From 44f60ec5e2a65204472e25a62a4631d9f6ed1602 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 27 Jul 2011 15:14:17 -0400 Subject: [PATCH 001/487] Revert "3.0-git3 snapshot" This reverts commit 4a2041744e262bb41936adfb3db0b85e13c73b11. --- Makefile | 2 - config-arm | 4 - config-debug | 2 - config-generic | 17 ---- config-nodebug | 2 - config-powerpc-generic | 4 - config-powerpc64 | 2 - config-x86-generic | 7 -- config-x86_64-generic | 6 -- dmar-disable-when-ricoh-multifunction.patch | 4 +- hda_intel-prealloc-4mb-dmabuffer.patch | 47 +++++++++++ kernel.spec | 25 ++++-- linux-2.6-intel-iommu-igfx.patch | 4 +- ...2x00-Add-device-ID-for-RT539F-device.patch | 23 ++++++ linux-2.6-silence-noise.patch | 4 +- ...ix-invalid-signal-values-from-device.patch | 82 +++++++++++++++++++ linux-2.6.30-no-pcspkr-modalias.patch | 4 +- sources | 1 - 18 files changed, 176 insertions(+), 64 deletions(-) create mode 100644 hda_intel-prealloc-4mb-dmabuffer.patch create mode 100644 linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch create mode 100644 linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch diff --git a/Makefile b/Makefile index 0b7442ab7..cffc926c2 100644 --- a/Makefile +++ b/Makefile @@ -92,7 +92,6 @@ debug: @perl -pi -e 's/# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set/CONFIG_CPU_NOTIFIER_ERROR_INJECT=m/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_PER_CPU_MAPS is not set/CONFIG_DEBUG_PER_CPU_MAPS=y/' config-nodebug @perl -pi -e 's/# CONFIG_TEST_LIST_SORT is not set/CONFIG_TEST_LIST_SORT=y/' config-nodebug - @perl -pi -e 's/# CONFIG_DEBUG_ATOMIC_SLEEP is not set/CONFIG_DEBUG_ATOMIC_SLEEP=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_SET_MODULE_RONX is not set/CONFIG_DEBUG_SET_MODULE_RONX=y/' config-nodebug @@ -171,7 +170,6 @@ release: #@perl -pi -e 's/CONFIG_KDB_KEYBOARD=y/# CONFIG_KDB_KEYBOARD is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_PER_CPU_MAPS=y/# CONFIG_DEBUG_PER_CPU_MAPS is not set/' config-nodebug @perl -pi -e 's/CONFIG_TEST_LIST_SORT=y/# CONFIG_TEST_LIST_SORT is not set/' config-nodebug - @perl -pi -e 's/CONFIG_DEBUG_ATOMIC_SLEEP=y/# CONFIG_DEBUG_ATOMIC_SLEEP is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_SET_MODULE_RONX=y/# CONFIG_DEBUG_SET_MODULE_RONX is not set/' config-nodebug diff --git a/config-arm b/config-arm index 1f26e7233..dd6f90ad6 100644 --- a/config-arm +++ b/config-arm @@ -147,7 +147,3 @@ CONFIG_PROC_DEVICETREE=y CONFIG_MTD_PHYSMAP_OF=m CONFIG_SERIAL_OF_PLATFORM=m CONFIG_MMC_SDHCI_OF=m -CONFIG_MMC_SDHCI_PXAV3=m -CONFIG_MMC_SDHCI_PXAV2=m - -CONFIG_FTGMAC100=m diff --git a/config-debug b/config-debug index 21e52bfd7..7bbaa0b59 100644 --- a/config-debug +++ b/config-debug @@ -2,8 +2,6 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y -CONFIG_DEBUG_ATOMIC_SLEEP=y - CONFIG_DEBUG_MUTEXES=y CONFIG_DEBUG_RT_MUTEXES=y CONFIG_DEBUG_LOCK_ALLOC=y diff --git a/config-generic b/config-generic index 6a4cf325b..a1ebab70f 100644 --- a/config-generic +++ b/config-generic @@ -1043,7 +1043,6 @@ CONFIG_IP_SET_HASH_IPPORTIP=m CONFIG_IP_SET_HASH_IPPORTNET=m CONFIG_IP_SET_HASH_NET=m CONFIG_IP_SET_HASH_NETPORT=m -CONFIG_IP_SET_HASH_NETIFACE=m CONFIG_IP_SET_LIST_SET=m # @@ -1348,7 +1347,6 @@ CONFIG_R8169=m CONFIG_R8169_VLAN=y CONFIG_SKGE=m # CONFIG_SKGE_DEBUG is not set -CONFIG_SKGE_GENESIS=y CONFIG_TIGON3=m CONFIG_SKY2=m # CONFIG_SKY2_DEBUG is not set @@ -1587,7 +1585,6 @@ CONFIG_WL1271_SPI=m CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m CONFIG_RTL8192CU=m -CONFIG_RTL8192DE=m CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m @@ -1668,8 +1665,6 @@ CONFIG_BAYCOM_PAR=m CONFIG_BAYCOM_EPP=m CONFIG_YAM=m -CONFIG_NFC=m - # # IrDA (infrared) support # @@ -2993,7 +2988,6 @@ CONFIG_SND_HDA_INPUT_JACK=y CONFIG_SND_HDA_PATCH_LOADER=y CONFIG_SND_HDA_HWDEP=y CONFIG_SND_HDA_CODEC_REALTEK=y -CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS=y CONFIG_SND_HDA_CODEC_CA0110=y CONFIG_SND_HDA_CODEC_ANALOG=y CONFIG_SND_HDA_CODEC_SIGMATEL=y @@ -3006,12 +3000,10 @@ CONFIG_SND_HDA_CODEC_INTELHDMI=y CONFIG_SND_HDA_CODEC_SI3054=y CONFIG_SND_HDA_CODEC_NVHDMI=y CONFIG_SND_HDA_CODEC_HDMI=y -CONFIG_SND_HDA_CODEC_CA0132=y CONFIG_SND_HDA_GENERIC=y CONFIG_SND_HDA_POWER_SAVE=y CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 CONFIG_SND_HDA_RECONFIG=y -CONFIG_SND_HDA_PREALLOC_SIZE=4096 CONFIG_SND_HDSPM=m CONFIG_SND_HIFIER=m CONFIG_SND_ICE1712=m @@ -3203,10 +3195,6 @@ CONFIG_HID_KEYTOUCH=m CONFIG_HID_LCPOWER=m CONFIG_HID_ROCCAT_ARVO=m CONFIG_HID_ROCCAT_KOVAPLUS=m -CONFIG_HID_HOLTEK=m -CONFIG_HOLTEK_FF=y -CONFIG_HID_SPEEDLINK=m -CONFIG_HID_WIIMOTE=m # # USB Imaging devices @@ -3935,8 +3923,6 @@ CONFIG_CRC32=m CONFIG_CRC_CCITT=m CONFIG_CRC_ITU_T=m CONFIG_CRC_T10DIF=m -CONFIG_CRC8=m -CONFIG_CORDIC=m CONFIG_CRYPTO_ZLIB=m CONFIG_ZLIB_INFLATE=y @@ -4654,7 +4640,6 @@ CONFIG_EVENT_POWER_TRACING_DEPRECATED=y CONFIG_NFC_DEVICES=y CONFIG_PN544_NFC=m -CONFIG_NFC_PN533=m CONFIG_TARGET_CORE=m CONFIG_LOOPBACK_TARGET=m @@ -4682,5 +4667,3 @@ CONFIG_BCMA_HOST_PCI=y # CONFIG_GOOGLE_FIRMWARE is not set CONFIG_INTEL_MID_PTI=m - -CONFIG_IOMMU_SUPPORT=y diff --git a/config-nodebug b/config-nodebug index a3fbf944d..5730cd1b2 100644 --- a/config-nodebug +++ b/config-nodebug @@ -2,8 +2,6 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y -CONFIG_DEBUG_ATOMIC_SLEEP=y - CONFIG_DEBUG_MUTEXES=y CONFIG_DEBUG_RT_MUTEXES=y CONFIG_DEBUG_LOCK_ALLOC=y diff --git a/config-powerpc-generic b/config-powerpc-generic index 97baa8a83..8dd44f399 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -342,7 +342,3 @@ CONFIG_CRYPTO_DEV_FSL_CAAM_INTC=y CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_COUNT_THLD=255 CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD=2048 CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=m - -# CONFIG_GPIO_GENERIC_PLATFORM is not set -# CONFIG_GPIO_MCP23S08 is not set - diff --git a/config-powerpc64 b/config-powerpc64 index 8e7d75d42..8866a5320 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -188,5 +188,3 @@ CONFIG_PSERIES_ENERGY=m CONFIG_PPC_ICSWX=y CONFIG_IO_EVENT_IRQ=y CONFIG_HW_RANDOM_AMD=m - -CONFIG_BPF_JIT=y diff --git a/config-x86-generic b/config-x86-generic index f41bb9095..bd2f93b70 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -374,8 +374,6 @@ CONFIG_XEN_DEBUG_FS=y CONFIG_XEN_PLATFORM_PCI=m CONFIG_XEN_GNTDEV=m CONFIG_INPUT_XEN_KBDDEV_FRONTEND=m -CONFIG_XEN_SELFBALLOONING=y -CONFIG_XEN_PCIDEV_BACKEND=m CONFIG_MTD_ESB2ROM=m CONFIG_MTD_CK804XROM=m @@ -555,8 +553,3 @@ CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m CONFIG_HP_ACCEL=m # CONFIG_RAPIDIO is not set - -# CONFIG_X86_INTEL_MID is not set - -# CONFIG_GPIO_GENERIC_PLATFORM is not set -# CONFIG_GPIO_MCP23S08 is not set diff --git a/config-x86_64-generic b/config-x86_64-generic index 340d7472d..f4c3c30cf 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -317,8 +317,6 @@ CONFIG_XEN_GNTDEV=m CONFIG_XEN_DEBUG_FS=y CONFIG_XEN_PLATFORM_PCI=m CONFIG_INPUT_XEN_KBDDEV_FRONTEND=m -CONFIG_XEN_SELFBALLOONING=y -CONFIG_XEN_PCIDEV_BACKEND=m CONFIG_DMADEVICES=y CONFIG_INTEL_IOATDMA=m @@ -464,7 +462,3 @@ CONFIG_HP_ACCEL=m # CONFIG_RAPIDIO is not set CONFIG_BPF_JIT=y - -# CONFIG_GPIO_GENERIC_PLATFORM is not set -# CONFIG_GPIO_MCP23S08 is not set - diff --git a/dmar-disable-when-ricoh-multifunction.patch b/dmar-disable-when-ricoh-multifunction.patch index a4528617e..120730f9e 100644 --- a/dmar-disable-when-ricoh-multifunction.patch +++ b/dmar-disable-when-ricoh-multifunction.patch @@ -9,8 +9,8 @@ Subject: [PATCH] dmar: disable if ricoh multifunction detected diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 4789f8e..5923914 100644 ---- a/drivers/iommu/intel-iommu.c -+++ b/drivers/iommu/intel-iommu.c +--- a/drivers/pci/intel-iommu.c ++++ b/drivers/pci/intel-iommu.c @@ -3784,6 +3784,16 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_g DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt); diff --git a/hda_intel-prealloc-4mb-dmabuffer.patch b/hda_intel-prealloc-4mb-dmabuffer.patch new file mode 100644 index 000000000..36e6aca4f --- /dev/null +++ b/hda_intel-prealloc-4mb-dmabuffer.patch @@ -0,0 +1,47 @@ +From c69fcbd1f60b0842f7c1ad2c95692ffd19c4932b Mon Sep 17 00:00:00 2001 +From: Kyle McMartin +Date: Mon, 29 Mar 2010 23:56:08 -0400 +Subject: hda_intel-prealloc-4mb-dmabuffer + +--- + sound/pci/hda/hda_intel.c | 14 +++++++++++++- + 1 files changed, 13 insertions(+), 1 deletions(-) + +diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c +index 4bb9067..37db515 100644 +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -1986,6 +1986,7 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, + struct azx_pcm *apcm; + int pcm_dev = cpcm->device; + int s, err; ++ size_t prealloc_min = 64*1024; /* 64KB */ + + if (pcm_dev >= HDA_MAX_PCMS) { + snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", +@@ -2019,10 +2020,21 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, + if (cpcm->stream[s].substreams) + snd_pcm_set_ops(pcm, s, &azx_pcm_ops); + } ++ + /* buffer pre-allocation */ ++ ++ /* subtle, don't allocate a big buffer for modems... ++ * also, don't just test 32BIT_MASK, since azx supports ++ * 64-bit DMA in some cases. ++ */ ++ /* lennart wants a 2.2MB buffer for 2sec of 48khz */ ++ if (pcm->dev_class == SNDRV_PCM_CLASS_GENERIC && ++ chip->pci->dma_mask >= DMA_32BIT_MASK) ++ prealloc_min = 4 * 1024 * 1024; /* 4MB */ ++ + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, + snd_dma_pci_data(chip->pci), +- 1024 * 64, 32 * 1024 * 1024); ++ prealloc_min, 32 * 1024 * 1024); + return 0; + } + +-- +1.7.0.1 + diff --git a/kernel.spec b/kernel.spec index d13d02707..3f55fbb92 100644 --- a/kernel.spec +++ b/kernel.spec @@ -6,7 +6,7 @@ Summary: The Linux kernel # For a stable, released kernel, released_kernel should be 1. For rawhide # and/or a kernel built from an rc or git snapshot, released_kernel should # be 0. -%global released_kernel 0 +%global released_kernel 1 # Save original buildid for later if it's defined %if 0%{?buildid:1} @@ -80,11 +80,12 @@ Summary: The Linux kernel ## The not-released-kernel case ## %else # The next upstream release sublevel (base_sublevel+1) -%define upstream_sublevel %(echo $((%{base_sublevel} + 1))) +# % define upstream_sublevel %(echo $((%{base_sublevel} + 1))) +%define upstream_sublevel 0 # The rc snapshot level %define rcrev 0 # The git snapshot level -%define gitrev 3 +%define gitrev 0 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -638,6 +639,8 @@ Patch470: die-floppy-die.patch Patch510: linux-2.6-silence-noise.patch Patch530: linux-2.6-silence-fbcon-logo.patch +Patch610: hda_intel-prealloc-4mb-dmabuffer.patch + Patch700: linux-2.6-e1000-ich9-montevina.patch Patch800: linux-2.6-crash-driver.patch @@ -679,6 +682,10 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12018: neuter_intel_microcode_load.patch +Patch12019: linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch + +Patch12020: linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch + # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch Patch12204: linux-2.6-enable-more-pci-autosuspend.patch @@ -1190,9 +1197,12 @@ ApplyPatch linux-2.6-defaults-aspm.patch # ACPI # ALSA +ApplyPatch hda_intel-prealloc-4mb-dmabuffer.patch # Networking +ApplyPatch linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch + # Misc fixes # The input layer spews crap no-one cares about. ApplyPatch linux-2.6-input-kill-stupid-messages.patch @@ -1252,6 +1262,8 @@ ApplyPatch add-appleir-usb-driver.patch ApplyPatch neuter_intel_microcode_load.patch +ApplyPatch linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch + # Runtime PM #ApplyPatch linux-2.6-usb-pci-autosuspend.patch ### Broken by implicit notify support & ACPICA rebase @@ -1262,7 +1274,7 @@ ApplyPatch neuter_intel_microcode_load.patch ApplyPatch dmar-disable-when-ricoh-multifunction.patch # utrace. -#ApplyPatch utrace.patch +ApplyPatch utrace.patch # END OF PATCH APPLICATIONS @@ -1873,11 +1885,6 @@ fi # and build. %changelog -* Mon Jul 25 2011 Kyle McMartin -- Linux 3.0-git3 -- Drop hda_intel-prealloc-4mb-dmabuffer.patch, set new - CONFIG_SND_HDA_PREALLOC_SIZE=4096 for similar effect. - * Fri Jul 22 2011 Dave Jones - bootwrapper needs objcopy. Add it to requires: (wwoods) diff --git a/linux-2.6-intel-iommu-igfx.patch b/linux-2.6-intel-iommu-igfx.patch index b2f8f19e3..44fd14186 100644 --- a/linux-2.6-intel-iommu-igfx.patch +++ b/linux-2.6-intel-iommu-igfx.patch @@ -43,8 +43,8 @@ index e7848a0..9914485 100644 for io virtual address below 32 bit forcing dual diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 4173125..8f36786 100644 ---- a/drivers/iommu/intel-iommu.c -+++ b/drivers/iommu/intel-iommu.c +--- a/drivers/pci/intel-iommu.c ++++ b/drivers/pci/intel-iommu.c @@ -340,7 +340,8 @@ int dmar_disabled = 0; int dmar_disabled = 1; #endif /*CONFIG_DMAR_DEFAULT_ON*/ diff --git a/linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch b/linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch new file mode 100644 index 000000000..abf01cfe4 --- /dev/null +++ b/linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch @@ -0,0 +1,23 @@ +commit 71e0b38c2914018b01f3f08b43ee9e3328197699 +Author: Gertjan van Wingerde +Date: Wed Jul 6 22:58:55 2011 +0200 + + rt2x00: Add device ID for RT539F device. + + Reported-by: Wim Vander Schelden + Signed-off-by: Gertjan van Wingerde + Signed-off-by: Ivo van Doorn + Signed-off-by: John W. Linville + +diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c +index 5513edf..fd99449 100644 +--- a/drivers/net/wireless/rt2x00/rt2800pci.c ++++ b/drivers/net/wireless/rt2x00/rt2800pci.c +@@ -1160,6 +1160,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { + #endif + #ifdef CONFIG_RT2800PCI_RT53XX + { PCI_DEVICE(0x1814, 0x5390) }, ++ { PCI_DEVICE(0x1814, 0x539f) }, + #endif + { 0, } + }; diff --git a/linux-2.6-silence-noise.patch b/linux-2.6-silence-noise.patch index 1e4d7c57f..8aba3cdab 100644 --- a/linux-2.6-silence-noise.patch +++ b/linux-2.6-silence-noise.patch @@ -46,8 +46,8 @@ Signed-off-by: Dave Jones + * In case of error we but don't return the error code immediately. + * Below we will return -EPROTONOSUPPORT */ -- if (err) -- printk_ratelimited(KERN_ERR "can: request_module " +- if (err && printk_ratelimit()) +- printk(KERN_ERR "can: request_module " - "(can-proto-%d) failed.\n", protocol); cp = can_get_proto(protocol); diff --git a/linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch b/linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch new file mode 100644 index 000000000..f91ceb808 --- /dev/null +++ b/linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch @@ -0,0 +1,82 @@ +commit 7a1d6564a15183cb5994656040966df09af8390f +Author: Jussi Kivilinna +Date: Mon Jun 20 14:42:28 2011 +0300 + + zd1211rw: fix invalid signal values from device + + Driver uses IEEE80211_HW_SIGNAL_UNSPEC and so signal values reported to + mac80211 should be in range 0..100. Sometimes device return out of range + values. These out of range values can then trigger warning in + cfg80211_inform_bss_frame. + + This patch adds checks to enforce range returned from driver to + mac80211 be in 0..100 range. + + Signed-off-by: Jussi Kivilinna + Signed-off-by: John W. Linville + +diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h +index 5463ca9..9a1b013 100644 +--- a/drivers/net/wireless/zd1211rw/zd_def.h ++++ b/drivers/net/wireless/zd1211rw/zd_def.h +@@ -37,9 +37,15 @@ typedef u16 __nocast zd_addr_t; + if (net_ratelimit()) \ + dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \ + } while (0) ++# define dev_dbg_f_cond(dev, cond, fmt, args...) ({ \ ++ bool __cond = !!(cond); \ ++ if (unlikely(__cond)) \ ++ dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \ ++}) + #else + # define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0) + # define dev_dbg_f_limit(dev, fmt, args...) do { (void)(dev); } while (0) ++# define dev_dbg_f_cond(dev, cond, fmt, args...) do { (void)(dev); } while (0) + #endif /* DEBUG */ + + #ifdef DEBUG +diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c +index 5037c8b..5de28bf 100644 +--- a/drivers/net/wireless/zd1211rw/zd_mac.c ++++ b/drivers/net/wireless/zd1211rw/zd_mac.c +@@ -160,6 +160,22 @@ static int zd_reg2alpha2(u8 regdomain, char *alpha2) + return 1; + } + ++static int zd_check_signal(struct ieee80211_hw *hw, int signal) ++{ ++ struct zd_mac *mac = zd_hw_mac(hw); ++ ++ dev_dbg_f_cond(zd_mac_dev(mac), signal < 0 || signal > 100, ++ "%s: signal value from device not in range 0..100, " ++ "but %d.\n", __func__, signal); ++ ++ if (signal < 0) ++ signal = 0; ++ else if (signal > 100) ++ signal = 100; ++ ++ return signal; ++} ++ + int zd_mac_preinit_hw(struct ieee80211_hw *hw) + { + int r; +@@ -461,7 +477,7 @@ static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, + if (istatus.rates[i].idx = -1; /* terminate */ + +- info->status.ack_signal = ackssi; ++ info->status.ack_signal = zd_check_signal(hw, ackssi); + ieee80211_tx_status_irqsafe(hw, skb); + } + +@@ -982,7 +998,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) + + stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq; + stats.band = IEEE80211_BAND_2GHZ; +- stats.signal = status->signal_strength; ++ stats.signal = zd_check_signal(hw, status->signal_strength); + + rate = zd_rx_rate(buffer, status); + diff --git a/linux-2.6.30-no-pcspkr-modalias.patch b/linux-2.6.30-no-pcspkr-modalias.patch index e210f4625..c703b8844 100644 --- a/linux-2.6.30-no-pcspkr-modalias.patch +++ b/linux-2.6.30-no-pcspkr-modalias.patch @@ -7,5 +7,5 @@ diff -up linux-2.6.30.noarch/drivers/input/misc/pcspkr.c.jx linux-2.6.30.noarch/ MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:pcspkr"); - static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) - { + #if defined(CONFIG_MIPS) || defined(CONFIG_X86) + /* Use the global PIT lock ! */ diff --git a/sources b/sources index 9167d7bae..cbf1c63cd 100644 --- a/sources +++ b/sources @@ -1,2 +1 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 -ce0c7face215619004aeac9c85c36324 patch-3.0-git3.bz2 From e4df40cdf27e57d207daa3f0c202ba0ee1e0e8d3 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 27 Jul 2011 15:27:13 -0400 Subject: [PATCH 002/487] make release --- config-generic | 8 ++-- config-nodebug | 102 +++++++++++++++++++++--------------------- config-x86_64-generic | 2 +- kernel.spec | 7 ++- 4 files changed, 61 insertions(+), 58 deletions(-) diff --git a/config-generic b/config-generic index a1ebab70f..40ec3cff5 100644 --- a/config-generic +++ b/config-generic @@ -1472,12 +1472,12 @@ CONFIG_ATMEL=m CONFIG_B43=m CONFIG_B43_PCMCIA=y CONFIG_B43_SDIO=y -CONFIG_B43_DEBUG=y +# CONFIG_B43_DEBUG is not set CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y # CONFIG_B43_FORCE_PIO is not set CONFIG_B43LEGACY=m -CONFIG_B43LEGACY_DEBUG=y +# CONFIG_B43LEGACY_DEBUG is not set CONFIG_B43LEGACY_DMA=y CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y @@ -4004,7 +4004,7 @@ CONFIG_IBMASR=m CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y # CONFIG_PM_VERBOSE is not set -CONFIG_PM_TEST_SUSPEND=y +# CONFIG_PM_TEST_SUSPEND is not set CONFIG_PM_RUNTIME=y CONFIG_CPU_FREQ=y @@ -4483,7 +4483,7 @@ CONFIG_USB_ATMEL=m # CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FUNCTION_GRAPH_TRACER is not set -CONFIG_BOOT_TRACER=y +# CONFIG_BOOT_TRACER is not set CONFIG_EARLY_PRINTK_DBGP=y CONFIG_SECURITYFS=y diff --git a/config-nodebug b/config-nodebug index 5730cd1b2..62650aa3a 100644 --- a/config-nodebug +++ b/config-nodebug @@ -2,99 +2,99 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_RT_MUTEXES=y -CONFIG_DEBUG_LOCK_ALLOC=y -CONFIG_PROVE_LOCKING=y -CONFIG_DEBUG_VM=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_PROVE_RCU=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_PROVE_RCU is not set # CONFIG_PROVE_RCU_REPEATEDLY is not set -CONFIG_DEBUG_PER_CPU_MAPS=y +# CONFIG_DEBUG_PER_CPU_MAPS is not set CONFIG_CPUMASK_OFFSTACK=y -CONFIG_CPU_NOTIFIER_ERROR_INJECT=m +# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set -CONFIG_FAULT_INJECTION=y -CONFIG_FAILSLAB=y -CONFIG_FAIL_PAGE_ALLOC=y -CONFIG_FAIL_MAKE_REQUEST=y -CONFIG_FAULT_INJECTION_DEBUG_FS=y -CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y -CONFIG_FAIL_IO_TIMEOUT=y +# CONFIG_FAULT_INJECTION is not set +# CONFIG_FAILSLAB is not set +# CONFIG_FAIL_PAGE_ALLOC is not set +# CONFIG_FAIL_MAKE_REQUEST is not set +# CONFIG_FAULT_INJECTION_DEBUG_FS is not set +# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set +# CONFIG_FAIL_IO_TIMEOUT is not set -CONFIG_SLUB_DEBUG_ON=y +# CONFIG_SLUB_DEBUG_ON is not set -CONFIG_LOCK_STAT=y +# CONFIG_LOCK_STAT is not set -CONFIG_DEBUG_STACK_USAGE=y +# CONFIG_DEBUG_STACK_USAGE is not set -CONFIG_ACPI_DEBUG=y +# CONFIG_ACPI_DEBUG is not set # CONFIG_ACPI_DEBUG_FUNC_TRACE is not set -CONFIG_DEBUG_SG=y +# CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_PAGEALLOC is not set -CONFIG_DEBUG_WRITECOUNT=y -CONFIG_DEBUG_OBJECTS=y +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_OBJECTS_SELFTEST is not set -CONFIG_DEBUG_OBJECTS_FREE=y -CONFIG_DEBUG_OBJECTS_TIMERS=y -CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +# CONFIG_DEBUG_OBJECTS_FREE is not set +# CONFIG_DEBUG_OBJECTS_TIMERS is not set +# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 -CONFIG_X86_PTDUMP=y +# CONFIG_X86_PTDUMP is not set -CONFIG_CAN_DEBUG_DEVICES=y +# CONFIG_CAN_DEBUG_DEVICES is not set -CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_SYSCTL_SYSCALL_CHECK is not set -CONFIG_DEBUG_NOTIFIERS=y +# CONFIG_DEBUG_NOTIFIERS is not set -CONFIG_DMA_API_DEBUG=y +# CONFIG_DMA_API_DEBUG is not set -CONFIG_MMIOTRACE=y +# CONFIG_MMIOTRACE is not set -CONFIG_DEBUG_CREDENTIALS=y +# CONFIG_DEBUG_CREDENTIALS is not set # off in both production debug and nodebug builds, # on in rawhide nodebug builds -CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set -CONFIG_EXT4_DEBUG=y +# CONFIG_EXT4_DEBUG is not set -CONFIG_DEBUG_PERF_USE_VMALLOC=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set -CONFIG_JBD2_DEBUG=y +# CONFIG_JBD2_DEBUG is not set -CONFIG_DEBUG_CFQ_IOSCHED=y +# CONFIG_DEBUG_CFQ_IOSCHED is not set -CONFIG_DRBD_FAULT_INJECTION=y +# CONFIG_DRBD_FAULT_INJECTION is not set -CONFIG_ATH_DEBUG=y -CONFIG_CARL9170_DEBUGFS=y -CONFIG_IWLWIFI_DEVICE_TRACING=y +# CONFIG_ATH_DEBUG is not set +# CONFIG_CARL9170_DEBUGFS is not set +# CONFIG_IWLWIFI_DEVICE_TRACING is not set -CONFIG_DEBUG_OBJECTS_WORK=y +# CONFIG_DEBUG_OBJECTS_WORK is not set # CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set -CONFIG_DMADEVICES_DEBUG=y -CONFIG_DMADEVICES_VDEBUG=y +# CONFIG_DMADEVICES_DEBUG is not set +# CONFIG_DMADEVICES_VDEBUG is not set CONFIG_PM_ADVANCED_DEBUG=y -CONFIG_CEPH_LIB_PRETTYDEBUG=y -CONFIG_QUOTA_DEBUG=y +# CONFIG_CEPH_LIB_PRETTYDEBUG is not set +# CONFIG_QUOTA_DEBUG is not set CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y CONFIG_KDB_KEYBOARD=y -CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y -CONFIG_TEST_LIST_SORT=y +# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set +# CONFIG_TEST_LIST_SORT is not set -CONFIG_DEBUG_SET_MODULE_RONX=y +# CONFIG_DEBUG_SET_MODULE_RONX is not set diff --git a/config-x86_64-generic b/config-x86_64-generic index f4c3c30cf..51879a762 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -16,7 +16,7 @@ CONFIG_K8_NUMA=y CONFIG_AMD_NUMA=y CONFIG_X86_64_ACPI_NUMA=y # CONFIG_NUMA_EMU is not set -CONFIG_NR_CPUS=512 +CONFIG_NR_CPUS=256 CONFIG_X86_POWERNOW_K8=m CONFIG_X86_P4_CLOCKMOD=m CONFIG_IA32_EMULATION=y diff --git a/kernel.spec b/kernel.spec index 3f55fbb92..f5f9f4792 100644 --- a/kernel.spec +++ b/kernel.spec @@ -131,7 +131,7 @@ Summary: The Linux kernel %define doc_build_fail true %endif -%define rawhide_skip_docs 1 +%define rawhide_skip_docs 0 %if 0%{?rawhide_skip_docs} %define with_doc 0 %define doc_build_fail true @@ -154,7 +154,7 @@ Summary: The Linux kernel # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. -%define debugbuildsenabled 0 +%define debugbuildsenabled 1 # Want to build a vanilla kernel build without any non-upstream patches? %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} @@ -1885,6 +1885,9 @@ fi # and build. %changelog +* Wed Jul 27 2011 Dave Jones +- Turn off debug builds. + * Fri Jul 22 2011 Dave Jones - bootwrapper needs objcopy. Add it to requires: (wwoods) From 7cec0fdc372f603afeaf104b6777609aebd58f3f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 28 Jul 2011 12:52:32 -0400 Subject: [PATCH 003/487] Add patch from linux-next to help multiseat issues --- kernel.spec | 9 ++++++- udlfb-bind-framebuffer-to-interface.patch | 33 +++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 udlfb-bind-framebuffer-to-interface.patch diff --git a/kernel.spec b/kernel.spec index f5f9f4792..2f5a0c7e8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -686,6 +686,8 @@ Patch12019: linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch Patch12020: linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch +Patch12021: udlfb-bind-framebuffer-to-interface.patch + # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch Patch12204: linux-2.6-enable-more-pci-autosuspend.patch @@ -1264,6 +1266,8 @@ ApplyPatch neuter_intel_microcode_load.patch ApplyPatch linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch +ApplyPatch udlfb-bind-framebuffer-to-interface.patch + # Runtime PM #ApplyPatch linux-2.6-usb-pci-autosuspend.patch ### Broken by implicit notify support & ACPICA rebase @@ -1885,6 +1889,9 @@ fi # and build. %changelog +* Thu Jul 28 2011 Josh Boyer +- Backport patch to correct udlfb removal events (rhbz 726163) + * Wed Jul 27 2011 Dave Jones - Turn off debug builds. diff --git a/udlfb-bind-framebuffer-to-interface.patch b/udlfb-bind-framebuffer-to-interface.patch new file mode 100644 index 000000000..1c5c6df9b --- /dev/null +++ b/udlfb-bind-framebuffer-to-interface.patch @@ -0,0 +1,33 @@ +From c91a793f66d5b06292aa431ae3a36c8aca991fa3 Mon Sep 17 00:00:00 2001 +From: Kay Sievers +Date: Tue, 5 Jul 2011 17:04:11 -0700 +Subject: [PATCH] drivers/video/udlfb bind framebuffer to interface. + +Udlfb has been binding the framebuffer device to its parent, which +isn't correct and causes confusion with operations like udev remove. + +Coming plug and play multiseat support is dependent on this fix. + +Signed-off-by: Kay Sievers +Signed-off-by: Bernie Thompson +Signed-off-by: Paul Mundt +--- + drivers/video/udlfb.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c +index 816a4fd..c6584c9 100644 +--- a/drivers/video/udlfb.c ++++ b/drivers/video/udlfb.c +@@ -1549,7 +1549,7 @@ static int dlfb_usb_probe(struct usb_interface *interface, + /* We don't register a new USB class. Our client interface is fbdev */ + + /* allocates framebuffer driver structure, not framebuffer memory */ +- info = framebuffer_alloc(0, &usbdev->dev); ++ info = framebuffer_alloc(0, &interface->dev); + if (!info) { + retval = -ENOMEM; + pr_err("framebuffer_alloc failed\n"); +-- +1.7.4.4 + From 73a609865cb91aa05397988289f1f82fd561e389 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 28 Jul 2011 21:36:33 -0400 Subject: [PATCH 004/487] module-init-tools needs to be a prereq, not a conflict. --- kernel.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 2f5a0c7e8..4c3c4199b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -432,7 +432,7 @@ Summary: The Linux kernel # First the general kernel 2.6 required versions as per # Documentation/Changes # -%define kernel_dot_org_conflicts ppp < 2.4.3-3, isdn4k-utils < 3.2-32, nfs-utils < 1.0.7-12, e2fsprogs < 1.37-4, util-linux < 2.12, jfsutils < 1.1.7-2, reiserfs-utils < 3.6.19-2, xfsprogs < 2.6.13-4, procps < 3.2.5-6.3, oprofile < 0.9.1-2, module-init-tools < 3.13-1, device-mapper-libs < 1.02.63-2, mdadm < 3.2.1-5 +%define kernel_dot_org_conflicts ppp < 2.4.3-3, isdn4k-utils < 3.2-32, nfs-utils < 1.0.7-12, e2fsprogs < 1.37-4, util-linux < 2.12, jfsutils < 1.1.7-2, reiserfs-utils < 3.6.19-2, xfsprogs < 2.6.13-4, procps < 3.2.5-6.3, oprofile < 0.9.1-2, device-mapper-libs < 1.02.63-2, mdadm < 3.2.1-5 # # Then a series of requirements that are distribution specific, either @@ -450,7 +450,7 @@ Summary: The Linux kernel # Packages that need to be installed before the kernel is, because the %%post # scripts use them. # -%define kernel_prereq fileutils, module-init-tools, initscripts >= 8.11.1-1, grubby >= 7.0.10-1 +%define kernel_prereq fileutils, module-init-tools >= 3.16-2, initscripts >= 8.11.1-1, grubby >= 7.0.10-1 %define initrd_prereq dracut >= 001-7 # @@ -1889,6 +1889,9 @@ fi # and build. %changelog +* Thu Jul 28 2011 Dave Jones +- module-init-tools needs to be a prereq, not a conflict. + * Thu Jul 28 2011 Josh Boyer - Backport patch to correct udlfb removal events (rhbz 726163) From 12fe727f0d1c384202dbd24d4a5f7f948c555f06 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 29 Jul 2011 22:49:51 -0400 Subject: [PATCH 005/487] fix scsi_dispatch oops. --- fix-scsi_dispatch_cmd.patch | 68 +++++++++++++++++++++++++++++++++++++ kernel.spec | 7 ++++ 2 files changed, 75 insertions(+) create mode 100644 fix-scsi_dispatch_cmd.patch diff --git a/fix-scsi_dispatch_cmd.patch b/fix-scsi_dispatch_cmd.patch new file mode 100644 index 000000000..3976791ca --- /dev/null +++ b/fix-scsi_dispatch_cmd.patch @@ -0,0 +1,68 @@ +commit bfe159a51203c15d23cb3158fffdc25ec4b4dda1 +Author: James Bottomley +Date: Thu Jul 7 15:45:40 2011 -0500 + + [SCSI] fix crash in scsi_dispatch_cmd() + + USB surprise removal of sr is triggering an oops in + scsi_dispatch_command(). What seems to be happening is that USB is + hanging on to a queue reference until the last close of the upper + device, so the crash is caused by surprise remove of a mounted CD + followed by attempted unmount. + + The problem is that USB doesn't issue its final commands as part of + the SCSI teardown path, but on last close when the block queue is long + gone. The long term fix is probably to make sr do the teardown in the + same way as sd (so remove all the lower bits on ejection, but keep the + upper disk alive until last close of user space). However, the + current oops can be simply fixed by not allowing any commands to be + sent to a dead queue. + + Cc: stable@kernel.org + Signed-off-by: James Bottomley + +diff --git a/block/blk-core.c b/block/blk-core.c +index d2f8f40..1d49e1c 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -839,6 +839,9 @@ struct request *blk_get_request(struct request_queue *q, int rw, gfp_t gfp_mask) + { + struct request *rq; + ++ if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) ++ return NULL; ++ + BUG_ON(rw != READ && rw != WRITE); + + spin_lock_irq(q->queue_lock); +diff --git a/block/blk-exec.c b/block/blk-exec.c +index 8a0e7ec..a1ebceb 100644 +--- a/block/blk-exec.c ++++ b/block/blk-exec.c +@@ -50,6 +50,13 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, + { + int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; + ++ if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) { ++ rq->errors = -ENXIO; ++ if (rq->end_io) ++ rq->end_io(rq, rq->errors); ++ return; ++ } ++ + rq->rq_disk = bd_disk; + rq->end_io = done; + WARN_ON(irqs_disabled()); +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index ec1803a..28d9c9d 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -213,6 +213,8 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, + int ret = DRIVER_ERROR << 24; + + req = blk_get_request(sdev->request_queue, write, __GFP_WAIT); ++ if (!req) ++ return ret; + + if (bufflen && blk_rq_map_kern(sdev->request_queue, req, + buffer, bufflen, __GFP_WAIT)) diff --git a/kernel.spec b/kernel.spec index 4c3c4199b..003a6a044 100644 --- a/kernel.spec +++ b/kernel.spec @@ -695,6 +695,8 @@ Patch12205: runtime_pm_fixups.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch +Patch13000: fix-scsi_dispatch_cmd.patch + Patch20000: utrace.patch %endif @@ -1277,6 +1279,8 @@ ApplyPatch udlfb-bind-framebuffer-to-interface.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch +ApplyPatch fix-scsi_dispatch_cmd.patch + # utrace. ApplyPatch utrace.patch @@ -1889,6 +1893,9 @@ fi # and build. %changelog +* Fri Jul 29 2011 Dave Jones +- Fix scsi_dispatch_cmd oops (USB eject problems, etc). + * Thu Jul 28 2011 Dave Jones - module-init-tools needs to be a prereq, not a conflict. From a145ed9864b356ff6855e65ddbec590547a11715 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 2 Aug 2011 12:53:17 -0400 Subject: [PATCH 006/487] Add change to include the rt2x00 drivers in modules.networking --- kernel.spec | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 003a6a044..be59935ee 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -1526,7 +1526,7 @@ BuildKernel() { } collect_modules_list networking \ - 'register_netdev|ieee80211_register_hw|usbnet_probe|phy_driver_register' + 'register_netdev|ieee80211_register_hw|usbnet_probe|phy_driver_register|rt2x00(pci|usb)_probe' collect_modules_list block \ 'ata_scsi_ioctl|scsi_add_host|scsi_add_host_with_dma|blk_init_queue|register_mtd_blktrans|scsi_esp_register|scsi_register_device_handler' collect_modules_list drm \ @@ -1893,6 +1893,10 @@ fi # and build. %changelog +* Tue Aug 02 2011 Josh Boyer +- Add change from Yanko Kaneti to get the rt2x00 drivers in modules.networking + (rhbz 708314) + * Fri Jul 29 2011 Dave Jones - Fix scsi_dispatch_cmd oops (USB eject problems, etc). From ec0811cedbdac76b50ffd4ee48fd796c64b4bd57 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 2 Aug 2011 14:33:26 -0400 Subject: [PATCH 007/487] Add patch to fix epoll lockdep warnings make debug as we're still really early in the release --- config-generic | 8 +- config-nodebug | 102 +++++++++---------- config-x86_64-generic | 2 +- epoll-fix-spurious-lockdep-warnings.patch | 116 ++++++++++++++++++++++ kernel.spec | 10 +- 5 files changed, 180 insertions(+), 58 deletions(-) create mode 100644 epoll-fix-spurious-lockdep-warnings.patch diff --git a/config-generic b/config-generic index 40ec3cff5..a1ebab70f 100644 --- a/config-generic +++ b/config-generic @@ -1472,12 +1472,12 @@ CONFIG_ATMEL=m CONFIG_B43=m CONFIG_B43_PCMCIA=y CONFIG_B43_SDIO=y -# CONFIG_B43_DEBUG is not set +CONFIG_B43_DEBUG=y CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y # CONFIG_B43_FORCE_PIO is not set CONFIG_B43LEGACY=m -# CONFIG_B43LEGACY_DEBUG is not set +CONFIG_B43LEGACY_DEBUG=y CONFIG_B43LEGACY_DMA=y CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y @@ -4004,7 +4004,7 @@ CONFIG_IBMASR=m CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y # CONFIG_PM_VERBOSE is not set -# CONFIG_PM_TEST_SUSPEND is not set +CONFIG_PM_TEST_SUSPEND=y CONFIG_PM_RUNTIME=y CONFIG_CPU_FREQ=y @@ -4483,7 +4483,7 @@ CONFIG_USB_ATMEL=m # CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FUNCTION_GRAPH_TRACER is not set -# CONFIG_BOOT_TRACER is not set +CONFIG_BOOT_TRACER=y CONFIG_EARLY_PRINTK_DBGP=y CONFIG_SECURITYFS=y diff --git a/config-nodebug b/config-nodebug index 62650aa3a..5730cd1b2 100644 --- a/config-nodebug +++ b/config-nodebug @@ -2,99 +2,99 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_PROVE_LOCKING is not set -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_PROVE_RCU is not set +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_RT_MUTEXES=y +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_LOCKING=y +CONFIG_DEBUG_VM=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_PROVE_RCU=y # CONFIG_PROVE_RCU_REPEATEDLY is not set -# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_DEBUG_PER_CPU_MAPS=y CONFIG_CPUMASK_OFFSTACK=y -# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set +CONFIG_CPU_NOTIFIER_ERROR_INJECT=m -# CONFIG_FAULT_INJECTION is not set -# CONFIG_FAILSLAB is not set -# CONFIG_FAIL_PAGE_ALLOC is not set -# CONFIG_FAIL_MAKE_REQUEST is not set -# CONFIG_FAULT_INJECTION_DEBUG_FS is not set -# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set -# CONFIG_FAIL_IO_TIMEOUT is not set +CONFIG_FAULT_INJECTION=y +CONFIG_FAILSLAB=y +CONFIG_FAIL_PAGE_ALLOC=y +CONFIG_FAIL_MAKE_REQUEST=y +CONFIG_FAULT_INJECTION_DEBUG_FS=y +CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y +CONFIG_FAIL_IO_TIMEOUT=y -# CONFIG_SLUB_DEBUG_ON is not set +CONFIG_SLUB_DEBUG_ON=y -# CONFIG_LOCK_STAT is not set +CONFIG_LOCK_STAT=y -# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_STACK_USAGE=y -# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_DEBUG=y # CONFIG_ACPI_DEBUG_FUNC_TRACE is not set -# CONFIG_DEBUG_SG is not set +CONFIG_DEBUG_SG=y # CONFIG_DEBUG_PAGEALLOC is not set -# CONFIG_DEBUG_WRITECOUNT is not set -# CONFIG_DEBUG_OBJECTS is not set +CONFIG_DEBUG_WRITECOUNT=y +CONFIG_DEBUG_OBJECTS=y # CONFIG_DEBUG_OBJECTS_SELFTEST is not set -# CONFIG_DEBUG_OBJECTS_FREE is not set -# CONFIG_DEBUG_OBJECTS_TIMERS is not set -# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set +CONFIG_DEBUG_OBJECTS_FREE=y +CONFIG_DEBUG_OBJECTS_TIMERS=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 -# CONFIG_X86_PTDUMP is not set +CONFIG_X86_PTDUMP=y -# CONFIG_CAN_DEBUG_DEVICES is not set +CONFIG_CAN_DEBUG_DEVICES=y -# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y -# CONFIG_DEBUG_NOTIFIERS is not set +CONFIG_DEBUG_NOTIFIERS=y -# CONFIG_DMA_API_DEBUG is not set +CONFIG_DMA_API_DEBUG=y -# CONFIG_MMIOTRACE is not set +CONFIG_MMIOTRACE=y -# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_DEBUG_CREDENTIALS=y # off in both production debug and nodebug builds, # on in rawhide nodebug builds -# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y -# CONFIG_EXT4_DEBUG is not set +CONFIG_EXT4_DEBUG=y -# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_DEBUG_PERF_USE_VMALLOC=y -# CONFIG_JBD2_DEBUG is not set +CONFIG_JBD2_DEBUG=y -# CONFIG_DEBUG_CFQ_IOSCHED is not set +CONFIG_DEBUG_CFQ_IOSCHED=y -# CONFIG_DRBD_FAULT_INJECTION is not set +CONFIG_DRBD_FAULT_INJECTION=y -# CONFIG_ATH_DEBUG is not set -# CONFIG_CARL9170_DEBUGFS is not set -# CONFIG_IWLWIFI_DEVICE_TRACING is not set +CONFIG_ATH_DEBUG=y +CONFIG_CARL9170_DEBUGFS=y +CONFIG_IWLWIFI_DEVICE_TRACING=y -# CONFIG_DEBUG_OBJECTS_WORK is not set +CONFIG_DEBUG_OBJECTS_WORK=y # CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set -# CONFIG_DMADEVICES_DEBUG is not set -# CONFIG_DMADEVICES_VDEBUG is not set +CONFIG_DMADEVICES_DEBUG=y +CONFIG_DMADEVICES_VDEBUG=y CONFIG_PM_ADVANCED_DEBUG=y -# CONFIG_CEPH_LIB_PRETTYDEBUG is not set -# CONFIG_QUOTA_DEBUG is not set +CONFIG_CEPH_LIB_PRETTYDEBUG=y +CONFIG_QUOTA_DEBUG=y CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y CONFIG_KDB_KEYBOARD=y -# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set -# CONFIG_TEST_LIST_SORT is not set +CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y +CONFIG_TEST_LIST_SORT=y -# CONFIG_DEBUG_SET_MODULE_RONX is not set +CONFIG_DEBUG_SET_MODULE_RONX=y diff --git a/config-x86_64-generic b/config-x86_64-generic index 51879a762..f4c3c30cf 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -16,7 +16,7 @@ CONFIG_K8_NUMA=y CONFIG_AMD_NUMA=y CONFIG_X86_64_ACPI_NUMA=y # CONFIG_NUMA_EMU is not set -CONFIG_NR_CPUS=256 +CONFIG_NR_CPUS=512 CONFIG_X86_POWERNOW_K8=m CONFIG_X86_P4_CLOCKMOD=m CONFIG_IA32_EMULATION=y diff --git a/epoll-fix-spurious-lockdep-warnings.patch b/epoll-fix-spurious-lockdep-warnings.patch new file mode 100644 index 000000000..131796af8 --- /dev/null +++ b/epoll-fix-spurious-lockdep-warnings.patch @@ -0,0 +1,116 @@ +epoll can acquire multiple ep->mutex on multiple "struct eventpoll"s +at once in the case where one epoll fd is monitoring another epoll +fd. This is perfectly OK, since we're careful about the lock ordering, +but causes spurious lockdep warnings. Annotate the recursion using +mutex_lock_nested, and add a comment explaining the nesting rules for +good measure. + +Reported-by: Paul Bolle +Signed-off-by: Nelson Elhage +--- + I've tested this on a synthetic epoll test case, that just adds e1 to + e2 and then does an epoll_wait(). I verified that it caused lockdep + problems on 3.0 and that this patch fixed it, but I haven't done more + extensive testing. Paul, are you able to test systemd against this? + + fs/eventpoll.c | 25 ++++++++++++++++++------- + 1 files changed, 18 insertions(+), 7 deletions(-) + +diff --git a/fs/eventpoll.c b/fs/eventpoll.c +index f9cfd16..0cb7bc6 100644 +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -76,6 +76,15 @@ + * Events that require holding "epmutex" are very rare, while for + * normal operations the epoll private "ep->mtx" will guarantee + * a better scalability. ++ * It is possible to acquire multiple "ep->mtx"es at once in the case ++ * when one epoll fd is added to another. In this case, we always ++ * acquire the locks in the order of nesting (i.e. after epoll_ctl(e1, ++ * EPOLL_CTL_ADD, e2), e1->mtx will always be acquired before ++ * e2->mtx). Since we disallow cycles of epoll file descriptors, this ++ * ensures that the mutexes are well-ordered. In order to communicate ++ * this nesting to lockdep, when walking a tree of epoll file ++ * descriptors, we use the current recursion depth as the lockdep ++ * subkey. + */ + + /* Epoll private bits inside the event mask */ +@@ -464,13 +473,15 @@ static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi) + * @ep: Pointer to the epoll private data structure. + * @sproc: Pointer to the scan callback. + * @priv: Private opaque data passed to the @sproc callback. ++ * @depth: The current depth of recursive f_op->poll calls. + * + * Returns: The same integer error code returned by the @sproc callback. + */ + static int ep_scan_ready_list(struct eventpoll *ep, + int (*sproc)(struct eventpoll *, + struct list_head *, void *), +- void *priv) ++ void *priv, ++ int depth) + { + int error, pwake = 0; + unsigned long flags; +@@ -481,7 +492,7 @@ static int ep_scan_ready_list(struct eventpoll *ep, + * We need to lock this because we could be hit by + * eventpoll_release_file() and epoll_ctl(). + */ +- mutex_lock(&ep->mtx); ++ mutex_lock_nested(&ep->mtx, depth); + + /* + * Steal the ready list, and re-init the original one to the +@@ -670,7 +681,7 @@ static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head, + + static int ep_poll_readyevents_proc(void *priv, void *cookie, int call_nests) + { +- return ep_scan_ready_list(priv, ep_read_events_proc, NULL); ++ return ep_scan_ready_list(priv, ep_read_events_proc, NULL, call_nests + 1); + } + + static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait) +@@ -737,7 +748,7 @@ void eventpoll_release_file(struct file *file) + + ep = epi->ep; + list_del_init(&epi->fllink); +- mutex_lock(&ep->mtx); ++ mutex_lock_nested(&ep->mtx, 0); + ep_remove(ep, epi); + mutex_unlock(&ep->mtx); + } +@@ -1134,7 +1145,7 @@ static int ep_send_events(struct eventpoll *ep, + esed.maxevents = maxevents; + esed.events = events; + +- return ep_scan_ready_list(ep, ep_send_events_proc, &esed); ++ return ep_scan_ready_list(ep, ep_send_events_proc, &esed, 0); + } + + static inline struct timespec ep_set_mstimeout(long ms) +@@ -1267,7 +1278,7 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests) + struct rb_node *rbp; + struct epitem *epi; + +- mutex_lock(&ep->mtx); ++ mutex_lock_nested(&ep->mtx, call_nests + 1); + for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) { + epi = rb_entry(rbp, struct epitem, rbn); + if (unlikely(is_file_epoll(epi->ffd.file))) { +@@ -1409,7 +1420,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, + } + + +- mutex_lock(&ep->mtx); ++ mutex_lock_nested(&ep->mtx, 0); + + /* + * Try to lookup the file inside our RB tree, Since we grabbed "mtx" +-- +1.7.4.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index be59935ee..7e8210d15 100644 --- a/kernel.spec +++ b/kernel.spec @@ -131,7 +131,7 @@ Summary: The Linux kernel %define doc_build_fail true %endif -%define rawhide_skip_docs 0 +%define rawhide_skip_docs 1 %if 0%{?rawhide_skip_docs} %define with_doc 0 %define doc_build_fail true @@ -154,7 +154,7 @@ Summary: The Linux kernel # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. -%define debugbuildsenabled 1 +%define debugbuildsenabled 0 # Want to build a vanilla kernel build without any non-upstream patches? %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} @@ -696,6 +696,7 @@ Patch12205: runtime_pm_fixups.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13000: fix-scsi_dispatch_cmd.patch +Patch13001: epoll-fix-spurious-lockdep-warnings.patch Patch20000: utrace.patch @@ -1280,6 +1281,7 @@ ApplyPatch udlfb-bind-framebuffer-to-interface.patch ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch fix-scsi_dispatch_cmd.patch +ApplyPatch epoll-fix-spurious-lockdep-warnings.patch # utrace. ApplyPatch utrace.patch @@ -1893,6 +1895,10 @@ fi # and build. %changelog +* Tue Aug 02 2011 Josh Boyer +- Fix epoll recursive lockdep warnings (rhbz 722472) +- Turn debug builds back on + * Tue Aug 02 2011 Josh Boyer - Add change from Yanko Kaneti to get the rt2x00 drivers in modules.networking (rhbz 708314) From e0ce6b691cc02dd16c0fb91ad5a16da874c3a02f Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 2 Aug 2011 18:19:14 -0400 Subject: [PATCH 008/487] Change USB_SERIAL_OPTION back to modular. (rhbz 727680) --- config-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index a1ebab70f..36f6379ab 100644 --- a/config-generic +++ b/config-generic @@ -3381,7 +3381,7 @@ CONFIG_USB_SERIAL_MOS7715_PARPORT=y CONFIG_USB_SERIAL_MOS7840=m CONFIG_USB_SERIAL_MOTOROLA=m CONFIG_USB_SERIAL_NAVMAN=m -CONFIG_USB_SERIAL_OPTION=y +CONFIG_USB_SERIAL_OPTION=m CONFIG_USB_SERIAL_OTI6858=m CONFIG_USB_SERIAL_OPTICON=m CONFIG_USB_SERIAL_OMNINET=m diff --git a/kernel.spec b/kernel.spec index 7e8210d15..dfe7cdf7a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1895,6 +1895,9 @@ fi # and build. %changelog +* Tue Aug 02 2011 Dave Jones +- Change USB_SERIAL_OPTION back to modular. (rhbz 727680) + * Tue Aug 02 2011 Josh Boyer - Fix epoll recursive lockdep warnings (rhbz 722472) - Turn debug builds back on From 0c6a0c8d9d81a40eefa4dbfb45c17fc5f4722ebe Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 2 Aug 2011 19:23:10 -0400 Subject: [PATCH 009/487] Add fix from 3.1 for mounting HFSPlus filesystems --- ...io-requests-are-not-smaller-than-the.patch | 315 ++++++++++++++++++ kernel.spec | 7 +- 2 files changed, 321 insertions(+), 1 deletion(-) create mode 100644 hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch diff --git a/hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch b/hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch new file mode 100644 index 000000000..c81bf91d1 --- /dev/null +++ b/hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch @@ -0,0 +1,315 @@ +From 6596528e391ad978a6a120142cba97a1d7324cb6 Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Mon, 18 Jul 2011 08:06:23 -0700 +Subject: [PATCH] hfsplus: ensure bio requests are not smaller than the + hardware sectors + +Currently all bio requests are 512 bytes, which may fail for media +whose physical sector size is larger than this. Ensure these +requests are not smaller than the block device logical block size. + +BugLink: http://bugs.launchpad.net/bugs/734883 +Signed-off-by: Seth Forshee +Signed-off-by: Christoph Hellwig +--- + fs/hfsplus/hfsplus_fs.h | 16 ++++++++- + fs/hfsplus/part_tbl.c | 32 ++++++++++-------- + fs/hfsplus/super.c | 12 +++--- + fs/hfsplus/wrapper.c | 83 +++++++++++++++++++++++++++++++++++----------- + 4 files changed, 101 insertions(+), 42 deletions(-) + +diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h +index 0bebf74..81dfd1e 100644 +--- a/fs/hfsplus/hfsplus_fs.h ++++ b/fs/hfsplus/hfsplus_fs.h +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include "hfsplus_raw.h" + + #define DBG_BNODE_REFS 0x00000001 +@@ -110,7 +111,9 @@ struct hfsplus_vh; + struct hfs_btree; + + struct hfsplus_sb_info { ++ void *s_vhdr_buf; + struct hfsplus_vh *s_vhdr; ++ void *s_backup_vhdr_buf; + struct hfsplus_vh *s_backup_vhdr; + struct hfs_btree *ext_tree; + struct hfs_btree *cat_tree; +@@ -258,6 +261,15 @@ struct hfsplus_readdir_data { + struct hfsplus_cat_key key; + }; + ++/* ++ * Find minimum acceptible I/O size for an hfsplus sb. ++ */ ++static inline unsigned short hfsplus_min_io_size(struct super_block *sb) ++{ ++ return max_t(unsigned short, bdev_logical_block_size(sb->s_bdev), ++ HFSPLUS_SECTOR_SIZE); ++} ++ + #define hfs_btree_open hfsplus_btree_open + #define hfs_btree_close hfsplus_btree_close + #define hfs_btree_write hfsplus_btree_write +@@ -436,8 +448,8 @@ int hfsplus_compare_dentry(const struct dentry *parent, + /* wrapper.c */ + int hfsplus_read_wrapper(struct super_block *); + int hfs_part_find(struct super_block *, sector_t *, sector_t *); +-int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, +- void *data, int rw); ++int hfsplus_submit_bio(struct super_block *sb, sector_t sector, ++ void *buf, void **data, int rw); + + /* time macros */ + #define __hfsp_mt2ut(t) (be32_to_cpu(t) - 2082844800U) +diff --git a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c +index 40ad88c..eb355d8 100644 +--- a/fs/hfsplus/part_tbl.c ++++ b/fs/hfsplus/part_tbl.c +@@ -88,11 +88,12 @@ static int hfs_parse_old_pmap(struct super_block *sb, struct old_pmap *pm, + return -ENOENT; + } + +-static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm, +- sector_t *part_start, sector_t *part_size) ++static int hfs_parse_new_pmap(struct super_block *sb, void *buf, ++ struct new_pmap *pm, sector_t *part_start, sector_t *part_size) + { + struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); + int size = be32_to_cpu(pm->pmMapBlkCnt); ++ int buf_size = hfsplus_min_io_size(sb); + int res; + int i = 0; + +@@ -107,11 +108,14 @@ static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm, + if (++i >= size) + return -ENOENT; + +- res = hfsplus_submit_bio(sb->s_bdev, +- *part_start + HFS_PMAP_BLK + i, +- pm, READ); +- if (res) +- return res; ++ pm = (struct new_pmap *)((u8 *)pm + HFSPLUS_SECTOR_SIZE); ++ if ((u8 *)pm - (u8 *)buf >= buf_size) { ++ res = hfsplus_submit_bio(sb, ++ *part_start + HFS_PMAP_BLK + i, ++ buf, (void **)&pm, READ); ++ if (res) ++ return res; ++ } + } while (pm->pmSig == cpu_to_be16(HFS_NEW_PMAP_MAGIC)); + + return -ENOENT; +@@ -124,15 +128,15 @@ static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm, + int hfs_part_find(struct super_block *sb, + sector_t *part_start, sector_t *part_size) + { +- void *data; ++ void *buf, *data; + int res; + +- data = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL); +- if (!data) ++ buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); ++ if (!buf) + return -ENOMEM; + +- res = hfsplus_submit_bio(sb->s_bdev, *part_start + HFS_PMAP_BLK, +- data, READ); ++ res = hfsplus_submit_bio(sb, *part_start + HFS_PMAP_BLK, ++ buf, &data, READ); + if (res) + goto out; + +@@ -141,13 +145,13 @@ int hfs_part_find(struct super_block *sb, + res = hfs_parse_old_pmap(sb, data, part_start, part_size); + break; + case HFS_NEW_PMAP_MAGIC: +- res = hfs_parse_new_pmap(sb, data, part_start, part_size); ++ res = hfs_parse_new_pmap(sb, buf, data, part_start, part_size); + break; + default: + res = -ENOENT; + break; + } + out: +- kfree(data); ++ kfree(buf); + return res; + } +diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c +index 84f56e1..c106ca2 100644 +--- a/fs/hfsplus/super.c ++++ b/fs/hfsplus/super.c +@@ -203,17 +203,17 @@ int hfsplus_sync_fs(struct super_block *sb, int wait) + write_backup = 1; + } + +- error2 = hfsplus_submit_bio(sb->s_bdev, ++ error2 = hfsplus_submit_bio(sb, + sbi->part_start + HFSPLUS_VOLHEAD_SECTOR, +- sbi->s_vhdr, WRITE_SYNC); ++ sbi->s_vhdr_buf, NULL, WRITE_SYNC); + if (!error) + error = error2; + if (!write_backup) + goto out; + +- error2 = hfsplus_submit_bio(sb->s_bdev, ++ error2 = hfsplus_submit_bio(sb, + sbi->part_start + sbi->sect_count - 2, +- sbi->s_backup_vhdr, WRITE_SYNC); ++ sbi->s_backup_vhdr_buf, NULL, WRITE_SYNC); + if (!error) + error2 = error; + out: +@@ -257,8 +257,8 @@ static void hfsplus_put_super(struct super_block *sb) + hfs_btree_close(sbi->ext_tree); + iput(sbi->alloc_file); + iput(sbi->hidden_dir); +- kfree(sbi->s_vhdr); +- kfree(sbi->s_backup_vhdr); ++ kfree(sbi->s_vhdr_buf); ++ kfree(sbi->s_backup_vhdr_buf); + unload_nls(sbi->nls); + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; +diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c +index 2f933e8..10e515a 100644 +--- a/fs/hfsplus/wrapper.c ++++ b/fs/hfsplus/wrapper.c +@@ -31,25 +31,67 @@ static void hfsplus_end_io_sync(struct bio *bio, int err) + complete(bio->bi_private); + } + +-int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, +- void *data, int rw) ++/* ++ * hfsplus_submit_bio - Perfrom block I/O ++ * @sb: super block of volume for I/O ++ * @sector: block to read or write, for blocks of HFSPLUS_SECTOR_SIZE bytes ++ * @buf: buffer for I/O ++ * @data: output pointer for location of requested data ++ * @rw: direction of I/O ++ * ++ * The unit of I/O is hfsplus_min_io_size(sb), which may be bigger than ++ * HFSPLUS_SECTOR_SIZE, and @buf must be sized accordingly. On reads ++ * @data will return a pointer to the start of the requested sector, ++ * which may not be the same location as @buf. ++ * ++ * If @sector is not aligned to the bdev logical block size it will ++ * be rounded down. For writes this means that @buf should contain data ++ * that starts at the rounded-down address. As long as the data was ++ * read using hfsplus_submit_bio() and the same buffer is used things ++ * will work correctly. ++ */ ++int hfsplus_submit_bio(struct super_block *sb, sector_t sector, ++ void *buf, void **data, int rw) + { + DECLARE_COMPLETION_ONSTACK(wait); + struct bio *bio; + int ret = 0; ++ unsigned int io_size; ++ loff_t start; ++ int offset; ++ ++ /* ++ * Align sector to hardware sector size and find offset. We ++ * assume that io_size is a power of two, which _should_ ++ * be true. ++ */ ++ io_size = hfsplus_min_io_size(sb); ++ start = (loff_t)sector << HFSPLUS_SECTOR_SHIFT; ++ offset = start & (io_size - 1); ++ sector &= ~((io_size >> HFSPLUS_SECTOR_SHIFT) - 1); + + bio = bio_alloc(GFP_NOIO, 1); + bio->bi_sector = sector; +- bio->bi_bdev = bdev; ++ bio->bi_bdev = sb->s_bdev; + bio->bi_end_io = hfsplus_end_io_sync; + bio->bi_private = &wait; + +- /* +- * We always submit one sector at a time, so bio_add_page must not fail. +- */ +- if (bio_add_page(bio, virt_to_page(data), HFSPLUS_SECTOR_SIZE, +- offset_in_page(data)) != HFSPLUS_SECTOR_SIZE) +- BUG(); ++ if (!(rw & WRITE) && data) ++ *data = (u8 *)buf + offset; ++ ++ while (io_size > 0) { ++ unsigned int page_offset = offset_in_page(buf); ++ unsigned int len = min_t(unsigned int, PAGE_SIZE - page_offset, ++ io_size); ++ ++ ret = bio_add_page(bio, virt_to_page(buf), len, page_offset); ++ if (ret != len) { ++ ret = -EIO; ++ goto out; ++ } ++ io_size -= len; ++ buf = (u8 *)buf + len; ++ } + + submit_bio(rw, bio); + wait_for_completion(&wait); +@@ -57,8 +99,9 @@ int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, + if (!bio_flagged(bio, BIO_UPTODATE)) + ret = -EIO; + ++out: + bio_put(bio); +- return ret; ++ return ret < 0 ? ret : 0; + } + + static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd) +@@ -143,17 +186,17 @@ int hfsplus_read_wrapper(struct super_block *sb) + goto out; + + error = -ENOMEM; +- sbi->s_vhdr = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL); +- if (!sbi->s_vhdr) ++ sbi->s_vhdr_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); ++ if (!sbi->s_vhdr_buf) + goto out; +- sbi->s_backup_vhdr = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL); +- if (!sbi->s_backup_vhdr) ++ sbi->s_backup_vhdr_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); ++ if (!sbi->s_backup_vhdr_buf) + goto out_free_vhdr; + + reread: +- error = hfsplus_submit_bio(sb->s_bdev, +- part_start + HFSPLUS_VOLHEAD_SECTOR, +- sbi->s_vhdr, READ); ++ error = hfsplus_submit_bio(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, ++ sbi->s_vhdr_buf, (void **)&sbi->s_vhdr, ++ READ); + if (error) + goto out_free_backup_vhdr; + +@@ -183,9 +226,9 @@ reread: + goto reread; + } + +- error = hfsplus_submit_bio(sb->s_bdev, +- part_start + part_size - 2, +- sbi->s_backup_vhdr, READ); ++ error = hfsplus_submit_bio(sb, part_start + part_size - 2, ++ sbi->s_backup_vhdr_buf, ++ (void **)&sbi->s_backup_vhdr, READ); + if (error) + goto out_free_backup_vhdr; + +-- +1.7.6 + diff --git a/kernel.spec b/kernel.spec index dfe7cdf7a..c2d30b1d5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -697,6 +697,7 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13000: fix-scsi_dispatch_cmd.patch Patch13001: epoll-fix-spurious-lockdep-warnings.patch +Patch13002: hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch Patch20000: utrace.patch @@ -1282,6 +1283,7 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch fix-scsi_dispatch_cmd.patch ApplyPatch epoll-fix-spurious-lockdep-warnings.patch +ApplyPatch hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch # utrace. ApplyPatch utrace.patch @@ -1895,6 +1897,9 @@ fi # and build. %changelog +* Tue Aug 02 2011 Josh Boyer +- Add patch to fix HFSPlus filesystem mounting (rhbz 720771) + * Tue Aug 02 2011 Dave Jones - Change USB_SERIAL_OPTION back to modular. (rhbz 727680) From b91dd47839b4f61cd471f50913f64392dcfdf406 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 3 Aug 2011 08:07:37 -0400 Subject: [PATCH 010/487] Add patches for rhbz 720128,720054 --- fix-cdc-ncm-dma-stack-vars.patch | 114 ++++++++++++++++++ kernel.spec | 9 ++ ...tek-driver-uses-stack-memory-for-DMA.patch | 96 +++++++++++++++ 3 files changed, 219 insertions(+) create mode 100644 fix-cdc-ncm-dma-stack-vars.patch create mode 100644 ums-realtek-driver-uses-stack-memory-for-DMA.patch diff --git a/fix-cdc-ncm-dma-stack-vars.patch b/fix-cdc-ncm-dma-stack-vars.patch new file mode 100644 index 000000000..7f46a00fe --- /dev/null +++ b/fix-cdc-ncm-dma-stack-vars.patch @@ -0,0 +1,114 @@ +commit d072ef23b8ee6bcabc00beff0b5702e704a473cb +Author: Josh Boyer +Date: Tue Aug 2 08:09:56 2011 -0400 + + usbnet/cdc_ncm: Don't use stack variables for DMA buffers + + The cdc_ncm driver still has a few places where stack variables are passed + to the cdc_ncm_do_request function. This triggers a stack trace in + lib/dma-debug.c if the CONFIG_DEBUG_DMA_API option is set. + + Adjust these calls to pass parameters that have been allocated with kzalloc. + + Signed-off-by: Josh Boyer + +diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c +index fd622a6..96dd386 100644 +--- a/drivers/net/usb/cdc_ncm.c ++++ b/drivers/net/usb/cdc_ncm.c +@@ -260,23 +260,38 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) + req.wIndex = cpu_to_le16(iface_no); + + if (flags & USB_CDC_NCM_NCAP_NTB_INPUT_SIZE) { +- struct usb_cdc_ncm_ndp_input_size ndp_in_sz; ++ struct usb_cdc_ncm_ndp_input_size *ndp_in_sz; ++ ++ ndp_in_sz = kzalloc(sizeof(*ndp_in_sz), GFP_KERNEL); ++ if (!ndp_in_sz) { ++ err = -ENOMEM; ++ goto size_err; ++ } + + req.wLength = 8; +- ndp_in_sz.dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); +- ndp_in_sz.wNtbInMaxDatagrams = ++ ndp_in_sz->dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); ++ ndp_in_sz->wNtbInMaxDatagrams = + cpu_to_le16(CDC_NCM_DPT_DATAGRAMS_MAX); +- ndp_in_sz.wReserved = 0; +- err = cdc_ncm_do_request(ctx, &req, &ndp_in_sz, 0, NULL, ++ ndp_in_sz->wReserved = 0; ++ err = cdc_ncm_do_request(ctx, &req, ndp_in_sz, 0, NULL, + 1000); ++ kfree(ndp_in_sz); + } else { +- __le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); ++ __le32 *dwNtbInMaxSize; ++ dwNtbInMaxSize = kzalloc(sizeof(*dwNtbInMaxSize), GFP_KERNEL); ++ if (!dwNtbInMaxSize) { ++ err = -ENOMEM; ++ goto size_err; ++ } ++ *dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); + + req.wLength = 4; +- err = cdc_ncm_do_request(ctx, &req, &dwNtbInMaxSize, 0, ++ err = cdc_ncm_do_request(ctx, &req, dwNtbInMaxSize, 0, + NULL, 1000); ++ kfree(dwNtbInMaxSize); + } + ++size_err: + if (err) + pr_debug("Setting NTB Input Size failed\n"); + } +@@ -362,9 +377,15 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) + + /* set Max Datagram Size (MTU) */ + if (flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE) { +- __le16 max_datagram_size; ++ __le16 *max_datagram_size; + u16 eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize); + ++ max_datagram_size = kzalloc(sizeof(*max_datagram_size), GFP_KERNEL); ++ if (!max_datagram_size) { ++ err = -ENOMEM; ++ goto max_dgram_err; ++ } ++ + req.bmRequestType = USB_TYPE_CLASS | USB_DIR_IN | + USB_RECIP_INTERFACE; + req.bNotificationType = USB_CDC_GET_MAX_DATAGRAM_SIZE; +@@ -372,13 +393,15 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) + req.wIndex = cpu_to_le16(iface_no); + req.wLength = cpu_to_le16(2); + +- err = cdc_ncm_do_request(ctx, &req, &max_datagram_size, 0, NULL, ++ err = cdc_ncm_do_request(ctx, &req, max_datagram_size, 0, NULL, + 1000); ++ + if (err) { + pr_debug("GET_MAX_DATAGRAM_SIZE failed, use size=%u\n", + CDC_NCM_MIN_DATAGRAM_SIZE); ++ kfree(max_datagram_size); + } else { +- ctx->max_datagram_size = le16_to_cpu(max_datagram_size); ++ ctx->max_datagram_size = le16_to_cpu(*max_datagram_size); + /* Check Eth descriptor value */ + if (eth_max_sz < CDC_NCM_MAX_DATAGRAM_SIZE) { + if (ctx->max_datagram_size > eth_max_sz) +@@ -401,10 +424,12 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) + req.wValue = 0; + req.wIndex = cpu_to_le16(iface_no); + req.wLength = 2; +- max_datagram_size = cpu_to_le16(ctx->max_datagram_size); ++ *max_datagram_size = cpu_to_le16(ctx->max_datagram_size); + +- err = cdc_ncm_do_request(ctx, &req, &max_datagram_size, ++ err = cdc_ncm_do_request(ctx, &req, max_datagram_size, + 0, NULL, 1000); ++ kfree(max_datagram_size); ++max_dgram_err: + if (err) + pr_debug("SET_MAX_DATAGRAM_SIZE failed\n"); + } diff --git a/kernel.spec b/kernel.spec index c2d30b1d5..2016b0e20 100644 --- a/kernel.spec +++ b/kernel.spec @@ -688,6 +688,9 @@ Patch12020: linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch Patch12021: udlfb-bind-framebuffer-to-interface.patch +Patch12022: fix-cdc-ncm-dma-stack-vars.patch +Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch + # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch Patch12204: linux-2.6-enable-more-pci-autosuspend.patch @@ -1271,6 +1274,8 @@ ApplyPatch neuter_intel_microcode_load.patch ApplyPatch linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch ApplyPatch udlfb-bind-framebuffer-to-interface.patch +ApplyPatch fix-cdc-ncm-dma-stack-vars.patch +ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch # Runtime PM #ApplyPatch linux-2.6-usb-pci-autosuspend.patch @@ -1897,6 +1902,10 @@ fi # and build. %changelog +* Wed Aug 03 2011 Josh Boyer +- Add patch to fix backtrace in cdc_ncm driver (rhbz 720128) +- Add patch to fix backtrace in usm-realtek driver (rhbz 720054) + * Tue Aug 02 2011 Josh Boyer - Add patch to fix HFSPlus filesystem mounting (rhbz 720771) diff --git a/ums-realtek-driver-uses-stack-memory-for-DMA.patch b/ums-realtek-driver-uses-stack-memory-for-DMA.patch new file mode 100644 index 000000000..2564fdbf2 --- /dev/null +++ b/ums-realtek-driver-uses-stack-memory-for-DMA.patch @@ -0,0 +1,96 @@ +commit 82e632009bb7d6b97f8cabe9918c82703f4e5cd2 +Author: Josh Boyer +Date: Tue Aug 2 08:37:53 2011 -0400 + + This patch changed rts51x_read_mem, rts51x_write_mem, and rts51x_read_status to + allocate temporary buffers with kmalloc. This way stack addresses are not used + for DMA when these functions call rts51x_bulk_transport. + + Signed-off-by: Adam Cozzette + Backported-by: Josh Boyer + +diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c +index d509a4a..69a1bd3 100644 +--- a/drivers/usb/storage/realtek_cr.c ++++ b/drivers/usb/storage/realtek_cr.c +@@ -285,6 +285,11 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) + { + int retval; + u8 cmnd[12] = {0}; ++ u8 *buf; ++ ++ buf = kmalloc(len, GFP_NOIO); ++ if (buf == NULL) ++ return USB_STOR_TRANSPORT_ERROR; + + US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); + +@@ -296,10 +301,14 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) + cmnd[5] = (u8)len; + + retval = rts51x_bulk_transport(us, 0, cmnd, 12, +- data, len, DMA_FROM_DEVICE, NULL); +- if (retval != USB_STOR_TRANSPORT_GOOD) ++ buf, len, DMA_FROM_DEVICE, NULL); ++ if (retval != USB_STOR_TRANSPORT_GOOD) { ++ kfree(buf); + return -EIO; ++ } + ++ memcpy(data, buf, len); ++ kfree(buf); + return 0; + } + +@@ -307,6 +316,12 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) + { + int retval; + u8 cmnd[12] = {0}; ++ u8 *buf; ++ ++ buf = kmalloc(len, GFP_NOIO); ++ if (buf == NULL) ++ return USB_STOR_TRANSPORT_ERROR; ++ memcpy(buf, data, len); + + US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); + +@@ -318,7 +333,8 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) + cmnd[5] = (u8)len; + + retval = rts51x_bulk_transport(us, 0, cmnd, 12, +- data, len, DMA_TO_DEVICE, NULL); ++ buf, len, DMA_TO_DEVICE, NULL); ++ kfree(buf); + if (retval != USB_STOR_TRANSPORT_GOOD) + return -EIO; + +@@ -330,6 +346,11 @@ static int rts51x_read_status(struct us_data *us, + { + int retval; + u8 cmnd[12] = {0}; ++ u8 *buf; ++ ++ buf = kmalloc(len, GFP_NOIO); ++ if (buf == NULL) ++ return USB_STOR_TRANSPORT_ERROR; + + US_DEBUGP("%s, lun = %d\n", __func__, lun); + +@@ -337,10 +358,14 @@ static int rts51x_read_status(struct us_data *us, + cmnd[1] = 0x09; + + retval = rts51x_bulk_transport(us, lun, cmnd, 12, +- status, len, DMA_FROM_DEVICE, actlen); +- if (retval != USB_STOR_TRANSPORT_GOOD) ++ buf, len, DMA_FROM_DEVICE, actlen); ++ if (retval != USB_STOR_TRANSPORT_GOOD) { ++ kfree(buf); + return -EIO; ++ } + ++ memcpy(status, buf, len); ++ kfree(buf); + return 0; + } + From 0df6e18dc6901b8ab2d9ca6f77255e3b1c6f03bd Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 3 Aug 2011 13:37:40 -0400 Subject: [PATCH 011/487] Disable CONFIG_BCMA since no driver currently uses it (rhbz 727796) --- config-generic | 4 +--- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/config-generic b/config-generic index 36f6379ab..52793e9e2 100644 --- a/config-generic +++ b/config-generic @@ -4661,9 +4661,7 @@ CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 CONFIG_TEST_KSTRTOX=m -CONFIG_BCMA=m -CONFIG_BCMA_HOST_PCI=y -# CONFIG_BCMA_DEBUG is not set +# CONFIG_BCMA is not set # CONFIG_GOOGLE_FIRMWARE is not set CONFIG_INTEL_MID_PTI=m diff --git a/kernel.spec b/kernel.spec index 2016b0e20..f1873007c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1902,6 +1902,9 @@ fi # and build. %changelog +* Wed Aug 03 2011 John W. Linville +- Disable CONFIG_BCMA since no driver currently uses it (rhbz 727796) + * Wed Aug 03 2011 Josh Boyer - Add patch to fix backtrace in cdc_ncm driver (rhbz 720128) - Add patch to fix backtrace in usm-realtek driver (rhbz 720054) From 9efe707d77bd66be72e1d0bd97a4c0934e9cffaa Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 4 Aug 2011 13:27:47 -0400 Subject: [PATCH 012/487] Drop neuter_intel_microcode_load.patch (rhbz 690930) --- kernel.spec | 7 +++---- neuter_intel_microcode_load.patch | 24 ------------------------ 2 files changed, 3 insertions(+), 28 deletions(-) delete mode 100644 neuter_intel_microcode_load.patch diff --git a/kernel.spec b/kernel.spec index f1873007c..6ab3c73e4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -680,8 +680,6 @@ Patch12010: add-appleir-usb-driver.patch Patch12016: disable-i8042-check-on-apple-mac.patch -Patch12018: neuter_intel_microcode_load.patch - Patch12019: linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch Patch12020: linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch @@ -1269,8 +1267,6 @@ ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch add-appleir-usb-driver.patch -ApplyPatch neuter_intel_microcode_load.patch - ApplyPatch linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch ApplyPatch udlfb-bind-framebuffer-to-interface.patch @@ -1902,6 +1898,9 @@ fi # and build. %changelog +* Thu Aug 04 2011 Dave Jones +- Drop neuter_intel_microcode_load.patch (rhbz 690930) + * Wed Aug 03 2011 John W. Linville - Disable CONFIG_BCMA since no driver currently uses it (rhbz 727796) diff --git a/neuter_intel_microcode_load.patch b/neuter_intel_microcode_load.patch deleted file mode 100644 index 2766e439d..000000000 --- a/neuter_intel_microcode_load.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c -index ebd193e..c57024a 100644 ---- a/arch/x86/kernel/microcode_intel.c -+++ b/arch/x86/kernel/microcode_intel.c -@@ -453,9 +453,18 @@ static void microcode_fini_cpu(int cpu) - uci->mc = NULL; - } - -+/* we don't ship the broken out files... -+ * instead, we'll just fail here, and load it with microcode_ctl -+ */ -+static enum ucode_state noop_request_microcode_fw(int cpu, -+ struct device *device) -+{ -+ return UCODE_NFOUND; -+} -+ - static struct microcode_ops microcode_intel_ops = { - .request_microcode_user = request_microcode_user, -- .request_microcode_fw = request_microcode_fw, -+ .request_microcode_fw = noop_request_microcode_fw, - .collect_cpu_info = collect_cpu_info, - .apply_microcode = apply_microcode, - .microcode_fini_cpu = microcode_fini_cpu, From 6f3e186bc7721c5b24ad90d4a751cccfccd445e6 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Aug 2011 08:47:23 -0400 Subject: [PATCH 013/487] Add patch to fix 32bit EFI service mapping (rhbz 726701) --- efi-dont-map-boot-services-on-32bit.patch | 22 ++++++++++++++++++++++ kernel.spec | 8 +++++++- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 efi-dont-map-boot-services-on-32bit.patch diff --git a/efi-dont-map-boot-services-on-32bit.patch b/efi-dont-map-boot-services-on-32bit.patch new file mode 100644 index 000000000..7cc614992 --- /dev/null +++ b/efi-dont-map-boot-services-on-32bit.patch @@ -0,0 +1,22 @@ +diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c +index 3ae4128..ff7dc70 100644 +--- a/arch/x86/platform/efi/efi.c ++++ b/arch/x86/platform/efi/efi.c +@@ -659,10 +659,13 @@ void __init efi_enter_virtual_mode(void) + + for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { + md = p; +- if (!(md->attribute & EFI_MEMORY_RUNTIME) && +- md->type != EFI_BOOT_SERVICES_CODE && +- md->type != EFI_BOOT_SERVICES_DATA) +- continue; ++ if (!(md->attribute & EFI_MEMORY_RUNTIME)) { ++#ifdef CONFIG_X86_64 ++ if (md->type != EFI_BOOT_SERVICES_CODE && ++ md->type != EFI_BOOT_SERVICES_DATA) ++#endif ++ continue; ++ } + + size = md->num_pages << EFI_PAGE_SHIFT; + end = md->phys_addr + size; diff --git a/kernel.spec b/kernel.spec index 6ab3c73e4..b675ba66e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -700,6 +700,7 @@ Patch13000: fix-scsi_dispatch_cmd.patch Patch13001: epoll-fix-spurious-lockdep-warnings.patch Patch13002: hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch +Patch13003: efi-dont-map-boot-services-on-32bit.patch Patch20000: utrace.patch %endif @@ -1286,6 +1287,8 @@ ApplyPatch fix-scsi_dispatch_cmd.patch ApplyPatch epoll-fix-spurious-lockdep-warnings.patch ApplyPatch hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch +ApplyPatch efi-dont-map-boot-services-on-32bit.patch + # utrace. ApplyPatch utrace.patch @@ -1898,6 +1901,9 @@ fi # and build. %changelog +* Fri Aug 05 2011 Josh Boyer +- Add patch for rhbz 726701 from Matthew Garrett + * Thu Aug 04 2011 Dave Jones - Drop neuter_intel_microcode_load.patch (rhbz 690930) From 5bc7ff510af16fd5916ed8f03acb954024857fc5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Aug 2011 10:54:24 -0400 Subject: [PATCH 014/487] Linux 3.0.1 stable update. Drop included patches --- fix-scsi_dispatch_cmd.patch | 68 ------------------- kernel.spec | 13 ++-- ...2x00-Add-device-ID-for-RT539F-device.patch | 23 ------- sources | 1 + 4 files changed, 6 insertions(+), 99 deletions(-) delete mode 100644 fix-scsi_dispatch_cmd.patch delete mode 100644 linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch diff --git a/fix-scsi_dispatch_cmd.patch b/fix-scsi_dispatch_cmd.patch deleted file mode 100644 index 3976791ca..000000000 --- a/fix-scsi_dispatch_cmd.patch +++ /dev/null @@ -1,68 +0,0 @@ -commit bfe159a51203c15d23cb3158fffdc25ec4b4dda1 -Author: James Bottomley -Date: Thu Jul 7 15:45:40 2011 -0500 - - [SCSI] fix crash in scsi_dispatch_cmd() - - USB surprise removal of sr is triggering an oops in - scsi_dispatch_command(). What seems to be happening is that USB is - hanging on to a queue reference until the last close of the upper - device, so the crash is caused by surprise remove of a mounted CD - followed by attempted unmount. - - The problem is that USB doesn't issue its final commands as part of - the SCSI teardown path, but on last close when the block queue is long - gone. The long term fix is probably to make sr do the teardown in the - same way as sd (so remove all the lower bits on ejection, but keep the - upper disk alive until last close of user space). However, the - current oops can be simply fixed by not allowing any commands to be - sent to a dead queue. - - Cc: stable@kernel.org - Signed-off-by: James Bottomley - -diff --git a/block/blk-core.c b/block/blk-core.c -index d2f8f40..1d49e1c 100644 ---- a/block/blk-core.c -+++ b/block/blk-core.c -@@ -839,6 +839,9 @@ struct request *blk_get_request(struct request_queue *q, int rw, gfp_t gfp_mask) - { - struct request *rq; - -+ if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) -+ return NULL; -+ - BUG_ON(rw != READ && rw != WRITE); - - spin_lock_irq(q->queue_lock); -diff --git a/block/blk-exec.c b/block/blk-exec.c -index 8a0e7ec..a1ebceb 100644 ---- a/block/blk-exec.c -+++ b/block/blk-exec.c -@@ -50,6 +50,13 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, - { - int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; - -+ if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) { -+ rq->errors = -ENXIO; -+ if (rq->end_io) -+ rq->end_io(rq, rq->errors); -+ return; -+ } -+ - rq->rq_disk = bd_disk; - rq->end_io = done; - WARN_ON(irqs_disabled()); -diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c -index ec1803a..28d9c9d 100644 ---- a/drivers/scsi/scsi_lib.c -+++ b/drivers/scsi/scsi_lib.c -@@ -213,6 +213,8 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, - int ret = DRIVER_ERROR << 24; - - req = blk_get_request(sdev->request_queue, write, __GFP_WAIT); -+ if (!req) -+ return ret; - - if (bufflen && blk_rq_map_kern(sdev->request_queue, req, - buffer, bufflen, __GFP_WAIT)) diff --git a/kernel.spec b/kernel.spec index b675ba66e..bc5fcd4e7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 5 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -63,7 +63,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 0 +%define stable_update 1 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -680,8 +680,6 @@ Patch12010: add-appleir-usb-driver.patch Patch12016: disable-i8042-check-on-apple-mac.patch -Patch12019: linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch - Patch12020: linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch Patch12021: udlfb-bind-framebuffer-to-interface.patch @@ -696,7 +694,6 @@ Patch12205: runtime_pm_fixups.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch -Patch13000: fix-scsi_dispatch_cmd.patch Patch13001: epoll-fix-spurious-lockdep-warnings.patch Patch13002: hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch @@ -1268,8 +1265,6 @@ ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch add-appleir-usb-driver.patch -ApplyPatch linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch - ApplyPatch udlfb-bind-framebuffer-to-interface.patch ApplyPatch fix-cdc-ncm-dma-stack-vars.patch ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch @@ -1283,7 +1278,6 @@ ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch -ApplyPatch fix-scsi_dispatch_cmd.patch ApplyPatch epoll-fix-spurious-lockdep-warnings.patch ApplyPatch hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch @@ -1901,6 +1895,9 @@ fi # and build. %changelog +* Fri Aug 05 2011 Josh Boyer +- 3.0.1 + * Fri Aug 05 2011 Josh Boyer - Add patch for rhbz 726701 from Matthew Garrett diff --git a/linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch b/linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch deleted file mode 100644 index abf01cfe4..000000000 --- a/linux-2.6-rt2x00-Add-device-ID-for-RT539F-device.patch +++ /dev/null @@ -1,23 +0,0 @@ -commit 71e0b38c2914018b01f3f08b43ee9e3328197699 -Author: Gertjan van Wingerde -Date: Wed Jul 6 22:58:55 2011 +0200 - - rt2x00: Add device ID for RT539F device. - - Reported-by: Wim Vander Schelden - Signed-off-by: Gertjan van Wingerde - Signed-off-by: Ivo van Doorn - Signed-off-by: John W. Linville - -diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c -index 5513edf..fd99449 100644 ---- a/drivers/net/wireless/rt2x00/rt2800pci.c -+++ b/drivers/net/wireless/rt2x00/rt2800pci.c -@@ -1160,6 +1160,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { - #endif - #ifdef CONFIG_RT2800PCI_RT53XX - { PCI_DEVICE(0x1814, 0x5390) }, -+ { PCI_DEVICE(0x1814, 0x539f) }, - #endif - { 0, } - }; diff --git a/sources b/sources index cbf1c63cd..e117e493c 100644 --- a/sources +++ b/sources @@ -1 +1,2 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 +ac49f7907f1fc85fbab92d0f1aa1552a patch-3.0.1.bz2 From 702278a733410359c325dc3e2c5606a34d780fc3 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 5 Aug 2011 16:13:33 -0400 Subject: [PATCH 015/487] Deselect CONFIG_DECNET. Unmaintained, and rubbish. --- config-generic | 4 +--- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/config-generic b/config-generic index 52793e9e2..63327649e 100644 --- a/config-generic +++ b/config-generic @@ -844,9 +844,7 @@ CONFIG_NET_9P_VIRTIO=m # CONFIG_NET_9P_DEBUG is not set CONFIG_NET_9P_RDMA=m -CONFIG_DECNET=m -CONFIG_DECNET_ROUTER=y -# CONFIG_DECNET_NF_GRABULATOR is not set +# CONFIG_DECNET is not set CONFIG_BRIDGE=m CONFIG_BRIDGE_IGMP_SNOOPING=y # CONFIG_NETWORK_PHY_TIMESTAMPING is not set diff --git a/kernel.spec b/kernel.spec index bc5fcd4e7..aebc691b0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1895,6 +1895,9 @@ fi # and build. %changelog +* Fri Aug 05 2011 Dave Jones +- Deselect CONFIG_DECNET. Unmaintained, and rubbish. + * Fri Aug 05 2011 Josh Boyer - 3.0.1 From bca2221f92a30ed079a73943b1fb89a9f9068d02 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 5 Aug 2011 14:44:20 -0400 Subject: [PATCH 016/487] Adjust for 3.x numbering scheme --- kernel.spec | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/kernel.spec b/kernel.spec index aebc691b0..79be57bf3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -68,7 +68,7 @@ Summary: The Linux kernel %define stable_rc 0 # Set rpm version accordingly %if 0%{?stable_update} -%define stablerev .%{stable_update} +%define stablerev %{stable_update} %define stable_base %{stable_update} %if 0%{?stable_rc} # stable RCs are incremental patches, so we need the previous stable patch @@ -1387,14 +1387,18 @@ BuildKernel() { KernelVer=%{version}-%{release}.%{_target_cpu}${Flavour:+.${Flavour}} echo BUILDING A KERNEL FOR ${Flavour} %{_target_cpu}... - # make sure EXTRAVERSION says what we want it to say - perl -p -i -e "s/^EXTRAVERSION.*/EXTRAVERSION = %{?stablerev}-%{release}.%{_target_cpu}${Flavour:+.${Flavour}}/" Makefile + %if 0%{?stable_update} + # make sure SUBLEVEL is incremented on a stable release. Sigh 3.x. + perl -p -i -e "s/^SUBLEVEL.*/SUBLEVEL = %{?stablerev}/" Makefile + %endif - # if pre-rc1 devel kernel, must fix up SUBLEVEL for our versioning scheme - ### XXX this will probably be dead code in 3.0 --kyle + # make sure EXTRAVERSION says what we want it to say + perl -p -i -e "s/^EXTRAVERSION.*/EXTRAVERSION = -%{release}.%{_target_cpu}${Flavour:+.${Flavour}}/" Makefile + + # if pre-rc1 devel kernel, must fix up PATCHLEVEL for our versioning scheme %if !0%{?rcrev} %if 0%{?gitrev} - perl -p -i -e 's/^SUBLEVEL.*/SUBLEVEL = %{upstream_sublevel}/' Makefile + perl -p -i -e 's/^PATCHLEVEL.*/PATCHLEVEL = %{upstream_sublevel}/' Makefile %endif %endif @@ -1895,6 +1899,9 @@ fi # and build. %changelog +* Fri Aug 05 2011 Josh Boyer +- Adjust Makefile munging for new 3.x numbering scheme + * Fri Aug 05 2011 Dave Jones - Deselect CONFIG_DECNET. Unmaintained, and rubbish. From c307f0b0e766acd54b7c9e031f9b613d85640371 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 8 Aug 2011 14:01:20 -0400 Subject: [PATCH 017/487] Update utrace patch --- kernel.spec | 5 +- utrace.patch | 1169 +++++++++++++++++++++++++++++++------------------- 2 files changed, 742 insertions(+), 432 deletions(-) diff --git a/kernel.spec b/kernel.spec index 79be57bf3..843f9f55f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -1899,6 +1899,9 @@ fi # and build. %changelog +* Mon Aug 08 2011 Josh Boyer +- Bring in utrace fixes davej applied to f15. (rhbz 728379) + * Fri Aug 05 2011 Josh Boyer - Adjust Makefile munging for new 3.x numbering scheme diff --git a/utrace.patch b/utrace.patch index 55d0b3c1b..f5515e3ed 100644 --- a/utrace.patch +++ b/utrace.patch @@ -1,41 +1,42 @@ -From davej Thu Jun 30 20:27:03 2011 +From davej Sun Aug 7 15:19:08 2011 Return-Path: oleg@redhat.com Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:03 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:00 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:08 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:17:59 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 10DAED812A; - Thu, 30 Jun 2011 20:23:00 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id fiwBBweCuo8A; Thu, 30 Jun 2011 20:22:59 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E7CA2D810F; - Thu, 30 Jun 2011 20:22:59 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F09A8A5D58; + Sun, 7 Aug 2011 15:17:58 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 6mY7uBb0+l7B; Sun, 7 Aug 2011 15:17:58 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D1DFE9C7FA; + Sun, 7 Aug 2011 15:17:58 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610MpCP015143; - Thu, 30 Jun 2011 20:22:52 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JHtc4027719; + Sun, 7 Aug 2011 15:17:56 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:20:59 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:20:57 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:19 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:17 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 01/19] utrace core -Message-ID: <20110701002057.GA25776@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 01/22] utrace core +Message-ID: <20110807191517.GA14365@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 148213 -Lines: 4119 +Content-Length: 148212 +Lines: 4118 From: Roland McGrath @@ -4156,8 +4157,7 @@ index 0000000..f332d65 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:04 2011 +From davej Sun Aug 7 15:19:09 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -4166,40 +4166,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:04 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:09 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:03 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:01 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2259ED812A; - Thu, 30 Jun 2011 20:23:03 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A1FB8D89A7; + Sun, 7 Aug 2011 15:18:01 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id Ex9fFDzwy1Zb; Thu, 30 Jun 2011 20:23:03 -0400 (EDT) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 0EF28D810F; - Thu, 30 Jun 2011 20:23:03 -0400 (EDT) + with ESMTP id JtiDMxvrW-Di; Sun, 7 Aug 2011 15:18:01 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7F0E6D8988; + Sun, 7 Aug 2011 15:18:01 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610Mt6X021086; - Thu, 30 Jun 2011 20:22:56 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JHxlJ027726; + Sun, 7 Aug 2011 15:17:59 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:03 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:01 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:23 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:21 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 02/19] utrace: remove jobctl bits -Message-ID: <20110701002101.GA25779@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 02/22] utrace: remove jobctl bits +Message-ID: <20110807191521.GA14373@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 1890 -Lines: 56 +Content-Length: 1889 +Lines: 55 - change utrace_get_signal() to check GROUP_STOP_PENDING instead of signal->group_stop_count. With the recent changes group_stop_count @@ -4257,8 +4258,7 @@ index f332d65..6e7fafb 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:05 2011 +From davej Sun Aug 7 15:19:10 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -4267,40 +4267,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:05 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:10 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:06 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:04 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6B38AD812A; - Thu, 30 Jun 2011 20:23:06 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 473EDD89A7; + Sun, 7 Aug 2011 15:18:04 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id f4153Z6E7KGl; Thu, 30 Jun 2011 20:23:06 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 55D4AD810F; - Thu, 30 Jun 2011 20:23:06 -0400 (EDT) + with ESMTP id uA3eVmUnKFQu; Sun, 7 Aug 2011 15:18:04 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 29079D8988; + Sun, 7 Aug 2011 15:18:04 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610Mwi2015168; - Thu, 30 Jun 2011 20:22:59 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JI1LH027738; + Sun, 7 Aug 2011 15:18:02 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:06 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:04 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:25 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:23 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 03/19] ptrace: take ->siglock around s/TRACED/RUNNING/ -Message-ID: <20110701002104.GA25787@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 03/22] ptrace: take ->siglock around s/TRACED/RUNNING/ +Message-ID: <20110807191523.GA14376@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 1624 -Lines: 56 +Content-Length: 1623 +Lines: 55 change ptrace_resume() and ptrace_stop() to take ->siglock around changing task->state from TRACED to RUNNING. @@ -4358,8 +4359,7 @@ index ff76786..2138cee 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:06 2011 +From davej Sun Aug 7 15:19:11 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -4368,40 +4368,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:06 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:09 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:11 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:06 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E1AB7D812A; - Thu, 30 Jun 2011 20:23:09 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id QhOnA49nS3Vp; Thu, 30 Jun 2011 20:23:09 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C5E15D810F; - Thu, 30 Jun 2011 20:23:09 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D76B6A5D58; + Sun, 7 Aug 2011 15:18:06 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id xyKeY-zzvTgR; Sun, 7 Aug 2011 15:18:06 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BB0E49C7FA; + Sun, 7 Aug 2011 15:18:06 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610N2Kd007635; - Thu, 30 Jun 2011 20:23:02 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JI4PF028668; + Sun, 7 Aug 2011 15:18:05 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:10 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:07 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:28 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:26 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 04/19] introduce wake_up_quiescent() -Message-ID: <20110701002107.GA25790@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 04/22] introduce wake_up_quiescent() +Message-ID: <20110807191526.GA14383@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 3104 -Lines: 93 +Content-Length: 3103 +Lines: 92 No functional changes. Add the new helper, wake_up_quiescent(task, state), which simply returns wake_up_state(task, state). Change all callers which @@ -4496,8 +4497,7 @@ index 6e7fafb..d7c547c 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:07 2011 +From davej Sun Aug 7 15:19:13 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -4506,40 +4506,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:07 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:13 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:13 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:09 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2CF811287F3; - Thu, 30 Jun 2011 20:23:13 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C8DCF1322A2; + Sun, 7 Aug 2011 15:18:09 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id dNPA3WxO-7pp; Thu, 30 Jun 2011 20:23:13 -0400 (EDT) + with ESMTP id ZQXZL5xrzV21; Sun, 7 Aug 2011 15:18:09 -0400 (EDT) Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 154D61287DD; - Thu, 30 Jun 2011 20:23:13 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B3D6D128FDA; + Sun, 7 Aug 2011 15:18:09 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610N5nY021107; - Thu, 30 Jun 2011 20:23:06 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JI7P5029847; + Sun, 7 Aug 2011 15:18:07 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:13 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:11 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:31 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:28 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 05/19] introduce ptrace_signal_wake_up() -Message-ID: <20110701002111.GA25797@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 05/22] introduce ptrace_signal_wake_up() +Message-ID: <20110807191528.GA14386@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO -Content-Length: 1975 -Lines: 68 +Content-Length: 1974 +Lines: 67 Add the new helper, ptrace_signal_wake_up(), change ptrace.c to use it instead of signal_wake_up(). @@ -4609,8 +4610,7 @@ index 26ae214..0b2aba5 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:08 2011 +From davej Sun Aug 7 15:19:14 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -4619,41 +4619,42 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:08 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:14 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:16 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:12 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6FB379C0CB; - Thu, 30 Jun 2011 20:23:16 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 72BBDA5D58; + Sun, 7 Aug 2011 15:18:12 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id IYB64KKErOyI; Thu, 30 Jun 2011 20:23:16 -0400 (EDT) + with ESMTP id k8I1SMuU0ydh; Sun, 7 Aug 2011 15:18:12 -0400 (EDT) Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 597119C0C5; - Thu, 30 Jun 2011 20:23:16 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5DFAB9C7FA; + Sun, 7 Aug 2011 15:18:12 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610N8bE032569; - Thu, 30 Jun 2011 20:23:09 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIAjF028676; + Sun, 7 Aug 2011 15:18:10 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:16 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:14 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:34 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:31 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 06/19] wait_task_inactive: treat task->state and +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 06/22] wait_task_inactive: treat task->state and match_state as bitmasks -Message-ID: <20110701002114.GA25804@redhat.com> +Message-ID: <20110807191531.GA14393@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 1558 -Lines: 39 +Content-Length: 1557 +Lines: 38 Change wait_task_inactive() to check "state & match_state" instead of "state == match_state". This should not make any difference, but this @@ -4694,8 +4695,7 @@ index 3f2e502..ade7997 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:09 2011 +From davej Sun Aug 7 15:19:15 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -4704,40 +4704,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:09 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:19 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:15 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:15 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A6BD4D810F; - Thu, 30 Jun 2011 20:23:19 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 2ovLSk6W1SGg; Thu, 30 Jun 2011 20:23:19 -0400 (EDT) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8DBABD812A; - Thu, 30 Jun 2011 20:23:19 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1FD1B1322A2; + Sun, 7 Aug 2011 15:18:15 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id gfct30463vGS; Sun, 7 Aug 2011 15:18:15 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 01C04128FDA; + Sun, 7 Aug 2011 15:18:15 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610NCUq026299; - Thu, 30 Jun 2011 20:23:12 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JICKL027777; + Sun, 7 Aug 2011 15:18:13 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:19 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:17 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:36 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:34 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 07/19] introduce TASK_UTRACED state -Message-ID: <20110701002117.GA25807@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 07/22] introduce TASK_UTRACED state +Message-ID: <20110807191534.GA14396@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 2913 -Lines: 84 +Content-Length: 2912 +Lines: 83 Introduce TASK_UTRACED state, will be used by utrace instead of TASK_TRACED. @@ -4823,8 +4824,7 @@ index b87de83..7a0008c 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:10 2011 +From davej Sun Aug 7 15:19:17 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -4833,40 +4833,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:10 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:23 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:17 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:17 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1A66AD812A; - Thu, 30 Jun 2011 20:23:23 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id fctUcQ+-lYpk; Thu, 30 Jun 2011 20:23:23 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F2D35D810F; - Thu, 30 Jun 2011 20:23:22 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B634FA5D5A; + Sun, 7 Aug 2011 15:18:17 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 3vEyYZtZ8hD5; Sun, 7 Aug 2011 15:18:17 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9921A9C7FA; + Sun, 7 Aug 2011 15:18:17 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NF1u015200; - Thu, 30 Jun 2011 20:23:15 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIFH8028686; + Sun, 7 Aug 2011 15:18:16 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:23 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:20 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:39 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:37 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 08/19] utrace: use TASK_UTRACED instead of TASK_TRACED -Message-ID: <20110701002120.GA25814@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 08/22] utrace: use TASK_UTRACED instead of TASK_TRACED +Message-ID: <20110807191537.GA14403@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 4316 -Lines: 130 +Content-Length: 4315 +Lines: 129 Change utrace.c to use TASK_UTRACED instead of TASK_TRACED. @@ -4998,8 +4999,7 @@ index d7c547c..be98607 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:12 2011 +From davej Sun Aug 7 15:19:19 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5008,41 +5008,42 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:12 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:26 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:19 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:24 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 289969C0C5; - Thu, 30 Jun 2011 20:23:26 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id q99JSaVz2X1O; Thu, 30 Jun 2011 20:23:26 -0400 (EDT) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 143F89C0C3; - Thu, 30 Jun 2011 20:23:26 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 53AC0D89A9; + Sun, 7 Aug 2011 15:18:20 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id CGhyA84rXAKN; Sun, 7 Aug 2011 15:18:20 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 36B2CD8988; + Sun, 7 Aug 2011 15:18:20 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610NI9T021133; - Thu, 30 Jun 2011 20:23:19 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIIFB028696; + Sun, 7 Aug 2011 15:18:18 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:26 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:24 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:41 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:39 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 09/19] tracehooks: kill tracehook_finish_jctl(), add +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 09/22] tracehooks: kill tracehook_finish_jctl(), add tracehook_finish_stop() -Message-ID: <20110701002124.GA25817@redhat.com> +Message-ID: <20110807191539.GA14406@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 2782 -Lines: 86 +Content-Length: 2781 +Lines: 85 tracehook_finish_jctl() is needed to avoid the races with SIGKILL which wakes up UTRACED task, and thus it should be called every time @@ -5130,8 +5131,7 @@ index be98607..daa96b9 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:13 2011 +From davej Sun Aug 7 15:19:18 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5140,40 +5140,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:13 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:29 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:18 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:22 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A748FD813B; - Thu, 30 Jun 2011 20:23:29 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id EwbxGxAU7ASi; Thu, 30 Jun 2011 20:23:29 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 72761D810F; - Thu, 30 Jun 2011 20:23:29 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id DD6839C7FA; + Sun, 7 Aug 2011 15:18:22 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id hZs6VyadcD7K; Sun, 7 Aug 2011 15:18:22 -0400 (EDT) +Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C7B129C7DE; + Sun, 7 Aug 2011 15:18:22 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NMAW015213; - Thu, 30 Jun 2011 20:23:22 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIKMe020605; + Sun, 7 Aug 2011 15:18:21 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:29 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:27 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:44 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:42 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 10/19] teach wake_up_quiescent() to do "selective" wake_up -Message-ID: <20110701002127.GA25824@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 10/22] teach wake_up_quiescent() to do "selective" wake_up +Message-ID: <20110807191542.GA14409@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO -Content-Length: 1335 -Lines: 46 +Content-Length: 1334 +Lines: 45 Both utrace and ptrace can want the same thread to be quiescent, in this case its state is TASK_TRACED | TASK_UTRACED. And this also means that @@ -5221,8 +5222,7 @@ index a7979ad..57552e6 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:14 2011 +From davej Sun Aug 7 15:19:20 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5231,41 +5231,42 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:14 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:32 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:20 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:25 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C94CF9C0C5; - Thu, 30 Jun 2011 20:23:32 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 9R-z4gQXQITf; Thu, 30 Jun 2011 20:23:32 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7C2991322AA; + Sun, 7 Aug 2011 15:18:25 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id rHOxOwY4bOdr; Sun, 7 Aug 2011 15:18:25 -0400 (EDT) Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B55759C0C3; - Thu, 30 Jun 2011 20:23:32 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 67ABD128FDA; + Sun, 7 Aug 2011 15:18:25 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610NPe5021144; - Thu, 30 Jun 2011 20:23:25 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JINVP029911; + Sun, 7 Aug 2011 15:18:23 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:33 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:30 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:47 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:45 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 11/19] ptrace_stop: do not assume the task is running after +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 11/22] ptrace_stop: do not assume the task is running after wake_up_quiescent() -Message-ID: <20110701002130.GA25827@redhat.com> +Message-ID: <20110807191545.GA14416@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO -Content-Length: 962 -Lines: 31 +Content-Length: 961 +Lines: 30 If ptrace_stop() sets TASK_TRACED and then detects we should not stop, it can race with utrace_do_stop() which can see TASK_TRACED and add @@ -5298,8 +5299,7 @@ index 57552e6..89e691d 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:17 2011 +From davej Sun Aug 7 15:19:21 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5308,41 +5308,42 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:17 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:21 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:36 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:28 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4390F1287F3; - Thu, 30 Jun 2011 20:23:36 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1B4B91322AE; + Sun, 7 Aug 2011 15:18:28 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id v5mzxCjpefBI; Thu, 30 Jun 2011 20:23:36 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 283B21287DD; - Thu, 30 Jun 2011 20:23:36 -0400 (EDT) + with ESMTP id q5tv0cJeZqLD; Sun, 7 Aug 2011 15:18:28 -0400 (EDT) +Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 071461322A9; + Sun, 7 Aug 2011 15:18:28 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NSc9032626; - Thu, 30 Jun 2011 20:23:29 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIPFB020635; + Sun, 7 Aug 2011 15:18:26 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:36 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:34 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:49 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:47 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 12/19] get_signal_to_deliver: restructure utrace/ptrace +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 12/22] get_signal_to_deliver: restructure utrace/ptrace signal reporting -Message-ID: <20110701002134.GA25834@redhat.com> +Message-ID: <20110807191547.GA14419@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO -Content-Length: 2012 -Lines: 73 +Content-Length: 2011 +Lines: 72 get_signal_to_deliver() assumes that either tracehook_get_signal() does nothing (without CONFIG_UTRACE), or it also reports the signal to ptrace @@ -5417,8 +5418,7 @@ index 89e691d..d0e0c67 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:18 2011 +From davej Sun Aug 7 15:19:22 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5427,40 +5427,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:18 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:39 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:22 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:30 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 74BDFD813B; - Thu, 30 Jun 2011 20:23:39 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id tAGkG+GCPdeN; Thu, 30 Jun 2011 20:23:39 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5B728D812A; - Thu, 30 Jun 2011 20:23:39 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BFD8F1322A2; + Sun, 7 Aug 2011 15:18:30 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id JczS8HsLYY6X; Sun, 7 Aug 2011 15:18:30 -0400 (EDT) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A8F91128FDA; + Sun, 7 Aug 2011 15:18:30 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NWY1032629; - Thu, 30 Jun 2011 20:23:32 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIS1m029940; + Sun, 7 Aug 2011 15:18:29 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:39 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:37 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:52 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:50 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 13/19] introduce ptrace_set_syscall_trace() -Message-ID: <20110701002137.GA25837@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 13/22] introduce ptrace_set_syscall_trace() +Message-ID: <20110807191550.GA14426@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO -Content-Length: 1581 -Lines: 52 +Content-Length: 1580 +Lines: 51 No functional changes. Add the new helper, ptrace_set_syscall_trace(), which should be used to set/clear TIF_SYSCALL_TRACE in ptrace code. @@ -5514,8 +5515,7 @@ index 0b2aba5..b6fd922 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:20 2011 +From davej Sun Aug 7 15:19:23 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5524,40 +5524,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:20 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:23 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:42 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:33 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id CFC3F9C0C5; - Thu, 30 Jun 2011 20:23:42 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 585699C7DE; + Sun, 7 Aug 2011 15:18:33 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id vS4KlM5ek+bt; Thu, 30 Jun 2011 20:23:42 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B28CA9C0C3; - Thu, 30 Jun 2011 20:23:42 -0400 (EDT) + with ESMTP id Zp+5oAzhYq2W; Sun, 7 Aug 2011 15:18:33 -0400 (EDT) +Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 44532909E4; + Sun, 7 Aug 2011 15:18:33 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NZvo015255; - Thu, 30 Jun 2011 20:23:35 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIV6n020657; + Sun, 7 Aug 2011 15:18:31 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:43 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:40 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:54 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:52 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 14/19] introduce PT_SYSCALL_TRACE flag -Message-ID: <20110701002140.GA25844@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 14/22] introduce PT_SYSCALL_TRACE flag +Message-ID: <20110807191552.GA14429@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO -Content-Length: 2236 -Lines: 73 +Content-Length: 2235 +Lines: 72 Currently tracehooks assume that if the ptraced task has TIF_SYSCALL_TRACE set, the tracee should report the syscall. @@ -5632,8 +5633,7 @@ index b6fd922..0825a01 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:21 2011 +From davej Sun Aug 7 15:19:24 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5642,41 +5642,42 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:21 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:24 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:46 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:35 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 35A70D812A; - Thu, 30 Jun 2011 20:23:46 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F0377D89A9; + Sun, 7 Aug 2011 15:18:35 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id L06hkGLA8FQs; Thu, 30 Jun 2011 20:23:46 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 21C2BD810F; - Thu, 30 Jun 2011 20:23:46 -0400 (EDT) + with ESMTP id cBLqfABIHZ6h; Sun, 7 Aug 2011 15:18:35 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id DC799D8988; + Sun, 7 Aug 2011 15:18:35 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610Nc7k007721; - Thu, 30 Jun 2011 20:23:39 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIXU3007727; + Sun, 7 Aug 2011 15:18:34 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:46 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:44 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:15:57 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:55 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 15/19] utrace: don't clear TIF_SYSCALL_TRACE if it is +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 15/22] utrace: don't clear TIF_SYSCALL_TRACE if it is needed by ptrace -Message-ID: <20110701002144.GA25847@redhat.com> +Message-ID: <20110807191555.GA14436@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO -Content-Length: 797 -Lines: 24 +Content-Length: 796 +Lines: 23 TIF_SYSCALL_TRACE should be cleared only if both ptrace and utrace do not want it, change utrace_reset() to check PT_SYSCALL_TRACE before @@ -5702,8 +5703,7 @@ index daa96b9..a824ac3 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:22 2011 +From davej Sun Aug 7 15:19:25 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5712,40 +5712,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:22 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:25 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:49 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:38 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 72E0C9C0C3; - Thu, 30 Jun 2011 20:23:49 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A6B3C9C7DE; + Sun, 7 Aug 2011 15:18:38 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id o3ezwgloxuCS; Thu, 30 Jun 2011 20:23:49 -0400 (EDT) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5DD6A9C0C5; - Thu, 30 Jun 2011 20:23:49 -0400 (EDT) + with ESMTP id ln+MaW5alQl7; Sun, 7 Aug 2011 15:18:38 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8A6D2909E4; + Sun, 7 Aug 2011 15:18:38 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610NglX026379; - Thu, 30 Jun 2011 20:23:42 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIaYf007737; + Sun, 7 Aug 2011 15:18:36 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:49 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:47 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:16:00 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:15:58 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 16/19] introduce task_utrace_lock/task_utrace_unlock -Message-ID: <20110701002147.GA25854@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 16/22] introduce task_utrace_lock/task_utrace_unlock +Message-ID: <20110807191558.GA14440@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO -Content-Length: 2190 -Lines: 81 +Content-Length: 2189 +Lines: 80 - Add task_utrace_lock(task). It simply takes task->utrace->lock if this task was ever utraced. Otherwise it takes task_lock(), this @@ -5828,8 +5829,7 @@ index a824ac3..508c13c 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:24 2011 +From davej Sun Aug 7 15:19:27 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5838,41 +5838,42 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:24 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:52 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:27 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:41 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id DB8D8D812A; - Thu, 30 Jun 2011 20:23:52 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 74TDLZXBCl6s; Thu, 30 Jun 2011 20:23:52 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C6776D810F; - Thu, 30 Jun 2011 20:23:52 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 41B111322A2; + Sun, 7 Aug 2011 15:18:41 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id ypKNrfgt9t+i; Sun, 7 Aug 2011 15:18:41 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2D805128FDA; + Sun, 7 Aug 2011 15:18:41 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NjAl015271; - Thu, 30 Jun 2011 20:23:45 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIdnm028810; + Sun, 7 Aug 2011 15:18:39 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:53 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:50 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:16:02 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:16:00 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 17/19] teach ptrace_set_syscall_trace() to play well with +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 17/22] teach ptrace_set_syscall_trace() to play well with utrace -Message-ID: <20110701002150.GA25861@redhat.com> +Message-ID: <20110807191600.GA14443@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 1513 -Lines: 49 +Content-Length: 1512 +Lines: 48 1. ptrace_set_syscall_trace(true)->set_tsk_thread_flag(TIF_SYSCALL_TRACE) can race with utrace_control()->utrace_reset() path which can miss @@ -5923,8 +5924,7 @@ index 0825a01..209ea2d 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:24 2011 +From davej Sun Aug 7 15:19:27 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -5933,40 +5933,41 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:24 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:56 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:27 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:43 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6CD231287F3; - Thu, 30 Jun 2011 20:23:56 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id XX9YNcTcP1Ny; Thu, 30 Jun 2011 20:23:56 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 504BF1287DD; - Thu, 30 Jun 2011 20:23:56 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E37B59C7DE; + Sun, 7 Aug 2011 15:18:43 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id NRVgSzxr7avy; Sun, 7 Aug 2011 15:18:43 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C6D6E909E4; + Sun, 7 Aug 2011 15:18:43 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p610NmjB032686; - Thu, 30 Jun 2011 20:23:49 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIfAM007754; + Sun, 7 Aug 2011 15:18:42 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:56 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:54 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:16:05 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:16:03 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 18/19] introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK -Message-ID: <20110701002154.GA25864@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 18/22] introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK +Message-ID: <20110807191603.GA14450@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO -Content-Length: 3725 -Lines: 108 +Content-Length: 3724 +Lines: 107 Add the new internal ptrace flags, PT_SINGLE_STEP and PT_SINGLE_BLOCK. @@ -6076,8 +6077,7 @@ index 209ea2d..44908d0 100644 -- 1.5.5.1 - -From davej Thu Jun 30 20:27:26 2011 +From davej Sun Aug 7 15:19:29 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -6086,58 +6086,92 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 30 Jun 2011 20:27:26 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Thu, 30 Jun 2011 20:23:59 -0400 (EDT) + for (single-drop); Sun, 07 Aug 2011 15:19:29 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:46 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8FF6B9C0C5; - Thu, 30 Jun 2011 20:23:59 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id pNFtYrppMjXf; Thu, 30 Jun 2011 20:23:59 -0400 (EDT) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7C2B89C0C3; - Thu, 30 Jun 2011 20:23:59 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 810E31322A2; + Sun, 7 Aug 2011 15:18:46 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id ptiIThWTq2a6; Sun, 7 Aug 2011 15:18:46 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6B665128FDA; + Sun, 7 Aug 2011 15:18:46 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p610Nqpd026408; - Thu, 30 Jun 2011 20:23:52 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIiI8007757; + Sun, 7 Aug 2011 15:18:44 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Fri, 1 Jul 2011 02:21:59 +0200 (CEST) -Date: Fri, 1 Jul 2011 02:21:57 +0200 + oleg@redhat.com; Sun, 7 Aug 2011 21:16:08 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:16:06 +0200 From: Oleg Nesterov To: "Frank Ch. Eigler" , Kyle McMartin , Dave Jones , Josh Stone , Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 19/19] utrace: consult PT_SINGLE_STEP/PT_SINGLE_BLOCK - before user_disable_single_step() -Message-ID: <20110701002157.GA25871@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 19/22] utrace: finish_resume_report: don't do + user_xxx_step() if ptrace_wants_step() +Message-ID: <20110807191606.GA14453@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO -Content-Length: 1150 -Lines: 41 +Content-Length: 2740 +Lines: 83 -- do not do user_enable_block_step() if PT_SINGLE_STEP is set, in this - case ptrace has already called user_enable_single_step() +finish_resume_report() should not enable/disable the stepping if +ptrace_wants_step() == T. If ptrace wants block_step while utrace +wants single_step we could "promote" the stepping, but I do not +think this really makes sense. -- do not do user_disable_single_step() if PT_*_STEP is set, ptrace needs - the stepping - -Unless the tracee is killed this can't race with ptrace, this is called -by the tracee itself. +Unless the tracee is killed this can't race with ptrace, this is +called by the tracee itself. If it is killed we do not care. Signed-off-by: Oleg Nesterov --- - kernel/utrace.c | 6 ++++-- - 1 files changed, 4 insertions(+), 2 deletions(-) + include/linux/tracehook.h | 8 ++++---- + kernel/utrace.c | 9 ++++++--- + 2 files changed, 10 insertions(+), 7 deletions(-) +diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h +index 06edb52..5612d2d 100644 +--- a/include/linux/tracehook.h ++++ b/include/linux/tracehook.h +@@ -121,8 +121,8 @@ static inline __must_check int tracehook_report_syscall_entry( + return 0; + } + +-#define ptrace_wants_step() \ +- (current->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK)) ++#define ptrace_wants_step(task) \ ++ ((task)->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK)) + + /** + * tracehook_report_syscall_exit - task has just finished a system call +@@ -146,7 +146,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) + if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) + utrace_report_syscall_exit(regs); + +- if (step && ptrace_wants_step()) { ++ if (step && ptrace_wants_step(current)) { + siginfo_t info; + user_single_step_siginfo(current, regs, &info); + force_sig_info(SIGTRAP, &info, current); +@@ -439,7 +439,7 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, + { + if (task_utrace_flags(current)) + utrace_signal_handler(current, stepping); +- if (stepping && ptrace_wants_step()) ++ if (stepping && ptrace_wants_step(current)) + ptrace_notify(SIGTRAP); + } + diff --git a/kernel/utrace.c b/kernel/utrace.c -index 508c13c..d6607cb 100644 +index 508c13c..fbabb81 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -1828,7 +1828,8 @@ static void finish_resume_report(struct task_struct *task, @@ -6145,17 +6179,27 @@ index 508c13c..d6607cb 100644 case UTRACE_BLOCKSTEP: if (likely(arch_has_block_step())) { - user_enable_block_step(task); -+ if (!(current->ptrace & PT_SINGLE_STEP)) ++ if (!ptrace_wants_step(task)) + user_enable_block_step(task); break; } -@@ -1856,7 +1857,8 @@ static void finish_resume_report(struct task_struct *task, +@@ -1841,7 +1842,8 @@ static void finish_resume_report(struct task_struct *task, + + case UTRACE_SINGLESTEP: + if (likely(arch_has_single_step())) { +- user_enable_single_step(task); ++ if (!ptrace_wants_step(task)) ++ user_enable_single_step(task); + } else { + /* + * This means some callback is to blame for failing +@@ -1856,7 +1858,8 @@ static void finish_resume_report(struct task_struct *task, case UTRACE_REPORT: case UTRACE_RESUME: default: - user_disable_single_step(task); -+ if (!(current->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK))) ++ if (!ptrace_wants_step(task)) + user_disable_single_step(task); break; } @@ -6163,4 +6207,267 @@ index 508c13c..d6607cb 100644 -- 1.5.5.1 +From davej Sun Aug 7 15:19:30 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Sun, 07 Aug 2011 15:19:30 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:49 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1C4A79C7DE; + Sun, 7 Aug 2011 15:18:49 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id GxHOzMqYQY8N; Sun, 7 Aug 2011 15:18:49 -0400 (EDT) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 066D2909E4; + Sun, 7 Aug 2011 15:18:49 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIkkD030034; + Sun, 7 Aug 2011 15:18:47 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Sun, 7 Aug 2011 21:16:10 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:16:08 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 20/22] ptrace: shift user_*_step() from ptrace_resume() to + ptrace_stop() +Message-ID: <20110807191608.GA14460@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +Status: RO +Content-Length: 2384 +Lines: 70 + +1. ptrace_resume() plays with the stopped task which can be also + task_is_utraced(). In this case user_enable_xxx_step() can race + with utrace_reset()->user_disable_single_step(). + + We could change utrace_reset() to check ptrace_wants_step() and + add the task_utrace_lock + unlock barrier after ptrace_resume() + sets PT_SINGLE_STEP. + + But it is better to reassign enable/desable from the tracer to + the tracee, it can check its PT_SINGLE_ bits after wakeup. This + also makes sense because enable_step(task) can be faster if + task == current. + +2. ptrace can do user_disable_single_step() while utrace needs the + stepping. + + Set TIF_NOTIFY_RESUME after user_disable_single_step() to ensure + the tracee can't return to the user-space without utrace_resume(). + Any correct engine which wants the stepping should reassert it. + +Signed-off-by: Oleg Nesterov +--- + kernel/ptrace.c | 4 ---- + kernel/signal.c | 12 ++++++++++++ + 2 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index 44908d0..d37b30d 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -580,14 +580,10 @@ static int ptrace_resume(struct task_struct *child, long request, + if (unlikely(!arch_has_block_step())) + return -EIO; + child->ptrace |= PT_SINGLE_BLOCK; +- user_enable_block_step(child); + } else if (is_singlestep(request) || is_sysemu_singlestep(request)) { + if (unlikely(!arch_has_single_step())) + return -EIO; + child->ptrace |= PT_SINGLE_STEP; +- user_enable_single_step(child); +- } else { +- user_disable_single_step(child); + } + + child->exit_code = data; +diff --git a/kernel/signal.c b/kernel/signal.c +index d0e0c67..bc40bd7 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -1840,6 +1840,18 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) + } + + tracehook_finish_stop(); ++ ++ if (current->ptrace & PT_SINGLE_BLOCK) ++ user_enable_block_step(current); ++ else if (current->ptrace & PT_SINGLE_STEP) ++ user_enable_single_step(current); ++ else { ++ user_disable_single_step(current); ++ /* if utrace needs the stepping it should reassert */ ++ if (task_utrace_flags(current)) ++ set_thread_flag(TIF_NOTIFY_RESUME); ++ } ++ + /* + * While in TASK_TRACED, we were considered "frozen enough". + * Now that we woke up, it's crucial if we're supposed to be +-- +1.5.5.1 + +From davej Sun Aug 7 15:19:31 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Sun, 07 Aug 2011 15:19:31 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:51 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id AD8D0D89A9; + Sun, 7 Aug 2011 15:18:51 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id LHAT6DyOymTI; Sun, 7 Aug 2011 15:18:51 -0400 (EDT) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 99798D8988; + Sun, 7 Aug 2011 15:18:51 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIn3U030041; + Sun, 7 Aug 2011 15:18:50 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Sun, 7 Aug 2011 21:16:13 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:16:11 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 21/22] ptrace_disable: no need to disable stepping +Message-ID: <20110807191611.GA14463@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +Status: RO +Content-Length: 944 +Lines: 28 + +ptrace_disable() is called when the tracee is quiescent and we +are going to untrace. This means we are going to clear ->ptrace +and wake up the tracee. Now that ptrace_stop() checks PT_ bits +and does user_disable_single_step() we can remove this code from +ptrace_disable(), it is unneeded and not utrace-friendly. + +TODO: change !x86 code. + +Signed-off-by: Oleg Nesterov +--- + arch/x86/kernel/ptrace.c | 2 -- + 1 files changed, 0 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c +index 7ab475f..f1cdc7d 100644 +--- a/arch/x86/kernel/ptrace.c ++++ b/arch/x86/kernel/ptrace.c +@@ -807,8 +807,6 @@ static int ioperm_get(struct task_struct *target, + */ + void ptrace_disable(struct task_struct *child) + { +- child->ptrace &= ~(PT_SINGLE_STEP | PT_SINGLE_BLOCK); +- user_disable_single_step(child); + #ifdef TIF_SYSCALL_EMU + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); + #endif +-- +1.5.5.1 + +From davej Sun Aug 7 15:19:32 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Sun, 07 Aug 2011 15:19:32 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:54 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 57405D89A9; + Sun, 7 Aug 2011 15:18:54 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id XgEdPuPz9LNX; Sun, 7 Aug 2011 15:18:54 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 42E6BD8988; + Sun, 7 Aug 2011 15:18:54 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIqEO027919; + Sun, 7 Aug 2011 15:18:52 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Sun, 7 Aug 2011 21:16:15 +0200 (CEST) +Date: Sun, 7 Aug 2011 21:16:13 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 22/22] ptrace_report_syscall: check TIF_SYSCALL_EMU +Message-ID: <20110807191613.GA14470@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +Status: RO +Content-Length: 862 +Lines: 27 + +4d16a64 "introduce PT_SYSCALL_TRACE flag" breaks PTRACE_SYSEMU +which doesn't set PT_SYSCALL_TRACE. + +Change ptrace_report_syscall() to check TIF_SYSCALL_EMU as well. +This can't conflict with utrace, this flag can only be set by +ptrace. + +Signed-off-by: Oleg Nesterov +--- + include/linux/tracehook.h | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h +index 5612d2d..ac833de 100644 +--- a/include/linux/tracehook.h ++++ b/include/linux/tracehook.h +@@ -76,7 +76,7 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) + { + int ptrace = task_ptrace(current); + +- if (!(ptrace & PT_SYSCALL_TRACE)) ++ if (!(ptrace & PT_SYSCALL_TRACE) && !test_thread_flag(TIF_SYSCALL_EMU)) + return; + + ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); +-- +1.5.5.1 From a39077043a549868be9a3c592020973b0d8bc789 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 9 Aug 2011 13:32:21 -0400 Subject: [PATCH 018/487] Enable CONFIG_SAMSUNG_LAPTOP (rhbz 729363) --- config-x86-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-x86-generic b/config-x86-generic index bd2f93b70..231db7a40 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -501,7 +501,7 @@ CONFIG_X86_DECODER_SELFTEST=y CONFIG_ACPI_CMPC=m CONFIG_MSI_WMI=m CONFIG_TOSHIBA_BT_RFKILL=m -# CONFIG_SAMSUNG_LAPTOP is not set +CONFIG_SAMSUNG_LAPTOP=m CONFIG_VGA_SWITCHEROO=y CONFIG_LPC_SCH=m diff --git a/kernel.spec b/kernel.spec index 843f9f55f..96440ce8e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1899,6 +1899,9 @@ fi # and build. %changelog +* Tue Aug 09 2011 Dave Jones +- Enable CONFIG_SAMSUNG_LAPTOP (rhbz 729363) + * Mon Aug 08 2011 Josh Boyer - Bring in utrace fixes davej applied to f15. (rhbz 728379) From 14afc06f788037957c8dca6b3ca2fa0cb7d8ff34 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 9 Aug 2011 14:10:15 -0400 Subject: [PATCH 019/487] ptrace_report_syscall: check if TIF_SYSCALL_EMU is defined --- kernel.spec | 3 ++ utrace.patch | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/kernel.spec b/kernel.spec index 96440ce8e..ff6bc89d1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1899,6 +1899,9 @@ fi # and build. %changelog +* Tue Aug 09 2011 Dave Jones +- ptrace_report_syscall: check if TIF_SYSCALL_EMU is defined + * Tue Aug 09 2011 Dave Jones - Enable CONFIG_SAMSUNG_LAPTOP (rhbz 729363) diff --git a/utrace.patch b/utrace.patch index f5515e3ed..f70d0b1fb 100644 --- a/utrace.patch +++ b/utrace.patch @@ -6471,3 +6471,82 @@ index 5612d2d..ac833de 100644 -- 1.5.5.1 +From davej Tue Aug 9 13:34:35 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.51] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Tue, 09 Aug 2011 13:34:35 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Tue, 9 Aug 2011 13:33:16 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 16B6E9EBAD; + Tue, 9 Aug 2011 13:33:16 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id T2mXXk1FjIIy; Tue, 9 Aug 2011 13:33:16 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 025259EBA5; + Tue, 9 Aug 2011 13:33:16 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p79HXDVF004054; + Tue, 9 Aug 2011 13:33:13 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Tue, 9 Aug 2011 19:30:35 +0200 (CEST) +Date: Tue, 9 Aug 2011 19:30:33 +0200 +From: Oleg Nesterov +To: "Frank Ch. Eigler" , Kyle McMartin , + Dave Jones , Josh Stone , + Matthew Garrett , David Smith +Cc: kernel@lists.fedoraproject.org, Tony Breeds +Subject: [PATCH utrace-3.0 23/22] ptrace_report_syscall: check if + TIF_SYSCALL_EMU is defined +Message-ID: <20110809173033.GA26443@redhat.com> +References: <20110701002053.GA25767@redhat.com> <20110807191434.GA13184@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110807191434.GA13184@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Status: RO +Content-Length: 844 +Lines: 31 + +From: Tony Breeds + +TIF_SYSCALL_EMU is x86 only, add ifdef into ptrace_report_syscall(). + +Signed-off-by: Oleg Nesterov +--- + include/linux/tracehook.h | 8 ++++++-- + 1 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h +index ac833de..d5baf86 100644 +--- a/include/linux/tracehook.h ++++ b/include/linux/tracehook.h +@@ -76,8 +76,12 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) + { + int ptrace = task_ptrace(current); + +- if (!(ptrace & PT_SYSCALL_TRACE) && !test_thread_flag(TIF_SYSCALL_EMU)) +- return; ++ if (!(ptrace & PT_SYSCALL_TRACE)) { ++#ifdef TIF_SYSCALL_EMU ++ if (!test_thread_flag(TIF_SYSCALL_EMU)) ++#endif ++ return; ++ } + + ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); + +-- +1.5.5.1 + + From a9bf2facb11e02a25bb244278e92de015704fc30 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 9 Aug 2011 16:32:30 -0400 Subject: [PATCH 020/487] Sync with f15 for rhbz 728872 --- block-stray-block-put-after-teardown.patch | 11 +++++++++++ kernel.spec | 8 +++++++- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 block-stray-block-put-after-teardown.patch diff --git a/block-stray-block-put-after-teardown.patch b/block-stray-block-put-after-teardown.patch new file mode 100644 index 000000000..f4bf9c40c --- /dev/null +++ b/block-stray-block-put-after-teardown.patch @@ -0,0 +1,11 @@ +--- linux-2.6.39.noarch/block/elevator.c~ 2011-08-09 10:07:41.532774872 -0400 ++++ linux-2.6.39.noarch/block/elevator.c 2011-08-09 10:07:56.131724173 -0400 +@@ -815,7 +815,7 @@ void elv_completed_request(struct reques + */ + if (blk_account_rq(rq)) { + q->in_flight[rq_is_sync(rq)]--; +- if ((rq->cmd_flags & REQ_SORTED) && ++ if ((rq->cmd_flags & REQ_SORTED) && e->ops && + e->ops->elevator_completed_req_fn) + e->ops->elevator_completed_req_fn(q, rq); + } diff --git a/kernel.spec b/kernel.spec index ff6bc89d1..abac0be7a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -686,6 +686,7 @@ Patch12021: udlfb-bind-framebuffer-to-interface.patch Patch12022: fix-cdc-ncm-dma-stack-vars.patch Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch +Patch12024: block-stray-block-put-after-teardown.patch # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch @@ -698,6 +699,7 @@ Patch13001: epoll-fix-spurious-lockdep-warnings.patch Patch13002: hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch + Patch20000: utrace.patch %endif @@ -1268,6 +1270,7 @@ ApplyPatch add-appleir-usb-driver.patch ApplyPatch udlfb-bind-framebuffer-to-interface.patch ApplyPatch fix-cdc-ncm-dma-stack-vars.patch ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch +ApplyPatch block-stray-block-put-after-teardown.patch # Runtime PM #ApplyPatch linux-2.6-usb-pci-autosuspend.patch @@ -1899,6 +1902,9 @@ fi # and build. %changelog +* Tue Aug 09 2011 Josh Boyer +- Add patch davej applied to f15 for rhbz 728872 + * Tue Aug 09 2011 Dave Jones - ptrace_report_syscall: check if TIF_SYSCALL_EMU is defined From 268afcecae577a86b7638315a182f36bd7ea3868 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 9 Aug 2011 16:48:18 -0400 Subject: [PATCH 021/487] enable for 64bit too --- config-x86_64-generic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-x86_64-generic b/config-x86_64-generic index f4c3c30cf..fd1e9c39f 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -409,7 +409,7 @@ CONFIG_FUNCTION_GRAPH_TRACER=y CONFIG_ACPI_CMPC=m CONFIG_MSI_WMI=m CONFIG_TOSHIBA_BT_RFKILL=m -# CONFIG_SAMSUNG_LAPTOP is not set +CONFIG_SAMSUNG_LAPTOP=m CONFIG_CS5535_MFGPT=m CONFIG_GEODE_WDT=m From ed165f2540ea58a17537c809d8b32958f704137a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 1 Jul 2011 15:33:00 -0500 Subject: [PATCH 022/487] From: David Marlin Modify to split the ARM config files to work more like other archs. Rename: config-arm -> config-arm-generic Add: config-arm-omap-generic --- Makefile.config | 14 +- config-arm => config-arm-generic | 2 + config-arm-omap-generic | 1090 ++++++++++++++++++++++++++++++ kernel.spec | 9 +- 4 files changed, 1111 insertions(+), 4 deletions(-) rename config-arm => config-arm-generic (98%) create mode 100644 config-arm-omap-generic diff --git a/Makefile.config b/Makefile.config index 53812fa9b..35060e32f 100644 --- a/Makefile.config +++ b/Makefile.config @@ -8,7 +8,8 @@ CONFIGFILES = \ $(CFG)-i686.config $(CFG)-i686-debug.config \ $(CFG)-i686-PAE.config $(CFG)-i686-PAEdebug.config \ $(CFG)-x86_64.config $(CFG)-x86_64-debug.config \ - $(CFG)-s390x.config $(CFG)-arm.config \ + $(CFG)-s390x.config \ + $(CFG)-arm.config $(CFG)-armv7l-omap.config \ $(CFG)-ppc.config $(CFG)-ppc-smp.config \ $(CFG)-sparc64.config \ $(CFG)-ppc64.config $(CFG)-ppc64-debug.config \ @@ -32,6 +33,12 @@ temp-generic: config-generic temp-debug-generic: config-generic cat config-generic config-debug > temp-debug-generic +temp-arm-generic: config-arm-generic temp-generic + perl merge.pl $^ > $@ + +temp-armv7l-omap-generic: config-arm-omap-generic temp-arm-generic + perl merge.pl $^ > $@ + temp-x86-generic: config-x86-generic temp-generic perl merge.pl $^ > $@ @@ -92,7 +99,10 @@ kernel-$(VERSION)-ppc64-debug.config: config-powerpc64 temp-powerpc-debug-generi kernel-$(VERSION)-s390x.config: config-s390x temp-s390-generic perl merge.pl $^ s390 > $@ -kernel-$(VERSION)-arm.config: config-arm temp-generic +kernel-$(VERSION)-arm.config: /dev/null temp-arm-generic + perl merge.pl $^ arm > $@ + +kernel-$(VERSION)-armv7l-omap.config: /dev/null temp-armv7l-omap-generic perl merge.pl $^ arm > $@ kernel-$(VERSION)-ppc.config: /dev/null temp-powerpc32-generic diff --git a/config-arm b/config-arm-generic similarity index 98% rename from config-arm rename to config-arm-generic index dd6f90ad6..5b79fe23d 100644 --- a/config-arm +++ b/config-arm-generic @@ -146,4 +146,6 @@ CONFIG_USE_OF=y CONFIG_PROC_DEVICETREE=y CONFIG_MTD_PHYSMAP_OF=m CONFIG_SERIAL_OF_PLATFORM=m +# CONFIG_LEDS_GPIO_OF is not set CONFIG_MMC_SDHCI_OF=m + diff --git a/config-arm-omap-generic b/config-arm-omap-generic new file mode 100644 index 000000000..34b5389d6 --- /dev/null +++ b/config-arm-omap-generic @@ -0,0 +1,1090 @@ +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_LOCKBREAK=y +CONFIG_ARCH_HAS_CPUFREQ=y +# CONFIG_SPARSE_IRQ is not set +CONFIG_TREE_PREEMPT_RCU=y +CONFIG_PREEMPT_RCU=y +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_RCU_BOOST is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_BLK_CGROUP is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_STOP_MACHINE=y +# CONFIG_INLINE_SPIN_UNLOCK is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set +# CONFIG_INLINE_READ_UNLOCK is not set +# CONFIG_INLINE_READ_UNLOCK_IRQ is not set +# CONFIG_INLINE_WRITE_UNLOCK is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_OMAP=y +# CONFIG_GPIO_PCA953X is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# TI OMAP Common Features +CONFIG_ARCH_OMAP_OTG=y +# CONFIG_ARCH_OMAP1 is not set +CONFIG_ARCH_OMAP2PLUS=y + +# +# OMAP Feature Selections +# +CONFIG_OMAP_SMARTREFLEX=y +CONFIG_OMAP_SMARTREFLEX_CLASS3=y +CONFIG_OMAP_RESET_CLOCKS=y +CONFIG_OMAP_MUX=y +# CONFIG_OMAP_MUX_DEBUG is not set +CONFIG_OMAP_MUX_WARNINGS=y +CONFIG_OMAP_MCBSP=y +CONFIG_OMAP_MBOX_FWK=m +CONFIG_OMAP_MBOX_KFIFO_SIZE=256 +CONFIG_OMAP_32K_TIMER=y +# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set +CONFIG_OMAP_32K_TIMER_HZ=128 +CONFIG_OMAP_DM_TIMER=y +# CONFIG_OMAP_PM_NONE is not set +CONFIG_OMAP_PM_NOOP=y + +# +# TI OMAP2/3/4 Specific Features +# +CONFIG_ARCH_OMAP2PLUS_TYPICAL=y +# CONFIG_ARCH_OMAP2 is not set +CONFIG_ARCH_OMAP3=y +CONFIG_ARCH_OMAP4=y +CONFIG_SOC_OMAP3430=y +# CONFIG_SOC_OMAPTI816X is not set +CONFIG_OMAP_PACKAGE_CBB=y +CONFIG_OMAP_PACKAGE_CBL=y +CONFIG_OMAP_PACKAGE_CBS=y + +# +# OMAP Board Type +# +CONFIG_MACH_OMAP3_BEAGLE=y +CONFIG_MACH_DEVKIT8000=y +CONFIG_MACH_OMAP_LDP=y +CONFIG_MACH_OMAP3530_LV_SOM=y +CONFIG_MACH_OMAP3_TORPEDO=y +CONFIG_MACH_OVERO=y +CONFIG_MACH_OMAP3EVM=y +CONFIG_MACH_OMAP3517EVM=y +CONFIG_MACH_CRANEBOARD=y +CONFIG_MACH_OMAP3_PANDORA=y +CONFIG_MACH_OMAP3_TOUCHBOOK=y +CONFIG_MACH_OMAP_3430SDP=y +CONFIG_MACH_NOKIA_RM680=y +CONFIG_MACH_NOKIA_RX51=y +CONFIG_MACH_OMAP_ZOOM2=y +CONFIG_MACH_OMAP_ZOOM3=y +CONFIG_MACH_CM_T35=y +CONFIG_MACH_CM_T3517=y +CONFIG_MACH_IGEP0020=y +CONFIG_MACH_IGEP0030=y +CONFIG_MACH_SBC3530=y +CONFIG_MACH_OMAP_3630SDP=y +CONFIG_MACH_OMAP_4430SDP=y +CONFIG_MACH_OMAP4_PANDA=y +CONFIG_MACH_TI8168EVM=y +CONFIG_OMAP3_EMU=y +# CONFIG_OMAP3_SDRC_AC_TIMING is not set +# System MMU +CONFIG_CPU_32v6K=y +CONFIG_CPU_V7=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_ARM_THUMBEE=y +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_CACHE_L2X0=y +CONFIG_CACHE_PL310=y +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_CPU_HAS_PMU=y +CONFIG_ARM_ERRATA_430973=y +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_742230 is not set +# CONFIG_ARM_ERRATA_742231 is not set +CONFIG_PL310_ERRATA_588369=y +CONFIG_ARM_ERRATA_720789=y +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_751472 is not set +# CONFIG_ARM_ERRATA_753970 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_ARM_ERRATA_754327 is not set +CONFIG_ARM_GIC=y +# CONFIG_PCI_SYSCALL is not set +# CONFIG_PCCARD is not set +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_HAVE_ARM_SCU=y +CONFIG_HAVE_ARM_TWD=y +CONFIG_NR_CPUS=2 +CONFIG_HOTPLUG_CPU=y +CONFIG_LOCAL_TIMERS=y +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_HZ=128 +# CONFIG_THUMB2_KERNEL is not set +# CONFIG_OABI_COMPAT is not set +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y +CONFIG_HW_PERF_EVENTS=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +# CONFIG_CC_STACKPROTECTOR is not set +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_AUTO_ZRELADDR is not set +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_VFPv3=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_BINFMT_MISC=m +CONFIG_PM_DEBUG=y +# CONFIG_PM_ADVANCED_DEBUG is not set +# CONFIG_PM_VERBOSE is not set +CONFIG_CAN_PM_TRACE=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_APM_EMULATION is not set +CONFIG_ARCH_HAS_OPP=y +CONFIG_PM_OPP=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set +# CONFIG_ARPD is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +CONFIG_IPV6=y +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_IPV6_SUBTREES is not set +# CONFIG_IPV6_MROUTE is not set +CONFIG_NF_DEFRAG_IPV4=m +# CONFIG_NET_DCCPPROBE is not set +# CONFIG_L2TP_V3 is not set +# CONFIG_DECNET_ROUTER is not set +# CONFIG_NET_SCH_INGRESS is not set +# CONFIG_NET_CLS_U32 is not set +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_ACT_CSUM is not set +# CONFIG_NET_CLS_IND is not set +CONFIG_RPS=y +CONFIG_XPS=y +# CONFIG_CAN_SLCAN is not set +# CONFIG_CAN_DEV is not set +CONFIG_RXKAD=m +CONFIG_FIRMWARE_IN_KERNEL=y +# CONFIG_DEBUG_DEVRES is not set +CONFIG_MTD=y +CONFIG_MTD_TESTS=m +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +CONFIG_SM_FTL=m +CONFIG_MTD_PHYSMAP=m +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_GPIO_ADDR is not set +CONFIG_MTD_PLATRAM=m +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=m +CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_MTD_SST25L is not set +CONFIG_MTD_SLRAM=m +CONFIG_MTD_PHRAM=m +CONFIG_MTD_DOC2000=m +CONFIG_MTD_DOC2001=m +CONFIG_MTD_DOC2001PLUS=m +CONFIG_MTD_DOCPROBE=m +CONFIG_MTD_DOCECC=m +# CONFIG_MTD_DOCPROBE_ADVANCED is not set +CONFIG_MTD_DOCPROBE_ADDRESS=0 +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_OMAP2=y +CONFIG_MTD_NAND_OMAP_PREFETCH=y +CONFIG_MTD_NAND_OMAP_PREFETCH_DMA=y +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_NANDSIM is not set +CONFIG_MTD_NAND_PLATFORM=y +# CONFIG_MTD_ALAUDA is not set +CONFIG_MTD_ONENAND=y +# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set +# CONFIG_MTD_ONENAND_GENERIC is not set +CONFIG_MTD_ONENAND_OMAP2=y +# CONFIG_MTD_ONENAND_OTP is not set +CONFIG_MTD_ONENAND_2X_PROGRAM=y +CONFIG_MTD_ONENAND_SIM=m +CONFIG_MTD_UBI_GLUEBI=m +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV_RAM_SIZE=65536 +CONFIG_MG_DISK=m +CONFIG_MG_DISK_RES=0 +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +CONFIG_HMC6352=m +CONFIG_DS1682=m +CONFIG_TI_DAC7512=m +CONFIG_BMP085=m +CONFIG_C2PORT=m +CONFIG_EEPROM_AT25=m +# CONFIG_IWMC3200TOP_DEBUGFS is not set +# CONFIG_SCSI_PROC_FS is not set +# CONFIG_BLK_DEV_SR_VENDOR is not set +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_SATA_AHCI_PLATFORM is not set +# CONFIG_DM_DEBUG is not set +# CONFIG_DM_RAID is not set +# CONFIG_DM_LOG_USERSPACE is not set +CONFIG_DM_MULTIPATH=y +# CONFIG_TARGET_CORE is not set +# CONFIG_MACVTAP is not set +CONFIG_MII=y +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM63XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_TI_DAVINCI_EMAC is not set +# CONFIG_TI_DAVINCI_MDIO is not set +# CONFIG_TI_DAVINCI_CPDMA is not set +CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y +CONFIG_ENC28J60=m +# CONFIG_ENC28J60_WRITEVERIFY is not set +# CONFIG_ETHOC is not set +CONFIG_SMC911X=y +CONFIG_SMSC911X=y +# CONFIG_DNET is not set +# CONFIG_B44 is not set +CONFIG_KS8851=m +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_ATH9K_HTC is not set +# CONFIG_AR9170_USB is not set +# CONFIG_B43_SDIO is not set +# CONFIG_B43_PHY_N is not set +# CONFIG_HOSTAP is not set +# CONFIG_IWM is not set +CONFIG_LIBERTAS_SPI=m +# CONFIG_LIBERTAS_MESH is not set +CONFIG_P54_SPI=m +# CONFIG_P54_SPI_DEFAULT_EEPROM is not set +# CONFIG_RT2800USB_RT33XX is not set +# CONFIG_RTL8192CE is not set +CONFIG_WL1251_SPI=m +CONFIG_WL12XX_SPI=m +CONFIG_WL12XX_SDIO_TEST=m +# CONFIG_WIMAX_IWMC3200_SDIO is not set +CONFIG_USB_USBNET=y +CONFIG_USB_NET_CDCETHER=y +CONFIG_USB_NET_CDC_NCM=y +CONFIG_USB_NET_RNDIS_HOST=y +# CONFIG_ATM_TCP is not set +# CONFIG_IEEE802154_FAKEHARD is not set +# CONFIG_CAIF_TTY is not set +# CONFIG_CAIF_SPI_SLAVE is not set +CONFIG_PPP_BSDCOMP=m +# CONFIG_PPPOL2TP is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +CONFIG_INPUT_POLLDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_EVBUG=m +# CONFIG_KEYBOARD_QT2160 is not set +CONFIG_KEYBOARD_LKKBD=m +CONFIG_KEYBOARD_GPIO=m +CONFIG_KEYBOARD_TCA6416=m +CONFIG_KEYBOARD_MATRIX=m +CONFIG_KEYBOARD_LM8323=m +CONFIG_KEYBOARD_MCS=m +CONFIG_KEYBOARD_NEWTON=m +CONFIG_KEYBOARD_STOWAWAY=m +CONFIG_KEYBOARD_SUNKBD=m +# CONFIG_KEYBOARD_OMAP4 is not set +CONFIG_KEYBOARD_TWL4030=m +CONFIG_KEYBOARD_XTKBD=m +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_GPIO=m +CONFIG_JOYSTICK_AS5011=m +# CONFIG_TABLET_USB_HANWANG is not set +CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_AD7877=m +CONFIG_TOUCHSCREEN_AD7879=m +CONFIG_TOUCHSCREEN_AD7879_I2C=m +# CONFIG_TOUCHSCREEN_AD7879_SPI is not set +CONFIG_TOUCHSCREEN_CY8CTMG110=m +CONFIG_TOUCHSCREEN_HAMPSHIRE=m +CONFIG_TOUCHSCREEN_QT602240=m +CONFIG_TOUCHSCREEN_TPS6507X=m +# CONFIG_TOUCHSCREEN_TSC2005 is not set +CONFIG_INPUT_AD714X=m +CONFIG_INPUT_AD714X_I2C=m +CONFIG_INPUT_AD714X_SPI=m +# CONFIG_INPUT_APPLEIR is not set +CONFIG_INPUT_TWL4030_PWRBUTTON=y +CONFIG_INPUT_TWL4030_VIBRA=y +CONFIG_INPUT_UINPUT=y +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +CONFIG_INPUT_ADXL34X=m +CONFIG_INPUT_ADXL34X_I2C=m +CONFIG_INPUT_ADXL34X_SPI=m +# CONFIG_INPUT_CMA3000_I2C is not set +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_GAMEPORT_NS558 is not set +# CONFIG_GAMEPORT_L4 is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +CONFIG_SERIAL_8250_DETECT_IRQ=y +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_OMAP=y +CONFIG_SERIAL_OMAP_CONSOLE=y +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_GPIO is not set +CONFIG_I2C_OMAP=y +# CONFIG_I2C_SIMTEC is not set +CONFIG_I2C_TAOS_EVM=m +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y +# SPI Master Controller Drivers +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +CONFIG_SPI_OMAP24XX=y +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set +# SPI Protocol Masters +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# +# CONFIG_GPIO_BASIC_MMIO is not set +# CONFIG_GPIO_IT8761E is not set +# CONFIG_GPIO_PL061 is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +CONFIG_GPIO_TWL4030=y +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_CHARGER_TWL4030 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set +CONFIG_WATCHDOG_NOWAYOUT=y +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_MPCORE_WATCHDOG is not set +CONFIG_OMAP_WATCHDOG=y +# CONFIG_TWL4030_WATCHDOG is not set +CONFIG_SSB=y +# CONFIG_SSB_SDIOHOST is not set +CONFIG_MFD_CORE=y +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS65010 is not set +CONFIG_TWL4030_CORE=y +# CONFIG_TWL4030_MADC is not set +CONFIG_TWL4030_POWER=y +CONFIG_TWL4030_CODEC=y +# CONFIG_TWL6030_PWM is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_EZX_PCAP is not set +CONFIG_MFD_OMAP_USB_HOST=y +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_WL1273_CORE is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_DUMMY is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +CONFIG_REGULATOR_TWL4030=y +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_TPS6524X is not set +CONFIG_MEDIA_SUPPORT=y +CONFIG_RC_CORE=y +CONFIG_LIRC=y +CONFIG_IR_RC5_SZ_DECODER=y +CONFIG_IR_LIRC_CODEC=y +# CONFIG_RC_LOOPBACK is not set +CONFIG_VIDEOBUF_DMA_CONTIG=m +CONFIG_V4L2_MEM2MEM_DEV=m +# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set +# Encoders/decoders and other helper chips +# + +# +CONFIG_VIDEO_IR_I2C=m +CONFIG_VIDEO_CS5345=m +CONFIG_VIDEO_M52790=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_VP27SMPX=m +CONFIG_VIDEO_OV7670=m +CONFIG_VIDEO_SAA717X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m +# +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_SAA6588 is not set +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_MT9V032 is not set +# CONFIG_VIDEO_TCM825X is not set +# CONFIG_VIDEO_SAA7110 is not set +# CONFIG_VIDEO_SAA7191 is not set +# CONFIG_VIDEO_TVP514X is not set +# CONFIG_VIDEO_TVP5150 is not set +CONFIG_VIDEO_TVP7002=m +# CONFIG_VIDEO_VPX3220 is not set +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_ADV7343 is not set +CONFIG_VIDEO_AK881X=m +# CONFIG_VIDEO_VPFE_CAPTURE is not set +CONFIG_VIDEO_OMAP2_VOUT=m +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_VIDEO_AU0828 is not set +# CONFIG_VIDEO_SR030PC30 is not set +# CONFIG_VIDEO_OMAP3 is not set +# CONFIG_SOC_CAMERA is not set +CONFIG_USB_ET61X251=m +CONFIG_USB_SN9C102=m +CONFIG_VIDEO_MEM2MEM_TESTDEV=m +CONFIG_RADIO_TEA5764=m +CONFIG_RADIO_SAA7706H=m +CONFIG_RADIO_TEF6862=m +# CONFIG_TTPCI_EEPROM is not set +# CONFIG_SMS_SDIO_DRV is not set +# CONFIG_DVB_DUMMY_FE is not set +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_PLL=m +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB_DDC is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set +# CONFIG_FB_OMAP_LCD_VGA is not set +CONFIG_OMAP2_VRAM=y +CONFIG_OMAP2_VRFB=y +CONFIG_OMAP2_DSS=y +CONFIG_OMAP2_VRAM_SIZE=12 +CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y +# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set +CONFIG_OMAP2_DSS_DPI=y +# CONFIG_OMAP2_DSS_RFBI is not set +CONFIG_OMAP2_DSS_VENC=y +CONFIG_OMAP4_DSS_HDMI=y +# CONFIG_OMAP2_DSS_SDI is not set +# CONFIG_OMAP2_DSS_DSI is not set +# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set +CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1 +CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET=y +CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y +CONFIG_FB_OMAP2=y +CONFIG_FB_OMAP2_DEBUG_SUPPORT=y +CONFIG_FB_OMAP2_NUM_FBS=3 + +# +# OMAP2/3 Display Device Drivers +# +CONFIG_PANEL_GENERIC_DPI=y +CONFIG_PANEL_SHARP_LS037V7DW01=y +CONFIG_PANEL_NEC_NL8048HL11_01B=y +CONFIG_PANEL_TPO_TD043MTEA1=y +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +# CONFIG_LCD_PLATFORM is not set +# CONFIG_LCD_S6E63M0 is not set +CONFIG_BACKLIGHT_GENERIC=m +CONFIG_DISPLAY_SUPPORT=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_JACK=y +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=m +CONFIG_SND_SEQ_HRTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_RAWMIDI_SEQ=m +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_SOC=y +# CONFIG_SND_SOC_CACHE_LZO is not set +CONFIG_SND_OMAP_SOC=y +CONFIG_SND_OMAP_SOC_MCBSP=y +CONFIG_SND_OMAP_SOC_MCPDM=y +CONFIG_SND_OMAP_SOC_RX51=y +CONFIG_SND_OMAP_SOC_OVERO=y +CONFIG_SND_OMAP_SOC_OMAP3EVM=y +CONFIG_SND_OMAP_SOC_AM3517EVM=y +CONFIG_SND_OMAP_SOC_SDP3430=y +CONFIG_SND_OMAP_SOC_SDP4430=y +CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=y +CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y +CONFIG_SND_OMAP_SOC_ZOOM2=y +CONFIG_SND_OMAP_SOC_IGEP0020=y +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +CONFIG_SND_SOC_TLV320AIC23=y +CONFIG_SND_SOC_TLV320AIC3X=y +CONFIG_SND_SOC_TWL4030=y +CONFIG_SND_SOC_TWL6040=y +# CONFIG_SOUND_PRIME is not set +CONFIG_HID=y +CONFIG_HID_3M_PCT=m +CONFIG_HID_A4TECH=m +# CONFIG_HID_ACRUX is not set +CONFIG_HID_APPLE=m +CONFIG_HID_BELKIN=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_EZKEY=m +CONFIG_HID_KYE=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_LOGITECH=m +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MOSART=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_NTRIG=m +CONFIG_HID_QUANTA=m +CONFIG_HID_STANTUM=m +# CONFIG_HID_TIVO_SLIDE is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set +# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_EHCI_HCD_OMAP=y +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_U132_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_MUSB_TUSB6010 is not set +CONFIG_USB_MUSB_OMAP2PLUS=y +# CONFIG_USB_MUSB_AM35X is not set +# CONFIG_USB_MUSB_HOST is not set +# CONFIG_USB_MUSB_PERIPHERAL is not set +CONFIG_USB_MUSB_OTG=y +CONFIG_USB_GADGET_MUSB_HDRC=y +CONFIG_USB_INVENTRA_DMA=y +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=m +CONFIG_USB_STORAGE_FREECOM=m +CONFIG_USB_STORAGE_ISD200=m +CONFIG_USB_STORAGE_USBAT=m +CONFIG_USB_STORAGE_SDDR09=m +CONFIG_USB_STORAGE_SDDR55=m +CONFIG_USB_STORAGE_JUMPSHOT=m +CONFIG_USB_STORAGE_ALAUDA=m +CONFIG_USB_STORAGE_ONETOUCH=m +CONFIG_USB_STORAGE_KARMA=m +CONFIG_USB_STORAGE_CYPRESS_ATACB=m +# CONFIG_USB_UAS is not set +# CONFIG_USB_LIBUSUAL is not set +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +CONFIG_USB_SERIAL_KEYSPAN_USA28=y +CONFIG_USB_SERIAL_KEYSPAN_USA28X=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y +CONFIG_USB_SERIAL_KEYSPAN_USA19=y +CONFIG_USB_SERIAL_KEYSPAN_USA18X=y +CONFIG_USB_SERIAL_KEYSPAN_USA19W=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y +CONFIG_USB_SERIAL_KEYSPAN_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +# CONFIG_USB_SERIAL_SAFE_PADDED is not set +# CONFIG_USB_SERIAL_SAMBA is not set +CONFIG_USB_SERIAL_ZIO=m +CONFIG_USB_RIO500=m +CONFIG_USB_CYPRESS_CY7C63=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_TEST=m +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_R8A66597 is not set +# CONFIG_USB_GADGET_PXA_U2O is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +CONFIG_USB_ETH=y +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_ETH_EEM=y +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_NOKIA is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set +CONFIG_USB_GPIO_VBUS=y +# CONFIG_ISP1301_OMAP is not set +CONFIG_TWL4030_USB=y +CONFIG_TWL6030_USB=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_OMAP=m +CONFIG_MMC_OMAP_HS=y +CONFIG_MMC_SPI=m +# CONFIG_MMC_DW is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MEMSTICK is not set +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_GPIO_PLATFORM=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_LT3593 is not set +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_GPIO is not set +# CONFIG_NFC_DEVICES is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_TWL4030=m +CONFIG_RTC_DRV_S35390A=m +CONFIG_RTC_DRV_M41T94=m +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1390=m +CONFIG_RTC_DRV_MAX6902=m +CONFIG_RTC_DRV_R9701=m +CONFIG_RTC_DRV_RS5C348=m +CONFIG_RTC_DRV_DS3234=m +CONFIG_RTC_DRV_PCF2123=m +CONFIG_RTC_DRV_CMOS=m +CONFIG_RTC_DRV_M48T86=m +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_USB_SE401 is not set +# CONFIG_USB_VICAM is not set +CONFIG_PRISM2_USB=m +CONFIG_BRCM80211=y +CONFIG_BRCMFMAC=y +CONFIG_RT2870=m +CONFIG_R8712U=m +CONFIG_R8712_AP=y +CONFIG_ZRAM=m +# CONFIG_ZRAM_DEBUG is not set +# CONFIG_LIRC_STAGING is not set +CONFIG_TIDSPBRIDGE=m +CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE=0x600000 +# CONFIG_TIDSPBRIDGE_DEBUG is not set +CONFIG_TIDSPBRIDGE_RECOVERY=y +# CONFIG_TIDSPBRIDGE_CACHE_LINE_CHECK is not set +CONFIG_TIDSPBRIDGE_WDT3=y +CONFIG_TIDSPBRIDGE_WDT_TIMEOUT=5 +# CONFIG_TIDSPBRIDGE_NTFY_PWRERR is not set +# CONFIG_TIDSPBRIDGE_BACKTRACE is not set +# CONFIG_WESTBRIDGE is not set +CONFIG_WESTBRIDGE_HAL_SELECTED=y +CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL=y +# CONFIG_MACH_NO_WESTBRIDGE is not set +# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set +# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_JFS_STATISTICS=y +CONFIG_XFS_RT=y +CONFIG_OCFS2_FS_STATS=y +CONFIG_OCFS2_DEBUG_MASKLOG=y +# CONFIG_BTRFS_FS is not set +CONFIG_PRINT_QUOTA_WARNING=y +CONFIG_QUOTA_TREE=m +CONFIG_QFMT_V1=m +CONFIG_QFMT_V2=m +CONFIG_AUTOFS4_FS=m +CONFIG_ISO9660_FS=m +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_RW is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_LZO=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +# CONFIG_JFFS2_CMODE_PRIORITY is not set +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_JFFS2_CMODE_FAVOURLZO=y +# CONFIG_LOGFS is not set +CONFIG_NFS_FS=m +# CONFIG_NFS_V4_1 is not set +CONFIG_ROOT_NFS=y +CONFIG_NFSD_DEPRECATED=y +CONFIG_LOCKD=y +CONFIG_NFS_ACL_SUPPORT=y +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_FSCACHE is not set +# CONFIG_CIFS_ACL is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_9P_FSCACHE is not set +# CONFIG_9P_FS_POSIX_ACL is not set +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=y +# CONFIG_DLM_DEBUG is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_DEBUG_PREEMPT=y +# CONFIG_BKL is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_RCU_CPU_STALL_VERBOSE=y +# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_RING_BUFFER_BENCHMARK is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_KGDB_TESTS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +CONFIG_EARLY_PRINTK=y +# CONFIG_DEBUG_ICEDCC is not set +CONFIG_OC_ETM=y +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_LSM_MMAP_MIN_ADDR=0 +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0 +# CONFIG_IMA is not set +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_RNG=m +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_SEQIV=m +CONFIG_CRYPTO_CTR=m +# CONFIG_CRYPTO_VMAC is not set +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_USER_API=m +CONFIG_CRYPTO_USER_API_HASH=m +CONFIG_CRYPTO_USER_API_SKCIPHER=m +CONFIG_CRYPTO_DEV_OMAP_SHAM=m +CONFIG_CRYPTO_DEV_OMAP_AES=m +CONFIG_LIBCRC32C=y +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set +# CONFIG_LCD_LD9040 is not set +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_CGROUP_PERF is not set +# CONFIG_OPROFILE is not set +# CONFIG_OPROFILE is not set +# CONFIG_PATA_ARASAN_CF is not set +# CONFIG_BT_ATH3K is not set +# CONFIG_BT_WILINK is not set +# CONFIG_USB_HSO is not set diff --git a/kernel.spec b/kernel.spec index abac0be7a..92a7b6cb8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -382,6 +382,7 @@ Summary: The Linux kernel %ifarch %{arm} %define all_arch_configs kernel-%{version}-arm*.config %define image_install_path boot +%define asmarch arm %define hdrarch arm %define make_target vmlinux %define kernel_image vmlinux @@ -557,7 +558,8 @@ Source70: config-s390x Source90: config-sparc64-generic -Source100: config-arm +Source100: config-arm-generic +Source110: config-arm-omap-generic # This file is intentionally left empty in the stock kernel. Its a nicety # added for those wanting to do custom rebuilds with altered config opts. @@ -1902,6 +1904,9 @@ fi # and build. %changelog +* Tue Aug 09 2011 Josh Boyer +- Add Makefile.config and ARM config changes from David Marlin + * Tue Aug 09 2011 Josh Boyer - Add patch davej applied to f15 for rhbz 728872 From bba41d6786c78297e85b61f7aec79a60087541bf Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 11 Aug 2011 14:46:57 -0400 Subject: [PATCH 023/487] Sync with f15 for rhbz 729340. Whee! --- kernel.spec | 10 ++++++++-- xen-blkfront-name-adjust.patch | 30 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 xen-blkfront-name-adjust.patch diff --git a/kernel.spec b/kernel.spec index 92a7b6cb8..10f29bc22 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 5 +%global baserelease 6 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -650,7 +650,9 @@ Patch800: linux-2.6-crash-driver.patch # crypto/ # virt + ksm patches -Patch1555: fix_xen_guest_on_old_EC2.patch +Patch1500: fix_xen_guest_on_old_EC2.patch +Patch1501: xen-blkfront-name-adjust.patch + # DRM @@ -1243,6 +1245,7 @@ ApplyPatch linux-2.6-e1000-ich9-montevina.patch # Assorted Virt Fixes ApplyPatch fix_xen_guest_on_old_EC2.patch +ApplyPatch xen-blkfront-name-adjust.patch # DRM core @@ -1904,6 +1907,9 @@ fi # and build. %changelog +* Thu Aug 11 2011 Josh Boyer +- Add patch davej applied to f15 for rhbz 729340 + * Tue Aug 09 2011 Josh Boyer - Add Makefile.config and ARM config changes from David Marlin diff --git a/xen-blkfront-name-adjust.patch b/xen-blkfront-name-adjust.patch new file mode 100644 index 000000000..9573c7bf5 --- /dev/null +++ b/xen-blkfront-name-adjust.patch @@ -0,0 +1,30 @@ +commit 196cfe2ae8fcdc03b3c7d627e7dfe8c0ce7229f9 +Author: Stefan Bader +Date: Thu Jul 14 15:30:22 2011 +0200 + + xen-blkfront: Drop name and minor adjustments for emulated scsi devices + + These were intended to avoid the namespace clash when representing + emulated IDE and SCSI devices. However that seems to confuse users + more than expected (a disk defined as sda becomes xvde). + So for now go back to the scheme which does no adjustments. This + will break when mixing IDE and SCSI names in the configuration of + guests but should be by now expected. + + Acked-by: Stefano Stabellini + Signed-off-by: Stefan Bader + Signed-off-by: Konrad Rzeszutek Wilk + +--- linux-2.6.39.noarch/drivers/block/xen-blkfront.c~ 2011-08-11 11:54:25.656150889 -0400 ++++ linux-2.6.39.noarch/drivers/block/xen-blkfront.c 2011-08-11 11:54:54.573046334 -0400 +@@ -123,8 +123,8 @@ static DEFINE_SPINLOCK(minor_lock); + #define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED)) + #define EMULATED_HD_DISK_MINOR_OFFSET (0) + #define EMULATED_HD_DISK_NAME_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET / 256) +-#define EMULATED_SD_DISK_MINOR_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET + (4 * 16)) +-#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_HD_DISK_NAME_OFFSET + 4) ++#define EMULATED_SD_DISK_MINOR_OFFSET (0) ++#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_SD_DISK_MINOR_OFFSET / 256) + + #define DEV_NAME "xvd" /* name in /dev */ + From 716ab00b8c4dfc4e490ee79f90c7722034fbe203 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 11 Aug 2011 14:59:19 -0400 Subject: [PATCH 024/487] Add quirk patch for logitech webcams (rhbz 729269) --- kernel.spec | 3 +++ usb-add-quirk-for-logitech-webcams.patch | 30 ++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 usb-add-quirk-for-logitech-webcams.patch diff --git a/kernel.spec b/kernel.spec index 10f29bc22..bb97ce2af 100644 --- a/kernel.spec +++ b/kernel.spec @@ -691,6 +691,7 @@ Patch12021: udlfb-bind-framebuffer-to-interface.patch Patch12022: fix-cdc-ncm-dma-stack-vars.patch Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch Patch12024: block-stray-block-put-after-teardown.patch +Patch12025: usb-add-quirk-for-logitech-webcams.patch # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch @@ -1276,6 +1277,7 @@ ApplyPatch udlfb-bind-framebuffer-to-interface.patch ApplyPatch fix-cdc-ncm-dma-stack-vars.patch ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch ApplyPatch block-stray-block-put-after-teardown.patch +ApplyPatch usb-add-quirk-for-logitech-webcams.patch # Runtime PM #ApplyPatch linux-2.6-usb-pci-autosuspend.patch @@ -1909,6 +1911,7 @@ fi %changelog * Thu Aug 11 2011 Josh Boyer - Add patch davej applied to f15 for rhbz 729340 +- Add munged together patch for rhbz 729269 * Tue Aug 09 2011 Josh Boyer - Add Makefile.config and ARM config changes from David Marlin diff --git a/usb-add-quirk-for-logitech-webcams.patch b/usb-add-quirk-for-logitech-webcams.patch new file mode 100644 index 000000000..fa32f34f9 --- /dev/null +++ b/usb-add-quirk-for-logitech-webcams.patch @@ -0,0 +1,30 @@ +commit a218e3649310bd2ee0e8b7ec6353ab029d020289 +Author: Oliver Neukum +Date: Tue Aug 9 08:12:37 2011 -0400 + + USB: quirk for Logitech C250, C270, and C310 webcams + + This need for this was shown by the new PM code + + Signed-off-by: Oliver Neukum + +diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c +index 81ce6a8..5114281 100644 +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -41,6 +41,15 @@ static const struct usb_device_id usb_quirk_list[] = { + /* Logitech Harmony 700-series */ + { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, + ++ /* Logitech Webcam C250 */ ++ { USB_DEVICE(0x046d, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, ++ ++ /* Logitech Webcam C310 */ ++ { USB_DEVICE(0x046d, 0x081b), .driver_info = USB_QUIRK_RESET_RESUME }, ++ ++ /* Logitech Webcam C270 */ ++ { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME }, ++ + /* Philips PSC805 audio device */ + { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME }, + From 52149c3ebb54a8db86897a8fe9d89dcdd3e402c1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 11 Aug 2011 22:14:40 -0400 Subject: [PATCH 025/487] Make ide_pmac a module (rhbz 730039) --- config-powerpc-generic | 2 +- kernel.spec | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config-powerpc-generic b/config-powerpc-generic index 8dd44f399..0bf87f708 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -159,7 +159,7 @@ CONFIG_IDE_TASK_IOCTL=y # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set -CONFIG_BLK_DEV_IDE_PMAC=y +CONFIG_BLK_DEV_IDE_PMAC=m CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y CONFIG_BLK_DEV_IDEDMA=y # CONFIG_BLK_DEV_HD is not set diff --git a/kernel.spec b/kernel.spec index bb97ce2af..6dbf65e17 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1912,6 +1912,7 @@ fi * Thu Aug 11 2011 Josh Boyer - Add patch davej applied to f15 for rhbz 729340 - Add munged together patch for rhbz 729269 +- Build ide_pmac as a module (rhbz 730039) * Tue Aug 09 2011 Josh Boyer - Add Makefile.config and ARM config changes from David Marlin From 0ffe7fc9b03104c86ce8fbea76e05018e6f9ff6b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sat, 13 Aug 2011 17:13:36 -0400 Subject: [PATCH 026/487] CPU_FREQ drivers should now be built-in on x86-64. --- config-x86_64-generic | 4 ++-- kernel.spec | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/config-x86_64-generic b/config-x86_64-generic index fd1e9c39f..85da0d997 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -17,8 +17,8 @@ CONFIG_AMD_NUMA=y CONFIG_X86_64_ACPI_NUMA=y # CONFIG_NUMA_EMU is not set CONFIG_NR_CPUS=512 -CONFIG_X86_POWERNOW_K8=m -CONFIG_X86_P4_CLOCKMOD=m +CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_P4_CLOCKMOD=y CONFIG_IA32_EMULATION=y # CONFIG_IA32_AOUT is not set # CONFIG_IOMMU_DEBUG is not set diff --git a/kernel.spec b/kernel.spec index 6dbf65e17..1050a983c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1909,6 +1909,9 @@ fi # and build. %changelog +* Sat Aug 13 2011 Dave Jones +- CPU_FREQ drivers should now be built-in on x86-64. + * Thu Aug 11 2011 Josh Boyer - Add patch davej applied to f15 for rhbz 729340 - Add munged together patch for rhbz 729269 From 9765980dfcba8e290b18190f68928ca3e9b8d6c8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 16 Aug 2011 10:32:18 -0400 Subject: [PATCH 027/487] Bring in Linux-3.1-rc2 --- Makefile.config | 18 +- add-appleir-usb-driver.patch | 5 +- config-arm-generic | 5 +- config-arm-omap-generic | 9 + config-debug | 2 + config-generic | 53 +- config-ia64-generic | 1 + config-nodebug | 2 + config-powerpc-generic | 7 + config-powerpc64 | 6 + config-s390x | 1 - config-sparc64-generic | 2 - config-x86-32-generic | 206 ++ config-x86-generic | 277 +- config-x86_64-generic | 377 +-- dmar-disable-when-ricoh-multifunction.patch | 4 +- epoll-fix-spurious-lockdep-warnings.patch | 2 +- fix-cdc-ncm-dma-stack-vars.patch | 97 +- hda_intel-prealloc-4mb-dmabuffer.patch | 47 - ...io-requests-are-not-smaller-than-the.patch | 315 -- kernel.spec | 33 +- linux-2.6-crash-driver.patch | 61 +- linux-2.6-intel-iommu-igfx.patch | 4 +- linux-2.6-silence-noise.patch | 4 +- ...ix-invalid-signal-values-from-device.patch | 82 - linux-2.6.30-no-pcspkr-modalias.patch | 13 +- rcu-avoid-just-onlined-cpu-resched.patch | 47 + sources | 2 +- ...tek-driver-uses-stack-memory-for-DMA.patch | 89 +- utrace.patch | 2963 +++++++++++------ 30 files changed, 2471 insertions(+), 2263 deletions(-) create mode 100644 config-x86-32-generic delete mode 100644 hda_intel-prealloc-4mb-dmabuffer.patch delete mode 100644 hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch delete mode 100644 linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch create mode 100644 rcu-avoid-just-onlined-cpu-resched.patch diff --git a/Makefile.config b/Makefile.config index 35060e32f..0e71c35c0 100644 --- a/Makefile.config +++ b/Makefile.config @@ -39,16 +39,22 @@ temp-arm-generic: config-arm-generic temp-generic temp-armv7l-omap-generic: config-arm-omap-generic temp-arm-generic perl merge.pl $^ > $@ -temp-x86-generic: config-x86-generic temp-generic +temp-x86-32: config-x86-32-generic config-x86-generic perl merge.pl $^ > $@ -temp-x86-debug-generic: config-x86-generic temp-debug-generic +temp-x86-32-generic: temp-x86-32 temp-generic perl merge.pl $^ > $@ -temp-x86_64-generic: config-x86_64-generic temp-generic +temp-x86-debug-generic: temp-x86-32 temp-debug-generic perl merge.pl $^ > $@ -temp-x86_64-debug-generic: config-x86_64-generic temp-debug-generic +temp-x86-64: config-x86_64-generic config-x86-generic + perl merge.pl $^ > $@ + +temp-x86_64-generic: temp-x86-64 temp-generic + perl merge.pl $^ > $@ + +temp-x86_64-debug-generic: temp-x86-64 temp-debug-generic perl merge.pl $^ > $@ temp-sparc64-generic: config-sparc64-generic temp-generic @@ -69,13 +75,13 @@ temp-s390-generic: config-s390x temp-generic temp-ia64-generic: config-ia64-generic temp-generic perl merge.pl $^ > $@ -kernel-$(VERSION)-i686-PAE.config: config-i686-PAE temp-x86-generic +kernel-$(VERSION)-i686-PAE.config: config-i686-PAE temp-x86-32-generic perl merge.pl $^ i386 > $@ kernel-$(VERSION)-i686-PAEdebug.config: config-i686-PAE temp-x86-debug-generic perl merge.pl $^ i386 > $@ -kernel-$(VERSION)-i686.config: /dev/null temp-x86-generic +kernel-$(VERSION)-i686.config: /dev/null temp-x86-32-generic perl merge.pl $^ i386 > $@ kernel-$(VERSION)-i686-debug.config: /dev/null temp-x86-debug-generic diff --git a/add-appleir-usb-driver.patch b/add-appleir-usb-driver.patch index 26477ccce..0ab0ed6f4 100644 --- a/add-appleir-usb-driver.patch +++ b/add-appleir-usb-driver.patch @@ -140,9 +140,8 @@ diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 60de906..2f2f2e7 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig -@@ -209,6 +209,19 @@ config INPUT_KEYSPAN_REMOTE - To compile this driver as a module, choose M here: the module will - be called keyspan_remote. + help + Say Y here if you need accelerometer to work in polling mode. +config INPUT_APPLEIR + tristate "Apple infrared receiver (built in)" diff --git a/config-arm-generic b/config-arm-generic index 5b79fe23d..dec424128 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -9,6 +9,7 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_ARCH_VERSATILE=y CONFIG_ARCH_VERSATILE_PB=y CONFIG_MACH_VERSATILE_AB=y +CONFIG_MACH_VERSATILE_DT=y CONFIG_HIGHMEM=y # CONFIG_HIGHPTE is not set @@ -146,6 +147,8 @@ CONFIG_USE_OF=y CONFIG_PROC_DEVICETREE=y CONFIG_MTD_PHYSMAP_OF=m CONFIG_SERIAL_OF_PLATFORM=m -# CONFIG_LEDS_GPIO_OF is not set CONFIG_MMC_SDHCI_OF=m +CONFIG_MMC_SDHCI_PXAV3=m +CONFIG_MMC_SDHCI_PXAV2=m +CONFIG_FTGMAC100=m diff --git a/config-arm-omap-generic b/config-arm-omap-generic index 34b5389d6..df7ab065a 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -275,6 +275,7 @@ CONFIG_TI_DAC7512=m CONFIG_BMP085=m CONFIG_C2PORT=m CONFIG_EEPROM_AT25=m +CONFIG_EEPROM_93XX46=m # CONFIG_IWMC3200TOP_DEBUGFS is not set # CONFIG_SCSI_PROC_FS is not set # CONFIG_BLK_DEV_SR_VENDOR is not set @@ -387,6 +388,7 @@ CONFIG_INPUT_AD714X_SPI=m # CONFIG_INPUT_APPLEIR is not set CONFIG_INPUT_TWL4030_PWRBUTTON=y CONFIG_INPUT_TWL4030_VIBRA=y +CONFIG_INPUT_TWL6040_VIBRA=y CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set CONFIG_INPUT_ADXL34X=m @@ -445,6 +447,7 @@ CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y # CONFIG_DEBUG_GPIO is not set CONFIG_GPIO_SYSFS=y +# CONFIG_GPIO_GENERIC_PLATFORM is not set # # Memory mapped GPIO expanders: @@ -568,6 +571,7 @@ CONFIG_OMAP_WATCHDOG=y CONFIG_SSB=y # CONFIG_SSB_SDIOHOST is not set CONFIG_MFD_CORE=y +# CONFIG_MFD_AAT2870_CORE is not set # CONFIG_MFD_88PM860X is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_ASIC3 is not set @@ -597,6 +601,8 @@ CONFIG_TWL4030_CODEC=y CONFIG_MFD_OMAP_USB_HOST=y # CONFIG_MFD_TPS6586X is not set # CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set # CONFIG_MFD_WL1273_CORE is not set CONFIG_REGULATOR=y # CONFIG_REGULATOR_DEBUG is not set @@ -640,6 +646,7 @@ CONFIG_VIDEO_SAA717X=m CONFIG_VIDEO_SAA7127=m CONFIG_VIDEO_UPD64031A=m CONFIG_VIDEO_UPD64083=m +CONFIG_VIDEO_ADP1653=m # # CONFIG_VIDEO_TVAUDIO is not set # CONFIG_VIDEO_TDA7432 is not set @@ -736,6 +743,7 @@ CONFIG_PANEL_TPO_TD043MTEA1=y # CONFIG_LCD_VGG2432A4 is not set # CONFIG_LCD_PLATFORM is not set # CONFIG_LCD_S6E63M0 is not set +# CONFIG_LCD_AMS369FG06 is not set CONFIG_BACKLIGHT_GENERIC=m CONFIG_DISPLAY_SUPPORT=y # CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set @@ -790,6 +798,7 @@ CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=y CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y CONFIG_SND_OMAP_SOC_ZOOM2=y CONFIG_SND_OMAP_SOC_IGEP0020=y +CONFIG_SND_OMAP_SOC_OMAP4_HDMI=y CONFIG_SND_SOC_I2C_AND_SPI=y # CONFIG_SND_SOC_ALL_CODECS is not set CONFIG_SND_SOC_TLV320AIC23=y diff --git a/config-debug b/config-debug index 7bbaa0b59..21e52bfd7 100644 --- a/config-debug +++ b/config-debug @@ -2,6 +2,8 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y +CONFIG_DEBUG_ATOMIC_SLEEP=y + CONFIG_DEBUG_MUTEXES=y CONFIG_DEBUG_RT_MUTEXES=y CONFIG_DEBUG_LOCK_ALLOC=y diff --git a/config-generic b/config-generic index 63327649e..e320aeffa 100644 --- a/config-generic +++ b/config-generic @@ -528,6 +528,7 @@ CONFIG_MEGARAID_LEGACY=m CONFIG_MEGARAID_SAS=m CONFIG_SCSI_MVSAS=m # CONFIG_SCSI_MVSAS_DEBUG is not set +CONFIG_SCSI_MVSAS_TASKLET=y CONFIG_SCSI_MPT2SAS=m CONFIG_SCSI_MPT2SAS_MAX_SGE=128 CONFIG_SCSI_MPT2SAS_LOGGING=y @@ -734,6 +735,10 @@ CONFIG_FIREWIRE_NOSY=m # CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set # +# Virtualization support drivers +# +# CONFIG_VIRT_DRIVERS is not set + # Networking support # CONFIG_NET=y @@ -1041,6 +1046,7 @@ CONFIG_IP_SET_HASH_IPPORTIP=m CONFIG_IP_SET_HASH_IPPORTNET=m CONFIG_IP_SET_HASH_NET=m CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m CONFIG_IP_SET_LIST_SET=m # @@ -1345,6 +1351,7 @@ CONFIG_R8169=m CONFIG_R8169_VLAN=y CONFIG_SKGE=m # CONFIG_SKGE_DEBUG is not set +CONFIG_SKGE_GENESIS=y CONFIG_TIGON3=m CONFIG_SKY2=m # CONFIG_SKY2_DEBUG is not set @@ -1470,6 +1477,7 @@ CONFIG_ATMEL=m CONFIG_B43=m CONFIG_B43_PCMCIA=y CONFIG_B43_SDIO=y +CONFIG_B43_BCMA=y CONFIG_B43_DEBUG=y CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y @@ -1583,6 +1591,7 @@ CONFIG_WL1271_SPI=m CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m CONFIG_RTL8192CU=m +CONFIG_RTL8192DE=m CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m @@ -1663,6 +1672,8 @@ CONFIG_BAYCOM_PAR=m CONFIG_BAYCOM_EPP=m CONFIG_YAM=m +CONFIG_NFC=m + # # IrDA (infrared) support # @@ -2033,6 +2044,10 @@ CONFIG_INPUT_APPLEIR=m # CONFIG_INPUT_AD714X is not set # CONFIG_INPUT_PCF8574 is not set +CONFIG_INPUT_MMA8450=m +CONFIG_INPUT_MPU3050=m +CONFIG_INPUT_KXTJ9=m +# CONFIG_INPUT_KXTJ9_POLLED_MODE is not set # # Character devices @@ -2229,6 +2244,7 @@ CONFIG_SENSORS_LM93=m CONFIG_SENSORS_LTC4245=m CONFIG_SENSORS_MAX1619=m CONFIG_SENSORS_MAX6650=m +CONFIG_SENSORS_NTC_THERMISTOR=m CONFIG_SENSORS_PC87360=m CONFIG_SENSORS_PC87427=m CONFIG_SENSORS_PCF8591=m @@ -2259,6 +2275,7 @@ CONFIG_SENSORS_W83792D=m CONFIG_SENSORS_W83793=m CONFIG_SENSORS_LTC4215=m CONFIG_SENSORS_LM95241=m +CONFIG_SENSORS_LM95245=m CONFIG_SENSORS_TMP421=m CONFIG_SENSORS_WM8350=m CONFIG_SENSORS_WM831X=m @@ -2282,6 +2299,7 @@ CONFIG_SENSORS_LINEAGE=m CONFIG_SENSORS_LTC4151=m CONFIG_SENSORS_MAX6639=m CONFIG_SENSORS_SCH5627=m +CONFIG_SENSORS_SCH5636=m CONFIG_SENSORS_ADS1015=m CONFIG_SENSORS_MAX16065=m CONFIG_SENSORS_MAX6642=m @@ -2293,13 +2311,16 @@ CONFIG_SENSORS_EMC6W201=m CONFIG_PMBUS=m CONFIG_SENSORS_PMBUS=m CONFIG_SENSORS_MAX16064=m +CONFIG_SENSORS_LM25066=m CONFIG_SENSORS_MAX34440=m CONFIG_SENSORS_MAX8688=m +CONFIG_SENSORS_MAX1668=m # CONFIG_HMC6352 is not set # CONFIG_BMP085 is not set # CONFIG_PCH_PHUB is not set # CONFIG_SERIAL_PCH_UART is not set +# CONFIG_USB_SWITCH_FSA9480 is not set CONFIG_W1=m CONFIG_W1_CON=y @@ -2339,6 +2360,7 @@ CONFIG_IPMI_POWEROFF=m # Watchdog Cards # CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_CORE=y # CONFIG_WATCHDOG_NOWAYOUT is not set CONFIG_SOFT_WATCHDOG=m CONFIG_WDTPCI=m @@ -2373,6 +2395,7 @@ CONFIG_USBPCWATCHDOG=m CONFIG_WM8350_WATCHDOG=m CONFIG_WM831X_WATCHDOG=m # CONFIG_MAX63XX_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_TIMERIOMEM=m @@ -2524,6 +2547,7 @@ CONFIG_VIDEO_CX88_VP3054=m CONFIG_VIDEO_EM28XX=m CONFIG_VIDEO_EM28XX_ALSA=m CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_VIDEO_EM28XX_RC=y CONFIG_VIDEO_CX231XX=m CONFIG_VIDEO_CX231XX_ALSA=m CONFIG_VIDEO_CX231XX_DVB=m @@ -2585,6 +2609,7 @@ CONFIG_MEDIA_TUNER_MT2131=m CONFIG_MEDIA_TUNER_QT1010=m CONFIG_MEDIA_TUNER_XC2028=m CONFIG_MEDIA_TUNER_XC5000=m +CONFIG_MEDIA_TUNER_XC4000=m CONFIG_MEDIA_TUNER_MXL5005S=m CONFIG_MEDIA_TUNER_MXL5007T=m CONFIG_MEDIA_TUNER_MC44S803=m @@ -2597,6 +2622,7 @@ CONFIG_MEDIA_TUNER_TDA18212=m # CONFIG_DVB_CAPTURE_DRIVERS=y CONFIG_DVB_CORE=m +CONFIG_DVB_NET=y CONFIG_DVB_MAX_ADAPTERS=8 CONFIG_DVB_DYNAMIC_MINORS=y @@ -2605,6 +2631,8 @@ CONFIG_DVB_STB0899=m CONFIG_DVB_STB6100=m CONFIG_DVB_STV090x=m CONFIG_DVB_STV6110x=m +CONFIG_DVB_DRXK=m +CONFIG_DVB_TDA18271C2DD=m CONFIG_DVB_CX24110=m CONFIG_DVB_CX24123=m CONFIG_DVB_MT312=m @@ -2690,6 +2718,7 @@ CONFIG_DVB_LGS8GL5=m CONFIG_DVB_DUMMY_FE=m CONFIG_DVB_FIREDTV=m CONFIG_DVB_NGENE=m +CONFIG_DVB_DDBRIDGE=m CONFIG_DVB_MB86A20S=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_DIB9000=m @@ -2767,6 +2796,7 @@ CONFIG_IR_RC6_DECODER=m CONFIG_IR_JVC_DECODER=m CONFIG_IR_SONY_DECODER=m CONFIG_IR_RC5_SZ_DECODER=m +CONFIG_IR_MCE_KBD_DECODER=m CONFIG_IR_LIRC_CODEC=m CONFIG_IR_IMON=m CONFIG_IR_MCEUSB=m @@ -2986,6 +3016,7 @@ CONFIG_SND_HDA_INPUT_JACK=y CONFIG_SND_HDA_PATCH_LOADER=y CONFIG_SND_HDA_HWDEP=y CONFIG_SND_HDA_CODEC_REALTEK=y +CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS=y CONFIG_SND_HDA_CODEC_CA0110=y CONFIG_SND_HDA_CODEC_ANALOG=y CONFIG_SND_HDA_CODEC_SIGMATEL=y @@ -2998,10 +3029,12 @@ CONFIG_SND_HDA_CODEC_INTELHDMI=y CONFIG_SND_HDA_CODEC_SI3054=y CONFIG_SND_HDA_CODEC_NVHDMI=y CONFIG_SND_HDA_CODEC_HDMI=y +CONFIG_SND_HDA_CODEC_CA0132=y CONFIG_SND_HDA_GENERIC=y CONFIG_SND_HDA_POWER_SAVE=y CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 CONFIG_SND_HDA_RECONFIG=y +CONFIG_SND_HDA_PREALLOC_SIZE=4096 CONFIG_SND_HDSPM=m CONFIG_SND_HIFIER=m CONFIG_SND_ICE1712=m @@ -3193,6 +3226,10 @@ CONFIG_HID_KEYTOUCH=m CONFIG_HID_LCPOWER=m CONFIG_HID_ROCCAT_ARVO=m CONFIG_HID_ROCCAT_KOVAPLUS=m +CONFIG_HID_HOLTEK=m +CONFIG_HOLTEK_FF=y +CONFIG_HID_SPEEDLINK=m +CONFIG_HID_WIIMOTE=m # # USB Imaging devices @@ -3254,6 +3291,7 @@ CONFIG_USB_GSPCA_SQ930X=m CONFIG_USB_GSPCA_NW80X=m CONFIG_USB_GSPCA_VICAM=m CONFIG_USB_GSPCA_KINECT=m +CONFIG_USB_GSPCA_SE401=m CONFIG_USB_IBMCAM=m CONFIG_USB_KONICAWC=m @@ -3277,6 +3315,7 @@ CONFIG_SOC_CAMERA_MT9T112=m CONFIG_SOC_CAMERA_RJ54N1=m CONFIG_SOC_CAMERA_OV9640=m CONFIG_SOC_CAMERA_OV6650=m +CONFIG_SOC_CAMERA_OV5642=m CONFIG_SOC_CAMERA_IMX074=m CONFIG_SOC_CAMERA_OV2640=m CONFIG_SOC_CAMERA_OV9740=m @@ -3510,7 +3549,7 @@ CONFIG_MFD_WM8400=m # CONFIG_MFD_RDC321X is not set # CONFIG_MFD_JANZ_CMODIO is not set # CONFIG_MFD_WM831X_I2C is not set -CONFIG_MFD_CS5535=m +# CONFIG_MFD_CS5535 is not set # # File systems @@ -3631,6 +3670,7 @@ CONFIG_SQUASHFS=m CONFIG_SQUASHFS_XATTR=y CONFIG_SQUASHFS_LZO=y CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_ZLIB=y # CONFIG_SQUASHFS_EMBEDDED is not set CONFIG_VXFS_FS=m # CONFIG_HPFS_FS is not set @@ -3664,6 +3704,7 @@ CONFIG_NFS_FSCACHE=y # CONFIG_NFS_USE_NEW_IDMAPPER is not set # CONFIG_NFSD_DEPRECATED is not set CONFIG_PNFS_OBJLAYOUT=m +CONFIG_PNFS_BLOCK=m CONFIG_LOCKD=m CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y @@ -3921,6 +3962,8 @@ CONFIG_CRC32=m CONFIG_CRC_CCITT=m CONFIG_CRC_ITU_T=m CONFIG_CRC_T10DIF=m +CONFIG_CRC8=m +CONFIG_CORDIC=m CONFIG_CRYPTO_ZLIB=m CONFIG_ZLIB_INFLATE=y @@ -4177,6 +4220,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_AMS_DELTA is not set # CONFIG_LEDS_LOCOMO is not set # CONFIG_LEDS_NET48XX is not set +# CONFIG_LEDS_NET5501 is not set # CONFIG_LEDS_PCA9532 is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_BD2802 is not set @@ -4229,6 +4273,7 @@ CONFIG_FUNCTION_TRACER=y CONFIG_STACK_TRACER=y CONFIG_KPROBES=y +CONFIG_JUMP_LABEL=y CONFIG_OPTPROBES=y # CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set @@ -4320,7 +4365,6 @@ CONFIG_RESOURCE_COUNTERS=y #FIXME: x86 generic? CONFIG_LEDS_CLEVO_MAIL=m -CONFIG_I8K=m CONFIG_INPUT_APANEL=m # CONFIG_INTEL_MENLOW is not set @@ -4638,8 +4682,10 @@ CONFIG_EVENT_POWER_TRACING_DEPRECATED=y CONFIG_NFC_DEVICES=y CONFIG_PN544_NFC=m +CONFIG_NFC_PN533=m CONFIG_TARGET_CORE=m +CONFIG_ISCSI_TARGET=m CONFIG_LOOPBACK_TARGET=m # CONFIG_LOOPBACK_TARGET_CDB_DEBUG is not set CONFIG_TCM_IBLOCK=m @@ -4663,3 +4709,6 @@ CONFIG_TEST_KSTRTOX=m # CONFIG_GOOGLE_FIRMWARE is not set CONFIG_INTEL_MID_PTI=m + +CONFIG_IOMMU_SUPPORT=y + diff --git a/config-ia64-generic b/config-ia64-generic index f469b9621..ca97689fa 100644 --- a/config-ia64-generic +++ b/config-ia64-generic @@ -191,6 +191,7 @@ CONFIG_HP_ILO=m CONFIG_PARAVIRT_GUEST=y CONFIG_PARAVIRT=y +CONFIG_PARAVIRT_TIME_ACCOUNTING=y CONFIG_DMAR_DEFAULT_ON=y diff --git a/config-nodebug b/config-nodebug index 5730cd1b2..a3fbf944d 100644 --- a/config-nodebug +++ b/config-nodebug @@ -2,6 +2,8 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y +CONFIG_DEBUG_ATOMIC_SLEEP=y + CONFIG_DEBUG_MUTEXES=y CONFIG_DEBUG_RT_MUTEXES=y CONFIG_DEBUG_LOCK_ALLOC=y diff --git a/config-powerpc-generic b/config-powerpc-generic index 0bf87f708..5e1ddf74d 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -314,16 +314,19 @@ CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m # CONFIG_MFD_88PM8607 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set # CONFIG_MFD_WL1273_CORE is not set # CONFIG_XPS_USB_HCD_XILINX is not set # CONFIG_MMC_SDHCI_OF_ESDHC is not set # CONFIG_MMC_SDHCI_OF_HLWD is not set # CONFIG_MFD_TC35892 is not set +# CONFIG_MFD_AAT2870_CORE is not set # CONFIG_GPIO_SCH is not set # CONFIG_PPC_MPC512x is not set +# CONFIG_RTC_DRV_MPC5121 is not set CONFIG_MPC512X_DMA=m @@ -342,3 +345,7 @@ CONFIG_CRYPTO_DEV_FSL_CAAM_INTC=y CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_COUNT_THLD=255 CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD=2048 CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=m + +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_MCP23S08 is not set + diff --git a/config-powerpc64 b/config-powerpc64 index 8866a5320..f27f5b383 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -44,6 +44,7 @@ CONFIG_LPARCFG=y CONFIG_SERIAL_ICOM=m CONFIG_HVCS=m CONFIG_HVC_CONSOLE=y +# CONFIG_HVC_OLD_HVSI is not set CONFIG_HOTPLUG_PCI=y CONFIG_THERM_PM72=y CONFIG_IBMVETH=m @@ -174,6 +175,8 @@ CONFIG_PERF_EVENTS=y CONFIG_EVENT_PROFILE=y CONFIG_KVM_BOOK3S_64=m +#-- Enable _HV once publicly available POWER7 hardware can use it +# CONFIG_KVM_BOOK3S_64_HV is not set # CONFIG_KVM_EXIT_TIMING is not set #-- bz#607175 @@ -188,3 +191,6 @@ CONFIG_PSERIES_ENERGY=m CONFIG_PPC_ICSWX=y CONFIG_IO_EVENT_IRQ=y CONFIG_HW_RANDOM_AMD=m + +CONFIG_BPF_JIT=y +CONFIG_CPU_FREQ_MAPLE=y diff --git a/config-s390x b/config-s390x index da9db13c1..5251b5b32 100644 --- a/config-s390x +++ b/config-s390x @@ -236,5 +236,4 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_WARN_DYNAMIC_STACK is not set -CONFIG_JUMP_LABEL=y CONFIG_CRYPTO_GHASH_S390=m diff --git a/config-sparc64-generic b/config-sparc64-generic index 8cc28f74a..e5ee2c4b9 100644 --- a/config-sparc64-generic +++ b/config-sparc64-generic @@ -191,8 +191,6 @@ CONFIG_FB_XVR1000=y CONFIG_CRYPTO_DEV_NIAGARA2=y -CONFIG_JUMP_LABEL=y - # CONFIG_MTD_OF_PARTS is not set # CONFIG_MTD_PHYSMAP_OF is not set # CONFIG_MMC_SDHCI_OF is not set diff --git a/config-x86-32-generic b/config-x86-32-generic new file mode 100644 index 000000000..8b66c9291 --- /dev/null +++ b/config-x86-32-generic @@ -0,0 +1,206 @@ +# CONFIG_64BIT is not set + +CONFIG_X86_32_NON_STANDARD=y + +# CONFIG_X86_ELAN is not set +# CONFIG_X86_NUMAQ is not set +# CONFIG_X86_SUMMIT is not set +CONFIG_X86_BIGSMP=y +# CONFIG_X86_VISWS is not set +# CONFIG_X86_RDC321X is not set +# CONFIG_X86_ES7000 is not set +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set +CONFIG_M686=y +# CONFIG_MPENTIUMII is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MCYRIXIII is not set +# CONFIG_MVIAC3_2 is not set + +CONFIG_NR_CPUS=64 +CONFIG_X86_GENERIC=y +# CONFIG_X86_PPRO_FENCE is not set + +CONFIG_TOSHIBA=m + +CONFIG_SONYPI=m +CONFIG_SONYPI_COMPAT=y + +# CONFIG_NUMA is not set + +# CONFIG_NOHIGHMEM is not set +CONFIG_HIGHMEM4G=y +# CONFIG_HIGHMEM64G is not set +CONFIG_HIGHMEM=y +CONFIG_HIGHPTE=y + +# CONFIG_MATH_EMULATION is not set + +CONFIG_FB_GEODE=y +CONFIG_FB_GEODE_LX=y +CONFIG_FB_GEODE_GX=y +# CONFIG_FB_GEODE_GX1 is not set + +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOMMCONFIG is not set +CONFIG_PCI_GOANY=y + +# FIXME: wtf? "x86 specific drivers" +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_IBM_ASM=m + +# +# APM (Advanced Power Management) BIOS Support +# +CONFIG_APM=y +# CONFIG_APM_IGNORE_USER_SUSPEND is not set +# CONFIG_APM_DO_ENABLE is not set +CONFIG_APM_CPU_IDLE=y +# CONFIG_APM_DISPLAY_BLANK is not set +# CONFIG_APM_ALLOW_INTS is not set + +CONFIG_ACPI_BLACKLIST_YEAR=1999 + + +# CONFIG_X86_POWERNOW_K6 is not set +CONFIG_X86_POWERNOW_K7=y +# CONFIG_X86_GX_SUSPMOD is not set +CONFIG_X86_SPEEDSTEP_ICH=y +CONFIG_X86_SPEEDSTEP_SMI=y +CONFIG_X86_SPEEDSTEP_LIB=y +# CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set +CONFIG_X86_LONGRUN=y +# CONFIG_X86_LONGHAUL is not set +# CONFIG_X86_CPUFREQ_NFORCE2 is not set +# e_powersaver is dangerous +# CONFIG_X86_E_POWERSAVER is not set + +CONFIG_X86_HT=y +CONFIG_X86_TRAMPOLINE=y + + +# CONFIG_4KSTACKS is not set + +CONFIG_PCI_DIRECT=y + +# SHPC has half-arsed PCI probing, which makes it load on too many systems +# CONFIG_HOTPLUG_PCI_SHPC is not set + +CONFIG_BLK_DEV_AMD74XX=y + +CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI15X3=m +CONFIG_I2C_ALI1563=m +CONFIG_I2C_SIS5595=m +CONFIG_I2C_SIS630=m + +CONFIG_SCx200_ACB=m + +# CONFIG_X86_REBOOTFIXUPS is not set + +CONFIG_PC8736x_GPIO=m +# CONFIG_NSC_GPIO is not set +CONFIG_CS5535_GPIO=m +CONFIG_GPIO_SCH=m + +CONFIG_SND_ISA=y +CONFIG_SND_ES18XX=m + +CONFIG_HW_RANDOM_GEODE=m + +# CONFIG_SGI_IOC4 is not set + +CONFIG_TC1100_WMI=m + +CONFIG_IB700_WDT=m + +CONFIG_PHYSICAL_ALIGN=0x400000 +CONFIG_PHYSICAL_START=0x400000 + +# CONFIG_KEXEC_JUMP is not set + +CONFIG_CRYPTO_AES_586=y +CONFIG_CRYPTO_DEV_GEODE=m +CONFIG_CRYPTO_TWOFISH_586=m + +CONFIG_VIDEO_CAFE_CCIC=m + +CONFIG_VMI=y + +CONFIG_XEN_MAX_DOMAIN_MEMORY=8 + +CONFIG_MTD_NAND_CAFE=m + +# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set + + +CONFIG_OLPC=y +CONFIG_OLPC_OPENFIRMWARE=y +CONFIG_BATTERY_OLPC=y +CONFIG_MOUSE_PS2_OLPC=y +CONFIG_OLPC_XO1_PM=y +CONFIG_OLPC_XO15_SCI=y +CONFIG_OLPC_XO1_RTC=y +CONFIG_OLPC_XO1_SCI=y +# staging +# CONFIG_FB_OLPC_DCON is not set + +# CONFIG_SPARSE_IRQ is not set + +CONFIG_RCU_FANOUT=32 + +# CONFIG_X86_ANCIENT_MCE is not set + +# CONFIG_X86_MRST is not set + +CONFIG_I2C_PXA=m +# CONFIG_GPIO_LANGWELL is not set + +# CONFIG_INTEL_TXT is not set + +CONFIG_GEODE_WDT=m +CONFIG_CS5535_MFGPT=m +CONFIG_CS5535_CLOCK_EVENT_SRC=m + +CONFIG_LEDS_INTEL_SS4200=m + +CONFIG_OLPC_XO1=m +CONFIG_XO1_RFKILL=m + +CONFIG_X86_32_IRIS=m + + +CONFIG_MTD_OF_PARTS=m +CONFIG_MTD_PHYSMAP_OF=m +CONFIG_PROC_DEVICETREE=y +CONFIG_SERIAL_OF_PLATFORM=m +CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m +# CONFIG_MMC_SDHCI_OF is not set + +# CONFIG_X86_INTEL_MID is not set + +CONFIG_MFD_CS5535=m + +# I2O enabled only for 32-bit x86, disabled for PAE kernel +CONFIG_I2O=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m +CONFIG_I2O_CONFIG=y +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_BUS=m + diff --git a/config-x86-generic b/config-x86-generic index 231db7a40..0f1216ede 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -1,68 +1,30 @@ CONFIG_UID16=y -# CONFIG_64BIT is not set -# CONFIG_KERNEL_LZMA is not set -# -# Processor type and features -# -# -# Enable summit and co via the generic arch -# CONFIG_X86_EXTENDED_PLATFORM=y -CONFIG_X86_32_NON_STANDARD=y -# CONFIG_X86_ELAN is not set -# CONFIG_X86_NUMAQ is not set -# CONFIG_X86_SUMMIT is not set -CONFIG_X86_BIGSMP=y -# CONFIG_X86_VISWS is not set -# CONFIG_X86_RDC321X is not set -# CONFIG_X86_ES7000 is not set -# CONFIG_M386 is not set -# CONFIG_M486 is not set -# CONFIG_M586 is not set -# CONFIG_M586TSC is not set -# CONFIG_M586MMX is not set -CONFIG_M686=y -# CONFIG_MPENTIUMII is not set -# CONFIG_MPENTIUMIII is not set -# CONFIG_MPENTIUMM is not set -# CONFIG_MPENTIUM4 is not set -# CONFIG_MK6 is not set -# CONFIG_MK7 is not set -# CONFIG_MK8 is not set -# CONFIG_MCRUSOE is not set -# CONFIG_MWINCHIPC6 is not set -# CONFIG_MWINCHIP3D is not set -# CONFIG_MCYRIXIII is not set -# CONFIG_MVIAC3_2 is not set CONFIG_SMP=y -CONFIG_NR_CPUS=64 + CONFIG_X86_GENERIC=y -# CONFIG_X86_PPRO_FENCE is not set + CONFIG_HPET=y CONFIG_HPET_TIMER=y # CONFIG_HPET_MMAP is not set -CONFIG_X86_MCE=y -CONFIG_TOSHIBA=m + CONFIG_I8K=m -CONFIG_SONYPI=m CONFIG_SONYPI_COMPAT=y CONFIG_MICROCODE=m +CONFIG_MICROCODE_INTEL=y +CONFIG_MICROCODE_AMD=y + CONFIG_X86_MSR=y CONFIG_X86_CPUID=y CONFIG_EDD=m # CONFIG_EDD_OFF is not set -# CONFIG_NUMA is not set -# CONFIG_NOHIGHMEM is not set -CONFIG_HIGHMEM4G=y -# CONFIG_HIGHMEM64G is not set -CONFIG_HIGHMEM=y -CONFIG_HIGHPTE=y - -# CONFIG_MATH_EMULATION is not set CONFIG_MTRR=y +CONFIG_MTRR_SANITIZER=y +CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=1 +CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1 CONFIG_X86_PAT=y CONFIG_X86_PM_TIMER=y @@ -70,60 +32,30 @@ CONFIG_EFI=y CONFIG_EFI_VARS=y CONFIG_EFI_PCDP=y CONFIG_FB_EFI=y + +# FIXME: 32bit only? # CONFIG_FB_N411 is not set CONFIG_DMAR=y CONFIG_DMAR_BROKEN_GFX_WA=y CONFIG_DMAR_FLOPPY_WA=y CONFIG_DMAR_DEFAULT_ON=y - -CONFIG_FB_GEODE=y -CONFIG_FB_GEODE_LX=y -CONFIG_FB_GEODE_GX=y -# CONFIG_FB_GEODE_GX1 is not set - -# CONFIG_PCI_GOBIOS is not set -# CONFIG_PCI_GODIRECT is not set -# CONFIG_PCI_GOMMCONFIG is not set -CONFIG_PCI_GOANY=y - -# -# x86 specific drivers -# -CONFIG_PCMCIA_FDOMAIN=m -CONFIG_SCSI_FUTURE_DOMAIN=m CONFIG_SCSI_ADVANSYS=m -CONFIG_CC_STACKPROTECTOR=y - CONFIG_SECCOMP=y CONFIG_CAPI_EICON=y -# I2O enabled only for 32-bit x86, disabled for PAE kernel -CONFIG_I2O=m -CONFIG_I2O_BLOCK=m -CONFIG_I2O_SCSI=m -CONFIG_I2O_PROC=m -CONFIG_I2O_CONFIG=y -CONFIG_I2O_EXT_ADAPTEC=y -CONFIG_I2O_CONFIG_OLD_IOCTL=y -CONFIG_I2O_BUS=m - -# -# APM (Advanced Power Management) BIOS Support -# -CONFIG_APM=y -# CONFIG_APM_IGNORE_USER_SUSPEND is not set -# CONFIG_APM_DO_ENABLE is not set -CONFIG_APM_CPU_IDLE=y -# CONFIG_APM_DISPLAY_BLANK is not set -# CONFIG_APM_ALLOW_INTS is not set - # # Kernel debugging # CONFIG_X86_MPPARSE=y +# CONFIG_X86_VERBOSE_BOOTUP is not set +# CONFIG_MMIOTRACE_TEST is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_DEBUG_RODATA=y +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_DEBUG_NMI_TIMEOUT=5 CONFIG_ACPI=y CONFIG_ACPI_AC=y @@ -131,7 +63,6 @@ CONFIG_ACPI_AC=y CONFIG_ACPI_PROCFS_POWER=y CONFIG_ACPI_SYSFS_POWER=y CONFIG_ACPI_BATTERY=y -CONFIG_ACPI_BLACKLIST_YEAR=1999 CONFIG_ACPI_BUTTON=y CONFIG_ACPI_CONTAINER=m CONFIG_ACPI_DOCK=y @@ -143,7 +74,6 @@ CONFIG_ACPI_PROCFS=y CONFIG_ACPI_SBS=m CONFIG_ACPI_SLEEP=y CONFIG_ACPI_THERMAL=y -CONFIG_TOPSTAR_LAPTOP=m CONFIG_ACPI_TOSHIBA=m CONFIG_ACPI_VIDEO=m # CONFIG_ACPI_PROC_EVENT is not set @@ -153,54 +83,32 @@ CONFIG_ACPI_PROCESSOR_AGGREGATOR=m CONFIG_ACPI_HED=m CONFIG_ACPI_APEI=y CONFIG_ACPI_APEI_PCIEAER=y -CONFIG_ACPI_APEI_GHES=m +CONFIG_ACPI_APEI_GHES=y +CONFIG_ACPI_APEI_MEMORY_FAILURE=y # CONFIG_ACPI_APEI_EINJ is not set CONFIG_ACPI_IPMI=m CONFIG_ACPI_CUSTOM_METHOD=m CONFIG_X86_ACPI_CPUFREQ=y CONFIG_X86_PCC_CPUFREQ=y -# CONFIG_X86_POWERNOW_K6 is not set -CONFIG_X86_POWERNOW_K7=y CONFIG_X86_POWERNOW_K8=y -# CONFIG_X86_GX_SUSPMOD is not set -# CONFIG_X86_SPEEDSTEP_CENTRINO is not set -CONFIG_X86_SPEEDSTEP_ICH=y -CONFIG_X86_SPEEDSTEP_SMI=y -CONFIG_X86_SPEEDSTEP_LIB=y -# CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set CONFIG_X86_P4_CLOCKMOD=y -CONFIG_X86_LONGRUN=y -# CONFIG_X86_LONGHAUL is not set -# CONFIG_X86_CPUFREQ_NFORCE2 is not set -# e_powersaver is dangerous -# CONFIG_X86_E_POWERSAVER is not set - -CONFIG_X86_HT=y -CONFIG_X86_TRAMPOLINE=y +# CONFIG_X86_SPEEDSTEP_CENTRINO is not set # # various x86 specific drivers # CONFIG_NVRAM=y -CONFIG_IBM_ASM=m -CONFIG_CRYPTO_TWOFISH_586=m CONFIG_CRYPTO_DEV_PADLOCK=m CONFIG_CRYPTO_DEV_PADLOCK_AES=m CONFIG_CRYPTO_DEV_PADLOCK_SHA=m CONFIG_GENERIC_ISA_DMA=y -CONFIG_SCHED_SMT=y + CONFIG_SUSPEND=y CONFIG_HIBERNATION=y CONFIG_PM_STD_PARTITION="" -CONFIG_DEBUG_RODATA=y -CONFIG_DEBUG_STACKOVERFLOW=y -# CONFIG_4KSTACKS is not set -CONFIG_DEBUG_NMI_TIMEOUT=5 - -CONFIG_PCI_DIRECT=y CONFIG_PCI_MMCONFIG=y CONFIG_PCI_BIOS=y @@ -209,8 +117,7 @@ CONFIG_HOTPLUG_PCI_COMPAQ=m # CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set CONFIG_HOTPLUG_PCI_IBM=m # CONFIG_HOTPLUG_PCI_CPCI is not set -# SHPC has half-arsed PCI probing, which makes it load on too many systems -# CONFIG_HOTPLUG_PCI_SHPC is not set + CONFIG_PM=y CONFIG_IPW2100=m @@ -223,9 +130,6 @@ CONFIG_IPW2200_QOS=y CONFIG_BLK_DEV_AMD74XX=y -CONFIG_I2C_ALI1535=m -CONFIG_I2C_ALI15X3=m -CONFIG_I2C_ALI1563=m CONFIG_I2C_AMD756=m CONFIG_I2C_AMD756_S4882=m CONFIG_I2C_AMD8111=m @@ -234,45 +138,35 @@ CONFIG_I2C_ISCH=m CONFIG_I2C_NFORCE2=m CONFIG_I2C_NFORCE2_S4985=m CONFIG_I2C_PIIX4=m -CONFIG_I2C_SIS5595=m -CONFIG_I2C_SIS630=m CONFIG_I2C_SIS96X=m - CONFIG_I2C_VIA=m CONFIG_I2C_VIAPRO=m -CONFIG_SCx200_ACB=m - -# CONFIG_X86_REBOOTFIXUPS is not set - CONFIG_DELL_RBU=m CONFIG_DCDBAS=m -CONFIG_GPIO_SCH=m -CONFIG_PC8736x_GPIO=m -# CONFIG_NSC_GPIO is not set -CONFIG_CS5535_GPIO=m - CONFIG_EDAC=y # CONFIG_EDAC_DEBUG is not set CONFIG_EDAC_MM_EDAC=m CONFIG_EDAC_AMD76X=m +CONFIG_EDAC_AMD8111=m +CONFIG_EDAC_AMD8131=m CONFIG_EDAC_E7XXX=m CONFIG_EDAC_E752X=m CONFIG_EDAC_I82860=m CONFIG_EDAC_I82875P=m CONFIG_EDAC_I82975X=m CONFIG_EDAC_I3000=m +CONFIG_EDAC_I3200=m CONFIG_EDAC_I5000=m CONFIG_EDAC_I5100=m CONFIG_EDAC_I5400=m -CONFIG_EDAC_R82600=m -CONFIG_EDAC_AMD8131=m -CONFIG_EDAC_AMD8111=m -CONFIG_EDAC_I7CORE=m -CONFIG_EDAC_I3000=m CONFIG_EDAC_I7300=m +CONFIG_EDAC_I7CORE=m +CONFIG_EDAC_R82600=m CONFIG_EDAC_X38=m +CONFIG_EDAC_MCE_INJ=m +CONFIG_EDAC_DECODE_MCE=m CONFIG_SCHED_MC=y @@ -283,77 +177,70 @@ CONFIG_TCG_INFINEON=m CONFIG_HW_RANDOM_INTEL=m CONFIG_HW_RANDOM_AMD=m -CONFIG_HW_RANDOM_GEODE=m CONFIG_HW_RANDOM_VIA=m - # CONFIG_COMPAT_VDSO is not set -# CONFIG_SGI_IOC4 is not set - CONFIG_X86_PLATFORM_DEVICES=y + CONFIG_ASUS_LAPTOP=m CONFIG_COMPAL_LAPTOP=m +CONFIG_DELL_LAPTOP=m CONFIG_EEEPC_LAPTOP=m -CONFIG_EEEPC_WMI=m CONFIG_FUJITSU_LAPTOP=m # CONFIG_FUJITSU_LAPTOP_DEBUG is not set CONFIG_IDEAPAD_LAPTOP=m CONFIG_MSI_LAPTOP=m +CONFIG_PANASONIC_LAPTOP=m +CONFIG_SAMSUNG_LAPTOP=m CONFIG_SONY_LAPTOP=m -CONFIG_DELL_LAPTOP=m +CONFIG_TOPSTAR_LAPTOP=m + CONFIG_ACPI_WMI=m CONFIG_ACER_WMI=m CONFIG_ACERHDF=m -CONFIG_TC1100_WMI=m +CONFIG_ASUS_WMI=m +CONFIG_ASUS_NB_WMI=m CONFIG_HP_WMI=m # CONFIG_INTEL_SCU_IPC is not set CONFIG_DELL_WMI=m CONFIG_DELL_WMI_AIO=m -CONFIG_ASUS_WMI=m -CONFIG_ASUS_NB_WMI=m -CONFIG_XO15_EBOOK=m +CONFIG_EEEPC_WMI=m CONFIG_INTEL_OAKTRAIL=m +CONFIG_SAMSUNG_Q10=m +CONFIG_XO15_EBOOK=m # CONFIG_TOUCHSCREEN_INTEL_MID is not set # CONFIG_SMSC37B787_WDT is not set CONFIG_W83697HF_WDT=m -CONFIG_IB700_WDT=m -CONFIG_RELOCATABLE=y -CONFIG_PHYSICAL_ALIGN=0x400000 -CONFIG_PHYSICAL_START=0x400000 CONFIG_CRASH_DUMP=y -# CONFIG_KEXEC_JUMP is not set CONFIG_PROC_VMCORE=y CONFIG_CRASH=m -CONFIG_CRYPTO_DEV_GEODE=m - -CONFIG_VIDEO_CAFE_CCIC=m - CONFIG_VIRTUALIZATION=y CONFIG_KVM=m CONFIG_KVM_INTEL=m CONFIG_KVM_AMD=m CONFIG_LGUEST=m +CONFIG_LGUEST_GUEST=y CONFIG_PARAVIRT_GUEST=y CONFIG_PARAVIRT=y +CONFIG_PARAVIRT_TIME_ACCOUNTING=y # CONFIG_PARAVIRT_DEBUG is not set # PARAVIRT_SPINLOCKS has a 5% perf hit +# FIXME: Still true ? References? # CONFIG_PARAVIRT_SPINLOCKS is not set + CONFIG_KVM_CLOCK=y CONFIG_KVM_GUEST=y CONFIG_KVM_MMU_AUDIT=y # default $x would be nice... -CONFIG_LGUEST_GUEST=y -CONFIG_VMI=y CONFIG_XEN=y # CONFIG_XEN_DEBUG is not set -CONFIG_XEN_MAX_DOMAIN_MEMORY=8 CONFIG_XEN_BALLOON=y CONFIG_XEN_SCRUB_PAGES=y CONFIG_XEN_SAVE_RESTORE=y @@ -374,10 +261,11 @@ CONFIG_XEN_DEBUG_FS=y CONFIG_XEN_PLATFORM_PCI=m CONFIG_XEN_GNTDEV=m CONFIG_INPUT_XEN_KBDDEV_FRONTEND=m +CONFIG_XEN_SELFBALLOONING=y +CONFIG_XEN_PCIDEV_BACKEND=m CONFIG_MTD_ESB2ROM=m CONFIG_MTD_CK804XROM=m -CONFIG_MTD_NAND_CAFE=m CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -407,53 +295,34 @@ CONFIG_INTEL_IOATDMA=m CONFIG_SENSORS_I5K_AMB=m CONFIG_SENSORS_FAM15H_POWER=m CONFIG_SENSORS_ACPI_POWER=m +CONFIG_SENSORS_PKGTEMP=m # CONFIG_CPA_DEBUG is not set -# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set CONFIG_HP_WATCHDOG=m CONFIG_NV_TCO=m CONFIG_SP5100_TCO=m -CONFIG_OLPC=y -CONFIG_OLPC_OPENFIRMWARE=y -CONFIG_BATTERY_OLPC=y -CONFIG_MOUSE_PS2_OLPC=y - -# staging -# CONFIG_FB_OLPC_DCON is not set - CONFIG_STRICT_DEVMEM=y # CONFIG_NO_BOOTMEM is not set # CONFIG_MEMTEST is not set # CONFIG_MAXSMP is not set -CONFIG_MTRR_SANITIZER=y -CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=1 -CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1 + CONFIG_SYSPROF_TRACER=y -# CONFIG_X86_VERBOSE_BOOTUP is not set -# CONFIG_MMIOTRACE_TEST is not set - -# CONFIG_DEBUG_PER_CPU_MAPS is not set - CONFIG_HP_ILO=m CONFIG_BACKLIGHT_APPLE=m CONFIG_OPROFILE_IBS=y -CONFIG_MICROCODE_INTEL=y -CONFIG_MICROCODE_AMD=y # CONFIG_X86_CHECK_BIOS_CORRUPTION is not set CONFIG_X86_RESERVE_LOW_64K=y # CONFIG_CMDLINE_BOOL is not set -CONFIG_PANASONIC_LAPTOP=m - CONFIG_X86_PTRACE_BTS=y CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y @@ -461,47 +330,28 @@ CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y CONFIG_POWER_TRACER=y CONFIG_HW_BRANCH_TRACER=y -# CONFIG_SPARSE_IRQ is not set - -CONFIG_RCU_FANOUT=32 - # CONFIG_IOMMU_STRESS is not set CONFIG_PERF_COUNTERS=y CONFIG_PERF_EVENTS=y CONFIG_EVENT_PROFILE=y +CONFIG_X86_MCE=y CONFIG_X86_MCE_INTEL=y CONFIG_X86_MCE_AMD=y -# CONFIG_X86_ANCIENT_MCE is not set # CONFIG_X86_MCE_INJECT is not set -# CONFIG_X86_MRST is not set CONFIG_SFI=y CONFIG_INPUT_WINBOND_CIR=m CONFIG_I2C_SCMI=m -CONFIG_I2C_PXA=m CONFIG_SBC_FITPC2_WATCHDOG=m -CONFIG_EDAC_I3200=m -CONFIG_EDAC_DECODE_MCE=m - -# CONFIG_GPIO_LANGWELL is not set - -# CONFIG_INTEL_TXT is not set - -CONFIG_CS5535_MFGPT=m -CONFIG_GEODE_WDT=m -CONFIG_CS5535_CLOCK_EVENT_SRC=m - -CONFIG_LEDS_INTEL_SS4200=m CONFIG_X86_DECODER_SELFTEST=y CONFIG_ACPI_CMPC=m CONFIG_MSI_WMI=m CONFIG_TOSHIBA_BT_RFKILL=m -CONFIG_SAMSUNG_LAPTOP=m CONFIG_VGA_SWITCHEROO=y CONFIG_LPC_SCH=m @@ -510,46 +360,39 @@ CONFIG_PCI_CNB20LE_QUIRK=y CONFIG_ACPI_EC_DEBUGFS=m # CONFIG_ACPI_APEI_ERST_DEBUG is not set +# CONFIG_ACPI_QUICKSTART is not set +CONFIG_IDEAPAD_ACPI=m + CONFIG_INTEL_IDLE=y + # CONFIG_TOUCHSCREEN_CY8CTMG110 is not set -CONFIG_SENSORS_PKGTEMP=m CONFIG_F71808E_WDT=m CONFIG_HPWDT_NMI_DECODING=y # CONFIG_MFD_TPS6586X is not set # CONFIG_INTEL_MID_DMAC is not set CONFIG_PCH_DMA=m -# CONFIG_ACPI_QUICKSTART is not set -CONFIG_IDEAPAD_ACPI=m CONFIG_INTEL_IPS=m # CONFIG_IBM_RTL is not set -CONFIG_OLPC_XO1=m -CONFIG_XO1_RFKILL=m CONFIG_VIDEO_VIA_CAMERA=m -CONFIG_EDAC_MCE_INJ=m CONFIG_IRQ_TIME_ACCOUNTING=y CONFIG_X86_RESERVE_LOW=64 CONFIG_PCH_GBE=m CONFIG_PCH_PHUB=m -CONFIG_JUMP_LABEL=y - -CONFIG_X86_32_IRIS=m - CONFIG_TRANSPARENT_HUGEPAGE=y CONFIG_CRYPTO_AES_NI_INTEL=y -CONFIG_CRYPTO_AES_586=y - -CONFIG_MTD_OF_PARTS=m -CONFIG_MTD_PHYSMAP_OF=m -CONFIG_PROC_DEVICETREE=y -CONFIG_SERIAL_OF_PLATFORM=m -CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m -# CONFIG_MMC_SDHCI_OF is not set CONFIG_HP_ACCEL=m # CONFIG_RAPIDIO is not set + +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_MCP23S08 is not set + +CONFIG_SCHED_SMT=y +CONFIG_CC_STACKPROTECTOR=y +CONFIG_RELOCATABLE=y diff --git a/config-x86_64-generic b/config-x86_64-generic index 85da0d997..15277d705 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -1,229 +1,59 @@ CONFIG_64BIT=y -CONFIG_UID16=y -# CONFIG_KERNEL_LZMA is not set # CONFIG_MK8 is not set # CONFIG_MPSC is not set CONFIG_GENERIC_CPU=y -CONFIG_X86_EXTENDED_PLATFORM=y + # CONFIG_X86_VSMP is not set # CONFIG_X86_UV is not set -CONFIG_X86_MSR=y -CONFIG_X86_CPUID=y -CONFIG_MTRR=y CONFIG_NUMA=y CONFIG_K8_NUMA=y CONFIG_AMD_NUMA=y CONFIG_X86_64_ACPI_NUMA=y # CONFIG_NUMA_EMU is not set + CONFIG_NR_CPUS=512 -CONFIG_X86_POWERNOW_K8=y -CONFIG_X86_P4_CLOCKMOD=y +CONFIG_PHYSICAL_START=0x1000000 + CONFIG_IA32_EMULATION=y # CONFIG_IA32_AOUT is not set + +CONFIG_AMD_IOMMU=y +CONFIG_AMD_IOMMU_STATS=y # CONFIG_IOMMU_DEBUG is not set -CONFIG_DEBUG_RODATA=y -CONFIG_MICROCODE=m CONFIG_SWIOTLB=y CONFIG_CALGARY_IOMMU=y CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y -CONFIG_X86_PM_TIMER=y -CONFIG_EDD=m -# CONFIG_EDD_OFF is not set -CONFIG_PCI_BIOS=y -CONFIG_PCI_MMCONFIG=y -CONFIG_DMAR=y -CONFIG_DMAR_BROKEN_GFX_WA=y -CONFIG_DMAR_FLOPPY_WA=y -CONFIG_DMAR_DEFAULT_ON=y CONFIG_KEXEC_JUMP=y -CONFIG_EFI=y -CONFIG_EFI_VARS=y -CONFIG_EFI_PCDP=y -CONFIG_FB_EFI=y - -CONFIG_SCSI_ADVANSYS=m - -CONFIG_SECCOMP=y - -CONFIG_CAPI_EICON=y - -CONFIG_GENERIC_ISA_DMA=y -CONFIG_SCHED_SMT=y -CONFIG_SUSPEND=y -CONFIG_HIBERNATION=y -CONFIG_PM_STD_PARTITION="" - -# CONFIG_X86_SPEEDSTEP_CENTRINO is not set -CONFIG_X86_PCC_CPUFREQ=y -CONFIG_X86_ACPI_CPUFREQ=y - -CONFIG_ACPI=y -CONFIG_ACPI_AC=y -# CONFIG_ACPI_ASUS is not set -CONFIG_ACPI_PROCFS_POWER=y -CONFIG_ACPI_SYSFS_POWER=y -CONFIG_ACPI_BATTERY=y CONFIG_ACPI_BLACKLIST_YEAR=0 -CONFIG_ACPI_BUTTON=y -CONFIG_ACPI_CONTAINER=m -CONFIG_ACPI_DOCK=y -CONFIG_ACPI_FAN=y CONFIG_ACPI_HOTPLUG_MEMORY=m -CONFIG_ACPI_NUMA=y -CONFIG_ACPI_PROCESSOR=y -CONFIG_ACPI_PROCFS=y -CONFIG_ACPI_SBS=m -CONFIG_ACPI_SLEEP=y -CONFIG_ACPI_THERMAL=y -CONFIG_ACPI_TOSHIBA=m -CONFIG_ACPI_POWER=y -CONFIG_ACPI_VIDEO=m -# CONFIG_ACPI_PROC_EVENT is not set -CONFIG_ACPI_POWER_METER=m -CONFIG_ACPI_PROCESSOR_AGGREGATOR=m -CONFIG_ACPI_HED=m -CONFIG_ACPI_APEI=y -CONFIG_ACPI_APEI_PCIEAER=y -CONFIG_ACPI_APEI_GHES=m -# CONFIG_ACPI_APEI_EINJ is not set -CONFIG_ACPI_IPMI=m -CONFIG_ACPI_CUSTOM_METHOD=m - -CONFIG_X86_PLATFORM_DEVICES=y -CONFIG_ASUS_LAPTOP=m -CONFIG_COMPAL_LAPTOP=m -CONFIG_FUJITSU_LAPTOP=m -# CONFIG_FUJITSU_LAPTOP_DEBUG is not set -CONFIG_MSI_LAPTOP=m -CONFIG_SONY_LAPTOP=m -CONFIG_SONYPI_COMPAT=y -CONFIG_EEEPC_LAPTOP=m -CONFIG_EEEPC_WMI=m -CONFIG_DELL_LAPTOP=m -CONFIG_ACPI_WMI=m -CONFIG_ACER_WMI=m -CONFIG_ACERHDF=m -CONFIG_HP_WMI=m -CONFIG_DELL_WMI=m -CONFIG_DELL_WMI_AIO=m -CONFIG_ASUS_WMI=m -CONFIG_ASUS_NB_WMI=m -# CONFIG_XO15_EBOOK is not set -CONFIG_INTEL_OAKTRAIL=m # CONFIG_INTEL_SCU_IPC is not set -# CONFIG_TOUCHSCREEN_INTEL_MID is not set - -CONFIG_THINKPAD_ACPI=m -# CONFIG_THINKPAD_ACPI_DEBUG is not set -# CONFIG_THINKPAD_ACPI_DEBUGFACILITIES is not set -CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y -CONFIG_THINKPAD_ACPI_VIDEO=y -CONFIG_THINKPAD_ACPI_ALSA_SUPPORT=y -# CONFIG_THINKPAD_ACPI_UNSAFE_LEDS is not set - -CONFIG_HOTPLUG_PCI=y -CONFIG_HOTPLUG_PCI_COMPAQ=m -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -CONFIG_HOTPLUG_PCI_IBM=m -# CONFIG_HOTPLUG_PCI_CPCI is not set # SHPC has half-arsed PCI probing, which makes it load on too many systems CONFIG_HOTPLUG_PCI_SHPC=m -CONFIG_HPET=y -# CONFIG_HPET_MMAP is not set -CONFIG_PM=y - -CONFIG_IPW2100=m -CONFIG_IPW2100_MONITOR=y -CONFIG_IPW2200=m -CONFIG_IPW2200_MONITOR=y -CONFIG_IPW2200_RADIOTAP=y -CONFIG_IPW2200_PROMISCUOUS=y -CONFIG_IPW2200_QOS=y - CONFIG_PNP=y -CONFIG_PNPACPI=y +# Really ? not 32bit only ? CONFIG_BLK_DEV_AMD74XX=y -CONFIG_CRYPTO_DEV_PADLOCK=m -CONFIG_CRYPTO_DEV_PADLOCK_AES=m -CONFIG_CRYPTO_DEV_PADLOCK_SHA=m CONFIG_CRYPTO_AES_X86_64=y -CONFIG_CRYPTO_AES_NI_INTEL=y - CONFIG_CRYPTO_TWOFISH_X86_64=m CONFIG_CRYPTO_SALSA20_X86_64=m - -CONFIG_X86_MCE=y -CONFIG_X86_MCE_INTEL=y -CONFIG_X86_MCE_AMD=y +CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m # CONFIG_I2C_ALI1535 is not set # CONFIG_I2C_ALI1563 is not set # CONFIG_I2C_ALI15X3 is not set -CONFIG_I2C_AMD756=m -CONFIG_I2C_AMD756_S4882=m -CONFIG_I2C_AMD8111=m -CONFIG_I2C_I801=m -CONFIG_I2C_ISCH=m -CONFIG_I2C_NFORCE2_S4985=m -CONFIG_I2C_PIIX4=m # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set -CONFIG_I2C_SIS96X=m -CONFIG_I2C_VIA=m -CONFIG_I2C_VIAPRO=m - -CONFIG_DELL_RBU=m -CONFIG_DCDBAS=m - -CONFIG_NVRAM=y - -CONFIG_EDAC=y -# CONFIG_EDAC_DEBUG is not set -CONFIG_EDAC_MM_EDAC=m -CONFIG_EDAC_AMD76X=m -CONFIG_EDAC_E7XXX=m -CONFIG_EDAC_E752X=m -CONFIG_EDAC_I5000=m -CONFIG_EDAC_I5100=m -CONFIG_EDAC_I5400=m -CONFIG_EDAC_I82875P=m -CONFIG_EDAC_I82860=m -CONFIG_EDAC_I82975X=m -CONFIG_EDAC_R82600=m -CONFIG_EDAC_AMD8131=m -CONFIG_EDAC_AMD8111=m CONFIG_EDAC_AMD64=m # CONFIG_EDAC_AMD64_ERROR_INJECTION is not set -CONFIG_EDAC_DECODE_MCE=m -CONFIG_EDAC_I7CORE=m -CONFIG_EDAC_I3000=m -CONFIG_EDAC_I7300=m -CONFIG_EDAC_X38=m -CONFIG_SCHED_MC=y - -CONFIG_TCG_INFINEON=m - -CONFIG_HW_RANDOM_INTEL=m -CONFIG_HW_RANDOM_AMD=m -CONFIG_HW_RANDOM_VIA=m - -# CONFIG_HW_RANDOM_GEODE is not set - - -CONFIG_DEBUG_STACKOVERFLOW=y -CONFIG_DEBUG_NMI_TIMEOUT=5 - -CONFIG_GPIO_SCH=m # CONFIG_PC8736x_GPIO is not set # CONFIG_DISCONTIGMEM_MANUAL is not set @@ -242,223 +72,46 @@ CONFIG_MEMORY_HOTREMOVE=y # CONFIG_BLK_DEV_CS5530 is not set # CONFIG_BLK_DEV_CS5535 is not set -CONFIG_CC_STACKPROTECTOR=y - CONFIG_SGI_IOC4=m CONFIG_SGI_XP=m CONFIG_SGI_GRU=m # CONFIG_SGI_GRU_DEBUG is not set -# CONFIG_SMSC37B787_WDT is not set -CONFIG_W83697HF_WDT=m - # CONFIG_VIDEO_CAFE_CCIC is not set -CONFIG_MTD_ESB2ROM=m -CONFIG_MTD_CK804XROM=m - -CONFIG_RELOCATABLE=y -CONFIG_MACINTOSH_DRIVERS=y - -CONFIG_CRASH_DUMP=y -CONFIG_PHYSICAL_START=0x1000000 -CONFIG_PROC_VMCORE=y -CONFIG_CRASH=m - -CONFIG_DMIID=y -CONFIG_DMI_SYSFS=y - -CONFIG_ISCSI_IBFT_FIND=y -CONFIG_ISCSI_IBFT=m - - -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_CPU_IDLE=y -# CONFIG_CPU_IDLE_GOV_LADDER is not set -CONFIG_CPU_IDLE_GOV_MENU=y - -CONFIG_VIRTUALIZATION=y -CONFIG_KVM=m -CONFIG_KVM_INTEL=m -CONFIG_KVM_AMD=m - -CONFIG_PARAVIRT_GUEST=y -CONFIG_PARAVIRT=y -# CONFIG_PARAVIRT_DEBUG is not set -# PARAVIRT_SPINLOCKS has a 5% perf hit -# CONFIG_PARAVIRT_SPINLOCKS is not set -CONFIG_KVM_CLOCK=y -CONFIG_KVM_GUEST=y -CONFIG_KVM_MMU_AUDIT=y - -CONFIG_XEN=y -# CONFIG_XEN_DEBUG is not set CONFIG_XEN_MAX_DOMAIN_MEMORY=32 -CONFIG_XEN_BALLOON=y -CONFIG_XEN_SCRUB_PAGES=y -CONFIG_XEN_SAVE_RESTORE=y -CONFIG_HVC_XEN=y -CONFIG_XEN_FBDEV_FRONTEND=y -CONFIG_XEN_KBDDEV_FRONTEND=y -CONFIG_XEN_BLKDEV_FRONTEND=m -CONFIG_XEN_NETDEV_FRONTEND=m -CONFIG_XEN_NETDEV_BACKEND=m -CONFIG_XEN_WDT=m -CONFIG_XEN_GRANT_DEV_ALLOC=m -CONFIG_XEN_PCIDEV_FRONTEND=m -CONFIG_XENFS=m -CONFIG_XEN_COMPAT_XENFS=y +CONFIG_XEN_BALLOON_MEMORY_HOTPLUG=y CONFIG_XEN_DEV_EVTCHN=m CONFIG_XEN_SYS_HYPERVISOR=y -CONFIG_XEN_BACKEND=y -CONFIG_XEN_BLKDEV_BACKEND=m -CONFIG_XEN_GNTDEV=m -CONFIG_XEN_DEBUG_FS=y -CONFIG_XEN_PLATFORM_PCI=m -CONFIG_INPUT_XEN_KBDDEV_FRONTEND=m -CONFIG_DMADEVICES=y -CONFIG_INTEL_IOATDMA=m - -CONFIG_SENSORS_I5K_AMB=m -CONFIG_SENSORS_FAM15H_POWER=m -CONFIG_SENSORS_ACPI_POWER=m - -# CONFIG_COMPAT_VDSO is not set CONFIG_PROVIDE_OHCI1394_DMA_INIT=y -# CONFIG_DEBUG_PER_CPU_MAPS is not set -# CONFIG_CPA_DEBUG is not set - -CONFIG_HP_WATCHDOG=m -CONFIG_NV_TCO=m -CONFIG_SP5100_TCO=m CONFIG_FRAME_WARN=2048 CONFIG_NODES_SHIFT=9 -CONFIG_X86_PAT=y -# FIXME: These should be 32bit only -# CONFIG_FB_N411 is not set -CONFIG_STRICT_DEVMEM=y CONFIG_DIRECT_GBPAGES=y -# CONFIG_NO_BOOTMEM is not set - -# CONFIG_MEMTEST is not set -CONFIG_AMD_IOMMU=y -CONFIG_AMD_IOMMU_STATS=y -# CONFIG_MAXSMP is not set -CONFIG_MTRR_SANITIZER=y -CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=1 -CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1 -CONFIG_SYSPROF_TRACER=y -# CONFIG_X86_VERBOSE_BOOTUP is not set -# CONFIG_MMIOTRACE_TEST is not set - CONFIG_X86_MPPARSE=y -CONFIG_BACKLIGHT_APPLE=m - -CONFIG_OPROFILE_IBS=y -CONFIG_MICROCODE_INTEL=y -CONFIG_MICROCODE_AMD=y - -# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set -CONFIG_X86_RESERVE_LOW_64K=y - -# CONFIG_CMDLINE_BOOL is not set - -CONFIG_PANASONIC_LAPTOP=m - -CONFIG_X86_PTRACE_BTS=y - CONFIG_I7300_IDLE=m CONFIG_INTR_REMAP=y -CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y - -CONFIG_POWER_TRACER=y -CONFIG_HW_BRANCH_TRACER=y - CONFIG_X86_X2APIC=y CONFIG_SPARSE_IRQ=y CONFIG_RCU_FANOUT=64 -# CONFIG_IOMMU_STRESS is not set - -CONFIG_PERF_COUNTERS=y -CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y - -# CONFIG_X86_MCE_INJECT is not set - -CONFIG_SFI=y -CONFIG_INPUT_WINBOND_CIR=m -CONFIG_I2C_SCMI=m -CONFIG_SBC_FITPC2_WATCHDOG=m -CONFIG_EDAC_I3200=m -CONFIG_TOPSTAR_LAPTOP=m CONFIG_INTEL_TXT=y + CONFIG_GPIO_LANGWELL=y CONFIG_FUNCTION_GRAPH_TRACER=y -CONFIG_ACPI_CMPC=m -CONFIG_MSI_WMI=m -CONFIG_TOSHIBA_BT_RFKILL=m -CONFIG_SAMSUNG_LAPTOP=m - -CONFIG_CS5535_MFGPT=m -CONFIG_GEODE_WDT=m -CONFIG_CS5535_CLOCK_EVENT_SRC=m - -CONFIG_X86_DECODER_SELFTEST=y - -CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m - -CONFIG_VGA_SWITCHEROO=y -CONFIG_LPC_SCH=m - CONFIG_I7300_IDLE=m -CONFIG_PCI_CNB20LE_QUIRK=y - -CONFIG_ACPI_EC_DEBUGFS=m -# CONFIG_ACPI_APEI_ERST_DEBUG is not set -CONFIG_INTEL_IDLE=y -# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set -CONFIG_SENSORS_PKGTEMP=m -CONFIG_F71808E_WDT=m -CONFIG_HPWDT_NMI_DECODING=y -# CONFIG_MFD_TPS6586X is not set -# CONFIG_INTEL_MID_DMAC is not set -CONFIG_PCH_DMA=m -# CONFIG_ACPI_QUICKSTART is not set -CONFIG_IDEAPAD_ACPI=m -CONFIG_INTEL_IPS=m -CONFIG_IDEAPAD_LAPTOP=m -# CONFIG_IBM_RTL is not set - -CONFIG_EDAC_MCE_INJ=m -CONFIG_IRQ_TIME_ACCOUNTING=y -CONFIG_X86_RESERVE_LOW=64 - -CONFIG_PCH_GBE=m -CONFIG_PCH_PHUB=m - -CONFIG_VIDEO_VIA_CAMERA=m - -CONFIG_JUMP_LABEL=y - -CONFIG_HP_ILO=m - -CONFIG_TRANSPARENT_HUGEPAGE=y - -CONFIG_HP_ACCEL=m - -# CONFIG_RAPIDIO is not set - CONFIG_BPF_JIT=y + +# Should be 32bit only, but lacks KConfig depends +# CONFIG_XO15_EBOOK is not set + diff --git a/dmar-disable-when-ricoh-multifunction.patch b/dmar-disable-when-ricoh-multifunction.patch index 120730f9e..a4528617e 100644 --- a/dmar-disable-when-ricoh-multifunction.patch +++ b/dmar-disable-when-ricoh-multifunction.patch @@ -9,8 +9,8 @@ Subject: [PATCH] dmar: disable if ricoh multifunction detected diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 4789f8e..5923914 100644 ---- a/drivers/pci/intel-iommu.c -+++ b/drivers/pci/intel-iommu.c +--- a/drivers/iommu/intel-iommu.c ++++ b/drivers/iommu/intel-iommu.c @@ -3784,6 +3784,16 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_g DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt); diff --git a/epoll-fix-spurious-lockdep-warnings.patch b/epoll-fix-spurious-lockdep-warnings.patch index 131796af8..c163a86d7 100644 --- a/epoll-fix-spurious-lockdep-warnings.patch +++ b/epoll-fix-spurious-lockdep-warnings.patch @@ -113,4 +113,4 @@ index f9cfd16..0cb7bc6 100644 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file +More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/fix-cdc-ncm-dma-stack-vars.patch b/fix-cdc-ncm-dma-stack-vars.patch index 7f46a00fe..17b555a85 100644 --- a/fix-cdc-ncm-dma-stack-vars.patch +++ b/fix-cdc-ncm-dma-stack-vars.patch @@ -1,4 +1,4 @@ -commit d072ef23b8ee6bcabc00beff0b5702e704a473cb +commit 05511b61169da2f8dab464df61fa2bb952763a23 Author: Josh Boyer Date: Tue Aug 2 08:09:56 2011 -0400 @@ -13,11 +13,11 @@ Date: Tue Aug 2 08:09:56 2011 -0400 Signed-off-by: Josh Boyer diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c -index fd622a6..96dd386 100644 +index a03336e..f06fb78 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c -@@ -260,23 +260,38 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) - req.wIndex = cpu_to_le16(iface_no); +@@ -228,23 +228,40 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) + if (ctx->rx_max != le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize)) { if (flags & USB_CDC_NCM_NCAP_NTB_INPUT_SIZE) { - struct usb_cdc_ncm_ndp_input_size ndp_in_sz; @@ -28,87 +28,82 @@ index fd622a6..96dd386 100644 + err = -ENOMEM; + goto size_err; + } - - req.wLength = 8; -- ndp_in_sz.dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); -- ndp_in_sz.wNtbInMaxDatagrams = -+ ndp_in_sz->dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); -+ ndp_in_sz->wNtbInMaxDatagrams = - cpu_to_le16(CDC_NCM_DPT_DATAGRAMS_MAX); -- ndp_in_sz.wReserved = 0; -- err = cdc_ncm_do_request(ctx, &req, &ndp_in_sz, 0, NULL, -+ ndp_in_sz->wReserved = 0; -+ err = cdc_ncm_do_request(ctx, &req, ndp_in_sz, 0, NULL, - 1000); ++ + err = usb_control_msg(ctx->udev, + usb_sndctrlpipe(ctx->udev, 0), + USB_CDC_SET_NTB_INPUT_SIZE, + USB_TYPE_CLASS | USB_DIR_OUT + | USB_RECIP_INTERFACE, +- 0, iface_no, &ndp_in_sz, 8, 1000); ++ 0, iface_no, ndp_in_sz, 8, 1000); + kfree(ndp_in_sz); } else { - __le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); + __le32 *dwNtbInMaxSize; -+ dwNtbInMaxSize = kzalloc(sizeof(*dwNtbInMaxSize), GFP_KERNEL); ++ dwNtbInMaxSize = kzalloc(sizeof(*dwNtbInMaxSize), ++ GFP_KERNEL); + if (!dwNtbInMaxSize) { + err = -ENOMEM; + goto size_err; + } + *dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); - - req.wLength = 4; -- err = cdc_ncm_do_request(ctx, &req, &dwNtbInMaxSize, 0, -+ err = cdc_ncm_do_request(ctx, &req, dwNtbInMaxSize, 0, - NULL, 1000); ++ + err = usb_control_msg(ctx->udev, + usb_sndctrlpipe(ctx->udev, 0), + USB_CDC_SET_NTB_INPUT_SIZE, + USB_TYPE_CLASS | USB_DIR_OUT + | USB_RECIP_INTERFACE, +- 0, iface_no, &dwNtbInMaxSize, 4, 1000); ++ 0, iface_no, dwNtbInMaxSize, 4, 1000); + kfree(dwNtbInMaxSize); } - +- +size_err: - if (err) + if (err < 0) pr_debug("Setting NTB Input Size failed\n"); } -@@ -362,9 +377,15 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) +@@ -325,19 +342,29 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) /* set Max Datagram Size (MTU) */ if (flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE) { - __le16 max_datagram_size; + __le16 *max_datagram_size; u16 eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize); - -+ max_datagram_size = kzalloc(sizeof(*max_datagram_size), GFP_KERNEL); ++ ++ max_datagram_size = kzalloc(sizeof(*max_datagram_size), ++ GFP_KERNEL); + if (!max_datagram_size) { + err = -ENOMEM; + goto max_dgram_err; + } + - req.bmRequestType = USB_TYPE_CLASS | USB_DIR_IN | - USB_RECIP_INTERFACE; - req.bNotificationType = USB_CDC_GET_MAX_DATAGRAM_SIZE; -@@ -372,13 +393,15 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) - req.wIndex = cpu_to_le16(iface_no); - req.wLength = cpu_to_le16(2); - -- err = cdc_ncm_do_request(ctx, &req, &max_datagram_size, 0, NULL, -+ err = cdc_ncm_do_request(ctx, &req, max_datagram_size, 0, NULL, - 1000); -+ - if (err) { + err = usb_control_msg(ctx->udev, usb_rcvctrlpipe(ctx->udev, 0), + USB_CDC_GET_MAX_DATAGRAM_SIZE, + USB_TYPE_CLASS | USB_DIR_IN + | USB_RECIP_INTERFACE, +- 0, iface_no, &max_datagram_size, ++ 0, iface_no, max_datagram_size, + 2, 1000); + if (err < 0) { pr_debug("GET_MAX_DATAGRAM_SIZE failed, use size=%u\n", CDC_NCM_MIN_DATAGRAM_SIZE); + kfree(max_datagram_size); } else { - ctx->max_datagram_size = le16_to_cpu(max_datagram_size); -+ ctx->max_datagram_size = le16_to_cpu(*max_datagram_size); ++ ctx->max_datagram_size = ++ le16_to_cpu(*max_datagram_size); /* Check Eth descriptor value */ if (eth_max_sz < CDC_NCM_MAX_DATAGRAM_SIZE) { if (ctx->max_datagram_size > eth_max_sz) -@@ -401,10 +424,12 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) - req.wValue = 0; - req.wIndex = cpu_to_le16(iface_no); - req.wLength = 2; -- max_datagram_size = cpu_to_le16(ctx->max_datagram_size); -+ *max_datagram_size = cpu_to_le16(ctx->max_datagram_size); - -- err = cdc_ncm_do_request(ctx, &req, &max_datagram_size, -+ err = cdc_ncm_do_request(ctx, &req, max_datagram_size, - 0, NULL, 1000); +@@ -360,8 +387,10 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) + USB_TYPE_CLASS | USB_DIR_OUT + | USB_RECIP_INTERFACE, + 0, +- iface_no, &max_datagram_size, ++ iface_no, max_datagram_size, + 2, 1000); + kfree(max_datagram_size); +max_dgram_err: - if (err) + if (err < 0) pr_debug("SET_MAX_DATAGRAM_SIZE failed\n"); } diff --git a/hda_intel-prealloc-4mb-dmabuffer.patch b/hda_intel-prealloc-4mb-dmabuffer.patch deleted file mode 100644 index 36e6aca4f..000000000 --- a/hda_intel-prealloc-4mb-dmabuffer.patch +++ /dev/null @@ -1,47 +0,0 @@ -From c69fcbd1f60b0842f7c1ad2c95692ffd19c4932b Mon Sep 17 00:00:00 2001 -From: Kyle McMartin -Date: Mon, 29 Mar 2010 23:56:08 -0400 -Subject: hda_intel-prealloc-4mb-dmabuffer - ---- - sound/pci/hda/hda_intel.c | 14 +++++++++++++- - 1 files changed, 13 insertions(+), 1 deletions(-) - -diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c -index 4bb9067..37db515 100644 ---- a/sound/pci/hda/hda_intel.c -+++ b/sound/pci/hda/hda_intel.c -@@ -1986,6 +1986,7 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, - struct azx_pcm *apcm; - int pcm_dev = cpcm->device; - int s, err; -+ size_t prealloc_min = 64*1024; /* 64KB */ - - if (pcm_dev >= HDA_MAX_PCMS) { - snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", -@@ -2019,10 +2020,21 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, - if (cpcm->stream[s].substreams) - snd_pcm_set_ops(pcm, s, &azx_pcm_ops); - } -+ - /* buffer pre-allocation */ -+ -+ /* subtle, don't allocate a big buffer for modems... -+ * also, don't just test 32BIT_MASK, since azx supports -+ * 64-bit DMA in some cases. -+ */ -+ /* lennart wants a 2.2MB buffer for 2sec of 48khz */ -+ if (pcm->dev_class == SNDRV_PCM_CLASS_GENERIC && -+ chip->pci->dma_mask >= DMA_32BIT_MASK) -+ prealloc_min = 4 * 1024 * 1024; /* 4MB */ -+ - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci), -- 1024 * 64, 32 * 1024 * 1024); -+ prealloc_min, 32 * 1024 * 1024); - return 0; - } - --- -1.7.0.1 - diff --git a/hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch b/hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch deleted file mode 100644 index c81bf91d1..000000000 --- a/hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch +++ /dev/null @@ -1,315 +0,0 @@ -From 6596528e391ad978a6a120142cba97a1d7324cb6 Mon Sep 17 00:00:00 2001 -From: Seth Forshee -Date: Mon, 18 Jul 2011 08:06:23 -0700 -Subject: [PATCH] hfsplus: ensure bio requests are not smaller than the - hardware sectors - -Currently all bio requests are 512 bytes, which may fail for media -whose physical sector size is larger than this. Ensure these -requests are not smaller than the block device logical block size. - -BugLink: http://bugs.launchpad.net/bugs/734883 -Signed-off-by: Seth Forshee -Signed-off-by: Christoph Hellwig ---- - fs/hfsplus/hfsplus_fs.h | 16 ++++++++- - fs/hfsplus/part_tbl.c | 32 ++++++++++-------- - fs/hfsplus/super.c | 12 +++--- - fs/hfsplus/wrapper.c | 83 +++++++++++++++++++++++++++++++++++----------- - 4 files changed, 101 insertions(+), 42 deletions(-) - -diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h -index 0bebf74..81dfd1e 100644 ---- a/fs/hfsplus/hfsplus_fs.h -+++ b/fs/hfsplus/hfsplus_fs.h -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include "hfsplus_raw.h" - - #define DBG_BNODE_REFS 0x00000001 -@@ -110,7 +111,9 @@ struct hfsplus_vh; - struct hfs_btree; - - struct hfsplus_sb_info { -+ void *s_vhdr_buf; - struct hfsplus_vh *s_vhdr; -+ void *s_backup_vhdr_buf; - struct hfsplus_vh *s_backup_vhdr; - struct hfs_btree *ext_tree; - struct hfs_btree *cat_tree; -@@ -258,6 +261,15 @@ struct hfsplus_readdir_data { - struct hfsplus_cat_key key; - }; - -+/* -+ * Find minimum acceptible I/O size for an hfsplus sb. -+ */ -+static inline unsigned short hfsplus_min_io_size(struct super_block *sb) -+{ -+ return max_t(unsigned short, bdev_logical_block_size(sb->s_bdev), -+ HFSPLUS_SECTOR_SIZE); -+} -+ - #define hfs_btree_open hfsplus_btree_open - #define hfs_btree_close hfsplus_btree_close - #define hfs_btree_write hfsplus_btree_write -@@ -436,8 +448,8 @@ int hfsplus_compare_dentry(const struct dentry *parent, - /* wrapper.c */ - int hfsplus_read_wrapper(struct super_block *); - int hfs_part_find(struct super_block *, sector_t *, sector_t *); --int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, -- void *data, int rw); -+int hfsplus_submit_bio(struct super_block *sb, sector_t sector, -+ void *buf, void **data, int rw); - - /* time macros */ - #define __hfsp_mt2ut(t) (be32_to_cpu(t) - 2082844800U) -diff --git a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c -index 40ad88c..eb355d8 100644 ---- a/fs/hfsplus/part_tbl.c -+++ b/fs/hfsplus/part_tbl.c -@@ -88,11 +88,12 @@ static int hfs_parse_old_pmap(struct super_block *sb, struct old_pmap *pm, - return -ENOENT; - } - --static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm, -- sector_t *part_start, sector_t *part_size) -+static int hfs_parse_new_pmap(struct super_block *sb, void *buf, -+ struct new_pmap *pm, sector_t *part_start, sector_t *part_size) - { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); - int size = be32_to_cpu(pm->pmMapBlkCnt); -+ int buf_size = hfsplus_min_io_size(sb); - int res; - int i = 0; - -@@ -107,11 +108,14 @@ static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm, - if (++i >= size) - return -ENOENT; - -- res = hfsplus_submit_bio(sb->s_bdev, -- *part_start + HFS_PMAP_BLK + i, -- pm, READ); -- if (res) -- return res; -+ pm = (struct new_pmap *)((u8 *)pm + HFSPLUS_SECTOR_SIZE); -+ if ((u8 *)pm - (u8 *)buf >= buf_size) { -+ res = hfsplus_submit_bio(sb, -+ *part_start + HFS_PMAP_BLK + i, -+ buf, (void **)&pm, READ); -+ if (res) -+ return res; -+ } - } while (pm->pmSig == cpu_to_be16(HFS_NEW_PMAP_MAGIC)); - - return -ENOENT; -@@ -124,15 +128,15 @@ static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm, - int hfs_part_find(struct super_block *sb, - sector_t *part_start, sector_t *part_size) - { -- void *data; -+ void *buf, *data; - int res; - -- data = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL); -- if (!data) -+ buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); -+ if (!buf) - return -ENOMEM; - -- res = hfsplus_submit_bio(sb->s_bdev, *part_start + HFS_PMAP_BLK, -- data, READ); -+ res = hfsplus_submit_bio(sb, *part_start + HFS_PMAP_BLK, -+ buf, &data, READ); - if (res) - goto out; - -@@ -141,13 +145,13 @@ int hfs_part_find(struct super_block *sb, - res = hfs_parse_old_pmap(sb, data, part_start, part_size); - break; - case HFS_NEW_PMAP_MAGIC: -- res = hfs_parse_new_pmap(sb, data, part_start, part_size); -+ res = hfs_parse_new_pmap(sb, buf, data, part_start, part_size); - break; - default: - res = -ENOENT; - break; - } - out: -- kfree(data); -+ kfree(buf); - return res; - } -diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c -index 84f56e1..c106ca2 100644 ---- a/fs/hfsplus/super.c -+++ b/fs/hfsplus/super.c -@@ -203,17 +203,17 @@ int hfsplus_sync_fs(struct super_block *sb, int wait) - write_backup = 1; - } - -- error2 = hfsplus_submit_bio(sb->s_bdev, -+ error2 = hfsplus_submit_bio(sb, - sbi->part_start + HFSPLUS_VOLHEAD_SECTOR, -- sbi->s_vhdr, WRITE_SYNC); -+ sbi->s_vhdr_buf, NULL, WRITE_SYNC); - if (!error) - error = error2; - if (!write_backup) - goto out; - -- error2 = hfsplus_submit_bio(sb->s_bdev, -+ error2 = hfsplus_submit_bio(sb, - sbi->part_start + sbi->sect_count - 2, -- sbi->s_backup_vhdr, WRITE_SYNC); -+ sbi->s_backup_vhdr_buf, NULL, WRITE_SYNC); - if (!error) - error2 = error; - out: -@@ -257,8 +257,8 @@ static void hfsplus_put_super(struct super_block *sb) - hfs_btree_close(sbi->ext_tree); - iput(sbi->alloc_file); - iput(sbi->hidden_dir); -- kfree(sbi->s_vhdr); -- kfree(sbi->s_backup_vhdr); -+ kfree(sbi->s_vhdr_buf); -+ kfree(sbi->s_backup_vhdr_buf); - unload_nls(sbi->nls); - kfree(sb->s_fs_info); - sb->s_fs_info = NULL; -diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c -index 2f933e8..10e515a 100644 ---- a/fs/hfsplus/wrapper.c -+++ b/fs/hfsplus/wrapper.c -@@ -31,25 +31,67 @@ static void hfsplus_end_io_sync(struct bio *bio, int err) - complete(bio->bi_private); - } - --int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, -- void *data, int rw) -+/* -+ * hfsplus_submit_bio - Perfrom block I/O -+ * @sb: super block of volume for I/O -+ * @sector: block to read or write, for blocks of HFSPLUS_SECTOR_SIZE bytes -+ * @buf: buffer for I/O -+ * @data: output pointer for location of requested data -+ * @rw: direction of I/O -+ * -+ * The unit of I/O is hfsplus_min_io_size(sb), which may be bigger than -+ * HFSPLUS_SECTOR_SIZE, and @buf must be sized accordingly. On reads -+ * @data will return a pointer to the start of the requested sector, -+ * which may not be the same location as @buf. -+ * -+ * If @sector is not aligned to the bdev logical block size it will -+ * be rounded down. For writes this means that @buf should contain data -+ * that starts at the rounded-down address. As long as the data was -+ * read using hfsplus_submit_bio() and the same buffer is used things -+ * will work correctly. -+ */ -+int hfsplus_submit_bio(struct super_block *sb, sector_t sector, -+ void *buf, void **data, int rw) - { - DECLARE_COMPLETION_ONSTACK(wait); - struct bio *bio; - int ret = 0; -+ unsigned int io_size; -+ loff_t start; -+ int offset; -+ -+ /* -+ * Align sector to hardware sector size and find offset. We -+ * assume that io_size is a power of two, which _should_ -+ * be true. -+ */ -+ io_size = hfsplus_min_io_size(sb); -+ start = (loff_t)sector << HFSPLUS_SECTOR_SHIFT; -+ offset = start & (io_size - 1); -+ sector &= ~((io_size >> HFSPLUS_SECTOR_SHIFT) - 1); - - bio = bio_alloc(GFP_NOIO, 1); - bio->bi_sector = sector; -- bio->bi_bdev = bdev; -+ bio->bi_bdev = sb->s_bdev; - bio->bi_end_io = hfsplus_end_io_sync; - bio->bi_private = &wait; - -- /* -- * We always submit one sector at a time, so bio_add_page must not fail. -- */ -- if (bio_add_page(bio, virt_to_page(data), HFSPLUS_SECTOR_SIZE, -- offset_in_page(data)) != HFSPLUS_SECTOR_SIZE) -- BUG(); -+ if (!(rw & WRITE) && data) -+ *data = (u8 *)buf + offset; -+ -+ while (io_size > 0) { -+ unsigned int page_offset = offset_in_page(buf); -+ unsigned int len = min_t(unsigned int, PAGE_SIZE - page_offset, -+ io_size); -+ -+ ret = bio_add_page(bio, virt_to_page(buf), len, page_offset); -+ if (ret != len) { -+ ret = -EIO; -+ goto out; -+ } -+ io_size -= len; -+ buf = (u8 *)buf + len; -+ } - - submit_bio(rw, bio); - wait_for_completion(&wait); -@@ -57,8 +99,9 @@ int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, - if (!bio_flagged(bio, BIO_UPTODATE)) - ret = -EIO; - -+out: - bio_put(bio); -- return ret; -+ return ret < 0 ? ret : 0; - } - - static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd) -@@ -143,17 +186,17 @@ int hfsplus_read_wrapper(struct super_block *sb) - goto out; - - error = -ENOMEM; -- sbi->s_vhdr = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL); -- if (!sbi->s_vhdr) -+ sbi->s_vhdr_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); -+ if (!sbi->s_vhdr_buf) - goto out; -- sbi->s_backup_vhdr = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL); -- if (!sbi->s_backup_vhdr) -+ sbi->s_backup_vhdr_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); -+ if (!sbi->s_backup_vhdr_buf) - goto out_free_vhdr; - - reread: -- error = hfsplus_submit_bio(sb->s_bdev, -- part_start + HFSPLUS_VOLHEAD_SECTOR, -- sbi->s_vhdr, READ); -+ error = hfsplus_submit_bio(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, -+ sbi->s_vhdr_buf, (void **)&sbi->s_vhdr, -+ READ); - if (error) - goto out_free_backup_vhdr; - -@@ -183,9 +226,9 @@ reread: - goto reread; - } - -- error = hfsplus_submit_bio(sb->s_bdev, -- part_start + part_size - 2, -- sbi->s_backup_vhdr, READ); -+ error = hfsplus_submit_bio(sb, part_start + part_size - 2, -+ sbi->s_backup_vhdr_buf, -+ (void **)&sbi->s_backup_vhdr, READ); - if (error) - goto out_free_backup_vhdr; - --- -1.7.6 - diff --git a/kernel.spec b/kernel.spec index 1050a983c..30e182916 100644 --- a/kernel.spec +++ b/kernel.spec @@ -6,7 +6,7 @@ Summary: The Linux kernel # For a stable, released kernel, released_kernel should be 1. For rawhide # and/or a kernel built from an rc or git snapshot, released_kernel should # be 0. -%global released_kernel 1 +%global released_kernel 0 # Save original buildid for later if it's defined %if 0%{?buildid:1} @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 6 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -63,7 +63,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 1 +%define stable_update 0 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -80,10 +80,9 @@ Summary: The Linux kernel ## The not-released-kernel case ## %else # The next upstream release sublevel (base_sublevel+1) -# % define upstream_sublevel %(echo $((%{base_sublevel} + 1))) -%define upstream_sublevel 0 +%define upstream_sublevel %(echo $((%{base_sublevel} + 1))) # The rc snapshot level -%define rcrev 0 +%define rcrev 2 # The git snapshot level %define gitrev 0 # Set rpm version accordingly @@ -544,6 +543,7 @@ Source24: config-rhel-generic Source30: config-x86-generic Source31: config-i686-PAE +Source32: config-x86-32-generic Source40: config-x86_64-generic @@ -641,8 +641,6 @@ Patch470: die-floppy-die.patch Patch510: linux-2.6-silence-noise.patch Patch530: linux-2.6-silence-fbcon-logo.patch -Patch610: hda_intel-prealloc-4mb-dmabuffer.patch - Patch700: linux-2.6-e1000-ich9-montevina.patch Patch800: linux-2.6-crash-driver.patch @@ -684,14 +682,14 @@ Patch12010: add-appleir-usb-driver.patch Patch12016: disable-i8042-check-on-apple-mac.patch -Patch12020: linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch - Patch12021: udlfb-bind-framebuffer-to-interface.patch Patch12022: fix-cdc-ncm-dma-stack-vars.patch Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch -Patch12024: block-stray-block-put-after-teardown.patch -Patch12025: usb-add-quirk-for-logitech-webcams.patch +Patch12024: epoll-fix-spurious-lockdep-warnings.patch +Patch12025: rcu-avoid-just-onlined-cpu-resched.patch +Patch12026: block-stray-block-put-after-teardown.patch +Patch12027: usb-add-quirk-for-logitech-webcams.patch # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch @@ -700,9 +698,6 @@ Patch12205: runtime_pm_fixups.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch -Patch13001: epoll-fix-spurious-lockdep-warnings.patch -Patch13002: hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch - Patch13003: efi-dont-map-boot-services-on-32bit.patch Patch20000: utrace.patch @@ -1209,11 +1204,9 @@ ApplyPatch linux-2.6-defaults-aspm.patch # ACPI # ALSA -ApplyPatch hda_intel-prealloc-4mb-dmabuffer.patch # Networking -ApplyPatch linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch # Misc fixes # The input layer spews crap no-one cares about. @@ -1276,6 +1269,8 @@ ApplyPatch add-appleir-usb-driver.patch ApplyPatch udlfb-bind-framebuffer-to-interface.patch ApplyPatch fix-cdc-ncm-dma-stack-vars.patch ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch +ApplyPatch epoll-fix-spurious-lockdep-warnings.patch +ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch ApplyPatch block-stray-block-put-after-teardown.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch @@ -1288,9 +1283,6 @@ ApplyPatch usb-add-quirk-for-logitech-webcams.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch -ApplyPatch epoll-fix-spurious-lockdep-warnings.patch -ApplyPatch hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch - ApplyPatch efi-dont-map-boot-services-on-32bit.patch # utrace. @@ -1304,6 +1296,7 @@ ApplyPatch utrace.patch chmod +x scripts/checkpatch.pl +# This Prevents scripts/setlocalversion from mucking with our version numbers. touch .scmversion # only deal with configs if we are going to build for the arch diff --git a/linux-2.6-crash-driver.patch b/linux-2.6-crash-driver.patch index b8377d321..239f0f6a0 100644 --- a/linux-2.6-crash-driver.patch +++ b/linux-2.6-crash-driver.patch @@ -1,17 +1,17 @@ -From df42d15cd28f468ecd4c30465b98a53cce90617c Mon Sep 17 00:00:00 2001 +From f72d640713d01b3b704c6e84ab49b62f19fc9c22 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Tue, 30 Mar 2010 00:16:25 -0400 -Subject: dev-crash-driver.patch +Subject: [PATCH] dev-crash-driver.patch --- arch/ia64/include/asm/crash.h | 90 +++++++++++++++++++++++++++++ arch/ia64/kernel/ia64_ksyms.c | 3 + arch/x86/include/asm/crash.h | 75 ++++++++++++++++++++++++ arch/x86/mm/ioremap.c | 2 + - drivers/char/Kconfig | 2 + + drivers/char/Kconfig | 3 + drivers/char/Makefile | 2 + drivers/char/crash.c | 128 +++++++++++++++++++++++++++++++++++++++++ - 7 files changed, 302 insertions(+), 0 deletions(-) + 7 files changed, 303 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/include/asm/crash.h create mode 100644 arch/x86/include/asm/crash.h create mode 100644 drivers/char/crash.c @@ -208,7 +208,7 @@ index 0000000..dfcc006 + +#endif /* _ASM_I386_CRASH_H */ diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c -index 5eb1ba7..3e525d2 100644 +index be1ef57..ac659f7 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -24,6 +24,8 @@ @@ -220,6 +220,30 @@ index 5eb1ba7..3e525d2 100644 /* * Fix up the linear direct mapping of the kernel to avoid cache attribute * conflicts. +diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig +index 423fd56..e04a561 100644 +--- a/drivers/char/Kconfig ++++ b/drivers/char/Kconfig +@@ -4,6 +4,9 @@ + + menu "Character devices" + ++config CRASH ++ tristate "Crash Utility memory driver" ++ + source "drivers/tty/Kconfig" + + config DEVKMEM +diff --git a/drivers/char/Makefile b/drivers/char/Makefile +index 32762ba..3d5d525 100644 +--- a/drivers/char/Makefile ++++ b/drivers/char/Makefile +@@ -65,3 +65,5 @@ obj-$(CONFIG_JS_RTC) += js-rtc.o + js-rtc-y = rtc.o + + obj-$(CONFIG_TILE_SROM) += tile-srom.o ++ ++obj-$(CONFIG_CRASH) += crash.o diff --git a/drivers/char/crash.c b/drivers/char/crash.c new file mode 100644 index 0000000..e5437de @@ -354,29 +378,6 @@ index 0000000..e5437de +module_exit(crash_cleanup_module); + +MODULE_LICENSE("GPL"); +-- +1.7.6 -diff --git a/drivers/char/Makefile b/drivers/char/Makefile -index ba53ec9..6588b33 100644 ---- a/drivers/char/Makefile -+++ b/drivers/char/Makefile -@@ -98,3 +98,5 @@ obj-$(CONFIG_RAMOOPS) += ramoops.o - - obj-$(CONFIG_JS_RTC) += js-rtc.o - js-rtc-y = rtc.o -+ -+obj-$(CONFIG_CRASH) += crash.o - -diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig -index 04f8b2d..e8fb997 100644 ---- a/drivers/char/Kconfig -+++ b/drivers/char/Kconfig -@@ -4,6 +4,9 @@ - - menu "Character devices" - -+config CRASH -+ tristate "Crash Utility memory driver" -+ - source "drivers/tty/Kconfig" - - config DEVKMEM diff --git a/linux-2.6-intel-iommu-igfx.patch b/linux-2.6-intel-iommu-igfx.patch index 44fd14186..b2f8f19e3 100644 --- a/linux-2.6-intel-iommu-igfx.patch +++ b/linux-2.6-intel-iommu-igfx.patch @@ -43,8 +43,8 @@ index e7848a0..9914485 100644 for io virtual address below 32 bit forcing dual diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 4173125..8f36786 100644 ---- a/drivers/pci/intel-iommu.c -+++ b/drivers/pci/intel-iommu.c +--- a/drivers/iommu/intel-iommu.c ++++ b/drivers/iommu/intel-iommu.c @@ -340,7 +340,8 @@ int dmar_disabled = 0; int dmar_disabled = 1; #endif /*CONFIG_DMAR_DEFAULT_ON*/ diff --git a/linux-2.6-silence-noise.patch b/linux-2.6-silence-noise.patch index 8aba3cdab..1e4d7c57f 100644 --- a/linux-2.6-silence-noise.patch +++ b/linux-2.6-silence-noise.patch @@ -46,8 +46,8 @@ Signed-off-by: Dave Jones + * In case of error we but don't return the error code immediately. + * Below we will return -EPROTONOSUPPORT */ -- if (err && printk_ratelimit()) -- printk(KERN_ERR "can: request_module " +- if (err) +- printk_ratelimited(KERN_ERR "can: request_module " - "(can-proto-%d) failed.\n", protocol); cp = can_get_proto(protocol); diff --git a/linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch b/linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch deleted file mode 100644 index f91ceb808..000000000 --- a/linux-2.6-zd1211rw-fix-invalid-signal-values-from-device.patch +++ /dev/null @@ -1,82 +0,0 @@ -commit 7a1d6564a15183cb5994656040966df09af8390f -Author: Jussi Kivilinna -Date: Mon Jun 20 14:42:28 2011 +0300 - - zd1211rw: fix invalid signal values from device - - Driver uses IEEE80211_HW_SIGNAL_UNSPEC and so signal values reported to - mac80211 should be in range 0..100. Sometimes device return out of range - values. These out of range values can then trigger warning in - cfg80211_inform_bss_frame. - - This patch adds checks to enforce range returned from driver to - mac80211 be in 0..100 range. - - Signed-off-by: Jussi Kivilinna - Signed-off-by: John W. Linville - -diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h -index 5463ca9..9a1b013 100644 ---- a/drivers/net/wireless/zd1211rw/zd_def.h -+++ b/drivers/net/wireless/zd1211rw/zd_def.h -@@ -37,9 +37,15 @@ typedef u16 __nocast zd_addr_t; - if (net_ratelimit()) \ - dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \ - } while (0) -+# define dev_dbg_f_cond(dev, cond, fmt, args...) ({ \ -+ bool __cond = !!(cond); \ -+ if (unlikely(__cond)) \ -+ dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \ -+}) - #else - # define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0) - # define dev_dbg_f_limit(dev, fmt, args...) do { (void)(dev); } while (0) -+# define dev_dbg_f_cond(dev, cond, fmt, args...) do { (void)(dev); } while (0) - #endif /* DEBUG */ - - #ifdef DEBUG -diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c -index 5037c8b..5de28bf 100644 ---- a/drivers/net/wireless/zd1211rw/zd_mac.c -+++ b/drivers/net/wireless/zd1211rw/zd_mac.c -@@ -160,6 +160,22 @@ static int zd_reg2alpha2(u8 regdomain, char *alpha2) - return 1; - } - -+static int zd_check_signal(struct ieee80211_hw *hw, int signal) -+{ -+ struct zd_mac *mac = zd_hw_mac(hw); -+ -+ dev_dbg_f_cond(zd_mac_dev(mac), signal < 0 || signal > 100, -+ "%s: signal value from device not in range 0..100, " -+ "but %d.\n", __func__, signal); -+ -+ if (signal < 0) -+ signal = 0; -+ else if (signal > 100) -+ signal = 100; -+ -+ return signal; -+} -+ - int zd_mac_preinit_hw(struct ieee80211_hw *hw) - { - int r; -@@ -461,7 +477,7 @@ static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, - if (istatus.rates[i].idx = -1; /* terminate */ - -- info->status.ack_signal = ackssi; -+ info->status.ack_signal = zd_check_signal(hw, ackssi); - ieee80211_tx_status_irqsafe(hw, skb); - } - -@@ -982,7 +998,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) - - stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq; - stats.band = IEEE80211_BAND_2GHZ; -- stats.signal = status->signal_strength; -+ stats.signal = zd_check_signal(hw, status->signal_strength); - - rate = zd_rx_rate(buffer, status); - diff --git a/linux-2.6.30-no-pcspkr-modalias.patch b/linux-2.6.30-no-pcspkr-modalias.patch index c703b8844..439269cef 100644 --- a/linux-2.6.30-no-pcspkr-modalias.patch +++ b/linux-2.6.30-no-pcspkr-modalias.patch @@ -1,11 +1,12 @@ -diff -up linux-2.6.30.noarch/drivers/input/misc/pcspkr.c.jx linux-2.6.30.noarch/drivers/input/misc/pcspkr.c ---- linux-2.6.30.noarch/drivers/input/misc/pcspkr.c.jx 2009-07-28 16:54:44.000000000 -0400 -+++ linux-2.6.30.noarch/drivers/input/misc/pcspkr.c 2009-07-28 16:59:36.000000000 -0400 -@@ -23,7 +23,6 @@ +diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c +index 34f4d2e..3e40c70 100644 +--- a/drivers/input/misc/pcspkr.c ++++ b/drivers/input/misc/pcspkr.c +@@ -24,7 +24,6 @@ MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("PC Speaker beeper driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:pcspkr"); - #if defined(CONFIG_MIPS) || defined(CONFIG_X86) - /* Use the global PIT lock ! */ + static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) + { diff --git a/rcu-avoid-just-onlined-cpu-resched.patch b/rcu-avoid-just-onlined-cpu-resched.patch new file mode 100644 index 000000000..517f37591 --- /dev/null +++ b/rcu-avoid-just-onlined-cpu-resched.patch @@ -0,0 +1,47 @@ +rcu: Avoid having just-onlined CPU resched itself when RCU is idle + +CPUs set rdp->qs_pending when coming online to resolve races with +grace-period start. However, this means that if RCU is idle, the +just-onlined CPU might needlessly send itself resched IPIs. Adjust +the online-CPU initialization to avoid this, and also to correctly +cause the CPU to respond to the current grace period if needed. + +Signed-off-by: Paul E. McKenney +--- + kernel/rcutree.c | 13 +++++++++---- + 1 files changed, 9 insertions(+), 4 deletions(-) + +diff --git a/kernel/rcutree.c b/kernel/rcutree.c +index ba06207..472d6b2 100644 +--- a/kernel/rcutree.c ++++ b/kernel/rcutree.c +@@ -1865,8 +1865,6 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible) + + /* Set up local state, ensuring consistent view of global state. */ + raw_spin_lock_irqsave(&rnp->lock, flags); +- rdp->passed_quiesc = 0; /* We could be racing with new GP, */ +- rdp->qs_pending = 1; /* so set up to respond to current GP. */ + rdp->beenonline = 1; /* We have now been online. */ + rdp->preemptible = preemptible; + rdp->qlen_last_fqs_check = 0; +@@ -1891,8 +1889,15 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible) + rnp->qsmaskinit |= mask; + mask = rnp->grpmask; + if (rnp == rdp->mynode) { +- rdp->gpnum = rnp->completed; /* if GP in progress... */ +- rdp->completed = rnp->completed; ++ /* ++ * If there is a grace period in progress, we will ++ * set up to wait for it next time we run the ++ * RCU core code. ++ */ ++ rdp->gpnum = rnp->completed; ++ rdp->completed = rnp->completed; ++ rdp->passed_quiesc = 0; ++ rdp->qs_pending = 0; + rdp->passed_quiesc_completed = rnp->completed - 1; + } + raw_spin_unlock(&rnp->lock); /* irqs already disabled. */ +-- +1.7.6 + diff --git a/sources b/sources index e117e493c..e9feef65c 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 -ac49f7907f1fc85fbab92d0f1aa1552a patch-3.0.1.bz2 +f358c354ab6d3b0da1265b504f85ec50 patch-3.1-rc2.bz2 diff --git a/ums-realtek-driver-uses-stack-memory-for-DMA.patch b/ums-realtek-driver-uses-stack-memory-for-DMA.patch index 2564fdbf2..98c8b0cf9 100644 --- a/ums-realtek-driver-uses-stack-memory-for-DMA.patch +++ b/ums-realtek-driver-uses-stack-memory-for-DMA.patch @@ -1,22 +1,69 @@ -commit 82e632009bb7d6b97f8cabe9918c82703f4e5cd2 -Author: Josh Boyer -Date: Tue Aug 2 08:37:53 2011 -0400 +From patchwork Tue Aug 2 05:04:11 2011 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +Subject: ums-realtek driver uses stack memory for DMA +Date: Tue, 02 Aug 2011 05:04:11 -0000 +From: Adam Cozzette +X-Patchwork-Id: 1028062 +Message-Id: <20110802050411.GC3857@[192.168.0.12]> +To: Josh Boyer +Cc: edwin_rong , wwang , + Greg Kroah-Hartman , linux-usb@vger.kernel.org, + linux-kernel@vger.kernel.org - This patch changed rts51x_read_mem, rts51x_write_mem, and rts51x_read_status to - allocate temporary buffers with kmalloc. This way stack addresses are not used - for DMA when these functions call rts51x_bulk_transport. - - Signed-off-by: Adam Cozzette - Backported-by: Josh Boyer +On Mon, Aug 01, 2011 at 05:09:06PM -0400, Josh Boyer wrote: +> Hello, +> +> We have a report that the ums-realtek driver is generating a backtrace +> due to using stack variables for DMA buffers. The backtrace is below +> and you can view the bug report here: +> https://bugzilla.redhat.com/show_bug.cgi?id=720054 +> +> Looking through the code, it seems that every call to rts51x_read_mem, +> rts51x_write_mem, and rts51x_read_status passes a stack variable to +> rts51x_bulk_transport, which then calls usb_stor_bulk_transfer_buf with +> this and generates the backtrace. It is my understanding that the +> driver should be passing variables that are not on the stack and have +> been allocated with memory that will be suitable for the DMA api (e.g. +> kmalloc). +> +> Was this missed during the initial review and is anyone working on +> adapting the driver to be compliant? + +Could you try out this patch if it looks ok to you? I have not tested it because +unfortunately I don't have the hardware. Right now it generates some compile +warnings like this one: + +drivers/usb/storage/realtek_cr.c:419:40: warning: ‘buf[0]’ may be used uninitialized in this function [-Wuninitialized] + +It think they are harmless but I didn't see an obvious way to get rid of them, +so if you have any suggestions I would be glad to hear them. + +This patch changed rts51x_read_mem, rts51x_write_mem, and rts51x_read_status to +allocate temporary buffers with kmalloc. This way stack addresses are not used +for DMA when these functions call rts51x_bulk_transport. + +Signed-off-by: Adam Cozzette + +--- +realtek_cr.c | 35 ++++++++++++++++++++++++++++++----- + 1 file changed, 30 insertions(+), 5 deletions(-) + +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c -index d509a4a..69a1bd3 100644 +index 34adc4b..232167a 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c -@@ -285,6 +285,11 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) +@@ -320,6 +320,11 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) { int retval; - u8 cmnd[12] = {0}; + u8 cmnd[12] = { 0 }; + u8 *buf; + + buf = kmalloc(len, GFP_NOIO); @@ -25,8 +72,8 @@ index d509a4a..69a1bd3 100644 US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); -@@ -296,10 +301,14 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) - cmnd[5] = (u8)len; +@@ -331,10 +336,14 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) + cmnd[5] = (u8) len; retval = rts51x_bulk_transport(us, 0, cmnd, 12, - data, len, DMA_FROM_DEVICE, NULL); @@ -42,10 +89,10 @@ index d509a4a..69a1bd3 100644 return 0; } -@@ -307,6 +316,12 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) +@@ -342,6 +351,12 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) { int retval; - u8 cmnd[12] = {0}; + u8 cmnd[12] = { 0 }; + u8 *buf; + + buf = kmalloc(len, GFP_NOIO); @@ -55,8 +102,8 @@ index d509a4a..69a1bd3 100644 US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); -@@ -318,7 +333,8 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) - cmnd[5] = (u8)len; +@@ -353,7 +368,8 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) + cmnd[5] = (u8) len; retval = rts51x_bulk_transport(us, 0, cmnd, 12, - data, len, DMA_TO_DEVICE, NULL); @@ -65,10 +112,10 @@ index d509a4a..69a1bd3 100644 if (retval != USB_STOR_TRANSPORT_GOOD) return -EIO; -@@ -330,6 +346,11 @@ static int rts51x_read_status(struct us_data *us, +@@ -365,6 +381,11 @@ static int rts51x_read_status(struct us_data *us, { int retval; - u8 cmnd[12] = {0}; + u8 cmnd[12] = { 0 }; + u8 *buf; + + buf = kmalloc(len, GFP_NOIO); @@ -77,7 +124,7 @@ index d509a4a..69a1bd3 100644 US_DEBUGP("%s, lun = %d\n", __func__, lun); -@@ -337,10 +358,14 @@ static int rts51x_read_status(struct us_data *us, +@@ -372,10 +393,14 @@ static int rts51x_read_status(struct us_data *us, cmnd[1] = 0x09; retval = rts51x_bulk_transport(us, lun, cmnd, 12, diff --git a/utrace.patch b/utrace.patch index f70d0b1fb..c04ac77c8 100644 --- a/utrace.patch +++ b/utrace.patch @@ -1,42 +1,42 @@ -From davej Sun Aug 7 15:19:08 2011 +From davej Wed Aug 3 15:16:11 2011 Return-Path: oleg@redhat.com -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:08 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:17:59 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:11 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:37 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F09A8A5D58; - Sun, 7 Aug 2011 15:17:58 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 6mY7uBb0+l7B; Sun, 7 Aug 2011 15:17:58 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 92D6F9D8C5; + Wed, 3 Aug 2011 15:12:08 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id RRq2PiCBdMzK; Wed, 3 Aug 2011 15:12:08 -0400 (EDT) Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D1DFE9C7FA; - Sun, 7 Aug 2011 15:17:58 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 75C149D898; + Wed, 3 Aug 2011 15:12:08 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JHtc4027719; - Sun, 7 Aug 2011 15:17:56 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JC01d029136; + Wed, 3 Aug 2011 15:12:01 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:19 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:17 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:28 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:26 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 01/22] utrace core -Message-ID: <20110807191517.GA14365@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 01/31] utrace core +Message-ID: <20110803190926.GA30903@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 148212 -Lines: 4118 +Content-Length: 139951 +Lines: 3867 From: Roland McGrath @@ -59,11 +59,11 @@ the next patches try to fix this. This is is same/old utrace-core patch except: - - use group_stop/GROUP_STOP_DEQUEUED instead of removed + - use task->jobctl/JOBCTL_STOP_DEQUEUED instead of removed signal->flags/SIGNAL_STOP_DEQUEUED in utrace_get_signal() - - rediff the changes in tracehook.h against the current code - without PT_PTRACED tweaks which were needed for ptrace-utrace + - do not include the tracehook changes, this comes with the + next patches Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov @@ -72,30 +72,28 @@ Signed-off-by: Oleg Nesterov Documentation/DocBook/utrace.tmpl | 589 +++++++++ fs/proc/array.c | 3 + include/linux/sched.h | 5 + - include/linux/tracehook.h | 85 ++- include/linux/utrace.h | 692 +++++++++++ init/Kconfig | 9 + kernel/Makefile | 1 + - kernel/fork.c | 3 + kernel/utrace.c | 2440 +++++++++++++++++++++++++++++++++++++ - 10 files changed, 3827 insertions(+), 2 deletions(-) + 8 files changed, 3740 insertions(+), 1 deletions(-) create mode 100644 Documentation/DocBook/utrace.tmpl create mode 100644 include/linux/utrace.h create mode 100644 kernel/utrace.c diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile -index 3cebfa0..86c288b 100644 +index 66725a3..08ed954 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -14,7 +14,7 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ 80211.xml debugobjects.xml sh.xml regulator.xml \ alsa-driver-api.xml writing-an-alsa-driver.xml \ -- tracepoint.xml media.xml drm.xml -+ tracepoint.xml utrace.xml media.xml drm.xml +- tracepoint.xml drm.xml media_api.xml ++ tracepoint.xml utrace.xml drm.xml media_api.xml + + include $(srctree)/Documentation/DocBook/media/Makefile - ### - # The build process is as follows (targets): diff --git a/Documentation/DocBook/utrace.tmpl b/Documentation/DocBook/utrace.tmpl new file mode 100644 index 0000000..0c40add @@ -692,7 +690,7 @@ index 0000000..0c40add + + diff --git a/fs/proc/array.c b/fs/proc/array.c -index 9b45ee8..496fef3 100644 +index 3a1dafd..f0c0ea2 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -81,6 +81,7 @@ @@ -713,10 +711,10 @@ index 9b45ee8..496fef3 100644 if (p->files) fdt = files_fdtable(p->files); diff --git a/include/linux/sched.h b/include/linux/sched.h -index a837b20..b87de83 100644 +index 20b03bf..c6d79af 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h -@@ -1397,6 +1397,11 @@ struct task_struct { +@@ -1406,6 +1406,11 @@ struct task_struct { #endif seccomp_t seccomp; @@ -728,235 +726,6 @@ index a837b20..b87de83 100644 /* Thread group tracking */ u32 parent_exec_id; u32 self_exec_id; -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index e95f523..7d7bdde 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -49,6 +49,7 @@ - #include - #include - #include -+#include - struct linux_binprm; - - /** -@@ -63,6 +64,8 @@ struct linux_binprm; - */ - static inline int tracehook_expect_breakpoints(struct task_struct *task) - { -+ if (unlikely(task_utrace_flags(task) & UTRACE_EVENT(SIGNAL_CORE))) -+ return 1; - return (task_ptrace(task) & PT_PTRACED) != 0; - } - -@@ -111,6 +114,9 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) - static inline __must_check int tracehook_report_syscall_entry( - struct pt_regs *regs) - { -+ if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && -+ utrace_report_syscall_entry(regs)) -+ return 1; - ptrace_report_syscall(regs); - return 0; - } -@@ -134,6 +140,9 @@ static inline __must_check int tracehook_report_syscall_entry( - */ - static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) - { -+ if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) -+ utrace_report_syscall_exit(regs); -+ - if (step) { - siginfo_t info; - user_single_step_siginfo(current, regs, &info); -@@ -201,6 +210,8 @@ static inline void tracehook_report_exec(struct linux_binfmt *fmt, - struct linux_binprm *bprm, - struct pt_regs *regs) - { -+ if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXEC))) -+ utrace_report_exec(fmt, bprm, regs); - if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) && - unlikely(task_ptrace(current) & PT_PTRACED)) - send_sig(SIGTRAP, current, 0); -@@ -218,10 +229,37 @@ static inline void tracehook_report_exec(struct linux_binfmt *fmt, - */ - static inline void tracehook_report_exit(long *exit_code) - { -+ if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXIT))) -+ utrace_report_exit(exit_code); - ptrace_event(PT_TRACE_EXIT, PTRACE_EVENT_EXIT, *exit_code); - } - - /** -+ * tracehook_init_task - task_struct has just been copied -+ * @task: new &struct task_struct just copied from parent -+ * -+ * Called from do_fork() when @task has just been duplicated. -+ * After this, @task will be passed to tracehook_free_task() -+ * even if the rest of its setup fails before it is fully created. -+ */ -+static inline void tracehook_init_task(struct task_struct *task) -+{ -+ utrace_init_task(task); -+} -+ -+/** -+ * tracehook_free_task - task_struct is being freed -+ * @task: dead &struct task_struct being freed -+ * -+ * Called from free_task() when @task is no longer in use. -+ */ -+static inline void tracehook_free_task(struct task_struct *task) -+{ -+ if (task_utrace_struct(task)) -+ utrace_free_task(task); -+} -+ -+/** - * tracehook_prepare_clone - prepare for new child to be cloned - * @clone_flags: %CLONE_* flags from clone/fork/vfork system call - * -@@ -285,6 +323,8 @@ static inline void tracehook_report_clone(struct pt_regs *regs, - unsigned long clone_flags, - pid_t pid, struct task_struct *child) - { -+ if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE))) -+ utrace_report_clone(clone_flags, child); - if (unlikely(task_ptrace(child))) { - /* - * It doesn't matter who attached/attaching to this -@@ -317,6 +357,9 @@ static inline void tracehook_report_clone_complete(int trace, - pid_t pid, - struct task_struct *child) - { -+ if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE)) && -+ (clone_flags & CLONE_VFORK)) -+ utrace_finish_vfork(current); - if (unlikely(trace)) - ptrace_event(0, trace, pid); - } -@@ -351,6 +394,10 @@ static inline void tracehook_report_vfork_done(struct task_struct *child, - */ - static inline void tracehook_prepare_release_task(struct task_struct *task) - { -+ /* see utrace_add_engine() about this barrier */ -+ smp_mb(); -+ if (task_utrace_flags(task)) -+ utrace_maybe_reap(task, task_utrace_struct(task), true); - } - - /** -@@ -365,6 +412,7 @@ static inline void tracehook_prepare_release_task(struct task_struct *task) - static inline void tracehook_finish_release_task(struct task_struct *task) - { - ptrace_release_task(task); -+ BUG_ON(task->exit_state != EXIT_DEAD); - } - - /** -@@ -386,6 +434,8 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, - const struct k_sigaction *ka, - struct pt_regs *regs, int stepping) - { -+ if (task_utrace_flags(current)) -+ utrace_signal_handler(current, stepping); - if (stepping) - ptrace_notify(SIGTRAP); - } -@@ -403,6 +453,8 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, - static inline int tracehook_consider_ignored_signal(struct task_struct *task, - int sig) - { -+ if (unlikely(task_utrace_flags(task) & UTRACE_EVENT(SIGNAL_IGN))) -+ return 1; - return (task_ptrace(task) & PT_PTRACED) != 0; - } - -@@ -422,6 +474,9 @@ static inline int tracehook_consider_ignored_signal(struct task_struct *task, - static inline int tracehook_consider_fatal_signal(struct task_struct *task, - int sig) - { -+ if (unlikely(task_utrace_flags(task) & (UTRACE_EVENT(SIGNAL_TERM) | -+ UTRACE_EVENT(SIGNAL_CORE)))) -+ return 1; - return (task_ptrace(task) & PT_PTRACED) != 0; - } - -@@ -436,6 +491,8 @@ static inline int tracehook_consider_fatal_signal(struct task_struct *task, - */ - static inline int tracehook_force_sigpending(void) - { -+ if (unlikely(task_utrace_flags(current))) -+ return utrace_interrupt_pending(); - return 0; - } - -@@ -465,6 +522,8 @@ static inline int tracehook_get_signal(struct task_struct *task, - siginfo_t *info, - struct k_sigaction *return_ka) - { -+ if (unlikely(task_utrace_flags(task))) -+ return utrace_get_signal(task, regs, info, return_ka); - return 0; - } - -@@ -475,6 +534,8 @@ static inline int tracehook_get_signal(struct task_struct *task, - */ - static inline void tracehook_finish_jctl(void) - { -+ if (task_utrace_flags(current)) -+ utrace_finish_stop(); - } - - #define DEATH_REAP -1 -@@ -497,6 +558,8 @@ static inline void tracehook_finish_jctl(void) - static inline int tracehook_notify_death(struct task_struct *task, - void **death_cookie, int group_dead) - { -+ *death_cookie = task_utrace_struct(task); -+ - if (task_detached(task)) - return task->ptrace ? SIGCHLD : DEATH_REAP; - -@@ -533,6 +596,15 @@ static inline void tracehook_report_death(struct task_struct *task, - int signal, void *death_cookie, - int group_dead) - { -+ /* -+ * If utrace_set_events() was just called to enable -+ * UTRACE_EVENT(DEATH), then we are obliged to call -+ * utrace_report_death() and not miss it. utrace_set_events() -+ * checks @task->exit_state under tasklist_lock to synchronize -+ * with exit_notify(), the caller. -+ */ -+ if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) -+ utrace_report_death(task, death_cookie, group_dead, signal); - } - - #ifdef TIF_NOTIFY_RESUME -@@ -562,10 +634,21 @@ static inline void set_notify_resume(struct task_struct *task) - * asynchronously, this will be called again before we return to - * user mode. - * -- * Called without locks. -+ * Called without locks. However, on some machines this may be -+ * called with interrupts disabled. - */ - static inline void tracehook_notify_resume(struct pt_regs *regs) - { -+ struct task_struct *task = current; -+ /* -+ * Prevent the following store/load from getting ahead of the -+ * caller which clears TIF_NOTIFY_RESUME. This pairs with the -+ * implicit mb() before setting TIF_NOTIFY_RESUME in -+ * set_notify_resume(). -+ */ -+ smp_mb(); -+ if (task_utrace_flags(task)) -+ utrace_resume(task, regs); - } - #endif /* TIF_NOTIFY_RESUME */ - diff --git a/include/linux/utrace.h b/include/linux/utrace.h new file mode 100644 index 0000000..f251efe @@ -1656,7 +1425,7 @@ index 0000000..f251efe + +#endif /* linux/utrace.h */ diff --git a/init/Kconfig b/init/Kconfig -index 412c21b..a03ae51 100644 +index d627783..7afce1f 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -372,6 +372,15 @@ config AUDIT_TREE @@ -1676,7 +1445,7 @@ index 412c21b..a03ae51 100644 menu "RCU Subsystem" diff --git a/kernel/Makefile b/kernel/Makefile -index 2d64cfc..4a22e81 100644 +index d06467f..85828da 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o @@ -1687,30 +1456,9 @@ index 2d64cfc..4a22e81 100644 obj-$(CONFIG_AUDIT) += audit.o auditfilter.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o obj-$(CONFIG_AUDIT_WATCH) += audit_watch.o -diff --git a/kernel/fork.c b/kernel/fork.c -index 0276c30..62caf3d 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -168,6 +168,7 @@ void free_task(struct task_struct *tsk) - free_thread_info(tsk->stack); - rt_mutex_debug_task_free(tsk); - ftrace_graph_exit_task(tsk); -+ tracehook_free_task(tsk); - free_task_struct(tsk); - } - EXPORT_SYMBOL(free_task); -@@ -1095,6 +1096,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, - if (!p) - goto fork_out; - -+ tracehook_init_task(p); -+ - ftrace_graph_init_task(p); - - rt_mutex_init_task(p); diff --git a/kernel/utrace.c b/kernel/utrace.c new file mode 100644 -index 0000000..f332d65 +index 0000000..ef856c9 --- /dev/null +++ b/kernel/utrace.c @@ -0,0 +1,2440 @@ @@ -4000,7 +3748,7 @@ index 0000000..f332d65 + spin_lock_irq(&task->sighand->siglock); + + if (sig_kernel_stop(signr)) -+ task->group_stop |= GROUP_STOP_DEQUEUED; ++ task->jobctl |= JOBCTL_STOP_DEQUEUED; + + return signr; +} @@ -4157,52 +3905,838 @@ index 0000000..f332d65 -- 1.5.5.1 -From davej Sun Aug 7 15:19:09 2011 + +From davej Wed Aug 3 15:16:13 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:09 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:01 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:13 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:37 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A1FB8D89A7; - Sun, 7 Aug 2011 15:18:01 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id JtiDMxvrW-Di; Sun, 7 Aug 2011 15:18:01 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7F0E6D8988; - Sun, 7 Aug 2011 15:18:01 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 419B39D8CF; + Wed, 3 Aug 2011 15:12:11 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id AmaThyCcp1K4; Wed, 3 Aug 2011 15:12:11 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2A0B29CE59; + Wed, 3 Aug 2011 15:12:11 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JHxlJ027726; - Sun, 7 Aug 2011 15:17:59 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JC3DW023262; + Wed, 3 Aug 2011 15:12:04 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:23 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:21 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:31 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:29 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 02/22] utrace: remove jobctl bits -Message-ID: <20110807191521.GA14373@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 02/31] utrace: add utrace_init_task/utrace_free_task calls +Message-ID: <20110803190929.GA30907@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 1889 -Lines: 55 +Content-Length: 1295 +Lines: 47 -- change utrace_get_signal() to check GROUP_STOP_PENDING instead of +Add the necessary copy_process()->utrace_init_task() and +free_task()->utrace_free_task() calls. + +Originally this was the part of "utrace core" patch, but since +tracehooks are dying it doesn't make sense to reintroduce them. +Instead, just call the utrace_ helpers directly. This is fine +even without CONFIG_UTRACE, gcc is smart enough to optimize out +the code in free_task(). + +Signed-off-by: Oleg Nesterov +--- + kernel/fork.c | 5 +++++ + 1 files changed, 5 insertions(+), 0 deletions(-) + +diff --git a/kernel/fork.c b/kernel/fork.c +index e7ceaca..a9891da 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -66,6 +66,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -167,6 +168,8 @@ void free_task(struct task_struct *tsk) + free_thread_info(tsk->stack); + rt_mutex_debug_task_free(tsk); + ftrace_graph_exit_task(tsk); ++ if (task_utrace_struct(tsk)) ++ utrace_free_task(tsk); + free_task_struct(tsk); + } + EXPORT_SYMBOL(free_task); +@@ -1096,6 +1099,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, + if (!p) + goto fork_out; + ++ utrace_init_task(p); ++ + ftrace_graph_init_task(p); + + rt_mutex_init_task(p); +-- +1.5.5.1 + + +From davej Wed Aug 3 15:16:18 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:16:18 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:07 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F28379DE70; + Wed, 3 Aug 2011 15:12:13 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id p92IDp0LZ5jX; Wed, 3 Aug 2011 15:12:13 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D4E339DE68; + Wed, 3 Aug 2011 15:12:13 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JC6IA023283; + Wed, 3 Aug 2011 15:12:07 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:34 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:32 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 03/31] tracehooks: add utrace hooks +Message-ID: <20110803190932.GA30915@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Status: RO +Content-Length: 2310 +Lines: 75 + +Add the necessary utrace hooks in the tracehooks which were not +removed yet. + +Signed-off-by: Oleg Nesterov +--- + include/linux/tracehook.h | 22 +++++++++++++++++++++- + 1 files changed, 21 insertions(+), 1 deletions(-) + +diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h +index a71a292..8cc28bc 100644 +--- a/include/linux/tracehook.h ++++ b/include/linux/tracehook.h +@@ -49,6 +49,7 @@ + #include + #include + #include ++#include + struct linux_binprm; + + /* +@@ -96,6 +97,9 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) + static inline __must_check int tracehook_report_syscall_entry( + struct pt_regs *regs) + { ++ if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && ++ utrace_report_syscall_entry(regs)) ++ return 1; + ptrace_report_syscall(regs); + return 0; + } +@@ -119,6 +123,9 @@ static inline __must_check int tracehook_report_syscall_entry( + */ + static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) + { ++ if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) ++ utrace_report_syscall_exit(regs); ++ + if (step) { + siginfo_t info; + user_single_step_siginfo(current, regs, &info); +@@ -148,6 +155,8 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, + const struct k_sigaction *ka, + struct pt_regs *regs, int stepping) + { ++ if (task_utrace_flags(current)) ++ utrace_signal_handler(current, stepping); + if (stepping) + ptrace_notify(SIGTRAP); + } +@@ -179,10 +188,21 @@ static inline void set_notify_resume(struct task_struct *task) + * asynchronously, this will be called again before we return to + * user mode. + * +- * Called without locks. ++ * Called without locks. However, on some machines this may be ++ * called with interrupts disabled. + */ + static inline void tracehook_notify_resume(struct pt_regs *regs) + { ++ struct task_struct *task = current; ++ /* ++ * Prevent the following store/load from getting ahead of the ++ * caller which clears TIF_NOTIFY_RESUME. This pairs with the ++ * implicit mb() before setting TIF_NOTIFY_RESUME in ++ * set_notify_resume(). ++ */ ++ smp_mb(); ++ if (task_utrace_flags(task)) ++ utrace_resume(task, regs); + } + #endif /* TIF_NOTIFY_RESUME */ + +-- +1.5.5.1 + + +From davej Wed Aug 3 15:16:14 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:16:14 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:37 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 92FCA9D8FA; + Wed, 3 Aug 2011 15:12:16 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id lQaZCHUpw8DT; Wed, 3 Aug 2011 15:12:16 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7479B9D8C9; + Wed, 3 Aug 2011 15:12:16 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JC91G023308; + Wed, 3 Aug 2011 15:12:09 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:37 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:35 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 04/31] tracehooks: reintroduce + tracehook_consider_fatal_signal() +Message-ID: <20110803190935.GA30918@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Status: RO +Content-Length: 3257 +Lines: 90 + +Add the killed tracehook_consider_fatal_signal() back. It has multiple +callers and it is not easy add the necessary checks inline. + +Signed-off-by: Oleg Nesterov +--- + arch/s390/kernel/traps.c | 4 ++-- + include/linux/tracehook.h | 22 ++++++++++++++++++++++ + kernel/signal.c | 4 ++-- + 3 files changed, 26 insertions(+), 4 deletions(-) + +diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c +index ffabcd9..1018ab6 100644 +--- a/arch/s390/kernel/traps.c ++++ b/arch/s390/kernel/traps.c +@@ -329,7 +329,7 @@ void __kprobes do_per_trap(struct pt_regs *regs) + + if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP) + return; +- if (!current->ptrace) ++ if (!tracehook_consider_fatal_signal(current, SIGTRAP)) + return; + info.si_signo = SIGTRAP; + info.si_errno = 0; +@@ -428,7 +428,7 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code, + if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) + return; + if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) { +- if (current->ptrace) { ++ if (tracehook_consider_fatal_signal(current, SIGTRAP)) { + info.si_signo = SIGTRAP; + info.si_errno = 0; + info.si_code = TRAP_BRKPT; +diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h +index 8cc28bc..ec2af67 100644 +--- a/include/linux/tracehook.h ++++ b/include/linux/tracehook.h +@@ -161,6 +161,28 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, + ptrace_notify(SIGTRAP); + } + ++/** ++ * tracehook_consider_fatal_signal - suppress special handling of fatal signal ++ * @task: task receiving the signal ++ * @sig: signal number being sent ++ * ++ * Return nonzero to prevent special handling of this termination signal. ++ * Normally handler for signal is %SIG_DFL. It can be %SIG_IGN if @sig is ++ * ignored, in which case force_sig() is about to reset it to %SIG_DFL. ++ * When this returns zero, this signal might cause a quick termination ++ * that does not give the debugger a chance to intercept the signal. ++ * ++ * Called with or without @task->sighand->siglock held. ++ */ ++static inline int tracehook_consider_fatal_signal(struct task_struct *task, ++ int sig) ++{ ++ if (unlikely(task_utrace_flags(task) & (UTRACE_EVENT(SIGNAL_TERM) | ++ UTRACE_EVENT(SIGNAL_CORE)))) ++ return 1; ++ return task->ptrace != 0; ++} ++ + #ifdef TIF_NOTIFY_RESUME + /** + * set_notify_resume - cause tracehook_notify_resume() to be called +diff --git a/kernel/signal.c b/kernel/signal.c +index 291c970..d7ef0da 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -494,7 +494,7 @@ int unhandled_signal(struct task_struct *tsk, int sig) + if (handler != SIG_IGN && handler != SIG_DFL) + return 0; + /* if ptraced, let the tracer determine */ +- return !tsk->ptrace; ++ return !tracehook_consider_fatal_signal(tsk, sig); + } + + /* +@@ -982,7 +982,7 @@ static void complete_signal(int sig, struct task_struct *p, int group) + if (sig_fatal(p, sig) && + !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) && + !sigismember(&t->real_blocked, sig) && +- (sig == SIGKILL || !t->ptrace)) { ++ (sig == SIGKILL || !tracehook_consider_fatal_signal(t, sig))) { + /* + * This signal will be fatal to the whole group. + */ +-- +1.5.5.1 + + +From davej Wed Aug 3 15:16:20 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:16:20 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:08 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 374FE9DE74; + Wed, 3 Aug 2011 15:12:19 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id Sun0Twp72xGV; Wed, 3 Aug 2011 15:12:19 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 223E39DD25; + Wed, 3 Aug 2011 15:12:19 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCBgK008326; + Wed, 3 Aug 2011 15:12:12 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:39 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:37 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 05/31] add utrace hooks into sig_ignored() and + recalc_sigpending() +Message-ID: <20110803190937.GA30926@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Status: RO +Content-Length: 1508 +Lines: 51 + +Add the necessary and somewhat "special" hooks into sig_ignored() and +recalc_sigpending(). Basically this restores _force_sigpending() and +_consider_ignored_signal() tracehook logic. + +Signed-off-by: Oleg Nesterov +--- + include/linux/utrace.h | 2 ++ + kernel/signal.c | 7 ++++++- + 2 files changed, 8 insertions(+), 1 deletions(-) + +diff --git a/include/linux/utrace.h b/include/linux/utrace.h +index f251efe..1b8da1c 100644 +--- a/include/linux/utrace.h ++++ b/include/linux/utrace.h +@@ -107,6 +107,8 @@ bool utrace_report_syscall_entry(struct pt_regs *); + void utrace_report_syscall_exit(struct pt_regs *); + void utrace_signal_handler(struct task_struct *, int); + ++#define UTRACE_FLAG(task, ev) (task_utrace_flags(task) & UTRACE_EVENT(ev)) ++ + #ifndef CONFIG_UTRACE + + /* +diff --git a/kernel/signal.c b/kernel/signal.c +index d7ef0da..0f9af0b 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -87,7 +87,7 @@ static int sig_ignored(struct task_struct *t, int sig, int from_ancestor_ns) + /* + * Tracers may want to know about even ignored signals. + */ +- return !t->ptrace; ++ return !t->ptrace && !UTRACE_FLAG(t, SIGNAL_IGN); + } + + /* +@@ -150,6 +150,11 @@ void recalc_sigpending_and_wake(struct task_struct *t) + + void recalc_sigpending(void) + { ++ if (task_utrace_flags(current) && utrace_interrupt_pending()) { ++ set_thread_flag(TIF_SIGPENDING); ++ return; ++ } ++ + if (!recalc_sigpending_tsk(current) && !freezing(current)) + clear_thread_flag(TIF_SIGPENDING); + +-- +1.5.5.1 + + +From davej Wed Aug 3 15:16:21 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:16:21 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:09 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 054279DE7D; + Wed, 3 Aug 2011 15:12:22 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 1BosZIzYSIW0; Wed, 3 Aug 2011 15:12:21 -0400 (EDT) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E41DC9DE7B; + Wed, 3 Aug 2011 15:12:21 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JCEgD022264; + Wed, 3 Aug 2011 15:12:15 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:42 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:40 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 06/31] restore the EXEC/EXIT/CLONE utrace hooks +Message-ID: <20110803190940.GA30929@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +Status: RO +Content-Length: 2383 +Lines: 83 + +Restore the "trivial" EXEC/EXIT/CLONE utrace hooks. Add the +simple helper, UTRACE_HOOK(), to minimize the changes. + +Signed-off-by: Oleg Nesterov +--- + fs/exec.c | 5 ++++- + include/linux/utrace.h | 6 ++++++ + kernel/exit.c | 1 + + kernel/fork.c | 4 ++++ + 4 files changed, 15 insertions(+), 1 deletions(-) + +diff --git a/fs/exec.c b/fs/exec.c +index da80612..a0814cd 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1401,9 +1401,12 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) + */ + bprm->recursion_depth = depth; + if (retval >= 0) { +- if (depth == 0) ++ if (depth == 0) { ++ UTRACE_HOOK(current, EXEC, ++ report_exec(fmt, bprm, regs)); + ptrace_event(PTRACE_EVENT_EXEC, + old_pid); ++ } + put_binfmt(fmt); + allow_write_access(bprm->file); + if (bprm->file) +diff --git a/include/linux/utrace.h b/include/linux/utrace.h +index 1b8da1c..9ac0b1b 100644 +--- a/include/linux/utrace.h ++++ b/include/linux/utrace.h +@@ -109,6 +109,12 @@ void utrace_signal_handler(struct task_struct *, int); + + #define UTRACE_FLAG(task, ev) (task_utrace_flags(task) & UTRACE_EVENT(ev)) + ++#define UTRACE_HOOK(task, ev, callback) \ ++ do { \ ++ if (UTRACE_FLAG(task, ev)) \ ++ utrace_ ## callback; \ ++ } while (0) ++ + #ifndef CONFIG_UTRACE + + /* +diff --git a/kernel/exit.c b/kernel/exit.c +index 2913b35..c1b0ab6 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -913,6 +913,7 @@ NORET_TYPE void do_exit(long code) + */ + set_fs(USER_DS); + ++ UTRACE_HOOK(current, EXIT, report_exit(&code)); + ptrace_event(PTRACE_EVENT_EXIT, code); + + validate_creds_for_do_exit(tsk); +diff --git a/kernel/fork.c b/kernel/fork.c +index a9891da..37f4a07 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -1539,6 +1539,8 @@ long do_fork(unsigned long clone_flags, + + audit_finish_fork(p); + ++ UTRACE_HOOK(current, CLONE, report_clone(clone_flags, p)); ++ + /* + * We set PF_STARTING at creation in case tracing wants to + * use this to distinguish a fully live task from one that +@@ -1550,6 +1552,8 @@ long do_fork(unsigned long clone_flags, + wake_up_new_task(p); + + /* forking complete and child started to run, tell ptracer */ ++ if (clone_flags & CLONE_VFORK) ++ UTRACE_HOOK(current, CLONE, finish_vfork(current)); + if (unlikely(trace)) + ptrace_event(trace, nr); + +-- +1.5.5.1 + + +From davej Wed Aug 3 15:16:23 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:16:23 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:13 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B36EC9DE82; + Wed, 3 Aug 2011 15:12:24 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 7Qqv+lXfqHw6; Wed, 3 Aug 2011 15:12:24 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9F8AF9DD25; + Wed, 3 Aug 2011 15:12:24 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCH0U023349; + Wed, 3 Aug 2011 15:12:17 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:45 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:43 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 07/31] utrace: utrace_report_death() can use + task_utrace_struct() +Message-ID: <20110803190943.GA30936@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Status: RO +Content-Length: 1692 +Lines: 44 + +utrace_report_death() assumes that the caller (exit_notify) should +pass task->utrace as an argument. This is no longer needed, it can +safely do task_utrace_struct(). This way we avoid the nasty changes +in exit_notify(). + +Signed-off-by: Oleg Nesterov +--- + include/linux/utrace.h | 2 +- + kernel/utrace.c | 5 +++-- + 2 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/include/linux/utrace.h b/include/linux/utrace.h +index 9ac0b1b..9a2e2f4 100644 +--- a/include/linux/utrace.h ++++ b/include/linux/utrace.h +@@ -99,7 +99,7 @@ int utrace_get_signal(struct task_struct *, struct pt_regs *, + void utrace_report_clone(unsigned long, struct task_struct *); + void utrace_finish_vfork(struct task_struct *); + void utrace_report_exit(long *exit_code); +-void utrace_report_death(struct task_struct *, struct utrace *, bool, int); ++void utrace_report_death(struct task_struct *, bool, int); + void utrace_report_jctl(int notify, int type); + void utrace_report_exec(struct linux_binfmt *, struct linux_binprm *, + struct pt_regs *regs); +diff --git a/kernel/utrace.c b/kernel/utrace.c +index ef856c9..1e750ad 100644 +--- a/kernel/utrace.c ++++ b/kernel/utrace.c +@@ -1759,9 +1759,10 @@ void utrace_report_exit(long *exit_code) + * For this reason, utrace_release_task checks for the event bits that get + * us here, and delays its cleanup for us to do. + */ +-void utrace_report_death(struct task_struct *task, struct utrace *utrace, +- bool group_dead, int signal) ++void utrace_report_death(struct task_struct *task, bool group_dead, int signal) + { ++ struct utrace *utrace = task_utrace_struct(task); ++ + INIT_REPORT(report); + + BUG_ON(!task->exit_state); +-- +1.5.5.1 + + +From davej Wed Aug 3 15:16:15 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:16:15 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:39 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 76DA49D9C7; + Wed, 3 Aug 2011 15:12:27 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 25xHJjCTouA4; Wed, 3 Aug 2011 15:12:27 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 490E79D9AB; + Wed, 3 Aug 2011 15:12:27 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCKXo023360; + Wed, 3 Aug 2011 15:12:20 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:47 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:45 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 08/31] restore the DEATH/REAP utrace hooks +Message-ID: <20110803190945.GA30939@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Status: RO +Content-Length: 2346 +Lines: 70 + +Restore the necessary hooks in release_task() and exit_notify(), +add the corresponding helpers into utrace.h. + +Note: the @signal argument passed to ->report_death() does not +match the previous behaviour. I think this shouldn't affect the +current users, and I bet nobody can really understand what this +magic argument should actually mean anyway. + +Signed-off-by: Oleg Nesterov +--- + include/linux/utrace.h | 22 ++++++++++++++++++++++ + kernel/exit.c | 4 ++++ + 2 files changed, 26 insertions(+), 0 deletions(-) + +diff --git a/include/linux/utrace.h b/include/linux/utrace.h +index 9a2e2f4..cf13839 100644 +--- a/include/linux/utrace.h ++++ b/include/linux/utrace.h +@@ -697,4 +697,26 @@ static inline __must_check int utrace_barrier_pid(struct pid *pid, + + #endif /* CONFIG_UTRACE */ + ++static inline void utrace_release_task(struct task_struct *task) ++{ ++ /* see utrace_add_engine() about this barrier */ ++ smp_mb(); ++ if (task_utrace_flags(task)) ++ utrace_maybe_reap(task, task_utrace_struct(task), true); ++} ++ ++static inline void utrace_exit_notify(struct task_struct *task, ++ int signal, int group_dead) ++{ ++ /* ++ * If utrace_set_events() was just called to enable ++ * UTRACE_EVENT(DEATH), then we are obliged to call ++ * utrace_report_death() and not miss it. utrace_set_events() ++ * checks @task->exit_state under tasklist_lock to synchronize ++ * with exit_notify(), the caller. ++ */ ++ if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) ++ utrace_report_death(task, group_dead, signal); ++} ++ + #endif /* linux/utrace.h */ +diff --git a/kernel/exit.c b/kernel/exit.c +index c1b0ab6..ba5ba22 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -168,6 +168,8 @@ void release_task(struct task_struct * p) + struct task_struct *leader; + int zap_leader; + repeat: ++ utrace_release_task(p); ++ + /* don't need to get the RCU readlock here - the process is dead and + * can't be modifying its own credentials. But shut RCU-lockdep up */ + rcu_read_lock(); +@@ -860,6 +862,8 @@ static void exit_notify(struct task_struct *tsk, int group_dead) + wake_up_process(tsk->signal->group_exit_task); + write_unlock_irq(&tasklist_lock); + ++ utrace_exit_notify(tsk, autoreap ? -1 : SIGCHLD, group_dead); ++ + /* If the process is dead, release it - nobody will wait for it */ + if (autoreap) + release_task(tsk); +-- +1.5.5.1 + + +From davej Wed Aug 3 15:22:02 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:22:02 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:17:16 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 26DB69DE8C; + Wed, 3 Aug 2011 15:12:30 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id DbxGfmFvtTiR; Wed, 3 Aug 2011 15:12:30 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 0A30A9DE91; + Wed, 3 Aug 2011 15:12:30 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCMDQ008389; + Wed, 3 Aug 2011 15:12:23 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:50 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:48 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 09/31] utrace: remove jobctl bits +Message-ID: <20110803190948.GA30942@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Status: RO +Content-Length: 1888 +Lines: 56 + +- change utrace_get_signal() to check JOBCTL_STOP_PENDING instead of signal->group_stop_count. With the recent changes group_stop_count doesn't necessarily mean this task should participate in group stop. @@ -4215,7 +4749,7 @@ Signed-off-by: Oleg Nesterov 1 files changed, 2 insertions(+), 14 deletions(-) diff --git a/kernel/utrace.c b/kernel/utrace.c -index f332d65..6e7fafb 100644 +index 1e750ad..5d3974e 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -648,11 +648,7 @@ static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) @@ -4246,62 +4780,63 @@ index f332d65..6e7fafb 100644 spin_unlock_irq(&task->sighand->siglock); spin_unlock(&utrace->lock); -@@ -2036,7 +2024,7 @@ int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, +@@ -2037,7 +2025,7 @@ int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, ka = NULL; memset(return_ka, 0, sizeof *return_ka); } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || - unlikely(task->signal->group_stop_count)) { -+ unlikely(task->group_stop & GROUP_STOP_PENDING)) { ++ unlikely(task->jobctl & JOBCTL_STOP_PENDING)) { /* * If no engine is interested in intercepting signals or * we must stop, let the caller just dequeue them normally -- 1.5.5.1 -From davej Sun Aug 7 15:19:10 2011 + +From davej Wed Aug 3 15:16:17 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:10 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:04 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:17 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:52 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 473EDD89A7; - Sun, 7 Aug 2011 15:18:04 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id uA3eVmUnKFQu; Sun, 7 Aug 2011 15:18:04 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 29079D8988; - Sun, 7 Aug 2011 15:18:04 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id AB6E39DA46; + Wed, 3 Aug 2011 15:12:32 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id LkzmRGslEelr; Wed, 3 Aug 2011 15:12:32 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 959659DA60; + Wed, 3 Aug 2011 15:12:32 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JI1LH027738; - Sun, 7 Aug 2011 15:18:02 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCPx7023400; + Wed, 3 Aug 2011 15:12:25 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:25 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:23 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:53 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:51 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 03/22] ptrace: take ->siglock around s/TRACED/RUNNING/ -Message-ID: <20110807191523.GA14376@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 10/31] ptrace: take ->siglock around s/TRACED/RUNNING/ +Message-ID: <20110803190951.GA30949@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 1623 -Lines: 55 +Content-Length: 1624 +Lines: 56 change ptrace_resume() and ptrace_stop() to take ->siglock around changing task->state from TRACED to RUNNING. @@ -4316,10 +4851,10 @@ Signed-off-by: Oleg Nesterov 2 files changed, 10 insertions(+), 1 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 2df1157..9988b13 100644 +index 9de3ecf..56b8fc1 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c -@@ -534,6 +534,8 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info) +@@ -589,6 +589,8 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info) static int ptrace_resume(struct task_struct *child, long request, unsigned long data) { @@ -4328,7 +4863,7 @@ index 2df1157..9988b13 100644 if (!valid_signal(data)) return -EIO; -@@ -562,7 +564,11 @@ static int ptrace_resume(struct task_struct *child, long request, +@@ -617,7 +619,11 @@ static int ptrace_resume(struct task_struct *child, long request, } child->exit_code = data; @@ -4342,10 +4877,10 @@ index 2df1157..9988b13 100644 return 0; } diff --git a/kernel/signal.c b/kernel/signal.c -index ff76786..2138cee 100644 +index 0f9af0b..71f5cca 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -1799,7 +1799,10 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1878,7 +1878,10 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) if (gstop_done) do_notify_parent_cldstop(current, false, why); @@ -4359,50 +4894,51 @@ index ff76786..2138cee 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:11 2011 + +From davej Wed Aug 3 15:16:37 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:11 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:37 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:06 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:29 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D76B6A5D58; - Sun, 7 Aug 2011 15:18:06 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5034E9DEA4; + Wed, 3 Aug 2011 15:12:35 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id xyKeY-zzvTgR; Sun, 7 Aug 2011 15:18:06 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BB0E49C7FA; - Sun, 7 Aug 2011 15:18:06 -0400 (EDT) + with ESMTP id 8BhFlmqmXy8l; Wed, 3 Aug 2011 15:12:35 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 31AEE9DEAB; + Wed, 3 Aug 2011 15:12:35 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JI4PF028668; - Sun, 7 Aug 2011 15:18:05 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCRCZ008434; + Wed, 3 Aug 2011 15:12:28 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:28 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:26 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:55 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:53 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 04/22] introduce wake_up_quiescent() -Message-ID: <20110807191526.GA14383@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 11/31] introduce wake_up_quiescent() +Message-ID: <20110803190953.GA30952@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO -Content-Length: 3103 -Lines: 92 +Content-Length: 3186 +Lines: 93 No functional changes. Add the new helper, wake_up_quiescent(task, state), which simply returns wake_up_state(task, state). Change all callers which @@ -4432,10 +4968,10 @@ index a822300..2be3712 100644 extern int do_send_sig_info(int sig, struct siginfo *info, struct task_struct *p, bool group); diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 9988b13..26ae214 100644 +index 56b8fc1..4194664 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c -@@ -566,7 +566,7 @@ static int ptrace_resume(struct task_struct *child, long request, +@@ -621,7 +621,7 @@ static int ptrace_resume(struct task_struct *child, long request, child->exit_code = data; if (lock_task_sighand(child, &flags)) { @@ -4445,10 +4981,10 @@ index 9988b13..26ae214 100644 } diff --git a/kernel/signal.c b/kernel/signal.c -index 2138cee..4fcf1c7 100644 +index 71f5cca..3e8e0b1 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -652,6 +652,14 @@ void signal_wake_up(struct task_struct *t, int resume) +@@ -702,6 +702,14 @@ void signal_wake_up(struct task_struct *t, int resume) } /* @@ -4463,16 +4999,16 @@ index 2138cee..4fcf1c7 100644 * Remove signals in mask from the pending set and queue. * Returns 1 if any signals were found. * -@@ -811,7 +819,7 @@ static int prepare_signal(int sig, struct task_struct *p, int from_ancestor_ns) - do { - task_clear_group_stop_pending(t); +@@ -888,7 +896,7 @@ static int prepare_signal(int sig, struct task_struct *p, int from_ancestor_ns) + task_clear_jobctl_pending(t, JOBCTL_STOP_PENDING); rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending); -- wake_up_state(t, __TASK_STOPPED); -+ wake_up_quiescent(t, __TASK_STOPPED); + if (likely(!(t->ptrace & PT_SEIZED))) +- wake_up_state(t, __TASK_STOPPED); ++ wake_up_quiescent(t, __TASK_STOPPED); + else + ptrace_trap_notify(t); } while_each_thread(p, t); - - /* -@@ -1800,7 +1808,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1879,7 +1887,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) do_notify_parent_cldstop(current, false, why); spin_lock_irq(¤t->sighand->siglock); @@ -4482,7 +5018,7 @@ index 2138cee..4fcf1c7 100644 if (clear_code) diff --git a/kernel/utrace.c b/kernel/utrace.c -index 6e7fafb..d7c547c 100644 +index 5d3974e..cebc390 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -648,7 +648,7 @@ static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) @@ -4497,53 +5033,54 @@ index 6e7fafb..d7c547c 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:13 2011 + +From davej Wed Aug 3 15:22:01 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:13 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:22:01 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:09 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:17:15 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C8DCF1322A2; - Sun, 7 Aug 2011 15:18:09 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F2DE19DC07; + Wed, 3 Aug 2011 15:12:37 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id ZQXZL5xrzV21; Sun, 7 Aug 2011 15:18:09 -0400 (EDT) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B3D6D128FDA; - Sun, 7 Aug 2011 15:18:09 -0400 (EDT) + with ESMTP id IYfqfx8GhNWc; Wed, 3 Aug 2011 15:12:37 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D645E9DAF7; + Wed, 3 Aug 2011 15:12:37 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JI7P5029847; - Sun, 7 Aug 2011 15:18:07 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCUNh008446; + Wed, 3 Aug 2011 15:12:31 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:31 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:28 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:09:58 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:56 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 05/22] introduce ptrace_signal_wake_up() -Message-ID: <20110807191528.GA14386@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 12/31] introduce ptrace_signal_wake_up() +Message-ID: <20110803190956.GA30959@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO -Content-Length: 1974 -Lines: 67 +Content-Length: 3667 +Lines: 113 -Add the new helper, ptrace_signal_wake_up(), change ptrace.c to use -it instead of signal_wake_up(). +Add the new helper, ptrace_signal_wake_up(), change ptrace.c/signal.c +to use it instead of signal_wake_up() to wake up a STOPPED/TRACED task. The new helper does almost the same, except: @@ -4563,18 +5100,32 @@ wake_up_quiescent(). Signed-off-by: Oleg Nesterov --- - kernel/ptrace.c | 16 ++++++++++++++-- - 1 files changed, 14 insertions(+), 2 deletions(-) + include/linux/ptrace.h | 1 + + kernel/ptrace.c | 20 ++++++++++++++++---- + kernel/signal.c | 2 +- + 3 files changed, 18 insertions(+), 5 deletions(-) +diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h +index 800f113..6d9282a 100644 +--- a/include/linux/ptrace.h ++++ b/include/linux/ptrace.h +@@ -113,6 +113,7 @@ + #include /* For unlikely. */ + #include /* For struct task_struct. */ + ++extern void ptrace_signal_wake_up(struct task_struct *p, int quiescent); + + extern long arch_ptrace(struct task_struct *child, long request, + unsigned long addr, unsigned long data); diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 26ae214..0b2aba5 100644 +index 4194664..1a50090 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c -@@ -24,6 +24,18 @@ - #include +@@ -25,6 +25,18 @@ #include + #include -+static void ptrace_signal_wake_up(struct task_struct *p, int quiescent) ++void ptrace_signal_wake_up(struct task_struct *p, int quiescent) +{ + unsigned int state; + @@ -4587,74 +5138,106 @@ index 26ae214..0b2aba5 100644 + kick_process(p); +} - /* - * ptrace a task: make the debugger its new parent and -@@ -92,7 +104,7 @@ void __ptrace_unlink(struct task_struct *child) + static int ptrace_trapping_sleep_fn(void *flags) + { +@@ -106,7 +118,7 @@ void __ptrace_unlink(struct task_struct *child) * TASK_KILLABLE sleeps. */ - if (child->group_stop & GROUP_STOP_PENDING || task_is_traced(child)) + if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child)) - signal_wake_up(child, task_is_traced(child)); + ptrace_signal_wake_up(child, task_is_traced(child)); spin_unlock(&child->sighand->siglock); } -@@ -245,7 +257,7 @@ static int ptrace_attach(struct task_struct *task) +@@ -296,7 +308,7 @@ static int ptrace_attach(struct task_struct *task, long request, */ - if (task_is_stopped(task)) { - task->group_stop |= GROUP_STOP_PENDING | GROUP_STOP_TRAPPING; + if (task_is_stopped(task) && + task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING)) - signal_wake_up(task, 1); + ptrace_signal_wake_up(task, 1); - wait_trap = true; - } + spin_unlock(&task->sighand->siglock); + +@@ -731,7 +743,7 @@ int ptrace_request(struct task_struct *child, long request, + * tracee into STOP. + */ + if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP))) +- signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); ++ ptrace_signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); + + unlock_task_sighand(child, &flags); + ret = 0; +@@ -760,7 +772,7 @@ int ptrace_request(struct task_struct *child, long request, + * of this trap and now. Trigger re-trap immediately. + */ + if (child->jobctl & JOBCTL_TRAP_NOTIFY) +- signal_wake_up(child, true); ++ ptrace_signal_wake_up(child, true); + + unlock_task_sighand(child, &flags); + ret = 0; +diff --git a/kernel/signal.c b/kernel/signal.c +index 3e8e0b1..0dc6abb 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -854,7 +854,7 @@ static void ptrace_trap_notify(struct task_struct *t) + assert_spin_locked(&t->sighand->siglock); + + task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY); +- signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); ++ ptrace_signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); + } + + /* -- 1.5.5.1 -From davej Sun Aug 7 15:19:14 2011 + +From davej Wed Aug 3 15:15:58 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:14 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:12 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:15:58 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:13:17 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 72BBDA5D58; - Sun, 7 Aug 2011 15:18:12 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id k8I1SMuU0ydh; Sun, 7 Aug 2011 15:18:12 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8FF88DA558; + Wed, 3 Aug 2011 15:12:40 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 1cOfIyuaRoO3; Wed, 3 Aug 2011 15:12:40 -0400 (EDT) Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5DFAB9C7FA; - Sun, 7 Aug 2011 15:18:12 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7B6E8DA4A9; + Wed, 3 Aug 2011 15:12:40 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIAjF028676; - Sun, 7 Aug 2011 15:18:10 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCXpn023459; + Wed, 3 Aug 2011 15:12:33 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:34 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:31 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:01 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:09:59 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 06/22] wait_task_inactive: treat task->state and +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 13/31] wait_task_inactive: treat task->state and match_state as bitmasks -Message-ID: <20110807191531.GA14393@redhat.com> +Message-ID: <20110803190959.GA30962@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 1557 -Lines: 38 +Content-Length: 1558 +Lines: 39 Change wait_task_inactive() to check "state & match_state" instead of "state == match_state". This should not make any difference, but this @@ -4680,10 +5263,10 @@ Signed-off-by: Oleg Nesterov 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c -index 3f2e502..ade7997 100644 +index ccacdbd..66ef2fb 100644 --- a/kernel/sched.c +++ b/kernel/sched.c -@@ -2277,7 +2277,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) +@@ -2289,7 +2289,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) * is actually now running somewhere else! */ while (task_running(rq, p)) { @@ -4695,50 +5278,51 @@ index 3f2e502..ade7997 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:15 2011 + +From davej Wed Aug 3 15:16:24 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:15 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:24 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:15 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:21 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1FD1B1322A2; - Sun, 7 Aug 2011 15:18:15 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 34C189DC30; + Wed, 3 Aug 2011 15:12:43 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id gfct30463vGS; Sun, 7 Aug 2011 15:18:15 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 01C04128FDA; - Sun, 7 Aug 2011 15:18:15 -0400 (EDT) + with ESMTP id RHggq6bqo+Q9; Wed, 3 Aug 2011 15:12:43 -0400 (EDT) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 210D59DC14; + Wed, 3 Aug 2011 15:12:43 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JICKL027777; - Sun, 7 Aug 2011 15:18:13 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JCZsD022395; + Wed, 3 Aug 2011 15:12:36 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:36 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:34 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:03 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:01 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 07/22] introduce TASK_UTRACED state -Message-ID: <20110807191534.GA14396@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 14/31] introduce TASK_UTRACED state +Message-ID: <20110803191001.GA30969@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO -Content-Length: 2912 -Lines: 83 +Content-Length: 2913 +Lines: 84 Introduce TASK_UTRACED state, will be used by utrace instead of TASK_TRACED. @@ -4752,7 +5336,7 @@ Signed-off-by: Oleg Nesterov 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/fs/proc/array.c b/fs/proc/array.c -index 496fef3..bfaa998 100644 +index f0c0ea2..e0daec4 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -138,11 +138,12 @@ static const char * const task_state_array[] = { @@ -4774,7 +5358,7 @@ index 496fef3..bfaa998 100644 static inline const char *get_task_state(struct task_struct *tsk) diff --git a/include/linux/sched.h b/include/linux/sched.h -index b87de83..7a0008c 100644 +index c6d79af..f3f0a77 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -184,16 +184,17 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) @@ -4824,50 +5408,51 @@ index b87de83..7a0008c 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:17 2011 + +From davej Wed Aug 3 15:16:02 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:17 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:17 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:02 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:13:18 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B634FA5D5A; - Sun, 7 Aug 2011 15:18:17 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 3vEyYZtZ8hD5; Sun, 7 Aug 2011 15:18:17 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9921A9C7FA; - Sun, 7 Aug 2011 15:18:17 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D7FFADA44E; + Wed, 3 Aug 2011 15:12:45 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id LFGdvSMswLJT; Wed, 3 Aug 2011 15:12:45 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BA46CDA441; + Wed, 3 Aug 2011 15:12:45 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIFH8028686; - Sun, 7 Aug 2011 15:18:16 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCcpZ029424; + Wed, 3 Aug 2011 15:12:39 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:39 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:37 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:06 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:04 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 08/22] utrace: use TASK_UTRACED instead of TASK_TRACED -Message-ID: <20110807191537.GA14403@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 15/31] utrace: use TASK_UTRACED instead of TASK_TRACED +Message-ID: <20110803191004.GA30972@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 4315 -Lines: 129 +Content-Length: 4316 +Lines: 130 Change utrace.c to use TASK_UTRACED instead of TASK_TRACED. @@ -4887,7 +5472,7 @@ Signed-off-by: Oleg Nesterov 1 files changed, 14 insertions(+), 12 deletions(-) diff --git a/kernel/utrace.c b/kernel/utrace.c -index d7c547c..be98607 100644 +index cebc390..2097103 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -462,6 +462,8 @@ static void put_detached_list(struct list_head *list) @@ -4999,59 +5584,57 @@ index d7c547c..be98607 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:19 2011 + +From davej Wed Aug 3 15:21:40 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:19 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:24 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:21:40 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:42 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 53AC0D89A9; - Sun, 7 Aug 2011 15:18:20 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id CGhyA84rXAKN; Sun, 7 Aug 2011 15:18:20 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 36B2CD8988; - Sun, 7 Aug 2011 15:18:20 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7035E9DECC; + Wed, 3 Aug 2011 15:12:48 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id rmRalMQFlNua; Wed, 3 Aug 2011 15:12:48 -0400 (EDT) +Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5CC809DEC9; + Wed, 3 Aug 2011 15:12:48 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIIFB028696; - Sun, 7 Aug 2011 15:18:18 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JCfwv010344; + Wed, 3 Aug 2011 15:12:41 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:41 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:39 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:09 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:07 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 09/22] tracehooks: kill tracehook_finish_jctl(), add - tracehook_finish_stop() -Message-ID: <20110807191539.GA14406@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 16/31] reintroduce tracehook_finish_jctl() as + utrace_end_stop() +Message-ID: <20110803191007.GA30979@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO -Content-Length: 2781 -Lines: 85 +Content-Length: 2401 +Lines: 77 -tracehook_finish_jctl() is needed to avoid the races with SIGKILL -which wakes up UTRACED task, and thus it should be called every time -after the STOPPED/TRACED/UTRACED returns from schedule(), remember -that TASK_UTRACED can be added while the task is STOPPED/UTRACED. - -- rename it to tracehook_finish_stop(),jctl no longer matches the - reality. +utrace_finish_stop() is needed to avoid the races with SIGKILL which +wakes up UTRACED task, and thus it should be called every time after +the STOPPED/TRACED/UTRACED returns from schedule(), remember that +TASK_UTRACED can be added while the task is STOPPED/UTRACED. - change do_signal_state() to call this helper right after schedule(), otherwise this logic is broken by the upstream changes @@ -5061,62 +5644,56 @@ that TASK_UTRACED can be added while the task is STOPPED/UTRACED. Signed-off-by: Oleg Nesterov --- - include/linux/tracehook.h | 6 +++--- - kernel/signal.c | 5 +++-- - kernel/utrace.c | 2 +- - 3 files changed, 7 insertions(+), 6 deletions(-) + include/linux/utrace.h | 11 +++++++++++ + kernel/signal.c | 5 +++++ + kernel/utrace.c | 2 +- + 3 files changed, 17 insertions(+), 1 deletions(-) -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 7d7bdde..3c7b6b3 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -528,11 +528,11 @@ static inline int tracehook_get_signal(struct task_struct *task, +diff --git a/include/linux/utrace.h b/include/linux/utrace.h +index cf13839..0279c74 100644 +--- a/include/linux/utrace.h ++++ b/include/linux/utrace.h +@@ -719,4 +719,15 @@ static inline void utrace_exit_notify(struct task_struct *task, + utrace_report_death(task, group_dead, signal); } - /** -- * tracehook_finish_jctl - report about return from job control stop -+ * tracehook_finish_stop - report about return from STOPPED/TRACED - * -- * This is called by do_signal_stop() after wakeup. ++/** ++ * utrace_end_stop - report about return from STOPPED/TRACED ++ * + * This is called by do_signal_stop() and ptrace_stop after wakeup. - */ --static inline void tracehook_finish_jctl(void) -+static inline void tracehook_finish_stop(void) - { - if (task_utrace_flags(current)) - utrace_finish_stop(); ++ */ ++static inline void utrace_end_stop(void) ++{ ++ if (task_utrace_flags(current)) ++ utrace_finish_stop(); ++} ++ + #endif /* linux/utrace.h */ diff --git a/kernel/signal.c b/kernel/signal.c -index 4fcf1c7..a7979ad 100644 +index 0dc6abb..a625309 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -1816,6 +1816,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1895,6 +1895,8 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) read_unlock(&tasklist_lock); } -+ tracehook_finish_stop(); ++ utrace_end_stop(); ++ /* * While in TASK_TRACED, we were considered "frozen enough". * Now that we woke up, it's crucial if we're supposed to be -@@ -1952,6 +1953,8 @@ retry: +@@ -2059,6 +2061,9 @@ static bool do_signal_stop(int signr) + /* Now we don't run again until woken by SIGCONT or SIGKILL */ schedule(); - -+ tracehook_finish_stop(); + - spin_lock_irq(¤t->sighand->siglock); ++ utrace_end_stop(); ++ + return true; } else { - ptrace_stop(current->group_stop & GROUP_STOP_SIGMASK, -@@ -1974,8 +1977,6 @@ retry: - - spin_unlock_irq(¤t->sighand->siglock); - -- tracehook_finish_jctl(); -- - return 1; - } - + /* diff --git a/kernel/utrace.c b/kernel/utrace.c -index be98607..daa96b9 100644 +index 2097103..d41b982 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -741,7 +741,7 @@ static bool utrace_reset(struct task_struct *task, struct utrace *utrace) @@ -5131,50 +5708,51 @@ index be98607..daa96b9 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:18 2011 + +From davej Wed Aug 3 15:21:41 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:18 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:21:41 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:22 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:42 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id DD6839C7FA; - Sun, 7 Aug 2011 15:18:22 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 153719DD18; + Wed, 3 Aug 2011 15:12:51 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id hZs6VyadcD7K; Sun, 7 Aug 2011 15:18:22 -0400 (EDT) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C7B129C7DE; - Sun, 7 Aug 2011 15:18:22 -0400 (EDT) + with ESMTP id ffM0oM8RRtgL; Wed, 3 Aug 2011 15:12:51 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 0253E9DEC9; + Wed, 3 Aug 2011 15:12:51 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIKMe020605; - Sun, 7 Aug 2011 15:18:21 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCh9Z023559; + Wed, 3 Aug 2011 15:12:44 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:44 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:42 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:11 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:09 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 10/22] teach wake_up_quiescent() to do "selective" wake_up -Message-ID: <20110807191542.GA14409@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 17/31] teach wake_up_quiescent() to do "selective" wake_up +Message-ID: <20110803191009.GA30982@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 1334 -Lines: 45 +Content-Length: 1335 +Lines: 46 Both utrace and ptrace can want the same thread to be quiescent, in this case its state is TASK_TRACED | TASK_UTRACED. And this also means that @@ -5189,10 +5767,10 @@ Signed-off-by: Oleg Nesterov 1 files changed, 15 insertions(+), 0 deletions(-) diff --git a/kernel/signal.c b/kernel/signal.c -index a7979ad..57552e6 100644 +index a625309..0d1675a 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -651,11 +651,26 @@ void signal_wake_up(struct task_struct *t, int resume) +@@ -701,11 +701,26 @@ void signal_wake_up(struct task_struct *t, int resume) kick_process(t); } @@ -5222,51 +5800,52 @@ index a7979ad..57552e6 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:20 2011 + +From davej Wed Aug 3 15:21:43 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:20 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:25 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:21:43 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:43 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7C2991322AA; - Sun, 7 Aug 2011 15:18:25 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id rHOxOwY4bOdr; Sun, 7 Aug 2011 15:18:25 -0400 (EDT) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 67ABD128FDA; - Sun, 7 Aug 2011 15:18:25 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B0E899DECF; + Wed, 3 Aug 2011 15:12:53 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id s0bDFhAmsQWN; Wed, 3 Aug 2011 15:12:53 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9DC6E9DEC9; + Wed, 3 Aug 2011 15:12:53 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JINVP029911; - Sun, 7 Aug 2011 15:18:23 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCkUr029453; + Wed, 3 Aug 2011 15:12:46 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:47 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:45 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:14 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:12 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 11/22] ptrace_stop: do not assume the task is running after +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 18/31] ptrace_stop: do not assume the task is running after wake_up_quiescent() -Message-ID: <20110807191545.GA14416@redhat.com> +Message-ID: <20110803191012.GA30985@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 961 -Lines: 30 +Content-Length: 956 +Lines: 31 If ptrace_stop() sets TASK_TRACED and then detects we should not stop, it can race with utrace_do_stop() which can see TASK_TRACED and add @@ -5278,10 +5857,10 @@ Signed-off-by: Oleg Nesterov 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/kernel/signal.c b/kernel/signal.c -index 57552e6..89e691d 100644 +index 0d1675a..249760f 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -1829,6 +1829,14 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1908,6 +1908,14 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) if (clear_code) current->exit_code = 0; read_unlock(&tasklist_lock); @@ -5295,173 +5874,297 @@ index 57552e6..89e691d 100644 + schedule(); } - tracehook_finish_stop(); + utrace_end_stop(); -- 1.5.5.1 -From davej Sun Aug 7 15:19:21 2011 + +From davej Wed Aug 3 15:16:26 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:21 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:26 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:28 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:22 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1B4B91322AE; - Sun, 7 Aug 2011 15:18:28 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 69B489DC62; + Wed, 3 Aug 2011 15:12:56 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id q5tv0cJeZqLD; Sun, 7 Aug 2011 15:18:28 -0400 (EDT) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 071461322A9; - Sun, 7 Aug 2011 15:18:28 -0400 (EDT) + with ESMTP id 4BNNeoYSdCTc; Wed, 3 Aug 2011 15:12:56 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4A9899DC14; + Wed, 3 Aug 2011 15:12:56 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIPFB020635; - Sun, 7 Aug 2011 15:18:26 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCnRf023575; + Wed, 3 Aug 2011 15:12:49 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:49 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:47 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:16 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:14 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 12/22] get_signal_to_deliver: restructure utrace/ptrace - signal reporting -Message-ID: <20110807191547.GA14419@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 19/31] get_signal_to_deliver: restore/restructure + utrace/ptrace signal reporting +Message-ID: <20110803191014.GA30992@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 2011 -Lines: 72 +Content-Length: 3556 +Lines: 115 -get_signal_to_deliver() assumes that either tracehook_get_signal() does -nothing (without CONFIG_UTRACE), or it also reports the signal to ptrace -engine implemented on top of utrace. Now that ptrace works independently -this doesn't work. +- Reintroduce tracehook_get_signal() as utrace_hook_signal(). -Change the code to call ptrace_signal() after tracehook_get_signal(). +- Change get_signal_to_deliver() to call utrace_hook_signal() first, + before dequeue_signal() -Move ->ptrace check from ptrace_signal() to get_signal_to_deliver(), -we do not want to change *return_ka if it was initialized by utrace -and the task is not traced. +- Always call ptrace_signal() if signal != SIGKILL, no matter whether + this signal comes from utrace or not. + + Since this can change signr again, update "struct k_sigaction *ka" + in this case. IOW, roughly, ptrace acts as if it is the last attached engine, it takes the final decision about the signal. Signed-off-by: Oleg Nesterov --- - kernel/signal.c | 24 +++++++++++------------- - 1 files changed, 11 insertions(+), 13 deletions(-) + include/linux/utrace.h | 31 +++++++++++++++++++++++++++++++ + kernel/signal.c | 30 ++++++++++++++++++++---------- + 2 files changed, 51 insertions(+), 10 deletions(-) +diff --git a/include/linux/utrace.h b/include/linux/utrace.h +index 0279c74..63103e2 100644 +--- a/include/linux/utrace.h ++++ b/include/linux/utrace.h +@@ -730,4 +730,35 @@ static inline void utrace_end_stop(void) + utrace_finish_stop(); + } + ++/** ++ * utrace_hook_signal - deliver synthetic signal to traced task ++ * @task: @current ++ * @regs: task_pt_regs(@current) ++ * @info: details of synthetic signal ++ * @return_ka: sigaction for synthetic signal ++ * ++ * Return zero to check for a real pending signal normally. ++ * Return -1 after releasing the siglock to repeat the check. ++ * Return a signal number to induce an artificial signal delivery, ++ * setting *@info and *@return_ka to specify its details and behavior. ++ * ++ * The @return_ka->sa_handler value controls the disposition of the ++ * signal, no matter the signal number. For %SIG_DFL, the return value ++ * is a representative signal to indicate the behavior (e.g. %SIGTERM ++ * for death, %SIGQUIT for core dump, %SIGSTOP for job control stop, ++ * %SIGTSTP for stop unless in an orphaned pgrp), but the signal number ++ * reported will be @info->si_signo instead. ++ * ++ * Called with @task->sighand->siglock held, before dequeuing pending signals. ++ */ ++static inline int utrace_hook_signal(struct task_struct *task, ++ struct pt_regs *regs, ++ siginfo_t *info, ++ struct k_sigaction *return_ka) ++{ ++ if (unlikely(task_utrace_flags(task))) ++ return utrace_get_signal(task, regs, info, return_ka); ++ return 0; ++} ++ + #endif /* linux/utrace.h */ diff --git a/kernel/signal.c b/kernel/signal.c -index 89e691d..d0e0c67 100644 +index 249760f..3c783d3 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -2006,9 +2006,6 @@ retry: - static int ptrace_signal(int signr, siginfo_t *info, - struct pt_regs *regs, void *cookie) - { -- if (!task_ptrace(current)) -- return signr; -- - ptrace_signal_deliver(regs, cookie); +@@ -2234,17 +2234,27 @@ relock: + for (;;) { + struct k_sigaction *ka; - /* Let the debugger run. */ -@@ -2110,6 +2107,7 @@ relock: - signr = tracehook_get_signal(current, regs, info, return_ka); - if (unlikely(signr < 0)) +- if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) && +- do_signal_stop(0)) ++ signr = utrace_hook_signal(current, regs, info, return_ka); ++ if (unlikely(signr < 0)) goto relock; + +- if (unlikely(current->jobctl & JOBCTL_TRAP_MASK)) { +- do_jobctl_trap(); +- spin_unlock_irq(&sighand->siglock); +- goto relock; +- } ++ if (unlikely(signr != 0)) ++ ka = return_ka; ++ else { ++ if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) && ++ do_signal_stop(0)) ++ goto relock; + +- signr = dequeue_signal(current, ¤t->blocked, info); ++ if (unlikely(current->jobctl & JOBCTL_TRAP_MASK)) { ++ do_jobctl_trap(); ++ spin_unlock_irq(&sighand->siglock); ++ goto relock; ++ } + - if (unlikely(signr != 0)) - ka = return_ka; - else { -@@ -2117,18 +2115,18 @@ relock: - GROUP_STOP_PENDING) && do_signal_stop(0)) - goto relock; - -- signr = dequeue_signal(current, ¤t->blocked, -- info); + signr = dequeue_signal(current, ¤t->blocked, info); - -- if (!signr) -- break; /* will return 0 */ ++ + ka = &sighand->action[signr-1]; + } -- if (signr != SIGKILL) { -- signr = ptrace_signal(signr, info, -- regs, cookie); -- if (!signr) -- continue; -- } -+ if (!signr) -+ break; /* will return 0 */ -+ -+ if (signr != SIGKILL && current->ptrace) { -+ signr = ptrace_signal(signr, info, regs, cookie); -+ if (!signr) -+ continue; + if (!signr) + break; /* will return 0 */ +@@ -2254,9 +2264,9 @@ relock: + regs, cookie); + if (!signr) + continue; +- } - ka = &sighand->action[signr-1]; - } +- ka = &sighand->action[signr-1]; ++ ka = &sighand->action[signr-1]; ++ } + + /* Trace actually delivered signals. */ + trace_signal_deliver(signr, info, ka); -- 1.5.5.1 -From davej Sun Aug 7 15:19:22 2011 + +From davej Wed Aug 3 15:16:27 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:22 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:27 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:30 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:22 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BFD8F1322A2; - Sun, 7 Aug 2011 15:18:30 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 119589DC72; + Wed, 3 Aug 2011 15:12:59 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id JczS8HsLYY6X; Sun, 7 Aug 2011 15:18:30 -0400 (EDT) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A8F91128FDA; - Sun, 7 Aug 2011 15:18:30 -0400 (EDT) + with ESMTP id Vxp8fnt8hEcf; Wed, 3 Aug 2011 15:12:59 -0400 (EDT) +Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F22049DCAE; + Wed, 3 Aug 2011 15:12:58 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIS1m029940; - Sun, 7 Aug 2011 15:18:29 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JCpO4010401; + Wed, 3 Aug 2011 15:12:52 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:52 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:50 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:19 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:17 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 13/22] introduce ptrace_set_syscall_trace() -Message-ID: <20110807191550.GA14426@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 20/31] utrace_get_signal: + s/JOBCTL_STOP_PENDING/JOBCTL_PENDING_MASK/ +Message-ID: <20110803191017.GA30995@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO -Content-Length: 1580 -Lines: 51 +Content-Length: 1204 +Lines: 33 + +utrace_get_signal() checks JOBCTL_STOP_PENDING to detect the +case when we should not try to dequeue the signal but should +try to participate in the group-stop. + +With the recent changes this is not enough, everything which +contrbutes to recalc_sigpending_tsk() should be respected. + +Check JOBCTL_PENDING_MASK instead. This matches the +JOBCTL_STOP_PENDING | JOBCTL_TRAP_MASK code in the caller, +get_signal_to_deliver(). Note that this code won't run if +utrace_get_signal() returns signr > 0. + +Signed-off-by: Oleg Nesterov +--- + kernel/utrace.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/kernel/utrace.c b/kernel/utrace.c +index d41b982..0bb0a06 100644 +--- a/kernel/utrace.c ++++ b/kernel/utrace.c +@@ -2027,7 +2027,7 @@ int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, + ka = NULL; + memset(return_ka, 0, sizeof *return_ka); + } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || +- unlikely(task->jobctl & JOBCTL_STOP_PENDING)) { ++ unlikely(task->jobctl & JOBCTL_PENDING_MASK)) { + /* + * If no engine is interested in intercepting signals or + * we must stop, let the caller just dequeue them normally +-- +1.5.5.1 + + +From davej Wed Aug 3 15:16:03 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:16:03 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:13:19 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A9253DA3CB; + Wed, 3 Aug 2011 15:13:01 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id HLlRhTJ2MbYS; Wed, 3 Aug 2011 15:13:01 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9582C4C43B; + Wed, 3 Aug 2011 15:13:01 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCsFX008586; + Wed, 3 Aug 2011 15:12:54 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:22 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:20 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 21/31] introduce ptrace_set_syscall_trace() +Message-ID: <20110803191020.GA31002@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Status: RO +Content-Length: 1549 +Lines: 52 No functional changes. Add the new helper, ptrace_set_syscall_trace(), which should be used to set/clear TIF_SYSCALL_TRACE in ptrace code. @@ -5473,10 +6176,10 @@ Signed-off-by: Oleg Nesterov 1 files changed, 10 insertions(+), 5 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 0b2aba5..b6fd922 100644 +index 1a50090..dc2ad34 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c -@@ -37,6 +37,14 @@ static void ptrace_signal_wake_up(struct task_struct *p, int quiescent) +@@ -38,6 +38,14 @@ void ptrace_signal_wake_up(struct task_struct *p, int quiescent) kick_process(p); } @@ -5488,10 +6191,10 @@ index 0b2aba5..b6fd922 100644 + clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); +} + - /* - * ptrace a task: make the debugger its new parent and - * move it to the ptrace list. -@@ -364,7 +372,7 @@ static int ptrace_detach(struct task_struct *child, unsigned int data) + static int ptrace_trapping_sleep_fn(void *flags) + { + schedule(); +@@ -418,7 +426,7 @@ static int ptrace_detach(struct task_struct *child, unsigned int data) /* Architecture-specific hardware disable .. */ ptrace_disable(child); @@ -5500,7 +6203,7 @@ index 0b2aba5..b6fd922 100644 write_lock_irq(&tasklist_lock); /* -@@ -551,10 +559,7 @@ static int ptrace_resume(struct task_struct *child, long request, +@@ -606,10 +614,7 @@ static int ptrace_resume(struct task_struct *child, long request, if (!valid_signal(data)) return -EIO; @@ -5515,50 +6218,51 @@ index 0b2aba5..b6fd922 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:23 2011 + +From davej Wed Aug 3 15:21:45 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:23 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:21:45 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:33 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:43 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 585699C7DE; - Sun, 7 Aug 2011 15:18:33 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5C4889DEE6; + Wed, 3 Aug 2011 15:13:04 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id Zp+5oAzhYq2W; Sun, 7 Aug 2011 15:18:33 -0400 (EDT) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 44532909E4; - Sun, 7 Aug 2011 15:18:33 -0400 (EDT) + with ESMTP id eXIPU4nVv+7Z; Wed, 3 Aug 2011 15:13:04 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 3F82C9DED6; + Wed, 3 Aug 2011 15:13:04 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIV6n020657; - Sun, 7 Aug 2011 15:18:31 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCueo029507; + Wed, 3 Aug 2011 15:12:57 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:54 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:52 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:24 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:22 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 14/22] introduce PT_SYSCALL_TRACE flag -Message-ID: <20110807191552.GA14429@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 22/31] introduce PT_SYSCALL_TRACE flag +Message-ID: <20110803191022.GA31005@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 2235 -Lines: 72 +Content-Length: 2268 +Lines: 73 Currently tracehooks assume that if the ptraced task has TIF_SYSCALL_TRACE set, the tracee should report the syscall. @@ -5577,33 +6281,33 @@ Signed-off-by: Oleg Nesterov 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h -index 9178d5c..98d995d 100644 +index 6d9282a..c10f610 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h -@@ -90,6 +90,8 @@ +@@ -104,6 +104,8 @@ #define PT_TRACE_MASK 0x000003f4 -+#define PT_SYSCALL_TRACE 0x00010000 ++#define PT_SYSCALL_TRACE 0x00020000 + /* single stepping state bits (used on ARM and PA-RISC) */ #define PT_SINGLESTEP_BIT 31 #define PT_SINGLESTEP (1<ptrace = 0; - if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) { +@@ -227,6 +229,7 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) + + if (unlikely(ptrace) && current->ptrace) { child->ptrace = current->ptrace; + child->ptrace &= ~PT_SYSCALL_TRACE; __ptrace_link(child, current->parent); - } + if (child->ptrace & PT_SEIZED) diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 3c7b6b3..6ce7a37 100644 +index ec2af67..eb9fe30 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h -@@ -76,7 +76,7 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) +@@ -59,7 +59,7 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) { - int ptrace = task_ptrace(current); + int ptrace = current->ptrace; - if (!(ptrace & PT_PTRACED)) + if (!(ptrace & PT_SYSCALL_TRACE)) @@ -5611,10 +6315,10 @@ index 3c7b6b3..6ce7a37 100644 ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index b6fd922..0825a01 100644 +index dc2ad34..7deb292 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c -@@ -39,10 +39,13 @@ static void ptrace_signal_wake_up(struct task_struct *p, int quiescent) +@@ -40,10 +40,13 @@ void ptrace_signal_wake_up(struct task_struct *p, int quiescent) static void ptrace_set_syscall_trace(struct task_struct *p, bool on) { @@ -5629,55 +6333,56 @@ index b6fd922..0825a01 100644 + } } - /* + static int ptrace_trapping_sleep_fn(void *flags) -- 1.5.5.1 -From davej Sun Aug 7 15:19:24 2011 + +From davej Wed Aug 3 15:16:05 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:24 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:05 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:35 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:13:20 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F0377D89A9; - Sun, 7 Aug 2011 15:18:35 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E516ADA488; + Wed, 3 Aug 2011 15:13:06 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id cBLqfABIHZ6h; Sun, 7 Aug 2011 15:18:35 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id DC799D8988; - Sun, 7 Aug 2011 15:18:35 -0400 (EDT) + with ESMTP id rP7Um8DZjclX; Wed, 3 Aug 2011 15:13:06 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D155EDA3F8; + Wed, 3 Aug 2011 15:13:06 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIXU3007727; - Sun, 7 Aug 2011 15:18:34 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCxfF029532; + Wed, 3 Aug 2011 15:13:00 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:15:57 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:55 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:27 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:25 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 15/22] utrace: don't clear TIF_SYSCALL_TRACE if it is +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 23/31] utrace: don't clear TIF_SYSCALL_TRACE if it is needed by ptrace -Message-ID: <20110807191555.GA14436@redhat.com> +Message-ID: <20110803191025.GA31012@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 796 -Lines: 23 +Content-Length: 797 +Lines: 24 TIF_SYSCALL_TRACE should be cleared only if both ptrace and utrace do not want it, change utrace_reset() to check PT_SYSCALL_TRACE before @@ -5689,7 +6394,7 @@ Signed-off-by: Oleg Nesterov 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/kernel/utrace.c b/kernel/utrace.c -index daa96b9..a824ac3 100644 +index 0bb0a06..bebf6de 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -697,6 +697,7 @@ static bool utrace_reset(struct task_struct *task, struct utrace *utrace) @@ -5703,50 +6408,51 @@ index daa96b9..a824ac3 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:25 2011 + +From davej Wed Aug 3 15:16:08 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:25 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:38 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:08 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:29 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A6B3C9C7DE; - Sun, 7 Aug 2011 15:18:38 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id ln+MaW5alQl7; Sun, 7 Aug 2011 15:18:38 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8A6D2909E4; - Sun, 7 Aug 2011 15:18:38 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 80872DA4B2; + Wed, 3 Aug 2011 15:13:09 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id AbpC0Wk1ZhtT; Wed, 3 Aug 2011 15:13:09 -0400 (EDT) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6D97DDA3F8; + Wed, 3 Aug 2011 15:13:09 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIaYf007737; - Sun, 7 Aug 2011 15:18:36 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JD2RU022591; + Wed, 3 Aug 2011 15:13:02 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:16:00 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:15:58 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:30 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:28 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 16/22] introduce task_utrace_lock/task_utrace_unlock -Message-ID: <20110807191558.GA14440@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 24/31] introduce task_utrace_lock/task_utrace_unlock +Message-ID: <20110803191028.GA31015@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO -Content-Length: 2189 -Lines: 80 +Content-Length: 2190 +Lines: 81 - Add task_utrace_lock(task). It simply takes task->utrace->lock if this task was ever utraced. Otherwise it takes task_lock(), this @@ -5763,10 +6469,10 @@ Signed-off-by: Oleg Nesterov 2 files changed, 35 insertions(+), 0 deletions(-) diff --git a/include/linux/utrace.h b/include/linux/utrace.h -index f251efe..5176f5f 100644 +index 63103e2..f37373b 100644 --- a/include/linux/utrace.h +++ b/include/linux/utrace.h -@@ -109,6 +109,12 @@ void utrace_signal_handler(struct task_struct *, int); +@@ -117,6 +117,12 @@ void utrace_signal_handler(struct task_struct *, int); #ifndef CONFIG_UTRACE @@ -5779,7 +6485,7 @@ index f251efe..5176f5f 100644 /* * uses these accessors to avoid #ifdef CONFIG_UTRACE. */ -@@ -131,6 +137,9 @@ static inline void task_utrace_proc_status(struct seq_file *m, +@@ -139,6 +145,9 @@ static inline void task_utrace_proc_status(struct seq_file *m, #else /* CONFIG_UTRACE */ @@ -5790,7 +6496,7 @@ index f251efe..5176f5f 100644 { return task->utrace_flags; diff --git a/kernel/utrace.c b/kernel/utrace.c -index a824ac3..508c13c 100644 +index bebf6de..960dd9e 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -79,6 +79,32 @@ static int __init utrace_init(void) @@ -5829,51 +6535,52 @@ index a824ac3..508c13c 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:27 2011 + +From davej Wed Aug 3 15:21:46 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:27 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:41 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:21:46 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:43 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 41B111322A2; - Sun, 7 Aug 2011 15:18:41 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id ypKNrfgt9t+i; Sun, 7 Aug 2011 15:18:41 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2D805128FDA; - Sun, 7 Aug 2011 15:18:41 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 24B3E9DEF6; + Wed, 3 Aug 2011 15:13:12 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 2jg9j3-p4bHL; Wed, 3 Aug 2011 15:13:12 -0400 (EDT) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 119759DEF9; + Wed, 3 Aug 2011 15:13:12 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIdnm028810; - Sun, 7 Aug 2011 15:18:39 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JD485022603; + Wed, 3 Aug 2011 15:13:05 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:16:02 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:16:00 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:32 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:30 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 17/22] teach ptrace_set_syscall_trace() to play well with +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 25/31] teach ptrace_set_syscall_trace() to play well with utrace -Message-ID: <20110807191600.GA14443@redhat.com> +Message-ID: <20110803191030.GA31018@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO -Content-Length: 1512 -Lines: 48 +Content-Length: 1545 +Lines: 49 1. ptrace_set_syscall_trace(true)->set_tsk_thread_flag(TIF_SYSCALL_TRACE) can race with utrace_control()->utrace_reset() path which can miss @@ -5892,18 +6599,18 @@ Signed-off-by: Oleg Nesterov 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 0825a01..209ea2d 100644 +index 7deb292..69850e9 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c -@@ -23,6 +23,7 @@ - #include +@@ -24,6 +24,7 @@ #include #include + #include +#include - static void ptrace_signal_wake_up(struct task_struct *p, int quiescent) + void ptrace_signal_wake_up(struct task_struct *p, int quiescent) { -@@ -39,13 +40,16 @@ static void ptrace_signal_wake_up(struct task_struct *p, int quiescent) +@@ -40,13 +41,16 @@ void ptrace_signal_wake_up(struct task_struct *p, int quiescent) static void ptrace_set_syscall_trace(struct task_struct *p, bool on) { @@ -5920,54 +6627,55 @@ index 0825a01..209ea2d 100644 + task_utrace_unlock(p); } - /* + static int ptrace_trapping_sleep_fn(void *flags) -- 1.5.5.1 -From davej Sun Aug 7 15:19:27 2011 + +From davej Wed Aug 3 15:16:29 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:27 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:43 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:28 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:24 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E37B59C7DE; - Sun, 7 Aug 2011 15:18:43 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id NRVgSzxr7avy; Sun, 7 Aug 2011 15:18:43 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C6D6E909E4; - Sun, 7 Aug 2011 15:18:43 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 062709DE55; + Wed, 3 Aug 2011 15:13:15 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id lhwVoEywGaPJ; Wed, 3 Aug 2011 15:13:14 -0400 (EDT) +Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E4C139DE11; + Wed, 3 Aug 2011 15:13:14 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIfAM007754; - Sun, 7 Aug 2011 15:18:42 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JD7Go010523; + Wed, 3 Aug 2011 15:13:08 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:16:05 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:16:03 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:35 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:33 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 18/22] introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK -Message-ID: <20110807191603.GA14450@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 26/31] introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK +Message-ID: <20110803191033.GA31025@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO -Content-Length: 3724 -Lines: 107 +Content-Length: 3723 +Lines: 108 Add the new internal ptrace flags, PT_SINGLE_STEP and PT_SINGLE_BLOCK. @@ -5987,10 +6695,10 @@ Signed-off-by: Oleg Nesterov 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c -index 807c2a2..7ab475f 100644 +index 8252879..d1557dc 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c -@@ -807,6 +807,7 @@ static int ioperm_get(struct task_struct *target, +@@ -808,6 +808,7 @@ static int ioperm_get(struct task_struct *target, */ void ptrace_disable(struct task_struct *child) { @@ -5999,33 +6707,33 @@ index 807c2a2..7ab475f 100644 #ifdef TIF_SYSCALL_EMU clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h -index 98d995d..65b1e4f 100644 +index c10f610..2743315 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h -@@ -91,6 +91,8 @@ +@@ -105,6 +105,8 @@ #define PT_TRACE_MASK 0x000003f4 - #define PT_SYSCALL_TRACE 0x00010000 -+#define PT_SINGLE_STEP 0x00020000 -+#define PT_SINGLE_BLOCK 0x00040000 + #define PT_SYSCALL_TRACE 0x00020000 ++#define PT_SINGLE_STEP 0x00040000 ++#define PT_SINGLE_BLOCK 0x00080000 /* single stepping state bits (used on ARM and PA-RISC) */ #define PT_SINGLESTEP_BIT 31 -@@ -189,7 +191,8 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) - child->ptrace = 0; - if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) { +@@ -229,7 +231,8 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) + + if (unlikely(ptrace) && current->ptrace) { child->ptrace = current->ptrace; - child->ptrace &= ~PT_SYSCALL_TRACE; + child->ptrace &= + ~(PT_SYSCALL_TRACE | PT_SINGLE_STEP | PT_SINGLE_BLOCK); __ptrace_link(child, current->parent); - } + if (child->ptrace & PT_SEIZED) diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 6ce7a37..06edb52 100644 +index eb9fe30..21c8ca2 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h -@@ -121,6 +121,9 @@ static inline __must_check int tracehook_report_syscall_entry( +@@ -104,6 +104,9 @@ static inline __must_check int tracehook_report_syscall_entry( return 0; } @@ -6035,7 +6743,7 @@ index 6ce7a37..06edb52 100644 /** * tracehook_report_syscall_exit - task has just finished a system call * @regs: user register state of current task -@@ -143,7 +146,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) +@@ -126,7 +129,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) utrace_report_syscall_exit(regs); @@ -6044,7 +6752,7 @@ index 6ce7a37..06edb52 100644 siginfo_t info; user_single_step_siginfo(current, regs, &info); force_sig_info(SIGTRAP, &info, current); -@@ -436,7 +439,7 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, +@@ -157,7 +160,7 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, { if (task_utrace_flags(current)) utrace_signal_handler(current, stepping); @@ -6054,10 +6762,10 @@ index 6ce7a37..06edb52 100644 } diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 209ea2d..44908d0 100644 +index 69850e9..d250a71 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c -@@ -575,13 +575,16 @@ static int ptrace_resume(struct task_struct *child, long request, +@@ -630,13 +630,16 @@ static int ptrace_resume(struct task_struct *child, long request, clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); #endif @@ -6077,51 +6785,52 @@ index 209ea2d..44908d0 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:29 2011 + +From davej Wed Aug 3 15:16:30 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:29 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:30 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:46 -0400 (EDT) + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:25 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 810E31322A2; - Sun, 7 Aug 2011 15:18:46 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B3BF49DE11; + Wed, 3 Aug 2011 15:13:17 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id ptiIThWTq2a6; Sun, 7 Aug 2011 15:18:46 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6B665128FDA; - Sun, 7 Aug 2011 15:18:46 -0400 (EDT) + with ESMTP id zC72ecV9Jz07; Wed, 3 Aug 2011 15:13:17 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 98ACE9DE59; + Wed, 3 Aug 2011 15:13:17 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIiI8007757; - Sun, 7 Aug 2011 15:18:44 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JDATh023726; + Wed, 3 Aug 2011 15:13:10 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:16:08 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:16:06 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:38 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:36 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 19/22] utrace: finish_resume_report: don't do +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 27/31] utrace: finish_resume_report: don't do user_xxx_step() if ptrace_wants_step() -Message-ID: <20110807191606.GA14453@redhat.com> +Message-ID: <20110803191036.GA31028@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO -Content-Length: 2740 -Lines: 83 +Content-Length: 2741 +Lines: 84 finish_resume_report() should not enable/disable the stepping if ptrace_wants_step() == T. If ptrace wants block_step while utrace @@ -6138,10 +6847,10 @@ Signed-off-by: Oleg Nesterov 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 06edb52..5612d2d 100644 +index 21c8ca2..b6812d4 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h -@@ -121,8 +121,8 @@ static inline __must_check int tracehook_report_syscall_entry( +@@ -104,8 +104,8 @@ static inline __must_check int tracehook_report_syscall_entry( return 0; } @@ -6152,7 +6861,7 @@ index 06edb52..5612d2d 100644 /** * tracehook_report_syscall_exit - task has just finished a system call -@@ -146,7 +146,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) +@@ -129,7 +129,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) utrace_report_syscall_exit(regs); @@ -6161,7 +6870,7 @@ index 06edb52..5612d2d 100644 siginfo_t info; user_single_step_siginfo(current, regs, &info); force_sig_info(SIGTRAP, &info, current); -@@ -439,7 +439,7 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, +@@ -160,7 +160,7 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, { if (task_utrace_flags(current)) utrace_signal_handler(current, stepping); @@ -6171,10 +6880,10 @@ index 06edb52..5612d2d 100644 } diff --git a/kernel/utrace.c b/kernel/utrace.c -index 508c13c..fbabb81 100644 +index 960dd9e..05e8532 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c -@@ -1828,7 +1828,8 @@ static void finish_resume_report(struct task_struct *task, +@@ -1829,7 +1829,8 @@ static void finish_resume_report(struct task_struct *task, case UTRACE_BLOCKSTEP: if (likely(arch_has_block_step())) { @@ -6184,7 +6893,7 @@ index 508c13c..fbabb81 100644 break; } -@@ -1841,7 +1842,8 @@ static void finish_resume_report(struct task_struct *task, +@@ -1842,7 +1843,8 @@ static void finish_resume_report(struct task_struct *task, case UTRACE_SINGLESTEP: if (likely(arch_has_single_step())) { @@ -6194,7 +6903,7 @@ index 508c13c..fbabb81 100644 } else { /* * This means some callback is to blame for failing -@@ -1856,7 +1858,8 @@ static void finish_resume_report(struct task_struct *task, +@@ -1857,7 +1859,8 @@ static void finish_resume_report(struct task_struct *task, case UTRACE_REPORT: case UTRACE_RESUME: default: @@ -6207,50 +6916,51 @@ index 508c13c..fbabb81 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:30 2011 + +From davej Wed Aug 3 15:16:32 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:30 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:49 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:32 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:25 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1C4A79C7DE; - Sun, 7 Aug 2011 15:18:49 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id GxHOzMqYQY8N; Sun, 7 Aug 2011 15:18:49 -0400 (EDT) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 066D2909E4; - Sun, 7 Aug 2011 15:18:49 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 614CD9DE73; + Wed, 3 Aug 2011 15:13:20 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id jcWOXzUaaIYu; Wed, 3 Aug 2011 15:13:20 -0400 (EDT) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 438889DE59; + Wed, 3 Aug 2011 15:13:20 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIkkD030034; - Sun, 7 Aug 2011 15:18:47 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JDDZ7029595; + Wed, 3 Aug 2011 15:13:13 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:16:10 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:16:08 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:40 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:38 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 20/22] ptrace: shift user_*_step() from ptrace_resume() to +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 28/31] ptrace: shift user_*_step() from ptrace_resume() to ptrace_stop() -Message-ID: <20110807191608.GA14460@redhat.com> +Message-ID: <20110803191038.GA31035@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 2384 +Content-Length: 2374 Lines: 70 1. ptrace_resume() plays with the stopped task which can be also @@ -6276,14 +6986,14 @@ Lines: 70 Signed-off-by: Oleg Nesterov --- kernel/ptrace.c | 4 ---- - kernel/signal.c | 12 ++++++++++++ - 2 files changed, 12 insertions(+), 4 deletions(-) + kernel/signal.c | 11 +++++++++++ + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 44908d0..d37b30d 100644 +index d250a71..d1ef124 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c -@@ -580,14 +580,10 @@ static int ptrace_resume(struct task_struct *child, long request, +@@ -635,14 +635,10 @@ static int ptrace_resume(struct task_struct *child, long request, if (unlikely(!arch_has_block_step())) return -EIO; child->ptrace |= PT_SINGLE_BLOCK; @@ -6299,14 +7009,13 @@ index 44908d0..d37b30d 100644 child->exit_code = data; diff --git a/kernel/signal.c b/kernel/signal.c -index d0e0c67..bc40bd7 100644 +index 3c783d3..43a3e77 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -1840,6 +1840,18 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) - } +@@ -1920,6 +1920,17 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) + + utrace_end_stop(); - tracehook_finish_stop(); -+ + if (current->ptrace & PT_SINGLE_BLOCK) + user_enable_block_step(current); + else if (current->ptrace & PT_SINGLE_STEP) @@ -6324,50 +7033,51 @@ index d0e0c67..bc40bd7 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:31 2011 + +From davej Wed Aug 3 15:16:34 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:31 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:51 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:16:34 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:25 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id AD8D0D89A9; - Sun, 7 Aug 2011 15:18:51 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id LHAT6DyOymTI; Sun, 7 Aug 2011 15:18:51 -0400 (EDT) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 99798D8988; - Sun, 7 Aug 2011 15:18:51 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1A6019DE59; + Wed, 3 Aug 2011 15:13:23 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id db2hhAqFwsPu; Wed, 3 Aug 2011 15:13:23 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 034739DE83; + Wed, 3 Aug 2011 15:13:23 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p77JIn3U030041; - Sun, 7 Aug 2011 15:18:50 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JDFNp008715; + Wed, 3 Aug 2011 15:13:16 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:16:13 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:16:11 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:43 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:41 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 21/22] ptrace_disable: no need to disable stepping -Message-ID: <20110807191611.GA14463@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 29/31] ptrace_disable: no need to disable stepping +Message-ID: <20110803191041.GA31039@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO -Content-Length: 944 -Lines: 28 +Content-Length: 945 +Lines: 29 ptrace_disable() is called when the tracee is quiescent and we are going to untrace. This means we are going to clear ->ptrace @@ -6383,10 +7093,10 @@ Signed-off-by: Oleg Nesterov 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c -index 7ab475f..f1cdc7d 100644 +index d1557dc..96d315a 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c -@@ -807,8 +807,6 @@ static int ioperm_get(struct task_struct *target, +@@ -808,8 +808,6 @@ static int ioperm_get(struct task_struct *target, */ void ptrace_disable(struct task_struct *child) { @@ -6398,50 +7108,51 @@ index 7ab475f..f1cdc7d 100644 -- 1.5.5.1 -From davej Sun Aug 7 15:19:32 2011 + +From davej Wed Aug 3 15:21:48 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] +Received: from mail.corp.redhat.com [10.5.5.52] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Sun, 07 Aug 2011 15:19:32 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Sun, 7 Aug 2011 15:18:54 -0400 (EDT) + for (single-drop); Wed, 03 Aug 2011 15:21:48 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:52 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 57405D89A9; - Sun, 7 Aug 2011 15:18:54 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id XgEdPuPz9LNX; Sun, 7 Aug 2011 15:18:54 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 42E6BD8988; - Sun, 7 Aug 2011 15:18:54 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 95706917AF; + Wed, 3 Aug 2011 15:13:25 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id ctq4DF3wXncJ; Wed, 3 Aug 2011 15:13:25 -0400 (EDT) +Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7FD14914AF; + Wed, 3 Aug 2011 15:13:25 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p77JIqEO027919; - Sun, 7 Aug 2011 15:18:52 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JDIRO010579; + Wed, 3 Aug 2011 15:13:18 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Sun, 7 Aug 2011 21:16:15 +0200 (CEST) -Date: Sun, 7 Aug 2011 21:16:13 +0200 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:46 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:44 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 22/22] ptrace_report_syscall: check TIF_SYSCALL_EMU -Message-ID: <20110807191613.GA14470@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 30/31] ptrace_report_syscall: check TIF_SYSCALL_EMU +Message-ID: <20110803191044.GA31046@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO -Content-Length: 862 -Lines: 27 +Content-Length: 858 +Lines: 28 4d16a64 "introduce PT_SYSCALL_TRACE flag" breaks PTRACE_SYSEMU which doesn't set PT_SYSCALL_TRACE. @@ -6456,12 +7167,12 @@ Signed-off-by: Oleg Nesterov 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 5612d2d..ac833de 100644 +index b6812d4..90ca578 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h -@@ -76,7 +76,7 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) +@@ -59,7 +59,7 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) { - int ptrace = task_ptrace(current); + int ptrace = current->ptrace; - if (!(ptrace & PT_SYSCALL_TRACE)) + if (!(ptrace & PT_SYSCALL_TRACE) && !test_thread_flag(TIF_SYSCALL_EMU)) @@ -6471,7 +7182,81 @@ index 5612d2d..ac833de 100644 -- 1.5.5.1 -From davej Tue Aug 9 13:34:35 2011 + +From davej Wed Aug 3 15:21:49 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Wed, 03 Aug 2011 15:21:49 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:52 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 400F49191F; + Wed, 3 Aug 2011 15:13:28 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id UeLOLM29JRc7; Wed, 3 Aug 2011 15:13:28 -0400 (EDT) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2D05C903F6; + Wed, 3 Aug 2011 15:13:28 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JDKCA023784; + Wed, 3 Aug 2011 15:13:21 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 3 Aug 2011 21:10:48 +0200 (CEST) +Date: Wed, 3 Aug 2011 21:10:46 +0200 +From: Oleg Nesterov +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH 31/31] utrace_resume: check irqs_disabled() to shut up + lockdep +Message-ID: <20110803191046.GA31049@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20110803190806.GA30619@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Status: RO +Content-Length: 823 +Lines: 26 + +utrace_resume() enables irqs unconditionally. With the recent changes +in lockdep.c this triggers the warning. Check irqs_disabled() before +local_irq_enable(). + +Signed-off-by: Oleg Nesterov +--- + kernel/utrace.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/kernel/utrace.c b/kernel/utrace.c +index 05e8532..c817a46 100644 +--- a/kernel/utrace.c ++++ b/kernel/utrace.c +@@ -1881,7 +1881,8 @@ void utrace_resume(struct task_struct *task, struct pt_regs *regs) + * code path leads to calling into get_signal_to_deliver(), which + * implicitly reenables them by virtue of spin_unlock_irq. + */ +- local_irq_enable(); ++ if (irqs_disabled()) /* make trace_hardirqs_on() happy */ ++ local_irq_enable(); + + /* + * If this flag is still set it's because there was a signal +-- +1.5.5.1 + + +From davej Tue Aug 9 13:39:54 2011 Return-Path: oleg@redhat.com X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on gelk.kernelslacker.org @@ -6480,42 +7265,42 @@ X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 Received: from mail.corp.redhat.com [10.5.5.51] by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Tue, 09 Aug 2011 13:34:35 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Tue, 9 Aug 2011 13:33:16 -0400 (EDT) + for (single-drop); Tue, 09 Aug 2011 13:39:54 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + mail04.corp.redhat.com with LMTP; Tue, 9 Aug 2011 13:39:44 -0400 (EDT) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 16B6E9EBAD; - Tue, 9 Aug 2011 13:33:16 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id T2mXXk1FjIIy; Tue, 9 Aug 2011 13:33:16 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 025259EBA5; - Tue, 9 Aug 2011 13:33:16 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5FCAC12983C; + Tue, 9 Aug 2011 13:39:44 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id nDWbqog6fbHK; Tue, 9 Aug 2011 13:39:44 -0400 (EDT) +Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4BEF712983B; + Tue, 9 Aug 2011 13:39:44 -0400 (EDT) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p79HXDVF004054; - Tue, 9 Aug 2011 13:33:13 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p79HdahY022801; + Tue, 9 Aug 2011 13:39:37 -0400 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Tue, 9 Aug 2011 19:30:35 +0200 (CEST) -Date: Tue, 9 Aug 2011 19:30:33 +0200 + oleg@redhat.com; Tue, 9 Aug 2011 19:36:58 +0200 (CEST) +Date: Tue, 9 Aug 2011 19:36:56 +0200 From: Oleg Nesterov -To: "Frank Ch. Eigler" , Kyle McMartin , - Dave Jones , Josh Stone , - Matthew Garrett , David Smith -Cc: kernel@lists.fedoraproject.org, Tony Breeds -Subject: [PATCH utrace-3.0 23/22] ptrace_report_syscall: check if +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com +Subject: [PATCH utrace-3.1 32/31] ptrace_report_syscall: check if TIF_SYSCALL_EMU is defined -Message-ID: <20110809173033.GA26443@redhat.com> -References: <20110701002053.GA25767@redhat.com> <20110807191434.GA13184@redhat.com> +Message-ID: <20110809173656.GC26443@redhat.com> +References: <20110802174514.GA23073@redhat.com> <20110803190806.GA30619@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110807191434.GA13184@redhat.com> +In-Reply-To: <20110803190806.GA30619@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO -Content-Length: 844 +Content-Length: 839 Lines: 31 From: Tony Breeds @@ -6528,12 +7313,12 @@ Signed-off-by: Oleg Nesterov 1 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index ac833de..d5baf86 100644 +index 90ca578..a1bac95 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h -@@ -76,8 +76,12 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) +@@ -59,8 +59,12 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) { - int ptrace = task_ptrace(current); + int ptrace = current->ptrace; - if (!(ptrace & PT_SYSCALL_TRACE) && !test_thread_flag(TIF_SYSCALL_EMU)) - return; From f8effed74e5a6ea746a28ca9a8d3ae434b636ded Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Tue, 16 Aug 2011 13:00:45 -0500 Subject: [PATCH 028/487] setup config for tegra based arm boards, add device tree patches for arm build tegra and omap kernel on arm --- Makefile.config | 8 ++++++- kernel.spec | 63 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/Makefile.config b/Makefile.config index 0e71c35c0..7415c9155 100644 --- a/Makefile.config +++ b/Makefile.config @@ -9,7 +9,7 @@ CONFIGFILES = \ $(CFG)-i686-PAE.config $(CFG)-i686-PAEdebug.config \ $(CFG)-x86_64.config $(CFG)-x86_64-debug.config \ $(CFG)-s390x.config \ - $(CFG)-arm.config $(CFG)-armv7l-omap.config \ + $(CFG)-arm.config $(CFG)-armv7l-omap.config $(CFG)-armv7l-tegra.config \ $(CFG)-ppc.config $(CFG)-ppc-smp.config \ $(CFG)-sparc64.config \ $(CFG)-ppc64.config $(CFG)-ppc64-debug.config \ @@ -39,6 +39,9 @@ temp-arm-generic: config-arm-generic temp-generic temp-armv7l-omap-generic: config-arm-omap-generic temp-arm-generic perl merge.pl $^ > $@ +temp-armv7l-tegra: config-arm-tegra temp-arm-generic + perl merge.pl $^ > $@ + temp-x86-32: config-x86-32-generic config-x86-generic perl merge.pl $^ > $@ @@ -111,6 +114,9 @@ kernel-$(VERSION)-arm.config: /dev/null temp-arm-generic kernel-$(VERSION)-armv7l-omap.config: /dev/null temp-armv7l-omap-generic perl merge.pl $^ arm > $@ +kernel-$(VERSION)-armv7l-tegra.config: /dev/null temp-armv7l-tegra + perl merge.pl $^ arm > $@ + kernel-$(VERSION)-ppc.config: /dev/null temp-powerpc32-generic perl merge.pl $^ powerpc > $@ diff --git a/kernel.spec b/kernel.spec index 30e182916..f08ed3549 100644 --- a/kernel.spec +++ b/kernel.spec @@ -121,6 +121,10 @@ Summary: The Linux kernel %define with_bootwrapper %{?_without_bootwrapper: 0} %{?!_without_bootwrapper: 1} # Want to build a the vsdo directories installed %define with_vdso_install %{?_without_vdso_install: 0} %{?!_without_vdso_install: 1} +# ARM OMAP (Beagle/Panda Board) +%define with_omap %{?_without_omap: 0} %{?!_without_omap: 1} +# kernel-tegra (only valid for arm) +%define with_tegra %{?_without_tegra: 0} %{?!_without_tegra: 1} # Build the kernel-doc package, but don't fail the build if it botches. # Here "true" means "continue" and "false" means "fail the build". @@ -229,6 +233,12 @@ Summary: The Linux kernel %define with_pae 0 %endif +# kernel-tegra and omap is only built on arm +%ifnarch %{arm} +%define with_tegra 0 +%define with_omap 0 +%endif + # if requested, only build base kernel %if %{with_baseonly} %define with_smp 0 @@ -383,8 +393,10 @@ Summary: The Linux kernel %define image_install_path boot %define asmarch arm %define hdrarch arm -%define make_target vmlinux -%define kernel_image vmlinux +%define make_target bzImage +%define kernel_image arch/arm/boot/zImage +%define with_up 0 +%define with_perf 0 %endif %if %{nopatches} @@ -407,7 +419,7 @@ Summary: The Linux kernel # Which is a BadThing(tm). # We only build kernel-headers on the following... -%define nobuildarches i386 s390 sparc sparcv9 %{arm} +%define nobuildarches i386 s390 sparc sparcv9 %ifarch %nobuildarches %define with_up 0 @@ -560,6 +572,7 @@ Source90: config-sparc64-generic Source100: config-arm-generic Source110: config-arm-omap-generic +Source111: config-arm-tegra # This file is intentionally left empty in the stock kernel. Its a nicety # added for those wanting to do custom rebuilds with altered config opts. @@ -702,6 +715,9 @@ Patch13003: efi-dont-map-boot-services-on-32bit.patch Patch20000: utrace.patch +# Flattened devicetree support +Patch21000: arm-omap-dt-compat.patch +Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -894,6 +910,19 @@ It should only be installed when trying to gather additional information on kernel bugs, as some of these options impact performance noticably. +%define variant_summary The Linux kernel compiled for TI-OMAP boards +%kernel_variant_package omap +%description omap +This package includes a version of the Linux kernel with support for +TI-OMAP based systems, i.e., BeagleBoard-xM. + +%define variant_summary The Linux kernel compiled for tegra boards +%kernel_variant_package tegra +%description tegra +This package includes a version of the Linux kernel with support for +nvidia tegra based systems, i.e., trimslice, ac-100. + + %prep # do a few sanity-checks for --with *only builds %if %{with_baseonly} @@ -1156,6 +1185,12 @@ ApplyOptionalPatch linux-2.6-upstream-reverts.patch -R # ApplyPatch linux-2.6.29-sparc-IOC_TYPECHECK.patch +# +# ARM +# +ApplyPatch arm-omap-dt-compat.patch +ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch + # # Exec shield # @@ -1595,6 +1630,14 @@ BuildKernel %make_target %kernel_image PAEdebug BuildKernel %make_target %kernel_image PAE %endif +%if %{with_omap} +BuildKernel %make_target %kernel_image omap +%endif + +%if %{with_tegra} +BuildKernel %make_target %kernel_image tegra +%endif + %if %{with_up} BuildKernel %make_target %kernel_image %endif @@ -1787,6 +1830,12 @@ fi}\ %kernel_variant_post -v PAEdebug -r (kernel|kernel-smp) %kernel_variant_preun PAEdebug +%kernel_variant_preun omap +%kernel_variant_post -v omap + +%kernel_variant_preun tegra +%kernel_variant_post -v tegra + if [ -x /sbin/ldconfig ] then /sbin/ldconfig -X || exit $? @@ -1897,11 +1946,19 @@ fi %kernel_variant_files %{with_debug} debug %kernel_variant_files %{with_pae} PAE %kernel_variant_files %{with_pae_debug} PAEdebug +%kernel_variant_files %{with_omap} omap +%kernel_variant_files %{with_tegra} tegra # plz don't put in a version string unless you're going to tag # and build. %changelog +* Tue Aug 16 2011 Dennis Gilmore +- add config for arm tegra devices +- setup kernel to build omap image (patch from David Marlin) +- setup kernel to build tegra image based on omap work +- add arm device tree patches + * Sat Aug 13 2011 Dave Jones - CPU_FREQ drivers should now be built-in on x86-64. From e8d576e5d4afa13c6170fb1b41ae71ead3501509 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Wed, 10 Aug 2011 14:50:02 -0500 Subject: [PATCH 029/487] only build kernel headers on the base arm arches --- kernel.spec | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel.spec b/kernel.spec index f08ed3549..88ad6b2f9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -396,6 +396,11 @@ Summary: The Linux kernel %define make_target bzImage %define kernel_image arch/arm/boot/zImage %define with_up 0 +# we only build headers on the base arm arches +# just like we used to only build them on i386 for x86 +%ifnarch armv5tel armv7hl +%define with_headers 0 +%endif %define with_perf 0 %endif From 8e25ffdc6e873f985fe801bc3505569940403ad1 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Wed, 10 Aug 2011 15:06:10 -0500 Subject: [PATCH 030/487] only build the omap and tegra variants on armv7 builds --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 88ad6b2f9..16715917b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -233,8 +233,8 @@ Summary: The Linux kernel %define with_pae 0 %endif -# kernel-tegra and omap is only built on arm -%ifnarch %{arm} +# kernel-tegra and omap is only built on armv7 hard and softfp +%ifnarch armv7hl armv7l %define with_tegra 0 %define with_omap 0 %endif From a051e56cfeb791e59989523e49bc7e27944bfd36 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Tue, 16 Aug 2011 13:01:38 -0500 Subject: [PATCH 031/487] add tegra config and device tree patches --- arm-omap-dt-compat.patch | 42 +++++++++ ...reading-mac-address-from-device-tree.patch | 92 +++++++++++++++++++ config-arm-tegra | 71 ++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 arm-omap-dt-compat.patch create mode 100644 arm-smsc-support-reading-mac-address-from-device-tree.patch create mode 100644 config-arm-tegra diff --git a/arm-omap-dt-compat.patch b/arm-omap-dt-compat.patch new file mode 100644 index 000000000..ab7cd0a4d --- /dev/null +++ b/arm-omap-dt-compat.patch @@ -0,0 +1,42 @@ +diff -up linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap3beagle.c.fdt linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap3beagle.c +--- linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap3beagle.c.fdt 2011-08-04 16:51:12.034188064 -0500 ++++ linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap3beagle.c 2011-08-04 22:13:52.801156923 -0500 +@@ -591,6 +591,11 @@ static void __init omap3_beagle_init(voi + beagle_opp_init(); + } + ++static const char *omap3_beagle_dt_match[] __initdata = { ++ "ti,omap3-beagle", ++ NULL ++}; ++ + MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board") + /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */ + .boot_params = 0x80000100, +@@ -600,4 +605,5 @@ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagl + .init_irq = omap3_beagle_init_irq, + .init_machine = omap3_beagle_init, + .timer = &omap_timer, ++ .dt_compat = omap3_beagle_dt_match, + MACHINE_END +diff -up linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c.fdt linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c +--- linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c.fdt 2011-08-04 16:51:12.092169023 -0500 ++++ linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c 2011-08-04 22:15:29.200157437 -0500 +@@ -708,6 +708,11 @@ static void __init omap4_panda_map_io(vo + omap44xx_map_common_io(); + } + ++static const char *omap4_panda_match[] __initdata = { ++ "ti,omap4-panda", ++ NULL, ++}; ++ + MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board") + /* Maintainer: David Anders - Texas Instruments Inc */ + .boot_params = 0x80000100, +@@ -717,4 +722,5 @@ MACHINE_START(OMAP4_PANDA, "OMAP4 Panda + .init_irq = gic_init_irq, + .init_machine = omap4_panda_init, + .timer = &omap_timer, ++ .dt_compat = omap4_panda_match, + MACHINE_END diff --git a/arm-smsc-support-reading-mac-address-from-device-tree.patch b/arm-smsc-support-reading-mac-address-from-device-tree.patch new file mode 100644 index 000000000..a36c68369 --- /dev/null +++ b/arm-smsc-support-reading-mac-address-from-device-tree.patch @@ -0,0 +1,92 @@ +From 0b608345e114681f66ca0a3cf9d9434728da62ce Mon Sep 17 00:00:00 2001 +From: Ken Cox +Date: Thu, 23 Jun 2011 10:36:43 -0500 +Subject: [PATCH] Support reading mac address from device tree. + +If CONFIG_OF is enabled, we will try to read the mac address from the device tree. This enables us the ability to have a "static" mac address on arm boards such as the pandaboard and beagleboard which generate random mac addresses. +--- + drivers/net/usb/smsc75xx.c | 17 +++++++++++++++++ + drivers/net/usb/smsc95xx.c | 18 +++++++++++++++++- + 2 files changed, 34 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c +index 753ee6e..ac0a200 100644 +--- a/drivers/net/usb/smsc75xx.c ++++ b/drivers/net/usb/smsc75xx.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #include "smsc75xx.h" + + #define SMSC_CHIPNAME "smsc75xx" +@@ -658,6 +659,22 @@ static int smsc75xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) + + static void smsc75xx_init_mac_address(struct usbnet *dev) + { ++ void *address; ++#ifdef CONFIG_OF ++ struct device_node *np; ++ ++ /* try the device tree */ ++ np = of_find_node_by_name(NULL, "smsc75xx"); ++ if (np) { ++ address = of_get_property(np, "local-mac-address", NULL); ++ if (address) { ++ memcpy(dev->net->dev_addr, address, ETH_ALEN); ++ netif_dbg(dev, ifup, dev->net, "MAC address read from device tree\n"); ++ return; ++ } ++ } ++#endif ++ + /* try reading mac address from EEPROM */ + if (smsc75xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, + dev->net->dev_addr) == 0) { +diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c +index bc86f4b..c83942d 100644 +--- a/drivers/net/usb/smsc95xx.c ++++ b/drivers/net/usb/smsc95xx.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #include "smsc95xx.h" + + #define SMSC_CHIPNAME "smsc95xx" +@@ -639,6 +640,22 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) + + static void smsc95xx_init_mac_address(struct usbnet *dev) + { ++ void *address; ++#ifdef CONFIG_OF ++ struct device_node *np; ++ ++ /* try the device tree */ ++ np = of_find_node_by_name(NULL, "smsc95xx"); ++ if (np) { ++ address = of_get_property(np, "local-mac-address", NULL); ++ if (address) { ++ memcpy(dev->net->dev_addr, address, ETH_ALEN); ++ netif_dbg(dev, ifup, dev->net, "MAC address read from device tree\n"); ++ return; ++ } ++ } ++#endif ++ + /* try reading mac address from EEPROM */ + if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, + dev->net->dev_addr) == 0) { +@@ -648,7 +665,6 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) + return; + } + } +- + /* no eeprom, or eeprom values are invalid. generate random MAC */ + random_ether_addr(dev->net->dev_addr); + netif_dbg(dev, ifup, dev->net, "MAC address set to random_ether_addr\n"); +-- +1.7.2.3 + diff --git a/config-arm-tegra b/config-arm-tegra new file mode 100644 index 000000000..31d89b3b2 --- /dev/null +++ b/config-arm-tegra @@ -0,0 +1,71 @@ +CONFIG_ARCH_TEGRA=y +CONFIG_MACH_HARMONY=y +CONFIG_MACH_KAEN=y +CONFIG_MACH_PAZ00=y +CONFIG_MACH_TRIMSLICE=y +CONFIG_MACH_WARIO=y +CONFIG_TEGRA_DEBUG_UARTD=y +CONFIG_ARM_ERRATA_742230=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_SMP=y +CONFIG_NR_CPUS=2 +CONFIG_PREEMPT=y +CONFIG_AEABI=y + +CONFIG_I2C_TEGRA=y + +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_TEGRA=y + +# CONFIG_RCU_BOOST is not set +CONFIG_TEGRA_SYSTEM_DMA=y +CONFIG_TEGRA_EMC_SCALING_ENABLE=y +CONFIG_ARM_THUMBEE=y +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_CACHE_L2X0=y +CONFIG_ARM_ERRATA_430973=y +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_742231 is not set +CONFIG_PL310_ERRATA_588369=y +CONFIG_ARM_ERRATA_720789=y +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_751472 is not set +# CONFIG_ARM_ERRATA_753970 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_ARM_ERRATA_754327 is not set +CONFIG_SMP_ON_UP=y +CONFIG_LOCAL_TIMERS=y +# CONFIG_THUMB2_KERNEL is not set +CONFIG_HW_PERF_EVENTS=y +# CONFIG_NEON is not set +# CONFIG_RFKILL_GPIO is not set +CONFIG_KEYBOARD_TEGRA=y +# CONFIG_MPCORE_WATCHDOG is not set +CONFIG_USB_EHCI_TEGRA=y +CONFIG_RTC_DRV_TEGRA=m +CONFIG_MFD_NVEC=y +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_RCU_CPU_STALL_VERBOSE is not set +# CONFIG_PREEMPT_TRACER is not set +CONFIG_KEYBOARD_NVEC=y +CONFIG_SERIO_NVEC_PS2=y +CONFIG_NVEC_POWER=y + +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEBUG=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y From 68bd044f8ab06d85d628995a5513fdff60ff604e Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Fri, 12 Aug 2011 00:37:40 -0500 Subject: [PATCH 032/487] tweak the arm configs a little build a up image on armv5tel its a basic qemu image. setup to make configs for building kernels on hardware floating point arm arches --- Makefile.config | 13 ++++++++++++- config-arm-generic | 5 ++++- config-arm-tegra | 18 +++++++++++++++++- kernel.spec | 3 +++ 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/Makefile.config b/Makefile.config index 7415c9155..ccb035d77 100644 --- a/Makefile.config +++ b/Makefile.config @@ -9,7 +9,9 @@ CONFIGFILES = \ $(CFG)-i686-PAE.config $(CFG)-i686-PAEdebug.config \ $(CFG)-x86_64.config $(CFG)-x86_64-debug.config \ $(CFG)-s390x.config \ - $(CFG)-arm.config $(CFG)-armv7l-omap.config $(CFG)-armv7l-tegra.config \ + $(CFG)-arm.config $(CFG)-armv5tel.config \ + $(CFG)-armv7l-omap.config $(CFG)-armv7l-tegra.config \ + $(CFG)-armv7hl-omap.config $(CFG)-armv7hl-tegra.config \ $(CFG)-ppc.config $(CFG)-ppc-smp.config \ $(CFG)-sparc64.config \ $(CFG)-ppc64.config $(CFG)-ppc64-debug.config \ @@ -111,12 +113,21 @@ kernel-$(VERSION)-s390x.config: config-s390x temp-s390-generic kernel-$(VERSION)-arm.config: /dev/null temp-arm-generic perl merge.pl $^ arm > $@ +kernel-$(VERSION)-armv5tel.config: /dev/null temp-arm-generic + perl merge.pl $^ arm > $@ + kernel-$(VERSION)-armv7l-omap.config: /dev/null temp-armv7l-omap-generic perl merge.pl $^ arm > $@ kernel-$(VERSION)-armv7l-tegra.config: /dev/null temp-armv7l-tegra perl merge.pl $^ arm > $@ +kernel-$(VERSION)-armv7hl-omap.config: /dev/null temp-armv7l-omap-generic + perl merge.pl $^ arm > $@ + +kernel-$(VERSION)-armv7hl-tegra.config: /dev/null temp-armv7l-tegra + perl merge.pl $^ arm > $@ + kernel-$(VERSION)-ppc.config: /dev/null temp-powerpc32-generic perl merge.pl $^ powerpc > $@ diff --git a/config-arm-generic b/config-arm-generic index dec424128..3d236b807 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -83,9 +83,12 @@ CONFIG_FB_ARMCLCD=m CONFIG_SND_ARM=y CONFIG_SND_ARMAACI=m +CONFIG_SND_SOC=m +# CONFIG_SND_SOC_CACHE_LZO is not set +# CONFIG_SND_SOC_ALL_CODECS is not set CONFIG_USB_MUSB_HDRC=y -# CONFIG_MUSB_PIO_ONLY is not set +CONFIG_MUSB_PIO_ONLY=y CONFIG_USB_TUSB6010=y # CONFIG_USB_MUSB_DEBUG is not set diff --git a/config-arm-tegra b/config-arm-tegra index 31d89b3b2..15e9ed720 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -49,6 +49,11 @@ CONFIG_KEYBOARD_TEGRA=y # CONFIG_MPCORE_WATCHDOG is not set CONFIG_USB_EHCI_TEGRA=y CONFIG_RTC_DRV_TEGRA=m + +CONFIG_SND_SOC_TEGRA=m +CONFIG_SND_SOC_TEGRA_WM8903=m +CONFIG_SND_SOC_TEGRA_TRIMSLICE=m + CONFIG_MFD_NVEC=y # CONFIG_DEBUG_PREEMPT is not set # CONFIG_RCU_CPU_STALL_VERBOSE is not set @@ -56,6 +61,7 @@ CONFIG_MFD_NVEC=y CONFIG_KEYBOARD_NVEC=y CONFIG_SERIO_NVEC_PS2=y CONFIG_NVEC_POWER=y +CONFIG_POWER_SUPPLY=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_DEBUG=y @@ -67,5 +73,15 @@ CONFIG_CPU_FREQ_GOV_USERSPACE=m CONFIG_CPU_FREQ_GOV_ONDEMAND=m CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m CONFIG_CPU_FREQ_TABLE=y -CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y + + +# these modules all fail with missing __bad_udelay +# http://www.spinics.net/lists/arm/msg15615.html provides some background +# CONFIG_SUNGEM is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_RADEON is not set +# CONFIG_DRM_RADEON is not set +# CONFIG_ATM_HE is not set +# CONFIG_SCSI_ACARD is not set diff --git a/kernel.spec b/kernel.spec index 16715917b..6ea849500 100644 --- a/kernel.spec +++ b/kernel.spec @@ -395,7 +395,10 @@ Summary: The Linux kernel %define hdrarch arm %define make_target bzImage %define kernel_image arch/arm/boot/zImage +# we build a up kernel on armv5tel. its used for qemu. +%ifnarch armv5tel %define with_up 0 +%endif # we only build headers on the base arm arches # just like we used to only build them on i386 for x86 %ifnarch armv5tel armv7hl From d5210424c1685e5625b73ac3ba34edc734903e00 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Tue, 16 Aug 2011 11:37:01 -0500 Subject: [PATCH 033/487] the modules effected by __bad_udelay need to be excluded on all arm arches not just the tegra boards disable them in config-arm-generic --- config-arm-generic | 9 +++++++++ config-arm-tegra | 9 --------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/config-arm-generic b/config-arm-generic index 3d236b807..296d52b08 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -155,3 +155,12 @@ CONFIG_MMC_SDHCI_PXAV3=m CONFIG_MMC_SDHCI_PXAV2=m CONFIG_FTGMAC100=m + +# these modules all fail with missing __bad_udelay +# http://www.spinics.net/lists/arm/msg15615.html provides some background +# CONFIG_SUNGEM is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_RADEON is not set +# CONFIG_DRM_RADEON is not set +# CONFIG_ATM_HE is not set +# CONFIG_SCSI_ACARD is not set diff --git a/config-arm-tegra b/config-arm-tegra index 15e9ed720..c72660bf8 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -76,12 +76,3 @@ CONFIG_CPU_FREQ_TABLE=y CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y - -# these modules all fail with missing __bad_udelay -# http://www.spinics.net/lists/arm/msg15615.html provides some background -# CONFIG_SUNGEM is not set -# CONFIG_FB_SAVAGE is not set -# CONFIG_FB_RADEON is not set -# CONFIG_DRM_RADEON is not set -# CONFIG_ATM_HE is not set -# CONFIG_SCSI_ACARD is not set From 2fe4ccdc751769a7ef2526cf109d14b4f6d5422e Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Tue, 16 Aug 2011 11:41:15 -0500 Subject: [PATCH 034/487] disable crystalhd module on the generic arm qemu build but enable it on the others disable tpm on arm build in mmc_block on tegra build --- config-arm-generic | 7 +++++++ config-arm-omap-generic | 3 ++- config-arm-tegra | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/config-arm-generic b/config-arm-generic index 296d52b08..307c66d68 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -156,6 +156,13 @@ CONFIG_MMC_SDHCI_PXAV2=m CONFIG_FTGMAC100=m +# disable TPM on arm at least on the trimslices it causes havoc +# CONFIG_TCG_TPM is not set +# CONFIG_IMA is not set + +# ERROR: "__bswapsi2" [drivers/staging/crystalhd/crystalhd.ko] undefined! +# CONFIG_CRYSTALHD is not set + # these modules all fail with missing __bad_udelay # http://www.spinics.net/lists/arm/msg15615.html provides some background # CONFIG_SUNGEM is not set diff --git a/config-arm-omap-generic b/config-arm-omap-generic index df7ab065a..12a6e30e3 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -415,7 +415,6 @@ CONFIG_SERIAL_OMAP_CONSOLE=y # CONFIG_HW_RANDOM_TIMERIOMEM is not set # CONFIG_R3964 is not set # CONFIG_RAW_DRIVER is not set -# CONFIG_TCG_TPM is not set CONFIG_I2C=y CONFIG_I2C_CHARDEV=y # CONFIG_I2C_GPIO is not set @@ -1097,3 +1096,5 @@ CONFIG_LIBCRC32C=y # CONFIG_BT_ATH3K is not set # CONFIG_BT_WILINK is not set # CONFIG_USB_HSO is not set + +CONFIG_CRYSTALHD=m diff --git a/config-arm-tegra b/config-arm-tegra index c72660bf8..c79efcf5b 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -16,6 +16,7 @@ CONFIG_AEABI=y CONFIG_I2C_TEGRA=y CONFIG_MMC=y +CONFIG_MMC_BLOCK=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_TEGRA=y @@ -76,3 +77,4 @@ CONFIG_CPU_FREQ_TABLE=y CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CRYSTALHD=m From cb6a4e1b979e9ed2d27450777e48de73f32aa766 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Tue, 16 Aug 2011 12:56:09 -0500 Subject: [PATCH 035/487] update arm configs for 3.1 update omap devicetree patch for updated field names --- arm-omap-dt-compat.patch | 4 ++-- config-arm-omap-generic | 1 + config-arm-tegra | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arm-omap-dt-compat.patch b/arm-omap-dt-compat.patch index ab7cd0a4d..4046e938f 100644 --- a/arm-omap-dt-compat.patch +++ b/arm-omap-dt-compat.patch @@ -16,7 +16,7 @@ diff -up linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap3beagle.c.fdt linux-2 @@ -600,4 +605,5 @@ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagl .init_irq = omap3_beagle_init_irq, .init_machine = omap3_beagle_init, - .timer = &omap_timer, + .timer = &omap3_secure_timer, + .dt_compat = omap3_beagle_dt_match, MACHINE_END diff -up linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c.fdt linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c @@ -37,6 +37,6 @@ diff -up linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c.fdt linux-2. @@ -717,4 +722,5 @@ MACHINE_START(OMAP4_PANDA, "OMAP4 Panda .init_irq = gic_init_irq, .init_machine = omap4_panda_init, - .timer = &omap_timer, + .timer = &omap4_timer, + .dt_compat = omap4_panda_match, MACHINE_END diff --git a/config-arm-omap-generic b/config-arm-omap-generic index 12a6e30e3..29f6ade6a 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -928,6 +928,7 @@ CONFIG_MMC_SPI=m # CONFIG_MEMSTICK is not set CONFIG_LEDS_GPIO=y CONFIG_LEDS_GPIO_PLATFORM=y +CONFIG_LEDS_GPIO_OF=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set diff --git a/config-arm-tegra b/config-arm-tegra index c79efcf5b..91c176bcd 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -4,6 +4,7 @@ CONFIG_MACH_KAEN=y CONFIG_MACH_PAZ00=y CONFIG_MACH_TRIMSLICE=y CONFIG_MACH_WARIO=y +CONFIG_MACH_TEGRA_DT=y CONFIG_TEGRA_DEBUG_UARTD=y CONFIG_ARM_ERRATA_742230=y CONFIG_NO_HZ=y @@ -46,6 +47,8 @@ CONFIG_LOCAL_TIMERS=y CONFIG_HW_PERF_EVENTS=y # CONFIG_NEON is not set # CONFIG_RFKILL_GPIO is not set +CONFIG_GPIO_GENERIC_PLATFORM=y +# CONFIG_GPIO_MCP23S08 is not set CONFIG_KEYBOARD_TEGRA=y # CONFIG_MPCORE_WATCHDOG is not set CONFIG_USB_EHCI_TEGRA=y From 686a19481137a26b32d85a9be56930f815547644 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 16 Aug 2011 15:16:45 -0400 Subject: [PATCH 036/487] Prepare for packaging more of tools/ by renaming 'perf' subpackage to kernel-tools --- kernel.spec | 50 ++++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/kernel.spec b/kernel.spec index 6ea849500..e87e74991 100644 --- a/kernel.spec +++ b/kernel.spec @@ -113,8 +113,8 @@ Summary: The Linux kernel %define with_headers %{?_without_headers: 0} %{?!_without_headers: 1} # kernel-firmware %define with_firmware %{?_with_firmware: 1} %{?!_with_firmware: 0} -# tools/perf -%define with_perf %{?_without_perf: 0} %{?!_without_perf: 1} +# tools +%define with_tools %{?_without_tools: 0} %{?!_without_tools: 1} # kernel-debuginfo %define with_debuginfo %{?_without_debuginfo: 0} %{?!_without_debuginfo: 1} # kernel-bootwrapper (for creating zImages from kernel + initrd) @@ -268,7 +268,7 @@ Summary: The Linux kernel %endif %define with_smp 0 %define with_pae 0 -%define with_perf 0 +%define with_tools 0 %endif %define all_x86 i386 i686 @@ -299,7 +299,7 @@ Summary: The Linux kernel %ifarch noarch %define with_up 0 %define with_headers 0 -%define with_perf 0 +%define with_tools 0 %define all_arch_configs kernel-%{version}-*.config %define with_firmware %{?_with_firmware: 1} %{?!_with_firmware: 0} %endif @@ -348,7 +348,7 @@ Summary: The Linux kernel %define image_install_path boot %define make_target image %define kernel_image arch/s390/boot/image -%define with_perf 0 +%define with_tools 0 %endif %ifarch sparc64 @@ -357,7 +357,7 @@ Summary: The Linux kernel %define make_target image %define kernel_image arch/sparc/boot/image %define image_install_path boot -%define with_perf 0 +%define with_tools 0 %endif %ifarch sparcv9 @@ -434,7 +434,7 @@ Summary: The Linux kernel %define with_smp 0 %define with_pae 0 %define with_debuginfo 0 -%define with_perf 0 +%define with_tools 0 %define _enable_debug_packages 0 %endif @@ -531,7 +531,7 @@ BuildRequires: xmlto, asciidoc %if %{with_sparse} BuildRequires: sparse >= 0.4.1 %endif -%if %{with_perf} +%if %{with_tools} BuildRequires: elfutils-devel zlib-devel binutils-devel newt-devel python-devel perl(ExtUtils::Embed) %endif BuildConflicts: rhbuildsys(DiskFree) < 500Mb @@ -789,21 +789,23 @@ Group: Development/Debug This package is required by %{name}-debuginfo subpackages. It provides the kernel source files common to all builds. -%if %{with_perf} -%package -n perf -Summary: Performance monitoring for the Linux kernel +%if %{with_tools} +%package -n kernel-tools +Summary: Assortment of tools for the Linux kernel Group: Development/System License: GPLv2 -%description -n perf -This package provides the perf tool and the supporting documentation. +Obsoletes: perf +%description -n kernel-tools +This package contains the tools/ directory from the kernel source +- the perf tool and the supporting documentation. -%package -n perf-debuginfo -Summary: Debug information for package perf +%package -n kernel-tools-debuginfo +Summary: Debug information for package kernel-tools Group: Development/Debug Requires: %{name}-debuginfo-common-%{_target_cpu} = %{version}-%{release} AutoReqProv: no -%description -n perf-debuginfo -This package provides debug information for package perf. +%description -n kernel-tools-debuginfo +This package provides debug information for package kernel-tools. # Note that this pattern only works right to match the .build-id # symlinks because of the trailing nonmatching alternation and @@ -1656,7 +1658,7 @@ BuildKernel %make_target %kernel_image smp %global perf_make \ make %{?_smp_mflags} -C tools/perf -s V=1 HAVE_CPLUS_DEMANGLE=1 prefix=%{_prefix} -%if %{with_perf} +%if %{with_tools} %{perf_make} all %{perf_make} man || %{doc_build_fail} %endif @@ -1714,7 +1716,7 @@ xargs -0 --no-run-if-empty %{__install} -m 444 -t $man9dir $m ls $man9dir | grep -q '' || > $man9dir/BROKEN %endif # with_doc -%if %{with_perf} +%if %{with_tools} # perf tool binary and supporting scripts/binaries %{perf_make} DESTDIR=$RPM_BUILD_ROOT install @@ -1883,8 +1885,8 @@ fi %{_datadir}/man/man9/* %endif -%if %{with_perf} -%files -n perf +%if %{with_tools} +%files -n kernel-tools %defattr(-,root,root) %{_bindir}/perf %dir %{_libexecdir}/perf-core @@ -1892,7 +1894,7 @@ fi %{_mandir}/man[1-8]/* %if %{with_debuginfo} -%files -f perf-debuginfo.list -n perf-debuginfo +%files -f perf-debuginfo.list -n kernel-tools-debuginfo %defattr(-,root,root) %endif %endif @@ -1961,6 +1963,10 @@ fi # and build. %changelog +* Tue Aug 16 2011 Dave Jones +- Prepare for packaging more of tools/ by renaming 'perf' subpackage + to kernel-tools + * Tue Aug 16 2011 Dennis Gilmore - add config for arm tegra devices - setup kernel to build omap image (patch from David Marlin) From 1c2e433fec53d93224d170e88a5e919bad65bb14 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 17 Aug 2011 21:18:53 -0400 Subject: [PATCH 037/487] Create the kernel-tools package. WHEE --- cpupower.config | 3 ++ cpupower.service | 13 ++++++ kernel.spec | 118 +++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 119 insertions(+), 15 deletions(-) create mode 100644 cpupower.config create mode 100644 cpupower.service diff --git a/cpupower.config b/cpupower.config new file mode 100644 index 000000000..8629a4a3e --- /dev/null +++ b/cpupower.config @@ -0,0 +1,3 @@ +# See 'cpupower help' and cpupower(1) for more info +CPUPOWER_START_OPTS="frequency-set -g performance" +CPUPOWER_STOP_OPTS="frequency-set -g ondemand" diff --git a/cpupower.service b/cpupower.service new file mode 100644 index 000000000..5f10ab7ee --- /dev/null +++ b/cpupower.service @@ -0,0 +1,13 @@ +[Unit] +Description=Configure CPU power related settings +After=syslog.target + +[Service] +Type=oneshot +RemainAfterExit=yes +EnvironmentFile=/etc/sysconfig/cpupower +ExecStart=/usr/bin/cpupower $CPUPOWER_START_OPTS +ExecStop=/usr/bin/cpupower $CPUPOWER_STOP_OPTS + +[Install] +WantedBy=multi-user.target diff --git a/kernel.spec b/kernel.spec index e87e74991..a4f120f1a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -443,6 +443,9 @@ Summary: The Linux kernel %define with_pae_debug %{with_debug} %endif +# Architectures we build tools/cpupower on +%define cpupowerarchs %{ix86} x86_64 ppc ppc64 + # # Three sets of minimum package version requirements in the form of Conflicts: # to versions below the minimum @@ -532,7 +535,7 @@ BuildRequires: xmlto, asciidoc BuildRequires: sparse >= 0.4.1 %endif %if %{with_tools} -BuildRequires: elfutils-devel zlib-devel binutils-devel newt-devel python-devel perl(ExtUtils::Embed) +BuildRequires: elfutils-devel zlib-devel binutils-devel newt-devel python-devel perl(ExtUtils::Embed) pciutils-devel %endif BuildConflicts: rhbuildsys(DiskFree) < 500Mb @@ -586,6 +589,10 @@ Source111: config-arm-tegra # added for those wanting to do custom rebuilds with altered config opts. Source1000: config-local +# Sources for kernel-tools +Source2000: cpupower.service +Source2001: cpupower.config + # Here should be only the patches up to the upstream canonical Linus tree. # For a stable release kernel @@ -795,10 +802,19 @@ Summary: Assortment of tools for the Linux kernel Group: Development/System License: GPLv2 Obsoletes: perf +Provides: perf %description -n kernel-tools This package contains the tools/ directory from the kernel source - the perf tool and the supporting documentation. +%package -n kernel-tools-devel +Summary: Assortment of tools for the Linux kernel +Group: Development/System +License: GPLv2 +%description -n kernel-tools-devel +This package contains the development files for the tools/ directory from +the kernel source. + %package -n kernel-tools-debuginfo Summary: Debug information for package kernel-tools Group: Development/Debug @@ -811,7 +827,7 @@ This package provides debug information for package kernel-tools. # symlinks because of the trailing nonmatching alternation and # the leading .*, because of find-debuginfo.sh's buggy handling # of matching the pattern against the symlinks file. -%{expand:%%global debuginfo_args %{?debuginfo_args} -p '.*%%{_bindir}/perf(\.debug)?|.*%%{_libexecdir}/perf-core/.*|XXX' -o perf-debuginfo.list} +%{expand:%%global debuginfo_args %{?debuginfo_args} -p '.*%%{_bindir}/perf(\.debug)?|.*%%{_libexecdir}/perf-core/.*|.*%%{_bindir}/centrino-decode(\.debug)?|.*%%{_bindir}/powernow-k8-decode(\.debug)?|.*%%{_bindir}/cpupower(\.debug)?|.*%%{_libdir}/libcpupower.*|XXX' -o kernel-tools-debuginfo.list} %endif @@ -1656,11 +1672,30 @@ BuildKernel %make_target %kernel_image BuildKernel %make_target %kernel_image smp %endif -%global perf_make \ - make %{?_smp_mflags} -C tools/perf -s V=1 HAVE_CPLUS_DEMANGLE=1 prefix=%{_prefix} %if %{with_tools} -%{perf_make} all -%{perf_make} man || %{doc_build_fail} +# perf +make %{?_smp_mflags} -C tools/perf -s V=1 HAVE_CPLUS_DEMANGLE=1 prefix=%{_prefix} all +make %{?_smp_mflags} -C tools/perf -s V=1 prefix=%{_prefix} man || %{doc_build_fail} + +%ifarch %{cpupowerarchs} +# cpupower +# make sure version-gen.sh is executable. +chmod +x tools/power/cpupower/utils/version-gen.sh +make %{?_smp_mflags} -C tools/power/cpupower CPUFRQ_BENCH=false +# this is fairly unnecessary at the moment. The x86_64 dir just contains +# symlinks to the i386 dir in the tarball, but patch hates that. We'll just +# build the i386 dir in all cases for now. +#ifarch {ix86} + cd tools/power/cpupower/debug/i386 + make %{?_smp_mflags} centrino-decode powernow-k8-decode + cd - +#endif +#ifarch x86_64 +# cd tools/power/cpupower/debug/x86_64 +# make {?_smp_mflags} +# cd - +#endif +%endif %endif %if %{with_doc} @@ -1716,13 +1751,9 @@ xargs -0 --no-run-if-empty %{__install} -m 444 -t $man9dir $m ls $man9dir | grep -q '' || > $man9dir/BROKEN %endif # with_doc -%if %{with_tools} -# perf tool binary and supporting scripts/binaries -%{perf_make} DESTDIR=$RPM_BUILD_ROOT install - -# perf man pages (note: implicit rpm magic compresses them later) -%{perf_make} DESTDIR=$RPM_BUILD_ROOT install-man || %{doc_build_fail} -%endif +# We have to do the headers install before the tools install because the +# kernel headers_install will remove any header files in /usr/include that +# it doesn't install itself. %if %{with_headers} # Install kernel headers @@ -1748,6 +1779,37 @@ rm -f $RPM_BUILD_ROOT/usr/include/asm*/io.h rm -f $RPM_BUILD_ROOT/usr/include/asm*/irq.h %endif +%if %{with_tools} +# perf tool binary and supporting scripts/binaries +make -C tools/perf -s V=1 DESTDIR=$RPM_BUILD_ROOT HAVE_CPLUS_DEMANGLE=1 prefix=%{_prefix} install + +# perf man pages (note: implicit rpm magic compresses them later) +make -C tools/perf -s V=1 DESTDIR=$RPM_BUILD_ROOT HAVE_CPLUS_DEMANGLE=1 prefix=%{_prefix} install-man || %{doc_build_fail} + +%ifarch %{cpupowerarchs} +make -C tools/power/cpupower DESTDIR=$RPM_BUILD_ROOT libdir=%{_libdir} mandir=%{_mandir} CPUFRQ_BENCH=false install +rm -f %{buildroot}%{_libdir}/*.{a,la} +%find_lang cpupower +mv cpupower.lang ../ +#ifarch #{ix86} + cd tools/power/cpupower/debug/i386 + install -m755 centrino-decode %{buildroot}%{_bindir}/centrino-decode + install -m755 powernow-k8-decode %{buildroot}%{_bindir}/powernow-k8-decode + cd - +#endif +#ifarch x86_64 +# cd tools/power/cpupower/debug/x86_64 +# install -m755 powernow-k8-decode {buildroot}{_bindir}/powernow-k8-decode +# cd - +#endif +chmod 0755 %{buildroot}%{_libdir}/libcpupower.so* +mkdir -p %{buildroot}%{_unitdir} %{buildroot}%{_sysconfdir}/sysconfig +install -m644 %{SOURCE2000} %{buildroot}%{_unitdir}/cpupower.service +install -m644 %{SOURCE2001} %{buildroot}%{_sysconfdir}/sysconfig/cpupower +%endif + +%endif + %if %{with_firmware} %{build_firmware} %endif @@ -1768,6 +1830,12 @@ rm -rf $RPM_BUILD_ROOT ### scripts ### +%post -n kernel-tools +/sbin/ldconfig + +%postun -n kernel-tools +/sbin/ldconfig + # # This macro defines a %%post script for a kernel*-devel package. # %%kernel_devel_post [] @@ -1787,6 +1855,7 @@ then\ fi\ %{nil} + # This macro defines a %%posttrans script for a kernel package. # %%kernel_variant_posttrans [] # More text can follow to go at the end of this variant's %%post. @@ -1886,17 +1955,33 @@ fi %endif %if %{with_tools} -%files -n kernel-tools +%files -n kernel-tools -f cpupower.lang %defattr(-,root,root) %{_bindir}/perf %dir %{_libexecdir}/perf-core %{_libexecdir}/perf-core/* %{_mandir}/man[1-8]/* +%ifarch %{cpupowerarchs} +%{_bindir}/cpupower +%{_bindir}/centrino-decode +%{_bindir}/powernow-k8-decode +%{_libdir}/libcpupower.so.0 +%{_libdir}/libcpupower.so.0.0.0 +%{_unitdir}/cpupower.service +%config(noreplace) %{_sysconfdir}/sysconfig/cpupower +%endif + %if %{with_debuginfo} -%files -f perf-debuginfo.list -n kernel-tools-debuginfo +%files -f kernel-tools-debuginfo.list -n kernel-tools-debuginfo %defattr(-,root,root) %endif + +%ifarch %{cpupowerarchs} +%files -n kernel-tools-devel +%{_libdir}/libcpupower.so +%{_includedir}/cpufreq.h +%endif %endif # This is %%{image_install_path} on an arch where that includes ELF files, @@ -1963,6 +2048,9 @@ fi # and build. %changelog +* Wed Aug 17 2011 Josh Boyer +- Create the kernel-tools subpackages based on a start by davej + * Tue Aug 16 2011 Dave Jones - Prepare for packaging more of tools/ by renaming 'perf' subpackage to kernel-tools From e9094d47cdce90fb48573727a5c8821b0808f215 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 17 Aug 2011 22:14:23 -0400 Subject: [PATCH 038/487] Make sure %post/%postun for kernel-tools is wrapped with %{with_tools} otherwise noarch fails (also make prep) --- kernel.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel.spec b/kernel.spec index a4f120f1a..db5fb3540 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1830,11 +1830,13 @@ rm -rf $RPM_BUILD_ROOT ### scripts ### +%if %{with_tools} %post -n kernel-tools /sbin/ldconfig %postun -n kernel-tools /sbin/ldconfig +%endif # # This macro defines a %%post script for a kernel*-devel package. From 3774ce3c1d759a5287cea68fc2c0ce158c3154e1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 18 Aug 2011 11:44:24 -0400 Subject: [PATCH 039/487] Adjust obsoletes/provides to replace the cpupowerutils package --- kernel.spec | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index db5fb3540..324b26c62 100644 --- a/kernel.spec +++ b/kernel.spec @@ -802,7 +802,14 @@ Summary: Assortment of tools for the Linux kernel Group: Development/System License: GPLv2 Obsoletes: perf -Provides: perf +Provides: perf +Provides: cpupowerutils = 1:009-0.6.p1 +Obsoletes: cpupowerutils < 1:009-0.6.p1 +Provides: cpufreq-utils = 1:009-0.6.p1 +Provides: cpufrequtils = 1:009-0.6.p1 +Obsoletes: cpufreq-utils < 1:009-0.6.p1 +Obsoletes: cpufrequtils < 1:009-0.6.p1 +Obsoletes: cpuspeed < 1:1.5-16 %description -n kernel-tools This package contains the tools/ directory from the kernel source - the perf tool and the supporting documentation. @@ -811,6 +818,7 @@ This package contains the tools/ directory from the kernel source Summary: Assortment of tools for the Linux kernel Group: Development/System License: GPLv2 +Requires: kernel-tools = %{version}-%{release} %description -n kernel-tools-devel This package contains the development files for the tools/ directory from the kernel source. @@ -2050,6 +2058,9 @@ fi # and build. %changelog +* Thu Aug 18 2011 Josh Boyer +- Adjust provides/obsoletes to replace the cpupowerutils package + * Wed Aug 17 2011 Josh Boyer - Create the kernel-tools subpackages based on a start by davej From 1c2cec9cfb6a3484d1f07652030b1655df69ca78 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 19 Aug 2011 08:32:04 -0400 Subject: [PATCH 040/487] 3.1-rc2-git5 snapshot Make XHCI builtin, add a patch to fix a race in the crypto framework --- config-generic | 2 +- config-ia64-generic | 1 + crypto-register-cryptd-first.patch | 26 ++++++++++++++++++++++++++ kernel.spec | 12 ++++++++++-- sources | 1 + 5 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 crypto-register-cryptd-first.patch diff --git a/config-generic b/config-generic index e320aeffa..443b2c114 100644 --- a/config-generic +++ b/config-generic @@ -3126,7 +3126,7 @@ CONFIG_USB_SL811_HCD=m CONFIG_USB_SL811_HCD_ISO=y # CONFIG_USB_SL811_CS is not set # CONFIG_USB_R8A66597_HCD is not set -CONFIG_USB_XHCI_HCD=m +CONFIG_USB_XHCI_HCD=y # CONFIG_USB_XHCI_HCD_DEBUGGING is not set CONFIG_USB_ISP1362_HCD=m diff --git a/config-ia64-generic b/config-ia64-generic index ca97689fa..52900a8e7 100644 --- a/config-ia64-generic +++ b/config-ia64-generic @@ -13,6 +13,7 @@ CONFIG_EFI=y # CONFIG_ITANIUM is not set CONFIG_MCKINLEY=y CONFIG_IA64_GENERIC=y +CONFIG_DMAR=y # CONFIG_IA64_DIG is not set # CONFIG_IA64_HP_ZX1 is not set # CONFIG_IA64_SGI_SN2 is not set diff --git a/crypto-register-cryptd-first.patch b/crypto-register-cryptd-first.patch new file mode 100644 index 000000000..0cd55d6fc --- /dev/null +++ b/crypto-register-cryptd-first.patch @@ -0,0 +1,26 @@ +commit 9d4c522a113f6caa8b792ae829a25490fa87b1a2 +Author: Herbert Xu +Date: Fri Aug 19 16:11:23 2011 +0800 + + crypto: cryptd - Use subsys_initcall to prevent races with aesni + + As cryptd is depeneded on by other algorithms such as aesni-intel, + it needs to be registered before them. When everything is built + as modules, this occurs naturally. However, for this to work when + they are built-in, we need to use subsys_initcall in cryptd. + + Signed-off-by: Herbert Xu + +diff --git a/crypto/cryptd.c b/crypto/cryptd.c +index e46d21a..671d4d6 100644 +--- a/crypto/cryptd.c ++++ b/crypto/cryptd.c +@@ -945,7 +945,7 @@ static void __exit cryptd_exit(void) + crypto_unregister_template(&cryptd_tmpl); + } + +-module_init(cryptd_init); ++subsys_initcall(cryptd_init); + module_exit(cryptd_exit); + + MODULE_LICENSE("GPL"); diff --git a/kernel.spec b/kernel.spec index 324b26c62..83e480b48 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 1 +%global baserelease 0 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -84,7 +84,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 2 # The git snapshot level -%define gitrev 0 +%define gitrev 5 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -718,6 +718,7 @@ Patch12024: epoll-fix-spurious-lockdep-warnings.patch Patch12025: rcu-avoid-just-onlined-cpu-resched.patch Patch12026: block-stray-block-put-after-teardown.patch Patch12027: usb-add-quirk-for-logitech-webcams.patch +Patch12029: crypto-register-cryptd-first.patch # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch @@ -1343,6 +1344,8 @@ ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch ApplyPatch block-stray-block-put-after-teardown.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch +ApplyPatch crypto-register-cryptd-first.patch + # Runtime PM #ApplyPatch linux-2.6-usb-pci-autosuspend.patch ### Broken by implicit notify support & ACPICA rebase @@ -2058,6 +2061,11 @@ fi # and build. %changelog +* Fri Aug 19 2011 Josh Boyer +- Linux 3.1-rc2-git5 +- Change XHCI to builtin (rhbz 731706) +- Add patch to fix race between cryptd and aesni (rhbz 721002) + * Thu Aug 18 2011 Josh Boyer - Adjust provides/obsoletes to replace the cpupowerutils package diff --git a/sources b/sources index e9feef65c..3ad55dba1 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 f358c354ab6d3b0da1265b504f85ec50 patch-3.1-rc2.bz2 +93c566575ae1dc33be4bc345177e4a7d patch-3.1-rc2-git5.bz2 From edd19fe2d284d48e3eb0f518cd266414abd58a09 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 19 Aug 2011 09:30:34 -0400 Subject: [PATCH 041/487] Fix 64-bit divide error in btrfs --- btrfs-use-do_div.patch | 38 ++++++++++++++++++++++++++++++++++++++ kernel.spec | 7 ++++++- 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 btrfs-use-do_div.patch diff --git a/btrfs-use-do_div.patch b/btrfs-use-do_div.patch new file mode 100644 index 000000000..e32907ddb --- /dev/null +++ b/btrfs-use-do_div.patch @@ -0,0 +1,38 @@ +From: Liu Bo cn.fujitsu.com> +Subject: [PATCH] Btrfs: use do_div to avoid compile errors on 32bit box +Date: 2011-08-19 09:48:44 GMT (3 hours and 36 minutes ago) + +When doing div operation of u64 type, we need to be careful and use do_div +to avoid compile ERROR on 32bit box: + +"ERROR: "__udivdi3" [fs/btrfs/btrfs.ko] undefined! +make[1]: *** [__modpost] Error 1 + +Signed-off-by: Liu Bo cn.fujitsu.com> +--- + fs/btrfs/extent-tree.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 80d6148..9b495ce 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -6796,14 +6796,14 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr) + index = get_block_group_index(block_group); + if (index == 0) { + dev_min = 4; +- min_free /= 2; ++ do_div(min_free, 2); + } else if (index == 1) { + dev_min = 2; + } else if (index == 2) { + min_free *= 2; + } else if (index == 3) { + dev_min = fs_devices->rw_devices; +- min_free /= dev_min; ++ do_div(min_free, dev_min); + } + + mutex_lock(&root->fs_info->chunk_mutex); +-- +1.6.5.2 diff --git a/kernel.spec b/kernel.spec index 83e480b48..7d2d1a846 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 0 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -719,6 +719,7 @@ Patch12025: rcu-avoid-just-onlined-cpu-resched.patch Patch12026: block-stray-block-put-after-teardown.patch Patch12027: usb-add-quirk-for-logitech-webcams.patch Patch12029: crypto-register-cryptd-first.patch +Patch12030: btrfs-use-do_div.patch # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch @@ -1345,6 +1346,7 @@ ApplyPatch block-stray-block-put-after-teardown.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch ApplyPatch crypto-register-cryptd-first.patch +ApplyPatch btrfs-use-do_div.patch # Runtime PM #ApplyPatch linux-2.6-usb-pci-autosuspend.patch @@ -2061,6 +2063,9 @@ fi # and build. %changelog +* Fri Aug 19 2011 Josh Boyer +- Add patch from upstream to fix 64-bit divide error in btrfs + * Fri Aug 19 2011 Josh Boyer - Linux 3.1-rc2-git5 - Change XHCI to builtin (rhbz 731706) From 348da18a206cc175373cc32d6163b1a594d7cd24 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 19 Aug 2011 09:58:07 -0400 Subject: [PATCH 042/487] BR gettext for translations. --- kernel.spec | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 7d2d1a846..0edce3f4a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -535,7 +535,7 @@ BuildRequires: xmlto, asciidoc BuildRequires: sparse >= 0.4.1 %endif %if %{with_tools} -BuildRequires: elfutils-devel zlib-devel binutils-devel newt-devel python-devel perl(ExtUtils::Embed) pciutils-devel +BuildRequires: elfutils-devel zlib-devel binutils-devel newt-devel python-devel perl(ExtUtils::Embed) pciutils-devel gettext %endif BuildConflicts: rhbuildsys(DiskFree) < 500Mb @@ -2065,6 +2065,7 @@ fi %changelog * Fri Aug 19 2011 Josh Boyer - Add patch from upstream to fix 64-bit divide error in btrfs +- Add BuildRequires on gettext for cpupowerutils translations * Fri Aug 19 2011 Josh Boyer - Linux 3.1-rc2-git5 From 5d1d642bab0833d37504d8b5d65e97f549382e20 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sat, 20 Aug 2011 08:13:48 -0400 Subject: [PATCH 043/487] 3.1-rc2-git7 snapshot. Fix provides/obsoletes for cpupowerutils-devel --- config-generic | 2 ++ kernel.spec | 11 +++++++---- sources | 2 +- xen-blkfront-name-adjust.patch | 30 ------------------------------ 4 files changed, 10 insertions(+), 35 deletions(-) delete mode 100644 xen-blkfront-name-adjust.patch diff --git a/config-generic b/config-generic index 443b2c114..38e09006b 100644 --- a/config-generic +++ b/config-generic @@ -359,6 +359,7 @@ CONFIG_CISS_SCSI_TAPE=y CONFIG_BLK_DEV_DAC960=m CONFIG_BLK_DEV_UMEM=m CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_OSD=m @@ -375,6 +376,7 @@ CONFIG_BLK_DEV_DELKIN=m # CONFIG_BLK_DEV_TC86C001 is not set CONFIG_LBDAF=y CONFIG_BLK_DEV_BSG=y +CONFIG_BLK_DEV_BSGLIB=y CONFIG_BLK_DEV_INTEGRITY=y CONFIG_BLK_DEV_THROTTLING=y diff --git a/kernel.spec b/kernel.spec index 0edce3f4a..fa415c6a9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -84,7 +84,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 2 # The git snapshot level -%define gitrev 5 +%define gitrev 7 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -677,8 +677,6 @@ Patch800: linux-2.6-crash-driver.patch # virt + ksm patches Patch1500: fix_xen_guest_on_old_EC2.patch -Patch1501: xen-blkfront-name-adjust.patch - # DRM @@ -821,6 +819,8 @@ Summary: Assortment of tools for the Linux kernel Group: Development/System License: GPLv2 Requires: kernel-tools = %{version}-%{release} +Provides: cpupowerutils-devel = 1:009-0.6.p1 +Obsoletes: cpupowerutils-devel < 1:009-0.6.p1 %description -n kernel-tools-devel This package contains the development files for the tools/ directory from the kernel source. @@ -1310,7 +1310,6 @@ ApplyPatch linux-2.6-e1000-ich9-montevina.patch # Assorted Virt Fixes ApplyPatch fix_xen_guest_on_old_EC2.patch -ApplyPatch xen-blkfront-name-adjust.patch # DRM core @@ -2063,6 +2062,10 @@ fi # and build. %changelog +* Sat Aug 20 2011 Josh Boyer +- Linux 3.1-rc2-git7 +- Add a provides/obsoletes for cpupowerutils-devel + * Fri Aug 19 2011 Josh Boyer - Add patch from upstream to fix 64-bit divide error in btrfs - Add BuildRequires on gettext for cpupowerutils translations diff --git a/sources b/sources index 3ad55dba1..c60442bdf 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 f358c354ab6d3b0da1265b504f85ec50 patch-3.1-rc2.bz2 -93c566575ae1dc33be4bc345177e4a7d patch-3.1-rc2-git5.bz2 +a617a4b89580d5e4e5be5033f8c3285b patch-3.1-rc2-git7.bz2 diff --git a/xen-blkfront-name-adjust.patch b/xen-blkfront-name-adjust.patch deleted file mode 100644 index 9573c7bf5..000000000 --- a/xen-blkfront-name-adjust.patch +++ /dev/null @@ -1,30 +0,0 @@ -commit 196cfe2ae8fcdc03b3c7d627e7dfe8c0ce7229f9 -Author: Stefan Bader -Date: Thu Jul 14 15:30:22 2011 +0200 - - xen-blkfront: Drop name and minor adjustments for emulated scsi devices - - These were intended to avoid the namespace clash when representing - emulated IDE and SCSI devices. However that seems to confuse users - more than expected (a disk defined as sda becomes xvde). - So for now go back to the scheme which does no adjustments. This - will break when mixing IDE and SCSI names in the configuration of - guests but should be by now expected. - - Acked-by: Stefano Stabellini - Signed-off-by: Stefan Bader - Signed-off-by: Konrad Rzeszutek Wilk - ---- linux-2.6.39.noarch/drivers/block/xen-blkfront.c~ 2011-08-11 11:54:25.656150889 -0400 -+++ linux-2.6.39.noarch/drivers/block/xen-blkfront.c 2011-08-11 11:54:54.573046334 -0400 -@@ -123,8 +123,8 @@ static DEFINE_SPINLOCK(minor_lock); - #define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED)) - #define EMULATED_HD_DISK_MINOR_OFFSET (0) - #define EMULATED_HD_DISK_NAME_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET / 256) --#define EMULATED_SD_DISK_MINOR_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET + (4 * 16)) --#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_HD_DISK_NAME_OFFSET + 4) -+#define EMULATED_SD_DISK_MINOR_OFFSET (0) -+#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_SD_DISK_MINOR_OFFSET / 256) - - #define DEV_NAME "xvd" /* name in /dev */ - From 46d0c5fee1276b16827b6296fa479ccc0513cf2a Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 22 Aug 2011 11:03:52 -0400 Subject: [PATCH 044/487] Avoid false quiescent states in rcutree with CONFIG_RCU_FAST_NO_HZ. (rhbz 577968) --- kernel.spec | 7 +++ rcutree-avoid-false-quiescent-states.patch | 67 ++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 rcutree-avoid-false-quiescent-states.patch diff --git a/kernel.spec b/kernel.spec index fa415c6a9..bfa767391 100644 --- a/kernel.spec +++ b/kernel.spec @@ -699,6 +699,8 @@ Patch2900: linux-2.6-v4l-dvb-update.patch Patch2901: linux-2.6-v4l-dvb-experimental.patch Patch2902: linux-2.6-v4l-dvb-uvcvideo-update.patch +Patch3000: rcutree-avoid-false-quiescent-states.patch + # fs fixes # NFSv4 @@ -1332,6 +1334,8 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch #ApplyPatch linux-2.6-v4l-dvb-uvcvideo-update.patch # Patches headed upstream +ApplyPatch rcutree-avoid-false-quiescent-states.patch + ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch add-appleir-usb-driver.patch @@ -2062,6 +2066,9 @@ fi # and build. %changelog +* Mon Aug 22 2011 Dave Jones +- Avoid false quiescent states in rcutree with CONFIG_RCU_FAST_NO_HZ. (rhbz 577968) + * Sat Aug 20 2011 Josh Boyer - Linux 3.1-rc2-git7 - Add a provides/obsoletes for cpupowerutils-devel diff --git a/rcutree-avoid-false-quiescent-states.patch b/rcutree-avoid-false-quiescent-states.patch new file mode 100644 index 000000000..9c7ffea34 --- /dev/null +++ b/rcutree-avoid-false-quiescent-states.patch @@ -0,0 +1,67 @@ +diff --git a/kernel/rcutree.c b/kernel/rcutree.c +index ba06207..c38a882 100644 +--- a/kernel/rcutree.c ++++ b/kernel/rcutree.c +@@ -1476,9 +1476,6 @@ static void rcu_process_callbacks(struct softirq_action *unused) + &__get_cpu_var(rcu_sched_data)); + __rcu_process_callbacks(&rcu_bh_state, &__get_cpu_var(rcu_bh_data)); + rcu_preempt_process_callbacks(); +- +- /* If we are last CPU on way to dyntick-idle mode, accelerate it. */ +- rcu_needs_cpu_flush(); + } + + /* +diff --git a/kernel/rcutree.h b/kernel/rcutree.h +index 01b2ccd..795f7fc 100644 +--- a/kernel/rcutree.h ++++ b/kernel/rcutree.h +@@ -450,7 +450,6 @@ static int rcu_preempt_needs_cpu(int cpu); + static void __cpuinit rcu_preempt_init_percpu_data(int cpu); + static void rcu_preempt_send_cbs_to_online(void); + static void __init __rcu_init_preempt(void); +-static void rcu_needs_cpu_flush(void); + static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags); + static void rcu_preempt_boost_start_gp(struct rcu_node *rnp); + static void invoke_rcu_callbacks_kthread(void); +diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h +index 8aafbb8..b0254de 100644 +--- a/kernel/rcutree_plugin.h ++++ b/kernel/rcutree_plugin.h +@@ -1907,15 +1907,6 @@ int rcu_needs_cpu(int cpu) + return rcu_needs_cpu_quick_check(cpu); + } + +-/* +- * Check to see if we need to continue a callback-flush operations to +- * allow the last CPU to enter dyntick-idle mode. But fast dyntick-idle +- * entry is not configured, so we never do need to. +- */ +-static void rcu_needs_cpu_flush(void) +-{ +-} +- + #else /* #if !defined(CONFIG_RCU_FAST_NO_HZ) */ + + #define RCU_NEEDS_CPU_FLUSHES 5 +@@ -1991,20 +1982,4 @@ int rcu_needs_cpu(int cpu) + return c; + } + +-/* +- * Check to see if we need to continue a callback-flush operations to +- * allow the last CPU to enter dyntick-idle mode. +- */ +-static void rcu_needs_cpu_flush(void) +-{ +- int cpu = smp_processor_id(); +- unsigned long flags; +- +- if (per_cpu(rcu_dyntick_drain, cpu) <= 0) +- return; +- local_irq_save(flags); +- (void)rcu_needs_cpu(cpu); +- local_irq_restore(flags); +-} +- + #endif /* #else #if !defined(CONFIG_RCU_FAST_NO_HZ) */ From 7885dbca86b58e3bf039e132f21cdc0cb982ca27 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 22 Aug 2011 17:15:34 -0400 Subject: [PATCH 045/487] 3.1-rc3. Add patch to fix duplicate backlight registration on i915 --- btrfs-use-do_div.patch | 38 ------------------------- fix-intel-duplicate-backlight.patch | 44 +++++++++++++++++++++++++++++ kernel.spec | 14 +++++---- sources | 3 +- 4 files changed, 54 insertions(+), 45 deletions(-) delete mode 100644 btrfs-use-do_div.patch create mode 100644 fix-intel-duplicate-backlight.patch diff --git a/btrfs-use-do_div.patch b/btrfs-use-do_div.patch deleted file mode 100644 index e32907ddb..000000000 --- a/btrfs-use-do_div.patch +++ /dev/null @@ -1,38 +0,0 @@ -From: Liu Bo cn.fujitsu.com> -Subject: [PATCH] Btrfs: use do_div to avoid compile errors on 32bit box -Date: 2011-08-19 09:48:44 GMT (3 hours and 36 minutes ago) - -When doing div operation of u64 type, we need to be careful and use do_div -to avoid compile ERROR on 32bit box: - -"ERROR: "__udivdi3" [fs/btrfs/btrfs.ko] undefined! -make[1]: *** [__modpost] Error 1 - -Signed-off-by: Liu Bo cn.fujitsu.com> ---- - fs/btrfs/extent-tree.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c -index 80d6148..9b495ce 100644 ---- a/fs/btrfs/extent-tree.c -+++ b/fs/btrfs/extent-tree.c -@@ -6796,14 +6796,14 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr) - index = get_block_group_index(block_group); - if (index == 0) { - dev_min = 4; -- min_free /= 2; -+ do_div(min_free, 2); - } else if (index == 1) { - dev_min = 2; - } else if (index == 2) { - min_free *= 2; - } else if (index == 3) { - dev_min = fs_devices->rw_devices; -- min_free /= dev_min; -+ do_div(min_free, dev_min); - } - - mutex_lock(&root->fs_info->chunk_mutex); --- -1.6.5.2 diff --git a/fix-intel-duplicate-backlight.patch b/fix-intel-duplicate-backlight.patch new file mode 100644 index 000000000..c33e92ec2 --- /dev/null +++ b/fix-intel-duplicate-backlight.patch @@ -0,0 +1,44 @@ +From: Kamal Mostafa +To: Linux Kernel , + intel-gfx@lists.freedesktop.org +Cc: Matthew Garrett , + Keith Packard , + Kamal Mostafa +Subject: [PATCH] i915: do not setup intel_backlight twice +Date: Mon, 22 Aug 2011 12:39:10 -0700 +Message-Id: <1314041950-12433-1-git-send-email-kamal@canonical.com> +X-Mailer: git-send-email 1.7.4.1 +In-Reply-To: <20110817141010.GA21479@redhat.com> +References: <20110817141010.GA21479@redhat.com> +Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org + +The commit "Not all systems expose a firmware or platform mechanism for +changing the backlight intensity on i915, so add native driver support" +adds calls to intel_panel_setup_backlight() from intel_{lvds,dp}_init +so do not call it again from intel_setup_outputs(). + +BugLink: http://bugs.launchpad.net/bugs/831542 + +Signed-off-by: Kamal Mostafa +--- + drivers/gpu/drm/i915/intel_display.c | 2 -- + 1 files changed, 0 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index ee1d701..5a1ae9f 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -7238,8 +7238,6 @@ static void intel_setup_outputs(struct drm_device *dev) + intel_encoder_clones(dev, encoder->clone_mask); + } + +- intel_panel_setup_backlight(dev); +- + /* disable all the possible outputs/crtcs before entering KMS mode */ + drm_helper_disable_unused_functions(dev); + } +-- +1.7.4.1 diff --git a/kernel.spec b/kernel.spec index bfa767391..9ae502c69 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 2 +%global baserelease 0 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -82,9 +82,9 @@ Summary: The Linux kernel # The next upstream release sublevel (base_sublevel+1) %define upstream_sublevel %(echo $((%{base_sublevel} + 1))) # The rc snapshot level -%define rcrev 2 +%define rcrev 3 # The git snapshot level -%define gitrev 7 +%define gitrev 0 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -719,7 +719,7 @@ Patch12025: rcu-avoid-just-onlined-cpu-resched.patch Patch12026: block-stray-block-put-after-teardown.patch Patch12027: usb-add-quirk-for-logitech-webcams.patch Patch12029: crypto-register-cryptd-first.patch -Patch12030: btrfs-use-do_div.patch +Patch12030: fix-intel-duplicate-backlight.patch # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch @@ -1349,7 +1349,7 @@ ApplyPatch block-stray-block-put-after-teardown.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch ApplyPatch crypto-register-cryptd-first.patch -ApplyPatch btrfs-use-do_div.patch +ApplyPatch fix-intel-duplicate-backlight.patch # Runtime PM #ApplyPatch linux-2.6-usb-pci-autosuspend.patch @@ -2066,6 +2066,10 @@ fi # and build. %changelog +* Mon Aug 22 2011 Josh Boyer +- Linux 3.1-rc3 +- Add patch to fix duplicate backlight registration (rhbz 732202) + * Mon Aug 22 2011 Dave Jones - Avoid false quiescent states in rcutree with CONFIG_RCU_FAST_NO_HZ. (rhbz 577968) diff --git a/sources b/sources index c60442bdf..c733b510b 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 -f358c354ab6d3b0da1265b504f85ec50 patch-3.1-rc2.bz2 -a617a4b89580d5e4e5be5033f8c3285b patch-3.1-rc2-git7.bz2 +b9a15f79846c4d01fa3019a3112a8d04 patch-3.1-rc3.bz2 From 1be8cbc361611079b563f5497c4b1458e227bafe Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 24 Aug 2011 08:41:30 -0400 Subject: [PATCH 046/487] Revert 'iwlwifi: advertise max aggregate size'. (rhbz 708747) --- iwlagn-revert-max-aggregate-size.patch | 13 +++++++++++++ kernel.spec | 7 ++++++- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 iwlagn-revert-max-aggregate-size.patch diff --git a/iwlagn-revert-max-aggregate-size.patch b/iwlagn-revert-max-aggregate-size.patch new file mode 100644 index 000000000..d9e9a8db4 --- /dev/null +++ b/iwlagn-revert-max-aggregate-size.patch @@ -0,0 +1,13 @@ +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c +index b0ae4de..afa00ec 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn.c +@@ -2140,8 +2140,6 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, + IEEE80211_HW_SPECTRUM_MGMT | + IEEE80211_HW_REPORTS_TX_ACK_STATUS; + +- hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF; +- + hw->flags |= IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_SUPPORTS_DYNAMIC_PS; + diff --git a/kernel.spec b/kernel.spec index 9ae502c69..5677e0505 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 0 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -729,6 +729,7 @@ Patch12205: runtime_pm_fixups.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch +Patch13004: iwlagn-revert-max-aggregate-size.patch Patch20000: utrace.patch @@ -1361,6 +1362,7 @@ ApplyPatch fix-intel-duplicate-backlight.patch ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch +ApplyPatch iwlagn-revert-max-aggregate-size.patch # utrace. ApplyPatch utrace.patch @@ -2066,6 +2068,9 @@ fi # and build. %changelog +* Wed Aug 24 2011 Josh Boyer +- Revert 'iwlwifi: advertise max aggregate size'. (rhbz 708747) + * Mon Aug 22 2011 Josh Boyer - Linux 3.1-rc3 - Add patch to fix duplicate backlight registration (rhbz 732202) From d1ab8a1bfd855c68b1b04a6e64ef68e823cdd7d8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 26 Aug 2011 08:30:26 -0400 Subject: [PATCH 047/487] 3.1-rc3-git5 cleanup some of the cpupowerutils build stuff --- fix-cdc-ncm-dma-stack-vars.patch | 109 ------------------------------- kernel.spec | 43 ++++++------ sources | 1 + 3 files changed, 22 insertions(+), 131 deletions(-) delete mode 100644 fix-cdc-ncm-dma-stack-vars.patch diff --git a/fix-cdc-ncm-dma-stack-vars.patch b/fix-cdc-ncm-dma-stack-vars.patch deleted file mode 100644 index 17b555a85..000000000 --- a/fix-cdc-ncm-dma-stack-vars.patch +++ /dev/null @@ -1,109 +0,0 @@ -commit 05511b61169da2f8dab464df61fa2bb952763a23 -Author: Josh Boyer -Date: Tue Aug 2 08:09:56 2011 -0400 - - usbnet/cdc_ncm: Don't use stack variables for DMA buffers - - The cdc_ncm driver still has a few places where stack variables are passed - to the cdc_ncm_do_request function. This triggers a stack trace in - lib/dma-debug.c if the CONFIG_DEBUG_DMA_API option is set. - - Adjust these calls to pass parameters that have been allocated with kzalloc. - - Signed-off-by: Josh Boyer - -diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c -index a03336e..f06fb78 100644 ---- a/drivers/net/usb/cdc_ncm.c -+++ b/drivers/net/usb/cdc_ncm.c -@@ -228,23 +228,40 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) - if (ctx->rx_max != le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize)) { - - if (flags & USB_CDC_NCM_NCAP_NTB_INPUT_SIZE) { -- struct usb_cdc_ncm_ndp_input_size ndp_in_sz; -+ struct usb_cdc_ncm_ndp_input_size *ndp_in_sz; -+ -+ ndp_in_sz = kzalloc(sizeof(*ndp_in_sz), GFP_KERNEL); -+ if (!ndp_in_sz) { -+ err = -ENOMEM; -+ goto size_err; -+ } -+ - err = usb_control_msg(ctx->udev, - usb_sndctrlpipe(ctx->udev, 0), - USB_CDC_SET_NTB_INPUT_SIZE, - USB_TYPE_CLASS | USB_DIR_OUT - | USB_RECIP_INTERFACE, -- 0, iface_no, &ndp_in_sz, 8, 1000); -+ 0, iface_no, ndp_in_sz, 8, 1000); -+ kfree(ndp_in_sz); - } else { -- __le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); -+ __le32 *dwNtbInMaxSize; -+ dwNtbInMaxSize = kzalloc(sizeof(*dwNtbInMaxSize), -+ GFP_KERNEL); -+ if (!dwNtbInMaxSize) { -+ err = -ENOMEM; -+ goto size_err; -+ } -+ *dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); -+ - err = usb_control_msg(ctx->udev, - usb_sndctrlpipe(ctx->udev, 0), - USB_CDC_SET_NTB_INPUT_SIZE, - USB_TYPE_CLASS | USB_DIR_OUT - | USB_RECIP_INTERFACE, -- 0, iface_no, &dwNtbInMaxSize, 4, 1000); -+ 0, iface_no, dwNtbInMaxSize, 4, 1000); -+ kfree(dwNtbInMaxSize); - } -- -+size_err: - if (err < 0) - pr_debug("Setting NTB Input Size failed\n"); - } -@@ -325,19 +342,29 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) - - /* set Max Datagram Size (MTU) */ - if (flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE) { -- __le16 max_datagram_size; -+ __le16 *max_datagram_size; - u16 eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize); -+ -+ max_datagram_size = kzalloc(sizeof(*max_datagram_size), -+ GFP_KERNEL); -+ if (!max_datagram_size) { -+ err = -ENOMEM; -+ goto max_dgram_err; -+ } -+ - err = usb_control_msg(ctx->udev, usb_rcvctrlpipe(ctx->udev, 0), - USB_CDC_GET_MAX_DATAGRAM_SIZE, - USB_TYPE_CLASS | USB_DIR_IN - | USB_RECIP_INTERFACE, -- 0, iface_no, &max_datagram_size, -+ 0, iface_no, max_datagram_size, - 2, 1000); - if (err < 0) { - pr_debug("GET_MAX_DATAGRAM_SIZE failed, use size=%u\n", - CDC_NCM_MIN_DATAGRAM_SIZE); -+ kfree(max_datagram_size); - } else { -- ctx->max_datagram_size = le16_to_cpu(max_datagram_size); -+ ctx->max_datagram_size = -+ le16_to_cpu(*max_datagram_size); - /* Check Eth descriptor value */ - if (eth_max_sz < CDC_NCM_MAX_DATAGRAM_SIZE) { - if (ctx->max_datagram_size > eth_max_sz) -@@ -360,8 +387,10 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) - USB_TYPE_CLASS | USB_DIR_OUT - | USB_RECIP_INTERFACE, - 0, -- iface_no, &max_datagram_size, -+ iface_no, max_datagram_size, - 2, 1000); -+ kfree(max_datagram_size); -+max_dgram_err: - if (err < 0) - pr_debug("SET_MAX_DATAGRAM_SIZE failed\n"); - } diff --git a/kernel.spec b/kernel.spec index 5677e0505..204157552 100644 --- a/kernel.spec +++ b/kernel.spec @@ -84,7 +84,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 3 # The git snapshot level -%define gitrev 0 +%define gitrev 5 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -712,7 +712,6 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12021: udlfb-bind-framebuffer-to-interface.patch -Patch12022: fix-cdc-ncm-dma-stack-vars.patch Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch Patch12024: epoll-fix-spurious-lockdep-warnings.patch Patch12025: rcu-avoid-just-onlined-cpu-resched.patch @@ -1342,7 +1341,6 @@ ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch add-appleir-usb-driver.patch ApplyPatch udlfb-bind-framebuffer-to-interface.patch -ApplyPatch fix-cdc-ncm-dma-stack-vars.patch ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch ApplyPatch epoll-fix-spurious-lockdep-warnings.patch ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch @@ -1699,20 +1697,17 @@ make %{?_smp_mflags} -C tools/perf -s V=1 prefix=%{_prefix} man || %{doc_build_f # cpupower # make sure version-gen.sh is executable. chmod +x tools/power/cpupower/utils/version-gen.sh -make %{?_smp_mflags} -C tools/power/cpupower CPUFRQ_BENCH=false -# this is fairly unnecessary at the moment. The x86_64 dir just contains -# symlinks to the i386 dir in the tarball, but patch hates that. We'll just -# build the i386 dir in all cases for now. -#ifarch {ix86} +make %{?_smp_mflags} -C tools/power/cpupower CPUFREQ_BENCH=false +%ifarch %{ix86} cd tools/power/cpupower/debug/i386 make %{?_smp_mflags} centrino-decode powernow-k8-decode cd - -#endif -#ifarch x86_64 -# cd tools/power/cpupower/debug/x86_64 -# make {?_smp_mflags} -# cd - -#endif +%endif +%ifarch x86_64 + cd tools/power/cpupower/debug/x86_64 + make %{?_smp_mflags} centrino-decode powernow-k8-decode + cd - +%endif %endif %endif @@ -1805,21 +1800,22 @@ make -C tools/perf -s V=1 DESTDIR=$RPM_BUILD_ROOT HAVE_CPLUS_DEMANGLE=1 prefix=% make -C tools/perf -s V=1 DESTDIR=$RPM_BUILD_ROOT HAVE_CPLUS_DEMANGLE=1 prefix=%{_prefix} install-man || %{doc_build_fail} %ifarch %{cpupowerarchs} -make -C tools/power/cpupower DESTDIR=$RPM_BUILD_ROOT libdir=%{_libdir} mandir=%{_mandir} CPUFRQ_BENCH=false install +make -C tools/power/cpupower DESTDIR=$RPM_BUILD_ROOT libdir=%{_libdir} mandir=%{_mandir} CPUFREQ_BENCH=false install rm -f %{buildroot}%{_libdir}/*.{a,la} %find_lang cpupower mv cpupower.lang ../ -#ifarch #{ix86} +%ifarch %{ix86} cd tools/power/cpupower/debug/i386 install -m755 centrino-decode %{buildroot}%{_bindir}/centrino-decode install -m755 powernow-k8-decode %{buildroot}%{_bindir}/powernow-k8-decode cd - -#endif -#ifarch x86_64 -# cd tools/power/cpupower/debug/x86_64 -# install -m755 powernow-k8-decode {buildroot}{_bindir}/powernow-k8-decode -# cd - -#endif +%endif +%ifarch x86_64 + cd tools/power/cpupower/debug/x86_64 + install -m755 centrino-decode %{buildroot}%{_bindir}/centrino-decode + install -m755 powernow-k8-decode %{buildroot}%{_bindir}/powernow-k8-decode + cd - +%endif chmod 0755 %{buildroot}%{_libdir}/libcpupower.so* mkdir -p %{buildroot}%{_unitdir} %{buildroot}%{_sysconfdir}/sysconfig install -m644 %{SOURCE2000} %{buildroot}%{_unitdir}/cpupower.service @@ -2068,6 +2064,9 @@ fi # and build. %changelog +* Fri Aug 26 2011 Josh Boyer +- Linux 3.1-rc3-git5 + * Wed Aug 24 2011 Josh Boyer - Revert 'iwlwifi: advertise max aggregate size'. (rhbz 708747) diff --git a/sources b/sources index c733b510b..9045d10b2 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 b9a15f79846c4d01fa3019a3112a8d04 patch-3.1-rc3.bz2 +d616dde9b999388576b12d9ad7edeca1 patch-3.1-rc3-git5.bz2 From 61dbaf7ef7d2cc30ffba53434ecf91dcb90b7bcf Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 26 Aug 2011 11:34:06 -0400 Subject: [PATCH 048/487] Drop acpi-ec-add-delay-before-write.patch (rhbz 733690) --- TODO | 1 - acpi-ec-add-delay-before-write.patch | 51 ---------------------------- kernel.spec | 5 +-- 3 files changed, 3 insertions(+), 54 deletions(-) delete mode 100644 acpi-ec-add-delay-before-write.patch diff --git a/TODO b/TODO index 968324422..c6549f4ad 100644 --- a/TODO +++ b/TODO @@ -47,7 +47,6 @@ * linux-2.6-usb-pci-autosuspend.patch * linux-2.6-enable-more-pci-autosuspend.patch * linux-2.6-acpi-debug-infinite-loop.patch -* acpi-ec-add-delay-before-write.patch Responsible: mjg59 * linux-2.6-v4l-dvb-experimental.patch diff --git a/acpi-ec-add-delay-before-write.patch b/acpi-ec-add-delay-before-write.patch deleted file mode 100644 index f1cb50817..000000000 --- a/acpi-ec-add-delay-before-write.patch +++ /dev/null @@ -1,51 +0,0 @@ -https://bugzilla.kernel.org/show_bug.cgi?id=14733#c41 - -diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c -index 27e0b92..09fbb69 100644 ---- a/drivers/acpi/ec.c -+++ b/drivers/acpi/ec.c -@@ -226,6 +226,7 @@ static int ec_poll(struct acpi_ec *ec) - if (ec_transaction_done(ec)) - return 0; - } else { -+ msleep(1); - if (wait_event_timeout(ec->wait, - ec_transaction_done(ec), - msecs_to_jiffies(1))) -@@ -233,8 +234,8 @@ static int ec_poll(struct acpi_ec *ec) - } - advance_transaction(ec, acpi_ec_read_status(ec)); - } while (time_before(jiffies, delay)); -- if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) -- break; -+// if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) -+// break; - pr_debug(PREFIX "controller reset, restart transaction\n"); - spin_lock_irqsave(&ec->curr_lock, flags); - start_transaction(ec); -@@ -271,15 +272,24 @@ static int ec_check_ibf0(struct acpi_ec *ec) - return (status & ACPI_EC_FLAG_IBF) == 0; - } - -+/* try to clean input buffer with burst_disable transaction */ -+static int acpi_ec_clean_buffer(struct acpi_ec *ec) -+{ -+ struct transaction t = {.command = ACPI_EC_BURST_DISABLE, -+ .wdata = NULL, .rdata = NULL, -+ .wlen = 0, .rlen = 0}; -+ return acpi_ec_transaction_unlocked(ec, &t); -+} -+ - static int ec_wait_ibf0(struct acpi_ec *ec) - { - unsigned long delay = jiffies + msecs_to_jiffies(ec_delay); - /* interrupt wait manually if GPE mode is not active */ - while (time_before(jiffies, delay)) - if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), - msecs_to_jiffies(1))) - return 0; -- return -ETIME; -+ return acpi_ec_clean_buffer(ec); - } - - static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) diff --git a/kernel.spec b/kernel.spec index 204157552..502a713d6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -656,7 +656,6 @@ Patch383: linux-2.6-defaults-aspm.patch Patch390: linux-2.6-defaults-acpi-video.patch Patch391: linux-2.6-acpi-video-dos.patch -Patch393: acpi-ec-add-delay-before-write.patch Patch394: linux-2.6-acpi-debug-infinite-loop.patch Patch450: linux-2.6-input-kill-stupid-messages.patch @@ -1257,7 +1256,6 @@ ApplyPatch linux-2.6-32bit-mmap-exec-randomization.patch # ACPI ApplyPatch linux-2.6-defaults-acpi-video.patch ApplyPatch linux-2.6-acpi-video-dos.patch -ApplyPatch acpi-ec-add-delay-before-write.patch ApplyPatch linux-2.6-acpi-debug-infinite-loop.patch # Various low-impact patches to aid debugging. @@ -2064,6 +2062,9 @@ fi # and build. %changelog +* Fri Aug 26 2011 Dave Jones +- Drop acpi-ec-add-delay-before-write.patch (rhbz 733690) + * Fri Aug 26 2011 Josh Boyer - Linux 3.1-rc3-git5 From af75d596645d1007982824e2076c5e1b855bd9c6 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 26 Aug 2011 11:35:07 -0400 Subject: [PATCH 049/487] remove unapplied patches --- TODO | 2 - kernel.spec | 8 - linux-2.6-enable-more-pci-autosuspend.patch | 452 -------------------- linux-2.6-usb-pci-autosuspend.patch | 22 - 4 files changed, 484 deletions(-) delete mode 100644 linux-2.6-enable-more-pci-autosuspend.patch delete mode 100644 linux-2.6-usb-pci-autosuspend.patch diff --git a/TODO b/TODO index c6549f4ad..f444b44d6 100644 --- a/TODO +++ b/TODO @@ -44,8 +44,6 @@ davej bugged Ingo again on Jun 17 2011 about upstreaming. * runtime_pm_fixups.patch -* linux-2.6-usb-pci-autosuspend.patch -* linux-2.6-enable-more-pci-autosuspend.patch * linux-2.6-acpi-debug-infinite-loop.patch Responsible: mjg59 diff --git a/kernel.spec b/kernel.spec index 502a713d6..5baddbb72 100644 --- a/kernel.spec +++ b/kernel.spec @@ -720,8 +720,6 @@ Patch12029: crypto-register-cryptd-first.patch Patch12030: fix-intel-duplicate-backlight.patch # Runtime power management -Patch12203: linux-2.6-usb-pci-autosuspend.patch -Patch12204: linux-2.6-enable-more-pci-autosuspend.patch Patch12205: runtime_pm_fixups.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch @@ -1348,12 +1346,6 @@ ApplyPatch usb-add-quirk-for-logitech-webcams.patch ApplyPatch crypto-register-cryptd-first.patch ApplyPatch fix-intel-duplicate-backlight.patch -# Runtime PM -#ApplyPatch linux-2.6-usb-pci-autosuspend.patch -### Broken by implicit notify support & ACPICA rebase -###ApplyPatch linux-2.6-enable-more-pci-autosuspend.patch -#ApplyPatch runtime_pm_fixups.patch - # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch diff --git a/linux-2.6-enable-more-pci-autosuspend.patch b/linux-2.6-enable-more-pci-autosuspend.patch deleted file mode 100644 index 666ded640..000000000 --- a/linux-2.6-enable-more-pci-autosuspend.patch +++ /dev/null @@ -1,452 +0,0 @@ - drivers/acpi/acpica/aclocal.h | 7 +-- - drivers/acpi/acpica/evgpe.c | 75 +++++++++++++++----------------- - drivers/acpi/acpica/evgpeinit.c | 11 +---- - drivers/acpi/acpica/evgpeutil.c | 5 +- - drivers/acpi/acpica/evxface.c | 23 +++++----- - drivers/acpi/ec.c | 2 +- - drivers/acpi/pci_bind.c | 86 ++++++++++++++++++++++++++++++++++++++ - drivers/acpi/sleep.c | 2 +- - drivers/char/ipmi/ipmi_si_intf.c | 2 +- - include/acpi/acpixf.h | 3 +- - 10 files changed, 143 insertions(+), 73 deletions(-) - -diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h -index 2ceb0c0..3663362 100644 ---- a/drivers/acpi/acpica/aclocal.h -+++ b/drivers/acpi/acpica/aclocal.h -@@ -406,17 +406,16 @@ struct acpi_predefined_data { - * - ****************************************************************************/ - --/* Dispatch info for each GPE -- either a method or handler, cannot be both */ -+/* Dispatch info for each GPE */ - - struct acpi_handler_info { - acpi_event_handler address; /* Address of handler, if any */ - void *context; /* Context to be passed to handler */ -- struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */ - u8 orig_flags; /* Original misc info about this GPE */ - u8 orig_enabled; /* Set if the GPE was originally enabled */ - }; - --union acpi_gpe_dispatch_info { -+struct acpi_gpe_dispatch_info { - struct acpi_namespace_node *method_node; /* Method node for this GPE level */ - struct acpi_handler_info *handler; - }; -@@ -426,7 +425,7 @@ union acpi_gpe_dispatch_info { - * NOTE: Important to keep this struct as small as possible. - */ - struct acpi_gpe_event_info { -- union acpi_gpe_dispatch_info dispatch; /* Either Method or Handler */ -+ struct acpi_gpe_dispatch_info dispatch; - struct acpi_gpe_register_info *register_info; /* Backpointer to register info */ - u8 flags; /* Misc info about this GPE */ - u8 gpe_number; /* This GPE */ -diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c -index f226eac..c4b1c4c 100644 ---- a/drivers/acpi/acpica/evgpe.c -+++ b/drivers/acpi/acpica/evgpe.c -@@ -474,9 +474,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) - * Must check for control method type dispatch one more time to avoid a - * race with ev_gpe_install_handler - */ -- if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) == -- ACPI_GPE_DISPATCH_METHOD) { -- -+ if (local_gpe_event_info.flags & ACPI_GPE_DISPATCH_METHOD) { - /* Allocate the evaluation information block */ - - info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); -@@ -575,41 +573,15 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) - } - - /* -- * Dispatch the GPE to either an installed handler, or the control method -- * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke -- * it and do not attempt to run the method. If there is neither a handler -- * nor a method, we disable this GPE to prevent further such pointless -- * events from firing. -+ * Dispatch the GPE to either any installed handler or control -+ * method associated with this GPE (_Lxx or _Exx). We invoke -+ * the method first in case it has side effects that would be -+ * interfered with if the handler has already altered hardware -+ * state. If there is neither a handler nor a method, we -+ * disable this GPE to prevent further such pointless events -+ * from firing. - */ -- switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) { -- case ACPI_GPE_DISPATCH_HANDLER: -- -- /* -- * Invoke the installed handler (at interrupt level) -- * Ignore return status for now. -- * TBD: leave GPE disabled on error? -- */ -- (void)gpe_event_info->dispatch.handler->address(gpe_event_info-> -- dispatch. -- handler-> -- context); -- -- /* It is now safe to clear level-triggered events. */ -- -- if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == -- ACPI_GPE_LEVEL_TRIGGERED) { -- status = acpi_hw_clear_gpe(gpe_event_info); -- if (ACPI_FAILURE(status)) { -- ACPI_EXCEPTION((AE_INFO, status, -- "Unable to clear GPE[0x%2X]", -- gpe_number)); -- return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); -- } -- } -- break; -- -- case ACPI_GPE_DISPATCH_METHOD: -- -+ if (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) { - /* - * Disable the GPE, so it doesn't keep firing before the method has a - * chance to run (it runs asynchronously with interrupts enabled). -@@ -634,10 +606,34 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) - "Unable to queue handler for GPE[0x%2X] - event disabled", - gpe_number)); - } -- break; -+ } - -- default: -+ if (gpe_event_info->flags & ACPI_GPE_DISPATCH_HANDLER) { -+ /* -+ * Invoke the installed handler (at interrupt level) -+ * Ignore return status for now. -+ * TBD: leave GPE disabled on error? -+ */ -+ (void)gpe_event_info->dispatch.handler->address(gpe_event_info-> -+ dispatch. -+ handler-> -+ context); - -+ /* It is now safe to clear level-triggered events. */ -+ -+ if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == -+ ACPI_GPE_LEVEL_TRIGGERED) { -+ status = acpi_hw_clear_gpe(gpe_event_info); -+ if (ACPI_FAILURE(status)) { -+ ACPI_EXCEPTION((AE_INFO, status, -+ "Unable to clear GPE[0x%2X]", -+ gpe_number)); -+ return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); -+ } -+ } -+ } -+ -+ if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) { - /* - * No handler or method to run! - * 03/2010: This case should no longer be possible. We will not allow -@@ -658,7 +654,6 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) - gpe_number)); - return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); - } -- break; - } - - return_UINT32(ACPI_INTERRUPT_HANDLED); -diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c -index 2c7def9..9915b52 100644 ---- a/drivers/acpi/acpica/evgpeinit.c -+++ b/drivers/acpi/acpica/evgpeinit.c -@@ -386,16 +386,7 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle, - return_ACPI_STATUS(AE_OK); - } - -- if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == -- ACPI_GPE_DISPATCH_HANDLER) { -- -- /* If there is already a handler, ignore this GPE method */ -- -- return_ACPI_STATUS(AE_OK); -- } -- -- if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == -- ACPI_GPE_DISPATCH_METHOD) { -+ if (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) { - /* - * If there is already a method, ignore this method. But check - * for a type mismatch (if both the _Lxx AND _Exx exist) -diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c -index 19a0e51..434ad1b 100644 ---- a/drivers/acpi/acpica/evgpeutil.c -+++ b/drivers/acpi/acpica/evgpeutil.c -@@ -323,12 +323,11 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, - ACPI_GPE_REGISTER_WIDTH) - + j]; - -- if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == -- ACPI_GPE_DISPATCH_HANDLER) { -+ if (gpe_event_info->flags & ACPI_GPE_DISPATCH_HANDLER) { - ACPI_FREE(gpe_event_info->dispatch.handler); - gpe_event_info->dispatch.handler = NULL; - gpe_event_info->flags &= -- ~ACPI_GPE_DISPATCH_MASK; -+ ~ACPI_GPE_DISPATCH_HANDLER; - } - } - } -diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c -index 36af222..b097136 100644 ---- a/drivers/acpi/acpica/evxface.c -+++ b/drivers/acpi/acpica/evxface.c -@@ -662,6 +662,8 @@ ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler) - * edge- or level-triggered interrupt. - * Address - Address of the handler - * Context - Value passed to the handler on each GPE -+ * keep_method - Whether the existing method should be -+ * displaced or kept - * - * RETURN: Status - * -@@ -671,7 +673,8 @@ ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler) - acpi_status - acpi_install_gpe_handler(acpi_handle gpe_device, - u32 gpe_number, -- u32 type, acpi_event_handler address, void *context) -+ u32 type, acpi_event_handler address, void *context, -+ bool keep_method) - { - struct acpi_gpe_event_info *gpe_event_info; - struct acpi_handler_info *handler; -@@ -711,8 +714,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device, - - /* Make sure that there isn't a handler there already */ - -- if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == -- ACPI_GPE_DISPATCH_HANDLER) { -+ if (gpe_event_info->flags & ACPI_GPE_DISPATCH_HANDLER) { - status = AE_ALREADY_EXISTS; - goto free_and_exit; - } -@@ -721,7 +723,6 @@ acpi_install_gpe_handler(acpi_handle gpe_device, - - handler->address = address; - handler->context = context; -- handler->method_node = gpe_event_info->dispatch.method_node; - handler->orig_flags = gpe_event_info->flags & - (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); - -@@ -732,7 +733,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device, - */ - - if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD) -- && gpe_event_info->runtime_count) { -+ && gpe_event_info->runtime_count && !keep_method) { - handler->orig_enabled = 1; - (void)acpi_raw_disable_gpe(gpe_event_info); - } -@@ -741,10 +742,10 @@ acpi_install_gpe_handler(acpi_handle gpe_device, - - gpe_event_info->dispatch.handler = handler; - -- /* Setup up dispatch flags to indicate handler (vs. method) */ -+ if (!keep_method) -+ gpe_event_info->flags &= -+ ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); - -- gpe_event_info->flags &= -- ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); - gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER); - - acpi_os_release_lock(acpi_gbl_gpe_lock, flags); -@@ -813,8 +814,7 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, - - /* Make sure that a handler is indeed installed */ - -- if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) != -- ACPI_GPE_DISPATCH_HANDLER) { -+ if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_HANDLER)) { - status = AE_NOT_EXIST; - goto unlock_and_exit; - } -@@ -830,9 +830,8 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, - - handler = gpe_event_info->dispatch.handler; - -- /* Restore Method node (if any), set dispatch flags */ -+ /* Set dispatch flags */ - -- gpe_event_info->dispatch.method_node = handler->method_node; - gpe_event_info->flags &= - ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); - gpe_event_info->flags |= handler->orig_flags; -diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c -index 372ff80..9a39f82 100644 ---- a/drivers/acpi/ec.c -+++ b/drivers/acpi/ec.c -@@ -740,7 +740,7 @@ static int ec_install_handlers(struct acpi_ec *ec) - return 0; - status = acpi_install_gpe_handler(NULL, ec->gpe, - ACPI_GPE_EDGE_TRIGGERED, -- &acpi_ec_gpe_handler, ec); -+ &acpi_ec_gpe_handler, ec, false); - if (ACPI_FAILURE(status)) - return -ENODEV; - -diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c -index 2ef0409..8b3cc6a 100644 ---- a/drivers/acpi/pci_bind.c -+++ b/drivers/acpi/pci_bind.c -@@ -28,6 +28,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -35,6 +36,43 @@ - #define _COMPONENT ACPI_PCI_COMPONENT - ACPI_MODULE_NAME("pci_bind"); - -+static LIST_HEAD(acpi_pci_gpe_devs); -+ -+struct pci_gpe_dev { -+ struct list_head node; -+ struct pci_dev *dev; -+ acpi_handle gpe_device; -+ int gpe_number; -+ struct work_struct work; -+}; -+ -+static void acpi_pci_wake_handler_work(struct work_struct *work) -+{ -+ struct pci_gpe_dev *gpe_dev = container_of(work, struct pci_gpe_dev, -+ work); -+ -+ pci_check_pme_status(gpe_dev->dev); -+ pm_runtime_resume(&gpe_dev->dev->dev); -+ pci_wakeup_event(gpe_dev->dev); -+ if (gpe_dev->dev->subordinate) -+ pci_pme_wakeup_bus(gpe_dev->dev->subordinate); -+} -+ -+static u32 acpi_pci_wake_handler(void *data) -+{ -+ long gpe_number = (long) data; -+ struct pci_gpe_dev *gpe_dev; -+ -+ list_for_each_entry(gpe_dev, &acpi_pci_gpe_devs, node) { -+ if (gpe_number != gpe_dev->gpe_number) -+ continue; -+ -+ schedule_work(&gpe_dev->work); -+ } -+ -+ return ACPI_INTERRUPT_HANDLED; -+} -+ - static int acpi_pci_unbind(struct acpi_device *device) - { - struct pci_dev *dev; -@@ -43,6 +81,30 @@ static int acpi_pci_unbind(struct acpi_device *device) - if (!dev) - goto out; - -+ if (device->wakeup.flags.valid) { -+ struct pci_gpe_dev *gpe_dev; -+ struct pci_gpe_dev *tmp; -+ int gpe_count = 0; -+ int gpe_number = device->wakeup.gpe_number; -+ acpi_handle gpe_device = device->wakeup.gpe_device; -+ -+ list_for_each_entry_safe(gpe_dev, tmp, &acpi_pci_gpe_devs, node) { -+ if (gpe_dev->dev == dev) { -+ flush_work(&gpe_dev->work); -+ list_del(&gpe_dev->node); -+ kfree(gpe_dev); -+ } else if (gpe_dev->gpe_number == gpe_number && -+ gpe_dev->gpe_device == gpe_device) { -+ gpe_count++; -+ } -+ } -+ -+ if (gpe_count == 0) { -+ acpi_remove_gpe_handler(gpe_device, gpe_number, -+ &acpi_pci_wake_handler); -+ } -+ } -+ - device_set_run_wake(&dev->dev, false); - pci_acpi_remove_pm_notifier(device); - -@@ -71,6 +133,30 @@ static int acpi_pci_bind(struct acpi_device *device) - return 0; - - pci_acpi_add_pm_notifier(device, dev); -+ if (device->wakeup.flags.valid) { -+ struct pci_gpe_dev *gpe_dev; -+ acpi_handle gpe_device = device->wakeup.gpe_device; -+ long gpe_number = device->wakeup.gpe_number; -+ -+ gpe_dev = kmalloc(sizeof(struct pci_gpe_dev), GFP_KERNEL); -+ if (gpe_dev) { -+ gpe_dev->dev = dev; -+ gpe_dev->gpe_device = gpe_device; -+ gpe_dev->gpe_number = gpe_number; -+ INIT_WORK(&gpe_dev->work, acpi_pci_wake_handler_work); -+ -+ acpi_install_gpe_handler(gpe_device, gpe_number, -+ ACPI_GPE_LEVEL_TRIGGERED, -+ &acpi_pci_wake_handler, -+ (void *)gpe_number, -+ true); -+ acpi_gpe_can_wake(device->wakeup.gpe_device, -+ device->wakeup.gpe_number); -+ device->wakeup.flags.run_wake = 1; -+ list_add_tail(&gpe_dev->node, &acpi_pci_gpe_devs); -+ } -+ } -+ - if (device->wakeup.flags.run_wake) - device_set_run_wake(&dev->dev, true); - -diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c -index 721d93b..b0ddef6 100644 ---- a/drivers/acpi/sleep.c -+++ b/drivers/acpi/sleep.c -@@ -643,7 +643,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) - if (acpi_target_sleep_state != ACPI_STATE_S0 || - status != AE_NOT_FOUND) - d_max = d_min; -- } else if (d_max < d_min) { -+ } else if (ACPI_SUCCESS(status) && d_max < d_min) { - /* Warn the user of the broken DSDT */ - printk(KERN_WARNING "ACPI: Wrong value from %s\n", - acpi_method); -diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c -index 035da9e..62a48b2 100644 ---- a/drivers/char/ipmi/ipmi_si_intf.c -+++ b/drivers/char/ipmi/ipmi_si_intf.c -@@ -1970,7 +1970,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info) - info->irq, - ACPI_GPE_LEVEL_TRIGGERED, - &ipmi_acpi_gpe, -- info); -+ info, false); - if (status != AE_OK) { - dev_warn(info->dev, "%s unable to claim ACPI GPE %d," - " running polled\n", DEVICE_NAME, info->irq); -diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h -index 53b7cfd..740eb7e 100644 ---- a/include/acpi/acpixf.h -+++ b/include/acpi/acpixf.h -@@ -258,7 +258,8 @@ acpi_remove_address_space_handler(acpi_handle device, - acpi_status - acpi_install_gpe_handler(acpi_handle gpe_device, - u32 gpe_number, -- u32 type, acpi_event_handler address, void *context); -+ u32 type, acpi_event_handler address, void *context, -+ bool keep_method); - - acpi_status - acpi_remove_gpe_handler(acpi_handle gpe_device, diff --git a/linux-2.6-usb-pci-autosuspend.patch b/linux-2.6-usb-pci-autosuspend.patch deleted file mode 100644 index 610a7654d..000000000 --- a/linux-2.6-usb-pci-autosuspend.patch +++ /dev/null @@ -1,22 +0,0 @@ -commit 15d89120d03116adbbf3226a85fbd2fff0b12576 -Author: Matthew Garrett -Date: Fri Sep 17 11:09:12 2010 -0400 - - Enable USB PCI autosuspend by default - -diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c -index c3f9854..3c020e6 100644 ---- a/drivers/usb/core/hcd-pci.c -+++ b/drivers/usb/core/hcd-pci.c -@@ -248,8 +248,10 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) - goto err4; - set_hs_companion(dev, hcd); - -- if (pci_dev_run_wake(dev)) -+ if (pci_dev_run_wake(dev)) { - pm_runtime_put_noidle(&dev->dev); -+ pm_runtime_allow(&dev->dev); -+ } - return retval; - - err4: From c1f2ddc01e9a53a75257740ee51ac709ca6303b7 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 26 Aug 2011 11:40:49 -0400 Subject: [PATCH 050/487] remove more detritus --- TODO | 1 - kernel.spec | 3 - runtime_pm_fixups.patch | 138 ---------------------------------------- 3 files changed, 142 deletions(-) delete mode 100644 runtime_pm_fixups.patch diff --git a/TODO b/TODO index f444b44d6..78e0355c7 100644 --- a/TODO +++ b/TODO @@ -43,7 +43,6 @@ One half of the remaining exec-shield diff. davej bugged Ingo again on Jun 17 2011 about upstreaming. -* runtime_pm_fixups.patch * linux-2.6-acpi-debug-infinite-loop.patch Responsible: mjg59 diff --git a/kernel.spec b/kernel.spec index 5baddbb72..5832d54ee 100644 --- a/kernel.spec +++ b/kernel.spec @@ -719,9 +719,6 @@ Patch12027: usb-add-quirk-for-logitech-webcams.patch Patch12029: crypto-register-cryptd-first.patch Patch12030: fix-intel-duplicate-backlight.patch -# Runtime power management -Patch12205: runtime_pm_fixups.patch - Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch diff --git a/runtime_pm_fixups.patch b/runtime_pm_fixups.patch deleted file mode 100644 index 1be6149d6..000000000 --- a/runtime_pm_fixups.patch +++ /dev/null @@ -1,138 +0,0 @@ -From 141d0d01ab292d4ea3a6d5e96b4048e10e68c1d3 Mon Sep 17 00:00:00 2001 -From: Kyle McMartin -Date: Mon, 24 Jan 2011 13:01:57 -0500 -Subject: [PATCH] runtime_pm_fixups - ---- - drivers/acpi/bus.c | 3 ++- - drivers/acpi/pci_bind.c | 6 ++++++ - drivers/acpi/power.c | 5 ++++- - drivers/acpi/sleep.c | 2 +- - drivers/acpi/wakeup.c | 2 +- - drivers/pci/pci-acpi.c | 2 +- - include/acpi/acpi_bus.h | 2 +- - 7 files changed, 16 insertions(+), 6 deletions(-) - -diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c -index 7ced61f..e4e0114 100644 ---- a/drivers/acpi/bus.c -+++ b/drivers/acpi/bus.c -@@ -256,7 +256,8 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state) - * a lower-powered state. - */ - if (state < device->power.state) { -- if (device->power.flags.power_resources) { -+ if (device->power.flags.power_resources && -+ !device->wakeup.run_wake_count) { - result = acpi_power_transition(device, state); - if (result) - goto end; -diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c -index 2ef0409..4b0bb68 100644 ---- a/drivers/acpi/pci_bind.c -+++ b/drivers/acpi/pci_bind.c -@@ -32,6 +32,8 @@ - #include - #include - -+#include "internal.h" -+ - #define _COMPONENT ACPI_PCI_COMPONENT - ACPI_MODULE_NAME("pci_bind"); - -@@ -65,6 +67,7 @@ static int acpi_pci_bind(struct acpi_device *device) - acpi_handle handle; - struct pci_bus *bus; - struct pci_dev *dev; -+ int state; - - dev = acpi_get_pci_dev(device->handle); - if (!dev) -@@ -87,6 +90,9 @@ static int acpi_pci_bind(struct acpi_device *device) - device->ops.unbind = acpi_pci_unbind; - } - -+ acpi_power_get_inferred_state(device, &state); -+ acpi_power_transition(device, state); -+ - /* - * Evaluate and parse _PRT, if exists. This code allows parsing of - * _PRT objects within the scope of non-bridge devices. Note that -diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c -index 9ac2a9f..cd6a8df 100644 ---- a/drivers/acpi/power.c -+++ b/drivers/acpi/power.c -@@ -412,7 +412,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) - * State Wake) for the device, if present - * 2. Shutdown down the power resources - */ --int acpi_disable_wakeup_device_power(struct acpi_device *dev) -+int acpi_disable_wakeup_device_power(struct acpi_device *dev, int sleep_state) - { - int i, err = 0; - -@@ -435,6 +435,9 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) - if (err) - goto out; - -+ if (sleep_state == ACPI_STATE_S0) -+ goto out; -+ - /* Close power resource */ - for (i = 0; i < dev->wakeup.resources.count; i++) { - int ret = acpi_power_off(dev->wakeup.resources.handles[i]); -diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c -index d6a8cd1..5d68dc0 100644 ---- a/drivers/acpi/sleep.c -+++ b/drivers/acpi/sleep.c -@@ -697,7 +697,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable) - - error = enable ? - acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) : -- acpi_disable_wakeup_device_power(adev); -+ acpi_disable_wakeup_device_power(adev, acpi_target_sleep_state); - if (!error) - dev_info(dev, "wake-up capability %s by ACPI\n", - enable ? "enabled" : "disabled"); -diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c -index ed65014..a0cabc3 100644 ---- a/drivers/acpi/wakeup.c -+++ b/drivers/acpi/wakeup.c -@@ -73,7 +73,7 @@ void acpi_disable_wakeup_devices(u8 sleep_state) - ACPI_GPE_DISABLE); - - if (device_may_wakeup(&dev->dev)) -- acpi_disable_wakeup_device_power(dev); -+ acpi_disable_wakeup_device_power(dev, sleep_state); - } - } - -diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c -index 6fe0772..819fa7a 100644 ---- a/drivers/pci/pci-acpi.c -+++ b/drivers/pci/pci-acpi.c -@@ -302,7 +302,7 @@ static int acpi_dev_run_wake(struct device *phys_dev, bool enable) - if (!--dev->wakeup.run_wake_count) { - acpi_disable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number); -- acpi_disable_wakeup_device_power(dev); -+ acpi_disable_wakeup_device_power(dev, ACPI_STATE_S0); - } - } else { - error = -EALREADY; -diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h -index 78ca429..92d6e86 100644 ---- a/include/acpi/acpi_bus.h -+++ b/include/acpi/acpi_bus.h -@@ -379,7 +379,7 @@ struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); - #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) - - int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state); --int acpi_disable_wakeup_device_power(struct acpi_device *dev); -+int acpi_disable_wakeup_device_power(struct acpi_device *dev, int state); - - #ifdef CONFIG_PM_OPS - int acpi_pm_device_sleep_state(struct device *, int *); --- -1.7.3.5 - From 43981af01a2610941e575a197a5b359edd5deb3d Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 26 Aug 2011 11:47:56 -0400 Subject: [PATCH 051/487] remove pointless linux-2.6.29-sparc-IOC_TYPECHECK.patch this is the same definition as the one in asm-generic --- TODO | 3 --- kernel.spec | 13 ------------- linux-2.6.29-sparc-IOC_TYPECHECK.patch | 21 --------------------- 3 files changed, 37 deletions(-) delete mode 100644 linux-2.6.29-sparc-IOC_TYPECHECK.patch diff --git a/TODO b/TODO index 78e0355c7..db301e61e 100644 --- a/TODO +++ b/TODO @@ -23,9 +23,6 @@ Rolandware that is used by the debuginfo generation. Possibly upstreamable ? -* linux-2.6.29-sparc-IOC_TYPECHECK.patch - Responsible: Spot/Dennis. - * linux-2.6-v4l-dvb-uvcvideo-update.patch Responsible: Hans. diff --git a/kernel.spec b/kernel.spec index 5832d54ee..73320a32e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1204,19 +1204,6 @@ ApplyOptionalPatch linux-2.6-upstream-reverts.patch -R # Architecture patches # x86(-64) -# -# Intel IOMMU -# - -# -# PowerPC -# - -# -# SPARC64 -# -ApplyPatch linux-2.6.29-sparc-IOC_TYPECHECK.patch - # # ARM # diff --git a/linux-2.6.29-sparc-IOC_TYPECHECK.patch b/linux-2.6.29-sparc-IOC_TYPECHECK.patch deleted file mode 100644 index d73c30adc..000000000 --- a/linux-2.6.29-sparc-IOC_TYPECHECK.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -up vanilla-2.6.29-rc7-git2/arch/sparc/include/asm/ioctl.h.BAD vanilla-2.6.29-rc7-git2/arch/sparc/include/asm/ioctl.h ---- vanilla-2.6.29-rc7-git2/arch/sparc/include/asm/ioctl.h.BAD 2009-03-09 17:01:32.000000000 -0400 -+++ vanilla-2.6.29-rc7-git2/arch/sparc/include/asm/ioctl.h 2009-03-09 16:52:27.000000000 -0400 -@@ -41,6 +41,17 @@ - ((nr) << _IOC_NRSHIFT) | \ - ((size) << _IOC_SIZESHIFT)) - -+#ifdef __KERNEL__ -+/* provoke compile error for invalid uses of size argument */ -+extern unsigned int __invalid_size_argument_for_IOC; -+#define _IOC_TYPECHECK(t) \ -+ ((sizeof(t) == sizeof(t[1]) && \ -+ sizeof(t) < (1 << _IOC_SIZEBITS)) ? \ -+ sizeof(t) : __invalid_size_argument_for_IOC) -+#else -+#define _IOC_TYPECHECK(t) (sizeof(t)) -+#endif -+ - #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) - #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) - #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) From 6c65eeebda31456a1cc72c813525b9faf8e3f352 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 26 Aug 2011 11:49:28 -0400 Subject: [PATCH 052/487] derp, remove the file reference too. --- kernel.spec | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 73320a32e..5f70e380d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -644,8 +644,6 @@ Patch09: linux-2.6-upstream-reverts.patch # Standalone patches -Patch150: linux-2.6.29-sparc-IOC_TYPECHECK.patch - Patch160: linux-2.6-32bit-mmap-exec-randomization.patch Patch161: linux-2.6-i386-nx-emulation.patch From 0b7ee5c023a492f8b4d0e14d813081cd3ef8ba21 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 26 Aug 2011 12:45:58 -0400 Subject: [PATCH 053/487] Drop linux-2.6-32bit-mmap-exec-randomization.patch Outlived it's usefulness (and made of ugly) --- kernel.spec | 8 +- linux-2.6-32bit-mmap-exec-randomization.patch | 226 ------------------ 2 files changed, 5 insertions(+), 229 deletions(-) delete mode 100644 linux-2.6-32bit-mmap-exec-randomization.patch diff --git a/kernel.spec b/kernel.spec index 5f70e380d..fb1d6cbcc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -644,7 +644,6 @@ Patch09: linux-2.6-upstream-reverts.patch # Standalone patches -Patch160: linux-2.6-32bit-mmap-exec-randomization.patch Patch161: linux-2.6-i386-nx-emulation.patch Patch202: linux-2.6-debug-taint-vm.patch @@ -1209,10 +1208,9 @@ ApplyPatch arm-omap-dt-compat.patch ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch # -# Exec shield +# NX Emulation # ApplyPatch linux-2.6-i386-nx-emulation.patch -ApplyPatch linux-2.6-32bit-mmap-exec-randomization.patch # # bugfixes to drivers and filesystems @@ -2036,6 +2034,10 @@ fi # and build. %changelog +* Fri Aug 26 2011 Dave Jones +- Drop linux-2.6-32bit-mmap-exec-randomization.patch + Outlived it's usefulness (and made of ugly) + * Fri Aug 26 2011 Dave Jones - Drop acpi-ec-add-delay-before-write.patch (rhbz 733690) diff --git a/linux-2.6-32bit-mmap-exec-randomization.patch b/linux-2.6-32bit-mmap-exec-randomization.patch deleted file mode 100644 index 6008173b0..000000000 --- a/linux-2.6-32bit-mmap-exec-randomization.patch +++ /dev/null @@ -1,226 +0,0 @@ -Before: -Heap randomisation test (PIE) : 16 bits (guessed) -Main executable randomisation (PIE) : 8 bits (guessed) - -after: -Heap randomisation test (PIE) : 19 bits (guessed) -Main executable randomisation (PIE) : 12 bits (guessed) - - - ---- b/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -397,6 +397,10 @@ - extern unsigned long - arch_get_unmapped_area(struct file *, unsigned long, unsigned long, - unsigned long, unsigned long); -+ -+extern unsigned long -+arch_get_unmapped_exec_area(struct file *, unsigned long, unsigned long, -+ unsigned long, unsigned long); - extern unsigned long - arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, ---- b/mm/mmap.c -+++ b/mm/mmap.c -@@ -28,6 +28,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -1000,7 +1001,8 @@ - /* Obtain the address to map to. we verify (or select) it and ensure - * that it represents a valid section of the address space. - */ -- addr = get_unmapped_area(file, addr, len, pgoff, flags); -+ addr = get_unmapped_area_prot(file, addr, len, pgoff, flags, -+ prot & PROT_EXEC); - if (addr & ~PAGE_MASK) - return addr; - -@@ -1552,8 +1554,8 @@ - } - - unsigned long --get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, -- unsigned long pgoff, unsigned long flags) -+get_unmapped_area_prot(struct file *file, unsigned long addr, unsigned long len, -+ unsigned long pgoff, unsigned long flags, int exec) - { - unsigned long (*get_area)(struct file *, unsigned long, - unsigned long, unsigned long, unsigned long); -@@ -1566,7 +1568,11 @@ - if (len > TASK_SIZE) - return -ENOMEM; - -- get_area = current->mm->get_unmapped_area; -+ if (exec && current->mm->get_unmapped_exec_area) -+ get_area = current->mm->get_unmapped_exec_area; -+ else -+ get_area = current->mm->get_unmapped_area; -+ - if (file && file->f_op && file->f_op->get_unmapped_area) - get_area = file->f_op->get_unmapped_area; - addr = get_area(file, addr, len, pgoff, flags); -@@ -1580,8 +1586,83 @@ - - return arch_rebalance_pgtables(addr, len); - } -+EXPORT_SYMBOL(get_unmapped_area_prot); -+ -+static bool should_randomize(void) -+{ -+ return (current->flags & PF_RANDOMIZE) && -+ !(current->personality & ADDR_NO_RANDOMIZE); -+} -+ -+#define SHLIB_BASE 0x00110000 -+ -+unsigned long -+arch_get_unmapped_exec_area(struct file *filp, unsigned long addr0, -+ unsigned long len0, unsigned long pgoff, unsigned long flags) -+{ -+ unsigned long addr = addr0, len = len0; -+ struct mm_struct *mm = current->mm; -+ struct vm_area_struct *vma; -+ unsigned long tmp; -+ -+ if (len > TASK_SIZE) -+ return -ENOMEM; -+ -+ if (flags & MAP_FIXED) -+ return addr; -+ -+ if (!addr) -+ addr = !should_randomize() ? SHLIB_BASE : -+ randomize_range(SHLIB_BASE, 0x01000000, len); -+ -+ if (addr) { -+ addr = PAGE_ALIGN(addr); -+ vma = find_vma(mm, addr); -+ if (TASK_SIZE - len >= addr && -+ (!vma || addr + len <= vma->vm_start)) -+ return addr; -+ } -+ -+ addr = SHLIB_BASE; -+ for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { -+ /* At this point: (!vma || addr < vma->vm_end). */ -+ if (TASK_SIZE - len < addr) -+ return -ENOMEM; -+ -+ if (!vma || addr + len <= vma->vm_start) { -+ /* -+ * Must not let a PROT_EXEC mapping get into the -+ * brk area: -+ */ -+ if (addr + len > mm->brk) -+ goto failed; -+ -+ /* -+ * Up until the brk area we randomize addresses -+ * as much as possible: -+ */ -+ if (addr >= 0x01000000 && should_randomize()) { -+ tmp = randomize_range(0x01000000, -+ PAGE_ALIGN(max(mm->start_brk, -+ (unsigned long)0x08000000)), len); -+ vma = find_vma(mm, tmp); -+ if (TASK_SIZE - len >= tmp && -+ (!vma || tmp + len <= vma->vm_start)) -+ return tmp; -+ } -+ /* -+ * Ok, randomization didnt work out - return -+ * the result of the linear search: -+ */ -+ return addr; -+ } -+ addr = vma->vm_end; -+ } -+ -+failed: -+ return current->mm->get_unmapped_area(filp, addr0, len0, pgoff, flags); -+} - --EXPORT_SYMBOL(get_unmapped_area); - - /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ - struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) ---- a/arch/x86/mm/mmap.c -+++ b/arch/x86/mm/mmap.c -@@ -124,13 +124,16 @@ static unsigned long mmap_legacy_base(void) - */ - void arch_pick_mmap_layout(struct mm_struct *mm) - { - if (mmap_is_legacy()) { - mm->mmap_base = mmap_legacy_base(); - mm->get_unmapped_area = arch_get_unmapped_area; - mm->unmap_area = arch_unmap_area; - } else { - mm->mmap_base = mmap_base(); - mm->get_unmapped_area = arch_get_unmapped_area_topdown; -+ if (!(current->personality & READ_IMPLIES_EXEC) -+ && mmap_is_ia32()) -+ mm->get_unmapped_exec_area = arch_get_unmapped_exec_area; - mm->unmap_area = arch_unmap_area_topdown; - } - } ---- a/arch/x86/vdso/vdso32-setup.c -+++ b/arch/x86/vdso/vdso32-setup.c -@@ -331,7 +331,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) - if (compat) - addr = VDSO_HIGH_BASE; - else { -- addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0); -+ addr = get_unmapped_area_prot(NULL, 0, PAGE_SIZE, 0, 0, 1); - if (IS_ERR_VALUE(addr)) { - ret = addr; - goto up_fail; ---- a/include/linux/mm.h -+++ b/include/linux/mm.h -@@ -1263,7 +1263,13 @@ extern int install_special_mapping(struct mm_struct *mm, - unsigned long addr, unsigned long len, - unsigned long flags, struct page **pages); - --extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); -+extern unsigned long get_unmapped_area_prot(struct file *, unsigned long, unsigned long, unsigned long, unsigned long, int); -+ -+static inline unsigned long get_unmapped_area(struct file *file, unsigned long addr, -+ unsigned long len, unsigned long pgoff, unsigned long flags) -+{ -+ return get_unmapped_area_prot(file, addr, len, pgoff, flags, 0); -+} - - extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, - unsigned long len, unsigned long prot, ---- a/include/linux/mm_types.h -+++ b/include/linux/mm_types.h -@@ -227,6 +227,9 @@ struct mm_struct { - unsigned long (*get_unmapped_area) (struct file *filp, - unsigned long addr, unsigned long len, - unsigned long pgoff, unsigned long flags); -+ unsigned long (*get_unmapped_exec_area) (struct file *filp, -+ unsigned long addr, unsigned long len, -+ unsigned long pgoff, unsigned long flags); - void (*unmap_area) (struct mm_struct *mm, unsigned long addr); - #endif - unsigned long mmap_base; /* base of mmap area */ ---- a/mm/mremap.c -+++ b/mm/mremap.c -@@ -487,10 +487,10 @@ unsigned long do_mremap(unsigned long addr, - if (vma->vm_flags & VM_MAYSHARE) - map_flags |= MAP_SHARED; - -- new_addr = get_unmapped_area(vma->vm_file, 0, new_len, -+ new_addr = get_unmapped_area_prot(vma->vm_file, 0, new_len, - vma->vm_pgoff + - ((addr - vma->vm_start) >> PAGE_SHIFT), -- map_flags); -+ map_flags, vma->vm_flags & VM_EXEC); - if (new_addr & ~PAGE_MASK) { - ret = new_addr; - goto out; From 42df3844c7e63f51ed6e948e58f60bd3431bfa78 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 26 Aug 2011 14:26:25 -0400 Subject: [PATCH 054/487] Drop linux-2.6-debug-vm-would-have-oomkilled.patch The oom-killer heuristics have improved enough that this should never be necessary (and it probably doesn't dtrt any more) --- TODO | 1 - kernel.spec | 7 +- linux-2.6-debug-vm-would-have-oomkilled.patch | 69 ------------------- 3 files changed, 5 insertions(+), 72 deletions(-) delete mode 100644 linux-2.6-debug-vm-would-have-oomkilled.patch diff --git a/TODO b/TODO index db301e61e..24e57f99a 100644 --- a/TODO +++ b/TODO @@ -4,7 +4,6 @@ Empty * linux-2.6-debug-taint-vm.patch -* linux-2.6-debug-vm-would-have-oomkilled.patch TODO: Push upstream * linux-2.6-acpi-video-dos.patch diff --git a/kernel.spec b/kernel.spec index fb1d6cbcc..83004f082 100644 --- a/kernel.spec +++ b/kernel.spec @@ -647,7 +647,6 @@ Patch09: linux-2.6-upstream-reverts.patch Patch161: linux-2.6-i386-nx-emulation.patch Patch202: linux-2.6-debug-taint-vm.patch -Patch203: linux-2.6-debug-vm-would-have-oomkilled.patch Patch383: linux-2.6-defaults-aspm.patch @@ -1238,7 +1237,6 @@ ApplyPatch linux-2.6-acpi-debug-infinite-loop.patch # Various low-impact patches to aid debugging. ApplyPatch linux-2.6-debug-taint-vm.patch -ApplyPatch linux-2.6-debug-vm-would-have-oomkilled.patch # # PCI @@ -2034,6 +2032,11 @@ fi # and build. %changelog +* Fri Aug 26 2011 Dave Jones +- Drop linux-2.6-debug-vm-would-have-oomkilled.patch + The oom-killer heuristics have improved enough that this should + never be necessary (and it probably doesn't dtrt any more) + * Fri Aug 26 2011 Dave Jones - Drop linux-2.6-32bit-mmap-exec-randomization.patch Outlived it's usefulness (and made of ugly) diff --git a/linux-2.6-debug-vm-would-have-oomkilled.patch b/linux-2.6-debug-vm-would-have-oomkilled.patch deleted file mode 100644 index 8bd05ab06..000000000 --- a/linux-2.6-debug-vm-would-have-oomkilled.patch +++ /dev/null @@ -1,69 +0,0 @@ -From beb764ac03e52eba1a654afb4273fab1f9de3cff Mon Sep 17 00:00:00 2001 -From: Kyle McMartin -Date: Mon, 29 Nov 2010 20:59:14 -0500 -Subject: [PATCH] linux-2.6-debug-vm-would_have_oomkilled - ---- - include/linux/oom.h | 1 + - kernel/sysctl.c | 7 +++++++ - mm/oom_kill.c | 8 ++++++++ - 3 files changed, 16 insertions(+), 0 deletions(-) - -diff --git a/include/linux/oom.h b/include/linux/oom.h -index 5e3aa83..79a27b4 100644 ---- a/include/linux/oom.h -+++ b/include/linux/oom.h -@@ -72,5 +72,6 @@ extern struct task_struct *find_lock_task_mm(struct task_struct *p); - extern int sysctl_oom_dump_tasks; - extern int sysctl_oom_kill_allocating_task; - extern int sysctl_panic_on_oom; -+extern int sysctl_would_have_oomkilled; - #endif /* __KERNEL__*/ - #endif /* _INCLUDE_LINUX_OOM_H */ -diff --git a/kernel/sysctl.c b/kernel/sysctl.c -index 5abfa15..a0fed6d 100644 ---- a/kernel/sysctl.c -+++ b/kernel/sysctl.c -@@ -1000,6 +1000,13 @@ static struct ctl_table vm_table[] = { - .proc_handler = proc_dointvec, - }, - { -+ .procname = "would_have_oomkilled", -+ .data = &sysctl_would_have_oomkilled, -+ .maxlen = sizeof(sysctl_would_have_oomkilled), -+ .mode = 0644, -+ .proc_handler = proc_dointvec, -+ }, -+ { - .procname = "overcommit_ratio", - .data = &sysctl_overcommit_ratio, - .maxlen = sizeof(sysctl_overcommit_ratio), -diff --git a/mm/oom_kill.c b/mm/oom_kill.c -index 7dcca55..281ac39 100644 ---- a/mm/oom_kill.c -+++ b/mm/oom_kill.c -@@ -35,6 +35,7 @@ - int sysctl_panic_on_oom; - int sysctl_oom_kill_allocating_task; - int sysctl_oom_dump_tasks = 1; -+int sysctl_would_have_oomkilled; - static DEFINE_SPINLOCK(zone_scan_lock); - - #ifdef CONFIG_NUMA -@@ -477,6 +478,13 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, - } - - task_lock(p); -+ if (sysctl_would_have_oomkilled) { -+ printk(KERN_ERR "%s: would have killed process %d (%s), but continuing instead...\n", -+ __func__, task_pid_nr(p), p->comm); -+ task_unlock(p); -+ return 0; -+ } -+ - pr_err("%s: Kill process %d (%s) score %d or sacrifice child\n", - message, task_pid_nr(p), p->comm, points); - task_unlock(p); --- -1.7.3.2 - From ad3c6818fc663b6399c1eb5f112347369a897a47 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 26 Aug 2011 16:17:39 -0400 Subject: [PATCH 055/487] Enable CONFIG_DETECT_HUNG_TASK for debug builds & rawhide. Also sync Makefile with master/ --- Makefile | 4 ++++ config-debug | 5 +++++ config-generic | 1 - config-nodebug | 5 +++++ kernel.spec | 3 +++ 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cffc926c2..afa3992c5 100644 --- a/Makefile +++ b/Makefile @@ -92,6 +92,8 @@ debug: @perl -pi -e 's/# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set/CONFIG_CPU_NOTIFIER_ERROR_INJECT=m/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_PER_CPU_MAPS is not set/CONFIG_DEBUG_PER_CPU_MAPS=y/' config-nodebug @perl -pi -e 's/# CONFIG_TEST_LIST_SORT is not set/CONFIG_TEST_LIST_SORT=y/' config-nodebug + @perl -pi -e 's/# CONFIG_DEBUG_ATOMIC_SLEEP is not set/CONFIG_DEBUG_ATOMIC_SLEEP=y/' config-nodebug + @perl -pi -e 's/# CONFIG_DETECT_HUNG_TASK is not set/CONFIG_DETECT_HUNG_TASK=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_SET_MODULE_RONX is not set/CONFIG_DEBUG_SET_MODULE_RONX=y/' config-nodebug @@ -170,6 +172,8 @@ release: #@perl -pi -e 's/CONFIG_KDB_KEYBOARD=y/# CONFIG_KDB_KEYBOARD is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_PER_CPU_MAPS=y/# CONFIG_DEBUG_PER_CPU_MAPS is not set/' config-nodebug @perl -pi -e 's/CONFIG_TEST_LIST_SORT=y/# CONFIG_TEST_LIST_SORT is not set/' config-nodebug + @perl -pi -e 's/CONFIG_DEBUG_ATOMIC_SLEEP=y/# CONFIG_DEBUG_ATOMIC_SLEEP is not set/' config-nodebug + @perl -pi -e 's/CONFIG_DETECT_HUNG_TASK=y/# CONFIG_DETECT_HUNG_TASK is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_SET_MODULE_RONX=y/# CONFIG_DEBUG_SET_MODULE_RONX is not set/' config-nodebug diff --git a/config-debug b/config-debug index 21e52bfd7..c5cd5b338 100644 --- a/config-debug +++ b/config-debug @@ -100,3 +100,8 @@ CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y CONFIG_TEST_LIST_SORT=y CONFIG_DEBUG_SET_MODULE_RONX=y + +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set + diff --git a/config-generic b/config-generic index 38e09006b..e37094a4d 100644 --- a/config-generic +++ b/config-generic @@ -4617,7 +4617,6 @@ CONFIG_LOCKUP_DETECTOR=y # CONFIG_DEBUG_INFO_REDUCED is not set # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set # CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set -# CONFIG_DETECT_HUNG_TASK is not set # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set CONFIG_ATOMIC64_SELFTEST=y diff --git a/config-nodebug b/config-nodebug index a3fbf944d..2ec48fe9a 100644 --- a/config-nodebug +++ b/config-nodebug @@ -100,3 +100,8 @@ CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y CONFIG_TEST_LIST_SORT=y CONFIG_DEBUG_SET_MODULE_RONX=y + +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set + diff --git a/kernel.spec b/kernel.spec index 83004f082..88b80cd3b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2032,6 +2032,9 @@ fi # and build. %changelog +* Fri Aug 26 2011 Dave Jones +- Enable CONFIG_DETECT_HUNG_TASK for debug builds & rawhide. + * Fri Aug 26 2011 Dave Jones - Drop linux-2.6-debug-vm-would-have-oomkilled.patch The oom-killer heuristics have improved enough that this should From d28459969730b7e1d3377047ab0564de8c626c64 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sat, 27 Aug 2011 13:25:52 -0400 Subject: [PATCH 056/487] Fix NX emulation Fix get_gate_vma usage in i386 NX emulation Fix up dependancy on the dropped randomization patch. --- kernel.spec | 4 ++++ linux-2.6-i386-nx-emulation.patch | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 88b80cd3b..f75da1fc5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2032,6 +2032,10 @@ fi # and build. %changelog +* Sat Aug 27 2011 Dave Jones +- Fix get_gate_vma usage in i386 NX emulation +- Fix up dependancy on the dropped randomization patch. + * Fri Aug 26 2011 Dave Jones - Enable CONFIG_DETECT_HUNG_TASK for debug builds & rawhide. diff --git a/linux-2.6-i386-nx-emulation.patch b/linux-2.6-i386-nx-emulation.patch index 856b9b95a..33a343747 100644 --- a/linux-2.6-i386-nx-emulation.patch +++ b/linux-2.6-i386-nx-emulation.patch @@ -249,7 +249,7 @@ + for (vma = current->mm->mmap; vma; vma = vma->vm_next) + if ((vma->vm_flags & VM_EXEC) && (vma->vm_end > limit)) + limit = vma->vm_end; -+ vma = get_gate_vma(current); ++ vma = get_gate_vma(current->mm); + if (vma && (vma->vm_flags & VM_EXEC) && (vma->vm_end > limit)) + limit = vma->vm_end; + spin_unlock(¤t->mm->page_table_lock); @@ -606,7 +606,7 @@ index 57d1868..29c0c35 100644 + /* in the case of NX emulation, shove the brk segment way out of the + way of the exec randomization area, since it can collide with + future allocations if not. */ -+ if ( (mm->get_unmapped_exec_area == arch_get_unmapped_exec_area) && ++ if ( (mm->get_unmapped_exec == arch_get_unmapped_exec_area) && + (mm->brk < 0x08000000) ) { + bump = (TASK_SIZE/6); + } From 4998b415c81d7c99b89c26dfaee806e27abb0fcc Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sat, 27 Aug 2011 13:28:21 -0400 Subject: [PATCH 057/487] make grablogs work again --- scripts/grab-logs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/grab-logs.sh b/scripts/grab-logs.sh index 8a445ec99..5df573571 100755 --- a/scripts/grab-logs.sh +++ b/scripts/grab-logs.sh @@ -1,6 +1,6 @@ #!/bin/sh -VER=$(make verrel) +VER=$(fedpkg verrel) ver=$(echo $VER | sed -e 's/-/ /g' | awk '{print $2}') rev=$(echo $VER | sed -e 's/-/ /g' | awk '{print $3}') From 4746078140448821f9a4646e085bfa048a99866a Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sat, 27 Aug 2011 13:58:46 -0400 Subject: [PATCH 058/487] Bring back the 32bit mmap randomization patch for now. NX emulation is still too dependant upon it. --- kernel.spec | 5 +- linux-2.6-32bit-mmap-exec-randomization.patch | 226 ++++++++++++++++++ linux-2.6-i386-nx-emulation.patch | 2 +- 3 files changed, 231 insertions(+), 2 deletions(-) create mode 100644 linux-2.6-32bit-mmap-exec-randomization.patch diff --git a/kernel.spec b/kernel.spec index f75da1fc5..dc611da07 100644 --- a/kernel.spec +++ b/kernel.spec @@ -644,6 +644,7 @@ Patch09: linux-2.6-upstream-reverts.patch # Standalone patches +Patch160: linux-2.6-32bit-mmap-exec-randomization.patch Patch161: linux-2.6-i386-nx-emulation.patch Patch202: linux-2.6-debug-taint-vm.patch @@ -1209,6 +1210,7 @@ ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch # # NX Emulation # +ApplyPatch linux-2.6-32bit-mmap-exec-randomization.patch ApplyPatch linux-2.6-i386-nx-emulation.patch # @@ -2034,7 +2036,8 @@ fi %changelog * Sat Aug 27 2011 Dave Jones - Fix get_gate_vma usage in i386 NX emulation -- Fix up dependancy on the dropped randomization patch. +- Bring back the 32bit mmap randomization patch for now. + NX emulation is still too dependant upon it. * Fri Aug 26 2011 Dave Jones - Enable CONFIG_DETECT_HUNG_TASK for debug builds & rawhide. diff --git a/linux-2.6-32bit-mmap-exec-randomization.patch b/linux-2.6-32bit-mmap-exec-randomization.patch new file mode 100644 index 000000000..6008173b0 --- /dev/null +++ b/linux-2.6-32bit-mmap-exec-randomization.patch @@ -0,0 +1,226 @@ +Before: +Heap randomisation test (PIE) : 16 bits (guessed) +Main executable randomisation (PIE) : 8 bits (guessed) + +after: +Heap randomisation test (PIE) : 19 bits (guessed) +Main executable randomisation (PIE) : 12 bits (guessed) + + + +--- b/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -397,6 +397,10 @@ + extern unsigned long + arch_get_unmapped_area(struct file *, unsigned long, unsigned long, + unsigned long, unsigned long); ++ ++extern unsigned long ++arch_get_unmapped_exec_area(struct file *, unsigned long, unsigned long, ++ unsigned long, unsigned long); + extern unsigned long + arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, +--- b/mm/mmap.c ++++ b/mm/mmap.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -1000,7 +1001,8 @@ + /* Obtain the address to map to. we verify (or select) it and ensure + * that it represents a valid section of the address space. + */ +- addr = get_unmapped_area(file, addr, len, pgoff, flags); ++ addr = get_unmapped_area_prot(file, addr, len, pgoff, flags, ++ prot & PROT_EXEC); + if (addr & ~PAGE_MASK) + return addr; + +@@ -1552,8 +1554,8 @@ + } + + unsigned long +-get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, +- unsigned long pgoff, unsigned long flags) ++get_unmapped_area_prot(struct file *file, unsigned long addr, unsigned long len, ++ unsigned long pgoff, unsigned long flags, int exec) + { + unsigned long (*get_area)(struct file *, unsigned long, + unsigned long, unsigned long, unsigned long); +@@ -1566,7 +1568,11 @@ + if (len > TASK_SIZE) + return -ENOMEM; + +- get_area = current->mm->get_unmapped_area; ++ if (exec && current->mm->get_unmapped_exec_area) ++ get_area = current->mm->get_unmapped_exec_area; ++ else ++ get_area = current->mm->get_unmapped_area; ++ + if (file && file->f_op && file->f_op->get_unmapped_area) + get_area = file->f_op->get_unmapped_area; + addr = get_area(file, addr, len, pgoff, flags); +@@ -1580,8 +1586,83 @@ + + return arch_rebalance_pgtables(addr, len); + } ++EXPORT_SYMBOL(get_unmapped_area_prot); ++ ++static bool should_randomize(void) ++{ ++ return (current->flags & PF_RANDOMIZE) && ++ !(current->personality & ADDR_NO_RANDOMIZE); ++} ++ ++#define SHLIB_BASE 0x00110000 ++ ++unsigned long ++arch_get_unmapped_exec_area(struct file *filp, unsigned long addr0, ++ unsigned long len0, unsigned long pgoff, unsigned long flags) ++{ ++ unsigned long addr = addr0, len = len0; ++ struct mm_struct *mm = current->mm; ++ struct vm_area_struct *vma; ++ unsigned long tmp; ++ ++ if (len > TASK_SIZE) ++ return -ENOMEM; ++ ++ if (flags & MAP_FIXED) ++ return addr; ++ ++ if (!addr) ++ addr = !should_randomize() ? SHLIB_BASE : ++ randomize_range(SHLIB_BASE, 0x01000000, len); ++ ++ if (addr) { ++ addr = PAGE_ALIGN(addr); ++ vma = find_vma(mm, addr); ++ if (TASK_SIZE - len >= addr && ++ (!vma || addr + len <= vma->vm_start)) ++ return addr; ++ } ++ ++ addr = SHLIB_BASE; ++ for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { ++ /* At this point: (!vma || addr < vma->vm_end). */ ++ if (TASK_SIZE - len < addr) ++ return -ENOMEM; ++ ++ if (!vma || addr + len <= vma->vm_start) { ++ /* ++ * Must not let a PROT_EXEC mapping get into the ++ * brk area: ++ */ ++ if (addr + len > mm->brk) ++ goto failed; ++ ++ /* ++ * Up until the brk area we randomize addresses ++ * as much as possible: ++ */ ++ if (addr >= 0x01000000 && should_randomize()) { ++ tmp = randomize_range(0x01000000, ++ PAGE_ALIGN(max(mm->start_brk, ++ (unsigned long)0x08000000)), len); ++ vma = find_vma(mm, tmp); ++ if (TASK_SIZE - len >= tmp && ++ (!vma || tmp + len <= vma->vm_start)) ++ return tmp; ++ } ++ /* ++ * Ok, randomization didnt work out - return ++ * the result of the linear search: ++ */ ++ return addr; ++ } ++ addr = vma->vm_end; ++ } ++ ++failed: ++ return current->mm->get_unmapped_area(filp, addr0, len0, pgoff, flags); ++} + +-EXPORT_SYMBOL(get_unmapped_area); + + /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ + struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) +--- a/arch/x86/mm/mmap.c ++++ b/arch/x86/mm/mmap.c +@@ -124,13 +124,16 @@ static unsigned long mmap_legacy_base(void) + */ + void arch_pick_mmap_layout(struct mm_struct *mm) + { + if (mmap_is_legacy()) { + mm->mmap_base = mmap_legacy_base(); + mm->get_unmapped_area = arch_get_unmapped_area; + mm->unmap_area = arch_unmap_area; + } else { + mm->mmap_base = mmap_base(); + mm->get_unmapped_area = arch_get_unmapped_area_topdown; ++ if (!(current->personality & READ_IMPLIES_EXEC) ++ && mmap_is_ia32()) ++ mm->get_unmapped_exec_area = arch_get_unmapped_exec_area; + mm->unmap_area = arch_unmap_area_topdown; + } + } +--- a/arch/x86/vdso/vdso32-setup.c ++++ b/arch/x86/vdso/vdso32-setup.c +@@ -331,7 +331,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) + if (compat) + addr = VDSO_HIGH_BASE; + else { +- addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0); ++ addr = get_unmapped_area_prot(NULL, 0, PAGE_SIZE, 0, 0, 1); + if (IS_ERR_VALUE(addr)) { + ret = addr; + goto up_fail; +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -1263,7 +1263,13 @@ extern int install_special_mapping(struct mm_struct *mm, + unsigned long addr, unsigned long len, + unsigned long flags, struct page **pages); + +-extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); ++extern unsigned long get_unmapped_area_prot(struct file *, unsigned long, unsigned long, unsigned long, unsigned long, int); ++ ++static inline unsigned long get_unmapped_area(struct file *file, unsigned long addr, ++ unsigned long len, unsigned long pgoff, unsigned long flags) ++{ ++ return get_unmapped_area_prot(file, addr, len, pgoff, flags, 0); ++} + + extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, + unsigned long len, unsigned long prot, +--- a/include/linux/mm_types.h ++++ b/include/linux/mm_types.h +@@ -227,6 +227,9 @@ struct mm_struct { + unsigned long (*get_unmapped_area) (struct file *filp, + unsigned long addr, unsigned long len, + unsigned long pgoff, unsigned long flags); ++ unsigned long (*get_unmapped_exec_area) (struct file *filp, ++ unsigned long addr, unsigned long len, ++ unsigned long pgoff, unsigned long flags); + void (*unmap_area) (struct mm_struct *mm, unsigned long addr); + #endif + unsigned long mmap_base; /* base of mmap area */ +--- a/mm/mremap.c ++++ b/mm/mremap.c +@@ -487,10 +487,10 @@ unsigned long do_mremap(unsigned long addr, + if (vma->vm_flags & VM_MAYSHARE) + map_flags |= MAP_SHARED; + +- new_addr = get_unmapped_area(vma->vm_file, 0, new_len, ++ new_addr = get_unmapped_area_prot(vma->vm_file, 0, new_len, + vma->vm_pgoff + + ((addr - vma->vm_start) >> PAGE_SHIFT), +- map_flags); ++ map_flags, vma->vm_flags & VM_EXEC); + if (new_addr & ~PAGE_MASK) { + ret = new_addr; + goto out; diff --git a/linux-2.6-i386-nx-emulation.patch b/linux-2.6-i386-nx-emulation.patch index 33a343747..fb58c612e 100644 --- a/linux-2.6-i386-nx-emulation.patch +++ b/linux-2.6-i386-nx-emulation.patch @@ -606,7 +606,7 @@ index 57d1868..29c0c35 100644 + /* in the case of NX emulation, shove the brk segment way out of the + way of the exec randomization area, since it can collide with + future allocations if not. */ -+ if ( (mm->get_unmapped_exec == arch_get_unmapped_exec_area) && ++ if ( (mm->get_unmapped_exec_area == arch_get_unmapped_exec_area) && + (mm->brk < 0x08000000) ) { + bump = (TASK_SIZE/6); + } From 1423389e5030378277758f9d7bc5eaa04953d7dc Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sat, 27 Aug 2011 17:56:57 -0400 Subject: [PATCH 059/487] fix up some config warnings --- config-arm-omap-generic | 1 - config-generic | 6 +----- config-powerpc-generic | 8 +++++++- config-x86-32-generic | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/config-arm-omap-generic b/config-arm-omap-generic index 29f6ade6a..19ea52191 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -705,7 +705,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_ARMCLCD is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set -# CONFIG_FB_MB862XX is not set # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set # CONFIG_FB_OMAP_LCD_VGA is not set CONFIG_OMAP2_VRAM=y diff --git a/config-generic b/config-generic index e37094a4d..91ddd6868 100644 --- a/config-generic +++ b/config-generic @@ -2892,10 +2892,7 @@ CONFIG_FB_VIA=m CONFIG_FB_VIA_X_COMPATIBILITY=y # CONFIG_FB_VIA_DIRECT_PROCFS is not set CONFIG_FB_METRONOME=m -CONFIG_FB_MB862XX=m -CONFIG_FB_MB862XX_PCI_GDC=y -CONFIG_FB_MB862XX_LIME=y -CONFIG_FB_MB862XX_I2C=y +# CONFIG_FB_MB862XX is not set # CONFIG_FB_PRE_INIT_FB is not set # CONFIG_FB_TMIO is not set # CONFIG_FB_BROADSHEET is not set @@ -4617,7 +4614,6 @@ CONFIG_LOCKUP_DETECTOR=y # CONFIG_DEBUG_INFO_REDUCED is not set # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set # CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set -# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set CONFIG_ATOMIC64_SELFTEST=y CONFIG_MEMORY_FAILURE=y diff --git a/config-powerpc-generic b/config-powerpc-generic index 5e1ddf74d..ee9ab243d 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -47,6 +47,12 @@ CONFIG_FB_ATY_BACKLIGHT=y CONFIG_FB_RADEON_BACKLIGHT=y CONFIG_FB_RIVA_BACKLIGHT=y CONFIG_FB_NVIDIA_BACKLIGHT=y +# FIXME: Do we care about this hardware ? +CONFIG_FB_MB862XX=m +CONFIG_FB_MB862XX_PCI_GDC=y +CONFIG_FB_MB862XX_LIME=y +CONFIG_FB_MB862XX_I2C=y + CONFIG_SND_POWERMAC=m CONFIG_SND_POWERMAC_AUTO_DRC=y @@ -192,7 +198,7 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set -CONFIG_MTD_OF_PARTS=m +CONFIG_MTD_OF_PARTS=y # CONFIG_MTD_NAND_FSL_ELBC is not set CONFIG_THERMAL=y diff --git a/config-x86-32-generic b/config-x86-32-generic index 8b66c9291..f42d60da6 100644 --- a/config-x86-32-generic +++ b/config-x86-32-generic @@ -183,7 +183,7 @@ CONFIG_XO1_RFKILL=m CONFIG_X86_32_IRIS=m -CONFIG_MTD_OF_PARTS=m +CONFIG_MTD_OF_PARTS=y CONFIG_MTD_PHYSMAP_OF=m CONFIG_PROC_DEVICETREE=y CONFIG_SERIAL_OF_PLATFORM=m From c73810ba63eab5b78733f1db8944dccd1dabc712 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 29 Aug 2011 08:31:59 -0400 Subject: [PATCH 060/487] Linux 3.1-rc4 --- fix-intel-duplicate-backlight.patch | 44 ----------------------------- kernel.spec | 11 ++++---- sources | 3 +- 3 files changed, 7 insertions(+), 51 deletions(-) delete mode 100644 fix-intel-duplicate-backlight.patch diff --git a/fix-intel-duplicate-backlight.patch b/fix-intel-duplicate-backlight.patch deleted file mode 100644 index c33e92ec2..000000000 --- a/fix-intel-duplicate-backlight.patch +++ /dev/null @@ -1,44 +0,0 @@ -From: Kamal Mostafa -To: Linux Kernel , - intel-gfx@lists.freedesktop.org -Cc: Matthew Garrett , - Keith Packard , - Kamal Mostafa -Subject: [PATCH] i915: do not setup intel_backlight twice -Date: Mon, 22 Aug 2011 12:39:10 -0700 -Message-Id: <1314041950-12433-1-git-send-email-kamal@canonical.com> -X-Mailer: git-send-email 1.7.4.1 -In-Reply-To: <20110817141010.GA21479@redhat.com> -References: <20110817141010.GA21479@redhat.com> -Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org - -The commit "Not all systems expose a firmware or platform mechanism for -changing the backlight intensity on i915, so add native driver support" -adds calls to intel_panel_setup_backlight() from intel_{lvds,dp}_init -so do not call it again from intel_setup_outputs(). - -BugLink: http://bugs.launchpad.net/bugs/831542 - -Signed-off-by: Kamal Mostafa ---- - drivers/gpu/drm/i915/intel_display.c | 2 -- - 1 files changed, 0 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c -index ee1d701..5a1ae9f 100644 ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -7238,8 +7238,6 @@ static void intel_setup_outputs(struct drm_device *dev) - intel_encoder_clones(dev, encoder->clone_mask); - } - -- intel_panel_setup_backlight(dev); -- - /* disable all the possible outputs/crtcs before entering KMS mode */ - drm_helper_disable_unused_functions(dev); - } --- -1.7.4.1 diff --git a/kernel.spec b/kernel.spec index dc611da07..8558f50da 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 1 +%global baserelease 0 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -82,9 +82,9 @@ Summary: The Linux kernel # The next upstream release sublevel (base_sublevel+1) %define upstream_sublevel %(echo $((%{base_sublevel} + 1))) # The rc snapshot level -%define rcrev 3 +%define rcrev 4 # The git snapshot level -%define gitrev 5 +%define gitrev 0 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -714,7 +714,6 @@ Patch12025: rcu-avoid-just-onlined-cpu-resched.patch Patch12026: block-stray-block-put-after-teardown.patch Patch12027: usb-add-quirk-for-logitech-webcams.patch Patch12029: crypto-register-cryptd-first.patch -Patch12030: fix-intel-duplicate-backlight.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch @@ -1324,7 +1323,6 @@ ApplyPatch block-stray-block-put-after-teardown.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch ApplyPatch crypto-register-cryptd-first.patch -ApplyPatch fix-intel-duplicate-backlight.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -2034,6 +2032,9 @@ fi # and build. %changelog +* Mon Aug 29 2011 Josh Boyer +- Linux 3.1-rc4 + * Sat Aug 27 2011 Dave Jones - Fix get_gate_vma usage in i386 NX emulation - Bring back the 32bit mmap randomization patch for now. diff --git a/sources b/sources index 9045d10b2..5958093ad 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 -b9a15f79846c4d01fa3019a3112a8d04 patch-3.1-rc3.bz2 -d616dde9b999388576b12d9ad7edeca1 patch-3.1-rc3-git5.bz2 +0b0f625fd2d97699e5dbf71554373e6b patch-3.1-rc4.bz2 From 650d9cd05e606beacafd4466a654a09357b11840 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 30 Aug 2011 09:00:08 -0400 Subject: [PATCH 061/487] Add patch to fix rhbz 606017 --- ...ensure-thermal-limits-match-cpu-freq.patch | 128 ++++++++++++++++++ kernel.spec | 7 +- 2 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 acpi-ensure-thermal-limits-match-cpu-freq.patch diff --git a/acpi-ensure-thermal-limits-match-cpu-freq.patch b/acpi-ensure-thermal-limits-match-cpu-freq.patch new file mode 100644 index 000000000..3945af197 --- /dev/null +++ b/acpi-ensure-thermal-limits-match-cpu-freq.patch @@ -0,0 +1,128 @@ +The ACPI thermal management code supports slowing down a CPU when it's +overheating. Right now that's done by choosing to run it at 100%, 75%, 50% +or 25% of full speed. However, most CPUs do not allow an arbitrary +frequency to be set and so will run at the first frequency below that value. +This doesn't match the intent of the specification, which is to drop the +frequency state by state until the temperature stabalises. Fix this up +so it uses actual frequencies rather than percentages. + +Reported by: Gene Snider +Signed-off-by: Matthew Garrett +--- + drivers/acpi/processor_thermal.c | 45 +++++++++++++++++++++---------------- + 1 files changed, 25 insertions(+), 20 deletions(-) + +diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c +index 870550d..1c4eb60 100644 +--- a/drivers/acpi/processor_thermal.c ++++ b/drivers/acpi/processor_thermal.c +@@ -52,10 +52,8 @@ ACPI_MODULE_NAME("processor_thermal"); + * _any_ cpufreq driver and not only the acpi-cpufreq driver. + */ + +-#define CPUFREQ_THERMAL_MIN_STEP 0 +-#define CPUFREQ_THERMAL_MAX_STEP 3 + +-static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg); ++static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_limit_state); + static unsigned int acpi_thermal_cpufreq_is_init = 0; + + static int cpu_has_cpufreq(unsigned int cpu) +@@ -70,19 +68,19 @@ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, + unsigned long event, void *data) + { + struct cpufreq_policy *policy = data; +- unsigned long max_freq = 0; ++ int state = per_cpu(cpufreq_thermal_limit_state, policy->cpu); ++ struct cpufreq_frequency_table *table; + + if (event != CPUFREQ_ADJUST) +- goto out; ++ return 0; ++ ++ table = cpufreq_frequency_get_table(policy->cpu); + +- max_freq = ( +- policy->cpuinfo.max_freq * +- (100 - per_cpu(cpufreq_thermal_reduction_pctg, policy->cpu) * 20) +- ) / 100; ++ if (!table) ++ return 0; + +- cpufreq_verify_within_limits(policy, 0, max_freq); ++ cpufreq_verify_within_limits(policy, 0, table[state].frequency); + +- out: + return 0; + } + +@@ -92,10 +90,21 @@ static struct notifier_block acpi_thermal_cpufreq_notifier_block = { + + static int cpufreq_get_max_state(unsigned int cpu) + { ++ int count = 0; ++ struct cpufreq_frequency_table *table; ++ + if (!cpu_has_cpufreq(cpu)) + return 0; + +- return CPUFREQ_THERMAL_MAX_STEP; ++ table = cpufreq_frequency_get_table(cpu); ++ ++ if (!table) ++ return 0; ++ ++ while (table[count].frequency != CPUFREQ_TABLE_END) ++ count++; ++ ++ return count; + } + + static int cpufreq_get_cur_state(unsigned int cpu) +@@ -103,7 +112,7 @@ static int cpufreq_get_cur_state(unsigned int cpu) + if (!cpu_has_cpufreq(cpu)) + return 0; + +- return per_cpu(cpufreq_thermal_reduction_pctg, cpu); ++ return per_cpu(cpufreq_thermal_limit_state, cpu); + } + + static int cpufreq_set_cur_state(unsigned int cpu, int state) +@@ -111,7 +120,7 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state) + if (!cpu_has_cpufreq(cpu)) + return 0; + +- per_cpu(cpufreq_thermal_reduction_pctg, cpu) = state; ++ per_cpu(cpufreq_thermal_limit_state, cpu) = state; + cpufreq_update_policy(cpu); + return 0; + } +@@ -122,7 +131,7 @@ void acpi_thermal_cpufreq_init(void) + + for (i = 0; i < nr_cpu_ids; i++) + if (cpu_present(i)) +- per_cpu(cpufreq_thermal_reduction_pctg, i) = 0; ++ per_cpu(cpufreq_thermal_limit_state, i) = 0; + + i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block, + CPUFREQ_POLICY_NOTIFIER); +@@ -170,15 +179,11 @@ int acpi_processor_get_limit_info(struct acpi_processor *pr) + return 0; + } + +-/* thermal coolign device callbacks */ ++/* thermal cooling device callbacks */ + static int acpi_processor_max_state(struct acpi_processor *pr) + { + int max_state = 0; + +- /* +- * There exists four states according to +- * cpufreq_thermal_reduction_ptg. 0, 1, 2, 3 +- */ + max_state += cpufreq_get_max_state(pr->id); + if (pr->flags.throttling) + max_state += (pr->throttling.state_count -1); +-- +1.7.6.1 + diff --git a/kernel.spec b/kernel.spec index 8558f50da..492d39fa9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 0 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -654,6 +654,7 @@ Patch383: linux-2.6-defaults-aspm.patch Patch390: linux-2.6-defaults-acpi-video.patch Patch391: linux-2.6-acpi-video-dos.patch Patch394: linux-2.6-acpi-debug-infinite-loop.patch +Patch395: acpi-ensure-thermal-limits-match-cpu-freq.patch Patch450: linux-2.6-input-kill-stupid-messages.patch Patch452: linux-2.6.30-no-pcspkr-modalias.patch @@ -1235,6 +1236,7 @@ ApplyPatch linux-2.6-i386-nx-emulation.patch ApplyPatch linux-2.6-defaults-acpi-video.patch ApplyPatch linux-2.6-acpi-video-dos.patch ApplyPatch linux-2.6-acpi-debug-infinite-loop.patch +ApplyPatch acpi-ensure-thermal-limits-match-cpu-freq.patch # Various low-impact patches to aid debugging. ApplyPatch linux-2.6-debug-taint-vm.patch @@ -2032,6 +2034,9 @@ fi # and build. %changelog +* Tue Aug 30 2011 Josh Boyer +- Add patch to fix rhbz 606017 + * Mon Aug 29 2011 Josh Boyer - Linux 3.1-rc4 From 3e5e72ab2b08feddc3a82e3820c2aaaf30c3d580 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 30 Aug 2011 10:22:56 -0400 Subject: [PATCH 062/487] Fixup acpi patch to select CPU_FREQ_TABLE so we don't get an undefined link error --- ...ensure-thermal-limits-match-cpu-freq.patch | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/acpi-ensure-thermal-limits-match-cpu-freq.patch b/acpi-ensure-thermal-limits-match-cpu-freq.patch index 3945af197..9d97b6024 100644 --- a/acpi-ensure-thermal-limits-match-cpu-freq.patch +++ b/acpi-ensure-thermal-limits-match-cpu-freq.patch @@ -1,3 +1,8 @@ +From 9a056a5843ff83db987d6e18625f4a2ee64b5450 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Tue, 30 Aug 2011 10:07:24 -0400 +Subject: [PATCH] ACPI: Ensure thermal limits match CPU frequencies + The ACPI thermal management code supports slowing down a CPU when it's overheating. Right now that's done by choosing to run it at 100%, 75%, 50% or 25% of full speed. However, most CPUs do not allow an arbitrary @@ -9,9 +14,22 @@ so it uses actual frequencies rather than percentages. Reported by: Gene Snider Signed-off-by: Matthew Garrett --- + drivers/acpi/Kconfig | 1 + drivers/acpi/processor_thermal.c | 45 +++++++++++++++++++++---------------- - 1 files changed, 25 insertions(+), 20 deletions(-) + 2 files changed, 26 insertions(+), 20 deletions(-) +diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig +index de0e3df..7d1bdb5 100644 +--- a/drivers/acpi/Kconfig ++++ b/drivers/acpi/Kconfig +@@ -185,6 +185,7 @@ config ACPI_PROCESSOR + tristate "Processor" + select THERMAL + select CPU_IDLE ++ select CPU_FREQ_TABLE + default y + help + This driver installs ACPI as the idle handler for Linux and uses diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 870550d..1c4eb60 100644 --- a/drivers/acpi/processor_thermal.c @@ -124,5 +142,5 @@ index 870550d..1c4eb60 100644 if (pr->flags.throttling) max_state += (pr->throttling.state_count -1); -- -1.7.6.1 +1.7.6 From 787b0f02c4187f3eb4150a856e9e4318a824381c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 30 Aug 2011 11:44:45 -0400 Subject: [PATCH 063/487] Revert "x86: Serialize EFI time accesses on rtc_lock" (rhbz 732755) --- kernel.spec | 5 +++ revert-efi-rtclock.patch | 76 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 revert-efi-rtclock.patch diff --git a/kernel.spec b/kernel.spec index 492d39fa9..176fb0fe1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -718,6 +718,7 @@ Patch12029: crypto-register-cryptd-first.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch +Patch13002: revert-efi-rtclock.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch Patch13004: iwlagn-revert-max-aggregate-size.patch @@ -1329,6 +1330,7 @@ ApplyPatch crypto-register-cryptd-first.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch +ApplyPatch revert-efi-rtclock.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch ApplyPatch iwlagn-revert-max-aggregate-size.patch @@ -2034,6 +2036,9 @@ fi # and build. %changelog +* Tue Aug 30 2011 Dave Jones +- Revert "x86: Serialize EFI time accesses on rtc_lock" (rhbz 732755) + * Tue Aug 30 2011 Josh Boyer - Add patch to fix rhbz 606017 diff --git a/revert-efi-rtclock.patch b/revert-efi-rtclock.patch new file mode 100644 index 000000000..87ecaa11a --- /dev/null +++ b/revert-efi-rtclock.patch @@ -0,0 +1,76 @@ +diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c +index 3ae4128..e17c6d2 100644 +--- a/arch/x86/platform/efi/efi.c ++++ b/arch/x86/platform/efi/efi.c +@@ -89,50 +89,26 @@ early_param("add_efi_memmap", setup_add_efi_memmap); + + static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) + { +- unsigned long flags; +- efi_status_t status; +- +- spin_lock_irqsave(&rtc_lock, flags); +- status = efi_call_virt2(get_time, tm, tc); +- spin_unlock_irqrestore(&rtc_lock, flags); +- return status; ++ return efi_call_virt2(get_time, tm, tc); + } + + static efi_status_t virt_efi_set_time(efi_time_t *tm) + { +- unsigned long flags; +- efi_status_t status; +- +- spin_lock_irqsave(&rtc_lock, flags); +- status = efi_call_virt1(set_time, tm); +- spin_unlock_irqrestore(&rtc_lock, flags); +- return status; ++ return efi_call_virt1(set_time, tm); + } + + static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled, + efi_bool_t *pending, + efi_time_t *tm) + { +- unsigned long flags; +- efi_status_t status; +- +- spin_lock_irqsave(&rtc_lock, flags); +- status = efi_call_virt3(get_wakeup_time, +- enabled, pending, tm); +- spin_unlock_irqrestore(&rtc_lock, flags); +- return status; ++ return efi_call_virt3(get_wakeup_time, ++ enabled, pending, tm); + } + + static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) + { +- unsigned long flags; +- efi_status_t status; +- +- spin_lock_irqsave(&rtc_lock, flags); +- status = efi_call_virt2(set_wakeup_time, +- enabled, tm); +- spin_unlock_irqrestore(&rtc_lock, flags); +- return status; ++ return efi_call_virt2(set_wakeup_time, ++ enabled, tm); + } + + static efi_status_t virt_efi_get_variable(efi_char16_t *name, +@@ -232,14 +208,11 @@ static efi_status_t __init phys_efi_set_virtual_address_map( + static efi_status_t __init phys_efi_get_time(efi_time_t *tm, + efi_time_cap_t *tc) + { +- unsigned long flags; + efi_status_t status; + +- spin_lock_irqsave(&rtc_lock, flags); + efi_call_phys_prelog(); + status = efi_call_phys2(efi_phys.get_time, tm, tc); + efi_call_phys_epilog(); +- spin_unlock_irqrestore(&rtc_lock, flags); + return status; + } + From 9cabd45dbb0558aa5a72d121da616ef6e0b20328 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 1 Sep 2011 14:27:30 -0400 Subject: [PATCH 064/487] utrace: s390: fix the compile problem with traps.c (rhbz 735118) --- kernel.spec | 3 +++ utrace.patch | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/kernel.spec b/kernel.spec index 176fb0fe1..7ee812f5f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2036,6 +2036,9 @@ fi # and build. %changelog +* Thu Sep 01 2011 Dave Jones +- utrace: s390: fix the compile problem with traps.c (rhbz 735118) + * Tue Aug 30 2011 Dave Jones - Revert "x86: Serialize EFI time accesses on rtc_lock" (rhbz 732755) diff --git a/utrace.patch b/utrace.patch index c04ac77c8..fbf28ff62 100644 --- a/utrace.patch +++ b/utrace.patch @@ -7335,3 +7335,74 @@ index 90ca578..a1bac95 100644 1.5.5.1 +From davej Thu Sep 1 14:14:49 2011 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk with IMAP (fetchmail-6.3.20) + for (single-drop); Thu, 01 Sep 2011 14:14:49 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail04.corp.redhat.com with LMTP; Thu, 1 Sep 2011 14:13:55 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1BA199C63F; + Thu, 1 Sep 2011 14:13:55 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 0vQx9zlcQB36; Thu, 1 Sep 2011 14:13:55 -0400 (EDT) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 009959C63D; + Thu, 1 Sep 2011 14:13:55 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p81IDrDX015389; + Thu, 1 Sep 2011 14:13:54 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Thu, 1 Sep 2011 20:10:54 +0200 (CEST) +Date: Thu, 1 Sep 2011 20:10:53 +0200 +From: Oleg Nesterov +To: Dave Jones +Cc: kernel@lists.fedoraproject.org, cebbert@redhat.com +Subject: [PATCH F-16] bz735118: utrace: s390: fix the compile problem with + traps.c +Message-ID: <20110901181053.GA24990@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +Status: RO +Content-Length: 777 +Lines: 27 + +https://bugzilla.redhat.com/show_bug.cgi?id=735118 + +d99e60e5 "tracehooks: reintroduce tracehook_consider_fatal_signal()" +breaks the compilation of arch/s390/kernel/traps.c. Restore the +necessary include removed by upstream 73b7d40f commit. + +Signed-off-by: Oleg Nesterov +--- + arch/s390/kernel/traps.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c +index 1018ab6..50e975d 100644 +--- a/arch/s390/kernel/traps.c ++++ b/arch/s390/kernel/traps.c +@@ -18,7 +18,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +-- +1.5.5.1 + + From 29656445beaba8ef78df7926114ab48e55f31606 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 2 Sep 2011 11:52:43 -0400 Subject: [PATCH 065/487] Apply patch to fix lockdep reports from ext4 (rhbz 732572) --- ext4-lockdep.patch | 12 ++++++++++++ kernel.spec | 6 ++++++ 2 files changed, 18 insertions(+) create mode 100644 ext4-lockdep.patch diff --git a/ext4-lockdep.patch b/ext4-lockdep.patch new file mode 100644 index 000000000..357e22cff --- /dev/null +++ b/ext4-lockdep.patch @@ -0,0 +1,12 @@ +--- linux-3.0.noarch/fs/ext4/inode.c~ 2011-09-02 11:50:56.206445843 -0400 ++++ linux-3.0.noarch/fs/ext4/inode.c 2011-09-02 11:51:31.224323827 -0400 +@@ -121,9 +121,6 @@ void ext4_evict_inode(struct inode *inod + + trace_ext4_evict_inode(inode); + +- mutex_lock(&inode->i_mutex); +- ext4_flush_completed_IO(inode); +- mutex_unlock(&inode->i_mutex); + ext4_ioend_wait(inode); + + if (inode->i_nlink) { diff --git a/kernel.spec b/kernel.spec index 7ee812f5f..14f9fe22f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -647,6 +647,8 @@ Patch09: linux-2.6-upstream-reverts.patch Patch160: linux-2.6-32bit-mmap-exec-randomization.patch Patch161: linux-2.6-i386-nx-emulation.patch +Patch200: ext4-lockdep.patch + Patch202: linux-2.6-debug-taint-vm.patch Patch383: linux-2.6-defaults-aspm.patch @@ -1219,6 +1221,7 @@ ApplyPatch linux-2.6-i386-nx-emulation.patch # # ext4 +ApplyPatch ext4-lockdep.patch # xfs @@ -2036,6 +2039,9 @@ fi # and build. %changelog +* Fri Sep 02 2011 Dave Jones +- Apply patch to fix lockdep reports from ext4 (rhbz 732572) + * Thu Sep 01 2011 Dave Jones - utrace: s390: fix the compile problem with traps.c (rhbz 735118) From b8b5e6ba50b8a2600a77edcd8c4b31b9c19c2700 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 7 Sep 2011 12:23:33 -0400 Subject: [PATCH 066/487] Fix for rhbz 735437 --- kernel.spec | 7 +++- ucvideo-fix-crash-when-linking-entities.patch | 34 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 ucvideo-fix-crash-when-linking-entities.patch diff --git a/kernel.spec b/kernel.spec index 14f9fe22f..0ece624b0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -723,6 +723,7 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13002: revert-efi-rtclock.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch Patch13004: iwlagn-revert-max-aggregate-size.patch +Patch13005: ucvideo-fix-crash-when-linking-entities.patch Patch20000: utrace.patch @@ -1336,6 +1337,7 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch revert-efi-rtclock.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch ApplyPatch iwlagn-revert-max-aggregate-size.patch +ApplyPatch ucvideo-fix-crash-when-linking-entities.patch # utrace. ApplyPatch utrace.patch @@ -2039,6 +2041,9 @@ fi # and build. %changelog +* Wed Sep 07 2011 Josh Boyer +- Add patch to fix oops when linking entities in ucvideo (rhbz 735437) + * Fri Sep 02 2011 Dave Jones - Apply patch to fix lockdep reports from ext4 (rhbz 732572) diff --git a/ucvideo-fix-crash-when-linking-entities.patch b/ucvideo-fix-crash-when-linking-entities.patch new file mode 100644 index 000000000..69f86d64c --- /dev/null +++ b/ucvideo-fix-crash-when-linking-entities.patch @@ -0,0 +1,34 @@ +The uvc_mc_register_entity() function wrongfully selects the +media_entity associated with a UVC entity when creating links. This +results in access to uninitialized media_entity structures and can hit a +BUG_ON statement in media_entity_create_link(). Fix it. + +Signed-off-by: Laurent Pinchart +--- + drivers/media/video/uvc/uvc_entity.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +This patch should fix a v3.0 regression that results in a kernel crash as +reported in http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=637740 and +https://bugzilla.redhat.com/show_bug.cgi?id=735437. + +Test results will be welcome. + +diff --git a/drivers/media/video/uvc/uvc_entity.c b/drivers/media/video/uvc/uvc_entity.c +index 48fea37..29e2399 100644 +--- a/drivers/media/video/uvc/uvc_entity.c ++++ b/drivers/media/video/uvc/uvc_entity.c +@@ -49,7 +49,7 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain, + if (remote == NULL) + return -EINVAL; + +- source = (UVC_ENTITY_TYPE(remote) != UVC_TT_STREAMING) ++ source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING) + ? (remote->vdev ? &remote->vdev->entity : NULL) + : &remote->subdev.entity; + if (source == NULL) +-- +Regards, + +Laurent Pinchart + From cf1d9f1e39efde16243b528d596930ad669178fe Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 8 Sep 2011 11:44:04 -0400 Subject: [PATCH 067/487] Drop obsolete config options --- config-generic | 131 +-------------------------------------------- config-x86-generic | 15 ------ 2 files changed, 1 insertion(+), 145 deletions(-) diff --git a/config-generic b/config-generic index 91ddd6868..9d4a6e3b3 100644 --- a/config-generic +++ b/config-generic @@ -45,7 +45,6 @@ CONFIG_LOG_BUF_SHIFT=17 # CONFIG_EXPERT is not set CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y -CONFIG_KALLSYMS_EXTRA_PASS=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y @@ -92,7 +91,6 @@ CONFIG_PCI_STUB=y CONFIG_PCI_IOV=y CONFIG_HT_IRQ=y CONFIG_PCI_MSI=y -CONFIG_PCI_MSI_DEFAULT_ON=y CONFIG_PCIEPORTBUS=y CONFIG_PCIEAER=y CONFIG_PCIEASPM=y @@ -101,7 +99,6 @@ CONFIG_PCIE_ECRC=y CONFIG_PCIEAER_INJECT=m CONFIG_HOTPLUG_PCI_PCIE=y CONFIG_HOTPLUG_PCI_FAKE=m -CONFIG_PCI_LEGACY=y CONFIG_ISA=y # CONFIG_EISA is not set @@ -118,7 +115,6 @@ CONFIG_YENTA=m CONFIG_CARDBUS=y CONFIG_I82092=m CONFIG_PD6729=m -CONFIG_PCMCIA_IOCTL=y CONFIG_PCCARD=y CONFIG_MMC=m @@ -195,9 +191,7 @@ CONFIG_EXTRA_FIRMWARE="" CONFIG_MTD=m # CONFIG_MTD_DEBUG is not set CONFIG_MTD_SWAP=m -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_AR7_PARTS=m -CONFIG_MTD_CONCAT=m CONFIG_MTD_CMDLINE_PARTS=y # # User Modules And Translation Layers @@ -488,7 +482,6 @@ CONFIG_SCSI_SAS_ATTRS=m CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SAS_ATA=y -# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set CONFIG_SCSI_SAS_HOST_SMP=y CONFIG_RAID_ATTRS=m @@ -728,7 +721,6 @@ CONFIG_FIREWIRE_NOSY=m # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -765,7 +757,6 @@ CONFIG_TCP_MD5SIG=y # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y CONFIG_UNIX=y CONFIG_NET_KEY=m CONFIG_NET_KEY_MIGRATE=y @@ -929,7 +920,6 @@ CONFIG_BRIDGE_NETFILTER=y # IP: Netfilter Configuration # -CONFIG_NF_CT_ACCT=y CONFIG_NF_CONNTRACK_MARK=y CONFIG_NF_CONNTRACK_SECMARK=y CONFIG_NF_CONNTRACK_EVENTS=y @@ -955,7 +945,6 @@ CONFIG_NF_CT_PROTO_SCTP=m CONFIG_NF_CT_NETLINK=m CONFIG_NF_CT_PROTO_UDPLITE=m -CONFIG_IP_NF_MATCH_ADDRTYPE=m CONFIG_IP_NF_MATCH_AH=m CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_TTL=m @@ -1082,7 +1071,6 @@ CONFIG_IP_DCCP_CCID2=m # CONFIG_IP_DCCP_CCID2_DEBUG is not set CONFIG_IP_DCCP_CCID3=y # CONFIG_IP_DCCP_CCID3_DEBUG is not set -CONFIG_IP_DCCP_CCID3_RTO=100 # CONFIG_IP_DCCP_DEBUG is not set CONFIG_NET_DCCPPROBE=m @@ -1306,7 +1294,6 @@ CONFIG_ATL1E=m CONFIG_E100=m CONFIG_FEALNX=m CONFIG_FORCEDETH=m -CONFIG_FORCEDETH_NAPI=y CONFIG_NATSEMI=m CONFIG_NE2K_PCI=m CONFIG_8139CP=m @@ -1350,7 +1337,6 @@ CONFIG_NS83820=m CONFIG_HAMACHI=m CONFIG_YELLOWFIN=m CONFIG_R8169=m -CONFIG_R8169_VLAN=y CONFIG_SKGE=m # CONFIG_SKGE_DEBUG is not set CONFIG_SKGE_GENESIS=y @@ -1417,9 +1403,6 @@ CONFIG_SLIP_SMART=y # CONFIG_WLAN=y # CONFIG_STRIP is not set -# CONFIG_ARLAN is not set -CONFIG_PCMCIA_WAVELAN=m -CONFIG_PCMCIA_NETWAVE=m # CONFIG_PCMCIA_RAYCS is not set CONFIG_WIRELESS=y @@ -1431,7 +1414,6 @@ CONFIG_CFG80211_DEBUGFS=y CONFIG_CFG80211_DEFAULT_PS=y CONFIG_NL80211=y # CONFIG_NL80211_TESTMODE is not set -# CONFIG_WIRELESS_OLD_REGULATORY is not set CONFIG_WIRELESS_EXT=y CONFIG_WIRELESS_EXT_SYSFS=y CONFIG_LIB80211=m @@ -1522,7 +1504,6 @@ CONFIG_LIBERTAS_MESH=y CONFIG_IWLWIFI=m CONFIG_IWLWIFI_DEBUG=y CONFIG_IWLWIFI_DEBUGFS=y -CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT=y CONFIG_IWLWIFI_DEVICE_SVTOOL=y # CONFIG_IWL_P2P is not set CONFIG_IWLAGN=m @@ -1531,9 +1512,7 @@ CONFIG_IWLWIFI_LEGACY_DEBUG=y CONFIG_IWLWIFI_LEGACY_DEBUGFS=y # CONFIG_IWLWIFI_LEGACY_DEVICE_TRACING is not set CONFIG_IWL4965=y -CONFIG_IWL5000=y CONFIG_IWL3945=m -CONFIG_IWL3945_SPECTRUM_MEASUREMENT=y # CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE is not set CONFIG_IWM=m # CONFIG_IWM_DEBUG is not set @@ -1574,7 +1553,6 @@ CONFIG_USB_NET_KALMIA=m CONFIG_USB_NET_SMSC75XX=m CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set -CONFIG_AR9170_USB=m CONFIG_WL12XX_MENU=m CONFIG_WL12XX=m @@ -1586,9 +1564,6 @@ CONFIG_WL12XX_SDIO=m CONFIG_WL1251=m CONFIG_WL1251_SPI=m CONFIG_WL1251_SDIO=m -CONFIG_WL1271=m -CONFIG_WL1271_SDIO=m -CONFIG_WL1271_SPI=m CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m @@ -1719,7 +1694,6 @@ CONFIG_WINBOND_FIR=m # CONFIG_BT=m CONFIG_BT_L2CAP=y -CONFIG_BT_L2CAP_EXT_FEATURES=y CONFIG_BT_SCO=y CONFIG_BT_CMTP=m CONFIG_BT_RFCOMM=m @@ -1844,8 +1818,6 @@ CONFIG_ISDN_CAPI=m CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y CONFIG_ISDN_CAPI_MIDDLEWARE=y CONFIG_ISDN_CAPI_CAPI20=m -CONFIG_ISDN_CAPI_CAPIFS_BOOL=y -CONFIG_ISDN_CAPI_CAPIFS=m # # CAPI hardware drivers @@ -2010,7 +1982,6 @@ CONFIG_TOUCHSCREEN_INEXIO=m CONFIG_TOUCHSCREEN_MTOUCH=m CONFIG_TOUCHSCREEN_MCS5000=m CONFIG_TOUCHSCREEN_MK712=m -# CONFIG_TOUCHSCREEN_QT602240 is not set CONFIG_TOUCHSCREEN_PENMOUNT=m # CONFIG_TOUCHSCREEN_TPS6507X is not set CONFIG_TOUCHSCREEN_TSC2007=m @@ -2042,7 +2013,6 @@ CONFIG_MAC_EMUMOUSEBTN=y CONFIG_INPUT_WM831X_ON=m -CONFIG_INPUT_APPLEIR=m # CONFIG_INPUT_AD714X is not set # CONFIG_INPUT_PCF8574 is not set @@ -2090,19 +2060,12 @@ CONFIG_SERIAL_8250_MANY_PORTS=y CONFIG_SERIAL_8250_SHARE_IRQ=y # CONFIG_SERIAL_8250_DETECT_IRQ is not set CONFIG_SERIAL_8250_RSA=y -# CONFIG_COMPUTONE is not set CONFIG_CYCLADES=m # CONFIG_CYZ_INTR is not set -# CONFIG_DIGIEPCA is not set # CONFIG_MOXA_INTELLIO is not set # CONFIG_MOXA_SMARTIO is not set # CONFIG_ISI is not set -# CONFIG_RISCOM8 is not set -# CONFIG_SPECIALIX is not set -# CONFIG_SX is not set # CONFIG_RIO is not set -# CONFIG_STALLION is not set -# CONFIG_ISTALLION is not set CONFIG_SERIAL_JSM=m # CONFIG_SERIAL_MFD_HSU is not set @@ -2153,7 +2116,6 @@ CONFIG_I2C_ALGOPCA=m # CONFIG_I2C_AMD8111 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_I2C_ELEKTOR is not set # CONFIG_I2C_I801 is not set # CONFIG_I2C_ISCH is not set @@ -2206,7 +2168,6 @@ CONFIG_SENSORS_ADM9240=m CONFIG_SENSORS_ADS7828=m CONFIG_SENSORS_ADT7462=m CONFIG_SENSORS_ADT7470=m -CONFIG_SENSORS_ADT7473=m CONFIG_SENSORS_ADT7475=m CONFIG_SENSORS_APPLESMC=m CONFIG_SENSORS_ASB100=m @@ -2477,7 +2438,6 @@ CONFIG_DRM_R128=m CONFIG_DRM_RADEON=m CONFIG_DRM_RADEON_KMS=y CONFIG_DRM_I810=m -# CONFIG_DRM_I830 is not set CONFIG_DRM_MGA=m CONFIG_DRM_SIS=m CONFIG_DRM_SAVAGE=m @@ -2512,8 +2472,6 @@ CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_DEV=m # CONFIG_VIDEO_ADV_DEBUG is not set CONFIG_VIDEO_HELPER_CHIPS_AUTO=y -CONFIG_VIDEO_ALLOW_V4L1=y -CONFIG_VIDEO_V4L1_COMPAT=y CONFIG_VIDEO_V4L2=y CONFIG_VIDEO_V4L2_SUBDEV_API=y # CONFIG_VIDEO_VIVI is not set @@ -2559,17 +2517,13 @@ CONFIG_VIDEO_HEXIUM_GEMINI=m CONFIG_VIDEO_IVTV=m CONFIG_VIDEO_MEYE=m CONFIG_VIDEO_MXB=m -# CONFIG_VIDEO_OVCAMCHIP is not set CONFIG_VIDEO_PVRUSB2_DVB=y CONFIG_VIDEO_HDPVR=m -CONFIG_VIDEO_SAA5246A=m -CONFIG_VIDEO_SAA5249=m CONFIG_VIDEO_SAA6588=m CONFIG_VIDEO_SAA7134=m CONFIG_VIDEO_SAA7134_ALSA=m CONFIG_VIDEO_SAA7134_DVB=m CONFIG_VIDEO_SAA7134_RC=y -CONFIG_VIDEO_STRADIS=m CONFIG_VIDEO_USBVISION=m CONFIG_VIDEO_W9966=m CONFIG_VIDEO_ZORAN=m @@ -2592,9 +2546,7 @@ CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y # # Radio Adapters # -CONFIG_RADIO_GEMTEK_PCI=m CONFIG_RADIO_MAXIRADIO=m -CONFIG_RADIO_MAESTRO=m CONFIG_RADIO_WL1273=m CONFIG_RADIO_WL128X=m @@ -2712,8 +2664,6 @@ CONFIG_DVB_USB_DW2102=m CONFIG_DVB_USB_FRIIO=m CONFIG_DVB_USB_EC168=m CONFIG_DVB_DM1105=m -CONFIG_DVB_DRX397XD=m -CONFIG_DVB_LGDT3304=m CONFIG_DVB_S921=m CONFIG_DVB_ISL6405=m CONFIG_DVB_LGS8GL5=m @@ -3020,13 +2970,10 @@ CONFIG_SND_HDA_CODEC_CA0110=y CONFIG_SND_HDA_CODEC_ANALOG=y CONFIG_SND_HDA_CODEC_SIGMATEL=y CONFIG_SND_HDA_CODEC_VIA=y -CONFIG_SND_HDA_CODEC_ATIHDMI=y CONFIG_SND_HDA_CODEC_CIRRUS=y CONFIG_SND_HDA_CODEC_CONEXANT=y CONFIG_SND_HDA_CODEC_CMEDIA=y -CONFIG_SND_HDA_CODEC_INTELHDMI=y CONFIG_SND_HDA_CODEC_SI3054=y -CONFIG_SND_HDA_CODEC_NVHDMI=y CONFIG_SND_HDA_CODEC_HDMI=y CONFIG_SND_HDA_CODEC_CA0132=y CONFIG_SND_HDA_GENERIC=y @@ -3035,7 +2982,6 @@ CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 CONFIG_SND_HDA_RECONFIG=y CONFIG_SND_HDA_PREALLOC_SIZE=4096 CONFIG_SND_HDSPM=m -CONFIG_SND_HIFIER=m CONFIG_SND_ICE1712=m CONFIG_SND_ICE1724=m CONFIG_SND_INTEL8X0=y @@ -3184,18 +3130,13 @@ CONFIG_USB_IDMOUSE=m CONFIG_DRAGONRISE_FF=y CONFIG_GREENASIA_FF=y CONFIG_SMARTJOYPLUS_FF=y -CONFIG_HID_3M_PCT=y CONFIG_LOGIG940_FF=y CONFIG_HID_MAGICMOUSE=y -CONFIG_HID_MOSART=y CONFIG_HID_MULTITOUCH=m CONFIG_HID_NTRIG=y CONFIG_HID_QUANTA=y -CONFIG_HID_STANTUM=y -CONFIG_HID_CANDO=m CONFIG_HID_PRODIKEYS=m CONFIG_HID_DRAGONRISE=m -CONFIG_HID_EGALAX=m CONFIG_HID_GYRATION=m CONFIG_HID_TWINHAN=m CONFIG_HID_ORTEK=m @@ -3239,10 +3180,7 @@ CONFIG_USB_MICROTEK=m # # USB Multimedia devices # -CONFIG_DAB=y -CONFIG_USB_DABUSB=m -CONFIG_USB_VICAM=m CONFIG_USB_DSBR=m # CONFIG_USB_ET61X251 is not set CONFIG_USB_M5602=m @@ -3262,7 +3200,6 @@ CONFIG_USB_GSPCA_PAC207=m CONFIG_USB_GSPCA_PAC7311=m CONFIG_USB_GSPCA_SN9C2028=m CONFIG_USB_GSPCA_SN9C20X=m -CONFIG_USB_GSPCA_SN9C20X_EVDEV=y CONFIG_USB_GSPCA_SONIXB=m CONFIG_USB_GSPCA_SONIXJ=m CONFIG_USB_GSPCA_SPCA500=m @@ -3292,14 +3229,9 @@ CONFIG_USB_GSPCA_VICAM=m CONFIG_USB_GSPCA_KINECT=m CONFIG_USB_GSPCA_SE401=m -CONFIG_USB_IBMCAM=m -CONFIG_USB_KONICAWC=m -# CONFIG_USB_OV511 is not set CONFIG_USB_S2255=m -CONFIG_USB_SE401=m # CONFIG_VIDEO_SH_MOBILE_CEU is not set # CONFIG_VIDEO_SH_MOBILE_CSI2 is not set -# CONFIG_USB_STV680 is not set # CONFIG_USB_SN9C102 is not set CONFIG_USB_ZR364XX=m CONFIG_SOC_CAMERA=m @@ -3435,7 +3367,6 @@ CONFIG_USB_SERIAL_QCAUX=m CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m CONFIG_USB_SERIAL_DEBUG=m CONFIG_USB_SERIAL_SSU100=m -CONFIG_USB_SERIAL_SAMBA=m CONFIG_USB_SERIAL_CONSOLE=y @@ -3454,7 +3385,6 @@ CONFIG_USB_SEVSEG=m CONFIG_USB_ALI_M5632=y CONFIG_USB_APPLEDISPLAY=m CONFIG_USB_ATM=m -CONFIG_USB_BERRY_CHARGE=m CONFIG_USB_CXACRU=m # CONFIG_USB_C67X00_HCD is not set # CONFIG_USB_CYTHERM is not set @@ -3464,7 +3394,6 @@ CONFIG_USB_FTDI_ELAN=m CONFIG_USB_FILE_STORAGE=m # CONFIG_USB_FILE_STORAGE_TEST is not set # CONFIG_USB_GADGET is not set -# CONFIG_USB_GADGET_GOKU is not set # CONFIG_USB_GADGETFS is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set @@ -3472,7 +3401,6 @@ CONFIG_USB_FILE_STORAGE=m CONFIG_USB_IOWARRIOR=m CONFIG_USB_ISIGHTFW=m CONFIG_USB_YUREX=m -CONFIG_USB_VST=m CONFIG_USB_LCD=m CONFIG_USB_LD=m CONFIG_USB_LEGOTOWER=m @@ -3481,7 +3409,6 @@ CONFIG_USB_PWC=m CONFIG_USB_PWC_INPUT_EVDEV=y # CONFIG_USB_PWC_DEBUG is not set # CONFIG_USB_RIO500 is not set -# CONFIG_USB_QUICKCAM_MESSENGER is not set CONFIG_USB_SISUSBVGA=m CONFIG_USB_SISUSBVGA_CON=y CONFIG_RADIO_SI470X=y @@ -3496,7 +3423,6 @@ CONFIG_USB_TRANCEVIBRATOR=m CONFIG_USB_U132_HCD=m CONFIG_USB_UEAGLEATM=m CONFIG_USB_XUSBATM=m -# CONFIG_USB_ZC0301 is not set CONFIG_USB_ZERO=m CONFIG_USB_ANNOUNCE_NEW_DEVICES=y @@ -3591,7 +3517,6 @@ CONFIG_QFMT_V2=y CONFIG_QUOTACTL=y CONFIG_DNOTIFY=y # Autofsv3 is obsolete. -# CONFIG_AUTOFS_FS is not set # systemd is dependant upon AUTOFS, so build it in. CONFIG_AUTOFS4_FS=y CONFIG_EXOFS_FS=m @@ -3701,7 +3626,6 @@ CONFIG_NFSD_V4=y CONFIG_NFS_FSCACHE=y # CONFIG_NFS_USE_LEGACY_DNS is not set # CONFIG_NFS_USE_NEW_IDMAPPER is not set -# CONFIG_NFSD_DEPRECATED is not set CONFIG_PNFS_OBJLAYOUT=m CONFIG_PNFS_BLOCK=m CONFIG_LOCKD=m @@ -3711,13 +3635,9 @@ CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m CONFIG_SUNRPC_XPRT_RDMA=m CONFIG_RPCSEC_GSS_KRB5=m -CONFIG_RPCSEC_GSS_SPKM3=m -# CONFIG_SMB_FS is not set -# CONFIG_SMB_NLS_DEFAULT is not set CONFIG_CIFS=m CONFIG_CIFS_STATS=y # CONFIG_CIFS_STATS2 is not set -CONFIG_CIFS_EXPERIMENTAL=y CONFIG_CIFS_UPCALL=y CONFIG_CIFS_XATTR=y CONFIG_CIFS_POSIX=y @@ -3999,7 +3919,6 @@ CONFIG_SCHEDSTATS=y CONFIG_SCHED_DEBUG=y CONFIG_FAIR_GROUP_SCHED=y CONFIG_SCHED_OMIT_FRAME_POINTER=y -CONFIG_GROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_SCHED_AUTOGROUP=y @@ -4008,14 +3927,13 @@ CONFIG_PROC_PID_CPUSET=y CONFIG_CGROUPS=y # CONFIG_CGROUP_DEBUG is not set -CONFIG_CGROUP_NS=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_SCHED=y CONFIG_CGROUP_MEM_RES_CTLR=y CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y # XXX disabled by default, pass 'swapaccount' -# CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED is not set +# CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED is not set CONFIG_CGROUP_PERF=y CONFIG_BLK_CGROUP=y # CONFIG_DEBUG_BLK_CGROUP is not set @@ -4043,12 +3961,10 @@ CONFIG_IBMASR=m CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y -# CONFIG_PM_VERBOSE is not set CONFIG_PM_TEST_SUSPEND=y CONFIG_PM_RUNTIME=y CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_DEBUG=y CONFIG_CPU_FREQ_GOV_PERFORMANCE=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y @@ -4118,7 +4034,6 @@ CONFIG_EWRK3=m # CONFIG_SKISA is not set # CONFIG_PROTEON is not set # CONFIG_SMCTR is not set -# CONFIG_WAVELAN is not set # CONFIG_HISAX_16_0 is not set # CONFIG_HISAX_AVM_A1 is not set # CONFIG_HISAX_IX1MICROR2 is not set @@ -4171,7 +4086,6 @@ CONFIG_RADIO_ADAPTERS=y # CONFIG_SND_AD1848 is not set # CONFIG_SND_CS4231 is not set CONFIG_SND_CS4236=m -# CONFIG_SND_ES968 is not set # CONFIG_SND_ES1688 is not set # CONFIG_SND_ES18XX is not set # CONFIG_SND_GUSCLASSIC is not set @@ -4190,9 +4104,7 @@ CONFIG_SND_SBAWE=m # CONFIG_SND_ALS100 is not set # CONFIG_SND_AZT2320 is not set # CONFIG_SND_CMI8330 is not set -# CONFIG_SND_DT019X is not set CONFIG_SND_OPL3SA2=m -# CONFIG_SND_SGALAXY is not set # CONFIG_SND_SSCAPE is not set CONFIG_SND_DARLA20=m CONFIG_SND_GINA20=m @@ -4260,9 +4172,7 @@ CONFIG_DYNAMIC_FTRACE=y # CONFIG_IRQSOFF_TRACER is not set CONFIG_SCHED_TRACER=y CONFIG_CONTEXT_SWITCH_TRACER=y -CONFIG_WORKQUEUE_TRACER=y CONFIG_FTRACE_SYSCALLS=y -CONFIG_KMEMTRACE=y CONFIG_FTRACE_MCOUNT_RECORD=y # CONFIG_FTRACE_STARTUP_TEST is not set # CONFIG_TRACE_BRANCH_PROFILING is not set @@ -4312,7 +4222,6 @@ CONFIG_AUXDISPLAY=y CONFIG_UIO=m CONFIG_UIO_CIF=m -CONFIG_UIO_SMX=m # CONFIG_UIO_PDRV is not set # CONFIG_UIO_PDRV_GENIRQ is not set CONFIG_UIO_AEC=m @@ -4326,20 +4235,14 @@ CONFIG_UIO_PCI_GENERIC=m # LIRC CONFIG_LIRC_STAGING=y CONFIG_LIRC_BT829=m -CONFIG_LIRC_ENE0100=m -CONFIG_LIRC_I2C=m CONFIG_LIRC_IGORPLUGUSB=m CONFIG_LIRC_IMON=m -CONFIG_LIRC_IT87=m -CONFIG_LIRC_ITE8709=m -CONFIG_LIRC_MCEUSB=m CONFIG_LIRC_ZILOG=m CONFIG_LIRC_PARALLEL=m CONFIG_LIRC_SERIAL=m CONFIG_LIRC_SERIAL_TRANSMITTER=y CONFIG_LIRC_SASEM=m CONFIG_LIRC_SIR=m -CONFIG_LIRC_STREAMZAP=m CONFIG_LIRC_TTUSBIR=m # CONFIG_SAMPLES is not set @@ -4400,7 +4303,6 @@ CONFIG_OPTIMIZE_INLINING=y CONFIG_NETFILTER_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_MATCH_RECENT=m -# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set CONFIG_NETFILTER_XT_MATCH_SOCKET=m # CONFIG_IP_VS_IPV6 is not set @@ -4414,7 +4316,6 @@ CONFIG_NET_SCH_MULTIQ=m CONFIG_NET_ACT_SKBEDIT=m CONFIG_PHONET=m -# CONFIG_PHONET_PIPECTRLR is not set CONFIG_ICS932S401=m # CONFIG_C2PORT is not set @@ -4439,12 +4340,9 @@ CONFIG_USB_HWA_HCD=m CONFIG_UWB=m CONFIG_UWB_HWA=m CONFIG_UWB_WHCI=m -CONFIG_UWB_WLP=m CONFIG_UWB_I1480U=m -CONFIG_UWB_I1480U_WLP=m CONFIG_STAGING=y -# CONFIG_STAGING_EXCLUDE_BUILD is not set # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set # CONFIG_VIDEO_TM6000 is not set @@ -4452,31 +4350,20 @@ CONFIG_STAGING=y # CONFIG_WLAGS49_H25 is not set # CONFIG_VIDEO_DT3155 is not set # CONFIG_TI_ST is not set -# CONFIG_ST_BT is not set # CONFIG_FB_XGI is not set # CONFIG_VIDEO_GO7007 is not set -# CONFIG_USB_IP_COMMON is not set # CONFIG_DT3155 is not set # CONFIG_W35UND is not set # CONFIG_PRISM2_USB is not set # CONFIG_ECHO is not set CONFIG_USB_ATMEL=m -# CONFIG_POCH is not set -# CONFIG_OTUS is not set -# CONFIG_RT2860 is not set -# CONFIG_RT2870 is not set # CONFIG_COMEDI is not set # CONFIG_ASUS_OLED is not set # CONFIG_PANEL is not set -# CONFIG_ALTERA_PCIE_CHDMA is not set -# CONFIG_INPUT_MIMIO is not set # CONFIG_TRANZPORT is not set # CONFIG_POHMELFS is not set -# CONFIG_B3DFG is not set # CONFIG_IDE_PHISON is not set -# CONFIG_PLAN9AUTH is not set # CONFIG_LINE6_USB is not set -# CONFIG_RTL8192SU is not set # CONFIG_IIO is not set # CONFIG_VME_BUS is not set # CONFIG_RAR_REGISTER is not set @@ -4488,7 +4375,6 @@ CONFIG_USB_ATMEL=m # CONFIG_HYPERV is not set # CONFIG_R8187SE is not set # CONFIG_RTL8192U is not set -# CONFIG_RAMZSWAP is not set # CONFIG_BATMAN_ADV is not set # CONFIG_FB_SM7XX is not set # CONFIG_SPECTRA is not set @@ -4496,7 +4382,6 @@ CONFIG_USB_ATMEL=m # CONFIG_EASYCAP is not set # CONFIG_SOLO6X10 is not set # CONFIG_ACPI_QUICKSTART is not set -# CONFIG_BRCM80211 is not set # CONFIG_R8712U is not set # CONFIG_ATH6K_LEGACY is not set # CONFIG_USB_ENESTORAGE is not set @@ -4521,10 +4406,8 @@ CONFIG_USB_ATMEL=m # # CONFIG_DEBUG_VIRTUAL is not set -# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FUNCTION_GRAPH_TRACER is not set -CONFIG_BOOT_TRACER=y CONFIG_EARLY_PRINTK_DBGP=y CONFIG_SECURITYFS=y @@ -4547,8 +4430,6 @@ CONFIG_LSM_MMAP_MIN_ADDR=65536 # CONFIG_PAGE_POISONING is not set -CONFIG_SLOW_WORK=y -CONFIG_SLOW_WORK_DEBUG=y # CONFIG_CRASH_DUMP is not set # CONFIG_CRASH is not set @@ -4557,7 +4438,6 @@ CONFIG_STRIP_ASM_SYMS=y # CONFIG_RCU_FANOUT_EXACT is not set CONFIG_RCU_FAST_NO_HZ=y -CONFIG_SRCU_SYNCHRONIZE_DELAY=10 CONFIG_RCU_CPU_STALL_TIMEOUT=60 CONFIG_KSM=y @@ -4601,7 +4481,6 @@ CONFIG_FB_UDL=m # from getting useful bug-reports makes it worth leaving them on. CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_HIGHMEM=y -CONFIG_DEBUG_SPINLOCK_SLEEP=y CONFIG_BOOT_PRINTK_DELAY=y CONFIG_DEBUG_LIST=y CONFIG_DEBUG_SHIRQ=y @@ -4609,7 +4488,6 @@ CONFIG_DEBUG_DEVRES=y CONFIG_DEBUG_RODATA_TEST=y CONFIG_DEBUG_NX_TEST=m CONFIG_DEBUG_BOOT_PARAMS=y -CONFIG_DETECT_SOFTLOCKUP=y CONFIG_LOCKUP_DETECTOR=y # CONFIG_DEBUG_INFO_REDUCED is not set # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set @@ -4645,18 +4523,14 @@ CONFIG_GPIO_SYSFS=y # CONFIG_GPIO_SCH is not set # CONFIG_GPIO_LANGWELL is not set # CONFIG_GPIO_RDC321X is not set -# CONFIG_GPIO_BASIC_MMIO is not set # CONFIG_GPIO_VX855 is not set # CONFIG_GPIO_PCH is not set # CONFIG_GPIO_ML_IOH is not set -CONFIG_KSYM_TRACER=y -CONFIG_PROFILE_KSYM_TRACER=y CONFIG_KPROBE_EVENT=y # CONFIG_RAMOOPS is not set -CONFIG_IR_CORE=m CONFIG_IR_ENE=m CONFIG_IR_STREAMZAP=m CONFIG_IR_WINBOND_CIR=m @@ -4671,20 +4545,17 @@ CONFIG_SPARSE_RCU_POINTER=y # CONFIG_PM_OPP is not set -CONFIG_BKL=y CONFIG_EVENT_POWER_TRACING_DEPRECATED=y # CONFIG_XZ_DEC_TEST is not set -CONFIG_NFC_DEVICES=y CONFIG_PN544_NFC=m CONFIG_NFC_PN533=m CONFIG_TARGET_CORE=m CONFIG_ISCSI_TARGET=m CONFIG_LOOPBACK_TARGET=m -# CONFIG_LOOPBACK_TARGET_CDB_DEBUG is not set CONFIG_TCM_IBLOCK=m CONFIG_TCM_FILEIO=m CONFIG_TCM_PSCSI=m diff --git a/config-x86-generic b/config-x86-generic index 0f1216ede..4437ccbb4 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -55,13 +55,11 @@ CONFIG_X86_MPPARSE=y # CONFIG_DEBUG_PER_CPU_MAPS is not set CONFIG_DEBUG_RODATA=y CONFIG_DEBUG_STACKOVERFLOW=y -CONFIG_DEBUG_NMI_TIMEOUT=5 CONFIG_ACPI=y CONFIG_ACPI_AC=y # CONFIG_ACPI_ASUS is not set CONFIG_ACPI_PROCFS_POWER=y -CONFIG_ACPI_SYSFS_POWER=y CONFIG_ACPI_BATTERY=y CONFIG_ACPI_BUTTON=y CONFIG_ACPI_CONTAINER=m @@ -69,7 +67,6 @@ CONFIG_ACPI_DOCK=y CONFIG_ACPI_FAN=y CONFIG_ACPI_NUMA=y CONFIG_ACPI_PROCESSOR=y -CONFIG_ACPI_POWER=y CONFIG_ACPI_PROCFS=y CONFIG_ACPI_SBS=m CONFIG_ACPI_SLEEP=y @@ -78,7 +75,6 @@ CONFIG_ACPI_TOSHIBA=m CONFIG_ACPI_VIDEO=m # CONFIG_ACPI_PROC_EVENT is not set CONFIG_PNPACPI=y -CONFIG_ACPI_POWER_METER=m CONFIG_ACPI_PROCESSOR_AGGREGATOR=m CONFIG_ACPI_HED=m CONFIG_ACPI_APEI=y @@ -246,7 +242,6 @@ CONFIG_XEN_SCRUB_PAGES=y CONFIG_XEN_SAVE_RESTORE=y CONFIG_HVC_XEN=y CONFIG_XEN_FBDEV_FRONTEND=y -CONFIG_XEN_KBDDEV_FRONTEND=y CONFIG_XEN_BLKDEV_FRONTEND=m CONFIG_XEN_NETDEV_FRONTEND=m CONFIG_XEN_NETDEV_BACKEND=m @@ -295,7 +290,6 @@ CONFIG_INTEL_IOATDMA=m CONFIG_SENSORS_I5K_AMB=m CONFIG_SENSORS_FAM15H_POWER=m CONFIG_SENSORS_ACPI_POWER=m -CONFIG_SENSORS_PKGTEMP=m # CONFIG_CPA_DEBUG is not set @@ -310,31 +304,24 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_MEMTEST is not set # CONFIG_MAXSMP is not set -CONFIG_SYSPROF_TRACER=y CONFIG_HP_ILO=m CONFIG_BACKLIGHT_APPLE=m -CONFIG_OPROFILE_IBS=y # CONFIG_X86_CHECK_BIOS_CORRUPTION is not set -CONFIG_X86_RESERVE_LOW_64K=y # CONFIG_CMDLINE_BOOL is not set -CONFIG_X86_PTRACE_BTS=y CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y -CONFIG_POWER_TRACER=y -CONFIG_HW_BRANCH_TRACER=y # CONFIG_IOMMU_STRESS is not set CONFIG_PERF_COUNTERS=y CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y CONFIG_X86_MCE=y CONFIG_X86_MCE_INTEL=y @@ -343,7 +330,6 @@ CONFIG_X86_MCE_AMD=y CONFIG_SFI=y -CONFIG_INPUT_WINBOND_CIR=m CONFIG_I2C_SCMI=m CONFIG_SBC_FITPC2_WATCHDOG=m @@ -361,7 +347,6 @@ CONFIG_PCI_CNB20LE_QUIRK=y CONFIG_ACPI_EC_DEBUGFS=m # CONFIG_ACPI_APEI_ERST_DEBUG is not set # CONFIG_ACPI_QUICKSTART is not set -CONFIG_IDEAPAD_ACPI=m CONFIG_INTEL_IDLE=y From 9a1d0419efa5191d65a3f9d8dca2645eac0e5bbd Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 8 Sep 2011 13:14:26 -0400 Subject: [PATCH 068/487] Drop/replace obsolete debug options, remove stray backslashes --- Makefile | 14 ++++---------- config-debug | 2 +- config-nodebug | 2 +- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index afa3992c5..3e9e3a8fa 100644 --- a/Makefile +++ b/Makefile @@ -36,13 +36,11 @@ debug: @perl -pi -e 's/# CONFIG_DEBUG_SLAB is not set/CONFIG_DEBUG_SLAB=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_MUTEXES is not set/CONFIG_DEBUG_MUTEXES=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_RT_MUTEXES is not set/CONFIG_DEBUG_RT_MUTEXES=y/' config-nodebug - @perl -pi -e 's/# CONFIG_DEBUG_RWSEMS is not set/CONFIG_DEBUG_RWSEMS=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_LOCK_ALLOC is not set/CONFIG_DEBUG_LOCK_ALLOC=y/' config-nodebug @perl -pi -e 's/# CONFIG_PROVE_LOCKING is not set/CONFIG_PROVE_LOCKING=y/' config-nodebug @perl -pi -e 's/# CONFIG_PROVE_RCU is not set/CONFIG_PROVE_RCU=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_SPINLOCK is not set/CONFIG_DEBUG_SPINLOCK=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_VM is not set/CONFIG_DEBUG_VM=y/' config-nodebug - @perl -pi -e 's/# CONFIG_DEBUG_SLEEP_IN_IRQ is not set/CONFIG_DEBUG_SLEEP_IN_IRQ=y/' config-nodebug @perl -pi -e 's/# CONFIG_FAULT_INJECTION is not set/CONFIG_FAULT_INJECTION=y/' config-nodebug @perl -pi -e 's/# CONFIG_FAILSLAB is not set/CONFIG_FAILSLAB=y/' config-nodebug @perl -pi -e 's/# CONFIG_FAIL_PAGE_ALLOC is not set/CONFIG_FAIL_PAGE_ALLOC=y/' config-nodebug @@ -66,7 +64,6 @@ debug: @perl -pi -e 's/# CONFIG_DMA_API_DEBUG is not set/CONFIG_DMA_API_DEBUG=y/' config-nodebug @perl -pi -e 's/# CONFIG_PM_TEST_SUSPEND is not set/CONFIG_PM_TEST_SUSPEND=y/' config-generic @perl -pi -e 's/# CONFIG_PM_ADVANCED_DEBUG is not set/CONFIG_PM_ADVANCED_DEBUG=y/' config-generic - @perl -pi -e 's/# CONFIG_BOOT_TRACER is not set/CONFIG_BOOT_TRACER=y/' config-generic @perl -pi -e 's/# CONFIG_B43_DEBUG is not set/CONFIG_B43_DEBUG=y/' config-generic @perl -pi -e 's/# CONFIG_B43LEGACY_DEBUG is not set/CONFIG_B43LEGACY_DEBUG=y/' config-generic @perl -pi -e 's/# CONFIG_MMIOTRACE is not set/CONFIG_MMIOTRACE=y/' config-nodebug @@ -77,7 +74,7 @@ debug: @perl -pi -e 's/# CONFIG_EXT4_DEBUG is not set/CONFIG_EXT4_DEBUG=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_PERF_USE_VMALLOC is not set/CONFIG_DEBUG_PERF_USE_VMALLOC=y/' config-nodebug @perl -pi -e 's/# CONFIG_JBD2_DEBUG is not set/CONFIG_JBD2_DEBUG=y/' config-nodebug - @perl -pi -e 's/# CONFIG_DEBUG_CFQ_IOSCHED is not set/CONFIG_DEBUG_CFQ_IOSCHED=y/' config-nodebug + @perl -pi -e 's/# CONFIG_DEBUG_BLK_CGROUP is not set/CONFIG_DEBUG_BLK_CGROUP=y/' config-nodebug @perl -pi -e 's/# CONFIG_DRBD_FAULT_INJECTION is not set/CONFIG_DRBD_FAULT_INJECTION=y/' config-nodebug @perl -pi -e 's/# CONFIG_ATH_DEBUG is not set/CONFIG_ATH_DEBUG=y/' config-nodebug @perl -pi -e 's/# CONFIG_CARL9170_DEBUGFS is not set/CONFIG_CARL9170_DEBUGFS=y/' config-nodebug @@ -116,13 +113,11 @@ release: @perl -pi -e 's/CONFIG_DEBUG_SLAB=y/# CONFIG_DEBUG_SLAB is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_MUTEXES=y/# CONFIG_DEBUG_MUTEXES is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_RT_MUTEXES=y/# CONFIG_DEBUG_RT_MUTEXES is not set/' config-nodebug - @perl -pi -e 's/CONFIG_DEBUG_RWSEMS=y/# CONFIG_DEBUG_RWSEMS is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_LOCK_ALLOC=y/# CONFIG_DEBUG_LOCK_ALLOC is not set/' config-nodebug @perl -pi -e 's/CONFIG_PROVE_LOCKING=y/# CONFIG_PROVE_LOCKING is not set/' config-nodebug @perl -pi -e 's/CONFIG_PROVE_RCU=y/# CONFIG_PROVE_RCU is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_SPINLOCK=y/# CONFIG_DEBUG_SPINLOCK is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_VM=y/# CONFIG_DEBUG_VM is not set/' config-nodebug - @perl -pi -e 's/CONFIG_DEBUG_SLEEP_IN_IRQ=y/# CONFIG_DEBUG_SLEEP_IN_IRQ is not set/' config-nodebug @perl -pi -e 's/CONFIG_FAULT_INJECTION=y/# CONFIG_FAULT_INJECTION is not set/' config-nodebug @perl -pi -e 's/CONFIG_FAILSLAB=y/# CONFIG_FAILSLAB is not set/' config-nodebug @perl -pi -e 's/CONFIG_FAIL_PAGE_ALLOC=y/# CONFIG_FAIL_PAGE_ALLOC is not set/' config-nodebug @@ -144,9 +139,8 @@ release: @perl -pi -e 's/CONFIG_SYSCTL_SYSCALL_CHECK=y/# CONFIG_SYSCTL_SYSCALL_CHECK is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_NOTIFIERS=y/# CONFIG_DEBUG_NOTIFIERS is not set/' config-nodebug @perl -pi -e 's/CONFIG_DMA_API_DEBUG=y/# CONFIG_DMA_API_DEBUG is not set/' config-nodebug - @perl -pi -e 's/CONFIG_PM_TEST_SUSPEND=y/#\ CONFIG_PM_TEST_SUSPEND\ is\ not\ set/' config-generic - @perl -pi -e 's/CONFIG_PM_ADVANCED_DEBUG=y/#\ CONFIG_PM_ADVANCED_DEBUG\ is\ not\ set/' config-generic - @perl -pi -e 's/CONFIG_BOOT_TRACER=y/#\ CONFIG_BOOT_TRACER\ is\ not\ set/' config-generic + @perl -pi -e 's/CONFIG_PM_TEST_SUSPEND=y/# CONFIG_PM_TEST_SUSPEND is not set/' config-generic + @perl -pi -e 's/CONFIG_PM_ADVANCED_DEBUG=y/# CONFIG_PM_ADVANCED_DEBUG is not set/' config-generic @perl -pi -e 's/CONFIG_B43_DEBUG=y/# CONFIG_B43_DEBUG is not set/' config-generic @perl -pi -e 's/CONFIG_B43LEGACY_DEBUG=y/# CONFIG_B43LEGACY_DEBUG is not set/' config-generic @perl -pi -e 's/CONFIG_MMIOTRACE=y/# CONFIG_MMIOTRACE is not set/' config-nodebug @@ -157,7 +151,7 @@ release: @perl -pi -e 's/CONFIG_EXT4_DEBUG=y/# CONFIG_EXT4_DEBUG is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_PERF_USE_VMALLOC=y/# CONFIG_DEBUG_PERF_USE_VMALLOC is not set/' config-nodebug @perl -pi -e 's/CONFIG_JBD2_DEBUG=y/# CONFIG_JBD2_DEBUG is not set/' config-nodebug - @perl -pi -e 's/CONFIG_DEBUG_CFQ_IOSCHED=y/# CONFIG_DEBUG_CFQ_IOSCHED is not set/' config-nodebug + @perl -pi -e 's/CONFIG_DEBUG_BLK_CGROUP=y/# CONFIG_DEBUG_BLK_CGROUP is not set/' config-nodebug @perl -pi -e 's/CONFIG_DRBD_FAULT_INJECTION=y/# CONFIG_DRBD_FAULT_INJECTION is not set/' config-nodebug @perl -pi -e 's/CONFIG_ATH_DEBUG=y/# CONFIG_ATH_DEBUG is not set/' config-nodebug @perl -pi -e 's/CONFIG_CARL9170_DEBUGFS=y/# CONFIG_CARL9170_DEBUGFS is not set/' config-nodebug diff --git a/config-debug b/config-debug index c5cd5b338..a25239038 100644 --- a/config-debug +++ b/config-debug @@ -72,7 +72,7 @@ CONFIG_DEBUG_PERF_USE_VMALLOC=y CONFIG_JBD2_DEBUG=y -CONFIG_DEBUG_CFQ_IOSCHED=y +CONFIG_DEBUG_BLK_CGROUP=y CONFIG_DRBD_FAULT_INJECTION=y diff --git a/config-nodebug b/config-nodebug index 2ec48fe9a..a6acb91de 100644 --- a/config-nodebug +++ b/config-nodebug @@ -72,7 +72,7 @@ CONFIG_DEBUG_PERF_USE_VMALLOC=y CONFIG_JBD2_DEBUG=y -CONFIG_DEBUG_CFQ_IOSCHED=y +CONFIG_DEBUG_BLK_CGROUP=y CONFIG_DRBD_FAULT_INJECTION=y From 512ca00d34667d3cc10d908048773dc3c93fadc9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 9 Sep 2011 10:16:11 -0400 Subject: [PATCH 069/487] 3.1-rc5 --- ext4-lockdep.patch | 12 ------------ kernel.spec | 10 +++++----- sources | 2 +- 3 files changed, 6 insertions(+), 18 deletions(-) delete mode 100644 ext4-lockdep.patch diff --git a/ext4-lockdep.patch b/ext4-lockdep.patch deleted file mode 100644 index 357e22cff..000000000 --- a/ext4-lockdep.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- linux-3.0.noarch/fs/ext4/inode.c~ 2011-09-02 11:50:56.206445843 -0400 -+++ linux-3.0.noarch/fs/ext4/inode.c 2011-09-02 11:51:31.224323827 -0400 -@@ -121,9 +121,6 @@ void ext4_evict_inode(struct inode *inod - - trace_ext4_evict_inode(inode); - -- mutex_lock(&inode->i_mutex); -- ext4_flush_completed_IO(inode); -- mutex_unlock(&inode->i_mutex); - ext4_ioend_wait(inode); - - if (inode->i_nlink) { diff --git a/kernel.spec b/kernel.spec index 0ece624b0..2fe33b67c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 2 +%global baserelease 0 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -82,7 +82,7 @@ Summary: The Linux kernel # The next upstream release sublevel (base_sublevel+1) %define upstream_sublevel %(echo $((%{base_sublevel} + 1))) # The rc snapshot level -%define rcrev 4 +%define rcrev 5 # The git snapshot level %define gitrev 0 # Set rpm version accordingly @@ -647,8 +647,6 @@ Patch09: linux-2.6-upstream-reverts.patch Patch160: linux-2.6-32bit-mmap-exec-randomization.patch Patch161: linux-2.6-i386-nx-emulation.patch -Patch200: ext4-lockdep.patch - Patch202: linux-2.6-debug-taint-vm.patch Patch383: linux-2.6-defaults-aspm.patch @@ -1222,7 +1220,6 @@ ApplyPatch linux-2.6-i386-nx-emulation.patch # # ext4 -ApplyPatch ext4-lockdep.patch # xfs @@ -2041,6 +2038,9 @@ fi # and build. %changelog +* Fri Sep 09 2011 Josh Boyer 3.1.0-0.rc5.git0.0 +- Linux 3.1-rc5 + * Wed Sep 07 2011 Josh Boyer - Add patch to fix oops when linking entities in ucvideo (rhbz 735437) diff --git a/sources b/sources index 5958093ad..fc4847acc 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 -0b0f625fd2d97699e5dbf71554373e6b patch-3.1-rc4.bz2 +12eca0e62e330950dff895a67b3c3087 patch-3.1-rc5.bz2 From f0c9ab6275a856940da10f6a21a8225af27f083e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 9 Sep 2011 11:21:22 -0400 Subject: [PATCH 070/487] Change to 64K page size for ppc64 kernels (rhbz 736751) --- config-powerpc64 | 3 ++- kernel.spec | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/config-powerpc64 b/config-powerpc64 index f27f5b383..9f042f46c 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -108,7 +108,8 @@ CONFIG_NR_CPUS=128 CONFIG_RTAS_PROC=y CONFIG_IOMMU_VMERGE=y CONFIG_NUMA=y -# CONFIG_PPC_64K_PAGES is not set +CONFIG_PPC_64K_PAGES=y +CONFIG_PPC_SUBPAGE_PROT=y CONFIG_SCHED_SMT=y # CONFIG_MV643XX_ETH is not set diff --git a/kernel.spec b/kernel.spec index 2fe33b67c..4895b650d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 0 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2038,6 +2038,9 @@ fi # and build. %changelog +* Fri Sep 09 2011 Josh Boyer +- Change to 64K page size for ppc64 kernels (rhbz 736751) + * Fri Sep 09 2011 Josh Boyer 3.1.0-0.rc5.git0.0 - Linux 3.1-rc5 From 224f377cbfd7013e1741053636837ac0358bc580 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 12 Sep 2011 18:05:34 -0400 Subject: [PATCH 071/487] 3.1-rc6 (includes fix for 736521) This is another hand-rolled patch from a fully updated git tree as of today. The top level upstream commit is b6fd41e29dea9c6753b1843a77e50433e6123bcb Also turn off debug options so we can use this kernel to test a few performance related bugs --- config-generic | 6 +-- config-nodebug | 106 +++++++++++++++++++++--------------------- config-x86_64-generic | 2 +- kernel.spec | 12 +++-- sources | 2 +- 5 files changed, 66 insertions(+), 62 deletions(-) diff --git a/config-generic b/config-generic index 9d4a6e3b3..2d9887606 100644 --- a/config-generic +++ b/config-generic @@ -1462,12 +1462,12 @@ CONFIG_B43=m CONFIG_B43_PCMCIA=y CONFIG_B43_SDIO=y CONFIG_B43_BCMA=y -CONFIG_B43_DEBUG=y +# CONFIG_B43_DEBUG is not set CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y # CONFIG_B43_FORCE_PIO is not set CONFIG_B43LEGACY=m -CONFIG_B43LEGACY_DEBUG=y +# CONFIG_B43LEGACY_DEBUG is not set CONFIG_B43LEGACY_DMA=y CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y @@ -3961,7 +3961,7 @@ CONFIG_IBMASR=m CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y -CONFIG_PM_TEST_SUSPEND=y +# CONFIG_PM_TEST_SUSPEND is not set CONFIG_PM_RUNTIME=y CONFIG_CPU_FREQ=y diff --git a/config-nodebug b/config-nodebug index a6acb91de..084f88e2e 100644 --- a/config-nodebug +++ b/config-nodebug @@ -2,106 +2,106 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_DEBUG=y CONFIG_SND_PCM_XRUN_DEBUG=y -CONFIG_DEBUG_ATOMIC_SLEEP=y +# CONFIG_DEBUG_ATOMIC_SLEEP is not set -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_RT_MUTEXES=y -CONFIG_DEBUG_LOCK_ALLOC=y -CONFIG_PROVE_LOCKING=y -CONFIG_DEBUG_VM=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_PROVE_RCU=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_PROVE_RCU is not set # CONFIG_PROVE_RCU_REPEATEDLY is not set -CONFIG_DEBUG_PER_CPU_MAPS=y +# CONFIG_DEBUG_PER_CPU_MAPS is not set CONFIG_CPUMASK_OFFSTACK=y -CONFIG_CPU_NOTIFIER_ERROR_INJECT=m +# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set -CONFIG_FAULT_INJECTION=y -CONFIG_FAILSLAB=y -CONFIG_FAIL_PAGE_ALLOC=y -CONFIG_FAIL_MAKE_REQUEST=y -CONFIG_FAULT_INJECTION_DEBUG_FS=y -CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y -CONFIG_FAIL_IO_TIMEOUT=y +# CONFIG_FAULT_INJECTION is not set +# CONFIG_FAILSLAB is not set +# CONFIG_FAIL_PAGE_ALLOC is not set +# CONFIG_FAIL_MAKE_REQUEST is not set +# CONFIG_FAULT_INJECTION_DEBUG_FS is not set +# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set +# CONFIG_FAIL_IO_TIMEOUT is not set -CONFIG_SLUB_DEBUG_ON=y +# CONFIG_SLUB_DEBUG_ON is not set -CONFIG_LOCK_STAT=y +# CONFIG_LOCK_STAT is not set -CONFIG_DEBUG_STACK_USAGE=y +# CONFIG_DEBUG_STACK_USAGE is not set -CONFIG_ACPI_DEBUG=y +# CONFIG_ACPI_DEBUG is not set # CONFIG_ACPI_DEBUG_FUNC_TRACE is not set -CONFIG_DEBUG_SG=y +# CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_PAGEALLOC is not set -CONFIG_DEBUG_WRITECOUNT=y -CONFIG_DEBUG_OBJECTS=y +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_OBJECTS_SELFTEST is not set -CONFIG_DEBUG_OBJECTS_FREE=y -CONFIG_DEBUG_OBJECTS_TIMERS=y -CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +# CONFIG_DEBUG_OBJECTS_FREE is not set +# CONFIG_DEBUG_OBJECTS_TIMERS is not set +# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 -CONFIG_X86_PTDUMP=y +# CONFIG_X86_PTDUMP is not set -CONFIG_CAN_DEBUG_DEVICES=y +# CONFIG_CAN_DEBUG_DEVICES is not set -CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_SYSCTL_SYSCALL_CHECK is not set -CONFIG_DEBUG_NOTIFIERS=y +# CONFIG_DEBUG_NOTIFIERS is not set -CONFIG_DMA_API_DEBUG=y +# CONFIG_DMA_API_DEBUG is not set -CONFIG_MMIOTRACE=y +# CONFIG_MMIOTRACE is not set -CONFIG_DEBUG_CREDENTIALS=y +# CONFIG_DEBUG_CREDENTIALS is not set # off in both production debug and nodebug builds, # on in rawhide nodebug builds -CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set -CONFIG_EXT4_DEBUG=y +# CONFIG_EXT4_DEBUG is not set -CONFIG_DEBUG_PERF_USE_VMALLOC=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set -CONFIG_JBD2_DEBUG=y +# CONFIG_JBD2_DEBUG is not set -CONFIG_DEBUG_BLK_CGROUP=y +# CONFIG_DEBUG_BLK_CGROUP is not set -CONFIG_DRBD_FAULT_INJECTION=y +# CONFIG_DRBD_FAULT_INJECTION is not set -CONFIG_ATH_DEBUG=y -CONFIG_CARL9170_DEBUGFS=y -CONFIG_IWLWIFI_DEVICE_TRACING=y +# CONFIG_ATH_DEBUG is not set +# CONFIG_CARL9170_DEBUGFS is not set +# CONFIG_IWLWIFI_DEVICE_TRACING is not set -CONFIG_DEBUG_OBJECTS_WORK=y +# CONFIG_DEBUG_OBJECTS_WORK is not set # CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set -CONFIG_DMADEVICES_DEBUG=y -CONFIG_DMADEVICES_VDEBUG=y +# CONFIG_DMADEVICES_DEBUG is not set +# CONFIG_DMADEVICES_VDEBUG is not set CONFIG_PM_ADVANCED_DEBUG=y -CONFIG_CEPH_LIB_PRETTYDEBUG=y -CONFIG_QUOTA_DEBUG=y +# CONFIG_CEPH_LIB_PRETTYDEBUG is not set +# CONFIG_QUOTA_DEBUG is not set CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y CONFIG_KDB_KEYBOARD=y -CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y -CONFIG_TEST_LIST_SORT=y +# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set +# CONFIG_TEST_LIST_SORT is not set -CONFIG_DEBUG_SET_MODULE_RONX=y +# CONFIG_DEBUG_SET_MODULE_RONX is not set -CONFIG_DETECT_HUNG_TASK=y +# CONFIG_DETECT_HUNG_TASK is not set CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set diff --git a/config-x86_64-generic b/config-x86_64-generic index 15277d705..a31c5e82c 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -12,7 +12,7 @@ CONFIG_AMD_NUMA=y CONFIG_X86_64_ACPI_NUMA=y # CONFIG_NUMA_EMU is not set -CONFIG_NR_CPUS=512 +CONFIG_NR_CPUS=256 CONFIG_PHYSICAL_START=0x1000000 CONFIG_IA32_EMULATION=y diff --git a/kernel.spec b/kernel.spec index 4895b650d..953e63689 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 1 +%global baserelease 0 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -82,7 +82,7 @@ Summary: The Linux kernel # The next upstream release sublevel (base_sublevel+1) %define upstream_sublevel %(echo $((%{base_sublevel} + 1))) # The rc snapshot level -%define rcrev 5 +%define rcrev 6 # The git snapshot level %define gitrev 0 # Set rpm version accordingly @@ -134,7 +134,7 @@ Summary: The Linux kernel %define doc_build_fail true %endif -%define rawhide_skip_docs 1 +%define rawhide_skip_docs 0 %if 0%{?rawhide_skip_docs} %define with_doc 0 %define doc_build_fail true @@ -157,7 +157,7 @@ Summary: The Linux kernel # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. -%define debugbuildsenabled 0 +%define debugbuildsenabled 1 # Want to build a vanilla kernel build without any non-upstream patches? %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} @@ -2038,6 +2038,10 @@ fi # and build. %changelog +* Mon Sep 12 2011 Josh Boyer 3.1.0-0.rc6.git0.0 +- Linux 3.1-rc6 (contains the fix for 737076) +- Disable debug builds + * Fri Sep 09 2011 Josh Boyer - Change to 64K page size for ppc64 kernels (rhbz 736751) diff --git a/sources b/sources index fc4847acc..474ac9f50 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 -12eca0e62e330950dff895a67b3c3087 patch-3.1-rc5.bz2 +e283598a0c4cbc6da64cda68101fdbf1 patch-3.1-rc6.bz2 From 35fd65a18148b9807439832f8964537a15f23705 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 13 Sep 2011 12:14:28 -0400 Subject: [PATCH 072/487] drm/i915: Shut the fbc messages up when drm.debug & 4 --- drm-i915-fbc-stfu.patch | 102 ++++++++++++++++++++++++++++++++++++++++ kernel.spec | 6 +++ 2 files changed, 108 insertions(+) create mode 100644 drm-i915-fbc-stfu.patch diff --git a/drm-i915-fbc-stfu.patch b/drm-i915-fbc-stfu.patch new file mode 100644 index 000000000..7e30dae4b --- /dev/null +++ b/drm-i915-fbc-stfu.patch @@ -0,0 +1,102 @@ +From c5d1455d9340c63e5c5d987e2d816e77538caa90 Mon Sep 17 00:00:00 2001 +From: Adam Jackson +Date: Tue, 13 Sep 2011 12:07:37 -0400 +Subject: [PATCH] drm/i915: Shut the fbc messages up + +FB compression enable/disable fires on pretty much every pageflip now, +which is just uncredibly excessive. Hush that noise. + +Signed-off-by: Adam Jackson +--- + drivers/gpu/drm/i915/intel_display.c | 19 ------------------- + 1 files changed, 0 insertions(+), 19 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index 56a8554..a6d14eb 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -1474,8 +1474,6 @@ static void i8xx_disable_fbc(struct drm_device *dev) + DRM_DEBUG_KMS("FBC idle timed out\n"); + return; + } +- +- DRM_DEBUG_KMS("disabled FBC\n"); + } + + static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) +@@ -1516,9 +1514,6 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) + fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT; + fbc_ctl |= obj->fence_reg; + I915_WRITE(FBC_CONTROL, fbc_ctl); +- +- DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %d, ", +- cfb_pitch, crtc->y, intel_crtc->plane); + } + + static bool i8xx_fbc_enabled(struct drm_device *dev) +@@ -1551,8 +1546,6 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) + + /* enable it... */ + I915_WRITE(DPFC_CONTROL, I915_READ(DPFC_CONTROL) | DPFC_CTL_EN); +- +- DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); + } + + static void g4x_disable_fbc(struct drm_device *dev) +@@ -1565,8 +1558,6 @@ static void g4x_disable_fbc(struct drm_device *dev) + if (dpfc_ctl & DPFC_CTL_EN) { + dpfc_ctl &= ~DPFC_CTL_EN; + I915_WRITE(DPFC_CONTROL, dpfc_ctl); +- +- DRM_DEBUG_KMS("disabled FBC\n"); + } + } + +@@ -1631,8 +1622,6 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) + I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y); + sandybridge_blit_fbc_update(dev); + } +- +- DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); + } + + static void ironlake_disable_fbc(struct drm_device *dev) +@@ -1645,8 +1634,6 @@ static void ironlake_disable_fbc(struct drm_device *dev) + if (dpfc_ctl & DPFC_CTL_EN) { + dpfc_ctl &= ~DPFC_CTL_EN; + I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); +- +- DRM_DEBUG_KMS("disabled FBC\n"); + } + } + +@@ -1701,8 +1688,6 @@ static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv) + if (dev_priv->fbc_work == NULL) + return; + +- DRM_DEBUG_KMS("cancelling pending FBC enable\n"); +- + /* Synchronisation is provided by struct_mutex and checking of + * dev_priv->fbc_work, so we can perform the cancellation + * entirely asynchronously. +@@ -1743,8 +1728,6 @@ static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval) + + dev_priv->fbc_work = work; + +- DRM_DEBUG_KMS("scheduling delayed FBC enable\n"); +- + /* Delay the actual enabling to let pageflipping cease and the + * display to settle before starting the compression. Note that + * this delay also serves a second purpose: it allows for a +@@ -1800,8 +1783,6 @@ static void intel_update_fbc(struct drm_device *dev) + struct intel_framebuffer *intel_fb; + struct drm_i915_gem_object *obj; + +- DRM_DEBUG_KMS("\n"); +- + if (!i915_powersave) + return; + +-- +1.7.6 + diff --git a/kernel.spec b/kernel.spec index 953e63689..97f415c7f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -683,6 +683,8 @@ Patch1810: drm-nouveau-updates.patch Patch1824: drm-intel-next.patch # make sure the lvds comes back on lid open Patch1825: drm-intel-make-lvds-work.patch +# hush the i915 fbc noise +Patch1826: drm-i915-fbc-stfu.patch Patch1900: linux-2.6-intel-iommu-igfx.patch @@ -1300,6 +1302,7 @@ ApplyOptionalPatch drm-nouveau-updates.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch ApplyPatch drm-intel-make-lvds-work.patch +ApplyPatch drm-i915-fbc-stfu.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch # silence the ACPI blacklist code @@ -2038,6 +2041,9 @@ fi # and build. %changelog +* Tue Sep 13 2011 Adam Jackson +- drm/i915: Shut the fbc messages up when drm.debug & 4 + * Mon Sep 12 2011 Josh Boyer 3.1.0-0.rc6.git0.0 - Linux 3.1-rc6 (contains the fix for 737076) - Disable debug builds From b226a238b480f155bec13dbe703b4d639b30623c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 14 Sep 2011 09:21:29 -0400 Subject: [PATCH 073/487] Add patches Bastien pointed out for MacBookAir 4,1 support --- add-macbookair41-btusb.patch | 67 ++++++++++++++++++ add-macbookair41-keyboard.patch | 119 ++++++++++++++++++++++++++++++++ add-macbookair41-trackpad.patch | 100 +++++++++++++++++++++++++++ kernel.spec | 13 +++- 4 files changed, 298 insertions(+), 1 deletion(-) create mode 100644 add-macbookair41-btusb.patch create mode 100644 add-macbookair41-keyboard.patch create mode 100644 add-macbookair41-trackpad.patch diff --git a/add-macbookair41-btusb.patch b/add-macbookair41-btusb.patch new file mode 100644 index 000000000..8997cede8 --- /dev/null +++ b/add-macbookair41-btusb.patch @@ -0,0 +1,67 @@ +Path: news.gmane.org!not-for-mail +From: Pieter-Augustijn Van Malleghem +Newsgroups: gmane.linux.bluez.kernel +Subject: [PATCH] Add MacBookAir4,1 support +Date: Wed, 7 Sep 2011 02:28:10 -0400 +Lines: 18 +Approved: news@gmane.org +Message-ID: <20110907062810.GA4755@Caligula> +NNTP-Posting-Host: lo.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +X-Trace: dough.gmane.org 1315376918 16651 80.91.229.12 (7 Sep 2011 06:28:38 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Wed, 7 Sep 2011 06:28:38 +0000 (UTC) +To: linux-bluetooth-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Original-X-From: linux-bluetooth-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Wed Sep 07 08:28:35 2011 +Return-path: +Envelope-to: glbk-linux-bluetooth-1dZseelyfdZg9hUCZPvPmw@public.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1R1Bce-00013w-IP + for glbk-linux-bluetooth-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Wed, 07 Sep 2011 08:28:32 +0200 +Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand + id S1755760Ab1IGG22 (ORCPT + ); + Wed, 7 Sep 2011 02:28:28 -0400 +Original-Received: from mail-qy0-f174.google.com ([209.85.216.174]:48109 "EHLO + mail-qy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1756054Ab1IGG2V (ORCPT + ); + Wed, 7 Sep 2011 02:28:21 -0400 +Original-Received: by qyk7 with SMTP id 7so455185qyk.19 + for ; Tue, 06 Sep 2011 23:28:20 -0700 (PDT) +Original-Received: by 10.224.192.6 with SMTP id do6mr4345154qab.189.1315376900296; + Tue, 06 Sep 2011 23:28:20 -0700 (PDT) +Original-Received: from Caligula ([140.247.187.88]) + by mx.google.com with ESMTPS id dr7sm2176040qab.26.2011.09.06.23.28.19 + (version=TLSv1/SSLv3 cipher=OTHER); + Tue, 06 Sep 2011 23:28:19 -0700 (PDT) +Content-Disposition: inline +User-Agent: Mutt/1.5.21 (2010-09-15) +Original-Sender: linux-bluetooth-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-bluetooth-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Xref: news.gmane.org gmane.linux.bluez.kernel:16281 +Archived-At: + +This patch against current git adds the hardware ID for the Apple +MacBookAir4,1, released in July 2011. The device features a BCM2046 +USB chip. The patch was inspired by the previous modifications adding +support for the MacBookAir3,x. + +Signed-off-by: Pieter-Augustijn Van Malleghem +--- linux/drivers/bluetooth/btusb.c 2011-09-06 23:41:57.000000000 -0400 ++++ patched/drivers/bluetooth/btusb.c 2011-09-06 23:50:27.000000000 -0400 +@@ -72,6 +72,9 @@ + /* Apple MacBookAir3,1, MacBookAir3,2 */ + { USB_DEVICE(0x05ac, 0x821b) }, + ++ /* Apple MacBookAir4,1 */ ++ { USB_DEVICE(0x05ac, 0x821f) }, ++ + /* Apple MacBookPro8,2 */ + { USB_DEVICE(0x05ac, 0x821a) }, + diff --git a/add-macbookair41-keyboard.patch b/add-macbookair41-keyboard.patch new file mode 100644 index 000000000..cb8c71d9e --- /dev/null +++ b/add-macbookair41-keyboard.patch @@ -0,0 +1,119 @@ +Path: news.gmane.org!not-for-mail +From: Pieter-Augustijn Van Malleghem +Newsgroups: gmane.linux.kernel.input +Subject: [PATCH] Add MacBookAir4,1 keyboard support +Date: Wed, 7 Sep 2011 16:15:52 -0400 +Lines: 72 +Approved: news@gmane.org +Message-ID: <20110907201552.GA1962@Caligula> +NNTP-Posting-Host: lo.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +X-Trace: dough.gmane.org 1315426570 11003 80.91.229.12 (7 Sep 2011 20:16:10 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Wed, 7 Sep 2011 20:16:10 +0000 (UTC) +To: linux-input@vger.kernel.org +Original-X-From: linux-input-owner@vger.kernel.org Wed Sep 07 22:16:06 2011 +Return-path: +Envelope-to: glki-linux-input-2@lo.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1R1OXV-0007QX-Ll + for glki-linux-input-2@lo.gmane.org; Wed, 07 Sep 2011 22:16:06 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1751419Ab1IGUQE (ORCPT ); + Wed, 7 Sep 2011 16:16:04 -0400 +Original-Received: from mail-vx0-f174.google.com ([209.85.220.174]:57168 "EHLO + mail-vx0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1751237Ab1IGUQC (ORCPT + ); Wed, 7 Sep 2011 16:16:02 -0400 +Original-Received: by vxj15 with SMTP id 15so31147vxj.19 + for ; Wed, 07 Sep 2011 13:16:02 -0700 (PDT) +Original-Received: by 10.52.69.210 with SMTP id g18mr64348vdu.133.1315426562281; + Wed, 07 Sep 2011 13:16:02 -0700 (PDT) +Original-Received: from Caligula ([140.247.246.50]) + by mx.google.com with ESMTPS id ch2sm944169vdc.19.2011.09.07.13.16.01 + (version=TLSv1/SSLv3 cipher=OTHER); + Wed, 07 Sep 2011 13:16:01 -0700 (PDT) +Content-Disposition: inline +User-Agent: Mutt/1.5.21 (2010-09-15) +Original-Sender: linux-input-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-input@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel.input:21462 +Archived-At: + +This patch adds support for the Apple MacBookAir4,1 released in July +2011. It was inspired by Joshua Dillon's patch for the MacBookAir4,2 +posted on http://www.almostsure.com/mba42/hid-apple-dkms.patch. + +Signed-off-by: Pieter-Augustijn Van Malleghem +diff -uNr linux/drivers/hid/hid-apple.c patched/drivers/hid/hid-apple.c +--- linux/drivers/hid/hid-apple.c 2011-09-06 23:41:58.000000000 -0400 ++++ patched/drivers/hid/hid-apple.c 2011-09-06 23:53:05.000000000 -0400 +@@ -183,6 +183,9 @@ + if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI && + hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) + table = macbookair_fn_keys; ++ else if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI && ++ hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) ++ table = macbookair_fn_keys; + else if (hid->product < 0x21d || hid->product >= 0x300) + table = powerbook_fn_keys; + else +@@ -493,6 +499,12 @@ + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI), ++ .driver_data = APPLE_HAS_FN }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO), ++ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS), ++ .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), +diff -uNr linux/drivers/hid/hid-core.c patched/drivers/hid/hid-core.c +--- linux/drivers/hid/hid-core.c 2011-09-06 23:41:58.000000000 -0400 ++++ patched/drivers/hid/hid-core.c 2011-09-06 23:56:22.000000000 -0400 +@@ -1340,6 +1340,9 @@ + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS) }, +@@ -1892,6 +1895,9 @@ + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, + { } +diff -uNr linux/drivers/hid/hid-ids.h patched/drivers/hid/hid-ids.h +--- linux/drivers/hid/hid-ids.h 2011-09-06 23:41:58.000000000 -0400 ++++ patched/drivers/hid/hid-ids.h 2011-09-06 23:57:39.000000000 -0400 +@@ -109,6 +109,9 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 + #define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 + #define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 ++#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249 ++#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a ++#define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b + #define USB_DEVICE_ID_APPLE_ALU_REVB_ANSI 0x024f + #define USB_DEVICE_ID_APPLE_ALU_REVB_ISO 0x0250 + #define USB_DEVICE_ID_APPLE_ALU_REVB_JIS 0x0251 +-- +To unsubscribe from this list: send the line "unsubscribe linux-input" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + diff --git a/add-macbookair41-trackpad.patch b/add-macbookair41-trackpad.patch new file mode 100644 index 000000000..ec6890e5e --- /dev/null +++ b/add-macbookair41-trackpad.patch @@ -0,0 +1,100 @@ +Path: news.gmane.org!not-for-mail +From: Pieter-Augustijn Van Malleghem +Newsgroups: gmane.linux.kernel.input +Subject: [PATCH] Add MacBookAir4,1 trackpad support +Date: Wed, 7 Sep 2011 16:16:39 -0400 +Lines: 53 +Approved: news@gmane.org +Message-ID: <20110907201639.GA2004@Caligula> +NNTP-Posting-Host: lo.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +X-Trace: dough.gmane.org 1315427050 14847 80.91.229.12 (7 Sep 2011 20:24:10 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Wed, 7 Sep 2011 20:24:10 +0000 (UTC) +To: linux-input@vger.kernel.org +Original-X-From: linux-input-owner@vger.kernel.org Wed Sep 07 22:24:06 2011 +Return-path: +Envelope-to: glki-linux-input-2@lo.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1R1OfE-0003bX-Dq + for glki-linux-input-2@lo.gmane.org; Wed, 07 Sep 2011 22:24:04 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1756616Ab1IGUYD (ORCPT ); + Wed, 7 Sep 2011 16:24:03 -0400 +Original-Received: from mail-vx0-f174.google.com ([209.85.220.174]:45534 "EHLO + mail-vx0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1755813Ab1IGUYB (ORCPT + ); Wed, 7 Sep 2011 16:24:01 -0400 +Original-Received: by vxj15 with SMTP id 15so37615vxj.19 + for ; Wed, 07 Sep 2011 13:24:01 -0700 (PDT) +Original-Received: by 10.52.173.49 with SMTP id bh17mr2675458vdc.82.1315426608488; + Wed, 07 Sep 2011 13:16:48 -0700 (PDT) +Original-Received: from Caligula ([140.247.246.50]) + by mx.google.com with ESMTPS id da15sm937150vdb.26.2011.09.07.13.16.47 + (version=TLSv1/SSLv3 cipher=OTHER); + Wed, 07 Sep 2011 13:16:47 -0700 (PDT) +Content-Disposition: inline +User-Agent: Mutt/1.5.21 (2010-09-15) +Original-Sender: linux-input-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-input@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel.input:21463 +Archived-At: + +This patch adds trackpad support for the MacBookAir4,1, released in July 2011. +It is very similar to the MacBookAir4,2 patch submitted by Joshua Dillon and +Chase Douglas. + +Signed-off-by: Pieter-Augustijn Van Malleghem +--- linux/drivers/input/mouse/bcm5974.c 2011-09-06 23:41:58.000000000 -0400 ++++ patched/drivers/input/mouse/bcm5974.c 2011-09-07 00:02:44.000000000 -0400 +@@ -67,6 +67,10 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 + #define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 + #define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 ++/* MacbookAir4,1 (unibody, July 2011) */ ++#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249 ++#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a ++#define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b + /* MacbookAir4,2 (unibody, July 2011) */ + #define USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI 0x024c + #define USB_DEVICE_ID_APPLE_WELLSPRING6_ISO 0x024d +@@ -112,6 +116,10 @@ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ISO), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), ++ /* MacbookAir4,1 */ ++ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI), ++ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO), ++ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS), + /* MacbookAir4,2 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6_ISO), +@@ -334,6 +342,18 @@ + { DIM_X, DIM_X / SN_COORD, -4750, 5280 }, + { DIM_Y, DIM_Y / SN_COORD, -150, 6730 } + }, ++ { ++ USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI, ++ USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO, ++ USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS, ++ HAS_INTEGRATED_BUTTON, ++ 0x84, sizeof(struct bt_data), ++ 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, ++ { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, ++ { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, ++ { DIM_X, DIM_X / SN_COORD, -4620, 5140 }, ++ { DIM_Y, DIM_Y / SN_COORD, -150, 6600 } ++ }, + {} + }; + +-- +To unsubscribe from this list: send the line "unsubscribe linux-input" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + diff --git a/kernel.spec b/kernel.spec index 97f415c7f..29fbf8e96 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 0 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -725,6 +725,10 @@ Patch13003: efi-dont-map-boot-services-on-32bit.patch Patch13004: iwlagn-revert-max-aggregate-size.patch Patch13005: ucvideo-fix-crash-when-linking-entities.patch +Patch13006: add-macbookair41-trackpad.patch +Patch13007: add-macbookair41-keyboard.patch +Patch13008: add-macbookair41-btusb.patch + Patch20000: utrace.patch # Flattened devicetree support @@ -1339,6 +1343,10 @@ ApplyPatch efi-dont-map-boot-services-on-32bit.patch ApplyPatch iwlagn-revert-max-aggregate-size.patch ApplyPatch ucvideo-fix-crash-when-linking-entities.patch +ApplyPatch add-macbookair41-trackpad.patch +ApplyPatch add-macbookair41-keyboard.patch +ApplyPatch add-macbookair41-btusb.patch + # utrace. ApplyPatch utrace.patch @@ -2041,6 +2049,9 @@ fi # and build. %changelog +* Wed Sep 14 2011 Josh Boyer +- Add support for Macbook Air 4,1 keyboard, trackpad, and bluetooth + * Tue Sep 13 2011 Adam Jackson - drm/i915: Shut the fbc messages up when drm.debug & 4 From 5e909ef60ba649ea88a4236c8bc28338ca120cf5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 14 Sep 2011 09:44:30 -0400 Subject: [PATCH 074/487] Add patch to fix POWER virtual serial driver (rhbz 738096) --- hvcs_pi_buf_alloc.patch | 43 +++++++++++++++++++++++++++++++++++++++++ kernel.spec | 5 +++++ 2 files changed, 48 insertions(+) create mode 100644 hvcs_pi_buf_alloc.patch diff --git a/hvcs_pi_buf_alloc.patch b/hvcs_pi_buf_alloc.patch new file mode 100644 index 000000000..ecabe49b1 --- /dev/null +++ b/hvcs_pi_buf_alloc.patch @@ -0,0 +1,43 @@ + +The Power platform requires the partner info buffer to be page aligned +otherwise it will fail the partner info hcall with H_PARAMETER. Switch +from using kmalloc to allocate this buffer to __get_free_page to ensure +page alignment. + +Signed-off-by: Brian King +--- + + drivers/tty/hvc/hvcs.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff -puN drivers/tty/hvc/hvcs.c~hvcs_pi_buf_alloc drivers/tty/hvc/hvcs.c +--- linux-2.6/drivers/tty/hvc/hvcs.c~hvcs_pi_buf_alloc 2011-09-09 16:00:25.000000000 -0500 ++++ linux-2.6-bjking1/drivers/tty/hvc/hvcs.c 2011-09-09 16:07:08.000000000 -0500 +@@ -1532,7 +1532,7 @@ static int __devinit hvcs_initialize(voi + goto register_fail; + } + +- hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL); ++ hvcs_pi_buff = (unsigned long *) __get_free_page(GFP_KERNEL); + if (!hvcs_pi_buff) { + rc = -ENOMEM; + goto buff_alloc_fail; +@@ -1548,7 +1548,7 @@ static int __devinit hvcs_initialize(voi + return 0; + + kthread_fail: +- kfree(hvcs_pi_buff); ++ free_page((unsigned long)hvcs_pi_buff); + buff_alloc_fail: + tty_unregister_driver(hvcs_tty_driver); + register_fail: +@@ -1597,7 +1597,7 @@ static void __exit hvcs_module_exit(void + kthread_stop(hvcs_task); + + spin_lock(&hvcs_pi_lock); +- kfree(hvcs_pi_buff); ++ free_page((unsigned long)hvcs_pi_buff); + hvcs_pi_buff = NULL; + spin_unlock(&hvcs_pi_lock); + +_ diff --git a/kernel.spec b/kernel.spec index 29fbf8e96..0b9f3d779 100644 --- a/kernel.spec +++ b/kernel.spec @@ -729,6 +729,8 @@ Patch13006: add-macbookair41-trackpad.patch Patch13007: add-macbookair41-keyboard.patch Patch13008: add-macbookair41-btusb.patch +Patch13009: hvcs_pi_buf_alloc.patch + Patch20000: utrace.patch # Flattened devicetree support @@ -1347,6 +1349,8 @@ ApplyPatch add-macbookair41-trackpad.patch ApplyPatch add-macbookair41-keyboard.patch ApplyPatch add-macbookair41-btusb.patch +ApplyPatch hvcs_pi_buf_alloc.patch + # utrace. ApplyPatch utrace.patch @@ -2051,6 +2055,7 @@ fi %changelog * Wed Sep 14 2011 Josh Boyer - Add support for Macbook Air 4,1 keyboard, trackpad, and bluetooth +- Add patch to fix HVCS on ppc64 (rhbz 738096) * Tue Sep 13 2011 Adam Jackson - drm/i915: Shut the fbc messages up when drm.debug & 4 From 203a23e9e4d49baf8da60e8fa06396472078e96a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 14 Sep 2011 14:29:35 -0400 Subject: [PATCH 075/487] Add patches to fix various ibmveth driver issues (rhbz 733766) --- ...-Checksum-offload-is-always-disabled.patch | 70 ++++++++++++++ ibmveth-Fix-DMA-unmap-error.patch | 78 ++++++++++++++++ ...h-Fix-issue-with-DMA-mapping-failure.patch | 93 +++++++++++++++++++ kernel.spec | 11 ++- 4 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 ibmveth-Checksum-offload-is-always-disabled.patch create mode 100644 ibmveth-Fix-DMA-unmap-error.patch create mode 100644 ibmveth-Fix-issue-with-DMA-mapping-failure.patch diff --git a/ibmveth-Checksum-offload-is-always-disabled.patch b/ibmveth-Checksum-offload-is-always-disabled.patch new file mode 100644 index 000000000..9daee4113 --- /dev/null +++ b/ibmveth-Checksum-offload-is-always-disabled.patch @@ -0,0 +1,70 @@ +Path: news.gmane.org!not-for-mail +From: Anton Blanchard +Newsgroups: gmane.linux.network +Subject: [PATCH 3/4] ibmveth: Checksum offload is always disabled +Date: Thu, 08 Sep 2011 10:41:05 +1000 +Lines: 23 +Approved: news@gmane.org +Message-ID: <20110908004121.744925909@samba.org> +References: <20110908004102.355674129@samba.org> +NNTP-Posting-Host: lo.gmane.org +X-Trace: dough.gmane.org 1315442745 17939 80.91.229.12 (8 Sep 2011 00:45:45 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Thu, 8 Sep 2011 00:45:45 +0000 (UTC) +Cc: netdev@vger.kernel.org +To: Santiago Leon , + brking@linux.vnet.ibm.com, rcj@linux.vnet.ibm.com, + mirq-linux@rere.qmqm.pl +Original-X-From: netdev-owner@vger.kernel.org Thu Sep 08 02:45:39 2011 +Return-path: +Envelope-to: linux-netdev-2@lo.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1R1SkN-0001Tk-2c + for linux-netdev-2@lo.gmane.org; Thu, 08 Sep 2011 02:45:39 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1757675Ab1IHApb (ORCPT ); + Wed, 7 Sep 2011 20:45:31 -0400 +Original-Received: from ozlabs.org ([203.10.76.45]:45063 "EHLO ozlabs.org" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1757657Ab1IHAp1 (ORCPT ); + Wed, 7 Sep 2011 20:45:27 -0400 +Original-Received: from localhost (ppp121-44-79-234.lns20.syd6.internode.on.net [121.44.79.234]) + (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits)) + (Client did not present a certificate) + by ozlabs.org (Postfix) with ESMTPSA id 17FFBB6F98; + Thu, 8 Sep 2011 10:45:26 +1000 (EST) +X-Mailbox-Line: From anton@samba.org Thu Sep 8 10:41:21 2011 +User-Agent: quilt/0.48-1 +Content-Disposition: inline; filename=ibmveth_fix_csum.patch +Original-Sender: netdev-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org +Xref: news.gmane.org gmane.linux.network:205929 +Archived-At: + +Commit b9367bf3ee6d (net: ibmveth: convert to hw_features) reversed +a check in ibmveth_set_csum_offload that results in checksum offload +never being enabled. + +Signed-off-by: Anton Blanchard +Cc: # 3.0+ +--- + +Index: linux-build/drivers/net/ibmveth.c +=================================================================== +--- linux-build.orig/drivers/net/ibmveth.c 2011-09-01 16:02:12.198726425 +1000 ++++ linux-build/drivers/net/ibmveth.c 2011-09-01 16:05:37.282482851 +1000 +@@ -812,7 +812,7 @@ static int ibmveth_set_csum_offload(stru + } else + adapter->fw_ipv6_csum_support = data; + +- if (ret != H_SUCCESS || ret6 != H_SUCCESS) ++ if (ret == H_SUCCESS || ret6 == H_SUCCESS) + adapter->rx_csum = data; + else + rc1 = -EIO; + + diff --git a/ibmveth-Fix-DMA-unmap-error.patch b/ibmveth-Fix-DMA-unmap-error.patch new file mode 100644 index 000000000..b619a1677 --- /dev/null +++ b/ibmveth-Fix-DMA-unmap-error.patch @@ -0,0 +1,78 @@ +Path: news.gmane.org!not-for-mail +From: Anton Blanchard +Newsgroups: gmane.linux.network +Subject: [PATCH 1/4] ibmveth: Fix DMA unmap error +Date: Thu, 08 Sep 2011 10:41:03 +1000 +Lines: 32 +Approved: news@gmane.org +Message-ID: <20110908004121.570234962@samba.org> +References: <20110908004102.355674129@samba.org> +NNTP-Posting-Host: lo.gmane.org +X-Trace: dough.gmane.org 1315442763 18071 80.91.229.12 (8 Sep 2011 00:46:03 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Thu, 8 Sep 2011 00:46:03 +0000 (UTC) +Cc: netdev@vger.kernel.org +To: Santiago Leon , + brking@linux.vnet.ibm.com, rcj@linux.vnet.ibm.com +Original-X-From: netdev-owner@vger.kernel.org Thu Sep 08 02:45:56 2011 +Return-path: +Envelope-to: linux-netdev-2@lo.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1R1Ska-0001cA-40 + for linux-netdev-2@lo.gmane.org; Thu, 08 Sep 2011 02:45:52 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1757671Ab1IHAp3 (ORCPT ); + Wed, 7 Sep 2011 20:45:29 -0400 +Original-Received: from ozlabs.org ([203.10.76.45]:42999 "EHLO ozlabs.org" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1757658Ab1IHAp1 (ORCPT ); + Wed, 7 Sep 2011 20:45:27 -0400 +Original-Received: from localhost (ppp121-44-79-234.lns20.syd6.internode.on.net [121.44.79.234]) + (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits)) + (Client did not present a certificate) + by ozlabs.org (Postfix) with ESMTPSA id ACF33B6F8E; + Thu, 8 Sep 2011 10:45:24 +1000 (EST) +X-Mailbox-Line: From anton@samba.org Thu Sep 8 10:41:21 2011 +User-Agent: quilt/0.48-1 +Content-Disposition: inline; filename=ibmveth_1.patch +Original-Sender: netdev-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org +Xref: news.gmane.org gmane.linux.network:205933 +Archived-At: + +From: Brian King + +Commit 6e8ab30ec677 (ibmveth: Add scatter-gather support) introduced a +DMA mapping API inconsistency resulting in dma_unmap_page getting +called on memory mapped via dma_map_single. This was seen when +CONFIG_DMA_API_DEBUG was enabled. Fix up this API usage inconsistency. + +Signed-off-by: Brian King +Acked-by: Anton Blanchard +Cc: # v2.6.37+ +--- + +Index: linux-build/drivers/net/ibmveth.c +=================================================================== +--- linux-build.orig/drivers/net/ibmveth.c 2011-09-08 08:00:16.842856634 +1000 ++++ linux-build/drivers/net/ibmveth.c 2011-09-08 09:45:43.163851274 +1000 +@@ -1026,7 +1026,12 @@ retry_bounce: + netdev->stats.tx_bytes += skb->len; + } + +- for (i = 0; i < skb_shinfo(skb)->nr_frags + 1; i++) ++ dma_unmap_single(&adapter->vdev->dev, ++ descs[0].fields.address, ++ descs[0].fields.flags_len & IBMVETH_BUF_LEN_MASK, ++ DMA_TO_DEVICE); ++ ++ for (i = 1; i < skb_shinfo(skb)->nr_frags + 1; i++) + dma_unmap_page(&adapter->vdev->dev, descs[i].fields.address, + descs[i].fields.flags_len & IBMVETH_BUF_LEN_MASK, + DMA_TO_DEVICE); + + diff --git a/ibmveth-Fix-issue-with-DMA-mapping-failure.patch b/ibmveth-Fix-issue-with-DMA-mapping-failure.patch new file mode 100644 index 000000000..af2d834c3 --- /dev/null +++ b/ibmveth-Fix-issue-with-DMA-mapping-failure.patch @@ -0,0 +1,93 @@ +Path: news.gmane.org!not-for-mail +From: Anton Blanchard +Newsgroups: gmane.linux.network +Subject: [PATCH 2/4] ibmveth: Fix issue with DMA mapping failure +Date: Thu, 08 Sep 2011 10:41:04 +1000 +Lines: 47 +Approved: news@gmane.org +Message-ID: <20110908004121.669225190@samba.org> +References: <20110908004102.355674129@samba.org> +NNTP-Posting-Host: lo.gmane.org +X-Trace: dough.gmane.org 1315442760 18037 80.91.229.12 (8 Sep 2011 00:46:00 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Thu, 8 Sep 2011 00:46:00 +0000 (UTC) +Cc: netdev@vger.kernel.org +To: Santiago Leon , + brking@linux.vnet.ibm.com, rcj@linux.vnet.ibm.com +Original-X-From: netdev-owner@vger.kernel.org Thu Sep 08 02:45:55 2011 +Return-path: +Envelope-to: linux-netdev-2@lo.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1R1Ska-0001cA-M3 + for linux-netdev-2@lo.gmane.org; Thu, 08 Sep 2011 02:45:53 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1757665Ab1IHApa (ORCPT ); + Wed, 7 Sep 2011 20:45:30 -0400 +Original-Received: from ozlabs.org ([203.10.76.45]:60840 "EHLO ozlabs.org" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1757659Ab1IHAp1 (ORCPT ); + Wed, 7 Sep 2011 20:45:27 -0400 +Original-Received: from localhost (ppp121-44-79-234.lns20.syd6.internode.on.net [121.44.79.234]) + (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits)) + (Client did not present a certificate) + by ozlabs.org (Postfix) with ESMTPSA id 56E01B6F97; + Thu, 8 Sep 2011 10:45:25 +1000 (EST) +X-Mailbox-Line: From anton@samba.org Thu Sep 8 10:41:21 2011 +User-Agent: quilt/0.48-1 +Content-Disposition: inline; filename=ibmveth_dma_mapping_error.patch +Original-Sender: netdev-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org +Xref: news.gmane.org gmane.linux.network:205931 +Archived-At: + +descs[].fields.address is 32bit which truncates any dma mapping +errors so dma_mapping_error() fails to catch it. + +Use a dma_addr_t to do the comparison. With this patch I was able +to transfer many gigabytes of data with IOMMU fault injection set +at 10% probability. + +Signed-off-by: Anton Blanchard +Cc: # v2.6.37+ +--- + +Index: linux-build/drivers/net/ibmveth.c +=================================================================== +--- linux-build.orig/drivers/net/ibmveth.c 2011-09-01 15:01:18.066844039 +1000 ++++ linux-build/drivers/net/ibmveth.c 2011-09-01 15:03:34.299079796 +1000 +@@ -930,6 +930,7 @@ static netdev_tx_t ibmveth_start_xmit(st + union ibmveth_buf_desc descs[6]; + int last, i; + int force_bounce = 0; ++ dma_addr_t dma_addr; + + /* + * veth handles a maximum of 6 segments including the header, so +@@ -994,17 +995,16 @@ retry_bounce: + } + + /* Map the header */ +- descs[0].fields.address = dma_map_single(&adapter->vdev->dev, skb->data, +- skb_headlen(skb), +- DMA_TO_DEVICE); +- if (dma_mapping_error(&adapter->vdev->dev, descs[0].fields.address)) ++ dma_addr = dma_map_single(&adapter->vdev->dev, skb->data, ++ skb_headlen(skb), DMA_TO_DEVICE); ++ if (dma_mapping_error(&adapter->vdev->dev, dma_addr)) + goto map_failed; + + descs[0].fields.flags_len = desc_flags | skb_headlen(skb); ++ descs[0].fields.address = dma_addr; + + /* Map the frags */ + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { +- unsigned long dma_addr; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + dma_addr = dma_map_page(&adapter->vdev->dev, frag->page, + + diff --git a/kernel.spec b/kernel.spec index 0b9f3d779..7fd2c78b4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -731,6 +731,10 @@ Patch13008: add-macbookair41-btusb.patch Patch13009: hvcs_pi_buf_alloc.patch +Patch13010: ibmveth-Fix-DMA-unmap-error.patch +Patch13011: ibmveth-Fix-issue-with-DMA-mapping-failure.patch +Patch13012: ibmveth-Checksum-offload-is-always-disabled.patch + Patch20000: utrace.patch # Flattened devicetree support @@ -1351,6 +1355,10 @@ ApplyPatch add-macbookair41-btusb.patch ApplyPatch hvcs_pi_buf_alloc.patch +ApplyPatch ibmveth-Fix-DMA-unmap-error.patch +ApplyPatch ibmveth-Fix-issue-with-DMA-mapping-failure.patch +ApplyPatch ibmveth-Checksum-offload-is-always-disabled.patch + # utrace. ApplyPatch utrace.patch @@ -2056,6 +2064,7 @@ fi * Wed Sep 14 2011 Josh Boyer - Add support for Macbook Air 4,1 keyboard, trackpad, and bluetooth - Add patch to fix HVCS on ppc64 (rhbz 738096) +- Add various ibmveth driver fixes (rhbz 733766) * Tue Sep 13 2011 Adam Jackson - drm/i915: Shut the fbc messages up when drm.debug & 4 From dc3e1e56ab1b0b51a687b39db567131aee5297ad Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 14 Sep 2011 15:48:33 -0400 Subject: [PATCH 076/487] Enabled CONFIG_IP_VS_IPV6 (bz 738194) --- config-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 2d9887606..973a1be00 100644 --- a/config-generic +++ b/config-generic @@ -4305,7 +4305,7 @@ CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_MATCH_RECENT=m CONFIG_NETFILTER_XT_MATCH_SOCKET=m -# CONFIG_IP_VS_IPV6 is not set +CONFIG_IP_VS_IPV6=y CONFIG_NET_DSA=y CONFIG_NET_DSA_MV88E6060=y diff --git a/kernel.spec b/kernel.spec index 7fd2c78b4..c825aa9c9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2061,6 +2061,9 @@ fi # and build. %changelog +* Wed Sep 14 2011 Neil Horman +- Enable CONFIG_IP_VS_IPV6 (bz 738194) + * Wed Sep 14 2011 Josh Boyer - Add support for Macbook Air 4,1 keyboard, trackpad, and bluetooth - Add patch to fix HVCS on ppc64 (rhbz 738096) From 9d940d046e9b493a71c894fb77135feb2ae07ef9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 14 Sep 2011 16:12:02 -0400 Subject: [PATCH 077/487] Add patch to fix deadlock in ppc64 icswx code (rhbz 737984) --- kernel.spec | 7 +++ powerpc-Fix-deadlock-in-icswx-code.patch | 74 ++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 powerpc-Fix-deadlock-in-icswx-code.patch diff --git a/kernel.spec b/kernel.spec index c825aa9c9..526c56205 100644 --- a/kernel.spec +++ b/kernel.spec @@ -735,6 +735,8 @@ Patch13010: ibmveth-Fix-DMA-unmap-error.patch Patch13011: ibmveth-Fix-issue-with-DMA-mapping-failure.patch Patch13012: ibmveth-Checksum-offload-is-always-disabled.patch +Patch13013: powerpc-Fix-deadlock-in-icswx-code.patch + Patch20000: utrace.patch # Flattened devicetree support @@ -1359,6 +1361,8 @@ ApplyPatch ibmveth-Fix-DMA-unmap-error.patch ApplyPatch ibmveth-Fix-issue-with-DMA-mapping-failure.patch ApplyPatch ibmveth-Checksum-offload-is-always-disabled.patch +ApplyPatch powerpc-Fix-deadlock-in-icswx-code.patch + # utrace. ApplyPatch utrace.patch @@ -2061,6 +2065,9 @@ fi # and build. %changelog +* Wed Sep 14 2011 Josh Boyer +- Add patch to fix deadlock in ppc64 icswx (rhbz 737984) + * Wed Sep 14 2011 Neil Horman - Enable CONFIG_IP_VS_IPV6 (bz 738194) diff --git a/powerpc-Fix-deadlock-in-icswx-code.patch b/powerpc-Fix-deadlock-in-icswx-code.patch new file mode 100644 index 000000000..a2ce3cf76 --- /dev/null +++ b/powerpc-Fix-deadlock-in-icswx-code.patch @@ -0,0 +1,74 @@ +From patchwork Wed Sep 14 19:43:15 2011 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: powerpc: Fix deadlock in icswx code +Date: Wed, 14 Sep 2011 09:43:15 -0000 +From: Anton Blanchard +X-Patchwork-Id: 114701 +Message-Id: <20110915054315.5e5ae062@kryten> +To: benh@kernel.crashing.org, paulus@samba.org +Cc: linuxppc-dev@lists.ozlabs.org + +The icswx code introduced an A-B B-A deadlock: + + CPU0 CPU1 + ---- ---- +lock(&anon_vma->mutex); + lock(&mm->mmap_sem); + lock(&anon_vma->mutex); +lock(&mm->mmap_sem); + +Instead of using the mmap_sem to keep mm_users constant, take the +page table spinlock. + +Signed-off-by: Anton Blanchard +Cc: + +--- + + +diff --git a/arch/powerpc/mm/mmu_context_hash64.c b/arch/powerpc/mm/mmu_context_hash64.c +index 3bafc3d..4ff587e 100644 +--- a/arch/powerpc/mm/mmu_context_hash64.c ++++ b/arch/powerpc/mm/mmu_context_hash64.c +@@ -136,8 +136,8 @@ int use_cop(unsigned long acop, struct mm_struct *mm) + if (!mm || !acop) + return -EINVAL; + +- /* We need to make sure mm_users doesn't change */ +- down_read(&mm->mmap_sem); ++ /* The page_table_lock ensures mm_users won't change under us */ ++ spin_lock(&mm->page_table_lock); + spin_lock(mm->context.cop_lockp); + + if (mm->context.cop_pid == COP_PID_NONE) { +@@ -164,7 +164,7 @@ int use_cop(unsigned long acop, struct mm_struct *mm) + + out: + spin_unlock(mm->context.cop_lockp); +- up_read(&mm->mmap_sem); ++ spin_unlock(&mm->page_table_lock); + + return ret; + } +@@ -185,8 +185,8 @@ void drop_cop(unsigned long acop, struct mm_struct *mm) + if (WARN_ON_ONCE(!mm)) + return; + +- /* We need to make sure mm_users doesn't change */ +- down_read(&mm->mmap_sem); ++ /* The page_table_lock ensures mm_users won't change under us */ ++ spin_lock(&mm->page_table_lock); + spin_lock(mm->context.cop_lockp); + + mm->context.acop &= ~acop; +@@ -213,7 +213,7 @@ void drop_cop(unsigned long acop, struct mm_struct *mm) + } + + spin_unlock(mm->context.cop_lockp); +- up_read(&mm->mmap_sem); ++ spin_unlock(&mm->page_table_lock); + } + EXPORT_SYMBOL_GPL(drop_cop); + From 34c20229d7f87f298a1a5041106bb00706ba057b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 15 Sep 2011 10:16:34 -0400 Subject: [PATCH 078/487] Fix CVE-2011-3191 --- ...le-memory-corruption-in-CIFSFindNext.patch | 82 +++++++++++++++++++ kernel.spec | 9 ++ 2 files changed, 91 insertions(+) create mode 100644 cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch diff --git a/cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch b/cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch new file mode 100644 index 000000000..06fc5c74a --- /dev/null +++ b/cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch @@ -0,0 +1,82 @@ +Path: news.gmane.org!not-for-mail +From: Jeff Layton +Newsgroups: gmane.linux.kernel.cifs +Subject: [PATCH] cifs: fix possible memory corruption in CIFSFindNext +Date: Tue, 23 Aug 2011 07:21:28 -0400 +Lines: 37 +Approved: news@gmane.org +Message-ID: <1314098488-1547-1-git-send-email-jlayton@redhat.com> +NNTP-Posting-Host: lo.gmane.org +X-Trace: dough.gmane.org 1314098501 27164 80.91.229.12 (23 Aug 2011 11:21:41 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Tue, 23 Aug 2011 11:21:41 +0000 (UTC) +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, dcl-HN4QTLPn1qTvY7RNz7mR4EEOCMrvLtNR@public.gmane.org +To: smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org +Original-X-From: linux-cifs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Tue Aug 23 13:21:37 2011 +Return-path: +Envelope-to: glkc-linux-cifs-1dZseelyfdZg9hUCZPvPmw@public.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1Qvp33-0003JC-05 + for glkc-linux-cifs-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Tue, 23 Aug 2011 13:21:37 +0200 +Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand + id S1752435Ab1HWLVg (ORCPT ); + Tue, 23 Aug 2011 07:21:36 -0400 +Original-Received: from mail-gy0-f174.google.com ([209.85.160.174]:43114 "EHLO + mail-gy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1751065Ab1HWLVf (ORCPT + ); Tue, 23 Aug 2011 07:21:35 -0400 +Original-Received: by gya6 with SMTP id 6so4228912gya.19 + for ; Tue, 23 Aug 2011 04:21:35 -0700 (PDT) +Original-Received: by 10.101.144.18 with SMTP id w18mr3505731ann.133.1314098494691; + Tue, 23 Aug 2011 04:21:34 -0700 (PDT) +Original-Received: from salusa.poochiereds.net (cpe-075-177-182-191.nc.res.rr.com [75.177.182.191]) + by mx.google.com with ESMTPS id d33sm48355ano.35.2011.08.23.04.21.32 + (version=SSLv3 cipher=OTHER); + Tue, 23 Aug 2011 04:21:33 -0700 (PDT) +X-Mailer: git-send-email 1.7.6 +Original-Sender: linux-cifs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Xref: news.gmane.org gmane.linux.kernel.cifs:4006 +Archived-At: + +The name_len variable in CIFSFindNext is a signed int that gets set to +the resume_name_len in the cifs_search_info. The resume_name_len however +is unsigned and for some infolevels is populated directly from a 32 bit +value sent by the server. + +If the server sends a very large value for this, then that value could +look negative when converted to a signed int. That would make that +value pass the PATH_MAX check later in CIFSFindNext. The name_len would +then be used as a length value for a memcpy. It would then be treated +as unsigned again, and the memcpy scribbles over a ton of memory. + +Fix this by making the name_len an unsigned value in CIFSFindNext. + +Cc: +Reported-by: Darren Lavender +Signed-off-by: Jeff Layton +--- + fs/cifs/cifssmb.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c +index f4d0988..950464d 100644 +--- a/fs/cifs/cifssmb.c ++++ b/fs/cifs/cifssmb.c +@@ -4089,7 +4089,8 @@ int CIFSFindNext(const int xid, struct cifs_tcon *tcon, + T2_FNEXT_RSP_PARMS *parms; + char *response_data; + int rc = 0; +- int bytes_returned, name_len; ++ int bytes_returned; ++ unsigned int name_len; + __u16 params, byte_count; + + cFYI(1, "In FindNext"); +-- +1.7.6 + diff --git a/kernel.spec b/kernel.spec index 526c56205..49fb20d1d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -737,6 +737,9 @@ Patch13012: ibmveth-Checksum-offload-is-always-disabled.patch Patch13013: powerpc-Fix-deadlock-in-icswx-code.patch +# CVE-2011-3191 +Patch13014: cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch + Patch20000: utrace.patch # Flattened devicetree support @@ -1363,6 +1366,9 @@ ApplyPatch ibmveth-Checksum-offload-is-always-disabled.patch ApplyPatch powerpc-Fix-deadlock-in-icswx-code.patch +# CVE-2011-3191 +ApplyPatch cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch + # utrace. ApplyPatch utrace.patch @@ -2065,6 +2071,9 @@ fi # and build. %changelog +* Thu Sep 15 2011 Josh Boyer +- CVE-2011-3191: cifs: fix possible memory corruption in CIFSFindNext + * Wed Sep 14 2011 Josh Boyer - Add patch to fix deadlock in ppc64 icswx (rhbz 737984) From 9d984d002ac98d4b9ecda45cb26aced7b3f4c657 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 15 Sep 2011 14:01:12 -0400 Subject: [PATCH 079/487] Set CONFIG_MAX_ZONEORDER to 9 on ppc64 with 64K pages The previous setting of 13 caused build errors: In file included from include/linux/topology.h:32:0, from include/linux/sched.h:78, from arch/powerpc/kernel/asm-offsets.c:17: include/linux/mmzone.h:961:2: error: #error Allocator MAX_ORDER exceeds SECTION_SIZE make[1]: *** [arch/powerpc/kernel/asm-offsets.s] Error 1 --- config-powerpc64 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-powerpc64 b/config-powerpc64 index 9f042f46c..2bee4edbf 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -149,7 +149,7 @@ CONFIG_EDAC_CPC925=m CONFIG_FRAME_WARN=2048 CONFIG_PHYP_DUMP=y -CONFIG_FORCE_MAX_ZONEORDER=13 +CONFIG_FORCE_MAX_ZONEORDER=9 CONFIG_VIRTUALIZATION=y CONFIG_VSX=y From 10328f76dcdbbc95ed3bfdc04103aaa414fb2c2e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 16 Sep 2011 07:47:40 -0400 Subject: [PATCH 080/487] Add patch to fix deadlock in ipw2x00 (rhbz 738387) Also adjust %files list to not include x86-only binaries on non-x86 arches in kernel-tools --- ipw2x00-fix-rtnl-mutex-deadlock.patch | 224 ++++++++++++++++++++++++++ kernel.spec | 12 +- 2 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 ipw2x00-fix-rtnl-mutex-deadlock.patch diff --git a/ipw2x00-fix-rtnl-mutex-deadlock.patch b/ipw2x00-fix-rtnl-mutex-deadlock.patch new file mode 100644 index 000000000..3c98bc2b8 --- /dev/null +++ b/ipw2x00-fix-rtnl-mutex-deadlock.patch @@ -0,0 +1,224 @@ +Path: news.gmane.org!not-for-mail +From: Stanislaw Gruszka +Newsgroups: gmane.linux.kernel.wireless.general +Subject: [PATCH] ipw2x00: fix rtnl mutex deadlock +Date: Wed, 14 Sep 2011 16:47:50 +0200 +Lines: 173 +Approved: news@gmane.org +Message-ID: <1316011670-6787-1-git-send-email-sgruszka@redhat.com> +NNTP-Posting-Host: lo.gmane.org +X-Trace: dough.gmane.org 1316011688 20989 80.91.229.12 (14 Sep 2011 14:48:08 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Wed, 14 Sep 2011 14:48:08 +0000 (UTC) +Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, + Andrew Morton , + "Rafael J. Wysocki" , + Maciej Rutecki , + Michael Witten , + Witold Baryluk , + Stanislaw Gruszka +To: "John W. Linville" +Original-X-From: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Wed Sep 14 16:48:02 2011 +Return-path: +Envelope-to: glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1R3qkr-0005Xu-KZ + for glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Wed, 14 Sep 2011 16:48:02 +0200 +Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand + id S1755562Ab1INOr7 (ORCPT + ); + Wed, 14 Sep 2011 10:47:59 -0400 +Original-Received: from mx1.redhat.com ([209.132.183.28]:50585 "EHLO mx1.redhat.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1751756Ab1INOr7 (ORCPT ); + Wed, 14 Sep 2011 10:47:59 -0400 +Original-Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p8EEldiu028562 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Wed, 14 Sep 2011 10:47:40 -0400 +Original-Received: from localhost (dhcp-27-35.brq.redhat.com [10.34.27.35]) + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p8EElaD3010274; + Wed, 14 Sep 2011 10:47:37 -0400 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +Original-Sender: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Xref: news.gmane.org gmane.linux.kernel.wireless.general:77103 +Archived-At: + +This fix regression introduced by: + +commit: ecb4433550f0620f3d1471ae7099037ede30a91e +Author: Stanislaw Gruszka +Date: Fri Aug 12 14:00:59 2011 +0200 + + mac80211: fix suspend/resume races with unregister hw + +Above commit add rtnl_lock() into wiphy_register(), what cause deadlock +when initializing ipw2x00 driver, which itself call wiphy_register() +from register_netdev() internal callback with rtnl mutex taken. + +To fix move wiphy_register() outside register_netdev(). This solution +have side effect of not creating /sys/class/net/wlanX/phy80211 link, +but that's a minor issue we can live with. + +Bisected-by: Witold Baryluk +Bisected-by: Michael Witten +Tested-by: Witold Baryluk +Tested-by: Michael Witten +Signed-off-by: Stanislaw Gruszka +--- +ecb4433550f0620f3d1471ae7099037ede30a91e was CCed to stable but we +drop it there, when bug was reported. So this patch is only intended +to 3.1 + + drivers/net/wireless/ipw2x00/ipw2100.c | 21 +++++++++++----- + drivers/net/wireless/ipw2x00/ipw2200.c | 39 +++++++++++++++++++++---------- + 2 files changed, 40 insertions(+), 20 deletions(-) + +diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c +index 3774dd0..ef9ad79 100644 +--- a/drivers/net/wireless/ipw2x00/ipw2100.c ++++ b/drivers/net/wireless/ipw2x00/ipw2100.c +@@ -1903,15 +1903,17 @@ static void ipw2100_down(struct ipw2100_priv *priv) + static int ipw2100_net_init(struct net_device *dev) + { + struct ipw2100_priv *priv = libipw_priv(dev); ++ ++ return ipw2100_up(priv, 1); ++} ++ ++static int ipw2100_wdev_init(struct net_device *dev) ++{ ++ struct ipw2100_priv *priv = libipw_priv(dev); + const struct libipw_geo *geo = libipw_get_geo(priv->ieee); + struct wireless_dev *wdev = &priv->ieee->wdev; +- int ret; + int i; + +- ret = ipw2100_up(priv, 1); +- if (ret) +- return ret; +- + memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN); + + /* fill-out priv->ieee->bg_band */ +@@ -6350,9 +6352,13 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + "Error calling register_netdev.\n"); + goto fail; + } ++ registered = 1; ++ ++ err = ipw2100_wdev_init(dev); ++ if (err) ++ goto fail; + + mutex_lock(&priv->action_mutex); +- registered = 1; + + IPW_DEBUG_INFO("%s: Bound to %s\n", dev->name, pci_name(pci_dev)); + +@@ -6389,7 +6395,8 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, + + fail_unlock: + mutex_unlock(&priv->action_mutex); +- ++ wiphy_unregister(priv->ieee->wdev.wiphy); ++ kfree(priv->ieee->bg_band.channels); + fail: + if (dev) { + if (registered) +diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c +index 87813c3..4ffebed 100644 +--- a/drivers/net/wireless/ipw2x00/ipw2200.c ++++ b/drivers/net/wireless/ipw2x00/ipw2200.c +@@ -11425,16 +11425,23 @@ static void ipw_bg_down(struct work_struct *work) + /* Called by register_netdev() */ + static int ipw_net_init(struct net_device *dev) + { ++ int rc = 0; ++ struct ipw_priv *priv = libipw_priv(dev); ++ ++ mutex_lock(&priv->mutex); ++ if (ipw_up(priv)) ++ rc = -EIO; ++ mutex_unlock(&priv->mutex); ++ ++ return rc; ++} ++ ++static int ipw_wdev_init(struct net_device *dev) ++{ + int i, rc = 0; + struct ipw_priv *priv = libipw_priv(dev); + const struct libipw_geo *geo = libipw_get_geo(priv->ieee); + struct wireless_dev *wdev = &priv->ieee->wdev; +- mutex_lock(&priv->mutex); +- +- if (ipw_up(priv)) { +- rc = -EIO; +- goto out; +- } + + memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN); + +@@ -11519,13 +11526,9 @@ static int ipw_net_init(struct net_device *dev) + set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); + + /* With that information in place, we can now register the wiphy... */ +- if (wiphy_register(wdev->wiphy)) { ++ if (wiphy_register(wdev->wiphy)) + rc = -EIO; +- goto out; +- } +- + out: +- mutex_unlock(&priv->mutex); + return rc; + } + +@@ -11832,14 +11835,22 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, + goto out_remove_sysfs; + } + ++ err = ipw_wdev_init(net_dev); ++ if (err) { ++ IPW_ERROR("failed to register wireless device\n"); ++ goto out_unregister_netdev; ++ } ++ + #ifdef CONFIG_IPW2200_PROMISCUOUS + if (rtap_iface) { + err = ipw_prom_alloc(priv); + if (err) { + IPW_ERROR("Failed to register promiscuous network " + "device (error %d).\n", err); +- unregister_netdev(priv->net_dev); +- goto out_remove_sysfs; ++ wiphy_unregister(priv->ieee->wdev.wiphy); ++ kfree(priv->ieee->a_band.channels); ++ kfree(priv->ieee->bg_band.channels); ++ goto out_unregister_netdev; + } + } + #endif +@@ -11851,6 +11862,8 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, + + return 0; + ++ out_unregister_netdev: ++ unregister_netdev(priv->net_dev); + out_remove_sysfs: + sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); + out_release_irq: +-- +1.7.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + diff --git a/kernel.spec b/kernel.spec index 49fb20d1d..8538a2437 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -740,6 +740,8 @@ Patch13013: powerpc-Fix-deadlock-in-icswx-code.patch # CVE-2011-3191 Patch13014: cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch +Patch13015: ipw2x00-fix-rtnl-mutex-deadlock.patch + Patch20000: utrace.patch # Flattened devicetree support @@ -1369,6 +1371,8 @@ ApplyPatch powerpc-Fix-deadlock-in-icswx-code.patch # CVE-2011-3191 ApplyPatch cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch +ApplyPatch ipw2x00-fix-rtnl-mutex-deadlock.patch + # utrace. ApplyPatch utrace.patch @@ -1987,8 +1991,10 @@ fi %ifarch %{cpupowerarchs} %{_bindir}/cpupower +%ifarch %{ix86} x86_64 %{_bindir}/centrino-decode %{_bindir}/powernow-k8-decode +%endif %{_libdir}/libcpupower.so.0 %{_libdir}/libcpupower.so.0.0.0 %{_unitdir}/cpupower.service @@ -2071,6 +2077,10 @@ fi # and build. %changelog +* Fri Sep 16 2011 Josh Boyer 3.1.0-0.rc6.git0.3.fc16 +- Add patch to fix deadlock in ipw2x00 (rhbz 738387) +- Fixup kernel-tools file section for ppc/ppc64 + * Thu Sep 15 2011 Josh Boyer - CVE-2011-3191: cifs: fix possible memory corruption in CIFSFindNext From b6064a6490f9a553577085dfd347962984d4008a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 20 Sep 2011 16:43:27 +1000 Subject: [PATCH 081/487] nouveau: pull in updates queued for 3.2, NVCF/NVD9 support --- drm-nouveau-updates.patch | 8527 ++++++++++++++++++++++++++++++++++++- kernel.spec | 5 +- 2 files changed, 8530 insertions(+), 2 deletions(-) diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index 607602cfc..d311d860d 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -1 +1,8526 @@ -nil +diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile +index 0583677..35ef5b1 100644 +--- a/drivers/gpu/drm/nouveau/Makefile ++++ b/drivers/gpu/drm/nouveau/Makefile +@@ -21,16 +21,17 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ + nv40_grctx.o nv50_grctx.o nvc0_grctx.o \ + nv84_crypt.o \ + nva3_copy.o nvc0_copy.o \ +- nv40_mpeg.o nv50_mpeg.o \ ++ nv31_mpeg.o nv50_mpeg.o \ + nv04_instmem.o nv50_instmem.o nvc0_instmem.o \ +- nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \ +- nv50_cursor.o nv50_display.o \ + nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ + nv04_crtc.o nv04_display.o nv04_cursor.o \ ++ nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \ ++ nv50_cursor.o nv50_display.o \ ++ nvd0_display.o \ + nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o \ + nv10_gpio.o nv50_gpio.o \ + nv50_calc.o \ +- nv04_pm.o nv50_pm.o nva3_pm.o \ ++ nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \ + nv50_vram.o nvc0_vram.o \ + nv50_vm.o nvc0_vm.o + +diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c +index 00a55df..fa22b28 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c ++++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c +@@ -37,8 +37,10 @@ + #include "nouveau_drv.h" + #include "nouveau_drm.h" + #include "nouveau_reg.h" ++#include "nouveau_encoder.h" + +-static int nv40_get_intensity(struct backlight_device *bd) ++static int ++nv40_get_intensity(struct backlight_device *bd) + { + struct drm_device *dev = bl_get_data(bd); + int val = (nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK) +@@ -47,7 +49,8 @@ static int nv40_get_intensity(struct backlight_device *bd) + return val; + } + +-static int nv40_set_intensity(struct backlight_device *bd) ++static int ++nv40_set_intensity(struct backlight_device *bd) + { + struct drm_device *dev = bl_get_data(bd); + int val = bd->props.brightness; +@@ -65,30 +68,8 @@ static const struct backlight_ops nv40_bl_ops = { + .update_status = nv40_set_intensity, + }; + +-static int nv50_get_intensity(struct backlight_device *bd) +-{ +- struct drm_device *dev = bl_get_data(bd); +- +- return nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT); +-} +- +-static int nv50_set_intensity(struct backlight_device *bd) +-{ +- struct drm_device *dev = bl_get_data(bd); +- int val = bd->props.brightness; +- +- nv_wr32(dev, NV50_PDISPLAY_SOR_BACKLIGHT, +- val | NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE); +- return 0; +-} +- +-static const struct backlight_ops nv50_bl_ops = { +- .options = BL_CORE_SUSPENDRESUME, +- .get_brightness = nv50_get_intensity, +- .update_status = nv50_set_intensity, +-}; +- +-static int nouveau_nv40_backlight_init(struct drm_connector *connector) ++static int ++nv40_backlight_init(struct drm_connector *connector) + { + struct drm_device *dev = connector->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; +@@ -113,34 +94,129 @@ static int nouveau_nv40_backlight_init(struct drm_connector *connector) + return 0; + } + +-static int nouveau_nv50_backlight_init(struct drm_connector *connector) ++static int ++nv50_get_intensity(struct backlight_device *bd) ++{ ++ struct nouveau_encoder *nv_encoder = bl_get_data(bd); ++ struct drm_device *dev = nv_encoder->base.base.dev; ++ int or = nv_encoder->or; ++ u32 div = 1025; ++ u32 val; ++ ++ val = nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(or)); ++ val &= NV50_PDISP_SOR_PWM_CTL_VAL; ++ return ((val * 100) + (div / 2)) / div; ++} ++ ++static int ++nv50_set_intensity(struct backlight_device *bd) ++{ ++ struct nouveau_encoder *nv_encoder = bl_get_data(bd); ++ struct drm_device *dev = nv_encoder->base.base.dev; ++ int or = nv_encoder->or; ++ u32 div = 1025; ++ u32 val = (bd->props.brightness * div) / 100; ++ ++ nv_wr32(dev, NV50_PDISP_SOR_PWM_CTL(or), ++ NV50_PDISP_SOR_PWM_CTL_NEW | val); ++ return 0; ++} ++ ++static const struct backlight_ops nv50_bl_ops = { ++ .options = BL_CORE_SUSPENDRESUME, ++ .get_brightness = nv50_get_intensity, ++ .update_status = nv50_set_intensity, ++}; ++ ++static int ++nva3_get_intensity(struct backlight_device *bd) ++{ ++ struct nouveau_encoder *nv_encoder = bl_get_data(bd); ++ struct drm_device *dev = nv_encoder->base.base.dev; ++ int or = nv_encoder->or; ++ u32 div, val; ++ ++ div = nv_rd32(dev, NV50_PDISP_SOR_PWM_DIV(or)); ++ val = nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(or)); ++ val &= NVA3_PDISP_SOR_PWM_CTL_VAL; ++ if (div && div >= val) ++ return ((val * 100) + (div / 2)) / div; ++ ++ return 100; ++} ++ ++static int ++nva3_set_intensity(struct backlight_device *bd) ++{ ++ struct nouveau_encoder *nv_encoder = bl_get_data(bd); ++ struct drm_device *dev = nv_encoder->base.base.dev; ++ int or = nv_encoder->or; ++ u32 div, val; ++ ++ div = nv_rd32(dev, NV50_PDISP_SOR_PWM_DIV(or)); ++ val = (bd->props.brightness * div) / 100; ++ if (div) { ++ nv_wr32(dev, NV50_PDISP_SOR_PWM_CTL(or), val | ++ NV50_PDISP_SOR_PWM_CTL_NEW | ++ NVA3_PDISP_SOR_PWM_CTL_UNK); ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++static const struct backlight_ops nva3_bl_ops = { ++ .options = BL_CORE_SUSPENDRESUME, ++ .get_brightness = nva3_get_intensity, ++ .update_status = nva3_set_intensity, ++}; ++ ++static int ++nv50_backlight_init(struct drm_connector *connector) + { + struct drm_device *dev = connector->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_encoder *nv_encoder; + struct backlight_properties props; + struct backlight_device *bd; ++ const struct backlight_ops *ops; ++ ++ nv_encoder = find_encoder(connector, OUTPUT_LVDS); ++ if (!nv_encoder) { ++ nv_encoder = find_encoder(connector, OUTPUT_DP); ++ if (!nv_encoder) ++ return -ENODEV; ++ } + +- if (!nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT)) ++ if (!nv_rd32(dev, NV50_PDISP_SOR_PWM_CTL(nv_encoder->or))) + return 0; + ++ if (dev_priv->chipset <= 0xa0 || ++ dev_priv->chipset == 0xaa || ++ dev_priv->chipset == 0xac) ++ ops = &nv50_bl_ops; ++ else ++ ops = &nva3_bl_ops; ++ + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; +- props.max_brightness = 1025; +- bd = backlight_device_register("nv_backlight", &connector->kdev, dev, +- &nv50_bl_ops, &props); ++ props.max_brightness = 100; ++ bd = backlight_device_register("nv_backlight", &connector->kdev, ++ nv_encoder, ops, &props); + if (IS_ERR(bd)) + return PTR_ERR(bd); + + dev_priv->backlight = bd; +- bd->props.brightness = nv50_get_intensity(bd); ++ bd->props.brightness = bd->ops->get_brightness(bd); + backlight_update_status(bd); + return 0; + } + +-int nouveau_backlight_init(struct drm_connector *connector) ++int ++nouveau_backlight_init(struct drm_device *dev) + { +- struct drm_device *dev = connector->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct drm_connector *connector; + + #ifdef CONFIG_ACPI + if (acpi_video_backlight_support()) { +@@ -150,21 +226,28 @@ int nouveau_backlight_init(struct drm_connector *connector) + } + #endif + +- switch (dev_priv->card_type) { +- case NV_40: +- return nouveau_nv40_backlight_init(connector); +- case NV_50: +- return nouveau_nv50_backlight_init(connector); +- default: +- break; ++ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { ++ if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && ++ connector->connector_type != DRM_MODE_CONNECTOR_eDP) ++ continue; ++ ++ switch (dev_priv->card_type) { ++ case NV_40: ++ return nv40_backlight_init(connector); ++ case NV_50: ++ return nv50_backlight_init(connector); ++ default: ++ break; ++ } + } + ++ + return 0; + } + +-void nouveau_backlight_exit(struct drm_connector *connector) ++void ++nouveau_backlight_exit(struct drm_device *dev) + { +- struct drm_device *dev = connector->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->backlight) { +diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c +index b311fab..032a820 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_bios.c ++++ b/drivers/gpu/drm/nouveau/nouveau_bios.c +@@ -296,6 +296,11 @@ munge_reg(struct nvbios *bios, uint32_t reg) + if (dev_priv->card_type < NV_50) + return reg; + ++ if (reg & 0x80000000) { ++ BUG_ON(bios->display.crtc < 0); ++ reg += bios->display.crtc * 0x800; ++ } ++ + if (reg & 0x40000000) { + BUG_ON(!dcbent); + +@@ -304,7 +309,7 @@ munge_reg(struct nvbios *bios, uint32_t reg) + reg += 0x00000080; + } + +- reg &= ~0x60000000; ++ reg &= ~0xe0000000; + return reg; + } + +@@ -1174,22 +1179,19 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + * + */ + +- struct bit_displayport_encoder_table *dpe = NULL; + struct dcb_entry *dcb = bios->display.output; + struct drm_device *dev = bios->dev; + uint8_t cond = bios->data[offset + 1]; +- int dummy; ++ uint8_t *table, *entry; + + BIOSLOG(bios, "0x%04X: subop 0x%02X\n", offset, cond); + + if (!iexec->execute) + return 3; + +- dpe = nouveau_bios_dp_table(dev, dcb, &dummy); +- if (!dpe) { +- NV_ERROR(dev, "0x%04X: INIT_3A: no encoder table!!\n", offset); ++ table = nouveau_dp_bios_data(dev, dcb, &entry); ++ if (!table) + return 3; +- } + + switch (cond) { + case 0: +@@ -1203,7 +1205,7 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + break; + case 1: + case 2: +- if (!(dpe->unknown & cond)) ++ if (!(entry[5] & cond)) + iexec->execute = false; + break; + case 5: +@@ -3221,6 +3223,49 @@ init_8d(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + return 1; + } + ++static void ++init_gpio_unknv50(struct nvbios *bios, struct dcb_gpio_entry *gpio) ++{ ++ const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; ++ u32 r, s, v; ++ ++ /* Not a clue, needs de-magicing */ ++ r = nv50_gpio_ctl[gpio->line >> 4]; ++ s = (gpio->line & 0x0f); ++ v = bios_rd32(bios, r) & ~(0x00010001 << s); ++ switch ((gpio->entry & 0x06000000) >> 25) { ++ case 1: ++ v |= (0x00000001 << s); ++ break; ++ case 2: ++ v |= (0x00010000 << s); ++ break; ++ default: ++ break; ++ } ++ ++ bios_wr32(bios, r, v); ++} ++ ++static void ++init_gpio_unknvd0(struct nvbios *bios, struct dcb_gpio_entry *gpio) ++{ ++ u32 v, i; ++ ++ v = bios_rd32(bios, 0x00d610 + (gpio->line * 4)); ++ v &= 0xffffff00; ++ v |= (gpio->entry & 0x00ff0000) >> 16; ++ bios_wr32(bios, 0x00d610 + (gpio->line * 4), v); ++ ++ i = (gpio->entry & 0x1f000000) >> 24; ++ if (i) { ++ v = bios_rd32(bios, 0x00d640 + ((i - 1) * 4)); ++ v &= 0xffffff00; ++ v |= gpio->line; ++ bios_wr32(bios, 0x00d640 + ((i - 1) * 4), v); ++ } ++} ++ + static int + init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + { +@@ -3235,7 +3280,6 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + + struct drm_nouveau_private *dev_priv = bios->dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; +- const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; + int i; + + if (dev_priv->card_type < NV_50) { +@@ -3248,33 +3292,20 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + + for (i = 0; i < bios->dcb.gpio.entries; i++) { + struct dcb_gpio_entry *gpio = &bios->dcb.gpio.entry[i]; +- uint32_t r, s, v; + + BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry); + + BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n", + offset, gpio->tag, gpio->state_default); +- if (bios->execute) +- pgpio->set(bios->dev, gpio->tag, gpio->state_default); + +- /* The NVIDIA binary driver doesn't appear to actually do +- * any of this, my VBIOS does however. +- */ +- /* Not a clue, needs de-magicing */ +- r = nv50_gpio_ctl[gpio->line >> 4]; +- s = (gpio->line & 0x0f); +- v = bios_rd32(bios, r) & ~(0x00010001 << s); +- switch ((gpio->entry & 0x06000000) >> 25) { +- case 1: +- v |= (0x00000001 << s); +- break; +- case 2: +- v |= (0x00010000 << s); +- break; +- default: +- break; +- } +- bios_wr32(bios, r, v); ++ if (!bios->execute) ++ continue; ++ ++ pgpio->set(bios->dev, gpio->tag, gpio->state_default); ++ if (dev_priv->card_type < NV_D0) ++ init_gpio_unknv50(bios, gpio); ++ else ++ init_gpio_unknvd0(bios, gpio); + } + + return 1; +@@ -3737,6 +3768,10 @@ parse_init_table(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + int count = 0, i, ret; + uint8_t id; + ++ /* catch NULL script pointers */ ++ if (offset == 0) ++ return 0; ++ + /* + * Loop until INIT_DONE causes us to break out of the loop + * (or until offset > bios length just in case... ) +@@ -4389,86 +4424,37 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b + return 0; + } + +-static uint8_t * +-bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent, +- uint16_t record, int record_len, int record_nr, +- bool match_link) ++/* BIT 'U'/'d' table encoder subtables have hashes matching them to ++ * a particular set of encoders. ++ * ++ * This function returns true if a particular DCB entry matches. ++ */ ++bool ++bios_encoder_match(struct dcb_entry *dcb, u32 hash) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nvbios *bios = &dev_priv->vbios; +- uint32_t entry; +- uint16_t table; +- int i, v; ++ if ((hash & 0x000000f0) != (dcb->location << 4)) ++ return false; ++ if ((hash & 0x0000000f) != dcb->type) ++ return false; ++ if (!(hash & (dcb->or << 16))) ++ return false; + +- switch (dcbent->type) { ++ switch (dcb->type) { + case OUTPUT_TMDS: + case OUTPUT_LVDS: + case OUTPUT_DP: +- break; +- default: +- match_link = false; +- break; +- } +- +- for (i = 0; i < record_nr; i++, record += record_len) { +- table = ROM16(bios->data[record]); +- if (!table) +- continue; +- entry = ROM32(bios->data[table]); +- +- if (match_link) { +- v = (entry & 0x00c00000) >> 22; +- if (!(v & dcbent->sorconf.link)) +- continue; ++ if (hash & 0x00c00000) { ++ if (!(hash & (dcb->sorconf.link << 22))) ++ return false; + } +- +- v = (entry & 0x000f0000) >> 16; +- if (!(v & dcbent->or)) +- continue; +- +- v = (entry & 0x000000f0) >> 4; +- if (v != dcbent->location) +- continue; +- +- v = (entry & 0x0000000f); +- if (v != dcbent->type) +- continue; +- +- return &bios->data[table]; +- } +- +- return NULL; +-} +- +-void * +-nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent, +- int *length) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nvbios *bios = &dev_priv->vbios; +- uint8_t *table; +- +- if (!bios->display.dp_table_ptr) { +- NV_ERROR(dev, "No pointer to DisplayPort table\n"); +- return NULL; +- } +- table = &bios->data[bios->display.dp_table_ptr]; +- +- if (table[0] != 0x20 && table[0] != 0x21) { +- NV_ERROR(dev, "DisplayPort table version 0x%02x unknown\n", +- table[0]); +- return NULL; ++ default: ++ return true; + } +- +- *length = table[4]; +- return bios_output_config_match(dev, dcbent, +- bios->display.dp_table_ptr + table[1], +- table[2], table[3], table[0] >= 0x21); + } + + int +-nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, +- uint32_t sub, int pxclk) ++nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, ++ struct dcb_entry *dcbent, int crtc) + { + /* + * The display script table is located by the BIT 'U' table. +@@ -4498,7 +4484,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, + uint8_t *table = &bios->data[bios->display.script_table_ptr]; + uint8_t *otable = NULL; + uint16_t script; +- int i = 0; ++ int i; + + if (!bios->display.script_table_ptr) { + NV_ERROR(dev, "No pointer to output script table\n"); +@@ -4550,30 +4536,33 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, + + NV_DEBUG_KMS(dev, "Searching for output entry for %d %d %d\n", + dcbent->type, dcbent->location, dcbent->or); +- otable = bios_output_config_match(dev, dcbent, table[1] + +- bios->display.script_table_ptr, +- table[2], table[3], table[0] >= 0x21); ++ for (i = 0; i < table[3]; i++) { ++ otable = ROMPTR(bios, table[table[1] + (i * table[2])]); ++ if (otable && bios_encoder_match(dcbent, ROM32(otable[0]))) ++ break; ++ } ++ + if (!otable) { + NV_DEBUG_KMS(dev, "failed to match any output table\n"); + return 1; + } + +- if (pxclk < -2 || pxclk > 0) { ++ if (pclk < -2 || pclk > 0) { + /* Try to find matching script table entry */ + for (i = 0; i < otable[5]; i++) { +- if (ROM16(otable[table[4] + i*6]) == sub) ++ if (ROM16(otable[table[4] + i*6]) == type) + break; + } + + if (i == otable[5]) { + NV_ERROR(dev, "Table 0x%04x not found for %d/%d, " + "using first\n", +- sub, dcbent->type, dcbent->or); ++ type, dcbent->type, dcbent->or); + i = 0; + } + } + +- if (pxclk == 0) { ++ if (pclk == 0) { + script = ROM16(otable[6]); + if (!script) { + NV_DEBUG_KMS(dev, "output script 0 not found\n"); +@@ -4581,9 +4570,9 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, + } + + NV_DEBUG_KMS(dev, "0x%04X: parsing output script 0\n", script); +- nouveau_bios_run_init_table(dev, script, dcbent); ++ nouveau_bios_run_init_table(dev, script, dcbent, crtc); + } else +- if (pxclk == -1) { ++ if (pclk == -1) { + script = ROM16(otable[8]); + if (!script) { + NV_DEBUG_KMS(dev, "output script 1 not found\n"); +@@ -4591,9 +4580,9 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, + } + + NV_DEBUG_KMS(dev, "0x%04X: parsing output script 1\n", script); +- nouveau_bios_run_init_table(dev, script, dcbent); ++ nouveau_bios_run_init_table(dev, script, dcbent, crtc); + } else +- if (pxclk == -2) { ++ if (pclk == -2) { + if (table[4] >= 12) + script = ROM16(otable[10]); + else +@@ -4604,31 +4593,31 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, + } + + NV_DEBUG_KMS(dev, "0x%04X: parsing output script 2\n", script); +- nouveau_bios_run_init_table(dev, script, dcbent); ++ nouveau_bios_run_init_table(dev, script, dcbent, crtc); + } else +- if (pxclk > 0) { ++ if (pclk > 0) { + script = ROM16(otable[table[4] + i*6 + 2]); + if (script) +- script = clkcmptable(bios, script, pxclk); ++ script = clkcmptable(bios, script, pclk); + if (!script) { + NV_DEBUG_KMS(dev, "clock script 0 not found\n"); + return 1; + } + + NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 0\n", script); +- nouveau_bios_run_init_table(dev, script, dcbent); ++ nouveau_bios_run_init_table(dev, script, dcbent, crtc); + } else +- if (pxclk < 0) { ++ if (pclk < 0) { + script = ROM16(otable[table[4] + i*6 + 4]); + if (script) +- script = clkcmptable(bios, script, -pxclk); ++ script = clkcmptable(bios, script, -pclk); + if (!script) { + NV_DEBUG_KMS(dev, "clock script 1 not found\n"); + return 1; + } + + NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 1\n", script); +- nouveau_bios_run_init_table(dev, script, dcbent); ++ nouveau_bios_run_init_table(dev, script, dcbent, crtc); + } + + return 0; +@@ -5478,14 +5467,6 @@ parse_bit_U_tbl_entry(struct drm_device *dev, struct nvbios *bios, + return 0; + } + +-static int +-parse_bit_displayport_tbl_entry(struct drm_device *dev, struct nvbios *bios, +- struct bit_entry *bitentry) +-{ +- bios->display.dp_table_ptr = ROM16(bios->data[bitentry->offset]); +- return 0; +-} +- + struct bit_table { + const char id; + int (* const parse_fn)(struct drm_device *, struct nvbios *, struct bit_entry *); +@@ -5559,7 +5540,6 @@ parse_bit_structure(struct nvbios *bios, const uint16_t bitoffset) + parse_bit_table(bios, bitoffset, &BIT_TABLE('L', lvds)); + parse_bit_table(bios, bitoffset, &BIT_TABLE('T', tmds)); + parse_bit_table(bios, bitoffset, &BIT_TABLE('U', U)); +- parse_bit_table(bios, bitoffset, &BIT_TABLE('d', displayport)); + + return 0; + } +@@ -5884,9 +5864,15 @@ parse_dcb_gpio_table(struct nvbios *bios) + } + + e->line = (e->entry & 0x0000001f) >> 0; +- e->state_default = (e->entry & 0x01000000) >> 24; +- e->state[0] = (e->entry & 0x18000000) >> 27; +- e->state[1] = (e->entry & 0x60000000) >> 29; ++ if (gpio[0] == 0x40) { ++ e->state_default = (e->entry & 0x01000000) >> 24; ++ e->state[0] = (e->entry & 0x18000000) >> 27; ++ e->state[1] = (e->entry & 0x60000000) >> 29; ++ } else { ++ e->state_default = (e->entry & 0x00000080) >> 7; ++ e->state[0] = (entry[4] >> 4) & 3; ++ e->state[1] = (entry[4] >> 6) & 3; ++ } + } + } + +@@ -6156,7 +6142,14 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, + } + case OUTPUT_DP: + entry->dpconf.sor.link = (conf & 0x00000030) >> 4; +- entry->dpconf.link_bw = (conf & 0x00e00000) >> 21; ++ switch ((conf & 0x00e00000) >> 21) { ++ case 0: ++ entry->dpconf.link_bw = 162000; ++ break; ++ default: ++ entry->dpconf.link_bw = 270000; ++ break; ++ } + switch ((conf & 0x0f000000) >> 24) { + case 0xf: + entry->dpconf.link_nr = 4; +@@ -6769,7 +6762,7 @@ uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev) + + void + nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, +- struct dcb_entry *dcbent) ++ struct dcb_entry *dcbent, int crtc) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->vbios; +@@ -6777,11 +6770,22 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, + + spin_lock_bh(&bios->lock); + bios->display.output = dcbent; ++ bios->display.crtc = crtc; + parse_init_table(bios, table, &iexec); + bios->display.output = NULL; + spin_unlock_bh(&bios->lock); + } + ++void ++nouveau_bios_init_exec(struct drm_device *dev, uint16_t table) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nvbios *bios = &dev_priv->vbios; ++ struct init_exec iexec = { true, false }; ++ ++ parse_init_table(bios, table, &iexec); ++} ++ + static bool NVInitVBIOS(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +@@ -6863,9 +6867,8 @@ nouveau_run_vbios_init(struct drm_device *dev) + + if (dev_priv->card_type >= NV_50) { + for (i = 0; i < bios->dcb.entries; i++) { +- nouveau_bios_run_display_table(dev, +- &bios->dcb.entry[i], +- 0, 0); ++ nouveau_bios_run_display_table(dev, 0, 0, ++ &bios->dcb.entry[i], -1); + } + } + +diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h +index 050c314..8adb69e 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_bios.h ++++ b/drivers/gpu/drm/nouveau/nouveau_bios.h +@@ -289,8 +289,8 @@ struct nvbios { + + struct { + struct dcb_entry *output; ++ int crtc; + uint16_t script_table_ptr; +- uint16_t dp_table_ptr; + } display; + + struct { +diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c +index 890d50e..7226f41 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_bo.c ++++ b/drivers/gpu/drm/nouveau/nouveau_bo.c +@@ -956,7 +956,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) + break; + } + +- if (dev_priv->card_type == NV_C0) ++ if (dev_priv->card_type >= NV_C0) + page_shift = node->page_shift; + else + page_shift = 12; +diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c +index b0d753f..a319d56 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_channel.c ++++ b/drivers/gpu/drm/nouveau/nouveau_channel.c +@@ -411,13 +411,17 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, + return ret; + init->channel = chan->id; + +- if (chan->dma.ib_max) +- init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM | +- NOUVEAU_GEM_DOMAIN_GART; +- else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM) ++ if (nouveau_vram_pushbuf == 0) { ++ if (chan->dma.ib_max) ++ init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM | ++ NOUVEAU_GEM_DOMAIN_GART; ++ else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM) ++ init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM; ++ else ++ init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART; ++ } else { + init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM; +- else +- init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART; ++ } + + if (dev_priv->card_type < NV_C0) { + init->subchan[0].handle = NvM2MF; +diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c +index 939d4df..e0d275e 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_connector.c ++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c +@@ -39,7 +39,7 @@ + + static void nouveau_connector_hotplug(void *, int); + +-static struct nouveau_encoder * ++struct nouveau_encoder * + find_encoder(struct drm_connector *connector, int type) + { + struct drm_device *dev = connector->dev; +@@ -116,10 +116,6 @@ nouveau_connector_destroy(struct drm_connector *connector) + nouveau_connector_hotplug, connector); + } + +- if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS || +- connector->connector_type == DRM_MODE_CONNECTOR_eDP) +- nouveau_backlight_exit(connector); +- + kfree(nv_connector->edid); + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); +@@ -712,11 +708,8 @@ nouveau_connector_mode_valid(struct drm_connector *connector, + case OUTPUT_TV: + return get_slave_funcs(encoder)->mode_valid(encoder, mode); + case OUTPUT_DP: +- if (nv_encoder->dp.link_bw == DP_LINK_BW_2_7) +- max_clock = nv_encoder->dp.link_nr * 270000; +- else +- max_clock = nv_encoder->dp.link_nr * 162000; +- ++ max_clock = nv_encoder->dp.link_nr; ++ max_clock *= nv_encoder->dp.link_bw; + clock = clock * nouveau_connector_bpp(connector) / 8; + break; + default: +@@ -871,7 +864,6 @@ nouveau_connector_create(struct drm_device *dev, int index) + dev->mode_config.scaling_mode_property, + nv_connector->scaling_mode); + } +- connector->polled = DRM_CONNECTOR_POLL_CONNECT; + /* fall-through */ + case DCB_CONNECTOR_TV_0: + case DCB_CONNECTOR_TV_1: +@@ -888,27 +880,20 @@ nouveau_connector_create(struct drm_device *dev, int index) + dev->mode_config.dithering_mode_property, + nv_connector->use_dithering ? + DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF); +- +- if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS) { +- if (dev_priv->card_type >= NV_50) +- connector->polled = DRM_CONNECTOR_POLL_HPD; +- else +- connector->polled = DRM_CONNECTOR_POLL_CONNECT; +- } + break; + } + +- if (pgpio->irq_register) { ++ if (nv_connector->dcb->gpio_tag != 0xff && pgpio->irq_register) { + pgpio->irq_register(dev, nv_connector->dcb->gpio_tag, + nouveau_connector_hotplug, connector); ++ ++ connector->polled = DRM_CONNECTOR_POLL_HPD; ++ } else { ++ connector->polled = DRM_CONNECTOR_POLL_CONNECT; + } + + drm_sysfs_connector_add(connector); + +- if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS || +- connector->connector_type == DRM_MODE_CONNECTOR_eDP) +- nouveau_backlight_init(connector); +- + dcb->drm = connector; + return dcb->drm; + +@@ -925,22 +910,13 @@ nouveau_connector_hotplug(void *data, int plugged) + struct drm_connector *connector = data; + struct drm_device *dev = connector->dev; + +- NV_INFO(dev, "%splugged %s\n", plugged ? "" : "un", +- drm_get_connector_name(connector)); +- +- if (connector->encoder && connector->encoder->crtc && +- connector->encoder->crtc->enabled) { +- struct nouveau_encoder *nv_encoder = nouveau_encoder(connector->encoder); +- struct drm_encoder_helper_funcs *helper = +- connector->encoder->helper_private; ++ NV_DEBUG(dev, "%splugged %s\n", plugged ? "" : "un", ++ drm_get_connector_name(connector)); + +- if (nv_encoder->dcb->type == OUTPUT_DP) { +- if (plugged) +- helper->dpms(connector->encoder, DRM_MODE_DPMS_ON); +- else +- helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF); +- } +- } ++ if (plugged) ++ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); ++ else ++ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + + drm_helper_hpd_irq_event(dev); + } +diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h +index cb1ce2a..bf8e128 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_crtc.h ++++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h +@@ -82,14 +82,13 @@ static inline struct drm_crtc *to_drm_crtc(struct nouveau_crtc *crtc) + } + + int nv50_crtc_create(struct drm_device *dev, int index); +-int nv50_cursor_init(struct nouveau_crtc *); +-void nv50_cursor_fini(struct nouveau_crtc *); + int nv50_crtc_cursor_set(struct drm_crtc *drm_crtc, struct drm_file *file_priv, + uint32_t buffer_handle, uint32_t width, + uint32_t height); + int nv50_crtc_cursor_move(struct drm_crtc *drm_crtc, int x, int y); + + int nv04_cursor_init(struct nouveau_crtc *); ++int nv50_cursor_init(struct nouveau_crtc *); + + struct nouveau_connector * + nouveau_crtc_connector_get(struct nouveau_crtc *crtc); +diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c +index eb514ea..ddbabef 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_display.c ++++ b/drivers/gpu/drm/nouveau/nouveau_display.c +@@ -105,9 +105,12 @@ nouveau_framebuffer_init(struct drm_device *dev, + if (dev_priv->chipset == 0x50) + nv_fb->r_format |= (tile_flags << 8); + +- if (!tile_flags) +- nv_fb->r_pitch = 0x00100000 | fb->pitch; +- else { ++ if (!tile_flags) { ++ if (dev_priv->card_type < NV_D0) ++ nv_fb->r_pitch = 0x00100000 | fb->pitch; ++ else ++ nv_fb->r_pitch = 0x01000000 | fb->pitch; ++ } else { + u32 mode = nvbo->tile_mode; + if (dev_priv->card_type >= NV_C0) + mode >>= 4; +diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c +index 7beb82a..de5efe7 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_dp.c ++++ b/drivers/gpu/drm/nouveau/nouveau_dp.c +@@ -28,418 +28,619 @@ + #include "nouveau_i2c.h" + #include "nouveau_connector.h" + #include "nouveau_encoder.h" ++#include "nouveau_crtc.h" ++ ++/****************************************************************************** ++ * aux channel util functions ++ *****************************************************************************/ ++#define AUX_DBG(fmt, args...) do { \ ++ if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_AUXCH) { \ ++ NV_PRINTK(KERN_DEBUG, dev, "AUXCH(%d): " fmt, ch, ##args); \ ++ } \ ++} while (0) ++#define AUX_ERR(fmt, args...) NV_ERROR(dev, "AUXCH(%d): " fmt, ch, ##args) ++ ++static void ++auxch_fini(struct drm_device *dev, int ch) ++{ ++ nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000); ++} + + static int +-auxch_rd(struct drm_encoder *encoder, int address, uint8_t *buf, int size) ++auxch_init(struct drm_device *dev, int ch) + { +- struct drm_device *dev = encoder->dev; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct nouveau_i2c_chan *auxch; +- int ret; +- +- auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); +- if (!auxch) +- return -ENODEV; +- +- ret = nouveau_dp_auxch(auxch, 9, address, buf, size); +- if (ret) +- return ret; ++ const u32 unksel = 1; /* nfi which to use, or if it matters.. */ ++ const u32 ureq = unksel ? 0x00100000 : 0x00200000; ++ const u32 urep = unksel ? 0x01000000 : 0x02000000; ++ u32 ctrl, timeout; ++ ++ /* wait up to 1ms for any previous transaction to be done... */ ++ timeout = 1000; ++ do { ++ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); ++ udelay(1); ++ if (!timeout--) { ++ AUX_ERR("begin idle timeout 0x%08x", ctrl); ++ return -EBUSY; ++ } ++ } while (ctrl & 0x03010000); ++ ++ /* set some magic, and wait up to 1ms for it to appear */ ++ nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq); ++ timeout = 1000; ++ do { ++ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); ++ udelay(1); ++ if (!timeout--) { ++ AUX_ERR("magic wait 0x%08x\n", ctrl); ++ auxch_fini(dev, ch); ++ return -EBUSY; ++ } ++ } while ((ctrl & 0x03000000) != urep); + + return 0; + } + + static int +-auxch_wr(struct drm_encoder *encoder, int address, uint8_t *buf, int size) ++auxch_tx(struct drm_device *dev, int ch, u8 type, u32 addr, u8 *data, u8 size) + { +- struct drm_device *dev = encoder->dev; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct nouveau_i2c_chan *auxch; +- int ret; ++ u32 ctrl, stat, timeout, retries; ++ u32 xbuf[4] = {}; ++ int ret, i; + +- auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); +- if (!auxch) +- return -ENODEV; ++ AUX_DBG("%d: 0x%08x %d\n", type, addr, size); + +- ret = nouveau_dp_auxch(auxch, 8, address, buf, size); +- return ret; +-} ++ ret = auxch_init(dev, ch); ++ if (ret) ++ goto out; + +-static int +-nouveau_dp_lane_count_set(struct drm_encoder *encoder, uint8_t cmd) +-{ +- struct drm_device *dev = encoder->dev; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- uint32_t tmp; +- int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); +- +- tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); +- tmp &= ~(NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED | +- NV50_SOR_DP_CTRL_LANE_MASK); +- tmp |= ((1 << (cmd & DP_LANE_COUNT_MASK)) - 1) << 16; +- if (cmd & DP_LANE_COUNT_ENHANCED_FRAME_EN) +- tmp |= NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED; +- nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp); +- +- return auxch_wr(encoder, DP_LANE_COUNT_SET, &cmd, 1); +-} ++ stat = nv_rd32(dev, 0x00e4e8 + (ch * 0x50)); ++ if (!(stat & 0x10000000)) { ++ AUX_DBG("sink not detected\n"); ++ ret = -ENXIO; ++ goto out; ++ } + +-static int +-nouveau_dp_link_bw_set(struct drm_encoder *encoder, uint8_t cmd) +-{ +- struct drm_device *dev = encoder->dev; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- uint32_t tmp; +- int reg = 0x614300 + (nv_encoder->or * 0x800); ++ if (!(type & 1)) { ++ memcpy(xbuf, data, size); ++ for (i = 0; i < 16; i += 4) { ++ AUX_DBG("wr 0x%08x\n", xbuf[i / 4]); ++ nv_wr32(dev, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]); ++ } ++ } + +- tmp = nv_rd32(dev, reg); +- tmp &= 0xfff3ffff; +- if (cmd == DP_LINK_BW_2_7) +- tmp |= 0x00040000; +- nv_wr32(dev, reg, tmp); ++ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); ++ ctrl &= ~0x0001f0ff; ++ ctrl |= type << 12; ++ ctrl |= size - 1; ++ nv_wr32(dev, 0x00e4e0 + (ch * 0x50), addr); ++ ++ /* retry transaction a number of times on failure... */ ++ ret = -EREMOTEIO; ++ for (retries = 0; retries < 32; retries++) { ++ /* reset, and delay a while if this is a retry */ ++ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); ++ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); ++ if (retries) ++ udelay(400); ++ ++ /* transaction request, wait up to 1ms for it to complete */ ++ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl); ++ ++ timeout = 1000; ++ do { ++ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); ++ udelay(1); ++ if (!timeout--) { ++ AUX_ERR("tx req timeout 0x%08x\n", ctrl); ++ goto out; ++ } ++ } while (ctrl & 0x00010000); + +- return auxch_wr(encoder, DP_LINK_BW_SET, &cmd, 1); +-} ++ /* read status, and check if transaction completed ok */ ++ stat = nv_mask(dev, 0x00e4e8 + (ch * 0x50), 0, 0); ++ if (!(stat & 0x000f0f00)) { ++ ret = 0; ++ break; ++ } + +-static int +-nouveau_dp_link_train_set(struct drm_encoder *encoder, int pattern) +-{ +- struct drm_device *dev = encoder->dev; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- uint32_t tmp; +- uint8_t cmd; +- int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); +- int ret; ++ AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); ++ } + +- tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); +- tmp &= ~NV50_SOR_DP_CTRL_TRAINING_PATTERN; +- tmp |= (pattern << 24); +- nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp); ++ if (type & 1) { ++ for (i = 0; i < 16; i += 4) { ++ xbuf[i / 4] = nv_rd32(dev, 0x00e4d0 + (ch * 0x50) + i); ++ AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); ++ } ++ memcpy(data, xbuf, size); ++ } + +- ret = auxch_rd(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1); +- if (ret) +- return ret; +- cmd &= ~DP_TRAINING_PATTERN_MASK; +- cmd |= (pattern & DP_TRAINING_PATTERN_MASK); +- return auxch_wr(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1); ++out: ++ auxch_fini(dev, ch); ++ return ret; + } + +-static int +-nouveau_dp_max_voltage_swing(struct drm_encoder *encoder) ++static u32 ++dp_link_bw_get(struct drm_device *dev, int or, int link) + { +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct drm_device *dev = encoder->dev; +- struct bit_displayport_encoder_table_entry *dpse; +- struct bit_displayport_encoder_table *dpe; +- int i, dpe_headerlen, max_vs = 0; +- +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) +- return false; +- dpse = (void *)((char *)dpe + dpe_headerlen); ++ u32 ctrl = nv_rd32(dev, 0x614300 + (or * 0x800)); ++ if (!(ctrl & 0x000c0000)) ++ return 162000; ++ return 270000; ++} + +- for (i = 0; i < dpe_headerlen; i++, dpse++) { +- if (dpse->vs_level > max_vs) +- max_vs = dpse->vs_level; ++static int ++dp_lane_count_get(struct drm_device *dev, int or, int link) ++{ ++ u32 ctrl = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); ++ switch (ctrl & 0x000f0000) { ++ case 0x00010000: return 1; ++ case 0x00030000: return 2; ++ default: ++ return 4; + } +- +- return max_vs; + } + +-static int +-nouveau_dp_max_pre_emphasis(struct drm_encoder *encoder, int vs) ++void ++nouveau_dp_tu_update(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) + { +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct drm_device *dev = encoder->dev; +- struct bit_displayport_encoder_table_entry *dpse; +- struct bit_displayport_encoder_table *dpe; +- int i, dpe_headerlen, max_pre = 0; ++ const u32 symbol = 100000; ++ int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0; ++ int TU, VTUi, VTUf, VTUa; ++ u64 link_data_rate, link_ratio, unk; ++ u32 best_diff = 64 * symbol; ++ u32 link_nr, link_bw, r; ++ ++ /* calculate packed data rate for each lane */ ++ link_nr = dp_lane_count_get(dev, or, link); ++ link_data_rate = (clk * bpp / 8) / link_nr; ++ ++ /* calculate ratio of packed data rate to link symbol rate */ ++ link_bw = dp_link_bw_get(dev, or, link); ++ link_ratio = link_data_rate * symbol; ++ r = do_div(link_ratio, link_bw); ++ ++ for (TU = 64; TU >= 32; TU--) { ++ /* calculate average number of valid symbols in each TU */ ++ u32 tu_valid = link_ratio * TU; ++ u32 calc, diff; ++ ++ /* find a hw representation for the fraction.. */ ++ VTUi = tu_valid / symbol; ++ calc = VTUi * symbol; ++ diff = tu_valid - calc; ++ if (diff) { ++ if (diff >= (symbol / 2)) { ++ VTUf = symbol / (symbol - diff); ++ if (symbol - (VTUf * diff)) ++ VTUf++; ++ ++ if (VTUf <= 15) { ++ VTUa = 1; ++ calc += symbol - (symbol / VTUf); ++ } else { ++ VTUa = 0; ++ VTUf = 1; ++ calc += symbol; ++ } ++ } else { ++ VTUa = 0; ++ VTUf = min((int)(symbol / diff), 15); ++ calc += symbol / VTUf; ++ } + +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) +- return false; +- dpse = (void *)((char *)dpe + dpe_headerlen); ++ diff = calc - tu_valid; ++ } else { ++ /* no remainder, but the hw doesn't like the fractional ++ * part to be zero. decrement the integer part and ++ * have the fraction add a whole symbol back ++ */ ++ VTUa = 0; ++ VTUf = 1; ++ VTUi--; ++ } + +- for (i = 0; i < dpe_headerlen; i++, dpse++) { +- if (dpse->vs_level != vs) +- continue; ++ if (diff < best_diff) { ++ best_diff = diff; ++ bestTU = TU; ++ bestVTUa = VTUa; ++ bestVTUf = VTUf; ++ bestVTUi = VTUi; ++ if (diff == 0) ++ break; ++ } ++ } + +- if (dpse->pre_level > max_pre) +- max_pre = dpse->pre_level; ++ if (!bestTU) { ++ NV_ERROR(dev, "DP: unable to find suitable config\n"); ++ return; + } + +- return max_pre; ++ /* XXX close to vbios numbers, but not right */ ++ unk = (symbol - link_ratio) * bestTU; ++ unk *= link_ratio; ++ r = do_div(unk, symbol); ++ r = do_div(unk, symbol); ++ unk += 6; ++ ++ nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x000001fc, bestTU << 2); ++ nv_mask(dev, NV50_SOR_DP_SCFG(or, link), 0x010f7f3f, bestVTUa << 24 | ++ bestVTUf << 16 | ++ bestVTUi << 8 | ++ unk); + } + +-static bool +-nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config) ++u8 * ++nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) + { +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct drm_device *dev = encoder->dev; +- struct bit_displayport_encoder_table *dpe; +- int ret, i, dpe_headerlen, vs = 0, pre = 0; +- uint8_t request[2]; +- +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) +- return false; +- +- ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2); +- if (ret) +- return false; +- +- NV_DEBUG_KMS(dev, "\t\tadjust 0x%02x 0x%02x\n", request[0], request[1]); +- +- /* Keep all lanes at the same level.. */ +- for (i = 0; i < nv_encoder->dp.link_nr; i++) { +- int lane_req = (request[i >> 1] >> ((i & 1) << 2)) & 0xf; +- int lane_vs = lane_req & 3; +- int lane_pre = (lane_req >> 2) & 3; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nvbios *bios = &dev_priv->vbios; ++ struct bit_entry d; ++ u8 *table; ++ int i; ++ ++ if (bit_table(dev, 'd', &d)) { ++ NV_ERROR(dev, "BIT 'd' table not found\n"); ++ return NULL; ++ } + +- if (lane_vs > vs) +- vs = lane_vs; +- if (lane_pre > pre) +- pre = lane_pre; ++ if (d.version != 1) { ++ NV_ERROR(dev, "BIT 'd' table version %d unknown\n", d.version); ++ return NULL; + } + +- if (vs >= nouveau_dp_max_voltage_swing(encoder)) { +- vs = nouveau_dp_max_voltage_swing(encoder); +- vs |= 4; ++ table = ROMPTR(bios, d.data[0]); ++ if (!table) { ++ NV_ERROR(dev, "displayport table pointer invalid\n"); ++ return NULL; + } + +- if (pre >= nouveau_dp_max_pre_emphasis(encoder, vs & 3)) { +- pre = nouveau_dp_max_pre_emphasis(encoder, vs & 3); +- pre |= 4; ++ switch (table[0]) { ++ case 0x20: ++ case 0x21: ++ case 0x30: ++ break; ++ default: ++ NV_ERROR(dev, "displayport table 0x%02x unknown\n", table[0]); ++ return NULL; + } + +- /* Update the configuration for all lanes.. */ +- for (i = 0; i < nv_encoder->dp.link_nr; i++) +- config[i] = (pre << 3) | vs; ++ for (i = 0; i < table[3]; i++) { ++ *entry = ROMPTR(bios, table[table[1] + (i * table[2])]); ++ if (*entry && bios_encoder_match(dcb, ROM32((*entry)[0]))) ++ return table; ++ } + +- return true; ++ NV_ERROR(dev, "displayport encoder table not found\n"); ++ return NULL; + } + +-static bool +-nouveau_dp_link_train_commit(struct drm_encoder *encoder, uint8_t *config) +-{ +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct drm_device *dev = encoder->dev; +- struct bit_displayport_encoder_table_entry *dpse; +- struct bit_displayport_encoder_table *dpe; +- int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); +- int dpe_headerlen, ret, i; ++/****************************************************************************** ++ * link training ++ *****************************************************************************/ ++struct dp_state { ++ struct dcb_entry *dcb; ++ u8 *table; ++ u8 *entry; ++ int auxch; ++ int crtc; ++ int or; ++ int link; ++ u8 *dpcd; ++ int link_nr; ++ u32 link_bw; ++ u8 stat[6]; ++ u8 conf[4]; ++}; + +- NV_DEBUG_KMS(dev, "\t\tconfig 0x%02x 0x%02x 0x%02x 0x%02x\n", +- config[0], config[1], config[2], config[3]); ++static void ++dp_set_link_config(struct drm_device *dev, struct dp_state *dp) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ int or = dp->or, link = dp->link; ++ u8 *entry, sink[2]; ++ u32 dp_ctrl; ++ u16 script; ++ ++ NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); ++ ++ /* set selected link rate on source */ ++ switch (dp->link_bw) { ++ case 270000: ++ nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00040000); ++ sink[0] = DP_LINK_BW_2_7; ++ break; ++ default: ++ nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00000000); ++ sink[0] = DP_LINK_BW_1_62; ++ break; ++ } + +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) +- return false; +- dpse = (void *)((char *)dpe + dpe_headerlen); ++ /* offset +0x0a of each dp encoder table entry is a pointer to another ++ * table, that has (among other things) pointers to more scripts that ++ * need to be executed, this time depending on link speed. ++ */ ++ entry = ROMPTR(&dev_priv->vbios, dp->entry[10]); ++ if (entry) { ++ if (dp->table[0] < 0x30) { ++ while (dp->link_bw < (ROM16(entry[0]) * 10)) ++ entry += 4; ++ script = ROM16(entry[2]); ++ } else { ++ while (dp->link_bw < (entry[0] * 27000)) ++ entry += 3; ++ script = ROM16(entry[1]); ++ } + +- for (i = 0; i < dpe->record_nr; i++, dpse++) { +- if (dpse->vs_level == (config[0] & 3) && +- dpse->pre_level == ((config[0] >> 3) & 3)) +- break; ++ nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc); + } +- BUG_ON(i == dpe->record_nr); +- +- for (i = 0; i < nv_encoder->dp.link_nr; i++) { +- const int shift[4] = { 16, 8, 0, 24 }; +- uint32_t mask = 0xff << shift[i]; +- uint32_t reg0, reg1, reg2; +- +- reg0 = nv_rd32(dev, NV50_SOR_DP_UNK118(or, link)) & ~mask; +- reg0 |= (dpse->reg0 << shift[i]); +- reg1 = nv_rd32(dev, NV50_SOR_DP_UNK120(or, link)) & ~mask; +- reg1 |= (dpse->reg1 << shift[i]); +- reg2 = nv_rd32(dev, NV50_SOR_DP_UNK130(or, link)) & 0xffff00ff; +- reg2 |= (dpse->reg2 << 8); +- nv_wr32(dev, NV50_SOR_DP_UNK118(or, link), reg0); +- nv_wr32(dev, NV50_SOR_DP_UNK120(or, link), reg1); +- nv_wr32(dev, NV50_SOR_DP_UNK130(or, link), reg2); ++ ++ /* configure lane count on the source */ ++ dp_ctrl = ((1 << dp->link_nr) - 1) << 16; ++ sink[1] = dp->link_nr; ++ if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) { ++ dp_ctrl |= 0x00004000; ++ sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + } + +- ret = auxch_wr(encoder, DP_TRAINING_LANE0_SET, config, 4); +- if (ret) +- return false; ++ nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x001f4000, dp_ctrl); + +- return true; ++ /* inform the sink of the new configuration */ ++ auxch_tx(dev, dp->auxch, 8, DP_LINK_BW_SET, sink, 2); + } + +-bool +-nouveau_dp_link_train(struct drm_encoder *encoder) ++static void ++dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 tp) + { +- struct drm_device *dev = encoder->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct nouveau_connector *nv_connector; +- struct bit_displayport_encoder_table *dpe; +- int dpe_headerlen; +- uint8_t config[4], status[3]; +- bool cr_done, cr_max_vs, eq_done, hpd_state; +- int ret = 0, i, tries, voltage; ++ u8 sink_tp; + +- NV_DEBUG_KMS(dev, "link training!!\n"); ++ NV_DEBUG_KMS(dev, "training pattern %d\n", tp); + +- nv_connector = nouveau_encoder_connector_get(nv_encoder); +- if (!nv_connector) +- return false; ++ nv_mask(dev, NV50_SOR_DP_CTRL(dp->or, dp->link), 0x0f000000, tp << 24); + +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) { +- NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or); +- return false; +- } ++ auxch_tx(dev, dp->auxch, 9, DP_TRAINING_PATTERN_SET, &sink_tp, 1); ++ sink_tp &= ~DP_TRAINING_PATTERN_MASK; ++ sink_tp |= tp; ++ auxch_tx(dev, dp->auxch, 8, DP_TRAINING_PATTERN_SET, &sink_tp, 1); ++} + +- /* disable hotplug detect, this flips around on some panels during +- * link training. +- */ +- hpd_state = pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); ++static const u8 nv50_lane_map[] = { 16, 8, 0, 24 }; ++static const u8 nvaf_lane_map[] = { 24, 16, 8, 0 }; ++ ++static int ++dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 mask = 0, drv = 0, pre = 0, unk = 0; ++ const u8 *shifts; ++ int link = dp->link; ++ int or = dp->or; ++ int i; ++ ++ if (dev_priv->chipset != 0xaf) ++ shifts = nv50_lane_map; ++ else ++ shifts = nvaf_lane_map; ++ ++ for (i = 0; i < dp->link_nr; i++) { ++ u8 *conf = dp->entry + dp->table[4]; ++ u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf; ++ u8 lpre = (lane & 0x0c) >> 2; ++ u8 lvsw = (lane & 0x03) >> 0; ++ ++ mask |= 0xff << shifts[i]; ++ unk |= 1 << (shifts[i] >> 3); ++ ++ dp->conf[i] = (lpre << 3) | lvsw; ++ if (lvsw == DP_TRAIN_VOLTAGE_SWING_1200) ++ dp->conf[i] |= DP_TRAIN_MAX_SWING_REACHED; ++ if (lpre == DP_TRAIN_PRE_EMPHASIS_9_5) ++ dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; ++ ++ NV_DEBUG_KMS(dev, "config lane %d %02x\n", i, dp->conf[i]); ++ ++ if (dp->table[0] < 0x30) { ++ u8 *last = conf + (dp->entry[4] * dp->table[5]); ++ while (lvsw != conf[0] || lpre != conf[1]) { ++ conf += dp->table[5]; ++ if (conf >= last) ++ return -EINVAL; ++ } ++ ++ conf += 2; ++ } else { ++ /* no lookup table anymore, set entries for each ++ * combination of voltage swing and pre-emphasis ++ * level allowed by the DP spec. ++ */ ++ switch (lvsw) { ++ case 0: lpre += 0; break; ++ case 1: lpre += 4; break; ++ case 2: lpre += 7; break; ++ case 3: lpre += 9; break; ++ } ++ ++ conf = conf + (lpre * dp->table[5]); ++ conf++; ++ } + +- if (dpe->script0) { +- NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); +- nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0), +- nv_encoder->dcb); ++ drv |= conf[0] << shifts[i]; ++ pre |= conf[1] << shifts[i]; ++ unk = (unk & ~0x0000ff00) | (conf[2] << 8); + } + +-train: +- cr_done = eq_done = false; ++ nv_mask(dev, NV50_SOR_DP_UNK118(or, link), mask, drv); ++ nv_mask(dev, NV50_SOR_DP_UNK120(or, link), mask, pre); ++ nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000ff0f, unk); + +- /* set link configuration */ +- NV_DEBUG_KMS(dev, "\tbegin train: bw %d, lanes %d\n", +- nv_encoder->dp.link_bw, nv_encoder->dp.link_nr); ++ return auxch_tx(dev, dp->auxch, 8, DP_TRAINING_LANE0_SET, dp->conf, 4); ++} + +- ret = nouveau_dp_link_bw_set(encoder, nv_encoder->dp.link_bw); +- if (ret) +- return false; ++static int ++dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay) ++{ ++ int ret; + +- config[0] = nv_encoder->dp.link_nr; +- if (nv_encoder->dp.dpcd_version >= 0x11 && +- nv_encoder->dp.enhanced_frame) +- config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; ++ udelay(delay); + +- ret = nouveau_dp_lane_count_set(encoder, config[0]); ++ ret = auxch_tx(dev, dp->auxch, 9, DP_LANE0_1_STATUS, dp->stat, 6); + if (ret) +- return false; ++ return ret; + +- /* clock recovery */ +- NV_DEBUG_KMS(dev, "\tbegin cr\n"); +- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_1); +- if (ret) +- goto stop; ++ NV_DEBUG_KMS(dev, "status %02x %02x %02x %02x %02x %02x\n", ++ dp->stat[0], dp->stat[1], dp->stat[2], dp->stat[3], ++ dp->stat[4], dp->stat[5]); ++ return 0; ++} + +- tries = 0; +- voltage = -1; +- memset(config, 0x00, sizeof(config)); +- for (;;) { +- if (!nouveau_dp_link_train_commit(encoder, config)) +- break; ++static int ++dp_link_train_cr(struct drm_device *dev, struct dp_state *dp) ++{ ++ bool cr_done = false, abort = false; ++ int voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK; ++ int tries = 0, i; + +- udelay(100); ++ dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_1); + +- ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 2); +- if (ret) ++ do { ++ if (dp_link_train_commit(dev, dp) || ++ dp_link_train_update(dev, dp, 100)) + break; +- NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n", +- status[0], status[1]); + + cr_done = true; +- cr_max_vs = false; +- for (i = 0; i < nv_encoder->dp.link_nr; i++) { +- int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf; +- ++ for (i = 0; i < dp->link_nr; i++) { ++ u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; + if (!(lane & DP_LANE_CR_DONE)) { + cr_done = false; +- if (config[i] & DP_TRAIN_MAX_PRE_EMPHASIS_REACHED) +- cr_max_vs = true; ++ if (dp->conf[i] & DP_TRAIN_MAX_SWING_REACHED) ++ abort = true; + break; + } + } + +- if ((config[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { +- voltage = config[0] & DP_TRAIN_VOLTAGE_SWING_MASK; ++ if ((dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { ++ voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK; + tries = 0; + } ++ } while (!cr_done && !abort && ++tries < 5); + +- if (cr_done || cr_max_vs || (++tries == 5)) +- break; +- +- if (!nouveau_dp_link_train_adjust(encoder, config)) +- break; +- } +- +- if (!cr_done) +- goto stop; ++ return cr_done ? 0 : -1; ++} + +- /* channel equalisation */ +- NV_DEBUG_KMS(dev, "\tbegin eq\n"); +- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_2); +- if (ret) +- goto stop; ++static int ++dp_link_train_eq(struct drm_device *dev, struct dp_state *dp) ++{ ++ bool eq_done, cr_done = true; ++ int tries = 0, i; + +- for (tries = 0; tries <= 5; tries++) { +- udelay(400); ++ dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_2); + +- ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 3); +- if (ret) ++ do { ++ if (dp_link_train_update(dev, dp, 400)) + break; +- NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n", +- status[0], status[1]); + +- eq_done = true; +- if (!(status[2] & DP_INTERLANE_ALIGN_DONE)) +- eq_done = false; +- +- for (i = 0; eq_done && i < nv_encoder->dp.link_nr; i++) { +- int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf; +- +- if (!(lane & DP_LANE_CR_DONE)) { ++ eq_done = !!(dp->stat[2] & DP_INTERLANE_ALIGN_DONE); ++ for (i = 0; i < dp->link_nr && eq_done; i++) { ++ u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; ++ if (!(lane & DP_LANE_CR_DONE)) + cr_done = false; +- break; +- } +- + if (!(lane & DP_LANE_CHANNEL_EQ_DONE) || +- !(lane & DP_LANE_SYMBOL_LOCKED)) { ++ !(lane & DP_LANE_SYMBOL_LOCKED)) + eq_done = false; +- break; +- } + } + +- if (eq_done || !cr_done) ++ if (dp_link_train_commit(dev, dp)) + break; ++ } while (!eq_done && cr_done && ++tries <= 5); + +- if (!nouveau_dp_link_train_adjust(encoder, config) || +- !nouveau_dp_link_train_commit(encoder, config)) +- break; +- } ++ return eq_done ? 0 : -1; ++} + +-stop: +- /* end link training */ +- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_DISABLE); +- if (ret) ++bool ++nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) ++{ ++ struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; ++ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); ++ struct nouveau_connector *nv_connector = ++ nouveau_encoder_connector_get(nv_encoder); ++ struct drm_device *dev = encoder->dev; ++ struct nouveau_i2c_chan *auxch; ++ const u32 bw_list[] = { 270000, 162000, 0 }; ++ const u32 *link_bw = bw_list; ++ struct dp_state dp; ++ ++ auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); ++ if (!auxch) + return false; + +- /* retry at a lower setting, if possible */ +- if (!ret && !(eq_done && cr_done)) { +- NV_DEBUG_KMS(dev, "\twe failed\n"); +- if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62) { +- NV_DEBUG_KMS(dev, "retry link training at low rate\n"); +- nv_encoder->dp.link_bw = DP_LINK_BW_1_62; +- goto train; +- } ++ dp.table = nouveau_dp_bios_data(dev, nv_encoder->dcb, &dp.entry); ++ if (!dp.table) ++ return -EINVAL; ++ ++ dp.dcb = nv_encoder->dcb; ++ dp.crtc = nv_crtc->index; ++ dp.auxch = auxch->rd; ++ dp.or = nv_encoder->or; ++ dp.link = !(nv_encoder->dcb->sorconf.link & 1); ++ dp.dpcd = nv_encoder->dp.dpcd; ++ ++ /* some sinks toggle hotplug in response to some of the actions ++ * we take during link training (DP_SET_POWER is one), we need ++ * to ignore them for the moment to avoid races. ++ */ ++ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); ++ ++ /* enable down-spreading, if possible */ ++ if (dp.table[1] >= 16) { ++ u16 script = ROM16(dp.entry[14]); ++ if (nv_encoder->dp.dpcd[3] & 1) ++ script = ROM16(dp.entry[12]); ++ ++ nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc); + } + +- if (dpe->script1) { +- NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or); +- nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1), +- nv_encoder->dcb); ++ /* execute pre-train script from vbios */ ++ nouveau_bios_run_init_table(dev, ROM16(dp.entry[6]), dp.dcb, dp.crtc); ++ ++ /* start off at highest link rate supported by encoder and display */ ++ while (*link_bw > nv_encoder->dp.link_bw) ++ link_bw++; ++ ++ while (link_bw[0]) { ++ /* find minimum required lane count at this link rate */ ++ dp.link_nr = nv_encoder->dp.link_nr; ++ while ((dp.link_nr >> 1) * link_bw[0] > datarate) ++ dp.link_nr >>= 1; ++ ++ /* drop link rate to minimum with this lane count */ ++ while ((link_bw[1] * dp.link_nr) > datarate) ++ link_bw++; ++ dp.link_bw = link_bw[0]; ++ ++ /* program selected link configuration */ ++ dp_set_link_config(dev, &dp); ++ ++ /* attempt to train the link at this configuration */ ++ memset(dp.stat, 0x00, sizeof(dp.stat)); ++ if (!dp_link_train_cr(dev, &dp) && ++ !dp_link_train_eq(dev, &dp)) ++ break; ++ ++ /* retry at lower rate */ ++ link_bw++; + } + +- /* re-enable hotplug detect */ +- pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, hpd_state); ++ /* finish link training */ ++ dp_set_training_pattern(dev, &dp, DP_TRAINING_PATTERN_DISABLE); + +- return eq_done; ++ /* execute post-train script from vbios */ ++ nouveau_bios_run_init_table(dev, ROM16(dp.entry[8]), dp.dcb, dp.crtc); ++ ++ /* re-enable hotplug detect */ ++ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true); ++ return true; + } + + bool +@@ -447,31 +648,34 @@ nouveau_dp_detect(struct drm_encoder *encoder) + { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; +- uint8_t dpcd[4]; ++ struct nouveau_i2c_chan *auxch; ++ u8 *dpcd = nv_encoder->dp.dpcd; + int ret; + +- ret = auxch_rd(encoder, 0x0000, dpcd, 4); +- if (ret) ++ auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); ++ if (!auxch) + return false; + +- NV_DEBUG_KMS(dev, "encoder: link_bw %d, link_nr %d\n" +- "display: link_bw %d, link_nr %d version 0x%02x\n", +- nv_encoder->dcb->dpconf.link_bw, +- nv_encoder->dcb->dpconf.link_nr, +- dpcd[1], dpcd[2] & 0x0f, dpcd[0]); ++ ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8); ++ if (ret) ++ return false; + +- nv_encoder->dp.dpcd_version = dpcd[0]; ++ nv_encoder->dp.link_bw = 27000 * dpcd[1]; ++ nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; + +- nv_encoder->dp.link_bw = dpcd[1]; +- if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62 && +- !nv_encoder->dcb->dpconf.link_bw) +- nv_encoder->dp.link_bw = DP_LINK_BW_1_62; ++ NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n", ++ nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); ++ NV_DEBUG_KMS(dev, "encoder: %dx%d\n", ++ nv_encoder->dcb->dpconf.link_nr, ++ nv_encoder->dcb->dpconf.link_bw); + +- nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; +- if (nv_encoder->dp.link_nr > nv_encoder->dcb->dpconf.link_nr) ++ if (nv_encoder->dcb->dpconf.link_nr < nv_encoder->dp.link_nr) + nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr; ++ if (nv_encoder->dcb->dpconf.link_bw < nv_encoder->dp.link_bw) ++ nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw; + +- nv_encoder->dp.enhanced_frame = (dpcd[2] & DP_ENHANCED_FRAME_CAP); ++ NV_DEBUG_KMS(dev, "maximum: %dx%d\n", ++ nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); + + return true; + } +@@ -480,105 +684,13 @@ int + nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, + uint8_t *data, int data_nr) + { +- struct drm_device *dev = auxch->dev; +- uint32_t tmp, ctrl, stat = 0, data32[4] = {}; +- int ret = 0, i, index = auxch->rd; +- +- NV_DEBUG_KMS(dev, "ch %d cmd %d addr 0x%x len %d\n", index, cmd, addr, data_nr); +- +- tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); +- nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp | 0x00100000); +- tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); +- if (!(tmp & 0x01000000)) { +- NV_ERROR(dev, "expected bit 24 == 1, got 0x%08x\n", tmp); +- ret = -EIO; +- goto out; +- } +- +- for (i = 0; i < 3; i++) { +- tmp = nv_rd32(dev, NV50_AUXCH_STAT(auxch->rd)); +- if (tmp & NV50_AUXCH_STAT_STATE_READY) +- break; +- udelay(100); +- } +- +- if (i == 3) { +- ret = -EBUSY; +- goto out; +- } +- +- if (!(cmd & 1)) { +- memcpy(data32, data, data_nr); +- for (i = 0; i < 4; i++) { +- NV_DEBUG_KMS(dev, "wr %d: 0x%08x\n", i, data32[i]); +- nv_wr32(dev, NV50_AUXCH_DATA_OUT(index, i), data32[i]); +- } +- } +- +- nv_wr32(dev, NV50_AUXCH_ADDR(index), addr); +- ctrl = nv_rd32(dev, NV50_AUXCH_CTRL(index)); +- ctrl &= ~(NV50_AUXCH_CTRL_CMD | NV50_AUXCH_CTRL_LEN); +- ctrl |= (cmd << NV50_AUXCH_CTRL_CMD_SHIFT); +- ctrl |= ((data_nr - 1) << NV50_AUXCH_CTRL_LEN_SHIFT); +- +- for (i = 0; i < 16; i++) { +- nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x80000000); +- nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl); +- nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x00010000); +- if (!nv_wait(dev, NV50_AUXCH_CTRL(index), +- 0x00010000, 0x00000000)) { +- NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n", +- nv_rd32(dev, NV50_AUXCH_CTRL(index))); +- ret = -EBUSY; +- goto out; +- } +- +- udelay(400); +- +- stat = nv_rd32(dev, NV50_AUXCH_STAT(index)); +- if ((stat & NV50_AUXCH_STAT_REPLY_AUX) != +- NV50_AUXCH_STAT_REPLY_AUX_DEFER) +- break; +- } +- +- if (i == 16) { +- NV_ERROR(dev, "auxch DEFER too many times, bailing\n"); +- ret = -EREMOTEIO; +- goto out; +- } +- +- if (cmd & 1) { +- if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) { +- ret = -EREMOTEIO; +- goto out; +- } +- +- for (i = 0; i < 4; i++) { +- data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i)); +- NV_DEBUG_KMS(dev, "rd %d: 0x%08x\n", i, data32[i]); +- } +- memcpy(data, data32, data_nr); +- } +- +-out: +- tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); +- nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp & ~0x00100000); +- tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); +- if (tmp & 0x01000000) { +- NV_ERROR(dev, "expected bit 24 == 0, got 0x%08x\n", tmp); +- ret = -EIO; +- } +- +- udelay(400); +- +- return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY); ++ return auxch_tx(auxch->dev, auxch->rd, cmd, addr, data, data_nr); + } + + static int + nouveau_dp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) + { + struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adap; +- struct drm_device *dev = auxch->dev; + struct i2c_msg *msg = msgs; + int ret, mcnt = num; + +@@ -602,19 +714,6 @@ nouveau_dp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) + if (ret < 0) + return ret; + +- switch (ret & NV50_AUXCH_STAT_REPLY_I2C) { +- case NV50_AUXCH_STAT_REPLY_I2C_ACK: +- break; +- case NV50_AUXCH_STAT_REPLY_I2C_NACK: +- return -EREMOTEIO; +- case NV50_AUXCH_STAT_REPLY_I2C_DEFER: +- udelay(100); +- continue; +- default: +- NV_ERROR(dev, "bad auxch reply: 0x%08x\n", ret); +- return -EREMOTEIO; +- } +- + ptr += cnt; + remaining -= cnt; + } +diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c +index b30ddd8..c1e01f3 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_drv.c ++++ b/drivers/gpu/drm/nouveau/nouveau_drv.c +@@ -41,7 +41,7 @@ int nouveau_agpmode = -1; + module_param_named(agpmode, nouveau_agpmode, int, 0400); + + MODULE_PARM_DESC(modeset, "Enable kernel modesetting"); +-static int nouveau_modeset = -1; /* kms */ ++int nouveau_modeset = -1; + module_param_named(modeset, nouveau_modeset, int, 0400); + + MODULE_PARM_DESC(vbios, "Override default VBIOS location"); +diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h +index d7d51de..29837da 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_drv.h ++++ b/drivers/gpu/drm/nouveau/nouveau_drv.h +@@ -414,12 +414,13 @@ struct nouveau_gpio_engine { + }; + + struct nouveau_pm_voltage_level { +- u8 voltage; +- u8 vid; ++ u32 voltage; /* microvolts */ ++ u8 vid; + }; + + struct nouveau_pm_voltage { + bool supported; ++ u8 version; + u8 vid_mask; + + struct nouveau_pm_voltage_level *level; +@@ -428,17 +429,48 @@ struct nouveau_pm_voltage { + + struct nouveau_pm_memtiming { + int id; +- u32 reg_100220; +- u32 reg_100224; +- u32 reg_100228; +- u32 reg_10022c; +- u32 reg_100230; +- u32 reg_100234; +- u32 reg_100238; +- u32 reg_10023c; +- u32 reg_100240; ++ u32 reg_0; /* 0x10f290 on Fermi, 0x100220 for older */ ++ u32 reg_1; ++ u32 reg_2; ++ u32 reg_3; ++ u32 reg_4; ++ u32 reg_5; ++ u32 reg_6; ++ u32 reg_7; ++ u32 reg_8; ++ /* To be written to 0x1002c0 */ ++ u8 CL; ++ u8 WR; + }; + ++struct nouveau_pm_tbl_header{ ++ u8 version; ++ u8 header_len; ++ u8 entry_cnt; ++ u8 entry_len; ++}; ++ ++struct nouveau_pm_tbl_entry{ ++ u8 tWR; ++ u8 tUNK_1; ++ u8 tCL; ++ u8 tRP; /* Byte 3 */ ++ u8 empty_4; ++ u8 tRAS; /* Byte 5 */ ++ u8 empty_6; ++ u8 tRFC; /* Byte 7 */ ++ u8 empty_8; ++ u8 tRC; /* Byte 9 */ ++ u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14; ++ u8 empty_15,empty_16,empty_17; ++ u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21; ++}; ++ ++/* nouveau_mem.c */ ++void nv30_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, ++ struct nouveau_pm_tbl_entry *e, uint8_t magic_number, ++ struct nouveau_pm_memtiming *timing); ++ + #define NOUVEAU_PM_MAX_LEVEL 8 + struct nouveau_pm_level { + struct device_attribute dev_attr; +@@ -448,11 +480,19 @@ struct nouveau_pm_level { + u32 core; + u32 memory; + u32 shader; +- u32 unk05; +- u32 unk0a; +- +- u8 voltage; +- u8 fanspeed; ++ u32 rop; ++ u32 copy; ++ u32 daemon; ++ u32 vdec; ++ u32 unk05; /* nv50:nva3, roughly.. */ ++ u32 unka0; /* nva3:nvc0 */ ++ u32 hub01; /* nvc0- */ ++ u32 hub06; /* nvc0- */ ++ u32 hub07; /* nvc0- */ ++ ++ u32 volt_min; /* microvolts */ ++ u32 volt_max; ++ u8 fanspeed; + + u16 memscript; + struct nouveau_pm_memtiming *timing; +@@ -496,6 +536,11 @@ struct nouveau_pm_engine { + void *(*clock_pre)(struct drm_device *, struct nouveau_pm_level *, + u32 id, int khz); + void (*clock_set)(struct drm_device *, void *); ++ ++ int (*clocks_get)(struct drm_device *, struct nouveau_pm_level *); ++ void *(*clocks_pre)(struct drm_device *, struct nouveau_pm_level *); ++ void (*clocks_set)(struct drm_device *, void *); ++ + int (*voltage_get)(struct drm_device *); + int (*voltage_set)(struct drm_device *, int voltage); + int (*fanspeed_get)(struct drm_device *); +@@ -504,7 +549,7 @@ struct nouveau_pm_engine { + }; + + struct nouveau_vram_engine { +- struct nouveau_mm *mm; ++ struct nouveau_mm mm; + + int (*init)(struct drm_device *); + void (*takedown)(struct drm_device *dev); +@@ -623,6 +668,7 @@ enum nouveau_card_type { + NV_40 = 0x40, + NV_50 = 0x50, + NV_C0 = 0xc0, ++ NV_D0 = 0xd0 + }; + + struct drm_nouveau_private { +@@ -633,8 +679,8 @@ struct drm_nouveau_private { + enum nouveau_card_type card_type; + /* exact chipset, derived from NV_PMC_BOOT_0 */ + int chipset; +- int stepping; + int flags; ++ u32 crystal; + + void __iomem *mmio; + +@@ -721,7 +767,6 @@ struct drm_nouveau_private { + uint64_t vram_size; + uint64_t vram_sys_base; + +- uint64_t fb_phys; + uint64_t fb_available_size; + uint64_t fb_mappable_pages; + uint64_t fb_aper_free; +@@ -784,6 +829,7 @@ nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo) + } + + /* nouveau_drv.c */ ++extern int nouveau_modeset; + extern int nouveau_agpmode; + extern int nouveau_duallink; + extern int nouveau_uscript_lvds; +@@ -824,6 +870,8 @@ extern bool nouveau_wait_eq(struct drm_device *, uint64_t timeout, + uint32_t reg, uint32_t mask, uint32_t val); + extern bool nouveau_wait_ne(struct drm_device *, uint64_t timeout, + uint32_t reg, uint32_t mask, uint32_t val); ++extern bool nouveau_wait_cb(struct drm_device *, u64 timeout, ++ bool (*cond)(void *), void *); + extern bool nouveau_wait_for_idle(struct drm_device *); + extern int nouveau_card_init(struct drm_device *); + +@@ -1006,15 +1054,15 @@ static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector + + /* nouveau_backlight.c */ + #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT +-extern int nouveau_backlight_init(struct drm_connector *); +-extern void nouveau_backlight_exit(struct drm_connector *); ++extern int nouveau_backlight_init(struct drm_device *); ++extern void nouveau_backlight_exit(struct drm_device *); + #else +-static inline int nouveau_backlight_init(struct drm_connector *dev) ++static inline int nouveau_backlight_init(struct drm_device *dev) + { + return 0; + } + +-static inline void nouveau_backlight_exit(struct drm_connector *dev) { } ++static inline void nouveau_backlight_exit(struct drm_device *dev) { } + #endif + + /* nouveau_bios.c */ +@@ -1022,7 +1070,8 @@ extern int nouveau_bios_init(struct drm_device *); + extern void nouveau_bios_takedown(struct drm_device *dev); + extern int nouveau_run_vbios_init(struct drm_device *); + extern void nouveau_bios_run_init_table(struct drm_device *, uint16_t table, +- struct dcb_entry *); ++ struct dcb_entry *, int crtc); ++extern void nouveau_bios_init_exec(struct drm_device *, uint16_t table); + extern struct dcb_gpio_entry *nouveau_bios_gpio_entry(struct drm_device *, + enum dcb_gpio_tag); + extern struct dcb_connector_table_entry * +@@ -1030,11 +1079,8 @@ nouveau_bios_connector_entry(struct drm_device *, int index); + extern u32 get_pll_register(struct drm_device *, enum pll_types); + extern int get_pll_limits(struct drm_device *, uint32_t limit_match, + struct pll_lims *); +-extern int nouveau_bios_run_display_table(struct drm_device *, +- struct dcb_entry *, +- uint32_t script, int pxclk); +-extern void *nouveau_bios_dp_table(struct drm_device *, struct dcb_entry *, +- int *length); ++extern int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk, ++ struct dcb_entry *, int crtc); + extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *); + extern uint8_t *nouveau_bios_embedded_edid(struct drm_device *); + extern int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk, +@@ -1043,6 +1089,7 @@ extern int run_tmds_table(struct drm_device *, struct dcb_entry *, + int head, int pxclk); + extern int call_lvds_script(struct drm_device *, struct dcb_entry *, int head, + enum LVDS_script, int pxclk); ++bool bios_encoder_match(struct dcb_entry *, u32 hash); + + /* nouveau_ttm.c */ + int nouveau_ttm_global_init(struct drm_nouveau_private *); +@@ -1053,7 +1100,9 @@ int nouveau_ttm_mmap(struct file *, struct vm_area_struct *); + int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, + uint8_t *data, int data_nr); + bool nouveau_dp_detect(struct drm_encoder *); +-bool nouveau_dp_link_train(struct drm_encoder *); ++bool nouveau_dp_link_train(struct drm_encoder *, u32 datarate); ++void nouveau_dp_tu_update(struct drm_device *, int, int, u32, u32); ++u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_entry *, u8 **); + + /* nv04_fb.c */ + extern int nv04_fb_init(struct drm_device *); +@@ -1179,8 +1228,8 @@ extern int nva3_copy_create(struct drm_device *dev); + /* nvc0_copy.c */ + extern int nvc0_copy_create(struct drm_device *dev, int engine); + +-/* nv40_mpeg.c */ +-extern int nv40_mpeg_create(struct drm_device *dev); ++/* nv31_mpeg.c */ ++extern int nv31_mpeg_create(struct drm_device *dev); + + /* nv50_mpeg.c */ + extern int nv50_mpeg_create(struct drm_device *dev); +@@ -1265,6 +1314,11 @@ extern int nv04_display_create(struct drm_device *); + extern int nv04_display_init(struct drm_device *); + extern void nv04_display_destroy(struct drm_device *); + ++/* nvd0_display.c */ ++extern int nvd0_display_create(struct drm_device *); ++extern int nvd0_display_init(struct drm_device *); ++extern void nvd0_display_destroy(struct drm_device *); ++ + /* nv04_crtc.c */ + extern int nv04_crtc_create(struct drm_device *, int index); + +@@ -1374,6 +1428,8 @@ int nv50_gpio_init(struct drm_device *dev); + void nv50_gpio_fini(struct drm_device *dev); + int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); + int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); ++int nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); ++int nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); + int nv50_gpio_irq_register(struct drm_device *, enum dcb_gpio_tag, + void (*)(void *, int), void *); + void nv50_gpio_irq_unregister(struct drm_device *, enum dcb_gpio_tag, +@@ -1448,6 +1504,8 @@ static inline void nv_wr08(struct drm_device *dev, unsigned reg, u8 val) + nouveau_wait_eq(dev, 2000000000ULL, (reg), (mask), (val)) + #define nv_wait_ne(dev, reg, mask, val) \ + nouveau_wait_ne(dev, 2000000000ULL, (reg), (mask), (val)) ++#define nv_wait_cb(dev, func, data) \ ++ nouveau_wait_cb(dev, 2000000000ULL, (func), (data)) + + /* PRAMIN access */ + static inline u32 nv_ri32(struct drm_device *dev, unsigned offset) +@@ -1514,6 +1572,7 @@ enum { + NOUVEAU_REG_DEBUG_RMVIO = 0x80, + NOUVEAU_REG_DEBUG_VGAATTR = 0x100, + NOUVEAU_REG_DEBUG_EVO = 0x200, ++ NOUVEAU_REG_DEBUG_AUXCH = 0x400 + }; + + #define NV_REG_DEBUG(type, dev, fmt, arg...) do { \ +diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h +index ae69b61..e5d6e3f 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h ++++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h +@@ -49,17 +49,17 @@ struct nouveau_encoder { + + union { + struct { +- int mc_unknown; +- uint32_t unk0; +- uint32_t unk1; +- int dpcd_version; ++ u8 dpcd[8]; + int link_nr; + int link_bw; +- bool enhanced_frame; ++ u32 datarate; + } dp; + }; + }; + ++struct nouveau_encoder * ++find_encoder(struct drm_connector *connector, int type); ++ + static inline struct nouveau_encoder *nouveau_encoder(struct drm_encoder *enc) + { + struct drm_encoder_slave *slave = to_encoder_slave(enc); +@@ -83,21 +83,4 @@ nouveau_encoder_connector_get(struct nouveau_encoder *encoder); + int nv50_sor_create(struct drm_connector *, struct dcb_entry *); + int nv50_dac_create(struct drm_connector *, struct dcb_entry *); + +-struct bit_displayport_encoder_table { +- uint32_t match; +- uint8_t record_nr; +- uint8_t unknown; +- uint16_t script0; +- uint16_t script1; +- uint16_t unknown_table; +-} __attribute__ ((packed)); +- +-struct bit_displayport_encoder_table_entry { +- uint8_t vs_level; +- uint8_t pre_level; +- uint8_t reg0; +- uint8_t reg1; +- uint8_t reg2; +-} __attribute__ ((packed)); +- + #endif /* __NOUVEAU_ENCODER_H__ */ +diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c +index c919cfc..81116cf 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_fence.c ++++ b/drivers/gpu/drm/nouveau/nouveau_fence.c +@@ -519,7 +519,7 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) + if (USE_SEMA(dev) && dev_priv->chipset < 0x84) { + struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem; + +- ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, ++ ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_FROM_MEMORY, + mem->start << PAGE_SHIFT, + mem->size, NV_MEM_ACCESS_RW, + NV_MEM_TARGET_VRAM, &obj); +diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c +index cb389d0..f6a27fa 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_i2c.c ++++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c +@@ -107,6 +107,13 @@ nv4e_i2c_getsda(void *data) + return !!((nv_rd32(dev, i2c->rd) >> 16) & 8); + } + ++static const uint32_t nv50_i2c_port[] = { ++ 0x00e138, 0x00e150, 0x00e168, 0x00e180, ++ 0x00e254, 0x00e274, 0x00e764, 0x00e780, ++ 0x00e79c, 0x00e7b8 ++}; ++#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port) ++ + static int + nv50_i2c_getscl(void *data) + { +@@ -130,28 +137,32 @@ static void + nv50_i2c_setscl(void *data, int state) + { + struct nouveau_i2c_chan *i2c = data; +- struct drm_device *dev = i2c->dev; + +- nv_wr32(dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0)); ++ nv_wr32(i2c->dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0)); + } + + static void + nv50_i2c_setsda(void *data, int state) + { + struct nouveau_i2c_chan *i2c = data; +- struct drm_device *dev = i2c->dev; + +- nv_wr32(dev, i2c->wr, +- (nv_rd32(dev, i2c->rd) & 1) | 4 | (state ? 2 : 0)); ++ nv_mask(i2c->dev, i2c->wr, 0x00000006, 4 | (state ? 2 : 0)); + i2c->data = state; + } + +-static const uint32_t nv50_i2c_port[] = { +- 0x00e138, 0x00e150, 0x00e168, 0x00e180, +- 0x00e254, 0x00e274, 0x00e764, 0x00e780, +- 0x00e79c, 0x00e7b8 +-}; +-#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port) ++static int ++nvd0_i2c_getscl(void *data) ++{ ++ struct nouveau_i2c_chan *i2c = data; ++ return !!(nv_rd32(i2c->dev, i2c->rd) & 0x10); ++} ++ ++static int ++nvd0_i2c_getsda(void *data) ++{ ++ struct nouveau_i2c_chan *i2c = data; ++ return !!(nv_rd32(i2c->dev, i2c->rd) & 0x20); ++} + + int + nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) +@@ -163,7 +174,8 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) + if (entry->chan) + return -EEXIST; + +- if (dev_priv->card_type >= NV_50 && entry->read >= NV50_I2C_PORTS) { ++ if (dev_priv->card_type >= NV_50 && ++ dev_priv->card_type <= NV_C0 && entry->read >= NV50_I2C_PORTS) { + NV_ERROR(dev, "unknown i2c port %d\n", entry->read); + return -EINVAL; + } +@@ -192,10 +204,17 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) + case 5: + i2c->bit.setsda = nv50_i2c_setsda; + i2c->bit.setscl = nv50_i2c_setscl; +- i2c->bit.getsda = nv50_i2c_getsda; +- i2c->bit.getscl = nv50_i2c_getscl; +- i2c->rd = nv50_i2c_port[entry->read]; +- i2c->wr = i2c->rd; ++ if (dev_priv->card_type < NV_D0) { ++ i2c->bit.getsda = nv50_i2c_getsda; ++ i2c->bit.getscl = nv50_i2c_getscl; ++ i2c->rd = nv50_i2c_port[entry->read]; ++ i2c->wr = i2c->rd; ++ } else { ++ i2c->bit.getsda = nvd0_i2c_getsda; ++ i2c->bit.getscl = nvd0_i2c_getscl; ++ i2c->rd = 0x00d014 + (entry->read * 0x20); ++ i2c->wr = i2c->rd; ++ } + break; + case 6: + i2c->rd = entry->read; +@@ -267,7 +286,10 @@ nouveau_i2c_find(struct drm_device *dev, int index) + val = 0xe001; + } + +- nv_wr32(dev, reg, (nv_rd32(dev, reg) & ~0xf003) | val); ++ /* nfi, but neither auxch or i2c work if it's 1 */ ++ nv_mask(dev, reg + 0x0c, 0x00000001, 0x00000000); ++ /* nfi, but switches auxch vs normal i2c */ ++ nv_mask(dev, reg + 0x00, 0x0000f003, val); + } + + if (!i2c->chan && nouveau_i2c_init(dev, i2c, index)) +diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c +index f9ae2fc..36bec48 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_mem.c ++++ b/drivers/gpu/drm/nouveau/nouveau_mem.c +@@ -408,8 +408,6 @@ nouveau_mem_vram_init(struct drm_device *dev) + if (ret) + return ret; + +- dev_priv->fb_phys = pci_resource_start(dev->pdev, 1); +- + ret = nouveau_ttm_global_init(dev_priv); + if (ret) + return ret; +@@ -504,35 +502,146 @@ nouveau_mem_gart_init(struct drm_device *dev) + return 0; + } + ++/* XXX: For now a dummy. More samples required, possibly even a card ++ * Called from nouveau_perf.c */ ++void nv30_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, ++ struct nouveau_pm_tbl_entry *e, uint8_t magic_number, ++ struct nouveau_pm_memtiming *timing) { ++ ++ NV_DEBUG(dev,"Timing entry format unknown, please contact nouveau developers"); ++} ++ ++void nv40_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, ++ struct nouveau_pm_tbl_entry *e, uint8_t magic_number, ++ struct nouveau_pm_memtiming *timing) { ++ ++ timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP); ++ ++ /* XXX: I don't trust the -1's and +1's... they must come ++ * from somewhere! */ ++ timing->reg_1 = (e->tWR + 2 + magic_number) << 24 | ++ 1 << 16 | ++ (e->tUNK_1 + 2 + magic_number) << 8 | ++ (e->tCL + 2 - magic_number); ++ timing->reg_2 = (magic_number << 24 | e->tUNK_12 << 16 | e->tUNK_11 << 8 | e->tUNK_10); ++ timing->reg_2 |= 0x20200000; ++ ++ NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x\n", timing->id, ++ timing->reg_0, timing->reg_1,timing->reg_2); ++} ++ ++void nv50_mem_timing_entry(struct drm_device *dev, struct bit_entry *P, struct nouveau_pm_tbl_header *hdr, ++ struct nouveau_pm_tbl_entry *e, uint8_t magic_number,struct nouveau_pm_memtiming *timing) { ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ ++ uint8_t unk18 = 1, ++ unk19 = 1, ++ unk20 = 0, ++ unk21 = 0; ++ ++ switch (min(hdr->entry_len, (u8) 22)) { ++ case 22: ++ unk21 = e->tUNK_21; ++ case 21: ++ unk20 = e->tUNK_20; ++ case 20: ++ unk19 = e->tUNK_19; ++ case 19: ++ unk18 = e->tUNK_18; ++ break; ++ } ++ ++ timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP); ++ ++ /* XXX: I don't trust the -1's and +1's... they must come ++ * from somewhere! */ ++ timing->reg_1 = (e->tWR + unk19 + 1 + magic_number) << 24 | ++ max(unk18, (u8) 1) << 16 | ++ (e->tUNK_1 + unk19 + 1 + magic_number) << 8; ++ if (dev_priv->chipset == 0xa8) { ++ timing->reg_1 |= (e->tCL - 1); ++ } else { ++ timing->reg_1 |= (e->tCL + 2 - magic_number); ++ } ++ timing->reg_2 = (e->tUNK_12 << 16 | e->tUNK_11 << 8 | e->tUNK_10); ++ ++ timing->reg_5 = (e->tRAS << 24 | e->tRC); ++ timing->reg_5 += max(e->tUNK_10, e->tUNK_11) << 16; ++ ++ if (P->version == 1) { ++ timing->reg_2 |= magic_number << 24; ++ timing->reg_3 = (0x14 + e->tCL) << 24 | ++ 0x16 << 16 | ++ (e->tCL - 1) << 8 | ++ (e->tCL - 1); ++ timing->reg_4 = (nv_rd32(dev,0x10022c) & 0xffff0000) | e->tUNK_13 << 8 | e->tUNK_13; ++ timing->reg_5 |= (e->tCL + 2) << 8; ++ timing->reg_7 = 0x4000202 | (e->tCL - 1) << 16; ++ } else { ++ timing->reg_2 |= (unk19 - 1) << 24; ++ /* XXX: reg_10022c for recentish cards pretty much unknown*/ ++ timing->reg_3 = e->tCL - 1; ++ timing->reg_4 = (unk20 << 24 | unk21 << 16 | ++ e->tUNK_13 << 8 | e->tUNK_13); ++ /* XXX: +6? */ ++ timing->reg_5 |= (unk19 + 6) << 8; ++ ++ /* XXX: reg_10023c currently unknown ++ * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */ ++ timing->reg_7 = 0x202; ++ } ++ ++ NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", timing->id, ++ timing->reg_0, timing->reg_1, ++ timing->reg_2, timing->reg_3); ++ NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n", ++ timing->reg_4, timing->reg_5, ++ timing->reg_6, timing->reg_7); ++ NV_DEBUG(dev, " 240: %08x\n", timing->reg_8); ++} ++ ++void nvc0_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, ++ struct nouveau_pm_tbl_entry *e, struct nouveau_pm_memtiming *timing) { ++ timing->reg_0 = (e->tRC << 24 | (e->tRFC & 0x7f) << 17 | e->tRAS << 8 | e->tRP); ++ timing->reg_1 = (nv_rd32(dev,0x10f294) & 0xff000000) | (e->tUNK_11&0x0f) << 20 | (e->tUNK_19 << 7) | (e->tCL & 0x0f); ++ timing->reg_2 = (nv_rd32(dev,0x10f298) & 0xff0000ff) | e->tWR << 16 | e->tUNK_1 << 8; ++ timing->reg_3 = e->tUNK_20 << 9 | e->tUNK_13; ++ timing->reg_4 = (nv_rd32(dev,0x10f2a0) & 0xfff000ff) | e->tUNK_12 << 15; ++ NV_DEBUG(dev, "Entry %d: 290: %08x %08x %08x %08x\n", timing->id, ++ timing->reg_0, timing->reg_1, ++ timing->reg_2, timing->reg_3); ++ NV_DEBUG(dev, " 2a0: %08x %08x %08x %08x\n", ++ timing->reg_4, timing->reg_5, ++ timing->reg_6, timing->reg_7); ++} ++ ++/** ++ * Processes the Memory Timing BIOS table, stores generated ++ * register values ++ * @pre init scripts were run, memtiming regs are initialized ++ */ + void + nouveau_mem_timing_init(struct drm_device *dev) + { +- /* cards < NVC0 only */ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nouveau_pm_memtimings *memtimings = &pm->memtimings; + struct nvbios *bios = &dev_priv->vbios; + struct bit_entry P; +- u8 tUNK_0, tUNK_1, tUNK_2; +- u8 tRP; /* Byte 3 */ +- u8 tRAS; /* Byte 5 */ +- u8 tRFC; /* Byte 7 */ +- u8 tRC; /* Byte 9 */ +- u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14; +- u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21; +- u8 magic_number = 0; /* Yeah... sorry*/ +- u8 *mem = NULL, *entry; +- int i, recordlen, entries; ++ struct nouveau_pm_tbl_header *hdr = NULL; ++ uint8_t magic_number; ++ u8 *entry; ++ int i; + + if (bios->type == NVBIOS_BIT) { + if (bit_table(dev, 'P', &P)) + return; + + if (P.version == 1) +- mem = ROMPTR(bios, P.data[4]); ++ hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[4]); + else + if (P.version == 2) +- mem = ROMPTR(bios, P.data[8]); ++ hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[8]); + else { + NV_WARN(dev, "unknown mem for BIT P %d\n", P.version); + } +@@ -541,150 +650,56 @@ nouveau_mem_timing_init(struct drm_device *dev) + return; + } + +- if (!mem) { ++ if (!hdr) { + NV_DEBUG(dev, "memory timing table pointer invalid\n"); + return; + } + +- if (mem[0] != 0x10) { +- NV_WARN(dev, "memory timing table 0x%02x unknown\n", mem[0]); ++ if (hdr->version != 0x10) { ++ NV_WARN(dev, "memory timing table 0x%02x unknown\n", hdr->version); + return; + } + + /* validate record length */ +- entries = mem[2]; +- recordlen = mem[3]; +- if (recordlen < 15) { +- NV_ERROR(dev, "mem timing table length unknown: %d\n", mem[3]); ++ if (hdr->entry_len < 15) { ++ NV_ERROR(dev, "mem timing table length unknown: %d\n", hdr->entry_len); + return; + } + + /* parse vbios entries into common format */ + memtimings->timing = +- kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL); ++ kcalloc(hdr->entry_cnt, sizeof(*memtimings->timing), GFP_KERNEL); + if (!memtimings->timing) + return; + + /* Get "some number" from the timing reg for NV_40 and NV_50 +- * Used in calculations later */ +- if (dev_priv->card_type >= NV_40 && dev_priv->chipset < 0x98) { ++ * Used in calculations later... source unknown */ ++ magic_number = 0; ++ if (P.version == 1) { + magic_number = (nv_rd32(dev, 0x100228) & 0x0f000000) >> 24; + } + +- entry = mem + mem[1]; +- for (i = 0; i < entries; i++, entry += recordlen) { ++ entry = (u8*) hdr + hdr->header_len; ++ for (i = 0; i < hdr->entry_cnt; i++, entry += hdr->entry_len) { + struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i]; + if (entry[0] == 0) + continue; + +- tUNK_18 = 1; +- tUNK_19 = 1; +- tUNK_20 = 0; +- tUNK_21 = 0; +- switch (min(recordlen, 22)) { +- case 22: +- tUNK_21 = entry[21]; +- case 21: +- tUNK_20 = entry[20]; +- case 20: +- tUNK_19 = entry[19]; +- case 19: +- tUNK_18 = entry[18]; +- default: +- tUNK_0 = entry[0]; +- tUNK_1 = entry[1]; +- tUNK_2 = entry[2]; +- tRP = entry[3]; +- tRAS = entry[5]; +- tRFC = entry[7]; +- tRC = entry[9]; +- tUNK_10 = entry[10]; +- tUNK_11 = entry[11]; +- tUNK_12 = entry[12]; +- tUNK_13 = entry[13]; +- tUNK_14 = entry[14]; +- break; +- } +- +- timing->reg_100220 = (tRC << 24 | tRFC << 16 | tRAS << 8 | tRP); +- +- /* XXX: I don't trust the -1's and +1's... they must come +- * from somewhere! */ +- timing->reg_100224 = (tUNK_0 + tUNK_19 + 1 + magic_number) << 24 | +- max(tUNK_18, (u8) 1) << 16 | +- (tUNK_1 + tUNK_19 + 1 + magic_number) << 8; +- if (dev_priv->chipset == 0xa8) { +- timing->reg_100224 |= (tUNK_2 - 1); +- } else { +- timing->reg_100224 |= (tUNK_2 + 2 - magic_number); +- } +- +- timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10); +- if (dev_priv->chipset >= 0xa3 && dev_priv->chipset < 0xaa) +- timing->reg_100228 |= (tUNK_19 - 1) << 24; +- else +- timing->reg_100228 |= magic_number << 24; +- +- if (dev_priv->card_type == NV_40) { +- /* NV40: don't know what the rest of the regs are.. +- * And don't need to know either */ +- timing->reg_100228 |= 0x20200000; +- } else if (dev_priv->card_type >= NV_50) { +- if (dev_priv->chipset < 0x98 || +- (dev_priv->chipset == 0x98 && +- dev_priv->stepping <= 0xa1)) { +- timing->reg_10022c = (0x14 + tUNK_2) << 24 | +- 0x16 << 16 | +- (tUNK_2 - 1) << 8 | +- (tUNK_2 - 1); +- } else { +- /* XXX: reg_10022c for recentish cards */ +- timing->reg_10022c = tUNK_2 - 1; +- } +- +- timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 | +- tUNK_13 << 8 | tUNK_13); +- +- timing->reg_100234 = (tRAS << 24 | tRC); +- timing->reg_100234 += max(tUNK_10, tUNK_11) << 16; +- +- if (dev_priv->chipset < 0x98 || +- (dev_priv->chipset == 0x98 && +- dev_priv->stepping <= 0xa1)) { +- timing->reg_100234 |= (tUNK_2 + 2) << 8; +- } else { +- /* XXX: +6? */ +- timing->reg_100234 |= (tUNK_19 + 6) << 8; +- } +- +- /* XXX; reg_100238 +- * reg_100238: 0x00?????? */ +- timing->reg_10023c = 0x202; +- if (dev_priv->chipset < 0x98 || +- (dev_priv->chipset == 0x98 && +- dev_priv->stepping <= 0xa1)) { +- timing->reg_10023c |= 0x4000000 | (tUNK_2 - 1) << 16; +- } else { +- /* XXX: reg_10023c +- * currently unknown +- * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */ +- } +- +- /* XXX: reg_100240? */ +- } + timing->id = i; +- +- NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i, +- timing->reg_100220, timing->reg_100224, +- timing->reg_100228, timing->reg_10022c); +- NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n", +- timing->reg_100230, timing->reg_100234, +- timing->reg_100238, timing->reg_10023c); +- NV_DEBUG(dev, " 240: %08x\n", timing->reg_100240); ++ timing->WR = entry[0]; ++ timing->CL = entry[2]; ++ ++ if(dev_priv->card_type <= NV_40) { ++ nv40_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]); ++ } else if(dev_priv->card_type == NV_50){ ++ nv50_mem_timing_entry(dev,&P,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]); ++ } else if(dev_priv->card_type == NV_C0) { ++ nvc0_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,&pm->memtimings.timing[i]); ++ } + } + +- memtimings->nr_timing = entries; +- memtimings->supported = (dev_priv->chipset <= 0x98); ++ memtimings->nr_timing = hdr->entry_cnt; ++ memtimings->supported = P.version == 1; + } + + void +@@ -693,7 +708,10 @@ nouveau_mem_timing_fini(struct drm_device *dev) + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_memtimings *mem = &dev_priv->engine.pm.memtimings; + +- kfree(mem->timing); ++ if(mem->timing) { ++ kfree(mem->timing); ++ mem->timing = NULL; ++ } + } + + static int +diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.c b/drivers/gpu/drm/nouveau/nouveau_mm.c +index 1640dec..b29ffb3 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_mm.c ++++ b/drivers/gpu/drm/nouveau/nouveau_mm.c +@@ -27,7 +27,7 @@ + #include "nouveau_mm.h" + + static inline void +-region_put(struct nouveau_mm *rmm, struct nouveau_mm_node *a) ++region_put(struct nouveau_mm *mm, struct nouveau_mm_node *a) + { + list_del(&a->nl_entry); + list_del(&a->fl_entry); +@@ -35,7 +35,7 @@ region_put(struct nouveau_mm *rmm, struct nouveau_mm_node *a) + } + + static struct nouveau_mm_node * +-region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size) ++region_split(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) + { + struct nouveau_mm_node *b; + +@@ -57,33 +57,33 @@ region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size) + return b; + } + +-#define node(root, dir) ((root)->nl_entry.dir == &rmm->nodes) ? NULL : \ ++#define node(root, dir) ((root)->nl_entry.dir == &mm->nodes) ? NULL : \ + list_entry((root)->nl_entry.dir, struct nouveau_mm_node, nl_entry) + + void +-nouveau_mm_put(struct nouveau_mm *rmm, struct nouveau_mm_node *this) ++nouveau_mm_put(struct nouveau_mm *mm, struct nouveau_mm_node *this) + { + struct nouveau_mm_node *prev = node(this, prev); + struct nouveau_mm_node *next = node(this, next); + +- list_add(&this->fl_entry, &rmm->free); ++ list_add(&this->fl_entry, &mm->free); + this->type = 0; + + if (prev && prev->type == 0) { + prev->length += this->length; +- region_put(rmm, this); ++ region_put(mm, this); + this = prev; + } + + if (next && next->type == 0) { + next->offset = this->offset; + next->length += this->length; +- region_put(rmm, this); ++ region_put(mm, this); + } + } + + int +-nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc, ++nouveau_mm_get(struct nouveau_mm *mm, int type, u32 size, u32 size_nc, + u32 align, struct nouveau_mm_node **pnode) + { + struct nouveau_mm_node *prev, *this, *next; +@@ -92,17 +92,17 @@ nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc, + u32 splitoff; + u32 s, e; + +- list_for_each_entry(this, &rmm->free, fl_entry) { ++ list_for_each_entry(this, &mm->free, fl_entry) { + e = this->offset + this->length; + s = this->offset; + + prev = node(this, prev); + if (prev && prev->type != type) +- s = roundup(s, rmm->block_size); ++ s = roundup(s, mm->block_size); + + next = node(this, next); + if (next && next->type != type) +- e = rounddown(e, rmm->block_size); ++ e = rounddown(e, mm->block_size); + + s = (s + align_mask) & ~align_mask; + e &= ~align_mask; +@@ -110,10 +110,10 @@ nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc, + continue; + + splitoff = s - this->offset; +- if (splitoff && !region_split(rmm, this, splitoff)) ++ if (splitoff && !region_split(mm, this, splitoff)) + return -ENOMEM; + +- this = region_split(rmm, this, min(size, e - s)); ++ this = region_split(mm, this, min(size, e - s)); + if (!this) + return -ENOMEM; + +@@ -127,52 +127,49 @@ nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc, + } + + int +-nouveau_mm_init(struct nouveau_mm **prmm, u32 offset, u32 length, u32 block) ++nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block) + { +- struct nouveau_mm *rmm; +- struct nouveau_mm_node *heap; ++ struct nouveau_mm_node *node; ++ ++ if (block) { ++ mutex_init(&mm->mutex); ++ INIT_LIST_HEAD(&mm->nodes); ++ INIT_LIST_HEAD(&mm->free); ++ mm->block_size = block; ++ mm->heap_nodes = 0; ++ } + +- heap = kzalloc(sizeof(*heap), GFP_KERNEL); +- if (!heap) ++ node = kzalloc(sizeof(*node), GFP_KERNEL); ++ if (!node) + return -ENOMEM; +- heap->offset = roundup(offset, block); +- heap->length = rounddown(offset + length, block) - heap->offset; ++ node->offset = roundup(offset, mm->block_size); ++ node->length = rounddown(offset + length, mm->block_size) - node->offset; + +- rmm = kzalloc(sizeof(*rmm), GFP_KERNEL); +- if (!rmm) { +- kfree(heap); +- return -ENOMEM; +- } +- rmm->block_size = block; +- mutex_init(&rmm->mutex); +- INIT_LIST_HEAD(&rmm->nodes); +- INIT_LIST_HEAD(&rmm->free); +- list_add(&heap->nl_entry, &rmm->nodes); +- list_add(&heap->fl_entry, &rmm->free); +- +- *prmm = rmm; ++ list_add_tail(&node->nl_entry, &mm->nodes); ++ list_add_tail(&node->fl_entry, &mm->free); ++ mm->heap_nodes++; + return 0; + } + + int +-nouveau_mm_fini(struct nouveau_mm **prmm) ++nouveau_mm_fini(struct nouveau_mm *mm) + { +- struct nouveau_mm *rmm = *prmm; + struct nouveau_mm_node *node, *heap = +- list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry); +- +- if (!list_is_singular(&rmm->nodes)) { +- printk(KERN_ERR "nouveau_mm not empty at destroy time!\n"); +- list_for_each_entry(node, &rmm->nodes, nl_entry) { +- printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n", +- node->type, node->offset, node->length); ++ list_first_entry(&mm->nodes, struct nouveau_mm_node, nl_entry); ++ int nodes = 0; ++ ++ list_for_each_entry(node, &mm->nodes, nl_entry) { ++ if (nodes++ == mm->heap_nodes) { ++ printk(KERN_ERR "nouveau_mm in use at destroy time!\n"); ++ list_for_each_entry(node, &mm->nodes, nl_entry) { ++ printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n", ++ node->type, node->offset, node->length); ++ } ++ WARN_ON(1); ++ return -EBUSY; + } +- WARN_ON(1); +- return -EBUSY; + } + + kfree(heap); +- kfree(rmm); +- *prmm = NULL; + return 0; + } +diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.h b/drivers/gpu/drm/nouveau/nouveau_mm.h +index b9c016d..57a600c 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_mm.h ++++ b/drivers/gpu/drm/nouveau/nouveau_mm.h +@@ -42,10 +42,11 @@ struct nouveau_mm { + struct mutex mutex; + + u32 block_size; ++ int heap_nodes; + }; + +-int nouveau_mm_init(struct nouveau_mm **, u32 offset, u32 length, u32 block); +-int nouveau_mm_fini(struct nouveau_mm **); ++int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block); ++int nouveau_mm_fini(struct nouveau_mm *); + int nouveau_mm_pre(struct nouveau_mm *); + int nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc, + u32 align, struct nouveau_mm_node **); +diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c +index 159b7c4..02222c5 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_object.c ++++ b/drivers/gpu/drm/nouveau/nouveau_object.c +@@ -693,6 +693,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) + static int + nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm) + { ++ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct drm_device *dev = chan->dev; + struct nouveau_gpuobj *pgd = NULL; + struct nouveau_vm_pgd *vpgd; +@@ -722,6 +723,9 @@ nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm) + nv_wo32(chan->ramin, 0x020c, 0x000000ff); + + /* map display semaphore buffers into channel's vm */ ++ if (dev_priv->card_type >= NV_D0) ++ return 0; ++ + for (i = 0; i < 2; i++) { + struct nv50_display_crtc *dispc = &nv50_display(dev)->crtc[i]; + +@@ -746,7 +750,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, + int ret, i; + + NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); +- if (dev_priv->card_type == NV_C0) ++ if (dev_priv->card_type >= NV_C0) + return nvc0_gpuobj_channel_init(chan, vm); + + /* Allocate a chunk of memory for per-channel object storage */ +@@ -793,7 +797,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, + return ret; + + /* dma objects for display sync channel semaphore blocks */ +- for (i = 0; i < 2; i++) { ++ for (i = 0; i < dev->mode_config.num_crtc; i++) { + struct nouveau_gpuobj *sem = NULL; + struct nv50_display_crtc *dispc = + &nv50_display(dev)->crtc[i]; +@@ -875,18 +879,18 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) + + NV_DEBUG(dev, "ch%d\n", chan->id); + +- if (dev_priv->card_type >= NV_50) { ++ if (dev_priv->card_type >= NV_50 && dev_priv->card_type <= NV_C0) { + struct nv50_display *disp = nv50_display(dev); + +- for (i = 0; i < 2; i++) { ++ for (i = 0; i < dev->mode_config.num_crtc; i++) { + struct nv50_display_crtc *dispc = &disp->crtc[i]; + nouveau_bo_vma_del(dispc->sem.bo, &chan->dispc_vma[i]); + } +- +- nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); +- nouveau_gpuobj_ref(NULL, &chan->vm_pd); + } + ++ nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); ++ nouveau_gpuobj_ref(NULL, &chan->vm_pd); ++ + if (drm_mm_initialized(&chan->ramin_heap)) + drm_mm_takedown(&chan->ramin_heap); + nouveau_gpuobj_ref(NULL, &chan->ramin); +diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c +index ef9dec0..9f178aa 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_perf.c ++++ b/drivers/gpu/drm/nouveau/nouveau_perf.c +@@ -127,13 +127,57 @@ nouveau_perf_timing(struct drm_device *dev, struct bit_entry *P, + + entry += ramcfg * recordlen; + if (entry[1] >= pm->memtimings.nr_timing) { +- NV_WARN(dev, "timingset %d does not exist\n", entry[1]); ++ if (entry[1] != 0xff) ++ NV_WARN(dev, "timingset %d does not exist\n", entry[1]); + return NULL; + } + + return &pm->memtimings.timing[entry[1]]; + } + ++static void ++nouveau_perf_voltage(struct drm_device *dev, struct bit_entry *P, ++ struct nouveau_pm_level *perflvl) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nvbios *bios = &dev_priv->vbios; ++ u8 *vmap; ++ int id; ++ ++ id = perflvl->volt_min; ++ perflvl->volt_min = 0; ++ ++ /* boards using voltage table version <0x40 store the voltage ++ * level directly in the perflvl entry as a multiple of 10mV ++ */ ++ if (dev_priv->engine.pm.voltage.version < 0x40) { ++ perflvl->volt_min = id * 10000; ++ perflvl->volt_max = perflvl->volt_min; ++ return; ++ } ++ ++ /* on newer ones, the perflvl stores an index into yet another ++ * vbios table containing a min/max voltage value for the perflvl ++ */ ++ if (P->version != 2 || P->length < 34) { ++ NV_DEBUG(dev, "where's our volt map table ptr? %d %d\n", ++ P->version, P->length); ++ return; ++ } ++ ++ vmap = ROMPTR(bios, P->data[32]); ++ if (!vmap) { ++ NV_DEBUG(dev, "volt map table pointer invalid\n"); ++ return; ++ } ++ ++ if (id < vmap[3]) { ++ vmap += vmap[1] + (vmap[2] * id); ++ perflvl->volt_min = ROM32(vmap[0]); ++ perflvl->volt_max = ROM32(vmap[4]); ++ } ++} ++ + void + nouveau_perf_init(struct drm_device *dev) + { +@@ -141,6 +185,8 @@ nouveau_perf_init(struct drm_device *dev) + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct nvbios *bios = &dev_priv->vbios; + struct bit_entry P; ++ struct nouveau_pm_memtimings *memtimings = &pm->memtimings; ++ struct nouveau_pm_tbl_header mt_hdr; + u8 version, headerlen, recordlen, entries; + u8 *perf, *entry; + int vid, i; +@@ -188,6 +234,22 @@ nouveau_perf_init(struct drm_device *dev) + } + + entry = perf + headerlen; ++ ++ /* For version 0x15, initialize memtiming table */ ++ if(version == 0x15) { ++ memtimings->timing = ++ kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL); ++ if(!memtimings) { ++ NV_WARN(dev,"Could not allocate memtiming table\n"); ++ return; ++ } ++ ++ mt_hdr.entry_cnt = entries; ++ mt_hdr.entry_len = 14; ++ mt_hdr.version = version; ++ mt_hdr.header_len = 4; ++ } ++ + for (i = 0; i < entries; i++) { + struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; + +@@ -203,7 +265,8 @@ nouveau_perf_init(struct drm_device *dev) + case 0x13: + case 0x15: + perflvl->fanspeed = entry[55]; +- perflvl->voltage = (recordlen > 56) ? entry[56] : 0; ++ if (recordlen > 56) ++ perflvl->volt_min = entry[56]; + perflvl->core = ROM32(entry[1]) * 10; + perflvl->memory = ROM32(entry[5]) * 20; + break; +@@ -211,9 +274,10 @@ nouveau_perf_init(struct drm_device *dev) + case 0x23: + case 0x24: + perflvl->fanspeed = entry[4]; +- perflvl->voltage = entry[5]; +- perflvl->core = ROM16(entry[6]) * 1000; +- ++ perflvl->volt_min = entry[5]; ++ perflvl->shader = ROM16(entry[6]) * 1000; ++ perflvl->core = perflvl->shader; ++ perflvl->core += (signed char)entry[8] * 1000; + if (dev_priv->chipset == 0x49 || + dev_priv->chipset == 0x4b) + perflvl->memory = ROM16(entry[11]) * 1000; +@@ -223,7 +287,7 @@ nouveau_perf_init(struct drm_device *dev) + break; + case 0x25: + perflvl->fanspeed = entry[4]; +- perflvl->voltage = entry[5]; ++ perflvl->volt_min = entry[5]; + perflvl->core = ROM16(entry[6]) * 1000; + perflvl->shader = ROM16(entry[10]) * 1000; + perflvl->memory = ROM16(entry[12]) * 1000; +@@ -232,7 +296,7 @@ nouveau_perf_init(struct drm_device *dev) + perflvl->memscript = ROM16(entry[2]); + case 0x35: + perflvl->fanspeed = entry[6]; +- perflvl->voltage = entry[7]; ++ perflvl->volt_min = entry[7]; + perflvl->core = ROM16(entry[8]) * 1000; + perflvl->shader = ROM16(entry[10]) * 1000; + perflvl->memory = ROM16(entry[12]) * 1000; +@@ -240,30 +304,34 @@ nouveau_perf_init(struct drm_device *dev) + perflvl->unk05 = ROM16(entry[16]) * 1000; + break; + case 0x40: +-#define subent(n) entry[perf[2] + ((n) * perf[3])] ++#define subent(n) (ROM16(entry[perf[2] + ((n) * perf[3])]) & 0xfff) * 1000 + perflvl->fanspeed = 0; /*XXX*/ +- perflvl->voltage = entry[2]; ++ perflvl->volt_min = entry[2]; + if (dev_priv->card_type == NV_50) { +- perflvl->core = ROM16(subent(0)) & 0xfff; +- perflvl->shader = ROM16(subent(1)) & 0xfff; +- perflvl->memory = ROM16(subent(2)) & 0xfff; ++ perflvl->core = subent(0); ++ perflvl->shader = subent(1); ++ perflvl->memory = subent(2); ++ perflvl->vdec = subent(3); ++ perflvl->unka0 = subent(4); + } else { +- perflvl->shader = ROM16(subent(3)) & 0xfff; ++ perflvl->hub06 = subent(0); ++ perflvl->hub01 = subent(1); ++ perflvl->copy = subent(2); ++ perflvl->shader = subent(3); ++ perflvl->rop = subent(4); ++ perflvl->memory = subent(5); ++ perflvl->vdec = subent(6); ++ perflvl->daemon = subent(10); ++ perflvl->hub07 = subent(11); + perflvl->core = perflvl->shader / 2; +- perflvl->unk0a = ROM16(subent(4)) & 0xfff; +- perflvl->memory = ROM16(subent(5)) & 0xfff; + } +- +- perflvl->core *= 1000; +- perflvl->shader *= 1000; +- perflvl->memory *= 1000; +- perflvl->unk0a *= 1000; + break; + } + + /* make sure vid is valid */ +- if (pm->voltage.supported && perflvl->voltage) { +- vid = nouveau_volt_vid_lookup(dev, perflvl->voltage); ++ nouveau_perf_voltage(dev, &P, perflvl); ++ if (pm->voltage.supported && perflvl->volt_min) { ++ vid = nouveau_volt_vid_lookup(dev, perflvl->volt_min); + if (vid < 0) { + NV_DEBUG(dev, "drop perflvl %d, bad vid\n", i); + entry += recordlen; +@@ -272,7 +340,11 @@ nouveau_perf_init(struct drm_device *dev) + } + + /* get the corresponding memory timings */ +- if (version > 0x15) { ++ if (version == 0x15) { ++ memtimings->timing[i].id = i; ++ nv30_mem_timing_entry(dev,&mt_hdr,(struct nouveau_pm_tbl_entry*) &entry[41],0,&memtimings->timing[i]); ++ perflvl->timing = &memtimings->timing[i]; ++ } else if (version > 0x15) { + /* last 3 args are for < 0x40, ignored for >= 0x40 */ + perflvl->timing = + nouveau_perf_timing(dev, &P, +diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c +index da8d994..a539fd2 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_pm.c ++++ b/drivers/gpu/drm/nouveau/nouveau_pm.c +@@ -64,18 +64,26 @@ nouveau_pm_perflvl_set(struct drm_device *dev, struct nouveau_pm_level *perflvl) + if (perflvl == pm->cur) + return 0; + +- if (pm->voltage.supported && pm->voltage_set && perflvl->voltage) { +- ret = pm->voltage_set(dev, perflvl->voltage); ++ if (pm->voltage.supported && pm->voltage_set && perflvl->volt_min) { ++ ret = pm->voltage_set(dev, perflvl->volt_min); + if (ret) { + NV_ERROR(dev, "voltage_set %d failed: %d\n", +- perflvl->voltage, ret); ++ perflvl->volt_min, ret); + } + } + +- nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core); +- nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader); +- nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory); +- nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05); ++ if (pm->clocks_pre) { ++ void *state = pm->clocks_pre(dev, perflvl); ++ if (IS_ERR(state)) ++ return PTR_ERR(state); ++ pm->clocks_set(dev, state); ++ } else ++ if (pm->clock_set) { ++ nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core); ++ nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader); ++ nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory); ++ nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05); ++ } + + pm->cur = perflvl; + return 0; +@@ -92,9 +100,6 @@ nouveau_pm_profile_set(struct drm_device *dev, const char *profile) + if (nouveau_perflvl_wr != 7777) + return -EPERM; + +- if (!pm->clock_set) +- return -EINVAL; +- + if (!strncmp(profile, "boot", 4)) + perflvl = &pm->boot; + else { +@@ -123,31 +128,37 @@ nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + int ret; + +- if (!pm->clock_get) +- return -EINVAL; +- + memset(perflvl, 0, sizeof(*perflvl)); + +- ret = pm->clock_get(dev, PLL_CORE); +- if (ret > 0) +- perflvl->core = ret; ++ if (pm->clocks_get) { ++ ret = pm->clocks_get(dev, perflvl); ++ if (ret) ++ return ret; ++ } else ++ if (pm->clock_get) { ++ ret = pm->clock_get(dev, PLL_CORE); ++ if (ret > 0) ++ perflvl->core = ret; + +- ret = pm->clock_get(dev, PLL_MEMORY); +- if (ret > 0) +- perflvl->memory = ret; ++ ret = pm->clock_get(dev, PLL_MEMORY); ++ if (ret > 0) ++ perflvl->memory = ret; + +- ret = pm->clock_get(dev, PLL_SHADER); +- if (ret > 0) +- perflvl->shader = ret; ++ ret = pm->clock_get(dev, PLL_SHADER); ++ if (ret > 0) ++ perflvl->shader = ret; + +- ret = pm->clock_get(dev, PLL_UNK05); +- if (ret > 0) +- perflvl->unk05 = ret; ++ ret = pm->clock_get(dev, PLL_UNK05); ++ if (ret > 0) ++ perflvl->unk05 = ret; ++ } + + if (pm->voltage.supported && pm->voltage_get) { + ret = pm->voltage_get(dev); +- if (ret > 0) +- perflvl->voltage = ret; ++ if (ret > 0) { ++ perflvl->volt_min = ret; ++ perflvl->volt_max = ret; ++ } + } + + return 0; +@@ -156,7 +167,7 @@ nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) + static void + nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) + { +- char c[16], s[16], v[16], f[16], t[16]; ++ char c[16], s[16], v[32], f[16], t[16], m[16]; + + c[0] = '\0'; + if (perflvl->core) +@@ -166,9 +177,19 @@ nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) + if (perflvl->shader) + snprintf(s, sizeof(s), " shader %dMHz", perflvl->shader / 1000); + ++ m[0] = '\0'; ++ if (perflvl->memory) ++ snprintf(m, sizeof(m), " memory %dMHz", perflvl->memory / 1000); ++ + v[0] = '\0'; +- if (perflvl->voltage) +- snprintf(v, sizeof(v), " voltage %dmV", perflvl->voltage * 10); ++ if (perflvl->volt_min && perflvl->volt_min != perflvl->volt_max) { ++ snprintf(v, sizeof(v), " voltage %dmV-%dmV", ++ perflvl->volt_min / 1000, perflvl->volt_max / 1000); ++ } else ++ if (perflvl->volt_min) { ++ snprintf(v, sizeof(v), " voltage %dmV", ++ perflvl->volt_min / 1000); ++ } + + f[0] = '\0'; + if (perflvl->fanspeed) +@@ -178,8 +199,7 @@ nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) + if (perflvl->timing) + snprintf(t, sizeof(t), " timing %d", perflvl->timing->id); + +- snprintf(ptr, len, "memory %dMHz%s%s%s%s%s\n", perflvl->memory / 1000, +- c, s, v, f, t); ++ snprintf(ptr, len, "%s%s%s%s%s%s\n", c, s, m, t, v, f); + } + + static ssize_t +@@ -190,7 +210,7 @@ nouveau_pm_get_perflvl_info(struct device *d, + char *ptr = buf; + int len = PAGE_SIZE; + +- snprintf(ptr, len, "%d: ", perflvl->id); ++ snprintf(ptr, len, "%d:", perflvl->id); + ptr += strlen(buf); + len -= strlen(buf); + +@@ -211,9 +231,9 @@ nouveau_pm_get_perflvl(struct device *d, struct device_attribute *a, char *buf) + if (!pm->cur) + snprintf(ptr, len, "setting: boot\n"); + else if (pm->cur == &pm->boot) +- snprintf(ptr, len, "setting: boot\nc: "); ++ snprintf(ptr, len, "setting: boot\nc:"); + else +- snprintf(ptr, len, "setting: static %d\nc: ", pm->cur->id); ++ snprintf(ptr, len, "setting: static %d\nc:", pm->cur->id); + ptr += strlen(buf); + len -= strlen(buf); + +@@ -292,7 +312,7 @@ nouveau_sysfs_fini(struct drm_device *dev) + } + } + +-#ifdef CONFIG_HWMON ++#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) + static ssize_t + nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) + { +@@ -409,7 +429,7 @@ static const struct attribute_group hwmon_attrgroup = { + static int + nouveau_hwmon_init(struct drm_device *dev) + { +-#ifdef CONFIG_HWMON ++#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + struct device *hwmon_dev; +@@ -442,7 +462,7 @@ nouveau_hwmon_init(struct drm_device *dev) + static void + nouveau_hwmon_fini(struct drm_device *dev) + { +-#ifdef CONFIG_HWMON ++#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pm_engine *pm = &dev_priv->engine.pm; + +@@ -488,7 +508,7 @@ nouveau_pm_init(struct drm_device *dev) + NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl); + for (i = 0; i < pm->nr_perflvl; i++) { + nouveau_pm_perflvl_info(&pm->perflvl[i], info, sizeof(info)); +- NV_INFO(dev, "%d: %s", pm->perflvl[i].id, info); ++ NV_INFO(dev, "%d:%s", pm->perflvl[i].id, info); + } + + /* determine current ("boot") performance level */ +@@ -498,7 +518,7 @@ nouveau_pm_init(struct drm_device *dev) + pm->cur = &pm->boot; + + nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info)); +- NV_INFO(dev, "c: %s", info); ++ NV_INFO(dev, "c:%s", info); + } + + /* switch performance levels now if requested */ +diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.h b/drivers/gpu/drm/nouveau/nouveau_pm.h +index 4a9838dd..8ac02cd 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_pm.h ++++ b/drivers/gpu/drm/nouveau/nouveau_pm.h +@@ -52,6 +52,11 @@ void *nv04_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, + u32 id, int khz); + void nv04_pm_clock_set(struct drm_device *, void *); + ++/* nv40_pm.c */ ++int nv40_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); ++void *nv40_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); ++void nv40_pm_clocks_set(struct drm_device *, void *); ++ + /* nv50_pm.c */ + int nv50_pm_clock_get(struct drm_device *, u32 id); + void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, +@@ -59,10 +64,12 @@ void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, + void nv50_pm_clock_set(struct drm_device *, void *); + + /* nva3_pm.c */ +-int nva3_pm_clock_get(struct drm_device *, u32 id); +-void *nva3_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, +- u32 id, int khz); +-void nva3_pm_clock_set(struct drm_device *, void *); ++int nva3_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); ++void *nva3_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); ++void nva3_pm_clocks_set(struct drm_device *, void *); ++ ++/* nvc0_pm.c */ ++int nvc0_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); + + /* nouveau_temp.c */ + void nouveau_temp_init(struct drm_device *dev); +diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h +index f18cdfc..43a96b9 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_reg.h ++++ b/drivers/gpu/drm/nouveau/nouveau_reg.h +@@ -826,9 +826,12 @@ + #define NV50_PDISPLAY_SOR_DPMS_STATE_ACTIVE 0x00030000 + #define NV50_PDISPLAY_SOR_DPMS_STATE_BLANKED 0x00080000 + #define NV50_PDISPLAY_SOR_DPMS_STATE_WAIT 0x10000000 +-#define NV50_PDISPLAY_SOR_BACKLIGHT 0x0061c084 +-#define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE 0x80000000 +-#define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL 0x00000fff ++#define NV50_PDISP_SOR_PWM_DIV(i) (0x0061c080 + (i) * 0x800) ++#define NV50_PDISP_SOR_PWM_CTL(i) (0x0061c084 + (i) * 0x800) ++#define NV50_PDISP_SOR_PWM_CTL_NEW 0x80000000 ++#define NVA3_PDISP_SOR_PWM_CTL_UNK 0x40000000 ++#define NV50_PDISP_SOR_PWM_CTL_VAL 0x000007ff ++#define NVA3_PDISP_SOR_PWM_CTL_VAL 0x00ffffff + #define NV50_SOR_DP_CTRL(i, l) (0x0061c10c + (i) * 0x800 + (l) * 0x80) + #define NV50_SOR_DP_CTRL_ENABLED 0x00000001 + #define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED 0x00004000 +@@ -843,7 +846,7 @@ + #define NV50_SOR_DP_CTRL_TRAINING_PATTERN_2 0x02000000 + #define NV50_SOR_DP_UNK118(i, l) (0x0061c118 + (i) * 0x800 + (l) * 0x80) + #define NV50_SOR_DP_UNK120(i, l) (0x0061c120 + (i) * 0x800 + (l) * 0x80) +-#define NV50_SOR_DP_UNK128(i, l) (0x0061c128 + (i) * 0x800 + (l) * 0x80) ++#define NV50_SOR_DP_SCFG(i, l) (0x0061c128 + (i) * 0x800 + (l) * 0x80) + #define NV50_SOR_DP_UNK130(i, l) (0x0061c130 + (i) * 0x800 + (l) * 0x80) + + #define NV50_PDISPLAY_USER(i) ((i) * 0x1000 + 0x00640000) +diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c +index 2706cb3..b75258a 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c ++++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c +@@ -12,8 +12,8 @@ struct nouveau_sgdma_be { + struct drm_device *dev; + + dma_addr_t *pages; +- bool *ttm_alloced; + unsigned nr_pages; ++ bool unmap_pages; + + u64 offset; + bool bound; +@@ -26,43 +26,28 @@ nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages, + { + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; + struct drm_device *dev = nvbe->dev; ++ int i; + + NV_DEBUG(nvbe->dev, "num_pages = %ld\n", num_pages); + +- if (nvbe->pages) +- return -EINVAL; +- +- nvbe->pages = kmalloc(sizeof(dma_addr_t) * num_pages, GFP_KERNEL); +- if (!nvbe->pages) +- return -ENOMEM; ++ nvbe->pages = dma_addrs; ++ nvbe->nr_pages = num_pages; ++ nvbe->unmap_pages = true; + +- nvbe->ttm_alloced = kmalloc(sizeof(bool) * num_pages, GFP_KERNEL); +- if (!nvbe->ttm_alloced) { +- kfree(nvbe->pages); +- nvbe->pages = NULL; +- return -ENOMEM; ++ /* this code path isn't called and is incorrect anyways */ ++ if (0) { /* dma_addrs[0] != DMA_ERROR_CODE) { */ ++ nvbe->unmap_pages = false; ++ return 0; + } + +- nvbe->nr_pages = 0; +- while (num_pages--) { +- /* this code path isn't called and is incorrect anyways */ +- if (0) { /*dma_addrs[nvbe->nr_pages] != DMA_ERROR_CODE)*/ +- nvbe->pages[nvbe->nr_pages] = +- dma_addrs[nvbe->nr_pages]; +- nvbe->ttm_alloced[nvbe->nr_pages] = true; +- } else { +- nvbe->pages[nvbe->nr_pages] = +- pci_map_page(dev->pdev, pages[nvbe->nr_pages], 0, +- PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); +- if (pci_dma_mapping_error(dev->pdev, +- nvbe->pages[nvbe->nr_pages])) { +- be->func->clear(be); +- return -EFAULT; +- } +- nvbe->ttm_alloced[nvbe->nr_pages] = false; ++ for (i = 0; i < num_pages; i++) { ++ nvbe->pages[i] = pci_map_page(dev->pdev, pages[i], 0, ++ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); ++ if (pci_dma_mapping_error(dev->pdev, nvbe->pages[i])) { ++ nvbe->nr_pages = --i; ++ be->func->clear(be); ++ return -EFAULT; + } +- +- nvbe->nr_pages++; + } + + return 0; +@@ -72,25 +57,16 @@ static void + nouveau_sgdma_clear(struct ttm_backend *be) + { + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; +- struct drm_device *dev; +- +- if (nvbe && nvbe->pages) { +- dev = nvbe->dev; +- NV_DEBUG(dev, "\n"); ++ struct drm_device *dev = nvbe->dev; + +- if (nvbe->bound) +- be->func->unbind(be); ++ if (nvbe->bound) ++ be->func->unbind(be); + ++ if (nvbe->unmap_pages) { + while (nvbe->nr_pages--) { +- if (!nvbe->ttm_alloced[nvbe->nr_pages]) +- pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages], ++ pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages], + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + } +- kfree(nvbe->pages); +- kfree(nvbe->ttm_alloced); +- nvbe->pages = NULL; +- nvbe->ttm_alloced = NULL; +- nvbe->nr_pages = 0; + } + } + +diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c +index 10656e4..82478e0 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_state.c ++++ b/drivers/gpu/drm/nouveau/nouveau_state.c +@@ -286,9 +286,9 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->gpio.get = nv10_gpio_get; + engine->gpio.set = nv10_gpio_set; + engine->gpio.irq_enable = NULL; +- engine->pm.clock_get = nv04_pm_clock_get; +- engine->pm.clock_pre = nv04_pm_clock_pre; +- engine->pm.clock_set = nv04_pm_clock_set; ++ engine->pm.clocks_get = nv40_pm_clocks_get; ++ engine->pm.clocks_pre = nv40_pm_clocks_pre; ++ engine->pm.clocks_set = nv40_pm_clocks_set; + engine->pm.voltage_get = nouveau_voltage_gpio_get; + engine->pm.voltage_set = nouveau_voltage_gpio_set; + engine->pm.temp_get = nv40_temp_get; +@@ -299,7 +299,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + case 0x50: + case 0x80: /* gotta love NVIDIA's consistency.. */ + case 0x90: +- case 0xA0: ++ case 0xa0: + engine->instmem.init = nv50_instmem_init; + engine->instmem.takedown = nv50_instmem_takedown; + engine->instmem.suspend = nv50_instmem_suspend; +@@ -359,9 +359,9 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->pm.clock_set = nv50_pm_clock_set; + break; + default: +- engine->pm.clock_get = nva3_pm_clock_get; +- engine->pm.clock_pre = nva3_pm_clock_pre; +- engine->pm.clock_set = nva3_pm_clock_set; ++ engine->pm.clocks_get = nva3_pm_clocks_get; ++ engine->pm.clocks_pre = nva3_pm_clocks_pre; ++ engine->pm.clocks_set = nva3_pm_clocks_set; + break; + } + engine->pm.voltage_get = nouveau_voltage_gpio_get; +@@ -376,7 +376,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->vram.put = nv50_vram_del; + engine->vram.flags_valid = nv50_vram_flags_valid; + break; +- case 0xC0: ++ case 0xc0: + engine->instmem.init = nvc0_instmem_init; + engine->instmem.takedown = nvc0_instmem_takedown; + engine->instmem.suspend = nvc0_instmem_suspend; +@@ -422,12 +422,73 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->vram.put = nv50_vram_del; + engine->vram.flags_valid = nvc0_vram_flags_valid; + engine->pm.temp_get = nv84_temp_get; ++ engine->pm.clocks_get = nvc0_pm_clocks_get; ++ engine->pm.voltage_get = nouveau_voltage_gpio_get; ++ engine->pm.voltage_set = nouveau_voltage_gpio_set; ++ break; ++ case 0xd0: ++ engine->instmem.init = nvc0_instmem_init; ++ engine->instmem.takedown = nvc0_instmem_takedown; ++ engine->instmem.suspend = nvc0_instmem_suspend; ++ engine->instmem.resume = nvc0_instmem_resume; ++ engine->instmem.get = nv50_instmem_get; ++ engine->instmem.put = nv50_instmem_put; ++ engine->instmem.map = nv50_instmem_map; ++ engine->instmem.unmap = nv50_instmem_unmap; ++ engine->instmem.flush = nv84_instmem_flush; ++ engine->mc.init = nv50_mc_init; ++ engine->mc.takedown = nv50_mc_takedown; ++ engine->timer.init = nv04_timer_init; ++ engine->timer.read = nv04_timer_read; ++ engine->timer.takedown = nv04_timer_takedown; ++ engine->fb.init = nvc0_fb_init; ++ engine->fb.takedown = nvc0_fb_takedown; ++ engine->fifo.channels = 128; ++ engine->fifo.init = nvc0_fifo_init; ++ engine->fifo.takedown = nvc0_fifo_takedown; ++ engine->fifo.disable = nvc0_fifo_disable; ++ engine->fifo.enable = nvc0_fifo_enable; ++ engine->fifo.reassign = nvc0_fifo_reassign; ++ engine->fifo.channel_id = nvc0_fifo_channel_id; ++ engine->fifo.create_context = nvc0_fifo_create_context; ++ engine->fifo.destroy_context = nvc0_fifo_destroy_context; ++ engine->fifo.load_context = nvc0_fifo_load_context; ++ engine->fifo.unload_context = nvc0_fifo_unload_context; ++ engine->display.early_init = nouveau_stub_init; ++ engine->display.late_takedown = nouveau_stub_takedown; ++ engine->display.create = nvd0_display_create; ++ engine->display.init = nvd0_display_init; ++ engine->display.destroy = nvd0_display_destroy; ++ engine->gpio.init = nv50_gpio_init; ++ engine->gpio.takedown = nouveau_stub_takedown; ++ engine->gpio.get = nvd0_gpio_get; ++ engine->gpio.set = nvd0_gpio_set; ++ engine->gpio.irq_register = nv50_gpio_irq_register; ++ engine->gpio.irq_unregister = nv50_gpio_irq_unregister; ++ engine->gpio.irq_enable = nv50_gpio_irq_enable; ++ engine->vram.init = nvc0_vram_init; ++ engine->vram.takedown = nv50_vram_fini; ++ engine->vram.get = nvc0_vram_new; ++ engine->vram.put = nv50_vram_del; ++ engine->vram.flags_valid = nvc0_vram_flags_valid; ++ engine->pm.clocks_get = nvc0_pm_clocks_get; ++ engine->pm.voltage_get = nouveau_voltage_gpio_get; ++ engine->pm.voltage_set = nouveau_voltage_gpio_set; + break; + default: + NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); + return 1; + } + ++ /* headless mode */ ++ if (nouveau_modeset == 2) { ++ engine->display.early_init = nouveau_stub_init; ++ engine->display.late_takedown = nouveau_stub_takedown; ++ engine->display.create = nouveau_stub_init; ++ engine->display.init = nouveau_stub_init; ++ engine->display.destroy = nouveau_stub_takedown; ++ } ++ + return 0; + } + +@@ -449,21 +510,6 @@ nouveau_vga_set_decode(void *priv, bool state) + return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; + } + +-static int +-nouveau_card_init_channel(struct drm_device *dev) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- int ret; +- +- ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL, +- NvDmaFB, NvDmaTT); +- if (ret) +- return ret; +- +- mutex_unlock(&dev_priv->channel->mutex); +- return 0; +-} +- + static void nouveau_switcheroo_set_state(struct pci_dev *pdev, + enum vga_switcheroo_state state) + { +@@ -630,8 +676,11 @@ nouveau_card_init(struct drm_device *dev) + break; + } + +- if (dev_priv->card_type == NV_40) +- nv40_mpeg_create(dev); ++ if (dev_priv->card_type == NV_40 || ++ dev_priv->chipset == 0x31 || ++ dev_priv->chipset == 0x34 || ++ dev_priv->chipset == 0x36) ++ nv31_mpeg_create(dev); + else + if (dev_priv->card_type == NV_50 && + (dev_priv->chipset < 0x98 || dev_priv->chipset == 0xa0)) +@@ -651,41 +700,69 @@ nouveau_card_init(struct drm_device *dev) + goto out_engine; + } + +- ret = engine->display.create(dev); ++ ret = nouveau_irq_init(dev); + if (ret) + goto out_fifo; + +- ret = drm_vblank_init(dev, nv_two_heads(dev) ? 2 : 1); +- if (ret) +- goto out_vblank; ++ /* initialise general modesetting */ ++ drm_mode_config_init(dev); ++ drm_mode_create_scaling_mode_property(dev); ++ drm_mode_create_dithering_property(dev); ++ dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; ++ dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1); ++ dev->mode_config.min_width = 0; ++ dev->mode_config.min_height = 0; ++ if (dev_priv->card_type < NV_10) { ++ dev->mode_config.max_width = 2048; ++ dev->mode_config.max_height = 2048; ++ } else ++ if (dev_priv->card_type < NV_50) { ++ dev->mode_config.max_width = 4096; ++ dev->mode_config.max_height = 4096; ++ } else { ++ dev->mode_config.max_width = 8192; ++ dev->mode_config.max_height = 8192; ++ } + +- ret = nouveau_irq_init(dev); ++ ret = engine->display.create(dev); + if (ret) +- goto out_vblank; ++ goto out_irq; + +- /* what about PVIDEO/PCRTC/PRAMDAC etc? */ ++ nouveau_backlight_init(dev); + + if (dev_priv->eng[NVOBJ_ENGINE_GR]) { + ret = nouveau_fence_init(dev); + if (ret) +- goto out_irq; ++ goto out_disp; + +- ret = nouveau_card_init_channel(dev); ++ ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL, ++ NvDmaFB, NvDmaTT); + if (ret) + goto out_fence; ++ ++ mutex_unlock(&dev_priv->channel->mutex); ++ } ++ ++ if (dev->mode_config.num_crtc) { ++ ret = drm_vblank_init(dev, dev->mode_config.num_crtc); ++ if (ret) ++ goto out_chan; ++ ++ nouveau_fbcon_init(dev); ++ drm_kms_helper_poll_init(dev); + } + +- nouveau_fbcon_init(dev); +- drm_kms_helper_poll_init(dev); + return 0; + ++out_chan: ++ nouveau_channel_put_unlocked(&dev_priv->channel); + out_fence: + nouveau_fence_fini(dev); ++out_disp: ++ nouveau_backlight_exit(dev); ++ engine->display.destroy(dev); + out_irq: + nouveau_irq_fini(dev); +-out_vblank: +- drm_vblank_cleanup(dev); +- engine->display.destroy(dev); + out_fifo: + if (!dev_priv->noaccel) + engine->fifo.takedown(dev); +@@ -732,15 +809,20 @@ static void nouveau_card_takedown(struct drm_device *dev) + struct nouveau_engine *engine = &dev_priv->engine; + int e; + +- drm_kms_helper_poll_fini(dev); +- nouveau_fbcon_fini(dev); ++ if (dev->mode_config.num_crtc) { ++ drm_kms_helper_poll_fini(dev); ++ nouveau_fbcon_fini(dev); ++ drm_vblank_cleanup(dev); ++ } + + if (dev_priv->channel) { + nouveau_channel_put_unlocked(&dev_priv->channel); + nouveau_fence_fini(dev); + } + ++ nouveau_backlight_exit(dev); + engine->display.destroy(dev); ++ drm_mode_config_cleanup(dev); + + if (!dev_priv->noaccel) { + engine->fifo.takedown(dev); +@@ -774,7 +856,6 @@ static void nouveau_card_takedown(struct drm_device *dev) + engine->vram.takedown(dev); + + nouveau_irq_fini(dev); +- drm_vblank_cleanup(dev); + + nouveau_pm_fini(dev); + nouveau_bios_takedown(dev); +@@ -907,7 +988,7 @@ static int nouveau_remove_conflicting_drivers(struct drm_device *dev) + int nouveau_load(struct drm_device *dev, unsigned long flags) + { + struct drm_nouveau_private *dev_priv; +- uint32_t reg0; ++ uint32_t reg0, strap; + resource_size_t mmio_start_offs; + int ret; + +@@ -951,13 +1032,11 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) + + /* Time to determine the card architecture */ + reg0 = nv_rd32(dev, NV03_PMC_BOOT_0); +- dev_priv->stepping = 0; /* XXX: add stepping for pre-NV10? */ + + /* We're dealing with >=NV10 */ + if ((reg0 & 0x0f000000) > 0) { + /* Bit 27-20 contain the architecture in hex */ + dev_priv->chipset = (reg0 & 0xff00000) >> 20; +- dev_priv->stepping = (reg0 & 0xff); + /* NV04 or NV05 */ + } else if ((reg0 & 0xff00fff0) == 0x20004000) { + if (reg0 & 0x00f00000) +@@ -987,6 +1066,9 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) + case 0xc0: + dev_priv->card_type = NV_C0; + break; ++ case 0xd0: ++ dev_priv->card_type = NV_D0; ++ break; + default: + NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0); + ret = -EINVAL; +@@ -996,6 +1078,23 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) + NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", + dev_priv->card_type, reg0); + ++ /* determine frequency of timing crystal */ ++ strap = nv_rd32(dev, 0x101000); ++ if ( dev_priv->chipset < 0x17 || ++ (dev_priv->chipset >= 0x20 && dev_priv->chipset <= 0x25)) ++ strap &= 0x00000040; ++ else ++ strap &= 0x00400040; ++ ++ switch (strap) { ++ case 0x00000000: dev_priv->crystal = 13500; break; ++ case 0x00000040: dev_priv->crystal = 14318; break; ++ case 0x00400000: dev_priv->crystal = 27000; break; ++ case 0x00400040: dev_priv->crystal = 25000; break; ++ } ++ ++ NV_DEBUG(dev, "crystal freq: %dKHz\n", dev_priv->crystal); ++ + /* Determine whether we'll attempt acceleration or not, some + * cards are disabled by default here due to them being known + * non-functional, or never been tested due to lack of hw. +@@ -1030,7 +1129,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) + ioremap(pci_resource_start(dev->pdev, ramin_bar), + dev_priv->ramin_size); + if (!dev_priv->ramin) { +- NV_ERROR(dev, "Failed to PRAMIN BAR"); ++ NV_ERROR(dev, "Failed to map PRAMIN BAR\n"); + ret = -ENOMEM; + goto err_mmio; + } +@@ -1130,7 +1229,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, + getparam->value = 1; + break; + case NOUVEAU_GETPARAM_HAS_PAGEFLIP: +- getparam->value = 1; ++ getparam->value = dev_priv->card_type < NV_D0; + break; + case NOUVEAU_GETPARAM_GRAPH_UNITS: + /* NV40 and NV50 versions are quite different, but register +@@ -1198,6 +1297,23 @@ nouveau_wait_ne(struct drm_device *dev, uint64_t timeout, + return false; + } + ++/* Wait until cond(data) == true, up until timeout has hit */ ++bool ++nouveau_wait_cb(struct drm_device *dev, u64 timeout, ++ bool (*cond)(void *), void *data) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; ++ u64 start = ptimer->read(dev); ++ ++ do { ++ if (cond(data) == true) ++ return true; ++ } while (ptimer->read(dev) - start < timeout); ++ ++ return false; ++} ++ + /* Waits for PGRAPH to go completely idle */ + bool nouveau_wait_for_idle(struct drm_device *dev) + { +diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c +index 244fd38..ef0832b 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_vm.c ++++ b/drivers/gpu/drm/nouveau/nouveau_vm.c +@@ -172,9 +172,9 @@ nouveau_vm_unmap_pgt(struct nouveau_vm *vm, int big, u32 fpde, u32 lpde) + vm->map_pgt(vpgd->obj, pde, vpgt->obj); + } + +- mutex_unlock(&vm->mm->mutex); ++ mutex_unlock(&vm->mm.mutex); + nouveau_gpuobj_ref(NULL, &pgt); +- mutex_lock(&vm->mm->mutex); ++ mutex_lock(&vm->mm.mutex); + } + } + +@@ -191,18 +191,18 @@ nouveau_vm_map_pgt(struct nouveau_vm *vm, u32 pde, u32 type) + pgt_size = (1 << (vm->pgt_bits + 12)) >> type; + pgt_size *= 8; + +- mutex_unlock(&vm->mm->mutex); ++ mutex_unlock(&vm->mm.mutex); + ret = nouveau_gpuobj_new(vm->dev, NULL, pgt_size, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &pgt); +- mutex_lock(&vm->mm->mutex); ++ mutex_lock(&vm->mm.mutex); + if (unlikely(ret)) + return ret; + + /* someone beat us to filling the PDE while we didn't have the lock */ + if (unlikely(vpgt->refcount[big]++)) { +- mutex_unlock(&vm->mm->mutex); ++ mutex_unlock(&vm->mm.mutex); + nouveau_gpuobj_ref(NULL, &pgt); +- mutex_lock(&vm->mm->mutex); ++ mutex_lock(&vm->mm.mutex); + return 0; + } + +@@ -223,10 +223,10 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, + u32 fpde, lpde, pde; + int ret; + +- mutex_lock(&vm->mm->mutex); +- ret = nouveau_mm_get(vm->mm, page_shift, msize, 0, align, &vma->node); ++ mutex_lock(&vm->mm.mutex); ++ ret = nouveau_mm_get(&vm->mm, page_shift, msize, 0, align, &vma->node); + if (unlikely(ret != 0)) { +- mutex_unlock(&vm->mm->mutex); ++ mutex_unlock(&vm->mm.mutex); + return ret; + } + +@@ -245,13 +245,13 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, + if (ret) { + if (pde != fpde) + nouveau_vm_unmap_pgt(vm, big, fpde, pde - 1); +- nouveau_mm_put(vm->mm, vma->node); +- mutex_unlock(&vm->mm->mutex); ++ nouveau_mm_put(&vm->mm, vma->node); ++ mutex_unlock(&vm->mm.mutex); + vma->node = NULL; + return ret; + } + } +- mutex_unlock(&vm->mm->mutex); ++ mutex_unlock(&vm->mm.mutex); + + vma->vm = vm; + vma->offset = (u64)vma->node->offset << 12; +@@ -270,11 +270,11 @@ nouveau_vm_put(struct nouveau_vma *vma) + fpde = (vma->node->offset >> vm->pgt_bits); + lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits; + +- mutex_lock(&vm->mm->mutex); ++ mutex_lock(&vm->mm.mutex); + nouveau_vm_unmap_pgt(vm, vma->node->type != vm->spg_shift, fpde, lpde); +- nouveau_mm_put(vm->mm, vma->node); ++ nouveau_mm_put(&vm->mm, vma->node); + vma->node = NULL; +- mutex_unlock(&vm->mm->mutex); ++ mutex_unlock(&vm->mm.mutex); + } + + int +@@ -306,7 +306,7 @@ nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset, + block = length; + + } else +- if (dev_priv->card_type == NV_C0) { ++ if (dev_priv->card_type >= NV_C0) { + vm->map_pgt = nvc0_vm_map_pgt; + vm->map = nvc0_vm_map; + vm->map_sg = nvc0_vm_map_sg; +@@ -360,11 +360,11 @@ nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd) + + nouveau_gpuobj_ref(pgd, &vpgd->obj); + +- mutex_lock(&vm->mm->mutex); ++ mutex_lock(&vm->mm.mutex); + for (i = vm->fpde; i <= vm->lpde; i++) + vm->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj); + list_add(&vpgd->head, &vm->pgd_list); +- mutex_unlock(&vm->mm->mutex); ++ mutex_unlock(&vm->mm.mutex); + return 0; + } + +@@ -377,7 +377,7 @@ nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd) + if (!mpgd) + return; + +- mutex_lock(&vm->mm->mutex); ++ mutex_lock(&vm->mm.mutex); + list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { + if (vpgd->obj == mpgd) { + pgd = vpgd->obj; +@@ -386,7 +386,7 @@ nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd) + break; + } + } +- mutex_unlock(&vm->mm->mutex); ++ mutex_unlock(&vm->mm.mutex); + + nouveau_gpuobj_ref(NULL, &pgd); + } +diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h +index 579ca8c..6ce995f 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_vm.h ++++ b/drivers/gpu/drm/nouveau/nouveau_vm.h +@@ -51,7 +51,7 @@ struct nouveau_vma { + + struct nouveau_vm { + struct drm_device *dev; +- struct nouveau_mm *mm; ++ struct nouveau_mm mm; + int refcount; + + struct list_head pgd_list; +diff --git a/drivers/gpu/drm/nouveau/nouveau_volt.c b/drivers/gpu/drm/nouveau/nouveau_volt.c +index 75e87274..86d03e1 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_volt.c ++++ b/drivers/gpu/drm/nouveau/nouveau_volt.c +@@ -27,7 +27,7 @@ + #include "nouveau_drv.h" + #include "nouveau_pm.h" + +-static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a }; ++static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a, 0x73 }; + static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]); + + int +@@ -170,6 +170,13 @@ nouveau_volt_init(struct drm_device *dev) + */ + vidshift = 2; + break; ++ case 0x40: ++ headerlen = volt[1]; ++ recordlen = volt[2]; ++ entries = volt[3]; /* not a clue what the entries are for.. */ ++ vidmask = volt[11]; /* guess.. */ ++ vidshift = 0; ++ break; + default: + NV_WARN(dev, "voltage table 0x%02x unknown\n", volt[0]); + return; +@@ -197,16 +204,37 @@ nouveau_volt_init(struct drm_device *dev) + } + + /* parse vbios entries into common format */ +- voltage->level = kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL); +- if (!voltage->level) +- return; ++ voltage->version = volt[0]; ++ if (voltage->version < 0x40) { ++ voltage->nr_level = entries; ++ voltage->level = ++ kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL); ++ if (!voltage->level) ++ return; + +- entry = volt + headerlen; +- for (i = 0; i < entries; i++, entry += recordlen) { +- voltage->level[i].voltage = entry[0]; +- voltage->level[i].vid = entry[1] >> vidshift; ++ entry = volt + headerlen; ++ for (i = 0; i < entries; i++, entry += recordlen) { ++ voltage->level[i].voltage = entry[0] * 10000; ++ voltage->level[i].vid = entry[1] >> vidshift; ++ } ++ } else { ++ u32 volt_uv = ROM32(volt[4]); ++ s16 step_uv = ROM16(volt[8]); ++ u8 vid; ++ ++ voltage->nr_level = voltage->vid_mask + 1; ++ voltage->level = kcalloc(voltage->nr_level, ++ sizeof(*voltage->level), GFP_KERNEL); ++ if (!voltage->level) ++ return; ++ ++ for (vid = 0; vid <= voltage->vid_mask; vid++) { ++ voltage->level[vid].voltage = volt_uv; ++ voltage->level[vid].vid = vid; ++ volt_uv += step_uv; ++ } + } +- voltage->nr_level = entries; ++ + voltage->supported = true; + } + +diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c +index 1715e14..6bd8518 100644 +--- a/drivers/gpu/drm/nouveau/nv04_display.c ++++ b/drivers/gpu/drm/nouveau/nv04_display.c +@@ -126,27 +126,6 @@ nv04_display_create(struct drm_device *dev) + + nouveau_hw_save_vga_fonts(dev, 1); + +- drm_mode_config_init(dev); +- drm_mode_create_scaling_mode_property(dev); +- drm_mode_create_dithering_property(dev); +- +- dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; +- +- dev->mode_config.min_width = 0; +- dev->mode_config.min_height = 0; +- switch (dev_priv->card_type) { +- case NV_04: +- dev->mode_config.max_width = 2048; +- dev->mode_config.max_height = 2048; +- break; +- default: +- dev->mode_config.max_width = 4096; +- dev->mode_config.max_height = 4096; +- break; +- } +- +- dev->mode_config.fb_base = dev_priv->fb_phys; +- + nv04_crtc_create(dev, 0); + if (nv_two_heads(dev)) + nv04_crtc_create(dev, 1); +@@ -235,8 +214,6 @@ nv04_display_destroy(struct drm_device *dev) + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + crtc->funcs->restore(crtc); + +- drm_mode_config_cleanup(dev); +- + nouveau_hw_save_vga_fonts(dev, 0); + } + +diff --git a/drivers/gpu/drm/nouveau/nv04_pm.c b/drivers/gpu/drm/nouveau/nv04_pm.c +index eb1c70d..9ae92a8 100644 +--- a/drivers/gpu/drm/nouveau/nv04_pm.c ++++ b/drivers/gpu/drm/nouveau/nv04_pm.c +@@ -68,6 +68,7 @@ void + nv04_pm_clock_set(struct drm_device *dev, void *pre_state) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; + struct nv04_pm_state *state = pre_state; + u32 reg = state->pll.reg; + +@@ -85,6 +86,9 @@ nv04_pm_clock_set(struct drm_device *dev, void *pre_state) + nv_mask(dev, 0x1002c0, 0, 1 << 8); + } + ++ if (reg == NV_PRAMDAC_NVPLL_COEFF) ++ ptimer->init(dev); ++ + kfree(state); + } + +diff --git a/drivers/gpu/drm/nouveau/nv04_timer.c b/drivers/gpu/drm/nouveau/nv04_timer.c +index 1d09ddd..263301b 100644 +--- a/drivers/gpu/drm/nouveau/nv04_timer.c ++++ b/drivers/gpu/drm/nouveau/nv04_timer.c +@@ -6,43 +6,75 @@ + int + nv04_timer_init(struct drm_device *dev) + { ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 m, n, d; ++ + nv_wr32(dev, NV04_PTIMER_INTR_EN_0, 0x00000000); + nv_wr32(dev, NV04_PTIMER_INTR_0, 0xFFFFFFFF); + +- /* Just use the pre-existing values when possible for now; these regs +- * are not written in nv (driver writer missed a /4 on the address), and +- * writing 8 and 3 to the correct regs breaks the timings on the LVDS +- * hardware sequencing microcode. +- * A correct solution (involving calculations with the GPU PLL) can +- * be done when kernel modesetting lands +- */ +- if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) || +- !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) { +- nv_wr32(dev, NV04_PTIMER_NUMERATOR, 0x00000008); +- nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 0x00000003); ++ /* aim for 31.25MHz, which gives us nanosecond timestamps */ ++ d = 1000000 / 32; ++ ++ /* determine base clock for timer source */ ++ if (dev_priv->chipset < 0x40) { ++ n = dev_priv->engine.pm.clock_get(dev, PLL_CORE); ++ } else ++ if (dev_priv->chipset == 0x40) { ++ /*XXX: figure this out */ ++ n = 0; ++ } else { ++ n = dev_priv->crystal; ++ m = 1; ++ while (n < (d * 2)) { ++ n += (n / m); ++ m++; ++ } ++ ++ nv_wr32(dev, 0x009220, m - 1); ++ } ++ ++ if (!n) { ++ NV_WARN(dev, "PTIMER: unknown input clock freq\n"); ++ if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) || ++ !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) { ++ nv_wr32(dev, NV04_PTIMER_NUMERATOR, 1); ++ nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 1); ++ } ++ return 0; ++ } ++ ++ /* reduce ratio to acceptable values */ ++ while (((n % 5) == 0) && ((d % 5) == 0)) { ++ n /= 5; ++ d /= 5; + } + ++ while (((n % 2) == 0) && ((d % 2) == 0)) { ++ n /= 2; ++ d /= 2; ++ } ++ ++ while (n > 0xffff || d > 0xffff) { ++ n >>= 1; ++ d >>= 1; ++ } ++ ++ nv_wr32(dev, NV04_PTIMER_NUMERATOR, n); ++ nv_wr32(dev, NV04_PTIMER_DENOMINATOR, d); + return 0; + } + +-uint64_t ++u64 + nv04_timer_read(struct drm_device *dev) + { +- uint32_t low; +- /* From kmmio dumps on nv28 this looks like how the blob does this. +- * It reads the high dword twice, before and after. +- * The only explanation seems to be that the 64-bit timer counter +- * advances between high and low dword reads and may corrupt the +- * result. Not confirmed. +- */ +- uint32_t high2 = nv_rd32(dev, NV04_PTIMER_TIME_1); +- uint32_t high1; ++ u32 hi, lo; ++ + do { +- high1 = high2; +- low = nv_rd32(dev, NV04_PTIMER_TIME_0); +- high2 = nv_rd32(dev, NV04_PTIMER_TIME_1); +- } while (high1 != high2); +- return (((uint64_t)high2) << 32) | (uint64_t)low; ++ hi = nv_rd32(dev, NV04_PTIMER_TIME_1); ++ lo = nv_rd32(dev, NV04_PTIMER_TIME_0); ++ } while (hi != nv_rd32(dev, NV04_PTIMER_TIME_1)); ++ ++ return ((u64)hi << 32 | lo); + } + + void +diff --git a/drivers/gpu/drm/nouveau/nv31_mpeg.c b/drivers/gpu/drm/nouveau/nv31_mpeg.c +new file mode 100644 +index 0000000..6f06a07 +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nv31_mpeg.c +@@ -0,0 +1,344 @@ ++/* ++ * Copyright 2011 Red Hat Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: Ben Skeggs ++ */ ++ ++#include "drmP.h" ++#include "nouveau_drv.h" ++#include "nouveau_ramht.h" ++ ++struct nv31_mpeg_engine { ++ struct nouveau_exec_engine base; ++ atomic_t refcount; ++}; ++ ++ ++static int ++nv31_mpeg_context_new(struct nouveau_channel *chan, int engine) ++{ ++ struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); ++ ++ if (!atomic_add_unless(&pmpeg->refcount, 1, 1)) ++ return -EBUSY; ++ ++ chan->engctx[engine] = (void *)0xdeadcafe; ++ return 0; ++} ++ ++static void ++nv31_mpeg_context_del(struct nouveau_channel *chan, int engine) ++{ ++ struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); ++ atomic_dec(&pmpeg->refcount); ++ chan->engctx[engine] = NULL; ++} ++ ++static int ++nv40_mpeg_context_new(struct nouveau_channel *chan, int engine) ++{ ++ struct drm_device *dev = chan->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpuobj *ctx = NULL; ++ unsigned long flags; ++ int ret; ++ ++ NV_DEBUG(dev, "ch%d\n", chan->id); ++ ++ ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC | ++ NVOBJ_FLAG_ZERO_FREE, &ctx); ++ if (ret) ++ return ret; ++ ++ nv_wo32(ctx, 0x78, 0x02001ec1); ++ ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ nv_mask(dev, 0x002500, 0x00000001, 0x00000000); ++ if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id) ++ nv_wr32(dev, 0x00330c, ctx->pinst >> 4); ++ nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4); ++ nv_mask(dev, 0x002500, 0x00000001, 0x00000001); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); ++ ++ chan->engctx[engine] = ctx; ++ return 0; ++} ++ ++static void ++nv40_mpeg_context_del(struct nouveau_channel *chan, int engine) ++{ ++ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; ++ struct nouveau_gpuobj *ctx = chan->engctx[engine]; ++ struct drm_device *dev = chan->dev; ++ unsigned long flags; ++ u32 inst = 0x80000000 | (ctx->pinst >> 4); ++ ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); ++ if (nv_rd32(dev, 0x00b318) == inst) ++ nv_mask(dev, 0x00b318, 0x80000000, 0x00000000); ++ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); ++ ++ nouveau_gpuobj_ref(NULL, &ctx); ++ chan->engctx[engine] = NULL; ++} ++ ++static int ++nv31_mpeg_object_new(struct nouveau_channel *chan, int engine, ++ u32 handle, u16 class) ++{ ++ struct drm_device *dev = chan->dev; ++ struct nouveau_gpuobj *obj = NULL; ++ int ret; ++ ++ ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC | ++ NVOBJ_FLAG_ZERO_FREE, &obj); ++ if (ret) ++ return ret; ++ obj->engine = 2; ++ obj->class = class; ++ ++ nv_wo32(obj, 0x00, class); ++ ++ ret = nouveau_ramht_insert(chan, handle, obj); ++ nouveau_gpuobj_ref(NULL, &obj); ++ return ret; ++} ++ ++static int ++nv31_mpeg_init(struct drm_device *dev, int engine) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); ++ int i; ++ ++ /* VPE init */ ++ nv_mask(dev, 0x000200, 0x00000002, 0x00000000); ++ nv_mask(dev, 0x000200, 0x00000002, 0x00000002); ++ nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ ++ nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ ++ ++ for (i = 0; i < dev_priv->engine.fb.num_tiles; i++) ++ pmpeg->base.set_tile_region(dev, i); ++ ++ /* PMPEG init */ ++ nv_wr32(dev, 0x00b32c, 0x00000000); ++ nv_wr32(dev, 0x00b314, 0x00000100); ++ nv_wr32(dev, 0x00b220, nv44_graph_class(dev) ? 0x00000044 : 0x00000031); ++ nv_wr32(dev, 0x00b300, 0x02001ec1); ++ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); ++ ++ nv_wr32(dev, 0x00b100, 0xffffffff); ++ nv_wr32(dev, 0x00b140, 0xffffffff); ++ ++ if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) { ++ NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200)); ++ return -EBUSY; ++ } ++ ++ return 0; ++} ++ ++static int ++nv31_mpeg_fini(struct drm_device *dev, int engine, bool suspend) ++{ ++ /*XXX: context save? */ ++ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); ++ nv_wr32(dev, 0x00b140, 0x00000000); ++ return 0; ++} ++ ++static int ++nv31_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) ++{ ++ struct drm_device *dev = chan->dev; ++ u32 inst = data << 4; ++ u32 dma0 = nv_ri32(dev, inst + 0); ++ u32 dma1 = nv_ri32(dev, inst + 4); ++ u32 dma2 = nv_ri32(dev, inst + 8); ++ u32 base = (dma2 & 0xfffff000) | (dma0 >> 20); ++ u32 size = dma1 + 1; ++ ++ /* only allow linear DMA objects */ ++ if (!(dma0 & 0x00002000)) ++ return -EINVAL; ++ ++ if (mthd == 0x0190) { ++ /* DMA_CMD */ ++ nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000)); ++ nv_wr32(dev, 0x00b334, base); ++ nv_wr32(dev, 0x00b324, size); ++ } else ++ if (mthd == 0x01a0) { ++ /* DMA_DATA */ ++ nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); ++ nv_wr32(dev, 0x00b360, base); ++ nv_wr32(dev, 0x00b364, size); ++ } else { ++ /* DMA_IMAGE, VRAM only */ ++ if (dma0 & 0x000c0000) ++ return -EINVAL; ++ ++ nv_wr32(dev, 0x00b370, base); ++ nv_wr32(dev, 0x00b374, size); ++ } ++ ++ return 0; ++} ++ ++static int ++nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_gpuobj *ctx; ++ unsigned long flags; ++ int i; ++ ++ /* hardcode drm channel id on nv3x, so swmthd lookup works */ ++ if (dev_priv->card_type < NV_40) ++ return 0; ++ ++ spin_lock_irqsave(&dev_priv->channels.lock, flags); ++ for (i = 0; i < dev_priv->engine.fifo.channels; i++) { ++ if (!dev_priv->channels.ptr[i]) ++ continue; ++ ++ ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG]; ++ if (ctx && ctx->pinst == inst) ++ break; ++ } ++ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); ++ return i; ++} ++ ++static void ++nv31_vpe_set_tile_region(struct drm_device *dev, int i) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; ++ ++ nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch); ++ nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit); ++ nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr); ++} ++ ++static void ++nv31_mpeg_isr(struct drm_device *dev) ++{ ++ u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4; ++ u32 chid = nv31_mpeg_isr_chid(dev, inst); ++ u32 stat = nv_rd32(dev, 0x00b100); ++ u32 type = nv_rd32(dev, 0x00b230); ++ u32 mthd = nv_rd32(dev, 0x00b234); ++ u32 data = nv_rd32(dev, 0x00b238); ++ u32 show = stat; ++ ++ if (stat & 0x01000000) { ++ /* happens on initial binding of the object */ ++ if (type == 0x00000020 && mthd == 0x0000) { ++ nv_mask(dev, 0x00b308, 0x00000000, 0x00000000); ++ show &= ~0x01000000; ++ } ++ ++ if (type == 0x00000010) { ++ if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data)) ++ show &= ~0x01000000; ++ } ++ } ++ ++ nv_wr32(dev, 0x00b100, stat); ++ nv_wr32(dev, 0x00b230, 0x00000001); ++ ++ if (show && nouveau_ratelimit()) { ++ NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", ++ chid, inst, stat, type, mthd, data); ++ } ++} ++ ++static void ++nv31_vpe_isr(struct drm_device *dev) ++{ ++ if (nv_rd32(dev, 0x00b100)) ++ nv31_mpeg_isr(dev); ++ ++ if (nv_rd32(dev, 0x00b800)) { ++ u32 stat = nv_rd32(dev, 0x00b800); ++ NV_INFO(dev, "PMSRCH: 0x%08x\n", stat); ++ nv_wr32(dev, 0xb800, stat); ++ } ++} ++ ++static void ++nv31_mpeg_destroy(struct drm_device *dev, int engine) ++{ ++ struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); ++ ++ nouveau_irq_unregister(dev, 0); ++ ++ NVOBJ_ENGINE_DEL(dev, MPEG); ++ kfree(pmpeg); ++} ++ ++int ++nv31_mpeg_create(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv31_mpeg_engine *pmpeg; ++ ++ pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); ++ if (!pmpeg) ++ return -ENOMEM; ++ atomic_set(&pmpeg->refcount, 0); ++ ++ pmpeg->base.destroy = nv31_mpeg_destroy; ++ pmpeg->base.init = nv31_mpeg_init; ++ pmpeg->base.fini = nv31_mpeg_fini; ++ if (dev_priv->card_type < NV_40) { ++ pmpeg->base.context_new = nv31_mpeg_context_new; ++ pmpeg->base.context_del = nv31_mpeg_context_del; ++ } else { ++ pmpeg->base.context_new = nv40_mpeg_context_new; ++ pmpeg->base.context_del = nv40_mpeg_context_del; ++ } ++ pmpeg->base.object_new = nv31_mpeg_object_new; ++ ++ /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between ++ * all VPE engines, for this driver's purposes the PMPEG engine ++ * will be treated as the "master" and handle the global VPE ++ * bits too ++ */ ++ pmpeg->base.set_tile_region = nv31_vpe_set_tile_region; ++ nouveau_irq_register(dev, 0, nv31_vpe_isr); ++ ++ NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); ++ NVOBJ_CLASS(dev, 0x3174, MPEG); ++ NVOBJ_MTHD (dev, 0x3174, 0x0190, nv31_mpeg_mthd_dma); ++ NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv31_mpeg_mthd_dma); ++ NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv31_mpeg_mthd_dma); ++ ++#if 0 ++ NVOBJ_ENGINE_ADD(dev, ME, &pme->base); ++ NVOBJ_CLASS(dev, 0x4075, ME); ++#endif ++ return 0; ++ ++} +diff --git a/drivers/gpu/drm/nouveau/nv40_mpeg.c b/drivers/gpu/drm/nouveau/nv40_mpeg.c +deleted file mode 100644 +index ad03a0e..0000000 +--- a/drivers/gpu/drm/nouveau/nv40_mpeg.c ++++ /dev/null +@@ -1,311 +0,0 @@ +-/* +- * Copyright 2011 Red Hat Inc. +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. +- * +- * Authors: Ben Skeggs +- */ +- +-#include "drmP.h" +-#include "nouveau_drv.h" +-#include "nouveau_ramht.h" +- +-struct nv40_mpeg_engine { +- struct nouveau_exec_engine base; +-}; +- +-static int +-nv40_mpeg_context_new(struct nouveau_channel *chan, int engine) +-{ +- struct drm_device *dev = chan->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpuobj *ctx = NULL; +- unsigned long flags; +- int ret; +- +- NV_DEBUG(dev, "ch%d\n", chan->id); +- +- ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC | +- NVOBJ_FLAG_ZERO_FREE, &ctx); +- if (ret) +- return ret; +- +- nv_wo32(ctx, 0x78, 0x02001ec1); +- +- spin_lock_irqsave(&dev_priv->context_switch_lock, flags); +- nv_mask(dev, 0x002500, 0x00000001, 0x00000000); +- if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id) +- nv_wr32(dev, 0x00330c, ctx->pinst >> 4); +- nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4); +- nv_mask(dev, 0x002500, 0x00000001, 0x00000001); +- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +- +- chan->engctx[engine] = ctx; +- return 0; +-} +- +-static void +-nv40_mpeg_context_del(struct nouveau_channel *chan, int engine) +-{ +- struct drm_nouveau_private *dev_priv = chan->dev->dev_private; +- struct nouveau_gpuobj *ctx = chan->engctx[engine]; +- struct drm_device *dev = chan->dev; +- unsigned long flags; +- u32 inst = 0x80000000 | (ctx->pinst >> 4); +- +- spin_lock_irqsave(&dev_priv->context_switch_lock, flags); +- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); +- if (nv_rd32(dev, 0x00b318) == inst) +- nv_mask(dev, 0x00b318, 0x80000000, 0x00000000); +- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); +- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); +- +- nouveau_gpuobj_ref(NULL, &ctx); +- chan->engctx[engine] = NULL; +-} +- +-static int +-nv40_mpeg_object_new(struct nouveau_channel *chan, int engine, +- u32 handle, u16 class) +-{ +- struct drm_device *dev = chan->dev; +- struct nouveau_gpuobj *obj = NULL; +- int ret; +- +- ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC | +- NVOBJ_FLAG_ZERO_FREE, &obj); +- if (ret) +- return ret; +- obj->engine = 2; +- obj->class = class; +- +- nv_wo32(obj, 0x00, class); +- +- ret = nouveau_ramht_insert(chan, handle, obj); +- nouveau_gpuobj_ref(NULL, &obj); +- return ret; +-} +- +-static int +-nv40_mpeg_init(struct drm_device *dev, int engine) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine); +- int i; +- +- /* VPE init */ +- nv_mask(dev, 0x000200, 0x00000002, 0x00000000); +- nv_mask(dev, 0x000200, 0x00000002, 0x00000002); +- nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ +- nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ +- +- for (i = 0; i < dev_priv->engine.fb.num_tiles; i++) +- pmpeg->base.set_tile_region(dev, i); +- +- /* PMPEG init */ +- nv_wr32(dev, 0x00b32c, 0x00000000); +- nv_wr32(dev, 0x00b314, 0x00000100); +- nv_wr32(dev, 0x00b220, 0x00000044); +- nv_wr32(dev, 0x00b300, 0x02001ec1); +- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); +- +- nv_wr32(dev, 0x00b100, 0xffffffff); +- nv_wr32(dev, 0x00b140, 0xffffffff); +- +- if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) { +- NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200)); +- return -EBUSY; +- } +- +- return 0; +-} +- +-static int +-nv40_mpeg_fini(struct drm_device *dev, int engine, bool suspend) +-{ +- /*XXX: context save? */ +- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); +- nv_wr32(dev, 0x00b140, 0x00000000); +- return 0; +-} +- +-static int +-nv40_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) +-{ +- struct drm_device *dev = chan->dev; +- u32 inst = data << 4; +- u32 dma0 = nv_ri32(dev, inst + 0); +- u32 dma1 = nv_ri32(dev, inst + 4); +- u32 dma2 = nv_ri32(dev, inst + 8); +- u32 base = (dma2 & 0xfffff000) | (dma0 >> 20); +- u32 size = dma1 + 1; +- +- /* only allow linear DMA objects */ +- if (!(dma0 & 0x00002000)) +- return -EINVAL; +- +- if (mthd == 0x0190) { +- /* DMA_CMD */ +- nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000)); +- nv_wr32(dev, 0x00b334, base); +- nv_wr32(dev, 0x00b324, size); +- } else +- if (mthd == 0x01a0) { +- /* DMA_DATA */ +- nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); +- nv_wr32(dev, 0x00b360, base); +- nv_wr32(dev, 0x00b364, size); +- } else { +- /* DMA_IMAGE, VRAM only */ +- if (dma0 & 0x000c0000) +- return -EINVAL; +- +- nv_wr32(dev, 0x00b370, base); +- nv_wr32(dev, 0x00b374, size); +- } +- +- return 0; +-} +- +-static int +-nv40_mpeg_isr_chid(struct drm_device *dev, u32 inst) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpuobj *ctx; +- unsigned long flags; +- int i; +- +- spin_lock_irqsave(&dev_priv->channels.lock, flags); +- for (i = 0; i < dev_priv->engine.fifo.channels; i++) { +- if (!dev_priv->channels.ptr[i]) +- continue; +- +- ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG]; +- if (ctx && ctx->pinst == inst) +- break; +- } +- spin_unlock_irqrestore(&dev_priv->channels.lock, flags); +- return i; +-} +- +-static void +-nv40_vpe_set_tile_region(struct drm_device *dev, int i) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; +- +- nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch); +- nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit); +- nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr); +-} +- +-static void +-nv40_mpeg_isr(struct drm_device *dev) +-{ +- u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4; +- u32 chid = nv40_mpeg_isr_chid(dev, inst); +- u32 stat = nv_rd32(dev, 0x00b100); +- u32 type = nv_rd32(dev, 0x00b230); +- u32 mthd = nv_rd32(dev, 0x00b234); +- u32 data = nv_rd32(dev, 0x00b238); +- u32 show = stat; +- +- if (stat & 0x01000000) { +- /* happens on initial binding of the object */ +- if (type == 0x00000020 && mthd == 0x0000) { +- nv_mask(dev, 0x00b308, 0x00000000, 0x00000000); +- show &= ~0x01000000; +- } +- +- if (type == 0x00000010) { +- if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data)) +- show &= ~0x01000000; +- } +- } +- +- nv_wr32(dev, 0x00b100, stat); +- nv_wr32(dev, 0x00b230, 0x00000001); +- +- if (show && nouveau_ratelimit()) { +- NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", +- chid, inst, stat, type, mthd, data); +- } +-} +- +-static void +-nv40_vpe_isr(struct drm_device *dev) +-{ +- if (nv_rd32(dev, 0x00b100)) +- nv40_mpeg_isr(dev); +- +- if (nv_rd32(dev, 0x00b800)) { +- u32 stat = nv_rd32(dev, 0x00b800); +- NV_INFO(dev, "PMSRCH: 0x%08x\n", stat); +- nv_wr32(dev, 0xb800, stat); +- } +-} +- +-static void +-nv40_mpeg_destroy(struct drm_device *dev, int engine) +-{ +- struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine); +- +- nouveau_irq_unregister(dev, 0); +- +- NVOBJ_ENGINE_DEL(dev, MPEG); +- kfree(pmpeg); +-} +- +-int +-nv40_mpeg_create(struct drm_device *dev) +-{ +- struct nv40_mpeg_engine *pmpeg; +- +- pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); +- if (!pmpeg) +- return -ENOMEM; +- +- pmpeg->base.destroy = nv40_mpeg_destroy; +- pmpeg->base.init = nv40_mpeg_init; +- pmpeg->base.fini = nv40_mpeg_fini; +- pmpeg->base.context_new = nv40_mpeg_context_new; +- pmpeg->base.context_del = nv40_mpeg_context_del; +- pmpeg->base.object_new = nv40_mpeg_object_new; +- +- /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between +- * all VPE engines, for this driver's purposes the PMPEG engine +- * will be treated as the "master" and handle the global VPE +- * bits too +- */ +- pmpeg->base.set_tile_region = nv40_vpe_set_tile_region; +- nouveau_irq_register(dev, 0, nv40_vpe_isr); +- +- NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); +- NVOBJ_CLASS(dev, 0x3174, MPEG); +- NVOBJ_MTHD (dev, 0x3174, 0x0190, nv40_mpeg_mthd_dma); +- NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv40_mpeg_mthd_dma); +- NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv40_mpeg_mthd_dma); +- +-#if 0 +- NVOBJ_ENGINE_ADD(dev, ME, &pme->base); +- NVOBJ_CLASS(dev, 0x4075, ME); +-#endif +- return 0; +- +-} +diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c +new file mode 100644 +index 0000000..bbc0b9c +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nv40_pm.c +@@ -0,0 +1,338 @@ ++/* ++ * Copyright 2011 Red Hat Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: Ben Skeggs ++ */ ++ ++#include "drmP.h" ++#include "nouveau_drv.h" ++#include "nouveau_bios.h" ++#include "nouveau_pm.h" ++#include "nouveau_hw.h" ++ ++#define min2(a,b) ((a) < (b) ? (a) : (b)) ++ ++static u32 ++read_pll_1(struct drm_device *dev, u32 reg) ++{ ++ u32 ctrl = nv_rd32(dev, reg + 0x00); ++ int P = (ctrl & 0x00070000) >> 16; ++ int N = (ctrl & 0x0000ff00) >> 8; ++ int M = (ctrl & 0x000000ff) >> 0; ++ u32 ref = 27000, clk = 0; ++ ++ if (ctrl & 0x80000000) ++ clk = ref * N / M; ++ ++ return clk >> P; ++} ++ ++static u32 ++read_pll_2(struct drm_device *dev, u32 reg) ++{ ++ u32 ctrl = nv_rd32(dev, reg + 0x00); ++ u32 coef = nv_rd32(dev, reg + 0x04); ++ int N2 = (coef & 0xff000000) >> 24; ++ int M2 = (coef & 0x00ff0000) >> 16; ++ int N1 = (coef & 0x0000ff00) >> 8; ++ int M1 = (coef & 0x000000ff) >> 0; ++ int P = (ctrl & 0x00070000) >> 16; ++ u32 ref = 27000, clk = 0; ++ ++ if (ctrl & 0x80000000) ++ clk = ref * N1 / M1; ++ ++ if (!(ctrl & 0x00000100)) { ++ if (ctrl & 0x40000000) ++ clk = clk * N2 / M2; ++ } ++ ++ return clk >> P; ++} ++ ++static u32 ++read_clk(struct drm_device *dev, u32 src) ++{ ++ switch (src) { ++ case 3: ++ return read_pll_2(dev, 0x004000); ++ case 2: ++ return read_pll_1(dev, 0x004008); ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++int ++nv40_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) ++{ ++ u32 ctrl = nv_rd32(dev, 0x00c040); ++ ++ perflvl->core = read_clk(dev, (ctrl & 0x00000003) >> 0); ++ perflvl->shader = read_clk(dev, (ctrl & 0x00000030) >> 4); ++ perflvl->memory = read_pll_2(dev, 0x4020); ++ return 0; ++} ++ ++struct nv40_pm_state { ++ u32 ctrl; ++ u32 npll_ctrl; ++ u32 npll_coef; ++ u32 spll; ++ u32 mpll_ctrl; ++ u32 mpll_coef; ++}; ++ ++static int ++nv40_calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll, ++ u32 clk, int *N1, int *M1, int *N2, int *M2, int *log2P) ++{ ++ struct nouveau_pll_vals coef; ++ int ret; ++ ++ ret = get_pll_limits(dev, reg, pll); ++ if (ret) ++ return ret; ++ ++ if (clk < pll->vco1.maxfreq) ++ pll->vco2.maxfreq = 0; ++ ++ ret = nouveau_calc_pll_mnp(dev, pll, clk, &coef); ++ if (ret == 0) ++ return -ERANGE; ++ ++ *N1 = coef.N1; ++ *M1 = coef.M1; ++ if (N2 && M2) { ++ if (pll->vco2.maxfreq) { ++ *N2 = coef.N2; ++ *M2 = coef.M2; ++ } else { ++ *N2 = 1; ++ *M2 = 1; ++ } ++ } ++ *log2P = coef.log2P; ++ return 0; ++} ++ ++void * ++nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) ++{ ++ struct nv40_pm_state *info; ++ struct pll_lims pll; ++ int N1, N2, M1, M2, log2P; ++ int ret; ++ ++ info = kmalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return ERR_PTR(-ENOMEM); ++ ++ /* core/geometric clock */ ++ ret = nv40_calc_pll(dev, 0x004000, &pll, perflvl->core, ++ &N1, &M1, &N2, &M2, &log2P); ++ if (ret < 0) ++ goto out; ++ ++ if (N2 == M2) { ++ info->npll_ctrl = 0x80000100 | (log2P << 16); ++ info->npll_coef = (N1 << 8) | M1; ++ } else { ++ info->npll_ctrl = 0xc0000000 | (log2P << 16); ++ info->npll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1; ++ } ++ ++ /* use the second PLL for shader/rop clock, if it differs from core */ ++ if (perflvl->shader && perflvl->shader != perflvl->core) { ++ ret = nv40_calc_pll(dev, 0x004008, &pll, perflvl->shader, ++ &N1, &M1, NULL, NULL, &log2P); ++ if (ret < 0) ++ goto out; ++ ++ info->spll = 0xc0000000 | (log2P << 16) | (N1 << 8) | M1; ++ info->ctrl = 0x00000223; ++ } else { ++ info->spll = 0x00000000; ++ info->ctrl = 0x00000333; ++ } ++ ++ /* memory clock */ ++ ret = nv40_calc_pll(dev, 0x004020, &pll, perflvl->memory, ++ &N1, &M1, &N2, &M2, &log2P); ++ if (ret < 0) ++ goto out; ++ ++ info->mpll_ctrl = 0x80000000 | (log2P << 16); ++ info->mpll_ctrl |= min2(pll.log2p_bias + log2P, pll.max_log2p) << 20; ++ if (N2 == M2) { ++ info->mpll_ctrl |= 0x00000100; ++ info->mpll_coef = (N1 << 8) | M1; ++ } else { ++ info->mpll_ctrl |= 0x40000000; ++ info->mpll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1; ++ } ++ ++out: ++ if (ret < 0) { ++ kfree(info); ++ info = ERR_PTR(ret); ++ } ++ return info; ++} ++ ++static bool ++nv40_pm_gr_idle(void *data) ++{ ++ struct drm_device *dev = data; ++ ++ if ((nv_rd32(dev, 0x400760) & 0x000000f0) >> 4 != ++ (nv_rd32(dev, 0x400760) & 0x0000000f)) ++ return false; ++ ++ if (nv_rd32(dev, 0x400700)) ++ return false; ++ ++ return true; ++} ++ ++void ++nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv40_pm_state *info = pre_state; ++ unsigned long flags; ++ struct bit_entry M; ++ u32 crtc_mask = 0; ++ u8 sr1[2]; ++ int i; ++ ++ /* determine which CRTCs are active, fetch VGA_SR1 for each */ ++ for (i = 0; i < 2; i++) { ++ u32 vbl = nv_rd32(dev, 0x600808 + (i * 0x2000)); ++ u32 cnt = 0; ++ do { ++ if (vbl != nv_rd32(dev, 0x600808 + (i * 0x2000))) { ++ nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01); ++ sr1[i] = nv_rd08(dev, 0x0c03c5 + (i * 0x2000)); ++ if (!(sr1[i] & 0x20)) ++ crtc_mask |= (1 << i); ++ break; ++ } ++ udelay(1); ++ } while (cnt++ < 32); ++ } ++ ++ /* halt and idle engines */ ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ nv_mask(dev, 0x002500, 0x00000001, 0x00000000); ++ if (!nv_wait(dev, 0x002500, 0x00000010, 0x00000000)) ++ goto resume; ++ nv_mask(dev, 0x003220, 0x00000001, 0x00000000); ++ if (!nv_wait(dev, 0x003220, 0x00000010, 0x00000000)) ++ goto resume; ++ nv_mask(dev, 0x003200, 0x00000001, 0x00000000); ++ nv04_fifo_cache_pull(dev, false); ++ ++ if (!nv_wait_cb(dev, nv40_pm_gr_idle, dev)) ++ goto resume; ++ ++ /* set engine clocks */ ++ nv_mask(dev, 0x00c040, 0x00000333, 0x00000000); ++ nv_wr32(dev, 0x004004, info->npll_coef); ++ nv_mask(dev, 0x004000, 0xc0070100, info->npll_ctrl); ++ nv_mask(dev, 0x004008, 0xc007ffff, info->spll); ++ mdelay(5); ++ nv_mask(dev, 0x00c040, 0x00000333, info->ctrl); ++ ++ /* wait for vblank start on active crtcs, disable memory access */ ++ for (i = 0; i < 2; i++) { ++ if (!(crtc_mask & (1 << i))) ++ continue; ++ nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00000000); ++ nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); ++ nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01); ++ nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i] | 0x20); ++ } ++ ++ /* prepare ram for reclocking */ ++ nv_wr32(dev, 0x1002d4, 0x00000001); /* precharge */ ++ nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */ ++ nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */ ++ nv_mask(dev, 0x100210, 0x80000000, 0x00000000); /* no auto refresh */ ++ nv_wr32(dev, 0x1002dc, 0x00000001); /* enable self-refresh */ ++ ++ /* change the PLL of each memory partition */ ++ nv_mask(dev, 0x00c040, 0x0000c000, 0x00000000); ++ switch (dev_priv->chipset) { ++ case 0x40: ++ case 0x45: ++ case 0x41: ++ case 0x42: ++ case 0x47: ++ nv_mask(dev, 0x004044, 0xc0771100, info->mpll_ctrl); ++ nv_mask(dev, 0x00402c, 0xc0771100, info->mpll_ctrl); ++ nv_wr32(dev, 0x004048, info->mpll_coef); ++ nv_wr32(dev, 0x004030, info->mpll_coef); ++ case 0x43: ++ case 0x49: ++ case 0x4b: ++ nv_mask(dev, 0x004038, 0xc0771100, info->mpll_ctrl); ++ nv_wr32(dev, 0x00403c, info->mpll_coef); ++ default: ++ nv_mask(dev, 0x004020, 0xc0771100, info->mpll_ctrl); ++ nv_wr32(dev, 0x004024, info->mpll_coef); ++ break; ++ } ++ udelay(100); ++ nv_mask(dev, 0x00c040, 0x0000c000, 0x0000c000); ++ ++ /* re-enable normal operation of memory controller */ ++ nv_wr32(dev, 0x1002dc, 0x00000000); ++ nv_mask(dev, 0x100210, 0x80000000, 0x80000000); ++ udelay(100); ++ ++ /* execute memory reset script from vbios */ ++ if (!bit_table(dev, 'M', &M)) ++ nouveau_bios_init_exec(dev, ROM16(M.data[0])); ++ ++ /* make sure we're in vblank (hopefully the same one as before), and ++ * then re-enable crtc memory access ++ */ ++ for (i = 0; i < 2; i++) { ++ if (!(crtc_mask & (1 << i))) ++ continue; ++ nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); ++ nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01); ++ nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i]); ++ } ++ ++ /* resume engines */ ++resume: ++ nv_wr32(dev, 0x003250, 0x00000001); ++ nv_mask(dev, 0x003220, 0x00000001, 0x00000001); ++ nv_wr32(dev, 0x003200, 0x00000001); ++ nv_wr32(dev, 0x002500, 0x00000001); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); ++ ++ kfree(info); ++} +diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c +index 5d98907..882080e 100644 +--- a/drivers/gpu/drm/nouveau/nv50_crtc.c ++++ b/drivers/gpu/drm/nouveau/nv50_crtc.c +@@ -329,8 +329,6 @@ nv50_crtc_destroy(struct drm_crtc *crtc) + + drm_crtc_cleanup(&nv_crtc->base); + +- nv50_cursor_fini(nv_crtc); +- + nouveau_bo_unmap(nv_crtc->lut.nvbo); + nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); + nouveau_bo_unmap(nv_crtc->cursor.nvbo); +diff --git a/drivers/gpu/drm/nouveau/nv50_cursor.c b/drivers/gpu/drm/nouveau/nv50_cursor.c +index 9752c35..adfc9b6 100644 +--- a/drivers/gpu/drm/nouveau/nv50_cursor.c ++++ b/drivers/gpu/drm/nouveau/nv50_cursor.c +@@ -137,21 +137,3 @@ nv50_cursor_init(struct nouveau_crtc *nv_crtc) + nv_crtc->cursor.show = nv50_cursor_show; + return 0; + } +- +-void +-nv50_cursor_fini(struct nouveau_crtc *nv_crtc) +-{ +- struct drm_device *dev = nv_crtc->base.dev; +- int idx = nv_crtc->index; +- +- NV_DEBUG_KMS(dev, "\n"); +- +- nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), 0); +- if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), +- NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { +- NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); +- NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", +- nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx))); +- } +-} +- +diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c +index db1a5f4..d23ca00 100644 +--- a/drivers/gpu/drm/nouveau/nv50_display.c ++++ b/drivers/gpu/drm/nouveau/nv50_display.c +@@ -247,6 +247,16 @@ static int nv50_display_disable(struct drm_device *dev) + } + } + ++ for (i = 0; i < 2; i++) { ++ nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0); ++ if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), ++ NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { ++ NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); ++ NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", ++ nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); ++ } ++ } ++ + nv50_evo_fini(dev); + + for (i = 0; i < 3; i++) { +@@ -286,23 +296,6 @@ int nv50_display_create(struct drm_device *dev) + return -ENOMEM; + dev_priv->engine.display.priv = priv; + +- /* init basic kernel modesetting */ +- drm_mode_config_init(dev); +- +- /* Initialise some optional connector properties. */ +- drm_mode_create_scaling_mode_property(dev); +- drm_mode_create_dithering_property(dev); +- +- dev->mode_config.min_width = 0; +- dev->mode_config.min_height = 0; +- +- dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; +- +- dev->mode_config.max_width = 8192; +- dev->mode_config.max_height = 8192; +- +- dev->mode_config.fb_base = dev_priv->fb_phys; +- + /* Create CRTC objects */ + for (i = 0; i < 2; i++) + nv50_crtc_create(dev, i); +@@ -364,8 +357,6 @@ nv50_display_destroy(struct drm_device *dev) + + NV_DEBUG_KMS(dev, "\n"); + +- drm_mode_config_cleanup(dev); +- + nv50_display_disable(dev); + nouveau_irq_unregister(dev, 26); + kfree(disp); +@@ -698,7 +689,7 @@ nv50_display_unk10_handler(struct drm_device *dev) + struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i]; + + if (dcb->type == type && (dcb->or & (1 << or))) { +- nouveau_bios_run_display_table(dev, dcb, 0, -1); ++ nouveau_bios_run_display_table(dev, 0, -1, dcb, -1); + disp->irq.dcb = dcb; + goto ack; + } +@@ -711,37 +702,6 @@ ack: + } + + static void +-nv50_display_unk20_dp_hack(struct drm_device *dev, struct dcb_entry *dcb) +-{ +- int or = ffs(dcb->or) - 1, link = !(dcb->dpconf.sor.link & 1); +- struct drm_encoder *encoder; +- uint32_t tmp, unk0 = 0, unk1 = 0; +- +- if (dcb->type != OUTPUT_DP) +- return; +- +- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- +- if (nv_encoder->dcb == dcb) { +- unk0 = nv_encoder->dp.unk0; +- unk1 = nv_encoder->dp.unk1; +- break; +- } +- } +- +- if (unk0 || unk1) { +- tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); +- tmp &= 0xfffffe03; +- nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp | unk0); +- +- tmp = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link)); +- tmp &= 0xfef080c0; +- nv_wr32(dev, NV50_SOR_DP_UNK128(or, link), tmp | unk1); +- } +-} +- +-static void + nv50_display_unk20_handler(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +@@ -753,7 +713,7 @@ nv50_display_unk20_handler(struct drm_device *dev) + NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); + dcb = disp->irq.dcb; + if (dcb) { +- nouveau_bios_run_display_table(dev, dcb, 0, -2); ++ nouveau_bios_run_display_table(dev, 0, -2, dcb, -1); + disp->irq.dcb = NULL; + } + +@@ -837,9 +797,15 @@ nv50_display_unk20_handler(struct drm_device *dev) + } + + script = nv50_display_script_select(dev, dcb, mc, pclk); +- nouveau_bios_run_display_table(dev, dcb, script, pclk); ++ nouveau_bios_run_display_table(dev, script, pclk, dcb, -1); + +- nv50_display_unk20_dp_hack(dev, dcb); ++ if (type == OUTPUT_DP) { ++ int link = !(dcb->dpconf.sor.link & 1); ++ if ((mc & 0x000f0000) == 0x00020000) ++ nouveau_dp_tu_update(dev, or, link, pclk, 18); ++ else ++ nouveau_dp_tu_update(dev, or, link, pclk, 24); ++ } + + if (dcb->type != OUTPUT_ANALOG) { + tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or)); +@@ -904,7 +870,7 @@ nv50_display_unk40_handler(struct drm_device *dev) + if (!dcb) + goto ack; + +- nouveau_bios_run_display_table(dev, dcb, script, -pclk); ++ nouveau_bios_run_display_table(dev, script, -pclk, dcb, -1); + nv50_display_unk40_dp_set_tmds(dev, dcb); + + ack: +diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c +index d4f4206..793a5cc 100644 +--- a/drivers/gpu/drm/nouveau/nv50_gpio.c ++++ b/drivers/gpu/drm/nouveau/nv50_gpio.c +@@ -98,6 +98,37 @@ nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) + } + + int ++nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) ++{ ++ struct dcb_gpio_entry *gpio; ++ u32 v; ++ ++ gpio = nouveau_bios_gpio_entry(dev, tag); ++ if (!gpio) ++ return -ENOENT; ++ ++ v = nv_rd32(dev, 0x00d610 + (gpio->line * 4)); ++ v &= 0x00004000; ++ return (!!v == (gpio->state[1] & 1)); ++} ++ ++int ++nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) ++{ ++ struct dcb_gpio_entry *gpio; ++ u32 v; ++ ++ gpio = nouveau_bios_gpio_entry(dev, tag); ++ if (!gpio) ++ return -ENOENT; ++ ++ v = gpio->state[state] ^ 2; ++ ++ nv_mask(dev, 0x00d610 + (gpio->line * 4), 0x00003000, v << 12); ++ return 0; ++} ++ ++int + nv50_gpio_irq_register(struct drm_device *dev, enum dcb_gpio_tag tag, + void (*handler)(void *, int), void *data) + { +diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c +index d43c46c..8c979b3 100644 +--- a/drivers/gpu/drm/nouveau/nv50_graph.c ++++ b/drivers/gpu/drm/nouveau/nv50_graph.c +@@ -120,70 +120,62 @@ nv50_graph_unload_context(struct drm_device *dev) + return 0; + } + +-static void +-nv50_graph_init_reset(struct drm_device *dev) +-{ +- uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21); +- NV_DEBUG(dev, "\n"); +- +- nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e); +- nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | pmc_e); +-} +- +-static void +-nv50_graph_init_intr(struct drm_device *dev) +-{ +- NV_DEBUG(dev, "\n"); +- +- nv_wr32(dev, NV03_PGRAPH_INTR, 0xffffffff); +- nv_wr32(dev, 0x400138, 0xffffffff); +- nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xffffffff); +-} +- +-static void +-nv50_graph_init_regs__nv(struct drm_device *dev) ++static int ++nv50_graph_init(struct drm_device *dev, int engine) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- uint32_t units = nv_rd32(dev, 0x1540); ++ struct nv50_graph_engine *pgraph = nv_engine(dev, engine); ++ u32 units = nv_rd32(dev, 0x001540); + int i; + + NV_DEBUG(dev, "\n"); + ++ /* master reset */ ++ nv_mask(dev, 0x000200, 0x00200100, 0x00000000); ++ nv_mask(dev, 0x000200, 0x00200100, 0x00200100); ++ nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */ ++ ++ /* reset/enable traps and interrupts */ + nv_wr32(dev, 0x400804, 0xc0000000); + nv_wr32(dev, 0x406800, 0xc0000000); + nv_wr32(dev, 0x400c04, 0xc0000000); + nv_wr32(dev, 0x401800, 0xc0000000); + nv_wr32(dev, 0x405018, 0xc0000000); + nv_wr32(dev, 0x402000, 0xc0000000); +- + for (i = 0; i < 16; i++) { +- if (units & 1 << i) { +- if (dev_priv->chipset < 0xa0) { +- nv_wr32(dev, 0x408900 + (i << 12), 0xc0000000); +- nv_wr32(dev, 0x408e08 + (i << 12), 0xc0000000); +- nv_wr32(dev, 0x408314 + (i << 12), 0xc0000000); +- } else { +- nv_wr32(dev, 0x408600 + (i << 11), 0xc0000000); +- nv_wr32(dev, 0x408708 + (i << 11), 0xc0000000); +- nv_wr32(dev, 0x40831c + (i << 11), 0xc0000000); +- } ++ if (!(units & (1 << i))) ++ continue; ++ ++ if (dev_priv->chipset < 0xa0) { ++ nv_wr32(dev, 0x408900 + (i << 12), 0xc0000000); ++ nv_wr32(dev, 0x408e08 + (i << 12), 0xc0000000); ++ nv_wr32(dev, 0x408314 + (i << 12), 0xc0000000); ++ } else { ++ nv_wr32(dev, 0x408600 + (i << 11), 0xc0000000); ++ nv_wr32(dev, 0x408708 + (i << 11), 0xc0000000); ++ nv_wr32(dev, 0x40831c + (i << 11), 0xc0000000); + } + } + + nv_wr32(dev, 0x400108, 0xffffffff); +- +- nv_wr32(dev, 0x400824, 0x00004000); ++ nv_wr32(dev, 0x400138, 0xffffffff); ++ nv_wr32(dev, 0x400100, 0xffffffff); ++ nv_wr32(dev, 0x40013c, 0xffffffff); + nv_wr32(dev, 0x400500, 0x00010001); +-} +- +-static void +-nv50_graph_init_zcull(struct drm_device *dev) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- int i; +- +- NV_DEBUG(dev, "\n"); + ++ /* upload context program, initialise ctxctl defaults */ ++ nv_wr32(dev, 0x400324, 0x00000000); ++ for (i = 0; i < pgraph->ctxprog_size; i++) ++ nv_wr32(dev, 0x400328, pgraph->ctxprog[i]); ++ nv_wr32(dev, 0x400824, 0x00000000); ++ nv_wr32(dev, 0x400828, 0x00000000); ++ nv_wr32(dev, 0x40082c, 0x00000000); ++ nv_wr32(dev, 0x400830, 0x00000000); ++ nv_wr32(dev, 0x400724, 0x00000000); ++ nv_wr32(dev, 0x40032c, 0x00000000); ++ nv_wr32(dev, 0x400320, 4); /* CTXCTL_CMD = NEWCTXDMA */ ++ ++ /* some unknown zcull magic */ + switch (dev_priv->chipset & 0xf0) { + case 0x50: + case 0x80: +@@ -212,43 +204,7 @@ nv50_graph_init_zcull(struct drm_device *dev) + nv_wr32(dev, 0x402c28 + (i * 8), 0x00000000); + nv_wr32(dev, 0x402c2c + (i * 8), 0x00000000); + } +-} +- +-static int +-nv50_graph_init_ctxctl(struct drm_device *dev) +-{ +- struct nv50_graph_engine *pgraph = nv_engine(dev, NVOBJ_ENGINE_GR); +- int i; +- +- NV_DEBUG(dev, "\n"); +- +- nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); +- for (i = 0; i < pgraph->ctxprog_size; i++) +- nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, pgraph->ctxprog[i]); +- +- nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */ +- nv_wr32(dev, 0x400320, 4); +- nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0); +- nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, 0); +- return 0; +-} +- +-static int +-nv50_graph_init(struct drm_device *dev, int engine) +-{ +- int ret; +- +- NV_DEBUG(dev, "\n"); +- +- nv50_graph_init_reset(dev); +- nv50_graph_init_regs__nv(dev); +- nv50_graph_init_zcull(dev); +- +- ret = nv50_graph_init_ctxctl(dev); +- if (ret) +- return ret; + +- nv50_graph_init_intr(dev); + return 0; + } + +diff --git a/drivers/gpu/drm/nouveau/nv50_grctx.c b/drivers/gpu/drm/nouveau/nv50_grctx.c +index de9abff..d05c2c3 100644 +--- a/drivers/gpu/drm/nouveau/nv50_grctx.c ++++ b/drivers/gpu/drm/nouveau/nv50_grctx.c +@@ -40,6 +40,12 @@ + #define CP_FLAG_UNK0B ((0 * 32) + 0xb) + #define CP_FLAG_UNK0B_CLEAR 0 + #define CP_FLAG_UNK0B_SET 1 ++#define CP_FLAG_XFER_SWITCH ((0 * 32) + 0xe) ++#define CP_FLAG_XFER_SWITCH_DISABLE 0 ++#define CP_FLAG_XFER_SWITCH_ENABLE 1 ++#define CP_FLAG_STATE ((0 * 32) + 0x1c) ++#define CP_FLAG_STATE_STOPPED 0 ++#define CP_FLAG_STATE_RUNNING 1 + #define CP_FLAG_UNK1D ((0 * 32) + 0x1d) + #define CP_FLAG_UNK1D_CLEAR 0 + #define CP_FLAG_UNK1D_SET 1 +@@ -194,6 +200,9 @@ nv50_grctx_init(struct nouveau_grctx *ctx) + "the devs.\n"); + return -ENOSYS; + } ++ ++ cp_set (ctx, STATE, RUNNING); ++ cp_set (ctx, XFER_SWITCH, ENABLE); + /* decide whether we're loading/unloading the context */ + cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save); + cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save); +@@ -260,6 +269,8 @@ nv50_grctx_init(struct nouveau_grctx *ctx) + cp_name(ctx, cp_exit); + cp_set (ctx, USER_SAVE, NOT_PENDING); + cp_set (ctx, USER_LOAD, NOT_PENDING); ++ cp_set (ctx, XFER_SWITCH, DISABLE); ++ cp_set (ctx, STATE, STOPPED); + cp_out (ctx, CP_END); + ctx->ctxvals_pos += 0x400; /* padding... no idea why you need it */ + +diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c +index 8a28100..3d5a86b 100644 +--- a/drivers/gpu/drm/nouveau/nv50_pm.c ++++ b/drivers/gpu/drm/nouveau/nv50_pm.c +@@ -115,15 +115,15 @@ nv50_pm_clock_set(struct drm_device *dev, void *pre_state) + BIT_M.version == 1 && BIT_M.length >= 0x0b) { + script = ROM16(BIT_M.data[0x05]); + if (script) +- nouveau_bios_run_init_table(dev, script, NULL); ++ nouveau_bios_run_init_table(dev, script, NULL, -1); + script = ROM16(BIT_M.data[0x07]); + if (script) +- nouveau_bios_run_init_table(dev, script, NULL); ++ nouveau_bios_run_init_table(dev, script, NULL, -1); + script = ROM16(BIT_M.data[0x09]); + if (script) +- nouveau_bios_run_init_table(dev, script, NULL); ++ nouveau_bios_run_init_table(dev, script, NULL, -1); + +- nouveau_bios_run_init_table(dev, perflvl->memscript, NULL); ++ nouveau_bios_run_init_table(dev, perflvl->memscript, NULL, -1); + } + + if (state->type == PLL_MEMORY) { +diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c +index ffe8b48..2633aa8 100644 +--- a/drivers/gpu/drm/nouveau/nv50_sor.c ++++ b/drivers/gpu/drm/nouveau/nv50_sor.c +@@ -124,7 +124,7 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) + if (mode == DRM_MODE_DPMS_ON) { + u8 status = DP_SET_POWER_D0; + nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); +- nouveau_dp_link_train(encoder); ++ nouveau_dp_link_train(encoder, nv_encoder->dp.datarate); + } else { + u8 status = DP_SET_POWER_D3; + nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); +@@ -187,14 +187,13 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); ++ struct nouveau_connector *nv_connector; + uint32_t mode_ctl = 0; + int ret; + + NV_DEBUG_KMS(dev, "or %d type %d -> crtc %d\n", + nv_encoder->or, nv_encoder->dcb->type, crtc->index); + +- nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); +- + switch (nv_encoder->dcb->type) { + case OUTPUT_TMDS: + if (nv_encoder->dcb->sorconf.link & 1) { +@@ -206,7 +205,15 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + mode_ctl = 0x0200; + break; + case OUTPUT_DP: +- mode_ctl |= (nv_encoder->dp.mc_unknown << 16); ++ nv_connector = nouveau_encoder_connector_get(nv_encoder); ++ if (nv_connector && nv_connector->base.display_info.bpc == 6) { ++ nv_encoder->dp.datarate = crtc->mode->clock * 18 / 8; ++ mode_ctl |= 0x00020000; ++ } else { ++ nv_encoder->dp.datarate = crtc->mode->clock * 24 / 8; ++ mode_ctl |= 0x00050000; ++ } ++ + if (nv_encoder->dcb->sorconf.link & 1) + mode_ctl |= 0x00000800; + else +@@ -227,6 +234,8 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) + mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NVSYNC; + ++ nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); ++ + ret = RING_SPACE(evo, 2); + if (ret) { + NV_ERROR(dev, "no space while connecting SOR\n"); +@@ -313,31 +322,6 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry) + encoder->possible_crtcs = entry->heads; + encoder->possible_clones = 0; + +- if (nv_encoder->dcb->type == OUTPUT_DP) { +- int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1); +- uint32_t tmp; +- +- tmp = nv_rd32(dev, 0x61c700 + (or * 0x800)); +- if (!tmp) +- tmp = nv_rd32(dev, 0x610798 + (or * 8)); +- +- switch ((tmp & 0x00000f00) >> 8) { +- case 8: +- case 9: +- nv_encoder->dp.mc_unknown = (tmp & 0x000f0000) >> 16; +- tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); +- nv_encoder->dp.unk0 = tmp & 0x000001fc; +- tmp = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link)); +- nv_encoder->dp.unk1 = tmp & 0x010f7f3f; +- break; +- default: +- break; +- } +- +- if (!nv_encoder->dp.mc_unknown) +- nv_encoder->dp.mc_unknown = 5; +- } +- + drm_mode_connector_attach_encoder(connector, encoder); + return 0; + } +diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c +index af32dae..9da2383 100644 +--- a/drivers/gpu/drm/nouveau/nv50_vram.c ++++ b/drivers/gpu/drm/nouveau/nv50_vram.c +@@ -51,7 +51,7 @@ void + nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_mm *mm = dev_priv->engine.vram.mm; ++ struct nouveau_mm *mm = &dev_priv->engine.vram.mm; + struct nouveau_mm_node *this; + struct nouveau_mem *mem; + +@@ -82,7 +82,7 @@ nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, + u32 memtype, struct nouveau_mem **pmem) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_mm *mm = dev_priv->engine.vram.mm; ++ struct nouveau_mm *mm = &dev_priv->engine.vram.mm; + struct nouveau_mm_node *r; + struct nouveau_mem *mem; + int comp = (memtype & 0x300) >> 8; +diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c +index e4b2b9e..618c144 100644 +--- a/drivers/gpu/drm/nouveau/nva3_pm.c ++++ b/drivers/gpu/drm/nouveau/nva3_pm.c +@@ -27,178 +27,316 @@ + #include "nouveau_bios.h" + #include "nouveau_pm.h" + +-/* This is actually a lot more complex than it appears here, but hopefully +- * this should be able to deal with what the VBIOS leaves for us.. +- * +- * If not, well, I'll jump off that bridge when I come to it. +- */ ++static u32 read_clk(struct drm_device *, int, bool); ++static u32 read_pll(struct drm_device *, int, u32); + +-struct nva3_pm_state { +- enum pll_types type; +- u32 src0; +- u32 src1; +- u32 ctrl; +- u32 coef; +- u32 old_pnm; +- u32 new_pnm; +- u32 new_div; +-}; ++static u32 ++read_vco(struct drm_device *dev, int clk) ++{ ++ u32 sctl = nv_rd32(dev, 0x4120 + (clk * 4)); ++ if ((sctl & 0x00000030) != 0x00000030) ++ return read_pll(dev, 0x41, 0x00e820); ++ return read_pll(dev, 0x42, 0x00e8a0); ++} + +-static int +-nva3_pm_pll_offset(u32 id) ++static u32 ++read_clk(struct drm_device *dev, int clk, bool ignore_en) + { +- static const u32 pll_map[] = { +- 0x00, PLL_CORE, +- 0x01, PLL_SHADER, +- 0x02, PLL_MEMORY, +- 0x00, 0x00 +- }; +- const u32 *map = pll_map; +- +- while (map[1]) { +- if (id == map[1]) +- return map[0]; +- map += 2; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 sctl, sdiv, sclk; ++ ++ /* refclk for the 0xe8xx plls is a fixed frequency */ ++ if (clk >= 0x40) { ++ if (dev_priv->chipset == 0xaf) { ++ /* no joke.. seriously.. sigh.. */ ++ return nv_rd32(dev, 0x00471c) * 1000; ++ } ++ ++ return dev_priv->crystal; + } + +- return -ENOENT; ++ sctl = nv_rd32(dev, 0x4120 + (clk * 4)); ++ if (!ignore_en && !(sctl & 0x00000100)) ++ return 0; ++ ++ switch (sctl & 0x00003000) { ++ case 0x00000000: ++ return dev_priv->crystal; ++ case 0x00002000: ++ if (sctl & 0x00000040) ++ return 108000; ++ return 100000; ++ case 0x00003000: ++ sclk = read_vco(dev, clk); ++ sdiv = ((sctl & 0x003f0000) >> 16) + 2; ++ return (sclk * 2) / sdiv; ++ default: ++ return 0; ++ } + } + +-int +-nva3_pm_clock_get(struct drm_device *dev, u32 id) ++static u32 ++read_pll(struct drm_device *dev, int clk, u32 pll) ++{ ++ u32 ctrl = nv_rd32(dev, pll + 0); ++ u32 sclk = 0, P = 1, N = 1, M = 1; ++ ++ if (!(ctrl & 0x00000008)) { ++ if (ctrl & 0x00000001) { ++ u32 coef = nv_rd32(dev, pll + 4); ++ M = (coef & 0x000000ff) >> 0; ++ N = (coef & 0x0000ff00) >> 8; ++ P = (coef & 0x003f0000) >> 16; ++ ++ /* no post-divider on these.. */ ++ if ((pll & 0x00ff00) == 0x00e800) ++ P = 1; ++ ++ sclk = read_clk(dev, 0x00 + clk, false); ++ } ++ } else { ++ sclk = read_clk(dev, 0x10 + clk, false); ++ } ++ ++ return sclk * N / (M * P); ++} ++ ++struct creg { ++ u32 clk; ++ u32 pll; ++}; ++ ++static int ++calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) + { +- u32 src0, src1, ctrl, coef; +- struct pll_lims pll; +- int ret, off; +- int P, N, M; ++ struct pll_lims limits; ++ u32 oclk, sclk, sdiv; ++ int P, N, M, diff; ++ int ret; ++ ++ reg->pll = 0; ++ reg->clk = 0; ++ if (!khz) { ++ NV_DEBUG(dev, "no clock for 0x%04x/0x%02x\n", pll, clk); ++ return 0; ++ } + +- ret = get_pll_limits(dev, id, &pll); ++ switch (khz) { ++ case 27000: ++ reg->clk = 0x00000100; ++ return khz; ++ case 100000: ++ reg->clk = 0x00002100; ++ return khz; ++ case 108000: ++ reg->clk = 0x00002140; ++ return khz; ++ default: ++ sclk = read_vco(dev, clk); ++ sdiv = min((sclk * 2) / (khz - 2999), (u32)65); ++ /* if the clock has a PLL attached, and we can get a within ++ * [-2, 3) MHz of a divider, we'll disable the PLL and use ++ * the divider instead. ++ * ++ * divider can go as low as 2, limited here because NVIDIA ++ * and the VBIOS on my NVA8 seem to prefer using the PLL ++ * for 810MHz - is there a good reason? ++ */ ++ if (sdiv > 4) { ++ oclk = (sclk * 2) / sdiv; ++ diff = khz - oclk; ++ if (!pll || (diff >= -2000 && diff < 3000)) { ++ reg->clk = (((sdiv - 2) << 16) | 0x00003100); ++ return oclk; ++ } ++ } ++ ++ if (!pll) { ++ NV_ERROR(dev, "bad freq %02x: %d %d\n", clk, khz, sclk); ++ return -ERANGE; ++ } ++ ++ break; ++ } ++ ++ ret = get_pll_limits(dev, pll, &limits); + if (ret) + return ret; + +- off = nva3_pm_pll_offset(id); +- if (off < 0) +- return off; ++ limits.refclk = read_clk(dev, clk - 0x10, true); ++ if (!limits.refclk) ++ return -EINVAL; ++ ++ ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P); ++ if (ret >= 0) { ++ reg->clk = nv_rd32(dev, 0x4120 + (clk * 4)); ++ reg->pll = (P << 16) | (N << 8) | M; ++ } ++ return ret; ++} ++ ++static void ++prog_pll(struct drm_device *dev, int clk, u32 pll, struct creg *reg) ++{ ++ const u32 src0 = 0x004120 + (clk * 4); ++ const u32 src1 = 0x004160 + (clk * 4); ++ const u32 ctrl = pll + 0; ++ const u32 coef = pll + 4; ++ u32 cntl; ++ ++ if (!reg->clk && !reg->pll) { ++ NV_DEBUG(dev, "no clock for %02x\n", clk); ++ return; ++ } + +- src0 = nv_rd32(dev, 0x4120 + (off * 4)); +- src1 = nv_rd32(dev, 0x4160 + (off * 4)); +- ctrl = nv_rd32(dev, pll.reg + 0); +- coef = nv_rd32(dev, pll.reg + 4); +- NV_DEBUG(dev, "PLL %02x: 0x%08x 0x%08x 0x%08x 0x%08x\n", +- id, src0, src1, ctrl, coef); ++ cntl = nv_rd32(dev, ctrl) & 0xfffffff2; ++ if (reg->pll) { ++ nv_mask(dev, src0, 0x00000101, 0x00000101); ++ nv_wr32(dev, coef, reg->pll); ++ nv_wr32(dev, ctrl, cntl | 0x00000015); ++ nv_mask(dev, src1, 0x00000100, 0x00000000); ++ nv_mask(dev, src1, 0x00000001, 0x00000000); ++ } else { ++ nv_mask(dev, src1, 0x003f3141, 0x00000101 | reg->clk); ++ nv_wr32(dev, ctrl, cntl | 0x0000001d); ++ nv_mask(dev, ctrl, 0x00000001, 0x00000000); ++ nv_mask(dev, src0, 0x00000100, 0x00000000); ++ nv_mask(dev, src0, 0x00000001, 0x00000000); ++ } ++} + +- if (ctrl & 0x00000008) { +- u32 div = ((src1 & 0x003c0000) >> 18) + 1; +- return (pll.refclk * 2) / div; ++static void ++prog_clk(struct drm_device *dev, int clk, struct creg *reg) ++{ ++ if (!reg->clk) { ++ NV_DEBUG(dev, "no clock for %02x\n", clk); ++ return; + } + +- P = (coef & 0x003f0000) >> 16; +- N = (coef & 0x0000ff00) >> 8; +- M = (coef & 0x000000ff); +- return pll.refclk * N / M / P; ++ nv_mask(dev, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | reg->clk); ++} ++ ++int ++nva3_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) ++{ ++ perflvl->core = read_pll(dev, 0x00, 0x4200); ++ perflvl->shader = read_pll(dev, 0x01, 0x4220); ++ perflvl->memory = read_pll(dev, 0x02, 0x4000); ++ perflvl->unka0 = read_clk(dev, 0x20, false); ++ perflvl->vdec = read_clk(dev, 0x21, false); ++ perflvl->daemon = read_clk(dev, 0x25, false); ++ perflvl->copy = perflvl->core; ++ return 0; + } + ++struct nva3_pm_state { ++ struct creg nclk; ++ struct creg sclk; ++ struct creg mclk; ++ struct creg vdec; ++ struct creg unka0; ++}; ++ + void * +-nva3_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, +- u32 id, int khz) ++nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) + { +- struct nva3_pm_state *pll; +- struct pll_lims limits; +- int N, M, P, diff; +- int ret, off; ++ struct nva3_pm_state *info; ++ int ret; + +- ret = get_pll_limits(dev, id, &limits); ++ info = kzalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return ERR_PTR(-ENOMEM); ++ ++ ret = calc_clk(dev, 0x10, 0x4200, perflvl->core, &info->nclk); + if (ret < 0) +- return (ret == -ENOENT) ? NULL : ERR_PTR(ret); ++ goto out; + +- off = nva3_pm_pll_offset(id); +- if (id < 0) +- return ERR_PTR(-EINVAL); ++ ret = calc_clk(dev, 0x11, 0x4220, perflvl->shader, &info->sclk); ++ if (ret < 0) ++ goto out; + ++ ret = calc_clk(dev, 0x12, 0x4000, perflvl->memory, &info->mclk); ++ if (ret < 0) ++ goto out; + +- pll = kzalloc(sizeof(*pll), GFP_KERNEL); +- if (!pll) +- return ERR_PTR(-ENOMEM); +- pll->type = id; +- pll->src0 = 0x004120 + (off * 4); +- pll->src1 = 0x004160 + (off * 4); +- pll->ctrl = limits.reg + 0; +- pll->coef = limits.reg + 4; +- +- /* If target clock is within [-2, 3) MHz of a divisor, we'll +- * use that instead of calculating MNP values +- */ +- pll->new_div = min((limits.refclk * 2) / (khz - 2999), 16); +- if (pll->new_div) { +- diff = khz - ((limits.refclk * 2) / pll->new_div); +- if (diff < -2000 || diff >= 3000) +- pll->new_div = 0; +- } ++ ret = calc_clk(dev, 0x20, 0x0000, perflvl->unka0, &info->unka0); ++ if (ret < 0) ++ goto out; + +- if (!pll->new_div) { +- ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P); +- if (ret < 0) +- return ERR_PTR(ret); ++ ret = calc_clk(dev, 0x21, 0x0000, perflvl->vdec, &info->vdec); ++ if (ret < 0) ++ goto out; + +- pll->new_pnm = (P << 16) | (N << 8) | M; +- pll->new_div = 2 - 1; +- } else { +- pll->new_pnm = 0; +- pll->new_div--; ++out: ++ if (ret < 0) { ++ kfree(info); ++ info = ERR_PTR(ret); + } ++ return info; ++} ++ ++static bool ++nva3_pm_grcp_idle(void *data) ++{ ++ struct drm_device *dev = data; + +- if ((nv_rd32(dev, pll->src1) & 0x00000101) != 0x00000101) +- pll->old_pnm = nv_rd32(dev, pll->coef); +- return pll; ++ if (!(nv_rd32(dev, 0x400304) & 0x00000001)) ++ return true; ++ if (nv_rd32(dev, 0x400308) == 0x0050001c) ++ return true; ++ return false; + } + + void +-nva3_pm_clock_set(struct drm_device *dev, void *pre_state) ++nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) + { +- struct nva3_pm_state *pll = pre_state; +- u32 ctrl = 0; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nva3_pm_state *info = pre_state; ++ unsigned long flags; + +- /* For the memory clock, NVIDIA will build a "script" describing +- * the reclocking process and ask PDAEMON to execute it. +- */ +- if (pll->type == PLL_MEMORY) { +- nv_wr32(dev, 0x100210, 0); +- nv_wr32(dev, 0x1002dc, 1); +- nv_wr32(dev, 0x004018, 0x00001000); +- ctrl = 0x18000100; ++ /* prevent any new grctx switches from starting */ ++ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); ++ nv_wr32(dev, 0x400324, 0x00000000); ++ nv_wr32(dev, 0x400328, 0x0050001c); /* wait flag 0x1c */ ++ /* wait for any pending grctx switches to complete */ ++ if (!nv_wait_cb(dev, nva3_pm_grcp_idle, dev)) { ++ NV_ERROR(dev, "pm: ctxprog didn't go idle\n"); ++ goto cleanup; + } +- +- if (pll->old_pnm || !pll->new_pnm) { +- nv_mask(dev, pll->src1, 0x003c0101, 0x00000101 | +- (pll->new_div << 18)); +- nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl); +- nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000); ++ /* freeze PFIFO */ ++ nv_mask(dev, 0x002504, 0x00000001, 0x00000001); ++ if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010)) { ++ NV_ERROR(dev, "pm: fifo didn't go idle\n"); ++ goto cleanup; + } + +- if (pll->new_pnm) { +- nv_mask(dev, pll->src0, 0x00000101, 0x00000101); +- nv_wr32(dev, pll->coef, pll->new_pnm); +- nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl); +- nv_mask(dev, pll->ctrl, 0x00000010, 0x00000000); +- nv_mask(dev, pll->ctrl, 0x00020010, 0x00020010); +- nv_wr32(dev, pll->ctrl, 0x00010015 | ctrl); +- nv_mask(dev, pll->src1, 0x00000100, 0x00000000); +- nv_mask(dev, pll->src1, 0x00000001, 0x00000000); +- if (pll->type == PLL_MEMORY) +- nv_wr32(dev, 0x4018, 0x10005000); +- } else { +- nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000); +- nv_mask(dev, pll->src0, 0x00000100, 0x00000000); +- nv_mask(dev, pll->src0, 0x00000001, 0x00000000); +- if (pll->type == PLL_MEMORY) +- nv_wr32(dev, 0x4018, 0x1000d000); +- } ++ prog_pll(dev, 0x00, 0x004200, &info->nclk); ++ prog_pll(dev, 0x01, 0x004220, &info->sclk); ++ prog_clk(dev, 0x20, &info->unka0); ++ prog_clk(dev, 0x21, &info->vdec); + +- if (pll->type == PLL_MEMORY) { ++ if (info->mclk.clk || info->mclk.pll) { ++ nv_wr32(dev, 0x100210, 0); ++ nv_wr32(dev, 0x1002dc, 1); ++ nv_wr32(dev, 0x004018, 0x00001000); ++ prog_pll(dev, 0x02, 0x004000, &info->mclk); ++ if (nv_rd32(dev, 0x4000) & 0x00000008) ++ nv_wr32(dev, 0x004018, 0x1000d000); ++ else ++ nv_wr32(dev, 0x004018, 0x10005000); + nv_wr32(dev, 0x1002dc, 0); + nv_wr32(dev, 0x100210, 0x80000000); + } + +- kfree(pll); ++cleanup: ++ /* unfreeze PFIFO */ ++ nv_mask(dev, 0x002504, 0x00000001, 0x00000000); ++ /* restore ctxprog to normal */ ++ nv_wr32(dev, 0x400324, 0x00000000); ++ nv_wr32(dev, 0x400328, 0x0070009c); /* set flag 0x1c */ ++ /* unblock it if necessary */ ++ if (nv_rd32(dev, 0x400308) == 0x0050001c) ++ nv_mask(dev, 0x400824, 0x10000000, 0x10000000); ++ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); ++ kfree(info); + } +- +diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c +index 08e6b11..5bf5503 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_fb.c ++++ b/drivers/gpu/drm/nouveau/nvc0_fb.c +@@ -32,6 +32,30 @@ struct nvc0_fb_priv { + dma_addr_t r100c10; + }; + ++static inline void ++nvc0_mfb_subp_isr(struct drm_device *dev, int unit, int subp) ++{ ++ u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400); ++ u32 stat = nv_rd32(dev, subp_base + 0x020); ++ ++ if (stat) { ++ NV_INFO(dev, "PMFB%d_SUBP%d: 0x%08x\n", unit, subp, stat); ++ nv_wr32(dev, subp_base + 0x020, stat); ++ } ++} ++ ++static void ++nvc0_mfb_isr(struct drm_device *dev) ++{ ++ u32 units = nv_rd32(dev, 0x00017c); ++ while (units) { ++ u32 subp, unit = ffs(units) - 1; ++ for (subp = 0; subp < 2; subp++) ++ nvc0_mfb_subp_isr(dev, unit, subp); ++ units &= ~(1 << unit); ++ } ++} ++ + static void + nvc0_fb_destroy(struct drm_device *dev) + { +@@ -39,6 +63,8 @@ nvc0_fb_destroy(struct drm_device *dev) + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + struct nvc0_fb_priv *priv = pfb->priv; + ++ nouveau_irq_unregister(dev, 25); ++ + if (priv->r100c10_page) { + pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); +@@ -74,6 +100,7 @@ nvc0_fb_create(struct drm_device *dev) + return -EFAULT; + } + ++ nouveau_irq_register(dev, 25, nvc0_mfb_isr); + return 0; + } + +diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c +index 6f9f341..dcbe0d5 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_fifo.c ++++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c +@@ -322,7 +322,7 @@ nvc0_fifo_init(struct drm_device *dev) + } + + /* PSUBFIFO[n] */ +- for (i = 0; i < 3; i++) { ++ for (i = 0; i < priv->spoon_nr; i++) { + nv_mask(dev, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); + nv_wr32(dev, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ + nv_wr32(dev, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTR_EN */ +diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c +index 5b2f6f4..4b8d0b3 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_graph.c ++++ b/drivers/gpu/drm/nouveau/nvc0_graph.c +@@ -390,7 +390,7 @@ nvc0_graph_init_gpc_0(struct drm_device *dev) + } + + nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918); +- nv_wr32(dev, GPC_BCAST(0x08ac), priv->rop_nr); ++ nv_wr32(dev, GPC_BCAST(0x08ac), nv_rd32(dev, 0x100800)); + } + + static void +@@ -700,22 +700,6 @@ nvc0_graph_isr(struct drm_device *dev) + nv_wr32(dev, 0x400500, 0x00010001); + } + +-static void +-nvc0_runk140_isr(struct drm_device *dev) +-{ +- u32 units = nv_rd32(dev, 0x00017c) & 0x1f; +- +- while (units) { +- u32 unit = ffs(units) - 1; +- u32 reg = 0x140000 + unit * 0x2000; +- u32 st0 = nv_mask(dev, reg + 0x1020, 0, 0); +- u32 st1 = nv_mask(dev, reg + 0x1420, 0, 0); +- +- NV_DEBUG(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1); +- units &= ~(1 << unit); +- } +-} +- + static int + nvc0_graph_create_fw(struct drm_device *dev, const char *fwname, + struct nvc0_graph_fuc *fuc) +@@ -764,7 +748,6 @@ nvc0_graph_destroy(struct drm_device *dev, int engine) + } + + nouveau_irq_unregister(dev, 12); +- nouveau_irq_unregister(dev, 25); + + nouveau_gpuobj_ref(NULL, &priv->unk4188b8); + nouveau_gpuobj_ref(NULL, &priv->unk4188b4); +@@ -803,7 +786,6 @@ nvc0_graph_create(struct drm_device *dev) + + NVOBJ_ENGINE_ADD(dev, GR, &priv->base); + nouveau_irq_register(dev, 12, nvc0_graph_isr); +- nouveau_irq_register(dev, 25, nvc0_runk140_isr); + + if (nouveau_ctxfw) { + NV_INFO(dev, "PGRAPH: using external firmware\n"); +@@ -864,6 +846,9 @@ nvc0_graph_create(struct drm_device *dev) + case 0xce: /* 4/4/0/0, 4 */ + priv->magic_not_rop_nr = 0x03; + break; ++ case 0xcf: /* 4/0/0/0, 3 */ ++ priv->magic_not_rop_nr = 0x03; ++ break; + } + + if (!priv->magic_not_rop_nr) { +@@ -889,20 +874,3 @@ error: + nvc0_graph_destroy(dev, NVOBJ_ENGINE_GR); + return ret; + } +- +-MODULE_FIRMWARE("nouveau/nvc0_fuc409c"); +-MODULE_FIRMWARE("nouveau/nvc0_fuc409d"); +-MODULE_FIRMWARE("nouveau/nvc0_fuc41ac"); +-MODULE_FIRMWARE("nouveau/nvc0_fuc41ad"); +-MODULE_FIRMWARE("nouveau/nvc3_fuc409c"); +-MODULE_FIRMWARE("nouveau/nvc3_fuc409d"); +-MODULE_FIRMWARE("nouveau/nvc3_fuc41ac"); +-MODULE_FIRMWARE("nouveau/nvc3_fuc41ad"); +-MODULE_FIRMWARE("nouveau/nvc4_fuc409c"); +-MODULE_FIRMWARE("nouveau/nvc4_fuc409d"); +-MODULE_FIRMWARE("nouveau/nvc4_fuc41ac"); +-MODULE_FIRMWARE("nouveau/nvc4_fuc41ad"); +-MODULE_FIRMWARE("nouveau/fuc409c"); +-MODULE_FIRMWARE("nouveau/fuc409d"); +-MODULE_FIRMWARE("nouveau/fuc41ac"); +-MODULE_FIRMWARE("nouveau/fuc41ad"); +diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.h b/drivers/gpu/drm/nouveau/nvc0_graph.h +index 55689e9..636fe98 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_graph.h ++++ b/drivers/gpu/drm/nouveau/nvc0_graph.h +@@ -82,6 +82,7 @@ nvc0_graph_class(struct drm_device *dev) + case 0xc3: + case 0xc4: + case 0xce: /* guess, mmio trace shows only 0x9097 state */ ++ case 0xcf: /* guess, mmio trace shows only 0x9097 state */ + return 0x9097; + case 0xc1: + return 0x9197; +diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c +index 31018ea..dd0e6a7 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_grctx.c ++++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c +@@ -1678,7 +1678,10 @@ nvc0_grctx_generate_tp(struct drm_device *dev) + nv_wr32(dev, 0x419c04, 0x00000006); + nv_wr32(dev, 0x419c08, 0x00000002); + nv_wr32(dev, 0x419c20, 0x00000000); +- nv_wr32(dev, 0x419cb0, 0x00060048); //XXX: 0xce 0x00020048 ++ if (chipset == 0xce || chipset == 0xcf) ++ nv_wr32(dev, 0x419cb0, 0x00020048); ++ else ++ nv_wr32(dev, 0x419cb0, 0x00060048); + nv_wr32(dev, 0x419ce8, 0x00000000); + nv_wr32(dev, 0x419cf4, 0x00000183); + nv_wr32(dev, 0x419d20, chipset != 0xc1 ? 0x02180000 : 0x12180000); +@@ -1783,11 +1786,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) + nv_wr32(dev, 0x40587c, 0x00000000); + + if (1) { +- const u8 chipset_tp_max[] = { 16, 4, 0, 4, 8, 0, 0, 0, +- 16, 0, 0, 0, 0, 0, 8, 0 }; +- u8 max = chipset_tp_max[dev_priv->chipset & 0x0f]; +- u8 tpnr[GPC_MAX]; +- u8 data[TP_MAX]; ++ u8 tpnr[GPC_MAX], data[TP_MAX]; + + memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); + memset(data, 0x1f, sizeof(data)); +@@ -1801,7 +1800,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) + data[tp] = gpc; + } + +- for (i = 0; i < max / 4; i++) ++ for (i = 0; i < 4; i++) + nv_wr32(dev, 0x4060a8 + (i * 4), ((u32 *)data)[i]); + } + +diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc +index 0ec2add..06f5e26 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc ++++ b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc +@@ -77,6 +77,11 @@ chipsets: + .b16 nvc0_gpc_mmio_tail + .b16 nvc0_tpc_mmio_head + .b16 nvc3_tpc_mmio_tail ++.b8 0xcf 0 0 0 ++.b16 nvc0_gpc_mmio_head ++.b16 nvc0_gpc_mmio_tail ++.b16 nvc0_tpc_mmio_head ++.b16 nvcf_tpc_mmio_tail + .b8 0 0 0 0 + + // GPC mmio lists +@@ -134,8 +139,9 @@ mmctx_data(0x000750, 2) + nvc0_tpc_mmio_tail: + mmctx_data(0x000758, 1) + mmctx_data(0x0002c4, 1) +-mmctx_data(0x0004bc, 1) + mmctx_data(0x0006e0, 1) ++nvcf_tpc_mmio_tail: ++mmctx_data(0x0004bc, 1) + nvc3_tpc_mmio_tail: + mmctx_data(0x000544, 1) + nvc1_tpc_mmio_tail: +diff --git a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h +index 1896c89..6f82032 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h ++++ b/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h +@@ -25,23 +25,26 @@ uint32_t nvc0_grgpc_data[] = { + 0x00000000, + 0x00000000, + 0x000000c0, +- 0x011000b0, +- 0x01640114, ++ 0x011c00bc, ++ 0x01700120, + 0x000000c1, +- 0x011400b0, +- 0x01780114, ++ 0x012000bc, ++ 0x01840120, + 0x000000c3, +- 0x011000b0, +- 0x01740114, ++ 0x011c00bc, ++ 0x01800120, + 0x000000c4, +- 0x011000b0, +- 0x01740114, ++ 0x011c00bc, ++ 0x01800120, + 0x000000c8, +- 0x011000b0, +- 0x01640114, ++ 0x011c00bc, ++ 0x01700120, + 0x000000ce, +- 0x011000b0, +- 0x01740114, ++ 0x011c00bc, ++ 0x01800120, ++ 0x000000cf, ++ 0x011c00bc, ++ 0x017c0120, + 0x00000000, + 0x00000380, + 0x14000400, +@@ -90,8 +93,8 @@ uint32_t nvc0_grgpc_data[] = { + 0x04000750, + 0x00000758, + 0x000002c4, +- 0x000004bc, + 0x000006e0, ++ 0x000004bc, + 0x00000544, + }; + +diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc +index a1a5991..e4f8c7e 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc ++++ b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc +@@ -56,6 +56,9 @@ chipsets: + .b8 0xce 0 0 0 + .b16 nvc0_hub_mmio_head + .b16 nvc0_hub_mmio_tail ++.b8 0xcf 0 0 0 ++.b16 nvc0_hub_mmio_head ++.b16 nvc0_hub_mmio_tail + .b8 0 0 0 0 + + nvc0_hub_mmio_head: +diff --git a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h +index b3b541b..241d326 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h ++++ b/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h +@@ -23,17 +23,19 @@ uint32_t nvc0_grhub_data[] = { + 0x00000000, + 0x00000000, + 0x000000c0, +- 0x012c0090, ++ 0x01340098, + 0x000000c1, +- 0x01300090, ++ 0x01380098, + 0x000000c3, +- 0x012c0090, ++ 0x01340098, + 0x000000c4, +- 0x012c0090, ++ 0x01340098, + 0x000000c8, +- 0x012c0090, ++ 0x01340098, + 0x000000ce, +- 0x012c0090, ++ 0x01340098, ++ 0x000000cf, ++ 0x01340098, + 0x00000000, + 0x0417e91c, + 0x04400204, +@@ -190,8 +192,6 @@ uint32_t nvc0_grhub_data[] = { + 0x00000000, + 0x00000000, + 0x00000000, +- 0x00000000, +- 0x00000000, + }; + + uint32_t nvc0_grhub_code[] = { +diff --git a/drivers/gpu/drm/nouveau/nvc0_pm.c b/drivers/gpu/drm/nouveau/nvc0_pm.c +new file mode 100644 +index 0000000..929aded +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nvc0_pm.c +@@ -0,0 +1,155 @@ ++/* ++ * Copyright 2011 Red Hat Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: Ben Skeggs ++ */ ++ ++#include "drmP.h" ++#include "nouveau_drv.h" ++#include "nouveau_bios.h" ++#include "nouveau_pm.h" ++ ++static u32 read_div(struct drm_device *, int, u32, u32); ++static u32 read_pll(struct drm_device *, u32); ++ ++static u32 ++read_vco(struct drm_device *dev, u32 dsrc) ++{ ++ u32 ssrc = nv_rd32(dev, dsrc); ++ if (!(ssrc & 0x00000100)) ++ return read_pll(dev, 0x00e800); ++ return read_pll(dev, 0x00e820); ++} ++ ++static u32 ++read_pll(struct drm_device *dev, u32 pll) ++{ ++ u32 ctrl = nv_rd32(dev, pll + 0); ++ u32 coef = nv_rd32(dev, pll + 4); ++ u32 P = (coef & 0x003f0000) >> 16; ++ u32 N = (coef & 0x0000ff00) >> 8; ++ u32 M = (coef & 0x000000ff) >> 0; ++ u32 sclk, doff; ++ ++ if (!(ctrl & 0x00000001)) ++ return 0; ++ ++ switch (pll & 0xfff000) { ++ case 0x00e000: ++ sclk = 27000; ++ P = 1; ++ break; ++ case 0x137000: ++ doff = (pll - 0x137000) / 0x20; ++ sclk = read_div(dev, doff, 0x137120, 0x137140); ++ break; ++ case 0x132000: ++ switch (pll) { ++ case 0x132000: ++ sclk = read_pll(dev, 0x132020); ++ break; ++ case 0x132020: ++ sclk = read_div(dev, 0, 0x137320, 0x137330); ++ break; ++ default: ++ return 0; ++ } ++ break; ++ default: ++ return 0; ++ } ++ ++ return sclk * N / M / P; ++} ++ ++static u32 ++read_div(struct drm_device *dev, int doff, u32 dsrc, u32 dctl) ++{ ++ u32 ssrc = nv_rd32(dev, dsrc + (doff * 4)); ++ u32 sctl = nv_rd32(dev, dctl + (doff * 4)); ++ ++ switch (ssrc & 0x00000003) { ++ case 0: ++ if ((ssrc & 0x00030000) != 0x00030000) ++ return 27000; ++ return 108000; ++ case 2: ++ return 100000; ++ case 3: ++ if (sctl & 0x80000000) { ++ u32 sclk = read_vco(dev, dsrc + (doff * 4)); ++ u32 sdiv = (sctl & 0x0000003f) + 2; ++ return (sclk * 2) / sdiv; ++ } ++ ++ return read_vco(dev, dsrc + (doff * 4)); ++ default: ++ return 0; ++ } ++} ++ ++static u32 ++read_mem(struct drm_device *dev) ++{ ++ u32 ssel = nv_rd32(dev, 0x1373f0); ++ if (ssel & 0x00000001) ++ return read_div(dev, 0, 0x137300, 0x137310); ++ return read_pll(dev, 0x132000); ++} ++ ++static u32 ++read_clk(struct drm_device *dev, int clk) ++{ ++ u32 sctl = nv_rd32(dev, 0x137250 + (clk * 4)); ++ u32 ssel = nv_rd32(dev, 0x137100); ++ u32 sclk, sdiv; ++ ++ if (ssel & (1 << clk)) { ++ if (clk < 7) ++ sclk = read_pll(dev, 0x137000 + (clk * 0x20)); ++ else ++ sclk = read_pll(dev, 0x1370e0); ++ sdiv = ((sctl & 0x00003f00) >> 8) + 2; ++ } else { ++ sclk = read_div(dev, clk, 0x137160, 0x1371d0); ++ sdiv = ((sctl & 0x0000003f) >> 0) + 2; ++ } ++ ++ if (sctl & 0x80000000) ++ return (sclk * 2) / sdiv; ++ return sclk; ++} ++ ++int ++nvc0_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) ++{ ++ perflvl->shader = read_clk(dev, 0x00); ++ perflvl->core = perflvl->shader / 2; ++ perflvl->memory = read_mem(dev); ++ perflvl->rop = read_clk(dev, 0x01); ++ perflvl->hub07 = read_clk(dev, 0x02); ++ perflvl->hub06 = read_clk(dev, 0x07); ++ perflvl->hub01 = read_clk(dev, 0x08); ++ perflvl->copy = read_clk(dev, 0x09); ++ perflvl->daemon = read_clk(dev, 0x0c); ++ perflvl->vdec = read_clk(dev, 0x0e); ++ return 0; ++} +diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c +index e45a24d..edbfe93 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_vram.c ++++ b/drivers/gpu/drm/nouveau/nvc0_vram.c +@@ -61,7 +61,7 @@ nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, + u32 type, struct nouveau_mem **pmem) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_mm *mm = dev_priv->engine.vram.mm; ++ struct nouveau_mm *mm = &dev_priv->engine.vram.mm; + struct nouveau_mm_node *r; + struct nouveau_mem *mem; + int ret; +@@ -106,12 +106,50 @@ nvc0_vram_init(struct drm_device *dev) + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; + const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ + const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ +- u32 length; ++ u32 parts = nv_rd32(dev, 0x121c74); ++ u32 bsize = nv_rd32(dev, 0x10f20c); ++ u32 offset, length; ++ bool uniform = true; ++ int ret, i; + +- dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; +- dev_priv->vram_size *= nv_rd32(dev, 0x121c74); ++ NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800)); ++ NV_DEBUG(dev, "parts 0x%08x bcast_mem_amount 0x%08x\n", parts, bsize); + +- length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; ++ /* read amount of vram attached to each memory controller */ ++ for (i = 0; i < parts; i++) { ++ u32 psize = nv_rd32(dev, 0x11020c + (i * 0x1000)); ++ if (psize != bsize) { ++ if (psize < bsize) ++ bsize = psize; ++ uniform = false; ++ } ++ ++ NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", i, psize); ++ ++ dev_priv->vram_size += (u64)psize << 20; ++ } ++ ++ /* if all controllers have the same amount attached, there's no holes */ ++ if (uniform) { ++ offset = rsvd_head; ++ length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; ++ return nouveau_mm_init(&vram->mm, offset, length, 1); ++ } + +- return nouveau_mm_init(&vram->mm, rsvd_head, length, 1); ++ /* otherwise, address lowest common amount from 0GiB */ ++ ret = nouveau_mm_init(&vram->mm, rsvd_head, (bsize << 8) * parts, 1); ++ if (ret) ++ return ret; ++ ++ /* and the rest starting from (8GiB + common_size) */ ++ offset = (0x0200000000ULL >> 12) + (bsize << 8); ++ length = (dev_priv->vram_size >> 12) - (bsize << 8) - rsvd_tail; ++ ++ ret = nouveau_mm_init(&vram->mm, offset, length, 0); ++ if (ret) { ++ nouveau_mm_fini(&vram->mm); ++ return ret; ++ } ++ ++ return 0; + } +diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c +new file mode 100644 +index 0000000..23d63b4 +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nvd0_display.c +@@ -0,0 +1,1473 @@ ++/* ++ * Copyright 2011 Red Hat Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: Ben Skeggs ++ */ ++ ++#include ++ ++#include "drmP.h" ++#include "drm_crtc_helper.h" ++ ++#include "nouveau_drv.h" ++#include "nouveau_connector.h" ++#include "nouveau_encoder.h" ++#include "nouveau_crtc.h" ++#include "nouveau_dma.h" ++#include "nouveau_fb.h" ++#include "nv50_display.h" ++ ++struct nvd0_display { ++ struct nouveau_gpuobj *mem; ++ struct { ++ dma_addr_t handle; ++ u32 *ptr; ++ } evo[1]; ++ ++ struct tasklet_struct tasklet; ++ u32 modeset; ++}; ++ ++static struct nvd0_display * ++nvd0_display(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ return dev_priv->engine.display.priv; ++} ++ ++static inline int ++evo_icmd(struct drm_device *dev, int id, u32 mthd, u32 data) ++{ ++ int ret = 0; ++ nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000001); ++ nv_wr32(dev, 0x610704 + (id * 0x10), data); ++ nv_mask(dev, 0x610704 + (id * 0x10), 0x80000ffc, 0x80000000 | mthd); ++ if (!nv_wait(dev, 0x610704 + (id * 0x10), 0x80000000, 0x00000000)) ++ ret = -EBUSY; ++ nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000000); ++ return ret; ++} ++ ++static u32 * ++evo_wait(struct drm_device *dev, int id, int nr) ++{ ++ struct nvd0_display *disp = nvd0_display(dev); ++ u32 put = nv_rd32(dev, 0x640000 + (id * 0x1000)) / 4; ++ ++ if (put + nr >= (PAGE_SIZE / 4)) { ++ disp->evo[id].ptr[put] = 0x20000000; ++ ++ nv_wr32(dev, 0x640000 + (id * 0x1000), 0x00000000); ++ if (!nv_wait(dev, 0x640004 + (id * 0x1000), ~0, 0x00000000)) { ++ NV_ERROR(dev, "evo %d dma stalled\n", id); ++ return NULL; ++ } ++ ++ put = 0; ++ } ++ ++ return disp->evo[id].ptr + put; ++} ++ ++static void ++evo_kick(u32 *push, struct drm_device *dev, int id) ++{ ++ struct nvd0_display *disp = nvd0_display(dev); ++ nv_wr32(dev, 0x640000 + (id * 0x1000), (push - disp->evo[id].ptr) << 2); ++} ++ ++#define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m)) ++#define evo_data(p,d) *((p)++) = (d) ++ ++static struct drm_crtc * ++nvd0_display_crtc_get(struct drm_encoder *encoder) ++{ ++ return nouveau_encoder(encoder)->crtc; ++} ++ ++/****************************************************************************** ++ * CRTC ++ *****************************************************************************/ ++static int ++nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update) ++{ ++ struct drm_device *dev = nv_crtc->base.dev; ++ u32 *push, mode; ++ ++ mode = 0x00000000; ++ if (on) { ++ /* 0x11: 6bpc dynamic 2x2 ++ * 0x13: 8bpc dynamic 2x2 ++ * 0x19: 6bpc static 2x2 ++ * 0x1b: 8bpc static 2x2 ++ * 0x21: 6bpc temporal ++ * 0x23: 8bpc temporal ++ */ ++ mode = 0x00000011; ++ } ++ ++ push = evo_wait(dev, 0, 4); ++ if (push) { ++ evo_mthd(push, 0x0490 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, mode); ++ if (update) { ++ evo_mthd(push, 0x0080, 1); ++ evo_data(push, 0x00000000); ++ } ++ evo_kick(push, dev, 0); ++ } ++ ++ return 0; ++} ++ ++static int ++nvd0_crtc_set_scale(struct nouveau_crtc *nv_crtc, int type, bool update) ++{ ++ struct drm_display_mode *mode = &nv_crtc->base.mode; ++ struct drm_device *dev = nv_crtc->base.dev; ++ struct nouveau_connector *nv_connector; ++ u32 *push, outX, outY; ++ ++ outX = mode->hdisplay; ++ outY = mode->vdisplay; ++ ++ nv_connector = nouveau_crtc_connector_get(nv_crtc); ++ if (nv_connector && nv_connector->native_mode) { ++ struct drm_display_mode *native = nv_connector->native_mode; ++ u32 xratio = (native->hdisplay << 19) / mode->hdisplay; ++ u32 yratio = (native->vdisplay << 19) / mode->vdisplay; ++ ++ switch (type) { ++ case DRM_MODE_SCALE_ASPECT: ++ if (xratio > yratio) { ++ outX = (mode->hdisplay * yratio) >> 19; ++ outY = (mode->vdisplay * yratio) >> 19; ++ } else { ++ outX = (mode->hdisplay * xratio) >> 19; ++ outY = (mode->vdisplay * xratio) >> 19; ++ } ++ break; ++ case DRM_MODE_SCALE_FULLSCREEN: ++ outX = native->hdisplay; ++ outY = native->vdisplay; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ push = evo_wait(dev, 0, 16); ++ if (push) { ++ evo_mthd(push, 0x04c0 + (nv_crtc->index * 0x300), 3); ++ evo_data(push, (outY << 16) | outX); ++ evo_data(push, (outY << 16) | outX); ++ evo_data(push, (outY << 16) | outX); ++ evo_mthd(push, 0x0494 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x04b8 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, (mode->vdisplay << 16) | mode->hdisplay); ++ if (update) { ++ evo_mthd(push, 0x0080, 1); ++ evo_data(push, 0x00000000); ++ } ++ evo_kick(push, dev, 0); ++ } ++ ++ return 0; ++} ++ ++static int ++nvd0_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb, ++ int x, int y, bool update) ++{ ++ struct nouveau_framebuffer *nvfb = nouveau_framebuffer(fb); ++ u32 *push; ++ ++ push = evo_wait(fb->dev, 0, 16); ++ if (push) { ++ evo_mthd(push, 0x0460 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, nvfb->nvbo->bo.offset >> 8); ++ evo_mthd(push, 0x0468 + (nv_crtc->index * 0x300), 4); ++ evo_data(push, (fb->height << 16) | fb->width); ++ evo_data(push, nvfb->r_pitch); ++ evo_data(push, nvfb->r_format); ++ evo_data(push, nvfb->r_dma); ++ evo_mthd(push, 0x04b0 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, (y << 16) | x); ++ if (update) { ++ evo_mthd(push, 0x0080, 1); ++ evo_data(push, 0x00000000); ++ } ++ evo_kick(push, fb->dev, 0); ++ } ++ ++ nv_crtc->fb.tile_flags = nvfb->r_dma; ++ return 0; ++} ++ ++static void ++nvd0_crtc_cursor_show(struct nouveau_crtc *nv_crtc, bool show, bool update) ++{ ++ struct drm_device *dev = nv_crtc->base.dev; ++ u32 *push = evo_wait(dev, 0, 16); ++ if (push) { ++ if (show) { ++ evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2); ++ evo_data(push, 0x85000000); ++ evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8); ++ evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1); ++ evo_data(push, NvEvoVRAM); ++ } else { ++ evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, 0x05000000); ++ evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1); ++ evo_data(push, 0x00000000); ++ } ++ ++ if (update) { ++ evo_mthd(push, 0x0080, 1); ++ evo_data(push, 0x00000000); ++ } ++ ++ evo_kick(push, dev, 0); ++ } ++} ++ ++static void ++nvd0_crtc_dpms(struct drm_crtc *crtc, int mode) ++{ ++} ++ ++static void ++nvd0_crtc_prepare(struct drm_crtc *crtc) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ u32 *push; ++ ++ push = evo_wait(crtc->dev, 0, 2); ++ if (push) { ++ evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, 0x03000000); ++ evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1); ++ evo_data(push, 0x00000000); ++ evo_kick(push, crtc->dev, 0); ++ } ++ ++ nvd0_crtc_cursor_show(nv_crtc, false, false); ++} ++ ++static void ++nvd0_crtc_commit(struct drm_crtc *crtc) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ u32 *push; ++ ++ push = evo_wait(crtc->dev, 0, 32); ++ if (push) { ++ evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, nv_crtc->fb.tile_flags); ++ evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 4); ++ evo_data(push, 0x83000000); ++ evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8); ++ evo_data(push, 0x00000000); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1); ++ evo_data(push, NvEvoVRAM); ++ evo_mthd(push, 0x0430 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, 0xffffff00); ++ evo_kick(push, crtc->dev, 0); ++ } ++ ++ nvd0_crtc_cursor_show(nv_crtc, nv_crtc->cursor.visible, true); ++} ++ ++static bool ++nvd0_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ return true; ++} ++ ++static int ++nvd0_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) ++{ ++ struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb); ++ int ret; ++ ++ ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM); ++ if (ret) ++ return ret; ++ ++ if (old_fb) { ++ nvfb = nouveau_framebuffer(old_fb); ++ nouveau_bo_unpin(nvfb->nvbo); ++ } ++ ++ return 0; ++} ++ ++static int ++nvd0_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode, ++ struct drm_display_mode *mode, int x, int y, ++ struct drm_framebuffer *old_fb) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ struct nouveau_connector *nv_connector; ++ u32 htotal = mode->htotal; ++ u32 vtotal = mode->vtotal; ++ u32 hsyncw = mode->hsync_end - mode->hsync_start - 1; ++ u32 vsyncw = mode->vsync_end - mode->vsync_start - 1; ++ u32 hfrntp = mode->hsync_start - mode->hdisplay; ++ u32 vfrntp = mode->vsync_start - mode->vdisplay; ++ u32 hbackp = mode->htotal - mode->hsync_end; ++ u32 vbackp = mode->vtotal - mode->vsync_end; ++ u32 hss2be = hsyncw + hbackp; ++ u32 vss2be = vsyncw + vbackp; ++ u32 hss2de = htotal - hfrntp; ++ u32 vss2de = vtotal - vfrntp; ++ u32 syncs, *push; ++ int ret; ++ ++ syncs = 0x00000001; ++ if (mode->flags & DRM_MODE_FLAG_NHSYNC) ++ syncs |= 0x00000008; ++ if (mode->flags & DRM_MODE_FLAG_NVSYNC) ++ syncs |= 0x00000010; ++ ++ ret = nvd0_crtc_swap_fbs(crtc, old_fb); ++ if (ret) ++ return ret; ++ ++ push = evo_wait(crtc->dev, 0, 64); ++ if (push) { ++ evo_mthd(push, 0x0410 + (nv_crtc->index * 0x300), 5); ++ evo_data(push, 0x00000000); ++ evo_data(push, (vtotal << 16) | htotal); ++ evo_data(push, (vsyncw << 16) | hsyncw); ++ evo_data(push, (vss2be << 16) | hss2be); ++ evo_data(push, (vss2de << 16) | hss2de); ++ evo_mthd(push, 0x042c + (nv_crtc->index * 0x300), 1); ++ evo_data(push, 0x00000000); /* ??? */ ++ evo_mthd(push, 0x0450 + (nv_crtc->index * 0x300), 3); ++ evo_data(push, mode->clock * 1000); ++ evo_data(push, 0x00200000); /* ??? */ ++ evo_data(push, mode->clock * 1000); ++ evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 1); ++ evo_data(push, syncs); ++ evo_kick(push, crtc->dev, 0); ++ } ++ ++ nv_connector = nouveau_crtc_connector_get(nv_crtc); ++ nvd0_crtc_set_dither(nv_crtc, nv_connector->use_dithering, false); ++ nvd0_crtc_set_scale(nv_crtc, nv_connector->scaling_mode, false); ++ nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, false); ++ return 0; ++} ++ ++static int ++nvd0_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, ++ struct drm_framebuffer *old_fb) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ int ret; ++ ++ if (!crtc->fb) { ++ NV_DEBUG_KMS(crtc->dev, "No FB bound\n"); ++ return 0; ++ } ++ ++ ret = nvd0_crtc_swap_fbs(crtc, old_fb); ++ if (ret) ++ return ret; ++ ++ nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, true); ++ return 0; ++} ++ ++static int ++nvd0_crtc_mode_set_base_atomic(struct drm_crtc *crtc, ++ struct drm_framebuffer *fb, int x, int y, ++ enum mode_set_atomic state) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ nvd0_crtc_set_image(nv_crtc, fb, x, y, true); ++ return 0; ++} ++ ++static void ++nvd0_crtc_lut_load(struct drm_crtc *crtc) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo); ++ int i; ++ ++ for (i = 0; i < 256; i++) { ++ writew(0x6000 + (nv_crtc->lut.r[i] >> 2), lut + (i * 0x20) + 0); ++ writew(0x6000 + (nv_crtc->lut.g[i] >> 2), lut + (i * 0x20) + 2); ++ writew(0x6000 + (nv_crtc->lut.b[i] >> 2), lut + (i * 0x20) + 4); ++ } ++} ++ ++static int ++nvd0_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, ++ uint32_t handle, uint32_t width, uint32_t height) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ struct drm_device *dev = crtc->dev; ++ struct drm_gem_object *gem; ++ struct nouveau_bo *nvbo; ++ bool visible = (handle != 0); ++ int i, ret = 0; ++ ++ if (visible) { ++ if (width != 64 || height != 64) ++ return -EINVAL; ++ ++ gem = drm_gem_object_lookup(dev, file_priv, handle); ++ if (unlikely(!gem)) ++ return -ENOENT; ++ nvbo = nouveau_gem_object(gem); ++ ++ ret = nouveau_bo_map(nvbo); ++ if (ret == 0) { ++ for (i = 0; i < 64 * 64; i++) { ++ u32 v = nouveau_bo_rd32(nvbo, i); ++ nouveau_bo_wr32(nv_crtc->cursor.nvbo, i, v); ++ } ++ nouveau_bo_unmap(nvbo); ++ } ++ ++ drm_gem_object_unreference_unlocked(gem); ++ } ++ ++ if (visible != nv_crtc->cursor.visible) { ++ nvd0_crtc_cursor_show(nv_crtc, visible, true); ++ nv_crtc->cursor.visible = visible; ++ } ++ ++ return ret; ++} ++ ++static int ++nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ const u32 data = (y << 16) | x; ++ ++ nv_wr32(crtc->dev, 0x64d084 + (nv_crtc->index * 0x1000), data); ++ nv_wr32(crtc->dev, 0x64d080 + (nv_crtc->index * 0x1000), 0x00000000); ++ return 0; ++} ++ ++static void ++nvd0_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, ++ uint32_t start, uint32_t size) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ u32 end = max(start + size, (u32)256); ++ u32 i; ++ ++ for (i = start; i < end; i++) { ++ nv_crtc->lut.r[i] = r[i]; ++ nv_crtc->lut.g[i] = g[i]; ++ nv_crtc->lut.b[i] = b[i]; ++ } ++ ++ nvd0_crtc_lut_load(crtc); ++} ++ ++static void ++nvd0_crtc_destroy(struct drm_crtc *crtc) ++{ ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ nouveau_bo_unmap(nv_crtc->cursor.nvbo); ++ nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); ++ nouveau_bo_unmap(nv_crtc->lut.nvbo); ++ nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); ++ drm_crtc_cleanup(crtc); ++ kfree(crtc); ++} ++ ++static const struct drm_crtc_helper_funcs nvd0_crtc_hfunc = { ++ .dpms = nvd0_crtc_dpms, ++ .prepare = nvd0_crtc_prepare, ++ .commit = nvd0_crtc_commit, ++ .mode_fixup = nvd0_crtc_mode_fixup, ++ .mode_set = nvd0_crtc_mode_set, ++ .mode_set_base = nvd0_crtc_mode_set_base, ++ .mode_set_base_atomic = nvd0_crtc_mode_set_base_atomic, ++ .load_lut = nvd0_crtc_lut_load, ++}; ++ ++static const struct drm_crtc_funcs nvd0_crtc_func = { ++ .cursor_set = nvd0_crtc_cursor_set, ++ .cursor_move = nvd0_crtc_cursor_move, ++ .gamma_set = nvd0_crtc_gamma_set, ++ .set_config = drm_crtc_helper_set_config, ++ .destroy = nvd0_crtc_destroy, ++}; ++ ++static void ++nvd0_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y) ++{ ++} ++ ++static void ++nvd0_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset) ++{ ++} ++ ++static int ++nvd0_crtc_create(struct drm_device *dev, int index) ++{ ++ struct nouveau_crtc *nv_crtc; ++ struct drm_crtc *crtc; ++ int ret, i; ++ ++ nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL); ++ if (!nv_crtc) ++ return -ENOMEM; ++ ++ nv_crtc->index = index; ++ nv_crtc->set_dither = nvd0_crtc_set_dither; ++ nv_crtc->set_scale = nvd0_crtc_set_scale; ++ nv_crtc->cursor.set_offset = nvd0_cursor_set_offset; ++ nv_crtc->cursor.set_pos = nvd0_cursor_set_pos; ++ for (i = 0; i < 256; i++) { ++ nv_crtc->lut.r[i] = i << 8; ++ nv_crtc->lut.g[i] = i << 8; ++ nv_crtc->lut.b[i] = i << 8; ++ } ++ ++ crtc = &nv_crtc->base; ++ drm_crtc_init(dev, crtc, &nvd0_crtc_func); ++ drm_crtc_helper_add(crtc, &nvd0_crtc_hfunc); ++ drm_mode_crtc_set_gamma_size(crtc, 256); ++ ++ ret = nouveau_bo_new(dev, 64 * 64 * 4, 0x100, TTM_PL_FLAG_VRAM, ++ 0, 0x0000, &nv_crtc->cursor.nvbo); ++ if (!ret) { ++ ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); ++ if (!ret) ++ ret = nouveau_bo_map(nv_crtc->cursor.nvbo); ++ if (ret) ++ nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); ++ } ++ ++ if (ret) ++ goto out; ++ ++ ret = nouveau_bo_new(dev, 8192, 0x100, TTM_PL_FLAG_VRAM, ++ 0, 0x0000, &nv_crtc->lut.nvbo); ++ if (!ret) { ++ ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM); ++ if (!ret) ++ ret = nouveau_bo_map(nv_crtc->lut.nvbo); ++ if (ret) ++ nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); ++ } ++ ++ if (ret) ++ goto out; ++ ++ nvd0_crtc_lut_load(crtc); ++ ++out: ++ if (ret) ++ nvd0_crtc_destroy(crtc); ++ return ret; ++} ++ ++/****************************************************************************** ++ * DAC ++ *****************************************************************************/ ++static void ++nvd0_dac_dpms(struct drm_encoder *encoder, int mode) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct drm_device *dev = encoder->dev; ++ int or = nv_encoder->or; ++ u32 dpms_ctrl; ++ ++ dpms_ctrl = 0x80000000; ++ if (mode == DRM_MODE_DPMS_STANDBY || mode == DRM_MODE_DPMS_OFF) ++ dpms_ctrl |= 0x00000001; ++ if (mode == DRM_MODE_DPMS_SUSPEND || mode == DRM_MODE_DPMS_OFF) ++ dpms_ctrl |= 0x00000004; ++ ++ nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000); ++ nv_mask(dev, 0x61a004 + (or * 0x0800), 0xc000007f, dpms_ctrl); ++ nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000); ++} ++ ++static bool ++nvd0_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_connector *nv_connector; ++ ++ nv_connector = nouveau_encoder_connector_get(nv_encoder); ++ if (nv_connector && nv_connector->native_mode) { ++ if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) { ++ int id = adjusted_mode->base.id; ++ *adjusted_mode = *nv_connector->native_mode; ++ adjusted_mode->base.id = id; ++ } ++ } ++ ++ return true; ++} ++ ++static void ++nvd0_dac_prepare(struct drm_encoder *encoder) ++{ ++} ++ ++static void ++nvd0_dac_commit(struct drm_encoder *encoder) ++{ ++} ++ ++static void ++nvd0_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); ++ u32 *push; ++ ++ nvd0_dac_dpms(encoder, DRM_MODE_DPMS_ON); ++ ++ push = evo_wait(encoder->dev, 0, 4); ++ if (push) { ++ evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 2); ++ evo_data(push, 1 << nv_crtc->index); ++ evo_data(push, 0x00ff); ++ evo_kick(push, encoder->dev, 0); ++ } ++ ++ nv_encoder->crtc = encoder->crtc; ++} ++ ++static void ++nvd0_dac_disconnect(struct drm_encoder *encoder) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct drm_device *dev = encoder->dev; ++ u32 *push; ++ ++ if (nv_encoder->crtc) { ++ nvd0_crtc_prepare(nv_encoder->crtc); ++ ++ push = evo_wait(dev, 0, 4); ++ if (push) { ++ evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 1); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x0080, 1); ++ evo_data(push, 0x00000000); ++ evo_kick(push, dev, 0); ++ } ++ ++ nv_encoder->crtc = NULL; ++ } ++} ++ ++static enum drm_connector_status ++nvd0_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) ++{ ++ enum drm_connector_status status = connector_status_disconnected; ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct drm_device *dev = encoder->dev; ++ int or = nv_encoder->or; ++ u32 load; ++ ++ nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00100000); ++ udelay(9500); ++ nv_wr32(dev, 0x61a00c + (or * 0x800), 0x80000000); ++ ++ load = nv_rd32(dev, 0x61a00c + (or * 0x800)); ++ if ((load & 0x38000000) == 0x38000000) ++ status = connector_status_connected; ++ ++ nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00000000); ++ return status; ++} ++ ++static void ++nvd0_dac_destroy(struct drm_encoder *encoder) ++{ ++ drm_encoder_cleanup(encoder); ++ kfree(encoder); ++} ++ ++static const struct drm_encoder_helper_funcs nvd0_dac_hfunc = { ++ .dpms = nvd0_dac_dpms, ++ .mode_fixup = nvd0_dac_mode_fixup, ++ .prepare = nvd0_dac_prepare, ++ .commit = nvd0_dac_commit, ++ .mode_set = nvd0_dac_mode_set, ++ .disable = nvd0_dac_disconnect, ++ .get_crtc = nvd0_display_crtc_get, ++ .detect = nvd0_dac_detect ++}; ++ ++static const struct drm_encoder_funcs nvd0_dac_func = { ++ .destroy = nvd0_dac_destroy, ++}; ++ ++static int ++nvd0_dac_create(struct drm_connector *connector, struct dcb_entry *dcbe) ++{ ++ struct drm_device *dev = connector->dev; ++ struct nouveau_encoder *nv_encoder; ++ struct drm_encoder *encoder; ++ ++ nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); ++ if (!nv_encoder) ++ return -ENOMEM; ++ nv_encoder->dcb = dcbe; ++ nv_encoder->or = ffs(dcbe->or) - 1; ++ ++ encoder = to_drm_encoder(nv_encoder); ++ encoder->possible_crtcs = dcbe->heads; ++ encoder->possible_clones = 0; ++ drm_encoder_init(dev, encoder, &nvd0_dac_func, DRM_MODE_ENCODER_DAC); ++ drm_encoder_helper_add(encoder, &nvd0_dac_hfunc); ++ ++ drm_mode_connector_attach_encoder(connector, encoder); ++ return 0; ++} ++ ++/****************************************************************************** ++ * SOR ++ *****************************************************************************/ ++static void ++nvd0_sor_dpms(struct drm_encoder *encoder, int mode) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct drm_device *dev = encoder->dev; ++ struct drm_encoder *partner; ++ int or = nv_encoder->or; ++ u32 dpms_ctrl; ++ ++ nv_encoder->last_dpms = mode; ++ ++ list_for_each_entry(partner, &dev->mode_config.encoder_list, head) { ++ struct nouveau_encoder *nv_partner = nouveau_encoder(partner); ++ ++ if (partner->encoder_type != DRM_MODE_ENCODER_TMDS) ++ continue; ++ ++ if (nv_partner != nv_encoder && ++ nv_partner->dcb->or == nv_encoder->or) { ++ if (nv_partner->last_dpms == DRM_MODE_DPMS_ON) ++ return; ++ break; ++ } ++ } ++ ++ dpms_ctrl = (mode == DRM_MODE_DPMS_ON); ++ dpms_ctrl |= 0x80000000; ++ ++ nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); ++ nv_mask(dev, 0x61c004 + (or * 0x0800), 0x80000001, dpms_ctrl); ++ nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); ++ nv_wait(dev, 0x61c030 + (or * 0x0800), 0x10000000, 0x00000000); ++} ++ ++static bool ++nvd0_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_connector *nv_connector; ++ ++ nv_connector = nouveau_encoder_connector_get(nv_encoder); ++ if (nv_connector && nv_connector->native_mode) { ++ if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) { ++ int id = adjusted_mode->base.id; ++ *adjusted_mode = *nv_connector->native_mode; ++ adjusted_mode->base.id = id; ++ } ++ } ++ ++ return true; ++} ++ ++static void ++nvd0_sor_prepare(struct drm_encoder *encoder) ++{ ++} ++ ++static void ++nvd0_sor_commit(struct drm_encoder *encoder) ++{ ++} ++ ++static void ++nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, ++ struct drm_display_mode *mode) ++{ ++ struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); ++ struct nouveau_connector *nv_connector; ++ struct nvbios *bios = &dev_priv->vbios; ++ u32 mode_ctrl = (1 << nv_crtc->index); ++ u32 *push, or_config; ++ ++ nv_connector = nouveau_encoder_connector_get(nv_encoder); ++ switch (nv_encoder->dcb->type) { ++ case OUTPUT_TMDS: ++ if (nv_encoder->dcb->sorconf.link & 1) { ++ if (mode->clock < 165000) ++ mode_ctrl |= 0x00000100; ++ else ++ mode_ctrl |= 0x00000500; ++ } else { ++ mode_ctrl |= 0x00000200; ++ } ++ ++ or_config = (mode_ctrl & 0x00000f00) >> 8; ++ if (mode->clock >= 165000) ++ or_config |= 0x0100; ++ break; ++ case OUTPUT_LVDS: ++ or_config = (mode_ctrl & 0x00000f00) >> 8; ++ if (bios->fp_no_ddc) { ++ if (bios->fp.dual_link) ++ or_config |= 0x0100; ++ if (bios->fp.if_is_24bit) ++ or_config |= 0x0200; ++ } else { ++ if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG) { ++ if (((u8 *)nv_connector->edid)[121] == 2) ++ or_config |= 0x0100; ++ } else ++ if (mode->clock >= bios->fp.duallink_transition_clk) { ++ or_config |= 0x0100; ++ } ++ ++ if (or_config & 0x0100) { ++ if (bios->fp.strapless_is_24bit & 2) ++ or_config |= 0x0200; ++ } else { ++ if (bios->fp.strapless_is_24bit & 1) ++ or_config |= 0x0200; ++ } ++ ++ if (nv_connector->base.display_info.bpc == 8) ++ or_config |= 0x0200; ++ ++ } ++ break; ++ default: ++ BUG_ON(1); ++ break; ++ } ++ ++ nvd0_sor_dpms(encoder, DRM_MODE_DPMS_ON); ++ ++ push = evo_wait(encoder->dev, 0, 4); ++ if (push) { ++ evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 2); ++ evo_data(push, mode_ctrl); ++ evo_data(push, or_config); ++ evo_kick(push, encoder->dev, 0); ++ } ++ ++ nv_encoder->crtc = encoder->crtc; ++} ++ ++static void ++nvd0_sor_disconnect(struct drm_encoder *encoder) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct drm_device *dev = encoder->dev; ++ u32 *push; ++ ++ if (nv_encoder->crtc) { ++ nvd0_crtc_prepare(nv_encoder->crtc); ++ ++ push = evo_wait(dev, 0, 4); ++ if (push) { ++ evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x0080, 1); ++ evo_data(push, 0x00000000); ++ evo_kick(push, dev, 0); ++ } ++ ++ nv_encoder->crtc = NULL; ++ nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; ++ } ++} ++ ++static void ++nvd0_sor_destroy(struct drm_encoder *encoder) ++{ ++ drm_encoder_cleanup(encoder); ++ kfree(encoder); ++} ++ ++static const struct drm_encoder_helper_funcs nvd0_sor_hfunc = { ++ .dpms = nvd0_sor_dpms, ++ .mode_fixup = nvd0_sor_mode_fixup, ++ .prepare = nvd0_sor_prepare, ++ .commit = nvd0_sor_commit, ++ .mode_set = nvd0_sor_mode_set, ++ .disable = nvd0_sor_disconnect, ++ .get_crtc = nvd0_display_crtc_get, ++}; ++ ++static const struct drm_encoder_funcs nvd0_sor_func = { ++ .destroy = nvd0_sor_destroy, ++}; ++ ++static int ++nvd0_sor_create(struct drm_connector *connector, struct dcb_entry *dcbe) ++{ ++ struct drm_device *dev = connector->dev; ++ struct nouveau_encoder *nv_encoder; ++ struct drm_encoder *encoder; ++ ++ nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); ++ if (!nv_encoder) ++ return -ENOMEM; ++ nv_encoder->dcb = dcbe; ++ nv_encoder->or = ffs(dcbe->or) - 1; ++ nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; ++ ++ encoder = to_drm_encoder(nv_encoder); ++ encoder->possible_crtcs = dcbe->heads; ++ encoder->possible_clones = 0; ++ drm_encoder_init(dev, encoder, &nvd0_sor_func, DRM_MODE_ENCODER_TMDS); ++ drm_encoder_helper_add(encoder, &nvd0_sor_hfunc); ++ ++ drm_mode_connector_attach_encoder(connector, encoder); ++ return 0; ++} ++ ++/****************************************************************************** ++ * IRQ ++ *****************************************************************************/ ++static struct dcb_entry * ++lookup_dcb(struct drm_device *dev, int id, u32 mc) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ int type, or, i; ++ ++ if (id < 4) { ++ type = OUTPUT_ANALOG; ++ or = id; ++ } else { ++ switch (mc & 0x00000f00) { ++ case 0x00000000: type = OUTPUT_LVDS; break; ++ case 0x00000100: type = OUTPUT_TMDS; break; ++ case 0x00000200: type = OUTPUT_TMDS; break; ++ case 0x00000500: type = OUTPUT_TMDS; break; ++ default: ++ NV_ERROR(dev, "PDISP: unknown SOR mc 0x%08x\n", mc); ++ return NULL; ++ } ++ ++ or = id - 4; ++ } ++ ++ for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { ++ struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i]; ++ if (dcb->type == type && (dcb->or & (1 << or))) ++ return dcb; ++ } ++ ++ NV_ERROR(dev, "PDISP: DCB for %d/0x%08x not found\n", id, mc); ++ return NULL; ++} ++ ++static void ++nvd0_display_unk1_handler(struct drm_device *dev, u32 crtc, u32 mask) ++{ ++ struct dcb_entry *dcb; ++ int i; ++ ++ for (i = 0; mask && i < 8; i++) { ++ u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20)); ++ if (!(mcc & (1 << crtc))) ++ continue; ++ ++ dcb = lookup_dcb(dev, i, mcc); ++ if (!dcb) ++ continue; ++ ++ nouveau_bios_run_display_table(dev, 0x0000, -1, dcb, crtc); ++ } ++ ++ nv_wr32(dev, 0x6101d4, 0x00000000); ++ nv_wr32(dev, 0x6109d4, 0x00000000); ++ nv_wr32(dev, 0x6101d0, 0x80000000); ++} ++ ++static void ++nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) ++{ ++ struct dcb_entry *dcb; ++ u32 or, tmp, pclk; ++ int i; ++ ++ for (i = 0; mask && i < 8; i++) { ++ u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20)); ++ if (!(mcc & (1 << crtc))) ++ continue; ++ ++ dcb = lookup_dcb(dev, i, mcc); ++ if (!dcb) ++ continue; ++ ++ nouveau_bios_run_display_table(dev, 0x0000, -2, dcb, crtc); ++ } ++ ++ pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000; ++ if (mask & 0x00010000) { ++ nv50_crtc_set_clock(dev, crtc, pclk); ++ } ++ ++ for (i = 0; mask && i < 8; i++) { ++ u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20)); ++ u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20)); ++ if (!(mcp & (1 << crtc))) ++ continue; ++ ++ dcb = lookup_dcb(dev, i, mcp); ++ if (!dcb) ++ continue; ++ or = ffs(dcb->or) - 1; ++ ++ nouveau_bios_run_display_table(dev, cfg, pclk, dcb, crtc); ++ ++ nv_wr32(dev, 0x612200 + (crtc * 0x800), 0x00000000); ++ switch (dcb->type) { ++ case OUTPUT_ANALOG: ++ nv_wr32(dev, 0x612280 + (or * 0x800), 0x00000000); ++ break; ++ case OUTPUT_TMDS: ++ case OUTPUT_LVDS: ++ if (cfg & 0x00000100) ++ tmp = 0x00000101; ++ else ++ tmp = 0x00000000; ++ ++ nv_mask(dev, 0x612300 + (or * 0x800), 0x00000707, tmp); ++ break; ++ default: ++ break; ++ } ++ ++ break; ++ } ++ ++ nv_wr32(dev, 0x6101d4, 0x00000000); ++ nv_wr32(dev, 0x6109d4, 0x00000000); ++ nv_wr32(dev, 0x6101d0, 0x80000000); ++} ++ ++static void ++nvd0_display_unk4_handler(struct drm_device *dev, u32 crtc, u32 mask) ++{ ++ struct dcb_entry *dcb; ++ int pclk, i; ++ ++ pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000; ++ ++ for (i = 0; mask && i < 8; i++) { ++ u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20)); ++ u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20)); ++ if (!(mcp & (1 << crtc))) ++ continue; ++ ++ dcb = lookup_dcb(dev, i, mcp); ++ if (!dcb) ++ continue; ++ ++ nouveau_bios_run_display_table(dev, cfg, -pclk, dcb, crtc); ++ } ++ ++ nv_wr32(dev, 0x6101d4, 0x00000000); ++ nv_wr32(dev, 0x6109d4, 0x00000000); ++ nv_wr32(dev, 0x6101d0, 0x80000000); ++} ++ ++static void ++nvd0_display_bh(unsigned long data) ++{ ++ struct drm_device *dev = (struct drm_device *)data; ++ struct nvd0_display *disp = nvd0_display(dev); ++ u32 mask, crtc; ++ int i; ++ ++ if (drm_debug & (DRM_UT_DRIVER | DRM_UT_KMS)) { ++ NV_INFO(dev, "PDISP: modeset req %d\n", disp->modeset); ++ NV_INFO(dev, " STAT: 0x%08x 0x%08x 0x%08x\n", ++ nv_rd32(dev, 0x6101d0), ++ nv_rd32(dev, 0x6101d4), nv_rd32(dev, 0x6109d4)); ++ for (i = 0; i < 8; i++) { ++ NV_INFO(dev, " %s%d: 0x%08x 0x%08x\n", ++ i < 4 ? "DAC" : "SOR", i, ++ nv_rd32(dev, 0x640180 + (i * 0x20)), ++ nv_rd32(dev, 0x660180 + (i * 0x20))); ++ } ++ } ++ ++ mask = nv_rd32(dev, 0x6101d4); ++ crtc = 0; ++ if (!mask) { ++ mask = nv_rd32(dev, 0x6109d4); ++ crtc = 1; ++ } ++ ++ if (disp->modeset & 0x00000001) ++ nvd0_display_unk1_handler(dev, crtc, mask); ++ if (disp->modeset & 0x00000002) ++ nvd0_display_unk2_handler(dev, crtc, mask); ++ if (disp->modeset & 0x00000004) ++ nvd0_display_unk4_handler(dev, crtc, mask); ++} ++ ++static void ++nvd0_display_intr(struct drm_device *dev) ++{ ++ struct nvd0_display *disp = nvd0_display(dev); ++ u32 intr = nv_rd32(dev, 0x610088); ++ ++ if (intr & 0x00000002) { ++ u32 stat = nv_rd32(dev, 0x61009c); ++ int chid = ffs(stat) - 1; ++ if (chid >= 0) { ++ u32 mthd = nv_rd32(dev, 0x6101f0 + (chid * 12)); ++ u32 data = nv_rd32(dev, 0x6101f4 + (chid * 12)); ++ u32 unkn = nv_rd32(dev, 0x6101f8 + (chid * 12)); ++ ++ NV_INFO(dev, "EvoCh: chid %d mthd 0x%04x data 0x%08x " ++ "0x%08x 0x%08x\n", ++ chid, (mthd & 0x0000ffc), data, mthd, unkn); ++ nv_wr32(dev, 0x61009c, (1 << chid)); ++ nv_wr32(dev, 0x6101f0 + (chid * 12), 0x90000000); ++ } ++ ++ intr &= ~0x00000002; ++ } ++ ++ if (intr & 0x00100000) { ++ u32 stat = nv_rd32(dev, 0x6100ac); ++ ++ if (stat & 0x00000007) { ++ disp->modeset = stat; ++ tasklet_schedule(&disp->tasklet); ++ ++ nv_wr32(dev, 0x6100ac, (stat & 0x00000007)); ++ stat &= ~0x00000007; ++ } ++ ++ if (stat) { ++ NV_INFO(dev, "PDISP: unknown intr24 0x%08x\n", stat); ++ nv_wr32(dev, 0x6100ac, stat); ++ } ++ ++ intr &= ~0x00100000; ++ } ++ ++ if (intr & 0x01000000) { ++ u32 stat = nv_rd32(dev, 0x6100bc); ++ nv_wr32(dev, 0x6100bc, stat); ++ intr &= ~0x01000000; ++ } ++ ++ if (intr & 0x02000000) { ++ u32 stat = nv_rd32(dev, 0x6108bc); ++ nv_wr32(dev, 0x6108bc, stat); ++ intr &= ~0x02000000; ++ } ++ ++ if (intr) ++ NV_INFO(dev, "PDISP: unknown intr 0x%08x\n", intr); ++} ++ ++/****************************************************************************** ++ * Init ++ *****************************************************************************/ ++static void ++nvd0_display_fini(struct drm_device *dev) ++{ ++ int i; ++ ++ /* fini cursors */ ++ for (i = 14; i >= 13; i--) { ++ if (!(nv_rd32(dev, 0x610490 + (i * 0x10)) & 0x00000001)) ++ continue; ++ ++ nv_mask(dev, 0x610490 + (i * 0x10), 0x00000001, 0x00000000); ++ nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00000000); ++ nv_mask(dev, 0x610090, 1 << i, 0x00000000); ++ nv_mask(dev, 0x6100a0, 1 << i, 0x00000000); ++ } ++ ++ /* fini master */ ++ if (nv_rd32(dev, 0x610490) & 0x00000010) { ++ nv_mask(dev, 0x610490, 0x00000010, 0x00000000); ++ nv_mask(dev, 0x610490, 0x00000003, 0x00000000); ++ nv_wait(dev, 0x610490, 0x80000000, 0x00000000); ++ nv_mask(dev, 0x610090, 0x00000001, 0x00000000); ++ nv_mask(dev, 0x6100a0, 0x00000001, 0x00000000); ++ } ++} ++ ++int ++nvd0_display_init(struct drm_device *dev) ++{ ++ struct nvd0_display *disp = nvd0_display(dev); ++ u32 *push; ++ int i; ++ ++ if (nv_rd32(dev, 0x6100ac) & 0x00000100) { ++ nv_wr32(dev, 0x6100ac, 0x00000100); ++ nv_mask(dev, 0x6194e8, 0x00000001, 0x00000000); ++ if (!nv_wait(dev, 0x6194e8, 0x00000002, 0x00000000)) { ++ NV_ERROR(dev, "PDISP: 0x6194e8 0x%08x\n", ++ nv_rd32(dev, 0x6194e8)); ++ return -EBUSY; ++ } ++ } ++ ++ /* nfi what these are exactly, i do know that SOR_MODE_CTRL won't ++ * work at all unless you do the SOR part below. ++ */ ++ for (i = 0; i < 3; i++) { ++ u32 dac = nv_rd32(dev, 0x61a000 + (i * 0x800)); ++ nv_wr32(dev, 0x6101c0 + (i * 0x800), dac); ++ } ++ ++ for (i = 0; i < 4; i++) { ++ u32 sor = nv_rd32(dev, 0x61c000 + (i * 0x800)); ++ nv_wr32(dev, 0x6301c4 + (i * 0x800), sor); ++ } ++ ++ for (i = 0; i < 2; i++) { ++ u32 crtc0 = nv_rd32(dev, 0x616104 + (i * 0x800)); ++ u32 crtc1 = nv_rd32(dev, 0x616108 + (i * 0x800)); ++ u32 crtc2 = nv_rd32(dev, 0x61610c + (i * 0x800)); ++ nv_wr32(dev, 0x6101b4 + (i * 0x800), crtc0); ++ nv_wr32(dev, 0x6101b8 + (i * 0x800), crtc1); ++ nv_wr32(dev, 0x6101bc + (i * 0x800), crtc2); ++ } ++ ++ /* point at our hash table / objects, enable interrupts */ ++ nv_wr32(dev, 0x610010, (disp->mem->vinst >> 8) | 9); ++ nv_mask(dev, 0x6100b0, 0x00000307, 0x00000307); ++ ++ /* init master */ ++ nv_wr32(dev, 0x610494, (disp->evo[0].handle >> 8) | 3); ++ nv_wr32(dev, 0x610498, 0x00010000); ++ nv_wr32(dev, 0x61049c, 0x00000001); ++ nv_mask(dev, 0x610490, 0x00000010, 0x00000010); ++ nv_wr32(dev, 0x640000, 0x00000000); ++ nv_wr32(dev, 0x610490, 0x01000013); ++ if (!nv_wait(dev, 0x610490, 0x80000000, 0x00000000)) { ++ NV_ERROR(dev, "PDISP: master 0x%08x\n", ++ nv_rd32(dev, 0x610490)); ++ return -EBUSY; ++ } ++ nv_mask(dev, 0x610090, 0x00000001, 0x00000001); ++ nv_mask(dev, 0x6100a0, 0x00000001, 0x00000001); ++ ++ /* init cursors */ ++ for (i = 13; i <= 14; i++) { ++ nv_wr32(dev, 0x610490 + (i * 0x10), 0x00000001); ++ if (!nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00010000)) { ++ NV_ERROR(dev, "PDISP: curs%d 0x%08x\n", i, ++ nv_rd32(dev, 0x610490 + (i * 0x10))); ++ return -EBUSY; ++ } ++ ++ nv_mask(dev, 0x610090, 1 << i, 1 << i); ++ nv_mask(dev, 0x6100a0, 1 << i, 1 << i); ++ } ++ ++ push = evo_wait(dev, 0, 32); ++ if (!push) ++ return -EBUSY; ++ evo_mthd(push, 0x0088, 1); ++ evo_data(push, NvEvoSync); ++ evo_mthd(push, 0x0084, 1); ++ evo_data(push, 0x00000000); ++ evo_mthd(push, 0x0084, 1); ++ evo_data(push, 0x80000000); ++ evo_mthd(push, 0x008c, 1); ++ evo_data(push, 0x00000000); ++ evo_kick(push, dev, 0); ++ ++ return 0; ++} ++ ++void ++nvd0_display_destroy(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nvd0_display *disp = nvd0_display(dev); ++ struct pci_dev *pdev = dev->pdev; ++ ++ nvd0_display_fini(dev); ++ ++ pci_free_consistent(pdev, PAGE_SIZE, disp->evo[0].ptr, disp->evo[0].handle); ++ nouveau_gpuobj_ref(NULL, &disp->mem); ++ nouveau_irq_unregister(dev, 26); ++ ++ dev_priv->engine.display.priv = NULL; ++ kfree(disp); ++} ++ ++int ++nvd0_display_create(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; ++ struct dcb_table *dcb = &dev_priv->vbios.dcb; ++ struct drm_connector *connector, *tmp; ++ struct pci_dev *pdev = dev->pdev; ++ struct nvd0_display *disp; ++ struct dcb_entry *dcbe; ++ int ret, i; ++ ++ disp = kzalloc(sizeof(*disp), GFP_KERNEL); ++ if (!disp) ++ return -ENOMEM; ++ dev_priv->engine.display.priv = disp; ++ ++ /* create crtc objects to represent the hw heads */ ++ for (i = 0; i < 2; i++) { ++ ret = nvd0_crtc_create(dev, i); ++ if (ret) ++ goto out; ++ } ++ ++ /* create encoder/connector objects based on VBIOS DCB table */ ++ for (i = 0, dcbe = &dcb->entry[0]; i < dcb->entries; i++, dcbe++) { ++ connector = nouveau_connector_create(dev, dcbe->connector); ++ if (IS_ERR(connector)) ++ continue; ++ ++ if (dcbe->location != DCB_LOC_ON_CHIP) { ++ NV_WARN(dev, "skipping off-chip encoder %d/%d\n", ++ dcbe->type, ffs(dcbe->or) - 1); ++ continue; ++ } ++ ++ switch (dcbe->type) { ++ case OUTPUT_TMDS: ++ case OUTPUT_LVDS: ++ nvd0_sor_create(connector, dcbe); ++ break; ++ case OUTPUT_ANALOG: ++ nvd0_dac_create(connector, dcbe); ++ break; ++ default: ++ NV_WARN(dev, "skipping unsupported encoder %d/%d\n", ++ dcbe->type, ffs(dcbe->or) - 1); ++ continue; ++ } ++ } ++ ++ /* cull any connectors we created that don't have an encoder */ ++ list_for_each_entry_safe(connector, tmp, &dev->mode_config.connector_list, head) { ++ if (connector->encoder_ids[0]) ++ continue; ++ ++ NV_WARN(dev, "%s has no encoders, removing\n", ++ drm_get_connector_name(connector)); ++ connector->funcs->destroy(connector); ++ } ++ ++ /* setup interrupt handling */ ++ tasklet_init(&disp->tasklet, nvd0_display_bh, (unsigned long)dev); ++ nouveau_irq_register(dev, 26, nvd0_display_intr); ++ ++ /* hash table and dma objects for the memory areas we care about */ ++ ret = nouveau_gpuobj_new(dev, NULL, 0x4000, 0x10000, ++ NVOBJ_FLAG_ZERO_ALLOC, &disp->mem); ++ if (ret) ++ goto out; ++ ++ nv_wo32(disp->mem, 0x1000, 0x00000049); ++ nv_wo32(disp->mem, 0x1004, (disp->mem->vinst + 0x2000) >> 8); ++ nv_wo32(disp->mem, 0x1008, (disp->mem->vinst + 0x2fff) >> 8); ++ nv_wo32(disp->mem, 0x100c, 0x00000000); ++ nv_wo32(disp->mem, 0x1010, 0x00000000); ++ nv_wo32(disp->mem, 0x1014, 0x00000000); ++ nv_wo32(disp->mem, 0x0000, NvEvoSync); ++ nv_wo32(disp->mem, 0x0004, (0x1000 << 9) | 0x00000001); ++ ++ nv_wo32(disp->mem, 0x1020, 0x00000049); ++ nv_wo32(disp->mem, 0x1024, 0x00000000); ++ nv_wo32(disp->mem, 0x1028, (dev_priv->vram_size - 1) >> 8); ++ nv_wo32(disp->mem, 0x102c, 0x00000000); ++ nv_wo32(disp->mem, 0x1030, 0x00000000); ++ nv_wo32(disp->mem, 0x1034, 0x00000000); ++ nv_wo32(disp->mem, 0x0008, NvEvoVRAM); ++ nv_wo32(disp->mem, 0x000c, (0x1020 << 9) | 0x00000001); ++ ++ nv_wo32(disp->mem, 0x1040, 0x00000009); ++ nv_wo32(disp->mem, 0x1044, 0x00000000); ++ nv_wo32(disp->mem, 0x1048, (dev_priv->vram_size - 1) >> 8); ++ nv_wo32(disp->mem, 0x104c, 0x00000000); ++ nv_wo32(disp->mem, 0x1050, 0x00000000); ++ nv_wo32(disp->mem, 0x1054, 0x00000000); ++ nv_wo32(disp->mem, 0x0010, NvEvoVRAM_LP); ++ nv_wo32(disp->mem, 0x0014, (0x1040 << 9) | 0x00000001); ++ ++ nv_wo32(disp->mem, 0x1060, 0x0fe00009); ++ nv_wo32(disp->mem, 0x1064, 0x00000000); ++ nv_wo32(disp->mem, 0x1068, (dev_priv->vram_size - 1) >> 8); ++ nv_wo32(disp->mem, 0x106c, 0x00000000); ++ nv_wo32(disp->mem, 0x1070, 0x00000000); ++ nv_wo32(disp->mem, 0x1074, 0x00000000); ++ nv_wo32(disp->mem, 0x0018, NvEvoFB32); ++ nv_wo32(disp->mem, 0x001c, (0x1060 << 9) | 0x00000001); ++ ++ pinstmem->flush(dev); ++ ++ /* push buffers for evo channels */ ++ disp->evo[0].ptr = ++ pci_alloc_consistent(pdev, PAGE_SIZE, &disp->evo[0].handle); ++ if (!disp->evo[0].ptr) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ ret = nvd0_display_init(dev); ++ if (ret) ++ goto out; ++ ++out: ++ if (ret) ++ nvd0_display_destroy(dev); ++ return ret; ++} diff --git a/kernel.spec b/kernel.spec index 8538a2437..c01123810 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2077,6 +2077,9 @@ fi # and build. %changelog +* Tue Sep 20 2011 Ben Skeggs 3.1.0-0.rc6.git0.4.fc16 +- nouveau: patch in updates queued for 3.2, mostly new hw support (GF116/GF119) + * Fri Sep 16 2011 Josh Boyer 3.1.0-0.rc6.git0.3.fc16 - Add patch to fix deadlock in ipw2x00 (rhbz 738387) - Fixup kernel-tools file section for ppc/ppc64 From 1340c63c42c1dc3b9054263e8d742239995ade96 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Tue, 20 Sep 2011 10:56:56 +0100 Subject: [PATCH 082/487] Fix MacBookAir4,1 keymap, see http://thread.gmane.org/gmane.linux.kernel.input/21462/focus=21626 --- add-macbookair41-keyboard.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/add-macbookair41-keyboard.patch b/add-macbookair41-keyboard.patch index cb8c71d9e..bd5afdafe 100644 --- a/add-macbookair41-keyboard.patch +++ b/add-macbookair41-keyboard.patch @@ -59,7 +59,7 @@ diff -uNr linux/drivers/hid/hid-apple.c patched/drivers/hid/hid-apple.c table = macbookair_fn_keys; + else if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI && + hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) -+ table = macbookair_fn_keys; ++ table = apple_fn_keys; else if (hid->product < 0x21d || hid->product >= 0x300) table = powerbook_fn_keys; else From 36cbf57390d048256e18a1941c3b2a2ca79a395b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 20 Sep 2011 17:10:32 -0400 Subject: [PATCH 083/487] Limit 32-bit x86 kernels to 32 processors. --- config-x86-32-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-x86-32-generic b/config-x86-32-generic index f42d60da6..caeae9398 100644 --- a/config-x86-32-generic +++ b/config-x86-32-generic @@ -28,7 +28,7 @@ CONFIG_M686=y # CONFIG_MCYRIXIII is not set # CONFIG_MVIAC3_2 is not set -CONFIG_NR_CPUS=64 +CONFIG_NR_CPUS=32 CONFIG_X86_GENERIC=y # CONFIG_X86_PPRO_FENCE is not set diff --git a/kernel.spec b/kernel.spec index c01123810..f7582ee13 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2077,6 +2077,9 @@ fi # and build. %changelog +* Tue Sep 20 2011 Dave Jones +- Limit 32-bit x86 kernels to 32 processors. + * Tue Sep 20 2011 Ben Skeggs 3.1.0-0.rc6.git0.4.fc16 - nouveau: patch in updates queued for 3.2, mostly new hw support (GF116/GF119) From 5ec1187f2a3079f6096c90e3173a0d739c7113cc Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 20 Sep 2011 17:05:31 -0400 Subject: [PATCH 084/487] Bump NR_CPUS to 1024 on ppc64 --- config-powerpc64 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-powerpc64 b/config-powerpc64 index 2bee4edbf..7142d8007 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -95,7 +95,7 @@ CONFIG_APM_EMULATION=m CONFIG_PPC64=y CONFIG_VIRT_CPU_ACCOUNTING=y -CONFIG_NR_CPUS=128 +CONFIG_NR_CPUS=1024 # CONFIG_FB_PLATINUM is not set # CONFIG_FB_VALKYRIE is not set # CONFIG_FB_CT65550 is not set From 804ae40f5c129ef9e9da89607eb9f3879a340b6f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 21 Sep 2011 21:42:15 -0400 Subject: [PATCH 085/487] Linux 3.1-rc7 --- add-macbookair41-btusb.patch | 67 ------ add-macbookair41-trackpad.patch | 100 -------- ...le-memory-corruption-in-CIFSFindNext.patch | 82 ------- ...-Checksum-offload-is-always-disabled.patch | 70 ------ ibmveth-Fix-DMA-unmap-error.patch | 78 ------ ...h-Fix-issue-with-DMA-mapping-failure.patch | 93 -------- ipw2x00-fix-rtnl-mutex-deadlock.patch | 224 ------------------ iwlagn-revert-max-aggregate-size.patch | 13 - kernel.spec | 31 +-- sources | 2 +- 10 files changed, 6 insertions(+), 754 deletions(-) delete mode 100644 add-macbookair41-btusb.patch delete mode 100644 add-macbookair41-trackpad.patch delete mode 100644 cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch delete mode 100644 ibmveth-Checksum-offload-is-always-disabled.patch delete mode 100644 ibmveth-Fix-DMA-unmap-error.patch delete mode 100644 ibmveth-Fix-issue-with-DMA-mapping-failure.patch delete mode 100644 ipw2x00-fix-rtnl-mutex-deadlock.patch delete mode 100644 iwlagn-revert-max-aggregate-size.patch diff --git a/add-macbookair41-btusb.patch b/add-macbookair41-btusb.patch deleted file mode 100644 index 8997cede8..000000000 --- a/add-macbookair41-btusb.patch +++ /dev/null @@ -1,67 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Pieter-Augustijn Van Malleghem -Newsgroups: gmane.linux.bluez.kernel -Subject: [PATCH] Add MacBookAir4,1 support -Date: Wed, 7 Sep 2011 02:28:10 -0400 -Lines: 18 -Approved: news@gmane.org -Message-ID: <20110907062810.GA4755@Caligula> -NNTP-Posting-Host: lo.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Trace: dough.gmane.org 1315376918 16651 80.91.229.12 (7 Sep 2011 06:28:38 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Wed, 7 Sep 2011 06:28:38 +0000 (UTC) -To: linux-bluetooth-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Original-X-From: linux-bluetooth-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Wed Sep 07 08:28:35 2011 -Return-path: -Envelope-to: glbk-linux-bluetooth-1dZseelyfdZg9hUCZPvPmw@public.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1R1Bce-00013w-IP - for glbk-linux-bluetooth-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Wed, 07 Sep 2011 08:28:32 +0200 -Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand - id S1755760Ab1IGG22 (ORCPT - ); - Wed, 7 Sep 2011 02:28:28 -0400 -Original-Received: from mail-qy0-f174.google.com ([209.85.216.174]:48109 "EHLO - mail-qy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1756054Ab1IGG2V (ORCPT - ); - Wed, 7 Sep 2011 02:28:21 -0400 -Original-Received: by qyk7 with SMTP id 7so455185qyk.19 - for ; Tue, 06 Sep 2011 23:28:20 -0700 (PDT) -Original-Received: by 10.224.192.6 with SMTP id do6mr4345154qab.189.1315376900296; - Tue, 06 Sep 2011 23:28:20 -0700 (PDT) -Original-Received: from Caligula ([140.247.187.88]) - by mx.google.com with ESMTPS id dr7sm2176040qab.26.2011.09.06.23.28.19 - (version=TLSv1/SSLv3 cipher=OTHER); - Tue, 06 Sep 2011 23:28:19 -0700 (PDT) -Content-Disposition: inline -User-Agent: Mutt/1.5.21 (2010-09-15) -Original-Sender: linux-bluetooth-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-bluetooth-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Xref: news.gmane.org gmane.linux.bluez.kernel:16281 -Archived-At: - -This patch against current git adds the hardware ID for the Apple -MacBookAir4,1, released in July 2011. The device features a BCM2046 -USB chip. The patch was inspired by the previous modifications adding -support for the MacBookAir3,x. - -Signed-off-by: Pieter-Augustijn Van Malleghem ---- linux/drivers/bluetooth/btusb.c 2011-09-06 23:41:57.000000000 -0400 -+++ patched/drivers/bluetooth/btusb.c 2011-09-06 23:50:27.000000000 -0400 -@@ -72,6 +72,9 @@ - /* Apple MacBookAir3,1, MacBookAir3,2 */ - { USB_DEVICE(0x05ac, 0x821b) }, - -+ /* Apple MacBookAir4,1 */ -+ { USB_DEVICE(0x05ac, 0x821f) }, -+ - /* Apple MacBookPro8,2 */ - { USB_DEVICE(0x05ac, 0x821a) }, - diff --git a/add-macbookair41-trackpad.patch b/add-macbookair41-trackpad.patch deleted file mode 100644 index ec6890e5e..000000000 --- a/add-macbookair41-trackpad.patch +++ /dev/null @@ -1,100 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Pieter-Augustijn Van Malleghem -Newsgroups: gmane.linux.kernel.input -Subject: [PATCH] Add MacBookAir4,1 trackpad support -Date: Wed, 7 Sep 2011 16:16:39 -0400 -Lines: 53 -Approved: news@gmane.org -Message-ID: <20110907201639.GA2004@Caligula> -NNTP-Posting-Host: lo.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Trace: dough.gmane.org 1315427050 14847 80.91.229.12 (7 Sep 2011 20:24:10 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Wed, 7 Sep 2011 20:24:10 +0000 (UTC) -To: linux-input@vger.kernel.org -Original-X-From: linux-input-owner@vger.kernel.org Wed Sep 07 22:24:06 2011 -Return-path: -Envelope-to: glki-linux-input-2@lo.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1R1OfE-0003bX-Dq - for glki-linux-input-2@lo.gmane.org; Wed, 07 Sep 2011 22:24:04 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1756616Ab1IGUYD (ORCPT ); - Wed, 7 Sep 2011 16:24:03 -0400 -Original-Received: from mail-vx0-f174.google.com ([209.85.220.174]:45534 "EHLO - mail-vx0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1755813Ab1IGUYB (ORCPT - ); Wed, 7 Sep 2011 16:24:01 -0400 -Original-Received: by vxj15 with SMTP id 15so37615vxj.19 - for ; Wed, 07 Sep 2011 13:24:01 -0700 (PDT) -Original-Received: by 10.52.173.49 with SMTP id bh17mr2675458vdc.82.1315426608488; - Wed, 07 Sep 2011 13:16:48 -0700 (PDT) -Original-Received: from Caligula ([140.247.246.50]) - by mx.google.com with ESMTPS id da15sm937150vdb.26.2011.09.07.13.16.47 - (version=TLSv1/SSLv3 cipher=OTHER); - Wed, 07 Sep 2011 13:16:47 -0700 (PDT) -Content-Disposition: inline -User-Agent: Mutt/1.5.21 (2010-09-15) -Original-Sender: linux-input-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-input@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel.input:21463 -Archived-At: - -This patch adds trackpad support for the MacBookAir4,1, released in July 2011. -It is very similar to the MacBookAir4,2 patch submitted by Joshua Dillon and -Chase Douglas. - -Signed-off-by: Pieter-Augustijn Van Malleghem ---- linux/drivers/input/mouse/bcm5974.c 2011-09-06 23:41:58.000000000 -0400 -+++ patched/drivers/input/mouse/bcm5974.c 2011-09-07 00:02:44.000000000 -0400 -@@ -67,6 +67,10 @@ - #define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 - #define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 - #define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 -+/* MacbookAir4,1 (unibody, July 2011) */ -+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249 -+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a -+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b - /* MacbookAir4,2 (unibody, July 2011) */ - #define USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI 0x024c - #define USB_DEVICE_ID_APPLE_WELLSPRING6_ISO 0x024d -@@ -112,6 +116,10 @@ - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ISO), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), -+ /* MacbookAir4,1 */ -+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI), -+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO), -+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS), - /* MacbookAir4,2 */ - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING6_ISO), -@@ -334,6 +342,18 @@ - { DIM_X, DIM_X / SN_COORD, -4750, 5280 }, - { DIM_Y, DIM_Y / SN_COORD, -150, 6730 } - }, -+ { -+ USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI, -+ USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO, -+ USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS, -+ HAS_INTEGRATED_BUTTON, -+ 0x84, sizeof(struct bt_data), -+ 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, -+ { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, -+ { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, -+ { DIM_X, DIM_X / SN_COORD, -4620, 5140 }, -+ { DIM_Y, DIM_Y / SN_COORD, -150, 6600 } -+ }, - {} - }; - --- -To unsubscribe from this list: send the line "unsubscribe linux-input" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - diff --git a/cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch b/cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch deleted file mode 100644 index 06fc5c74a..000000000 --- a/cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch +++ /dev/null @@ -1,82 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Jeff Layton -Newsgroups: gmane.linux.kernel.cifs -Subject: [PATCH] cifs: fix possible memory corruption in CIFSFindNext -Date: Tue, 23 Aug 2011 07:21:28 -0400 -Lines: 37 -Approved: news@gmane.org -Message-ID: <1314098488-1547-1-git-send-email-jlayton@redhat.com> -NNTP-Posting-Host: lo.gmane.org -X-Trace: dough.gmane.org 1314098501 27164 80.91.229.12 (23 Aug 2011 11:21:41 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Tue, 23 Aug 2011 11:21:41 +0000 (UTC) -Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, dcl-HN4QTLPn1qTvY7RNz7mR4EEOCMrvLtNR@public.gmane.org -To: smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org -Original-X-From: linux-cifs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Tue Aug 23 13:21:37 2011 -Return-path: -Envelope-to: glkc-linux-cifs-1dZseelyfdZg9hUCZPvPmw@public.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1Qvp33-0003JC-05 - for glkc-linux-cifs-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Tue, 23 Aug 2011 13:21:37 +0200 -Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand - id S1752435Ab1HWLVg (ORCPT ); - Tue, 23 Aug 2011 07:21:36 -0400 -Original-Received: from mail-gy0-f174.google.com ([209.85.160.174]:43114 "EHLO - mail-gy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1751065Ab1HWLVf (ORCPT - ); Tue, 23 Aug 2011 07:21:35 -0400 -Original-Received: by gya6 with SMTP id 6so4228912gya.19 - for ; Tue, 23 Aug 2011 04:21:35 -0700 (PDT) -Original-Received: by 10.101.144.18 with SMTP id w18mr3505731ann.133.1314098494691; - Tue, 23 Aug 2011 04:21:34 -0700 (PDT) -Original-Received: from salusa.poochiereds.net (cpe-075-177-182-191.nc.res.rr.com [75.177.182.191]) - by mx.google.com with ESMTPS id d33sm48355ano.35.2011.08.23.04.21.32 - (version=SSLv3 cipher=OTHER); - Tue, 23 Aug 2011 04:21:33 -0700 (PDT) -X-Mailer: git-send-email 1.7.6 -Original-Sender: linux-cifs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Xref: news.gmane.org gmane.linux.kernel.cifs:4006 -Archived-At: - -The name_len variable in CIFSFindNext is a signed int that gets set to -the resume_name_len in the cifs_search_info. The resume_name_len however -is unsigned and for some infolevels is populated directly from a 32 bit -value sent by the server. - -If the server sends a very large value for this, then that value could -look negative when converted to a signed int. That would make that -value pass the PATH_MAX check later in CIFSFindNext. The name_len would -then be used as a length value for a memcpy. It would then be treated -as unsigned again, and the memcpy scribbles over a ton of memory. - -Fix this by making the name_len an unsigned value in CIFSFindNext. - -Cc: -Reported-by: Darren Lavender -Signed-off-by: Jeff Layton ---- - fs/cifs/cifssmb.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c -index f4d0988..950464d 100644 ---- a/fs/cifs/cifssmb.c -+++ b/fs/cifs/cifssmb.c -@@ -4089,7 +4089,8 @@ int CIFSFindNext(const int xid, struct cifs_tcon *tcon, - T2_FNEXT_RSP_PARMS *parms; - char *response_data; - int rc = 0; -- int bytes_returned, name_len; -+ int bytes_returned; -+ unsigned int name_len; - __u16 params, byte_count; - - cFYI(1, "In FindNext"); --- -1.7.6 - diff --git a/ibmveth-Checksum-offload-is-always-disabled.patch b/ibmveth-Checksum-offload-is-always-disabled.patch deleted file mode 100644 index 9daee4113..000000000 --- a/ibmveth-Checksum-offload-is-always-disabled.patch +++ /dev/null @@ -1,70 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Anton Blanchard -Newsgroups: gmane.linux.network -Subject: [PATCH 3/4] ibmveth: Checksum offload is always disabled -Date: Thu, 08 Sep 2011 10:41:05 +1000 -Lines: 23 -Approved: news@gmane.org -Message-ID: <20110908004121.744925909@samba.org> -References: <20110908004102.355674129@samba.org> -NNTP-Posting-Host: lo.gmane.org -X-Trace: dough.gmane.org 1315442745 17939 80.91.229.12 (8 Sep 2011 00:45:45 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Thu, 8 Sep 2011 00:45:45 +0000 (UTC) -Cc: netdev@vger.kernel.org -To: Santiago Leon , - brking@linux.vnet.ibm.com, rcj@linux.vnet.ibm.com, - mirq-linux@rere.qmqm.pl -Original-X-From: netdev-owner@vger.kernel.org Thu Sep 08 02:45:39 2011 -Return-path: -Envelope-to: linux-netdev-2@lo.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1R1SkN-0001Tk-2c - for linux-netdev-2@lo.gmane.org; Thu, 08 Sep 2011 02:45:39 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1757675Ab1IHApb (ORCPT ); - Wed, 7 Sep 2011 20:45:31 -0400 -Original-Received: from ozlabs.org ([203.10.76.45]:45063 "EHLO ozlabs.org" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1757657Ab1IHAp1 (ORCPT ); - Wed, 7 Sep 2011 20:45:27 -0400 -Original-Received: from localhost (ppp121-44-79-234.lns20.syd6.internode.on.net [121.44.79.234]) - (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits)) - (Client did not present a certificate) - by ozlabs.org (Postfix) with ESMTPSA id 17FFBB6F98; - Thu, 8 Sep 2011 10:45:26 +1000 (EST) -X-Mailbox-Line: From anton@samba.org Thu Sep 8 10:41:21 2011 -User-Agent: quilt/0.48-1 -Content-Disposition: inline; filename=ibmveth_fix_csum.patch -Original-Sender: netdev-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org -Xref: news.gmane.org gmane.linux.network:205929 -Archived-At: - -Commit b9367bf3ee6d (net: ibmveth: convert to hw_features) reversed -a check in ibmveth_set_csum_offload that results in checksum offload -never being enabled. - -Signed-off-by: Anton Blanchard -Cc: # 3.0+ ---- - -Index: linux-build/drivers/net/ibmveth.c -=================================================================== ---- linux-build.orig/drivers/net/ibmveth.c 2011-09-01 16:02:12.198726425 +1000 -+++ linux-build/drivers/net/ibmveth.c 2011-09-01 16:05:37.282482851 +1000 -@@ -812,7 +812,7 @@ static int ibmveth_set_csum_offload(stru - } else - adapter->fw_ipv6_csum_support = data; - -- if (ret != H_SUCCESS || ret6 != H_SUCCESS) -+ if (ret == H_SUCCESS || ret6 == H_SUCCESS) - adapter->rx_csum = data; - else - rc1 = -EIO; - - diff --git a/ibmveth-Fix-DMA-unmap-error.patch b/ibmveth-Fix-DMA-unmap-error.patch deleted file mode 100644 index b619a1677..000000000 --- a/ibmveth-Fix-DMA-unmap-error.patch +++ /dev/null @@ -1,78 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Anton Blanchard -Newsgroups: gmane.linux.network -Subject: [PATCH 1/4] ibmveth: Fix DMA unmap error -Date: Thu, 08 Sep 2011 10:41:03 +1000 -Lines: 32 -Approved: news@gmane.org -Message-ID: <20110908004121.570234962@samba.org> -References: <20110908004102.355674129@samba.org> -NNTP-Posting-Host: lo.gmane.org -X-Trace: dough.gmane.org 1315442763 18071 80.91.229.12 (8 Sep 2011 00:46:03 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Thu, 8 Sep 2011 00:46:03 +0000 (UTC) -Cc: netdev@vger.kernel.org -To: Santiago Leon , - brking@linux.vnet.ibm.com, rcj@linux.vnet.ibm.com -Original-X-From: netdev-owner@vger.kernel.org Thu Sep 08 02:45:56 2011 -Return-path: -Envelope-to: linux-netdev-2@lo.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1R1Ska-0001cA-40 - for linux-netdev-2@lo.gmane.org; Thu, 08 Sep 2011 02:45:52 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1757671Ab1IHAp3 (ORCPT ); - Wed, 7 Sep 2011 20:45:29 -0400 -Original-Received: from ozlabs.org ([203.10.76.45]:42999 "EHLO ozlabs.org" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1757658Ab1IHAp1 (ORCPT ); - Wed, 7 Sep 2011 20:45:27 -0400 -Original-Received: from localhost (ppp121-44-79-234.lns20.syd6.internode.on.net [121.44.79.234]) - (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits)) - (Client did not present a certificate) - by ozlabs.org (Postfix) with ESMTPSA id ACF33B6F8E; - Thu, 8 Sep 2011 10:45:24 +1000 (EST) -X-Mailbox-Line: From anton@samba.org Thu Sep 8 10:41:21 2011 -User-Agent: quilt/0.48-1 -Content-Disposition: inline; filename=ibmveth_1.patch -Original-Sender: netdev-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org -Xref: news.gmane.org gmane.linux.network:205933 -Archived-At: - -From: Brian King - -Commit 6e8ab30ec677 (ibmveth: Add scatter-gather support) introduced a -DMA mapping API inconsistency resulting in dma_unmap_page getting -called on memory mapped via dma_map_single. This was seen when -CONFIG_DMA_API_DEBUG was enabled. Fix up this API usage inconsistency. - -Signed-off-by: Brian King -Acked-by: Anton Blanchard -Cc: # v2.6.37+ ---- - -Index: linux-build/drivers/net/ibmveth.c -=================================================================== ---- linux-build.orig/drivers/net/ibmveth.c 2011-09-08 08:00:16.842856634 +1000 -+++ linux-build/drivers/net/ibmveth.c 2011-09-08 09:45:43.163851274 +1000 -@@ -1026,7 +1026,12 @@ retry_bounce: - netdev->stats.tx_bytes += skb->len; - } - -- for (i = 0; i < skb_shinfo(skb)->nr_frags + 1; i++) -+ dma_unmap_single(&adapter->vdev->dev, -+ descs[0].fields.address, -+ descs[0].fields.flags_len & IBMVETH_BUF_LEN_MASK, -+ DMA_TO_DEVICE); -+ -+ for (i = 1; i < skb_shinfo(skb)->nr_frags + 1; i++) - dma_unmap_page(&adapter->vdev->dev, descs[i].fields.address, - descs[i].fields.flags_len & IBMVETH_BUF_LEN_MASK, - DMA_TO_DEVICE); - - diff --git a/ibmveth-Fix-issue-with-DMA-mapping-failure.patch b/ibmveth-Fix-issue-with-DMA-mapping-failure.patch deleted file mode 100644 index af2d834c3..000000000 --- a/ibmveth-Fix-issue-with-DMA-mapping-failure.patch +++ /dev/null @@ -1,93 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Anton Blanchard -Newsgroups: gmane.linux.network -Subject: [PATCH 2/4] ibmveth: Fix issue with DMA mapping failure -Date: Thu, 08 Sep 2011 10:41:04 +1000 -Lines: 47 -Approved: news@gmane.org -Message-ID: <20110908004121.669225190@samba.org> -References: <20110908004102.355674129@samba.org> -NNTP-Posting-Host: lo.gmane.org -X-Trace: dough.gmane.org 1315442760 18037 80.91.229.12 (8 Sep 2011 00:46:00 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Thu, 8 Sep 2011 00:46:00 +0000 (UTC) -Cc: netdev@vger.kernel.org -To: Santiago Leon , - brking@linux.vnet.ibm.com, rcj@linux.vnet.ibm.com -Original-X-From: netdev-owner@vger.kernel.org Thu Sep 08 02:45:55 2011 -Return-path: -Envelope-to: linux-netdev-2@lo.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1R1Ska-0001cA-M3 - for linux-netdev-2@lo.gmane.org; Thu, 08 Sep 2011 02:45:53 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1757665Ab1IHApa (ORCPT ); - Wed, 7 Sep 2011 20:45:30 -0400 -Original-Received: from ozlabs.org ([203.10.76.45]:60840 "EHLO ozlabs.org" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1757659Ab1IHAp1 (ORCPT ); - Wed, 7 Sep 2011 20:45:27 -0400 -Original-Received: from localhost (ppp121-44-79-234.lns20.syd6.internode.on.net [121.44.79.234]) - (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits)) - (Client did not present a certificate) - by ozlabs.org (Postfix) with ESMTPSA id 56E01B6F97; - Thu, 8 Sep 2011 10:45:25 +1000 (EST) -X-Mailbox-Line: From anton@samba.org Thu Sep 8 10:41:21 2011 -User-Agent: quilt/0.48-1 -Content-Disposition: inline; filename=ibmveth_dma_mapping_error.patch -Original-Sender: netdev-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org -Xref: news.gmane.org gmane.linux.network:205931 -Archived-At: - -descs[].fields.address is 32bit which truncates any dma mapping -errors so dma_mapping_error() fails to catch it. - -Use a dma_addr_t to do the comparison. With this patch I was able -to transfer many gigabytes of data with IOMMU fault injection set -at 10% probability. - -Signed-off-by: Anton Blanchard -Cc: # v2.6.37+ ---- - -Index: linux-build/drivers/net/ibmveth.c -=================================================================== ---- linux-build.orig/drivers/net/ibmveth.c 2011-09-01 15:01:18.066844039 +1000 -+++ linux-build/drivers/net/ibmveth.c 2011-09-01 15:03:34.299079796 +1000 -@@ -930,6 +930,7 @@ static netdev_tx_t ibmveth_start_xmit(st - union ibmveth_buf_desc descs[6]; - int last, i; - int force_bounce = 0; -+ dma_addr_t dma_addr; - - /* - * veth handles a maximum of 6 segments including the header, so -@@ -994,17 +995,16 @@ retry_bounce: - } - - /* Map the header */ -- descs[0].fields.address = dma_map_single(&adapter->vdev->dev, skb->data, -- skb_headlen(skb), -- DMA_TO_DEVICE); -- if (dma_mapping_error(&adapter->vdev->dev, descs[0].fields.address)) -+ dma_addr = dma_map_single(&adapter->vdev->dev, skb->data, -+ skb_headlen(skb), DMA_TO_DEVICE); -+ if (dma_mapping_error(&adapter->vdev->dev, dma_addr)) - goto map_failed; - - descs[0].fields.flags_len = desc_flags | skb_headlen(skb); -+ descs[0].fields.address = dma_addr; - - /* Map the frags */ - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { -- unsigned long dma_addr; - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - - dma_addr = dma_map_page(&adapter->vdev->dev, frag->page, - - diff --git a/ipw2x00-fix-rtnl-mutex-deadlock.patch b/ipw2x00-fix-rtnl-mutex-deadlock.patch deleted file mode 100644 index 3c98bc2b8..000000000 --- a/ipw2x00-fix-rtnl-mutex-deadlock.patch +++ /dev/null @@ -1,224 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Stanislaw Gruszka -Newsgroups: gmane.linux.kernel.wireless.general -Subject: [PATCH] ipw2x00: fix rtnl mutex deadlock -Date: Wed, 14 Sep 2011 16:47:50 +0200 -Lines: 173 -Approved: news@gmane.org -Message-ID: <1316011670-6787-1-git-send-email-sgruszka@redhat.com> -NNTP-Posting-Host: lo.gmane.org -X-Trace: dough.gmane.org 1316011688 20989 80.91.229.12 (14 Sep 2011 14:48:08 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Wed, 14 Sep 2011 14:48:08 +0000 (UTC) -Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, - Andrew Morton , - "Rafael J. Wysocki" , - Maciej Rutecki , - Michael Witten , - Witold Baryluk , - Stanislaw Gruszka -To: "John W. Linville" -Original-X-From: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Wed Sep 14 16:48:02 2011 -Return-path: -Envelope-to: glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1R3qkr-0005Xu-KZ - for glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Wed, 14 Sep 2011 16:48:02 +0200 -Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand - id S1755562Ab1INOr7 (ORCPT - ); - Wed, 14 Sep 2011 10:47:59 -0400 -Original-Received: from mx1.redhat.com ([209.132.183.28]:50585 "EHLO mx1.redhat.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1751756Ab1INOr7 (ORCPT ); - Wed, 14 Sep 2011 10:47:59 -0400 -Original-Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p8EEldiu028562 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); - Wed, 14 Sep 2011 10:47:40 -0400 -Original-Received: from localhost (dhcp-27-35.brq.redhat.com [10.34.27.35]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p8EElaD3010274; - Wed, 14 Sep 2011 10:47:37 -0400 -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 -Original-Sender: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Xref: news.gmane.org gmane.linux.kernel.wireless.general:77103 -Archived-At: - -This fix regression introduced by: - -commit: ecb4433550f0620f3d1471ae7099037ede30a91e -Author: Stanislaw Gruszka -Date: Fri Aug 12 14:00:59 2011 +0200 - - mac80211: fix suspend/resume races with unregister hw - -Above commit add rtnl_lock() into wiphy_register(), what cause deadlock -when initializing ipw2x00 driver, which itself call wiphy_register() -from register_netdev() internal callback with rtnl mutex taken. - -To fix move wiphy_register() outside register_netdev(). This solution -have side effect of not creating /sys/class/net/wlanX/phy80211 link, -but that's a minor issue we can live with. - -Bisected-by: Witold Baryluk -Bisected-by: Michael Witten -Tested-by: Witold Baryluk -Tested-by: Michael Witten -Signed-off-by: Stanislaw Gruszka ---- -ecb4433550f0620f3d1471ae7099037ede30a91e was CCed to stable but we -drop it there, when bug was reported. So this patch is only intended -to 3.1 - - drivers/net/wireless/ipw2x00/ipw2100.c | 21 +++++++++++----- - drivers/net/wireless/ipw2x00/ipw2200.c | 39 +++++++++++++++++++++---------- - 2 files changed, 40 insertions(+), 20 deletions(-) - -diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c -index 3774dd0..ef9ad79 100644 ---- a/drivers/net/wireless/ipw2x00/ipw2100.c -+++ b/drivers/net/wireless/ipw2x00/ipw2100.c -@@ -1903,15 +1903,17 @@ static void ipw2100_down(struct ipw2100_priv *priv) - static int ipw2100_net_init(struct net_device *dev) - { - struct ipw2100_priv *priv = libipw_priv(dev); -+ -+ return ipw2100_up(priv, 1); -+} -+ -+static int ipw2100_wdev_init(struct net_device *dev) -+{ -+ struct ipw2100_priv *priv = libipw_priv(dev); - const struct libipw_geo *geo = libipw_get_geo(priv->ieee); - struct wireless_dev *wdev = &priv->ieee->wdev; -- int ret; - int i; - -- ret = ipw2100_up(priv, 1); -- if (ret) -- return ret; -- - memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN); - - /* fill-out priv->ieee->bg_band */ -@@ -6350,9 +6352,13 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, - "Error calling register_netdev.\n"); - goto fail; - } -+ registered = 1; -+ -+ err = ipw2100_wdev_init(dev); -+ if (err) -+ goto fail; - - mutex_lock(&priv->action_mutex); -- registered = 1; - - IPW_DEBUG_INFO("%s: Bound to %s\n", dev->name, pci_name(pci_dev)); - -@@ -6389,7 +6395,8 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, - - fail_unlock: - mutex_unlock(&priv->action_mutex); -- -+ wiphy_unregister(priv->ieee->wdev.wiphy); -+ kfree(priv->ieee->bg_band.channels); - fail: - if (dev) { - if (registered) -diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c -index 87813c3..4ffebed 100644 ---- a/drivers/net/wireless/ipw2x00/ipw2200.c -+++ b/drivers/net/wireless/ipw2x00/ipw2200.c -@@ -11425,16 +11425,23 @@ static void ipw_bg_down(struct work_struct *work) - /* Called by register_netdev() */ - static int ipw_net_init(struct net_device *dev) - { -+ int rc = 0; -+ struct ipw_priv *priv = libipw_priv(dev); -+ -+ mutex_lock(&priv->mutex); -+ if (ipw_up(priv)) -+ rc = -EIO; -+ mutex_unlock(&priv->mutex); -+ -+ return rc; -+} -+ -+static int ipw_wdev_init(struct net_device *dev) -+{ - int i, rc = 0; - struct ipw_priv *priv = libipw_priv(dev); - const struct libipw_geo *geo = libipw_get_geo(priv->ieee); - struct wireless_dev *wdev = &priv->ieee->wdev; -- mutex_lock(&priv->mutex); -- -- if (ipw_up(priv)) { -- rc = -EIO; -- goto out; -- } - - memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN); - -@@ -11519,13 +11526,9 @@ static int ipw_net_init(struct net_device *dev) - set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); - - /* With that information in place, we can now register the wiphy... */ -- if (wiphy_register(wdev->wiphy)) { -+ if (wiphy_register(wdev->wiphy)) - rc = -EIO; -- goto out; -- } -- - out: -- mutex_unlock(&priv->mutex); - return rc; - } - -@@ -11832,14 +11835,22 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, - goto out_remove_sysfs; - } - -+ err = ipw_wdev_init(net_dev); -+ if (err) { -+ IPW_ERROR("failed to register wireless device\n"); -+ goto out_unregister_netdev; -+ } -+ - #ifdef CONFIG_IPW2200_PROMISCUOUS - if (rtap_iface) { - err = ipw_prom_alloc(priv); - if (err) { - IPW_ERROR("Failed to register promiscuous network " - "device (error %d).\n", err); -- unregister_netdev(priv->net_dev); -- goto out_remove_sysfs; -+ wiphy_unregister(priv->ieee->wdev.wiphy); -+ kfree(priv->ieee->a_band.channels); -+ kfree(priv->ieee->bg_band.channels); -+ goto out_unregister_netdev; - } - } - #endif -@@ -11851,6 +11862,8 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, - - return 0; - -+ out_unregister_netdev: -+ unregister_netdev(priv->net_dev); - out_remove_sysfs: - sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); - out_release_irq: --- -1.7.1 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - diff --git a/iwlagn-revert-max-aggregate-size.patch b/iwlagn-revert-max-aggregate-size.patch deleted file mode 100644 index d9e9a8db4..000000000 --- a/iwlagn-revert-max-aggregate-size.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c -index b0ae4de..afa00ec 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c -@@ -2140,8 +2140,6 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, - IEEE80211_HW_SPECTRUM_MGMT | - IEEE80211_HW_REPORTS_TX_ACK_STATUS; - -- hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF; -- - hw->flags |= IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_SUPPORTS_DYNAMIC_PS; - diff --git a/kernel.spec b/kernel.spec index f7582ee13..c442af988 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 4 +%global baserelease 0 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -82,7 +82,7 @@ Summary: The Linux kernel # The next upstream release sublevel (base_sublevel+1) %define upstream_sublevel %(echo $((%{base_sublevel} + 1))) # The rc snapshot level -%define rcrev 6 +%define rcrev 7 # The git snapshot level %define gitrev 0 # Set rpm version accordingly @@ -722,26 +722,14 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13002: revert-efi-rtclock.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch -Patch13004: iwlagn-revert-max-aggregate-size.patch Patch13005: ucvideo-fix-crash-when-linking-entities.patch -Patch13006: add-macbookair41-trackpad.patch Patch13007: add-macbookair41-keyboard.patch -Patch13008: add-macbookair41-btusb.patch Patch13009: hvcs_pi_buf_alloc.patch -Patch13010: ibmveth-Fix-DMA-unmap-error.patch -Patch13011: ibmveth-Fix-issue-with-DMA-mapping-failure.patch -Patch13012: ibmveth-Checksum-offload-is-always-disabled.patch - Patch13013: powerpc-Fix-deadlock-in-icswx-code.patch -# CVE-2011-3191 -Patch13014: cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch - -Patch13015: ipw2x00-fix-rtnl-mutex-deadlock.patch - Patch20000: utrace.patch # Flattened devicetree support @@ -1353,26 +1341,14 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch revert-efi-rtclock.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch -ApplyPatch iwlagn-revert-max-aggregate-size.patch ApplyPatch ucvideo-fix-crash-when-linking-entities.patch -ApplyPatch add-macbookair41-trackpad.patch ApplyPatch add-macbookair41-keyboard.patch -ApplyPatch add-macbookair41-btusb.patch ApplyPatch hvcs_pi_buf_alloc.patch -ApplyPatch ibmveth-Fix-DMA-unmap-error.patch -ApplyPatch ibmveth-Fix-issue-with-DMA-mapping-failure.patch -ApplyPatch ibmveth-Checksum-offload-is-always-disabled.patch - ApplyPatch powerpc-Fix-deadlock-in-icswx-code.patch -# CVE-2011-3191 -ApplyPatch cifs-fix-possible-memory-corruption-in-CIFSFindNext.patch - -ApplyPatch ipw2x00-fix-rtnl-mutex-deadlock.patch - # utrace. ApplyPatch utrace.patch @@ -2077,6 +2053,9 @@ fi # and build. %changelog +* Wed Sep 21 2011 Josh Boyer +- Linux 3.1-rc7 + * Tue Sep 20 2011 Dave Jones - Limit 32-bit x86 kernels to 32 processors. diff --git a/sources b/sources index 474ac9f50..90baa3585 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 -e283598a0c4cbc6da64cda68101fdbf1 patch-3.1-rc6.bz2 +39d993cb8e337a037e9e703b82223cec patch-3.1-rc7.bz2 From 89003bbc998009814d4842f27d231e9f3d589b5d Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Thu, 22 Sep 2011 16:38:58 -0500 Subject: [PATCH 086/487] * Thu Sep 22 2011 Dennis Gilmore - build a vmlinux image on sparc64 --- kernel.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index c442af988..034a87b67 100644 --- a/kernel.spec +++ b/kernel.spec @@ -354,8 +354,8 @@ Summary: The Linux kernel %ifarch sparc64 %define asmarch sparc %define all_arch_configs kernel-%{version}-sparc64*.config -%define make_target image -%define kernel_image arch/sparc/boot/image +%define make_target vmlinux +%define kernel_image vmlinux %define image_install_path boot %define with_tools 0 %endif @@ -2053,6 +2053,9 @@ fi # and build. %changelog +* Thu Sep 22 2011 Dennis Gilmore +- build vmlinux image for sparc64 + * Wed Sep 21 2011 Josh Boyer - Linux 3.1-rc7 From 478ea8fd228f7887ede189aedddb74e66472e5db Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 22 Sep 2011 18:33:17 -0400 Subject: [PATCH 087/487] Make CONFIG_XEN_PLATFORM_PCI=y (rhbz 740664) --- config-x86-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-x86-generic b/config-x86-generic index 4437ccbb4..e1d81cfd6 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -253,7 +253,7 @@ CONFIG_XEN_COMPAT_XENFS=y CONFIG_XEN_BACKEND=y CONFIG_XEN_BLKDEV_BACKEND=m CONFIG_XEN_DEBUG_FS=y -CONFIG_XEN_PLATFORM_PCI=m +CONFIG_XEN_PLATFORM_PCI=y CONFIG_XEN_GNTDEV=m CONFIG_INPUT_XEN_KBDDEV_FRONTEND=m CONFIG_XEN_SELFBALLOONING=y diff --git a/kernel.spec b/kernel.spec index 034a87b67..58d040c14 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2053,6 +2053,9 @@ fi # and build. %changelog +* Thu Sep 22 2011 Dave Jones +- Make CONFIG_XEN_PLATFORM_PCI=y (rhbz 740664) + * Thu Sep 22 2011 Dennis Gilmore - build vmlinux image for sparc64 From 94601c03cefcc6914649f7cdef6ed0a8ba599e13 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 27 Sep 2011 20:18:05 -0400 Subject: [PATCH 088/487] Add patch-3.1-rc8.bz2 so Chuck can rebase f16/rawhide --- sources | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources b/sources index 90baa3585..2194c37b8 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 -39d993cb8e337a037e9e703b82223cec patch-3.1-rc7.bz2 +aae4a0422f4be618fcdbf4bf9de67143 patch-3.1-rc8.bz2 From bfd16e3858aa70c586f95e934738d9aaad837944 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Tue, 27 Sep 2011 21:05:32 -0400 Subject: [PATCH 089/487] Linux 3.1-rc8 New option: CONFIG_ARM_ERRATA_764369 is not set Fix up utrace.patch to apply after commit f9d81f61c --- config-arm-omap-generic | 1 + config-arm-tegra | 3 ++- kernel.spec | 7 ++++++- utrace.patch | 14 +++++++------- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/config-arm-omap-generic b/config-arm-omap-generic index 19ea52191..e396169b3 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -127,6 +127,7 @@ CONFIG_ARM_ERRATA_720789=y # CONFIG_ARM_ERRATA_753970 is not set # CONFIG_ARM_ERRATA_754322 is not set # CONFIG_ARM_ERRATA_754327 is not set +# CONFIG_ARM_ERRATA_764369 is not set CONFIG_ARM_GIC=y # CONFIG_PCI_SYSCALL is not set # CONFIG_PCCARD is not set diff --git a/config-arm-tegra b/config-arm-tegra index 91c176bcd..910b39f81 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -6,7 +6,6 @@ CONFIG_MACH_TRIMSLICE=y CONFIG_MACH_WARIO=y CONFIG_MACH_TEGRA_DT=y CONFIG_TEGRA_DEBUG_UARTD=y -CONFIG_ARM_ERRATA_742230=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y @@ -32,6 +31,7 @@ CONFIG_CACHE_L2X0=y CONFIG_ARM_ERRATA_430973=y # CONFIG_ARM_ERRATA_458693 is not set # CONFIG_ARM_ERRATA_460075 is not set +CONFIG_ARM_ERRATA_742230=y # CONFIG_ARM_ERRATA_742231 is not set CONFIG_PL310_ERRATA_588369=y CONFIG_ARM_ERRATA_720789=y @@ -41,6 +41,7 @@ CONFIG_ARM_ERRATA_720789=y # CONFIG_ARM_ERRATA_753970 is not set # CONFIG_ARM_ERRATA_754322 is not set # CONFIG_ARM_ERRATA_754327 is not set +# CONFIG_ARM_ERRATA_764369 is not set CONFIG_SMP_ON_UP=y CONFIG_LOCAL_TIMERS=y # CONFIG_THUMB2_KERNEL is not set diff --git a/kernel.spec b/kernel.spec index 58d040c14..7368062c3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -82,7 +82,7 @@ Summary: The Linux kernel # The next upstream release sublevel (base_sublevel+1) %define upstream_sublevel %(echo $((%{base_sublevel} + 1))) # The rc snapshot level -%define rcrev 7 +%define rcrev 8 # The git snapshot level %define gitrev 0 # Set rpm version accordingly @@ -2053,6 +2053,11 @@ fi # and build. %changelog +* Tue Sep 27 2011 Chuck Ebbert 3.1.0-0.rc8.git0.0 +- Linux 3.1-rc8 +- New option: CONFIG_ARM_ERRATA_764369 is not set +- Fix up utrace.patch to apply after commit f9d81f61c + * Thu Sep 22 2011 Dave Jones - Make CONFIG_XEN_PLATFORM_PCI=y (rhbz 740664) diff --git a/utrace.patch b/utrace.patch index fbf28ff62..576c737f3 100644 --- a/utrace.patch +++ b/utrace.patch @@ -5168,14 +5168,14 @@ index 4194664..1a50090 100644 unlock_task_sighand(child, &flags); ret = 0; @@ -760,7 +772,7 @@ int ptrace_request(struct task_struct *child, long request, - * of this trap and now. Trigger re-trap immediately. - */ - if (child->jobctl & JOBCTL_TRAP_NOTIFY) -- signal_wake_up(child, true); -+ ptrace_signal_wake_up(child, true); - + * start of this trap and now. Trigger re-trap. + */ + if (child->jobctl & JOBCTL_TRAP_NOTIFY) +- signal_wake_up(child, true); ++ ptrace_signal_wake_up(child, true); + ret = 0; + } unlock_task_sighand(child, &flags); - ret = 0; diff --git a/kernel/signal.c b/kernel/signal.c index 3e8e0b1..0dc6abb 100644 --- a/kernel/signal.c From 63a6d1a55d14f9e6861fb83cee886ea4c1f32993 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 29 Sep 2011 11:29:26 -0400 Subject: [PATCH 090/487] Update logitech USB quirk patch --- kernel.spec | 5 +- usb-add-quirk-for-logitech-webcams.patch | 69 +++++++++++++++++++----- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/kernel.spec b/kernel.spec index 7368062c3..70f4c2c34 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 0 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2053,6 +2053,9 @@ fi # and build. %changelog +* Thu Sep 29 2011 Josh Boyer +- Update logitech USB quirk patch + * Tue Sep 27 2011 Chuck Ebbert 3.1.0-0.rc8.git0.0 - Linux 3.1-rc8 - New option: CONFIG_ARM_ERRATA_764369 is not set diff --git a/usb-add-quirk-for-logitech-webcams.patch b/usb-add-quirk-for-logitech-webcams.patch index fa32f34f9..9a932ca57 100644 --- a/usb-add-quirk-for-logitech-webcams.patch +++ b/usb-add-quirk-for-logitech-webcams.patch @@ -1,30 +1,71 @@ -commit a218e3649310bd2ee0e8b7ec6353ab029d020289 -Author: Oliver Neukum -Date: Tue Aug 9 08:12:37 2011 -0400 +From 48ff94510ecf6b36c793c40ae3d15ce39a331e17 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Tue, 13 Sep 2011 08:42:21 +0200 +Subject: [PATCH] USB:add RESET_RESUME for webcams shown to be quirky - USB: quirk for Logitech C250, C270, and C310 webcams - - This need for this was shown by the new PM code - - Signed-off-by: Oliver Neukum +From 6f673c5ef819548b2cbaf7bb607779af6fdbe731 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Tue, 30 Aug 2011 15:34:32 +0200 +Subject: [PATCH] USB:add RESET_RESUME for webcams shown to be quirky + +The new runtime PM code has shown that many webcams suffer +from a race condition that may crash them upon resume. +Runtime PM is especially prone to show the problem because +it retains power to the cameras at all times. However +system suspension may also crash the devices and retain +power to the devices. +The only way to solve this problem without races is in +usbcore with the RESET_RESUME quirk. + +Signed-off-by: Oliver Neukum + +Add C300 ID from patch in rhbz #742010 +--- + drivers/usb/core/quirks.c | 24 ++++++++++++++++++++++++ + 1 files changed, 24 insertions(+), 0 deletions(-) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c -index 81ce6a8..5114281 100644 +index 81ce6a8..d6a8d82 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c -@@ -41,6 +41,15 @@ static const struct usb_device_id usb_quirk_list[] = { - /* Logitech Harmony 700-series */ - { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, +@@ -38,6 +38,27 @@ static const struct usb_device_id usb_quirk_list[] = { + /* Creative SB Audigy 2 NX */ + { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, ++ /* Logitech Webcam C200 */ ++ { USB_DEVICE(0x046d, 0x0802), .driver_info = USB_QUIRK_RESET_RESUME }, ++ + /* Logitech Webcam C250 */ + { USB_DEVICE(0x046d, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, + ++ /* Logitech Webcam C300 */ ++ { USB_DEVICE(0x046d, 0x0805), .driver_info = USB_QUIRK_RESET_RESUME }, ++ ++ /* Logitech Webcam B/C500 */ ++ { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME }, ++ ++ /* Logitech Webcam Pro 9000 */ ++ { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME }, ++ + /* Logitech Webcam C310 */ + { USB_DEVICE(0x046d, 0x081b), .driver_info = USB_QUIRK_RESET_RESUME }, + + /* Logitech Webcam C270 */ + { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME }, + - /* Philips PSC805 audio device */ - { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Logitech Harmony 700-series */ + { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, +@@ -69,6 +90,9 @@ static const struct usb_device_id usb_quirk_list[] = { + { USB_DEVICE(0x06a3, 0x0006), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, + ++ /* Guillemot Webcam Hercules Dualpix Exchange*/ ++ { USB_DEVICE(0x06f8, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, ++ + /* M-Systems Flash Disk Pioneers */ + { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, + +-- +1.7.6 + From de575f564b379b3ea70891258e07cf8572c45b0d Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 29 Sep 2011 20:45:21 -0400 Subject: [PATCH 091/487] Require grubby >= 8.3-1 so initrd line gets added (rhbz #725185) --- kernel.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 70f4c2c34..cf7aa747f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -473,7 +473,7 @@ Summary: The Linux kernel # Packages that need to be installed before the kernel is, because the %%post # scripts use them. # -%define kernel_prereq fileutils, module-init-tools >= 3.16-2, initscripts >= 8.11.1-1, grubby >= 7.0.10-1 +%define kernel_prereq fileutils, module-init-tools >= 3.16-2, initscripts >= 8.11.1-1, grubby >= 8.3-1 %define initrd_prereq dracut >= 001-7 # @@ -2053,6 +2053,9 @@ fi # and build. %changelog +* Thu Sep 29 2011 Chuck Ebbert +- Require grubby >= 8.3-1 so initrd line gets added (rhbz #725185) + * Thu Sep 29 2011 Josh Boyer - Update logitech USB quirk patch From c5c0d51eb59d13dccd975525ab2a511a8704b004 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 3 Oct 2011 23:01:13 -0400 Subject: [PATCH 092/487] Fix oopses on removal of external disks --- ...b1bf15b8532c396821774bf6451e563438f5.patch | 71 +++++++++++++++++++ kernel.spec | 7 ++ 2 files changed, 78 insertions(+) create mode 100644 777eb1bf15b8532c396821774bf6451e563438f5.patch diff --git a/777eb1bf15b8532c396821774bf6451e563438f5.patch b/777eb1bf15b8532c396821774bf6451e563438f5.patch new file mode 100644 index 000000000..7826375e0 --- /dev/null +++ b/777eb1bf15b8532c396821774bf6451e563438f5.patch @@ -0,0 +1,71 @@ +From 777eb1bf15b8532c396821774bf6451e563438f5 Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke +Date: Wed, 28 Sep 2011 08:07:01 -0600 +Subject: [PATCH] block: Free queue resources at blk_release_queue() + +A kernel crash is observed when a mounted ext3/ext4 filesystem is +physically removed. The problem is that blk_cleanup_queue() frees up +some resources eg by calling elevator_exit(), which are not checked for +in normal operation. So we should rather move these calls to the +destructor function blk_release_queue() as at that point all remaining +references are gone. However, in doing so we have to ensure that any +externally supplied queue_lock is disconnected as the driver might free +up the lock after the call of blk_cleanup_queue(), + +Signed-off-by: Hannes Reinecke +Signed-off-by: Jens Axboe +--- + block/blk-core.c | 13 ++++++------- + block/blk-sysfs.c | 5 +++++ + 2 files changed, 11 insertions(+), 7 deletions(-) + +diff --git a/block/blk-core.c b/block/blk-core.c +index b2ed78a..d34433a 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -348,9 +348,10 @@ void blk_put_queue(struct request_queue *q) + EXPORT_SYMBOL(blk_put_queue); + + /* +- * Note: If a driver supplied the queue lock, it should not zap that lock +- * unexpectedly as some queue cleanup components like elevator_exit() and +- * blk_throtl_exit() need queue lock. ++ * Note: If a driver supplied the queue lock, it is disconnected ++ * by this function. The actual state of the lock doesn't matter ++ * here as the request_queue isn't accessible after this point ++ * (QUEUE_FLAG_DEAD is set) and no other requests will be queued. + */ + void blk_cleanup_queue(struct request_queue *q) + { +@@ -367,10 +368,8 @@ void blk_cleanup_queue(struct request_queue *q) + queue_flag_set_unlocked(QUEUE_FLAG_DEAD, q); + mutex_unlock(&q->sysfs_lock); + +- if (q->elevator) +- elevator_exit(q->elevator); +- +- blk_throtl_exit(q); ++ if (q->queue_lock != &q->__queue_lock) ++ q->queue_lock = &q->__queue_lock; + + blk_put_queue(q); + } +diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c +index e681805..60fda88 100644 +--- a/block/blk-sysfs.c ++++ b/block/blk-sysfs.c +@@ -479,6 +479,11 @@ static void blk_release_queue(struct kobject *kobj) + + blk_sync_queue(q); + ++ if (q->elevator) ++ elevator_exit(q->elevator); ++ ++ blk_throtl_exit(q); ++ + if (rl->rq_pool) + mempool_destroy(rl->rq_pool); + +-- +1.7.5.4 + diff --git a/kernel.spec b/kernel.spec index cf7aa747f..6b046652d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -735,6 +735,8 @@ Patch20000: utrace.patch # Flattened devicetree support Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch + +Patch21010: 777eb1bf15b8532c396821774bf6451e563438f5.patch %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1352,6 +1354,8 @@ ApplyPatch powerpc-Fix-deadlock-in-icswx-code.patch # utrace. ApplyPatch utrace.patch +ApplyPatch 777eb1bf15b8532c396821774bf6451e563438f5.patch + # END OF PATCH APPLICATIONS %endif @@ -2053,6 +2057,9 @@ fi # and build. %changelog +* Mon Oct 03 2011 Chuck Ebbert 3.1.0-0.rc8.git0.1 +- block: Free queue resources at blk_release_queue() + * Thu Sep 29 2011 Chuck Ebbert - Require grubby >= 8.3-1 so initrd line gets added (rhbz #725185) From cf2d0ce1776cd25ed54bd4c3b3a43452c22972c2 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 5 Oct 2011 10:51:31 -0400 Subject: [PATCH 093/487] Linux 3.1-rc9 --- ...b1bf15b8532c396821774bf6451e563438f5.patch | 71 ------------------- drm-i915-fbc-stfu.patch | 2 +- kernel.spec | 12 ++-- sources | 2 +- ucvideo-fix-crash-when-linking-entities.patch | 34 --------- 5 files changed, 7 insertions(+), 114 deletions(-) delete mode 100644 777eb1bf15b8532c396821774bf6451e563438f5.patch delete mode 100644 ucvideo-fix-crash-when-linking-entities.patch diff --git a/777eb1bf15b8532c396821774bf6451e563438f5.patch b/777eb1bf15b8532c396821774bf6451e563438f5.patch deleted file mode 100644 index 7826375e0..000000000 --- a/777eb1bf15b8532c396821774bf6451e563438f5.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 777eb1bf15b8532c396821774bf6451e563438f5 Mon Sep 17 00:00:00 2001 -From: Hannes Reinecke -Date: Wed, 28 Sep 2011 08:07:01 -0600 -Subject: [PATCH] block: Free queue resources at blk_release_queue() - -A kernel crash is observed when a mounted ext3/ext4 filesystem is -physically removed. The problem is that blk_cleanup_queue() frees up -some resources eg by calling elevator_exit(), which are not checked for -in normal operation. So we should rather move these calls to the -destructor function blk_release_queue() as at that point all remaining -references are gone. However, in doing so we have to ensure that any -externally supplied queue_lock is disconnected as the driver might free -up the lock after the call of blk_cleanup_queue(), - -Signed-off-by: Hannes Reinecke -Signed-off-by: Jens Axboe ---- - block/blk-core.c | 13 ++++++------- - block/blk-sysfs.c | 5 +++++ - 2 files changed, 11 insertions(+), 7 deletions(-) - -diff --git a/block/blk-core.c b/block/blk-core.c -index b2ed78a..d34433a 100644 ---- a/block/blk-core.c -+++ b/block/blk-core.c -@@ -348,9 +348,10 @@ void blk_put_queue(struct request_queue *q) - EXPORT_SYMBOL(blk_put_queue); - - /* -- * Note: If a driver supplied the queue lock, it should not zap that lock -- * unexpectedly as some queue cleanup components like elevator_exit() and -- * blk_throtl_exit() need queue lock. -+ * Note: If a driver supplied the queue lock, it is disconnected -+ * by this function. The actual state of the lock doesn't matter -+ * here as the request_queue isn't accessible after this point -+ * (QUEUE_FLAG_DEAD is set) and no other requests will be queued. - */ - void blk_cleanup_queue(struct request_queue *q) - { -@@ -367,10 +368,8 @@ void blk_cleanup_queue(struct request_queue *q) - queue_flag_set_unlocked(QUEUE_FLAG_DEAD, q); - mutex_unlock(&q->sysfs_lock); - -- if (q->elevator) -- elevator_exit(q->elevator); -- -- blk_throtl_exit(q); -+ if (q->queue_lock != &q->__queue_lock) -+ q->queue_lock = &q->__queue_lock; - - blk_put_queue(q); - } -diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c -index e681805..60fda88 100644 ---- a/block/blk-sysfs.c -+++ b/block/blk-sysfs.c -@@ -479,6 +479,11 @@ static void blk_release_queue(struct kobject *kobj) - - blk_sync_queue(q); - -+ if (q->elevator) -+ elevator_exit(q->elevator); -+ -+ blk_throtl_exit(q); -+ - if (rl->rq_pool) - mempool_destroy(rl->rq_pool); - --- -1.7.5.4 - diff --git a/drm-i915-fbc-stfu.patch b/drm-i915-fbc-stfu.patch index 7e30dae4b..9240387ee 100644 --- a/drm-i915-fbc-stfu.patch +++ b/drm-i915-fbc-stfu.patch @@ -89,8 +89,8 @@ index 56a8554..a6d14eb 100644 * display to settle before starting the compression. Note that * this delay also serves a second purpose: it allows for a @@ -1800,8 +1783,6 @@ static void intel_update_fbc(struct drm_device *dev) - struct intel_framebuffer *intel_fb; struct drm_i915_gem_object *obj; + int enable_fbc; - DRM_DEBUG_KMS("\n"); - diff --git a/kernel.spec b/kernel.spec index 6b046652d..6bebdec51 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 1 +%global baserelease 0 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -82,7 +82,7 @@ Summary: The Linux kernel # The next upstream release sublevel (base_sublevel+1) %define upstream_sublevel %(echo $((%{base_sublevel} + 1))) # The rc snapshot level -%define rcrev 8 +%define rcrev 9 # The git snapshot level %define gitrev 0 # Set rpm version accordingly @@ -722,7 +722,6 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13002: revert-efi-rtclock.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch -Patch13005: ucvideo-fix-crash-when-linking-entities.patch Patch13007: add-macbookair41-keyboard.patch @@ -736,7 +735,6 @@ Patch20000: utrace.patch Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch -Patch21010: 777eb1bf15b8532c396821774bf6451e563438f5.patch %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1343,7 +1341,6 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch revert-efi-rtclock.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch -ApplyPatch ucvideo-fix-crash-when-linking-entities.patch ApplyPatch add-macbookair41-keyboard.patch @@ -1354,8 +1351,6 @@ ApplyPatch powerpc-Fix-deadlock-in-icswx-code.patch # utrace. ApplyPatch utrace.patch -ApplyPatch 777eb1bf15b8532c396821774bf6451e563438f5.patch - # END OF PATCH APPLICATIONS %endif @@ -2057,6 +2052,9 @@ fi # and build. %changelog +* Wed Oct 05 2011 Chuck Ebbert 3.1.0-0.rc9.git0.0 +- Linux 3.1-rc9 + * Mon Oct 03 2011 Chuck Ebbert 3.1.0-0.rc8.git0.1 - block: Free queue resources at blk_release_queue() diff --git a/sources b/sources index 2194c37b8..e509d0145 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 -aae4a0422f4be618fcdbf4bf9de67143 patch-3.1-rc8.bz2 +85fd0d4c9701392b6eb9293035726a02 patch-3.1-rc9.bz2 diff --git a/ucvideo-fix-crash-when-linking-entities.patch b/ucvideo-fix-crash-when-linking-entities.patch deleted file mode 100644 index 69f86d64c..000000000 --- a/ucvideo-fix-crash-when-linking-entities.patch +++ /dev/null @@ -1,34 +0,0 @@ -The uvc_mc_register_entity() function wrongfully selects the -media_entity associated with a UVC entity when creating links. This -results in access to uninitialized media_entity structures and can hit a -BUG_ON statement in media_entity_create_link(). Fix it. - -Signed-off-by: Laurent Pinchart ---- - drivers/media/video/uvc/uvc_entity.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -This patch should fix a v3.0 regression that results in a kernel crash as -reported in http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=637740 and -https://bugzilla.redhat.com/show_bug.cgi?id=735437. - -Test results will be welcome. - -diff --git a/drivers/media/video/uvc/uvc_entity.c b/drivers/media/video/uvc/uvc_entity.c -index 48fea37..29e2399 100644 ---- a/drivers/media/video/uvc/uvc_entity.c -+++ b/drivers/media/video/uvc/uvc_entity.c -@@ -49,7 +49,7 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain, - if (remote == NULL) - return -EINVAL; - -- source = (UVC_ENTITY_TYPE(remote) != UVC_TT_STREAMING) -+ source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING) - ? (remote->vdev ? &remote->vdev->entity : NULL) - : &remote->subdev.entity; - if (source == NULL) --- -Regards, - -Laurent Pinchart - From 885bf3a7eb5058b8dc0f2107404fa811bfdf224f Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 6 Oct 2011 18:37:12 -0400 Subject: [PATCH 094/487] Taint if virtualbox modules have been loaded. --- kernel.spec | 5 +++++ taint-vbox.patch | 15 +++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 taint-vbox.patch diff --git a/kernel.spec b/kernel.spec index 6bebdec51..8a4257a05 100644 --- a/kernel.spec +++ b/kernel.spec @@ -644,6 +644,7 @@ Patch09: linux-2.6-upstream-reverts.patch # Standalone patches +Patch100: taint-vbox.patch Patch160: linux-2.6-32bit-mmap-exec-randomization.patch Patch161: linux-2.6-i386-nx-emulation.patch @@ -1216,6 +1217,7 @@ ApplyOptionalPatch linux-2.6-upstream-reverts.patch -R ApplyPatch arm-omap-dt-compat.patch ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch +ApplyPatch taint-vbox.patch # # NX Emulation # @@ -2052,6 +2054,9 @@ fi # and build. %changelog +* Thu Oct 06 2011 Dave Jones +- Taint if virtualbox modules have been loaded. + * Wed Oct 05 2011 Chuck Ebbert 3.1.0-0.rc9.git0.0 - Linux 3.1-rc9 diff --git a/taint-vbox.patch b/taint-vbox.patch new file mode 100644 index 000000000..5cb3e47c9 --- /dev/null +++ b/taint-vbox.patch @@ -0,0 +1,15 @@ +diff --git a/kernel/module.c b/kernel/module.c +index 04379f92..d26c9a3 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -2653,6 +2653,10 @@ static int check_module_license_and_versions(struct module *mod) + if (strcmp(mod->name, "ndiswrapper") == 0) + add_taint(TAINT_PROPRIETARY_MODULE); + ++ /* vbox is garbage. */ ++ if (strcmp(mod->name, "vboxdrv") == 0) ++ add_taint(TAINT_CRAP); ++ + /* driverloader was caught wrongly pretending to be under GPL */ + if (strcmp(mod->name, "driverloader") == 0) + add_taint_module(mod, TAINT_PROPRIETARY_MODULE); From dfb88fb9b4fe96d85875673f53235b9fd78ea8a4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 6 Oct 2011 14:31:40 -0400 Subject: [PATCH 095/487] Add patch to fix Ricoh e823 SD card readers (rhbz 722509) --- kernel.spec | 11 ++- ...-for-lower-base-frequency-quirk-for-.patch | 73 +++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 mmc-Always-check-for-lower-base-frequency-quirk-for-.patch diff --git a/kernel.spec b/kernel.spec index 8a4257a05..17d88b8ad 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 0 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -736,6 +736,9 @@ Patch20000: utrace.patch Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch +#rhbz #722509 +Patch21002: mmc-Always-check-for-lower-base-frequency-quirk-for-.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1350,6 +1353,9 @@ ApplyPatch hvcs_pi_buf_alloc.patch ApplyPatch powerpc-Fix-deadlock-in-icswx-code.patch +#rhbz #722509 +ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch + # utrace. ApplyPatch utrace.patch @@ -2054,6 +2060,9 @@ fi # and build. %changelog +* Thu Oct 06 2011 Josh Boyer +- Add patch to fix base frequency check for Ricoh e823 devices (rhbz 722509) + * Thu Oct 06 2011 Dave Jones - Taint if virtualbox modules have been loaded. diff --git a/mmc-Always-check-for-lower-base-frequency-quirk-for-.patch b/mmc-Always-check-for-lower-base-frequency-quirk-for-.patch new file mode 100644 index 000000000..2d7caad83 --- /dev/null +++ b/mmc-Always-check-for-lower-base-frequency-quirk-for-.patch @@ -0,0 +1,73 @@ +From 65ff02dff67bf26a9c27d9aa11a30eaf3d28469e Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Wed, 5 Oct 2011 11:29:57 -0400 +Subject: [PATCH] mmc: Always check for lower base frequency quirk for Ricoh + 1180:e823 + +Commit 15bed0f2f added a quirk for the e823 Ricoh card reader to lower the +base frequency. However, the quirk first checks to see if the proprietary +MMC controller is disabled, and returns if so. On some devices, such as the +Lenovo X220, the MMC controller is already disabled by firmware it seems, +but the frequency change is still needed so sdhci-pci can talk to the cards. +Since the MMC controller is disabled, the frequency fixup was never being run +on these machines. + +This moves the e823 check above the MMC controller check so that it always +gets run. + +This fixes https://bugzilla.redhat.com/show_bug.cgi?id=722509 + +Signed-off-by: Josh Boyer +--- + drivers/pci/quirks.c | 28 ++++++++++++++-------------- + 1 files changed, 14 insertions(+), 14 deletions(-) + +diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c +index 1196f61..cec4629 100644 +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -2745,20 +2745,6 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) + /* disable must be done via function #0 */ + if (PCI_FUNC(dev->devfn)) + return; +- +- pci_read_config_byte(dev, 0xCB, &disable); +- +- if (disable & 0x02) +- return; +- +- pci_read_config_byte(dev, 0xCA, &write_enable); +- pci_write_config_byte(dev, 0xCA, 0x57); +- pci_write_config_byte(dev, 0xCB, disable | 0x02); +- pci_write_config_byte(dev, 0xCA, write_enable); +- +- dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n"); +- dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n"); +- + /* + * RICOH 0xe823 SD/MMC card reader fails to recognize + * certain types of SD/MMC cards. Lowering the SD base +@@ -2781,6 +2767,20 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) + + dev_notice(&dev->dev, "MMC controller base frequency changed to 50Mhz.\n"); + } ++ ++ pci_read_config_byte(dev, 0xCB, &disable); ++ ++ if (disable & 0x02) ++ return; ++ ++ pci_read_config_byte(dev, 0xCA, &write_enable); ++ pci_write_config_byte(dev, 0xCA, 0x57); ++ pci_write_config_byte(dev, 0xCB, disable | 0x02); ++ pci_write_config_byte(dev, 0xCA, write_enable); ++ ++ dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n"); ++ dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n"); ++ + } + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); + DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); +-- +1.7.6.4 + From b4e869a895e64b6295d856cd385acba1766c006f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 11 Oct 2011 08:45:11 -0400 Subject: [PATCH 096/487] Disable Xen balloon memory hotplug support (rhbz 744408) --- config-x86_64-generic | 2 +- kernel.spec | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/config-x86_64-generic b/config-x86_64-generic index a31c5e82c..693c3a8b6 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -80,7 +80,7 @@ CONFIG_SGI_GRU=m # CONFIG_VIDEO_CAFE_CCIC is not set CONFIG_XEN_MAX_DOMAIN_MEMORY=32 -CONFIG_XEN_BALLOON_MEMORY_HOTPLUG=y +# CONFIG_XEN_BALLOON_MEMORY_HOTPLUG is not set CONFIG_XEN_DEV_EVTCHN=m CONFIG_XEN_SYS_HYPERVISOR=y diff --git a/kernel.spec b/kernel.spec index 17d88b8ad..7f5575f0d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2060,6 +2060,9 @@ fi # and build. %changelog +* Tue Oct 11 2011 Josh Boyer +- Disable CONFIG_XEN_BALLOON_MEMORY_HOTPLUG (rhbz 744408) + * Thu Oct 06 2011 Josh Boyer - Add patch to fix base frequency check for Ricoh e823 devices (rhbz 722509) From a2975f8e0c1e14b291798b5f309c941aab7fd3db Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 13 Oct 2011 08:48:28 -0400 Subject: [PATCH 097/487] Add patch from Stanislaw Gruszka to fix iwlagn NULL dereference (rhbz 744155) --- ...x-ht_params-NULL-pointer-dereference.patch | 43 +++++++++++++++++++ kernel.spec | 9 +++- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 iwlagn-fix-ht_params-NULL-pointer-dereference.patch diff --git a/iwlagn-fix-ht_params-NULL-pointer-dereference.patch b/iwlagn-fix-ht_params-NULL-pointer-dereference.patch new file mode 100644 index 000000000..4dcf490bb --- /dev/null +++ b/iwlagn-fix-ht_params-NULL-pointer-dereference.patch @@ -0,0 +1,43 @@ +This fix regression introduced by commit: + +commit 15b3f3b006b42a678523cad989bfd60b76bf4403 +Author: Wey-Yi Guy +Date: Fri Jun 3 07:54:13 2011 -0700 + + iwlagn: set smps mode after assoc for 1000 device + +Also remove unneeded brackets on the way. + +Address: +https://bugzilla.redhat.com/show_bug.cgi?id=744155 + +If fix will not get 3.1 release, it should be applied in 3.1 stable. + +Cc: stable@kernel.org # 3.1+ +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +index ca632f9..5004342 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +@@ -296,8 +296,8 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv, + return ret; + } + +- if ((ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION) && +- priv->cfg->ht_params->smps_mode) ++ if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION && ++ priv->cfg->ht_params && priv->cfg->ht_params->smps_mode) + ieee80211_request_smps(ctx->vif, + priv->cfg->ht_params->smps_mode); + +-- +1.7.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index 7f5575f0d..4d73531a1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -730,6 +730,8 @@ Patch13009: hvcs_pi_buf_alloc.patch Patch13013: powerpc-Fix-deadlock-in-icswx-code.patch +Patch13014: iwlagn-fix-ht_params-NULL-pointer-dereference.patch + Patch20000: utrace.patch # Flattened devicetree support @@ -1353,6 +1355,8 @@ ApplyPatch hvcs_pi_buf_alloc.patch ApplyPatch powerpc-Fix-deadlock-in-icswx-code.patch +ApplyPatch iwlagn-fix-ht_params-NULL-pointer-dereference.patch + #rhbz #722509 ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch @@ -2060,6 +2064,9 @@ fi # and build. %changelog +* Thu Oct 13 2011 Josh Boyer +- Add patch from Stanislaw Gruszka to fix iwlagn NULL dereference (rhbz 744155) + * Tue Oct 11 2011 Josh Boyer - Disable CONFIG_XEN_BALLOON_MEMORY_HOTPLUG (rhbz 744408) From 91087d1d01b8eb2956be74e7f868c1475c19a029 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Thu, 13 Oct 2011 10:49:31 -0400 Subject: [PATCH 098/487] drm/i915: Treat SDVO LVDS as digital when parsing EDID (#729882) --- drm-i915-sdvo-lvds-is-digital.patch | 83 +++++++++++++++++++++++++++++ kernel.spec | 6 +++ 2 files changed, 89 insertions(+) create mode 100644 drm-i915-sdvo-lvds-is-digital.patch diff --git a/drm-i915-sdvo-lvds-is-digital.patch b/drm-i915-sdvo-lvds-is-digital.patch new file mode 100644 index 000000000..68d0c4b31 --- /dev/null +++ b/drm-i915-sdvo-lvds-is-digital.patch @@ -0,0 +1,83 @@ +From 64015d6d16d7ed5b6ffcec95dc13e8694bd2a4d6 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Mon, 20 Jun 2011 22:35:24 +0100 +Subject: [PATCH] drm/i915/sdvo: Include LVDS panels for the IS_DIGITAL check + +We were checking whether the supplied edid matched the connector it was +read from. We do this in case a DDC read returns an EDID for another +device on a multifunction or otherwise interesting card. However, we +failed to include LVDS as a digital device and so rejecting an otherwise +valid EDID. + +Fixes the detection of the secondary SDVO LVDS panel on the Libretto +W105. + +Signed-off-by: Chris Wilson +--- + drivers/gpu/drm/i915/intel_sdvo.c | 28 ++++++++++++++++++++-------- + 1 files changed, 20 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c +index f96975c..26eff9f 100644 +--- a/drivers/gpu/drm/i915/intel_sdvo.c ++++ b/drivers/gpu/drm/i915/intel_sdvo.c +@@ -49,6 +49,7 @@ + #define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK) + #define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK) + #define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK)) ++#define IS_DIGITAL(c) (c->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK)) + + + static const char *tv_format_names[] = { +@@ -1363,6 +1364,18 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) + return status; + } + ++static bool ++intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo, ++ struct edid *edid) ++{ ++ bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); ++ bool connector_is_digital = !!IS_DIGITAL(sdvo); ++ ++ DRM_DEBUG_KMS("connector_is_digital? %d, monitor_is_digital? %d\n", ++ connector_is_digital, monitor_is_digital); ++ return connector_is_digital == monitor_is_digital; ++} ++ + static enum drm_connector_status + intel_sdvo_detect(struct drm_connector *connector, bool force) + { +@@ -1407,10 +1420,12 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) + if (edid == NULL) + edid = intel_sdvo_get_analog_edid(connector); + if (edid != NULL) { +- if (edid->input & DRM_EDID_INPUT_DIGITAL) +- ret = connector_status_disconnected; +- else ++ if (intel_sdvo_connector_matches_edid(intel_sdvo_connector, ++ edid)) + ret = connector_status_connected; ++ else ++ ret = connector_status_disconnected; ++ + connector->display_info.raw_edid = NULL; + kfree(edid); + } else +@@ -1451,11 +1466,8 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) + edid = intel_sdvo_get_analog_edid(connector); + + if (edid != NULL) { +- struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); +- bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); +- bool connector_is_digital = !!IS_TMDS(intel_sdvo_connector); +- +- if (connector_is_digital == monitor_is_digital) { ++ if (intel_sdvo_connector_matches_edid(to_intel_sdvo_connector(connector), ++ edid)) { + drm_mode_connector_update_edid_property(connector, edid); + drm_add_edid_modes(connector, edid); + } +-- +1.7.5.4 + diff --git a/kernel.spec b/kernel.spec index 4d73531a1..09bf26492 100644 --- a/kernel.spec +++ b/kernel.spec @@ -686,6 +686,8 @@ Patch1824: drm-intel-next.patch Patch1825: drm-intel-make-lvds-work.patch # hush the i915 fbc noise Patch1826: drm-i915-fbc-stfu.patch +# rhbz#729882, https://bugs.freedesktop.org/attachment.cgi?id=49069 +Patch1827: drm-i915-sdvo-lvds-is-digital.patch Patch1900: linux-2.6-intel-iommu-igfx.patch @@ -1315,6 +1317,7 @@ ApplyOptionalPatch drm-nouveau-updates.patch ApplyOptionalPatch drm-intel-next.patch ApplyPatch drm-intel-make-lvds-work.patch ApplyPatch drm-i915-fbc-stfu.patch +ApplyPatch drm-i915-sdvo-lvds-is-digital.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch # silence the ACPI blacklist code @@ -2064,6 +2067,9 @@ fi # and build. %changelog +* Thu Oct 13 2011 Adam Jackson +- drm/i915: Treat SDVO LVDS as digital when parsing EDID (#729882) + * Thu Oct 13 2011 Josh Boyer - Add patch from Stanislaw Gruszka to fix iwlagn NULL dereference (rhbz 744155) From b6ba0deffa1d89ae4ce31aae9eba2eb489de2520 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 13 Oct 2011 15:51:57 -0400 Subject: [PATCH 099/487] Add C600 ID to the Logitech USB patch --- kernel.spec | 3 +++ usb-add-quirk-for-logitech-webcams.patch | 18 +++++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/kernel.spec b/kernel.spec index 09bf26492..89149b215 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2067,6 +2067,9 @@ fi # and build. %changelog +* Thu Oct 13 2011 Josh Boyer +- Update usb-add-quirk-for-logitech-webcams.patch with C600 ID (rhbz 742010) + * Thu Oct 13 2011 Adam Jackson - drm/i915: Treat SDVO LVDS as digital when parsing EDID (#729882) diff --git a/usb-add-quirk-for-logitech-webcams.patch b/usb-add-quirk-for-logitech-webcams.patch index 9a932ca57..052a27e73 100644 --- a/usb-add-quirk-for-logitech-webcams.patch +++ b/usb-add-quirk-for-logitech-webcams.patch @@ -1,4 +1,4 @@ -From 48ff94510ecf6b36c793c40ae3d15ce39a331e17 Mon Sep 17 00:00:00 2001 +From d5446509abd85b6845d91a319a033c5bd17e494d Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 13 Sep 2011 08:42:21 +0200 Subject: [PATCH] USB:add RESET_RESUME for webcams shown to be quirky @@ -20,15 +20,16 @@ usbcore with the RESET_RESUME quirk. Signed-off-by: Oliver Neukum Add C300 ID from patch in rhbz #742010 +Add C600 ID from rhbz #742010 --- - drivers/usb/core/quirks.c | 24 ++++++++++++++++++++++++ - 1 files changed, 24 insertions(+), 0 deletions(-) + drivers/usb/core/quirks.c | 27 +++++++++++++++++++++++++++ + 1 files changed, 27 insertions(+), 0 deletions(-) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c -index 81ce6a8..d6a8d82 100644 +index 81ce6a8..caa1991 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c -@@ -38,6 +38,27 @@ static const struct usb_device_id usb_quirk_list[] = { +@@ -38,6 +38,30 @@ static const struct usb_device_id usb_quirk_list[] = { /* Creative SB Audigy 2 NX */ { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, @@ -44,6 +45,9 @@ index 81ce6a8..d6a8d82 100644 + /* Logitech Webcam B/C500 */ + { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME }, + ++ /* Logitech Webcam C600 */ ++ { USB_DEVICE(0x046d, 0x0808), .driver_info = USB_QUIRK_RESET_RESUME }, ++ + /* Logitech Webcam Pro 9000 */ + { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME }, + @@ -56,7 +60,7 @@ index 81ce6a8..d6a8d82 100644 /* Logitech Harmony 700-series */ { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, -@@ -69,6 +90,9 @@ static const struct usb_device_id usb_quirk_list[] = { +@@ -69,6 +93,9 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x06a3, 0x0006), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, @@ -67,5 +71,5 @@ index 81ce6a8..d6a8d82 100644 { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, -- -1.7.6 +1.7.6.4 From 9258f325b1e782d2f088d087b2612c78e775aee5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 17 Oct 2011 13:24:14 -0400 Subject: [PATCH 100/487] Add two patches to fix stalls in khugepaged (rhbz 735946) --- ...direct-reclaim-for-higher-order-allo.patch | 54 +++++++++++++ ...-compaction-if-compaction-can-procee.patch | 81 +++++++++++++++++++ kernel.spec | 11 +++ 3 files changed, 146 insertions(+) create mode 100644 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch create mode 100644 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch diff --git a/0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch b/0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch new file mode 100644 index 000000000..77777f012 --- /dev/null +++ b/0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch @@ -0,0 +1,54 @@ +From 6b7025ea927d290a59d2772828435c1893f0267f Mon Sep 17 00:00:00 2001 +From: Rik van Riel +Date: Fri, 7 Oct 2011 16:17:22 +0100 +Subject: [PATCH 1/2] mm: vmscan: Limit direct reclaim for higher order + allocations + +When suffering from memory fragmentation due to unfreeable pages, +THP page faults will repeatedly try to compact memory. Due to the +unfreeable pages, compaction fails. + +Needless to say, at that point page reclaim also fails to create +free contiguous 2MB areas. However, that doesn't stop the current +code from trying, over and over again, and freeing a minimum of 4MB +(2UL << sc->order pages) at every single invocation. + +This resulted in my 12GB system having 2-3GB free memory, a +corresponding amount of used swap and very sluggish response times. + +This can be avoided by having the direct reclaim code not reclaim from +zones that already have plenty of free memory available for compaction. + +If compaction still fails due to unmovable memory, doing additional +reclaim will only hurt the system, not help. + +Signed-off-by: Rik van Riel +Signed-off-by: Mel Gorman +--- + mm/vmscan.c | 10 ++++++++++ + 1 files changed, 10 insertions(+), 0 deletions(-) + +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 6072d74..8c03534 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -2022,6 +2022,16 @@ static void shrink_zones(int priority, struct zonelist *zonelist, + continue; + if (zone->all_unreclaimable && priority != DEF_PRIORITY) + continue; /* Let kswapd poll it */ ++ if (COMPACTION_BUILD) { ++ /* ++ * If we already have plenty of memory free ++ * for compaction, don't free any more. ++ */ ++ if (sc->order > PAGE_ALLOC_COSTLY_ORDER && ++ (compaction_suitable(zone, sc->order) || ++ compaction_deferred(zone))) ++ continue; ++ } + /* + * This steals pages from memory cgroups over softlimit + * and returns the number of reclaimed pages and +-- +1.7.6.4 + diff --git a/0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch b/0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch new file mode 100644 index 000000000..e74b64d91 --- /dev/null +++ b/0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch @@ -0,0 +1,81 @@ +From c01043c9aa51a63bd01c60e53494ca4a7e994542 Mon Sep 17 00:00:00 2001 +From: Mel Gorman +Date: Fri, 7 Oct 2011 16:17:23 +0100 +Subject: [PATCH 2/2] mm: Abort reclaim/compaction if compaction can proceed + +If compaction can proceed, shrink_zones() stops doing any work but +the callers still shrink_slab(), raises the priority and potentially +sleeps. This patch aborts direct reclaim/compaction entirely if +compaction can proceed. + +Signed-off-by: Mel Gorman +--- + mm/vmscan.c | 20 ++++++++++++++++---- + 1 files changed, 16 insertions(+), 4 deletions(-) + +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 8c03534..b295a38 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -2000,14 +2000,19 @@ restart: + * + * If a zone is deemed to be full of pinned pages then just give it a light + * scan then give up on it. ++ * ++ * This function returns true if a zone is being reclaimed for a costly ++ * high-order allocation and compaction is either ready to begin or deferred. ++ * This indicates to the caller that it should retry the allocation or fail. + */ +-static void shrink_zones(int priority, struct zonelist *zonelist, ++static bool shrink_zones(int priority, struct zonelist *zonelist, + struct scan_control *sc) + { + struct zoneref *z; + struct zone *zone; + unsigned long nr_soft_reclaimed; + unsigned long nr_soft_scanned; ++ bool should_abort_reclaim = false; + + for_each_zone_zonelist_nodemask(zone, z, zonelist, + gfp_zone(sc->gfp_mask), sc->nodemask) { +@@ -2025,12 +2030,15 @@ static void shrink_zones(int priority, struct zonelist *zonelist, + if (COMPACTION_BUILD) { + /* + * If we already have plenty of memory free +- * for compaction, don't free any more. ++ * for compaction in this zone , don't free any ++ * more. + */ + if (sc->order > PAGE_ALLOC_COSTLY_ORDER && + (compaction_suitable(zone, sc->order) || +- compaction_deferred(zone))) ++ compaction_deferred(zone))) { ++ should_abort_reclaim = true; + continue; ++ } + } + /* + * This steals pages from memory cgroups over softlimit +@@ -2049,6 +2057,8 @@ static void shrink_zones(int priority, struct zonelist *zonelist, + + shrink_zone(priority, zone, sc); + } ++ ++ return should_abort_reclaim; + } + + static bool zone_reclaimable(struct zone *zone) +@@ -2113,7 +2123,9 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, + sc->nr_scanned = 0; + if (!priority) + disable_swap_token(sc->mem_cgroup); +- shrink_zones(priority, zonelist, sc); ++ if (shrink_zones(priority, zonelist, sc)) ++ break; ++ + /* + * Don't shrink slabs when reclaiming memory from + * over limit cgroups +-- +1.7.6.4 + diff --git a/kernel.spec b/kernel.spec index 89149b215..595aba4f0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -743,6 +743,10 @@ Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch #rhbz #722509 Patch21002: mmc-Always-check-for-lower-base-frequency-quirk-for-.patch +#rhbz #735946 +Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch +Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1366,6 +1370,10 @@ ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch # utrace. ApplyPatch utrace.patch +#rhbz #735946 +ApplyPatch 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch +ApplyPatch 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch + # END OF PATCH APPLICATIONS %endif @@ -2067,6 +2075,9 @@ fi # and build. %changelog +* Mon Oct 17 2011 Josh Boyer +- Add two patches to fix stalls in khugepaged (rhbz 735946) + * Thu Oct 13 2011 Josh Boyer - Update usb-add-quirk-for-logitech-webcams.patch with C600 ID (rhbz 742010) From c8515a48d8e1ceca12889b635fdc41fd39185250 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 18 Oct 2011 16:04:40 -0400 Subject: [PATCH 101/487] Add patch to fix invalid EFI remap calls from Matt Fleming --- kernel.spec | 6 + ...a-with-an-ioremap-address-is-invalid.patch | 211 ++++++++++++++++++ 2 files changed, 217 insertions(+) create mode 100644 x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch diff --git a/kernel.spec b/kernel.spec index 595aba4f0..3a359bd53 100644 --- a/kernel.spec +++ b/kernel.spec @@ -713,6 +713,7 @@ Patch12010: add-appleir-usb-driver.patch Patch12016: disable-i8042-check-on-apple-mac.patch Patch12021: udlfb-bind-framebuffer-to-interface.patch +Patch12022: x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch Patch12024: epoll-fix-spurious-lockdep-warnings.patch @@ -1350,6 +1351,8 @@ ApplyPatch usb-add-quirk-for-logitech-webcams.patch ApplyPatch crypto-register-cryptd-first.patch +ApplyPatch x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch + # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -2075,6 +2078,9 @@ fi # and build. %changelog +* Tue Oct 18 2011 Josh Boyer +- Add patch to fix invalid EFI remap calls from Matt Fleming + * Mon Oct 17 2011 Josh Boyer - Add two patches to fix stalls in khugepaged (rhbz 735946) diff --git a/x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch b/x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch new file mode 100644 index 000000000..f05567fe3 --- /dev/null +++ b/x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch @@ -0,0 +1,211 @@ +Path: news.gmane.org!not-for-mail +From: Matt Fleming +Newsgroups: gmane.linux.kernel +Subject: [PATCH v2] x86, efi: Calling __pa() with an ioremap'd address is invalid +Date: Fri, 14 Oct 2011 12:36:45 +0100 +Lines: 160 +Approved: news@gmane.org +Message-ID: <1318592205-11193-1-git-send-email-matt@console-pimps.org> +NNTP-Posting-Host: lo.gmane.org +X-Trace: dough.gmane.org 1318592224 30879 80.91.229.12 (14 Oct 2011 11:37:04 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Fri, 14 Oct 2011 11:37:04 +0000 (UTC) +Cc: Thomas Gleixner , Ingo Molnar , + "H. Peter Anvin" , Zhang Rui , + Huang Ying , + linux-kernel@vger.kernel.org +To: Matthew Garrett +Original-X-From: linux-kernel-owner@vger.kernel.org Fri Oct 14 13:36:59 2011 +Return-path: +Envelope-to: glk-linux-kernel-3@lo.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1REg4Q-0001UQ-SA + for glk-linux-kernel-3@lo.gmane.org; Fri, 14 Oct 2011 13:36:59 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1755420Ab1JNLgv (ORCPT ); + Fri, 14 Oct 2011 07:36:51 -0400 +Original-Received: from arkanian.console-pimps.org ([212.110.184.194]:46859 "EHLO + arkanian.console-pimps.org" rhost-flags-OK-OK-OK-OK) + by vger.kernel.org with ESMTP id S1751315Ab1JNLgu (ORCPT + ); + Fri, 14 Oct 2011 07:36:50 -0400 +Original-Received: by arkanian.console-pimps.org (Postfix, from userid 1002) + id 443C1C0009; Fri, 14 Oct 2011 12:36:49 +0100 (BST) +X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on + arkanian.vm.bytemark.co.uk +X-Spam-Level: +X-Spam-Status: No, score=-5.3 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00 + autolearn=ham version=3.2.5 +Original-Received: from localhost (02ddb86b.bb.sky.com [2.221.184.107]) + by arkanian.console-pimps.org (Postfix) with ESMTPSA id F0D40C0008; + Fri, 14 Oct 2011 12:36:47 +0100 (BST) +X-Mailer: git-send-email 1.7.4.4 +Original-Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel:1203294 +Archived-At: + +From: Matt Fleming + +If we encounter an efi_memory_desc_t without EFI_MEMORY_WB set in +->attribute we currently call set_memory_uc(), which in turn calls +__pa() on a potentially ioremap'd address. On CONFIG_X86_32 this is +invalid, resulting in the following oops, + + BUG: unable to handle kernel paging request at f7f22280 + IP: [] reserve_ram_pages_type+0x89/0x210 + *pdpt = 0000000001978001 *pde = 0000000001ffb067 *pte = 0000000000000000 + Oops: 0000 [#1] PREEMPT SMP + Modules linked in: + + Pid: 0, comm: swapper Not tainted 3.0.0-acpi-efi-0805 #3 + EIP: 0060:[] EFLAGS: 00010202 CPU: 0 + EIP is at reserve_ram_pages_type+0x89/0x210 + EAX: 0070e280 EBX: 38714000 ECX: f7814000 EDX: 00000000 + ESI: 00000000 EDI: 38715000 EBP: c189fef0 ESP: c189fea8 + DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 + Process swapper (pid: 0, ti=c189e000 task=c18bbe60 task.ti=c189e000) + Stack: + 80000200 ff108000 00000000 c189ff00 00038714 00000000 00000000 c189fed0 + c104f8ca 00038714 00000000 00038715 00000000 00000000 00038715 00000000 + 00000010 38715000 c189ff48 c1025aff 38715000 00000000 00000010 00000000 + Call Trace: + [] ? page_is_ram+0x1a/0x40 + [] reserve_memtype+0xdf/0x2f0 + [] set_memory_uc+0x49/0xa0 + [] efi_enter_virtual_mode+0x1c2/0x3aa + [] start_kernel+0x291/0x2f2 + [] ? loglevel+0x1b/0x1b + [] i386_start_kernel+0xbf/0xc8 + +So, if we're ioremap'ing an address range let's setup the mapping with +the correct caching attribute instead of modifying it after the fact. + +Also, take this opportunity to unify the 32/64-bit efi_ioremap() +implementations because they can both be implemented with +ioremap_{cache,nocache}. When asked about the original reason behind +using init_memory_mapping() for the 64-bit version Huang Ying said, + + "The intention of init_memory_mapping() usage is to make EFI virtual + address unchanged after kexec. But in fact, init_memory_mapping() + can not handle some memory range, so ioremap_xxx() is introduced as + a fix. Now we decide to use ioremap_xxx() anyway and use some other + scheme for kexec support, so init_memory_mapping() here is + unnecessary. IMHO, init_memory_mapping() is not as good as + ioremap_xxx() here." + +And because efi_ioremap() now consists of 4 lines, let's just inline +it directly into the one callsite in efi_enter_virtual_mode(). + +Cc: Thomas Gleixner +Cc: Ingo Molnar +Cc: H. Peter Anvin +Cc: Matthew Garrett +Cc: Zhang Rui +Cc: Huang Ying +Cc: stable@kernel.org +Signed-off-by: Matt Fleming +--- + arch/x86/include/asm/efi.h | 5 ----- + arch/x86/platform/efi/efi.c | 24 ++++++++++++++---------- + arch/x86/platform/efi/efi_64.c | 17 ----------------- + 3 files changed, 14 insertions(+), 32 deletions(-) + +diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h +index 7093e4a..b8d8bfc 100644 +--- a/arch/x86/include/asm/efi.h ++++ b/arch/x86/include/asm/efi.h +@@ -33,8 +33,6 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...); + #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \ + efi_call_virt(f, a1, a2, a3, a4, a5, a6) + +-#define efi_ioremap(addr, size, type) ioremap_cache(addr, size) +- + #else /* !CONFIG_X86_32 */ + + extern u64 efi_call0(void *fp); +@@ -84,9 +82,6 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3, + efi_call6((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ + (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6)) + +-extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, +- u32 type); +- + #endif /* CONFIG_X86_32 */ + + extern int add_efi_memmap; +diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c +index 3ae4128..6ea011c 100644 +--- a/arch/x86/platform/efi/efi.c ++++ b/arch/x86/platform/efi/efi.c +@@ -670,10 +670,21 @@ void __init efi_enter_virtual_mode(void) + end_pfn = PFN_UP(end); + if (end_pfn <= max_low_pfn_mapped + || (end_pfn > (1UL << (32 - PAGE_SHIFT)) +- && end_pfn <= max_pfn_mapped)) ++ && end_pfn <= max_pfn_mapped)) { + va = __va(md->phys_addr); +- else +- va = efi_ioremap(md->phys_addr, size, md->type); ++ ++ if (!(md->attribute & EFI_MEMORY_WB)) { ++ addr = (u64) (unsigned long)va; ++ npages = md->num_pages; ++ memrange_efi_to_native(&addr, &npages); ++ set_memory_uc(addr, npages); ++ } ++ } else { ++ if (!(md->attribute & EFI_MEMORY_WB)) ++ va = ioremap_nocache(md->phys_addr, size); ++ else ++ va = ioremap_cache(md->phys_addr, size); ++ } + + md->virt_addr = (u64) (unsigned long) va; + +@@ -683,13 +694,6 @@ void __init efi_enter_virtual_mode(void) + continue; + } + +- if (!(md->attribute & EFI_MEMORY_WB)) { +- addr = md->virt_addr; +- npages = md->num_pages; +- memrange_efi_to_native(&addr, &npages); +- set_memory_uc(addr, npages); +- } +- + systab = (u64) (unsigned long) efi_phys.systab; + if (md->phys_addr <= systab && systab < end) { + systab += md->virt_addr - md->phys_addr; +diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c +index ac3aa54..312250c 100644 +--- a/arch/x86/platform/efi/efi_64.c ++++ b/arch/x86/platform/efi/efi_64.c +@@ -80,20 +80,3 @@ void __init efi_call_phys_epilog(void) + local_irq_restore(efi_flags); + early_code_mapping_set_exec(0); + } +- +-void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, +- u32 type) +-{ +- unsigned long last_map_pfn; +- +- if (type == EFI_MEMORY_MAPPED_IO) +- return ioremap(phys_addr, size); +- +- last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size); +- if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size) { +- unsigned long top = last_map_pfn << PAGE_SHIFT; +- efi_ioremap(top, size - (top - phys_addr), type); +- } +- +- return (void __iomem *)__va(phys_addr); +-} +-- +1.7.4.4 + From f73c1196beec64a5513d437be11d82540c859046 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Tue, 18 Oct 2011 17:09:23 -0400 Subject: [PATCH 102/487] Fix lock inversion causing hangs in 3.1-rc9 (rhbz #746485) --- cputimer-cure-lock-inversion.patch | 73 ++++++++++++++++++++++++++++++ kernel.spec | 9 ++++ 2 files changed, 82 insertions(+) create mode 100644 cputimer-cure-lock-inversion.patch diff --git a/cputimer-cure-lock-inversion.patch b/cputimer-cure-lock-inversion.patch new file mode 100644 index 000000000..cebb775bf --- /dev/null +++ b/cputimer-cure-lock-inversion.patch @@ -0,0 +1,73 @@ +Subject: cputimer: Cure lock inversion +From: Peter Zijlstra +Date: Mon Oct 17 11:50:30 CEST 2011 + +There's a lock inversion between the cputimer->lock and rq->lock; notably +the two callchains involved are: + + update_rlimit_cpu() + sighand->siglock + set_process_cpu_timer() + cpu_timer_sample_group() + thread_group_cputimer() + cputimer->lock + thread_group_cputime() + task_sched_runtime() + ->pi_lock + rq->lock + + scheduler_tick() + rq->lock + task_tick_fair() + update_curr() + account_group_exec() + cputimer->lock + +Where the first one is enabling a CLOCK_PROCESS_CPUTIME_ID timer, and +the second one is keeping up-to-date. + +This problem was introduced by e8abccb7193 ("posix-cpu-timers: Cure +SMP accounting oddities"). + +Cure the problem by removing the cputimer->lock and rq->lock nesting, +this leaves concurrent enablers doing duplicate work, but the time +wasted should be on the same order otherwise wasted spinning on the +lock and the greater-than assignment filter should ensure we preserve +monotonicity. + +Reported-by: Dave Jones +Reported-by: Simon Kirby +Cc: stable@kernel.org +Cc: Thomas Gleixner +Signed-off-by: Peter Zijlstra +--- + kernel/posix-cpu-timers.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) +Index: linux-2.6/kernel/posix-cpu-timers.c +=================================================================== +--- linux-2.6.orig/kernel/posix-cpu-timers.c ++++ linux-2.6/kernel/posix-cpu-timers.c +@@ -274,9 +274,7 @@ void thread_group_cputimer(struct task_s + struct task_cputime sum; + unsigned long flags; + +- spin_lock_irqsave(&cputimer->lock, flags); + if (!cputimer->running) { +- cputimer->running = 1; + /* + * The POSIX timer interface allows for absolute time expiry + * values through the TIMER_ABSTIME flag, therefore we have +@@ -284,8 +282,11 @@ void thread_group_cputimer(struct task_s + * it. + */ + thread_group_cputime(tsk, &sum); ++ spin_lock_irqsave(&cputimer->lock, flags); ++ cputimer->running = 1; + update_gt_cputime(&cputimer->cputime, &sum); +- } ++ } else ++ spin_lock_irqsave(&cputimer->lock, flags); + *times = cputimer->cputime; + spin_unlock_irqrestore(&cputimer->lock, flags); + } + diff --git a/kernel.spec b/kernel.spec index 3a359bd53..808e1049c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -748,6 +748,9 @@ Patch21002: mmc-Always-check-for-lower-base-frequency-quirk-for-.patch Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch +# rhbz #746485 +Patch21030: cputimer-cure-lock-inversion.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1377,6 +1380,9 @@ ApplyPatch utrace.patch ApplyPatch 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch ApplyPatch 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch +# rhbz #746485 +ApplyPatch cputimer-cure-lock-inversion.patch + # END OF PATCH APPLICATIONS %endif @@ -2078,6 +2084,9 @@ fi # and build. %changelog +* Tue Oct 18 2011 Chuck Ebbert +- Fix lock inversion causing hangs in 3.1-rc9 (rhbz #746485) + * Tue Oct 18 2011 Josh Boyer - Add patch to fix invalid EFI remap calls from Matt Fleming From 4933c2453d3d8ad5d98821274b8b809be33a8376 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Tue, 18 Oct 2011 20:03:13 -0400 Subject: [PATCH 103/487] Linux 3.1-rc10 --- kernel.spec | 5 +++-- sources | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 808e1049c..f9167ba04 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 3 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -82,7 +82,7 @@ Summary: The Linux kernel # The next upstream release sublevel (base_sublevel+1) %define upstream_sublevel %(echo $((%{base_sublevel} + 1))) # The rc snapshot level -%define rcrev 9 +%define rcrev 10 # The git snapshot level %define gitrev 0 # Set rpm version accordingly @@ -2086,6 +2086,7 @@ fi %changelog * Tue Oct 18 2011 Chuck Ebbert - Fix lock inversion causing hangs in 3.1-rc9 (rhbz #746485) +- Linux 3.1-rc10 * Tue Oct 18 2011 Josh Boyer - Add patch to fix invalid EFI remap calls from Matt Fleming diff --git a/sources b/sources index e509d0145..b3a7cb26e 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 -85fd0d4c9701392b6eb9293035726a02 patch-3.1-rc9.bz2 +6a91efe6505579a181c5f5e1a68f6c3a patch-3.1-rc10.bz2 From 5cfb71ce9c1b7de54c03cf9f0ae59ada59728fe7 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 19 Oct 2011 00:39:47 -0400 Subject: [PATCH 104/487] Fix divide-by-zero in nouveau driver (rhbz #747129) --- drm-nouveau-updates-fix-nv40-pm.patch | 24 ++++++++++++++++++++++++ kernel.spec | 7 +++++++ 2 files changed, 31 insertions(+) create mode 100644 drm-nouveau-updates-fix-nv40-pm.patch diff --git a/drm-nouveau-updates-fix-nv40-pm.patch b/drm-nouveau-updates-fix-nv40-pm.patch new file mode 100644 index 000000000..16adf20dd --- /dev/null +++ b/drm-nouveau-updates-fix-nv40-pm.patch @@ -0,0 +1,24 @@ +diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c +index 9b5cbb4..73dfdff 100644 +--- a/drivers/gpu/drm/nouveau/nv40_pm.c ++++ b/drivers/gpu/drm/nouveau/nv40_pm.c +@@ -57,12 +57,14 @@ read_pll_2(struct drm_device *dev, u32 reg) + int P = (ctrl & 0x00070000) >> 16; + u32 ref = 27000, clk = 0; + +- if (ctrl & 0x80000000) ++ if ((ctrl & 0x80000000) && M1) { + clk = ref * N1 / M1; +- +- if (!(ctrl & 0x00000100)) { +- if (ctrl & 0x40000000) +- clk = clk * N2 / M2; ++ if ((ctrl & 0x40000100) == 0x40000000) { ++ if (M2) ++ clk = clk * N2 / M2; ++ else ++ clk = 0; ++ } + } + + return clk >> P; diff --git a/kernel.spec b/kernel.spec index f9167ba04..4613f7e1f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -680,6 +680,8 @@ Patch1500: fix_xen_guest_on_old_EC2.patch # nouveau + drm fixes Patch1810: drm-nouveau-updates.patch +# fix divide by zero (rhbz #747129) +Patch1811: drm-nouveau-updates-fix-nv40-pm.patch # intel drm is all merged upstream Patch1824: drm-intel-next.patch # make sure the lvds comes back on lid open @@ -1320,6 +1322,8 @@ ApplyPatch fix_xen_guest_on_old_EC2.patch # Nouveau DRM ApplyOptionalPatch drm-nouveau-updates.patch +# fix divide by zero (rhbz #747129) +ApplyPatch drm-nouveau-updates-fix-nv40-pm.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch @@ -2084,6 +2088,9 @@ fi # and build. %changelog +* Wed Oct 19 2011 Chuck Ebbert 3.1.0-0.rc10.git0.1 +- Fix divide-by-zero in nouveau driver (rhbz #747129) + * Tue Oct 18 2011 Chuck Ebbert - Fix lock inversion causing hangs in 3.1-rc9 (rhbz #746485) - Linux 3.1-rc10 From bb076be5901a704b5bbaf9c0a026c9325160e8df Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 19 Oct 2011 14:48:18 +1000 Subject: [PATCH 105/487] More complete fix for rhbz#747129 --- drm-nouveau-updates-fix-nv40-pm.patch | 24 ------------------------ drm-nouveau-updates.patch | 24 +++++++++++++++++------- kernel.spec | 4 ---- 3 files changed, 17 insertions(+), 35 deletions(-) delete mode 100644 drm-nouveau-updates-fix-nv40-pm.patch diff --git a/drm-nouveau-updates-fix-nv40-pm.patch b/drm-nouveau-updates-fix-nv40-pm.patch deleted file mode 100644 index 16adf20dd..000000000 --- a/drm-nouveau-updates-fix-nv40-pm.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c -index 9b5cbb4..73dfdff 100644 ---- a/drivers/gpu/drm/nouveau/nv40_pm.c -+++ b/drivers/gpu/drm/nouveau/nv40_pm.c -@@ -57,12 +57,14 @@ read_pll_2(struct drm_device *dev, u32 reg) - int P = (ctrl & 0x00070000) >> 16; - u32 ref = 27000, clk = 0; - -- if (ctrl & 0x80000000) -+ if ((ctrl & 0x80000000) && M1) { - clk = ref * N1 / M1; -- -- if (!(ctrl & 0x00000100)) { -- if (ctrl & 0x40000000) -- clk = clk * N2 / M2; -+ if ((ctrl & 0x40000100) == 0x40000000) { -+ if (M2) -+ clk = clk * N2 / M2; -+ else -+ clk = 0; -+ } - } - - return clk >> P; diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index d311d860d..1e7c9279e 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -5146,10 +5146,10 @@ index ad03a0e..0000000 -} diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c new file mode 100644 -index 0000000..bbc0b9c +index 0000000..e676b0d --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv40_pm.c -@@ -0,0 +1,338 @@ +@@ -0,0 +1,348 @@ +/* + * Copyright 2011 Red Hat Inc. + * @@ -5209,12 +5209,14 @@ index 0000000..bbc0b9c + int P = (ctrl & 0x00070000) >> 16; + u32 ref = 27000, clk = 0; + -+ if (ctrl & 0x80000000) ++ if ((ctrl & 0x80000000) && M1) { + clk = ref * N1 / M1; -+ -+ if (!(ctrl & 0x00000100)) { -+ if (ctrl & 0x40000000) -+ clk = clk * N2 / M2; ++ if ((ctrl & 0x40000100) == 0x40000000) { ++ if (M2) ++ clk = clk * N2 / M2; ++ else ++ clk = 0; ++ } + } + + return clk >> P; @@ -5329,6 +5331,11 @@ index 0000000..bbc0b9c + } + + /* memory clock */ ++ if (!perflvl->memory) { ++ info->mpll_ctrl = 0x00000000; ++ goto out; ++ } ++ + ret = nv40_calc_pll(dev, 0x004020, &pll, perflvl->memory, + &N1, &M1, &N2, &M2, &log2P); + if (ret < 0) @@ -5416,6 +5423,9 @@ index 0000000..bbc0b9c + mdelay(5); + nv_mask(dev, 0x00c040, 0x00000333, info->ctrl); + ++ if (!info->mpll_ctrl) ++ goto resume; ++ + /* wait for vblank start on active crtcs, disable memory access */ + for (i = 0; i < 2; i++) { + if (!(crtc_mask & (1 << i))) diff --git a/kernel.spec b/kernel.spec index 4613f7e1f..5bb627a8c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -680,8 +680,6 @@ Patch1500: fix_xen_guest_on_old_EC2.patch # nouveau + drm fixes Patch1810: drm-nouveau-updates.patch -# fix divide by zero (rhbz #747129) -Patch1811: drm-nouveau-updates-fix-nv40-pm.patch # intel drm is all merged upstream Patch1824: drm-intel-next.patch # make sure the lvds comes back on lid open @@ -1322,8 +1320,6 @@ ApplyPatch fix_xen_guest_on_old_EC2.patch # Nouveau DRM ApplyOptionalPatch drm-nouveau-updates.patch -# fix divide by zero (rhbz #747129) -ApplyPatch drm-nouveau-updates-fix-nv40-pm.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch From 65525f70c42f380460effaaf857d6a3663fa02de Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 19 Oct 2011 13:23:28 -0400 Subject: [PATCH 106/487] Add Sony VGN-FW21E to nonvs blacklist. (rhbz 641789) --- acpi-sony-nonvs-blacklist.patch | 19 +++++++++++++++++++ kernel.spec | 5 +++++ 2 files changed, 24 insertions(+) create mode 100644 acpi-sony-nonvs-blacklist.patch diff --git a/acpi-sony-nonvs-blacklist.patch b/acpi-sony-nonvs-blacklist.patch new file mode 100644 index 000000000..f332c6443 --- /dev/null +++ b/acpi-sony-nonvs-blacklist.patch @@ -0,0 +1,19 @@ +diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c +index 3ed80b2..17fc718 100644 +--- a/drivers/acpi/sleep.c ++++ b/drivers/acpi/sleep.c +@@ -390,6 +390,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { + }, + { + .callback = init_nvs_nosave, ++ .ident = "Sony Vaio VGN-FW21E", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"), ++ }, ++ }, ++ { ++ .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-SR11M", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), diff --git a/kernel.spec b/kernel.spec index 5bb627a8c..b2d4d0294 100644 --- a/kernel.spec +++ b/kernel.spec @@ -656,6 +656,7 @@ Patch390: linux-2.6-defaults-acpi-video.patch Patch391: linux-2.6-acpi-video-dos.patch Patch394: linux-2.6-acpi-debug-infinite-loop.patch Patch395: acpi-ensure-thermal-limits-match-cpu-freq.patch +Patch396: acpi-sony-nonvs-blacklist.patch Patch450: linux-2.6-input-kill-stupid-messages.patch Patch452: linux-2.6.30-no-pcspkr-modalias.patch @@ -1263,6 +1264,7 @@ ApplyPatch linux-2.6-defaults-acpi-video.patch ApplyPatch linux-2.6-acpi-video-dos.patch ApplyPatch linux-2.6-acpi-debug-infinite-loop.patch ApplyPatch acpi-ensure-thermal-limits-match-cpu-freq.patch +ApplyPatch acpi-sony-nonvs-blacklist.patch # Various low-impact patches to aid debugging. ApplyPatch linux-2.6-debug-taint-vm.patch @@ -2084,6 +2086,9 @@ fi # and build. %changelog +* Wed Oct 19 2011 Dave Jones +- Add Sony VGN-FW21E to nonvs blacklist. (rhbz 641789) + * Wed Oct 19 2011 Chuck Ebbert 3.1.0-0.rc10.git0.1 - Fix divide-by-zero in nouveau driver (rhbz #747129) From 5bbdbe628c83e1e0a6aa180db2716ad994a0ac3f Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 21 Oct 2011 13:01:26 -0400 Subject: [PATCH 107/487] Lower severity of Radeon lockup messages. --- drm-lower-severity-radeon-lockup.diff | 13 +++++++++++++ kernel.spec | 8 ++++++++ 2 files changed, 21 insertions(+) create mode 100644 drm-lower-severity-radeon-lockup.diff diff --git a/drm-lower-severity-radeon-lockup.diff b/drm-lower-severity-radeon-lockup.diff new file mode 100644 index 000000000..1302c92ea --- /dev/null +++ b/drm-lower-severity-radeon-lockup.diff @@ -0,0 +1,13 @@ +diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c +index 7fd4e3e..a488b50 100644 +--- a/drivers/gpu/drm/radeon/radeon_fence.c ++++ b/drivers/gpu/drm/radeon/radeon_fence.c +@@ -263,7 +263,7 @@ retry: + */ + if (seq == rdev->fence_drv.last_seq && radeon_gpu_is_lockup(rdev)) { + /* good news we believe it's a lockup */ +- WARN(1, "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n", ++ printk(KERN_WARNING "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n", + fence->seq, seq); + /* FIXME: what should we do ? marking everyone + * as signaled for now diff --git a/kernel.spec b/kernel.spec index b2d4d0294..bce645d85 100644 --- a/kernel.spec +++ b/kernel.spec @@ -690,6 +690,8 @@ Patch1826: drm-i915-fbc-stfu.patch # rhbz#729882, https://bugs.freedesktop.org/attachment.cgi?id=49069 Patch1827: drm-i915-sdvo-lvds-is-digital.patch +Patch1850: drm-lower-severity-radeon-lockup.diff + Patch1900: linux-2.6-intel-iommu-igfx.patch # Quiet boot fixes @@ -1328,6 +1330,9 @@ ApplyOptionalPatch drm-intel-next.patch ApplyPatch drm-intel-make-lvds-work.patch ApplyPatch drm-i915-fbc-stfu.patch ApplyPatch drm-i915-sdvo-lvds-is-digital.patch + +ApplyPatch drm-lower-severity-radeon-lockup.diff + ApplyPatch linux-2.6-intel-iommu-igfx.patch # silence the ACPI blacklist code @@ -2086,6 +2091,9 @@ fi # and build. %changelog +* Fri Oct 21 2011 Dave Jones +- Lower severity of Radeon lockup messages. + * Wed Oct 19 2011 Dave Jones - Add Sony VGN-FW21E to nonvs blacklist. (rhbz 641789) From 138bbe4bb3cc4c508b61a45ec6689429d524f1eb Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 21 Oct 2011 15:35:54 -0400 Subject: [PATCH 108/487] Update to upstream HEAD (v3.1-rc10-42-g2efd7c0) --- cputimer-cure-lock-inversion.patch | 73 --- kernel.spec | 11 +- patch-3.1-rc10-git1.log | 804 +++++++++++++++++++++++++++++ sources | 1 + 4 files changed, 809 insertions(+), 80 deletions(-) delete mode 100644 cputimer-cure-lock-inversion.patch create mode 100644 patch-3.1-rc10-git1.log diff --git a/cputimer-cure-lock-inversion.patch b/cputimer-cure-lock-inversion.patch deleted file mode 100644 index cebb775bf..000000000 --- a/cputimer-cure-lock-inversion.patch +++ /dev/null @@ -1,73 +0,0 @@ -Subject: cputimer: Cure lock inversion -From: Peter Zijlstra -Date: Mon Oct 17 11:50:30 CEST 2011 - -There's a lock inversion between the cputimer->lock and rq->lock; notably -the two callchains involved are: - - update_rlimit_cpu() - sighand->siglock - set_process_cpu_timer() - cpu_timer_sample_group() - thread_group_cputimer() - cputimer->lock - thread_group_cputime() - task_sched_runtime() - ->pi_lock - rq->lock - - scheduler_tick() - rq->lock - task_tick_fair() - update_curr() - account_group_exec() - cputimer->lock - -Where the first one is enabling a CLOCK_PROCESS_CPUTIME_ID timer, and -the second one is keeping up-to-date. - -This problem was introduced by e8abccb7193 ("posix-cpu-timers: Cure -SMP accounting oddities"). - -Cure the problem by removing the cputimer->lock and rq->lock nesting, -this leaves concurrent enablers doing duplicate work, but the time -wasted should be on the same order otherwise wasted spinning on the -lock and the greater-than assignment filter should ensure we preserve -monotonicity. - -Reported-by: Dave Jones -Reported-by: Simon Kirby -Cc: stable@kernel.org -Cc: Thomas Gleixner -Signed-off-by: Peter Zijlstra ---- - kernel/posix-cpu-timers.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) -Index: linux-2.6/kernel/posix-cpu-timers.c -=================================================================== ---- linux-2.6.orig/kernel/posix-cpu-timers.c -+++ linux-2.6/kernel/posix-cpu-timers.c -@@ -274,9 +274,7 @@ void thread_group_cputimer(struct task_s - struct task_cputime sum; - unsigned long flags; - -- spin_lock_irqsave(&cputimer->lock, flags); - if (!cputimer->running) { -- cputimer->running = 1; - /* - * The POSIX timer interface allows for absolute time expiry - * values through the TIMER_ABSTIME flag, therefore we have -@@ -284,8 +282,11 @@ void thread_group_cputimer(struct task_s - * it. - */ - thread_group_cputime(tsk, &sum); -+ spin_lock_irqsave(&cputimer->lock, flags); -+ cputimer->running = 1; - update_gt_cputime(&cputimer->cputime, &sum); -- } -+ } else -+ spin_lock_irqsave(&cputimer->lock, flags); - *times = cputimer->cputime; - spin_unlock_irqrestore(&cputimer->lock, flags); - } - diff --git a/kernel.spec b/kernel.spec index bce645d85..0b3ad138d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -84,7 +84,7 @@ Summary: The Linux kernel # The rc snapshot level %define rcrev 10 # The git snapshot level -%define gitrev 0 +%define gitrev 1 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -751,9 +751,6 @@ Patch21002: mmc-Always-check-for-lower-base-frequency-quirk-for-.patch Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch -# rhbz #746485 -Patch21030: cputimer-cure-lock-inversion.patch - %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1387,9 +1384,6 @@ ApplyPatch utrace.patch ApplyPatch 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch ApplyPatch 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch -# rhbz #746485 -ApplyPatch cputimer-cure-lock-inversion.patch - # END OF PATCH APPLICATIONS %endif @@ -2091,6 +2085,9 @@ fi # and build. %changelog +* Fri Oct 21 2011 Chuck Ebbert +- Update to upstream HEAD (v3.1-rc10-42-g2efd7c0) + * Fri Oct 21 2011 Dave Jones - Lower severity of Radeon lockup messages. diff --git a/patch-3.1-rc10-git1.log b/patch-3.1-rc10-git1.log new file mode 100644 index 000000000..ba8dfd171 --- /dev/null +++ b/patch-3.1-rc10-git1.log @@ -0,0 +1,804 @@ +commit 2efd7c0fdcbe041173e248ccc2d9c91df7f84ce5 +Merge: 62ddc00 7ed47b7 +Author: Linus Torvalds +Date: Fri Oct 21 17:02:18 2011 +0300 + + Merge git://github.com/herbertx/crypto + + * git://github.com/herbertx/crypto: + crypto: ghash - Avoid null pointer dereference if no key is set + +commit 62ddc0046eae6b8e8374f0ac3b27b12a57baa2f6 +Merge: fd11e15 ca201c0 +Author: Linus Torvalds +Date: Fri Oct 21 17:01:21 2011 +0300 + + Merge branch 'fix/hda' of git://github.com/tiwai/sound + + * 'fix/hda' of git://github.com/tiwai/sound: + ALSA: HDA: conexant support for Lenovo T520/W520 + ALSA: hda - Add position_fix quirk for Dell Inspiron 1010 + +commit 7ed47b7d142ec99ad6880bbbec51e9f12b3af74c +Author: Nick Bowler +Date: Thu Oct 20 14:16:55 2011 +0200 + + crypto: ghash - Avoid null pointer dereference if no key is set + + The ghash_update function passes a pointer to gf128mul_4k_lle which will + be NULL if ghash_setkey is not called or if the most recent call to + ghash_setkey failed to allocate memory. This causes an oops. Fix this + up by returning an error code in the null case. + + This is trivially triggered from unprivileged userspace through the + AF_ALG interface by simply writing to the socket without setting a key. + + The ghash_final function has a similar issue, but triggering it requires + a memory allocation failure in ghash_setkey _after_ at least one + successful call to ghash_update. + + BUG: unable to handle kernel NULL pointer dereference at 00000670 + IP: [] gf128mul_4k_lle+0x23/0x60 [gf128mul] + *pde = 00000000 + Oops: 0000 [#1] PREEMPT SMP + Modules linked in: ghash_generic gf128mul algif_hash af_alg nfs lockd nfs_acl sunrpc bridge ipv6 stp llc + + Pid: 1502, comm: hashatron Tainted: G W 3.1.0-rc9-00085-ge9308cf #32 Bochs Bochs + EIP: 0060:[] EFLAGS: 00000202 CPU: 0 + EIP is at gf128mul_4k_lle+0x23/0x60 [gf128mul] + EAX: d69db1f0 EBX: d6b8ddac ECX: 00000004 EDX: 00000000 + ESI: 00000670 EDI: d6b8ddac EBP: d6b8ddc8 ESP: d6b8dda4 + DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 + Process hashatron (pid: 1502, ti=d6b8c000 task=d6810000 task.ti=d6b8c000) + Stack: + 00000000 d69db1f0 00000163 00000000 d6b8ddc8 c101a520 d69db1f0 d52aa000 + 00000ff0 d6b8dde8 d88d310f d6b8a3f8 d52aa000 00001000 d88d502c d6b8ddfc + 00001000 d6b8ddf4 c11676ed d69db1e8 d6b8de24 c11679ad d52aa000 00000000 + Call Trace: + [] ? kmap_atomic_prot+0x37/0xa6 + [] ghash_update+0x85/0xbe [ghash_generic] + [] crypto_shash_update+0x18/0x1b + [] shash_ahash_update+0x22/0x36 + [] shash_async_update+0xb/0xd + [] hash_sendpage+0xba/0xf2 [algif_hash] + [] kernel_sendpage+0x39/0x4e + [] ? 0xd88cdfff + [] sock_sendpage+0x37/0x3e + [] ? kernel_sendpage+0x4e/0x4e + [] pipe_to_sendpage+0x56/0x61 + [] splice_from_pipe_feed+0x58/0xcd + [] ? splice_from_pipe_begin+0x10/0x10 + [] __splice_from_pipe+0x36/0x55 + [] ? splice_from_pipe_begin+0x10/0x10 + [] splice_from_pipe+0x51/0x64 + [] ? default_file_splice_write+0x2c/0x2c + [] generic_splice_sendpage+0x13/0x15 + [] ? splice_from_pipe_begin+0x10/0x10 + [] do_splice_from+0x5d/0x67 + [] sys_splice+0x2bf/0x363 + [] ? sysenter_exit+0xf/0x16 + [] ? trace_hardirqs_on_caller+0x10e/0x13f + [] sysenter_do_call+0x12/0x32 + Code: 83 c4 0c 5b 5e 5f c9 c3 55 b9 04 00 00 00 89 e5 57 8d 7d e4 56 53 8d 5d e4 83 ec 18 89 45 e0 89 55 dc 0f b6 70 0f c1 e6 04 01 d6 a5 be 0f 00 00 00 4e 89 d8 e8 48 ff ff ff 8b 45 e0 89 da 0f + EIP: [] gf128mul_4k_lle+0x23/0x60 [gf128mul] SS:ESP 0068:d6b8dda4 + CR2: 0000000000000670 + ---[ end trace 4eaa2a86a8e2da24 ]--- + note: hashatron[1502] exited with preempt_count 1 + BUG: scheduling while atomic: hashatron/1502/0x10000002 + INFO: lockdep is turned off. + [...] + + Signed-off-by: Nick Bowler + Cc: stable@kernel.org [2.6.37+] + Signed-off-by: Herbert Xu + +commit fd11e153b82ad1c84ccc71ba1cfedc222465198c +Merge: 505f48b aad4564 +Author: Linus Torvalds +Date: Thu Oct 20 22:16:28 2011 +0300 + + Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc + + * git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc: + sparc: Add alignment flag to PCI expansion resources + sparc: Avoid calling sigprocmask() + sparc: Use set_current_blocked() + sparc32,leon: SRMMU MMU Table probe fix + +commit 505f48b53478d3816d1f3b001815703cfd7afa09 +Merge: 486cf46 afaef73 +Author: Linus Torvalds +Date: Thu Oct 20 22:15:20 2011 +0300 + + Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net + + * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: + fib_rules: fix unresolved_rules counting + r8169: fix wrong eee setting for rlt8111evl + r8169: fix driver shutdown WoL regression. + ehea: Change maintainer to me + pptp: pptp_rcv_core() misses pskb_may_pull() call + tproxy: copy transparent flag when creating a time wait + pptp: fix skb leak in pptp_xmit() + bonding: use local function pointer of bond->recv_probe in bond_handle_frame + smsc911x: Add support for SMSC LAN89218 + tg3: negate USE_PHYLIB flag check + netconsole: enable netconsole can make net_device refcnt incorrent + bluetooth: Properly clone LSM attributes to newly created child connections + l2tp: fix a potential skb leak in l2tp_xmit_skb() + bridge: fix hang on removal of bridge via netlink + x25: Prevent skb overreads when checking call user data + x25: Handle undersized/fragmented skbs + x25: Validate incoming call user data lengths + udplite: fast-path computation of checksum coverage + IPVS netns shutdown/startup dead-lock + netfilter: nf_conntrack: fix event flooding in GRE protocol tracker + +commit 486cf46f3f9be5f2a966016c1a8fe01e32cde09e +Author: Hugh Dickins +Date: Wed Oct 19 12:50:35 2011 -0700 + + mm: fix race between mremap and removing migration entry + + I don't usually pay much attention to the stale "? " addresses in + stack backtraces, but this lucky report from Pawel Sikora hints that + mremap's move_ptes() has inadequate locking against page migration. + + 3.0 BUG_ON(!PageLocked(p)) in migration_entry_to_page(): + kernel BUG at include/linux/swapops.h:105! + RIP: 0010:[] [] + migration_entry_wait+0x156/0x160 + [] handle_pte_fault+0xae1/0xaf0 + [] ? __pte_alloc+0x42/0x120 + [] ? do_huge_pmd_anonymous_page+0xab/0x310 + [] handle_mm_fault+0x181/0x310 + [] ? vma_adjust+0x537/0x570 + [] do_page_fault+0x11d/0x4e0 + [] ? do_mremap+0x2d5/0x570 + [] page_fault+0x1f/0x30 + + mremap's down_write of mmap_sem, together with i_mmap_mutex or lock, + and pagetable locks, were good enough before page migration (with its + requirement that every migration entry be found) came in, and enough + while migration always held mmap_sem; but not enough nowadays, when + there's memory hotremove and compaction. + + The danger is that move_ptes() lets a migration entry dodge around + behind remove_migration_pte()'s back, so it's in the old location when + looking at the new, then in the new location when looking at the old. + + Either mremap's move_ptes() must additionally take anon_vma lock(), or + migration's remove_migration_pte() must stop peeking for is_swap_entry() + before it takes pagetable lock. + + Consensus chooses the latter: we prefer to add overhead to migration + than to mremapping, which gets used by JVMs and by exec stack setup. + + Reported-and-tested-by: Paweł Sikora + Signed-off-by: Hugh Dickins + Acked-by: Andrea Arcangeli + Acked-by: Mel Gorman + Cc: stable@vger.kernel.org + Signed-off-by: Linus Torvalds + +commit aad4564498dcb0aad769a79e5e2aa9a661dfb51f +Author: Kjetil Oftedal +Date: Wed Oct 19 16:20:50 2011 -0700 + + sparc: Add alignment flag to PCI expansion resources + + Currently no type of alignment is specified for PCI expansion roms while + parsing the openfirmware tree. This causes calls to pci_map_rom() to fail. + IORESOURCE_SIZEALIGN is the default alignment used for rom resouces in + pci/probe.c, and has been verified to work with various cards on a ultra 10. + + Signed-off-By: Kjetil Oftedal + Signed-off-by: David S. Miller + +commit afaef734e5f0004916d07ecf7d86292cdd00d59b +Author: Yan, Zheng +Date: Mon Oct 17 15:20:28 2011 +0000 + + fib_rules: fix unresolved_rules counting + + we should decrease ops->unresolved_rules when deleting a unresolved rule. + + Signed-off-by: Zheng Yan + Acked-by: Eric Dumazet + Signed-off-by: David S. Miller + +commit 1b23a3e3d1b969e285c57a2d38f3739283ecfb80 +Author: hayeswang +Date: Thu Oct 13 20:14:37 2011 +0000 + + r8169: fix wrong eee setting for rlt8111evl + + Correct the wrong parameter for setting EEE for RTL8111E-VL. + + Signed-off-by: Hayes Wang + Signed-off-by: David S. Miller + +commit 649b3b8c4e8681de443b4dc9e387c3036369e02e +Author: françois romieu +Date: Fri Oct 14 00:57:45 2011 +0000 + + r8169: fix driver shutdown WoL regression. + + Due to commit 92fc43b4159b518f5baae57301f26d770b0834c9 ("r8169: modify the + flow of the hw reset."), rtl8169_hw_reset stomps during driver shutdown on + RxConfig bits which are needed for WOL on some versions of the hardware. + + As these bits were formerly set from the r81{0x, 68}_pll_power_down methods, + factor them out for use in the driver shutdown (rtl_shutdown) handler. + + I favored __rtl8169_get_wol() -hardware state indication- over + RTL_FEATURE_WOL as the latter has become a good candidate for removal. + + Signed-off-by: Francois Romieu + Cc: Hayes + Tested-by: Marc Ballarin + Signed-off-by: David S. Miller + +commit 34b1901abdf8793cd679d0e48012d3d7570f88d6 +Author: Thadeu Lima de Souza Cascardo +Date: Thu Oct 13 09:56:19 2011 +0000 + + ehea: Change maintainer to me + + Breno Leitao has passed the maintainership to me. + + Signed-off-by: Thadeu Lima de Souza Cascardo + Cc: Breno Leitao + Acked-by: Breno Leitão + Signed-off-by: David S. Miller + +commit e4fcd69c9e4e273352e0f87cabd9648606da0c3e +Merge: f91f6cf e58fced +Author: Linus Torvalds +Date: Wed Oct 19 06:44:11 2011 -0700 + + Merge branch 'v4l_for_linus' of git://linuxtv.org/mchehab/for_linus + + * 'v4l_for_linus' of git://linuxtv.org/mchehab/for_linus: + [media] videodev: fix a NULL pointer dereference in v4l2_device_release() + +commit f91f6cfd4f9ea794dc3d0bbd54cb1d29d6ef3843 +Merge: bcd5cff 5a6e848 +Author: Linus Torvalds +Date: Wed Oct 19 06:43:24 2011 -0700 + + Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux + + * 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: + drm/radeon/kms/atom: fix handling of FB scratch indices + drm/radeon/kms/DCE4.1: fix Select_CrtcSource EncodeMode setting for DP bridges (v2) + drm/radeon/kms/DCE4.1: ss is not supported on the internal pplls + drm/radeon/kms/DCE4.1: fix dig encoder to transmitter mapping + ttm: Fix error-path using an uninitialized value + +commit e58fced201ad6e6cb673f07499919c3b20792d94 +Author: Antonio Ospite +Date: Wed Oct 12 17:59:26 2011 -0300 + + [media] videodev: fix a NULL pointer dereference in v4l2_device_release() + + The change in 8280b66 does not cover the case when v4l2_dev is already + NULL, fix that. + + With a Kinect sensor, seen as an USB camera using GSPCA in this context, + a NULL pointer dereference BUG can be triggered by just unplugging the + device after the camera driver has been loaded. + + Signed-off-by: Antonio Ospite + Signed-off-by: Mauro Carvalho Chehab + +commit 5a6e8482a16e61250a9121fc9ec719ab0529e760 +Author: Alex Deucher +Date: Tue Oct 18 20:10:05 2011 -0400 + + drm/radeon/kms/atom: fix handling of FB scratch indices + + FB scratch indices are dword indices, but we were treating + them as byte indices. As such, we were getting the wrong + FB scratch data for non-0 indices. Fix the indices and + guard the indexing against indices larger than the scratch + allocation. + + Fixes memory corruption on some boards if data was written + past the end of the FB scratch array. + + Signed-off-by: Alex Deucher + Reported-by: Dave Airlie + Tested-by: Dave Airlie + Cc: stable@kernel.org + Signed-off-by: Dave Airlie + +commit 4ea2739ea89883ddf79980a8aa27d5e57093e464 +Author: Eric Dumazet +Date: Mon Oct 17 17:59:53 2011 +0000 + + pptp: pptp_rcv_core() misses pskb_may_pull() call + + e1000e uses paged frags, so any layer incorrectly pulling bytes from skb + can trigger a BUG in skb_pull() + + [951.142737] [] skb_pull+0x15/0x17 + [951.142737] [] pptp_rcv_core+0x126/0x19a [pptp] + [951.152725] [] sk_receive_skb+0x69/0x105 + [951.163558] [] pptp_rcv+0xc8/0xdc [pptp] + [951.165092] [] gre_rcv+0x62/0x75 [gre] + [951.165092] [] ip_local_deliver_finish+0x150/0x1c1 + [951.177599] [] ? ip_local_deliver_finish+0x0/0x1c1 + [951.177599] [] NF_HOOK.clone.7+0x51/0x58 + [951.177599] [] ip_local_deliver+0x51/0x55 + [951.177599] [] ip_rcv_finish+0x31a/0x33e + [951.177599] [] ? ip_rcv_finish+0x0/0x33e + [951.204898] [] NF_HOOK.clone.7+0x51/0x58 + [951.214651] [] ip_rcv+0x21b/0x246 + + pptp_rcv_core() is a nice example of a function assuming everything it + needs is available in skb head. + + Reported-by: Bradley Peterson + Signed-off-by: Eric Dumazet + Signed-off-by: David S. Miller + +commit 58af19e387d8821927e49be3f467da5e6a0aa8fd +Author: KOVACS Krisztian +Date: Tue Oct 18 10:17:35 2011 +0000 + + tproxy: copy transparent flag when creating a time wait + + The transparent socket option setting was not copied to the time wait + socket when an inet socket was being replaced by a time wait socket. This + broke the --transparent option of the socket match and may have caused + that FIN packets belonging to sockets in FIN_WAIT2 or TIME_WAIT state + were being dropped by the packet filter. + + Signed-off-by: KOVACS Krisztian + Signed-off-by: David S. Miller + +commit 8bae8bd6cb24eecad9fda3e125d36ab9c67d3fd7 +Author: Eric Dumazet +Date: Mon Oct 17 17:01:47 2011 +0000 + + pptp: fix skb leak in pptp_xmit() + + In case we cant transmit skb, we must free it + + Signed-off-by: Eric Dumazet + CC: Dmitry Kozlov + Signed-off-by: David S. Miller + +commit 4d97480b1806e883eb1c7889d4e7a87e936e06d9 +Author: Mitsuo Hayasaka +Date: Wed Oct 12 16:04:29 2011 +0000 + + bonding: use local function pointer of bond->recv_probe in bond_handle_frame + + The bond->recv_probe is called in bond_handle_frame() when + a packet is received, but bond_close() sets it to NULL. So, + a panic occurs when both functions work in parallel. + + Why this happen: + After null pointer check of bond->recv_probe, an sk_buff is + duplicated and bond->recv_probe is called in bond_handle_frame. + So, a panic occurs when bond_close() is called between the + check and call of bond->recv_probe. + + Patch: + This patch uses a local function pointer of bond->recv_probe + in bond_handle_frame(). So, it can avoid the null pointer + dereference. + + Signed-off-by: Mitsuo Hayasaka + Cc: Jay Vosburgh + Cc: Andy Gospodarek + Cc: Eric Dumazet + Cc: WANG Cong + Acked-by: Eric Dumazet + Signed-off-by: David S. Miller + +commit 28c213793c994e4aac5f669ce856b5682a549bbb +Author: Phil Edworthy +Date: Wed Oct 12 02:29:39 2011 +0000 + + smsc911x: Add support for SMSC LAN89218 + + LAN89218 is register compatible with LAN911x. + + Signed-off-by: Phil Edworthy + Signed-off-by: David S. Miller + +commit e730c82347b9dc75914da998c44c3f348965db41 +Author: Jiri Pirko +Date: Tue Oct 11 23:00:41 2011 +0000 + + tg3: negate USE_PHYLIB flag check + + USE_PHYLIB flag in tg3_remove_one() is being checked incorrectly. This + results tg3_phy_fini->phy_disconnect is never called and when tg3 module + is removed. + + In my case this resulted in panics in phy_state_machine calling function + phydev->adjust_link. + + So correct this check. + + Signed-off-by: Jiri Pirko + Acked-by: Matt Carlson + Signed-off-by: David S. Miller + +commit d5123480b1d6f7d1a5fe1a13520cef88fb5d4c84 +Author: Gao feng +Date: Tue Oct 11 16:08:11 2011 +0000 + + netconsole: enable netconsole can make net_device refcnt incorrent + + There is no check if netconsole is enabled current. + so when exec echo 1 > enabled; + the reference of net_device will increment always. + + Signed-off-by: Gao feng + Acked-by: Flavio Leitner + Signed-off-by: David S. Miller + +commit 6230c9b4f8957c8938ee4cf2d03166d3c2dc89de +Author: Paul Moore +Date: Fri Oct 7 09:40:59 2011 +0000 + + bluetooth: Properly clone LSM attributes to newly created child connections + + The Bluetooth stack has internal connection handlers for all of the various + Bluetooth protocols, and unfortunately, they are currently lacking the LSM + hooks found in the core network stack's connection handlers. I say + unfortunately, because this can cause problems for users who have have an + LSM enabled and are using certain Bluetooth devices. See one problem + report below: + + * http://bugzilla.redhat.com/show_bug.cgi?id=741703 + + In order to keep things simple at this point in time, this patch fixes the + problem by cloning the parent socket's LSM attributes to the newly created + child socket. If we decide we need a more elaborate LSM marking mechanism + for Bluetooth (I somewhat doubt this) we can always revisit this decision + in the future. + + Reported-by: James M. Cape + Signed-off-by: Paul Moore + Acked-by: James Morris + Signed-off-by: David S. Miller + +commit 835acf5da239b91edb9f7ebe36516999e156e6ee +Author: Eric Dumazet +Date: Fri Oct 7 05:35:46 2011 +0000 + + l2tp: fix a potential skb leak in l2tp_xmit_skb() + + l2tp_xmit_skb() can leak one skb if skb_cow_head() returns an error. + + Signed-off-by: Eric Dumazet + Signed-off-by: David S. Miller + +commit 1ce5cce895309862d2c35d922816adebe094fe4a +Author: stephen hemminger +Date: Thu Oct 6 11:19:41 2011 +0000 + + bridge: fix hang on removal of bridge via netlink + + Need to cleanup bridge device timers and ports when being bridge + device is being removed via netlink. + + This fixes the problem of observed when doing: + ip link add br0 type bridge + ip link set dev eth1 master br0 + ip link set br0 up + ip link del br0 + + which would cause br0 to hang in unregister_netdev because + of leftover reference count. + + Reported-by: Sridhar Samudrala + Signed-off-by: Stephen Hemminger + Acked-by: Sridhar Samudrala + Signed-off-by: David S. Miller + +commit bcd5cff7216f9b2de0a148cc355eac199dc6f1cf +Author: Peter Zijlstra +Date: Mon Oct 17 11:50:30 2011 +0200 + + cputimer: Cure lock inversion + + There's a lock inversion between the cputimer->lock and rq->lock; + notably the two callchains involved are: + + update_rlimit_cpu() + sighand->siglock + set_process_cpu_timer() + cpu_timer_sample_group() + thread_group_cputimer() + cputimer->lock + thread_group_cputime() + task_sched_runtime() + ->pi_lock + rq->lock + + scheduler_tick() + rq->lock + task_tick_fair() + update_curr() + account_group_exec() + cputimer->lock + + Where the first one is enabling a CLOCK_PROCESS_CPUTIME_ID timer, and + the second one is keeping up-to-date. + + This problem was introduced by e8abccb7193 ("posix-cpu-timers: Cure + SMP accounting oddities"). + + Cure the problem by removing the cputimer->lock and rq->lock nesting, + this leaves concurrent enablers doing duplicate work, but the time + wasted should be on the same order otherwise wasted spinning on the + lock and the greater-than assignment filter should ensure we preserve + monotonicity. + + Reported-by: Dave Jones + Reported-by: Simon Kirby + Signed-off-by: Peter Zijlstra + Cc: stable@kernel.org + Cc: Linus Torvalds + Cc: Martin Schwidefsky + Link: http://lkml.kernel.org/r/1318928713.21167.4.camel@twins + Signed-off-by: Thomas Gleixner + +commit a4863ca93ccc52a83e7fbfc068b411b7faa03805 +Author: Alex Deucher +Date: Wed Oct 12 18:49:53 2011 -0400 + + drm/radeon/kms/DCE4.1: fix Select_CrtcSource EncodeMode setting for DP bridges (v2) + + Settings in this table reflect the physical panel/connector rather + than the internal dig encoding. + + v2: fix typo for DRM_MODE_CONNECTOR_VGA case. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 09cc6506f9e234b2ead60398ebb88c4b44421a93 +Author: Alex Deucher +Date: Wed Oct 12 18:44:33 2011 -0400 + + drm/radeon/kms/DCE4.1: ss is not supported on the internal pplls + + It's handled via external clock. It should already be protected + by the external ss flag, but add an explicit check just in case. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 3a6dea31453a101bd5e9e9c89a79f4fcb6b0342e +Author: Alex Deucher +Date: Wed Oct 12 18:44:32 2011 -0400 + + drm/radeon/kms/DCE4.1: fix dig encoder to transmitter mapping + + llano has fully routeable dig encoders similar to DCE3.2 while + ontario has a hardcoded mapping similar to DCE4.0. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit ca201c096269ee2d40037fea96a59fd0695888c4 +Author: Daniel Suchy +Date: Tue Oct 18 11:09:44 2011 +0200 + + ALSA: HDA: conexant support for Lenovo T520/W520 + + This is patch for Conexant codec of Intel HDA driver, adding new quirk + for Lenovo Thinkpad T520 and W520. Conexant autodetection works fine for + T520 (similar subsystem ID is used also in W520 model) and detects more + mixer features compared to generic (fallback) Lenovo quirk with + hardcoded options in Conexant codec. + + Patch was activelly tested with Linux 3.0.4, 3.0.6 and 3.0.7 without any + problems. + + Signed-off-by: Daniel Suchy + Cc: [3.0+] + Signed-off-by: Takashi Iwai + +commit 051a8cb6550d917225ead1cd008b5966350f6d53 +Author: Takashi Iwai +Date: Tue Oct 18 10:44:05 2011 +0200 + + ALSA: hda - Add position_fix quirk for Dell Inspiron 1010 + + The previous fix for the position-buffer check gives yet another + regression on a Dell laptop. The safest fix right now is to add a + static quirk for this device (and better to apply it for stable + kernels too). + + Reported-by: Éric Piel + Cc: + Signed-off-by: Takashi Iwai + +commit e22469ca88a8f1f6fe47adbf5e5ce0906aec07cd +Author: Thomas Hellstrom +Date: Mon Oct 17 13:27:34 2011 +0200 + + ttm: Fix error-path using an uninitialized value + + Pointed out by Michel Daenzer. + + Signed-off-by: Thomas Hellstrom + Signed-off-by: Dave Airlie + +commit ae2a4583154a5b985ed4a81c6259c55bafe6d810 +Merge: 7f81e25 ae1d48b +Author: David S. Miller +Date: Mon Oct 17 19:38:03 2011 -0400 + + Merge branch 'nf' of git://1984.lsi.us.es/net + +commit 7f81e25befdfb3272345a2e775f520e1d515fa20 +Author: Matthew Daley +Date: Fri Oct 14 18:45:05 2011 +0000 + + x25: Prevent skb overreads when checking call user data + + x25_find_listener does not check that the amount of call user data given + in the skb is big enough in per-socket comparisons, hence buffer + overreads may occur. Fix this by adding a check. + + Signed-off-by: Matthew Daley + Cc: Eric Dumazet + Cc: Andrew Hendry + Cc: stable + Acked-by: Andrew Hendry + Signed-off-by: David S. Miller + +commit cb101ed2c3c7c0224d16953fe77bfb9d6c2cb9df +Author: Matthew Daley +Date: Fri Oct 14 18:45:04 2011 +0000 + + x25: Handle undersized/fragmented skbs + + There are multiple locations in the X.25 packet layer where a skb is + assumed to be of at least a certain size and that all its data is + currently available at skb->data. These assumptions are not checked, + hence buffer overreads may occur. Use pskb_may_pull to check these + minimal size assumptions and ensure that data is available at skb->data + when necessary, as well as use skb_copy_bits where needed. + + Signed-off-by: Matthew Daley + Cc: Eric Dumazet + Cc: Andrew Hendry + Cc: stable + Acked-by: Andrew Hendry + Signed-off-by: David S. Miller + +commit c7fd0d48bde943e228e9c28ce971a22d6a1744c4 +Author: Matthew Daley +Date: Fri Oct 14 18:45:03 2011 +0000 + + x25: Validate incoming call user data lengths + + X.25 call user data is being copied in its entirety from incoming messages + without consideration to the size of the destination buffers, leading to + possible buffer overflows. Validate incoming call user data lengths before + these copies are performed. + + It appears this issue was noticed some time ago, however nothing seemed to + come of it: see http://www.spinics.net/lists/linux-x25/msg00043.html and + commit 8db09f26f912f7c90c764806e804b558da520d4f. + + Signed-off-by: Matthew Daley + Acked-by: Eric Dumazet + Tested-by: Andrew Hendry + Cc: stable + Signed-off-by: David S. Miller + +commit f36c23bb9f822904dacf83a329518d0a5fde7968 +Author: Gerrit Renker +Date: Mon Oct 17 19:07:30 2011 -0400 + + udplite: fast-path computation of checksum coverage + + Commit 903ab86d195cca295379699299c5fc10beba31c7 of 1 March this year ("udp: Add + lockless transmit path") introduced a new fast TX path that broke the checksum + coverage computation of UDP-lite, which so far depended on up->len (only set + if the socket is locked and 0 in the fast path). + + Fixed by providing both fast- and slow-path computation of checksum coverage. + The latter can be removed when UDP(-lite)v6 also uses a lockless transmit path. + + Reported-by: Thomas Volkert + Signed-off-by: Gerrit Renker + Signed-off-by: David S. Miller + +commit 27f20dca01b00eac445e5193565dd185548e7e34 +Author: David S. Miller +Date: Wed Oct 12 12:27:35 2011 -0700 + + sparc: Avoid calling sigprocmask() + + Use set_current_blocked() instead. + + Signed-off-by: David S. Miller + +commit faddf598f0ba98ba329bb83acad51aea40313c2a +Author: Matt Fleming +Date: Thu Aug 11 14:57:02 2011 +0100 + + sparc: Use set_current_blocked() + + As described in e6fa16ab ("signal: sigprocmask() should do + retarget_shared_pending()") the modification of current->blocked is + incorrect as we need to check whether the signal we're about to block + is pending in the shared queue. + + Cc: Oleg Nesterov + Cc: "David S. Miller" + Signed-off-by: Matt Fleming + Signed-off-by: David S. Miller + +commit ae1d48b23d5e79efbcf0cef4f0ebb9742361af59 +Author: Hans Schillstrom +Date: Tue Oct 11 10:54:35 2011 +0900 + + IPVS netns shutdown/startup dead-lock + + ip_vs_mutext is used by both netns shutdown code and startup + and both implicit uses sk_lock-AF_INET mutex. + + cleanup CPU-1 startup CPU-2 + ip_vs_dst_event() ip_vs_genl_set_cmd() + sk_lock-AF_INET __ip_vs_mutex + sk_lock-AF_INET + __ip_vs_mutex + * DEAD LOCK * + + A new mutex placed in ip_vs netns struct called sync_mutex is added. + + Comments from Julian and Simon added. + This patch has been running for more than 3 month now and it seems to work. + + Ver. 3 + IP_VS_SO_GET_DAEMON in do_ip_vs_get_ctl protected by sync_mutex + instead of __ip_vs_mutex as sugested by Julian. + + Signed-off-by: Hans Schillstrom + Acked-by: Julian Anastasov + Signed-off-by: Simon Horman + Signed-off-by: Pablo Neira Ayuso + +commit f22ed71cd60210d2f476986c0266004e4db45f34 +Author: Daniel Hellstrom +Date: Thu Sep 8 03:11:15 2011 +0000 + + sparc32,leon: SRMMU MMU Table probe fix + + The LEON MMU Model (SRMMU) does not implement MMu Table probing + in hardware, instead it is implemented in software. However the + software implementation does not return the PTE as it should which + always results in INVALID entires and the PROM mappings are not + inherited as they should during startup. The following patch + removes the masking of the PTE. + + Signed-off-by: Daniel Hellstrom + Signed-off-by: David S. Miller + +commit 98d9ae841ad620045d653fb05764e4a899f42dbd +Author: Florian Westphal +Date: Fri Sep 30 16:38:29 2011 +0200 + + netfilter: nf_conntrack: fix event flooding in GRE protocol tracker + + GRE connections cause ctnetlink event flood because the ASSURED event + is set for every packet received. + + Reported-by: Denys Fedoryshchenko + Tested-by: Denys Fedoryshchenko + Signed-off-by: Florian Westphal + Signed-off-by: Pablo Neira Ayuso diff --git a/sources b/sources index b3a7cb26e..7924e6091 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 6a91efe6505579a181c5f5e1a68f6c3a patch-3.1-rc10.bz2 +aaf9baa66a0fde2b3824ab618ac1be6c patch-3.1-rc10-git1.bz2 From ffd02941c7e07af3f38a46058520d88a59ec4c5e Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 21 Oct 2011 19:53:56 -0400 Subject: [PATCH 109/487] add version to changelog --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 0b3ad138d..256f5d268 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2085,7 +2085,7 @@ fi # and build. %changelog -* Fri Oct 21 2011 Chuck Ebbert +* Fri Oct 21 2011 Chuck Ebbert 3.1.0-0.rc10.git1.1 - Update to upstream HEAD (v3.1-rc10-42-g2efd7c0) * Fri Oct 21 2011 Dave Jones From 0a5023fe92115ee4df51296d88cbb74454197ca2 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 24 Oct 2011 07:45:47 -0400 Subject: [PATCH 110/487] Linux 3.1 --- kernel.spec | 7 +++++-- sources | 4 +--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/kernel.spec b/kernel.spec index 256f5d268..7db50a9dc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -6,7 +6,7 @@ Summary: The Linux kernel # For a stable, released kernel, released_kernel should be 1. For rawhide # and/or a kernel built from an rc or git snapshot, released_kernel should # be 0. -%global released_kernel 0 +%global released_kernel 1 # Save original buildid for later if it's defined %if 0%{?buildid:1} @@ -57,7 +57,7 @@ Summary: The Linux kernel # base_sublevel is the kernel version we're starting with and patching # on top of -- for example, 2.6.22-rc7-git1 starts with a 2.6.21 base, # which yields a base_sublevel of 21. -%define base_sublevel 0 +%define base_sublevel 1 ## If this is a released kernel ## %if 0%{?released_kernel} @@ -2085,6 +2085,9 @@ fi # and build. %changelog +* Mon Oct 24 2011 Chuck Ebbert 3.1.0-1 +- Linux 3.1 + * Fri Oct 21 2011 Chuck Ebbert 3.1.0-0.rc10.git1.1 - Update to upstream HEAD (v3.1-rc10-42-g2efd7c0) diff --git a/sources b/sources index 7924e6091..9529d7a05 100644 --- a/sources +++ b/sources @@ -1,3 +1 @@ -398e95866794def22b12dfbc15ce89c0 linux-3.0.tar.bz2 -6a91efe6505579a181c5f5e1a68f6c3a patch-3.1-rc10.bz2 -aaf9baa66a0fde2b3824ab618ac1be6c patch-3.1-rc10-git1.bz2 +8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 From 1ffed8724f6679829c6de80ec552c5d948409fa5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 24 Oct 2011 09:01:53 -0400 Subject: [PATCH 111/487] Backport 3 fixed from linux-next to fix dib0700 playback (rhbz 733827) --- kernel.spec | 13 +- ...-DiBcom-protect-the-I2C-bufer-access.patch | 1150 +++++++++++++++++ media-dib0700-correct-error-message.patch | 103 ++ ...00-protect-the-dib0700-buffer-access.patch | 248 ++++ 4 files changed, 1513 insertions(+), 1 deletion(-) create mode 100644 media-DiBcom-protect-the-I2C-bufer-access.patch create mode 100644 media-dib0700-correct-error-message.patch create mode 100644 media-dib0700-protect-the-dib0700-buffer-access.patch diff --git a/kernel.spec b/kernel.spec index 7db50a9dc..87abab899 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -704,6 +704,10 @@ Patch2900: linux-2.6-v4l-dvb-update.patch Patch2901: linux-2.6-v4l-dvb-experimental.patch Patch2902: linux-2.6-v4l-dvb-uvcvideo-update.patch +Patch2903: media-DiBcom-protect-the-I2C-bufer-access.patch +Patch2904: media-dib0700-protect-the-dib0700-buffer-access.patch +Patch2905: media-dib0700-correct-error-message.patch + Patch3000: rcutree-avoid-false-quiescent-states.patch # fs fixes @@ -1377,6 +1381,10 @@ ApplyPatch iwlagn-fix-ht_params-NULL-pointer-dereference.patch #rhbz #722509 ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch +ApplyPatch media-DiBcom-protect-the-I2C-bufer-access.patch +ApplyPatch media-dib0700-protect-the-dib0700-buffer-access.patch +ApplyPatch media-dib0700-correct-error-message.patch + # utrace. ApplyPatch utrace.patch @@ -2085,6 +2093,9 @@ fi # and build. %changelog +* Mon Oct 24 2011 Josh Boyer +- Backport 3 fixed from linux-next to fix dib0700 playback (rhbz 733827) + * Mon Oct 24 2011 Chuck Ebbert 3.1.0-1 - Linux 3.1 diff --git a/media-DiBcom-protect-the-I2C-bufer-access.patch b/media-DiBcom-protect-the-I2C-bufer-access.patch new file mode 100644 index 000000000..1b2a54b86 --- /dev/null +++ b/media-DiBcom-protect-the-I2C-bufer-access.patch @@ -0,0 +1,1150 @@ +From: Patrick Boettcher +Date: Wed, 3 Aug 2011 15:08:21 +0000 (-0300) +Subject: [media] DiBcom: protect the I2C bufer access +X-Git-Tag: next-20110927~67^2~4^2~225 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=79fcce3230b140f7675f8529ee53fe2f9644f902 + +[media] DiBcom: protect the I2C bufer access + +This patch protects the I2C buffer access in order to manage concurrent +access. This protection is done using mutex. +Furthermore, for the dib9000, if a pid filtering command is +received during the tuning, this pid filtering command is delayed to +avoid any concurrent access issue. + +Cc: Mauro Carvalho Chehab +Cc: Florian Mickler +Cc: stable@kernel.org +Signed-off-by: Olivier Grenie +Signed-off-by: Patrick Boettcher +Signed-off-by: Mauro Carvalho Chehab +--- + +diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c +index 1d47d4d..dc1cb17 100644 +--- a/drivers/media/dvb/frontends/dib0070.c ++++ b/drivers/media/dvb/frontends/dib0070.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include "dvb_frontend.h" + +@@ -78,10 +79,18 @@ struct dib0070_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[3]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + +-static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) ++static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = reg; + + memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); +@@ -96,13 +105,23 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) + + if (i2c_transfer(state->i2c, state->msg, 2) != 2) { + printk(KERN_WARNING "DiB0070 I2C read failed\n"); +- return 0; +- } +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ ret = 0; ++ } else ++ ret = (state->i2c_read_buffer[0] << 8) ++ | state->i2c_read_buffer[1]; ++ ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } + state->i2c_write_buffer[0] = reg; + state->i2c_write_buffer[1] = val >> 8; + state->i2c_write_buffer[2] = val & 0xff; +@@ -115,9 +134,12 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) + + if (i2c_transfer(state->i2c, state->msg, 1) != 1) { + printk(KERN_WARNING "DiB0070 I2C write failed\n"); +- return -EREMOTEIO; +- } +- return 0; ++ ret = -EREMOTEIO; ++ } else ++ ret = 0; ++ ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + #define HARD_RESET(state) do { \ +@@ -734,6 +756,7 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter + state->cfg = cfg; + state->i2c = i2c; + state->fe = fe; ++ mutex_init(&state->i2c_buffer_lock); + fe->tuner_priv = state; + + if (dib0070_reset(fe) != 0) +diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c +index c9c935a..b174d1c 100644 +--- a/drivers/media/dvb/frontends/dib0090.c ++++ b/drivers/media/dvb/frontends/dib0090.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include "dvb_frontend.h" + +@@ -196,6 +197,7 @@ struct dib0090_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[3]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + struct dib0090_fw_state { +@@ -208,10 +210,18 @@ struct dib0090_fw_state { + struct i2c_msg msg; + u8 i2c_write_buffer[2]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = reg; + + memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); +@@ -226,14 +236,24 @@ static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) + + if (i2c_transfer(state->i2c, state->msg, 2) != 2) { + printk(KERN_WARNING "DiB0090 I2C read failed\n"); +- return 0; +- } ++ ret = 0; ++ } else ++ ret = (state->i2c_read_buffer[0] << 8) ++ | state->i2c_read_buffer[1]; + +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + state->i2c_write_buffer[0] = reg & 0xff; + state->i2c_write_buffer[1] = val >> 8; + state->i2c_write_buffer[2] = val & 0xff; +@@ -246,13 +266,23 @@ static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) + + if (i2c_transfer(state->i2c, state->msg, 1) != 1) { + printk(KERN_WARNING "DiB0090 I2C write failed\n"); +- return -EREMOTEIO; +- } +- return 0; ++ ret = -EREMOTEIO; ++ } else ++ ret = 0; ++ ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = reg; + + memset(&state->msg, 0, sizeof(struct i2c_msg)); +@@ -262,13 +292,24 @@ static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg) + state->msg.len = 2; + if (i2c_transfer(state->i2c, &state->msg, 1) != 1) { + printk(KERN_WARNING "DiB0090 I2C read failed\n"); +- return 0; +- } +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ ret = 0; ++ } else ++ ret = (state->i2c_read_buffer[0] << 8) ++ | state->i2c_read_buffer[1]; ++ ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + state->i2c_write_buffer[0] = val >> 8; + state->i2c_write_buffer[1] = val & 0xff; + +@@ -279,9 +320,12 @@ static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val) + state->msg.len = 2; + if (i2c_transfer(state->i2c, &state->msg, 1) != 1) { + printk(KERN_WARNING "DiB0090 I2C write failed\n"); +- return -EREMOTEIO; +- } +- return 0; ++ ret = -EREMOTEIO; ++ } else ++ ret = 0; ++ ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + #define HARD_RESET(state) do { if (cfg->reset) { if (cfg->sleep) cfg->sleep(fe, 0); msleep(10); cfg->reset(fe, 1); msleep(10); cfg->reset(fe, 0); msleep(10); } } while (0) +@@ -2440,6 +2484,7 @@ struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapte + st->config = config; + st->i2c = i2c; + st->fe = fe; ++ mutex_init(&st->i2c_buffer_lock); + fe->tuner_priv = st; + + if (config->wbd == NULL) +@@ -2471,6 +2516,7 @@ struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_ada + st->config = config; + st->i2c = i2c; + st->fe = fe; ++ mutex_init(&st->i2c_buffer_lock); + fe->tuner_priv = st; + + if (dib0090_fw_reset_digital(fe, st->config) != 0) +diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c +index 79cb1c2..dbb76d7 100644 +--- a/drivers/media/dvb/frontends/dib7000m.c ++++ b/drivers/media/dvb/frontends/dib7000m.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + #include "dvb_frontend.h" + +@@ -55,6 +56,7 @@ struct dib7000m_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[4]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + enum dib7000m_power_mode { +@@ -69,6 +71,13 @@ enum dib7000m_power_mode { + + static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = (reg >> 8) | 0x80; + state->i2c_write_buffer[1] = reg & 0xff; + +@@ -85,11 +94,21 @@ static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) + if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2) + dprintk("i2c read error on %d",reg); + +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ mutex_unlock(&state->i2c_buffer_lock); ++ ++ return ret; + } + + static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + state->i2c_write_buffer[0] = (reg >> 8) & 0xff; + state->i2c_write_buffer[1] = reg & 0xff; + state->i2c_write_buffer[2] = (val >> 8) & 0xff; +@@ -101,7 +120,10 @@ static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) + state->msg[0].buf = state->i2c_write_buffer; + state->msg[0].len = 4; + +- return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; ++ ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? ++ -EREMOTEIO : 0); ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf) + { +@@ -1385,6 +1407,7 @@ struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, + demod = &st->demod; + demod->demodulator_priv = st; + memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops)); ++ mutex_init(&st->i2c_buffer_lock); + + st->timf_default = cfg->bw->timf; + +diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c +index a64a538..4eb9c2b 100644 +--- a/drivers/media/dvb/frontends/dib7000p.c ++++ b/drivers/media/dvb/frontends/dib7000p.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + #include "dvb_math.h" + #include "dvb_frontend.h" +@@ -68,6 +69,7 @@ struct dib7000p_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[4]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + enum dib7000p_power_mode { +@@ -81,6 +83,13 @@ static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff); + + static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = reg >> 8; + state->i2c_write_buffer[1] = reg & 0xff; + +@@ -97,11 +106,20 @@ static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) + if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2) + dprintk("i2c read error on %d", reg); + +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + state->i2c_write_buffer[0] = (reg >> 8) & 0xff; + state->i2c_write_buffer[1] = reg & 0xff; + state->i2c_write_buffer[2] = (val >> 8) & 0xff; +@@ -113,7 +131,10 @@ static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) + state->msg[0].buf = state->i2c_write_buffer; + state->msg[0].len = 4; + +- return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; ++ ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? ++ -EREMOTEIO : 0); ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf) +@@ -1646,6 +1667,7 @@ int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau + return -ENOMEM; + + dpst->i2c_adap = i2c; ++ mutex_init(&dpst->i2c_buffer_lock); + + for (k = no_of_demods - 1; k >= 0; k--) { + dpst->cfg = cfg[k]; +@@ -2324,6 +2346,7 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, + demod = &st->demod; + demod->demodulator_priv = st; + memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops)); ++ mutex_init(&st->i2c_buffer_lock); + + dib7000p_write_word(st, 1287, 0x0003); /* sram lead in, rdy */ + +@@ -2333,8 +2356,9 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, + st->version = dib7000p_read_word(st, 897); + + /* FIXME: make sure the dev.parent field is initialized, or else +- request_firmware() will hit an OOPS (this should be moved somewhere +- more common) */ ++ request_firmware() will hit an OOPS (this should be moved somewhere ++ more common) */ ++ st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent; + + /* FIXME: make sure the dev.parent field is initialized, or else + request_firmware() will hit an OOPS (this should be moved somewhere +diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c +index 7d2ea11..fe284d5 100644 +--- a/drivers/media/dvb/frontends/dib8000.c ++++ b/drivers/media/dvb/frontends/dib8000.c +@@ -10,6 +10,8 @@ + #include + #include + #include ++#include ++ + #include "dvb_math.h" + + #include "dvb_frontend.h" +@@ -37,6 +39,7 @@ struct i2c_device { + u8 addr; + u8 *i2c_write_buffer; + u8 *i2c_read_buffer; ++ struct mutex *i2c_buffer_lock; + }; + + struct dib8000_state { +@@ -77,6 +80,7 @@ struct dib8000_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[4]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + enum dib8000_power_mode { +@@ -86,24 +90,39 @@ enum dib8000_power_mode { + + static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg) + { ++ u16 ret; + struct i2c_msg msg[2] = { +- {.addr = i2c->addr >> 1, .flags = 0, +- .buf = i2c->i2c_write_buffer, .len = 2}, +- {.addr = i2c->addr >> 1, .flags = I2C_M_RD, +- .buf = i2c->i2c_read_buffer, .len = 2}, ++ {.addr = i2c->addr >> 1, .flags = 0, .len = 2}, ++ {.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2}, + }; + ++ if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ ++ msg[0].buf = i2c->i2c_write_buffer; + msg[0].buf[0] = reg >> 8; + msg[0].buf[1] = reg & 0xff; ++ msg[1].buf = i2c->i2c_read_buffer; + + if (i2c_transfer(i2c->adap, msg, 2) != 2) + dprintk("i2c read error on %d", reg); + +- return (msg[1].buf[0] << 8) | msg[1].buf[1]; ++ ret = (msg[1].buf[0] << 8) | msg[1].buf[1]; ++ mutex_unlock(i2c->i2c_buffer_lock); ++ return ret; + } + + static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = reg >> 8; + state->i2c_write_buffer[1] = reg & 0xff; + +@@ -120,7 +139,10 @@ static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) + if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2) + dprintk("i2c read error on %d", reg); + +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ mutex_unlock(&state->i2c_buffer_lock); ++ ++ return ret; + } + + static u32 dib8000_read32(struct dib8000_state *state, u16 reg) +@@ -135,22 +157,35 @@ static u32 dib8000_read32(struct dib8000_state *state, u16 reg) + + static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val) + { +- struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, +- .buf = i2c->i2c_write_buffer, .len = 4}; ++ struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4}; + int ret = 0; + ++ if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ ++ msg.buf = i2c->i2c_write_buffer; + msg.buf[0] = (reg >> 8) & 0xff; + msg.buf[1] = reg & 0xff; + msg.buf[2] = (val >> 8) & 0xff; + msg.buf[3] = val & 0xff; + + ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0; ++ mutex_unlock(i2c->i2c_buffer_lock); + + return ret; + } + + static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + state->i2c_write_buffer[0] = (reg >> 8) & 0xff; + state->i2c_write_buffer[1] = reg & 0xff; + state->i2c_write_buffer[2] = (val >> 8) & 0xff; +@@ -162,7 +197,11 @@ static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) + state->msg[0].buf = state->i2c_write_buffer; + state->msg[0].len = 4; + +- return i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; ++ ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? ++ -EREMOTEIO : 0); ++ mutex_unlock(&state->i2c_buffer_lock); ++ ++ return ret; + } + + static const s16 coeff_2k_sb_1seg_dqpsk[8] = { +@@ -2434,8 +2473,15 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau + if (!client.i2c_read_buffer) { + dprintk("%s: not enough memory", __func__); + ret = -ENOMEM; +- goto error_memory; ++ goto error_memory_read; ++ } ++ client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL); ++ if (!client.i2c_buffer_lock) { ++ dprintk("%s: not enough memory", __func__); ++ ret = -ENOMEM; ++ goto error_memory_lock; + } ++ mutex_init(client.i2c_buffer_lock); + + for (k = no_of_demods - 1; k >= 0; k--) { + /* designated i2c address */ +@@ -2476,8 +2522,10 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau + } + + error: ++ kfree(client.i2c_buffer_lock); ++error_memory_lock: + kfree(client.i2c_read_buffer); +-error_memory: ++error_memory_read: + kfree(client.i2c_write_buffer); + + return ret; +@@ -2581,6 +2629,8 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s + state->i2c.addr = i2c_addr; + state->i2c.i2c_write_buffer = state->i2c_write_buffer; + state->i2c.i2c_read_buffer = state->i2c_read_buffer; ++ mutex_init(&state->i2c_buffer_lock); ++ state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock; + state->gpio_val = cfg->gpio_val; + state->gpio_dir = cfg->gpio_dir; + +diff --git a/drivers/media/dvb/frontends/dib9000.c b/drivers/media/dvb/frontends/dib9000.c +index a085588..b931074 100644 +--- a/drivers/media/dvb/frontends/dib9000.c ++++ b/drivers/media/dvb/frontends/dib9000.c +@@ -38,6 +38,15 @@ struct i2c_device { + #define DibInitLock(lock) mutex_init(lock) + #define DibFreeLock(lock) + ++struct dib9000_pid_ctrl { ++#define DIB9000_PID_FILTER_CTRL 0 ++#define DIB9000_PID_FILTER 1 ++ u8 cmd; ++ u8 id; ++ u16 pid; ++ u8 onoff; ++}; ++ + struct dib9000_state { + struct i2c_device i2c; + +@@ -99,6 +108,10 @@ struct dib9000_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[255]; + u8 i2c_read_buffer[255]; ++ DIB_LOCK demod_lock; ++ u8 get_frontend_internal; ++ struct dib9000_pid_ctrl pid_ctrl[10]; ++ s8 pid_ctrl_index; /* -1: empty list; -2: do not use the list */ + }; + + static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +@@ -1743,19 +1756,56 @@ EXPORT_SYMBOL(dib9000_set_gpio); + int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) + { + struct dib9000_state *state = fe->demodulator_priv; +- u16 val = dib9000_read_word(state, 294 + 1) & 0xffef; ++ u16 val; ++ int ret; ++ ++ if ((state->pid_ctrl_index != -2) && (state->pid_ctrl_index < 9)) { ++ /* postpone the pid filtering cmd */ ++ dprintk("pid filter cmd postpone"); ++ state->pid_ctrl_index++; ++ state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER_CTRL; ++ state->pid_ctrl[state->pid_ctrl_index].onoff = onoff; ++ return 0; ++ } ++ ++ DibAcquireLock(&state->demod_lock); ++ ++ val = dib9000_read_word(state, 294 + 1) & 0xffef; + val |= (onoff & 0x1) << 4; + + dprintk("PID filter enabled %d", onoff); +- return dib9000_write_word(state, 294 + 1, val); ++ ret = dib9000_write_word(state, 294 + 1, val); ++ DibReleaseLock(&state->demod_lock); ++ return ret; ++ + } + EXPORT_SYMBOL(dib9000_fw_pid_filter_ctrl); + + int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) + { + struct dib9000_state *state = fe->demodulator_priv; ++ int ret; ++ ++ if (state->pid_ctrl_index != -2) { ++ /* postpone the pid filtering cmd */ ++ dprintk("pid filter postpone"); ++ if (state->pid_ctrl_index < 9) { ++ state->pid_ctrl_index++; ++ state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER; ++ state->pid_ctrl[state->pid_ctrl_index].id = id; ++ state->pid_ctrl[state->pid_ctrl_index].pid = pid; ++ state->pid_ctrl[state->pid_ctrl_index].onoff = onoff; ++ } else ++ dprintk("can not add any more pid ctrl cmd"); ++ return 0; ++ } ++ ++ DibAcquireLock(&state->demod_lock); + dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff); +- return dib9000_write_word(state, 300 + 1 + id, onoff ? (1 << 13) | pid : 0); ++ ret = dib9000_write_word(state, 300 + 1 + id, ++ onoff ? (1 << 13) | pid : 0); ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + EXPORT_SYMBOL(dib9000_fw_pid_filter); + +@@ -1778,6 +1828,7 @@ static void dib9000_release(struct dvb_frontend *demod) + DibFreeLock(&state->platform.risc.mbx_lock); + DibFreeLock(&state->platform.risc.mem_lock); + DibFreeLock(&state->platform.risc.mem_mbx_lock); ++ DibFreeLock(&state->demod_lock); + dibx000_exit_i2c_master(&st->i2c_master); + + i2c_del_adapter(&st->tuner_adap); +@@ -1795,14 +1846,19 @@ static int dib9000_sleep(struct dvb_frontend *fe) + { + struct dib9000_state *state = fe->demodulator_priv; + u8 index_frontend; +- int ret; ++ int ret = 0; + ++ DibAcquireLock(&state->demod_lock); + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { + ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]); + if (ret < 0) +- return ret; ++ goto error; + } +- return dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0); ++ ret = dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0); ++ ++error: ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + + static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune) +@@ -1816,7 +1872,10 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + struct dib9000_state *state = fe->demodulator_priv; + u8 index_frontend, sub_index_frontend; + fe_status_t stat; +- int ret; ++ int ret = 0; ++ ++ if (state->get_frontend_internal == 0) ++ DibAcquireLock(&state->demod_lock); + + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { + state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat); +@@ -1846,14 +1905,15 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + state->fe[index_frontend]->dtv_property_cache.rolloff; + } + } +- return 0; ++ ret = 0; ++ goto return_value; + } + } + + /* get the channel from master chip */ + ret = dib9000_fw_get_channel(fe, fep); + if (ret != 0) +- return ret; ++ goto return_value; + + /* synchronize the cache with the other frontends */ + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { +@@ -1866,8 +1926,12 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP; + state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff; + } ++ ret = 0; + +- return 0; ++return_value: ++ if (state->get_frontend_internal == 0) ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + + static int dib9000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) +@@ -1912,6 +1976,10 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + dprintk("dib9000: must specify bandwidth "); + return 0; + } ++ ++ state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */ ++ DibAcquireLock(&state->demod_lock); ++ + fe->dtv_property_cache.delivery_system = SYS_DVBT; + + /* set the master status */ +@@ -1974,13 +2042,18 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + /* check the tune result */ + if (exit_condition == 1) { /* tune failed */ + dprintk("tune failed"); ++ DibReleaseLock(&state->demod_lock); ++ /* tune failed; put all the pid filtering cmd to junk */ ++ state->pid_ctrl_index = -1; + return 0; + } + + dprintk("tune success on frontend%i", index_frontend_success); + + /* synchronize all the channel cache */ ++ state->get_frontend_internal = 1; + dib9000_get_frontend(state->fe[0], fep); ++ state->get_frontend_internal = 0; + + /* retune the other frontends with the found channel */ + channel_status.status = CHANNEL_STATUS_PARAMETERS_SET; +@@ -2025,6 +2098,28 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + /* turn off the diversity for the last frontend */ + dib9000_fw_set_diversity_in(state->fe[index_frontend - 1], 0); + ++ DibReleaseLock(&state->demod_lock); ++ if (state->pid_ctrl_index >= 0) { ++ u8 index_pid_filter_cmd; ++ u8 pid_ctrl_index = state->pid_ctrl_index; ++ ++ state->pid_ctrl_index = -2; ++ for (index_pid_filter_cmd = 0; ++ index_pid_filter_cmd <= pid_ctrl_index; ++ index_pid_filter_cmd++) { ++ if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER_CTRL) ++ dib9000_fw_pid_filter_ctrl(state->fe[0], ++ state->pid_ctrl[index_pid_filter_cmd].onoff); ++ else if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER) ++ dib9000_fw_pid_filter(state->fe[0], ++ state->pid_ctrl[index_pid_filter_cmd].id, ++ state->pid_ctrl[index_pid_filter_cmd].pid, ++ state->pid_ctrl[index_pid_filter_cmd].onoff); ++ } ++ } ++ /* do not postpone any more the pid filtering */ ++ state->pid_ctrl_index = -2; ++ + return 0; + } + +@@ -2041,6 +2136,7 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat) + u8 index_frontend; + u16 lock = 0, lock_slave = 0; + ++ DibAcquireLock(&state->demod_lock); + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) + lock_slave |= dib9000_read_lock(state->fe[index_frontend]); + +@@ -2059,6 +2155,8 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat) + if ((lock & 0x0008) || (lock_slave & 0x0008)) + *stat |= FE_HAS_LOCK; + ++ DibReleaseLock(&state->demod_lock); ++ + return 0; + } + +@@ -2066,10 +2164,14 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber) + { + struct dib9000_state *state = fe->demodulator_priv; + u16 *c; ++ int ret = 0; + ++ DibAcquireLock(&state->demod_lock); + DibAcquireLock(&state->platform.risc.mem_mbx_lock); +- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) +- return -EIO; ++ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { ++ ret = -EIO; ++ goto error; ++ } + dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, + state->i2c_read_buffer, 16 * 2); + DibReleaseLock(&state->platform.risc.mem_mbx_lock); +@@ -2077,7 +2179,10 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber) + c = (u16 *)state->i2c_read_buffer; + + *ber = c[10] << 16 | c[11]; +- return 0; ++ ++error: ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + + static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) +@@ -2086,7 +2191,9 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) + u8 index_frontend; + u16 *c = (u16 *)state->i2c_read_buffer; + u16 val; ++ int ret = 0; + ++ DibAcquireLock(&state->demod_lock); + *strength = 0; + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { + state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val); +@@ -2097,8 +2204,10 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) + } + + DibAcquireLock(&state->platform.risc.mem_mbx_lock); +- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) +- return -EIO; ++ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { ++ ret = -EIO; ++ goto error; ++ } + dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); + DibReleaseLock(&state->platform.risc.mem_mbx_lock); + +@@ -2107,7 +2216,10 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) + *strength = 65535; + else + *strength += val; +- return 0; ++ ++error: ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + + static u32 dib9000_get_snr(struct dvb_frontend *fe) +@@ -2151,6 +2263,7 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr) + u8 index_frontend; + u32 snr_master; + ++ DibAcquireLock(&state->demod_lock); + snr_master = dib9000_get_snr(fe); + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) + snr_master += dib9000_get_snr(state->fe[index_frontend]); +@@ -2161,6 +2274,8 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr) + } else + *snr = 0; + ++ DibReleaseLock(&state->demod_lock); ++ + return 0; + } + +@@ -2168,15 +2283,22 @@ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) + { + struct dib9000_state *state = fe->demodulator_priv; + u16 *c = (u16 *)state->i2c_read_buffer; ++ int ret = 0; + ++ DibAcquireLock(&state->demod_lock); + DibAcquireLock(&state->platform.risc.mem_mbx_lock); +- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) +- return -EIO; ++ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { ++ ret = -EIO; ++ goto error; ++ } + dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); + DibReleaseLock(&state->platform.risc.mem_mbx_lock); + + *unc = c[12]; +- return 0; ++ ++error: ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + + int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr) +@@ -2322,6 +2444,10 @@ struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, c + DibInitLock(&st->platform.risc.mbx_lock); + DibInitLock(&st->platform.risc.mem_lock); + DibInitLock(&st->platform.risc.mem_mbx_lock); ++ DibInitLock(&st->demod_lock); ++ st->get_frontend_internal = 0; ++ ++ st->pid_ctrl_index = -2; + + st->fe[0] = fe; + fe->demodulator_priv = st; +diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c +index dc5d17a..774d507 100644 +--- a/drivers/media/dvb/frontends/dibx000_common.c ++++ b/drivers/media/dvb/frontends/dibx000_common.c +@@ -1,4 +1,5 @@ + #include ++#include + + #include "dibx000_common.h" + +@@ -10,6 +11,13 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); + + static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + mst->i2c_write_buffer[0] = (reg >> 8) & 0xff; + mst->i2c_write_buffer[1] = reg & 0xff; + mst->i2c_write_buffer[2] = (val >> 8) & 0xff; +@@ -21,11 +29,21 @@ static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) + mst->msg[0].buf = mst->i2c_write_buffer; + mst->msg[0].len = 4; + +- return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0; ++ ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0; ++ mutex_unlock(&mst->i2c_buffer_lock); ++ ++ return ret; + } + + static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + mst->i2c_write_buffer[0] = reg >> 8; + mst->i2c_write_buffer[1] = reg & 0xff; + +@@ -42,7 +60,10 @@ static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg) + if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2) + dprintk("i2c read error on %d", reg); + +- return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1]; ++ ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1]; ++ mutex_unlock(&mst->i2c_buffer_lock); ++ ++ return ret; + } + + static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst) +@@ -257,6 +278,7 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg msg[], int num) + { + struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); ++ int ret; + + if (num > 32) { + dprintk("%s: too much I2C message to be transmitted (%i).\ +@@ -264,10 +286,15 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, + return -ENOMEM; + } + +- memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); +- + dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7); + ++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ ++ memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); ++ + /* open the gate */ + dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); + mst->msg[0].addr = mst->i2c_addr; +@@ -282,7 +309,11 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, + mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; + mst->msg[num + 1].len = 4; + +- return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO; ++ ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? ++ num : -EIO); ++ ++ mutex_unlock(&mst->i2c_buffer_lock); ++ return ret; + } + + static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = { +@@ -294,6 +325,7 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg msg[], int num) + { + struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); ++ int ret; + + if (num > 32) { + dprintk("%s: too much I2C message to be transmitted (%i).\ +@@ -301,10 +333,14 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, + return -ENOMEM; + } + +- memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); +- + dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); + ++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); ++ + /* open the gate */ + dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); + mst->msg[0].addr = mst->i2c_addr; +@@ -319,7 +355,10 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, + mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; + mst->msg[num + 1].len = 4; + +- return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO; ++ ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? ++ num : -EIO); ++ mutex_unlock(&mst->i2c_buffer_lock); ++ return ret; + } + + static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = { +@@ -390,8 +429,18 @@ static int i2c_adapter_init(struct i2c_adapter *i2c_adap, + int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, + struct i2c_adapter *i2c_adap, u8 i2c_addr) + { +- u8 tx[4]; +- struct i2c_msg m = {.addr = i2c_addr >> 1,.buf = tx,.len = 4 }; ++ int ret; ++ ++ mutex_init(&mst->i2c_buffer_lock); ++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ memset(mst->msg, 0, sizeof(struct i2c_msg)); ++ mst->msg[0].addr = i2c_addr >> 1; ++ mst->msg[0].flags = 0; ++ mst->msg[0].buf = mst->i2c_write_buffer; ++ mst->msg[0].len = 4; + + mst->device_rev = device_rev; + mst->i2c_adap = i2c_adap; +@@ -431,9 +480,12 @@ int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, + "DiBX000: could not initialize the master i2c_adapter\n"); + + /* initialize the i2c-master by closing the gate */ +- dibx000_i2c_gate_ctrl(mst, tx, 0, 0); ++ dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0); ++ ++ ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1); ++ mutex_unlock(&mst->i2c_buffer_lock); + +- return i2c_transfer(i2c_adap, &m, 1) == 1; ++ return ret; + } + + EXPORT_SYMBOL(dibx000_init_i2c_master); +diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h +index f031165..5e01147 100644 +--- a/drivers/media/dvb/frontends/dibx000_common.h ++++ b/drivers/media/dvb/frontends/dibx000_common.h +@@ -33,6 +33,7 @@ struct dibx000_i2c_master { + struct i2c_msg msg[34]; + u8 i2c_write_buffer[8]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, diff --git a/media-dib0700-correct-error-message.patch b/media-dib0700-correct-error-message.patch new file mode 100644 index 000000000..5e5d3bfa2 --- /dev/null +++ b/media-dib0700-correct-error-message.patch @@ -0,0 +1,103 @@ +From: Olivier Grenie +Date: Thu, 4 Aug 2011 16:10:03 +0000 (-0300) +Subject: [media] dib0700: correct error message +X-Git-Tag: next-20110927~67^2~4^2~223 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=680417bb318adc5f1f8f392730776176fbcdedd8 + +[media] dib0700: correct error message + +The goal of this patch is to correct a previous patch. In case of error, +the err() function should be used instead of dprintk() function. + +[mchehab@redhat.com: as I've replaced dprintk by deb_info, on the the + previous patch, to avoid breaking bisect, I had to fix a merge conflict + on this one] +Signed-off-by: Olivier Grenie +Signed-off-by: Mauro Carvalho Chehab +--- + +diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c +index a224e94..b693ed1 100644 +--- a/drivers/media/dvb/dvb-usb/dib0700_core.c ++++ b/drivers/media/dvb/dvb-usb/dib0700_core.c +@@ -31,7 +31,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, + int ret; + + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -117,7 +117,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ + int ret; + + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -138,7 +138,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) + + if (st->fw_version >= 0x10201) { + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -227,7 +227,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, + } else { + /* Write request */ + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + st->buf[0] = REQUEST_NEW_I2C_WRITE; +@@ -273,7 +273,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -368,7 +368,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, + int ret; + + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -400,7 +400,7 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) + return -EINVAL; + + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -560,7 +560,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) + } + + if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -610,7 +610,7 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) + int new_proto, ret; + + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + diff --git a/media-dib0700-protect-the-dib0700-buffer-access.patch b/media-dib0700-protect-the-dib0700-buffer-access.patch new file mode 100644 index 000000000..109cab8ec --- /dev/null +++ b/media-dib0700-protect-the-dib0700-buffer-access.patch @@ -0,0 +1,248 @@ +From: Olivier Grenie +Date: Mon, 1 Aug 2011 15:45:58 +0000 (-0300) +Subject: [media] dib0700: protect the dib0700 buffer access +X-Git-Tag: next-20110927~67^2~4^2~224 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=bff469f4167fdabfe15294f375577d7eadbaa1bb + +[media] dib0700: protect the dib0700 buffer access + +This patch protects the common buffer access inside the dib0700 in order +to manage concurrent access. This protection is done using mutex. + +Cc: Mauro Carvalho Chehab +Cc: Florian Mickler +Cc: stable@kernel.org +Signed-off-by: Javier Marcet +Signed-off-by: Olivier Grenie +Signed-off-by: Patrick Boettcher +[mchehab@redhat.com: dprint requires 3 arguments. Replaced by dib_info] +Signed-off-by: Mauro Carvalho Chehab +--- + +diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c +index 5eb91b4..a224e94 100644 +--- a/drivers/media/dvb/dvb-usb/dib0700_core.c ++++ b/drivers/media/dvb/dvb-usb/dib0700_core.c +@@ -30,6 +30,11 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, + struct dib0700_state *st = d->priv; + int ret; + ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } ++ + ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), + REQUEST_GET_VERSION, + USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, +@@ -46,6 +51,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, + if (fwtype != NULL) + *fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) | + (st->buf[14] << 8) | st->buf[15]; ++ mutex_unlock(&d->usb_mutex); + return ret; + } + +@@ -108,7 +114,12 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen + int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val) + { + struct dib0700_state *st = d->priv; +- s16 ret; ++ int ret; ++ ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } + + st->buf[0] = REQUEST_SET_GPIO; + st->buf[1] = gpio; +@@ -116,6 +127,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ + + ret = dib0700_ctrl_wr(d, st->buf, 3); + ++ mutex_unlock(&d->usb_mutex); + return ret; + } + +@@ -125,6 +137,11 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) + int ret; + + if (st->fw_version >= 0x10201) { ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } ++ + st->buf[0] = REQUEST_SET_USB_XFER_LEN; + st->buf[1] = (nb_ts_packets >> 8) & 0xff; + st->buf[2] = nb_ts_packets & 0xff; +@@ -132,6 +149,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) + deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets); + + ret = dib0700_ctrl_wr(d, st->buf, 3); ++ mutex_unlock(&d->usb_mutex); + } else { + deb_info("this firmware does not allow to change the USB xfer len\n"); + ret = -EIO; +@@ -208,6 +226,10 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, + + } else { + /* Write request */ ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } + st->buf[0] = REQUEST_NEW_I2C_WRITE; + st->buf[1] = msg[i].addr << 1; + st->buf[2] = (en_start << 7) | (en_stop << 6) | +@@ -227,6 +249,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, + USB_TYPE_VENDOR | USB_DIR_OUT, + 0, 0, st->buf, msg[i].len + 4, + USB_CTRL_GET_TIMEOUT); ++ mutex_unlock(&d->usb_mutex); + if (result < 0) { + deb_info("i2c write error (status = %d)\n", result); + break; +@@ -249,6 +272,10 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } + + for (i = 0; i < num; i++) { + /* fill in the address */ +@@ -279,6 +306,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, + break; + } + } ++ mutex_unlock(&d->usb_mutex); + mutex_unlock(&d->i2c_mutex); + + return i; +@@ -337,7 +365,12 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, + u16 pll_loopdiv, u16 free_div, u16 dsuScaler) + { + struct dib0700_state *st = d->priv; +- s16 ret; ++ int ret; ++ ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } + + st->buf[0] = REQUEST_SET_CLOCK; + st->buf[1] = (en_pll << 7) | (pll_src << 6) | +@@ -352,6 +385,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, + st->buf[9] = dsuScaler & 0xff; /* LSB */ + + ret = dib0700_ctrl_wr(d, st->buf, 10); ++ mutex_unlock(&d->usb_mutex); + + return ret; + } +@@ -360,10 +394,16 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) + { + struct dib0700_state *st = d->priv; + u16 divider; ++ int ret; + + if (scl_kHz == 0) + return -EINVAL; + ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } ++ + st->buf[0] = REQUEST_SET_I2C_PARAM; + divider = (u16) (30000 / scl_kHz); + st->buf[1] = 0; +@@ -379,7 +419,11 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) + deb_info("setting I2C speed: %04x %04x %04x (%d kHz).", + (st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) | + st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz); +- return dib0700_ctrl_wr(d, st->buf, 8); ++ ++ ret = dib0700_ctrl_wr(d, st->buf, 8); ++ mutex_unlock(&d->usb_mutex); ++ ++ return ret; + } + + +@@ -515,6 +559,11 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) + } + } + ++ if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } ++ + st->buf[0] = REQUEST_ENABLE_VIDEO; + /* this bit gives a kind of command, + * rather than enabling something or not */ +@@ -548,7 +597,10 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) + + deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]); + +- return dib0700_ctrl_wr(adap->dev, st->buf, 4); ++ ret = dib0700_ctrl_wr(adap->dev, st->buf, 4); ++ mutex_unlock(&adap->dev->usb_mutex); ++ ++ return ret; + } + + int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) +@@ -557,6 +609,11 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) + struct dib0700_state *st = d->priv; + int new_proto, ret; + ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } ++ + st->buf[0] = REQUEST_SET_RC; + st->buf[1] = 0; + st->buf[2] = 0; +@@ -567,23 +624,29 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) + else if (rc_type == RC_TYPE_NEC) + new_proto = 0; + else if (rc_type == RC_TYPE_RC6) { +- if (st->fw_version < 0x10200) +- return -EINVAL; ++ if (st->fw_version < 0x10200) { ++ ret = -EINVAL; ++ goto out; ++ } + + new_proto = 2; +- } else +- return -EINVAL; ++ } else { ++ ret = -EINVAL; ++ goto out; ++ } + + st->buf[1] = new_proto; + + ret = dib0700_ctrl_wr(d, st->buf, 3); + if (ret < 0) { + err("ir protocol setup failed"); +- return ret; ++ goto out; + } + + d->props.rc.core.protocol = rc_type; + ++out: ++ mutex_unlock(&d->usb_mutex); + return ret; + } + From 0cc31ee8bffe2e663e27b3a8902e6a2efa896ee6 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 25 Oct 2011 11:04:13 -0400 Subject: [PATCH 112/487] CVE-2011-1083: excessive in kernel CPU consumption when creating large nested epoll structures (rhbz 748668) --- epoll-limit-paths.patch | 465 ++++++++++++++++++++++++++++++++++++++++ kernel.spec | 7 +- 2 files changed, 471 insertions(+), 1 deletion(-) create mode 100644 epoll-limit-paths.patch diff --git a/epoll-limit-paths.patch b/epoll-limit-paths.patch new file mode 100644 index 000000000..440db27b9 --- /dev/null +++ b/epoll-limit-paths.patch @@ -0,0 +1,465 @@ +From 6a4ca79652219cf22da800d990e5b46feaea1ad9 Mon Sep 17 00:00:00 2001 +From: Jason Baron +Date: Mon, 24 Oct 2011 14:59:02 +1100 +Subject: [PATCH] epoll: limit paths + +epoll: limit paths + +The current epoll code can be tickled to run basically indefinitely in +both loop detection path check (on ep_insert()), and in the wakeup paths. +The programs that tickle this behavior set up deeply linked networks of +epoll file descriptors that cause the epoll algorithms to traverse them +indefinitely. A couple of these sample programs have been previously +posted in this thread: https://lkml.org/lkml/2011/2/25/297. + +To fix the loop detection path check algorithms, I simply keep track of +the epoll nodes that have been already visited. Thus, the loop detection +becomes proportional to the number of epoll file descriptor and links. +This dramatically decreases the run-time of the loop check algorithm. In +one diabolical case I tried it reduced the run-time from 15 mintues (all +in kernel time) to .3 seconds. + +Fixing the wakeup paths could be done at wakeup time in a similar manner +by keeping track of nodes that have already been visited, but the +complexity is harder, since there can be multiple wakeups on different +cpus...Thus, I've opted to limit the number of possible wakeup paths when +the paths are created. + +This is accomplished, by noting that the end file descriptor points that +are found during the loop detection pass (from the newly added link), are +actually the sources for wakeup events. I keep a list of these file +descriptors and limit the number and length of these paths that emanate +from these 'source file descriptors'. In the current implemetation I +allow 1000 paths of length 1, 500 of length 2, 100 of length 3, 50 of +length 4 and 10 of length 5. Note that it is sufficient to check the +'source file descriptors' reachable from the newly added link, since no +other 'source file descriptors' will have newly added links. This allows +us to check only the wakeup paths that may have gotten too long, and not +re-check all possible wakeup paths on the system. + +In terms of the path limit selection, I think its first worth noting that +the most common case for epoll, is probably the model where you have 1 +epoll file descriptor that is monitoring n number of 'source file +descriptors'. In this case, each 'source file descriptor' has a 1 path of +length 1. Thus, I believe that the limits I'm proposing are quite +reasonable and in fact may be too generous. Thus, I'm hoping that the +proposed limits will not prevent any workloads that currently work to +fail. + +In terms of locking, I have extended the use of the 'epmutex' to all +epoll_ctl add and remove operations. Currently its only used in a subset +of the add paths. I need to hold the epmutex, so that we can correctly +traverse a coherent graph, to check the number of paths. I believe that +this additional locking is probably ok, since its in the setup/teardown +paths, and doesn't affect the running paths, but it certainly is going to +add some extra overhead. Also, worth noting is that the epmuex was +recently added to the ep_ctl add operations in the initial path loop +detection code using the argument that it was not on a critical path. + +Another thing to note here, is the length of epoll chains that is allowed. +Currently, eventpoll.c defines: + +/* Maximum number of nesting allowed inside epoll sets */ +#define EP_MAX_NESTS 4 + +This basically means that I am limited to a graph depth of 5 (EP_MAX_NESTS ++ 1). However, this limit is currently only enforced during the loop +check detection code, and only when the epoll file descriptors are added +in a certain order. Thus, this limit is currently easily bypassed. The +newly added check for wakeup paths, stricly limits the wakeup paths to a +length of 5, regardless of the order in which ep's are linked together. +Thus, a side-effect of the new code is a more consistent enforcement of +the graph depth. + +Thus far, I've tested this, using the sample programs previously +mentioned, which now either return quickly or return -EINVAL. I've also +testing using the piptest.c epoll tester, which showed no difference in +performance. I've also created a number of different epoll networks and +tested that they behave as expectded. + +I believe this solves the original diabolical test cases, while still +preserving the sane epoll nesting. + +Signed-off-by: Jason Baron +Cc: Nelson Elhage +Cc: Davide Libenzi +Signed-off-by: Andrew Morton +--- + fs/eventpoll.c | 226 ++++++++++++++++++++++++++++++++++++++++----- + include/linux/eventpoll.h | 1 + + include/linux/fs.h | 1 + + 3 files changed, 203 insertions(+), 25 deletions(-) + +diff --git a/fs/eventpoll.c b/fs/eventpoll.c +index 4a53743..414ac74 100644 +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -197,6 +197,12 @@ struct eventpoll { + + /* The user that created the eventpoll descriptor */ + struct user_struct *user; ++ ++ struct file *file; ++ ++ /* used to optimize loop detection check */ ++ int visited; ++ struct list_head visitedllink; + }; + + /* Wait structure used by the poll hooks */ +@@ -255,6 +261,12 @@ static struct kmem_cache *epi_cache __read_mostly; + /* Slab cache used to allocate "struct eppoll_entry" */ + static struct kmem_cache *pwq_cache __read_mostly; + ++/* Visited nodes during ep_loop_check(), so we can unset them when we finish */ ++LIST_HEAD(visited_list); ++ ++/* Files with newly added links, which need a limit on emanating paths */ ++LIST_HEAD(tfile_check_list); ++ + #ifdef CONFIG_SYSCTL + + #include +@@ -276,6 +288,12 @@ ctl_table epoll_table[] = { + }; + #endif /* CONFIG_SYSCTL */ + ++static const struct file_operations eventpoll_fops; ++ ++static inline int is_file_epoll(struct file *f) ++{ ++ return f->f_op == &eventpoll_fops; ++} + + /* Setup the structure that is used as key for the RB tree */ + static inline void ep_set_ffd(struct epoll_filefd *ffd, +@@ -711,12 +729,6 @@ static const struct file_operations eventpoll_fops = { + .llseek = noop_llseek, + }; + +-/* Fast test to see if the file is an evenpoll file */ +-static inline int is_file_epoll(struct file *f) +-{ +- return f->f_op == &eventpoll_fops; +-} +- + /* + * This is called from eventpoll_release() to unlink files from the eventpoll + * interface. We need to have this facility to cleanup correctly files that are +@@ -926,6 +938,96 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi) + rb_insert_color(&epi->rbn, &ep->rbr); + } + ++ ++ ++#define PATH_ARR_SIZE 5 ++/* These are the number paths of length 1 to 5, that we are allowing to emanate ++ * from a single file of interest. For example, we allow 1000 paths of length ++ * 1, to emanate from each file of interest. This essentially represents the ++ * potential wakeup paths, which need to be limited in order to avoid massive ++ * uncontrolled wakeup storms. The common use case should be a single ep which ++ * is connected to n file sources. In this case each file source has 1 path ++ * of length 1. Thus, the numbers below should be more than sufficient. ++ */ ++int path_limits[PATH_ARR_SIZE] = { 1000, 500, 100, 50, 10 }; ++int path_count[PATH_ARR_SIZE]; ++ ++static int path_count_inc(int nests) ++{ ++ if (++path_count[nests] > path_limits[nests]) ++ return -1; ++ return 0; ++} ++ ++static void path_count_init(void) ++{ ++ int i; ++ ++ for (i = 0; i < PATH_ARR_SIZE; i++) ++ path_count[i] = 0; ++} ++ ++static int reverse_path_check_proc(void *priv, void *cookie, int call_nests) ++{ ++ int error = 0; ++ struct file *file = priv; ++ struct file *child_file; ++ struct epitem *epi; ++ ++ list_for_each_entry(epi, &file->f_ep_links, fllink) { ++ child_file = epi->ep->file; ++ if (is_file_epoll(child_file)) { ++ if (list_empty(&child_file->f_ep_links)) { ++ if (path_count_inc(call_nests)) { ++ error = -1; ++ break; ++ } ++ } else { ++ error = ep_call_nested(&poll_loop_ncalls, ++ EP_MAX_NESTS, ++ reverse_path_check_proc, ++ child_file, child_file, ++ current); ++ } ++ if (error != 0) ++ break; ++ } else { ++ printk(KERN_ERR "reverse_path_check_proc: " ++ "file is not an ep!\n"); ++ } ++ } ++ return error; ++} ++ ++/** ++ * reverse_path_check - The tfile_check_list is list of file *, which have ++ * links that are proposed to be newly added. We need to ++ * make sure that those added links don't add too many ++ * paths such that we will spend all our time waking up ++ * eventpoll objects. ++ * ++ * Returns: Returns zero if the proposed links don't create too many paths, ++ * -1 otherwise. ++ */ ++static int reverse_path_check(void) ++{ ++ int length = 0; ++ int error = 0; ++ struct file *current_file; ++ ++ /* let's call this for all tfiles */ ++ list_for_each_entry(current_file, &tfile_check_list, f_tfile_llink) { ++ length++; ++ path_count_init(); ++ error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, ++ reverse_path_check_proc, current_file, ++ current_file, current); ++ if (error) ++ break; ++ } ++ return error; ++} ++ + /* + * Must be called with "mtx" held. + */ +@@ -987,6 +1089,11 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, + */ + ep_rbtree_insert(ep, epi); + ++ /* now check if we've created too many backpaths */ ++ error = -EINVAL; ++ if (reverse_path_check()) ++ goto error_remove_epi; ++ + /* We have to drop the new item inside our item list to keep track of it */ + spin_lock_irqsave(&ep->lock, flags); + +@@ -1011,6 +1118,14 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, + + return 0; + ++error_remove_epi: ++ spin_lock(&tfile->f_lock); ++ if (ep_is_linked(&epi->fllink)) ++ list_del_init(&epi->fllink); ++ spin_unlock(&tfile->f_lock); ++ ++ rb_erase(&epi->rbn, &ep->rbr); ++ + error_unregister: + ep_unregister_pollwait(ep, epi); + +@@ -1275,18 +1390,35 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests) + int error = 0; + struct file *file = priv; + struct eventpoll *ep = file->private_data; ++ struct eventpoll *ep_tovisit; + struct rb_node *rbp; + struct epitem *epi; + + mutex_lock_nested(&ep->mtx, call_nests + 1); ++ ep->visited = 1; ++ list_add(&ep->visitedllink, &visited_list); + for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) { + epi = rb_entry(rbp, struct epitem, rbn); + if (unlikely(is_file_epoll(epi->ffd.file))) { ++ ep_tovisit = epi->ffd.file->private_data; ++ if (ep_tovisit->visited) ++ continue; + error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, +- ep_loop_check_proc, epi->ffd.file, +- epi->ffd.file->private_data, current); ++ ep_loop_check_proc, epi->ffd.file, ++ ep_tovisit, current); + if (error != 0) + break; ++ } else { ++ /* if we've reached a file that is not associated with ++ * an ep, then then we need to check if the newly added ++ * links are going to add too many wakeup paths. We do ++ * this by adding it to the tfile_check_list, if it's ++ * not already there, and calling reverse_path_check() ++ * during ep_insert() ++ */ ++ if (list_empty(&epi->ffd.file->f_tfile_llink)) ++ list_add(&epi->ffd.file->f_tfile_llink, ++ &tfile_check_list); + } + } + mutex_unlock(&ep->mtx); +@@ -1307,8 +1439,30 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests) + */ + static int ep_loop_check(struct eventpoll *ep, struct file *file) + { +- return ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, ++ int ret; ++ struct eventpoll *ep_cur, *ep_next; ++ ++ ret = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, + ep_loop_check_proc, file, ep, current); ++ /* clear visited list */ ++ list_for_each_entry_safe(ep_cur, ep_next, &visited_list, visitedllink) { ++ ep_cur->visited = 0; ++ list_del(&ep_cur->visitedllink); ++ } ++ return ret; ++} ++ ++static void clear_tfile_check_list(void) ++{ ++ struct file *file; ++ ++ /* first clear the tfile_check_list */ ++ while (!list_empty(&tfile_check_list)) { ++ file = list_first_entry(&tfile_check_list, struct file, ++ f_tfile_llink); ++ list_del_init(&file->f_tfile_llink); ++ } ++ INIT_LIST_HEAD(&tfile_check_list); + } + + /* +@@ -1316,8 +1470,9 @@ static int ep_loop_check(struct eventpoll *ep, struct file *file) + */ + SYSCALL_DEFINE1(epoll_create1, int, flags) + { +- int error; ++ int error, fd; + struct eventpoll *ep = NULL; ++ struct file *file; + + /* Check the EPOLL_* constant for consistency. */ + BUILD_BUG_ON(EPOLL_CLOEXEC != O_CLOEXEC); +@@ -1334,11 +1489,25 @@ SYSCALL_DEFINE1(epoll_create1, int, flags) + * Creates all the items needed to setup an eventpoll file. That is, + * a file structure and a free file descriptor. + */ +- error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep, ++ fd = get_unused_fd_flags(O_RDWR | (flags & O_CLOEXEC)); ++ if (fd < 0) { ++ error = fd; ++ goto out_free_ep; ++ } ++ file = anon_inode_getfile("[eventpoll]", &eventpoll_fops, ep, + O_RDWR | (flags & O_CLOEXEC)); +- if (error < 0) +- ep_free(ep); +- ++ if (IS_ERR(file)) { ++ error = PTR_ERR(file); ++ goto out_free_fd; ++ } ++ fd_install(fd, file); ++ ep->file = file; ++ return fd; ++ ++out_free_fd: ++ put_unused_fd(fd); ++out_free_ep: ++ ep_free(ep); + return error; + } + +@@ -1404,21 +1573,27 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, + /* + * When we insert an epoll file descriptor, inside another epoll file + * descriptor, there is the change of creating closed loops, which are +- * better be handled here, than in more critical paths. ++ * better be handled here, than in more critical paths. While we are ++ * checking for loops we also determine the list of files reachable ++ * and hang them on the tfile_check_list, so we can check that we ++ * haven't created too many possible wakeup paths. + * +- * We hold epmutex across the loop check and the insert in this case, in +- * order to prevent two separate inserts from racing and each doing the +- * insert "at the same time" such that ep_loop_check passes on both +- * before either one does the insert, thereby creating a cycle. ++ * We need to hold the epmutex across both ep_insert and ep_remove ++ * b/c we want to make sure we are looking at a coherent view of ++ * epoll network. + */ +- if (unlikely(is_file_epoll(tfile) && op == EPOLL_CTL_ADD)) { ++ if (op == EPOLL_CTL_ADD || op == EPOLL_CTL_DEL) { + mutex_lock(&epmutex); + did_lock_epmutex = 1; +- error = -ELOOP; +- if (ep_loop_check(ep, tfile) != 0) +- goto error_tgt_fput; + } +- ++ if (op == EPOLL_CTL_ADD) { ++ if (is_file_epoll(tfile)) { ++ error = -ELOOP; ++ if (ep_loop_check(ep, tfile) != 0) ++ goto error_tgt_fput; ++ } else ++ list_add(&tfile->f_tfile_llink, &tfile_check_list); ++ } + + mutex_lock_nested(&ep->mtx, 0); + +@@ -1437,6 +1612,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, + error = ep_insert(ep, &epds, tfile, fd); + } else + error = -EEXIST; ++ clear_tfile_check_list(); + break; + case EPOLL_CTL_DEL: + if (epi) +@@ -1455,7 +1631,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, + mutex_unlock(&ep->mtx); + + error_tgt_fput: +- if (unlikely(did_lock_epmutex)) ++ if (did_lock_epmutex) + mutex_unlock(&epmutex); + + fput(tfile); +diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h +index f362733..657ab55 100644 +--- a/include/linux/eventpoll.h ++++ b/include/linux/eventpoll.h +@@ -61,6 +61,7 @@ struct file; + static inline void eventpoll_init_file(struct file *file) + { + INIT_LIST_HEAD(&file->f_ep_links); ++ INIT_LIST_HEAD(&file->f_tfile_llink); + } + + +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 277f497..93778e0 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -985,6 +985,7 @@ struct file { + #ifdef CONFIG_EPOLL + /* Used by fs/eventpoll.c to link all the hooks to this file */ + struct list_head f_ep_links; ++ struct list_head f_tfile_llink; + #endif /* #ifdef CONFIG_EPOLL */ + struct address_space *f_mapping; + #ifdef CONFIG_DEBUG_WRITECOUNT +-- +1.7.6.4 + diff --git a/kernel.spec b/kernel.spec index 87abab899..d9c2bc78c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -728,6 +728,7 @@ Patch12025: rcu-avoid-just-onlined-cpu-resched.patch Patch12026: block-stray-block-put-after-teardown.patch Patch12027: usb-add-quirk-for-logitech-webcams.patch Patch12029: crypto-register-cryptd-first.patch +Patch12030: epoll-limit-paths.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch @@ -1356,6 +1357,7 @@ ApplyPatch add-appleir-usb-driver.patch ApplyPatch udlfb-bind-framebuffer-to-interface.patch ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch ApplyPatch epoll-fix-spurious-lockdep-warnings.patch +ApplyPatch epoll-limit-paths.patch ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch ApplyPatch block-stray-block-put-after-teardown.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch @@ -2093,6 +2095,9 @@ fi # and build. %changelog +* Tue Oct 25 2011 Josh Boyer +- CVE-2011-1083: excessive in kernel CPU consumption when creating large nested epoll structures (rhbz 748668) + * Mon Oct 24 2011 Josh Boyer - Backport 3 fixed from linux-next to fix dib0700 playback (rhbz 733827) From 4b0fbfcf05883a1b65982b825e4ed9d2507cb80f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 25 Oct 2011 13:52:02 -0400 Subject: [PATCH 113/487] CVE-2011-3347: be2net: promiscuous mode and non-member VLAN packets DoS (rhbz 748691) --- ...r-vlan-pkts-not-received-in-promisco.patch | 63 +++++++++++++++++++ ...-remove-bogus-unlikely-on-vlan-check.patch | 39 ++++++++++++ kernel.spec | 9 +++ 3 files changed, 111 insertions(+) create mode 100644 be2net-non-member-vlan-pkts-not-received-in-promisco.patch create mode 100644 benet-remove-bogus-unlikely-on-vlan-check.patch diff --git a/be2net-non-member-vlan-pkts-not-received-in-promisco.patch b/be2net-non-member-vlan-pkts-not-received-in-promisco.patch new file mode 100644 index 000000000..866473efd --- /dev/null +++ b/be2net-non-member-vlan-pkts-not-received-in-promisco.patch @@ -0,0 +1,63 @@ +From c0e64ef4899df4cedc872871e54e2c069d29e519 Mon Sep 17 00:00:00 2001 +From: Sathya Perla +Date: Tue, 2 Aug 2011 19:57:43 +0000 +Subject: [PATCH] be2net: non-member vlan pkts not received in promiscous mode + +While configuring promiscous mode, explicitly set the +VLAN_PROMISCOUS bit to make this happen. When switching off +promiscous mode, re-program the vids. + +Signed-off-by: Xavier Selvin +Signed-off-by: Sathya Perla +Signed-off-by: David S. Miller +--- + drivers/net/benet/be_cmds.c | 6 ++++-- + drivers/net/benet/be_main.c | 7 +++++++ + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c +index 1c25dbd..73fd949 100644 +--- a/drivers/net/benet/be_cmds.c ++++ b/drivers/net/benet/be_cmds.c +@@ -1586,9 +1586,11 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, bool en) + OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req)); + + req->if_id = cpu_to_le32(adapter->if_handle); +- req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS); ++ req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS ++ | BE_IF_FLAGS_VLAN_PROMISCUOUS); + if (en) +- req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS); ++ req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS ++ | BE_IF_FLAGS_VLAN_PROMISCUOUS); + + sge->pa_hi = cpu_to_le32(upper_32_bits(promiscous_cmd.dma)); + sge->pa_lo = cpu_to_le32(promiscous_cmd.dma & 0xFFFFFFFF); +diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c +index 3b2c5e6..32a5b11 100644 +--- a/drivers/net/benet/be_main.c ++++ b/drivers/net/benet/be_main.c +@@ -728,6 +728,10 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num) + status = be_cmd_vlan_config(adapter, if_handle, vtag, 1, 1, 0); + } + ++ /* No need to further configure vids if in promiscuous mode */ ++ if (adapter->promiscuous) ++ return 0; ++ + if (adapter->vlans_added <= adapter->max_vlans) { + /* Construct VLAN Table to give to HW */ + for (i = 0; i < VLAN_N_VID; i++) { +@@ -787,6 +791,9 @@ static void be_set_multicast_list(struct net_device *netdev) + if (adapter->promiscuous) { + adapter->promiscuous = false; + be_cmd_promiscuous_config(adapter, false); ++ ++ if (adapter->vlans_added) ++ be_vid_config(adapter, false, 0); + } + + /* Enable multicast promisc if num configured exceeds what we support */ +-- +1.7.6.4 + diff --git a/benet-remove-bogus-unlikely-on-vlan-check.patch b/benet-remove-bogus-unlikely-on-vlan-check.patch new file mode 100644 index 000000000..08c00817e --- /dev/null +++ b/benet-remove-bogus-unlikely-on-vlan-check.patch @@ -0,0 +1,39 @@ +From 82f15998fafe683add83f7a11b2e25f919b3cd2d Mon Sep 17 00:00:00 2001 +From: Jiri Pirko +Date: Tue, 25 Oct 2011 13:47:16 -0400 +Subject: [PATCH] benet: remove bogus "unlikely" on vlan check + +Use of unlikely in this place is wrong. Remove it. + +Signed-off-by: Jiri Pirko +Signed-off-by: David S. Miller +Backported-by: Josh Boyer +--- + drivers/net/benet/be_main.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c +index c411bb1..6df0c7e 100644 +--- a/drivers/net/benet/be_main.c ++++ b/drivers/net/benet/be_main.c +@@ -1192,7 +1192,7 @@ static void be_rx_compl_process(struct be_adapter *adapter, + skb->rxhash = rxcp->rss_hash; + + +- if (unlikely(rxcp->vlanf)) ++ if (rxcp->vlanf) + __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag); + + netif_receive_skb(skb); +@@ -1249,7 +1249,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, + if (adapter->netdev->features & NETIF_F_RXHASH) + skb->rxhash = rxcp->rss_hash; + +- if (unlikely(rxcp->vlanf)) ++ if (rxcp->vlanf) + __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag); + + napi_gro_frags(&eq_obj->napi); +-- +1.7.6.4 + diff --git a/kernel.spec b/kernel.spec index d9c2bc78c..f6f27d557 100644 --- a/kernel.spec +++ b/kernel.spec @@ -756,6 +756,10 @@ Patch21002: mmc-Always-check-for-lower-base-frequency-quirk-for-.patch Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch +#rhbz 748691 +Patch21030: be2net-non-member-vlan-pkts-not-received-in-promisco.patch +Patch21031: benet-remove-bogus-unlikely-on-vlan-check.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1394,6 +1398,10 @@ ApplyPatch utrace.patch ApplyPatch 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch ApplyPatch 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch +#rhbz 748691 +ApplyPatch be2net-non-member-vlan-pkts-not-received-in-promisco.patch +ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch + # END OF PATCH APPLICATIONS %endif @@ -2096,6 +2104,7 @@ fi %changelog * Tue Oct 25 2011 Josh Boyer +- CVE-2011-3347: be2net: promiscuous mode and non-member VLAN packets DoS (rhbz 748691) - CVE-2011-1083: excessive in kernel CPU consumption when creating large nested epoll structures (rhbz 748668) * Mon Oct 24 2011 Josh Boyer From 0e7a7173052c1e44eca3020e22efbf62ce5f8b86 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 26 Oct 2011 09:18:09 -0400 Subject: [PATCH 114/487] Add patch to fix XFS memory corruption (rhbz 749166) --- kernel.spec | 9 ++- ...le-memory-corruption-in-xfs_readlink.patch | 77 +++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch diff --git a/kernel.spec b/kernel.spec index f6f27d557..f1729ee2f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -760,6 +760,9 @@ Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch Patch21030: be2net-non-member-vlan-pkts-not-received-in-promisco.patch Patch21031: benet-remove-bogus-unlikely-on-vlan-check.patch +#rhbz 749166 +Patch21050: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1255,6 +1258,7 @@ ApplyPatch linux-2.6-i386-nx-emulation.patch # ext4 # xfs +ApplyPatch xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch # btrfs @@ -2103,6 +2107,9 @@ fi # and build. %changelog +* Wed Oct 26 2011 Josh Boyer +- Add patch to fix XFS memory corruption (rhbz 749166) + * Tue Oct 25 2011 Josh Boyer - CVE-2011-3347: be2net: promiscuous mode and non-member VLAN packets DoS (rhbz 748691) - CVE-2011-1083: excessive in kernel CPU consumption when creating large nested epoll structures (rhbz 748668) diff --git a/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch b/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch new file mode 100644 index 000000000..9e810dba8 --- /dev/null +++ b/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch @@ -0,0 +1,77 @@ +X-Spam-Checker-Version: SpamAssassin 3.4.0-r929098 (2010-03-30) on oss.sgi.com +X-Spam-Level: +X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,J_CHICKENPOX_64 + autolearn=no version=3.4.0-r929098 +Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) + by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id p9I1KBVD036341 + for ; Mon, 17 Oct 2011 20:20:11 -0500 +X-ASG-Debug-ID: 1318901280-3911029d0000-NocioJ +X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi +Received: from hades.usersys.redhat.com (localhost [127.0.0.1]) + by cuda.sgi.com (Spam Firewall) with ESMTP id B9D1DF75F0A + for ; Mon, 17 Oct 2011 18:28:01 -0700 (PDT) +Received: from hades.usersys.redhat.com ([187.60.101.4]) by cuda.sgi.com with ESMTP id 81CuyNdYBqrtvtnD for ; Mon, 17 Oct 2011 18:28:01 -0700 (PDT) +Received: by hades.usersys.redhat.com (Postfix, from userid 500) + id 5B763E089B; Tue, 18 Oct 2011 02:18:59 -0200 (BRST) +From: Carlos Maiolino +To: xfs@oss.sgi.com +Cc: Carlos Maiolino +X-ASG-Orig-Subj: [PATCH] Fix possible memory corruption in xfs_readlink +Subject: [PATCH] Fix possible memory corruption in xfs_readlink +Date: Tue, 18 Oct 2011 02:18:58 -0200 +Message-Id: <1318911538-9174-1-git-send-email-cmaiolino@redhat.com> +X-Mailer: git-send-email 1.7.6.2 +X-Barracuda-Connect: UNKNOWN[187.60.101.4] +X-Barracuda-Start-Time: 1318901282 +X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 +X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com +X-Barracuda-Spam-Score: -1.42 +X-Barracuda-Spam-Status: No, SCORE=-1.42 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=BSF_SC5_MJ1963, RDNS_NONE +X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.2.77645 + Rule breakdown below + pts rule name description + ---- ---------------------- -------------------------------------------------- + 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS + 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 +X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com +X-Virus-Status: Clean + +Fixes a possible memory corruption when the link is larger than +MAXPATHLEN and XFS_DEBUG is not enabled. This also remove the +S_ISLNK assert, since the inode mode is checked previously in +xfs_readlink_by_handle() and via VFS. + +Signed-off-by: Carlos Maiolino +--- + fs/xfs/xfs_vnodeops.c | 11 ++++++++--- + 1 files changed, 8 insertions(+), 3 deletions(-) + +diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c +index 51fc429..c3288be 100644 +--- a/fs/xfs/xfs_vnodeops.c ++++ b/fs/xfs/xfs_vnodeops.c +@@ -123,13 +123,18 @@ xfs_readlink( + + xfs_ilock(ip, XFS_ILOCK_SHARED); + +- ASSERT(S_ISLNK(ip->i_d.di_mode)); +- ASSERT(ip->i_d.di_size <= MAXPATHLEN); +- + pathlen = ip->i_d.di_size; + if (!pathlen) + goto out; + ++ if (pathlen > MAXPATHLEN) { ++ xfs_alert(mp, "%s: inode (%llu) symlink length (%d) too long", ++ __func__, (unsigned long long)ip->i_ino, pathlen); ++ ASSERT(0); ++ return XFS_ERROR(EFSCORRUPTED); ++ } ++ ++ + if (ip->i_df.if_flags & XFS_IFINLINE) { + memcpy(link, ip->i_df.if_u1.if_data, pathlen); + link[pathlen] = '\0'; +-- +1.7.6.2 + From 367ea3a69913b2494df30464844e7c12505e6750 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 26 Oct 2011 12:22:48 -0400 Subject: [PATCH 115/487] Edit changelog to reflect CVE-2011-4077 --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index f1729ee2f..ef73e56c3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2108,7 +2108,7 @@ fi %changelog * Wed Oct 26 2011 Josh Boyer -- Add patch to fix XFS memory corruption (rhbz 749166) +- CVE-2011-4077: xfs: potential buffer overflow in xfs_readlink() (rhbz 749166) * Tue Oct 25 2011 Josh Boyer - CVE-2011-3347: be2net: promiscuous mode and non-member VLAN packets DoS (rhbz 748691) From 06041ed4c0af6842547c88434b6b02392aff0e08 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Wed, 26 Oct 2011 20:17:55 -0500 Subject: [PATCH 116/487] - Rebuilt for glibc bug#747377 --- kernel.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index ef73e56c3..1aaf2c65b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2107,6 +2107,9 @@ fi # and build. %changelog +* Wed Oct 26 2011 Fedora Release Engineering - 3.1.0-5 +- Rebuilt for glibc bug#747377 + * Wed Oct 26 2011 Josh Boyer - CVE-2011-4077: xfs: potential buffer overflow in xfs_readlink() (rhbz 749166) From 4cce38ece8fc1fe23dc78dffc84121c5ba7a0ac6 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 28 Oct 2011 15:49:27 -0400 Subject: [PATCH 117/487] Shutup floppy.c. Abrt files enough bugs as it is (rhbz 749887) --- floppy-drop-disable_hlt-warning.patch | 13 +++++++++++++ kernel.spec | 7 ++++++- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 floppy-drop-disable_hlt-warning.patch diff --git a/floppy-drop-disable_hlt-warning.patch b/floppy-drop-disable_hlt-warning.patch new file mode 100644 index 000000000..8f0849e1e --- /dev/null +++ b/floppy-drop-disable_hlt-warning.patch @@ -0,0 +1,13 @@ +diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c +index 9955a53..aef66d1 100644 +--- a/drivers/block/floppy.c ++++ b/drivers/block/floppy.c +@@ -1038,7 +1038,7 @@ static void floppy_disable_hlt(void) + { + unsigned long flags; + +- WARN_ONCE(1, "floppy_disable_hlt() scheduled for removal in 2012"); ++ printk(KERN_INFO "floppy_disable_hlt() scheduled for removal in 2012"); + spin_lock_irqsave(&floppy_hlt_lock, flags); + if (!hlt_disabled) { + hlt_disabled = 1; diff --git a/kernel.spec b/kernel.spec index 1aaf2c65b..79ff54bf3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 5 +%global baserelease 6 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -664,6 +664,7 @@ Patch452: linux-2.6.30-no-pcspkr-modalias.patch Patch460: linux-2.6-serial-460800.patch Patch470: die-floppy-die.patch +Patch471: floppy-drop-disable_hlt-warning.patch Patch510: linux-2.6-silence-noise.patch Patch530: linux-2.6-silence-fbcon-logo.patch @@ -1304,6 +1305,7 @@ ApplyPatch linux-2.6-input-kill-stupid-messages.patch # stop floppy.ko from autoloading during udev... ApplyPatch die-floppy-die.patch +ApplyPatch floppy-drop-disable_hlt-warning.patch ApplyPatch linux-2.6.30-no-pcspkr-modalias.patch @@ -2107,6 +2109,9 @@ fi # and build. %changelog +* Fri Oct 28 2011 Josh Boyer +- Add patch to prevent tracebacks on a warning in floppy.c (rhbz 749887) + * Wed Oct 26 2011 Fedora Release Engineering - 3.1.0-5 - Rebuilt for glibc bug#747377 From f746a4af91d2570005dbabe02b289924084f9768 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 31 Oct 2011 21:01:48 -0400 Subject: [PATCH 118/487] Add patch to fix integer overflow of points in oom_badness (rhbz 750402) --- kernel.spec | 8 ++ oom-fix-integer-overflow-of-points.patch | 100 +++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 oom-fix-integer-overflow-of-points.patch diff --git a/kernel.spec b/kernel.spec index 79ff54bf3..b97c11ec8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -764,6 +764,8 @@ Patch21031: benet-remove-bogus-unlikely-on-vlan-check.patch #rhbz 749166 Patch21050: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch +Patch21070: oom-fix-integer-overflow-of-points.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1408,6 +1410,9 @@ ApplyPatch 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch ApplyPatch be2net-non-member-vlan-pkts-not-received-in-promisco.patch ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch +#rhbz 750402 +ApplyPatch oom-fix-integer-overflow-of-points.patch + # END OF PATCH APPLICATIONS %endif @@ -2109,6 +2114,9 @@ fi # and build. %changelog +* Mon Oct 31 2011 Josh Boyer +- Add patch to fix integer overflow of points in oom_badness (rhbz 750402) + * Fri Oct 28 2011 Josh Boyer - Add patch to prevent tracebacks on a warning in floppy.c (rhbz 749887) diff --git a/oom-fix-integer-overflow-of-points.patch b/oom-fix-integer-overflow-of-points.patch new file mode 100644 index 000000000..02f6a8f72 --- /dev/null +++ b/oom-fix-integer-overflow-of-points.patch @@ -0,0 +1,100 @@ + +Delivered-To: jwboyer@gmail.com +Received: by 10.220.45.11 with SMTP id c11cs62970vcf; + Mon, 31 Oct 2011 08:56:49 -0700 (PDT) +Received: by 10.101.15.19 with SMTP id s19mr2706064ani.103.1320076596057; + Mon, 31 Oct 2011 08:56:36 -0700 (PDT) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id x8si7676575ani.27.2011.10.31.08.56.32; + Mon, 31 Oct 2011 08:56:36 -0700 (PDT) +Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=linux-kernel-owner@vger.kernel.org +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S934545Ab1JaP4X (ORCPT + 99 others); + Mon, 31 Oct 2011 11:56:23 -0400 +Received: from mx1.redhat.com ([209.132.183.28]:23653 "EHLO mx1.redhat.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S934538Ab1JaP4X (ORCPT ); + Mon, 31 Oct 2011 11:56:23 -0400 +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p9VFuHOO027543 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Mon, 31 Oct 2011 11:56:18 -0400 +Received: from dhcp-26-164.brq.redhat.com (dhcp-26-164.brq.redhat.com [10.34.26.164]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p9VFuEK3018476; + Mon, 31 Oct 2011 11:56:15 -0400 +From: Frantisek Hrbata +To: rientjes@google.com +Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, + akpm@linux-foundation.org, kosaki.motohiro@jp.fujitsu.com, + oleg@redhat.com, minchan.kim@gmail.com, stable@kernel.org, + eteo@redhat.com, pmatouse@redhat.com +Subject: [PATCH v2] oom: fix integer overflow of points in oom_badness +Date: Mon, 31 Oct 2011 16:56:09 +0100 +Message-Id: <1320076569-23872-1-git-send-email-fhrbata@redhat.com> +In-Reply-To: <1320048865-13175-1-git-send-email-fhrbata@redhat.com> +References: <1320048865-13175-1-git-send-email-fhrbata@redhat.com> +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org + +An integer overflow will happen on 64bit archs if task's sum of rss, swapents +and nr_ptes exceeds (2^31)/1000 value. This was introduced by commit + +f755a04 oom: use pte pages in OOM score + +where the oom score computation was divided into several steps and it's no +longer computed as one expression in unsigned long(rss, swapents, nr_pte are +unsigned long), where the result value assigned to points(int) is in +range(1..1000). So there could be an int overflow while computing + +176 points *= 1000; + +and points may have negative value. Meaning the oom score for a mem hog task +will be one. + +196 if (points <= 0) +197 return 1; + +For example: +[ 3366] 0 3366 35390480 24303939 5 0 0 oom01 +Out of memory: Kill process 3366 (oom01) score 1 or sacrifice child + +Here the oom1 process consumes more than 24303939(rss)*4096~=92GB physical +memory, but it's oom score is one. + +In this situation the mem hog task is skipped and oom killer kills another and +most probably innocent task with oom score greater than one. + +The points variable should be of type long instead of int to prevent the int +overflow. + +Signed-off-by: Frantisek Hrbata +--- + mm/oom_kill.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/mm/oom_kill.c b/mm/oom_kill.c +index 626303b..e9a1785 100644 +--- a/mm/oom_kill.c ++++ b/mm/oom_kill.c +@@ -162,7 +162,7 @@ static bool oom_unkillable_task(struct task_struct *p, + unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem, + const nodemask_t *nodemask, unsigned long totalpages) + { +- int points; ++ long points; + + if (oom_unkillable_task(p, mem, nodemask)) + return 0; +-- +1.7.6.4 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ From 3ee6d6d1f9ddb6edff21722086fc3f85ccb2ac71 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 31 Oct 2011 21:10:19 -0400 Subject: [PATCH 119/487] Add CVE number in changelog (rhbz 750402) --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index b97c11ec8..e725d2074 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2115,7 +2115,7 @@ fi %changelog * Mon Oct 31 2011 Josh Boyer -- Add patch to fix integer overflow of points in oom_badness (rhbz 750402) +-CVE-2011-4097: oom_badness() integer overflow (rhbz 750402) * Fri Oct 28 2011 Josh Boyer - Add patch to prevent tracebacks on a warning in floppy.c (rhbz 749887) From 1d898c7c860661cacaa2823add8c676073be38de Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 1 Nov 2011 11:09:01 -0400 Subject: [PATCH 120/487] Drop x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid (rhbz 748516) Discussed this with Matt Fleming and Matthew Garrett. The patch was added to fix an oops case on 32-bit EFI machines, but we don't support 32-bit EFI and it is causing regressions on 64-bit EFI Macs. Drop the patch for now. --- kernel.spec | 10 +- ...a-with-an-ioremap-address-is-invalid.patch | 211 ------------------ 2 files changed, 5 insertions(+), 216 deletions(-) delete mode 100644 x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch diff --git a/kernel.spec b/kernel.spec index e725d2074..9b399af0e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 6 +%global baserelease 7 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -721,7 +721,6 @@ Patch12010: add-appleir-usb-driver.patch Patch12016: disable-i8042-check-on-apple-mac.patch Patch12021: udlfb-bind-framebuffer-to-interface.patch -Patch12022: x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch Patch12024: epoll-fix-spurious-lockdep-warnings.patch @@ -1376,8 +1375,6 @@ ApplyPatch usb-add-quirk-for-logitech-webcams.patch ApplyPatch crypto-register-cryptd-first.patch -ApplyPatch x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch - # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -2114,8 +2111,11 @@ fi # and build. %changelog +* Tue Nov 1 2011 Josh Boyer 3.1.0-7 +- Drop x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid (rhbz 748516) + * Mon Oct 31 2011 Josh Boyer --CVE-2011-4097: oom_badness() integer overflow (rhbz 750402) +- CVE-2011-4097: oom_badness() integer overflow (rhbz 750402) * Fri Oct 28 2011 Josh Boyer - Add patch to prevent tracebacks on a warning in floppy.c (rhbz 749887) diff --git a/x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch b/x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch deleted file mode 100644 index f05567fe3..000000000 --- a/x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid.patch +++ /dev/null @@ -1,211 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Matt Fleming -Newsgroups: gmane.linux.kernel -Subject: [PATCH v2] x86, efi: Calling __pa() with an ioremap'd address is invalid -Date: Fri, 14 Oct 2011 12:36:45 +0100 -Lines: 160 -Approved: news@gmane.org -Message-ID: <1318592205-11193-1-git-send-email-matt@console-pimps.org> -NNTP-Posting-Host: lo.gmane.org -X-Trace: dough.gmane.org 1318592224 30879 80.91.229.12 (14 Oct 2011 11:37:04 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Fri, 14 Oct 2011 11:37:04 +0000 (UTC) -Cc: Thomas Gleixner , Ingo Molnar , - "H. Peter Anvin" , Zhang Rui , - Huang Ying , - linux-kernel@vger.kernel.org -To: Matthew Garrett -Original-X-From: linux-kernel-owner@vger.kernel.org Fri Oct 14 13:36:59 2011 -Return-path: -Envelope-to: glk-linux-kernel-3@lo.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1REg4Q-0001UQ-SA - for glk-linux-kernel-3@lo.gmane.org; Fri, 14 Oct 2011 13:36:59 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1755420Ab1JNLgv (ORCPT ); - Fri, 14 Oct 2011 07:36:51 -0400 -Original-Received: from arkanian.console-pimps.org ([212.110.184.194]:46859 "EHLO - arkanian.console-pimps.org" rhost-flags-OK-OK-OK-OK) - by vger.kernel.org with ESMTP id S1751315Ab1JNLgu (ORCPT - ); - Fri, 14 Oct 2011 07:36:50 -0400 -Original-Received: by arkanian.console-pimps.org (Postfix, from userid 1002) - id 443C1C0009; Fri, 14 Oct 2011 12:36:49 +0100 (BST) -X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on - arkanian.vm.bytemark.co.uk -X-Spam-Level: -X-Spam-Status: No, score=-5.3 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00 - autolearn=ham version=3.2.5 -Original-Received: from localhost (02ddb86b.bb.sky.com [2.221.184.107]) - by arkanian.console-pimps.org (Postfix) with ESMTPSA id F0D40C0008; - Fri, 14 Oct 2011 12:36:47 +0100 (BST) -X-Mailer: git-send-email 1.7.4.4 -Original-Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel:1203294 -Archived-At: - -From: Matt Fleming - -If we encounter an efi_memory_desc_t without EFI_MEMORY_WB set in -->attribute we currently call set_memory_uc(), which in turn calls -__pa() on a potentially ioremap'd address. On CONFIG_X86_32 this is -invalid, resulting in the following oops, - - BUG: unable to handle kernel paging request at f7f22280 - IP: [] reserve_ram_pages_type+0x89/0x210 - *pdpt = 0000000001978001 *pde = 0000000001ffb067 *pte = 0000000000000000 - Oops: 0000 [#1] PREEMPT SMP - Modules linked in: - - Pid: 0, comm: swapper Not tainted 3.0.0-acpi-efi-0805 #3 - EIP: 0060:[] EFLAGS: 00010202 CPU: 0 - EIP is at reserve_ram_pages_type+0x89/0x210 - EAX: 0070e280 EBX: 38714000 ECX: f7814000 EDX: 00000000 - ESI: 00000000 EDI: 38715000 EBP: c189fef0 ESP: c189fea8 - DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 - Process swapper (pid: 0, ti=c189e000 task=c18bbe60 task.ti=c189e000) - Stack: - 80000200 ff108000 00000000 c189ff00 00038714 00000000 00000000 c189fed0 - c104f8ca 00038714 00000000 00038715 00000000 00000000 00038715 00000000 - 00000010 38715000 c189ff48 c1025aff 38715000 00000000 00000010 00000000 - Call Trace: - [] ? page_is_ram+0x1a/0x40 - [] reserve_memtype+0xdf/0x2f0 - [] set_memory_uc+0x49/0xa0 - [] efi_enter_virtual_mode+0x1c2/0x3aa - [] start_kernel+0x291/0x2f2 - [] ? loglevel+0x1b/0x1b - [] i386_start_kernel+0xbf/0xc8 - -So, if we're ioremap'ing an address range let's setup the mapping with -the correct caching attribute instead of modifying it after the fact. - -Also, take this opportunity to unify the 32/64-bit efi_ioremap() -implementations because they can both be implemented with -ioremap_{cache,nocache}. When asked about the original reason behind -using init_memory_mapping() for the 64-bit version Huang Ying said, - - "The intention of init_memory_mapping() usage is to make EFI virtual - address unchanged after kexec. But in fact, init_memory_mapping() - can not handle some memory range, so ioremap_xxx() is introduced as - a fix. Now we decide to use ioremap_xxx() anyway and use some other - scheme for kexec support, so init_memory_mapping() here is - unnecessary. IMHO, init_memory_mapping() is not as good as - ioremap_xxx() here." - -And because efi_ioremap() now consists of 4 lines, let's just inline -it directly into the one callsite in efi_enter_virtual_mode(). - -Cc: Thomas Gleixner -Cc: Ingo Molnar -Cc: H. Peter Anvin -Cc: Matthew Garrett -Cc: Zhang Rui -Cc: Huang Ying -Cc: stable@kernel.org -Signed-off-by: Matt Fleming ---- - arch/x86/include/asm/efi.h | 5 ----- - arch/x86/platform/efi/efi.c | 24 ++++++++++++++---------- - arch/x86/platform/efi/efi_64.c | 17 ----------------- - 3 files changed, 14 insertions(+), 32 deletions(-) - -diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h -index 7093e4a..b8d8bfc 100644 ---- a/arch/x86/include/asm/efi.h -+++ b/arch/x86/include/asm/efi.h -@@ -33,8 +33,6 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...); - #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \ - efi_call_virt(f, a1, a2, a3, a4, a5, a6) - --#define efi_ioremap(addr, size, type) ioremap_cache(addr, size) -- - #else /* !CONFIG_X86_32 */ - - extern u64 efi_call0(void *fp); -@@ -84,9 +82,6 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3, - efi_call6((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ - (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6)) - --extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, -- u32 type); -- - #endif /* CONFIG_X86_32 */ - - extern int add_efi_memmap; -diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c -index 3ae4128..6ea011c 100644 ---- a/arch/x86/platform/efi/efi.c -+++ b/arch/x86/platform/efi/efi.c -@@ -670,10 +670,21 @@ void __init efi_enter_virtual_mode(void) - end_pfn = PFN_UP(end); - if (end_pfn <= max_low_pfn_mapped - || (end_pfn > (1UL << (32 - PAGE_SHIFT)) -- && end_pfn <= max_pfn_mapped)) -+ && end_pfn <= max_pfn_mapped)) { - va = __va(md->phys_addr); -- else -- va = efi_ioremap(md->phys_addr, size, md->type); -+ -+ if (!(md->attribute & EFI_MEMORY_WB)) { -+ addr = (u64) (unsigned long)va; -+ npages = md->num_pages; -+ memrange_efi_to_native(&addr, &npages); -+ set_memory_uc(addr, npages); -+ } -+ } else { -+ if (!(md->attribute & EFI_MEMORY_WB)) -+ va = ioremap_nocache(md->phys_addr, size); -+ else -+ va = ioremap_cache(md->phys_addr, size); -+ } - - md->virt_addr = (u64) (unsigned long) va; - -@@ -683,13 +694,6 @@ void __init efi_enter_virtual_mode(void) - continue; - } - -- if (!(md->attribute & EFI_MEMORY_WB)) { -- addr = md->virt_addr; -- npages = md->num_pages; -- memrange_efi_to_native(&addr, &npages); -- set_memory_uc(addr, npages); -- } -- - systab = (u64) (unsigned long) efi_phys.systab; - if (md->phys_addr <= systab && systab < end) { - systab += md->virt_addr - md->phys_addr; -diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c -index ac3aa54..312250c 100644 ---- a/arch/x86/platform/efi/efi_64.c -+++ b/arch/x86/platform/efi/efi_64.c -@@ -80,20 +80,3 @@ void __init efi_call_phys_epilog(void) - local_irq_restore(efi_flags); - early_code_mapping_set_exec(0); - } -- --void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, -- u32 type) --{ -- unsigned long last_map_pfn; -- -- if (type == EFI_MEMORY_MAPPED_IO) -- return ioremap(phys_addr, size); -- -- last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size); -- if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size) { -- unsigned long top = last_map_pfn << PAGE_SHIFT; -- efi_ioremap(top, size - (top - phys_addr), type); -- } -- -- return (void __iomem *)__va(phys_addr); --} --- -1.7.4.4 - From 29b2acac723e8c16ffb9150051ba325e3dc85617 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 1 Nov 2011 12:56:19 -0400 Subject: [PATCH 121/487] Add another Sony laptop to the nonvs blacklist. (rhbz 641789) --- acpi-sony-nonvs-blacklist.patch | 19 +++++++++++++++++++ kernel.spec | 3 +++ 2 files changed, 22 insertions(+) diff --git a/acpi-sony-nonvs-blacklist.patch b/acpi-sony-nonvs-blacklist.patch index f332c6443..db500e8bf 100644 --- a/acpi-sony-nonvs-blacklist.patch +++ b/acpi-sony-nonvs-blacklist.patch @@ -17,3 +17,22 @@ index 3ed80b2..17fc718 100644 .ident = "Sony Vaio VGN-SR11M", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), +diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c +index 0e46fae..6d9a3ab 100644 +--- a/drivers/acpi/sleep.c ++++ b/drivers/acpi/sleep.c +@@ -398,6 +398,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { + }, + { + .callback = init_nvs_nosave, ++ .ident = "Sony Vaio VPCEB17FX", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"), ++ }, ++ }, ++ { ++ .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-SR11M", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), diff --git a/kernel.spec b/kernel.spec index 9b399af0e..fb0cd6ff4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2111,6 +2111,9 @@ fi # and build. %changelog +* Tue Nov 01 2011 Dave Jones 3.1.0-8 +- Add another Sony laptop to the nonvs blacklist. (rhbz 641789) + * Tue Nov 1 2011 Josh Boyer 3.1.0-7 - Drop x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid (rhbz 748516) From 58cf40bfda78ddd6ed33933d705bb099754ad96c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 1 Nov 2011 14:09:24 -0400 Subject: [PATCH 122/487] allow building the perf rpm for ARM (rhbz 741325) --- kernel.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index fb0cd6ff4..8860c4c78 100644 --- a/kernel.spec +++ b/kernel.spec @@ -398,13 +398,13 @@ Summary: The Linux kernel # we build a up kernel on armv5tel. its used for qemu. %ifnarch armv5tel %define with_up 0 +%define with_perf 0 %endif # we only build headers on the base arm arches # just like we used to only build them on i386 for x86 %ifnarch armv5tel armv7hl %define with_headers 0 %endif -%define with_perf 0 %endif %if %{nopatches} @@ -2111,6 +2111,9 @@ fi # and build. %changelog +* Tue Nov 01 2011 Dave Jones 3.1.0-8 +- allow building the perf rpm for ARM (rhbz 741325) + * Tue Nov 01 2011 Dave Jones 3.1.0-8 - Add another Sony laptop to the nonvs blacklist. (rhbz 641789) From 18db0fc8c6597a6831b141228141b22a6518cac7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 2 Nov 2011 09:55:36 -0400 Subject: [PATCH 123/487] Add patch to fix oops when removing wmi module (rhbz 706574) --- ...rly-cleanup-devices-to-avoid-crashes.patch | 41 +++++++++++++++++++ kernel.spec | 11 ++++- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 WMI-properly-cleanup-devices-to-avoid-crashes.patch diff --git a/WMI-properly-cleanup-devices-to-avoid-crashes.patch b/WMI-properly-cleanup-devices-to-avoid-crashes.patch new file mode 100644 index 000000000..1119d25f5 --- /dev/null +++ b/WMI-properly-cleanup-devices-to-avoid-crashes.patch @@ -0,0 +1,41 @@ +From 023b9565972a4a5e0f01b9aa32680af6e9b5c388 Mon Sep 17 00:00:00 2001 +From: Dmitry Torokhov +Date: Wed, 7 Sep 2011 15:00:02 -0700 +Subject: [PATCH] WMI: properly cleanup devices to avoid crashes + +We need to remove devices that we destroy from the list, otherwise +we'll crash if there are more than one "_WDG" methods in DSDT. + +This fixes https://bugzilla.kernel.org/show_bug.cgi?id=32052 + +Tested-by: Ilya Tumaykin +Cc: stable@kernel.org +Signed-off-by: Dmitry Torokhov +Acked-by: Carlos Corbacho +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/wmi.c | 6 +++++- + 1 files changed, 5 insertions(+), 1 deletions(-) + +diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c +index f23d5a8..9b88be4 100644 +--- a/drivers/platform/x86/wmi.c ++++ b/drivers/platform/x86/wmi.c +@@ -754,9 +754,13 @@ static void wmi_free_devices(void) + struct wmi_block *wblock, *next; + + /* Delete devices for all the GUIDs */ +- list_for_each_entry_safe(wblock, next, &wmi_block_list, list) ++ list_for_each_entry_safe(wblock, next, &wmi_block_list, list) { ++ list_del(&wblock->list); + if (wblock->dev.class) + device_unregister(&wblock->dev); ++ else ++ kfree(wblock); ++ } + } + + static bool guid_already_parsed(const char *guid_string) +-- +1.7.6.4 + diff --git a/kernel.spec b/kernel.spec index 8860c4c78..1893ab551 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 7 +%global baserelease 8 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -765,6 +765,9 @@ Patch21050: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch Patch21070: oom-fix-integer-overflow-of-points.patch +#rhbz 706574 +Patch21071: WMI-properly-cleanup-devices-to-avoid-crashes.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1410,6 +1413,9 @@ ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch #rhbz 750402 ApplyPatch oom-fix-integer-overflow-of-points.patch +#rhbz 706574 +ApplyPatch WMI-properly-cleanup-devices-to-avoid-crashes.patch + # END OF PATCH APPLICATIONS %endif @@ -2111,6 +2117,9 @@ fi # and build. %changelog +* Wed Nov 02 2011 Josh Boyer +- Add patch to fix oops when removing wmi module (rhbz 706574) + * Tue Nov 01 2011 Dave Jones 3.1.0-8 - allow building the perf rpm for ARM (rhbz 741325) From 436da03d79647ec0e9887f553d190c4b137c8d12 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 3 Nov 2011 09:39:46 -0400 Subject: [PATCH 124/487] Add commits queued for 3.2 for elantech driver (rhbz 728607) --- elantech.patch | 2116 ++++++++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 11 +- 2 files changed, 2126 insertions(+), 1 deletion(-) create mode 100644 elantech.patch diff --git a/elantech.patch b/elantech.patch new file mode 100644 index 000000000..255efd2b6 --- /dev/null +++ b/elantech.patch @@ -0,0 +1,2116 @@ +From 13ac768d9a8731c8b3bab7d6c86520f290272fe7 Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Fri, 9 Sep 2011 10:22:19 -0700 +Subject: Input: elantech - correct x, y value range for v2 hardware +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +x, y values are actually 12-bit long. Also update protocol document to +reflect the change. + +Signed-off-by: JJ Ding +Acked-by: Daniel Kurtz +Acked-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + Documentation/input/elantech.txt | 8 ++++---- + drivers/input/mouse/elantech.c | 8 ++++---- + 2 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt +index db798af..bce9941 100644 +--- a/Documentation/input/elantech.txt ++++ b/Documentation/input/elantech.txt +@@ -389,14 +389,14 @@ byte 0: + byte 1: + + bit 7 6 5 4 3 2 1 0 +- p7 p6 p5 p4 . x10 x9 x8 ++ p7 p6 p5 p4 x11 x10 x9 x8 + + byte 2: + + bit 7 6 5 4 3 2 1 0 + x7 x6 x5 x4 x3 x2 x1 x0 + +- x10..x0 = absolute x value (horizontal) ++ x11..x0 = absolute x value (horizontal) + + byte 3: + +@@ -420,7 +420,7 @@ byte 3: + byte 4: + + bit 7 6 5 4 3 2 1 0 +- p3 p1 p2 p0 . . y9 y8 ++ p3 p1 p2 p0 y11 y10 y9 y8 + + p7..p0 = pressure (not EF113) + +@@ -429,7 +429,7 @@ byte 5: + bit 7 6 5 4 3 2 1 0 + y7 y6 y5 y4 y3 y2 y1 y0 + +- y9..y0 = absolute y value (vertical) ++ y11..y0 = absolute y value (vertical) + + + 4.2.2 Two finger touch +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 3250356..da161da 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -290,15 +290,15 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + /* pass through... */ + case 1: + /* +- * byte 1: . . . . . x10 x9 x8 ++ * byte 1: . . . . x11 x10 x9 x8 + * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 + */ +- x1 = ((packet[1] & 0x07) << 8) | packet[2]; ++ x1 = ((packet[1] & 0x0f) << 8) | packet[2]; + /* +- * byte 4: . . . . . . y9 y8 ++ * byte 4: . . . . y11 y10 y9 y8 + * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 + */ +- y1 = ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5]); ++ y1 = ETP_YMAX_V2 - (((packet[4] & 0x0f) << 8) | packet[5]); + + input_report_abs(dev, ABS_X, x1); + input_report_abs(dev, ABS_Y, y1); +-- +1.7.6.4 + + +From c47c9334b4ebb6ecb565d9bf834df170fcd09484 Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Fri, 9 Sep 2011 10:22:58 -0700 +Subject: Input: elantech - get rid of ETP_2FT_* in elantech.h +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For two finger touches the coordinate of each finger gets reported +separately but with reduced resolution. + +With this change, we now have the same range for ST and MT data and +scale MT data because it has lower resolution to match ST. + +Suggested-by: Dmitry Torokhov +Signed-off-by: JJ Ding +Acked-by: Daniel Kurtz +Acked-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.c | 28 +++++++++++++--------------- + drivers/input/mouse/elantech.h | 11 ----------- + 2 files changed, 13 insertions(+), 26 deletions(-) + +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index da161da..cd8e2e5 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -273,11 +273,11 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + struct elantech_data *etd = psmouse->private; + struct input_dev *dev = psmouse->dev; + unsigned char *packet = psmouse->packet; +- unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0, width = 0, pres = 0; ++ unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0; ++ unsigned int width = 0, pres = 0; + + /* byte 0: n1 n0 . . . . R L */ + fingers = (packet[0] & 0xc0) >> 6; +- input_report_key(dev, BTN_TOUCH, fingers != 0); + + switch (fingers) { + case 3: +@@ -300,9 +300,6 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + */ + y1 = ETP_YMAX_V2 - (((packet[4] & 0x0f) << 8) | packet[5]); + +- input_report_abs(dev, ABS_X, x1); +- input_report_abs(dev, ABS_Y, y1); +- + pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); + width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); + break; +@@ -314,22 +311,18 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + * byte 0: . . ay8 ax8 . . . . + * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 + */ +- x1 = ((packet[0] & 0x10) << 4) | packet[1]; ++ x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2; + /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ +- y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); ++ y1 = ETP_YMAX_V2 - ++ ((((packet[0] & 0x20) << 3) | packet[2]) << 2); + /* + * byte 3: . . by8 bx8 . . . . + * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 + */ +- x2 = ((packet[3] & 0x10) << 4) | packet[4]; ++ x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2; + /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ +- y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); +- /* +- * For compatibility with the X Synaptics driver scale up +- * one coordinate and report as ordinary mouse movent +- */ +- input_report_abs(dev, ABS_X, x1 << 2); +- input_report_abs(dev, ABS_Y, y1 << 2); ++ y2 = ETP_YMAX_V2 - ++ ((((packet[3] & 0x20) << 3) | packet[5]) << 2); + + /* Unknown so just report sensible values */ + pres = 127; +@@ -337,6 +330,11 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + break; + } + ++ input_report_key(dev, BTN_TOUCH, fingers != 0); ++ if (fingers != 0) { ++ input_report_abs(dev, ABS_X, x1); ++ input_report_abs(dev, ABS_Y, y1); ++ } + elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); + input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); + input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); +diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h +index fabb2b9..1c5894e 100644 +--- a/drivers/input/mouse/elantech.h ++++ b/drivers/input/mouse/elantech.h +@@ -82,17 +82,6 @@ + #define ETP_WMIN_V2 0 + #define ETP_WMAX_V2 15 + +-/* +- * For two finger touches the coordinate of each finger gets reported +- * separately but with reduced resolution. +- */ +-#define ETP_2FT_FUZZ 4 +- +-#define ETP_2FT_XMIN ( 0 + ETP_2FT_FUZZ) +-#define ETP_2FT_XMAX (288 - ETP_2FT_FUZZ) +-#define ETP_2FT_YMIN ( 0 + ETP_2FT_FUZZ) +-#define ETP_2FT_YMAX (192 - ETP_2FT_FUZZ) +- + struct elantech_data { + unsigned char reg_10; + unsigned char reg_11; +-- +1.7.6.4 + + +From aa719e391c1769c93ec42a30daffa4ffa2a8503c Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Fri, 9 Sep 2011 10:26:16 -0700 +Subject: Input: elantech - use firmware provided x, y ranges +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +With newer hardware, the touchpad provides range info. +Let's use it. + +Signed-off-by: JJ Ding +Acked-by: Daniel Kurtz +Acked-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.c | 71 +++++++++++++++++++++++++++++++-------- + drivers/input/mouse/elantech.h | 3 +- + 2 files changed, 58 insertions(+), 16 deletions(-) + +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index cd8e2e5..296b6a6 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -223,7 +223,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) + input_report_abs(dev, ABS_X, + ((packet[1] & 0x0c) << 6) | packet[2]); + input_report_abs(dev, ABS_Y, +- ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3])); ++ etd->y_max - (((packet[1] & 0x03) << 8) | packet[3])); + } + + input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); +@@ -233,7 +233,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) + input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); + + if (etd->fw_version < 0x020000 && +- (etd->capabilities & ETP_CAP_HAS_ROCKER)) { ++ (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) { + /* rocker up */ + input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); + /* rocker down */ +@@ -298,7 +298,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + * byte 4: . . . . y11 y10 y9 y8 + * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 + */ +- y1 = ETP_YMAX_V2 - (((packet[4] & 0x0f) << 8) | packet[5]); ++ y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); + + pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); + width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); +@@ -313,7 +313,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + */ + x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2; + /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ +- y1 = ETP_YMAX_V2 - ++ y1 = etd->y_max - + ((((packet[0] & 0x20) << 3) | packet[2]) << 2); + /* + * byte 3: . . by8 bx8 . . . . +@@ -321,7 +321,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + */ + x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2; + /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ +- y2 = ETP_YMAX_V2 - ++ y2 = etd->y_max - + ((((packet[3] & 0x20) << 3) | packet[5]) << 2); + + /* Unknown so just report sensible values */ +@@ -468,6 +468,41 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) + return rc; + } + ++static void elantech_set_range(struct psmouse *psmouse, ++ unsigned int *x_min, unsigned int *y_min, ++ unsigned int *x_max, unsigned int *y_max) ++{ ++ struct elantech_data *etd = psmouse->private; ++ int i; ++ ++ switch (etd->hw_version) { ++ case 1: ++ *x_min = ETP_XMIN_V1; ++ *y_min = ETP_YMIN_V1; ++ *x_max = ETP_XMAX_V1; ++ *y_max = ETP_YMAX_V1; ++ break; ++ ++ case 2: ++ if (etd->fw_version == 0x020800 || ++ etd->fw_version == 0x020b00 || ++ etd->fw_version == 0x020030) { ++ *x_min = ETP_XMIN_V2; ++ *y_min = ETP_YMIN_V2; ++ *x_max = ETP_XMAX_V2; ++ *y_max = ETP_YMAX_V2; ++ } else { ++ i = (etd->fw_version > 0x020800 && ++ etd->fw_version < 0x020900) ? 1 : 2; ++ *x_min = 0; ++ *y_min = 0; ++ *x_max = (etd->capabilities[1] - i) * 64; ++ *y_max = (etd->capabilities[2] - i) * 64; ++ } ++ break; ++ } ++} ++ + /* + * Set the appropriate event bits for the input subsystem + */ +@@ -475,6 +510,9 @@ static void elantech_set_input_params(struct psmouse *psmouse) + { + struct input_dev *dev = psmouse->dev; + struct elantech_data *etd = psmouse->private; ++ unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0; ++ ++ elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max); + + __set_bit(EV_KEY, dev->evbit); + __set_bit(EV_ABS, dev->evbit); +@@ -492,18 +530,18 @@ static void elantech_set_input_params(struct psmouse *psmouse) + case 1: + /* Rocker button */ + if (etd->fw_version < 0x020000 && +- (etd->capabilities & ETP_CAP_HAS_ROCKER)) { ++ (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) { + __set_bit(BTN_FORWARD, dev->keybit); + __set_bit(BTN_BACK, dev->keybit); + } +- input_set_abs_params(dev, ABS_X, ETP_XMIN_V1, ETP_XMAX_V1, 0, 0); +- input_set_abs_params(dev, ABS_Y, ETP_YMIN_V1, ETP_YMAX_V1, 0, 0); ++ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); ++ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); + break; + + case 2: + __set_bit(BTN_TOOL_QUADTAP, dev->keybit); +- input_set_abs_params(dev, ABS_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); +- input_set_abs_params(dev, ABS_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); ++ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); ++ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); + if (etd->reports_pressure) { + input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, + ETP_PMAX_V2, 0, 0); +@@ -512,10 +550,12 @@ static void elantech_set_input_params(struct psmouse *psmouse) + } + __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); + input_mt_init_slots(dev, 2); +- input_set_abs_params(dev, ABS_MT_POSITION_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); +- input_set_abs_params(dev, ABS_MT_POSITION_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); ++ input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); ++ input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); + break; + } ++ ++ etd->y_max = y_max; + } + + struct elantech_attr_data { +@@ -769,13 +809,14 @@ int elantech_init(struct psmouse *psmouse) + pr_info("assuming hardware version %d, firmware version %d.%d.%d\n", + etd->hw_version, param[0], param[1], param[2]); + +- if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) { ++ if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, ++ etd->capabilities)) { + pr_err("failed to query capabilities.\n"); + goto init_fail; + } + pr_info("Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n", +- param[0], param[1], param[2]); +- etd->capabilities = param[0]; ++ etd->capabilities[0], etd->capabilities[1], ++ etd->capabilities[2]); + + /* + * This firmware suffers from misreporting coordinates when +diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h +index 1c5894e..b54ea27 100644 +--- a/drivers/input/mouse/elantech.h ++++ b/drivers/input/mouse/elantech.h +@@ -93,13 +93,14 @@ struct elantech_data { + unsigned char reg_25; + unsigned char reg_26; + unsigned char debug; +- unsigned char capabilities; ++ unsigned char capabilities[3]; + bool paritycheck; + bool jumpy_cursor; + bool reports_pressure; + unsigned char hw_version; + unsigned int fw_version; + unsigned int single_finger_reports; ++ unsigned int y_max; + unsigned char parity[256]; + }; + +-- +1.7.6.4 + + +From 91f395e84dc83707b01c69e297894dbf992a566e Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Fri, 9 Sep 2011 10:27:42 -0700 +Subject: Input: elantech - remove ETP_EDGE_FUZZ_V2 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Don't try to be too clever and remove ETP_EDGE_FUZZ_V2. X, Y ranges +should be just the raw resolution of the device. Otherwise, they can +cause underflow on the Y axis. + +Suggested-by: Éric Piel +Signed-off-by: JJ Ding +Acked-by: Daniel Kurtz +Acked-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.h | 15 ++++++--------- + 1 files changed, 6 insertions(+), 9 deletions(-) + +diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h +index b54ea27..d9e6144 100644 +--- a/drivers/input/mouse/elantech.h ++++ b/drivers/input/mouse/elantech.h +@@ -66,16 +66,13 @@ + #define ETP_YMAX_V1 (384 - ETP_EDGE_FUZZ_V1) + + /* +- * It seems the resolution for hardware version 2 doubled. +- * Hence the X and Y ranges are doubled too. +- * The bezel around the pad also appears to be smaller ++ * The resolution for older v2 hardware doubled. ++ * (newer v2's firmware provides command so we can query) + */ +-#define ETP_EDGE_FUZZ_V2 8 +- +-#define ETP_XMIN_V2 ( 0 + ETP_EDGE_FUZZ_V2) +-#define ETP_XMAX_V2 (1152 - ETP_EDGE_FUZZ_V2) +-#define ETP_YMIN_V2 ( 0 + ETP_EDGE_FUZZ_V2) +-#define ETP_YMAX_V2 ( 768 - ETP_EDGE_FUZZ_V2) ++#define ETP_XMIN_V2 0 ++#define ETP_XMAX_V2 1152 ++#define ETP_YMIN_V2 0 ++#define ETP_YMAX_V2 768 + + #define ETP_PMIN_V2 0 + #define ETP_PMAX_V2 255 +-- +1.7.6.4 + + +From cc66bde05d267cce5a6f64d877e63036505cc31e Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Fri, 9 Sep 2011 10:28:04 -0700 +Subject: Input: elantech - packet checking for v2 hardware +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For v2 hardware, there is no real parity check, but we can still check +some constant bits for data integrity. + +Also rename elantech_check_parity_v1 to elantech_packet_check_v1 to make +these packet checking function names consistent. + +Signed-off-by: JJ Ding +Acked-by: Daniel Kurtz +Acked-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.c | 39 ++++++++++++++++++++++++++++++++++----- + 1 files changed, 34 insertions(+), 5 deletions(-) + +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 296b6a6..f2e3a2b 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -350,7 +350,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + input_sync(dev); + } + +-static int elantech_check_parity_v1(struct psmouse *psmouse) ++static int elantech_packet_check_v1(struct psmouse *psmouse) + { + struct elantech_data *etd = psmouse->private; + unsigned char *packet = psmouse->packet; +@@ -374,6 +374,34 @@ static int elantech_check_parity_v1(struct psmouse *psmouse) + etd->parity[packet[3]] == p3; + } + ++static int elantech_packet_check_v2(struct psmouse *psmouse) ++{ ++ struct elantech_data *etd = psmouse->private; ++ unsigned char *packet = psmouse->packet; ++ ++ /* ++ * V2 hardware has two flavors. Older ones that do not report pressure, ++ * and newer ones that reports pressure and width. With newer ones, all ++ * packets (1, 2, 3 finger touch) have the same constant bits. With ++ * older ones, 1/3 finger touch packets and 2 finger touch packets ++ * have different constant bits. ++ * With all three cases, if the constant bits are not exactly what I ++ * expected, I consider them invalid. ++ */ ++ if (etd->reports_pressure) ++ return (packet[0] & 0x0c) == 0x04 && ++ (packet[3] & 0x0f) == 0x02; ++ ++ if ((packet[0] & 0xc0) == 0x80) ++ return (packet[0] & 0x0c) == 0x0c && ++ (packet[3] & 0x0e) == 0x08; ++ ++ return (packet[0] & 0x3c) == 0x3c && ++ (packet[1] & 0xf0) == 0x00 && ++ (packet[3] & 0x3e) == 0x38 && ++ (packet[4] & 0xf0) == 0x00; ++} ++ + /* + * Process byte stream from mouse and handle complete packets + */ +@@ -389,14 +417,16 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) + + switch (etd->hw_version) { + case 1: +- if (etd->paritycheck && !elantech_check_parity_v1(psmouse)) ++ if (etd->paritycheck && !elantech_packet_check_v1(psmouse)) + return PSMOUSE_BAD_DATA; + + elantech_report_absolute_v1(psmouse); + break; + + case 2: +- /* We don't know how to check parity in protocol v2 */ ++ if (etd->paritycheck && !elantech_packet_check_v2(psmouse)) ++ return PSMOUSE_BAD_DATA; ++ + elantech_report_absolute_v2(psmouse); + break; + } +@@ -795,8 +825,7 @@ int elantech_init(struct psmouse *psmouse) + etd->hw_version = 2; + /* For now show extra debug information */ + etd->debug = 1; +- /* Don't know how to do parity checking for version 2 */ +- etd->paritycheck = 0; ++ etd->paritycheck = 1; + + if (etd->fw_version >= 0x020800) + etd->reports_pressure = true; +-- +1.7.6.4 + + +From 7e1abba14d70426b251ee58451ab1671af425409 Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Fri, 9 Sep 2011 10:28:19 -0700 +Subject: Input: elantech - clean up elantech_init +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Group property setting code into elantech_set_properties. + +Signed-off-by: JJ Ding +Acked-by: Daniel Kurtz +Acked-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.c | 69 ++++++++++++++++++++++----------------- + 1 files changed, 39 insertions(+), 30 deletions(-) + +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index f2e3a2b..1ab1c14 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -791,6 +791,42 @@ static int elantech_reconnect(struct psmouse *psmouse) + } + + /* ++ * determine hardware version and set some properties according to it. ++ */ ++static void elantech_set_properties(struct elantech_data *etd) ++{ ++ /* ++ * Assume every version greater than 0x020030 is new EeePC style ++ * hardware with 6 byte packets, except 0x020600 ++ */ ++ if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) ++ etd->hw_version = 1; ++ else ++ etd->hw_version = 2; ++ ++ /* ++ * Turn on packet checking by default. ++ */ ++ etd->paritycheck = 1; ++ ++ /* ++ * This firmware suffers from misreporting coordinates when ++ * a touch action starts causing the mouse cursor or scrolled page ++ * to jump. Enable a workaround. ++ */ ++ etd->jumpy_cursor = ++ (etd->fw_version == 0x020022 || etd->fw_version == 0x020600); ++ ++ if (etd->hw_version == 2) { ++ /* For now show extra debug information */ ++ etd->debug = 1; ++ ++ if (etd->fw_version >= 0x020800) ++ etd->reports_pressure = true; ++ } ++} ++ ++/* + * Initialize the touchpad and create sysfs entries + */ + int elantech_init(struct psmouse *psmouse) +@@ -816,26 +852,9 @@ int elantech_init(struct psmouse *psmouse) + } + + etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; +- +- /* +- * Assume every version greater than this is new EeePC style +- * hardware with 6 byte packets +- */ +- if (etd->fw_version >= 0x020030) { +- etd->hw_version = 2; +- /* For now show extra debug information */ +- etd->debug = 1; +- etd->paritycheck = 1; +- +- if (etd->fw_version >= 0x020800) +- etd->reports_pressure = true; +- +- } else { +- etd->hw_version = 1; +- etd->paritycheck = 1; +- } +- +- pr_info("assuming hardware version %d, firmware version %d.%d.%d\n", ++ elantech_set_properties(etd); ++ pr_info("assuming hardware version %d " ++ "(with firmware version 0x%02x%02x%02x)\n", + etd->hw_version, param[0], param[1], param[2]); + + if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, +@@ -847,16 +866,6 @@ int elantech_init(struct psmouse *psmouse) + etd->capabilities[0], etd->capabilities[1], + etd->capabilities[2]); + +- /* +- * This firmware suffers from misreporting coordinates when +- * a touch action starts causing the mouse cursor or scrolled page +- * to jump. Enable a workaround. +- */ +- if (etd->fw_version == 0x020022 || etd->fw_version == 0x020600) { +- pr_info("firmware version 2.0.34/2.6.0 detected, enabling jumpy cursor workaround\n"); +- etd->jumpy_cursor = true; +- } +- + if (elantech_set_absolute_mode(psmouse)) { + pr_err("failed to put touchpad into absolute mode.\n"); + goto init_fail; +-- +1.7.6.4 + + +From 709d9ebd2853032df0599c30d5ac61c8397679f3 Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Fri, 9 Sep 2011 10:30:31 -0700 +Subject: Input: elantech - add v3 hardware support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +v3 hardware's packet format is almost identical to v2 (one/three finger touch), +except when sensing two finger touch, the hardware sends 12 bytes of data. + +Signed-off-by: JJ Ding +Acked-by: Daniel Kurtz +Acked-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + Documentation/input/elantech.txt | 117 +++++++++++++++++++-- + drivers/input/mouse/elantech.c | 208 ++++++++++++++++++++++++++++++++++---- + drivers/input/mouse/elantech.h | 12 ++ + 3 files changed, 306 insertions(+), 31 deletions(-) + +diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt +index bce9941..cee08ee 100644 +--- a/Documentation/input/elantech.txt ++++ b/Documentation/input/elantech.txt +@@ -16,15 +16,22 @@ Contents + + 1. Introduction + 2. Extra knobs +- 3. Hardware version 1 +- 3.1 Registers +- 3.2 Native relative mode 4 byte packet format +- 3.3 Native absolute mode 4 byte packet format +- 4. Hardware version 2 ++ 3. Differentiating hardware versions ++ 4. Hardware version 1 + 4.1 Registers +- 4.2 Native absolute mode 6 byte packet format +- 4.2.1 One finger touch +- 4.2.2 Two finger touch ++ 4.2 Native relative mode 4 byte packet format ++ 4.3 Native absolute mode 4 byte packet format ++ 5. Hardware version 2 ++ 5.1 Registers ++ 5.2 Native absolute mode 6 byte packet format ++ 5.2.1 Parity checking and packet re-synchronization ++ 5.2.2 One/Three finger touch ++ 5.2.3 Two finger touch ++ 6. Hardware version 3 ++ 6.1 Registers ++ 6.2 Native absolute mode 6 byte packet format ++ 6.2.1 One/Three finger touch ++ 6.2.2 Two finger touch + + + +@@ -375,7 +382,7 @@ For all the other ones, there are just a few constant bits: + + In case an error is detected, all the packets are shifted by one (and packet[0] is discarded). + +-5.2.1 One/Three finger touch ++5.2.2 One/Three finger touch + ~~~~~~~~~~~~~~~~ + + byte 0: +@@ -384,7 +391,7 @@ byte 0: + n1 n0 w3 w2 . . R L + + L, R = 1 when Left, Right mouse button pressed +- n1..n0 = numbers of fingers on touchpad ++ n1..n0 = number of fingers on touchpad + + byte 1: + +@@ -432,7 +439,7 @@ byte 5: + y11..y0 = absolute y value (vertical) + + +-4.2.2 Two finger touch ++5.2.3 Two finger touch + ~~~~~~~~~~~~~~~~ + + Note that the two pairs of coordinates are not exactly the coordinates of the +@@ -446,7 +453,7 @@ byte 0: + n1 n0 ay8 ax8 . . R L + + L, R = 1 when Left, Right mouse button pressed +- n1..n0 = numbers of fingers on touchpad ++ n1..n0 = number of fingers on touchpad + + byte 1: + +@@ -480,3 +487,89 @@ byte 5: + by7 by8 by5 by4 by3 by2 by1 by0 + + by8..by0 = upper-right finger absolute y value ++ ++///////////////////////////////////////////////////////////////////////////// ++ ++6. Hardware version 3 ++ ================== ++ ++6.1 Registers ++ ~~~~~~~~~ ++* reg_10 ++ ++ bit 7 6 5 4 3 2 1 0 ++ 0 0 0 0 0 0 0 A ++ ++ A: 1 = enable absolute tracking ++ ++6.2 Native absolute mode 6 byte packet format ++ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++1 and 3 finger touch shares the same 6-byte packet format, except that ++3 finger touch only reports the position of the center of all three fingers. ++ ++Firmware would send 12 bytes of data for 2 finger touch. ++ ++Note on debounce: ++In case the box has unstable power supply or other electricity issues, or ++when number of finger changes, F/W would send "debounce packet" to inform ++driver that the hardware is in debounce status. ++The debouce packet has the following signature: ++ byte 0: 0xc4 ++ byte 1: 0xff ++ byte 2: 0xff ++ byte 3: 0x02 ++ byte 4: 0xff ++ byte 5: 0xff ++When we encounter this kind of packet, we just ignore it. ++ ++6.2.1 One/Three finger touch ++ ~~~~~~~~~~~~~~~~~~~~~~ ++ ++byte 0: ++ ++ bit 7 6 5 4 3 2 1 0 ++ n1 n0 w3 w2 0 1 R L ++ ++ L, R = 1 when Left, Right mouse button pressed ++ n1..n0 = number of fingers on touchpad ++ ++byte 1: ++ ++ bit 7 6 5 4 3 2 1 0 ++ p7 p6 p5 p4 x11 x10 x9 x8 ++ ++byte 2: ++ ++ bit 7 6 5 4 3 2 1 0 ++ x7 x6 x5 x4 x3 x2 x1 x0 ++ ++ x11..x0 = absolute x value (horizontal) ++ ++byte 3: ++ ++ bit 7 6 5 4 3 2 1 0 ++ 0 0 w1 w0 0 0 1 0 ++ ++ w3..w0 = width of the finger touch ++ ++byte 4: ++ ++ bit 7 6 5 4 3 2 1 0 ++ p3 p1 p2 p0 y11 y10 y9 y8 ++ ++ p7..p0 = pressure ++ ++byte 5: ++ ++ bit 7 6 5 4 3 2 1 0 ++ y7 y6 y5 y4 y3 y2 y1 y0 ++ ++ y11..y0 = absolute y value (vertical) ++ ++6.2.2 Two finger touch ++ ~~~~~~~~~~~~~~~~ ++ ++The packet format is exactly the same for two finger touch, except the hardware ++sends two 6 byte packets. The first packet contains data for the first finger, ++the second packet has data for the second finger. So for two finger touch a ++total of 12 bytes are sent. +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 1ab1c14..9cfc70a 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -108,6 +108,16 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, + rc = -1; + } + break; ++ ++ case 3: ++ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || ++ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, reg) || ++ elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) { ++ rc = -1; ++ } ++ break; + } + + if (rc) +@@ -154,6 +164,18 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, + rc = -1; + } + break; ++ ++ case 3: ++ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || ++ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, reg) || ++ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, val) || ++ elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { ++ rc = -1; ++ } ++ break; + } + + if (rc) +@@ -350,6 +372,84 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) + input_sync(dev); + } + ++/* ++ * Interpret complete data packets and report absolute mode input events for ++ * hardware version 3. (12 byte packets for two fingers) ++ */ ++static void elantech_report_absolute_v3(struct psmouse *psmouse, ++ int packet_type) ++{ ++ struct input_dev *dev = psmouse->dev; ++ struct elantech_data *etd = psmouse->private; ++ unsigned char *packet = psmouse->packet; ++ unsigned int fingers = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0; ++ unsigned int width = 0, pres = 0; ++ ++ /* byte 0: n1 n0 . . . . R L */ ++ fingers = (packet[0] & 0xc0) >> 6; ++ ++ switch (fingers) { ++ case 3: ++ case 1: ++ /* ++ * byte 1: . . . . x11 x10 x9 x8 ++ * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 ++ */ ++ x1 = ((packet[1] & 0x0f) << 8) | packet[2]; ++ /* ++ * byte 4: . . . . y11 y10 y9 y8 ++ * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 ++ */ ++ y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); ++ break; ++ ++ case 2: ++ if (packet_type == PACKET_V3_HEAD) { ++ /* ++ * byte 1: . . . . ax11 ax10 ax9 ax8 ++ * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 ++ */ ++ etd->prev_x = ((packet[1] & 0x0f) << 8) | packet[2]; ++ /* ++ * byte 4: . . . . ay11 ay10 ay9 ay8 ++ * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 ++ */ ++ etd->prev_y = etd->y_max - ++ (((packet[4] & 0x0f) << 8) | packet[5]); ++ /* ++ * wait for next packet ++ */ ++ return; ++ } ++ ++ /* packet_type == PACKET_V3_TAIL */ ++ x1 = etd->prev_x; ++ y1 = etd->prev_y; ++ x2 = ((packet[1] & 0x0f) << 8) | packet[2]; ++ y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); ++ break; ++ } ++ ++ pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); ++ width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); ++ ++ input_report_key(dev, BTN_TOUCH, fingers != 0); ++ if (fingers != 0) { ++ input_report_abs(dev, ABS_X, x1); ++ input_report_abs(dev, ABS_Y, y1); ++ } ++ elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); ++ input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); ++ input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); ++ input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); ++ input_report_key(dev, BTN_LEFT, packet[0] & 0x01); ++ input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); ++ input_report_abs(dev, ABS_PRESSURE, pres); ++ input_report_abs(dev, ABS_TOOL_WIDTH, width); ++ ++ input_sync(dev); ++} ++ + static int elantech_packet_check_v1(struct psmouse *psmouse) + { + struct elantech_data *etd = psmouse->private; +@@ -403,11 +503,37 @@ static int elantech_packet_check_v2(struct psmouse *psmouse) + } + + /* ++ * We check the constant bits to determine what packet type we get, ++ * so packet checking is mandatory for v3 hardware. ++ */ ++static int elantech_packet_check_v3(struct psmouse *psmouse) ++{ ++ const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff }; ++ unsigned char *packet = psmouse->packet; ++ ++ /* ++ * check debounce first, it has the same signature in byte 0 ++ * and byte 3 as PACKET_V3_HEAD. ++ */ ++ if (!memcmp(packet, debounce_packet, sizeof(debounce_packet))) ++ return PACKET_DEBOUNCE; ++ ++ if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02) ++ return PACKET_V3_HEAD; ++ ++ if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) ++ return PACKET_V3_TAIL; ++ ++ return PACKET_UNKNOWN; ++} ++ ++/* + * Process byte stream from mouse and handle complete packets + */ + static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) + { + struct elantech_data *etd = psmouse->private; ++ int packet_type; + + if (psmouse->pktcnt < psmouse->pktsize) + return PSMOUSE_GOOD_DATA; +@@ -429,6 +555,18 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) + + elantech_report_absolute_v2(psmouse); + break; ++ ++ case 3: ++ packet_type = elantech_packet_check_v3(psmouse); ++ /* ignore debounce */ ++ if (packet_type == PACKET_DEBOUNCE) ++ return PSMOUSE_FULL_PACKET; ++ ++ if (packet_type == PACKET_UNKNOWN) ++ return PSMOUSE_BAD_DATA; ++ ++ elantech_report_absolute_v3(psmouse, packet_type); ++ break; + } + + return PSMOUSE_FULL_PACKET; +@@ -463,8 +601,15 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) + elantech_write_reg(psmouse, 0x11, etd->reg_11) || + elantech_write_reg(psmouse, 0x21, etd->reg_21)) { + rc = -1; +- break; + } ++ break; ++ ++ case 3: ++ etd->reg_10 = 0x0b; ++ if (elantech_write_reg(psmouse, 0x10, etd->reg_10)) ++ rc = -1; ++ ++ break; + } + + if (rc == 0) { +@@ -498,11 +643,12 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) + return rc; + } + +-static void elantech_set_range(struct psmouse *psmouse, +- unsigned int *x_min, unsigned int *y_min, +- unsigned int *x_max, unsigned int *y_max) ++static int elantech_set_range(struct psmouse *psmouse, ++ unsigned int *x_min, unsigned int *y_min, ++ unsigned int *x_max, unsigned int *y_max) + { + struct elantech_data *etd = psmouse->private; ++ unsigned char param[3]; + int i; + + switch (etd->hw_version) { +@@ -530,19 +676,30 @@ static void elantech_set_range(struct psmouse *psmouse, + *y_max = (etd->capabilities[2] - i) * 64; + } + break; ++ ++ case 3: ++ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) ++ return -1; ++ ++ *x_max = (0x0f & param[0]) << 8 | param[1]; ++ *y_max = (0xf0 & param[0]) << 4 | param[2]; ++ break; + } ++ ++ return 0; + } + + /* + * Set the appropriate event bits for the input subsystem + */ +-static void elantech_set_input_params(struct psmouse *psmouse) ++static int elantech_set_input_params(struct psmouse *psmouse) + { + struct input_dev *dev = psmouse->dev; + struct elantech_data *etd = psmouse->private; + unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0; + +- elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max); ++ if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max)) ++ return -1; + + __set_bit(EV_KEY, dev->evbit); + __set_bit(EV_ABS, dev->evbit); +@@ -570,6 +727,9 @@ static void elantech_set_input_params(struct psmouse *psmouse) + + case 2: + __set_bit(BTN_TOOL_QUADTAP, dev->keybit); ++ __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); ++ /* fall through */ ++ case 3: + input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); + input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); + if (etd->reports_pressure) { +@@ -578,7 +738,6 @@ static void elantech_set_input_params(struct psmouse *psmouse) + input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, + ETP_WMAX_V2, 0, 0); + } +- __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); + input_mt_init_slots(dev, 2); + input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); + input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); +@@ -586,6 +745,8 @@ static void elantech_set_input_params(struct psmouse *psmouse) + } + + etd->y_max = y_max; ++ ++ return 0; + } + + struct elantech_attr_data { +@@ -727,7 +888,8 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) + * Report this in case there are Elantech models that use a different + * set of magic numbers + */ +- if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) { ++ if (param[0] != 0x3c || param[1] != 0x03 || ++ (param[2] != 0xc8 && param[2] != 0x00)) { + pr_debug("unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", + param[0], param[1], param[2]); + return -1; +@@ -793,16 +955,16 @@ static int elantech_reconnect(struct psmouse *psmouse) + /* + * determine hardware version and set some properties according to it. + */ +-static void elantech_set_properties(struct elantech_data *etd) ++static int elantech_set_properties(struct elantech_data *etd) + { +- /* +- * Assume every version greater than 0x020030 is new EeePC style +- * hardware with 6 byte packets, except 0x020600 +- */ + if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) + etd->hw_version = 1; +- else ++ else if (etd->fw_version < 0x150600) + etd->hw_version = 2; ++ else if ((etd->fw_version & 0x0f0000) >> 16 == 5) ++ etd->hw_version = 3; ++ else ++ return -1; + + /* + * Turn on packet checking by default. +@@ -817,13 +979,15 @@ static void elantech_set_properties(struct elantech_data *etd) + etd->jumpy_cursor = + (etd->fw_version == 0x020022 || etd->fw_version == 0x020600); + +- if (etd->hw_version == 2) { ++ if (etd->hw_version > 1) { + /* For now show extra debug information */ + etd->debug = 1; + + if (etd->fw_version >= 0x020800) + etd->reports_pressure = true; + } ++ ++ return 0; + } + + /* +@@ -850,9 +1014,12 @@ int elantech_init(struct psmouse *psmouse) + pr_err("failed to query firmware version.\n"); + goto init_fail; + } +- + etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; +- elantech_set_properties(etd); ++ ++ if (elantech_set_properties(etd)) { ++ pr_err("unknown hardware version, aborting...\n"); ++ goto init_fail; ++ } + pr_info("assuming hardware version %d " + "(with firmware version 0x%02x%02x%02x)\n", + etd->hw_version, param[0], param[1], param[2]); +@@ -871,7 +1038,10 @@ int elantech_init(struct psmouse *psmouse) + goto init_fail; + } + +- elantech_set_input_params(psmouse); ++ if (elantech_set_input_params(psmouse)) { ++ pr_err("failed to query touchpad range.\n"); ++ goto init_fail; ++ } + + error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, + &elantech_attr_group); +@@ -883,7 +1053,7 @@ int elantech_init(struct psmouse *psmouse) + psmouse->protocol_handler = elantech_process_byte; + psmouse->disconnect = elantech_disconnect; + psmouse->reconnect = elantech_reconnect; +- psmouse->pktsize = etd->hw_version == 2 ? 6 : 4; ++ psmouse->pktsize = etd->hw_version > 1 ? 6 : 4; + + return 0; + +diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h +index d9e6144..236c33c 100644 +--- a/drivers/input/mouse/elantech.h ++++ b/drivers/input/mouse/elantech.h +@@ -16,6 +16,7 @@ + /* + * Command values for Synaptics style queries + */ ++#define ETP_FW_ID_QUERY 0x00 + #define ETP_FW_VERSION_QUERY 0x01 + #define ETP_CAPABILITIES_QUERY 0x02 + +@@ -24,6 +25,7 @@ + */ + #define ETP_REGISTER_READ 0x10 + #define ETP_REGISTER_WRITE 0x11 ++#define ETP_REGISTER_READWRITE 0x00 + + /* + * Hardware version 2 custom PS/2 command value +@@ -79,6 +81,14 @@ + #define ETP_WMIN_V2 0 + #define ETP_WMAX_V2 15 + ++/* ++ * v3 hardware has 2 kinds of packet types. ++ */ ++#define PACKET_UNKNOWN 0x01 ++#define PACKET_DEBOUNCE 0x02 ++#define PACKET_V3_HEAD 0x03 ++#define PACKET_V3_TAIL 0x04 ++ + struct elantech_data { + unsigned char reg_10; + unsigned char reg_11; +@@ -98,6 +108,8 @@ struct elantech_data { + unsigned int fw_version; + unsigned int single_finger_reports; + unsigned int y_max; ++ unsigned int prev_x; ++ unsigned int prev_y; + unsigned char parity[256]; + }; + +-- +1.7.6.4 + + +From 5936f37c68ab27b24d6f2faf23268a9aefd3092e Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Fri, 9 Sep 2011 10:31:58 -0700 +Subject: Input: elantech - add v4 hardware support + +v4 hardware is a true multitouch capable touchpad (up to 5 fingers). +The packet format is quite complex, please see protocol document for +reference. + +Signed-off-by: JJ Ding +Signed-off-by: Dmitry Torokhov +--- + Documentation/input/elantech.txt | 170 ++++++++++++++++++++++++++ + drivers/input/mouse/elantech.c | 249 ++++++++++++++++++++++++++++++++++++-- + drivers/input/mouse/elantech.h | 29 ++++- + 3 files changed, 432 insertions(+), 16 deletions(-) + +diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt +index cee08ee..5602eb7 100644 +--- a/Documentation/input/elantech.txt ++++ b/Documentation/input/elantech.txt +@@ -32,6 +32,12 @@ Contents + 6.2 Native absolute mode 6 byte packet format + 6.2.1 One/Three finger touch + 6.2.2 Two finger touch ++ 7. Hardware version 4 ++ 7.1 Registers ++ 7.2 Native absolute mode 6 byte packet format ++ 7.2.1 Status packet ++ 7.2.2 Head packet ++ 7.2.3 Motion packet + + + +@@ -573,3 +579,167 @@ The packet format is exactly the same for two finger touch, except the hardware + sends two 6 byte packets. The first packet contains data for the first finger, + the second packet has data for the second finger. So for two finger touch a + total of 12 bytes are sent. ++ ++///////////////////////////////////////////////////////////////////////////// ++ ++7. Hardware version 4 ++ ================== ++ ++7.1 Registers ++ ~~~~~~~~~ ++* reg_07 ++ ++ bit 7 6 5 4 3 2 1 0 ++ 0 0 0 0 0 0 0 A ++ ++ A: 1 = enable absolute tracking ++ ++7.2 Native absolute mode 6 byte packet format ++ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers. ++Unfortunately, due to PS/2's limited bandwidth, its packet format is rather ++complex. ++ ++Whenever the numbers or identities of the fingers changes, the hardware sends a ++status packet to indicate how many and which fingers is on touchpad, followed by ++head packets or motion packets. A head packet contains data of finger id, finger ++position (absolute x, y values), width, and pressure. A motion packet contains ++two fingers' position delta. ++ ++For example, when status packet tells there are 2 fingers on touchpad, then we ++can expect two following head packets. If the finger status doesn't change, ++the following packets would be motion packets, only sending delta of finger ++position, until we receive a status packet. ++ ++One exception is one finger touch. when a status packet tells us there is only ++one finger, the hardware would just send head packets afterwards. ++ ++7.2.1 Status packet ++ ~~~~~~~~~~~~~ ++ ++byte 0: ++ ++ bit 7 6 5 4 3 2 1 0 ++ . . . . 0 1 R L ++ ++ L, R = 1 when Left, Right mouse button pressed ++ ++byte 1: ++ ++ bit 7 6 5 4 3 2 1 0 ++ . . . ft4 ft3 ft2 ft1 ft0 ++ ++ ft4 ft3 ft2 ft1 ft0 ftn = 1 when finger n is on touchpad ++ ++byte 2: not used ++ ++byte 3: ++ ++ bit 7 6 5 4 3 2 1 0 ++ . . . 1 0 0 0 0 ++ ++ constant bits ++ ++byte 4: ++ ++ bit 7 6 5 4 3 2 1 0 ++ p . . . . . . . ++ ++ p = 1 for palm ++ ++byte 5: not used ++ ++7.2.2 Head packet ++ ~~~~~~~~~~~ ++ ++byte 0: ++ ++ bit 7 6 5 4 3 2 1 0 ++ w3 w2 w1 w0 0 1 R L ++ ++ L, R = 1 when Left, Right mouse button pressed ++ w3..w0 = finger width (spans how many trace lines) ++ ++byte 1: ++ ++ bit 7 6 5 4 3 2 1 0 ++ p7 p6 p5 p4 x11 x10 x9 x8 ++ ++byte 2: ++ ++ bit 7 6 5 4 3 2 1 0 ++ x7 x6 x5 x4 x3 x2 x1 x0 ++ ++ x11..x0 = absolute x value (horizontal) ++ ++byte 3: ++ ++ bit 7 6 5 4 3 2 1 0 ++ id2 id1 id0 1 0 0 0 1 ++ ++ id2..id0 = finger id ++ ++byte 4: ++ ++ bit 7 6 5 4 3 2 1 0 ++ p3 p1 p2 p0 y11 y10 y9 y8 ++ ++ p7..p0 = pressure ++ ++byte 5: ++ ++ bit 7 6 5 4 3 2 1 0 ++ y7 y6 y5 y4 y3 y2 y1 y0 ++ ++ y11..y0 = absolute y value (vertical) ++ ++7.2.3 Motion packet ++ ~~~~~~~~~~~~~ ++ ++byte 0: ++ ++ bit 7 6 5 4 3 2 1 0 ++ id2 id1 id0 w 0 1 R L ++ ++ L, R = 1 when Left, Right mouse button pressed ++ id2..id0 = finger id ++ w = 1 when delta overflows (> 127 or < -128), in this case ++ firmware sends us (delta x / 5) and (delta y / 5) ++ ++byte 1: ++ ++ bit 7 6 5 4 3 2 1 0 ++ x7 x6 x5 x4 x3 x2 x1 x0 ++ ++ x7..x0 = delta x (two's complement) ++ ++byte 2: ++ ++ bit 7 6 5 4 3 2 1 0 ++ y7 y6 y5 y4 y3 y2 y1 y0 ++ ++ y7..y0 = delta y (two's complement) ++ ++byte 3: ++ ++ bit 7 6 5 4 3 2 1 0 ++ id2 id1 id0 1 0 0 1 0 ++ ++ id2..id0 = finger id ++ ++byte 4: ++ ++ bit 7 6 5 4 3 2 1 0 ++ x7 x6 x5 x4 x3 x2 x1 x0 ++ ++ x7..x0 = delta x (two's complement) ++ ++byte 5: ++ ++ bit 7 6 5 4 3 2 1 0 ++ y7 y6 y5 y4 y3 y2 y1 y0 ++ ++ y7..y0 = delta y (two's complement) ++ ++ byte 0 ~ 2 for one finger ++ byte 3 ~ 5 for another +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 9cfc70a..b8733b3 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -84,7 +84,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, + unsigned char param[3]; + int rc = 0; + +- if (reg < 0x10 || reg > 0x26) ++ if (reg < 0x07 || reg > 0x26) + return -1; + + if (reg > 0x11 && reg < 0x20) +@@ -109,7 +109,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, + } + break; + +- case 3: ++ case 3 ... 4: + if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || + elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || + elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || +@@ -122,8 +122,10 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, + + if (rc) + pr_err("failed to read register 0x%02x.\n", reg); +- else ++ else if (etd->hw_version != 4) + *val = param[0]; ++ else ++ *val = param[1]; + + return rc; + } +@@ -137,7 +139,7 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, + struct elantech_data *etd = psmouse->private; + int rc = 0; + +- if (reg < 0x10 || reg > 0x26) ++ if (reg < 0x07 || reg > 0x26) + return -1; + + if (reg > 0x11 && reg < 0x20) +@@ -176,6 +178,20 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, + rc = -1; + } + break; ++ ++ case 4: ++ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || ++ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, reg) || ++ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || ++ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ++ elantech_ps2_command(psmouse, NULL, val) || ++ elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { ++ rc = -1; ++ } ++ break; + } + + if (rc) +@@ -409,12 +425,12 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, + * byte 1: . . . . ax11 ax10 ax9 ax8 + * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 + */ +- etd->prev_x = ((packet[1] & 0x0f) << 8) | packet[2]; ++ etd->mt[0].x = ((packet[1] & 0x0f) << 8) | packet[2]; + /* + * byte 4: . . . . ay11 ay10 ay9 ay8 + * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 + */ +- etd->prev_y = etd->y_max - ++ etd->mt[0].y = etd->y_max - + (((packet[4] & 0x0f) << 8) | packet[5]); + /* + * wait for next packet +@@ -423,8 +439,8 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, + } + + /* packet_type == PACKET_V3_TAIL */ +- x1 = etd->prev_x; +- y1 = etd->prev_y; ++ x1 = etd->mt[0].x; ++ y1 = etd->mt[0].y; + x2 = ((packet[1] & 0x0f) << 8) | packet[2]; + y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); + break; +@@ -450,6 +466,129 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, + input_sync(dev); + } + ++static void elantech_input_sync_v4(struct psmouse *psmouse) ++{ ++ struct input_dev *dev = psmouse->dev; ++ unsigned char *packet = psmouse->packet; ++ ++ input_report_key(dev, BTN_LEFT, packet[0] & 0x01); ++ input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); ++ input_mt_report_pointer_emulation(dev, true); ++ input_sync(dev); ++} ++ ++static void process_packet_status_v4(struct psmouse *psmouse) ++{ ++ struct input_dev *dev = psmouse->dev; ++ unsigned char *packet = psmouse->packet; ++ unsigned fingers; ++ int i; ++ ++ /* notify finger state change */ ++ fingers = packet[1] & 0x1f; ++ for (i = 0; i < ETP_MAX_FINGERS; i++) { ++ if ((fingers & (1 << i)) == 0) { ++ input_mt_slot(dev, i); ++ input_mt_report_slot_state(dev, MT_TOOL_FINGER, false); ++ } ++ } ++ ++ elantech_input_sync_v4(psmouse); ++} ++ ++static void process_packet_head_v4(struct psmouse *psmouse) ++{ ++ struct input_dev *dev = psmouse->dev; ++ struct elantech_data *etd = psmouse->private; ++ unsigned char *packet = psmouse->packet; ++ int id = ((packet[3] & 0xe0) >> 5) - 1; ++ int pres, traces; ++ ++ if (id < 0) ++ return; ++ ++ etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2]; ++ etd->mt[id].y = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); ++ pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); ++ traces = (packet[0] & 0xf0) >> 4; ++ ++ input_mt_slot(dev, id); ++ input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); ++ ++ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); ++ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); ++ input_report_abs(dev, ABS_MT_PRESSURE, pres); ++ input_report_abs(dev, ABS_MT_TOUCH_MAJOR, traces * etd->width); ++ /* report this for backwards compatibility */ ++ input_report_abs(dev, ABS_TOOL_WIDTH, traces); ++ ++ elantech_input_sync_v4(psmouse); ++} ++ ++static void process_packet_motion_v4(struct psmouse *psmouse) ++{ ++ struct input_dev *dev = psmouse->dev; ++ struct elantech_data *etd = psmouse->private; ++ unsigned char *packet = psmouse->packet; ++ int weight, delta_x1 = 0, delta_y1 = 0, delta_x2 = 0, delta_y2 = 0; ++ int id, sid; ++ ++ id = ((packet[0] & 0xe0) >> 5) - 1; ++ if (id < 0) ++ return; ++ ++ sid = ((packet[3] & 0xe0) >> 5) - 1; ++ weight = (packet[0] & 0x10) ? ETP_WEIGHT_VALUE : 1; ++ /* ++ * Motion packets give us the delta of x, y values of specific fingers, ++ * but in two's complement. Let the compiler do the conversion for us. ++ * Also _enlarge_ the numbers to int, in case of overflow. ++ */ ++ delta_x1 = (signed char)packet[1]; ++ delta_y1 = (signed char)packet[2]; ++ delta_x2 = (signed char)packet[4]; ++ delta_y2 = (signed char)packet[5]; ++ ++ etd->mt[id].x += delta_x1 * weight; ++ etd->mt[id].y -= delta_y1 * weight; ++ input_mt_slot(dev, id); ++ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); ++ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); ++ ++ if (sid >= 0) { ++ etd->mt[sid].x += delta_x2 * weight; ++ etd->mt[sid].y -= delta_y2 * weight; ++ input_mt_slot(dev, sid); ++ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[sid].x); ++ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[sid].y); ++ } ++ ++ elantech_input_sync_v4(psmouse); ++} ++ ++static void elantech_report_absolute_v4(struct psmouse *psmouse, ++ int packet_type) ++{ ++ switch (packet_type) { ++ case PACKET_V4_STATUS: ++ process_packet_status_v4(psmouse); ++ break; ++ ++ case PACKET_V4_HEAD: ++ process_packet_head_v4(psmouse); ++ break; ++ ++ case PACKET_V4_MOTION: ++ process_packet_motion_v4(psmouse); ++ break; ++ ++ case PACKET_UNKNOWN: ++ default: ++ /* impossible to get here */ ++ break; ++ } ++} ++ + static int elantech_packet_check_v1(struct psmouse *psmouse) + { + struct elantech_data *etd = psmouse->private; +@@ -504,7 +643,7 @@ static int elantech_packet_check_v2(struct psmouse *psmouse) + + /* + * We check the constant bits to determine what packet type we get, +- * so packet checking is mandatory for v3 hardware. ++ * so packet checking is mandatory for v3 and later hardware. + */ + static int elantech_packet_check_v3(struct psmouse *psmouse) + { +@@ -527,6 +666,25 @@ static int elantech_packet_check_v3(struct psmouse *psmouse) + return PACKET_UNKNOWN; + } + ++static int elantech_packet_check_v4(struct psmouse *psmouse) ++{ ++ unsigned char *packet = psmouse->packet; ++ ++ if ((packet[0] & 0x0c) == 0x04 && ++ (packet[3] & 0x1f) == 0x11) ++ return PACKET_V4_HEAD; ++ ++ if ((packet[0] & 0x0c) == 0x04 && ++ (packet[3] & 0x1f) == 0x12) ++ return PACKET_V4_MOTION; ++ ++ if ((packet[0] & 0x0c) == 0x04 && ++ (packet[3] & 0x1f) == 0x10) ++ return PACKET_V4_STATUS; ++ ++ return PACKET_UNKNOWN; ++} ++ + /* + * Process byte stream from mouse and handle complete packets + */ +@@ -567,6 +725,14 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) + + elantech_report_absolute_v3(psmouse, packet_type); + break; ++ ++ case 4: ++ packet_type = elantech_packet_check_v4(psmouse); ++ if (packet_type == PACKET_UNKNOWN) ++ return PSMOUSE_BAD_DATA; ++ ++ elantech_report_absolute_v4(psmouse, packet_type); ++ break; + } + + return PSMOUSE_FULL_PACKET; +@@ -610,6 +776,13 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) + rc = -1; + + break; ++ ++ case 4: ++ etd->reg_07 = 0x01; ++ if (elantech_write_reg(psmouse, 0x07, etd->reg_07)) ++ rc = -1; ++ ++ goto skip_readback_reg_10; /* v4 has no reg 0x10 to read */ + } + + if (rc == 0) { +@@ -637,6 +810,7 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) + } + } + ++ skip_readback_reg_10: + if (rc) + pr_err("failed to initialise registers.\n"); + +@@ -645,10 +819,12 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) + + static int elantech_set_range(struct psmouse *psmouse, + unsigned int *x_min, unsigned int *y_min, +- unsigned int *x_max, unsigned int *y_max) ++ unsigned int *x_max, unsigned int *y_max, ++ unsigned int *width) + { + struct elantech_data *etd = psmouse->private; + unsigned char param[3]; ++ unsigned char traces; + int i; + + switch (etd->hw_version) { +@@ -684,6 +860,19 @@ static int elantech_set_range(struct psmouse *psmouse, + *x_max = (0x0f & param[0]) << 8 | param[1]; + *y_max = (0xf0 & param[0]) << 4 | param[2]; + break; ++ ++ case 4: ++ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) ++ return -1; ++ ++ *x_max = (0x0f & param[0]) << 8 | param[1]; ++ *y_max = (0xf0 & param[0]) << 4 | param[2]; ++ traces = etd->capabilities[1]; ++ if ((traces < 2) || (traces > *x_max)) ++ return -1; ++ ++ *width = *x_max / (traces - 1); ++ break; + } + + return 0; +@@ -696,9 +885,9 @@ static int elantech_set_input_params(struct psmouse *psmouse) + { + struct input_dev *dev = psmouse->dev; + struct elantech_data *etd = psmouse->private; +- unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0; ++ unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0; + +- if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max)) ++ if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width)) + return -1; + + __set_bit(EV_KEY, dev->evbit); +@@ -742,9 +931,37 @@ static int elantech_set_input_params(struct psmouse *psmouse) + input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); + input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); + break; ++ ++ case 4: ++ __set_bit(BTN_TOOL_QUADTAP, dev->keybit); ++ /* For X to recognize me as touchpad. */ ++ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); ++ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); ++ /* ++ * range of pressure and width is the same as v2, ++ * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility. ++ */ ++ input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, ++ ETP_PMAX_V2, 0, 0); ++ input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, ++ ETP_WMAX_V2, 0, 0); ++ /* Multitouch capable pad, up to 5 fingers. */ ++ input_mt_init_slots(dev, ETP_MAX_FINGERS); ++ input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); ++ input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); ++ input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2, ++ ETP_PMAX_V2, 0, 0); ++ /* ++ * The firmware reports how many trace lines the finger spans, ++ * convert to surface unit as Protocol-B requires. ++ */ ++ input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0, ++ ETP_WMAX_V2 * width, 0, 0); ++ break; + } + + etd->y_max = y_max; ++ etd->width = width; + + return 0; + } +@@ -816,6 +1033,7 @@ static ssize_t elantech_set_int_attr(struct psmouse *psmouse, + elantech_show_int_attr, \ + elantech_set_int_attr) + ++ELANTECH_INT_ATTR(reg_07, 0x07); + ELANTECH_INT_ATTR(reg_10, 0x10); + ELANTECH_INT_ATTR(reg_11, 0x11); + ELANTECH_INT_ATTR(reg_20, 0x20); +@@ -829,6 +1047,7 @@ ELANTECH_INT_ATTR(debug, 0); + ELANTECH_INT_ATTR(paritycheck, 0); + + static struct attribute *elantech_attrs[] = { ++ &psmouse_attr_reg_07.dattr.attr, + &psmouse_attr_reg_10.dattr.attr, + &psmouse_attr_reg_11.dattr.attr, + &psmouse_attr_reg_20.dattr.attr, +@@ -957,12 +1176,16 @@ static int elantech_reconnect(struct psmouse *psmouse) + */ + static int elantech_set_properties(struct elantech_data *etd) + { ++ int ver = (etd->fw_version & 0x0f0000) >> 16; ++ + if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) + etd->hw_version = 1; + else if (etd->fw_version < 0x150600) + etd->hw_version = 2; +- else if ((etd->fw_version & 0x0f0000) >> 16 == 5) ++ else if (ver == 5) + etd->hw_version = 3; ++ else if (ver == 6) ++ etd->hw_version = 4; + else + return -1; + +diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h +index 236c33c..7ecaef0 100644 +--- a/drivers/input/mouse/elantech.h ++++ b/drivers/input/mouse/elantech.h +@@ -82,14 +82,37 @@ + #define ETP_WMAX_V2 15 + + /* +- * v3 hardware has 2 kinds of packet types. ++ * v3 hardware has 2 kinds of packet types, ++ * v4 hardware has 3. + */ + #define PACKET_UNKNOWN 0x01 + #define PACKET_DEBOUNCE 0x02 + #define PACKET_V3_HEAD 0x03 + #define PACKET_V3_TAIL 0x04 ++#define PACKET_V4_HEAD 0x05 ++#define PACKET_V4_MOTION 0x06 ++#define PACKET_V4_STATUS 0x07 ++ ++/* ++ * track up to 5 fingers for v4 hardware ++ */ ++#define ETP_MAX_FINGERS 5 ++ ++/* ++ * weight value for v4 hardware ++ */ ++#define ETP_WEIGHT_VALUE 5 ++ ++/* ++ * The base position for one finger, v4 hardware ++ */ ++struct finger_pos { ++ unsigned int x; ++ unsigned int y; ++}; + + struct elantech_data { ++ unsigned char reg_07; + unsigned char reg_10; + unsigned char reg_11; + unsigned char reg_20; +@@ -108,8 +131,8 @@ struct elantech_data { + unsigned int fw_version; + unsigned int single_finger_reports; + unsigned int y_max; +- unsigned int prev_x; +- unsigned int prev_y; ++ unsigned int width; ++ struct finger_pos mt[ETP_MAX_FINGERS]; + unsigned char parity[256]; + }; + +-- +1.7.6.4 + + +From 3c09085f371a68f09147abb59b35db928fe3950f Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Tue, 20 Sep 2011 22:42:51 -0700 +Subject: Input: elantech - better support all those v2 variants +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +V2 hardware has many variants. This patch adddresses two issues: + + - some model also has debounce packets, but with a different signature + than v3. Now we just check debounce for all v2 hardware. + + - due to different scanning methods the hardware uses, x and y ranges have + to be calculated differently. And for some specific versions, we can just + see them as custom-made, so set {x, y} the same values as Windows driver + does. + +Signed-off-by: JJ Ding +Tested-by: Richard Schütz +Reviewed-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.c | 46 +++++++++++++++++++++++++++++++++++---- + drivers/input/mouse/elantech.h | 1 + + 2 files changed, 42 insertions(+), 5 deletions(-) + +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index b8733b3..c2d91eb 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -613,6 +613,18 @@ static int elantech_packet_check_v1(struct psmouse *psmouse) + etd->parity[packet[3]] == p3; + } + ++static int elantech_debounce_check_v2(struct psmouse *psmouse) ++{ ++ /* ++ * When we encounter packet that matches this exactly, it means the ++ * hardware is in debounce status. Just ignore the whole packet. ++ */ ++ const u8 debounce_packet[] = { 0x84, 0xff, 0xff, 0x02, 0xff, 0xff }; ++ unsigned char *packet = psmouse->packet; ++ ++ return !memcmp(packet, debounce_packet, sizeof(debounce_packet)); ++} ++ + static int elantech_packet_check_v2(struct psmouse *psmouse) + { + struct elantech_data *etd = psmouse->private; +@@ -708,6 +720,10 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) + break; + + case 2: ++ /* ignore debounce */ ++ if (elantech_debounce_check_v2(psmouse)) ++ return PSMOUSE_FULL_PACKET; ++ + if (etd->paritycheck && !elantech_packet_check_v2(psmouse)) + return PSMOUSE_BAD_DATA; + +@@ -825,7 +841,6 @@ static int elantech_set_range(struct psmouse *psmouse, + struct elantech_data *etd = psmouse->private; + unsigned char param[3]; + unsigned char traces; +- int i; + + switch (etd->hw_version) { + case 1: +@@ -844,12 +859,33 @@ static int elantech_set_range(struct psmouse *psmouse, + *x_max = ETP_XMAX_V2; + *y_max = ETP_YMAX_V2; + } else { ++ int i; ++ int fixed_dpi; ++ + i = (etd->fw_version > 0x020800 && + etd->fw_version < 0x020900) ? 1 : 2; +- *x_min = 0; +- *y_min = 0; +- *x_max = (etd->capabilities[1] - i) * 64; +- *y_max = (etd->capabilities[2] - i) * 64; ++ ++ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) ++ return -1; ++ ++ fixed_dpi = param[1] & 0x10; ++ ++ if (((etd->fw_version >> 16) == 0x14) && fixed_dpi) { ++ if (synaptics_send_cmd(psmouse, ETP_SAMPLE_QUERY, param)) ++ return -1; ++ ++ *x_max = (etd->capabilities[1] - i) * param[1] / 2; ++ *y_max = (etd->capabilities[2] - i) * param[2] / 2; ++ } else if (etd->fw_version == 0x040216) { ++ *x_max = 819; ++ *y_max = 405; ++ } else if (etd->fw_version == 0x040219 || etd->fw_version == 0x040215) { ++ *x_max = 900; ++ *y_max = 500; ++ } else { ++ *x_max = (etd->capabilities[1] - i) * 64; ++ *y_max = (etd->capabilities[2] - i) * 64; ++ } + } + break; + +diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h +index 7ecaef0..9e5f1aa 100644 +--- a/drivers/input/mouse/elantech.h ++++ b/drivers/input/mouse/elantech.h +@@ -19,6 +19,7 @@ + #define ETP_FW_ID_QUERY 0x00 + #define ETP_FW_VERSION_QUERY 0x01 + #define ETP_CAPABILITIES_QUERY 0x02 ++#define ETP_SAMPLE_QUERY 0x03 + + /* + * Command values for register reading or writing +-- +1.7.6.4 + + +From 6c0ec284648f0346e96b0079999cb7af055f58ab Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Tue, 20 Sep 2011 22:42:51 -0700 +Subject: Input: elantech - remove module parameter force_elantech +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This essentially reverts commit f81bc788ff91d4efd4baf88b2c29713838caa8e5. + +With recent work on elantech driver, I believe we now have complete support +for all elantech touchpads. So remove this hack. + +Signed-off-by: JJ Ding +Reviewed-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.c | 12 ++---------- + 1 files changed, 2 insertions(+), 10 deletions(-) + +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index c2d91eb..25290b3 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -28,10 +28,6 @@ + printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \ + } while (0) + +-static bool force_elantech; +-module_param_named(force_elantech, force_elantech, bool, 0644); +-MODULE_PARM_DESC(force_elantech, "Force the Elantech PS/2 protocol extension to be used, 1 = enabled, 0 = disabled (default)."); +- + /* + * Send a Synaptics style sliced query command + */ +@@ -1164,12 +1160,8 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) + param[0], param[1], param[2]); + + if (!elantech_is_signature_valid(param)) { +- if (!force_elantech) { +- pr_debug("Probably not a real Elantech touchpad. Aborting.\n"); +- return -1; +- } +- +- pr_debug("Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n"); ++ pr_debug("Probably not a real Elantech touchpad. Aborting.\n"); ++ return -1; + } + + if (set_properties) { +-- +1.7.6.4 + diff --git a/kernel.spec b/kernel.spec index 1893ab551..e8e2ca5ec 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 8 +%global baserelease 9 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -768,6 +768,9 @@ Patch21070: oom-fix-integer-overflow-of-points.patch #rhbz 706574 Patch21071: WMI-properly-cleanup-devices-to-avoid-crashes.patch +#rhbz 728607 +Patch21060: elantech.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1416,6 +1419,9 @@ ApplyPatch oom-fix-integer-overflow-of-points.patch #rhbz 706574 ApplyPatch WMI-properly-cleanup-devices-to-avoid-crashes.patch +#rhbz 728607 +ApplyPatch elantech.patch + # END OF PATCH APPLICATIONS %endif @@ -2117,6 +2123,9 @@ fi # and build. %changelog +* Thu Nov 03 2011 Josh Boyer +- Add commits queued for 3.2 for elantech driver (rhbz 728607) + * Wed Nov 02 2011 Josh Boyer - Add patch to fix oops when removing wmi module (rhbz 706574) From 3be61a8c6020efec748f59e1b0e30ea0f1387025 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 3 Nov 2011 09:49:33 -0400 Subject: [PATCH 125/487] Fix crash when setting brightness via Fn keys on ideapads (rhbz 748210) --- ...eck-if-acpi-already-handle-backlight.patch | 31 +++++++++++++++++++ kernel.spec | 7 +++++ 2 files changed, 38 insertions(+) create mode 100644 ideapad-Check-if-acpi-already-handle-backlight.patch diff --git a/ideapad-Check-if-acpi-already-handle-backlight.patch b/ideapad-Check-if-acpi-already-handle-backlight.patch new file mode 100644 index 000000000..713e005d8 --- /dev/null +++ b/ideapad-Check-if-acpi-already-handle-backlight.patch @@ -0,0 +1,31 @@ +From d4afc7754a60b885b63ef23fd194984e2d53a4e6 Mon Sep 17 00:00:00 2001 +From: Rene Bollford +Date: Sun, 23 Oct 2011 09:56:42 +0200 +Subject: [PATCH] [PATCH] ideapad: Check if acpi already handle backlight + power to avoid a page fault + +This patch avoid a page fault in the ideapad-laptop extras when +turning the backlight power on or off. + +Signed-off-by: Rene Bolldorf +Signed-off-by: Matthew Garrett +--- + drivers/platform/x86/ideapad-laptop.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c +index 0c59541..0d94eec 100644 +--- a/drivers/platform/x86/ideapad-laptop.c ++++ b/drivers/platform/x86/ideapad-laptop.c +@@ -493,6 +493,8 @@ static void ideapad_backlight_notify_power(struct ideapad_private *priv) + unsigned long power; + struct backlight_device *blightdev = priv->blightdev; + ++ if (!blightdev) ++ return; + if (read_ec_data(ideapad_handle, 0x18, &power)) + return; + blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; +-- +1.7.6.4 + diff --git a/kernel.spec b/kernel.spec index e8e2ca5ec..42279c054 100644 --- a/kernel.spec +++ b/kernel.spec @@ -771,6 +771,9 @@ Patch21071: WMI-properly-cleanup-devices-to-avoid-crashes.patch #rhbz 728607 Patch21060: elantech.patch +#rhbz 748210 +Patch21061: ideapad-Check-if-acpi-already-handle-backlight.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1422,6 +1425,9 @@ ApplyPatch WMI-properly-cleanup-devices-to-avoid-crashes.patch #rhbz 728607 ApplyPatch elantech.patch +#rhbz 748210 +ApplyPatch ideapad-Check-if-acpi-already-handle-backlight.patch + # END OF PATCH APPLICATIONS %endif @@ -2125,6 +2131,7 @@ fi %changelog * Thu Nov 03 2011 Josh Boyer - Add commits queued for 3.2 for elantech driver (rhbz 728607) +- Fix crash when setting brightness via Fn keys on ideapads (rhbz 748210) * Wed Nov 02 2011 Josh Boyer - Add patch to fix oops when removing wmi module (rhbz 706574) From 36bb2cebdcba4d4906108facc87a9e867e555c87 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 3 Nov 2011 10:10:04 -0400 Subject: [PATCH 126/487] Adjust some PPC64 config settings suggested by Anton Blanchard --- config-powerpc64 | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/config-powerpc64 b/config-powerpc64 index 7142d8007..29ea23201 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -112,6 +112,12 @@ CONFIG_PPC_64K_PAGES=y CONFIG_PPC_SUBPAGE_PROT=y CONFIG_SCHED_SMT=y +CONFIG_HZ=100 +CONFIG_HZ_100=y +# CONFIG_HZ_1000 is not set + +CONFIG_MEMORY_HOTREMOVE=y + # CONFIG_MV643XX_ETH is not set CONFIG_IRQSTACKS=y CONFIG_DEBUG_STACKOVERFLOW=y @@ -120,7 +126,7 @@ CONFIG_DEBUG_STACKOVERFLOW=y CONFIG_EHEA=m CONFIG_INFINIBAND_EHCA=m -CONFIG_HCALL_STATS=y +# CONFIG_HCALL_STATS is not set CONFIG_XMON_DISASSEMBLY=y @@ -185,7 +191,9 @@ CONFIG_KVM_BOOK3S_64=m CONFIG_PPC_SMLPAR=y CONFIG_CMM=y #-- DLPAR memory remove -# CONFIG_SPARSEMEM_VMEMMAP is not set +CONFIG_SPARSEMEM_VMEMMAP=y + +# CONFIG_COMPACTION is not set CONFIG_PSERIES_ENERGY=m From 3468b5e931317862851aa1fcc220b591968fbc15 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 4 Nov 2011 11:57:52 -0400 Subject: [PATCH 127/487] Disable btrfs for ppc (rhbz 747079) --- config-powerpc-generic | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config-powerpc-generic b/config-powerpc-generic index ee9ab243d..ec2ff7c8e 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -355,3 +355,5 @@ CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=m # CONFIG_GPIO_GENERIC_PLATFORM is not set # CONFIG_GPIO_MCP23S08 is not set +# Disable btrfs until it is shown to work with 64k pages (rhbz 747079) +# CONFIG_BTRFS_FS is not set From 5c5ddd23f698df3861bafdda49b028c11fa46236 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 4 Nov 2011 13:38:52 -0400 Subject: [PATCH 128/487] remove dead option --- config-arm-omap-generic | 1 - 1 file changed, 1 deletion(-) diff --git a/config-arm-omap-generic b/config-arm-omap-generic index e396169b3..8c3ae6a24 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -1037,7 +1037,6 @@ CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 CONFIG_DEBUG_PREEMPT=y # CONFIG_BKL is not set # CONFIG_SPARSE_RCU_POINTER is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_HIGHMEM is not set # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_LIST is not set From 12413987823b6dfbef7ff61c61d4d6d60969bd2b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 7 Nov 2011 12:30:59 -0500 Subject: [PATCH 129/487] Add two patches to fix mac80211 issues (rhbz 731365) --- kernel.spec | 13 +++++- ...config-hw-when-going-back-on-channel.patch | 40 +++++++++++++++++ ...11-fix-remain_off_channel-regression.patch | 44 +++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 mac80211-config-hw-when-going-back-on-channel.patch create mode 100644 mac80211-fix-remain_off_channel-regression.patch diff --git a/kernel.spec b/kernel.spec index 42279c054..a1138f324 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 9 +%global baserelease 10 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -774,6 +774,10 @@ Patch21060: elantech.patch #rhbz 748210 Patch21061: ideapad-Check-if-acpi-already-handle-backlight.patch +#rhbz 731365 +Patch21062: mac80211-fix-remain_off_channel-regression.patch +Patch21063: mac80211-config-hw-when-going-back-on-channel.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1428,6 +1432,10 @@ ApplyPatch elantech.patch #rhbz 748210 ApplyPatch ideapad-Check-if-acpi-already-handle-backlight.patch +#rhbz 731365 +ApplyPatch mac80211-fix-remain_off_channel-regression.patch +ApplyPatch mac80211-config-hw-when-going-back-on-channel.patch + # END OF PATCH APPLICATIONS %endif @@ -2129,6 +2137,9 @@ fi # and build. %changelog +* Mon Nov 07 2011 Josh Boyer +- Add two patches to fix mac80211 issues (rhbz 731365) + * Thu Nov 03 2011 Josh Boyer - Add commits queued for 3.2 for elantech driver (rhbz 728607) - Fix crash when setting brightness via Fn keys on ideapads (rhbz 748210) diff --git a/mac80211-config-hw-when-going-back-on-channel.patch b/mac80211-config-hw-when-going-back-on-channel.patch new file mode 100644 index 000000000..351082744 --- /dev/null +++ b/mac80211-config-hw-when-going-back-on-channel.patch @@ -0,0 +1,40 @@ +From 776308dd5fa8a41e8bbb79818a66bd68a7db757e Mon Sep 17 00:00:00 2001 +From: Eliad Peller +Date: Thu, 20 Oct 2011 19:05:50 +0200 +Subject: [PATCH] mac80211: config hw when going back on-channel + +When going back on-channel, we should reconfigure +the hw iff the hardware is not already configured +to the operational channel. + +Signed-off-by: Eliad Peller +Cc: stable@kernel.org # 2.6.39+ +Signed-off-by: John W. Linville +--- + net/mac80211/work.c | 3 +-- + 1 files changed, 1 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/work.c b/net/mac80211/work.c +index bf5be22..6c53b6d 100644 +--- a/net/mac80211/work.c ++++ b/net/mac80211/work.c +@@ -1091,7 +1091,6 @@ static void ieee80211_work_work(struct work_struct *work) + } + + if (!remain_off_channel && local->tmp_channel) { +- bool on_oper_chan = ieee80211_cfg_on_oper_channel(local); + local->tmp_channel = NULL; + /* If tmp_channel wasn't operating channel, then + * we need to go back on-channel. +@@ -1101,7 +1100,7 @@ static void ieee80211_work_work(struct work_struct *work) + * we still need to do a hardware config. Currently, + * we cannot be here while scanning, however. + */ +- if (ieee80211_cfg_on_oper_channel(local) && !on_oper_chan) ++ if (!ieee80211_cfg_on_oper_channel(local)) + ieee80211_hw_config(local, 0); + + /* At the least, we need to disable offchannel_ps, +-- +1.7.6.2 + diff --git a/mac80211-fix-remain_off_channel-regression.patch b/mac80211-fix-remain_off_channel-regression.patch new file mode 100644 index 000000000..9f5d8f687 --- /dev/null +++ b/mac80211-fix-remain_off_channel-regression.patch @@ -0,0 +1,44 @@ +From 682ba5a44516529b29fc780c055e06104d36e31e Mon Sep 17 00:00:00 2001 +From: Eliad Peller +Date: Thu, 20 Oct 2011 19:05:49 +0200 +Subject: [PATCH] mac80211: fix remain_off_channel regression + +The offchannel code is currently broken - we should +remain_off_channel if the work was started, and +the work's channel and channel_type are the same +as local->tmp_channel and local->tmp_channel_type. + +However, if wk->chan_type and local->tmp_channel_type +coexist (e.g. have the same channel type), we won't +remain_off_channel. + +This behavior was introduced by commit da2fd1f +("mac80211: Allow work items to use existing +channel type.") + +Tested-by: Ben Greear +Signed-off-by: Eliad Peller +Cc: stable@kernel.org # 2.6.39+ +Signed-off-by: John W. Linville +--- + net/mac80211/work.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/work.c b/net/mac80211/work.c +index 94472eb..bf5be22 100644 +--- a/net/mac80211/work.c ++++ b/net/mac80211/work.c +@@ -1084,8 +1084,8 @@ static void ieee80211_work_work(struct work_struct *work) + continue; + if (wk->chan != local->tmp_channel) + continue; +- if (ieee80211_work_ct_coexists(wk->chan_type, +- local->tmp_channel_type)) ++ if (!ieee80211_work_ct_coexists(wk->chan_type, ++ local->tmp_channel_type)) + continue; + remain_off_channel = true; + } +-- +1.7.6.2 + From 5f42e49c37c91b4993ba29d8248d9b206bd21094 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Tue, 8 Nov 2011 13:34:13 -0500 Subject: [PATCH 130/487] Pull in msi irq per device in sysfs feature (bz 752176) --- kernel.spec | 8 ++ sysfs-msi-irq-per-device.patch | 239 +++++++++++++++++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 sysfs-msi-irq-per-device.patch diff --git a/kernel.spec b/kernel.spec index a1138f324..8003d5a7c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -778,6 +778,8 @@ Patch21061: ideapad-Check-if-acpi-already-handle-backlight.patch Patch21062: mac80211-fix-remain_off_channel-regression.patch Patch21063: mac80211-config-hw-when-going-back-on-channel.patch +#rhbz752176 +Patch21080: sysfs-msi-irq-per-device.patch %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1436,6 +1438,9 @@ ApplyPatch ideapad-Check-if-acpi-already-handle-backlight.patch ApplyPatch mac80211-fix-remain_off_channel-regression.patch ApplyPatch mac80211-config-hw-when-going-back-on-channel.patch +#rhbz 752176 +ApplyPatch sysfs-msi-irq-per-device.patch + # END OF PATCH APPLICATIONS %endif @@ -2137,6 +2142,9 @@ fi # and build. %changelog +* Tue Nov 08 2011 Neil Horman +- Add msi irq ennumeration per device in sysfs (rhbz 752176) + * Mon Nov 07 2011 Josh Boyer - Add two patches to fix mac80211 issues (rhbz 731365) diff --git a/sysfs-msi-irq-per-device.patch b/sysfs-msi-irq-per-device.patch new file mode 100644 index 000000000..a2bf57c92 --- /dev/null +++ b/sysfs-msi-irq-per-device.patch @@ -0,0 +1,239 @@ +From: Neil Horman +Date: Thu, 6 Oct 2011 18:08:18 +0000 (-0400) +Subject: PCI/sysfs: add per pci device msi[x] irq listing (v5) +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fjbarnes%2Fpci.git;a=commitdiff_plain;h=933aa5c1f69aa650f59ba783307fc7ed7cc5fafa + +PCI/sysfs: add per pci device msi[x] irq listing (v5) + +This patch adds a per-pci-device subdirectory in sysfs called: +/sys/bus/pci/devices//msi_irqs + +This sub-directory exports the set of msi vectors allocated by a given +pci device, by creating a numbered sub-directory for each vector beneath +msi_irqs. For each vector various attributes can be exported. +Currently the only attribute is called mode, which tracks the +operational mode of that vector (msi vs. msix) + +Acked-by: Greg Kroah-Hartman +Signed-off-by: Jesse Barnes +--- + +diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci +index 349ecf2..34f5110 100644 +--- a/Documentation/ABI/testing/sysfs-bus-pci ++++ b/Documentation/ABI/testing/sysfs-bus-pci +@@ -66,6 +66,24 @@ Description: + re-discover previously removed devices. + Depends on CONFIG_HOTPLUG. + ++What: /sys/bus/pci/devices/.../msi_irqs/ ++Date: September, 2011 ++Contact: Neil Horman ++Description: ++ The /sys/devices/.../msi_irqs directory contains a variable set ++ of sub-directories, with each sub-directory being named after a ++ corresponding msi irq vector allocated to that device. Each ++ numbered sub-directory N contains attributes of that irq. ++ Note that this directory is not created for device drivers which ++ do not support msi irqs ++ ++What: /sys/bus/pci/devices/.../msi_irqs//mode ++Date: September 2011 ++Contact: Neil Horman ++Description: ++ This attribute indicates the mode that the irq vector named by ++ the parent directory is in (msi vs. msix) ++ + What: /sys/bus/pci/devices/.../remove + Date: January 2009 + Contact: Linux PCI developers +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index 2f10328..73613e2 100644 +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -322,6 +322,8 @@ static void free_msi_irqs(struct pci_dev *dev) + if (list_is_last(&entry->list, &dev->msi_list)) + iounmap(entry->mask_base); + } ++ kobject_del(&entry->kobj); ++ kobject_put(&entry->kobj); + list_del(&entry->list); + kfree(entry); + } +@@ -402,6 +404,98 @@ void pci_restore_msi_state(struct pci_dev *dev) + } + EXPORT_SYMBOL_GPL(pci_restore_msi_state); + ++ ++#define to_msi_attr(obj) container_of(obj, struct msi_attribute, attr) ++#define to_msi_desc(obj) container_of(obj, struct msi_desc, kobj) ++ ++struct msi_attribute { ++ struct attribute attr; ++ ssize_t (*show)(struct msi_desc *entry, struct msi_attribute *attr, ++ char *buf); ++ ssize_t (*store)(struct msi_desc *entry, struct msi_attribute *attr, ++ const char *buf, size_t count); ++}; ++ ++static ssize_t show_msi_mode(struct msi_desc *entry, struct msi_attribute *atr, ++ char *buf) ++{ ++ return sprintf(buf, "%s\n", entry->msi_attrib.is_msix ? "msix" : "msi"); ++} ++ ++static ssize_t msi_irq_attr_show(struct kobject *kobj, ++ struct attribute *attr, char *buf) ++{ ++ struct msi_attribute *attribute = to_msi_attr(attr); ++ struct msi_desc *entry = to_msi_desc(kobj); ++ ++ if (!attribute->show) ++ return -EIO; ++ ++ return attribute->show(entry, attribute, buf); ++} ++ ++static const struct sysfs_ops msi_irq_sysfs_ops = { ++ .show = msi_irq_attr_show, ++}; ++ ++static struct msi_attribute mode_attribute = ++ __ATTR(mode, S_IRUGO, show_msi_mode, NULL); ++ ++ ++struct attribute *msi_irq_default_attrs[] = { ++ &mode_attribute.attr, ++ NULL ++}; ++ ++void msi_kobj_release(struct kobject *kobj) ++{ ++ struct msi_desc *entry = to_msi_desc(kobj); ++ ++ pci_dev_put(entry->dev); ++} ++ ++static struct kobj_type msi_irq_ktype = { ++ .release = msi_kobj_release, ++ .sysfs_ops = &msi_irq_sysfs_ops, ++ .default_attrs = msi_irq_default_attrs, ++}; ++ ++static int populate_msi_sysfs(struct pci_dev *pdev) ++{ ++ struct msi_desc *entry; ++ struct kobject *kobj; ++ int ret; ++ int count = 0; ++ ++ pdev->msi_kset = kset_create_and_add("msi_irqs", NULL, &pdev->dev.kobj); ++ if (!pdev->msi_kset) ++ return -ENOMEM; ++ ++ list_for_each_entry(entry, &pdev->msi_list, list) { ++ kobj = &entry->kobj; ++ kobj->kset = pdev->msi_kset; ++ pci_dev_get(pdev); ++ ret = kobject_init_and_add(kobj, &msi_irq_ktype, NULL, ++ "%u", entry->irq); ++ if (ret) ++ goto out_unroll; ++ ++ count++; ++ } ++ ++ return 0; ++ ++out_unroll: ++ list_for_each_entry(entry, &pdev->msi_list, list) { ++ if (!count) ++ break; ++ kobject_del(&entry->kobj); ++ kobject_put(&entry->kobj); ++ count--; ++ } ++ return ret; ++} ++ + /** + * msi_capability_init - configure device's MSI capability structure + * @dev: pointer to the pci_dev data structure of MSI device function +@@ -453,6 +547,13 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) + return ret; + } + ++ ret = populate_msi_sysfs(dev); ++ if (ret) { ++ msi_mask_irq(entry, mask, ~mask); ++ free_msi_irqs(dev); ++ return ret; ++ } ++ + /* Set MSI enabled bits */ + pci_intx_for_msi(dev, 0); + msi_set_enable(dev, pos, 1); +@@ -573,6 +674,12 @@ static int msix_capability_init(struct pci_dev *dev, + + msix_program_entries(dev, entries); + ++ ret = populate_msi_sysfs(dev); ++ if (ret) { ++ ret = 0; ++ goto error; ++ } ++ + /* Set MSI-X enabled bits and unmask the function */ + pci_intx_for_msi(dev, 0); + dev->msix_enabled = 1; +@@ -731,6 +838,8 @@ void pci_disable_msi(struct pci_dev *dev) + + pci_msi_shutdown(dev); + free_msi_irqs(dev); ++ kset_unregister(dev->msi_kset); ++ dev->msi_kset = NULL; + } + EXPORT_SYMBOL(pci_disable_msi); + +@@ -829,6 +938,8 @@ void pci_disable_msix(struct pci_dev *dev) + + pci_msix_shutdown(dev); + free_msi_irqs(dev); ++ kset_unregister(dev->msi_kset); ++ dev->msi_kset = NULL; + } + EXPORT_SYMBOL(pci_disable_msix); + +diff --git a/include/linux/msi.h b/include/linux/msi.h +index 05acced..ce93a34 100644 +--- a/include/linux/msi.h ++++ b/include/linux/msi.h +@@ -1,6 +1,7 @@ + #ifndef LINUX_MSI_H + #define LINUX_MSI_H + ++#include + #include + + struct msi_msg { +@@ -44,6 +45,8 @@ struct msi_desc { + + /* Last set MSI message */ + struct msi_msg msg; ++ ++ struct kobject kobj; + }; + + /* +diff --git a/include/linux/pci.h b/include/linux/pci.h +index 7cda65b..84225c7 100644 +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -336,6 +336,7 @@ struct pci_dev { + struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */ + #ifdef CONFIG_PCI_MSI + struct list_head msi_list; ++ struct kset *msi_kset; + #endif + struct pci_vpd *vpd; + #ifdef CONFIG_PCI_ATS From f8e6300ee73842f9a638c30c59748d7c4ba511f0 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 9 Nov 2011 13:50:58 -0500 Subject: [PATCH 131/487] Backport brcm80211 from 3.2-rc1 --- brcm80211.patch | 96991 ++++++++++++++++++++++++++++++++++++++++++++++ config-generic | 6 +- kernel.spec | 9 + 3 files changed, 97004 insertions(+), 2 deletions(-) create mode 100644 brcm80211.patch diff --git a/brcm80211.patch b/brcm80211.patch new file mode 100644 index 000000000..73c577f6d --- /dev/null +++ b/brcm80211.patch @@ -0,0 +1,96991 @@ +This patch represents the state of the brcm80211 driver as of 3.2-rc2, +plus a couple of one-line changes required to make it build on a 3.1 +base kernel. + +Obviously, this patch should be dropped completely when rebasing to the +final 3.2 kernel from upstream. + +-- John W. Linville + +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h.orig 2011-11-09 13:46:58.225800883 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h 2011-11-09 13:47:16.977566455 -0500 +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2011 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _bcmchip_h_ ++#define _bcmchip_h_ ++ ++/* bcm4329 */ ++/* SDIO device core, ID 0x829 */ ++#define BCM4329_CORE_BUS_BASE 0x18011000 ++/* internal memory core, ID 0x80e */ ++#define BCM4329_CORE_SOCRAM_BASE 0x18003000 ++/* ARM Cortex M3 core, ID 0x82a */ ++#define BCM4329_CORE_ARM_BASE 0x18002000 ++#define BCM4329_RAMSIZE 0x48000 ++/* firmware name */ ++#define BCM4329_FW_NAME "brcm/bcm4329-fullmac-4.bin" ++#define BCM4329_NV_NAME "brcm/bcm4329-fullmac-4.txt" ++ ++#endif /* _bcmchip_h_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c.orig 2011-11-09 13:46:58.226800871 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c 2011-11-09 13:47:16.978566442 -0500 +@@ -0,0 +1,371 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++/* ****************** SDIO CARD Interface Functions **************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include "dhd.h" ++#include "dhd_bus.h" ++#include "dhd_dbg.h" ++#include "sdio_host.h" ++ ++#define SDIOH_API_ACCESS_RETRY_LIMIT 2 ++ ++static void brcmf_sdioh_irqhandler(struct sdio_func *func) ++{ ++ struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev); ++ ++ brcmf_dbg(TRACE, "***IRQHandler\n"); ++ ++ sdio_release_host(func); ++ ++ brcmf_sdbrcm_isr(sdiodev->bus); ++ ++ sdio_claim_host(func); ++} ++ ++int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev) ++{ ++ brcmf_dbg(TRACE, "Entering\n"); ++ ++ sdio_claim_host(sdiodev->func[1]); ++ sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler); ++ sdio_release_host(sdiodev->func[1]); ++ ++ return 0; ++} ++ ++int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev) ++{ ++ brcmf_dbg(TRACE, "Entering\n"); ++ ++ sdio_claim_host(sdiodev->func[1]); ++ sdio_release_irq(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func[1]); ++ ++ return 0; ++} ++ ++u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr, ++ int *err) ++{ ++ int status; ++ s32 retry = 0; ++ u8 data = 0; ++ ++ do { ++ if (retry) /* wait for 1 ms till bus get settled down */ ++ udelay(1000); ++ status = brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, fnc_num, ++ addr, (u8 *) &data); ++ } while (status != 0 ++ && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); ++ if (err) ++ *err = status; ++ ++ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n", ++ fnc_num, addr, data); ++ ++ return data; ++} ++ ++void ++brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr, ++ u8 data, int *err) ++{ ++ int status; ++ s32 retry = 0; ++ ++ do { ++ if (retry) /* wait for 1 ms till bus get settled down */ ++ udelay(1000); ++ status = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, fnc_num, ++ addr, (u8 *) &data); ++ } while (status != 0 ++ && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); ++ if (err) ++ *err = status; ++ ++ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n", ++ fnc_num, addr, data); ++} ++ ++int ++brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) ++{ ++ int err = 0; ++ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, ++ (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err); ++ if (!err) ++ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_SBADDRMID, ++ (address >> 16) & SBSDIO_SBADDRMID_MASK, ++ &err); ++ if (!err) ++ brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_SBADDRHIGH, ++ (address >> 24) & SBSDIO_SBADDRHIGH_MASK, ++ &err); ++ ++ return err; ++} ++ ++u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size) ++{ ++ int status; ++ u32 word = 0; ++ uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; ++ ++ brcmf_dbg(INFO, "fun = 1, addr = 0x%x\n", addr); ++ ++ if (bar0 != sdiodev->sbwad) { ++ if (brcmf_sdcard_set_sbaddr_window(sdiodev, bar0)) ++ return 0xFFFFFFFF; ++ ++ sdiodev->sbwad = bar0; ++ } ++ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ if (size == 4) ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ ++ status = brcmf_sdioh_request_word(sdiodev, SDIOH_READ, SDIO_FUNC_1, ++ addr, &word, size); ++ ++ sdiodev->regfail = (status != 0); ++ ++ brcmf_dbg(INFO, "u32data = 0x%x\n", word); ++ ++ /* if ok, return appropriately masked word */ ++ if (status == 0) { ++ switch (size) { ++ case sizeof(u8): ++ return word & 0xff; ++ case sizeof(u16): ++ return word & 0xffff; ++ case sizeof(u32): ++ return word; ++ default: ++ sdiodev->regfail = true; ++ ++ } ++ } ++ ++ /* otherwise, bad sdio access or invalid size */ ++ brcmf_dbg(ERROR, "error reading addr 0x%04x size %d\n", addr, size); ++ return 0xFFFFFFFF; ++} ++ ++u32 brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size, ++ u32 data) ++{ ++ int status; ++ uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; ++ int err = 0; ++ ++ brcmf_dbg(INFO, "fun = 1, addr = 0x%x, uint%ddata = 0x%x\n", ++ addr, size * 8, data); ++ ++ if (bar0 != sdiodev->sbwad) { ++ err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); ++ if (err) ++ return err; ++ ++ sdiodev->sbwad = bar0; ++ } ++ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ if (size == 4) ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ status = ++ brcmf_sdioh_request_word(sdiodev, SDIOH_WRITE, SDIO_FUNC_1, ++ addr, &data, size); ++ sdiodev->regfail = (status != 0); ++ ++ if (status == 0) ++ return 0; ++ ++ brcmf_dbg(ERROR, "error writing 0x%08x to addr 0x%04x size %d\n", ++ data, addr, size); ++ return 0xFFFFFFFF; ++} ++ ++bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev) ++{ ++ return sdiodev->regfail; ++} ++ ++int ++brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ++ uint flags, ++ u8 *buf, uint nbytes, struct sk_buff *pkt) ++{ ++ int status; ++ uint incr_fix; ++ uint width; ++ uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; ++ int err = 0; ++ ++ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, nbytes); ++ ++ /* Async not implemented yet */ ++ if (flags & SDIO_REQ_ASYNC) ++ return -ENOTSUPP; ++ ++ if (bar0 != sdiodev->sbwad) { ++ err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); ++ if (err) ++ return err; ++ ++ sdiodev->sbwad = bar0; ++ } ++ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ ++ incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; ++ width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; ++ if (width == 4) ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ ++ status = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ, ++ fn, addr, width, nbytes, buf, pkt); ++ ++ return status; ++} ++ ++int ++brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ++ uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt) ++{ ++ uint incr_fix; ++ uint width; ++ uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; ++ int err = 0; ++ ++ brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, nbytes); ++ ++ /* Async not implemented yet */ ++ if (flags & SDIO_REQ_ASYNC) ++ return -ENOTSUPP; ++ ++ if (bar0 != sdiodev->sbwad) { ++ err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); ++ if (err) ++ return err; ++ ++ sdiodev->sbwad = bar0; ++ } ++ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ ++ incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; ++ width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; ++ if (width == 4) ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ ++ return brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn, ++ addr, width, nbytes, buf, pkt); ++} ++ ++int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr, ++ u8 *buf, uint nbytes) ++{ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ ++ return brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC, ++ (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1, ++ addr, 4, nbytes, buf, NULL); ++} ++ ++int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn) ++{ ++ char t_func = (char)fn; ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* issue abort cmd52 command through F0 */ ++ brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0, ++ SDIO_CCCR_ABORT, &t_func); ++ ++ brcmf_dbg(TRACE, "Exit\n"); ++ return 0; ++} ++ ++int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) ++{ ++ u32 regs = 0; ++ int ret = 0; ++ ++ ret = brcmf_sdioh_attach(sdiodev); ++ if (ret) ++ goto out; ++ ++ regs = SI_ENUM_BASE; ++ ++ /* Report the BAR, to fix if needed */ ++ sdiodev->sbwad = SI_ENUM_BASE; ++ ++ /* try to attach to the target device */ ++ sdiodev->bus = brcmf_sdbrcm_probe(0, 0, 0, 0, regs, sdiodev); ++ if (!sdiodev->bus) { ++ brcmf_dbg(ERROR, "device attach failed\n"); ++ ret = -ENODEV; ++ goto out; ++ } ++ ++out: ++ if (ret) ++ brcmf_sdio_remove(sdiodev); ++ ++ return ret; ++} ++EXPORT_SYMBOL(brcmf_sdio_probe); ++ ++int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev) ++{ ++ if (sdiodev->bus) { ++ brcmf_sdbrcm_disconnect(sdiodev->bus); ++ sdiodev->bus = NULL; ++ } ++ ++ brcmf_sdioh_detach(sdiodev); ++ ++ sdiodev->sbwad = 0; ++ ++ return 0; ++} ++EXPORT_SYMBOL(brcmf_sdio_remove); ++ ++void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable) ++{ ++ if (enable) ++ brcmf_sdbrcm_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS); ++ else ++ brcmf_sdbrcm_wd_timer(sdiodev->bus, 0); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c.orig 2011-11-09 13:46:58.228800847 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c 2011-11-09 13:47:16.980566416 -0500 +@@ -0,0 +1,626 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* request_irq() */ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include "sdio_host.h" ++#include "dhd.h" ++#include "dhd_dbg.h" ++#include "wl_cfg80211.h" ++ ++#define SDIO_VENDOR_ID_BROADCOM 0x02d0 ++ ++#define DMA_ALIGN_MASK 0x03 ++ ++#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 ++ ++#define SDIO_FUNC1_BLOCKSIZE 64 ++#define SDIO_FUNC2_BLOCKSIZE 512 ++ ++/* devices we support, null terminated */ ++static const struct sdio_device_id brcmf_sdmmc_ids[] = { ++ {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, ++ { /* end: all zeroes */ }, ++}; ++MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); ++ ++static bool ++brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev) ++{ ++ bool is_err = false; ++#ifdef CONFIG_PM_SLEEP ++ is_err = atomic_read(&sdiodev->suspend); ++#endif ++ return is_err; ++} ++ ++static void ++brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, wait_queue_head_t *wq) ++{ ++#ifdef CONFIG_PM_SLEEP ++ int retry = 0; ++ while (atomic_read(&sdiodev->suspend) && retry++ != 30) ++ wait_event_timeout(*wq, false, HZ/100); ++#endif ++} ++ ++static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, ++ uint regaddr, u8 *byte) ++{ ++ struct sdio_func *sdfunc = sdiodev->func[0]; ++ int err_ret; ++ ++ /* ++ * Can only directly write to some F0 registers. ++ * Handle F2 enable/disable and Abort command ++ * as a special case. ++ */ ++ if (regaddr == SDIO_CCCR_IOEx) { ++ sdfunc = sdiodev->func[2]; ++ if (sdfunc) { ++ sdio_claim_host(sdfunc); ++ if (*byte & SDIO_FUNC_ENABLE_2) { ++ /* Enable Function 2 */ ++ err_ret = sdio_enable_func(sdfunc); ++ if (err_ret) ++ brcmf_dbg(ERROR, ++ "enable F2 failed:%d\n", ++ err_ret); ++ } else { ++ /* Disable Function 2 */ ++ err_ret = sdio_disable_func(sdfunc); ++ if (err_ret) ++ brcmf_dbg(ERROR, ++ "Disable F2 failed:%d\n", ++ err_ret); ++ } ++ sdio_release_host(sdfunc); ++ } ++ } else if (regaddr == SDIO_CCCR_ABORT) { ++ sdio_claim_host(sdfunc); ++ sdio_writeb(sdfunc, *byte, regaddr, &err_ret); ++ sdio_release_host(sdfunc); ++ } else if (regaddr < 0xF0) { ++ brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr); ++ err_ret = -EPERM; ++ } else { ++ sdio_claim_host(sdfunc); ++ sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret); ++ sdio_release_host(sdfunc); ++ } ++ ++ return err_ret; ++} ++ ++int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, ++ uint regaddr, u8 *byte) ++{ ++ int err_ret; ++ ++ brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr); ++ ++ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait); ++ if (brcmf_pm_resume_error(sdiodev)) ++ return -EIO; ++ ++ if (rw && func == 0) { ++ /* handle F0 separately */ ++ err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte); ++ } else { ++ sdio_claim_host(sdiodev->func[func]); ++ if (rw) /* CMD52 Write */ ++ sdio_writeb(sdiodev->func[func], *byte, regaddr, ++ &err_ret); ++ else if (func == 0) { ++ *byte = sdio_f0_readb(sdiodev->func[func], regaddr, ++ &err_ret); ++ } else { ++ *byte = sdio_readb(sdiodev->func[func], regaddr, ++ &err_ret); ++ } ++ sdio_release_host(sdiodev->func[func]); ++ } ++ ++ if (err_ret) ++ brcmf_dbg(ERROR, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", ++ rw ? "write" : "read", func, regaddr, *byte, err_ret); ++ ++ return err_ret; ++} ++ ++int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, ++ uint rw, uint func, uint addr, u32 *word, ++ uint nbytes) ++{ ++ int err_ret = -EIO; ++ ++ if (func == 0) { ++ brcmf_dbg(ERROR, "Only CMD52 allowed to F0\n"); ++ return -EINVAL; ++ } ++ ++ brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", ++ rw, func, addr, nbytes); ++ ++ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); ++ if (brcmf_pm_resume_error(sdiodev)) ++ return -EIO; ++ /* Claim host controller */ ++ sdio_claim_host(sdiodev->func[func]); ++ ++ if (rw) { /* CMD52 Write */ ++ if (nbytes == 4) ++ sdio_writel(sdiodev->func[func], *word, addr, ++ &err_ret); ++ else if (nbytes == 2) ++ sdio_writew(sdiodev->func[func], (*word & 0xFFFF), ++ addr, &err_ret); ++ else ++ brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes); ++ } else { /* CMD52 Read */ ++ if (nbytes == 4) ++ *word = sdio_readl(sdiodev->func[func], addr, &err_ret); ++ else if (nbytes == 2) ++ *word = sdio_readw(sdiodev->func[func], addr, ++ &err_ret) & 0xFFFF; ++ else ++ brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes); ++ } ++ ++ /* Release host controller */ ++ sdio_release_host(sdiodev->func[func]); ++ ++ if (err_ret) ++ brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n", ++ rw ? "write" : "read", err_ret); ++ ++ return err_ret; ++} ++ ++static int ++brcmf_sdioh_request_packet(struct brcmf_sdio_dev *sdiodev, uint fix_inc, ++ uint write, uint func, uint addr, ++ struct sk_buff *pkt) ++{ ++ bool fifo = (fix_inc == SDIOH_DATA_FIX); ++ u32 SGCount = 0; ++ int err_ret = 0; ++ ++ struct sk_buff *pnext; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_packet_wait); ++ if (brcmf_pm_resume_error(sdiodev)) ++ return -EIO; ++ ++ /* Claim host controller */ ++ sdio_claim_host(sdiodev->func[func]); ++ for (pnext = pkt; pnext; pnext = pnext->next) { ++ uint pkt_len = pnext->len; ++ pkt_len += 3; ++ pkt_len &= 0xFFFFFFFC; ++ ++ if ((write) && (!fifo)) { ++ err_ret = sdio_memcpy_toio(sdiodev->func[func], addr, ++ ((u8 *) (pnext->data)), ++ pkt_len); ++ } else if (write) { ++ err_ret = sdio_memcpy_toio(sdiodev->func[func], addr, ++ ((u8 *) (pnext->data)), ++ pkt_len); ++ } else if (fifo) { ++ err_ret = sdio_readsb(sdiodev->func[func], ++ ((u8 *) (pnext->data)), ++ addr, pkt_len); ++ } else { ++ err_ret = sdio_memcpy_fromio(sdiodev->func[func], ++ ((u8 *) (pnext->data)), ++ addr, pkt_len); ++ } ++ ++ if (err_ret) { ++ brcmf_dbg(ERROR, "%s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n", ++ write ? "TX" : "RX", pnext, SGCount, addr, ++ pkt_len, err_ret); ++ } else { ++ brcmf_dbg(TRACE, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n", ++ write ? "TX" : "RX", pnext, SGCount, addr, ++ pkt_len); ++ } ++ ++ if (!fifo) ++ addr += pkt_len; ++ SGCount++; ++ ++ } ++ ++ /* Release host controller */ ++ sdio_release_host(sdiodev->func[func]); ++ ++ brcmf_dbg(TRACE, "Exit\n"); ++ return err_ret; ++} ++ ++/* ++ * This function takes a buffer or packet, and fixes everything up ++ * so that in the end, a DMA-able packet is created. ++ * ++ * A buffer does not have an associated packet pointer, ++ * and may or may not be aligned. ++ * A packet may consist of a single packet, or a packet chain. ++ * If it is a packet chain, then all the packets in the chain ++ * must be properly aligned. ++ * ++ * If the packet data is not aligned, then there may only be ++ * one packet, and in this case, it is copied to a new ++ * aligned packet. ++ * ++ */ ++int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, ++ uint fix_inc, uint write, uint func, uint addr, ++ uint reg_width, uint buflen_u, u8 *buffer, ++ struct sk_buff *pkt) ++{ ++ int Status; ++ struct sk_buff *mypkt = NULL; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); ++ if (brcmf_pm_resume_error(sdiodev)) ++ return -EIO; ++ /* Case 1: we don't have a packet. */ ++ if (pkt == NULL) { ++ brcmf_dbg(DATA, "Creating new %s Packet, len=%d\n", ++ write ? "TX" : "RX", buflen_u); ++ mypkt = brcmu_pkt_buf_get_skb(buflen_u); ++ if (!mypkt) { ++ brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n", ++ buflen_u); ++ return -EIO; ++ } ++ ++ /* For a write, copy the buffer data into the packet. */ ++ if (write) ++ memcpy(mypkt->data, buffer, buflen_u); ++ ++ Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write, ++ func, addr, mypkt); ++ ++ /* For a read, copy the packet data back to the buffer. */ ++ if (!write) ++ memcpy(buffer, mypkt->data, buflen_u); ++ ++ brcmu_pkt_buf_free_skb(mypkt); ++ } else if (((ulong) (pkt->data) & DMA_ALIGN_MASK) != 0) { ++ /* ++ * Case 2: We have a packet, but it is unaligned. ++ * In this case, we cannot have a chain (pkt->next == NULL) ++ */ ++ brcmf_dbg(DATA, "Creating aligned %s Packet, len=%d\n", ++ write ? "TX" : "RX", pkt->len); ++ mypkt = brcmu_pkt_buf_get_skb(pkt->len); ++ if (!mypkt) { ++ brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n", ++ pkt->len); ++ return -EIO; ++ } ++ ++ /* For a write, copy the buffer data into the packet. */ ++ if (write) ++ memcpy(mypkt->data, pkt->data, pkt->len); ++ ++ Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write, ++ func, addr, mypkt); ++ ++ /* For a read, copy the packet data back to the buffer. */ ++ if (!write) ++ memcpy(pkt->data, mypkt->data, mypkt->len); ++ ++ brcmu_pkt_buf_free_skb(mypkt); ++ } else { /* case 3: We have a packet and ++ it is aligned. */ ++ brcmf_dbg(DATA, "Aligned %s Packet, direct DMA\n", ++ write ? "Tx" : "Rx"); ++ Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write, ++ func, addr, pkt); ++ } ++ ++ return Status; ++} ++ ++/* Read client card reg */ ++static int ++brcmf_sdioh_card_regread(struct brcmf_sdio_dev *sdiodev, int func, u32 regaddr, ++ int regsize, u32 *data) ++{ ++ ++ if ((func == 0) || (regsize == 1)) { ++ u8 temp = 0; ++ ++ brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, func, regaddr, ++ &temp); ++ *data = temp; ++ *data &= 0xff; ++ brcmf_dbg(DATA, "byte read data=0x%02x\n", *data); ++ } else { ++ brcmf_sdioh_request_word(sdiodev, SDIOH_READ, func, regaddr, ++ data, regsize); ++ if (regsize == 2) ++ *data &= 0xffff; ++ ++ brcmf_dbg(DATA, "word read data=0x%08x\n", *data); ++ } ++ ++ return SUCCESS; ++} ++ ++static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr) ++{ ++ /* read 24 bits and return valid 17 bit addr */ ++ int i; ++ u32 scratch, regdata; ++ __le32 scratch_le; ++ u8 *ptr = (u8 *)&scratch_le; ++ ++ for (i = 0; i < 3; i++) { ++ if ((brcmf_sdioh_card_regread(sdiodev, 0, regaddr, 1, ++ ®data)) != SUCCESS) ++ brcmf_dbg(ERROR, "Can't read!\n"); ++ ++ *ptr++ = (u8) regdata; ++ regaddr++; ++ } ++ ++ /* Only the lower 17-bits are valid */ ++ scratch = le32_to_cpu(scratch_le); ++ scratch &= 0x0001FFFF; ++ return scratch; ++} ++ ++static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev) ++{ ++ int err_ret; ++ u32 fbraddr; ++ u8 func; ++ ++ brcmf_dbg(TRACE, "\n"); ++ ++ /* Get the Card's common CIS address */ ++ sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev, ++ SDIO_CCCR_CIS); ++ brcmf_dbg(INFO, "Card's Common CIS Ptr = 0x%x\n", ++ sdiodev->func_cis_ptr[0]); ++ ++ /* Get the Card's function CIS (for each function) */ ++ for (fbraddr = SDIO_FBR_BASE(1), func = 1; ++ func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) { ++ sdiodev->func_cis_ptr[func] = ++ brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr); ++ brcmf_dbg(INFO, "Function %d CIS Ptr = 0x%x\n", ++ func, sdiodev->func_cis_ptr[func]); ++ } ++ ++ /* Enable Function 1 */ ++ sdio_claim_host(sdiodev->func[1]); ++ err_ret = sdio_enable_func(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func[1]); ++ if (err_ret) ++ brcmf_dbg(ERROR, "Failed to enable F1 Err: 0x%08x\n", err_ret); ++ ++ return false; ++} ++ ++/* ++ * Public entry points & extern's ++ */ ++int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev) ++{ ++ int err_ret = 0; ++ ++ brcmf_dbg(TRACE, "\n"); ++ ++ sdiodev->num_funcs = 2; ++ ++ sdio_claim_host(sdiodev->func[1]); ++ err_ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE); ++ sdio_release_host(sdiodev->func[1]); ++ if (err_ret) { ++ brcmf_dbg(ERROR, "Failed to set F1 blocksize\n"); ++ goto out; ++ } ++ ++ sdio_claim_host(sdiodev->func[2]); ++ err_ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE); ++ sdio_release_host(sdiodev->func[2]); ++ if (err_ret) { ++ brcmf_dbg(ERROR, "Failed to set F2 blocksize\n"); ++ goto out; ++ } ++ ++ brcmf_sdioh_enablefuncs(sdiodev); ++ ++out: ++ brcmf_dbg(TRACE, "Done\n"); ++ return err_ret; ++} ++ ++void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev) ++{ ++ brcmf_dbg(TRACE, "\n"); ++ ++ /* Disable Function 2 */ ++ sdio_claim_host(sdiodev->func[2]); ++ sdio_disable_func(sdiodev->func[2]); ++ sdio_release_host(sdiodev->func[2]); ++ ++ /* Disable Function 1 */ ++ sdio_claim_host(sdiodev->func[1]); ++ sdio_disable_func(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func[1]); ++ ++} ++ ++static int brcmf_ops_sdio_probe(struct sdio_func *func, ++ const struct sdio_device_id *id) ++{ ++ int ret = 0; ++ struct brcmf_sdio_dev *sdiodev; ++ brcmf_dbg(TRACE, "Enter\n"); ++ brcmf_dbg(TRACE, "func->class=%x\n", func->class); ++ brcmf_dbg(TRACE, "sdio_vendor: 0x%04x\n", func->vendor); ++ brcmf_dbg(TRACE, "sdio_device: 0x%04x\n", func->device); ++ brcmf_dbg(TRACE, "Function#: 0x%04x\n", func->num); ++ ++ if (func->num == 1) { ++ if (dev_get_drvdata(&func->card->dev)) { ++ brcmf_dbg(ERROR, "card private drvdata occupied\n"); ++ return -ENXIO; ++ } ++ sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL); ++ if (!sdiodev) ++ return -ENOMEM; ++ sdiodev->func[0] = func->card->sdio_func[0]; ++ sdiodev->func[1] = func; ++ dev_set_drvdata(&func->card->dev, sdiodev); ++ ++ atomic_set(&sdiodev->suspend, false); ++ init_waitqueue_head(&sdiodev->request_byte_wait); ++ init_waitqueue_head(&sdiodev->request_word_wait); ++ init_waitqueue_head(&sdiodev->request_packet_wait); ++ init_waitqueue_head(&sdiodev->request_buffer_wait); ++ } ++ ++ if (func->num == 2) { ++ sdiodev = dev_get_drvdata(&func->card->dev); ++ if ((!sdiodev) || (sdiodev->func[1]->card != func->card)) ++ return -ENODEV; ++ sdiodev->func[2] = func; ++ ++ brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n"); ++ ret = brcmf_sdio_probe(sdiodev); ++ } ++ ++ return ret; ++} ++ ++static void brcmf_ops_sdio_remove(struct sdio_func *func) ++{ ++ struct brcmf_sdio_dev *sdiodev; ++ brcmf_dbg(TRACE, "Enter\n"); ++ brcmf_dbg(INFO, "func->class=%x\n", func->class); ++ brcmf_dbg(INFO, "sdio_vendor: 0x%04x\n", func->vendor); ++ brcmf_dbg(INFO, "sdio_device: 0x%04x\n", func->device); ++ brcmf_dbg(INFO, "Function#: 0x%04x\n", func->num); ++ ++ if (func->num == 2) { ++ sdiodev = dev_get_drvdata(&func->card->dev); ++ brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_remove...\n"); ++ brcmf_sdio_remove(sdiodev); ++ dev_set_drvdata(&func->card->dev, NULL); ++ kfree(sdiodev); ++ } ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int brcmf_sdio_suspend(struct device *dev) ++{ ++ mmc_pm_flag_t sdio_flags; ++ struct brcmf_sdio_dev *sdiodev; ++ struct sdio_func *func = dev_to_sdio_func(dev); ++ int ret = 0; ++ ++ brcmf_dbg(TRACE, "\n"); ++ ++ sdiodev = dev_get_drvdata(&func->card->dev); ++ ++ atomic_set(&sdiodev->suspend, true); ++ ++ sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]); ++ if (!(sdio_flags & MMC_PM_KEEP_POWER)) { ++ brcmf_dbg(ERROR, "Host can't keep power while suspended\n"); ++ return -EINVAL; ++ } ++ ++ ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER); ++ if (ret) { ++ brcmf_dbg(ERROR, "Failed to set pm_flags\n"); ++ return ret; ++ } ++ ++ brcmf_sdio_wdtmr_enable(sdiodev, false); ++ ++ return ret; ++} ++ ++static int brcmf_sdio_resume(struct device *dev) ++{ ++ struct brcmf_sdio_dev *sdiodev; ++ struct sdio_func *func = dev_to_sdio_func(dev); ++ ++ sdiodev = dev_get_drvdata(&func->card->dev); ++ brcmf_sdio_wdtmr_enable(sdiodev, true); ++ atomic_set(&sdiodev->suspend, false); ++ return 0; ++} ++ ++static const struct dev_pm_ops brcmf_sdio_pm_ops = { ++ .suspend = brcmf_sdio_suspend, ++ .resume = brcmf_sdio_resume, ++}; ++#endif /* CONFIG_PM_SLEEP */ ++ ++static struct sdio_driver brcmf_sdmmc_driver = { ++ .probe = brcmf_ops_sdio_probe, ++ .remove = brcmf_ops_sdio_remove, ++ .name = "brcmfmac", ++ .id_table = brcmf_sdmmc_ids, ++#ifdef CONFIG_PM_SLEEP ++ .drv = { ++ .pm = &brcmf_sdio_pm_ops, ++ }, ++#endif /* CONFIG_PM_SLEEP */ ++}; ++ ++/* bus register interface */ ++int brcmf_bus_register(void) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ return sdio_register_driver(&brcmf_sdmmc_driver); ++} ++ ++void brcmf_bus_unregister(void) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ sdio_unregister_driver(&brcmf_sdmmc_driver); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h.orig 2011-11-09 13:46:58.229800834 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h 2011-11-09 13:47:16.980566416 -0500 +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCMF_BUS_H_ ++#define _BRCMF_BUS_H_ ++ ++/* Packet alignment for most efficient SDIO (can change based on platform) */ ++#define BRCMF_SDALIGN (1 << 6) ++ ++/* watchdog polling interval in ms */ ++#define BRCMF_WD_POLL_MS 10 ++ ++/* ++ * Exported from brcmf bus module (brcmf_usb, brcmf_sdio) ++ */ ++ ++/* Indicate (dis)interest in finding dongles. */ ++extern int brcmf_bus_register(void); ++extern void brcmf_bus_unregister(void); ++ ++/* obtain linux device object providing bus function */ ++extern struct device *brcmf_bus_get_device(struct brcmf_bus *bus); ++ ++/* Stop bus module: clear pending frames, disable data flow */ ++extern void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus); ++ ++/* Initialize bus module: prepare for communication w/dongle */ ++extern int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr); ++ ++/* Send a data frame to the dongle. Callee disposes of txp. */ ++extern int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *txp); ++ ++/* Send/receive a control message to/from the dongle. ++ * Expects caller to enforce a single outstanding transaction. ++ */ ++extern int ++brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen); ++ ++extern int ++brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen); ++ ++extern void brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick); ++ ++#endif /* _BRCMF_BUS_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c.orig 2011-11-09 13:46:58.230800821 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c 2011-11-09 13:47:16.981566403 -0500 +@@ -0,0 +1,498 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/******************************************************************************* ++ * Communicates with the dongle by using dcmd codes. ++ * For certain dcmd codes, the dongle interprets string data from the host. ++ ******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "dhd.h" ++#include "dhd_proto.h" ++#include "dhd_bus.h" ++#include "dhd_dbg.h" ++ ++struct brcmf_proto_cdc_dcmd { ++ __le32 cmd; /* dongle command value */ ++ __le32 len; /* lower 16: output buflen; ++ * upper 16: input buflen (excludes header) */ ++ __le32 flags; /* flag defns given below */ ++ __le32 status; /* status code returned from the device */ ++}; ++ ++/* Max valid buffer size that can be sent to the dongle */ ++#define CDC_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN) ++ ++/* CDC flag definitions */ ++#define CDC_DCMD_ERROR 0x01 /* 1=cmd failed */ ++#define CDC_DCMD_SET 0x02 /* 0=get, 1=set cmd */ ++#define CDC_DCMD_IF_MASK 0xF000 /* I/F index */ ++#define CDC_DCMD_IF_SHIFT 12 ++#define CDC_DCMD_ID_MASK 0xFFFF0000 /* id an cmd pairing */ ++#define CDC_DCMD_ID_SHIFT 16 /* ID Mask shift bits */ ++#define CDC_DCMD_ID(flags) \ ++ (((flags) & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT) ++ ++/* ++ * BDC header - Broadcom specific extension of CDC. ++ * Used on data packets to convey priority across USB. ++ */ ++#define BDC_HEADER_LEN 4 ++#define BDC_PROTO_VER 1 /* Protocol version */ ++#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ ++#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ ++#define BDC_FLAG_SUM_GOOD 0x04 /* Good RX checksums */ ++#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */ ++#define BDC_PRIORITY_MASK 0x7 ++#define BDC_FLAG2_IF_MASK 0x0f /* packet rx interface in APSTA */ ++#define BDC_FLAG2_IF_SHIFT 0 ++ ++#define BDC_GET_IF_IDX(hdr) \ ++ ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT)) ++#define BDC_SET_IF_IDX(hdr, idx) \ ++ ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \ ++ ((idx) << BDC_FLAG2_IF_SHIFT))) ++ ++struct brcmf_proto_bdc_header { ++ u8 flags; ++ u8 priority; /* 802.1d Priority, 4:7 flow control info for usb */ ++ u8 flags2; ++ u8 rssi; ++}; ++ ++ ++#define RETRIES 2 /* # of retries to retrieve matching dcmd response */ ++#define BUS_HEADER_LEN (16+BRCMF_SDALIGN) /* Must be atleast SDPCM_RESERVE ++ * (amount of header tha might be added) ++ * plus any space that might be needed ++ * for alignment padding. ++ */ ++#define ROUND_UP_MARGIN 2048 /* Biggest SDIO block size possible for ++ * round off at the end of buffer ++ */ ++ ++struct brcmf_proto { ++ u16 reqid; ++ u8 pending; ++ u32 lastcmd; ++ u8 bus_header[BUS_HEADER_LEN]; ++ struct brcmf_proto_cdc_dcmd msg; ++ unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN]; ++}; ++ ++static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr) ++{ ++ struct brcmf_proto *prot = drvr->prot; ++ int len = le32_to_cpu(prot->msg.len) + ++ sizeof(struct brcmf_proto_cdc_dcmd); ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* NOTE : cdc->msg.len holds the desired length of the buffer to be ++ * returned. Only up to CDC_MAX_MSG_SIZE of this buffer area ++ * is actually sent to the dongle ++ */ ++ if (len > CDC_MAX_MSG_SIZE) ++ len = CDC_MAX_MSG_SIZE; ++ ++ /* Send request */ ++ return brcmf_sdbrcm_bus_txctl(drvr->bus, (unsigned char *)&prot->msg, ++ len); ++} ++ ++static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) ++{ ++ int ret; ++ struct brcmf_proto *prot = drvr->prot; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ do { ++ ret = brcmf_sdbrcm_bus_rxctl(drvr->bus, ++ (unsigned char *)&prot->msg, ++ len + sizeof(struct brcmf_proto_cdc_dcmd)); ++ if (ret < 0) ++ break; ++ } while (CDC_DCMD_ID(le32_to_cpu(prot->msg.flags)) != id); ++ ++ return ret; ++} ++ ++int ++brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, ++ void *buf, uint len) ++{ ++ struct brcmf_proto *prot = drvr->prot; ++ struct brcmf_proto_cdc_dcmd *msg = &prot->msg; ++ void *info; ++ int ret = 0, retries = 0; ++ u32 id, flags; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ brcmf_dbg(CTL, "cmd %d len %d\n", cmd, len); ++ ++ /* Respond "bcmerror" and "bcmerrorstr" with local cache */ ++ if (cmd == BRCMF_C_GET_VAR && buf) { ++ if (!strcmp((char *)buf, "bcmerrorstr")) { ++ strncpy((char *)buf, "bcm_error", ++ BCME_STRLEN); ++ goto done; ++ } else if (!strcmp((char *)buf, "bcmerror")) { ++ *(int *)buf = drvr->dongle_error; ++ goto done; ++ } ++ } ++ ++ memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); ++ ++ msg->cmd = cpu_to_le32(cmd); ++ msg->len = cpu_to_le32(len); ++ flags = (++prot->reqid << CDC_DCMD_ID_SHIFT); ++ flags = (flags & ~CDC_DCMD_IF_MASK) | ++ (ifidx << CDC_DCMD_IF_SHIFT); ++ msg->flags = cpu_to_le32(flags); ++ ++ if (buf) ++ memcpy(prot->buf, buf, len); ++ ++ ret = brcmf_proto_cdc_msg(drvr); ++ if (ret < 0) { ++ brcmf_dbg(ERROR, "brcmf_proto_cdc_msg failed w/status %d\n", ++ ret); ++ goto done; ++ } ++ ++retry: ++ /* wait for interrupt and get first fragment */ ++ ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len); ++ if (ret < 0) ++ goto done; ++ ++ flags = le32_to_cpu(msg->flags); ++ id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT; ++ ++ if ((id < prot->reqid) && (++retries < RETRIES)) ++ goto retry; ++ if (id != prot->reqid) { ++ brcmf_dbg(ERROR, "%s: unexpected request id %d (expected %d)\n", ++ brcmf_ifname(drvr, ifidx), id, prot->reqid); ++ ret = -EINVAL; ++ goto done; ++ } ++ ++ /* Check info buffer */ ++ info = (void *)&msg[1]; ++ ++ /* Copy info buffer */ ++ if (buf) { ++ if (ret < (int)len) ++ len = ret; ++ memcpy(buf, info, len); ++ } ++ ++ /* Check the ERROR flag */ ++ if (flags & CDC_DCMD_ERROR) { ++ ret = le32_to_cpu(msg->status); ++ /* Cache error from dongle */ ++ drvr->dongle_error = ret; ++ } ++ ++done: ++ return ret; ++} ++ ++int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, ++ void *buf, uint len) ++{ ++ struct brcmf_proto *prot = drvr->prot; ++ struct brcmf_proto_cdc_dcmd *msg = &prot->msg; ++ int ret = 0; ++ u32 flags, id; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ brcmf_dbg(CTL, "cmd %d len %d\n", cmd, len); ++ ++ memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); ++ ++ msg->cmd = cpu_to_le32(cmd); ++ msg->len = cpu_to_le32(len); ++ flags = (++prot->reqid << CDC_DCMD_ID_SHIFT) | CDC_DCMD_SET; ++ flags = (flags & ~CDC_DCMD_IF_MASK) | ++ (ifidx << CDC_DCMD_IF_SHIFT); ++ msg->flags = cpu_to_le32(flags); ++ ++ if (buf) ++ memcpy(prot->buf, buf, len); ++ ++ ret = brcmf_proto_cdc_msg(drvr); ++ if (ret < 0) ++ goto done; ++ ++ ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len); ++ if (ret < 0) ++ goto done; ++ ++ flags = le32_to_cpu(msg->flags); ++ id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT; ++ ++ if (id != prot->reqid) { ++ brcmf_dbg(ERROR, "%s: unexpected request id %d (expected %d)\n", ++ brcmf_ifname(drvr, ifidx), id, prot->reqid); ++ ret = -EINVAL; ++ goto done; ++ } ++ ++ /* Check the ERROR flag */ ++ if (flags & CDC_DCMD_ERROR) { ++ ret = le32_to_cpu(msg->status); ++ /* Cache error from dongle */ ++ drvr->dongle_error = ret; ++ } ++ ++done: ++ return ret; ++} ++ ++int ++brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx, struct brcmf_dcmd *dcmd, ++ int len) ++{ ++ struct brcmf_proto *prot = drvr->prot; ++ int ret = -1; ++ ++ if (drvr->busstate == BRCMF_BUS_DOWN) { ++ brcmf_dbg(ERROR, "bus is down. we have nothing to do.\n"); ++ return ret; ++ } ++ brcmf_os_proto_block(drvr); ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (len > BRCMF_DCMD_MAXLEN) ++ goto done; ++ ++ if (prot->pending == true) { ++ brcmf_dbg(TRACE, "CDC packet is pending!!!! cmd=0x%x (%lu) lastcmd=0x%x (%lu)\n", ++ dcmd->cmd, (unsigned long)dcmd->cmd, prot->lastcmd, ++ (unsigned long)prot->lastcmd); ++ if (dcmd->cmd == BRCMF_C_SET_VAR || ++ dcmd->cmd == BRCMF_C_GET_VAR) ++ brcmf_dbg(TRACE, "iovar cmd=%s\n", (char *)dcmd->buf); ++ ++ goto done; ++ } ++ ++ prot->pending = true; ++ prot->lastcmd = dcmd->cmd; ++ if (dcmd->set) ++ ret = brcmf_proto_cdc_set_dcmd(drvr, ifidx, dcmd->cmd, ++ dcmd->buf, len); ++ else { ++ ret = brcmf_proto_cdc_query_dcmd(drvr, ifidx, dcmd->cmd, ++ dcmd->buf, len); ++ if (ret > 0) ++ dcmd->used = ret - ++ sizeof(struct brcmf_proto_cdc_dcmd); ++ } ++ ++ if (ret >= 0) ++ ret = 0; ++ else { ++ struct brcmf_proto_cdc_dcmd *msg = &prot->msg; ++ /* len == needed when set/query fails from dongle */ ++ dcmd->needed = le32_to_cpu(msg->len); ++ } ++ ++ /* Intercept the wme_dp dongle cmd here */ ++ if (!ret && dcmd->cmd == BRCMF_C_SET_VAR && ++ !strcmp(dcmd->buf, "wme_dp")) { ++ int slen; ++ __le32 val = 0; ++ ++ slen = strlen("wme_dp") + 1; ++ if (len >= (int)(slen + sizeof(int))) ++ memcpy(&val, (char *)dcmd->buf + slen, sizeof(int)); ++ drvr->wme_dp = (u8) le32_to_cpu(val); ++ } ++ ++ prot->pending = false; ++ ++done: ++ brcmf_os_proto_unblock(drvr); ++ ++ return ret; ++} ++ ++static bool pkt_sum_needed(struct sk_buff *skb) ++{ ++ return skb->ip_summed == CHECKSUM_PARTIAL; ++} ++ ++static void pkt_set_sum_good(struct sk_buff *skb, bool x) ++{ ++ skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE); ++} ++ ++void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, ++ struct sk_buff *pktbuf) ++{ ++ struct brcmf_proto_bdc_header *h; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Push BDC header used to convey priority for buses that don't */ ++ ++ skb_push(pktbuf, BDC_HEADER_LEN); ++ ++ h = (struct brcmf_proto_bdc_header *)(pktbuf->data); ++ ++ h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); ++ if (pkt_sum_needed(pktbuf)) ++ h->flags |= BDC_FLAG_SUM_NEEDED; ++ ++ h->priority = (pktbuf->priority & BDC_PRIORITY_MASK); ++ h->flags2 = 0; ++ h->rssi = 0; ++ BDC_SET_IF_IDX(h, ifidx); ++} ++ ++int brcmf_proto_hdrpull(struct brcmf_pub *drvr, int *ifidx, ++ struct sk_buff *pktbuf) ++{ ++ struct brcmf_proto_bdc_header *h; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Pop BDC header used to convey priority for buses that don't */ ++ ++ if (pktbuf->len < BDC_HEADER_LEN) { ++ brcmf_dbg(ERROR, "rx data too short (%d < %d)\n", ++ pktbuf->len, BDC_HEADER_LEN); ++ return -EBADE; ++ } ++ ++ h = (struct brcmf_proto_bdc_header *)(pktbuf->data); ++ ++ *ifidx = BDC_GET_IF_IDX(h); ++ if (*ifidx >= BRCMF_MAX_IFS) { ++ brcmf_dbg(ERROR, "rx data ifnum out of range (%d)\n", *ifidx); ++ return -EBADE; ++ } ++ ++ if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) != ++ BDC_PROTO_VER) { ++ brcmf_dbg(ERROR, "%s: non-BDC packet received, flags 0x%x\n", ++ brcmf_ifname(drvr, *ifidx), h->flags); ++ return -EBADE; ++ } ++ ++ if (h->flags & BDC_FLAG_SUM_GOOD) { ++ brcmf_dbg(INFO, "%s: BDC packet received with good rx-csum, flags 0x%x\n", ++ brcmf_ifname(drvr, *ifidx), h->flags); ++ pkt_set_sum_good(pktbuf, true); ++ } ++ ++ pktbuf->priority = h->priority & BDC_PRIORITY_MASK; ++ ++ skb_pull(pktbuf, BDC_HEADER_LEN); ++ ++ return 0; ++} ++ ++int brcmf_proto_attach(struct brcmf_pub *drvr) ++{ ++ struct brcmf_proto *cdc; ++ ++ cdc = kzalloc(sizeof(struct brcmf_proto), GFP_ATOMIC); ++ if (!cdc) ++ goto fail; ++ ++ /* ensure that the msg buf directly follows the cdc msg struct */ ++ if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) { ++ brcmf_dbg(ERROR, "struct brcmf_proto is not correctly defined\n"); ++ goto fail; ++ } ++ ++ drvr->prot = cdc; ++ drvr->hdrlen += BDC_HEADER_LEN; ++ drvr->maxctl = BRCMF_DCMD_MAXLEN + ++ sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN; ++ return 0; ++ ++fail: ++ kfree(cdc); ++ return -ENOMEM; ++} ++ ++/* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */ ++void brcmf_proto_detach(struct brcmf_pub *drvr) ++{ ++ kfree(drvr->prot); ++ drvr->prot = NULL; ++} ++ ++void brcmf_proto_dstats(struct brcmf_pub *drvr) ++{ ++ /* No stats from dongle added yet, copy bus stats */ ++ drvr->dstats.tx_packets = drvr->tx_packets; ++ drvr->dstats.tx_errors = drvr->tx_errors; ++ drvr->dstats.rx_packets = drvr->rx_packets; ++ drvr->dstats.rx_errors = drvr->rx_errors; ++ drvr->dstats.rx_dropped = drvr->rx_dropped; ++ drvr->dstats.multicast = drvr->rx_multicast; ++ return; ++} ++ ++int brcmf_proto_init(struct brcmf_pub *drvr) ++{ ++ int ret = 0; ++ char buf[128]; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ brcmf_os_proto_block(drvr); ++ ++ /* Get the device MAC address */ ++ strcpy(buf, "cur_etheraddr"); ++ ret = brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, ++ buf, sizeof(buf)); ++ if (ret < 0) { ++ brcmf_os_proto_unblock(drvr); ++ return ret; ++ } ++ memcpy(drvr->mac, buf, ETH_ALEN); ++ ++ brcmf_os_proto_unblock(drvr); ++ ++ ret = brcmf_c_preinit_dcmds(drvr); ++ ++ /* Always assumes wl for now */ ++ drvr->iswl = true; ++ ++ return ret; ++} ++ ++void brcmf_proto_stop(struct brcmf_pub *drvr) ++{ ++ /* Nothing to do for CDC */ ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c.orig 2011-11-09 13:46:58.230800821 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c 2011-11-09 13:47:16.981566403 -0500 +@@ -0,0 +1,895 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "dhd.h" ++#include "dhd_bus.h" ++#include "dhd_proto.h" ++#include "dhd_dbg.h" ++ ++#define BRCM_OUI "\x00\x10\x18" ++#define DOT11_OUI_LEN 3 ++#define BCMILCP_BCM_SUBTYPE_EVENT 1 ++#define PKTFILTER_BUF_SIZE 2048 ++#define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */ ++ ++int brcmf_msg_level; ++ ++#define MSGTRACE_VERSION 1 ++ ++#define BRCMF_PKT_FILTER_FIXED_LEN offsetof(struct brcmf_pkt_filter_le, u) ++#define BRCMF_PKT_FILTER_PATTERN_FIXED_LEN \ ++ offsetof(struct brcmf_pkt_filter_pattern_le, mask_and_pattern) ++ ++#ifdef BCMDBG ++static const char brcmf_version[] = ++ "Dongle Host Driver, version " BRCMF_VERSION_STR "\nCompiled on " ++ __DATE__ " at " __TIME__; ++#else ++static const char brcmf_version[] = ++ "Dongle Host Driver, version " BRCMF_VERSION_STR; ++#endif ++ ++/* Message trace header */ ++struct msgtrace_hdr { ++ u8 version; ++ u8 spare; ++ __be16 len; /* Len of the trace */ ++ __be32 seqnum; /* Sequence number of message. Useful ++ * if the messsage has been lost ++ * because of DMA error or a bus reset ++ * (ex: SDIO Func2) ++ */ ++ __be32 discarded_bytes; /* Number of discarded bytes because of ++ trace overflow */ ++ __be32 discarded_printf; /* Number of discarded printf ++ because of trace overflow */ ++} __packed; ++ ++ ++uint ++brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen) ++{ ++ uint len; ++ ++ len = strlen(name) + 1; ++ ++ if ((len + datalen) > buflen) ++ return 0; ++ ++ strncpy(buf, name, buflen); ++ ++ /* append data onto the end of the name string */ ++ memcpy(&buf[len], data, datalen); ++ len += datalen; ++ ++ return len; ++} ++ ++void brcmf_c_init(void) ++{ ++ /* Init global variables at run-time, not as part of the declaration. ++ * This is required to support init/de-init of the driver. ++ * Initialization ++ * of globals as part of the declaration results in non-deterministic ++ * behaviour since the value of the globals may be different on the ++ * first time that the driver is initialized vs subsequent ++ * initializations. ++ */ ++ brcmf_msg_level = BRCMF_ERROR_VAL; ++} ++ ++bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q, ++ struct sk_buff *pkt, int prec) ++{ ++ struct sk_buff *p; ++ int eprec = -1; /* precedence to evict from */ ++ bool discard_oldest; ++ ++ /* Fast case, precedence queue is not full and we are also not ++ * exceeding total queue length ++ */ ++ if (!pktq_pfull(q, prec) && !pktq_full(q)) { ++ brcmu_pktq_penq(q, prec, pkt); ++ return true; ++ } ++ ++ /* Determine precedence from which to evict packet, if any */ ++ if (pktq_pfull(q, prec)) ++ eprec = prec; ++ else if (pktq_full(q)) { ++ p = brcmu_pktq_peek_tail(q, &eprec); ++ if (eprec > prec) ++ return false; ++ } ++ ++ /* Evict if needed */ ++ if (eprec >= 0) { ++ /* Detect queueing to unconfigured precedence */ ++ discard_oldest = ac_bitmap_tst(drvr->wme_dp, eprec); ++ if (eprec == prec && !discard_oldest) ++ return false; /* refuse newer (incoming) packet */ ++ /* Evict packet according to discard policy */ ++ p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) : ++ brcmu_pktq_pdeq_tail(q, eprec); ++ if (p == NULL) ++ brcmf_dbg(ERROR, "brcmu_pktq_penq() failed, oldest %d\n", ++ discard_oldest); ++ ++ brcmu_pkt_buf_free_skb(p); ++ } ++ ++ /* Enqueue */ ++ p = brcmu_pktq_penq(q, prec, pkt); ++ if (p == NULL) ++ brcmf_dbg(ERROR, "brcmu_pktq_penq() failed\n"); ++ ++ return p != NULL; ++} ++ ++#ifdef BCMDBG ++static void ++brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data) ++{ ++ uint i, status, reason; ++ bool group = false, flush_txq = false, link = false; ++ char *auth_str, *event_name; ++ unsigned char *buf; ++ char err_msg[256], eabuf[ETHER_ADDR_STR_LEN]; ++ static struct { ++ uint event; ++ char *event_name; ++ } event_names[] = { ++ { ++ BRCMF_E_SET_SSID, "SET_SSID"}, { ++ BRCMF_E_JOIN, "JOIN"}, { ++ BRCMF_E_START, "START"}, { ++ BRCMF_E_AUTH, "AUTH"}, { ++ BRCMF_E_AUTH_IND, "AUTH_IND"}, { ++ BRCMF_E_DEAUTH, "DEAUTH"}, { ++ BRCMF_E_DEAUTH_IND, "DEAUTH_IND"}, { ++ BRCMF_E_ASSOC, "ASSOC"}, { ++ BRCMF_E_ASSOC_IND, "ASSOC_IND"}, { ++ BRCMF_E_REASSOC, "REASSOC"}, { ++ BRCMF_E_REASSOC_IND, "REASSOC_IND"}, { ++ BRCMF_E_DISASSOC, "DISASSOC"}, { ++ BRCMF_E_DISASSOC_IND, "DISASSOC_IND"}, { ++ BRCMF_E_QUIET_START, "START_QUIET"}, { ++ BRCMF_E_QUIET_END, "END_QUIET"}, { ++ BRCMF_E_BEACON_RX, "BEACON_RX"}, { ++ BRCMF_E_LINK, "LINK"}, { ++ BRCMF_E_MIC_ERROR, "MIC_ERROR"}, { ++ BRCMF_E_NDIS_LINK, "NDIS_LINK"}, { ++ BRCMF_E_ROAM, "ROAM"}, { ++ BRCMF_E_TXFAIL, "TXFAIL"}, { ++ BRCMF_E_PMKID_CACHE, "PMKID_CACHE"}, { ++ BRCMF_E_RETROGRADE_TSF, "RETROGRADE_TSF"}, { ++ BRCMF_E_PRUNE, "PRUNE"}, { ++ BRCMF_E_AUTOAUTH, "AUTOAUTH"}, { ++ BRCMF_E_EAPOL_MSG, "EAPOL_MSG"}, { ++ BRCMF_E_SCAN_COMPLETE, "SCAN_COMPLETE"}, { ++ BRCMF_E_ADDTS_IND, "ADDTS_IND"}, { ++ BRCMF_E_DELTS_IND, "DELTS_IND"}, { ++ BRCMF_E_BCNSENT_IND, "BCNSENT_IND"}, { ++ BRCMF_E_BCNRX_MSG, "BCNRX_MSG"}, { ++ BRCMF_E_BCNLOST_MSG, "BCNLOST_MSG"}, { ++ BRCMF_E_ROAM_PREP, "ROAM_PREP"}, { ++ BRCMF_E_PFN_NET_FOUND, "PNO_NET_FOUND"}, { ++ BRCMF_E_PFN_NET_LOST, "PNO_NET_LOST"}, { ++ BRCMF_E_RESET_COMPLETE, "RESET_COMPLETE"}, { ++ BRCMF_E_JOIN_START, "JOIN_START"}, { ++ BRCMF_E_ROAM_START, "ROAM_START"}, { ++ BRCMF_E_ASSOC_START, "ASSOC_START"}, { ++ BRCMF_E_IBSS_ASSOC, "IBSS_ASSOC"}, { ++ BRCMF_E_RADIO, "RADIO"}, { ++ BRCMF_E_PSM_WATCHDOG, "PSM_WATCHDOG"}, { ++ BRCMF_E_PROBREQ_MSG, "PROBREQ_MSG"}, { ++ BRCMF_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND"}, { ++ BRCMF_E_PSK_SUP, "PSK_SUP"}, { ++ BRCMF_E_COUNTRY_CODE_CHANGED, "COUNTRY_CODE_CHANGED"}, { ++ BRCMF_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME"}, { ++ BRCMF_E_ICV_ERROR, "ICV_ERROR"}, { ++ BRCMF_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR"}, { ++ BRCMF_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR"}, { ++ BRCMF_E_TRACE, "TRACE"}, { ++ BRCMF_E_ACTION_FRAME, "ACTION FRAME"}, { ++ BRCMF_E_ACTION_FRAME_COMPLETE, "ACTION FRAME TX COMPLETE"}, { ++ BRCMF_E_IF, "IF"}, { ++ BRCMF_E_RSSI, "RSSI"}, { ++ BRCMF_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"} ++ }; ++ uint event_type, flags, auth_type, datalen; ++ static u32 seqnum_prev; ++ struct msgtrace_hdr hdr; ++ u32 nblost; ++ char *s, *p; ++ ++ event_type = be32_to_cpu(event->event_type); ++ flags = be16_to_cpu(event->flags); ++ status = be32_to_cpu(event->status); ++ reason = be32_to_cpu(event->reason); ++ auth_type = be32_to_cpu(event->auth_type); ++ datalen = be32_to_cpu(event->datalen); ++ /* debug dump of event messages */ ++ sprintf(eabuf, "%pM", event->addr); ++ ++ event_name = "UNKNOWN"; ++ for (i = 0; i < ARRAY_SIZE(event_names); i++) { ++ if (event_names[i].event == event_type) ++ event_name = event_names[i].event_name; ++ } ++ ++ brcmf_dbg(EVENT, "EVENT: %s, event ID = %d\n", event_name, event_type); ++ brcmf_dbg(EVENT, "flags 0x%04x, status %d, reason %d, auth_type %d MAC %s\n", ++ flags, status, reason, auth_type, eabuf); ++ ++ if (flags & BRCMF_EVENT_MSG_LINK) ++ link = true; ++ if (flags & BRCMF_EVENT_MSG_GROUP) ++ group = true; ++ if (flags & BRCMF_EVENT_MSG_FLUSHTXQ) ++ flush_txq = true; ++ ++ switch (event_type) { ++ case BRCMF_E_START: ++ case BRCMF_E_DEAUTH: ++ case BRCMF_E_DISASSOC: ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf); ++ break; ++ ++ case BRCMF_E_ASSOC_IND: ++ case BRCMF_E_REASSOC_IND: ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf); ++ break; ++ ++ case BRCMF_E_ASSOC: ++ case BRCMF_E_REASSOC: ++ if (status == BRCMF_E_STATUS_SUCCESS) ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, SUCCESS\n", ++ event_name, eabuf); ++ else if (status == BRCMF_E_STATUS_TIMEOUT) ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, TIMEOUT\n", ++ event_name, eabuf); ++ else if (status == BRCMF_E_STATUS_FAIL) ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, FAILURE, reason %d\n", ++ event_name, eabuf, (int)reason); ++ else ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, unexpected status %d\n", ++ event_name, eabuf, (int)status); ++ break; ++ ++ case BRCMF_E_DEAUTH_IND: ++ case BRCMF_E_DISASSOC_IND: ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, reason %d\n", ++ event_name, eabuf, (int)reason); ++ break; ++ ++ case BRCMF_E_AUTH: ++ case BRCMF_E_AUTH_IND: ++ if (auth_type == WLAN_AUTH_OPEN) ++ auth_str = "Open System"; ++ else if (auth_type == WLAN_AUTH_SHARED_KEY) ++ auth_str = "Shared Key"; ++ else { ++ sprintf(err_msg, "AUTH unknown: %d", (int)auth_type); ++ auth_str = err_msg; ++ } ++ if (event_type == BRCMF_E_AUTH_IND) ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s\n", ++ event_name, eabuf, auth_str); ++ else if (status == BRCMF_E_STATUS_SUCCESS) ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, SUCCESS\n", ++ event_name, eabuf, auth_str); ++ else if (status == BRCMF_E_STATUS_TIMEOUT) ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, TIMEOUT\n", ++ event_name, eabuf, auth_str); ++ else if (status == BRCMF_E_STATUS_FAIL) { ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, %s, FAILURE, reason %d\n", ++ event_name, eabuf, auth_str, (int)reason); ++ } ++ ++ break; ++ ++ case BRCMF_E_JOIN: ++ case BRCMF_E_ROAM: ++ case BRCMF_E_SET_SSID: ++ if (status == BRCMF_E_STATUS_SUCCESS) ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", ++ event_name, eabuf); ++ else if (status == BRCMF_E_STATUS_FAIL) ++ brcmf_dbg(EVENT, "MACEVENT: %s, failed\n", event_name); ++ else if (status == BRCMF_E_STATUS_NO_NETWORKS) ++ brcmf_dbg(EVENT, "MACEVENT: %s, no networks found\n", ++ event_name); ++ else ++ brcmf_dbg(EVENT, "MACEVENT: %s, unexpected status %d\n", ++ event_name, (int)status); ++ break; ++ ++ case BRCMF_E_BEACON_RX: ++ if (status == BRCMF_E_STATUS_SUCCESS) ++ brcmf_dbg(EVENT, "MACEVENT: %s, SUCCESS\n", event_name); ++ else if (status == BRCMF_E_STATUS_FAIL) ++ brcmf_dbg(EVENT, "MACEVENT: %s, FAIL\n", event_name); ++ else ++ brcmf_dbg(EVENT, "MACEVENT: %s, status %d\n", ++ event_name, status); ++ break; ++ ++ case BRCMF_E_LINK: ++ brcmf_dbg(EVENT, "MACEVENT: %s %s\n", ++ event_name, link ? "UP" : "DOWN"); ++ break; ++ ++ case BRCMF_E_MIC_ERROR: ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s, Group %d, Flush %d\n", ++ event_name, eabuf, group, flush_txq); ++ break; ++ ++ case BRCMF_E_ICV_ERROR: ++ case BRCMF_E_UNICAST_DECODE_ERROR: ++ case BRCMF_E_MULTICAST_DECODE_ERROR: ++ brcmf_dbg(EVENT, "MACEVENT: %s, MAC %s\n", event_name, eabuf); ++ break; ++ ++ case BRCMF_E_TXFAIL: ++ brcmf_dbg(EVENT, "MACEVENT: %s, RA %s\n", event_name, eabuf); ++ break; ++ ++ case BRCMF_E_SCAN_COMPLETE: ++ case BRCMF_E_PMKID_CACHE: ++ brcmf_dbg(EVENT, "MACEVENT: %s\n", event_name); ++ break; ++ ++ case BRCMF_E_PFN_NET_FOUND: ++ case BRCMF_E_PFN_NET_LOST: ++ case BRCMF_E_PFN_SCAN_COMPLETE: ++ brcmf_dbg(EVENT, "PNOEVENT: %s\n", event_name); ++ break; ++ ++ case BRCMF_E_PSK_SUP: ++ case BRCMF_E_PRUNE: ++ brcmf_dbg(EVENT, "MACEVENT: %s, status %d, reason %d\n", ++ event_name, (int)status, (int)reason); ++ break; ++ ++ case BRCMF_E_TRACE: ++ buf = (unsigned char *) event_data; ++ memcpy(&hdr, buf, sizeof(struct msgtrace_hdr)); ++ ++ if (hdr.version != MSGTRACE_VERSION) { ++ brcmf_dbg(ERROR, ++ "MACEVENT: %s [unsupported version --> brcmf" ++ " version:%d dongle version:%d]\n", ++ event_name, MSGTRACE_VERSION, hdr.version); ++ /* Reset datalen to avoid display below */ ++ datalen = 0; ++ break; ++ } ++ ++ /* There are 2 bytes available at the end of data */ ++ *(buf + sizeof(struct msgtrace_hdr) ++ + be16_to_cpu(hdr.len)) = '\0'; ++ ++ if (be32_to_cpu(hdr.discarded_bytes) ++ || be32_to_cpu(hdr.discarded_printf)) ++ brcmf_dbg(ERROR, ++ "WLC_E_TRACE: [Discarded traces in dongle -->" ++ " discarded_bytes %d discarded_printf %d]\n", ++ be32_to_cpu(hdr.discarded_bytes), ++ be32_to_cpu(hdr.discarded_printf)); ++ ++ nblost = be32_to_cpu(hdr.seqnum) - seqnum_prev - 1; ++ if (nblost > 0) ++ brcmf_dbg(ERROR, "WLC_E_TRACE: [Event lost --> seqnum " ++ " %d nblost %d\n", be32_to_cpu(hdr.seqnum), ++ nblost); ++ seqnum_prev = be32_to_cpu(hdr.seqnum); ++ ++ /* Display the trace buffer. Advance from \n to \n to ++ * avoid display big ++ * printf (issue with Linux printk ) ++ */ ++ p = (char *)&buf[sizeof(struct msgtrace_hdr)]; ++ while ((s = strstr(p, "\n")) != NULL) { ++ *s = '\0'; ++ printk(KERN_DEBUG"%s\n", p); ++ p = s + 1; ++ } ++ printk(KERN_DEBUG "%s\n", p); ++ ++ /* Reset datalen to avoid display below */ ++ datalen = 0; ++ break; ++ ++ case BRCMF_E_RSSI: ++ brcmf_dbg(EVENT, "MACEVENT: %s %d\n", ++ event_name, be32_to_cpu(*((__be32 *)event_data))); ++ break; ++ ++ default: ++ brcmf_dbg(EVENT, ++ "MACEVENT: %s %d, MAC %s, status %d, reason %d, " ++ "auth %d\n", event_name, event_type, eabuf, ++ (int)status, (int)reason, (int)auth_type); ++ break; ++ } ++ ++ /* show any appended data */ ++ if (datalen) { ++ buf = (unsigned char *) event_data; ++ brcmf_dbg(EVENT, " data (%d) : ", datalen); ++ for (i = 0; i < datalen; i++) ++ brcmf_dbg(EVENT, " 0x%02x ", *buf++); ++ brcmf_dbg(EVENT, "\n"); ++ } ++} ++#endif /* BCMDBG */ ++ ++int ++brcmf_c_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata, ++ struct brcmf_event_msg *event, void **data_ptr) ++{ ++ /* check whether packet is a BRCM event pkt */ ++ struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata; ++ struct brcmf_if_event *ifevent; ++ char *event_data; ++ u32 type, status; ++ u16 flags; ++ int evlen; ++ ++ if (memcmp(BRCM_OUI, &pvt_data->hdr.oui[0], DOT11_OUI_LEN)) { ++ brcmf_dbg(ERROR, "mismatched OUI, bailing\n"); ++ return -EBADE; ++ } ++ ++ /* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */ ++ if (get_unaligned_be16(&pvt_data->hdr.usr_subtype) != ++ BCMILCP_BCM_SUBTYPE_EVENT) { ++ brcmf_dbg(ERROR, "mismatched subtype, bailing\n"); ++ return -EBADE; ++ } ++ ++ *data_ptr = &pvt_data[1]; ++ event_data = *data_ptr; ++ ++ /* memcpy since BRCM event pkt may be unaligned. */ ++ memcpy(event, &pvt_data->msg, sizeof(struct brcmf_event_msg)); ++ ++ type = get_unaligned_be32(&event->event_type); ++ flags = get_unaligned_be16(&event->flags); ++ status = get_unaligned_be32(&event->status); ++ evlen = get_unaligned_be32(&event->datalen) + ++ sizeof(struct brcmf_event); ++ ++ switch (type) { ++ case BRCMF_E_IF: ++ ifevent = (struct brcmf_if_event *) event_data; ++ brcmf_dbg(TRACE, "if event\n"); ++ ++ if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) { ++ if (ifevent->action == BRCMF_E_IF_ADD) ++ brcmf_add_if(drvr_priv, ifevent->ifidx, NULL, ++ event->ifname, ++ pvt_data->eth.h_dest, ++ ifevent->flags, ifevent->bssidx); ++ else ++ brcmf_del_if(drvr_priv, ifevent->ifidx); ++ } else { ++ brcmf_dbg(ERROR, "Invalid ifidx %d for %s\n", ++ ifevent->ifidx, event->ifname); ++ } ++ ++ /* send up the if event: btamp user needs it */ ++ *ifidx = brcmf_ifname2idx(drvr_priv, event->ifname); ++ break; ++ ++ /* These are what external supplicant/authenticator wants */ ++ case BRCMF_E_LINK: ++ case BRCMF_E_ASSOC_IND: ++ case BRCMF_E_REASSOC_IND: ++ case BRCMF_E_DISASSOC_IND: ++ case BRCMF_E_MIC_ERROR: ++ default: ++ /* Fall through: this should get _everything_ */ ++ ++ *ifidx = brcmf_ifname2idx(drvr_priv, event->ifname); ++ brcmf_dbg(TRACE, "MAC event %d, flags %x, status %x\n", ++ type, flags, status); ++ ++ /* put it back to BRCMF_E_NDIS_LINK */ ++ if (type == BRCMF_E_NDIS_LINK) { ++ u32 temp1; ++ __be32 temp2; ++ ++ temp1 = get_unaligned_be32(&event->event_type); ++ brcmf_dbg(TRACE, "Converted to WLC_E_LINK type %d\n", ++ temp1); ++ ++ temp2 = cpu_to_be32(BRCMF_E_NDIS_LINK); ++ memcpy((void *)(&pvt_data->msg.event_type), &temp2, ++ sizeof(pvt_data->msg.event_type)); ++ } ++ break; ++ } ++ ++#ifdef BCMDBG ++ brcmf_c_show_host_event(event, event_data); ++#endif /* BCMDBG */ ++ ++ return 0; ++} ++ ++/* Convert user's input in hex pattern to byte-size mask */ ++static int brcmf_c_pattern_atoh(char *src, char *dst) ++{ ++ int i; ++ if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) { ++ brcmf_dbg(ERROR, "Mask invalid format. Needs to start with 0x\n"); ++ return -EINVAL; ++ } ++ src = src + 2; /* Skip past 0x */ ++ if (strlen(src) % 2 != 0) { ++ brcmf_dbg(ERROR, "Mask invalid format. Length must be even.\n"); ++ return -EINVAL; ++ } ++ for (i = 0; *src != '\0'; i++) { ++ unsigned long res; ++ char num[3]; ++ strncpy(num, src, 2); ++ num[2] = '\0'; ++ if (kstrtoul(num, 16, &res)) ++ return -EINVAL; ++ dst[i] = (u8)res; ++ src += 2; ++ } ++ return i; ++} ++ ++void ++brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable, ++ int master_mode) ++{ ++ unsigned long res; ++ char *argv[8]; ++ int i = 0; ++ const char *str; ++ int buf_len; ++ int str_len; ++ char *arg_save = NULL, *arg_org = NULL; ++ int rc; ++ char buf[128]; ++ struct brcmf_pkt_filter_enable_le enable_parm; ++ struct brcmf_pkt_filter_enable_le *pkt_filterp; ++ __le32 mmode_le; ++ ++ arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC); ++ if (!arg_save) ++ goto fail; ++ ++ arg_org = arg_save; ++ memcpy(arg_save, arg, strlen(arg) + 1); ++ ++ argv[i] = strsep(&arg_save, " "); ++ ++ i = 0; ++ if (NULL == argv[i]) { ++ brcmf_dbg(ERROR, "No args provided\n"); ++ goto fail; ++ } ++ ++ str = "pkt_filter_enable"; ++ str_len = strlen(str); ++ strncpy(buf, str, str_len); ++ buf[str_len] = '\0'; ++ buf_len = str_len + 1; ++ ++ pkt_filterp = (struct brcmf_pkt_filter_enable_le *) (buf + str_len + 1); ++ ++ /* Parse packet filter id. */ ++ enable_parm.id = 0; ++ if (!kstrtoul(argv[i], 0, &res)) ++ enable_parm.id = cpu_to_le32((u32)res); ++ ++ /* Parse enable/disable value. */ ++ enable_parm.enable = cpu_to_le32(enable); ++ ++ buf_len += sizeof(enable_parm); ++ memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm)); ++ ++ /* Enable/disable the specified filter. */ ++ rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len); ++ rc = rc >= 0 ? 0 : rc; ++ if (rc) ++ brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n", ++ arg, rc); ++ else ++ brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg); ++ ++ /* Contorl the master mode */ ++ mmode_le = cpu_to_le32(master_mode); ++ brcmf_c_mkiovar("pkt_filter_mode", (char *)&mmode_le, 4, buf, ++ sizeof(buf)); ++ rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, ++ sizeof(buf)); ++ rc = rc >= 0 ? 0 : rc; ++ if (rc) ++ brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n", ++ arg, rc); ++ ++fail: ++ kfree(arg_org); ++} ++ ++void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg) ++{ ++ const char *str; ++ struct brcmf_pkt_filter_le pkt_filter; ++ struct brcmf_pkt_filter_le *pkt_filterp; ++ unsigned long res; ++ int buf_len; ++ int str_len; ++ int rc; ++ u32 mask_size; ++ u32 pattern_size; ++ char *argv[8], *buf = NULL; ++ int i = 0; ++ char *arg_save = NULL, *arg_org = NULL; ++ ++ arg_save = kstrdup(arg, GFP_ATOMIC); ++ if (!arg_save) ++ goto fail; ++ ++ arg_org = arg_save; ++ ++ buf = kmalloc(PKTFILTER_BUF_SIZE, GFP_ATOMIC); ++ if (!buf) ++ goto fail; ++ ++ argv[i] = strsep(&arg_save, " "); ++ while (argv[i++]) ++ argv[i] = strsep(&arg_save, " "); ++ ++ i = 0; ++ if (NULL == argv[i]) { ++ brcmf_dbg(ERROR, "No args provided\n"); ++ goto fail; ++ } ++ ++ str = "pkt_filter_add"; ++ strcpy(buf, str); ++ str_len = strlen(str); ++ buf_len = str_len + 1; ++ ++ pkt_filterp = (struct brcmf_pkt_filter_le *) (buf + str_len + 1); ++ ++ /* Parse packet filter id. */ ++ pkt_filter.id = 0; ++ if (!kstrtoul(argv[i], 0, &res)) ++ pkt_filter.id = cpu_to_le32((u32)res); ++ ++ if (NULL == argv[++i]) { ++ brcmf_dbg(ERROR, "Polarity not provided\n"); ++ goto fail; ++ } ++ ++ /* Parse filter polarity. */ ++ pkt_filter.negate_match = 0; ++ if (!kstrtoul(argv[i], 0, &res)) ++ pkt_filter.negate_match = cpu_to_le32((u32)res); ++ ++ if (NULL == argv[++i]) { ++ brcmf_dbg(ERROR, "Filter type not provided\n"); ++ goto fail; ++ } ++ ++ /* Parse filter type. */ ++ pkt_filter.type = 0; ++ if (!kstrtoul(argv[i], 0, &res)) ++ pkt_filter.type = cpu_to_le32((u32)res); ++ ++ if (NULL == argv[++i]) { ++ brcmf_dbg(ERROR, "Offset not provided\n"); ++ goto fail; ++ } ++ ++ /* Parse pattern filter offset. */ ++ pkt_filter.u.pattern.offset = 0; ++ if (!kstrtoul(argv[i], 0, &res)) ++ pkt_filter.u.pattern.offset = cpu_to_le32((u32)res); ++ ++ if (NULL == argv[++i]) { ++ brcmf_dbg(ERROR, "Bitmask not provided\n"); ++ goto fail; ++ } ++ ++ /* Parse pattern filter mask. */ ++ mask_size = ++ brcmf_c_pattern_atoh ++ (argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern); ++ ++ if (NULL == argv[++i]) { ++ brcmf_dbg(ERROR, "Pattern not provided\n"); ++ goto fail; ++ } ++ ++ /* Parse pattern filter pattern. */ ++ pattern_size = ++ brcmf_c_pattern_atoh(argv[i], ++ (char *)&pkt_filterp->u.pattern. ++ mask_and_pattern[mask_size]); ++ ++ if (mask_size != pattern_size) { ++ brcmf_dbg(ERROR, "Mask and pattern not the same size\n"); ++ goto fail; ++ } ++ ++ pkt_filter.u.pattern.size_bytes = cpu_to_le32(mask_size); ++ buf_len += BRCMF_PKT_FILTER_FIXED_LEN; ++ buf_len += (BRCMF_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size); ++ ++ /* Keep-alive attributes are set in local ++ * variable (keep_alive_pkt), and ++ ** then memcpy'ed into buffer (keep_alive_pktp) since there is no ++ ** guarantee that the buffer is properly aligned. ++ */ ++ memcpy((char *)pkt_filterp, ++ &pkt_filter, ++ BRCMF_PKT_FILTER_FIXED_LEN + BRCMF_PKT_FILTER_PATTERN_FIXED_LEN); ++ ++ rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len); ++ rc = rc >= 0 ? 0 : rc; ++ ++ if (rc) ++ brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n", ++ arg, rc); ++ else ++ brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg); ++ ++fail: ++ kfree(arg_org); ++ ++ kfree(buf); ++} ++ ++static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode) ++{ ++ char iovbuf[32]; ++ int retcode; ++ ++ brcmf_c_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf)); ++ retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, ++ iovbuf, sizeof(iovbuf)); ++ retcode = retcode >= 0 ? 0 : retcode; ++ if (retcode) ++ brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, retcode = %d\n", ++ arp_mode, retcode); ++ else ++ brcmf_dbg(TRACE, "successfully set ARP offload mode to 0x%x\n", ++ arp_mode); ++} ++ ++static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable) ++{ ++ char iovbuf[32]; ++ int retcode; ++ ++ brcmf_c_mkiovar("arpoe", (char *)&arp_enable, 4, ++ iovbuf, sizeof(iovbuf)); ++ retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, ++ iovbuf, sizeof(iovbuf)); ++ retcode = retcode >= 0 ? 0 : retcode; ++ if (retcode) ++ brcmf_dbg(TRACE, "failed to enable ARP offload to %d, retcode = %d\n", ++ arp_enable, retcode); ++ else ++ brcmf_dbg(TRACE, "successfully enabled ARP offload to %d\n", ++ arp_enable); ++} ++ ++int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) ++{ ++ char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for ++ "event_msgs" + '\0' + bitvec */ ++ uint up = 0; ++ char buf[128], *ptr; ++ u32 dongle_align = BRCMF_SDALIGN; ++ u32 glom = 0; ++ u32 roaming = 1; ++ uint bcn_timeout = 3; ++ int scan_assoc_time = 40; ++ int scan_unassoc_time = 40; ++ int i; ++ ++ brcmf_os_proto_block(drvr); ++ ++ /* Set Country code */ ++ if (drvr->country_code[0] != 0) { ++ if (brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_COUNTRY, ++ drvr->country_code, ++ sizeof(drvr->country_code)) < 0) ++ brcmf_dbg(ERROR, "country code setting failed\n"); ++ } ++ ++ /* query for 'ver' to get version info from firmware */ ++ memset(buf, 0, sizeof(buf)); ++ ptr = buf; ++ brcmf_c_mkiovar("ver", NULL, 0, buf, sizeof(buf)); ++ brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, buf, sizeof(buf)); ++ strsep(&ptr, "\n"); ++ /* Print fw version info */ ++ brcmf_dbg(ERROR, "Firmware version = %s\n", buf); ++ ++ /* Match Host and Dongle rx alignment */ ++ brcmf_c_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, ++ sizeof(iovbuf)); ++ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, ++ sizeof(iovbuf)); ++ ++ /* disable glom option per default */ ++ brcmf_c_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); ++ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, ++ sizeof(iovbuf)); ++ ++ /* Setup timeout if Beacons are lost and roam is off to report ++ link down */ ++ brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, ++ sizeof(iovbuf)); ++ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, ++ sizeof(iovbuf)); ++ ++ /* Enable/Disable build-in roaming to allowed ext supplicant to take ++ of romaing */ ++ brcmf_c_mkiovar("roam_off", (char *)&roaming, 4, ++ iovbuf, sizeof(iovbuf)); ++ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, ++ sizeof(iovbuf)); ++ ++ /* Force STA UP */ ++ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_UP, (char *)&up, sizeof(up)); ++ ++ /* Setup event_msgs */ ++ brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN, ++ iovbuf, sizeof(iovbuf)); ++ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, ++ sizeof(iovbuf)); ++ ++ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME, ++ (char *)&scan_assoc_time, sizeof(scan_assoc_time)); ++ brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME, ++ (char *)&scan_unassoc_time, sizeof(scan_unassoc_time)); ++ ++ /* Set and enable ARP offload feature */ ++ brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE); ++ brcmf_c_arp_offload_enable(drvr, true); ++ ++ /* Set up pkt filter */ ++ for (i = 0; i < drvr->pktfilter_count; i++) { ++ brcmf_c_pktfilter_offload_set(drvr, drvr->pktfilter[i]); ++ brcmf_c_pktfilter_offload_enable(drvr, drvr->pktfilter[i], ++ 0, true); ++ } ++ ++ brcmf_os_proto_unblock(drvr); ++ ++ return 0; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h.orig 2011-11-09 13:46:58.231800808 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h 2011-11-09 13:47:16.981566403 -0500 +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCMF_DBG_H_ ++#define _BRCMF_DBG_H_ ++ ++#if defined(BCMDBG) ++ ++#define brcmf_dbg(level, fmt, ...) \ ++do { \ ++ if (BRCMF_ERROR_VAL == BRCMF_##level##_VAL) { \ ++ if (brcmf_msg_level & BRCMF_##level##_VAL) { \ ++ if (net_ratelimit()) \ ++ printk(KERN_DEBUG "%s: " fmt, \ ++ __func__, ##__VA_ARGS__); \ ++ } \ ++ } else { \ ++ if (brcmf_msg_level & BRCMF_##level##_VAL) { \ ++ printk(KERN_DEBUG "%s: " fmt, \ ++ __func__, ##__VA_ARGS__); \ ++ } \ ++ } \ ++} while (0) ++ ++#define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL) ++#define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL) ++#define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL) ++#define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL) ++#define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL) ++ ++#else /* (defined BCMDBG) || (defined BCMDBG) */ ++ ++#define brcmf_dbg(level, fmt, ...) no_printk(fmt, ##__VA_ARGS__) ++ ++#define BRCMF_DATA_ON() 0 ++#define BRCMF_CTL_ON() 0 ++#define BRCMF_HDRS_ON() 0 ++#define BRCMF_BYTES_ON() 0 ++#define BRCMF_GLOM_ON() 0 ++ ++#endif /* defined(BCMDBG) */ ++ ++extern int brcmf_msg_level; ++ ++#endif /* _BRCMF_DBG_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd.h.orig 2011-11-09 13:46:58.231800808 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd.h 2011-11-09 13:47:16.982566390 -0500 +@@ -0,0 +1,776 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/**************** ++ * Common types * ++ */ ++ ++#ifndef _BRCMF_H_ ++#define _BRCMF_H_ ++ ++#define BRCMF_VERSION_STR "4.218.248.5" ++ ++/******************************************************************************* ++ * IO codes that are interpreted by dongle firmware ++ ******************************************************************************/ ++#define BRCMF_C_UP 2 ++#define BRCMF_C_SET_PROMISC 10 ++#define BRCMF_C_GET_RATE 12 ++#define BRCMF_C_GET_INFRA 19 ++#define BRCMF_C_SET_INFRA 20 ++#define BRCMF_C_GET_AUTH 21 ++#define BRCMF_C_SET_AUTH 22 ++#define BRCMF_C_GET_BSSID 23 ++#define BRCMF_C_GET_SSID 25 ++#define BRCMF_C_SET_SSID 26 ++#define BRCMF_C_GET_CHANNEL 29 ++#define BRCMF_C_GET_SRL 31 ++#define BRCMF_C_GET_LRL 33 ++#define BRCMF_C_GET_RADIO 37 ++#define BRCMF_C_SET_RADIO 38 ++#define BRCMF_C_GET_PHYTYPE 39 ++#define BRCMF_C_SET_KEY 45 ++#define BRCMF_C_SET_PASSIVE_SCAN 49 ++#define BRCMF_C_SCAN 50 ++#define BRCMF_C_SCAN_RESULTS 51 ++#define BRCMF_C_DISASSOC 52 ++#define BRCMF_C_REASSOC 53 ++#define BRCMF_C_SET_ROAM_TRIGGER 55 ++#define BRCMF_C_SET_ROAM_DELTA 57 ++#define BRCMF_C_GET_DTIMPRD 77 ++#define BRCMF_C_SET_COUNTRY 84 ++#define BRCMF_C_GET_PM 85 ++#define BRCMF_C_SET_PM 86 ++#define BRCMF_C_GET_AP 117 ++#define BRCMF_C_SET_AP 118 ++#define BRCMF_C_GET_RSSI 127 ++#define BRCMF_C_GET_WSEC 133 ++#define BRCMF_C_SET_WSEC 134 ++#define BRCMF_C_GET_PHY_NOISE 135 ++#define BRCMF_C_GET_BSS_INFO 136 ++#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 ++#define BRCMF_C_SET_SCAN_UNASSOC_TIME 187 ++#define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201 ++#define BRCMF_C_GET_VALID_CHANNELS 217 ++#define BRCMF_C_GET_KEY_PRIMARY 235 ++#define BRCMF_C_SET_KEY_PRIMARY 236 ++#define BRCMF_C_SET_SCAN_PASSIVE_TIME 258 ++#define BRCMF_C_GET_VAR 262 ++#define BRCMF_C_SET_VAR 263 ++ ++/* phy types (returned by WLC_GET_PHYTPE) */ ++#define WLC_PHY_TYPE_A 0 ++#define WLC_PHY_TYPE_B 1 ++#define WLC_PHY_TYPE_G 2 ++#define WLC_PHY_TYPE_N 4 ++#define WLC_PHY_TYPE_LP 5 ++#define WLC_PHY_TYPE_SSN 6 ++#define WLC_PHY_TYPE_HT 7 ++#define WLC_PHY_TYPE_LCN 8 ++#define WLC_PHY_TYPE_NULL 0xf ++ ++#define BRCMF_EVENTING_MASK_LEN 16 ++ ++#define TOE_TX_CSUM_OL 0x00000001 ++#define TOE_RX_CSUM_OL 0x00000002 ++ ++#define BRCMF_BSS_INFO_VERSION 108 /* current ver of brcmf_bss_info struct */ ++ ++/* size of brcmf_scan_params not including variable length array */ ++#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64 ++ ++/* masks for channel and ssid count */ ++#define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff ++#define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16 ++ ++#define BRCMF_SCAN_ACTION_START 1 ++#define BRCMF_SCAN_ACTION_CONTINUE 2 ++#define WL_SCAN_ACTION_ABORT 3 ++ ++#define BRCMF_ISCAN_REQ_VERSION 1 ++ ++/* brcmf_iscan_results status values */ ++#define BRCMF_SCAN_RESULTS_SUCCESS 0 ++#define BRCMF_SCAN_RESULTS_PARTIAL 1 ++#define BRCMF_SCAN_RESULTS_PENDING 2 ++#define BRCMF_SCAN_RESULTS_ABORTED 3 ++#define BRCMF_SCAN_RESULTS_NO_MEM 4 ++ ++/* Indicates this key is using soft encrypt */ ++#define WL_SOFT_KEY (1 << 0) ++/* primary (ie tx) key */ ++#define BRCMF_PRIMARY_KEY (1 << 1) ++/* Reserved for backward compat */ ++#define WL_KF_RES_4 (1 << 4) ++/* Reserved for backward compat */ ++#define WL_KF_RES_5 (1 << 5) ++/* Indicates a group key for a IBSS PEER */ ++#define WL_IBSS_PEER_GROUP_KEY (1 << 6) ++ ++/* For supporting multiple interfaces */ ++#define BRCMF_MAX_IFS 16 ++#define BRCMF_DEL_IF -0xe ++#define BRCMF_BAD_IF -0xf ++ ++#define DOT11_BSSTYPE_ANY 2 ++#define DOT11_MAX_DEFAULT_KEYS 4 ++ ++#define BRCMF_EVENT_MSG_LINK 0x01 ++#define BRCMF_EVENT_MSG_FLUSHTXQ 0x02 ++#define BRCMF_EVENT_MSG_GROUP 0x04 ++ ++struct brcmf_event_msg { ++ __be16 version; ++ __be16 flags; ++ __be32 event_type; ++ __be32 status; ++ __be32 reason; ++ __be32 auth_type; ++ __be32 datalen; ++ u8 addr[ETH_ALEN]; ++ char ifname[IFNAMSIZ]; ++} __packed; ++ ++struct brcm_ethhdr { ++ u16 subtype; ++ u16 length; ++ u8 version; ++ u8 oui[3]; ++ u16 usr_subtype; ++} __packed; ++ ++struct brcmf_event { ++ struct ethhdr eth; ++ struct brcm_ethhdr hdr; ++ struct brcmf_event_msg msg; ++} __packed; ++ ++struct dngl_stats { ++ unsigned long rx_packets; /* total packets received */ ++ unsigned long tx_packets; /* total packets transmitted */ ++ unsigned long rx_bytes; /* total bytes received */ ++ unsigned long tx_bytes; /* total bytes transmitted */ ++ unsigned long rx_errors; /* bad packets received */ ++ unsigned long tx_errors; /* packet transmit problems */ ++ unsigned long rx_dropped; /* packets dropped by dongle */ ++ unsigned long tx_dropped; /* packets dropped by dongle */ ++ unsigned long multicast; /* multicast packets received */ ++}; ++ ++/* event codes sent by the dongle to this driver */ ++#define BRCMF_E_SET_SSID 0 ++#define BRCMF_E_JOIN 1 ++#define BRCMF_E_START 2 ++#define BRCMF_E_AUTH 3 ++#define BRCMF_E_AUTH_IND 4 ++#define BRCMF_E_DEAUTH 5 ++#define BRCMF_E_DEAUTH_IND 6 ++#define BRCMF_E_ASSOC 7 ++#define BRCMF_E_ASSOC_IND 8 ++#define BRCMF_E_REASSOC 9 ++#define BRCMF_E_REASSOC_IND 10 ++#define BRCMF_E_DISASSOC 11 ++#define BRCMF_E_DISASSOC_IND 12 ++#define BRCMF_E_QUIET_START 13 ++#define BRCMF_E_QUIET_END 14 ++#define BRCMF_E_BEACON_RX 15 ++#define BRCMF_E_LINK 16 ++#define BRCMF_E_MIC_ERROR 17 ++#define BRCMF_E_NDIS_LINK 18 ++#define BRCMF_E_ROAM 19 ++#define BRCMF_E_TXFAIL 20 ++#define BRCMF_E_PMKID_CACHE 21 ++#define BRCMF_E_RETROGRADE_TSF 22 ++#define BRCMF_E_PRUNE 23 ++#define BRCMF_E_AUTOAUTH 24 ++#define BRCMF_E_EAPOL_MSG 25 ++#define BRCMF_E_SCAN_COMPLETE 26 ++#define BRCMF_E_ADDTS_IND 27 ++#define BRCMF_E_DELTS_IND 28 ++#define BRCMF_E_BCNSENT_IND 29 ++#define BRCMF_E_BCNRX_MSG 30 ++#define BRCMF_E_BCNLOST_MSG 31 ++#define BRCMF_E_ROAM_PREP 32 ++#define BRCMF_E_PFN_NET_FOUND 33 ++#define BRCMF_E_PFN_NET_LOST 34 ++#define BRCMF_E_RESET_COMPLETE 35 ++#define BRCMF_E_JOIN_START 36 ++#define BRCMF_E_ROAM_START 37 ++#define BRCMF_E_ASSOC_START 38 ++#define BRCMF_E_IBSS_ASSOC 39 ++#define BRCMF_E_RADIO 40 ++#define BRCMF_E_PSM_WATCHDOG 41 ++#define BRCMF_E_PROBREQ_MSG 44 ++#define BRCMF_E_SCAN_CONFIRM_IND 45 ++#define BRCMF_E_PSK_SUP 46 ++#define BRCMF_E_COUNTRY_CODE_CHANGED 47 ++#define BRCMF_E_EXCEEDED_MEDIUM_TIME 48 ++#define BRCMF_E_ICV_ERROR 49 ++#define BRCMF_E_UNICAST_DECODE_ERROR 50 ++#define BRCMF_E_MULTICAST_DECODE_ERROR 51 ++#define BRCMF_E_TRACE 52 ++#define BRCMF_E_IF 54 ++#define BRCMF_E_RSSI 56 ++#define BRCMF_E_PFN_SCAN_COMPLETE 57 ++#define BRCMF_E_EXTLOG_MSG 58 ++#define BRCMF_E_ACTION_FRAME 59 ++#define BRCMF_E_ACTION_FRAME_COMPLETE 60 ++#define BRCMF_E_PRE_ASSOC_IND 61 ++#define BRCMF_E_PRE_REASSOC_IND 62 ++#define BRCMF_E_CHANNEL_ADOPTED 63 ++#define BRCMF_E_AP_STARTED 64 ++#define BRCMF_E_DFS_AP_STOP 65 ++#define BRCMF_E_DFS_AP_RESUME 66 ++#define BRCMF_E_RESERVED1 67 ++#define BRCMF_E_RESERVED2 68 ++#define BRCMF_E_ESCAN_RESULT 69 ++#define BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70 ++#define BRCMF_E_DCS_REQUEST 73 ++ ++#define BRCMF_E_FIFO_CREDIT_MAP 74 ++ ++#define BRCMF_E_LAST 75 ++ ++#define BRCMF_E_STATUS_SUCCESS 0 ++#define BRCMF_E_STATUS_FAIL 1 ++#define BRCMF_E_STATUS_TIMEOUT 2 ++#define BRCMF_E_STATUS_NO_NETWORKS 3 ++#define BRCMF_E_STATUS_ABORT 4 ++#define BRCMF_E_STATUS_NO_ACK 5 ++#define BRCMF_E_STATUS_UNSOLICITED 6 ++#define BRCMF_E_STATUS_ATTEMPT 7 ++#define BRCMF_E_STATUS_PARTIAL 8 ++#define BRCMF_E_STATUS_NEWSCAN 9 ++#define BRCMF_E_STATUS_NEWASSOC 10 ++#define BRCMF_E_STATUS_11HQUIET 11 ++#define BRCMF_E_STATUS_SUPPRESS 12 ++#define BRCMF_E_STATUS_NOCHANS 13 ++#define BRCMF_E_STATUS_CS_ABORT 15 ++#define BRCMF_E_STATUS_ERROR 16 ++ ++#define BRCMF_E_REASON_INITIAL_ASSOC 0 ++#define BRCMF_E_REASON_LOW_RSSI 1 ++#define BRCMF_E_REASON_DEAUTH 2 ++#define BRCMF_E_REASON_DISASSOC 3 ++#define BRCMF_E_REASON_BCNS_LOST 4 ++#define BRCMF_E_REASON_MINTXRATE 9 ++#define BRCMF_E_REASON_TXFAIL 10 ++ ++#define BRCMF_E_REASON_FAST_ROAM_FAILED 5 ++#define BRCMF_E_REASON_DIRECTED_ROAM 6 ++#define BRCMF_E_REASON_TSPEC_REJECTED 7 ++#define BRCMF_E_REASON_BETTER_AP 8 ++ ++#define BRCMF_E_PRUNE_ENCR_MISMATCH 1 ++#define BRCMF_E_PRUNE_BCAST_BSSID 2 ++#define BRCMF_E_PRUNE_MAC_DENY 3 ++#define BRCMF_E_PRUNE_MAC_NA 4 ++#define BRCMF_E_PRUNE_REG_PASSV 5 ++#define BRCMF_E_PRUNE_SPCT_MGMT 6 ++#define BRCMF_E_PRUNE_RADAR 7 ++#define BRCMF_E_RSN_MISMATCH 8 ++#define BRCMF_E_PRUNE_NO_COMMON_RATES 9 ++#define BRCMF_E_PRUNE_BASIC_RATES 10 ++#define BRCMF_E_PRUNE_CIPHER_NA 12 ++#define BRCMF_E_PRUNE_KNOWN_STA 13 ++#define BRCMF_E_PRUNE_WDS_PEER 15 ++#define BRCMF_E_PRUNE_QBSS_LOAD 16 ++#define BRCMF_E_PRUNE_HOME_AP 17 ++ ++#define BRCMF_E_SUP_OTHER 0 ++#define BRCMF_E_SUP_DECRYPT_KEY_DATA 1 ++#define BRCMF_E_SUP_BAD_UCAST_WEP128 2 ++#define BRCMF_E_SUP_BAD_UCAST_WEP40 3 ++#define BRCMF_E_SUP_UNSUP_KEY_LEN 4 ++#define BRCMF_E_SUP_PW_KEY_CIPHER 5 ++#define BRCMF_E_SUP_MSG3_TOO_MANY_IE 6 ++#define BRCMF_E_SUP_MSG3_IE_MISMATCH 7 ++#define BRCMF_E_SUP_NO_INSTALL_FLAG 8 ++#define BRCMF_E_SUP_MSG3_NO_GTK 9 ++#define BRCMF_E_SUP_GRP_KEY_CIPHER 10 ++#define BRCMF_E_SUP_GRP_MSG1_NO_GTK 11 ++#define BRCMF_E_SUP_GTK_DECRYPT_FAIL 12 ++#define BRCMF_E_SUP_SEND_FAIL 13 ++#define BRCMF_E_SUP_DEAUTH 14 ++ ++#define BRCMF_E_IF_ADD 1 ++#define BRCMF_E_IF_DEL 2 ++#define BRCMF_E_IF_CHANGE 3 ++ ++#define BRCMF_E_IF_ROLE_STA 0 ++#define BRCMF_E_IF_ROLE_AP 1 ++#define BRCMF_E_IF_ROLE_WDS 2 ++ ++#define BRCMF_E_LINK_BCN_LOSS 1 ++#define BRCMF_E_LINK_DISASSOC 2 ++#define BRCMF_E_LINK_ASSOC_REC 3 ++#define BRCMF_E_LINK_BSSCFG_DIS 4 ++ ++/* The level of bus communication with the dongle */ ++enum brcmf_bus_state { ++ BRCMF_BUS_DOWN, /* Not ready for frame transfers */ ++ BRCMF_BUS_LOAD, /* Download access only (CPU reset) */ ++ BRCMF_BUS_DATA /* Ready for frame transfers */ ++}; ++ ++/* Pattern matching filter. Specifies an offset within received packets to ++ * start matching, the pattern to match, the size of the pattern, and a bitmask ++ * that indicates which bits within the pattern should be matched. ++ */ ++struct brcmf_pkt_filter_pattern_le { ++ /* ++ * Offset within received packet to start pattern matching. ++ * Offset '0' is the first byte of the ethernet header. ++ */ ++ __le32 offset; ++ /* Size of the pattern. Bitmask must be the same size.*/ ++ __le32 size_bytes; ++ /* ++ * Variable length mask and pattern data. mask starts at offset 0. ++ * Pattern immediately follows mask. ++ */ ++ u8 mask_and_pattern[1]; ++}; ++ ++/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */ ++struct brcmf_pkt_filter_le { ++ __le32 id; /* Unique filter id, specified by app. */ ++ __le32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */ ++ __le32 negate_match; /* Negate the result of filter matches */ ++ union { /* Filter definitions */ ++ struct brcmf_pkt_filter_pattern_le pattern; /* Filter pattern */ ++ } u; ++}; ++ ++/* IOVAR "pkt_filter_enable" parameter. */ ++struct brcmf_pkt_filter_enable_le { ++ __le32 id; /* Unique filter id */ ++ __le32 enable; /* Enable/disable bool */ ++}; ++ ++/* BSS info structure ++ * Applications MUST CHECK ie_offset field and length field to access IEs and ++ * next bss_info structure in a vector (in struct brcmf_scan_results) ++ */ ++struct brcmf_bss_info { ++ __le32 version; /* version field */ ++ __le32 length; /* byte length of data in this record, ++ * starting at version and including IEs ++ */ ++ u8 BSSID[ETH_ALEN]; ++ __le16 beacon_period; /* units are Kusec */ ++ __le16 capability; /* Capability information */ ++ u8 SSID_len; ++ u8 SSID[32]; ++ struct { ++ __le32 count; /* # rates in this set */ ++ u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ ++ } rateset; /* supported rates */ ++ __le16 chanspec; /* chanspec for bss */ ++ __le16 atim_window; /* units are Kusec */ ++ u8 dtim_period; /* DTIM period */ ++ __le16 RSSI; /* receive signal strength (in dBm) */ ++ s8 phy_noise; /* noise (in dBm) */ ++ ++ u8 n_cap; /* BSS is 802.11N Capable */ ++ /* 802.11N BSS Capabilities (based on HT_CAP_*): */ ++ __le32 nbss_cap; ++ u8 ctl_ch; /* 802.11N BSS control channel number */ ++ __le32 reserved32[1]; /* Reserved for expansion of BSS properties */ ++ u8 flags; /* flags */ ++ u8 reserved[3]; /* Reserved for expansion of BSS properties */ ++ u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ ++ ++ __le16 ie_offset; /* offset at which IEs start, from beginning */ ++ __le32 ie_length; /* byte length of Information Elements */ ++ __le16 SNR; /* average SNR of during frame reception */ ++ /* Add new fields here */ ++ /* variable length Information Elements */ ++}; ++ ++struct brcm_rateset_le { ++ /* # rates in this set */ ++ __le32 count; ++ /* rates in 500kbps units w/hi bit set if basic */ ++ u8 rates[WL_NUMRATES]; ++}; ++ ++struct brcmf_ssid { ++ u32 SSID_len; ++ unsigned char SSID[32]; ++}; ++ ++struct brcmf_ssid_le { ++ __le32 SSID_len; ++ unsigned char SSID[32]; ++}; ++ ++struct brcmf_scan_params_le { ++ struct brcmf_ssid_le ssid_le; /* default: {0, ""} */ ++ u8 bssid[ETH_ALEN]; /* default: bcast */ ++ s8 bss_type; /* default: any, ++ * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT ++ */ ++ u8 scan_type; /* flags, 0 use default */ ++ __le32 nprobes; /* -1 use default, number of probes per channel */ ++ __le32 active_time; /* -1 use default, dwell time per channel for ++ * active scanning ++ */ ++ __le32 passive_time; /* -1 use default, dwell time per channel ++ * for passive scanning ++ */ ++ __le32 home_time; /* -1 use default, dwell time for the ++ * home channel between channel scans ++ */ ++ __le32 channel_num; /* count of channels and ssids that follow ++ * ++ * low half is count of channels in ++ * channel_list, 0 means default (use all ++ * available channels) ++ * ++ * high half is entries in struct brcmf_ssid ++ * array that follows channel_list, aligned for ++ * s32 (4 bytes) meaning an odd channel count ++ * implies a 2-byte pad between end of ++ * channel_list and first ssid ++ * ++ * if ssid count is zero, single ssid in the ++ * fixed parameter portion is assumed, otherwise ++ * ssid in the fixed portion is ignored ++ */ ++ __le16 channel_list[1]; /* list of chanspecs */ ++}; ++ ++/* incremental scan struct */ ++struct brcmf_iscan_params_le { ++ __le32 version; ++ __le16 action; ++ __le16 scan_duration; ++ struct brcmf_scan_params_le params_le; ++}; ++ ++struct brcmf_scan_results { ++ u32 buflen; ++ u32 version; ++ u32 count; ++ struct brcmf_bss_info bss_info[1]; ++}; ++ ++struct brcmf_scan_results_le { ++ __le32 buflen; ++ __le32 version; ++ __le32 count; ++ struct brcmf_bss_info bss_info[1]; ++}; ++ ++/* used for association with a specific BSSID and chanspec list */ ++struct brcmf_assoc_params_le { ++ /* 00:00:00:00:00:00: broadcast scan */ ++ u8 bssid[ETH_ALEN]; ++ /* 0: all available channels, otherwise count of chanspecs in ++ * chanspec_list */ ++ __le32 chanspec_num; ++ /* list of chanspecs */ ++ __le16 chanspec_list[1]; ++}; ++ ++/* used for join with or without a specific bssid and channel list */ ++struct brcmf_join_params { ++ struct brcmf_ssid_le ssid_le; ++ struct brcmf_assoc_params_le params_le; ++}; ++ ++/* size of brcmf_scan_results not including variable length array */ ++#define BRCMF_SCAN_RESULTS_FIXED_SIZE \ ++ (sizeof(struct brcmf_scan_results) - sizeof(struct brcmf_bss_info)) ++ ++/* incremental scan results struct */ ++struct brcmf_iscan_results { ++ union { ++ u32 status; ++ __le32 status_le; ++ }; ++ union { ++ struct brcmf_scan_results results; ++ struct brcmf_scan_results_le results_le; ++ }; ++}; ++ ++/* size of brcmf_iscan_results not including variable length array */ ++#define BRCMF_ISCAN_RESULTS_FIXED_SIZE \ ++ (BRCMF_SCAN_RESULTS_FIXED_SIZE + \ ++ offsetof(struct brcmf_iscan_results, results)) ++ ++struct brcmf_wsec_key { ++ u32 index; /* key index */ ++ u32 len; /* key length */ ++ u8 data[WLAN_MAX_KEY_LEN]; /* key data */ ++ u32 pad_1[18]; ++ u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ ++ u32 flags; /* misc flags */ ++ u32 pad_2[3]; ++ u32 iv_initialized; /* has IV been initialized already? */ ++ u32 pad_3; ++ /* Rx IV */ ++ struct { ++ u32 hi; /* upper 32 bits of IV */ ++ u16 lo; /* lower 16 bits of IV */ ++ } rxiv; ++ u32 pad_4[2]; ++ u8 ea[ETH_ALEN]; /* per station */ ++}; ++ ++/* ++ * dongle requires same struct as above but with fields in little endian order ++ */ ++struct brcmf_wsec_key_le { ++ __le32 index; /* key index */ ++ __le32 len; /* key length */ ++ u8 data[WLAN_MAX_KEY_LEN]; /* key data */ ++ __le32 pad_1[18]; ++ __le32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ ++ __le32 flags; /* misc flags */ ++ __le32 pad_2[3]; ++ __le32 iv_initialized; /* has IV been initialized already? */ ++ __le32 pad_3; ++ /* Rx IV */ ++ struct { ++ __le32 hi; /* upper 32 bits of IV */ ++ __le16 lo; /* lower 16 bits of IV */ ++ } rxiv; ++ __le32 pad_4[2]; ++ u8 ea[ETH_ALEN]; /* per station */ ++}; ++ ++/* Used to get specific STA parameters */ ++struct brcmf_scb_val_le { ++ __le32 val; ++ u8 ea[ETH_ALEN]; ++}; ++ ++/* channel encoding */ ++struct brcmf_channel_info_le { ++ __le32 hw_channel; ++ __le32 target_channel; ++ __le32 scan_channel; ++}; ++ ++/* Bus independent dongle command */ ++struct brcmf_dcmd { ++ uint cmd; /* common dongle cmd definition */ ++ void *buf; /* pointer to user buffer */ ++ uint len; /* length of user buffer */ ++ u8 set; /* get or set request (optional) */ ++ uint used; /* bytes read or written (optional) */ ++ uint needed; /* bytes needed (optional) */ ++}; ++ ++/* Forward decls for struct brcmf_pub (see below) */ ++struct brcmf_bus; /* device bus info */ ++struct brcmf_proto; /* device communication protocol info */ ++struct brcmf_info; /* device driver info */ ++struct brcmf_cfg80211_dev; /* cfg80211 device info */ ++ ++/* Common structure for module and instance linkage */ ++struct brcmf_pub { ++ /* Linkage ponters */ ++ struct brcmf_bus *bus; ++ struct brcmf_proto *prot; ++ struct brcmf_info *info; ++ struct brcmf_cfg80211_dev *config; ++ ++ /* Internal brcmf items */ ++ bool up; /* Driver up/down (to OS) */ ++ bool txoff; /* Transmit flow-controlled */ ++ enum brcmf_bus_state busstate; ++ uint hdrlen; /* Total BRCMF header length (proto + bus) */ ++ uint maxctl; /* Max size rxctl request from proto to bus */ ++ uint rxsz; /* Rx buffer size bus module should use */ ++ u8 wme_dp; /* wme discard priority */ ++ ++ /* Dongle media info */ ++ bool iswl; /* Dongle-resident driver is wl */ ++ unsigned long drv_version; /* Version of dongle-resident driver */ ++ u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */ ++ struct dngl_stats dstats; /* Stats for dongle-based data */ ++ ++ /* Additional stats for the bus level */ ++ ++ /* Data packets sent to dongle */ ++ unsigned long tx_packets; ++ /* Multicast data packets sent to dongle */ ++ unsigned long tx_multicast; ++ /* Errors in sending data to dongle */ ++ unsigned long tx_errors; ++ /* Control packets sent to dongle */ ++ unsigned long tx_ctlpkts; ++ /* Errors sending control frames to dongle */ ++ unsigned long tx_ctlerrs; ++ /* Packets sent up the network interface */ ++ unsigned long rx_packets; ++ /* Multicast packets sent up the network interface */ ++ unsigned long rx_multicast; ++ /* Errors processing rx data packets */ ++ unsigned long rx_errors; ++ /* Control frames processed from dongle */ ++ unsigned long rx_ctlpkts; ++ ++ /* Errors in processing rx control frames */ ++ unsigned long rx_ctlerrs; ++ /* Packets dropped locally (no memory) */ ++ unsigned long rx_dropped; ++ /* Packets flushed due to unscheduled sendup thread */ ++ unsigned long rx_flushed; ++ /* Number of times dpc scheduled by watchdog timer */ ++ unsigned long wd_dpc_sched; ++ ++ /* Number of packets where header read-ahead was used. */ ++ unsigned long rx_readahead_cnt; ++ /* Number of tx packets we had to realloc for headroom */ ++ unsigned long tx_realloc; ++ /* Number of flow control pkts recvd */ ++ unsigned long fc_packets; ++ ++ /* Last error return */ ++ int bcmerror; ++ uint tickcnt; ++ ++ /* Last error from dongle */ ++ int dongle_error; ++ ++ /* Suspend disable flag flag */ ++ int suspend_disable_flag; /* "1" to disable all extra powersaving ++ during suspend */ ++ int in_suspend; /* flag set to 1 when early suspend called */ ++ int dtim_skip; /* dtim skip , default 0 means wake each dtim */ ++ ++ /* Pkt filter defination */ ++ char *pktfilter[100]; ++ int pktfilter_count; ++ ++ u8 country_code[BRCM_CNTRY_BUF_SZ]; ++ char eventmask[BRCMF_EVENTING_MASK_LEN]; ++ ++}; ++ ++struct brcmf_if_event { ++ u8 ifidx; ++ u8 action; ++ u8 flags; ++ u8 bssidx; ++}; ++ ++struct bcmevent_name { ++ uint event; ++ const char *name; ++}; ++ ++extern const struct bcmevent_name bcmevent_names[]; ++ ++extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen, ++ char *buf, uint len); ++ ++/* Indication from bus module regarding presence/insertion of dongle. ++ * Return struct brcmf_pub pointer, used as handle to OS module in later calls. ++ * Returned structure should have bus and prot pointers filled in. ++ * bus_hdrlen specifies required headroom for bus module header. ++ */ ++extern struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, ++ uint bus_hdrlen); ++extern int brcmf_net_attach(struct brcmf_pub *drvr, int idx); ++extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev); ++ ++extern s32 brcmf_exec_dcmd(struct net_device *dev, u32 cmd, void *arg, u32 len); ++ ++/* Indication from bus module regarding removal/absence of dongle */ ++extern void brcmf_detach(struct brcmf_pub *drvr); ++ ++/* Indication from bus module to change flow-control state */ ++extern void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool on); ++ ++extern bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q, ++ struct sk_buff *pkt, int prec); ++ ++/* Receive frame for delivery to OS. Callee disposes of rxp. */ ++extern void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, ++ struct sk_buff *rxp, int numpkt); ++ ++/* Return pointer to interface name */ ++extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx); ++ ++/* Notify tx completion */ ++extern void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, ++ bool success); ++ ++/* Query dongle */ ++extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, ++ uint cmd, void *buf, uint len); ++ ++/* OS independent layer functions */ ++extern int brcmf_os_proto_block(struct brcmf_pub *drvr); ++extern int brcmf_os_proto_unblock(struct brcmf_pub *drvr); ++#ifdef BCMDBG ++extern int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size); ++#endif /* BCMDBG */ ++ ++extern int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name); ++extern int brcmf_c_host_event(struct brcmf_info *drvr_priv, int *idx, ++ void *pktdata, struct brcmf_event_msg *, ++ void **data_ptr); ++ ++extern void brcmf_c_init(void); ++ ++extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, ++ struct net_device *ndev, char *name, u8 *mac_addr, ++ u32 flags, u8 bssidx); ++extern void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx); ++ ++/* Send packet to dongle via data channel */ ++extern int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx,\ ++ struct sk_buff *pkt); ++ ++extern int brcmf_bus_start(struct brcmf_pub *drvr); ++ ++extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg); ++extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, ++ int enable, int master_mode); ++ ++#define BRCMF_DCMD_SMLEN 256 /* "small" cmd buffer required */ ++#define BRCMF_DCMD_MEDLEN 1536 /* "med" cmd buffer required */ ++#define BRCMF_DCMD_MAXLEN 8192 /* max length cmd buffer required */ ++ ++/* message levels */ ++#define BRCMF_ERROR_VAL 0x0001 ++#define BRCMF_TRACE_VAL 0x0002 ++#define BRCMF_INFO_VAL 0x0004 ++#define BRCMF_DATA_VAL 0x0008 ++#define BRCMF_CTL_VAL 0x0010 ++#define BRCMF_TIMER_VAL 0x0020 ++#define BRCMF_HDRS_VAL 0x0040 ++#define BRCMF_BYTES_VAL 0x0080 ++#define BRCMF_INTR_VAL 0x0100 ++#define BRCMF_GLOM_VAL 0x0400 ++#define BRCMF_EVENT_VAL 0x0800 ++#define BRCMF_BTA_VAL 0x1000 ++#define BRCMF_ISCAN_VAL 0x2000 ++ ++/* Enter idle immediately (no timeout) */ ++#define BRCMF_IDLE_IMMEDIATE (-1) ++#define BRCMF_IDLE_ACTIVE 0 /* Do not request any SD clock change ++ when idle */ ++#define BRCMF_IDLE_INTERVAL 1 ++ ++#endif /* _BRCMF_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c.orig 2011-11-09 13:46:58.232800795 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c 2011-11-09 13:47:16.983566378 -0500 +@@ -0,0 +1,1356 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dhd.h" ++#include "dhd_bus.h" ++#include "dhd_proto.h" ++#include "dhd_dbg.h" ++#include "wl_cfg80211.h" ++#include "bcmchip.h" ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac driver."); ++MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards"); ++MODULE_LICENSE("Dual BSD/GPL"); ++ ++ ++/* Interface control information */ ++struct brcmf_if { ++ struct brcmf_info *info; /* back pointer to brcmf_info */ ++ /* OS/stack specifics */ ++ struct net_device *ndev; ++ struct net_device_stats stats; ++ int idx; /* iface idx in dongle */ ++ int state; /* interface state */ ++ u8 mac_addr[ETH_ALEN]; /* assigned MAC address */ ++}; ++ ++/* Local private structure (extension of pub) */ ++struct brcmf_info { ++ struct brcmf_pub pub; ++ ++ /* OS/stack specifics */ ++ struct brcmf_if *iflist[BRCMF_MAX_IFS]; ++ ++ struct mutex proto_block; ++ ++ struct work_struct setmacaddr_work; ++ struct work_struct multicast_work; ++ u8 macvalue[ETH_ALEN]; ++ atomic_t pend_8021x_cnt; ++}; ++ ++/* Error bits */ ++module_param(brcmf_msg_level, int, 0); ++ ++ ++static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *ndev) ++{ ++ int i = 0; ++ ++ while (i < BRCMF_MAX_IFS) { ++ if (drvr_priv->iflist[i] && drvr_priv->iflist[i]->ndev == ndev) ++ return i; ++ i++; ++ } ++ ++ return BRCMF_BAD_IF; ++} ++ ++int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name) ++{ ++ int i = BRCMF_MAX_IFS; ++ struct brcmf_if *ifp; ++ ++ if (name == NULL || *name == '\0') ++ return 0; ++ ++ while (--i > 0) { ++ ifp = drvr_priv->iflist[i]; ++ if (ifp && !strncmp(ifp->ndev->name, name, IFNAMSIZ)) ++ break; ++ } ++ ++ brcmf_dbg(TRACE, "return idx %d for \"%s\"\n", i, name); ++ ++ return i; /* default - the primary interface */ ++} ++ ++char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx) ++{ ++ struct brcmf_info *drvr_priv = drvr->info; ++ ++ if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { ++ brcmf_dbg(ERROR, "ifidx %d out of range\n", ifidx); ++ return ""; ++ } ++ ++ if (drvr_priv->iflist[ifidx] == NULL) { ++ brcmf_dbg(ERROR, "null i/f %d\n", ifidx); ++ return ""; ++ } ++ ++ if (drvr_priv->iflist[ifidx]->ndev) ++ return drvr_priv->iflist[ifidx]->ndev->name; ++ ++ return ""; ++} ++ ++static void _brcmf_set_multicast_list(struct work_struct *work) ++{ ++ struct net_device *ndev; ++ struct netdev_hw_addr *ha; ++ u32 dcmd_value, cnt; ++ __le32 cnt_le; ++ __le32 dcmd_le_value; ++ ++ struct brcmf_dcmd dcmd; ++ char *buf, *bufp; ++ uint buflen; ++ int ret; ++ ++ struct brcmf_info *drvr_priv = container_of(work, struct brcmf_info, ++ multicast_work); ++ ++ ndev = drvr_priv->iflist[0]->ndev; ++ cnt = netdev_mc_count(ndev); ++ ++ /* Determine initial value of allmulti flag */ ++ dcmd_value = (ndev->flags & IFF_ALLMULTI) ? true : false; ++ ++ /* Send down the multicast list first. */ ++ ++ buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETH_ALEN); ++ bufp = buf = kmalloc(buflen, GFP_ATOMIC); ++ if (!bufp) ++ return; ++ ++ strcpy(bufp, "mcast_list"); ++ bufp += strlen("mcast_list") + 1; ++ ++ cnt_le = cpu_to_le32(cnt); ++ memcpy(bufp, &cnt_le, sizeof(cnt)); ++ bufp += sizeof(cnt_le); ++ ++ netdev_for_each_mc_addr(ha, ndev) { ++ if (!cnt) ++ break; ++ memcpy(bufp, ha->addr, ETH_ALEN); ++ bufp += ETH_ALEN; ++ cnt--; ++ } ++ ++ memset(&dcmd, 0, sizeof(dcmd)); ++ dcmd.cmd = BRCMF_C_SET_VAR; ++ dcmd.buf = buf; ++ dcmd.len = buflen; ++ dcmd.set = true; ++ ++ ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len); ++ if (ret < 0) { ++ brcmf_dbg(ERROR, "%s: set mcast_list failed, cnt %d\n", ++ brcmf_ifname(&drvr_priv->pub, 0), cnt); ++ dcmd_value = cnt ? true : dcmd_value; ++ } ++ ++ kfree(buf); ++ ++ /* Now send the allmulti setting. This is based on the setting in the ++ * net_device flags, but might be modified above to be turned on if we ++ * were trying to set some addresses and dongle rejected it... ++ */ ++ ++ buflen = sizeof("allmulti") + sizeof(dcmd_value); ++ buf = kmalloc(buflen, GFP_ATOMIC); ++ if (!buf) ++ return; ++ ++ dcmd_le_value = cpu_to_le32(dcmd_value); ++ ++ if (!brcmf_c_mkiovar ++ ("allmulti", (void *)&dcmd_le_value, ++ sizeof(dcmd_le_value), buf, buflen)) { ++ brcmf_dbg(ERROR, "%s: mkiovar failed for allmulti, datalen %d buflen %u\n", ++ brcmf_ifname(&drvr_priv->pub, 0), ++ (int)sizeof(dcmd_value), buflen); ++ kfree(buf); ++ return; ++ } ++ ++ memset(&dcmd, 0, sizeof(dcmd)); ++ dcmd.cmd = BRCMF_C_SET_VAR; ++ dcmd.buf = buf; ++ dcmd.len = buflen; ++ dcmd.set = true; ++ ++ ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len); ++ if (ret < 0) { ++ brcmf_dbg(ERROR, "%s: set allmulti %d failed\n", ++ brcmf_ifname(&drvr_priv->pub, 0), ++ le32_to_cpu(dcmd_le_value)); ++ } ++ ++ kfree(buf); ++ ++ /* Finally, pick up the PROMISC flag as well, like the NIC ++ driver does */ ++ ++ dcmd_value = (ndev->flags & IFF_PROMISC) ? true : false; ++ dcmd_le_value = cpu_to_le32(dcmd_value); ++ ++ memset(&dcmd, 0, sizeof(dcmd)); ++ dcmd.cmd = BRCMF_C_SET_PROMISC; ++ dcmd.buf = &dcmd_le_value; ++ dcmd.len = sizeof(dcmd_le_value); ++ dcmd.set = true; ++ ++ ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len); ++ if (ret < 0) { ++ brcmf_dbg(ERROR, "%s: set promisc %d failed\n", ++ brcmf_ifname(&drvr_priv->pub, 0), ++ le32_to_cpu(dcmd_le_value)); ++ } ++} ++ ++static void ++_brcmf_set_mac_address(struct work_struct *work) ++{ ++ char buf[32]; ++ struct brcmf_dcmd dcmd; ++ int ret; ++ ++ struct brcmf_info *drvr_priv = container_of(work, struct brcmf_info, ++ setmacaddr_work); ++ ++ brcmf_dbg(TRACE, "enter\n"); ++ if (!brcmf_c_mkiovar("cur_etheraddr", (char *)drvr_priv->macvalue, ++ ETH_ALEN, buf, 32)) { ++ brcmf_dbg(ERROR, "%s: mkiovar failed for cur_etheraddr\n", ++ brcmf_ifname(&drvr_priv->pub, 0)); ++ return; ++ } ++ memset(&dcmd, 0, sizeof(dcmd)); ++ dcmd.cmd = BRCMF_C_SET_VAR; ++ dcmd.buf = buf; ++ dcmd.len = 32; ++ dcmd.set = true; ++ ++ ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len); ++ if (ret < 0) ++ brcmf_dbg(ERROR, "%s: set cur_etheraddr failed\n", ++ brcmf_ifname(&drvr_priv->pub, 0)); ++ else ++ memcpy(drvr_priv->iflist[0]->ndev->dev_addr, ++ drvr_priv->macvalue, ETH_ALEN); ++ ++ return; ++} ++ ++static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr) ++{ ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **) ++ netdev_priv(ndev); ++ struct sockaddr *sa = (struct sockaddr *)addr; ++ int ifidx; ++ ++ ifidx = brcmf_net2idx(drvr_priv, ndev); ++ if (ifidx == BRCMF_BAD_IF) ++ return -1; ++ ++ memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN); ++ schedule_work(&drvr_priv->setmacaddr_work); ++ return 0; ++} ++ ++static void brcmf_netdev_set_multicast_list(struct net_device *ndev) ++{ ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **) ++ netdev_priv(ndev); ++ int ifidx; ++ ++ ifidx = brcmf_net2idx(drvr_priv, ndev); ++ if (ifidx == BRCMF_BAD_IF) ++ return; ++ ++ schedule_work(&drvr_priv->multicast_work); ++} ++ ++int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf) ++{ ++ struct brcmf_info *drvr_priv = drvr->info; ++ ++ /* Reject if down */ ++ if (!drvr->up || (drvr->busstate == BRCMF_BUS_DOWN)) ++ return -ENODEV; ++ ++ /* Update multicast statistic */ ++ if (pktbuf->len >= ETH_ALEN) { ++ u8 *pktdata = (u8 *) (pktbuf->data); ++ struct ethhdr *eh = (struct ethhdr *)pktdata; ++ ++ if (is_multicast_ether_addr(eh->h_dest)) ++ drvr->tx_multicast++; ++ if (ntohs(eh->h_proto) == ETH_P_PAE) ++ atomic_inc(&drvr_priv->pend_8021x_cnt); ++ } ++ ++ /* If the protocol uses a data header, apply it */ ++ brcmf_proto_hdrpush(drvr, ifidx, pktbuf); ++ ++ /* Use bus module to send data frame */ ++ return brcmf_sdbrcm_bus_txdata(drvr->bus, pktbuf); ++} ++ ++static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) ++{ ++ int ret; ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **) ++ netdev_priv(ndev); ++ int ifidx; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Reject if down */ ++ if (!drvr_priv->pub.up || (drvr_priv->pub.busstate == BRCMF_BUS_DOWN)) { ++ brcmf_dbg(ERROR, "xmit rejected pub.up=%d busstate=%d\n", ++ drvr_priv->pub.up, drvr_priv->pub.busstate); ++ netif_stop_queue(ndev); ++ return -ENODEV; ++ } ++ ++ ifidx = brcmf_net2idx(drvr_priv, ndev); ++ if (ifidx == BRCMF_BAD_IF) { ++ brcmf_dbg(ERROR, "bad ifidx %d\n", ifidx); ++ netif_stop_queue(ndev); ++ return -ENODEV; ++ } ++ ++ /* Make sure there's enough room for any header */ ++ if (skb_headroom(skb) < drvr_priv->pub.hdrlen) { ++ struct sk_buff *skb2; ++ ++ brcmf_dbg(INFO, "%s: insufficient headroom\n", ++ brcmf_ifname(&drvr_priv->pub, ifidx)); ++ drvr_priv->pub.tx_realloc++; ++ skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen); ++ dev_kfree_skb(skb); ++ skb = skb2; ++ if (skb == NULL) { ++ brcmf_dbg(ERROR, "%s: skb_realloc_headroom failed\n", ++ brcmf_ifname(&drvr_priv->pub, ifidx)); ++ ret = -ENOMEM; ++ goto done; ++ } ++ } ++ ++ ret = brcmf_sendpkt(&drvr_priv->pub, ifidx, skb); ++ ++done: ++ if (ret) ++ drvr_priv->pub.dstats.tx_dropped++; ++ else ++ drvr_priv->pub.tx_packets++; ++ ++ /* Return ok: we always eat the packet */ ++ return 0; ++} ++ ++void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool state) ++{ ++ struct net_device *ndev; ++ struct brcmf_info *drvr_priv = drvr->info; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ drvr->txoff = state; ++ ndev = drvr_priv->iflist[ifidx]->ndev; ++ if (state == ON) ++ netif_stop_queue(ndev); ++ else ++ netif_wake_queue(ndev); ++} ++ ++static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, ++ void *pktdata, struct brcmf_event_msg *event, ++ void **data) ++{ ++ int bcmerror = 0; ++ ++ bcmerror = brcmf_c_host_event(drvr_priv, ifidx, pktdata, event, data); ++ if (bcmerror != 0) ++ return bcmerror; ++ ++ if (drvr_priv->iflist[*ifidx]->ndev) ++ brcmf_cfg80211_event(drvr_priv->iflist[*ifidx]->ndev, ++ event, *data); ++ ++ return bcmerror; ++} ++ ++void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb, ++ int numpkt) ++{ ++ struct brcmf_info *drvr_priv = drvr->info; ++ unsigned char *eth; ++ uint len; ++ void *data; ++ struct sk_buff *pnext, *save_pktbuf; ++ int i; ++ struct brcmf_if *ifp; ++ struct brcmf_event_msg event; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ save_pktbuf = skb; ++ ++ for (i = 0; skb && i < numpkt; i++, skb = pnext) { ++ ++ pnext = skb->next; ++ skb->next = NULL; ++ ++ /* Get the protocol, maintain skb around eth_type_trans() ++ * The main reason for this hack is for the limitation of ++ * Linux 2.4 where 'eth_type_trans' uses the ++ * 'net->hard_header_len' ++ * to perform skb_pull inside vs ETH_HLEN. Since to avoid ++ * coping of the packet coming from the network stack to add ++ * BDC, Hardware header etc, during network interface ++ * registration ++ * we set the 'net->hard_header_len' to ETH_HLEN + extra space ++ * required ++ * for BDC, Hardware header etc. and not just the ETH_HLEN ++ */ ++ eth = skb->data; ++ len = skb->len; ++ ++ ifp = drvr_priv->iflist[ifidx]; ++ if (ifp == NULL) ++ ifp = drvr_priv->iflist[0]; ++ ++ skb->dev = ifp->ndev; ++ skb->protocol = eth_type_trans(skb, skb->dev); ++ ++ if (skb->pkt_type == PACKET_MULTICAST) ++ drvr_priv->pub.rx_multicast++; ++ ++ skb->data = eth; ++ skb->len = len; ++ ++ /* Strip header, count, deliver upward */ ++ skb_pull(skb, ETH_HLEN); ++ ++ /* Process special event packets and then discard them */ ++ if (ntohs(skb->protocol) == ETH_P_LINK_CTL) ++ brcmf_host_event(drvr_priv, &ifidx, ++ skb_mac_header(skb), ++ &event, &data); ++ ++ if (drvr_priv->iflist[ifidx] && ++ !drvr_priv->iflist[ifidx]->state) ++ ifp = drvr_priv->iflist[ifidx]; ++ ++ if (ifp->ndev) ++ ifp->ndev->last_rx = jiffies; ++ ++ drvr->dstats.rx_bytes += skb->len; ++ drvr->rx_packets++; /* Local count */ ++ ++ if (in_interrupt()) ++ netif_rx(skb); ++ else ++ /* If the receive is not processed inside an ISR, ++ * the softirqd must be woken explicitly to service ++ * the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled ++ * by netif_rx_ni(), but in earlier kernels, we need ++ * to do it manually. ++ */ ++ netif_rx_ni(skb); ++ } ++} ++ ++void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, bool success) ++{ ++ uint ifidx; ++ struct brcmf_info *drvr_priv = drvr->info; ++ struct ethhdr *eh; ++ u16 type; ++ ++ brcmf_proto_hdrpull(drvr, &ifidx, txp); ++ ++ eh = (struct ethhdr *)(txp->data); ++ type = ntohs(eh->h_proto); ++ ++ if (type == ETH_P_PAE) ++ atomic_dec(&drvr_priv->pend_8021x_cnt); ++ ++} ++ ++static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev) ++{ ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **) ++ netdev_priv(ndev); ++ struct brcmf_if *ifp; ++ int ifidx; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ ifidx = brcmf_net2idx(drvr_priv, ndev); ++ if (ifidx == BRCMF_BAD_IF) ++ return NULL; ++ ++ ifp = drvr_priv->iflist[ifidx]; ++ ++ if (drvr_priv->pub.up) ++ /* Use the protocol to get dongle stats */ ++ brcmf_proto_dstats(&drvr_priv->pub); ++ ++ /* Copy dongle stats to net device stats */ ++ ifp->stats.rx_packets = drvr_priv->pub.dstats.rx_packets; ++ ifp->stats.tx_packets = drvr_priv->pub.dstats.tx_packets; ++ ifp->stats.rx_bytes = drvr_priv->pub.dstats.rx_bytes; ++ ifp->stats.tx_bytes = drvr_priv->pub.dstats.tx_bytes; ++ ifp->stats.rx_errors = drvr_priv->pub.dstats.rx_errors; ++ ifp->stats.tx_errors = drvr_priv->pub.dstats.tx_errors; ++ ifp->stats.rx_dropped = drvr_priv->pub.dstats.rx_dropped; ++ ifp->stats.tx_dropped = drvr_priv->pub.dstats.tx_dropped; ++ ifp->stats.multicast = drvr_priv->pub.dstats.multicast; ++ ++ return &ifp->stats; ++} ++ ++/* Retrieve current toe component enables, which are kept ++ as a bitmap in toe_ol iovar */ ++static int brcmf_toe_get(struct brcmf_info *drvr_priv, int ifidx, u32 *toe_ol) ++{ ++ struct brcmf_dcmd dcmd; ++ __le32 toe_le; ++ char buf[32]; ++ int ret; ++ ++ memset(&dcmd, 0, sizeof(dcmd)); ++ ++ dcmd.cmd = BRCMF_C_GET_VAR; ++ dcmd.buf = buf; ++ dcmd.len = (uint) sizeof(buf); ++ dcmd.set = false; ++ ++ strcpy(buf, "toe_ol"); ++ ret = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, dcmd.len); ++ if (ret < 0) { ++ /* Check for older dongle image that doesn't support toe_ol */ ++ if (ret == -EIO) { ++ brcmf_dbg(ERROR, "%s: toe not supported by device\n", ++ brcmf_ifname(&drvr_priv->pub, ifidx)); ++ return -EOPNOTSUPP; ++ } ++ ++ brcmf_dbg(INFO, "%s: could not get toe_ol: ret=%d\n", ++ brcmf_ifname(&drvr_priv->pub, ifidx), ret); ++ return ret; ++ } ++ ++ memcpy(&toe_le, buf, sizeof(u32)); ++ *toe_ol = le32_to_cpu(toe_le); ++ return 0; ++} ++ ++/* Set current toe component enables in toe_ol iovar, ++ and set toe global enable iovar */ ++static int brcmf_toe_set(struct brcmf_info *drvr_priv, int ifidx, u32 toe_ol) ++{ ++ struct brcmf_dcmd dcmd; ++ char buf[32]; ++ int ret; ++ __le32 toe_le = cpu_to_le32(toe_ol); ++ ++ memset(&dcmd, 0, sizeof(dcmd)); ++ ++ dcmd.cmd = BRCMF_C_SET_VAR; ++ dcmd.buf = buf; ++ dcmd.len = (uint) sizeof(buf); ++ dcmd.set = true; ++ ++ /* Set toe_ol as requested */ ++ strcpy(buf, "toe_ol"); ++ memcpy(&buf[sizeof("toe_ol")], &toe_le, sizeof(u32)); ++ ++ ret = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, dcmd.len); ++ if (ret < 0) { ++ brcmf_dbg(ERROR, "%s: could not set toe_ol: ret=%d\n", ++ brcmf_ifname(&drvr_priv->pub, ifidx), ret); ++ return ret; ++ } ++ ++ /* Enable toe globally only if any components are enabled. */ ++ toe_le = cpu_to_le32(toe_ol != 0); ++ ++ strcpy(buf, "toe"); ++ memcpy(&buf[sizeof("toe")], &toe_le, sizeof(u32)); ++ ++ ret = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, dcmd.len); ++ if (ret < 0) { ++ brcmf_dbg(ERROR, "%s: could not set toe: ret=%d\n", ++ brcmf_ifname(&drvr_priv->pub, ifidx), ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void brcmf_ethtool_get_drvinfo(struct net_device *ndev, ++ struct ethtool_drvinfo *info) ++{ ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **) ++ netdev_priv(ndev); ++ ++ sprintf(info->driver, KBUILD_MODNAME); ++ sprintf(info->version, "%lu", drvr_priv->pub.drv_version); ++ sprintf(info->fw_version, "%s", BCM4329_FW_NAME); ++ sprintf(info->bus_info, "%s", ++ dev_name(brcmf_bus_get_device(drvr_priv->pub.bus))); ++} ++ ++static struct ethtool_ops brcmf_ethtool_ops = { ++ .get_drvinfo = brcmf_ethtool_get_drvinfo ++}; ++ ++static int brcmf_ethtool(struct brcmf_info *drvr_priv, void __user *uaddr) ++{ ++ struct ethtool_drvinfo info; ++ char drvname[sizeof(info.driver)]; ++ u32 cmd; ++ struct ethtool_value edata; ++ u32 toe_cmpnt, csum_dir; ++ int ret; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* all ethtool calls start with a cmd word */ ++ if (copy_from_user(&cmd, uaddr, sizeof(u32))) ++ return -EFAULT; ++ ++ switch (cmd) { ++ case ETHTOOL_GDRVINFO: ++ /* Copy out any request driver name */ ++ if (copy_from_user(&info, uaddr, sizeof(info))) ++ return -EFAULT; ++ strncpy(drvname, info.driver, sizeof(info.driver)); ++ drvname[sizeof(info.driver) - 1] = '\0'; ++ ++ /* clear struct for return */ ++ memset(&info, 0, sizeof(info)); ++ info.cmd = cmd; ++ ++ /* if requested, identify ourselves */ ++ if (strcmp(drvname, "?dhd") == 0) { ++ sprintf(info.driver, "dhd"); ++ strcpy(info.version, BRCMF_VERSION_STR); ++ } ++ ++ /* otherwise, require dongle to be up */ ++ else if (!drvr_priv->pub.up) { ++ brcmf_dbg(ERROR, "dongle is not up\n"); ++ return -ENODEV; ++ } ++ ++ /* finally, report dongle driver type */ ++ else if (drvr_priv->pub.iswl) ++ sprintf(info.driver, "wl"); ++ else ++ sprintf(info.driver, "xx"); ++ ++ sprintf(info.version, "%lu", drvr_priv->pub.drv_version); ++ if (copy_to_user(uaddr, &info, sizeof(info))) ++ return -EFAULT; ++ brcmf_dbg(CTL, "given %*s, returning %s\n", ++ (int)sizeof(drvname), drvname, info.driver); ++ break; ++ ++ /* Get toe offload components from dongle */ ++ case ETHTOOL_GRXCSUM: ++ case ETHTOOL_GTXCSUM: ++ ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt); ++ if (ret < 0) ++ return ret; ++ ++ csum_dir = ++ (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL; ++ ++ edata.cmd = cmd; ++ edata.data = (toe_cmpnt & csum_dir) ? 1 : 0; ++ ++ if (copy_to_user(uaddr, &edata, sizeof(edata))) ++ return -EFAULT; ++ break; ++ ++ /* Set toe offload components in dongle */ ++ case ETHTOOL_SRXCSUM: ++ case ETHTOOL_STXCSUM: ++ if (copy_from_user(&edata, uaddr, sizeof(edata))) ++ return -EFAULT; ++ ++ /* Read the current settings, update and write back */ ++ ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt); ++ if (ret < 0) ++ return ret; ++ ++ csum_dir = ++ (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL; ++ ++ if (edata.data != 0) ++ toe_cmpnt |= csum_dir; ++ else ++ toe_cmpnt &= ~csum_dir; ++ ++ ret = brcmf_toe_set(drvr_priv, 0, toe_cmpnt); ++ if (ret < 0) ++ return ret; ++ ++ /* If setting TX checksum mode, tell Linux the new mode */ ++ if (cmd == ETHTOOL_STXCSUM) { ++ if (edata.data) ++ drvr_priv->iflist[0]->ndev->features |= ++ NETIF_F_IP_CSUM; ++ else ++ drvr_priv->iflist[0]->ndev->features &= ++ ~NETIF_F_IP_CSUM; ++ } ++ ++ break; ++ ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; ++} ++ ++static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr, ++ int cmd) ++{ ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **) ++ netdev_priv(ndev); ++ int ifidx; ++ ++ ifidx = brcmf_net2idx(drvr_priv, ndev); ++ brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifidx, cmd); ++ ++ if (ifidx == BRCMF_BAD_IF) ++ return -1; ++ ++ if (cmd == SIOCETHTOOL) ++ return brcmf_ethtool(drvr_priv, ifr->ifr_data); ++ ++ return -EOPNOTSUPP; ++} ++ ++/* called only from within this driver. Sends a command to the dongle. */ ++s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len) ++{ ++ struct brcmf_dcmd dcmd; ++ s32 err = 0; ++ int buflen = 0; ++ bool is_set_key_cmd; ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **) ++ netdev_priv(ndev); ++ int ifidx; ++ ++ memset(&dcmd, 0, sizeof(dcmd)); ++ dcmd.cmd = cmd; ++ dcmd.buf = arg; ++ dcmd.len = len; ++ ++ ifidx = brcmf_net2idx(drvr_priv, ndev); ++ ++ if (dcmd.buf != NULL) ++ buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN); ++ ++ /* send to dongle (must be up, and wl) */ ++ if ((drvr_priv->pub.busstate != BRCMF_BUS_DATA)) { ++ brcmf_dbg(ERROR, "DONGLE_DOWN\n"); ++ err = -EIO; ++ goto done; ++ } ++ ++ if (!drvr_priv->pub.iswl) { ++ err = -EIO; ++ goto done; ++ } ++ ++ /* ++ * Intercept BRCMF_C_SET_KEY CMD - serialize M4 send and ++ * set key CMD to prevent M4 encryption. ++ */ ++ is_set_key_cmd = ((dcmd.cmd == BRCMF_C_SET_KEY) || ++ ((dcmd.cmd == BRCMF_C_SET_VAR) && ++ !(strncmp("wsec_key", dcmd.buf, 9))) || ++ ((dcmd.cmd == BRCMF_C_SET_VAR) && ++ !(strncmp("bsscfg:wsec_key", dcmd.buf, 15)))); ++ if (is_set_key_cmd) ++ brcmf_netdev_wait_pend8021x(ndev); ++ ++ err = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, buflen); ++ ++done: ++ if (err > 0) ++ err = 0; ++ ++ return err; ++} ++ ++static int brcmf_netdev_stop(struct net_device *ndev) ++{ ++ struct brcmf_pub *drvr = *(struct brcmf_pub **) netdev_priv(ndev); ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ brcmf_cfg80211_down(drvr->config); ++ if (drvr->up == 0) ++ return 0; ++ ++ /* Set state and stop OS transmissions */ ++ drvr->up = 0; ++ netif_stop_queue(ndev); ++ ++ return 0; ++} ++ ++static int brcmf_netdev_open(struct net_device *ndev) ++{ ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **) ++ netdev_priv(ndev); ++ u32 toe_ol; ++ int ifidx = brcmf_net2idx(drvr_priv, ndev); ++ s32 ret = 0; ++ ++ brcmf_dbg(TRACE, "ifidx %d\n", ifidx); ++ ++ if (ifidx == 0) { /* do it only for primary eth0 */ ++ ++ /* try to bring up bus */ ++ ret = brcmf_bus_start(&drvr_priv->pub); ++ if (ret != 0) { ++ brcmf_dbg(ERROR, "failed with code %d\n", ret); ++ return -1; ++ } ++ atomic_set(&drvr_priv->pend_8021x_cnt, 0); ++ ++ memcpy(ndev->dev_addr, drvr_priv->pub.mac, ETH_ALEN); ++ ++ /* Get current TOE mode from dongle */ ++ if (brcmf_toe_get(drvr_priv, ifidx, &toe_ol) >= 0 ++ && (toe_ol & TOE_TX_CSUM_OL) != 0) ++ drvr_priv->iflist[ifidx]->ndev->features |= ++ NETIF_F_IP_CSUM; ++ else ++ drvr_priv->iflist[ifidx]->ndev->features &= ++ ~NETIF_F_IP_CSUM; ++ } ++ /* Allow transmit calls */ ++ netif_start_queue(ndev); ++ drvr_priv->pub.up = 1; ++ if (brcmf_cfg80211_up(drvr_priv->pub.config)) { ++ brcmf_dbg(ERROR, "failed to bring up cfg80211\n"); ++ return -1; ++ } ++ ++ return ret; ++} ++ ++int ++brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, struct net_device *ndev, ++ char *name, u8 *mac_addr, u32 flags, u8 bssidx) ++{ ++ struct brcmf_if *ifp; ++ int ret = 0, err = 0; ++ ++ brcmf_dbg(TRACE, "idx %d, handle->%p\n", ifidx, ndev); ++ ++ ifp = drvr_priv->iflist[ifidx]; ++ if (!ifp) { ++ ifp = kmalloc(sizeof(struct brcmf_if), GFP_ATOMIC); ++ if (!ifp) ++ return -ENOMEM; ++ } ++ ++ memset(ifp, 0, sizeof(struct brcmf_if)); ++ ifp->info = drvr_priv; ++ drvr_priv->iflist[ifidx] = ifp; ++ if (mac_addr != NULL) ++ memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN); ++ ++ if (ndev == NULL) { ++ ifp->state = BRCMF_E_IF_ADD; ++ ifp->idx = ifidx; ++ /* ++ * Delete the existing interface before overwriting it ++ * in case we missed the BRCMF_E_IF_DEL event. ++ */ ++ if (ifp->ndev != NULL) { ++ brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n", ++ ifp->ndev->name); ++ netif_stop_queue(ifp->ndev); ++ unregister_netdev(ifp->ndev); ++ free_netdev(ifp->ndev); ++ } ++ ++ /* Allocate netdev, including space for private structure */ ++ ifp->ndev = alloc_netdev(sizeof(drvr_priv), "wlan%d", ++ ether_setup); ++ if (!ifp->ndev) { ++ brcmf_dbg(ERROR, "OOM - alloc_netdev\n"); ++ ret = -ENOMEM; ++ } ++ ++ if (ret == 0) { ++ memcpy(netdev_priv(ifp->ndev), &drvr_priv, ++ sizeof(drvr_priv)); ++ err = brcmf_net_attach(&drvr_priv->pub, ifp->idx); ++ if (err != 0) { ++ brcmf_dbg(ERROR, "brcmf_net_attach failed, err %d\n", ++ err); ++ ret = -EOPNOTSUPP; ++ } else { ++ brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n", ++ current->pid, ifp->ndev->name); ++ ifp->state = 0; ++ } ++ } ++ ++ if (ret < 0) { ++ if (ifp->ndev) ++ free_netdev(ifp->ndev); ++ ++ drvr_priv->iflist[ifp->idx] = NULL; ++ kfree(ifp); ++ } ++ } else ++ ifp->ndev = ndev; ++ ++ return 0; ++} ++ ++void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx) ++{ ++ struct brcmf_if *ifp; ++ ++ brcmf_dbg(TRACE, "idx %d\n", ifidx); ++ ++ ifp = drvr_priv->iflist[ifidx]; ++ if (!ifp) { ++ brcmf_dbg(ERROR, "Null interface\n"); ++ return; ++ } ++ ++ ifp->state = BRCMF_E_IF_DEL; ++ ifp->idx = ifidx; ++ if (ifp->ndev != NULL) { ++ netif_stop_queue(ifp->ndev); ++ unregister_netdev(ifp->ndev); ++ free_netdev(ifp->ndev); ++ drvr_priv->iflist[ifidx] = NULL; ++ kfree(ifp); ++ } ++} ++ ++struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen) ++{ ++ struct brcmf_info *drvr_priv = NULL; ++ struct net_device *ndev; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Allocate netdev, including space for private structure */ ++ ndev = alloc_netdev(sizeof(drvr_priv), "wlan%d", ether_setup); ++ if (!ndev) { ++ brcmf_dbg(ERROR, "OOM - alloc_netdev\n"); ++ goto fail; ++ } ++ ++ /* Allocate primary brcmf_info */ ++ drvr_priv = kzalloc(sizeof(struct brcmf_info), GFP_ATOMIC); ++ if (!drvr_priv) ++ goto fail; ++ ++ /* ++ * Save the brcmf_info into the priv ++ */ ++ memcpy(netdev_priv(ndev), &drvr_priv, sizeof(drvr_priv)); ++ ++ if (brcmf_add_if(drvr_priv, 0, ndev, ndev->name, NULL, 0, 0) == ++ BRCMF_BAD_IF) ++ goto fail; ++ ++ ndev->netdev_ops = NULL; ++ mutex_init(&drvr_priv->proto_block); ++ ++ /* Link to info module */ ++ drvr_priv->pub.info = drvr_priv; ++ ++ /* Link to bus module */ ++ drvr_priv->pub.bus = bus; ++ drvr_priv->pub.hdrlen = bus_hdrlen; ++ ++ /* Attach and link in the protocol */ ++ if (brcmf_proto_attach(&drvr_priv->pub) != 0) { ++ brcmf_dbg(ERROR, "brcmf_prot_attach failed\n"); ++ goto fail; ++ } ++ ++ /* Attach and link in the cfg80211 */ ++ drvr_priv->pub.config = ++ brcmf_cfg80211_attach(ndev, ++ brcmf_bus_get_device(bus), ++ &drvr_priv->pub); ++ if (drvr_priv->pub.config == NULL) { ++ brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n"); ++ goto fail; ++ } ++ ++ INIT_WORK(&drvr_priv->setmacaddr_work, _brcmf_set_mac_address); ++ INIT_WORK(&drvr_priv->multicast_work, _brcmf_set_multicast_list); ++ ++ /* ++ * Save the brcmf_info into the priv ++ */ ++ memcpy(netdev_priv(ndev), &drvr_priv, sizeof(drvr_priv)); ++ ++ return &drvr_priv->pub; ++ ++fail: ++ if (ndev) ++ free_netdev(ndev); ++ if (drvr_priv) ++ brcmf_detach(&drvr_priv->pub); ++ ++ return NULL; ++} ++ ++int brcmf_bus_start(struct brcmf_pub *drvr) ++{ ++ int ret = -1; ++ struct brcmf_info *drvr_priv = drvr->info; ++ /* Room for "event_msgs" + '\0' + bitvec */ ++ char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; ++ ++ brcmf_dbg(TRACE, "\n"); ++ ++ /* Bring up the bus */ ++ ret = brcmf_sdbrcm_bus_init(&drvr_priv->pub); ++ if (ret != 0) { ++ brcmf_dbg(ERROR, "brcmf_sdbrcm_bus_init failed %d\n", ret); ++ return ret; ++ } ++ ++ /* If bus is not ready, can't come up */ ++ if (drvr_priv->pub.busstate != BRCMF_BUS_DATA) { ++ brcmf_dbg(ERROR, "failed bus is not ready\n"); ++ return -ENODEV; ++ } ++ ++ brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN, ++ iovbuf, sizeof(iovbuf)); ++ brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, iovbuf, ++ sizeof(iovbuf)); ++ memcpy(drvr->eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN); ++ ++ setbit(drvr->eventmask, BRCMF_E_SET_SSID); ++ setbit(drvr->eventmask, BRCMF_E_PRUNE); ++ setbit(drvr->eventmask, BRCMF_E_AUTH); ++ setbit(drvr->eventmask, BRCMF_E_REASSOC); ++ setbit(drvr->eventmask, BRCMF_E_REASSOC_IND); ++ setbit(drvr->eventmask, BRCMF_E_DEAUTH_IND); ++ setbit(drvr->eventmask, BRCMF_E_DISASSOC_IND); ++ setbit(drvr->eventmask, BRCMF_E_DISASSOC); ++ setbit(drvr->eventmask, BRCMF_E_JOIN); ++ setbit(drvr->eventmask, BRCMF_E_ASSOC_IND); ++ setbit(drvr->eventmask, BRCMF_E_PSK_SUP); ++ setbit(drvr->eventmask, BRCMF_E_LINK); ++ setbit(drvr->eventmask, BRCMF_E_NDIS_LINK); ++ setbit(drvr->eventmask, BRCMF_E_MIC_ERROR); ++ setbit(drvr->eventmask, BRCMF_E_PMKID_CACHE); ++ setbit(drvr->eventmask, BRCMF_E_TXFAIL); ++ setbit(drvr->eventmask, BRCMF_E_JOIN_START); ++ setbit(drvr->eventmask, BRCMF_E_SCAN_COMPLETE); ++ ++/* enable dongle roaming event */ ++ ++ drvr->pktfilter_count = 1; ++ /* Setup filter to allow only unicast */ ++ drvr->pktfilter[0] = "100 0 0 0 0x01 0x00"; ++ ++ /* Bus is ready, do any protocol initialization */ ++ ret = brcmf_proto_init(&drvr_priv->pub); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static struct net_device_ops brcmf_netdev_ops_pri = { ++ .ndo_open = brcmf_netdev_open, ++ .ndo_stop = brcmf_netdev_stop, ++ .ndo_get_stats = brcmf_netdev_get_stats, ++ .ndo_do_ioctl = brcmf_netdev_ioctl_entry, ++ .ndo_start_xmit = brcmf_netdev_start_xmit, ++ .ndo_set_mac_address = brcmf_netdev_set_mac_address, ++ .ndo_set_rx_mode = brcmf_netdev_set_multicast_list ++}; ++ ++int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx) ++{ ++ struct brcmf_info *drvr_priv = drvr->info; ++ struct net_device *ndev; ++ u8 temp_addr[ETH_ALEN] = { ++ 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33}; ++ ++ brcmf_dbg(TRACE, "ifidx %d\n", ifidx); ++ ++ ndev = drvr_priv->iflist[ifidx]->ndev; ++ ndev->netdev_ops = &brcmf_netdev_ops_pri; ++ ++ /* ++ * We have to use the primary MAC for virtual interfaces ++ */ ++ if (ifidx != 0) { ++ /* for virtual interfaces use the primary MAC */ ++ memcpy(temp_addr, drvr_priv->pub.mac, ETH_ALEN); ++ ++ } ++ ++ if (ifidx == 1) { ++ brcmf_dbg(TRACE, "ACCESS POINT MAC:\n"); ++ /* ACCESSPOINT INTERFACE CASE */ ++ temp_addr[0] |= 0X02; /* set bit 2 , ++ - Locally Administered address */ ++ ++ } ++ ndev->hard_header_len = ETH_HLEN + drvr_priv->pub.hdrlen; ++ ndev->ethtool_ops = &brcmf_ethtool_ops; ++ ++ drvr_priv->pub.rxsz = ndev->mtu + ndev->hard_header_len + ++ drvr_priv->pub.hdrlen; ++ ++ memcpy(ndev->dev_addr, temp_addr, ETH_ALEN); ++ ++ if (register_netdev(ndev) != 0) { ++ brcmf_dbg(ERROR, "couldn't register the net device\n"); ++ goto fail; ++ } ++ ++ brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); ++ ++ return 0; ++ ++fail: ++ ndev->netdev_ops = NULL; ++ return -EBADE; ++} ++ ++static void brcmf_bus_detach(struct brcmf_pub *drvr) ++{ ++ struct brcmf_info *drvr_priv; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (drvr) { ++ drvr_priv = drvr->info; ++ if (drvr_priv) { ++ /* Stop the protocol module */ ++ brcmf_proto_stop(&drvr_priv->pub); ++ ++ /* Stop the bus module */ ++ brcmf_sdbrcm_bus_stop(drvr_priv->pub.bus); ++ } ++ } ++} ++ ++void brcmf_detach(struct brcmf_pub *drvr) ++{ ++ struct brcmf_info *drvr_priv; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (drvr) { ++ drvr_priv = drvr->info; ++ if (drvr_priv) { ++ struct brcmf_if *ifp; ++ int i; ++ ++ for (i = 1; i < BRCMF_MAX_IFS; i++) ++ if (drvr_priv->iflist[i]) ++ brcmf_del_if(drvr_priv, i); ++ ++ ifp = drvr_priv->iflist[0]; ++ if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) { ++ rtnl_lock(); ++ brcmf_netdev_stop(ifp->ndev); ++ rtnl_unlock(); ++ unregister_netdev(ifp->ndev); ++ } ++ ++ cancel_work_sync(&drvr_priv->setmacaddr_work); ++ cancel_work_sync(&drvr_priv->multicast_work); ++ ++ brcmf_bus_detach(drvr); ++ ++ if (drvr->prot) ++ brcmf_proto_detach(drvr); ++ ++ brcmf_cfg80211_detach(drvr->config); ++ ++ free_netdev(ifp->ndev); ++ kfree(ifp); ++ kfree(drvr_priv); ++ } ++ } ++} ++ ++static void __exit brcmf_module_cleanup(void) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ brcmf_bus_unregister(); ++} ++ ++static int __init brcmf_module_init(void) ++{ ++ int error; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ error = brcmf_bus_register(); ++ ++ if (error) { ++ brcmf_dbg(ERROR, "brcmf_bus_register failed\n"); ++ goto failed; ++ } ++ return 0; ++ ++failed: ++ return -EINVAL; ++} ++ ++module_init(brcmf_module_init); ++module_exit(brcmf_module_cleanup); ++ ++int brcmf_os_proto_block(struct brcmf_pub *drvr) ++{ ++ struct brcmf_info *drvr_priv = drvr->info; ++ ++ if (drvr_priv) { ++ mutex_lock(&drvr_priv->proto_block); ++ return 1; ++ } ++ return 0; ++} ++ ++int brcmf_os_proto_unblock(struct brcmf_pub *drvr) ++{ ++ struct brcmf_info *drvr_priv = drvr->info; ++ ++ if (drvr_priv) { ++ mutex_unlock(&drvr_priv->proto_block); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv) ++{ ++ return atomic_read(&drvr_priv->pend_8021x_cnt); ++} ++ ++#define MAX_WAIT_FOR_8021X_TX 10 ++ ++int brcmf_netdev_wait_pend8021x(struct net_device *ndev) ++{ ++ struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(ndev); ++ int timeout = 10 * HZ / 1000; ++ int ntimes = MAX_WAIT_FOR_8021X_TX; ++ int pend = brcmf_get_pend_8021x_cnt(drvr_priv); ++ ++ while (ntimes && pend) { ++ if (pend) { ++ set_current_state(TASK_INTERRUPTIBLE); ++ schedule_timeout(timeout); ++ set_current_state(TASK_RUNNING); ++ ntimes--; ++ } ++ pend = brcmf_get_pend_8021x_cnt(drvr_priv); ++ } ++ return pend; ++} ++ ++#ifdef BCMDBG ++int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size) ++{ ++ int ret = 0; ++ struct file *fp; ++ mm_segment_t old_fs; ++ loff_t pos = 0; ++ ++ /* change to KERNEL_DS address limit */ ++ old_fs = get_fs(); ++ set_fs(KERNEL_DS); ++ ++ /* open file to write */ ++ fp = filp_open("/tmp/mem_dump", O_WRONLY | O_CREAT, 0640); ++ if (!fp) { ++ brcmf_dbg(ERROR, "open file error\n"); ++ ret = -1; ++ goto exit; ++ } ++ ++ /* Write buf to file */ ++ fp->f_op->write(fp, (char __user *)buf, size, &pos); ++ ++exit: ++ /* free buf before return */ ++ kfree(buf); ++ /* close file before return */ ++ if (fp) ++ filp_close(fp, current->files); ++ /* restore previous address limit */ ++ set_fs(old_fs); ++ ++ return ret; ++} ++#endif /* BCMDBG */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h.orig 2011-11-09 13:46:58.232800795 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h 2011-11-09 13:47:16.983566378 -0500 +@@ -0,0 +1,60 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCMF_PROTO_H_ ++#define _BRCMF_PROTO_H_ ++ ++/* ++ * Exported from the brcmf protocol module (brcmf_cdc) ++ */ ++ ++/* Linkage, sets prot link and updates hdrlen in pub */ ++extern int brcmf_proto_attach(struct brcmf_pub *drvr); ++ ++/* Unlink, frees allocated protocol memory (including brcmf_proto) */ ++extern void brcmf_proto_detach(struct brcmf_pub *drvr); ++ ++/* Initialize protocol: sync w/dongle state. ++ * Sets dongle media info (iswl, drv_version, mac address). ++ */ ++extern int brcmf_proto_init(struct brcmf_pub *drvr); ++ ++/* Stop protocol: sync w/dongle state. */ ++extern void brcmf_proto_stop(struct brcmf_pub *drvr); ++ ++/* Add any protocol-specific data header. ++ * Caller must reserve prot_hdrlen prepend space. ++ */ ++extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, ++ struct sk_buff *txp); ++ ++/* Remove any protocol-specific data header. */ ++extern int brcmf_proto_hdrpull(struct brcmf_pub *, int *ifidx, ++ struct sk_buff *rxp); ++ ++/* Use protocol to issue command to dongle */ ++extern int brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx, ++ struct brcmf_dcmd *dcmd, int len); ++ ++/* Update local copy of dongle statistics */ ++extern void brcmf_proto_dstats(struct brcmf_pub *drvr); ++ ++extern int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr); ++ ++extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, ++ uint cmd, void *buf, uint len); ++ ++#endif /* _BRCMF_PROTO_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c.orig 2011-11-09 13:46:58.235800758 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c 2011-11-09 13:47:16.986566342 -0500 +@@ -0,0 +1,4591 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "sdio_host.h" ++ ++#define DCMD_RESP_TIMEOUT 2000 /* In milli second */ ++ ++#ifdef BCMDBG ++ ++#define BRCMF_TRAP_INFO_SIZE 80 ++ ++#define CBUF_LEN (128) ++ ++struct rte_log_le { ++ __le32 buf; /* Can't be pointer on (64-bit) hosts */ ++ __le32 buf_size; ++ __le32 idx; ++ char *_buf_compat; /* Redundant pointer for backward compat. */ ++}; ++ ++struct rte_console { ++ /* Virtual UART ++ * When there is no UART (e.g. Quickturn), ++ * the host should write a complete ++ * input line directly into cbuf and then write ++ * the length into vcons_in. ++ * This may also be used when there is a real UART ++ * (at risk of conflicting with ++ * the real UART). vcons_out is currently unused. ++ */ ++ uint vcons_in; ++ uint vcons_out; ++ ++ /* Output (logging) buffer ++ * Console output is written to a ring buffer log_buf at index log_idx. ++ * The host may read the output when it sees log_idx advance. ++ * Output will be lost if the output wraps around faster than the host ++ * polls. ++ */ ++ struct rte_log_le log_le; ++ ++ /* Console input line buffer ++ * Characters are read one at a time into cbuf ++ * until is received, then ++ * the buffer is processed as a command line. ++ * Also used for virtual UART. ++ */ ++ uint cbuf_idx; ++ char cbuf[CBUF_LEN]; ++}; ++ ++#endif /* BCMDBG */ ++#include ++ ++#include "dhd.h" ++#include "dhd_bus.h" ++#include "dhd_proto.h" ++#include "dhd_dbg.h" ++#include ++ ++#define TXQLEN 2048 /* bulk tx queue length */ ++#define TXHI (TXQLEN - 256) /* turn on flow control above TXHI */ ++#define TXLOW (TXHI - 256) /* turn off flow control below TXLOW */ ++#define PRIOMASK 7 ++ ++#define TXRETRIES 2 /* # of retries for tx frames */ ++ ++#define BRCMF_RXBOUND 50 /* Default for max rx frames in ++ one scheduling */ ++ ++#define BRCMF_TXBOUND 20 /* Default for max tx frames in ++ one scheduling */ ++ ++#define BRCMF_TXMINMAX 1 /* Max tx frames if rx still pending */ ++ ++#define MEMBLOCK 2048 /* Block size used for downloading ++ of dongle image */ ++#define MAX_DATA_BUF (32 * 1024) /* Must be large enough to hold ++ biggest possible glom */ ++ ++#define BRCMF_FIRSTREAD (1 << 6) ++ ++ ++/* SBSDIO_DEVICE_CTL */ ++ ++/* 1: device will assert busy signal when receiving CMD53 */ ++#define SBSDIO_DEVCTL_SETBUSY 0x01 ++/* 1: assertion of sdio interrupt is synchronous to the sdio clock */ ++#define SBSDIO_DEVCTL_SPI_INTR_SYNC 0x02 ++/* 1: mask all interrupts to host except the chipActive (rev 8) */ ++#define SBSDIO_DEVCTL_CA_INT_ONLY 0x04 ++/* 1: isolate internal sdio signals, put external pads in tri-state; requires ++ * sdio bus power cycle to clear (rev 9) */ ++#define SBSDIO_DEVCTL_PADS_ISO 0x08 ++/* Force SD->SB reset mapping (rev 11) */ ++#define SBSDIO_DEVCTL_SB_RST_CTL 0x30 ++/* Determined by CoreControl bit */ ++#define SBSDIO_DEVCTL_RST_CORECTL 0x00 ++/* Force backplane reset */ ++#define SBSDIO_DEVCTL_RST_BPRESET 0x10 ++/* Force no backplane reset */ ++#define SBSDIO_DEVCTL_RST_NOBPRESET 0x20 ++ ++/* SBSDIO_FUNC1_CHIPCLKCSR */ ++ ++/* Force ALP request to backplane */ ++#define SBSDIO_FORCE_ALP 0x01 ++/* Force HT request to backplane */ ++#define SBSDIO_FORCE_HT 0x02 ++/* Force ILP request to backplane */ ++#define SBSDIO_FORCE_ILP 0x04 ++/* Make ALP ready (power up xtal) */ ++#define SBSDIO_ALP_AVAIL_REQ 0x08 ++/* Make HT ready (power up PLL) */ ++#define SBSDIO_HT_AVAIL_REQ 0x10 ++/* Squelch clock requests from HW */ ++#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20 ++/* Status: ALP is ready */ ++#define SBSDIO_ALP_AVAIL 0x40 ++/* Status: HT is ready */ ++#define SBSDIO_HT_AVAIL 0x80 ++ ++#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL) ++#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS) ++#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS) ++#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval)) ++ ++#define SBSDIO_CLKAV(regval, alponly) \ ++ (SBSDIO_ALPAV(regval) && (alponly ? 1 : SBSDIO_HTAV(regval))) ++ ++/* direct(mapped) cis space */ ++ ++/* MAPPED common CIS address */ ++#define SBSDIO_CIS_BASE_COMMON 0x1000 ++/* maximum bytes in one CIS */ ++#define SBSDIO_CIS_SIZE_LIMIT 0x200 ++/* cis offset addr is < 17 bits */ ++#define SBSDIO_CIS_OFT_ADDR_MASK 0x1FFFF ++ ++/* manfid tuple length, include tuple, link bytes */ ++#define SBSDIO_CIS_MANFID_TUPLE_LEN 6 ++ ++/* intstatus */ ++#define I_SMB_SW0 (1 << 0) /* To SB Mail S/W interrupt 0 */ ++#define I_SMB_SW1 (1 << 1) /* To SB Mail S/W interrupt 1 */ ++#define I_SMB_SW2 (1 << 2) /* To SB Mail S/W interrupt 2 */ ++#define I_SMB_SW3 (1 << 3) /* To SB Mail S/W interrupt 3 */ ++#define I_SMB_SW_MASK 0x0000000f /* To SB Mail S/W interrupts mask */ ++#define I_SMB_SW_SHIFT 0 /* To SB Mail S/W interrupts shift */ ++#define I_HMB_SW0 (1 << 4) /* To Host Mail S/W interrupt 0 */ ++#define I_HMB_SW1 (1 << 5) /* To Host Mail S/W interrupt 1 */ ++#define I_HMB_SW2 (1 << 6) /* To Host Mail S/W interrupt 2 */ ++#define I_HMB_SW3 (1 << 7) /* To Host Mail S/W interrupt 3 */ ++#define I_HMB_SW_MASK 0x000000f0 /* To Host Mail S/W interrupts mask */ ++#define I_HMB_SW_SHIFT 4 /* To Host Mail S/W interrupts shift */ ++#define I_WR_OOSYNC (1 << 8) /* Write Frame Out Of Sync */ ++#define I_RD_OOSYNC (1 << 9) /* Read Frame Out Of Sync */ ++#define I_PC (1 << 10) /* descriptor error */ ++#define I_PD (1 << 11) /* data error */ ++#define I_DE (1 << 12) /* Descriptor protocol Error */ ++#define I_RU (1 << 13) /* Receive descriptor Underflow */ ++#define I_RO (1 << 14) /* Receive fifo Overflow */ ++#define I_XU (1 << 15) /* Transmit fifo Underflow */ ++#define I_RI (1 << 16) /* Receive Interrupt */ ++#define I_BUSPWR (1 << 17) /* SDIO Bus Power Change (rev 9) */ ++#define I_XMTDATA_AVAIL (1 << 23) /* bits in fifo */ ++#define I_XI (1 << 24) /* Transmit Interrupt */ ++#define I_RF_TERM (1 << 25) /* Read Frame Terminate */ ++#define I_WF_TERM (1 << 26) /* Write Frame Terminate */ ++#define I_PCMCIA_XU (1 << 27) /* PCMCIA Transmit FIFO Underflow */ ++#define I_SBINT (1 << 28) /* sbintstatus Interrupt */ ++#define I_CHIPACTIVE (1 << 29) /* chip from doze to active state */ ++#define I_SRESET (1 << 30) /* CCCR RES interrupt */ ++#define I_IOE2 (1U << 31) /* CCCR IOE2 Bit Changed */ ++#define I_ERRORS (I_PC | I_PD | I_DE | I_RU | I_RO | I_XU) ++#define I_DMA (I_RI | I_XI | I_ERRORS) ++ ++/* corecontrol */ ++#define CC_CISRDY (1 << 0) /* CIS Ready */ ++#define CC_BPRESEN (1 << 1) /* CCCR RES signal */ ++#define CC_F2RDY (1 << 2) /* set CCCR IOR2 bit */ ++#define CC_CLRPADSISO (1 << 3) /* clear SDIO pads isolation */ ++#define CC_XMTDATAAVAIL_MODE (1 << 4) ++#define CC_XMTDATAAVAIL_CTRL (1 << 5) ++ ++/* SDA_FRAMECTRL */ ++#define SFC_RF_TERM (1 << 0) /* Read Frame Terminate */ ++#define SFC_WF_TERM (1 << 1) /* Write Frame Terminate */ ++#define SFC_CRC4WOOS (1 << 2) /* CRC error for write out of sync */ ++#define SFC_ABORTALL (1 << 3) /* Abort all in-progress frames */ ++ ++/* HW frame tag */ ++#define SDPCM_FRAMETAG_LEN 4 /* 2 bytes len, 2 bytes check val */ ++ ++/* Total length of frame header for dongle protocol */ ++#define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN) ++#define SDPCM_RESERVE (SDPCM_HDRLEN + BRCMF_SDALIGN) ++ ++/* ++ * Software allocation of To SB Mailbox resources ++ */ ++ ++/* tosbmailbox bits corresponding to intstatus bits */ ++#define SMB_NAK (1 << 0) /* Frame NAK */ ++#define SMB_INT_ACK (1 << 1) /* Host Interrupt ACK */ ++#define SMB_USE_OOB (1 << 2) /* Use OOB Wakeup */ ++#define SMB_DEV_INT (1 << 3) /* Miscellaneous Interrupt */ ++ ++/* tosbmailboxdata */ ++#define SMB_DATA_VERSION_SHIFT 16 /* host protocol version */ ++ ++/* ++ * Software allocation of To Host Mailbox resources ++ */ ++ ++/* intstatus bits */ ++#define I_HMB_FC_STATE I_HMB_SW0 /* Flow Control State */ ++#define I_HMB_FC_CHANGE I_HMB_SW1 /* Flow Control State Changed */ ++#define I_HMB_FRAME_IND I_HMB_SW2 /* Frame Indication */ ++#define I_HMB_HOST_INT I_HMB_SW3 /* Miscellaneous Interrupt */ ++ ++/* tohostmailboxdata */ ++#define HMB_DATA_NAKHANDLED 1 /* retransmit NAK'd frame */ ++#define HMB_DATA_DEVREADY 2 /* talk to host after enable */ ++#define HMB_DATA_FC 4 /* per prio flowcontrol update flag */ ++#define HMB_DATA_FWREADY 8 /* fw ready for protocol activity */ ++ ++#define HMB_DATA_FCDATA_MASK 0xff000000 ++#define HMB_DATA_FCDATA_SHIFT 24 ++ ++#define HMB_DATA_VERSION_MASK 0x00ff0000 ++#define HMB_DATA_VERSION_SHIFT 16 ++ ++/* ++ * Software-defined protocol header ++ */ ++ ++/* Current protocol version */ ++#define SDPCM_PROT_VERSION 4 ++ ++/* SW frame header */ ++#define SDPCM_PACKET_SEQUENCE(p) (((u8 *)p)[0] & 0xff) ++ ++#define SDPCM_CHANNEL_MASK 0x00000f00 ++#define SDPCM_CHANNEL_SHIFT 8 ++#define SDPCM_PACKET_CHANNEL(p) (((u8 *)p)[1] & 0x0f) ++ ++#define SDPCM_NEXTLEN_OFFSET 2 ++ ++/* Data Offset from SOF (HW Tag, SW Tag, Pad) */ ++#define SDPCM_DOFFSET_OFFSET 3 /* Data Offset */ ++#define SDPCM_DOFFSET_VALUE(p) (((u8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff) ++#define SDPCM_DOFFSET_MASK 0xff000000 ++#define SDPCM_DOFFSET_SHIFT 24 ++#define SDPCM_FCMASK_OFFSET 4 /* Flow control */ ++#define SDPCM_FCMASK_VALUE(p) (((u8 *)p)[SDPCM_FCMASK_OFFSET] & 0xff) ++#define SDPCM_WINDOW_OFFSET 5 /* Credit based fc */ ++#define SDPCM_WINDOW_VALUE(p) (((u8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff) ++ ++#define SDPCM_SWHEADER_LEN 8 /* SW header is 64 bits */ ++ ++/* logical channel numbers */ ++#define SDPCM_CONTROL_CHANNEL 0 /* Control channel Id */ ++#define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication Channel Id */ ++#define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv Channel Id */ ++#define SDPCM_GLOM_CHANNEL 3 /* For coalesced packets */ ++#define SDPCM_TEST_CHANNEL 15 /* Reserved for test/debug packets */ ++ ++#define SDPCM_SEQUENCE_WRAP 256 /* wrap-around val for 8bit frame seq */ ++ ++#define SDPCM_GLOMDESC(p) (((u8 *)p)[1] & 0x80) ++ ++/* ++ * Shared structure between dongle and the host. ++ * The structure contains pointers to trap or assert information. ++ */ ++#define SDPCM_SHARED_VERSION 0x0002 ++#define SDPCM_SHARED_VERSION_MASK 0x00FF ++#define SDPCM_SHARED_ASSERT_BUILT 0x0100 ++#define SDPCM_SHARED_ASSERT 0x0200 ++#define SDPCM_SHARED_TRAP 0x0400 ++ ++/* Space for header read, limit for data packets */ ++#define MAX_HDR_READ (1 << 6) ++#define MAX_RX_DATASZ 2048 ++ ++/* Maximum milliseconds to wait for F2 to come up */ ++#define BRCMF_WAIT_F2RDY 3000 ++ ++/* Bump up limit on waiting for HT to account for first startup; ++ * if the image is doing a CRC calculation before programming the PMU ++ * for HT availability, it could take a couple hundred ms more, so ++ * max out at a 1 second (1000000us). ++ */ ++#undef PMU_MAX_TRANSITION_DLY ++#define PMU_MAX_TRANSITION_DLY 1000000 ++ ++/* Value for ChipClockCSR during initial setup */ ++#define BRCMF_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | \ ++ SBSDIO_ALP_AVAIL_REQ) ++ ++/* Flags for SDH calls */ ++#define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED) ++ ++/* sbimstate */ ++#define SBIM_IBE 0x20000 /* inbanderror */ ++#define SBIM_TO 0x40000 /* timeout */ ++#define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */ ++#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */ ++ ++/* sbtmstatelow */ ++ ++/* reset */ ++#define SBTML_RESET 0x0001 ++/* reject field */ ++#define SBTML_REJ_MASK 0x0006 ++/* reject */ ++#define SBTML_REJ 0x0002 ++/* temporary reject, for error recovery */ ++#define SBTML_TMPREJ 0x0004 ++ ++/* Shift to locate the SI control flags in sbtml */ ++#define SBTML_SICF_SHIFT 16 ++ ++/* sbtmstatehigh */ ++#define SBTMH_SERR 0x0001 /* serror */ ++#define SBTMH_INT 0x0002 /* interrupt */ ++#define SBTMH_BUSY 0x0004 /* busy */ ++#define SBTMH_TO 0x0020 /* timeout (sonics >= 2.3) */ ++ ++/* Shift to locate the SI status flags in sbtmh */ ++#define SBTMH_SISF_SHIFT 16 ++ ++/* sbidlow */ ++#define SBIDL_INIT 0x80 /* initiator */ ++ ++/* sbidhigh */ ++#define SBIDH_RC_MASK 0x000f /* revision code */ ++#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */ ++#define SBIDH_RCE_SHIFT 8 ++#define SBCOREREV(sbidh) \ ++ ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | \ ++ ((sbidh) & SBIDH_RC_MASK)) ++#define SBIDH_CC_MASK 0x8ff0 /* core code */ ++#define SBIDH_CC_SHIFT 4 ++#define SBIDH_VC_MASK 0xffff0000 /* vendor code */ ++#define SBIDH_VC_SHIFT 16 ++ ++/* ++ * Conversion of 802.1D priority to precedence level ++ */ ++static uint prio2prec(u32 prio) ++{ ++ return (prio == PRIO_8021D_NONE || prio == PRIO_8021D_BE) ? ++ (prio^2) : prio; ++} ++ ++/* ++ * Core reg address translation. ++ * Both macro's returns a 32 bits byte address on the backplane bus. ++ */ ++#define CORE_CC_REG(base, field) \ ++ (base + offsetof(struct chipcregs, field)) ++#define CORE_BUS_REG(base, field) \ ++ (base + offsetof(struct sdpcmd_regs, field)) ++#define CORE_SB(base, field) \ ++ (base + SBCONFIGOFF + offsetof(struct sbconfig, field)) ++ ++/* core registers */ ++struct sdpcmd_regs { ++ u32 corecontrol; /* 0x00, rev8 */ ++ u32 corestatus; /* rev8 */ ++ u32 PAD[1]; ++ u32 biststatus; /* rev8 */ ++ ++ /* PCMCIA access */ ++ u16 pcmciamesportaladdr; /* 0x010, rev8 */ ++ u16 PAD[1]; ++ u16 pcmciamesportalmask; /* rev8 */ ++ u16 PAD[1]; ++ u16 pcmciawrframebc; /* rev8 */ ++ u16 PAD[1]; ++ u16 pcmciaunderflowtimer; /* rev8 */ ++ u16 PAD[1]; ++ ++ /* interrupt */ ++ u32 intstatus; /* 0x020, rev8 */ ++ u32 hostintmask; /* rev8 */ ++ u32 intmask; /* rev8 */ ++ u32 sbintstatus; /* rev8 */ ++ u32 sbintmask; /* rev8 */ ++ u32 funcintmask; /* rev4 */ ++ u32 PAD[2]; ++ u32 tosbmailbox; /* 0x040, rev8 */ ++ u32 tohostmailbox; /* rev8 */ ++ u32 tosbmailboxdata; /* rev8 */ ++ u32 tohostmailboxdata; /* rev8 */ ++ ++ /* synchronized access to registers in SDIO clock domain */ ++ u32 sdioaccess; /* 0x050, rev8 */ ++ u32 PAD[3]; ++ ++ /* PCMCIA frame control */ ++ u8 pcmciaframectrl; /* 0x060, rev8 */ ++ u8 PAD[3]; ++ u8 pcmciawatermark; /* rev8 */ ++ u8 PAD[155]; ++ ++ /* interrupt batching control */ ++ u32 intrcvlazy; /* 0x100, rev8 */ ++ u32 PAD[3]; ++ ++ /* counters */ ++ u32 cmd52rd; /* 0x110, rev8 */ ++ u32 cmd52wr; /* rev8 */ ++ u32 cmd53rd; /* rev8 */ ++ u32 cmd53wr; /* rev8 */ ++ u32 abort; /* rev8 */ ++ u32 datacrcerror; /* rev8 */ ++ u32 rdoutofsync; /* rev8 */ ++ u32 wroutofsync; /* rev8 */ ++ u32 writebusy; /* rev8 */ ++ u32 readwait; /* rev8 */ ++ u32 readterm; /* rev8 */ ++ u32 writeterm; /* rev8 */ ++ u32 PAD[40]; ++ u32 clockctlstatus; /* rev8 */ ++ u32 PAD[7]; ++ ++ u32 PAD[128]; /* DMA engines */ ++ ++ /* SDIO/PCMCIA CIS region */ ++ char cis[512]; /* 0x400-0x5ff, rev6 */ ++ ++ /* PCMCIA function control registers */ ++ char pcmciafcr[256]; /* 0x600-6ff, rev6 */ ++ u16 PAD[55]; ++ ++ /* PCMCIA backplane access */ ++ u16 backplanecsr; /* 0x76E, rev6 */ ++ u16 backplaneaddr0; /* rev6 */ ++ u16 backplaneaddr1; /* rev6 */ ++ u16 backplaneaddr2; /* rev6 */ ++ u16 backplaneaddr3; /* rev6 */ ++ u16 backplanedata0; /* rev6 */ ++ u16 backplanedata1; /* rev6 */ ++ u16 backplanedata2; /* rev6 */ ++ u16 backplanedata3; /* rev6 */ ++ u16 PAD[31]; ++ ++ /* sprom "size" & "blank" info */ ++ u16 spromstatus; /* 0x7BE, rev2 */ ++ u32 PAD[464]; ++ ++ u16 PAD[0x80]; ++}; ++ ++#ifdef BCMDBG ++/* Device console log buffer state */ ++struct brcmf_console { ++ uint count; /* Poll interval msec counter */ ++ uint log_addr; /* Log struct address (fixed) */ ++ struct rte_log_le log_le; /* Log struct (host copy) */ ++ uint bufsize; /* Size of log buffer */ ++ u8 *buf; /* Log buffer (host copy) */ ++ uint last; /* Last buffer read index */ ++}; ++#endif /* BCMDBG */ ++ ++struct sdpcm_shared { ++ u32 flags; ++ u32 trap_addr; ++ u32 assert_exp_addr; ++ u32 assert_file_addr; ++ u32 assert_line; ++ u32 console_addr; /* Address of struct rte_console */ ++ u32 msgtrace_addr; ++ u8 tag[32]; ++}; ++ ++struct sdpcm_shared_le { ++ __le32 flags; ++ __le32 trap_addr; ++ __le32 assert_exp_addr; ++ __le32 assert_file_addr; ++ __le32 assert_line; ++ __le32 console_addr; /* Address of struct rte_console */ ++ __le32 msgtrace_addr; ++ u8 tag[32]; ++}; ++ ++ ++/* misc chip info needed by some of the routines */ ++struct chip_info { ++ u32 chip; ++ u32 chiprev; ++ u32 cccorebase; ++ u32 ccrev; ++ u32 cccaps; ++ u32 buscorebase; /* 32 bits backplane bus address */ ++ u32 buscorerev; ++ u32 buscoretype; ++ u32 ramcorebase; ++ u32 armcorebase; ++ u32 pmurev; ++ u32 ramsize; ++}; ++ ++/* Private data for SDIO bus interaction */ ++struct brcmf_bus { ++ struct brcmf_pub *drvr; ++ ++ struct brcmf_sdio_dev *sdiodev; /* sdio device handler */ ++ struct chip_info *ci; /* Chip info struct */ ++ char *vars; /* Variables (from CIS and/or other) */ ++ uint varsz; /* Size of variables buffer */ ++ ++ u32 ramsize; /* Size of RAM in SOCRAM (bytes) */ ++ ++ u32 hostintmask; /* Copy of Host Interrupt Mask */ ++ u32 intstatus; /* Intstatus bits (events) pending */ ++ bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */ ++ bool fcstate; /* State of dongle flow-control */ ++ ++ uint blocksize; /* Block size of SDIO transfers */ ++ uint roundup; /* Max roundup limit */ ++ ++ struct pktq txq; /* Queue length used for flow-control */ ++ u8 flowcontrol; /* per prio flow control bitmask */ ++ u8 tx_seq; /* Transmit sequence number (next) */ ++ u8 tx_max; /* Maximum transmit sequence allowed */ ++ ++ u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN]; ++ u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ ++ u16 nextlen; /* Next Read Len from last header */ ++ u8 rx_seq; /* Receive sequence number (expected) */ ++ bool rxskip; /* Skip receive (awaiting NAK ACK) */ ++ ++ uint rxbound; /* Rx frames to read before resched */ ++ uint txbound; /* Tx frames to send before resched */ ++ uint txminmax; ++ ++ struct sk_buff *glomd; /* Packet containing glomming descriptor */ ++ struct sk_buff *glom; /* Packet chain for glommed superframe */ ++ uint glomerr; /* Glom packet read errors */ ++ ++ u8 *rxbuf; /* Buffer for receiving control packets */ ++ uint rxblen; /* Allocated length of rxbuf */ ++ u8 *rxctl; /* Aligned pointer into rxbuf */ ++ u8 *databuf; /* Buffer for receiving big glom packet */ ++ u8 *dataptr; /* Aligned pointer into databuf */ ++ uint rxlen; /* Length of valid data in buffer */ ++ ++ u8 sdpcm_ver; /* Bus protocol reported by dongle */ ++ ++ bool intr; /* Use interrupts */ ++ bool poll; /* Use polling */ ++ bool ipend; /* Device interrupt is pending */ ++ uint intrcount; /* Count of device interrupt callbacks */ ++ uint lastintrs; /* Count as of last watchdog timer */ ++ uint spurious; /* Count of spurious interrupts */ ++ uint pollrate; /* Ticks between device polls */ ++ uint polltick; /* Tick counter */ ++ uint pollcnt; /* Count of active polls */ ++ ++#ifdef BCMDBG ++ uint console_interval; ++ struct brcmf_console console; /* Console output polling support */ ++ uint console_addr; /* Console address from shared struct */ ++#endif /* BCMDBG */ ++ ++ uint regfails; /* Count of R_REG failures */ ++ ++ uint clkstate; /* State of sd and backplane clock(s) */ ++ bool activity; /* Activity flag for clock down */ ++ s32 idletime; /* Control for activity timeout */ ++ s32 idlecount; /* Activity timeout counter */ ++ s32 idleclock; /* How to set bus driver when idle */ ++ s32 sd_rxchain; ++ bool use_rxchain; /* If brcmf should use PKT chains */ ++ bool sleeping; /* Is SDIO bus sleeping? */ ++ bool rxflow_mode; /* Rx flow control mode */ ++ bool rxflow; /* Is rx flow control on */ ++ bool alp_only; /* Don't use HT clock (ALP only) */ ++/* Field to decide if rx of control frames happen in rxbuf or lb-pool */ ++ bool usebufpool; ++ ++ /* Some additional counters */ ++ uint tx_sderrs; /* Count of tx attempts with sd errors */ ++ uint fcqueued; /* Tx packets that got queued */ ++ uint rxrtx; /* Count of rtx requests (NAK to dongle) */ ++ uint rx_toolong; /* Receive frames too long to receive */ ++ uint rxc_errors; /* SDIO errors when reading control frames */ ++ uint rx_hdrfail; /* SDIO errors on header reads */ ++ uint rx_badhdr; /* Bad received headers (roosync?) */ ++ uint rx_badseq; /* Mismatched rx sequence number */ ++ uint fc_rcvd; /* Number of flow-control events received */ ++ uint fc_xoff; /* Number which turned on flow-control */ ++ uint fc_xon; /* Number which turned off flow-control */ ++ uint rxglomfail; /* Failed deglom attempts */ ++ uint rxglomframes; /* Number of glom frames (superframes) */ ++ uint rxglompkts; /* Number of packets from glom frames */ ++ uint f2rxhdrs; /* Number of header reads */ ++ uint f2rxdata; /* Number of frame data reads */ ++ uint f2txdata; /* Number of f2 frame writes */ ++ uint f1regdata; /* Number of f1 register accesses */ ++ ++ u8 *ctrl_frame_buf; ++ u32 ctrl_frame_len; ++ bool ctrl_frame_stat; ++ ++ spinlock_t txqlock; ++ wait_queue_head_t ctrl_wait; ++ wait_queue_head_t dcmd_resp_wait; ++ ++ struct timer_list timer; ++ struct completion watchdog_wait; ++ struct task_struct *watchdog_tsk; ++ bool wd_timer_valid; ++ uint save_ms; ++ ++ struct task_struct *dpc_tsk; ++ struct completion dpc_wait; ++ ++ struct semaphore sdsem; ++ ++ const char *fw_name; ++ const struct firmware *firmware; ++ const char *nv_name; ++ u32 fw_ptr; ++}; ++ ++struct sbconfig { ++ u32 PAD[2]; ++ u32 sbipsflag; /* initiator port ocp slave flag */ ++ u32 PAD[3]; ++ u32 sbtpsflag; /* target port ocp slave flag */ ++ u32 PAD[11]; ++ u32 sbtmerrloga; /* (sonics >= 2.3) */ ++ u32 PAD; ++ u32 sbtmerrlog; /* (sonics >= 2.3) */ ++ u32 PAD[3]; ++ u32 sbadmatch3; /* address match3 */ ++ u32 PAD; ++ u32 sbadmatch2; /* address match2 */ ++ u32 PAD; ++ u32 sbadmatch1; /* address match1 */ ++ u32 PAD[7]; ++ u32 sbimstate; /* initiator agent state */ ++ u32 sbintvec; /* interrupt mask */ ++ u32 sbtmstatelow; /* target state */ ++ u32 sbtmstatehigh; /* target state */ ++ u32 sbbwa0; /* bandwidth allocation table0 */ ++ u32 PAD; ++ u32 sbimconfiglow; /* initiator configuration */ ++ u32 sbimconfighigh; /* initiator configuration */ ++ u32 sbadmatch0; /* address match0 */ ++ u32 PAD; ++ u32 sbtmconfiglow; /* target configuration */ ++ u32 sbtmconfighigh; /* target configuration */ ++ u32 sbbconfig; /* broadcast configuration */ ++ u32 PAD; ++ u32 sbbstate; /* broadcast state */ ++ u32 PAD[3]; ++ u32 sbactcnfg; /* activate configuration */ ++ u32 PAD[3]; ++ u32 sbflagst; /* current sbflags */ ++ u32 PAD[3]; ++ u32 sbidlow; /* identification */ ++ u32 sbidhigh; /* identification */ ++}; ++ ++/* clkstate */ ++#define CLK_NONE 0 ++#define CLK_SDONLY 1 ++#define CLK_PENDING 2 /* Not used yet */ ++#define CLK_AVAIL 3 ++ ++#ifdef BCMDBG ++static int qcount[NUMPRIO]; ++static int tx_packets[NUMPRIO]; ++#endif /* BCMDBG */ ++ ++#define SDIO_DRIVE_STRENGTH 6 /* in milliamps */ ++ ++#define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL) ++ ++/* Retry count for register access failures */ ++static const uint retry_limit = 2; ++ ++/* Limit on rounding up frames */ ++static const uint max_roundup = 512; ++ ++#define ALIGNMENT 4 ++ ++static void pkt_align(struct sk_buff *p, int len, int align) ++{ ++ uint datalign; ++ datalign = (unsigned long)(p->data); ++ datalign = roundup(datalign, (align)) - datalign; ++ if (datalign) ++ skb_pull(p, datalign); ++ __skb_trim(p, len); ++} ++ ++/* To check if there's window offered */ ++static bool data_ok(struct brcmf_bus *bus) ++{ ++ return (u8)(bus->tx_max - bus->tx_seq) != 0 && ++ ((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0; ++} ++ ++/* ++ * Reads a register in the SDIO hardware block. This block occupies a series of ++ * adresses on the 32 bit backplane bus. ++ */ ++static void ++r_sdreg32(struct brcmf_bus *bus, u32 *regvar, u32 reg_offset, u32 *retryvar) ++{ ++ *retryvar = 0; ++ do { ++ *regvar = brcmf_sdcard_reg_read(bus->sdiodev, ++ bus->ci->buscorebase + reg_offset, sizeof(u32)); ++ } while (brcmf_sdcard_regfail(bus->sdiodev) && ++ (++(*retryvar) <= retry_limit)); ++ if (*retryvar) { ++ bus->regfails += (*retryvar-1); ++ if (*retryvar > retry_limit) { ++ brcmf_dbg(ERROR, "FAILED READ %Xh\n", reg_offset); ++ *regvar = 0; ++ } ++ } ++} ++ ++static void ++w_sdreg32(struct brcmf_bus *bus, u32 regval, u32 reg_offset, u32 *retryvar) ++{ ++ *retryvar = 0; ++ do { ++ brcmf_sdcard_reg_write(bus->sdiodev, ++ bus->ci->buscorebase + reg_offset, ++ sizeof(u32), regval); ++ } while (brcmf_sdcard_regfail(bus->sdiodev) && ++ (++(*retryvar) <= retry_limit)); ++ if (*retryvar) { ++ bus->regfails += (*retryvar-1); ++ if (*retryvar > retry_limit) ++ brcmf_dbg(ERROR, "FAILED REGISTER WRITE %Xh\n", ++ reg_offset); ++ } ++} ++ ++#define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND) ++ ++#define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) ++ ++/* Packet free applicable unconditionally for sdio and sdspi. ++ * Conditional if bufpool was present for gspi bus. ++ */ ++static void brcmf_sdbrcm_pktfree2(struct brcmf_bus *bus, struct sk_buff *pkt) ++{ ++ if (bus->usebufpool) ++ brcmu_pkt_buf_free_skb(pkt); ++} ++ ++/* Turn backplane clock on or off */ ++static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok) ++{ ++ int err; ++ u8 clkctl, clkreq, devctl; ++ unsigned long timeout; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ clkctl = 0; ++ ++ if (on) { ++ /* Request HT Avail */ ++ clkreq = ++ bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ; ++ ++ if ((bus->ci->chip == BCM4329_CHIP_ID) ++ && (bus->ci->chiprev == 0)) ++ clkreq |= SBSDIO_FORCE_ALP; ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); ++ if (err) { ++ brcmf_dbg(ERROR, "HT Avail request error: %d\n", err); ++ return -EBADE; ++ } ++ ++ if (pendok && ((bus->ci->buscoretype == PCMCIA_CORE_ID) ++ && (bus->ci->buscorerev == 9))) { ++ u32 dummy, retries; ++ r_sdreg32(bus, &dummy, ++ offsetof(struct sdpcmd_regs, clockctlstatus), ++ &retries); ++ } ++ ++ /* Check current status */ ++ clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ if (err) { ++ brcmf_dbg(ERROR, "HT Avail read error: %d\n", err); ++ return -EBADE; ++ } ++ ++ /* Go to pending and await interrupt if appropriate */ ++ if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) { ++ /* Allow only clock-available interrupt */ ++ devctl = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, &err); ++ if (err) { ++ brcmf_dbg(ERROR, "Devctl error setting CA: %d\n", ++ err); ++ return -EBADE; ++ } ++ ++ devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, devctl, &err); ++ brcmf_dbg(INFO, "CLKCTL: set PENDING\n"); ++ bus->clkstate = CLK_PENDING; ++ ++ return 0; ++ } else if (bus->clkstate == CLK_PENDING) { ++ /* Cancel CA-only interrupt filter */ ++ devctl = ++ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, &err); ++ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, devctl, &err); ++ } ++ ++ /* Otherwise, wait here (polling) for HT Avail */ ++ timeout = jiffies + ++ msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000); ++ while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { ++ clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, ++ &err); ++ if (time_after(jiffies, timeout)) ++ break; ++ else ++ usleep_range(5000, 10000); ++ } ++ if (err) { ++ brcmf_dbg(ERROR, "HT Avail request error: %d\n", err); ++ return -EBADE; ++ } ++ if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { ++ brcmf_dbg(ERROR, "HT Avail timeout (%d): clkctl 0x%02x\n", ++ PMU_MAX_TRANSITION_DLY, clkctl); ++ return -EBADE; ++ } ++ ++ /* Mark clock available */ ++ bus->clkstate = CLK_AVAIL; ++ brcmf_dbg(INFO, "CLKCTL: turned ON\n"); ++ ++#if defined(BCMDBG) ++ if (bus->alp_only != true) { ++ if (SBSDIO_ALPONLY(clkctl)) ++ brcmf_dbg(ERROR, "HT Clock should be on\n"); ++ } ++#endif /* defined (BCMDBG) */ ++ ++ bus->activity = true; ++ } else { ++ clkreq = 0; ++ ++ if (bus->clkstate == CLK_PENDING) { ++ /* Cancel CA-only interrupt filter */ ++ devctl = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, &err); ++ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, devctl, &err); ++ } ++ ++ bus->clkstate = CLK_SDONLY; ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); ++ brcmf_dbg(INFO, "CLKCTL: turned OFF\n"); ++ if (err) { ++ brcmf_dbg(ERROR, "Failed access turning clock off: %d\n", ++ err); ++ return -EBADE; ++ } ++ } ++ return 0; ++} ++ ++/* Change idle/active SD state */ ++static int brcmf_sdbrcm_sdclk(struct brcmf_bus *bus, bool on) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (on) ++ bus->clkstate = CLK_SDONLY; ++ else ++ bus->clkstate = CLK_NONE; ++ ++ return 0; ++} ++ ++/* Transition SD and backplane clock readiness */ ++static int brcmf_sdbrcm_clkctl(struct brcmf_bus *bus, uint target, bool pendok) ++{ ++#ifdef BCMDBG ++ uint oldstate = bus->clkstate; ++#endif /* BCMDBG */ ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Early exit if we're already there */ ++ if (bus->clkstate == target) { ++ if (target == CLK_AVAIL) { ++ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); ++ bus->activity = true; ++ } ++ return 0; ++ } ++ ++ switch (target) { ++ case CLK_AVAIL: ++ /* Make sure SD clock is available */ ++ if (bus->clkstate == CLK_NONE) ++ brcmf_sdbrcm_sdclk(bus, true); ++ /* Now request HT Avail on the backplane */ ++ brcmf_sdbrcm_htclk(bus, true, pendok); ++ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); ++ bus->activity = true; ++ break; ++ ++ case CLK_SDONLY: ++ /* Remove HT request, or bring up SD clock */ ++ if (bus->clkstate == CLK_NONE) ++ brcmf_sdbrcm_sdclk(bus, true); ++ else if (bus->clkstate == CLK_AVAIL) ++ brcmf_sdbrcm_htclk(bus, false, false); ++ else ++ brcmf_dbg(ERROR, "request for %d -> %d\n", ++ bus->clkstate, target); ++ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); ++ break; ++ ++ case CLK_NONE: ++ /* Make sure to remove HT request */ ++ if (bus->clkstate == CLK_AVAIL) ++ brcmf_sdbrcm_htclk(bus, false, false); ++ /* Now remove the SD clock */ ++ brcmf_sdbrcm_sdclk(bus, false); ++ brcmf_sdbrcm_wd_timer(bus, 0); ++ break; ++ } ++#ifdef BCMDBG ++ brcmf_dbg(INFO, "%d -> %d\n", oldstate, bus->clkstate); ++#endif /* BCMDBG */ ++ ++ return 0; ++} ++ ++static int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep) ++{ ++ uint retries = 0; ++ ++ brcmf_dbg(INFO, "request %s (currently %s)\n", ++ sleep ? "SLEEP" : "WAKE", ++ bus->sleeping ? "SLEEP" : "WAKE"); ++ ++ /* Done if we're already in the requested state */ ++ if (sleep == bus->sleeping) ++ return 0; ++ ++ /* Going to sleep: set the alarm and turn off the lights... */ ++ if (sleep) { ++ /* Don't sleep if something is pending */ ++ if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq)) ++ return -EBUSY; ++ ++ /* Make sure the controller has the bus up */ ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); ++ ++ /* Tell device to start using OOB wakeup */ ++ w_sdreg32(bus, SMB_USE_OOB, ++ offsetof(struct sdpcmd_regs, tosbmailbox), &retries); ++ if (retries > retry_limit) ++ brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"); ++ ++ /* Turn off our contribution to the HT clock request */ ++ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, ++ SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); ++ ++ /* Isolate the bus */ ++ if (bus->ci->chip != BCM4329_CHIP_ID) { ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, ++ SBSDIO_DEVCTL_PADS_ISO, NULL); ++ } ++ ++ /* Change state */ ++ bus->sleeping = true; ++ ++ } else { ++ /* Waking up: bus power up is ok, set local state */ ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); ++ ++ /* Force pad isolation off if possible ++ (in case power never toggled) */ ++ if ((bus->ci->buscoretype == PCMCIA_CORE_ID) ++ && (bus->ci->buscorerev >= 10)) ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, 0, NULL); ++ ++ /* Make sure the controller has the bus up */ ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); ++ ++ /* Send misc interrupt to indicate OOB not needed */ ++ w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, tosbmailboxdata), ++ &retries); ++ if (retries <= retry_limit) ++ w_sdreg32(bus, SMB_DEV_INT, ++ offsetof(struct sdpcmd_regs, tosbmailbox), ++ &retries); ++ ++ if (retries > retry_limit) ++ brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"); ++ ++ /* Make sure we have SD bus access */ ++ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); ++ ++ /* Change state */ ++ bus->sleeping = false; ++ } ++ ++ return 0; ++} ++ ++static void bus_wake(struct brcmf_bus *bus) ++{ ++ if (bus->sleeping) ++ brcmf_sdbrcm_bussleep(bus, false); ++} ++ ++static u32 brcmf_sdbrcm_hostmail(struct brcmf_bus *bus) ++{ ++ u32 intstatus = 0; ++ u32 hmb_data; ++ u8 fcbits; ++ uint retries = 0; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Read mailbox data and ack that we did so */ ++ r_sdreg32(bus, &hmb_data, ++ offsetof(struct sdpcmd_regs, tohostmailboxdata), &retries); ++ ++ if (retries <= retry_limit) ++ w_sdreg32(bus, SMB_INT_ACK, ++ offsetof(struct sdpcmd_regs, tosbmailbox), &retries); ++ bus->f1regdata += 2; ++ ++ /* Dongle recomposed rx frames, accept them again */ ++ if (hmb_data & HMB_DATA_NAKHANDLED) { ++ brcmf_dbg(INFO, "Dongle reports NAK handled, expect rtx of %d\n", ++ bus->rx_seq); ++ if (!bus->rxskip) ++ brcmf_dbg(ERROR, "unexpected NAKHANDLED!\n"); ++ ++ bus->rxskip = false; ++ intstatus |= I_HMB_FRAME_IND; ++ } ++ ++ /* ++ * DEVREADY does not occur with gSPI. ++ */ ++ if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) { ++ bus->sdpcm_ver = ++ (hmb_data & HMB_DATA_VERSION_MASK) >> ++ HMB_DATA_VERSION_SHIFT; ++ if (bus->sdpcm_ver != SDPCM_PROT_VERSION) ++ brcmf_dbg(ERROR, "Version mismatch, dongle reports %d, " ++ "expecting %d\n", ++ bus->sdpcm_ver, SDPCM_PROT_VERSION); ++ else ++ brcmf_dbg(INFO, "Dongle ready, protocol version %d\n", ++ bus->sdpcm_ver); ++ } ++ ++ /* ++ * Flow Control has been moved into the RX headers and this out of band ++ * method isn't used any more. ++ * remaining backward compatible with older dongles. ++ */ ++ if (hmb_data & HMB_DATA_FC) { ++ fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >> ++ HMB_DATA_FCDATA_SHIFT; ++ ++ if (fcbits & ~bus->flowcontrol) ++ bus->fc_xoff++; ++ ++ if (bus->flowcontrol & ~fcbits) ++ bus->fc_xon++; ++ ++ bus->fc_rcvd++; ++ bus->flowcontrol = fcbits; ++ } ++ ++ /* Shouldn't be any others */ ++ if (hmb_data & ~(HMB_DATA_DEVREADY | ++ HMB_DATA_NAKHANDLED | ++ HMB_DATA_FC | ++ HMB_DATA_FWREADY | ++ HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK)) ++ brcmf_dbg(ERROR, "Unknown mailbox data content: 0x%02x\n", ++ hmb_data); ++ ++ return intstatus; ++} ++ ++static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx) ++{ ++ uint retries = 0; ++ u16 lastrbc; ++ u8 hi, lo; ++ int err; ++ ++ brcmf_dbg(ERROR, "%sterminate frame%s\n", ++ abort ? "abort command, " : "", ++ rtx ? ", send NAK" : ""); ++ ++ if (abort) ++ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_FRAMECTRL, ++ SFC_RF_TERM, &err); ++ bus->f1regdata++; ++ ++ /* Wait until the packet has been flushed (device/FIFO stable) */ ++ for (lastrbc = retries = 0xffff; retries > 0; retries--) { ++ hi = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_RFRAMEBCHI, NULL); ++ lo = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_RFRAMEBCLO, NULL); ++ bus->f1regdata += 2; ++ ++ if ((hi == 0) && (lo == 0)) ++ break; ++ ++ if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) { ++ brcmf_dbg(ERROR, "count growing: last 0x%04x now 0x%04x\n", ++ lastrbc, (hi << 8) + lo); ++ } ++ lastrbc = (hi << 8) + lo; ++ } ++ ++ if (!retries) ++ brcmf_dbg(ERROR, "count never zeroed: last 0x%04x\n", lastrbc); ++ else ++ brcmf_dbg(INFO, "flush took %d iterations\n", 0xffff - retries); ++ ++ if (rtx) { ++ bus->rxrtx++; ++ w_sdreg32(bus, SMB_NAK, ++ offsetof(struct sdpcmd_regs, tosbmailbox), &retries); ++ ++ bus->f1regdata++; ++ if (retries <= retry_limit) ++ bus->rxskip = true; ++ } ++ ++ /* Clear partial in any case */ ++ bus->nextlen = 0; ++ ++ /* If we can't reach the device, signal failure */ ++ if (err || brcmf_sdcard_regfail(bus->sdiodev)) ++ bus->drvr->busstate = BRCMF_BUS_DOWN; ++} ++ ++static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq) ++{ ++ u16 dlen, totlen; ++ u8 *dptr, num = 0; ++ ++ u16 sublen, check; ++ struct sk_buff *pfirst, *plast, *pnext, *save_pfirst; ++ ++ int errcode; ++ u8 chan, seq, doff, sfdoff; ++ u8 txmax; ++ ++ int ifidx = 0; ++ bool usechain = bus->use_rxchain; ++ ++ /* If packets, issue read(s) and send up packet chain */ ++ /* Return sequence numbers consumed? */ ++ ++ brcmf_dbg(TRACE, "start: glomd %p glom %p\n", bus->glomd, bus->glom); ++ ++ /* If there's a descriptor, generate the packet chain */ ++ if (bus->glomd) { ++ pfirst = plast = pnext = NULL; ++ dlen = (u16) (bus->glomd->len); ++ dptr = bus->glomd->data; ++ if (!dlen || (dlen & 1)) { ++ brcmf_dbg(ERROR, "bad glomd len(%d), ignore descriptor\n", ++ dlen); ++ dlen = 0; ++ } ++ ++ for (totlen = num = 0; dlen; num++) { ++ /* Get (and move past) next length */ ++ sublen = get_unaligned_le16(dptr); ++ dlen -= sizeof(u16); ++ dptr += sizeof(u16); ++ if ((sublen < SDPCM_HDRLEN) || ++ ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) { ++ brcmf_dbg(ERROR, "descriptor len %d bad: %d\n", ++ num, sublen); ++ pnext = NULL; ++ break; ++ } ++ if (sublen % BRCMF_SDALIGN) { ++ brcmf_dbg(ERROR, "sublen %d not multiple of %d\n", ++ sublen, BRCMF_SDALIGN); ++ usechain = false; ++ } ++ totlen += sublen; ++ ++ /* For last frame, adjust read len so total ++ is a block multiple */ ++ if (!dlen) { ++ sublen += ++ (roundup(totlen, bus->blocksize) - totlen); ++ totlen = roundup(totlen, bus->blocksize); ++ } ++ ++ /* Allocate/chain packet for next subframe */ ++ pnext = brcmu_pkt_buf_get_skb(sublen + BRCMF_SDALIGN); ++ if (pnext == NULL) { ++ brcmf_dbg(ERROR, "bcm_pkt_buf_get_skb failed, num %d len %d\n", ++ num, sublen); ++ break; ++ } ++ if (!pfirst) { ++ pfirst = plast = pnext; ++ } else { ++ plast->next = pnext; ++ plast = pnext; ++ } ++ ++ /* Adhere to start alignment requirements */ ++ pkt_align(pnext, sublen, BRCMF_SDALIGN); ++ } ++ ++ /* If all allocations succeeded, save packet chain ++ in bus structure */ ++ if (pnext) { ++ brcmf_dbg(GLOM, "allocated %d-byte packet chain for %d subframes\n", ++ totlen, num); ++ if (BRCMF_GLOM_ON() && bus->nextlen && ++ totlen != bus->nextlen) { ++ brcmf_dbg(GLOM, "glomdesc mismatch: nextlen %d glomdesc %d rxseq %d\n", ++ bus->nextlen, totlen, rxseq); ++ } ++ bus->glom = pfirst; ++ pfirst = pnext = NULL; ++ } else { ++ if (pfirst) ++ brcmu_pkt_buf_free_skb(pfirst); ++ bus->glom = NULL; ++ num = 0; ++ } ++ ++ /* Done with descriptor packet */ ++ brcmu_pkt_buf_free_skb(bus->glomd); ++ bus->glomd = NULL; ++ bus->nextlen = 0; ++ } ++ ++ /* Ok -- either we just generated a packet chain, ++ or had one from before */ ++ if (bus->glom) { ++ if (BRCMF_GLOM_ON()) { ++ brcmf_dbg(GLOM, "try superframe read, packet chain:\n"); ++ for (pnext = bus->glom; pnext; pnext = pnext->next) { ++ brcmf_dbg(GLOM, " %p: %p len 0x%04x (%d)\n", ++ pnext, (u8 *) (pnext->data), ++ pnext->len, pnext->len); ++ } ++ } ++ ++ pfirst = bus->glom; ++ dlen = (u16) brcmu_pkttotlen(pfirst); ++ ++ /* Do an SDIO read for the superframe. Configurable iovar to ++ * read directly into the chained packet, or allocate a large ++ * packet and and copy into the chain. ++ */ ++ if (usechain) { ++ errcode = brcmf_sdcard_recv_buf(bus->sdiodev, ++ bus->sdiodev->sbwad, ++ SDIO_FUNC_2, ++ F2SYNC, (u8 *) pfirst->data, dlen, ++ pfirst); ++ } else if (bus->dataptr) { ++ errcode = brcmf_sdcard_recv_buf(bus->sdiodev, ++ bus->sdiodev->sbwad, ++ SDIO_FUNC_2, ++ F2SYNC, bus->dataptr, dlen, ++ NULL); ++ sublen = (u16) brcmu_pktfrombuf(pfirst, 0, dlen, ++ bus->dataptr); ++ if (sublen != dlen) { ++ brcmf_dbg(ERROR, "FAILED TO COPY, dlen %d sublen %d\n", ++ dlen, sublen); ++ errcode = -1; ++ } ++ pnext = NULL; ++ } else { ++ brcmf_dbg(ERROR, "COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", ++ dlen); ++ errcode = -1; ++ } ++ bus->f2rxdata++; ++ ++ /* On failure, kill the superframe, allow a couple retries */ ++ if (errcode < 0) { ++ brcmf_dbg(ERROR, "glom read of %d bytes failed: %d\n", ++ dlen, errcode); ++ bus->drvr->rx_errors++; ++ ++ if (bus->glomerr++ < 3) { ++ brcmf_sdbrcm_rxfail(bus, true, true); ++ } else { ++ bus->glomerr = 0; ++ brcmf_sdbrcm_rxfail(bus, true, false); ++ brcmu_pkt_buf_free_skb(bus->glom); ++ bus->rxglomfail++; ++ bus->glom = NULL; ++ } ++ return 0; ++ } ++#ifdef BCMDBG ++ if (BRCMF_GLOM_ON()) { ++ printk(KERN_DEBUG "SUPERFRAME:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ pfirst->data, min_t(int, pfirst->len, 48)); ++ } ++#endif ++ ++ /* Validate the superframe header */ ++ dptr = (u8 *) (pfirst->data); ++ sublen = get_unaligned_le16(dptr); ++ check = get_unaligned_le16(dptr + sizeof(u16)); ++ ++ chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); ++ seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); ++ bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; ++ if ((bus->nextlen << 4) > MAX_RX_DATASZ) { ++ brcmf_dbg(INFO, "nextlen too large (%d) seq %d\n", ++ bus->nextlen, seq); ++ bus->nextlen = 0; ++ } ++ doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); ++ txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); ++ ++ errcode = 0; ++ if ((u16)~(sublen ^ check)) { ++ brcmf_dbg(ERROR, "(superframe): HW hdr error: len/check 0x%04x/0x%04x\n", ++ sublen, check); ++ errcode = -1; ++ } else if (roundup(sublen, bus->blocksize) != dlen) { ++ brcmf_dbg(ERROR, "(superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n", ++ sublen, roundup(sublen, bus->blocksize), ++ dlen); ++ errcode = -1; ++ } else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) != ++ SDPCM_GLOM_CHANNEL) { ++ brcmf_dbg(ERROR, "(superframe): bad channel %d\n", ++ SDPCM_PACKET_CHANNEL( ++ &dptr[SDPCM_FRAMETAG_LEN])); ++ errcode = -1; ++ } else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) { ++ brcmf_dbg(ERROR, "(superframe): got 2nd descriptor?\n"); ++ errcode = -1; ++ } else if ((doff < SDPCM_HDRLEN) || ++ (doff > (pfirst->len - SDPCM_HDRLEN))) { ++ brcmf_dbg(ERROR, "(superframe): Bad data offset %d: HW %d pkt %d min %d\n", ++ doff, sublen, pfirst->len, SDPCM_HDRLEN); ++ errcode = -1; ++ } ++ ++ /* Check sequence number of superframe SW header */ ++ if (rxseq != seq) { ++ brcmf_dbg(INFO, "(superframe) rx_seq %d, expected %d\n", ++ seq, rxseq); ++ bus->rx_badseq++; ++ rxseq = seq; ++ } ++ ++ /* Check window for sanity */ ++ if ((u8) (txmax - bus->tx_seq) > 0x40) { ++ brcmf_dbg(ERROR, "unlikely tx max %d with tx_seq %d\n", ++ txmax, bus->tx_seq); ++ txmax = bus->tx_seq + 2; ++ } ++ bus->tx_max = txmax; ++ ++ /* Remove superframe header, remember offset */ ++ skb_pull(pfirst, doff); ++ sfdoff = doff; ++ ++ /* Validate all the subframe headers */ ++ for (num = 0, pnext = pfirst; pnext && !errcode; ++ num++, pnext = pnext->next) { ++ dptr = (u8 *) (pnext->data); ++ dlen = (u16) (pnext->len); ++ sublen = get_unaligned_le16(dptr); ++ check = get_unaligned_le16(dptr + sizeof(u16)); ++ chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); ++ doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); ++#ifdef BCMDBG ++ if (BRCMF_GLOM_ON()) { ++ printk(KERN_DEBUG "subframe:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ dptr, 32); ++ } ++#endif ++ ++ if ((u16)~(sublen ^ check)) { ++ brcmf_dbg(ERROR, "(subframe %d): HW hdr error: len/check 0x%04x/0x%04x\n", ++ num, sublen, check); ++ errcode = -1; ++ } else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) { ++ brcmf_dbg(ERROR, "(subframe %d): length mismatch: len 0x%04x, expect 0x%04x\n", ++ num, sublen, dlen); ++ errcode = -1; ++ } else if ((chan != SDPCM_DATA_CHANNEL) && ++ (chan != SDPCM_EVENT_CHANNEL)) { ++ brcmf_dbg(ERROR, "(subframe %d): bad channel %d\n", ++ num, chan); ++ errcode = -1; ++ } else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) { ++ brcmf_dbg(ERROR, "(subframe %d): Bad data offset %d: HW %d min %d\n", ++ num, doff, sublen, SDPCM_HDRLEN); ++ errcode = -1; ++ } ++ } ++ ++ if (errcode) { ++ /* Terminate frame on error, request ++ a couple retries */ ++ if (bus->glomerr++ < 3) { ++ /* Restore superframe header space */ ++ skb_push(pfirst, sfdoff); ++ brcmf_sdbrcm_rxfail(bus, true, true); ++ } else { ++ bus->glomerr = 0; ++ brcmf_sdbrcm_rxfail(bus, true, false); ++ brcmu_pkt_buf_free_skb(bus->glom); ++ bus->rxglomfail++; ++ bus->glom = NULL; ++ } ++ bus->nextlen = 0; ++ return 0; ++ } ++ ++ /* Basic SD framing looks ok - process each packet (header) */ ++ save_pfirst = pfirst; ++ bus->glom = NULL; ++ plast = NULL; ++ ++ for (num = 0; pfirst; rxseq++, pfirst = pnext) { ++ pnext = pfirst->next; ++ pfirst->next = NULL; ++ ++ dptr = (u8 *) (pfirst->data); ++ sublen = get_unaligned_le16(dptr); ++ chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); ++ seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); ++ doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); ++ ++ brcmf_dbg(GLOM, "Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n", ++ num, pfirst, pfirst->data, ++ pfirst->len, sublen, chan, seq); ++ ++ /* precondition: chan == SDPCM_DATA_CHANNEL || ++ chan == SDPCM_EVENT_CHANNEL */ ++ ++ if (rxseq != seq) { ++ brcmf_dbg(GLOM, "rx_seq %d, expected %d\n", ++ seq, rxseq); ++ bus->rx_badseq++; ++ rxseq = seq; ++ } ++#ifdef BCMDBG ++ if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) { ++ printk(KERN_DEBUG "Rx Subframe Data:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ dptr, dlen); ++ } ++#endif ++ ++ __skb_trim(pfirst, sublen); ++ skb_pull(pfirst, doff); ++ ++ if (pfirst->len == 0) { ++ brcmu_pkt_buf_free_skb(pfirst); ++ if (plast) ++ plast->next = pnext; ++ else ++ save_pfirst = pnext; ++ ++ continue; ++ } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, ++ pfirst) != 0) { ++ brcmf_dbg(ERROR, "rx protocol error\n"); ++ bus->drvr->rx_errors++; ++ brcmu_pkt_buf_free_skb(pfirst); ++ if (plast) ++ plast->next = pnext; ++ else ++ save_pfirst = pnext; ++ ++ continue; ++ } ++ ++ /* this packet will go up, link back into ++ chain and count it */ ++ pfirst->next = pnext; ++ plast = pfirst; ++ num++; ++ ++#ifdef BCMDBG ++ if (BRCMF_GLOM_ON()) { ++ brcmf_dbg(GLOM, "subframe %d to stack, %p (%p/%d) nxt/lnk %p/%p\n", ++ num, pfirst, pfirst->data, ++ pfirst->len, pfirst->next, ++ pfirst->prev); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ pfirst->data, ++ min_t(int, pfirst->len, 32)); ++ } ++#endif /* BCMDBG */ ++ } ++ if (num) { ++ up(&bus->sdsem); ++ brcmf_rx_frame(bus->drvr, ifidx, save_pfirst, num); ++ down(&bus->sdsem); ++ } ++ ++ bus->rxglomframes++; ++ bus->rxglompkts += num; ++ } ++ return num; ++} ++ ++static int brcmf_sdbrcm_dcmd_resp_wait(struct brcmf_bus *bus, uint *condition, ++ bool *pending) ++{ ++ DECLARE_WAITQUEUE(wait, current); ++ int timeout = msecs_to_jiffies(DCMD_RESP_TIMEOUT); ++ ++ /* Wait until control frame is available */ ++ add_wait_queue(&bus->dcmd_resp_wait, &wait); ++ set_current_state(TASK_INTERRUPTIBLE); ++ ++ while (!(*condition) && (!signal_pending(current) && timeout)) ++ timeout = schedule_timeout(timeout); ++ ++ if (signal_pending(current)) ++ *pending = true; ++ ++ set_current_state(TASK_RUNNING); ++ remove_wait_queue(&bus->dcmd_resp_wait, &wait); ++ ++ return timeout; ++} ++ ++static int brcmf_sdbrcm_dcmd_resp_wake(struct brcmf_bus *bus) ++{ ++ if (waitqueue_active(&bus->dcmd_resp_wait)) ++ wake_up_interruptible(&bus->dcmd_resp_wait); ++ ++ return 0; ++} ++static void ++brcmf_sdbrcm_read_control(struct brcmf_bus *bus, u8 *hdr, uint len, uint doff) ++{ ++ uint rdlen, pad; ++ ++ int sdret; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Set rxctl for frame (w/optional alignment) */ ++ bus->rxctl = bus->rxbuf; ++ bus->rxctl += BRCMF_FIRSTREAD; ++ pad = ((unsigned long)bus->rxctl % BRCMF_SDALIGN); ++ if (pad) ++ bus->rxctl += (BRCMF_SDALIGN - pad); ++ bus->rxctl -= BRCMF_FIRSTREAD; ++ ++ /* Copy the already-read portion over */ ++ memcpy(bus->rxctl, hdr, BRCMF_FIRSTREAD); ++ if (len <= BRCMF_FIRSTREAD) ++ goto gotpkt; ++ ++ /* Raise rdlen to next SDIO block to avoid tail command */ ++ rdlen = len - BRCMF_FIRSTREAD; ++ if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) { ++ pad = bus->blocksize - (rdlen % bus->blocksize); ++ if ((pad <= bus->roundup) && (pad < bus->blocksize) && ++ ((len + pad) < bus->drvr->maxctl)) ++ rdlen += pad; ++ } else if (rdlen % BRCMF_SDALIGN) { ++ rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN); ++ } ++ ++ /* Satisfy length-alignment requirements */ ++ if (rdlen & (ALIGNMENT - 1)) ++ rdlen = roundup(rdlen, ALIGNMENT); ++ ++ /* Drop if the read is too big or it exceeds our maximum */ ++ if ((rdlen + BRCMF_FIRSTREAD) > bus->drvr->maxctl) { ++ brcmf_dbg(ERROR, "%d-byte control read exceeds %d-byte buffer\n", ++ rdlen, bus->drvr->maxctl); ++ bus->drvr->rx_errors++; ++ brcmf_sdbrcm_rxfail(bus, false, false); ++ goto done; ++ } ++ ++ if ((len - doff) > bus->drvr->maxctl) { ++ brcmf_dbg(ERROR, "%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n", ++ len, len - doff, bus->drvr->maxctl); ++ bus->drvr->rx_errors++; ++ bus->rx_toolong++; ++ brcmf_sdbrcm_rxfail(bus, false, false); ++ goto done; ++ } ++ ++ /* Read remainder of frame body into the rxctl buffer */ ++ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, ++ bus->sdiodev->sbwad, ++ SDIO_FUNC_2, ++ F2SYNC, (bus->rxctl + BRCMF_FIRSTREAD), rdlen, ++ NULL); ++ bus->f2rxdata++; ++ ++ /* Control frame failures need retransmission */ ++ if (sdret < 0) { ++ brcmf_dbg(ERROR, "read %d control bytes failed: %d\n", ++ rdlen, sdret); ++ bus->rxc_errors++; ++ brcmf_sdbrcm_rxfail(bus, true, true); ++ goto done; ++ } ++ ++gotpkt: ++ ++#ifdef BCMDBG ++ if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) { ++ printk(KERN_DEBUG "RxCtrl:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, bus->rxctl, len); ++ } ++#endif ++ ++ /* Point to valid data and indicate its length */ ++ bus->rxctl += doff; ++ bus->rxlen = len - doff; ++ ++done: ++ /* Awake any waiters */ ++ brcmf_sdbrcm_dcmd_resp_wake(bus); ++} ++ ++/* Pad read to blocksize for efficiency */ ++static void brcmf_pad(struct brcmf_bus *bus, u16 *pad, u16 *rdlen) ++{ ++ if (bus->roundup && bus->blocksize && *rdlen > bus->blocksize) { ++ *pad = bus->blocksize - (*rdlen % bus->blocksize); ++ if (*pad <= bus->roundup && *pad < bus->blocksize && ++ *rdlen + *pad + BRCMF_FIRSTREAD < MAX_RX_DATASZ) ++ *rdlen += *pad; ++ } else if (*rdlen % BRCMF_SDALIGN) { ++ *rdlen += BRCMF_SDALIGN - (*rdlen % BRCMF_SDALIGN); ++ } ++} ++ ++static void ++brcmf_alloc_pkt_and_read(struct brcmf_bus *bus, u16 rdlen, ++ struct sk_buff **pkt, u8 **rxbuf) ++{ ++ int sdret; /* Return code from calls */ ++ ++ *pkt = brcmu_pkt_buf_get_skb(rdlen + BRCMF_SDALIGN); ++ if (*pkt == NULL) ++ return; ++ ++ pkt_align(*pkt, rdlen, BRCMF_SDALIGN); ++ *rxbuf = (u8 *) ((*pkt)->data); ++ /* Read the entire frame */ ++ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, ++ SDIO_FUNC_2, F2SYNC, ++ *rxbuf, rdlen, *pkt); ++ bus->f2rxdata++; ++ ++ if (sdret < 0) { ++ brcmf_dbg(ERROR, "(nextlen): read %d bytes failed: %d\n", ++ rdlen, sdret); ++ brcmu_pkt_buf_free_skb(*pkt); ++ bus->drvr->rx_errors++; ++ /* Force retry w/normal header read. ++ * Don't attempt NAK for ++ * gSPI ++ */ ++ brcmf_sdbrcm_rxfail(bus, true, true); ++ *pkt = NULL; ++ } ++} ++ ++/* Checks the header */ ++static int ++brcmf_check_rxbuf(struct brcmf_bus *bus, struct sk_buff *pkt, u8 *rxbuf, ++ u8 rxseq, u16 nextlen, u16 *len) ++{ ++ u16 check; ++ bool len_consistent; /* Result of comparing readahead len and ++ len from hw-hdr */ ++ ++ memcpy(bus->rxhdr, rxbuf, SDPCM_HDRLEN); ++ ++ /* Extract hardware header fields */ ++ *len = get_unaligned_le16(bus->rxhdr); ++ check = get_unaligned_le16(bus->rxhdr + sizeof(u16)); ++ ++ /* All zeros means readahead info was bad */ ++ if (!(*len | check)) { ++ brcmf_dbg(INFO, "(nextlen): read zeros in HW header???\n"); ++ goto fail; ++ } ++ ++ /* Validate check bytes */ ++ if ((u16)~(*len ^ check)) { ++ brcmf_dbg(ERROR, "(nextlen): HW hdr error: nextlen/len/check 0x%04x/0x%04x/0x%04x\n", ++ nextlen, *len, check); ++ bus->rx_badhdr++; ++ brcmf_sdbrcm_rxfail(bus, false, false); ++ goto fail; ++ } ++ ++ /* Validate frame length */ ++ if (*len < SDPCM_HDRLEN) { ++ brcmf_dbg(ERROR, "(nextlen): HW hdr length invalid: %d\n", ++ *len); ++ goto fail; ++ } ++ ++ /* Check for consistency with readahead info */ ++ len_consistent = (nextlen != (roundup(*len, 16) >> 4)); ++ if (len_consistent) { ++ /* Mismatch, force retry w/normal ++ header (may be >4K) */ ++ brcmf_dbg(ERROR, "(nextlen): mismatch, nextlen %d len %d rnd %d; expected rxseq %d\n", ++ nextlen, *len, roundup(*len, 16), ++ rxseq); ++ brcmf_sdbrcm_rxfail(bus, true, true); ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ brcmf_sdbrcm_pktfree2(bus, pkt); ++ return -EINVAL; ++} ++ ++/* Return true if there may be more frames to read */ ++static uint ++brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished) ++{ ++ u16 len, check; /* Extracted hardware header fields */ ++ u8 chan, seq, doff; /* Extracted software header fields */ ++ u8 fcbits; /* Extracted fcbits from software header */ ++ ++ struct sk_buff *pkt; /* Packet for event or data frames */ ++ u16 pad; /* Number of pad bytes to read */ ++ u16 rdlen; /* Total number of bytes to read */ ++ u8 rxseq; /* Next sequence number to expect */ ++ uint rxleft = 0; /* Remaining number of frames allowed */ ++ int sdret; /* Return code from calls */ ++ u8 txmax; /* Maximum tx sequence offered */ ++ u8 *rxbuf; ++ int ifidx = 0; ++ uint rxcount = 0; /* Total frames read */ ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Not finished unless we encounter no more frames indication */ ++ *finished = false; ++ ++ for (rxseq = bus->rx_seq, rxleft = maxframes; ++ !bus->rxskip && rxleft && bus->drvr->busstate != BRCMF_BUS_DOWN; ++ rxseq++, rxleft--) { ++ ++ /* Handle glomming separately */ ++ if (bus->glom || bus->glomd) { ++ u8 cnt; ++ brcmf_dbg(GLOM, "calling rxglom: glomd %p, glom %p\n", ++ bus->glomd, bus->glom); ++ cnt = brcmf_sdbrcm_rxglom(bus, rxseq); ++ brcmf_dbg(GLOM, "rxglom returned %d\n", cnt); ++ rxseq += cnt - 1; ++ rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1; ++ continue; ++ } ++ ++ /* Try doing single read if we can */ ++ if (bus->nextlen) { ++ u16 nextlen = bus->nextlen; ++ bus->nextlen = 0; ++ ++ rdlen = len = nextlen << 4; ++ brcmf_pad(bus, &pad, &rdlen); ++ ++ /* ++ * After the frame is received we have to ++ * distinguish whether it is data ++ * or non-data frame. ++ */ ++ brcmf_alloc_pkt_and_read(bus, rdlen, &pkt, &rxbuf); ++ if (pkt == NULL) { ++ /* Give up on data, request rtx of events */ ++ brcmf_dbg(ERROR, "(nextlen): brcmf_alloc_pkt_and_read failed: len %d rdlen %d expected rxseq %d\n", ++ len, rdlen, rxseq); ++ continue; ++ } ++ ++ if (brcmf_check_rxbuf(bus, pkt, rxbuf, rxseq, nextlen, ++ &len) < 0) ++ continue; ++ ++ /* Extract software header fields */ ++ chan = SDPCM_PACKET_CHANNEL( ++ &bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ seq = SDPCM_PACKET_SEQUENCE( ++ &bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ doff = SDPCM_DOFFSET_VALUE( ++ &bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ txmax = SDPCM_WINDOW_VALUE( ++ &bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ ++ bus->nextlen = ++ bus->rxhdr[SDPCM_FRAMETAG_LEN + ++ SDPCM_NEXTLEN_OFFSET]; ++ if ((bus->nextlen << 4) > MAX_RX_DATASZ) { ++ brcmf_dbg(INFO, "(nextlen): got frame w/nextlen too large (%d), seq %d\n", ++ bus->nextlen, seq); ++ bus->nextlen = 0; ++ } ++ ++ bus->drvr->rx_readahead_cnt++; ++ ++ /* Handle Flow Control */ ++ fcbits = SDPCM_FCMASK_VALUE( ++ &bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ ++ if (bus->flowcontrol != fcbits) { ++ if (~bus->flowcontrol & fcbits) ++ bus->fc_xoff++; ++ ++ if (bus->flowcontrol & ~fcbits) ++ bus->fc_xon++; ++ ++ bus->fc_rcvd++; ++ bus->flowcontrol = fcbits; ++ } ++ ++ /* Check and update sequence number */ ++ if (rxseq != seq) { ++ brcmf_dbg(INFO, "(nextlen): rx_seq %d, expected %d\n", ++ seq, rxseq); ++ bus->rx_badseq++; ++ rxseq = seq; ++ } ++ ++ /* Check window for sanity */ ++ if ((u8) (txmax - bus->tx_seq) > 0x40) { ++ brcmf_dbg(ERROR, "got unlikely tx max %d with tx_seq %d\n", ++ txmax, bus->tx_seq); ++ txmax = bus->tx_seq + 2; ++ } ++ bus->tx_max = txmax; ++ ++#ifdef BCMDBG ++ if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) { ++ printk(KERN_DEBUG "Rx Data:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ rxbuf, len); ++ } else if (BRCMF_HDRS_ON()) { ++ printk(KERN_DEBUG "RxHdr:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ bus->rxhdr, SDPCM_HDRLEN); ++ } ++#endif ++ ++ if (chan == SDPCM_CONTROL_CHANNEL) { ++ brcmf_dbg(ERROR, "(nextlen): readahead on control packet %d?\n", ++ seq); ++ /* Force retry w/normal header read */ ++ bus->nextlen = 0; ++ brcmf_sdbrcm_rxfail(bus, false, true); ++ brcmf_sdbrcm_pktfree2(bus, pkt); ++ continue; ++ } ++ ++ /* Validate data offset */ ++ if ((doff < SDPCM_HDRLEN) || (doff > len)) { ++ brcmf_dbg(ERROR, "(nextlen): bad data offset %d: HW len %d min %d\n", ++ doff, len, SDPCM_HDRLEN); ++ brcmf_sdbrcm_rxfail(bus, false, false); ++ brcmf_sdbrcm_pktfree2(bus, pkt); ++ continue; ++ } ++ ++ /* All done with this one -- now deliver the packet */ ++ goto deliver; ++ } ++ ++ /* Read frame header (hardware and software) */ ++ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, ++ SDIO_FUNC_2, F2SYNC, bus->rxhdr, ++ BRCMF_FIRSTREAD, NULL); ++ bus->f2rxhdrs++; ++ ++ if (sdret < 0) { ++ brcmf_dbg(ERROR, "RXHEADER FAILED: %d\n", sdret); ++ bus->rx_hdrfail++; ++ brcmf_sdbrcm_rxfail(bus, true, true); ++ continue; ++ } ++#ifdef BCMDBG ++ if (BRCMF_BYTES_ON() || BRCMF_HDRS_ON()) { ++ printk(KERN_DEBUG "RxHdr:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ bus->rxhdr, SDPCM_HDRLEN); ++ } ++#endif ++ ++ /* Extract hardware header fields */ ++ len = get_unaligned_le16(bus->rxhdr); ++ check = get_unaligned_le16(bus->rxhdr + sizeof(u16)); ++ ++ /* All zeros means no more frames */ ++ if (!(len | check)) { ++ *finished = true; ++ break; ++ } ++ ++ /* Validate check bytes */ ++ if ((u16) ~(len ^ check)) { ++ brcmf_dbg(ERROR, "HW hdr err: len/check 0x%04x/0x%04x\n", ++ len, check); ++ bus->rx_badhdr++; ++ brcmf_sdbrcm_rxfail(bus, false, false); ++ continue; ++ } ++ ++ /* Validate frame length */ ++ if (len < SDPCM_HDRLEN) { ++ brcmf_dbg(ERROR, "HW hdr length invalid: %d\n", len); ++ continue; ++ } ++ ++ /* Extract software header fields */ ++ chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ ++ /* Validate data offset */ ++ if ((doff < SDPCM_HDRLEN) || (doff > len)) { ++ brcmf_dbg(ERROR, "Bad data offset %d: HW len %d, min %d seq %d\n", ++ doff, len, SDPCM_HDRLEN, seq); ++ bus->rx_badhdr++; ++ brcmf_sdbrcm_rxfail(bus, false, false); ++ continue; ++ } ++ ++ /* Save the readahead length if there is one */ ++ bus->nextlen = ++ bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; ++ if ((bus->nextlen << 4) > MAX_RX_DATASZ) { ++ brcmf_dbg(INFO, "(nextlen): got frame w/nextlen too large (%d), seq %d\n", ++ bus->nextlen, seq); ++ bus->nextlen = 0; ++ } ++ ++ /* Handle Flow Control */ ++ fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ ++ if (bus->flowcontrol != fcbits) { ++ if (~bus->flowcontrol & fcbits) ++ bus->fc_xoff++; ++ ++ if (bus->flowcontrol & ~fcbits) ++ bus->fc_xon++; ++ ++ bus->fc_rcvd++; ++ bus->flowcontrol = fcbits; ++ } ++ ++ /* Check and update sequence number */ ++ if (rxseq != seq) { ++ brcmf_dbg(INFO, "rx_seq %d, expected %d\n", seq, rxseq); ++ bus->rx_badseq++; ++ rxseq = seq; ++ } ++ ++ /* Check window for sanity */ ++ if ((u8) (txmax - bus->tx_seq) > 0x40) { ++ brcmf_dbg(ERROR, "unlikely tx max %d with tx_seq %d\n", ++ txmax, bus->tx_seq); ++ txmax = bus->tx_seq + 2; ++ } ++ bus->tx_max = txmax; ++ ++ /* Call a separate function for control frames */ ++ if (chan == SDPCM_CONTROL_CHANNEL) { ++ brcmf_sdbrcm_read_control(bus, bus->rxhdr, len, doff); ++ continue; ++ } ++ ++ /* precondition: chan is either SDPCM_DATA_CHANNEL, ++ SDPCM_EVENT_CHANNEL, SDPCM_TEST_CHANNEL or ++ SDPCM_GLOM_CHANNEL */ ++ ++ /* Length to read */ ++ rdlen = (len > BRCMF_FIRSTREAD) ? (len - BRCMF_FIRSTREAD) : 0; ++ ++ /* May pad read to blocksize for efficiency */ ++ if (bus->roundup && bus->blocksize && ++ (rdlen > bus->blocksize)) { ++ pad = bus->blocksize - (rdlen % bus->blocksize); ++ if ((pad <= bus->roundup) && (pad < bus->blocksize) && ++ ((rdlen + pad + BRCMF_FIRSTREAD) < MAX_RX_DATASZ)) ++ rdlen += pad; ++ } else if (rdlen % BRCMF_SDALIGN) { ++ rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN); ++ } ++ ++ /* Satisfy length-alignment requirements */ ++ if (rdlen & (ALIGNMENT - 1)) ++ rdlen = roundup(rdlen, ALIGNMENT); ++ ++ if ((rdlen + BRCMF_FIRSTREAD) > MAX_RX_DATASZ) { ++ /* Too long -- skip this frame */ ++ brcmf_dbg(ERROR, "too long: len %d rdlen %d\n", ++ len, rdlen); ++ bus->drvr->rx_errors++; ++ bus->rx_toolong++; ++ brcmf_sdbrcm_rxfail(bus, false, false); ++ continue; ++ } ++ ++ pkt = brcmu_pkt_buf_get_skb(rdlen + ++ BRCMF_FIRSTREAD + BRCMF_SDALIGN); ++ if (!pkt) { ++ /* Give up on data, request rtx of events */ ++ brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: rdlen %d chan %d\n", ++ rdlen, chan); ++ bus->drvr->rx_dropped++; ++ brcmf_sdbrcm_rxfail(bus, false, RETRYCHAN(chan)); ++ continue; ++ } ++ ++ /* Leave room for what we already read, and align remainder */ ++ skb_pull(pkt, BRCMF_FIRSTREAD); ++ pkt_align(pkt, rdlen, BRCMF_SDALIGN); ++ ++ /* Read the remaining frame data */ ++ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, ++ SDIO_FUNC_2, F2SYNC, ((u8 *) (pkt->data)), ++ rdlen, pkt); ++ bus->f2rxdata++; ++ ++ if (sdret < 0) { ++ brcmf_dbg(ERROR, "read %d %s bytes failed: %d\n", rdlen, ++ ((chan == SDPCM_EVENT_CHANNEL) ? "event" ++ : ((chan == SDPCM_DATA_CHANNEL) ? "data" ++ : "test")), sdret); ++ brcmu_pkt_buf_free_skb(pkt); ++ bus->drvr->rx_errors++; ++ brcmf_sdbrcm_rxfail(bus, true, RETRYCHAN(chan)); ++ continue; ++ } ++ ++ /* Copy the already-read portion */ ++ skb_push(pkt, BRCMF_FIRSTREAD); ++ memcpy(pkt->data, bus->rxhdr, BRCMF_FIRSTREAD); ++ ++#ifdef BCMDBG ++ if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) { ++ printk(KERN_DEBUG "Rx Data:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ pkt->data, len); ++ } ++#endif ++ ++deliver: ++ /* Save superframe descriptor and allocate packet frame */ ++ if (chan == SDPCM_GLOM_CHANNEL) { ++ if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) { ++ brcmf_dbg(GLOM, "glom descriptor, %d bytes:\n", ++ len); ++#ifdef BCMDBG ++ if (BRCMF_GLOM_ON()) { ++ printk(KERN_DEBUG "Glom Data:\n"); ++ print_hex_dump_bytes("", ++ DUMP_PREFIX_OFFSET, ++ pkt->data, len); ++ } ++#endif ++ __skb_trim(pkt, len); ++ skb_pull(pkt, SDPCM_HDRLEN); ++ bus->glomd = pkt; ++ } else { ++ brcmf_dbg(ERROR, "%s: glom superframe w/o " ++ "descriptor!\n", __func__); ++ brcmf_sdbrcm_rxfail(bus, false, false); ++ } ++ continue; ++ } ++ ++ /* Fill in packet len and prio, deliver upward */ ++ __skb_trim(pkt, len); ++ skb_pull(pkt, doff); ++ ++ if (pkt->len == 0) { ++ brcmu_pkt_buf_free_skb(pkt); ++ continue; ++ } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, pkt) != 0) { ++ brcmf_dbg(ERROR, "rx protocol error\n"); ++ brcmu_pkt_buf_free_skb(pkt); ++ bus->drvr->rx_errors++; ++ continue; ++ } ++ ++ /* Unlock during rx call */ ++ up(&bus->sdsem); ++ brcmf_rx_frame(bus->drvr, ifidx, pkt, 1); ++ down(&bus->sdsem); ++ } ++ rxcount = maxframes - rxleft; ++#ifdef BCMDBG ++ /* Message if we hit the limit */ ++ if (!rxleft) ++ brcmf_dbg(DATA, "hit rx limit of %d frames\n", ++ maxframes); ++ else ++#endif /* BCMDBG */ ++ brcmf_dbg(DATA, "processed %d frames\n", rxcount); ++ /* Back off rxseq if awaiting rtx, update rx_seq */ ++ if (bus->rxskip) ++ rxseq--; ++ bus->rx_seq = rxseq; ++ ++ return rxcount; ++} ++ ++static int ++brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn, uint flags, ++ u8 *buf, uint nbytes, struct sk_buff *pkt) ++{ ++ return brcmf_sdcard_send_buf ++ (bus->sdiodev, addr, fn, flags, buf, nbytes, pkt); ++} ++ ++static void ++brcmf_sdbrcm_wait_for_event(struct brcmf_bus *bus, bool *lockvar) ++{ ++ up(&bus->sdsem); ++ wait_event_interruptible_timeout(bus->ctrl_wait, ++ (*lockvar == false), HZ * 2); ++ down(&bus->sdsem); ++ return; ++} ++ ++static void ++brcmf_sdbrcm_wait_event_wakeup(struct brcmf_bus *bus) ++{ ++ if (waitqueue_active(&bus->ctrl_wait)) ++ wake_up_interruptible(&bus->ctrl_wait); ++ return; ++} ++ ++/* Writes a HW/SW header into the packet and sends it. */ ++/* Assumes: (a) header space already there, (b) caller holds lock */ ++static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt, ++ uint chan, bool free_pkt) ++{ ++ int ret; ++ u8 *frame; ++ u16 len, pad = 0; ++ u32 swheader; ++ struct sk_buff *new; ++ int i; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ frame = (u8 *) (pkt->data); ++ ++ /* Add alignment padding, allocate new packet if needed */ ++ pad = ((unsigned long)frame % BRCMF_SDALIGN); ++ if (pad) { ++ if (skb_headroom(pkt) < pad) { ++ brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n", ++ skb_headroom(pkt), pad); ++ bus->drvr->tx_realloc++; ++ new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN); ++ if (!new) { ++ brcmf_dbg(ERROR, "couldn't allocate new %d-byte packet\n", ++ pkt->len + BRCMF_SDALIGN); ++ ret = -ENOMEM; ++ goto done; ++ } ++ ++ pkt_align(new, pkt->len, BRCMF_SDALIGN); ++ memcpy(new->data, pkt->data, pkt->len); ++ if (free_pkt) ++ brcmu_pkt_buf_free_skb(pkt); ++ /* free the pkt if canned one is not used */ ++ free_pkt = true; ++ pkt = new; ++ frame = (u8 *) (pkt->data); ++ /* precondition: (frame % BRCMF_SDALIGN) == 0) */ ++ pad = 0; ++ } else { ++ skb_push(pkt, pad); ++ frame = (u8 *) (pkt->data); ++ /* precondition: pad + SDPCM_HDRLEN <= pkt->len */ ++ memset(frame, 0, pad + SDPCM_HDRLEN); ++ } ++ } ++ /* precondition: pad < BRCMF_SDALIGN */ ++ ++ /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ ++ len = (u16) (pkt->len); ++ *(__le16 *) frame = cpu_to_le16(len); ++ *(((__le16 *) frame) + 1) = cpu_to_le16(~len); ++ ++ /* Software tag: channel, sequence number, data offset */ ++ swheader = ++ ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq | ++ (((pad + ++ SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); ++ ++ put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN); ++ put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); ++ ++#ifdef BCMDBG ++ tx_packets[pkt->priority]++; ++ if (BRCMF_BYTES_ON() && ++ (((BRCMF_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) || ++ (BRCMF_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) { ++ printk(KERN_DEBUG "Tx Frame:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, frame, len); ++ } else if (BRCMF_HDRS_ON()) { ++ printk(KERN_DEBUG "TxHdr:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ frame, min_t(u16, len, 16)); ++ } ++#endif ++ ++ /* Raise len to next SDIO block to eliminate tail command */ ++ if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { ++ u16 pad = bus->blocksize - (len % bus->blocksize); ++ if ((pad <= bus->roundup) && (pad < bus->blocksize)) ++ len += pad; ++ } else if (len % BRCMF_SDALIGN) { ++ len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN); ++ } ++ ++ /* Some controllers have trouble with odd bytes -- round to even */ ++ if (len & (ALIGNMENT - 1)) ++ len = roundup(len, ALIGNMENT); ++ ++ ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad, ++ SDIO_FUNC_2, F2SYNC, frame, ++ len, pkt); ++ bus->f2txdata++; ++ ++ if (ret < 0) { ++ /* On failure, abort the command and terminate the frame */ ++ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", ++ ret); ++ bus->tx_sderrs++; ++ ++ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, ++ NULL); ++ bus->f1regdata++; ++ ++ for (i = 0; i < 3; i++) { ++ u8 hi, lo; ++ hi = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCHI, ++ NULL); ++ lo = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCLO, ++ NULL); ++ bus->f1regdata += 2; ++ if ((hi == 0) && (lo == 0)) ++ break; ++ } ++ ++ } ++ if (ret == 0) ++ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; ++ ++done: ++ /* restore pkt buffer pointer before calling tx complete routine */ ++ skb_pull(pkt, SDPCM_HDRLEN + pad); ++ up(&bus->sdsem); ++ brcmf_txcomplete(bus->drvr, pkt, ret != 0); ++ down(&bus->sdsem); ++ ++ if (free_pkt) ++ brcmu_pkt_buf_free_skb(pkt); ++ ++ return ret; ++} ++ ++static uint brcmf_sdbrcm_sendfromq(struct brcmf_bus *bus, uint maxframes) ++{ ++ struct sk_buff *pkt; ++ u32 intstatus = 0; ++ uint retries = 0; ++ int ret = 0, prec_out; ++ uint cnt = 0; ++ uint datalen; ++ u8 tx_prec_map; ++ ++ struct brcmf_pub *drvr = bus->drvr; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ tx_prec_map = ~bus->flowcontrol; ++ ++ /* Send frames until the limit or some other event */ ++ for (cnt = 0; (cnt < maxframes) && data_ok(bus); cnt++) { ++ spin_lock_bh(&bus->txqlock); ++ pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out); ++ if (pkt == NULL) { ++ spin_unlock_bh(&bus->txqlock); ++ break; ++ } ++ spin_unlock_bh(&bus->txqlock); ++ datalen = pkt->len - SDPCM_HDRLEN; ++ ++ ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true); ++ if (ret) ++ bus->drvr->tx_errors++; ++ else ++ bus->drvr->dstats.tx_bytes += datalen; ++ ++ /* In poll mode, need to check for other events */ ++ if (!bus->intr && cnt) { ++ /* Check device status, signal pending interrupt */ ++ r_sdreg32(bus, &intstatus, ++ offsetof(struct sdpcmd_regs, intstatus), ++ &retries); ++ bus->f2txdata++; ++ if (brcmf_sdcard_regfail(bus->sdiodev)) ++ break; ++ if (intstatus & bus->hostintmask) ++ bus->ipend = true; ++ } ++ } ++ ++ /* Deflow-control stack if needed */ ++ if (drvr->up && (drvr->busstate == BRCMF_BUS_DATA) && ++ drvr->txoff && (pktq_len(&bus->txq) < TXLOW)) ++ brcmf_txflowcontrol(drvr, 0, OFF); ++ ++ return cnt; ++} ++ ++static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus) ++{ ++ u32 intstatus, newstatus = 0; ++ uint retries = 0; ++ uint rxlimit = bus->rxbound; /* Rx frames to read before resched */ ++ uint txlimit = bus->txbound; /* Tx frames to send before resched */ ++ uint framecnt = 0; /* Temporary counter of tx/rx frames */ ++ bool rxdone = true; /* Flag for no more read data */ ++ bool resched = false; /* Flag indicating resched wanted */ ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Start with leftover status bits */ ++ intstatus = bus->intstatus; ++ ++ down(&bus->sdsem); ++ ++ /* If waiting for HTAVAIL, check status */ ++ if (bus->clkstate == CLK_PENDING) { ++ int err; ++ u8 clkctl, devctl = 0; ++ ++#ifdef BCMDBG ++ /* Check for inconsistent device control */ ++ devctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, &err); ++ if (err) { ++ brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", err); ++ bus->drvr->busstate = BRCMF_BUS_DOWN; ++ } ++#endif /* BCMDBG */ ++ ++ /* Read CSR, if clock on switch to AVAIL, else ignore */ ++ clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ if (err) { ++ brcmf_dbg(ERROR, "error reading CSR: %d\n", ++ err); ++ bus->drvr->busstate = BRCMF_BUS_DOWN; ++ } ++ ++ brcmf_dbg(INFO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", ++ devctl, clkctl); ++ ++ if (SBSDIO_HTAV(clkctl)) { ++ devctl = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, &err); ++ if (err) { ++ brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", ++ err); ++ bus->drvr->busstate = BRCMF_BUS_DOWN; ++ } ++ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_DEVICE_CTL, devctl, &err); ++ if (err) { ++ brcmf_dbg(ERROR, "error writing DEVCTL: %d\n", ++ err); ++ bus->drvr->busstate = BRCMF_BUS_DOWN; ++ } ++ bus->clkstate = CLK_AVAIL; ++ } else { ++ goto clkwait; ++ } ++ } ++ ++ bus_wake(bus); ++ ++ /* Make sure backplane clock is on */ ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true); ++ if (bus->clkstate == CLK_PENDING) ++ goto clkwait; ++ ++ /* Pending interrupt indicates new device status */ ++ if (bus->ipend) { ++ bus->ipend = false; ++ r_sdreg32(bus, &newstatus, ++ offsetof(struct sdpcmd_regs, intstatus), &retries); ++ bus->f1regdata++; ++ if (brcmf_sdcard_regfail(bus->sdiodev)) ++ newstatus = 0; ++ newstatus &= bus->hostintmask; ++ bus->fcstate = !!(newstatus & I_HMB_FC_STATE); ++ if (newstatus) { ++ w_sdreg32(bus, newstatus, ++ offsetof(struct sdpcmd_regs, intstatus), ++ &retries); ++ bus->f1regdata++; ++ } ++ } ++ ++ /* Merge new bits with previous */ ++ intstatus |= newstatus; ++ bus->intstatus = 0; ++ ++ /* Handle flow-control change: read new state in case our ack ++ * crossed another change interrupt. If change still set, assume ++ * FC ON for safety, let next loop through do the debounce. ++ */ ++ if (intstatus & I_HMB_FC_CHANGE) { ++ intstatus &= ~I_HMB_FC_CHANGE; ++ w_sdreg32(bus, I_HMB_FC_CHANGE, ++ offsetof(struct sdpcmd_regs, intstatus), &retries); ++ ++ r_sdreg32(bus, &newstatus, ++ offsetof(struct sdpcmd_regs, intstatus), &retries); ++ bus->f1regdata += 2; ++ bus->fcstate = ++ !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)); ++ intstatus |= (newstatus & bus->hostintmask); ++ } ++ ++ /* Handle host mailbox indication */ ++ if (intstatus & I_HMB_HOST_INT) { ++ intstatus &= ~I_HMB_HOST_INT; ++ intstatus |= brcmf_sdbrcm_hostmail(bus); ++ } ++ ++ /* Generally don't ask for these, can get CRC errors... */ ++ if (intstatus & I_WR_OOSYNC) { ++ brcmf_dbg(ERROR, "Dongle reports WR_OOSYNC\n"); ++ intstatus &= ~I_WR_OOSYNC; ++ } ++ ++ if (intstatus & I_RD_OOSYNC) { ++ brcmf_dbg(ERROR, "Dongle reports RD_OOSYNC\n"); ++ intstatus &= ~I_RD_OOSYNC; ++ } ++ ++ if (intstatus & I_SBINT) { ++ brcmf_dbg(ERROR, "Dongle reports SBINT\n"); ++ intstatus &= ~I_SBINT; ++ } ++ ++ /* Would be active due to wake-wlan in gSPI */ ++ if (intstatus & I_CHIPACTIVE) { ++ brcmf_dbg(INFO, "Dongle reports CHIPACTIVE\n"); ++ intstatus &= ~I_CHIPACTIVE; ++ } ++ ++ /* Ignore frame indications if rxskip is set */ ++ if (bus->rxskip) ++ intstatus &= ~I_HMB_FRAME_IND; ++ ++ /* On frame indication, read available frames */ ++ if (PKT_AVAILABLE()) { ++ framecnt = brcmf_sdbrcm_readframes(bus, rxlimit, &rxdone); ++ if (rxdone || bus->rxskip) ++ intstatus &= ~I_HMB_FRAME_IND; ++ rxlimit -= min(framecnt, rxlimit); ++ } ++ ++ /* Keep still-pending events for next scheduling */ ++ bus->intstatus = intstatus; ++ ++clkwait: ++ if (data_ok(bus) && bus->ctrl_frame_stat && ++ (bus->clkstate == CLK_AVAIL)) { ++ int ret, i; ++ ++ ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad, ++ SDIO_FUNC_2, F2SYNC, (u8 *) bus->ctrl_frame_buf, ++ (u32) bus->ctrl_frame_len, NULL); ++ ++ if (ret < 0) { ++ /* On failure, abort the command and ++ terminate the frame */ ++ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", ++ ret); ++ bus->tx_sderrs++; ++ ++ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, ++ NULL); ++ bus->f1regdata++; ++ ++ for (i = 0; i < 3; i++) { ++ u8 hi, lo; ++ hi = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCHI, ++ NULL); ++ lo = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCLO, ++ NULL); ++ bus->f1regdata += 2; ++ if ((hi == 0) && (lo == 0)) ++ break; ++ } ++ ++ } ++ if (ret == 0) ++ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; ++ ++ brcmf_dbg(INFO, "Return_dpc value is : %d\n", ret); ++ bus->ctrl_frame_stat = false; ++ brcmf_sdbrcm_wait_event_wakeup(bus); ++ } ++ /* Send queued frames (limit 1 if rx may still be pending) */ ++ else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate && ++ brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit ++ && data_ok(bus)) { ++ framecnt = rxdone ? txlimit : min(txlimit, bus->txminmax); ++ framecnt = brcmf_sdbrcm_sendfromq(bus, framecnt); ++ txlimit -= framecnt; ++ } ++ ++ /* Resched if events or tx frames are pending, ++ else await next interrupt */ ++ /* On failed register access, all bets are off: ++ no resched or interrupts */ ++ if ((bus->drvr->busstate == BRCMF_BUS_DOWN) || ++ brcmf_sdcard_regfail(bus->sdiodev)) { ++ brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation %d\n", ++ brcmf_sdcard_regfail(bus->sdiodev)); ++ bus->drvr->busstate = BRCMF_BUS_DOWN; ++ bus->intstatus = 0; ++ } else if (bus->clkstate == CLK_PENDING) { ++ brcmf_dbg(INFO, "rescheduled due to CLK_PENDING awaiting I_CHIPACTIVE interrupt\n"); ++ resched = true; ++ } else if (bus->intstatus || bus->ipend || ++ (!bus->fcstate && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) ++ && data_ok(bus)) || PKT_AVAILABLE()) { ++ resched = true; ++ } ++ ++ bus->dpc_sched = resched; ++ ++ /* If we're done for now, turn off clock request. */ ++ if ((bus->clkstate != CLK_PENDING) ++ && bus->idletime == BRCMF_IDLE_IMMEDIATE) { ++ bus->activity = false; ++ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); ++ } ++ ++ up(&bus->sdsem); ++ ++ return resched; ++} ++ ++static int brcmf_sdbrcm_dpc_thread(void *data) ++{ ++ struct brcmf_bus *bus = (struct brcmf_bus *) data; ++ ++ allow_signal(SIGTERM); ++ /* Run until signal received */ ++ while (1) { ++ if (kthread_should_stop()) ++ break; ++ if (!wait_for_completion_interruptible(&bus->dpc_wait)) { ++ /* Call bus dpc unless it indicated down ++ (then clean stop) */ ++ if (bus->drvr->busstate != BRCMF_BUS_DOWN) { ++ if (brcmf_sdbrcm_dpc(bus)) ++ complete(&bus->dpc_wait); ++ } else { ++ /* after stopping the bus, exit thread */ ++ brcmf_sdbrcm_bus_stop(bus); ++ bus->dpc_tsk = NULL; ++ break; ++ } ++ } else ++ break; ++ } ++ return 0; ++} ++ ++int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt) ++{ ++ int ret = -EBADE; ++ uint datalen, prec; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ datalen = pkt->len; ++ ++ /* Add space for the header */ ++ skb_push(pkt, SDPCM_HDRLEN); ++ /* precondition: IS_ALIGNED((unsigned long)(pkt->data), 2) */ ++ ++ prec = prio2prec((pkt->priority & PRIOMASK)); ++ ++ /* Check for existing queue, current flow-control, ++ pending event, or pending clock */ ++ brcmf_dbg(TRACE, "deferring pktq len %d\n", pktq_len(&bus->txq)); ++ bus->fcqueued++; ++ ++ /* Priority based enq */ ++ spin_lock_bh(&bus->txqlock); ++ if (brcmf_c_prec_enq(bus->drvr, &bus->txq, pkt, prec) == false) { ++ skb_pull(pkt, SDPCM_HDRLEN); ++ brcmf_txcomplete(bus->drvr, pkt, false); ++ brcmu_pkt_buf_free_skb(pkt); ++ brcmf_dbg(ERROR, "out of bus->txq !!!\n"); ++ ret = -ENOSR; ++ } else { ++ ret = 0; ++ } ++ spin_unlock_bh(&bus->txqlock); ++ ++ if (pktq_len(&bus->txq) >= TXHI) ++ brcmf_txflowcontrol(bus->drvr, 0, ON); ++ ++#ifdef BCMDBG ++ if (pktq_plen(&bus->txq, prec) > qcount[prec]) ++ qcount[prec] = pktq_plen(&bus->txq, prec); ++#endif ++ /* Schedule DPC if needed to send queued packet(s) */ ++ if (!bus->dpc_sched) { ++ bus->dpc_sched = true; ++ if (bus->dpc_tsk) ++ complete(&bus->dpc_wait); ++ } ++ ++ return ret; ++} ++ ++static int ++brcmf_sdbrcm_membytes(struct brcmf_bus *bus, bool write, u32 address, u8 *data, ++ uint size) ++{ ++ int bcmerror = 0; ++ u32 sdaddr; ++ uint dsize; ++ ++ /* Determine initial transfer parameters */ ++ sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK; ++ if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK) ++ dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr); ++ else ++ dsize = size; ++ ++ /* Set the backplane window to include the start address */ ++ bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address); ++ if (bcmerror) { ++ brcmf_dbg(ERROR, "window change failed\n"); ++ goto xfer_done; ++ } ++ ++ /* Do the transfer(s) */ ++ while (size) { ++ brcmf_dbg(INFO, "%s %d bytes at offset 0x%08x in window 0x%08x\n", ++ write ? "write" : "read", dsize, ++ sdaddr, address & SBSDIO_SBWINDOW_MASK); ++ bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write, ++ sdaddr, data, dsize); ++ if (bcmerror) { ++ brcmf_dbg(ERROR, "membytes transfer failed\n"); ++ break; ++ } ++ ++ /* Adjust for next transfer (if any) */ ++ size -= dsize; ++ if (size) { ++ data += dsize; ++ address += dsize; ++ bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, ++ address); ++ if (bcmerror) { ++ brcmf_dbg(ERROR, "window change failed\n"); ++ break; ++ } ++ sdaddr = 0; ++ dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size); ++ } ++ } ++ ++xfer_done: ++ /* Return the window to backplane enumeration space for core access */ ++ if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, bus->sdiodev->sbwad)) ++ brcmf_dbg(ERROR, "FAILED to set window back to 0x%x\n", ++ bus->sdiodev->sbwad); ++ ++ return bcmerror; ++} ++ ++#ifdef BCMDBG ++#define CONSOLE_LINE_MAX 192 ++ ++static int brcmf_sdbrcm_readconsole(struct brcmf_bus *bus) ++{ ++ struct brcmf_console *c = &bus->console; ++ u8 line[CONSOLE_LINE_MAX], ch; ++ u32 n, idx, addr; ++ int rv; ++ ++ /* Don't do anything until FWREADY updates console address */ ++ if (bus->console_addr == 0) ++ return 0; ++ ++ /* Read console log struct */ ++ addr = bus->console_addr + offsetof(struct rte_console, log_le); ++ rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&c->log_le, ++ sizeof(c->log_le)); ++ if (rv < 0) ++ return rv; ++ ++ /* Allocate console buffer (one time only) */ ++ if (c->buf == NULL) { ++ c->bufsize = le32_to_cpu(c->log_le.buf_size); ++ c->buf = kmalloc(c->bufsize, GFP_ATOMIC); ++ if (c->buf == NULL) ++ return -ENOMEM; ++ } ++ ++ idx = le32_to_cpu(c->log_le.idx); ++ ++ /* Protect against corrupt value */ ++ if (idx > c->bufsize) ++ return -EBADE; ++ ++ /* Skip reading the console buffer if the index pointer ++ has not moved */ ++ if (idx == c->last) ++ return 0; ++ ++ /* Read the console buffer */ ++ addr = le32_to_cpu(c->log_le.buf); ++ rv = brcmf_sdbrcm_membytes(bus, false, addr, c->buf, c->bufsize); ++ if (rv < 0) ++ return rv; ++ ++ while (c->last != idx) { ++ for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) { ++ if (c->last == idx) { ++ /* This would output a partial line. ++ * Instead, back up ++ * the buffer pointer and output this ++ * line next time around. ++ */ ++ if (c->last >= n) ++ c->last -= n; ++ else ++ c->last = c->bufsize - n; ++ goto break2; ++ } ++ ch = c->buf[c->last]; ++ c->last = (c->last + 1) % c->bufsize; ++ if (ch == '\n') ++ break; ++ line[n] = ch; ++ } ++ ++ if (n > 0) { ++ if (line[n - 1] == '\r') ++ n--; ++ line[n] = 0; ++ printk(KERN_DEBUG "CONSOLE: %s\n", line); ++ } ++ } ++break2: ++ ++ return 0; ++} ++#endif /* BCMDBG */ ++ ++static int brcmf_tx_frame(struct brcmf_bus *bus, u8 *frame, u16 len) ++{ ++ int i; ++ int ret; ++ ++ bus->ctrl_frame_stat = false; ++ ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad, ++ SDIO_FUNC_2, F2SYNC, frame, len, NULL); ++ ++ if (ret < 0) { ++ /* On failure, abort the command and terminate the frame */ ++ brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", ++ ret); ++ bus->tx_sderrs++; ++ ++ brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_FRAMECTRL, ++ SFC_WF_TERM, NULL); ++ bus->f1regdata++; ++ ++ for (i = 0; i < 3; i++) { ++ u8 hi, lo; ++ hi = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCHI, ++ NULL); ++ lo = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCLO, ++ NULL); ++ bus->f1regdata += 2; ++ if (hi == 0 && lo == 0) ++ break; ++ } ++ return ret; ++ } ++ ++ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; ++ ++ return ret; ++} ++ ++int ++brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) ++{ ++ u8 *frame; ++ u16 len; ++ u32 swheader; ++ uint retries = 0; ++ u8 doff = 0; ++ int ret = -1; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Back the pointer to make a room for bus header */ ++ frame = msg - SDPCM_HDRLEN; ++ len = (msglen += SDPCM_HDRLEN); ++ ++ /* Add alignment padding (optional for ctl frames) */ ++ doff = ((unsigned long)frame % BRCMF_SDALIGN); ++ if (doff) { ++ frame -= doff; ++ len += doff; ++ msglen += doff; ++ memset(frame, 0, doff + SDPCM_HDRLEN); ++ } ++ /* precondition: doff < BRCMF_SDALIGN */ ++ doff += SDPCM_HDRLEN; ++ ++ /* Round send length to next SDIO block */ ++ if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { ++ u16 pad = bus->blocksize - (len % bus->blocksize); ++ if ((pad <= bus->roundup) && (pad < bus->blocksize)) ++ len += pad; ++ } else if (len % BRCMF_SDALIGN) { ++ len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN); ++ } ++ ++ /* Satisfy length-alignment requirements */ ++ if (len & (ALIGNMENT - 1)) ++ len = roundup(len, ALIGNMENT); ++ ++ /* precondition: IS_ALIGNED((unsigned long)frame, 2) */ ++ ++ /* Need to lock here to protect txseq and SDIO tx calls */ ++ down(&bus->sdsem); ++ ++ bus_wake(bus); ++ ++ /* Make sure backplane clock is on */ ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); ++ ++ /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ ++ *(__le16 *) frame = cpu_to_le16((u16) msglen); ++ *(((__le16 *) frame) + 1) = cpu_to_le16(~msglen); ++ ++ /* Software tag: channel, sequence number, data offset */ ++ swheader = ++ ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & ++ SDPCM_CHANNEL_MASK) ++ | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) & ++ SDPCM_DOFFSET_MASK); ++ put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN); ++ put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); ++ ++ if (!data_ok(bus)) { ++ brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n", ++ bus->tx_max, bus->tx_seq); ++ bus->ctrl_frame_stat = true; ++ /* Send from dpc */ ++ bus->ctrl_frame_buf = frame; ++ bus->ctrl_frame_len = len; ++ ++ brcmf_sdbrcm_wait_for_event(bus, &bus->ctrl_frame_stat); ++ ++ if (bus->ctrl_frame_stat == false) { ++ brcmf_dbg(INFO, "ctrl_frame_stat == false\n"); ++ ret = 0; ++ } else { ++ brcmf_dbg(INFO, "ctrl_frame_stat == true\n"); ++ ret = -1; ++ } ++ } ++ ++ if (ret == -1) { ++#ifdef BCMDBG ++ if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) { ++ printk(KERN_DEBUG "Tx Frame:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ frame, len); ++ } else if (BRCMF_HDRS_ON()) { ++ printk(KERN_DEBUG "TxHdr:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ frame, min_t(u16, len, 16)); ++ } ++#endif ++ ++ do { ++ ret = brcmf_tx_frame(bus, frame, len); ++ } while (ret < 0 && retries++ < TXRETRIES); ++ } ++ ++ if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) { ++ bus->activity = false; ++ brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); ++ } ++ ++ up(&bus->sdsem); ++ ++ if (ret) ++ bus->drvr->tx_ctlerrs++; ++ else ++ bus->drvr->tx_ctlpkts++; ++ ++ return ret ? -EIO : 0; ++} ++ ++int ++brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) ++{ ++ int timeleft; ++ uint rxlen = 0; ++ bool pending; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Wait until control frame is available */ ++ timeleft = brcmf_sdbrcm_dcmd_resp_wait(bus, &bus->rxlen, &pending); ++ ++ down(&bus->sdsem); ++ rxlen = bus->rxlen; ++ memcpy(msg, bus->rxctl, min(msglen, rxlen)); ++ bus->rxlen = 0; ++ up(&bus->sdsem); ++ ++ if (rxlen) { ++ brcmf_dbg(CTL, "resumed on rxctl frame, got %d expected %d\n", ++ rxlen, msglen); ++ } else if (timeleft == 0) { ++ brcmf_dbg(ERROR, "resumed on timeout\n"); ++ } else if (pending == true) { ++ brcmf_dbg(CTL, "cancelled\n"); ++ return -ERESTARTSYS; ++ } else { ++ brcmf_dbg(CTL, "resumed for unknown reason?\n"); ++ } ++ ++ if (rxlen) ++ bus->drvr->rx_ctlpkts++; ++ else ++ bus->drvr->rx_ctlerrs++; ++ ++ return rxlen ? (int)rxlen : -ETIMEDOUT; ++} ++ ++static int brcmf_sdbrcm_downloadvars(struct brcmf_bus *bus, void *arg, int len) ++{ ++ int bcmerror = 0; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Basic sanity checks */ ++ if (bus->drvr->up) { ++ bcmerror = -EISCONN; ++ goto err; ++ } ++ if (!len) { ++ bcmerror = -EOVERFLOW; ++ goto err; ++ } ++ ++ /* Free the old ones and replace with passed variables */ ++ kfree(bus->vars); ++ ++ bus->vars = kmalloc(len, GFP_ATOMIC); ++ bus->varsz = bus->vars ? len : 0; ++ if (bus->vars == NULL) { ++ bcmerror = -ENOMEM; ++ goto err; ++ } ++ ++ /* Copy the passed variables, which should include the ++ terminating double-null */ ++ memcpy(bus->vars, arg, bus->varsz); ++err: ++ return bcmerror; ++} ++ ++static int brcmf_sdbrcm_write_vars(struct brcmf_bus *bus) ++{ ++ int bcmerror = 0; ++ u32 varsize; ++ u32 varaddr; ++ u8 *vbuffer; ++ u32 varsizew; ++ __le32 varsizew_le; ++#ifdef BCMDBG ++ char *nvram_ularray; ++#endif /* BCMDBG */ ++ ++ /* Even if there are no vars are to be written, we still ++ need to set the ramsize. */ ++ varsize = bus->varsz ? roundup(bus->varsz, 4) : 0; ++ varaddr = (bus->ramsize - 4) - varsize; ++ ++ if (bus->vars) { ++ vbuffer = kzalloc(varsize, GFP_ATOMIC); ++ if (!vbuffer) ++ return -ENOMEM; ++ ++ memcpy(vbuffer, bus->vars, bus->varsz); ++ ++ /* Write the vars list */ ++ bcmerror = ++ brcmf_sdbrcm_membytes(bus, true, varaddr, vbuffer, varsize); ++#ifdef BCMDBG ++ /* Verify NVRAM bytes */ ++ brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n", varsize); ++ nvram_ularray = kmalloc(varsize, GFP_ATOMIC); ++ if (!nvram_ularray) ++ return -ENOMEM; ++ ++ /* Upload image to verify downloaded contents. */ ++ memset(nvram_ularray, 0xaa, varsize); ++ ++ /* Read the vars list to temp buffer for comparison */ ++ bcmerror = ++ brcmf_sdbrcm_membytes(bus, false, varaddr, nvram_ularray, ++ varsize); ++ if (bcmerror) { ++ brcmf_dbg(ERROR, "error %d on reading %d nvram bytes at 0x%08x\n", ++ bcmerror, varsize, varaddr); ++ } ++ /* Compare the org NVRAM with the one read from RAM */ ++ if (memcmp(vbuffer, nvram_ularray, varsize)) ++ brcmf_dbg(ERROR, "Downloaded NVRAM image is corrupted\n"); ++ else ++ brcmf_dbg(ERROR, "Download/Upload/Compare of NVRAM ok\n"); ++ ++ kfree(nvram_ularray); ++#endif /* BCMDBG */ ++ ++ kfree(vbuffer); ++ } ++ ++ /* adjust to the user specified RAM */ ++ brcmf_dbg(INFO, "Physical memory size: %d\n", bus->ramsize); ++ brcmf_dbg(INFO, "Vars are at %d, orig varsize is %d\n", ++ varaddr, varsize); ++ varsize = ((bus->ramsize - 4) - varaddr); ++ ++ /* ++ * Determine the length token: ++ * Varsize, converted to words, in lower 16-bits, checksum ++ * in upper 16-bits. ++ */ ++ if (bcmerror) { ++ varsizew = 0; ++ varsizew_le = cpu_to_le32(0); ++ } else { ++ varsizew = varsize / 4; ++ varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF); ++ varsizew_le = cpu_to_le32(varsizew); ++ } ++ ++ brcmf_dbg(INFO, "New varsize is %d, length token=0x%08x\n", ++ varsize, varsizew); ++ ++ /* Write the length token to the last word */ ++ bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->ramsize - 4), ++ (u8 *)&varsizew_le, 4); ++ ++ return bcmerror; ++} ++ ++static void ++brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_dev *sdiodev, u32 corebase) ++{ ++ u32 regdata; ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbtmstatelow), 4); ++ if (regdata & SBTML_RESET) ++ return; ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbtmstatelow), 4); ++ if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) { ++ /* ++ * set target reject and spin until busy is clear ++ * (preserve core-specific bits) ++ */ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbtmstatelow), 4); ++ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), ++ 4, regdata | SBTML_REJ); ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbtmstatelow), 4); ++ udelay(1); ++ SPINWAIT((brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbtmstatehigh), 4) & ++ SBTMH_BUSY), 100000); ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbtmstatehigh), 4); ++ if (regdata & SBTMH_BUSY) ++ brcmf_dbg(ERROR, "ARM core still busy\n"); ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbidlow), 4); ++ if (regdata & SBIDL_INIT) { ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbimstate), 4) | ++ SBIM_RJ; ++ brcmf_sdcard_reg_write(sdiodev, ++ CORE_SB(corebase, sbimstate), 4, ++ regdata); ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbimstate), 4); ++ udelay(1); ++ SPINWAIT((brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbimstate), 4) & ++ SBIM_BY), 100000); ++ } ++ ++ /* set reset and reject while enabling the clocks */ ++ brcmf_sdcard_reg_write(sdiodev, ++ CORE_SB(corebase, sbtmstatelow), 4, ++ (((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | ++ SBTML_REJ | SBTML_RESET)); ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbtmstatelow), 4); ++ udelay(10); ++ ++ /* clear the initiator reject bit */ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbidlow), 4); ++ if (regdata & SBIDL_INIT) { ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbimstate), 4) & ++ ~SBIM_RJ; ++ brcmf_sdcard_reg_write(sdiodev, ++ CORE_SB(corebase, sbimstate), 4, ++ regdata); ++ } ++ } ++ ++ /* leave reset and reject asserted */ ++ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4, ++ (SBTML_REJ | SBTML_RESET)); ++ udelay(1); ++} ++ ++static void ++brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_dev *sdiodev, u32 corebase) ++{ ++ u32 regdata; ++ ++ /* ++ * Must do the disable sequence first to work for ++ * arbitrary current core state. ++ */ ++ brcmf_sdbrcm_chip_disablecore(sdiodev, corebase); ++ ++ /* ++ * Now do the initialization sequence. ++ * set reset while enabling the clock and ++ * forcing them on throughout the core ++ */ ++ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4, ++ ((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | ++ SBTML_RESET); ++ udelay(1); ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbtmstatehigh), 4); ++ if (regdata & SBTMH_SERR) ++ brcmf_sdcard_reg_write(sdiodev, ++ CORE_SB(corebase, sbtmstatehigh), 4, 0); ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(corebase, sbimstate), 4); ++ if (regdata & (SBIM_IBE | SBIM_TO)) ++ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbimstate), 4, ++ regdata & ~(SBIM_IBE | SBIM_TO)); ++ ++ /* clear reset and allow it to propagate throughout the core */ ++ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4, ++ (SICF_FGC << SBTML_SICF_SHIFT) | ++ (SICF_CLOCK_EN << SBTML_SICF_SHIFT)); ++ udelay(1); ++ ++ /* leave clock enabled */ ++ brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4, ++ (SICF_CLOCK_EN << SBTML_SICF_SHIFT)); ++ udelay(1); ++} ++ ++static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter) ++{ ++ uint retries; ++ u32 regdata; ++ int bcmerror = 0; ++ ++ /* To enter download state, disable ARM and reset SOCRAM. ++ * To exit download state, simply reset ARM (default is RAM boot). ++ */ ++ if (enter) { ++ bus->alp_only = true; ++ ++ brcmf_sdbrcm_chip_disablecore(bus->sdiodev, ++ bus->ci->armcorebase); ++ ++ brcmf_sdbrcm_chip_resetcore(bus->sdiodev, bus->ci->ramcorebase); ++ ++ /* Clear the top bit of memory */ ++ if (bus->ramsize) { ++ u32 zeros = 0; ++ brcmf_sdbrcm_membytes(bus, true, bus->ramsize - 4, ++ (u8 *)&zeros, 4); ++ } ++ } else { ++ regdata = brcmf_sdcard_reg_read(bus->sdiodev, ++ CORE_SB(bus->ci->ramcorebase, sbtmstatelow), 4); ++ regdata &= (SBTML_RESET | SBTML_REJ_MASK | ++ (SICF_CLOCK_EN << SBTML_SICF_SHIFT)); ++ if ((SICF_CLOCK_EN << SBTML_SICF_SHIFT) != regdata) { ++ brcmf_dbg(ERROR, "SOCRAM core is down after reset?\n"); ++ bcmerror = -EBADE; ++ goto fail; ++ } ++ ++ bcmerror = brcmf_sdbrcm_write_vars(bus); ++ if (bcmerror) { ++ brcmf_dbg(ERROR, "no vars written to RAM\n"); ++ bcmerror = 0; ++ } ++ ++ w_sdreg32(bus, 0xFFFFFFFF, ++ offsetof(struct sdpcmd_regs, intstatus), &retries); ++ ++ brcmf_sdbrcm_chip_resetcore(bus->sdiodev, bus->ci->armcorebase); ++ ++ /* Allow HT Clock now that the ARM is running. */ ++ bus->alp_only = false; ++ ++ bus->drvr->busstate = BRCMF_BUS_LOAD; ++ } ++fail: ++ return bcmerror; ++} ++ ++static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus) ++{ ++ if (bus->firmware->size < bus->fw_ptr + len) ++ len = bus->firmware->size - bus->fw_ptr; ++ ++ memcpy(buf, &bus->firmware->data[bus->fw_ptr], len); ++ bus->fw_ptr += len; ++ return len; ++} ++ ++MODULE_FIRMWARE(BCM4329_FW_NAME); ++MODULE_FIRMWARE(BCM4329_NV_NAME); ++ ++static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus) ++{ ++ int offset = 0; ++ uint len; ++ u8 *memblock = NULL, *memptr; ++ int ret; ++ ++ brcmf_dbg(INFO, "Enter\n"); ++ ++ bus->fw_name = BCM4329_FW_NAME; ++ ret = request_firmware(&bus->firmware, bus->fw_name, ++ &bus->sdiodev->func[2]->dev); ++ if (ret) { ++ brcmf_dbg(ERROR, "Fail to request firmware %d\n", ret); ++ return ret; ++ } ++ bus->fw_ptr = 0; ++ ++ memptr = memblock = kmalloc(MEMBLOCK + BRCMF_SDALIGN, GFP_ATOMIC); ++ if (memblock == NULL) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ if ((u32)(unsigned long)memblock % BRCMF_SDALIGN) ++ memptr += (BRCMF_SDALIGN - ++ ((u32)(unsigned long)memblock % BRCMF_SDALIGN)); ++ ++ /* Download image */ ++ while ((len = ++ brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus))) { ++ ret = brcmf_sdbrcm_membytes(bus, true, offset, memptr, len); ++ if (ret) { ++ brcmf_dbg(ERROR, "error %d on writing %d membytes at 0x%08x\n", ++ ret, MEMBLOCK, offset); ++ goto err; ++ } ++ ++ offset += MEMBLOCK; ++ } ++ ++err: ++ kfree(memblock); ++ ++ release_firmware(bus->firmware); ++ bus->fw_ptr = 0; ++ ++ return ret; ++} ++ ++/* ++ * ProcessVars:Takes a buffer of "=\n" lines read from a file ++ * and ending in a NUL. ++ * Removes carriage returns, empty lines, comment lines, and converts ++ * newlines to NULs. ++ * Shortens buffer as needed and pads with NULs. End of buffer is marked ++ * by two NULs. ++*/ ++ ++static uint brcmf_process_nvram_vars(char *varbuf, uint len) ++{ ++ char *dp; ++ bool findNewline; ++ int column; ++ uint buf_len, n; ++ ++ dp = varbuf; ++ ++ findNewline = false; ++ column = 0; ++ ++ for (n = 0; n < len; n++) { ++ if (varbuf[n] == 0) ++ break; ++ if (varbuf[n] == '\r') ++ continue; ++ if (findNewline && varbuf[n] != '\n') ++ continue; ++ findNewline = false; ++ if (varbuf[n] == '#') { ++ findNewline = true; ++ continue; ++ } ++ if (varbuf[n] == '\n') { ++ if (column == 0) ++ continue; ++ *dp++ = 0; ++ column = 0; ++ continue; ++ } ++ *dp++ = varbuf[n]; ++ column++; ++ } ++ buf_len = dp - varbuf; ++ ++ while (dp < varbuf + n) ++ *dp++ = 0; ++ ++ return buf_len; ++} ++ ++static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus) ++{ ++ uint len; ++ char *memblock = NULL; ++ char *bufp; ++ int ret; ++ ++ bus->nv_name = BCM4329_NV_NAME; ++ ret = request_firmware(&bus->firmware, bus->nv_name, ++ &bus->sdiodev->func[2]->dev); ++ if (ret) { ++ brcmf_dbg(ERROR, "Fail to request nvram %d\n", ret); ++ return ret; ++ } ++ bus->fw_ptr = 0; ++ ++ memblock = kmalloc(MEMBLOCK, GFP_ATOMIC); ++ if (memblock == NULL) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ len = brcmf_sdbrcm_get_image(memblock, MEMBLOCK, bus); ++ ++ if (len > 0 && len < MEMBLOCK) { ++ bufp = (char *)memblock; ++ bufp[len] = 0; ++ len = brcmf_process_nvram_vars(bufp, len); ++ bufp += len; ++ *bufp++ = 0; ++ if (len) ++ ret = brcmf_sdbrcm_downloadvars(bus, memblock, len + 1); ++ if (ret) ++ brcmf_dbg(ERROR, "error downloading vars: %d\n", ret); ++ } else { ++ brcmf_dbg(ERROR, "error reading nvram file: %d\n", len); ++ ret = -EIO; ++ } ++ ++err: ++ kfree(memblock); ++ ++ release_firmware(bus->firmware); ++ bus->fw_ptr = 0; ++ ++ return ret; ++} ++ ++static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus) ++{ ++ int bcmerror = -1; ++ ++ /* Keep arm in reset */ ++ if (brcmf_sdbrcm_download_state(bus, true)) { ++ brcmf_dbg(ERROR, "error placing ARM core in reset\n"); ++ goto err; ++ } ++ ++ /* External image takes precedence if specified */ ++ if (brcmf_sdbrcm_download_code_file(bus)) { ++ brcmf_dbg(ERROR, "dongle image file download failed\n"); ++ goto err; ++ } ++ ++ /* External nvram takes precedence if specified */ ++ if (brcmf_sdbrcm_download_nvram(bus)) ++ brcmf_dbg(ERROR, "dongle nvram file download failed\n"); ++ ++ /* Take arm out of reset */ ++ if (brcmf_sdbrcm_download_state(bus, false)) { ++ brcmf_dbg(ERROR, "error getting out of ARM core reset\n"); ++ goto err; ++ } ++ ++ bcmerror = 0; ++ ++err: ++ return bcmerror; ++} ++ ++static bool ++brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus) ++{ ++ bool ret; ++ ++ /* Download the firmware */ ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); ++ ++ ret = _brcmf_sdbrcm_download_firmware(bus) == 0; ++ ++ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); ++ ++ return ret; ++} ++ ++void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus) ++{ ++ u32 local_hostintmask; ++ u8 saveclk; ++ uint retries; ++ int err; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (bus->watchdog_tsk) { ++ send_sig(SIGTERM, bus->watchdog_tsk, 1); ++ kthread_stop(bus->watchdog_tsk); ++ bus->watchdog_tsk = NULL; ++ } ++ ++ if (bus->dpc_tsk && bus->dpc_tsk != current) { ++ send_sig(SIGTERM, bus->dpc_tsk, 1); ++ kthread_stop(bus->dpc_tsk); ++ bus->dpc_tsk = NULL; ++ } ++ ++ down(&bus->sdsem); ++ ++ bus_wake(bus); ++ ++ /* Enable clock for device interrupts */ ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); ++ ++ /* Disable and clear interrupts at the chip level also */ ++ w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask), &retries); ++ local_hostintmask = bus->hostintmask; ++ bus->hostintmask = 0; ++ ++ /* Change our idea of bus state */ ++ bus->drvr->busstate = BRCMF_BUS_DOWN; ++ ++ /* Force clocks on backplane to be sure F2 interrupt propagates */ ++ saveclk = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ if (!err) { ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, ++ (saveclk | SBSDIO_FORCE_HT), &err); ++ } ++ if (err) ++ brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err); ++ ++ /* Turn off the bus (F2), free any pending packets */ ++ brcmf_dbg(INTR, "disable SDIO interrupts\n"); ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, ++ SDIO_FUNC_ENABLE_1, NULL); ++ ++ /* Clear any pending interrupts now that F2 is disabled */ ++ w_sdreg32(bus, local_hostintmask, ++ offsetof(struct sdpcmd_regs, intstatus), &retries); ++ ++ /* Turn off the backplane clock (only) */ ++ brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); ++ ++ /* Clear the data packet queues */ ++ brcmu_pktq_flush(&bus->txq, true, NULL, NULL); ++ ++ /* Clear any held glomming stuff */ ++ if (bus->glomd) ++ brcmu_pkt_buf_free_skb(bus->glomd); ++ ++ if (bus->glom) ++ brcmu_pkt_buf_free_skb(bus->glom); ++ ++ bus->glom = bus->glomd = NULL; ++ ++ /* Clear rx control and wake any waiters */ ++ bus->rxlen = 0; ++ brcmf_sdbrcm_dcmd_resp_wake(bus); ++ ++ /* Reset some F2 state stuff */ ++ bus->rxskip = false; ++ bus->tx_seq = bus->rx_seq = 0; ++ ++ up(&bus->sdsem); ++} ++ ++int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr) ++{ ++ struct brcmf_bus *bus = drvr->bus; ++ unsigned long timeout; ++ uint retries = 0; ++ u8 ready, enable; ++ int err, ret = 0; ++ u8 saveclk; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* try to download image and nvram to the dongle */ ++ if (drvr->busstate == BRCMF_BUS_DOWN) { ++ if (!(brcmf_sdbrcm_download_firmware(bus))) ++ return -1; ++ } ++ ++ if (!bus->drvr) ++ return 0; ++ ++ /* Start the watchdog timer */ ++ bus->drvr->tickcnt = 0; ++ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); ++ ++ down(&bus->sdsem); ++ ++ /* Make sure backplane clock is on, needed to generate F2 interrupt */ ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); ++ if (bus->clkstate != CLK_AVAIL) ++ goto exit; ++ ++ /* Force clocks on backplane to be sure F2 interrupt propagates */ ++ saveclk = ++ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ if (!err) { ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, ++ (saveclk | SBSDIO_FORCE_HT), &err); ++ } ++ if (err) { ++ brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err); ++ goto exit; ++ } ++ ++ /* Enable function 2 (frame transfers) */ ++ w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, ++ offsetof(struct sdpcmd_regs, tosbmailboxdata), &retries); ++ enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2); ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, ++ enable, NULL); ++ ++ timeout = jiffies + msecs_to_jiffies(BRCMF_WAIT_F2RDY); ++ ready = 0; ++ while (enable != ready) { ++ ready = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_0, ++ SDIO_CCCR_IORx, NULL); ++ if (time_after(jiffies, timeout)) ++ break; ++ else if (time_after(jiffies, timeout - BRCMF_WAIT_F2RDY + 50)) ++ /* prevent busy waiting if it takes too long */ ++ msleep_interruptible(20); ++ } ++ ++ brcmf_dbg(INFO, "enable 0x%02x, ready 0x%02x\n", enable, ready); ++ ++ /* If F2 successfully enabled, set core and enable interrupts */ ++ if (ready == enable) { ++ /* Set up the interrupt mask and enable interrupts */ ++ bus->hostintmask = HOSTINTMASK; ++ w_sdreg32(bus, bus->hostintmask, ++ offsetof(struct sdpcmd_regs, hostintmask), &retries); ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_WATERMARK, 8, &err); ++ ++ /* Set bus state according to enable result */ ++ drvr->busstate = BRCMF_BUS_DATA; ++ } ++ ++ else { ++ /* Disable F2 again */ ++ enable = SDIO_FUNC_ENABLE_1; ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, ++ SDIO_CCCR_IOEx, enable, NULL); ++ } ++ ++ /* Restore previous clock setting */ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); ++ ++ /* If we didn't come up, turn off backplane clock */ ++ if (drvr->busstate != BRCMF_BUS_DATA) ++ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); ++ ++exit: ++ up(&bus->sdsem); ++ ++ return ret; ++} ++ ++void brcmf_sdbrcm_isr(void *arg) ++{ ++ struct brcmf_bus *bus = (struct brcmf_bus *) arg; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (!bus) { ++ brcmf_dbg(ERROR, "bus is null pointer, exiting\n"); ++ return; ++ } ++ ++ if (bus->drvr->busstate == BRCMF_BUS_DOWN) { ++ brcmf_dbg(ERROR, "bus is down. we have nothing to do\n"); ++ return; ++ } ++ /* Count the interrupt call */ ++ bus->intrcount++; ++ bus->ipend = true; ++ ++ /* Shouldn't get this interrupt if we're sleeping? */ ++ if (bus->sleeping) { ++ brcmf_dbg(ERROR, "INTERRUPT WHILE SLEEPING??\n"); ++ return; ++ } ++ ++ /* Disable additional interrupts (is this needed now)? */ ++ if (!bus->intr) ++ brcmf_dbg(ERROR, "isr w/o interrupt configured!\n"); ++ ++ bus->dpc_sched = true; ++ if (bus->dpc_tsk) ++ complete(&bus->dpc_wait); ++} ++ ++static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_pub *drvr) ++{ ++ struct brcmf_bus *bus; ++ ++ brcmf_dbg(TIMER, "Enter\n"); ++ ++ bus = drvr->bus; ++ ++ /* Ignore the timer if simulating bus down */ ++ if (bus->sleeping) ++ return false; ++ ++ down(&bus->sdsem); ++ ++ /* Poll period: check device if appropriate. */ ++ if (bus->poll && (++bus->polltick >= bus->pollrate)) { ++ u32 intstatus = 0; ++ ++ /* Reset poll tick */ ++ bus->polltick = 0; ++ ++ /* Check device if no interrupts */ ++ if (!bus->intr || (bus->intrcount == bus->lastintrs)) { ++ ++ if (!bus->dpc_sched) { ++ u8 devpend; ++ devpend = brcmf_sdcard_cfg_read(bus->sdiodev, ++ SDIO_FUNC_0, SDIO_CCCR_INTx, ++ NULL); ++ intstatus = ++ devpend & (INTR_STATUS_FUNC1 | ++ INTR_STATUS_FUNC2); ++ } ++ ++ /* If there is something, make like the ISR and ++ schedule the DPC */ ++ if (intstatus) { ++ bus->pollcnt++; ++ bus->ipend = true; ++ ++ bus->dpc_sched = true; ++ if (bus->dpc_tsk) ++ complete(&bus->dpc_wait); ++ } ++ } ++ ++ /* Update interrupt tracking */ ++ bus->lastintrs = bus->intrcount; ++ } ++#ifdef BCMDBG ++ /* Poll for console output periodically */ ++ if (drvr->busstate == BRCMF_BUS_DATA && bus->console_interval != 0) { ++ bus->console.count += BRCMF_WD_POLL_MS; ++ if (bus->console.count >= bus->console_interval) { ++ bus->console.count -= bus->console_interval; ++ /* Make sure backplane clock is on */ ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); ++ if (brcmf_sdbrcm_readconsole(bus) < 0) ++ /* stop on error */ ++ bus->console_interval = 0; ++ } ++ } ++#endif /* BCMDBG */ ++ ++ /* On idle timeout clear activity flag and/or turn off clock */ ++ if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { ++ if (++bus->idlecount >= bus->idletime) { ++ bus->idlecount = 0; ++ if (bus->activity) { ++ bus->activity = false; ++ brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); ++ } else { ++ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); ++ } ++ } ++ } ++ ++ up(&bus->sdsem); ++ ++ return bus->ipend; ++} ++ ++static bool brcmf_sdbrcm_chipmatch(u16 chipid) ++{ ++ if (chipid == BCM4329_CHIP_ID) ++ return true; ++ return false; ++} ++ ++static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ kfree(bus->rxbuf); ++ bus->rxctl = bus->rxbuf = NULL; ++ bus->rxlen = 0; ++ ++ kfree(bus->databuf); ++ bus->databuf = NULL; ++} ++ ++static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (bus->drvr->maxctl) { ++ bus->rxblen = ++ roundup((bus->drvr->maxctl + SDPCM_HDRLEN), ++ ALIGNMENT) + BRCMF_SDALIGN; ++ bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC); ++ if (!(bus->rxbuf)) ++ goto fail; ++ } ++ ++ /* Allocate buffer to receive glomed packet */ ++ bus->databuf = kmalloc(MAX_DATA_BUF, GFP_ATOMIC); ++ if (!(bus->databuf)) { ++ /* release rxbuf which was already located as above */ ++ if (!bus->rxblen) ++ kfree(bus->rxbuf); ++ goto fail; ++ } ++ ++ /* Align the buffer */ ++ if ((unsigned long)bus->databuf % BRCMF_SDALIGN) ++ bus->dataptr = bus->databuf + (BRCMF_SDALIGN - ++ ((unsigned long)bus->databuf % BRCMF_SDALIGN)); ++ else ++ bus->dataptr = bus->databuf; ++ ++ return true; ++ ++fail: ++ return false; ++} ++ ++/* SDIO Pad drive strength to select value mappings */ ++struct sdiod_drive_str { ++ u8 strength; /* Pad Drive Strength in mA */ ++ u8 sel; /* Chip-specific select value */ ++}; ++ ++/* SDIO Drive Strength to sel value table for PMU Rev 1 */ ++static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = { ++ { ++ 4, 0x2}, { ++ 2, 0x3}, { ++ 1, 0x0}, { ++ 0, 0x0} ++ }; ++ ++/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */ ++static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = { ++ { ++ 12, 0x7}, { ++ 10, 0x6}, { ++ 8, 0x5}, { ++ 6, 0x4}, { ++ 4, 0x2}, { ++ 2, 0x1}, { ++ 0, 0x0} ++ }; ++ ++/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */ ++static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = { ++ { ++ 32, 0x7}, { ++ 26, 0x6}, { ++ 22, 0x5}, { ++ 16, 0x4}, { ++ 12, 0x3}, { ++ 8, 0x2}, { ++ 4, 0x1}, { ++ 0, 0x0} ++ }; ++ ++#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) ++ ++static char *brcmf_chipname(uint chipid, char *buf, uint len) ++{ ++ const char *fmt; ++ ++ fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x"; ++ snprintf(buf, len, fmt, chipid); ++ return buf; ++} ++ ++static void brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus, ++ u32 drivestrength) { ++ struct sdiod_drive_str *str_tab = NULL; ++ u32 str_mask = 0; ++ u32 str_shift = 0; ++ char chn[8]; ++ ++ if (!(bus->ci->cccaps & CC_CAP_PMU)) ++ return; ++ ++ switch (SDIOD_DRVSTR_KEY(bus->ci->chip, bus->ci->pmurev)) { ++ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1): ++ str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1; ++ str_mask = 0x30000000; ++ str_shift = 28; ++ break; ++ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2): ++ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3): ++ str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2; ++ str_mask = 0x00003800; ++ str_shift = 11; ++ break; ++ case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8): ++ str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3; ++ str_mask = 0x00003800; ++ str_shift = 11; ++ break; ++ default: ++ brcmf_dbg(ERROR, "No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", ++ brcmf_chipname(bus->ci->chip, chn, 8), ++ bus->ci->chiprev, bus->ci->pmurev); ++ break; ++ } ++ ++ if (str_tab != NULL) { ++ u32 drivestrength_sel = 0; ++ u32 cc_data_temp; ++ int i; ++ ++ for (i = 0; str_tab[i].strength != 0; i++) { ++ if (drivestrength >= str_tab[i].strength) { ++ drivestrength_sel = str_tab[i].sel; ++ break; ++ } ++ } ++ ++ brcmf_sdcard_reg_write(bus->sdiodev, ++ CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), ++ 4, 1); ++ cc_data_temp = brcmf_sdcard_reg_read(bus->sdiodev, ++ CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), 4); ++ cc_data_temp &= ~str_mask; ++ drivestrength_sel <<= str_shift; ++ cc_data_temp |= drivestrength_sel; ++ brcmf_sdcard_reg_write(bus->sdiodev, ++ CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), ++ 4, cc_data_temp); ++ ++ brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n", ++ drivestrength, cc_data_temp); ++ } ++} ++ ++static int ++brcmf_sdbrcm_chip_recognition(struct brcmf_sdio_dev *sdiodev, ++ struct chip_info *ci, u32 regs) ++{ ++ u32 regdata; ++ ++ /* ++ * Get CC core rev ++ * Chipid is assume to be at offset 0 from regs arg ++ * For different chiptypes or old sdio hosts w/o chipcommon, ++ * other ways of recognition should be added here. ++ */ ++ ci->cccorebase = regs; ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_CC_REG(ci->cccorebase, chipid), 4); ++ ci->chip = regdata & CID_ID_MASK; ++ ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; ++ ++ brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev); ++ ++ /* Address of cores for new chips should be added here */ ++ switch (ci->chip) { ++ case BCM4329_CHIP_ID: ++ ci->buscorebase = BCM4329_CORE_BUS_BASE; ++ ci->ramcorebase = BCM4329_CORE_SOCRAM_BASE; ++ ci->armcorebase = BCM4329_CORE_ARM_BASE; ++ ci->ramsize = BCM4329_RAMSIZE; ++ break; ++ default: ++ brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip); ++ return -ENODEV; ++ } ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(ci->cccorebase, sbidhigh), 4); ++ ci->ccrev = SBCOREREV(regdata); ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_CC_REG(ci->cccorebase, pmucapabilities), 4); ++ ci->pmurev = regdata & PCAP_REV_MASK; ++ ++ regdata = brcmf_sdcard_reg_read(sdiodev, ++ CORE_SB(ci->buscorebase, sbidhigh), 4); ++ ci->buscorerev = SBCOREREV(regdata); ++ ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT; ++ ++ brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n", ++ ci->ccrev, ci->pmurev, ci->buscorerev, ci->buscoretype); ++ ++ /* get chipcommon capabilites */ ++ ci->cccaps = brcmf_sdcard_reg_read(sdiodev, ++ CORE_CC_REG(ci->cccorebase, capabilities), 4); ++ ++ return 0; ++} ++ ++static int ++brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs) ++{ ++ struct chip_info *ci; ++ int err; ++ u8 clkval, clkset; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* alloc chip_info_t */ ++ ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC); ++ if (NULL == ci) ++ return -ENOMEM; ++ ++ /* bus/core/clk setup for register access */ ++ /* Try forcing SDIO core to do ALPAvail request only */ ++ clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); ++ if (err) { ++ brcmf_dbg(ERROR, "error writing for HT off\n"); ++ goto fail; ++ } ++ ++ /* If register supported, wait for ALPAvail and then force ALP */ ++ /* This may take up to 15 milliseconds */ ++ clkval = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, NULL); ++ if ((clkval & ~SBSDIO_AVBITS) == clkset) { ++ SPINWAIT(((clkval = ++ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, ++ NULL)), ++ !SBSDIO_ALPAV(clkval)), ++ PMU_MAX_TRANSITION_DLY); ++ if (!SBSDIO_ALPAV(clkval)) { ++ brcmf_dbg(ERROR, "timeout on ALPAV wait, clkval 0x%02x\n", ++ clkval); ++ err = -EBUSY; ++ goto fail; ++ } ++ clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | ++ SBSDIO_FORCE_ALP; ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, ++ clkset, &err); ++ udelay(65); ++ } else { ++ brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n", ++ clkset, clkval); ++ err = -EACCES; ++ goto fail; ++ } ++ ++ /* Also, disable the extra SDIO pull-ups */ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); ++ ++ err = brcmf_sdbrcm_chip_recognition(bus->sdiodev, ci, regs); ++ if (err) ++ goto fail; ++ ++ /* ++ * Make sure any on-chip ARM is off (in case strapping is wrong), ++ * or downloaded code was already running. ++ */ ++ brcmf_sdbrcm_chip_disablecore(bus->sdiodev, ci->armcorebase); ++ ++ brcmf_sdcard_reg_write(bus->sdiodev, ++ CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0); ++ brcmf_sdcard_reg_write(bus->sdiodev, ++ CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0); ++ ++ /* Disable F2 to clear any intermediate frame state on the dongle */ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, ++ SDIO_FUNC_ENABLE_1, NULL); ++ ++ /* WAR: cmd52 backplane read so core HW will drop ALPReq */ ++ clkval = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ 0, NULL); ++ ++ /* Done with backplane-dependent accesses, can drop clock... */ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); ++ ++ bus->ci = ci; ++ return 0; ++fail: ++ bus->ci = NULL; ++ kfree(ci); ++ return err; ++} ++ ++static bool ++brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva) ++{ ++ u8 clkctl = 0; ++ int err = 0; ++ int reg_addr; ++ u32 reg_val; ++ ++ bus->alp_only = true; ++ ++ /* Return the window to backplane enumeration space for core access */ ++ if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, SI_ENUM_BASE)) ++ brcmf_dbg(ERROR, "FAILED to return to SI_ENUM_BASE\n"); ++ ++#ifdef BCMDBG ++ printk(KERN_DEBUG "F1 signature read @0x18000000=0x%4x\n", ++ brcmf_sdcard_reg_read(bus->sdiodev, SI_ENUM_BASE, 4)); ++ ++#endif /* BCMDBG */ ++ ++ /* ++ * Force PLL off until brcmf_sdbrcm_chip_attach() ++ * programs PLL control regs ++ */ ++ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, ++ BRCMF_INIT_CLKCTL1, &err); ++ if (!err) ++ clkctl = ++ brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ ++ if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) { ++ brcmf_dbg(ERROR, "ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n", ++ err, BRCMF_INIT_CLKCTL1, clkctl); ++ goto fail; ++ } ++ ++ if (brcmf_sdbrcm_chip_attach(bus, regsva)) { ++ brcmf_dbg(ERROR, "brcmf_sdbrcm_chip_attach failed!\n"); ++ goto fail; ++ } ++ ++ if (!brcmf_sdbrcm_chipmatch((u16) bus->ci->chip)) { ++ brcmf_dbg(ERROR, "unsupported chip: 0x%04x\n", bus->ci->chip); ++ goto fail; ++ } ++ ++ brcmf_sdbrcm_sdiod_drive_strength_init(bus, SDIO_DRIVE_STRENGTH); ++ ++ /* Get info on the ARM and SOCRAM cores... */ ++ brcmf_sdcard_reg_read(bus->sdiodev, ++ CORE_SB(bus->ci->armcorebase, sbidhigh), 4); ++ bus->ramsize = bus->ci->ramsize; ++ if (!(bus->ramsize)) { ++ brcmf_dbg(ERROR, "failed to find SOCRAM memory!\n"); ++ goto fail; ++ } ++ ++ /* Set core control so an SDIO reset does a backplane reset */ ++ reg_addr = bus->ci->buscorebase + ++ offsetof(struct sdpcmd_regs, corecontrol); ++ reg_val = brcmf_sdcard_reg_read(bus->sdiodev, reg_addr, sizeof(u32)); ++ brcmf_sdcard_reg_write(bus->sdiodev, reg_addr, sizeof(u32), ++ reg_val | CC_BPRESEN); ++ ++ brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN); ++ ++ /* Locate an appropriately-aligned portion of hdrbuf */ ++ bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0], ++ BRCMF_SDALIGN); ++ ++ /* Set the poll and/or interrupt flags */ ++ bus->intr = true; ++ bus->poll = false; ++ if (bus->poll) ++ bus->pollrate = 1; ++ ++ return true; ++ ++fail: ++ return false; ++} ++ ++static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* Disable F2 to clear any intermediate frame state on the dongle */ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, ++ SDIO_FUNC_ENABLE_1, NULL); ++ ++ bus->drvr->busstate = BRCMF_BUS_DOWN; ++ bus->sleeping = false; ++ bus->rxflow = false; ++ ++ /* Done with backplane-dependent accesses, can drop clock... */ ++ brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); ++ ++ /* ...and initialize clock/power states */ ++ bus->clkstate = CLK_SDONLY; ++ bus->idletime = BRCMF_IDLE_INTERVAL; ++ bus->idleclock = BRCMF_IDLE_ACTIVE; ++ ++ /* Query the F2 block size, set roundup accordingly */ ++ bus->blocksize = bus->sdiodev->func[2]->cur_blksize; ++ bus->roundup = min(max_roundup, bus->blocksize); ++ ++ /* bus module does not support packet chaining */ ++ bus->use_rxchain = false; ++ bus->sd_rxchain = false; ++ ++ return true; ++} ++ ++static int ++brcmf_sdbrcm_watchdog_thread(void *data) ++{ ++ struct brcmf_bus *bus = (struct brcmf_bus *)data; ++ ++ allow_signal(SIGTERM); ++ /* Run until signal received */ ++ while (1) { ++ if (kthread_should_stop()) ++ break; ++ if (!wait_for_completion_interruptible(&bus->watchdog_wait)) { ++ brcmf_sdbrcm_bus_watchdog(bus->drvr); ++ /* Count the tick for reference */ ++ bus->drvr->tickcnt++; ++ } else ++ break; ++ } ++ return 0; ++} ++ ++static void ++brcmf_sdbrcm_watchdog(unsigned long data) ++{ ++ struct brcmf_bus *bus = (struct brcmf_bus *)data; ++ ++ if (bus->watchdog_tsk) { ++ complete(&bus->watchdog_wait); ++ /* Reschedule the watchdog */ ++ if (bus->wd_timer_valid) ++ mod_timer(&bus->timer, ++ jiffies + BRCMF_WD_POLL_MS * HZ / 1000); ++ } ++} ++ ++static void ++brcmf_sdbrcm_chip_detach(struct brcmf_bus *bus) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ kfree(bus->ci); ++ bus->ci = NULL; ++} ++ ++static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (bus->ci) { ++ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); ++ brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); ++ brcmf_sdbrcm_chip_detach(bus); ++ if (bus->vars && bus->varsz) ++ kfree(bus->vars); ++ bus->vars = NULL; ++ } ++ ++ brcmf_dbg(TRACE, "Disconnected\n"); ++} ++ ++/* Detach and free everything */ ++static void brcmf_sdbrcm_release(struct brcmf_bus *bus) ++{ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (bus) { ++ /* De-register interrupt handler */ ++ brcmf_sdcard_intr_dereg(bus->sdiodev); ++ ++ if (bus->drvr) { ++ brcmf_detach(bus->drvr); ++ brcmf_sdbrcm_release_dongle(bus); ++ bus->drvr = NULL; ++ } ++ ++ brcmf_sdbrcm_release_malloc(bus); ++ ++ kfree(bus); ++ } ++ ++ brcmf_dbg(TRACE, "Disconnected\n"); ++} ++ ++void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype, ++ u32 regsva, struct brcmf_sdio_dev *sdiodev) ++{ ++ int ret; ++ struct brcmf_bus *bus; ++ ++ /* Init global variables at run-time, not as part of the declaration. ++ * This is required to support init/de-init of the driver. ++ * Initialization ++ * of globals as part of the declaration results in non-deterministic ++ * behavior since the value of the globals may be different on the ++ * first time that the driver is initialized vs subsequent ++ * initializations. ++ */ ++ brcmf_c_init(); ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ /* We make an assumption about address window mappings: ++ * regsva == SI_ENUM_BASE*/ ++ ++ /* Allocate private bus interface state */ ++ bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC); ++ if (!bus) ++ goto fail; ++ ++ bus->sdiodev = sdiodev; ++ sdiodev->bus = bus; ++ bus->txbound = BRCMF_TXBOUND; ++ bus->rxbound = BRCMF_RXBOUND; ++ bus->txminmax = BRCMF_TXMINMAX; ++ bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1; ++ bus->usebufpool = false; /* Use bufpool if allocated, ++ else use locally malloced rxbuf */ ++ ++ /* attempt to attach to the dongle */ ++ if (!(brcmf_sdbrcm_probe_attach(bus, regsva))) { ++ brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_attach failed\n"); ++ goto fail; ++ } ++ ++ spin_lock_init(&bus->txqlock); ++ init_waitqueue_head(&bus->ctrl_wait); ++ init_waitqueue_head(&bus->dcmd_resp_wait); ++ ++ /* Set up the watchdog timer */ ++ init_timer(&bus->timer); ++ bus->timer.data = (unsigned long)bus; ++ bus->timer.function = brcmf_sdbrcm_watchdog; ++ ++ /* Initialize thread based operation and lock */ ++ sema_init(&bus->sdsem, 1); ++ ++ /* Initialize watchdog thread */ ++ init_completion(&bus->watchdog_wait); ++ bus->watchdog_tsk = kthread_run(brcmf_sdbrcm_watchdog_thread, ++ bus, "brcmf_watchdog"); ++ if (IS_ERR(bus->watchdog_tsk)) { ++ printk(KERN_WARNING ++ "brcmf_watchdog thread failed to start\n"); ++ bus->watchdog_tsk = NULL; ++ } ++ /* Initialize DPC thread */ ++ init_completion(&bus->dpc_wait); ++ bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread, ++ bus, "brcmf_dpc"); ++ if (IS_ERR(bus->dpc_tsk)) { ++ printk(KERN_WARNING ++ "brcmf_dpc thread failed to start\n"); ++ bus->dpc_tsk = NULL; ++ } ++ ++ /* Attach to the brcmf/OS/network interface */ ++ bus->drvr = brcmf_attach(bus, SDPCM_RESERVE); ++ if (!bus->drvr) { ++ brcmf_dbg(ERROR, "brcmf_attach failed\n"); ++ goto fail; ++ } ++ ++ /* Allocate buffers */ ++ if (!(brcmf_sdbrcm_probe_malloc(bus))) { ++ brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_malloc failed\n"); ++ goto fail; ++ } ++ ++ if (!(brcmf_sdbrcm_probe_init(bus))) { ++ brcmf_dbg(ERROR, "brcmf_sdbrcm_probe_init failed\n"); ++ goto fail; ++ } ++ ++ /* Register interrupt callback, but mask it (not operational yet). */ ++ brcmf_dbg(INTR, "disable SDIO interrupts (not interested yet)\n"); ++ ret = brcmf_sdcard_intr_reg(bus->sdiodev); ++ if (ret != 0) { ++ brcmf_dbg(ERROR, "FAILED: sdcard_intr_reg returned %d\n", ret); ++ goto fail; ++ } ++ brcmf_dbg(INTR, "registered SDIO interrupt function ok\n"); ++ ++ brcmf_dbg(INFO, "completed!!\n"); ++ ++ /* if firmware path present try to download and bring up bus */ ++ ret = brcmf_bus_start(bus->drvr); ++ if (ret != 0) { ++ if (ret == -ENOLINK) { ++ brcmf_dbg(ERROR, "dongle is not responding\n"); ++ goto fail; ++ } ++ } ++ /* Ok, have the per-port tell the stack we're open for business */ ++ if (brcmf_net_attach(bus->drvr, 0) != 0) { ++ brcmf_dbg(ERROR, "Net attach failed!!\n"); ++ goto fail; ++ } ++ ++ return bus; ++ ++fail: ++ brcmf_sdbrcm_release(bus); ++ return NULL; ++} ++ ++void brcmf_sdbrcm_disconnect(void *ptr) ++{ ++ struct brcmf_bus *bus = (struct brcmf_bus *)ptr; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ if (bus) ++ brcmf_sdbrcm_release(bus); ++ ++ brcmf_dbg(TRACE, "Disconnected\n"); ++} ++ ++struct device *brcmf_bus_get_device(struct brcmf_bus *bus) ++{ ++ return &bus->sdiodev->func[2]->dev; ++} ++ ++void ++brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick) ++{ ++ /* don't start the wd until fw is loaded */ ++ if (bus->drvr->busstate == BRCMF_BUS_DOWN) ++ return; ++ ++ /* Totally stop the timer */ ++ if (!wdtick && bus->wd_timer_valid == true) { ++ del_timer_sync(&bus->timer); ++ bus->wd_timer_valid = false; ++ bus->save_ms = wdtick; ++ return; ++ } ++ ++ if (wdtick) { ++ if (bus->save_ms != BRCMF_WD_POLL_MS) { ++ if (bus->wd_timer_valid == true) ++ /* Stop timer and restart at new value */ ++ del_timer_sync(&bus->timer); ++ ++ /* Create timer again when watchdog period is ++ dynamically changed or in the first instance ++ */ ++ bus->timer.expires = ++ jiffies + BRCMF_WD_POLL_MS * HZ / 1000; ++ add_timer(&bus->timer); ++ ++ } else { ++ /* Re arm the timer, at last watchdog period */ ++ mod_timer(&bus->timer, ++ jiffies + BRCMF_WD_POLL_MS * HZ / 1000); ++ } ++ ++ bus->wd_timer_valid = true; ++ bus->save_ms = wdtick; ++ } ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/Makefile.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/Makefile +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/Makefile.orig 2011-11-09 13:46:58.235800758 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/Makefile 2011-11-09 13:47:16.986566342 -0500 +@@ -0,0 +1,33 @@ ++# ++# Makefile fragment for Broadcom 802.11n Networking Device Driver ++# ++# Copyright (c) 2010 Broadcom Corporation ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ccflags-y += \ ++ -Idrivers/net/wireless/brcm80211/brcmfmac \ ++ -Idrivers/net/wireless/brcm80211/include ++ ++DHDOFILES = \ ++ wl_cfg80211.o \ ++ dhd_cdc.o \ ++ dhd_common.o \ ++ dhd_sdio.o \ ++ dhd_linux.o \ ++ bcmsdh.o \ ++ bcmsdh_sdmmc.o ++ ++obj-$(CONFIG_BRCMFMAC) += brcmfmac.o ++brcmfmac-objs += $(DHDOFILES) ++ccflags-y += -D__CHECK_ENDIAN__ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h.orig 2011-11-09 13:46:58.235800758 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h 2011-11-09 13:47:16.987566330 -0500 +@@ -0,0 +1,252 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_SDH_H_ ++#define _BRCM_SDH_H_ ++ ++#include ++ ++#define SDIO_FUNC_0 0 ++#define SDIO_FUNC_1 1 ++#define SDIO_FUNC_2 2 ++ ++#define SDIOD_FBR_SIZE 0x100 ++ ++/* io_en */ ++#define SDIO_FUNC_ENABLE_1 0x02 ++#define SDIO_FUNC_ENABLE_2 0x04 ++ ++/* io_rdys */ ++#define SDIO_FUNC_READY_1 0x02 ++#define SDIO_FUNC_READY_2 0x04 ++ ++/* intr_status */ ++#define INTR_STATUS_FUNC1 0x2 ++#define INTR_STATUS_FUNC2 0x4 ++ ++/* Maximum number of I/O funcs */ ++#define SDIOD_MAX_IOFUNCS 7 ++ ++/* as of sdiod rev 0, supports 3 functions */ ++#define SBSDIO_NUM_FUNCTION 3 ++ ++/* function 1 miscellaneous registers */ ++ ++/* sprom command and status */ ++#define SBSDIO_SPROM_CS 0x10000 ++/* sprom info register */ ++#define SBSDIO_SPROM_INFO 0x10001 ++/* sprom indirect access data byte 0 */ ++#define SBSDIO_SPROM_DATA_LOW 0x10002 ++/* sprom indirect access data byte 1 */ ++#define SBSDIO_SPROM_DATA_HIGH 0x10003 ++/* sprom indirect access addr byte 0 */ ++#define SBSDIO_SPROM_ADDR_LOW 0x10004 ++/* sprom indirect access addr byte 0 */ ++#define SBSDIO_SPROM_ADDR_HIGH 0x10005 ++/* xtal_pu (gpio) output */ ++#define SBSDIO_CHIP_CTRL_DATA 0x10006 ++/* xtal_pu (gpio) enable */ ++#define SBSDIO_CHIP_CTRL_EN 0x10007 ++/* rev < 7, watermark for sdio device */ ++#define SBSDIO_WATERMARK 0x10008 ++/* control busy signal generation */ ++#define SBSDIO_DEVICE_CTL 0x10009 ++ ++/* SB Address Window Low (b15) */ ++#define SBSDIO_FUNC1_SBADDRLOW 0x1000A ++/* SB Address Window Mid (b23:b16) */ ++#define SBSDIO_FUNC1_SBADDRMID 0x1000B ++/* SB Address Window High (b31:b24) */ ++#define SBSDIO_FUNC1_SBADDRHIGH 0x1000C ++/* Frame Control (frame term/abort) */ ++#define SBSDIO_FUNC1_FRAMECTRL 0x1000D ++/* ChipClockCSR (ALP/HT ctl/status) */ ++#define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E ++/* SdioPullUp (on cmd, d0-d2) */ ++#define SBSDIO_FUNC1_SDIOPULLUP 0x1000F ++/* Write Frame Byte Count Low */ ++#define SBSDIO_FUNC1_WFRAMEBCLO 0x10019 ++/* Write Frame Byte Count High */ ++#define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A ++/* Read Frame Byte Count Low */ ++#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B ++/* Read Frame Byte Count High */ ++#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C ++ ++#define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */ ++#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001C /* f1 misc register end */ ++ ++/* function 1 OCP space */ ++ ++/* sb offset addr is <= 15 bits, 32k */ ++#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF ++#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000 ++/* with b15, maps to 32-bit SB access */ ++#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 ++ ++/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */ ++ ++#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */ ++#define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */ ++#define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */ ++/* Address bits from SBADDR regs */ ++#define SBSDIO_SBWINDOW_MASK 0xffff8000 ++ ++#define SDIOH_READ 0 /* Read request */ ++#define SDIOH_WRITE 1 /* Write request */ ++ ++#define SDIOH_DATA_FIX 0 /* Fixed addressing */ ++#define SDIOH_DATA_INC 1 /* Incremental addressing */ ++ ++/* internal return code */ ++#define SUCCESS 0 ++#define ERROR 1 ++ ++struct brcmf_sdreg { ++ int func; ++ int offset; ++ int value; ++}; ++ ++struct brcmf_sdio_dev { ++ struct sdio_func *func[SDIO_MAX_FUNCS]; ++ u8 num_funcs; /* Supported funcs on client */ ++ u32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; ++ u32 sbwad; /* Save backplane window address */ ++ bool regfail; /* status of last reg_r/w call */ ++ void *bus; ++ atomic_t suspend; /* suspend flag */ ++ wait_queue_head_t request_byte_wait; ++ wait_queue_head_t request_word_wait; ++ wait_queue_head_t request_packet_wait; ++ wait_queue_head_t request_buffer_wait; ++ ++}; ++ ++/* Register/deregister device interrupt handler. */ ++extern int ++brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev); ++ ++extern int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev); ++ ++/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface). ++ * fn: function number ++ * addr: unmodified SDIO-space address ++ * data: data byte to write ++ * err: pointer to error code (or NULL) ++ */ ++extern u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint func, ++ u32 addr, int *err); ++extern void brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint func, ++ u32 addr, u8 data, int *err); ++ ++/* Synchronous access to device (client) core registers via CMD53 to F1. ++ * addr: backplane address (i.e. >= regsva from attach) ++ * size: register width in bytes (2 or 4) ++ * data: data for register write ++ */ ++extern u32 ++brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size); ++ ++extern u32 ++brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size, ++ u32 data); ++ ++/* Indicate if last reg read/write failed */ ++extern bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev); ++ ++/* Buffer transfer to/from device (client) core via cmd53. ++ * fn: function number ++ * addr: backplane address (i.e. >= regsva from attach) ++ * flags: backplane width, address increment, sync/async ++ * buf: pointer to memory data buffer ++ * nbytes: number of bytes to transfer to/from buf ++ * pkt: pointer to packet associated with buf (if any) ++ * complete: callback function for command completion (async only) ++ * handle: handle for completion callback (first arg in callback) ++ * Returns 0 or error code. ++ * NOTE: Async operation is not currently supported. ++ */ ++extern int ++brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ++ uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt); ++extern int ++brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ++ uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt); ++ ++/* Flags bits */ ++ ++/* Four-byte target (backplane) width (vs. two-byte) */ ++#define SDIO_REQ_4BYTE 0x1 ++/* Fixed address (FIFO) (vs. incrementing address) */ ++#define SDIO_REQ_FIXED 0x2 ++/* Async request (vs. sync request) */ ++#define SDIO_REQ_ASYNC 0x4 ++ ++/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only). ++ * rw: read or write (0/1) ++ * addr: direct SDIO address ++ * buf: pointer to memory data buffer ++ * nbytes: number of bytes to transfer to/from buf ++ * Returns 0 or error code. ++ */ ++extern int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, ++ u32 addr, u8 *buf, uint nbytes); ++ ++/* Issue an abort to the specified function */ ++extern int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn); ++ ++/* platform specific/high level functions */ ++extern int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev); ++extern int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev); ++ ++extern int brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, ++ u32 address); ++ ++/* attach, return handler on success, NULL if failed. ++ * The handler shall be provided by all subsequent calls. No local cache ++ * cfghdl points to the starting address of pci device mapped memory ++ */ ++extern int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev); ++extern void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev); ++ ++/* read or write one byte using cmd52 */ ++extern int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, ++ uint fnc, uint addr, u8 *byte); ++ ++/* read or write 2/4 bytes using cmd53 */ ++extern int ++brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, ++ uint rw, uint fnc, uint addr, ++ u32 *word, uint nbyte); ++ ++/* read or write any buffer using cmd53 */ ++extern int ++brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, ++ uint fix_inc, uint rw, uint fnc_num, ++ u32 addr, uint regwidth, ++ u32 buflen, u8 *buffer, struct sk_buff *pkt); ++ ++/* Watchdog timer interface for pm ops */ ++extern void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, ++ bool enable); ++ ++extern void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype, ++ u32 regsva, struct brcmf_sdio_dev *sdiodev); ++extern void brcmf_sdbrcm_disconnect(void *ptr); ++extern void brcmf_sdbrcm_isr(void *arg); ++#endif /* _BRCM_SDH_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c.orig 2011-11-09 13:46:58.237800734 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c 2011-11-09 13:47:16.989566304 -0500 +@@ -0,0 +1,3868 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include "dhd.h" ++#include "wl_cfg80211.h" ++ ++#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \ ++ (sizeof(struct brcmf_assoc_params_le) - sizeof(u16)) ++ ++static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255}; ++ ++static u32 brcmf_dbg_level = WL_DBG_ERR; ++ ++static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data) ++{ ++ dev->driver_data = data; ++} ++ ++static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev) ++{ ++ void *data = NULL; ++ ++ if (dev) ++ data = dev->driver_data; ++ return data; ++} ++ ++static ++struct brcmf_cfg80211_priv *brcmf_priv_get(struct brcmf_cfg80211_dev *cfg_dev) ++{ ++ struct brcmf_cfg80211_iface *ci = brcmf_get_drvdata(cfg_dev); ++ return ci->cfg_priv; ++} ++ ++static bool check_sys_up(struct wiphy *wiphy) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) { ++ WL_INFO("device is not ready : status (%d)\n", ++ (int)cfg_priv->status); ++ return false; ++ } ++ return true; ++} ++ ++#define CHAN2G(_channel, _freq, _flags) { \ ++ .band = IEEE80211_BAND_2GHZ, \ ++ .center_freq = (_freq), \ ++ .hw_value = (_channel), \ ++ .flags = (_flags), \ ++ .max_antenna_gain = 0, \ ++ .max_power = 30, \ ++} ++ ++#define CHAN5G(_channel, _flags) { \ ++ .band = IEEE80211_BAND_5GHZ, \ ++ .center_freq = 5000 + (5 * (_channel)), \ ++ .hw_value = (_channel), \ ++ .flags = (_flags), \ ++ .max_antenna_gain = 0, \ ++ .max_power = 30, \ ++} ++ ++#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2) ++#define RATETAB_ENT(_rateid, _flags) \ ++ { \ ++ .bitrate = RATE_TO_BASE100KBPS(_rateid), \ ++ .hw_value = (_rateid), \ ++ .flags = (_flags), \ ++ } ++ ++static struct ieee80211_rate __wl_rates[] = { ++ RATETAB_ENT(BRCM_RATE_1M, 0), ++ RATETAB_ENT(BRCM_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATETAB_ENT(BRCM_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATETAB_ENT(BRCM_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATETAB_ENT(BRCM_RATE_6M, 0), ++ RATETAB_ENT(BRCM_RATE_9M, 0), ++ RATETAB_ENT(BRCM_RATE_12M, 0), ++ RATETAB_ENT(BRCM_RATE_18M, 0), ++ RATETAB_ENT(BRCM_RATE_24M, 0), ++ RATETAB_ENT(BRCM_RATE_36M, 0), ++ RATETAB_ENT(BRCM_RATE_48M, 0), ++ RATETAB_ENT(BRCM_RATE_54M, 0), ++}; ++ ++#define wl_a_rates (__wl_rates + 4) ++#define wl_a_rates_size 8 ++#define wl_g_rates (__wl_rates + 0) ++#define wl_g_rates_size 12 ++ ++static struct ieee80211_channel __wl_2ghz_channels[] = { ++ CHAN2G(1, 2412, 0), ++ CHAN2G(2, 2417, 0), ++ CHAN2G(3, 2422, 0), ++ CHAN2G(4, 2427, 0), ++ CHAN2G(5, 2432, 0), ++ CHAN2G(6, 2437, 0), ++ CHAN2G(7, 2442, 0), ++ CHAN2G(8, 2447, 0), ++ CHAN2G(9, 2452, 0), ++ CHAN2G(10, 2457, 0), ++ CHAN2G(11, 2462, 0), ++ CHAN2G(12, 2467, 0), ++ CHAN2G(13, 2472, 0), ++ CHAN2G(14, 2484, 0), ++}; ++ ++static struct ieee80211_channel __wl_5ghz_a_channels[] = { ++ CHAN5G(34, 0), CHAN5G(36, 0), ++ CHAN5G(38, 0), CHAN5G(40, 0), ++ CHAN5G(42, 0), CHAN5G(44, 0), ++ CHAN5G(46, 0), CHAN5G(48, 0), ++ CHAN5G(52, 0), CHAN5G(56, 0), ++ CHAN5G(60, 0), CHAN5G(64, 0), ++ CHAN5G(100, 0), CHAN5G(104, 0), ++ CHAN5G(108, 0), CHAN5G(112, 0), ++ CHAN5G(116, 0), CHAN5G(120, 0), ++ CHAN5G(124, 0), CHAN5G(128, 0), ++ CHAN5G(132, 0), CHAN5G(136, 0), ++ CHAN5G(140, 0), CHAN5G(149, 0), ++ CHAN5G(153, 0), CHAN5G(157, 0), ++ CHAN5G(161, 0), CHAN5G(165, 0), ++ CHAN5G(184, 0), CHAN5G(188, 0), ++ CHAN5G(192, 0), CHAN5G(196, 0), ++ CHAN5G(200, 0), CHAN5G(204, 0), ++ CHAN5G(208, 0), CHAN5G(212, 0), ++ CHAN5G(216, 0), ++}; ++ ++static struct ieee80211_channel __wl_5ghz_n_channels[] = { ++ CHAN5G(32, 0), CHAN5G(34, 0), ++ CHAN5G(36, 0), CHAN5G(38, 0), ++ CHAN5G(40, 0), CHAN5G(42, 0), ++ CHAN5G(44, 0), CHAN5G(46, 0), ++ CHAN5G(48, 0), CHAN5G(50, 0), ++ CHAN5G(52, 0), CHAN5G(54, 0), ++ CHAN5G(56, 0), CHAN5G(58, 0), ++ CHAN5G(60, 0), CHAN5G(62, 0), ++ CHAN5G(64, 0), CHAN5G(66, 0), ++ CHAN5G(68, 0), CHAN5G(70, 0), ++ CHAN5G(72, 0), CHAN5G(74, 0), ++ CHAN5G(76, 0), CHAN5G(78, 0), ++ CHAN5G(80, 0), CHAN5G(82, 0), ++ CHAN5G(84, 0), CHAN5G(86, 0), ++ CHAN5G(88, 0), CHAN5G(90, 0), ++ CHAN5G(92, 0), CHAN5G(94, 0), ++ CHAN5G(96, 0), CHAN5G(98, 0), ++ CHAN5G(100, 0), CHAN5G(102, 0), ++ CHAN5G(104, 0), CHAN5G(106, 0), ++ CHAN5G(108, 0), CHAN5G(110, 0), ++ CHAN5G(112, 0), CHAN5G(114, 0), ++ CHAN5G(116, 0), CHAN5G(118, 0), ++ CHAN5G(120, 0), CHAN5G(122, 0), ++ CHAN5G(124, 0), CHAN5G(126, 0), ++ CHAN5G(128, 0), CHAN5G(130, 0), ++ CHAN5G(132, 0), CHAN5G(134, 0), ++ CHAN5G(136, 0), CHAN5G(138, 0), ++ CHAN5G(140, 0), CHAN5G(142, 0), ++ CHAN5G(144, 0), CHAN5G(145, 0), ++ CHAN5G(146, 0), CHAN5G(147, 0), ++ CHAN5G(148, 0), CHAN5G(149, 0), ++ CHAN5G(150, 0), CHAN5G(151, 0), ++ CHAN5G(152, 0), CHAN5G(153, 0), ++ CHAN5G(154, 0), CHAN5G(155, 0), ++ CHAN5G(156, 0), CHAN5G(157, 0), ++ CHAN5G(158, 0), CHAN5G(159, 0), ++ CHAN5G(160, 0), CHAN5G(161, 0), ++ CHAN5G(162, 0), CHAN5G(163, 0), ++ CHAN5G(164, 0), CHAN5G(165, 0), ++ CHAN5G(166, 0), CHAN5G(168, 0), ++ CHAN5G(170, 0), CHAN5G(172, 0), ++ CHAN5G(174, 0), CHAN5G(176, 0), ++ CHAN5G(178, 0), CHAN5G(180, 0), ++ CHAN5G(182, 0), CHAN5G(184, 0), ++ CHAN5G(186, 0), CHAN5G(188, 0), ++ CHAN5G(190, 0), CHAN5G(192, 0), ++ CHAN5G(194, 0), CHAN5G(196, 0), ++ CHAN5G(198, 0), CHAN5G(200, 0), ++ CHAN5G(202, 0), CHAN5G(204, 0), ++ CHAN5G(206, 0), CHAN5G(208, 0), ++ CHAN5G(210, 0), CHAN5G(212, 0), ++ CHAN5G(214, 0), CHAN5G(216, 0), ++ CHAN5G(218, 0), CHAN5G(220, 0), ++ CHAN5G(222, 0), CHAN5G(224, 0), ++ CHAN5G(226, 0), CHAN5G(228, 0), ++}; ++ ++static struct ieee80211_supported_band __wl_band_2ghz = { ++ .band = IEEE80211_BAND_2GHZ, ++ .channels = __wl_2ghz_channels, ++ .n_channels = ARRAY_SIZE(__wl_2ghz_channels), ++ .bitrates = wl_g_rates, ++ .n_bitrates = wl_g_rates_size, ++}; ++ ++static struct ieee80211_supported_band __wl_band_5ghz_a = { ++ .band = IEEE80211_BAND_5GHZ, ++ .channels = __wl_5ghz_a_channels, ++ .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels), ++ .bitrates = wl_a_rates, ++ .n_bitrates = wl_a_rates_size, ++}; ++ ++static struct ieee80211_supported_band __wl_band_5ghz_n = { ++ .band = IEEE80211_BAND_5GHZ, ++ .channels = __wl_5ghz_n_channels, ++ .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels), ++ .bitrates = wl_a_rates, ++ .n_bitrates = wl_a_rates_size, ++}; ++ ++static const u32 __wl_cipher_suites[] = { ++ WLAN_CIPHER_SUITE_WEP40, ++ WLAN_CIPHER_SUITE_WEP104, ++ WLAN_CIPHER_SUITE_TKIP, ++ WLAN_CIPHER_SUITE_CCMP, ++ WLAN_CIPHER_SUITE_AES_CMAC, ++}; ++ ++/* tag_ID/length/value_buffer tuple */ ++struct brcmf_tlv { ++ u8 id; ++ u8 len; ++ u8 data[1]; ++}; ++ ++/* Quarter dBm units to mW ++ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 ++ * Table is offset so the last entry is largest mW value that fits in ++ * a u16. ++ */ ++ ++#define QDBM_OFFSET 153 /* Offset for first entry */ ++#define QDBM_TABLE_LEN 40 /* Table size */ ++ ++/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET. ++ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2 ++ */ ++#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */ ++ ++/* Largest mW value that will round down to the last table entry, ++ * QDBM_OFFSET + QDBM_TABLE_LEN-1. ++ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + ++ * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2. ++ */ ++#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */ ++ ++static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = { ++/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */ ++/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, ++/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, ++/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, ++/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, ++/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096 ++}; ++ ++static u16 brcmf_qdbm_to_mw(u8 qdbm) ++{ ++ uint factor = 1; ++ int idx = qdbm - QDBM_OFFSET; ++ ++ if (idx >= QDBM_TABLE_LEN) ++ /* clamp to max u16 mW value */ ++ return 0xFFFF; ++ ++ /* scale the qdBm index up to the range of the table 0-40 ++ * where an offset of 40 qdBm equals a factor of 10 mW. ++ */ ++ while (idx < 0) { ++ idx += 40; ++ factor *= 10; ++ } ++ ++ /* return the mW value scaled down to the correct factor of 10, ++ * adding in factor/2 to get proper rounding. ++ */ ++ return (nqdBm_to_mW_map[idx] + factor / 2) / factor; ++} ++ ++static u8 brcmf_mw_to_qdbm(u16 mw) ++{ ++ u8 qdbm; ++ int offset; ++ uint mw_uint = mw; ++ uint boundary; ++ ++ /* handle boundary case */ ++ if (mw_uint <= 1) ++ return 0; ++ ++ offset = QDBM_OFFSET; ++ ++ /* move mw into the range of the table */ ++ while (mw_uint < QDBM_TABLE_LOW_BOUND) { ++ mw_uint *= 10; ++ offset -= 40; ++ } ++ ++ for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) { ++ boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] - ++ nqdBm_to_mW_map[qdbm]) / 2; ++ if (mw_uint < boundary) ++ break; ++ } ++ ++ qdbm += (u8) offset; ++ ++ return qdbm; ++} ++ ++/* function for reading/writing a single u32 from/to the dongle */ ++static int ++brcmf_exec_dcmd_u32(struct net_device *ndev, u32 cmd, u32 *par) ++{ ++ int err; ++ __le32 par_le = cpu_to_le32(*par); ++ ++ err = brcmf_exec_dcmd(ndev, cmd, &par_le, sizeof(__le32)); ++ *par = le32_to_cpu(par_le); ++ ++ return err; ++} ++ ++static void convert_key_from_CPU(struct brcmf_wsec_key *key, ++ struct brcmf_wsec_key_le *key_le) ++{ ++ key_le->index = cpu_to_le32(key->index); ++ key_le->len = cpu_to_le32(key->len); ++ key_le->algo = cpu_to_le32(key->algo); ++ key_le->flags = cpu_to_le32(key->flags); ++ key_le->rxiv.hi = cpu_to_le32(key->rxiv.hi); ++ key_le->rxiv.lo = cpu_to_le16(key->rxiv.lo); ++ key_le->iv_initialized = cpu_to_le32(key->iv_initialized); ++ memcpy(key_le->data, key->data, sizeof(key->data)); ++ memcpy(key_le->ea, key->ea, sizeof(key->ea)); ++} ++ ++static int send_key_to_dongle(struct net_device *ndev, ++ struct brcmf_wsec_key *key) ++{ ++ int err; ++ struct brcmf_wsec_key_le key_le; ++ ++ convert_key_from_CPU(key, &key_le); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le, sizeof(key_le)); ++ if (err) ++ WL_ERR("WLC_SET_KEY error (%d)\n", err); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, ++ enum nl80211_iftype type, u32 *flags, ++ struct vif_params *params) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct wireless_dev *wdev; ++ s32 infra = 0; ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ switch (type) { ++ case NL80211_IFTYPE_MONITOR: ++ case NL80211_IFTYPE_WDS: ++ WL_ERR("type (%d) : currently we do not support this type\n", ++ type); ++ return -EOPNOTSUPP; ++ case NL80211_IFTYPE_ADHOC: ++ cfg_priv->conf->mode = WL_MODE_IBSS; ++ infra = 0; ++ break; ++ case NL80211_IFTYPE_STATION: ++ cfg_priv->conf->mode = WL_MODE_BSS; ++ infra = 1; ++ break; ++ default: ++ err = -EINVAL; ++ goto done; ++ } ++ ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra); ++ if (err) { ++ WL_ERR("WLC_SET_INFRA error (%d)\n", err); ++ err = -EAGAIN; ++ } else { ++ wdev = ndev->ieee80211_ptr; ++ wdev->iftype = type; ++ } ++ ++ WL_INFO("IF Type = %s\n", ++ (cfg_priv->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra"); ++ ++done: ++ WL_TRACE("Exit\n"); ++ ++ return err; ++} ++ ++static s32 brcmf_dev_intvar_set(struct net_device *ndev, s8 *name, s32 val) ++{ ++ s8 buf[BRCMF_DCMD_SMLEN]; ++ u32 len; ++ s32 err = 0; ++ __le32 val_le; ++ ++ val_le = cpu_to_le32(val); ++ len = brcmf_c_mkiovar(name, (char *)(&val_le), sizeof(val_le), buf, ++ sizeof(buf)); ++ BUG_ON(!len); ++ ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len); ++ if (err) ++ WL_ERR("error (%d)\n", err); ++ ++ return err; ++} ++ ++static s32 ++brcmf_dev_intvar_get(struct net_device *ndev, s8 *name, s32 *retval) ++{ ++ union { ++ s8 buf[BRCMF_DCMD_SMLEN]; ++ __le32 val; ++ } var; ++ u32 len; ++ u32 data_null; ++ s32 err = 0; ++ ++ len = ++ brcmf_c_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), ++ sizeof(var.buf)); ++ BUG_ON(!len); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, &var, len); ++ if (err) ++ WL_ERR("error (%d)\n", err); ++ ++ *retval = le32_to_cpu(var.val); ++ ++ return err; ++} ++ ++static void brcmf_set_mpc(struct net_device *ndev, int mpc) ++{ ++ s32 err = 0; ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ ++ if (test_bit(WL_STATUS_READY, &cfg_priv->status)) { ++ err = brcmf_dev_intvar_set(ndev, "mpc", mpc); ++ if (err) { ++ WL_ERR("fail to set mpc\n"); ++ return; ++ } ++ WL_INFO("MPC : %d\n", mpc); ++ } ++} ++ ++static void wl_iscan_prep(struct brcmf_scan_params_le *params_le, ++ struct brcmf_ssid *ssid) ++{ ++ memcpy(params_le->bssid, ether_bcast, ETH_ALEN); ++ params_le->bss_type = DOT11_BSSTYPE_ANY; ++ params_le->scan_type = 0; ++ params_le->channel_num = 0; ++ params_le->nprobes = cpu_to_le32(-1); ++ params_le->active_time = cpu_to_le32(-1); ++ params_le->passive_time = cpu_to_le32(-1); ++ params_le->home_time = cpu_to_le32(-1); ++ if (ssid && ssid->SSID_len) ++ memcpy(¶ms_le->ssid_le, ssid, sizeof(struct brcmf_ssid)); ++} ++ ++static s32 ++brcmf_dev_iovar_setbuf(struct net_device *ndev, s8 * iovar, void *param, ++ s32 paramlen, void *bufptr, s32 buflen) ++{ ++ s32 iolen; ++ ++ iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen); ++ BUG_ON(!iolen); ++ ++ return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, bufptr, iolen); ++} ++ ++static s32 ++brcmf_dev_iovar_getbuf(struct net_device *ndev, s8 * iovar, void *param, ++ s32 paramlen, void *bufptr, s32 buflen) ++{ ++ s32 iolen; ++ ++ iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen); ++ BUG_ON(!iolen); ++ ++ return brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, bufptr, buflen); ++} ++ ++static s32 ++brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan, ++ struct brcmf_ssid *ssid, u16 action) ++{ ++ s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE + ++ offsetof(struct brcmf_iscan_params_le, params_le); ++ struct brcmf_iscan_params_le *params; ++ s32 err = 0; ++ ++ if (ssid && ssid->SSID_len) ++ params_size += sizeof(struct brcmf_ssid); ++ params = kzalloc(params_size, GFP_KERNEL); ++ if (!params) ++ return -ENOMEM; ++ BUG_ON(params_size >= BRCMF_DCMD_SMLEN); ++ ++ wl_iscan_prep(¶ms->params_le, ssid); ++ ++ params->version = cpu_to_le32(BRCMF_ISCAN_REQ_VERSION); ++ params->action = cpu_to_le16(action); ++ params->scan_duration = cpu_to_le16(0); ++ ++ err = brcmf_dev_iovar_setbuf(iscan->ndev, "iscan", params, params_size, ++ iscan->dcmd_buf, BRCMF_DCMD_SMLEN); ++ if (err) { ++ if (err == -EBUSY) ++ WL_INFO("system busy : iscan canceled\n"); ++ else ++ WL_ERR("error (%d)\n", err); ++ } ++ ++ kfree(params); ++ return err; ++} ++ ++static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); ++ struct net_device *ndev = cfg_to_ndev(cfg_priv); ++ struct brcmf_ssid ssid; ++ __le32 passive_scan; ++ s32 err = 0; ++ ++ /* Broadcast scan by default */ ++ memset(&ssid, 0, sizeof(ssid)); ++ ++ iscan->state = WL_ISCAN_STATE_SCANING; ++ ++ passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1); ++ err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN, ++ &passive_scan, sizeof(passive_scan)); ++ if (err) { ++ WL_ERR("error (%d)\n", err); ++ return err; ++ } ++ brcmf_set_mpc(ndev, 0); ++ cfg_priv->iscan_kickstart = true; ++ err = brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START); ++ if (err) { ++ brcmf_set_mpc(ndev, 1); ++ cfg_priv->iscan_kickstart = false; ++ return err; ++ } ++ mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000); ++ iscan->timer_on = 1; ++ return err; ++} ++ ++static s32 ++__brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, ++ struct cfg80211_scan_request *request, ++ struct cfg80211_ssid *this_ssid) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ struct cfg80211_ssid *ssids; ++ struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int; ++ __le32 passive_scan; ++ bool iscan_req; ++ bool spec_scan; ++ s32 err = 0; ++ u32 SSID_len; ++ ++ if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { ++ WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status); ++ return -EAGAIN; ++ } ++ if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status)) { ++ WL_ERR("Scanning being aborted : status (%lu)\n", ++ cfg_priv->status); ++ return -EAGAIN; ++ } ++ if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) { ++ WL_ERR("Connecting : status (%lu)\n", ++ cfg_priv->status); ++ return -EAGAIN; ++ } ++ ++ iscan_req = false; ++ spec_scan = false; ++ if (request) { ++ /* scan bss */ ++ ssids = request->ssids; ++ if (cfg_priv->iscan_on && (!ssids || !ssids->ssid_len)) ++ iscan_req = true; ++ } else { ++ /* scan in ibss */ ++ /* we don't do iscan in ibss */ ++ ssids = this_ssid; ++ } ++ ++ cfg_priv->scan_request = request; ++ set_bit(WL_STATUS_SCANNING, &cfg_priv->status); ++ if (iscan_req) { ++ err = brcmf_do_iscan(cfg_priv); ++ if (!err) ++ return err; ++ else ++ goto scan_out; ++ } else { ++ WL_SCAN("ssid \"%s\", ssid_len (%d)\n", ++ ssids->ssid, ssids->ssid_len); ++ memset(&sr->ssid_le, 0, sizeof(sr->ssid_le)); ++ SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len); ++ sr->ssid_le.SSID_len = cpu_to_le32(0); ++ if (SSID_len) { ++ memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len); ++ sr->ssid_le.SSID_len = cpu_to_le32(SSID_len); ++ spec_scan = true; ++ } else { ++ WL_SCAN("Broadcast scan\n"); ++ } ++ ++ passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN, ++ &passive_scan, sizeof(passive_scan)); ++ if (err) { ++ WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err); ++ goto scan_out; ++ } ++ brcmf_set_mpc(ndev, 0); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le, ++ sizeof(sr->ssid_le)); ++ if (err) { ++ if (err == -EBUSY) ++ WL_INFO("system busy : scan for \"%s\" " ++ "canceled\n", sr->ssid_le.SSID); ++ else ++ WL_ERR("WLC_SCAN error (%d)\n", err); ++ ++ brcmf_set_mpc(ndev, 1); ++ goto scan_out; ++ } ++ } ++ ++ return 0; ++ ++scan_out: ++ clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); ++ cfg_priv->scan_request = NULL; ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, ++ struct cfg80211_scan_request *request) ++{ ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ err = __brcmf_cfg80211_scan(wiphy, ndev, request, NULL); ++ if (err) ++ WL_ERR("scan error (%d)\n", err); ++ ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold) ++{ ++ s32 err = 0; ++ ++ err = brcmf_dev_intvar_set(ndev, "rtsthresh", rts_threshold); ++ if (err) ++ WL_ERR("Error (%d)\n", err); ++ ++ return err; ++} ++ ++static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold) ++{ ++ s32 err = 0; ++ ++ err = brcmf_dev_intvar_set(ndev, "fragthresh", frag_threshold); ++ if (err) ++ WL_ERR("Error (%d)\n", err); ++ ++ return err; ++} ++ ++static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l) ++{ ++ s32 err = 0; ++ u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL); ++ ++ err = brcmf_exec_dcmd_u32(ndev, cmd, &retry); ++ if (err) { ++ WL_ERR("cmd (%d) , error (%d)\n", cmd, err); ++ return err; ++ } ++ return err; ++} ++ ++static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct net_device *ndev = cfg_to_ndev(cfg_priv); ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ if (changed & WIPHY_PARAM_RTS_THRESHOLD && ++ (cfg_priv->conf->rts_threshold != wiphy->rts_threshold)) { ++ cfg_priv->conf->rts_threshold = wiphy->rts_threshold; ++ err = brcmf_set_rts(ndev, cfg_priv->conf->rts_threshold); ++ if (!err) ++ goto done; ++ } ++ if (changed & WIPHY_PARAM_FRAG_THRESHOLD && ++ (cfg_priv->conf->frag_threshold != wiphy->frag_threshold)) { ++ cfg_priv->conf->frag_threshold = wiphy->frag_threshold; ++ err = brcmf_set_frag(ndev, cfg_priv->conf->frag_threshold); ++ if (!err) ++ goto done; ++ } ++ if (changed & WIPHY_PARAM_RETRY_LONG ++ && (cfg_priv->conf->retry_long != wiphy->retry_long)) { ++ cfg_priv->conf->retry_long = wiphy->retry_long; ++ err = brcmf_set_retry(ndev, cfg_priv->conf->retry_long, true); ++ if (!err) ++ goto done; ++ } ++ if (changed & WIPHY_PARAM_RETRY_SHORT ++ && (cfg_priv->conf->retry_short != wiphy->retry_short)) { ++ cfg_priv->conf->retry_short = wiphy->retry_short; ++ err = brcmf_set_retry(ndev, cfg_priv->conf->retry_short, false); ++ if (!err) ++ goto done; ++ } ++ ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item) ++{ ++ switch (item) { ++ case WL_PROF_SEC: ++ return &cfg_priv->profile->sec; ++ case WL_PROF_BSSID: ++ return &cfg_priv->profile->bssid; ++ case WL_PROF_SSID: ++ return &cfg_priv->profile->ssid; ++ } ++ WL_ERR("invalid item (%d)\n", item); ++ return NULL; ++} ++ ++static s32 ++brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv, ++ const struct brcmf_event_msg *e, void *data, s32 item) ++{ ++ s32 err = 0; ++ struct brcmf_ssid *ssid; ++ ++ switch (item) { ++ case WL_PROF_SSID: ++ ssid = (struct brcmf_ssid *) data; ++ memset(cfg_priv->profile->ssid.SSID, 0, ++ sizeof(cfg_priv->profile->ssid.SSID)); ++ memcpy(cfg_priv->profile->ssid.SSID, ++ ssid->SSID, ssid->SSID_len); ++ cfg_priv->profile->ssid.SSID_len = ssid->SSID_len; ++ break; ++ case WL_PROF_BSSID: ++ if (data) ++ memcpy(cfg_priv->profile->bssid, data, ETH_ALEN); ++ else ++ memset(cfg_priv->profile->bssid, 0, ETH_ALEN); ++ break; ++ case WL_PROF_SEC: ++ memcpy(&cfg_priv->profile->sec, data, ++ sizeof(cfg_priv->profile->sec)); ++ break; ++ case WL_PROF_BEACONINT: ++ cfg_priv->profile->beacon_interval = *(u16 *)data; ++ break; ++ case WL_PROF_DTIMPERIOD: ++ cfg_priv->profile->dtim_period = *(u8 *)data; ++ break; ++ default: ++ WL_ERR("unsupported item (%d)\n", item); ++ err = -EOPNOTSUPP; ++ break; ++ } ++ ++ return err; ++} ++ ++static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof) ++{ ++ memset(prof, 0, sizeof(*prof)); ++} ++ ++static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params, ++ size_t *join_params_size) ++{ ++ u16 chanspec = 0; ++ ++ if (ch != 0) { ++ if (ch <= CH_MAX_2G_CHANNEL) ++ chanspec |= WL_CHANSPEC_BAND_2G; ++ else ++ chanspec |= WL_CHANSPEC_BAND_5G; ++ ++ chanspec |= WL_CHANSPEC_BW_20; ++ chanspec |= WL_CHANSPEC_CTL_SB_NONE; ++ ++ *join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE + ++ sizeof(u16); ++ ++ chanspec |= (ch & WL_CHANSPEC_CHAN_MASK); ++ join_params->params_le.chanspec_list[0] = cpu_to_le16(chanspec); ++ join_params->params_le.chanspec_num = cpu_to_le32(1); ++ ++ WL_CONN("join_params->params.chanspec_list[0]= %#X," ++ "channel %d, chanspec %#X\n", ++ chanspec, ch, chanspec); ++ } ++} ++ ++static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct net_device *ndev = NULL; ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ ++ if (cfg_priv->link_up) { ++ ndev = cfg_to_ndev(cfg_priv); ++ WL_INFO("Call WLC_DISASSOC to stop excess roaming\n "); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, NULL, 0); ++ if (err) ++ WL_ERR("WLC_DISASSOC failed (%d)\n", err); ++ cfg_priv->link_up = false; ++ } ++ WL_TRACE("Exit\n"); ++} ++ ++static s32 ++brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, ++ struct cfg80211_ibss_params *params) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct brcmf_join_params join_params; ++ size_t join_params_size = 0; ++ s32 err = 0; ++ s32 wsec = 0; ++ s32 bcnprd; ++ struct brcmf_ssid ssid; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ if (params->ssid) ++ WL_CONN("SSID: %s\n", params->ssid); ++ else { ++ WL_CONN("SSID: NULL, Not supported\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ set_bit(WL_STATUS_CONNECTING, &cfg_priv->status); ++ ++ if (params->bssid) ++ WL_CONN("BSSID: %02X %02X %02X %02X %02X %02X\n", ++ params->bssid[0], params->bssid[1], params->bssid[2], ++ params->bssid[3], params->bssid[4], params->bssid[5]); ++ else ++ WL_CONN("No BSSID specified\n"); ++ ++ if (params->channel) ++ WL_CONN("channel: %d\n", params->channel->center_freq); ++ else ++ WL_CONN("no channel specified\n"); ++ ++ if (params->channel_fixed) ++ WL_CONN("fixed channel required\n"); ++ else ++ WL_CONN("no fixed channel required\n"); ++ ++ if (params->ie && params->ie_len) ++ WL_CONN("ie len: %d\n", params->ie_len); ++ else ++ WL_CONN("no ie specified\n"); ++ ++ if (params->beacon_interval) ++ WL_CONN("beacon interval: %d\n", params->beacon_interval); ++ else ++ WL_CONN("no beacon interval specified\n"); ++ ++ if (params->basic_rates) ++ WL_CONN("basic rates: %08X\n", params->basic_rates); ++ else ++ WL_CONN("no basic rates specified\n"); ++ ++ if (params->privacy) ++ WL_CONN("privacy required\n"); ++ else ++ WL_CONN("no privacy required\n"); ++ ++ /* Configure Privacy for starter */ ++ if (params->privacy) ++ wsec |= WEP_ENABLED; ++ ++ err = brcmf_dev_intvar_set(ndev, "wsec", wsec); ++ if (err) { ++ WL_ERR("wsec failed (%d)\n", err); ++ goto done; ++ } ++ ++ /* Configure Beacon Interval for starter */ ++ if (params->beacon_interval) ++ bcnprd = params->beacon_interval; ++ else ++ bcnprd = 100; ++ ++ err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_BCNPRD, &bcnprd); ++ if (err) { ++ WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err); ++ goto done; ++ } ++ ++ /* Configure required join parameter */ ++ memset(&join_params, 0, sizeof(struct brcmf_join_params)); ++ ++ /* SSID */ ++ ssid.SSID_len = min_t(u32, params->ssid_len, 32); ++ memcpy(ssid.SSID, params->ssid, ssid.SSID_len); ++ memcpy(join_params.ssid_le.SSID, params->ssid, ssid.SSID_len); ++ join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len); ++ join_params_size = sizeof(join_params.ssid_le); ++ brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID); ++ ++ /* BSSID */ ++ if (params->bssid) { ++ memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN); ++ join_params_size = sizeof(join_params.ssid_le) + ++ BRCMF_ASSOC_PARAMS_FIXED_SIZE; ++ } else { ++ memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN); ++ } ++ ++ brcmf_update_prof(cfg_priv, NULL, ++ &join_params.params_le.bssid, WL_PROF_BSSID); ++ ++ /* Channel */ ++ if (params->channel) { ++ u32 target_channel; ++ ++ cfg_priv->channel = ++ ieee80211_frequency_to_channel( ++ params->channel->center_freq); ++ if (params->channel_fixed) { ++ /* adding chanspec */ ++ brcmf_ch_to_chanspec(cfg_priv->channel, ++ &join_params, &join_params_size); ++ } ++ ++ /* set channel for starter */ ++ target_channel = cfg_priv->channel; ++ err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_CHANNEL, ++ &target_channel); ++ if (err) { ++ WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err); ++ goto done; ++ } ++ } else ++ cfg_priv->channel = 0; ++ ++ cfg_priv->ibss_starter = false; ++ ++ ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, ++ &join_params, join_params_size); ++ if (err) { ++ WL_ERR("WLC_SET_SSID failed (%d)\n", err); ++ goto done; ++ } ++ ++done: ++ if (err) ++ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ brcmf_link_down(cfg_priv); ++ ++ WL_TRACE("Exit\n"); ++ ++ return err; ++} ++ ++static s32 brcmf_set_wpa_version(struct net_device *ndev, ++ struct cfg80211_connect_params *sme) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ struct brcmf_cfg80211_security *sec; ++ s32 val = 0; ++ s32 err = 0; ++ ++ if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) ++ val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED; ++ else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) ++ val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED; ++ else ++ val = WPA_AUTH_DISABLED; ++ WL_CONN("setting wpa_auth to 0x%0x\n", val); ++ err = brcmf_dev_intvar_set(ndev, "wpa_auth", val); ++ if (err) { ++ WL_ERR("set wpa_auth failed (%d)\n", err); ++ return err; ++ } ++ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); ++ sec->wpa_versions = sme->crypto.wpa_versions; ++ return err; ++} ++ ++static s32 brcmf_set_auth_type(struct net_device *ndev, ++ struct cfg80211_connect_params *sme) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ struct brcmf_cfg80211_security *sec; ++ s32 val = 0; ++ s32 err = 0; ++ ++ switch (sme->auth_type) { ++ case NL80211_AUTHTYPE_OPEN_SYSTEM: ++ val = 0; ++ WL_CONN("open system\n"); ++ break; ++ case NL80211_AUTHTYPE_SHARED_KEY: ++ val = 1; ++ WL_CONN("shared key\n"); ++ break; ++ case NL80211_AUTHTYPE_AUTOMATIC: ++ val = 2; ++ WL_CONN("automatic\n"); ++ break; ++ case NL80211_AUTHTYPE_NETWORK_EAP: ++ WL_CONN("network eap\n"); ++ default: ++ val = 2; ++ WL_ERR("invalid auth type (%d)\n", sme->auth_type); ++ break; ++ } ++ ++ err = brcmf_dev_intvar_set(ndev, "auth", val); ++ if (err) { ++ WL_ERR("set auth failed (%d)\n", err); ++ return err; ++ } ++ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); ++ sec->auth_type = sme->auth_type; ++ return err; ++} ++ ++static s32 ++brcmf_set_set_cipher(struct net_device *ndev, ++ struct cfg80211_connect_params *sme) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ struct brcmf_cfg80211_security *sec; ++ s32 pval = 0; ++ s32 gval = 0; ++ s32 err = 0; ++ ++ if (sme->crypto.n_ciphers_pairwise) { ++ switch (sme->crypto.ciphers_pairwise[0]) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ case WLAN_CIPHER_SUITE_WEP104: ++ pval = WEP_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ pval = TKIP_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ pval = AES_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ pval = AES_ENABLED; ++ break; ++ default: ++ WL_ERR("invalid cipher pairwise (%d)\n", ++ sme->crypto.ciphers_pairwise[0]); ++ return -EINVAL; ++ } ++ } ++ if (sme->crypto.cipher_group) { ++ switch (sme->crypto.cipher_group) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ case WLAN_CIPHER_SUITE_WEP104: ++ gval = WEP_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ gval = TKIP_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ gval = AES_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ gval = AES_ENABLED; ++ break; ++ default: ++ WL_ERR("invalid cipher group (%d)\n", ++ sme->crypto.cipher_group); ++ return -EINVAL; ++ } ++ } ++ ++ WL_CONN("pval (%d) gval (%d)\n", pval, gval); ++ err = brcmf_dev_intvar_set(ndev, "wsec", pval | gval); ++ if (err) { ++ WL_ERR("error (%d)\n", err); ++ return err; ++ } ++ ++ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); ++ sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0]; ++ sec->cipher_group = sme->crypto.cipher_group; ++ ++ return err; ++} ++ ++static s32 ++brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ struct brcmf_cfg80211_security *sec; ++ s32 val = 0; ++ s32 err = 0; ++ ++ if (sme->crypto.n_akm_suites) { ++ err = brcmf_dev_intvar_get(ndev, "wpa_auth", &val); ++ if (err) { ++ WL_ERR("could not get wpa_auth (%d)\n", err); ++ return err; ++ } ++ if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) { ++ switch (sme->crypto.akm_suites[0]) { ++ case WLAN_AKM_SUITE_8021X: ++ val = WPA_AUTH_UNSPECIFIED; ++ break; ++ case WLAN_AKM_SUITE_PSK: ++ val = WPA_AUTH_PSK; ++ break; ++ default: ++ WL_ERR("invalid cipher group (%d)\n", ++ sme->crypto.cipher_group); ++ return -EINVAL; ++ } ++ } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { ++ switch (sme->crypto.akm_suites[0]) { ++ case WLAN_AKM_SUITE_8021X: ++ val = WPA2_AUTH_UNSPECIFIED; ++ break; ++ case WLAN_AKM_SUITE_PSK: ++ val = WPA2_AUTH_PSK; ++ break; ++ default: ++ WL_ERR("invalid cipher group (%d)\n", ++ sme->crypto.cipher_group); ++ return -EINVAL; ++ } ++ } ++ ++ WL_CONN("setting wpa_auth to %d\n", val); ++ err = brcmf_dev_intvar_set(ndev, "wpa_auth", val); ++ if (err) { ++ WL_ERR("could not set wpa_auth (%d)\n", err); ++ return err; ++ } ++ } ++ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); ++ sec->wpa_auth = sme->crypto.akm_suites[0]; ++ ++ return err; ++} ++ ++static s32 ++brcmf_set_wep_sharedkey(struct net_device *ndev, ++ struct cfg80211_connect_params *sme) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ struct brcmf_cfg80211_security *sec; ++ struct brcmf_wsec_key key; ++ s32 val; ++ s32 err = 0; ++ ++ WL_CONN("key len (%d)\n", sme->key_len); ++ ++ if (sme->key_len == 0) ++ return 0; ++ ++ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); ++ WL_CONN("wpa_versions 0x%x cipher_pairwise 0x%x\n", ++ sec->wpa_versions, sec->cipher_pairwise); ++ ++ if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) ++ return 0; ++ ++ if (sec->cipher_pairwise & ++ (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104)) { ++ memset(&key, 0, sizeof(key)); ++ key.len = (u32) sme->key_len; ++ key.index = (u32) sme->key_idx; ++ if (key.len > sizeof(key.data)) { ++ WL_ERR("Too long key length (%u)\n", key.len); ++ return -EINVAL; ++ } ++ memcpy(key.data, sme->key, key.len); ++ key.flags = BRCMF_PRIMARY_KEY; ++ switch (sec->cipher_pairwise) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ key.algo = CRYPTO_ALGO_WEP1; ++ break; ++ case WLAN_CIPHER_SUITE_WEP104: ++ key.algo = CRYPTO_ALGO_WEP128; ++ break; ++ default: ++ WL_ERR("Invalid algorithm (%d)\n", ++ sme->crypto.ciphers_pairwise[0]); ++ return -EINVAL; ++ } ++ /* Set the new key/index */ ++ WL_CONN("key length (%d) key index (%d) algo (%d)\n", ++ key.len, key.index, key.algo); ++ WL_CONN("key \"%s\"\n", key.data); ++ err = send_key_to_dongle(ndev, &key); ++ if (err) ++ return err; ++ ++ if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) { ++ WL_CONN("set auth_type to shared key\n"); ++ val = 1; /* shared key */ ++ err = brcmf_dev_intvar_set(ndev, "auth", val); ++ if (err) { ++ WL_ERR("set auth failed (%d)\n", err); ++ return err; ++ } ++ } ++ } ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, ++ struct cfg80211_connect_params *sme) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct ieee80211_channel *chan = sme->channel; ++ struct brcmf_join_params join_params; ++ size_t join_params_size; ++ struct brcmf_ssid ssid; ++ ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ if (!sme->ssid) { ++ WL_ERR("Invalid ssid\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ set_bit(WL_STATUS_CONNECTING, &cfg_priv->status); ++ ++ if (chan) { ++ cfg_priv->channel = ++ ieee80211_frequency_to_channel(chan->center_freq); ++ WL_CONN("channel (%d), center_req (%d)\n", ++ cfg_priv->channel, chan->center_freq); ++ } else ++ cfg_priv->channel = 0; ++ ++ WL_INFO("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len); ++ ++ err = brcmf_set_wpa_version(ndev, sme); ++ if (err) { ++ WL_ERR("wl_set_wpa_version failed (%d)\n", err); ++ goto done; ++ } ++ ++ err = brcmf_set_auth_type(ndev, sme); ++ if (err) { ++ WL_ERR("wl_set_auth_type failed (%d)\n", err); ++ goto done; ++ } ++ ++ err = brcmf_set_set_cipher(ndev, sme); ++ if (err) { ++ WL_ERR("wl_set_set_cipher failed (%d)\n", err); ++ goto done; ++ } ++ ++ err = brcmf_set_key_mgmt(ndev, sme); ++ if (err) { ++ WL_ERR("wl_set_key_mgmt failed (%d)\n", err); ++ goto done; ++ } ++ ++ err = brcmf_set_wep_sharedkey(ndev, sme); ++ if (err) { ++ WL_ERR("brcmf_set_wep_sharedkey failed (%d)\n", err); ++ goto done; ++ } ++ ++ memset(&join_params, 0, sizeof(join_params)); ++ join_params_size = sizeof(join_params.ssid_le); ++ ++ ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), sme->ssid_len); ++ memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid.SSID_len); ++ memcpy(&ssid.SSID, sme->ssid, ssid.SSID_len); ++ join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len); ++ brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID); ++ ++ memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN); ++ ++ if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN) ++ WL_CONN("ssid \"%s\", len (%d)\n", ++ ssid.SSID, ssid.SSID_len); ++ ++ brcmf_ch_to_chanspec(cfg_priv->channel, ++ &join_params, &join_params_size); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, ++ &join_params, join_params_size); ++ if (err) ++ WL_ERR("WLC_SET_SSID failed (%d)\n", err); ++ ++done: ++ if (err) ++ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, ++ u16 reason_code) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct brcmf_scb_val_le scbval; ++ s32 err = 0; ++ ++ WL_TRACE("Enter. Reason code = %d\n", reason_code); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ clear_bit(WL_STATUS_CONNECTED, &cfg_priv->status); ++ ++ memcpy(&scbval.ea, brcmf_read_prof(cfg_priv, WL_PROF_BSSID), ETH_ALEN); ++ scbval.val = cpu_to_le32(reason_code); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, &scbval, ++ sizeof(struct brcmf_scb_val_le)); ++ if (err) ++ WL_ERR("error (%d)\n", err); ++ ++ cfg_priv->link_up = false; ++ ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, ++ enum nl80211_tx_power_setting type, s32 dbm) ++{ ++ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct net_device *ndev = cfg_to_ndev(cfg_priv); ++ u16 txpwrmw; ++ s32 err = 0; ++ s32 disable = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ switch (type) { ++ case NL80211_TX_POWER_AUTOMATIC: ++ break; ++ case NL80211_TX_POWER_LIMITED: ++ if (dbm < 0) { ++ WL_ERR("TX_POWER_LIMITED - dbm is negative\n"); ++ err = -EINVAL; ++ goto done; ++ } ++ break; ++ case NL80211_TX_POWER_FIXED: ++ if (dbm < 0) { ++ WL_ERR("TX_POWER_FIXED - dbm is negative\n"); ++ err = -EINVAL; ++ goto done; ++ } ++ break; ++ } ++ /* Make sure radio is off or on as far as software is concerned */ ++ disable = WL_RADIO_SW_DISABLE << 16; ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_RADIO, &disable); ++ if (err) ++ WL_ERR("WLC_SET_RADIO error (%d)\n", err); ++ ++ if (dbm > 0xffff) ++ txpwrmw = 0xffff; ++ else ++ txpwrmw = (u16) dbm; ++ err = brcmf_dev_intvar_set(ndev, "qtxpower", ++ (s32) (brcmf_mw_to_qdbm(txpwrmw))); ++ if (err) ++ WL_ERR("qtxpower error (%d)\n", err); ++ cfg_priv->conf->tx_power = dbm; ++ ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct net_device *ndev = cfg_to_ndev(cfg_priv); ++ s32 txpwrdbm; ++ u8 result; ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ err = brcmf_dev_intvar_get(ndev, "qtxpower", &txpwrdbm); ++ if (err) { ++ WL_ERR("error (%d)\n", err); ++ goto done; ++ } ++ ++ result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE); ++ *dbm = (s32) brcmf_qdbm_to_mw(result); ++ ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, ++ u8 key_idx, bool unicast, bool multicast) ++{ ++ u32 index; ++ u32 wsec; ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ WL_CONN("key index (%d)\n", key_idx); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec); ++ if (err) { ++ WL_ERR("WLC_GET_WSEC error (%d)\n", err); ++ goto done; ++ } ++ ++ if (wsec & WEP_ENABLED) { ++ /* Just select a new current key */ ++ index = key_idx; ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_KEY_PRIMARY, ++ &index); ++ if (err) ++ WL_ERR("error (%d)\n", err); ++ } ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, ++ u8 key_idx, const u8 *mac_addr, struct key_params *params) ++{ ++ struct brcmf_wsec_key key; ++ struct brcmf_wsec_key_le key_le; ++ s32 err = 0; ++ ++ memset(&key, 0, sizeof(key)); ++ key.index = (u32) key_idx; ++ /* Instead of bcast for ea address for default wep keys, ++ driver needs it to be Null */ ++ if (!is_multicast_ether_addr(mac_addr)) ++ memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN); ++ key.len = (u32) params->key_len; ++ /* check for key index change */ ++ if (key.len == 0) { ++ /* key delete */ ++ err = send_key_to_dongle(ndev, &key); ++ if (err) ++ return err; ++ } else { ++ if (key.len > sizeof(key.data)) { ++ WL_ERR("Invalid key length (%d)\n", key.len); ++ return -EINVAL; ++ } ++ ++ WL_CONN("Setting the key index %d\n", key.index); ++ memcpy(key.data, params->key, key.len); ++ ++ if (params->cipher == WLAN_CIPHER_SUITE_TKIP) { ++ u8 keybuf[8]; ++ memcpy(keybuf, &key.data[24], sizeof(keybuf)); ++ memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); ++ memcpy(&key.data[16], keybuf, sizeof(keybuf)); ++ } ++ ++ /* if IW_ENCODE_EXT_RX_SEQ_VALID set */ ++ if (params->seq && params->seq_len == 6) { ++ /* rx iv */ ++ u8 *ivptr; ++ ivptr = (u8 *) params->seq; ++ key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) | ++ (ivptr[3] << 8) | ivptr[2]; ++ key.rxiv.lo = (ivptr[1] << 8) | ivptr[0]; ++ key.iv_initialized = true; ++ } ++ ++ switch (params->cipher) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ key.algo = CRYPTO_ALGO_WEP1; ++ WL_CONN("WLAN_CIPHER_SUITE_WEP40\n"); ++ break; ++ case WLAN_CIPHER_SUITE_WEP104: ++ key.algo = CRYPTO_ALGO_WEP128; ++ WL_CONN("WLAN_CIPHER_SUITE_WEP104\n"); ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ key.algo = CRYPTO_ALGO_TKIP; ++ WL_CONN("WLAN_CIPHER_SUITE_TKIP\n"); ++ break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ key.algo = CRYPTO_ALGO_AES_CCM; ++ WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n"); ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ key.algo = CRYPTO_ALGO_AES_CCM; ++ WL_CONN("WLAN_CIPHER_SUITE_CCMP\n"); ++ break; ++ default: ++ WL_ERR("Invalid cipher (0x%x)\n", params->cipher); ++ return -EINVAL; ++ } ++ convert_key_from_CPU(&key, &key_le); ++ ++ brcmf_netdev_wait_pend8021x(ndev); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le, ++ sizeof(key_le)); ++ if (err) { ++ WL_ERR("WLC_SET_KEY error (%d)\n", err); ++ return err; ++ } ++ } ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, ++ u8 key_idx, bool pairwise, const u8 *mac_addr, ++ struct key_params *params) ++{ ++ struct brcmf_wsec_key key; ++ s32 val; ++ s32 wsec; ++ s32 err = 0; ++ u8 keybuf[8]; ++ ++ WL_TRACE("Enter\n"); ++ WL_CONN("key index (%d)\n", key_idx); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ if (mac_addr) { ++ WL_TRACE("Exit"); ++ return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params); ++ } ++ memset(&key, 0, sizeof(key)); ++ ++ key.len = (u32) params->key_len; ++ key.index = (u32) key_idx; ++ ++ if (key.len > sizeof(key.data)) { ++ WL_ERR("Too long key length (%u)\n", key.len); ++ err = -EINVAL; ++ goto done; ++ } ++ memcpy(key.data, params->key, key.len); ++ ++ key.flags = BRCMF_PRIMARY_KEY; ++ switch (params->cipher) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ key.algo = CRYPTO_ALGO_WEP1; ++ WL_CONN("WLAN_CIPHER_SUITE_WEP40\n"); ++ break; ++ case WLAN_CIPHER_SUITE_WEP104: ++ key.algo = CRYPTO_ALGO_WEP128; ++ WL_CONN("WLAN_CIPHER_SUITE_WEP104\n"); ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ memcpy(keybuf, &key.data[24], sizeof(keybuf)); ++ memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); ++ memcpy(&key.data[16], keybuf, sizeof(keybuf)); ++ key.algo = CRYPTO_ALGO_TKIP; ++ WL_CONN("WLAN_CIPHER_SUITE_TKIP\n"); ++ break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ key.algo = CRYPTO_ALGO_AES_CCM; ++ WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n"); ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ key.algo = CRYPTO_ALGO_AES_CCM; ++ WL_CONN("WLAN_CIPHER_SUITE_CCMP\n"); ++ break; ++ default: ++ WL_ERR("Invalid cipher (0x%x)\n", params->cipher); ++ err = -EINVAL; ++ goto done; ++ } ++ ++ err = send_key_to_dongle(ndev, &key); /* Set the new key/index */ ++ if (err) ++ goto done; ++ ++ val = WEP_ENABLED; ++ err = brcmf_dev_intvar_get(ndev, "wsec", &wsec); ++ if (err) { ++ WL_ERR("get wsec error (%d)\n", err); ++ goto done; ++ } ++ wsec &= ~(WEP_ENABLED); ++ wsec |= val; ++ err = brcmf_dev_intvar_set(ndev, "wsec", wsec); ++ if (err) { ++ WL_ERR("set wsec error (%d)\n", err); ++ goto done; ++ } ++ ++ val = 1; /* assume shared key. otherwise 0 */ ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val); ++ if (err) ++ WL_ERR("WLC_SET_AUTH error (%d)\n", err); ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, ++ u8 key_idx, bool pairwise, const u8 *mac_addr) ++{ ++ struct brcmf_wsec_key key; ++ s32 err = 0; ++ s32 val; ++ s32 wsec; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ memset(&key, 0, sizeof(key)); ++ ++ key.index = (u32) key_idx; ++ key.flags = BRCMF_PRIMARY_KEY; ++ key.algo = CRYPTO_ALGO_OFF; ++ ++ WL_CONN("key index (%d)\n", key_idx); ++ ++ /* Set the new key/index */ ++ err = send_key_to_dongle(ndev, &key); ++ if (err) { ++ if (err == -EINVAL) { ++ if (key.index >= DOT11_MAX_DEFAULT_KEYS) ++ /* we ignore this key index in this case */ ++ WL_ERR("invalid key index (%d)\n", key_idx); ++ } ++ /* Ignore this error, may happen during DISASSOC */ ++ err = -EAGAIN; ++ goto done; ++ } ++ ++ val = 0; ++ err = brcmf_dev_intvar_get(ndev, "wsec", &wsec); ++ if (err) { ++ WL_ERR("get wsec error (%d)\n", err); ++ /* Ignore this error, may happen during DISASSOC */ ++ err = -EAGAIN; ++ goto done; ++ } ++ wsec &= ~(WEP_ENABLED); ++ wsec |= val; ++ err = brcmf_dev_intvar_set(ndev, "wsec", wsec); ++ if (err) { ++ WL_ERR("set wsec error (%d)\n", err); ++ /* Ignore this error, may happen during DISASSOC */ ++ err = -EAGAIN; ++ goto done; ++ } ++ ++ val = 0; /* assume open key. otherwise 1 */ ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val); ++ if (err) { ++ WL_ERR("WLC_SET_AUTH error (%d)\n", err); ++ /* Ignore this error, may happen during DISASSOC */ ++ err = -EAGAIN; ++ } ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, ++ u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie, ++ void (*callback) (void *cookie, struct key_params * params)) ++{ ++ struct key_params params; ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct brcmf_cfg80211_security *sec; ++ s32 wsec; ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ WL_CONN("key index (%d)\n", key_idx); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ memset(¶ms, 0, sizeof(params)); ++ ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec); ++ if (err) { ++ WL_ERR("WLC_GET_WSEC error (%d)\n", err); ++ /* Ignore this error, may happen during DISASSOC */ ++ err = -EAGAIN; ++ goto done; ++ } ++ switch (wsec) { ++ case WEP_ENABLED: ++ sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); ++ if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) { ++ params.cipher = WLAN_CIPHER_SUITE_WEP40; ++ WL_CONN("WLAN_CIPHER_SUITE_WEP40\n"); ++ } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) { ++ params.cipher = WLAN_CIPHER_SUITE_WEP104; ++ WL_CONN("WLAN_CIPHER_SUITE_WEP104\n"); ++ } ++ break; ++ case TKIP_ENABLED: ++ params.cipher = WLAN_CIPHER_SUITE_TKIP; ++ WL_CONN("WLAN_CIPHER_SUITE_TKIP\n"); ++ break; ++ case AES_ENABLED: ++ params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; ++ WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n"); ++ break; ++ default: ++ WL_ERR("Invalid algo (0x%x)\n", wsec); ++ err = -EINVAL; ++ goto done; ++ } ++ callback(cookie, ¶ms); ++ ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, ++ struct net_device *ndev, u8 key_idx) ++{ ++ WL_INFO("Not supported\n"); ++ ++ return -EOPNOTSUPP; ++} ++ ++static s32 ++brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, ++ u8 *mac, struct station_info *sinfo) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct brcmf_scb_val_le scb_val; ++ int rssi; ++ s32 rate; ++ s32 err = 0; ++ u8 *bssid = brcmf_read_prof(cfg_priv, WL_PROF_BSSID); ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ if (memcmp(mac, bssid, ETH_ALEN)) { ++ WL_ERR("Wrong Mac address cfg_mac-%X:%X:%X:%X:%X:%X" ++ "wl_bssid-%X:%X:%X:%X:%X:%X\n", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ++ bssid[0], bssid[1], bssid[2], bssid[3], ++ bssid[4], bssid[5]); ++ err = -ENOENT; ++ goto done; ++ } ++ ++ /* Report the current tx rate */ ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_RATE, &rate); ++ if (err) { ++ WL_ERR("Could not get rate (%d)\n", err); ++ } else { ++ sinfo->filled |= STATION_INFO_TX_BITRATE; ++ sinfo->txrate.legacy = rate * 5; ++ WL_CONN("Rate %d Mbps\n", rate / 2); ++ } ++ ++ if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) { ++ scb_val.val = cpu_to_le32(0); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val, ++ sizeof(struct brcmf_scb_val_le)); ++ if (err) ++ WL_ERR("Could not get rssi (%d)\n", err); ++ ++ rssi = le32_to_cpu(scb_val.val); ++ sinfo->filled |= STATION_INFO_SIGNAL; ++ sinfo->signal = rssi; ++ WL_CONN("RSSI %d dBm\n", rssi); ++ } ++ ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, ++ bool enabled, s32 timeout) ++{ ++ s32 pm; ++ s32 err = 0; ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ ++ WL_TRACE("Enter\n"); ++ ++ /* ++ * Powersave enable/disable request is coming from the ++ * cfg80211 even before the interface is up. In that ++ * scenario, driver will be storing the power save ++ * preference in cfg_priv struct to apply this to ++ * FW later while initializing the dongle ++ */ ++ cfg_priv->pwr_save = enabled; ++ if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) { ++ ++ WL_INFO("Device is not ready," ++ "storing the value in cfg_priv struct\n"); ++ goto done; ++ } ++ ++ pm = enabled ? PM_FAST : PM_OFF; ++ WL_INFO("power save %s\n", (pm ? "enabled" : "disabled")); ++ ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &pm); ++ if (err) { ++ if (err == -ENODEV) ++ WL_ERR("net_device is not ready yet\n"); ++ else ++ WL_ERR("error (%d)\n", err); ++ } ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev, ++ const u8 *addr, ++ const struct cfg80211_bitrate_mask *mask) ++{ ++ struct brcm_rateset_le rateset_le; ++ s32 rate; ++ s32 val; ++ s32 err_bg; ++ s32 err_a; ++ u32 legacy; ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ /* addr param is always NULL. ignore it */ ++ /* Get current rateset */ ++ err = brcmf_exec_dcmd(ndev, BRCM_GET_CURR_RATESET, &rateset_le, ++ sizeof(rateset_le)); ++ if (err) { ++ WL_ERR("could not get current rateset (%d)\n", err); ++ goto done; ++ } ++ ++ legacy = ffs(mask->control[IEEE80211_BAND_2GHZ].legacy & 0xFFFF); ++ if (!legacy) ++ legacy = ffs(mask->control[IEEE80211_BAND_5GHZ].legacy & ++ 0xFFFF); ++ ++ val = wl_g_rates[legacy - 1].bitrate * 100000; ++ ++ if (val < le32_to_cpu(rateset_le.count)) ++ /* Select rate by rateset index */ ++ rate = rateset_le.rates[val] & 0x7f; ++ else ++ /* Specified rate in bps */ ++ rate = val / 500000; ++ ++ WL_CONN("rate %d mbps\n", rate / 2); ++ ++ /* ++ * ++ * Set rate override, ++ * Since the is a/b/g-blind, both a/bg_rate are enforced. ++ */ ++ err_bg = brcmf_dev_intvar_set(ndev, "bg_rate", rate); ++ err_a = brcmf_dev_intvar_set(ndev, "a_rate", rate); ++ if (err_bg && err_a) { ++ WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a); ++ err = err_bg | err_a; ++ } ++ ++done: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv, ++ struct brcmf_bss_info *bi) ++{ ++ struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); ++ struct ieee80211_channel *notify_channel; ++ struct cfg80211_bss *bss; ++ struct ieee80211_supported_band *band; ++ s32 err = 0; ++ u16 channel; ++ u32 freq; ++ u64 notify_timestamp; ++ u16 notify_capability; ++ u16 notify_interval; ++ u8 *notify_ie; ++ size_t notify_ielen; ++ s32 notify_signal; ++ ++ if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) { ++ WL_ERR("Bss info is larger than buffer. Discarding\n"); ++ return 0; ++ } ++ ++ channel = bi->ctl_ch ? bi->ctl_ch : ++ CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec)); ++ ++ if (channel <= CH_MAX_2G_CHANNEL) ++ band = wiphy->bands[IEEE80211_BAND_2GHZ]; ++ else ++ band = wiphy->bands[IEEE80211_BAND_5GHZ]; ++ ++ freq = ieee80211_channel_to_frequency(channel, band->band); ++ notify_channel = ieee80211_get_channel(wiphy, freq); ++ ++ notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */ ++ notify_capability = le16_to_cpu(bi->capability); ++ notify_interval = le16_to_cpu(bi->beacon_period); ++ notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset); ++ notify_ielen = le32_to_cpu(bi->ie_length); ++ notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100; ++ ++ WL_CONN("bssid: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", ++ bi->BSSID[0], bi->BSSID[1], bi->BSSID[2], ++ bi->BSSID[3], bi->BSSID[4], bi->BSSID[5]); ++ WL_CONN("Channel: %d(%d)\n", channel, freq); ++ WL_CONN("Capability: %X\n", notify_capability); ++ WL_CONN("Beacon interval: %d\n", notify_interval); ++ WL_CONN("Signal: %d\n", notify_signal); ++ WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp); ++ ++ bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID, ++ notify_timestamp, notify_capability, notify_interval, notify_ie, ++ notify_ielen, notify_signal, GFP_KERNEL); ++ ++ if (!bss) { ++ WL_ERR("cfg80211_inform_bss_frame error\n"); ++ return -EINVAL; ++ } ++ ++ return err; ++} ++ ++static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_scan_results *bss_list; ++ struct brcmf_bss_info *bi = NULL; /* must be initialized */ ++ s32 err = 0; ++ int i; ++ ++ bss_list = cfg_priv->bss_list; ++ if (bss_list->version != BRCMF_BSS_INFO_VERSION) { ++ WL_ERR("Version %d != WL_BSS_INFO_VERSION\n", ++ bss_list->version); ++ return -EOPNOTSUPP; ++ } ++ WL_SCAN("scanned AP count (%d)\n", bss_list->count); ++ for (i = 0; i < bss_list->count && i < WL_AP_MAX; i++) { ++ bi = next_bss(bss_list, bi); ++ err = brcmf_inform_single_bss(cfg_priv, bi); ++ if (err) ++ break; ++ } ++ return err; ++} ++ ++static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv, ++ struct net_device *ndev, const u8 *bssid) ++{ ++ struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); ++ struct ieee80211_channel *notify_channel; ++ struct brcmf_bss_info *bi = NULL; ++ struct ieee80211_supported_band *band; ++ u8 *buf = NULL; ++ s32 err = 0; ++ u16 channel; ++ u32 freq; ++ u64 notify_timestamp; ++ u16 notify_capability; ++ u16 notify_interval; ++ u8 *notify_ie; ++ size_t notify_ielen; ++ s32 notify_signal; ++ ++ WL_TRACE("Enter\n"); ++ ++ buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); ++ if (buf == NULL) { ++ err = -ENOMEM; ++ goto CleanUp; ++ } ++ ++ *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX); ++ ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX); ++ if (err) { ++ WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err); ++ goto CleanUp; ++ } ++ ++ bi = (struct brcmf_bss_info *)(buf + 4); ++ ++ channel = bi->ctl_ch ? bi->ctl_ch : ++ CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec)); ++ ++ if (channel <= CH_MAX_2G_CHANNEL) ++ band = wiphy->bands[IEEE80211_BAND_2GHZ]; ++ else ++ band = wiphy->bands[IEEE80211_BAND_5GHZ]; ++ ++ freq = ieee80211_channel_to_frequency(channel, band->band); ++ notify_channel = ieee80211_get_channel(wiphy, freq); ++ ++ notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */ ++ notify_capability = le16_to_cpu(bi->capability); ++ notify_interval = le16_to_cpu(bi->beacon_period); ++ notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset); ++ notify_ielen = le32_to_cpu(bi->ie_length); ++ notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100; ++ ++ WL_CONN("channel: %d(%d)\n", channel, freq); ++ WL_CONN("capability: %X\n", notify_capability); ++ WL_CONN("beacon interval: %d\n", notify_interval); ++ WL_CONN("signal: %d\n", notify_signal); ++ WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp); ++ ++ cfg80211_inform_bss(wiphy, notify_channel, bssid, ++ notify_timestamp, notify_capability, notify_interval, ++ notify_ie, notify_ielen, notify_signal, GFP_KERNEL); ++ ++CleanUp: ++ ++ kfree(buf); ++ ++ WL_TRACE("Exit\n"); ++ ++ return err; ++} ++ ++static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ return cfg_priv->conf->mode == WL_MODE_IBSS; ++} ++ ++/* ++ * Traverse a string of 1-byte tag/1-byte length/variable-length value ++ * triples, returning a pointer to the substring whose first element ++ * matches tag ++ */ ++static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key) ++{ ++ struct brcmf_tlv *elt; ++ int totlen; ++ ++ elt = (struct brcmf_tlv *) buf; ++ totlen = buflen; ++ ++ /* find tagged parameter */ ++ while (totlen >= 2) { ++ int len = elt->len; ++ ++ /* validate remaining totlen */ ++ if ((elt->id == key) && (totlen >= (len + 2))) ++ return elt; ++ ++ elt = (struct brcmf_tlv *) ((u8 *) elt + (len + 2)); ++ totlen -= (len + 2); ++ } ++ ++ return NULL; ++} ++ ++static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_bss_info *bi; ++ struct brcmf_ssid *ssid; ++ struct brcmf_tlv *tim; ++ u16 beacon_interval; ++ u8 dtim_period; ++ size_t ie_len; ++ u8 *ie; ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (brcmf_is_ibssmode(cfg_priv)) ++ return err; ++ ++ ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg_priv, WL_PROF_SSID); ++ ++ *(__le32 *)cfg_priv->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX); ++ err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_GET_BSS_INFO, ++ cfg_priv->extra_buf, WL_EXTRA_BUF_MAX); ++ if (err) { ++ WL_ERR("Could not get bss info %d\n", err); ++ goto update_bss_info_out; ++ } ++ ++ bi = (struct brcmf_bss_info *)(cfg_priv->extra_buf + 4); ++ err = brcmf_inform_single_bss(cfg_priv, bi); ++ if (err) ++ goto update_bss_info_out; ++ ++ ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset); ++ ie_len = le32_to_cpu(bi->ie_length); ++ beacon_interval = le16_to_cpu(bi->beacon_period); ++ ++ tim = brcmf_parse_tlvs(ie, ie_len, WLAN_EID_TIM); ++ if (tim) ++ dtim_period = tim->data[1]; ++ else { ++ /* ++ * active scan was done so we could not get dtim ++ * information out of probe response. ++ * so we speficially query dtim information to dongle. ++ */ ++ u32 var; ++ err = brcmf_dev_intvar_get(cfg_to_ndev(cfg_priv), ++ "dtim_assoc", &var); ++ if (err) { ++ WL_ERR("wl dtim_assoc failed (%d)\n", err); ++ goto update_bss_info_out; ++ } ++ dtim_period = (u8)var; ++ } ++ ++ brcmf_update_prof(cfg_priv, NULL, &beacon_interval, WL_PROF_BEACONINT); ++ brcmf_update_prof(cfg_priv, NULL, &dtim_period, WL_PROF_DTIMPERIOD); ++ ++update_bss_info_out: ++ WL_TRACE("Exit"); ++ return err; ++} ++ ++static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); ++ struct brcmf_ssid ssid; ++ ++ if (cfg_priv->iscan_on) { ++ iscan->state = WL_ISCAN_STATE_IDLE; ++ ++ if (iscan->timer_on) { ++ del_timer_sync(&iscan->timer); ++ iscan->timer_on = 0; ++ } ++ ++ cancel_work_sync(&iscan->work); ++ ++ /* Abort iscan running in FW */ ++ memset(&ssid, 0, sizeof(ssid)); ++ brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT); ++ } ++} ++ ++static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan, ++ bool aborted) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan); ++ struct net_device *ndev = cfg_to_ndev(cfg_priv); ++ ++ if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { ++ WL_ERR("Scan complete while device not scanning\n"); ++ return; ++ } ++ if (cfg_priv->scan_request) { ++ WL_SCAN("ISCAN Completed scan: %s\n", ++ aborted ? "Aborted" : "Done"); ++ cfg80211_scan_done(cfg_priv->scan_request, aborted); ++ brcmf_set_mpc(ndev, 1); ++ cfg_priv->scan_request = NULL; ++ } ++ cfg_priv->iscan_kickstart = false; ++} ++ ++static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan) ++{ ++ if (iscan->state != WL_ISCAN_STATE_IDLE) { ++ WL_SCAN("wake up iscan\n"); ++ schedule_work(&iscan->work); ++ return 0; ++ } ++ ++ return -EIO; ++} ++ ++static s32 ++brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status, ++ struct brcmf_scan_results **bss_list) ++{ ++ struct brcmf_iscan_results list; ++ struct brcmf_scan_results *results; ++ struct brcmf_scan_results_le *results_le; ++ struct brcmf_iscan_results *list_buf; ++ s32 err = 0; ++ ++ memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX); ++ list_buf = (struct brcmf_iscan_results *)iscan->scan_buf; ++ results = &list_buf->results; ++ results_le = &list_buf->results_le; ++ results->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE; ++ results->version = 0; ++ results->count = 0; ++ ++ memset(&list, 0, sizeof(list)); ++ list.results_le.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX); ++ err = brcmf_dev_iovar_getbuf(iscan->ndev, "iscanresults", &list, ++ BRCMF_ISCAN_RESULTS_FIXED_SIZE, ++ iscan->scan_buf, WL_ISCAN_BUF_MAX); ++ if (err) { ++ WL_ERR("error (%d)\n", err); ++ return err; ++ } ++ results->buflen = le32_to_cpu(results_le->buflen); ++ results->version = le32_to_cpu(results_le->version); ++ results->count = le32_to_cpu(results_le->count); ++ WL_SCAN("results->count = %d\n", results_le->count); ++ WL_SCAN("results->buflen = %d\n", results_le->buflen); ++ *status = le32_to_cpu(list_buf->status_le); ++ WL_SCAN("status = %d\n", *status); ++ *bss_list = results; ++ ++ return err; ++} ++ ++static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; ++ s32 err = 0; ++ ++ iscan->state = WL_ISCAN_STATE_IDLE; ++ brcmf_inform_bss(cfg_priv); ++ brcmf_notify_iscan_complete(iscan, false); ++ ++ return err; ++} ++ ++static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; ++ s32 err = 0; ++ ++ /* Reschedule the timer */ ++ mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000); ++ iscan->timer_on = 1; ++ ++ return err; ++} ++ ++static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; ++ s32 err = 0; ++ ++ brcmf_inform_bss(cfg_priv); ++ brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE); ++ /* Reschedule the timer */ ++ mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000); ++ iscan->timer_on = 1; ++ ++ return err; ++} ++ ++static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; ++ s32 err = 0; ++ ++ iscan->state = WL_ISCAN_STATE_IDLE; ++ brcmf_notify_iscan_complete(iscan, true); ++ ++ return err; ++} ++ ++static void brcmf_cfg80211_iscan_handler(struct work_struct *work) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = ++ container_of(work, struct brcmf_cfg80211_iscan_ctrl, ++ work); ++ struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan); ++ struct brcmf_cfg80211_iscan_eloop *el = &iscan->el; ++ u32 status = BRCMF_SCAN_RESULTS_PARTIAL; ++ ++ if (iscan->timer_on) { ++ del_timer_sync(&iscan->timer); ++ iscan->timer_on = 0; ++ } ++ ++ if (brcmf_get_iscan_results(iscan, &status, &cfg_priv->bss_list)) { ++ status = BRCMF_SCAN_RESULTS_ABORTED; ++ WL_ERR("Abort iscan\n"); ++ } ++ ++ el->handler[status](cfg_priv); ++} ++ ++static void brcmf_iscan_timer(unsigned long data) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = ++ (struct brcmf_cfg80211_iscan_ctrl *)data; ++ ++ if (iscan) { ++ iscan->timer_on = 0; ++ WL_SCAN("timer expired\n"); ++ brcmf_wakeup_iscan(iscan); ++ } ++} ++ ++static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); ++ ++ if (cfg_priv->iscan_on) { ++ iscan->state = WL_ISCAN_STATE_IDLE; ++ INIT_WORK(&iscan->work, brcmf_cfg80211_iscan_handler); ++ } ++ ++ return 0; ++} ++ ++static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el) ++{ ++ memset(el, 0, sizeof(*el)); ++ el->handler[BRCMF_SCAN_RESULTS_SUCCESS] = brcmf_iscan_done; ++ el->handler[BRCMF_SCAN_RESULTS_PARTIAL] = brcmf_iscan_inprogress; ++ el->handler[BRCMF_SCAN_RESULTS_PENDING] = brcmf_iscan_pending; ++ el->handler[BRCMF_SCAN_RESULTS_ABORTED] = brcmf_iscan_aborted; ++ el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted; ++} ++ ++static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); ++ int err = 0; ++ ++ if (cfg_priv->iscan_on) { ++ iscan->ndev = cfg_to_ndev(cfg_priv); ++ brcmf_init_iscan_eloop(&iscan->el); ++ iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS; ++ init_timer(&iscan->timer); ++ iscan->timer.data = (unsigned long) iscan; ++ iscan->timer.function = brcmf_iscan_timer; ++ err = brcmf_invoke_iscan(cfg_priv); ++ if (!err) ++ iscan->data = cfg_priv; ++ } ++ ++ return err; ++} ++ ++static void brcmf_delay(u32 ms) ++{ ++ if (ms < 1000 / HZ) { ++ cond_resched(); ++ mdelay(ms); ++ } else { ++ msleep(ms); ++ } ++} ++ ++static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ ++ /* ++ * Check for WL_STATUS_READY before any function call which ++ * could result is bus access. Don't block the resume for ++ * any driver error conditions ++ */ ++ WL_TRACE("Enter\n"); ++ ++ if (test_bit(WL_STATUS_READY, &cfg_priv->status)) ++ brcmf_invoke_iscan(wiphy_to_cfg(wiphy)); ++ ++ WL_TRACE("Exit\n"); ++ return 0; ++} ++ ++static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, ++ struct cfg80211_wowlan *wow) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct net_device *ndev = cfg_to_ndev(cfg_priv); ++ ++ WL_TRACE("Enter\n"); ++ ++ /* ++ * Check for WL_STATUS_READY before any function call which ++ * could result is bus access. Don't block the suspend for ++ * any driver error conditions ++ */ ++ ++ /* ++ * While going to suspend if associated with AP disassociate ++ * from AP to save power while system is in suspended state ++ */ ++ if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) || ++ test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) && ++ test_bit(WL_STATUS_READY, &cfg_priv->status)) { ++ WL_INFO("Disassociating from AP" ++ " while entering suspend state\n"); ++ brcmf_link_down(cfg_priv); ++ ++ /* ++ * Make sure WPA_Supplicant receives all the event ++ * generated due to DISASSOC call to the fw to keep ++ * the state fw and WPA_Supplicant state consistent ++ */ ++ brcmf_delay(500); ++ } ++ ++ set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); ++ if (test_bit(WL_STATUS_READY, &cfg_priv->status)) ++ brcmf_term_iscan(cfg_priv); ++ ++ if (cfg_priv->scan_request) { ++ /* Indidate scan abort to cfg80211 layer */ ++ WL_INFO("Terminating scan in progress\n"); ++ cfg80211_scan_done(cfg_priv->scan_request, true); ++ cfg_priv->scan_request = NULL; ++ } ++ clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); ++ clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); ++ ++ /* Turn off watchdog timer */ ++ if (test_bit(WL_STATUS_READY, &cfg_priv->status)) { ++ WL_INFO("Enable MPC\n"); ++ brcmf_set_mpc(ndev, 1); ++ } ++ ++ WL_TRACE("Exit\n"); ++ ++ return 0; ++} ++ ++static __used s32 ++brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ u32 buflen; ++ ++ buflen = brcmf_c_mkiovar(name, buf, len, cfg_priv->dcmd_buf, ++ WL_DCMD_LEN_MAX); ++ BUG_ON(!buflen); ++ ++ return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg_priv->dcmd_buf, ++ buflen); ++} ++ ++static s32 ++brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf, ++ s32 buf_len) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ u32 len; ++ s32 err = 0; ++ ++ len = brcmf_c_mkiovar(name, NULL, 0, cfg_priv->dcmd_buf, ++ WL_DCMD_LEN_MAX); ++ BUG_ON(!len); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg_priv->dcmd_buf, ++ WL_DCMD_LEN_MAX); ++ if (err) { ++ WL_ERR("error (%d)\n", err); ++ return err; ++ } ++ memcpy(buf, cfg_priv->dcmd_buf, buf_len); ++ ++ return err; ++} ++ ++static __used s32 ++brcmf_update_pmklist(struct net_device *ndev, ++ struct brcmf_cfg80211_pmk_list *pmk_list, s32 err) ++{ ++ int i, j; ++ int pmkid_len; ++ ++ pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid); ++ ++ WL_CONN("No of elements %d\n", pmkid_len); ++ for (i = 0; i < pmkid_len; i++) { ++ WL_CONN("PMKID[%d]: %pM =\n", i, ++ &pmk_list->pmkids.pmkid[i].BSSID); ++ for (j = 0; j < WLAN_PMKID_LEN; j++) ++ WL_CONN("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]); ++ } ++ ++ if (!err) ++ brcmf_dev_bufvar_set(ndev, "pmkid_info", (char *)pmk_list, ++ sizeof(*pmk_list)); ++ ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, ++ struct cfg80211_pmksa *pmksa) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids; ++ s32 err = 0; ++ int i; ++ int pmkid_len; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ pmkid_len = le32_to_cpu(pmkids->npmkid); ++ for (i = 0; i < pmkid_len; i++) ++ if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN)) ++ break; ++ if (i < WL_NUM_PMKIDS_MAX) { ++ memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN); ++ memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN); ++ if (i == pmkid_len) { ++ pmkid_len++; ++ pmkids->npmkid = cpu_to_le32(pmkid_len); ++ } ++ } else ++ err = -EINVAL; ++ ++ WL_CONN("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n", ++ pmkids->pmkid[pmkid_len].BSSID); ++ for (i = 0; i < WLAN_PMKID_LEN; i++) ++ WL_CONN("%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]); ++ ++ err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err); ++ ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, ++ struct cfg80211_pmksa *pmksa) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ struct pmkid_list pmkid; ++ s32 err = 0; ++ int i, pmkid_len; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN); ++ memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN); ++ ++ WL_CONN("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n", ++ &pmkid.pmkid[0].BSSID); ++ for (i = 0; i < WLAN_PMKID_LEN; i++) ++ WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]); ++ ++ pmkid_len = le32_to_cpu(cfg_priv->pmk_list->pmkids.npmkid); ++ for (i = 0; i < pmkid_len; i++) ++ if (!memcmp ++ (pmksa->bssid, &cfg_priv->pmk_list->pmkids.pmkid[i].BSSID, ++ ETH_ALEN)) ++ break; ++ ++ if ((pmkid_len > 0) ++ && (i < pmkid_len)) { ++ memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0, ++ sizeof(struct pmkid)); ++ for (; i < (pmkid_len - 1); i++) { ++ memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID, ++ &cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID, ++ ETH_ALEN); ++ memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].PMKID, ++ &cfg_priv->pmk_list->pmkids.pmkid[i + 1].PMKID, ++ WLAN_PMKID_LEN); ++ } ++ cfg_priv->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1); ++ } else ++ err = -EINVAL; ++ ++ err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err); ++ ++ WL_TRACE("Exit\n"); ++ return err; ++ ++} ++ ++static s32 ++brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ if (!check_sys_up(wiphy)) ++ return -EIO; ++ ++ memset(cfg_priv->pmk_list, 0, sizeof(*cfg_priv->pmk_list)); ++ err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err); ++ ++ WL_TRACE("Exit\n"); ++ return err; ++ ++} ++ ++static struct cfg80211_ops wl_cfg80211_ops = { ++ .change_virtual_intf = brcmf_cfg80211_change_iface, ++ .scan = brcmf_cfg80211_scan, ++ .set_wiphy_params = brcmf_cfg80211_set_wiphy_params, ++ .join_ibss = brcmf_cfg80211_join_ibss, ++ .leave_ibss = brcmf_cfg80211_leave_ibss, ++ .get_station = brcmf_cfg80211_get_station, ++ .set_tx_power = brcmf_cfg80211_set_tx_power, ++ .get_tx_power = brcmf_cfg80211_get_tx_power, ++ .add_key = brcmf_cfg80211_add_key, ++ .del_key = brcmf_cfg80211_del_key, ++ .get_key = brcmf_cfg80211_get_key, ++ .set_default_key = brcmf_cfg80211_config_default_key, ++ .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key, ++ .set_power_mgmt = brcmf_cfg80211_set_power_mgmt, ++ .set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask, ++ .connect = brcmf_cfg80211_connect, ++ .disconnect = brcmf_cfg80211_disconnect, ++ .suspend = brcmf_cfg80211_suspend, ++ .resume = brcmf_cfg80211_resume, ++ .set_pmksa = brcmf_cfg80211_set_pmksa, ++ .del_pmksa = brcmf_cfg80211_del_pmksa, ++ .flush_pmksa = brcmf_cfg80211_flush_pmksa ++}; ++ ++static s32 brcmf_mode_to_nl80211_iftype(s32 mode) ++{ ++ s32 err = 0; ++ ++ switch (mode) { ++ case WL_MODE_BSS: ++ return NL80211_IFTYPE_STATION; ++ case WL_MODE_IBSS: ++ return NL80211_IFTYPE_ADHOC; ++ default: ++ return NL80211_IFTYPE_UNSPECIFIED; ++ } ++ ++ return err; ++} ++ ++static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface, ++ struct device *ndev) ++{ ++ struct wireless_dev *wdev; ++ s32 err = 0; ++ ++ wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); ++ if (!wdev) ++ return ERR_PTR(-ENOMEM); ++ ++ wdev->wiphy = ++ wiphy_new(&wl_cfg80211_ops, ++ sizeof(struct brcmf_cfg80211_priv) + sizeof_iface); ++ if (!wdev->wiphy) { ++ WL_ERR("Couldn not allocate wiphy device\n"); ++ err = -ENOMEM; ++ goto wiphy_new_out; ++ } ++ set_wiphy_dev(wdev->wiphy, ndev); ++ wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; ++ wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; ++ wdev->wiphy->interface_modes = ++ BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); ++ wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; ++ wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set ++ * it as 11a by default. ++ * This will be updated with ++ * 11n phy tables in ++ * "ifconfig up" ++ * if phy has 11n capability ++ */ ++ wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; ++ wdev->wiphy->cipher_suites = __wl_cipher_suites; ++ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); ++ wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power ++ * save mode ++ * by default ++ */ ++ err = wiphy_register(wdev->wiphy); ++ if (err < 0) { ++ WL_ERR("Couldn not register wiphy device (%d)\n", err); ++ goto wiphy_register_out; ++ } ++ return wdev; ++ ++wiphy_register_out: ++ wiphy_free(wdev->wiphy); ++ ++wiphy_new_out: ++ kfree(wdev); ++ ++ return ERR_PTR(err); ++} ++ ++static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct wireless_dev *wdev = cfg_priv->wdev; ++ ++ if (!wdev) { ++ WL_ERR("wdev is invalid\n"); ++ return; ++ } ++ wiphy_unregister(wdev->wiphy); ++ wiphy_free(wdev->wiphy); ++ kfree(wdev); ++ cfg_priv->wdev = NULL; ++} ++ ++static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv, ++ const struct brcmf_event_msg *e) ++{ ++ u32 event = be32_to_cpu(e->event_type); ++ u32 status = be32_to_cpu(e->status); ++ ++ if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) { ++ WL_CONN("Processing set ssid\n"); ++ cfg_priv->link_up = true; ++ return true; ++ } ++ ++ return false; ++} ++ ++static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv, ++ const struct brcmf_event_msg *e) ++{ ++ u32 event = be32_to_cpu(e->event_type); ++ u16 flags = be16_to_cpu(e->flags); ++ ++ if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) { ++ WL_CONN("Processing link down\n"); ++ return true; ++ } ++ return false; ++} ++ ++static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv, ++ const struct brcmf_event_msg *e) ++{ ++ u32 event = be32_to_cpu(e->event_type); ++ u32 status = be32_to_cpu(e->status); ++ ++ if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) { ++ WL_CONN("Processing Link %s & no network found\n", ++ be16_to_cpu(e->flags) & BRCMF_EVENT_MSG_LINK ? ++ "up" : "down"); ++ return true; ++ } ++ ++ if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) { ++ WL_CONN("Processing connecting & no network found\n"); ++ return true; ++ } ++ ++ return false; ++} ++ ++static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); ++ ++ kfree(conn_info->req_ie); ++ conn_info->req_ie = NULL; ++ conn_info->req_ie_len = 0; ++ kfree(conn_info->resp_ie); ++ conn_info->resp_ie = NULL; ++ conn_info->resp_ie_len = 0; ++} ++ ++static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct net_device *ndev = cfg_to_ndev(cfg_priv); ++ struct brcmf_cfg80211_assoc_ielen_le *assoc_info; ++ struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); ++ u32 req_len; ++ u32 resp_len; ++ s32 err = 0; ++ ++ brcmf_clear_assoc_ies(cfg_priv); ++ ++ err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg_priv->extra_buf, ++ WL_ASSOC_INFO_MAX); ++ if (err) { ++ WL_ERR("could not get assoc info (%d)\n", err); ++ return err; ++ } ++ assoc_info = ++ (struct brcmf_cfg80211_assoc_ielen_le *)cfg_priv->extra_buf; ++ req_len = le32_to_cpu(assoc_info->req_len); ++ resp_len = le32_to_cpu(assoc_info->resp_len); ++ if (req_len) { ++ err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies", ++ cfg_priv->extra_buf, ++ WL_ASSOC_INFO_MAX); ++ if (err) { ++ WL_ERR("could not get assoc req (%d)\n", err); ++ return err; ++ } ++ conn_info->req_ie_len = req_len; ++ conn_info->req_ie = ++ kmemdup(cfg_priv->extra_buf, conn_info->req_ie_len, ++ GFP_KERNEL); ++ } else { ++ conn_info->req_ie_len = 0; ++ conn_info->req_ie = NULL; ++ } ++ if (resp_len) { ++ err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies", ++ cfg_priv->extra_buf, ++ WL_ASSOC_INFO_MAX); ++ if (err) { ++ WL_ERR("could not get assoc resp (%d)\n", err); ++ return err; ++ } ++ conn_info->resp_ie_len = resp_len; ++ conn_info->resp_ie = ++ kmemdup(cfg_priv->extra_buf, conn_info->resp_ie_len, ++ GFP_KERNEL); ++ } else { ++ conn_info->resp_ie_len = 0; ++ conn_info->resp_ie = NULL; ++ } ++ WL_CONN("req len (%d) resp len (%d)\n", ++ conn_info->req_ie_len, conn_info->resp_ie_len); ++ ++ return err; ++} ++ ++static s32 ++brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv, ++ struct net_device *ndev, ++ const struct brcmf_event_msg *e) ++{ ++ struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); ++ struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); ++ struct brcmf_channel_info_le channel_le; ++ struct ieee80211_channel *notify_channel; ++ struct ieee80211_supported_band *band; ++ u32 freq; ++ s32 err = 0; ++ u32 target_channel; ++ ++ WL_TRACE("Enter\n"); ++ ++ brcmf_get_assoc_ies(cfg_priv); ++ brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID); ++ brcmf_update_bss_info(cfg_priv); ++ ++ brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le, ++ sizeof(channel_le)); ++ ++ target_channel = le32_to_cpu(channel_le.target_channel); ++ WL_CONN("Roamed to channel %d\n", target_channel); ++ ++ if (target_channel <= CH_MAX_2G_CHANNEL) ++ band = wiphy->bands[IEEE80211_BAND_2GHZ]; ++ else ++ band = wiphy->bands[IEEE80211_BAND_5GHZ]; ++ ++ freq = ieee80211_channel_to_frequency(target_channel, band->band); ++ notify_channel = ieee80211_get_channel(wiphy, freq); ++ ++ cfg80211_roamed(ndev, notify_channel, ++ (u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID), ++ conn_info->req_ie, conn_info->req_ie_len, ++ conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); ++ WL_CONN("Report roaming result\n"); ++ ++ set_bit(WL_STATUS_CONNECTED, &cfg_priv->status); ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv, ++ struct net_device *ndev, const struct brcmf_event_msg *e, ++ bool completed) ++{ ++ struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ ++ if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) { ++ if (completed) { ++ brcmf_get_assoc_ies(cfg_priv); ++ brcmf_update_prof(cfg_priv, NULL, &e->addr, ++ WL_PROF_BSSID); ++ brcmf_update_bss_info(cfg_priv); ++ } ++ cfg80211_connect_result(ndev, ++ (u8 *)brcmf_read_prof(cfg_priv, ++ WL_PROF_BSSID), ++ conn_info->req_ie, ++ conn_info->req_ie_len, ++ conn_info->resp_ie, ++ conn_info->resp_ie_len, ++ completed ? WLAN_STATUS_SUCCESS : ++ WLAN_STATUS_AUTH_TIMEOUT, ++ GFP_KERNEL); ++ if (completed) ++ set_bit(WL_STATUS_CONNECTED, &cfg_priv->status); ++ WL_CONN("Report connect result - connection %s\n", ++ completed ? "succeeded" : "failed"); ++ } ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv, ++ struct net_device *ndev, ++ const struct brcmf_event_msg *e, void *data) ++{ ++ s32 err = 0; ++ ++ if (brcmf_is_linkup(cfg_priv, e)) { ++ WL_CONN("Linkup\n"); ++ if (brcmf_is_ibssmode(cfg_priv)) { ++ brcmf_update_prof(cfg_priv, NULL, (void *)e->addr, ++ WL_PROF_BSSID); ++ wl_inform_ibss(cfg_priv, ndev, e->addr); ++ cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL); ++ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); ++ set_bit(WL_STATUS_CONNECTED, &cfg_priv->status); ++ } else ++ brcmf_bss_connect_done(cfg_priv, ndev, e, true); ++ } else if (brcmf_is_linkdown(cfg_priv, e)) { ++ WL_CONN("Linkdown\n"); ++ if (brcmf_is_ibssmode(cfg_priv)) { ++ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); ++ if (test_and_clear_bit(WL_STATUS_CONNECTED, ++ &cfg_priv->status)) ++ brcmf_link_down(cfg_priv); ++ } else { ++ brcmf_bss_connect_done(cfg_priv, ndev, e, false); ++ if (test_and_clear_bit(WL_STATUS_CONNECTED, ++ &cfg_priv->status)) { ++ cfg80211_disconnected(ndev, 0, NULL, 0, ++ GFP_KERNEL); ++ brcmf_link_down(cfg_priv); ++ } ++ } ++ brcmf_init_prof(cfg_priv->profile); ++ } else if (brcmf_is_nonetwork(cfg_priv, e)) { ++ if (brcmf_is_ibssmode(cfg_priv)) ++ clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); ++ else ++ brcmf_bss_connect_done(cfg_priv, ndev, e, false); ++ } ++ ++ return err; ++} ++ ++static s32 ++brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv, ++ struct net_device *ndev, ++ const struct brcmf_event_msg *e, void *data) ++{ ++ s32 err = 0; ++ u32 event = be32_to_cpu(e->event_type); ++ u32 status = be32_to_cpu(e->status); ++ ++ if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) { ++ if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) ++ brcmf_bss_roaming_done(cfg_priv, ndev, e); ++ else ++ brcmf_bss_connect_done(cfg_priv, ndev, e, true); ++ } ++ ++ return err; ++} ++ ++static s32 ++brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv, ++ struct net_device *ndev, ++ const struct brcmf_event_msg *e, void *data) ++{ ++ u16 flags = be16_to_cpu(e->flags); ++ enum nl80211_key_type key_type; ++ ++ if (flags & BRCMF_EVENT_MSG_GROUP) ++ key_type = NL80211_KEYTYPE_GROUP; ++ else ++ key_type = NL80211_KEYTYPE_PAIRWISE; ++ ++ cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1, ++ NULL, GFP_KERNEL); ++ ++ return 0; ++} ++ ++static s32 ++brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv, ++ struct net_device *ndev, ++ const struct brcmf_event_msg *e, void *data) ++{ ++ struct brcmf_channel_info_le channel_inform_le; ++ struct brcmf_scan_results_le *bss_list_le; ++ u32 len = WL_SCAN_BUF_MAX; ++ s32 err = 0; ++ bool scan_abort = false; ++ u32 scan_channel; ++ ++ WL_TRACE("Enter\n"); ++ ++ if (cfg_priv->iscan_on && cfg_priv->iscan_kickstart) { ++ WL_TRACE("Exit\n"); ++ return brcmf_wakeup_iscan(cfg_to_iscan(cfg_priv)); ++ } ++ ++ if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { ++ WL_ERR("Scan complete while device not scanning\n"); ++ scan_abort = true; ++ err = -EINVAL; ++ goto scan_done_out; ++ } ++ ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_inform_le, ++ sizeof(channel_inform_le)); ++ if (err) { ++ WL_ERR("scan busy (%d)\n", err); ++ scan_abort = true; ++ goto scan_done_out; ++ } ++ scan_channel = le32_to_cpu(channel_inform_le.scan_channel); ++ if (scan_channel) ++ WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel); ++ cfg_priv->bss_list = cfg_priv->scan_results; ++ bss_list_le = (struct brcmf_scan_results_le *) cfg_priv->bss_list; ++ ++ memset(cfg_priv->scan_results, 0, len); ++ bss_list_le->buflen = cpu_to_le32(len); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS, ++ cfg_priv->scan_results, len); ++ if (err) { ++ WL_ERR("%s Scan_results error (%d)\n", ndev->name, err); ++ err = -EINVAL; ++ scan_abort = true; ++ goto scan_done_out; ++ } ++ cfg_priv->scan_results->buflen = le32_to_cpu(bss_list_le->buflen); ++ cfg_priv->scan_results->version = le32_to_cpu(bss_list_le->version); ++ cfg_priv->scan_results->count = le32_to_cpu(bss_list_le->count); ++ ++ err = brcmf_inform_bss(cfg_priv); ++ if (err) { ++ scan_abort = true; ++ goto scan_done_out; ++ } ++ ++scan_done_out: ++ if (cfg_priv->scan_request) { ++ WL_SCAN("calling cfg80211_scan_done\n"); ++ cfg80211_scan_done(cfg_priv->scan_request, scan_abort); ++ brcmf_set_mpc(ndev, 1); ++ cfg_priv->scan_request = NULL; ++ } ++ ++ WL_TRACE("Exit\n"); ++ ++ return err; ++} ++ ++static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf) ++{ ++ conf->mode = (u32)-1; ++ conf->frag_threshold = (u32)-1; ++ conf->rts_threshold = (u32)-1; ++ conf->retry_short = (u32)-1; ++ conf->retry_long = (u32)-1; ++ conf->tx_power = -1; ++} ++ ++static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el) ++{ ++ memset(el, 0, sizeof(*el)); ++ el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status; ++ el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status; ++ el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status; ++ el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status; ++ el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status; ++} ++ ++static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ kfree(cfg_priv->scan_results); ++ cfg_priv->scan_results = NULL; ++ kfree(cfg_priv->bss_info); ++ cfg_priv->bss_info = NULL; ++ kfree(cfg_priv->conf); ++ cfg_priv->conf = NULL; ++ kfree(cfg_priv->profile); ++ cfg_priv->profile = NULL; ++ kfree(cfg_priv->scan_req_int); ++ cfg_priv->scan_req_int = NULL; ++ kfree(cfg_priv->dcmd_buf); ++ cfg_priv->dcmd_buf = NULL; ++ kfree(cfg_priv->extra_buf); ++ cfg_priv->extra_buf = NULL; ++ kfree(cfg_priv->iscan); ++ cfg_priv->iscan = NULL; ++ kfree(cfg_priv->pmk_list); ++ cfg_priv->pmk_list = NULL; ++} ++ ++static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ cfg_priv->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL); ++ if (!cfg_priv->scan_results) ++ goto init_priv_mem_out; ++ cfg_priv->conf = kzalloc(sizeof(*cfg_priv->conf), GFP_KERNEL); ++ if (!cfg_priv->conf) ++ goto init_priv_mem_out; ++ cfg_priv->profile = kzalloc(sizeof(*cfg_priv->profile), GFP_KERNEL); ++ if (!cfg_priv->profile) ++ goto init_priv_mem_out; ++ cfg_priv->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); ++ if (!cfg_priv->bss_info) ++ goto init_priv_mem_out; ++ cfg_priv->scan_req_int = kzalloc(sizeof(*cfg_priv->scan_req_int), ++ GFP_KERNEL); ++ if (!cfg_priv->scan_req_int) ++ goto init_priv_mem_out; ++ cfg_priv->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL); ++ if (!cfg_priv->dcmd_buf) ++ goto init_priv_mem_out; ++ cfg_priv->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); ++ if (!cfg_priv->extra_buf) ++ goto init_priv_mem_out; ++ cfg_priv->iscan = kzalloc(sizeof(*cfg_priv->iscan), GFP_KERNEL); ++ if (!cfg_priv->iscan) ++ goto init_priv_mem_out; ++ cfg_priv->pmk_list = kzalloc(sizeof(*cfg_priv->pmk_list), GFP_KERNEL); ++ if (!cfg_priv->pmk_list) ++ goto init_priv_mem_out; ++ ++ return 0; ++ ++init_priv_mem_out: ++ brcmf_deinit_priv_mem(cfg_priv); ++ ++ return -ENOMEM; ++} ++ ++/* ++* retrieve first queued event from head ++*/ ++ ++static struct brcmf_cfg80211_event_q *brcmf_deq_event( ++ struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_event_q *e = NULL; ++ ++ spin_lock_irq(&cfg_priv->evt_q_lock); ++ if (!list_empty(&cfg_priv->evt_q_list)) { ++ e = list_first_entry(&cfg_priv->evt_q_list, ++ struct brcmf_cfg80211_event_q, evt_q_list); ++ list_del(&e->evt_q_list); ++ } ++ spin_unlock_irq(&cfg_priv->evt_q_lock); ++ ++ return e; ++} ++ ++/* ++** push event to tail of the queue ++*/ ++ ++static s32 ++brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event, ++ const struct brcmf_event_msg *msg) ++{ ++ struct brcmf_cfg80211_event_q *e; ++ s32 err = 0; ++ ++ e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_KERNEL); ++ if (!e) ++ return -ENOMEM; ++ ++ e->etype = event; ++ memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg)); ++ ++ spin_lock_irq(&cfg_priv->evt_q_lock); ++ list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list); ++ spin_unlock_irq(&cfg_priv->evt_q_lock); ++ ++ return err; ++} ++ ++static void brcmf_put_event(struct brcmf_cfg80211_event_q *e) ++{ ++ kfree(e); ++} ++ ++static void brcmf_cfg80211_event_handler(struct work_struct *work) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv = ++ container_of(work, struct brcmf_cfg80211_priv, ++ event_work); ++ struct brcmf_cfg80211_event_q *e; ++ ++ e = brcmf_deq_event(cfg_priv); ++ if (unlikely(!e)) { ++ WL_ERR("event queue empty...\n"); ++ return; ++ } ++ ++ do { ++ WL_INFO("event type (%d)\n", e->etype); ++ if (cfg_priv->el.handler[e->etype]) ++ cfg_priv->el.handler[e->etype](cfg_priv, ++ cfg_to_ndev(cfg_priv), ++ &e->emsg, e->edata); ++ else ++ WL_INFO("Unknown Event (%d): ignoring\n", e->etype); ++ brcmf_put_event(e); ++ } while ((e = brcmf_deq_event(cfg_priv))); ++ ++} ++ ++static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ spin_lock_init(&cfg_priv->evt_q_lock); ++ INIT_LIST_HEAD(&cfg_priv->evt_q_list); ++} ++ ++static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct brcmf_cfg80211_event_q *e; ++ ++ spin_lock_irq(&cfg_priv->evt_q_lock); ++ while (!list_empty(&cfg_priv->evt_q_list)) { ++ e = list_first_entry(&cfg_priv->evt_q_list, ++ struct brcmf_cfg80211_event_q, evt_q_list); ++ list_del(&e->evt_q_list); ++ kfree(e); ++ } ++ spin_unlock_irq(&cfg_priv->evt_q_lock); ++} ++ ++static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ s32 err = 0; ++ ++ cfg_priv->scan_request = NULL; ++ cfg_priv->pwr_save = true; ++ cfg_priv->iscan_on = true; /* iscan on & off switch. ++ we enable iscan per default */ ++ cfg_priv->roam_on = true; /* roam on & off switch. ++ we enable roam per default */ ++ ++ cfg_priv->iscan_kickstart = false; ++ cfg_priv->active_scan = true; /* we do active scan for ++ specific scan per default */ ++ cfg_priv->dongle_up = false; /* dongle is not up yet */ ++ brcmf_init_eq(cfg_priv); ++ err = brcmf_init_priv_mem(cfg_priv); ++ if (err) ++ return err; ++ INIT_WORK(&cfg_priv->event_work, brcmf_cfg80211_event_handler); ++ brcmf_init_eloop_handler(&cfg_priv->el); ++ mutex_init(&cfg_priv->usr_sync); ++ err = brcmf_init_iscan(cfg_priv); ++ if (err) ++ return err; ++ brcmf_init_conf(cfg_priv->conf); ++ brcmf_init_prof(cfg_priv->profile); ++ brcmf_link_down(cfg_priv); ++ ++ return err; ++} ++ ++static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ cancel_work_sync(&cfg_priv->event_work); ++ cfg_priv->dongle_up = false; /* dongle down */ ++ brcmf_flush_eq(cfg_priv); ++ brcmf_link_down(cfg_priv); ++ brcmf_term_iscan(cfg_priv); ++ brcmf_deinit_priv_mem(cfg_priv); ++} ++ ++struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, ++ struct device *busdev, ++ void *data) ++{ ++ struct wireless_dev *wdev; ++ struct brcmf_cfg80211_priv *cfg_priv; ++ struct brcmf_cfg80211_iface *ci; ++ struct brcmf_cfg80211_dev *cfg_dev; ++ s32 err = 0; ++ ++ if (!ndev) { ++ WL_ERR("ndev is invalid\n"); ++ return NULL; ++ } ++ cfg_dev = kzalloc(sizeof(struct brcmf_cfg80211_dev), GFP_KERNEL); ++ if (!cfg_dev) ++ return NULL; ++ ++ wdev = brcmf_alloc_wdev(sizeof(struct brcmf_cfg80211_iface), busdev); ++ if (IS_ERR(wdev)) { ++ kfree(cfg_dev); ++ return NULL; ++ } ++ ++ wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS); ++ cfg_priv = wdev_to_cfg(wdev); ++ cfg_priv->wdev = wdev; ++ cfg_priv->pub = data; ++ ci = (struct brcmf_cfg80211_iface *)&cfg_priv->ci; ++ ci->cfg_priv = cfg_priv; ++ ndev->ieee80211_ptr = wdev; ++ SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); ++ wdev->netdev = ndev; ++ err = wl_init_priv(cfg_priv); ++ if (err) { ++ WL_ERR("Failed to init iwm_priv (%d)\n", err); ++ goto cfg80211_attach_out; ++ } ++ brcmf_set_drvdata(cfg_dev, ci); ++ ++ return cfg_dev; ++ ++cfg80211_attach_out: ++ brcmf_free_wdev(cfg_priv); ++ kfree(cfg_dev); ++ return NULL; ++} ++ ++void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg_dev) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv; ++ ++ cfg_priv = brcmf_priv_get(cfg_dev); ++ ++ wl_deinit_priv(cfg_priv); ++ brcmf_free_wdev(cfg_priv); ++ brcmf_set_drvdata(cfg_dev, NULL); ++ kfree(cfg_dev); ++} ++ ++void ++brcmf_cfg80211_event(struct net_device *ndev, ++ const struct brcmf_event_msg *e, void *data) ++{ ++ u32 event_type = be32_to_cpu(e->event_type); ++ struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); ++ ++ if (!brcmf_enq_event(cfg_priv, event_type, e)) ++ schedule_work(&cfg_priv->event_work); ++} ++ ++static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype) ++{ ++ s32 infra = 0; ++ s32 err = 0; ++ ++ switch (iftype) { ++ case NL80211_IFTYPE_MONITOR: ++ case NL80211_IFTYPE_WDS: ++ WL_ERR("type (%d) : currently we do not support this mode\n", ++ iftype); ++ err = -EINVAL; ++ return err; ++ case NL80211_IFTYPE_ADHOC: ++ infra = 0; ++ break; ++ case NL80211_IFTYPE_STATION: ++ infra = 1; ++ break; ++ default: ++ err = -EINVAL; ++ WL_ERR("invalid type (%d)\n", iftype); ++ return err; ++ } ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra); ++ if (err) { ++ WL_ERR("WLC_SET_INFRA error (%d)\n", err); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static s32 brcmf_dongle_eventmsg(struct net_device *ndev) ++{ ++ /* Room for "event_msgs" + '\0' + bitvec */ ++ s8 iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; ++ s8 eventmask[BRCMF_EVENTING_MASK_LEN]; ++ s32 err = 0; ++ ++ WL_TRACE("Enter\n"); ++ ++ /* Setup event_msgs */ ++ brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, ++ iovbuf, sizeof(iovbuf)); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf)); ++ if (err) { ++ WL_ERR("Get event_msgs error (%d)\n", err); ++ goto dongle_eventmsg_out; ++ } ++ memcpy(eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN); ++ ++ setbit(eventmask, BRCMF_E_SET_SSID); ++ setbit(eventmask, BRCMF_E_ROAM); ++ setbit(eventmask, BRCMF_E_PRUNE); ++ setbit(eventmask, BRCMF_E_AUTH); ++ setbit(eventmask, BRCMF_E_REASSOC); ++ setbit(eventmask, BRCMF_E_REASSOC_IND); ++ setbit(eventmask, BRCMF_E_DEAUTH_IND); ++ setbit(eventmask, BRCMF_E_DISASSOC_IND); ++ setbit(eventmask, BRCMF_E_DISASSOC); ++ setbit(eventmask, BRCMF_E_JOIN); ++ setbit(eventmask, BRCMF_E_ASSOC_IND); ++ setbit(eventmask, BRCMF_E_PSK_SUP); ++ setbit(eventmask, BRCMF_E_LINK); ++ setbit(eventmask, BRCMF_E_NDIS_LINK); ++ setbit(eventmask, BRCMF_E_MIC_ERROR); ++ setbit(eventmask, BRCMF_E_PMKID_CACHE); ++ setbit(eventmask, BRCMF_E_TXFAIL); ++ setbit(eventmask, BRCMF_E_JOIN_START); ++ setbit(eventmask, BRCMF_E_SCAN_COMPLETE); ++ ++ brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, ++ iovbuf, sizeof(iovbuf)); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); ++ if (err) { ++ WL_ERR("Set event_msgs error (%d)\n", err); ++ goto dongle_eventmsg_out; ++ } ++ ++dongle_eventmsg_out: ++ WL_TRACE("Exit\n"); ++ return err; ++} ++ ++static s32 ++brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) ++{ ++ s8 iovbuf[32]; ++ s32 err = 0; ++ __le32 roamtrigger[2]; ++ __le32 roam_delta[2]; ++ __le32 bcn_to_le; ++ __le32 roamvar_le; ++ ++ /* ++ * Setup timeout if Beacons are lost and roam is ++ * off to report link down ++ */ ++ if (roamvar) { ++ bcn_to_le = cpu_to_le32(bcn_timeout); ++ brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_to_le, ++ sizeof(bcn_to_le), iovbuf, sizeof(iovbuf)); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, ++ iovbuf, sizeof(iovbuf)); ++ if (err) { ++ WL_ERR("bcn_timeout error (%d)\n", err); ++ goto dongle_rom_out; ++ } ++ } ++ ++ /* ++ * Enable/Disable built-in roaming to allow supplicant ++ * to take care of roaming ++ */ ++ WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On"); ++ roamvar_le = cpu_to_le32(roamvar); ++ brcmf_c_mkiovar("roam_off", (char *)&roamvar_le, ++ sizeof(roamvar_le), iovbuf, sizeof(iovbuf)); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); ++ if (err) { ++ WL_ERR("roam_off error (%d)\n", err); ++ goto dongle_rom_out; ++ } ++ ++ roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL); ++ roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_TRIGGER, ++ (void *)roamtrigger, sizeof(roamtrigger)); ++ if (err) { ++ WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err); ++ goto dongle_rom_out; ++ } ++ ++ roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA); ++ roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL); ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_DELTA, ++ (void *)roam_delta, sizeof(roam_delta)); ++ if (err) { ++ WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err); ++ goto dongle_rom_out; ++ } ++ ++dongle_rom_out: ++ return err; ++} ++ ++static s32 ++brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, ++ s32 scan_unassoc_time, s32 scan_passive_time) ++{ ++ s32 err = 0; ++ __le32 scan_assoc_tm_le = cpu_to_le32(scan_assoc_time); ++ __le32 scan_unassoc_tm_le = cpu_to_le32(scan_unassoc_time); ++ __le32 scan_passive_tm_le = cpu_to_le32(scan_passive_time); ++ ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME, ++ &scan_assoc_tm_le, sizeof(scan_assoc_tm_le)); ++ if (err) { ++ if (err == -EOPNOTSUPP) ++ WL_INFO("Scan assoc time is not supported\n"); ++ else ++ WL_ERR("Scan assoc time error (%d)\n", err); ++ goto dongle_scantime_out; ++ } ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME, ++ &scan_unassoc_tm_le, sizeof(scan_unassoc_tm_le)); ++ if (err) { ++ if (err == -EOPNOTSUPP) ++ WL_INFO("Scan unassoc time is not supported\n"); ++ else ++ WL_ERR("Scan unassoc time error (%d)\n", err); ++ goto dongle_scantime_out; ++ } ++ ++ err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME, ++ &scan_passive_tm_le, sizeof(scan_passive_tm_le)); ++ if (err) { ++ if (err == -EOPNOTSUPP) ++ WL_INFO("Scan passive time is not supported\n"); ++ else ++ WL_ERR("Scan passive time error (%d)\n", err); ++ goto dongle_scantime_out; ++ } ++ ++dongle_scantime_out: ++ return err; ++} ++ ++static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct wiphy *wiphy; ++ s32 phy_list; ++ s8 phy; ++ s32 err = 0; ++ ++ err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST, ++ &phy_list, sizeof(phy_list)); ++ if (err) { ++ WL_ERR("error (%d)\n", err); ++ return err; ++ } ++ ++ phy = ((char *)&phy_list)[1]; ++ WL_INFO("%c phy\n", phy); ++ if (phy == 'n' || phy == 'a') { ++ wiphy = cfg_to_wiphy(cfg_priv); ++ wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n; ++ } ++ ++ return err; ++} ++ ++static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ return wl_update_wiphybands(cfg_priv); ++} ++ ++static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ struct net_device *ndev; ++ struct wireless_dev *wdev; ++ s32 power_mode; ++ s32 err = 0; ++ ++ if (cfg_priv->dongle_up) ++ return err; ++ ++ ndev = cfg_to_ndev(cfg_priv); ++ wdev = ndev->ieee80211_ptr; ++ ++ brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME, ++ WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME); ++ ++ err = brcmf_dongle_eventmsg(ndev); ++ if (err) ++ goto default_conf_out; ++ ++ power_mode = cfg_priv->pwr_save ? PM_FAST : PM_OFF; ++ err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode); ++ if (err) ++ goto default_conf_out; ++ WL_INFO("power save set to %s\n", ++ (power_mode ? "enabled" : "disabled")); ++ ++ err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1), ++ WL_BEACON_TIMEOUT); ++ if (err) ++ goto default_conf_out; ++ err = brcmf_dongle_mode(ndev, wdev->iftype); ++ if (err && err != -EINPROGRESS) ++ goto default_conf_out; ++ err = brcmf_dongle_probecap(cfg_priv); ++ if (err) ++ goto default_conf_out; ++ ++ /* -EINPROGRESS: Call commit handler */ ++ ++default_conf_out: ++ ++ cfg_priv->dongle_up = true; ++ ++ return err; ++ ++} ++ ++static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ char buf[10+IFNAMSIZ]; ++ struct dentry *fd; ++ s32 err = 0; ++ ++ sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name); ++ cfg_priv->debugfsdir = debugfs_create_dir(buf, ++ cfg_to_wiphy(cfg_priv)->debugfsdir); ++ ++ fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir, ++ (u16 *)&cfg_priv->profile->beacon_interval); ++ if (!fd) { ++ err = -ENOMEM; ++ goto err_out; ++ } ++ ++ fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir, ++ (u8 *)&cfg_priv->profile->dtim_period); ++ if (!fd) { ++ err = -ENOMEM; ++ goto err_out; ++ } ++ ++err_out: ++ return err; ++} ++ ++static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ debugfs_remove_recursive(cfg_priv->debugfsdir); ++ cfg_priv->debugfsdir = NULL; ++} ++ ++static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ s32 err = 0; ++ ++ set_bit(WL_STATUS_READY, &cfg_priv->status); ++ ++ brcmf_debugfs_add_netdev_params(cfg_priv); ++ ++ err = brcmf_config_dongle(cfg_priv); ++ if (err) ++ return err; ++ ++ brcmf_invoke_iscan(cfg_priv); ++ ++ return err; ++} ++ ++static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv) ++{ ++ /* ++ * While going down, if associated with AP disassociate ++ * from AP to save power ++ */ ++ if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) || ++ test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) && ++ test_bit(WL_STATUS_READY, &cfg_priv->status)) { ++ WL_INFO("Disassociating from AP"); ++ brcmf_link_down(cfg_priv); ++ ++ /* Make sure WPA_Supplicant receives all the event ++ generated due to DISASSOC call to the fw to keep ++ the state fw and WPA_Supplicant state consistent ++ */ ++ brcmf_delay(500); ++ } ++ ++ set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); ++ brcmf_term_iscan(cfg_priv); ++ if (cfg_priv->scan_request) { ++ cfg80211_scan_done(cfg_priv->scan_request, true); ++ /* May need to perform this to cover rmmod */ ++ /* wl_set_mpc(cfg_to_ndev(wl), 1); */ ++ cfg_priv->scan_request = NULL; ++ } ++ clear_bit(WL_STATUS_READY, &cfg_priv->status); ++ clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); ++ clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); ++ ++ brcmf_debugfs_remove_netdev(cfg_priv); ++ ++ return 0; ++} ++ ++s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv; ++ s32 err = 0; ++ ++ cfg_priv = brcmf_priv_get(cfg_dev); ++ mutex_lock(&cfg_priv->usr_sync); ++ err = __brcmf_cfg80211_up(cfg_priv); ++ mutex_unlock(&cfg_priv->usr_sync); ++ ++ return err; ++} ++ ++s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev) ++{ ++ struct brcmf_cfg80211_priv *cfg_priv; ++ s32 err = 0; ++ ++ cfg_priv = brcmf_priv_get(cfg_dev); ++ mutex_lock(&cfg_priv->usr_sync); ++ err = __brcmf_cfg80211_down(cfg_priv); ++ mutex_unlock(&cfg_priv->usr_sync); ++ ++ return err; ++} ++ ++static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv, ++ u8 t, u8 l, u8 *v) ++{ ++ struct brcmf_cfg80211_ie *ie = &cfg_priv->ie; ++ s32 err = 0; ++ ++ if (ie->offset + l + 2 > WL_TLV_INFO_MAX) { ++ WL_ERR("ei crosses buffer boundary\n"); ++ return -ENOSPC; ++ } ++ ie->buf[ie->offset] = t; ++ ie->buf[ie->offset + 1] = l; ++ memcpy(&ie->buf[ie->offset + 2], v, l); ++ ie->offset += l + 2; ++ ++ return err; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h.orig 2011-11-09 13:46:58.238800722 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h 2011-11-09 13:47:16.989566304 -0500 +@@ -0,0 +1,375 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _wl_cfg80211_h_ ++#define _wl_cfg80211_h_ ++ ++struct brcmf_cfg80211_conf; ++struct brcmf_cfg80211_iface; ++struct brcmf_cfg80211_priv; ++struct brcmf_cfg80211_security; ++struct brcmf_cfg80211_ibss; ++ ++#define WL_DBG_NONE 0 ++#define WL_DBG_CONN (1 << 5) ++#define WL_DBG_SCAN (1 << 4) ++#define WL_DBG_TRACE (1 << 3) ++#define WL_DBG_INFO (1 << 1) ++#define WL_DBG_ERR (1 << 0) ++#define WL_DBG_MASK ((WL_DBG_INFO | WL_DBG_ERR | WL_DBG_TRACE) | \ ++ (WL_DBG_SCAN) | (WL_DBG_CONN)) ++ ++#define WL_ERR(fmt, args...) \ ++do { \ ++ if (brcmf_dbg_level & WL_DBG_ERR) { \ ++ if (net_ratelimit()) { \ ++ printk(KERN_ERR "ERROR @%s : " fmt, \ ++ __func__, ##args); \ ++ } \ ++ } \ ++} while (0) ++ ++#if (defined BCMDBG) ++#define WL_INFO(fmt, args...) \ ++do { \ ++ if (brcmf_dbg_level & WL_DBG_INFO) { \ ++ if (net_ratelimit()) { \ ++ printk(KERN_ERR "INFO @%s : " fmt, \ ++ __func__, ##args); \ ++ } \ ++ } \ ++} while (0) ++ ++#define WL_TRACE(fmt, args...) \ ++do { \ ++ if (brcmf_dbg_level & WL_DBG_TRACE) { \ ++ if (net_ratelimit()) { \ ++ printk(KERN_ERR "TRACE @%s : " fmt, \ ++ __func__, ##args); \ ++ } \ ++ } \ ++} while (0) ++ ++#define WL_SCAN(fmt, args...) \ ++do { \ ++ if (brcmf_dbg_level & WL_DBG_SCAN) { \ ++ if (net_ratelimit()) { \ ++ printk(KERN_ERR "SCAN @%s : " fmt, \ ++ __func__, ##args); \ ++ } \ ++ } \ ++} while (0) ++ ++#define WL_CONN(fmt, args...) \ ++do { \ ++ if (brcmf_dbg_level & WL_DBG_CONN) { \ ++ if (net_ratelimit()) { \ ++ printk(KERN_ERR "CONN @%s : " fmt, \ ++ __func__, ##args); \ ++ } \ ++ } \ ++} while (0) ++ ++#else /* (defined BCMDBG) */ ++#define WL_INFO(fmt, args...) ++#define WL_TRACE(fmt, args...) ++#define WL_SCAN(fmt, args...) ++#define WL_CONN(fmt, args...) ++#endif /* (defined BCMDBG) */ ++ ++#define WL_NUM_SCAN_MAX 1 ++#define WL_NUM_PMKIDS_MAX MAXPMKID /* will be used ++ * for 2.6.33 kernel ++ * or later ++ */ ++#define WL_SCAN_BUF_MAX (1024 * 8) ++#define WL_TLV_INFO_MAX 1024 ++#define WL_BSS_INFO_MAX 2048 ++#define WL_ASSOC_INFO_MAX 512 /* ++ * needs to grab assoc info from dongle to ++ * report it to cfg80211 through "connect" ++ * event ++ */ ++#define WL_DCMD_LEN_MAX 1024 ++#define WL_EXTRA_BUF_MAX 2048 ++#define WL_ISCAN_BUF_MAX 2048 /* ++ * the buf length can be BRCMF_DCMD_MAXLEN ++ * to reduce iteration ++ */ ++#define WL_ISCAN_TIMER_INTERVAL_MS 3000 ++#define WL_SCAN_ERSULTS_LAST (BRCMF_SCAN_RESULTS_NO_MEM+1) ++#define WL_AP_MAX 256 /* virtually unlimitted as long ++ * as kernel memory allows ++ */ ++ ++#define WL_ROAM_TRIGGER_LEVEL -75 ++#define WL_ROAM_DELTA 20 ++#define WL_BEACON_TIMEOUT 3 ++ ++#define WL_SCAN_CHANNEL_TIME 40 ++#define WL_SCAN_UNASSOC_TIME 40 ++#define WL_SCAN_PASSIVE_TIME 120 ++ ++/* dongle status */ ++enum wl_status { ++ WL_STATUS_READY, ++ WL_STATUS_SCANNING, ++ WL_STATUS_SCAN_ABORTING, ++ WL_STATUS_CONNECTING, ++ WL_STATUS_CONNECTED ++}; ++ ++/* wi-fi mode */ ++enum wl_mode { ++ WL_MODE_BSS, ++ WL_MODE_IBSS, ++ WL_MODE_AP ++}; ++ ++/* dongle profile list */ ++enum wl_prof_list { ++ WL_PROF_MODE, ++ WL_PROF_SSID, ++ WL_PROF_SEC, ++ WL_PROF_IBSS, ++ WL_PROF_BAND, ++ WL_PROF_BSSID, ++ WL_PROF_ACT, ++ WL_PROF_BEACONINT, ++ WL_PROF_DTIMPERIOD ++}; ++ ++/* dongle iscan state */ ++enum wl_iscan_state { ++ WL_ISCAN_STATE_IDLE, ++ WL_ISCAN_STATE_SCANING ++}; ++ ++/* dongle configuration */ ++struct brcmf_cfg80211_conf { ++ u32 mode; /* adhoc , infrastructure or ap */ ++ u32 frag_threshold; ++ u32 rts_threshold; ++ u32 retry_short; ++ u32 retry_long; ++ s32 tx_power; ++ struct ieee80211_channel channel; ++}; ++ ++/* cfg80211 main event loop */ ++struct brcmf_cfg80211_event_loop { ++ s32(*handler[BRCMF_E_LAST]) (struct brcmf_cfg80211_priv *cfg_priv, ++ struct net_device *ndev, ++ const struct brcmf_event_msg *e, ++ void *data); ++}; ++ ++/* representing interface of cfg80211 plane */ ++struct brcmf_cfg80211_iface { ++ struct brcmf_cfg80211_priv *cfg_priv; ++}; ++ ++struct brcmf_cfg80211_dev { ++ void *driver_data; /* to store cfg80211 object information */ ++}; ++ ++/* basic structure of scan request */ ++struct brcmf_cfg80211_scan_req { ++ struct brcmf_ssid_le ssid_le; ++}; ++ ++/* basic structure of information element */ ++struct brcmf_cfg80211_ie { ++ u16 offset; ++ u8 buf[WL_TLV_INFO_MAX]; ++}; ++ ++/* event queue for cfg80211 main event */ ++struct brcmf_cfg80211_event_q { ++ struct list_head evt_q_list; ++ u32 etype; ++ struct brcmf_event_msg emsg; ++ s8 edata[1]; ++}; ++ ++/* security information with currently associated ap */ ++struct brcmf_cfg80211_security { ++ u32 wpa_versions; ++ u32 auth_type; ++ u32 cipher_pairwise; ++ u32 cipher_group; ++ u32 wpa_auth; ++}; ++ ++/* ibss information for currently joined ibss network */ ++struct brcmf_cfg80211_ibss { ++ u8 beacon_interval; /* in millisecond */ ++ u8 atim; /* in millisecond */ ++ s8 join_only; ++ u8 band; ++ u8 channel; ++}; ++ ++/* dongle profile */ ++struct brcmf_cfg80211_profile { ++ u32 mode; ++ struct brcmf_ssid ssid; ++ u8 bssid[ETH_ALEN]; ++ u16 beacon_interval; ++ u8 dtim_period; ++ struct brcmf_cfg80211_security sec; ++ struct brcmf_cfg80211_ibss ibss; ++ s32 band; ++}; ++ ++/* dongle iscan event loop */ ++struct brcmf_cfg80211_iscan_eloop { ++ s32 (*handler[WL_SCAN_ERSULTS_LAST]) ++ (struct brcmf_cfg80211_priv *cfg_priv); ++}; ++ ++/* dongle iscan controller */ ++struct brcmf_cfg80211_iscan_ctrl { ++ struct net_device *ndev; ++ struct timer_list timer; ++ u32 timer_ms; ++ u32 timer_on; ++ s32 state; ++ struct work_struct work; ++ struct brcmf_cfg80211_iscan_eloop el; ++ void *data; ++ s8 dcmd_buf[BRCMF_DCMD_SMLEN]; ++ s8 scan_buf[WL_ISCAN_BUF_MAX]; ++}; ++ ++/* association inform */ ++struct brcmf_cfg80211_connect_info { ++ u8 *req_ie; ++ s32 req_ie_len; ++ u8 *resp_ie; ++ s32 resp_ie_len; ++}; ++ ++/* assoc ie length */ ++struct brcmf_cfg80211_assoc_ielen_le { ++ __le32 req_len; ++ __le32 resp_len; ++}; ++ ++/* wpa2 pmk list */ ++struct brcmf_cfg80211_pmk_list { ++ struct pmkid_list pmkids; ++ struct pmkid foo[MAXPMKID - 1]; ++}; ++ ++/* dongle private data of cfg80211 interface */ ++struct brcmf_cfg80211_priv { ++ struct wireless_dev *wdev; /* representing wl cfg80211 device */ ++ struct brcmf_cfg80211_conf *conf; /* dongle configuration */ ++ struct cfg80211_scan_request *scan_request; /* scan request ++ object */ ++ struct brcmf_cfg80211_event_loop el; /* main event loop */ ++ struct list_head evt_q_list; /* used for event queue */ ++ spinlock_t evt_q_lock; /* for event queue synchronization */ ++ struct mutex usr_sync; /* maily for dongle up/down synchronization */ ++ struct brcmf_scan_results *bss_list; /* bss_list holding scanned ++ ap information */ ++ struct brcmf_scan_results *scan_results; ++ struct brcmf_cfg80211_scan_req *scan_req_int; /* scan request object ++ for internal purpose */ ++ struct wl_cfg80211_bss_info *bss_info; /* bss information for ++ cfg80211 layer */ ++ struct brcmf_cfg80211_ie ie; /* information element object for ++ internal purpose */ ++ struct brcmf_cfg80211_profile *profile; /* holding dongle profile */ ++ struct brcmf_cfg80211_iscan_ctrl *iscan; /* iscan controller */ ++ struct brcmf_cfg80211_connect_info conn_info; /* association info */ ++ struct brcmf_cfg80211_pmk_list *pmk_list; /* wpa2 pmk list */ ++ struct work_struct event_work; /* event handler work struct */ ++ unsigned long status; /* current dongle status */ ++ void *pub; ++ u32 channel; /* current channel */ ++ bool iscan_on; /* iscan on/off switch */ ++ bool iscan_kickstart; /* indicate iscan already started */ ++ bool active_scan; /* current scan mode */ ++ bool ibss_starter; /* indicates this sta is ibss starter */ ++ bool link_up; /* link/connection up flag */ ++ bool pwr_save; /* indicate whether dongle to support ++ power save mode */ ++ bool dongle_up; /* indicate whether dongle up or not */ ++ bool roam_on; /* on/off switch for dongle self-roaming */ ++ bool scan_tried; /* indicates if first scan attempted */ ++ u8 *dcmd_buf; /* dcmd buffer */ ++ u8 *extra_buf; /* maily to grab assoc information */ ++ struct dentry *debugfsdir; ++ u8 ci[0] __aligned(NETDEV_ALIGN); ++}; ++ ++static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_priv *w) ++{ ++ return w->wdev->wiphy; ++} ++ ++static inline struct brcmf_cfg80211_priv *wiphy_to_cfg(struct wiphy *w) ++{ ++ return (struct brcmf_cfg80211_priv *)(wiphy_priv(w)); ++} ++ ++static inline struct brcmf_cfg80211_priv *wdev_to_cfg(struct wireless_dev *wd) ++{ ++ return (struct brcmf_cfg80211_priv *)(wdev_priv(wd)); ++} ++ ++static inline struct net_device *cfg_to_ndev(struct brcmf_cfg80211_priv *cfg) ++{ ++ return cfg->wdev->netdev; ++} ++ ++static inline struct brcmf_cfg80211_priv *ndev_to_cfg(struct net_device *ndev) ++{ ++ return wdev_to_cfg(ndev->ieee80211_ptr); ++} ++ ++#define iscan_to_cfg(i) ((struct brcmf_cfg80211_priv *)(i->data)) ++#define cfg_to_iscan(w) (w->iscan) ++ ++static inline struct ++brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_priv *cfg) ++{ ++ return &cfg->conn_info; ++} ++ ++static inline struct brcmf_bss_info *next_bss(struct brcmf_scan_results *list, ++ struct brcmf_bss_info *bss) ++{ ++ return bss = bss ? ++ (struct brcmf_bss_info *)((unsigned long)bss + ++ le32_to_cpu(bss->length)) : ++ list->bss_info; ++} ++ ++extern struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, ++ struct device *busdev, ++ void *data); ++extern void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg); ++ ++/* event handler from dongle */ ++extern void brcmf_cfg80211_event(struct net_device *ndev, ++ const struct brcmf_event_msg *e, void *data); ++extern s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev); ++extern s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev); ++ ++#endif /* _wl_cfg80211_h_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c.orig 2011-11-09 13:46:58.239800709 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c 2011-11-09 13:47:16.991566278 -0500 +@@ -0,0 +1,2079 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * File contents: support functions for PCI/PCIe ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include "types.h" ++#include "pub.h" ++#include "pmu.h" ++#include "srom.h" ++#include "nicpci.h" ++#include "aiutils.h" ++ ++/* slow_clk_ctl */ ++ /* slow clock source mask */ ++#define SCC_SS_MASK 0x00000007 ++ /* source of slow clock is LPO */ ++#define SCC_SS_LPO 0x00000000 ++ /* source of slow clock is crystal */ ++#define SCC_SS_XTAL 0x00000001 ++ /* source of slow clock is PCI */ ++#define SCC_SS_PCI 0x00000002 ++ /* LPOFreqSel, 1: 160Khz, 0: 32KHz */ ++#define SCC_LF 0x00000200 ++ /* LPOPowerDown, 1: LPO is disabled, 0: LPO is enabled */ ++#define SCC_LP 0x00000400 ++ /* ForceSlowClk, 1: sb/cores running on slow clock, 0: power logic control */ ++#define SCC_FS 0x00000800 ++ /* IgnorePllOffReq, 1/0: ++ * power logic ignores/honors PLL clock disable requests from core ++ */ ++#define SCC_IP 0x00001000 ++ /* XtalControlEn, 1/0: ++ * power logic does/doesn't disable crystal when appropriate ++ */ ++#define SCC_XC 0x00002000 ++ /* XtalPU (RO), 1/0: crystal running/disabled */ ++#define SCC_XP 0x00004000 ++ /* ClockDivider (SlowClk = 1/(4+divisor)) */ ++#define SCC_CD_MASK 0xffff0000 ++#define SCC_CD_SHIFT 16 ++ ++/* system_clk_ctl */ ++ /* ILPen: Enable Idle Low Power */ ++#define SYCC_IE 0x00000001 ++ /* ALPen: Enable Active Low Power */ ++#define SYCC_AE 0x00000002 ++ /* ForcePLLOn */ ++#define SYCC_FP 0x00000004 ++ /* Force ALP (or HT if ALPen is not set */ ++#define SYCC_AR 0x00000008 ++ /* Force HT */ ++#define SYCC_HR 0x00000010 ++ /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */ ++#define SYCC_CD_MASK 0xffff0000 ++#define SYCC_CD_SHIFT 16 ++ ++#define CST4329_SPROM_OTP_SEL_MASK 0x00000003 ++ /* OTP is powered up, use def. CIS, no SPROM */ ++#define CST4329_DEFCIS_SEL 0 ++ /* OTP is powered up, SPROM is present */ ++#define CST4329_SPROM_SEL 1 ++ /* OTP is powered up, no SPROM */ ++#define CST4329_OTP_SEL 2 ++ /* OTP is powered down, SPROM is present */ ++#define CST4329_OTP_PWRDN 3 ++ ++#define CST4329_SPI_SDIO_MODE_MASK 0x00000004 ++#define CST4329_SPI_SDIO_MODE_SHIFT 2 ++ ++/* 43224 chip-specific ChipControl register bits */ ++#define CCTRL43224_GPIO_TOGGLE 0x8000 ++ /* 12 mA drive strength */ ++#define CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 ++ /* 12 mA drive strength for later 43224s */ ++#define CCTRL_43224B0_12MA_LED_DRIVE 0xF0 ++ ++/* 43236 Chip specific ChipStatus register bits */ ++#define CST43236_SFLASH_MASK 0x00000040 ++#define CST43236_OTP_MASK 0x00000080 ++#define CST43236_HSIC_MASK 0x00000100 /* USB/HSIC */ ++#define CST43236_BP_CLK 0x00000200 /* 120/96Mbps */ ++#define CST43236_BOOT_MASK 0x00001800 ++#define CST43236_BOOT_SHIFT 11 ++#define CST43236_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ ++#define CST43236_BOOT_FROM_ROM 1 /* boot from ROM */ ++#define CST43236_BOOT_FROM_FLASH 2 /* boot from FLASH */ ++#define CST43236_BOOT_FROM_INVALID 3 ++ ++/* 4331 chip-specific ChipControl register bits */ ++ /* 0 disable */ ++#define CCTRL4331_BT_COEXIST (1<<0) ++ /* 0 SECI is disabled (JTAG functional) */ ++#define CCTRL4331_SECI (1<<1) ++ /* 0 disable */ ++#define CCTRL4331_EXT_LNA (1<<2) ++ /* sprom/gpio13-15 mux */ ++#define CCTRL4331_SPROM_GPIO13_15 (1<<3) ++ /* 0 ext pa disable, 1 ext pa enabled */ ++#define CCTRL4331_EXTPA_EN (1<<4) ++ /* set drive out GPIO_CLK on sprom_cs pin */ ++#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5) ++ /* use sprom_cs pin as PCIE mdio interface */ ++#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) ++ /* aband extpa will be at gpio2/5 and sprom_dout */ ++#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) ++ /* override core control on pipe_AuxClkEnable */ ++#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) ++ /* override core control on pipe_AuxPowerDown */ ++#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) ++ /* pcie_auxclkenable */ ++#define CCTRL4331_PCIE_AUXCLKEN (1<<10) ++ /* pcie_pipe_pllpowerdown */ ++#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) ++ /* enable bt_shd0 at gpio4 */ ++#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) ++ /* enable bt_shd1 at gpio5 */ ++#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) ++ ++/* 4331 Chip specific ChipStatus register bits */ ++ /* crystal frequency 20/40Mhz */ ++#define CST4331_XTAL_FREQ 0x00000001 ++#define CST4331_SPROM_PRESENT 0x00000002 ++#define CST4331_OTP_PRESENT 0x00000004 ++#define CST4331_LDO_RF 0x00000008 ++#define CST4331_LDO_PAR 0x00000010 ++ ++/* 4319 chip-specific ChipStatus register bits */ ++#define CST4319_SPI_CPULESSUSB 0x00000001 ++#define CST4319_SPI_CLK_POL 0x00000002 ++#define CST4319_SPI_CLK_PH 0x00000008 ++ /* gpio [7:6], SDIO CIS selection */ ++#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0 ++#define CST4319_SPROM_OTP_SEL_SHIFT 6 ++ /* use default CIS, OTP is powered up */ ++#define CST4319_DEFCIS_SEL 0x00000000 ++ /* use SPROM, OTP is powered up */ ++#define CST4319_SPROM_SEL 0x00000040 ++ /* use OTP, OTP is powered up */ ++#define CST4319_OTP_SEL 0x00000080 ++ /* use SPROM, OTP is powered down */ ++#define CST4319_OTP_PWRDN 0x000000c0 ++ /* gpio [8], sdio/usb mode */ ++#define CST4319_SDIO_USB_MODE 0x00000100 ++#define CST4319_REMAP_SEL_MASK 0x00000600 ++#define CST4319_ILPDIV_EN 0x00000800 ++#define CST4319_XTAL_PD_POL 0x00001000 ++#define CST4319_LPO_SEL 0x00002000 ++#define CST4319_RES_INIT_MODE 0x0000c000 ++ /* PALDO is configured with external PNP */ ++#define CST4319_PALDO_EXTPNP 0x00010000 ++#define CST4319_CBUCK_MODE_MASK 0x00060000 ++#define CST4319_CBUCK_MODE_BURST 0x00020000 ++#define CST4319_CBUCK_MODE_LPBURST 0x00060000 ++#define CST4319_RCAL_VALID 0x01000000 ++#define CST4319_RCAL_VALUE_MASK 0x3e000000 ++#define CST4319_RCAL_VALUE_SHIFT 25 ++ ++/* 4336 chip-specific ChipStatus register bits */ ++#define CST4336_SPI_MODE_MASK 0x00000001 ++#define CST4336_SPROM_PRESENT 0x00000002 ++#define CST4336_OTP_PRESENT 0x00000004 ++#define CST4336_ARMREMAP_0 0x00000008 ++#define CST4336_ILPDIV_EN_MASK 0x00000010 ++#define CST4336_ILPDIV_EN_SHIFT 4 ++#define CST4336_XTAL_PD_POL_MASK 0x00000020 ++#define CST4336_XTAL_PD_POL_SHIFT 5 ++#define CST4336_LPO_SEL_MASK 0x00000040 ++#define CST4336_LPO_SEL_SHIFT 6 ++#define CST4336_RES_INIT_MODE_MASK 0x00000180 ++#define CST4336_RES_INIT_MODE_SHIFT 7 ++#define CST4336_CBUCK_MODE_MASK 0x00000600 ++#define CST4336_CBUCK_MODE_SHIFT 9 ++ ++/* 4313 chip-specific ChipStatus register bits */ ++#define CST4313_SPROM_PRESENT 1 ++#define CST4313_OTP_PRESENT 2 ++#define CST4313_SPROM_OTP_SEL_MASK 0x00000002 ++#define CST4313_SPROM_OTP_SEL_SHIFT 0 ++ ++/* 4313 Chip specific ChipControl register bits */ ++ /* 12 mA drive strengh for later 4313 */ ++#define CCTRL_4313_12MA_LED_DRIVE 0x00000007 ++ ++/* Manufacturer Ids */ ++#define MFGID_ARM 0x43b ++#define MFGID_BRCM 0x4bf ++#define MFGID_MIPS 0x4a7 ++ ++/* Enumeration ROM registers */ ++#define ER_EROMENTRY 0x000 ++#define ER_REMAPCONTROL 0xe00 ++#define ER_REMAPSELECT 0xe04 ++#define ER_MASTERSELECT 0xe10 ++#define ER_ITCR 0xf00 ++#define ER_ITIP 0xf04 ++ ++/* Erom entries */ ++#define ER_TAG 0xe ++#define ER_TAG1 0x6 ++#define ER_VALID 1 ++#define ER_CI 0 ++#define ER_MP 2 ++#define ER_ADD 4 ++#define ER_END 0xe ++#define ER_BAD 0xffffffff ++ ++/* EROM CompIdentA */ ++#define CIA_MFG_MASK 0xfff00000 ++#define CIA_MFG_SHIFT 20 ++#define CIA_CID_MASK 0x000fff00 ++#define CIA_CID_SHIFT 8 ++#define CIA_CCL_MASK 0x000000f0 ++#define CIA_CCL_SHIFT 4 ++ ++/* EROM CompIdentB */ ++#define CIB_REV_MASK 0xff000000 ++#define CIB_REV_SHIFT 24 ++#define CIB_NSW_MASK 0x00f80000 ++#define CIB_NSW_SHIFT 19 ++#define CIB_NMW_MASK 0x0007c000 ++#define CIB_NMW_SHIFT 14 ++#define CIB_NSP_MASK 0x00003e00 ++#define CIB_NSP_SHIFT 9 ++#define CIB_NMP_MASK 0x000001f0 ++#define CIB_NMP_SHIFT 4 ++ ++/* EROM AddrDesc */ ++#define AD_ADDR_MASK 0xfffff000 ++#define AD_SP_MASK 0x00000f00 ++#define AD_SP_SHIFT 8 ++#define AD_ST_MASK 0x000000c0 ++#define AD_ST_SHIFT 6 ++#define AD_ST_SLAVE 0x00000000 ++#define AD_ST_BRIDGE 0x00000040 ++#define AD_ST_SWRAP 0x00000080 ++#define AD_ST_MWRAP 0x000000c0 ++#define AD_SZ_MASK 0x00000030 ++#define AD_SZ_SHIFT 4 ++#define AD_SZ_4K 0x00000000 ++#define AD_SZ_8K 0x00000010 ++#define AD_SZ_16K 0x00000020 ++#define AD_SZ_SZD 0x00000030 ++#define AD_AG32 0x00000008 ++#define AD_ADDR_ALIGN 0x00000fff ++#define AD_SZ_BASE 0x00001000 /* 4KB */ ++ ++/* EROM SizeDesc */ ++#define SD_SZ_MASK 0xfffff000 ++#define SD_SG32 0x00000008 ++#define SD_SZ_ALIGN 0x00000fff ++ ++/* PCI config space bit 4 for 4306c0 slow clock source */ ++#define PCI_CFG_GPIO_SCS 0x10 ++/* PCI config space GPIO 14 for Xtal power-up */ ++#define PCI_CFG_GPIO_XTAL 0x40 ++/* PCI config space GPIO 15 for PLL power-down */ ++#define PCI_CFG_GPIO_PLL 0x80 ++ ++/* power control defines */ ++#define PLL_DELAY 150 /* us pll on delay */ ++#define FREF_DELAY 200 /* us fref change delay */ ++#define XTAL_ON_DELAY 1000 /* us crystal power-on delay */ ++ ++/* resetctrl */ ++#define AIRC_RESET 1 ++ ++#define NOREV -1 /* Invalid rev */ ++ ++/* GPIO Based LED powersave defines */ ++#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */ ++#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */ ++ ++/* When Srom support present, fields in sromcontrol */ ++#define SRC_START 0x80000000 ++#define SRC_BUSY 0x80000000 ++#define SRC_OPCODE 0x60000000 ++#define SRC_OP_READ 0x00000000 ++#define SRC_OP_WRITE 0x20000000 ++#define SRC_OP_WRDIS 0x40000000 ++#define SRC_OP_WREN 0x60000000 ++#define SRC_OTPSEL 0x00000010 ++#define SRC_LOCK 0x00000008 ++#define SRC_SIZE_MASK 0x00000006 ++#define SRC_SIZE_1K 0x00000000 ++#define SRC_SIZE_4K 0x00000002 ++#define SRC_SIZE_16K 0x00000004 ++#define SRC_SIZE_SHIFT 1 ++#define SRC_PRESENT 0x00000001 ++ ++/* External PA enable mask */ ++#define GPIO_CTRL_EPA_EN_MASK 0x40 ++ ++#define DEFAULT_GPIOTIMERVAL \ ++ ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME) ++ ++#define BADIDX (SI_MAXCORES + 1) ++ ++/* Newer chips can access PCI/PCIE and CC core without requiring to change ++ * PCI BAR0 WIN ++ */ ++#define SI_FAST(si) (((si)->pub.buscoretype == PCIE_CORE_ID) || \ ++ (((si)->pub.buscoretype == PCI_CORE_ID) && \ ++ (si)->pub.buscorerev >= 13)) ++ ++#define CCREGS_FAST(si) (((char __iomem *)((si)->curmap) + \ ++ PCI_16KB0_CCREGS_OFFSET)) ++ ++#define IS_SIM(chippkg) \ ++ ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) ++ ++/* ++ * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts ++ * before after core switching to avoid invalid register accesss inside ISR. ++ */ ++#define INTR_OFF(si, intr_val) \ ++ if ((si)->intrsoff_fn && \ ++ (si)->coreid[(si)->curidx] == (si)->dev_coreid) \ ++ intr_val = (*(si)->intrsoff_fn)((si)->intr_arg) ++ ++#define INTR_RESTORE(si, intr_val) \ ++ if ((si)->intrsrestore_fn && \ ++ (si)->coreid[(si)->curidx] == (si)->dev_coreid) \ ++ (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val) ++ ++#define PCI(si) ((si)->pub.buscoretype == PCI_CORE_ID) ++#define PCIE(si) ((si)->pub.buscoretype == PCIE_CORE_ID) ++ ++#define PCI_FORCEHT(si) (PCIE(si) && (si->pub.chip == BCM4716_CHIP_ID)) ++ ++#ifdef BCMDBG ++#define SI_MSG(args) printk args ++#else ++#define SI_MSG(args) ++#endif /* BCMDBG */ ++ ++#define GOODCOREADDR(x, b) \ ++ (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ ++ IS_ALIGNED((x), SI_CORE_SIZE)) ++ ++#define PCIEREGS(si) ((__iomem char *)((si)->curmap) + \ ++ PCI_16KB0_PCIREGS_OFFSET) ++ ++struct aidmp { ++ u32 oobselina30; /* 0x000 */ ++ u32 oobselina74; /* 0x004 */ ++ u32 PAD[6]; ++ u32 oobselinb30; /* 0x020 */ ++ u32 oobselinb74; /* 0x024 */ ++ u32 PAD[6]; ++ u32 oobselinc30; /* 0x040 */ ++ u32 oobselinc74; /* 0x044 */ ++ u32 PAD[6]; ++ u32 oobselind30; /* 0x060 */ ++ u32 oobselind74; /* 0x064 */ ++ u32 PAD[38]; ++ u32 oobselouta30; /* 0x100 */ ++ u32 oobselouta74; /* 0x104 */ ++ u32 PAD[6]; ++ u32 oobseloutb30; /* 0x120 */ ++ u32 oobseloutb74; /* 0x124 */ ++ u32 PAD[6]; ++ u32 oobseloutc30; /* 0x140 */ ++ u32 oobseloutc74; /* 0x144 */ ++ u32 PAD[6]; ++ u32 oobseloutd30; /* 0x160 */ ++ u32 oobseloutd74; /* 0x164 */ ++ u32 PAD[38]; ++ u32 oobsynca; /* 0x200 */ ++ u32 oobseloutaen; /* 0x204 */ ++ u32 PAD[6]; ++ u32 oobsyncb; /* 0x220 */ ++ u32 oobseloutben; /* 0x224 */ ++ u32 PAD[6]; ++ u32 oobsyncc; /* 0x240 */ ++ u32 oobseloutcen; /* 0x244 */ ++ u32 PAD[6]; ++ u32 oobsyncd; /* 0x260 */ ++ u32 oobseloutden; /* 0x264 */ ++ u32 PAD[38]; ++ u32 oobaextwidth; /* 0x300 */ ++ u32 oobainwidth; /* 0x304 */ ++ u32 oobaoutwidth; /* 0x308 */ ++ u32 PAD[5]; ++ u32 oobbextwidth; /* 0x320 */ ++ u32 oobbinwidth; /* 0x324 */ ++ u32 oobboutwidth; /* 0x328 */ ++ u32 PAD[5]; ++ u32 oobcextwidth; /* 0x340 */ ++ u32 oobcinwidth; /* 0x344 */ ++ u32 oobcoutwidth; /* 0x348 */ ++ u32 PAD[5]; ++ u32 oobdextwidth; /* 0x360 */ ++ u32 oobdinwidth; /* 0x364 */ ++ u32 oobdoutwidth; /* 0x368 */ ++ u32 PAD[37]; ++ u32 ioctrlset; /* 0x400 */ ++ u32 ioctrlclear; /* 0x404 */ ++ u32 ioctrl; /* 0x408 */ ++ u32 PAD[61]; ++ u32 iostatus; /* 0x500 */ ++ u32 PAD[127]; ++ u32 ioctrlwidth; /* 0x700 */ ++ u32 iostatuswidth; /* 0x704 */ ++ u32 PAD[62]; ++ u32 resetctrl; /* 0x800 */ ++ u32 resetstatus; /* 0x804 */ ++ u32 resetreadid; /* 0x808 */ ++ u32 resetwriteid; /* 0x80c */ ++ u32 PAD[60]; ++ u32 errlogctrl; /* 0x900 */ ++ u32 errlogdone; /* 0x904 */ ++ u32 errlogstatus; /* 0x908 */ ++ u32 errlogaddrlo; /* 0x90c */ ++ u32 errlogaddrhi; /* 0x910 */ ++ u32 errlogid; /* 0x914 */ ++ u32 errloguser; /* 0x918 */ ++ u32 errlogflags; /* 0x91c */ ++ u32 PAD[56]; ++ u32 intstatus; /* 0xa00 */ ++ u32 PAD[127]; ++ u32 config; /* 0xe00 */ ++ u32 PAD[63]; ++ u32 itcr; /* 0xf00 */ ++ u32 PAD[3]; ++ u32 itipooba; /* 0xf10 */ ++ u32 itipoobb; /* 0xf14 */ ++ u32 itipoobc; /* 0xf18 */ ++ u32 itipoobd; /* 0xf1c */ ++ u32 PAD[4]; ++ u32 itipoobaout; /* 0xf30 */ ++ u32 itipoobbout; /* 0xf34 */ ++ u32 itipoobcout; /* 0xf38 */ ++ u32 itipoobdout; /* 0xf3c */ ++ u32 PAD[4]; ++ u32 itopooba; /* 0xf50 */ ++ u32 itopoobb; /* 0xf54 */ ++ u32 itopoobc; /* 0xf58 */ ++ u32 itopoobd; /* 0xf5c */ ++ u32 PAD[4]; ++ u32 itopoobain; /* 0xf70 */ ++ u32 itopoobbin; /* 0xf74 */ ++ u32 itopoobcin; /* 0xf78 */ ++ u32 itopoobdin; /* 0xf7c */ ++ u32 PAD[4]; ++ u32 itopreset; /* 0xf90 */ ++ u32 PAD[15]; ++ u32 peripherialid4; /* 0xfd0 */ ++ u32 peripherialid5; /* 0xfd4 */ ++ u32 peripherialid6; /* 0xfd8 */ ++ u32 peripherialid7; /* 0xfdc */ ++ u32 peripherialid0; /* 0xfe0 */ ++ u32 peripherialid1; /* 0xfe4 */ ++ u32 peripherialid2; /* 0xfe8 */ ++ u32 peripherialid3; /* 0xfec */ ++ u32 componentid0; /* 0xff0 */ ++ u32 componentid1; /* 0xff4 */ ++ u32 componentid2; /* 0xff8 */ ++ u32 componentid3; /* 0xffc */ ++}; ++ ++/* EROM parsing */ ++ ++static u32 ++get_erom_ent(struct si_pub *sih, u32 __iomem **eromptr, u32 mask, u32 match) ++{ ++ u32 ent; ++ uint inv = 0, nom = 0; ++ ++ while (true) { ++ ent = R_REG(*eromptr); ++ (*eromptr)++; ++ ++ if (mask == 0) ++ break; ++ ++ if ((ent & ER_VALID) == 0) { ++ inv++; ++ continue; ++ } ++ ++ if (ent == (ER_END | ER_VALID)) ++ break; ++ ++ if ((ent & mask) == match) ++ break; ++ ++ nom++; ++ } ++ ++ return ent; ++} ++ ++static u32 ++get_asd(struct si_pub *sih, u32 __iomem **eromptr, uint sp, uint ad, uint st, ++ u32 *addrl, u32 *addrh, u32 *sizel, u32 *sizeh) ++{ ++ u32 asd, sz, szd; ++ ++ asd = get_erom_ent(sih, eromptr, ER_VALID, ER_VALID); ++ if (((asd & ER_TAG1) != ER_ADD) || ++ (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) || ++ ((asd & AD_ST_MASK) != st)) { ++ /* This is not what we want, "push" it back */ ++ (*eromptr)--; ++ return 0; ++ } ++ *addrl = asd & AD_ADDR_MASK; ++ if (asd & AD_AG32) ++ *addrh = get_erom_ent(sih, eromptr, 0, 0); ++ else ++ *addrh = 0; ++ *sizeh = 0; ++ sz = asd & AD_SZ_MASK; ++ if (sz == AD_SZ_SZD) { ++ szd = get_erom_ent(sih, eromptr, 0, 0); ++ *sizel = szd & SD_SZ_MASK; ++ if (szd & SD_SG32) ++ *sizeh = get_erom_ent(sih, eromptr, 0, 0); ++ } else ++ *sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT); ++ ++ return asd; ++} ++ ++static void ai_hwfixup(struct si_info *sii) ++{ ++} ++ ++/* parse the enumeration rom to identify all cores */ ++static void ai_scan(struct si_pub *sih, struct chipcregs __iomem *cc) ++{ ++ struct si_info *sii = (struct si_info *)sih; ++ ++ u32 erombase; ++ u32 __iomem *eromptr, *eromlim; ++ void __iomem *regs = cc; ++ ++ erombase = R_REG(&cc->eromptr); ++ ++ /* Set wrappers address */ ++ sii->curwrap = (void *)((unsigned long)cc + SI_CORE_SIZE); ++ ++ /* Now point the window at the erom */ ++ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, erombase); ++ eromptr = regs; ++ eromlim = eromptr + (ER_REMAPCONTROL / sizeof(u32)); ++ ++ while (eromptr < eromlim) { ++ u32 cia, cib, cid, mfg, crev, nmw, nsw, nmp, nsp; ++ u32 mpd, asd, addrl, addrh, sizel, sizeh; ++ u32 __iomem *base; ++ uint i, j, idx; ++ bool br; ++ ++ br = false; ++ ++ /* Grok a component */ ++ cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI); ++ if (cia == (ER_END | ER_VALID)) { ++ /* Found END of erom */ ++ ai_hwfixup(sii); ++ return; ++ } ++ base = eromptr - 1; ++ cib = get_erom_ent(sih, &eromptr, 0, 0); ++ ++ if ((cib & ER_TAG) != ER_CI) { ++ /* CIA not followed by CIB */ ++ goto error; ++ } ++ ++ cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT; ++ mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT; ++ crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT; ++ nmw = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT; ++ nsw = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT; ++ nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT; ++ nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT; ++ ++ if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0)) ++ continue; ++ if ((nmw + nsw == 0)) { ++ /* A component which is not a core */ ++ if (cid == OOB_ROUTER_CORE_ID) { ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, ++ &addrl, &addrh, &sizel, &sizeh); ++ if (asd != 0) ++ sii->oob_router = addrl; ++ } ++ continue; ++ } ++ ++ idx = sii->numcores; ++/* sii->eromptr[idx] = base; */ ++ sii->cia[idx] = cia; ++ sii->cib[idx] = cib; ++ sii->coreid[idx] = cid; ++ ++ for (i = 0; i < nmp; i++) { ++ mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); ++ if ((mpd & ER_TAG) != ER_MP) { ++ /* Not enough MP entries for component */ ++ goto error; ++ } ++ } ++ ++ /* First Slave Address Descriptor should be port 0: ++ * the main register space for the core ++ */ ++ asd = ++ get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd == 0) { ++ /* Try again to see if it is a bridge */ ++ asd = ++ get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, ++ &addrh, &sizel, &sizeh); ++ if (asd != 0) ++ br = true; ++ else if ((addrh != 0) || (sizeh != 0) ++ || (sizel != SI_CORE_SIZE)) { ++ /* First Slave ASD for core malformed */ ++ goto error; ++ } ++ } ++ sii->coresba[idx] = addrl; ++ sii->coresba_size[idx] = sizel; ++ /* Get any more ASDs in port 0 */ ++ j = 1; ++ do { ++ asd = ++ get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, ++ &addrh, &sizel, &sizeh); ++ if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE)) { ++ sii->coresba2[idx] = addrl; ++ sii->coresba2_size[idx] = sizel; ++ } ++ j++; ++ } while (asd != 0); ++ ++ /* Go through the ASDs for other slave ports */ ++ for (i = 1; i < nsp; i++) { ++ j = 0; ++ do { ++ asd = ++ get_asd(sih, &eromptr, i, j++, AD_ST_SLAVE, ++ &addrl, &addrh, &sizel, &sizeh); ++ } while (asd != 0); ++ if (j == 0) { ++ /* SP has no address descriptors */ ++ goto error; ++ } ++ } ++ ++ /* Now get master wrappers */ ++ for (i = 0; i < nmw; i++) { ++ asd = ++ get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl, ++ &addrh, &sizel, &sizeh); ++ if (asd == 0) { ++ /* Missing descriptor for MW */ ++ goto error; ++ } ++ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { ++ /* Master wrapper %d is not 4KB */ ++ goto error; ++ } ++ if (i == 0) ++ sii->wrapba[idx] = addrl; ++ } ++ ++ /* And finally slave wrappers */ ++ for (i = 0; i < nsw; i++) { ++ uint fwp = (nsp == 1) ? 0 : 1; ++ asd = ++ get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP, ++ &addrl, &addrh, &sizel, &sizeh); ++ if (asd == 0) { ++ /* Missing descriptor for SW */ ++ goto error; ++ } ++ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { ++ /* Slave wrapper is not 4KB */ ++ goto error; ++ } ++ if ((nmw == 0) && (i == 0)) ++ sii->wrapba[idx] = addrl; ++ } ++ ++ /* Don't record bridges */ ++ if (br) ++ continue; ++ ++ /* Done with core */ ++ sii->numcores++; ++ } ++ ++ error: ++ /* Reached end of erom without finding END */ ++ sii->numcores = 0; ++ return; ++} ++ ++/* ++ * This function changes the logical "focus" to the indicated core. ++ * Return the current core's virtual address. Since each core starts with the ++ * same set of registers (BIST, clock control, etc), the returned address ++ * contains the first register of this 'common' register block (not to be ++ * confused with 'common core'). ++ */ ++void __iomem *ai_setcoreidx(struct si_pub *sih, uint coreidx) ++{ ++ struct si_info *sii = (struct si_info *)sih; ++ u32 addr = sii->coresba[coreidx]; ++ u32 wrap = sii->wrapba[coreidx]; ++ ++ if (coreidx >= sii->numcores) ++ return NULL; ++ ++ /* point bar0 window */ ++ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, addr); ++ /* point bar0 2nd 4KB window */ ++ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN2, wrap); ++ sii->curidx = coreidx; ++ ++ return sii->curmap; ++} ++ ++/* Return the number of address spaces in current core */ ++int ai_numaddrspaces(struct si_pub *sih) ++{ ++ return 2; ++} ++ ++/* Return the address of the nth address space in the current core */ ++u32 ai_addrspace(struct si_pub *sih, uint asidx) ++{ ++ struct si_info *sii; ++ uint cidx; ++ ++ sii = (struct si_info *)sih; ++ cidx = sii->curidx; ++ ++ if (asidx == 0) ++ return sii->coresba[cidx]; ++ else if (asidx == 1) ++ return sii->coresba2[cidx]; ++ else { ++ /* Need to parse the erom again to find addr space */ ++ return 0; ++ } ++} ++ ++/* Return the size of the nth address space in the current core */ ++u32 ai_addrspacesize(struct si_pub *sih, uint asidx) ++{ ++ struct si_info *sii; ++ uint cidx; ++ ++ sii = (struct si_info *)sih; ++ cidx = sii->curidx; ++ ++ if (asidx == 0) ++ return sii->coresba_size[cidx]; ++ else if (asidx == 1) ++ return sii->coresba2_size[cidx]; ++ else { ++ /* Need to parse the erom again to find addr */ ++ return 0; ++ } ++} ++ ++uint ai_flag(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ struct aidmp *ai; ++ ++ sii = (struct si_info *)sih; ++ ai = sii->curwrap; ++ ++ return R_REG(&ai->oobselouta30) & 0x1f; ++} ++ ++void ai_setint(struct si_pub *sih, int siflag) ++{ ++} ++ ++uint ai_corevendor(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ u32 cia; ++ ++ sii = (struct si_info *)sih; ++ cia = sii->cia[sii->curidx]; ++ return (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT; ++} ++ ++uint ai_corerev(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ u32 cib; ++ ++ sii = (struct si_info *)sih; ++ cib = sii->cib[sii->curidx]; ++ return (cib & CIB_REV_MASK) >> CIB_REV_SHIFT; ++} ++ ++bool ai_iscoreup(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ struct aidmp *ai; ++ ++ sii = (struct si_info *)sih; ++ ai = sii->curwrap; ++ ++ return (((R_REG(&ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) == ++ SICF_CLOCK_EN) ++ && ((R_REG(&ai->resetctrl) & AIRC_RESET) == 0)); ++} ++ ++void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val) ++{ ++ struct si_info *sii; ++ struct aidmp *ai; ++ u32 w; ++ ++ sii = (struct si_info *)sih; ++ ++ ai = sii->curwrap; ++ ++ if (mask || val) { ++ w = ((R_REG(&ai->ioctrl) & ~mask) | val); ++ W_REG(&ai->ioctrl, w); ++ } ++} ++ ++u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val) ++{ ++ struct si_info *sii; ++ struct aidmp *ai; ++ u32 w; ++ ++ sii = (struct si_info *)sih; ++ ai = sii->curwrap; ++ ++ if (mask || val) { ++ w = ((R_REG(&ai->ioctrl) & ~mask) | val); ++ W_REG(&ai->ioctrl, w); ++ } ++ ++ return R_REG(&ai->ioctrl); ++} ++ ++/* return true if PCIE capability exists in the pci config space */ ++static bool ai_ispcie(struct si_info *sii) ++{ ++ u8 cap_ptr; ++ ++ cap_ptr = ++ pcicore_find_pci_capability(sii->pbus, PCI_CAP_ID_EXP, NULL, ++ NULL); ++ if (!cap_ptr) ++ return false; ++ ++ return true; ++} ++ ++static bool ai_buscore_prep(struct si_info *sii) ++{ ++ /* kludge to enable the clock on the 4306 which lacks a slowclock */ ++ if (!ai_ispcie(sii)) ++ ai_clkctl_xtal(&sii->pub, XTAL | PLL, ON); ++ return true; ++} ++ ++u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val) ++{ ++ struct si_info *sii; ++ struct aidmp *ai; ++ u32 w; ++ ++ sii = (struct si_info *)sih; ++ ai = sii->curwrap; ++ ++ if (mask || val) { ++ w = ((R_REG(&ai->iostatus) & ~mask) | val); ++ W_REG(&ai->iostatus, w); ++ } ++ ++ return R_REG(&ai->iostatus); ++} ++ ++static bool ++ai_buscore_setup(struct si_info *sii, u32 savewin, uint *origidx) ++{ ++ bool pci, pcie; ++ uint i; ++ uint pciidx, pcieidx, pcirev, pcierev; ++ struct chipcregs __iomem *cc; ++ ++ cc = ai_setcoreidx(&sii->pub, SI_CC_IDX); ++ ++ /* get chipcommon rev */ ++ sii->pub.ccrev = (int)ai_corerev(&sii->pub); ++ ++ /* get chipcommon chipstatus */ ++ if (sii->pub.ccrev >= 11) ++ sii->pub.chipst = R_REG(&cc->chipstatus); ++ ++ /* get chipcommon capabilites */ ++ sii->pub.cccaps = R_REG(&cc->capabilities); ++ /* get chipcommon extended capabilities */ ++ ++ if (sii->pub.ccrev >= 35) ++ sii->pub.cccaps_ext = R_REG(&cc->capabilities_ext); ++ ++ /* get pmu rev and caps */ ++ if (sii->pub.cccaps & CC_CAP_PMU) { ++ sii->pub.pmucaps = R_REG(&cc->pmucapabilities); ++ sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; ++ } ++ ++ /* figure out bus/orignal core idx */ ++ sii->pub.buscoretype = NODEV_CORE_ID; ++ sii->pub.buscorerev = NOREV; ++ sii->pub.buscoreidx = BADIDX; ++ ++ pci = pcie = false; ++ pcirev = pcierev = NOREV; ++ pciidx = pcieidx = BADIDX; ++ ++ for (i = 0; i < sii->numcores; i++) { ++ uint cid, crev; ++ ++ ai_setcoreidx(&sii->pub, i); ++ cid = ai_coreid(&sii->pub); ++ crev = ai_corerev(&sii->pub); ++ ++ if (cid == PCI_CORE_ID) { ++ pciidx = i; ++ pcirev = crev; ++ pci = true; ++ } else if (cid == PCIE_CORE_ID) { ++ pcieidx = i; ++ pcierev = crev; ++ pcie = true; ++ } ++ ++ /* find the core idx before entering this func. */ ++ if ((savewin && (savewin == sii->coresba[i])) || ++ (cc == sii->regs[i])) ++ *origidx = i; ++ } ++ ++ if (pci && pcie) { ++ if (ai_ispcie(sii)) ++ pci = false; ++ else ++ pcie = false; ++ } ++ if (pci) { ++ sii->pub.buscoretype = PCI_CORE_ID; ++ sii->pub.buscorerev = pcirev; ++ sii->pub.buscoreidx = pciidx; ++ } else if (pcie) { ++ sii->pub.buscoretype = PCIE_CORE_ID; ++ sii->pub.buscorerev = pcierev; ++ sii->pub.buscoreidx = pcieidx; ++ } ++ ++ /* fixup necessary chip/core configurations */ ++ if (SI_FAST(sii)) { ++ if (!sii->pch) { ++ sii->pch = pcicore_init(&sii->pub, sii->pbus, ++ (__iomem void *)PCIEREGS(sii)); ++ if (sii->pch == NULL) ++ return false; ++ } ++ } ++ if (ai_pci_fixcfg(&sii->pub)) { ++ /* si_doattach: si_pci_fixcfg failed */ ++ return false; ++ } ++ ++ /* return to the original core */ ++ ai_setcoreidx(&sii->pub, *origidx); ++ ++ return true; ++} ++ ++/* ++ * get boardtype and boardrev ++ */ ++static __used void ai_nvram_process(struct si_info *sii) ++{ ++ uint w = 0; ++ ++ /* do a pci config read to get subsystem id and subvendor id */ ++ pci_read_config_dword(sii->pbus, PCI_SUBSYSTEM_VENDOR_ID, &w); ++ ++ sii->pub.boardvendor = w & 0xffff; ++ sii->pub.boardtype = (w >> 16) & 0xffff; ++ sii->pub.boardflags = getintvar(&sii->pub, BRCMS_SROM_BOARDFLAGS); ++} ++ ++static struct si_info *ai_doattach(struct si_info *sii, ++ void __iomem *regs, struct pci_dev *pbus) ++{ ++ struct si_pub *sih = &sii->pub; ++ u32 w, savewin; ++ struct chipcregs __iomem *cc; ++ uint socitype; ++ uint origidx; ++ ++ memset((unsigned char *) sii, 0, sizeof(struct si_info)); ++ ++ savewin = 0; ++ ++ sih->buscoreidx = BADIDX; ++ ++ sii->curmap = regs; ++ sii->pbus = pbus; ++ ++ /* find Chipcommon address */ ++ pci_read_config_dword(sii->pbus, PCI_BAR0_WIN, &savewin); ++ if (!GOODCOREADDR(savewin, SI_ENUM_BASE)) ++ savewin = SI_ENUM_BASE; ++ ++ pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, ++ SI_ENUM_BASE); ++ cc = (struct chipcregs __iomem *) regs; ++ ++ /* bus/core/clk setup for register access */ ++ if (!ai_buscore_prep(sii)) ++ return NULL; ++ ++ /* ++ * ChipID recognition. ++ * We assume we can read chipid at offset 0 from the regs arg. ++ * If we add other chiptypes (or if we need to support old sdio ++ * hosts w/o chipcommon), some way of recognizing them needs to ++ * be added here. ++ */ ++ w = R_REG(&cc->chipid); ++ socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; ++ /* Might as wll fill in chip id rev & pkg */ ++ sih->chip = w & CID_ID_MASK; ++ sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; ++ sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; ++ ++ sih->issim = false; ++ ++ /* scan for cores */ ++ if (socitype == SOCI_AI) { ++ SI_MSG(("Found chip type AI (0x%08x)\n", w)); ++ /* pass chipc address instead of original core base */ ++ ai_scan(&sii->pub, cc); ++ } else { ++ /* Found chip of unknown type */ ++ return NULL; ++ } ++ /* no cores found, bail out */ ++ if (sii->numcores == 0) ++ return NULL; ++ ++ /* bus/core/clk setup */ ++ origidx = SI_CC_IDX; ++ if (!ai_buscore_setup(sii, savewin, &origidx)) ++ goto exit; ++ ++ /* Init nvram from sprom/otp if they exist */ ++ if (srom_var_init(&sii->pub, cc)) ++ goto exit; ++ ++ ai_nvram_process(sii); ++ ++ /* === NVRAM, clock is ready === */ ++ cc = (struct chipcregs __iomem *) ai_setcore(sih, CC_CORE_ID, 0); ++ W_REG(&cc->gpiopullup, 0); ++ W_REG(&cc->gpiopulldown, 0); ++ ai_setcoreidx(sih, origidx); ++ ++ /* PMU specific initializations */ ++ if (sih->cccaps & CC_CAP_PMU) { ++ u32 xtalfreq; ++ si_pmu_init(sih); ++ si_pmu_chip_init(sih); ++ ++ xtalfreq = si_pmu_measure_alpclk(sih); ++ si_pmu_pll_init(sih, xtalfreq); ++ si_pmu_res_init(sih); ++ si_pmu_swreg_init(sih); ++ } ++ ++ /* setup the GPIO based LED powersave register */ ++ w = getintvar(sih, BRCMS_SROM_LEDDC); ++ if (w == 0) ++ w = DEFAULT_GPIOTIMERVAL; ++ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, gpiotimerval), ++ ~0, w); ++ ++ if (PCIE(sii)) ++ pcicore_attach(sii->pch, SI_DOATTACH); ++ ++ if (sih->chip == BCM43224_CHIP_ID) { ++ /* ++ * enable 12 mA drive strenth for 43224 and ++ * set chipControl register bit 15 ++ */ ++ if (sih->chiprev == 0) { ++ SI_MSG(("Applying 43224A0 WARs\n")); ++ ai_corereg(sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol), ++ CCTRL43224_GPIO_TOGGLE, ++ CCTRL43224_GPIO_TOGGLE); ++ si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE, ++ CCTRL_43224A0_12MA_LED_DRIVE); ++ } ++ if (sih->chiprev >= 1) { ++ SI_MSG(("Applying 43224B0+ WARs\n")); ++ si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE, ++ CCTRL_43224B0_12MA_LED_DRIVE); ++ } ++ } ++ ++ if (sih->chip == BCM4313_CHIP_ID) { ++ /* ++ * enable 12 mA drive strenth for 4313 and ++ * set chipControl register bit 1 ++ */ ++ SI_MSG(("Applying 4313 WARs\n")); ++ si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE, ++ CCTRL_4313_12MA_LED_DRIVE); ++ } ++ ++ return sii; ++ ++ exit: ++ if (sii->pch) ++ pcicore_deinit(sii->pch); ++ sii->pch = NULL; ++ ++ return NULL; ++} ++ ++/* ++ * Allocate a si handle. ++ * devid - pci device id (used to determine chip#) ++ * osh - opaque OS handle ++ * regs - virtual address of initial core registers ++ */ ++struct si_pub * ++ai_attach(void __iomem *regs, struct pci_dev *sdh) ++{ ++ struct si_info *sii; ++ ++ /* alloc struct si_info */ ++ sii = kmalloc(sizeof(struct si_info), GFP_ATOMIC); ++ if (sii == NULL) ++ return NULL; ++ ++ if (ai_doattach(sii, regs, sdh) == NULL) { ++ kfree(sii); ++ return NULL; ++ } ++ ++ return (struct si_pub *) sii; ++} ++ ++/* may be called with core in reset */ ++void ai_detach(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ ++ struct si_pub *si_local = NULL; ++ memcpy(&si_local, &sih, sizeof(struct si_pub **)); ++ ++ sii = (struct si_info *)sih; ++ ++ if (sii == NULL) ++ return; ++ ++ if (sii->pch) ++ pcicore_deinit(sii->pch); ++ sii->pch = NULL; ++ ++ srom_free_vars(sih); ++ kfree(sii); ++} ++ ++/* register driver interrupt disabling and restoring callback functions */ ++void ++ai_register_intr_callback(struct si_pub *sih, void *intrsoff_fn, ++ void *intrsrestore_fn, ++ void *intrsenabled_fn, void *intr_arg) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ sii->intr_arg = intr_arg; ++ sii->intrsoff_fn = (u32 (*)(void *)) intrsoff_fn; ++ sii->intrsrestore_fn = (void (*) (void *, u32)) intrsrestore_fn; ++ sii->intrsenabled_fn = (bool (*)(void *)) intrsenabled_fn; ++ /* save current core id. when this function called, the current core ++ * must be the core which provides driver functions(il, et, wl, etc.) ++ */ ++ sii->dev_coreid = sii->coreid[sii->curidx]; ++} ++ ++void ai_deregister_intr_callback(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ sii->intrsoff_fn = NULL; ++} ++ ++uint ai_coreid(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ return sii->coreid[sii->curidx]; ++} ++ ++uint ai_coreidx(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ return sii->curidx; ++} ++ ++bool ai_backplane64(struct si_pub *sih) ++{ ++ return (sih->cccaps & CC_CAP_BKPLN64) != 0; ++} ++ ++/* return index of coreid or BADIDX if not found */ ++uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit) ++{ ++ struct si_info *sii; ++ uint found; ++ uint i; ++ ++ sii = (struct si_info *)sih; ++ ++ found = 0; ++ ++ for (i = 0; i < sii->numcores; i++) ++ if (sii->coreid[i] == coreid) { ++ if (found == coreunit) ++ return i; ++ found++; ++ } ++ ++ return BADIDX; ++} ++ ++/* ++ * This function changes logical "focus" to the indicated core; ++ * must be called with interrupts off. ++ * Moreover, callers should keep interrupts off during switching ++ * out of and back to d11 core. ++ */ ++void __iomem *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit) ++{ ++ uint idx; ++ ++ idx = ai_findcoreidx(sih, coreid, coreunit); ++ if (idx >= SI_MAXCORES) ++ return NULL; ++ ++ return ai_setcoreidx(sih, idx); ++} ++ ++/* Turn off interrupt as required by ai_setcore, before switch core */ ++void __iomem *ai_switch_core(struct si_pub *sih, uint coreid, uint *origidx, ++ uint *intr_val) ++{ ++ void __iomem *cc; ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ ++ if (SI_FAST(sii)) { ++ /* Overloading the origidx variable to remember the coreid, ++ * this works because the core ids cannot be confused with ++ * core indices. ++ */ ++ *origidx = coreid; ++ if (coreid == CC_CORE_ID) ++ return CCREGS_FAST(sii); ++ else if (coreid == sih->buscoretype) ++ return PCIEREGS(sii); ++ } ++ INTR_OFF(sii, *intr_val); ++ *origidx = sii->curidx; ++ cc = ai_setcore(sih, coreid, 0); ++ return cc; ++} ++ ++/* restore coreidx and restore interrupt */ ++void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ if (SI_FAST(sii) ++ && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype))) ++ return; ++ ++ ai_setcoreidx(sih, coreid); ++ INTR_RESTORE(sii, intr_val); ++} ++ ++void ai_write_wrapperreg(struct si_pub *sih, u32 offset, u32 val) ++{ ++ struct si_info *sii = (struct si_info *)sih; ++ u32 *w = (u32 *) sii->curwrap; ++ W_REG(w + (offset / 4), val); ++ return; ++} ++ ++/* ++ * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set ++ * operation, switch back to the original core, and return the new value. ++ * ++ * When using the silicon backplane, no fiddling with interrupts or core ++ * switches is needed. ++ * ++ * Also, when using pci/pcie, we can optimize away the core switching for pci ++ * registers and (on newer pci cores) chipcommon registers. ++ */ ++uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask, ++ uint val) ++{ ++ uint origidx = 0; ++ u32 __iomem *r = NULL; ++ uint w; ++ uint intr_val = 0; ++ bool fast = false; ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ ++ if (coreidx >= SI_MAXCORES) ++ return 0; ++ ++ /* ++ * If pci/pcie, we can get at pci/pcie regs ++ * and on newer cores to chipc ++ */ ++ if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) { ++ /* Chipc registers are mapped at 12KB */ ++ fast = true; ++ r = (u32 __iomem *)((__iomem char *)sii->curmap + ++ PCI_16KB0_CCREGS_OFFSET + regoff); ++ } else if (sii->pub.buscoreidx == coreidx) { ++ /* ++ * pci registers are at either in the last 2KB of ++ * an 8KB window or, in pcie and pci rev 13 at 8KB ++ */ ++ fast = true; ++ if (SI_FAST(sii)) ++ r = (u32 __iomem *)((__iomem char *)sii->curmap + ++ PCI_16KB0_PCIREGS_OFFSET + regoff); ++ else ++ r = (u32 __iomem *)((__iomem char *)sii->curmap + ++ ((regoff >= SBCONFIGOFF) ? ++ PCI_BAR0_PCISBR_OFFSET : ++ PCI_BAR0_PCIREGS_OFFSET) + regoff); ++ } ++ ++ if (!fast) { ++ INTR_OFF(sii, intr_val); ++ ++ /* save current core index */ ++ origidx = ai_coreidx(&sii->pub); ++ ++ /* switch core */ ++ r = (u32 __iomem *) ((unsigned char __iomem *) ++ ai_setcoreidx(&sii->pub, coreidx) + regoff); ++ } ++ ++ /* mask and set */ ++ if (mask || val) { ++ w = (R_REG(r) & ~mask) | val; ++ W_REG(r, w); ++ } ++ ++ /* readback */ ++ w = R_REG(r); ++ ++ if (!fast) { ++ /* restore core index */ ++ if (origidx != coreidx) ++ ai_setcoreidx(&sii->pub, origidx); ++ ++ INTR_RESTORE(sii, intr_val); ++ } ++ ++ return w; ++} ++ ++void ai_core_disable(struct si_pub *sih, u32 bits) ++{ ++ struct si_info *sii; ++ u32 dummy; ++ struct aidmp *ai; ++ ++ sii = (struct si_info *)sih; ++ ++ ai = sii->curwrap; ++ ++ /* if core is already in reset, just return */ ++ if (R_REG(&ai->resetctrl) & AIRC_RESET) ++ return; ++ ++ W_REG(&ai->ioctrl, bits); ++ dummy = R_REG(&ai->ioctrl); ++ udelay(10); ++ ++ W_REG(&ai->resetctrl, AIRC_RESET); ++ udelay(1); ++} ++ ++/* reset and re-enable a core ++ * inputs: ++ * bits - core specific bits that are set during and after reset sequence ++ * resetbits - core specific bits that are set only during reset sequence ++ */ ++void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits) ++{ ++ struct si_info *sii; ++ struct aidmp *ai; ++ u32 dummy; ++ ++ sii = (struct si_info *)sih; ++ ai = sii->curwrap; ++ ++ /* ++ * Must do the disable sequence first to work ++ * for arbitrary current core state. ++ */ ++ ai_core_disable(sih, (bits | resetbits)); ++ ++ /* ++ * Now do the initialization sequence. ++ */ ++ W_REG(&ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN)); ++ dummy = R_REG(&ai->ioctrl); ++ W_REG(&ai->resetctrl, 0); ++ udelay(1); ++ ++ W_REG(&ai->ioctrl, (bits | SICF_CLOCK_EN)); ++ dummy = R_REG(&ai->ioctrl); ++ udelay(1); ++} ++ ++/* return the slow clock source - LPO, XTAL, or PCI */ ++static uint ai_slowclk_src(struct si_info *sii) ++{ ++ struct chipcregs __iomem *cc; ++ u32 val; ++ ++ if (sii->pub.ccrev < 6) { ++ pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, ++ &val); ++ if (val & PCI_CFG_GPIO_SCS) ++ return SCC_SS_PCI; ++ return SCC_SS_XTAL; ++ } else if (sii->pub.ccrev < 10) { ++ cc = (struct chipcregs __iomem *) ++ ai_setcoreidx(&sii->pub, sii->curidx); ++ return R_REG(&cc->slow_clk_ctl) & SCC_SS_MASK; ++ } else /* Insta-clock */ ++ return SCC_SS_XTAL; ++} ++ ++/* ++* return the ILP (slowclock) min or max frequency ++* precondition: we've established the chip has dynamic clk control ++*/ ++static uint ai_slowclk_freq(struct si_info *sii, bool max_freq, ++ struct chipcregs __iomem *cc) ++{ ++ u32 slowclk; ++ uint div; ++ ++ slowclk = ai_slowclk_src(sii); ++ if (sii->pub.ccrev < 6) { ++ if (slowclk == SCC_SS_PCI) ++ return max_freq ? (PCIMAXFREQ / 64) ++ : (PCIMINFREQ / 64); ++ else ++ return max_freq ? (XTALMAXFREQ / 32) ++ : (XTALMINFREQ / 32); ++ } else if (sii->pub.ccrev < 10) { ++ div = 4 * ++ (((R_REG(&cc->slow_clk_ctl) & SCC_CD_MASK) >> ++ SCC_CD_SHIFT) + 1); ++ if (slowclk == SCC_SS_LPO) ++ return max_freq ? LPOMAXFREQ : LPOMINFREQ; ++ else if (slowclk == SCC_SS_XTAL) ++ return max_freq ? (XTALMAXFREQ / div) ++ : (XTALMINFREQ / div); ++ else if (slowclk == SCC_SS_PCI) ++ return max_freq ? (PCIMAXFREQ / div) ++ : (PCIMINFREQ / div); ++ } else { ++ /* Chipc rev 10 is InstaClock */ ++ div = R_REG(&cc->system_clk_ctl) >> SYCC_CD_SHIFT; ++ div = 4 * (div + 1); ++ return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div); ++ } ++ return 0; ++} ++ ++static void ++ai_clkctl_setdelay(struct si_info *sii, struct chipcregs __iomem *cc) ++{ ++ uint slowmaxfreq, pll_delay, slowclk; ++ uint pll_on_delay, fref_sel_delay; ++ ++ pll_delay = PLL_DELAY; ++ ++ /* ++ * If the slow clock is not sourced by the xtal then ++ * add the xtal_on_delay since the xtal will also be ++ * powered down by dynamic clk control logic. ++ */ ++ ++ slowclk = ai_slowclk_src(sii); ++ if (slowclk != SCC_SS_XTAL) ++ pll_delay += XTAL_ON_DELAY; ++ ++ /* Starting with 4318 it is ILP that is used for the delays */ ++ slowmaxfreq = ++ ai_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? false : true, cc); ++ ++ pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; ++ fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; ++ ++ W_REG(&cc->pll_on_delay, pll_on_delay); ++ W_REG(&cc->fref_sel_delay, fref_sel_delay); ++} ++ ++/* initialize power control delay registers */ ++void ai_clkctl_init(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ uint origidx = 0; ++ struct chipcregs __iomem *cc; ++ bool fast; ++ ++ if (!(sih->cccaps & CC_CAP_PWR_CTL)) ++ return; ++ ++ sii = (struct si_info *)sih; ++ fast = SI_FAST(sii); ++ if (!fast) { ++ origidx = sii->curidx; ++ cc = (struct chipcregs __iomem *) ++ ai_setcore(sih, CC_CORE_ID, 0); ++ if (cc == NULL) ++ return; ++ } else { ++ cc = (struct chipcregs __iomem *) CCREGS_FAST(sii); ++ if (cc == NULL) ++ return; ++ } ++ ++ /* set all Instaclk chip ILP to 1 MHz */ ++ if (sih->ccrev >= 10) ++ SET_REG(&cc->system_clk_ctl, SYCC_CD_MASK, ++ (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); ++ ++ ai_clkctl_setdelay(sii, cc); ++ ++ if (!fast) ++ ai_setcoreidx(sih, origidx); ++} ++ ++/* ++ * return the value suitable for writing to the ++ * dot11 core FAST_PWRUP_DELAY register ++ */ ++u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ uint origidx = 0; ++ struct chipcregs __iomem *cc; ++ uint slowminfreq; ++ u16 fpdelay; ++ uint intr_val = 0; ++ bool fast; ++ ++ sii = (struct si_info *)sih; ++ if (sih->cccaps & CC_CAP_PMU) { ++ INTR_OFF(sii, intr_val); ++ fpdelay = si_pmu_fast_pwrup_delay(sih); ++ INTR_RESTORE(sii, intr_val); ++ return fpdelay; ++ } ++ ++ if (!(sih->cccaps & CC_CAP_PWR_CTL)) ++ return 0; ++ ++ fast = SI_FAST(sii); ++ fpdelay = 0; ++ if (!fast) { ++ origidx = sii->curidx; ++ INTR_OFF(sii, intr_val); ++ cc = (struct chipcregs __iomem *) ++ ai_setcore(sih, CC_CORE_ID, 0); ++ if (cc == NULL) ++ goto done; ++ } else { ++ cc = (struct chipcregs __iomem *) CCREGS_FAST(sii); ++ if (cc == NULL) ++ goto done; ++ } ++ ++ slowminfreq = ai_slowclk_freq(sii, false, cc); ++ fpdelay = (((R_REG(&cc->pll_on_delay) + 2) * 1000000) + ++ (slowminfreq - 1)) / slowminfreq; ++ ++ done: ++ if (!fast) { ++ ai_setcoreidx(sih, origidx); ++ INTR_RESTORE(sii, intr_val); ++ } ++ return fpdelay; ++} ++ ++/* turn primary xtal and/or pll off/on */ ++int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on) ++{ ++ struct si_info *sii; ++ u32 in, out, outen; ++ ++ sii = (struct si_info *)sih; ++ ++ /* pcie core doesn't have any mapping to control the xtal pu */ ++ if (PCIE(sii)) ++ return -1; ++ ++ pci_read_config_dword(sii->pbus, PCI_GPIO_IN, &in); ++ pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, &out); ++ pci_read_config_dword(sii->pbus, PCI_GPIO_OUTEN, &outen); ++ ++ /* ++ * Avoid glitching the clock if GPRS is already using it. ++ * We can't actually read the state of the PLLPD so we infer it ++ * by the value of XTAL_PU which *is* readable via gpioin. ++ */ ++ if (on && (in & PCI_CFG_GPIO_XTAL)) ++ return 0; ++ ++ if (what & XTAL) ++ outen |= PCI_CFG_GPIO_XTAL; ++ if (what & PLL) ++ outen |= PCI_CFG_GPIO_PLL; ++ ++ if (on) { ++ /* turn primary xtal on */ ++ if (what & XTAL) { ++ out |= PCI_CFG_GPIO_XTAL; ++ if (what & PLL) ++ out |= PCI_CFG_GPIO_PLL; ++ pci_write_config_dword(sii->pbus, ++ PCI_GPIO_OUT, out); ++ pci_write_config_dword(sii->pbus, ++ PCI_GPIO_OUTEN, outen); ++ udelay(XTAL_ON_DELAY); ++ } ++ ++ /* turn pll on */ ++ if (what & PLL) { ++ out &= ~PCI_CFG_GPIO_PLL; ++ pci_write_config_dword(sii->pbus, ++ PCI_GPIO_OUT, out); ++ mdelay(2); ++ } ++ } else { ++ if (what & XTAL) ++ out &= ~PCI_CFG_GPIO_XTAL; ++ if (what & PLL) ++ out |= PCI_CFG_GPIO_PLL; ++ pci_write_config_dword(sii->pbus, ++ PCI_GPIO_OUT, out); ++ pci_write_config_dword(sii->pbus, ++ PCI_GPIO_OUTEN, outen); ++ } ++ ++ return 0; ++} ++ ++/* clk control mechanism through chipcommon, no policy checking */ ++static bool _ai_clkctl_cc(struct si_info *sii, uint mode) ++{ ++ uint origidx = 0; ++ struct chipcregs __iomem *cc; ++ u32 scc; ++ uint intr_val = 0; ++ bool fast = SI_FAST(sii); ++ ++ /* chipcommon cores prior to rev6 don't support dynamic clock control */ ++ if (sii->pub.ccrev < 6) ++ return false; ++ ++ if (!fast) { ++ INTR_OFF(sii, intr_val); ++ origidx = sii->curidx; ++ cc = (struct chipcregs __iomem *) ++ ai_setcore(&sii->pub, CC_CORE_ID, 0); ++ } else { ++ cc = (struct chipcregs __iomem *) CCREGS_FAST(sii); ++ if (cc == NULL) ++ goto done; ++ } ++ ++ if (!(sii->pub.cccaps & CC_CAP_PWR_CTL) && (sii->pub.ccrev < 20)) ++ goto done; ++ ++ switch (mode) { ++ case CLK_FAST: /* FORCEHT, fast (pll) clock */ ++ if (sii->pub.ccrev < 10) { ++ /* ++ * don't forget to force xtal back ++ * on before we clear SCC_DYN_XTAL.. ++ */ ++ ai_clkctl_xtal(&sii->pub, XTAL, ON); ++ SET_REG(&cc->slow_clk_ctl, ++ (SCC_XC | SCC_FS | SCC_IP), SCC_IP); ++ } else if (sii->pub.ccrev < 20) { ++ OR_REG(&cc->system_clk_ctl, SYCC_HR); ++ } else { ++ OR_REG(&cc->clk_ctl_st, CCS_FORCEHT); ++ } ++ ++ /* wait for the PLL */ ++ if (sii->pub.cccaps & CC_CAP_PMU) { ++ u32 htavail = CCS_HTAVAIL; ++ SPINWAIT(((R_REG(&cc->clk_ctl_st) & htavail) ++ == 0), PMU_MAX_TRANSITION_DLY); ++ } else { ++ udelay(PLL_DELAY); ++ } ++ break; ++ ++ case CLK_DYNAMIC: /* enable dynamic clock control */ ++ if (sii->pub.ccrev < 10) { ++ scc = R_REG(&cc->slow_clk_ctl); ++ scc &= ~(SCC_FS | SCC_IP | SCC_XC); ++ if ((scc & SCC_SS_MASK) != SCC_SS_XTAL) ++ scc |= SCC_XC; ++ W_REG(&cc->slow_clk_ctl, scc); ++ ++ /* ++ * for dynamic control, we have to ++ * release our xtal_pu "force on" ++ */ ++ if (scc & SCC_XC) ++ ai_clkctl_xtal(&sii->pub, XTAL, OFF); ++ } else if (sii->pub.ccrev < 20) { ++ /* Instaclock */ ++ AND_REG(&cc->system_clk_ctl, ~SYCC_HR); ++ } else { ++ AND_REG(&cc->clk_ctl_st, ~CCS_FORCEHT); ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ done: ++ if (!fast) { ++ ai_setcoreidx(&sii->pub, origidx); ++ INTR_RESTORE(sii, intr_val); ++ } ++ return mode == CLK_FAST; ++} ++ ++/* ++ * clock control policy function throught chipcommon ++ * ++ * set dynamic clk control mode (forceslow, forcefast, dynamic) ++ * returns true if we are forcing fast clock ++ * this is a wrapper over the next internal function ++ * to allow flexible policy settings for outside caller ++ */ ++bool ai_clkctl_cc(struct si_pub *sih, uint mode) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ ++ /* chipcommon cores prior to rev6 don't support dynamic clock control */ ++ if (sih->ccrev < 6) ++ return false; ++ ++ if (PCI_FORCEHT(sii)) ++ return mode == CLK_FAST; ++ ++ return _ai_clkctl_cc(sii, mode); ++} ++ ++/* Build device path */ ++int ai_devpath(struct si_pub *sih, char *path, int size) ++{ ++ int slen; ++ ++ if (!path || size <= 0) ++ return -1; ++ ++ slen = snprintf(path, (size_t) size, "pci/%u/%u/", ++ ((struct si_info *)sih)->pbus->bus->number, ++ PCI_SLOT(((struct pci_dev *) ++ (((struct si_info *)(sih))->pbus))->devfn)); ++ ++ if (slen < 0 || slen >= size) { ++ path[0] = '\0'; ++ return -1; ++ } ++ ++ return 0; ++} ++ ++void ai_pci_up(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ ++ if (PCI_FORCEHT(sii)) ++ _ai_clkctl_cc(sii, CLK_FAST); ++ ++ if (PCIE(sii)) ++ pcicore_up(sii->pch, SI_PCIUP); ++ ++} ++ ++/* Unconfigure and/or apply various WARs when system is going to sleep mode */ ++void ai_pci_sleep(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ ++ pcicore_sleep(sii->pch); ++} ++ ++/* Unconfigure and/or apply various WARs when going down */ ++void ai_pci_down(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ ++ /* release FORCEHT since chip is going to "down" state */ ++ if (PCI_FORCEHT(sii)) ++ _ai_clkctl_cc(sii, CLK_DYNAMIC); ++ ++ pcicore_down(sii->pch, SI_PCIDOWN); ++} ++ ++/* ++ * Configure the pci core for pci client (NIC) action ++ * coremask is the bitvec of cores by index to be enabled. ++ */ ++void ai_pci_setup(struct si_pub *sih, uint coremask) ++{ ++ struct si_info *sii; ++ struct sbpciregs __iomem *regs = NULL; ++ u32 siflag = 0, w; ++ uint idx = 0; ++ ++ sii = (struct si_info *)sih; ++ ++ if (PCI(sii)) { ++ /* get current core index */ ++ idx = sii->curidx; ++ ++ /* we interrupt on this backplane flag number */ ++ siflag = ai_flag(sih); ++ ++ /* switch over to pci core */ ++ regs = ai_setcoreidx(sih, sii->pub.buscoreidx); ++ } ++ ++ /* ++ * Enable sb->pci interrupts. Assume ++ * PCI rev 2.3 support was added in pci core rev 6 and things changed.. ++ */ ++ if (PCIE(sii) || (PCI(sii) && ((sii->pub.buscorerev) >= 6))) { ++ /* pci config write to set this core bit in PCIIntMask */ ++ pci_read_config_dword(sii->pbus, PCI_INT_MASK, &w); ++ w |= (coremask << PCI_SBIM_SHIFT); ++ pci_write_config_dword(sii->pbus, PCI_INT_MASK, w); ++ } else { ++ /* set sbintvec bit for our flag number */ ++ ai_setint(sih, siflag); ++ } ++ ++ if (PCI(sii)) { ++ pcicore_pci_setup(sii->pch, regs); ++ ++ /* switch back to previous core */ ++ ai_setcoreidx(sih, idx); ++ } ++} ++ ++/* ++ * Fixup SROMless PCI device's configuration. ++ * The current core may be changed upon return. ++ */ ++int ai_pci_fixcfg(struct si_pub *sih) ++{ ++ uint origidx; ++ void __iomem *regs = NULL; ++ struct si_info *sii = (struct si_info *)sih; ++ ++ /* Fixup PI in SROM shadow area to enable the correct PCI core access */ ++ /* save the current index */ ++ origidx = ai_coreidx(&sii->pub); ++ ++ /* check 'pi' is correct and fix it if not */ ++ regs = ai_setcore(&sii->pub, sii->pub.buscoretype, 0); ++ if (sii->pub.buscoretype == PCIE_CORE_ID) ++ pcicore_fixcfg_pcie(sii->pch, ++ (struct sbpcieregs __iomem *)regs); ++ else if (sii->pub.buscoretype == PCI_CORE_ID) ++ pcicore_fixcfg_pci(sii->pch, (struct sbpciregs __iomem *)regs); ++ ++ /* restore the original index */ ++ ai_setcoreidx(&sii->pub, origidx); ++ ++ pcicore_hwup(sii->pch); ++ return 0; ++} ++ ++/* mask&set gpiocontrol bits */ ++u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val, u8 priority) ++{ ++ uint regoff; ++ ++ regoff = offsetof(struct chipcregs, gpiocontrol); ++ return ai_corereg(sih, SI_CC_IDX, regoff, mask, val); ++} ++ ++void ai_chipcontrl_epa4331(struct si_pub *sih, bool on) ++{ ++ struct si_info *sii; ++ struct chipcregs __iomem *cc; ++ uint origidx; ++ u32 val; ++ ++ sii = (struct si_info *)sih; ++ origidx = ai_coreidx(sih); ++ ++ cc = (struct chipcregs __iomem *) ai_setcore(sih, CC_CORE_ID, 0); ++ ++ val = R_REG(&cc->chipcontrol); ++ ++ if (on) { ++ if (sih->chippkg == 9 || sih->chippkg == 0xb) ++ /* Ext PA Controls for 4331 12x9 Package */ ++ W_REG(&cc->chipcontrol, val | ++ CCTRL4331_EXTPA_EN | ++ CCTRL4331_EXTPA_ON_GPIO2_5); ++ else ++ /* Ext PA Controls for 4331 12x12 Package */ ++ W_REG(&cc->chipcontrol, ++ val | CCTRL4331_EXTPA_EN); ++ } else { ++ val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); ++ W_REG(&cc->chipcontrol, val); ++ } ++ ++ ai_setcoreidx(sih, origidx); ++} ++ ++/* Enable BT-COEX & Ex-PA for 4313 */ ++void ai_epa_4313war(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ struct chipcregs __iomem *cc; ++ uint origidx; ++ ++ sii = (struct si_info *)sih; ++ origidx = ai_coreidx(sih); ++ ++ cc = ai_setcore(sih, CC_CORE_ID, 0); ++ ++ /* EPA Fix */ ++ W_REG(&cc->gpiocontrol, ++ R_REG(&cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK); ++ ++ ai_setcoreidx(sih, origidx); ++} ++ ++/* check if the device is removed */ ++bool ai_deviceremoved(struct si_pub *sih) ++{ ++ u32 w; ++ struct si_info *sii; ++ ++ sii = (struct si_info *)sih; ++ ++ pci_read_config_dword(sii->pbus, PCI_VENDOR_ID, &w); ++ if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM) ++ return true; ++ ++ return false; ++} ++ ++bool ai_is_sprom_available(struct si_pub *sih) ++{ ++ if (sih->ccrev >= 31) { ++ struct si_info *sii; ++ uint origidx; ++ struct chipcregs __iomem *cc; ++ u32 sromctrl; ++ ++ if ((sih->cccaps & CC_CAP_SROM) == 0) ++ return false; ++ ++ sii = (struct si_info *)sih; ++ origidx = sii->curidx; ++ cc = ai_setcoreidx(sih, SI_CC_IDX); ++ sromctrl = R_REG(&cc->sromcontrol); ++ ai_setcoreidx(sih, origidx); ++ return sromctrl & SRC_PRESENT; ++ } ++ ++ switch (sih->chip) { ++ case BCM4313_CHIP_ID: ++ return (sih->chipst & CST4313_SPROM_PRESENT) != 0; ++ default: ++ return true; ++ } ++} ++ ++bool ai_is_otp_disabled(struct si_pub *sih) ++{ ++ switch (sih->chip) { ++ case BCM4313_CHIP_ID: ++ return (sih->chipst & CST4313_OTP_PRESENT) == 0; ++ /* These chips always have their OTP on */ ++ case BCM43224_CHIP_ID: ++ case BCM43225_CHIP_ID: ++ default: ++ return false; ++ } ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h.orig 2011-11-09 13:46:58.239800709 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h 2011-11-09 13:47:16.991566278 -0500 +@@ -0,0 +1,378 @@ ++/* ++ * Copyright (c) 2011 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_AIUTILS_H_ ++#define _BRCM_AIUTILS_H_ ++ ++#include "types.h" ++ ++/* ++ * SOC Interconnect Address Map. ++ * All regions may not exist on all chips. ++ */ ++/* each core gets 4Kbytes for registers */ ++#define SI_CORE_SIZE 0x1000 ++/* ++ * Max cores (this is arbitrary, for software ++ * convenience and could be changed if we ++ * make any larger chips ++ */ ++#define SI_MAXCORES 16 ++ ++/* Client Mode sb2pcitranslation2 size in bytes */ ++#define SI_PCI_DMA_SZ 0x40000000 ++ ++/* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */ ++#define SI_PCIE_DMA_H32 0x80000000 ++ ++/* core codes */ ++#define NODEV_CORE_ID 0x700 /* Invalid coreid */ ++#define CC_CORE_ID 0x800 /* chipcommon core */ ++#define ILINE20_CORE_ID 0x801 /* iline20 core */ ++#define SRAM_CORE_ID 0x802 /* sram core */ ++#define SDRAM_CORE_ID 0x803 /* sdram core */ ++#define PCI_CORE_ID 0x804 /* pci core */ ++#define MIPS_CORE_ID 0x805 /* mips core */ ++#define ENET_CORE_ID 0x806 /* enet mac core */ ++#define CODEC_CORE_ID 0x807 /* v90 codec core */ ++#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */ ++#define ADSL_CORE_ID 0x809 /* ADSL core */ ++#define ILINE100_CORE_ID 0x80a /* iline100 core */ ++#define IPSEC_CORE_ID 0x80b /* ipsec core */ ++#define UTOPIA_CORE_ID 0x80c /* utopia core */ ++#define PCMCIA_CORE_ID 0x80d /* pcmcia core */ ++#define SOCRAM_CORE_ID 0x80e /* internal memory core */ ++#define MEMC_CORE_ID 0x80f /* memc sdram core */ ++#define OFDM_CORE_ID 0x810 /* OFDM phy core */ ++#define EXTIF_CORE_ID 0x811 /* external interface core */ ++#define D11_CORE_ID 0x812 /* 802.11 MAC core */ ++#define APHY_CORE_ID 0x813 /* 802.11a phy core */ ++#define BPHY_CORE_ID 0x814 /* 802.11b phy core */ ++#define GPHY_CORE_ID 0x815 /* 802.11g phy core */ ++#define MIPS33_CORE_ID 0x816 /* mips3302 core */ ++#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */ ++#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */ ++#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */ ++#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */ ++#define SDIOH_CORE_ID 0x81b /* sdio host core */ ++#define ROBO_CORE_ID 0x81c /* roboswitch core */ ++#define ATA100_CORE_ID 0x81d /* parallel ATA core */ ++#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */ ++#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */ ++#define PCIE_CORE_ID 0x820 /* pci express core */ ++#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */ ++#define SRAMC_CORE_ID 0x822 /* SRAM controller core */ ++#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */ ++#define ARM11_CORE_ID 0x824 /* ARM 1176 core */ ++#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */ ++#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */ ++#define PMU_CORE_ID 0x827 /* PMU core */ ++#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */ ++#define SDIOD_CORE_ID 0x829 /* SDIO device core */ ++#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */ ++#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */ ++#define MIPS74K_CORE_ID 0x82c /* mips 74k core */ ++#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */ ++#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */ ++#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */ ++#define SC_CORE_ID 0x831 /* shared common core */ ++#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */ ++#define SPIH_CORE_ID 0x833 /* SPI host core */ ++#define I2S_CORE_ID 0x834 /* I2S core */ ++#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */ ++#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */ ++#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */ ++#define DEF_AI_COMP 0xfff /* Default component, in ai chips it ++ * maps all unused address ranges ++ */ ++ ++/* chipcommon being the first core: */ ++#define SI_CC_IDX 0 ++ ++/* SOC Interconnect types (aka chip types) */ ++#define SOCI_AI 1 ++ ++/* Common core control flags */ ++#define SICF_BIST_EN 0x8000 ++#define SICF_PME_EN 0x4000 ++#define SICF_CORE_BITS 0x3ffc ++#define SICF_FGC 0x0002 ++#define SICF_CLOCK_EN 0x0001 ++ ++/* Common core status flags */ ++#define SISF_BIST_DONE 0x8000 ++#define SISF_BIST_ERROR 0x4000 ++#define SISF_GATED_CLK 0x2000 ++#define SISF_DMA64 0x1000 ++#define SISF_CORE_BITS 0x0fff ++ ++/* A register that is common to all cores to ++ * communicate w/PMU regarding clock control. ++ */ ++#define SI_CLK_CTL_ST 0x1e0 /* clock control and status */ ++ ++/* clk_ctl_st register */ ++#define CCS_FORCEALP 0x00000001 /* force ALP request */ ++#define CCS_FORCEHT 0x00000002 /* force HT request */ ++#define CCS_FORCEILP 0x00000004 /* force ILP request */ ++#define CCS_ALPAREQ 0x00000008 /* ALP Avail Request */ ++#define CCS_HTAREQ 0x00000010 /* HT Avail Request */ ++#define CCS_FORCEHWREQOFF 0x00000020 /* Force HW Clock Request Off */ ++#define CCS_ERSRC_REQ_MASK 0x00000700 /* external resource requests */ ++#define CCS_ERSRC_REQ_SHIFT 8 ++#define CCS_ALPAVAIL 0x00010000 /* ALP is available */ ++#define CCS_HTAVAIL 0x00020000 /* HT is available */ ++#define CCS_BP_ON_APL 0x00040000 /* RO: running on ALP clock */ ++#define CCS_BP_ON_HT 0x00080000 /* RO: running on HT clock */ ++#define CCS_ERSRC_STS_MASK 0x07000000 /* external resource status */ ++#define CCS_ERSRC_STS_SHIFT 24 ++ ++/* HT avail in chipc and pcmcia on 4328a0 */ ++#define CCS0_HTAVAIL 0x00010000 ++/* ALP avail in chipc and pcmcia on 4328a0 */ ++#define CCS0_ALPAVAIL 0x00020000 ++ ++/* Not really related to SOC Interconnect, but a couple of software ++ * conventions for the use the flash space: ++ */ ++ ++/* Minumum amount of flash we support */ ++#define FLASH_MIN 0x00020000 /* Minimum flash size */ ++ ++#define CC_SROM_OTP 0x800 /* SROM/OTP address space */ ++ ++/* gpiotimerval */ ++#define GPIO_ONTIME_SHIFT 16 ++ ++/* Fields in clkdiv */ ++#define CLKD_OTP 0x000f0000 ++#define CLKD_OTP_SHIFT 16 ++ ++/* Package IDs */ ++#define BCM4717_PKG_ID 9 /* 4717 package id */ ++#define BCM4718_PKG_ID 10 /* 4718 package id */ ++#define BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */ ++ ++/* these are router chips */ ++#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */ ++#define BCM47162_CHIP_ID 47162 /* 47162 chipcommon chipid */ ++#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */ ++ ++/* dynamic clock control defines */ ++#define LPOMINFREQ 25000 /* low power oscillator min */ ++#define LPOMAXFREQ 43000 /* low power oscillator max */ ++#define XTALMINFREQ 19800000 /* 20 MHz - 1% */ ++#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */ ++#define PCIMINFREQ 25000000 /* 25 MHz */ ++#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */ ++ ++#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ ++#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ ++ ++/* clkctl xtal what flags */ ++#define XTAL 0x1 /* primary crystal oscillator (2050) */ ++#define PLL 0x2 /* main chip pll */ ++ ++/* clkctl clk mode */ ++#define CLK_FAST 0 /* force fast (pll) clock */ ++#define CLK_DYNAMIC 2 /* enable dynamic clock control */ ++ ++/* GPIO usage priorities */ ++#define GPIO_DRV_PRIORITY 0 /* Driver */ ++#define GPIO_APP_PRIORITY 1 /* Application */ ++#define GPIO_HI_PRIORITY 2 /* Highest priority. Ignore GPIO ++ * reservation ++ */ ++ ++/* GPIO pull up/down */ ++#define GPIO_PULLUP 0 ++#define GPIO_PULLDN 1 ++ ++/* GPIO event regtype */ ++#define GPIO_REGEVT 0 /* GPIO register event */ ++#define GPIO_REGEVT_INTMSK 1 /* GPIO register event int mask */ ++#define GPIO_REGEVT_INTPOL 2 /* GPIO register event int polarity */ ++ ++/* device path */ ++#define SI_DEVPATH_BUFSZ 16 /* min buffer size in bytes */ ++ ++/* SI routine enumeration: to be used by update function with multiple hooks */ ++#define SI_DOATTACH 1 ++#define SI_PCIDOWN 2 ++#define SI_PCIUP 3 ++ ++/* ++ * Data structure to export all chip specific common variables ++ * public (read-only) portion of aiutils handle returned by si_attach() ++ */ ++struct si_pub { ++ uint buscoretype; /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */ ++ uint buscorerev; /* buscore rev */ ++ uint buscoreidx; /* buscore index */ ++ int ccrev; /* chip common core rev */ ++ u32 cccaps; /* chip common capabilities */ ++ u32 cccaps_ext; /* chip common capabilities extension */ ++ int pmurev; /* pmu core rev */ ++ u32 pmucaps; /* pmu capabilities */ ++ uint boardtype; /* board type */ ++ uint boardvendor; /* board vendor */ ++ uint boardflags; /* board flags */ ++ uint boardflags2; /* board flags2 */ ++ uint chip; /* chip number */ ++ uint chiprev; /* chip revision */ ++ uint chippkg; /* chip package option */ ++ u32 chipst; /* chip status */ ++ bool issim; /* chip is in simulation or emulation */ ++ uint socirev; /* SOC interconnect rev */ ++ bool pci_pr32414; ++ ++}; ++ ++struct pci_dev; ++ ++struct gpioh_item { ++ void *arg; ++ bool level; ++ void (*handler) (u32 stat, void *arg); ++ u32 event; ++ struct gpioh_item *next; ++}; ++ ++/* misc si info needed by some of the routines */ ++struct si_info { ++ struct si_pub pub; /* back plane public state (must be first) */ ++ struct pci_dev *pbus; /* handle to pci bus */ ++ uint dev_coreid; /* the core provides driver functions */ ++ void *intr_arg; /* interrupt callback function arg */ ++ u32 (*intrsoff_fn) (void *intr_arg); /* turns chip interrupts off */ ++ /* restore chip interrupts */ ++ void (*intrsrestore_fn) (void *intr_arg, u32 arg); ++ /* check if interrupts are enabled */ ++ bool (*intrsenabled_fn) (void *intr_arg); ++ ++ struct pcicore_info *pch; /* PCI/E core handle */ ++ ++ struct list_head var_list; /* list of srom variables */ ++ ++ void __iomem *curmap; /* current regs va */ ++ void __iomem *regs[SI_MAXCORES]; /* other regs va */ ++ ++ uint curidx; /* current core index */ ++ uint numcores; /* # discovered cores */ ++ uint coreid[SI_MAXCORES]; /* id of each core */ ++ u32 coresba[SI_MAXCORES]; /* backplane address of each core */ ++ void *regs2[SI_MAXCORES]; /* 2nd virtual address per core (usbh20) */ ++ u32 coresba2[SI_MAXCORES]; /* 2nd phys address per core (usbh20) */ ++ u32 coresba_size[SI_MAXCORES]; /* backplane address space size */ ++ u32 coresba2_size[SI_MAXCORES]; /* second address space size */ ++ ++ void *curwrap; /* current wrapper va */ ++ void *wrappers[SI_MAXCORES]; /* other cores wrapper va */ ++ u32 wrapba[SI_MAXCORES]; /* address of controlling wrapper */ ++ ++ u32 cia[SI_MAXCORES]; /* erom cia entry for each core */ ++ u32 cib[SI_MAXCORES]; /* erom cia entry for each core */ ++ u32 oob_router; /* oob router registers for axi */ ++}; ++ ++/* ++ * Many of the routines below take an 'sih' handle as their first arg. ++ * Allocate this by calling si_attach(). Free it by calling si_detach(). ++ * At any one time, the sih is logically focused on one particular si core ++ * (the "current core"). ++ * Use si_setcore() or si_setcoreidx() to change the association to another core ++ */ ++ ++ ++/* AMBA Interconnect exported externs */ ++extern uint ai_flag(struct si_pub *sih); ++extern void ai_setint(struct si_pub *sih, int siflag); ++extern uint ai_coreidx(struct si_pub *sih); ++extern uint ai_corevendor(struct si_pub *sih); ++extern uint ai_corerev(struct si_pub *sih); ++extern bool ai_iscoreup(struct si_pub *sih); ++extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val); ++extern void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val); ++extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val); ++extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask, ++ uint val); ++extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits); ++extern void ai_core_disable(struct si_pub *sih, u32 bits); ++extern int ai_numaddrspaces(struct si_pub *sih); ++extern u32 ai_addrspace(struct si_pub *sih, uint asidx); ++extern u32 ai_addrspacesize(struct si_pub *sih, uint asidx); ++extern void ai_write_wrap_reg(struct si_pub *sih, u32 offset, u32 val); ++ ++/* === exported functions === */ ++extern struct si_pub *ai_attach(void __iomem *regs, struct pci_dev *sdh); ++extern void ai_detach(struct si_pub *sih); ++extern uint ai_coreid(struct si_pub *sih); ++extern uint ai_corerev(struct si_pub *sih); ++extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask, ++ uint val); ++extern void ai_write_wrapperreg(struct si_pub *sih, u32 offset, u32 val); ++extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val); ++extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val); ++extern bool ai_iscoreup(struct si_pub *sih); ++extern uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit); ++extern void __iomem *ai_setcoreidx(struct si_pub *sih, uint coreidx); ++extern void __iomem *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit); ++extern void __iomem *ai_switch_core(struct si_pub *sih, uint coreid, ++ uint *origidx, uint *intr_val); ++extern void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val); ++extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits); ++extern void ai_core_disable(struct si_pub *sih, u32 bits); ++extern u32 ai_alp_clock(struct si_pub *sih); ++extern u32 ai_ilp_clock(struct si_pub *sih); ++extern void ai_pci_setup(struct si_pub *sih, uint coremask); ++extern void ai_setint(struct si_pub *sih, int siflag); ++extern bool ai_backplane64(struct si_pub *sih); ++extern void ai_register_intr_callback(struct si_pub *sih, void *intrsoff_fn, ++ void *intrsrestore_fn, ++ void *intrsenabled_fn, void *intr_arg); ++extern void ai_deregister_intr_callback(struct si_pub *sih); ++extern void ai_clkctl_init(struct si_pub *sih); ++extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih); ++extern bool ai_clkctl_cc(struct si_pub *sih, uint mode); ++extern int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on); ++extern bool ai_deviceremoved(struct si_pub *sih); ++extern u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val, ++ u8 priority); ++ ++/* OTP status */ ++extern bool ai_is_otp_disabled(struct si_pub *sih); ++ ++/* SPROM availability */ ++extern bool ai_is_sprom_available(struct si_pub *sih); ++ ++/* ++ * Build device path. Path size must be >= SI_DEVPATH_BUFSZ. ++ * The returned path is NULL terminated and has trailing '/'. ++ * Return 0 on success, nonzero otherwise. ++ */ ++extern int ai_devpath(struct si_pub *sih, char *path, int size); ++ ++extern void ai_pci_sleep(struct si_pub *sih); ++extern void ai_pci_down(struct si_pub *sih); ++extern void ai_pci_up(struct si_pub *sih); ++extern int ai_pci_fixcfg(struct si_pub *sih); ++ ++extern void ai_chipcontrl_epa4331(struct si_pub *sih, bool on); ++/* Enable Ex-PA for 4313 */ ++extern void ai_epa_4313war(struct si_pub *sih); ++ ++#endif /* _BRCM_AIUTILS_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c.orig 2011-11-09 13:46:58.240800696 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c 2011-11-09 13:47:16.992566265 -0500 +@@ -0,0 +1,1241 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++ ++#include "rate.h" ++#include "scb.h" ++#include "phy/phy_hal.h" ++#include "antsel.h" ++#include "main.h" ++#include "ampdu.h" ++ ++/* max number of mpdus in an ampdu */ ++#define AMPDU_MAX_MPDU 32 ++/* max number of mpdus in an ampdu to a legacy */ ++#define AMPDU_NUM_MPDU_LEGACY 16 ++/* max Tx ba window size (in pdu) */ ++#define AMPDU_TX_BA_MAX_WSIZE 64 ++/* default Tx ba window size (in pdu) */ ++#define AMPDU_TX_BA_DEF_WSIZE 64 ++/* default Rx ba window size (in pdu) */ ++#define AMPDU_RX_BA_DEF_WSIZE 64 ++/* max Rx ba window size (in pdu) */ ++#define AMPDU_RX_BA_MAX_WSIZE 64 ++/* max dur of tx ampdu (in msec) */ ++#define AMPDU_MAX_DUR 5 ++/* default tx retry limit */ ++#define AMPDU_DEF_RETRY_LIMIT 5 ++/* default tx retry limit at reg rate */ ++#define AMPDU_DEF_RR_RETRY_LIMIT 2 ++/* default weight of ampdu in txfifo */ ++#define AMPDU_DEF_TXPKT_WEIGHT 2 ++/* default ffpld reserved bytes */ ++#define AMPDU_DEF_FFPLD_RSVD 2048 ++/* # of inis to be freed on detach */ ++#define AMPDU_INI_FREE 10 ++/* max # of mpdus released at a time */ ++#define AMPDU_SCB_MAX_RELEASE 20 ++ ++#define NUM_FFPLD_FIFO 4 /* number of fifo concerned by pre-loading */ ++#define FFPLD_TX_MAX_UNFL 200 /* default value of the average number of ampdu ++ * without underflows ++ */ ++#define FFPLD_MPDU_SIZE 1800 /* estimate of maximum mpdu size */ ++#define FFPLD_MAX_MCS 23 /* we don't deal with mcs 32 */ ++#define FFPLD_PLD_INCR 1000 /* increments in bytes */ ++#define FFPLD_MAX_AMPDU_CNT 5000 /* maximum number of ampdu we ++ * accumulate between resets. ++ */ ++ ++#define AMPDU_DELIMITER_LEN 4 ++ ++/* max allowed number of mpdus in an ampdu (2 streams) */ ++#define AMPDU_NUM_MPDU 16 ++ ++#define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE) ++ ++/* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */ ++#define AMPDU_MAX_MPDU_OVERHEAD (FCS_LEN + DOT11_ICV_AES_LEN +\ ++ AMPDU_DELIMITER_LEN + 3\ ++ + DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN) ++ ++/* modulo add/sub, bound = 2^k */ ++#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1)) ++#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1)) ++ ++/* structure to hold tx fifo information and pre-loading state ++ * counters specific to tx underflows of ampdus ++ * some counters might be redundant with the ones in wlc or ampdu structures. ++ * This allows to maintain a specific state independently of ++ * how often and/or when the wlc counters are updated. ++ * ++ * ampdu_pld_size: number of bytes to be pre-loaded ++ * mcs2ampdu_table: per-mcs max # of mpdus in an ampdu ++ * prev_txfunfl: num of underflows last read from the HW macstats counter ++ * accum_txfunfl: num of underflows since we modified pld params ++ * accum_txampdu: num of tx ampdu since we modified pld params ++ * prev_txampdu: previous reading of tx ampdu ++ * dmaxferrate: estimated dma avg xfer rate in kbits/sec ++ */ ++struct brcms_fifo_info { ++ u16 ampdu_pld_size; ++ u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1]; ++ u16 prev_txfunfl; ++ u32 accum_txfunfl; ++ u32 accum_txampdu; ++ u32 prev_txampdu; ++ u32 dmaxferrate; ++}; ++ ++/* AMPDU module specific state ++ * ++ * wlc: pointer to main wlc structure ++ * scb_handle: scb cubby handle to retrieve data from scb ++ * ini_enable: per-tid initiator enable/disable of ampdu ++ * ba_tx_wsize: Tx ba window size (in pdu) ++ * ba_rx_wsize: Rx ba window size (in pdu) ++ * retry_limit: mpdu transmit retry limit ++ * rr_retry_limit: mpdu transmit retry limit at regular rate ++ * retry_limit_tid: per-tid mpdu transmit retry limit ++ * rr_retry_limit_tid: per-tid mpdu transmit retry limit at regular rate ++ * mpdu_density: min mpdu spacing (0-7) ==> 2^(x-1)/8 usec ++ * max_pdu: max pdus allowed in ampdu ++ * dur: max duration of an ampdu (in msec) ++ * txpkt_weight: weight of ampdu in txfifo; reduces rate lag ++ * rx_factor: maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes ++ * ffpld_rsvd: number of bytes to reserve for preload ++ * max_txlen: max size of ampdu per mcs, bw and sgi ++ * mfbr: enable multiple fallback rate ++ * tx_max_funl: underflows should be kept such that ++ * (tx_max_funfl*underflows) < tx frames ++ * fifo_tb: table of fifo infos ++ */ ++struct ampdu_info { ++ struct brcms_c_info *wlc; ++ int scb_handle; ++ u8 ini_enable[AMPDU_MAX_SCB_TID]; ++ u8 ba_tx_wsize; ++ u8 ba_rx_wsize; ++ u8 retry_limit; ++ u8 rr_retry_limit; ++ u8 retry_limit_tid[AMPDU_MAX_SCB_TID]; ++ u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID]; ++ u8 mpdu_density; ++ s8 max_pdu; ++ u8 dur; ++ u8 txpkt_weight; ++ u8 rx_factor; ++ u32 ffpld_rsvd; ++ u32 max_txlen[MCS_TABLE_SIZE][2][2]; ++ bool mfbr; ++ u32 tx_max_funl; ++ struct brcms_fifo_info fifo_tb[NUM_FFPLD_FIFO]; ++}; ++ ++/* used for flushing ampdu packets */ ++struct cb_del_ampdu_pars { ++ struct ieee80211_sta *sta; ++ u16 tid; ++}; ++ ++static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur) ++{ ++ u32 rate, mcs; ++ ++ for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) { ++ /* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */ ++ /* 20MHz, No SGI */ ++ rate = mcs_2_rate(mcs, false, false); ++ ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3; ++ /* 40 MHz, No SGI */ ++ rate = mcs_2_rate(mcs, true, false); ++ ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3; ++ /* 20MHz, SGI */ ++ rate = mcs_2_rate(mcs, false, true); ++ ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3; ++ /* 40 MHz, SGI */ ++ rate = mcs_2_rate(mcs, true, true); ++ ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3; ++ } ++} ++ ++static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu) ++{ ++ if (BRCMS_PHY_11N_CAP(ampdu->wlc->band)) ++ return true; ++ else ++ return false; ++} ++ ++static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on) ++{ ++ struct brcms_c_info *wlc = ampdu->wlc; ++ ++ wlc->pub->_ampdu = false; ++ ++ if (on) { ++ if (!(wlc->pub->_n_enab & SUPPORT_11N)) { ++ wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not " ++ "nmode enabled\n", wlc->pub->unit); ++ return -ENOTSUPP; ++ } ++ if (!brcms_c_ampdu_cap(ampdu)) { ++ wiphy_err(ampdu->wlc->wiphy, "wl%d: device not " ++ "ampdu capable\n", wlc->pub->unit); ++ return -ENOTSUPP; ++ } ++ wlc->pub->_ampdu = on; ++ } ++ ++ return 0; ++} ++ ++static void brcms_c_ffpld_init(struct ampdu_info *ampdu) ++{ ++ int i, j; ++ struct brcms_fifo_info *fifo; ++ ++ for (j = 0; j < NUM_FFPLD_FIFO; j++) { ++ fifo = (ampdu->fifo_tb + j); ++ fifo->ampdu_pld_size = 0; ++ for (i = 0; i <= FFPLD_MAX_MCS; i++) ++ fifo->mcs2ampdu_table[i] = 255; ++ fifo->dmaxferrate = 0; ++ fifo->accum_txampdu = 0; ++ fifo->prev_txfunfl = 0; ++ fifo->accum_txfunfl = 0; ++ ++ } ++} ++ ++struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc) ++{ ++ struct ampdu_info *ampdu; ++ int i; ++ ++ ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC); ++ if (!ampdu) ++ return NULL; ++ ++ ampdu->wlc = wlc; ++ ++ for (i = 0; i < AMPDU_MAX_SCB_TID; i++) ++ ampdu->ini_enable[i] = true; ++ /* Disable ampdu for VO by default */ ++ ampdu->ini_enable[PRIO_8021D_VO] = false; ++ ampdu->ini_enable[PRIO_8021D_NC] = false; ++ ++ /* Disable ampdu for BK by default since not enough fifo space */ ++ ampdu->ini_enable[PRIO_8021D_NONE] = false; ++ ampdu->ini_enable[PRIO_8021D_BK] = false; ++ ++ ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE; ++ ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE; ++ ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY; ++ ampdu->max_pdu = AUTO; ++ ampdu->dur = AMPDU_MAX_DUR; ++ ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT; ++ ++ ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD; ++ /* ++ * bump max ampdu rcv size to 64k for all 11n ++ * devices except 4321A0 and 4321A1 ++ */ ++ if (BRCMS_ISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2)) ++ ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K; ++ else ++ ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_64K; ++ ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT; ++ ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT; ++ ++ for (i = 0; i < AMPDU_MAX_SCB_TID; i++) { ++ ampdu->retry_limit_tid[i] = ampdu->retry_limit; ++ ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit; ++ } ++ ++ brcms_c_scb_ampdu_update_max_txlen(ampdu, ampdu->dur); ++ ampdu->mfbr = false; ++ /* try to set ampdu to the default value */ ++ brcms_c_ampdu_set(ampdu, wlc->pub->_ampdu); ++ ++ ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL; ++ brcms_c_ffpld_init(ampdu); ++ ++ return ampdu; ++} ++ ++void brcms_c_ampdu_detach(struct ampdu_info *ampdu) ++{ ++ kfree(ampdu); ++} ++ ++static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu, ++ struct scb *scb) ++{ ++ struct scb_ampdu *scb_ampdu = &scb->scb_ampdu; ++ int i; ++ ++ scb_ampdu->max_pdu = AMPDU_NUM_MPDU; ++ ++ /* go back to legacy size if some preloading is occurring */ ++ for (i = 0; i < NUM_FFPLD_FIFO; i++) { ++ if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR) ++ scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY; ++ } ++ ++ /* apply user override */ ++ if (ampdu->max_pdu != AUTO) ++ scb_ampdu->max_pdu = (u8) ampdu->max_pdu; ++ ++ scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, ++ AMPDU_SCB_MAX_RELEASE); ++ ++ if (scb_ampdu->max_rx_ampdu_bytes) ++ scb_ampdu->release = min_t(u8, scb_ampdu->release, ++ scb_ampdu->max_rx_ampdu_bytes / 1600); ++ ++ scb_ampdu->release = min(scb_ampdu->release, ++ ampdu->fifo_tb[TX_AC_BE_FIFO]. ++ mcs2ampdu_table[FFPLD_MAX_MCS]); ++} ++ ++static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu) ++{ ++ brcms_c_scb_ampdu_update_config(ampdu, &du->wlc->pri_scb); ++} ++ ++static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f) ++{ ++ int i; ++ u32 phy_rate, dma_rate, tmp; ++ u8 max_mpdu; ++ struct brcms_fifo_info *fifo = (ampdu->fifo_tb + f); ++ ++ /* recompute the dma rate */ ++ /* note : we divide/multiply by 100 to avoid integer overflows */ ++ max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], ++ AMPDU_NUM_MPDU_LEGACY); ++ phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false); ++ dma_rate = ++ (((phy_rate / 100) * ++ (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size)) ++ / (max_mpdu * FFPLD_MPDU_SIZE)) * 100; ++ fifo->dmaxferrate = dma_rate; ++ ++ /* fill up the mcs2ampdu table; do not recalc the last mcs */ ++ dma_rate = dma_rate >> 7; ++ for (i = 0; i < FFPLD_MAX_MCS; i++) { ++ /* shifting to keep it within integer range */ ++ phy_rate = mcs_2_rate(i, true, false) >> 7; ++ if (phy_rate > dma_rate) { ++ tmp = ((fifo->ampdu_pld_size * phy_rate) / ++ ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1; ++ tmp = min_t(u32, tmp, 255); ++ fifo->mcs2ampdu_table[i] = (u8) tmp; ++ } ++ } ++} ++ ++/* evaluate the dma transfer rate using the tx underflows as feedback. ++ * If necessary, increase tx fifo preloading. If not enough, ++ * decrease maximum ampdu size for each mcs till underflows stop ++ * Return 1 if pre-loading not active, -1 if not an underflow event, ++ * 0 if pre-loading module took care of the event. ++ */ ++static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid) ++{ ++ struct ampdu_info *ampdu = wlc->ampdu; ++ u32 phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false); ++ u32 txunfl_ratio; ++ u8 max_mpdu; ++ u32 current_ampdu_cnt = 0; ++ u16 max_pld_size; ++ u32 new_txunfl; ++ struct brcms_fifo_info *fifo = (ampdu->fifo_tb + fid); ++ uint xmtfifo_sz; ++ u16 cur_txunfl; ++ ++ /* return if we got here for a different reason than underflows */ ++ cur_txunfl = brcms_b_read_shm(wlc->hw, ++ M_UCODE_MACSTAT + ++ offsetof(struct macstat, txfunfl[fid])); ++ new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl); ++ if (new_txunfl == 0) { ++ BCMMSG(wlc->wiphy, "TX status FRAG set but no tx underflows\n"); ++ return -1; ++ } ++ fifo->prev_txfunfl = cur_txunfl; ++ ++ if (!ampdu->tx_max_funl) ++ return 1; ++ ++ /* check if fifo is big enough */ ++ if (brcms_b_xmtfifo_sz_get(wlc->hw, fid, &xmtfifo_sz)) ++ return -1; ++ ++ if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd) ++ return 1; ++ ++ max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd; ++ fifo->accum_txfunfl += new_txunfl; ++ ++ /* we need to wait for at least 10 underflows */ ++ if (fifo->accum_txfunfl < 10) ++ return 0; ++ ++ BCMMSG(wlc->wiphy, "ampdu_count %d tx_underflows %d\n", ++ current_ampdu_cnt, fifo->accum_txfunfl); ++ ++ /* ++ compute the current ratio of tx unfl per ampdu. ++ When the current ampdu count becomes too ++ big while the ratio remains small, we reset ++ the current count in order to not ++ introduce too big of a latency in detecting a ++ large amount of tx underflows later. ++ */ ++ ++ txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl; ++ ++ if (txunfl_ratio > ampdu->tx_max_funl) { ++ if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) ++ fifo->accum_txfunfl = 0; ++ ++ return 0; ++ } ++ max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], ++ AMPDU_NUM_MPDU_LEGACY); ++ ++ /* In case max value max_pdu is already lower than ++ the fifo depth, there is nothing more we can do. ++ */ ++ ++ if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) { ++ fifo->accum_txfunfl = 0; ++ return 0; ++ } ++ ++ if (fifo->ampdu_pld_size < max_pld_size) { ++ ++ /* increment by TX_FIFO_PLD_INC bytes */ ++ fifo->ampdu_pld_size += FFPLD_PLD_INCR; ++ if (fifo->ampdu_pld_size > max_pld_size) ++ fifo->ampdu_pld_size = max_pld_size; ++ ++ /* update scb release size */ ++ brcms_c_scb_ampdu_update_config_all(ampdu); ++ ++ /* ++ * compute a new dma xfer rate for max_mpdu @ max mcs. ++ * This is the minimum dma rate that can achieve no ++ * underflow condition for the current mpdu size. ++ * ++ * note : we divide/multiply by 100 to avoid integer overflows ++ */ ++ fifo->dmaxferrate = ++ (((phy_rate / 100) * ++ (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size)) ++ / (max_mpdu * FFPLD_MPDU_SIZE)) * 100; ++ ++ BCMMSG(wlc->wiphy, "DMA estimated transfer rate %d; " ++ "pre-load size %d\n", ++ fifo->dmaxferrate, fifo->ampdu_pld_size); ++ } else { ++ ++ /* decrease ampdu size */ ++ if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) { ++ if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255) ++ fifo->mcs2ampdu_table[FFPLD_MAX_MCS] = ++ AMPDU_NUM_MPDU_LEGACY - 1; ++ else ++ fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1; ++ ++ /* recompute the table */ ++ brcms_c_ffpld_calc_mcs2ampdu_table(ampdu, fid); ++ ++ /* update scb release size */ ++ brcms_c_scb_ampdu_update_config_all(ampdu); ++ } ++ } ++ fifo->accum_txfunfl = 0; ++ return 0; ++} ++ ++void ++brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, ++ u8 ba_wsize, /* negotiated ba window size (in pdu) */ ++ uint max_rx_ampdu_bytes) /* from ht_cap in beacon */ ++{ ++ struct scb_ampdu *scb_ampdu; ++ struct scb_ampdu_tid_ini *ini; ++ struct ampdu_info *ampdu = wlc->ampdu; ++ struct scb *scb = &wlc->pri_scb; ++ scb_ampdu = &scb->scb_ampdu; ++ ++ if (!ampdu->ini_enable[tid]) { ++ wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n", ++ __func__, tid); ++ return; ++ } ++ ++ ini = &scb_ampdu->ini[tid]; ++ ini->tid = tid; ++ ini->scb = scb_ampdu->scb; ++ ini->ba_wsize = ba_wsize; ++ scb_ampdu->max_rx_ampdu_bytes = max_rx_ampdu_bytes; ++} ++ ++int ++brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi, ++ struct sk_buff **pdu, int prec) ++{ ++ struct brcms_c_info *wlc; ++ struct sk_buff *p, *pkt[AMPDU_MAX_MPDU]; ++ u8 tid, ndelim; ++ int err = 0; ++ u8 preamble_type = BRCMS_GF_PREAMBLE; ++ u8 fbr_preamble_type = BRCMS_GF_PREAMBLE; ++ u8 rts_preamble_type = BRCMS_LONG_PREAMBLE; ++ u8 rts_fbr_preamble_type = BRCMS_LONG_PREAMBLE; ++ ++ bool rr = true, fbr = false; ++ uint i, count = 0, fifo, seg_cnt = 0; ++ u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0; ++ u32 ampdu_len, max_ampdu_bytes = 0; ++ struct d11txh *txh = NULL; ++ u8 *plcp; ++ struct ieee80211_hdr *h; ++ struct scb *scb; ++ struct scb_ampdu *scb_ampdu; ++ struct scb_ampdu_tid_ini *ini; ++ u8 mcs = 0; ++ bool use_rts = false, use_cts = false; ++ u32 rspec = 0, rspec_fallback = 0; ++ u32 rts_rspec = 0, rts_rspec_fallback = 0; ++ u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ; ++ struct ieee80211_rts *rts; ++ u8 rr_retry_limit; ++ struct brcms_fifo_info *f; ++ bool fbr_iscck; ++ struct ieee80211_tx_info *tx_info; ++ u16 qlen; ++ struct wiphy *wiphy; ++ ++ wlc = ampdu->wlc; ++ wiphy = wlc->wiphy; ++ p = *pdu; ++ ++ tid = (u8) (p->priority); ++ ++ f = ampdu->fifo_tb + prio2fifo[tid]; ++ ++ scb = &wlc->pri_scb; ++ scb_ampdu = &scb->scb_ampdu; ++ ini = &scb_ampdu->ini[tid]; ++ ++ /* Let pressure continue to build ... */ ++ qlen = pktq_plen(&qi->q, prec); ++ if (ini->tx_in_transit > 0 && ++ qlen < min(scb_ampdu->max_pdu, ini->ba_wsize)) ++ /* Collect multiple MPDU's to be sent in the next AMPDU */ ++ return -EBUSY; ++ ++ /* at this point we intend to transmit an AMPDU */ ++ rr_retry_limit = ampdu->rr_retry_limit_tid[tid]; ++ ampdu_len = 0; ++ dma_len = 0; ++ while (p) { ++ struct ieee80211_tx_rate *txrate; ++ ++ tx_info = IEEE80211_SKB_CB(p); ++ txrate = tx_info->status.rates; ++ ++ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { ++ err = brcms_c_prep_pdu(wlc, p, &fifo); ++ } else { ++ wiphy_err(wiphy, "%s: AMPDU flag is off!\n", __func__); ++ *pdu = NULL; ++ err = 0; ++ break; ++ } ++ ++ if (err) { ++ if (err == -EBUSY) { ++ wiphy_err(wiphy, "wl%d: sendampdu: " ++ "prep_xdu retry; seq 0x%x\n", ++ wlc->pub->unit, seq); ++ *pdu = p; ++ break; ++ } ++ ++ /* error in the packet; reject it */ ++ wiphy_err(wiphy, "wl%d: sendampdu: prep_xdu " ++ "rejected; seq 0x%x\n", wlc->pub->unit, seq); ++ *pdu = NULL; ++ break; ++ } ++ ++ /* pkt is good to be aggregated */ ++ txh = (struct d11txh *) p->data; ++ plcp = (u8 *) (txh + 1); ++ h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN); ++ seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT; ++ index = TX_SEQ_TO_INDEX(seq); ++ ++ /* check mcl fields and test whether it can be agg'd */ ++ mcl = le16_to_cpu(txh->MacTxControlLow); ++ mcl &= ~TXC_AMPDU_MASK; ++ fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3); ++ txh->PreloadSize = 0; /* always default to 0 */ ++ ++ /* Handle retry limits */ ++ if (txrate[0].count <= rr_retry_limit) { ++ txrate[0].count++; ++ rr = true; ++ fbr = false; ++ } else { ++ fbr = true; ++ rr = false; ++ txrate[1].count++; ++ } ++ ++ /* extract the length info */ ++ len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) ++ : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback); ++ ++ /* retrieve null delimiter count */ ++ ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM]; ++ seg_cnt += 1; ++ ++ BCMMSG(wlc->wiphy, "wl%d: mpdu %d plcp_len %d\n", ++ wlc->pub->unit, count, len); ++ ++ /* ++ * aggregateable mpdu. For ucode/hw agg, ++ * test whether need to break or change the epoch ++ */ ++ if (count == 0) { ++ mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT); ++ /* refill the bits since might be a retx mpdu */ ++ mcl |= TXC_STARTMSDU; ++ rts = (struct ieee80211_rts *)&txh->rts_frame; ++ ++ if (ieee80211_is_rts(rts->frame_control)) { ++ mcl |= TXC_SENDRTS; ++ use_rts = true; ++ } ++ if (ieee80211_is_cts(rts->frame_control)) { ++ mcl |= TXC_SENDCTS; ++ use_cts = true; ++ } ++ } else { ++ mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT); ++ mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS); ++ } ++ ++ len = roundup(len, 4); ++ ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN); ++ ++ dma_len += (u16) brcmu_pkttotlen(p); ++ ++ BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d" ++ " seg_cnt %d null delim %d\n", ++ wlc->pub->unit, ampdu_len, seg_cnt, ndelim); ++ ++ txh->MacTxControlLow = cpu_to_le16(mcl); ++ ++ /* this packet is added */ ++ pkt[count++] = p; ++ ++ /* patch the first MPDU */ ++ if (count == 1) { ++ u8 plcp0, plcp3, is40, sgi; ++ struct ieee80211_sta *sta; ++ ++ sta = tx_info->control.sta; ++ ++ if (rr) { ++ plcp0 = plcp[0]; ++ plcp3 = plcp[3]; ++ } else { ++ plcp0 = txh->FragPLCPFallback[0]; ++ plcp3 = txh->FragPLCPFallback[3]; ++ ++ } ++ is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0; ++ sgi = plcp3_issgi(plcp3) ? 1 : 0; ++ mcs = plcp0 & ~MIMO_PLCP_40MHZ; ++ max_ampdu_bytes = ++ min(scb_ampdu->max_rx_ampdu_bytes, ++ ampdu->max_txlen[mcs][is40][sgi]); ++ ++ if (is40) ++ mimo_ctlchbw = ++ CHSPEC_SB_UPPER(wlc_phy_chanspec_get( ++ wlc->band->pi)) ++ ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ; ++ ++ /* rebuild the rspec and rspec_fallback */ ++ rspec = RSPEC_MIMORATE; ++ rspec |= plcp[0] & ~MIMO_PLCP_40MHZ; ++ if (plcp[0] & MIMO_PLCP_40MHZ) ++ rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT); ++ ++ if (fbr_iscck) /* CCK */ ++ rspec_fallback = cck_rspec(cck_phy2mac_rate ++ (txh->FragPLCPFallback[0])); ++ else { /* MIMO */ ++ rspec_fallback = RSPEC_MIMORATE; ++ rspec_fallback |= ++ txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ; ++ if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ) ++ rspec_fallback |= ++ (PHY_TXC1_BW_40MHZ << ++ RSPEC_BW_SHIFT); ++ } ++ ++ if (use_rts || use_cts) { ++ rts_rspec = ++ brcms_c_rspec_to_rts_rspec(wlc, ++ rspec, false, mimo_ctlchbw); ++ rts_rspec_fallback = ++ brcms_c_rspec_to_rts_rspec(wlc, ++ rspec_fallback, false, mimo_ctlchbw); ++ } ++ } ++ ++ /* if (first mpdu for host agg) */ ++ /* test whether to add more */ ++ if ((mcs_2_rate(mcs, true, false) >= f->dmaxferrate) && ++ (count == f->mcs2ampdu_table[mcs])) { ++ BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping" ++ " ampdu at %d for mcs %d\n", ++ wlc->pub->unit, count, mcs); ++ break; ++ } ++ ++ if (count == scb_ampdu->max_pdu) ++ break; ++ ++ /* ++ * check to see if the next pkt is ++ * a candidate for aggregation ++ */ ++ p = pktq_ppeek(&qi->q, prec); ++ /* tx_info must be checked with current p */ ++ tx_info = IEEE80211_SKB_CB(p); ++ ++ if (p) { ++ if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && ++ ((u8) (p->priority) == tid)) { ++ ++ plen = brcmu_pkttotlen(p) + ++ AMPDU_MAX_MPDU_OVERHEAD; ++ plen = max(scb_ampdu->min_len, plen); ++ ++ if ((plen + ampdu_len) > max_ampdu_bytes) { ++ p = NULL; ++ continue; ++ } ++ ++ /* ++ * check if there are enough ++ * descriptors available ++ */ ++ if (*wlc->core->txavail[fifo] <= seg_cnt + 1) { ++ wiphy_err(wiphy, "%s: No fifo space " ++ "!!\n", __func__); ++ p = NULL; ++ continue; ++ } ++ p = brcmu_pktq_pdeq(&qi->q, prec); ++ } else { ++ p = NULL; ++ } ++ } ++ } /* end while(p) */ ++ ++ ini->tx_in_transit += count; ++ ++ if (count) { ++ /* patch up the last txh */ ++ txh = (struct d11txh *) pkt[count - 1]->data; ++ mcl = le16_to_cpu(txh->MacTxControlLow); ++ mcl &= ~TXC_AMPDU_MASK; ++ mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT); ++ txh->MacTxControlLow = cpu_to_le16(mcl); ++ ++ /* remove the null delimiter after last mpdu */ ++ ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM]; ++ txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0; ++ ampdu_len -= ndelim * AMPDU_DELIMITER_LEN; ++ ++ /* remove the pad len from last mpdu */ ++ fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0); ++ len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) ++ : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback); ++ ampdu_len -= roundup(len, 4) - len; ++ ++ /* patch up the first txh & plcp */ ++ txh = (struct d11txh *) pkt[0]->data; ++ plcp = (u8 *) (txh + 1); ++ ++ BRCMS_SET_MIMO_PLCP_LEN(plcp, ampdu_len); ++ /* mark plcp to indicate ampdu */ ++ BRCMS_SET_MIMO_PLCP_AMPDU(plcp); ++ ++ /* reset the mixed mode header durations */ ++ if (txh->MModeLen) { ++ u16 mmodelen = ++ brcms_c_calc_lsig_len(wlc, rspec, ampdu_len); ++ txh->MModeLen = cpu_to_le16(mmodelen); ++ preamble_type = BRCMS_MM_PREAMBLE; ++ } ++ if (txh->MModeFbrLen) { ++ u16 mmfbrlen = ++ brcms_c_calc_lsig_len(wlc, rspec_fallback, ++ ampdu_len); ++ txh->MModeFbrLen = cpu_to_le16(mmfbrlen); ++ fbr_preamble_type = BRCMS_MM_PREAMBLE; ++ } ++ ++ /* set the preload length */ ++ if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) { ++ dma_len = min(dma_len, f->ampdu_pld_size); ++ txh->PreloadSize = cpu_to_le16(dma_len); ++ } else ++ txh->PreloadSize = 0; ++ ++ mch = le16_to_cpu(txh->MacTxControlHigh); ++ ++ /* update RTS dur fields */ ++ if (use_rts || use_cts) { ++ u16 durid; ++ rts = (struct ieee80211_rts *)&txh->rts_frame; ++ if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) == ++ TXC_PREAMBLE_RTS_MAIN_SHORT) ++ rts_preamble_type = BRCMS_SHORT_PREAMBLE; ++ ++ if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) == ++ TXC_PREAMBLE_RTS_FB_SHORT) ++ rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE; ++ ++ durid = ++ brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec, ++ rspec, rts_preamble_type, ++ preamble_type, ampdu_len, ++ true); ++ rts->duration = cpu_to_le16(durid); ++ durid = brcms_c_compute_rtscts_dur(wlc, use_cts, ++ rts_rspec_fallback, ++ rspec_fallback, ++ rts_fbr_preamble_type, ++ fbr_preamble_type, ++ ampdu_len, true); ++ txh->RTSDurFallback = cpu_to_le16(durid); ++ /* set TxFesTimeNormal */ ++ txh->TxFesTimeNormal = rts->duration; ++ /* set fallback rate version of TxFesTimeNormal */ ++ txh->TxFesTimeFallback = txh->RTSDurFallback; ++ } ++ ++ /* set flag and plcp for fallback rate */ ++ if (fbr) { ++ mch |= TXC_AMPDU_FBR; ++ txh->MacTxControlHigh = cpu_to_le16(mch); ++ BRCMS_SET_MIMO_PLCP_AMPDU(plcp); ++ BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback); ++ } ++ ++ BCMMSG(wlc->wiphy, "wl%d: count %d ampdu_len %d\n", ++ wlc->pub->unit, count, ampdu_len); ++ ++ /* inform rate_sel if it this is a rate probe pkt */ ++ frameid = le16_to_cpu(txh->TxFrameID); ++ if (frameid & TXFID_RATE_PROBE_MASK) ++ wiphy_err(wiphy, "%s: XXX what to do with " ++ "TXFID_RATE_PROBE_MASK!?\n", __func__); ++ ++ for (i = 0; i < count; i++) ++ brcms_c_txfifo(wlc, fifo, pkt[i], i == (count - 1), ++ ampdu->txpkt_weight); ++ ++ } ++ /* endif (count) */ ++ return err; ++} ++ ++static void ++brcms_c_ampdu_rate_status(struct brcms_c_info *wlc, ++ struct ieee80211_tx_info *tx_info, ++ struct tx_status *txs, u8 mcs) ++{ ++ struct ieee80211_tx_rate *txrate = tx_info->status.rates; ++ int i; ++ ++ /* clear the rest of the rates */ ++ for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) { ++ txrate[i].idx = -1; ++ txrate[i].count = 0; ++ } ++} ++ ++static void ++brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, ++ struct sk_buff *p, struct tx_status *txs, ++ u32 s1, u32 s2) ++{ ++ struct scb_ampdu *scb_ampdu; ++ struct brcms_c_info *wlc = ampdu->wlc; ++ struct scb_ampdu_tid_ini *ini; ++ u8 bitmap[8], queue, tid; ++ struct d11txh *txh; ++ u8 *plcp; ++ struct ieee80211_hdr *h; ++ u16 seq, start_seq = 0, bindex, index, mcl; ++ u8 mcs = 0; ++ bool ba_recd = false, ack_recd = false; ++ u8 suc_mpdu = 0, tot_mpdu = 0; ++ uint supr_status; ++ bool update_rate = true, retry = true, tx_error = false; ++ u16 mimoantsel = 0; ++ u8 antselid = 0; ++ u8 retry_limit, rr_retry_limit; ++ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p); ++ struct wiphy *wiphy = wlc->wiphy; ++ ++#ifdef BCMDBG ++ u8 hole[AMPDU_MAX_MPDU]; ++ memset(hole, 0, sizeof(hole)); ++#endif ++ ++ scb_ampdu = &scb->scb_ampdu; ++ tid = (u8) (p->priority); ++ ++ ini = &scb_ampdu->ini[tid]; ++ retry_limit = ampdu->retry_limit_tid[tid]; ++ rr_retry_limit = ampdu->rr_retry_limit_tid[tid]; ++ memset(bitmap, 0, sizeof(bitmap)); ++ queue = txs->frameid & TXFID_QUEUE_MASK; ++ supr_status = txs->status & TX_STATUS_SUPR_MASK; ++ ++ if (txs->status & TX_STATUS_ACK_RCV) { ++ if (TX_STATUS_SUPR_UF == supr_status) ++ update_rate = false; ++ ++ WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE)); ++ start_seq = txs->sequence >> SEQNUM_SHIFT; ++ bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >> ++ TX_STATUS_BA_BMAP03_SHIFT; ++ ++ WARN_ON(s1 & TX_STATUS_INTERMEDIATE); ++ WARN_ON(!(s1 & TX_STATUS_AMPDU)); ++ ++ bitmap[0] |= ++ (s1 & TX_STATUS_BA_BMAP47_MASK) << ++ TX_STATUS_BA_BMAP47_SHIFT; ++ bitmap[1] = (s1 >> 8) & 0xff; ++ bitmap[2] = (s1 >> 16) & 0xff; ++ bitmap[3] = (s1 >> 24) & 0xff; ++ ++ bitmap[4] = s2 & 0xff; ++ bitmap[5] = (s2 >> 8) & 0xff; ++ bitmap[6] = (s2 >> 16) & 0xff; ++ bitmap[7] = (s2 >> 24) & 0xff; ++ ++ ba_recd = true; ++ } else { ++ if (supr_status) { ++ update_rate = false; ++ if (supr_status == TX_STATUS_SUPR_BADCH) { ++ wiphy_err(wiphy, "%s: Pkt tx suppressed, " ++ "illegal channel possibly %d\n", ++ __func__, CHSPEC_CHANNEL( ++ wlc->default_bss->chanspec)); ++ } else { ++ if (supr_status != TX_STATUS_SUPR_FRAG) ++ wiphy_err(wiphy, "%s:" ++ "supr_status 0x%x\n", ++ __func__, supr_status); ++ } ++ /* no need to retry for badch; will fail again */ ++ if (supr_status == TX_STATUS_SUPR_BADCH || ++ supr_status == TX_STATUS_SUPR_EXPTIME) { ++ retry = false; ++ } else if (supr_status == TX_STATUS_SUPR_EXPTIME) { ++ /* TX underflow: ++ * try tuning pre-loading or ampdu size ++ */ ++ } else if (supr_status == TX_STATUS_SUPR_FRAG) { ++ /* ++ * if there were underflows, but pre-loading ++ * is not active, notify rate adaptation. ++ */ ++ if (brcms_c_ffpld_check_txfunfl(wlc, ++ prio2fifo[tid]) > 0) ++ tx_error = true; ++ } ++ } else if (txs->phyerr) { ++ update_rate = false; ++ wiphy_err(wiphy, "wl%d: ampdu tx phy " ++ "error (0x%x)\n", wlc->pub->unit, ++ txs->phyerr); ++ ++ if (brcm_msg_level & LOG_ERROR_VAL) { ++ brcmu_prpkt("txpkt (AMPDU)", p); ++ brcms_c_print_txdesc((struct d11txh *) p->data); ++ } ++ brcms_c_print_txstatus(txs); ++ } ++ } ++ ++ /* loop through all pkts and retry if not acked */ ++ while (p) { ++ tx_info = IEEE80211_SKB_CB(p); ++ txh = (struct d11txh *) p->data; ++ mcl = le16_to_cpu(txh->MacTxControlLow); ++ plcp = (u8 *) (txh + 1); ++ h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN); ++ seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT; ++ ++ if (tot_mpdu == 0) { ++ mcs = plcp[0] & MIMO_PLCP_MCS_MASK; ++ mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel); ++ } ++ ++ index = TX_SEQ_TO_INDEX(seq); ++ ack_recd = false; ++ if (ba_recd) { ++ bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX); ++ BCMMSG(wlc->wiphy, "tid %d seq %d," ++ " start_seq %d, bindex %d set %d, index %d\n", ++ tid, seq, start_seq, bindex, ++ isset(bitmap, bindex), index); ++ /* if acked then clear bit and free packet */ ++ if ((bindex < AMPDU_TX_BA_MAX_WSIZE) ++ && isset(bitmap, bindex)) { ++ ini->tx_in_transit--; ++ ini->txretry[index] = 0; ++ ++ /* ++ * ampdu_ack_len: ++ * number of acked aggregated frames ++ */ ++ /* ampdu_len: number of aggregated frames */ ++ brcms_c_ampdu_rate_status(wlc, tx_info, txs, ++ mcs); ++ tx_info->flags |= IEEE80211_TX_STAT_ACK; ++ tx_info->flags |= IEEE80211_TX_STAT_AMPDU; ++ tx_info->status.ampdu_ack_len = ++ tx_info->status.ampdu_len = 1; ++ ++ skb_pull(p, D11_PHY_HDR_LEN); ++ skb_pull(p, D11_TXH_LEN); ++ ++ ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, ++ p); ++ ack_recd = true; ++ suc_mpdu++; ++ } ++ } ++ /* either retransmit or send bar if ack not recd */ ++ if (!ack_recd) { ++ struct ieee80211_tx_rate *txrate = ++ tx_info->status.rates; ++ if (retry && (txrate[0].count < (int)retry_limit)) { ++ ini->txretry[index]++; ++ ini->tx_in_transit--; ++ /* ++ * Use high prededence for retransmit to ++ * give some punch ++ */ ++ /* brcms_c_txq_enq(wlc, scb, p, ++ * BRCMS_PRIO_TO_PREC(tid)); */ ++ brcms_c_txq_enq(wlc, scb, p, ++ BRCMS_PRIO_TO_HI_PREC(tid)); ++ } else { ++ /* Retry timeout */ ++ ini->tx_in_transit--; ++ ieee80211_tx_info_clear_status(tx_info); ++ tx_info->status.ampdu_ack_len = 0; ++ tx_info->status.ampdu_len = 1; ++ tx_info->flags |= ++ IEEE80211_TX_STAT_AMPDU_NO_BACK; ++ skb_pull(p, D11_PHY_HDR_LEN); ++ skb_pull(p, D11_TXH_LEN); ++ wiphy_err(wiphy, "%s: BA Timeout, seq %d, in_" ++ "transit %d\n", "AMPDU status", seq, ++ ini->tx_in_transit); ++ ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, ++ p); ++ } ++ } ++ tot_mpdu++; ++ ++ /* break out if last packet of ampdu */ ++ if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) == ++ TXC_AMPDU_LAST) ++ break; ++ ++ p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED); ++ } ++ brcms_c_send_q(wlc); ++ ++ /* update rate state */ ++ antselid = brcms_c_antsel_antsel2id(wlc->asi, mimoantsel); ++ ++ brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight); ++} ++ ++void ++brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb, ++ struct sk_buff *p, struct tx_status *txs) ++{ ++ struct scb_ampdu *scb_ampdu; ++ struct brcms_c_info *wlc = ampdu->wlc; ++ struct scb_ampdu_tid_ini *ini; ++ u32 s1 = 0, s2 = 0; ++ struct ieee80211_tx_info *tx_info; ++ ++ tx_info = IEEE80211_SKB_CB(p); ++ ++ /* BMAC_NOTE: For the split driver, second level txstatus comes later ++ * So if the ACK was received then wait for the second level else just ++ * call the first one ++ */ ++ if (txs->status & TX_STATUS_ACK_RCV) { ++ u8 status_delay = 0; ++ ++ /* wait till the next 8 bytes of txstatus is available */ ++ while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) { ++ udelay(1); ++ status_delay++; ++ if (status_delay > 10) ++ return; /* error condition */ ++ } ++ ++ s2 = R_REG(&wlc->regs->frmtxstatus2); ++ } ++ ++ if (scb) { ++ scb_ampdu = &scb->scb_ampdu; ++ ini = &scb_ampdu->ini[p->priority]; ++ brcms_c_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2); ++ } else { ++ /* loop through all pkts and free */ ++ u8 queue = txs->frameid & TXFID_QUEUE_MASK; ++ struct d11txh *txh; ++ u16 mcl; ++ while (p) { ++ tx_info = IEEE80211_SKB_CB(p); ++ txh = (struct d11txh *) p->data; ++ mcl = le16_to_cpu(txh->MacTxControlLow); ++ brcmu_pkt_buf_free_skb(p); ++ /* break out if last packet of ampdu */ ++ if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) == ++ TXC_AMPDU_LAST) ++ break; ++ p = dma_getnexttxp(wlc->hw->di[queue], ++ DMA_RANGE_TRANSMITTED); ++ } ++ brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight); ++ } ++} ++ ++void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc) ++{ ++ char template[T_RAM_ACCESS_SZ * 2]; ++ ++ /* driver needs to write the ta in the template; ta is at offset 16 */ ++ memset(template, 0, sizeof(template)); ++ memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN); ++ brcms_b_write_template_ram(wlc->hw, (T_BA_TPL_BASE + 16), ++ (T_RAM_ACCESS_SZ * 2), ++ template); ++} ++ ++bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid) ++{ ++ return wlc->ampdu->ini_enable[tid]; ++} ++ ++void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu) ++{ ++ struct brcms_c_info *wlc = ampdu->wlc; ++ ++ /* ++ * Extend ucode internal watchdog timer to ++ * match larger received frames ++ */ ++ if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) == ++ IEEE80211_HT_MAX_AMPDU_64K) { ++ brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX); ++ brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX); ++ } else { ++ brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF); ++ brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF); ++ } ++} ++ ++/* ++ * callback function that helps flushing ampdu packets from a priority queue ++ */ ++static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a) ++{ ++ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu); ++ struct cb_del_ampdu_pars *ampdu_pars = ++ (struct cb_del_ampdu_pars *)arg_a; ++ bool rc; ++ ++ rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false; ++ rc = rc && (tx_info->control.sta == NULL || ampdu_pars->sta == NULL || ++ tx_info->control.sta == ampdu_pars->sta); ++ rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid); ++ return rc; ++} ++ ++/* ++ * callback function that helps invalidating ampdu packets in a DMA queue ++ */ ++static void dma_cb_fn_ampdu(void *txi, void *arg_a) ++{ ++ struct ieee80211_sta *sta = arg_a; ++ struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi; ++ ++ if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && ++ (tx_info->control.sta == sta || sta == NULL)) ++ tx_info->control.sta = NULL; ++} ++ ++/* ++ * When a remote party is no longer available for ampdu communication, any ++ * pending tx ampdu packets in the driver have to be flushed. ++ */ ++void brcms_c_ampdu_flush(struct brcms_c_info *wlc, ++ struct ieee80211_sta *sta, u16 tid) ++{ ++ struct brcms_txq_info *qi = wlc->pkt_queue; ++ struct pktq *pq = &qi->q; ++ int prec; ++ struct cb_del_ampdu_pars ampdu_pars; ++ ++ ampdu_pars.sta = sta; ++ ampdu_pars.tid = tid; ++ for (prec = 0; prec < pq->num_prec; prec++) ++ brcmu_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt, ++ (void *)&du_pars); ++ brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h.orig 2011-11-09 13:46:58.240800696 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h 2011-11-09 13:47:16.992566265 -0500 +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_AMPDU_H_ ++#define _BRCM_AMPDU_H_ ++ ++extern struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc); ++extern void brcms_c_ampdu_detach(struct ampdu_info *ampdu); ++extern int brcms_c_sendampdu(struct ampdu_info *ampdu, ++ struct brcms_txq_info *qi, ++ struct sk_buff **aggp, int prec); ++extern void brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb, ++ struct sk_buff *p, struct tx_status *txs); ++extern void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc); ++extern void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu); ++ ++#endif /* _BRCM_AMPDU_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.c.orig 2011-11-09 13:46:58.240800696 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.c 2011-11-09 13:47:16.992566265 -0500 +@@ -0,0 +1,307 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include "types.h" ++#include "main.h" ++#include "phy_shim.h" ++#include "antsel.h" ++ ++#define ANT_SELCFG_AUTO 0x80 /* bit indicates antenna sel AUTO */ ++#define ANT_SELCFG_MASK 0x33 /* antenna configuration mask */ ++#define ANT_SELCFG_TX_UNICAST 0 /* unicast tx antenna configuration */ ++#define ANT_SELCFG_RX_UNICAST 1 /* unicast rx antenna configuration */ ++#define ANT_SELCFG_TX_DEF 2 /* default tx antenna configuration */ ++#define ANT_SELCFG_RX_DEF 3 /* default rx antenna configuration */ ++ ++/* useful macros */ ++#define BRCMS_ANTSEL_11N_0(ant) ((((ant) & ANT_SELCFG_MASK) >> 4) & 0xf) ++#define BRCMS_ANTSEL_11N_1(ant) (((ant) & ANT_SELCFG_MASK) & 0xf) ++#define BRCMS_ANTIDX_11N(ant) (((BRCMS_ANTSEL_11N_0(ant)) << 2) +\ ++ (BRCMS_ANTSEL_11N_1(ant))) ++#define BRCMS_ANT_ISAUTO_11N(ant) (((ant) & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO) ++#define BRCMS_ANTSEL_11N(ant) ((ant) & ANT_SELCFG_MASK) ++ ++/* antenna switch */ ++/* defines for no boardlevel antenna diversity */ ++#define ANT_SELCFG_DEF_2x2 0x01 /* default antenna configuration */ ++ ++/* 2x3 antdiv defines and tables for GPIO communication */ ++#define ANT_SELCFG_NUM_2x3 3 ++#define ANT_SELCFG_DEF_2x3 0x01 /* default antenna configuration */ ++ ++/* 2x4 antdiv rev4 defines and tables for GPIO communication */ ++#define ANT_SELCFG_NUM_2x4 4 ++#define ANT_SELCFG_DEF_2x4 0x02 /* default antenna configuration */ ++ ++static const u16 mimo_2x4_div_antselpat_tbl[] = { ++ 0, 0, 0x9, 0xa, /* ant0: 0 ant1: 2,3 */ ++ 0, 0, 0x5, 0x6, /* ant0: 1 ant1: 2,3 */ ++ 0, 0, 0, 0, /* n.a. */ ++ 0, 0, 0, 0 /* n.a. */ ++}; ++ ++static const u8 mimo_2x4_div_antselid_tbl[16] = { ++ 0, 0, 0, 0, 0, 2, 3, 0, ++ 0, 0, 1, 0, 0, 0, 0, 0 /* pat to antselid */ ++}; ++ ++static const u16 mimo_2x3_div_antselpat_tbl[] = { ++ 16, 0, 1, 16, /* ant0: 0 ant1: 1,2 */ ++ 16, 16, 16, 16, /* n.a. */ ++ 16, 2, 16, 16, /* ant0: 2 ant1: 1 */ ++ 16, 16, 16, 16 /* n.a. */ ++}; ++ ++static const u8 mimo_2x3_div_antselid_tbl[16] = { ++ 0, 1, 2, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0 /* pat to antselid */ ++}; ++ ++/* boardlevel antenna selection: init antenna selection structure */ ++static void ++brcms_c_antsel_init_cfg(struct antsel_info *asi, struct brcms_antselcfg *antsel, ++ bool auto_sel) ++{ ++ if (asi->antsel_type == ANTSEL_2x3) { ++ u8 antcfg_def = ANT_SELCFG_DEF_2x3 | ++ ((asi->antsel_avail && auto_sel) ? ANT_SELCFG_AUTO : 0); ++ antsel->ant_config[ANT_SELCFG_TX_DEF] = antcfg_def; ++ antsel->ant_config[ANT_SELCFG_TX_UNICAST] = antcfg_def; ++ antsel->ant_config[ANT_SELCFG_RX_DEF] = antcfg_def; ++ antsel->ant_config[ANT_SELCFG_RX_UNICAST] = antcfg_def; ++ antsel->num_antcfg = ANT_SELCFG_NUM_2x3; ++ ++ } else if (asi->antsel_type == ANTSEL_2x4) { ++ ++ antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x4; ++ antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x4; ++ antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x4; ++ antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x4; ++ antsel->num_antcfg = ANT_SELCFG_NUM_2x4; ++ ++ } else { /* no antenna selection available */ ++ ++ antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x2; ++ antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x2; ++ antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x2; ++ antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x2; ++ antsel->num_antcfg = 0; ++ } ++} ++ ++struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc) ++{ ++ struct antsel_info *asi; ++ struct si_pub *sih = wlc->hw->sih; ++ ++ asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC); ++ if (!asi) ++ return NULL; ++ ++ asi->wlc = wlc; ++ asi->pub = wlc->pub; ++ asi->antsel_type = ANTSEL_NA; ++ asi->antsel_avail = false; ++ asi->antsel_antswitch = (u8) getintvar(sih, BRCMS_SROM_ANTSWITCH); ++ ++ if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) { ++ switch (asi->antsel_antswitch) { ++ case ANTSWITCH_TYPE_1: ++ case ANTSWITCH_TYPE_2: ++ case ANTSWITCH_TYPE_3: ++ /* 4321/2 board with 2x3 switch logic */ ++ asi->antsel_type = ANTSEL_2x3; ++ /* Antenna selection availability */ ++ if (((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) || ++ ((u16) getintvar(sih, BRCMS_SROM_AA5G) == 7)) { ++ asi->antsel_avail = true; ++ } else if ( ++ (u16) getintvar(sih, BRCMS_SROM_AA2G) == 3 || ++ (u16) getintvar(sih, BRCMS_SROM_AA5G) == 3) { ++ asi->antsel_avail = false; ++ } else { ++ asi->antsel_avail = false; ++ wiphy_err(wlc->wiphy, "antsel_attach: 2o3 " ++ "board cfg invalid\n"); ++ } ++ ++ break; ++ default: ++ break; ++ } ++ } else if ((asi->pub->sromrev == 4) && ++ ((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) && ++ ((u16) getintvar(sih, BRCMS_SROM_AA5G) == 0)) { ++ /* hack to match old 4321CB2 cards with 2of3 antenna switch */ ++ asi->antsel_type = ANTSEL_2x3; ++ asi->antsel_avail = true; ++ } else if (asi->pub->boardflags2 & BFL2_2X4_DIV) { ++ asi->antsel_type = ANTSEL_2x4; ++ asi->antsel_avail = true; ++ } ++ ++ /* Set the antenna selection type for the low driver */ ++ brcms_b_antsel_type_set(wlc->hw, asi->antsel_type); ++ ++ /* Init (auto/manual) antenna selection */ ++ brcms_c_antsel_init_cfg(asi, &asi->antcfg_11n, true); ++ brcms_c_antsel_init_cfg(asi, &asi->antcfg_cur, true); ++ ++ return asi; ++} ++ ++void brcms_c_antsel_detach(struct antsel_info *asi) ++{ ++ kfree(asi); ++} ++ ++/* ++ * boardlevel antenna selection: ++ * convert ant_cfg to mimo_antsel (ucode interface) ++ */ ++static u16 brcms_c_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg) ++{ ++ u8 idx = BRCMS_ANTIDX_11N(BRCMS_ANTSEL_11N(ant_cfg)); ++ u16 mimo_antsel = 0; ++ ++ if (asi->antsel_type == ANTSEL_2x4) { ++ /* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */ ++ mimo_antsel = (mimo_2x4_div_antselpat_tbl[idx] & 0xf); ++ return mimo_antsel; ++ ++ } else if (asi->antsel_type == ANTSEL_2x3) { ++ /* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */ ++ mimo_antsel = (mimo_2x3_div_antselpat_tbl[idx] & 0xf); ++ return mimo_antsel; ++ } ++ ++ return mimo_antsel; ++} ++ ++/* boardlevel antenna selection: ucode interface control */ ++static int brcms_c_antsel_cfgupd(struct antsel_info *asi, ++ struct brcms_antselcfg *antsel) ++{ ++ struct brcms_c_info *wlc = asi->wlc; ++ u8 ant_cfg; ++ u16 mimo_antsel; ++ ++ /* 1) Update TX antconfig for all frames that are not unicast data ++ * (aka default TX) ++ */ ++ ant_cfg = antsel->ant_config[ANT_SELCFG_TX_DEF]; ++ mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg); ++ brcms_b_write_shm(wlc->hw, M_MIMO_ANTSEL_TXDFLT, mimo_antsel); ++ /* ++ * Update driver stats for currently selected ++ * default tx/rx antenna config ++ */ ++ asi->antcfg_cur.ant_config[ANT_SELCFG_TX_DEF] = ant_cfg; ++ ++ /* 2) Update RX antconfig for all frames that are not unicast data ++ * (aka default RX) ++ */ ++ ant_cfg = antsel->ant_config[ANT_SELCFG_RX_DEF]; ++ mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg); ++ brcms_b_write_shm(wlc->hw, M_MIMO_ANTSEL_RXDFLT, mimo_antsel); ++ /* ++ * Update driver stats for currently selected ++ * default tx/rx antenna config ++ */ ++ asi->antcfg_cur.ant_config[ANT_SELCFG_RX_DEF] = ant_cfg; ++ ++ return 0; ++} ++ ++void brcms_c_antsel_init(struct antsel_info *asi) ++{ ++ if ((asi->antsel_type == ANTSEL_2x3) || ++ (asi->antsel_type == ANTSEL_2x4)) ++ brcms_c_antsel_cfgupd(asi, &asi->antcfg_11n); ++} ++ ++/* boardlevel antenna selection: convert id to ant_cfg */ ++static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id) ++{ ++ u8 antcfg = ANT_SELCFG_DEF_2x2; ++ ++ if (asi->antsel_type == ANTSEL_2x4) { ++ /* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */ ++ antcfg = (((id & 0x2) << 3) | ((id & 0x1) + 2)); ++ return antcfg; ++ ++ } else if (asi->antsel_type == ANTSEL_2x3) { ++ /* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */ ++ antcfg = (((id & 0x02) << 4) | ((id & 0x1) + 1)); ++ return antcfg; ++ } ++ ++ return antcfg; ++} ++ ++void ++brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef, bool sel, ++ u8 antselid, u8 fbantselid, u8 *antcfg, ++ u8 *fbantcfg) ++{ ++ u8 ant; ++ ++ /* if use default, assign it and return */ ++ if (usedef) { ++ *antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_DEF]; ++ *fbantcfg = *antcfg; ++ return; ++ } ++ ++ if (!sel) { ++ *antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST]; ++ *fbantcfg = *antcfg; ++ ++ } else { ++ ant = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST]; ++ if ((ant & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO) { ++ *antcfg = brcms_c_antsel_id2antcfg(asi, antselid); ++ *fbantcfg = brcms_c_antsel_id2antcfg(asi, fbantselid); ++ } else { ++ *antcfg = ++ asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST]; ++ *fbantcfg = *antcfg; ++ } ++ } ++ return; ++} ++ ++/* boardlevel antenna selection: convert mimo_antsel (ucode interface) to id */ ++u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel) ++{ ++ u8 antselid = 0; ++ ++ if (asi->antsel_type == ANTSEL_2x4) { ++ /* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */ ++ antselid = mimo_2x4_div_antselid_tbl[(antsel & 0xf)]; ++ return antselid; ++ ++ } else if (asi->antsel_type == ANTSEL_2x3) { ++ /* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */ ++ antselid = mimo_2x3_div_antselid_tbl[(antsel & 0xf)]; ++ return antselid; ++ } ++ ++ return antselid; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.h.orig 2011-11-09 13:46:58.241800683 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/antsel.h 2011-11-09 13:47:16.993566253 -0500 +@@ -0,0 +1,29 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_ANTSEL_H_ ++#define _BRCM_ANTSEL_H_ ++ ++extern struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc); ++extern void brcms_c_antsel_detach(struct antsel_info *asi); ++extern void brcms_c_antsel_init(struct antsel_info *asi); ++extern void brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef, ++ bool sel, ++ u8 id, u8 fbid, u8 *antcfg, ++ u8 *fbantcfg); ++extern u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel); ++ ++#endif /* _BRCM_ANTSEL_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.c.orig 2011-11-09 13:46:58.241800683 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.c 2011-11-09 13:47:16.993566253 -0500 +@@ -0,0 +1,23 @@ ++/* ++ * Copyright (c) 2011 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include /* bug in tracepoint.h, it should include this */ ++ ++#ifndef __CHECKER__ ++#include "mac80211_if.h" ++#define CREATE_TRACE_POINTS ++#include "brcms_trace_events.h" ++#endif +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h.orig 2011-11-09 13:46:58.241800683 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h 2011-11-09 13:47:16.993566253 -0500 +@@ -0,0 +1,92 @@ ++/* ++ * Copyright (c) 2011 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM brcmsmac ++ ++#if !defined(__TRACE_BRCMSMAC_H) || defined(TRACE_HEADER_MULTI_READ) ++ ++#define __TRACE_BRCMSMAC_H ++ ++#include ++#include "mac80211_if.h" ++ ++#ifndef CONFIG_BRCMDBG ++#undef TRACE_EVENT ++#define TRACE_EVENT(name, proto, ...) \ ++static inline void trace_ ## name(proto) {} ++#endif ++ ++/* ++ * We define a tracepoint, its arguments, its printk format and its ++ * 'fast binary record' layout. ++ */ ++TRACE_EVENT(brcms_timer, ++ /* TPPROTO is the prototype of the function called by this tracepoint */ ++ TP_PROTO(struct brcms_timer *t), ++ /* ++ * TPARGS(firstarg, p) are the parameters names, same as found in the ++ * prototype. ++ */ ++ TP_ARGS(t), ++ /* ++ * Fast binary tracing: define the trace record via TP_STRUCT__entry(). ++ * You can think about it like a regular C structure local variable ++ * definition. ++ */ ++ TP_STRUCT__entry( ++ __field(uint, ms) ++ __field(uint, set) ++ __field(uint, periodic) ++ ), ++ TP_fast_assign( ++ __entry->ms = t->ms; ++ __entry->set = t->set; ++ __entry->periodic = t->periodic; ++ ), ++ TP_printk( ++ "ms=%u set=%u periodic=%u", ++ __entry->ms, __entry->set, __entry->periodic ++ ) ++); ++ ++TRACE_EVENT(brcms_dpc, ++ TP_PROTO(unsigned long data), ++ TP_ARGS(data), ++ TP_STRUCT__entry( ++ __field(unsigned long, data) ++ ), ++ TP_fast_assign( ++ __entry->data = data; ++ ), ++ TP_printk( ++ "data=%p", ++ (void *)__entry->data ++ ) ++); ++ ++#endif /* __TRACE_BRCMSMAC_H */ ++ ++#ifdef CONFIG_BRCMDBG ++ ++#undef TRACE_INCLUDE_PATH ++#define TRACE_INCLUDE_PATH . ++#undef TRACE_INCLUDE_FILE ++#define TRACE_INCLUDE_FILE brcms_trace_events ++ ++#include ++ ++#endif /* CONFIG_BRCMDBG */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.c.orig 2011-11-09 13:46:58.242800670 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.c 2011-11-09 13:47:16.994566241 -0500 +@@ -0,0 +1,1591 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include ++#include "pub.h" ++#include "phy/phy_hal.h" ++#include "main.h" ++#include "stf.h" ++#include "channel.h" ++ ++/* QDB() macro takes a dB value and converts to a quarter dB value */ ++#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR) ++ ++#define LOCALE_CHAN_01_11 (1<<0) ++#define LOCALE_CHAN_12_13 (1<<1) ++#define LOCALE_CHAN_14 (1<<2) ++#define LOCALE_SET_5G_LOW_JP1 (1<<3) /* 34-48, step 2 */ ++#define LOCALE_SET_5G_LOW_JP2 (1<<4) /* 34-46, step 4 */ ++#define LOCALE_SET_5G_LOW1 (1<<5) /* 36-48, step 4 */ ++#define LOCALE_SET_5G_LOW2 (1<<6) /* 52 */ ++#define LOCALE_SET_5G_LOW3 (1<<7) /* 56-64, step 4 */ ++#define LOCALE_SET_5G_MID1 (1<<8) /* 100-116, step 4 */ ++#define LOCALE_SET_5G_MID2 (1<<9) /* 120-124, step 4 */ ++#define LOCALE_SET_5G_MID3 (1<<10) /* 128 */ ++#define LOCALE_SET_5G_HIGH1 (1<<11) /* 132-140, step 4 */ ++#define LOCALE_SET_5G_HIGH2 (1<<12) /* 149-161, step 4 */ ++#define LOCALE_SET_5G_HIGH3 (1<<13) /* 165 */ ++#define LOCALE_CHAN_52_140_ALL (1<<14) ++#define LOCALE_SET_5G_HIGH4 (1<<15) /* 184-216 */ ++ ++#define LOCALE_CHAN_36_64 (LOCALE_SET_5G_LOW1 | \ ++ LOCALE_SET_5G_LOW2 | \ ++ LOCALE_SET_5G_LOW3) ++#define LOCALE_CHAN_52_64 (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3) ++#define LOCALE_CHAN_100_124 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2) ++#define LOCALE_CHAN_100_140 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | \ ++ LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1) ++#define LOCALE_CHAN_149_165 (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3) ++#define LOCALE_CHAN_184_216 LOCALE_SET_5G_HIGH4 ++ ++#define LOCALE_CHAN_01_14 (LOCALE_CHAN_01_11 | \ ++ LOCALE_CHAN_12_13 | \ ++ LOCALE_CHAN_14) ++ ++#define LOCALE_RADAR_SET_NONE 0 ++#define LOCALE_RADAR_SET_1 1 ++ ++#define LOCALE_RESTRICTED_NONE 0 ++#define LOCALE_RESTRICTED_SET_2G_SHORT 1 ++#define LOCALE_RESTRICTED_CHAN_165 2 ++#define LOCALE_CHAN_ALL_5G 3 ++#define LOCALE_RESTRICTED_JAPAN_LEGACY 4 ++#define LOCALE_RESTRICTED_11D_2G 5 ++#define LOCALE_RESTRICTED_11D_5G 6 ++#define LOCALE_RESTRICTED_LOW_HI 7 ++#define LOCALE_RESTRICTED_12_13_14 8 ++ ++#define LOCALE_2G_IDX_i 0 ++#define LOCALE_5G_IDX_11 0 ++#define LOCALE_MIMO_IDX_bn 0 ++#define LOCALE_MIMO_IDX_11n 0 ++ ++/* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */ ++#define BRCMS_MAXPWR_TBL_SIZE 6 ++/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */ ++#define BRCMS_MAXPWR_MIMO_TBL_SIZE 14 ++ ++/* power level in group of 2.4GHz band channels: ++ * maxpwr[0] - CCK channels [1] ++ * maxpwr[1] - CCK channels [2-10] ++ * maxpwr[2] - CCK channels [11-14] ++ * maxpwr[3] - OFDM channels [1] ++ * maxpwr[4] - OFDM channels [2-10] ++ * maxpwr[5] - OFDM channels [11-14] ++ */ ++ ++/* maxpwr mapping to 5GHz band channels: ++ * maxpwr[0] - channels [34-48] ++ * maxpwr[1] - channels [52-60] ++ * maxpwr[2] - channels [62-64] ++ * maxpwr[3] - channels [100-140] ++ * maxpwr[4] - channels [149-165] ++ */ ++#define BAND_5G_PWR_LVLS 5 /* 5 power levels for 5G */ ++ ++#define LC(id) LOCALE_MIMO_IDX_ ## id ++ ++#define LC_2G(id) LOCALE_2G_IDX_ ## id ++ ++#define LC_5G(id) LOCALE_5G_IDX_ ## id ++ ++#define LOCALES(band2, band5, mimo2, mimo5) \ ++ {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)} ++ ++/* macro to get 2.4 GHz channel group index for tx power */ ++#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2)) ++#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5)) ++ ++/* macro to get 5 GHz channel group index for tx power */ ++#define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \ ++ (((c) < 62) ? 1 : \ ++ (((c) < 100) ? 2 : \ ++ (((c) < 149) ? 3 : 4)))) ++ ++#define ISDFS_EU(fl) (((fl) & BRCMS_DFS_EU) == BRCMS_DFS_EU) ++ ++struct brcms_cm_band { ++ /* struct locale_info flags */ ++ u8 locale_flags; ++ /* List of valid channels in the country */ ++ struct brcms_chanvec valid_channels; ++ /* List of restricted use channels */ ++ const struct brcms_chanvec *restricted_channels; ++ /* List of radar sensitive channels */ ++ const struct brcms_chanvec *radar_channels; ++ u8 PAD[8]; ++}; ++ ++ /* locale per-channel tx power limits for MIMO frames ++ * maxpwr arrays are index by channel for 2.4 GHz limits, and ++ * by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel) ++ */ ++struct locale_mimo_info { ++ /* tx 20 MHz power limits, qdBm units */ ++ s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE]; ++ /* tx 40 MHz power limits, qdBm units */ ++ s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE]; ++ u8 flags; ++}; ++ ++/* Country names and abbreviations with locale defined from ISO 3166 */ ++struct country_info { ++ const u8 locale_2G; /* 2.4G band locale */ ++ const u8 locale_5G; /* 5G band locale */ ++ const u8 locale_mimo_2G; /* 2.4G mimo info */ ++ const u8 locale_mimo_5G; /* 5G mimo info */ ++}; ++ ++struct brcms_cm_info { ++ struct brcms_pub *pub; ++ struct brcms_c_info *wlc; ++ char srom_ccode[BRCM_CNTRY_BUF_SZ]; /* Country Code in SROM */ ++ uint srom_regrev; /* Regulatory Rev for the SROM ccode */ ++ const struct country_info *country; /* current country def */ ++ char ccode[BRCM_CNTRY_BUF_SZ]; /* current internal Country Code */ ++ uint regrev; /* current Regulatory Revision */ ++ char country_abbrev[BRCM_CNTRY_BUF_SZ]; /* current advertised ccode */ ++ /* per-band state (one per phy/radio) */ ++ struct brcms_cm_band bandstate[MAXBANDS]; ++ /* quiet channels currently for radar sensitivity or 11h support */ ++ /* channels on which we cannot transmit */ ++ struct brcms_chanvec quiet_channels; ++}; ++ ++/* locale channel and power info. */ ++struct locale_info { ++ u32 valid_channels; ++ /* List of radar sensitive channels */ ++ u8 radar_channels; ++ /* List of channels used only if APs are detected */ ++ u8 restricted_channels; ++ /* Max tx pwr in qdBm for each sub-band */ ++ s8 maxpwr[BRCMS_MAXPWR_TBL_SIZE]; ++ /* Country IE advertised max tx pwr in dBm per sub-band */ ++ s8 pub_maxpwr[BAND_5G_PWR_LVLS]; ++ u8 flags; ++}; ++ ++/* Regulatory Matrix Spreadsheet (CLM) MIMO v3.7.9 */ ++ ++/* ++ * Some common channel sets ++ */ ++ ++/* No channels */ ++static const struct brcms_chanvec chanvec_none = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* All 2.4 GHz HW channels */ ++static const struct brcms_chanvec chanvec_all_2G = { ++ {0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* All 5 GHz HW channels */ ++static const struct brcms_chanvec chanvec_all_5G = { ++ {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x11, 0x11, ++ 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, ++ 0x11, 0x11, 0x20, 0x22, 0x22, 0x00, 0x00, 0x11, ++ 0x11, 0x11, 0x11, 0x01} ++}; ++ ++/* ++ * Radar channel sets ++ */ ++ ++/* Channels 52 - 64, 100 - 140 */ ++static const struct brcms_chanvec radar_set1 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, /* 52 - 60 */ ++ 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, /* 64, 100 - 124 */ ++ 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 - 140 */ ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* ++ * Restricted channel sets ++ */ ++ ++/* Channels 34, 38, 42, 46 */ ++static const struct brcms_chanvec restricted_set_japan_legacy = { ++ {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* Channels 12, 13 */ ++static const struct brcms_chanvec restricted_set_2g_short = { ++ {0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* Channel 165 */ ++static const struct brcms_chanvec restricted_chan_165 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* Channels 36 - 48 & 149 - 165 */ ++static const struct brcms_chanvec restricted_low_hi = { ++ {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x20, 0x22, 0x22, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* Channels 12 - 14 */ ++static const struct brcms_chanvec restricted_set_12_13_14 = { ++ {0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* global memory to provide working buffer for expanded locale */ ++ ++static const struct brcms_chanvec *g_table_radar_set[] = { ++ &chanvec_none, ++ &radar_set1 ++}; ++ ++static const struct brcms_chanvec *g_table_restricted_chan[] = { ++ &chanvec_none, /* restricted_set_none */ ++ &restricted_set_2g_short, ++ &restricted_chan_165, ++ &chanvec_all_5G, ++ &restricted_set_japan_legacy, ++ &chanvec_all_2G, /* restricted_set_11d_2G */ ++ &chanvec_all_5G, /* restricted_set_11d_5G */ ++ &restricted_low_hi, ++ &restricted_set_12_13_14 ++}; ++ ++static const struct brcms_chanvec locale_2g_01_11 = { ++ {0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_2g_12_13 = { ++ {0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_2g_14 = { ++ {0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_LOW_JP1 = { ++ {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_LOW_JP2 = { ++ {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_LOW1 = { ++ {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_LOW2 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_LOW3 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_MID1 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_MID2 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_MID3 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_HIGH1 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_HIGH2 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x20, 0x22, 0x02, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_HIGH3 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_52_140_ALL = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, ++ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, ++ 0x11, 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_chanvec locale_5g_HIGH4 = { ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, ++ 0x11, 0x11, 0x11, 0x11} ++}; ++ ++static const struct brcms_chanvec *g_table_locale_base[] = { ++ &locale_2g_01_11, ++ &locale_2g_12_13, ++ &locale_2g_14, ++ &locale_5g_LOW_JP1, ++ &locale_5g_LOW_JP2, ++ &locale_5g_LOW1, ++ &locale_5g_LOW2, ++ &locale_5g_LOW3, ++ &locale_5g_MID1, ++ &locale_5g_MID2, ++ &locale_5g_MID3, ++ &locale_5g_HIGH1, ++ &locale_5g_HIGH2, ++ &locale_5g_HIGH3, ++ &locale_5g_52_140_ALL, ++ &locale_5g_HIGH4 ++}; ++ ++static void brcms_c_locale_add_channels(struct brcms_chanvec *target, ++ const struct brcms_chanvec *channels) ++{ ++ u8 i; ++ for (i = 0; i < sizeof(struct brcms_chanvec); i++) ++ target->vec[i] |= channels->vec[i]; ++} ++ ++static void brcms_c_locale_get_channels(const struct locale_info *locale, ++ struct brcms_chanvec *channels) ++{ ++ u8 i; ++ ++ memset(channels, 0, sizeof(struct brcms_chanvec)); ++ ++ for (i = 0; i < ARRAY_SIZE(g_table_locale_base); i++) { ++ if (locale->valid_channels & (1 << i)) ++ brcms_c_locale_add_channels(channels, ++ g_table_locale_base[i]); ++ } ++} ++ ++/* ++ * Locale Definitions - 2.4 GHz ++ */ ++static const struct locale_info locale_i = { /* locale i. channel 1 - 13 */ ++ LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13, ++ LOCALE_RADAR_SET_NONE, ++ LOCALE_RESTRICTED_SET_2G_SHORT, ++ {QDB(19), QDB(19), QDB(19), ++ QDB(19), QDB(19), QDB(19)}, ++ {20, 20, 20, 0}, ++ BRCMS_EIRP ++}; ++ ++/* ++ * Locale Definitions - 5 GHz ++ */ ++static const struct locale_info locale_11 = { ++ /* locale 11. channel 36 - 48, 52 - 64, 100 - 140, 149 - 165 */ ++ LOCALE_CHAN_36_64 | LOCALE_CHAN_100_140 | LOCALE_CHAN_149_165, ++ LOCALE_RADAR_SET_1, ++ LOCALE_RESTRICTED_NONE, ++ {QDB(21), QDB(21), QDB(21), QDB(21), QDB(21)}, ++ {23, 23, 23, 30, 30}, ++ BRCMS_EIRP | BRCMS_DFS_EU ++}; ++ ++static const struct locale_info *g_locale_2g_table[] = { ++ &locale_i ++}; ++ ++static const struct locale_info *g_locale_5g_table[] = { ++ &locale_11 ++}; ++ ++/* ++ * MIMO Locale Definitions - 2.4 GHz ++ */ ++static const struct locale_mimo_info locale_bn = { ++ {QDB(13), QDB(13), QDB(13), QDB(13), QDB(13), ++ QDB(13), QDB(13), QDB(13), QDB(13), QDB(13), ++ QDB(13), QDB(13), QDB(13)}, ++ {0, 0, QDB(13), QDB(13), QDB(13), ++ QDB(13), QDB(13), QDB(13), QDB(13), QDB(13), ++ QDB(13), 0, 0}, ++ 0 ++}; ++ ++static const struct locale_mimo_info *g_mimo_2g_table[] = { ++ &locale_bn ++}; ++ ++/* ++ * MIMO Locale Definitions - 5 GHz ++ */ ++static const struct locale_mimo_info locale_11n = { ++ { /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)}, ++ {QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)}, ++ 0 ++}; ++ ++static const struct locale_mimo_info *g_mimo_5g_table[] = { ++ &locale_11n ++}; ++ ++static const struct { ++ char abbrev[BRCM_CNTRY_BUF_SZ]; /* country abbreviation */ ++ struct country_info country; ++} cntry_locales[] = { ++ { ++ "X2", LOCALES(i, 11, bn, 11n)}, /* Worldwide RoW 2 */ ++}; ++ ++#ifdef SUPPORT_40MHZ ++/* 20MHz channel info for 40MHz pairing support */ ++struct chan20_info { ++ u8 sb; ++ u8 adj_sbs; ++}; ++ ++/* indicates adjacent channels that are allowed for a 40 Mhz channel and ++ * those that permitted by the HT ++ */ ++struct chan20_info chan20_info[] = { ++ /* 11b/11g */ ++/* 0 */ {1, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 1 */ {2, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 2 */ {3, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 3 */ {4, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 4 */ {5, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, ++/* 5 */ {6, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, ++/* 6 */ {7, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, ++/* 7 */ {8, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, ++/* 8 */ {9, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)}, ++/* 9 */ {10, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 10 */ {11, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 11 */ {12, (CH_LOWER_SB)}, ++/* 12 */ {13, (CH_LOWER_SB)}, ++/* 13 */ {14, (CH_LOWER_SB)}, ++ ++/* 11a japan high */ ++/* 14 */ {34, (CH_UPPER_SB)}, ++/* 15 */ {38, (CH_LOWER_SB)}, ++/* 16 */ {42, (CH_LOWER_SB)}, ++/* 17 */ {46, (CH_LOWER_SB)}, ++ ++/* 11a usa low */ ++/* 18 */ {36, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 19 */ {40, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 20 */ {44, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 21 */ {48, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 22 */ {52, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 23 */ {56, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 24 */ {60, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 25 */ {64, (CH_LOWER_SB | CH_EWA_VALID)}, ++ ++/* 11a Europe */ ++/* 26 */ {100, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 27 */ {104, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 28 */ {108, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 29 */ {112, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 30 */ {116, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 31 */ {120, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 32 */ {124, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 33 */ {128, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 34 */ {132, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 35 */ {136, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 36 */ {140, (CH_LOWER_SB)}, ++ ++/* 11a usa high, ref5 only */ ++/* The 0x80 bit in pdiv means these are REF5, other entries are REF20 */ ++/* 37 */ {149, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 38 */ {153, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 39 */ {157, (CH_UPPER_SB | CH_EWA_VALID)}, ++/* 40 */ {161, (CH_LOWER_SB | CH_EWA_VALID)}, ++/* 41 */ {165, (CH_LOWER_SB)}, ++ ++/* 11a japan */ ++/* 42 */ {184, (CH_UPPER_SB)}, ++/* 43 */ {188, (CH_LOWER_SB)}, ++/* 44 */ {192, (CH_UPPER_SB)}, ++/* 45 */ {196, (CH_LOWER_SB)}, ++/* 46 */ {200, (CH_UPPER_SB)}, ++/* 47 */ {204, (CH_LOWER_SB)}, ++/* 48 */ {208, (CH_UPPER_SB)}, ++/* 49 */ {212, (CH_LOWER_SB)}, ++/* 50 */ {216, (CH_LOWER_SB)} ++}; ++#endif /* SUPPORT_40MHZ */ ++ ++static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx) ++{ ++ if (locale_idx >= ARRAY_SIZE(g_locale_2g_table)) ++ return NULL; /* error condition */ ++ ++ return g_locale_2g_table[locale_idx]; ++} ++ ++static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx) ++{ ++ if (locale_idx >= ARRAY_SIZE(g_locale_5g_table)) ++ return NULL; /* error condition */ ++ ++ return g_locale_5g_table[locale_idx]; ++} ++ ++static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx) ++{ ++ if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table)) ++ return NULL; ++ ++ return g_mimo_2g_table[locale_idx]; ++} ++ ++static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx) ++{ ++ if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table)) ++ return NULL; ++ ++ return g_mimo_5g_table[locale_idx]; ++} ++ ++static int ++brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm, const char *ccode, ++ char *mapped_ccode, uint *mapped_regrev) ++{ ++ return false; ++} ++ ++/* Lookup a country info structure from a null terminated country ++ * abbreviation and regrev directly with no translation. ++ */ ++static const struct country_info * ++brcms_c_country_lookup_direct(const char *ccode, uint regrev) ++{ ++ uint size, i; ++ ++ /* Should just return 0 for single locale driver. */ ++ /* Keep it this way in case we add more locales. (for now anyway) */ ++ ++ /* ++ * all other country def arrays are for regrev == 0, so if ++ * regrev is non-zero, fail ++ */ ++ if (regrev > 0) ++ return NULL; ++ ++ /* find matched table entry from country code */ ++ size = ARRAY_SIZE(cntry_locales); ++ for (i = 0; i < size; i++) { ++ if (strcmp(ccode, cntry_locales[i].abbrev) == 0) ++ return &cntry_locales[i].country; ++ } ++ return NULL; ++} ++ ++static const struct country_info * ++brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm, const char *ccode, ++ char *mapped_ccode, uint *mapped_regrev) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ const struct country_info *country; ++ uint srom_regrev = wlc_cm->srom_regrev; ++ const char *srom_ccode = wlc_cm->srom_ccode; ++ int mapped; ++ ++ /* check for currently supported ccode size */ ++ if (strlen(ccode) > (BRCM_CNTRY_BUF_SZ - 1)) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: ccode \"%s\" too long for " ++ "match\n", wlc->pub->unit, __func__, ccode); ++ return NULL; ++ } ++ ++ /* default mapping is the given ccode and regrev 0 */ ++ strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ); ++ *mapped_regrev = 0; ++ ++ /* If the desired country code matches the srom country code, ++ * then the mapped country is the srom regulatory rev. ++ * Otherwise look for an aggregate mapping. ++ */ ++ if (!strcmp(srom_ccode, ccode)) { ++ *mapped_regrev = srom_regrev; ++ mapped = 0; ++ wiphy_err(wlc->wiphy, "srom_code == ccode %s\n", __func__); ++ } else { ++ mapped = ++ brcms_c_country_aggregate_map(wlc_cm, ccode, mapped_ccode, ++ mapped_regrev); ++ } ++ ++ /* find the matching built-in country definition */ ++ country = brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev); ++ ++ /* if there is not an exact rev match, default to rev zero */ ++ if (country == NULL && *mapped_regrev != 0) { ++ *mapped_regrev = 0; ++ country = ++ brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev); ++ } ++ ++ return country; ++} ++ ++/* Lookup a country info structure from a null terminated country code ++ * The lookup is case sensitive. ++ */ ++static const struct country_info * ++brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode) ++{ ++ const struct country_info *country; ++ char mapped_ccode[BRCM_CNTRY_BUF_SZ]; ++ uint mapped_regrev; ++ ++ /* ++ * map the country code to a built-in country code, regrev, and ++ * country_info struct ++ */ ++ country = brcms_c_countrycode_map(wlc->cmi, ccode, mapped_ccode, ++ &mapped_regrev); ++ ++ return country; ++} ++ ++/* ++ * reset the quiet channels vector to the union ++ * of the restricted and radar channel sets ++ */ ++static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ uint i, j; ++ struct brcms_band *band; ++ const struct brcms_chanvec *chanvec; ++ ++ memset(&wlc_cm->quiet_channels, 0, sizeof(struct brcms_chanvec)); ++ ++ band = wlc->band; ++ for (i = 0; i < wlc->pub->_nbands; ++ i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) { ++ ++ /* initialize quiet channels for restricted channels */ ++ chanvec = wlc_cm->bandstate[band->bandunit].restricted_channels; ++ for (j = 0; j < sizeof(struct brcms_chanvec); j++) ++ wlc_cm->quiet_channels.vec[j] |= chanvec->vec[j]; ++ ++ } ++} ++ ++/* Is the channel valid for the current locale and current band? */ ++static bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ ++ return ((val < MAXCHANNEL) && ++ isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec, ++ val)); ++} ++ ++/* Is the channel valid for the current locale and specified band? */ ++static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm, ++ uint bandunit, uint val) ++{ ++ return ((val < MAXCHANNEL) ++ && isset(wlc_cm->bandstate[bandunit].valid_channels.vec, val)); ++} ++ ++/* Is the channel valid for the current locale? (but don't consider channels not ++ * available due to bandlocking) ++ */ ++static bool brcms_c_valid_channel20_db(struct brcms_cm_info *wlc_cm, uint val) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ ++ return brcms_c_valid_channel20(wlc->cmi, val) || ++ (!wlc->bandlocked ++ && brcms_c_valid_channel20_in_band(wlc->cmi, ++ OTHERBANDUNIT(wlc), val)); ++} ++ ++/* JP, J1 - J10 are Japan ccodes */ ++static bool brcms_c_japan_ccode(const char *ccode) ++{ ++ return (ccode[0] == 'J' && ++ (ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9'))); ++} ++ ++/* Returns true if currently set country is Japan or variant */ ++static bool brcms_c_japan(struct brcms_c_info *wlc) ++{ ++ return brcms_c_japan_ccode(wlc->cmi->country_abbrev); ++} ++ ++static void ++brcms_c_channel_min_txpower_limits_with_local_constraint( ++ struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr, ++ u8 local_constraint_qdbm) ++{ ++ int j; ++ ++ /* CCK Rates */ ++ for (j = 0; j < WL_TX_POWER_CCK_NUM; j++) ++ txpwr->cck[j] = min(txpwr->cck[j], local_constraint_qdbm); ++ ++ /* 20 MHz Legacy OFDM SISO */ ++ for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++) ++ txpwr->ofdm[j] = min(txpwr->ofdm[j], local_constraint_qdbm); ++ ++ /* 20 MHz Legacy OFDM CDD */ ++ for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) ++ txpwr->ofdm_cdd[j] = ++ min(txpwr->ofdm_cdd[j], local_constraint_qdbm); ++ ++ /* 40 MHz Legacy OFDM SISO */ ++ for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) ++ txpwr->ofdm_40_siso[j] = ++ min(txpwr->ofdm_40_siso[j], local_constraint_qdbm); ++ ++ /* 40 MHz Legacy OFDM CDD */ ++ for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++) ++ txpwr->ofdm_40_cdd[j] = ++ min(txpwr->ofdm_40_cdd[j], local_constraint_qdbm); ++ ++ /* 20MHz MCS 0-7 SISO */ ++ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) ++ txpwr->mcs_20_siso[j] = ++ min(txpwr->mcs_20_siso[j], local_constraint_qdbm); ++ ++ /* 20MHz MCS 0-7 CDD */ ++ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) ++ txpwr->mcs_20_cdd[j] = ++ min(txpwr->mcs_20_cdd[j], local_constraint_qdbm); ++ ++ /* 20MHz MCS 0-7 STBC */ ++ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) ++ txpwr->mcs_20_stbc[j] = ++ min(txpwr->mcs_20_stbc[j], local_constraint_qdbm); ++ ++ /* 20MHz MCS 8-15 MIMO */ ++ for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++) ++ txpwr->mcs_20_mimo[j] = ++ min(txpwr->mcs_20_mimo[j], local_constraint_qdbm); ++ ++ /* 40MHz MCS 0-7 SISO */ ++ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) ++ txpwr->mcs_40_siso[j] = ++ min(txpwr->mcs_40_siso[j], local_constraint_qdbm); ++ ++ /* 40MHz MCS 0-7 CDD */ ++ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) ++ txpwr->mcs_40_cdd[j] = ++ min(txpwr->mcs_40_cdd[j], local_constraint_qdbm); ++ ++ /* 40MHz MCS 0-7 STBC */ ++ for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++) ++ txpwr->mcs_40_stbc[j] = ++ min(txpwr->mcs_40_stbc[j], local_constraint_qdbm); ++ ++ /* 40MHz MCS 8-15 MIMO */ ++ for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++) ++ txpwr->mcs_40_mimo[j] = ++ min(txpwr->mcs_40_mimo[j], local_constraint_qdbm); ++ ++ /* 40MHz MCS 32 */ ++ txpwr->mcs32 = min(txpwr->mcs32, local_constraint_qdbm); ++ ++} ++ ++/* Update the radio state (enable/disable) and tx power targets ++ * based on a new set of channel/regulatory information ++ */ ++static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ uint chan; ++ struct txpwr_limits txpwr; ++ ++ /* search for the existence of any valid channel */ ++ for (chan = 0; chan < MAXCHANNEL; chan++) { ++ if (brcms_c_valid_channel20_db(wlc->cmi, chan)) ++ break; ++ } ++ if (chan == MAXCHANNEL) ++ chan = INVCHANNEL; ++ ++ /* ++ * based on the channel search above, set or ++ * clear WL_RADIO_COUNTRY_DISABLE. ++ */ ++ if (chan == INVCHANNEL) { ++ /* ++ * country/locale with no valid channels, set ++ * the radio disable bit ++ */ ++ mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); ++ wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" " ++ "nbands %d bandlocked %d\n", wlc->pub->unit, ++ __func__, wlc_cm->country_abbrev, wlc->pub->_nbands, ++ wlc->bandlocked); ++ } else if (mboolisset(wlc->pub->radio_disabled, ++ WL_RADIO_COUNTRY_DISABLE)) { ++ /* ++ * country/locale with valid channel, clear ++ * the radio disable bit ++ */ ++ mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE); ++ } ++ ++ /* ++ * Now that the country abbreviation is set, if the radio supports 2G, ++ * then set channel 14 restrictions based on the new locale. ++ */ ++ if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G) ++ wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi, ++ brcms_c_japan(wlc) ? true : ++ false); ++ ++ if (wlc->pub->up && chan != INVCHANNEL) { ++ brcms_c_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr); ++ brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm, ++ &txpwr, BRCMS_TXPWR_MAX); ++ wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec); ++ } ++} ++ ++static int ++brcms_c_channels_init(struct brcms_cm_info *wlc_cm, ++ const struct country_info *country) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ uint i, j; ++ struct brcms_band *band; ++ const struct locale_info *li; ++ struct brcms_chanvec sup_chan; ++ const struct locale_mimo_info *li_mimo; ++ ++ band = wlc->band; ++ for (i = 0; i < wlc->pub->_nbands; ++ i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) { ++ ++ li = (band->bandtype == BRCM_BAND_5G) ? ++ brcms_c_get_locale_5g(country->locale_5G) : ++ brcms_c_get_locale_2g(country->locale_2G); ++ wlc_cm->bandstate[band->bandunit].locale_flags = li->flags; ++ li_mimo = (band->bandtype == BRCM_BAND_5G) ? ++ brcms_c_get_mimo_5g(country->locale_mimo_5G) : ++ brcms_c_get_mimo_2g(country->locale_mimo_2G); ++ ++ /* merge the mimo non-mimo locale flags */ ++ wlc_cm->bandstate[band->bandunit].locale_flags |= ++ li_mimo->flags; ++ ++ wlc_cm->bandstate[band->bandunit].restricted_channels = ++ g_table_restricted_chan[li->restricted_channels]; ++ wlc_cm->bandstate[band->bandunit].radar_channels = ++ g_table_radar_set[li->radar_channels]; ++ ++ /* ++ * set the channel availability, masking out the channels ++ * that may not be supported on this phy. ++ */ ++ wlc_phy_chanspec_band_validch(band->pi, band->bandtype, ++ &sup_chan); ++ brcms_c_locale_get_channels(li, ++ &wlc_cm->bandstate[band->bandunit]. ++ valid_channels); ++ for (j = 0; j < sizeof(struct brcms_chanvec); j++) ++ wlc_cm->bandstate[band->bandunit].valid_channels. ++ vec[j] &= sup_chan.vec[j]; ++ } ++ ++ brcms_c_quiet_channels_reset(wlc_cm); ++ brcms_c_channels_commit(wlc_cm); ++ ++ return 0; ++} ++ ++/* ++ * set the driver's current country and regulatory information ++ * using a country code as the source. Look up built in country ++ * information found with the country code. ++ */ ++static void ++brcms_c_set_country_common(struct brcms_cm_info *wlc_cm, ++ const char *country_abbrev, ++ const char *ccode, uint regrev, ++ const struct country_info *country) ++{ ++ const struct locale_info *locale; ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ char prev_country_abbrev[BRCM_CNTRY_BUF_SZ]; ++ ++ /* save current country state */ ++ wlc_cm->country = country; ++ ++ memset(&prev_country_abbrev, 0, BRCM_CNTRY_BUF_SZ); ++ strncpy(prev_country_abbrev, wlc_cm->country_abbrev, ++ BRCM_CNTRY_BUF_SZ - 1); ++ ++ strncpy(wlc_cm->country_abbrev, country_abbrev, BRCM_CNTRY_BUF_SZ - 1); ++ strncpy(wlc_cm->ccode, ccode, BRCM_CNTRY_BUF_SZ - 1); ++ wlc_cm->regrev = regrev; ++ ++ if ((wlc->pub->_n_enab & SUPPORT_11N) != ++ wlc->protection->nmode_user) ++ brcms_c_set_nmode(wlc); ++ ++ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]); ++ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]); ++ /* set or restore gmode as required by regulatory */ ++ locale = brcms_c_get_locale_2g(country->locale_2G); ++ if (locale && (locale->flags & BRCMS_NO_OFDM)) ++ brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false); ++ else ++ brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false); ++ ++ brcms_c_channels_init(wlc_cm, country); ++ ++ return; ++} ++ ++static int ++brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm, ++ const char *country_abbrev, ++ const char *ccode, int regrev) ++{ ++ const struct country_info *country; ++ char mapped_ccode[BRCM_CNTRY_BUF_SZ]; ++ uint mapped_regrev; ++ ++ /* if regrev is -1, lookup the mapped country code, ++ * otherwise use the ccode and regrev directly ++ */ ++ if (regrev == -1) { ++ /* ++ * map the country code to a built-in country ++ * code, regrev, and country_info ++ */ ++ country = ++ brcms_c_countrycode_map(wlc_cm, ccode, mapped_ccode, ++ &mapped_regrev); ++ } else { ++ /* find the matching built-in country definition */ ++ country = brcms_c_country_lookup_direct(ccode, regrev); ++ strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ); ++ mapped_regrev = regrev; ++ } ++ ++ if (country == NULL) ++ return -EINVAL; ++ ++ /* set the driver state for the country */ ++ brcms_c_set_country_common(wlc_cm, country_abbrev, mapped_ccode, ++ mapped_regrev, country); ++ ++ return 0; ++} ++ ++/* ++ * set the driver's current country and regulatory information using ++ * a country code as the source. Lookup built in country information ++ * found with the country code. ++ */ ++static int ++brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm, const char *ccode) ++{ ++ char country_abbrev[BRCM_CNTRY_BUF_SZ]; ++ strncpy(country_abbrev, ccode, BRCM_CNTRY_BUF_SZ); ++ return brcms_c_set_countrycode_rev(wlc_cm, country_abbrev, ccode, -1); ++} ++ ++struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc) ++{ ++ struct brcms_cm_info *wlc_cm; ++ char country_abbrev[BRCM_CNTRY_BUF_SZ]; ++ const struct country_info *country; ++ struct brcms_pub *pub = wlc->pub; ++ char *ccode; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ ++ wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC); ++ if (wlc_cm == NULL) ++ return NULL; ++ wlc_cm->pub = pub; ++ wlc_cm->wlc = wlc; ++ wlc->cmi = wlc_cm; ++ ++ /* store the country code for passing up as a regulatory hint */ ++ ccode = getvar(wlc->hw->sih, BRCMS_SROM_CCODE); ++ if (ccode) ++ strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1); ++ ++ /* ++ * internal country information which must match ++ * regulatory constraints in firmware ++ */ ++ memset(country_abbrev, 0, BRCM_CNTRY_BUF_SZ); ++ strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1); ++ country = brcms_c_country_lookup(wlc, country_abbrev); ++ ++ /* save default country for exiting 11d regulatory mode */ ++ strncpy(wlc->country_default, country_abbrev, BRCM_CNTRY_BUF_SZ - 1); ++ ++ /* initialize autocountry_default to driver default */ ++ strncpy(wlc->autocountry_default, "X2", BRCM_CNTRY_BUF_SZ - 1); ++ ++ brcms_c_set_countrycode(wlc_cm, country_abbrev); ++ ++ return wlc_cm; ++} ++ ++void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm) ++{ ++ kfree(wlc_cm); ++} ++ ++u8 ++brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm, ++ uint bandunit) ++{ ++ return wlc_cm->bandstate[bandunit].locale_flags; ++} ++ ++static bool ++brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, u16 chspec) ++{ ++ return (wlc_cm->wlc->pub->_n_enab & SUPPORT_11N) && ++ CHSPEC_IS40(chspec) ? ++ (isset(wlc_cm->quiet_channels.vec, ++ lower_20_sb(CHSPEC_CHANNEL(chspec))) || ++ isset(wlc_cm->quiet_channels.vec, ++ upper_20_sb(CHSPEC_CHANNEL(chspec)))) : ++ isset(wlc_cm->quiet_channels.vec, CHSPEC_CHANNEL(chspec)); ++} ++ ++void ++brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, ++ u8 local_constraint_qdbm) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ struct txpwr_limits txpwr; ++ ++ brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr); ++ ++ brcms_c_channel_min_txpower_limits_with_local_constraint( ++ wlc_cm, &txpwr, local_constraint_qdbm ++ ); ++ ++ brcms_b_set_chanspec(wlc->hw, chanspec, ++ (brcms_c_quiet_chanspec(wlc_cm, chanspec) != 0), ++ &txpwr); ++} ++ ++#ifdef POWER_DBG ++static void wlc_phy_txpower_limits_dump(struct txpwr_limits *txpwr) ++{ ++ int i; ++ char buf[80]; ++ char fraction[4][4] = { " ", ".25", ".5 ", ".75" }; ++ ++ sprintf(buf, "CCK "); ++ for (i = 0; i < BRCMS_NUM_RATES_CCK; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->cck[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->cck[i] % BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "20 MHz OFDM SISO "); ++ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->ofdm[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->ofdm[i] % BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "20 MHz OFDM CDD "); ++ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->ofdm_cdd[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->ofdm_cdd[i] % BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "40 MHz OFDM SISO "); ++ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->ofdm_40_siso[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->ofdm_40_siso[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "40 MHz OFDM CDD "); ++ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->ofdm_40_cdd[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->ofdm_40_cdd[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "20 MHz MCS0-7 SISO "); ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->mcs_20_siso[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs_20_siso[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "20 MHz MCS0-7 CDD "); ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->mcs_20_cdd[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs_20_cdd[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "20 MHz MCS0-7 STBC "); ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->mcs_20_stbc[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs_20_stbc[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "20 MHz MCS8-15 SDM "); ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->mcs_20_mimo[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs_20_mimo[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "40 MHz MCS0-7 SISO "); ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->mcs_40_siso[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs_40_siso[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "40 MHz MCS0-7 CDD "); ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->mcs_40_cdd[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs_40_cdd[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "40 MHz MCS0-7 STBC "); ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->mcs_40_stbc[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs_40_stbc[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ sprintf(buf, "40 MHz MCS8-15 SDM "); ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) ++ sprintf(buf[strlen(buf)], " %2d%s", ++ txpwr->mcs_40_mimo[i] / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs_40_mimo[i] % ++ BRCMS_TXPWR_DB_FACTOR]); ++ } ++ printk(KERN_DEBUG "%s\n", buf); ++ ++ printk(KERN_DEBUG "MCS32 %2d%s\n", ++ txpwr->mcs32 / BRCMS_TXPWR_DB_FACTOR, ++ fraction[txpwr->mcs32 % BRCMS_TXPWR_DB_FACTOR]); ++} ++#endif /* POWER_DBG */ ++ ++void ++brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, ++ struct txpwr_limits *txpwr) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ uint i; ++ uint chan; ++ int maxpwr; ++ int delta; ++ const struct country_info *country; ++ struct brcms_band *band; ++ const struct locale_info *li; ++ int conducted_max = BRCMS_TXPWR_MAX; ++ int conducted_ofdm_max = BRCMS_TXPWR_MAX; ++ const struct locale_mimo_info *li_mimo; ++ int maxpwr20, maxpwr40; ++ int maxpwr_idx; ++ uint j; ++ ++ memset(txpwr, 0, sizeof(struct txpwr_limits)); ++ ++ if (!brcms_c_valid_chanspec_db(wlc_cm, chanspec)) { ++ country = brcms_c_country_lookup(wlc, wlc->autocountry_default); ++ if (country == NULL) ++ return; ++ } else { ++ country = wlc_cm->country; ++ } ++ ++ chan = CHSPEC_CHANNEL(chanspec); ++ band = wlc->bandstate[chspec_bandunit(chanspec)]; ++ li = (band->bandtype == BRCM_BAND_5G) ? ++ brcms_c_get_locale_5g(country->locale_5G) : ++ brcms_c_get_locale_2g(country->locale_2G); ++ ++ li_mimo = (band->bandtype == BRCM_BAND_5G) ? ++ brcms_c_get_mimo_5g(country->locale_mimo_5G) : ++ brcms_c_get_mimo_2g(country->locale_mimo_2G); ++ ++ if (li->flags & BRCMS_EIRP) { ++ delta = band->antgain; ++ } else { ++ delta = 0; ++ if (band->antgain > QDB(6)) ++ delta = band->antgain - QDB(6); /* Excess over 6 dB */ ++ } ++ ++ if (li == &locale_i) { ++ conducted_max = QDB(22); ++ conducted_ofdm_max = QDB(22); ++ } ++ ++ /* CCK txpwr limits for 2.4G band */ ++ if (band->bandtype == BRCM_BAND_2G) { ++ maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_CCK(chan)]; ++ ++ maxpwr = maxpwr - delta; ++ maxpwr = max(maxpwr, 0); ++ maxpwr = min(maxpwr, conducted_max); ++ ++ for (i = 0; i < BRCMS_NUM_RATES_CCK; i++) ++ txpwr->cck[i] = (u8) maxpwr; ++ } ++ ++ /* OFDM txpwr limits for 2.4G or 5G bands */ ++ if (band->bandtype == BRCM_BAND_2G) ++ maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_OFDM(chan)]; ++ else ++ maxpwr = li->maxpwr[CHANNEL_POWER_IDX_5G(chan)]; ++ ++ maxpwr = maxpwr - delta; ++ maxpwr = max(maxpwr, 0); ++ maxpwr = min(maxpwr, conducted_ofdm_max); ++ ++ /* Keep OFDM lmit below CCK limit */ ++ if (band->bandtype == BRCM_BAND_2G) ++ maxpwr = min_t(int, maxpwr, txpwr->cck[0]); ++ ++ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) ++ txpwr->ofdm[i] = (u8) maxpwr; ++ ++ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) { ++ /* ++ * OFDM 40 MHz SISO has the same power as the corresponding ++ * MCS0-7 rate unless overriden by the locale specific code. ++ * We set this value to 0 as a flag (presumably 0 dBm isn't ++ * a possibility) and then copy the MCS0-7 value to the 40 MHz ++ * value if it wasn't explicitly set. ++ */ ++ txpwr->ofdm_40_siso[i] = 0; ++ ++ txpwr->ofdm_cdd[i] = (u8) maxpwr; ++ ++ txpwr->ofdm_40_cdd[i] = 0; ++ } ++ ++ /* MIMO/HT specific limits */ ++ if (li_mimo->flags & BRCMS_EIRP) { ++ delta = band->antgain; ++ } else { ++ delta = 0; ++ if (band->antgain > QDB(6)) ++ delta = band->antgain - QDB(6); /* Excess over 6 dB */ ++ } ++ ++ if (band->bandtype == BRCM_BAND_2G) ++ maxpwr_idx = (chan - 1); ++ else ++ maxpwr_idx = CHANNEL_POWER_IDX_5G(chan); ++ ++ maxpwr20 = li_mimo->maxpwr20[maxpwr_idx]; ++ maxpwr40 = li_mimo->maxpwr40[maxpwr_idx]; ++ ++ maxpwr20 = maxpwr20 - delta; ++ maxpwr20 = max(maxpwr20, 0); ++ maxpwr40 = maxpwr40 - delta; ++ maxpwr40 = max(maxpwr40, 0); ++ ++ /* Fill in the MCS 0-7 (SISO) rates */ ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { ++ ++ /* ++ * 20 MHz has the same power as the corresponding OFDM rate ++ * unless overriden by the locale specific code. ++ */ ++ txpwr->mcs_20_siso[i] = txpwr->ofdm[i]; ++ txpwr->mcs_40_siso[i] = 0; ++ } ++ ++ /* Fill in the MCS 0-7 CDD rates */ ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { ++ txpwr->mcs_20_cdd[i] = (u8) maxpwr20; ++ txpwr->mcs_40_cdd[i] = (u8) maxpwr40; ++ } ++ ++ /* ++ * These locales have SISO expressed in the ++ * table and override CDD later ++ */ ++ if (li_mimo == &locale_bn) { ++ if (li_mimo == &locale_bn) { ++ maxpwr20 = QDB(16); ++ maxpwr40 = 0; ++ ++ if (chan >= 3 && chan <= 11) ++ maxpwr40 = QDB(16); ++ } ++ ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { ++ txpwr->mcs_20_siso[i] = (u8) maxpwr20; ++ txpwr->mcs_40_siso[i] = (u8) maxpwr40; ++ } ++ } ++ ++ /* Fill in the MCS 0-7 STBC rates */ ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { ++ txpwr->mcs_20_stbc[i] = 0; ++ txpwr->mcs_40_stbc[i] = 0; ++ } ++ ++ /* Fill in the MCS 8-15 SDM rates */ ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) { ++ txpwr->mcs_20_mimo[i] = (u8) maxpwr20; ++ txpwr->mcs_40_mimo[i] = (u8) maxpwr40; ++ } ++ ++ /* Fill in MCS32 */ ++ txpwr->mcs32 = (u8) maxpwr40; ++ ++ for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) { ++ if (txpwr->ofdm_40_cdd[i] == 0) ++ txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j]; ++ if (i == 0) { ++ i = i + 1; ++ if (txpwr->ofdm_40_cdd[i] == 0) ++ txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j]; ++ } ++ } ++ ++ /* ++ * Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO ++ * value if it wasn't provided explicitly. ++ */ ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { ++ if (txpwr->mcs_40_siso[i] == 0) ++ txpwr->mcs_40_siso[i] = txpwr->mcs_40_cdd[i]; ++ } ++ ++ for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) { ++ if (txpwr->ofdm_40_siso[i] == 0) ++ txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j]; ++ if (i == 0) { ++ i = i + 1; ++ if (txpwr->ofdm_40_siso[i] == 0) ++ txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j]; ++ } ++ } ++ ++ /* ++ * Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding ++ * STBC values if they weren't provided explicitly. ++ */ ++ for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) { ++ if (txpwr->mcs_20_stbc[i] == 0) ++ txpwr->mcs_20_stbc[i] = txpwr->mcs_20_cdd[i]; ++ ++ if (txpwr->mcs_40_stbc[i] == 0) ++ txpwr->mcs_40_stbc[i] = txpwr->mcs_40_cdd[i]; ++ } ++ ++#ifdef POWER_DBG ++ wlc_phy_txpower_limits_dump(txpwr); ++#endif ++ return; ++} ++ ++/* ++ * Verify the chanspec is using a legal set of parameters, i.e. that the ++ * chanspec specified a band, bw, ctl_sb and channel and that the ++ * combination could be legal given any set of circumstances. ++ * RETURNS: true is the chanspec is malformed, false if it looks good. ++ */ ++static bool brcms_c_chspec_malformed(u16 chanspec) ++{ ++ /* must be 2G or 5G band */ ++ if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec)) ++ return true; ++ /* must be 20 or 40 bandwidth */ ++ if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec)) ++ return true; ++ ++ /* 20MHZ b/w must have no ctl sb, 40 must have a ctl sb */ ++ if (CHSPEC_IS20(chanspec)) { ++ if (!CHSPEC_SB_NONE(chanspec)) ++ return true; ++ } else if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) { ++ return true; ++ } ++ ++ return false; ++} ++ ++/* ++ * Validate the chanspec for this locale, for 40MHZ we need to also ++ * check that the sidebands are valid 20MZH channels in this locale ++ * and they are also a legal HT combination ++ */ ++static bool ++brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec, ++ bool dualband) ++{ ++ struct brcms_c_info *wlc = wlc_cm->wlc; ++ u8 channel = CHSPEC_CHANNEL(chspec); ++ ++ /* check the chanspec */ ++ if (brcms_c_chspec_malformed(chspec)) { ++ wiphy_err(wlc->wiphy, "wl%d: malformed chanspec 0x%x\n", ++ wlc->pub->unit, chspec); ++ return false; ++ } ++ ++ if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) != ++ chspec_bandunit(chspec)) ++ return false; ++ ++ /* Check a 20Mhz channel */ ++ if (CHSPEC_IS20(chspec)) { ++ if (dualband) ++ return brcms_c_valid_channel20_db(wlc_cm->wlc->cmi, ++ channel); ++ else ++ return brcms_c_valid_channel20(wlc_cm->wlc->cmi, ++ channel); ++ } ++#ifdef SUPPORT_40MHZ ++ /* ++ * We know we are now checking a 40MHZ channel, so we should ++ * only be here for NPHYS ++ */ ++ if (BRCMS_ISNPHY(wlc->band) || BRCMS_ISSSLPNPHY(wlc->band)) { ++ u8 upper_sideband = 0, idx; ++ u8 num_ch20_entries = ++ sizeof(chan20_info) / sizeof(struct chan20_info); ++ ++ if (!VALID_40CHANSPEC_IN_BAND(wlc, chspec_bandunit(chspec))) ++ return false; ++ ++ if (dualband) { ++ if (!brcms_c_valid_channel20_db(wlc->cmi, ++ lower_20_sb(channel)) || ++ !brcms_c_valid_channel20_db(wlc->cmi, ++ upper_20_sb(channel))) ++ return false; ++ } else { ++ if (!brcms_c_valid_channel20(wlc->cmi, ++ lower_20_sb(channel)) || ++ !brcms_c_valid_channel20(wlc->cmi, ++ upper_20_sb(channel))) ++ return false; ++ } ++ ++ /* find the lower sideband info in the sideband array */ ++ for (idx = 0; idx < num_ch20_entries; idx++) { ++ if (chan20_info[idx].sb == lower_20_sb(channel)) ++ upper_sideband = chan20_info[idx].adj_sbs; ++ } ++ /* check that the lower sideband allows an upper sideband */ ++ if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) == ++ (CH_UPPER_SB | CH_EWA_VALID)) ++ return true; ++ return false; ++ } ++#endif /* 40 MHZ */ ++ ++ return false; ++} ++ ++bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec) ++{ ++ return brcms_c_valid_chanspec_ext(wlc_cm, chspec, true); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.h.orig 2011-11-09 13:46:58.242800670 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/channel.h 2011-11-09 13:47:16.994566241 -0500 +@@ -0,0 +1,53 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_CHANNEL_H_ ++#define _BRCM_CHANNEL_H_ ++ ++/* conversion for phy txpwr calculations that use .25 dB units */ ++#define BRCMS_TXPWR_DB_FACTOR 4 ++ ++/* bits for locale_info flags */ ++#define BRCMS_PEAK_CONDUCTED 0x00 /* Peak for locals */ ++#define BRCMS_EIRP 0x01 /* Flag for EIRP */ ++#define BRCMS_DFS_TPC 0x02 /* Flag for DFS TPC */ ++#define BRCMS_NO_OFDM 0x04 /* Flag for No OFDM */ ++#define BRCMS_NO_40MHZ 0x08 /* Flag for No MIMO 40MHz */ ++#define BRCMS_NO_MIMO 0x10 /* Flag for No MIMO, 20 or 40 MHz */ ++#define BRCMS_RADAR_TYPE_EU 0x20 /* Flag for EU */ ++#define BRCMS_DFS_FCC BRCMS_DFS_TPC /* Flag for DFS FCC */ ++ ++#define BRCMS_DFS_EU (BRCMS_DFS_TPC | BRCMS_RADAR_TYPE_EU) /* Flag for DFS EU */ ++ ++extern struct brcms_cm_info * ++brcms_c_channel_mgr_attach(struct brcms_c_info *wlc); ++ ++extern void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm); ++ ++extern u8 brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm, ++ uint bandunit); ++ ++extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, ++ u16 chspec); ++ ++extern void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, ++ u16 chanspec, ++ struct txpwr_limits *txpwr); ++extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, ++ u16 chanspec, ++ u8 local_constraint_qdbm); ++ ++#endif /* _WLC_CHANNEL_H */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/d11.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/d11.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/d11.h.orig 2011-11-09 13:46:58.243800657 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/d11.h 2011-11-09 13:47:16.996566217 -0500 +@@ -0,0 +1,1898 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_D11_H_ ++#define _BRCM_D11_H_ ++ ++#include ++ ++#include ++#include "pub.h" ++#include "dma.h" ++ ++/* RX FIFO numbers */ ++#define RX_FIFO 0 /* data and ctl frames */ ++#define RX_TXSTATUS_FIFO 3 /* RX fifo for tx status packages */ ++ ++/* TX FIFO numbers using WME Access Category */ ++#define TX_AC_BK_FIFO 0 /* Background TX FIFO */ ++#define TX_AC_BE_FIFO 1 /* Best-Effort TX FIFO */ ++#define TX_AC_VI_FIFO 2 /* Video TX FIFO */ ++#define TX_AC_VO_FIFO 3 /* Voice TX FIFO */ ++#define TX_BCMC_FIFO 4 /* Broadcast/Multicast TX FIFO */ ++#define TX_ATIM_FIFO 5 /* TX fifo for ATIM window info */ ++ ++/* Addr is byte address used by SW; offset is word offset used by uCode */ ++ ++/* Per AC TX limit settings */ ++#define M_AC_TXLMT_BASE_ADDR (0x180 * 2) ++#define M_AC_TXLMT_ADDR(_ac) (M_AC_TXLMT_BASE_ADDR + (2 * (_ac))) ++ ++/* Legacy TX FIFO numbers */ ++#define TX_DATA_FIFO TX_AC_BE_FIFO ++#define TX_CTL_FIFO TX_AC_VO_FIFO ++ ++#define WL_RSSI_ANT_MAX 4 /* max possible rx antennas */ ++ ++struct intctrlregs { ++ u32 intstatus; ++ u32 intmask; ++}; ++ ++/* PIO structure, ++ * support two PIO format: 2 bytes access and 4 bytes access ++ * basic FIFO register set is per channel(transmit or receive) ++ * a pair of channels is defined for convenience ++ */ ++/* 2byte-wide pio register set per channel(xmt or rcv) */ ++struct pio2regs { ++ u16 fifocontrol; ++ u16 fifodata; ++ u16 fifofree; /* only valid in xmt channel, not in rcv channel */ ++ u16 PAD; ++}; ++ ++/* a pair of pio channels(tx and rx) */ ++struct pio2regp { ++ struct pio2regs tx; ++ struct pio2regs rx; ++}; ++ ++/* 4byte-wide pio register set per channel(xmt or rcv) */ ++struct pio4regs { ++ u32 fifocontrol; ++ u32 fifodata; ++}; ++ ++/* a pair of pio channels(tx and rx) */ ++struct pio4regp { ++ struct pio4regs tx; ++ struct pio4regs rx; ++}; ++ ++/* read: 32-bit register that can be read as 32-bit or as 2 16-bit ++ * write: only low 16b-it half can be written ++ */ ++union pmqreg { ++ u32 pmqhostdata; /* read only! */ ++ struct { ++ u16 pmqctrlstatus; /* read/write */ ++ u16 PAD; ++ } w; ++}; ++ ++struct fifo64 { ++ struct dma64regs dmaxmt; /* dma tx */ ++ struct pio4regs piotx; /* pio tx */ ++ struct dma64regs dmarcv; /* dma rx */ ++ struct pio4regs piorx; /* pio rx */ ++}; ++ ++/* ++ * Host Interface Registers ++ */ ++struct d11regs { ++ /* Device Control ("semi-standard host registers") */ ++ u32 PAD[3]; /* 0x0 - 0x8 */ ++ u32 biststatus; /* 0xC */ ++ u32 biststatus2; /* 0x10 */ ++ u32 PAD; /* 0x14 */ ++ u32 gptimer; /* 0x18 */ ++ u32 usectimer; /* 0x1c *//* for corerev >= 26 */ ++ ++ /* Interrupt Control *//* 0x20 */ ++ struct intctrlregs intctrlregs[8]; ++ ++ u32 PAD[40]; /* 0x60 - 0xFC */ ++ ++ u32 intrcvlazy[4]; /* 0x100 - 0x10C */ ++ ++ u32 PAD[4]; /* 0x110 - 0x11c */ ++ ++ u32 maccontrol; /* 0x120 */ ++ u32 maccommand; /* 0x124 */ ++ u32 macintstatus; /* 0x128 */ ++ u32 macintmask; /* 0x12C */ ++ ++ /* Transmit Template Access */ ++ u32 tplatewrptr; /* 0x130 */ ++ u32 tplatewrdata; /* 0x134 */ ++ u32 PAD[2]; /* 0x138 - 0x13C */ ++ ++ /* PMQ registers */ ++ union pmqreg pmqreg; /* 0x140 */ ++ u32 pmqpatl; /* 0x144 */ ++ u32 pmqpath; /* 0x148 */ ++ u32 PAD; /* 0x14C */ ++ ++ u32 chnstatus; /* 0x150 */ ++ u32 psmdebug; /* 0x154 */ ++ u32 phydebug; /* 0x158 */ ++ u32 machwcap; /* 0x15C */ ++ ++ /* Extended Internal Objects */ ++ u32 objaddr; /* 0x160 */ ++ u32 objdata; /* 0x164 */ ++ u32 PAD[2]; /* 0x168 - 0x16c */ ++ ++ u32 frmtxstatus; /* 0x170 */ ++ u32 frmtxstatus2; /* 0x174 */ ++ u32 PAD[2]; /* 0x178 - 0x17c */ ++ ++ /* TSF host access */ ++ u32 tsf_timerlow; /* 0x180 */ ++ u32 tsf_timerhigh; /* 0x184 */ ++ u32 tsf_cfprep; /* 0x188 */ ++ u32 tsf_cfpstart; /* 0x18c */ ++ u32 tsf_cfpmaxdur32; /* 0x190 */ ++ u32 PAD[3]; /* 0x194 - 0x19c */ ++ ++ u32 maccontrol1; /* 0x1a0 */ ++ u32 machwcap1; /* 0x1a4 */ ++ u32 PAD[14]; /* 0x1a8 - 0x1dc */ ++ ++ /* Clock control and hardware workarounds*/ ++ u32 clk_ctl_st; /* 0x1e0 */ ++ u32 hw_war; ++ u32 d11_phypllctl; /* the phypll request/avail bits are ++ * moved to clk_ctl_st ++ */ ++ u32 PAD[5]; /* 0x1ec - 0x1fc */ ++ ++ /* 0x200-0x37F dma/pio registers */ ++ struct fifo64 fifo64regs[6]; ++ ++ /* FIFO diagnostic port access */ ++ struct dma32diag dmafifo; /* 0x380 - 0x38C */ ++ ++ u32 aggfifocnt; /* 0x390 */ ++ u32 aggfifodata; /* 0x394 */ ++ u32 PAD[16]; /* 0x398 - 0x3d4 */ ++ u16 radioregaddr; /* 0x3d8 */ ++ u16 radioregdata; /* 0x3da */ ++ ++ /* ++ * time delay between the change on rf disable input and ++ * radio shutdown ++ */ ++ u32 rfdisabledly; /* 0x3DC */ ++ ++ /* PHY register access */ ++ u16 phyversion; /* 0x3e0 - 0x0 */ ++ u16 phybbconfig; /* 0x3e2 - 0x1 */ ++ u16 phyadcbias; /* 0x3e4 - 0x2 Bphy only */ ++ u16 phyanacore; /* 0x3e6 - 0x3 pwwrdwn on aphy */ ++ u16 phyrxstatus0; /* 0x3e8 - 0x4 */ ++ u16 phyrxstatus1; /* 0x3ea - 0x5 */ ++ u16 phycrsth; /* 0x3ec - 0x6 */ ++ u16 phytxerror; /* 0x3ee - 0x7 */ ++ u16 phychannel; /* 0x3f0 - 0x8 */ ++ u16 PAD[1]; /* 0x3f2 - 0x9 */ ++ u16 phytest; /* 0x3f4 - 0xa */ ++ u16 phy4waddr; /* 0x3f6 - 0xb */ ++ u16 phy4wdatahi; /* 0x3f8 - 0xc */ ++ u16 phy4wdatalo; /* 0x3fa - 0xd */ ++ u16 phyregaddr; /* 0x3fc - 0xe */ ++ u16 phyregdata; /* 0x3fe - 0xf */ ++ ++ /* IHR *//* 0x400 - 0x7FE */ ++ ++ /* RXE Block */ ++ u16 PAD[3]; /* 0x400 - 0x406 */ ++ u16 rcv_fifo_ctl; /* 0x406 */ ++ u16 PAD; /* 0x408 - 0x40a */ ++ u16 rcv_frm_cnt; /* 0x40a */ ++ u16 PAD[4]; /* 0x40a - 0x414 */ ++ u16 rssi; /* 0x414 */ ++ u16 PAD[5]; /* 0x414 - 0x420 */ ++ u16 rcm_ctl; /* 0x420 */ ++ u16 rcm_mat_data; /* 0x422 */ ++ u16 rcm_mat_mask; /* 0x424 */ ++ u16 rcm_mat_dly; /* 0x426 */ ++ u16 rcm_cond_mask_l; /* 0x428 */ ++ u16 rcm_cond_mask_h; /* 0x42A */ ++ u16 rcm_cond_dly; /* 0x42C */ ++ u16 PAD[1]; /* 0x42E */ ++ u16 ext_ihr_addr; /* 0x430 */ ++ u16 ext_ihr_data; /* 0x432 */ ++ u16 rxe_phyrs_2; /* 0x434 */ ++ u16 rxe_phyrs_3; /* 0x436 */ ++ u16 phy_mode; /* 0x438 */ ++ u16 rcmta_ctl; /* 0x43a */ ++ u16 rcmta_size; /* 0x43c */ ++ u16 rcmta_addr0; /* 0x43e */ ++ u16 rcmta_addr1; /* 0x440 */ ++ u16 rcmta_addr2; /* 0x442 */ ++ u16 PAD[30]; /* 0x444 - 0x480 */ ++ ++ /* PSM Block *//* 0x480 - 0x500 */ ++ ++ u16 PAD; /* 0x480 */ ++ u16 psm_maccontrol_h; /* 0x482 */ ++ u16 psm_macintstatus_l; /* 0x484 */ ++ u16 psm_macintstatus_h; /* 0x486 */ ++ u16 psm_macintmask_l; /* 0x488 */ ++ u16 psm_macintmask_h; /* 0x48A */ ++ u16 PAD; /* 0x48C */ ++ u16 psm_maccommand; /* 0x48E */ ++ u16 psm_brc; /* 0x490 */ ++ u16 psm_phy_hdr_param; /* 0x492 */ ++ u16 psm_postcard; /* 0x494 */ ++ u16 psm_pcard_loc_l; /* 0x496 */ ++ u16 psm_pcard_loc_h; /* 0x498 */ ++ u16 psm_gpio_in; /* 0x49A */ ++ u16 psm_gpio_out; /* 0x49C */ ++ u16 psm_gpio_oe; /* 0x49E */ ++ ++ u16 psm_bred_0; /* 0x4A0 */ ++ u16 psm_bred_1; /* 0x4A2 */ ++ u16 psm_bred_2; /* 0x4A4 */ ++ u16 psm_bred_3; /* 0x4A6 */ ++ u16 psm_brcl_0; /* 0x4A8 */ ++ u16 psm_brcl_1; /* 0x4AA */ ++ u16 psm_brcl_2; /* 0x4AC */ ++ u16 psm_brcl_3; /* 0x4AE */ ++ u16 psm_brpo_0; /* 0x4B0 */ ++ u16 psm_brpo_1; /* 0x4B2 */ ++ u16 psm_brpo_2; /* 0x4B4 */ ++ u16 psm_brpo_3; /* 0x4B6 */ ++ u16 psm_brwk_0; /* 0x4B8 */ ++ u16 psm_brwk_1; /* 0x4BA */ ++ u16 psm_brwk_2; /* 0x4BC */ ++ u16 psm_brwk_3; /* 0x4BE */ ++ ++ u16 psm_base_0; /* 0x4C0 */ ++ u16 psm_base_1; /* 0x4C2 */ ++ u16 psm_base_2; /* 0x4C4 */ ++ u16 psm_base_3; /* 0x4C6 */ ++ u16 psm_base_4; /* 0x4C8 */ ++ u16 psm_base_5; /* 0x4CA */ ++ u16 psm_base_6; /* 0x4CC */ ++ u16 psm_pc_reg_0; /* 0x4CE */ ++ u16 psm_pc_reg_1; /* 0x4D0 */ ++ u16 psm_pc_reg_2; /* 0x4D2 */ ++ u16 psm_pc_reg_3; /* 0x4D4 */ ++ u16 PAD[0xD]; /* 0x4D6 - 0x4DE */ ++ u16 psm_corectlsts; /* 0x4f0 *//* Corerev >= 13 */ ++ u16 PAD[0x7]; /* 0x4f2 - 0x4fE */ ++ ++ /* TXE0 Block *//* 0x500 - 0x580 */ ++ u16 txe_ctl; /* 0x500 */ ++ u16 txe_aux; /* 0x502 */ ++ u16 txe_ts_loc; /* 0x504 */ ++ u16 txe_time_out; /* 0x506 */ ++ u16 txe_wm_0; /* 0x508 */ ++ u16 txe_wm_1; /* 0x50A */ ++ u16 txe_phyctl; /* 0x50C */ ++ u16 txe_status; /* 0x50E */ ++ u16 txe_mmplcp0; /* 0x510 */ ++ u16 txe_mmplcp1; /* 0x512 */ ++ u16 txe_phyctl1; /* 0x514 */ ++ ++ u16 PAD[0x05]; /* 0x510 - 0x51E */ ++ ++ /* Transmit control */ ++ u16 xmtfifodef; /* 0x520 */ ++ u16 xmtfifo_frame_cnt; /* 0x522 *//* Corerev >= 16 */ ++ u16 xmtfifo_byte_cnt; /* 0x524 *//* Corerev >= 16 */ ++ u16 xmtfifo_head; /* 0x526 *//* Corerev >= 16 */ ++ u16 xmtfifo_rd_ptr; /* 0x528 *//* Corerev >= 16 */ ++ u16 xmtfifo_wr_ptr; /* 0x52A *//* Corerev >= 16 */ ++ u16 xmtfifodef1; /* 0x52C *//* Corerev >= 16 */ ++ ++ u16 PAD[0x09]; /* 0x52E - 0x53E */ ++ ++ u16 xmtfifocmd; /* 0x540 */ ++ u16 xmtfifoflush; /* 0x542 */ ++ u16 xmtfifothresh; /* 0x544 */ ++ u16 xmtfifordy; /* 0x546 */ ++ u16 xmtfifoprirdy; /* 0x548 */ ++ u16 xmtfiforqpri; /* 0x54A */ ++ u16 xmttplatetxptr; /* 0x54C */ ++ u16 PAD; /* 0x54E */ ++ u16 xmttplateptr; /* 0x550 */ ++ u16 smpl_clct_strptr; /* 0x552 *//* Corerev >= 22 */ ++ u16 smpl_clct_stpptr; /* 0x554 *//* Corerev >= 22 */ ++ u16 smpl_clct_curptr; /* 0x556 *//* Corerev >= 22 */ ++ u16 PAD[0x04]; /* 0x558 - 0x55E */ ++ u16 xmttplatedatalo; /* 0x560 */ ++ u16 xmttplatedatahi; /* 0x562 */ ++ ++ u16 PAD[2]; /* 0x564 - 0x566 */ ++ ++ u16 xmtsel; /* 0x568 */ ++ u16 xmttxcnt; /* 0x56A */ ++ u16 xmttxshmaddr; /* 0x56C */ ++ ++ u16 PAD[0x09]; /* 0x56E - 0x57E */ ++ ++ /* TXE1 Block */ ++ u16 PAD[0x40]; /* 0x580 - 0x5FE */ ++ ++ /* TSF Block */ ++ u16 PAD[0X02]; /* 0x600 - 0x602 */ ++ u16 tsf_cfpstrt_l; /* 0x604 */ ++ u16 tsf_cfpstrt_h; /* 0x606 */ ++ u16 PAD[0X05]; /* 0x608 - 0x610 */ ++ u16 tsf_cfppretbtt; /* 0x612 */ ++ u16 PAD[0XD]; /* 0x614 - 0x62C */ ++ u16 tsf_clk_frac_l; /* 0x62E */ ++ u16 tsf_clk_frac_h; /* 0x630 */ ++ u16 PAD[0X14]; /* 0x632 - 0x658 */ ++ u16 tsf_random; /* 0x65A */ ++ u16 PAD[0x05]; /* 0x65C - 0x664 */ ++ /* GPTimer 2 registers */ ++ u16 tsf_gpt2_stat; /* 0x666 */ ++ u16 tsf_gpt2_ctr_l; /* 0x668 */ ++ u16 tsf_gpt2_ctr_h; /* 0x66A */ ++ u16 tsf_gpt2_val_l; /* 0x66C */ ++ u16 tsf_gpt2_val_h; /* 0x66E */ ++ u16 tsf_gptall_stat; /* 0x670 */ ++ u16 PAD[0x07]; /* 0x672 - 0x67E */ ++ ++ /* IFS Block */ ++ u16 ifs_sifs_rx_tx_tx; /* 0x680 */ ++ u16 ifs_sifs_nav_tx; /* 0x682 */ ++ u16 ifs_slot; /* 0x684 */ ++ u16 PAD; /* 0x686 */ ++ u16 ifs_ctl; /* 0x688 */ ++ u16 PAD[0x3]; /* 0x68a - 0x68F */ ++ u16 ifsstat; /* 0x690 */ ++ u16 ifsmedbusyctl; /* 0x692 */ ++ u16 iftxdur; /* 0x694 */ ++ u16 PAD[0x3]; /* 0x696 - 0x69b */ ++ /* EDCF support in dot11macs */ ++ u16 ifs_aifsn; /* 0x69c */ ++ u16 ifs_ctl1; /* 0x69e */ ++ ++ /* slow clock registers */ ++ u16 scc_ctl; /* 0x6a0 */ ++ u16 scc_timer_l; /* 0x6a2 */ ++ u16 scc_timer_h; /* 0x6a4 */ ++ u16 scc_frac; /* 0x6a6 */ ++ u16 scc_fastpwrup_dly; /* 0x6a8 */ ++ u16 scc_per; /* 0x6aa */ ++ u16 scc_per_frac; /* 0x6ac */ ++ u16 scc_cal_timer_l; /* 0x6ae */ ++ u16 scc_cal_timer_h; /* 0x6b0 */ ++ u16 PAD; /* 0x6b2 */ ++ ++ u16 PAD[0x26]; ++ ++ /* NAV Block */ ++ u16 nav_ctl; /* 0x700 */ ++ u16 navstat; /* 0x702 */ ++ u16 PAD[0x3e]; /* 0x702 - 0x77E */ ++ ++ /* WEP/PMQ Block *//* 0x780 - 0x7FE */ ++ u16 PAD[0x20]; /* 0x780 - 0x7BE */ ++ ++ u16 wepctl; /* 0x7C0 */ ++ u16 wepivloc; /* 0x7C2 */ ++ u16 wepivkey; /* 0x7C4 */ ++ u16 wepwkey; /* 0x7C6 */ ++ ++ u16 PAD[4]; /* 0x7C8 - 0x7CE */ ++ u16 pcmctl; /* 0X7D0 */ ++ u16 pcmstat; /* 0X7D2 */ ++ u16 PAD[6]; /* 0x7D4 - 0x7DE */ ++ ++ u16 pmqctl; /* 0x7E0 */ ++ u16 pmqstatus; /* 0x7E2 */ ++ u16 pmqpat0; /* 0x7E4 */ ++ u16 pmqpat1; /* 0x7E6 */ ++ u16 pmqpat2; /* 0x7E8 */ ++ ++ u16 pmqdat; /* 0x7EA */ ++ u16 pmqdator; /* 0x7EC */ ++ u16 pmqhst; /* 0x7EE */ ++ u16 pmqpath0; /* 0x7F0 */ ++ u16 pmqpath1; /* 0x7F2 */ ++ u16 pmqpath2; /* 0x7F4 */ ++ u16 pmqdath; /* 0x7F6 */ ++ ++ u16 PAD[0x04]; /* 0x7F8 - 0x7FE */ ++ ++ /* SHM *//* 0x800 - 0xEFE */ ++ u16 PAD[0x380]; /* 0x800 - 0xEFE */ ++}; ++ ++#define PIHR_BASE 0x0400 /* byte address of packed IHR region */ ++ ++/* biststatus */ ++#define BT_DONE (1U << 31) /* bist done */ ++#define BT_B2S (1 << 30) /* bist2 ram summary bit */ ++ ++/* intstatus and intmask */ ++#define I_PC (1 << 10) /* pci descriptor error */ ++#define I_PD (1 << 11) /* pci data error */ ++#define I_DE (1 << 12) /* descriptor protocol error */ ++#define I_RU (1 << 13) /* receive descriptor underflow */ ++#define I_RO (1 << 14) /* receive fifo overflow */ ++#define I_XU (1 << 15) /* transmit fifo underflow */ ++#define I_RI (1 << 16) /* receive interrupt */ ++#define I_XI (1 << 24) /* transmit interrupt */ ++ ++/* interrupt receive lazy */ ++#define IRL_TO_MASK 0x00ffffff /* timeout */ ++#define IRL_FC_MASK 0xff000000 /* frame count */ ++#define IRL_FC_SHIFT 24 /* frame count */ ++ ++/*== maccontrol register ==*/ ++#define MCTL_GMODE (1U << 31) ++#define MCTL_DISCARD_PMQ (1 << 30) ++#define MCTL_WAKE (1 << 26) ++#define MCTL_HPS (1 << 25) ++#define MCTL_PROMISC (1 << 24) ++#define MCTL_KEEPBADFCS (1 << 23) ++#define MCTL_KEEPCONTROL (1 << 22) ++#define MCTL_PHYLOCK (1 << 21) ++#define MCTL_BCNS_PROMISC (1 << 20) ++#define MCTL_LOCK_RADIO (1 << 19) ++#define MCTL_AP (1 << 18) ++#define MCTL_INFRA (1 << 17) ++#define MCTL_BIGEND (1 << 16) ++#define MCTL_GPOUT_SEL_MASK (3 << 14) ++#define MCTL_GPOUT_SEL_SHIFT 14 ++#define MCTL_EN_PSMDBG (1 << 13) ++#define MCTL_IHR_EN (1 << 10) ++#define MCTL_SHM_UPPER (1 << 9) ++#define MCTL_SHM_EN (1 << 8) ++#define MCTL_PSM_JMP_0 (1 << 2) ++#define MCTL_PSM_RUN (1 << 1) ++#define MCTL_EN_MAC (1 << 0) ++ ++/*== maccommand register ==*/ ++#define MCMD_BCN0VLD (1 << 0) ++#define MCMD_BCN1VLD (1 << 1) ++#define MCMD_DIRFRMQVAL (1 << 2) ++#define MCMD_CCA (1 << 3) ++#define MCMD_BG_NOISE (1 << 4) ++#define MCMD_SKIP_SHMINIT (1 << 5) /* only used for simulation */ ++#define MCMD_SAMPLECOLL MCMD_SKIP_SHMINIT /* reuse for sample collect */ ++ ++/*== macintstatus/macintmask ==*/ ++/* gracefully suspended */ ++#define MI_MACSSPNDD (1 << 0) ++/* beacon template available */ ++#define MI_BCNTPL (1 << 1) ++/* TBTT indication */ ++#define MI_TBTT (1 << 2) ++/* beacon successfully tx'd */ ++#define MI_BCNSUCCESS (1 << 3) ++/* beacon canceled (IBSS) */ ++#define MI_BCNCANCLD (1 << 4) ++/* end of ATIM-window (IBSS) */ ++#define MI_ATIMWINEND (1 << 5) ++/* PMQ entries available */ ++#define MI_PMQ (1 << 6) ++/* non-specific gen-stat bits that are set by PSM */ ++#define MI_NSPECGEN_0 (1 << 7) ++/* non-specific gen-stat bits that are set by PSM */ ++#define MI_NSPECGEN_1 (1 << 8) ++/* MAC level Tx error */ ++#define MI_MACTXERR (1 << 9) ++/* non-specific gen-stat bits that are set by PSM */ ++#define MI_NSPECGEN_3 (1 << 10) ++/* PHY Tx error */ ++#define MI_PHYTXERR (1 << 11) ++/* Power Management Event */ ++#define MI_PME (1 << 12) ++/* General-purpose timer0 */ ++#define MI_GP0 (1 << 13) ++/* General-purpose timer1 */ ++#define MI_GP1 (1 << 14) ++/* (ORed) DMA-interrupts */ ++#define MI_DMAINT (1 << 15) ++/* MAC has completed a TX FIFO Suspend/Flush */ ++#define MI_TXSTOP (1 << 16) ++/* MAC has completed a CCA measurement */ ++#define MI_CCA (1 << 17) ++/* MAC has collected background noise samples */ ++#define MI_BG_NOISE (1 << 18) ++/* MBSS DTIM TBTT indication */ ++#define MI_DTIM_TBTT (1 << 19) ++/* Probe response queue needs attention */ ++#define MI_PRQ (1 << 20) ++/* Radio/PHY has been powered back up. */ ++#define MI_PWRUP (1 << 21) ++#define MI_RESERVED3 (1 << 22) ++#define MI_RESERVED2 (1 << 23) ++#define MI_RESERVED1 (1 << 25) ++/* MAC detected change on RF Disable input*/ ++#define MI_RFDISABLE (1 << 28) ++/* MAC has completed a TX */ ++#define MI_TFS (1 << 29) ++/* A phy status change wrt G mode */ ++#define MI_PHYCHANGED (1 << 30) ++/* general purpose timeout */ ++#define MI_TO (1U << 31) ++ ++/* Mac capabilities registers */ ++/*== machwcap ==*/ ++#define MCAP_TKIPMIC 0x80000000 /* TKIP MIC hardware present */ ++ ++/*== pmqhost data ==*/ ++/* data entry of head pmq entry */ ++#define PMQH_DATA_MASK 0xffff0000 ++/* PM entry for BSS config */ ++#define PMQH_BSSCFG 0x00100000 ++/* PM Mode OFF: power save off */ ++#define PMQH_PMOFF 0x00010000 ++/* PM Mode ON: power save on */ ++#define PMQH_PMON 0x00020000 ++/* Dis-associated or De-authenticated */ ++#define PMQH_DASAT 0x00040000 ++/* ATIM not acknowledged */ ++#define PMQH_ATIMFAIL 0x00080000 ++/* delete head entry */ ++#define PMQH_DEL_ENTRY 0x00000001 ++/* delete head entry to cur read pointer -1 */ ++#define PMQH_DEL_MULT 0x00000002 ++/* pmq overflow indication */ ++#define PMQH_OFLO 0x00000004 ++/* entries are present in pmq */ ++#define PMQH_NOT_EMPTY 0x00000008 ++ ++/*== phydebug ==*/ ++/* phy is asserting carrier sense */ ++#define PDBG_CRS (1 << 0) ++/* phy is taking xmit byte from mac this cycle */ ++#define PDBG_TXA (1 << 1) ++/* mac is instructing the phy to transmit a frame */ ++#define PDBG_TXF (1 << 2) ++/* phy is signalling a transmit Error to the mac */ ++#define PDBG_TXE (1 << 3) ++/* phy detected the end of a valid frame preamble */ ++#define PDBG_RXF (1 << 4) ++/* phy detected the end of a valid PLCP header */ ++#define PDBG_RXS (1 << 5) ++/* rx start not asserted */ ++#define PDBG_RXFRG (1 << 6) ++/* mac is taking receive byte from phy this cycle */ ++#define PDBG_RXV (1 << 7) ++/* RF portion of the radio is disabled */ ++#define PDBG_RFD (1 << 16) ++ ++/*== objaddr register ==*/ ++#define OBJADDR_SEL_MASK 0x000F0000 ++#define OBJADDR_UCM_SEL 0x00000000 ++#define OBJADDR_SHM_SEL 0x00010000 ++#define OBJADDR_SCR_SEL 0x00020000 ++#define OBJADDR_IHR_SEL 0x00030000 ++#define OBJADDR_RCMTA_SEL 0x00040000 ++#define OBJADDR_SRCHM_SEL 0x00060000 ++#define OBJADDR_WINC 0x01000000 ++#define OBJADDR_RINC 0x02000000 ++#define OBJADDR_AUTO_INC 0x03000000 ++ ++#define WEP_PCMADDR 0x07d4 ++#define WEP_PCMDATA 0x07d6 ++ ++/*== frmtxstatus ==*/ ++#define TXS_V (1 << 0) /* valid bit */ ++#define TXS_STATUS_MASK 0xffff ++#define TXS_FID_MASK 0xffff0000 ++#define TXS_FID_SHIFT 16 ++ ++/*== frmtxstatus2 ==*/ ++#define TXS_SEQ_MASK 0xffff ++#define TXS_PTX_MASK 0xff0000 ++#define TXS_PTX_SHIFT 16 ++#define TXS_MU_MASK 0x01000000 ++#define TXS_MU_SHIFT 24 ++ ++/*== clk_ctl_st ==*/ ++#define CCS_ERSRC_REQ_D11PLL 0x00000100 /* d11 core pll request */ ++#define CCS_ERSRC_REQ_PHYPLL 0x00000200 /* PHY pll request */ ++#define CCS_ERSRC_AVAIL_D11PLL 0x01000000 /* d11 core pll available */ ++#define CCS_ERSRC_AVAIL_PHYPLL 0x02000000 /* PHY pll available */ ++ ++/* HT Cloclk Ctrl and Clock Avail for 4313 */ ++#define CCS_ERSRC_REQ_HT 0x00000010 /* HT avail request */ ++#define CCS_ERSRC_AVAIL_HT 0x00020000 /* HT clock available */ ++ ++/* tsf_cfprep register */ ++#define CFPREP_CBI_MASK 0xffffffc0 ++#define CFPREP_CBI_SHIFT 6 ++#define CFPREP_CFPP 0x00000001 ++ ++/* tx fifo sizes values are in terms of 256 byte blocks */ ++#define TXFIFOCMD_RESET_MASK (1 << 15) /* reset */ ++#define TXFIFOCMD_FIFOSEL_SHIFT 8 /* fifo */ ++#define TXFIFO_FIFOTOP_SHIFT 8 /* fifo start */ ++ ++#define TXFIFO_START_BLK16 65 /* Base address + 32 * 512 B/P */ ++#define TXFIFO_START_BLK 6 /* Base address + 6 * 256 B */ ++#define TXFIFO_SIZE_UNIT 256 /* one unit corresponds to 256 bytes */ ++#define MBSS16_TEMPLMEM_MINBLKS 65 /* one unit corresponds to 256 bytes */ ++ ++/*== phy versions (PhyVersion:Revision field) ==*/ ++/* analog block version */ ++#define PV_AV_MASK 0xf000 ++/* analog block version bitfield offset */ ++#define PV_AV_SHIFT 12 ++/* phy type */ ++#define PV_PT_MASK 0x0f00 ++/* phy type bitfield offset */ ++#define PV_PT_SHIFT 8 ++/* phy version */ ++#define PV_PV_MASK 0x000f ++#define PHY_TYPE(v) ((v & PV_PT_MASK) >> PV_PT_SHIFT) ++ ++/*== phy types (PhyVersion:PhyType field) ==*/ ++#define PHY_TYPE_N 4 /* N-Phy value */ ++#define PHY_TYPE_SSN 6 /* SSLPN-Phy value */ ++#define PHY_TYPE_LCN 8 /* LCN-Phy value */ ++#define PHY_TYPE_LCNXN 9 /* LCNXN-Phy value */ ++#define PHY_TYPE_NULL 0xf /* Invalid Phy value */ ++ ++/*== analog types (PhyVersion:AnalogType field) ==*/ ++#define ANA_11N_013 5 ++ ++/* 802.11a PLCP header def */ ++struct ofdm_phy_hdr { ++ u8 rlpt[3]; /* rate, length, parity, tail */ ++ u16 service; ++ u8 pad; ++} __packed; ++ ++#define D11A_PHY_HDR_GRATE(phdr) ((phdr)->rlpt[0] & 0x0f) ++#define D11A_PHY_HDR_GRES(phdr) (((phdr)->rlpt[0] >> 4) & 0x01) ++#define D11A_PHY_HDR_GLENGTH(phdr) (((u32 *)((phdr)->rlpt) >> 5) & 0x0fff) ++#define D11A_PHY_HDR_GPARITY(phdr) (((phdr)->rlpt[3] >> 1) & 0x01) ++#define D11A_PHY_HDR_GTAIL(phdr) (((phdr)->rlpt[3] >> 2) & 0x3f) ++ ++/* rate encoded per 802.11a-1999 sec 17.3.4.1 */ ++#define D11A_PHY_HDR_SRATE(phdr, rate) \ ++ ((phdr)->rlpt[0] = ((phdr)->rlpt[0] & 0xf0) | ((rate) & 0xf)) ++/* set reserved field to zero */ ++#define D11A_PHY_HDR_SRES(phdr) ((phdr)->rlpt[0] &= 0xef) ++/* length is number of octets in PSDU */ ++#define D11A_PHY_HDR_SLENGTH(phdr, length) \ ++ (*(u32 *)((phdr)->rlpt) = *(u32 *)((phdr)->rlpt) | \ ++ (((length) & 0x0fff) << 5)) ++/* set the tail to all zeros */ ++#define D11A_PHY_HDR_STAIL(phdr) ((phdr)->rlpt[3] &= 0x03) ++ ++#define D11A_PHY_HDR_LEN_L 3 /* low-rate part of PLCP header */ ++#define D11A_PHY_HDR_LEN_R 2 /* high-rate part of PLCP header */ ++ ++#define D11A_PHY_TX_DELAY (2) /* 2.1 usec */ ++ ++#define D11A_PHY_HDR_TIME (4) /* low-rate part of PLCP header */ ++#define D11A_PHY_PRE_TIME (16) ++#define D11A_PHY_PREHDR_TIME (D11A_PHY_PRE_TIME + D11A_PHY_HDR_TIME) ++ ++/* 802.11b PLCP header def */ ++struct cck_phy_hdr { ++ u8 signal; ++ u8 service; ++ u16 length; ++ u16 crc; ++} __packed; ++ ++#define D11B_PHY_HDR_LEN 6 ++ ++#define D11B_PHY_TX_DELAY (3) /* 3.4 usec */ ++ ++#define D11B_PHY_LHDR_TIME (D11B_PHY_HDR_LEN << 3) ++#define D11B_PHY_LPRE_TIME (144) ++#define D11B_PHY_LPREHDR_TIME (D11B_PHY_LPRE_TIME + D11B_PHY_LHDR_TIME) ++ ++#define D11B_PHY_SHDR_TIME (D11B_PHY_LHDR_TIME >> 1) ++#define D11B_PHY_SPRE_TIME (D11B_PHY_LPRE_TIME >> 1) ++#define D11B_PHY_SPREHDR_TIME (D11B_PHY_SPRE_TIME + D11B_PHY_SHDR_TIME) ++ ++#define D11B_PLCP_SIGNAL_LOCKED (1 << 2) ++#define D11B_PLCP_SIGNAL_LE (1 << 7) ++ ++#define MIMO_PLCP_MCS_MASK 0x7f /* mcs index */ ++#define MIMO_PLCP_40MHZ 0x80 /* 40 Hz frame */ ++#define MIMO_PLCP_AMPDU 0x08 /* ampdu */ ++ ++#define BRCMS_GET_CCK_PLCP_LEN(plcp) (plcp[4] + (plcp[5] << 8)) ++#define BRCMS_GET_MIMO_PLCP_LEN(plcp) (plcp[1] + (plcp[2] << 8)) ++#define BRCMS_SET_MIMO_PLCP_LEN(plcp, len) \ ++ do { \ ++ plcp[1] = len & 0xff; \ ++ plcp[2] = ((len >> 8) & 0xff); \ ++ } while (0); ++ ++#define BRCMS_SET_MIMO_PLCP_AMPDU(plcp) (plcp[3] |= MIMO_PLCP_AMPDU) ++#define BRCMS_CLR_MIMO_PLCP_AMPDU(plcp) (plcp[3] &= ~MIMO_PLCP_AMPDU) ++#define BRCMS_IS_MIMO_PLCP_AMPDU(plcp) (plcp[3] & MIMO_PLCP_AMPDU) ++ ++/* ++ * The dot11a PLCP header is 5 bytes. To simplify the software (so that we ++ * don't need e.g. different tx DMA headers for 11a and 11b), the PLCP header ++ * has padding added in the ucode. ++ */ ++#define D11_PHY_HDR_LEN 6 ++ ++/* TX DMA buffer header */ ++struct d11txh { ++ __le16 MacTxControlLow; /* 0x0 */ ++ __le16 MacTxControlHigh; /* 0x1 */ ++ __le16 MacFrameControl; /* 0x2 */ ++ __le16 TxFesTimeNormal; /* 0x3 */ ++ __le16 PhyTxControlWord; /* 0x4 */ ++ __le16 PhyTxControlWord_1; /* 0x5 */ ++ __le16 PhyTxControlWord_1_Fbr; /* 0x6 */ ++ __le16 PhyTxControlWord_1_Rts; /* 0x7 */ ++ __le16 PhyTxControlWord_1_FbrRts; /* 0x8 */ ++ __le16 MainRates; /* 0x9 */ ++ __le16 XtraFrameTypes; /* 0xa */ ++ u8 IV[16]; /* 0x0b - 0x12 */ ++ u8 TxFrameRA[6]; /* 0x13 - 0x15 */ ++ __le16 TxFesTimeFallback; /* 0x16 */ ++ u8 RTSPLCPFallback[6]; /* 0x17 - 0x19 */ ++ __le16 RTSDurFallback; /* 0x1a */ ++ u8 FragPLCPFallback[6]; /* 0x1b - 1d */ ++ __le16 FragDurFallback; /* 0x1e */ ++ __le16 MModeLen; /* 0x1f */ ++ __le16 MModeFbrLen; /* 0x20 */ ++ __le16 TstampLow; /* 0x21 */ ++ __le16 TstampHigh; /* 0x22 */ ++ __le16 ABI_MimoAntSel; /* 0x23 */ ++ __le16 PreloadSize; /* 0x24 */ ++ __le16 AmpduSeqCtl; /* 0x25 */ ++ __le16 TxFrameID; /* 0x26 */ ++ __le16 TxStatus; /* 0x27 */ ++ __le16 MaxNMpdus; /* 0x28 */ ++ __le16 MaxABytes_MRT; /* 0x29 */ ++ __le16 MaxABytes_FBR; /* 0x2a */ ++ __le16 MinMBytes; /* 0x2b */ ++ u8 RTSPhyHeader[D11_PHY_HDR_LEN]; /* 0x2c - 0x2e */ ++ struct ieee80211_rts rts_frame; /* 0x2f - 0x36 */ ++ u16 PAD; /* 0x37 */ ++} __packed; ++ ++#define D11_TXH_LEN 112 /* bytes */ ++ ++/* Frame Types */ ++#define FT_CCK 0 ++#define FT_OFDM 1 ++#define FT_HT 2 ++#define FT_N 3 ++ ++/* ++ * Position of MPDU inside A-MPDU; indicated with bits 10:9 ++ * of MacTxControlLow ++ */ ++#define TXC_AMPDU_SHIFT 9 /* shift for ampdu settings */ ++#define TXC_AMPDU_NONE 0 /* Regular MPDU, not an A-MPDU */ ++#define TXC_AMPDU_FIRST 1 /* first MPDU of an A-MPDU */ ++#define TXC_AMPDU_MIDDLE 2 /* intermediate MPDU of an A-MPDU */ ++#define TXC_AMPDU_LAST 3 /* last (or single) MPDU of an A-MPDU */ ++ ++/*== MacTxControlLow ==*/ ++#define TXC_AMIC 0x8000 ++#define TXC_SENDCTS 0x0800 ++#define TXC_AMPDU_MASK 0x0600 ++#define TXC_BW_40 0x0100 ++#define TXC_FREQBAND_5G 0x0080 ++#define TXC_DFCS 0x0040 ++#define TXC_IGNOREPMQ 0x0020 ++#define TXC_HWSEQ 0x0010 ++#define TXC_STARTMSDU 0x0008 ++#define TXC_SENDRTS 0x0004 ++#define TXC_LONGFRAME 0x0002 ++#define TXC_IMMEDACK 0x0001 ++ ++/*== MacTxControlHigh ==*/ ++/* RTS fallback preamble type 1 = SHORT 0 = LONG */ ++#define TXC_PREAMBLE_RTS_FB_SHORT 0x8000 ++/* RTS main rate preamble type 1 = SHORT 0 = LONG */ ++#define TXC_PREAMBLE_RTS_MAIN_SHORT 0x4000 ++/* ++ * Main fallback rate preamble type ++ * 1 = SHORT for OFDM/GF for MIMO ++ * 0 = LONG for CCK/MM for MIMO ++ */ ++#define TXC_PREAMBLE_DATA_FB_SHORT 0x2000 ++ ++/* TXC_PREAMBLE_DATA_MAIN is in PhyTxControl bit 5 */ ++/* use fallback rate for this AMPDU */ ++#define TXC_AMPDU_FBR 0x1000 ++#define TXC_SECKEY_MASK 0x0FF0 ++#define TXC_SECKEY_SHIFT 4 ++/* Use alternate txpwr defined at loc. M_ALT_TXPWR_IDX */ ++#define TXC_ALT_TXPWR 0x0008 ++#define TXC_SECTYPE_MASK 0x0007 ++#define TXC_SECTYPE_SHIFT 0 ++ ++/* Null delimiter for Fallback rate */ ++#define AMPDU_FBR_NULL_DELIM 5 /* Location of Null delimiter count for AMPDU */ ++ ++/* PhyTxControl for Mimophy */ ++#define PHY_TXC_PWR_MASK 0xFC00 ++#define PHY_TXC_PWR_SHIFT 10 ++#define PHY_TXC_ANT_MASK 0x03C0 /* bit 6, 7, 8, 9 */ ++#define PHY_TXC_ANT_SHIFT 6 ++#define PHY_TXC_ANT_0_1 0x00C0 /* auto, last rx */ ++#define PHY_TXC_LCNPHY_ANT_LAST 0x0000 ++#define PHY_TXC_ANT_3 0x0200 /* virtual antenna 3 */ ++#define PHY_TXC_ANT_2 0x0100 /* virtual antenna 2 */ ++#define PHY_TXC_ANT_1 0x0080 /* virtual antenna 1 */ ++#define PHY_TXC_ANT_0 0x0040 /* virtual antenna 0 */ ++#define PHY_TXC_SHORT_HDR 0x0010 ++ ++#define PHY_TXC_OLD_ANT_0 0x0000 ++#define PHY_TXC_OLD_ANT_1 0x0100 ++#define PHY_TXC_OLD_ANT_LAST 0x0300 ++ ++/* PhyTxControl_1 for Mimophy */ ++#define PHY_TXC1_BW_MASK 0x0007 ++#define PHY_TXC1_BW_10MHZ 0 ++#define PHY_TXC1_BW_10MHZ_UP 1 ++#define PHY_TXC1_BW_20MHZ 2 ++#define PHY_TXC1_BW_20MHZ_UP 3 ++#define PHY_TXC1_BW_40MHZ 4 ++#define PHY_TXC1_BW_40MHZ_DUP 5 ++#define PHY_TXC1_MODE_SHIFT 3 ++#define PHY_TXC1_MODE_MASK 0x0038 ++#define PHY_TXC1_MODE_SISO 0 ++#define PHY_TXC1_MODE_CDD 1 ++#define PHY_TXC1_MODE_STBC 2 ++#define PHY_TXC1_MODE_SDM 3 ++ ++/* PhyTxControl for HTphy that are different from Mimophy */ ++#define PHY_TXC_HTANT_MASK 0x3fC0 /* bits 6-13 */ ++ ++/* XtraFrameTypes */ ++#define XFTS_RTS_FT_SHIFT 2 ++#define XFTS_FBRRTS_FT_SHIFT 4 ++#define XFTS_CHANNEL_SHIFT 8 ++ ++/* Antenna diversity bit in ant_wr_settle */ ++#define PHY_AWS_ANTDIV 0x2000 ++ ++/* IFS ctl */ ++#define IFS_USEEDCF (1 << 2) ++ ++/* IFS ctl1 */ ++#define IFS_CTL1_EDCRS (1 << 3) ++#define IFS_CTL1_EDCRS_20L (1 << 4) ++#define IFS_CTL1_EDCRS_40 (1 << 5) ++ ++/* ABI_MimoAntSel */ ++#define ABI_MAS_ADDR_BMP_IDX_MASK 0x0f00 ++#define ABI_MAS_ADDR_BMP_IDX_SHIFT 8 ++#define ABI_MAS_FBR_ANT_PTN_MASK 0x00f0 ++#define ABI_MAS_FBR_ANT_PTN_SHIFT 4 ++#define ABI_MAS_MRT_ANT_PTN_MASK 0x000f ++ ++/* tx status packet */ ++struct tx_status { ++ u16 framelen; ++ u16 PAD; ++ u16 frameid; ++ u16 status; ++ u16 lasttxtime; ++ u16 sequence; ++ u16 phyerr; ++ u16 ackphyrxsh; ++} __packed; ++ ++#define TXSTATUS_LEN 16 ++ ++/* status field bit definitions */ ++#define TX_STATUS_FRM_RTX_MASK 0xF000 ++#define TX_STATUS_FRM_RTX_SHIFT 12 ++#define TX_STATUS_RTS_RTX_MASK 0x0F00 ++#define TX_STATUS_RTS_RTX_SHIFT 8 ++#define TX_STATUS_MASK 0x00FE ++#define TX_STATUS_PMINDCTD (1 << 7) /* PM mode indicated to AP */ ++#define TX_STATUS_INTERMEDIATE (1 << 6) /* intermediate or 1st ampdu pkg */ ++#define TX_STATUS_AMPDU (1 << 5) /* AMPDU status */ ++#define TX_STATUS_SUPR_MASK 0x1C /* suppress status bits (4:2) */ ++#define TX_STATUS_SUPR_SHIFT 2 ++#define TX_STATUS_ACK_RCV (1 << 1) /* ACK received */ ++#define TX_STATUS_VALID (1 << 0) /* Tx status valid */ ++#define TX_STATUS_NO_ACK 0 ++ ++/* suppress status reason codes */ ++#define TX_STATUS_SUPR_PMQ (1 << 2) /* PMQ entry */ ++#define TX_STATUS_SUPR_FLUSH (2 << 2) /* flush request */ ++#define TX_STATUS_SUPR_FRAG (3 << 2) /* previous frag failure */ ++#define TX_STATUS_SUPR_TBTT (3 << 2) /* SHARED: Probe resp supr for TBTT */ ++#define TX_STATUS_SUPR_BADCH (4 << 2) /* channel mismatch */ ++#define TX_STATUS_SUPR_EXPTIME (5 << 2) /* lifetime expiry */ ++#define TX_STATUS_SUPR_UF (6 << 2) /* underflow */ ++ ++/* Unexpected tx status for rate update */ ++#define TX_STATUS_UNEXP(status) \ ++ ((((status) & TX_STATUS_INTERMEDIATE) != 0) && \ ++ TX_STATUS_UNEXP_AMPDU(status)) ++ ++/* Unexpected tx status for A-MPDU rate update */ ++#define TX_STATUS_UNEXP_AMPDU(status) \ ++ ((((status) & TX_STATUS_SUPR_MASK) != 0) && \ ++ (((status) & TX_STATUS_SUPR_MASK) != TX_STATUS_SUPR_EXPTIME)) ++ ++#define TX_STATUS_BA_BMAP03_MASK 0xF000 /* ba bitmap 0:3 in 1st pkg */ ++#define TX_STATUS_BA_BMAP03_SHIFT 12 /* ba bitmap 0:3 in 1st pkg */ ++#define TX_STATUS_BA_BMAP47_MASK 0x001E /* ba bitmap 4:7 in 2nd pkg */ ++#define TX_STATUS_BA_BMAP47_SHIFT 3 /* ba bitmap 4:7 in 2nd pkg */ ++ ++/* RXE (Receive Engine) */ ++ ++/* RCM_CTL */ ++#define RCM_INC_MASK_H 0x0080 ++#define RCM_INC_MASK_L 0x0040 ++#define RCM_INC_DATA 0x0020 ++#define RCM_INDEX_MASK 0x001F ++#define RCM_SIZE 15 ++ ++#define RCM_MAC_OFFSET 0 /* current MAC address */ ++#define RCM_BSSID_OFFSET 3 /* current BSSID address */ ++#define RCM_F_BSSID_0_OFFSET 6 /* foreign BSS CFP tracking */ ++#define RCM_F_BSSID_1_OFFSET 9 /* foreign BSS CFP tracking */ ++#define RCM_F_BSSID_2_OFFSET 12 /* foreign BSS CFP tracking */ ++ ++#define RCM_WEP_TA0_OFFSET 16 ++#define RCM_WEP_TA1_OFFSET 19 ++#define RCM_WEP_TA2_OFFSET 22 ++#define RCM_WEP_TA3_OFFSET 25 ++ ++/* PSM Block */ ++ ++/* psm_phy_hdr_param bits */ ++#define MAC_PHY_RESET 1 ++#define MAC_PHY_CLOCK_EN 2 ++#define MAC_PHY_FORCE_CLK 4 ++ ++/* WEP Block */ ++ ++/* WEP_WKEY */ ++#define WKEY_START (1 << 8) ++#define WKEY_SEL_MASK 0x1F ++ ++/* WEP data formats */ ++ ++/* the number of RCMTA entries */ ++#define RCMTA_SIZE 50 ++ ++#define M_ADDR_BMP_BLK (0x37e * 2) ++#define M_ADDR_BMP_BLK_SZ 12 ++ ++#define ADDR_BMP_RA (1 << 0) /* Receiver Address (RA) */ ++#define ADDR_BMP_TA (1 << 1) /* Transmitter Address (TA) */ ++#define ADDR_BMP_BSSID (1 << 2) /* BSSID */ ++#define ADDR_BMP_AP (1 << 3) /* Infra-BSS Access Point */ ++#define ADDR_BMP_STA (1 << 4) /* Infra-BSS Station */ ++#define ADDR_BMP_RESERVED1 (1 << 5) ++#define ADDR_BMP_RESERVED2 (1 << 6) ++#define ADDR_BMP_RESERVED3 (1 << 7) ++#define ADDR_BMP_BSS_IDX_MASK (3 << 8) /* BSS control block index */ ++#define ADDR_BMP_BSS_IDX_SHIFT 8 ++ ++#define WSEC_MAX_RCMTA_KEYS 54 ++ ++/* max keys in M_TKMICKEYS_BLK */ ++#define WSEC_MAX_TKMIC_ENGINE_KEYS 12 /* 8 + 4 default */ ++ ++/* max RXE match registers */ ++#define WSEC_MAX_RXE_KEYS 4 ++ ++/* SECKINDXALGO (Security Key Index & Algorithm Block) word format */ ++/* SKL (Security Key Lookup) */ ++#define SKL_ALGO_MASK 0x0007 ++#define SKL_ALGO_SHIFT 0 ++#define SKL_KEYID_MASK 0x0008 ++#define SKL_KEYID_SHIFT 3 ++#define SKL_INDEX_MASK 0x03F0 ++#define SKL_INDEX_SHIFT 4 ++#define SKL_GRP_ALGO_MASK 0x1c00 ++#define SKL_GRP_ALGO_SHIFT 10 ++ ++/* additional bits defined for IBSS group key support */ ++#define SKL_IBSS_INDEX_MASK 0x01F0 ++#define SKL_IBSS_INDEX_SHIFT 4 ++#define SKL_IBSS_KEYID1_MASK 0x0600 ++#define SKL_IBSS_KEYID1_SHIFT 9 ++#define SKL_IBSS_KEYID2_MASK 0x1800 ++#define SKL_IBSS_KEYID2_SHIFT 11 ++#define SKL_IBSS_KEYALGO_MASK 0xE000 ++#define SKL_IBSS_KEYALGO_SHIFT 13 ++ ++#define WSEC_MODE_OFF 0 ++#define WSEC_MODE_HW 1 ++#define WSEC_MODE_SW 2 ++ ++#define WSEC_ALGO_OFF 0 ++#define WSEC_ALGO_WEP1 1 ++#define WSEC_ALGO_TKIP 2 ++#define WSEC_ALGO_AES 3 ++#define WSEC_ALGO_WEP128 4 ++#define WSEC_ALGO_AES_LEGACY 5 ++#define WSEC_ALGO_NALG 6 ++ ++#define AES_MODE_NONE 0 ++#define AES_MODE_CCM 1 ++ ++/* WEP_CTL (Rev 0) */ ++#define WECR0_KEYREG_SHIFT 0 ++#define WECR0_KEYREG_MASK 0x7 ++#define WECR0_DECRYPT (1 << 3) ++#define WECR0_IVINLINE (1 << 4) ++#define WECR0_WEPALG_SHIFT 5 ++#define WECR0_WEPALG_MASK (0x7 << 5) ++#define WECR0_WKEYSEL_SHIFT 8 ++#define WECR0_WKEYSEL_MASK (0x7 << 8) ++#define WECR0_WKEYSTART (1 << 11) ++#define WECR0_WEPINIT (1 << 14) ++#define WECR0_ICVERR (1 << 15) ++ ++/* Frame template map byte offsets */ ++#define T_ACTS_TPL_BASE (0) ++#define T_NULL_TPL_BASE (0xc * 2) ++#define T_QNULL_TPL_BASE (0x1c * 2) ++#define T_RR_TPL_BASE (0x2c * 2) ++#define T_BCN0_TPL_BASE (0x34 * 2) ++#define T_PRS_TPL_BASE (0x134 * 2) ++#define T_BCN1_TPL_BASE (0x234 * 2) ++#define T_TX_FIFO_TXRAM_BASE (T_ACTS_TPL_BASE + \ ++ (TXFIFO_START_BLK * TXFIFO_SIZE_UNIT)) ++ ++#define T_BA_TPL_BASE T_QNULL_TPL_BASE /* template area for BA */ ++ ++#define T_RAM_ACCESS_SZ 4 /* template ram is 4 byte access only */ ++ ++/* Shared Mem byte offsets */ ++ ++/* Location where the ucode expects the corerev */ ++#define M_MACHW_VER (0x00b * 2) ++ ++/* Location where the ucode expects the MAC capabilities */ ++#define M_MACHW_CAP_L (0x060 * 2) ++#define M_MACHW_CAP_H (0x061 * 2) ++ ++/* WME shared memory */ ++#define M_EDCF_STATUS_OFF (0x007 * 2) ++#define M_TXF_CUR_INDEX (0x018 * 2) ++#define M_EDCF_QINFO (0x120 * 2) ++ ++/* PS-mode related parameters */ ++#define M_DOT11_SLOT (0x008 * 2) ++#define M_DOT11_DTIMPERIOD (0x009 * 2) ++#define M_NOSLPZNATDTIM (0x026 * 2) ++ ++/* Beacon-related parameters */ ++#define M_BCN0_FRM_BYTESZ (0x00c * 2) /* Bcn 0 template length */ ++#define M_BCN1_FRM_BYTESZ (0x00d * 2) /* Bcn 1 template length */ ++#define M_BCN_TXTSF_OFFSET (0x00e * 2) ++#define M_TIMBPOS_INBEACON (0x00f * 2) ++#define M_SFRMTXCNTFBRTHSD (0x022 * 2) ++#define M_LFRMTXCNTFBRTHSD (0x023 * 2) ++#define M_BCN_PCTLWD (0x02a * 2) ++#define M_BCN_LI (0x05b * 2) /* beacon listen interval */ ++ ++/* MAX Rx Frame len */ ++#define M_MAXRXFRM_LEN (0x010 * 2) ++ ++/* ACK/CTS related params */ ++#define M_RSP_PCTLWD (0x011 * 2) ++ ++/* Hardware Power Control */ ++#define M_TXPWR_N (0x012 * 2) ++#define M_TXPWR_TARGET (0x013 * 2) ++#define M_TXPWR_MAX (0x014 * 2) ++#define M_TXPWR_CUR (0x019 * 2) ++ ++/* Rx-related parameters */ ++#define M_RX_PAD_DATA_OFFSET (0x01a * 2) ++ ++/* WEP Shared mem data */ ++#define M_SEC_DEFIVLOC (0x01e * 2) ++#define M_SEC_VALNUMSOFTMCHTA (0x01f * 2) ++#define M_PHYVER (0x028 * 2) ++#define M_PHYTYPE (0x029 * 2) ++#define M_SECRXKEYS_PTR (0x02b * 2) ++#define M_TKMICKEYS_PTR (0x059 * 2) ++#define M_SECKINDXALGO_BLK (0x2ea * 2) ++#define M_SECKINDXALGO_BLK_SZ 54 ++#define M_SECPSMRXTAMCH_BLK (0x2fa * 2) ++#define M_TKIP_TSC_TTAK (0x18c * 2) ++#define D11_MAX_KEY_SIZE 16 ++ ++#define M_MAX_ANTCNT (0x02e * 2) /* antenna swap threshold */ ++ ++/* Probe response related parameters */ ++#define M_SSIDLEN (0x024 * 2) ++#define M_PRB_RESP_FRM_LEN (0x025 * 2) ++#define M_PRS_MAXTIME (0x03a * 2) ++#define M_SSID (0xb0 * 2) ++#define M_CTXPRS_BLK (0xc0 * 2) ++#define C_CTX_PCTLWD_POS (0x4 * 2) ++ ++/* Delta between OFDM and CCK power in CCK power boost mode */ ++#define M_OFDM_OFFSET (0x027 * 2) ++ ++/* TSSI for last 4 11b/g CCK packets transmitted */ ++#define M_B_TSSI_0 (0x02c * 2) ++#define M_B_TSSI_1 (0x02d * 2) ++ ++/* Host flags to turn on ucode options */ ++#define M_HOST_FLAGS1 (0x02f * 2) ++#define M_HOST_FLAGS2 (0x030 * 2) ++#define M_HOST_FLAGS3 (0x031 * 2) ++#define M_HOST_FLAGS4 (0x03c * 2) ++#define M_HOST_FLAGS5 (0x06a * 2) ++#define M_HOST_FLAGS_SZ 16 ++ ++#define M_RADAR_REG (0x033 * 2) ++ ++/* TSSI for last 4 11a OFDM packets transmitted */ ++#define M_A_TSSI_0 (0x034 * 2) ++#define M_A_TSSI_1 (0x035 * 2) ++ ++/* noise interference measurement */ ++#define M_NOISE_IF_COUNT (0x034 * 2) ++#define M_NOISE_IF_TIMEOUT (0x035 * 2) ++ ++#define M_RF_RX_SP_REG1 (0x036 * 2) ++ ++/* TSSI for last 4 11g OFDM packets transmitted */ ++#define M_G_TSSI_0 (0x038 * 2) ++#define M_G_TSSI_1 (0x039 * 2) ++ ++/* Background noise measure */ ++#define M_JSSI_0 (0x44 * 2) ++#define M_JSSI_1 (0x45 * 2) ++#define M_JSSI_AUX (0x46 * 2) ++ ++#define M_CUR_2050_RADIOCODE (0x47 * 2) ++ ++/* TX fifo sizes */ ++#define M_FIFOSIZE0 (0x4c * 2) ++#define M_FIFOSIZE1 (0x4d * 2) ++#define M_FIFOSIZE2 (0x4e * 2) ++#define M_FIFOSIZE3 (0x4f * 2) ++#define D11_MAX_TX_FRMS 32 /* max frames allowed in tx fifo */ ++ ++/* Current channel number plus upper bits */ ++#define M_CURCHANNEL (0x50 * 2) ++#define D11_CURCHANNEL_5G 0x0100; ++#define D11_CURCHANNEL_40 0x0200; ++#define D11_CURCHANNEL_MAX 0x00FF; ++ ++/* last posted frameid on the bcmc fifo */ ++#define M_BCMC_FID (0x54 * 2) ++#define INVALIDFID 0xffff ++ ++/* extended beacon phyctl bytes for 11N */ ++#define M_BCN_PCTL1WD (0x058 * 2) ++ ++/* idle busy ratio to duty_cycle requirement */ ++#define M_TX_IDLE_BUSY_RATIO_X_16_CCK (0x52 * 2) ++#define M_TX_IDLE_BUSY_RATIO_X_16_OFDM (0x5A * 2) ++ ++/* CW RSSI for LCNPHY */ ++#define M_LCN_RSSI_0 0x1332 ++#define M_LCN_RSSI_1 0x1338 ++#define M_LCN_RSSI_2 0x133e ++#define M_LCN_RSSI_3 0x1344 ++ ++/* SNR for LCNPHY */ ++#define M_LCN_SNR_A_0 0x1334 ++#define M_LCN_SNR_B_0 0x1336 ++ ++#define M_LCN_SNR_A_1 0x133a ++#define M_LCN_SNR_B_1 0x133c ++ ++#define M_LCN_SNR_A_2 0x1340 ++#define M_LCN_SNR_B_2 0x1342 ++ ++#define M_LCN_SNR_A_3 0x1346 ++#define M_LCN_SNR_B_3 0x1348 ++ ++#define M_LCN_LAST_RESET (81*2) ++#define M_LCN_LAST_LOC (63*2) ++#define M_LCNPHY_RESET_STATUS (4902) ++#define M_LCNPHY_DSC_TIME (0x98d*2) ++#define M_LCNPHY_RESET_CNT_DSC (0x98b*2) ++#define M_LCNPHY_RESET_CNT (0x98c*2) ++ ++/* Rate table offsets */ ++#define M_RT_DIRMAP_A (0xe0 * 2) ++#define M_RT_BBRSMAP_A (0xf0 * 2) ++#define M_RT_DIRMAP_B (0x100 * 2) ++#define M_RT_BBRSMAP_B (0x110 * 2) ++ ++/* Rate table entry offsets */ ++#define M_RT_PRS_PLCP_POS 10 ++#define M_RT_PRS_DUR_POS 16 ++#define M_RT_OFDM_PCTL1_POS 18 ++ ++#define M_20IN40_IQ (0x380 * 2) ++ ++/* SHM locations where ucode stores the current power index */ ++#define M_CURR_IDX1 (0x384 * 2) ++#define M_CURR_IDX2 (0x387 * 2) ++ ++#define M_BSCALE_ANT0 (0x5e * 2) ++#define M_BSCALE_ANT1 (0x5f * 2) ++ ++/* Antenna Diversity Testing */ ++#define M_MIMO_ANTSEL_RXDFLT (0x63 * 2) ++#define M_ANTSEL_CLKDIV (0x61 * 2) ++#define M_MIMO_ANTSEL_TXDFLT (0x64 * 2) ++ ++#define M_MIMO_MAXSYM (0x5d * 2) ++#define MIMO_MAXSYM_DEF 0x8000 /* 32k */ ++#define MIMO_MAXSYM_MAX 0xffff /* 64k */ ++ ++#define M_WATCHDOG_8TU (0x1e * 2) ++#define WATCHDOG_8TU_DEF 5 ++#define WATCHDOG_8TU_MAX 10 ++ ++/* Manufacturing Test Variables */ ++/* PER test mode */ ++#define M_PKTENG_CTRL (0x6c * 2) ++/* IFS for TX mode */ ++#define M_PKTENG_IFS (0x6d * 2) ++/* Lower word of tx frmcnt/rx lostcnt */ ++#define M_PKTENG_FRMCNT_LO (0x6e * 2) ++/* Upper word of tx frmcnt/rx lostcnt */ ++#define M_PKTENG_FRMCNT_HI (0x6f * 2) ++ ++/* Index variation in vbat ripple */ ++#define M_LCN_PWR_IDX_MAX (0x67 * 2) /* highest index read by ucode */ ++#define M_LCN_PWR_IDX_MIN (0x66 * 2) /* lowest index read by ucode */ ++ ++/* M_PKTENG_CTRL bit definitions */ ++#define M_PKTENG_MODE_TX 0x0001 ++#define M_PKTENG_MODE_TX_RIFS 0x0004 ++#define M_PKTENG_MODE_TX_CTS 0x0008 ++#define M_PKTENG_MODE_RX 0x0002 ++#define M_PKTENG_MODE_RX_WITH_ACK 0x0402 ++#define M_PKTENG_MODE_MASK 0x0003 ++/* TX frames indicated in the frmcnt reg */ ++#define M_PKTENG_FRMCNT_VLD 0x0100 ++ ++/* Sample Collect parameters (bitmap and type) */ ++/* Trigger bitmap for sample collect */ ++#define M_SMPL_COL_BMP (0x37d * 2) ++/* Sample collect type */ ++#define M_SMPL_COL_CTL (0x3b2 * 2) ++ ++#define ANTSEL_CLKDIV_4MHZ 6 ++#define MIMO_ANTSEL_BUSY 0x4000 /* bit 14 (busy) */ ++#define MIMO_ANTSEL_SEL 0x8000 /* bit 15 write the value */ ++#define MIMO_ANTSEL_WAIT 50 /* 50us wait */ ++#define MIMO_ANTSEL_OVERRIDE 0x8000 /* flag */ ++ ++struct shm_acparams { ++ u16 txop; ++ u16 cwmin; ++ u16 cwmax; ++ u16 cwcur; ++ u16 aifs; ++ u16 bslots; ++ u16 reggap; ++ u16 status; ++ u16 rsvd[8]; ++} __packed; ++#define M_EDCF_QLEN (16 * 2) ++ ++#define WME_STATUS_NEWAC (1 << 8) ++ ++/* M_HOST_FLAGS */ ++#define MHFMAX 5 /* Number of valid hostflag half-word (u16) */ ++#define MHF1 0 /* Hostflag 1 index */ ++#define MHF2 1 /* Hostflag 2 index */ ++#define MHF3 2 /* Hostflag 3 index */ ++#define MHF4 3 /* Hostflag 4 index */ ++#define MHF5 4 /* Hostflag 5 index */ ++ ++/* Flags in M_HOST_FLAGS */ ++/* Enable ucode antenna diversity help */ ++#define MHF1_ANTDIV 0x0001 ++/* Enable EDCF access control */ ++#define MHF1_EDCF 0x0100 ++#define MHF1_IQSWAP_WAR 0x0200 ++/* Disable Slow clock request, for corerev < 11 */ ++#define MHF1_FORCEFASTCLK 0x0400 ++ ++/* Flags in M_HOST_FLAGS2 */ ++ ++/* Flush BCMC FIFO immediately */ ++#define MHF2_TXBCMC_NOW 0x0040 ++/* Enable ucode/hw power control */ ++#define MHF2_HWPWRCTL 0x0080 ++#define MHF2_NPHY40MHZ_WAR 0x0800 ++ ++/* Flags in M_HOST_FLAGS3 */ ++/* enabled mimo antenna selection */ ++#define MHF3_ANTSEL_EN 0x0001 ++/* antenna selection mode: 0: 2x3, 1: 2x4 */ ++#define MHF3_ANTSEL_MODE 0x0002 ++#define MHF3_RESERVED1 0x0004 ++#define MHF3_RESERVED2 0x0008 ++#define MHF3_NPHY_MLADV_WAR 0x0010 ++ ++/* Flags in M_HOST_FLAGS4 */ ++/* force bphy Tx on core 0 (board level WAR) */ ++#define MHF4_BPHY_TXCORE0 0x0080 ++/* for 4313A0 FEM boards */ ++#define MHF4_EXTPA_ENABLE 0x4000 ++ ++/* Flags in M_HOST_FLAGS5 */ ++#define MHF5_4313_GPIOCTRL 0x0001 ++#define MHF5_RESERVED1 0x0002 ++#define MHF5_RESERVED2 0x0004 ++/* Radio power setting for ucode */ ++#define M_RADIO_PWR (0x32 * 2) ++ ++/* phy noise recorded by ucode right after tx */ ++#define M_PHY_NOISE (0x037 * 2) ++#define PHY_NOISE_MASK 0x00ff ++ ++/* ++ * Receive Frame Data Header for 802.11b DCF-only frames ++ * ++ * RxFrameSize: Actual byte length of the frame data received ++ * PAD: padding (not used) ++ * PhyRxStatus_0: PhyRxStatus 15:0 ++ * PhyRxStatus_1: PhyRxStatus 31:16 ++ * PhyRxStatus_2: PhyRxStatus 47:32 ++ * PhyRxStatus_3: PhyRxStatus 63:48 ++ * PhyRxStatus_4: PhyRxStatus 79:64 ++ * PhyRxStatus_5: PhyRxStatus 95:80 ++ * RxStatus1: MAC Rx Status ++ * RxStatus2: extended MAC Rx status ++ * RxTSFTime: RxTSFTime time of first MAC symbol + M_PHY_PLCPRX_DLY ++ * RxChan: gain code, channel radio code, and phy type ++ */ ++struct d11rxhdr_le { ++ __le16 RxFrameSize; ++ u16 PAD; ++ __le16 PhyRxStatus_0; ++ __le16 PhyRxStatus_1; ++ __le16 PhyRxStatus_2; ++ __le16 PhyRxStatus_3; ++ __le16 PhyRxStatus_4; ++ __le16 PhyRxStatus_5; ++ __le16 RxStatus1; ++ __le16 RxStatus2; ++ __le16 RxTSFTime; ++ __le16 RxChan; ++} __packed; ++ ++struct d11rxhdr { ++ u16 RxFrameSize; ++ u16 PAD; ++ u16 PhyRxStatus_0; ++ u16 PhyRxStatus_1; ++ u16 PhyRxStatus_2; ++ u16 PhyRxStatus_3; ++ u16 PhyRxStatus_4; ++ u16 PhyRxStatus_5; ++ u16 RxStatus1; ++ u16 RxStatus2; ++ u16 RxTSFTime; ++ u16 RxChan; ++} __packed; ++ ++/* PhyRxStatus_0: */ ++/* NPHY only: CCK, OFDM, preN, N */ ++#define PRXS0_FT_MASK 0x0003 ++/* NPHY only: clip count adjustment steps by AGC */ ++#define PRXS0_CLIP_MASK 0x000C ++#define PRXS0_CLIP_SHIFT 2 ++/* PHY received a frame with unsupported rate */ ++#define PRXS0_UNSRATE 0x0010 ++/* GPHY: rx ant, NPHY: upper sideband */ ++#define PRXS0_RXANT_UPSUBBAND 0x0020 ++/* CCK frame only: lost crs during cck frame reception */ ++#define PRXS0_LCRS 0x0040 ++/* Short Preamble */ ++#define PRXS0_SHORTH 0x0080 ++/* PLCP violation */ ++#define PRXS0_PLCPFV 0x0100 ++/* PLCP header integrity check failed */ ++#define PRXS0_PLCPHCF 0x0200 ++/* legacy PHY gain control */ ++#define PRXS0_GAIN_CTL 0x4000 ++/* NPHY: Antennas used for received frame, bitmask */ ++#define PRXS0_ANTSEL_MASK 0xF000 ++#define PRXS0_ANTSEL_SHIFT 0x12 ++ ++/* subfield PRXS0_FT_MASK */ ++#define PRXS0_CCK 0x0000 ++/* valid only for G phy, use rxh->RxChan for A phy */ ++#define PRXS0_OFDM 0x0001 ++#define PRXS0_PREN 0x0002 ++#define PRXS0_STDN 0x0003 ++ ++/* subfield PRXS0_ANTSEL_MASK */ ++#define PRXS0_ANTSEL_0 0x0 /* antenna 0 is used */ ++#define PRXS0_ANTSEL_1 0x2 /* antenna 1 is used */ ++#define PRXS0_ANTSEL_2 0x4 /* antenna 2 is used */ ++#define PRXS0_ANTSEL_3 0x8 /* antenna 3 is used */ ++ ++/* PhyRxStatus_1: */ ++#define PRXS1_JSSI_MASK 0x00FF ++#define PRXS1_JSSI_SHIFT 0 ++#define PRXS1_SQ_MASK 0xFF00 ++#define PRXS1_SQ_SHIFT 8 ++ ++/* nphy PhyRxStatus_1: */ ++#define PRXS1_nphy_PWR0_MASK 0x00FF ++#define PRXS1_nphy_PWR1_MASK 0xFF00 ++ ++/* HTPHY Rx Status defines */ ++/* htphy PhyRxStatus_0: those bit are overlapped with PhyRxStatus_0 */ ++#define PRXS0_BAND 0x0400 /* 0 = 2.4G, 1 = 5G */ ++#define PRXS0_RSVD 0x0800 /* reserved; set to 0 */ ++#define PRXS0_UNUSED 0xF000 /* unused and not defined; set to 0 */ ++ ++/* htphy PhyRxStatus_1: */ ++/* core enables for {3..0}, 0=disabled, 1=enabled */ ++#define PRXS1_HTPHY_CORE_MASK 0x000F ++/* antenna configation */ ++#define PRXS1_HTPHY_ANTCFG_MASK 0x00F0 ++/* Mixmode PLCP Length low byte mask */ ++#define PRXS1_HTPHY_MMPLCPLenL_MASK 0xFF00 ++ ++/* htphy PhyRxStatus_2: */ ++/* Mixmode PLCP Length high byte maskw */ ++#define PRXS2_HTPHY_MMPLCPLenH_MASK 0x000F ++/* Mixmode PLCP rate mask */ ++#define PRXS2_HTPHY_MMPLCH_RATE_MASK 0x00F0 ++/* Rx power on core 0 */ ++#define PRXS2_HTPHY_RXPWR_ANT0 0xFF00 ++ ++/* htphy PhyRxStatus_3: */ ++/* Rx power on core 1 */ ++#define PRXS3_HTPHY_RXPWR_ANT1 0x00FF ++/* Rx power on core 2 */ ++#define PRXS3_HTPHY_RXPWR_ANT2 0xFF00 ++ ++/* htphy PhyRxStatus_4: */ ++/* Rx power on core 3 */ ++#define PRXS4_HTPHY_RXPWR_ANT3 0x00FF ++/* Coarse frequency offset */ ++#define PRXS4_HTPHY_CFO 0xFF00 ++ ++/* htphy PhyRxStatus_5: */ ++/* Fine frequency offset */ ++#define PRXS5_HTPHY_FFO 0x00FF ++/* Advance Retard */ ++#define PRXS5_HTPHY_AR 0xFF00 ++ ++#define HTPHY_MMPLCPLen(rxs) \ ++ ((((rxs)->PhyRxStatus_1 & PRXS1_HTPHY_MMPLCPLenL_MASK) >> 8) | \ ++ (((rxs)->PhyRxStatus_2 & PRXS2_HTPHY_MMPLCPLenH_MASK) << 8)) ++/* Get Rx power on core 0 */ ++#define HTPHY_RXPWR_ANT0(rxs) \ ++ ((((rxs)->PhyRxStatus_2) & PRXS2_HTPHY_RXPWR_ANT0) >> 8) ++/* Get Rx power on core 1 */ ++#define HTPHY_RXPWR_ANT1(rxs) \ ++ (((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT1) ++/* Get Rx power on core 2 */ ++#define HTPHY_RXPWR_ANT2(rxs) \ ++ ((((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT2) >> 8) ++ ++/* ucode RxStatus1: */ ++#define RXS_BCNSENT 0x8000 ++#define RXS_SECKINDX_MASK 0x07e0 ++#define RXS_SECKINDX_SHIFT 5 ++#define RXS_DECERR (1 << 4) ++#define RXS_DECATMPT (1 << 3) ++/* PAD bytes to make IP data 4 bytes aligned */ ++#define RXS_PBPRES (1 << 2) ++#define RXS_RESPFRAMETX (1 << 1) ++#define RXS_FCSERR (1 << 0) ++ ++/* ucode RxStatus2: */ ++#define RXS_AMSDU_MASK 1 ++#define RXS_AGGTYPE_MASK 0x6 ++#define RXS_AGGTYPE_SHIFT 1 ++#define RXS_PHYRXST_VALID (1 << 8) ++#define RXS_RXANT_MASK 0x3 ++#define RXS_RXANT_SHIFT 12 ++ ++/* RxChan */ ++#define RXS_CHAN_40 0x1000 ++#define RXS_CHAN_5G 0x0800 ++#define RXS_CHAN_ID_MASK 0x07f8 ++#define RXS_CHAN_ID_SHIFT 3 ++#define RXS_CHAN_PHYTYPE_MASK 0x0007 ++#define RXS_CHAN_PHYTYPE_SHIFT 0 ++ ++/* Index of attenuations used during ucode power control. */ ++#define M_PWRIND_BLKS (0x184 * 2) ++#define M_PWRIND_MAP0 (M_PWRIND_BLKS + 0x0) ++#define M_PWRIND_MAP1 (M_PWRIND_BLKS + 0x2) ++#define M_PWRIND_MAP2 (M_PWRIND_BLKS + 0x4) ++#define M_PWRIND_MAP3 (M_PWRIND_BLKS + 0x6) ++/* M_PWRIND_MAP(core) macro */ ++#define M_PWRIND_MAP(core) (M_PWRIND_BLKS + ((core)<<1)) ++ ++/* PSM SHM variable offsets */ ++#define M_PSM_SOFT_REGS 0x0 ++#define M_BOM_REV_MAJOR (M_PSM_SOFT_REGS + 0x0) ++#define M_BOM_REV_MINOR (M_PSM_SOFT_REGS + 0x2) ++#define M_UCODE_DBGST (M_PSM_SOFT_REGS + 0x40) /* ucode debug status code */ ++#define M_UCODE_MACSTAT (M_PSM_SOFT_REGS + 0xE0) /* macstat counters */ ++ ++#define M_AGING_THRSH (0x3e * 2) /* max time waiting for medium before tx */ ++#define M_MBURST_SIZE (0x40 * 2) /* max frames in a frameburst */ ++#define M_MBURST_TXOP (0x41 * 2) /* max frameburst TXOP in unit of us */ ++#define M_SYNTHPU_DLY (0x4a * 2) /* pre-wakeup for synthpu, default: 500 */ ++#define M_PRETBTT (0x4b * 2) ++ ++/* offset to the target txpwr */ ++#define M_ALT_TXPWR_IDX (M_PSM_SOFT_REGS + (0x3b * 2)) ++#define M_PHY_TX_FLT_PTR (M_PSM_SOFT_REGS + (0x3d * 2)) ++#define M_CTS_DURATION (M_PSM_SOFT_REGS + (0x5c * 2)) ++#define M_LP_RCCAL_OVR (M_PSM_SOFT_REGS + (0x6b * 2)) ++ ++/* PKTENG Rx Stats Block */ ++#define M_RXSTATS_BLK_PTR (M_PSM_SOFT_REGS + (0x65 * 2)) ++ ++/* ucode debug status codes */ ++/* not valid really */ ++#define DBGST_INACTIVE 0 ++/* after zeroing SHM, before suspending at init */ ++#define DBGST_INIT 1 ++/* "normal" state */ ++#define DBGST_ACTIVE 2 ++/* suspended */ ++#define DBGST_SUSPENDED 3 ++/* asleep (PS mode) */ ++#define DBGST_ASLEEP 4 ++ ++/* Scratch Reg defs */ ++enum _ePsmScratchPadRegDefinitions { ++ S_RSV0 = 0, ++ S_RSV1, ++ S_RSV2, ++ ++ /* offset 0x03: scratch registers for Dot11-contants */ ++ S_DOT11_CWMIN, /* CW-minimum */ ++ S_DOT11_CWMAX, /* CW-maximum */ ++ S_DOT11_CWCUR, /* CW-current */ ++ S_DOT11_SRC_LMT, /* short retry count limit */ ++ S_DOT11_LRC_LMT, /* long retry count limit */ ++ S_DOT11_DTIMCOUNT, /* DTIM-count */ ++ ++ /* offset 0x09: Tx-side scratch registers */ ++ S_SEQ_NUM, /* hardware sequence number reg */ ++ S_SEQ_NUM_FRAG, /* seq num for frags (at the start of MSDU) */ ++ S_FRMRETX_CNT, /* frame retx count */ ++ S_SSRC, /* Station short retry count */ ++ S_SLRC, /* Station long retry count */ ++ S_EXP_RSP, /* Expected response frame */ ++ S_OLD_BREM, /* Remaining backoff ctr */ ++ S_OLD_CWWIN, /* saved-off CW-cur */ ++ S_TXECTL, /* TXE-Ctl word constructed in scr-pad */ ++ S_CTXTST, /* frm type-subtype as read from Tx-descr */ ++ ++ /* offset 0x13: Rx-side scratch registers */ ++ S_RXTST, /* Type and subtype in Rxframe */ ++ ++ /* Global state register */ ++ S_STREG, /* state storage actual bit maps below */ ++ ++ S_TXPWR_SUM, /* Tx power control: accumulator */ ++ S_TXPWR_ITER, /* Tx power control: iteration */ ++ S_RX_FRMTYPE, /* Rate and PHY type for frames */ ++ S_THIS_AGG, /* Size of this AGG (A-MSDU) */ ++ ++ S_KEYINDX, ++ S_RXFRMLEN, /* Receive MPDU length in bytes */ ++ ++ /* offset 0x1B: Receive TSF time stored in SCR */ ++ S_RXTSFTMRVAL_WD3, /* TSF value at the start of rx */ ++ S_RXTSFTMRVAL_WD2, /* TSF value at the start of rx */ ++ S_RXTSFTMRVAL_WD1, /* TSF value at the start of rx */ ++ S_RXTSFTMRVAL_WD0, /* TSF value at the start of rx */ ++ S_RXSSN, /* Received start seq number for A-MPDU BA */ ++ S_RXQOSFLD, /* Rx-QoS field (if present) */ ++ ++ /* offset 0x21: Scratch pad regs used in microcode as temp storage */ ++ S_TMP0, /* stmp0 */ ++ S_TMP1, /* stmp1 */ ++ S_TMP2, /* stmp2 */ ++ S_TMP3, /* stmp3 */ ++ S_TMP4, /* stmp4 */ ++ S_TMP5, /* stmp5 */ ++ S_PRQPENALTY_CTR, /* Probe response queue penalty counter */ ++ S_ANTCNT, /* unsuccessful attempts on current ant. */ ++ S_SYMBOL, /* flag for possible symbol ctl frames */ ++ S_RXTP, /* rx frame type */ ++ S_STREG2, /* extra state storage */ ++ S_STREG3, /* even more extra state storage */ ++ S_STREG4, /* ... */ ++ S_STREG5, /* remember to initialize it to zero */ ++ ++ S_ADJPWR_IDX, ++ S_CUR_PTR, /* Temp pointer for A-MPDU re-Tx SHM table */ ++ S_REVID4, /* 0x33 */ ++ S_INDX, /* 0x34 */ ++ S_ADDR0, /* 0x35 */ ++ S_ADDR1, /* 0x36 */ ++ S_ADDR2, /* 0x37 */ ++ S_ADDR3, /* 0x38 */ ++ S_ADDR4, /* 0x39 */ ++ S_ADDR5, /* 0x3A */ ++ S_TMP6, /* 0x3B */ ++ S_KEYINDX_BU, /* Backup for Key index */ ++ S_MFGTEST_TMP0, /* Temp regs used for RX test calculations */ ++ S_RXESN, /* Received end sequence number for A-MPDU BA */ ++ S_STREG6, /* 0x3F */ ++}; ++ ++#define S_BEACON_INDX S_OLD_BREM ++#define S_PRS_INDX S_OLD_CWWIN ++#define S_PHYTYPE S_SSRC ++#define S_PHYVER S_SLRC ++ ++/* IHR SLOW_CTRL values */ ++#define SLOW_CTRL_PDE (1 << 0) ++#define SLOW_CTRL_FD (1 << 8) ++ ++/* ucode mac statistic counters in shared memory */ ++struct macstat { ++ u16 txallfrm; /* 0x80 */ ++ u16 txrtsfrm; /* 0x82 */ ++ u16 txctsfrm; /* 0x84 */ ++ u16 txackfrm; /* 0x86 */ ++ u16 txdnlfrm; /* 0x88 */ ++ u16 txbcnfrm; /* 0x8a */ ++ u16 txfunfl[8]; /* 0x8c - 0x9b */ ++ u16 txtplunfl; /* 0x9c */ ++ u16 txphyerr; /* 0x9e */ ++ u16 pktengrxducast; /* 0xa0 */ ++ u16 pktengrxdmcast; /* 0xa2 */ ++ u16 rxfrmtoolong; /* 0xa4 */ ++ u16 rxfrmtooshrt; /* 0xa6 */ ++ u16 rxinvmachdr; /* 0xa8 */ ++ u16 rxbadfcs; /* 0xaa */ ++ u16 rxbadplcp; /* 0xac */ ++ u16 rxcrsglitch; /* 0xae */ ++ u16 rxstrt; /* 0xb0 */ ++ u16 rxdfrmucastmbss; /* 0xb2 */ ++ u16 rxmfrmucastmbss; /* 0xb4 */ ++ u16 rxcfrmucast; /* 0xb6 */ ++ u16 rxrtsucast; /* 0xb8 */ ++ u16 rxctsucast; /* 0xba */ ++ u16 rxackucast; /* 0xbc */ ++ u16 rxdfrmocast; /* 0xbe */ ++ u16 rxmfrmocast; /* 0xc0 */ ++ u16 rxcfrmocast; /* 0xc2 */ ++ u16 rxrtsocast; /* 0xc4 */ ++ u16 rxctsocast; /* 0xc6 */ ++ u16 rxdfrmmcast; /* 0xc8 */ ++ u16 rxmfrmmcast; /* 0xca */ ++ u16 rxcfrmmcast; /* 0xcc */ ++ u16 rxbeaconmbss; /* 0xce */ ++ u16 rxdfrmucastobss; /* 0xd0 */ ++ u16 rxbeaconobss; /* 0xd2 */ ++ u16 rxrsptmout; /* 0xd4 */ ++ u16 bcntxcancl; /* 0xd6 */ ++ u16 PAD; ++ u16 rxf0ovfl; /* 0xda */ ++ u16 rxf1ovfl; /* 0xdc */ ++ u16 rxf2ovfl; /* 0xde */ ++ u16 txsfovfl; /* 0xe0 */ ++ u16 pmqovfl; /* 0xe2 */ ++ u16 rxcgprqfrm; /* 0xe4 */ ++ u16 rxcgprsqovfl; /* 0xe6 */ ++ u16 txcgprsfail; /* 0xe8 */ ++ u16 txcgprssuc; /* 0xea */ ++ u16 prs_timeout; /* 0xec */ ++ u16 rxnack; ++ u16 frmscons; ++ u16 txnack; ++ u16 txglitch_nack; ++ u16 txburst; /* 0xf6 # tx bursts */ ++ u16 bphy_rxcrsglitch; /* bphy rx crs glitch */ ++ u16 phywatchdog; /* 0xfa # of phy watchdog events */ ++ u16 PAD; ++ u16 bphy_badplcp; /* bphy bad plcp */ ++}; ++ ++/* dot11 core-specific control flags */ ++#define SICF_PCLKE 0x0004 /* PHY clock enable */ ++#define SICF_PRST 0x0008 /* PHY reset */ ++#define SICF_MPCLKE 0x0010 /* MAC PHY clockcontrol enable */ ++#define SICF_FREF 0x0020 /* PLL FreqRefSelect */ ++/* NOTE: the following bw bits only apply when the core is attached ++ * to a NPHY ++ */ ++#define SICF_BWMASK 0x00c0 /* phy clock mask (b6 & b7) */ ++#define SICF_BW40 0x0080 /* 40MHz BW (160MHz phyclk) */ ++#define SICF_BW20 0x0040 /* 20MHz BW (80MHz phyclk) */ ++#define SICF_BW10 0x0000 /* 10MHz BW (40MHz phyclk) */ ++#define SICF_GMODE 0x2000 /* gmode enable */ ++ ++/* dot11 core-specific status flags */ ++#define SISF_2G_PHY 0x0001 /* 2.4G capable phy */ ++#define SISF_5G_PHY 0x0002 /* 5G capable phy */ ++#define SISF_FCLKA 0x0004 /* FastClkAvailable */ ++#define SISF_DB_PHY 0x0008 /* Dualband phy */ ++ ++/* === End of MAC reg, Beginning of PHY(b/a/g/n) reg === */ ++/* radio and LPPHY regs are separated */ ++ ++#define BPHY_REG_OFT_BASE 0x0 ++/* offsets for indirect access to bphy registers */ ++#define BPHY_BB_CONFIG 0x01 ++#define BPHY_ADCBIAS 0x02 ++#define BPHY_ANACORE 0x03 ++#define BPHY_PHYCRSTH 0x06 ++#define BPHY_TEST 0x0a ++#define BPHY_PA_TX_TO 0x10 ++#define BPHY_SYNTH_DC_TO 0x11 ++#define BPHY_PA_TX_TIME_UP 0x12 ++#define BPHY_RX_FLTR_TIME_UP 0x13 ++#define BPHY_TX_POWER_OVERRIDE 0x14 ++#define BPHY_RF_OVERRIDE 0x15 ++#define BPHY_RF_TR_LOOKUP1 0x16 ++#define BPHY_RF_TR_LOOKUP2 0x17 ++#define BPHY_COEFFS 0x18 ++#define BPHY_PLL_OUT 0x19 ++#define BPHY_REFRESH_MAIN 0x1a ++#define BPHY_REFRESH_TO0 0x1b ++#define BPHY_REFRESH_TO1 0x1c ++#define BPHY_RSSI_TRESH 0x20 ++#define BPHY_IQ_TRESH_HH 0x21 ++#define BPHY_IQ_TRESH_H 0x22 ++#define BPHY_IQ_TRESH_L 0x23 ++#define BPHY_IQ_TRESH_LL 0x24 ++#define BPHY_GAIN 0x25 ++#define BPHY_LNA_GAIN_RANGE 0x26 ++#define BPHY_JSSI 0x27 ++#define BPHY_TSSI_CTL 0x28 ++#define BPHY_TSSI 0x29 ++#define BPHY_TR_LOSS_CTL 0x2a ++#define BPHY_LO_LEAKAGE 0x2b ++#define BPHY_LO_RSSI_ACC 0x2c ++#define BPHY_LO_IQMAG_ACC 0x2d ++#define BPHY_TX_DC_OFF1 0x2e ++#define BPHY_TX_DC_OFF2 0x2f ++#define BPHY_PEAK_CNT_THRESH 0x30 ++#define BPHY_FREQ_OFFSET 0x31 ++#define BPHY_DIVERSITY_CTL 0x32 ++#define BPHY_PEAK_ENERGY_LO 0x33 ++#define BPHY_PEAK_ENERGY_HI 0x34 ++#define BPHY_SYNC_CTL 0x35 ++#define BPHY_TX_PWR_CTRL 0x36 ++#define BPHY_TX_EST_PWR 0x37 ++#define BPHY_STEP 0x38 ++#define BPHY_WARMUP 0x39 ++#define BPHY_LMS_CFF_READ 0x3a ++#define BPHY_LMS_COEFF_I 0x3b ++#define BPHY_LMS_COEFF_Q 0x3c ++#define BPHY_SIG_POW 0x3d ++#define BPHY_RFDC_CANCEL_CTL 0x3e ++#define BPHY_HDR_TYPE 0x40 ++#define BPHY_SFD_TO 0x41 ++#define BPHY_SFD_CTL 0x42 ++#define BPHY_DEBUG 0x43 ++#define BPHY_RX_DELAY_COMP 0x44 ++#define BPHY_CRS_DROP_TO 0x45 ++#define BPHY_SHORT_SFD_NZEROS 0x46 ++#define BPHY_DSSS_COEFF1 0x48 ++#define BPHY_DSSS_COEFF2 0x49 ++#define BPHY_CCK_COEFF1 0x4a ++#define BPHY_CCK_COEFF2 0x4b ++#define BPHY_TR_CORR 0x4c ++#define BPHY_ANGLE_SCALE 0x4d ++#define BPHY_TX_PWR_BASE_IDX 0x4e ++#define BPHY_OPTIONAL_MODES2 0x4f ++#define BPHY_CCK_LMS_STEP 0x50 ++#define BPHY_BYPASS 0x51 ++#define BPHY_CCK_DELAY_LONG 0x52 ++#define BPHY_CCK_DELAY_SHORT 0x53 ++#define BPHY_PPROC_CHAN_DELAY 0x54 ++#define BPHY_DDFS_ENABLE 0x58 ++#define BPHY_PHASE_SCALE 0x59 ++#define BPHY_FREQ_CONTROL 0x5a ++#define BPHY_LNA_GAIN_RANGE_10 0x5b ++#define BPHY_LNA_GAIN_RANGE_32 0x5c ++#define BPHY_OPTIONAL_MODES 0x5d ++#define BPHY_RX_STATUS2 0x5e ++#define BPHY_RX_STATUS3 0x5f ++#define BPHY_DAC_CONTROL 0x60 ++#define BPHY_ANA11G_FILT_CTRL 0x62 ++#define BPHY_REFRESH_CTRL 0x64 ++#define BPHY_RF_OVERRIDE2 0x65 ++#define BPHY_SPUR_CANCEL_CTRL 0x66 ++#define BPHY_FINE_DIGIGAIN_CTRL 0x67 ++#define BPHY_RSSI_LUT 0x88 ++#define BPHY_RSSI_LUT_END 0xa7 ++#define BPHY_TSSI_LUT 0xa8 ++#define BPHY_TSSI_LUT_END 0xc7 ++#define BPHY_TSSI2PWR_LUT 0x380 ++#define BPHY_TSSI2PWR_LUT_END 0x39f ++#define BPHY_LOCOMP_LUT 0x3a0 ++#define BPHY_LOCOMP_LUT_END 0x3bf ++#define BPHY_TXGAIN_LUT 0x3c0 ++#define BPHY_TXGAIN_LUT_END 0x3ff ++ ++/* Bits in BB_CONFIG: */ ++#define PHY_BBC_ANT_MASK 0x0180 ++#define PHY_BBC_ANT_SHIFT 7 ++#define BB_DARWIN 0x1000 ++#define BBCFG_RESETCCA 0x4000 ++#define BBCFG_RESETRX 0x8000 ++ ++/* Bits in phytest(0x0a): */ ++#define TST_DDFS 0x2000 ++#define TST_TXFILT1 0x0800 ++#define TST_UNSCRAM 0x0400 ++#define TST_CARR_SUPP 0x0200 ++#define TST_DC_COMP_LOOP 0x0100 ++#define TST_LOOPBACK 0x0080 ++#define TST_TXFILT0 0x0040 ++#define TST_TXTEST_ENABLE 0x0020 ++#define TST_TXTEST_RATE 0x0018 ++#define TST_TXTEST_PHASE 0x0007 ++ ++/* phytest txTestRate values */ ++#define TST_TXTEST_RATE_1MBPS 0 ++#define TST_TXTEST_RATE_2MBPS 1 ++#define TST_TXTEST_RATE_5_5MBPS 2 ++#define TST_TXTEST_RATE_11MBPS 3 ++#define TST_TXTEST_RATE_SHIFT 3 ++ ++#define SHM_BYT_CNT 0x2 /* IHR location */ ++#define MAX_BYT_CNT 0x600 /* Maximum frame len */ ++ ++struct d11cnt { ++ u32 txfrag; ++ u32 txmulti; ++ u32 txfail; ++ u32 txretry; ++ u32 txretrie; ++ u32 rxdup; ++ u32 txrts; ++ u32 txnocts; ++ u32 txnoack; ++ u32 rxfrag; ++ u32 rxmulti; ++ u32 rxcrc; ++ u32 txfrmsnt; ++ u32 rxundec; ++}; ++ ++#endif /* _BRCM_D11_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.c.orig 2011-11-09 13:46:58.244800645 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.c 2011-11-09 13:47:16.997566205 -0500 +@@ -0,0 +1,1425 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include "types.h" ++#include "dma.h" ++ ++/* ++ * DMA hardware requires each descriptor ring to be 8kB aligned, and fit within ++ * a contiguous 8kB physical address. ++ */ ++#define D64RINGALIGN_BITS 13 ++#define D64MAXRINGSZ (1 << D64RINGALIGN_BITS) ++#define D64RINGALIGN (1 << D64RINGALIGN_BITS) ++ ++#define D64MAXDD (D64MAXRINGSZ / sizeof(struct dma64desc)) ++ ++/* transmit channel control */ ++#define D64_XC_XE 0x00000001 /* transmit enable */ ++#define D64_XC_SE 0x00000002 /* transmit suspend request */ ++#define D64_XC_LE 0x00000004 /* loopback enable */ ++#define D64_XC_FL 0x00000010 /* flush request */ ++#define D64_XC_PD 0x00000800 /* parity check disable */ ++#define D64_XC_AE 0x00030000 /* address extension bits */ ++#define D64_XC_AE_SHIFT 16 ++ ++/* transmit descriptor table pointer */ ++#define D64_XP_LD_MASK 0x00000fff /* last valid descriptor */ ++ ++/* transmit channel status */ ++#define D64_XS0_CD_MASK 0x00001fff /* current descriptor pointer */ ++#define D64_XS0_XS_MASK 0xf0000000 /* transmit state */ ++#define D64_XS0_XS_SHIFT 28 ++#define D64_XS0_XS_DISABLED 0x00000000 /* disabled */ ++#define D64_XS0_XS_ACTIVE 0x10000000 /* active */ ++#define D64_XS0_XS_IDLE 0x20000000 /* idle wait */ ++#define D64_XS0_XS_STOPPED 0x30000000 /* stopped */ ++#define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */ ++ ++#define D64_XS1_AD_MASK 0x00001fff /* active descriptor */ ++#define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */ ++#define D64_XS1_XE_SHIFT 28 ++#define D64_XS1_XE_NOERR 0x00000000 /* no error */ ++#define D64_XS1_XE_DPE 0x10000000 /* descriptor protocol error */ ++#define D64_XS1_XE_DFU 0x20000000 /* data fifo underrun */ ++#define D64_XS1_XE_DTE 0x30000000 /* data transfer error */ ++#define D64_XS1_XE_DESRE 0x40000000 /* descriptor read error */ ++#define D64_XS1_XE_COREE 0x50000000 /* core error */ ++ ++/* receive channel control */ ++/* receive enable */ ++#define D64_RC_RE 0x00000001 ++/* receive frame offset */ ++#define D64_RC_RO_MASK 0x000000fe ++#define D64_RC_RO_SHIFT 1 ++/* direct fifo receive (pio) mode */ ++#define D64_RC_FM 0x00000100 ++/* separate rx header descriptor enable */ ++#define D64_RC_SH 0x00000200 ++/* overflow continue */ ++#define D64_RC_OC 0x00000400 ++/* parity check disable */ ++#define D64_RC_PD 0x00000800 ++/* address extension bits */ ++#define D64_RC_AE 0x00030000 ++#define D64_RC_AE_SHIFT 16 ++ ++/* flags for dma controller */ ++/* partity enable */ ++#define DMA_CTRL_PEN (1 << 0) ++/* rx overflow continue */ ++#define DMA_CTRL_ROC (1 << 1) ++/* allow rx scatter to multiple descriptors */ ++#define DMA_CTRL_RXMULTI (1 << 2) ++/* Unframed Rx/Tx data */ ++#define DMA_CTRL_UNFRAMED (1 << 3) ++ ++/* receive descriptor table pointer */ ++#define D64_RP_LD_MASK 0x00000fff /* last valid descriptor */ ++ ++/* receive channel status */ ++#define D64_RS0_CD_MASK 0x00001fff /* current descriptor pointer */ ++#define D64_RS0_RS_MASK 0xf0000000 /* receive state */ ++#define D64_RS0_RS_SHIFT 28 ++#define D64_RS0_RS_DISABLED 0x00000000 /* disabled */ ++#define D64_RS0_RS_ACTIVE 0x10000000 /* active */ ++#define D64_RS0_RS_IDLE 0x20000000 /* idle wait */ ++#define D64_RS0_RS_STOPPED 0x30000000 /* stopped */ ++#define D64_RS0_RS_SUSP 0x40000000 /* suspend pending */ ++ ++#define D64_RS1_AD_MASK 0x0001ffff /* active descriptor */ ++#define D64_RS1_RE_MASK 0xf0000000 /* receive errors */ ++#define D64_RS1_RE_SHIFT 28 ++#define D64_RS1_RE_NOERR 0x00000000 /* no error */ ++#define D64_RS1_RE_DPO 0x10000000 /* descriptor protocol error */ ++#define D64_RS1_RE_DFU 0x20000000 /* data fifo overflow */ ++#define D64_RS1_RE_DTE 0x30000000 /* data transfer error */ ++#define D64_RS1_RE_DESRE 0x40000000 /* descriptor read error */ ++#define D64_RS1_RE_COREE 0x50000000 /* core error */ ++ ++/* fifoaddr */ ++#define D64_FA_OFF_MASK 0xffff /* offset */ ++#define D64_FA_SEL_MASK 0xf0000 /* select */ ++#define D64_FA_SEL_SHIFT 16 ++#define D64_FA_SEL_XDD 0x00000 /* transmit dma data */ ++#define D64_FA_SEL_XDP 0x10000 /* transmit dma pointers */ ++#define D64_FA_SEL_RDD 0x40000 /* receive dma data */ ++#define D64_FA_SEL_RDP 0x50000 /* receive dma pointers */ ++#define D64_FA_SEL_XFD 0x80000 /* transmit fifo data */ ++#define D64_FA_SEL_XFP 0x90000 /* transmit fifo pointers */ ++#define D64_FA_SEL_RFD 0xc0000 /* receive fifo data */ ++#define D64_FA_SEL_RFP 0xd0000 /* receive fifo pointers */ ++#define D64_FA_SEL_RSD 0xe0000 /* receive frame status data */ ++#define D64_FA_SEL_RSP 0xf0000 /* receive frame status pointers */ ++ ++/* descriptor control flags 1 */ ++#define D64_CTRL_COREFLAGS 0x0ff00000 /* core specific flags */ ++#define D64_CTRL1_EOT ((u32)1 << 28) /* end of descriptor table */ ++#define D64_CTRL1_IOC ((u32)1 << 29) /* interrupt on completion */ ++#define D64_CTRL1_EOF ((u32)1 << 30) /* end of frame */ ++#define D64_CTRL1_SOF ((u32)1 << 31) /* start of frame */ ++ ++/* descriptor control flags 2 */ ++/* buffer byte count. real data len must <= 16KB */ ++#define D64_CTRL2_BC_MASK 0x00007fff ++/* address extension bits */ ++#define D64_CTRL2_AE 0x00030000 ++#define D64_CTRL2_AE_SHIFT 16 ++/* parity bit */ ++#define D64_CTRL2_PARITY 0x00040000 ++ ++/* control flags in the range [27:20] are core-specific and not defined here */ ++#define D64_CTRL_CORE_MASK 0x0ff00000 ++ ++#define D64_RX_FRM_STS_LEN 0x0000ffff /* frame length mask */ ++#define D64_RX_FRM_STS_OVFL 0x00800000 /* RxOverFlow */ ++#define D64_RX_FRM_STS_DSCRCNT 0x0f000000 /* no. of descriptors used - 1 */ ++#define D64_RX_FRM_STS_DATATYPE 0xf0000000 /* core-dependent data type */ ++ ++/* ++ * packet headroom necessary to accommodate the largest header ++ * in the system, (i.e TXOFF). By doing, we avoid the need to ++ * allocate an extra buffer for the header when bridging to WL. ++ * There is a compile time check in wlc.c which ensure that this ++ * value is at least as big as TXOFF. This value is used in ++ * dma_rxfill(). ++ */ ++ ++#define BCMEXTRAHDROOM 172 ++ ++/* debug/trace */ ++#ifdef BCMDBG ++#define DMA_ERROR(args) \ ++ do { \ ++ if (!(*di->msg_level & 1)) \ ++ ; \ ++ else \ ++ printk args; \ ++ } while (0) ++#define DMA_TRACE(args) \ ++ do { \ ++ if (!(*di->msg_level & 2)) \ ++ ; \ ++ else \ ++ printk args; \ ++ } while (0) ++#else ++#define DMA_ERROR(args) ++#define DMA_TRACE(args) ++#endif /* BCMDBG */ ++ ++#define DMA_NONE(args) ++ ++#define MAXNAMEL 8 /* 8 char names */ ++ ++/* macros to convert between byte offsets and indexes */ ++#define B2I(bytes, type) ((bytes) / sizeof(type)) ++#define I2B(index, type) ((index) * sizeof(type)) ++ ++#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */ ++#define PCI32ADDR_HIGH_SHIFT 30 /* address[31:30] */ ++ ++#define PCI64ADDR_HIGH 0x80000000 /* address[63] */ ++#define PCI64ADDR_HIGH_SHIFT 31 /* address[63] */ ++ ++/* ++ * DMA Descriptor ++ * Descriptors are only read by the hardware, never written back. ++ */ ++struct dma64desc { ++ __le32 ctrl1; /* misc control bits & bufcount */ ++ __le32 ctrl2; /* buffer count and address extension */ ++ __le32 addrlow; /* memory address of the date buffer, bits 31:0 */ ++ __le32 addrhigh; /* memory address of the date buffer, bits 63:32 */ ++}; ++ ++/* dma engine software state */ ++struct dma_info { ++ struct dma_pub dma; /* exported structure */ ++ uint *msg_level; /* message level pointer */ ++ char name[MAXNAMEL]; /* callers name for diag msgs */ ++ ++ struct pci_dev *pbus; /* bus handle */ ++ ++ bool dma64; /* this dma engine is operating in 64-bit mode */ ++ bool addrext; /* this dma engine supports DmaExtendedAddrChanges */ ++ ++ /* 64-bit dma tx engine registers */ ++ struct dma64regs __iomem *d64txregs; ++ /* 64-bit dma rx engine registers */ ++ struct dma64regs __iomem *d64rxregs; ++ /* pointer to dma64 tx descriptor ring */ ++ struct dma64desc *txd64; ++ /* pointer to dma64 rx descriptor ring */ ++ struct dma64desc *rxd64; ++ ++ u16 dmadesc_align; /* alignment requirement for dma descriptors */ ++ ++ u16 ntxd; /* # tx descriptors tunable */ ++ u16 txin; /* index of next descriptor to reclaim */ ++ u16 txout; /* index of next descriptor to post */ ++ /* pointer to parallel array of pointers to packets */ ++ struct sk_buff **txp; ++ /* Aligned physical address of descriptor ring */ ++ dma_addr_t txdpa; ++ /* Original physical address of descriptor ring */ ++ dma_addr_t txdpaorig; ++ u16 txdalign; /* #bytes added to alloc'd mem to align txd */ ++ u32 txdalloc; /* #bytes allocated for the ring */ ++ u32 xmtptrbase; /* When using unaligned descriptors, the ptr register ++ * is not just an index, it needs all 13 bits to be ++ * an offset from the addr register. ++ */ ++ ++ u16 nrxd; /* # rx descriptors tunable */ ++ u16 rxin; /* index of next descriptor to reclaim */ ++ u16 rxout; /* index of next descriptor to post */ ++ /* pointer to parallel array of pointers to packets */ ++ struct sk_buff **rxp; ++ /* Aligned physical address of descriptor ring */ ++ dma_addr_t rxdpa; ++ /* Original physical address of descriptor ring */ ++ dma_addr_t rxdpaorig; ++ u16 rxdalign; /* #bytes added to alloc'd mem to align rxd */ ++ u32 rxdalloc; /* #bytes allocated for the ring */ ++ u32 rcvptrbase; /* Base for ptr reg when using unaligned descriptors */ ++ ++ /* tunables */ ++ unsigned int rxbufsize; /* rx buffer size in bytes, not including ++ * the extra headroom ++ */ ++ uint rxextrahdrroom; /* extra rx headroom, reverseved to assist upper ++ * stack, e.g. some rx pkt buffers will be ++ * bridged to tx side without byte copying. ++ * The extra headroom needs to be large enough ++ * to fit txheader needs. Some dongle driver may ++ * not need it. ++ */ ++ uint nrxpost; /* # rx buffers to keep posted */ ++ unsigned int rxoffset; /* rxcontrol offset */ ++ /* add to get dma address of descriptor ring, low 32 bits */ ++ uint ddoffsetlow; ++ /* high 32 bits */ ++ uint ddoffsethigh; ++ /* add to get dma address of data buffer, low 32 bits */ ++ uint dataoffsetlow; ++ /* high 32 bits */ ++ uint dataoffsethigh; ++ /* descriptor base need to be aligned or not */ ++ bool aligndesc_4k; ++}; ++ ++/* ++ * default dma message level (if input msg_level ++ * pointer is null in dma_attach()) ++ */ ++static uint dma_msg_level; ++ ++/* Check for odd number of 1's */ ++static u32 parity32(__le32 data) ++{ ++ /* no swap needed for counting 1's */ ++ u32 par_data = *(u32 *)&data; ++ ++ par_data ^= par_data >> 16; ++ par_data ^= par_data >> 8; ++ par_data ^= par_data >> 4; ++ par_data ^= par_data >> 2; ++ par_data ^= par_data >> 1; ++ ++ return par_data & 1; ++} ++ ++static bool dma64_dd_parity(struct dma64desc *dd) ++{ ++ return parity32(dd->addrlow ^ dd->addrhigh ^ dd->ctrl1 ^ dd->ctrl2); ++} ++ ++/* descriptor bumping functions */ ++ ++static uint xxd(uint x, uint n) ++{ ++ return x & (n - 1); /* faster than %, but n must be power of 2 */ ++} ++ ++static uint txd(struct dma_info *di, uint x) ++{ ++ return xxd(x, di->ntxd); ++} ++ ++static uint rxd(struct dma_info *di, uint x) ++{ ++ return xxd(x, di->nrxd); ++} ++ ++static uint nexttxd(struct dma_info *di, uint i) ++{ ++ return txd(di, i + 1); ++} ++ ++static uint prevtxd(struct dma_info *di, uint i) ++{ ++ return txd(di, i - 1); ++} ++ ++static uint nextrxd(struct dma_info *di, uint i) ++{ ++ return txd(di, i + 1); ++} ++ ++static uint ntxdactive(struct dma_info *di, uint h, uint t) ++{ ++ return txd(di, t-h); ++} ++ ++static uint nrxdactive(struct dma_info *di, uint h, uint t) ++{ ++ return rxd(di, t-h); ++} ++ ++static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags) ++{ ++ uint dmactrlflags = di->dma.dmactrlflags; ++ ++ if (di == NULL) { ++ DMA_ERROR(("%s: _dma_ctrlflags: NULL dma handle\n", di->name)); ++ return 0; ++ } ++ ++ dmactrlflags &= ~mask; ++ dmactrlflags |= flags; ++ ++ /* If trying to enable parity, check if parity is actually supported */ ++ if (dmactrlflags & DMA_CTRL_PEN) { ++ u32 control; ++ ++ control = R_REG(&di->d64txregs->control); ++ W_REG(&di->d64txregs->control, ++ control | D64_XC_PD); ++ if (R_REG(&di->d64txregs->control) & D64_XC_PD) ++ /* We *can* disable it so it is supported, ++ * restore control register ++ */ ++ W_REG(&di->d64txregs->control, ++ control); ++ else ++ /* Not supported, don't allow it to be enabled */ ++ dmactrlflags &= ~DMA_CTRL_PEN; ++ } ++ ++ di->dma.dmactrlflags = dmactrlflags; ++ ++ return dmactrlflags; ++} ++ ++static bool _dma64_addrext(struct dma64regs __iomem *dma64regs) ++{ ++ u32 w; ++ OR_REG(&dma64regs->control, D64_XC_AE); ++ w = R_REG(&dma64regs->control); ++ AND_REG(&dma64regs->control, ~D64_XC_AE); ++ return (w & D64_XC_AE) == D64_XC_AE; ++} ++ ++/* ++ * return true if this dma engine supports DmaExtendedAddrChanges, ++ * otherwise false ++ */ ++static bool _dma_isaddrext(struct dma_info *di) ++{ ++ /* DMA64 supports full 32- or 64-bit operation. AE is always valid */ ++ ++ /* not all tx or rx channel are available */ ++ if (di->d64txregs != NULL) { ++ if (!_dma64_addrext(di->d64txregs)) ++ DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have " ++ "AE set\n", di->name)); ++ return true; ++ } else if (di->d64rxregs != NULL) { ++ if (!_dma64_addrext(di->d64rxregs)) ++ DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have " ++ "AE set\n", di->name)); ++ return true; ++ } ++ ++ return false; ++} ++ ++static bool _dma_descriptor_align(struct dma_info *di) ++{ ++ u32 addrl; ++ ++ /* Check to see if the descriptors need to be aligned on 4K/8K or not */ ++ if (di->d64txregs != NULL) { ++ W_REG(&di->d64txregs->addrlow, 0xff0); ++ addrl = R_REG(&di->d64txregs->addrlow); ++ if (addrl != 0) ++ return false; ++ } else if (di->d64rxregs != NULL) { ++ W_REG(&di->d64rxregs->addrlow, 0xff0); ++ addrl = R_REG(&di->d64rxregs->addrlow); ++ if (addrl != 0) ++ return false; ++ } ++ return true; ++} ++ ++/* ++ * Descriptor table must start at the DMA hardware dictated alignment, so ++ * allocated memory must be large enough to support this requirement. ++ */ ++static void *dma_alloc_consistent(struct pci_dev *pdev, uint size, ++ u16 align_bits, uint *alloced, ++ dma_addr_t *pap) ++{ ++ if (align_bits) { ++ u16 align = (1 << align_bits); ++ if (!IS_ALIGNED(PAGE_SIZE, align)) ++ size += align; ++ *alloced = size; ++ } ++ return pci_alloc_consistent(pdev, size, pap); ++} ++ ++static ++u8 dma_align_sizetobits(uint size) ++{ ++ u8 bitpos = 0; ++ while (size >>= 1) ++ bitpos++; ++ return bitpos; ++} ++ ++/* This function ensures that the DMA descriptor ring will not get allocated ++ * across Page boundary. If the allocation is done across the page boundary ++ * at the first time, then it is freed and the allocation is done at ++ * descriptor ring size aligned location. This will ensure that the ring will ++ * not cross page boundary ++ */ ++static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size, ++ u16 *alignbits, uint *alloced, ++ dma_addr_t *descpa) ++{ ++ void *va; ++ u32 desc_strtaddr; ++ u32 alignbytes = 1 << *alignbits; ++ ++ va = dma_alloc_consistent(di->pbus, size, *alignbits, alloced, descpa); ++ ++ if (NULL == va) ++ return NULL; ++ ++ desc_strtaddr = (u32) roundup((unsigned long)va, alignbytes); ++ if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr ++ & boundary)) { ++ *alignbits = dma_align_sizetobits(size); ++ pci_free_consistent(di->pbus, size, va, *descpa); ++ va = dma_alloc_consistent(di->pbus, size, *alignbits, ++ alloced, descpa); ++ } ++ return va; ++} ++ ++static bool dma64_alloc(struct dma_info *di, uint direction) ++{ ++ u16 size; ++ uint ddlen; ++ void *va; ++ uint alloced = 0; ++ u16 align; ++ u16 align_bits; ++ ++ ddlen = sizeof(struct dma64desc); ++ ++ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); ++ align_bits = di->dmadesc_align; ++ align = (1 << align_bits); ++ ++ if (direction == DMA_TX) { ++ va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits, ++ &alloced, &di->txdpaorig); ++ if (va == NULL) { ++ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd)" ++ " failed\n", di->name)); ++ return false; ++ } ++ align = (1 << align_bits); ++ di->txd64 = (struct dma64desc *) ++ roundup((unsigned long)va, align); ++ di->txdalign = (uint) ((s8 *)di->txd64 - (s8 *) va); ++ di->txdpa = di->txdpaorig + di->txdalign; ++ di->txdalloc = alloced; ++ } else { ++ va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits, ++ &alloced, &di->rxdpaorig); ++ if (va == NULL) { ++ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd)" ++ " failed\n", di->name)); ++ return false; ++ } ++ align = (1 << align_bits); ++ di->rxd64 = (struct dma64desc *) ++ roundup((unsigned long)va, align); ++ di->rxdalign = (uint) ((s8 *)di->rxd64 - (s8 *) va); ++ di->rxdpa = di->rxdpaorig + di->rxdalign; ++ di->rxdalloc = alloced; ++ } ++ ++ return true; ++} ++ ++static bool _dma_alloc(struct dma_info *di, uint direction) ++{ ++ return dma64_alloc(di, direction); ++} ++ ++struct dma_pub *dma_attach(char *name, struct si_pub *sih, ++ void __iomem *dmaregstx, void __iomem *dmaregsrx, ++ uint ntxd, uint nrxd, ++ uint rxbufsize, int rxextheadroom, ++ uint nrxpost, uint rxoffset, uint *msg_level) ++{ ++ struct dma_info *di; ++ uint size; ++ ++ /* allocate private info structure */ ++ di = kzalloc(sizeof(struct dma_info), GFP_ATOMIC); ++ if (di == NULL) ++ return NULL; ++ ++ di->msg_level = msg_level ? msg_level : &dma_msg_level; ++ ++ ++ di->dma64 = ((ai_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64); ++ ++ /* init dma reg pointer */ ++ di->d64txregs = (struct dma64regs __iomem *) dmaregstx; ++ di->d64rxregs = (struct dma64regs __iomem *) dmaregsrx; ++ ++ /* ++ * Default flags (which can be changed by the driver calling ++ * dma_ctrlflags before enable): For backwards compatibility ++ * both Rx Overflow Continue and Parity are DISABLED. ++ */ ++ _dma_ctrlflags(di, DMA_CTRL_ROC | DMA_CTRL_PEN, 0); ++ ++ DMA_TRACE(("%s: dma_attach: %s flags 0x%x ntxd %d nrxd %d " ++ "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d " ++ "dmaregstx %p dmaregsrx %p\n", name, "DMA64", ++ di->dma.dmactrlflags, ntxd, nrxd, rxbufsize, ++ rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx)); ++ ++ /* make a private copy of our callers name */ ++ strncpy(di->name, name, MAXNAMEL); ++ di->name[MAXNAMEL - 1] = '\0'; ++ ++ di->pbus = ((struct si_info *)sih)->pbus; ++ ++ /* save tunables */ ++ di->ntxd = (u16) ntxd; ++ di->nrxd = (u16) nrxd; ++ ++ /* the actual dma size doesn't include the extra headroom */ ++ di->rxextrahdrroom = ++ (rxextheadroom == -1) ? BCMEXTRAHDROOM : rxextheadroom; ++ if (rxbufsize > BCMEXTRAHDROOM) ++ di->rxbufsize = (u16) (rxbufsize - di->rxextrahdrroom); ++ else ++ di->rxbufsize = (u16) rxbufsize; ++ ++ di->nrxpost = (u16) nrxpost; ++ di->rxoffset = (u8) rxoffset; ++ ++ /* ++ * figure out the DMA physical address offset for dd and data ++ * PCI/PCIE: they map silicon backplace address to zero ++ * based memory, need offset ++ * Other bus: use zero SI_BUS BIGENDIAN kludge: use sdram ++ * swapped region for data buffer, not descriptor ++ */ ++ di->ddoffsetlow = 0; ++ di->dataoffsetlow = 0; ++ /* add offset for pcie with DMA64 bus */ ++ di->ddoffsetlow = 0; ++ di->ddoffsethigh = SI_PCIE_DMA_H32; ++ di->dataoffsetlow = di->ddoffsetlow; ++ di->dataoffsethigh = di->ddoffsethigh; ++ /* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */ ++ if ((ai_coreid(sih) == SDIOD_CORE_ID) ++ && ((ai_corerev(sih) > 0) && (ai_corerev(sih) <= 2))) ++ di->addrext = 0; ++ else if ((ai_coreid(sih) == I2S_CORE_ID) && ++ ((ai_corerev(sih) == 0) || (ai_corerev(sih) == 1))) ++ di->addrext = 0; ++ else ++ di->addrext = _dma_isaddrext(di); ++ ++ /* does the descriptor need to be aligned and if yes, on 4K/8K or not */ ++ di->aligndesc_4k = _dma_descriptor_align(di); ++ if (di->aligndesc_4k) { ++ di->dmadesc_align = D64RINGALIGN_BITS; ++ if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) ++ /* for smaller dd table, HW relax alignment reqmnt */ ++ di->dmadesc_align = D64RINGALIGN_BITS - 1; ++ } else { ++ di->dmadesc_align = 4; /* 16 byte alignment */ ++ } ++ ++ DMA_NONE(("DMA descriptor align_needed %d, align %d\n", ++ di->aligndesc_4k, di->dmadesc_align)); ++ ++ /* allocate tx packet pointer vector */ ++ if (ntxd) { ++ size = ntxd * sizeof(void *); ++ di->txp = kzalloc(size, GFP_ATOMIC); ++ if (di->txp == NULL) ++ goto fail; ++ } ++ ++ /* allocate rx packet pointer vector */ ++ if (nrxd) { ++ size = nrxd * sizeof(void *); ++ di->rxp = kzalloc(size, GFP_ATOMIC); ++ if (di->rxp == NULL) ++ goto fail; ++ } ++ ++ /* ++ * allocate transmit descriptor ring, only need ntxd descriptors ++ * but it must be aligned ++ */ ++ if (ntxd) { ++ if (!_dma_alloc(di, DMA_TX)) ++ goto fail; ++ } ++ ++ /* ++ * allocate receive descriptor ring, only need nrxd descriptors ++ * but it must be aligned ++ */ ++ if (nrxd) { ++ if (!_dma_alloc(di, DMA_RX)) ++ goto fail; ++ } ++ ++ if ((di->ddoffsetlow != 0) && !di->addrext) { ++ if (di->txdpa > SI_PCI_DMA_SZ) { ++ DMA_ERROR(("%s: dma_attach: txdpa 0x%x: addrext not " ++ "supported\n", di->name, (u32)di->txdpa)); ++ goto fail; ++ } ++ if (di->rxdpa > SI_PCI_DMA_SZ) { ++ DMA_ERROR(("%s: dma_attach: rxdpa 0x%x: addrext not " ++ "supported\n", di->name, (u32)di->rxdpa)); ++ goto fail; ++ } ++ } ++ ++ DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x " ++ "dataoffsethigh " "0x%x addrext %d\n", di->ddoffsetlow, ++ di->ddoffsethigh, di->dataoffsetlow, di->dataoffsethigh, ++ di->addrext)); ++ ++ return (struct dma_pub *) di; ++ ++ fail: ++ dma_detach((struct dma_pub *)di); ++ return NULL; ++} ++ ++static inline void ++dma64_dd_upd(struct dma_info *di, struct dma64desc *ddring, ++ dma_addr_t pa, uint outidx, u32 *flags, u32 bufcount) ++{ ++ u32 ctrl2 = bufcount & D64_CTRL2_BC_MASK; ++ ++ /* PCI bus with big(>1G) physical address, use address extension */ ++ if ((di->dataoffsetlow == 0) || !(pa & PCI32ADDR_HIGH)) { ++ ddring[outidx].addrlow = cpu_to_le32(pa + di->dataoffsetlow); ++ ddring[outidx].addrhigh = cpu_to_le32(di->dataoffsethigh); ++ ddring[outidx].ctrl1 = cpu_to_le32(*flags); ++ ddring[outidx].ctrl2 = cpu_to_le32(ctrl2); ++ } else { ++ /* address extension for 32-bit PCI */ ++ u32 ae; ++ ++ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ pa &= ~PCI32ADDR_HIGH; ++ ++ ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE; ++ ddring[outidx].addrlow = cpu_to_le32(pa + di->dataoffsetlow); ++ ddring[outidx].addrhigh = cpu_to_le32(di->dataoffsethigh); ++ ddring[outidx].ctrl1 = cpu_to_le32(*flags); ++ ddring[outidx].ctrl2 = cpu_to_le32(ctrl2); ++ } ++ if (di->dma.dmactrlflags & DMA_CTRL_PEN) { ++ if (dma64_dd_parity(&ddring[outidx])) ++ ddring[outidx].ctrl2 = ++ cpu_to_le32(ctrl2 | D64_CTRL2_PARITY); ++ } ++} ++ ++/* !! may be called with core in reset */ ++void dma_detach(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ ++ DMA_TRACE(("%s: dma_detach\n", di->name)); ++ ++ /* free dma descriptor rings */ ++ if (di->txd64) ++ pci_free_consistent(di->pbus, di->txdalloc, ++ ((s8 *)di->txd64 - di->txdalign), ++ (di->txdpaorig)); ++ if (di->rxd64) ++ pci_free_consistent(di->pbus, di->rxdalloc, ++ ((s8 *)di->rxd64 - di->rxdalign), ++ (di->rxdpaorig)); ++ ++ /* free packet pointer vectors */ ++ kfree(di->txp); ++ kfree(di->rxp); ++ ++ /* free our private info structure */ ++ kfree(di); ++ ++} ++ ++/* initialize descriptor table base address */ ++static void ++_dma_ddtable_init(struct dma_info *di, uint direction, dma_addr_t pa) ++{ ++ if (!di->aligndesc_4k) { ++ if (direction == DMA_TX) ++ di->xmtptrbase = pa; ++ else ++ di->rcvptrbase = pa; ++ } ++ ++ if ((di->ddoffsetlow == 0) ++ || !(pa & PCI32ADDR_HIGH)) { ++ if (direction == DMA_TX) { ++ W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow); ++ W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh); ++ } else { ++ W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow); ++ W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh); ++ } ++ } else { ++ /* DMA64 32bits address extension */ ++ u32 ae; ++ ++ /* shift the high bit(s) from pa to ae */ ++ ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ pa &= ~PCI32ADDR_HIGH; ++ ++ if (direction == DMA_TX) { ++ W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow); ++ W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh); ++ SET_REG(&di->d64txregs->control, ++ D64_XC_AE, (ae << D64_XC_AE_SHIFT)); ++ } else { ++ W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow); ++ W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh); ++ SET_REG(&di->d64rxregs->control, ++ D64_RC_AE, (ae << D64_RC_AE_SHIFT)); ++ } ++ } ++} ++ ++static void _dma_rxenable(struct dma_info *di) ++{ ++ uint dmactrlflags = di->dma.dmactrlflags; ++ u32 control; ++ ++ DMA_TRACE(("%s: dma_rxenable\n", di->name)); ++ ++ control = ++ (R_REG(&di->d64rxregs->control) & D64_RC_AE) | ++ D64_RC_RE; ++ ++ if ((dmactrlflags & DMA_CTRL_PEN) == 0) ++ control |= D64_RC_PD; ++ ++ if (dmactrlflags & DMA_CTRL_ROC) ++ control |= D64_RC_OC; ++ ++ W_REG(&di->d64rxregs->control, ++ ((di->rxoffset << D64_RC_RO_SHIFT) | control)); ++} ++ ++void dma_rxinit(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ ++ DMA_TRACE(("%s: dma_rxinit\n", di->name)); ++ ++ if (di->nrxd == 0) ++ return; ++ ++ di->rxin = di->rxout = 0; ++ ++ /* clear rx descriptor ring */ ++ memset(di->rxd64, '\0', di->nrxd * sizeof(struct dma64desc)); ++ ++ /* DMA engine with out alignment requirement requires table to be inited ++ * before enabling the engine ++ */ ++ if (!di->aligndesc_4k) ++ _dma_ddtable_init(di, DMA_RX, di->rxdpa); ++ ++ _dma_rxenable(di); ++ ++ if (di->aligndesc_4k) ++ _dma_ddtable_init(di, DMA_RX, di->rxdpa); ++} ++ ++static struct sk_buff *dma64_getnextrxp(struct dma_info *di, bool forceall) ++{ ++ uint i, curr; ++ struct sk_buff *rxp; ++ dma_addr_t pa; ++ ++ i = di->rxin; ++ ++ /* return if no packets posted */ ++ if (i == di->rxout) ++ return NULL; ++ ++ curr = ++ B2I(((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, struct dma64desc); ++ ++ /* ignore curr if forceall */ ++ if (!forceall && (i == curr)) ++ return NULL; ++ ++ /* get the packet pointer that corresponds to the rx descriptor */ ++ rxp = di->rxp[i]; ++ di->rxp[i] = NULL; ++ ++ pa = le32_to_cpu(di->rxd64[i].addrlow) - di->dataoffsetlow; ++ ++ /* clear this packet from the descriptor ring */ ++ pci_unmap_single(di->pbus, pa, di->rxbufsize, PCI_DMA_FROMDEVICE); ++ ++ di->rxd64[i].addrlow = cpu_to_le32(0xdeadbeef); ++ di->rxd64[i].addrhigh = cpu_to_le32(0xdeadbeef); ++ ++ di->rxin = nextrxd(di, i); ++ ++ return rxp; ++} ++ ++static struct sk_buff *_dma_getnextrxp(struct dma_info *di, bool forceall) ++{ ++ if (di->nrxd == 0) ++ return NULL; ++ ++ return dma64_getnextrxp(di, forceall); ++} ++ ++/* ++ * !! rx entry routine ++ * returns a pointer to the next frame received, or NULL if there are no more ++ * if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is ++ * supported with pkts chain ++ * otherwise, it's treated as giant pkt and will be tossed. ++ * The DMA scattering starts with normal DMA header, followed by first ++ * buffer data. After it reaches the max size of buffer, the data continues ++ * in next DMA descriptor buffer WITHOUT DMA header ++ */ ++struct sk_buff *dma_rx(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ struct sk_buff *p, *head, *tail; ++ uint len; ++ uint pkt_len; ++ int resid = 0; ++ ++ next_frame: ++ head = _dma_getnextrxp(di, false); ++ if (head == NULL) ++ return NULL; ++ ++ len = le16_to_cpu(*(__le16 *) (head->data)); ++ DMA_TRACE(("%s: dma_rx len %d\n", di->name, len)); ++ dma_spin_for_len(len, head); ++ ++ /* set actual length */ ++ pkt_len = min((di->rxoffset + len), di->rxbufsize); ++ __skb_trim(head, pkt_len); ++ resid = len - (di->rxbufsize - di->rxoffset); ++ ++ /* check for single or multi-buffer rx */ ++ if (resid > 0) { ++ tail = head; ++ while ((resid > 0) && (p = _dma_getnextrxp(di, false))) { ++ tail->next = p; ++ pkt_len = min_t(uint, resid, di->rxbufsize); ++ __skb_trim(p, pkt_len); ++ ++ tail = p; ++ resid -= di->rxbufsize; ++ } ++ ++#ifdef BCMDBG ++ if (resid > 0) { ++ uint cur; ++ cur = ++ B2I(((R_REG(&di->d64rxregs->status0) & ++ D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, ++ struct dma64desc); ++ DMA_ERROR(("dma_rx, rxin %d rxout %d, hw_curr %d\n", ++ di->rxin, di->rxout, cur)); ++ } ++#endif /* BCMDBG */ ++ ++ if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) { ++ DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n", ++ di->name, len)); ++ brcmu_pkt_buf_free_skb(head); ++ di->dma.rxgiants++; ++ goto next_frame; ++ } ++ } ++ ++ return head; ++} ++ ++static bool dma64_rxidle(struct dma_info *di) ++{ ++ DMA_TRACE(("%s: dma_rxidle\n", di->name)); ++ ++ if (di->nrxd == 0) ++ return true; ++ ++ return ((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) == ++ (R_REG(&di->d64rxregs->ptr) & D64_RS0_CD_MASK)); ++} ++ ++/* ++ * post receive buffers ++ * return false is refill failed completely and ring is empty this will stall ++ * the rx dma and user might want to call rxfill again asap. This unlikely ++ * happens on memory-rich NIC, but often on memory-constrained dongle ++ */ ++bool dma_rxfill(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ struct sk_buff *p; ++ u16 rxin, rxout; ++ u32 flags = 0; ++ uint n; ++ uint i; ++ dma_addr_t pa; ++ uint extra_offset = 0; ++ bool ring_empty; ++ ++ ring_empty = false; ++ ++ /* ++ * Determine how many receive buffers we're lacking ++ * from the full complement, allocate, initialize, ++ * and post them, then update the chip rx lastdscr. ++ */ ++ ++ rxin = di->rxin; ++ rxout = di->rxout; ++ ++ n = di->nrxpost - nrxdactive(di, rxin, rxout); ++ ++ DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n)); ++ ++ if (di->rxbufsize > BCMEXTRAHDROOM) ++ extra_offset = di->rxextrahdrroom; ++ ++ for (i = 0; i < n; i++) { ++ /* ++ * the di->rxbufsize doesn't include the extra headroom, ++ * we need to add it to the size to be allocated ++ */ ++ p = brcmu_pkt_buf_get_skb(di->rxbufsize + extra_offset); ++ ++ if (p == NULL) { ++ DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n", ++ di->name)); ++ if (i == 0 && dma64_rxidle(di)) { ++ DMA_ERROR(("%s: rxfill64: ring is empty !\n", ++ di->name)); ++ ring_empty = true; ++ } ++ di->dma.rxnobuf++; ++ break; ++ } ++ /* reserve an extra headroom, if applicable */ ++ if (extra_offset) ++ skb_pull(p, extra_offset); ++ ++ /* Do a cached write instead of uncached write since DMA_MAP ++ * will flush the cache. ++ */ ++ *(u32 *) (p->data) = 0; ++ ++ pa = pci_map_single(di->pbus, p->data, ++ di->rxbufsize, PCI_DMA_FROMDEVICE); ++ ++ /* save the free packet pointer */ ++ di->rxp[rxout] = p; ++ ++ /* reset flags for each descriptor */ ++ flags = 0; ++ if (rxout == (di->nrxd - 1)) ++ flags = D64_CTRL1_EOT; ++ ++ dma64_dd_upd(di, di->rxd64, pa, rxout, &flags, ++ di->rxbufsize); ++ rxout = nextrxd(di, rxout); ++ } ++ ++ di->rxout = rxout; ++ ++ /* update the chip lastdscr pointer */ ++ W_REG(&di->d64rxregs->ptr, ++ di->rcvptrbase + I2B(rxout, struct dma64desc)); ++ ++ return ring_empty; ++} ++ ++void dma_rxreclaim(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ struct sk_buff *p; ++ ++ DMA_TRACE(("%s: dma_rxreclaim\n", di->name)); ++ ++ while ((p = _dma_getnextrxp(di, true))) ++ brcmu_pkt_buf_free_skb(p); ++} ++ ++void dma_counterreset(struct dma_pub *pub) ++{ ++ /* reset all software counters */ ++ pub->rxgiants = 0; ++ pub->rxnobuf = 0; ++ pub->txnobuf = 0; ++} ++ ++/* get the address of the var in order to change later */ ++unsigned long dma_getvar(struct dma_pub *pub, const char *name) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ ++ if (!strcmp(name, "&txavail")) ++ return (unsigned long)&(di->dma.txavail); ++ return 0; ++} ++ ++/* 64-bit DMA functions */ ++ ++void dma_txinit(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ u32 control = D64_XC_XE; ++ ++ DMA_TRACE(("%s: dma_txinit\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ di->txin = di->txout = 0; ++ di->dma.txavail = di->ntxd - 1; ++ ++ /* clear tx descriptor ring */ ++ memset(di->txd64, '\0', (di->ntxd * sizeof(struct dma64desc))); ++ ++ /* DMA engine with out alignment requirement requires table to be inited ++ * before enabling the engine ++ */ ++ if (!di->aligndesc_4k) ++ _dma_ddtable_init(di, DMA_TX, di->txdpa); ++ ++ if ((di->dma.dmactrlflags & DMA_CTRL_PEN) == 0) ++ control |= D64_XC_PD; ++ OR_REG(&di->d64txregs->control, control); ++ ++ /* DMA engine with alignment requirement requires table to be inited ++ * before enabling the engine ++ */ ++ if (di->aligndesc_4k) ++ _dma_ddtable_init(di, DMA_TX, di->txdpa); ++} ++ ++void dma_txsuspend(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ ++ DMA_TRACE(("%s: dma_txsuspend\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ OR_REG(&di->d64txregs->control, D64_XC_SE); ++} ++ ++void dma_txresume(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ ++ DMA_TRACE(("%s: dma_txresume\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ AND_REG(&di->d64txregs->control, ~D64_XC_SE); ++} ++ ++bool dma_txsuspended(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ ++ return (di->ntxd == 0) || ++ ((R_REG(&di->d64txregs->control) & D64_XC_SE) == ++ D64_XC_SE); ++} ++ ++void dma_txreclaim(struct dma_pub *pub, enum txd_range range) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ struct sk_buff *p; ++ ++ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, ++ (range == DMA_RANGE_ALL) ? "all" : ++ ((range == ++ DMA_RANGE_TRANSMITTED) ? "transmitted" : ++ "transferred"))); ++ ++ if (di->txin == di->txout) ++ return; ++ ++ while ((p = dma_getnexttxp(pub, range))) { ++ /* For unframed data, we don't have any packets to free */ ++ if (!(di->dma.dmactrlflags & DMA_CTRL_UNFRAMED)) ++ brcmu_pkt_buf_free_skb(p); ++ } ++} ++ ++bool dma_txreset(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ u32 status; ++ ++ if (di->ntxd == 0) ++ return true; ++ ++ /* suspend tx DMA first */ ++ W_REG(&di->d64txregs->control, D64_XC_SE); ++ SPINWAIT(((status = ++ (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK)) ++ != D64_XS0_XS_DISABLED) && (status != D64_XS0_XS_IDLE) ++ && (status != D64_XS0_XS_STOPPED), 10000); ++ ++ W_REG(&di->d64txregs->control, 0); ++ SPINWAIT(((status = ++ (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK)) ++ != D64_XS0_XS_DISABLED), 10000); ++ ++ /* wait for the last transaction to complete */ ++ udelay(300); ++ ++ return status == D64_XS0_XS_DISABLED; ++} ++ ++bool dma_rxreset(struct dma_pub *pub) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ u32 status; ++ ++ if (di->nrxd == 0) ++ return true; ++ ++ W_REG(&di->d64rxregs->control, 0); ++ SPINWAIT(((status = ++ (R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK)) ++ != D64_RS0_RS_DISABLED), 10000); ++ ++ return status == D64_RS0_RS_DISABLED; ++} ++ ++/* ++ * !! tx entry routine ++ * WARNING: call must check the return value for error. ++ * the error(toss frames) could be fatal and cause many subsequent hard ++ * to debug problems ++ */ ++int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ struct sk_buff *p, *next; ++ unsigned char *data; ++ uint len; ++ u16 txout; ++ u32 flags = 0; ++ dma_addr_t pa; ++ ++ DMA_TRACE(("%s: dma_txfast\n", di->name)); ++ ++ txout = di->txout; ++ ++ /* ++ * Walk the chain of packet buffers ++ * allocating and initializing transmit descriptor entries. ++ */ ++ for (p = p0; p; p = next) { ++ data = p->data; ++ len = p->len; ++ next = p->next; ++ ++ /* return nonzero if out of tx descriptors */ ++ if (nexttxd(di, txout) == di->txin) ++ goto outoftxd; ++ ++ if (len == 0) ++ continue; ++ ++ /* get physical address of buffer start */ ++ pa = pci_map_single(di->pbus, data, len, PCI_DMA_TODEVICE); ++ ++ flags = 0; ++ if (p == p0) ++ flags |= D64_CTRL1_SOF; ++ ++ /* With a DMA segment list, Descriptor table is filled ++ * using the segment list instead of looping over ++ * buffers in multi-chain DMA. Therefore, EOF for SGLIST ++ * is when end of segment list is reached. ++ */ ++ if (next == NULL) ++ flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF); ++ if (txout == (di->ntxd - 1)) ++ flags |= D64_CTRL1_EOT; ++ ++ dma64_dd_upd(di, di->txd64, pa, txout, &flags, len); ++ ++ txout = nexttxd(di, txout); ++ } ++ ++ /* if last txd eof not set, fix it */ ++ if (!(flags & D64_CTRL1_EOF)) ++ di->txd64[prevtxd(di, txout)].ctrl1 = ++ cpu_to_le32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF); ++ ++ /* save the packet */ ++ di->txp[prevtxd(di, txout)] = p0; ++ ++ /* bump the tx descriptor index */ ++ di->txout = txout; ++ ++ /* kick the chip */ ++ if (commit) ++ W_REG(&di->d64txregs->ptr, ++ di->xmtptrbase + I2B(txout, struct dma64desc)); ++ ++ /* tx flow control */ ++ di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1; ++ ++ return 0; ++ ++ outoftxd: ++ DMA_ERROR(("%s: dma_txfast: out of txds !!!\n", di->name)); ++ brcmu_pkt_buf_free_skb(p0); ++ di->dma.txavail = 0; ++ di->dma.txnobuf++; ++ return -1; ++} ++ ++/* ++ * Reclaim next completed txd (txds if using chained buffers) in the range ++ * specified and return associated packet. ++ * If range is DMA_RANGE_TRANSMITTED, reclaim descriptors that have be ++ * transmitted as noted by the hardware "CurrDescr" pointer. ++ * If range is DMA_RANGE_TRANSFERED, reclaim descriptors that have be ++ * transferred by the DMA as noted by the hardware "ActiveDescr" pointer. ++ * If range is DMA_RANGE_ALL, reclaim all txd(s) posted to the ring and ++ * return associated packet regardless of the value of hardware pointers. ++ */ ++struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range) ++{ ++ struct dma_info *di = (struct dma_info *)pub; ++ u16 start, end, i; ++ u16 active_desc; ++ struct sk_buff *txp; ++ ++ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, ++ (range == DMA_RANGE_ALL) ? "all" : ++ ((range == ++ DMA_RANGE_TRANSMITTED) ? "transmitted" : ++ "transferred"))); ++ ++ if (di->ntxd == 0) ++ return NULL; ++ ++ txp = NULL; ++ ++ start = di->txin; ++ if (range == DMA_RANGE_ALL) ++ end = di->txout; ++ else { ++ struct dma64regs __iomem *dregs = di->d64txregs; ++ ++ end = (u16) (B2I(((R_REG(&dregs->status0) & ++ D64_XS0_CD_MASK) - ++ di->xmtptrbase) & D64_XS0_CD_MASK, ++ struct dma64desc)); ++ ++ if (range == DMA_RANGE_TRANSFERED) { ++ active_desc = ++ (u16) (R_REG(&dregs->status1) & ++ D64_XS1_AD_MASK); ++ active_desc = ++ (active_desc - di->xmtptrbase) & D64_XS0_CD_MASK; ++ active_desc = B2I(active_desc, struct dma64desc); ++ if (end != active_desc) ++ end = prevtxd(di, active_desc); ++ } ++ } ++ ++ if ((start == 0) && (end > di->txout)) ++ goto bogus; ++ ++ for (i = start; i != end && !txp; i = nexttxd(di, i)) { ++ dma_addr_t pa; ++ uint size; ++ ++ pa = le32_to_cpu(di->txd64[i].addrlow) - di->dataoffsetlow; ++ ++ size = ++ (le32_to_cpu(di->txd64[i].ctrl2) & ++ D64_CTRL2_BC_MASK); ++ ++ di->txd64[i].addrlow = cpu_to_le32(0xdeadbeef); ++ di->txd64[i].addrhigh = cpu_to_le32(0xdeadbeef); ++ ++ txp = di->txp[i]; ++ di->txp[i] = NULL; ++ ++ pci_unmap_single(di->pbus, pa, size, PCI_DMA_TODEVICE); ++ } ++ ++ di->txin = i; ++ ++ /* tx flow control */ ++ di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) - 1; ++ ++ return txp; ++ ++ bogus: ++ DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d " ++ "force %d\n", start, end, di->txout, forceall)); ++ return NULL; ++} ++ ++/* ++ * Mac80211 initiated actions sometimes require packets in the DMA queue to be ++ * modified. The modified portion of the packet is not under control of the DMA ++ * engine. This function calls a caller-supplied function for each packet in ++ * the caller specified dma chain. ++ */ ++void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc) ++ (void *pkt, void *arg_a), void *arg_a) ++{ ++ struct dma_info *di = (struct dma_info *) dmah; ++ uint i = di->txin; ++ uint end = di->txout; ++ struct sk_buff *skb; ++ struct ieee80211_tx_info *tx_info; ++ ++ while (i != end) { ++ skb = (struct sk_buff *)di->txp[i]; ++ if (skb != NULL) { ++ tx_info = (struct ieee80211_tx_info *)skb->cb; ++ (callback_fnc)(tx_info, arg_a); ++ } ++ i = nexttxd(di, i); ++ } ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.h.orig 2011-11-09 13:46:58.244800645 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/dma.h 2011-11-09 13:47:16.997566205 -0500 +@@ -0,0 +1,120 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_DMA_H_ ++#define _BRCM_DMA_H_ ++ ++#include ++#include "types.h" /* forward structure declarations */ ++ ++/* map/unmap direction */ ++#define DMA_TX 1 /* TX direction for DMA */ ++#define DMA_RX 2 /* RX direction for DMA */ ++ ++/* DMA structure: ++ * support two DMA engines: 32 bits address or 64 bit addressing ++ * basic DMA register set is per channel(transmit or receive) ++ * a pair of channels is defined for convenience ++ */ ++ ++/* 32 bits addressing */ ++ ++struct dma32diag { /* diag access */ ++ u32 fifoaddr; /* diag address */ ++ u32 fifodatalow; /* low 32bits of data */ ++ u32 fifodatahigh; /* high 32bits of data */ ++ u32 pad; /* reserved */ ++}; ++ ++/* 64 bits addressing */ ++ ++/* dma registers per channel(xmt or rcv) */ ++struct dma64regs { ++ u32 control; /* enable, et al */ ++ u32 ptr; /* last descriptor posted to chip */ ++ u32 addrlow; /* desc ring base address low 32-bits (8K aligned) */ ++ u32 addrhigh; /* desc ring base address bits 63:32 (8K aligned) */ ++ u32 status0; /* current descriptor, xmt state */ ++ u32 status1; /* active descriptor, xmt error */ ++}; ++ ++/* range param for dma_getnexttxp() and dma_txreclaim */ ++enum txd_range { ++ DMA_RANGE_ALL = 1, ++ DMA_RANGE_TRANSMITTED, ++ DMA_RANGE_TRANSFERED ++}; ++ ++/* ++ * Exported data structure (read-only) ++ */ ++/* export structure */ ++struct dma_pub { ++ uint txavail; /* # free tx descriptors */ ++ uint dmactrlflags; /* dma control flags */ ++ ++ /* rx error counters */ ++ uint rxgiants; /* rx giant frames */ ++ uint rxnobuf; /* rx out of dma descriptors */ ++ /* tx error counters */ ++ uint txnobuf; /* tx out of dma descriptors */ ++}; ++ ++extern struct dma_pub *dma_attach(char *name, struct si_pub *sih, ++ void __iomem *dmaregstx, void __iomem *dmaregsrx, ++ uint ntxd, uint nrxd, ++ uint rxbufsize, int rxextheadroom, ++ uint nrxpost, uint rxoffset, uint *msg_level); ++ ++void dma_rxinit(struct dma_pub *pub); ++struct sk_buff *dma_rx(struct dma_pub *pub); ++bool dma_rxfill(struct dma_pub *pub); ++bool dma_rxreset(struct dma_pub *pub); ++bool dma_txreset(struct dma_pub *pub); ++void dma_txinit(struct dma_pub *pub); ++int dma_txfast(struct dma_pub *pub, struct sk_buff *p0, bool commit); ++void dma_txsuspend(struct dma_pub *pub); ++bool dma_txsuspended(struct dma_pub *pub); ++void dma_txresume(struct dma_pub *pub); ++void dma_txreclaim(struct dma_pub *pub, enum txd_range range); ++void dma_rxreclaim(struct dma_pub *pub); ++void dma_detach(struct dma_pub *pub); ++unsigned long dma_getvar(struct dma_pub *pub, const char *name); ++struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range); ++void dma_counterreset(struct dma_pub *pub); ++ ++void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc) ++ (void *pkt, void *arg_a), void *arg_a); ++ ++/* ++ * DMA(Bug) on bcm47xx chips seems to declare that the packet is ready, but ++ * the packet length is not updated yet (by DMA) on the expected time. ++ * Workaround is to hold processor till DMA updates the length, and stay off ++ * the bus to allow DMA update the length in buffer ++ */ ++static inline void dma_spin_for_len(uint len, struct sk_buff *head) ++{ ++#if defined(CONFIG_BCM47XX) ++ if (!len) { ++ while (!(len = *(u16 *) KSEG1ADDR(head->data))) ++ udelay(1); ++ ++ *(u16 *) (head->data) = cpu_to_le16((u16) len); ++ } ++#endif /* defined(CONFIG_BCM47XX) */ ++} ++ ++#endif /* _BRCM_DMA_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c.orig 2011-11-09 13:46:58.245800633 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c 2011-11-09 13:47:16.998566192 -0500 +@@ -0,0 +1,1697 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#define __UNDEF_NO_VERSION__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "nicpci.h" ++#include "phy/phy_int.h" ++#include "d11.h" ++#include "channel.h" ++#include "scb.h" ++#include "pub.h" ++#include "ucode_loader.h" ++#include "mac80211_if.h" ++#include "main.h" ++ ++#define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ ++ ++/* Flags we support */ ++#define MAC_FILTERS (FIF_PROMISC_IN_BSS | \ ++ FIF_ALLMULTI | \ ++ FIF_FCSFAIL | \ ++ FIF_PLCPFAIL | \ ++ FIF_CONTROL | \ ++ FIF_OTHER_BSS | \ ++ FIF_BCN_PRBRESP_PROMISC) ++ ++#define CHAN2GHZ(channel, freqency, chflags) { \ ++ .band = IEEE80211_BAND_2GHZ, \ ++ .center_freq = (freqency), \ ++ .hw_value = (channel), \ ++ .flags = chflags, \ ++ .max_antenna_gain = 0, \ ++ .max_power = 19, \ ++} ++ ++#define CHAN5GHZ(channel, chflags) { \ ++ .band = IEEE80211_BAND_5GHZ, \ ++ .center_freq = 5000 + 5*(channel), \ ++ .hw_value = (channel), \ ++ .flags = chflags, \ ++ .max_antenna_gain = 0, \ ++ .max_power = 21, \ ++} ++ ++#define RATE(rate100m, _flags) { \ ++ .bitrate = (rate100m), \ ++ .flags = (_flags), \ ++ .hw_value = (rate100m / 5), \ ++} ++ ++struct firmware_hdr { ++ __le32 offset; ++ __le32 len; ++ __le32 idx; ++}; ++ ++static const char * const brcms_firmwares[MAX_FW_IMAGES] = { ++ "brcm/bcm43xx", ++ NULL ++}; ++ ++static int n_adapters_found; ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver."); ++MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards"); ++MODULE_LICENSE("Dual BSD/GPL"); ++ ++/* recognized PCI IDs */ ++static DEFINE_PCI_DEVICE_TABLE(brcms_pci_id_table) = { ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, /* 43225 2G */ ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, /* 43224 DUAL */ ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, /* 4313 DUAL */ ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, /* 43224 Ven */ ++ {0} ++}; ++ ++MODULE_DEVICE_TABLE(pci, brcms_pci_id_table); ++ ++#ifdef BCMDBG ++static int msglevel = 0xdeadbeef; ++module_param(msglevel, int, 0); ++#endif /* BCMDBG */ ++ ++static struct ieee80211_channel brcms_2ghz_chantable[] = { ++ CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN2GHZ(2, 2417, IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN2GHZ(3, 2422, IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN2GHZ(4, 2427, IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN2GHZ(5, 2432, 0), ++ CHAN2GHZ(6, 2437, 0), ++ CHAN2GHZ(7, 2442, 0), ++ CHAN2GHZ(8, 2447, IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN2GHZ(9, 2452, IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN2GHZ(12, 2467, ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN2GHZ(13, 2472, ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN2GHZ(14, 2484, ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) ++}; ++ ++static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = { ++ /* UNII-1 */ ++ CHAN5GHZ(36, IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(40, IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(44, IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS), ++ /* UNII-2 */ ++ CHAN5GHZ(52, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(56, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(60, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(64, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), ++ /* MID */ ++ CHAN5GHZ(100, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(104, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(108, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(112, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(116, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(120, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(124, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(128, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(132, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(136, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(140, ++ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS | ++ IEEE80211_CHAN_NO_HT40MINUS), ++ /* UNII-3 */ ++ CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(153, IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(157, IEEE80211_CHAN_NO_HT40MINUS), ++ CHAN5GHZ(161, IEEE80211_CHAN_NO_HT40PLUS), ++ CHAN5GHZ(165, IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) ++}; ++ ++/* ++ * The rate table is used for both 2.4G and 5G rates. The ++ * latter being a subset as it does not support CCK rates. ++ */ ++static struct ieee80211_rate legacy_ratetable[] = { ++ RATE(10, 0), ++ RATE(20, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATE(55, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATE(110, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATE(60, 0), ++ RATE(90, 0), ++ RATE(120, 0), ++ RATE(180, 0), ++ RATE(240, 0), ++ RATE(360, 0), ++ RATE(480, 0), ++ RATE(540, 0), ++}; ++ ++static const struct ieee80211_supported_band brcms_band_2GHz_nphy_template = { ++ .band = IEEE80211_BAND_2GHZ, ++ .channels = brcms_2ghz_chantable, ++ .n_channels = ARRAY_SIZE(brcms_2ghz_chantable), ++ .bitrates = legacy_ratetable, ++ .n_bitrates = ARRAY_SIZE(legacy_ratetable), ++ .ht_cap = { ++ /* from include/linux/ieee80211.h */ ++ .cap = IEEE80211_HT_CAP_GRN_FLD | ++ IEEE80211_HT_CAP_SGI_20 | ++ IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT, ++ .ht_supported = true, ++ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, ++ .ampdu_density = AMPDU_DEF_MPDU_DENSITY, ++ .mcs = { ++ /* placeholders for now */ ++ .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}, ++ .rx_highest = cpu_to_le16(500), ++ .tx_params = IEEE80211_HT_MCS_TX_DEFINED} ++ } ++}; ++ ++static const struct ieee80211_supported_band brcms_band_5GHz_nphy_template = { ++ .band = IEEE80211_BAND_5GHZ, ++ .channels = brcms_5ghz_nphy_chantable, ++ .n_channels = ARRAY_SIZE(brcms_5ghz_nphy_chantable), ++ .bitrates = legacy_ratetable + BRCMS_LEGACY_5G_RATE_OFFSET, ++ .n_bitrates = ARRAY_SIZE(legacy_ratetable) - ++ BRCMS_LEGACY_5G_RATE_OFFSET, ++ .ht_cap = { ++ .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | ++ IEEE80211_HT_CAP_SGI_40 | ++ IEEE80211_HT_CAP_40MHZ_INTOLERANT, /* No 40 mhz yet */ ++ .ht_supported = true, ++ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, ++ .ampdu_density = AMPDU_DEF_MPDU_DENSITY, ++ .mcs = { ++ /* placeholders for now */ ++ .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}, ++ .rx_highest = cpu_to_le16(500), ++ .tx_params = IEEE80211_HT_MCS_TX_DEFINED} ++ } ++}; ++ ++/* flags the given rate in rateset as requested */ ++static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, bool is_br) ++{ ++ u32 i; ++ ++ for (i = 0; i < rs->count; i++) { ++ if (rate != (rs->rates[i] & 0x7f)) ++ continue; ++ ++ if (is_br) ++ rs->rates[i] |= BRCMS_RATE_FLAG; ++ else ++ rs->rates[i] &= BRCMS_RATE_MASK; ++ return; ++ } ++} ++ ++static void brcms_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb) ++{ ++ struct brcms_info *wl = hw->priv; ++ ++ spin_lock_bh(&wl->lock); ++ if (!wl->pub->up) { ++ wiphy_err(wl->wiphy, "ops->tx called while down\n"); ++ kfree_skb(skb); ++ goto done; ++ } ++ brcms_c_sendpkt_mac80211(wl->wlc, skb, hw); ++ done: ++ spin_unlock_bh(&wl->lock); ++} ++ ++static int brcms_ops_start(struct ieee80211_hw *hw) ++{ ++ struct brcms_info *wl = hw->priv; ++ bool blocked; ++ ++ ieee80211_wake_queues(hw); ++ spin_lock_bh(&wl->lock); ++ blocked = brcms_rfkill_set_hw_state(wl); ++ spin_unlock_bh(&wl->lock); ++ if (!blocked) ++ wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); ++ ++ return 0; ++} ++ ++static void brcms_ops_stop(struct ieee80211_hw *hw) ++{ ++ ieee80211_stop_queues(hw); ++} ++ ++static int ++brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ++{ ++ struct brcms_info *wl; ++ int err; ++ ++ /* Just STA for now */ ++ if (vif->type != NL80211_IFTYPE_AP && ++ vif->type != NL80211_IFTYPE_MESH_POINT && ++ vif->type != NL80211_IFTYPE_STATION && ++ vif->type != NL80211_IFTYPE_WDS && ++ vif->type != NL80211_IFTYPE_ADHOC) { ++ wiphy_err(hw->wiphy, "%s: Attempt to add type %d, only" ++ " STA for now\n", __func__, vif->type); ++ return -EOPNOTSUPP; ++ } ++ ++ wl = hw->priv; ++ spin_lock_bh(&wl->lock); ++ if (!wl->pub->up) ++ err = brcms_up(wl); ++ else ++ err = -ENODEV; ++ spin_unlock_bh(&wl->lock); ++ ++ if (err != 0) ++ wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__, ++ err); ++ ++ return err; ++} ++ ++static void ++brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ++{ ++ struct brcms_info *wl; ++ ++ wl = hw->priv; ++ ++ /* put driver in down state */ ++ spin_lock_bh(&wl->lock); ++ brcms_down(wl); ++ spin_unlock_bh(&wl->lock); ++} ++ ++static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed) ++{ ++ struct ieee80211_conf *conf = &hw->conf; ++ struct brcms_info *wl = hw->priv; ++ int err = 0; ++ int new_int; ++ struct wiphy *wiphy = hw->wiphy; ++ ++ spin_lock_bh(&wl->lock); ++ if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { ++ brcms_c_set_beacon_listen_interval(wl->wlc, ++ conf->listen_interval); ++ } ++ if (changed & IEEE80211_CONF_CHANGE_MONITOR) ++ wiphy_err(wiphy, "%s: change monitor mode: %s (implement)\n", ++ __func__, conf->flags & IEEE80211_CONF_MONITOR ? ++ "true" : "false"); ++ if (changed & IEEE80211_CONF_CHANGE_PS) ++ wiphy_err(wiphy, "%s: change power-save mode: %s (implement)\n", ++ __func__, conf->flags & IEEE80211_CONF_PS ? ++ "true" : "false"); ++ ++ if (changed & IEEE80211_CONF_CHANGE_POWER) { ++ err = brcms_c_set_tx_power(wl->wlc, conf->power_level); ++ if (err < 0) { ++ wiphy_err(wiphy, "%s: Error setting power_level\n", ++ __func__); ++ goto config_out; ++ } ++ new_int = brcms_c_get_tx_power(wl->wlc); ++ if (new_int != conf->power_level) ++ wiphy_err(wiphy, "%s: Power level req != actual, %d %d" ++ "\n", __func__, conf->power_level, ++ new_int); ++ } ++ if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { ++ if (conf->channel_type == NL80211_CHAN_HT20 || ++ conf->channel_type == NL80211_CHAN_NO_HT) ++ err = brcms_c_set_channel(wl->wlc, ++ conf->channel->hw_value); ++ else ++ err = -ENOTSUPP; ++ } ++ if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) ++ err = brcms_c_set_rate_limit(wl->wlc, ++ conf->short_frame_max_tx_count, ++ conf->long_frame_max_tx_count); ++ ++ config_out: ++ spin_unlock_bh(&wl->lock); ++ return err; ++} ++ ++static void ++brcms_ops_bss_info_changed(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_bss_conf *info, u32 changed) ++{ ++ struct brcms_info *wl = hw->priv; ++ struct wiphy *wiphy = hw->wiphy; ++ ++ if (changed & BSS_CHANGED_ASSOC) { ++ /* association status changed (associated/disassociated) ++ * also implies a change in the AID. ++ */ ++ wiphy_err(wiphy, "%s: %s: %sassociated\n", KBUILD_MODNAME, ++ __func__, info->assoc ? "" : "dis"); ++ spin_lock_bh(&wl->lock); ++ brcms_c_associate_upd(wl->wlc, info->assoc); ++ spin_unlock_bh(&wl->lock); ++ } ++ if (changed & BSS_CHANGED_ERP_SLOT) { ++ s8 val; ++ ++ /* slot timing changed */ ++ if (info->use_short_slot) ++ val = 1; ++ else ++ val = 0; ++ spin_lock_bh(&wl->lock); ++ brcms_c_set_shortslot_override(wl->wlc, val); ++ spin_unlock_bh(&wl->lock); ++ } ++ ++ if (changed & BSS_CHANGED_HT) { ++ /* 802.11n parameters changed */ ++ u16 mode = info->ht_operation_mode; ++ ++ spin_lock_bh(&wl->lock); ++ brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_CFG, ++ mode & IEEE80211_HT_OP_MODE_PROTECTION); ++ brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_NONGF, ++ mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); ++ brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_OBSS, ++ mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT); ++ spin_unlock_bh(&wl->lock); ++ } ++ if (changed & BSS_CHANGED_BASIC_RATES) { ++ struct ieee80211_supported_band *bi; ++ u32 br_mask, i; ++ u16 rate; ++ struct brcm_rateset rs; ++ int error; ++ ++ /* retrieve the current rates */ ++ spin_lock_bh(&wl->lock); ++ brcms_c_get_current_rateset(wl->wlc, &rs); ++ spin_unlock_bh(&wl->lock); ++ ++ br_mask = info->basic_rates; ++ bi = hw->wiphy->bands[brcms_c_get_curband(wl->wlc)]; ++ for (i = 0; i < bi->n_bitrates; i++) { ++ /* convert to internal rate value */ ++ rate = (bi->bitrates[i].bitrate << 1) / 10; ++ ++ /* set/clear basic rate flag */ ++ brcms_set_basic_rate(&rs, rate, br_mask & 1); ++ br_mask >>= 1; ++ } ++ ++ /* update the rate set */ ++ spin_lock_bh(&wl->lock); ++ error = brcms_c_set_rateset(wl->wlc, &rs); ++ spin_unlock_bh(&wl->lock); ++ if (error) ++ wiphy_err(wiphy, "changing basic rates failed: %d\n", ++ error); ++ } ++ if (changed & BSS_CHANGED_BEACON_INT) { ++ /* Beacon interval changed */ ++ spin_lock_bh(&wl->lock); ++ brcms_c_set_beacon_period(wl->wlc, info->beacon_int); ++ spin_unlock_bh(&wl->lock); ++ } ++ if (changed & BSS_CHANGED_BSSID) { ++ /* BSSID changed, for whatever reason (IBSS and managed mode) */ ++ spin_lock_bh(&wl->lock); ++ brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid); ++ spin_unlock_bh(&wl->lock); ++ } ++ if (changed & BSS_CHANGED_BEACON) ++ /* Beacon data changed, retrieve new beacon (beaconing modes) */ ++ wiphy_err(wiphy, "%s: beacon changed\n", __func__); ++ ++ if (changed & BSS_CHANGED_BEACON_ENABLED) { ++ /* Beaconing should be enabled/disabled (beaconing modes) */ ++ wiphy_err(wiphy, "%s: Beacon enabled: %s\n", __func__, ++ info->enable_beacon ? "true" : "false"); ++ } ++ ++ if (changed & BSS_CHANGED_CQM) { ++ /* Connection quality monitor config changed */ ++ wiphy_err(wiphy, "%s: cqm change: threshold %d, hys %d " ++ " (implement)\n", __func__, info->cqm_rssi_thold, ++ info->cqm_rssi_hyst); ++ } ++ ++ if (changed & BSS_CHANGED_IBSS) { ++ /* IBSS join status changed */ ++ wiphy_err(wiphy, "%s: IBSS joined: %s (implement)\n", __func__, ++ info->ibss_joined ? "true" : "false"); ++ } ++ ++ if (changed & BSS_CHANGED_ARP_FILTER) { ++ /* Hardware ARP filter address list or state changed */ ++ wiphy_err(wiphy, "%s: arp filtering: enabled %s, count %d" ++ " (implement)\n", __func__, info->arp_filter_enabled ? ++ "true" : "false", info->arp_addr_cnt); ++ } ++ ++ if (changed & BSS_CHANGED_QOS) { ++ /* ++ * QoS for this association was enabled/disabled. ++ * Note that it is only ever disabled for station mode. ++ */ ++ wiphy_err(wiphy, "%s: qos enabled: %s (implement)\n", __func__, ++ info->qos ? "true" : "false"); ++ } ++ return; ++} ++ ++static void ++brcms_ops_configure_filter(struct ieee80211_hw *hw, ++ unsigned int changed_flags, ++ unsigned int *total_flags, u64 multicast) ++{ ++ struct brcms_info *wl = hw->priv; ++ struct wiphy *wiphy = hw->wiphy; ++ ++ changed_flags &= MAC_FILTERS; ++ *total_flags &= MAC_FILTERS; ++ if (changed_flags & FIF_PROMISC_IN_BSS) ++ wiphy_err(wiphy, "FIF_PROMISC_IN_BSS\n"); ++ if (changed_flags & FIF_ALLMULTI) ++ wiphy_err(wiphy, "FIF_ALLMULTI\n"); ++ if (changed_flags & FIF_FCSFAIL) ++ wiphy_err(wiphy, "FIF_FCSFAIL\n"); ++ if (changed_flags & FIF_PLCPFAIL) ++ wiphy_err(wiphy, "FIF_PLCPFAIL\n"); ++ if (changed_flags & FIF_CONTROL) ++ wiphy_err(wiphy, "FIF_CONTROL\n"); ++ if (changed_flags & FIF_OTHER_BSS) ++ wiphy_err(wiphy, "FIF_OTHER_BSS\n"); ++ if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { ++ spin_lock_bh(&wl->lock); ++ if (*total_flags & FIF_BCN_PRBRESP_PROMISC) { ++ wl->pub->mac80211_state |= MAC80211_PROMISC_BCNS; ++ brcms_c_mac_bcn_promisc_change(wl->wlc, 1); ++ } else { ++ brcms_c_mac_bcn_promisc_change(wl->wlc, 0); ++ wl->pub->mac80211_state &= ~MAC80211_PROMISC_BCNS; ++ } ++ spin_unlock_bh(&wl->lock); ++ } ++ return; ++} ++ ++static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw) ++{ ++ struct brcms_info *wl = hw->priv; ++ spin_lock_bh(&wl->lock); ++ brcms_c_scan_start(wl->wlc); ++ spin_unlock_bh(&wl->lock); ++ return; ++} ++ ++static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw) ++{ ++ struct brcms_info *wl = hw->priv; ++ spin_lock_bh(&wl->lock); ++ brcms_c_scan_stop(wl->wlc); ++ spin_unlock_bh(&wl->lock); ++ return; ++} ++ ++static int ++brcms_ops_conf_tx(struct ieee80211_hw *hw, u16 queue, ++ const struct ieee80211_tx_queue_params *params) ++{ ++ struct brcms_info *wl = hw->priv; ++ ++ spin_lock_bh(&wl->lock); ++ brcms_c_wme_setparams(wl->wlc, queue, params, true); ++ spin_unlock_bh(&wl->lock); ++ ++ return 0; ++} ++ ++static int ++brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta) ++{ ++ struct brcms_info *wl = hw->priv; ++ struct scb *scb = &wl->wlc->pri_scb; ++ ++ brcms_c_init_scb(scb); ++ ++ wl->pub->global_ampdu = &(scb->scb_ampdu); ++ wl->pub->global_ampdu->scb = scb; ++ wl->pub->global_ampdu->max_pdu = 16; ++ ++ sta->ht_cap.ht_supported = true; ++ sta->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; ++ sta->ht_cap.ampdu_density = AMPDU_DEF_MPDU_DENSITY; ++ sta->ht_cap.cap = IEEE80211_HT_CAP_GRN_FLD | ++ IEEE80211_HT_CAP_SGI_20 | ++ IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT; ++ ++ /* ++ * minstrel_ht initiates addBA on our behalf by calling ++ * ieee80211_start_tx_ba_session() ++ */ ++ return 0; ++} ++ ++static int ++brcms_ops_ampdu_action(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ enum ieee80211_ampdu_mlme_action action, ++ struct ieee80211_sta *sta, u16 tid, u16 *ssn, ++ u8 buf_size) ++{ ++ struct brcms_info *wl = hw->priv; ++ struct scb *scb = &wl->wlc->pri_scb; ++ int status; ++ ++ if (WARN_ON(scb->magic != SCB_MAGIC)) ++ return -EIDRM; ++ switch (action) { ++ case IEEE80211_AMPDU_RX_START: ++ break; ++ case IEEE80211_AMPDU_RX_STOP: ++ break; ++ case IEEE80211_AMPDU_TX_START: ++ spin_lock_bh(&wl->lock); ++ status = brcms_c_aggregatable(wl->wlc, tid); ++ spin_unlock_bh(&wl->lock); ++ if (!status) { ++ wiphy_err(wl->wiphy, "START: tid %d is not agg\'able\n", ++ tid); ++ return -EINVAL; ++ } ++ ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); ++ break; ++ ++ case IEEE80211_AMPDU_TX_STOP: ++ spin_lock_bh(&wl->lock); ++ brcms_c_ampdu_flush(wl->wlc, sta, tid); ++ spin_unlock_bh(&wl->lock); ++ ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); ++ break; ++ case IEEE80211_AMPDU_TX_OPERATIONAL: ++ /* ++ * BA window size from ADDBA response ('buf_size') defines how ++ * many outstanding MPDUs are allowed for the BA stream by ++ * recipient and traffic class. 'ampdu_factor' gives maximum ++ * AMPDU size. ++ */ ++ spin_lock_bh(&wl->lock); ++ brcms_c_ampdu_tx_operational(wl->wlc, tid, buf_size, ++ (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + ++ sta->ht_cap.ampdu_factor)) - 1); ++ spin_unlock_bh(&wl->lock); ++ /* Power save wakeup */ ++ break; ++ default: ++ wiphy_err(wl->wiphy, "%s: Invalid command, ignoring\n", ++ __func__); ++ } ++ ++ return 0; ++} ++ ++static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw) ++{ ++ struct brcms_info *wl = hw->priv; ++ bool blocked; ++ ++ spin_lock_bh(&wl->lock); ++ blocked = brcms_c_check_radio_disabled(wl->wlc); ++ spin_unlock_bh(&wl->lock); ++ ++ wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked); ++} ++ ++static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop) ++{ ++ struct brcms_info *wl = hw->priv; ++ ++ no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false"); ++ ++ /* wait for packet queue and dma fifos to run empty */ ++ spin_lock_bh(&wl->lock); ++ brcms_c_wait_for_tx_completion(wl->wlc, drop); ++ spin_unlock_bh(&wl->lock); ++} ++ ++static const struct ieee80211_ops brcms_ops = { ++ .tx = brcms_ops_tx, ++ .start = brcms_ops_start, ++ .stop = brcms_ops_stop, ++ .add_interface = brcms_ops_add_interface, ++ .remove_interface = brcms_ops_remove_interface, ++ .config = brcms_ops_config, ++ .bss_info_changed = brcms_ops_bss_info_changed, ++ .configure_filter = brcms_ops_configure_filter, ++ .sw_scan_start = brcms_ops_sw_scan_start, ++ .sw_scan_complete = brcms_ops_sw_scan_complete, ++ .conf_tx = brcms_ops_conf_tx, ++ .sta_add = brcms_ops_sta_add, ++ .ampdu_action = brcms_ops_ampdu_action, ++ .rfkill_poll = brcms_ops_rfkill_poll, ++ .flush = brcms_ops_flush, ++}; ++ ++/* ++ * is called in brcms_pci_probe() context, therefore no locking required. ++ */ ++static int brcms_set_hint(struct brcms_info *wl, char *abbrev) ++{ ++ return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev); ++} ++ ++void brcms_dpc(unsigned long data) ++{ ++ struct brcms_info *wl; ++ ++ wl = (struct brcms_info *) data; ++ ++ spin_lock_bh(&wl->lock); ++ ++ /* call the common second level interrupt handler */ ++ if (wl->pub->up) { ++ if (wl->resched) { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wl->isr_lock, flags); ++ brcms_c_intrsupd(wl->wlc); ++ spin_unlock_irqrestore(&wl->isr_lock, flags); ++ } ++ ++ wl->resched = brcms_c_dpc(wl->wlc, true); ++ } ++ ++ /* brcms_c_dpc() may bring the driver down */ ++ if (!wl->pub->up) ++ goto done; ++ ++ /* re-schedule dpc */ ++ if (wl->resched) ++ tasklet_schedule(&wl->tasklet); ++ else ++ /* re-enable interrupts */ ++ brcms_intrson(wl); ++ ++ done: ++ spin_unlock_bh(&wl->lock); ++} ++ ++/* ++ * Precondition: Since this function is called in brcms_pci_probe() context, ++ * no locking is required. ++ */ ++static int brcms_request_fw(struct brcms_info *wl, struct pci_dev *pdev) ++{ ++ int status; ++ struct device *device = &pdev->dev; ++ char fw_name[100]; ++ int i; ++ ++ memset(&wl->fw, 0, sizeof(struct brcms_firmware)); ++ for (i = 0; i < MAX_FW_IMAGES; i++) { ++ if (brcms_firmwares[i] == NULL) ++ break; ++ sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i], ++ UCODE_LOADER_API_VER); ++ status = request_firmware(&wl->fw.fw_bin[i], fw_name, device); ++ if (status) { ++ wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n", ++ KBUILD_MODNAME, fw_name); ++ return status; ++ } ++ sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i], ++ UCODE_LOADER_API_VER); ++ status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device); ++ if (status) { ++ wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n", ++ KBUILD_MODNAME, fw_name); ++ return status; ++ } ++ wl->fw.hdr_num_entries[i] = ++ wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr)); ++ } ++ wl->fw.fw_cnt = i; ++ return brcms_ucode_data_init(wl, &wl->ucode); ++} ++ ++/* ++ * Precondition: Since this function is called in brcms_pci_probe() context, ++ * no locking is required. ++ */ ++static void brcms_release_fw(struct brcms_info *wl) ++{ ++ int i; ++ for (i = 0; i < MAX_FW_IMAGES; i++) { ++ release_firmware(wl->fw.fw_bin[i]); ++ release_firmware(wl->fw.fw_hdr[i]); ++ } ++} ++ ++/** ++ * This function frees the WL per-device resources. ++ * ++ * This function frees resources owned by the WL device pointed to ++ * by the wl parameter. ++ * ++ * precondition: can both be called locked and unlocked ++ * ++ */ ++static void brcms_free(struct brcms_info *wl) ++{ ++ struct brcms_timer *t, *next; ++ ++ /* free ucode data */ ++ if (wl->fw.fw_cnt) ++ brcms_ucode_data_free(&wl->ucode); ++ if (wl->irq) ++ free_irq(wl->irq, wl); ++ ++ /* kill dpc */ ++ tasklet_kill(&wl->tasklet); ++ ++ if (wl->pub) ++ brcms_c_module_unregister(wl->pub, "linux", wl); ++ ++ /* free common resources */ ++ if (wl->wlc) { ++ brcms_c_detach(wl->wlc); ++ wl->wlc = NULL; ++ wl->pub = NULL; ++ } ++ ++ /* virtual interface deletion is deferred so we cannot spinwait */ ++ ++ /* wait for all pending callbacks to complete */ ++ while (atomic_read(&wl->callbacks) > 0) ++ schedule(); ++ ++ /* free timers */ ++ for (t = wl->timers; t; t = next) { ++ next = t->next; ++#ifdef BCMDBG ++ kfree(t->name); ++#endif ++ kfree(t); ++ } ++ ++ /* ++ * unregister_netdev() calls get_stats() which may read chip ++ * registers so we cannot unmap the chip registers until ++ * after calling unregister_netdev() . ++ */ ++ if (wl->regsva) ++ iounmap(wl->regsva); ++ ++ wl->regsva = NULL; ++} ++ ++/* ++* called from both kernel as from this kernel module. ++* precondition: perimeter lock is not acquired. ++*/ ++static void brcms_remove(struct pci_dev *pdev) ++{ ++ struct brcms_info *wl; ++ struct ieee80211_hw *hw; ++ int status; ++ ++ hw = pci_get_drvdata(pdev); ++ wl = hw->priv; ++ if (!wl) { ++ pr_err("wl: brcms_remove: pci_get_drvdata failed\n"); ++ return; ++ } ++ ++ spin_lock_bh(&wl->lock); ++ status = brcms_c_chipmatch(pdev->vendor, pdev->device); ++ spin_unlock_bh(&wl->lock); ++ if (!status) { ++ wiphy_err(wl->wiphy, "wl: brcms_remove: chipmatch " ++ "failed\n"); ++ return; ++ } ++ if (wl->wlc) { ++ wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); ++ wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); ++ ieee80211_unregister_hw(hw); ++ spin_lock_bh(&wl->lock); ++ brcms_down(wl); ++ spin_unlock_bh(&wl->lock); ++ } ++ pci_disable_device(pdev); ++ ++ brcms_free(wl); ++ ++ pci_set_drvdata(pdev, NULL); ++ ieee80211_free_hw(hw); ++} ++ ++static irqreturn_t brcms_isr(int irq, void *dev_id) ++{ ++ struct brcms_info *wl; ++ bool ours, wantdpc; ++ ++ wl = (struct brcms_info *) dev_id; ++ ++ spin_lock(&wl->isr_lock); ++ ++ /* call common first level interrupt handler */ ++ ours = brcms_c_isr(wl->wlc, &wantdpc); ++ if (ours) { ++ /* if more to do... */ ++ if (wantdpc) { ++ ++ /* ...and call the second level interrupt handler */ ++ /* schedule dpc */ ++ tasklet_schedule(&wl->tasklet); ++ } ++ } ++ ++ spin_unlock(&wl->isr_lock); ++ ++ return IRQ_RETVAL(ours); ++} ++ ++/* ++ * is called in brcms_pci_probe() context, therefore no locking required. ++ */ ++static int ieee_hw_rate_init(struct ieee80211_hw *hw) ++{ ++ struct brcms_info *wl = hw->priv; ++ struct brcms_c_info *wlc = wl->wlc; ++ struct ieee80211_supported_band *band; ++ int has_5g = 0; ++ u16 phy_type; ++ ++ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL; ++ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; ++ ++ phy_type = brcms_c_get_phy_type(wl->wlc, 0); ++ if (phy_type == PHY_TYPE_N || phy_type == PHY_TYPE_LCN) { ++ band = &wlc->bandstate[BAND_2G_INDEX]->band; ++ *band = brcms_band_2GHz_nphy_template; ++ if (phy_type == PHY_TYPE_LCN) { ++ /* Single stream */ ++ band->ht_cap.mcs.rx_mask[1] = 0; ++ band->ht_cap.mcs.rx_highest = cpu_to_le16(72); ++ } ++ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band; ++ } else { ++ return -EPERM; ++ } ++ ++ /* Assume all bands use the same phy. True for 11n devices. */ ++ if (wl->pub->_nbands > 1) { ++ has_5g++; ++ if (phy_type == PHY_TYPE_N || phy_type == PHY_TYPE_LCN) { ++ band = &wlc->bandstate[BAND_5G_INDEX]->band; ++ *band = brcms_band_5GHz_nphy_template; ++ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = band; ++ } else { ++ return -EPERM; ++ } ++ } ++ return 0; ++} ++ ++/* ++ * is called in brcms_pci_probe() context, therefore no locking required. ++ */ ++static int ieee_hw_init(struct ieee80211_hw *hw) ++{ ++ hw->flags = IEEE80211_HW_SIGNAL_DBM ++ /* | IEEE80211_HW_CONNECTION_MONITOR What is this? */ ++ | IEEE80211_HW_REPORTS_TX_ACK_STATUS ++ | IEEE80211_HW_AMPDU_AGGREGATION; ++ ++ hw->extra_tx_headroom = brcms_c_get_header_len(); ++ hw->queues = N_TX_QUEUES; ++ hw->max_rates = 2; /* Primary rate and 1 fallback rate */ ++ ++ /* channel change time is dependent on chip and band */ ++ hw->channel_change_time = 7 * 1000; ++ hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); ++ ++ hw->rate_control_algorithm = "minstrel_ht"; ++ ++ hw->sta_data_size = 0; ++ return ieee_hw_rate_init(hw); ++} ++ ++/** ++ * attach to the WL device. ++ * ++ * Attach to the WL device identified by vendor and device parameters. ++ * regs is a host accessible memory address pointing to WL device registers. ++ * ++ * brcms_attach is not defined as static because in the case where no bus ++ * is defined, wl_attach will never be called, and thus, gcc will issue ++ * a warning that this function is defined but not used if we declare ++ * it as static. ++ * ++ * ++ * is called in brcms_pci_probe() context, therefore no locking required. ++ */ ++static struct brcms_info *brcms_attach(u16 vendor, u16 device, ++ resource_size_t regs, ++ struct pci_dev *btparam, uint irq) ++{ ++ struct brcms_info *wl = NULL; ++ int unit, err; ++ struct ieee80211_hw *hw; ++ u8 perm[ETH_ALEN]; ++ ++ unit = n_adapters_found; ++ err = 0; ++ ++ if (unit < 0) ++ return NULL; ++ ++ /* allocate private info */ ++ hw = pci_get_drvdata(btparam); /* btparam == pdev */ ++ if (hw != NULL) ++ wl = hw->priv; ++ if (WARN_ON(hw == NULL) || WARN_ON(wl == NULL)) ++ return NULL; ++ wl->wiphy = hw->wiphy; ++ ++ atomic_set(&wl->callbacks, 0); ++ ++ /* setup the bottom half handler */ ++ tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl); ++ ++ wl->regsva = ioremap_nocache(regs, PCI_BAR0_WINSZ); ++ if (wl->regsva == NULL) { ++ wiphy_err(wl->wiphy, "wl%d: ioremap() failed\n", unit); ++ goto fail; ++ } ++ spin_lock_init(&wl->lock); ++ spin_lock_init(&wl->isr_lock); ++ ++ /* prepare ucode */ ++ if (brcms_request_fw(wl, btparam) < 0) { ++ wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in " ++ "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm"); ++ brcms_release_fw(wl); ++ brcms_remove(btparam); ++ return NULL; ++ } ++ ++ /* common load-time initialization */ ++ wl->wlc = brcms_c_attach(wl, vendor, device, unit, false, ++ wl->regsva, btparam, &err); ++ brcms_release_fw(wl); ++ if (!wl->wlc) { ++ wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n", ++ KBUILD_MODNAME, err); ++ goto fail; ++ } ++ wl->pub = brcms_c_pub(wl->wlc); ++ ++ wl->pub->ieee_hw = hw; ++ ++ /* disable mpc */ ++ brcms_c_set_radio_mpc(wl->wlc, false); ++ ++ /* register our interrupt handler */ ++ if (request_irq(irq, brcms_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) { ++ wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit); ++ goto fail; ++ } ++ wl->irq = irq; ++ ++ /* register module */ ++ brcms_c_module_register(wl->pub, "linux", wl, NULL); ++ ++ if (ieee_hw_init(hw)) { ++ wiphy_err(wl->wiphy, "wl%d: %s: ieee_hw_init failed!\n", unit, ++ __func__); ++ goto fail; ++ } ++ ++ memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN); ++ if (WARN_ON(!is_valid_ether_addr(perm))) ++ goto fail; ++ SET_IEEE80211_PERM_ADDR(hw, perm); ++ ++ err = ieee80211_register_hw(hw); ++ if (err) ++ wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status" ++ "%d\n", __func__, err); ++ ++ if (wl->pub->srom_ccode[0]) ++ err = brcms_set_hint(wl, wl->pub->srom_ccode); ++ else ++ err = brcms_set_hint(wl, "US"); ++ if (err) ++ wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n", ++ __func__, err); ++ ++ n_adapters_found++; ++ return wl; ++ ++fail: ++ brcms_free(wl); ++ return NULL; ++} ++ ++ ++ ++/** ++ * determines if a device is a WL device, and if so, attaches it. ++ * ++ * This function determines if a device pointed to by pdev is a WL device, ++ * and if so, performs a brcms_attach() on it. ++ * ++ * Perimeter lock is initialized in the course of this function. ++ */ ++static int __devinit ++brcms_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ++{ ++ int rc; ++ struct brcms_info *wl; ++ struct ieee80211_hw *hw; ++ u32 val; ++ ++ dev_info(&pdev->dev, "bus %d slot %d func %d irq %d\n", ++ pdev->bus->number, PCI_SLOT(pdev->devfn), ++ PCI_FUNC(pdev->devfn), pdev->irq); ++ ++ if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) || ++ ((pdev->device != 0x0576) && ++ ((pdev->device & 0xff00) != 0x4300) && ++ ((pdev->device & 0xff00) != 0x4700) && ++ ((pdev->device < 43000) || (pdev->device > 43999)))) ++ return -ENODEV; ++ ++ rc = pci_enable_device(pdev); ++ if (rc) { ++ pr_err("%s: Cannot enable device %d-%d_%d\n", ++ __func__, pdev->bus->number, PCI_SLOT(pdev->devfn), ++ PCI_FUNC(pdev->devfn)); ++ return -ENODEV; ++ } ++ pci_set_master(pdev); ++ ++ pci_read_config_dword(pdev, 0x40, &val); ++ if ((val & 0x0000ff00) != 0) ++ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); ++ ++ hw = ieee80211_alloc_hw(sizeof(struct brcms_info), &brcms_ops); ++ if (!hw) { ++ pr_err("%s: ieee80211_alloc_hw failed\n", __func__); ++ return -ENOMEM; ++ } ++ ++ SET_IEEE80211_DEV(hw, &pdev->dev); ++ ++ pci_set_drvdata(pdev, hw); ++ ++ memset(hw->priv, 0, sizeof(*wl)); ++ ++ wl = brcms_attach(pdev->vendor, pdev->device, ++ pci_resource_start(pdev, 0), pdev, ++ pdev->irq); ++ ++ if (!wl) { ++ pr_err("%s: %s: brcms_attach failed!\n", KBUILD_MODNAME, ++ __func__); ++ return -ENODEV; ++ } ++ return 0; ++} ++ ++static int brcms_suspend(struct pci_dev *pdev, pm_message_t state) ++{ ++ struct brcms_info *wl; ++ struct ieee80211_hw *hw; ++ ++ hw = pci_get_drvdata(pdev); ++ wl = hw->priv; ++ if (!wl) { ++ wiphy_err(wl->wiphy, ++ "brcms_suspend: pci_get_drvdata failed\n"); ++ return -ENODEV; ++ } ++ ++ /* only need to flag hw is down for proper resume */ ++ spin_lock_bh(&wl->lock); ++ wl->pub->hw_up = false; ++ spin_unlock_bh(&wl->lock); ++ ++ pci_save_state(pdev); ++ pci_disable_device(pdev); ++ return pci_set_power_state(pdev, PCI_D3hot); ++} ++ ++static int brcms_resume(struct pci_dev *pdev) ++{ ++ struct brcms_info *wl; ++ struct ieee80211_hw *hw; ++ int err = 0; ++ u32 val; ++ ++ hw = pci_get_drvdata(pdev); ++ wl = hw->priv; ++ if (!wl) { ++ wiphy_err(wl->wiphy, ++ "wl: brcms_resume: pci_get_drvdata failed\n"); ++ return -ENODEV; ++ } ++ ++ err = pci_set_power_state(pdev, PCI_D0); ++ if (err) ++ return err; ++ ++ pci_restore_state(pdev); ++ ++ err = pci_enable_device(pdev); ++ if (err) ++ return err; ++ ++ pci_set_master(pdev); ++ ++ pci_read_config_dword(pdev, 0x40, &val); ++ if ((val & 0x0000ff00) != 0) ++ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); ++ ++ /* ++ * done. driver will be put in up state ++ * in brcms_ops_add_interface() call. ++ */ ++ return err; ++} ++ ++static struct pci_driver brcms_pci_driver = { ++ .name = KBUILD_MODNAME, ++ .probe = brcms_pci_probe, ++ .suspend = brcms_suspend, ++ .resume = brcms_resume, ++ .remove = __devexit_p(brcms_remove), ++ .id_table = brcms_pci_id_table, ++}; ++ ++/** ++ * This is the main entry point for the WL driver. ++ * ++ * This function determines if a device pointed to by pdev is a WL device, ++ * and if so, performs a brcms_attach() on it. ++ * ++ */ ++static int __init brcms_module_init(void) ++{ ++ int error = -ENODEV; ++ ++#ifdef BCMDBG ++ if (msglevel != 0xdeadbeef) ++ brcm_msg_level = msglevel; ++#endif /* BCMDBG */ ++ ++ error = pci_register_driver(&brcms_pci_driver); ++ if (!error) ++ return 0; ++ ++ ++ ++ return error; ++} ++ ++/** ++ * This function unloads the WL driver from the system. ++ * ++ * This function unconditionally unloads the WL driver module from the ++ * system. ++ * ++ */ ++static void __exit brcms_module_exit(void) ++{ ++ pci_unregister_driver(&brcms_pci_driver); ++ ++} ++ ++module_init(brcms_module_init); ++module_exit(brcms_module_exit); ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif, ++ bool state, int prio) ++{ ++ wiphy_err(wl->wiphy, "Shouldn't be here %s\n", __func__); ++} ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++void brcms_init(struct brcms_info *wl) ++{ ++ BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit); ++ brcms_reset(wl); ++ ++ brcms_c_init(wl->wlc); ++} ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++uint brcms_reset(struct brcms_info *wl) ++{ ++ BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit); ++ brcms_c_reset(wl->wlc); ++ ++ /* dpc will not be rescheduled */ ++ wl->resched = 0; ++ ++ return 0; ++} ++ ++/* ++ * These are interrupt on/off entry points. Disable interrupts ++ * during interrupt state transition. ++ */ ++void brcms_intrson(struct brcms_info *wl) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wl->isr_lock, flags); ++ brcms_c_intrson(wl->wlc); ++ spin_unlock_irqrestore(&wl->isr_lock, flags); ++} ++ ++u32 brcms_intrsoff(struct brcms_info *wl) ++{ ++ unsigned long flags; ++ u32 status; ++ ++ spin_lock_irqsave(&wl->isr_lock, flags); ++ status = brcms_c_intrsoff(wl->wlc); ++ spin_unlock_irqrestore(&wl->isr_lock, flags); ++ return status; ++} ++ ++void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wl->isr_lock, flags); ++ brcms_c_intrsrestore(wl->wlc, macintmask); ++ spin_unlock_irqrestore(&wl->isr_lock, flags); ++} ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++int brcms_up(struct brcms_info *wl) ++{ ++ int error = 0; ++ ++ if (wl->pub->up) ++ return 0; ++ ++ error = brcms_c_up(wl->wlc); ++ ++ return error; ++} ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++void brcms_down(struct brcms_info *wl) ++{ ++ uint callbacks, ret_val = 0; ++ ++ /* call common down function */ ++ ret_val = brcms_c_down(wl->wlc); ++ callbacks = atomic_read(&wl->callbacks) - ret_val; ++ ++ /* wait for down callbacks to complete */ ++ spin_unlock_bh(&wl->lock); ++ ++ /* For HIGH_only driver, it's important to actually schedule other work, ++ * not just spin wait since everything runs at schedule level ++ */ ++ SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000); ++ ++ spin_lock_bh(&wl->lock); ++} ++ ++/* ++* precondition: perimeter lock is not acquired ++ */ ++static void _brcms_timer(struct work_struct *work) ++{ ++ struct brcms_timer *t = container_of(work, struct brcms_timer, ++ dly_wrk.work); ++ ++ spin_lock_bh(&t->wl->lock); ++ ++ if (t->set) { ++ if (t->periodic) { ++ atomic_inc(&t->wl->callbacks); ++ ieee80211_queue_delayed_work(t->wl->pub->ieee_hw, ++ &t->dly_wrk, ++ msecs_to_jiffies(t->ms)); ++ } else { ++ t->set = false; ++ } ++ ++ t->fn(t->arg); ++ } ++ ++ atomic_dec(&t->wl->callbacks); ++ ++ spin_unlock_bh(&t->wl->lock); ++} ++ ++/* ++ * Adds a timer to the list. Caller supplies a timer function. ++ * Is called from wlc. ++ * ++ * precondition: perimeter lock has been acquired ++ */ ++struct brcms_timer *brcms_init_timer(struct brcms_info *wl, ++ void (*fn) (void *arg), ++ void *arg, const char *name) ++{ ++ struct brcms_timer *t; ++ ++ t = kzalloc(sizeof(struct brcms_timer), GFP_ATOMIC); ++ if (!t) ++ return NULL; ++ ++ INIT_DELAYED_WORK(&t->dly_wrk, _brcms_timer); ++ t->wl = wl; ++ t->fn = fn; ++ t->arg = arg; ++ t->next = wl->timers; ++ wl->timers = t; ++ ++#ifdef BCMDBG ++ t->name = kmalloc(strlen(name) + 1, GFP_ATOMIC); ++ if (t->name) ++ strcpy(t->name, name); ++#endif ++ ++ return t; ++} ++ ++/* ++ * adds only the kernel timer since it's going to be more accurate ++ * as well as it's easier to make it periodic ++ * ++ * precondition: perimeter lock has been acquired ++ */ ++void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic) ++{ ++ struct ieee80211_hw *hw = t->wl->pub->ieee_hw; ++ ++#ifdef BCMDBG ++ if (t->set) ++ wiphy_err(hw->wiphy, "%s: Already set. Name: %s, per %d\n", ++ __func__, t->name, periodic); ++#endif ++ t->ms = ms; ++ t->periodic = (bool) periodic; ++ t->set = true; ++ ++ atomic_inc(&t->wl->callbacks); ++ ++ ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms)); ++} ++ ++/* ++ * return true if timer successfully deleted, false if still pending ++ * ++ * precondition: perimeter lock has been acquired ++ */ ++bool brcms_del_timer(struct brcms_timer *t) ++{ ++ if (t->set) { ++ t->set = false; ++ if (!cancel_delayed_work(&t->dly_wrk)) ++ return false; ++ ++ atomic_dec(&t->wl->callbacks); ++ } ++ ++ return true; ++} ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++void brcms_free_timer(struct brcms_timer *t) ++{ ++ struct brcms_info *wl = t->wl; ++ struct brcms_timer *tmp; ++ ++ /* delete the timer in case it is active */ ++ brcms_del_timer(t); ++ ++ if (wl->timers == t) { ++ wl->timers = wl->timers->next; ++#ifdef BCMDBG ++ kfree(t->name); ++#endif ++ kfree(t); ++ return; ++ ++ } ++ ++ tmp = wl->timers; ++ while (tmp) { ++ if (tmp->next == t) { ++ tmp->next = t->next; ++#ifdef BCMDBG ++ kfree(t->name); ++#endif ++ kfree(t); ++ return; ++ } ++ tmp = tmp->next; ++ } ++ ++} ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx) ++{ ++ int i, entry; ++ const u8 *pdata; ++ struct firmware_hdr *hdr; ++ for (i = 0; i < wl->fw.fw_cnt; i++) { ++ hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data; ++ for (entry = 0; entry < wl->fw.hdr_num_entries[i]; ++ entry++, hdr++) { ++ u32 len = le32_to_cpu(hdr->len); ++ if (le32_to_cpu(hdr->idx) == idx) { ++ pdata = wl->fw.fw_bin[i]->data + ++ le32_to_cpu(hdr->offset); ++ *pbuf = kmalloc(len, GFP_ATOMIC); ++ if (*pbuf == NULL) ++ goto fail; ++ ++ memcpy(*pbuf, pdata, len); ++ return 0; ++ } ++ } ++ } ++ wiphy_err(wl->wiphy, "ERROR: ucode buf tag:%d can not be found!\n", ++ idx); ++ *pbuf = NULL; ++fail: ++ return -ENODATA; ++} ++ ++/* ++ * Precondition: Since this function is called in brcms_pci_probe() context, ++ * no locking is required. ++ */ ++int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx) ++{ ++ int i, entry; ++ const u8 *pdata; ++ struct firmware_hdr *hdr; ++ for (i = 0; i < wl->fw.fw_cnt; i++) { ++ hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data; ++ for (entry = 0; entry < wl->fw.hdr_num_entries[i]; ++ entry++, hdr++) { ++ if (le32_to_cpu(hdr->idx) == idx) { ++ pdata = wl->fw.fw_bin[i]->data + ++ le32_to_cpu(hdr->offset); ++ if (le32_to_cpu(hdr->len) != 4) { ++ wiphy_err(wl->wiphy, ++ "ERROR: fw hdr len\n"); ++ return -ENOMSG; ++ } ++ *n_bytes = le32_to_cpu(*((__le32 *) pdata)); ++ return 0; ++ } ++ } ++ } ++ wiphy_err(wl->wiphy, "ERROR: ucode tag:%d can not be found!\n", idx); ++ return -ENOMSG; ++} ++ ++/* ++ * precondition: can both be called locked and unlocked ++ */ ++void brcms_ucode_free_buf(void *p) ++{ ++ kfree(p); ++} ++ ++/* ++ * checks validity of all firmware images loaded from user space ++ * ++ * Precondition: Since this function is called in brcms_pci_probe() context, ++ * no locking is required. ++ */ ++int brcms_check_firmwares(struct brcms_info *wl) ++{ ++ int i; ++ int entry; ++ int rc = 0; ++ const struct firmware *fw; ++ const struct firmware *fw_hdr; ++ struct firmware_hdr *ucode_hdr; ++ for (i = 0; i < MAX_FW_IMAGES && rc == 0; i++) { ++ fw = wl->fw.fw_bin[i]; ++ fw_hdr = wl->fw.fw_hdr[i]; ++ if (fw == NULL && fw_hdr == NULL) { ++ break; ++ } else if (fw == NULL || fw_hdr == NULL) { ++ wiphy_err(wl->wiphy, "%s: invalid bin/hdr fw\n", ++ __func__); ++ rc = -EBADF; ++ } else if (fw_hdr->size % sizeof(struct firmware_hdr)) { ++ wiphy_err(wl->wiphy, "%s: non integral fw hdr file " ++ "size %zu/%zu\n", __func__, fw_hdr->size, ++ sizeof(struct firmware_hdr)); ++ rc = -EBADF; ++ } else if (fw->size < MIN_FW_SIZE || fw->size > MAX_FW_SIZE) { ++ wiphy_err(wl->wiphy, "%s: out of bounds fw file size " ++ "%zu\n", __func__, fw->size); ++ rc = -EBADF; ++ } else { ++ /* check if ucode section overruns firmware image */ ++ ucode_hdr = (struct firmware_hdr *)fw_hdr->data; ++ for (entry = 0; entry < wl->fw.hdr_num_entries[i] && ++ !rc; entry++, ucode_hdr++) { ++ if (le32_to_cpu(ucode_hdr->offset) + ++ le32_to_cpu(ucode_hdr->len) > ++ fw->size) { ++ wiphy_err(wl->wiphy, ++ "%s: conflicting bin/hdr\n", ++ __func__); ++ rc = -EBADF; ++ } ++ } ++ } ++ } ++ if (rc == 0 && wl->fw.fw_cnt != i) { ++ wiphy_err(wl->wiphy, "%s: invalid fw_cnt=%d\n", __func__, ++ wl->fw.fw_cnt); ++ rc = -EBADF; ++ } ++ return rc; ++} ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++bool brcms_rfkill_set_hw_state(struct brcms_info *wl) ++{ ++ bool blocked = brcms_c_check_radio_disabled(wl->wlc); ++ ++ spin_unlock_bh(&wl->lock); ++ wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked); ++ if (blocked) ++ wiphy_rfkill_start_polling(wl->pub->ieee_hw->wiphy); ++ spin_lock_bh(&wl->lock); ++ return blocked; ++} ++ ++/* ++ * precondition: perimeter lock has been acquired ++ */ ++void brcms_msleep(struct brcms_info *wl, uint ms) ++{ ++ spin_unlock_bh(&wl->lock); ++ msleep(ms); ++ spin_lock_bh(&wl->lock); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h.orig 2011-11-09 13:46:58.246800621 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h 2011-11-09 13:47:16.998566192 -0500 +@@ -0,0 +1,108 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_MAC80211_IF_H_ ++#define _BRCM_MAC80211_IF_H_ ++ ++#include ++#include ++#include ++ ++#include "ucode_loader.h" ++/* ++ * Starting index for 5G rates in the ++ * legacy rate table. ++ */ ++#define BRCMS_LEGACY_5G_RATE_OFFSET 4 ++ ++/* softmac ioctl definitions */ ++#define BRCMS_SET_SHORTSLOT_OVERRIDE 146 ++ ++struct brcms_timer { ++ struct delayed_work dly_wrk; ++ struct brcms_info *wl; ++ void (*fn) (void *); /* function called upon expiration */ ++ void *arg; /* fixed argument provided to called function */ ++ uint ms; ++ bool periodic; ++ bool set; /* indicates if timer is active */ ++ struct brcms_timer *next; /* for freeing on unload */ ++#ifdef BCMDBG ++ char *name; /* Description of the timer */ ++#endif ++}; ++ ++struct brcms_if { ++ uint subunit; /* WDS/BSS unit */ ++ struct pci_dev *pci_dev; ++}; ++ ++#define MAX_FW_IMAGES 4 ++struct brcms_firmware { ++ u32 fw_cnt; ++ const struct firmware *fw_bin[MAX_FW_IMAGES]; ++ const struct firmware *fw_hdr[MAX_FW_IMAGES]; ++ u32 hdr_num_entries[MAX_FW_IMAGES]; ++}; ++ ++struct brcms_info { ++ struct brcms_pub *pub; /* pointer to public wlc state */ ++ struct brcms_c_info *wlc; /* pointer to private common data */ ++ u32 magic; ++ ++ int irq; ++ ++ spinlock_t lock; /* per-device perimeter lock */ ++ spinlock_t isr_lock; /* per-device ISR synchronization lock */ ++ ++ /* regsva for unmap in brcms_free() */ ++ void __iomem *regsva; /* opaque chip registers virtual address */ ++ ++ /* timer related fields */ ++ atomic_t callbacks; /* # outstanding callback functions */ ++ struct brcms_timer *timers; /* timer cleanup queue */ ++ ++ struct tasklet_struct tasklet; /* dpc tasklet */ ++ bool resched; /* dpc needs to be and is rescheduled */ ++ struct brcms_firmware fw; ++ struct wiphy *wiphy; ++ struct brcms_ucode ucode; ++}; ++ ++/* misc callbacks */ ++extern void brcms_init(struct brcms_info *wl); ++extern uint brcms_reset(struct brcms_info *wl); ++extern void brcms_intrson(struct brcms_info *wl); ++extern u32 brcms_intrsoff(struct brcms_info *wl); ++extern void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask); ++extern int brcms_up(struct brcms_info *wl); ++extern void brcms_down(struct brcms_info *wl); ++extern void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif, ++ bool state, int prio); ++extern bool brcms_rfkill_set_hw_state(struct brcms_info *wl); ++ ++/* timer functions */ ++extern struct brcms_timer *brcms_init_timer(struct brcms_info *wl, ++ void (*fn) (void *arg), void *arg, ++ const char *name); ++extern void brcms_free_timer(struct brcms_timer *timer); ++extern void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic); ++extern bool brcms_del_timer(struct brcms_timer *timer); ++extern void brcms_msleep(struct brcms_info *wl, uint ms); ++extern void brcms_dpc(unsigned long data); ++extern void brcms_timer(struct brcms_timer *t); ++ ++#endif /* _BRCM_MAC80211_IF_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.c.orig 2011-11-09 13:46:58.250800570 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.c 2011-11-09 13:47:17.004566116 -0500 +@@ -0,0 +1,8775 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rate.h" ++#include "scb.h" ++#include "phy/phy_hal.h" ++#include "channel.h" ++#include "antsel.h" ++#include "stf.h" ++#include "ampdu.h" ++#include "mac80211_if.h" ++#include "ucode_loader.h" ++#include "main.h" ++ ++/* ++ * Indication for txflowcontrol that all priority bits in ++ * TXQ_STOP_FOR_PRIOFC_MASK are to be considered. ++ */ ++#define ALLPRIO -1 ++ ++/* ++ * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL. ++ */ ++#define SSID_FMT_BUF_LEN ((4 * IEEE80211_MAX_SSID_LEN) + 1) ++ ++/* watchdog timer, in unit of ms */ ++#define TIMER_INTERVAL_WATCHDOG 1000 ++/* radio monitor timer, in unit of ms */ ++#define TIMER_INTERVAL_RADIOCHK 800 ++ ++/* Max MPC timeout, in unit of watchdog */ ++#ifndef BRCMS_MPC_MAX_DELAYCNT ++#define BRCMS_MPC_MAX_DELAYCNT 10 ++#endif ++ ++/* Min MPC timeout, in unit of watchdog */ ++#define BRCMS_MPC_MIN_DELAYCNT 1 ++#define BRCMS_MPC_THRESHOLD 3 /* MPC count threshold level */ ++ ++/* beacon interval, in unit of 1024TU */ ++#define BEACON_INTERVAL_DEFAULT 100 ++/* DTIM interval, in unit of beacon interval */ ++#define DTIM_INTERVAL_DEFAULT 3 ++ ++/* Scale down delays to accommodate QT slow speed */ ++/* beacon interval, in unit of 1024TU */ ++#define BEACON_INTERVAL_DEF_QT 20 ++/* DTIM interval, in unit of beacon interval */ ++#define DTIM_INTERVAL_DEF_QT 1 ++ ++#define TBTT_ALIGN_LEEWAY_US 100 /* min leeway before first TBTT in us */ ++ ++/* n-mode support capability */ ++/* 2x2 includes both 1x1 & 2x2 devices ++ * reserved #define 2 for future when we want to separate 1x1 & 2x2 and ++ * control it independently ++ */ ++#define WL_11N_2x2 1 ++#define WL_11N_3x3 3 ++#define WL_11N_4x4 4 ++ ++/* define 11n feature disable flags */ ++#define WLFEATURE_DISABLE_11N 0x00000001 ++#define WLFEATURE_DISABLE_11N_STBC_TX 0x00000002 ++#define WLFEATURE_DISABLE_11N_STBC_RX 0x00000004 ++#define WLFEATURE_DISABLE_11N_SGI_TX 0x00000008 ++#define WLFEATURE_DISABLE_11N_SGI_RX 0x00000010 ++#define WLFEATURE_DISABLE_11N_AMPDU_TX 0x00000020 ++#define WLFEATURE_DISABLE_11N_AMPDU_RX 0x00000040 ++#define WLFEATURE_DISABLE_11N_GF 0x00000080 ++ ++#define EDCF_ACI_MASK 0x60 ++#define EDCF_ACI_SHIFT 5 ++#define EDCF_ECWMIN_MASK 0x0f ++#define EDCF_ECWMAX_SHIFT 4 ++#define EDCF_AIFSN_MASK 0x0f ++#define EDCF_AIFSN_MAX 15 ++#define EDCF_ECWMAX_MASK 0xf0 ++ ++#define EDCF_AC_BE_TXOP_STA 0x0000 ++#define EDCF_AC_BK_TXOP_STA 0x0000 ++#define EDCF_AC_VO_ACI_STA 0x62 ++#define EDCF_AC_VO_ECW_STA 0x32 ++#define EDCF_AC_VI_ACI_STA 0x42 ++#define EDCF_AC_VI_ECW_STA 0x43 ++#define EDCF_AC_BK_ECW_STA 0xA4 ++#define EDCF_AC_VI_TXOP_STA 0x005e ++#define EDCF_AC_VO_TXOP_STA 0x002f ++#define EDCF_AC_BE_ACI_STA 0x03 ++#define EDCF_AC_BE_ECW_STA 0xA4 ++#define EDCF_AC_BK_ACI_STA 0x27 ++#define EDCF_AC_VO_TXOP_AP 0x002f ++ ++#define EDCF_TXOP2USEC(txop) ((txop) << 5) ++#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1) ++ ++#define APHY_SYMBOL_TIME 4 ++#define APHY_PREAMBLE_TIME 16 ++#define APHY_SIGNAL_TIME 4 ++#define APHY_SIFS_TIME 16 ++#define APHY_SERVICE_NBITS 16 ++#define APHY_TAIL_NBITS 6 ++#define BPHY_SIFS_TIME 10 ++#define BPHY_PLCP_SHORT_TIME 96 ++ ++#define PREN_PREAMBLE 24 ++#define PREN_MM_EXT 12 ++#define PREN_PREAMBLE_EXT 4 ++ ++#define DOT11_MAC_HDR_LEN 24 ++#define DOT11_ACK_LEN 10 ++#define DOT11_BA_LEN 4 ++#define DOT11_OFDM_SIGNAL_EXTENSION 6 ++#define DOT11_MIN_FRAG_LEN 256 ++#define DOT11_RTS_LEN 16 ++#define DOT11_CTS_LEN 10 ++#define DOT11_BA_BITMAP_LEN 128 ++#define DOT11_MIN_BEACON_PERIOD 1 ++#define DOT11_MAX_BEACON_PERIOD 0xFFFF ++#define DOT11_MAXNUMFRAGS 16 ++#define DOT11_MAX_FRAG_LEN 2346 ++ ++#define BPHY_PLCP_TIME 192 ++#define RIFS_11N_TIME 2 ++ ++#define WME_VER 1 ++#define WME_SUBTYPE_PARAM_IE 1 ++#define WME_TYPE 2 ++#define WME_OUI "\x00\x50\xf2" ++ ++#define AC_BE 0 ++#define AC_BK 1 ++#define AC_VI 2 ++#define AC_VO 3 ++ ++#define BCN_TMPL_LEN 512 /* length of the BCN template area */ ++ ++/* brcms_bss_info flag bit values */ ++#define BRCMS_BSS_HT 0x0020 /* BSS is HT (MIMO) capable */ ++ ++/* Flags used in brcms_c_txq_info.stopped */ ++/* per prio flow control bits */ ++#define TXQ_STOP_FOR_PRIOFC_MASK 0x000000FF ++/* stop txq enqueue for packet drain */ ++#define TXQ_STOP_FOR_PKT_DRAIN 0x00000100 ++/* stop txq enqueue for ampdu flow control */ ++#define TXQ_STOP_FOR_AMPDU_FLOW_CNTRL 0x00000200 ++ ++#define BRCMS_HWRXOFF 38 /* chip rx buffer offset */ ++ ++/* Find basic rate for a given rate */ ++static u8 brcms_basic_rate(struct brcms_c_info *wlc, u32 rspec) ++{ ++ if (is_mcs_rate(rspec)) ++ return wlc->band->basic_rate[mcs_table[rspec & RSPEC_RATE_MASK] ++ .leg_ofdm]; ++ return wlc->band->basic_rate[rspec & RSPEC_RATE_MASK]; ++} ++ ++static u16 frametype(u32 rspec, u8 mimoframe) ++{ ++ if (is_mcs_rate(rspec)) ++ return mimoframe; ++ return is_cck_rate(rspec) ? FT_CCK : FT_OFDM; ++} ++ ++/* rfdisable delay timer 500 ms, runs of ALP clock */ ++#define RFDISABLE_DEFAULT 10000000 ++ ++#define BRCMS_TEMPSENSE_PERIOD 10 /* 10 second timeout */ ++ ++/* precedences numbers for wlc queues. These are twice as may levels as ++ * 802.1D priorities. ++ * Odd numbers are used for HI priority traffic at same precedence levels ++ * These constants are used ONLY by wlc_prio2prec_map. Do not use them ++ * elsewhere. ++ */ ++#define _BRCMS_PREC_NONE 0 /* None = - */ ++#define _BRCMS_PREC_BK 2 /* BK - Background */ ++#define _BRCMS_PREC_BE 4 /* BE - Best-effort */ ++#define _BRCMS_PREC_EE 6 /* EE - Excellent-effort */ ++#define _BRCMS_PREC_CL 8 /* CL - Controlled Load */ ++#define _BRCMS_PREC_VI 10 /* Vi - Video */ ++#define _BRCMS_PREC_VO 12 /* Vo - Voice */ ++#define _BRCMS_PREC_NC 14 /* NC - Network Control */ ++ ++/* The BSS is generating beacons in HW */ ++#define BRCMS_BSSCFG_HW_BCN 0x20 ++ ++#define SYNTHPU_DLY_APHY_US 3700 /* a phy synthpu_dly time in us */ ++#define SYNTHPU_DLY_BPHY_US 1050 /* b/g phy synthpu_dly time in us */ ++#define SYNTHPU_DLY_NPHY_US 2048 /* n phy REV3 synthpu_dly time in us */ ++#define SYNTHPU_DLY_LPPHY_US 300 /* lpphy synthpu_dly time in us */ ++ ++#define SYNTHPU_DLY_PHY_US_QT 100 /* QT synthpu_dly time in us */ ++ ++#define ANTCNT 10 /* vanilla M_MAX_ANTCNT value */ ++ ++/* Per-AC retry limit register definitions; uses defs.h bitfield macros */ ++#define EDCF_SHORT_S 0 ++#define EDCF_SFB_S 4 ++#define EDCF_LONG_S 8 ++#define EDCF_LFB_S 12 ++#define EDCF_SHORT_M BITFIELD_MASK(4) ++#define EDCF_SFB_M BITFIELD_MASK(4) ++#define EDCF_LONG_M BITFIELD_MASK(4) ++#define EDCF_LFB_M BITFIELD_MASK(4) ++ ++#define RETRY_SHORT_DEF 7 /* Default Short retry Limit */ ++#define RETRY_SHORT_MAX 255 /* Maximum Short retry Limit */ ++#define RETRY_LONG_DEF 4 /* Default Long retry count */ ++#define RETRY_SHORT_FB 3 /* Short count for fallback rate */ ++#define RETRY_LONG_FB 2 /* Long count for fallback rate */ ++ ++#define APHY_CWMIN 15 ++#define PHY_CWMAX 1023 ++ ++#define EDCF_AIFSN_MIN 1 ++ ++#define FRAGNUM_MASK 0xF ++ ++#define APHY_SLOT_TIME 9 ++#define BPHY_SLOT_TIME 20 ++ ++#define WL_SPURAVOID_OFF 0 ++#define WL_SPURAVOID_ON1 1 ++#define WL_SPURAVOID_ON2 2 ++ ++/* invalid core flags, use the saved coreflags */ ++#define BRCMS_USE_COREFLAGS 0xffffffff ++ ++/* values for PLCPHdr_override */ ++#define BRCMS_PLCP_AUTO -1 ++#define BRCMS_PLCP_SHORT 0 ++#define BRCMS_PLCP_LONG 1 ++ ++/* values for g_protection_override and n_protection_override */ ++#define BRCMS_PROTECTION_AUTO -1 ++#define BRCMS_PROTECTION_OFF 0 ++#define BRCMS_PROTECTION_ON 1 ++#define BRCMS_PROTECTION_MMHDR_ONLY 2 ++#define BRCMS_PROTECTION_CTS_ONLY 3 ++ ++/* values for g_protection_control and n_protection_control */ ++#define BRCMS_PROTECTION_CTL_OFF 0 ++#define BRCMS_PROTECTION_CTL_LOCAL 1 ++#define BRCMS_PROTECTION_CTL_OVERLAP 2 ++ ++/* values for n_protection */ ++#define BRCMS_N_PROTECTION_OFF 0 ++#define BRCMS_N_PROTECTION_OPTIONAL 1 ++#define BRCMS_N_PROTECTION_20IN40 2 ++#define BRCMS_N_PROTECTION_MIXEDMODE 3 ++ ++/* values for band specific 40MHz capabilities */ ++#define BRCMS_N_BW_20ALL 0 ++#define BRCMS_N_BW_40ALL 1 ++#define BRCMS_N_BW_20IN2G_40IN5G 2 ++ ++/* bitflags for SGI support (sgi_rx iovar) */ ++#define BRCMS_N_SGI_20 0x01 ++#define BRCMS_N_SGI_40 0x02 ++ ++/* defines used by the nrate iovar */ ++/* MSC in use,indicates b0-6 holds an mcs */ ++#define NRATE_MCS_INUSE 0x00000080 ++/* rate/mcs value */ ++#define NRATE_RATE_MASK 0x0000007f ++/* stf mode mask: siso, cdd, stbc, sdm */ ++#define NRATE_STF_MASK 0x0000ff00 ++/* stf mode shift */ ++#define NRATE_STF_SHIFT 8 ++/* bit indicates override both rate & mode */ ++#define NRATE_OVERRIDE 0x80000000 ++/* bit indicate to override mcs only */ ++#define NRATE_OVERRIDE_MCS_ONLY 0x40000000 ++#define NRATE_SGI_MASK 0x00800000 /* sgi mode */ ++#define NRATE_SGI_SHIFT 23 /* sgi mode */ ++#define NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */ ++#define NRATE_LDPC_SHIFT 22 /* ldpc shift */ ++ ++#define NRATE_STF_SISO 0 /* stf mode SISO */ ++#define NRATE_STF_CDD 1 /* stf mode CDD */ ++#define NRATE_STF_STBC 2 /* stf mode STBC */ ++#define NRATE_STF_SDM 3 /* stf mode SDM */ ++ ++#define MAX_DMA_SEGS 4 ++ ++/* Max # of entries in Tx FIFO based on 4kb page size */ ++#define NTXD 256 ++/* Max # of entries in Rx FIFO based on 4kb page size */ ++#define NRXD 256 ++ ++/* try to keep this # rbufs posted to the chip */ ++#define NRXBUFPOST 32 ++ ++/* data msg txq hiwat mark */ ++#define BRCMS_DATAHIWAT 50 ++ ++/* bounded rx loops */ ++#define RXBND 8 /* max # frames to process in brcms_c_recv() */ ++#define TXSBND 8 /* max # tx status to process in wlc_txstatus() */ ++ ++/* ++ * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL. ++ */ ++#define SSID_FMT_BUF_LEN ((4 * IEEE80211_MAX_SSID_LEN) + 1) ++ ++/* brcmu_format_flags() bit description structure */ ++struct brcms_c_bit_desc { ++ u32 bit; ++ const char *name; ++}; ++ ++/* ++ * The following table lists the buffer memory allocated to xmt fifos in HW. ++ * the size is in units of 256bytes(one block), total size is HW dependent ++ * ucode has default fifo partition, sw can overwrite if necessary ++ * ++ * This is documented in twiki under the topic UcodeTxFifo. Please ensure ++ * the twiki is updated before making changes. ++ */ ++ ++/* Starting corerev for the fifo size table */ ++#define XMTFIFOTBL_STARTREV 20 ++ ++struct d11init { ++ __le16 addr; ++ __le16 size; ++ __le32 value; ++}; ++ ++struct edcf_acparam { ++ u8 ACI; ++ u8 ECW; ++ u16 TXOP; ++} __packed; ++ ++const u8 prio2fifo[NUMPRIO] = { ++ TX_AC_BE_FIFO, /* 0 BE AC_BE Best Effort */ ++ TX_AC_BK_FIFO, /* 1 BK AC_BK Background */ ++ TX_AC_BK_FIFO, /* 2 -- AC_BK Background */ ++ TX_AC_BE_FIFO, /* 3 EE AC_BE Best Effort */ ++ TX_AC_VI_FIFO, /* 4 CL AC_VI Video */ ++ TX_AC_VI_FIFO, /* 5 VI AC_VI Video */ ++ TX_AC_VO_FIFO, /* 6 VO AC_VO Voice */ ++ TX_AC_VO_FIFO /* 7 NC AC_VO Voice */ ++}; ++ ++/* debug/trace */ ++uint brcm_msg_level = ++#if defined(BCMDBG) ++ LOG_ERROR_VAL; ++#else ++ 0; ++#endif /* BCMDBG */ ++ ++/* TX FIFO number to WME/802.1E Access Category */ ++static const u8 wme_fifo2ac[] = { AC_BK, AC_BE, AC_VI, AC_VO, AC_BE, AC_BE }; ++ ++/* WME/802.1E Access Category to TX FIFO number */ ++static const u8 wme_ac2fifo[] = { 1, 0, 2, 3 }; ++ ++/* 802.1D Priority to precedence queue mapping */ ++const u8 wlc_prio2prec_map[] = { ++ _BRCMS_PREC_BE, /* 0 BE - Best-effort */ ++ _BRCMS_PREC_BK, /* 1 BK - Background */ ++ _BRCMS_PREC_NONE, /* 2 None = - */ ++ _BRCMS_PREC_EE, /* 3 EE - Excellent-effort */ ++ _BRCMS_PREC_CL, /* 4 CL - Controlled Load */ ++ _BRCMS_PREC_VI, /* 5 Vi - Video */ ++ _BRCMS_PREC_VO, /* 6 Vo - Voice */ ++ _BRCMS_PREC_NC, /* 7 NC - Network Control */ ++}; ++ ++static const u16 xmtfifo_sz[][NFIFO] = { ++ /* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */ ++ {20, 192, 192, 21, 17, 5}, ++ /* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */ ++ {9, 58, 22, 14, 14, 5}, ++ /* corerev 22: 5120, 49152, 49152, 5376, 4352, 1280 */ ++ {20, 192, 192, 21, 17, 5}, ++ /* corerev 23: 5120, 49152, 49152, 5376, 4352, 1280 */ ++ {20, 192, 192, 21, 17, 5}, ++ /* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */ ++ {9, 58, 22, 14, 14, 5}, ++}; ++ ++static const u8 acbitmap2maxprio[] = { ++ PRIO_8021D_BE, PRIO_8021D_BE, PRIO_8021D_BK, PRIO_8021D_BK, ++ PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, ++ PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, ++ PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO ++}; ++ ++#ifdef BCMDBG ++static const char * const fifo_names[] = { ++ "AC_BK", "AC_BE", "AC_VI", "AC_VO", "BCMC", "ATIM" }; ++#else ++static const char fifo_names[6][0]; ++#endif ++ ++#ifdef BCMDBG ++/* pointer to most recently allocated wl/wlc */ ++static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL); ++#endif ++ ++/* currently the best mechanism for determining SIFS is the band in use */ ++static u16 get_sifs(struct brcms_band *band) ++{ ++ return band->bandtype == BRCM_BAND_5G ? APHY_SIFS_TIME : ++ BPHY_SIFS_TIME; ++} ++ ++/* ++ * Detect Card removed. ++ * Even checking an sbconfig register read will not false trigger when the core ++ * is in reset it breaks CF address mechanism. Accessing gphy phyversion will ++ * cause SB error if aphy is in reset on 4306B0-DB. Need a simple accessible ++ * reg with fixed 0/1 pattern (some platforms return all 0). ++ * If clocks are present, call the sb routine which will figure out if the ++ * device is removed. ++ */ ++static bool brcms_deviceremoved(struct brcms_c_info *wlc) ++{ ++ if (!wlc->hw->clk) ++ return ai_deviceremoved(wlc->hw->sih); ++ return (R_REG(&wlc->hw->regs->maccontrol) & ++ (MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN; ++} ++ ++/* sum the individual fifo tx pending packet counts */ ++static s16 brcms_txpktpendtot(struct brcms_c_info *wlc) ++{ ++ return wlc->core->txpktpend[0] + wlc->core->txpktpend[1] + ++ wlc->core->txpktpend[2] + wlc->core->txpktpend[3]; ++} ++ ++static bool brcms_is_mband_unlocked(struct brcms_c_info *wlc) ++{ ++ return wlc->pub->_nbands > 1 && !wlc->bandlocked; ++} ++ ++static int brcms_chspec_bw(u16 chanspec) ++{ ++ if (CHSPEC_IS40(chanspec)) ++ return BRCMS_40_MHZ; ++ if (CHSPEC_IS20(chanspec)) ++ return BRCMS_20_MHZ; ++ ++ return BRCMS_10_MHZ; ++} ++ ++/* ++ * return true if Minimum Power Consumption should ++ * be entered, false otherwise ++ */ ++static bool brcms_c_is_non_delay_mpc(struct brcms_c_info *wlc) ++{ ++ return false; ++} ++ ++static bool brcms_c_ismpc(struct brcms_c_info *wlc) ++{ ++ return (wlc->mpc_delay_off == 0) && (brcms_c_is_non_delay_mpc(wlc)); ++} ++ ++static void brcms_c_bsscfg_mfree(struct brcms_bss_cfg *cfg) ++{ ++ if (cfg == NULL) ++ return; ++ ++ kfree(cfg->current_bss); ++ kfree(cfg); ++} ++ ++static void brcms_c_detach_mfree(struct brcms_c_info *wlc) ++{ ++ if (wlc == NULL) ++ return; ++ ++ brcms_c_bsscfg_mfree(wlc->bsscfg); ++ kfree(wlc->pub); ++ kfree(wlc->modulecb); ++ kfree(wlc->default_bss); ++ kfree(wlc->protection); ++ kfree(wlc->stf); ++ kfree(wlc->bandstate[0]); ++ kfree(wlc->corestate->macstat_snapshot); ++ kfree(wlc->corestate); ++ kfree(wlc->hw->bandstate[0]); ++ kfree(wlc->hw); ++ ++ /* free the wlc */ ++ kfree(wlc); ++ wlc = NULL; ++} ++ ++static struct brcms_bss_cfg *brcms_c_bsscfg_malloc(uint unit) ++{ ++ struct brcms_bss_cfg *cfg; ++ ++ cfg = kzalloc(sizeof(struct brcms_bss_cfg), GFP_ATOMIC); ++ if (cfg == NULL) ++ goto fail; ++ ++ cfg->current_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC); ++ if (cfg->current_bss == NULL) ++ goto fail; ++ ++ return cfg; ++ ++ fail: ++ brcms_c_bsscfg_mfree(cfg); ++ return NULL; ++} ++ ++static struct brcms_c_info * ++brcms_c_attach_malloc(uint unit, uint *err, uint devid) ++{ ++ struct brcms_c_info *wlc; ++ ++ wlc = kzalloc(sizeof(struct brcms_c_info), GFP_ATOMIC); ++ if (wlc == NULL) { ++ *err = 1002; ++ goto fail; ++ } ++ ++ /* allocate struct brcms_c_pub state structure */ ++ wlc->pub = kzalloc(sizeof(struct brcms_pub), GFP_ATOMIC); ++ if (wlc->pub == NULL) { ++ *err = 1003; ++ goto fail; ++ } ++ wlc->pub->wlc = wlc; ++ ++ /* allocate struct brcms_hardware state structure */ ++ ++ wlc->hw = kzalloc(sizeof(struct brcms_hardware), GFP_ATOMIC); ++ if (wlc->hw == NULL) { ++ *err = 1005; ++ goto fail; ++ } ++ wlc->hw->wlc = wlc; ++ ++ wlc->hw->bandstate[0] = ++ kzalloc(sizeof(struct brcms_hw_band) * MAXBANDS, GFP_ATOMIC); ++ if (wlc->hw->bandstate[0] == NULL) { ++ *err = 1006; ++ goto fail; ++ } else { ++ int i; ++ ++ for (i = 1; i < MAXBANDS; i++) ++ wlc->hw->bandstate[i] = (struct brcms_hw_band *) ++ ((unsigned long)wlc->hw->bandstate[0] + ++ (sizeof(struct brcms_hw_band) * i)); ++ } ++ ++ wlc->modulecb = ++ kzalloc(sizeof(struct modulecb) * BRCMS_MAXMODULES, GFP_ATOMIC); ++ if (wlc->modulecb == NULL) { ++ *err = 1009; ++ goto fail; ++ } ++ ++ wlc->default_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC); ++ if (wlc->default_bss == NULL) { ++ *err = 1010; ++ goto fail; ++ } ++ ++ wlc->bsscfg = brcms_c_bsscfg_malloc(unit); ++ if (wlc->bsscfg == NULL) { ++ *err = 1011; ++ goto fail; ++ } ++ ++ wlc->protection = kzalloc(sizeof(struct brcms_protection), ++ GFP_ATOMIC); ++ if (wlc->protection == NULL) { ++ *err = 1016; ++ goto fail; ++ } ++ ++ wlc->stf = kzalloc(sizeof(struct brcms_stf), GFP_ATOMIC); ++ if (wlc->stf == NULL) { ++ *err = 1017; ++ goto fail; ++ } ++ ++ wlc->bandstate[0] = ++ kzalloc(sizeof(struct brcms_band)*MAXBANDS, GFP_ATOMIC); ++ if (wlc->bandstate[0] == NULL) { ++ *err = 1025; ++ goto fail; ++ } else { ++ int i; ++ ++ for (i = 1; i < MAXBANDS; i++) ++ wlc->bandstate[i] = (struct brcms_band *) ++ ((unsigned long)wlc->bandstate[0] ++ + (sizeof(struct brcms_band)*i)); ++ } ++ ++ wlc->corestate = kzalloc(sizeof(struct brcms_core), GFP_ATOMIC); ++ if (wlc->corestate == NULL) { ++ *err = 1026; ++ goto fail; ++ } ++ ++ wlc->corestate->macstat_snapshot = ++ kzalloc(sizeof(struct macstat), GFP_ATOMIC); ++ if (wlc->corestate->macstat_snapshot == NULL) { ++ *err = 1027; ++ goto fail; ++ } ++ ++ return wlc; ++ ++ fail: ++ brcms_c_detach_mfree(wlc); ++ return NULL; ++} ++ ++/* ++ * Update the slot timing for standard 11b/g (20us slots) ++ * or shortslot 11g (9us slots) ++ * The PSM needs to be suspended for this call. ++ */ ++static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw, ++ bool shortslot) ++{ ++ struct d11regs __iomem *regs; ++ ++ regs = wlc_hw->regs; ++ ++ if (shortslot) { ++ /* 11g short slot: 11a timing */ ++ W_REG(®s->ifs_slot, 0x0207); /* APHY_SLOT_TIME */ ++ brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME); ++ } else { ++ /* 11g long slot: 11b timing */ ++ W_REG(®s->ifs_slot, 0x0212); /* BPHY_SLOT_TIME */ ++ brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME); ++ } ++} ++ ++/* ++ * calculate frame duration of a given rate and length, return ++ * time in usec unit ++ */ ++uint ++brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec, ++ u8 preamble_type, uint mac_len) ++{ ++ uint nsyms, dur = 0, Ndps, kNdps; ++ uint rate = rspec2rate(ratespec); ++ ++ if (rate == 0) { ++ wiphy_err(wlc->wiphy, "wl%d: WAR: using rate of 1 mbps\n", ++ wlc->pub->unit); ++ rate = BRCM_RATE_1M; ++ } ++ ++ BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, len%d\n", ++ wlc->pub->unit, ratespec, preamble_type, mac_len); ++ ++ if (is_mcs_rate(ratespec)) { ++ uint mcs = ratespec & RSPEC_RATE_MASK; ++ int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec); ++ ++ dur = PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT); ++ if (preamble_type == BRCMS_MM_PREAMBLE) ++ dur += PREN_MM_EXT; ++ /* 1000Ndbps = kbps * 4 */ ++ kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec), ++ rspec_issgi(ratespec)) * 4; ++ ++ if (rspec_stc(ratespec) == 0) ++ nsyms = ++ CEIL((APHY_SERVICE_NBITS + 8 * mac_len + ++ APHY_TAIL_NBITS) * 1000, kNdps); ++ else ++ /* STBC needs to have even number of symbols */ ++ nsyms = ++ 2 * ++ CEIL((APHY_SERVICE_NBITS + 8 * mac_len + ++ APHY_TAIL_NBITS) * 1000, 2 * kNdps); ++ ++ dur += APHY_SYMBOL_TIME * nsyms; ++ if (wlc->band->bandtype == BRCM_BAND_2G) ++ dur += DOT11_OFDM_SIGNAL_EXTENSION; ++ } else if (is_ofdm_rate(rate)) { ++ dur = APHY_PREAMBLE_TIME; ++ dur += APHY_SIGNAL_TIME; ++ /* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */ ++ Ndps = rate * 2; ++ /* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */ ++ nsyms = ++ CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS), ++ Ndps); ++ dur += APHY_SYMBOL_TIME * nsyms; ++ if (wlc->band->bandtype == BRCM_BAND_2G) ++ dur += DOT11_OFDM_SIGNAL_EXTENSION; ++ } else { ++ /* ++ * calc # bits * 2 so factor of 2 in rate (1/2 mbps) ++ * will divide out ++ */ ++ mac_len = mac_len * 8 * 2; ++ /* calc ceiling of bits/rate = microseconds of air time */ ++ dur = (mac_len + rate - 1) / rate; ++ if (preamble_type & BRCMS_SHORT_PREAMBLE) ++ dur += BPHY_PLCP_SHORT_TIME; ++ else ++ dur += BPHY_PLCP_TIME; ++ } ++ return dur; ++} ++ ++static void brcms_c_write_inits(struct brcms_hardware *wlc_hw, ++ const struct d11init *inits) ++{ ++ int i; ++ u8 __iomem *base; ++ u8 __iomem *addr; ++ u16 size; ++ u32 value; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ base = (u8 __iomem *)wlc_hw->regs; ++ ++ for (i = 0; inits[i].addr != cpu_to_le16(0xffff); i++) { ++ size = le16_to_cpu(inits[i].size); ++ addr = base + le16_to_cpu(inits[i].addr); ++ value = le32_to_cpu(inits[i].value); ++ if (size == 2) ++ W_REG((u16 __iomem *)addr, value); ++ else if (size == 4) ++ W_REG((u32 __iomem *)addr, value); ++ else ++ break; ++ } ++} ++ ++static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs) ++{ ++ u8 idx; ++ u16 addr[] = { ++ M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4, ++ M_HOST_FLAGS5 ++ }; ++ ++ for (idx = 0; idx < MHFMAX; idx++) ++ brcms_b_write_shm(wlc_hw, addr[idx], mhfs[idx]); ++} ++ ++static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw) ++{ ++ struct wiphy *wiphy = wlc_hw->wlc->wiphy; ++ struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode; ++ ++ /* init microcode host flags */ ++ brcms_c_write_mhf(wlc_hw, wlc_hw->band->mhfs); ++ ++ /* do band-specific ucode IHR, SHM, and SCR inits */ ++ if (D11REV_IS(wlc_hw->corerev, 23)) { ++ if (BRCMS_ISNPHY(wlc_hw->band)) ++ brcms_c_write_inits(wlc_hw, ucode->d11n0bsinitvals16); ++ else ++ wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" ++ " %d\n", __func__, wlc_hw->unit, ++ wlc_hw->corerev); ++ } else { ++ if (D11REV_IS(wlc_hw->corerev, 24)) { ++ if (BRCMS_ISLCNPHY(wlc_hw->band)) ++ brcms_c_write_inits(wlc_hw, ++ ucode->d11lcn0bsinitvals24); ++ else ++ wiphy_err(wiphy, "%s: wl%d: unsupported phy in" ++ " core rev %d\n", __func__, ++ wlc_hw->unit, wlc_hw->corerev); ++ } else { ++ wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n", ++ __func__, wlc_hw->unit, wlc_hw->corerev); ++ } ++ } ++} ++ ++static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk) ++{ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: clk %d\n", wlc_hw->unit, clk); ++ ++ wlc_hw->phyclk = clk; ++ ++ if (OFF == clk) { /* clear gmode bit, put phy into reset */ ++ ++ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC | SICF_GMODE), ++ (SICF_PRST | SICF_FGC)); ++ udelay(1); ++ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_PRST); ++ udelay(1); ++ ++ } else { /* take phy out of reset */ ++ ++ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_FGC); ++ udelay(1); ++ ai_core_cflags(wlc_hw->sih, (SICF_FGC), 0); ++ udelay(1); ++ ++ } ++} ++ ++/* low-level band switch utility routine */ ++static void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit) ++{ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, ++ bandunit); ++ ++ wlc_hw->band = wlc_hw->bandstate[bandunit]; ++ ++ /* ++ * BMAC_NOTE: ++ * until we eliminate need for wlc->band refs in low level code ++ */ ++ wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit]; ++ ++ /* set gmode core flag */ ++ if (wlc_hw->sbclk && !wlc_hw->noreset) ++ ai_core_cflags(wlc_hw->sih, SICF_GMODE, ++ ((bandunit == 0) ? SICF_GMODE : 0)); ++} ++ ++/* switch to new band but leave it inactive */ ++static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ u32 macintmask; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0); ++ ++ /* disable interrupts */ ++ macintmask = brcms_intrsoff(wlc->wl); ++ ++ /* radio off */ ++ wlc_phy_switch_radio(wlc_hw->band->pi, OFF); ++ ++ brcms_b_core_phy_clk(wlc_hw, OFF); ++ ++ brcms_c_setxband(wlc_hw, bandunit); ++ ++ return macintmask; ++} ++ ++/* process an individual struct tx_status */ ++static bool ++brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs) ++{ ++ struct sk_buff *p; ++ uint queue; ++ struct d11txh *txh; ++ struct scb *scb = NULL; ++ bool free_pdu; ++ int tx_rts, tx_frame_count, tx_rts_count; ++ uint totlen, supr_status; ++ bool lastframe; ++ struct ieee80211_hdr *h; ++ u16 mcl; ++ struct ieee80211_tx_info *tx_info; ++ struct ieee80211_tx_rate *txrate; ++ int i; ++ ++ /* discard intermediate indications for ucode with one legitimate case: ++ * e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, ++ * but the subsequent tx of DATA failed. so it will start rts/cts ++ * from the beginning (resetting the rts transmission count) ++ */ ++ if (!(txs->status & TX_STATUS_AMPDU) ++ && (txs->status & TX_STATUS_INTERMEDIATE)) { ++ wiphy_err(wlc->wiphy, "%s: INTERMEDIATE but not AMPDU\n", ++ __func__); ++ return false; ++ } ++ ++ queue = txs->frameid & TXFID_QUEUE_MASK; ++ if (queue >= NFIFO) { ++ p = NULL; ++ goto fatal; ++ } ++ ++ p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED); ++ if (p == NULL) ++ goto fatal; ++ ++ txh = (struct d11txh *) (p->data); ++ mcl = le16_to_cpu(txh->MacTxControlLow); ++ ++ if (txs->phyerr) { ++ if (brcm_msg_level & LOG_ERROR_VAL) { ++ wiphy_err(wlc->wiphy, "phyerr 0x%x, rate 0x%x\n", ++ txs->phyerr, txh->MainRates); ++ brcms_c_print_txdesc(txh); ++ } ++ brcms_c_print_txstatus(txs); ++ } ++ ++ if (txs->frameid != le16_to_cpu(txh->TxFrameID)) ++ goto fatal; ++ tx_info = IEEE80211_SKB_CB(p); ++ h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN); ++ ++ if (tx_info->control.sta) ++ scb = &wlc->pri_scb; ++ ++ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { ++ brcms_c_ampdu_dotxstatus(wlc->ampdu, scb, p, txs); ++ return false; ++ } ++ ++ supr_status = txs->status & TX_STATUS_SUPR_MASK; ++ if (supr_status == TX_STATUS_SUPR_BADCH) ++ BCMMSG(wlc->wiphy, ++ "%s: Pkt tx suppressed, possibly channel %d\n", ++ __func__, CHSPEC_CHANNEL(wlc->default_bss->chanspec)); ++ ++ tx_rts = le16_to_cpu(txh->MacTxControlLow) & TXC_SENDRTS; ++ tx_frame_count = ++ (txs->status & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT; ++ tx_rts_count = ++ (txs->status & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT; ++ ++ lastframe = !ieee80211_has_morefrags(h->frame_control); ++ ++ if (!lastframe) { ++ wiphy_err(wlc->wiphy, "Not last frame!\n"); ++ } else { ++ /* ++ * Set information to be consumed by Minstrel ht. ++ * ++ * The "fallback limit" is the number of tx attempts a given ++ * MPDU is sent at the "primary" rate. Tx attempts beyond that ++ * limit are sent at the "secondary" rate. ++ * A 'short frame' does not exceed RTS treshold. ++ */ ++ u16 sfbl, /* Short Frame Rate Fallback Limit */ ++ lfbl, /* Long Frame Rate Fallback Limit */ ++ fbl; ++ ++ if (queue < AC_COUNT) { ++ sfbl = GFIELD(wlc->wme_retries[wme_fifo2ac[queue]], ++ EDCF_SFB); ++ lfbl = GFIELD(wlc->wme_retries[wme_fifo2ac[queue]], ++ EDCF_LFB); ++ } else { ++ sfbl = wlc->SFBL; ++ lfbl = wlc->LFBL; ++ } ++ ++ txrate = tx_info->status.rates; ++ if (txrate[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ++ fbl = lfbl; ++ else ++ fbl = sfbl; ++ ++ ieee80211_tx_info_clear_status(tx_info); ++ ++ if ((tx_frame_count > fbl) && (txrate[1].idx >= 0)) { ++ /* ++ * rate selection requested a fallback rate ++ * and we used it ++ */ ++ txrate[0].count = fbl; ++ txrate[1].count = tx_frame_count - fbl; ++ } else { ++ /* ++ * rate selection did not request fallback rate, or ++ * we didn't need it ++ */ ++ txrate[0].count = tx_frame_count; ++ /* ++ * rc80211_minstrel.c:minstrel_tx_status() expects ++ * unused rates to be marked with idx = -1 ++ */ ++ txrate[1].idx = -1; ++ txrate[1].count = 0; ++ } ++ ++ /* clear the rest of the rates */ ++ for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) { ++ txrate[i].idx = -1; ++ txrate[i].count = 0; ++ } ++ ++ if (txs->status & TX_STATUS_ACK_RCV) ++ tx_info->flags |= IEEE80211_TX_STAT_ACK; ++ } ++ ++ totlen = brcmu_pkttotlen(p); ++ free_pdu = true; ++ ++ brcms_c_txfifo_complete(wlc, queue, 1); ++ ++ if (lastframe) { ++ p->next = NULL; ++ p->prev = NULL; ++ /* remove PLCP & Broadcom tx descriptor header */ ++ skb_pull(p, D11_PHY_HDR_LEN); ++ skb_pull(p, D11_TXH_LEN); ++ ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, p); ++ } else { ++ wiphy_err(wlc->wiphy, "%s: Not last frame => not calling " ++ "tx_status\n", __func__); ++ } ++ ++ return false; ++ ++ fatal: ++ if (p) ++ brcmu_pkt_buf_free_skb(p); ++ ++ return true; ++ ++} ++ ++/* process tx completion events in BMAC ++ * Return true if more tx status need to be processed. false otherwise. ++ */ ++static bool ++brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) ++{ ++ bool morepending = false; ++ struct brcms_c_info *wlc = wlc_hw->wlc; ++ struct d11regs __iomem *regs; ++ struct tx_status txstatus, *txs; ++ u32 s1, s2; ++ uint n = 0; ++ /* ++ * Param 'max_tx_num' indicates max. # tx status to process before ++ * break out. ++ */ ++ uint max_tx_num = bound ? TXSBND : -1; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ txs = &txstatus; ++ regs = wlc_hw->regs; ++ *fatal = false; ++ while (!(*fatal) ++ && (s1 = R_REG(®s->frmtxstatus)) & TXS_V) { ++ ++ if (s1 == 0xffffffff) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", ++ wlc_hw->unit, __func__); ++ return morepending; ++ } ++ ++ s2 = R_REG(®s->frmtxstatus2); ++ ++ txs->status = s1 & TXS_STATUS_MASK; ++ txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT; ++ txs->sequence = s2 & TXS_SEQ_MASK; ++ txs->phyerr = (s2 & TXS_PTX_MASK) >> TXS_PTX_SHIFT; ++ txs->lasttxtime = 0; ++ ++ *fatal = brcms_c_dotxstatus(wlc_hw->wlc, txs); ++ ++ /* !give others some time to run! */ ++ if (++n >= max_tx_num) ++ break; ++ } ++ ++ if (*fatal) ++ return 0; ++ ++ if (n >= max_tx_num) ++ morepending = true; ++ ++ if (!pktq_empty(&wlc->pkt_queue->q)) ++ brcms_c_send_q(wlc); ++ ++ return morepending; ++} ++ ++static void brcms_c_tbtt(struct brcms_c_info *wlc) ++{ ++ if (!wlc->bsscfg->BSS) ++ /* ++ * DirFrmQ is now valid...defer setting until end ++ * of ATIM window ++ */ ++ wlc->qvalid |= MCMD_DIRFRMQVAL; ++} ++ ++/* set initial host flags value */ ++static void ++brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ ++ memset(mhfs, 0, MHFMAX * sizeof(u16)); ++ ++ mhfs[MHF2] |= mhf2_init; ++ ++ /* prohibit use of slowclock on multifunction boards */ ++ if (wlc_hw->boardflags & BFL_NOPLLDOWN) ++ mhfs[MHF1] |= MHF1_FORCEFASTCLK; ++ ++ if (BRCMS_ISNPHY(wlc_hw->band) && NREV_LT(wlc_hw->band->phyrev, 2)) { ++ mhfs[MHF2] |= MHF2_NPHY40MHZ_WAR; ++ mhfs[MHF1] |= MHF1_IQSWAP_WAR; ++ } ++} ++ ++static struct dma64regs __iomem * ++dmareg(struct brcms_hardware *hw, uint direction, uint fifonum) ++{ ++ if (direction == DMA_TX) ++ return &(hw->regs->fifo64regs[fifonum].dmaxmt); ++ return &(hw->regs->fifo64regs[fifonum].dmarcv); ++} ++ ++static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme) ++{ ++ uint i; ++ char name[8]; ++ /* ++ * ucode host flag 2 needed for pio mode, independent of band and fifo ++ */ ++ u16 pio_mhf2 = 0; ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ uint unit = wlc_hw->unit; ++ struct wiphy *wiphy = wlc->wiphy; ++ ++ /* name and offsets for dma_attach */ ++ snprintf(name, sizeof(name), "wl%d", unit); ++ ++ if (wlc_hw->di[0] == NULL) { /* Init FIFOs */ ++ int dma_attach_err = 0; ++ ++ /* ++ * FIFO 0 ++ * TX: TX_AC_BK_FIFO (TX AC Background data packets) ++ * RX: RX_FIFO (RX data packets) ++ */ ++ wlc_hw->di[0] = dma_attach(name, wlc_hw->sih, ++ (wme ? dmareg(wlc_hw, DMA_TX, 0) : ++ NULL), dmareg(wlc_hw, DMA_RX, 0), ++ (wme ? NTXD : 0), NRXD, ++ RXBUFSZ, -1, NRXBUFPOST, ++ BRCMS_HWRXOFF, &brcm_msg_level); ++ dma_attach_err |= (NULL == wlc_hw->di[0]); ++ ++ /* ++ * FIFO 1 ++ * TX: TX_AC_BE_FIFO (TX AC Best-Effort data packets) ++ * (legacy) TX_DATA_FIFO (TX data packets) ++ * RX: UNUSED ++ */ ++ wlc_hw->di[1] = dma_attach(name, wlc_hw->sih, ++ dmareg(wlc_hw, DMA_TX, 1), NULL, ++ NTXD, 0, 0, -1, 0, 0, ++ &brcm_msg_level); ++ dma_attach_err |= (NULL == wlc_hw->di[1]); ++ ++ /* ++ * FIFO 2 ++ * TX: TX_AC_VI_FIFO (TX AC Video data packets) ++ * RX: UNUSED ++ */ ++ wlc_hw->di[2] = dma_attach(name, wlc_hw->sih, ++ dmareg(wlc_hw, DMA_TX, 2), NULL, ++ NTXD, 0, 0, -1, 0, 0, ++ &brcm_msg_level); ++ dma_attach_err |= (NULL == wlc_hw->di[2]); ++ /* ++ * FIFO 3 ++ * TX: TX_AC_VO_FIFO (TX AC Voice data packets) ++ * (legacy) TX_CTL_FIFO (TX control & mgmt packets) ++ */ ++ wlc_hw->di[3] = dma_attach(name, wlc_hw->sih, ++ dmareg(wlc_hw, DMA_TX, 3), ++ NULL, NTXD, 0, 0, -1, ++ 0, 0, &brcm_msg_level); ++ dma_attach_err |= (NULL == wlc_hw->di[3]); ++/* Cleaner to leave this as if with AP defined */ ++ ++ if (dma_attach_err) { ++ wiphy_err(wiphy, "wl%d: wlc_attach: dma_attach failed" ++ "\n", unit); ++ return false; ++ } ++ ++ /* get pointer to dma engine tx flow control variable */ ++ for (i = 0; i < NFIFO; i++) ++ if (wlc_hw->di[i]) ++ wlc_hw->txavail[i] = ++ (uint *) dma_getvar(wlc_hw->di[i], ++ "&txavail"); ++ } ++ ++ /* initial ucode host flags */ ++ brcms_c_mhfdef(wlc, wlc_hw->band->mhfs, pio_mhf2); ++ ++ return true; ++} ++ ++static void brcms_b_detach_dmapio(struct brcms_hardware *wlc_hw) ++{ ++ uint j; ++ ++ for (j = 0; j < NFIFO; j++) { ++ if (wlc_hw->di[j]) { ++ dma_detach(wlc_hw->di[j]); ++ wlc_hw->di[j] = NULL; ++ } ++ } ++} ++ ++/* ++ * Initialize brcms_c_info default values ... ++ * may get overrides later in this function ++ * BMAC_NOTES, move low out and resolve the dangling ones ++ */ ++static void brcms_b_info_init(struct brcms_hardware *wlc_hw) ++{ ++ struct brcms_c_info *wlc = wlc_hw->wlc; ++ ++ /* set default sw macintmask value */ ++ wlc->defmacintmask = DEF_MACINTMASK; ++ ++ /* various 802.11g modes */ ++ wlc_hw->shortslot = false; ++ ++ wlc_hw->SFBL = RETRY_SHORT_FB; ++ wlc_hw->LFBL = RETRY_LONG_FB; ++ ++ /* default mac retry limits */ ++ wlc_hw->SRL = RETRY_SHORT_DEF; ++ wlc_hw->LRL = RETRY_LONG_DEF; ++ wlc_hw->chanspec = ch20mhz_chspec(1); ++} ++ ++static void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw) ++{ ++ /* delay before first read of ucode state */ ++ udelay(40); ++ ++ /* wait until ucode is no longer asleep */ ++ SPINWAIT((brcms_b_read_shm(wlc_hw, M_UCODE_DBGST) == ++ DBGST_ASLEEP), wlc_hw->wlc->fastpwrup_dly); ++} ++ ++/* control chip clock to save power, enable dynamic clock or force fast clock */ ++static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode) ++{ ++ if (wlc_hw->sih->cccaps & CC_CAP_PMU) { ++ /* new chips with PMU, CCS_FORCEHT will distribute the HT clock ++ * on backplane, but mac core will still run on ALP(not HT) when ++ * it enters powersave mode, which means the FCA bit may not be ++ * set. Should wakeup mac if driver wants it to run on HT. ++ */ ++ ++ if (wlc_hw->clk) { ++ if (mode == CLK_FAST) { ++ OR_REG(&wlc_hw->regs->clk_ctl_st, ++ CCS_FORCEHT); ++ ++ udelay(64); ++ ++ SPINWAIT(((R_REG ++ (&wlc_hw->regs-> ++ clk_ctl_st) & CCS_HTAVAIL) == 0), ++ PMU_MAX_TRANSITION_DLY); ++ WARN_ON(!(R_REG ++ (&wlc_hw->regs-> ++ clk_ctl_st) & CCS_HTAVAIL)); ++ } else { ++ if ((wlc_hw->sih->pmurev == 0) && ++ (R_REG ++ (&wlc_hw->regs-> ++ clk_ctl_st) & (CCS_FORCEHT | CCS_HTAREQ))) ++ SPINWAIT(((R_REG ++ (&wlc_hw->regs-> ++ clk_ctl_st) & CCS_HTAVAIL) ++ == 0), ++ PMU_MAX_TRANSITION_DLY); ++ AND_REG(&wlc_hw->regs->clk_ctl_st, ++ ~CCS_FORCEHT); ++ } ++ } ++ wlc_hw->forcefastclk = (mode == CLK_FAST); ++ } else { ++ ++ /* old chips w/o PMU, force HT through cc, ++ * then use FCA to verify mac is running fast clock ++ */ ++ ++ wlc_hw->forcefastclk = ai_clkctl_cc(wlc_hw->sih, mode); ++ ++ /* check fast clock is available (if core is not in reset) */ ++ if (wlc_hw->forcefastclk && wlc_hw->clk) ++ WARN_ON(!(ai_core_sflags(wlc_hw->sih, 0, 0) & ++ SISF_FCLKA)); ++ ++ /* ++ * keep the ucode wake bit on if forcefastclk is on since we ++ * do not want ucode to put us back to slow clock when it dozes ++ * for PM mode. Code below matches the wake override bit with ++ * current forcefastclk state. Only setting bit in wake_override ++ * instead of waking ucode immediately since old code had this ++ * behavior. Older code set wlc->forcefastclk but only had the ++ * wake happen if the wakup_ucode work (protected by an up ++ * check) was executed just below. ++ */ ++ if (wlc_hw->forcefastclk) ++ mboolset(wlc_hw->wake_override, ++ BRCMS_WAKE_OVERRIDE_FORCEFAST); ++ else ++ mboolclr(wlc_hw->wake_override, ++ BRCMS_WAKE_OVERRIDE_FORCEFAST); ++ } ++} ++ ++/* set or clear ucode host flag bits ++ * it has an optimization for no-change write ++ * it only writes through shared memory when the core has clock; ++ * pre-CLK changes should use wlc_write_mhf to get around the optimization ++ * ++ * ++ * bands values are: BRCM_BAND_AUTO <--- Current band only ++ * BRCM_BAND_5G <--- 5G band only ++ * BRCM_BAND_2G <--- 2G band only ++ * BRCM_BAND_ALL <--- All bands ++ */ ++void ++brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, u16 val, ++ int bands) ++{ ++ u16 save; ++ u16 addr[MHFMAX] = { ++ M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4, ++ M_HOST_FLAGS5 ++ }; ++ struct brcms_hw_band *band; ++ ++ if ((val & ~mask) || idx >= MHFMAX) ++ return; /* error condition */ ++ ++ switch (bands) { ++ /* Current band only or all bands, ++ * then set the band to current band ++ */ ++ case BRCM_BAND_AUTO: ++ case BRCM_BAND_ALL: ++ band = wlc_hw->band; ++ break; ++ case BRCM_BAND_5G: ++ band = wlc_hw->bandstate[BAND_5G_INDEX]; ++ break; ++ case BRCM_BAND_2G: ++ band = wlc_hw->bandstate[BAND_2G_INDEX]; ++ break; ++ default: ++ band = NULL; /* error condition */ ++ } ++ ++ if (band) { ++ save = band->mhfs[idx]; ++ band->mhfs[idx] = (band->mhfs[idx] & ~mask) | val; ++ ++ /* optimization: only write through if changed, and ++ * changed band is the current band ++ */ ++ if (wlc_hw->clk && (band->mhfs[idx] != save) ++ && (band == wlc_hw->band)) ++ brcms_b_write_shm(wlc_hw, addr[idx], ++ (u16) band->mhfs[idx]); ++ } ++ ++ if (bands == BRCM_BAND_ALL) { ++ wlc_hw->bandstate[0]->mhfs[idx] = ++ (wlc_hw->bandstate[0]->mhfs[idx] & ~mask) | val; ++ wlc_hw->bandstate[1]->mhfs[idx] = ++ (wlc_hw->bandstate[1]->mhfs[idx] & ~mask) | val; ++ } ++} ++ ++/* set the maccontrol register to desired reset state and ++ * initialize the sw cache of the register ++ */ ++static void brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw) ++{ ++ /* IHR accesses are always enabled, PSM disabled, HPS off and WAKE on */ ++ wlc_hw->maccontrol = 0; ++ wlc_hw->suspended_fifos = 0; ++ wlc_hw->wake_override = 0; ++ wlc_hw->mute_override = 0; ++ brcms_b_mctrl(wlc_hw, ~0, MCTL_IHR_EN | MCTL_WAKE); ++} ++ ++/* ++ * write the software state of maccontrol and ++ * overrides to the maccontrol register ++ */ ++static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw) ++{ ++ u32 maccontrol = wlc_hw->maccontrol; ++ ++ /* OR in the wake bit if overridden */ ++ if (wlc_hw->wake_override) ++ maccontrol |= MCTL_WAKE; ++ ++ /* set AP and INFRA bits for mute if needed */ ++ if (wlc_hw->mute_override) { ++ maccontrol &= ~(MCTL_AP); ++ maccontrol |= MCTL_INFRA; ++ } ++ ++ W_REG(&wlc_hw->regs->maccontrol, maccontrol); ++} ++ ++/* set or clear maccontrol bits */ ++void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val) ++{ ++ u32 maccontrol; ++ u32 new_maccontrol; ++ ++ if (val & ~mask) ++ return; /* error condition */ ++ maccontrol = wlc_hw->maccontrol; ++ new_maccontrol = (maccontrol & ~mask) | val; ++ ++ /* if the new maccontrol value is the same as the old, nothing to do */ ++ if (new_maccontrol == maccontrol) ++ return; ++ ++ /* something changed, cache the new value */ ++ wlc_hw->maccontrol = new_maccontrol; ++ ++ /* write the new values with overrides applied */ ++ brcms_c_mctrl_write(wlc_hw); ++} ++ ++void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw, ++ u32 override_bit) ++{ ++ if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) { ++ mboolset(wlc_hw->wake_override, override_bit); ++ return; ++ } ++ ++ mboolset(wlc_hw->wake_override, override_bit); ++ ++ brcms_c_mctrl_write(wlc_hw); ++ brcms_b_wait_for_wake(wlc_hw); ++} ++ ++void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw, ++ u32 override_bit) ++{ ++ mboolclr(wlc_hw->wake_override, override_bit); ++ ++ if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) ++ return; ++ ++ brcms_c_mctrl_write(wlc_hw); ++} ++ ++/* When driver needs ucode to stop beaconing, it has to make sure that ++ * MCTL_AP is clear and MCTL_INFRA is set ++ * Mode MCTL_AP MCTL_INFRA ++ * AP 1 1 ++ * STA 0 1 <--- This will ensure no beacons ++ * IBSS 0 0 ++ */ ++static void brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw) ++{ ++ wlc_hw->mute_override = 1; ++ ++ /* if maccontrol already has AP == 0 and INFRA == 1 without this ++ * override, then there is no change to write ++ */ ++ if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA) ++ return; ++ ++ brcms_c_mctrl_write(wlc_hw); ++} ++ ++/* Clear the override on AP and INFRA bits */ ++static void brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw) ++{ ++ if (wlc_hw->mute_override == 0) ++ return; ++ ++ wlc_hw->mute_override = 0; ++ ++ /* if maccontrol already has AP == 0 and INFRA == 1 without this ++ * override, then there is no change to write ++ */ ++ if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA) ++ return; ++ ++ brcms_c_mctrl_write(wlc_hw); ++} ++ ++/* ++ * Write a MAC address to the given match reg offset in the RXE match engine. ++ */ ++static void ++brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset, ++ const u8 *addr) ++{ ++ struct d11regs __iomem *regs; ++ u16 mac_l; ++ u16 mac_m; ++ u16 mac_h; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: brcms_b_set_addrmatch\n", ++ wlc_hw->unit); ++ ++ regs = wlc_hw->regs; ++ mac_l = addr[0] | (addr[1] << 8); ++ mac_m = addr[2] | (addr[3] << 8); ++ mac_h = addr[4] | (addr[5] << 8); ++ ++ /* enter the MAC addr into the RXE match registers */ ++ W_REG(®s->rcm_ctl, RCM_INC_DATA | match_reg_offset); ++ W_REG(®s->rcm_mat_data, mac_l); ++ W_REG(®s->rcm_mat_data, mac_m); ++ W_REG(®s->rcm_mat_data, mac_h); ++ ++} ++ ++void ++brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len, ++ void *buf) ++{ ++ struct d11regs __iomem *regs; ++ u32 word; ++ __le32 word_le; ++ __be32 word_be; ++ bool be_bit; ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ regs = wlc_hw->regs; ++ W_REG(®s->tplatewrptr, offset); ++ ++ /* if MCTL_BIGEND bit set in mac control register, ++ * the chip swaps data in fifo, as well as data in ++ * template ram ++ */ ++ be_bit = (R_REG(®s->maccontrol) & MCTL_BIGEND) != 0; ++ ++ while (len > 0) { ++ memcpy(&word, buf, sizeof(u32)); ++ ++ if (be_bit) { ++ word_be = cpu_to_be32(word); ++ word = *(u32 *)&word_be; ++ } else { ++ word_le = cpu_to_le32(word); ++ word = *(u32 *)&word_le; ++ } ++ ++ W_REG(®s->tplatewrdata, word); ++ ++ buf = (u8 *) buf + sizeof(u32); ++ len -= sizeof(u32); ++ } ++} ++ ++static void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin) ++{ ++ wlc_hw->band->CWmin = newmin; ++ ++ W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMIN); ++ (void)R_REG(&wlc_hw->regs->objaddr); ++ W_REG(&wlc_hw->regs->objdata, newmin); ++} ++ ++static void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax) ++{ ++ wlc_hw->band->CWmax = newmax; ++ ++ W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMAX); ++ (void)R_REG(&wlc_hw->regs->objaddr); ++ W_REG(&wlc_hw->regs->objdata, newmax); ++} ++ ++void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw) ++{ ++ bool fastclk; ++ ++ /* request FAST clock if not on */ ++ fastclk = wlc_hw->forcefastclk; ++ if (!fastclk) ++ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); ++ ++ wlc_phy_bw_state_set(wlc_hw->band->pi, bw); ++ ++ brcms_b_phy_reset(wlc_hw); ++ wlc_phy_init(wlc_hw->band->pi, wlc_phy_chanspec_get(wlc_hw->band->pi)); ++ ++ /* restore the clk */ ++ if (!fastclk) ++ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); ++} ++ ++static void brcms_b_upd_synthpu(struct brcms_hardware *wlc_hw) ++{ ++ u16 v; ++ struct brcms_c_info *wlc = wlc_hw->wlc; ++ /* update SYNTHPU_DLY */ ++ ++ if (BRCMS_ISLCNPHY(wlc->band)) ++ v = SYNTHPU_DLY_LPPHY_US; ++ else if (BRCMS_ISNPHY(wlc->band) && (NREV_GE(wlc->band->phyrev, 3))) ++ v = SYNTHPU_DLY_NPHY_US; ++ else ++ v = SYNTHPU_DLY_BPHY_US; ++ ++ brcms_b_write_shm(wlc_hw, M_SYNTHPU_DLY, v); ++} ++ ++static void brcms_c_ucode_txant_set(struct brcms_hardware *wlc_hw) ++{ ++ u16 phyctl; ++ u16 phytxant = wlc_hw->bmac_phytxant; ++ u16 mask = PHY_TXC_ANT_MASK; ++ ++ /* set the Probe Response frame phy control word */ ++ phyctl = brcms_b_read_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS); ++ phyctl = (phyctl & ~mask) | phytxant; ++ brcms_b_write_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS, phyctl); ++ ++ /* set the Response (ACK/CTS) frame phy control word */ ++ phyctl = brcms_b_read_shm(wlc_hw, M_RSP_PCTLWD); ++ phyctl = (phyctl & ~mask) | phytxant; ++ brcms_b_write_shm(wlc_hw, M_RSP_PCTLWD, phyctl); ++} ++ ++static u16 brcms_b_ofdm_ratetable_offset(struct brcms_hardware *wlc_hw, ++ u8 rate) ++{ ++ uint i; ++ u8 plcp_rate = 0; ++ struct plcp_signal_rate_lookup { ++ u8 rate; ++ u8 signal_rate; ++ }; ++ /* OFDM RATE sub-field of PLCP SIGNAL field, per 802.11 sec 17.3.4.1 */ ++ const struct plcp_signal_rate_lookup rate_lookup[] = { ++ {BRCM_RATE_6M, 0xB}, ++ {BRCM_RATE_9M, 0xF}, ++ {BRCM_RATE_12M, 0xA}, ++ {BRCM_RATE_18M, 0xE}, ++ {BRCM_RATE_24M, 0x9}, ++ {BRCM_RATE_36M, 0xD}, ++ {BRCM_RATE_48M, 0x8}, ++ {BRCM_RATE_54M, 0xC} ++ }; ++ ++ for (i = 0; i < ARRAY_SIZE(rate_lookup); i++) { ++ if (rate == rate_lookup[i].rate) { ++ plcp_rate = rate_lookup[i].signal_rate; ++ break; ++ } ++ } ++ ++ /* Find the SHM pointer to the rate table entry by looking in the ++ * Direct-map Table ++ */ ++ return 2 * brcms_b_read_shm(wlc_hw, M_RT_DIRMAP_A + (plcp_rate * 2)); ++} ++ ++static void brcms_upd_ofdm_pctl1_table(struct brcms_hardware *wlc_hw) ++{ ++ u8 rate; ++ u8 rates[8] = { ++ BRCM_RATE_6M, BRCM_RATE_9M, BRCM_RATE_12M, BRCM_RATE_18M, ++ BRCM_RATE_24M, BRCM_RATE_36M, BRCM_RATE_48M, BRCM_RATE_54M ++ }; ++ u16 entry_ptr; ++ u16 pctl1; ++ uint i; ++ ++ if (!BRCMS_PHY_11N_CAP(wlc_hw->band)) ++ return; ++ ++ /* walk the phy rate table and update the entries */ ++ for (i = 0; i < ARRAY_SIZE(rates); i++) { ++ rate = rates[i]; ++ ++ entry_ptr = brcms_b_ofdm_ratetable_offset(wlc_hw, rate); ++ ++ /* read the SHM Rate Table entry OFDM PCTL1 values */ ++ pctl1 = ++ brcms_b_read_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS); ++ ++ /* modify the value */ ++ pctl1 &= ~PHY_TXC1_MODE_MASK; ++ pctl1 |= (wlc_hw->hw_stf_ss_opmode << PHY_TXC1_MODE_SHIFT); ++ ++ /* Update the SHM Rate Table entry OFDM PCTL1 values */ ++ brcms_b_write_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS, ++ pctl1); ++ } ++} ++ ++/* band-specific init */ ++static void brcms_b_bsinit(struct brcms_c_info *wlc, u16 chanspec) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ ++ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, ++ wlc_hw->band->bandunit); ++ ++ brcms_c_ucode_bsinit(wlc_hw); ++ ++ wlc_phy_init(wlc_hw->band->pi, chanspec); ++ ++ brcms_c_ucode_txant_set(wlc_hw); ++ ++ /* ++ * cwmin is band-specific, update hardware ++ * with value for current band ++ */ ++ brcms_b_set_cwmin(wlc_hw, wlc_hw->band->CWmin); ++ brcms_b_set_cwmax(wlc_hw, wlc_hw->band->CWmax); ++ ++ brcms_b_update_slot_timing(wlc_hw, ++ wlc_hw->band->bandtype == BRCM_BAND_5G ? ++ true : wlc_hw->shortslot); ++ ++ /* write phytype and phyvers */ ++ brcms_b_write_shm(wlc_hw, M_PHYTYPE, (u16) wlc_hw->band->phytype); ++ brcms_b_write_shm(wlc_hw, M_PHYVER, (u16) wlc_hw->band->phyrev); ++ ++ /* ++ * initialize the txphyctl1 rate table since ++ * shmem is shared between bands ++ */ ++ brcms_upd_ofdm_pctl1_table(wlc_hw); ++ ++ brcms_b_upd_synthpu(wlc_hw); ++} ++ ++/* Perform a soft reset of the PHY PLL */ ++void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw) ++{ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ ai_corereg(wlc_hw->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_addr), ~0, 0); ++ udelay(1); ++ ai_corereg(wlc_hw->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_data), 0x4, 0); ++ udelay(1); ++ ai_corereg(wlc_hw->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_data), 0x4, 4); ++ udelay(1); ++ ai_corereg(wlc_hw->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_data), 0x4, 0); ++ udelay(1); ++} ++ ++/* light way to turn on phy clock without reset for NPHY only ++ * refer to brcms_b_core_phy_clk for full version ++ */ ++void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk) ++{ ++ /* support(necessary for NPHY and HYPHY) only */ ++ if (!BRCMS_ISNPHY(wlc_hw->band)) ++ return; ++ ++ if (ON == clk) ++ ai_core_cflags(wlc_hw->sih, SICF_FGC, SICF_FGC); ++ else ++ ai_core_cflags(wlc_hw->sih, SICF_FGC, 0); ++ ++} ++ ++void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk) ++{ ++ if (ON == clk) ++ ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, SICF_MPCLKE); ++ else ++ ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, 0); ++} ++ ++void brcms_b_phy_reset(struct brcms_hardware *wlc_hw) ++{ ++ struct brcms_phy_pub *pih = wlc_hw->band->pi; ++ u32 phy_bw_clkbits; ++ bool phy_in_reset = false; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ if (pih == NULL) ++ return; ++ ++ phy_bw_clkbits = wlc_phy_clk_bwbits(wlc_hw->band->pi); ++ ++ /* Specific reset sequence required for NPHY rev 3 and 4 */ ++ if (BRCMS_ISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) && ++ NREV_LE(wlc_hw->band->phyrev, 4)) { ++ /* Set the PHY bandwidth */ ++ ai_core_cflags(wlc_hw->sih, SICF_BWMASK, phy_bw_clkbits); ++ ++ udelay(1); ++ ++ /* Perform a soft reset of the PHY PLL */ ++ brcms_b_core_phypll_reset(wlc_hw); ++ ++ /* reset the PHY */ ++ ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_PCLKE), ++ (SICF_PRST | SICF_PCLKE)); ++ phy_in_reset = true; ++ } else { ++ ai_core_cflags(wlc_hw->sih, ++ (SICF_PRST | SICF_PCLKE | SICF_BWMASK), ++ (SICF_PRST | SICF_PCLKE | phy_bw_clkbits)); ++ } ++ ++ udelay(2); ++ brcms_b_core_phy_clk(wlc_hw, ON); ++ ++ if (pih) ++ wlc_phy_anacore(pih, ON); ++} ++ ++/* switch to and initialize new band */ ++static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit, ++ u16 chanspec) { ++ struct brcms_c_info *wlc = wlc_hw->wlc; ++ u32 macintmask; ++ ++ /* Enable the d11 core before accessing it */ ++ if (!ai_iscoreup(wlc_hw->sih)) { ++ ai_core_reset(wlc_hw->sih, 0, 0); ++ brcms_c_mctrl_reset(wlc_hw); ++ } ++ ++ macintmask = brcms_c_setband_inact(wlc, bandunit); ++ ++ if (!wlc_hw->up) ++ return; ++ ++ brcms_b_core_phy_clk(wlc_hw, ON); ++ ++ /* band-specific initializations */ ++ brcms_b_bsinit(wlc, chanspec); ++ ++ /* ++ * If there are any pending software interrupt bits, ++ * then replace these with a harmless nonzero value ++ * so brcms_c_dpc() will re-enable interrupts when done. ++ */ ++ if (wlc->macintstatus) ++ wlc->macintstatus = MI_DMAINT; ++ ++ /* restore macintmask */ ++ brcms_intrsrestore(wlc->wl, macintmask); ++ ++ /* ucode should still be suspended.. */ ++ WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0); ++} ++ ++static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw) ++{ ++ ++ /* reject unsupported corerev */ ++ if (!CONF_HAS(D11CONF, wlc_hw->corerev)) { ++ wiphy_err(wlc_hw->wlc->wiphy, "unsupported core rev %d\n", ++ wlc_hw->corerev); ++ return false; ++ } ++ ++ return true; ++} ++ ++/* Validate some board info parameters */ ++static bool brcms_c_validboardtype(struct brcms_hardware *wlc_hw) ++{ ++ uint boardrev = wlc_hw->boardrev; ++ ++ /* 4 bits each for board type, major, minor, and tiny version */ ++ uint brt = (boardrev & 0xf000) >> 12; ++ uint b0 = (boardrev & 0xf00) >> 8; ++ uint b1 = (boardrev & 0xf0) >> 4; ++ uint b2 = boardrev & 0xf; ++ ++ /* voards from other vendors are always considered valid */ ++ if (wlc_hw->sih->boardvendor != PCI_VENDOR_ID_BROADCOM) ++ return true; ++ ++ /* do some boardrev sanity checks when boardvendor is Broadcom */ ++ if (boardrev == 0) ++ return false; ++ ++ if (boardrev <= 0xff) ++ return true; ++ ++ if ((brt > 2) || (brt == 0) || (b0 > 9) || (b0 == 0) || (b1 > 9) ++ || (b2 > 9)) ++ return false; ++ ++ return true; ++} ++ ++static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw) ++{ ++ enum brcms_srom_id var_id = BRCMS_SROM_MACADDR; ++ char *macaddr; ++ ++ /* If macaddr exists, use it (Sromrev4, CIS, ...). */ ++ macaddr = getvar(wlc_hw->sih, var_id); ++ if (macaddr != NULL) ++ return macaddr; ++ ++ if (wlc_hw->_nbands > 1) ++ var_id = BRCMS_SROM_ET1MACADDR; ++ else ++ var_id = BRCMS_SROM_IL0MACADDR; ++ ++ macaddr = getvar(wlc_hw->sih, var_id); ++ if (macaddr == NULL) ++ wiphy_err(wlc_hw->wlc->wiphy, "wl%d: wlc_get_macaddr: macaddr " ++ "getvar(%d) not found\n", wlc_hw->unit, var_id); ++ ++ return macaddr; ++} ++ ++/* power both the pll and external oscillator on/off */ ++static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want) ++{ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: want %d\n", wlc_hw->unit, want); ++ ++ /* ++ * dont power down if plldown is false or ++ * we must poll hw radio disable ++ */ ++ if (!want && wlc_hw->pllreq) ++ return; ++ ++ if (wlc_hw->sih) ++ ai_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want); ++ ++ wlc_hw->sbclk = want; ++ if (!wlc_hw->sbclk) { ++ wlc_hw->clk = false; ++ if (wlc_hw->band && wlc_hw->band->pi) ++ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false); ++ } ++} ++ ++/* ++ * Return true if radio is disabled, otherwise false. ++ * hw radio disable signal is an external pin, users activate it asynchronously ++ * this function could be called when driver is down and w/o clock ++ * it operates on different registers depending on corerev and boardflag. ++ */ ++static bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw) ++{ ++ bool v, clk, xtal; ++ u32 resetbits = 0, flags = 0; ++ ++ xtal = wlc_hw->sbclk; ++ if (!xtal) ++ brcms_b_xtal(wlc_hw, ON); ++ ++ /* may need to take core out of reset first */ ++ clk = wlc_hw->clk; ++ if (!clk) { ++ /* ++ * mac no longer enables phyclk automatically when driver ++ * accesses phyreg throughput mac. This can be skipped since ++ * only mac reg is accessed below ++ */ ++ flags |= SICF_PCLKE; ++ ++ /* ++ * AI chip doesn't restore bar0win2 on ++ * hibernation/resume, need sw fixup ++ */ ++ if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || ++ (wlc_hw->sih->chip == BCM43225_CHIP_ID)) ++ wlc_hw->regs = (struct d11regs __iomem *) ++ ai_setcore(wlc_hw->sih, D11_CORE_ID, 0); ++ ai_core_reset(wlc_hw->sih, flags, resetbits); ++ brcms_c_mctrl_reset(wlc_hw); ++ } ++ ++ v = ((R_REG(&wlc_hw->regs->phydebug) & PDBG_RFD) != 0); ++ ++ /* put core back into reset */ ++ if (!clk) ++ ai_core_disable(wlc_hw->sih, 0); ++ ++ if (!xtal) ++ brcms_b_xtal(wlc_hw, OFF); ++ ++ return v; ++} ++ ++static bool wlc_dma_rxreset(struct brcms_hardware *wlc_hw, uint fifo) ++{ ++ struct dma_pub *di = wlc_hw->di[fifo]; ++ return dma_rxreset(di); ++} ++ ++/* d11 core reset ++ * ensure fask clock during reset ++ * reset dma ++ * reset d11(out of reset) ++ * reset phy(out of reset) ++ * clear software macintstatus for fresh new start ++ * one testing hack wlc_hw->noreset will bypass the d11/phy reset ++ */ ++void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) ++{ ++ struct d11regs __iomem *regs; ++ uint i; ++ bool fastclk; ++ u32 resetbits = 0; ++ ++ if (flags == BRCMS_USE_COREFLAGS) ++ flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0); ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ regs = wlc_hw->regs; ++ ++ /* request FAST clock if not on */ ++ fastclk = wlc_hw->forcefastclk; ++ if (!fastclk) ++ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); ++ ++ /* reset the dma engines except first time thru */ ++ if (ai_iscoreup(wlc_hw->sih)) { ++ for (i = 0; i < NFIFO; i++) ++ if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i]))) ++ wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: " ++ "dma_txreset[%d]: cannot stop dma\n", ++ wlc_hw->unit, __func__, i); ++ ++ if ((wlc_hw->di[RX_FIFO]) ++ && (!wlc_dma_rxreset(wlc_hw, RX_FIFO))) ++ wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: dma_rxreset" ++ "[%d]: cannot stop dma\n", ++ wlc_hw->unit, __func__, RX_FIFO); ++ } ++ /* if noreset, just stop the psm and return */ ++ if (wlc_hw->noreset) { ++ wlc_hw->wlc->macintstatus = 0; /* skip wl_dpc after down */ ++ brcms_b_mctrl(wlc_hw, MCTL_PSM_RUN | MCTL_EN_MAC, 0); ++ return; ++ } ++ ++ /* ++ * mac no longer enables phyclk automatically when driver accesses ++ * phyreg throughput mac, AND phy_reset is skipped at early stage when ++ * band->pi is invalid. need to enable PHY CLK ++ */ ++ flags |= SICF_PCLKE; ++ ++ /* ++ * reset the core ++ * In chips with PMU, the fastclk request goes through d11 core ++ * reg 0x1e0, which is cleared by the core_reset. have to re-request it. ++ * ++ * This adds some delay and we can optimize it by also requesting ++ * fastclk through chipcommon during this period if necessary. But ++ * that has to work coordinate with other driver like mips/arm since ++ * they may touch chipcommon as well. ++ */ ++ wlc_hw->clk = false; ++ ai_core_reset(wlc_hw->sih, flags, resetbits); ++ wlc_hw->clk = true; ++ if (wlc_hw->band && wlc_hw->band->pi) ++ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true); ++ ++ brcms_c_mctrl_reset(wlc_hw); ++ ++ if (wlc_hw->sih->cccaps & CC_CAP_PMU) ++ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); ++ ++ brcms_b_phy_reset(wlc_hw); ++ ++ /* turn on PHY_PLL */ ++ brcms_b_core_phypll_ctl(wlc_hw, true); ++ ++ /* clear sw intstatus */ ++ wlc_hw->wlc->macintstatus = 0; ++ ++ /* restore the clk setting */ ++ if (!fastclk) ++ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); ++} ++ ++/* txfifo sizes needs to be modified(increased) since the newer cores ++ * have more memory. ++ */ ++static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw) ++{ ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ u16 fifo_nu; ++ u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk; ++ u16 txfifo_def, txfifo_def1; ++ u16 txfifo_cmd; ++ ++ /* tx fifos start at TXFIFO_START_BLK from the Base address */ ++ txfifo_startblk = TXFIFO_START_BLK; ++ ++ /* sequence of operations: reset fifo, set fifo size, reset fifo */ ++ for (fifo_nu = 0; fifo_nu < NFIFO; fifo_nu++) { ++ ++ txfifo_endblk = txfifo_startblk + wlc_hw->xmtfifo_sz[fifo_nu]; ++ txfifo_def = (txfifo_startblk & 0xff) | ++ (((txfifo_endblk - 1) & 0xff) << TXFIFO_FIFOTOP_SHIFT); ++ txfifo_def1 = ((txfifo_startblk >> 8) & 0x1) | ++ ((((txfifo_endblk - ++ 1) >> 8) & 0x1) << TXFIFO_FIFOTOP_SHIFT); ++ txfifo_cmd = ++ TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT); ++ ++ W_REG(®s->xmtfifocmd, txfifo_cmd); ++ W_REG(®s->xmtfifodef, txfifo_def); ++ W_REG(®s->xmtfifodef1, txfifo_def1); ++ ++ W_REG(®s->xmtfifocmd, txfifo_cmd); ++ ++ txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu]; ++ } ++ /* ++ * need to propagate to shm location to be in sync since ucode/hw won't ++ * do this ++ */ ++ brcms_b_write_shm(wlc_hw, M_FIFOSIZE0, ++ wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]); ++ brcms_b_write_shm(wlc_hw, M_FIFOSIZE1, ++ wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]); ++ brcms_b_write_shm(wlc_hw, M_FIFOSIZE2, ++ ((wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO] << 8) | wlc_hw-> ++ xmtfifo_sz[TX_AC_BK_FIFO])); ++ brcms_b_write_shm(wlc_hw, M_FIFOSIZE3, ++ ((wlc_hw->xmtfifo_sz[TX_ATIM_FIFO] << 8) | wlc_hw-> ++ xmtfifo_sz[TX_BCMC_FIFO])); ++} ++ ++/* This function is used for changing the tsf frac register ++ * If spur avoidance mode is off, the mac freq will be 80/120/160Mhz ++ * If spur avoidance mode is on1, the mac freq will be 82/123/164Mhz ++ * If spur avoidance mode is on2, the mac freq will be 84/126/168Mhz ++ * HTPHY Formula is 2^26/freq(MHz) e.g. ++ * For spuron2 - 126MHz -> 2^26/126 = 532610.0 ++ * - 532610 = 0x82082 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x2082 ++ * For spuron: 123MHz -> 2^26/123 = 545600.5 ++ * - 545601 = 0x85341 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x5341 ++ * For spur off: 120MHz -> 2^26/120 = 559240.5 ++ * - 559241 = 0x88889 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x8889 ++ */ ++ ++void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode) ++{ ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ ++ if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || ++ (wlc_hw->sih->chip == BCM43225_CHIP_ID)) { ++ if (spurmode == WL_SPURAVOID_ON2) { /* 126Mhz */ ++ W_REG(®s->tsf_clk_frac_l, 0x2082); ++ W_REG(®s->tsf_clk_frac_h, 0x8); ++ } else if (spurmode == WL_SPURAVOID_ON1) { /* 123Mhz */ ++ W_REG(®s->tsf_clk_frac_l, 0x5341); ++ W_REG(®s->tsf_clk_frac_h, 0x8); ++ } else { /* 120Mhz */ ++ W_REG(®s->tsf_clk_frac_l, 0x8889); ++ W_REG(®s->tsf_clk_frac_h, 0x8); ++ } ++ } else if (BRCMS_ISLCNPHY(wlc_hw->band)) { ++ if (spurmode == WL_SPURAVOID_ON1) { /* 82Mhz */ ++ W_REG(®s->tsf_clk_frac_l, 0x7CE0); ++ W_REG(®s->tsf_clk_frac_h, 0xC); ++ } else { /* 80Mhz */ ++ W_REG(®s->tsf_clk_frac_l, 0xCCCD); ++ W_REG(®s->tsf_clk_frac_h, 0xC); ++ } ++ } ++} ++ ++/* Initialize GPIOs that are controlled by D11 core */ ++static void brcms_c_gpio_init(struct brcms_c_info *wlc) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ struct d11regs __iomem *regs; ++ u32 gc, gm; ++ ++ regs = wlc_hw->regs; ++ ++ /* use GPIO select 0 to get all gpio signals from the gpio out reg */ ++ brcms_b_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0); ++ ++ /* ++ * Common GPIO setup: ++ * G0 = LED 0 = WLAN Activity ++ * G1 = LED 1 = WLAN 2.4 GHz Radio State ++ * G2 = LED 2 = WLAN 5 GHz Radio State ++ * G4 = radio disable input (HI enabled, LO disabled) ++ */ ++ ++ gc = gm = 0; ++ ++ /* Allocate GPIOs for mimo antenna diversity feature */ ++ if (wlc_hw->antsel_type == ANTSEL_2x3) { ++ /* Enable antenna diversity, use 2x3 mode */ ++ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN, ++ MHF3_ANTSEL_EN, BRCM_BAND_ALL); ++ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, ++ MHF3_ANTSEL_MODE, BRCM_BAND_ALL); ++ ++ /* init superswitch control */ ++ wlc_phy_antsel_init(wlc_hw->band->pi, false); ++ ++ } else if (wlc_hw->antsel_type == ANTSEL_2x4) { ++ gm |= gc |= (BOARD_GPIO_12 | BOARD_GPIO_13); ++ /* ++ * The board itself is powered by these GPIOs ++ * (when not sending pattern) so set them high ++ */ ++ OR_REG(®s->psm_gpio_oe, ++ (BOARD_GPIO_12 | BOARD_GPIO_13)); ++ OR_REG(®s->psm_gpio_out, ++ (BOARD_GPIO_12 | BOARD_GPIO_13)); ++ ++ /* Enable antenna diversity, use 2x4 mode */ ++ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN, ++ MHF3_ANTSEL_EN, BRCM_BAND_ALL); ++ brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, 0, ++ BRCM_BAND_ALL); ++ ++ /* Configure the desired clock to be 4Mhz */ ++ brcms_b_write_shm(wlc_hw, M_ANTSEL_CLKDIV, ++ ANTSEL_CLKDIV_4MHZ); ++ } ++ ++ /* ++ * gpio 9 controls the PA. ucode is responsible ++ * for wiggling out and oe ++ */ ++ if (wlc_hw->boardflags & BFL_PACTRL) ++ gm |= gc |= BOARD_GPIO_PACTRL; ++ ++ /* apply to gpiocontrol register */ ++ ai_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY); ++} ++ ++static void brcms_ucode_write(struct brcms_hardware *wlc_hw, ++ const __le32 ucode[], const size_t nbytes) ++{ ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ uint i; ++ uint count; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ count = (nbytes / sizeof(u32)); ++ ++ W_REG(®s->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL)); ++ (void)R_REG(®s->objaddr); ++ for (i = 0; i < count; i++) ++ W_REG(®s->objdata, le32_to_cpu(ucode[i])); ++ ++} ++ ++static void brcms_ucode_download(struct brcms_hardware *wlc_hw) ++{ ++ struct brcms_c_info *wlc; ++ struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode; ++ ++ wlc = wlc_hw->wlc; ++ ++ if (wlc_hw->ucode_loaded) ++ return; ++ ++ if (D11REV_IS(wlc_hw->corerev, 23)) { ++ if (BRCMS_ISNPHY(wlc_hw->band)) { ++ brcms_ucode_write(wlc_hw, ucode->bcm43xx_16_mimo, ++ ucode->bcm43xx_16_mimosz); ++ wlc_hw->ucode_loaded = true; ++ } else ++ wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in " ++ "corerev %d\n", ++ __func__, wlc_hw->unit, wlc_hw->corerev); ++ } else if (D11REV_IS(wlc_hw->corerev, 24)) { ++ if (BRCMS_ISLCNPHY(wlc_hw->band)) { ++ brcms_ucode_write(wlc_hw, ucode->bcm43xx_24_lcn, ++ ucode->bcm43xx_24_lcnsz); ++ wlc_hw->ucode_loaded = true; ++ } else { ++ wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in " ++ "corerev %d\n", ++ __func__, wlc_hw->unit, wlc_hw->corerev); ++ } ++ } ++} ++ ++void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant) ++{ ++ /* update sw state */ ++ wlc_hw->bmac_phytxant = phytxant; ++ ++ /* push to ucode if up */ ++ if (!wlc_hw->up) ++ return; ++ brcms_c_ucode_txant_set(wlc_hw); ++ ++} ++ ++u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw) ++{ ++ return (u16) wlc_hw->wlc->stf->txant; ++} ++ ++void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type) ++{ ++ wlc_hw->antsel_type = antsel_type; ++ ++ /* Update the antsel type for phy module to use */ ++ wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type); ++} ++ ++static void brcms_c_fatal_error(struct brcms_c_info *wlc) ++{ ++ wiphy_err(wlc->wiphy, "wl%d: fatal error, reinitializing\n", ++ wlc->pub->unit); ++ brcms_init(wlc->wl); ++} ++ ++static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw) ++{ ++ bool fatal = false; ++ uint unit; ++ uint intstatus, idx; ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ struct wiphy *wiphy = wlc_hw->wlc->wiphy; ++ ++ unit = wlc_hw->unit; ++ ++ for (idx = 0; idx < NFIFO; idx++) { ++ /* read intstatus register and ignore any non-error bits */ ++ intstatus = ++ R_REG(®s->intctrlregs[idx].intstatus) & I_ERRORS; ++ if (!intstatus) ++ continue; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: intstatus%d 0x%x\n", ++ unit, idx, intstatus); ++ ++ if (intstatus & I_RO) { ++ wiphy_err(wiphy, "wl%d: fifo %d: receive fifo " ++ "overflow\n", unit, idx); ++ fatal = true; ++ } ++ ++ if (intstatus & I_PC) { ++ wiphy_err(wiphy, "wl%d: fifo %d: descriptor error\n", ++ unit, idx); ++ fatal = true; ++ } ++ ++ if (intstatus & I_PD) { ++ wiphy_err(wiphy, "wl%d: fifo %d: data error\n", unit, ++ idx); ++ fatal = true; ++ } ++ ++ if (intstatus & I_DE) { ++ wiphy_err(wiphy, "wl%d: fifo %d: descriptor protocol " ++ "error\n", unit, idx); ++ fatal = true; ++ } ++ ++ if (intstatus & I_RU) ++ wiphy_err(wiphy, "wl%d: fifo %d: receive descriptor " ++ "underflow\n", idx, unit); ++ ++ if (intstatus & I_XU) { ++ wiphy_err(wiphy, "wl%d: fifo %d: transmit fifo " ++ "underflow\n", idx, unit); ++ fatal = true; ++ } ++ ++ if (fatal) { ++ brcms_c_fatal_error(wlc_hw->wlc); /* big hammer */ ++ break; ++ } else ++ W_REG(®s->intctrlregs[idx].intstatus, ++ intstatus); ++ } ++} ++ ++void brcms_c_intrson(struct brcms_c_info *wlc) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ wlc->macintmask = wlc->defmacintmask; ++ W_REG(&wlc_hw->regs->macintmask, wlc->macintmask); ++} ++ ++/* ++ * callback for siutils.c, which has only wlc handler, no wl they both check ++ * up, not only because there is no need to off/restore d11 interrupt but also ++ * because per-port code may require sync with valid interrupt. ++ */ ++static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc) ++{ ++ if (!wlc->hw->up) ++ return 0; ++ ++ return brcms_intrsoff(wlc->wl); ++} ++ ++static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask) ++{ ++ if (!wlc->hw->up) ++ return; ++ ++ brcms_intrsrestore(wlc->wl, macintmask); ++} ++ ++u32 brcms_c_intrsoff(struct brcms_c_info *wlc) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ u32 macintmask; ++ ++ if (!wlc_hw->clk) ++ return 0; ++ ++ macintmask = wlc->macintmask; /* isr can still happen */ ++ ++ W_REG(&wlc_hw->regs->macintmask, 0); ++ (void)R_REG(&wlc_hw->regs->macintmask); /* sync readback */ ++ udelay(1); /* ensure int line is no longer driven */ ++ wlc->macintmask = 0; ++ ++ /* return previous macintmask; resolve race between us and our isr */ ++ return wlc->macintstatus ? 0 : macintmask; ++} ++ ++void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ if (!wlc_hw->clk) ++ return; ++ ++ wlc->macintmask = macintmask; ++ W_REG(&wlc_hw->regs->macintmask, wlc->macintmask); ++} ++ ++static void brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw, ++ uint tx_fifo) ++{ ++ u8 fifo = 1 << tx_fifo; ++ ++ /* Two clients of this code, 11h Quiet period and scanning. */ ++ ++ /* only suspend if not already suspended */ ++ if ((wlc_hw->suspended_fifos & fifo) == fifo) ++ return; ++ ++ /* force the core awake only if not already */ ++ if (wlc_hw->suspended_fifos == 0) ++ brcms_c_ucode_wake_override_set(wlc_hw, ++ BRCMS_WAKE_OVERRIDE_TXFIFO); ++ ++ wlc_hw->suspended_fifos |= fifo; ++ ++ if (wlc_hw->di[tx_fifo]) { ++ /* ++ * Suspending AMPDU transmissions in the middle can cause ++ * underflow which may result in mismatch between ucode and ++ * driver so suspend the mac before suspending the FIFO ++ */ ++ if (BRCMS_PHY_11N_CAP(wlc_hw->band)) ++ brcms_c_suspend_mac_and_wait(wlc_hw->wlc); ++ ++ dma_txsuspend(wlc_hw->di[tx_fifo]); ++ ++ if (BRCMS_PHY_11N_CAP(wlc_hw->band)) ++ brcms_c_enable_mac(wlc_hw->wlc); ++ } ++} ++ ++static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw, ++ uint tx_fifo) ++{ ++ /* BMAC_NOTE: BRCMS_TX_FIFO_ENAB is done in brcms_c_dpc() for DMA case ++ * but need to be done here for PIO otherwise the watchdog will catch ++ * the inconsistency and fire ++ */ ++ /* Two clients of this code, 11h Quiet period and scanning. */ ++ if (wlc_hw->di[tx_fifo]) ++ dma_txresume(wlc_hw->di[tx_fifo]); ++ ++ /* allow core to sleep again */ ++ if (wlc_hw->suspended_fifos == 0) ++ return; ++ else { ++ wlc_hw->suspended_fifos &= ~(1 << tx_fifo); ++ if (wlc_hw->suspended_fifos == 0) ++ brcms_c_ucode_wake_override_clear(wlc_hw, ++ BRCMS_WAKE_OVERRIDE_TXFIFO); ++ } ++} ++ ++static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool on, u32 flags) ++{ ++ static const u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; ++ ++ if (on) { ++ /* suspend tx fifos */ ++ brcms_b_tx_fifo_suspend(wlc_hw, TX_DATA_FIFO); ++ brcms_b_tx_fifo_suspend(wlc_hw, TX_CTL_FIFO); ++ brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_BK_FIFO); ++ brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO); ++ ++ /* zero the address match register so we do not send ACKs */ ++ brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, ++ null_ether_addr); ++ } else { ++ /* resume tx fifos */ ++ brcms_b_tx_fifo_resume(wlc_hw, TX_DATA_FIFO); ++ brcms_b_tx_fifo_resume(wlc_hw, TX_CTL_FIFO); ++ brcms_b_tx_fifo_resume(wlc_hw, TX_AC_BK_FIFO); ++ brcms_b_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO); ++ ++ /* Restore address */ ++ brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, ++ wlc_hw->etheraddr); ++ } ++ ++ wlc_phy_mute_upd(wlc_hw->band->pi, on, flags); ++ ++ if (on) ++ brcms_c_ucode_mute_override_set(wlc_hw); ++ else ++ brcms_c_ucode_mute_override_clear(wlc_hw); ++} ++ ++/* ++ * Read and clear macintmask and macintstatus and intstatus registers. ++ * This routine should be called with interrupts off ++ * Return: ++ * -1 if brcms_deviceremoved(wlc) evaluates to true; ++ * 0 if the interrupt is not for us, or we are in some special cases; ++ * device interrupt status bits otherwise. ++ */ ++static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ u32 macintstatus; ++ ++ /* macintstatus includes a DMA interrupt summary bit */ ++ macintstatus = R_REG(®s->macintstatus); ++ ++ BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit, ++ macintstatus); ++ ++ /* detect cardbus removed, in power down(suspend) and in reset */ ++ if (brcms_deviceremoved(wlc)) ++ return -1; ++ ++ /* brcms_deviceremoved() succeeds even when the core is still resetting, ++ * handle that case here. ++ */ ++ if (macintstatus == 0xffffffff) ++ return 0; ++ ++ /* defer unsolicited interrupts */ ++ macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask); ++ ++ /* if not for us */ ++ if (macintstatus == 0) ++ return 0; ++ ++ /* interrupts are already turned off for CFE build ++ * Caution: For CFE Turning off the interrupts again has some undesired ++ * consequences ++ */ ++ /* turn off the interrupts */ ++ W_REG(®s->macintmask, 0); ++ (void)R_REG(®s->macintmask); /* sync readback */ ++ wlc->macintmask = 0; ++ ++ /* clear device interrupts */ ++ W_REG(®s->macintstatus, macintstatus); ++ ++ /* MI_DMAINT is indication of non-zero intstatus */ ++ if (macintstatus & MI_DMAINT) ++ /* ++ * only fifo interrupt enabled is I_RI in ++ * RX_FIFO. If MI_DMAINT is set, assume it ++ * is set and clear the interrupt. ++ */ ++ W_REG(®s->intctrlregs[RX_FIFO].intstatus, ++ DEF_RXINTMASK); ++ ++ return macintstatus; ++} ++ ++/* Update wlc->macintstatus and wlc->intstatus[]. */ ++/* Return true if they are updated successfully. false otherwise */ ++bool brcms_c_intrsupd(struct brcms_c_info *wlc) ++{ ++ u32 macintstatus; ++ ++ /* read and clear macintstatus and intstatus registers */ ++ macintstatus = wlc_intstatus(wlc, false); ++ ++ /* device is removed */ ++ if (macintstatus == 0xffffffff) ++ return false; ++ ++ /* update interrupt status in software */ ++ wlc->macintstatus |= macintstatus; ++ ++ return true; ++} ++ ++/* ++ * First-level interrupt processing. ++ * Return true if this was our interrupt, false otherwise. ++ * *wantdpc will be set to true if further brcms_c_dpc() processing is required, ++ * false otherwise. ++ */ ++bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ u32 macintstatus; ++ ++ *wantdpc = false; ++ ++ if (!wlc_hw->up || !wlc->macintmask) ++ return false; ++ ++ /* read and clear macintstatus and intstatus registers */ ++ macintstatus = wlc_intstatus(wlc, true); ++ ++ if (macintstatus == 0xffffffff) ++ wiphy_err(wlc->wiphy, "DEVICEREMOVED detected in the ISR code" ++ " path\n"); ++ ++ /* it is not for us */ ++ if (macintstatus == 0) ++ return false; ++ ++ *wantdpc = true; ++ ++ /* save interrupt status bits */ ++ wlc->macintstatus = macintstatus; ++ ++ return true; ++ ++} ++ ++void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ u32 mc, mi; ++ struct wiphy *wiphy = wlc->wiphy; ++ ++ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, ++ wlc_hw->band->bandunit); ++ ++ /* ++ * Track overlapping suspend requests ++ */ ++ wlc_hw->mac_suspend_depth++; ++ if (wlc_hw->mac_suspend_depth > 1) ++ return; ++ ++ /* force the core awake */ ++ brcms_c_ucode_wake_override_set(wlc_hw, BRCMS_WAKE_OVERRIDE_MACSUSPEND); ++ ++ mc = R_REG(®s->maccontrol); ++ ++ if (mc == 0xffffffff) { ++ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, ++ __func__); ++ brcms_down(wlc->wl); ++ return; ++ } ++ WARN_ON(mc & MCTL_PSM_JMP_0); ++ WARN_ON(!(mc & MCTL_PSM_RUN)); ++ WARN_ON(!(mc & MCTL_EN_MAC)); ++ ++ mi = R_REG(®s->macintstatus); ++ if (mi == 0xffffffff) { ++ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, ++ __func__); ++ brcms_down(wlc->wl); ++ return; ++ } ++ WARN_ON(mi & MI_MACSSPNDD); ++ ++ brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, 0); ++ ++ SPINWAIT(!(R_REG(®s->macintstatus) & MI_MACSSPNDD), ++ BRCMS_MAX_MAC_SUSPEND); ++ ++ if (!(R_REG(®s->macintstatus) & MI_MACSSPNDD)) { ++ wiphy_err(wiphy, "wl%d: wlc_suspend_mac_and_wait: waited %d uS" ++ " and MI_MACSSPNDD is still not on.\n", ++ wlc_hw->unit, BRCMS_MAX_MAC_SUSPEND); ++ wiphy_err(wiphy, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, " ++ "psm_brc 0x%04x\n", wlc_hw->unit, ++ R_REG(®s->psmdebug), ++ R_REG(®s->phydebug), ++ R_REG(®s->psm_brc)); ++ } ++ ++ mc = R_REG(®s->maccontrol); ++ if (mc == 0xffffffff) { ++ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, ++ __func__); ++ brcms_down(wlc->wl); ++ return; ++ } ++ WARN_ON(mc & MCTL_PSM_JMP_0); ++ WARN_ON(!(mc & MCTL_PSM_RUN)); ++ WARN_ON(mc & MCTL_EN_MAC); ++} ++ ++void brcms_c_enable_mac(struct brcms_c_info *wlc) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ u32 mc, mi; ++ ++ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit, ++ wlc->band->bandunit); ++ ++ /* ++ * Track overlapping suspend requests ++ */ ++ wlc_hw->mac_suspend_depth--; ++ if (wlc_hw->mac_suspend_depth > 0) ++ return; ++ ++ mc = R_REG(®s->maccontrol); ++ WARN_ON(mc & MCTL_PSM_JMP_0); ++ WARN_ON(mc & MCTL_EN_MAC); ++ WARN_ON(!(mc & MCTL_PSM_RUN)); ++ ++ brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC); ++ W_REG(®s->macintstatus, MI_MACSSPNDD); ++ ++ mc = R_REG(®s->maccontrol); ++ WARN_ON(mc & MCTL_PSM_JMP_0); ++ WARN_ON(!(mc & MCTL_EN_MAC)); ++ WARN_ON(!(mc & MCTL_PSM_RUN)); ++ ++ mi = R_REG(®s->macintstatus); ++ WARN_ON(mi & MI_MACSSPNDD); ++ ++ brcms_c_ucode_wake_override_clear(wlc_hw, ++ BRCMS_WAKE_OVERRIDE_MACSUSPEND); ++} ++ ++void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode) ++{ ++ wlc_hw->hw_stf_ss_opmode = stf_mode; ++ ++ if (wlc_hw->clk) ++ brcms_upd_ofdm_pctl1_table(wlc_hw); ++} ++ ++static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw) ++{ ++ struct d11regs __iomem *regs; ++ u32 w, val; ++ struct wiphy *wiphy = wlc_hw->wlc->wiphy; ++ ++ BCMMSG(wiphy, "wl%d\n", wlc_hw->unit); ++ ++ regs = wlc_hw->regs; ++ ++ /* Validate dchip register access */ ++ ++ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); ++ (void)R_REG(®s->objaddr); ++ w = R_REG(®s->objdata); ++ ++ /* Can we write and read back a 32bit register? */ ++ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); ++ (void)R_REG(®s->objaddr); ++ W_REG(®s->objdata, (u32) 0xaa5555aa); ++ ++ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); ++ (void)R_REG(®s->objaddr); ++ val = R_REG(®s->objdata); ++ if (val != (u32) 0xaa5555aa) { ++ wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, " ++ "expected 0xaa5555aa\n", wlc_hw->unit, val); ++ return false; ++ } ++ ++ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); ++ (void)R_REG(®s->objaddr); ++ W_REG(®s->objdata, (u32) 0x55aaaa55); ++ ++ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); ++ (void)R_REG(®s->objaddr); ++ val = R_REG(®s->objdata); ++ if (val != (u32) 0x55aaaa55) { ++ wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, " ++ "expected 0x55aaaa55\n", wlc_hw->unit, val); ++ return false; ++ } ++ ++ W_REG(®s->objaddr, OBJADDR_SHM_SEL | 0); ++ (void)R_REG(®s->objaddr); ++ W_REG(®s->objdata, w); ++ ++ /* clear CFPStart */ ++ W_REG(®s->tsf_cfpstart, 0); ++ ++ w = R_REG(®s->maccontrol); ++ if ((w != (MCTL_IHR_EN | MCTL_WAKE)) && ++ (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) { ++ wiphy_err(wiphy, "wl%d: validate_chip_access: maccontrol = " ++ "0x%x, expected 0x%x or 0x%x\n", wlc_hw->unit, w, ++ (MCTL_IHR_EN | MCTL_WAKE), ++ (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE)); ++ return false; ++ } ++ ++ return true; ++} ++ ++#define PHYPLL_WAIT_US 100000 ++ ++void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on) ++{ ++ struct d11regs __iomem *regs; ++ u32 tmp; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ tmp = 0; ++ regs = wlc_hw->regs; ++ ++ if (on) { ++ if ((wlc_hw->sih->chip == BCM4313_CHIP_ID)) { ++ OR_REG(®s->clk_ctl_st, ++ (CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL | ++ CCS_ERSRC_REQ_PHYPLL)); ++ SPINWAIT((R_REG(®s->clk_ctl_st) & ++ (CCS_ERSRC_AVAIL_HT)) != (CCS_ERSRC_AVAIL_HT), ++ PHYPLL_WAIT_US); ++ ++ tmp = R_REG(®s->clk_ctl_st); ++ if ((tmp & (CCS_ERSRC_AVAIL_HT)) != ++ (CCS_ERSRC_AVAIL_HT)) ++ wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on PHY" ++ " PLL failed\n", __func__); ++ } else { ++ OR_REG(®s->clk_ctl_st, ++ (CCS_ERSRC_REQ_D11PLL | CCS_ERSRC_REQ_PHYPLL)); ++ SPINWAIT((R_REG(®s->clk_ctl_st) & ++ (CCS_ERSRC_AVAIL_D11PLL | ++ CCS_ERSRC_AVAIL_PHYPLL)) != ++ (CCS_ERSRC_AVAIL_D11PLL | ++ CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US); ++ ++ tmp = R_REG(®s->clk_ctl_st); ++ if ((tmp & ++ (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) ++ != ++ (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) ++ wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on " ++ "PHY PLL failed\n", __func__); ++ } ++ } else { ++ /* ++ * Since the PLL may be shared, other cores can still ++ * be requesting it; so we'll deassert the request but ++ * not wait for status to comply. ++ */ ++ AND_REG(®s->clk_ctl_st, ~CCS_ERSRC_REQ_PHYPLL); ++ tmp = R_REG(®s->clk_ctl_st); ++ } ++} ++ ++static void brcms_c_coredisable(struct brcms_hardware *wlc_hw) ++{ ++ bool dev_gone; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ dev_gone = brcms_deviceremoved(wlc_hw->wlc); ++ ++ if (dev_gone) ++ return; ++ ++ if (wlc_hw->noreset) ++ return; ++ ++ /* radio off */ ++ wlc_phy_switch_radio(wlc_hw->band->pi, OFF); ++ ++ /* turn off analog core */ ++ wlc_phy_anacore(wlc_hw->band->pi, OFF); ++ ++ /* turn off PHYPLL to save power */ ++ brcms_b_core_phypll_ctl(wlc_hw, false); ++ ++ wlc_hw->clk = false; ++ ai_core_disable(wlc_hw->sih, 0); ++ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false); ++} ++ ++static void brcms_c_flushqueues(struct brcms_c_info *wlc) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ uint i; ++ ++ /* free any posted tx packets */ ++ for (i = 0; i < NFIFO; i++) ++ if (wlc_hw->di[i]) { ++ dma_txreclaim(wlc_hw->di[i], DMA_RANGE_ALL); ++ wlc->core->txpktpend[i] = 0; ++ BCMMSG(wlc->wiphy, "pktpend fifo %d clrd\n", i); ++ } ++ ++ /* free any posted rx packets */ ++ dma_rxreclaim(wlc_hw->di[RX_FIFO]); ++} ++ ++static u16 ++brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel) ++{ ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ u16 __iomem *objdata_lo = (u16 __iomem *)®s->objdata; ++ u16 __iomem *objdata_hi = objdata_lo + 1; ++ u16 v; ++ ++ W_REG(®s->objaddr, sel | (offset >> 2)); ++ (void)R_REG(®s->objaddr); ++ if (offset & 2) ++ v = R_REG(objdata_hi); ++ else ++ v = R_REG(objdata_lo); ++ ++ return v; ++} ++ ++static void ++brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, u16 v, ++ u32 sel) ++{ ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ u16 __iomem *objdata_lo = (u16 __iomem *)®s->objdata; ++ u16 __iomem *objdata_hi = objdata_lo + 1; ++ ++ W_REG(®s->objaddr, sel | (offset >> 2)); ++ (void)R_REG(®s->objaddr); ++ if (offset & 2) ++ W_REG(objdata_hi, v); ++ else ++ W_REG(objdata_lo, v); ++} ++ ++/* ++ * Read a single u16 from shared memory. ++ * SHM 'offset' needs to be an even address ++ */ ++u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset) ++{ ++ return brcms_b_read_objmem(wlc_hw, offset, OBJADDR_SHM_SEL); ++} ++ ++/* ++ * Write a single u16 to shared memory. ++ * SHM 'offset' needs to be an even address ++ */ ++void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, u16 v) ++{ ++ brcms_b_write_objmem(wlc_hw, offset, v, OBJADDR_SHM_SEL); ++} ++ ++/* ++ * Copy a buffer to shared memory of specified type . ++ * SHM 'offset' needs to be an even address and ++ * Buffer length 'len' must be an even number of bytes ++ * 'sel' selects the type of memory ++ */ ++void ++brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, uint offset, ++ const void *buf, int len, u32 sel) ++{ ++ u16 v; ++ const u8 *p = (const u8 *)buf; ++ int i; ++ ++ if (len <= 0 || (offset & 1) || (len & 1)) ++ return; ++ ++ for (i = 0; i < len; i += 2) { ++ v = p[i] | (p[i + 1] << 8); ++ brcms_b_write_objmem(wlc_hw, offset + i, v, sel); ++ } ++} ++ ++/* ++ * Copy a piece of shared memory of specified type to a buffer . ++ * SHM 'offset' needs to be an even address and ++ * Buffer length 'len' must be an even number of bytes ++ * 'sel' selects the type of memory ++ */ ++void ++brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, void *buf, ++ int len, u32 sel) ++{ ++ u16 v; ++ u8 *p = (u8 *) buf; ++ int i; ++ ++ if (len <= 0 || (offset & 1) || (len & 1)) ++ return; ++ ++ for (i = 0; i < len; i += 2) { ++ v = brcms_b_read_objmem(wlc_hw, offset + i, sel); ++ p[i] = v & 0xFF; ++ p[i + 1] = (v >> 8) & 0xFF; ++ } ++} ++ ++/* Copy a buffer to shared memory. ++ * SHM 'offset' needs to be an even address and ++ * Buffer length 'len' must be an even number of bytes ++ */ ++static void brcms_c_copyto_shm(struct brcms_c_info *wlc, uint offset, ++ const void *buf, int len) ++{ ++ brcms_b_copyto_objmem(wlc->hw, offset, buf, len, OBJADDR_SHM_SEL); ++} ++ ++static void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw, ++ u16 SRL, u16 LRL) ++{ ++ wlc_hw->SRL = SRL; ++ wlc_hw->LRL = LRL; ++ ++ /* write retry limit to SCR, shouldn't need to suspend */ ++ if (wlc_hw->up) { ++ W_REG(&wlc_hw->regs->objaddr, ++ OBJADDR_SCR_SEL | S_DOT11_SRC_LMT); ++ (void)R_REG(&wlc_hw->regs->objaddr); ++ W_REG(&wlc_hw->regs->objdata, wlc_hw->SRL); ++ W_REG(&wlc_hw->regs->objaddr, ++ OBJADDR_SCR_SEL | S_DOT11_LRC_LMT); ++ (void)R_REG(&wlc_hw->regs->objaddr); ++ W_REG(&wlc_hw->regs->objdata, wlc_hw->LRL); ++ } ++} ++ ++static void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set, u32 req_bit) ++{ ++ if (set) { ++ if (mboolisset(wlc_hw->pllreq, req_bit)) ++ return; ++ ++ mboolset(wlc_hw->pllreq, req_bit); ++ ++ if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) { ++ if (!wlc_hw->sbclk) ++ brcms_b_xtal(wlc_hw, ON); ++ } ++ } else { ++ if (!mboolisset(wlc_hw->pllreq, req_bit)) ++ return; ++ ++ mboolclr(wlc_hw->pllreq, req_bit); ++ ++ if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) { ++ if (wlc_hw->sbclk) ++ brcms_b_xtal(wlc_hw, OFF); ++ } ++ } ++} ++ ++static void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail) ++{ ++ wlc_hw->antsel_avail = antsel_avail; ++} ++ ++/* ++ * conditions under which the PM bit should be set in outgoing frames ++ * and STAY_AWAKE is meaningful ++ */ ++static bool brcms_c_ps_allowed(struct brcms_c_info *wlc) ++{ ++ struct brcms_bss_cfg *cfg = wlc->bsscfg; ++ ++ /* disallow PS when one of the following global conditions meets */ ++ if (!wlc->pub->associated) ++ return false; ++ ++ /* disallow PS when one of these meets when not scanning */ ++ if (wlc->monitor) ++ return false; ++ ++ if (cfg->associated) { ++ /* ++ * disallow PS when one of the following ++ * bsscfg specific conditions meets ++ */ ++ if (!cfg->BSS) ++ return false; ++ ++ return false; ++ } ++ ++ return true; ++} ++ ++static void brcms_c_statsupd(struct brcms_c_info *wlc) ++{ ++ int i; ++ struct macstat macstats; ++#ifdef BCMDBG ++ u16 delta; ++ u16 rxf0ovfl; ++ u16 txfunfl[NFIFO]; ++#endif /* BCMDBG */ ++ ++ /* if driver down, make no sense to update stats */ ++ if (!wlc->pub->up) ++ return; ++ ++#ifdef BCMDBG ++ /* save last rx fifo 0 overflow count */ ++ rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl; ++ ++ /* save last tx fifo underflow count */ ++ for (i = 0; i < NFIFO; i++) ++ txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i]; ++#endif /* BCMDBG */ ++ ++ /* Read mac stats from contiguous shared memory */ ++ brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, &macstats, ++ sizeof(struct macstat), OBJADDR_SHM_SEL); ++ ++#ifdef BCMDBG ++ /* check for rx fifo 0 overflow */ ++ delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl); ++ if (delta) ++ wiphy_err(wlc->wiphy, "wl%d: %u rx fifo 0 overflows!\n", ++ wlc->pub->unit, delta); ++ ++ /* check for tx fifo underflows */ ++ for (i = 0; i < NFIFO; i++) { ++ delta = ++ (u16) (wlc->core->macstat_snapshot->txfunfl[i] - ++ txfunfl[i]); ++ if (delta) ++ wiphy_err(wlc->wiphy, "wl%d: %u tx fifo %d underflows!" ++ "\n", wlc->pub->unit, delta, i); ++ } ++#endif /* BCMDBG */ ++ ++ /* merge counters from dma module */ ++ for (i = 0; i < NFIFO; i++) { ++ if (wlc->hw->di[i]) ++ dma_counterreset(wlc->hw->di[i]); ++ } ++} ++ ++static void brcms_b_reset(struct brcms_hardware *wlc_hw) ++{ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ /* reset the core */ ++ if (!brcms_deviceremoved(wlc_hw->wlc)) ++ brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); ++ ++ /* purge the dma rings */ ++ brcms_c_flushqueues(wlc_hw->wlc); ++} ++ ++void brcms_c_reset(struct brcms_c_info *wlc) ++{ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ ++ /* slurp up hw mac counters before core reset */ ++ brcms_c_statsupd(wlc); ++ ++ /* reset our snapshot of macstat counters */ ++ memset((char *)wlc->core->macstat_snapshot, 0, ++ sizeof(struct macstat)); ++ ++ brcms_b_reset(wlc->hw); ++} ++ ++/* Return the channel the driver should initialize during brcms_c_init. ++ * the channel may have to be changed from the currently configured channel ++ * if other configurations are in conflict (bandlocked, 11n mode disabled, ++ * invalid channel for current country, etc.) ++ */ ++static u16 brcms_c_init_chanspec(struct brcms_c_info *wlc) ++{ ++ u16 chanspec = ++ 1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE | ++ WL_CHANSPEC_BAND_2G; ++ ++ return chanspec; ++} ++ ++void brcms_c_init_scb(struct scb *scb) ++{ ++ int i; ++ ++ memset(scb, 0, sizeof(struct scb)); ++ scb->flags = SCB_WMECAP | SCB_HTCAP; ++ for (i = 0; i < NUMPRIO; i++) { ++ scb->seqnum[i] = 0; ++ scb->seqctl[i] = 0xFFFF; ++ } ++ ++ scb->seqctl_nonqos = 0xFFFF; ++ scb->magic = SCB_MAGIC; ++} ++ ++/* d11 core init ++ * reset PSM ++ * download ucode/PCM ++ * let ucode run to suspended ++ * download ucode inits ++ * config other core registers ++ * init dma ++ */ ++static void brcms_b_coreinit(struct brcms_c_info *wlc) ++{ ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ struct d11regs __iomem *regs; ++ u32 sflags; ++ uint bcnint_us; ++ uint i = 0; ++ bool fifosz_fixup = false; ++ int err = 0; ++ u16 buf[NFIFO]; ++ struct wiphy *wiphy = wlc->wiphy; ++ struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode; ++ ++ regs = wlc_hw->regs; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ /* reset PSM */ ++ brcms_b_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE)); ++ ++ brcms_ucode_download(wlc_hw); ++ /* ++ * FIFOSZ fixup. driver wants to controls the fifo allocation. ++ */ ++ fifosz_fixup = true; ++ ++ /* let the PSM run to the suspended state, set mode to BSS STA */ ++ W_REG(®s->macintstatus, -1); ++ brcms_b_mctrl(wlc_hw, ~0, ++ (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE)); ++ ++ /* wait for ucode to self-suspend after auto-init */ ++ SPINWAIT(((R_REG(®s->macintstatus) & MI_MACSSPNDD) == 0), ++ 1000 * 1000); ++ if ((R_REG(®s->macintstatus) & MI_MACSSPNDD) == 0) ++ wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-" ++ "suspend!\n", wlc_hw->unit); ++ ++ brcms_c_gpio_init(wlc); ++ ++ sflags = ai_core_sflags(wlc_hw->sih, 0, 0); ++ ++ if (D11REV_IS(wlc_hw->corerev, 23)) { ++ if (BRCMS_ISNPHY(wlc_hw->band)) ++ brcms_c_write_inits(wlc_hw, ucode->d11n0initvals16); ++ else ++ wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" ++ " %d\n", __func__, wlc_hw->unit, ++ wlc_hw->corerev); ++ } else if (D11REV_IS(wlc_hw->corerev, 24)) { ++ if (BRCMS_ISLCNPHY(wlc_hw->band)) ++ brcms_c_write_inits(wlc_hw, ucode->d11lcn0initvals24); ++ else ++ wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev" ++ " %d\n", __func__, wlc_hw->unit, ++ wlc_hw->corerev); ++ } else { ++ wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n", ++ __func__, wlc_hw->unit, wlc_hw->corerev); ++ } ++ ++ /* For old ucode, txfifo sizes needs to be modified(increased) */ ++ if (fifosz_fixup == true) ++ brcms_b_corerev_fifofixup(wlc_hw); ++ ++ /* check txfifo allocations match between ucode and driver */ ++ buf[TX_AC_BE_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE0); ++ if (buf[TX_AC_BE_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]) { ++ i = TX_AC_BE_FIFO; ++ err = -1; ++ } ++ buf[TX_AC_VI_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE1); ++ if (buf[TX_AC_VI_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]) { ++ i = TX_AC_VI_FIFO; ++ err = -1; ++ } ++ buf[TX_AC_BK_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE2); ++ buf[TX_AC_VO_FIFO] = (buf[TX_AC_BK_FIFO] >> 8) & 0xff; ++ buf[TX_AC_BK_FIFO] &= 0xff; ++ if (buf[TX_AC_BK_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BK_FIFO]) { ++ i = TX_AC_BK_FIFO; ++ err = -1; ++ } ++ if (buf[TX_AC_VO_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO]) { ++ i = TX_AC_VO_FIFO; ++ err = -1; ++ } ++ buf[TX_BCMC_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE3); ++ buf[TX_ATIM_FIFO] = (buf[TX_BCMC_FIFO] >> 8) & 0xff; ++ buf[TX_BCMC_FIFO] &= 0xff; ++ if (buf[TX_BCMC_FIFO] != wlc_hw->xmtfifo_sz[TX_BCMC_FIFO]) { ++ i = TX_BCMC_FIFO; ++ err = -1; ++ } ++ if (buf[TX_ATIM_FIFO] != wlc_hw->xmtfifo_sz[TX_ATIM_FIFO]) { ++ i = TX_ATIM_FIFO; ++ err = -1; ++ } ++ if (err != 0) ++ wiphy_err(wiphy, "wlc_coreinit: txfifo mismatch: ucode size %d" ++ " driver size %d index %d\n", buf[i], ++ wlc_hw->xmtfifo_sz[i], i); ++ ++ /* make sure we can still talk to the mac */ ++ WARN_ON(R_REG(®s->maccontrol) == 0xffffffff); ++ ++ /* band-specific inits done by wlc_bsinit() */ ++ ++ /* Set up frame burst size and antenna swap threshold init values */ ++ brcms_b_write_shm(wlc_hw, M_MBURST_SIZE, MAXTXFRAMEBURST); ++ brcms_b_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT); ++ ++ /* enable one rx interrupt per received frame */ ++ W_REG(®s->intrcvlazy[0], (1 << IRL_FC_SHIFT)); ++ ++ /* set the station mode (BSS STA) */ ++ brcms_b_mctrl(wlc_hw, ++ (MCTL_INFRA | MCTL_DISCARD_PMQ | MCTL_AP), ++ (MCTL_INFRA | MCTL_DISCARD_PMQ)); ++ ++ /* set up Beacon interval */ ++ bcnint_us = 0x8000 << 10; ++ W_REG(®s->tsf_cfprep, (bcnint_us << CFPREP_CBI_SHIFT)); ++ W_REG(®s->tsf_cfpstart, bcnint_us); ++ W_REG(®s->macintstatus, MI_GP1); ++ ++ /* write interrupt mask */ ++ W_REG(®s->intctrlregs[RX_FIFO].intmask, DEF_RXINTMASK); ++ ++ /* allow the MAC to control the PHY clock (dynamic on/off) */ ++ brcms_b_macphyclk_set(wlc_hw, ON); ++ ++ /* program dynamic clock control fast powerup delay register */ ++ wlc->fastpwrup_dly = ai_clkctl_fast_pwrup_delay(wlc_hw->sih); ++ W_REG(®s->scc_fastpwrup_dly, wlc->fastpwrup_dly); ++ ++ /* tell the ucode the corerev */ ++ brcms_b_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev); ++ ++ /* tell the ucode MAC capabilities */ ++ brcms_b_write_shm(wlc_hw, M_MACHW_CAP_L, ++ (u16) (wlc_hw->machwcap & 0xffff)); ++ brcms_b_write_shm(wlc_hw, M_MACHW_CAP_H, ++ (u16) ((wlc_hw-> ++ machwcap >> 16) & 0xffff)); ++ ++ /* write retry limits to SCR, this done after PSM init */ ++ W_REG(®s->objaddr, OBJADDR_SCR_SEL | S_DOT11_SRC_LMT); ++ (void)R_REG(®s->objaddr); ++ W_REG(®s->objdata, wlc_hw->SRL); ++ W_REG(®s->objaddr, OBJADDR_SCR_SEL | S_DOT11_LRC_LMT); ++ (void)R_REG(®s->objaddr); ++ W_REG(®s->objdata, wlc_hw->LRL); ++ ++ /* write rate fallback retry limits */ ++ brcms_b_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL); ++ brcms_b_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL); ++ ++ AND_REG(®s->ifs_ctl, 0x0FFF); ++ W_REG(®s->ifs_aifsn, EDCF_AIFSN_MIN); ++ ++ /* init the tx dma engines */ ++ for (i = 0; i < NFIFO; i++) { ++ if (wlc_hw->di[i]) ++ dma_txinit(wlc_hw->di[i]); ++ } ++ ++ /* init the rx dma engine(s) and post receive buffers */ ++ dma_rxinit(wlc_hw->di[RX_FIFO]); ++ dma_rxfill(wlc_hw->di[RX_FIFO]); ++} ++ ++void ++static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec, ++ bool mute) { ++ u32 macintmask; ++ bool fastclk; ++ struct brcms_c_info *wlc = wlc_hw->wlc; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ /* request FAST clock if not on */ ++ fastclk = wlc_hw->forcefastclk; ++ if (!fastclk) ++ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); ++ ++ /* disable interrupts */ ++ macintmask = brcms_intrsoff(wlc->wl); ++ ++ /* set up the specified band and chanspec */ ++ brcms_c_setxband(wlc_hw, chspec_bandunit(chanspec)); ++ wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec); ++ ++ /* do one-time phy inits and calibration */ ++ wlc_phy_cal_init(wlc_hw->band->pi); ++ ++ /* core-specific initialization */ ++ brcms_b_coreinit(wlc); ++ ++ /* suspend the tx fifos and mute the phy for preism cac time */ ++ if (mute) ++ brcms_b_mute(wlc_hw, ON, PHY_MUTE_FOR_PREISM); ++ ++ /* band-specific inits */ ++ brcms_b_bsinit(wlc, chanspec); ++ ++ /* restore macintmask */ ++ brcms_intrsrestore(wlc->wl, macintmask); ++ ++ /* seed wake_override with BRCMS_WAKE_OVERRIDE_MACSUSPEND since the mac ++ * is suspended and brcms_c_enable_mac() will clear this override bit. ++ */ ++ mboolset(wlc_hw->wake_override, BRCMS_WAKE_OVERRIDE_MACSUSPEND); ++ ++ /* ++ * initialize mac_suspend_depth to 1 to match ucode ++ * initial suspended state ++ */ ++ wlc_hw->mac_suspend_depth = 1; ++ ++ /* restore the clk */ ++ if (!fastclk) ++ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); ++} ++ ++static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc, ++ u16 chanspec) ++{ ++ /* Save our copy of the chanspec */ ++ wlc->chanspec = chanspec; ++ ++ /* Set the chanspec and power limits for this locale */ ++ brcms_c_channel_set_chanspec(wlc->cmi, chanspec, BRCMS_TXPWR_MAX); ++ ++ if (wlc->stf->ss_algosel_auto) ++ brcms_c_stf_ss_algo_channel_get(wlc, &wlc->stf->ss_algo_channel, ++ chanspec); ++ ++ brcms_c_stf_ss_update(wlc, wlc->band); ++} ++ ++static void ++brcms_default_rateset(struct brcms_c_info *wlc, struct brcms_c_rateset *rs) ++{ ++ brcms_c_rateset_default(rs, NULL, wlc->band->phytype, ++ wlc->band->bandtype, false, BRCMS_RATE_MASK_FULL, ++ (bool) (wlc->pub->_n_enab & SUPPORT_11N), ++ brcms_chspec_bw(wlc->default_bss->chanspec), ++ wlc->stf->txstreams); ++} ++ ++/* derive wlc->band->basic_rate[] table from 'rateset' */ ++static void brcms_c_rate_lookup_init(struct brcms_c_info *wlc, ++ struct brcms_c_rateset *rateset) ++{ ++ u8 rate; ++ u8 mandatory; ++ u8 cck_basic = 0; ++ u8 ofdm_basic = 0; ++ u8 *br = wlc->band->basic_rate; ++ uint i; ++ ++ /* incoming rates are in 500kbps units as in 802.11 Supported Rates */ ++ memset(br, 0, BRCM_MAXRATE + 1); ++ ++ /* For each basic rate in the rates list, make an entry in the ++ * best basic lookup. ++ */ ++ for (i = 0; i < rateset->count; i++) { ++ /* only make an entry for a basic rate */ ++ if (!(rateset->rates[i] & BRCMS_RATE_FLAG)) ++ continue; ++ ++ /* mask off basic bit */ ++ rate = (rateset->rates[i] & BRCMS_RATE_MASK); ++ ++ if (rate > BRCM_MAXRATE) { ++ wiphy_err(wlc->wiphy, "brcms_c_rate_lookup_init: " ++ "invalid rate 0x%X in rate set\n", ++ rateset->rates[i]); ++ continue; ++ } ++ ++ br[rate] = rate; ++ } ++ ++ /* The rate lookup table now has non-zero entries for each ++ * basic rate, equal to the basic rate: br[basicN] = basicN ++ * ++ * To look up the best basic rate corresponding to any ++ * particular rate, code can use the basic_rate table ++ * like this ++ * ++ * basic_rate = wlc->band->basic_rate[tx_rate] ++ * ++ * Make sure there is a best basic rate entry for ++ * every rate by walking up the table from low rates ++ * to high, filling in holes in the lookup table ++ */ ++ ++ for (i = 0; i < wlc->band->hw_rateset.count; i++) { ++ rate = wlc->band->hw_rateset.rates[i]; ++ ++ if (br[rate] != 0) { ++ /* This rate is a basic rate. ++ * Keep track of the best basic rate so far by ++ * modulation type. ++ */ ++ if (is_ofdm_rate(rate)) ++ ofdm_basic = rate; ++ else ++ cck_basic = rate; ++ ++ continue; ++ } ++ ++ /* This rate is not a basic rate so figure out the ++ * best basic rate less than this rate and fill in ++ * the hole in the table ++ */ ++ ++ br[rate] = is_ofdm_rate(rate) ? ofdm_basic : cck_basic; ++ ++ if (br[rate] != 0) ++ continue; ++ ++ if (is_ofdm_rate(rate)) { ++ /* ++ * In 11g and 11a, the OFDM mandatory rates ++ * are 6, 12, and 24 Mbps ++ */ ++ if (rate >= BRCM_RATE_24M) ++ mandatory = BRCM_RATE_24M; ++ else if (rate >= BRCM_RATE_12M) ++ mandatory = BRCM_RATE_12M; ++ else ++ mandatory = BRCM_RATE_6M; ++ } else { ++ /* In 11b, all CCK rates are mandatory 1 - 11 Mbps */ ++ mandatory = rate; ++ } ++ ++ br[rate] = mandatory; ++ } ++} ++ ++static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc, ++ u16 chanspec) ++{ ++ struct brcms_c_rateset default_rateset; ++ uint parkband; ++ uint i, band_order[2]; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ /* ++ * We might have been bandlocked during down and the chip ++ * power-cycled (hibernate). Figure out the right band to park on ++ */ ++ if (wlc->bandlocked || wlc->pub->_nbands == 1) { ++ /* updated in brcms_c_bandlock() */ ++ parkband = wlc->band->bandunit; ++ band_order[0] = band_order[1] = parkband; ++ } else { ++ /* park on the band of the specified chanspec */ ++ parkband = chspec_bandunit(chanspec); ++ ++ /* order so that parkband initialize last */ ++ band_order[0] = parkband ^ 1; ++ band_order[1] = parkband; ++ } ++ ++ /* make each band operational, software state init */ ++ for (i = 0; i < wlc->pub->_nbands; i++) { ++ uint j = band_order[i]; ++ ++ wlc->band = wlc->bandstate[j]; ++ ++ brcms_default_rateset(wlc, &default_rateset); ++ ++ /* fill in hw_rate */ ++ brcms_c_rateset_filter(&default_rateset, &wlc->band->hw_rateset, ++ false, BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK, ++ (bool) (wlc->pub->_n_enab & SUPPORT_11N)); ++ ++ /* init basic rate lookup */ ++ brcms_c_rate_lookup_init(wlc, &default_rateset); ++ } ++ ++ /* sync up phy/radio chanspec */ ++ brcms_c_set_phy_chanspec(wlc, chanspec); ++} ++ ++static void brcms_c_mac_bcn_promisc(struct brcms_c_info *wlc) ++{ ++ if (wlc->bcnmisc_monitor) ++ brcms_b_mctrl(wlc->hw, MCTL_BCNS_PROMISC, MCTL_BCNS_PROMISC); ++ else ++ brcms_b_mctrl(wlc->hw, MCTL_BCNS_PROMISC, 0); ++} ++ ++void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc, bool promisc) ++{ ++ wlc->bcnmisc_monitor = promisc; ++ brcms_c_mac_bcn_promisc(wlc); ++} ++ ++/* set or clear maccontrol bits MCTL_PROMISC and MCTL_KEEPCONTROL */ ++static void brcms_c_mac_promisc(struct brcms_c_info *wlc) ++{ ++ u32 promisc_bits = 0; ++ ++ /* ++ * promiscuous mode just sets MCTL_PROMISC ++ * Note: APs get all BSS traffic without the need to set ++ * the MCTL_PROMISC bit since all BSS data traffic is ++ * directed at the AP ++ */ ++ if (wlc->pub->promisc) ++ promisc_bits |= MCTL_PROMISC; ++ ++ /* monitor mode needs both MCTL_PROMISC and MCTL_KEEPCONTROL ++ * Note: monitor mode also needs MCTL_BCNS_PROMISC, but that is ++ * handled in brcms_c_mac_bcn_promisc() ++ */ ++ if (wlc->monitor) ++ promisc_bits |= MCTL_PROMISC | MCTL_KEEPCONTROL; ++ ++ brcms_b_mctrl(wlc->hw, MCTL_PROMISC | MCTL_KEEPCONTROL, promisc_bits); ++} ++ ++/* ++ * ucode, hwmac update ++ * Channel dependent updates for ucode and hw ++ */ ++static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc) ++{ ++ /* enable or disable any active IBSSs depending on whether or not ++ * we are on the home channel ++ */ ++ if (wlc->home_chanspec == wlc_phy_chanspec_get(wlc->band->pi)) { ++ if (wlc->pub->associated) { ++ /* ++ * BMAC_NOTE: This is something that should be fixed ++ * in ucode inits. I think that the ucode inits set ++ * up the bcn templates and shm values with a bogus ++ * beacon. This should not be done in the inits. If ++ * ucode needs to set up a beacon for testing, the ++ * test routines should write it down, not expect the ++ * inits to populate a bogus beacon. ++ */ ++ if (BRCMS_PHY_11N_CAP(wlc->band)) ++ brcms_b_write_shm(wlc->hw, ++ M_BCN_TXTSF_OFFSET, 0); ++ } ++ } else { ++ /* disable an active IBSS if we are not on the home channel */ ++ } ++ ++ /* update the various promisc bits */ ++ brcms_c_mac_bcn_promisc(wlc); ++ brcms_c_mac_promisc(wlc); ++} ++ ++static void brcms_c_write_rate_shm(struct brcms_c_info *wlc, u8 rate, ++ u8 basic_rate) ++{ ++ u8 phy_rate, index; ++ u8 basic_phy_rate, basic_index; ++ u16 dir_table, basic_table; ++ u16 basic_ptr; ++ ++ /* Shared memory address for the table we are reading */ ++ dir_table = is_ofdm_rate(basic_rate) ? M_RT_DIRMAP_A : M_RT_DIRMAP_B; ++ ++ /* Shared memory address for the table we are writing */ ++ basic_table = is_ofdm_rate(rate) ? M_RT_BBRSMAP_A : M_RT_BBRSMAP_B; ++ ++ /* ++ * for a given rate, the LS-nibble of the PLCP SIGNAL field is ++ * the index into the rate table. ++ */ ++ phy_rate = rate_info[rate] & BRCMS_RATE_MASK; ++ basic_phy_rate = rate_info[basic_rate] & BRCMS_RATE_MASK; ++ index = phy_rate & 0xf; ++ basic_index = basic_phy_rate & 0xf; ++ ++ /* Find the SHM pointer to the ACK rate entry by looking in the ++ * Direct-map Table ++ */ ++ basic_ptr = brcms_b_read_shm(wlc->hw, (dir_table + basic_index * 2)); ++ ++ /* Update the SHM BSS-basic-rate-set mapping table with the pointer ++ * to the correct basic rate for the given incoming rate ++ */ ++ brcms_b_write_shm(wlc->hw, (basic_table + index * 2), basic_ptr); ++} ++ ++static const struct brcms_c_rateset * ++brcms_c_rateset_get_hwrs(struct brcms_c_info *wlc) ++{ ++ const struct brcms_c_rateset *rs_dflt; ++ ++ if (BRCMS_PHY_11N_CAP(wlc->band)) { ++ if (wlc->band->bandtype == BRCM_BAND_5G) ++ rs_dflt = &ofdm_mimo_rates; ++ else ++ rs_dflt = &cck_ofdm_mimo_rates; ++ } else if (wlc->band->gmode) ++ rs_dflt = &cck_ofdm_rates; ++ else ++ rs_dflt = &cck_rates; ++ ++ return rs_dflt; ++} ++ ++static void brcms_c_set_ratetable(struct brcms_c_info *wlc) ++{ ++ const struct brcms_c_rateset *rs_dflt; ++ struct brcms_c_rateset rs; ++ u8 rate, basic_rate; ++ uint i; ++ ++ rs_dflt = brcms_c_rateset_get_hwrs(wlc); ++ ++ brcms_c_rateset_copy(rs_dflt, &rs); ++ brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams); ++ ++ /* walk the phy rate table and update SHM basic rate lookup table */ ++ for (i = 0; i < rs.count; i++) { ++ rate = rs.rates[i] & BRCMS_RATE_MASK; ++ ++ /* for a given rate brcms_basic_rate returns the rate at ++ * which a response ACK/CTS should be sent. ++ */ ++ basic_rate = brcms_basic_rate(wlc, rate); ++ if (basic_rate == 0) ++ /* This should only happen if we are using a ++ * restricted rateset. ++ */ ++ basic_rate = rs.rates[0] & BRCMS_RATE_MASK; ++ ++ brcms_c_write_rate_shm(wlc, rate, basic_rate); ++ } ++} ++ ++/* band-specific init */ ++static void brcms_c_bsinit(struct brcms_c_info *wlc) ++{ ++ BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", ++ wlc->pub->unit, wlc->band->bandunit); ++ ++ /* write ucode ACK/CTS rate table */ ++ brcms_c_set_ratetable(wlc); ++ ++ /* update some band specific mac configuration */ ++ brcms_c_ucode_mac_upd(wlc); ++ ++ /* init antenna selection */ ++ brcms_c_antsel_init(wlc->asi); ++ ++} ++ ++/* formula: IDLE_BUSY_RATIO_X_16 = (100-duty_cycle)/duty_cycle*16 */ ++static int ++brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle, bool isOFDM, ++ bool writeToShm) ++{ ++ int idle_busy_ratio_x_16 = 0; ++ uint offset = ++ isOFDM ? M_TX_IDLE_BUSY_RATIO_X_16_OFDM : ++ M_TX_IDLE_BUSY_RATIO_X_16_CCK; ++ if (duty_cycle > 100 || duty_cycle < 0) { ++ wiphy_err(wlc->wiphy, "wl%d: duty cycle value off limit\n", ++ wlc->pub->unit); ++ return -EINVAL; ++ } ++ if (duty_cycle) ++ idle_busy_ratio_x_16 = (100 - duty_cycle) * 16 / duty_cycle; ++ /* Only write to shared memory when wl is up */ ++ if (writeToShm) ++ brcms_b_write_shm(wlc->hw, offset, (u16) idle_busy_ratio_x_16); ++ ++ if (isOFDM) ++ wlc->tx_duty_cycle_ofdm = (u16) duty_cycle; ++ else ++ wlc->tx_duty_cycle_cck = (u16) duty_cycle; ++ ++ return 0; ++} ++ ++/* ++ * Initialize the base precedence map for dequeueing ++ * from txq based on WME settings ++ */ ++static void brcms_c_tx_prec_map_init(struct brcms_c_info *wlc) ++{ ++ wlc->tx_prec_map = BRCMS_PREC_BMP_ALL; ++ memset(wlc->fifo2prec_map, 0, NFIFO * sizeof(u16)); ++ ++ wlc->fifo2prec_map[TX_AC_BK_FIFO] = BRCMS_PREC_BMP_AC_BK; ++ wlc->fifo2prec_map[TX_AC_BE_FIFO] = BRCMS_PREC_BMP_AC_BE; ++ wlc->fifo2prec_map[TX_AC_VI_FIFO] = BRCMS_PREC_BMP_AC_VI; ++ wlc->fifo2prec_map[TX_AC_VO_FIFO] = BRCMS_PREC_BMP_AC_VO; ++} ++ ++static void ++brcms_c_txflowcontrol_signal(struct brcms_c_info *wlc, ++ struct brcms_txq_info *qi, bool on, int prio) ++{ ++ /* transmit flowcontrol is not yet implemented */ ++} ++ ++static void brcms_c_txflowcontrol_reset(struct brcms_c_info *wlc) ++{ ++ struct brcms_txq_info *qi; ++ ++ for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) { ++ if (qi->stopped) { ++ brcms_c_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO); ++ qi->stopped = 0; ++ } ++ } ++} ++ ++/* push sw hps and wake state through hardware */ ++static void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc) ++{ ++ u32 v1, v2; ++ bool hps; ++ bool awake_before; ++ ++ hps = brcms_c_ps_allowed(wlc); ++ ++ BCMMSG(wlc->wiphy, "wl%d: hps %d\n", wlc->pub->unit, hps); ++ ++ v1 = R_REG(&wlc->regs->maccontrol); ++ v2 = MCTL_WAKE; ++ if (hps) ++ v2 |= MCTL_HPS; ++ ++ brcms_b_mctrl(wlc->hw, MCTL_WAKE | MCTL_HPS, v2); ++ ++ awake_before = ((v1 & MCTL_WAKE) || ((v1 & MCTL_HPS) == 0)); ++ ++ if (!awake_before) ++ brcms_b_wait_for_wake(wlc->hw); ++} ++ ++/* ++ * Write this BSS config's MAC address to core. ++ * Updates RXE match engine. ++ */ ++static int brcms_c_set_mac(struct brcms_bss_cfg *bsscfg) ++{ ++ int err = 0; ++ struct brcms_c_info *wlc = bsscfg->wlc; ++ ++ /* enter the MAC addr into the RXE match registers */ ++ brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, bsscfg->cur_etheraddr); ++ ++ brcms_c_ampdu_macaddr_upd(wlc); ++ ++ return err; ++} ++ ++/* Write the BSS config's BSSID address to core (set_bssid in d11procs.tcl). ++ * Updates RXE match engine. ++ */ ++static void brcms_c_set_bssid(struct brcms_bss_cfg *bsscfg) ++{ ++ /* we need to update BSSID in RXE match registers */ ++ brcms_c_set_addrmatch(bsscfg->wlc, RCM_BSSID_OFFSET, bsscfg->BSSID); ++} ++ ++static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot) ++{ ++ wlc_hw->shortslot = shortslot; ++ ++ if (wlc_hw->band->bandtype == BRCM_BAND_2G && wlc_hw->up) { ++ brcms_c_suspend_mac_and_wait(wlc_hw->wlc); ++ brcms_b_update_slot_timing(wlc_hw, shortslot); ++ brcms_c_enable_mac(wlc_hw->wlc); ++ } ++} ++ ++/* ++ * Suspend the the MAC and update the slot timing ++ * for standard 11b/g (20us slots) or shortslot 11g (9us slots). ++ */ ++static void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot) ++{ ++ /* use the override if it is set */ ++ if (wlc->shortslot_override != BRCMS_SHORTSLOT_AUTO) ++ shortslot = (wlc->shortslot_override == BRCMS_SHORTSLOT_ON); ++ ++ if (wlc->shortslot == shortslot) ++ return; ++ ++ wlc->shortslot = shortslot; ++ ++ brcms_b_set_shortslot(wlc->hw, shortslot); ++} ++ ++static void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec) ++{ ++ if (wlc->home_chanspec != chanspec) { ++ wlc->home_chanspec = chanspec; ++ ++ if (wlc->bsscfg->associated) ++ wlc->bsscfg->current_bss->chanspec = chanspec; ++ } ++} ++ ++void ++brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec, ++ bool mute, struct txpwr_limits *txpwr) ++{ ++ uint bandunit; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d: 0x%x\n", wlc_hw->unit, chanspec); ++ ++ wlc_hw->chanspec = chanspec; ++ ++ /* Switch bands if necessary */ ++ if (wlc_hw->_nbands > 1) { ++ bandunit = chspec_bandunit(chanspec); ++ if (wlc_hw->band->bandunit != bandunit) { ++ /* brcms_b_setband disables other bandunit, ++ * use light band switch if not up yet ++ */ ++ if (wlc_hw->up) { ++ wlc_phy_chanspec_radio_set(wlc_hw-> ++ bandstate[bandunit]-> ++ pi, chanspec); ++ brcms_b_setband(wlc_hw, bandunit, chanspec); ++ } else { ++ brcms_c_setxband(wlc_hw, bandunit); ++ } ++ } ++ } ++ ++ wlc_phy_initcal_enable(wlc_hw->band->pi, !mute); ++ ++ if (!wlc_hw->up) { ++ if (wlc_hw->clk) ++ wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, ++ chanspec); ++ wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec); ++ } else { ++ wlc_phy_chanspec_set(wlc_hw->band->pi, chanspec); ++ wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, chanspec); ++ ++ /* Update muting of the channel */ ++ brcms_b_mute(wlc_hw, mute, 0); ++ } ++} ++ ++/* switch to and initialize new band */ ++static void brcms_c_setband(struct brcms_c_info *wlc, ++ uint bandunit) ++{ ++ wlc->band = wlc->bandstate[bandunit]; ++ ++ if (!wlc->pub->up) ++ return; ++ ++ /* wait for at least one beacon before entering sleeping state */ ++ brcms_c_set_ps_ctrl(wlc); ++ ++ /* band-specific initializations */ ++ brcms_c_bsinit(wlc); ++} ++ ++static void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec) ++{ ++ uint bandunit; ++ bool switchband = false; ++ u16 old_chanspec = wlc->chanspec; ++ ++ if (!brcms_c_valid_chanspec_db(wlc->cmi, chanspec)) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Bad channel %d\n", ++ wlc->pub->unit, __func__, CHSPEC_CHANNEL(chanspec)); ++ return; ++ } ++ ++ /* Switch bands if necessary */ ++ if (wlc->pub->_nbands > 1) { ++ bandunit = chspec_bandunit(chanspec); ++ if (wlc->band->bandunit != bandunit || wlc->bandinit_pending) { ++ switchband = true; ++ if (wlc->bandlocked) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: chspec %d " ++ "band is locked!\n", ++ wlc->pub->unit, __func__, ++ CHSPEC_CHANNEL(chanspec)); ++ return; ++ } ++ /* ++ * should the setband call come after the ++ * brcms_b_chanspec() ? if the setband updates ++ * (brcms_c_bsinit) use low level calls to inspect and ++ * set state, the state inspected may be from the wrong ++ * band, or the following brcms_b_set_chanspec() may ++ * undo the work. ++ */ ++ brcms_c_setband(wlc, bandunit); ++ } ++ } ++ ++ /* sync up phy/radio chanspec */ ++ brcms_c_set_phy_chanspec(wlc, chanspec); ++ ++ /* init antenna selection */ ++ if (brcms_chspec_bw(old_chanspec) != brcms_chspec_bw(chanspec)) { ++ brcms_c_antsel_init(wlc->asi); ++ ++ /* Fix the hardware rateset based on bw. ++ * Mainly add MCS32 for 40Mhz, remove MCS 32 for 20Mhz ++ */ ++ brcms_c_rateset_bw_mcs_filter(&wlc->band->hw_rateset, ++ wlc->band->mimo_cap_40 ? brcms_chspec_bw(chanspec) : 0); ++ } ++ ++ /* update some mac configuration since chanspec changed */ ++ brcms_c_ucode_mac_upd(wlc); ++} ++ ++/* ++ * This function changes the phytxctl for beacon based on current ++ * beacon ratespec AND txant setting as per this table: ++ * ratespec CCK ant = wlc->stf->txant ++ * OFDM ant = 3 ++ */ ++void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, ++ u32 bcn_rspec) ++{ ++ u16 phyctl; ++ u16 phytxant = wlc->stf->phytxant; ++ u16 mask = PHY_TXC_ANT_MASK; ++ ++ /* for non-siso rates or default setting, use the available chains */ ++ if (BRCMS_PHY_11N_CAP(wlc->band)) ++ phytxant = brcms_c_stf_phytxchain_sel(wlc, bcn_rspec); ++ ++ phyctl = brcms_b_read_shm(wlc->hw, M_BCN_PCTLWD); ++ phyctl = (phyctl & ~mask) | phytxant; ++ brcms_b_write_shm(wlc->hw, M_BCN_PCTLWD, phyctl); ++} ++ ++/* ++ * centralized protection config change function to simplify debugging, no ++ * consistency checking this should be called only on changes to avoid overhead ++ * in periodic function ++ */ ++void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val) ++{ ++ BCMMSG(wlc->wiphy, "idx %d, val %d\n", idx, val); ++ ++ switch (idx) { ++ case BRCMS_PROT_G_SPEC: ++ wlc->protection->_g = (bool) val; ++ break; ++ case BRCMS_PROT_G_OVR: ++ wlc->protection->g_override = (s8) val; ++ break; ++ case BRCMS_PROT_G_USER: ++ wlc->protection->gmode_user = (u8) val; ++ break; ++ case BRCMS_PROT_OVERLAP: ++ wlc->protection->overlap = (s8) val; ++ break; ++ case BRCMS_PROT_N_USER: ++ wlc->protection->nmode_user = (s8) val; ++ break; ++ case BRCMS_PROT_N_CFG: ++ wlc->protection->n_cfg = (s8) val; ++ break; ++ case BRCMS_PROT_N_CFG_OVR: ++ wlc->protection->n_cfg_override = (s8) val; ++ break; ++ case BRCMS_PROT_N_NONGF: ++ wlc->protection->nongf = (bool) val; ++ break; ++ case BRCMS_PROT_N_NONGF_OVR: ++ wlc->protection->nongf_override = (s8) val; ++ break; ++ case BRCMS_PROT_N_PAM_OVR: ++ wlc->protection->n_pam_override = (s8) val; ++ break; ++ case BRCMS_PROT_N_OBSS: ++ wlc->protection->n_obss = (bool) val; ++ break; ++ ++ default: ++ break; ++ } ++ ++} ++ ++static void brcms_c_ht_update_sgi_rx(struct brcms_c_info *wlc, int val) ++{ ++ if (wlc->pub->up) { ++ brcms_c_update_beacon(wlc); ++ brcms_c_update_probe_resp(wlc, true); ++ } ++} ++ ++static void brcms_c_ht_update_ldpc(struct brcms_c_info *wlc, s8 val) ++{ ++ wlc->stf->ldpc = val; ++ ++ if (wlc->pub->up) { ++ brcms_c_update_beacon(wlc); ++ brcms_c_update_probe_resp(wlc, true); ++ wlc_phy_ldpc_override_set(wlc->band->pi, (val ? true : false)); ++ } ++} ++ ++void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci, ++ const struct ieee80211_tx_queue_params *params, ++ bool suspend) ++{ ++ int i; ++ struct shm_acparams acp_shm; ++ u16 *shm_entry; ++ ++ /* Only apply params if the core is out of reset and has clocks */ ++ if (!wlc->clk) { ++ wiphy_err(wlc->wiphy, "wl%d: %s : no-clock\n", wlc->pub->unit, ++ __func__); ++ return; ++ } ++ ++ memset((char *)&acp_shm, 0, sizeof(struct shm_acparams)); ++ /* fill in shm ac params struct */ ++ acp_shm.txop = params->txop; ++ /* convert from units of 32us to us for ucode */ ++ wlc->edcf_txop[aci & 0x3] = acp_shm.txop = ++ EDCF_TXOP2USEC(acp_shm.txop); ++ acp_shm.aifs = (params->aifs & EDCF_AIFSN_MASK); ++ ++ if (aci == AC_VI && acp_shm.txop == 0 ++ && acp_shm.aifs < EDCF_AIFSN_MAX) ++ acp_shm.aifs++; ++ ++ if (acp_shm.aifs < EDCF_AIFSN_MIN ++ || acp_shm.aifs > EDCF_AIFSN_MAX) { ++ wiphy_err(wlc->wiphy, "wl%d: edcf_setparams: bad " ++ "aifs %d\n", wlc->pub->unit, acp_shm.aifs); ++ } else { ++ acp_shm.cwmin = params->cw_min; ++ acp_shm.cwmax = params->cw_max; ++ acp_shm.cwcur = acp_shm.cwmin; ++ acp_shm.bslots = ++ R_REG(&wlc->regs->tsf_random) & acp_shm.cwcur; ++ acp_shm.reggap = acp_shm.bslots + acp_shm.aifs; ++ /* Indicate the new params to the ucode */ ++ acp_shm.status = brcms_b_read_shm(wlc->hw, (M_EDCF_QINFO + ++ wme_ac2fifo[aci] * ++ M_EDCF_QLEN + ++ M_EDCF_STATUS_OFF)); ++ acp_shm.status |= WME_STATUS_NEWAC; ++ ++ /* Fill in shm acparam table */ ++ shm_entry = (u16 *) &acp_shm; ++ for (i = 0; i < (int)sizeof(struct shm_acparams); i += 2) ++ brcms_b_write_shm(wlc->hw, ++ M_EDCF_QINFO + ++ wme_ac2fifo[aci] * M_EDCF_QLEN + i, ++ *shm_entry++); ++ } ++ ++ if (suspend) { ++ brcms_c_suspend_mac_and_wait(wlc); ++ brcms_c_enable_mac(wlc); ++ } ++} ++ ++void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend) ++{ ++ u16 aci; ++ int i_ac; ++ struct ieee80211_tx_queue_params txq_pars; ++ static const struct edcf_acparam default_edcf_acparams[] = { ++ {EDCF_AC_BE_ACI_STA, EDCF_AC_BE_ECW_STA, EDCF_AC_BE_TXOP_STA}, ++ {EDCF_AC_BK_ACI_STA, EDCF_AC_BK_ECW_STA, EDCF_AC_BK_TXOP_STA}, ++ {EDCF_AC_VI_ACI_STA, EDCF_AC_VI_ECW_STA, EDCF_AC_VI_TXOP_STA}, ++ {EDCF_AC_VO_ACI_STA, EDCF_AC_VO_ECW_STA, EDCF_AC_VO_TXOP_STA} ++ }; /* ucode needs these parameters during its initialization */ ++ const struct edcf_acparam *edcf_acp = &default_edcf_acparams[0]; ++ ++ for (i_ac = 0; i_ac < AC_COUNT; i_ac++, edcf_acp++) { ++ /* find out which ac this set of params applies to */ ++ aci = (edcf_acp->ACI & EDCF_ACI_MASK) >> EDCF_ACI_SHIFT; ++ ++ /* fill in shm ac params struct */ ++ txq_pars.txop = edcf_acp->TXOP; ++ txq_pars.aifs = edcf_acp->ACI; ++ ++ /* CWmin = 2^(ECWmin) - 1 */ ++ txq_pars.cw_min = EDCF_ECW2CW(edcf_acp->ECW & EDCF_ECWMIN_MASK); ++ /* CWmax = 2^(ECWmax) - 1 */ ++ txq_pars.cw_max = EDCF_ECW2CW((edcf_acp->ECW & EDCF_ECWMAX_MASK) ++ >> EDCF_ECWMAX_SHIFT); ++ brcms_c_wme_setparams(wlc, aci, &txq_pars, suspend); ++ } ++ ++ if (suspend) { ++ brcms_c_suspend_mac_and_wait(wlc); ++ brcms_c_enable_mac(wlc); ++ } ++} ++ ++/* maintain LED behavior in down state */ ++static void brcms_c_down_led_upd(struct brcms_c_info *wlc) ++{ ++ /* ++ * maintain LEDs while in down state, turn on sbclk if ++ * not available yet. Turn on sbclk if necessary ++ */ ++ brcms_b_pllreq(wlc->hw, true, BRCMS_PLLREQ_FLIP); ++ brcms_b_pllreq(wlc->hw, false, BRCMS_PLLREQ_FLIP); ++} ++ ++static void brcms_c_radio_monitor_start(struct brcms_c_info *wlc) ++{ ++ /* Don't start the timer if HWRADIO feature is disabled */ ++ if (wlc->radio_monitor) ++ return; ++ ++ wlc->radio_monitor = true; ++ brcms_b_pllreq(wlc->hw, true, BRCMS_PLLREQ_RADIO_MON); ++ brcms_add_timer(wlc->radio_timer, TIMER_INTERVAL_RADIOCHK, true); ++} ++ ++static void brcms_c_radio_disable(struct brcms_c_info *wlc) ++{ ++ if (!wlc->pub->up) { ++ brcms_c_down_led_upd(wlc); ++ return; ++ } ++ ++ brcms_c_radio_monitor_start(wlc); ++ brcms_down(wlc->wl); ++} ++ ++static void brcms_c_radio_enable(struct brcms_c_info *wlc) ++{ ++ if (wlc->pub->up) ++ return; ++ ++ if (brcms_deviceremoved(wlc)) ++ return; ++ ++ brcms_up(wlc->wl); ++} ++ ++static bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc) ++{ ++ if (!wlc->radio_monitor) ++ return true; ++ ++ wlc->radio_monitor = false; ++ brcms_b_pllreq(wlc->hw, false, BRCMS_PLLREQ_RADIO_MON); ++ return brcms_del_timer(wlc->radio_timer); ++} ++ ++/* read hwdisable state and propagate to wlc flag */ ++static void brcms_c_radio_hwdisable_upd(struct brcms_c_info *wlc) ++{ ++ if (wlc->pub->hw_off) ++ return; ++ ++ if (brcms_b_radio_read_hwdisabled(wlc->hw)) ++ mboolset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE); ++ else ++ mboolclr(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE); ++} ++ ++/* ++ * centralized radio disable/enable function, ++ * invoke radio enable/disable after updating hwradio status ++ */ ++static void brcms_c_radio_upd(struct brcms_c_info *wlc) ++{ ++ if (wlc->pub->radio_disabled) ++ brcms_c_radio_disable(wlc); ++ else ++ brcms_c_radio_enable(wlc); ++} ++ ++/* update hwradio status and return it */ ++bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc) ++{ ++ brcms_c_radio_hwdisable_upd(wlc); ++ ++ return mboolisset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE) ? ++ true : false; ++} ++ ++/* periodical query hw radio button while driver is "down" */ ++static void brcms_c_radio_timer(void *arg) ++{ ++ struct brcms_c_info *wlc = (struct brcms_c_info *) arg; ++ ++ if (brcms_deviceremoved(wlc)) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit, ++ __func__); ++ brcms_down(wlc->wl); ++ return; ++ } ++ ++ /* cap mpc off count */ ++ if (wlc->mpc_offcnt < BRCMS_MPC_MAX_DELAYCNT) ++ wlc->mpc_offcnt++; ++ ++ brcms_c_radio_hwdisable_upd(wlc); ++ brcms_c_radio_upd(wlc); ++} ++ ++/* common low-level watchdog code */ ++static void brcms_b_watchdog(void *arg) ++{ ++ struct brcms_c_info *wlc = (struct brcms_c_info *) arg; ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ if (!wlc_hw->up) ++ return; ++ ++ /* increment second count */ ++ wlc_hw->now++; ++ ++ /* Check for FIFO error interrupts */ ++ brcms_b_fifoerrors(wlc_hw); ++ ++ /* make sure RX dma has buffers */ ++ dma_rxfill(wlc->hw->di[RX_FIFO]); ++ ++ wlc_phy_watchdog(wlc_hw->band->pi); ++} ++ ++static void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc) ++{ ++ bool mpc_radio, radio_state; ++ ++ /* ++ * Clear the WL_RADIO_MPC_DISABLE bit when mpc feature is disabled ++ * in case the WL_RADIO_MPC_DISABLE bit was set. Stop the radio ++ * monitor also when WL_RADIO_MPC_DISABLE is the only reason that ++ * the radio is going down. ++ */ ++ if (!wlc->mpc) { ++ if (!wlc->pub->radio_disabled) ++ return; ++ mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE); ++ brcms_c_radio_upd(wlc); ++ if (!wlc->pub->radio_disabled) ++ brcms_c_radio_monitor_stop(wlc); ++ return; ++ } ++ ++ /* ++ * sync ismpc logic with WL_RADIO_MPC_DISABLE bit in ++ * wlc->pub->radio_disabled to go ON, always call radio_upd ++ * synchronously to go OFF, postpone radio_upd to later when ++ * context is safe(e.g. watchdog) ++ */ ++ radio_state = ++ (mboolisset(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE) ? OFF : ++ ON); ++ mpc_radio = (brcms_c_ismpc(wlc) == true) ? OFF : ON; ++ ++ if (radio_state == ON && mpc_radio == OFF) ++ wlc->mpc_delay_off = wlc->mpc_dlycnt; ++ else if (radio_state == OFF && mpc_radio == ON) { ++ mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE); ++ brcms_c_radio_upd(wlc); ++ if (wlc->mpc_offcnt < BRCMS_MPC_THRESHOLD) ++ wlc->mpc_dlycnt = BRCMS_MPC_MAX_DELAYCNT; ++ else ++ wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT; ++ } ++ /* ++ * Below logic is meant to capture the transition from mpc off ++ * to mpc on for reasons other than wlc->mpc_delay_off keeping ++ * the mpc off. In that case reset wlc->mpc_delay_off to ++ * wlc->mpc_dlycnt, so that we restart the countdown of mpc_delay_off ++ */ ++ if ((wlc->prev_non_delay_mpc == false) && ++ (brcms_c_is_non_delay_mpc(wlc) == true) && wlc->mpc_delay_off) ++ wlc->mpc_delay_off = wlc->mpc_dlycnt; ++ ++ wlc->prev_non_delay_mpc = brcms_c_is_non_delay_mpc(wlc); ++} ++ ++/* common watchdog code */ ++static void brcms_c_watchdog(void *arg) ++{ ++ struct brcms_c_info *wlc = (struct brcms_c_info *) arg; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ ++ if (!wlc->pub->up) ++ return; ++ ++ if (brcms_deviceremoved(wlc)) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit, ++ __func__); ++ brcms_down(wlc->wl); ++ return; ++ } ++ ++ /* increment second count */ ++ wlc->pub->now++; ++ ++ /* delay radio disable */ ++ if (wlc->mpc_delay_off) { ++ if (--wlc->mpc_delay_off == 0) { ++ mboolset(wlc->pub->radio_disabled, ++ WL_RADIO_MPC_DISABLE); ++ if (wlc->mpc && brcms_c_ismpc(wlc)) ++ wlc->mpc_offcnt = 0; ++ } ++ } ++ ++ /* mpc sync */ ++ brcms_c_radio_mpc_upd(wlc); ++ /* radio sync: sw/hw/mpc --> radio_disable/radio_enable */ ++ brcms_c_radio_hwdisable_upd(wlc); ++ brcms_c_radio_upd(wlc); ++ /* if radio is disable, driver may be down, quit here */ ++ if (wlc->pub->radio_disabled) ++ return; ++ ++ brcms_b_watchdog(wlc); ++ ++ /* ++ * occasionally sample mac stat counters to ++ * detect 16-bit counter wrap ++ */ ++ if ((wlc->pub->now % SW_TIMER_MAC_STAT_UPD) == 0) ++ brcms_c_statsupd(wlc); ++ ++ if (BRCMS_ISNPHY(wlc->band) && ++ ((wlc->pub->now - wlc->tempsense_lasttime) >= ++ BRCMS_TEMPSENSE_PERIOD)) { ++ wlc->tempsense_lasttime = wlc->pub->now; ++ brcms_c_tempsense_upd(wlc); ++ } ++} ++ ++static void brcms_c_watchdog_by_timer(void *arg) ++{ ++ brcms_c_watchdog(arg); ++} ++ ++static bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit) ++{ ++ wlc->wdtimer = brcms_init_timer(wlc->wl, brcms_c_watchdog_by_timer, ++ wlc, "watchdog"); ++ if (!wlc->wdtimer) { ++ wiphy_err(wlc->wiphy, "wl%d: wl_init_timer for wdtimer " ++ "failed\n", unit); ++ goto fail; ++ } ++ ++ wlc->radio_timer = brcms_init_timer(wlc->wl, brcms_c_radio_timer, ++ wlc, "radio"); ++ if (!wlc->radio_timer) { ++ wiphy_err(wlc->wiphy, "wl%d: wl_init_timer for radio_timer " ++ "failed\n", unit); ++ goto fail; ++ } ++ ++ return true; ++ ++ fail: ++ return false; ++} ++ ++/* ++ * Initialize brcms_c_info default values ... ++ * may get overrides later in this function ++ */ ++static void brcms_c_info_init(struct brcms_c_info *wlc, int unit) ++{ ++ int i; ++ ++ /* Save our copy of the chanspec */ ++ wlc->chanspec = ch20mhz_chspec(1); ++ ++ /* various 802.11g modes */ ++ wlc->shortslot = false; ++ wlc->shortslot_override = BRCMS_SHORTSLOT_AUTO; ++ ++ brcms_c_protection_upd(wlc, BRCMS_PROT_G_OVR, BRCMS_PROTECTION_AUTO); ++ brcms_c_protection_upd(wlc, BRCMS_PROT_G_SPEC, false); ++ ++ brcms_c_protection_upd(wlc, BRCMS_PROT_N_CFG_OVR, ++ BRCMS_PROTECTION_AUTO); ++ brcms_c_protection_upd(wlc, BRCMS_PROT_N_CFG, BRCMS_N_PROTECTION_OFF); ++ brcms_c_protection_upd(wlc, BRCMS_PROT_N_NONGF_OVR, ++ BRCMS_PROTECTION_AUTO); ++ brcms_c_protection_upd(wlc, BRCMS_PROT_N_NONGF, false); ++ brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR, AUTO); ++ ++ brcms_c_protection_upd(wlc, BRCMS_PROT_OVERLAP, ++ BRCMS_PROTECTION_CTL_OVERLAP); ++ ++ /* 802.11g draft 4.0 NonERP elt advertisement */ ++ wlc->include_legacy_erp = true; ++ ++ wlc->stf->ant_rx_ovr = ANT_RX_DIV_DEF; ++ wlc->stf->txant = ANT_TX_DEF; ++ ++ wlc->prb_resp_timeout = BRCMS_PRB_RESP_TIMEOUT; ++ ++ wlc->usr_fragthresh = DOT11_DEFAULT_FRAG_LEN; ++ for (i = 0; i < NFIFO; i++) ++ wlc->fragthresh[i] = DOT11_DEFAULT_FRAG_LEN; ++ wlc->RTSThresh = DOT11_DEFAULT_RTS_LEN; ++ ++ /* default rate fallback retry limits */ ++ wlc->SFBL = RETRY_SHORT_FB; ++ wlc->LFBL = RETRY_LONG_FB; ++ ++ /* default mac retry limits */ ++ wlc->SRL = RETRY_SHORT_DEF; ++ wlc->LRL = RETRY_LONG_DEF; ++ ++ /* WME QoS mode is Auto by default */ ++ wlc->pub->_ampdu = AMPDU_AGG_HOST; ++ wlc->pub->bcmerror = 0; ++ ++ /* initialize mpc delay */ ++ wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT; ++} ++ ++static uint brcms_c_attach_module(struct brcms_c_info *wlc) ++{ ++ uint err = 0; ++ uint unit; ++ unit = wlc->pub->unit; ++ ++ wlc->asi = brcms_c_antsel_attach(wlc); ++ if (wlc->asi == NULL) { ++ wiphy_err(wlc->wiphy, "wl%d: attach: antsel_attach " ++ "failed\n", unit); ++ err = 44; ++ goto fail; ++ } ++ ++ wlc->ampdu = brcms_c_ampdu_attach(wlc); ++ if (wlc->ampdu == NULL) { ++ wiphy_err(wlc->wiphy, "wl%d: attach: ampdu_attach " ++ "failed\n", unit); ++ err = 50; ++ goto fail; ++ } ++ ++ if ((brcms_c_stf_attach(wlc) != 0)) { ++ wiphy_err(wlc->wiphy, "wl%d: attach: stf_attach " ++ "failed\n", unit); ++ err = 68; ++ goto fail; ++ } ++ fail: ++ return err; ++} ++ ++struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc) ++{ ++ return wlc->pub; ++} ++ ++/* low level attach ++ * run backplane attach, init nvram ++ * run phy attach ++ * initialize software state for each core and band ++ * put the whole chip in reset(driver down state), no clock ++ */ ++static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device, ++ uint unit, bool piomode, void __iomem *regsva, ++ struct pci_dev *btparam) ++{ ++ struct brcms_hardware *wlc_hw; ++ struct d11regs __iomem *regs; ++ char *macaddr = NULL; ++ uint err = 0; ++ uint j; ++ bool wme = false; ++ struct shared_phy_params sha_params; ++ struct wiphy *wiphy = wlc->wiphy; ++ ++ BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, vendor, ++ device); ++ ++ wme = true; ++ ++ wlc_hw = wlc->hw; ++ wlc_hw->wlc = wlc; ++ wlc_hw->unit = unit; ++ wlc_hw->band = wlc_hw->bandstate[0]; ++ wlc_hw->_piomode = piomode; ++ ++ /* populate struct brcms_hardware with default values */ ++ brcms_b_info_init(wlc_hw); ++ ++ /* ++ * Do the hardware portion of the attach. Also initialize software ++ * state that depends on the particular hardware we are running. ++ */ ++ wlc_hw->sih = ai_attach(regsva, btparam); ++ if (wlc_hw->sih == NULL) { ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: si_attach failed\n", ++ unit); ++ err = 11; ++ goto fail; ++ } ++ ++ /* verify again the device is supported */ ++ if (!brcms_c_chipmatch(vendor, device)) { ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported " ++ "vendor/device (0x%x/0x%x)\n", ++ unit, vendor, device); ++ err = 12; ++ goto fail; ++ } ++ ++ wlc_hw->vendorid = vendor; ++ wlc_hw->deviceid = device; ++ ++ /* set bar0 window to point at D11 core */ ++ wlc_hw->regs = (struct d11regs __iomem *) ++ ai_setcore(wlc_hw->sih, D11_CORE_ID, 0); ++ wlc_hw->corerev = ai_corerev(wlc_hw->sih); ++ ++ regs = wlc_hw->regs; ++ ++ wlc->regs = wlc_hw->regs; ++ ++ /* validate chip, chiprev and corerev */ ++ if (!brcms_c_isgoodchip(wlc_hw)) { ++ err = 13; ++ goto fail; ++ } ++ ++ /* initialize power control registers */ ++ ai_clkctl_init(wlc_hw->sih); ++ ++ /* request fastclock and force fastclock for the rest of attach ++ * bring the d11 core out of reset. ++ * For PMU chips, the first wlc_clkctl_clk is no-op since core-clk ++ * is still false; But it will be called again inside wlc_corereset, ++ * after d11 is out of reset. ++ */ ++ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); ++ brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); ++ ++ if (!brcms_b_validate_chip_access(wlc_hw)) { ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: validate_chip_access " ++ "failed\n", unit); ++ err = 14; ++ goto fail; ++ } ++ ++ /* get the board rev, used just below */ ++ j = getintvar(wlc_hw->sih, BRCMS_SROM_BOARDREV); ++ /* promote srom boardrev of 0xFF to 1 */ ++ if (j == BOARDREV_PROMOTABLE) ++ j = BOARDREV_PROMOTED; ++ wlc_hw->boardrev = (u16) j; ++ if (!brcms_c_validboardtype(wlc_hw)) { ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported Broadcom " ++ "board type (0x%x)" " or revision level (0x%x)\n", ++ unit, wlc_hw->sih->boardtype, wlc_hw->boardrev); ++ err = 15; ++ goto fail; ++ } ++ wlc_hw->sromrev = (u8) getintvar(wlc_hw->sih, BRCMS_SROM_REV); ++ wlc_hw->boardflags = (u32) getintvar(wlc_hw->sih, ++ BRCMS_SROM_BOARDFLAGS); ++ wlc_hw->boardflags2 = (u32) getintvar(wlc_hw->sih, ++ BRCMS_SROM_BOARDFLAGS2); ++ ++ if (wlc_hw->boardflags & BFL_NOPLLDOWN) ++ brcms_b_pllreq(wlc_hw, true, BRCMS_PLLREQ_SHARED); ++ ++ /* check device id(srom, nvram etc.) to set bands */ ++ if (wlc_hw->deviceid == BCM43224_D11N_ID || ++ wlc_hw->deviceid == BCM43224_D11N_ID_VEN1) ++ /* Dualband boards */ ++ wlc_hw->_nbands = 2; ++ else ++ wlc_hw->_nbands = 1; ++ ++ if ((wlc_hw->sih->chip == BCM43225_CHIP_ID)) ++ wlc_hw->_nbands = 1; ++ ++ /* BMAC_NOTE: remove init of pub values when brcms_c_attach() ++ * unconditionally does the init of these values ++ */ ++ wlc->vendorid = wlc_hw->vendorid; ++ wlc->deviceid = wlc_hw->deviceid; ++ wlc->pub->sih = wlc_hw->sih; ++ wlc->pub->corerev = wlc_hw->corerev; ++ wlc->pub->sromrev = wlc_hw->sromrev; ++ wlc->pub->boardrev = wlc_hw->boardrev; ++ wlc->pub->boardflags = wlc_hw->boardflags; ++ wlc->pub->boardflags2 = wlc_hw->boardflags2; ++ wlc->pub->_nbands = wlc_hw->_nbands; ++ ++ wlc_hw->physhim = wlc_phy_shim_attach(wlc_hw, wlc->wl, wlc); ++ ++ if (wlc_hw->physhim == NULL) { ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_shim_attach " ++ "failed\n", unit); ++ err = 25; ++ goto fail; ++ } ++ ++ /* pass all the parameters to wlc_phy_shared_attach in one struct */ ++ sha_params.sih = wlc_hw->sih; ++ sha_params.physhim = wlc_hw->physhim; ++ sha_params.unit = unit; ++ sha_params.corerev = wlc_hw->corerev; ++ sha_params.vid = wlc_hw->vendorid; ++ sha_params.did = wlc_hw->deviceid; ++ sha_params.chip = wlc_hw->sih->chip; ++ sha_params.chiprev = wlc_hw->sih->chiprev; ++ sha_params.chippkg = wlc_hw->sih->chippkg; ++ sha_params.sromrev = wlc_hw->sromrev; ++ sha_params.boardtype = wlc_hw->sih->boardtype; ++ sha_params.boardrev = wlc_hw->boardrev; ++ sha_params.boardvendor = wlc_hw->sih->boardvendor; ++ sha_params.boardflags = wlc_hw->boardflags; ++ sha_params.boardflags2 = wlc_hw->boardflags2; ++ sha_params.buscorerev = wlc_hw->sih->buscorerev; ++ ++ /* alloc and save pointer to shared phy state area */ ++ wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params); ++ if (!wlc_hw->phy_sh) { ++ err = 16; ++ goto fail; ++ } ++ ++ /* initialize software state for each core and band */ ++ for (j = 0; j < wlc_hw->_nbands; j++) { ++ /* ++ * band0 is always 2.4Ghz ++ * band1, if present, is 5Ghz ++ */ ++ ++ brcms_c_setxband(wlc_hw, j); ++ ++ wlc_hw->band->bandunit = j; ++ wlc_hw->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G; ++ wlc->band->bandunit = j; ++ wlc->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G; ++ wlc->core->coreidx = ai_coreidx(wlc_hw->sih); ++ ++ wlc_hw->machwcap = R_REG(®s->machwcap); ++ wlc_hw->machwcap_backup = wlc_hw->machwcap; ++ ++ /* init tx fifo size */ ++ wlc_hw->xmtfifo_sz = ++ xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)]; ++ ++ /* Get a phy for this band */ ++ wlc_hw->band->pi = ++ wlc_phy_attach(wlc_hw->phy_sh, regs, ++ wlc_hw->band->bandtype, ++ wlc->wiphy); ++ if (wlc_hw->band->pi == NULL) { ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_" ++ "attach failed\n", unit); ++ err = 17; ++ goto fail; ++ } ++ ++ wlc_phy_machwcap_set(wlc_hw->band->pi, wlc_hw->machwcap); ++ ++ wlc_phy_get_phyversion(wlc_hw->band->pi, &wlc_hw->band->phytype, ++ &wlc_hw->band->phyrev, ++ &wlc_hw->band->radioid, ++ &wlc_hw->band->radiorev); ++ wlc_hw->band->abgphy_encore = ++ wlc_phy_get_encore(wlc_hw->band->pi); ++ wlc->band->abgphy_encore = wlc_phy_get_encore(wlc_hw->band->pi); ++ wlc_hw->band->core_flags = ++ wlc_phy_get_coreflags(wlc_hw->band->pi); ++ ++ /* verify good phy_type & supported phy revision */ ++ if (BRCMS_ISNPHY(wlc_hw->band)) { ++ if (NCONF_HAS(wlc_hw->band->phyrev)) ++ goto good_phy; ++ else ++ goto bad_phy; ++ } else if (BRCMS_ISLCNPHY(wlc_hw->band)) { ++ if (LCNCONF_HAS(wlc_hw->band->phyrev)) ++ goto good_phy; ++ else ++ goto bad_phy; ++ } else { ++ bad_phy: ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: unsupported " ++ "phy type/rev (%d/%d)\n", unit, ++ wlc_hw->band->phytype, wlc_hw->band->phyrev); ++ err = 18; ++ goto fail; ++ } ++ ++ good_phy: ++ /* ++ * BMAC_NOTE: wlc->band->pi should not be set below and should ++ * be done in the high level attach. However we can not make ++ * that change until all low level access is changed to ++ * wlc_hw->band->pi. Instead do the wlc->band->pi init below, ++ * keeping wlc_hw->band->pi as well for incremental update of ++ * low level fns, and cut over low only init when all fns ++ * updated. ++ */ ++ wlc->band->pi = wlc_hw->band->pi; ++ wlc->band->phytype = wlc_hw->band->phytype; ++ wlc->band->phyrev = wlc_hw->band->phyrev; ++ wlc->band->radioid = wlc_hw->band->radioid; ++ wlc->band->radiorev = wlc_hw->band->radiorev; ++ ++ /* default contention windows size limits */ ++ wlc_hw->band->CWmin = APHY_CWMIN; ++ wlc_hw->band->CWmax = PHY_CWMAX; ++ ++ if (!brcms_b_attach_dmapio(wlc, j, wme)) { ++ err = 19; ++ goto fail; ++ } ++ } ++ ++ /* disable core to match driver "down" state */ ++ brcms_c_coredisable(wlc_hw); ++ ++ /* Match driver "down" state */ ++ ai_pci_down(wlc_hw->sih); ++ ++ /* register sb interrupt callback functions */ ++ ai_register_intr_callback(wlc_hw->sih, (void *)brcms_c_wlintrsoff, ++ (void *)brcms_c_wlintrsrestore, NULL, wlc); ++ ++ /* turn off pll and xtal to match driver "down" state */ ++ brcms_b_xtal(wlc_hw, OFF); ++ ++ /* ******************************************************************* ++ * The hardware is in the DOWN state at this point. D11 core ++ * or cores are in reset with clocks off, and the board PLLs ++ * are off if possible. ++ * ++ * Beyond this point, wlc->sbclk == false and chip registers ++ * should not be touched. ++ ********************************************************************* ++ */ ++ ++ /* init etheraddr state variables */ ++ macaddr = brcms_c_get_macaddr(wlc_hw); ++ if (macaddr == NULL) { ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: macaddr not found\n", ++ unit); ++ err = 21; ++ goto fail; ++ } ++ if (!mac_pton(macaddr, wlc_hw->etheraddr) || ++ is_broadcast_ether_addr(wlc_hw->etheraddr) || ++ is_zero_ether_addr(wlc_hw->etheraddr)) { ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr %s\n", ++ unit, macaddr); ++ err = 22; ++ goto fail; ++ } ++ ++ BCMMSG(wlc->wiphy, ++ "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n", ++ wlc_hw->deviceid, wlc_hw->_nbands, ++ wlc_hw->sih->boardtype, macaddr); ++ ++ return err; ++ ++ fail: ++ wiphy_err(wiphy, "wl%d: brcms_b_attach: failed with err %d\n", unit, ++ err); ++ return err; ++} ++ ++static void brcms_c_attach_antgain_init(struct brcms_c_info *wlc) ++{ ++ uint unit; ++ unit = wlc->pub->unit; ++ ++ if ((wlc->band->antgain == -1) && (wlc->pub->sromrev == 1)) { ++ /* default antenna gain for srom rev 1 is 2 dBm (8 qdbm) */ ++ wlc->band->antgain = 8; ++ } else if (wlc->band->antgain == -1) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in" ++ " srom, using 2dB\n", unit, __func__); ++ wlc->band->antgain = 8; ++ } else { ++ s8 gain, fract; ++ /* Older sroms specified gain in whole dbm only. In order ++ * be able to specify qdbm granularity and remain backward ++ * compatible the whole dbms are now encoded in only ++ * low 6 bits and remaining qdbms are encoded in the hi 2 bits. ++ * 6 bit signed number ranges from -32 - 31. ++ * ++ * Examples: ++ * 0x1 = 1 db, ++ * 0xc1 = 1.75 db (1 + 3 quarters), ++ * 0x3f = -1 (-1 + 0 quarters), ++ * 0x7f = -.75 (-1 + 1 quarters) = -3 qdbm. ++ * 0xbf = -.50 (-1 + 2 quarters) = -2 qdbm. ++ */ ++ gain = wlc->band->antgain & 0x3f; ++ gain <<= 2; /* Sign extend */ ++ gain >>= 2; ++ fract = (wlc->band->antgain & 0xc0) >> 6; ++ wlc->band->antgain = 4 * gain + fract; ++ } ++} ++ ++static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc) ++{ ++ int aa; ++ uint unit; ++ int bandtype; ++ struct si_pub *sih = wlc->hw->sih; ++ ++ unit = wlc->pub->unit; ++ bandtype = wlc->band->bandtype; ++ ++ /* get antennas available */ ++ if (bandtype == BRCM_BAND_5G) ++ aa = (s8) getintvar(sih, BRCMS_SROM_AA5G); ++ else ++ aa = (s8) getintvar(sih, BRCMS_SROM_AA2G); ++ ++ if ((aa < 1) || (aa > 15)) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in" ++ " srom (0x%x), using 3\n", unit, __func__, aa); ++ aa = 3; ++ } ++ ++ /* reset the defaults if we have a single antenna */ ++ if (aa == 1) { ++ wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_0; ++ wlc->stf->txant = ANT_TX_FORCE_0; ++ } else if (aa == 2) { ++ wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_1; ++ wlc->stf->txant = ANT_TX_FORCE_1; ++ } else { ++ } ++ ++ /* Compute Antenna Gain */ ++ if (bandtype == BRCM_BAND_5G) ++ wlc->band->antgain = (s8) getintvar(sih, BRCMS_SROM_AG1); ++ else ++ wlc->band->antgain = (s8) getintvar(sih, BRCMS_SROM_AG0); ++ ++ brcms_c_attach_antgain_init(wlc); ++ ++ return true; ++} ++ ++static void brcms_c_bss_default_init(struct brcms_c_info *wlc) ++{ ++ u16 chanspec; ++ struct brcms_band *band; ++ struct brcms_bss_info *bi = wlc->default_bss; ++ ++ /* init default and target BSS with some sane initial values */ ++ memset((char *)(bi), 0, sizeof(struct brcms_bss_info)); ++ bi->beacon_period = BEACON_INTERVAL_DEFAULT; ++ ++ /* fill the default channel as the first valid channel ++ * starting from the 2G channels ++ */ ++ chanspec = ch20mhz_chspec(1); ++ wlc->home_chanspec = bi->chanspec = chanspec; ++ ++ /* find the band of our default channel */ ++ band = wlc->band; ++ if (wlc->pub->_nbands > 1 && ++ band->bandunit != chspec_bandunit(chanspec)) ++ band = wlc->bandstate[OTHERBANDUNIT(wlc)]; ++ ++ /* init bss rates to the band specific default rate set */ ++ brcms_c_rateset_default(&bi->rateset, NULL, band->phytype, ++ band->bandtype, false, BRCMS_RATE_MASK_FULL, ++ (bool) (wlc->pub->_n_enab & SUPPORT_11N), ++ brcms_chspec_bw(chanspec), wlc->stf->txstreams); ++ ++ if (wlc->pub->_n_enab & SUPPORT_11N) ++ bi->flags |= BRCMS_BSS_HT; ++} ++ ++static struct brcms_txq_info *brcms_c_txq_alloc(struct brcms_c_info *wlc) ++{ ++ struct brcms_txq_info *qi, *p; ++ ++ qi = kzalloc(sizeof(struct brcms_txq_info), GFP_ATOMIC); ++ if (qi != NULL) { ++ /* ++ * Have enough room for control packets along with HI watermark ++ * Also, add room to txq for total psq packets if all the SCBs ++ * leave PS mode. The watermark for flowcontrol to OS packets ++ * will remain the same ++ */ ++ brcmu_pktq_init(&qi->q, BRCMS_PREC_COUNT, ++ 2 * BRCMS_DATAHIWAT + PKTQ_LEN_DEFAULT); ++ ++ /* add this queue to the the global list */ ++ p = wlc->tx_queues; ++ if (p == NULL) { ++ wlc->tx_queues = qi; ++ } else { ++ while (p->next != NULL) ++ p = p->next; ++ p->next = qi; ++ } ++ } ++ return qi; ++} ++ ++static void brcms_c_txq_free(struct brcms_c_info *wlc, ++ struct brcms_txq_info *qi) ++{ ++ struct brcms_txq_info *p; ++ ++ if (qi == NULL) ++ return; ++ ++ /* remove the queue from the linked list */ ++ p = wlc->tx_queues; ++ if (p == qi) ++ wlc->tx_queues = p->next; ++ else { ++ while (p != NULL && p->next != qi) ++ p = p->next; ++ if (p != NULL) ++ p->next = p->next->next; ++ } ++ ++ kfree(qi); ++} ++ ++static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap) ++{ ++ uint i; ++ struct brcms_band *band; ++ ++ for (i = 0; i < wlc->pub->_nbands; i++) { ++ band = wlc->bandstate[i]; ++ if (band->bandtype == BRCM_BAND_5G) { ++ if ((bwcap == BRCMS_N_BW_40ALL) ++ || (bwcap == BRCMS_N_BW_20IN2G_40IN5G)) ++ band->mimo_cap_40 = true; ++ else ++ band->mimo_cap_40 = false; ++ } else { ++ if (bwcap == BRCMS_N_BW_40ALL) ++ band->mimo_cap_40 = true; ++ else ++ band->mimo_cap_40 = false; ++ } ++ } ++} ++ ++static void brcms_c_timers_deinit(struct brcms_c_info *wlc) ++{ ++ /* free timer state */ ++ if (wlc->wdtimer) { ++ brcms_free_timer(wlc->wdtimer); ++ wlc->wdtimer = NULL; ++ } ++ if (wlc->radio_timer) { ++ brcms_free_timer(wlc->radio_timer); ++ wlc->radio_timer = NULL; ++ } ++} ++ ++static void brcms_c_detach_module(struct brcms_c_info *wlc) ++{ ++ if (wlc->asi) { ++ brcms_c_antsel_detach(wlc->asi); ++ wlc->asi = NULL; ++ } ++ ++ if (wlc->ampdu) { ++ brcms_c_ampdu_detach(wlc->ampdu); ++ wlc->ampdu = NULL; ++ } ++ ++ brcms_c_stf_detach(wlc); ++} ++ ++/* ++ * low level detach ++ */ ++static int brcms_b_detach(struct brcms_c_info *wlc) ++{ ++ uint i; ++ struct brcms_hw_band *band; ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ int callbacks; ++ ++ callbacks = 0; ++ ++ if (wlc_hw->sih) { ++ /* ++ * detach interrupt sync mechanism since interrupt is disabled ++ * and per-port interrupt object may has been freed. this must ++ * be done before sb core switch ++ */ ++ ai_deregister_intr_callback(wlc_hw->sih); ++ ai_pci_sleep(wlc_hw->sih); ++ } ++ ++ brcms_b_detach_dmapio(wlc_hw); ++ ++ band = wlc_hw->band; ++ for (i = 0; i < wlc_hw->_nbands; i++) { ++ if (band->pi) { ++ /* Detach this band's phy */ ++ wlc_phy_detach(band->pi); ++ band->pi = NULL; ++ } ++ band = wlc_hw->bandstate[OTHERBANDUNIT(wlc)]; ++ } ++ ++ /* Free shared phy state */ ++ kfree(wlc_hw->phy_sh); ++ ++ wlc_phy_shim_detach(wlc_hw->physhim); ++ ++ if (wlc_hw->sih) { ++ ai_detach(wlc_hw->sih); ++ wlc_hw->sih = NULL; ++ } ++ ++ return callbacks; ++ ++} ++ ++/* ++ * Return a count of the number of driver callbacks still pending. ++ * ++ * General policy is that brcms_c_detach can only dealloc/free software states. ++ * It can NOT touch hardware registers since the d11core may be in reset and ++ * clock may not be available. ++ * One exception is sb register access, which is possible if crystal is turned ++ * on after "down" state, driver should avoid software timer with the exception ++ * of radio_monitor. ++ */ ++uint brcms_c_detach(struct brcms_c_info *wlc) ++{ ++ uint callbacks = 0; ++ ++ if (wlc == NULL) ++ return 0; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ ++ callbacks += brcms_b_detach(wlc); ++ ++ /* delete software timers */ ++ if (!brcms_c_radio_monitor_stop(wlc)) ++ callbacks++; ++ ++ brcms_c_channel_mgr_detach(wlc->cmi); ++ ++ brcms_c_timers_deinit(wlc); ++ ++ brcms_c_detach_module(wlc); ++ ++ ++ while (wlc->tx_queues != NULL) ++ brcms_c_txq_free(wlc, wlc->tx_queues); ++ ++ brcms_c_detach_mfree(wlc); ++ return callbacks; ++} ++ ++/* update state that depends on the current value of "ap" */ ++static void brcms_c_ap_upd(struct brcms_c_info *wlc) ++{ ++ /* STA-BSS; short capable */ ++ wlc->PLCPHdr_override = BRCMS_PLCP_SHORT; ++ ++ /* fixup mpc */ ++ wlc->mpc = true; ++} ++ ++/* Initialize just the hardware when coming out of POR or S3/S5 system states */ ++static void brcms_b_hw_up(struct brcms_hardware *wlc_hw) ++{ ++ if (wlc_hw->wlc->pub->hw_up) ++ return; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ /* ++ * Enable pll and xtal, initialize the power control registers, ++ * and force fastclock for the remainder of brcms_c_up(). ++ */ ++ brcms_b_xtal(wlc_hw, ON); ++ ai_clkctl_init(wlc_hw->sih); ++ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); ++ ++ ai_pci_fixcfg(wlc_hw->sih); ++ ++ /* ++ * AI chip doesn't restore bar0win2 on ++ * hibernation/resume, need sw fixup ++ */ ++ if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) || ++ (wlc_hw->sih->chip == BCM43225_CHIP_ID)) ++ wlc_hw->regs = (struct d11regs __iomem *) ++ ai_setcore(wlc_hw->sih, D11_CORE_ID, 0); ++ ++ /* ++ * Inform phy that a POR reset has occurred so ++ * it does a complete phy init ++ */ ++ wlc_phy_por_inform(wlc_hw->band->pi); ++ ++ wlc_hw->ucode_loaded = false; ++ wlc_hw->wlc->pub->hw_up = true; ++ ++ if ((wlc_hw->boardflags & BFL_FEM) ++ && (wlc_hw->sih->chip == BCM4313_CHIP_ID)) { ++ if (! ++ (wlc_hw->boardrev >= 0x1250 ++ && (wlc_hw->boardflags & BFL_FEM_BT))) ++ ai_epa_4313war(wlc_hw->sih); ++ } ++} ++ ++static int brcms_b_up_prep(struct brcms_hardware *wlc_hw) ++{ ++ uint coremask; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ /* ++ * Enable pll and xtal, initialize the power control registers, ++ * and force fastclock for the remainder of brcms_c_up(). ++ */ ++ brcms_b_xtal(wlc_hw, ON); ++ ai_clkctl_init(wlc_hw->sih); ++ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); ++ ++ /* ++ * Configure pci/pcmcia here instead of in brcms_c_attach() ++ * to allow mfg hotswap: down, hotswap (chip power cycle), up. ++ */ ++ coremask = (1 << wlc_hw->wlc->core->coreidx); ++ ++ ai_pci_setup(wlc_hw->sih, coremask); ++ ++ /* ++ * Need to read the hwradio status here to cover the case where the ++ * system is loaded with the hw radio disabled. We do not want to ++ * bring the driver up in this case. ++ */ ++ if (brcms_b_radio_read_hwdisabled(wlc_hw)) { ++ /* put SB PCI in down state again */ ++ ai_pci_down(wlc_hw->sih); ++ brcms_b_xtal(wlc_hw, OFF); ++ return -ENOMEDIUM; ++ } ++ ++ ai_pci_up(wlc_hw->sih); ++ ++ /* reset the d11 core */ ++ brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); ++ ++ return 0; ++} ++ ++static int brcms_b_up_finish(struct brcms_hardware *wlc_hw) ++{ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ wlc_hw->up = true; ++ wlc_phy_hw_state_upd(wlc_hw->band->pi, true); ++ ++ /* FULLY enable dynamic power control and d11 core interrupt */ ++ brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); ++ brcms_intrson(wlc_hw->wlc->wl); ++ return 0; ++} ++ ++/* ++ * Write WME tunable parameters for retransmit/max rate ++ * from wlc struct to ucode ++ */ ++static void brcms_c_wme_retries_write(struct brcms_c_info *wlc) ++{ ++ int ac; ++ ++ /* Need clock to do this */ ++ if (!wlc->clk) ++ return; ++ ++ for (ac = 0; ac < AC_COUNT; ac++) ++ brcms_b_write_shm(wlc->hw, M_AC_TXLMT_ADDR(ac), ++ wlc->wme_retries[ac]); ++} ++ ++/* make interface operational */ ++int brcms_c_up(struct brcms_c_info *wlc) ++{ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ ++ /* HW is turned off so don't try to access it */ ++ if (wlc->pub->hw_off || brcms_deviceremoved(wlc)) ++ return -ENOMEDIUM; ++ ++ if (!wlc->pub->hw_up) { ++ brcms_b_hw_up(wlc->hw); ++ wlc->pub->hw_up = true; ++ } ++ ++ if ((wlc->pub->boardflags & BFL_FEM) ++ && (wlc->pub->sih->chip == BCM4313_CHIP_ID)) { ++ if (wlc->pub->boardrev >= 0x1250 ++ && (wlc->pub->boardflags & BFL_FEM_BT)) ++ brcms_b_mhf(wlc->hw, MHF5, MHF5_4313_GPIOCTRL, ++ MHF5_4313_GPIOCTRL, BRCM_BAND_ALL); ++ else ++ brcms_b_mhf(wlc->hw, MHF4, MHF4_EXTPA_ENABLE, ++ MHF4_EXTPA_ENABLE, BRCM_BAND_ALL); ++ } ++ ++ /* ++ * Need to read the hwradio status here to cover the case where the ++ * system is loaded with the hw radio disabled. We do not want to bring ++ * the driver up in this case. If radio is disabled, abort up, lower ++ * power, start radio timer and return 0(for NDIS) don't call ++ * radio_update to avoid looping brcms_c_up. ++ * ++ * brcms_b_up_prep() returns either 0 or -BCME_RADIOOFF only ++ */ ++ if (!wlc->pub->radio_disabled) { ++ int status = brcms_b_up_prep(wlc->hw); ++ if (status == -ENOMEDIUM) { ++ if (!mboolisset ++ (wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE)) { ++ struct brcms_bss_cfg *bsscfg = wlc->bsscfg; ++ mboolset(wlc->pub->radio_disabled, ++ WL_RADIO_HW_DISABLE); ++ ++ if (bsscfg->enable && bsscfg->BSS) ++ wiphy_err(wlc->wiphy, "wl%d: up" ++ ": rfdisable -> " ++ "bsscfg_disable()\n", ++ wlc->pub->unit); ++ } ++ } ++ } ++ ++ if (wlc->pub->radio_disabled) { ++ brcms_c_radio_monitor_start(wlc); ++ return 0; ++ } ++ ++ /* brcms_b_up_prep has done brcms_c_corereset(). so clk is on, set it */ ++ wlc->clk = true; ++ ++ brcms_c_radio_monitor_stop(wlc); ++ ++ /* Set EDCF hostflags */ ++ brcms_b_mhf(wlc->hw, MHF1, MHF1_EDCF, MHF1_EDCF, BRCM_BAND_ALL); ++ ++ brcms_init(wlc->wl); ++ wlc->pub->up = true; ++ ++ if (wlc->bandinit_pending) { ++ brcms_c_suspend_mac_and_wait(wlc); ++ brcms_c_set_chanspec(wlc, wlc->default_bss->chanspec); ++ wlc->bandinit_pending = false; ++ brcms_c_enable_mac(wlc); ++ } ++ ++ brcms_b_up_finish(wlc->hw); ++ ++ /* Program the TX wme params with the current settings */ ++ brcms_c_wme_retries_write(wlc); ++ ++ /* start one second watchdog timer */ ++ brcms_add_timer(wlc->wdtimer, TIMER_INTERVAL_WATCHDOG, true); ++ wlc->WDarmed = true; ++ ++ /* ensure antenna config is up to date */ ++ brcms_c_stf_phy_txant_upd(wlc); ++ /* ensure LDPC config is in sync */ ++ brcms_c_ht_update_ldpc(wlc, wlc->stf->ldpc); ++ ++ return 0; ++} ++ ++static uint brcms_c_down_del_timer(struct brcms_c_info *wlc) ++{ ++ uint callbacks = 0; ++ ++ return callbacks; ++} ++ ++static int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw) ++{ ++ bool dev_gone; ++ uint callbacks = 0; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ if (!wlc_hw->up) ++ return callbacks; ++ ++ dev_gone = brcms_deviceremoved(wlc_hw->wlc); ++ ++ /* disable interrupts */ ++ if (dev_gone) ++ wlc_hw->wlc->macintmask = 0; ++ else { ++ /* now disable interrupts */ ++ brcms_intrsoff(wlc_hw->wlc->wl); ++ ++ /* ensure we're running on the pll clock again */ ++ brcms_b_clkctl_clk(wlc_hw, CLK_FAST); ++ } ++ /* down phy at the last of this stage */ ++ callbacks += wlc_phy_down(wlc_hw->band->pi); ++ ++ return callbacks; ++} ++ ++static int brcms_b_down_finish(struct brcms_hardware *wlc_hw) ++{ ++ uint callbacks = 0; ++ bool dev_gone; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ ++ if (!wlc_hw->up) ++ return callbacks; ++ ++ wlc_hw->up = false; ++ wlc_phy_hw_state_upd(wlc_hw->band->pi, false); ++ ++ dev_gone = brcms_deviceremoved(wlc_hw->wlc); ++ ++ if (dev_gone) { ++ wlc_hw->sbclk = false; ++ wlc_hw->clk = false; ++ wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false); ++ ++ /* reclaim any posted packets */ ++ brcms_c_flushqueues(wlc_hw->wlc); ++ } else { ++ ++ /* Reset and disable the core */ ++ if (ai_iscoreup(wlc_hw->sih)) { ++ if (R_REG(&wlc_hw->regs->maccontrol) & ++ MCTL_EN_MAC) ++ brcms_c_suspend_mac_and_wait(wlc_hw->wlc); ++ callbacks += brcms_reset(wlc_hw->wlc->wl); ++ brcms_c_coredisable(wlc_hw); ++ } ++ ++ /* turn off primary xtal and pll */ ++ if (!wlc_hw->noreset) { ++ ai_pci_down(wlc_hw->sih); ++ brcms_b_xtal(wlc_hw, OFF); ++ } ++ } ++ ++ return callbacks; ++} ++ ++/* ++ * Mark the interface nonoperational, stop the software mechanisms, ++ * disable the hardware, free any transient buffer state. ++ * Return a count of the number of driver callbacks still pending. ++ */ ++uint brcms_c_down(struct brcms_c_info *wlc) ++{ ++ ++ uint callbacks = 0; ++ int i; ++ bool dev_gone = false; ++ struct brcms_txq_info *qi; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ ++ /* check if we are already in the going down path */ ++ if (wlc->going_down) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Driver going down so return" ++ "\n", wlc->pub->unit, __func__); ++ return 0; ++ } ++ if (!wlc->pub->up) ++ return callbacks; ++ ++ /* in between, mpc could try to bring down again.. */ ++ wlc->going_down = true; ++ ++ callbacks += brcms_b_bmac_down_prep(wlc->hw); ++ ++ dev_gone = brcms_deviceremoved(wlc); ++ ++ /* Call any registered down handlers */ ++ for (i = 0; i < BRCMS_MAXMODULES; i++) { ++ if (wlc->modulecb[i].down_fn) ++ callbacks += ++ wlc->modulecb[i].down_fn(wlc->modulecb[i].hdl); ++ } ++ ++ /* cancel the watchdog timer */ ++ if (wlc->WDarmed) { ++ if (!brcms_del_timer(wlc->wdtimer)) ++ callbacks++; ++ wlc->WDarmed = false; ++ } ++ /* cancel all other timers */ ++ callbacks += brcms_c_down_del_timer(wlc); ++ ++ wlc->pub->up = false; ++ ++ wlc_phy_mute_upd(wlc->band->pi, false, PHY_MUTE_ALL); ++ ++ /* clear txq flow control */ ++ brcms_c_txflowcontrol_reset(wlc); ++ ++ /* flush tx queues */ ++ for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) ++ brcmu_pktq_flush(&qi->q, true, NULL, NULL); ++ ++ callbacks += brcms_b_down_finish(wlc->hw); ++ ++ /* brcms_b_down_finish has done brcms_c_coredisable(). so clk is off */ ++ wlc->clk = false; ++ ++ wlc->going_down = false; ++ return callbacks; ++} ++ ++/* Set the current gmode configuration */ ++int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config) ++{ ++ int ret = 0; ++ uint i; ++ struct brcms_c_rateset rs; ++ /* Default to 54g Auto */ ++ /* Advertise and use shortslot (-1/0/1 Auto/Off/On) */ ++ s8 shortslot = BRCMS_SHORTSLOT_AUTO; ++ bool shortslot_restrict = false; /* Restrict association to stations ++ * that support shortslot ++ */ ++ bool ofdm_basic = false; /* Make 6, 12, and 24 basic rates */ ++ /* Advertise and use short preambles (-1/0/1 Auto/Off/On) */ ++ int preamble = BRCMS_PLCP_LONG; ++ bool preamble_restrict = false; /* Restrict association to stations ++ * that support short preambles ++ */ ++ struct brcms_band *band; ++ ++ /* if N-support is enabled, allow Gmode set as long as requested ++ * Gmode is not GMODE_LEGACY_B ++ */ ++ if ((wlc->pub->_n_enab & SUPPORT_11N) && gmode == GMODE_LEGACY_B) ++ return -ENOTSUPP; ++ ++ /* verify that we are dealing with 2G band and grab the band pointer */ ++ if (wlc->band->bandtype == BRCM_BAND_2G) ++ band = wlc->band; ++ else if ((wlc->pub->_nbands > 1) && ++ (wlc->bandstate[OTHERBANDUNIT(wlc)]->bandtype == BRCM_BAND_2G)) ++ band = wlc->bandstate[OTHERBANDUNIT(wlc)]; ++ else ++ return -EINVAL; ++ ++ /* Legacy or bust when no OFDM is supported by regulatory */ ++ if ((brcms_c_channel_locale_flags_in_band(wlc->cmi, band->bandunit) & ++ BRCMS_NO_OFDM) && (gmode != GMODE_LEGACY_B)) ++ return -EINVAL; ++ ++ /* update configuration value */ ++ if (config == true) ++ brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode); ++ ++ /* Clear rateset override */ ++ memset(&rs, 0, sizeof(struct brcms_c_rateset)); ++ ++ switch (gmode) { ++ case GMODE_LEGACY_B: ++ shortslot = BRCMS_SHORTSLOT_OFF; ++ brcms_c_rateset_copy(&gphy_legacy_rates, &rs); ++ ++ break; ++ ++ case GMODE_LRS: ++ break; ++ ++ case GMODE_AUTO: ++ /* Accept defaults */ ++ break; ++ ++ case GMODE_ONLY: ++ ofdm_basic = true; ++ preamble = BRCMS_PLCP_SHORT; ++ preamble_restrict = true; ++ break; ++ ++ case GMODE_PERFORMANCE: ++ shortslot = BRCMS_SHORTSLOT_ON; ++ shortslot_restrict = true; ++ ofdm_basic = true; ++ preamble = BRCMS_PLCP_SHORT; ++ preamble_restrict = true; ++ break; ++ ++ default: ++ /* Error */ ++ wiphy_err(wlc->wiphy, "wl%d: %s: invalid gmode %d\n", ++ wlc->pub->unit, __func__, gmode); ++ return -ENOTSUPP; ++ } ++ ++ band->gmode = gmode; ++ ++ wlc->shortslot_override = shortslot; ++ ++ /* Use the default 11g rateset */ ++ if (!rs.count) ++ brcms_c_rateset_copy(&cck_ofdm_rates, &rs); ++ ++ if (ofdm_basic) { ++ for (i = 0; i < rs.count; i++) { ++ if (rs.rates[i] == BRCM_RATE_6M ++ || rs.rates[i] == BRCM_RATE_12M ++ || rs.rates[i] == BRCM_RATE_24M) ++ rs.rates[i] |= BRCMS_RATE_FLAG; ++ } ++ } ++ ++ /* Set default bss rateset */ ++ wlc->default_bss->rateset.count = rs.count; ++ memcpy(wlc->default_bss->rateset.rates, rs.rates, ++ sizeof(wlc->default_bss->rateset.rates)); ++ ++ return ret; ++} ++ ++int brcms_c_set_nmode(struct brcms_c_info *wlc) ++{ ++ uint i; ++ s32 nmode = AUTO; ++ ++ if (wlc->stf->txstreams == WL_11N_3x3) ++ nmode = WL_11N_3x3; ++ else ++ nmode = WL_11N_2x2; ++ ++ /* force GMODE_AUTO if NMODE is ON */ ++ brcms_c_set_gmode(wlc, GMODE_AUTO, true); ++ if (nmode == WL_11N_3x3) ++ wlc->pub->_n_enab = SUPPORT_HT; ++ else ++ wlc->pub->_n_enab = SUPPORT_11N; ++ wlc->default_bss->flags |= BRCMS_BSS_HT; ++ /* add the mcs rates to the default and hw ratesets */ ++ brcms_c_rateset_mcs_build(&wlc->default_bss->rateset, ++ wlc->stf->txstreams); ++ for (i = 0; i < wlc->pub->_nbands; i++) ++ memcpy(wlc->bandstate[i]->hw_rateset.mcs, ++ wlc->default_bss->rateset.mcs, MCSSET_LEN); ++ ++ return 0; ++} ++ ++static int ++brcms_c_set_internal_rateset(struct brcms_c_info *wlc, ++ struct brcms_c_rateset *rs_arg) ++{ ++ struct brcms_c_rateset rs, new; ++ uint bandunit; ++ ++ memcpy(&rs, rs_arg, sizeof(struct brcms_c_rateset)); ++ ++ /* check for bad count value */ ++ if ((rs.count == 0) || (rs.count > BRCMS_NUMRATES)) ++ return -EINVAL; ++ ++ /* try the current band */ ++ bandunit = wlc->band->bandunit; ++ memcpy(&new, &rs, sizeof(struct brcms_c_rateset)); ++ if (brcms_c_rate_hwrs_filter_sort_validate ++ (&new, &wlc->bandstate[bandunit]->hw_rateset, true, ++ wlc->stf->txstreams)) ++ goto good; ++ ++ /* try the other band */ ++ if (brcms_is_mband_unlocked(wlc)) { ++ bandunit = OTHERBANDUNIT(wlc); ++ memcpy(&new, &rs, sizeof(struct brcms_c_rateset)); ++ if (brcms_c_rate_hwrs_filter_sort_validate(&new, ++ &wlc-> ++ bandstate[bandunit]-> ++ hw_rateset, true, ++ wlc->stf->txstreams)) ++ goto good; ++ } ++ ++ return -EBADE; ++ ++ good: ++ /* apply new rateset */ ++ memcpy(&wlc->default_bss->rateset, &new, ++ sizeof(struct brcms_c_rateset)); ++ memcpy(&wlc->bandstate[bandunit]->defrateset, &new, ++ sizeof(struct brcms_c_rateset)); ++ return 0; ++} ++ ++static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc) ++{ ++ u8 r; ++ bool war = false; ++ ++ if (wlc->bsscfg->associated) ++ r = wlc->bsscfg->current_bss->rateset.rates[0]; ++ else ++ r = wlc->default_bss->rateset.rates[0]; ++ ++ wlc_phy_ofdm_rateset_war(wlc->band->pi, war); ++} ++ ++int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel) ++{ ++ u16 chspec = ch20mhz_chspec(channel); ++ ++ if (channel < 0 || channel > MAXCHANNEL) ++ return -EINVAL; ++ ++ if (!brcms_c_valid_chanspec_db(wlc->cmi, chspec)) ++ return -EINVAL; ++ ++ ++ if (!wlc->pub->up && brcms_is_mband_unlocked(wlc)) { ++ if (wlc->band->bandunit != chspec_bandunit(chspec)) ++ wlc->bandinit_pending = true; ++ else ++ wlc->bandinit_pending = false; ++ } ++ ++ wlc->default_bss->chanspec = chspec; ++ /* brcms_c_BSSinit() will sanitize the rateset before ++ * using it.. */ ++ if (wlc->pub->up && (wlc_phy_chanspec_get(wlc->band->pi) != chspec)) { ++ brcms_c_set_home_chanspec(wlc, chspec); ++ brcms_c_suspend_mac_and_wait(wlc); ++ brcms_c_set_chanspec(wlc, chspec); ++ brcms_c_enable_mac(wlc); ++ } ++ return 0; ++} ++ ++int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl) ++{ ++ int ac; ++ ++ if (srl < 1 || srl > RETRY_SHORT_MAX || ++ lrl < 1 || lrl > RETRY_SHORT_MAX) ++ return -EINVAL; ++ ++ wlc->SRL = srl; ++ wlc->LRL = lrl; ++ ++ brcms_b_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL); ++ ++ for (ac = 0; ac < AC_COUNT; ac++) { ++ wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], ++ EDCF_SHORT, wlc->SRL); ++ wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], ++ EDCF_LONG, wlc->LRL); ++ } ++ brcms_c_wme_retries_write(wlc); ++ ++ return 0; ++} ++ ++void brcms_c_get_current_rateset(struct brcms_c_info *wlc, ++ struct brcm_rateset *currs) ++{ ++ struct brcms_c_rateset *rs; ++ ++ if (wlc->pub->associated) ++ rs = &wlc->bsscfg->current_bss->rateset; ++ else ++ rs = &wlc->default_bss->rateset; ++ ++ /* Copy only legacy rateset section */ ++ currs->count = rs->count; ++ memcpy(&currs->rates, &rs->rates, rs->count); ++} ++ ++int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs) ++{ ++ struct brcms_c_rateset internal_rs; ++ int bcmerror; ++ ++ if (rs->count > BRCMS_NUMRATES) ++ return -ENOBUFS; ++ ++ memset(&internal_rs, 0, sizeof(struct brcms_c_rateset)); ++ ++ /* Copy only legacy rateset section */ ++ internal_rs.count = rs->count; ++ memcpy(&internal_rs.rates, &rs->rates, internal_rs.count); ++ ++ /* merge rateset coming in with the current mcsset */ ++ if (wlc->pub->_n_enab & SUPPORT_11N) { ++ struct brcms_bss_info *mcsset_bss; ++ if (wlc->bsscfg->associated) ++ mcsset_bss = wlc->bsscfg->current_bss; ++ else ++ mcsset_bss = wlc->default_bss; ++ memcpy(internal_rs.mcs, &mcsset_bss->rateset.mcs[0], ++ MCSSET_LEN); ++ } ++ ++ bcmerror = brcms_c_set_internal_rateset(wlc, &internal_rs); ++ if (!bcmerror) ++ brcms_c_ofdm_rateset_war(wlc); ++ ++ return bcmerror; ++} ++ ++int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period) ++{ ++ if (period < DOT11_MIN_BEACON_PERIOD || ++ period > DOT11_MAX_BEACON_PERIOD) ++ return -EINVAL; ++ ++ wlc->default_bss->beacon_period = period; ++ return 0; ++} ++ ++u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx) ++{ ++ return wlc->band->phytype; ++} ++ ++void brcms_c_set_shortslot_override(struct brcms_c_info *wlc, s8 sslot_override) ++{ ++ wlc->shortslot_override = sslot_override; ++ ++ /* ++ * shortslot is an 11g feature, so no more work if we are ++ * currently on the 5G band ++ */ ++ if (wlc->band->bandtype == BRCM_BAND_5G) ++ return; ++ ++ if (wlc->pub->up && wlc->pub->associated) { ++ /* let watchdog or beacon processing update shortslot */ ++ } else if (wlc->pub->up) { ++ /* unassociated shortslot is off */ ++ brcms_c_switch_shortslot(wlc, false); ++ } else { ++ /* driver is down, so just update the brcms_c_info ++ * value */ ++ if (wlc->shortslot_override == BRCMS_SHORTSLOT_AUTO) ++ wlc->shortslot = false; ++ else ++ wlc->shortslot = ++ (wlc->shortslot_override == ++ BRCMS_SHORTSLOT_ON); ++ } ++} ++ ++/* ++ * register watchdog and down handlers. ++ */ ++int brcms_c_module_register(struct brcms_pub *pub, ++ const char *name, struct brcms_info *hdl, ++ int (*d_fn)(void *handle)) ++{ ++ struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc; ++ int i; ++ ++ /* find an empty entry and just add, no duplication check! */ ++ for (i = 0; i < BRCMS_MAXMODULES; i++) { ++ if (wlc->modulecb[i].name[0] == '\0') { ++ strncpy(wlc->modulecb[i].name, name, ++ sizeof(wlc->modulecb[i].name) - 1); ++ wlc->modulecb[i].hdl = hdl; ++ wlc->modulecb[i].down_fn = d_fn; ++ return 0; ++ } ++ } ++ ++ return -ENOSR; ++} ++ ++/* unregister module callbacks */ ++int brcms_c_module_unregister(struct brcms_pub *pub, const char *name, ++ struct brcms_info *hdl) ++{ ++ struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc; ++ int i; ++ ++ if (wlc == NULL) ++ return -ENODATA; ++ ++ for (i = 0; i < BRCMS_MAXMODULES; i++) { ++ if (!strcmp(wlc->modulecb[i].name, name) && ++ (wlc->modulecb[i].hdl == hdl)) { ++ memset(&wlc->modulecb[i], 0, sizeof(struct modulecb)); ++ return 0; ++ } ++ } ++ ++ /* table not found! */ ++ return -ENODATA; ++} ++ ++#ifdef BCMDBG ++static const char * const supr_reason[] = { ++ "None", "PMQ Entry", "Flush request", ++ "Previous frag failure", "Channel mismatch", ++ "Lifetime Expiry", "Underflow" ++}; ++ ++static void brcms_c_print_txs_status(u16 s) ++{ ++ printk(KERN_DEBUG "[15:12] %d frame attempts\n", ++ (s & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT); ++ printk(KERN_DEBUG " [11:8] %d rts attempts\n", ++ (s & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT); ++ printk(KERN_DEBUG " [7] %d PM mode indicated\n", ++ ((s & TX_STATUS_PMINDCTD) ? 1 : 0)); ++ printk(KERN_DEBUG " [6] %d intermediate status\n", ++ ((s & TX_STATUS_INTERMEDIATE) ? 1 : 0)); ++ printk(KERN_DEBUG " [5] %d AMPDU\n", ++ (s & TX_STATUS_AMPDU) ? 1 : 0); ++ printk(KERN_DEBUG " [4:2] %d Frame Suppressed Reason (%s)\n", ++ ((s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT), ++ supr_reason[(s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT]); ++ printk(KERN_DEBUG " [1] %d acked\n", ++ ((s & TX_STATUS_ACK_RCV) ? 1 : 0)); ++} ++#endif /* BCMDBG */ ++ ++void brcms_c_print_txstatus(struct tx_status *txs) ++{ ++#if defined(BCMDBG) ++ u16 s = txs->status; ++ u16 ackphyrxsh = txs->ackphyrxsh; ++ ++ printk(KERN_DEBUG "\ntxpkt (MPDU) Complete\n"); ++ ++ printk(KERN_DEBUG "FrameID: %04x ", txs->frameid); ++ printk(KERN_DEBUG "TxStatus: %04x", s); ++ printk(KERN_DEBUG "\n"); ++ ++ brcms_c_print_txs_status(s); ++ ++ printk(KERN_DEBUG "LastTxTime: %04x ", txs->lasttxtime); ++ printk(KERN_DEBUG "Seq: %04x ", txs->sequence); ++ printk(KERN_DEBUG "PHYTxStatus: %04x ", txs->phyerr); ++ printk(KERN_DEBUG "RxAckRSSI: %04x ", ++ (ackphyrxsh & PRXS1_JSSI_MASK) >> PRXS1_JSSI_SHIFT); ++ printk(KERN_DEBUG "RxAckSQ: %04x", ++ (ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT); ++ printk(KERN_DEBUG "\n"); ++#endif /* defined(BCMDBG) */ ++} ++ ++bool brcms_c_chipmatch(u16 vendor, u16 device) ++{ ++ if (vendor != PCI_VENDOR_ID_BROADCOM) { ++ pr_err("chipmatch: unknown vendor id %04x\n", vendor); ++ return false; ++ } ++ ++ if (device == BCM43224_D11N_ID_VEN1) ++ return true; ++ if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID)) ++ return true; ++ if (device == BCM4313_D11N2G_ID) ++ return true; ++ if ((device == BCM43236_D11N_ID) || (device == BCM43236_D11N2G_ID)) ++ return true; ++ ++ pr_err("chipmatch: unknown device id %04x\n", device); ++ return false; ++} ++ ++#if defined(BCMDBG) ++void brcms_c_print_txdesc(struct d11txh *txh) ++{ ++ u16 mtcl = le16_to_cpu(txh->MacTxControlLow); ++ u16 mtch = le16_to_cpu(txh->MacTxControlHigh); ++ u16 mfc = le16_to_cpu(txh->MacFrameControl); ++ u16 tfest = le16_to_cpu(txh->TxFesTimeNormal); ++ u16 ptcw = le16_to_cpu(txh->PhyTxControlWord); ++ u16 ptcw_1 = le16_to_cpu(txh->PhyTxControlWord_1); ++ u16 ptcw_1_Fbr = le16_to_cpu(txh->PhyTxControlWord_1_Fbr); ++ u16 ptcw_1_Rts = le16_to_cpu(txh->PhyTxControlWord_1_Rts); ++ u16 ptcw_1_FbrRts = le16_to_cpu(txh->PhyTxControlWord_1_FbrRts); ++ u16 mainrates = le16_to_cpu(txh->MainRates); ++ u16 xtraft = le16_to_cpu(txh->XtraFrameTypes); ++ u8 *iv = txh->IV; ++ u8 *ra = txh->TxFrameRA; ++ u16 tfestfb = le16_to_cpu(txh->TxFesTimeFallback); ++ u8 *rtspfb = txh->RTSPLCPFallback; ++ u16 rtsdfb = le16_to_cpu(txh->RTSDurFallback); ++ u8 *fragpfb = txh->FragPLCPFallback; ++ u16 fragdfb = le16_to_cpu(txh->FragDurFallback); ++ u16 mmodelen = le16_to_cpu(txh->MModeLen); ++ u16 mmodefbrlen = le16_to_cpu(txh->MModeFbrLen); ++ u16 tfid = le16_to_cpu(txh->TxFrameID); ++ u16 txs = le16_to_cpu(txh->TxStatus); ++ u16 mnmpdu = le16_to_cpu(txh->MaxNMpdus); ++ u16 mabyte = le16_to_cpu(txh->MaxABytes_MRT); ++ u16 mabyte_f = le16_to_cpu(txh->MaxABytes_FBR); ++ u16 mmbyte = le16_to_cpu(txh->MinMBytes); ++ ++ u8 *rtsph = txh->RTSPhyHeader; ++ struct ieee80211_rts rts = txh->rts_frame; ++ char hexbuf[256]; ++ ++ /* add plcp header along with txh descriptor */ ++ printk(KERN_DEBUG "Raw TxDesc + plcp header:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ++ txh, sizeof(struct d11txh) + 48); ++ ++ printk(KERN_DEBUG "TxCtlLow: %04x ", mtcl); ++ printk(KERN_DEBUG "TxCtlHigh: %04x ", mtch); ++ printk(KERN_DEBUG "FC: %04x ", mfc); ++ printk(KERN_DEBUG "FES Time: %04x\n", tfest); ++ printk(KERN_DEBUG "PhyCtl: %04x%s ", ptcw, ++ (ptcw & PHY_TXC_SHORT_HDR) ? " short" : ""); ++ printk(KERN_DEBUG "PhyCtl_1: %04x ", ptcw_1); ++ printk(KERN_DEBUG "PhyCtl_1_Fbr: %04x\n", ptcw_1_Fbr); ++ printk(KERN_DEBUG "PhyCtl_1_Rts: %04x ", ptcw_1_Rts); ++ printk(KERN_DEBUG "PhyCtl_1_Fbr_Rts: %04x\n", ptcw_1_FbrRts); ++ printk(KERN_DEBUG "MainRates: %04x ", mainrates); ++ printk(KERN_DEBUG "XtraFrameTypes: %04x ", xtraft); ++ printk(KERN_DEBUG "\n"); ++ ++ brcmu_format_hex(hexbuf, iv, sizeof(txh->IV)); ++ printk(KERN_DEBUG "SecIV: %s\n", hexbuf); ++ brcmu_format_hex(hexbuf, ra, sizeof(txh->TxFrameRA)); ++ printk(KERN_DEBUG "RA: %s\n", hexbuf); ++ ++ printk(KERN_DEBUG "Fb FES Time: %04x ", tfestfb); ++ brcmu_format_hex(hexbuf, rtspfb, sizeof(txh->RTSPLCPFallback)); ++ printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf); ++ printk(KERN_DEBUG "RTS DUR: %04x ", rtsdfb); ++ brcmu_format_hex(hexbuf, fragpfb, sizeof(txh->FragPLCPFallback)); ++ printk(KERN_DEBUG "PLCP: %s ", hexbuf); ++ printk(KERN_DEBUG "DUR: %04x", fragdfb); ++ printk(KERN_DEBUG "\n"); ++ ++ printk(KERN_DEBUG "MModeLen: %04x ", mmodelen); ++ printk(KERN_DEBUG "MModeFbrLen: %04x\n", mmodefbrlen); ++ ++ printk(KERN_DEBUG "FrameID: %04x\n", tfid); ++ printk(KERN_DEBUG "TxStatus: %04x\n", txs); ++ ++ printk(KERN_DEBUG "MaxNumMpdu: %04x\n", mnmpdu); ++ printk(KERN_DEBUG "MaxAggbyte: %04x\n", mabyte); ++ printk(KERN_DEBUG "MaxAggbyte_fb: %04x\n", mabyte_f); ++ printk(KERN_DEBUG "MinByte: %04x\n", mmbyte); ++ ++ brcmu_format_hex(hexbuf, rtsph, sizeof(txh->RTSPhyHeader)); ++ printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf); ++ brcmu_format_hex(hexbuf, (u8 *) &rts, sizeof(txh->rts_frame)); ++ printk(KERN_DEBUG "RTS Frame: %s", hexbuf); ++ printk(KERN_DEBUG "\n"); ++} ++#endif /* defined(BCMDBG) */ ++ ++#if defined(BCMDBG) ++int ++brcms_c_format_flags(const struct brcms_c_bit_desc *bd, u32 flags, char *buf, ++ int len) ++{ ++ int i; ++ char *p = buf; ++ char hexstr[16]; ++ int slen = 0, nlen = 0; ++ u32 bit; ++ const char *name; ++ ++ if (len < 2 || !buf) ++ return 0; ++ ++ buf[0] = '\0'; ++ ++ for (i = 0; flags != 0; i++) { ++ bit = bd[i].bit; ++ name = bd[i].name; ++ if (bit == 0 && flags != 0) { ++ /* print any unnamed bits */ ++ snprintf(hexstr, 16, "0x%X", flags); ++ name = hexstr; ++ flags = 0; /* exit loop */ ++ } else if ((flags & bit) == 0) ++ continue; ++ flags &= ~bit; ++ nlen = strlen(name); ++ slen += nlen; ++ /* count btwn flag space */ ++ if (flags != 0) ++ slen += 1; ++ /* need NULL char as well */ ++ if (len <= slen) ++ break; ++ /* copy NULL char but don't count it */ ++ strncpy(p, name, nlen + 1); ++ p += nlen; ++ /* copy btwn flag space and NULL char */ ++ if (flags != 0) ++ p += snprintf(p, 2, " "); ++ len -= slen; ++ } ++ ++ /* indicate the str was too short */ ++ if (flags != 0) { ++ if (len < 2) ++ p -= 2 - len; /* overwrite last char */ ++ p += snprintf(p, 2, ">"); ++ } ++ ++ return (int)(p - buf); ++} ++#endif /* defined(BCMDBG) */ ++ ++#if defined(BCMDBG) ++void brcms_c_print_rxh(struct d11rxhdr *rxh) ++{ ++ u16 len = rxh->RxFrameSize; ++ u16 phystatus_0 = rxh->PhyRxStatus_0; ++ u16 phystatus_1 = rxh->PhyRxStatus_1; ++ u16 phystatus_2 = rxh->PhyRxStatus_2; ++ u16 phystatus_3 = rxh->PhyRxStatus_3; ++ u16 macstatus1 = rxh->RxStatus1; ++ u16 macstatus2 = rxh->RxStatus2; ++ char flagstr[64]; ++ char lenbuf[20]; ++ static const struct brcms_c_bit_desc macstat_flags[] = { ++ {RXS_FCSERR, "FCSErr"}, ++ {RXS_RESPFRAMETX, "Reply"}, ++ {RXS_PBPRES, "PADDING"}, ++ {RXS_DECATMPT, "DeCr"}, ++ {RXS_DECERR, "DeCrErr"}, ++ {RXS_BCNSENT, "Bcn"}, ++ {0, NULL} ++ }; ++ ++ printk(KERN_DEBUG "Raw RxDesc:\n"); ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, rxh, ++ sizeof(struct d11rxhdr)); ++ ++ brcms_c_format_flags(macstat_flags, macstatus1, flagstr, 64); ++ ++ snprintf(lenbuf, sizeof(lenbuf), "0x%x", len); ++ ++ printk(KERN_DEBUG "RxFrameSize: %6s (%d)%s\n", lenbuf, len, ++ (rxh->PhyRxStatus_0 & PRXS0_SHORTH) ? " short preamble" : ""); ++ printk(KERN_DEBUG "RxPHYStatus: %04x %04x %04x %04x\n", ++ phystatus_0, phystatus_1, phystatus_2, phystatus_3); ++ printk(KERN_DEBUG "RxMACStatus: %x %s\n", macstatus1, flagstr); ++ printk(KERN_DEBUG "RXMACaggtype: %x\n", ++ (macstatus2 & RXS_AGGTYPE_MASK)); ++ printk(KERN_DEBUG "RxTSFTime: %04x\n", rxh->RxTSFTime); ++} ++#endif /* defined(BCMDBG) */ ++ ++u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate) ++{ ++ u16 table_ptr; ++ u8 phy_rate, index; ++ ++ /* get the phy specific rate encoding for the PLCP SIGNAL field */ ++ if (is_ofdm_rate(rate)) ++ table_ptr = M_RT_DIRMAP_A; ++ else ++ table_ptr = M_RT_DIRMAP_B; ++ ++ /* for a given rate, the LS-nibble of the PLCP SIGNAL field is ++ * the index into the rate table. ++ */ ++ phy_rate = rate_info[rate] & BRCMS_RATE_MASK; ++ index = phy_rate & 0xf; ++ ++ /* Find the SHM pointer to the rate table entry by looking in the ++ * Direct-map Table ++ */ ++ return 2 * brcms_b_read_shm(wlc_hw, table_ptr + (index * 2)); ++} ++ ++static bool ++brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q, ++ struct sk_buff *pkt, int prec, bool head) ++{ ++ struct sk_buff *p; ++ int eprec = -1; /* precedence to evict from */ ++ ++ /* Determine precedence from which to evict packet, if any */ ++ if (pktq_pfull(q, prec)) ++ eprec = prec; ++ else if (pktq_full(q)) { ++ p = brcmu_pktq_peek_tail(q, &eprec); ++ if (eprec > prec) { ++ wiphy_err(wlc->wiphy, "%s: Failing: eprec %d > prec %d" ++ "\n", __func__, eprec, prec); ++ return false; ++ } ++ } ++ ++ /* Evict if needed */ ++ if (eprec >= 0) { ++ bool discard_oldest; ++ ++ discard_oldest = ac_bitmap_tst(0, eprec); ++ ++ /* Refuse newer packet unless configured to discard oldest */ ++ if (eprec == prec && !discard_oldest) { ++ wiphy_err(wlc->wiphy, "%s: No where to go, prec == %d" ++ "\n", __func__, prec); ++ return false; ++ } ++ ++ /* Evict packet according to discard policy */ ++ p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) : ++ brcmu_pktq_pdeq_tail(q, eprec); ++ brcmu_pkt_buf_free_skb(p); ++ } ++ ++ /* Enqueue */ ++ if (head) ++ p = brcmu_pktq_penq_head(q, prec, pkt); ++ else ++ p = brcmu_pktq_penq(q, prec, pkt); ++ ++ return true; ++} ++ ++/* ++ * Attempts to queue a packet onto a multiple-precedence queue, ++ * if necessary evicting a lower precedence packet from the queue. ++ * ++ * 'prec' is the precedence number that has already been mapped ++ * from the packet priority. ++ * ++ * Returns true if packet consumed (queued), false if not. ++ */ ++static bool brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q, ++ struct sk_buff *pkt, int prec) ++{ ++ return brcms_c_prec_enq_head(wlc, q, pkt, prec, false); ++} ++ ++void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb, ++ struct sk_buff *sdu, uint prec) ++{ ++ struct brcms_txq_info *qi = wlc->pkt_queue; /* Check me */ ++ struct pktq *q = &qi->q; ++ int prio; ++ ++ prio = sdu->priority; ++ ++ if (!brcms_c_prec_enq(wlc, q, sdu, prec)) { ++ /* ++ * we might hit this condtion in case ++ * packet flooding from mac80211 stack ++ */ ++ brcmu_pkt_buf_free_skb(sdu); ++ } ++} ++ ++/* ++ * bcmc_fid_generate: ++ * Generate frame ID for a BCMC packet. The frag field is not used ++ * for MC frames so is used as part of the sequence number. ++ */ ++static inline u16 ++bcmc_fid_generate(struct brcms_c_info *wlc, struct brcms_bss_cfg *bsscfg, ++ struct d11txh *txh) ++{ ++ u16 frameid; ++ ++ frameid = le16_to_cpu(txh->TxFrameID) & ~(TXFID_SEQ_MASK | ++ TXFID_QUEUE_MASK); ++ frameid |= ++ (((wlc-> ++ mc_fid_counter++) << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) | ++ TX_BCMC_FIFO; ++ ++ return frameid; ++} ++ ++static uint ++brcms_c_calc_ack_time(struct brcms_c_info *wlc, u32 rspec, ++ u8 preamble_type) ++{ ++ uint dur = 0; ++ ++ BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d\n", ++ wlc->pub->unit, rspec, preamble_type); ++ /* ++ * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that ++ * is less than or equal to the rate of the immediately previous ++ * frame in the FES ++ */ ++ rspec = brcms_basic_rate(wlc, rspec); ++ /* ACK frame len == 14 == 2(fc) + 2(dur) + 6(ra) + 4(fcs) */ ++ dur = ++ brcms_c_calc_frame_time(wlc, rspec, preamble_type, ++ (DOT11_ACK_LEN + FCS_LEN)); ++ return dur; ++} ++ ++static uint ++brcms_c_calc_cts_time(struct brcms_c_info *wlc, u32 rspec, ++ u8 preamble_type) ++{ ++ BCMMSG(wlc->wiphy, "wl%d: ratespec 0x%x, preamble_type %d\n", ++ wlc->pub->unit, rspec, preamble_type); ++ return brcms_c_calc_ack_time(wlc, rspec, preamble_type); ++} ++ ++static uint ++brcms_c_calc_ba_time(struct brcms_c_info *wlc, u32 rspec, ++ u8 preamble_type) ++{ ++ BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, " ++ "preamble_type %d\n", wlc->pub->unit, rspec, preamble_type); ++ /* ++ * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that ++ * is less than or equal to the rate of the immediately previous ++ * frame in the FES ++ */ ++ rspec = brcms_basic_rate(wlc, rspec); ++ /* BA len == 32 == 16(ctl hdr) + 4(ba len) + 8(bitmap) + 4(fcs) */ ++ return brcms_c_calc_frame_time(wlc, rspec, preamble_type, ++ (DOT11_BA_LEN + DOT11_BA_BITMAP_LEN + ++ FCS_LEN)); ++} ++ ++/* brcms_c_compute_frame_dur() ++ * ++ * Calculate the 802.11 MAC header DUR field for MPDU ++ * DUR for a single frame = 1 SIFS + 1 ACK ++ * DUR for a frame with following frags = 3 SIFS + 2 ACK + next frag time ++ * ++ * rate MPDU rate in unit of 500kbps ++ * next_frag_len next MPDU length in bytes ++ * preamble_type use short/GF or long/MM PLCP header ++ */ ++static u16 ++brcms_c_compute_frame_dur(struct brcms_c_info *wlc, u32 rate, ++ u8 preamble_type, uint next_frag_len) ++{ ++ u16 dur, sifs; ++ ++ sifs = get_sifs(wlc->band); ++ ++ dur = sifs; ++ dur += (u16) brcms_c_calc_ack_time(wlc, rate, preamble_type); ++ ++ if (next_frag_len) { ++ /* Double the current DUR to get 2 SIFS + 2 ACKs */ ++ dur *= 2; ++ /* add another SIFS and the frag time */ ++ dur += sifs; ++ dur += ++ (u16) brcms_c_calc_frame_time(wlc, rate, preamble_type, ++ next_frag_len); ++ } ++ return dur; ++} ++ ++/* The opposite of brcms_c_calc_frame_time */ ++static uint ++brcms_c_calc_frame_len(struct brcms_c_info *wlc, u32 ratespec, ++ u8 preamble_type, uint dur) ++{ ++ uint nsyms, mac_len, Ndps, kNdps; ++ uint rate = rspec2rate(ratespec); ++ ++ BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, dur %d\n", ++ wlc->pub->unit, ratespec, preamble_type, dur); ++ ++ if (is_mcs_rate(ratespec)) { ++ uint mcs = ratespec & RSPEC_RATE_MASK; ++ int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec); ++ dur -= PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT); ++ /* payload calculation matches that of regular ofdm */ ++ if (wlc->band->bandtype == BRCM_BAND_2G) ++ dur -= DOT11_OFDM_SIGNAL_EXTENSION; ++ /* kNdbps = kbps * 4 */ ++ kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec), ++ rspec_issgi(ratespec)) * 4; ++ nsyms = dur / APHY_SYMBOL_TIME; ++ mac_len = ++ ((nsyms * kNdps) - ++ ((APHY_SERVICE_NBITS + APHY_TAIL_NBITS) * 1000)) / 8000; ++ } else if (is_ofdm_rate(ratespec)) { ++ dur -= APHY_PREAMBLE_TIME; ++ dur -= APHY_SIGNAL_TIME; ++ /* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */ ++ Ndps = rate * 2; ++ nsyms = dur / APHY_SYMBOL_TIME; ++ mac_len = ++ ((nsyms * Ndps) - ++ (APHY_SERVICE_NBITS + APHY_TAIL_NBITS)) / 8; ++ } else { ++ if (preamble_type & BRCMS_SHORT_PREAMBLE) ++ dur -= BPHY_PLCP_SHORT_TIME; ++ else ++ dur -= BPHY_PLCP_TIME; ++ mac_len = dur * rate; ++ /* divide out factor of 2 in rate (1/2 mbps) */ ++ mac_len = mac_len / 8 / 2; ++ } ++ return mac_len; ++} ++ ++/* ++ * Return true if the specified rate is supported by the specified band. ++ * BRCM_BAND_AUTO indicates the current band. ++ */ ++static bool brcms_c_valid_rate(struct brcms_c_info *wlc, u32 rspec, int band, ++ bool verbose) ++{ ++ struct brcms_c_rateset *hw_rateset; ++ uint i; ++ ++ if ((band == BRCM_BAND_AUTO) || (band == wlc->band->bandtype)) ++ hw_rateset = &wlc->band->hw_rateset; ++ else if (wlc->pub->_nbands > 1) ++ hw_rateset = &wlc->bandstate[OTHERBANDUNIT(wlc)]->hw_rateset; ++ else ++ /* other band specified and we are a single band device */ ++ return false; ++ ++ /* check if this is a mimo rate */ ++ if (is_mcs_rate(rspec)) { ++ if ((rspec & RSPEC_RATE_MASK) >= MCS_TABLE_SIZE) ++ goto error; ++ ++ return isset(hw_rateset->mcs, (rspec & RSPEC_RATE_MASK)); ++ } ++ ++ for (i = 0; i < hw_rateset->count; i++) ++ if (hw_rateset->rates[i] == rspec2rate(rspec)) ++ return true; ++ error: ++ if (verbose) ++ wiphy_err(wlc->wiphy, "wl%d: valid_rate: rate spec 0x%x " ++ "not in hw_rateset\n", wlc->pub->unit, rspec); ++ ++ return false; ++} ++ ++static u32 ++mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band, ++ u32 int_val) ++{ ++ u8 stf = (int_val & NRATE_STF_MASK) >> NRATE_STF_SHIFT; ++ u8 rate = int_val & NRATE_RATE_MASK; ++ u32 rspec; ++ bool ismcs = ((int_val & NRATE_MCS_INUSE) == NRATE_MCS_INUSE); ++ bool issgi = ((int_val & NRATE_SGI_MASK) >> NRATE_SGI_SHIFT); ++ bool override_mcs_only = ((int_val & NRATE_OVERRIDE_MCS_ONLY) ++ == NRATE_OVERRIDE_MCS_ONLY); ++ int bcmerror = 0; ++ ++ if (!ismcs) ++ return (u32) rate; ++ ++ /* validate the combination of rate/mcs/stf is allowed */ ++ if ((wlc->pub->_n_enab & SUPPORT_11N) && ismcs) { ++ /* mcs only allowed when nmode */ ++ if (stf > PHY_TXC1_MODE_SDM) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid stf\n", ++ wlc->pub->unit, __func__); ++ bcmerror = -EINVAL; ++ goto done; ++ } ++ ++ /* mcs 32 is a special case, DUP mode 40 only */ ++ if (rate == 32) { ++ if (!CHSPEC_IS40(wlc->home_chanspec) || ++ ((stf != PHY_TXC1_MODE_SISO) ++ && (stf != PHY_TXC1_MODE_CDD))) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid mcs " ++ "32\n", wlc->pub->unit, __func__); ++ bcmerror = -EINVAL; ++ goto done; ++ } ++ /* mcs > 7 must use stf SDM */ ++ } else if (rate > HIGHEST_SINGLE_STREAM_MCS) { ++ /* mcs > 7 must use stf SDM */ ++ if (stf != PHY_TXC1_MODE_SDM) { ++ BCMMSG(wlc->wiphy, "wl%d: enabling " ++ "SDM mode for mcs %d\n", ++ wlc->pub->unit, rate); ++ stf = PHY_TXC1_MODE_SDM; ++ } ++ } else { ++ /* ++ * MCS 0-7 may use SISO, CDD, and for ++ * phy_rev >= 3 STBC ++ */ ++ if ((stf > PHY_TXC1_MODE_STBC) || ++ (!BRCMS_STBC_CAP_PHY(wlc) ++ && (stf == PHY_TXC1_MODE_STBC))) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid STBC" ++ "\n", wlc->pub->unit, __func__); ++ bcmerror = -EINVAL; ++ goto done; ++ } ++ } ++ } else if (is_ofdm_rate(rate)) { ++ if ((stf != PHY_TXC1_MODE_CDD) && (stf != PHY_TXC1_MODE_SISO)) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid OFDM\n", ++ wlc->pub->unit, __func__); ++ bcmerror = -EINVAL; ++ goto done; ++ } ++ } else if (is_cck_rate(rate)) { ++ if ((cur_band->bandtype != BRCM_BAND_2G) ++ || (stf != PHY_TXC1_MODE_SISO)) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Invalid CCK\n", ++ wlc->pub->unit, __func__); ++ bcmerror = -EINVAL; ++ goto done; ++ } ++ } else { ++ wiphy_err(wlc->wiphy, "wl%d: %s: Unknown rate type\n", ++ wlc->pub->unit, __func__); ++ bcmerror = -EINVAL; ++ goto done; ++ } ++ /* make sure multiple antennae are available for non-siso rates */ ++ if ((stf != PHY_TXC1_MODE_SISO) && (wlc->stf->txstreams == 1)) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: SISO antenna but !SISO " ++ "request\n", wlc->pub->unit, __func__); ++ bcmerror = -EINVAL; ++ goto done; ++ } ++ ++ rspec = rate; ++ if (ismcs) { ++ rspec |= RSPEC_MIMORATE; ++ /* For STBC populate the STC field of the ratespec */ ++ if (stf == PHY_TXC1_MODE_STBC) { ++ u8 stc; ++ stc = 1; /* Nss for single stream is always 1 */ ++ rspec |= (stc << RSPEC_STC_SHIFT); ++ } ++ } ++ ++ rspec |= (stf << RSPEC_STF_SHIFT); ++ ++ if (override_mcs_only) ++ rspec |= RSPEC_OVERRIDE_MCS_ONLY; ++ ++ if (issgi) ++ rspec |= RSPEC_SHORT_GI; ++ ++ if ((rate != 0) ++ && !brcms_c_valid_rate(wlc, rspec, cur_band->bandtype, true)) ++ return rate; ++ ++ return rspec; ++done: ++ return rate; ++} ++ ++/* ++ * Compute PLCP, but only requires actual rate and length of pkt. ++ * Rate is given in the driver standard multiple of 500 kbps. ++ * le is set for 11 Mbps rate if necessary. ++ * Broken out for PRQ. ++ */ ++ ++static void brcms_c_cck_plcp_set(struct brcms_c_info *wlc, int rate_500, ++ uint length, u8 *plcp) ++{ ++ u16 usec = 0; ++ u8 le = 0; ++ ++ switch (rate_500) { ++ case BRCM_RATE_1M: ++ usec = length << 3; ++ break; ++ case BRCM_RATE_2M: ++ usec = length << 2; ++ break; ++ case BRCM_RATE_5M5: ++ usec = (length << 4) / 11; ++ if ((length << 4) - (usec * 11) > 0) ++ usec++; ++ break; ++ case BRCM_RATE_11M: ++ usec = (length << 3) / 11; ++ if ((length << 3) - (usec * 11) > 0) { ++ usec++; ++ if ((usec * 11) - (length << 3) >= 8) ++ le = D11B_PLCP_SIGNAL_LE; ++ } ++ break; ++ ++ default: ++ wiphy_err(wlc->wiphy, ++ "brcms_c_cck_plcp_set: unsupported rate %d\n", ++ rate_500); ++ rate_500 = BRCM_RATE_1M; ++ usec = length << 3; ++ break; ++ } ++ /* PLCP signal byte */ ++ plcp[0] = rate_500 * 5; /* r (500kbps) * 5 == r (100kbps) */ ++ /* PLCP service byte */ ++ plcp[1] = (u8) (le | D11B_PLCP_SIGNAL_LOCKED); ++ /* PLCP length u16, little endian */ ++ plcp[2] = usec & 0xff; ++ plcp[3] = (usec >> 8) & 0xff; ++ /* PLCP CRC16 */ ++ plcp[4] = 0; ++ plcp[5] = 0; ++} ++ ++/* Rate: 802.11 rate code, length: PSDU length in octets */ ++static void brcms_c_compute_mimo_plcp(u32 rspec, uint length, u8 *plcp) ++{ ++ u8 mcs = (u8) (rspec & RSPEC_RATE_MASK); ++ plcp[0] = mcs; ++ if (rspec_is40mhz(rspec) || (mcs == 32)) ++ plcp[0] |= MIMO_PLCP_40MHZ; ++ BRCMS_SET_MIMO_PLCP_LEN(plcp, length); ++ plcp[3] = rspec_mimoplcp3(rspec); /* rspec already holds this byte */ ++ plcp[3] |= 0x7; /* set smoothing, not sounding ppdu & reserved */ ++ plcp[4] = 0; /* number of extension spatial streams bit 0 & 1 */ ++ plcp[5] = 0; ++} ++ ++/* Rate: 802.11 rate code, length: PSDU length in octets */ ++static void ++brcms_c_compute_ofdm_plcp(u32 rspec, u32 length, u8 *plcp) ++{ ++ u8 rate_signal; ++ u32 tmp = 0; ++ int rate = rspec2rate(rspec); ++ ++ /* ++ * encode rate per 802.11a-1999 sec 17.3.4.1, with lsb ++ * transmitted first ++ */ ++ rate_signal = rate_info[rate] & BRCMS_RATE_MASK; ++ memset(plcp, 0, D11_PHY_HDR_LEN); ++ D11A_PHY_HDR_SRATE((struct ofdm_phy_hdr *) plcp, rate_signal); ++ ++ tmp = (length & 0xfff) << 5; ++ plcp[2] |= (tmp >> 16) & 0xff; ++ plcp[1] |= (tmp >> 8) & 0xff; ++ plcp[0] |= tmp & 0xff; ++} ++ ++/* Rate: 802.11 rate code, length: PSDU length in octets */ ++static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, u32 rspec, ++ uint length, u8 *plcp) ++{ ++ int rate = rspec2rate(rspec); ++ ++ brcms_c_cck_plcp_set(wlc, rate, length, plcp); ++} ++ ++static void ++brcms_c_compute_plcp(struct brcms_c_info *wlc, u32 rspec, ++ uint length, u8 *plcp) ++{ ++ if (is_mcs_rate(rspec)) ++ brcms_c_compute_mimo_plcp(rspec, length, plcp); ++ else if (is_ofdm_rate(rspec)) ++ brcms_c_compute_ofdm_plcp(rspec, length, plcp); ++ else ++ brcms_c_compute_cck_plcp(wlc, rspec, length, plcp); ++} ++ ++/* brcms_c_compute_rtscts_dur() ++ * ++ * Calculate the 802.11 MAC header DUR field for an RTS or CTS frame ++ * DUR for normal RTS/CTS w/ frame = 3 SIFS + 1 CTS + next frame time + 1 ACK ++ * DUR for CTS-TO-SELF w/ frame = 2 SIFS + next frame time + 1 ACK ++ * ++ * cts cts-to-self or rts/cts ++ * rts_rate rts or cts rate in unit of 500kbps ++ * rate next MPDU rate in unit of 500kbps ++ * frame_len next MPDU frame length in bytes ++ */ ++u16 ++brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only, ++ u32 rts_rate, ++ u32 frame_rate, u8 rts_preamble_type, ++ u8 frame_preamble_type, uint frame_len, bool ba) ++{ ++ u16 dur, sifs; ++ ++ sifs = get_sifs(wlc->band); ++ ++ if (!cts_only) { ++ /* RTS/CTS */ ++ dur = 3 * sifs; ++ dur += ++ (u16) brcms_c_calc_cts_time(wlc, rts_rate, ++ rts_preamble_type); ++ } else { ++ /* CTS-TO-SELF */ ++ dur = 2 * sifs; ++ } ++ ++ dur += ++ (u16) brcms_c_calc_frame_time(wlc, frame_rate, frame_preamble_type, ++ frame_len); ++ if (ba) ++ dur += ++ (u16) brcms_c_calc_ba_time(wlc, frame_rate, ++ BRCMS_SHORT_PREAMBLE); ++ else ++ dur += ++ (u16) brcms_c_calc_ack_time(wlc, frame_rate, ++ frame_preamble_type); ++ return dur; ++} ++ ++static u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec) ++{ ++ u16 phyctl1 = 0; ++ u16 bw; ++ ++ if (BRCMS_ISLCNPHY(wlc->band)) { ++ bw = PHY_TXC1_BW_20MHZ; ++ } else { ++ bw = rspec_get_bw(rspec); ++ /* 10Mhz is not supported yet */ ++ if (bw < PHY_TXC1_BW_20MHZ) { ++ wiphy_err(wlc->wiphy, "phytxctl1_calc: bw %d is " ++ "not supported yet, set to 20L\n", bw); ++ bw = PHY_TXC1_BW_20MHZ; ++ } ++ } ++ ++ if (is_mcs_rate(rspec)) { ++ uint mcs = rspec & RSPEC_RATE_MASK; ++ ++ /* bw, stf, coding-type is part of rspec_phytxbyte2 returns */ ++ phyctl1 = rspec_phytxbyte2(rspec); ++ /* set the upper byte of phyctl1 */ ++ phyctl1 |= (mcs_table[mcs].tx_phy_ctl3 << 8); ++ } else if (is_cck_rate(rspec) && !BRCMS_ISLCNPHY(wlc->band) ++ && !BRCMS_ISSSLPNPHY(wlc->band)) { ++ /* ++ * In CCK mode LPPHY overloads OFDM Modulation bits with CCK ++ * Data Rate. Eventually MIMOPHY would also be converted to ++ * this format ++ */ ++ /* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */ ++ phyctl1 = (bw | (rspec_stf(rspec) << PHY_TXC1_MODE_SHIFT)); ++ } else { /* legacy OFDM/CCK */ ++ s16 phycfg; ++ /* get the phyctl byte from rate phycfg table */ ++ phycfg = brcms_c_rate_legacy_phyctl(rspec2rate(rspec)); ++ if (phycfg == -1) { ++ wiphy_err(wlc->wiphy, "phytxctl1_calc: wrong " ++ "legacy OFDM/CCK rate\n"); ++ phycfg = 0; ++ } ++ /* set the upper byte of phyctl1 */ ++ phyctl1 = ++ (bw | (phycfg << 8) | ++ (rspec_stf(rspec) << PHY_TXC1_MODE_SHIFT)); ++ } ++ return phyctl1; ++} ++ ++/* ++ * Add struct d11txh, struct cck_phy_hdr. ++ * ++ * 'p' data must start with 802.11 MAC header ++ * 'p' must allow enough bytes of local headers to be "pushed" onto the packet ++ * ++ * headroom == D11_PHY_HDR_LEN + D11_TXH_LEN (D11_TXH_LEN is now 104 bytes) ++ * ++ */ ++static u16 ++brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw, ++ struct sk_buff *p, struct scb *scb, uint frag, ++ uint nfrags, uint queue, uint next_frag_len) ++{ ++ struct ieee80211_hdr *h; ++ struct d11txh *txh; ++ u8 *plcp, plcp_fallback[D11_PHY_HDR_LEN]; ++ int len, phylen, rts_phylen; ++ u16 mch, phyctl, xfts, mainrates; ++ u16 seq = 0, mcl = 0, status = 0, frameid = 0; ++ u32 rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M }; ++ u32 rts_rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M }; ++ bool use_rts = false; ++ bool use_cts = false; ++ bool use_rifs = false; ++ bool short_preamble[2] = { false, false }; ++ u8 preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE }; ++ u8 rts_preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE }; ++ u8 *rts_plcp, rts_plcp_fallback[D11_PHY_HDR_LEN]; ++ struct ieee80211_rts *rts = NULL; ++ bool qos; ++ uint ac; ++ bool hwtkmic = false; ++ u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ; ++#define ANTCFG_NONE 0xFF ++ u8 antcfg = ANTCFG_NONE; ++ u8 fbantcfg = ANTCFG_NONE; ++ uint phyctl1_stf = 0; ++ u16 durid = 0; ++ struct ieee80211_tx_rate *txrate[2]; ++ int k; ++ struct ieee80211_tx_info *tx_info; ++ bool is_mcs; ++ u16 mimo_txbw; ++ u8 mimo_preamble_type; ++ ++ /* locate 802.11 MAC header */ ++ h = (struct ieee80211_hdr *)(p->data); ++ qos = ieee80211_is_data_qos(h->frame_control); ++ ++ /* compute length of frame in bytes for use in PLCP computations */ ++ len = brcmu_pkttotlen(p); ++ phylen = len + FCS_LEN; ++ ++ /* Get tx_info */ ++ tx_info = IEEE80211_SKB_CB(p); ++ ++ /* add PLCP */ ++ plcp = skb_push(p, D11_PHY_HDR_LEN); ++ ++ /* add Broadcom tx descriptor header */ ++ txh = (struct d11txh *) skb_push(p, D11_TXH_LEN); ++ memset(txh, 0, D11_TXH_LEN); ++ ++ /* setup frameid */ ++ if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { ++ /* non-AP STA should never use BCMC queue */ ++ if (queue == TX_BCMC_FIFO) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: ASSERT queue == " ++ "TX_BCMC!\n", wlc->pub->unit, __func__); ++ frameid = bcmc_fid_generate(wlc, NULL, txh); ++ } else { ++ /* Increment the counter for first fragment */ ++ if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) ++ scb->seqnum[p->priority]++; ++ ++ /* extract fragment number from frame first */ ++ seq = le16_to_cpu(h->seq_ctrl) & FRAGNUM_MASK; ++ seq |= (scb->seqnum[p->priority] << SEQNUM_SHIFT); ++ h->seq_ctrl = cpu_to_le16(seq); ++ ++ frameid = ((seq << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) | ++ (queue & TXFID_QUEUE_MASK); ++ } ++ } ++ frameid |= queue & TXFID_QUEUE_MASK; ++ ++ /* set the ignpmq bit for all pkts tx'd in PS mode and for beacons */ ++ if (ieee80211_is_beacon(h->frame_control)) ++ mcl |= TXC_IGNOREPMQ; ++ ++ txrate[0] = tx_info->control.rates; ++ txrate[1] = txrate[0] + 1; ++ ++ /* ++ * if rate control algorithm didn't give us a fallback ++ * rate, use the primary rate ++ */ ++ if (txrate[1]->idx < 0) ++ txrate[1] = txrate[0]; ++ ++ for (k = 0; k < hw->max_rates; k++) { ++ is_mcs = txrate[k]->flags & IEEE80211_TX_RC_MCS ? true : false; ++ if (!is_mcs) { ++ if ((txrate[k]->idx >= 0) ++ && (txrate[k]->idx < ++ hw->wiphy->bands[tx_info->band]->n_bitrates)) { ++ rspec[k] = ++ hw->wiphy->bands[tx_info->band]-> ++ bitrates[txrate[k]->idx].hw_value; ++ short_preamble[k] = ++ txrate[k]-> ++ flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE ? ++ true : false; ++ } else { ++ rspec[k] = BRCM_RATE_1M; ++ } ++ } else { ++ rspec[k] = mac80211_wlc_set_nrate(wlc, wlc->band, ++ NRATE_MCS_INUSE | txrate[k]->idx); ++ } ++ ++ /* ++ * Currently only support same setting for primay and ++ * fallback rates. Unify flags for each rate into a ++ * single value for the frame ++ */ ++ use_rts |= ++ txrate[k]-> ++ flags & IEEE80211_TX_RC_USE_RTS_CTS ? true : false; ++ use_cts |= ++ txrate[k]-> ++ flags & IEEE80211_TX_RC_USE_CTS_PROTECT ? true : false; ++ ++ ++ /* ++ * (1) RATE: ++ * determine and validate primary rate ++ * and fallback rates ++ */ ++ if (!rspec_active(rspec[k])) { ++ rspec[k] = BRCM_RATE_1M; ++ } else { ++ if (!is_multicast_ether_addr(h->addr1)) { ++ /* set tx antenna config */ ++ brcms_c_antsel_antcfg_get(wlc->asi, false, ++ false, 0, 0, &antcfg, &fbantcfg); ++ } ++ } ++ } ++ ++ phyctl1_stf = wlc->stf->ss_opmode; ++ ++ if (wlc->pub->_n_enab & SUPPORT_11N) { ++ for (k = 0; k < hw->max_rates; k++) { ++ /* ++ * apply siso/cdd to single stream mcs's or ofdm ++ * if rspec is auto selected ++ */ ++ if (((is_mcs_rate(rspec[k]) && ++ is_single_stream(rspec[k] & RSPEC_RATE_MASK)) || ++ is_ofdm_rate(rspec[k])) ++ && ((rspec[k] & RSPEC_OVERRIDE_MCS_ONLY) ++ || !(rspec[k] & RSPEC_OVERRIDE))) { ++ rspec[k] &= ~(RSPEC_STF_MASK | RSPEC_STC_MASK); ++ ++ /* For SISO MCS use STBC if possible */ ++ if (is_mcs_rate(rspec[k]) ++ && BRCMS_STF_SS_STBC_TX(wlc, scb)) { ++ u8 stc; ++ ++ /* Nss for single stream is always 1 */ ++ stc = 1; ++ rspec[k] |= (PHY_TXC1_MODE_STBC << ++ RSPEC_STF_SHIFT) | ++ (stc << RSPEC_STC_SHIFT); ++ } else ++ rspec[k] |= ++ (phyctl1_stf << RSPEC_STF_SHIFT); ++ } ++ ++ /* ++ * Is the phy configured to use 40MHZ frames? If ++ * so then pick the desired txbw ++ */ ++ if (brcms_chspec_bw(wlc->chanspec) == BRCMS_40_MHZ) { ++ /* default txbw is 20in40 SB */ ++ mimo_ctlchbw = mimo_txbw = ++ CHSPEC_SB_UPPER(wlc_phy_chanspec_get( ++ wlc->band->pi)) ++ ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ; ++ ++ if (is_mcs_rate(rspec[k])) { ++ /* mcs 32 must be 40b/w DUP */ ++ if ((rspec[k] & RSPEC_RATE_MASK) ++ == 32) { ++ mimo_txbw = ++ PHY_TXC1_BW_40MHZ_DUP; ++ /* use override */ ++ } else if (wlc->mimo_40txbw != AUTO) ++ mimo_txbw = wlc->mimo_40txbw; ++ /* else check if dst is using 40 Mhz */ ++ else if (scb->flags & SCB_IS40) ++ mimo_txbw = PHY_TXC1_BW_40MHZ; ++ } else if (is_ofdm_rate(rspec[k])) { ++ if (wlc->ofdm_40txbw != AUTO) ++ mimo_txbw = wlc->ofdm_40txbw; ++ } else if (wlc->cck_40txbw != AUTO) { ++ mimo_txbw = wlc->cck_40txbw; ++ } ++ } else { ++ /* ++ * mcs32 is 40 b/w only. ++ * This is possible for probe packets on ++ * a STA during SCAN ++ */ ++ if ((rspec[k] & RSPEC_RATE_MASK) == 32) ++ /* mcs 0 */ ++ rspec[k] = RSPEC_MIMORATE; ++ ++ mimo_txbw = PHY_TXC1_BW_20MHZ; ++ } ++ ++ /* Set channel width */ ++ rspec[k] &= ~RSPEC_BW_MASK; ++ if ((k == 0) || ((k > 0) && is_mcs_rate(rspec[k]))) ++ rspec[k] |= (mimo_txbw << RSPEC_BW_SHIFT); ++ else ++ rspec[k] |= (mimo_ctlchbw << RSPEC_BW_SHIFT); ++ ++ /* Disable short GI, not supported yet */ ++ rspec[k] &= ~RSPEC_SHORT_GI; ++ ++ mimo_preamble_type = BRCMS_MM_PREAMBLE; ++ if (txrate[k]->flags & IEEE80211_TX_RC_GREEN_FIELD) ++ mimo_preamble_type = BRCMS_GF_PREAMBLE; ++ ++ if ((txrate[k]->flags & IEEE80211_TX_RC_MCS) ++ && (!is_mcs_rate(rspec[k]))) { ++ wiphy_err(wlc->wiphy, "wl%d: %s: IEEE80211_TX_" ++ "RC_MCS != is_mcs_rate(rspec)\n", ++ wlc->pub->unit, __func__); ++ } ++ ++ if (is_mcs_rate(rspec[k])) { ++ preamble_type[k] = mimo_preamble_type; ++ ++ /* ++ * if SGI is selected, then forced mm ++ * for single stream ++ */ ++ if ((rspec[k] & RSPEC_SHORT_GI) ++ && is_single_stream(rspec[k] & ++ RSPEC_RATE_MASK)) ++ preamble_type[k] = BRCMS_MM_PREAMBLE; ++ } ++ ++ /* should be better conditionalized */ ++ if (!is_mcs_rate(rspec[0]) ++ && (tx_info->control.rates[0]. ++ flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)) ++ preamble_type[k] = BRCMS_SHORT_PREAMBLE; ++ } ++ } else { ++ for (k = 0; k < hw->max_rates; k++) { ++ /* Set ctrlchbw as 20Mhz */ ++ rspec[k] &= ~RSPEC_BW_MASK; ++ rspec[k] |= (PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT); ++ ++ /* for nphy, stf of ofdm frames must follow policies */ ++ if (BRCMS_ISNPHY(wlc->band) && is_ofdm_rate(rspec[k])) { ++ rspec[k] &= ~RSPEC_STF_MASK; ++ rspec[k] |= phyctl1_stf << RSPEC_STF_SHIFT; ++ } ++ } ++ } ++ ++ /* Reset these for use with AMPDU's */ ++ txrate[0]->count = 0; ++ txrate[1]->count = 0; ++ ++ /* (2) PROTECTION, may change rspec */ ++ if ((ieee80211_is_data(h->frame_control) || ++ ieee80211_is_mgmt(h->frame_control)) && ++ (phylen > wlc->RTSThresh) && !is_multicast_ether_addr(h->addr1)) ++ use_rts = true; ++ ++ /* (3) PLCP: determine PLCP header and MAC duration, ++ * fill struct d11txh */ ++ brcms_c_compute_plcp(wlc, rspec[0], phylen, plcp); ++ brcms_c_compute_plcp(wlc, rspec[1], phylen, plcp_fallback); ++ memcpy(&txh->FragPLCPFallback, ++ plcp_fallback, sizeof(txh->FragPLCPFallback)); ++ ++ /* Length field now put in CCK FBR CRC field */ ++ if (is_cck_rate(rspec[1])) { ++ txh->FragPLCPFallback[4] = phylen & 0xff; ++ txh->FragPLCPFallback[5] = (phylen & 0xff00) >> 8; ++ } ++ ++ /* MIMO-RATE: need validation ?? */ ++ mainrates = is_ofdm_rate(rspec[0]) ? ++ D11A_PHY_HDR_GRATE((struct ofdm_phy_hdr *) plcp) : ++ plcp[0]; ++ ++ /* DUR field for main rate */ ++ if (!ieee80211_is_pspoll(h->frame_control) && ++ !is_multicast_ether_addr(h->addr1) && !use_rifs) { ++ durid = ++ brcms_c_compute_frame_dur(wlc, rspec[0], preamble_type[0], ++ next_frag_len); ++ h->duration_id = cpu_to_le16(durid); ++ } else if (use_rifs) { ++ /* NAV protect to end of next max packet size */ ++ durid = ++ (u16) brcms_c_calc_frame_time(wlc, rspec[0], ++ preamble_type[0], ++ DOT11_MAX_FRAG_LEN); ++ durid += RIFS_11N_TIME; ++ h->duration_id = cpu_to_le16(durid); ++ } ++ ++ /* DUR field for fallback rate */ ++ if (ieee80211_is_pspoll(h->frame_control)) ++ txh->FragDurFallback = h->duration_id; ++ else if (is_multicast_ether_addr(h->addr1) || use_rifs) ++ txh->FragDurFallback = 0; ++ else { ++ durid = brcms_c_compute_frame_dur(wlc, rspec[1], ++ preamble_type[1], next_frag_len); ++ txh->FragDurFallback = cpu_to_le16(durid); ++ } ++ ++ /* (4) MAC-HDR: MacTxControlLow */ ++ if (frag == 0) ++ mcl |= TXC_STARTMSDU; ++ ++ if (!is_multicast_ether_addr(h->addr1)) ++ mcl |= TXC_IMMEDACK; ++ ++ if (wlc->band->bandtype == BRCM_BAND_5G) ++ mcl |= TXC_FREQBAND_5G; ++ ++ if (CHSPEC_IS40(wlc_phy_chanspec_get(wlc->band->pi))) ++ mcl |= TXC_BW_40; ++ ++ /* set AMIC bit if using hardware TKIP MIC */ ++ if (hwtkmic) ++ mcl |= TXC_AMIC; ++ ++ txh->MacTxControlLow = cpu_to_le16(mcl); ++ ++ /* MacTxControlHigh */ ++ mch = 0; ++ ++ /* Set fallback rate preamble type */ ++ if ((preamble_type[1] == BRCMS_SHORT_PREAMBLE) || ++ (preamble_type[1] == BRCMS_GF_PREAMBLE)) { ++ if (rspec2rate(rspec[1]) != BRCM_RATE_1M) ++ mch |= TXC_PREAMBLE_DATA_FB_SHORT; ++ } ++ ++ /* MacFrameControl */ ++ memcpy(&txh->MacFrameControl, &h->frame_control, sizeof(u16)); ++ txh->TxFesTimeNormal = cpu_to_le16(0); ++ ++ txh->TxFesTimeFallback = cpu_to_le16(0); ++ ++ /* TxFrameRA */ ++ memcpy(&txh->TxFrameRA, &h->addr1, ETH_ALEN); ++ ++ /* TxFrameID */ ++ txh->TxFrameID = cpu_to_le16(frameid); ++ ++ /* ++ * TxStatus, Note the case of recreating the first frag of a suppressed ++ * frame then we may need to reset the retry cnt's via the status reg ++ */ ++ txh->TxStatus = cpu_to_le16(status); ++ ++ /* ++ * extra fields for ucode AMPDU aggregation, the new fields are added to ++ * the END of previous structure so that it's compatible in driver. ++ */ ++ txh->MaxNMpdus = cpu_to_le16(0); ++ txh->MaxABytes_MRT = cpu_to_le16(0); ++ txh->MaxABytes_FBR = cpu_to_le16(0); ++ txh->MinMBytes = cpu_to_le16(0); ++ ++ /* (5) RTS/CTS: determine RTS/CTS PLCP header and MAC duration, ++ * furnish struct d11txh */ ++ /* RTS PLCP header and RTS frame */ ++ if (use_rts || use_cts) { ++ if (use_rts && use_cts) ++ use_cts = false; ++ ++ for (k = 0; k < 2; k++) { ++ rts_rspec[k] = brcms_c_rspec_to_rts_rspec(wlc, rspec[k], ++ false, ++ mimo_ctlchbw); ++ } ++ ++ if (!is_ofdm_rate(rts_rspec[0]) && ++ !((rspec2rate(rts_rspec[0]) == BRCM_RATE_1M) || ++ (wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) { ++ rts_preamble_type[0] = BRCMS_SHORT_PREAMBLE; ++ mch |= TXC_PREAMBLE_RTS_MAIN_SHORT; ++ } ++ ++ if (!is_ofdm_rate(rts_rspec[1]) && ++ !((rspec2rate(rts_rspec[1]) == BRCM_RATE_1M) || ++ (wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) { ++ rts_preamble_type[1] = BRCMS_SHORT_PREAMBLE; ++ mch |= TXC_PREAMBLE_RTS_FB_SHORT; ++ } ++ ++ /* RTS/CTS additions to MacTxControlLow */ ++ if (use_cts) { ++ txh->MacTxControlLow |= cpu_to_le16(TXC_SENDCTS); ++ } else { ++ txh->MacTxControlLow |= cpu_to_le16(TXC_SENDRTS); ++ txh->MacTxControlLow |= cpu_to_le16(TXC_LONGFRAME); ++ } ++ ++ /* RTS PLCP header */ ++ rts_plcp = txh->RTSPhyHeader; ++ if (use_cts) ++ rts_phylen = DOT11_CTS_LEN + FCS_LEN; ++ else ++ rts_phylen = DOT11_RTS_LEN + FCS_LEN; ++ ++ brcms_c_compute_plcp(wlc, rts_rspec[0], rts_phylen, rts_plcp); ++ ++ /* fallback rate version of RTS PLCP header */ ++ brcms_c_compute_plcp(wlc, rts_rspec[1], rts_phylen, ++ rts_plcp_fallback); ++ memcpy(&txh->RTSPLCPFallback, rts_plcp_fallback, ++ sizeof(txh->RTSPLCPFallback)); ++ ++ /* RTS frame fields... */ ++ rts = (struct ieee80211_rts *)&txh->rts_frame; ++ ++ durid = brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec[0], ++ rspec[0], rts_preamble_type[0], ++ preamble_type[0], phylen, false); ++ rts->duration = cpu_to_le16(durid); ++ /* fallback rate version of RTS DUR field */ ++ durid = brcms_c_compute_rtscts_dur(wlc, use_cts, ++ rts_rspec[1], rspec[1], ++ rts_preamble_type[1], ++ preamble_type[1], phylen, false); ++ txh->RTSDurFallback = cpu_to_le16(durid); ++ ++ if (use_cts) { ++ rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | ++ IEEE80211_STYPE_CTS); ++ ++ memcpy(&rts->ra, &h->addr2, ETH_ALEN); ++ } else { ++ rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | ++ IEEE80211_STYPE_RTS); ++ ++ memcpy(&rts->ra, &h->addr1, 2 * ETH_ALEN); ++ } ++ ++ /* mainrate ++ * low 8 bits: main frag rate/mcs, ++ * high 8 bits: rts/cts rate/mcs ++ */ ++ mainrates |= (is_ofdm_rate(rts_rspec[0]) ? ++ D11A_PHY_HDR_GRATE( ++ (struct ofdm_phy_hdr *) rts_plcp) : ++ rts_plcp[0]) << 8; ++ } else { ++ memset((char *)txh->RTSPhyHeader, 0, D11_PHY_HDR_LEN); ++ memset((char *)&txh->rts_frame, 0, ++ sizeof(struct ieee80211_rts)); ++ memset((char *)txh->RTSPLCPFallback, 0, ++ sizeof(txh->RTSPLCPFallback)); ++ txh->RTSDurFallback = 0; ++ } ++ ++#ifdef SUPPORT_40MHZ ++ /* add null delimiter count */ ++ if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && is_mcs_rate(rspec)) ++ txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = ++ brcm_c_ampdu_null_delim_cnt(wlc->ampdu, scb, rspec, phylen); ++ ++#endif ++ ++ /* ++ * Now that RTS/RTS FB preamble types are updated, write ++ * the final value ++ */ ++ txh->MacTxControlHigh = cpu_to_le16(mch); ++ ++ /* ++ * MainRates (both the rts and frag plcp rates have ++ * been calculated now) ++ */ ++ txh->MainRates = cpu_to_le16(mainrates); ++ ++ /* XtraFrameTypes */ ++ xfts = frametype(rspec[1], wlc->mimoft); ++ xfts |= (frametype(rts_rspec[0], wlc->mimoft) << XFTS_RTS_FT_SHIFT); ++ xfts |= (frametype(rts_rspec[1], wlc->mimoft) << XFTS_FBRRTS_FT_SHIFT); ++ xfts |= CHSPEC_CHANNEL(wlc_phy_chanspec_get(wlc->band->pi)) << ++ XFTS_CHANNEL_SHIFT; ++ txh->XtraFrameTypes = cpu_to_le16(xfts); ++ ++ /* PhyTxControlWord */ ++ phyctl = frametype(rspec[0], wlc->mimoft); ++ if ((preamble_type[0] == BRCMS_SHORT_PREAMBLE) || ++ (preamble_type[0] == BRCMS_GF_PREAMBLE)) { ++ if (rspec2rate(rspec[0]) != BRCM_RATE_1M) ++ phyctl |= PHY_TXC_SHORT_HDR; ++ } ++ ++ /* phytxant is properly bit shifted */ ++ phyctl |= brcms_c_stf_d11hdrs_phyctl_txant(wlc, rspec[0]); ++ txh->PhyTxControlWord = cpu_to_le16(phyctl); ++ ++ /* PhyTxControlWord_1 */ ++ if (BRCMS_PHY_11N_CAP(wlc->band)) { ++ u16 phyctl1 = 0; ++ ++ phyctl1 = brcms_c_phytxctl1_calc(wlc, rspec[0]); ++ txh->PhyTxControlWord_1 = cpu_to_le16(phyctl1); ++ phyctl1 = brcms_c_phytxctl1_calc(wlc, rspec[1]); ++ txh->PhyTxControlWord_1_Fbr = cpu_to_le16(phyctl1); ++ ++ if (use_rts || use_cts) { ++ phyctl1 = brcms_c_phytxctl1_calc(wlc, rts_rspec[0]); ++ txh->PhyTxControlWord_1_Rts = cpu_to_le16(phyctl1); ++ phyctl1 = brcms_c_phytxctl1_calc(wlc, rts_rspec[1]); ++ txh->PhyTxControlWord_1_FbrRts = cpu_to_le16(phyctl1); ++ } ++ ++ /* ++ * For mcs frames, if mixedmode(overloaded with long preamble) ++ * is going to be set, fill in non-zero MModeLen and/or ++ * MModeFbrLen it will be unnecessary if they are separated ++ */ ++ if (is_mcs_rate(rspec[0]) && ++ (preamble_type[0] == BRCMS_MM_PREAMBLE)) { ++ u16 mmodelen = ++ brcms_c_calc_lsig_len(wlc, rspec[0], phylen); ++ txh->MModeLen = cpu_to_le16(mmodelen); ++ } ++ ++ if (is_mcs_rate(rspec[1]) && ++ (preamble_type[1] == BRCMS_MM_PREAMBLE)) { ++ u16 mmodefbrlen = ++ brcms_c_calc_lsig_len(wlc, rspec[1], phylen); ++ txh->MModeFbrLen = cpu_to_le16(mmodefbrlen); ++ } ++ } ++ ++ ac = skb_get_queue_mapping(p); ++ if ((scb->flags & SCB_WMECAP) && qos && wlc->edcf_txop[ac]) { ++ uint frag_dur, dur, dur_fallback; ++ ++ /* WME: Update TXOP threshold */ ++ if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) && frag == 0) { ++ frag_dur = ++ brcms_c_calc_frame_time(wlc, rspec[0], ++ preamble_type[0], phylen); ++ ++ if (rts) { ++ /* 1 RTS or CTS-to-self frame */ ++ dur = ++ brcms_c_calc_cts_time(wlc, rts_rspec[0], ++ rts_preamble_type[0]); ++ dur_fallback = ++ brcms_c_calc_cts_time(wlc, rts_rspec[1], ++ rts_preamble_type[1]); ++ /* (SIFS + CTS) + SIFS + frame + SIFS + ACK */ ++ dur += le16_to_cpu(rts->duration); ++ dur_fallback += ++ le16_to_cpu(txh->RTSDurFallback); ++ } else if (use_rifs) { ++ dur = frag_dur; ++ dur_fallback = 0; ++ } else { ++ /* frame + SIFS + ACK */ ++ dur = frag_dur; ++ dur += ++ brcms_c_compute_frame_dur(wlc, rspec[0], ++ preamble_type[0], 0); ++ ++ dur_fallback = ++ brcms_c_calc_frame_time(wlc, rspec[1], ++ preamble_type[1], ++ phylen); ++ dur_fallback += ++ brcms_c_compute_frame_dur(wlc, rspec[1], ++ preamble_type[1], 0); ++ } ++ /* NEED to set TxFesTimeNormal (hard) */ ++ txh->TxFesTimeNormal = cpu_to_le16((u16) dur); ++ /* ++ * NEED to set fallback rate version of ++ * TxFesTimeNormal (hard) ++ */ ++ txh->TxFesTimeFallback = ++ cpu_to_le16((u16) dur_fallback); ++ ++ /* ++ * update txop byte threshold (txop minus intraframe ++ * overhead) ++ */ ++ if (wlc->edcf_txop[ac] >= (dur - frag_dur)) { ++ uint newfragthresh; ++ ++ newfragthresh = ++ brcms_c_calc_frame_len(wlc, ++ rspec[0], preamble_type[0], ++ (wlc->edcf_txop[ac] - ++ (dur - frag_dur))); ++ /* range bound the fragthreshold */ ++ if (newfragthresh < DOT11_MIN_FRAG_LEN) ++ newfragthresh = ++ DOT11_MIN_FRAG_LEN; ++ else if (newfragthresh > ++ wlc->usr_fragthresh) ++ newfragthresh = ++ wlc->usr_fragthresh; ++ /* update the fragthresh and do txc update */ ++ if (wlc->fragthresh[queue] != ++ (u16) newfragthresh) ++ wlc->fragthresh[queue] = ++ (u16) newfragthresh; ++ } else { ++ wiphy_err(wlc->wiphy, "wl%d: %s txop invalid " ++ "for rate %d\n", ++ wlc->pub->unit, fifo_names[queue], ++ rspec2rate(rspec[0])); ++ } ++ ++ if (dur > wlc->edcf_txop[ac]) ++ wiphy_err(wlc->wiphy, "wl%d: %s: %s txop " ++ "exceeded phylen %d/%d dur %d/%d\n", ++ wlc->pub->unit, __func__, ++ fifo_names[queue], ++ phylen, wlc->fragthresh[queue], ++ dur, wlc->edcf_txop[ac]); ++ } ++ } ++ ++ return 0; ++} ++ ++void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu, ++ struct ieee80211_hw *hw) ++{ ++ u8 prio; ++ uint fifo; ++ struct scb *scb = &wlc->pri_scb; ++ struct ieee80211_hdr *d11_header = (struct ieee80211_hdr *)(sdu->data); ++ ++ /* ++ * 802.11 standard requires management traffic ++ * to go at highest priority ++ */ ++ prio = ieee80211_is_data(d11_header->frame_control) ? sdu->priority : ++ MAXPRIO; ++ fifo = prio2fifo[prio]; ++ if (brcms_c_d11hdrs_mac80211(wlc, hw, sdu, scb, 0, 1, fifo, 0)) ++ return; ++ brcms_c_txq_enq(wlc, scb, sdu, BRCMS_PRIO_TO_PREC(prio)); ++ brcms_c_send_q(wlc); ++} ++ ++void brcms_c_send_q(struct brcms_c_info *wlc) ++{ ++ struct sk_buff *pkt[DOT11_MAXNUMFRAGS]; ++ int prec; ++ u16 prec_map; ++ int err = 0, i, count; ++ uint fifo; ++ struct brcms_txq_info *qi = wlc->pkt_queue; ++ struct pktq *q = &qi->q; ++ struct ieee80211_tx_info *tx_info; ++ ++ prec_map = wlc->tx_prec_map; ++ ++ /* Send all the enq'd pkts that we can. ++ * Dequeue packets with precedence with empty HW fifo only ++ */ ++ while (prec_map && (pkt[0] = brcmu_pktq_mdeq(q, prec_map, &prec))) { ++ tx_info = IEEE80211_SKB_CB(pkt[0]); ++ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { ++ err = brcms_c_sendampdu(wlc->ampdu, qi, pkt, prec); ++ } else { ++ count = 1; ++ err = brcms_c_prep_pdu(wlc, pkt[0], &fifo); ++ if (!err) { ++ for (i = 0; i < count; i++) ++ brcms_c_txfifo(wlc, fifo, pkt[i], true, ++ 1); ++ } ++ } ++ ++ if (err == -EBUSY) { ++ brcmu_pktq_penq_head(q, prec, pkt[0]); ++ /* ++ * If send failed due to any other reason than a ++ * change in HW FIFO condition, quit. Otherwise, ++ * read the new prec_map! ++ */ ++ if (prec_map == wlc->tx_prec_map) ++ break; ++ prec_map = wlc->tx_prec_map; ++ } ++ } ++} ++ ++void ++brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p, ++ bool commit, s8 txpktpend) ++{ ++ u16 frameid = INVALIDFID; ++ struct d11txh *txh; ++ ++ txh = (struct d11txh *) (p->data); ++ ++ /* When a BC/MC frame is being committed to the BCMC fifo ++ * via DMA (NOT PIO), update ucode or BSS info as appropriate. ++ */ ++ if (fifo == TX_BCMC_FIFO) ++ frameid = le16_to_cpu(txh->TxFrameID); ++ ++ /* ++ * Bump up pending count for if not using rpc. If rpc is ++ * used, this will be handled in brcms_b_txfifo() ++ */ ++ if (commit) { ++ wlc->core->txpktpend[fifo] += txpktpend; ++ BCMMSG(wlc->wiphy, "pktpend inc %d to %d\n", ++ txpktpend, wlc->core->txpktpend[fifo]); ++ } ++ ++ /* Commit BCMC sequence number in the SHM frame ID location */ ++ if (frameid != INVALIDFID) { ++ /* ++ * To inform the ucode of the last mcast frame posted ++ * so that it can clear moredata bit ++ */ ++ brcms_b_write_shm(wlc->hw, M_BCMC_FID, frameid); ++ } ++ ++ if (dma_txfast(wlc->hw->di[fifo], p, commit) < 0) ++ wiphy_err(wlc->wiphy, "txfifo: fatal, toss frames !!!\n"); ++} ++ ++u32 ++brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec, ++ bool use_rspec, u16 mimo_ctlchbw) ++{ ++ u32 rts_rspec = 0; ++ ++ if (use_rspec) ++ /* use frame rate as rts rate */ ++ rts_rspec = rspec; ++ else if (wlc->band->gmode && wlc->protection->_g && !is_cck_rate(rspec)) ++ /* Use 11Mbps as the g protection RTS target rate and fallback. ++ * Use the brcms_basic_rate() lookup to find the best basic rate ++ * under the target in case 11 Mbps is not Basic. ++ * 6 and 9 Mbps are not usually selected by rate selection, but ++ * even if the OFDM rate we are protecting is 6 or 9 Mbps, 11 ++ * is more robust. ++ */ ++ rts_rspec = brcms_basic_rate(wlc, BRCM_RATE_11M); ++ else ++ /* calculate RTS rate and fallback rate based on the frame rate ++ * RTS must be sent at a basic rate since it is a ++ * control frame, sec 9.6 of 802.11 spec ++ */ ++ rts_rspec = brcms_basic_rate(wlc, rspec); ++ ++ if (BRCMS_PHY_11N_CAP(wlc->band)) { ++ /* set rts txbw to correct side band */ ++ rts_rspec &= ~RSPEC_BW_MASK; ++ ++ /* ++ * if rspec/rspec_fallback is 40MHz, then send RTS on both ++ * 20MHz channel (DUP), otherwise send RTS on control channel ++ */ ++ if (rspec_is40mhz(rspec) && !is_cck_rate(rts_rspec)) ++ rts_rspec |= (PHY_TXC1_BW_40MHZ_DUP << RSPEC_BW_SHIFT); ++ else ++ rts_rspec |= (mimo_ctlchbw << RSPEC_BW_SHIFT); ++ ++ /* pick siso/cdd as default for ofdm */ ++ if (is_ofdm_rate(rts_rspec)) { ++ rts_rspec &= ~RSPEC_STF_MASK; ++ rts_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT); ++ } ++ } ++ return rts_rspec; ++} ++ ++void ++brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, s8 txpktpend) ++{ ++ wlc->core->txpktpend[fifo] -= txpktpend; ++ BCMMSG(wlc->wiphy, "pktpend dec %d to %d\n", txpktpend, ++ wlc->core->txpktpend[fifo]); ++ ++ /* There is more room; mark precedences related to this FIFO sendable */ ++ wlc->tx_prec_map |= wlc->fifo2prec_map[fifo]; ++ ++ /* figure out which bsscfg is being worked on... */ ++} ++ ++/* Update beacon listen interval in shared memory */ ++static void brcms_c_bcn_li_upd(struct brcms_c_info *wlc) ++{ ++ /* wake up every DTIM is the default */ ++ if (wlc->bcn_li_dtim == 1) ++ brcms_b_write_shm(wlc->hw, M_BCN_LI, 0); ++ else ++ brcms_b_write_shm(wlc->hw, M_BCN_LI, ++ (wlc->bcn_li_dtim << 8) | wlc->bcn_li_bcn); ++} ++ ++static void ++brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr, ++ u32 *tsf_h_ptr) ++{ ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ ++ /* read the tsf timer low, then high to get an atomic read */ ++ *tsf_l_ptr = R_REG(®s->tsf_timerlow); ++ *tsf_h_ptr = R_REG(®s->tsf_timerhigh); ++} ++ ++/* ++ * recover 64bit TSF value from the 16bit TSF value in the rx header ++ * given the assumption that the TSF passed in header is within 65ms ++ * of the current tsf. ++ * ++ * 6 5 4 4 3 2 1 ++ * 3.......6.......8.......0.......2.......4.......6.......8......0 ++ * |<---------- tsf_h ----------->||<--- tsf_l -->||<-RxTSFTime ->| ++ * ++ * The RxTSFTime are the lowest 16 bits and provided by the ucode. The ++ * tsf_l is filled in by brcms_b_recv, which is done earlier in the ++ * receive call sequence after rx interrupt. Only the higher 16 bits ++ * are used. Finally, the tsf_h is read from the tsf register. ++ */ ++static u64 brcms_c_recover_tsf64(struct brcms_c_info *wlc, ++ struct d11rxhdr *rxh) ++{ ++ u32 tsf_h, tsf_l; ++ u16 rx_tsf_0_15, rx_tsf_16_31; ++ ++ brcms_b_read_tsf(wlc->hw, &tsf_l, &tsf_h); ++ ++ rx_tsf_16_31 = (u16)(tsf_l >> 16); ++ rx_tsf_0_15 = rxh->RxTSFTime; ++ ++ /* ++ * a greater tsf time indicates the low 16 bits of ++ * tsf_l wrapped, so decrement the high 16 bits. ++ */ ++ if ((u16)tsf_l < rx_tsf_0_15) { ++ rx_tsf_16_31 -= 1; ++ if (rx_tsf_16_31 == 0xffff) ++ tsf_h -= 1; ++ } ++ ++ return ((u64)tsf_h << 32) | (((u32)rx_tsf_16_31 << 16) + rx_tsf_0_15); ++} ++ ++static void ++prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh, ++ struct sk_buff *p, ++ struct ieee80211_rx_status *rx_status) ++{ ++ int preamble; ++ int channel; ++ u32 rspec; ++ unsigned char *plcp; ++ ++ /* fill in TSF and flag its presence */ ++ rx_status->mactime = brcms_c_recover_tsf64(wlc, rxh); ++ rx_status->flag |= RX_FLAG_MACTIME_MPDU; ++ ++ channel = BRCMS_CHAN_CHANNEL(rxh->RxChan); ++ ++ if (channel > 14) { ++ rx_status->band = IEEE80211_BAND_5GHZ; ++ rx_status->freq = ieee80211_ofdm_chan_to_freq( ++ WF_CHAN_FACTOR_5_G/2, channel); ++ ++ } else { ++ rx_status->band = IEEE80211_BAND_2GHZ; ++ rx_status->freq = ieee80211_dsss_chan_to_freq(channel); ++ } ++ ++ rx_status->signal = wlc_phy_rssi_compute(wlc->hw->band->pi, rxh); ++ ++ /* noise */ ++ /* qual */ ++ rx_status->antenna = ++ (rxh->PhyRxStatus_0 & PRXS0_RXANT_UPSUBBAND) ? 1 : 0; ++ ++ plcp = p->data; ++ ++ rspec = brcms_c_compute_rspec(rxh, plcp); ++ if (is_mcs_rate(rspec)) { ++ rx_status->rate_idx = rspec & RSPEC_RATE_MASK; ++ rx_status->flag |= RX_FLAG_HT; ++ if (rspec_is40mhz(rspec)) ++ rx_status->flag |= RX_FLAG_40MHZ; ++ } else { ++ switch (rspec2rate(rspec)) { ++ case BRCM_RATE_1M: ++ rx_status->rate_idx = 0; ++ break; ++ case BRCM_RATE_2M: ++ rx_status->rate_idx = 1; ++ break; ++ case BRCM_RATE_5M5: ++ rx_status->rate_idx = 2; ++ break; ++ case BRCM_RATE_11M: ++ rx_status->rate_idx = 3; ++ break; ++ case BRCM_RATE_6M: ++ rx_status->rate_idx = 4; ++ break; ++ case BRCM_RATE_9M: ++ rx_status->rate_idx = 5; ++ break; ++ case BRCM_RATE_12M: ++ rx_status->rate_idx = 6; ++ break; ++ case BRCM_RATE_18M: ++ rx_status->rate_idx = 7; ++ break; ++ case BRCM_RATE_24M: ++ rx_status->rate_idx = 8; ++ break; ++ case BRCM_RATE_36M: ++ rx_status->rate_idx = 9; ++ break; ++ case BRCM_RATE_48M: ++ rx_status->rate_idx = 10; ++ break; ++ case BRCM_RATE_54M: ++ rx_status->rate_idx = 11; ++ break; ++ default: ++ wiphy_err(wlc->wiphy, "%s: Unknown rate\n", __func__); ++ } ++ ++ /* ++ * For 5GHz, we should decrease the index as it is ++ * a subset of the 2.4G rates. See bitrates field ++ * of brcms_band_5GHz_nphy (in mac80211_if.c). ++ */ ++ if (rx_status->band == IEEE80211_BAND_5GHZ) ++ rx_status->rate_idx -= BRCMS_LEGACY_5G_RATE_OFFSET; ++ ++ /* Determine short preamble and rate_idx */ ++ preamble = 0; ++ if (is_cck_rate(rspec)) { ++ if (rxh->PhyRxStatus_0 & PRXS0_SHORTH) ++ rx_status->flag |= RX_FLAG_SHORTPRE; ++ } else if (is_ofdm_rate(rspec)) { ++ rx_status->flag |= RX_FLAG_SHORTPRE; ++ } else { ++ wiphy_err(wlc->wiphy, "%s: Unknown modulation\n", ++ __func__); ++ } ++ } ++ ++ if (plcp3_issgi(plcp[3])) ++ rx_status->flag |= RX_FLAG_SHORT_GI; ++ ++ if (rxh->RxStatus1 & RXS_DECERR) { ++ rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC; ++ wiphy_err(wlc->wiphy, "%s: RX_FLAG_FAILED_PLCP_CRC\n", ++ __func__); ++ } ++ if (rxh->RxStatus1 & RXS_FCSERR) { ++ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; ++ wiphy_err(wlc->wiphy, "%s: RX_FLAG_FAILED_FCS_CRC\n", ++ __func__); ++ } ++} ++ ++static void ++brcms_c_recvctl(struct brcms_c_info *wlc, struct d11rxhdr *rxh, ++ struct sk_buff *p) ++{ ++ int len_mpdu; ++ struct ieee80211_rx_status rx_status; ++ ++ memset(&rx_status, 0, sizeof(rx_status)); ++ prep_mac80211_status(wlc, rxh, p, &rx_status); ++ ++ /* mac header+body length, exclude CRC and plcp header */ ++ len_mpdu = p->len - D11_PHY_HDR_LEN - FCS_LEN; ++ skb_pull(p, D11_PHY_HDR_LEN); ++ __skb_trim(p, len_mpdu); ++ ++ memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status)); ++ ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p); ++} ++ ++/* calculate frame duration for Mixed-mode L-SIG spoofing, return ++ * number of bytes goes in the length field ++ * ++ * Formula given by HT PHY Spec v 1.13 ++ * len = 3(nsyms + nstream + 3) - 3 ++ */ ++u16 ++brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec, ++ uint mac_len) ++{ ++ uint nsyms, len = 0, kNdps; ++ ++ BCMMSG(wlc->wiphy, "wl%d: rate %d, len%d\n", ++ wlc->pub->unit, rspec2rate(ratespec), mac_len); ++ ++ if (is_mcs_rate(ratespec)) { ++ uint mcs = ratespec & RSPEC_RATE_MASK; ++ int tot_streams = (mcs_2_txstreams(mcs) + 1) + ++ rspec_stc(ratespec); ++ ++ /* ++ * the payload duration calculation matches that ++ * of regular ofdm ++ */ ++ /* 1000Ndbps = kbps * 4 */ ++ kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec), ++ rspec_issgi(ratespec)) * 4; ++ ++ if (rspec_stc(ratespec) == 0) ++ nsyms = ++ CEIL((APHY_SERVICE_NBITS + 8 * mac_len + ++ APHY_TAIL_NBITS) * 1000, kNdps); ++ else ++ /* STBC needs to have even number of symbols */ ++ nsyms = ++ 2 * ++ CEIL((APHY_SERVICE_NBITS + 8 * mac_len + ++ APHY_TAIL_NBITS) * 1000, 2 * kNdps); ++ ++ /* (+3) account for HT-SIG(2) and HT-STF(1) */ ++ nsyms += (tot_streams + 3); ++ /* ++ * 3 bytes/symbol @ legacy 6Mbps rate ++ * (-3) excluding service bits and tail bits ++ */ ++ len = (3 * nsyms) - 3; ++ } ++ ++ return (u16) len; ++} ++ ++static void ++brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len) ++{ ++ const struct brcms_c_rateset *rs_dflt; ++ struct brcms_c_rateset rs; ++ u8 rate; ++ u16 entry_ptr; ++ u8 plcp[D11_PHY_HDR_LEN]; ++ u16 dur, sifs; ++ uint i; ++ ++ sifs = get_sifs(wlc->band); ++ ++ rs_dflt = brcms_c_rateset_get_hwrs(wlc); ++ ++ brcms_c_rateset_copy(rs_dflt, &rs); ++ brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams); ++ ++ /* ++ * walk the phy rate table and update MAC core SHM ++ * basic rate table entries ++ */ ++ for (i = 0; i < rs.count; i++) { ++ rate = rs.rates[i] & BRCMS_RATE_MASK; ++ ++ entry_ptr = brcms_b_rate_shm_offset(wlc->hw, rate); ++ ++ /* Calculate the Probe Response PLCP for the given rate */ ++ brcms_c_compute_plcp(wlc, rate, frame_len, plcp); ++ ++ /* ++ * Calculate the duration of the Probe Response ++ * frame plus SIFS for the MAC ++ */ ++ dur = (u16) brcms_c_calc_frame_time(wlc, rate, ++ BRCMS_LONG_PREAMBLE, frame_len); ++ dur += sifs; ++ ++ /* Update the SHM Rate Table entry Probe Response values */ ++ brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_PLCP_POS, ++ (u16) (plcp[0] + (plcp[1] << 8))); ++ brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_PLCP_POS + 2, ++ (u16) (plcp[2] + (plcp[3] << 8))); ++ brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_DUR_POS, dur); ++ } ++} ++ ++/* Max buffering needed for beacon template/prb resp template is 142 bytes. ++ * ++ * PLCP header is 6 bytes. ++ * 802.11 A3 header is 24 bytes. ++ * Max beacon frame body template length is 112 bytes. ++ * Max probe resp frame body template length is 110 bytes. ++ * ++ * *len on input contains the max length of the packet available. ++ * ++ * The *len value is set to the number of bytes in buf used, and starts ++ * with the PLCP and included up to, but not including, the 4 byte FCS. ++ */ ++static void ++brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type, ++ u32 bcn_rspec, ++ struct brcms_bss_cfg *cfg, u16 *buf, int *len) ++{ ++ static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255}; ++ struct cck_phy_hdr *plcp; ++ struct ieee80211_mgmt *h; ++ int hdr_len, body_len; ++ ++ hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN; ++ ++ /* calc buffer size provided for frame body */ ++ body_len = *len - hdr_len; ++ /* return actual size */ ++ *len = hdr_len + body_len; ++ ++ /* format PHY and MAC headers */ ++ memset((char *)buf, 0, hdr_len); ++ ++ plcp = (struct cck_phy_hdr *) buf; ++ ++ /* ++ * PLCP for Probe Response frames are filled in from ++ * core's rate table ++ */ ++ if (type == IEEE80211_STYPE_BEACON) ++ /* fill in PLCP */ ++ brcms_c_compute_plcp(wlc, bcn_rspec, ++ (DOT11_MAC_HDR_LEN + body_len + FCS_LEN), ++ (u8 *) plcp); ++ ++ /* "Regular" and 16 MBSS but not for 4 MBSS */ ++ /* Update the phytxctl for the beacon based on the rspec */ ++ brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec); ++ ++ h = (struct ieee80211_mgmt *)&plcp[1]; ++ ++ /* fill in 802.11 header */ ++ h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type); ++ ++ /* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */ ++ /* A1 filled in by MAC for prb resp, broadcast for bcn */ ++ if (type == IEEE80211_STYPE_BEACON) ++ memcpy(&h->da, ðer_bcast, ETH_ALEN); ++ memcpy(&h->sa, &cfg->cur_etheraddr, ETH_ALEN); ++ memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN); ++ ++ /* SEQ filled in by MAC */ ++} ++ ++int brcms_c_get_header_len(void) ++{ ++ return TXOFF; ++} ++ ++/* ++ * Update all beacons for the system. ++ */ ++void brcms_c_update_beacon(struct brcms_c_info *wlc) ++{ ++ struct brcms_bss_cfg *bsscfg = wlc->bsscfg; ++ ++ if (bsscfg->up && !bsscfg->BSS) ++ /* Clear the soft intmask */ ++ wlc->defmacintmask &= ~MI_BCNTPL; ++} ++ ++/* Write ssid into shared memory */ ++static void ++brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg) ++{ ++ u8 *ssidptr = cfg->SSID; ++ u16 base = M_SSID; ++ u8 ssidbuf[IEEE80211_MAX_SSID_LEN]; ++ ++ /* padding the ssid with zero and copy it into shm */ ++ memset(ssidbuf, 0, IEEE80211_MAX_SSID_LEN); ++ memcpy(ssidbuf, ssidptr, cfg->SSID_len); ++ ++ brcms_c_copyto_shm(wlc, base, ssidbuf, IEEE80211_MAX_SSID_LEN); ++ brcms_b_write_shm(wlc->hw, M_SSIDLEN, (u16) cfg->SSID_len); ++} ++ ++static void ++brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc, ++ struct brcms_bss_cfg *cfg, ++ bool suspend) ++{ ++ u16 prb_resp[BCN_TMPL_LEN / 2]; ++ int len = BCN_TMPL_LEN; ++ ++ /* ++ * write the probe response to hardware, or save in ++ * the config structure ++ */ ++ ++ /* create the probe response template */ ++ brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0, ++ cfg, prb_resp, &len); ++ ++ if (suspend) ++ brcms_c_suspend_mac_and_wait(wlc); ++ ++ /* write the probe response into the template region */ ++ brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE, ++ (len + 3) & ~3, prb_resp); ++ ++ /* write the length of the probe response frame (+PLCP/-FCS) */ ++ brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len); ++ ++ /* write the SSID and SSID length */ ++ brcms_c_shm_ssid_upd(wlc, cfg); ++ ++ /* ++ * Write PLCP headers and durations for probe response frames ++ * at all rates. Use the actual frame length covered by the ++ * PLCP header for the call to brcms_c_mod_prb_rsp_rate_table() ++ * by subtracting the PLCP len and adding the FCS. ++ */ ++ len += (-D11_PHY_HDR_LEN + FCS_LEN); ++ brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len); ++ ++ if (suspend) ++ brcms_c_enable_mac(wlc); ++} ++ ++void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend) ++{ ++ struct brcms_bss_cfg *bsscfg = wlc->bsscfg; ++ ++ /* update AP or IBSS probe responses */ ++ if (bsscfg->up && !bsscfg->BSS) ++ brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend); ++} ++ ++/* prepares pdu for transmission. returns BCM error codes */ ++int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu, uint *fifop) ++{ ++ uint fifo; ++ struct d11txh *txh; ++ struct ieee80211_hdr *h; ++ struct scb *scb; ++ ++ txh = (struct d11txh *) (pdu->data); ++ h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN); ++ ++ /* get the pkt queue info. This was put at brcms_c_sendctl or ++ * brcms_c_send for PDU */ ++ fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK; ++ ++ scb = NULL; ++ ++ *fifop = fifo; ++ ++ /* return if insufficient dma resources */ ++ if (*wlc->core->txavail[fifo] < MAX_DMA_SEGS) { ++ /* Mark precedences related to this FIFO, unsendable */ ++ /* A fifo is full. Clear precedences related to that FIFO */ ++ wlc->tx_prec_map &= ~(wlc->fifo2prec_map[fifo]); ++ return -EBUSY; ++ } ++ return 0; ++} ++ ++int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, ++ uint *blocks) ++{ ++ if (fifo >= NFIFO) ++ return -EINVAL; ++ ++ *blocks = wlc_hw->xmtfifo_sz[fifo]; ++ ++ return 0; ++} ++ ++void ++brcms_c_set_addrmatch(struct brcms_c_info *wlc, int match_reg_offset, ++ const u8 *addr) ++{ ++ brcms_b_set_addrmatch(wlc->hw, match_reg_offset, addr); ++ if (match_reg_offset == RCM_BSSID_OFFSET) ++ memcpy(wlc->bsscfg->BSSID, addr, ETH_ALEN); ++} ++ ++/* ++ * Flag 'scan in progress' to withhold dynamic phy calibration ++ */ ++void brcms_c_scan_start(struct brcms_c_info *wlc) ++{ ++ wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, true); ++} ++ ++void brcms_c_scan_stop(struct brcms_c_info *wlc) ++{ ++ wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, false); ++} ++ ++void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state) ++{ ++ wlc->pub->associated = state; ++ wlc->bsscfg->associated = state; ++} ++ ++/* ++ * When a remote STA/AP is removed by Mac80211, or when it can no longer accept ++ * AMPDU traffic, packets pending in hardware have to be invalidated so that ++ * when later on hardware releases them, they can be handled appropriately. ++ */ ++void brcms_c_inval_dma_pkts(struct brcms_hardware *hw, ++ struct ieee80211_sta *sta, ++ void (*dma_callback_fn)) ++{ ++ struct dma_pub *dmah; ++ int i; ++ for (i = 0; i < NFIFO; i++) { ++ dmah = hw->di[i]; ++ if (dmah != NULL) ++ dma_walk_packets(dmah, dma_callback_fn, sta); ++ } ++} ++ ++int brcms_c_get_curband(struct brcms_c_info *wlc) ++{ ++ return wlc->band->bandunit; ++} ++ ++void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop) ++{ ++ /* flush packet queue when requested */ ++ if (drop) ++ brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL); ++ ++ /* wait for queue and DMA fifos to run dry */ ++ while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0) ++ brcms_msleep(wlc->wl, 1); ++} ++ ++void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval) ++{ ++ wlc->bcn_li_bcn = interval; ++ if (wlc->pub->up) ++ brcms_c_bcn_li_upd(wlc); ++} ++ ++int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr) ++{ ++ uint qdbm; ++ ++ /* Remove override bit and clip to max qdbm value */ ++ qdbm = min_t(uint, txpwr * BRCMS_TXPWR_DB_FACTOR, 0xff); ++ return wlc_phy_txpower_set(wlc->band->pi, qdbm, false); ++} ++ ++int brcms_c_get_tx_power(struct brcms_c_info *wlc) ++{ ++ uint qdbm; ++ bool override; ++ ++ wlc_phy_txpower_get(wlc->band->pi, &qdbm, &override); ++ ++ /* Return qdbm units */ ++ return (int)(qdbm / BRCMS_TXPWR_DB_FACTOR); ++} ++ ++void brcms_c_set_radio_mpc(struct brcms_c_info *wlc, bool mpc) ++{ ++ wlc->mpc = mpc; ++ brcms_c_radio_mpc_upd(wlc); ++} ++ ++/* Process received frames */ ++/* ++ * Return true if more frames need to be processed. false otherwise. ++ * Param 'bound' indicates max. # frames to process before break out. ++ */ ++static void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p) ++{ ++ struct d11rxhdr *rxh; ++ struct ieee80211_hdr *h; ++ uint len; ++ bool is_amsdu; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ ++ /* frame starts with rxhdr */ ++ rxh = (struct d11rxhdr *) (p->data); ++ ++ /* strip off rxhdr */ ++ skb_pull(p, BRCMS_HWRXOFF); ++ ++ /* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */ ++ if (rxh->RxStatus1 & RXS_PBPRES) { ++ if (p->len < 2) { ++ wiphy_err(wlc->wiphy, "wl%d: recv: rcvd runt of " ++ "len %d\n", wlc->pub->unit, p->len); ++ goto toss; ++ } ++ skb_pull(p, 2); ++ } ++ ++ h = (struct ieee80211_hdr *)(p->data + D11_PHY_HDR_LEN); ++ len = p->len; ++ ++ if (rxh->RxStatus1 & RXS_FCSERR) { ++ if (wlc->pub->mac80211_state & MAC80211_PROMISC_BCNS) { ++ wiphy_err(wlc->wiphy, "FCSERR while scanning******* -" ++ " tossing\n"); ++ goto toss; ++ } else { ++ wiphy_err(wlc->wiphy, "RCSERR!!!\n"); ++ goto toss; ++ } ++ } ++ ++ /* check received pkt has at least frame control field */ ++ if (len < D11_PHY_HDR_LEN + sizeof(h->frame_control)) ++ goto toss; ++ ++ /* not supporting A-MSDU */ ++ is_amsdu = rxh->RxStatus2 & RXS_AMSDU_MASK; ++ if (is_amsdu) ++ goto toss; ++ ++ brcms_c_recvctl(wlc, rxh, p); ++ return; ++ ++ toss: ++ brcmu_pkt_buf_free_skb(p); ++} ++ ++/* Process received frames */ ++/* ++ * Return true if more frames need to be processed. false otherwise. ++ * Param 'bound' indicates max. # frames to process before break out. ++ */ ++static bool ++brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound) ++{ ++ struct sk_buff *p; ++ struct sk_buff *head = NULL; ++ struct sk_buff *tail = NULL; ++ uint n = 0; ++ uint bound_limit = bound ? RXBND : -1; ++ ++ BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); ++ /* gather received frames */ ++ while ((p = dma_rx(wlc_hw->di[fifo]))) { ++ ++ if (!tail) ++ head = tail = p; ++ else { ++ tail->prev = p; ++ tail = p; ++ } ++ ++ /* !give others some time to run! */ ++ if (++n >= bound_limit) ++ break; ++ } ++ ++ /* post more rbufs */ ++ dma_rxfill(wlc_hw->di[fifo]); ++ ++ /* process each frame */ ++ while ((p = head) != NULL) { ++ struct d11rxhdr_le *rxh_le; ++ struct d11rxhdr *rxh; ++ head = head->prev; ++ p->prev = NULL; ++ ++ rxh_le = (struct d11rxhdr_le *)p->data; ++ rxh = (struct d11rxhdr *)p->data; ++ ++ /* fixup rx header endianness */ ++ rxh->RxFrameSize = le16_to_cpu(rxh_le->RxFrameSize); ++ rxh->PhyRxStatus_0 = le16_to_cpu(rxh_le->PhyRxStatus_0); ++ rxh->PhyRxStatus_1 = le16_to_cpu(rxh_le->PhyRxStatus_1); ++ rxh->PhyRxStatus_2 = le16_to_cpu(rxh_le->PhyRxStatus_2); ++ rxh->PhyRxStatus_3 = le16_to_cpu(rxh_le->PhyRxStatus_3); ++ rxh->PhyRxStatus_4 = le16_to_cpu(rxh_le->PhyRxStatus_4); ++ rxh->PhyRxStatus_5 = le16_to_cpu(rxh_le->PhyRxStatus_5); ++ rxh->RxStatus1 = le16_to_cpu(rxh_le->RxStatus1); ++ rxh->RxStatus2 = le16_to_cpu(rxh_le->RxStatus2); ++ rxh->RxTSFTime = le16_to_cpu(rxh_le->RxTSFTime); ++ rxh->RxChan = le16_to_cpu(rxh_le->RxChan); ++ ++ brcms_c_recv(wlc_hw->wlc, p); ++ } ++ ++ return n >= bound_limit; ++} ++ ++/* second-level interrupt processing ++ * Return true if another dpc needs to be re-scheduled. false otherwise. ++ * Param 'bounded' indicates if applicable loops should be bounded. ++ */ ++bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) ++{ ++ u32 macintstatus; ++ struct brcms_hardware *wlc_hw = wlc->hw; ++ struct d11regs __iomem *regs = wlc_hw->regs; ++ struct wiphy *wiphy = wlc->wiphy; ++ ++ if (brcms_deviceremoved(wlc)) { ++ wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit, ++ __func__); ++ brcms_down(wlc->wl); ++ return false; ++ } ++ ++ /* grab and clear the saved software intstatus bits */ ++ macintstatus = wlc->macintstatus; ++ wlc->macintstatus = 0; ++ ++ BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n", ++ wlc_hw->unit, macintstatus); ++ ++ WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */ ++ ++ /* tx status */ ++ if (macintstatus & MI_TFS) { ++ bool fatal; ++ if (brcms_b_txstatus(wlc->hw, bounded, &fatal)) ++ wlc->macintstatus |= MI_TFS; ++ if (fatal) { ++ wiphy_err(wiphy, "MI_TFS: fatal\n"); ++ goto fatal; ++ } ++ } ++ ++ if (macintstatus & (MI_TBTT | MI_DTIM_TBTT)) ++ brcms_c_tbtt(wlc); ++ ++ /* ATIM window end */ ++ if (macintstatus & MI_ATIMWINEND) { ++ BCMMSG(wlc->wiphy, "end of ATIM window\n"); ++ OR_REG(®s->maccommand, wlc->qvalid); ++ wlc->qvalid = 0; ++ } ++ ++ /* ++ * received data or control frame, MI_DMAINT is ++ * indication of RX_FIFO interrupt ++ */ ++ if (macintstatus & MI_DMAINT) ++ if (brcms_b_recv(wlc_hw, RX_FIFO, bounded)) ++ wlc->macintstatus |= MI_DMAINT; ++ ++ /* noise sample collected */ ++ if (macintstatus & MI_BG_NOISE) ++ wlc_phy_noise_sample_intr(wlc_hw->band->pi); ++ ++ if (macintstatus & MI_GP0) { ++ wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d " ++ "(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now); ++ ++ printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n", ++ __func__, wlc_hw->sih->chip, ++ wlc_hw->sih->chiprev); ++ /* big hammer */ ++ brcms_init(wlc->wl); ++ } ++ ++ /* gptimer timeout */ ++ if (macintstatus & MI_TO) ++ W_REG(®s->gptimer, 0); ++ ++ if (macintstatus & MI_RFDISABLE) { ++ BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the" ++ " RF Disable Input\n", wlc_hw->unit); ++ brcms_rfkill_set_hw_state(wlc->wl); ++ } ++ ++ /* send any enq'd tx packets. Just makes sure to jump start tx */ ++ if (!pktq_empty(&wlc->pkt_queue->q)) ++ brcms_c_send_q(wlc); ++ ++ /* it isn't done and needs to be resched if macintstatus is non-zero */ ++ return wlc->macintstatus != 0; ++ ++ fatal: ++ brcms_init(wlc->wl); ++ return wlc->macintstatus != 0; ++} ++ ++void brcms_c_init(struct brcms_c_info *wlc) ++{ ++ struct d11regs __iomem *regs; ++ u16 chanspec; ++ bool mute = false; ++ ++ BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); ++ ++ regs = wlc->regs; ++ ++ /* ++ * This will happen if a big-hammer was executed. In ++ * that case, we want to go back to the channel that ++ * we were on and not new channel ++ */ ++ if (wlc->pub->associated) ++ chanspec = wlc->home_chanspec; ++ else ++ chanspec = brcms_c_init_chanspec(wlc); ++ ++ brcms_b_init(wlc->hw, chanspec, mute); ++ ++ /* update beacon listen interval */ ++ brcms_c_bcn_li_upd(wlc); ++ ++ /* write ethernet address to core */ ++ brcms_c_set_mac(wlc->bsscfg); ++ brcms_c_set_bssid(wlc->bsscfg); ++ ++ /* Update tsf_cfprep if associated and up */ ++ if (wlc->pub->associated && wlc->bsscfg->up) { ++ u32 bi; ++ ++ /* get beacon period and convert to uS */ ++ bi = wlc->bsscfg->current_bss->beacon_period << 10; ++ /* ++ * update since init path would reset ++ * to default value ++ */ ++ W_REG(®s->tsf_cfprep, ++ (bi << CFPREP_CBI_SHIFT)); ++ ++ /* Update maccontrol PM related bits */ ++ brcms_c_set_ps_ctrl(wlc); ++ } ++ ++ brcms_c_bandinit_ordered(wlc, chanspec); ++ ++ /* init probe response timeout */ ++ brcms_b_write_shm(wlc->hw, M_PRS_MAXTIME, wlc->prb_resp_timeout); ++ ++ /* init max burst txop (framebursting) */ ++ brcms_b_write_shm(wlc->hw, M_MBURST_TXOP, ++ (wlc-> ++ _rifs ? (EDCF_AC_VO_TXOP_AP << 5) : MAXFRAMEBURST_TXOP)); ++ ++ /* initialize maximum allowed duty cycle */ ++ brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_ofdm, true, true); ++ brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_cck, false, true); ++ ++ /* ++ * Update some shared memory locations related to ++ * max AMPDU size allowed to received ++ */ ++ brcms_c_ampdu_shm_upd(wlc->ampdu); ++ ++ /* band-specific inits */ ++ brcms_c_bsinit(wlc); ++ ++ /* Enable EDCF mode (while the MAC is suspended) */ ++ OR_REG(®s->ifs_ctl, IFS_USEEDCF); ++ brcms_c_edcf_setparams(wlc, false); ++ ++ /* Init precedence maps for empty FIFOs */ ++ brcms_c_tx_prec_map_init(wlc); ++ ++ /* read the ucode version if we have not yet done so */ ++ if (wlc->ucode_rev == 0) { ++ wlc->ucode_rev = ++ brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR) << NBITS(u16); ++ wlc->ucode_rev |= brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR); ++ } ++ ++ /* ..now really unleash hell (allow the MAC out of suspend) */ ++ brcms_c_enable_mac(wlc); ++ ++ /* clear tx flow control */ ++ brcms_c_txflowcontrol_reset(wlc); ++ ++ /* enable the RF Disable Delay timer */ ++ W_REG(&wlc->regs->rfdisabledly, RFDISABLE_DEFAULT); ++ ++ /* initialize mpc delay */ ++ wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT; ++ ++ /* ++ * Initialize WME parameters; if they haven't been set by some other ++ * mechanism (IOVar, etc) then read them from the hardware. ++ */ ++ if (GFIELD(wlc->wme_retries[0], EDCF_SHORT) == 0) { ++ /* Uninitialized; read from HW */ ++ int ac; ++ ++ for (ac = 0; ac < AC_COUNT; ac++) ++ wlc->wme_retries[ac] = ++ brcms_b_read_shm(wlc->hw, M_AC_TXLMT_ADDR(ac)); ++ } ++} ++ ++/* ++ * The common driver entry routine. Error codes should be unique ++ */ ++struct brcms_c_info * ++brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit, ++ bool piomode, void __iomem *regsva, struct pci_dev *btparam, ++ uint *perr) ++{ ++ struct brcms_c_info *wlc; ++ uint err = 0; ++ uint i, j; ++ struct brcms_pub *pub; ++ ++ /* allocate struct brcms_c_info state and its substructures */ ++ wlc = (struct brcms_c_info *) brcms_c_attach_malloc(unit, &err, device); ++ if (wlc == NULL) ++ goto fail; ++ wlc->wiphy = wl->wiphy; ++ pub = wlc->pub; ++ ++#if defined(BCMDBG) ++ wlc_info_dbg = wlc; ++#endif ++ ++ wlc->band = wlc->bandstate[0]; ++ wlc->core = wlc->corestate; ++ wlc->wl = wl; ++ pub->unit = unit; ++ pub->_piomode = piomode; ++ wlc->bandinit_pending = false; ++ ++ /* populate struct brcms_c_info with default values */ ++ brcms_c_info_init(wlc, unit); ++ ++ /* update sta/ap related parameters */ ++ brcms_c_ap_upd(wlc); ++ ++ /* ++ * low level attach steps(all hw accesses go ++ * inside, no more in rest of the attach) ++ */ ++ err = brcms_b_attach(wlc, vendor, device, unit, piomode, regsva, ++ btparam); ++ if (err) ++ goto fail; ++ ++ brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR, OFF); ++ ++ pub->phy_11ncapable = BRCMS_PHY_11N_CAP(wlc->band); ++ ++ /* disable allowed duty cycle */ ++ wlc->tx_duty_cycle_ofdm = 0; ++ wlc->tx_duty_cycle_cck = 0; ++ ++ brcms_c_stf_phy_chain_calc(wlc); ++ ++ /* txchain 1: txant 0, txchain 2: txant 1 */ ++ if (BRCMS_ISNPHY(wlc->band) && (wlc->stf->txstreams == 1)) ++ wlc->stf->txant = wlc->stf->hw_txchain - 1; ++ ++ /* push to BMAC driver */ ++ wlc_phy_stf_chain_init(wlc->band->pi, wlc->stf->hw_txchain, ++ wlc->stf->hw_rxchain); ++ ++ /* pull up some info resulting from the low attach */ ++ for (i = 0; i < NFIFO; i++) ++ wlc->core->txavail[i] = wlc->hw->txavail[i]; ++ ++ memcpy(&wlc->perm_etheraddr, &wlc->hw->etheraddr, ETH_ALEN); ++ memcpy(&pub->cur_etheraddr, &wlc->hw->etheraddr, ETH_ALEN); ++ ++ for (j = 0; j < wlc->pub->_nbands; j++) { ++ wlc->band = wlc->bandstate[j]; ++ ++ if (!brcms_c_attach_stf_ant_init(wlc)) { ++ err = 24; ++ goto fail; ++ } ++ ++ /* default contention windows size limits */ ++ wlc->band->CWmin = APHY_CWMIN; ++ wlc->band->CWmax = PHY_CWMAX; ++ ++ /* init gmode value */ ++ if (wlc->band->bandtype == BRCM_BAND_2G) { ++ wlc->band->gmode = GMODE_AUTO; ++ brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, ++ wlc->band->gmode); ++ } ++ ++ /* init _n_enab supported mode */ ++ if (BRCMS_PHY_11N_CAP(wlc->band)) { ++ pub->_n_enab = SUPPORT_11N; ++ brcms_c_protection_upd(wlc, BRCMS_PROT_N_USER, ++ ((pub->_n_enab == ++ SUPPORT_11N) ? WL_11N_2x2 : ++ WL_11N_3x3)); ++ } ++ ++ /* init per-band default rateset, depend on band->gmode */ ++ brcms_default_rateset(wlc, &wlc->band->defrateset); ++ ++ /* fill in hw_rateset */ ++ brcms_c_rateset_filter(&wlc->band->defrateset, ++ &wlc->band->hw_rateset, false, ++ BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK, ++ (bool) (wlc->pub->_n_enab & SUPPORT_11N)); ++ } ++ ++ /* ++ * update antenna config due to ++ * wlc->stf->txant/txchain/ant_rx_ovr change ++ */ ++ brcms_c_stf_phy_txant_upd(wlc); ++ ++ /* attach each modules */ ++ err = brcms_c_attach_module(wlc); ++ if (err != 0) ++ goto fail; ++ ++ if (!brcms_c_timers_init(wlc, unit)) { ++ wiphy_err(wl->wiphy, "wl%d: %s: init_timer failed\n", unit, ++ __func__); ++ err = 32; ++ goto fail; ++ } ++ ++ /* depend on rateset, gmode */ ++ wlc->cmi = brcms_c_channel_mgr_attach(wlc); ++ if (!wlc->cmi) { ++ wiphy_err(wl->wiphy, "wl%d: %s: channel_mgr_attach failed" ++ "\n", unit, __func__); ++ err = 33; ++ goto fail; ++ } ++ ++ /* init default when all parameters are ready, i.e. ->rateset */ ++ brcms_c_bss_default_init(wlc); ++ ++ /* ++ * Complete the wlc default state initializations.. ++ */ ++ ++ /* allocate our initial queue */ ++ wlc->pkt_queue = brcms_c_txq_alloc(wlc); ++ if (wlc->pkt_queue == NULL) { ++ wiphy_err(wl->wiphy, "wl%d: %s: failed to malloc tx queue\n", ++ unit, __func__); ++ err = 100; ++ goto fail; ++ } ++ ++ wlc->bsscfg->wlc = wlc; ++ ++ wlc->mimoft = FT_HT; ++ wlc->mimo_40txbw = AUTO; ++ wlc->ofdm_40txbw = AUTO; ++ wlc->cck_40txbw = AUTO; ++ brcms_c_update_mimo_band_bwcap(wlc, BRCMS_N_BW_20IN2G_40IN5G); ++ ++ /* Set default values of SGI */ ++ if (BRCMS_SGI_CAP_PHY(wlc)) { ++ brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 | ++ BRCMS_N_SGI_40)); ++ } else if (BRCMS_ISSSLPNPHY(wlc->band)) { ++ brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 | ++ BRCMS_N_SGI_40)); ++ } else { ++ brcms_c_ht_update_sgi_rx(wlc, 0); ++ } ++ ++ /* initialize radio_mpc_disable according to wlc->mpc */ ++ brcms_c_radio_mpc_upd(wlc); ++ brcms_b_antsel_set(wlc->hw, wlc->asi->antsel_avail); ++ ++ if (perr) ++ *perr = 0; ++ ++ return wlc; ++ ++ fail: ++ wiphy_err(wl->wiphy, "wl%d: %s: failed with err %d\n", ++ unit, __func__, err); ++ if (wlc) ++ brcms_c_detach(wlc); ++ ++ if (perr) ++ *perr = err; ++ return NULL; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.h.orig 2011-11-09 13:46:58.251800557 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/main.h 2011-11-09 13:47:17.004566116 -0500 +@@ -0,0 +1,735 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_MAIN_H_ ++#define _BRCM_MAIN_H_ ++ ++#include ++ ++#include ++#include "types.h" ++#include "d11.h" ++#include "scb.h" ++ ++#define INVCHANNEL 255 /* invalid channel */ ++ ++/* max # brcms_c_module_register() calls */ ++#define BRCMS_MAXMODULES 22 ++ ++#define SEQNUM_SHIFT 4 ++#define SEQNUM_MAX 0x1000 ++ ++#define NTXRATE 64 /* # tx MPDUs rate is reported for */ ++ ++/* Maximum wait time for a MAC suspend */ ++/* uS: 83mS is max packet time (64KB ampdu @ 6Mbps) */ ++#define BRCMS_MAX_MAC_SUSPEND 83000 ++ ++/* responses for probe requests older that this are tossed, zero to disable */ ++#define BRCMS_PRB_RESP_TIMEOUT 0 /* Disable probe response timeout */ ++ ++/* transmit buffer max headroom for protocol headers */ ++#define TXOFF (D11_TXH_LEN + D11_PHY_HDR_LEN) ++ ++#define AC_COUNT 4 ++ ++/* Macros for doing definition and get/set of bitfields ++ * Usage example, e.g. a three-bit field (bits 4-6): ++ * #define _M BITFIELD_MASK(3) ++ * #define _S 4 ++ * ... ++ * regval = R_REG(osh, ®s->regfoo); ++ * field = GFIELD(regval, ); ++ * regval = SFIELD(regval, , 1); ++ * W_REG(osh, ®s->regfoo, regval); ++ */ ++#define BITFIELD_MASK(width) \ ++ (((unsigned)1 << (width)) - 1) ++#define GFIELD(val, field) \ ++ (((val) >> field ## _S) & field ## _M) ++#define SFIELD(val, field, bits) \ ++ (((val) & (~(field ## _M << field ## _S))) | \ ++ ((unsigned)(bits) << field ## _S)) ++ ++#define SW_TIMER_MAC_STAT_UPD 30 /* periodic MAC stats update */ ++ ++/* max # supported core revisions (0 .. MAXCOREREV - 1) */ ++#define MAXCOREREV 28 ++ ++/* Double check that unsupported cores are not enabled */ ++#if CONF_MSK(D11CONF, 0x4f) || CONF_GE(D11CONF, MAXCOREREV) ++#error "Configuration for D11CONF includes unsupported versions." ++#endif /* Bad versions */ ++ ++/* values for shortslot_override */ ++#define BRCMS_SHORTSLOT_AUTO -1 /* Driver will manage Shortslot setting */ ++#define BRCMS_SHORTSLOT_OFF 0 /* Turn off short slot */ ++#define BRCMS_SHORTSLOT_ON 1 /* Turn on short slot */ ++ ++/* value for short/long and mixmode/greenfield preamble */ ++#define BRCMS_LONG_PREAMBLE (0) ++#define BRCMS_SHORT_PREAMBLE (1 << 0) ++#define BRCMS_GF_PREAMBLE (1 << 1) ++#define BRCMS_MM_PREAMBLE (1 << 2) ++#define BRCMS_IS_MIMO_PREAMBLE(_pre) (((_pre) == BRCMS_GF_PREAMBLE) || \ ++ ((_pre) == BRCMS_MM_PREAMBLE)) ++ ++/* TxFrameID */ ++/* seq and frag bits: SEQNUM_SHIFT, FRAGNUM_MASK (802.11.h) */ ++/* rate epoch bits: TXFID_RATE_SHIFT, TXFID_RATE_MASK ((wlc_rate.c) */ ++#define TXFID_QUEUE_MASK 0x0007 /* Bits 0-2 */ ++#define TXFID_SEQ_MASK 0x7FE0 /* Bits 5-15 */ ++#define TXFID_SEQ_SHIFT 5 /* Number of bit shifts */ ++#define TXFID_RATE_PROBE_MASK 0x8000 /* Bit 15 for rate probe */ ++#define TXFID_RATE_MASK 0x0018 /* Mask for bits 3 and 4 */ ++#define TXFID_RATE_SHIFT 3 /* Shift 3 bits for rate mask */ ++ ++/* promote boardrev */ ++#define BOARDREV_PROMOTABLE 0xFF /* from */ ++#define BOARDREV_PROMOTED 1 /* to */ ++ ++#define DATA_BLOCK_TX_SUPR (1 << 4) ++ ++/* 802.1D Priority to TX FIFO number for wme */ ++extern const u8 prio2fifo[]; ++ ++/* Ucode MCTL_WAKE override bits */ ++#define BRCMS_WAKE_OVERRIDE_CLKCTL 0x01 ++#define BRCMS_WAKE_OVERRIDE_PHYREG 0x02 ++#define BRCMS_WAKE_OVERRIDE_MACSUSPEND 0x04 ++#define BRCMS_WAKE_OVERRIDE_TXFIFO 0x08 ++#define BRCMS_WAKE_OVERRIDE_FORCEFAST 0x10 ++ ++/* stuff pulled in from wlc.c */ ++ ++/* Interrupt bit error summary. Don't include I_RU: we refill DMA at other ++ * times; and if we run out, constant I_RU interrupts may cause lockup. We ++ * will still get error counts from rx0ovfl. ++ */ ++#define I_ERRORS (I_PC | I_PD | I_DE | I_RO | I_XU) ++/* default software intmasks */ ++#define DEF_RXINTMASK (I_RI) /* enable rx int on rxfifo only */ ++#define DEF_MACINTMASK (MI_TXSTOP | MI_TBTT | MI_ATIMWINEND | MI_PMQ | \ ++ MI_PHYTXERR | MI_DMAINT | MI_TFS | MI_BG_NOISE | \ ++ MI_CCA | MI_TO | MI_GP0 | MI_RFDISABLE | MI_PWRUP) ++ ++#define MAXTXPKTS 6 /* max # pkts pending */ ++ ++/* frameburst */ ++#define MAXTXFRAMEBURST 8 /* vanilla xpress mode: max frames/burst */ ++#define MAXFRAMEBURST_TXOP 10000 /* Frameburst TXOP in usec */ ++ ++#define NFIFO 6 /* # tx/rx fifopairs */ ++ ++/* PLL requests */ ++ ++/* pll is shared on old chips */ ++#define BRCMS_PLLREQ_SHARED 0x1 ++/* hold pll for radio monitor register checking */ ++#define BRCMS_PLLREQ_RADIO_MON 0x2 ++/* hold/release pll for some short operation */ ++#define BRCMS_PLLREQ_FLIP 0x4 ++ ++#define CHANNEL_BANDUNIT(wlc, ch) \ ++ (((ch) <= CH_MAX_2G_CHANNEL) ? BAND_2G_INDEX : BAND_5G_INDEX) ++ ++#define OTHERBANDUNIT(wlc) \ ++ ((uint)((wlc)->band->bandunit ? BAND_2G_INDEX : BAND_5G_INDEX)) ++ ++/* ++ * 802.11 protection information ++ * ++ * _g: use g spec protection, driver internal. ++ * g_override: override for use of g spec protection. ++ * gmode_user: user config gmode, operating band->gmode is different. ++ * overlap: Overlap BSS/IBSS protection for both 11g and 11n. ++ * nmode_user: user config nmode, operating pub->nmode is different. ++ * n_cfg: use OFDM protection on MIMO frames. ++ * n_cfg_override: override for use of N protection. ++ * nongf: non-GF present protection. ++ * nongf_override: override for use of GF protection. ++ * n_pam_override: override for preamble: MM or GF. ++ * n_obss: indicated OBSS Non-HT STA present. ++*/ ++struct brcms_protection { ++ bool _g; ++ s8 g_override; ++ u8 gmode_user; ++ s8 overlap; ++ s8 nmode_user; ++ s8 n_cfg; ++ s8 n_cfg_override; ++ bool nongf; ++ s8 nongf_override; ++ s8 n_pam_override; ++ bool n_obss; ++}; ++ ++/* ++ * anything affecting the single/dual streams/antenna operation ++ * ++ * hw_txchain: HW txchain bitmap cfg. ++ * txchain: txchain bitmap being used. ++ * txstreams: number of txchains being used. ++ * hw_rxchain: HW rxchain bitmap cfg. ++ * rxchain: rxchain bitmap being used. ++ * rxstreams: number of rxchains being used. ++ * ant_rx_ovr: rx antenna override. ++ * txant: userTx antenna setting. ++ * phytxant: phyTx antenna setting in txheader. ++ * ss_opmode: singlestream Operational mode, 0:siso; 1:cdd. ++ * ss_algosel_auto: if true, use wlc->stf->ss_algo_channel; ++ * else use wlc->band->stf->ss_mode_band. ++ * ss_algo_channel: ss based on per-channel algo: 0: SISO, 1: CDD 2: STBC. ++ * rxchain_restore_delay: delay time to restore default rxchain. ++ * ldpc: AUTO/ON/OFF ldpc cap supported. ++ * txcore[MAX_STREAMS_SUPPORTED + 1]: bitmap of selected core for each Nsts. ++ * spatial_policy: ++ */ ++struct brcms_stf { ++ u8 hw_txchain; ++ u8 txchain; ++ u8 txstreams; ++ u8 hw_rxchain; ++ u8 rxchain; ++ u8 rxstreams; ++ u8 ant_rx_ovr; ++ s8 txant; ++ u16 phytxant; ++ u8 ss_opmode; ++ bool ss_algosel_auto; ++ u16 ss_algo_channel; ++ u8 rxchain_restore_delay; ++ s8 ldpc; ++ u8 txcore[MAX_STREAMS_SUPPORTED + 1]; ++ s8 spatial_policy; ++}; ++ ++#define BRCMS_STF_SS_STBC_TX(wlc, scb) \ ++ (((wlc)->stf->txstreams > 1) && (((wlc)->band->band_stf_stbc_tx == ON) \ ++ || (((scb)->flags & SCB_STBCCAP) && \ ++ (wlc)->band->band_stf_stbc_tx == AUTO && \ ++ isset(&((wlc)->stf->ss_algo_channel), PHY_TXC1_MODE_STBC)))) ++ ++#define BRCMS_STBC_CAP_PHY(wlc) (BRCMS_ISNPHY(wlc->band) && \ ++ NREV_GE(wlc->band->phyrev, 3)) ++ ++#define BRCMS_SGI_CAP_PHY(wlc) ((BRCMS_ISNPHY(wlc->band) && \ ++ NREV_GE(wlc->band->phyrev, 3)) || \ ++ BRCMS_ISLCNPHY(wlc->band)) ++ ++#define BRCMS_CHAN_PHYTYPE(x) (((x) & RXS_CHAN_PHYTYPE_MASK) \ ++ >> RXS_CHAN_PHYTYPE_SHIFT) ++#define BRCMS_CHAN_CHANNEL(x) (((x) & RXS_CHAN_ID_MASK) \ ++ >> RXS_CHAN_ID_SHIFT) ++ ++/* ++ * core state (mac) ++ */ ++struct brcms_core { ++ uint coreidx; /* # sb enumerated core */ ++ ++ /* fifo */ ++ uint *txavail[NFIFO]; /* # tx descriptors available */ ++ s16 txpktpend[NFIFO]; /* tx admission control */ ++ ++ struct macstat *macstat_snapshot; /* mac hw prev read values */ ++}; ++ ++/* ++ * band state (phy+ana+radio) ++ */ ++struct brcms_band { ++ int bandtype; /* BRCM_BAND_2G, BRCM_BAND_5G */ ++ uint bandunit; /* bandstate[] index */ ++ ++ u16 phytype; /* phytype */ ++ u16 phyrev; ++ u16 radioid; ++ u16 radiorev; ++ struct brcms_phy_pub *pi; /* pointer to phy specific information */ ++ bool abgphy_encore; ++ ++ u8 gmode; /* currently active gmode */ ++ ++ struct scb *hwrs_scb; /* permanent scb for hw rateset */ ++ ++ /* band-specific copy of default_bss.rateset */ ++ struct brcms_c_rateset defrateset; ++ ++ u8 band_stf_ss_mode; /* Configured STF type, 0:siso; 1:cdd */ ++ s8 band_stf_stbc_tx; /* STBC TX 0:off; 1:force on; -1:auto */ ++ /* rates supported by chip (phy-specific) */ ++ struct brcms_c_rateset hw_rateset; ++ u8 basic_rate[BRCM_MAXRATE + 1]; /* basic rates indexed by rate */ ++ bool mimo_cap_40; /* 40 MHz cap enabled on this band */ ++ s8 antgain; /* antenna gain from srom */ ++ ++ u16 CWmin; /* minimum size of contention window, in unit of aSlotTime */ ++ u16 CWmax; /* maximum size of contention window, in unit of aSlotTime */ ++ struct ieee80211_supported_band band; ++}; ++ ++/* module control blocks */ ++struct modulecb { ++ /* module name : NULL indicates empty array member */ ++ char name[32]; ++ /* handle passed when handler 'doiovar' is called */ ++ struct brcms_info *hdl; ++ ++ int (*down_fn)(void *handle); /* down handler. Note: the int returned ++ * by the down function is a count of the ++ * number of timers that could not be ++ * freed. ++ */ ++ ++}; ++ ++struct brcms_hw_band { ++ int bandtype; /* BRCM_BAND_2G, BRCM_BAND_5G */ ++ uint bandunit; /* bandstate[] index */ ++ u16 mhfs[MHFMAX]; /* MHF array shadow */ ++ u8 bandhw_stf_ss_mode; /* HW configured STF type, 0:siso; 1:cdd */ ++ u16 CWmin; ++ u16 CWmax; ++ u32 core_flags; ++ ++ u16 phytype; /* phytype */ ++ u16 phyrev; ++ u16 radioid; ++ u16 radiorev; ++ struct brcms_phy_pub *pi; /* pointer to phy specific information */ ++ bool abgphy_encore; ++}; ++ ++struct brcms_hardware { ++ bool _piomode; /* true if pio mode */ ++ struct brcms_c_info *wlc; ++ ++ /* fifo */ ++ struct dma_pub *di[NFIFO]; /* dma handles, per fifo */ ++ ++ uint unit; /* device instance number */ ++ ++ /* version info */ ++ u16 vendorid; /* PCI vendor id */ ++ u16 deviceid; /* PCI device id */ ++ uint corerev; /* core revision */ ++ u8 sromrev; /* version # of the srom */ ++ u16 boardrev; /* version # of particular board */ ++ u32 boardflags; /* Board specific flags from srom */ ++ u32 boardflags2; /* More board flags if sromrev >= 4 */ ++ u32 machwcap; /* MAC capabilities */ ++ u32 machwcap_backup; /* backup of machwcap */ ++ ++ struct si_pub *sih; /* SI handle (cookie for siutils calls) */ ++ struct d11regs __iomem *regs; /* pointer to device registers */ ++ struct phy_shim_info *physhim; /* phy shim layer handler */ ++ struct shared_phy *phy_sh; /* pointer to shared phy state */ ++ struct brcms_hw_band *band;/* pointer to active per-band state */ ++ /* band state per phy/radio */ ++ struct brcms_hw_band *bandstate[MAXBANDS]; ++ u16 bmac_phytxant; /* cache of high phytxant state */ ++ bool shortslot; /* currently using 11g ShortSlot timing */ ++ u16 SRL; /* 802.11 dot11ShortRetryLimit */ ++ u16 LRL; /* 802.11 dot11LongRetryLimit */ ++ u16 SFBL; /* Short Frame Rate Fallback Limit */ ++ u16 LFBL; /* Long Frame Rate Fallback Limit */ ++ ++ bool up; /* d11 hardware up and running */ ++ uint now; /* # elapsed seconds */ ++ uint _nbands; /* # bands supported */ ++ u16 chanspec; /* bmac chanspec shadow */ ++ ++ uint *txavail[NFIFO]; /* # tx descriptors available */ ++ const u16 *xmtfifo_sz; /* fifo size in 256B for each xmt fifo */ ++ ++ u32 pllreq; /* pll requests to keep PLL on */ ++ ++ u8 suspended_fifos; /* Which TX fifo to remain awake for */ ++ u32 maccontrol; /* Cached value of maccontrol */ ++ uint mac_suspend_depth; /* current depth of mac_suspend levels */ ++ u32 wake_override; /* bit flags to force MAC to WAKE mode */ ++ u32 mute_override; /* Prevent ucode from sending beacons */ ++ u8 etheraddr[ETH_ALEN]; /* currently configured ethernet address */ ++ bool noreset; /* true= do not reset hw, used by WLC_OUT */ ++ bool forcefastclk; /* true if h/w is forcing to use fast clk */ ++ bool clk; /* core is out of reset and has clock */ ++ bool sbclk; /* sb has clock */ ++ bool phyclk; /* phy is out of reset and has clock */ ++ ++ bool ucode_loaded; /* true after ucode downloaded */ ++ ++ ++ u8 hw_stf_ss_opmode; /* STF single stream operation mode */ ++ u8 antsel_type; /* Type of boardlevel mimo antenna switch-logic ++ * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board ++ */ ++ u32 antsel_avail; /* ++ * put struct antsel_info here if more info is ++ * needed ++ */ ++}; ++ ++/* TX Queue information ++ * ++ * Each flow of traffic out of the device has a TX Queue with independent ++ * flow control. Several interfaces may be associated with a single TX Queue ++ * if they belong to the same flow of traffic from the device. For multi-channel ++ * operation there are independent TX Queues for each channel. ++ */ ++struct brcms_txq_info { ++ struct brcms_txq_info *next; ++ struct pktq q; ++ uint stopped; /* tx flow control bits */ ++}; ++ ++/* ++ * Principal common driver data structure. ++ * ++ * pub: pointer to driver public state. ++ * wl: pointer to specific private state. ++ * regs: pointer to device registers. ++ * hw: HW related state. ++ * clkreq_override: setting for clkreq for PCIE : Auto, 0, 1. ++ * fastpwrup_dly: time in us needed to bring up d11 fast clock. ++ * macintstatus: bit channel between isr and dpc. ++ * macintmask: sw runtime master macintmask value. ++ * defmacintmask: default "on" macintmask value. ++ * clk: core is out of reset and has clock. ++ * core: pointer to active io core. ++ * band: pointer to active per-band state. ++ * corestate: per-core state (one per hw core). ++ * bandstate: per-band state (one per phy/radio). ++ * qvalid: DirFrmQValid and BcMcFrmQValid. ++ * ampdu: ampdu module handler. ++ * asi: antsel module handler. ++ * cmi: channel manager module handler. ++ * vendorid: PCI vendor id. ++ * deviceid: PCI device id. ++ * ucode_rev: microcode revision. ++ * machwcap: MAC capabilities, BMAC shadow. ++ * perm_etheraddr: original sprom local ethernet address. ++ * bandlocked: disable auto multi-band switching. ++ * bandinit_pending: track band init in auto band. ++ * radio_monitor: radio timer is running. ++ * going_down: down path intermediate variable. ++ * mpc: enable minimum power consumption. ++ * mpc_dlycnt: # of watchdog cnt before turn disable radio. ++ * mpc_offcnt: # of watchdog cnt that radio is disabled. ++ * mpc_delay_off: delay radio disable by # of watchdog cnt. ++ * prev_non_delay_mpc: prev state brcms_c_is_non_delay_mpc. ++ * wdtimer: timer for watchdog routine. ++ * radio_timer: timer for hw radio button monitor routine. ++ * monitor: monitor (MPDU sniffing) mode. ++ * bcnmisc_monitor: bcns promisc mode override for monitor. ++ * _rifs: enable per-packet rifs. ++ * bcn_li_bcn: beacon listen interval in # beacons. ++ * bcn_li_dtim: beacon listen interval in # dtims. ++ * WDarmed: watchdog timer is armed. ++ * WDlast: last time wlc_watchdog() was called. ++ * edcf_txop[AC_COUNT]: current txop for each ac. ++ * wme_retries: per-AC retry limits. ++ * tx_prec_map: Precedence map based on HW FIFO space. ++ * fifo2prec_map[NFIFO]: pointer to fifo2_prec map based on WME. ++ * bsscfg: set of BSS configurations, idx 0 is default and always valid. ++ * cfg: the primary bsscfg (can be AP or STA). ++ * tx_queues: common TX Queue list. ++ * modulecb: ++ * mimoft: SIGN or 11N. ++ * cck_40txbw: 11N, cck tx b/w override when in 40MHZ mode. ++ * ofdm_40txbw: 11N, ofdm tx b/w override when in 40MHZ mode. ++ * mimo_40txbw: 11N, mimo tx b/w override when in 40MHZ mode. ++ * default_bss: configured BSS parameters. ++ * mc_fid_counter: BC/MC FIFO frame ID counter. ++ * country_default: saved country for leaving 802.11d auto-country mode. ++ * autocountry_default: initial country for 802.11d auto-country mode. ++ * prb_resp_timeout: do not send prb resp if request older ++ * than this, 0 = disable. ++ * home_chanspec: shared home chanspec. ++ * chanspec: target operational channel. ++ * usr_fragthresh: user configured fragmentation threshold. ++ * fragthresh[NFIFO]: per-fifo fragmentation thresholds. ++ * RTSThresh: 802.11 dot11RTSThreshold. ++ * SRL: 802.11 dot11ShortRetryLimit. ++ * LRL: 802.11 dot11LongRetryLimit. ++ * SFBL: Short Frame Rate Fallback Limit. ++ * LFBL: Long Frame Rate Fallback Limit. ++ * shortslot: currently using 11g ShortSlot timing. ++ * shortslot_override: 11g ShortSlot override. ++ * include_legacy_erp: include Legacy ERP info elt ID 47 as well as g ID 42. ++ * PLCPHdr_override: 802.11b Preamble Type override. ++ * stf: ++ * bcn_rspec: save bcn ratespec purpose. ++ * tempsense_lasttime; ++ * tx_duty_cycle_ofdm: maximum allowed duty cycle for OFDM. ++ * tx_duty_cycle_cck: maximum allowed duty cycle for CCK. ++ * pkt_queue: txq for transmit packets. ++ * wiphy: ++ * pri_scb: primary Station Control Block ++ */ ++struct brcms_c_info { ++ struct brcms_pub *pub; ++ struct brcms_info *wl; ++ struct d11regs __iomem *regs; ++ struct brcms_hardware *hw; ++ ++ /* clock */ ++ u16 fastpwrup_dly; ++ ++ /* interrupt */ ++ u32 macintstatus; ++ u32 macintmask; ++ u32 defmacintmask; ++ ++ bool clk; ++ ++ /* multiband */ ++ struct brcms_core *core; ++ struct brcms_band *band; ++ struct brcms_core *corestate; ++ struct brcms_band *bandstate[MAXBANDS]; ++ ++ /* packet queue */ ++ uint qvalid; ++ ++ struct ampdu_info *ampdu; ++ struct antsel_info *asi; ++ struct brcms_cm_info *cmi; ++ ++ u16 vendorid; ++ u16 deviceid; ++ uint ucode_rev; ++ ++ u8 perm_etheraddr[ETH_ALEN]; ++ ++ bool bandlocked; ++ bool bandinit_pending; ++ ++ bool radio_monitor; ++ bool going_down; ++ ++ bool mpc; ++ u8 mpc_dlycnt; ++ u8 mpc_offcnt; ++ u8 mpc_delay_off; ++ u8 prev_non_delay_mpc; ++ ++ struct brcms_timer *wdtimer; ++ struct brcms_timer *radio_timer; ++ ++ /* promiscuous */ ++ bool monitor; ++ bool bcnmisc_monitor; ++ ++ /* driver feature */ ++ bool _rifs; ++ ++ /* AP-STA synchronization, power save */ ++ u8 bcn_li_bcn; ++ u8 bcn_li_dtim; ++ ++ bool WDarmed; ++ u32 WDlast; ++ ++ /* WME */ ++ u16 edcf_txop[AC_COUNT]; ++ ++ u16 wme_retries[AC_COUNT]; ++ u16 tx_prec_map; ++ u16 fifo2prec_map[NFIFO]; ++ ++ struct brcms_bss_cfg *bsscfg; ++ ++ /* tx queue */ ++ struct brcms_txq_info *tx_queues; ++ ++ struct modulecb *modulecb; ++ ++ u8 mimoft; ++ s8 cck_40txbw; ++ s8 ofdm_40txbw; ++ s8 mimo_40txbw; ++ ++ struct brcms_bss_info *default_bss; ++ ++ u16 mc_fid_counter; ++ ++ char country_default[BRCM_CNTRY_BUF_SZ]; ++ char autocountry_default[BRCM_CNTRY_BUF_SZ]; ++ u16 prb_resp_timeout; ++ ++ u16 home_chanspec; ++ ++ /* PHY parameters */ ++ u16 chanspec; ++ u16 usr_fragthresh; ++ u16 fragthresh[NFIFO]; ++ u16 RTSThresh; ++ u16 SRL; ++ u16 LRL; ++ u16 SFBL; ++ u16 LFBL; ++ ++ /* network config */ ++ bool shortslot; ++ s8 shortslot_override; ++ bool include_legacy_erp; ++ ++ struct brcms_protection *protection; ++ s8 PLCPHdr_override; ++ ++ struct brcms_stf *stf; ++ ++ u32 bcn_rspec; ++ ++ uint tempsense_lasttime; ++ ++ u16 tx_duty_cycle_ofdm; ++ u16 tx_duty_cycle_cck; ++ ++ struct brcms_txq_info *pkt_queue; ++ struct wiphy *wiphy; ++ struct scb pri_scb; ++}; ++ ++/* antsel module specific state */ ++struct antsel_info { ++ struct brcms_c_info *wlc; /* pointer to main wlc structure */ ++ struct brcms_pub *pub; /* pointer to public fn */ ++ u8 antsel_type; /* Type of boardlevel mimo antenna switch-logic ++ * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board ++ */ ++ u8 antsel_antswitch; /* board level antenna switch type */ ++ bool antsel_avail; /* Ant selection availability (SROM based) */ ++ struct brcms_antselcfg antcfg_11n; /* antenna configuration */ ++ struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */ ++}; ++ ++/* ++ * BSS configuration state ++ * ++ * wlc: wlc to which this bsscfg belongs to. ++ * up: is this configuration up operational ++ * enable: is this configuration enabled ++ * associated: is BSS in ASSOCIATED state ++ * BSS: infraustructure or adhoc ++ * SSID_len: the length of SSID ++ * SSID: SSID string ++ * ++ * ++ * BSSID: BSSID (associated) ++ * cur_etheraddr: h/w address ++ * flags: BSSCFG flags; see below ++ * ++ * current_bss: BSS parms in ASSOCIATED state ++ * ++ * ++ * ID: 'unique' ID of this bsscfg, assigned at bsscfg allocation ++ */ ++struct brcms_bss_cfg { ++ struct brcms_c_info *wlc; ++ bool up; ++ bool enable; ++ bool associated; ++ bool BSS; ++ u8 SSID_len; ++ u8 SSID[IEEE80211_MAX_SSID_LEN]; ++ u8 BSSID[ETH_ALEN]; ++ u8 cur_etheraddr[ETH_ALEN]; ++ struct brcms_bss_info *current_bss; ++}; ++ ++extern void brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, ++ struct sk_buff *p, ++ bool commit, s8 txpktpend); ++extern void brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, ++ s8 txpktpend); ++extern void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb, ++ struct sk_buff *sdu, uint prec); ++extern void brcms_c_print_txstatus(struct tx_status *txs); ++extern int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, ++ uint *blocks); ++ ++#if defined(BCMDBG) ++extern void brcms_c_print_txdesc(struct d11txh *txh); ++#else ++#define brcms_c_print_txdesc(a) ++#endif ++ ++extern int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config); ++extern void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc, ++ bool promisc); ++extern void brcms_c_send_q(struct brcms_c_info *wlc); ++extern int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu, ++ uint *fifo); ++extern u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec, ++ uint mac_len); ++extern u32 brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, ++ u32 rspec, ++ bool use_rspec, u16 mimo_ctlchbw); ++extern u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only, ++ u32 rts_rate, ++ u32 frame_rate, ++ u8 rts_preamble_type, ++ u8 frame_preamble_type, uint frame_len, ++ bool ba); ++extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw, ++ struct ieee80211_sta *sta, ++ void (*dma_callback_fn)); ++extern void brcms_c_update_beacon(struct brcms_c_info *wlc); ++extern void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend); ++extern int brcms_c_set_nmode(struct brcms_c_info *wlc); ++extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, ++ u32 bcn_rate); ++extern void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, ++ u8 antsel_type); ++extern void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, ++ u16 chanspec, ++ bool mute, struct txpwr_limits *txpwr); ++extern void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, ++ u16 v); ++extern u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset); ++extern void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, ++ u16 val, int bands); ++extern void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags); ++extern void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val); ++extern void brcms_b_phy_reset(struct brcms_hardware *wlc_hw); ++extern void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw); ++extern void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw); ++extern void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw, ++ u32 override_bit); ++extern void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw, ++ u32 override_bit); ++extern void brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, ++ int offset, int len, void *buf); ++extern u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate); ++extern void brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, ++ uint offset, const void *buf, int len, ++ u32 sel); ++extern void brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, ++ void *buf, int len, u32 sel); ++extern void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode); ++extern u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw); ++extern void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk); ++extern void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk); ++extern void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on); ++extern void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant); ++extern void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, ++ u8 stf_mode); ++extern void brcms_c_init_scb(struct scb *scb); ++ ++#endif /* _BRCM_MAIN_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/Makefile.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/Makefile +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/Makefile.orig 2011-11-09 13:46:58.251800557 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/Makefile 2011-11-09 13:47:17.005566104 -0500 +@@ -0,0 +1,51 @@ ++# ++# Makefile fragment for Broadcom 802.11n Networking Device Driver ++# ++# Copyright (c) 2010 Broadcom Corporation ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ccflags-y := \ ++ -D__CHECK_ENDIAN__ \ ++ -Idrivers/net/wireless/brcm80211/brcmsmac \ ++ -Idrivers/net/wireless/brcm80211/brcmsmac/phy \ ++ -Idrivers/net/wireless/brcm80211/include ++ ++BRCMSMAC_OFILES := \ ++ mac80211_if.o \ ++ ucode_loader.o \ ++ ampdu.o \ ++ antsel.o \ ++ channel.o \ ++ main.o \ ++ phy_shim.o \ ++ pmu.o \ ++ rate.o \ ++ stf.o \ ++ aiutils.o \ ++ phy/phy_cmn.o \ ++ phy/phy_lcn.o \ ++ phy/phy_n.o \ ++ phy/phytbl_lcn.o \ ++ phy/phytbl_n.o \ ++ phy/phy_qmath.o \ ++ otp.o \ ++ srom.o \ ++ dma.o \ ++ nicpci.o \ ++ brcms_trace_events.o ++ ++MODULEPFX := brcmsmac ++ ++obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o ++$(MODULEPFX)-objs = $(BRCMSMAC_OFILES) +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c.orig 2011-11-09 13:46:58.252800545 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c 2011-11-09 13:47:17.005566104 -0500 +@@ -0,0 +1,835 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include "aiutils.h" ++#include "pub.h" ++#include "nicpci.h" ++ ++/* SPROM offsets */ ++#define SRSH_ASPM_OFFSET 4 /* word 4 */ ++#define SRSH_ASPM_ENB 0x18 /* bit 3, 4 */ ++#define SRSH_ASPM_L1_ENB 0x10 /* bit 4 */ ++#define SRSH_ASPM_L0s_ENB 0x8 /* bit 3 */ ++ ++#define SRSH_PCIE_MISC_CONFIG 5 /* word 5 */ ++#define SRSH_L23READY_EXIT_NOPERST 0x8000 /* bit 15 */ ++#define SRSH_CLKREQ_OFFSET_REV5 20 /* word 20 for srom rev <= 5 */ ++#define SRSH_CLKREQ_ENB 0x0800 /* bit 11 */ ++#define SRSH_BD_OFFSET 6 /* word 6 */ ++ ++/* chipcontrol */ ++#define CHIPCTRL_4321_PLL_DOWN 0x800000/* serdes PLL down override */ ++ ++/* MDIO control */ ++#define MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */ ++#define MDIOCTL_DIVISOR_VAL 0x2 ++#define MDIOCTL_PREAM_EN 0x80 /* Enable preamble sequnce */ ++#define MDIOCTL_ACCESS_DONE 0x100 /* Transaction complete */ ++ ++/* MDIO Data */ ++#define MDIODATA_MASK 0x0000ffff /* data 2 bytes */ ++#define MDIODATA_TA 0x00020000 /* Turnaround */ ++ ++#define MDIODATA_REGADDR_SHF 18 /* Regaddr shift */ ++#define MDIODATA_REGADDR_MASK 0x007c0000 /* Regaddr Mask */ ++#define MDIODATA_DEVADDR_SHF 23 /* Physmedia devaddr shift */ ++#define MDIODATA_DEVADDR_MASK 0x0f800000 ++ /* Physmedia devaddr Mask */ ++ ++/* MDIO Data for older revisions < 10 */ ++#define MDIODATA_REGADDR_SHF_OLD 18 /* Regaddr shift */ ++#define MDIODATA_REGADDR_MASK_OLD 0x003c0000 ++ /* Regaddr Mask */ ++#define MDIODATA_DEVADDR_SHF_OLD 22 /* Physmedia devaddr shift */ ++#define MDIODATA_DEVADDR_MASK_OLD 0x0fc00000 ++ /* Physmedia devaddr Mask */ ++ ++/* Transactions flags */ ++#define MDIODATA_WRITE 0x10000000 ++#define MDIODATA_READ 0x20000000 ++#define MDIODATA_START 0x40000000 ++ ++#define MDIODATA_DEV_ADDR 0x0 /* dev address for serdes */ ++#define MDIODATA_BLK_ADDR 0x1F /* blk address for serdes */ ++ ++/* serdes regs (rev < 10) */ ++#define MDIODATA_DEV_PLL 0x1d /* SERDES PLL Dev */ ++#define MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */ ++#define MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */ ++ ++/* SERDES RX registers */ ++#define SERDES_RX_CTRL 1 /* Rx cntrl */ ++#define SERDES_RX_TIMER1 2 /* Rx Timer1 */ ++#define SERDES_RX_CDR 6 /* CDR */ ++#define SERDES_RX_CDRBW 7 /* CDR BW */ ++/* SERDES RX control register */ ++#define SERDES_RX_CTRL_FORCE 0x80 /* rxpolarity_force */ ++#define SERDES_RX_CTRL_POLARITY 0x40 /* rxpolarity_value */ ++ ++/* SERDES PLL registers */ ++#define SERDES_PLL_CTRL 1 /* PLL control reg */ ++#define PLL_CTRL_FREQDET_EN 0x4000 /* bit 14 is FREQDET on */ ++ ++/* Linkcontrol reg offset in PCIE Cap */ ++#define PCIE_CAP_LINKCTRL_OFFSET 16 /* offset in pcie cap */ ++#define PCIE_CAP_LCREG_ASPML0s 0x01 /* ASPM L0s in linkctrl */ ++#define PCIE_CAP_LCREG_ASPML1 0x02 /* ASPM L1 in linkctrl */ ++#define PCIE_CLKREQ_ENAB 0x100 /* CLKREQ Enab in linkctrl */ ++ ++#define PCIE_ASPM_ENAB 3 /* ASPM L0s & L1 in linkctrl */ ++#define PCIE_ASPM_L1_ENAB 2 /* ASPM L0s & L1 in linkctrl */ ++#define PCIE_ASPM_L0s_ENAB 1 /* ASPM L0s & L1 in linkctrl */ ++#define PCIE_ASPM_DISAB 0 /* ASPM L0s & L1 in linkctrl */ ++ ++/* Power management threshold */ ++#define PCIE_L1THRESHOLDTIME_MASK 0xFF00 /* bits 8 - 15 */ ++#define PCIE_L1THRESHOLDTIME_SHIFT 8 /* PCIE_L1THRESHOLDTIME_SHIFT */ ++#define PCIE_L1THRESHOLD_WARVAL 0x72 /* WAR value */ ++#define PCIE_ASPMTIMER_EXTEND 0x01000000 ++ /* > rev7: ++ * enable extend ASPM timer ++ */ ++ ++/* different register spaces to access thru pcie indirect access */ ++#define PCIE_CONFIGREGS 1 /* Access to config space */ ++#define PCIE_PCIEREGS 2 /* Access to pcie registers */ ++ ++/* PCIE protocol PHY diagnostic registers */ ++#define PCIE_PLP_STATUSREG 0x204 /* Status */ ++ ++/* Status reg PCIE_PLP_STATUSREG */ ++#define PCIE_PLP_POLARITYINV_STAT 0x10 ++ ++/* PCIE protocol DLLP diagnostic registers */ ++#define PCIE_DLLP_LCREG 0x100 /* Link Control */ ++#define PCIE_DLLP_PMTHRESHREG 0x128 /* Power Management Threshold */ ++ ++/* PCIE protocol TLP diagnostic registers */ ++#define PCIE_TLP_WORKAROUNDSREG 0x004 /* TLP Workarounds */ ++ ++/* Sonics to PCI translation types */ ++#define SBTOPCI_PREF 0x4 /* prefetch enable */ ++#define SBTOPCI_BURST 0x8 /* burst enable */ ++#define SBTOPCI_RC_READMULTI 0x20 /* memory read multiple */ ++ ++#define PCI_CLKRUN_DSBL 0x8000 /* Bit 15 forceClkrun */ ++ ++/* PCI core index in SROM shadow area */ ++#define SRSH_PI_OFFSET 0 /* first word */ ++#define SRSH_PI_MASK 0xf000 /* bit 15:12 */ ++#define SRSH_PI_SHIFT 12 /* bit 15:12 */ ++ ++/* Sonics side: PCI core and host control registers */ ++struct sbpciregs { ++ u32 control; /* PCI control */ ++ u32 PAD[3]; ++ u32 arbcontrol; /* PCI arbiter control */ ++ u32 clkrun; /* Clkrun Control (>=rev11) */ ++ u32 PAD[2]; ++ u32 intstatus; /* Interrupt status */ ++ u32 intmask; /* Interrupt mask */ ++ u32 sbtopcimailbox; /* Sonics to PCI mailbox */ ++ u32 PAD[9]; ++ u32 bcastaddr; /* Sonics broadcast address */ ++ u32 bcastdata; /* Sonics broadcast data */ ++ u32 PAD[2]; ++ u32 gpioin; /* ro: gpio input (>=rev2) */ ++ u32 gpioout; /* rw: gpio output (>=rev2) */ ++ u32 gpioouten; /* rw: gpio output enable (>= rev2) */ ++ u32 gpiocontrol; /* rw: gpio control (>= rev2) */ ++ u32 PAD[36]; ++ u32 sbtopci0; /* Sonics to PCI translation 0 */ ++ u32 sbtopci1; /* Sonics to PCI translation 1 */ ++ u32 sbtopci2; /* Sonics to PCI translation 2 */ ++ u32 PAD[189]; ++ u32 pcicfg[4][64]; /* 0x400 - 0x7FF, PCI Cfg Space (>=rev8) */ ++ u16 sprom[36]; /* SPROM shadow Area */ ++ u32 PAD[46]; ++}; ++ ++/* SB side: PCIE core and host control registers */ ++struct sbpcieregs { ++ u32 control; /* host mode only */ ++ u32 PAD[2]; ++ u32 biststatus; /* bist Status: 0x00C */ ++ u32 gpiosel; /* PCIE gpio sel: 0x010 */ ++ u32 gpioouten; /* PCIE gpio outen: 0x14 */ ++ u32 PAD[2]; ++ u32 intstatus; /* Interrupt status: 0x20 */ ++ u32 intmask; /* Interrupt mask: 0x24 */ ++ u32 sbtopcimailbox; /* sb to pcie mailbox: 0x028 */ ++ u32 PAD[53]; ++ u32 sbtopcie0; /* sb to pcie translation 0: 0x100 */ ++ u32 sbtopcie1; /* sb to pcie translation 1: 0x104 */ ++ u32 sbtopcie2; /* sb to pcie translation 2: 0x108 */ ++ u32 PAD[5]; ++ ++ /* pcie core supports in direct access to config space */ ++ u32 configaddr; /* pcie config space access: Address field: 0x120 */ ++ u32 configdata; /* pcie config space access: Data field: 0x124 */ ++ ++ /* mdio access to serdes */ ++ u32 mdiocontrol; /* controls the mdio access: 0x128 */ ++ u32 mdiodata; /* Data to the mdio access: 0x12c */ ++ ++ /* pcie protocol phy/dllp/tlp register indirect access mechanism */ ++ u32 pcieindaddr; /* indirect access to ++ * the internal register: 0x130 ++ */ ++ u32 pcieinddata; /* Data to/from the internal regsiter: 0x134 */ ++ ++ u32 clkreqenctrl; /* >= rev 6, Clkreq rdma control : 0x138 */ ++ u32 PAD[177]; ++ u32 pciecfg[4][64]; /* 0x400 - 0x7FF, PCIE Cfg Space */ ++ u16 sprom[64]; /* SPROM shadow Area */ ++}; ++ ++struct pcicore_info { ++ union { ++ struct sbpcieregs __iomem *pcieregs; ++ struct sbpciregs __iomem *pciregs; ++ } regs; /* Memory mapped register to the core */ ++ ++ struct si_pub *sih; /* System interconnect handle */ ++ struct pci_dev *dev; ++ u8 pciecap_lcreg_offset;/* PCIE capability LCreg offset ++ * in the config space ++ */ ++ bool pcie_pr42767; ++ u8 pcie_polarity; ++ u8 pcie_war_aspm_ovr; /* Override ASPM/Clkreq settings */ ++ ++ u8 pmecap_offset; /* PM Capability offset in the config space */ ++ bool pmecap; /* Capable of generating PME */ ++}; ++ ++#define PCIE_ASPM(sih) \ ++ (((sih)->buscoretype == PCIE_CORE_ID) && \ ++ (((sih)->buscorerev >= 3) && \ ++ ((sih)->buscorerev <= 5))) ++ ++ ++/* delay needed between the mdio control/ mdiodata register data access */ ++static void pr28829_delay(void) ++{ ++ udelay(10); ++} ++ ++/* Initialize the PCI core. ++ * It's caller's responsibility to make sure that this is done only once ++ */ ++struct pcicore_info *pcicore_init(struct si_pub *sih, struct pci_dev *pdev, ++ void __iomem *regs) ++{ ++ struct pcicore_info *pi; ++ ++ /* alloc struct pcicore_info */ ++ pi = kzalloc(sizeof(struct pcicore_info), GFP_ATOMIC); ++ if (pi == NULL) ++ return NULL; ++ ++ pi->sih = sih; ++ pi->dev = pdev; ++ ++ if (sih->buscoretype == PCIE_CORE_ID) { ++ u8 cap_ptr; ++ pi->regs.pcieregs = regs; ++ cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_EXP, ++ NULL, NULL); ++ pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET; ++ } else ++ pi->regs.pciregs = regs; ++ ++ return pi; ++} ++ ++void pcicore_deinit(struct pcicore_info *pch) ++{ ++ kfree(pch); ++} ++ ++/* return cap_offset if requested capability exists in the PCI config space */ ++/* Note that it's caller's responsibility to make sure it's a pci bus */ ++u8 ++pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id, ++ unsigned char *buf, u32 *buflen) ++{ ++ u8 cap_id; ++ u8 cap_ptr = 0; ++ u32 bufsize; ++ u8 byte_val; ++ ++ /* check for Header type 0 */ ++ pci_read_config_byte(dev, PCI_HEADER_TYPE, &byte_val); ++ if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL) ++ goto end; ++ ++ /* check if the capability pointer field exists */ ++ pci_read_config_byte(dev, PCI_STATUS, &byte_val); ++ if (!(byte_val & PCI_STATUS_CAP_LIST)) ++ goto end; ++ ++ pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &cap_ptr); ++ /* check if the capability pointer is 0x00 */ ++ if (cap_ptr == 0x00) ++ goto end; ++ ++ /* loop thru the capability list ++ * and see if the pcie capability exists ++ */ ++ ++ pci_read_config_byte(dev, cap_ptr, &cap_id); ++ ++ while (cap_id != req_cap_id) { ++ pci_read_config_byte(dev, cap_ptr + 1, &cap_ptr); ++ if (cap_ptr == 0x00) ++ break; ++ pci_read_config_byte(dev, cap_ptr, &cap_id); ++ } ++ if (cap_id != req_cap_id) ++ goto end; ++ ++ /* found the caller requested capability */ ++ if (buf != NULL && buflen != NULL) { ++ u8 cap_data; ++ ++ bufsize = *buflen; ++ if (!bufsize) ++ goto end; ++ *buflen = 0; ++ /* copy the capability data excluding cap ID and next ptr */ ++ cap_data = cap_ptr + 2; ++ if ((bufsize + cap_data) > PCI_SZPCR) ++ bufsize = PCI_SZPCR - cap_data; ++ *buflen = bufsize; ++ while (bufsize--) { ++ pci_read_config_byte(dev, cap_data, buf); ++ cap_data++; ++ buf++; ++ } ++ } ++end: ++ return cap_ptr; ++} ++ ++/* ***** Register Access API */ ++static uint ++pcie_readreg(struct sbpcieregs __iomem *pcieregs, uint addrtype, uint offset) ++{ ++ uint retval = 0xFFFFFFFF; ++ ++ switch (addrtype) { ++ case PCIE_CONFIGREGS: ++ W_REG(&pcieregs->configaddr, offset); ++ (void)R_REG((&pcieregs->configaddr)); ++ retval = R_REG(&pcieregs->configdata); ++ break; ++ case PCIE_PCIEREGS: ++ W_REG(&pcieregs->pcieindaddr, offset); ++ (void)R_REG(&pcieregs->pcieindaddr); ++ retval = R_REG(&pcieregs->pcieinddata); ++ break; ++ } ++ ++ return retval; ++} ++ ++static uint pcie_writereg(struct sbpcieregs __iomem *pcieregs, uint addrtype, ++ uint offset, uint val) ++{ ++ switch (addrtype) { ++ case PCIE_CONFIGREGS: ++ W_REG((&pcieregs->configaddr), offset); ++ W_REG((&pcieregs->configdata), val); ++ break; ++ case PCIE_PCIEREGS: ++ W_REG((&pcieregs->pcieindaddr), offset); ++ W_REG((&pcieregs->pcieinddata), val); ++ break; ++ default: ++ break; ++ } ++ return 0; ++} ++ ++static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk) ++{ ++ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; ++ uint mdiodata, i = 0; ++ uint pcie_serdes_spinwait = 200; ++ ++ mdiodata = (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | ++ (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | ++ (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) | ++ (blk << 4)); ++ W_REG(&pcieregs->mdiodata, mdiodata); ++ ++ pr28829_delay(); ++ /* retry till the transaction is complete */ ++ while (i < pcie_serdes_spinwait) { ++ if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) ++ break; ++ ++ udelay(1000); ++ i++; ++ } ++ ++ if (i >= pcie_serdes_spinwait) ++ return false; ++ ++ return true; ++} ++ ++static int ++pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write, ++ uint *val) ++{ ++ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; ++ uint mdiodata; ++ uint i = 0; ++ uint pcie_serdes_spinwait = 10; ++ ++ /* enable mdio access to SERDES */ ++ W_REG(&pcieregs->mdiocontrol, MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); ++ ++ if (pi->sih->buscorerev >= 10) { ++ /* new serdes is slower in rw, ++ * using two layers of reg address mapping ++ */ ++ if (!pcie_mdiosetblock(pi, physmedia)) ++ return 1; ++ mdiodata = ((MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | ++ (regaddr << MDIODATA_REGADDR_SHF)); ++ pcie_serdes_spinwait *= 20; ++ } else { ++ mdiodata = ((physmedia << MDIODATA_DEVADDR_SHF_OLD) | ++ (regaddr << MDIODATA_REGADDR_SHF_OLD)); ++ } ++ ++ if (!write) ++ mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA); ++ else ++ mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | ++ *val); ++ ++ W_REG(&pcieregs->mdiodata, mdiodata); ++ ++ pr28829_delay(); ++ ++ /* retry till the transaction is complete */ ++ while (i < pcie_serdes_spinwait) { ++ if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) { ++ if (!write) { ++ pr28829_delay(); ++ *val = (R_REG(&pcieregs->mdiodata) & ++ MDIODATA_MASK); ++ } ++ /* Disable mdio access to SERDES */ ++ W_REG(&pcieregs->mdiocontrol, 0); ++ return 0; ++ } ++ udelay(1000); ++ i++; ++ } ++ ++ /* Timed out. Disable mdio access to SERDES. */ ++ W_REG(&pcieregs->mdiocontrol, 0); ++ return 1; ++} ++ ++/* use the mdio interface to read from mdio slaves */ ++static int ++pcie_mdioread(struct pcicore_info *pi, uint physmedia, uint regaddr, ++ uint *regval) ++{ ++ return pcie_mdioop(pi, physmedia, regaddr, false, regval); ++} ++ ++/* use the mdio interface to write to mdio slaves */ ++static int ++pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint regaddr, uint val) ++{ ++ return pcie_mdioop(pi, physmedia, regaddr, true, &val); ++} ++ ++/* ***** Support functions ***** */ ++static u8 pcie_clkreq(struct pcicore_info *pi, u32 mask, u32 val) ++{ ++ u32 reg_val; ++ u8 offset; ++ ++ offset = pi->pciecap_lcreg_offset; ++ if (!offset) ++ return 0; ++ ++ pci_read_config_dword(pi->dev, offset, ®_val); ++ /* set operation */ ++ if (mask) { ++ if (val) ++ reg_val |= PCIE_CLKREQ_ENAB; ++ else ++ reg_val &= ~PCIE_CLKREQ_ENAB; ++ pci_write_config_dword(pi->dev, offset, reg_val); ++ pci_read_config_dword(pi->dev, offset, ®_val); ++ } ++ if (reg_val & PCIE_CLKREQ_ENAB) ++ return 1; ++ else ++ return 0; ++} ++ ++static void pcie_extendL1timer(struct pcicore_info *pi, bool extend) ++{ ++ u32 w; ++ struct si_pub *sih = pi->sih; ++ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; ++ ++ if (sih->buscoretype != PCIE_CORE_ID || sih->buscorerev < 7) ++ return; ++ ++ w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); ++ if (extend) ++ w |= PCIE_ASPMTIMER_EXTEND; ++ else ++ w &= ~PCIE_ASPMTIMER_EXTEND; ++ pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w); ++ w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); ++} ++ ++/* centralized clkreq control policy */ ++static void pcie_clkreq_upd(struct pcicore_info *pi, uint state) ++{ ++ struct si_pub *sih = pi->sih; ++ ++ switch (state) { ++ case SI_DOATTACH: ++ if (PCIE_ASPM(sih)) ++ pcie_clkreq(pi, 1, 0); ++ break; ++ case SI_PCIDOWN: ++ if (sih->buscorerev == 6) { /* turn on serdes PLL down */ ++ ai_corereg(sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_addr), ++ ~0, 0); ++ ai_corereg(sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_data), ++ ~0x40, 0); ++ } else if (pi->pcie_pr42767) { ++ pcie_clkreq(pi, 1, 1); ++ } ++ break; ++ case SI_PCIUP: ++ if (sih->buscorerev == 6) { /* turn off serdes PLL down */ ++ ai_corereg(sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_addr), ++ ~0, 0); ++ ai_corereg(sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_data), ++ ~0x40, 0x40); ++ } else if (PCIE_ASPM(sih)) { /* disable clkreq */ ++ pcie_clkreq(pi, 1, 0); ++ } ++ break; ++ } ++} ++ ++/* ***** PCI core WARs ***** */ ++/* Done only once at attach time */ ++static void pcie_war_polarity(struct pcicore_info *pi) ++{ ++ u32 w; ++ ++ if (pi->pcie_polarity != 0) ++ return; ++ ++ w = pcie_readreg(pi->regs.pcieregs, PCIE_PCIEREGS, PCIE_PLP_STATUSREG); ++ ++ /* Detect the current polarity at attach and force that polarity and ++ * disable changing the polarity ++ */ ++ if ((w & PCIE_PLP_POLARITYINV_STAT) == 0) ++ pi->pcie_polarity = SERDES_RX_CTRL_FORCE; ++ else ++ pi->pcie_polarity = (SERDES_RX_CTRL_FORCE | ++ SERDES_RX_CTRL_POLARITY); ++} ++ ++/* enable ASPM and CLKREQ if srom doesn't have it */ ++/* Needs to happen when update to shadow SROM is needed ++ * : Coming out of 'standby'/'hibernate' ++ * : If pcie_war_aspm_ovr state changed ++ */ ++static void pcie_war_aspm_clkreq(struct pcicore_info *pi) ++{ ++ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; ++ struct si_pub *sih = pi->sih; ++ u16 val16; ++ u16 __iomem *reg16; ++ u32 w; ++ ++ if (!PCIE_ASPM(sih)) ++ return; ++ ++ /* bypass this on QT or VSIM */ ++ reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET]; ++ val16 = R_REG(reg16); ++ ++ val16 &= ~SRSH_ASPM_ENB; ++ if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB) ++ val16 |= SRSH_ASPM_ENB; ++ else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L1_ENAB) ++ val16 |= SRSH_ASPM_L1_ENB; ++ else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB) ++ val16 |= SRSH_ASPM_L0s_ENB; ++ ++ W_REG(reg16, val16); ++ ++ pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w); ++ w &= ~PCIE_ASPM_ENAB; ++ w |= pi->pcie_war_aspm_ovr; ++ pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w); ++ ++ reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET_REV5]; ++ val16 = R_REG(reg16); ++ ++ if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) { ++ val16 |= SRSH_CLKREQ_ENB; ++ pi->pcie_pr42767 = true; ++ } else ++ val16 &= ~SRSH_CLKREQ_ENB; ++ ++ W_REG(reg16, val16); ++} ++ ++/* Apply the polarity determined at the start */ ++/* Needs to happen when coming out of 'standby'/'hibernate' */ ++static void pcie_war_serdes(struct pcicore_info *pi) ++{ ++ u32 w = 0; ++ ++ if (pi->pcie_polarity != 0) ++ pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CTRL, ++ pi->pcie_polarity); ++ ++ pcie_mdioread(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w); ++ if (w & PLL_CTRL_FREQDET_EN) { ++ w &= ~PLL_CTRL_FREQDET_EN; ++ pcie_mdiowrite(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w); ++ } ++} ++ ++/* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */ ++/* Needs to happen when coming out of 'standby'/'hibernate' */ ++static void pcie_misc_config_fixup(struct pcicore_info *pi) ++{ ++ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; ++ u16 val16; ++ u16 __iomem *reg16; ++ ++ reg16 = &pcieregs->sprom[SRSH_PCIE_MISC_CONFIG]; ++ val16 = R_REG(reg16); ++ ++ if ((val16 & SRSH_L23READY_EXIT_NOPERST) == 0) { ++ val16 |= SRSH_L23READY_EXIT_NOPERST; ++ W_REG(reg16, val16); ++ } ++} ++ ++/* quick hack for testing */ ++/* Needs to happen when coming out of 'standby'/'hibernate' */ ++static void pcie_war_noplldown(struct pcicore_info *pi) ++{ ++ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; ++ u16 __iomem *reg16; ++ ++ /* turn off serdes PLL down */ ++ ai_corereg(pi->sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol), ++ CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN); ++ ++ /* clear srom shadow backdoor */ ++ reg16 = &pcieregs->sprom[SRSH_BD_OFFSET]; ++ W_REG(reg16, 0); ++} ++ ++/* Needs to happen when coming out of 'standby'/'hibernate' */ ++static void pcie_war_pci_setup(struct pcicore_info *pi) ++{ ++ struct si_pub *sih = pi->sih; ++ struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs; ++ u32 w; ++ ++ if (sih->buscorerev == 0 || sih->buscorerev == 1) { ++ w = pcie_readreg(pcieregs, PCIE_PCIEREGS, ++ PCIE_TLP_WORKAROUNDSREG); ++ w |= 0x8; ++ pcie_writereg(pcieregs, PCIE_PCIEREGS, ++ PCIE_TLP_WORKAROUNDSREG, w); ++ } ++ ++ if (sih->buscorerev == 1) { ++ w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG); ++ w |= 0x40; ++ pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w); ++ } ++ ++ if (sih->buscorerev == 0) { ++ pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128); ++ pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100); ++ pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466); ++ } else if (PCIE_ASPM(sih)) { ++ /* Change the L1 threshold for better performance */ ++ w = pcie_readreg(pcieregs, PCIE_PCIEREGS, ++ PCIE_DLLP_PMTHRESHREG); ++ w &= ~PCIE_L1THRESHOLDTIME_MASK; ++ w |= PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT; ++ pcie_writereg(pcieregs, PCIE_PCIEREGS, ++ PCIE_DLLP_PMTHRESHREG, w); ++ ++ pcie_war_serdes(pi); ++ ++ pcie_war_aspm_clkreq(pi); ++ } else if (pi->sih->buscorerev == 7) ++ pcie_war_noplldown(pi); ++ ++ /* Note that the fix is actually in the SROM, ++ * that's why this is open-ended ++ */ ++ if (pi->sih->buscorerev >= 6) ++ pcie_misc_config_fixup(pi); ++} ++ ++/* ***** Functions called during driver state changes ***** */ ++void pcicore_attach(struct pcicore_info *pi, int state) ++{ ++ struct si_pub *sih = pi->sih; ++ u32 bfl2 = (u32)getintvar(sih, BRCMS_SROM_BOARDFLAGS2); ++ ++ /* Determine if this board needs override */ ++ if (PCIE_ASPM(sih)) { ++ if (bfl2 & BFL2_PCIEWAR_OVR) ++ pi->pcie_war_aspm_ovr = PCIE_ASPM_DISAB; ++ else ++ pi->pcie_war_aspm_ovr = PCIE_ASPM_ENAB; ++ } ++ ++ /* These need to happen in this order only */ ++ pcie_war_polarity(pi); ++ ++ pcie_war_serdes(pi); ++ ++ pcie_war_aspm_clkreq(pi); ++ ++ pcie_clkreq_upd(pi, state); ++ ++} ++ ++void pcicore_hwup(struct pcicore_info *pi) ++{ ++ if (!pi || pi->sih->buscoretype != PCIE_CORE_ID) ++ return; ++ ++ pcie_war_pci_setup(pi); ++} ++ ++void pcicore_up(struct pcicore_info *pi, int state) ++{ ++ if (!pi || pi->sih->buscoretype != PCIE_CORE_ID) ++ return; ++ ++ /* Restore L1 timer for better performance */ ++ pcie_extendL1timer(pi, true); ++ ++ pcie_clkreq_upd(pi, state); ++} ++ ++/* When the device is going to enter D3 state ++ * (or the system is going to enter S3/S4 states) ++ */ ++void pcicore_sleep(struct pcicore_info *pi) ++{ ++ u32 w; ++ ++ if (!pi || !PCIE_ASPM(pi->sih)) ++ return; ++ ++ pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w); ++ w &= ~PCIE_CAP_LCREG_ASPML1; ++ pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w); ++ ++ pi->pcie_pr42767 = false; ++} ++ ++void pcicore_down(struct pcicore_info *pi, int state) ++{ ++ if (!pi || pi->sih->buscoretype != PCIE_CORE_ID) ++ return; ++ ++ pcie_clkreq_upd(pi, state); ++ ++ /* Reduce L1 timer for better power savings */ ++ pcie_extendL1timer(pi, false); ++} ++ ++/* precondition: current core is sii->buscoretype */ ++static void pcicore_fixcfg(struct pcicore_info *pi, u16 __iomem *reg16) ++{ ++ struct si_info *sii = (struct si_info *)(pi->sih); ++ u16 val16; ++ uint pciidx; ++ ++ pciidx = ai_coreidx(&sii->pub); ++ val16 = R_REG(reg16); ++ if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16)pciidx) { ++ val16 = (u16)(pciidx << SRSH_PI_SHIFT) | ++ (val16 & ~SRSH_PI_MASK); ++ W_REG(reg16, val16); ++ } ++} ++ ++void ++pcicore_fixcfg_pci(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs) ++{ ++ pcicore_fixcfg(pi, &pciregs->sprom[SRSH_PI_OFFSET]); ++} ++ ++void pcicore_fixcfg_pcie(struct pcicore_info *pi, ++ struct sbpcieregs __iomem *pcieregs) ++{ ++ pcicore_fixcfg(pi, &pcieregs->sprom[SRSH_PI_OFFSET]); ++} ++ ++/* precondition: current core is pci core */ ++void ++pcicore_pci_setup(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs) ++{ ++ u32 w; ++ ++ OR_REG(&pciregs->sbtopci2, SBTOPCI_PREF | SBTOPCI_BURST); ++ ++ if (((struct si_info *)(pi->sih))->pub.buscorerev >= 11) { ++ OR_REG(&pciregs->sbtopci2, SBTOPCI_RC_READMULTI); ++ w = R_REG(&pciregs->clkrun); ++ W_REG(&pciregs->clkrun, w | PCI_CLKRUN_DSBL); ++ w = R_REG(&pciregs->clkrun); ++ } ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h.orig 2011-11-09 13:46:58.252800545 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h 2011-11-09 13:47:17.005566104 -0500 +@@ -0,0 +1,82 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_NICPCI_H_ ++#define _BRCM_NICPCI_H_ ++ ++#include "types.h" ++ ++/* PCI configuration address space size */ ++#define PCI_SZPCR 256 ++ ++/* Brcm PCI configuration registers */ ++/* backplane address space accessed by BAR0 */ ++#define PCI_BAR0_WIN 0x80 ++/* sprom property control */ ++#define PCI_SPROM_CONTROL 0x88 ++/* mask of PCI and other cores interrupts */ ++#define PCI_INT_MASK 0x94 ++/* backplane core interrupt mask bits offset */ ++#define PCI_SBIM_SHIFT 8 ++/* backplane address space accessed by second 4KB of BAR0 */ ++#define PCI_BAR0_WIN2 0xac ++/* pci config space gpio input (>=rev3) */ ++#define PCI_GPIO_IN 0xb0 ++/* pci config space gpio output (>=rev3) */ ++#define PCI_GPIO_OUT 0xb4 ++/* pci config space gpio output enable (>=rev3) */ ++#define PCI_GPIO_OUTEN 0xb8 ++ ++/* bar0 + 4K accesses external sprom */ ++#define PCI_BAR0_SPROM_OFFSET (4 * 1024) ++/* bar0 + 6K accesses pci core registers */ ++#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) ++/* ++ * pci core SB registers are at the end of the ++ * 8KB window, so their address is the "regular" ++ * address plus 4K ++ */ ++#define PCI_BAR0_PCISBR_OFFSET (4 * 1024) ++/* bar0 window size Match with corerev 13 */ ++#define PCI_BAR0_WINSZ (16 * 1024) ++/* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */ ++/* bar0 + 8K accesses pci/pcie core registers */ ++#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024) ++/* bar0 + 12K accesses chipc core registers */ ++#define PCI_16KB0_CCREGS_OFFSET (12 * 1024) ++ ++struct sbpciregs; ++struct sbpcieregs; ++ ++extern struct pcicore_info *pcicore_init(struct si_pub *sih, ++ struct pci_dev *pdev, ++ void __iomem *regs); ++extern void pcicore_deinit(struct pcicore_info *pch); ++extern void pcicore_attach(struct pcicore_info *pch, int state); ++extern void pcicore_hwup(struct pcicore_info *pch); ++extern void pcicore_up(struct pcicore_info *pch, int state); ++extern void pcicore_sleep(struct pcicore_info *pch); ++extern void pcicore_down(struct pcicore_info *pch, int state); ++extern u8 pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id, ++ unsigned char *buf, u32 *buflen); ++extern void pcicore_fixcfg_pci(struct pcicore_info *pch, ++ struct sbpciregs __iomem *pciregs); ++extern void pcicore_fixcfg_pcie(struct pcicore_info *pch, ++ struct sbpcieregs __iomem *pciregs); ++extern void pcicore_pci_setup(struct pcicore_info *pch, ++ struct sbpciregs __iomem *pciregs); ++ ++#endif /* _BRCM_NICPCI_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.c.orig 2011-11-09 13:46:58.252800545 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.c 2011-11-09 13:47:17.006566092 -0500 +@@ -0,0 +1,426 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include "aiutils.h" ++#include "otp.h" ++ ++#define OTPS_GUP_MASK 0x00000f00 ++#define OTPS_GUP_SHIFT 8 ++/* h/w subregion is programmed */ ++#define OTPS_GUP_HW 0x00000100 ++/* s/w subregion is programmed */ ++#define OTPS_GUP_SW 0x00000200 ++/* chipid/pkgopt subregion is programmed */ ++#define OTPS_GUP_CI 0x00000400 ++/* fuse subregion is programmed */ ++#define OTPS_GUP_FUSE 0x00000800 ++ ++/* Fields in otpprog in rev >= 21 */ ++#define OTPP_COL_MASK 0x000000ff ++#define OTPP_COL_SHIFT 0 ++#define OTPP_ROW_MASK 0x0000ff00 ++#define OTPP_ROW_SHIFT 8 ++#define OTPP_OC_MASK 0x0f000000 ++#define OTPP_OC_SHIFT 24 ++#define OTPP_READERR 0x10000000 ++#define OTPP_VALUE_MASK 0x20000000 ++#define OTPP_VALUE_SHIFT 29 ++#define OTPP_START_BUSY 0x80000000 ++#define OTPP_READ 0x40000000 ++ ++/* Opcodes for OTPP_OC field */ ++#define OTPPOC_READ 0 ++#define OTPPOC_BIT_PROG 1 ++#define OTPPOC_VERIFY 3 ++#define OTPPOC_INIT 4 ++#define OTPPOC_SET 5 ++#define OTPPOC_RESET 6 ++#define OTPPOC_OCST 7 ++#define OTPPOC_ROW_LOCK 8 ++#define OTPPOC_PRESCN_TEST 9 ++ ++#define OTPTYPE_IPX(ccrev) ((ccrev) == 21 || (ccrev) >= 23) ++ ++#define OTPP_TRIES 10000000 /* # of tries for OTPP */ ++ ++#define MAXNUMRDES 9 /* Maximum OTP redundancy entries */ ++ ++/* Fixed size subregions sizes in words */ ++#define OTPGU_CI_SZ 2 ++ ++struct otpinfo; ++ ++/* OTP function struct */ ++struct otp_fn_s { ++ int (*init)(struct si_pub *sih, struct otpinfo *oi); ++ int (*read_region)(struct otpinfo *oi, int region, u16 *data, ++ uint *wlen); ++}; ++ ++struct otpinfo { ++ uint ccrev; /* chipc revision */ ++ const struct otp_fn_s *fn; /* OTP functions */ ++ struct si_pub *sih; /* Saved sb handle */ ++ ++ /* IPX OTP section */ ++ u16 wsize; /* Size of otp in words */ ++ u16 rows; /* Geometry */ ++ u16 cols; /* Geometry */ ++ u32 status; /* Flag bits (lock/prog/rv). ++ * (Reflected only when OTP is power cycled) ++ */ ++ u16 hwbase; /* hardware subregion offset */ ++ u16 hwlim; /* hardware subregion boundary */ ++ u16 swbase; /* software subregion offset */ ++ u16 swlim; /* software subregion boundary */ ++ u16 fbase; /* fuse subregion offset */ ++ u16 flim; /* fuse subregion boundary */ ++ int otpgu_base; /* offset to General Use Region */ ++}; ++ ++/* OTP layout */ ++/* CC revs 21, 24 and 27 OTP General Use Region word offset */ ++#define REVA4_OTPGU_BASE 12 ++ ++/* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */ ++#define REVB8_OTPGU_BASE 20 ++ ++/* CC rev 36 OTP General Use Region word offset */ ++#define REV36_OTPGU_BASE 12 ++ ++/* Subregion word offsets in General Use region */ ++#define OTPGU_HSB_OFF 0 ++#define OTPGU_SFB_OFF 1 ++#define OTPGU_CI_OFF 2 ++#define OTPGU_P_OFF 3 ++#define OTPGU_SROM_OFF 4 ++ ++/* Flag bit offsets in General Use region */ ++#define OTPGU_HWP_OFF 60 ++#define OTPGU_SWP_OFF 61 ++#define OTPGU_CIP_OFF 62 ++#define OTPGU_FUSEP_OFF 63 ++#define OTPGU_CIP_MSK 0x4000 ++#define OTPGU_P_MSK 0xf000 ++#define OTPGU_P_SHIFT (OTPGU_HWP_OFF % 16) ++ ++/* OTP Size */ ++#define OTP_SZ_FU_324 ((roundup(324, 8))/8) /* 324 bits */ ++#define OTP_SZ_FU_288 (288/8) /* 288 bits */ ++#define OTP_SZ_FU_216 (216/8) /* 216 bits */ ++#define OTP_SZ_FU_72 (72/8) /* 72 bits */ ++#define OTP_SZ_CHECKSUM (16/8) /* 16 bits */ ++#define OTP4315_SWREG_SZ 178 /* 178 bytes */ ++#define OTP_SZ_FU_144 (144/8) /* 144 bits */ ++ ++static u16 ++ipxotp_otpr(struct otpinfo *oi, struct chipcregs __iomem *cc, uint wn) ++{ ++ return R_REG(&cc->sromotp[wn]); ++} ++ ++/* ++ * Calculate max HW/SW region byte size by subtracting fuse region ++ * and checksum size, osizew is oi->wsize (OTP size - GU size) in words ++ */ ++static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew) ++{ ++ int ret = 0; ++ ++ switch (sih->chip) { ++ case BCM43224_CHIP_ID: ++ case BCM43225_CHIP_ID: ++ ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM; ++ break; ++ case BCM4313_CHIP_ID: ++ ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM; ++ break; ++ default: ++ break; /* Don't know about this chip */ ++ } ++ ++ return ret; ++} ++ ++static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc) ++{ ++ uint k; ++ u32 otpp, st; ++ ++ /* ++ * record word offset of General Use Region ++ * for various chipcommon revs ++ */ ++ if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24 ++ || oi->sih->ccrev == 27) { ++ oi->otpgu_base = REVA4_OTPGU_BASE; ++ } else if (oi->sih->ccrev == 36) { ++ /* ++ * OTP size greater than equal to 2KB (128 words), ++ * otpgu_base is similar to rev23 ++ */ ++ if (oi->wsize >= 128) ++ oi->otpgu_base = REVB8_OTPGU_BASE; ++ else ++ oi->otpgu_base = REV36_OTPGU_BASE; ++ } else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) { ++ oi->otpgu_base = REVB8_OTPGU_BASE; ++ } ++ ++ /* First issue an init command so the status is up to date */ ++ otpp = ++ OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK); ++ ++ W_REG(&cc->otpprog, otpp); ++ for (k = 0; ++ ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY) ++ && (k < OTPP_TRIES); k++) ++ ; ++ if (k >= OTPP_TRIES) ++ return; ++ ++ /* Read OTP lock bits and subregion programmed indication bits */ ++ oi->status = R_REG(&cc->otpstatus); ++ ++ if ((oi->sih->chip == BCM43224_CHIP_ID) ++ || (oi->sih->chip == BCM43225_CHIP_ID)) { ++ u32 p_bits; ++ p_bits = ++ (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) & ++ OTPGU_P_MSK) ++ >> OTPGU_P_SHIFT; ++ oi->status |= (p_bits << OTPS_GUP_SHIFT); ++ } ++ ++ /* ++ * h/w region base and fuse region limit are fixed to ++ * the top and the bottom of the general use region. ++ * Everything else can be flexible. ++ */ ++ oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF; ++ oi->hwlim = oi->wsize; ++ if (oi->status & OTPS_GUP_HW) { ++ oi->hwlim = ++ ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16; ++ oi->swbase = oi->hwlim; ++ } else ++ oi->swbase = oi->hwbase; ++ ++ /* subtract fuse and checksum from beginning */ ++ oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2; ++ ++ if (oi->status & OTPS_GUP_SW) { ++ oi->swlim = ++ ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16; ++ oi->fbase = oi->swlim; ++ } else ++ oi->fbase = oi->swbase; ++ ++ oi->flim = oi->wsize; ++} ++ ++static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi) ++{ ++ uint idx; ++ struct chipcregs __iomem *cc; ++ ++ /* Make sure we're running IPX OTP */ ++ if (!OTPTYPE_IPX(sih->ccrev)) ++ return -EBADE; ++ ++ /* Make sure OTP is not disabled */ ++ if (ai_is_otp_disabled(sih)) ++ return -EBADE; ++ ++ /* Check for otp size */ ++ switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) { ++ case 0: ++ /* Nothing there */ ++ return -EBADE; ++ case 1: /* 32x64 */ ++ oi->rows = 32; ++ oi->cols = 64; ++ oi->wsize = 128; ++ break; ++ case 2: /* 64x64 */ ++ oi->rows = 64; ++ oi->cols = 64; ++ oi->wsize = 256; ++ break; ++ case 5: /* 96x64 */ ++ oi->rows = 96; ++ oi->cols = 64; ++ oi->wsize = 384; ++ break; ++ case 7: /* 16x64 *//* 1024 bits */ ++ oi->rows = 16; ++ oi->cols = 64; ++ oi->wsize = 64; ++ break; ++ default: ++ /* Don't know the geometry */ ++ return -EBADE; ++ } ++ ++ /* Retrieve OTP region info */ ++ idx = ai_coreidx(sih); ++ cc = ai_setcoreidx(sih, SI_CC_IDX); ++ ++ _ipxotp_init(oi, cc); ++ ++ ai_setcoreidx(sih, idx); ++ ++ return 0; ++} ++ ++static int ++ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen) ++{ ++ uint idx; ++ struct chipcregs __iomem *cc; ++ uint base, i, sz; ++ ++ /* Validate region selection */ ++ switch (region) { ++ case OTP_HW_RGN: ++ sz = (uint) oi->hwlim - oi->hwbase; ++ if (!(oi->status & OTPS_GUP_HW)) { ++ *wlen = sz; ++ return -ENODATA; ++ } ++ if (*wlen < sz) { ++ *wlen = sz; ++ return -EOVERFLOW; ++ } ++ base = oi->hwbase; ++ break; ++ case OTP_SW_RGN: ++ sz = ((uint) oi->swlim - oi->swbase); ++ if (!(oi->status & OTPS_GUP_SW)) { ++ *wlen = sz; ++ return -ENODATA; ++ } ++ if (*wlen < sz) { ++ *wlen = sz; ++ return -EOVERFLOW; ++ } ++ base = oi->swbase; ++ break; ++ case OTP_CI_RGN: ++ sz = OTPGU_CI_SZ; ++ if (!(oi->status & OTPS_GUP_CI)) { ++ *wlen = sz; ++ return -ENODATA; ++ } ++ if (*wlen < sz) { ++ *wlen = sz; ++ return -EOVERFLOW; ++ } ++ base = oi->otpgu_base + OTPGU_CI_OFF; ++ break; ++ case OTP_FUSE_RGN: ++ sz = (uint) oi->flim - oi->fbase; ++ if (!(oi->status & OTPS_GUP_FUSE)) { ++ *wlen = sz; ++ return -ENODATA; ++ } ++ if (*wlen < sz) { ++ *wlen = sz; ++ return -EOVERFLOW; ++ } ++ base = oi->fbase; ++ break; ++ case OTP_ALL_RGN: ++ sz = ((uint) oi->flim - oi->hwbase); ++ if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) { ++ *wlen = sz; ++ return -ENODATA; ++ } ++ if (*wlen < sz) { ++ *wlen = sz; ++ return -EOVERFLOW; ++ } ++ base = oi->hwbase; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ idx = ai_coreidx(oi->sih); ++ cc = ai_setcoreidx(oi->sih, SI_CC_IDX); ++ ++ /* Read the data */ ++ for (i = 0; i < sz; i++) ++ data[i] = ipxotp_otpr(oi, cc, base + i); ++ ++ ai_setcoreidx(oi->sih, idx); ++ *wlen = sz; ++ return 0; ++} ++ ++static const struct otp_fn_s ipxotp_fn = { ++ (int (*)(struct si_pub *, struct otpinfo *)) ipxotp_init, ++ (int (*)(struct otpinfo *, int, u16 *, uint *)) ipxotp_read_region, ++}; ++ ++static int otp_init(struct si_pub *sih, struct otpinfo *oi) ++{ ++ ++ int ret; ++ ++ memset(oi, 0, sizeof(struct otpinfo)); ++ ++ oi->ccrev = sih->ccrev; ++ ++ if (OTPTYPE_IPX(oi->ccrev)) ++ oi->fn = &ipxotp_fn; ++ ++ if (oi->fn == NULL) ++ return -EBADE; ++ ++ oi->sih = sih; ++ ++ ret = (oi->fn->init) (sih, oi); ++ ++ return ret; ++} ++ ++int ++otp_read_region(struct si_pub *sih, int region, u16 *data, uint *wlen) { ++ struct otpinfo otpinfo; ++ struct otpinfo *oi = &otpinfo; ++ int err = 0; ++ ++ if (ai_is_otp_disabled(sih)) { ++ err = -EPERM; ++ goto out; ++ } ++ ++ err = otp_init(sih, oi); ++ if (err) ++ goto out; ++ ++ err = ((oi)->fn->read_region)(oi, region, data, wlen); ++ ++ out: ++ return err; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.h.orig 2011-11-09 13:46:58.252800545 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/otp.h 2011-11-09 13:47:17.006566092 -0500 +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_OTP_H_ ++#define _BRCM_OTP_H_ ++ ++#include "types.h" ++ ++/* OTP regions */ ++#define OTP_HW_RGN 1 ++#define OTP_SW_RGN 2 ++#define OTP_CI_RGN 4 ++#define OTP_FUSE_RGN 8 ++/* From h/w region to end of OTP including checksum */ ++#define OTP_ALL_RGN 0xf ++ ++/* OTP Size */ ++#define OTP_SZ_MAX (6144/8) /* maximum bytes in one CIS */ ++ ++extern int otp_read_region(struct si_pub *sih, int region, u16 *data, ++ uint *wlen); ++ ++#endif /* _BRCM_OTP_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c.orig 2011-11-09 13:46:58.254800521 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c 2011-11-09 13:47:17.008566067 -0500 +@@ -0,0 +1,2988 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include "phy_hal.h" ++#include "phy_int.h" ++#include "phy_radio.h" ++#include "phy_lcn.h" ++#include "phyreg_n.h" ++ ++#define VALID_N_RADIO(radioid) ((radioid == BCM2055_ID) || \ ++ (radioid == BCM2056_ID) || \ ++ (radioid == BCM2057_ID)) ++ ++#define VALID_LCN_RADIO(radioid) (radioid == BCM2064_ID) ++ ++#define VALID_RADIO(pi, radioid) ( \ ++ (ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \ ++ (ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false)) ++ ++/* basic mux operation - can be optimized on several architectures */ ++#define MUX(pred, true, false) ((pred) ? (true) : (false)) ++ ++/* modulo inc/dec - assumes x E [0, bound - 1] */ ++#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1) ++ ++/* modulo inc/dec, bound = 2^k */ ++#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1)) ++#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1)) ++ ++struct chan_info_basic { ++ u16 chan; ++ u16 freq; ++}; ++ ++static const struct chan_info_basic chan_info_all[] = { ++ {1, 2412}, ++ {2, 2417}, ++ {3, 2422}, ++ {4, 2427}, ++ {5, 2432}, ++ {6, 2437}, ++ {7, 2442}, ++ {8, 2447}, ++ {9, 2452}, ++ {10, 2457}, ++ {11, 2462}, ++ {12, 2467}, ++ {13, 2472}, ++ {14, 2484}, ++ ++ {34, 5170}, ++ {38, 5190}, ++ {42, 5210}, ++ {46, 5230}, ++ ++ {36, 5180}, ++ {40, 5200}, ++ {44, 5220}, ++ {48, 5240}, ++ {52, 5260}, ++ {56, 5280}, ++ {60, 5300}, ++ {64, 5320}, ++ ++ {100, 5500}, ++ {104, 5520}, ++ {108, 5540}, ++ {112, 5560}, ++ {116, 5580}, ++ {120, 5600}, ++ {124, 5620}, ++ {128, 5640}, ++ {132, 5660}, ++ {136, 5680}, ++ {140, 5700}, ++ ++ {149, 5745}, ++ {153, 5765}, ++ {157, 5785}, ++ {161, 5805}, ++ {165, 5825}, ++ ++ {184, 4920}, ++ {188, 4940}, ++ {192, 4960}, ++ {196, 4980}, ++ {200, 5000}, ++ {204, 5020}, ++ {208, 5040}, ++ {212, 5060}, ++ {216, 50800} ++}; ++ ++const u8 ofdm_rate_lookup[] = { ++ ++ BRCM_RATE_48M, ++ BRCM_RATE_24M, ++ BRCM_RATE_12M, ++ BRCM_RATE_6M, ++ BRCM_RATE_54M, ++ BRCM_RATE_36M, ++ BRCM_RATE_18M, ++ BRCM_RATE_9M ++}; ++ ++#define PHY_WREG_LIMIT 24 ++ ++void wlc_phyreg_enter(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ wlapi_bmac_ucode_wake_override_phyreg_set(pi->sh->physhim); ++} ++ ++void wlc_phyreg_exit(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ wlapi_bmac_ucode_wake_override_phyreg_clear(pi->sh->physhim); ++} ++ ++void wlc_radioreg_enter(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, MCTL_LOCK_RADIO); ++ ++ udelay(10); ++} ++ ++void wlc_radioreg_exit(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ u16 dummy; ++ ++ dummy = R_REG(&pi->regs->phyversion); ++ pi->phy_wreg = 0; ++ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, 0); ++} ++ ++u16 read_radio_reg(struct brcms_phy *pi, u16 addr) ++{ ++ u16 data; ++ ++ if ((addr == RADIO_IDCODE)) ++ return 0xffff; ++ ++ switch (pi->pubpi.phy_type) { ++ case PHY_TYPE_N: ++ if (!CONF_HAS(PHYTYPE, PHY_TYPE_N)) ++ break; ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ addr |= RADIO_2057_READ_OFF; ++ else ++ addr |= RADIO_2055_READ_OFF; ++ break; ++ ++ case PHY_TYPE_LCN: ++ if (!CONF_HAS(PHYTYPE, PHY_TYPE_LCN)) ++ break; ++ addr |= RADIO_2064_READ_OFF; ++ break; ++ ++ default: ++ break; ++ } ++ ++ if ((D11REV_GE(pi->sh->corerev, 24)) || ++ (D11REV_IS(pi->sh->corerev, 22) ++ && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { ++ W_REG_FLUSH(&pi->regs->radioregaddr, addr); ++ data = R_REG(&pi->regs->radioregdata); ++ } else { ++ W_REG_FLUSH(&pi->regs->phy4waddr, addr); ++ ++#ifdef __ARM_ARCH_4T__ ++ __asm__(" .align 4 "); ++ __asm__(" nop "); ++ data = R_REG(&pi->regs->phy4wdatalo); ++#else ++ data = R_REG(&pi->regs->phy4wdatalo); ++#endif ++ ++ } ++ pi->phy_wreg = 0; ++ ++ return data; ++} ++ ++void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) ++{ ++ if ((D11REV_GE(pi->sh->corerev, 24)) || ++ (D11REV_IS(pi->sh->corerev, 22) ++ && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { ++ ++ W_REG_FLUSH(&pi->regs->radioregaddr, addr); ++ W_REG(&pi->regs->radioregdata, val); ++ } else { ++ W_REG_FLUSH(&pi->regs->phy4waddr, addr); ++ W_REG(&pi->regs->phy4wdatalo, val); ++ } ++ ++ if (++pi->phy_wreg >= pi->phy_wreg_limit) { ++ (void)R_REG(&pi->regs->maccontrol); ++ pi->phy_wreg = 0; ++ } ++} ++ ++static u32 read_radio_id(struct brcms_phy *pi) ++{ ++ u32 id; ++ ++ if (D11REV_GE(pi->sh->corerev, 24)) { ++ u32 b0, b1, b2; ++ ++ W_REG_FLUSH(&pi->regs->radioregaddr, 0); ++ b0 = (u32) R_REG(&pi->regs->radioregdata); ++ W_REG_FLUSH(&pi->regs->radioregaddr, 1); ++ b1 = (u32) R_REG(&pi->regs->radioregdata); ++ W_REG_FLUSH(&pi->regs->radioregaddr, 2); ++ b2 = (u32) R_REG(&pi->regs->radioregdata); ++ ++ id = ((b0 & 0xf) << 28) | (((b2 << 8) | b1) << 12) | ((b0 >> 4) ++ & 0xf); ++ } else { ++ W_REG_FLUSH(&pi->regs->phy4waddr, RADIO_IDCODE); ++ id = (u32) R_REG(&pi->regs->phy4wdatalo); ++ id |= (u32) R_REG(&pi->regs->phy4wdatahi) << 16; ++ } ++ pi->phy_wreg = 0; ++ return id; ++} ++ ++void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) ++{ ++ u16 rval; ++ ++ rval = read_radio_reg(pi, addr); ++ write_radio_reg(pi, addr, (rval & val)); ++} ++ ++void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) ++{ ++ u16 rval; ++ ++ rval = read_radio_reg(pi, addr); ++ write_radio_reg(pi, addr, (rval | val)); ++} ++ ++void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask) ++{ ++ u16 rval; ++ ++ rval = read_radio_reg(pi, addr); ++ write_radio_reg(pi, addr, (rval ^ mask)); ++} ++ ++void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val) ++{ ++ u16 rval; ++ ++ rval = read_radio_reg(pi, addr); ++ write_radio_reg(pi, addr, (rval & ~mask) | (val & mask)); ++} ++ ++void write_phy_channel_reg(struct brcms_phy *pi, uint val) ++{ ++ W_REG(&pi->regs->phychannel, val); ++} ++ ++u16 read_phy_reg(struct brcms_phy *pi, u16 addr) ++{ ++ struct d11regs __iomem *regs; ++ ++ regs = pi->regs; ++ ++ W_REG_FLUSH(®s->phyregaddr, addr); ++ ++ pi->phy_wreg = 0; ++ return R_REG(®s->phyregdata); ++} ++ ++void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) ++{ ++ struct d11regs __iomem *regs; ++ ++ regs = pi->regs; ++ ++#ifdef CONFIG_BCM47XX ++ W_REG_FLUSH(®s->phyregaddr, addr); ++ W_REG(®s->phyregdata, val); ++ if (addr == 0x72) ++ (void)R_REG(®s->phyregdata); ++#else ++ W_REG((u32 __iomem *)(®s->phyregaddr), addr | (val << 16)); ++ if (++pi->phy_wreg >= pi->phy_wreg_limit) { ++ pi->phy_wreg = 0; ++ (void)R_REG(®s->phyversion); ++ } ++#endif ++} ++ ++void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) ++{ ++ struct d11regs __iomem *regs; ++ ++ regs = pi->regs; ++ ++ W_REG_FLUSH(®s->phyregaddr, addr); ++ ++ W_REG(®s->phyregdata, (R_REG(®s->phyregdata) & val)); ++ pi->phy_wreg = 0; ++} ++ ++void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) ++{ ++ struct d11regs __iomem *regs; ++ ++ regs = pi->regs; ++ ++ W_REG_FLUSH(®s->phyregaddr, addr); ++ ++ W_REG(®s->phyregdata, (R_REG(®s->phyregdata) | val)); ++ pi->phy_wreg = 0; ++} ++ ++void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val) ++{ ++ struct d11regs __iomem *regs; ++ ++ regs = pi->regs; ++ ++ W_REG_FLUSH(®s->phyregaddr, addr); ++ ++ W_REG(®s->phyregdata, ++ ((R_REG(®s->phyregdata) & ~mask) | (val & mask))); ++ pi->phy_wreg = 0; ++} ++ ++static void wlc_set_phy_uninitted(struct brcms_phy *pi) ++{ ++ int i, j; ++ ++ pi->initialized = false; ++ ++ pi->tx_vos = 0xffff; ++ pi->nrssi_table_delta = 0x7fffffff; ++ pi->rc_cal = 0xffff; ++ pi->mintxbias = 0xffff; ++ pi->txpwridx = -1; ++ if (ISNPHY(pi)) { ++ pi->phy_spuravoid = SPURAVOID_DISABLE; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) ++ && NREV_LT(pi->pubpi.phy_rev, 7)) ++ pi->phy_spuravoid = SPURAVOID_AUTO; ++ ++ pi->nphy_papd_skip = 0; ++ pi->nphy_papd_epsilon_offset[0] = 0xf588; ++ pi->nphy_papd_epsilon_offset[1] = 0xf588; ++ pi->nphy_txpwr_idx[0] = 128; ++ pi->nphy_txpwr_idx[1] = 128; ++ pi->nphy_txpwrindex[0].index_internal = 40; ++ pi->nphy_txpwrindex[1].index_internal = 40; ++ pi->phy_pabias = 0; ++ } else { ++ pi->phy_spuravoid = SPURAVOID_AUTO; ++ } ++ pi->radiopwr = 0xffff; ++ for (i = 0; i < STATIC_NUM_RF; i++) { ++ for (j = 0; j < STATIC_NUM_BB; j++) ++ pi->stats_11b_txpower[i][j] = -1; ++ } ++} ++ ++struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp) ++{ ++ struct shared_phy *sh; ++ ++ sh = kzalloc(sizeof(struct shared_phy), GFP_ATOMIC); ++ if (sh == NULL) ++ return NULL; ++ ++ sh->sih = shp->sih; ++ sh->physhim = shp->physhim; ++ sh->unit = shp->unit; ++ sh->corerev = shp->corerev; ++ ++ sh->vid = shp->vid; ++ sh->did = shp->did; ++ sh->chip = shp->chip; ++ sh->chiprev = shp->chiprev; ++ sh->chippkg = shp->chippkg; ++ sh->sromrev = shp->sromrev; ++ sh->boardtype = shp->boardtype; ++ sh->boardrev = shp->boardrev; ++ sh->boardvendor = shp->boardvendor; ++ sh->boardflags = shp->boardflags; ++ sh->boardflags2 = shp->boardflags2; ++ sh->buscorerev = shp->buscorerev; ++ ++ sh->fast_timer = PHY_SW_TIMER_FAST; ++ sh->slow_timer = PHY_SW_TIMER_SLOW; ++ sh->glacial_timer = PHY_SW_TIMER_GLACIAL; ++ ++ sh->rssi_mode = RSSI_ANT_MERGE_MAX; ++ ++ return sh; ++} ++ ++static void wlc_phy_timercb_phycal(struct brcms_phy *pi) ++{ ++ uint delay = 5; ++ ++ if (PHY_PERICAL_MPHASE_PENDING(pi)) { ++ if (!pi->sh->up) { ++ wlc_phy_cal_perical_mphase_reset(pi); ++ return; ++ } ++ ++ if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)) { ++ ++ delay = 1000; ++ wlc_phy_cal_perical_mphase_restart(pi); ++ } else ++ wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_AUTO); ++ wlapi_add_timer(pi->phycal_timer, delay, 0); ++ return; ++ } ++ ++} ++ ++static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi) ++{ ++ u32 ver; ++ ++ ver = read_radio_id(pi); ++ ++ return ver; ++} ++ ++struct brcms_phy_pub * ++wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs, ++ int bandtype, struct wiphy *wiphy) ++{ ++ struct brcms_phy *pi; ++ u32 sflags = 0; ++ uint phyversion; ++ u32 idcode; ++ int i; ++ ++ if (D11REV_IS(sh->corerev, 4)) ++ sflags = SISF_2G_PHY | SISF_5G_PHY; ++ else ++ sflags = ai_core_sflags(sh->sih, 0, 0); ++ ++ if (bandtype == BRCM_BAND_5G) { ++ if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0) ++ return NULL; ++ } ++ ++ pi = sh->phy_head; ++ if ((sflags & SISF_DB_PHY) && pi) { ++ wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags); ++ pi->refcnt++; ++ return &pi->pubpi_ro; ++ } ++ ++ pi = kzalloc(sizeof(struct brcms_phy), GFP_ATOMIC); ++ if (pi == NULL) ++ return NULL; ++ pi->wiphy = wiphy; ++ pi->regs = regs; ++ pi->sh = sh; ++ pi->phy_init_por = true; ++ pi->phy_wreg_limit = PHY_WREG_LIMIT; ++ ++ pi->txpwr_percent = 100; ++ ++ pi->do_initcal = true; ++ ++ pi->phycal_tempdelta = 0; ++ ++ if (bandtype == BRCM_BAND_2G && (sflags & SISF_2G_PHY)) ++ pi->pubpi.coreflags = SICF_GMODE; ++ ++ wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags); ++ phyversion = R_REG(&pi->regs->phyversion); ++ ++ pi->pubpi.phy_type = PHY_TYPE(phyversion); ++ pi->pubpi.phy_rev = phyversion & PV_PV_MASK; ++ ++ if (pi->pubpi.phy_type == PHY_TYPE_LCNXN) { ++ pi->pubpi.phy_type = PHY_TYPE_N; ++ pi->pubpi.phy_rev += LCNXN_BASEREV; ++ } ++ pi->pubpi.phy_corenum = PHY_CORE_NUM_2; ++ pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT; ++ ++ if (!pi->pubpi.phy_type == PHY_TYPE_N && ++ !pi->pubpi.phy_type == PHY_TYPE_LCN) ++ goto err; ++ ++ if (bandtype == BRCM_BAND_5G) { ++ if (!ISNPHY(pi)) ++ goto err; ++ } else if (!ISNPHY(pi) && !ISLCNPHY(pi)) { ++ goto err; ++ } ++ ++ wlc_phy_anacore((struct brcms_phy_pub *) pi, ON); ++ ++ idcode = wlc_phy_get_radio_ver(pi); ++ pi->pubpi.radioid = ++ (idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT; ++ pi->pubpi.radiorev = ++ (idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT; ++ pi->pubpi.radiover = ++ (idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT; ++ if (!VALID_RADIO(pi, pi->pubpi.radioid)) ++ goto err; ++ ++ wlc_phy_switch_radio((struct brcms_phy_pub *) pi, OFF); ++ ++ wlc_set_phy_uninitted(pi); ++ ++ pi->bw = WL_CHANSPEC_BW_20; ++ pi->radio_chanspec = (bandtype == BRCM_BAND_2G) ? ++ ch20mhz_chspec(1) : ch20mhz_chspec(36); ++ ++ pi->rxiq_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY; ++ pi->rxiq_antsel = ANT_RX_DIV_DEF; ++ ++ pi->watchdog_override = true; ++ ++ pi->cal_type_override = PHY_PERICAL_AUTO; ++ ++ pi->nphy_saved_noisevars.bufcount = 0; ++ ++ if (ISNPHY(pi)) ++ pi->min_txpower = PHY_TXPWR_MIN_NPHY; ++ else ++ pi->min_txpower = PHY_TXPWR_MIN; ++ ++ pi->sh->phyrxchain = 0x3; ++ ++ pi->rx2tx_biasentry = -1; ++ ++ pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP; ++ pi->phy_txcore_enable_temp = ++ PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP; ++ pi->phy_tempsense_offset = 0; ++ pi->phy_txcore_heatedup = false; ++ ++ pi->nphy_lastcal_temp = -50; ++ ++ pi->phynoise_polling = true; ++ if (ISNPHY(pi) || ISLCNPHY(pi)) ++ pi->phynoise_polling = false; ++ ++ for (i = 0; i < TXP_NUM_RATES; i++) { ++ pi->txpwr_limit[i] = BRCMS_TXPWR_MAX; ++ pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX; ++ pi->tx_user_target[i] = BRCMS_TXPWR_MAX; ++ } ++ ++ pi->radiopwr_override = RADIOPWR_OVERRIDE_DEF; ++ ++ pi->user_txpwr_at_rfport = false; ++ ++ if (ISNPHY(pi)) { ++ ++ pi->phycal_timer = wlapi_init_timer(pi->sh->physhim, ++ wlc_phy_timercb_phycal, ++ pi, "phycal"); ++ if (!pi->phycal_timer) ++ goto err; ++ ++ if (!wlc_phy_attach_nphy(pi)) ++ goto err; ++ ++ } else if (ISLCNPHY(pi)) { ++ if (!wlc_phy_attach_lcnphy(pi)) ++ goto err; ++ ++ } ++ ++ pi->refcnt++; ++ pi->next = pi->sh->phy_head; ++ sh->phy_head = pi; ++ ++ memcpy(&pi->pubpi_ro, &pi->pubpi, sizeof(struct brcms_phy_pub)); ++ ++ return &pi->pubpi_ro; ++ ++err: ++ kfree(pi); ++ return NULL; ++} ++ ++void wlc_phy_detach(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (pih) { ++ if (--pi->refcnt) ++ return; ++ ++ if (pi->phycal_timer) { ++ wlapi_free_timer(pi->phycal_timer); ++ pi->phycal_timer = NULL; ++ } ++ ++ if (pi->sh->phy_head == pi) ++ pi->sh->phy_head = pi->next; ++ else if (pi->sh->phy_head->next == pi) ++ pi->sh->phy_head->next = NULL; ++ ++ if (pi->pi_fptr.detach) ++ (pi->pi_fptr.detach)(pi); ++ ++ kfree(pi); ++ } ++} ++ ++bool ++wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype, u16 *phyrev, ++ u16 *radioid, u16 *radiover) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ *phytype = (u16) pi->pubpi.phy_type; ++ *phyrev = (u16) pi->pubpi.phy_rev; ++ *radioid = pi->pubpi.radioid; ++ *radiover = pi->pubpi.radiorev; ++ ++ return true; ++} ++ ++bool wlc_phy_get_encore(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ return pi->pubpi.abgphy_encore; ++} ++ ++u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ return pi->pubpi.coreflags; ++} ++ ++void wlc_phy_anacore(struct brcms_phy_pub *pih, bool on) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (ISNPHY(pi)) { ++ if (on) { ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ write_phy_reg(pi, 0xa6, 0x0d); ++ write_phy_reg(pi, 0x8f, 0x0); ++ write_phy_reg(pi, 0xa7, 0x0d); ++ write_phy_reg(pi, 0xa5, 0x0); ++ } else { ++ write_phy_reg(pi, 0xa5, 0x0); ++ } ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ write_phy_reg(pi, 0x8f, 0x07ff); ++ write_phy_reg(pi, 0xa6, 0x0fd); ++ write_phy_reg(pi, 0xa5, 0x07ff); ++ write_phy_reg(pi, 0xa7, 0x0fd); ++ } else { ++ write_phy_reg(pi, 0xa5, 0x7fff); ++ } ++ } ++ } else if (ISLCNPHY(pi)) { ++ if (on) { ++ and_phy_reg(pi, 0x43b, ++ ~((0x1 << 0) | (0x1 << 1) | (0x1 << 2))); ++ } else { ++ or_phy_reg(pi, 0x43c, ++ (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); ++ or_phy_reg(pi, 0x43b, ++ (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); ++ } ++ } ++} ++ ++u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ u32 phy_bw_clkbits = 0; ++ ++ if (pi && (ISNPHY(pi) || ISLCNPHY(pi))) { ++ switch (pi->bw) { ++ case WL_CHANSPEC_BW_10: ++ phy_bw_clkbits = SICF_BW10; ++ break; ++ case WL_CHANSPEC_BW_20: ++ phy_bw_clkbits = SICF_BW20; ++ break; ++ case WL_CHANSPEC_BW_40: ++ phy_bw_clkbits = SICF_BW40; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ return phy_bw_clkbits; ++} ++ ++void wlc_phy_por_inform(struct brcms_phy_pub *ppi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ pi->phy_init_por = true; ++} ++ ++void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ pi->edcrs_threshold_lock = lock; ++ ++ write_phy_reg(pi, 0x22c, 0x46b); ++ write_phy_reg(pi, 0x22d, 0x46b); ++ write_phy_reg(pi, 0x22e, 0x3c0); ++ write_phy_reg(pi, 0x22f, 0x3c0); ++} ++ ++void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ pi->do_initcal = initcal; ++} ++ ++void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *pih, bool newstate) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (!pi || !pi->sh) ++ return; ++ ++ pi->sh->clk = newstate; ++} ++ ++void wlc_phy_hw_state_upd(struct brcms_phy_pub *pih, bool newstate) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (!pi || !pi->sh) ++ return; ++ ++ pi->sh->up = newstate; ++} ++ ++void wlc_phy_init(struct brcms_phy_pub *pih, u16 chanspec) ++{ ++ u32 mc; ++ void (*phy_init)(struct brcms_phy *) = NULL; ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (pi->init_in_progress) ++ return; ++ ++ pi->init_in_progress = true; ++ ++ pi->radio_chanspec = chanspec; ++ ++ mc = R_REG(&pi->regs->maccontrol); ++ if (WARN(mc & MCTL_EN_MAC, "HW error MAC running on init")) ++ return; ++ ++ if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) ++ pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC; ++ ++ if (WARN(!(ai_core_sflags(pi->sh->sih, 0, 0) & SISF_FCLKA), ++ "HW error SISF_FCLKA\n")) ++ return; ++ ++ phy_init = pi->pi_fptr.init; ++ ++ if (phy_init == NULL) ++ return; ++ ++ wlc_phy_anacore(pih, ON); ++ ++ if (CHSPEC_BW(pi->radio_chanspec) != pi->bw) ++ wlapi_bmac_bw_set(pi->sh->physhim, ++ CHSPEC_BW(pi->radio_chanspec)); ++ ++ pi->nphy_gain_boost = true; ++ ++ wlc_phy_switch_radio((struct brcms_phy_pub *) pi, ON); ++ ++ (*phy_init)(pi); ++ ++ pi->phy_init_por = false; ++ ++ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) ++ wlc_phy_do_dummy_tx(pi, true, OFF); ++ ++ if (!(ISNPHY(pi))) ++ wlc_phy_txpower_update_shm(pi); ++ ++ wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi, pi->sh->rx_antdiv); ++ ++ pi->init_in_progress = false; ++} ++ ++void wlc_phy_cal_init(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ void (*cal_init)(struct brcms_phy *) = NULL; ++ ++ if (WARN((R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) != 0, ++ "HW error: MAC enabled during phy cal\n")) ++ return; ++ ++ if (!pi->initialized) { ++ cal_init = pi->pi_fptr.calinit; ++ if (cal_init) ++ (*cal_init)(pi); ++ ++ pi->initialized = true; ++ } ++} ++ ++int wlc_phy_down(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ int callbacks = 0; ++ ++ if (pi->phycal_timer ++ && !wlapi_del_timer(pi->phycal_timer)) ++ callbacks++; ++ ++ pi->nphy_iqcal_chanspec_2G = 0; ++ pi->nphy_iqcal_chanspec_5G = 0; ++ ++ return callbacks; ++} ++ ++void ++wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset, ++ u16 tblAddr, u16 tblDataHi, u16 tblDataLo) ++{ ++ write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset); ++ ++ pi->tbl_data_hi = tblDataHi; ++ pi->tbl_data_lo = tblDataLo; ++ ++ if (pi->sh->chip == BCM43224_CHIP_ID && ++ pi->sh->chiprev == 1) { ++ pi->tbl_addr = tblAddr; ++ pi->tbl_save_id = tbl_id; ++ pi->tbl_save_offset = tbl_offset; ++ } ++} ++ ++void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val) ++{ ++ if ((pi->sh->chip == BCM43224_CHIP_ID) && ++ (pi->sh->chiprev == 1) && ++ (pi->tbl_save_id == NPHY_TBL_ID_ANTSWCTRLLUT)) { ++ read_phy_reg(pi, pi->tbl_data_lo); ++ ++ write_phy_reg(pi, pi->tbl_addr, ++ (pi->tbl_save_id << 10) | pi->tbl_save_offset); ++ pi->tbl_save_offset++; ++ } ++ ++ if (width == 32) { ++ write_phy_reg(pi, pi->tbl_data_hi, (u16) (val >> 16)); ++ write_phy_reg(pi, pi->tbl_data_lo, (u16) val); ++ } else { ++ write_phy_reg(pi, pi->tbl_data_lo, (u16) val); ++ } ++} ++ ++void ++wlc_phy_write_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info, ++ u16 tblAddr, u16 tblDataHi, u16 tblDataLo) ++{ ++ uint idx; ++ uint tbl_id = ptbl_info->tbl_id; ++ uint tbl_offset = ptbl_info->tbl_offset; ++ uint tbl_width = ptbl_info->tbl_width; ++ const u8 *ptbl_8b = (const u8 *)ptbl_info->tbl_ptr; ++ const u16 *ptbl_16b = (const u16 *)ptbl_info->tbl_ptr; ++ const u32 *ptbl_32b = (const u32 *)ptbl_info->tbl_ptr; ++ ++ write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset); ++ ++ for (idx = 0; idx < ptbl_info->tbl_len; idx++) { ++ ++ if ((pi->sh->chip == BCM43224_CHIP_ID) && ++ (pi->sh->chiprev == 1) && ++ (tbl_id == NPHY_TBL_ID_ANTSWCTRLLUT)) { ++ read_phy_reg(pi, tblDataLo); ++ ++ write_phy_reg(pi, tblAddr, ++ (tbl_id << 10) | (tbl_offset + idx)); ++ } ++ ++ if (tbl_width == 32) { ++ write_phy_reg(pi, tblDataHi, ++ (u16) (ptbl_32b[idx] >> 16)); ++ write_phy_reg(pi, tblDataLo, (u16) ptbl_32b[idx]); ++ } else if (tbl_width == 16) { ++ write_phy_reg(pi, tblDataLo, ptbl_16b[idx]); ++ } else { ++ write_phy_reg(pi, tblDataLo, ptbl_8b[idx]); ++ } ++ } ++} ++ ++void ++wlc_phy_read_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info, ++ u16 tblAddr, u16 tblDataHi, u16 tblDataLo) ++{ ++ uint idx; ++ uint tbl_id = ptbl_info->tbl_id; ++ uint tbl_offset = ptbl_info->tbl_offset; ++ uint tbl_width = ptbl_info->tbl_width; ++ u8 *ptbl_8b = (u8 *)ptbl_info->tbl_ptr; ++ u16 *ptbl_16b = (u16 *)ptbl_info->tbl_ptr; ++ u32 *ptbl_32b = (u32 *)ptbl_info->tbl_ptr; ++ ++ write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset); ++ ++ for (idx = 0; idx < ptbl_info->tbl_len; idx++) { ++ ++ if ((pi->sh->chip == BCM43224_CHIP_ID) && ++ (pi->sh->chiprev == 1)) { ++ (void)read_phy_reg(pi, tblDataLo); ++ ++ write_phy_reg(pi, tblAddr, ++ (tbl_id << 10) | (tbl_offset + idx)); ++ } ++ ++ if (tbl_width == 32) { ++ ptbl_32b[idx] = read_phy_reg(pi, tblDataLo); ++ ptbl_32b[idx] |= (read_phy_reg(pi, tblDataHi) << 16); ++ } else if (tbl_width == 16) { ++ ptbl_16b[idx] = read_phy_reg(pi, tblDataLo); ++ } else { ++ ptbl_8b[idx] = (u8) read_phy_reg(pi, tblDataLo); ++ } ++ } ++} ++ ++uint ++wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi, ++ struct radio_20xx_regs *radioregs) ++{ ++ uint i = 0; ++ ++ do { ++ if (radioregs[i].do_init) ++ write_radio_reg(pi, radioregs[i].address, ++ (u16) radioregs[i].init); ++ ++ i++; ++ } while (radioregs[i].address != 0xffff); ++ ++ return i; ++} ++ ++uint ++wlc_phy_init_radio_regs(struct brcms_phy *pi, ++ const struct radio_regs *radioregs, ++ u16 core_offset) ++{ ++ uint i = 0; ++ uint count = 0; ++ ++ do { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (radioregs[i].do_init_a) { ++ write_radio_reg(pi, ++ radioregs[i]. ++ address | core_offset, ++ (u16) radioregs[i].init_a); ++ if (ISNPHY(pi) && (++count % 4 == 0)) ++ BRCMS_PHY_WAR_PR51571(pi); ++ } ++ } else { ++ if (radioregs[i].do_init_g) { ++ write_radio_reg(pi, ++ radioregs[i]. ++ address | core_offset, ++ (u16) radioregs[i].init_g); ++ if (ISNPHY(pi) && (++count % 4 == 0)) ++ BRCMS_PHY_WAR_PR51571(pi); ++ } ++ } ++ ++ i++; ++ } while (radioregs[i].address != 0xffff); ++ ++ return i; ++} ++ ++void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on) ++{ ++#define DUMMY_PKT_LEN 20 ++ struct d11regs __iomem *regs = pi->regs; ++ int i, count; ++ u8 ofdmpkt[DUMMY_PKT_LEN] = { ++ 0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 ++ }; ++ u8 cckpkt[DUMMY_PKT_LEN] = { ++ 0x6e, 0x84, 0x0b, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 ++ }; ++ u32 *dummypkt; ++ ++ dummypkt = (u32 *) (ofdm ? ofdmpkt : cckpkt); ++ wlapi_bmac_write_template_ram(pi->sh->physhim, 0, DUMMY_PKT_LEN, ++ dummypkt); ++ ++ W_REG(®s->xmtsel, 0); ++ ++ if (D11REV_GE(pi->sh->corerev, 11)) ++ W_REG(®s->wepctl, 0x100); ++ else ++ W_REG(®s->wepctl, 0); ++ ++ W_REG(®s->txe_phyctl, (ofdm ? 1 : 0) | PHY_TXC_ANT_0); ++ if (ISNPHY(pi) || ISLCNPHY(pi)) ++ W_REG(®s->txe_phyctl1, 0x1A02); ++ ++ W_REG(®s->txe_wm_0, 0); ++ W_REG(®s->txe_wm_1, 0); ++ ++ W_REG(®s->xmttplatetxptr, 0); ++ W_REG(®s->xmttxcnt, DUMMY_PKT_LEN); ++ ++ W_REG(®s->xmtsel, ((8 << 8) | (1 << 5) | (1 << 2) | 2)); ++ ++ W_REG(®s->txe_ctl, 0); ++ ++ if (!pa_on) { ++ if (ISNPHY(pi)) ++ wlc_phy_pa_override_nphy(pi, OFF); ++ } ++ ++ if (ISNPHY(pi) || ISLCNPHY(pi)) ++ W_REG(®s->txe_aux, 0xD0); ++ else ++ W_REG(®s->txe_aux, ((1 << 5) | (1 << 4))); ++ ++ (void)R_REG(®s->txe_aux); ++ ++ i = 0; ++ count = ofdm ? 30 : 250; ++ while ((i++ < count) ++ && (R_REG(®s->txe_status) & (1 << 7))) ++ udelay(10); ++ ++ i = 0; ++ ++ while ((i++ < 10) ++ && ((R_REG(®s->txe_status) & (1 << 10)) == 0)) ++ udelay(10); ++ ++ i = 0; ++ ++ while ((i++ < 10) && ((R_REG(®s->ifsstat) & (1 << 8)))) ++ udelay(10); ++ ++ if (!pa_on) { ++ if (ISNPHY(pi)) ++ wlc_phy_pa_override_nphy(pi, ON); ++ } ++} ++ ++void wlc_phy_hold_upd(struct brcms_phy_pub *pih, u32 id, bool set) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (set) ++ mboolset(pi->measure_hold, id); ++ else ++ mboolclr(pi->measure_hold, id); ++ ++ return; ++} ++ ++void wlc_phy_mute_upd(struct brcms_phy_pub *pih, bool mute, u32 flags) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (mute) ++ mboolset(pi->measure_hold, PHY_HOLD_FOR_MUTE); ++ else ++ mboolclr(pi->measure_hold, PHY_HOLD_FOR_MUTE); ++ ++ if (!mute && (flags & PHY_MUTE_FOR_PREISM)) ++ pi->nphy_perical_last = pi->sh->now - pi->sh->glacial_timer; ++ return; ++} ++ ++void wlc_phy_clear_tssi(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (ISNPHY(pi)) { ++ return; ++ } else { ++ wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_0, NULL_TSSI_W); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_1, NULL_TSSI_W); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_0, NULL_TSSI_W); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_1, NULL_TSSI_W); ++ } ++} ++ ++static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi) ++{ ++ return false; ++} ++ ++void wlc_phy_switch_radio(struct brcms_phy_pub *pih, bool on) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ (void)R_REG(&pi->regs->maccontrol); ++ ++ if (ISNPHY(pi)) { ++ wlc_phy_switch_radio_nphy(pi, on); ++ } else if (ISLCNPHY(pi)) { ++ if (on) { ++ and_phy_reg(pi, 0x44c, ++ ~((0x1 << 8) | ++ (0x1 << 9) | ++ (0x1 << 10) | (0x1 << 11) | (0x1 << 12))); ++ and_phy_reg(pi, 0x4b0, ~((0x1 << 3) | (0x1 << 11))); ++ and_phy_reg(pi, 0x4f9, ~(0x1 << 3)); ++ } else { ++ and_phy_reg(pi, 0x44d, ++ ~((0x1 << 10) | ++ (0x1 << 11) | ++ (0x1 << 12) | (0x1 << 13) | (0x1 << 14))); ++ or_phy_reg(pi, 0x44c, ++ (0x1 << 8) | ++ (0x1 << 9) | ++ (0x1 << 10) | (0x1 << 11) | (0x1 << 12)); ++ ++ and_phy_reg(pi, 0x4b7, ~((0x7f << 8))); ++ and_phy_reg(pi, 0x4b1, ~((0x1 << 13))); ++ or_phy_reg(pi, 0x4b0, (0x1 << 3) | (0x1 << 11)); ++ and_phy_reg(pi, 0x4fa, ~((0x1 << 3))); ++ or_phy_reg(pi, 0x4f9, (0x1 << 3)); ++ } ++ } ++} ++ ++u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ return pi->bw; ++} ++ ++void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ pi->bw = bw; ++} ++ ++void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, u16 newch) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ pi->radio_chanspec = newch; ++ ++} ++ ++u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ return pi->radio_chanspec; ++} ++ ++void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, u16 chanspec) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ u16 m_cur_channel; ++ void (*chanspec_set)(struct brcms_phy *, u16) = NULL; ++ m_cur_channel = CHSPEC_CHANNEL(chanspec); ++ if (CHSPEC_IS5G(chanspec)) ++ m_cur_channel |= D11_CURCHANNEL_5G; ++ if (CHSPEC_IS40(chanspec)) ++ m_cur_channel |= D11_CURCHANNEL_40; ++ wlapi_bmac_write_shm(pi->sh->physhim, M_CURCHANNEL, m_cur_channel); ++ ++ chanspec_set = pi->pi_fptr.chanset; ++ if (chanspec_set) ++ (*chanspec_set)(pi, chanspec); ++ ++} ++ ++int wlc_phy_chanspec_freq2bandrange_lpssn(uint freq) ++{ ++ int range = -1; ++ ++ if (freq < 2500) ++ range = WL_CHAN_FREQ_RANGE_2G; ++ else if (freq <= 5320) ++ range = WL_CHAN_FREQ_RANGE_5GL; ++ else if (freq <= 5700) ++ range = WL_CHAN_FREQ_RANGE_5GM; ++ else ++ range = WL_CHAN_FREQ_RANGE_5GH; ++ ++ return range; ++} ++ ++int wlc_phy_chanspec_bandrange_get(struct brcms_phy *pi, u16 chanspec) ++{ ++ int range = -1; ++ uint channel = CHSPEC_CHANNEL(chanspec); ++ uint freq = wlc_phy_channel2freq(channel); ++ ++ if (ISNPHY(pi)) ++ range = wlc_phy_get_chan_freq_range_nphy(pi, channel); ++ else if (ISLCNPHY(pi)) ++ range = wlc_phy_chanspec_freq2bandrange_lpssn(freq); ++ ++ return range; ++} ++ ++void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi, ++ bool wide_filter) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ pi->channel_14_wide_filter = wide_filter; ++ ++} ++ ++int wlc_phy_channel2freq(uint channel) ++{ ++ uint i; ++ ++ for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) ++ if (chan_info_all[i].chan == channel) ++ return chan_info_all[i].freq; ++ return 0; ++} ++ ++void ++wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band, ++ struct brcms_chanvec *channels) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ uint i; ++ uint channel; ++ ++ memset(channels, 0, sizeof(struct brcms_chanvec)); ++ ++ for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) { ++ channel = chan_info_all[i].chan; ++ ++ if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM) ++ && (channel <= LAST_REF5_CHANNUM)) ++ continue; ++ ++ if ((band == BRCM_BAND_2G && channel <= CH_MAX_2G_CHANNEL) || ++ (band == BRCM_BAND_5G && channel > CH_MAX_2G_CHANNEL)) ++ setbit(channels->vec, channel); ++ } ++} ++ ++u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ uint i; ++ uint channel; ++ u16 chspec; ++ ++ for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) { ++ channel = chan_info_all[i].chan; ++ ++ if (ISNPHY(pi) && pi->bw == WL_CHANSPEC_BW_40) { ++ uint j; ++ ++ for (j = 0; j < ARRAY_SIZE(chan_info_all); j++) { ++ if (chan_info_all[j].chan == ++ channel + CH_10MHZ_APART) ++ break; ++ } ++ ++ if (j == ARRAY_SIZE(chan_info_all)) ++ continue; ++ ++ channel = upper_20_sb(channel); ++ chspec = channel | WL_CHANSPEC_BW_40 | ++ WL_CHANSPEC_CTL_SB_LOWER; ++ if (band == BRCM_BAND_2G) ++ chspec |= WL_CHANSPEC_BAND_2G; ++ else ++ chspec |= WL_CHANSPEC_BAND_5G; ++ } else ++ chspec = ch20mhz_chspec(channel); ++ ++ if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM) ++ && (channel <= LAST_REF5_CHANNUM)) ++ continue; ++ ++ if ((band == BRCM_BAND_2G && channel <= CH_MAX_2G_CHANNEL) || ++ (band == BRCM_BAND_5G && channel > CH_MAX_2G_CHANNEL)) ++ return chspec; ++ } ++ ++ return (u16) INVCHANSPEC; ++} ++ ++int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, bool *override) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ *qdbm = pi->tx_user_target[0]; ++ if (override != NULL) ++ *override = pi->txpwroverride; ++ return 0; ++} ++ ++void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi, ++ struct txpwr_limits *txpwr) ++{ ++ bool mac_enabled = false; ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ memcpy(&pi->tx_user_target[TXP_FIRST_CCK], ++ &txpwr->cck[0], BRCMS_NUM_RATES_CCK); ++ ++ memcpy(&pi->tx_user_target[TXP_FIRST_OFDM], ++ &txpwr->ofdm[0], BRCMS_NUM_RATES_OFDM); ++ memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_20_CDD], ++ &txpwr->ofdm_cdd[0], BRCMS_NUM_RATES_OFDM); ++ ++ memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_SISO], ++ &txpwr->ofdm_40_siso[0], BRCMS_NUM_RATES_OFDM); ++ memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_CDD], ++ &txpwr->ofdm_40_cdd[0], BRCMS_NUM_RATES_OFDM); ++ ++ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SISO], ++ &txpwr->mcs_20_siso[0], BRCMS_NUM_RATES_MCS_1_STREAM); ++ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_CDD], ++ &txpwr->mcs_20_cdd[0], BRCMS_NUM_RATES_MCS_1_STREAM); ++ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_STBC], ++ &txpwr->mcs_20_stbc[0], BRCMS_NUM_RATES_MCS_1_STREAM); ++ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SDM], ++ &txpwr->mcs_20_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM); ++ ++ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SISO], ++ &txpwr->mcs_40_siso[0], BRCMS_NUM_RATES_MCS_1_STREAM); ++ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_CDD], ++ &txpwr->mcs_40_cdd[0], BRCMS_NUM_RATES_MCS_1_STREAM); ++ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_STBC], ++ &txpwr->mcs_40_stbc[0], BRCMS_NUM_RATES_MCS_1_STREAM); ++ memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SDM], ++ &txpwr->mcs_40_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM); ++ ++ if (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ++ mac_enabled = true; ++ ++ if (mac_enabled) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ wlc_phy_txpower_recalc_target(pi); ++ wlc_phy_cal_txpower_recalc_sw(pi); ++ ++ if (mac_enabled) ++ wlapi_enable_mac(pi->sh->physhim); ++} ++ ++int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ int i; ++ ++ if (qdbm > 127) ++ return -EINVAL; ++ ++ for (i = 0; i < TXP_NUM_RATES; i++) ++ pi->tx_user_target[i] = (u8) qdbm; ++ ++ pi->txpwroverride = false; ++ ++ if (pi->sh->up) { ++ if (!SCAN_INPROG_PHY(pi)) { ++ bool suspend; ++ ++ suspend = (0 == (R_REG(&pi->regs->maccontrol) & ++ MCTL_EN_MAC)); ++ ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ wlc_phy_txpower_recalc_target(pi); ++ wlc_phy_cal_txpower_recalc_sw(pi); ++ ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++ } ++ } ++ return 0; ++} ++ ++void ++wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint channel, u8 *min_pwr, ++ u8 *max_pwr, int txp_rate_idx) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ uint i; ++ ++ *min_pwr = pi->min_txpower * BRCMS_TXPWR_DB_FACTOR; ++ ++ if (ISNPHY(pi)) { ++ if (txp_rate_idx < 0) ++ txp_rate_idx = TXP_FIRST_CCK; ++ wlc_phy_txpower_sromlimit_get_nphy(pi, channel, max_pwr, ++ (u8) txp_rate_idx); ++ ++ } else if ((channel <= CH_MAX_2G_CHANNEL)) { ++ if (txp_rate_idx < 0) ++ txp_rate_idx = TXP_FIRST_CCK; ++ *max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx]; ++ } else { ++ ++ *max_pwr = BRCMS_TXPWR_MAX; ++ ++ if (txp_rate_idx < 0) ++ txp_rate_idx = TXP_FIRST_OFDM; ++ ++ for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) { ++ if (channel == chan_info_all[i].chan) ++ break; ++ } ++ ++ if (pi->hwtxpwr) { ++ *max_pwr = pi->hwtxpwr[i]; ++ } else { ++ ++ if ((i >= FIRST_MID_5G_CHAN) && (i <= LAST_MID_5G_CHAN)) ++ *max_pwr = ++ pi->tx_srom_max_rate_5g_mid[txp_rate_idx]; ++ if ((i >= FIRST_HIGH_5G_CHAN) ++ && (i <= LAST_HIGH_5G_CHAN)) ++ *max_pwr = ++ pi->tx_srom_max_rate_5g_hi[txp_rate_idx]; ++ if ((i >= FIRST_LOW_5G_CHAN) && (i <= LAST_LOW_5G_CHAN)) ++ *max_pwr = ++ pi->tx_srom_max_rate_5g_low[txp_rate_idx]; ++ } ++ } ++} ++ ++void ++wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, uint chan, ++ u8 *max_txpwr, u8 *min_txpwr) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ u8 tx_pwr_max = 0; ++ u8 tx_pwr_min = 255; ++ u8 max_num_rate; ++ u8 maxtxpwr, mintxpwr, rate, pactrl; ++ ++ pactrl = 0; ++ ++ max_num_rate = ISNPHY(pi) ? TXP_NUM_RATES : ++ ISLCNPHY(pi) ? (TXP_LAST_SISO_MCS_20 + ++ 1) : (TXP_LAST_OFDM + 1); ++ ++ for (rate = 0; rate < max_num_rate; rate++) { ++ ++ wlc_phy_txpower_sromlimit(ppi, chan, &mintxpwr, &maxtxpwr, ++ rate); ++ ++ maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0; ++ ++ maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0; ++ ++ tx_pwr_max = max(tx_pwr_max, maxtxpwr); ++ tx_pwr_min = min(tx_pwr_min, maxtxpwr); ++ } ++ *max_txpwr = tx_pwr_max; ++ *min_txpwr = tx_pwr_min; ++} ++ ++void ++wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi, uint bandunit, ++ s32 *max_pwr, s32 *min_pwr, u32 *step_pwr) ++{ ++ return; ++} ++ ++u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ return pi->tx_power_min; ++} ++ ++u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ return pi->tx_power_max; ++} ++ ++static s8 wlc_phy_env_measure_vbat(struct brcms_phy *pi) ++{ ++ if (ISLCNPHY(pi)) ++ return wlc_lcnphy_vbatsense(pi, 0); ++ else ++ return 0; ++} ++ ++static s8 wlc_phy_env_measure_temperature(struct brcms_phy *pi) ++{ ++ if (ISLCNPHY(pi)) ++ return wlc_lcnphy_tempsense_degree(pi, 0); ++ else ++ return 0; ++} ++ ++static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy *pi, u32 band) ++{ ++ u8 i; ++ s8 temp, vbat; ++ ++ for (i = 0; i < TXP_NUM_RATES; i++) ++ pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX; ++ ++ vbat = wlc_phy_env_measure_vbat(pi); ++ temp = wlc_phy_env_measure_temperature(pi); ++ ++} ++ ++static s8 ++wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band, ++ u8 rate) ++{ ++ s8 offset = 0; ++ ++ if (!pi->user_txpwr_at_rfport) ++ return offset; ++ return offset; ++} ++ ++void wlc_phy_txpower_recalc_target(struct brcms_phy *pi) ++{ ++ u8 maxtxpwr, mintxpwr, rate, pactrl; ++ uint target_chan; ++ u8 tx_pwr_target[TXP_NUM_RATES]; ++ u8 tx_pwr_max = 0; ++ u8 tx_pwr_min = 255; ++ u8 tx_pwr_max_rate_ind = 0; ++ u8 max_num_rate; ++ u8 start_rate = 0; ++ u16 chspec; ++ u32 band = CHSPEC2BAND(pi->radio_chanspec); ++ void (*txpwr_recalc_fn)(struct brcms_phy *) = NULL; ++ ++ chspec = pi->radio_chanspec; ++ if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) ++ target_chan = CHSPEC_CHANNEL(chspec); ++ else if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) ++ target_chan = upper_20_sb(CHSPEC_CHANNEL(chspec)); ++ else ++ target_chan = lower_20_sb(CHSPEC_CHANNEL(chspec)); ++ ++ pactrl = 0; ++ if (ISLCNPHY(pi)) { ++ u32 offset_mcs, i; ++ ++ if (CHSPEC_IS40(pi->radio_chanspec)) { ++ offset_mcs = pi->mcs40_po; ++ for (i = TXP_FIRST_SISO_MCS_20; ++ i <= TXP_LAST_SISO_MCS_20; i++) { ++ pi->tx_srom_max_rate_2g[i - 8] = ++ pi->tx_srom_max_2g - ++ ((offset_mcs & 0xf) * 2); ++ offset_mcs >>= 4; ++ } ++ } else { ++ offset_mcs = pi->mcs20_po; ++ for (i = TXP_FIRST_SISO_MCS_20; ++ i <= TXP_LAST_SISO_MCS_20; i++) { ++ pi->tx_srom_max_rate_2g[i - 8] = ++ pi->tx_srom_max_2g - ++ ((offset_mcs & 0xf) * 2); ++ offset_mcs >>= 4; ++ } ++ } ++ } ++ ++ max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) : ++ ((ISLCNPHY(pi)) ? ++ (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1))); ++ ++ wlc_phy_upd_env_txpwr_rate_limits(pi, band); ++ ++ for (rate = start_rate; rate < max_num_rate; rate++) { ++ ++ tx_pwr_target[rate] = pi->tx_user_target[rate]; ++ ++ if (pi->user_txpwr_at_rfport) ++ tx_pwr_target[rate] += ++ wlc_user_txpwr_antport_to_rfport(pi, ++ target_chan, ++ band, ++ rate); ++ ++ wlc_phy_txpower_sromlimit((struct brcms_phy_pub *) pi, ++ target_chan, ++ &mintxpwr, &maxtxpwr, rate); ++ ++ maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]); ++ ++ maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0; ++ ++ maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0; ++ ++ maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]); ++ ++ if (pi->txpwr_percent <= 100) ++ maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100; ++ ++ tx_pwr_target[rate] = max(maxtxpwr, mintxpwr); ++ ++ tx_pwr_target[rate] = ++ min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]); ++ ++ if (tx_pwr_target[rate] > tx_pwr_max) ++ tx_pwr_max_rate_ind = rate; ++ ++ tx_pwr_max = max(tx_pwr_max, tx_pwr_target[rate]); ++ tx_pwr_min = min(tx_pwr_min, tx_pwr_target[rate]); ++ } ++ ++ memset(pi->tx_power_offset, 0, sizeof(pi->tx_power_offset)); ++ pi->tx_power_max = tx_pwr_max; ++ pi->tx_power_min = tx_pwr_min; ++ pi->tx_power_max_rate_ind = tx_pwr_max_rate_ind; ++ for (rate = 0; rate < max_num_rate; rate++) { ++ ++ pi->tx_power_target[rate] = tx_pwr_target[rate]; ++ ++ if (!pi->hwpwrctrl || ISNPHY(pi)) ++ pi->tx_power_offset[rate] = ++ pi->tx_power_max - pi->tx_power_target[rate]; ++ else ++ pi->tx_power_offset[rate] = ++ pi->tx_power_target[rate] - pi->tx_power_min; ++ } ++ ++ txpwr_recalc_fn = pi->pi_fptr.txpwrrecalc; ++ if (txpwr_recalc_fn) ++ (*txpwr_recalc_fn)(pi); ++} ++ ++static void ++wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr, ++ u16 chanspec) ++{ ++ u8 tmp_txpwr_limit[2 * BRCMS_NUM_RATES_OFDM]; ++ u8 *txpwr_ptr1 = NULL, *txpwr_ptr2 = NULL; ++ int rate_start_index = 0, rate1, rate2, k; ++ ++ for (rate1 = WL_TX_POWER_CCK_FIRST, rate2 = 0; ++ rate2 < WL_TX_POWER_CCK_NUM; rate1++, rate2++) ++ pi->txpwr_limit[rate1] = txpwr->cck[rate2]; ++ ++ for (rate1 = WL_TX_POWER_OFDM_FIRST, rate2 = 0; ++ rate2 < WL_TX_POWER_OFDM_NUM; rate1++, rate2++) ++ pi->txpwr_limit[rate1] = txpwr->ofdm[rate2]; ++ ++ if (ISNPHY(pi)) { ++ ++ for (k = 0; k < 4; k++) { ++ switch (k) { ++ case 0: ++ ++ txpwr_ptr1 = txpwr->mcs_20_siso; ++ txpwr_ptr2 = txpwr->ofdm; ++ rate_start_index = WL_TX_POWER_OFDM_FIRST; ++ break; ++ case 1: ++ ++ txpwr_ptr1 = txpwr->mcs_20_cdd; ++ txpwr_ptr2 = txpwr->ofdm_cdd; ++ rate_start_index = WL_TX_POWER_OFDM20_CDD_FIRST; ++ break; ++ case 2: ++ ++ txpwr_ptr1 = txpwr->mcs_40_siso; ++ txpwr_ptr2 = txpwr->ofdm_40_siso; ++ rate_start_index = ++ WL_TX_POWER_OFDM40_SISO_FIRST; ++ break; ++ case 3: ++ ++ txpwr_ptr1 = txpwr->mcs_40_cdd; ++ txpwr_ptr2 = txpwr->ofdm_40_cdd; ++ rate_start_index = WL_TX_POWER_OFDM40_CDD_FIRST; ++ break; ++ } ++ ++ for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; ++ rate2++) { ++ tmp_txpwr_limit[rate2] = 0; ++ tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] = ++ txpwr_ptr1[rate2]; ++ } ++ wlc_phy_mcs_to_ofdm_powers_nphy( ++ tmp_txpwr_limit, 0, ++ BRCMS_NUM_RATES_OFDM - ++ 1, BRCMS_NUM_RATES_OFDM); ++ for (rate1 = rate_start_index, rate2 = 0; ++ rate2 < BRCMS_NUM_RATES_OFDM; rate1++, rate2++) ++ pi->txpwr_limit[rate1] = ++ min(txpwr_ptr2[rate2], ++ tmp_txpwr_limit[rate2]); ++ } ++ ++ for (k = 0; k < 4; k++) { ++ switch (k) { ++ case 0: ++ ++ txpwr_ptr1 = txpwr->ofdm; ++ txpwr_ptr2 = txpwr->mcs_20_siso; ++ rate_start_index = WL_TX_POWER_MCS20_SISO_FIRST; ++ break; ++ case 1: ++ ++ txpwr_ptr1 = txpwr->ofdm_cdd; ++ txpwr_ptr2 = txpwr->mcs_20_cdd; ++ rate_start_index = WL_TX_POWER_MCS20_CDD_FIRST; ++ break; ++ case 2: ++ ++ txpwr_ptr1 = txpwr->ofdm_40_siso; ++ txpwr_ptr2 = txpwr->mcs_40_siso; ++ rate_start_index = WL_TX_POWER_MCS40_SISO_FIRST; ++ break; ++ case 3: ++ ++ txpwr_ptr1 = txpwr->ofdm_40_cdd; ++ txpwr_ptr2 = txpwr->mcs_40_cdd; ++ rate_start_index = WL_TX_POWER_MCS40_CDD_FIRST; ++ break; ++ } ++ for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM; ++ rate2++) { ++ tmp_txpwr_limit[rate2] = 0; ++ tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] = ++ txpwr_ptr1[rate2]; ++ } ++ wlc_phy_ofdm_to_mcs_powers_nphy( ++ tmp_txpwr_limit, 0, ++ BRCMS_NUM_RATES_OFDM - ++ 1, BRCMS_NUM_RATES_OFDM); ++ for (rate1 = rate_start_index, rate2 = 0; ++ rate2 < BRCMS_NUM_RATES_MCS_1_STREAM; ++ rate1++, rate2++) ++ pi->txpwr_limit[rate1] = ++ min(txpwr_ptr2[rate2], ++ tmp_txpwr_limit[rate2]); ++ } ++ ++ for (k = 0; k < 2; k++) { ++ switch (k) { ++ case 0: ++ ++ rate_start_index = WL_TX_POWER_MCS20_STBC_FIRST; ++ txpwr_ptr1 = txpwr->mcs_20_stbc; ++ break; ++ case 1: ++ ++ rate_start_index = WL_TX_POWER_MCS40_STBC_FIRST; ++ txpwr_ptr1 = txpwr->mcs_40_stbc; ++ break; ++ } ++ for (rate1 = rate_start_index, rate2 = 0; ++ rate2 < BRCMS_NUM_RATES_MCS_1_STREAM; ++ rate1++, rate2++) ++ pi->txpwr_limit[rate1] = txpwr_ptr1[rate2]; ++ } ++ ++ for (k = 0; k < 2; k++) { ++ switch (k) { ++ case 0: ++ ++ rate_start_index = WL_TX_POWER_MCS20_SDM_FIRST; ++ txpwr_ptr1 = txpwr->mcs_20_mimo; ++ break; ++ case 1: ++ ++ rate_start_index = WL_TX_POWER_MCS40_SDM_FIRST; ++ txpwr_ptr1 = txpwr->mcs_40_mimo; ++ break; ++ } ++ for (rate1 = rate_start_index, rate2 = 0; ++ rate2 < BRCMS_NUM_RATES_MCS_2_STREAM; ++ rate1++, rate2++) ++ pi->txpwr_limit[rate1] = txpwr_ptr1[rate2]; ++ } ++ ++ pi->txpwr_limit[WL_TX_POWER_MCS_32] = txpwr->mcs32; ++ ++ pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST] = ++ min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST], ++ pi->txpwr_limit[WL_TX_POWER_MCS_32]); ++ pi->txpwr_limit[WL_TX_POWER_MCS_32] = ++ pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST]; ++ } ++} ++ ++void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi, u8 txpwr_percent) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ pi->txpwr_percent = txpwr_percent; ++} ++ ++void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ pi->sh->machwcap = machwcap; ++} ++ ++void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ u16 rxc; ++ rxc = 0; ++ ++ if (start_end == ON) { ++ if (!ISNPHY(pi)) ++ return; ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 3) ++ || NREV_IS(pi->pubpi.phy_rev, 4)) { ++ W_REG(&pi->regs->phyregaddr, 0xa0); ++ (void)R_REG(&pi->regs->phyregaddr); ++ rxc = R_REG(&pi->regs->phyregdata); ++ W_REG(&pi->regs->phyregdata, ++ (0x1 << 15) | rxc); ++ } ++ } else { ++ if (NREV_IS(pi->pubpi.phy_rev, 3) ++ || NREV_IS(pi->pubpi.phy_rev, 4)) { ++ W_REG(&pi->regs->phyregaddr, 0xa0); ++ (void)R_REG(&pi->regs->phyregaddr); ++ W_REG(&pi->regs->phyregdata, rxc); ++ } ++ ++ wlc_phy_por_inform(ppi); ++ } ++} ++ ++void ++wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *txpwr, ++ u16 chanspec) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ wlc_phy_txpower_reg_limit_calc(pi, txpwr, chanspec); ++ ++ if (ISLCNPHY(pi)) { ++ int i, j; ++ for (i = TXP_FIRST_OFDM_20_CDD, j = 0; ++ j < BRCMS_NUM_RATES_MCS_1_STREAM; i++, j++) { ++ if (txpwr->mcs_20_siso[j]) ++ pi->txpwr_limit[i] = txpwr->mcs_20_siso[j]; ++ else ++ pi->txpwr_limit[i] = txpwr->ofdm[j]; ++ } ++ } ++ ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ wlc_phy_txpower_recalc_target(pi); ++ wlc_phy_cal_txpower_recalc_sw(pi); ++ wlapi_enable_mac(pi->sh->physhim); ++} ++ ++void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ pi->ofdm_rateset_war = war; ++} ++ ++void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, bool bf_preempt) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ pi->bf_preempt_4306 = bf_preempt; ++} ++ ++void wlc_phy_txpower_update_shm(struct brcms_phy *pi) ++{ ++ int j; ++ if (ISNPHY(pi)) ++ return; ++ ++ if (!pi->sh->clk) ++ return; ++ ++ if (pi->hwpwrctrl) { ++ u16 offset; ++ ++ wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_MAX, 63); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_N, ++ 1 << NUM_TSSI_FRAMES); ++ ++ wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_TARGET, ++ pi->tx_power_min << NUM_TSSI_FRAMES); ++ ++ wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_CUR, ++ pi->hwpwr_txcur); ++ ++ for (j = TXP_FIRST_OFDM; j <= TXP_LAST_OFDM; j++) { ++ const u8 ucode_ofdm_rates[] = { ++ 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c ++ }; ++ offset = wlapi_bmac_rate_shm_offset( ++ pi->sh->physhim, ++ ucode_ofdm_rates[j - TXP_FIRST_OFDM]); ++ wlapi_bmac_write_shm(pi->sh->physhim, offset + 6, ++ pi->tx_power_offset[j]); ++ wlapi_bmac_write_shm(pi->sh->physhim, offset + 14, ++ -(pi->tx_power_offset[j] / 2)); ++ } ++ ++ wlapi_bmac_mhf(pi->sh->physhim, MHF2, MHF2_HWPWRCTL, ++ MHF2_HWPWRCTL, BRCM_BAND_ALL); ++ } else { ++ int i; ++ ++ for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) ++ pi->tx_power_offset[i] = ++ (u8) roundup(pi->tx_power_offset[i], 8); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_OFDM_OFFSET, ++ (u16) ++ ((pi->tx_power_offset[TXP_FIRST_OFDM] ++ + 7) >> 3)); ++ } ++} ++ ++bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ if (ISNPHY(pi)) ++ return pi->nphy_txpwrctrl; ++ else ++ return pi->hwpwrctrl; ++} ++ ++void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ bool suspend; ++ ++ if (!pi->hwpwrctrl_capable) ++ return; ++ ++ pi->hwpwrctrl = hwpwrctrl; ++ pi->nphy_txpwrctrl = hwpwrctrl; ++ pi->txpwrctrl = hwpwrctrl; ++ ++ if (ISNPHY(pi)) { ++ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl); ++ if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) ++ wlc_phy_txpwr_fixpower_nphy(pi); ++ else ++ mod_phy_reg(pi, 0x1e7, (0x7f << 0), ++ pi->saved_txpwr_idx); ++ ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++ } ++} ++ ++void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi) ++{ ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ pi->ipa2g_on = (pi->srom_fem2g.extpagain == 2); ++ pi->ipa5g_on = (pi->srom_fem5g.extpagain == 2); ++ } else { ++ pi->ipa2g_on = false; ++ pi->ipa5g_on = false; ++ } ++} ++ ++static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi) ++{ ++ s16 tx0_status, tx1_status; ++ u16 estPower1, estPower2; ++ u8 pwr0, pwr1, adj_pwr0, adj_pwr1; ++ u32 est_pwr; ++ ++ estPower1 = read_phy_reg(pi, 0x118); ++ estPower2 = read_phy_reg(pi, 0x119); ++ ++ if ((estPower1 & (0x1 << 8)) == (0x1 << 8)) ++ pwr0 = (u8) (estPower1 & (0xff << 0)) >> 0; ++ else ++ pwr0 = 0x80; ++ ++ if ((estPower2 & (0x1 << 8)) == (0x1 << 8)) ++ pwr1 = (u8) (estPower2 & (0xff << 0)) >> 0; ++ else ++ pwr1 = 0x80; ++ ++ tx0_status = read_phy_reg(pi, 0x1ed); ++ tx1_status = read_phy_reg(pi, 0x1ee); ++ ++ if ((tx0_status & (0x1 << 15)) == (0x1 << 15)) ++ adj_pwr0 = (u8) (tx0_status & (0xff << 0)) >> 0; ++ else ++ adj_pwr0 = 0x80; ++ if ((tx1_status & (0x1 << 15)) == (0x1 << 15)) ++ adj_pwr1 = (u8) (tx1_status & (0xff << 0)) >> 0; ++ else ++ adj_pwr1 = 0x80; ++ ++ est_pwr = (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) | ++ adj_pwr1); ++ ++ return est_pwr; ++} ++ ++void ++wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, struct tx_power *power, ++ uint channel) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ uint rate, num_rates; ++ u8 min_pwr, max_pwr; ++ ++#if WL_TX_POWER_RATES != TXP_NUM_RATES ++#error "struct tx_power out of sync with this fn" ++#endif ++ ++ if (ISNPHY(pi)) { ++ power->rf_cores = 2; ++ power->flags |= (WL_TX_POWER_F_MIMO); ++ if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON) ++ power->flags |= ++ (WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW); ++ } else if (ISLCNPHY(pi)) { ++ power->rf_cores = 1; ++ power->flags |= (WL_TX_POWER_F_SISO); ++ if (pi->radiopwr_override == RADIOPWR_OVERRIDE_DEF) ++ power->flags |= WL_TX_POWER_F_ENABLED; ++ if (pi->hwpwrctrl) ++ power->flags |= WL_TX_POWER_F_HW; ++ } ++ ++ num_rates = ((ISNPHY(pi)) ? (TXP_NUM_RATES) : ++ ((ISLCNPHY(pi)) ? ++ (TXP_LAST_OFDM_20_CDD + 1) : (TXP_LAST_OFDM + 1))); ++ ++ for (rate = 0; rate < num_rates; rate++) { ++ power->user_limit[rate] = pi->tx_user_target[rate]; ++ wlc_phy_txpower_sromlimit(ppi, channel, &min_pwr, &max_pwr, ++ rate); ++ power->board_limit[rate] = (u8) max_pwr; ++ power->target[rate] = pi->tx_power_target[rate]; ++ } ++ ++ if (ISNPHY(pi)) { ++ u32 est_pout; ++ ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ wlc_phyreg_enter((struct brcms_phy_pub *) pi); ++ est_pout = wlc_phy_txpower_est_power_nphy(pi); ++ wlc_phyreg_exit((struct brcms_phy_pub *) pi); ++ wlapi_enable_mac(pi->sh->physhim); ++ ++ power->est_Pout[0] = (est_pout >> 8) & 0xff; ++ power->est_Pout[1] = est_pout & 0xff; ++ ++ power->est_Pout_act[0] = est_pout >> 24; ++ power->est_Pout_act[1] = (est_pout >> 16) & 0xff; ++ ++ if (power->est_Pout[0] == 0x80) ++ power->est_Pout[0] = 0; ++ if (power->est_Pout[1] == 0x80) ++ power->est_Pout[1] = 0; ++ ++ if (power->est_Pout_act[0] == 0x80) ++ power->est_Pout_act[0] = 0; ++ if (power->est_Pout_act[1] == 0x80) ++ power->est_Pout_act[1] = 0; ++ ++ power->est_Pout_cck = 0; ++ ++ power->tx_power_max[0] = pi->tx_power_max; ++ power->tx_power_max[1] = pi->tx_power_max; ++ ++ power->tx_power_max_rate_ind[0] = pi->tx_power_max_rate_ind; ++ power->tx_power_max_rate_ind[1] = pi->tx_power_max_rate_ind; ++ } else if (pi->hwpwrctrl && pi->sh->up) { ++ ++ wlc_phyreg_enter(ppi); ++ if (ISLCNPHY(pi)) { ++ ++ power->tx_power_max[0] = pi->tx_power_max; ++ power->tx_power_max[1] = pi->tx_power_max; ++ ++ power->tx_power_max_rate_ind[0] = ++ pi->tx_power_max_rate_ind; ++ power->tx_power_max_rate_ind[1] = ++ pi->tx_power_max_rate_ind; ++ ++ if (wlc_phy_tpc_isenabled_lcnphy(pi)) ++ power->flags |= ++ (WL_TX_POWER_F_HW | ++ WL_TX_POWER_F_ENABLED); ++ else ++ power->flags &= ++ ~(WL_TX_POWER_F_HW | ++ WL_TX_POWER_F_ENABLED); ++ ++ wlc_lcnphy_get_tssi(pi, (s8 *) &power->est_Pout[0], ++ (s8 *) &power->est_Pout_cck); ++ } ++ wlc_phyreg_exit(ppi); ++ } ++} ++ ++void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ pi->antsel_type = antsel_type; ++} ++ ++bool wlc_phy_test_ison(struct brcms_phy_pub *ppi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ return pi->phytest_on; ++} ++ ++void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ bool suspend; ++ ++ pi->sh->rx_antdiv = val; ++ ++ if (!(ISNPHY(pi) && D11REV_IS(pi->sh->corerev, 16))) { ++ if (val > ANT_RX_DIV_FORCE_1) ++ wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, ++ MHF1_ANTDIV, BRCM_BAND_ALL); ++ else ++ wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, 0, ++ BRCM_BAND_ALL); ++ } ++ ++ if (ISNPHY(pi)) ++ return; ++ ++ if (!pi->sh->clk) ++ return; ++ ++ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ if (ISLCNPHY(pi)) { ++ if (val > ANT_RX_DIV_FORCE_1) { ++ mod_phy_reg(pi, 0x410, (0x1 << 1), 0x01 << 1); ++ mod_phy_reg(pi, 0x410, ++ (0x1 << 0), ++ ((ANT_RX_DIV_START_1 == val) ? 1 : 0) << 0); ++ } else { ++ mod_phy_reg(pi, 0x410, (0x1 << 1), 0x00 << 1); ++ mod_phy_reg(pi, 0x410, (0x1 << 0), (u16) val << 0); ++ } ++ } ++ ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++ ++ return; ++} ++ ++static bool ++wlc_phy_noise_calc_phy(struct brcms_phy *pi, u32 *cmplx_pwr, s8 *pwr_ant) ++{ ++ s8 cmplx_pwr_dbm[PHY_CORE_MAX]; ++ u8 i; ++ ++ memset((u8 *) cmplx_pwr_dbm, 0, sizeof(cmplx_pwr_dbm)); ++ wlc_phy_compute_dB(cmplx_pwr, cmplx_pwr_dbm, pi->pubpi.phy_corenum); ++ ++ for (i = 0; i < pi->pubpi.phy_corenum; i++) { ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ cmplx_pwr_dbm[i] += (s8) PHY_NOISE_OFFSETFACT_4322; ++ else ++ ++ cmplx_pwr_dbm[i] += (s8) (16 - (15) * 3 - 70); ++ } ++ ++ for (i = 0; i < pi->pubpi.phy_corenum; i++) { ++ pi->nphy_noise_win[i][pi->nphy_noise_index] = cmplx_pwr_dbm[i]; ++ pwr_ant[i] = cmplx_pwr_dbm[i]; ++ } ++ pi->nphy_noise_index = ++ MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ); ++ return true; ++} ++ ++static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm) ++{ ++ if (!pi->phynoise_state) ++ return; ++ ++ if (pi->phynoise_state & PHY_NOISE_STATE_MON) { ++ if (pi->phynoise_chan_watchdog == channel) { ++ pi->sh->phy_noise_window[pi->sh->phy_noise_index] = ++ noise_dbm; ++ pi->sh->phy_noise_index = ++ MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ); ++ } ++ pi->phynoise_state &= ~PHY_NOISE_STATE_MON; ++ } ++ ++ if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL) ++ pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL; ++ ++} ++ ++static s8 wlc_phy_noise_read_shmem(struct brcms_phy *pi) ++{ ++ u32 cmplx_pwr[PHY_CORE_MAX]; ++ s8 noise_dbm_ant[PHY_CORE_MAX]; ++ u16 lo, hi; ++ u32 cmplx_pwr_tot = 0; ++ s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; ++ u8 idx, core; ++ ++ memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr)); ++ memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant)); ++ ++ for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2, ++ core++) { ++ lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx)); ++ hi = wlapi_bmac_read_shm(pi->sh->physhim, ++ M_PWRIND_MAP(idx + 1)); ++ cmplx_pwr[core] = (hi << 16) + lo; ++ cmplx_pwr_tot += cmplx_pwr[core]; ++ if (cmplx_pwr[core] == 0) ++ noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY; ++ else ++ cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE; ++ } ++ ++ if (cmplx_pwr_tot != 0) ++ wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant); ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ pi->nphy_noise_win[core][pi->nphy_noise_index] = ++ noise_dbm_ant[core]; ++ ++ if (noise_dbm_ant[core] > noise_dbm) ++ noise_dbm = noise_dbm_ant[core]; ++ } ++ pi->nphy_noise_index = ++ MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ); ++ ++ return noise_dbm; ++ ++} ++ ++void wlc_phy_noise_sample_intr(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ u16 jssi_aux; ++ u8 channel = 0; ++ s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; ++ ++ if (ISLCNPHY(pi)) { ++ u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1; ++ u16 lo, hi; ++ s32 pwr_offset_dB, gain_dB; ++ u16 status_0, status_1; ++ ++ jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX); ++ channel = jssi_aux & D11_CURCHANNEL_MAX; ++ ++ lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0); ++ hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1); ++ cmplx_pwr0 = (hi << 16) + lo; ++ ++ lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2); ++ hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3); ++ cmplx_pwr1 = (hi << 16) + lo; ++ cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6; ++ ++ status_0 = 0x44; ++ status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0); ++ if ((cmplx_pwr > 0 && cmplx_pwr < 500) ++ && ((status_1 & 0xc000) == 0x4000)) { ++ ++ wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm, ++ pi->pubpi.phy_corenum); ++ pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF); ++ if (pwr_offset_dB > 127) ++ pwr_offset_dB -= 256; ++ ++ noise_dbm += (s8) (pwr_offset_dB - 30); ++ ++ gain_dB = (status_0 & 0x1ff); ++ noise_dbm -= (s8) (gain_dB); ++ } else { ++ noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY; ++ } ++ } else if (ISNPHY(pi)) { ++ ++ jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX); ++ channel = jssi_aux & D11_CURCHANNEL_MAX; ++ ++ noise_dbm = wlc_phy_noise_read_shmem(pi); ++ } ++ ++ wlc_phy_noise_cb(pi, channel, noise_dbm); ++ ++} ++ ++static void ++wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; ++ bool sampling_in_progress = (pi->phynoise_state != 0); ++ bool wait_for_intr = true; ++ ++ switch (reason) { ++ case PHY_NOISE_SAMPLE_MON: ++ pi->phynoise_chan_watchdog = ch; ++ pi->phynoise_state |= PHY_NOISE_STATE_MON; ++ break; ++ ++ case PHY_NOISE_SAMPLE_EXTERNAL: ++ pi->phynoise_state |= PHY_NOISE_STATE_EXTERNAL; ++ break; ++ ++ default: ++ break; ++ } ++ ++ if (sampling_in_progress) ++ return; ++ ++ pi->phynoise_now = pi->sh->now; ++ ++ if (pi->phy_fixed_noise) { ++ if (ISNPHY(pi)) { ++ pi->nphy_noise_win[WL_ANT_IDX_1][pi->nphy_noise_index] = ++ PHY_NOISE_FIXED_VAL_NPHY; ++ pi->nphy_noise_win[WL_ANT_IDX_2][pi->nphy_noise_index] = ++ PHY_NOISE_FIXED_VAL_NPHY; ++ pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index, ++ PHY_NOISE_WINDOW_SZ); ++ noise_dbm = PHY_NOISE_FIXED_VAL_NPHY; ++ } else { ++ noise_dbm = PHY_NOISE_FIXED_VAL; ++ } ++ ++ wait_for_intr = false; ++ goto done; ++ } ++ ++ if (ISLCNPHY(pi)) { ++ if (!pi->phynoise_polling ++ || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) { ++ wlapi_bmac_write_shm(pi->sh->physhim, M_JSSI_0, 0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0); ++ ++ OR_REG(&pi->regs->maccommand, ++ MCMD_BG_NOISE); ++ } else { ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ wlc_lcnphy_deaf_mode(pi, (bool) 0); ++ noise_dbm = (s8) wlc_lcnphy_rx_signal_power(pi, 20); ++ wlc_lcnphy_deaf_mode(pi, (bool) 1); ++ wlapi_enable_mac(pi->sh->physhim); ++ wait_for_intr = false; ++ } ++ } else if (ISNPHY(pi)) { ++ if (!pi->phynoise_polling ++ || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) { ++ ++ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0); ++ ++ OR_REG(&pi->regs->maccommand, ++ MCMD_BG_NOISE); ++ } else { ++ struct phy_iq_est est[PHY_CORE_MAX]; ++ u32 cmplx_pwr[PHY_CORE_MAX]; ++ s8 noise_dbm_ant[PHY_CORE_MAX]; ++ u16 log_num_samps, num_samps, classif_state = 0; ++ u8 wait_time = 32; ++ u8 wait_crs = 0; ++ u8 i; ++ ++ memset((u8 *) est, 0, sizeof(est)); ++ memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr)); ++ memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant)); ++ ++ log_num_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY; ++ num_samps = 1 << log_num_samps; ++ ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ classif_state = wlc_phy_classifier_nphy(pi, 0, 0); ++ wlc_phy_classifier_nphy(pi, 3, 0); ++ wlc_phy_rx_iq_est_nphy(pi, est, num_samps, wait_time, ++ wait_crs); ++ wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state); ++ wlapi_enable_mac(pi->sh->physhim); ++ ++ for (i = 0; i < pi->pubpi.phy_corenum; i++) ++ cmplx_pwr[i] = (est[i].i_pwr + est[i].q_pwr) >> ++ log_num_samps; ++ ++ wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant); ++ ++ for (i = 0; i < pi->pubpi.phy_corenum; i++) { ++ pi->nphy_noise_win[i][pi->nphy_noise_index] = ++ noise_dbm_ant[i]; ++ ++ if (noise_dbm_ant[i] > noise_dbm) ++ noise_dbm = noise_dbm_ant[i]; ++ } ++ pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index, ++ PHY_NOISE_WINDOW_SZ); ++ ++ wait_for_intr = false; ++ } ++ } ++ ++done: ++ ++ if (!wait_for_intr) ++ wlc_phy_noise_cb(pi, ch, noise_dbm); ++ ++} ++ ++void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *pih) ++{ ++ u8 channel; ++ ++ channel = CHSPEC_CHANNEL(wlc_phy_chanspec_get(pih)); ++ ++ wlc_phy_noise_sample_request(pih, PHY_NOISE_SAMPLE_EXTERNAL, channel); ++} ++ ++static const s8 lcnphy_gain_index_offset_for_pkt_rssi[] = { ++ 8, ++ 8, ++ 8, ++ 8, ++ 8, ++ 8, ++ 8, ++ 9, ++ 10, ++ 8, ++ 8, ++ 7, ++ 7, ++ 1, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 1, ++ 1, ++ 0, ++ 0, ++ 0, ++ 0 ++}; ++ ++void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_cmplx_pwr_dB, u8 core) ++{ ++ u8 msb, secondmsb, i; ++ u32 tmp; ++ ++ for (i = 0; i < core; i++) { ++ secondmsb = 0; ++ tmp = cmplx_pwr[i]; ++ msb = fls(tmp); ++ if (msb) ++ secondmsb = (u8) ((tmp >> (--msb - 1)) & 1); ++ p_cmplx_pwr_dB[i] = (s8) (3 * msb + 2 * secondmsb); ++ } ++} ++ ++int wlc_phy_rssi_compute(struct brcms_phy_pub *pih, ++ struct d11rxhdr *rxh) ++{ ++ int rssi = rxh->PhyRxStatus_1 & PRXS1_JSSI_MASK; ++ uint radioid = pih->radioid; ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if ((pi->sh->corerev >= 11) ++ && !(rxh->RxStatus2 & RXS_PHYRXST_VALID)) { ++ rssi = BRCMS_RSSI_INVALID; ++ goto end; ++ } ++ ++ if (ISLCNPHY(pi)) { ++ u8 gidx = (rxh->PhyRxStatus_2 & 0xFC00) >> 10; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ if (rssi > 127) ++ rssi -= 256; ++ ++ rssi = rssi + lcnphy_gain_index_offset_for_pkt_rssi[gidx]; ++ if ((rssi > -46) && (gidx > 18)) ++ rssi = rssi + 7; ++ ++ rssi = rssi + pi_lcn->lcnphy_pkteng_rssi_slope; ++ ++ rssi = rssi + 2; ++ ++ } ++ ++ if (ISLCNPHY(pi)) { ++ if (rssi > 127) ++ rssi -= 256; ++ } else if (radioid == BCM2055_ID || radioid == BCM2056_ID ++ || radioid == BCM2057_ID) { ++ rssi = wlc_phy_rssi_compute_nphy(pi, rxh); ++ } ++ ++end: ++ return rssi; ++} ++ ++void wlc_phy_freqtrack_start(struct brcms_phy_pub *pih) ++{ ++ return; ++} ++ ++void wlc_phy_freqtrack_end(struct brcms_phy_pub *pih) ++{ ++ return; ++} ++ ++void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag) ++{ ++ struct brcms_phy *pi; ++ pi = (struct brcms_phy *) ppi; ++ ++ if (ISLCNPHY(pi)) ++ wlc_lcnphy_deaf_mode(pi, true); ++ else if (ISNPHY(pi)) ++ wlc_nphy_deaf_mode(pi, true); ++} ++ ++void wlc_phy_watchdog(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ bool delay_phy_cal = false; ++ pi->sh->now++; ++ ++ if (!pi->watchdog_override) ++ return; ++ ++ if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi))) ++ wlc_phy_noise_sample_request((struct brcms_phy_pub *) pi, ++ PHY_NOISE_SAMPLE_MON, ++ CHSPEC_CHANNEL(pi-> ++ radio_chanspec)); ++ ++ if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5) ++ pi->phynoise_state = 0; ++ ++ if ((!pi->phycal_txpower) || ++ ((pi->sh->now - pi->phycal_txpower) >= pi->sh->fast_timer)) { ++ ++ if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi)) ++ pi->phycal_txpower = pi->sh->now; ++ } ++ ++ if ((SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) ++ || ASSOC_INPROG_PHY(pi))) ++ return; ++ ++ if (ISNPHY(pi) && !pi->disable_percal && !delay_phy_cal) { ++ ++ if ((pi->nphy_perical != PHY_PERICAL_DISABLE) && ++ (pi->nphy_perical != PHY_PERICAL_MANUAL) && ++ ((pi->sh->now - pi->nphy_perical_last) >= ++ pi->sh->glacial_timer)) ++ wlc_phy_cal_perical((struct brcms_phy_pub *) pi, ++ PHY_PERICAL_WATCHDOG); ++ ++ wlc_phy_txpwr_papd_cal_nphy(pi); ++ } ++ ++ if (ISLCNPHY(pi)) { ++ if (pi->phy_forcecal || ++ ((pi->sh->now - pi->phy_lastcal) >= ++ pi->sh->glacial_timer)) { ++ if (!(SCAN_RM_IN_PROGRESS(pi) || ASSOC_INPROG_PHY(pi))) ++ wlc_lcnphy_calib_modes( ++ pi, ++ LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL); ++ if (! ++ (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) ++ || ASSOC_INPROG_PHY(pi) ++ || pi->carrier_suppr_disable ++ || pi->disable_percal)) ++ wlc_lcnphy_calib_modes(pi, ++ PHY_PERICAL_WATCHDOG); ++ } ++ } ++} ++ ++void wlc_phy_BSSinit(struct brcms_phy_pub *pih, bool bonlyap, int rssi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ uint i; ++ uint k; ++ ++ for (i = 0; i < MA_WINDOW_SZ; i++) ++ pi->sh->phy_noise_window[i] = (s8) (rssi & 0xff); ++ if (ISLCNPHY(pi)) { ++ for (i = 0; i < MA_WINDOW_SZ; i++) ++ pi->sh->phy_noise_window[i] = ++ PHY_NOISE_FIXED_VAL_LCNPHY; ++ } ++ pi->sh->phy_noise_index = 0; ++ ++ for (i = 0; i < PHY_NOISE_WINDOW_SZ; i++) { ++ for (k = WL_ANT_IDX_1; k < WL_ANT_RX_MAX; k++) ++ pi->nphy_noise_win[k][i] = PHY_NOISE_FIXED_VAL_NPHY; ++ } ++ pi->nphy_noise_index = 0; ++} ++ ++void ++wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag) ++{ ++ *eps_imag = (epsilon >> 13); ++ if (*eps_imag > 0xfff) ++ *eps_imag -= 0x2000; ++ ++ *eps_real = (epsilon & 0x1fff); ++ if (*eps_real > 0xfff) ++ *eps_real -= 0x2000; ++} ++ ++void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi) ++{ ++ wlapi_del_timer(pi->phycal_timer); ++ ++ pi->cal_type_override = PHY_PERICAL_AUTO; ++ pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE; ++ pi->mphase_txcal_cmdidx = 0; ++} ++ ++static void ++wlc_phy_cal_perical_mphase_schedule(struct brcms_phy *pi, uint delay) ++{ ++ ++ if ((pi->nphy_perical != PHY_PERICAL_MPHASE) && ++ (pi->nphy_perical != PHY_PERICAL_MANUAL)) ++ return; ++ ++ wlapi_del_timer(pi->phycal_timer); ++ ++ pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT; ++ wlapi_add_timer(pi->phycal_timer, delay, 0); ++} ++ ++void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason) ++{ ++ s16 nphy_currtemp = 0; ++ s16 delta_temp = 0; ++ bool do_periodic_cal = true; ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ if (!ISNPHY(pi)) ++ return; ++ ++ if ((pi->nphy_perical == PHY_PERICAL_DISABLE) || ++ (pi->nphy_perical == PHY_PERICAL_MANUAL)) ++ return; ++ ++ switch (reason) { ++ case PHY_PERICAL_DRIVERUP: ++ break; ++ ++ case PHY_PERICAL_PHYINIT: ++ if (pi->nphy_perical == PHY_PERICAL_MPHASE) { ++ if (PHY_PERICAL_MPHASE_PENDING(pi)) ++ wlc_phy_cal_perical_mphase_reset(pi); ++ ++ wlc_phy_cal_perical_mphase_schedule( ++ pi, ++ PHY_PERICAL_INIT_DELAY); ++ } ++ break; ++ ++ case PHY_PERICAL_JOIN_BSS: ++ case PHY_PERICAL_START_IBSS: ++ case PHY_PERICAL_UP_BSS: ++ if ((pi->nphy_perical == PHY_PERICAL_MPHASE) && ++ PHY_PERICAL_MPHASE_PENDING(pi)) ++ wlc_phy_cal_perical_mphase_reset(pi); ++ ++ pi->first_cal_after_assoc = true; ++ ++ pi->cal_type_override = PHY_PERICAL_FULL; ++ ++ if (pi->phycal_tempdelta) ++ pi->nphy_lastcal_temp = wlc_phy_tempsense_nphy(pi); ++ ++ wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_FULL); ++ break; ++ ++ case PHY_PERICAL_WATCHDOG: ++ if (pi->phycal_tempdelta) { ++ nphy_currtemp = wlc_phy_tempsense_nphy(pi); ++ delta_temp = ++ (nphy_currtemp > pi->nphy_lastcal_temp) ? ++ nphy_currtemp - pi->nphy_lastcal_temp : ++ pi->nphy_lastcal_temp - nphy_currtemp; ++ ++ if ((delta_temp < (s16) pi->phycal_tempdelta) && ++ (pi->nphy_txiqlocal_chanspec == ++ pi->radio_chanspec)) ++ do_periodic_cal = false; ++ else ++ pi->nphy_lastcal_temp = nphy_currtemp; ++ } ++ ++ if (do_periodic_cal) { ++ if (pi->nphy_perical == PHY_PERICAL_MPHASE) { ++ if (!PHY_PERICAL_MPHASE_PENDING(pi)) ++ wlc_phy_cal_perical_mphase_schedule( ++ pi, ++ PHY_PERICAL_WDOG_DELAY); ++ } else if (pi->nphy_perical == PHY_PERICAL_SPHASE) ++ wlc_phy_cal_perical_nphy_run(pi, ++ PHY_PERICAL_AUTO); ++ } ++ break; ++ default: ++ break; ++ } ++} ++ ++void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi) ++{ ++ pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT; ++ pi->mphase_txcal_cmdidx = 0; ++} ++ ++u8 wlc_phy_nbits(s32 value) ++{ ++ s32 abs_val; ++ u8 nbits = 0; ++ ++ abs_val = abs(value); ++ while ((abs_val >> nbits) > 0) ++ nbits++; ++ ++ return nbits; ++} ++ ++void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ pi->sh->hw_phytxchain = txchain; ++ pi->sh->hw_phyrxchain = rxchain; ++ pi->sh->phytxchain = txchain; ++ pi->sh->phyrxchain = rxchain; ++ pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain); ++} ++ ++void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ pi->sh->phytxchain = txchain; ++ ++ if (ISNPHY(pi)) ++ wlc_phy_rxcore_setstate_nphy(pih, rxchain); ++ ++ pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain); ++} ++ ++void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, u8 *rxchain) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ *txchain = pi->sh->phytxchain; ++ *rxchain = pi->sh->phyrxchain; ++} ++ ++u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih) ++{ ++ s16 nphy_currtemp; ++ u8 active_bitmap; ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ active_bitmap = (pi->phy_txcore_heatedup) ? 0x31 : 0x33; ++ ++ if (!pi->watchdog_override) ++ return active_bitmap; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 6)) { ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ nphy_currtemp = wlc_phy_tempsense_nphy(pi); ++ wlapi_enable_mac(pi->sh->physhim); ++ ++ if (!pi->phy_txcore_heatedup) { ++ if (nphy_currtemp >= pi->phy_txcore_disable_temp) { ++ active_bitmap &= 0xFD; ++ pi->phy_txcore_heatedup = true; ++ } ++ } else { ++ if (nphy_currtemp <= pi->phy_txcore_enable_temp) { ++ active_bitmap |= 0x2; ++ pi->phy_txcore_heatedup = false; ++ } ++ } ++ } ++ ++ return active_bitmap; ++} ++ ++s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, u16 chanspec) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ u8 siso_mcs_id, cdd_mcs_id; ++ ++ siso_mcs_id = ++ (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO : ++ TXP_FIRST_MCS_20_SISO; ++ cdd_mcs_id = ++ (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD : ++ TXP_FIRST_MCS_20_CDD; ++ ++ if (pi->tx_power_target[siso_mcs_id] > ++ (pi->tx_power_target[cdd_mcs_id] + 12)) ++ return PHY_TXC1_MODE_SISO; ++ else ++ return PHY_TXC1_MODE_CDD; ++} ++ ++const u8 *wlc_phy_get_ofdm_rate_lookup(void) ++{ ++ return ofdm_rate_lookup; ++} ++ ++void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode) ++{ ++ if ((pi->sh->chip == BCM4313_CHIP_ID) && ++ (pi->sh->boardflags & BFL_FEM)) { ++ if (mode) { ++ u16 txant = 0; ++ txant = wlapi_bmac_get_txant(pi->sh->physhim); ++ if (txant == 1) { ++ mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2); ++ ++ } ++ ai_corereg(pi->sh->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, gpiocontrol), ++ ~0x0, 0x0); ++ ai_corereg(pi->sh->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, gpioout), 0x40, ++ 0x40); ++ ai_corereg(pi->sh->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, gpioouten), 0x40, ++ 0x40); ++ } else { ++ mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2); ++ ++ mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2); ++ ++ ai_corereg(pi->sh->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, gpioout), 0x40, ++ 0x00); ++ ai_corereg(pi->sh->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, gpioouten), 0x40, ++ 0x0); ++ ai_corereg(pi->sh->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, gpiocontrol), ++ ~0x0, 0x40); ++ } ++ } ++} ++ ++void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool ldpc) ++{ ++ return; ++} ++ ++void ++wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, s8 *ofdmoffset) ++{ ++ *cckoffset = 0; ++ *ofdmoffset = 0; ++} ++ ++s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, u16 chanspec) ++{ ++ ++ return rssi; ++} ++ ++bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *ppi) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ if (ISNPHY(pi)) ++ return wlc_phy_n_txpower_ipa_ison(pi); ++ else ++ return 0; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h.orig 2011-11-09 13:46:58.254800521 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h 2011-11-09 13:47:17.008566067 -0500 +@@ -0,0 +1,301 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/* ++ * phy_hal.h: functionality exported from the phy to higher layers ++ */ ++ ++#ifndef _BRCM_PHY_HAL_H_ ++#define _BRCM_PHY_HAL_H_ ++ ++#include ++#include ++#include ++ ++#define IDCODE_VER_MASK 0x0000000f ++#define IDCODE_VER_SHIFT 0 ++#define IDCODE_MFG_MASK 0x00000fff ++#define IDCODE_MFG_SHIFT 0 ++#define IDCODE_ID_MASK 0x0ffff000 ++#define IDCODE_ID_SHIFT 12 ++#define IDCODE_REV_MASK 0xf0000000 ++#define IDCODE_REV_SHIFT 28 ++ ++#define NORADIO_ID 0xe4f5 ++#define NORADIO_IDCODE 0x4e4f5246 ++ ++#define BCM2055_ID 0x2055 ++#define BCM2055_IDCODE 0x02055000 ++#define BCM2055A0_IDCODE 0x1205517f ++ ++#define BCM2056_ID 0x2056 ++#define BCM2056_IDCODE 0x02056000 ++#define BCM2056A0_IDCODE 0x1205617f ++ ++#define BCM2057_ID 0x2057 ++#define BCM2057_IDCODE 0x02057000 ++#define BCM2057A0_IDCODE 0x1205717f ++ ++#define BCM2064_ID 0x2064 ++#define BCM2064_IDCODE 0x02064000 ++#define BCM2064A0_IDCODE 0x0206417f ++ ++#define PHY_TPC_HW_OFF false ++#define PHY_TPC_HW_ON true ++ ++#define PHY_PERICAL_DRIVERUP 1 ++#define PHY_PERICAL_WATCHDOG 2 ++#define PHY_PERICAL_PHYINIT 3 ++#define PHY_PERICAL_JOIN_BSS 4 ++#define PHY_PERICAL_START_IBSS 5 ++#define PHY_PERICAL_UP_BSS 6 ++#define PHY_PERICAL_CHAN 7 ++#define PHY_FULLCAL 8 ++ ++#define PHY_PERICAL_DISABLE 0 ++#define PHY_PERICAL_SPHASE 1 ++#define PHY_PERICAL_MPHASE 2 ++#define PHY_PERICAL_MANUAL 3 ++ ++#define PHY_HOLD_FOR_ASSOC 1 ++#define PHY_HOLD_FOR_SCAN 2 ++#define PHY_HOLD_FOR_RM 4 ++#define PHY_HOLD_FOR_PLT 8 ++#define PHY_HOLD_FOR_MUTE 16 ++#define PHY_HOLD_FOR_NOT_ASSOC 0x20 ++ ++#define PHY_MUTE_FOR_PREISM 1 ++#define PHY_MUTE_ALL 0xffffffff ++ ++#define PHY_NOISE_FIXED_VAL (-95) ++#define PHY_NOISE_FIXED_VAL_NPHY (-92) ++#define PHY_NOISE_FIXED_VAL_LCNPHY (-92) ++ ++#define PHY_MODE_CAL 0x0002 ++#define PHY_MODE_NOISEM 0x0004 ++ ++#define BRCMS_TXPWR_DB_FACTOR 4 ++ ++/* a large TX Power as an init value to factor out of min() calculations, ++ * keep low enough to fit in an s8, units are .25 dBm ++ */ ++#define BRCMS_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */ ++ ++#define BRCMS_NUM_RATES_CCK 4 ++#define BRCMS_NUM_RATES_OFDM 8 ++#define BRCMS_NUM_RATES_MCS_1_STREAM 8 ++#define BRCMS_NUM_RATES_MCS_2_STREAM 8 ++#define BRCMS_NUM_RATES_MCS_3_STREAM 8 ++#define BRCMS_NUM_RATES_MCS_4_STREAM 8 ++ ++#define BRCMS_RSSI_INVALID 0 /* invalid RSSI value */ ++ ++struct d11regs; ++struct phy_shim_info; ++ ++struct txpwr_limits { ++ u8 cck[BRCMS_NUM_RATES_CCK]; ++ u8 ofdm[BRCMS_NUM_RATES_OFDM]; ++ ++ u8 ofdm_cdd[BRCMS_NUM_RATES_OFDM]; ++ ++ u8 ofdm_40_siso[BRCMS_NUM_RATES_OFDM]; ++ u8 ofdm_40_cdd[BRCMS_NUM_RATES_OFDM]; ++ ++ u8 mcs_20_siso[BRCMS_NUM_RATES_MCS_1_STREAM]; ++ u8 mcs_20_cdd[BRCMS_NUM_RATES_MCS_1_STREAM]; ++ u8 mcs_20_stbc[BRCMS_NUM_RATES_MCS_1_STREAM]; ++ u8 mcs_20_mimo[BRCMS_NUM_RATES_MCS_2_STREAM]; ++ ++ u8 mcs_40_siso[BRCMS_NUM_RATES_MCS_1_STREAM]; ++ u8 mcs_40_cdd[BRCMS_NUM_RATES_MCS_1_STREAM]; ++ u8 mcs_40_stbc[BRCMS_NUM_RATES_MCS_1_STREAM]; ++ u8 mcs_40_mimo[BRCMS_NUM_RATES_MCS_2_STREAM]; ++ u8 mcs32; ++}; ++ ++struct tx_power { ++ u32 flags; ++ u16 chanspec; /* txpwr report for this channel */ ++ u16 local_chanspec; /* channel on which we are associated */ ++ u8 local_max; /* local max according to the AP */ ++ u8 local_constraint; /* local constraint according to the AP */ ++ s8 antgain[2]; /* Ant gain for each band - from SROM */ ++ u8 rf_cores; /* count of RF Cores being reported */ ++ u8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ ++ u8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain ++ * without adjustment */ ++ u8 est_Pout_cck; /* Latest CCK tx power out estimate */ ++ u8 tx_power_max[4]; /* Maximum target power among all rates */ ++ /* Index of the rate with the max target power */ ++ u8 tx_power_max_rate_ind[4]; ++ /* User limit */ ++ u8 user_limit[WL_TX_POWER_RATES]; ++ /* Regulatory power limit */ ++ u8 reg_limit[WL_TX_POWER_RATES]; ++ /* Max power board can support (SROM) */ ++ u8 board_limit[WL_TX_POWER_RATES]; ++ /* Latest target power */ ++ u8 target[WL_TX_POWER_RATES]; ++}; ++ ++struct tx_inst_power { ++ u8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ ++ u8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */ ++}; ++ ++struct brcms_chanvec { ++ u8 vec[MAXCHANNEL / NBBY]; ++}; ++ ++struct shared_phy_params { ++ struct si_pub *sih; ++ struct phy_shim_info *physhim; ++ uint unit; ++ uint corerev; ++ uint buscorerev; ++ u16 vid; ++ u16 did; ++ uint chip; ++ uint chiprev; ++ uint chippkg; ++ uint sromrev; ++ uint boardtype; ++ uint boardrev; ++ uint boardvendor; ++ u32 boardflags; ++ u32 boardflags2; ++}; ++ ++ ++extern struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp); ++extern struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh, ++ struct d11regs __iomem *regs, ++ int bandtype, struct wiphy *wiphy); ++extern void wlc_phy_detach(struct brcms_phy_pub *ppi); ++ ++extern bool wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype, ++ u16 *phyrev, u16 *radioid, ++ u16 *radiover); ++extern bool wlc_phy_get_encore(struct brcms_phy_pub *pih); ++extern u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih); ++ ++extern void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *ppi, bool newstate); ++extern void wlc_phy_hw_state_upd(struct brcms_phy_pub *ppi, bool newstate); ++extern void wlc_phy_init(struct brcms_phy_pub *ppi, u16 chanspec); ++extern void wlc_phy_watchdog(struct brcms_phy_pub *ppi); ++extern int wlc_phy_down(struct brcms_phy_pub *ppi); ++extern u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih); ++extern void wlc_phy_cal_init(struct brcms_phy_pub *ppi); ++extern void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init); ++ ++extern void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, ++ u16 chanspec); ++extern u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi); ++extern void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, ++ u16 newch); ++extern u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi); ++extern void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw); ++ ++extern int wlc_phy_rssi_compute(struct brcms_phy_pub *pih, ++ struct d11rxhdr *rxh); ++extern void wlc_phy_por_inform(struct brcms_phy_pub *ppi); ++extern void wlc_phy_noise_sample_intr(struct brcms_phy_pub *ppi); ++extern bool wlc_phy_bist_check_phy(struct brcms_phy_pub *ppi); ++ ++extern void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag); ++ ++extern void wlc_phy_switch_radio(struct brcms_phy_pub *ppi, bool on); ++extern void wlc_phy_anacore(struct brcms_phy_pub *ppi, bool on); ++ ++ ++extern void wlc_phy_BSSinit(struct brcms_phy_pub *ppi, bool bonlyap, int rssi); ++ ++extern void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi, ++ bool wide_filter); ++extern void wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band, ++ struct brcms_chanvec *channels); ++extern u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, ++ uint band); ++ ++extern void wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint chan, ++ u8 *_min_, u8 *_max_, int rate); ++extern void wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, ++ uint chan, u8 *_max_, u8 *_min_); ++extern void wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi, ++ uint band, s32 *, s32 *, u32 *); ++extern void wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, ++ struct txpwr_limits *, ++ u16 chanspec); ++extern int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, ++ bool *override); ++extern int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, ++ bool override); ++extern void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi, ++ struct txpwr_limits *); ++extern bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi); ++extern void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, ++ bool hwpwrctrl); ++extern u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi); ++extern u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi); ++extern bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *pih); ++ ++extern void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, ++ u8 rxchain); ++extern void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, ++ u8 rxchain); ++extern void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, ++ u8 *rxchain); ++extern u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih); ++extern s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, ++ u16 chanspec); ++extern void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool val); ++ ++extern void wlc_phy_cal_perical(struct brcms_phy_pub *ppi, u8 reason); ++extern void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *ppi); ++extern void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock); ++extern void wlc_phy_cal_papd_recal(struct brcms_phy_pub *ppi); ++ ++extern void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val); ++extern void wlc_phy_clear_tssi(struct brcms_phy_pub *ppi); ++extern void wlc_phy_hold_upd(struct brcms_phy_pub *ppi, u32 id, bool val); ++extern void wlc_phy_mute_upd(struct brcms_phy_pub *ppi, bool val, u32 flags); ++ ++extern void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type); ++ ++extern void wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, ++ struct tx_power *power, uint channel); ++ ++extern void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal); ++extern bool wlc_phy_test_ison(struct brcms_phy_pub *ppi); ++extern void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi, ++ u8 txpwr_percent); ++extern void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war); ++extern void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, ++ bool bf_preempt); ++extern void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap); ++ ++extern void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end); ++ ++extern void wlc_phy_freqtrack_start(struct brcms_phy_pub *ppi); ++extern void wlc_phy_freqtrack_end(struct brcms_phy_pub *ppi); ++ ++extern const u8 *wlc_phy_get_ofdm_rate_lookup(void); ++ ++extern s8 wlc_phy_get_tx_power_offset_by_mcs(struct brcms_phy_pub *ppi, ++ u8 mcs_offset); ++extern s8 wlc_phy_get_tx_power_offset(struct brcms_phy_pub *ppi, u8 tbl_offset); ++#endif /* _BRCM_PHY_HAL_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h.orig 2011-11-09 13:46:58.255800509 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h 2011-11-09 13:47:17.009566054 -0500 +@@ -0,0 +1,1169 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_PHY_INT_H_ ++#define _BRCM_PHY_INT_H_ ++ ++#include ++#include ++#include ++ ++#define PHY_VERSION { 1, 82, 8, 0 } ++ ++#define LCNXN_BASEREV 16 ++ ++struct phy_shim_info; ++ ++struct brcms_phy_srom_fem { ++ /* TSSI positive slope, 1: positive, 0: negative */ ++ u8 tssipos; ++ /* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */ ++ u8 extpagain; ++ /* support 32 combinations of different Pdet dynamic ranges */ ++ u8 pdetrange; ++ /* TR switch isolation */ ++ u8 triso; ++ /* antswctrl lookup table configuration: 32 possible choices */ ++ u8 antswctrllut; ++}; ++ ++#define ISNPHY(pi) PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_N) ++#define ISLCNPHY(pi) PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_LCN) ++ ++#define PHY_GET_RFATTN(rfgain) ((rfgain) & 0x0f) ++#define PHY_GET_PADMIX(rfgain) (((rfgain) & 0x10) >> 4) ++#define PHY_GET_RFGAINID(rfattn, padmix, width) ((rfattn) + ((padmix)*(width))) ++#define PHY_SAT(x, n) ((x) > ((1<<((n)-1))-1) ? ((1<<((n)-1))-1) : \ ++ ((x) < -(1<<((n)-1)) ? -(1<<((n)-1)) : (x))) ++#define PHY_SHIFT_ROUND(x, n) ((x) >= 0 ? ((x)+(1<<((n)-1)))>>(n) : (x)>>(n)) ++#define PHY_HW_ROUND(x, s) ((x >> s) + ((x >> (s-1)) & (s != 0))) ++ ++#define CH_5G_GROUP 3 ++#define A_LOW_CHANS 0 ++#define A_MID_CHANS 1 ++#define A_HIGH_CHANS 2 ++#define CH_2G_GROUP 1 ++#define G_ALL_CHANS 0 ++ ++#define FIRST_REF5_CHANNUM 149 ++#define LAST_REF5_CHANNUM 165 ++#define FIRST_5G_CHAN 14 ++#define LAST_5G_CHAN 50 ++#define FIRST_MID_5G_CHAN 14 ++#define LAST_MID_5G_CHAN 35 ++#define FIRST_HIGH_5G_CHAN 36 ++#define LAST_HIGH_5G_CHAN 41 ++#define FIRST_LOW_5G_CHAN 42 ++#define LAST_LOW_5G_CHAN 50 ++ ++#define BASE_LOW_5G_CHAN 4900 ++#define BASE_MID_5G_CHAN 5100 ++#define BASE_HIGH_5G_CHAN 5500 ++ ++#define CHAN5G_FREQ(chan) (5000 + chan*5) ++#define CHAN2G_FREQ(chan) (2407 + chan*5) ++ ++#define TXP_FIRST_CCK 0 ++#define TXP_LAST_CCK 3 ++#define TXP_FIRST_OFDM 4 ++#define TXP_LAST_OFDM 11 ++#define TXP_FIRST_OFDM_20_CDD 12 ++#define TXP_LAST_OFDM_20_CDD 19 ++#define TXP_FIRST_MCS_20_SISO 20 ++#define TXP_LAST_MCS_20_SISO 27 ++#define TXP_FIRST_MCS_20_CDD 28 ++#define TXP_LAST_MCS_20_CDD 35 ++#define TXP_FIRST_MCS_20_STBC 36 ++#define TXP_LAST_MCS_20_STBC 43 ++#define TXP_FIRST_MCS_20_SDM 44 ++#define TXP_LAST_MCS_20_SDM 51 ++#define TXP_FIRST_OFDM_40_SISO 52 ++#define TXP_LAST_OFDM_40_SISO 59 ++#define TXP_FIRST_OFDM_40_CDD 60 ++#define TXP_LAST_OFDM_40_CDD 67 ++#define TXP_FIRST_MCS_40_SISO 68 ++#define TXP_LAST_MCS_40_SISO 75 ++#define TXP_FIRST_MCS_40_CDD 76 ++#define TXP_LAST_MCS_40_CDD 83 ++#define TXP_FIRST_MCS_40_STBC 84 ++#define TXP_LAST_MCS_40_STBC 91 ++#define TXP_FIRST_MCS_40_SDM 92 ++#define TXP_LAST_MCS_40_SDM 99 ++#define TXP_MCS_32 100 ++#define TXP_NUM_RATES 101 ++#define ADJ_PWR_TBL_LEN 84 ++ ++#define TXP_FIRST_SISO_MCS_20 20 ++#define TXP_LAST_SISO_MCS_20 27 ++ ++#define PHY_CORE_NUM_1 1 ++#define PHY_CORE_NUM_2 2 ++#define PHY_CORE_NUM_3 3 ++#define PHY_CORE_NUM_4 4 ++#define PHY_CORE_MAX PHY_CORE_NUM_4 ++#define PHY_CORE_0 0 ++#define PHY_CORE_1 1 ++#define PHY_CORE_2 2 ++#define PHY_CORE_3 3 ++ ++#define MA_WINDOW_SZ 8 ++ ++#define PHY_NOISE_SAMPLE_MON 1 ++#define PHY_NOISE_SAMPLE_EXTERNAL 2 ++#define PHY_NOISE_WINDOW_SZ 16 ++#define PHY_NOISE_GLITCH_INIT_MA 10 ++#define PHY_NOISE_GLITCH_INIT_MA_BADPlCP 10 ++#define PHY_NOISE_STATE_MON 0x1 ++#define PHY_NOISE_STATE_EXTERNAL 0x2 ++#define PHY_NOISE_SAMPLE_LOG_NUM_NPHY 10 ++#define PHY_NOISE_SAMPLE_LOG_NUM_UCODE 9 ++ ++#define PHY_NOISE_OFFSETFACT_4322 (-103) ++#define PHY_NOISE_MA_WINDOW_SZ 2 ++ ++#define PHY_RSSI_TABLE_SIZE 64 ++#define RSSI_ANT_MERGE_MAX 0 ++#define RSSI_ANT_MERGE_MIN 1 ++#define RSSI_ANT_MERGE_AVG 2 ++ ++#define PHY_TSSI_TABLE_SIZE 64 ++#define APHY_TSSI_TABLE_SIZE 256 ++#define TX_GAIN_TABLE_LENGTH 64 ++#define DEFAULT_11A_TXP_IDX 24 ++#define NUM_TSSI_FRAMES 4 ++#define NULL_TSSI 0x7f ++#define NULL_TSSI_W 0x7f7f ++ ++#define PHY_PAPD_EPS_TBL_SIZE_LCNPHY 64 ++ ++#define LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL 9 ++ ++#define PHY_TXPWR_MIN 10 ++#define PHY_TXPWR_MIN_NPHY 8 ++#define RADIOPWR_OVERRIDE_DEF (-1) ++ ++#define PWRTBL_NUM_COEFF 3 ++ ++#define SPURAVOID_DISABLE 0 ++#define SPURAVOID_AUTO 1 ++#define SPURAVOID_FORCEON 2 ++#define SPURAVOID_FORCEON2 3 ++ ++#define PHY_SW_TIMER_FAST 15 ++#define PHY_SW_TIMER_SLOW 60 ++#define PHY_SW_TIMER_GLACIAL 120 ++ ++#define PHY_PERICAL_AUTO 0 ++#define PHY_PERICAL_FULL 1 ++#define PHY_PERICAL_PARTIAL 2 ++ ++#define PHY_PERICAL_NODELAY 0 ++#define PHY_PERICAL_INIT_DELAY 5 ++#define PHY_PERICAL_ASSOC_DELAY 5 ++#define PHY_PERICAL_WDOG_DELAY 5 ++ ++#define MPHASE_TXCAL_NUMCMDS 2 ++ ++#define PHY_PERICAL_MPHASE_PENDING(pi) \ ++ (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_IDLE) ++ ++enum { ++ MPHASE_CAL_STATE_IDLE = 0, ++ MPHASE_CAL_STATE_INIT = 1, ++ MPHASE_CAL_STATE_TXPHASE0, ++ MPHASE_CAL_STATE_TXPHASE1, ++ MPHASE_CAL_STATE_TXPHASE2, ++ MPHASE_CAL_STATE_TXPHASE3, ++ MPHASE_CAL_STATE_TXPHASE4, ++ MPHASE_CAL_STATE_TXPHASE5, ++ MPHASE_CAL_STATE_PAPDCAL, ++ MPHASE_CAL_STATE_RXCAL, ++ MPHASE_CAL_STATE_RSSICAL, ++ MPHASE_CAL_STATE_IDLETSSI ++}; ++ ++enum phy_cal_mode { ++ CAL_FULL, ++ CAL_RECAL, ++ CAL_CURRECAL, ++ CAL_DIGCAL, ++ CAL_GCTRL, ++ CAL_SOFT, ++ CAL_DIGLO ++}; ++ ++#define RDR_NTIERS 1 ++#define RDR_TIER_SIZE 64 ++#define RDR_LIST_SIZE (512/3) ++#define RDR_EPOCH_SIZE 40 ++#define RDR_NANTENNAS 2 ++#define RDR_NTIER_SIZE RDR_LIST_SIZE ++#define RDR_LP_BUFFER_SIZE 64 ++#define LP_LEN_HIS_SIZE 10 ++ ++#define STATIC_NUM_RF 32 ++#define STATIC_NUM_BB 9 ++ ++#define BB_MULT_MASK 0x0000ffff ++#define BB_MULT_VALID_MASK 0x80000000 ++ ++#define CORDIC_AG 39797 ++#define CORDIC_NI 18 ++#define FIXED(X) ((s32)((X) << 16)) ++ ++#define FLOAT(X) \ ++ (((X) >= 0) ? ((((X) >> 15) + 1) >> 1) : -((((-(X)) >> 15) + 1) >> 1)) ++ ++#define PHY_CHAIN_TX_DISABLE_TEMP 115 ++#define PHY_HYSTERESIS_DELTATEMP 5 ++ ++#define SCAN_INPROG_PHY(pi) \ ++ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN)) ++ ++#define PLT_INPROG_PHY(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_PLT)) ++ ++#define ASSOC_INPROG_PHY(pi) \ ++ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_ASSOC)) ++ ++#define SCAN_RM_IN_PROGRESS(pi) \ ++ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN | PHY_HOLD_FOR_RM)) ++ ++#define PHY_MUTED(pi) \ ++ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_MUTE)) ++ ++#define PUB_NOT_ASSOC(pi) \ ++ (mboolisset(pi->measure_hold, PHY_HOLD_FOR_NOT_ASSOC)) ++ ++struct phy_table_info { ++ uint table; ++ int q; ++ uint max; ++}; ++ ++struct phytbl_info { ++ const void *tbl_ptr; ++ u32 tbl_len; ++ u32 tbl_id; ++ u32 tbl_offset; ++ u32 tbl_width; ++}; ++ ++struct interference_info { ++ u8 curr_home_channel; ++ u16 crsminpwrthld_40_stored; ++ u16 crsminpwrthld_20L_stored; ++ u16 crsminpwrthld_20U_stored; ++ u16 init_gain_code_core1_stored; ++ u16 init_gain_code_core2_stored; ++ u16 init_gain_codeb_core1_stored; ++ u16 init_gain_codeb_core2_stored; ++ u16 init_gain_table_stored[4]; ++ ++ u16 clip1_hi_gain_code_core1_stored; ++ u16 clip1_hi_gain_code_core2_stored; ++ u16 clip1_hi_gain_codeb_core1_stored; ++ u16 clip1_hi_gain_codeb_core2_stored; ++ u16 nb_clip_thresh_core1_stored; ++ u16 nb_clip_thresh_core2_stored; ++ u16 init_ofdmlna2gainchange_stored[4]; ++ u16 init_ccklna2gainchange_stored[4]; ++ u16 clip1_lo_gain_code_core1_stored; ++ u16 clip1_lo_gain_code_core2_stored; ++ u16 clip1_lo_gain_codeb_core1_stored; ++ u16 clip1_lo_gain_codeb_core2_stored; ++ u16 w1_clip_thresh_core1_stored; ++ u16 w1_clip_thresh_core2_stored; ++ u16 radio_2056_core1_rssi_gain_stored; ++ u16 radio_2056_core2_rssi_gain_stored; ++ u16 energy_drop_timeout_len_stored; ++ ++ u16 ed_crs40_assertthld0_stored; ++ u16 ed_crs40_assertthld1_stored; ++ u16 ed_crs40_deassertthld0_stored; ++ u16 ed_crs40_deassertthld1_stored; ++ u16 ed_crs20L_assertthld0_stored; ++ u16 ed_crs20L_assertthld1_stored; ++ u16 ed_crs20L_deassertthld0_stored; ++ u16 ed_crs20L_deassertthld1_stored; ++ u16 ed_crs20U_assertthld0_stored; ++ u16 ed_crs20U_assertthld1_stored; ++ u16 ed_crs20U_deassertthld0_stored; ++ u16 ed_crs20U_deassertthld1_stored; ++ ++ u16 badplcp_ma; ++ u16 badplcp_ma_previous; ++ u16 badplcp_ma_total; ++ u16 badplcp_ma_list[MA_WINDOW_SZ]; ++ int badplcp_ma_index; ++ s16 pre_badplcp_cnt; ++ s16 bphy_pre_badplcp_cnt; ++ ++ u16 init_gain_core1; ++ u16 init_gain_core2; ++ u16 init_gainb_core1; ++ u16 init_gainb_core2; ++ u16 init_gain_rfseq[4]; ++ ++ u16 crsminpwr0; ++ u16 crsminpwrl0; ++ u16 crsminpwru0; ++ ++ s16 crsminpwr_index; ++ ++ u16 radio_2057_core1_rssi_wb1a_gc_stored; ++ u16 radio_2057_core2_rssi_wb1a_gc_stored; ++ u16 radio_2057_core1_rssi_wb1g_gc_stored; ++ u16 radio_2057_core2_rssi_wb1g_gc_stored; ++ u16 radio_2057_core1_rssi_wb2_gc_stored; ++ u16 radio_2057_core2_rssi_wb2_gc_stored; ++ u16 radio_2057_core1_rssi_nb_gc_stored; ++ u16 radio_2057_core2_rssi_nb_gc_stored; ++}; ++ ++struct aci_save_gphy { ++ u16 rc_cal_ovr; ++ u16 phycrsth1; ++ u16 phycrsth2; ++ u16 init_n1p1_gain; ++ u16 p1_p2_gain; ++ u16 n1_n2_gain; ++ u16 n1_p1_gain; ++ u16 div_search_gain; ++ u16 div_p1_p2_gain; ++ u16 div_search_gn_change; ++ u16 table_7_2; ++ u16 table_7_3; ++ u16 cckshbits_gnref; ++ u16 clip_thresh; ++ u16 clip2_thresh; ++ u16 clip3_thresh; ++ u16 clip_p2_thresh; ++ u16 clip_pwdn_thresh; ++ u16 clip_n1p1_thresh; ++ u16 clip_n1_pwdn_thresh; ++ u16 bbconfig; ++ u16 cthr_sthr_shdin; ++ u16 energy; ++ u16 clip_p1_p2_thresh; ++ u16 threshold; ++ u16 reg15; ++ u16 reg16; ++ u16 reg17; ++ u16 div_srch_idx; ++ u16 div_srch_p1_p2; ++ u16 div_srch_gn_back; ++ u16 ant_dwell; ++ u16 ant_wr_settle; ++}; ++ ++struct lo_complex_abgphy_info { ++ s8 i; ++ s8 q; ++}; ++ ++struct nphy_iq_comp { ++ s16 a0; ++ s16 b0; ++ s16 a1; ++ s16 b1; ++}; ++ ++struct nphy_txpwrindex { ++ s8 index; ++ s8 index_internal; ++ s8 index_internal_save; ++ u16 AfectrlOverride; ++ u16 AfeCtrlDacGain; ++ u16 rad_gain; ++ u8 bbmult; ++ u16 iqcomp_a; ++ u16 iqcomp_b; ++ u16 locomp; ++}; ++ ++struct txiqcal_cache { ++ ++ u16 txcal_coeffs_2G[8]; ++ u16 txcal_radio_regs_2G[8]; ++ struct nphy_iq_comp rxcal_coeffs_2G; ++ ++ u16 txcal_coeffs_5G[8]; ++ u16 txcal_radio_regs_5G[8]; ++ struct nphy_iq_comp rxcal_coeffs_5G; ++}; ++ ++struct nphy_pwrctrl { ++ s8 max_pwr_2g; ++ s8 idle_targ_2g; ++ s16 pwrdet_2g_a1; ++ s16 pwrdet_2g_b0; ++ s16 pwrdet_2g_b1; ++ s8 max_pwr_5gm; ++ s8 idle_targ_5gm; ++ s8 max_pwr_5gh; ++ s8 max_pwr_5gl; ++ s16 pwrdet_5gm_a1; ++ s16 pwrdet_5gm_b0; ++ s16 pwrdet_5gm_b1; ++ s16 pwrdet_5gl_a1; ++ s16 pwrdet_5gl_b0; ++ s16 pwrdet_5gl_b1; ++ s16 pwrdet_5gh_a1; ++ s16 pwrdet_5gh_b0; ++ s16 pwrdet_5gh_b1; ++ s8 idle_targ_5gl; ++ s8 idle_targ_5gh; ++ s8 idle_tssi_2g; ++ s8 idle_tssi_5g; ++ s8 idle_tssi; ++ s16 a1; ++ s16 b0; ++ s16 b1; ++}; ++ ++struct nphy_txgains { ++ u16 txlpf[2]; ++ u16 txgm[2]; ++ u16 pga[2]; ++ u16 pad[2]; ++ u16 ipa[2]; ++}; ++ ++#define PHY_NOISEVAR_BUFSIZE 10 ++ ++struct nphy_noisevar_buf { ++ int bufcount; ++ int tone_id[PHY_NOISEVAR_BUFSIZE]; ++ u32 noise_vars[PHY_NOISEVAR_BUFSIZE]; ++ u32 min_noise_vars[PHY_NOISEVAR_BUFSIZE]; ++}; ++ ++struct rssical_cache { ++ u16 rssical_radio_regs_2G[2]; ++ u16 rssical_phyregs_2G[12]; ++ ++ u16 rssical_radio_regs_5G[2]; ++ u16 rssical_phyregs_5G[12]; ++}; ++ ++struct lcnphy_cal_results { ++ ++ u16 txiqlocal_a; ++ u16 txiqlocal_b; ++ u16 txiqlocal_didq; ++ u8 txiqlocal_ei0; ++ u8 txiqlocal_eq0; ++ u8 txiqlocal_fi0; ++ u8 txiqlocal_fq0; ++ ++ u16 txiqlocal_bestcoeffs[11]; ++ u16 txiqlocal_bestcoeffs_valid; ++ ++ u32 papd_eps_tbl[PHY_PAPD_EPS_TBL_SIZE_LCNPHY]; ++ u16 analog_gain_ref; ++ u16 lut_begin; ++ u16 lut_end; ++ u16 lut_step; ++ u16 rxcompdbm; ++ u16 papdctrl; ++ u16 sslpnCalibClkEnCtrl; ++ ++ u16 rxiqcal_coeff_a0; ++ u16 rxiqcal_coeff_b0; ++}; ++ ++struct shared_phy { ++ struct brcms_phy *phy_head; ++ uint unit; ++ struct si_pub *sih; ++ struct phy_shim_info *physhim; ++ uint corerev; ++ u32 machwcap; ++ bool up; ++ bool clk; ++ uint now; ++ u16 vid; ++ u16 did; ++ uint chip; ++ uint chiprev; ++ uint chippkg; ++ uint sromrev; ++ uint boardtype; ++ uint boardrev; ++ uint boardvendor; ++ u32 boardflags; ++ u32 boardflags2; ++ uint buscorerev; ++ uint fast_timer; ++ uint slow_timer; ++ uint glacial_timer; ++ u8 rx_antdiv; ++ s8 phy_noise_window[MA_WINDOW_SZ]; ++ uint phy_noise_index; ++ u8 hw_phytxchain; ++ u8 hw_phyrxchain; ++ u8 phytxchain; ++ u8 phyrxchain; ++ u8 rssi_mode; ++ bool _rifs_phy; ++}; ++ ++struct brcms_phy_pub { ++ uint phy_type; ++ uint phy_rev; ++ u8 phy_corenum; ++ u16 radioid; ++ u8 radiorev; ++ u8 radiover; ++ ++ uint coreflags; ++ uint ana_rev; ++ bool abgphy_encore; ++}; ++ ++struct phy_func_ptr { ++ void (*init)(struct brcms_phy *); ++ void (*calinit)(struct brcms_phy *); ++ void (*chanset)(struct brcms_phy *, u16 chanspec); ++ void (*txpwrrecalc)(struct brcms_phy *); ++ int (*longtrn)(struct brcms_phy *, int); ++ void (*txiqccget)(struct brcms_phy *, u16 *, u16 *); ++ void (*txiqccset)(struct brcms_phy *, u16, u16); ++ u16 (*txloccget)(struct brcms_phy *); ++ void (*radioloftget)(struct brcms_phy *, u8 *, u8 *, u8 *, u8 *); ++ void (*carrsuppr)(struct brcms_phy *); ++ s32 (*rxsigpwr)(struct brcms_phy *, s32); ++ void (*detach)(struct brcms_phy *); ++}; ++ ++struct brcms_phy { ++ struct brcms_phy_pub pubpi_ro; ++ struct shared_phy *sh; ++ struct phy_func_ptr pi_fptr; ++ ++ union { ++ struct brcms_phy_lcnphy *pi_lcnphy; ++ } u; ++ bool user_txpwr_at_rfport; ++ ++ struct d11regs __iomem *regs; ++ struct brcms_phy *next; ++ struct brcms_phy_pub pubpi; ++ ++ bool do_initcal; ++ bool phytest_on; ++ bool ofdm_rateset_war; ++ bool bf_preempt_4306; ++ u16 radio_chanspec; ++ u8 antsel_type; ++ u16 bw; ++ u8 txpwr_percent; ++ bool phy_init_por; ++ ++ bool init_in_progress; ++ bool initialized; ++ bool sbtml_gm; ++ uint refcnt; ++ bool watchdog_override; ++ u8 phynoise_state; ++ uint phynoise_now; ++ int phynoise_chan_watchdog; ++ bool phynoise_polling; ++ bool disable_percal; ++ u32 measure_hold; ++ ++ s16 txpa_2g[PWRTBL_NUM_COEFF]; ++ s16 txpa_2g_low_temp[PWRTBL_NUM_COEFF]; ++ s16 txpa_2g_high_temp[PWRTBL_NUM_COEFF]; ++ s16 txpa_5g_low[PWRTBL_NUM_COEFF]; ++ s16 txpa_5g_mid[PWRTBL_NUM_COEFF]; ++ s16 txpa_5g_hi[PWRTBL_NUM_COEFF]; ++ ++ u8 tx_srom_max_2g; ++ u8 tx_srom_max_5g_low; ++ u8 tx_srom_max_5g_mid; ++ u8 tx_srom_max_5g_hi; ++ u8 tx_srom_max_rate_2g[TXP_NUM_RATES]; ++ u8 tx_srom_max_rate_5g_low[TXP_NUM_RATES]; ++ u8 tx_srom_max_rate_5g_mid[TXP_NUM_RATES]; ++ u8 tx_srom_max_rate_5g_hi[TXP_NUM_RATES]; ++ u8 tx_user_target[TXP_NUM_RATES]; ++ s8 tx_power_offset[TXP_NUM_RATES]; ++ u8 tx_power_target[TXP_NUM_RATES]; ++ ++ struct brcms_phy_srom_fem srom_fem2g; ++ struct brcms_phy_srom_fem srom_fem5g; ++ ++ u8 tx_power_max; ++ u8 tx_power_max_rate_ind; ++ bool hwpwrctrl; ++ u8 nphy_txpwrctrl; ++ s8 nphy_txrx_chain; ++ bool phy_5g_pwrgain; ++ ++ u16 phy_wreg; ++ u16 phy_wreg_limit; ++ ++ s8 n_preamble_override; ++ u8 antswitch; ++ u8 aa2g, aa5g; ++ ++ s8 idle_tssi[CH_5G_GROUP]; ++ s8 target_idle_tssi; ++ s8 txpwr_est_Pout; ++ u8 tx_power_min; ++ u8 txpwr_limit[TXP_NUM_RATES]; ++ u8 txpwr_env_limit[TXP_NUM_RATES]; ++ u8 adj_pwr_tbl_nphy[ADJ_PWR_TBL_LEN]; ++ ++ bool channel_14_wide_filter; ++ ++ bool txpwroverride; ++ bool txpwridx_override_aphy; ++ s16 radiopwr_override; ++ u16 hwpwr_txcur; ++ u8 saved_txpwr_idx; ++ ++ bool edcrs_threshold_lock; ++ ++ u32 tr_R_gain_val; ++ u32 tr_T_gain_val; ++ ++ s16 ofdm_analog_filt_bw_override; ++ s16 cck_analog_filt_bw_override; ++ s16 ofdm_rccal_override; ++ s16 cck_rccal_override; ++ u16 extlna_type; ++ ++ uint interference_mode_crs_time; ++ u16 crsglitch_prev; ++ bool interference_mode_crs; ++ ++ u32 phy_tx_tone_freq; ++ uint phy_lastcal; ++ bool phy_forcecal; ++ bool phy_fixed_noise; ++ u32 xtalfreq; ++ u8 pdiv; ++ s8 carrier_suppr_disable; ++ ++ bool phy_bphy_evm; ++ bool phy_bphy_rfcs; ++ s8 phy_scraminit; ++ u8 phy_gpiosel; ++ ++ s16 phy_txcore_disable_temp; ++ s16 phy_txcore_enable_temp; ++ s8 phy_tempsense_offset; ++ bool phy_txcore_heatedup; ++ ++ u16 radiopwr; ++ u16 bb_atten; ++ u16 txctl1; ++ ++ u16 mintxbias; ++ u16 mintxmag; ++ struct lo_complex_abgphy_info gphy_locomp_iq ++ [STATIC_NUM_RF][STATIC_NUM_BB]; ++ s8 stats_11b_txpower[STATIC_NUM_RF][STATIC_NUM_BB]; ++ u16 gain_table[TX_GAIN_TABLE_LENGTH]; ++ bool loopback_gain; ++ s16 max_lpback_gain_hdB; ++ s16 trsw_rx_gain_hdB; ++ u8 power_vec[8]; ++ ++ u16 rc_cal; ++ int nrssi_table_delta; ++ int nrssi_slope_scale; ++ int nrssi_slope_offset; ++ int min_rssi; ++ int max_rssi; ++ ++ s8 txpwridx; ++ u8 min_txpower; ++ ++ u8 a_band_high_disable; ++ ++ u16 tx_vos; ++ u16 global_tx_bb_dc_bias_loft; ++ ++ int rf_max; ++ int bb_max; ++ int rf_list_size; ++ int bb_list_size; ++ u16 *rf_attn_list; ++ u16 *bb_attn_list; ++ u16 padmix_mask; ++ u16 padmix_reg; ++ u16 *txmag_list; ++ uint txmag_len; ++ bool txmag_enable; ++ ++ s8 *a_tssi_to_dbm; ++ s8 *m_tssi_to_dbm; ++ s8 *l_tssi_to_dbm; ++ s8 *h_tssi_to_dbm; ++ u8 *hwtxpwr; ++ ++ u16 freqtrack_saved_regs[2]; ++ int cur_interference_mode; ++ bool hwpwrctrl_capable; ++ bool temppwrctrl_capable; ++ ++ uint phycal_nslope; ++ uint phycal_noffset; ++ uint phycal_mlo; ++ uint phycal_txpower; ++ ++ u8 phy_aa2g; ++ ++ bool nphy_tableloaded; ++ s8 nphy_rssisel; ++ u32 nphy_bb_mult_save; ++ u16 nphy_txiqlocal_bestc[11]; ++ bool nphy_txiqlocal_coeffsvalid; ++ struct nphy_txpwrindex nphy_txpwrindex[PHY_CORE_NUM_2]; ++ struct nphy_pwrctrl nphy_pwrctrl_info[PHY_CORE_NUM_2]; ++ u16 cck2gpo; ++ u32 ofdm2gpo; ++ u32 ofdm5gpo; ++ u32 ofdm5glpo; ++ u32 ofdm5ghpo; ++ u8 bw402gpo; ++ u8 bw405gpo; ++ u8 bw405glpo; ++ u8 bw405ghpo; ++ u8 cdd2gpo; ++ u8 cdd5gpo; ++ u8 cdd5glpo; ++ u8 cdd5ghpo; ++ u8 stbc2gpo; ++ u8 stbc5gpo; ++ u8 stbc5glpo; ++ u8 stbc5ghpo; ++ u8 bwdup2gpo; ++ u8 bwdup5gpo; ++ u8 bwdup5glpo; ++ u8 bwdup5ghpo; ++ u16 mcs2gpo[8]; ++ u16 mcs5gpo[8]; ++ u16 mcs5glpo[8]; ++ u16 mcs5ghpo[8]; ++ u32 nphy_rxcalparams; ++ ++ u8 phy_spuravoid; ++ bool phy_isspuravoid; ++ ++ u8 phy_pabias; ++ u8 nphy_papd_skip; ++ u8 nphy_tssi_slope; ++ ++ s16 nphy_noise_win[PHY_CORE_MAX][PHY_NOISE_WINDOW_SZ]; ++ u8 nphy_noise_index; ++ ++ u8 nphy_txpid2g[PHY_CORE_NUM_2]; ++ u8 nphy_txpid5g[PHY_CORE_NUM_2]; ++ u8 nphy_txpid5gl[PHY_CORE_NUM_2]; ++ u8 nphy_txpid5gh[PHY_CORE_NUM_2]; ++ ++ bool nphy_gain_boost; ++ bool nphy_elna_gain_config; ++ u16 old_bphy_test; ++ u16 old_bphy_testcontrol; ++ ++ bool phyhang_avoid; ++ ++ bool rssical_nphy; ++ u8 nphy_perical; ++ uint nphy_perical_last; ++ u8 cal_type_override; ++ u8 mphase_cal_phase_id; ++ u8 mphase_txcal_cmdidx; ++ u8 mphase_txcal_numcmds; ++ u16 mphase_txcal_bestcoeffs[11]; ++ u16 nphy_txiqlocal_chanspec; ++ u16 nphy_iqcal_chanspec_2G; ++ u16 nphy_iqcal_chanspec_5G; ++ u16 nphy_rssical_chanspec_2G; ++ u16 nphy_rssical_chanspec_5G; ++ struct wlapi_timer *phycal_timer; ++ bool use_int_tx_iqlo_cal_nphy; ++ bool internal_tx_iqlo_cal_tapoff_intpa_nphy; ++ s16 nphy_lastcal_temp; ++ ++ struct txiqcal_cache calibration_cache; ++ struct rssical_cache rssical_cache; ++ ++ u8 nphy_txpwr_idx[2]; ++ u8 nphy_papd_cal_type; ++ uint nphy_papd_last_cal; ++ u16 nphy_papd_tx_gain_at_last_cal[2]; ++ u8 nphy_papd_cal_gain_index[2]; ++ s16 nphy_papd_epsilon_offset[2]; ++ bool nphy_papd_recal_enable; ++ u32 nphy_papd_recal_counter; ++ bool nphy_force_papd_cal; ++ bool nphy_papdcomp; ++ bool ipa2g_on; ++ bool ipa5g_on; ++ ++ u16 classifier_state; ++ u16 clip_state[2]; ++ uint nphy_deaf_count; ++ u8 rxiq_samps; ++ u8 rxiq_antsel; ++ ++ u16 rfctrlIntc1_save; ++ u16 rfctrlIntc2_save; ++ bool first_cal_after_assoc; ++ u16 tx_rx_cal_radio_saveregs[22]; ++ u16 tx_rx_cal_phy_saveregs[15]; ++ ++ u8 nphy_cal_orig_pwr_idx[2]; ++ u8 nphy_txcal_pwr_idx[2]; ++ u8 nphy_rxcal_pwr_idx[2]; ++ u16 nphy_cal_orig_tx_gain[2]; ++ struct nphy_txgains nphy_cal_target_gain; ++ u16 nphy_txcal_bbmult; ++ u16 nphy_gmval; ++ ++ u16 nphy_saved_bbconf; ++ ++ bool nphy_gband_spurwar_en; ++ bool nphy_gband_spurwar2_en; ++ bool nphy_aband_spurwar_en; ++ u16 nphy_rccal_value; ++ u16 nphy_crsminpwr[3]; ++ struct nphy_noisevar_buf nphy_saved_noisevars; ++ bool nphy_anarxlpf_adjusted; ++ bool nphy_crsminpwr_adjusted; ++ bool nphy_noisevars_adjusted; ++ ++ bool nphy_rxcal_active; ++ u16 radar_percal_mask; ++ bool dfs_lp_buffer_nphy; ++ ++ u16 nphy_fineclockgatecontrol; ++ ++ s8 rx2tx_biasentry; ++ ++ u16 crsminpwr0; ++ u16 crsminpwrl0; ++ u16 crsminpwru0; ++ s16 noise_crsminpwr_index; ++ u16 init_gain_core1; ++ u16 init_gain_core2; ++ u16 init_gainb_core1; ++ u16 init_gainb_core2; ++ u8 aci_noise_curr_channel; ++ u16 init_gain_rfseq[4]; ++ ++ bool radio_is_on; ++ ++ bool nphy_sample_play_lpf_bw_ctl_ovr; ++ ++ u16 tbl_data_hi; ++ u16 tbl_data_lo; ++ u16 tbl_addr; ++ ++ uint tbl_save_id; ++ uint tbl_save_offset; ++ ++ u8 txpwrctrl; ++ s8 txpwrindex[PHY_CORE_MAX]; ++ ++ u8 phycal_tempdelta; ++ u32 mcs20_po; ++ u32 mcs40_po; ++ struct wiphy *wiphy; ++}; ++ ++struct cs32 { ++ s32 q; ++ s32 i; ++}; ++ ++struct radio_regs { ++ u16 address; ++ u32 init_a; ++ u32 init_g; ++ u8 do_init_a; ++ u8 do_init_g; ++}; ++ ++struct radio_20xx_regs { ++ u16 address; ++ u8 init; ++ u8 do_init; ++}; ++ ++struct lcnphy_radio_regs { ++ u16 address; ++ u8 init_a; ++ u8 init_g; ++ u8 do_init_a; ++ u8 do_init_g; ++}; ++ ++extern u16 read_phy_reg(struct brcms_phy *pi, u16 addr); ++extern void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val); ++extern void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val); ++extern void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val); ++extern void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val); ++ ++extern u16 read_radio_reg(struct brcms_phy *pi, u16 addr); ++extern void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val); ++extern void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val); ++extern void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, ++ u16 val); ++extern void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask); ++ ++extern void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val); ++ ++extern void wlc_phyreg_enter(struct brcms_phy_pub *pih); ++extern void wlc_phyreg_exit(struct brcms_phy_pub *pih); ++extern void wlc_radioreg_enter(struct brcms_phy_pub *pih); ++extern void wlc_radioreg_exit(struct brcms_phy_pub *pih); ++ ++extern void wlc_phy_read_table(struct brcms_phy *pi, ++ const struct phytbl_info *ptbl_info, ++ u16 tblAddr, u16 tblDataHi, ++ u16 tblDatalo); ++extern void wlc_phy_write_table(struct brcms_phy *pi, ++ const struct phytbl_info *ptbl_info, ++ u16 tblAddr, u16 tblDataHi, u16 tblDatalo); ++extern void wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, ++ uint tbl_offset, u16 tblAddr, u16 tblDataHi, ++ u16 tblDataLo); ++extern void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val); ++ ++extern void write_phy_channel_reg(struct brcms_phy *pi, uint val); ++extern void wlc_phy_txpower_update_shm(struct brcms_phy *pi); ++ ++extern u8 wlc_phy_nbits(s32 value); ++extern void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_dB, u8 core); ++ ++extern uint wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi, ++ struct radio_20xx_regs *radioregs); ++extern uint wlc_phy_init_radio_regs(struct brcms_phy *pi, ++ const struct radio_regs *radioregs, ++ u16 core_offset); ++ ++extern void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi); ++ ++extern void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on); ++extern void wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, ++ s32 *eps_imag); ++ ++extern void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi); ++extern void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi); ++ ++extern bool wlc_phy_attach_nphy(struct brcms_phy *pi); ++extern bool wlc_phy_attach_lcnphy(struct brcms_phy *pi); ++ ++extern void wlc_phy_detach_lcnphy(struct brcms_phy *pi); ++ ++extern void wlc_phy_init_nphy(struct brcms_phy *pi); ++extern void wlc_phy_init_lcnphy(struct brcms_phy *pi); ++ ++extern void wlc_phy_cal_init_nphy(struct brcms_phy *pi); ++extern void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi); ++ ++extern void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, ++ u16 chanspec); ++extern void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, ++ u16 chanspec); ++extern void wlc_phy_chanspec_set_fixup_lcnphy(struct brcms_phy *pi, ++ u16 chanspec); ++extern int wlc_phy_channel2freq(uint channel); ++extern int wlc_phy_chanspec_freq2bandrange_lpssn(uint); ++extern int wlc_phy_chanspec_bandrange_get(struct brcms_phy *, u16 chanspec); ++ ++extern void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode); ++extern s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi); ++ ++extern void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi); ++extern void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi); ++extern void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi); ++ ++extern void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index); ++extern void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable); ++extern void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi); ++extern void wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, ++ u16 max_val, bool iqcalmode); ++ ++extern void wlc_phy_txpower_sromlimit_get_nphy(struct brcms_phy *pi, uint chan, ++ u8 *max_pwr, u8 rate_id); ++extern void wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start, ++ u8 rate_mcs_end, ++ u8 rate_ofdm_start); ++extern void wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power, ++ u8 rate_ofdm_start, ++ u8 rate_ofdm_end, ++ u8 rate_mcs_start); ++ ++extern u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode); ++extern s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode); ++extern s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode); ++extern s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode); ++extern void wlc_phy_carrier_suppress_lcnphy(struct brcms_phy *pi); ++extern void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel); ++extern void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode); ++extern void wlc_2064_vco_cal(struct brcms_phy *pi); ++ ++extern void wlc_phy_txpower_recalc_target(struct brcms_phy *pi); ++ ++#define LCNPHY_TBL_ID_PAPDCOMPDELTATBL 0x18 ++#define LCNPHY_TX_POWER_TABLE_SIZE 128 ++#define LCNPHY_MAX_TX_POWER_INDEX (LCNPHY_TX_POWER_TABLE_SIZE - 1) ++#define LCNPHY_TBL_ID_TXPWRCTL 0x07 ++#define LCNPHY_TX_PWR_CTRL_OFF 0 ++#define LCNPHY_TX_PWR_CTRL_SW (0x1 << 15) ++#define LCNPHY_TX_PWR_CTRL_HW ((0x1 << 15) | \ ++ (0x1 << 14) | \ ++ (0x1 << 13)) ++ ++#define LCNPHY_TX_PWR_CTRL_TEMPBASED 0xE001 ++ ++extern void wlc_lcnphy_write_table(struct brcms_phy *pi, ++ const struct phytbl_info *pti); ++extern void wlc_lcnphy_read_table(struct brcms_phy *pi, ++ struct phytbl_info *pti); ++extern void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b); ++extern void wlc_lcnphy_set_tx_locc(struct brcms_phy *pi, u16 didq); ++extern void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b); ++extern u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi); ++extern void wlc_lcnphy_get_radio_loft(struct brcms_phy *pi, u8 *ei0, ++ u8 *eq0, u8 *fi0, u8 *fq0); ++extern void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode); ++extern void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode); ++extern bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi); ++extern void wlc_lcnphy_tx_pwr_update_npt(struct brcms_phy *pi); ++extern s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1); ++extern void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, ++ s8 *cck_pwr); ++extern void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi); ++ ++extern s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index); ++ ++#define NPHY_MAX_HPVGA1_INDEX 10 ++#define NPHY_DEF_HPVGA1_INDEXLIMIT 7 ++ ++struct phy_iq_est { ++ s32 iq_prod; ++ u32 i_pwr; ++ u32 q_pwr; ++}; ++ ++extern void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi, ++ bool enable); ++extern void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode); ++ ++#define wlc_phy_write_table_nphy(pi, pti) \ ++ wlc_phy_write_table(pi, pti, 0x72, 0x74, 0x73) ++ ++#define wlc_phy_read_table_nphy(pi, pti) \ ++ wlc_phy_read_table(pi, pti, 0x72, 0x74, 0x73) ++ ++#define wlc_nphy_table_addr(pi, id, off) \ ++ wlc_phy_table_addr((pi), (id), (off), 0x72, 0x74, 0x73) ++ ++#define wlc_nphy_table_data_write(pi, w, v) \ ++ wlc_phy_table_data_write((pi), (w), (v)) ++ ++extern void wlc_phy_table_read_nphy(struct brcms_phy *pi, u32, u32 l, u32 o, ++ u32 w, void *d); ++extern void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32, u32, u32, ++ u32, const void *); ++ ++#define PHY_IPA(pi) \ ++ ((pi->ipa2g_on && CHSPEC_IS2G(pi->radio_chanspec)) || \ ++ (pi->ipa5g_on && CHSPEC_IS5G(pi->radio_chanspec))) ++ ++#define BRCMS_PHY_WAR_PR51571(pi) \ ++ if (NREV_LT((pi)->pubpi.phy_rev, 3)) \ ++ (void)R_REG(&(pi)->regs->maccontrol) ++ ++extern void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype); ++extern void wlc_phy_aci_reset_nphy(struct brcms_phy *pi); ++extern void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en); ++ ++extern u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint chan); ++extern void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on); ++ ++extern void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi); ++ ++extern void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd); ++extern s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi); ++ ++extern u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val); ++ ++extern void wlc_phy_rx_iq_est_nphy(struct brcms_phy *pi, struct phy_iq_est *est, ++ u16 num_samps, u8 wait_time, ++ u8 wait_for_crs); ++ ++extern void wlc_phy_rx_iq_coeffs_nphy(struct brcms_phy *pi, u8 write, ++ struct nphy_iq_comp *comp); ++extern void wlc_phy_aci_and_noise_reduction_nphy(struct brcms_phy *pi); ++ ++extern void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, ++ u8 rxcore_bitmask); ++extern u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih); ++ ++extern void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type); ++extern void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi); ++extern void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi); ++extern void wlc_phy_txpwr_papd_cal_nphy(struct brcms_phy *pi); ++extern u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi); ++ ++extern struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi); ++extern int wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, ++ struct nphy_txgains target_gain, ++ bool full, bool m); ++extern int wlc_phy_cal_rxiq_nphy(struct brcms_phy *pi, ++ struct nphy_txgains target_gain, ++ u8 type, bool d); ++extern void wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, ++ s8 txpwrindex, bool res); ++extern void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core, u8 rssi_type); ++extern int wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, ++ s32 *rssi_buf, u8 nsamps); ++extern void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi); ++extern int wlc_phy_aci_scan_nphy(struct brcms_phy *pi); ++extern void wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, ++ s32 dBm_targetpower, bool debug); ++extern int wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, ++ u8 mode, u8, bool); ++extern void wlc_phy_stopplayback_nphy(struct brcms_phy *pi); ++extern void wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, ++ u8 num_samps); ++extern void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi); ++ ++extern int wlc_phy_rssi_compute_nphy(struct brcms_phy *pi, ++ struct d11rxhdr *rxh); ++ ++#define NPHY_TESTPATTERN_BPHY_EVM 0 ++#define NPHY_TESTPATTERN_BPHY_RFCS 1 ++ ++extern void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs); ++ ++void wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, ++ s8 *ofdmoffset); ++extern s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, ++ u16 chanspec); ++ ++extern bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pih); ++#endif /* _BRCM_PHY_INT_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c.orig 2011-11-09 13:46:58.257800483 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c 2011-11-09 13:47:17.012566015 -0500 +@@ -0,0 +1,5154 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include "phy_qmath.h" ++#include "phy_hal.h" ++#include "phy_radio.h" ++#include "phytbl_lcn.h" ++#include "phy_lcn.h" ++ ++#define PLL_2064_NDIV 90 ++#define PLL_2064_LOW_END_VCO 3000 ++#define PLL_2064_LOW_END_KVCO 27 ++#define PLL_2064_HIGH_END_VCO 4200 ++#define PLL_2064_HIGH_END_KVCO 68 ++#define PLL_2064_LOOP_BW_DOUBLER 200 ++#define PLL_2064_D30_DOUBLER 10500 ++#define PLL_2064_LOOP_BW 260 ++#define PLL_2064_D30 8000 ++#define PLL_2064_CAL_REF_TO 8 ++#define PLL_2064_MHZ 1000000 ++#define PLL_2064_OPEN_LOOP_DELAY 5 ++ ++#define TEMPSENSE 1 ++#define VBATSENSE 2 ++ ++#define NOISE_IF_UPD_CHK_INTERVAL 1 ++#define NOISE_IF_UPD_RST_INTERVAL 60 ++#define NOISE_IF_UPD_THRESHOLD_CNT 1 ++#define NOISE_IF_UPD_TRHRESHOLD 50 ++#define NOISE_IF_UPD_TIMEOUT 1000 ++#define NOISE_IF_OFF 0 ++#define NOISE_IF_CHK 1 ++#define NOISE_IF_ON 2 ++ ++#define PAPD_BLANKING_PROFILE 3 ++#define PAPD2LUT 0 ++#define PAPD_CORR_NORM 0 ++#define PAPD_BLANKING_THRESHOLD 0 ++#define PAPD_STOP_AFTER_LAST_UPDATE 0 ++ ++#define LCN_TARGET_PWR 60 ++ ++#define LCN_VBAT_OFFSET_433X 34649679 ++#define LCN_VBAT_SLOPE_433X 8258032 ++ ++#define LCN_VBAT_SCALE_NOM 53 ++#define LCN_VBAT_SCALE_DEN 432 ++ ++#define LCN_TEMPSENSE_OFFSET 80812 ++#define LCN_TEMPSENSE_DEN 2647 ++ ++#define LCN_BW_LMT 200 ++#define LCN_CUR_LMT 1250 ++#define LCN_MULT 1 ++#define LCN_VCO_DIV 30 ++#define LCN_OFFSET 680 ++#define LCN_FACT 490 ++#define LCN_CUR_DIV 2640 ++ ++#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT \ ++ (0 + 8) ++#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK \ ++ (0x7f << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT) ++ ++#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT \ ++ (0 + 8) ++#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK \ ++ (0x7f << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT) ++ ++#define wlc_lcnphy_enable_tx_gain_override(pi) \ ++ wlc_lcnphy_set_tx_gain_override(pi, true) ++#define wlc_lcnphy_disable_tx_gain_override(pi) \ ++ wlc_lcnphy_set_tx_gain_override(pi, false) ++ ++#define wlc_lcnphy_iqcal_active(pi) \ ++ (read_phy_reg((pi), 0x451) & \ ++ ((0x1 << 15) | (0x1 << 14))) ++ ++#define txpwrctrl_off(pi) (0x7 != ((read_phy_reg(pi, 0x4a4) & 0xE000) >> 13)) ++#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \ ++ (pi->temppwrctrl_capable) ++#define wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) \ ++ (pi->hwpwrctrl_capable) ++ ++#define SWCTRL_BT_TX 0x18 ++#define SWCTRL_OVR_DISABLE 0x40 ++ ++#define AFE_CLK_INIT_MODE_TXRX2X 1 ++#define AFE_CLK_INIT_MODE_PAPD 0 ++ ++#define LCNPHY_TBL_ID_IQLOCAL 0x00 ++ ++#define LCNPHY_TBL_ID_RFSEQ 0x08 ++#define LCNPHY_TBL_ID_GAIN_IDX 0x0d ++#define LCNPHY_TBL_ID_SW_CTRL 0x0f ++#define LCNPHY_TBL_ID_GAIN_TBL 0x12 ++#define LCNPHY_TBL_ID_SPUR 0x14 ++#define LCNPHY_TBL_ID_SAMPLEPLAY 0x15 ++#define LCNPHY_TBL_ID_SAMPLEPLAY1 0x16 ++ ++#define LCNPHY_TX_PWR_CTRL_RATE_OFFSET 832 ++#define LCNPHY_TX_PWR_CTRL_MAC_OFFSET 128 ++#define LCNPHY_TX_PWR_CTRL_GAIN_OFFSET 192 ++#define LCNPHY_TX_PWR_CTRL_IQ_OFFSET 320 ++#define LCNPHY_TX_PWR_CTRL_LO_OFFSET 448 ++#define LCNPHY_TX_PWR_CTRL_PWR_OFFSET 576 ++ ++#define LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313 140 ++ ++#define LCNPHY_TX_PWR_CTRL_START_NPT 1 ++#define LCNPHY_TX_PWR_CTRL_MAX_NPT 7 ++ ++#define LCNPHY_NOISE_SAMPLES_DEFAULT 5000 ++ ++#define LCNPHY_ACI_DETECT_START 1 ++#define LCNPHY_ACI_DETECT_PROGRESS 2 ++#define LCNPHY_ACI_DETECT_STOP 3 ++ ++#define LCNPHY_ACI_CRSHIFRMLO_TRSH 100 ++#define LCNPHY_ACI_GLITCH_TRSH 2000 ++#define LCNPHY_ACI_TMOUT 250 ++#define LCNPHY_ACI_DETECT_TIMEOUT 2 ++#define LCNPHY_ACI_START_DELAY 0 ++ ++#define wlc_lcnphy_tx_gain_override_enabled(pi) \ ++ (0 != (read_phy_reg((pi), 0x43b) & (0x1 << 6))) ++ ++#define wlc_lcnphy_total_tx_frames(pi) \ ++ wlapi_bmac_read_shm((pi)->sh->physhim, M_UCODE_MACSTAT + \ ++ offsetof(struct macstat, txallfrm)) ++ ++struct lcnphy_txgains { ++ u16 gm_gain; ++ u16 pga_gain; ++ u16 pad_gain; ++ u16 dac_gain; ++}; ++ ++enum lcnphy_cal_mode { ++ LCNPHY_CAL_FULL, ++ LCNPHY_CAL_RECAL, ++ LCNPHY_CAL_CURRECAL, ++ LCNPHY_CAL_DIGCAL, ++ LCNPHY_CAL_GCTRL ++}; ++ ++struct lcnphy_rx_iqcomp { ++ u8 chan; ++ s16 a; ++ s16 b; ++}; ++ ++struct lcnphy_spb_tone { ++ s16 re; ++ s16 im; ++}; ++ ++struct lcnphy_unsign16_struct { ++ u16 re; ++ u16 im; ++}; ++ ++struct lcnphy_iq_est { ++ u32 iq_prod; ++ u32 i_pwr; ++ u32 q_pwr; ++}; ++ ++struct lcnphy_sfo_cfg { ++ u16 ptcentreTs20; ++ u16 ptcentreFactor; ++}; ++ ++enum lcnphy_papd_cal_type { ++ LCNPHY_PAPD_CAL_CW, ++ LCNPHY_PAPD_CAL_OFDM ++}; ++ ++typedef u16 iqcal_gain_params_lcnphy[9]; ++ ++static const iqcal_gain_params_lcnphy tbl_iqcal_gainparams_lcnphy_2G[] = { ++ {0, 0, 0, 0, 0, 0, 0, 0, 0}, ++}; ++ ++static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = { ++ tbl_iqcal_gainparams_lcnphy_2G, ++}; ++ ++static const u16 iqcal_gainparams_numgains_lcnphy[1] = { ++ sizeof(tbl_iqcal_gainparams_lcnphy_2G) / ++ sizeof(*tbl_iqcal_gainparams_lcnphy_2G), ++}; ++ ++static const struct lcnphy_sfo_cfg lcnphy_sfo_cfg[] = { ++ {965, 1087}, ++ {967, 1085}, ++ {969, 1082}, ++ {971, 1080}, ++ {973, 1078}, ++ {975, 1076}, ++ {977, 1073}, ++ {979, 1071}, ++ {981, 1069}, ++ {983, 1067}, ++ {985, 1065}, ++ {987, 1063}, ++ {989, 1060}, ++ {994, 1055} ++}; ++ ++static const ++u16 lcnphy_iqcal_loft_gainladder[] = { ++ ((2 << 8) | 0), ++ ((3 << 8) | 0), ++ ((4 << 8) | 0), ++ ((6 << 8) | 0), ++ ((8 << 8) | 0), ++ ((11 << 8) | 0), ++ ((16 << 8) | 0), ++ ((16 << 8) | 1), ++ ((16 << 8) | 2), ++ ((16 << 8) | 3), ++ ((16 << 8) | 4), ++ ((16 << 8) | 5), ++ ((16 << 8) | 6), ++ ((16 << 8) | 7), ++ ((23 << 8) | 7), ++ ((32 << 8) | 7), ++ ((45 << 8) | 7), ++ ((64 << 8) | 7), ++ ((91 << 8) | 7), ++ ((128 << 8) | 7) ++}; ++ ++static const ++u16 lcnphy_iqcal_ir_gainladder[] = { ++ ((1 << 8) | 0), ++ ((2 << 8) | 0), ++ ((4 << 8) | 0), ++ ((6 << 8) | 0), ++ ((8 << 8) | 0), ++ ((11 << 8) | 0), ++ ((16 << 8) | 0), ++ ((23 << 8) | 0), ++ ((32 << 8) | 0), ++ ((45 << 8) | 0), ++ ((64 << 8) | 0), ++ ((64 << 8) | 1), ++ ((64 << 8) | 2), ++ ((64 << 8) | 3), ++ ((64 << 8) | 4), ++ ((64 << 8) | 5), ++ ((64 << 8) | 6), ++ ((64 << 8) | 7), ++ ((91 << 8) | 7), ++ ((128 << 8) | 7) ++}; ++ ++static const ++struct lcnphy_spb_tone lcnphy_spb_tone_3750[] = { ++ {88, 0}, ++ {73, 49}, ++ {34, 81}, ++ {-17, 86}, ++ {-62, 62}, ++ {-86, 17}, ++ {-81, -34}, ++ {-49, -73}, ++ {0, -88}, ++ {49, -73}, ++ {81, -34}, ++ {86, 17}, ++ {62, 62}, ++ {17, 86}, ++ {-34, 81}, ++ {-73, 49}, ++ {-88, 0}, ++ {-73, -49}, ++ {-34, -81}, ++ {17, -86}, ++ {62, -62}, ++ {86, -17}, ++ {81, 34}, ++ {49, 73}, ++ {0, 88}, ++ {-49, 73}, ++ {-81, 34}, ++ {-86, -17}, ++ {-62, -62}, ++ {-17, -86}, ++ {34, -81}, ++ {73, -49}, ++}; ++ ++static const ++u16 iqlo_loopback_rf_regs[20] = { ++ RADIO_2064_REG036, ++ RADIO_2064_REG11A, ++ RADIO_2064_REG03A, ++ RADIO_2064_REG025, ++ RADIO_2064_REG028, ++ RADIO_2064_REG005, ++ RADIO_2064_REG112, ++ RADIO_2064_REG0FF, ++ RADIO_2064_REG11F, ++ RADIO_2064_REG00B, ++ RADIO_2064_REG113, ++ RADIO_2064_REG007, ++ RADIO_2064_REG0FC, ++ RADIO_2064_REG0FD, ++ RADIO_2064_REG012, ++ RADIO_2064_REG057, ++ RADIO_2064_REG059, ++ RADIO_2064_REG05C, ++ RADIO_2064_REG078, ++ RADIO_2064_REG092, ++}; ++ ++static const ++u16 tempsense_phy_regs[14] = { ++ 0x503, ++ 0x4a4, ++ 0x4d0, ++ 0x4d9, ++ 0x4da, ++ 0x4a6, ++ 0x938, ++ 0x939, ++ 0x4d8, ++ 0x4d0, ++ 0x4d7, ++ 0x4a5, ++ 0x40d, ++ 0x4a2, ++}; ++ ++static const ++u16 rxiq_cal_rf_reg[11] = { ++ RADIO_2064_REG098, ++ RADIO_2064_REG116, ++ RADIO_2064_REG12C, ++ RADIO_2064_REG06A, ++ RADIO_2064_REG00B, ++ RADIO_2064_REG01B, ++ RADIO_2064_REG113, ++ RADIO_2064_REG01D, ++ RADIO_2064_REG114, ++ RADIO_2064_REG02E, ++ RADIO_2064_REG12A, ++}; ++ ++static const ++struct lcnphy_rx_iqcomp lcnphy_rx_iqcomp_table_rev0[] = { ++ {1, 0, 0}, ++ {2, 0, 0}, ++ {3, 0, 0}, ++ {4, 0, 0}, ++ {5, 0, 0}, ++ {6, 0, 0}, ++ {7, 0, 0}, ++ {8, 0, 0}, ++ {9, 0, 0}, ++ {10, 0, 0}, ++ {11, 0, 0}, ++ {12, 0, 0}, ++ {13, 0, 0}, ++ {14, 0, 0}, ++ {34, 0, 0}, ++ {38, 0, 0}, ++ {42, 0, 0}, ++ {46, 0, 0}, ++ {36, 0, 0}, ++ {40, 0, 0}, ++ {44, 0, 0}, ++ {48, 0, 0}, ++ {52, 0, 0}, ++ {56, 0, 0}, ++ {60, 0, 0}, ++ {64, 0, 0}, ++ {100, 0, 0}, ++ {104, 0, 0}, ++ {108, 0, 0}, ++ {112, 0, 0}, ++ {116, 0, 0}, ++ {120, 0, 0}, ++ {124, 0, 0}, ++ {128, 0, 0}, ++ {132, 0, 0}, ++ {136, 0, 0}, ++ {140, 0, 0}, ++ {149, 0, 0}, ++ {153, 0, 0}, ++ {157, 0, 0}, ++ {161, 0, 0}, ++ {165, 0, 0}, ++ {184, 0, 0}, ++ {188, 0, 0}, ++ {192, 0, 0}, ++ {196, 0, 0}, ++ {200, 0, 0}, ++ {204, 0, 0}, ++ {208, 0, 0}, ++ {212, 0, 0}, ++ {216, 0, 0}, ++}; ++ ++static const u32 lcnphy_23bitgaincode_table[] = { ++ 0x200100, ++ 0x200200, ++ 0x200004, ++ 0x200014, ++ 0x200024, ++ 0x200034, ++ 0x200134, ++ 0x200234, ++ 0x200334, ++ 0x200434, ++ 0x200037, ++ 0x200137, ++ 0x200237, ++ 0x200337, ++ 0x200437, ++ 0x000035, ++ 0x000135, ++ 0x000235, ++ 0x000037, ++ 0x000137, ++ 0x000237, ++ 0x000337, ++ 0x00013f, ++ 0x00023f, ++ 0x00033f, ++ 0x00034f, ++ 0x00044f, ++ 0x00144f, ++ 0x00244f, ++ 0x00254f, ++ 0x00354f, ++ 0x00454f, ++ 0x00464f, ++ 0x01464f, ++ 0x02464f, ++ 0x03464f, ++ 0x04464f, ++}; ++ ++static const s8 lcnphy_gain_table[] = { ++ -16, ++ -13, ++ 10, ++ 7, ++ 4, ++ 0, ++ 3, ++ 6, ++ 9, ++ 12, ++ 15, ++ 18, ++ 21, ++ 24, ++ 27, ++ 30, ++ 33, ++ 36, ++ 39, ++ 42, ++ 45, ++ 48, ++ 50, ++ 53, ++ 56, ++ 59, ++ 62, ++ 65, ++ 68, ++ 71, ++ 74, ++ 77, ++ 80, ++ 83, ++ 86, ++ 89, ++ 92, ++}; ++ ++static const s8 lcnphy_gain_index_offset_for_rssi[] = { ++ 7, ++ 7, ++ 7, ++ 7, ++ 7, ++ 7, ++ 7, ++ 8, ++ 7, ++ 7, ++ 6, ++ 7, ++ 7, ++ 4, ++ 4, ++ 4, ++ 4, ++ 4, ++ 4, ++ 4, ++ 4, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3, ++ 4, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ 2, ++ -1, ++ -2, ++ -2, ++ -2 ++}; ++ ++struct chan_info_2064_lcnphy { ++ uint chan; ++ uint freq; ++ u8 logen_buftune; ++ u8 logen_rccr_tx; ++ u8 txrf_mix_tune_ctrl; ++ u8 pa_input_tune_g; ++ u8 logen_rccr_rx; ++ u8 pa_rxrf_lna1_freq_tune; ++ u8 pa_rxrf_lna2_freq_tune; ++ u8 rxrf_rxrf_spare1; ++}; ++ ++static const struct chan_info_2064_lcnphy chan_info_2064_lcnphy[] = { ++ {1, 2412, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {2, 2417, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {3, 2422, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {4, 2427, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {5, 2432, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {6, 2437, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {7, 2442, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {8, 2447, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {9, 2452, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {10, 2457, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {11, 2462, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {12, 2467, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {13, 2472, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++ {14, 2484, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, ++}; ++ ++static const struct lcnphy_radio_regs lcnphy_radio_regs_2064[] = { ++ {0x00, 0, 0, 0, 0}, ++ {0x01, 0x64, 0x64, 0, 0}, ++ {0x02, 0x20, 0x20, 0, 0}, ++ {0x03, 0x66, 0x66, 0, 0}, ++ {0x04, 0xf8, 0xf8, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0x10, 0x10, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0x37, 0x37, 0, 0}, ++ {0x0B, 0x6, 0x6, 0, 0}, ++ {0x0C, 0x55, 0x55, 0, 0}, ++ {0x0D, 0x8b, 0x8b, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0x5, 0x5, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0xe, 0xe, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0xb, 0xb, 0, 0}, ++ {0x14, 0x2, 0x2, 0, 0}, ++ {0x15, 0x12, 0x12, 0, 0}, ++ {0x16, 0x12, 0x12, 0, 0}, ++ {0x17, 0xc, 0xc, 0, 0}, ++ {0x18, 0xc, 0xc, 0, 0}, ++ {0x19, 0xc, 0xc, 0, 0}, ++ {0x1A, 0x8, 0x8, 0, 0}, ++ {0x1B, 0x2, 0x2, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0x1, 0x1, 0, 0}, ++ {0x1E, 0x12, 0x12, 0, 0}, ++ {0x1F, 0x6e, 0x6e, 0, 0}, ++ {0x20, 0x2, 0x2, 0, 0}, ++ {0x21, 0x23, 0x23, 0, 0}, ++ {0x22, 0x8, 0x8, 0, 0}, ++ {0x23, 0, 0, 0, 0}, ++ {0x24, 0, 0, 0, 0}, ++ {0x25, 0xc, 0xc, 0, 0}, ++ {0x26, 0x33, 0x33, 0, 0}, ++ {0x27, 0x55, 0x55, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0x30, 0x30, 0, 0}, ++ {0x2A, 0xb, 0xb, 0, 0}, ++ {0x2B, 0x1b, 0x1b, 0, 0}, ++ {0x2C, 0x3, 0x3, 0, 0}, ++ {0x2D, 0x1b, 0x1b, 0, 0}, ++ {0x2E, 0, 0, 0, 0}, ++ {0x2F, 0x20, 0x20, 0, 0}, ++ {0x30, 0xa, 0xa, 0, 0}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0x62, 0x62, 0, 0}, ++ {0x33, 0x19, 0x19, 0, 0}, ++ {0x34, 0x33, 0x33, 0, 0}, ++ {0x35, 0x77, 0x77, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0x70, 0x70, 0, 0}, ++ {0x38, 0x3, 0x3, 0, 0}, ++ {0x39, 0xf, 0xf, 0, 0}, ++ {0x3A, 0x6, 0x6, 0, 0}, ++ {0x3B, 0xcf, 0xcf, 0, 0}, ++ {0x3C, 0x1a, 0x1a, 0, 0}, ++ {0x3D, 0x6, 0x6, 0, 0}, ++ {0x3E, 0x42, 0x42, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0xfb, 0xfb, 0, 0}, ++ {0x41, 0x9a, 0x9a, 0, 0}, ++ {0x42, 0x7a, 0x7a, 0, 0}, ++ {0x43, 0x29, 0x29, 0, 0}, ++ {0x44, 0, 0, 0, 0}, ++ {0x45, 0x8, 0x8, 0, 0}, ++ {0x46, 0xce, 0xce, 0, 0}, ++ {0x47, 0x27, 0x27, 0, 0}, ++ {0x48, 0x62, 0x62, 0, 0}, ++ {0x49, 0x6, 0x6, 0, 0}, ++ {0x4A, 0x58, 0x58, 0, 0}, ++ {0x4B, 0xf7, 0xf7, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0xb3, 0xb3, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0x2, 0x2, 0, 0}, ++ {0x50, 0, 0, 0, 0}, ++ {0x51, 0x9, 0x9, 0, 0}, ++ {0x52, 0x5, 0x5, 0, 0}, ++ {0x53, 0x17, 0x17, 0, 0}, ++ {0x54, 0x38, 0x38, 0, 0}, ++ {0x55, 0, 0, 0, 0}, ++ {0x56, 0, 0, 0, 0}, ++ {0x57, 0xb, 0xb, 0, 0}, ++ {0x58, 0, 0, 0, 0}, ++ {0x59, 0, 0, 0, 0}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0, 0, 0, 0}, ++ {0x5C, 0, 0, 0, 0}, ++ {0x5D, 0, 0, 0, 0}, ++ {0x5E, 0x88, 0x88, 0, 0}, ++ {0x5F, 0xcc, 0xcc, 0, 0}, ++ {0x60, 0x74, 0x74, 0, 0}, ++ {0x61, 0x74, 0x74, 0, 0}, ++ {0x62, 0x74, 0x74, 0, 0}, ++ {0x63, 0x44, 0x44, 0, 0}, ++ {0x64, 0x77, 0x77, 0, 0}, ++ {0x65, 0x44, 0x44, 0, 0}, ++ {0x66, 0x77, 0x77, 0, 0}, ++ {0x67, 0x55, 0x55, 0, 0}, ++ {0x68, 0x77, 0x77, 0, 0}, ++ {0x69, 0x77, 0x77, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0x7f, 0x7f, 0, 0}, ++ {0x6C, 0x8, 0x8, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0x88, 0x88, 0, 0}, ++ {0x6F, 0x66, 0x66, 0, 0}, ++ {0x70, 0x66, 0x66, 0, 0}, ++ {0x71, 0x28, 0x28, 0, 0}, ++ {0x72, 0x55, 0x55, 0, 0}, ++ {0x73, 0x4, 0x4, 0, 0}, ++ {0x74, 0, 0, 0, 0}, ++ {0x75, 0, 0, 0, 0}, ++ {0x76, 0, 0, 0, 0}, ++ {0x77, 0x1, 0x1, 0, 0}, ++ {0x78, 0xd6, 0xd6, 0, 0}, ++ {0x79, 0, 0, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0xb4, 0xb4, 0, 0}, ++ {0x84, 0x1, 0x1, 0, 0}, ++ {0x85, 0x20, 0x20, 0, 0}, ++ {0x86, 0x5, 0x5, 0, 0}, ++ {0x87, 0xff, 0xff, 0, 0}, ++ {0x88, 0x7, 0x7, 0, 0}, ++ {0x89, 0x77, 0x77, 0, 0}, ++ {0x8A, 0x77, 0x77, 0, 0}, ++ {0x8B, 0x77, 0x77, 0, 0}, ++ {0x8C, 0x77, 0x77, 0, 0}, ++ {0x8D, 0x8, 0x8, 0, 0}, ++ {0x8E, 0xa, 0xa, 0, 0}, ++ {0x8F, 0x8, 0x8, 0, 0}, ++ {0x90, 0x18, 0x18, 0, 0}, ++ {0x91, 0x5, 0x5, 0, 0}, ++ {0x92, 0x1f, 0x1f, 0, 0}, ++ {0x93, 0x10, 0x10, 0, 0}, ++ {0x94, 0x3, 0x3, 0, 0}, ++ {0x95, 0, 0, 0, 0}, ++ {0x96, 0, 0, 0, 0}, ++ {0x97, 0xaa, 0xaa, 0, 0}, ++ {0x98, 0, 0, 0, 0}, ++ {0x99, 0x23, 0x23, 0, 0}, ++ {0x9A, 0x7, 0x7, 0, 0}, ++ {0x9B, 0xf, 0xf, 0, 0}, ++ {0x9C, 0x10, 0x10, 0, 0}, ++ {0x9D, 0x3, 0x3, 0, 0}, ++ {0x9E, 0x4, 0x4, 0, 0}, ++ {0x9F, 0x20, 0x20, 0, 0}, ++ {0xA0, 0, 0, 0, 0}, ++ {0xA1, 0, 0, 0, 0}, ++ {0xA2, 0, 0, 0, 0}, ++ {0xA3, 0, 0, 0, 0}, ++ {0xA4, 0x1, 0x1, 0, 0}, ++ {0xA5, 0x77, 0x77, 0, 0}, ++ {0xA6, 0x77, 0x77, 0, 0}, ++ {0xA7, 0x77, 0x77, 0, 0}, ++ {0xA8, 0x77, 0x77, 0, 0}, ++ {0xA9, 0x8c, 0x8c, 0, 0}, ++ {0xAA, 0x88, 0x88, 0, 0}, ++ {0xAB, 0x78, 0x78, 0, 0}, ++ {0xAC, 0x57, 0x57, 0, 0}, ++ {0xAD, 0x88, 0x88, 0, 0}, ++ {0xAE, 0, 0, 0, 0}, ++ {0xAF, 0x8, 0x8, 0, 0}, ++ {0xB0, 0x88, 0x88, 0, 0}, ++ {0xB1, 0, 0, 0, 0}, ++ {0xB2, 0x1b, 0x1b, 0, 0}, ++ {0xB3, 0x3, 0x3, 0, 0}, ++ {0xB4, 0x24, 0x24, 0, 0}, ++ {0xB5, 0x3, 0x3, 0, 0}, ++ {0xB6, 0x1b, 0x1b, 0, 0}, ++ {0xB7, 0x24, 0x24, 0, 0}, ++ {0xB8, 0x3, 0x3, 0, 0}, ++ {0xB9, 0, 0, 0, 0}, ++ {0xBA, 0xaa, 0xaa, 0, 0}, ++ {0xBB, 0, 0, 0, 0}, ++ {0xBC, 0x4, 0x4, 0, 0}, ++ {0xBD, 0, 0, 0, 0}, ++ {0xBE, 0x8, 0x8, 0, 0}, ++ {0xBF, 0x11, 0x11, 0, 0}, ++ {0xC0, 0, 0, 0, 0}, ++ {0xC1, 0, 0, 0, 0}, ++ {0xC2, 0x62, 0x62, 0, 0}, ++ {0xC3, 0x1e, 0x1e, 0, 0}, ++ {0xC4, 0x33, 0x33, 0, 0}, ++ {0xC5, 0x37, 0x37, 0, 0}, ++ {0xC6, 0, 0, 0, 0}, ++ {0xC7, 0x70, 0x70, 0, 0}, ++ {0xC8, 0x1e, 0x1e, 0, 0}, ++ {0xC9, 0x6, 0x6, 0, 0}, ++ {0xCA, 0x4, 0x4, 0, 0}, ++ {0xCB, 0x2f, 0x2f, 0, 0}, ++ {0xCC, 0xf, 0xf, 0, 0}, ++ {0xCD, 0, 0, 0, 0}, ++ {0xCE, 0xff, 0xff, 0, 0}, ++ {0xCF, 0x8, 0x8, 0, 0}, ++ {0xD0, 0x3f, 0x3f, 0, 0}, ++ {0xD1, 0x3f, 0x3f, 0, 0}, ++ {0xD2, 0x3f, 0x3f, 0, 0}, ++ {0xD3, 0, 0, 0, 0}, ++ {0xD4, 0, 0, 0, 0}, ++ {0xD5, 0, 0, 0, 0}, ++ {0xD6, 0xcc, 0xcc, 0, 0}, ++ {0xD7, 0, 0, 0, 0}, ++ {0xD8, 0x8, 0x8, 0, 0}, ++ {0xD9, 0x8, 0x8, 0, 0}, ++ {0xDA, 0x8, 0x8, 0, 0}, ++ {0xDB, 0x11, 0x11, 0, 0}, ++ {0xDC, 0, 0, 0, 0}, ++ {0xDD, 0x87, 0x87, 0, 0}, ++ {0xDE, 0x88, 0x88, 0, 0}, ++ {0xDF, 0x8, 0x8, 0, 0}, ++ {0xE0, 0x8, 0x8, 0, 0}, ++ {0xE1, 0x8, 0x8, 0, 0}, ++ {0xE2, 0, 0, 0, 0}, ++ {0xE3, 0, 0, 0, 0}, ++ {0xE4, 0, 0, 0, 0}, ++ {0xE5, 0xf5, 0xf5, 0, 0}, ++ {0xE6, 0x30, 0x30, 0, 0}, ++ {0xE7, 0x1, 0x1, 0, 0}, ++ {0xE8, 0, 0, 0, 0}, ++ {0xE9, 0xff, 0xff, 0, 0}, ++ {0xEA, 0, 0, 0, 0}, ++ {0xEB, 0, 0, 0, 0}, ++ {0xEC, 0x22, 0x22, 0, 0}, ++ {0xED, 0, 0, 0, 0}, ++ {0xEE, 0, 0, 0, 0}, ++ {0xEF, 0, 0, 0, 0}, ++ {0xF0, 0x3, 0x3, 0, 0}, ++ {0xF1, 0x1, 0x1, 0, 0}, ++ {0xF2, 0, 0, 0, 0}, ++ {0xF3, 0, 0, 0, 0}, ++ {0xF4, 0, 0, 0, 0}, ++ {0xF5, 0, 0, 0, 0}, ++ {0xF6, 0, 0, 0, 0}, ++ {0xF7, 0x6, 0x6, 0, 0}, ++ {0xF8, 0, 0, 0, 0}, ++ {0xF9, 0, 0, 0, 0}, ++ {0xFA, 0x40, 0x40, 0, 0}, ++ {0xFB, 0, 0, 0, 0}, ++ {0xFC, 0x1, 0x1, 0, 0}, ++ {0xFD, 0x80, 0x80, 0, 0}, ++ {0xFE, 0x2, 0x2, 0, 0}, ++ {0xFF, 0x10, 0x10, 0, 0}, ++ {0x100, 0x2, 0x2, 0, 0}, ++ {0x101, 0x1e, 0x1e, 0, 0}, ++ {0x102, 0x1e, 0x1e, 0, 0}, ++ {0x103, 0, 0, 0, 0}, ++ {0x104, 0x1f, 0x1f, 0, 0}, ++ {0x105, 0, 0x8, 0, 1}, ++ {0x106, 0x2a, 0x2a, 0, 0}, ++ {0x107, 0xf, 0xf, 0, 0}, ++ {0x108, 0, 0, 0, 0}, ++ {0x109, 0, 0, 0, 0}, ++ {0x10A, 0, 0, 0, 0}, ++ {0x10B, 0, 0, 0, 0}, ++ {0x10C, 0, 0, 0, 0}, ++ {0x10D, 0, 0, 0, 0}, ++ {0x10E, 0, 0, 0, 0}, ++ {0x10F, 0, 0, 0, 0}, ++ {0x110, 0, 0, 0, 0}, ++ {0x111, 0, 0, 0, 0}, ++ {0x112, 0, 0, 0, 0}, ++ {0x113, 0, 0, 0, 0}, ++ {0x114, 0, 0, 0, 0}, ++ {0x115, 0, 0, 0, 0}, ++ {0x116, 0, 0, 0, 0}, ++ {0x117, 0, 0, 0, 0}, ++ {0x118, 0, 0, 0, 0}, ++ {0x119, 0, 0, 0, 0}, ++ {0x11A, 0, 0, 0, 0}, ++ {0x11B, 0, 0, 0, 0}, ++ {0x11C, 0x1, 0x1, 0, 0}, ++ {0x11D, 0, 0, 0, 0}, ++ {0x11E, 0, 0, 0, 0}, ++ {0x11F, 0, 0, 0, 0}, ++ {0x120, 0, 0, 0, 0}, ++ {0x121, 0, 0, 0, 0}, ++ {0x122, 0x80, 0x80, 0, 0}, ++ {0x123, 0, 0, 0, 0}, ++ {0x124, 0xf8, 0xf8, 0, 0}, ++ {0x125, 0, 0, 0, 0}, ++ {0x126, 0, 0, 0, 0}, ++ {0x127, 0, 0, 0, 0}, ++ {0x128, 0, 0, 0, 0}, ++ {0x129, 0, 0, 0, 0}, ++ {0x12A, 0, 0, 0, 0}, ++ {0x12B, 0, 0, 0, 0}, ++ {0x12C, 0, 0, 0, 0}, ++ {0x12D, 0, 0, 0, 0}, ++ {0x12E, 0, 0, 0, 0}, ++ {0x12F, 0, 0, 0, 0}, ++ {0x130, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++#define LCNPHY_NUM_DIG_FILT_COEFFS 16 ++#define LCNPHY_NUM_TX_DIG_FILTERS_CCK 13 ++ ++static const u16 LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK] ++ [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = { ++ {0, 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778, 1582, 64, ++ 128, 64,}, ++ {1, 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608, 1863, 93, ++ 167, 93,}, ++ {2, 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192, 778, 1582, 64, ++ 128, 64,}, ++ {3, 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205, 754, 1760, ++ 170, 340, 170,}, ++ {20, 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205, 767, 1760, ++ 256, 185, 256,}, ++ {21, 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205, 767, 1760, ++ 256, 273, 256,}, ++ {22, 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205, 767, 1760, ++ 256, 352, 256,}, ++ {23, 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205, 767, 1760, ++ 128, 233, 128,}, ++ {24, 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766, 1760, 256, ++ 1881, 256,}, ++ {25, 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765, 1760, 256, ++ 1881, 256,}, ++ {26, 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614, 1864, 128, ++ 384, 288,}, ++ {27, 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576, 613, 1864, ++ 128, 384, 288,}, ++ {30, 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205, 754, 1760, ++ 170, 340, 170,}, ++}; ++ ++#define LCNPHY_NUM_TX_DIG_FILTERS_OFDM 3 ++static const u16 LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM] ++ [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = { ++ {0, 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0, 0x0, ++ 0x278, 0xfea0, 0x80, 0x100, 0x80,}, ++ {1, 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50, ++ 750, 0xFE2B, 212, 0xFFCE, 212,}, ++ {2, 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748, ++ 0xFEF2, 128, 0xFFE2, 128} ++}; ++ ++#define wlc_lcnphy_set_start_tx_pwr_idx(pi, idx) \ ++ mod_phy_reg(pi, 0x4a4, \ ++ (0x1ff << 0), \ ++ (u16)(idx) << 0) ++ ++#define wlc_lcnphy_set_tx_pwr_npt(pi, npt) \ ++ mod_phy_reg(pi, 0x4a5, \ ++ (0x7 << 8), \ ++ (u16)(npt) << 8) ++ ++#define wlc_lcnphy_get_tx_pwr_ctrl(pi) \ ++ (read_phy_reg((pi), 0x4a4) & \ ++ ((0x1 << 15) | \ ++ (0x1 << 14) | \ ++ (0x1 << 13))) ++ ++#define wlc_lcnphy_get_tx_pwr_npt(pi) \ ++ ((read_phy_reg(pi, 0x4a5) & \ ++ (0x7 << 8)) >> \ ++ 8) ++ ++#define wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi) \ ++ (read_phy_reg(pi, 0x473) & 0x1ff) ++ ++#define wlc_lcnphy_get_target_tx_pwr(pi) \ ++ ((read_phy_reg(pi, 0x4a7) & \ ++ (0xff << 0)) >> \ ++ 0) ++ ++#define wlc_lcnphy_set_target_tx_pwr(pi, target) \ ++ mod_phy_reg(pi, 0x4a7, \ ++ (0xff << 0), \ ++ (u16)(target) << 0) ++ ++#define wlc_radio_2064_rcal_done(pi) \ ++ (0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20)) ++ ++#define tempsense_done(pi) \ ++ (0x8000 == (read_phy_reg(pi, 0x476) & 0x8000)) ++ ++#define LCNPHY_IQLOCC_READ(val) \ ++ ((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f))) ++ ++#define FIXED_TXPWR 78 ++#define LCNPHY_TEMPSENSE(val) ((s16)((val > 255) ? (val - 512) : val)) ++ ++void wlc_lcnphy_write_table(struct brcms_phy *pi, const struct phytbl_info *pti) ++{ ++ wlc_phy_write_table(pi, pti, 0x455, 0x457, 0x456); ++} ++ ++void wlc_lcnphy_read_table(struct brcms_phy *pi, struct phytbl_info *pti) ++{ ++ wlc_phy_read_table(pi, pti, 0x455, 0x457, 0x456); ++} ++ ++static void ++wlc_lcnphy_common_read_table(struct brcms_phy *pi, u32 tbl_id, ++ const u16 *tbl_ptr, u32 tbl_len, ++ u32 tbl_width, u32 tbl_offset) ++{ ++ struct phytbl_info tab; ++ tab.tbl_id = tbl_id; ++ tab.tbl_ptr = tbl_ptr; ++ tab.tbl_len = tbl_len; ++ tab.tbl_width = tbl_width; ++ tab.tbl_offset = tbl_offset; ++ wlc_lcnphy_read_table(pi, &tab); ++} ++ ++static void ++wlc_lcnphy_common_write_table(struct brcms_phy *pi, u32 tbl_id, ++ const u16 *tbl_ptr, u32 tbl_len, ++ u32 tbl_width, u32 tbl_offset) ++{ ++ ++ struct phytbl_info tab; ++ tab.tbl_id = tbl_id; ++ tab.tbl_ptr = tbl_ptr; ++ tab.tbl_len = tbl_len; ++ tab.tbl_width = tbl_width; ++ tab.tbl_offset = tbl_offset; ++ wlc_lcnphy_write_table(pi, &tab); ++} ++ ++static u32 ++wlc_lcnphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision) ++{ ++ u32 quotient, remainder, roundup, rbit; ++ ++ quotient = dividend / divisor; ++ remainder = dividend % divisor; ++ rbit = divisor & 1; ++ roundup = (divisor >> 1) + rbit; ++ ++ while (precision--) { ++ quotient <<= 1; ++ if (remainder >= roundup) { ++ quotient++; ++ remainder = ((remainder - roundup) << 1) + rbit; ++ } else { ++ remainder <<= 1; ++ } ++ } ++ ++ if (remainder >= roundup) ++ quotient++; ++ ++ return quotient; ++} ++ ++static int wlc_lcnphy_calc_floor(s16 coeff_x, int type) ++{ ++ int k; ++ k = 0; ++ if (type == 0) { ++ if (coeff_x < 0) ++ k = (coeff_x - 1) / 2; ++ else ++ k = coeff_x / 2; ++ } ++ ++ if (type == 1) { ++ if ((coeff_x + 1) < 0) ++ k = (coeff_x) / 2; ++ else ++ k = (coeff_x + 1) / 2; ++ } ++ return k; ++} ++ ++static void ++wlc_lcnphy_get_tx_gain(struct brcms_phy *pi, struct lcnphy_txgains *gains) ++{ ++ u16 dac_gain, rfgain0, rfgain1; ++ ++ dac_gain = read_phy_reg(pi, 0x439) >> 0; ++ gains->dac_gain = (dac_gain & 0x380) >> 7; ++ ++ rfgain0 = (read_phy_reg(pi, 0x4b5) & (0xffff << 0)) >> 0; ++ rfgain1 = (read_phy_reg(pi, 0x4fb) & (0x7fff << 0)) >> 0; ++ ++ gains->gm_gain = rfgain0 & 0xff; ++ gains->pga_gain = (rfgain0 >> 8) & 0xff; ++ gains->pad_gain = rfgain1 & 0xff; ++} ++ ++ ++static void wlc_lcnphy_set_dac_gain(struct brcms_phy *pi, u16 dac_gain) ++{ ++ u16 dac_ctrl; ++ ++ dac_ctrl = (read_phy_reg(pi, 0x439) >> 0); ++ dac_ctrl = dac_ctrl & 0xc7f; ++ dac_ctrl = dac_ctrl | (dac_gain << 7); ++ mod_phy_reg(pi, 0x439, (0xfff << 0), (dac_ctrl) << 0); ++ ++} ++ ++static void wlc_lcnphy_set_tx_gain_override(struct brcms_phy *pi, bool bEnable) ++{ ++ u16 bit = bEnable ? 1 : 0; ++ ++ mod_phy_reg(pi, 0x4b0, (0x1 << 7), bit << 7); ++ ++ mod_phy_reg(pi, 0x4b0, (0x1 << 14), bit << 14); ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 6), bit << 6); ++} ++ ++static void ++wlc_lcnphy_rx_gain_override_enable(struct brcms_phy *pi, bool enable) ++{ ++ u16 ebit = enable ? 1 : 0; ++ ++ mod_phy_reg(pi, 0x4b0, (0x1 << 8), ebit << 8); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 0), ebit << 0); ++ ++ if (LCNREV_LT(pi->pubpi.phy_rev, 2)) { ++ mod_phy_reg(pi, 0x44c, (0x1 << 4), ebit << 4); ++ mod_phy_reg(pi, 0x44c, (0x1 << 6), ebit << 6); ++ mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5); ++ mod_phy_reg(pi, 0x4b0, (0x1 << 6), ebit << 6); ++ } else { ++ mod_phy_reg(pi, 0x4b0, (0x1 << 12), ebit << 12); ++ mod_phy_reg(pi, 0x4b0, (0x1 << 13), ebit << 13); ++ mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5); ++ } ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ mod_phy_reg(pi, 0x4b0, (0x1 << 10), ebit << 10); ++ mod_phy_reg(pi, 0x4e5, (0x1 << 3), ebit << 3); ++ } ++} ++ ++static void ++wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi, ++ u16 trsw, ++ u16 ext_lna, ++ u16 biq2, ++ u16 biq1, ++ u16 tia, u16 lna2, u16 lna1) ++{ ++ u16 gain0_15, gain16_19; ++ ++ gain16_19 = biq2 & 0xf; ++ gain0_15 = ((biq1 & 0xf) << 12) | ++ ((tia & 0xf) << 8) | ++ ((lna2 & 0x3) << 6) | ++ ((lna2 & ++ 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0); ++ ++ mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0); ++ mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0); ++ mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11); ++ ++ if (LCNREV_LT(pi->pubpi.phy_rev, 2)) { ++ mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9); ++ mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10); ++ } else { ++ mod_phy_reg(pi, 0x4b1, (0x1 << 10), 0 << 10); ++ ++ mod_phy_reg(pi, 0x4b1, (0x1 << 15), 0 << 15); ++ ++ mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9); ++ } ++ ++ mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0); ++ ++} ++ ++static void wlc_lcnphy_set_trsw_override(struct brcms_phy *pi, bool tx, bool rx) ++{ ++ ++ mod_phy_reg(pi, 0x44d, ++ (0x1 << 1) | ++ (0x1 << 0), (tx ? (0x1 << 1) : 0) | (rx ? (0x1 << 0) : 0)); ++ ++ or_phy_reg(pi, 0x44c, (0x1 << 1) | (0x1 << 0)); ++} ++ ++static void wlc_lcnphy_clear_trsw_override(struct brcms_phy *pi) ++{ ++ ++ and_phy_reg(pi, 0x44c, (u16) ~((0x1 << 1) | (0x1 << 0))); ++} ++ ++static void wlc_lcnphy_set_rx_iq_comp(struct brcms_phy *pi, u16 a, u16 b) ++{ ++ mod_phy_reg(pi, 0x645, (0x3ff << 0), (a) << 0); ++ ++ mod_phy_reg(pi, 0x646, (0x3ff << 0), (b) << 0); ++ ++ mod_phy_reg(pi, 0x647, (0x3ff << 0), (a) << 0); ++ ++ mod_phy_reg(pi, 0x648, (0x3ff << 0), (b) << 0); ++ ++ mod_phy_reg(pi, 0x649, (0x3ff << 0), (a) << 0); ++ ++ mod_phy_reg(pi, 0x64a, (0x3ff << 0), (b) << 0); ++ ++} ++ ++static bool ++wlc_lcnphy_rx_iq_est(struct brcms_phy *pi, ++ u16 num_samps, ++ u8 wait_time, struct lcnphy_iq_est *iq_est) ++{ ++ int wait_count = 0; ++ bool result = true; ++ u8 phybw40; ++ phybw40 = CHSPEC_IS40(pi->radio_chanspec); ++ ++ mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5); ++ ++ mod_phy_reg(pi, 0x410, (0x1 << 3), (0) << 3); ++ ++ mod_phy_reg(pi, 0x482, (0xffff << 0), (num_samps) << 0); ++ ++ mod_phy_reg(pi, 0x481, (0xff << 0), ((u16) wait_time) << 0); ++ ++ mod_phy_reg(pi, 0x481, (0x1 << 8), (0) << 8); ++ ++ mod_phy_reg(pi, 0x481, (0x1 << 9), (1) << 9); ++ ++ while (read_phy_reg(pi, 0x481) & (0x1 << 9)) { ++ ++ if (wait_count > (10 * 500)) { ++ result = false; ++ goto cleanup; ++ } ++ udelay(100); ++ wait_count++; ++ } ++ ++ iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) | ++ (u32) read_phy_reg(pi, 0x484); ++ iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) | ++ (u32) read_phy_reg(pi, 0x486); ++ iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) | ++ (u32) read_phy_reg(pi, 0x488); ++ ++cleanup: ++ mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3); ++ ++ mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5); ++ ++ return result; ++} ++ ++static bool wlc_lcnphy_calc_rx_iq_comp(struct brcms_phy *pi, u16 num_samps) ++{ ++#define LCNPHY_MIN_RXIQ_PWR 2 ++ bool result; ++ u16 a0_new, b0_new; ++ struct lcnphy_iq_est iq_est = { 0, 0, 0 }; ++ s32 a, b, temp; ++ s16 iq_nbits, qq_nbits, arsh, brsh; ++ s32 iq; ++ u32 ii, qq; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ a0_new = ((read_phy_reg(pi, 0x645) & (0x3ff << 0)) >> 0); ++ b0_new = ((read_phy_reg(pi, 0x646) & (0x3ff << 0)) >> 0); ++ mod_phy_reg(pi, 0x6d1, (0x1 << 2), (0) << 2); ++ ++ mod_phy_reg(pi, 0x64b, (0x1 << 6), (1) << 6); ++ ++ wlc_lcnphy_set_rx_iq_comp(pi, 0, 0); ++ ++ result = wlc_lcnphy_rx_iq_est(pi, num_samps, 32, &iq_est); ++ if (!result) ++ goto cleanup; ++ ++ iq = (s32) iq_est.iq_prod; ++ ii = iq_est.i_pwr; ++ qq = iq_est.q_pwr; ++ ++ if ((ii + qq) < LCNPHY_MIN_RXIQ_PWR) { ++ result = false; ++ goto cleanup; ++ } ++ ++ iq_nbits = wlc_phy_nbits(iq); ++ qq_nbits = wlc_phy_nbits(qq); ++ ++ arsh = 10 - (30 - iq_nbits); ++ if (arsh >= 0) { ++ a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh))); ++ temp = (s32) (ii >> arsh); ++ if (temp == 0) ++ return false; ++ } else { ++ a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh))); ++ temp = (s32) (ii << -arsh); ++ if (temp == 0) ++ return false; ++ } ++ a /= temp; ++ brsh = qq_nbits - 31 + 20; ++ if (brsh >= 0) { ++ b = (qq << (31 - qq_nbits)); ++ temp = (s32) (ii >> brsh); ++ if (temp == 0) ++ return false; ++ } else { ++ b = (qq << (31 - qq_nbits)); ++ temp = (s32) (ii << -brsh); ++ if (temp == 0) ++ return false; ++ } ++ b /= temp; ++ b -= a * a; ++ b = (s32) int_sqrt((unsigned long) b); ++ b -= (1 << 10); ++ a0_new = (u16) (a & 0x3ff); ++ b0_new = (u16) (b & 0x3ff); ++cleanup: ++ ++ wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new); ++ ++ mod_phy_reg(pi, 0x64b, (0x1 << 0), (1) << 0); ++ ++ mod_phy_reg(pi, 0x64b, (0x1 << 3), (1) << 3); ++ ++ pi_lcn->lcnphy_cal_results.rxiqcal_coeff_a0 = a0_new; ++ pi_lcn->lcnphy_cal_results.rxiqcal_coeff_b0 = b0_new; ++ ++ return result; ++} ++ ++static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples) ++{ ++ struct lcnphy_iq_est iq_est = { 0, 0, 0 }; ++ ++ if (!wlc_lcnphy_rx_iq_est(pi, nsamples, 32, &iq_est)) ++ return 0; ++ return (iq_est.i_pwr + iq_est.q_pwr) / nsamples; ++} ++ ++static bool ++wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, ++ const struct lcnphy_rx_iqcomp *iqcomp, ++ int iqcomp_sz, bool tx_switch, bool rx_switch, int module, ++ int tx_gain_idx) ++{ ++ struct lcnphy_txgains old_gains; ++ u16 tx_pwr_ctrl; ++ u8 tx_gain_index_old = 0; ++ bool result = false, tx_gain_override_old = false; ++ u16 i, Core1TxControl_old, RFOverride0_old, ++ RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old, ++ rfoverride3_old, rfoverride3val_old, rfoverride4_old, ++ rfoverride4val_old, afectrlovr_old, afectrlovrval_old; ++ int tia_gain; ++ u32 received_power, rx_pwr_threshold; ++ u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl; ++ u16 values_to_save[11]; ++ s16 *ptr; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC); ++ if (NULL == ptr) ++ return false; ++ if (module == 2) { ++ while (iqcomp_sz--) { ++ if (iqcomp[iqcomp_sz].chan == ++ CHSPEC_CHANNEL(pi->radio_chanspec)) { ++ wlc_lcnphy_set_rx_iq_comp(pi, ++ (u16) ++ iqcomp[iqcomp_sz].a, ++ (u16) ++ iqcomp[iqcomp_sz].b); ++ result = true; ++ break; ++ } ++ } ++ goto cal_done; ++ } ++ ++ if (module == 1) { ++ ++ tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); ++ ++ for (i = 0; i < 11; i++) ++ values_to_save[i] = ++ read_radio_reg(pi, rxiq_cal_rf_reg[i]); ++ Core1TxControl_old = read_phy_reg(pi, 0x631); ++ ++ or_phy_reg(pi, 0x631, 0x0015); ++ ++ RFOverride0_old = read_phy_reg(pi, 0x44c); ++ RFOverrideVal0_old = read_phy_reg(pi, 0x44d); ++ rfoverride2_old = read_phy_reg(pi, 0x4b0); ++ rfoverride2val_old = read_phy_reg(pi, 0x4b1); ++ rfoverride3_old = read_phy_reg(pi, 0x4f9); ++ rfoverride3val_old = read_phy_reg(pi, 0x4fa); ++ rfoverride4_old = read_phy_reg(pi, 0x938); ++ rfoverride4val_old = read_phy_reg(pi, 0x939); ++ afectrlovr_old = read_phy_reg(pi, 0x43b); ++ afectrlovrval_old = read_phy_reg(pi, 0x43c); ++ old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); ++ old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db); ++ ++ tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); ++ if (tx_gain_override_old) { ++ wlc_lcnphy_get_tx_gain(pi, &old_gains); ++ tx_gain_index_old = pi_lcn->lcnphy_current_index; ++ } ++ ++ wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx); ++ ++ mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0); ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); ++ mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); ++ ++ write_radio_reg(pi, RADIO_2064_REG116, 0x06); ++ write_radio_reg(pi, RADIO_2064_REG12C, 0x07); ++ write_radio_reg(pi, RADIO_2064_REG06A, 0xd3); ++ write_radio_reg(pi, RADIO_2064_REG098, 0x03); ++ write_radio_reg(pi, RADIO_2064_REG00B, 0x7); ++ mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4); ++ write_radio_reg(pi, RADIO_2064_REG01D, 0x01); ++ write_radio_reg(pi, RADIO_2064_REG114, 0x01); ++ write_radio_reg(pi, RADIO_2064_REG02E, 0x10); ++ write_radio_reg(pi, RADIO_2064_REG12A, 0x08); ++ ++ mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0); ++ mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1); ++ mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1); ++ mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2); ++ mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2); ++ mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3); ++ mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3); ++ mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5); ++ mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5); ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0); ++ ++ wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0); ++ write_phy_reg(pi, 0x6da, 0xffff); ++ or_phy_reg(pi, 0x6db, 0x3); ++ wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch); ++ wlc_lcnphy_rx_gain_override_enable(pi, true); ++ ++ tia_gain = 8; ++ rx_pwr_threshold = 950; ++ while (tia_gain > 0) { ++ tia_gain -= 1; ++ wlc_lcnphy_set_rx_gain_by_distribution(pi, ++ 0, 0, 2, 2, ++ (u16) ++ tia_gain, 1, 0); ++ udelay(500); ++ ++ received_power = ++ wlc_lcnphy_measure_digital_power(pi, 2000); ++ if (received_power < rx_pwr_threshold) ++ break; ++ } ++ result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff); ++ ++ wlc_lcnphy_stop_tx_tone(pi); ++ ++ write_phy_reg(pi, 0x631, Core1TxControl_old); ++ ++ write_phy_reg(pi, 0x44c, RFOverrideVal0_old); ++ write_phy_reg(pi, 0x44d, RFOverrideVal0_old); ++ write_phy_reg(pi, 0x4b0, rfoverride2_old); ++ write_phy_reg(pi, 0x4b1, rfoverride2val_old); ++ write_phy_reg(pi, 0x4f9, rfoverride3_old); ++ write_phy_reg(pi, 0x4fa, rfoverride3val_old); ++ write_phy_reg(pi, 0x938, rfoverride4_old); ++ write_phy_reg(pi, 0x939, rfoverride4val_old); ++ write_phy_reg(pi, 0x43b, afectrlovr_old); ++ write_phy_reg(pi, 0x43c, afectrlovrval_old); ++ write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); ++ write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl); ++ ++ wlc_lcnphy_clear_trsw_override(pi); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2); ++ ++ for (i = 0; i < 11; i++) ++ write_radio_reg(pi, rxiq_cal_rf_reg[i], ++ values_to_save[i]); ++ ++ if (tx_gain_override_old) ++ wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old); ++ else ++ wlc_lcnphy_disable_tx_gain_override(pi); ++ ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl); ++ wlc_lcnphy_rx_gain_override_enable(pi, false); ++ } ++ ++cal_done: ++ kfree(ptr); ++ return result; ++} ++ ++s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi) ++{ ++ s8 index; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ if (txpwrctrl_off(pi)) ++ index = pi_lcn->lcnphy_current_index; ++ else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) ++ index = (s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on( ++ pi) / 2); ++ else ++ index = pi_lcn->lcnphy_current_index; ++ return index; ++} ++ ++void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel) ++{ ++ u16 afectrlovr, afectrlovrval; ++ afectrlovr = read_phy_reg(pi, 0x43b); ++ afectrlovrval = read_phy_reg(pi, 0x43c); ++ if (channel != 0) { ++ mod_phy_reg(pi, 0x43b, (0x1 << 1), (1) << 1); ++ ++ mod_phy_reg(pi, 0x43c, (0x1 << 1), (0) << 1); ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 4), (1) << 4); ++ ++ mod_phy_reg(pi, 0x43c, (0x1 << 6), (0) << 6); ++ ++ write_phy_reg(pi, 0x44b, 0xffff); ++ wlc_lcnphy_tx_pu(pi, 1); ++ ++ mod_phy_reg(pi, 0x634, (0xff << 8), (0) << 8); ++ ++ or_phy_reg(pi, 0x6da, 0x0080); ++ ++ or_phy_reg(pi, 0x00a, 0x228); ++ } else { ++ and_phy_reg(pi, 0x00a, ~(0x228)); ++ ++ and_phy_reg(pi, 0x6da, 0xFF7F); ++ write_phy_reg(pi, 0x43b, afectrlovr); ++ write_phy_reg(pi, 0x43c, afectrlovrval); ++ } ++} ++ ++static void wlc_lcnphy_toggle_afe_pwdn(struct brcms_phy *pi) ++{ ++ u16 save_AfeCtrlOvrVal, save_AfeCtrlOvr; ++ ++ save_AfeCtrlOvrVal = read_phy_reg(pi, 0x43c); ++ save_AfeCtrlOvr = read_phy_reg(pi, 0x43b); ++ ++ write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal | 0x1); ++ write_phy_reg(pi, 0x43b, save_AfeCtrlOvr | 0x1); ++ ++ write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal & 0xfffe); ++ write_phy_reg(pi, 0x43b, save_AfeCtrlOvr & 0xfffe); ++ ++ write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal); ++ write_phy_reg(pi, 0x43b, save_AfeCtrlOvr); ++} ++ ++static void ++wlc_lcnphy_txrx_spur_avoidance_mode(struct brcms_phy *pi, bool enable) ++{ ++ if (enable) { ++ write_phy_reg(pi, 0x942, 0x7); ++ write_phy_reg(pi, 0x93b, ((1 << 13) + 23)); ++ write_phy_reg(pi, 0x93c, ((1 << 13) + 1989)); ++ ++ write_phy_reg(pi, 0x44a, 0x084); ++ write_phy_reg(pi, 0x44a, 0x080); ++ write_phy_reg(pi, 0x6d3, 0x2222); ++ write_phy_reg(pi, 0x6d3, 0x2220); ++ } else { ++ write_phy_reg(pi, 0x942, 0x0); ++ write_phy_reg(pi, 0x93b, ((0 << 13) + 23)); ++ write_phy_reg(pi, 0x93c, ((0 << 13) + 1989)); ++ } ++ wlapi_switch_macfreq(pi->sh->physhim, enable); ++} ++ ++static void ++wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec) ++{ ++ u8 channel = CHSPEC_CHANNEL(chanspec); ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ if (channel == 14) ++ mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8); ++ else ++ mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8); ++ ++ pi_lcn->lcnphy_bandedge_corr = 2; ++ if (channel == 1) ++ pi_lcn->lcnphy_bandedge_corr = 4; ++ ++ if (channel == 1 || channel == 2 || channel == 3 || ++ channel == 4 || channel == 9 || ++ channel == 10 || channel == 11 || channel == 12) { ++ si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04); ++ si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0); ++ si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0); ++ ++ si_pmu_pllupd(pi->sh->sih); ++ write_phy_reg(pi, 0x942, 0); ++ wlc_lcnphy_txrx_spur_avoidance_mode(pi, false); ++ pi_lcn->lcnphy_spurmod = 0; ++ mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8); ++ ++ write_phy_reg(pi, 0x425, 0x5907); ++ } else { ++ si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04); ++ si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333); ++ si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820); ++ ++ si_pmu_pllupd(pi->sh->sih); ++ write_phy_reg(pi, 0x942, 0); ++ wlc_lcnphy_txrx_spur_avoidance_mode(pi, true); ++ ++ pi_lcn->lcnphy_spurmod = 0; ++ mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8); ++ ++ write_phy_reg(pi, 0x425, 0x590a); ++ } ++ ++ or_phy_reg(pi, 0x44a, 0x44); ++ write_phy_reg(pi, 0x44a, 0x80); ++} ++ ++static void ++wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel) ++{ ++ uint i; ++ const struct chan_info_2064_lcnphy *ci; ++ u8 rfpll_doubler = 0; ++ u8 pll_pwrup, pll_pwrup_ovr; ++ s32 qFxtal, qFref, qFvco, qFcal; ++ u8 d15, d16, f16, e44, e45; ++ u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div; ++ u16 loop_bw, d30, setCount; ++ ++ u8 h29, h28_ten, e30, h30_ten, cp_current; ++ u16 g30, d28; ++ ++ ci = &chan_info_2064_lcnphy[0]; ++ rfpll_doubler = 1; ++ ++ mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2); ++ ++ write_radio_reg(pi, RADIO_2064_REG09E, 0xf); ++ if (!rfpll_doubler) { ++ loop_bw = PLL_2064_LOOP_BW; ++ d30 = PLL_2064_D30; ++ } else { ++ loop_bw = PLL_2064_LOOP_BW_DOUBLER; ++ d30 = PLL_2064_D30_DOUBLER; ++ } ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++) ++ if (chan_info_2064_lcnphy[i].chan == channel) ++ break; ++ ++ if (i >= ARRAY_SIZE(chan_info_2064_lcnphy)) ++ return; ++ ++ ci = &chan_info_2064_lcnphy[i]; ++ } ++ ++ write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune); ++ ++ mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx); ++ ++ mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl); ++ ++ mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g); ++ ++ mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2, ++ (ci->logen_rccr_rx) << 2); ++ ++ mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune); ++ ++ mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4, ++ (ci->pa_rxrf_lna2_freq_tune) << 4); ++ ++ write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1); ++ ++ pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044); ++ pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B); ++ ++ or_radio_reg(pi, RADIO_2064_REG044, 0x07); ++ ++ or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1); ++ e44 = 0; ++ e45 = 0; ++ ++ fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq); ++ if (pi->xtalfreq > 26000000) ++ e44 = 1; ++ if (pi->xtalfreq > 52000000) ++ e45 = 1; ++ if (e44 == 0) ++ fcal_div = 1; ++ else if (e45 == 0) ++ fcal_div = 2; ++ else ++ fcal_div = 4; ++ fvco3 = (ci->freq * 3); ++ fref3 = 2 * fpfd; ++ ++ qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16); ++ qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16); ++ qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ; ++ qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16); ++ ++ write_radio_reg(pi, RADIO_2064_REG04F, 0x02); ++ ++ d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1; ++ write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2))); ++ write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5); ++ ++ d16 = (qFcal * 8 / (d15 + 1)) - 1; ++ write_radio_reg(pi, RADIO_2064_REG051, d16); ++ ++ f16 = ((d16 + 1) * (d15 + 1)) / qFcal; ++ setCount = f16 * 3 * (ci->freq) / 32 - 1; ++ mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0), ++ (u8) (setCount >> 8)); ++ ++ or_radio_reg(pi, RADIO_2064_REG053, 0x10); ++ write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff)); ++ ++ div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4; ++ ++ div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4; ++ while (div_frac >= fref3) { ++ div_int++; ++ div_frac -= fref3; ++ } ++ div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20); ++ ++ mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0), ++ (u8) (div_int >> 4)); ++ mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4), ++ (u8) (div_int << 4)); ++ mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0), ++ (u8) (div_frac >> 16)); ++ write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff); ++ write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff); ++ ++ write_radio_reg(pi, RADIO_2064_REG040, 0xfb); ++ ++ write_radio_reg(pi, RADIO_2064_REG041, 0x9A); ++ write_radio_reg(pi, RADIO_2064_REG042, 0xA3); ++ write_radio_reg(pi, RADIO_2064_REG043, 0x0C); ++ ++ h29 = LCN_BW_LMT / loop_bw; ++ d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) * ++ (fvco3 / 2 - PLL_2064_LOW_END_VCO)) / ++ (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO)) ++ + PLL_2064_LOW_END_KVCO; ++ h28_ten = (d28 * 10) / LCN_VCO_DIV; ++ e30 = (d30 - LCN_OFFSET) / LCN_FACT; ++ g30 = LCN_OFFSET + (e30 * LCN_FACT); ++ h30_ten = (g30 * 10) / LCN_CUR_DIV; ++ cp_current = ((LCN_CUR_LMT * h29 * LCN_MULT * 100) / h28_ten) / h30_ten; ++ mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current); ++ ++ if (channel >= 1 && channel <= 5) ++ write_radio_reg(pi, RADIO_2064_REG03C, 0x8); ++ else ++ write_radio_reg(pi, RADIO_2064_REG03C, 0x7); ++ write_radio_reg(pi, RADIO_2064_REG03D, 0x3); ++ ++ mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c); ++ udelay(1); ++ ++ wlc_2064_vco_cal(pi); ++ ++ write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup); ++ write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr); ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) { ++ write_radio_reg(pi, RADIO_2064_REG038, 3); ++ write_radio_reg(pi, RADIO_2064_REG091, 7); ++ } ++} ++ ++static int ++wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm, s16 filt_type) ++{ ++ s16 filt_index = -1; ++ int j; ++ ++ u16 addr[] = { ++ 0x910, ++ 0x91e, ++ 0x91f, ++ 0x924, ++ 0x925, ++ 0x926, ++ 0x920, ++ 0x921, ++ 0x927, ++ 0x928, ++ 0x929, ++ 0x922, ++ 0x923, ++ 0x930, ++ 0x931, ++ 0x932 ++ }; ++ ++ u16 addr_ofdm[] = { ++ 0x90f, ++ 0x900, ++ 0x901, ++ 0x906, ++ 0x907, ++ 0x908, ++ 0x902, ++ 0x903, ++ 0x909, ++ 0x90a, ++ 0x90b, ++ 0x904, ++ 0x905, ++ 0x90c, ++ 0x90d, ++ 0x90e ++ }; ++ ++ if (!is_ofdm) { ++ for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) { ++ if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) { ++ filt_index = (s16) j; ++ break; ++ } ++ } ++ ++ if (filt_index != -1) { ++ for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, addr[j], ++ LCNPHY_txdigfiltcoeffs_cck ++ [filt_index][j + 1]); ++ } ++ } else { ++ for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) { ++ if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) { ++ filt_index = (s16) j; ++ break; ++ } ++ } ++ ++ if (filt_index != -1) { ++ for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, addr_ofdm[j], ++ LCNPHY_txdigfiltcoeffs_ofdm ++ [filt_index][j + 1]); ++ } ++ } ++ ++ return (filt_index != -1) ? 0 : -1; ++} ++ ++void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec) ++{ ++ u8 channel = CHSPEC_CHANNEL(chanspec); ++ ++ wlc_phy_chanspec_radio_set((struct brcms_phy_pub *) pi, chanspec); ++ ++ wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec); ++ ++ or_phy_reg(pi, 0x44a, 0x44); ++ write_phy_reg(pi, 0x44a, 0x80); ++ ++ wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel); ++ udelay(1000); ++ ++ wlc_lcnphy_toggle_afe_pwdn(pi); ++ ++ write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20); ++ write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor); ++ ++ if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) { ++ mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8); ++ ++ wlc_lcnphy_load_tx_iir_filter(pi, false, 3); ++ } else { ++ mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8); ++ ++ wlc_lcnphy_load_tx_iir_filter(pi, false, 2); ++ } ++ ++ wlc_lcnphy_load_tx_iir_filter(pi, true, 0); ++ ++ mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3); ++ ++} ++ ++static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi) ++{ ++ u16 pa_gain; ++ ++ pa_gain = (read_phy_reg(pi, 0x4fb) & ++ LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK) >> ++ LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT; ++ ++ return pa_gain; ++} ++ ++static void wlc_lcnphy_set_tx_gain(struct brcms_phy *pi, ++ struct lcnphy_txgains *target_gains) ++{ ++ u16 pa_gain = wlc_lcnphy_get_pa_gain(pi); ++ ++ mod_phy_reg( ++ pi, 0x4b5, ++ (0xffff << 0), ++ ((target_gains->gm_gain) | ++ (target_gains->pga_gain << 8)) << ++ 0); ++ mod_phy_reg(pi, 0x4fb, ++ (0x7fff << 0), ++ ((target_gains->pad_gain) | (pa_gain << 8)) << 0); ++ ++ mod_phy_reg( ++ pi, 0x4fc, ++ (0xffff << 0), ++ ((target_gains->gm_gain) | ++ (target_gains->pga_gain << 8)) << ++ 0); ++ mod_phy_reg(pi, 0x4fd, ++ (0x7fff << 0), ++ ((target_gains->pad_gain) | (pa_gain << 8)) << 0); ++ ++ wlc_lcnphy_set_dac_gain(pi, target_gains->dac_gain); ++ ++ wlc_lcnphy_enable_tx_gain_override(pi); ++} ++ ++static void wlc_lcnphy_set_bbmult(struct brcms_phy *pi, u8 m0) ++{ ++ u16 m0m1 = (u16) m0 << 8; ++ struct phytbl_info tab; ++ ++ tab.tbl_ptr = &m0m1; ++ tab.tbl_len = 1; ++ tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; ++ tab.tbl_offset = 87; ++ tab.tbl_width = 16; ++ wlc_lcnphy_write_table(pi, &tab); ++} ++ ++static void wlc_lcnphy_clear_tx_power_offsets(struct brcms_phy *pi) ++{ ++ u32 data_buf[64]; ++ struct phytbl_info tab; ++ ++ memset(data_buf, 0, sizeof(data_buf)); ++ ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_ptr = data_buf; ++ ++ if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { ++ ++ tab.tbl_len = 30; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET; ++ wlc_lcnphy_write_table(pi, &tab); ++ } ++ ++ tab.tbl_len = 64; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_MAC_OFFSET; ++ wlc_lcnphy_write_table(pi, &tab); ++} ++ ++enum lcnphy_tssi_mode { ++ LCNPHY_TSSI_PRE_PA, ++ LCNPHY_TSSI_POST_PA, ++ LCNPHY_TSSI_EXT ++}; ++ ++static void ++wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos) ++{ ++ mod_phy_reg(pi, 0x4d7, (0x1 << 0), (0x1) << 0); ++ ++ mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1) << 6); ++ ++ if (LCNPHY_TSSI_POST_PA == pos) { ++ mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0) << 2); ++ ++ mod_phy_reg(pi, 0x4d9, (0x1 << 3), (1) << 3); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { ++ mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); ++ } else { ++ mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1); ++ mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); ++ } ++ } else { ++ mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2); ++ ++ mod_phy_reg(pi, 0x4d9, (0x1 << 3), (0) << 3); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { ++ mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); ++ } else { ++ mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0); ++ mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); ++ } ++ } ++ mod_phy_reg(pi, 0x637, (0x3 << 14), (0) << 14); ++ ++ if (LCNPHY_TSSI_EXT == pos) { ++ write_radio_reg(pi, RADIO_2064_REG07F, 1); ++ mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 0x2); ++ mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 0x1 << 7); ++ mod_radio_reg(pi, RADIO_2064_REG028, 0x1f, 0x3); ++ } ++} ++ ++static u16 wlc_lcnphy_rfseq_tbl_adc_pwrup(struct brcms_phy *pi) ++{ ++ u16 N1, N2, N3, N4, N5, N6, N; ++ N1 = ((read_phy_reg(pi, 0x4a5) & (0xff << 0)) ++ >> 0); ++ N2 = 1 << ((read_phy_reg(pi, 0x4a5) & (0x7 << 12)) ++ >> 12); ++ N3 = ((read_phy_reg(pi, 0x40d) & (0xff << 0)) ++ >> 0); ++ N4 = 1 << ((read_phy_reg(pi, 0x40d) & (0x7 << 8)) ++ >> 8); ++ N5 = ((read_phy_reg(pi, 0x4a2) & (0xff << 0)) ++ >> 0); ++ N6 = 1 << ((read_phy_reg(pi, 0x4a2) & (0x7 << 8)) ++ >> 8); ++ N = 2 * (N1 + N2 + N3 + N4 + 2 * (N5 + N6)) + 80; ++ if (N < 1600) ++ N = 1600; ++ return N; ++} ++ ++static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi) ++{ ++ u16 auxpga_vmid, auxpga_vmid_temp, auxpga_gain_temp; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ auxpga_vmid = (2 << 8) | ++ (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf; ++ auxpga_vmid_temp = (2 << 8) | (8 << 4) | 4; ++ auxpga_gain_temp = 2; ++ ++ mod_phy_reg(pi, 0x4d8, (0x1 << 0), (0) << 0); ++ ++ mod_phy_reg(pi, 0x4d8, (0x1 << 1), (0) << 1); ++ ++ mod_phy_reg(pi, 0x4d7, (0x1 << 3), (0) << 3); ++ ++ mod_phy_reg(pi, 0x4db, ++ (0x3ff << 0) | ++ (0x7 << 12), ++ (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12)); ++ ++ mod_phy_reg(pi, 0x4dc, ++ (0x3ff << 0) | ++ (0x7 << 12), ++ (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12)); ++ ++ mod_phy_reg(pi, 0x40a, ++ (0x3ff << 0) | ++ (0x7 << 12), ++ (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12)); ++ ++ mod_phy_reg(pi, 0x40b, ++ (0x3ff << 0) | ++ (0x7 << 12), ++ (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12)); ++ ++ mod_phy_reg(pi, 0x40c, ++ (0x3ff << 0) | ++ (0x7 << 12), ++ (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12)); ++ ++ mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5)); ++} ++ ++static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) ++{ ++ struct phytbl_info tab; ++ u32 rfseq, ind; ++ ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_ptr = &ind; ++ tab.tbl_len = 1; ++ tab.tbl_offset = 0; ++ for (ind = 0; ind < 128; ind++) { ++ wlc_lcnphy_write_table(pi, &tab); ++ tab.tbl_offset++; ++ } ++ tab.tbl_offset = 704; ++ for (ind = 0; ind < 128; ind++) { ++ wlc_lcnphy_write_table(pi, &tab); ++ tab.tbl_offset++; ++ } ++ mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0); ++ ++ mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2); ++ ++ mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4); ++ ++ wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT); ++ mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15); ++ ++ mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1ff << 0), (0) << 0); ++ ++ mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0); ++ ++ mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12); ++ ++ mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8); ++ ++ mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0); ++ ++ mod_phy_reg(pi, 0x40d, (0x7 << 8), (4) << 8); ++ ++ mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0); ++ ++ mod_phy_reg(pi, 0x4a2, (0x7 << 8), (4) << 8); ++ ++ mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (0) << 6); ++ ++ mod_phy_reg(pi, 0x4a8, (0xff << 0), (0x1) << 0); ++ ++ wlc_lcnphy_clear_tx_power_offsets(pi); ++ ++ mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15); ++ ++ mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (0xff) << 0); ++ ++ mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { ++ mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe); ++ mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); ++ } else { ++ mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1); ++ mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3); ++ } ++ ++ write_radio_reg(pi, RADIO_2064_REG025, 0xc); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { ++ mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1); ++ } else { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1); ++ else ++ mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 0 << 1); ++ } ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) ++ mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1); ++ else ++ mod_radio_reg(pi, RADIO_2064_REG03A, 0x4, 1 << 2); ++ ++ mod_radio_reg(pi, RADIO_2064_REG11A, 0x1, 1 << 0); ++ ++ mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 1 << 3); ++ ++ if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) ++ mod_phy_reg(pi, 0x4d7, ++ (0x1 << 3) | (0x7 << 12), 0 << 3 | 2 << 12); ++ ++ rfseq = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi); ++ tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; ++ tab.tbl_width = 16; ++ tab.tbl_ptr = &rfseq; ++ tab.tbl_len = 1; ++ tab.tbl_offset = 6; ++ wlc_lcnphy_write_table(pi, &tab); ++ ++ mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2); ++ ++ mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12); ++ ++ mod_phy_reg(pi, 0x4d7, (0x1 << 2), (1) << 2); ++ ++ mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8); ++ ++ wlc_lcnphy_pwrctrl_rssiparams(pi); ++} ++ ++void wlc_lcnphy_tx_pwr_update_npt(struct brcms_phy *pi) ++{ ++ u16 tx_cnt, tx_total, npt; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ tx_total = wlc_lcnphy_total_tx_frames(pi); ++ tx_cnt = tx_total - pi_lcn->lcnphy_tssi_tx_cnt; ++ npt = wlc_lcnphy_get_tx_pwr_npt(pi); ++ ++ if (tx_cnt > (1 << npt)) { ++ ++ pi_lcn->lcnphy_tssi_tx_cnt = tx_total; ++ ++ pi_lcn->lcnphy_tssi_idx = wlc_lcnphy_get_current_tx_pwr_idx(pi); ++ pi_lcn->lcnphy_tssi_npt = npt; ++ ++ } ++} ++ ++s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1) ++{ ++ s32 a, b, p; ++ ++ a = 32768 + (a1 * tssi); ++ b = (1024 * b0) + (64 * b1 * tssi); ++ p = ((2 * b) + a) / (2 * a); ++ ++ return p; ++} ++ ++static void wlc_lcnphy_txpower_reset_npt(struct brcms_phy *pi) ++{ ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) ++ return; ++ ++ pi_lcn->lcnphy_tssi_idx = LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313; ++ pi_lcn->lcnphy_tssi_npt = LCNPHY_TX_PWR_CTRL_START_NPT; ++} ++ ++void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi) ++{ ++ struct phytbl_info tab; ++ u32 rate_table[BRCMS_NUM_RATES_CCK + BRCMS_NUM_RATES_OFDM + ++ BRCMS_NUM_RATES_MCS_1_STREAM]; ++ uint i, j; ++ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) ++ return; ++ ++ for (i = 0, j = 0; i < ARRAY_SIZE(rate_table); i++, j++) { ++ ++ if (i == BRCMS_NUM_RATES_CCK + BRCMS_NUM_RATES_OFDM) ++ j = TXP_FIRST_MCS_20_SISO; ++ ++ rate_table[i] = (u32) ((s32) (-pi->tx_power_offset[j])); ++ } ++ ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_len = ARRAY_SIZE(rate_table); ++ tab.tbl_ptr = rate_table; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET; ++ wlc_lcnphy_write_table(pi, &tab); ++ ++ if (wlc_lcnphy_get_target_tx_pwr(pi) != pi->tx_power_min) { ++ wlc_lcnphy_set_target_tx_pwr(pi, pi->tx_power_min); ++ ++ wlc_lcnphy_txpower_reset_npt(pi); ++ } ++} ++ ++static void wlc_lcnphy_set_tx_pwr_soft_ctrl(struct brcms_phy *pi, s8 index) ++{ ++ u32 cck_offset[4] = { 22, 22, 22, 22 }; ++ u32 ofdm_offset, reg_offset_cck; ++ int i; ++ u16 index2; ++ struct phytbl_info tab; ++ ++ if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) ++ return; ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x0) << 14); ++ ++ or_phy_reg(pi, 0x6da, 0x0040); ++ ++ reg_offset_cck = 0; ++ for (i = 0; i < 4; i++) ++ cck_offset[i] -= reg_offset_cck; ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_len = 4; ++ tab.tbl_ptr = cck_offset; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET; ++ wlc_lcnphy_write_table(pi, &tab); ++ ofdm_offset = 0; ++ tab.tbl_len = 1; ++ tab.tbl_ptr = &ofdm_offset; ++ for (i = 836; i < 862; i++) { ++ tab.tbl_offset = i; ++ wlc_lcnphy_write_table(pi, &tab); ++ } ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0x1) << 15); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 13), (0x1) << 13); ++ ++ mod_phy_reg(pi, 0x4b0, (0x1 << 7), (0) << 7); ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 6), (0) << 6); ++ ++ mod_phy_reg(pi, 0x4a9, (0x1 << 15), (1) << 15); ++ ++ index2 = (u16) (index * 2); ++ mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0); ++ ++ mod_phy_reg(pi, 0x6a3, (0x1 << 4), (0) << 4); ++ ++} ++ ++static s8 wlc_lcnphy_tempcompensated_txpwrctrl(struct brcms_phy *pi) ++{ ++ s8 index, delta_brd, delta_temp, new_index, tempcorrx; ++ s16 manp, meas_temp, temp_diff; ++ bool neg = 0; ++ u16 temp; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) ++ return pi_lcn->lcnphy_current_index; ++ ++ index = FIXED_TXPWR; ++ ++ if (pi_lcn->lcnphy_tempsense_slope == 0) ++ return index; ++ ++ temp = (u16) wlc_lcnphy_tempsense(pi, 0); ++ meas_temp = LCNPHY_TEMPSENSE(temp); ++ ++ if (pi->tx_power_min != 0) ++ delta_brd = (pi_lcn->lcnphy_measPower - pi->tx_power_min); ++ else ++ delta_brd = 0; ++ ++ manp = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_rawtempsense); ++ temp_diff = manp - meas_temp; ++ if (temp_diff < 0) { ++ neg = 1; ++ temp_diff = -temp_diff; ++ } ++ ++ delta_temp = (s8) wlc_lcnphy_qdiv_roundup((u32) (temp_diff * 192), ++ (u32) (pi_lcn-> ++ lcnphy_tempsense_slope ++ * 10), 0); ++ if (neg) ++ delta_temp = -delta_temp; ++ ++ if (pi_lcn->lcnphy_tempsense_option == 3 ++ && LCNREV_IS(pi->pubpi.phy_rev, 0)) ++ delta_temp = 0; ++ if (pi_lcn->lcnphy_tempcorrx > 31) ++ tempcorrx = (s8) (pi_lcn->lcnphy_tempcorrx - 64); ++ else ++ tempcorrx = (s8) pi_lcn->lcnphy_tempcorrx; ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) ++ tempcorrx = 4; ++ new_index = ++ index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr; ++ new_index += tempcorrx; ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) ++ index = 127; ++ ++ if (new_index < 0 || new_index > 126) ++ return index; ++ ++ return new_index; ++} ++ ++static u16 wlc_lcnphy_set_tx_pwr_ctrl_mode(struct brcms_phy *pi, u16 mode) ++{ ++ ++ u16 current_mode = mode; ++ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && ++ mode == LCNPHY_TX_PWR_CTRL_HW) ++ current_mode = LCNPHY_TX_PWR_CTRL_TEMPBASED; ++ if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) && ++ mode == LCNPHY_TX_PWR_CTRL_TEMPBASED) ++ current_mode = LCNPHY_TX_PWR_CTRL_HW; ++ return current_mode; ++} ++ ++void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode) ++{ ++ u16 old_mode = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ s8 index; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, mode); ++ old_mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, old_mode); ++ ++ mod_phy_reg(pi, 0x6da, (0x1 << 6), ++ ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 1 : 0) << 6); ++ ++ mod_phy_reg(pi, 0x6a3, (0x1 << 4), ++ ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 0 : 1) << 4); ++ ++ if (old_mode != mode) { ++ if (LCNPHY_TX_PWR_CTRL_HW == old_mode) { ++ ++ wlc_lcnphy_tx_pwr_update_npt(pi); ++ ++ wlc_lcnphy_clear_tx_power_offsets(pi); ++ } ++ if (LCNPHY_TX_PWR_CTRL_HW == mode) { ++ ++ wlc_lcnphy_txpower_recalc_target(pi); ++ ++ wlc_lcnphy_set_start_tx_pwr_idx(pi, ++ pi_lcn-> ++ lcnphy_tssi_idx); ++ wlc_lcnphy_set_tx_pwr_npt(pi, pi_lcn->lcnphy_tssi_npt); ++ mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0); ++ ++ pi_lcn->lcnphy_tssi_tx_cnt = ++ wlc_lcnphy_total_tx_frames(pi); ++ ++ wlc_lcnphy_disable_tx_gain_override(pi); ++ pi_lcn->lcnphy_tx_power_idx_override = -1; ++ } else ++ wlc_lcnphy_enable_tx_gain_override(pi); ++ ++ mod_phy_reg(pi, 0x4a4, ++ ((0x1 << 15) | (0x1 << 14) | (0x1 << 13)), mode); ++ if (mode == LCNPHY_TX_PWR_CTRL_TEMPBASED) { ++ index = wlc_lcnphy_tempcompensated_txpwrctrl(pi); ++ wlc_lcnphy_set_tx_pwr_soft_ctrl(pi, index); ++ pi_lcn->lcnphy_current_index = (s8) ++ ((read_phy_reg(pi, ++ 0x4a9) & ++ 0xFF) / 2); ++ } ++ } ++} ++ ++static void ++wlc_lcnphy_tx_iqlo_loopback(struct brcms_phy *pi, u16 *values_to_save) ++{ ++ u16 vmid; ++ int i; ++ for (i = 0; i < 20; i++) ++ values_to_save[i] = ++ read_radio_reg(pi, iqlo_loopback_rf_regs[i]); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12); ++ mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 11), 1 << 11); ++ mod_phy_reg(pi, 0x44d, (0x1 << 13), 0 << 13); ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); ++ mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) ++ and_radio_reg(pi, RADIO_2064_REG03A, 0xFD); ++ else ++ and_radio_reg(pi, RADIO_2064_REG03A, 0xF9); ++ or_radio_reg(pi, RADIO_2064_REG11A, 0x1); ++ ++ or_radio_reg(pi, RADIO_2064_REG036, 0x01); ++ or_radio_reg(pi, RADIO_2064_REG11A, 0x18); ++ udelay(20); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) ++ mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0); ++ else ++ or_radio_reg(pi, RADIO_2064_REG03A, 1); ++ } else { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) ++ mod_radio_reg(pi, RADIO_2064_REG03A, 3, 1); ++ else ++ or_radio_reg(pi, RADIO_2064_REG03A, 0x3); ++ } ++ ++ udelay(20); ++ ++ write_radio_reg(pi, RADIO_2064_REG025, 0xF); ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) ++ mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x4); ++ else ++ mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x6); ++ } else { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) ++ mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x4 << 1); ++ else ++ mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x6 << 1); ++ } ++ ++ udelay(20); ++ ++ write_radio_reg(pi, RADIO_2064_REG005, 0x8); ++ or_radio_reg(pi, RADIO_2064_REG112, 0x80); ++ udelay(20); ++ ++ or_radio_reg(pi, RADIO_2064_REG0FF, 0x10); ++ or_radio_reg(pi, RADIO_2064_REG11F, 0x44); ++ udelay(20); ++ ++ or_radio_reg(pi, RADIO_2064_REG00B, 0x7); ++ or_radio_reg(pi, RADIO_2064_REG113, 0x10); ++ udelay(20); ++ ++ write_radio_reg(pi, RADIO_2064_REG007, 0x1); ++ udelay(20); ++ ++ vmid = 0x2A6; ++ mod_radio_reg(pi, RADIO_2064_REG0FC, 0x3 << 0, (vmid >> 8) & 0x3); ++ write_radio_reg(pi, RADIO_2064_REG0FD, (vmid & 0xff)); ++ or_radio_reg(pi, RADIO_2064_REG11F, 0x44); ++ udelay(20); ++ ++ or_radio_reg(pi, RADIO_2064_REG0FF, 0x10); ++ udelay(20); ++ write_radio_reg(pi, RADIO_2064_REG012, 0x02); ++ or_radio_reg(pi, RADIO_2064_REG112, 0x06); ++ write_radio_reg(pi, RADIO_2064_REG036, 0x11); ++ write_radio_reg(pi, RADIO_2064_REG059, 0xcc); ++ write_radio_reg(pi, RADIO_2064_REG05C, 0x2e); ++ write_radio_reg(pi, RADIO_2064_REG078, 0xd7); ++ write_radio_reg(pi, RADIO_2064_REG092, 0x15); ++} ++ ++static bool wlc_lcnphy_iqcal_wait(struct brcms_phy *pi) ++{ ++ uint delay_count = 0; ++ ++ while (wlc_lcnphy_iqcal_active(pi)) { ++ udelay(100); ++ delay_count++; ++ ++ if (delay_count > (10 * 500)) ++ break; ++ } ++ ++ return (0 == wlc_lcnphy_iqcal_active(pi)); ++} ++ ++static void ++wlc_lcnphy_tx_iqlo_loopback_cleanup(struct brcms_phy *pi, u16 *values_to_save) ++{ ++ int i; ++ ++ and_phy_reg(pi, 0x44c, 0x0 >> 11); ++ ++ and_phy_reg(pi, 0x43b, 0xC); ++ ++ for (i = 0; i < 20; i++) ++ write_radio_reg(pi, iqlo_loopback_rf_regs[i], ++ values_to_save[i]); ++} ++ ++static void ++wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi, ++ struct lcnphy_txgains *target_gains, ++ enum lcnphy_cal_mode cal_mode, bool keep_tone) ++{ ++ ++ struct lcnphy_txgains cal_gains, temp_gains; ++ u16 hash; ++ u8 band_idx; ++ int j; ++ u16 ncorr_override[5]; ++ u16 syst_coeffs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}; ++ ++ u16 commands_fullcal[] = { ++ 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 ++ }; ++ ++ u16 commands_recal[] = { ++ 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 ++ }; ++ ++ u16 command_nums_fullcal[] = { ++ 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 ++ }; ++ ++ u16 command_nums_recal[] = { ++ 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 ++ }; ++ u16 *command_nums = command_nums_fullcal; ++ ++ u16 *start_coeffs = NULL, *cal_cmds = NULL, cal_type, diq_start; ++ u16 tx_pwr_ctrl_old, save_txpwrctrlrfctrl2; ++ u16 save_sslpnCalibClkEnCtrl, save_sslpnRxFeClkEnCtrl; ++ bool tx_gain_override_old; ++ struct lcnphy_txgains old_gains; ++ uint i, n_cal_cmds = 0, n_cal_start = 0; ++ u16 *values_to_save; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ values_to_save = kmalloc(sizeof(u16) * 20, GFP_ATOMIC); ++ if (NULL == values_to_save) ++ return; ++ ++ save_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db); ++ save_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); ++ ++ or_phy_reg(pi, 0x6da, 0x40); ++ or_phy_reg(pi, 0x6db, 0x3); ++ ++ switch (cal_mode) { ++ case LCNPHY_CAL_FULL: ++ start_coeffs = syst_coeffs; ++ cal_cmds = commands_fullcal; ++ n_cal_cmds = ARRAY_SIZE(commands_fullcal); ++ break; ++ ++ case LCNPHY_CAL_RECAL: ++ start_coeffs = syst_coeffs; ++ cal_cmds = commands_recal; ++ n_cal_cmds = ARRAY_SIZE(commands_recal); ++ command_nums = command_nums_recal; ++ break; ++ ++ default: ++ break; ++ } ++ ++ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ start_coeffs, 11, 16, 64); ++ ++ write_phy_reg(pi, 0x6da, 0xffff); ++ mod_phy_reg(pi, 0x503, (0x1 << 3), (1) << 3); ++ ++ tx_pwr_ctrl_old = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12); ++ ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); ++ ++ save_txpwrctrlrfctrl2 = read_phy_reg(pi, 0x4db); ++ ++ mod_phy_reg(pi, 0x4db, (0x3ff << 0), (0x2a6) << 0); ++ ++ mod_phy_reg(pi, 0x4db, (0x7 << 12), (2) << 12); ++ ++ wlc_lcnphy_tx_iqlo_loopback(pi, values_to_save); ++ ++ tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); ++ if (tx_gain_override_old) ++ wlc_lcnphy_get_tx_gain(pi, &old_gains); ++ ++ if (!target_gains) { ++ if (!tx_gain_override_old) ++ wlc_lcnphy_set_tx_pwr_by_index(pi, ++ pi_lcn->lcnphy_tssi_idx); ++ wlc_lcnphy_get_tx_gain(pi, &temp_gains); ++ target_gains = &temp_gains; ++ } ++ ++ hash = (target_gains->gm_gain << 8) | ++ (target_gains->pga_gain << 4) | (target_gains->pad_gain); ++ ++ band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0); ++ ++ cal_gains = *target_gains; ++ memset(ncorr_override, 0, sizeof(ncorr_override)); ++ for (j = 0; j < iqcal_gainparams_numgains_lcnphy[band_idx]; j++) { ++ if (hash == tbl_iqcal_gainparams_lcnphy[band_idx][j][0]) { ++ cal_gains.gm_gain = ++ tbl_iqcal_gainparams_lcnphy[band_idx][j][1]; ++ cal_gains.pga_gain = ++ tbl_iqcal_gainparams_lcnphy[band_idx][j][2]; ++ cal_gains.pad_gain = ++ tbl_iqcal_gainparams_lcnphy[band_idx][j][3]; ++ memcpy(ncorr_override, ++ &tbl_iqcal_gainparams_lcnphy[band_idx][j][3], ++ sizeof(ncorr_override)); ++ break; ++ } ++ } ++ ++ wlc_lcnphy_set_tx_gain(pi, &cal_gains); ++ ++ write_phy_reg(pi, 0x453, 0xaa9); ++ write_phy_reg(pi, 0x93d, 0xc0); ++ ++ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ lcnphy_iqcal_loft_gainladder, ++ ARRAY_SIZE(lcnphy_iqcal_loft_gainladder), ++ 16, 0); ++ ++ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ lcnphy_iqcal_ir_gainladder, ++ ARRAY_SIZE( ++ lcnphy_iqcal_ir_gainladder), 16, ++ 32); ++ ++ if (pi->phy_tx_tone_freq) { ++ ++ wlc_lcnphy_stop_tx_tone(pi); ++ udelay(5); ++ wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1); ++ } else { ++ wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1); ++ } ++ ++ write_phy_reg(pi, 0x6da, 0xffff); ++ ++ for (i = n_cal_start; i < n_cal_cmds; i++) { ++ u16 zero_diq = 0; ++ u16 best_coeffs[11]; ++ u16 command_num; ++ ++ cal_type = (cal_cmds[i] & 0x0f00) >> 8; ++ ++ command_num = command_nums[i]; ++ if (ncorr_override[cal_type]) ++ command_num = ++ ncorr_override[cal_type] << 8 | (command_num & ++ 0xff); ++ ++ write_phy_reg(pi, 0x452, command_num); ++ ++ if ((cal_type == 3) || (cal_type == 4)) { ++ wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ &diq_start, 1, 16, 69); ++ ++ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ &zero_diq, 1, 16, 69); ++ } ++ ++ write_phy_reg(pi, 0x451, cal_cmds[i]); ++ ++ if (!wlc_lcnphy_iqcal_wait(pi)) ++ goto cleanup; ++ ++ wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ best_coeffs, ++ ARRAY_SIZE(best_coeffs), 16, 96); ++ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ best_coeffs, ++ ARRAY_SIZE(best_coeffs), 16, 64); ++ ++ if ((cal_type == 3) || (cal_type == 4)) ++ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ &diq_start, 1, 16, 69); ++ wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ pi_lcn->lcnphy_cal_results. ++ txiqlocal_bestcoeffs, ++ ARRAY_SIZE(pi_lcn-> ++ lcnphy_cal_results. ++ txiqlocal_bestcoeffs), ++ 16, 96); ++ } ++ ++ wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ pi_lcn->lcnphy_cal_results. ++ txiqlocal_bestcoeffs, ++ ARRAY_SIZE(pi_lcn->lcnphy_cal_results. ++ txiqlocal_bestcoeffs), 16, 96); ++ pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid = true; ++ ++ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ &pi_lcn->lcnphy_cal_results. ++ txiqlocal_bestcoeffs[0], 4, 16, 80); ++ ++ wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, ++ &pi_lcn->lcnphy_cal_results. ++ txiqlocal_bestcoeffs[5], 2, 16, 85); ++ ++cleanup: ++ wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, values_to_save); ++ kfree(values_to_save); ++ ++ if (!keep_tone) ++ wlc_lcnphy_stop_tx_tone(pi); ++ ++ write_phy_reg(pi, 0x4db, save_txpwrctrlrfctrl2); ++ ++ write_phy_reg(pi, 0x453, 0); ++ ++ if (tx_gain_override_old) ++ wlc_lcnphy_set_tx_gain(pi, &old_gains); ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl_old); ++ ++ write_phy_reg(pi, 0x6da, save_sslpnCalibClkEnCtrl); ++ write_phy_reg(pi, 0x6db, save_sslpnRxFeClkEnCtrl); ++ ++} ++ ++static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) ++{ ++ bool suspend, tx_gain_override_old; ++ struct lcnphy_txgains old_gains; ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ u16 idleTssi, idleTssi0_2C, idleTssi0_OB, idleTssi0_regvalue_OB, ++ idleTssi0_regvalue_2C; ++ u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ u16 SAVE_lpfgain = read_radio_reg(pi, RADIO_2064_REG112); ++ u16 SAVE_jtag_bb_afe_switch = ++ read_radio_reg(pi, RADIO_2064_REG007) & 1; ++ u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10; ++ u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4; ++ idleTssi = read_phy_reg(pi, 0x4ab); ++ suspend = ++ (0 == ++ (R_REG(&((struct brcms_phy *) pi)->regs->maccontrol) & ++ MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); ++ ++ tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); ++ wlc_lcnphy_get_tx_gain(pi, &old_gains); ++ ++ wlc_lcnphy_enable_tx_gain_override(pi); ++ wlc_lcnphy_set_tx_pwr_by_index(pi, 127); ++ write_radio_reg(pi, RADIO_2064_REG112, 0x6); ++ mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 1); ++ mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4); ++ mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2); ++ wlc_lcnphy_tssi_setup(pi); ++ wlc_phy_do_dummy_tx(pi, true, OFF); ++ idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0)) ++ >> 0); ++ ++ idleTssi0_2C = ((read_phy_reg(pi, 0x63e) & (0x1ff << 0)) ++ >> 0); ++ ++ if (idleTssi0_2C >= 256) ++ idleTssi0_OB = idleTssi0_2C - 256; ++ else ++ idleTssi0_OB = idleTssi0_2C + 256; ++ ++ idleTssi0_regvalue_OB = idleTssi0_OB; ++ if (idleTssi0_regvalue_OB >= 256) ++ idleTssi0_regvalue_2C = idleTssi0_regvalue_OB - 256; ++ else ++ idleTssi0_regvalue_2C = idleTssi0_regvalue_OB + 256; ++ mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (idleTssi0_regvalue_2C) << 0); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12); ++ ++ wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old); ++ wlc_lcnphy_set_tx_gain(pi, &old_gains); ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); ++ ++ write_radio_reg(pi, RADIO_2064_REG112, SAVE_lpfgain); ++ mod_radio_reg(pi, RADIO_2064_REG007, 0x1, SAVE_jtag_bb_afe_switch); ++ mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, SAVE_jtag_auxpga); ++ mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, SAVE_iqadc_aux_en); ++ mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1 << 7); ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++} ++ ++static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode) ++{ ++ bool suspend; ++ u16 save_txpwrCtrlEn; ++ u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain; ++ u16 auxpga_vmid; ++ struct phytbl_info tab; ++ u32 val; ++ u8 save_reg007, save_reg0FF, save_reg11F, save_reg005, save_reg025, ++ save_reg112; ++ u16 values_to_save[14]; ++ s8 index; ++ int i; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ udelay(999); ++ ++ save_reg007 = (u8) read_radio_reg(pi, RADIO_2064_REG007); ++ save_reg0FF = (u8) read_radio_reg(pi, RADIO_2064_REG0FF); ++ save_reg11F = (u8) read_radio_reg(pi, RADIO_2064_REG11F); ++ save_reg005 = (u8) read_radio_reg(pi, RADIO_2064_REG005); ++ save_reg025 = (u8) read_radio_reg(pi, RADIO_2064_REG025); ++ save_reg112 = (u8) read_radio_reg(pi, RADIO_2064_REG112); ++ ++ for (i = 0; i < 14; i++) ++ values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]); ++ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4); ++ ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); ++ index = pi_lcn->lcnphy_current_index; ++ wlc_lcnphy_set_tx_pwr_by_index(pi, 127); ++ mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 0x1); ++ mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 0x1 << 4); ++ mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0x1 << 2); ++ mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0); ++ ++ mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0) << 15); ++ ++ mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5); ++ ++ mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0); ++ ++ mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12); ++ ++ mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8); ++ ++ mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0); ++ ++ mod_phy_reg(pi, 0x40d, (0x7 << 8), (6) << 8); ++ ++ mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0); ++ ++ mod_phy_reg(pi, 0x4a2, (0x7 << 8), (6) << 8); ++ ++ mod_phy_reg(pi, 0x4d9, (0x7 << 4), (2) << 4); ++ ++ mod_phy_reg(pi, 0x4d9, (0x7 << 8), (3) << 8); ++ ++ mod_phy_reg(pi, 0x4d9, (0x7 << 12), (1) << 12); ++ ++ mod_phy_reg(pi, 0x4da, (0x1 << 12), (0) << 12); ++ ++ mod_phy_reg(pi, 0x4da, (0x1 << 13), (1) << 13); ++ ++ mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15); ++ ++ write_radio_reg(pi, RADIO_2064_REG025, 0xC); ++ ++ mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 0x1 << 3); ++ ++ mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2); ++ ++ mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2); ++ ++ mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12); ++ ++ val = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi); ++ tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; ++ tab.tbl_width = 16; ++ tab.tbl_len = 1; ++ tab.tbl_ptr = &val; ++ tab.tbl_offset = 6; ++ wlc_lcnphy_write_table(pi, &tab); ++ if (mode == TEMPSENSE) { ++ mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3); ++ ++ mod_phy_reg(pi, 0x4d7, (0x7 << 12), (1) << 12); ++ ++ auxpga_vmidcourse = 8; ++ auxpga_vmidfine = 0x4; ++ auxpga_gain = 2; ++ mod_radio_reg(pi, RADIO_2064_REG082, 0x20, 1 << 5); ++ } else { ++ mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3); ++ ++ mod_phy_reg(pi, 0x4d7, (0x7 << 12), (3) << 12); ++ ++ auxpga_vmidcourse = 7; ++ auxpga_vmidfine = 0xa; ++ auxpga_gain = 2; ++ } ++ auxpga_vmid = ++ (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine); ++ mod_phy_reg(pi, 0x4d8, (0x1 << 0), (1) << 0); ++ ++ mod_phy_reg(pi, 0x4d8, (0x3ff << 2), (auxpga_vmid) << 2); ++ ++ mod_phy_reg(pi, 0x4d8, (0x1 << 1), (1) << 1); ++ ++ mod_phy_reg(pi, 0x4d8, (0x7 << 12), (auxpga_gain) << 12); ++ ++ mod_phy_reg(pi, 0x4d0, (0x1 << 5), (1) << 5); ++ ++ write_radio_reg(pi, RADIO_2064_REG112, 0x6); ++ ++ wlc_phy_do_dummy_tx(pi, true, OFF); ++ if (!tempsense_done(pi)) ++ udelay(10); ++ ++ write_radio_reg(pi, RADIO_2064_REG007, (u16) save_reg007); ++ write_radio_reg(pi, RADIO_2064_REG0FF, (u16) save_reg0FF); ++ write_radio_reg(pi, RADIO_2064_REG11F, (u16) save_reg11F); ++ write_radio_reg(pi, RADIO_2064_REG005, (u16) save_reg005); ++ write_radio_reg(pi, RADIO_2064_REG025, (u16) save_reg025); ++ write_radio_reg(pi, RADIO_2064_REG112, (u16) save_reg112); ++ for (i = 0; i < 14; i++) ++ write_phy_reg(pi, tempsense_phy_regs[i], values_to_save[i]); ++ wlc_lcnphy_set_tx_pwr_by_index(pi, (int)index); ++ ++ write_radio_reg(pi, 0x4a4, save_txpwrCtrlEn); ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++ udelay(999); ++} ++ ++static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi) ++{ ++ struct lcnphy_txgains tx_gains; ++ u8 bbmult; ++ struct phytbl_info tab; ++ s32 a1, b0, b1; ++ s32 tssi, pwr, maxtargetpwr, mintargetpwr; ++ bool suspend; ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ ++ suspend = ++ (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ if (!pi->hwpwrctrl_capable) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ tx_gains.gm_gain = 4; ++ tx_gains.pga_gain = 12; ++ tx_gains.pad_gain = 12; ++ tx_gains.dac_gain = 0; ++ ++ bbmult = 150; ++ } else { ++ tx_gains.gm_gain = 7; ++ tx_gains.pga_gain = 15; ++ tx_gains.pad_gain = 14; ++ tx_gains.dac_gain = 0; ++ ++ bbmult = 150; ++ } ++ wlc_lcnphy_set_tx_gain(pi, &tx_gains); ++ wlc_lcnphy_set_bbmult(pi, bbmult); ++ wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); ++ } else { ++ ++ wlc_lcnphy_idle_tssi_est(ppi); ++ ++ wlc_lcnphy_clear_tx_power_offsets(pi); ++ ++ b0 = pi->txpa_2g[0]; ++ b1 = pi->txpa_2g[1]; ++ a1 = pi->txpa_2g[2]; ++ maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1); ++ mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1); ++ ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_ptr = &pwr; ++ tab.tbl_len = 1; ++ tab.tbl_offset = 0; ++ for (tssi = 0; tssi < 128; tssi++) { ++ pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1); ++ ++ pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr; ++ wlc_lcnphy_write_table(pi, &tab); ++ tab.tbl_offset++; ++ } ++ ++ mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7); ++ ++ write_phy_reg(pi, 0x4a8, 10); ++ ++ wlc_lcnphy_set_target_tx_pwr(pi, LCN_TARGET_PWR); ++ ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW); ++ } ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++} ++ ++static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi) ++{ ++ u16 m0m1; ++ struct phytbl_info tab; ++ ++ tab.tbl_ptr = &m0m1; ++ tab.tbl_len = 1; ++ tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; ++ tab.tbl_offset = 87; ++ tab.tbl_width = 16; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ return (u8) ((m0m1 & 0xff00) >> 8); ++} ++ ++static void wlc_lcnphy_set_pa_gain(struct brcms_phy *pi, u16 gain) ++{ ++ mod_phy_reg(pi, 0x4fb, ++ LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK, ++ gain << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT); ++ mod_phy_reg(pi, 0x4fd, ++ LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK, ++ gain << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT); ++} ++ ++void ++wlc_lcnphy_get_radio_loft(struct brcms_phy *pi, ++ u8 *ei0, u8 *eq0, u8 *fi0, u8 *fq0) ++{ ++ *ei0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG089)); ++ *eq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08A)); ++ *fi0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08B)); ++ *fq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08C)); ++} ++ ++void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b) ++{ ++ struct phytbl_info tab; ++ u16 iqcc[2]; ++ ++ iqcc[0] = a; ++ iqcc[1] = b; ++ ++ tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; ++ tab.tbl_width = 16; ++ tab.tbl_ptr = iqcc; ++ tab.tbl_len = 2; ++ tab.tbl_offset = 80; ++ wlc_lcnphy_write_table(pi, &tab); ++} ++ ++void wlc_lcnphy_set_tx_locc(struct brcms_phy *pi, u16 didq) ++{ ++ struct phytbl_info tab; ++ ++ tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; ++ tab.tbl_width = 16; ++ tab.tbl_ptr = &didq; ++ tab.tbl_len = 1; ++ tab.tbl_offset = 85; ++ wlc_lcnphy_write_table(pi, &tab); ++} ++ ++void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index) ++{ ++ struct phytbl_info tab; ++ u16 a, b; ++ u8 bb_mult; ++ u32 bbmultiqcomp, txgain, locoeffs, rfpower; ++ struct lcnphy_txgains gains; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ pi_lcn->lcnphy_tx_power_idx_override = (s8) index; ++ pi_lcn->lcnphy_current_index = (u8) index; ++ ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_len = 1; ++ ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); ++ ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index; ++ tab.tbl_ptr = &bbmultiqcomp; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index; ++ tab.tbl_width = 32; ++ tab.tbl_ptr = &txgain; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ gains.gm_gain = (u16) (txgain & 0xff); ++ gains.pga_gain = (u16) (txgain >> 8) & 0xff; ++ gains.pad_gain = (u16) (txgain >> 16) & 0xff; ++ gains.dac_gain = (u16) (bbmultiqcomp >> 28) & 0x07; ++ wlc_lcnphy_set_tx_gain(pi, &gains); ++ wlc_lcnphy_set_pa_gain(pi, (u16) (txgain >> 24) & 0x7f); ++ ++ bb_mult = (u8) ((bbmultiqcomp >> 20) & 0xff); ++ wlc_lcnphy_set_bbmult(pi, bb_mult); ++ ++ wlc_lcnphy_enable_tx_gain_override(pi); ++ ++ if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { ++ ++ a = (u16) ((bbmultiqcomp >> 10) & 0x3ff); ++ b = (u16) (bbmultiqcomp & 0x3ff); ++ wlc_lcnphy_set_tx_iqcc(pi, a, b); ++ ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + index; ++ tab.tbl_ptr = &locoeffs; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ wlc_lcnphy_set_tx_locc(pi, (u16) locoeffs); ++ ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index; ++ tab.tbl_ptr = &rfpower; ++ wlc_lcnphy_read_table(pi, &tab); ++ mod_phy_reg(pi, 0x6a6, (0x1fff << 0), (rfpower * 8) << 0); ++ ++ } ++} ++ ++static void wlc_lcnphy_clear_papd_comptable(struct brcms_phy *pi) ++{ ++ u32 j; ++ struct phytbl_info tab; ++ u32 temp_offset[128]; ++ tab.tbl_ptr = temp_offset; ++ tab.tbl_len = 128; ++ tab.tbl_id = LCNPHY_TBL_ID_PAPDCOMPDELTATBL; ++ tab.tbl_width = 32; ++ tab.tbl_offset = 0; ++ ++ memset(temp_offset, 0, sizeof(temp_offset)); ++ for (j = 1; j < 128; j += 2) ++ temp_offset[j] = 0x80000; ++ ++ wlc_lcnphy_write_table(pi, &tab); ++ return; ++} ++ ++void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable) ++{ ++ if (!bEnable) { ++ ++ and_phy_reg(pi, 0x43b, ~(u16) ((0x1 << 1) | (0x1 << 4))); ++ ++ mod_phy_reg(pi, 0x43c, (0x1 << 1), 1 << 1); ++ ++ and_phy_reg(pi, 0x44c, ++ ~(u16) ((0x1 << 3) | ++ (0x1 << 5) | ++ (0x1 << 12) | ++ (0x1 << 0) | (0x1 << 1) | (0x1 << 2))); ++ ++ and_phy_reg(pi, 0x44d, ++ ~(u16) ((0x1 << 3) | (0x1 << 5) | (0x1 << 14))); ++ mod_phy_reg(pi, 0x44d, (0x1 << 2), 1 << 2); ++ ++ mod_phy_reg(pi, 0x44d, (0x1 << 1) | (0x1 << 0), (0x1 << 0)); ++ ++ and_phy_reg(pi, 0x4f9, ++ ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2))); ++ ++ and_phy_reg(pi, 0x4fa, ++ ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2))); ++ } else { ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); ++ mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); ++ ++ mod_phy_reg(pi, 0x43b, (0x1 << 4), 1 << 4); ++ mod_phy_reg(pi, 0x43c, (0x1 << 6), 0 << 6); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12); ++ mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14); ++ ++ wlc_lcnphy_set_trsw_override(pi, true, false); ++ ++ mod_phy_reg(pi, 0x44d, (0x1 << 2), 0 << 2); ++ mod_phy_reg(pi, 0x44c, (0x1 << 2), 1 << 2); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3); ++ mod_phy_reg(pi, 0x44d, (0x1 << 3), 1 << 3); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5); ++ mod_phy_reg(pi, 0x44d, (0x1 << 5), 0 << 5); ++ ++ mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1); ++ mod_phy_reg(pi, 0x4fa, (0x1 << 1), 1 << 1); ++ ++ mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2); ++ mod_phy_reg(pi, 0x4fa, (0x1 << 2), 1 << 2); ++ ++ mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0x4fa, (0x1 << 0), 1 << 0); ++ } else { ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3); ++ mod_phy_reg(pi, 0x44d, (0x1 << 3), 0 << 3); ++ ++ mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5); ++ mod_phy_reg(pi, 0x44d, (0x1 << 5), 1 << 5); ++ ++ mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1); ++ mod_phy_reg(pi, 0x4fa, (0x1 << 1), 0 << 1); ++ ++ mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2); ++ mod_phy_reg(pi, 0x4fa, (0x1 << 2), 0 << 2); ++ ++ mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0); ++ } ++ } ++} ++ ++static void ++wlc_lcnphy_run_samples(struct brcms_phy *pi, ++ u16 num_samps, ++ u16 num_loops, u16 wait, bool iqcalmode) ++{ ++ ++ or_phy_reg(pi, 0x6da, 0x8080); ++ ++ mod_phy_reg(pi, 0x642, (0x7f << 0), (num_samps - 1) << 0); ++ if (num_loops != 0xffff) ++ num_loops--; ++ mod_phy_reg(pi, 0x640, (0xffff << 0), num_loops << 0); ++ ++ mod_phy_reg(pi, 0x641, (0xffff << 0), wait << 0); ++ ++ if (iqcalmode) { ++ ++ and_phy_reg(pi, 0x453, (u16) ~(0x1 << 15)); ++ or_phy_reg(pi, 0x453, (0x1 << 15)); ++ } else { ++ write_phy_reg(pi, 0x63f, 1); ++ wlc_lcnphy_tx_pu(pi, 1); ++ } ++ ++ or_radio_reg(pi, RADIO_2064_REG112, 0x6); ++} ++ ++void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode) ++{ ++ ++ u8 phybw40; ++ phybw40 = CHSPEC_IS40(pi->radio_chanspec); ++ ++ if (LCNREV_LT(pi->pubpi.phy_rev, 2)) { ++ mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5); ++ mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9); ++ } else { ++ mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5); ++ mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9); ++ } ++ ++ if (phybw40 == 0) { ++ mod_phy_reg((pi), 0x410, ++ (0x1 << 6) | ++ (0x1 << 5), ++ ((CHSPEC_IS2G( ++ pi->radio_chanspec)) ? (!mode) : 0) << ++ 6 | (!mode) << 5); ++ mod_phy_reg(pi, 0x410, (0x1 << 7), (mode) << 7); ++ } ++} ++ ++void ++wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, u16 max_val, ++ bool iqcalmode) ++{ ++ u8 phy_bw; ++ u16 num_samps, t, k; ++ u32 bw; ++ s32 theta = 0, rot = 0; ++ struct cordic_iq tone_samp; ++ u32 data_buf[64]; ++ u16 i_samp, q_samp; ++ struct phytbl_info tab; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ pi->phy_tx_tone_freq = f_kHz; ++ ++ wlc_lcnphy_deaf_mode(pi, true); ++ ++ phy_bw = 40; ++ if (pi_lcn->lcnphy_spurmod) { ++ write_phy_reg(pi, 0x942, 0x2); ++ write_phy_reg(pi, 0x93b, 0x0); ++ write_phy_reg(pi, 0x93c, 0x0); ++ wlc_lcnphy_txrx_spur_avoidance_mode(pi, false); ++ } ++ ++ if (f_kHz) { ++ k = 1; ++ do { ++ bw = phy_bw * 1000 * k; ++ num_samps = bw / abs(f_kHz); ++ k++; ++ } while ((num_samps * (u32) (abs(f_kHz))) != bw); ++ } else ++ num_samps = 2; ++ ++ rot = ((f_kHz * 36) / phy_bw) / 100; ++ theta = 0; ++ ++ for (t = 0; t < num_samps; t++) { ++ ++ tone_samp = cordic_calc_iq(theta); ++ ++ theta += rot; ++ ++ i_samp = (u16) (FLOAT(tone_samp.i * max_val) & 0x3ff); ++ q_samp = (u16) (FLOAT(tone_samp.q * max_val) & 0x3ff); ++ data_buf[t] = (i_samp << 10) | q_samp; ++ } ++ ++ mod_phy_reg(pi, 0x6d6, (0x3 << 0), 0 << 0); ++ ++ mod_phy_reg(pi, 0x6da, (0x1 << 3), 1 << 3); ++ ++ tab.tbl_ptr = data_buf; ++ tab.tbl_len = num_samps; ++ tab.tbl_id = LCNPHY_TBL_ID_SAMPLEPLAY; ++ tab.tbl_offset = 0; ++ tab.tbl_width = 32; ++ wlc_lcnphy_write_table(pi, &tab); ++ ++ wlc_lcnphy_run_samples(pi, num_samps, 0xffff, 0, iqcalmode); ++} ++ ++void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi) ++{ ++ s16 playback_status; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ pi->phy_tx_tone_freq = 0; ++ if (pi_lcn->lcnphy_spurmod) { ++ write_phy_reg(pi, 0x942, 0x7); ++ write_phy_reg(pi, 0x93b, 0x2017); ++ write_phy_reg(pi, 0x93c, 0x27c5); ++ wlc_lcnphy_txrx_spur_avoidance_mode(pi, true); ++ } ++ ++ playback_status = read_phy_reg(pi, 0x644); ++ if (playback_status & (0x1 << 0)) { ++ wlc_lcnphy_tx_pu(pi, 0); ++ mod_phy_reg(pi, 0x63f, (0x1 << 1), 1 << 1); ++ } else if (playback_status & (0x1 << 1)) ++ mod_phy_reg(pi, 0x453, (0x1 << 15), 0 << 15); ++ ++ mod_phy_reg(pi, 0x6d6, (0x3 << 0), 1 << 0); ++ ++ mod_phy_reg(pi, 0x6da, (0x1 << 3), 0 << 3); ++ ++ mod_phy_reg(pi, 0x6da, (0x1 << 7), 0 << 7); ++ ++ and_radio_reg(pi, RADIO_2064_REG112, 0xFFF9); ++ ++ wlc_lcnphy_deaf_mode(pi, false); ++} ++ ++static void ++wlc_lcnphy_set_cc(struct brcms_phy *pi, int cal_type, s16 coeff_x, s16 coeff_y) ++{ ++ u16 di0dq0; ++ u16 x, y, data_rf; ++ int k; ++ switch (cal_type) { ++ case 0: ++ wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y); ++ break; ++ case 2: ++ di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff); ++ wlc_lcnphy_set_tx_locc(pi, di0dq0); ++ break; ++ case 3: ++ k = wlc_lcnphy_calc_floor(coeff_x, 0); ++ y = 8 + k; ++ k = wlc_lcnphy_calc_floor(coeff_x, 1); ++ x = 8 - k; ++ data_rf = (x * 16 + y); ++ write_radio_reg(pi, RADIO_2064_REG089, data_rf); ++ k = wlc_lcnphy_calc_floor(coeff_y, 0); ++ y = 8 + k; ++ k = wlc_lcnphy_calc_floor(coeff_y, 1); ++ x = 8 - k; ++ data_rf = (x * 16 + y); ++ write_radio_reg(pi, RADIO_2064_REG08A, data_rf); ++ break; ++ case 4: ++ k = wlc_lcnphy_calc_floor(coeff_x, 0); ++ y = 8 + k; ++ k = wlc_lcnphy_calc_floor(coeff_x, 1); ++ x = 8 - k; ++ data_rf = (x * 16 + y); ++ write_radio_reg(pi, RADIO_2064_REG08B, data_rf); ++ k = wlc_lcnphy_calc_floor(coeff_y, 0); ++ y = 8 + k; ++ k = wlc_lcnphy_calc_floor(coeff_y, 1); ++ x = 8 - k; ++ data_rf = (x * 16 + y); ++ write_radio_reg(pi, RADIO_2064_REG08C, data_rf); ++ break; ++ } ++} ++ ++static struct lcnphy_unsign16_struct ++wlc_lcnphy_get_cc(struct brcms_phy *pi, int cal_type) ++{ ++ u16 a, b, didq; ++ u8 di0, dq0, ei, eq, fi, fq; ++ struct lcnphy_unsign16_struct cc; ++ cc.re = 0; ++ cc.im = 0; ++ switch (cal_type) { ++ case 0: ++ wlc_lcnphy_get_tx_iqcc(pi, &a, &b); ++ cc.re = a; ++ cc.im = b; ++ break; ++ case 2: ++ didq = wlc_lcnphy_get_tx_locc(pi); ++ di0 = (((didq & 0xff00) << 16) >> 24); ++ dq0 = (((didq & 0x00ff) << 24) >> 24); ++ cc.re = (u16) di0; ++ cc.im = (u16) dq0; ++ break; ++ case 3: ++ wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq); ++ cc.re = (u16) ei; ++ cc.im = (u16) eq; ++ break; ++ case 4: ++ wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq); ++ cc.re = (u16) fi; ++ cc.im = (u16) fq; ++ break; ++ } ++ return cc; ++} ++ ++static void ++wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh, ++ s16 *ptr, int mode) ++{ ++ u32 curval1, curval2, stpptr, curptr, strptr, val; ++ u16 sslpnCalibClkEnCtrl, timer; ++ u16 old_sslpnCalibClkEnCtrl; ++ s16 imag, real; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ timer = 0; ++ old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); ++ ++ curval1 = R_REG(&pi->regs->psm_corectlsts); ++ ptr[130] = 0; ++ W_REG(&pi->regs->psm_corectlsts, ((1 << 6) | curval1)); ++ ++ W_REG(&pi->regs->smpl_clct_strptr, 0x7E00); ++ W_REG(&pi->regs->smpl_clct_stpptr, 0x8000); ++ udelay(20); ++ curval2 = R_REG(&pi->regs->psm_phy_hdr_param); ++ W_REG(&pi->regs->psm_phy_hdr_param, curval2 | 0x30); ++ ++ write_phy_reg(pi, 0x555, 0x0); ++ write_phy_reg(pi, 0x5a6, 0x5); ++ ++ write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6)); ++ write_phy_reg(pi, 0x5cf, 3); ++ write_phy_reg(pi, 0x5a5, 0x3); ++ write_phy_reg(pi, 0x583, 0x0); ++ write_phy_reg(pi, 0x584, 0x0); ++ write_phy_reg(pi, 0x585, 0x0fff); ++ write_phy_reg(pi, 0x586, 0x0000); ++ ++ write_phy_reg(pi, 0x580, 0x4501); ++ ++ sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); ++ write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008)); ++ stpptr = R_REG(&pi->regs->smpl_clct_stpptr); ++ curptr = R_REG(&pi->regs->smpl_clct_curptr); ++ do { ++ udelay(10); ++ curptr = R_REG(&pi->regs->smpl_clct_curptr); ++ timer++; ++ } while ((curptr != stpptr) && (timer < 500)); ++ ++ W_REG(&pi->regs->psm_phy_hdr_param, 0x2); ++ strptr = 0x7E00; ++ W_REG(&pi->regs->tplatewrptr, strptr); ++ while (strptr < 0x8000) { ++ val = R_REG(&pi->regs->tplatewrdata); ++ imag = ((val >> 16) & 0x3ff); ++ real = ((val) & 0x3ff); ++ if (imag > 511) ++ imag -= 1024; ++ ++ if (real > 511) ++ real -= 1024; ++ ++ if (pi_lcn->lcnphy_iqcal_swp_dis) ++ ptr[(strptr - 0x7E00) / 4] = real; ++ else ++ ptr[(strptr - 0x7E00) / 4] = imag; ++ ++ if (clip_detect_algo) { ++ if (imag > thresh || imag < -thresh) { ++ strptr = 0x8000; ++ ptr[130] = 1; ++ } ++ } ++ ++ strptr += 4; ++ } ++ ++ write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); ++ W_REG(&pi->regs->psm_phy_hdr_param, curval2); ++ W_REG(&pi->regs->psm_corectlsts, curval1); ++} ++ ++static void ++wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels, ++ int step_size_lg2) ++{ ++ const struct lcnphy_spb_tone *phy_c1; ++ struct lcnphy_spb_tone phy_c2; ++ struct lcnphy_unsign16_struct phy_c3; ++ int phy_c4, phy_c5, k, l, j, phy_c6; ++ u16 phy_c7, phy_c8, phy_c9; ++ s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16; ++ s16 *ptr, phy_c17; ++ s32 phy_c18, phy_c19; ++ u32 phy_c20, phy_c21; ++ bool phy_c22, phy_c23, phy_c24, phy_c25; ++ u16 phy_c26, phy_c27; ++ u16 phy_c28, phy_c29, phy_c30; ++ u16 phy_c31; ++ u16 *phy_c32; ++ phy_c21 = 0; ++ phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0; ++ ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC); ++ if (NULL == ptr) ++ return; ++ ++ phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC); ++ if (NULL == phy_c32) { ++ kfree(ptr); ++ return; ++ } ++ phy_c26 = read_phy_reg(pi, 0x6da); ++ phy_c27 = read_phy_reg(pi, 0x6db); ++ phy_c31 = read_radio_reg(pi, RADIO_2064_REG026); ++ write_phy_reg(pi, 0x93d, 0xC0); ++ ++ wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0); ++ write_phy_reg(pi, 0x6da, 0xffff); ++ or_phy_reg(pi, 0x6db, 0x3); ++ ++ wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32); ++ udelay(500); ++ phy_c28 = read_phy_reg(pi, 0x938); ++ phy_c29 = read_phy_reg(pi, 0x4d7); ++ phy_c30 = read_phy_reg(pi, 0x4d8); ++ or_phy_reg(pi, 0x938, 0x1 << 2); ++ or_phy_reg(pi, 0x4d7, 0x1 << 2); ++ or_phy_reg(pi, 0x4d7, 0x1 << 3); ++ mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12); ++ or_phy_reg(pi, 0x4d8, 1 << 0); ++ or_phy_reg(pi, 0x4d8, 1 << 1); ++ mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2); ++ mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12); ++ phy_c1 = &lcnphy_spb_tone_3750[0]; ++ phy_c4 = 32; ++ ++ if (num_levels == 0) { ++ if (cal_type != 0) ++ num_levels = 4; ++ else ++ num_levels = 9; ++ } ++ if (step_size_lg2 == 0) { ++ if (cal_type != 0) ++ step_size_lg2 = 3; ++ else ++ step_size_lg2 = 8; ++ } ++ ++ phy_c7 = (1 << step_size_lg2); ++ phy_c3 = wlc_lcnphy_get_cc(pi, cal_type); ++ phy_c15 = (s16) phy_c3.re; ++ phy_c16 = (s16) phy_c3.im; ++ if (cal_type == 2) { ++ if (phy_c3.re > 127) ++ phy_c15 = phy_c3.re - 256; ++ if (phy_c3.im > 127) ++ phy_c16 = phy_c3.im - 256; ++ } ++ wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16); ++ udelay(20); ++ for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) { ++ phy_c23 = 1; ++ phy_c22 = 0; ++ switch (cal_type) { ++ case 0: ++ phy_c10 = 511; ++ break; ++ case 2: ++ phy_c10 = 127; ++ break; ++ case 3: ++ phy_c10 = 15; ++ break; ++ case 4: ++ phy_c10 = 15; ++ break; ++ } ++ ++ phy_c9 = read_phy_reg(pi, 0x93d); ++ phy_c9 = 2 * phy_c9; ++ phy_c24 = 0; ++ phy_c5 = 7; ++ phy_c25 = 1; ++ while (1) { ++ write_radio_reg(pi, RADIO_2064_REG026, ++ (phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4)); ++ udelay(50); ++ phy_c22 = 0; ++ ptr[130] = 0; ++ wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2); ++ if (ptr[130] == 1) ++ phy_c22 = 1; ++ if (phy_c22) ++ phy_c5 -= 1; ++ if ((phy_c22 != phy_c24) && (!phy_c25)) ++ break; ++ if (!phy_c22) ++ phy_c5 += 1; ++ if (phy_c5 <= 0 || phy_c5 >= 7) ++ break; ++ phy_c24 = phy_c22; ++ phy_c25 = 0; ++ } ++ ++ if (phy_c5 < 0) ++ phy_c5 = 0; ++ else if (phy_c5 > 7) ++ phy_c5 = 7; ++ ++ for (k = -phy_c7; k <= phy_c7; k += phy_c7) { ++ for (l = -phy_c7; l <= phy_c7; l += phy_c7) { ++ phy_c11 = phy_c15 + k; ++ phy_c12 = phy_c16 + l; ++ ++ if (phy_c11 < -phy_c10) ++ phy_c11 = -phy_c10; ++ else if (phy_c11 > phy_c10) ++ phy_c11 = phy_c10; ++ if (phy_c12 < -phy_c10) ++ phy_c12 = -phy_c10; ++ else if (phy_c12 > phy_c10) ++ phy_c12 = phy_c10; ++ wlc_lcnphy_set_cc(pi, cal_type, phy_c11, ++ phy_c12); ++ udelay(20); ++ wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2); ++ ++ phy_c18 = 0; ++ phy_c19 = 0; ++ for (j = 0; j < 128; j++) { ++ if (cal_type != 0) ++ phy_c6 = j % phy_c4; ++ else ++ phy_c6 = (2 * j) % phy_c4; ++ ++ phy_c2.re = phy_c1[phy_c6].re; ++ phy_c2.im = phy_c1[phy_c6].im; ++ phy_c17 = ptr[j]; ++ phy_c18 = phy_c18 + phy_c17 * phy_c2.re; ++ phy_c19 = phy_c19 + phy_c17 * phy_c2.im; ++ } ++ ++ phy_c18 = phy_c18 >> 10; ++ phy_c19 = phy_c19 >> 10; ++ phy_c20 = ((phy_c18 * phy_c18) + ++ (phy_c19 * phy_c19)); ++ ++ if (phy_c23 || phy_c20 < phy_c21) { ++ phy_c21 = phy_c20; ++ phy_c13 = phy_c11; ++ phy_c14 = phy_c12; ++ } ++ phy_c23 = 0; ++ } ++ } ++ phy_c23 = 1; ++ phy_c15 = phy_c13; ++ phy_c16 = phy_c14; ++ phy_c7 = phy_c7 >> 1; ++ wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16); ++ udelay(20); ++ } ++ goto cleanup; ++cleanup: ++ wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32); ++ wlc_lcnphy_stop_tx_tone(pi); ++ write_phy_reg(pi, 0x6da, phy_c26); ++ write_phy_reg(pi, 0x6db, phy_c27); ++ write_phy_reg(pi, 0x938, phy_c28); ++ write_phy_reg(pi, 0x4d7, phy_c29); ++ write_phy_reg(pi, 0x4d8, phy_c30); ++ write_radio_reg(pi, RADIO_2064_REG026, phy_c31); ++ ++ kfree(phy_c32); ++ kfree(ptr); ++} ++ ++void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b) ++{ ++ u16 iqcc[2]; ++ struct phytbl_info tab; ++ ++ tab.tbl_ptr = iqcc; ++ tab.tbl_len = 2; ++ tab.tbl_id = 0; ++ tab.tbl_offset = 80; ++ tab.tbl_width = 16; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ *a = iqcc[0]; ++ *b = iqcc[1]; ++} ++ ++static void wlc_lcnphy_tx_iqlo_soft_cal_full(struct brcms_phy *pi) ++{ ++ struct lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4; ++ ++ wlc_lcnphy_set_cc(pi, 0, 0, 0); ++ wlc_lcnphy_set_cc(pi, 2, 0, 0); ++ wlc_lcnphy_set_cc(pi, 3, 0, 0); ++ wlc_lcnphy_set_cc(pi, 4, 0, 0); ++ ++ wlc_lcnphy_a1(pi, 4, 0, 0); ++ wlc_lcnphy_a1(pi, 3, 0, 0); ++ wlc_lcnphy_a1(pi, 2, 3, 2); ++ wlc_lcnphy_a1(pi, 0, 5, 8); ++ wlc_lcnphy_a1(pi, 2, 2, 1); ++ wlc_lcnphy_a1(pi, 0, 4, 3); ++ ++ iqcc0 = wlc_lcnphy_get_cc(pi, 0); ++ locc2 = wlc_lcnphy_get_cc(pi, 2); ++ locc3 = wlc_lcnphy_get_cc(pi, 3); ++ locc4 = wlc_lcnphy_get_cc(pi, 4); ++} ++ ++u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi) ++{ ++ struct phytbl_info tab; ++ u16 didq; ++ ++ tab.tbl_id = 0; ++ tab.tbl_width = 16; ++ tab.tbl_ptr = &didq; ++ tab.tbl_len = 1; ++ tab.tbl_offset = 85; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ return didq; ++} ++ ++static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi) ++{ ++ ++ struct lcnphy_txgains target_gains, old_gains; ++ u8 save_bb_mult; ++ u16 a, b, didq, save_pa_gain = 0; ++ uint idx, SAVE_txpwrindex = 0xFF; ++ u32 val; ++ u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ struct phytbl_info tab; ++ u8 ei0, eq0, fi0, fq0; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ wlc_lcnphy_get_tx_gain(pi, &old_gains); ++ save_pa_gain = wlc_lcnphy_get_pa_gain(pi); ++ ++ save_bb_mult = wlc_lcnphy_get_bbmult(pi); ++ ++ if (SAVE_txpwrctrl == LCNPHY_TX_PWR_CTRL_OFF) ++ SAVE_txpwrindex = wlc_lcnphy_get_current_tx_pwr_idx(pi); ++ ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); ++ ++ target_gains.gm_gain = 7; ++ target_gains.pga_gain = 0; ++ target_gains.pad_gain = 21; ++ target_gains.dac_gain = 0; ++ wlc_lcnphy_set_tx_gain(pi, &target_gains); ++ wlc_lcnphy_set_tx_pwr_by_index(pi, 16); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) { ++ ++ wlc_lcnphy_set_tx_pwr_by_index(pi, 30); ++ ++ wlc_lcnphy_tx_iqlo_cal(pi, &target_gains, ++ (pi_lcn-> ++ lcnphy_recal ? LCNPHY_CAL_RECAL : ++ LCNPHY_CAL_FULL), false); ++ } else { ++ wlc_lcnphy_tx_iqlo_soft_cal_full(pi); ++ } ++ ++ wlc_lcnphy_get_radio_loft(pi, &ei0, &eq0, &fi0, &fq0); ++ if ((abs((s8) fi0) == 15) && (abs((s8) fq0) == 15)) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ target_gains.gm_gain = 255; ++ target_gains.pga_gain = 255; ++ target_gains.pad_gain = 0xf0; ++ target_gains.dac_gain = 0; ++ } else { ++ target_gains.gm_gain = 7; ++ target_gains.pga_gain = 45; ++ target_gains.pad_gain = 186; ++ target_gains.dac_gain = 0; ++ } ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1) ++ || pi_lcn->lcnphy_hw_iqcal_en) { ++ ++ target_gains.pga_gain = 0; ++ target_gains.pad_gain = 30; ++ wlc_lcnphy_set_tx_pwr_by_index(pi, 16); ++ wlc_lcnphy_tx_iqlo_cal(pi, &target_gains, ++ LCNPHY_CAL_FULL, false); ++ } else { ++ wlc_lcnphy_tx_iqlo_soft_cal_full(pi); ++ } ++ } ++ ++ wlc_lcnphy_get_tx_iqcc(pi, &a, &b); ++ ++ didq = wlc_lcnphy_get_tx_locc(pi); ++ ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_ptr = &val; ++ ++ tab.tbl_len = 1; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET; ++ ++ for (idx = 0; idx < 128; idx++) { ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + idx; ++ ++ wlc_lcnphy_read_table(pi, &tab); ++ val = (val & 0xfff00000) | ++ ((u32) (a & 0x3FF) << 10) | (b & 0x3ff); ++ wlc_lcnphy_write_table(pi, &tab); ++ ++ val = didq; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + idx; ++ wlc_lcnphy_write_table(pi, &tab); ++ } ++ ++ pi_lcn->lcnphy_cal_results.txiqlocal_a = a; ++ pi_lcn->lcnphy_cal_results.txiqlocal_b = b; ++ pi_lcn->lcnphy_cal_results.txiqlocal_didq = didq; ++ pi_lcn->lcnphy_cal_results.txiqlocal_ei0 = ei0; ++ pi_lcn->lcnphy_cal_results.txiqlocal_eq0 = eq0; ++ pi_lcn->lcnphy_cal_results.txiqlocal_fi0 = fi0; ++ pi_lcn->lcnphy_cal_results.txiqlocal_fq0 = fq0; ++ ++ wlc_lcnphy_set_bbmult(pi, save_bb_mult); ++ wlc_lcnphy_set_pa_gain(pi, save_pa_gain); ++ wlc_lcnphy_set_tx_gain(pi, &old_gains); ++ ++ if (SAVE_txpwrctrl != LCNPHY_TX_PWR_CTRL_OFF) ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); ++ else ++ wlc_lcnphy_set_tx_pwr_by_index(pi, SAVE_txpwrindex); ++} ++ ++s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode) ++{ ++ u16 tempsenseval1, tempsenseval2; ++ s16 avg = 0; ++ bool suspend = 0; ++ ++ if (mode == 1) { ++ suspend = ++ (0 == ++ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); ++ } ++ tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF; ++ tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF; ++ ++ if (tempsenseval1 > 255) ++ avg = (s16) (tempsenseval1 - 512); ++ else ++ avg = (s16) tempsenseval1; ++ ++ if (tempsenseval2 > 255) ++ avg += (s16) (tempsenseval2 - 512); ++ else ++ avg += (s16) tempsenseval2; ++ ++ avg /= 2; ++ ++ if (mode == 1) { ++ ++ mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14); ++ ++ udelay(100); ++ mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14); ++ ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++ } ++ return avg; ++} ++ ++u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode) ++{ ++ u16 tempsenseval1, tempsenseval2; ++ s32 avg = 0; ++ bool suspend = 0; ++ u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ if (mode == 1) { ++ suspend = ++ (0 == ++ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); ++ } ++ tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF; ++ tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF; ++ ++ if (tempsenseval1 > 255) ++ avg = (int)(tempsenseval1 - 512); ++ else ++ avg = (int)tempsenseval1; ++ ++ if (pi_lcn->lcnphy_tempsense_option == 1 || pi->hwpwrctrl_capable) { ++ if (tempsenseval2 > 255) ++ avg = (int)(avg - tempsenseval2 + 512); ++ else ++ avg = (int)(avg - tempsenseval2); ++ } else { ++ if (tempsenseval2 > 255) ++ avg = (int)(avg + tempsenseval2 - 512); ++ else ++ avg = (int)(avg + tempsenseval2); ++ avg = avg / 2; ++ } ++ if (avg < 0) ++ avg = avg + 512; ++ ++ if (pi_lcn->lcnphy_tempsense_option == 2) ++ avg = tempsenseval1; ++ ++ if (mode) ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); ++ ++ if (mode == 1) { ++ ++ mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14); ++ ++ udelay(100); ++ mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14); ++ ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++ } ++ return (u16) avg; ++} ++ ++s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode) ++{ ++ s32 degree = wlc_lcnphy_tempsense_new(pi, mode); ++ degree = ++ ((degree << ++ 10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1)) ++ / LCN_TEMPSENSE_DEN; ++ return (s8) degree; ++} ++ ++s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode) ++{ ++ u16 vbatsenseval; ++ s32 avg = 0; ++ bool suspend = 0; ++ ++ if (mode == 1) { ++ suspend = ++ (0 == ++ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE); ++ } ++ ++ vbatsenseval = read_phy_reg(pi, 0x475) & 0x1FF; ++ ++ if (vbatsenseval > 255) ++ avg = (s32) (vbatsenseval - 512); ++ else ++ avg = (s32) vbatsenseval; ++ ++ avg = (avg * LCN_VBAT_SCALE_NOM + ++ (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN; ++ ++ if (mode == 1) { ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++ } ++ return (s8) avg; ++} ++ ++static void wlc_lcnphy_afe_clk_init(struct brcms_phy *pi, u8 mode) ++{ ++ u8 phybw40; ++ phybw40 = CHSPEC_IS40(pi->radio_chanspec); ++ ++ mod_phy_reg(pi, 0x6d1, (0x1 << 7), (1) << 7); ++ ++ if (((mode == AFE_CLK_INIT_MODE_PAPD) && (phybw40 == 0)) || ++ (mode == AFE_CLK_INIT_MODE_TXRX2X)) ++ write_phy_reg(pi, 0x6d0, 0x7); ++ ++ wlc_lcnphy_toggle_afe_pwdn(pi); ++} ++ ++static void wlc_lcnphy_temp_adj(struct brcms_phy *pi) ++{ ++} ++ ++static void wlc_lcnphy_glacial_timer_based_cal(struct brcms_phy *pi) ++{ ++ bool suspend; ++ s8 index; ++ u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ suspend = ++ (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ wlc_lcnphy_deaf_mode(pi, true); ++ pi->phy_lastcal = pi->sh->now; ++ pi->phy_forcecal = false; ++ index = pi_lcn->lcnphy_current_index; ++ ++ wlc_lcnphy_txpwrtbl_iqlo_cal(pi); ++ ++ wlc_lcnphy_set_tx_pwr_by_index(pi, index); ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl); ++ wlc_lcnphy_deaf_mode(pi, false); ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++ ++} ++ ++static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi) ++{ ++ bool suspend, full_cal; ++ const struct lcnphy_rx_iqcomp *rx_iqcomp; ++ int rx_iqcomp_sz; ++ u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ s8 index; ++ struct phytbl_info tab; ++ s32 a1, b0, b1; ++ s32 tssi, pwr, maxtargetpwr, mintargetpwr; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ pi->phy_lastcal = pi->sh->now; ++ pi->phy_forcecal = false; ++ full_cal = ++ (pi_lcn->lcnphy_full_cal_channel != ++ CHSPEC_CHANNEL(pi->radio_chanspec)); ++ pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec); ++ index = pi_lcn->lcnphy_current_index; ++ ++ suspend = ++ (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) { ++ wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000); ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ } ++ ++ wlc_lcnphy_deaf_mode(pi, true); ++ ++ wlc_lcnphy_txpwrtbl_iqlo_cal(pi); ++ ++ rx_iqcomp = lcnphy_rx_iqcomp_table_rev0; ++ rx_iqcomp_sz = ARRAY_SIZE(lcnphy_rx_iqcomp_table_rev0); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) ++ wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 40); ++ else ++ wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 127); ++ ++ if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) { ++ ++ wlc_lcnphy_idle_tssi_est((struct brcms_phy_pub *) pi); ++ ++ b0 = pi->txpa_2g[0]; ++ b1 = pi->txpa_2g[1]; ++ a1 = pi->txpa_2g[2]; ++ maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1); ++ mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1); ++ ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_ptr = &pwr; ++ tab.tbl_len = 1; ++ tab.tbl_offset = 0; ++ for (tssi = 0; tssi < 128; tssi++) { ++ pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1); ++ pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr; ++ wlc_lcnphy_write_table(pi, &tab); ++ tab.tbl_offset++; ++ } ++ } ++ ++ wlc_lcnphy_set_tx_pwr_by_index(pi, index); ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl); ++ wlc_lcnphy_deaf_mode(pi, false); ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++} ++ ++void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode) ++{ ++ u16 temp_new; ++ int temp1, temp2, temp_diff; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ switch (mode) { ++ case PHY_PERICAL_CHAN: ++ break; ++ case PHY_FULLCAL: ++ wlc_lcnphy_periodic_cal(pi); ++ break; ++ case PHY_PERICAL_PHYINIT: ++ wlc_lcnphy_periodic_cal(pi); ++ break; ++ case PHY_PERICAL_WATCHDOG: ++ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { ++ temp_new = wlc_lcnphy_tempsense(pi, 0); ++ temp1 = LCNPHY_TEMPSENSE(temp_new); ++ temp2 = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_cal_temper); ++ temp_diff = temp1 - temp2; ++ if ((pi_lcn->lcnphy_cal_counter > 90) || ++ (temp_diff > 60) || (temp_diff < -60)) { ++ wlc_lcnphy_glacial_timer_based_cal(pi); ++ wlc_2064_vco_cal(pi); ++ pi_lcn->lcnphy_cal_temper = temp_new; ++ pi_lcn->lcnphy_cal_counter = 0; ++ } else ++ pi_lcn->lcnphy_cal_counter++; ++ } ++ break; ++ case LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL: ++ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) ++ wlc_lcnphy_tx_power_adjustment( ++ (struct brcms_phy_pub *) pi); ++ break; ++ } ++} ++ ++void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, s8 *cck_pwr) ++{ ++ s8 cck_offset; ++ u16 status; ++ status = (read_phy_reg(pi, 0x4ab)); ++ if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) && ++ (status & (0x1 << 15))) { ++ *ofdm_pwr = (s8) (((read_phy_reg(pi, 0x4ab) & (0x1ff << 0)) ++ >> 0) >> 1); ++ ++ if (wlc_phy_tpc_isenabled_lcnphy(pi)) ++ cck_offset = pi->tx_power_offset[TXP_FIRST_CCK]; ++ else ++ cck_offset = 0; ++ ++ *cck_pwr = *ofdm_pwr + cck_offset; ++ } else { ++ *cck_pwr = 0; ++ *ofdm_pwr = 0; ++ } ++} ++ ++void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi) ++{ ++ return; ++ ++} ++ ++void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi) ++{ ++ s8 index; ++ u16 index2; ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && ++ SAVE_txpwrctrl) { ++ index = wlc_lcnphy_tempcompensated_txpwrctrl(pi); ++ index2 = (u16) (index * 2); ++ mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0); ++ ++ pi_lcn->lcnphy_current_index = ++ (s8)((read_phy_reg(pi, 0x4a9) & 0xFF) / 2); ++ } ++} ++ ++static void ++wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi, ++ const struct lcnphy_tx_gain_tbl_entry *gain_table) ++{ ++ u32 j; ++ struct phytbl_info tab; ++ u32 val; ++ u16 pa_gain; ++ u16 gm_gain; ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) ++ pa_gain = 0x70; ++ else ++ pa_gain = 0x70; ++ ++ if (pi->sh->boardflags & BFL_FEM) ++ pa_gain = 0x10; ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_len = 1; ++ tab.tbl_ptr = &val; ++ ++ for (j = 0; j < 128; j++) { ++ gm_gain = gain_table[j].gm; ++ val = (((u32) pa_gain << 24) | ++ (gain_table[j].pad << 16) | ++ (gain_table[j].pga << 8) | gm_gain); ++ ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + j; ++ wlc_lcnphy_write_table(pi, &tab); ++ ++ val = (gain_table[j].dac << 28) | (gain_table[j].bb_mult << 20); ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + j; ++ wlc_lcnphy_write_table(pi, &tab); ++ } ++} ++ ++static void wlc_lcnphy_load_rfpower(struct brcms_phy *pi) ++{ ++ struct phytbl_info tab; ++ u32 val, bbmult, rfgain; ++ u8 index; ++ u8 scale_factor = 1; ++ s16 temp, temp1, temp2, qQ, qQ1, qQ2, shift; ++ ++ tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; ++ tab.tbl_width = 32; ++ tab.tbl_len = 1; ++ ++ for (index = 0; index < 128; index++) { ++ tab.tbl_ptr = &bbmult; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index; ++ wlc_lcnphy_read_table(pi, &tab); ++ bbmult = bbmult >> 20; ++ ++ tab.tbl_ptr = &rfgain; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ qm_log10((s32) (bbmult), 0, &temp1, &qQ1); ++ qm_log10((s32) (1 << 6), 0, &temp2, &qQ2); ++ ++ if (qQ1 < qQ2) { ++ temp2 = qm_shr16(temp2, qQ2 - qQ1); ++ qQ = qQ1; ++ } else { ++ temp1 = qm_shr16(temp1, qQ1 - qQ2); ++ qQ = qQ2; ++ } ++ temp = qm_sub16(temp1, temp2); ++ ++ if (qQ >= 4) ++ shift = qQ - 4; ++ else ++ shift = 4 - qQ; ++ ++ val = (((index << shift) + (5 * temp) + ++ (1 << (scale_factor + shift - 3))) >> (scale_factor + ++ shift - 2)); ++ ++ tab.tbl_ptr = &val; ++ tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index; ++ wlc_lcnphy_write_table(pi, &tab); ++ } ++} ++ ++static void wlc_lcnphy_bu_tweaks(struct brcms_phy *pi) ++{ ++ or_phy_reg(pi, 0x805, 0x1); ++ ++ mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0); ++ ++ mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0); ++ ++ write_phy_reg(pi, 0x414, 0x1e10); ++ write_phy_reg(pi, 0x415, 0x0640); ++ ++ mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8); ++ ++ or_phy_reg(pi, 0x44a, 0x44); ++ write_phy_reg(pi, 0x44a, 0x80); ++ mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0); ++ ++ mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0); ++ ++ if (!(pi->sh->boardrev < 0x1204)) ++ mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0); ++ ++ write_phy_reg(pi, 0x7d6, 0x0902); ++ mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0); ++ ++ mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) { ++ mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0); ++ ++ mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0); ++ ++ mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0); ++ ++ mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0); ++ ++ mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2); ++ ++ mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4); ++ mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0); ++ mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90); ++ mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2); ++ mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0); ++ ++ mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2); ++ ++ wlc_lcnphy_clear_tx_power_offsets(pi); ++ mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6); ++ ++ } ++} ++ ++static void wlc_lcnphy_rcal(struct brcms_phy *pi) ++{ ++ u8 rcal_value; ++ ++ and_radio_reg(pi, RADIO_2064_REG05B, 0xfD); ++ ++ or_radio_reg(pi, RADIO_2064_REG004, 0x40); ++ or_radio_reg(pi, RADIO_2064_REG120, 0x10); ++ ++ or_radio_reg(pi, RADIO_2064_REG078, 0x80); ++ or_radio_reg(pi, RADIO_2064_REG129, 0x02); ++ ++ or_radio_reg(pi, RADIO_2064_REG057, 0x01); ++ ++ or_radio_reg(pi, RADIO_2064_REG05B, 0x02); ++ mdelay(5); ++ SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000); ++ ++ if (wlc_radio_2064_rcal_done(pi)) { ++ rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C); ++ rcal_value = rcal_value & 0x1f; ++ } ++ ++ and_radio_reg(pi, RADIO_2064_REG05B, 0xfD); ++ ++ and_radio_reg(pi, RADIO_2064_REG057, 0xFE); ++} ++ ++static void wlc_lcnphy_rc_cal(struct brcms_phy *pi) ++{ ++ u8 dflt_rc_cal_val; ++ u16 flt_val; ++ ++ dflt_rc_cal_val = 7; ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) ++ dflt_rc_cal_val = 11; ++ flt_val = ++ (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) | ++ (dflt_rc_cal_val); ++ write_phy_reg(pi, 0x933, flt_val); ++ write_phy_reg(pi, 0x934, flt_val); ++ write_phy_reg(pi, 0x935, flt_val); ++ write_phy_reg(pi, 0x936, flt_val); ++ write_phy_reg(pi, 0x937, (flt_val & 0x1FF)); ++ ++ return; ++} ++ ++static void wlc_radio_2064_init(struct brcms_phy *pi) ++{ ++ u32 i; ++ const struct lcnphy_radio_regs *lcnphyregs = NULL; ++ ++ lcnphyregs = lcnphy_radio_regs_2064; ++ ++ for (i = 0; lcnphyregs[i].address != 0xffff; i++) ++ if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a) ++ write_radio_reg(pi, ++ ((lcnphyregs[i].address & 0x3fff) | ++ RADIO_DEFAULT_CORE), ++ (u16) lcnphyregs[i].init_a); ++ else if (lcnphyregs[i].do_init_g) ++ write_radio_reg(pi, ++ ((lcnphyregs[i].address & 0x3fff) | ++ RADIO_DEFAULT_CORE), ++ (u16) lcnphyregs[i].init_g); ++ ++ write_radio_reg(pi, RADIO_2064_REG032, 0x62); ++ write_radio_reg(pi, RADIO_2064_REG033, 0x19); ++ ++ write_radio_reg(pi, RADIO_2064_REG090, 0x10); ++ ++ write_radio_reg(pi, RADIO_2064_REG010, 0x00); ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 1)) { ++ ++ write_radio_reg(pi, RADIO_2064_REG060, 0x7f); ++ write_radio_reg(pi, RADIO_2064_REG061, 0x72); ++ write_radio_reg(pi, RADIO_2064_REG062, 0x7f); ++ } ++ ++ write_radio_reg(pi, RADIO_2064_REG01D, 0x02); ++ write_radio_reg(pi, RADIO_2064_REG01E, 0x06); ++ ++ mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0); ++ ++ mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3); ++ ++ mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6); ++ ++ mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9); ++ ++ mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12); ++ ++ write_phy_reg(pi, 0x4ea, 0x4688); ++ ++ mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0); ++ ++ mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6); ++ ++ mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0); ++ ++ wlc_lcnphy_set_tx_locc(pi, 0); ++ ++ wlc_lcnphy_rcal(pi); ++ ++ wlc_lcnphy_rc_cal(pi); ++} ++ ++static void wlc_lcnphy_radio_init(struct brcms_phy *pi) ++{ ++ wlc_radio_2064_init(pi); ++} ++ ++static void wlc_lcnphy_tbl_init(struct brcms_phy *pi) ++{ ++ uint idx; ++ u8 phybw40; ++ struct phytbl_info tab; ++ u32 val; ++ ++ phybw40 = CHSPEC_IS40(pi->radio_chanspec); ++ ++ for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++) ++ wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]); ++ ++ if (pi->sh->boardflags & BFL_FEM_BT) { ++ tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; ++ tab.tbl_width = 16; ++ tab.tbl_ptr = &val; ++ tab.tbl_len = 1; ++ val = 100; ++ tab.tbl_offset = 4; ++ wlc_lcnphy_write_table(pi, &tab); ++ } ++ ++ tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; ++ tab.tbl_width = 16; ++ tab.tbl_ptr = &val; ++ tab.tbl_len = 1; ++ ++ val = 114; ++ tab.tbl_offset = 0; ++ wlc_lcnphy_write_table(pi, &tab); ++ ++ val = 130; ++ tab.tbl_offset = 1; ++ wlc_lcnphy_write_table(pi, &tab); ++ ++ val = 6; ++ tab.tbl_offset = 8; ++ wlc_lcnphy_write_table(pi, &tab); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (pi->sh->boardflags & BFL_FEM) ++ wlc_lcnphy_load_tx_gain_table( ++ pi, ++ dot11lcnphy_2GHz_extPA_gaintable_rev0); ++ else ++ wlc_lcnphy_load_tx_gain_table( ++ pi, ++ dot11lcnphy_2GHz_gaintable_rev0); ++ } ++ ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { ++ const struct phytbl_info *tb; ++ int l; ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ l = dot11lcnphytbl_rx_gain_info_2G_rev2_sz; ++ if (pi->sh->boardflags & BFL_EXTLNA) ++ tb = dot11lcnphytbl_rx_gain_info_extlna_2G_rev2; ++ else ++ tb = dot11lcnphytbl_rx_gain_info_2G_rev2; ++ } else { ++ l = dot11lcnphytbl_rx_gain_info_5G_rev2_sz; ++ if (pi->sh->boardflags & BFL_EXTLNA_5GHz) ++ tb = dot11lcnphytbl_rx_gain_info_extlna_5G_rev2; ++ else ++ tb = dot11lcnphytbl_rx_gain_info_5G_rev2; ++ } ++ ++ for (idx = 0; idx < l; idx++) ++ wlc_lcnphy_write_table(pi, &tb[idx]); ++ } ++ ++ if ((pi->sh->boardflags & BFL_FEM) ++ && !(pi->sh->boardflags & BFL_FEM_BT)) ++ wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa); ++ else if (pi->sh->boardflags & BFL_FEM_BT) { ++ if (pi->sh->boardrev < 0x1250) ++ wlc_lcnphy_write_table( ++ pi, ++ &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa); ++ else ++ wlc_lcnphy_write_table( ++ pi, ++ &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250); ++ } else ++ wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313); ++ ++ wlc_lcnphy_load_rfpower(pi); ++ ++ wlc_lcnphy_clear_papd_comptable(pi); ++} ++ ++static void wlc_lcnphy_rev0_baseband_init(struct brcms_phy *pi) ++{ ++ u16 afectrl1; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ write_radio_reg(pi, RADIO_2064_REG11C, 0x0); ++ ++ write_phy_reg(pi, 0x43b, 0x0); ++ write_phy_reg(pi, 0x43c, 0x0); ++ write_phy_reg(pi, 0x44c, 0x0); ++ write_phy_reg(pi, 0x4e6, 0x0); ++ write_phy_reg(pi, 0x4f9, 0x0); ++ write_phy_reg(pi, 0x4b0, 0x0); ++ write_phy_reg(pi, 0x938, 0x0); ++ write_phy_reg(pi, 0x4b0, 0x0); ++ write_phy_reg(pi, 0x44e, 0); ++ ++ or_phy_reg(pi, 0x567, 0x03); ++ ++ or_phy_reg(pi, 0x44a, 0x44); ++ write_phy_reg(pi, 0x44a, 0x80); ++ ++ if (!(pi->sh->boardflags & BFL_FEM)) ++ wlc_lcnphy_set_tx_pwr_by_index(pi, 52); ++ ++ if (0) { ++ afectrl1 = 0; ++ afectrl1 = (u16) ((pi_lcn->lcnphy_rssi_vf) | ++ (pi_lcn->lcnphy_rssi_vc << 4) | ++ (pi_lcn->lcnphy_rssi_gs << 10)); ++ write_phy_reg(pi, 0x43e, afectrl1); ++ } ++ ++ mod_phy_reg(pi, 0x634, (0xff << 0), 0xC << 0); ++ if (pi->sh->boardflags & BFL_FEM) { ++ mod_phy_reg(pi, 0x634, (0xff << 0), 0xA << 0); ++ ++ write_phy_reg(pi, 0x910, 0x1); ++ } ++ ++ mod_phy_reg(pi, 0x448, (0x3 << 8), 1 << 8); ++ mod_phy_reg(pi, 0x608, (0xff << 0), 0x17 << 0); ++ mod_phy_reg(pi, 0x604, (0x7ff << 0), 0x3EA << 0); ++ ++} ++ ++static void wlc_lcnphy_rev2_baseband_init(struct brcms_phy *pi) ++{ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ mod_phy_reg(pi, 0x416, (0xff << 0), 80 << 0); ++ mod_phy_reg(pi, 0x416, (0xff << 8), 80 << 8); ++ } ++} ++ ++static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi) ++{ ++ s16 temp; ++ struct phytbl_info tab; ++ u32 tableBuffer[2]; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ temp = (s16) read_phy_reg(pi, 0x4df); ++ pi_lcn->lcnphy_ofdmgainidxtableoffset = (temp & (0xff << 0)) >> 0; ++ ++ if (pi_lcn->lcnphy_ofdmgainidxtableoffset > 127) ++ pi_lcn->lcnphy_ofdmgainidxtableoffset -= 256; ++ ++ pi_lcn->lcnphy_dsssgainidxtableoffset = (temp & (0xff << 8)) >> 8; ++ ++ if (pi_lcn->lcnphy_dsssgainidxtableoffset > 127) ++ pi_lcn->lcnphy_dsssgainidxtableoffset -= 256; ++ ++ tab.tbl_ptr = tableBuffer; ++ tab.tbl_len = 2; ++ tab.tbl_id = 17; ++ tab.tbl_offset = 59; ++ tab.tbl_width = 32; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ if (tableBuffer[0] > 63) ++ tableBuffer[0] -= 128; ++ pi_lcn->lcnphy_tr_R_gain_val = tableBuffer[0]; ++ ++ if (tableBuffer[1] > 63) ++ tableBuffer[1] -= 128; ++ pi_lcn->lcnphy_tr_T_gain_val = tableBuffer[1]; ++ ++ temp = (s16) (read_phy_reg(pi, 0x434) & (0xff << 0)); ++ if (temp > 127) ++ temp -= 256; ++ pi_lcn->lcnphy_input_pwr_offset_db = (s8) temp; ++ ++ pi_lcn->lcnphy_Med_Low_Gain_db = ++ (read_phy_reg(pi, 0x424) & (0xff << 8)) >> 8; ++ pi_lcn->lcnphy_Very_Low_Gain_db = ++ (read_phy_reg(pi, 0x425) & (0xff << 0)) >> 0; ++ ++ tab.tbl_ptr = tableBuffer; ++ tab.tbl_len = 2; ++ tab.tbl_id = LCNPHY_TBL_ID_GAIN_IDX; ++ tab.tbl_offset = 28; ++ tab.tbl_width = 32; ++ wlc_lcnphy_read_table(pi, &tab); ++ ++ pi_lcn->lcnphy_gain_idx_14_lowword = tableBuffer[0]; ++ pi_lcn->lcnphy_gain_idx_14_hiword = tableBuffer[1]; ++ ++} ++ ++static void wlc_lcnphy_baseband_init(struct brcms_phy *pi) ++{ ++ ++ wlc_lcnphy_tbl_init(pi); ++ wlc_lcnphy_rev0_baseband_init(pi); ++ if (LCNREV_IS(pi->pubpi.phy_rev, 2)) ++ wlc_lcnphy_rev2_baseband_init(pi); ++ wlc_lcnphy_bu_tweaks(pi); ++} ++ ++void wlc_phy_init_lcnphy(struct brcms_phy *pi) ++{ ++ u8 phybw40; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ phybw40 = CHSPEC_IS40(pi->radio_chanspec); ++ ++ pi_lcn->lcnphy_cal_counter = 0; ++ pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense; ++ ++ or_phy_reg(pi, 0x44a, 0x80); ++ and_phy_reg(pi, 0x44a, 0x7f); ++ ++ wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X); ++ ++ write_phy_reg(pi, 0x60a, 160); ++ ++ write_phy_reg(pi, 0x46a, 25); ++ ++ wlc_lcnphy_baseband_init(pi); ++ ++ wlc_lcnphy_radio_init(pi); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ wlc_lcnphy_tx_pwr_ctrl_init((struct brcms_phy_pub *) pi); ++ ++ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec); ++ ++ si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9); ++ ++ si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD); ++ ++ if ((pi->sh->boardflags & BFL_FEM) ++ && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) ++ wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR); ++ ++ wlc_lcnphy_agc_temp_init(pi); ++ ++ wlc_lcnphy_temp_adj(pi); ++ ++ mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14); ++ ++ udelay(100); ++ mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14); ++ ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW); ++ pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT; ++ wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT); ++} ++ ++static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) ++{ ++ s8 txpwr = 0; ++ int i; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ struct phy_shim_info *shim = pi->sh->physhim; ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ u16 cckpo = 0; ++ u32 offset_ofdm, offset_mcs; ++ ++ pi_lcn->lcnphy_tr_isolation_mid = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_TRISO2G); ++ ++ pi_lcn->lcnphy_rx_power_offset = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_RXPO2G); ++ ++ pi->txpa_2g[0] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B0); ++ pi->txpa_2g[1] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B1); ++ pi->txpa_2g[2] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B2); ++ ++ pi_lcn->lcnphy_rssi_vf = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMF2G); ++ pi_lcn->lcnphy_rssi_vc = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMC2G); ++ pi_lcn->lcnphy_rssi_gs = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISAV2G); ++ ++ pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf; ++ pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc; ++ pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs; ++ ++ pi_lcn->lcnphy_rssi_vf_hightemp = pi_lcn->lcnphy_rssi_vf; ++ pi_lcn->lcnphy_rssi_vc_hightemp = pi_lcn->lcnphy_rssi_vc; ++ pi_lcn->lcnphy_rssi_gs_hightemp = pi_lcn->lcnphy_rssi_gs; ++ ++ txpwr = (s8)wlapi_getintvar(shim, BRCMS_SROM_MAXP2GA0); ++ pi->tx_srom_max_2g = txpwr; ++ ++ for (i = 0; i < PWRTBL_NUM_COEFF; i++) { ++ pi->txpa_2g_low_temp[i] = pi->txpa_2g[i]; ++ pi->txpa_2g_high_temp[i] = pi->txpa_2g[i]; ++ } ++ ++ cckpo = (u16)wlapi_getintvar(shim, BRCMS_SROM_CCK2GPO); ++ offset_ofdm = (u32)wlapi_getintvar(shim, BRCMS_SROM_OFDM2GPO); ++ if (cckpo) { ++ uint max_pwr_chan = txpwr; ++ ++ for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) { ++ pi->tx_srom_max_rate_2g[i] = ++ max_pwr_chan - ((cckpo & 0xf) * 2); ++ cckpo >>= 4; ++ } ++ ++ for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) { ++ pi->tx_srom_max_rate_2g[i] = ++ max_pwr_chan - ++ ((offset_ofdm & 0xf) * 2); ++ offset_ofdm >>= 4; ++ } ++ } else { ++ u8 opo = 0; ++ ++ opo = (u8)wlapi_getintvar(shim, BRCMS_SROM_OPO); ++ ++ for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) ++ pi->tx_srom_max_rate_2g[i] = txpwr; ++ ++ for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) { ++ pi->tx_srom_max_rate_2g[i] = txpwr - ++ ((offset_ofdm & 0xf) * 2); ++ offset_ofdm >>= 4; ++ } ++ offset_mcs = ++ wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO1) << 16; ++ offset_mcs |= ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO0); ++ pi_lcn->lcnphy_mcs20_po = offset_mcs; ++ for (i = TXP_FIRST_SISO_MCS_20; ++ i <= TXP_LAST_SISO_MCS_20; i++) { ++ pi->tx_srom_max_rate_2g[i] = ++ txpwr - ((offset_mcs & 0xf) * 2); ++ offset_mcs >>= 4; ++ } ++ } ++ ++ pi_lcn->lcnphy_rawtempsense = ++ (u16)wlapi_getintvar(shim, BRCMS_SROM_RAWTEMPSENSE); ++ pi_lcn->lcnphy_measPower = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_MEASPOWER); ++ pi_lcn->lcnphy_tempsense_slope = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_SLOPE); ++ pi_lcn->lcnphy_hw_iqcal_en = ++ (bool)wlapi_getintvar(shim, BRCMS_SROM_HW_IQCAL_EN); ++ pi_lcn->lcnphy_iqcal_swp_dis = ++ (bool)wlapi_getintvar(shim, BRCMS_SROM_IQCAL_SWP_DIS); ++ pi_lcn->lcnphy_tempcorrx = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPCORRX); ++ pi_lcn->lcnphy_tempsense_option = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_OPTION); ++ pi_lcn->lcnphy_freqoffset_corr = ++ (u8)wlapi_getintvar(shim, BRCMS_SROM_FREQOFFSET_CORR); ++ if ((u8)wlapi_getintvar(shim, BRCMS_SROM_AA2G) > 1) ++ wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi, ++ (u8) wlapi_getintvar(shim, BRCMS_SROM_AA2G)); ++ } ++ pi_lcn->lcnphy_cck_dig_filt_type = -1; ++ ++ return true; ++} ++ ++void wlc_2064_vco_cal(struct brcms_phy *pi) ++{ ++ u8 calnrst; ++ ++ mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 1 << 3); ++ calnrst = (u8) read_radio_reg(pi, RADIO_2064_REG056) & 0xf8; ++ write_radio_reg(pi, RADIO_2064_REG056, calnrst); ++ udelay(1); ++ write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x03); ++ udelay(1); ++ write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x07); ++ udelay(300); ++ mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 0); ++} ++ ++bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi) ++{ ++ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) ++ return 0; ++ else ++ return (LCNPHY_TX_PWR_CTRL_HW == ++ wlc_lcnphy_get_tx_pwr_ctrl((pi))); ++} ++ ++void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi) ++{ ++ u16 pwr_ctrl; ++ if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { ++ wlc_lcnphy_calib_modes(pi, LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL); ++ } else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) { ++ pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); ++ wlc_lcnphy_txpower_recalc_target(pi); ++ wlc_lcnphy_set_tx_pwr_ctrl(pi, pwr_ctrl); ++ } ++} ++ ++void wlc_phy_detach_lcnphy(struct brcms_phy *pi) ++{ ++ kfree(pi->u.pi_lcnphy); ++} ++ ++bool wlc_phy_attach_lcnphy(struct brcms_phy *pi) ++{ ++ struct brcms_phy_lcnphy *pi_lcn; ++ ++ pi->u.pi_lcnphy = kzalloc(sizeof(struct brcms_phy_lcnphy), GFP_ATOMIC); ++ if (pi->u.pi_lcnphy == NULL) ++ return false; ++ ++ pi_lcn = pi->u.pi_lcnphy; ++ ++ if (0 == (pi->sh->boardflags & BFL_NOPA)) { ++ pi->hwpwrctrl = true; ++ pi->hwpwrctrl_capable = true; ++ } ++ ++ pi->xtalfreq = si_pmu_alp_clock(pi->sh->sih); ++ pi_lcn->lcnphy_papd_rxGnCtrl_init = 0; ++ ++ pi->pi_fptr.init = wlc_phy_init_lcnphy; ++ pi->pi_fptr.calinit = wlc_phy_cal_init_lcnphy; ++ pi->pi_fptr.chanset = wlc_phy_chanspec_set_lcnphy; ++ pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_lcnphy; ++ pi->pi_fptr.txiqccget = wlc_lcnphy_get_tx_iqcc; ++ pi->pi_fptr.txiqccset = wlc_lcnphy_set_tx_iqcc; ++ pi->pi_fptr.txloccget = wlc_lcnphy_get_tx_locc; ++ pi->pi_fptr.radioloftget = wlc_lcnphy_get_radio_loft; ++ pi->pi_fptr.detach = wlc_phy_detach_lcnphy; ++ ++ if (!wlc_phy_txpwr_srom_read_lcnphy(pi)) ++ return false; ++ ++ if ((pi->sh->boardflags & BFL_FEM) && ++ (LCNREV_IS(pi->pubpi.phy_rev, 1))) { ++ if (pi_lcn->lcnphy_tempsense_option == 3) { ++ pi->hwpwrctrl = true; ++ pi->hwpwrctrl_capable = true; ++ pi->temppwrctrl_capable = false; ++ } else { ++ pi->hwpwrctrl = false; ++ pi->hwpwrctrl_capable = false; ++ pi->temppwrctrl_capable = true; ++ } ++ } ++ ++ return true; ++} ++ ++static void wlc_lcnphy_set_rx_gain(struct brcms_phy *pi, u32 gain) ++{ ++ u16 trsw, ext_lna, lna1, lna2, tia, biq0, biq1, gain0_15, gain16_19; ++ ++ trsw = (gain & ((u32) 1 << 28)) ? 0 : 1; ++ ext_lna = (u16) (gain >> 29) & 0x01; ++ lna1 = (u16) (gain >> 0) & 0x0f; ++ lna2 = (u16) (gain >> 4) & 0x0f; ++ tia = (u16) (gain >> 8) & 0xf; ++ biq0 = (u16) (gain >> 12) & 0xf; ++ biq1 = (u16) (gain >> 16) & 0xf; ++ ++ gain0_15 = (u16) ((lna1 & 0x3) | ((lna1 & 0x3) << 2) | ++ ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) | ++ ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12)); ++ gain16_19 = biq1; ++ ++ mod_phy_reg(pi, 0x44d, (0x1 << 0), trsw << 0); ++ mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9); ++ mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10); ++ mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0); ++ mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11); ++ mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3); ++ } ++ wlc_lcnphy_rx_gain_override_enable(pi, true); ++} ++ ++static u32 wlc_lcnphy_get_receive_power(struct brcms_phy *pi, s32 *gain_index) ++{ ++ u32 received_power = 0; ++ s32 max_index = 0; ++ u32 gain_code = 0; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ max_index = 36; ++ if (*gain_index >= 0) ++ gain_code = lcnphy_23bitgaincode_table[*gain_index]; ++ ++ if (-1 == *gain_index) { ++ *gain_index = 0; ++ while ((*gain_index <= (s32) max_index) ++ && (received_power < 700)) { ++ wlc_lcnphy_set_rx_gain(pi, ++ lcnphy_23bitgaincode_table ++ [*gain_index]); ++ received_power = ++ wlc_lcnphy_measure_digital_power( ++ pi, ++ pi_lcn-> ++ lcnphy_noise_samples); ++ (*gain_index)++; ++ } ++ (*gain_index)--; ++ } else { ++ wlc_lcnphy_set_rx_gain(pi, gain_code); ++ received_power = ++ wlc_lcnphy_measure_digital_power(pi, ++ pi_lcn-> ++ lcnphy_noise_samples); ++ } ++ ++ return received_power; ++} ++ ++s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index) ++{ ++ s32 gain = 0; ++ s32 nominal_power_db; ++ s32 log_val, gain_mismatch, desired_gain, input_power_offset_db, ++ input_power_db; ++ s32 received_power, temperature; ++ u32 power; ++ u32 msb1, msb2, val1, val2, diff1, diff2; ++ uint freq; ++ struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; ++ ++ received_power = wlc_lcnphy_get_receive_power(pi, &gain_index); ++ ++ gain = lcnphy_gain_table[gain_index]; ++ ++ nominal_power_db = read_phy_reg(pi, 0x425) >> 8; ++ ++ power = (received_power * 16); ++ msb1 = ffs(power) - 1; ++ msb2 = msb1 + 1; ++ val1 = 1 << msb1; ++ val2 = 1 << msb2; ++ diff1 = (power - val1); ++ diff2 = (val2 - power); ++ if (diff1 < diff2) ++ log_val = msb1; ++ else ++ log_val = msb2; ++ ++ log_val = log_val * 3; ++ ++ gain_mismatch = (nominal_power_db / 2) - (log_val); ++ ++ desired_gain = gain + gain_mismatch; ++ ++ input_power_offset_db = read_phy_reg(pi, 0x434) & 0xFF; ++ ++ if (input_power_offset_db > 127) ++ input_power_offset_db -= 256; ++ ++ input_power_db = input_power_offset_db - desired_gain; ++ ++ input_power_db = ++ input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index]; ++ ++ freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(pi->radio_chanspec)); ++ if ((freq > 2427) && (freq <= 2467)) ++ input_power_db = input_power_db - 1; ++ ++ temperature = pi_lcn->lcnphy_lastsensed_temperature; ++ ++ if ((temperature - 15) < -30) ++ input_power_db = ++ input_power_db + ++ (((temperature - 10 - 25) * 286) >> 12) - ++ 7; ++ else if ((temperature - 15) < 4) ++ input_power_db = ++ input_power_db + ++ (((temperature - 10 - 25) * 286) >> 12) - ++ 3; ++ else ++ input_power_db = input_power_db + ++ (((temperature - 10 - 25) * 286) >> 12); ++ ++ wlc_lcnphy_rx_gain_override_enable(pi, 0); ++ ++ return input_power_db; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.h.orig 2011-11-09 13:46:58.258800470 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.h 2011-11-09 13:47:17.012566015 -0500 +@@ -0,0 +1,121 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_PHY_LCN_H_ ++#define _BRCM_PHY_LCN_H_ ++ ++#include ++ ++struct brcms_phy_lcnphy { ++ int lcnphy_txrf_sp_9_override; ++ u8 lcnphy_full_cal_channel; ++ u8 lcnphy_cal_counter; ++ u16 lcnphy_cal_temper; ++ bool lcnphy_recal; ++ ++ u8 lcnphy_rc_cap; ++ u32 lcnphy_mcs20_po; ++ ++ u8 lcnphy_tr_isolation_mid; ++ u8 lcnphy_tr_isolation_low; ++ u8 lcnphy_tr_isolation_hi; ++ ++ u8 lcnphy_bx_arch; ++ u8 lcnphy_rx_power_offset; ++ u8 lcnphy_rssi_vf; ++ u8 lcnphy_rssi_vc; ++ u8 lcnphy_rssi_gs; ++ u8 lcnphy_tssi_val; ++ u8 lcnphy_rssi_vf_lowtemp; ++ u8 lcnphy_rssi_vc_lowtemp; ++ u8 lcnphy_rssi_gs_lowtemp; ++ ++ u8 lcnphy_rssi_vf_hightemp; ++ u8 lcnphy_rssi_vc_hightemp; ++ u8 lcnphy_rssi_gs_hightemp; ++ ++ s16 lcnphy_pa0b0; ++ s16 lcnphy_pa0b1; ++ s16 lcnphy_pa0b2; ++ ++ u16 lcnphy_rawtempsense; ++ u8 lcnphy_measPower; ++ u8 lcnphy_tempsense_slope; ++ u8 lcnphy_freqoffset_corr; ++ u8 lcnphy_tempsense_option; ++ u8 lcnphy_tempcorrx; ++ bool lcnphy_iqcal_swp_dis; ++ bool lcnphy_hw_iqcal_en; ++ uint lcnphy_bandedge_corr; ++ bool lcnphy_spurmod; ++ u16 lcnphy_tssi_tx_cnt; ++ u16 lcnphy_tssi_idx; ++ u16 lcnphy_tssi_npt; ++ ++ u16 lcnphy_target_tx_freq; ++ s8 lcnphy_tx_power_idx_override; ++ u16 lcnphy_noise_samples; ++ ++ u32 lcnphy_papdRxGnIdx; ++ u32 lcnphy_papd_rxGnCtrl_init; ++ ++ u32 lcnphy_gain_idx_14_lowword; ++ u32 lcnphy_gain_idx_14_hiword; ++ u32 lcnphy_gain_idx_27_lowword; ++ u32 lcnphy_gain_idx_27_hiword; ++ s16 lcnphy_ofdmgainidxtableoffset; ++ s16 lcnphy_dsssgainidxtableoffset; ++ u32 lcnphy_tr_R_gain_val; ++ u32 lcnphy_tr_T_gain_val; ++ s8 lcnphy_input_pwr_offset_db; ++ u16 lcnphy_Med_Low_Gain_db; ++ u16 lcnphy_Very_Low_Gain_db; ++ s8 lcnphy_lastsensed_temperature; ++ s8 lcnphy_pkteng_rssi_slope; ++ u8 lcnphy_saved_tx_user_target[TXP_NUM_RATES]; ++ u8 lcnphy_volt_winner; ++ u8 lcnphy_volt_low; ++ u8 lcnphy_54_48_36_24mbps_backoff; ++ u8 lcnphy_11n_backoff; ++ u8 lcnphy_lowerofdm; ++ u8 lcnphy_cck; ++ u8 lcnphy_psat_2pt3_detected; ++ s32 lcnphy_lowest_Re_div_Im; ++ s8 lcnphy_final_papd_cal_idx; ++ u16 lcnphy_extstxctrl4; ++ u16 lcnphy_extstxctrl0; ++ u16 lcnphy_extstxctrl1; ++ s16 lcnphy_cck_dig_filt_type; ++ s16 lcnphy_ofdm_dig_filt_type; ++ struct lcnphy_cal_results lcnphy_cal_results; ++ ++ u8 lcnphy_psat_pwr; ++ u8 lcnphy_psat_indx; ++ s32 lcnphy_min_phase; ++ u8 lcnphy_final_idx; ++ u8 lcnphy_start_idx; ++ u8 lcnphy_current_index; ++ u16 lcnphy_logen_buf_1; ++ u16 lcnphy_local_ovr_2; ++ u16 lcnphy_local_oval_6; ++ u16 lcnphy_local_oval_5; ++ u16 lcnphy_logen_mixer_1; ++ ++ u8 lcnphy_aci_stat; ++ uint lcnphy_aci_start_time; ++ s8 lcnphy_tx_power_offset[TXP_NUM_RATES]; ++}; ++#endif /* _BRCM_PHY_LCN_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c.orig 2011-11-09 13:46:58.275800257 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c 2011-11-09 13:47:17.032565765 -0500 +@@ -0,0 +1,28876 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "phy_int.h" ++#include "phy_hal.h" ++#include "phy_radio.h" ++#include "phyreg_n.h" ++#include "phytbl_n.h" ++ ++#define READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name) \ ++ read_radio_reg(pi, radio_type##_##jspace##_##reg_name | \ ++ ((core == PHY_CORE_0) ? \ ++ radio_type##_##jspace##0 : \ ++ radio_type##_##jspace##1)) ++ ++#define WRITE_RADIO_REG2(pi, radio_type, jspace, core, reg_name, value) \ ++ write_radio_reg(pi, radio_type##_##jspace##_##reg_name | \ ++ ((core == PHY_CORE_0) ? \ ++ radio_type##_##jspace##0 : \ ++ radio_type##_##jspace##1), value) ++ ++#define WRITE_RADIO_SYN(pi, radio_type, reg_name, value) \ ++ write_radio_reg(pi, radio_type##_##SYN##_##reg_name, value) ++ ++#define READ_RADIO_REG3(pi, radio_type, jspace, core, reg_name) \ ++ read_radio_reg(pi, ((core == PHY_CORE_0) ? \ ++ radio_type##_##jspace##0##_##reg_name : \ ++ radio_type##_##jspace##1##_##reg_name)) ++ ++#define WRITE_RADIO_REG3(pi, radio_type, jspace, core, reg_name, value) \ ++ write_radio_reg(pi, ((core == PHY_CORE_0) ? \ ++ radio_type##_##jspace##0##_##reg_name : \ ++ radio_type##_##jspace##1##_##reg_name), \ ++ value) ++ ++#define READ_RADIO_REG4(pi, radio_type, jspace, core, reg_name) \ ++ read_radio_reg(pi, ((core == PHY_CORE_0) ? \ ++ radio_type##_##reg_name##_##jspace##0 : \ ++ radio_type##_##reg_name##_##jspace##1)) ++ ++#define WRITE_RADIO_REG4(pi, radio_type, jspace, core, reg_name, value) \ ++ write_radio_reg(pi, ((core == PHY_CORE_0) ? \ ++ radio_type##_##reg_name##_##jspace##0 : \ ++ radio_type##_##reg_name##_##jspace##1), \ ++ value) ++ ++#define NPHY_ACI_MAX_UNDETECT_WINDOW_SZ 40 ++#define NPHY_ACI_CHANNEL_DELTA 5 ++#define NPHY_ACI_CHANNEL_SKIP 4 ++#define NPHY_ACI_40MHZ_CHANNEL_DELTA 6 ++#define NPHY_ACI_40MHZ_CHANNEL_SKIP 5 ++#define NPHY_ACI_40MHZ_CHANNEL_DELTA_GE_REV3 6 ++#define NPHY_ACI_40MHZ_CHANNEL_SKIP_GE_REV3 5 ++#define NPHY_ACI_CHANNEL_DELTA_GE_REV3 4 ++#define NPHY_ACI_CHANNEL_SKIP_GE_REV3 3 ++ ++#define NPHY_NOISE_NOASSOC_GLITCH_TH_UP 2 ++ ++#define NPHY_NOISE_NOASSOC_GLITCH_TH_DN 8 ++ ++#define NPHY_NOISE_ASSOC_GLITCH_TH_UP 2 ++ ++#define NPHY_NOISE_ASSOC_GLITCH_TH_DN 8 ++ ++#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_UP 2 ++ ++#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_DN 8 ++ ++#define NPHY_NOISE_NOASSOC_ENTER_TH 400 ++ ++#define NPHY_NOISE_ASSOC_ENTER_TH 400 ++ ++#define NPHY_NOISE_ASSOC_RX_GLITCH_BADPLCP_ENTER_TH 400 ++ ++#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX 44 ++#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX_REV_7 56 ++ ++#define NPHY_NOISE_NOASSOC_CRSIDX_INCR 16 ++ ++#define NPHY_NOISE_ASSOC_CRSIDX_INCR 8 ++ ++#define NPHY_IS_SROM_REINTERPRET NREV_GE(pi->pubpi.phy_rev, 5) ++ ++#define NPHY_RSSICAL_MAXREAD 31 ++ ++#define NPHY_RSSICAL_NPOLL 8 ++#define NPHY_RSSICAL_MAXD (1<<20) ++#define NPHY_MIN_RXIQ_PWR 2 ++ ++#define NPHY_RSSICAL_W1_TARGET 25 ++#define NPHY_RSSICAL_W2_TARGET NPHY_RSSICAL_W1_TARGET ++#define NPHY_RSSICAL_NB_TARGET 0 ++ ++#define NPHY_RSSICAL_W1_TARGET_REV3 29 ++#define NPHY_RSSICAL_W2_TARGET_REV3 NPHY_RSSICAL_W1_TARGET_REV3 ++ ++#define NPHY_CALSANITY_RSSI_NB_MAX_POS 9 ++#define NPHY_CALSANITY_RSSI_NB_MAX_NEG -9 ++#define NPHY_CALSANITY_RSSI_W1_MAX_POS 12 ++#define NPHY_CALSANITY_RSSI_W1_MAX_NEG (NPHY_RSSICAL_W1_TARGET - \ ++ NPHY_RSSICAL_MAXREAD) ++#define NPHY_CALSANITY_RSSI_W2_MAX_POS NPHY_CALSANITY_RSSI_W1_MAX_POS ++#define NPHY_CALSANITY_RSSI_W2_MAX_NEG (NPHY_RSSICAL_W2_TARGET - \ ++ NPHY_RSSICAL_MAXREAD) ++#define NPHY_RSSI_SXT(x) ((s8) (-((x) & 0x20) + ((x) & 0x1f))) ++#define NPHY_RSSI_NB_VIOL(x) (((x) > NPHY_CALSANITY_RSSI_NB_MAX_POS) || \ ++ ((x) < NPHY_CALSANITY_RSSI_NB_MAX_NEG)) ++#define NPHY_RSSI_W1_VIOL(x) (((x) > NPHY_CALSANITY_RSSI_W1_MAX_POS) || \ ++ ((x) < NPHY_CALSANITY_RSSI_W1_MAX_NEG)) ++#define NPHY_RSSI_W2_VIOL(x) (((x) > NPHY_CALSANITY_RSSI_W2_MAX_POS) || \ ++ ((x) < NPHY_CALSANITY_RSSI_W2_MAX_NEG)) ++ ++#define NPHY_IQCAL_NUMGAINS 9 ++#define NPHY_N_GCTL 0x66 ++ ++#define NPHY_PAPD_EPS_TBL_SIZE 64 ++#define NPHY_PAPD_SCL_TBL_SIZE 64 ++#define NPHY_NUM_DIG_FILT_COEFFS 15 ++ ++#define NPHY_PAPD_COMP_OFF 0 ++#define NPHY_PAPD_COMP_ON 1 ++ ++#define NPHY_SROM_TEMPSHIFT 32 ++#define NPHY_SROM_MAXTEMPOFFSET 16 ++#define NPHY_SROM_MINTEMPOFFSET -16 ++ ++#define NPHY_CAL_MAXTEMPDELTA 64 ++ ++#define NPHY_NOISEVAR_TBLLEN40 256 ++#define NPHY_NOISEVAR_TBLLEN20 128 ++ ++#define NPHY_ANARXLPFBW_REDUCTIONFACT 7 ++ ++#define NPHY_ADJUSTED_MINCRSPOWER 0x1e ++ ++/* 5357 Chip specific ChipControl register bits */ ++#define CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */ ++#define CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */ ++ ++#define NPHY_CAL_TSSISAMPS 64 ++#define NPHY_TEST_TONE_FREQ_40MHz 4000 ++#define NPHY_TEST_TONE_FREQ_20MHz 2500 ++ ++#define MAX_205x_RCAL_WAITLOOPS 10000 ++ ++#define NPHY_RXCAL_TONEAMP 181 ++#define NPHY_RXCAL_TONEFREQ_40MHz 4000 ++#define NPHY_RXCAL_TONEFREQ_20MHz 2000 ++ ++#define TXFILT_SHAPING_OFDM20 0 ++#define TXFILT_SHAPING_OFDM40 1 ++#define TXFILT_SHAPING_CCK 2 ++#define TXFILT_DEFAULT_OFDM20 3 ++#define TXFILT_DEFAULT_OFDM40 4 ++ ++struct nphy_iqcal_params { ++ u16 txlpf; ++ u16 txgm; ++ u16 pga; ++ u16 pad; ++ u16 ipa; ++ u16 cal_gain; ++ u16 ncorr[5]; ++}; ++ ++struct nphy_txiqcal_ladder { ++ u8 percent; ++ u8 g_env; ++}; ++ ++struct nphy_ipa_txcalgains { ++ struct nphy_txgains gains; ++ bool useindex; ++ u8 index; ++}; ++ ++struct nphy_papd_restore_state { ++ u16 fbmix[2]; ++ u16 vga_master[2]; ++ u16 intpa_master[2]; ++ u16 afectrl[2]; ++ u16 afeoverride[2]; ++ u16 pwrup[2]; ++ u16 atten[2]; ++ u16 mm; ++}; ++ ++struct nphy_ipa_txrxgain { ++ u16 hpvga; ++ u16 lpf_biq1; ++ u16 lpf_biq0; ++ u16 lna2; ++ u16 lna1; ++ s8 txpwrindex; ++}; ++ ++#define NPHY_IPA_RXCAL_MAXGAININDEX (6 - 1) ++ ++static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz[] = { ++ {0, 0, 0, 0, 0, 100}, ++ {0, 0, 0, 0, 0, 50}, ++ {0, 0, 0, 0, 0, -1}, ++ {0, 0, 0, 3, 0, -1}, ++ {0, 0, 3, 3, 0, -1}, ++ {0, 2, 3, 3, 0, -1} ++}; ++ ++static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz[] = { ++ {0, 0, 0, 0, 0, 128}, ++ {0, 0, 0, 0, 0, 70}, ++ {0, 0, 0, 0, 0, 20}, ++ {0, 0, 0, 3, 0, 20}, ++ {0, 0, 3, 3, 0, 20}, ++ {0, 2, 3, 3, 0, 20} ++}; ++ ++static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz_rev7[] = { ++ {0, 0, 0, 0, 0, 100}, ++ {0, 0, 0, 0, 0, 50}, ++ {0, 0, 0, 0, 0, -1}, ++ {0, 0, 0, 3, 0, -1}, ++ {0, 0, 3, 3, 0, -1}, ++ {0, 0, 5, 3, 0, -1} ++}; ++ ++static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz_rev7[] = { ++ {0, 0, 0, 0, 0, 10}, ++ {0, 0, 0, 1, 0, 10}, ++ {0, 0, 1, 2, 0, 10}, ++ {0, 0, 1, 3, 0, 10}, ++ {0, 0, 4, 3, 0, 10}, ++ {0, 0, 6, 3, 0, 10} ++}; ++ ++enum { ++ NPHY_RXCAL_GAIN_INIT = 0, ++ NPHY_RXCAL_GAIN_UP, ++ NPHY_RXCAL_GAIN_DOWN ++}; ++ ++#define wlc_phy_get_papd_nphy(pi) \ ++ (read_phy_reg((pi), 0x1e7) & \ ++ ((0x1 << 15) | \ ++ (0x1 << 14) | \ ++ (0x1 << 13))) ++ ++static const u16 NPHY_IPA_REV4_txdigi_filtcoeffs[][NPHY_NUM_DIG_FILT_COEFFS] = { ++ {-377, 137, -407, 208, -1527, 956, 93, 186, 93, ++ 230, -44, 230, 201, -191, 201}, ++ {-77, 20, -98, 49, -93, 60, 56, 111, 56, 26, -5, ++ 26, 34, -32, 34}, ++ {-360, 164, -376, 164, -1533, 576, 308, -314, 308, ++ 121, -73, 121, 91, 124, 91}, ++ {-295, 200, -363, 142, -1391, 826, 151, 301, 151, ++ 151, 301, 151, 602, -752, 602}, ++ {-92, 58, -96, 49, -104, 44, 17, 35, 17, ++ 12, 25, 12, 13, 27, 13}, ++ {-375, 136, -399, 209, -1479, 949, 130, 260, 130, ++ 230, -44, 230, 201, -191, 201}, ++ {0xed9, 0xc8, 0xe95, 0x8e, 0xa91, 0x33a, 0x97, 0x12d, 0x97, ++ 0x97, 0x12d, 0x97, 0x25a, 0xd10, 0x25a} ++}; ++ ++struct chan_info_nphy_2055 { ++ u16 chan; ++ u16 freq; ++ uint unknown; ++ u8 RF_pll_ref; ++ u8 RF_rf_pll_mod1; ++ u8 RF_rf_pll_mod0; ++ u8 RF_vco_cap_tail; ++ u8 RF_vco_cal1; ++ u8 RF_vco_cal2; ++ u8 RF_pll_lf_c1; ++ u8 RF_pll_lf_r1; ++ u8 RF_pll_lf_c2; ++ u8 RF_lgbuf_cen_buf; ++ u8 RF_lgen_tune1; ++ u8 RF_lgen_tune2; ++ u8 RF_core1_lgbuf_a_tune; ++ u8 RF_core1_lgbuf_g_tune; ++ u8 RF_core1_rxrf_reg1; ++ u8 RF_core1_tx_pga_pad_tn; ++ u8 RF_core1_tx_mx_bgtrim; ++ u8 RF_core2_lgbuf_a_tune; ++ u8 RF_core2_lgbuf_g_tune; ++ u8 RF_core2_rxrf_reg1; ++ u8 RF_core2_tx_pga_pad_tn; ++ u8 RF_core2_tx_mx_bgtrim; ++ u16 PHY_BW1a; ++ u16 PHY_BW2; ++ u16 PHY_BW3; ++ u16 PHY_BW4; ++ u16 PHY_BW5; ++ u16 PHY_BW6; ++}; ++ ++struct chan_info_nphy_radio205x { ++ u16 chan; ++ u16 freq; ++ u8 RF_SYN_pll_vcocal1; ++ u8 RF_SYN_pll_vcocal2; ++ u8 RF_SYN_pll_refdiv; ++ u8 RF_SYN_pll_mmd2; ++ u8 RF_SYN_pll_mmd1; ++ u8 RF_SYN_pll_loopfilter1; ++ u8 RF_SYN_pll_loopfilter2; ++ u8 RF_SYN_pll_loopfilter3; ++ u8 RF_SYN_pll_loopfilter4; ++ u8 RF_SYN_pll_loopfilter5; ++ u8 RF_SYN_reserved_addr27; ++ u8 RF_SYN_reserved_addr28; ++ u8 RF_SYN_reserved_addr29; ++ u8 RF_SYN_logen_VCOBUF1; ++ u8 RF_SYN_logen_MIXER2; ++ u8 RF_SYN_logen_BUF3; ++ u8 RF_SYN_logen_BUF4; ++ u8 RF_RX0_lnaa_tune; ++ u8 RF_RX0_lnag_tune; ++ u8 RF_TX0_intpaa_boost_tune; ++ u8 RF_TX0_intpag_boost_tune; ++ u8 RF_TX0_pada_boost_tune; ++ u8 RF_TX0_padg_boost_tune; ++ u8 RF_TX0_pgaa_boost_tune; ++ u8 RF_TX0_pgag_boost_tune; ++ u8 RF_TX0_mixa_boost_tune; ++ u8 RF_TX0_mixg_boost_tune; ++ u8 RF_RX1_lnaa_tune; ++ u8 RF_RX1_lnag_tune; ++ u8 RF_TX1_intpaa_boost_tune; ++ u8 RF_TX1_intpag_boost_tune; ++ u8 RF_TX1_pada_boost_tune; ++ u8 RF_TX1_padg_boost_tune; ++ u8 RF_TX1_pgaa_boost_tune; ++ u8 RF_TX1_pgag_boost_tune; ++ u8 RF_TX1_mixa_boost_tune; ++ u8 RF_TX1_mixg_boost_tune; ++ u16 PHY_BW1a; ++ u16 PHY_BW2; ++ u16 PHY_BW3; ++ u16 PHY_BW4; ++ u16 PHY_BW5; ++ u16 PHY_BW6; ++}; ++ ++struct chan_info_nphy_radio2057 { ++ u16 chan; ++ u16 freq; ++ u8 RF_vcocal_countval0; ++ u8 RF_vcocal_countval1; ++ u8 RF_rfpll_refmaster_sparextalsize; ++ u8 RF_rfpll_loopfilter_r1; ++ u8 RF_rfpll_loopfilter_c2; ++ u8 RF_rfpll_loopfilter_c1; ++ u8 RF_cp_kpd_idac; ++ u8 RF_rfpll_mmd0; ++ u8 RF_rfpll_mmd1; ++ u8 RF_vcobuf_tune; ++ u8 RF_logen_mx2g_tune; ++ u8 RF_logen_mx5g_tune; ++ u8 RF_logen_indbuf2g_tune; ++ u8 RF_logen_indbuf5g_tune; ++ u8 RF_txmix2g_tune_boost_pu_core0; ++ u8 RF_pad2g_tune_pus_core0; ++ u8 RF_pga_boost_tune_core0; ++ u8 RF_txmix5g_boost_tune_core0; ++ u8 RF_pad5g_tune_misc_pus_core0; ++ u8 RF_lna2g_tune_core0; ++ u8 RF_lna5g_tune_core0; ++ u8 RF_txmix2g_tune_boost_pu_core1; ++ u8 RF_pad2g_tune_pus_core1; ++ u8 RF_pga_boost_tune_core1; ++ u8 RF_txmix5g_boost_tune_core1; ++ u8 RF_pad5g_tune_misc_pus_core1; ++ u8 RF_lna2g_tune_core1; ++ u8 RF_lna5g_tune_core1; ++ u16 PHY_BW1a; ++ u16 PHY_BW2; ++ u16 PHY_BW3; ++ u16 PHY_BW4; ++ u16 PHY_BW5; ++ u16 PHY_BW6; ++}; ++ ++struct chan_info_nphy_radio2057_rev5 { ++ u16 chan; ++ u16 freq; ++ u8 RF_vcocal_countval0; ++ u8 RF_vcocal_countval1; ++ u8 RF_rfpll_refmaster_sparextalsize; ++ u8 RF_rfpll_loopfilter_r1; ++ u8 RF_rfpll_loopfilter_c2; ++ u8 RF_rfpll_loopfilter_c1; ++ u8 RF_cp_kpd_idac; ++ u8 RF_rfpll_mmd0; ++ u8 RF_rfpll_mmd1; ++ u8 RF_vcobuf_tune; ++ u8 RF_logen_mx2g_tune; ++ u8 RF_logen_indbuf2g_tune; ++ u8 RF_txmix2g_tune_boost_pu_core0; ++ u8 RF_pad2g_tune_pus_core0; ++ u8 RF_lna2g_tune_core0; ++ u8 RF_txmix2g_tune_boost_pu_core1; ++ u8 RF_pad2g_tune_pus_core1; ++ u8 RF_lna2g_tune_core1; ++ u16 PHY_BW1a; ++ u16 PHY_BW2; ++ u16 PHY_BW3; ++ u16 PHY_BW4; ++ u16 PHY_BW5; ++ u16 PHY_BW6; ++}; ++ ++struct nphy_sfo_cfg { ++ u16 PHY_BW1a; ++ u16 PHY_BW2; ++ u16 PHY_BW3; ++ u16 PHY_BW4; ++ u16 PHY_BW5; ++ u16 PHY_BW6; ++}; ++ ++static const struct chan_info_nphy_2055 chan_info_nphy_2055[] = { ++ { ++ 184, 4920, 3280, 0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7B4, 0x7B0, 0x7AC, 0x214, 0x215, 0x216}, ++ { ++ 186, 4930, 3287, 0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7B8, 0x7B4, 0x7B0, 0x213, 0x214, 0x215}, ++ { ++ 188, 4940, 3293, 0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7BC, 0x7B8, 0x7B4, 0x212, 0x213, 0x214}, ++ { ++ 190, 4950, 3300, 0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7C0, 0x7BC, 0x7B8, 0x211, 0x212, 0x213}, ++ { ++ 192, 4960, 3307, 0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7C4, 0x7C0, 0x7BC, 0x20F, 0x211, 0x212}, ++ { ++ 194, 4970, 3313, 0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7C8, 0x7C4, 0x7C0, 0x20E, 0x20F, 0x211}, ++ { ++ 196, 4980, 3320, 0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7CC, 0x7C8, 0x7C4, 0x20D, 0x20E, 0x20F}, ++ { ++ 198, 4990, 3327, 0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7D0, 0x7CC, 0x7C8, 0x20C, 0x20D, 0x20E}, ++ { ++ 200, 5000, 3333, 0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7D4, 0x7D0, 0x7CC, 0x20B, 0x20C, 0x20D}, ++ { ++ 202, 5010, 3340, 0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7D8, 0x7D4, 0x7D0, 0x20A, 0x20B, 0x20C}, ++ { ++ 204, 5020, 3347, 0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7DC, 0x7D8, 0x7D4, 0x209, 0x20A, 0x20B}, ++ { ++ 206, 5030, 3353, 0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7E0, 0x7DC, 0x7D8, 0x208, 0x209, 0x20A}, ++ { ++ 208, 5040, 3360, 0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7E4, 0x7E0, 0x7DC, 0x207, 0x208, 0x209}, ++ { ++ 210, 5050, 3367, 0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F, ++ 0x0F, 0x8F, 0x7E8, 0x7E4, 0x7E0, 0x206, 0x207, 0x208}, ++ { ++ 212, 5060, 3373, 0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E, ++ 0x0F, 0x8E, 0x7EC, 0x7E8, 0x7E4, 0x205, 0x206, 0x207}, ++ { ++ 214, 5070, 3380, 0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A, ++ 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E, ++ 0x0F, 0x8E, 0x7F0, 0x7EC, 0x7E8, 0x204, 0x205, 0x206}, ++ { ++ 216, 5080, 3387, 0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A, ++ 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E, ++ 0x0F, 0x8D, 0x7F4, 0x7F0, 0x7EC, 0x203, 0x204, 0x205}, ++ { ++ 218, 5090, 3393, 0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A, ++ 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E, ++ 0x0F, 0x8D, 0x7F8, 0x7F4, 0x7F0, 0x202, 0x203, 0x204}, ++ { ++ 220, 5100, 3400, 0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A, ++ 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D, ++ 0x0F, 0x8D, 0x7FC, 0x7F8, 0x7F4, 0x201, 0x202, 0x203}, ++ { ++ 222, 5110, 3407, 0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A, ++ 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D, ++ 0x0F, 0x8D, 0x800, 0x7FC, 0x7F8, 0x200, 0x201, 0x202}, ++ { ++ 224, 5120, 3413, 0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A, ++ 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D, ++ 0x0F, 0x8C, 0x804, 0x800, 0x7FC, 0x1FF, 0x200, 0x201}, ++ { ++ 226, 5130, 3420, 0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A, ++ 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D, ++ 0x0F, 0x8C, 0x808, 0x804, 0x800, 0x1FE, 0x1FF, 0x200}, ++ { ++ 228, 5140, 3427, 0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A, ++ 0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E, 0x8B, 0xDD, 0x00, 0x0C, ++ 0x0E, 0x8B, 0x80C, 0x808, 0x804, 0x1FD, 0x1FE, 0x1FF}, ++ { ++ 32, 5160, 3440, 0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A, ++ 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B, ++ 0x0D, 0x8A, 0x814, 0x810, 0x80C, 0x1FB, 0x1FC, 0x1FD}, ++ { ++ 34, 5170, 3447, 0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A, ++ 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B, ++ 0x0D, 0x8A, 0x818, 0x814, 0x810, 0x1FA, 0x1FB, 0x1FC}, ++ { ++ 36, 5180, 3453, 0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A, ++ 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B, ++ 0x0C, 0x89, 0x81C, 0x818, 0x814, 0x1F9, 0x1FA, 0x1FB}, ++ { ++ 38, 5190, 3460, 0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A, ++ 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B, ++ 0x0C, 0x89, 0x820, 0x81C, 0x818, 0x1F8, 0x1F9, 0x1FA}, ++ { ++ 40, 5200, 3467, 0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A, ++ 0x0B, 0x89, 0x824, 0x820, 0x81C, 0x1F7, 0x1F8, 0x1F9}, ++ { ++ 42, 5210, 3473, 0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A, ++ 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A, ++ 0x0B, 0x89, 0x828, 0x824, 0x820, 0x1F6, 0x1F7, 0x1F8}, ++ { ++ 44, 5220, 3480, 0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A, ++ 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09, ++ 0x0A, 0x88, 0x82C, 0x828, 0x824, 0x1F5, 0x1F6, 0x1F7}, ++ { ++ 46, 5230, 3487, 0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A, ++ 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09, ++ 0x0A, 0x88, 0x830, 0x82C, 0x828, 0x1F4, 0x1F5, 0x1F6}, ++ { ++ 48, 5240, 3493, 0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A, ++ 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09, ++ 0x0A, 0x87, 0x834, 0x830, 0x82C, 0x1F3, 0x1F4, 0x1F5}, ++ { ++ 50, 5250, 3500, 0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A, ++ 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09, ++ 0x0A, 0x87, 0x838, 0x834, 0x830, 0x1F2, 0x1F3, 0x1F4}, ++ { ++ 52, 5260, 3507, 0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A, ++ 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08, ++ 0x09, 0x87, 0x83C, 0x838, 0x834, 0x1F1, 0x1F2, 0x1F3}, ++ { ++ 54, 5270, 3513, 0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A, ++ 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08, ++ 0x09, 0x87, 0x840, 0x83C, 0x838, 0x1F0, 0x1F1, 0x1F2}, ++ { ++ 56, 5280, 3520, 0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A, ++ 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08, ++ 0x08, 0x86, 0x844, 0x840, 0x83C, 0x1F0, 0x1F0, 0x1F1}, ++ { ++ 58, 5290, 3527, 0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A, ++ 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08, ++ 0x08, 0x86, 0x848, 0x844, 0x840, 0x1EF, 0x1F0, 0x1F0}, ++ { ++ 60, 5300, 3533, 0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A, ++ 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08, ++ 0x07, 0x85, 0x84C, 0x848, 0x844, 0x1EE, 0x1EF, 0x1F0}, ++ { ++ 62, 5310, 3540, 0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A, ++ 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08, ++ 0x07, 0x85, 0x850, 0x84C, 0x848, 0x1ED, 0x1EE, 0x1EF}, ++ { ++ 64, 5320, 3547, 0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A, ++ 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07, ++ 0x07, 0x84, 0x854, 0x850, 0x84C, 0x1EC, 0x1ED, 0x1EE}, ++ { ++ 66, 5330, 3553, 0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A, ++ 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07, ++ 0x07, 0x84, 0x858, 0x854, 0x850, 0x1EB, 0x1EC, 0x1ED}, ++ { ++ 68, 5340, 3560, 0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A, ++ 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07, ++ 0x06, 0x84, 0x85C, 0x858, 0x854, 0x1EA, 0x1EB, 0x1EC}, ++ { ++ 70, 5350, 3567, 0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A, ++ 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07, ++ 0x06, 0x84, 0x860, 0x85C, 0x858, 0x1E9, 0x1EA, 0x1EB}, ++ { ++ 72, 5360, 3573, 0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A, ++ 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06, ++ 0x05, 0x83, 0x864, 0x860, 0x85C, 0x1E8, 0x1E9, 0x1EA}, ++ { ++ 74, 5370, 3580, 0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A, ++ 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06, ++ 0x05, 0x83, 0x868, 0x864, 0x860, 0x1E7, 0x1E8, 0x1E9}, ++ { ++ 76, 5380, 3587, 0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A, ++ 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06, ++ 0x04, 0x82, 0x86C, 0x868, 0x864, 0x1E6, 0x1E7, 0x1E8}, ++ { ++ 78, 5390, 3593, 0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A, ++ 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06, ++ 0x04, 0x82, 0x870, 0x86C, 0x868, 0x1E5, 0x1E6, 0x1E7}, ++ { ++ 80, 5400, 3600, 0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A, ++ 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05, ++ 0x04, 0x81, 0x874, 0x870, 0x86C, 0x1E5, 0x1E5, 0x1E6}, ++ { ++ 82, 5410, 3607, 0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A, ++ 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05, ++ 0x04, 0x81, 0x878, 0x874, 0x870, 0x1E4, 0x1E5, 0x1E5}, ++ { ++ 84, 5420, 3613, 0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A, ++ 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05, ++ 0x03, 0x80, 0x87C, 0x878, 0x874, 0x1E3, 0x1E4, 0x1E5}, ++ { ++ 86, 5430, 3620, 0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A, ++ 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05, ++ 0x03, 0x80, 0x880, 0x87C, 0x878, 0x1E2, 0x1E3, 0x1E4}, ++ { ++ 88, 5440, 3627, 0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A, ++ 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04, ++ 0x02, 0x80, 0x884, 0x880, 0x87C, 0x1E1, 0x1E2, 0x1E3}, ++ { ++ 90, 5450, 3633, 0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A, ++ 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04, ++ 0x02, 0x80, 0x888, 0x884, 0x880, 0x1E0, 0x1E1, 0x1E2}, ++ { ++ 92, 5460, 3640, 0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A, ++ 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04, ++ 0x01, 0x80, 0x88C, 0x888, 0x884, 0x1DF, 0x1E0, 0x1E1}, ++ { ++ 94, 5470, 3647, 0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A, ++ 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04, ++ 0x01, 0x80, 0x890, 0x88C, 0x888, 0x1DE, 0x1DF, 0x1E0}, ++ { ++ 96, 5480, 3653, 0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A, ++ 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, ++ 0x00, 0x80, 0x894, 0x890, 0x88C, 0x1DD, 0x1DE, 0x1DF}, ++ { ++ 98, 5490, 3660, 0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A, ++ 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, ++ 0x00, 0x80, 0x898, 0x894, 0x890, 0x1DD, 0x1DD, 0x1DE}, ++ { ++ 100, 5500, 3667, 0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A, ++ 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, ++ 0x00, 0x80, 0x89C, 0x898, 0x894, 0x1DC, 0x1DD, 0x1DD}, ++ { ++ 102, 5510, 3673, 0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A, ++ 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03, ++ 0x00, 0x80, 0x8A0, 0x89C, 0x898, 0x1DB, 0x1DC, 0x1DD}, ++ { ++ 104, 5520, 3680, 0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A, ++ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, ++ 0x00, 0x80, 0x8A4, 0x8A0, 0x89C, 0x1DA, 0x1DB, 0x1DC}, ++ { ++ 106, 5530, 3687, 0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A, ++ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, ++ 0x00, 0x80, 0x8A8, 0x8A4, 0x8A0, 0x1D9, 0x1DA, 0x1DB}, ++ { ++ 108, 5540, 3693, 0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A, ++ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, ++ 0x00, 0x80, 0x8AC, 0x8A8, 0x8A4, 0x1D8, 0x1D9, 0x1DA}, ++ { ++ 110, 5550, 3700, 0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A, ++ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02, ++ 0x00, 0x80, 0x8B0, 0x8AC, 0x8A8, 0x1D7, 0x1D8, 0x1D9}, ++ { ++ 112, 5560, 3707, 0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A, ++ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, ++ 0x00, 0x80, 0x8B4, 0x8B0, 0x8AC, 0x1D7, 0x1D7, 0x1D8}, ++ { ++ 114, 5570, 3713, 0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A, ++ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, ++ 0x00, 0x80, 0x8B8, 0x8B4, 0x8B0, 0x1D6, 0x1D7, 0x1D7}, ++ { ++ 116, 5580, 3720, 0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A, ++ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, ++ 0x00, 0x80, 0x8BC, 0x8B8, 0x8B4, 0x1D5, 0x1D6, 0x1D7}, ++ { ++ 118, 5590, 3727, 0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A, ++ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01, ++ 0x00, 0x80, 0x8C0, 0x8BC, 0x8B8, 0x1D4, 0x1D5, 0x1D6}, ++ { ++ 120, 5600, 3733, 0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A, ++ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01, ++ 0x00, 0x80, 0x8C4, 0x8C0, 0x8BC, 0x1D3, 0x1D4, 0x1D5}, ++ { ++ 122, 5610, 3740, 0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A, ++ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01, ++ 0x00, 0x80, 0x8C8, 0x8C4, 0x8C0, 0x1D2, 0x1D3, 0x1D4}, ++ { ++ 124, 5620, 3747, 0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A, ++ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, ++ 0x00, 0x80, 0x8CC, 0x8C8, 0x8C4, 0x1D2, 0x1D2, 0x1D3}, ++ { ++ 126, 5630, 3753, 0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A, ++ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, ++ 0x00, 0x80, 0x8D0, 0x8CC, 0x8C8, 0x1D1, 0x1D2, 0x1D2}, ++ { ++ 128, 5640, 3760, 0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8D4, 0x8D0, 0x8CC, 0x1D0, 0x1D1, 0x1D2}, ++ { ++ 130, 5650, 3767, 0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8D8, 0x8D4, 0x8D0, 0x1CF, 0x1D0, 0x1D1}, ++ { ++ 132, 5660, 3773, 0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8DC, 0x8D8, 0x8D4, 0x1CE, 0x1CF, 0x1D0}, ++ { ++ 134, 5670, 3780, 0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8E0, 0x8DC, 0x8D8, 0x1CE, 0x1CE, 0x1CF}, ++ { ++ 136, 5680, 3787, 0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8E4, 0x8E0, 0x8DC, 0x1CD, 0x1CE, 0x1CE}, ++ { ++ 138, 5690, 3793, 0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8E8, 0x8E4, 0x8E0, 0x1CC, 0x1CD, 0x1CE}, ++ { ++ 140, 5700, 3800, 0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8EC, 0x8E8, 0x8E4, 0x1CB, 0x1CC, 0x1CD}, ++ { ++ 142, 5710, 3807, 0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8F0, 0x8EC, 0x8E8, 0x1CA, 0x1CB, 0x1CC}, ++ { ++ 144, 5720, 3813, 0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8F4, 0x8F0, 0x8EC, 0x1C9, 0x1CA, 0x1CB}, ++ { ++ 145, 5725, 3817, 0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8F6, 0x8F2, 0x8EE, 0x1C9, 0x1CA, 0x1CB}, ++ { ++ 146, 5730, 3820, 0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8F8, 0x8F4, 0x8F0, 0x1C9, 0x1C9, 0x1CA}, ++ { ++ 147, 5735, 3823, 0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8FA, 0x8F6, 0x8F2, 0x1C8, 0x1C9, 0x1CA}, ++ { ++ 148, 5740, 3827, 0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8FC, 0x8F8, 0x8F4, 0x1C8, 0x1C9, 0x1C9}, ++ { ++ 149, 5745, 3830, 0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x8FE, 0x8FA, 0x8F6, 0x1C8, 0x1C8, 0x1C9}, ++ { ++ 150, 5750, 3833, 0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x900, 0x8FC, 0x8F8, 0x1C7, 0x1C8, 0x1C9}, ++ { ++ 151, 5755, 3837, 0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x902, 0x8FE, 0x8FA, 0x1C7, 0x1C8, 0x1C8}, ++ { ++ 152, 5760, 3840, 0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x904, 0x900, 0x8FC, 0x1C6, 0x1C7, 0x1C8}, ++ { ++ 153, 5765, 3843, 0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x906, 0x902, 0x8FE, 0x1C6, 0x1C7, 0x1C8}, ++ { ++ 154, 5770, 3847, 0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x908, 0x904, 0x900, 0x1C6, 0x1C6, 0x1C7}, ++ { ++ 155, 5775, 3850, 0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x90A, 0x906, 0x902, 0x1C5, 0x1C6, 0x1C7}, ++ { ++ 156, 5780, 3853, 0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x90C, 0x908, 0x904, 0x1C5, 0x1C6, 0x1C6}, ++ { ++ 157, 5785, 3857, 0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x90E, 0x90A, 0x906, 0x1C4, 0x1C5, 0x1C6}, ++ { ++ 158, 5790, 3860, 0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x910, 0x90C, 0x908, 0x1C4, 0x1C5, 0x1C6}, ++ { ++ 159, 5795, 3863, 0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x912, 0x90E, 0x90A, 0x1C4, 0x1C4, 0x1C5}, ++ { ++ 160, 5800, 3867, 0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x914, 0x910, 0x90C, 0x1C3, 0x1C4, 0x1C5}, ++ { ++ 161, 5805, 3870, 0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x916, 0x912, 0x90E, 0x1C3, 0x1C4, 0x1C4}, ++ { ++ 162, 5810, 3873, 0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x918, 0x914, 0x910, 0x1C2, 0x1C3, 0x1C4}, ++ { ++ 163, 5815, 3877, 0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x91A, 0x916, 0x912, 0x1C2, 0x1C3, 0x1C4}, ++ { ++ 164, 5820, 3880, 0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x91C, 0x918, 0x914, 0x1C2, 0x1C2, 0x1C3}, ++ { ++ 165, 5825, 3883, 0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x91E, 0x91A, 0x916, 0x1C1, 0x1C2, 0x1C3}, ++ { ++ 166, 5830, 3887, 0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x920, 0x91C, 0x918, 0x1C1, 0x1C2, 0x1C2}, ++ { ++ 168, 5840, 3893, 0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x924, 0x920, 0x91C, 0x1C0, 0x1C1, 0x1C2}, ++ { ++ 170, 5850, 3900, 0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x928, 0x924, 0x920, 0x1BF, 0x1C0, 0x1C1}, ++ { ++ 172, 5860, 3907, 0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x92C, 0x928, 0x924, 0x1BF, 0x1BF, 0x1C0}, ++ { ++ 174, 5870, 3913, 0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x930, 0x92C, 0x928, 0x1BE, 0x1BF, 0x1BF}, ++ { ++ 176, 5880, 3920, 0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x934, 0x930, 0x92C, 0x1BD, 0x1BE, 0x1BF}, ++ { ++ 178, 5890, 3927, 0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x938, 0x934, 0x930, 0x1BC, 0x1BD, 0x1BE}, ++ { ++ 180, 5900, 3933, 0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x93C, 0x938, 0x934, 0x1BC, 0x1BC, 0x1BD}, ++ { ++ 182, 5910, 3940, 0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A, ++ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x80, 0x940, 0x93C, 0x938, 0x1BB, 0x1BC, 0x1BC}, ++ { ++ 1, 2412, 3216, 0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C, 0x80, 0xFF, 0x88, 0x0D, ++ 0x0C, 0x80, 0x3C9, 0x3C5, 0x3C1, 0x43A, 0x43F, 0x443}, ++ { ++ 2, 2417, 3223, 0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B, 0x80, 0xFF, 0x88, 0x0C, ++ 0x0B, 0x80, 0x3CB, 0x3C7, 0x3C3, 0x438, 0x43D, 0x441}, ++ { ++ 3, 2422, 3229, 0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C, ++ 0x0A, 0x80, 0x3CD, 0x3C9, 0x3C5, 0x436, 0x43A, 0x43F}, ++ { ++ 4, 2427, 3236, 0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C, ++ 0x0A, 0x80, 0x3CF, 0x3CB, 0x3C7, 0x434, 0x438, 0x43D}, ++ { ++ 5, 2432, 3243, 0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09, 0x80, 0xFF, 0x88, 0x0C, ++ 0x09, 0x80, 0x3D1, 0x3CD, 0x3C9, 0x431, 0x436, 0x43A}, ++ { ++ 6, 2437, 3249, 0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08, 0x80, 0xFF, 0x88, 0x0B, ++ 0x08, 0x80, 0x3D3, 0x3CF, 0x3CB, 0x42F, 0x434, 0x438}, ++ { ++ 7, 2442, 3256, 0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07, 0x80, 0xFF, 0x88, 0x0A, ++ 0x07, 0x80, 0x3D5, 0x3D1, 0x3CD, 0x42D, 0x431, 0x436}, ++ { ++ 8, 2447, 3263, 0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06, 0x80, 0xFF, 0x88, 0x0A, ++ 0x06, 0x80, 0x3D7, 0x3D3, 0x3CF, 0x42B, 0x42F, 0x434}, ++ { ++ 9, 2452, 3269, 0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06, 0x80, 0xFF, 0x88, 0x09, ++ 0x06, 0x80, 0x3D9, 0x3D5, 0x3D1, 0x429, 0x42D, 0x431}, ++ { ++ 10, 2457, 3276, 0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05, 0x80, 0xFF, 0x88, 0x08, ++ 0x05, 0x80, 0x3DB, 0x3D7, 0x3D3, 0x427, 0x42B, 0x42F}, ++ { ++ 11, 2462, 3283, 0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04, 0x80, 0xFF, 0x88, 0x08, ++ 0x04, 0x80, 0x3DD, 0x3D9, 0x3D5, 0x424, 0x429, 0x42D}, ++ { ++ 12, 2467, 3289, 0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03, 0x80, 0xFF, 0x88, 0x08, ++ 0x03, 0x80, 0x3DF, 0x3DB, 0x3D7, 0x422, 0x427, 0x42B}, ++ { ++ 13, 2472, 3296, 0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03, 0x80, 0xFF, 0x88, 0x07, ++ 0x03, 0x80, 0x3E1, 0x3DD, 0x3D9, 0x420, 0x424, 0x429}, ++ { ++ 14, 2484, 3312, 0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15, ++ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01, 0x80, 0xFF, 0x88, 0x07, ++ 0x01, 0x80, 0x3E6, 0x3E2, 0x3DE, 0x41B, 0x41F, 0x424} ++}; ++ ++static const struct chan_info_nphy_radio205x chan_info_nphyrev3_2056[] = { ++ { ++ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, ++ { ++ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, ++ { ++ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, ++ { ++ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, ++ { ++ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, ++ { ++ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, ++ { ++ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, ++ { ++ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, ++ { ++ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, ++ { ++ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, ++ { ++ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, ++ { ++ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, ++ { ++ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, ++ { ++ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, ++ { ++ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, ++ { ++ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, ++ { ++ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, ++ { ++ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, ++ { ++ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xff, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, ++ { ++ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xfc, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, ++ { ++ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xfc, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, ++ { ++ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xfc, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, ++ { ++ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xfc, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, ++ { ++ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xfc, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, ++ { ++ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xfc, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, ++ { ++ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xfc, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, ++ { ++ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xfc, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, ++ { ++ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, ++ { ++ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, ++ { ++ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, ++ { ++ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, ++ { ++ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, ++ { ++ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, ++ { ++ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, ++ { ++ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, ++ { ++ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, ++ { ++ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, ++ { ++ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfc, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, ++ { ++ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, ++ { ++ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, ++ { ++ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, ++ { ++ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, ++ { ++ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, ++ { ++ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, ++ { ++ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, ++ { ++ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, ++ { ++ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x05, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, ++ { ++ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xfa, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, ++ { ++ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xfa, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, ++ { ++ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xfa, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, ++ { ++ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xfa, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, ++ { ++ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xfa, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, ++ { ++ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xfa, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, ++ { ++ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, ++ { ++ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, ++ { ++ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, ++ { ++ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08, ++ 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, ++ { ++ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, ++ { ++ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, ++ { ++ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, ++ { ++ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, ++ { ++ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, ++ { ++ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, ++ { ++ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, ++ { ++ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, ++ { ++ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, ++ { ++ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, ++ { ++ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, ++ { ++ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, ++ { ++ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, ++ { ++ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, ++ { ++ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf8, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf8, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, ++ { ++ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf6, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, ++ { ++ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf6, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, ++ { ++ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf6, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, ++ { ++ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf6, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, ++ { ++ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf6, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, ++ { ++ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, ++ { ++ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, ++ { ++ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, ++ { ++ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, ++ { ++ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, ++ { ++ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, ++ { ++ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, ++ { ++ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, ++ { ++ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, ++ { ++ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, ++ { ++ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, ++ { ++ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, ++ { ++ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, ++ { ++ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, ++ { ++ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, ++ { ++ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, ++ { ++ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, ++ { ++ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf4, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, ++ { ++ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf2, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf2, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, ++ { ++ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf2, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, ++ { ++ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf2, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, ++ { ++ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06, ++ 0x00, 0xf2, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, ++ { ++ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x05, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05, ++ 0x00, 0xf2, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, ++ { ++ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x05, 0x00, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05, ++ 0x00, 0xf2, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, ++ { ++ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfd, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfb, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf7, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf6, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0f, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf5, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0d, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0d, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf3, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0d, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0d, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x05, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf0, 0x00, 0x05, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0d, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio205x chan_info_nphyrev4_2056_A1[] = { ++ { ++ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, ++ { ++ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, ++ { ++ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, ++ { ++ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, ++ { ++ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, ++ { ++ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, ++ { ++ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, ++ { ++ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, ++ { ++ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, ++ { ++ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, ++ { ++ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, ++ { ++ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, ++ { ++ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, ++ { ++ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, ++ { ++ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, ++ { ++ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, ++ { ++ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, ++ { ++ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, ++ { ++ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, ++ { ++ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, ++ { ++ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, ++ { ++ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, ++ { ++ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, ++ { ++ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, ++ { ++ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, ++ { ++ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, ++ { ++ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfe, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, ++ { ++ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, ++ { ++ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, ++ { ++ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, ++ { ++ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, ++ { ++ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, ++ { ++ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, ++ { ++ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, ++ { ++ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, ++ { ++ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, ++ { ++ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, ++ { ++ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, ++ { ++ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, ++ { ++ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, ++ { ++ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, ++ { ++ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, ++ { ++ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, ++ { ++ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, ++ { ++ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, ++ { ++ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, ++ { ++ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x08, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, ++ { ++ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, ++ { ++ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, ++ { ++ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, ++ { ++ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, ++ { ++ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, ++ { ++ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, ++ { ++ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, ++ { ++ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, ++ { ++ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, ++ { ++ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x07, 0x00, 0x7f, ++ 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f, ++ 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, ++ { ++ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x5c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, ++ { ++ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, ++ { ++ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, ++ { ++ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, ++ { ++ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, ++ { ++ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, ++ { ++ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, ++ { ++ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, ++ { ++ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f, ++ 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d, ++ 0x00, 0xf6, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, ++ { ++ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, ++ { ++ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, ++ { ++ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, ++ { ++ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, ++ { ++ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, ++ { ++ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, ++ { ++ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, ++ { ++ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, ++ { ++ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, ++ { ++ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x04, 0x00, 0x7f, ++ 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b, ++ 0x00, 0xf4, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, ++ { ++ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, ++ { ++ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, ++ { ++ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, ++ { ++ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, ++ { ++ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, ++ { ++ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, ++ { ++ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, ++ { ++ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, ++ { ++ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, ++ { ++ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, ++ { ++ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, ++ { ++ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, ++ 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a, ++ 0x00, 0xf2, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, ++ { ++ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, ++ { ++ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, ++ { ++ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, ++ { ++ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, ++ { ++ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, ++ { ++ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, ++ { ++ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, ++ { ++ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, ++ { ++ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, ++ { ++ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, ++ { ++ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, ++ 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09, ++ 0x00, 0xf0, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, ++ { ++ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf0, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, ++ { ++ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, ++ 0x00, 0x07, 0x00, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07, ++ 0x00, 0xf0, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, ++ { ++ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfd, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfb, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf8, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf7, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf5, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf3, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x04, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0e, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio205x chan_info_nphyrev5_2056v5[] = { ++ { ++ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, ++ 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, ++ { ++ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, ++ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, ++ { ++ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, ++ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, ++ { ++ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, ++ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, ++ { ++ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, ++ { ++ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, ++ { ++ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, ++ { ++ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, ++ { ++ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, ++ { ++ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, ++ { ++ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, ++ { ++ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, ++ { ++ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, ++ { ++ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, ++ { ++ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, ++ { ++ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, ++ { ++ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, ++ { ++ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, ++ { ++ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, ++ { ++ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, ++ { ++ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, ++ { ++ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, ++ { ++ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, ++ 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, ++ { ++ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, ++ { ++ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, ++ { ++ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, ++ { ++ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, ++ { ++ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, ++ { ++ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, ++ { ++ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, ++ { ++ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xea, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08, ++ 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, ++ { ++ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70, ++ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, ++ 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, ++ { ++ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70, ++ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, ++ 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, ++ { ++ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xd9, 0x00, 0x05, 0x00, 0x70, ++ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, ++ 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, ++ { ++ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xd8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, ++ { ++ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, ++ { ++ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, ++ { ++ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, ++ { ++ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, ++ { ++ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, ++ { ++ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, ++ { ++ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, ++ { ++ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa7, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, ++ { ++ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, ++ { ++ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x5b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, ++ { ++ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x96, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x5a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, ++ { ++ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x95, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x5a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, ++ { ++ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x5a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, ++ { ++ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x5a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, ++ { ++ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x5a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, ++ { ++ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x85, 0x00, 0x02, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x59, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, ++ { ++ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x59, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, ++ { ++ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x59, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, ++ { ++ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, ++ { ++ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x74, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, ++ { ++ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, ++ { ++ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, ++ { ++ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, ++ { ++ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, ++ { ++ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, ++ { ++ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x63, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03, ++ 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, ++ { ++ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, ++ 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, ++ 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, ++ { ++ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, ++ 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, ++ { ++ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, ++ { ++ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x76, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, ++ { ++ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x76, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, ++ { ++ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x76, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, ++ { ++ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x76, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, ++ { ++ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x76, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, ++ { ++ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x76, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, ++ { ++ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x75, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, ++ { ++ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x75, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, ++ { ++ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x75, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, ++ { ++ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x74, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, ++ { ++ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x74, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, ++ { ++ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x74, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, ++ { ++ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x74, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, ++ { ++ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x74, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, ++ { ++ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x74, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x74, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x84, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, ++ { ++ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x83, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, ++ { ++ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x83, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, ++ { ++ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x83, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, ++ { ++ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x83, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, ++ { ++ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x83, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, ++ { ++ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x83, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, ++ { ++ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, ++ { ++ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, ++ { ++ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, ++ { ++ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, ++ { ++ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, ++ { ++ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, ++ { ++ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x82, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, ++ { ++ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x72, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, ++ { ++ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x72, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, ++ { ++ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x72, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, ++ { ++ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x72, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, ++ { ++ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x71, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, ++ { ++ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x71, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, ++ { ++ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x71, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, ++ { ++ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x71, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, ++ { ++ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x71, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, ++ { ++ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x08, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x07, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x06, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x05, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x03, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v6[] = { ++ { ++ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, ++ { ++ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, ++ { ++ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, ++ { ++ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, ++ { ++ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, ++ { ++ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, ++ { ++ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, ++ { ++ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, ++ { ++ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, ++ { ++ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, ++ { ++ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, ++ { ++ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, ++ { ++ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, ++ { ++ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, ++ { ++ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, ++ { ++ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, ++ { ++ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, ++ { ++ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, ++ { ++ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, ++ { ++ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, ++ { ++ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, ++ { ++ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, ++ { ++ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, ++ { ++ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, ++ { ++ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, ++ { ++ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, ++ { ++ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, ++ { ++ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, ++ { ++ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, ++ { ++ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, ++ { ++ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, ++ { ++ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, ++ { ++ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, ++ { ++ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, ++ { ++ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, ++ { ++ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, ++ { ++ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, ++ { ++ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, ++ { ++ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, ++ { ++ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, ++ { ++ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, ++ { ++ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, ++ { ++ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, ++ { ++ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, ++ { ++ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, ++ { ++ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, ++ { ++ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, ++ { ++ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, ++ { ++ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, ++ { ++ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, ++ { ++ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, ++ { ++ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, ++ { ++ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, ++ { ++ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, ++ { ++ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, ++ { ++ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, ++ { ++ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, ++ { ++ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, ++ { ++ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, ++ { ++ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, ++ { ++ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, ++ { ++ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, ++ { ++ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, ++ { ++ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, ++ { ++ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, ++ { ++ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, ++ { ++ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, ++ { ++ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, ++ { ++ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, ++ { ++ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, ++ { ++ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, ++ { ++ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, ++ { ++ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, ++ { ++ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, ++ { ++ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, ++ { ++ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, ++ { ++ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, ++ { ++ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, ++ { ++ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, ++ { ++ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, ++ { ++ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, ++ { ++ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, ++ { ++ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, ++ { ++ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, ++ { ++ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, ++ { ++ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, ++ { ++ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, ++ { ++ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, ++ { ++ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, ++ { ++ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, ++ { ++ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, ++ { ++ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, ++ { ++ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, ++ { ++ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, ++ { ++ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, ++ { ++ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, ++ { ++ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, ++ { ++ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, ++ { ++ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, ++ { ++ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, ++ { ++ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, ++ { ++ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio205x chan_info_nphyrev5n6_2056v7[] = { ++ { ++ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, ++ 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, ++ { ++ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, ++ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, ++ { ++ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, ++ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, ++ { ++ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, ++ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, ++ { ++ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, ++ { ++ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, ++ { ++ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, ++ { ++ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, ++ { ++ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, ++ { ++ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, ++ { ++ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, ++ { ++ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, ++ { ++ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, ++ { ++ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, ++ { ++ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70, ++ 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, ++ { ++ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, ++ { ++ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, ++ { ++ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, ++ { ++ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, ++ { ++ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, ++ { ++ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, ++ { ++ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70, ++ 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, ++ { ++ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, ++ 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, ++ { ++ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, ++ { ++ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, ++ { ++ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, ++ { ++ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, ++ { ++ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, ++ { ++ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, ++ { ++ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xfa, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09, ++ 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, ++ { ++ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xea, 0x00, 0x06, 0x00, 0x70, ++ 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08, ++ 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, ++ { ++ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xe9, 0x00, 0x05, 0x00, 0x70, ++ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, ++ 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, ++ { ++ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xe9, 0x00, 0x05, 0x00, 0x70, ++ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, ++ 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, ++ { ++ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xd9, 0x00, 0x05, 0x00, 0x70, ++ 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08, ++ 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, ++ { ++ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xd8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, ++ { ++ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, ++ { ++ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, ++ { ++ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, ++ { ++ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, ++ { ++ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb8, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, ++ { ++ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xb7, 0x00, 0x04, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, ++ { ++ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xb7, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07, ++ 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, ++ { ++ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa7, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, ++ { ++ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, ++ { ++ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x7b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, ++ { ++ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x96, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x7a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, ++ { ++ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x7a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, ++ { ++ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06, ++ 0x00, 0x7a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, ++ { ++ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x95, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x7a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, ++ { ++ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x95, 0x00, 0x03, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x7a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, ++ { ++ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x85, 0x00, 0x02, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x79, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, ++ { ++ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x79, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, ++ { ++ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70, ++ 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, ++ 0x00, 0x79, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, ++ { ++ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x79, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, ++ { ++ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x74, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x79, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, ++ { ++ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x78, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, ++ { ++ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x78, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, ++ { ++ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, ++ { ++ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, ++ { ++ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04, ++ 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, ++ { ++ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x63, 0x00, 0x01, 0x00, 0x70, ++ 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03, ++ 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, ++ { ++ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x62, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, ++ 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, ++ 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, ++ { ++ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03, ++ 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, ++ { ++ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x52, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, ++ { ++ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x52, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x86, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, ++ { ++ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x86, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, ++ { ++ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x86, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, ++ { ++ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x86, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, ++ { ++ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x86, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, ++ { ++ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x86, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, ++ { ++ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x51, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, ++ 0x00, 0x85, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, ++ { ++ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x85, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, ++ { ++ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x85, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, ++ { ++ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x84, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, ++ { ++ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x84, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, ++ { ++ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x94, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, ++ { ++ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x94, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, ++ { ++ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x94, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, ++ { ++ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x94, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x94, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, ++ 0x00, 0x94, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, ++ { ++ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x93, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, ++ { ++ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x93, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, ++ { ++ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x93, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, ++ { ++ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x93, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, ++ { ++ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x30, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x93, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, ++ { ++ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x93, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, ++ { ++ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, ++ { ++ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, ++ { ++ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, ++ { ++ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, ++ { ++ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, ++ { ++ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, ++ { ++ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, ++ { ++ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, ++ { ++ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, ++ { ++ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, ++ { ++ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x92, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, ++ { ++ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x91, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, ++ { ++ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x91, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, ++ { ++ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x91, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, ++ { ++ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x91, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, ++ { ++ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, ++ 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, ++ 0x00, 0x91, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, ++ { ++ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x76, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x66, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x55, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x22, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v8[] = { ++ { ++ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, ++ { ++ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, ++ { ++ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, ++ { ++ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, ++ { ++ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, ++ { ++ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, ++ { ++ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, ++ { ++ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, ++ { ++ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, ++ { ++ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, ++ { ++ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, ++ { ++ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, ++ { ++ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, ++ { ++ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, ++ { ++ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, ++ { ++ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, ++ { ++ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, ++ { ++ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, ++ { ++ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, ++ { ++ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, ++ { ++ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, ++ { ++ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, ++ { ++ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, ++ { ++ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, ++ { ++ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, ++ { ++ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, ++ { ++ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, ++ { ++ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, ++ { ++ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, ++ { ++ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, ++ { ++ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, ++ { ++ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, ++ { ++ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, ++ { ++ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, ++ { ++ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, ++ { ++ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, ++ { ++ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, ++ { ++ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, ++ { ++ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, ++ { ++ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, ++ { ++ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, ++ { ++ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, ++ { ++ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, ++ { ++ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, ++ { ++ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, ++ { ++ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, ++ { ++ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, ++ { ++ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, ++ { ++ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, ++ { ++ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, ++ { ++ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, ++ { ++ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, ++ { ++ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, ++ { ++ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, ++ { ++ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, ++ { ++ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, ++ { ++ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, ++ { ++ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, ++ { ++ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, ++ { ++ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, ++ { ++ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, ++ { ++ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, ++ { ++ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, ++ { ++ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, ++ { ++ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, ++ { ++ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, ++ { ++ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, ++ { ++ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, ++ { ++ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, ++ { ++ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, ++ { ++ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, ++ { ++ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, ++ { ++ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, ++ { ++ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, ++ { ++ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, ++ { ++ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, ++ { ++ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, ++ { ++ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, ++ { ++ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, ++ { ++ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, ++ { ++ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, ++ { ++ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, ++ { ++ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, ++ { ++ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, ++ { ++ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, ++ { ++ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, ++ { ++ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, ++ { ++ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, ++ { ++ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, ++ { ++ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, ++ { ++ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, ++ { ++ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, ++ { ++ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, ++ { ++ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, ++ { ++ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, ++ { ++ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, ++ { ++ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, ++ { ++ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, ++ { ++ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, ++ { ++ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, ++ { ++ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, ++ { ++ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v11[] = { ++ { ++ 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216}, ++ { ++ 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215}, ++ { ++ 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214}, ++ { ++ 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213}, ++ { ++ 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212}, ++ { ++ 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211}, ++ { ++ 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f}, ++ { ++ 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e}, ++ { ++ 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d}, ++ { ++ 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c}, ++ { ++ 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b}, ++ { ++ 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a}, ++ { ++ 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209}, ++ { ++ 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208}, ++ { ++ 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207}, ++ { ++ 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206}, ++ { ++ 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205}, ++ { ++ 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204}, ++ { ++ 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203}, ++ { ++ 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202}, ++ { ++ 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201}, ++ { ++ 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200}, ++ { ++ 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, ++ 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, ++ 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff}, ++ { ++ 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd}, ++ { ++ 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc}, ++ { ++ 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, ++ 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e, ++ 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb}, ++ { ++ 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa}, ++ { ++ 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9}, ++ { ++ 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8}, ++ { ++ 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7}, ++ { ++ 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6}, ++ { ++ 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5}, ++ { ++ 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4}, ++ { ++ 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, ++ 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d, ++ 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3}, ++ { ++ 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2}, ++ { ++ 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1}, ++ { ++ 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0}, ++ { ++ 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0}, ++ { ++ 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef}, ++ { ++ 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, ++ 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee}, ++ { ++ 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed}, ++ { ++ 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec}, ++ { ++ 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, ++ 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb}, ++ { ++ 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea}, ++ { ++ 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9}, ++ { ++ 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8}, ++ { ++ 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7}, ++ { ++ 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6}, ++ { ++ 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5}, ++ { ++ 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5}, ++ { ++ 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, ++ 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4}, ++ { ++ 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3}, ++ { ++ 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2}, ++ { ++ 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1}, ++ { ++ 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0}, ++ { ++ 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df}, ++ { ++ 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de}, ++ { ++ 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd}, ++ { ++ 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd}, ++ { ++ 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc}, ++ { ++ 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db}, ++ { ++ 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9}, ++ { ++ 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8}, ++ { ++ 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, ++ 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7}, ++ { ++ 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7}, ++ { ++ 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6}, ++ { ++ 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5}, ++ { ++ 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, ++ 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4}, ++ { ++ 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3}, ++ { ++ 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2}, ++ { ++ 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2}, ++ { ++ 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, ++ 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1}, ++ { ++ 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0}, ++ { ++ 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf}, ++ { ++ 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce}, ++ { ++ 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce}, ++ { ++ 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd}, ++ { ++ 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc}, ++ { ++ 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb}, ++ { ++ 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca}, ++ { ++ 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca}, ++ { ++ 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9}, ++ { ++ 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, ++ 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9}, ++ { ++ 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9}, ++ { ++ 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8}, ++ { ++ 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8}, ++ { ++ 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7}, ++ { ++ 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7}, ++ { ++ 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6}, ++ { ++ 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6}, ++ { ++ 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5}, ++ { ++ 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5}, ++ { ++ 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4}, ++ { ++ 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4}, ++ { ++ 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3}, ++ { ++ 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x05, 0x05, 0x02, 0x15, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3}, ++ { ++ 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, ++ 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2}, ++ { ++ 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2}, ++ { ++ 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1}, ++ { ++ 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0}, ++ { ++ 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf}, ++ { ++ 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf}, ++ { ++ 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be}, ++ { ++ 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd}, ++ { ++ 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x02, 0x0c, 0x01, ++ 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, ++ 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, ++ 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc}, ++ { ++ 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x06, 0x06, 0x04, 0x2b, 0x01, ++ 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, ++ 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, ++ 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio2057 chan_info_nphyrev7_2057_rev4[] = { ++ { ++ 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b4, 0x07b0, 0x07ac, 0x0214, ++ 0x0215, ++ 0x0216, ++ }, ++ { ++ 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b8, 0x07b4, 0x07b0, 0x0213, ++ 0x0214, ++ 0x0215, ++ }, ++ { ++ 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07bc, 0x07b8, 0x07b4, 0x0212, ++ 0x0213, ++ 0x0214, ++ }, ++ { ++ 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c0, 0x07bc, 0x07b8, 0x0211, ++ 0x0212, ++ 0x0213, ++ }, ++ { ++ 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c4, 0x07c0, 0x07bc, 0x020f, ++ 0x0211, ++ 0x0212, ++ }, ++ { ++ 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c8, 0x07c4, 0x07c0, 0x020e, ++ 0x020f, ++ 0x0211, ++ }, ++ { ++ 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07cc, 0x07c8, 0x07c4, 0x020d, ++ 0x020e, ++ 0x020f, ++ }, ++ { ++ 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d0, 0x07cc, 0x07c8, 0x020c, ++ 0x020d, ++ 0x020e, ++ }, ++ { ++ 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d4, 0x07d0, 0x07cc, 0x020b, ++ 0x020c, ++ 0x020d, ++ }, ++ { ++ 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d8, 0x07d4, 0x07d0, 0x020a, ++ 0x020b, ++ 0x020c, ++ }, ++ { ++ 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07dc, 0x07d8, 0x07d4, 0x0209, ++ 0x020a, ++ 0x020b, ++ }, ++ { ++ 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e0, 0x07dc, 0x07d8, 0x0208, ++ 0x0209, ++ 0x020a, ++ }, ++ { ++ 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e4, 0x07e0, 0x07dc, 0x0207, ++ 0x0208, ++ 0x0209, ++ }, ++ { ++ 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e8, 0x07e4, 0x07e0, 0x0206, ++ 0x0207, ++ 0x0208, ++ }, ++ { ++ 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x00, ++ 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x07ec, 0x07e8, 0x07e4, 0x0205, ++ 0x0206, ++ 0x0207, ++ }, ++ { ++ 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00, ++ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f0, 0x07ec, 0x07e8, 0x0204, ++ 0x0205, ++ 0x0206, ++ }, ++ { ++ 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00, ++ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f4, 0x07f0, 0x07ec, 0x0203, ++ 0x0204, ++ 0x0205, ++ }, ++ { ++ 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07f8, 0x07f4, 0x07f0, 0x0202, ++ 0x0203, ++ 0x0204, ++ }, ++ { ++ 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07fc, 0x07f8, 0x07f4, 0x0201, ++ 0x0202, ++ 0x0203, ++ }, ++ { ++ 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0800, 0x07fc, 0x07f8, 0x0200, ++ 0x0201, ++ 0x0202, ++ }, ++ { ++ 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0804, 0x0800, 0x07fc, 0x01ff, ++ 0x0200, ++ 0x0201, ++ }, ++ { ++ 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0808, 0x0804, 0x0800, 0x01fe, ++ 0x01ff, ++ 0x0200, ++ }, ++ { ++ 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x080c, 0x0808, 0x0804, 0x01fd, ++ 0x01fe, ++ 0x01ff, ++ }, ++ { ++ 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0814, 0x0810, 0x080c, 0x01fb, ++ 0x01fc, ++ 0x01fd, ++ }, ++ { ++ 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0818, 0x0814, 0x0810, 0x01fa, ++ 0x01fb, ++ 0x01fc, ++ }, ++ { ++ 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x081c, 0x0818, 0x0814, 0x01f9, ++ 0x01fa, ++ 0x01fb, ++ }, ++ { ++ 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0820, 0x081c, 0x0818, 0x01f8, ++ 0x01f9, ++ 0x01fa, ++ }, ++ { ++ 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0824, 0x0820, 0x081c, 0x01f7, ++ 0x01f8, ++ 0x01f9, ++ }, ++ { ++ 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0828, 0x0824, 0x0820, 0x01f6, ++ 0x01f7, ++ 0x01f8, ++ }, ++ { ++ 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x082c, 0x0828, 0x0824, 0x01f5, ++ 0x01f6, ++ 0x01f7, ++ }, ++ { ++ 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0830, 0x082c, 0x0828, 0x01f4, ++ 0x01f5, ++ 0x01f6, ++ }, ++ { ++ 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0834, 0x0830, 0x082c, 0x01f3, ++ 0x01f4, ++ 0x01f5, ++ }, ++ { ++ 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0838, 0x0834, 0x0830, 0x01f2, ++ 0x01f3, ++ 0x01f4, ++ }, ++ { ++ 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x083c, 0x0838, 0x0834, 0x01f1, ++ 0x01f2, ++ 0x01f3, ++ }, ++ { ++ 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00, ++ 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x0840, 0x083c, 0x0838, 0x01f0, ++ 0x01f1, ++ 0x01f2, ++ }, ++ { ++ 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00, ++ 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0844, 0x0840, 0x083c, 0x01f0, ++ 0x01f0, ++ 0x01f1, ++ }, ++ { ++ 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00, ++ 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0848, 0x0844, 0x0840, 0x01ef, ++ 0x01f0, ++ 0x01f0, ++ }, ++ { ++ 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00, ++ 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x084c, 0x0848, 0x0844, 0x01ee, ++ 0x01ef, ++ 0x01f0, ++ }, ++ { ++ 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00, ++ 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0850, 0x084c, 0x0848, 0x01ed, ++ 0x01ee, ++ 0x01ef, ++ }, ++ { ++ 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00, ++ 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0854, 0x0850, 0x084c, 0x01ec, ++ 0x01ed, ++ 0x01ee, ++ }, ++ { ++ 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00, ++ 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0858, 0x0854, 0x0850, 0x01eb, ++ 0x01ec, ++ 0x01ed, ++ }, ++ { ++ 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x00, ++ 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x085c, 0x0858, 0x0854, 0x01ea, ++ 0x01eb, ++ 0x01ec, ++ }, ++ { ++ 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00, ++ 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0860, 0x085c, 0x0858, 0x01e9, ++ 0x01ea, ++ 0x01eb, ++ }, ++ { ++ 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00, ++ 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0864, 0x0860, 0x085c, 0x01e8, ++ 0x01e9, ++ 0x01ea, ++ }, ++ { ++ 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00, ++ 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0868, 0x0864, 0x0860, 0x01e7, ++ 0x01e8, ++ 0x01e9, ++ }, ++ { ++ 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00, ++ 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x086c, 0x0868, 0x0864, 0x01e6, ++ 0x01e7, ++ 0x01e8, ++ }, ++ { ++ 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x00, ++ 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x0870, 0x086c, 0x0868, 0x01e5, ++ 0x01e6, ++ 0x01e7, ++ }, ++ { ++ 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00, ++ 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0874, 0x0870, 0x086c, 0x01e5, ++ 0x01e5, ++ 0x01e6, ++ }, ++ { ++ 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00, ++ 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0878, 0x0874, 0x0870, 0x01e4, ++ 0x01e5, ++ 0x01e5, ++ }, ++ { ++ 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x00, ++ 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x087c, 0x0878, 0x0874, 0x01e3, ++ 0x01e4, ++ 0x01e5, ++ }, ++ { ++ 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00, ++ 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0880, 0x087c, 0x0878, 0x01e2, ++ 0x01e3, ++ 0x01e4, ++ }, ++ { ++ 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00, ++ 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0884, 0x0880, 0x087c, 0x01e1, ++ 0x01e2, ++ 0x01e3, ++ }, ++ { ++ 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00, ++ 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0888, 0x0884, 0x0880, 0x01e0, ++ 0x01e1, ++ 0x01e2, ++ }, ++ { ++ 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x00, ++ 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x088c, 0x0888, 0x0884, 0x01df, ++ 0x01e0, ++ 0x01e1, ++ }, ++ { ++ 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x0890, 0x088c, 0x0888, 0x01de, ++ 0x01df, ++ 0x01e0, ++ }, ++ { ++ 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0894, 0x0890, 0x088c, 0x01dd, ++ 0x01de, ++ 0x01df, ++ }, ++ { ++ 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0898, 0x0894, 0x0890, 0x01dd, ++ 0x01dd, ++ 0x01de, ++ }, ++ { ++ 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x089c, 0x0898, 0x0894, 0x01dc, ++ 0x01dd, ++ 0x01dd, ++ }, ++ { ++ 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x08a0, 0x089c, 0x0898, 0x01db, ++ 0x01dc, ++ 0x01dd, ++ }, ++ { ++ 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a4, 0x08a0, 0x089c, 0x01da, ++ 0x01db, ++ 0x01dc, ++ }, ++ { ++ 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a8, 0x08a4, 0x08a0, 0x01d9, ++ 0x01da, ++ 0x01db, ++ }, ++ { ++ 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08ac, 0x08a8, 0x08a4, 0x01d8, ++ 0x01d9, ++ 0x01da, ++ }, ++ { ++ 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b0, 0x08ac, 0x08a8, 0x01d7, ++ 0x01d8, ++ 0x01d9, ++ }, ++ { ++ 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b4, 0x08b0, 0x08ac, 0x01d7, ++ 0x01d7, ++ 0x01d8, ++ }, ++ { ++ 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00, ++ 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b8, 0x08b4, 0x08b0, 0x01d6, ++ 0x01d7, ++ 0x01d7, ++ }, ++ { ++ 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x00, ++ 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x08bc, 0x08b8, 0x08b4, 0x01d5, ++ 0x01d6, ++ 0x01d7, ++ }, ++ { ++ 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x00, ++ 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x08c0, 0x08bc, 0x08b8, 0x01d4, ++ 0x01d5, ++ 0x01d6, ++ }, ++ { ++ 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x00, ++ 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x08c4, 0x08c0, 0x08bc, 0x01d3, ++ 0x01d4, ++ 0x01d5, ++ }, ++ { ++ 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00, ++ 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08c8, 0x08c4, 0x08c0, 0x01d2, ++ 0x01d3, ++ 0x01d4, ++ }, ++ { ++ 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00, ++ 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08cc, 0x08c8, 0x08c4, 0x01d2, ++ 0x01d2, ++ 0x01d3, ++ }, ++ { ++ 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00, ++ 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d0, 0x08cc, 0x08c8, 0x01d1, ++ 0x01d2, ++ 0x01d2, ++ }, ++ { ++ 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00, ++ 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d4, 0x08d0, 0x08cc, 0x01d0, ++ 0x01d1, ++ 0x01d2, ++ }, ++ { ++ 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00, ++ 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08d8, 0x08d4, 0x08d0, 0x01cf, ++ 0x01d0, ++ 0x01d1, ++ }, ++ { ++ 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00, ++ 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08dc, 0x08d8, 0x08d4, 0x01ce, ++ 0x01cf, ++ 0x01d0, ++ }, ++ { ++ 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x00, ++ 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, ++ 0x01ce, ++ 0x01cf, ++ }, ++ { ++ 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, ++ 0x01ce, ++ 0x01ce, ++ }, ++ { ++ 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, ++ 0x01cd, ++ 0x01ce, ++ }, ++ { ++ 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, ++ 0x01cc, ++ 0x01cd, ++ }, ++ { ++ 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, ++ 0x01cb, ++ 0x01cc, ++ }, ++ { ++ 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, ++ 0x01ca, ++ 0x01cb, ++ }, ++ { ++ 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, ++ 0x01ca, ++ 0x01cb, ++ }, ++ { ++ 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, ++ 0x01c9, ++ 0x01ca, ++ }, ++ { ++ 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, ++ 0x01c9, ++ 0x01ca, ++ }, ++ { ++ 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, ++ 0x01c9, ++ 0x01c9, ++ }, ++ { ++ 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, ++ 0x01c8, ++ 0x01c9, ++ }, ++ { ++ 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, ++ 0x01c8, ++ 0x01c9, ++ }, ++ { ++ 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, ++ 0x01c8, ++ 0x01c8, ++ }, ++ { ++ 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, ++ 0x01c7, ++ 0x01c8, ++ }, ++ { ++ 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, ++ 0x01c7, ++ 0x01c8, ++ }, ++ { ++ 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, ++ 0x01c6, ++ 0x01c7, ++ }, ++ { ++ 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, ++ 0x01c6, ++ 0x01c7, ++ }, ++ { ++ 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, ++ 0x01c6, ++ 0x01c6, ++ }, ++ { ++ 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, ++ 0x01c5, ++ 0x01c6, ++ }, ++ { ++ 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, ++ 0x01c5, ++ 0x01c6, ++ }, ++ { ++ 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, ++ 0x01c4, ++ 0x01c5, ++ }, ++ { ++ 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, ++ 0x01c4, ++ 0x01c5, ++ }, ++ { ++ 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, ++ 0x01c4, ++ 0x01c4, ++ }, ++ { ++ 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, ++ 0x01c3, ++ 0x01c4, ++ }, ++ { ++ 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, ++ 0x01c3, ++ 0x01c4, ++ }, ++ { ++ 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, ++ 0x01c2, ++ 0x01c3, ++ }, ++ { ++ 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, ++ 0x01c2, ++ 0x01c3, ++ }, ++ { ++ 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, ++ 0x01c2, ++ 0x01c2, ++ }, ++ { ++ 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, ++ 0x01c1, ++ 0x01c2, ++ }, ++ { ++ 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, ++ 0x01c0, ++ 0x01c1, ++ }, ++ { ++ 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, ++ 0x01bf, ++ 0x01c0, ++ }, ++ { ++ 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, ++ 0x01bf, ++ 0x01bf, ++ }, ++ { ++ 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, ++ 0x01be, ++ 0x01bf, ++ }, ++ { ++ 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, ++ 0x01bd, ++ 0x01be, ++ }, ++ { ++ 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00, ++ 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, ++ 0x01bc, ++ 0x01bd, ++ }, ++ { ++ 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f, ++ 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71, ++ 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a, ++ 0x043f, ++ 0x0443, ++ }, ++ { ++ 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f, ++ 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71, ++ 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438, ++ 0x043d, ++ 0x0441, ++ }, ++ { ++ 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f, ++ 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71, ++ 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436, ++ 0x043a, ++ 0x043f, ++ }, ++ { ++ 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f, ++ 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71, ++ 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434, ++ 0x0438, ++ 0x043d, ++ }, ++ { ++ 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f, ++ 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51, ++ 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431, ++ 0x0436, ++ 0x043a, ++ }, ++ { ++ 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f, ++ 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51, ++ 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f, ++ 0x0434, ++ 0x0438, ++ }, ++ { ++ 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x51, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d, ++ 0x0431, ++ 0x0436, ++ }, ++ { ++ 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b, ++ 0x042f, ++ 0x0434, ++ }, ++ { ++ 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429, ++ 0x042d, ++ 0x0431, ++ }, ++ { ++ 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f, ++ 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31, ++ 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427, ++ 0x042b, ++ 0x042f, ++ }, ++ { ++ 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f, ++ 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31, ++ 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424, ++ 0x0429, ++ 0x042d, ++ }, ++ { ++ 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f, ++ 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11, ++ 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422, ++ 0x0427, ++ 0x042b, ++ }, ++ { ++ 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f, ++ 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11, ++ 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420, ++ 0x0424, ++ 0x0429, ++ }, ++ { ++ 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f, ++ 0x04, 0x00, 0x04, 0x00, 0x11, 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x11, ++ 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b, ++ 0x041f, ++ 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio2057_rev5 ++chan_info_nphyrev8_2057_rev5[] = { ++ { ++ 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d, ++ 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1, ++ 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d, ++ 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3, ++ 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d, ++ 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5, ++ 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c, ++ 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7, ++ 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c, ++ 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9, ++ 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c, ++ 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb, ++ 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b, ++ 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd, ++ 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b, ++ 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf, ++ 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b, ++ 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1, ++ 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b, ++ 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3, ++ 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b, ++ 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5, ++ 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b, ++ 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7, ++ 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a, ++ 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9, ++ 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a, ++ 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de, ++ 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio2057_rev5 ++chan_info_nphyrev9_2057_rev5v1[] = { ++ { ++ 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d, ++ 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1, ++ 0x043a, 0x043f, 0x0443}, ++ { ++ 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d, ++ 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3, ++ 0x0438, 0x043d, 0x0441}, ++ { ++ 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d, ++ 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5, ++ 0x0436, 0x043a, 0x043f}, ++ { ++ 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c, ++ 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7, ++ 0x0434, 0x0438, 0x043d}, ++ { ++ 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c, ++ 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9, ++ 0x0431, 0x0436, 0x043a}, ++ { ++ 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c, ++ 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb, ++ 0x042f, 0x0434, 0x0438}, ++ { ++ 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b, ++ 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd, ++ 0x042d, 0x0431, 0x0436}, ++ { ++ 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b, ++ 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf, ++ 0x042b, 0x042f, 0x0434}, ++ { ++ 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b, ++ 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1, ++ 0x0429, 0x042d, 0x0431}, ++ { ++ 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b, ++ 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3, ++ 0x0427, 0x042b, 0x042f}, ++ { ++ 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b, ++ 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5, ++ 0x0424, 0x0429, 0x042d}, ++ { ++ 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b, ++ 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7, ++ 0x0422, 0x0427, 0x042b}, ++ { ++ 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a, ++ 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9, ++ 0x0420, 0x0424, 0x0429}, ++ { ++ 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a, ++ 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de, ++ 0x041b, 0x041f, 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev7[] = { ++ { ++ 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b4, 0x07b0, 0x07ac, 0x0214, ++ 0x0215, ++ 0x0216}, ++ { ++ 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213, ++ 0x0214, ++ 0x0215}, ++ { ++ 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212, ++ 0x0213, ++ 0x0214}, ++ { ++ 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211, ++ 0x0212, ++ 0x0213}, ++ { ++ 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f, ++ 0x0211, ++ 0x0212}, ++ { ++ 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e, ++ 0x020f, ++ 0x0211}, ++ { ++ 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d, ++ 0x020e, ++ 0x020f}, ++ { ++ 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c, ++ 0x020d, ++ 0x020e}, ++ { ++ 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b, ++ 0x020c, ++ 0x020d}, ++ { ++ 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a, ++ 0x020b, ++ 0x020c}, ++ { ++ 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209, ++ 0x020a, ++ 0x020b}, ++ { ++ 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208, ++ 0x0209, ++ 0x020a}, ++ { ++ 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207, ++ 0x0208, ++ 0x0209}, ++ { ++ 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206, ++ 0x0207, ++ 0x0208}, ++ { ++ 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205, ++ 0x0206, ++ 0x0207}, ++ { ++ 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204, ++ 0x0205, ++ 0x0206}, ++ { ++ 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203, ++ 0x0204, ++ 0x0205}, ++ { ++ 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202, ++ 0x0203, ++ 0x0204}, ++ { ++ 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201, ++ 0x0202, ++ 0x0203}, ++ { ++ 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200, ++ 0x0201, ++ 0x0202}, ++ { ++ 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff, ++ 0x0200, ++ 0x0201}, ++ { ++ 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe, ++ 0x01ff, ++ 0x0200}, ++ { ++ 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd, ++ 0x01fe, ++ 0x01ff}, ++ { ++ 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb, ++ 0x01fc, ++ 0x01fd}, ++ { ++ 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa, ++ 0x01fb, ++ 0x01fc}, ++ { ++ 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9, ++ 0x01fa, ++ 0x01fb}, ++ { ++ 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8, ++ 0x01f9, ++ 0x01fa}, ++ { ++ 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7, ++ 0x01f8, ++ 0x01f9}, ++ { ++ 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6, ++ 0x01f7, ++ 0x01f8}, ++ { ++ 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5, ++ 0x01f6, ++ 0x01f7}, ++ { ++ 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4, ++ 0x01f5, ++ 0x01f6}, ++ { ++ 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3, ++ 0x01f4, ++ 0x01f5}, ++ { ++ 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2, ++ 0x01f3, ++ 0x01f4}, ++ { ++ 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1, ++ 0x01f2, ++ 0x01f3}, ++ { ++ 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0, ++ 0x01f1, ++ 0x01f2}, ++ { ++ 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0, ++ 0x01f0, ++ 0x01f1}, ++ { ++ 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef, ++ 0x01f0, ++ 0x01f0}, ++ { ++ 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee, ++ 0x01ef, ++ 0x01f0}, ++ { ++ 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed, ++ 0x01ee, ++ 0x01ef}, ++ { ++ 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec, ++ 0x01ed, ++ 0x01ee}, ++ { ++ 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb, ++ 0x01ec, ++ 0x01ed}, ++ { ++ 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea, ++ 0x01eb, ++ 0x01ec}, ++ { ++ 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9, ++ 0x01ea, ++ 0x01eb}, ++ { ++ 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8, ++ 0x01e9, ++ 0x01ea}, ++ { ++ 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7, ++ 0x01e8, ++ 0x01e9}, ++ { ++ 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6, ++ 0x01e7, ++ 0x01e8}, ++ { ++ 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5, ++ 0x01e6, ++ 0x01e7}, ++ { ++ 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5, ++ 0x01e5, ++ 0x01e6}, ++ { ++ 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4, ++ 0x01e5, ++ 0x01e5}, ++ { ++ 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3, ++ 0x01e4, ++ 0x01e5}, ++ { ++ 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2, ++ 0x01e3, ++ 0x01e4}, ++ { ++ 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1, ++ 0x01e2, ++ 0x01e3}, ++ { ++ 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0, ++ 0x01e1, ++ 0x01e2}, ++ { ++ 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df, ++ 0x01e0, ++ 0x01e1}, ++ { ++ 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de, ++ 0x01df, ++ 0x01e0}, ++ { ++ 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd, ++ 0x01de, ++ 0x01df}, ++ { ++ 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd, ++ 0x01dd, ++ 0x01de}, ++ { ++ 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc, ++ 0x01dd, ++ 0x01dd}, ++ { ++ 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db, ++ 0x01dc, ++ 0x01dd}, ++ { ++ 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da, ++ 0x01db, ++ 0x01dc}, ++ { ++ 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9, ++ 0x01da, ++ 0x01db}, ++ { ++ 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8, ++ 0x01d9, ++ 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7, ++ 0x01d8, ++ 0x01d9}, ++ { ++ 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7, ++ 0x01d7, ++ 0x01d8}, ++ { ++ 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6, ++ 0x01d7, ++ 0x01d7}, ++ { ++ 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5, ++ 0x01d6, ++ 0x01d7}, ++ { ++ 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4, ++ 0x01d5, ++ 0x01d6}, ++ { ++ 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3, ++ 0x01d4, ++ 0x01d5}, ++ { ++ 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2, ++ 0x01d3, ++ 0x01d4}, ++ { ++ 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2, ++ 0x01d2, ++ 0x01d3}, ++ { ++ 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1, ++ 0x01d2, ++ 0x01d2}, ++ { ++ 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0, ++ 0x01d1, ++ 0x01d2}, ++ { ++ 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf, ++ 0x01d0, ++ 0x01d1}, ++ { ++ 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce, ++ 0x01cf, ++ 0x01d0}, ++ { ++ 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce, ++ 0x01ce, ++ 0x01cf}, ++ { ++ 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd, ++ 0x01ce, ++ 0x01ce}, ++ { ++ 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc, ++ 0x01cd, ++ 0x01ce}, ++ { ++ 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb, ++ 0x01cc, ++ 0x01cd}, ++ { ++ 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca, ++ 0x01cb, ++ 0x01cc}, ++ { ++ 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9, ++ 0x01ca, ++ 0x01cb}, ++ { ++ 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9, ++ 0x01ca, ++ 0x01cb}, ++ { ++ 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9, ++ 0x01c9, ++ 0x01ca}, ++ { ++ 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8, ++ 0x01c9, ++ 0x01ca}, ++ { ++ 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8, ++ 0x01c9, ++ 0x01c9}, ++ { ++ 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8, ++ 0x01c8, ++ 0x01c9}, ++ { ++ 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, ++ 0x01c8, ++ 0x01c9}, ++ { ++ 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, ++ 0x01c8, ++ 0x01c8}, ++ { ++ 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, ++ 0x01c7, ++ 0x01c8}, ++ { ++ 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, ++ 0x01c7, ++ 0x01c8}, ++ { ++ 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, ++ 0x01c6, ++ 0x01c7}, ++ { ++ 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, ++ 0x01c6, ++ 0x01c7}, ++ { ++ 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, ++ 0x01c6, ++ 0x01c6}, ++ { ++ 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, ++ 0x01c5, ++ 0x01c6}, ++ { ++ 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, ++ 0x01c5, ++ 0x01c6}, ++ { ++ 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, ++ 0x01c4, ++ 0x01c5}, ++ { ++ 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, ++ 0x01c4, ++ 0x01c5}, ++ { ++ 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, ++ 0x01c4, ++ 0x01c4}, ++ { ++ 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, ++ 0x01c3, ++ 0x01c4}, ++ { ++ 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, ++ 0x01c3, ++ 0x01c4}, ++ { ++ 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, ++ 0x01c2, ++ 0x01c3}, ++ { ++ 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, ++ 0x01c2, ++ 0x01c3}, ++ { ++ 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, ++ 0x01c2, ++ 0x01c2}, ++ { ++ 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, ++ 0x01c1, ++ 0x01c2}, ++ { ++ 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, ++ 0x01c0, ++ 0x01c1}, ++ { ++ 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, ++ 0x01bf, ++ 0x01c0}, ++ { ++ 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, ++ 0x01bf, ++ 0x01bf}, ++ { ++ 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, ++ 0x01be, ++ 0x01bf}, ++ { ++ 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, ++ 0x01bd, ++ 0x01be}, ++ { ++ 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, ++ 0x01bc, ++ 0x01bd}, ++ { ++ 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f, ++ 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a, ++ 0x043f, ++ 0x0443}, ++ { ++ 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f, ++ 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438, ++ 0x043d, ++ 0x0441}, ++ { ++ 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f, ++ 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436, ++ 0x043a, ++ 0x043f}, ++ { ++ 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f, ++ 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434, ++ 0x0438, ++ 0x043d}, ++ { ++ 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f, ++ 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431, ++ 0x0436, ++ 0x043a}, ++ { ++ 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f, ++ 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f, ++ 0x0434, ++ 0x0438}, ++ { ++ 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d, ++ 0x0431, ++ 0x0436}, ++ { ++ 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b, ++ 0x042f, ++ 0x0434}, ++ { ++ 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429, ++ 0x042d, ++ 0x0431}, ++ { ++ 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f, ++ 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427, ++ 0x042b, ++ 0x042f}, ++ { ++ 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f, ++ 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424, ++ 0x0429, ++ 0x042d}, ++ { ++ 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f, ++ 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422, ++ 0x0427, ++ 0x042b}, ++ { ++ 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f, ++ 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420, ++ 0x0424, ++ 0x0429}, ++ { ++ 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f, ++ 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b, ++ 0x041f, ++ 0x0424} ++}; ++ ++static const struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev8[] = { ++ { ++ 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213, ++ 0x0214, ++ 0x0215}, ++ { ++ 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212, ++ 0x0213, ++ 0x0214}, ++ { ++ 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211, ++ 0x0212, ++ 0x0213}, ++ { ++ 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f, ++ 0x0211, ++ 0x0212}, ++ { ++ 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e, ++ 0x020f, ++ 0x0211}, ++ { ++ 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d, ++ 0x020e, ++ 0x020f}, ++ { ++ 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c, ++ 0x020d, ++ 0x020e}, ++ { ++ 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b, ++ 0x020c, ++ 0x020d}, ++ { ++ 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f, ++ 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a, ++ 0x020b, ++ 0x020c}, ++ { ++ 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209, ++ 0x020a, ++ 0x020b}, ++ { ++ 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208, ++ 0x0209, ++ 0x020a}, ++ { ++ 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207, ++ 0x0208, ++ 0x0209}, ++ { ++ 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206, ++ 0x0207, ++ 0x0208}, ++ { ++ 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205, ++ 0x0206, ++ 0x0207}, ++ { ++ 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204, ++ 0x0205, ++ 0x0206}, ++ { ++ 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203, ++ 0x0204, ++ 0x0205}, ++ { ++ 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e, ++ 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00, ++ 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202, ++ 0x0203, ++ 0x0204}, ++ { ++ 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201, ++ 0x0202, ++ 0x0203}, ++ { ++ 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200, ++ 0x0201, ++ 0x0202}, ++ { ++ 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff, ++ 0x0200, ++ 0x0201}, ++ { ++ 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe, ++ 0x01ff, ++ 0x0200}, ++ { ++ 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd, ++ 0x01fe, ++ 0x01ff}, ++ { ++ 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb, ++ 0x01fc, ++ 0x01fd}, ++ { ++ 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d, ++ 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa, ++ 0x01fb, ++ 0x01fc}, ++ { ++ 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9, ++ 0x01fa, ++ 0x01fb}, ++ { ++ 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00, ++ 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8, ++ 0x01f9, ++ 0x01fa}, ++ { ++ 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7, ++ 0x01f8, ++ 0x01f9}, ++ { ++ 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6, ++ 0x01f7, ++ 0x01f8}, ++ { ++ 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5, ++ 0x01f6, ++ 0x01f7}, ++ { ++ 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4, ++ 0x01f5, ++ 0x01f6}, ++ { ++ 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3, ++ 0x01f4, ++ 0x01f5}, ++ { ++ 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c, ++ 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2, ++ 0x01f3, ++ 0x01f4}, ++ { ++ 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1, ++ 0x01f2, ++ 0x01f3}, ++ { ++ 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0, ++ 0x01f1, ++ 0x01f2}, ++ { ++ 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0, ++ 0x01f0, ++ 0x01f1}, ++ { ++ 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00, ++ 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef, ++ 0x01f0, ++ 0x01f0}, ++ { ++ 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee, ++ 0x01ef, ++ 0x01f0}, ++ { ++ 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed, ++ 0x01ee, ++ 0x01ef}, ++ { ++ 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec, ++ 0x01ed, ++ 0x01ee}, ++ { ++ 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b, ++ 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb, ++ 0x01ec, ++ 0x01ed}, ++ { ++ 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea, ++ 0x01eb, ++ 0x01ec}, ++ { ++ 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9, ++ 0x01ea, ++ 0x01eb}, ++ { ++ 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8, ++ 0x01e9, ++ 0x01ea}, ++ { ++ 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7, ++ 0x01e8, ++ 0x01e9}, ++ { ++ 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6, ++ 0x01e7, ++ 0x01e8}, ++ { ++ 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00, ++ 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5, ++ 0x01e6, ++ 0x01e7}, ++ { ++ 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5, ++ 0x01e5, ++ 0x01e6}, ++ { ++ 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a, ++ 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4, ++ 0x01e5, ++ 0x01e5}, ++ { ++ 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3, ++ 0x01e4, ++ 0x01e5}, ++ { ++ 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2, ++ 0x01e3, ++ 0x01e4}, ++ { ++ 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1, ++ 0x01e2, ++ 0x01e3}, ++ { ++ 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0, ++ 0x01e1, ++ 0x01e2}, ++ { ++ 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df, ++ 0x01e0, ++ 0x01e1}, ++ { ++ 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de, ++ 0x01df, ++ 0x01e0}, ++ { ++ 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd, ++ 0x01de, ++ 0x01df}, ++ { ++ 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00, ++ 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd, ++ 0x01dd, ++ 0x01de}, ++ { ++ 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc, ++ 0x01dd, ++ 0x01dd}, ++ { ++ 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09, ++ 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db, ++ 0x01dc, ++ 0x01dd}, ++ { ++ 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da, ++ 0x01db, ++ 0x01dc}, ++ { ++ 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9, ++ 0x01da, ++ 0x01db}, ++ { ++ 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8, ++ 0x01d9, ++ 0x01da}, ++ { ++ 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7, ++ 0x01d8, ++ 0x01d9}, ++ { ++ 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7, ++ 0x01d7, ++ 0x01d8}, ++ { ++ 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6, ++ 0x01d7, ++ 0x01d7}, ++ { ++ 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5, ++ 0x01d6, ++ 0x01d7}, ++ { ++ 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00, ++ 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4, ++ 0x01d5, ++ 0x01d6}, ++ { ++ 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3, ++ 0x01d4, ++ 0x01d5}, ++ { ++ 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08, ++ 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2, ++ 0x01d3, ++ 0x01d4}, ++ { ++ 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2, ++ 0x01d2, ++ 0x01d3}, ++ { ++ 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1, ++ 0x01d2, ++ 0x01d2}, ++ { ++ 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0, ++ 0x01d1, ++ 0x01d2}, ++ { ++ 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf, ++ 0x01d0, ++ 0x01d1}, ++ { ++ 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce, ++ 0x01cf, ++ 0x01d0}, ++ { ++ 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce, ++ 0x01ce, ++ 0x01cf}, ++ { ++ 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd, ++ 0x01ce, ++ 0x01ce}, ++ { ++ 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00, ++ 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc, ++ 0x01cd, ++ 0x01ce}, ++ { ++ 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb, ++ 0x01cc, ++ 0x01cd}, ++ { ++ 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca, ++ 0x01cb, ++ 0x01cc}, ++ { ++ 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07, ++ 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9, ++ 0x01ca, ++ 0x01cb}, ++ { ++ 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9, ++ 0x01ca, ++ 0x01cb}, ++ { ++ 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9, ++ 0x01c9, ++ 0x01ca}, ++ { ++ 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8, ++ 0x01c9, ++ 0x01ca}, ++ { ++ 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8, ++ 0x01c9, ++ 0x01c9}, ++ { ++ 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8, ++ 0x01c8, ++ 0x01c9}, ++ { ++ 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, ++ 0x01c8, ++ 0x01c9}, ++ { ++ 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, ++ 0x01c8, ++ 0x01c8}, ++ { ++ 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, ++ 0x01c7, ++ 0x01c8}, ++ { ++ 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, ++ 0x01c7, ++ 0x01c8}, ++ { ++ 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, ++ 0x01c6, ++ 0x01c7}, ++ { ++ 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, ++ 0x01c6, ++ 0x01c7}, ++ { ++ 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06, ++ 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, ++ 0x01c6, ++ 0x01c6}, ++ { ++ 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, ++ 0x01c5, ++ 0x01c6}, ++ { ++ 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, ++ 0x01c5, ++ 0x01c6}, ++ { ++ 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, ++ 0x01c4, ++ 0x01c5}, ++ { ++ 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, ++ 0x01c4, ++ 0x01c5}, ++ { ++ 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, ++ 0x01c4, ++ 0x01c4}, ++ { ++ 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, ++ 0x01c3, ++ 0x01c4}, ++ { ++ 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, ++ 0x01c3, ++ 0x01c4}, ++ { ++ 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, ++ 0x01c2, ++ 0x01c3}, ++ { ++ 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, ++ 0x01c2, ++ 0x01c3}, ++ { ++ 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, ++ 0x01c2, ++ 0x01c2}, ++ { ++ 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05, ++ 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, ++ 0x01c1, ++ 0x01c2}, ++ { ++ 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, ++ 0x01c0, ++ 0x01c1}, ++ { ++ 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, ++ 0x01bf, ++ 0x01c0}, ++ { ++ 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04, ++ 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, ++ 0x01bf, ++ 0x01bf}, ++ { ++ 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, ++ 0x01be, ++ 0x01bf}, ++ { ++ 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, ++ 0x01bd, ++ 0x01be}, ++ { ++ 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03, ++ 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, ++ 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, ++ 0x01bc, ++ 0x01bd}, ++ { ++ 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f, ++ 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a, ++ 0x043f, ++ 0x0443}, ++ { ++ 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f, ++ 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438, ++ 0x043d, ++ 0x0441}, ++ { ++ 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f, ++ 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436, ++ 0x043a, ++ 0x043f}, ++ { ++ 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f, ++ 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434, ++ 0x0438, ++ 0x043d}, ++ { ++ 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f, ++ 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431, ++ 0x0436, ++ 0x043a}, ++ { ++ 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f, ++ 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f, ++ 0x0434, ++ 0x0438}, ++ { ++ 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d, ++ 0x0431, ++ 0x0436}, ++ { ++ 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b, ++ 0x042f, ++ 0x0434}, ++ { ++ 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f, ++ 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429, ++ 0x042d, ++ 0x0431}, ++ { ++ 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f, ++ 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427, ++ 0x042b, ++ 0x042f}, ++ { ++ 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f, ++ 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424, ++ 0x0429, ++ 0x042d}, ++ { ++ 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f, ++ 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422, ++ 0x0427, ++ 0x042b}, ++ { ++ 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f, ++ 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420, ++ 0x0424, ++ 0x0429}, ++ { ++ 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f, ++ 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61, ++ 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b, ++ 0x041f, ++ 0x0424} ++}; ++ ++static struct radio_regs regs_2055[] = { ++ {0x02, 0x80, 0x80, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0x27, 0x27, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0x27, 0x27, 0, 0}, ++ {0x07, 0x7f, 0x7f, 1, 1}, ++ {0x08, 0x7, 0x7, 1, 1}, ++ {0x09, 0x7f, 0x7f, 1, 1}, ++ {0x0A, 0x7, 0x7, 1, 1}, ++ {0x0B, 0x15, 0x15, 0, 0}, ++ {0x0C, 0x15, 0x15, 0, 0}, ++ {0x0D, 0x4f, 0x4f, 1, 1}, ++ {0x0E, 0x5, 0x5, 1, 1}, ++ {0x0F, 0x4f, 0x4f, 1, 1}, ++ {0x10, 0x5, 0x5, 1, 1}, ++ {0x11, 0xd0, 0xd0, 0, 0}, ++ {0x12, 0x2, 0x2, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0x40, 0x40, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0xc0, 0xc0, 0, 0}, ++ {0x1E, 0xff, 0xff, 0, 0}, ++ {0x1F, 0xc0, 0xc0, 0, 0}, ++ {0x20, 0xff, 0xff, 0, 0}, ++ {0x21, 0xc0, 0xc0, 0, 0}, ++ {0x22, 0, 0, 0, 0}, ++ {0x23, 0x2c, 0x2c, 0, 0}, ++ {0x24, 0, 0, 0, 0}, ++ {0x25, 0, 0, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0, 0, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0, 0, 0, 0}, ++ {0x2A, 0, 0, 0, 0}, ++ {0x2B, 0, 0, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0xa4, 0xa4, 0, 0}, ++ {0x2E, 0x38, 0x38, 0, 0}, ++ {0x2F, 0, 0, 0, 0}, ++ {0x30, 0x4, 0x4, 1, 1}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0xa, 0xa, 0, 0}, ++ {0x33, 0x87, 0x87, 0, 0}, ++ {0x34, 0x9, 0x9, 0, 0}, ++ {0x35, 0x70, 0x70, 0, 0}, ++ {0x36, 0x11, 0x11, 0, 0}, ++ {0x37, 0x18, 0x18, 1, 1}, ++ {0x38, 0x6, 0x6, 0, 0}, ++ {0x39, 0x4, 0x4, 1, 1}, ++ {0x3A, 0x6, 0x6, 0, 0}, ++ {0x3B, 0x9e, 0x9e, 0, 0}, ++ {0x3C, 0x9, 0x9, 0, 0}, ++ {0x3D, 0xc8, 0xc8, 1, 1}, ++ {0x3E, 0x88, 0x88, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0, 0, 0, 0}, ++ {0x42, 0x1, 0x1, 0, 0}, ++ {0x43, 0x2, 0x2, 0, 0}, ++ {0x44, 0x96, 0x96, 0, 0}, ++ {0x45, 0x3e, 0x3e, 0, 0}, ++ {0x46, 0x3e, 0x3e, 0, 0}, ++ {0x47, 0x13, 0x13, 0, 0}, ++ {0x48, 0x2, 0x2, 0, 0}, ++ {0x49, 0x15, 0x15, 0, 0}, ++ {0x4A, 0x7, 0x7, 0, 0}, ++ {0x4B, 0, 0, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0, 0, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0, 0, 0, 0}, ++ {0x50, 0x8, 0x8, 0, 0}, ++ {0x51, 0x8, 0x8, 0, 0}, ++ {0x52, 0x6, 0x6, 0, 0}, ++ {0x53, 0x84, 0x84, 1, 1}, ++ {0x54, 0xc3, 0xc3, 0, 0}, ++ {0x55, 0x8f, 0x8f, 0, 0}, ++ {0x56, 0xff, 0xff, 0, 0}, ++ {0x57, 0xff, 0xff, 0, 0}, ++ {0x58, 0x88, 0x88, 0, 0}, ++ {0x59, 0x88, 0x88, 0, 0}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0xcc, 0xcc, 0, 0}, ++ {0x5C, 0x6, 0x6, 0, 0}, ++ {0x5D, 0x80, 0x80, 0, 0}, ++ {0x5E, 0x80, 0x80, 0, 0}, ++ {0x5F, 0xf8, 0xf8, 0, 0}, ++ {0x60, 0x88, 0x88, 0, 0}, ++ {0x61, 0x88, 0x88, 0, 0}, ++ {0x62, 0x88, 0x8, 1, 1}, ++ {0x63, 0x88, 0x88, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0x1, 0x1, 1, 1}, ++ {0x66, 0x8a, 0x8a, 0, 0}, ++ {0x67, 0x8, 0x8, 0, 0}, ++ {0x68, 0x83, 0x83, 0, 0}, ++ {0x69, 0x6, 0x6, 0, 0}, ++ {0x6A, 0xa0, 0xa0, 0, 0}, ++ {0x6B, 0xa, 0xa, 0, 0}, ++ {0x6C, 0x87, 0x87, 1, 1}, ++ {0x6D, 0x2a, 0x2a, 0, 0}, ++ {0x6E, 0x2a, 0x2a, 0, 0}, ++ {0x6F, 0x2a, 0x2a, 0, 0}, ++ {0x70, 0x2a, 0x2a, 0, 0}, ++ {0x71, 0x18, 0x18, 0, 0}, ++ {0x72, 0x6a, 0x6a, 1, 1}, ++ {0x73, 0xab, 0xab, 1, 1}, ++ {0x74, 0x13, 0x13, 1, 1}, ++ {0x75, 0xc1, 0xc1, 1, 1}, ++ {0x76, 0xaa, 0xaa, 1, 1}, ++ {0x77, 0x87, 0x87, 1, 1}, ++ {0x78, 0, 0, 0, 0}, ++ {0x79, 0x6, 0x6, 0, 0}, ++ {0x7A, 0x7, 0x7, 0, 0}, ++ {0x7B, 0x7, 0x7, 0, 0}, ++ {0x7C, 0x15, 0x15, 0, 0}, ++ {0x7D, 0x55, 0x55, 0, 0}, ++ {0x7E, 0x97, 0x97, 1, 1}, ++ {0x7F, 0x8, 0x8, 0, 0}, ++ {0x80, 0x14, 0x14, 1, 1}, ++ {0x81, 0x33, 0x33, 0, 0}, ++ {0x82, 0x88, 0x88, 0, 0}, ++ {0x83, 0x6, 0x6, 0, 0}, ++ {0x84, 0x3, 0x3, 1, 1}, ++ {0x85, 0xa, 0xa, 0, 0}, ++ {0x86, 0x3, 0x3, 1, 1}, ++ {0x87, 0x2a, 0x2a, 0, 0}, ++ {0x88, 0xa4, 0xa4, 0, 0}, ++ {0x89, 0x18, 0x18, 0, 0}, ++ {0x8A, 0x28, 0x28, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0x4a, 0x4a, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0xf8, 0xf8, 0, 0}, ++ {0x8F, 0x88, 0x88, 0, 0}, ++ {0x90, 0x88, 0x88, 0, 0}, ++ {0x91, 0x88, 0x8, 1, 1}, ++ {0x92, 0x88, 0x88, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0x1, 0x1, 1, 1}, ++ {0x95, 0x8a, 0x8a, 0, 0}, ++ {0x96, 0x8, 0x8, 0, 0}, ++ {0x97, 0x83, 0x83, 0, 0}, ++ {0x98, 0x6, 0x6, 0, 0}, ++ {0x99, 0xa0, 0xa0, 0, 0}, ++ {0x9A, 0xa, 0xa, 0, 0}, ++ {0x9B, 0x87, 0x87, 1, 1}, ++ {0x9C, 0x2a, 0x2a, 0, 0}, ++ {0x9D, 0x2a, 0x2a, 0, 0}, ++ {0x9E, 0x2a, 0x2a, 0, 0}, ++ {0x9F, 0x2a, 0x2a, 0, 0}, ++ {0xA0, 0x18, 0x18, 0, 0}, ++ {0xA1, 0x6a, 0x6a, 1, 1}, ++ {0xA2, 0xab, 0xab, 1, 1}, ++ {0xA3, 0x13, 0x13, 1, 1}, ++ {0xA4, 0xc1, 0xc1, 1, 1}, ++ {0xA5, 0xaa, 0xaa, 1, 1}, ++ {0xA6, 0x87, 0x87, 1, 1}, ++ {0xA7, 0, 0, 0, 0}, ++ {0xA8, 0x6, 0x6, 0, 0}, ++ {0xA9, 0x7, 0x7, 0, 0}, ++ {0xAA, 0x7, 0x7, 0, 0}, ++ {0xAB, 0x15, 0x15, 0, 0}, ++ {0xAC, 0x55, 0x55, 0, 0}, ++ {0xAD, 0x97, 0x97, 1, 1}, ++ {0xAE, 0x8, 0x8, 0, 0}, ++ {0xAF, 0x14, 0x14, 1, 1}, ++ {0xB0, 0x33, 0x33, 0, 0}, ++ {0xB1, 0x88, 0x88, 0, 0}, ++ {0xB2, 0x6, 0x6, 0, 0}, ++ {0xB3, 0x3, 0x3, 1, 1}, ++ {0xB4, 0xa, 0xa, 0, 0}, ++ {0xB5, 0x3, 0x3, 1, 1}, ++ {0xB6, 0x2a, 0x2a, 0, 0}, ++ {0xB7, 0xa4, 0xa4, 0, 0}, ++ {0xB8, 0x18, 0x18, 0, 0}, ++ {0xB9, 0x28, 0x28, 0, 0}, ++ {0xBA, 0, 0, 0, 0}, ++ {0xBB, 0x4a, 0x4a, 0, 0}, ++ {0xBC, 0, 0, 0, 0}, ++ {0xBD, 0x71, 0x71, 0, 0}, ++ {0xBE, 0x72, 0x72, 0, 0}, ++ {0xBF, 0x73, 0x73, 0, 0}, ++ {0xC0, 0x74, 0x74, 0, 0}, ++ {0xC1, 0x75, 0x75, 0, 0}, ++ {0xC2, 0x76, 0x76, 0, 0}, ++ {0xC3, 0x77, 0x77, 0, 0}, ++ {0xC4, 0x78, 0x78, 0, 0}, ++ {0xC5, 0x79, 0x79, 0, 0}, ++ {0xC6, 0x7a, 0x7a, 0, 0}, ++ {0xC7, 0, 0, 0, 0}, ++ {0xC8, 0, 0, 0, 0}, ++ {0xC9, 0, 0, 0, 0}, ++ {0xCA, 0, 0, 0, 0}, ++ {0xCB, 0, 0, 0, 0}, ++ {0xCC, 0, 0, 0, 0}, ++ {0xCD, 0, 0, 0, 0}, ++ {0xCE, 0x6, 0x6, 0, 0}, ++ {0xCF, 0, 0, 0, 0}, ++ {0xD0, 0, 0, 0, 0}, ++ {0xD1, 0x18, 0x18, 0, 0}, ++ {0xD2, 0x88, 0x88, 0, 0}, ++ {0xD3, 0, 0, 0, 0}, ++ {0xD4, 0, 0, 0, 0}, ++ {0xD5, 0, 0, 0, 0}, ++ {0xD6, 0, 0, 0, 0}, ++ {0xD7, 0, 0, 0, 0}, ++ {0xD8, 0, 0, 0, 0}, ++ {0xD9, 0, 0, 0, 0}, ++ {0xDA, 0x6, 0x6, 0, 0}, ++ {0xDB, 0, 0, 0, 0}, ++ {0xDC, 0, 0, 0, 0}, ++ {0xDD, 0x18, 0x18, 0, 0}, ++ {0xDE, 0x88, 0x88, 0, 0}, ++ {0xDF, 0, 0, 0, 0}, ++ {0xE0, 0, 0, 0, 0}, ++ {0xE1, 0, 0, 0, 0}, ++ {0xE2, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static struct radio_regs regs_SYN_2056[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0x1, 0x1, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0x60, 0x60, 0, 0}, ++ {0x23, 0x6, 0x6, 0, 0}, ++ {0x24, 0xc, 0xc, 0, 0}, ++ {0x25, 0, 0, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0, 0, 0, 0}, ++ {0x28, 0x1, 0x1, 0, 0}, ++ {0x29, 0, 0, 0, 0}, ++ {0x2A, 0, 0, 0, 0}, ++ {0x2B, 0, 0, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0xd, 0xd, 0, 0}, ++ {0x2F, 0x1f, 0x1f, 0, 0}, ++ {0x30, 0x15, 0x15, 0, 0}, ++ {0x31, 0xf, 0xf, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0, 0, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0, 0, 0, 0}, ++ {0x38, 0, 0, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0, 0, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x13, 0x13, 0, 0}, ++ {0x3D, 0xf, 0xf, 0, 0}, ++ {0x3E, 0x18, 0x18, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x20, 0x20, 0, 0}, ++ {0x42, 0x20, 0x20, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x77, 0x77, 0, 0}, ++ {0x45, 0x7, 0x7, 0, 0}, ++ {0x46, 0x1, 0x1, 0, 0}, ++ {0x47, 0x4, 0x4, 0, 0}, ++ {0x48, 0xf, 0xf, 0, 0}, ++ {0x49, 0x30, 0x30, 0, 0}, ++ {0x4A, 0x32, 0x32, 0, 0}, ++ {0x4B, 0xd, 0xd, 0, 0}, ++ {0x4C, 0xd, 0xd, 0, 0}, ++ {0x4D, 0x4, 0x4, 0, 0}, ++ {0x4E, 0x6, 0x6, 0, 0}, ++ {0x4F, 0x1, 0x1, 0, 0}, ++ {0x50, 0x1c, 0x1c, 0, 0}, ++ {0x51, 0x2, 0x2, 0, 0}, ++ {0x52, 0x2, 0x2, 0, 0}, ++ {0x53, 0xf7, 0xf7, 1, 1}, ++ {0x54, 0xb4, 0xb4, 0, 0}, ++ {0x55, 0xd2, 0xd2, 0, 0}, ++ {0x56, 0, 0, 0, 0}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x4, 0x4, 0, 0}, ++ {0x59, 0x96, 0x96, 0, 0}, ++ {0x5A, 0x3e, 0x3e, 0, 0}, ++ {0x5B, 0x3e, 0x3e, 0, 0}, ++ {0x5C, 0x13, 0x13, 0, 0}, ++ {0x5D, 0x2, 0x2, 0, 0}, ++ {0x5E, 0, 0, 0, 0}, ++ {0x5F, 0x7, 0x7, 0, 0}, ++ {0x60, 0x7, 0x7, 1, 1}, ++ {0x61, 0x8, 0x8, 0, 0}, ++ {0x62, 0x3, 0x3, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0x40, 0x40, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0x1, 0x1, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0x60, 0x60, 0, 0}, ++ {0x71, 0x66, 0x66, 0, 0}, ++ {0x72, 0xc, 0xc, 0, 0}, ++ {0x73, 0x66, 0x66, 0, 0}, ++ {0x74, 0x8f, 0x8f, 1, 1}, ++ {0x75, 0, 0, 0, 0}, ++ {0x76, 0xcc, 0xcc, 0, 0}, ++ {0x77, 0x1, 0x1, 0, 0}, ++ {0x78, 0x66, 0x66, 0, 0}, ++ {0x79, 0x66, 0x66, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0xff, 0xff, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0x95, 0, 0, 0, 0}, ++ {0x96, 0, 0, 0, 0}, ++ {0x97, 0, 0, 0, 0}, ++ {0x98, 0, 0, 0, 0}, ++ {0x99, 0, 0, 0, 0}, ++ {0x9A, 0, 0, 0, 0}, ++ {0x9B, 0, 0, 0, 0}, ++ {0x9C, 0, 0, 0, 0}, ++ {0x9D, 0, 0, 0, 0}, ++ {0x9E, 0, 0, 0, 0}, ++ {0x9F, 0x6, 0x6, 0, 0}, ++ {0xA0, 0x66, 0x66, 0, 0}, ++ {0xA1, 0x66, 0x66, 0, 0}, ++ {0xA2, 0x66, 0x66, 0, 0}, ++ {0xA3, 0x66, 0x66, 0, 0}, ++ {0xA4, 0x66, 0x66, 0, 0}, ++ {0xA5, 0x66, 0x66, 0, 0}, ++ {0xA6, 0x66, 0x66, 0, 0}, ++ {0xA7, 0x66, 0x66, 0, 0}, ++ {0xA8, 0x66, 0x66, 0, 0}, ++ {0xA9, 0x66, 0x66, 0, 0}, ++ {0xAA, 0x66, 0x66, 0, 0}, ++ {0xAB, 0x66, 0x66, 0, 0}, ++ {0xAC, 0x66, 0x66, 0, 0}, ++ {0xAD, 0x66, 0x66, 0, 0}, ++ {0xAE, 0x66, 0x66, 0, 0}, ++ {0xAF, 0x66, 0x66, 0, 0}, ++ {0xB0, 0x66, 0x66, 0, 0}, ++ {0xB1, 0x66, 0x66, 0, 0}, ++ {0xB2, 0x66, 0x66, 0, 0}, ++ {0xB3, 0xa, 0xa, 0, 0}, ++ {0xB4, 0, 0, 0, 0}, ++ {0xB5, 0, 0, 0, 0}, ++ {0xB6, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_TX_2056[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0x88, 0x88, 0, 0}, ++ {0x22, 0x88, 0x88, 0, 0}, ++ {0x23, 0x88, 0x88, 0, 0}, ++ {0x24, 0x88, 0x88, 0, 0}, ++ {0x25, 0xc, 0xc, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0x3, 0x3, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0x3, 0x3, 0, 0}, ++ {0x2A, 0x37, 0x37, 0, 0}, ++ {0x2B, 0x3, 0x3, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0x1, 0x1, 0, 0}, ++ {0x2F, 0x1, 0x1, 0, 0}, ++ {0x30, 0, 0, 0, 0}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0x11, 0x11, 0, 0}, ++ {0x34, 0x11, 0x11, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0x3, 0x3, 0, 0}, ++ {0x38, 0xf, 0xf, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0x2d, 0x2d, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x6e, 0x6e, 0, 0}, ++ {0x3D, 0xf0, 0xf0, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x3, 0x3, 0, 0}, ++ {0x42, 0x3, 0x3, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x1e, 0x1e, 0, 0}, ++ {0x45, 0, 0, 0, 0}, ++ {0x46, 0x6e, 0x6e, 0, 0}, ++ {0x47, 0xf0, 0xf0, 1, 1}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x2, 0x2, 0, 0}, ++ {0x4A, 0xff, 0xff, 1, 1}, ++ {0x4B, 0xc, 0xc, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0x38, 0x38, 0, 0}, ++ {0x4E, 0x70, 0x70, 1, 1}, ++ {0x4F, 0x2, 0x2, 0, 0}, ++ {0x50, 0x88, 0x88, 0, 0}, ++ {0x51, 0xc, 0xc, 0, 0}, ++ {0x52, 0, 0, 0, 0}, ++ {0x53, 0x8, 0x8, 0, 0}, ++ {0x54, 0x70, 0x70, 1, 1}, ++ {0x55, 0x2, 0x2, 0, 0}, ++ {0x56, 0xff, 0xff, 1, 1}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x83, 0x83, 0, 0}, ++ {0x59, 0x77, 0x77, 1, 1}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x88, 0x88, 0, 0}, ++ {0x5D, 0, 0, 0, 0}, ++ {0x5E, 0x8, 0x8, 0, 0}, ++ {0x5F, 0x77, 0x77, 1, 1}, ++ {0x60, 0x1, 0x1, 0, 0}, ++ {0x61, 0, 0, 0, 0}, ++ {0x62, 0x7, 0x7, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0x7, 0x7, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0x74, 0x74, 1, 1}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0xa, 0xa, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0x2, 0x2, 0, 0}, ++ {0x72, 0, 0, 0, 0}, ++ {0x73, 0, 0, 0, 0}, ++ {0x74, 0xe, 0xe, 0, 0}, ++ {0x75, 0xe, 0xe, 0, 0}, ++ {0x76, 0xe, 0xe, 0, 0}, ++ {0x77, 0x13, 0x13, 0, 0}, ++ {0x78, 0x13, 0x13, 0, 0}, ++ {0x79, 0x1b, 0x1b, 0, 0}, ++ {0x7A, 0x1b, 0x1b, 0, 0}, ++ {0x7B, 0x55, 0x55, 0, 0}, ++ {0x7C, 0x5b, 0x5b, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_RX_2056[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0x3, 0x3, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0, 0, 0, 0}, ++ {0x23, 0x90, 0x90, 0, 0}, ++ {0x24, 0x55, 0x55, 0, 0}, ++ {0x25, 0x15, 0x15, 0, 0}, ++ {0x26, 0x5, 0x5, 0, 0}, ++ {0x27, 0x15, 0x15, 0, 0}, ++ {0x28, 0x5, 0x5, 0, 0}, ++ {0x29, 0x20, 0x20, 0, 0}, ++ {0x2A, 0x11, 0x11, 0, 0}, ++ {0x2B, 0x90, 0x90, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0x88, 0x88, 0, 0}, ++ {0x2E, 0x32, 0x32, 0, 0}, ++ {0x2F, 0x77, 0x77, 0, 0}, ++ {0x30, 0x17, 0x17, 1, 1}, ++ {0x31, 0xff, 0xff, 1, 1}, ++ {0x32, 0x20, 0x20, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0x88, 0x88, 0, 0}, ++ {0x35, 0x32, 0x32, 0, 0}, ++ {0x36, 0x77, 0x77, 0, 0}, ++ {0x37, 0x17, 0x17, 1, 1}, ++ {0x38, 0xf0, 0xf0, 1, 1}, ++ {0x39, 0x20, 0x20, 0, 0}, ++ {0x3A, 0x8, 0x8, 0, 0}, ++ {0x3B, 0x99, 0x99, 0, 0}, ++ {0x3C, 0, 0, 0, 0}, ++ {0x3D, 0x44, 0x44, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0x44, 0x44, 0, 0}, ++ {0x40, 0xf, 0xf, 1, 1}, ++ {0x41, 0x6, 0x6, 0, 0}, ++ {0x42, 0x4, 0x4, 0, 0}, ++ {0x43, 0x50, 0x50, 1, 1}, ++ {0x44, 0x8, 0x8, 0, 0}, ++ {0x45, 0x99, 0x99, 0, 0}, ++ {0x46, 0, 0, 0, 0}, ++ {0x47, 0x11, 0x11, 0, 0}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x44, 0x44, 0, 0}, ++ {0x4A, 0x7, 0x7, 0, 0}, ++ {0x4B, 0x6, 0x6, 0, 0}, ++ {0x4C, 0x4, 0x4, 0, 0}, ++ {0x4D, 0, 0, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0x66, 0x66, 0, 0}, ++ {0x50, 0x66, 0x66, 0, 0}, ++ {0x51, 0x57, 0x57, 0, 0}, ++ {0x52, 0x57, 0x57, 0, 0}, ++ {0x53, 0x44, 0x44, 0, 0}, ++ {0x54, 0, 0, 0, 0}, ++ {0x55, 0, 0, 0, 0}, ++ {0x56, 0x8, 0x8, 0, 0}, ++ {0x57, 0x8, 0x8, 0, 0}, ++ {0x58, 0x7, 0x7, 0, 0}, ++ {0x59, 0x22, 0x22, 0, 0}, ++ {0x5A, 0x22, 0x22, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x23, 0x23, 0, 0}, ++ {0x5D, 0x7, 0x7, 0, 0}, ++ {0x5E, 0x55, 0x55, 0, 0}, ++ {0x5F, 0x23, 0x23, 0, 0}, ++ {0x60, 0x41, 0x41, 0, 0}, ++ {0x61, 0x1, 0x1, 0, 0}, ++ {0x62, 0xa, 0xa, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0xc, 0xc, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0, 0, 0, 0}, ++ {0x72, 0x22, 0x22, 0, 0}, ++ {0x73, 0x22, 0x22, 0, 0}, ++ {0x74, 0x2, 0x2, 0, 0}, ++ {0x75, 0xa, 0xa, 0, 0}, ++ {0x76, 0x1, 0x1, 0, 0}, ++ {0x77, 0x22, 0x22, 0, 0}, ++ {0x78, 0x30, 0x30, 0, 0}, ++ {0x79, 0, 0, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_SYN_2056_A1[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0x1, 0x1, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0x60, 0x60, 0, 0}, ++ {0x23, 0x6, 0x6, 0, 0}, ++ {0x24, 0xc, 0xc, 0, 0}, ++ {0x25, 0, 0, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0, 0, 0, 0}, ++ {0x28, 0x1, 0x1, 0, 0}, ++ {0x29, 0, 0, 0, 0}, ++ {0x2A, 0, 0, 0, 0}, ++ {0x2B, 0, 0, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0xd, 0xd, 0, 0}, ++ {0x2F, 0x1f, 0x1f, 0, 0}, ++ {0x30, 0x15, 0x15, 0, 0}, ++ {0x31, 0xf, 0xf, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0, 0, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0, 0, 0, 0}, ++ {0x38, 0, 0, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0, 0, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x13, 0x13, 0, 0}, ++ {0x3D, 0xf, 0xf, 0, 0}, ++ {0x3E, 0x18, 0x18, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x20, 0x20, 0, 0}, ++ {0x42, 0x20, 0x20, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x77, 0x77, 0, 0}, ++ {0x45, 0x7, 0x7, 0, 0}, ++ {0x46, 0x1, 0x1, 0, 0}, ++ {0x47, 0x4, 0x4, 0, 0}, ++ {0x48, 0xf, 0xf, 0, 0}, ++ {0x49, 0x30, 0x30, 0, 0}, ++ {0x4A, 0x32, 0x32, 0, 0}, ++ {0x4B, 0xd, 0xd, 0, 0}, ++ {0x4C, 0xd, 0xd, 0, 0}, ++ {0x4D, 0x4, 0x4, 0, 0}, ++ {0x4E, 0x6, 0x6, 0, 0}, ++ {0x4F, 0x1, 0x1, 0, 0}, ++ {0x50, 0x1c, 0x1c, 0, 0}, ++ {0x51, 0x2, 0x2, 0, 0}, ++ {0x52, 0x2, 0x2, 0, 0}, ++ {0x53, 0xf7, 0xf7, 1, 1}, ++ {0x54, 0xb4, 0xb4, 0, 0}, ++ {0x55, 0xd2, 0xd2, 0, 0}, ++ {0x56, 0, 0, 0, 0}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x4, 0x4, 0, 0}, ++ {0x59, 0x96, 0x96, 0, 0}, ++ {0x5A, 0x3e, 0x3e, 0, 0}, ++ {0x5B, 0x3e, 0x3e, 0, 0}, ++ {0x5C, 0x13, 0x13, 0, 0}, ++ {0x5D, 0x2, 0x2, 0, 0}, ++ {0x5E, 0, 0, 0, 0}, ++ {0x5F, 0x7, 0x7, 0, 0}, ++ {0x60, 0x7, 0x7, 1, 1}, ++ {0x61, 0x8, 0x8, 0, 0}, ++ {0x62, 0x3, 0x3, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0x40, 0x40, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0x1, 0x1, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0x60, 0x60, 0, 0}, ++ {0x71, 0x66, 0x66, 0, 0}, ++ {0x72, 0xc, 0xc, 0, 0}, ++ {0x73, 0x66, 0x66, 0, 0}, ++ {0x74, 0x8f, 0x8f, 1, 1}, ++ {0x75, 0, 0, 0, 0}, ++ {0x76, 0xcc, 0xcc, 0, 0}, ++ {0x77, 0x1, 0x1, 0, 0}, ++ {0x78, 0x66, 0x66, 0, 0}, ++ {0x79, 0x66, 0x66, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0xff, 0xff, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0x95, 0, 0, 0, 0}, ++ {0x96, 0, 0, 0, 0}, ++ {0x97, 0, 0, 0, 0}, ++ {0x98, 0, 0, 0, 0}, ++ {0x99, 0, 0, 0, 0}, ++ {0x9A, 0, 0, 0, 0}, ++ {0x9B, 0, 0, 0, 0}, ++ {0x9C, 0, 0, 0, 0}, ++ {0x9D, 0, 0, 0, 0}, ++ {0x9E, 0, 0, 0, 0}, ++ {0x9F, 0x6, 0x6, 0, 0}, ++ {0xA0, 0x66, 0x66, 0, 0}, ++ {0xA1, 0x66, 0x66, 0, 0}, ++ {0xA2, 0x66, 0x66, 0, 0}, ++ {0xA3, 0x66, 0x66, 0, 0}, ++ {0xA4, 0x66, 0x66, 0, 0}, ++ {0xA5, 0x66, 0x66, 0, 0}, ++ {0xA6, 0x66, 0x66, 0, 0}, ++ {0xA7, 0x66, 0x66, 0, 0}, ++ {0xA8, 0x66, 0x66, 0, 0}, ++ {0xA9, 0x66, 0x66, 0, 0}, ++ {0xAA, 0x66, 0x66, 0, 0}, ++ {0xAB, 0x66, 0x66, 0, 0}, ++ {0xAC, 0x66, 0x66, 0, 0}, ++ {0xAD, 0x66, 0x66, 0, 0}, ++ {0xAE, 0x66, 0x66, 0, 0}, ++ {0xAF, 0x66, 0x66, 0, 0}, ++ {0xB0, 0x66, 0x66, 0, 0}, ++ {0xB1, 0x66, 0x66, 0, 0}, ++ {0xB2, 0x66, 0x66, 0, 0}, ++ {0xB3, 0xa, 0xa, 0, 0}, ++ {0xB4, 0, 0, 0, 0}, ++ {0xB5, 0, 0, 0, 0}, ++ {0xB6, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_TX_2056_A1[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0x88, 0x88, 0, 0}, ++ {0x22, 0x88, 0x88, 0, 0}, ++ {0x23, 0x88, 0x88, 0, 0}, ++ {0x24, 0x88, 0x88, 0, 0}, ++ {0x25, 0xc, 0xc, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0x3, 0x3, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0x3, 0x3, 0, 0}, ++ {0x2A, 0x37, 0x37, 0, 0}, ++ {0x2B, 0x3, 0x3, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0x1, 0x1, 0, 0}, ++ {0x2F, 0x1, 0x1, 0, 0}, ++ {0x30, 0, 0, 0, 0}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0x11, 0x11, 0, 0}, ++ {0x34, 0x11, 0x11, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0x3, 0x3, 0, 0}, ++ {0x38, 0xf, 0xf, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0x2d, 0x2d, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x6e, 0x6e, 0, 0}, ++ {0x3D, 0xf0, 0xf0, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x3, 0x3, 0, 0}, ++ {0x42, 0x3, 0x3, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x1e, 0x1e, 0, 0}, ++ {0x45, 0, 0, 0, 0}, ++ {0x46, 0x6e, 0x6e, 0, 0}, ++ {0x47, 0xf0, 0xf0, 1, 1}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x2, 0x2, 0, 0}, ++ {0x4A, 0xff, 0xff, 1, 1}, ++ {0x4B, 0xc, 0xc, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0x38, 0x38, 0, 0}, ++ {0x4E, 0x70, 0x70, 1, 1}, ++ {0x4F, 0x2, 0x2, 0, 0}, ++ {0x50, 0x88, 0x88, 0, 0}, ++ {0x51, 0xc, 0xc, 0, 0}, ++ {0x52, 0, 0, 0, 0}, ++ {0x53, 0x8, 0x8, 0, 0}, ++ {0x54, 0x70, 0x70, 1, 1}, ++ {0x55, 0x2, 0x2, 0, 0}, ++ {0x56, 0xff, 0xff, 1, 1}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x83, 0x83, 0, 0}, ++ {0x59, 0x77, 0x77, 1, 1}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x88, 0x88, 0, 0}, ++ {0x5D, 0, 0, 0, 0}, ++ {0x5E, 0x8, 0x8, 0, 0}, ++ {0x5F, 0x77, 0x77, 1, 1}, ++ {0x60, 0x1, 0x1, 0, 0}, ++ {0x61, 0, 0, 0, 0}, ++ {0x62, 0x7, 0x7, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0x7, 0x7, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0x72, 0x72, 1, 1}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0xa, 0xa, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0x2, 0x2, 0, 0}, ++ {0x72, 0, 0, 0, 0}, ++ {0x73, 0, 0, 0, 0}, ++ {0x74, 0xe, 0xe, 0, 0}, ++ {0x75, 0xe, 0xe, 0, 0}, ++ {0x76, 0xe, 0xe, 0, 0}, ++ {0x77, 0x13, 0x13, 0, 0}, ++ {0x78, 0x13, 0x13, 0, 0}, ++ {0x79, 0x1b, 0x1b, 0, 0}, ++ {0x7A, 0x1b, 0x1b, 0, 0}, ++ {0x7B, 0x55, 0x55, 0, 0}, ++ {0x7C, 0x5b, 0x5b, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_RX_2056_A1[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0x3, 0x3, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0, 0, 0, 0}, ++ {0x23, 0x90, 0x90, 0, 0}, ++ {0x24, 0x55, 0x55, 0, 0}, ++ {0x25, 0x15, 0x15, 0, 0}, ++ {0x26, 0x5, 0x5, 0, 0}, ++ {0x27, 0x15, 0x15, 0, 0}, ++ {0x28, 0x5, 0x5, 0, 0}, ++ {0x29, 0x20, 0x20, 0, 0}, ++ {0x2A, 0x11, 0x11, 0, 0}, ++ {0x2B, 0x90, 0x90, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0x88, 0x88, 0, 0}, ++ {0x2E, 0x32, 0x32, 0, 0}, ++ {0x2F, 0x77, 0x77, 0, 0}, ++ {0x30, 0x17, 0x17, 1, 1}, ++ {0x31, 0xff, 0xff, 1, 1}, ++ {0x32, 0x20, 0x20, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0x88, 0x88, 0, 0}, ++ {0x35, 0x32, 0x32, 0, 0}, ++ {0x36, 0x77, 0x77, 0, 0}, ++ {0x37, 0x17, 0x17, 1, 1}, ++ {0x38, 0xf0, 0xf0, 1, 1}, ++ {0x39, 0x20, 0x20, 0, 0}, ++ {0x3A, 0x8, 0x8, 0, 0}, ++ {0x3B, 0x55, 0x55, 1, 1}, ++ {0x3C, 0, 0, 0, 0}, ++ {0x3D, 0x44, 0x44, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0x44, 0x44, 0, 0}, ++ {0x40, 0xf, 0xf, 1, 1}, ++ {0x41, 0x6, 0x6, 0, 0}, ++ {0x42, 0x4, 0x4, 0, 0}, ++ {0x43, 0x50, 0x50, 1, 1}, ++ {0x44, 0x8, 0x8, 0, 0}, ++ {0x45, 0x55, 0x55, 1, 1}, ++ {0x46, 0, 0, 0, 0}, ++ {0x47, 0x11, 0x11, 0, 0}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x44, 0x44, 0, 0}, ++ {0x4A, 0x7, 0x7, 0, 0}, ++ {0x4B, 0x6, 0x6, 0, 0}, ++ {0x4C, 0x4, 0x4, 0, 0}, ++ {0x4D, 0, 0, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0x26, 0x26, 1, 1}, ++ {0x50, 0x26, 0x26, 1, 1}, ++ {0x51, 0xf, 0xf, 1, 1}, ++ {0x52, 0xf, 0xf, 1, 1}, ++ {0x53, 0x44, 0x44, 0, 0}, ++ {0x54, 0, 0, 0, 0}, ++ {0x55, 0, 0, 0, 0}, ++ {0x56, 0x8, 0x8, 0, 0}, ++ {0x57, 0x8, 0x8, 0, 0}, ++ {0x58, 0x7, 0x7, 0, 0}, ++ {0x59, 0x22, 0x22, 0, 0}, ++ {0x5A, 0x22, 0x22, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x2f, 0x2f, 1, 1}, ++ {0x5D, 0x7, 0x7, 0, 0}, ++ {0x5E, 0x55, 0x55, 0, 0}, ++ {0x5F, 0x23, 0x23, 0, 0}, ++ {0x60, 0x41, 0x41, 0, 0}, ++ {0x61, 0x1, 0x1, 0, 0}, ++ {0x62, 0xa, 0xa, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0xc, 0xc, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0, 0, 0, 0}, ++ {0x72, 0x22, 0x22, 0, 0}, ++ {0x73, 0x22, 0x22, 0, 0}, ++ {0x74, 0, 0, 1, 1}, ++ {0x75, 0xa, 0xa, 0, 0}, ++ {0x76, 0x1, 0x1, 0, 0}, ++ {0x77, 0x22, 0x22, 0, 0}, ++ {0x78, 0x30, 0x30, 0, 0}, ++ {0x79, 0, 0, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_SYN_2056_rev5[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0x1, 0x1, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0x60, 0x60, 0, 0}, ++ {0x23, 0x6, 0x6, 0, 0}, ++ {0x24, 0xc, 0xc, 0, 0}, ++ {0x25, 0, 0, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0, 0, 0, 0}, ++ {0x28, 0x1, 0x1, 0, 0}, ++ {0x29, 0, 0, 0, 0}, ++ {0x2A, 0, 0, 0, 0}, ++ {0x2B, 0, 0, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0, 0, 0, 0}, ++ {0x2F, 0x1f, 0x1f, 0, 0}, ++ {0x30, 0x15, 0x15, 0, 0}, ++ {0x31, 0xf, 0xf, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0, 0, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0, 0, 0, 0}, ++ {0x38, 0, 0, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0, 0, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x13, 0x13, 0, 0}, ++ {0x3D, 0xf, 0xf, 0, 0}, ++ {0x3E, 0x18, 0x18, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x20, 0x20, 0, 0}, ++ {0x42, 0x20, 0x20, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x77, 0x77, 0, 0}, ++ {0x45, 0x7, 0x7, 0, 0}, ++ {0x46, 0x1, 0x1, 0, 0}, ++ {0x47, 0x4, 0x4, 0, 0}, ++ {0x48, 0xf, 0xf, 0, 0}, ++ {0x49, 0x30, 0x30, 0, 0}, ++ {0x4A, 0x32, 0x32, 0, 0}, ++ {0x4B, 0xd, 0xd, 0, 0}, ++ {0x4C, 0xd, 0xd, 0, 0}, ++ {0x4D, 0x4, 0x4, 0, 0}, ++ {0x4E, 0x6, 0x6, 0, 0}, ++ {0x4F, 0x1, 0x1, 0, 0}, ++ {0x50, 0x1c, 0x1c, 0, 0}, ++ {0x51, 0x2, 0x2, 0, 0}, ++ {0x52, 0x2, 0x2, 0, 0}, ++ {0x53, 0xf7, 0xf7, 1, 1}, ++ {0x54, 0xb4, 0xb4, 0, 0}, ++ {0x55, 0xd2, 0xd2, 0, 0}, ++ {0x56, 0, 0, 0, 0}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x4, 0x4, 0, 0}, ++ {0x59, 0x96, 0x96, 0, 0}, ++ {0x5A, 0x3e, 0x3e, 0, 0}, ++ {0x5B, 0x3e, 0x3e, 0, 0}, ++ {0x5C, 0x13, 0x13, 0, 0}, ++ {0x5D, 0x2, 0x2, 0, 0}, ++ {0x5E, 0, 0, 0, 0}, ++ {0x5F, 0x7, 0x7, 0, 0}, ++ {0x60, 0x7, 0x7, 1, 1}, ++ {0x61, 0x8, 0x8, 0, 0}, ++ {0x62, 0x3, 0x3, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0x40, 0x40, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0x1, 0x1, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0x60, 0x60, 0, 0}, ++ {0x71, 0x66, 0x66, 0, 0}, ++ {0x72, 0xc, 0xc, 0, 0}, ++ {0x73, 0x66, 0x66, 0, 0}, ++ {0x74, 0x8f, 0x8f, 1, 1}, ++ {0x75, 0, 0, 0, 0}, ++ {0x76, 0xcc, 0xcc, 0, 0}, ++ {0x77, 0x1, 0x1, 0, 0}, ++ {0x78, 0x66, 0x66, 0, 0}, ++ {0x79, 0x66, 0x66, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0xff, 0xff, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0x95, 0, 0, 0, 0}, ++ {0x96, 0, 0, 0, 0}, ++ {0x97, 0, 0, 0, 0}, ++ {0x98, 0, 0, 0, 0}, ++ {0x99, 0, 0, 0, 0}, ++ {0x9A, 0, 0, 0, 0}, ++ {0x9B, 0, 0, 0, 0}, ++ {0x9C, 0, 0, 0, 0}, ++ {0x9D, 0, 0, 0, 0}, ++ {0x9E, 0, 0, 0, 0}, ++ {0x9F, 0x6, 0x6, 0, 0}, ++ {0xA0, 0x66, 0x66, 0, 0}, ++ {0xA1, 0x66, 0x66, 0, 0}, ++ {0xA2, 0x66, 0x66, 0, 0}, ++ {0xA3, 0x66, 0x66, 0, 0}, ++ {0xA4, 0x66, 0x66, 0, 0}, ++ {0xA5, 0x66, 0x66, 0, 0}, ++ {0xA6, 0x66, 0x66, 0, 0}, ++ {0xA7, 0x66, 0x66, 0, 0}, ++ {0xA8, 0x66, 0x66, 0, 0}, ++ {0xA9, 0x66, 0x66, 0, 0}, ++ {0xAA, 0x66, 0x66, 0, 0}, ++ {0xAB, 0x66, 0x66, 0, 0}, ++ {0xAC, 0x66, 0x66, 0, 0}, ++ {0xAD, 0x66, 0x66, 0, 0}, ++ {0xAE, 0x66, 0x66, 0, 0}, ++ {0xAF, 0x66, 0x66, 0, 0}, ++ {0xB0, 0x66, 0x66, 0, 0}, ++ {0xB1, 0x66, 0x66, 0, 0}, ++ {0xB2, 0x66, 0x66, 0, 0}, ++ {0xB3, 0xa, 0xa, 0, 0}, ++ {0xB4, 0, 0, 0, 0}, ++ {0xB5, 0, 0, 0, 0}, ++ {0xB6, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_TX_2056_rev5[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0x88, 0x88, 0, 0}, ++ {0x22, 0x88, 0x88, 0, 0}, ++ {0x23, 0x88, 0x88, 0, 0}, ++ {0x24, 0x88, 0x88, 0, 0}, ++ {0x25, 0xc, 0xc, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0x3, 0x3, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0x3, 0x3, 0, 0}, ++ {0x2A, 0x37, 0x37, 0, 0}, ++ {0x2B, 0x3, 0x3, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0x1, 0x1, 0, 0}, ++ {0x2F, 0x1, 0x1, 0, 0}, ++ {0x30, 0, 0, 0, 0}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0x11, 0x11, 0, 0}, ++ {0x34, 0x11, 0x11, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0x3, 0x3, 0, 0}, ++ {0x38, 0xf, 0xf, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0x2d, 0x2d, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x6e, 0x6e, 0, 0}, ++ {0x3D, 0xf0, 0xf0, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x3, 0x3, 0, 0}, ++ {0x42, 0x3, 0x3, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x1e, 0x1e, 0, 0}, ++ {0x45, 0, 0, 0, 0}, ++ {0x46, 0x6e, 0x6e, 0, 0}, ++ {0x47, 0xf0, 0xf0, 1, 1}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x2, 0x2, 0, 0}, ++ {0x4A, 0xff, 0xff, 1, 1}, ++ {0x4B, 0xc, 0xc, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0x38, 0x38, 0, 0}, ++ {0x4E, 0x70, 0x70, 1, 1}, ++ {0x4F, 0x2, 0x2, 0, 0}, ++ {0x50, 0x88, 0x88, 0, 0}, ++ {0x51, 0xc, 0xc, 0, 0}, ++ {0x52, 0, 0, 0, 0}, ++ {0x53, 0x8, 0x8, 0, 0}, ++ {0x54, 0x70, 0x70, 1, 1}, ++ {0x55, 0x2, 0x2, 0, 0}, ++ {0x56, 0xff, 0xff, 1, 1}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x83, 0x83, 0, 0}, ++ {0x59, 0x77, 0x77, 1, 1}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x88, 0x88, 0, 0}, ++ {0x5D, 0, 0, 0, 0}, ++ {0x5E, 0x8, 0x8, 0, 0}, ++ {0x5F, 0x77, 0x77, 1, 1}, ++ {0x60, 0x1, 0x1, 0, 0}, ++ {0x61, 0, 0, 0, 0}, ++ {0x62, 0x7, 0x7, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0x7, 0x7, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 1, 1}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0xa, 0xa, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0x2, 0x2, 0, 0}, ++ {0x72, 0, 0, 0, 0}, ++ {0x73, 0, 0, 0, 0}, ++ {0x74, 0xe, 0xe, 0, 0}, ++ {0x75, 0xe, 0xe, 0, 0}, ++ {0x76, 0xe, 0xe, 0, 0}, ++ {0x77, 0x13, 0x13, 0, 0}, ++ {0x78, 0x13, 0x13, 0, 0}, ++ {0x79, 0x1b, 0x1b, 0, 0}, ++ {0x7A, 0x1b, 0x1b, 0, 0}, ++ {0x7B, 0x55, 0x55, 0, 0}, ++ {0x7C, 0x5b, 0x5b, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0x70, 0x70, 0, 0}, ++ {0x94, 0x70, 0x70, 0, 0}, ++ {0x95, 0x71, 0x71, 1, 1}, ++ {0x96, 0x71, 0x71, 1, 1}, ++ {0x97, 0x72, 0x72, 1, 1}, ++ {0x98, 0x73, 0x73, 1, 1}, ++ {0x99, 0x74, 0x74, 1, 1}, ++ {0x9A, 0x75, 0x75, 1, 1}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_RX_2056_rev5[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0x3, 0x3, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0, 0, 0, 0}, ++ {0x23, 0x90, 0x90, 0, 0}, ++ {0x24, 0x55, 0x55, 0, 0}, ++ {0x25, 0x15, 0x15, 0, 0}, ++ {0x26, 0x5, 0x5, 0, 0}, ++ {0x27, 0x15, 0x15, 0, 0}, ++ {0x28, 0x5, 0x5, 0, 0}, ++ {0x29, 0x20, 0x20, 0, 0}, ++ {0x2A, 0x11, 0x11, 0, 0}, ++ {0x2B, 0x90, 0x90, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0x88, 0x88, 0, 0}, ++ {0x2E, 0x32, 0x32, 0, 0}, ++ {0x2F, 0x77, 0x77, 0, 0}, ++ {0x30, 0x17, 0x17, 1, 1}, ++ {0x31, 0xff, 0xff, 1, 1}, ++ {0x32, 0x20, 0x20, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0x88, 0x88, 0, 0}, ++ {0x35, 0x32, 0x32, 0, 0}, ++ {0x36, 0x77, 0x77, 0, 0}, ++ {0x37, 0x17, 0x17, 1, 1}, ++ {0x38, 0xf0, 0xf0, 1, 1}, ++ {0x39, 0x20, 0x20, 0, 0}, ++ {0x3A, 0x8, 0x8, 0, 0}, ++ {0x3B, 0x55, 0x55, 1, 1}, ++ {0x3C, 0, 0, 0, 0}, ++ {0x3D, 0x88, 0x88, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 1, 1}, ++ {0x40, 0x7, 0x7, 1, 1}, ++ {0x41, 0x6, 0x6, 0, 0}, ++ {0x42, 0x4, 0x4, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x8, 0x8, 0, 0}, ++ {0x45, 0x55, 0x55, 1, 1}, ++ {0x46, 0, 0, 0, 0}, ++ {0x47, 0x11, 0x11, 0, 0}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0, 0, 1, 1}, ++ {0x4A, 0x7, 0x7, 0, 0}, ++ {0x4B, 0x6, 0x6, 0, 0}, ++ {0x4C, 0x4, 0x4, 0, 0}, ++ {0x4D, 0, 0, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0x26, 0x26, 1, 1}, ++ {0x50, 0x26, 0x26, 1, 1}, ++ {0x51, 0xf, 0xf, 1, 1}, ++ {0x52, 0xf, 0xf, 1, 1}, ++ {0x53, 0x44, 0x44, 0, 0}, ++ {0x54, 0, 0, 0, 0}, ++ {0x55, 0, 0, 0, 0}, ++ {0x56, 0x8, 0x8, 0, 0}, ++ {0x57, 0x8, 0x8, 0, 0}, ++ {0x58, 0x7, 0x7, 0, 0}, ++ {0x59, 0x22, 0x22, 0, 0}, ++ {0x5A, 0x22, 0x22, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x4, 0x4, 1, 1}, ++ {0x5D, 0x7, 0x7, 0, 0}, ++ {0x5E, 0x55, 0x55, 0, 0}, ++ {0x5F, 0x23, 0x23, 0, 0}, ++ {0x60, 0x41, 0x41, 0, 0}, ++ {0x61, 0x1, 0x1, 0, 0}, ++ {0x62, 0xa, 0xa, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0xc, 0xc, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0, 0, 0, 0}, ++ {0x72, 0x22, 0x22, 0, 0}, ++ {0x73, 0x22, 0x22, 0, 0}, ++ {0x74, 0, 0, 1, 1}, ++ {0x75, 0xa, 0xa, 0, 0}, ++ {0x76, 0x1, 0x1, 0, 0}, ++ {0x77, 0x22, 0x22, 0, 0}, ++ {0x78, 0x30, 0x30, 0, 0}, ++ {0x79, 0, 0, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_SYN_2056_rev6[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0x1, 0x1, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0x60, 0x60, 0, 0}, ++ {0x23, 0x6, 0x6, 0, 0}, ++ {0x24, 0xc, 0xc, 0, 0}, ++ {0x25, 0, 0, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0, 0, 0, 0}, ++ {0x28, 0x1, 0x1, 0, 0}, ++ {0x29, 0, 0, 0, 0}, ++ {0x2A, 0, 0, 0, 0}, ++ {0x2B, 0, 0, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0, 0, 0, 0}, ++ {0x2F, 0x1f, 0x1f, 0, 0}, ++ {0x30, 0x15, 0x15, 0, 0}, ++ {0x31, 0xf, 0xf, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0, 0, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0, 0, 0, 0}, ++ {0x38, 0, 0, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0, 0, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x13, 0x13, 0, 0}, ++ {0x3D, 0xf, 0xf, 0, 0}, ++ {0x3E, 0x18, 0x18, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x20, 0x20, 0, 0}, ++ {0x42, 0x20, 0x20, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x77, 0x77, 0, 0}, ++ {0x45, 0x7, 0x7, 0, 0}, ++ {0x46, 0x1, 0x1, 0, 0}, ++ {0x47, 0x4, 0x4, 0, 0}, ++ {0x48, 0xf, 0xf, 0, 0}, ++ {0x49, 0x30, 0x30, 0, 0}, ++ {0x4A, 0x32, 0x32, 0, 0}, ++ {0x4B, 0xd, 0xd, 0, 0}, ++ {0x4C, 0xd, 0xd, 0, 0}, ++ {0x4D, 0x4, 0x4, 0, 0}, ++ {0x4E, 0x6, 0x6, 0, 0}, ++ {0x4F, 0x1, 0x1, 0, 0}, ++ {0x50, 0x1c, 0x1c, 0, 0}, ++ {0x51, 0x2, 0x2, 0, 0}, ++ {0x52, 0x2, 0x2, 0, 0}, ++ {0x53, 0xf7, 0xf7, 1, 1}, ++ {0x54, 0xb4, 0xb4, 0, 0}, ++ {0x55, 0xd2, 0xd2, 0, 0}, ++ {0x56, 0, 0, 0, 0}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x4, 0x4, 0, 0}, ++ {0x59, 0x96, 0x96, 0, 0}, ++ {0x5A, 0x3e, 0x3e, 0, 0}, ++ {0x5B, 0x3e, 0x3e, 0, 0}, ++ {0x5C, 0x13, 0x13, 0, 0}, ++ {0x5D, 0x2, 0x2, 0, 0}, ++ {0x5E, 0, 0, 0, 0}, ++ {0x5F, 0x7, 0x7, 0, 0}, ++ {0x60, 0x7, 0x7, 1, 1}, ++ {0x61, 0x8, 0x8, 0, 0}, ++ {0x62, 0x3, 0x3, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0x40, 0x40, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0x1, 0x1, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0x60, 0x60, 0, 0}, ++ {0x71, 0x66, 0x66, 0, 0}, ++ {0x72, 0xc, 0xc, 0, 0}, ++ {0x73, 0x66, 0x66, 0, 0}, ++ {0x74, 0x8f, 0x8f, 1, 1}, ++ {0x75, 0, 0, 0, 0}, ++ {0x76, 0xcc, 0xcc, 0, 0}, ++ {0x77, 0x1, 0x1, 0, 0}, ++ {0x78, 0x66, 0x66, 0, 0}, ++ {0x79, 0x66, 0x66, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0xff, 0xff, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0x95, 0, 0, 0, 0}, ++ {0x96, 0, 0, 0, 0}, ++ {0x97, 0, 0, 0, 0}, ++ {0x98, 0, 0, 0, 0}, ++ {0x99, 0, 0, 0, 0}, ++ {0x9A, 0, 0, 0, 0}, ++ {0x9B, 0, 0, 0, 0}, ++ {0x9C, 0, 0, 0, 0}, ++ {0x9D, 0, 0, 0, 0}, ++ {0x9E, 0, 0, 0, 0}, ++ {0x9F, 0x6, 0x6, 0, 0}, ++ {0xA0, 0x66, 0x66, 0, 0}, ++ {0xA1, 0x66, 0x66, 0, 0}, ++ {0xA2, 0x66, 0x66, 0, 0}, ++ {0xA3, 0x66, 0x66, 0, 0}, ++ {0xA4, 0x66, 0x66, 0, 0}, ++ {0xA5, 0x66, 0x66, 0, 0}, ++ {0xA6, 0x66, 0x66, 0, 0}, ++ {0xA7, 0x66, 0x66, 0, 0}, ++ {0xA8, 0x66, 0x66, 0, 0}, ++ {0xA9, 0x66, 0x66, 0, 0}, ++ {0xAA, 0x66, 0x66, 0, 0}, ++ {0xAB, 0x66, 0x66, 0, 0}, ++ {0xAC, 0x66, 0x66, 0, 0}, ++ {0xAD, 0x66, 0x66, 0, 0}, ++ {0xAE, 0x66, 0x66, 0, 0}, ++ {0xAF, 0x66, 0x66, 0, 0}, ++ {0xB0, 0x66, 0x66, 0, 0}, ++ {0xB1, 0x66, 0x66, 0, 0}, ++ {0xB2, 0x66, 0x66, 0, 0}, ++ {0xB3, 0xa, 0xa, 0, 0}, ++ {0xB4, 0, 0, 0, 0}, ++ {0xB5, 0, 0, 0, 0}, ++ {0xB6, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_TX_2056_rev6[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0x88, 0x88, 0, 0}, ++ {0x22, 0x88, 0x88, 0, 0}, ++ {0x23, 0x88, 0x88, 0, 0}, ++ {0x24, 0x88, 0x88, 0, 0}, ++ {0x25, 0xc, 0xc, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0x3, 0x3, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0x3, 0x3, 0, 0}, ++ {0x2A, 0x37, 0x37, 0, 0}, ++ {0x2B, 0x3, 0x3, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0x1, 0x1, 0, 0}, ++ {0x2F, 0x1, 0x1, 0, 0}, ++ {0x30, 0, 0, 0, 0}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0x11, 0x11, 0, 0}, ++ {0x34, 0xee, 0xee, 1, 1}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0x3, 0x3, 0, 0}, ++ {0x38, 0x50, 0x50, 1, 1}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0x50, 0x50, 1, 1}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x6e, 0x6e, 0, 0}, ++ {0x3D, 0xf0, 0xf0, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x3, 0x3, 0, 0}, ++ {0x42, 0x3, 0x3, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x1e, 0x1e, 0, 0}, ++ {0x45, 0, 0, 0, 0}, ++ {0x46, 0x6e, 0x6e, 0, 0}, ++ {0x47, 0xf0, 0xf0, 1, 1}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x2, 0x2, 0, 0}, ++ {0x4A, 0xff, 0xff, 1, 1}, ++ {0x4B, 0xc, 0xc, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0x38, 0x38, 0, 0}, ++ {0x4E, 0x70, 0x70, 1, 1}, ++ {0x4F, 0x2, 0x2, 0, 0}, ++ {0x50, 0x88, 0x88, 0, 0}, ++ {0x51, 0xc, 0xc, 0, 0}, ++ {0x52, 0, 0, 0, 0}, ++ {0x53, 0x8, 0x8, 0, 0}, ++ {0x54, 0x70, 0x70, 1, 1}, ++ {0x55, 0x2, 0x2, 0, 0}, ++ {0x56, 0xff, 0xff, 1, 1}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x83, 0x83, 0, 0}, ++ {0x59, 0x77, 0x77, 1, 1}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x88, 0x88, 0, 0}, ++ {0x5D, 0, 0, 0, 0}, ++ {0x5E, 0x8, 0x8, 0, 0}, ++ {0x5F, 0x77, 0x77, 1, 1}, ++ {0x60, 0x1, 0x1, 0, 0}, ++ {0x61, 0, 0, 0, 0}, ++ {0x62, 0x7, 0x7, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0x7, 0x7, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 1, 1}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0xa, 0xa, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0x2, 0x2, 0, 0}, ++ {0x72, 0, 0, 0, 0}, ++ {0x73, 0, 0, 0, 0}, ++ {0x74, 0xe, 0xe, 0, 0}, ++ {0x75, 0xe, 0xe, 0, 0}, ++ {0x76, 0xe, 0xe, 0, 0}, ++ {0x77, 0x13, 0x13, 0, 0}, ++ {0x78, 0x13, 0x13, 0, 0}, ++ {0x79, 0x1b, 0x1b, 0, 0}, ++ {0x7A, 0x1b, 0x1b, 0, 0}, ++ {0x7B, 0x55, 0x55, 0, 0}, ++ {0x7C, 0x5b, 0x5b, 0, 0}, ++ {0x7D, 0x30, 0x30, 1, 1}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0x70, 0x70, 0, 0}, ++ {0x94, 0x70, 0x70, 0, 0}, ++ {0x95, 0x70, 0x70, 0, 0}, ++ {0x96, 0x70, 0x70, 0, 0}, ++ {0x97, 0x70, 0x70, 0, 0}, ++ {0x98, 0x70, 0x70, 0, 0}, ++ {0x99, 0x70, 0x70, 0, 0}, ++ {0x9A, 0x70, 0x70, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_RX_2056_rev6[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0x3, 0x3, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0, 0, 0, 0}, ++ {0x23, 0x90, 0x90, 0, 0}, ++ {0x24, 0x55, 0x55, 0, 0}, ++ {0x25, 0x15, 0x15, 0, 0}, ++ {0x26, 0x5, 0x5, 0, 0}, ++ {0x27, 0x15, 0x15, 0, 0}, ++ {0x28, 0x5, 0x5, 0, 0}, ++ {0x29, 0x20, 0x20, 0, 0}, ++ {0x2A, 0x11, 0x11, 0, 0}, ++ {0x2B, 0x90, 0x90, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0x88, 0x88, 0, 0}, ++ {0x2E, 0x32, 0x32, 0, 0}, ++ {0x2F, 0x77, 0x77, 0, 0}, ++ {0x30, 0x17, 0x17, 1, 1}, ++ {0x31, 0xff, 0xff, 1, 1}, ++ {0x32, 0x20, 0x20, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0x88, 0x88, 0, 0}, ++ {0x35, 0x32, 0x32, 0, 0}, ++ {0x36, 0x77, 0x77, 0, 0}, ++ {0x37, 0x17, 0x17, 1, 1}, ++ {0x38, 0xf0, 0xf0, 1, 1}, ++ {0x39, 0x20, 0x20, 0, 0}, ++ {0x3A, 0x8, 0x8, 0, 0}, ++ {0x3B, 0x55, 0x55, 1, 1}, ++ {0x3C, 0, 0, 0, 0}, ++ {0x3D, 0x88, 0x88, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0x44, 0x44, 0, 0}, ++ {0x40, 0x7, 0x7, 1, 1}, ++ {0x41, 0x6, 0x6, 0, 0}, ++ {0x42, 0x4, 0x4, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x8, 0x8, 0, 0}, ++ {0x45, 0x55, 0x55, 1, 1}, ++ {0x46, 0, 0, 0, 0}, ++ {0x47, 0x11, 0x11, 0, 0}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x44, 0x44, 0, 0}, ++ {0x4A, 0x7, 0x7, 0, 0}, ++ {0x4B, 0x6, 0x6, 0, 0}, ++ {0x4C, 0x4, 0x4, 0, 0}, ++ {0x4D, 0, 0, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0x26, 0x26, 1, 1}, ++ {0x50, 0x26, 0x26, 1, 1}, ++ {0x51, 0xf, 0xf, 1, 1}, ++ {0x52, 0xf, 0xf, 1, 1}, ++ {0x53, 0x44, 0x44, 0, 0}, ++ {0x54, 0, 0, 0, 0}, ++ {0x55, 0, 0, 0, 0}, ++ {0x56, 0x8, 0x8, 0, 0}, ++ {0x57, 0x8, 0x8, 0, 0}, ++ {0x58, 0x7, 0x7, 0, 0}, ++ {0x59, 0x22, 0x22, 0, 0}, ++ {0x5A, 0x22, 0x22, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x4, 0x4, 1, 1}, ++ {0x5D, 0x7, 0x7, 0, 0}, ++ {0x5E, 0x55, 0x55, 0, 0}, ++ {0x5F, 0x23, 0x23, 0, 0}, ++ {0x60, 0x41, 0x41, 0, 0}, ++ {0x61, 0x1, 0x1, 0, 0}, ++ {0x62, 0xa, 0xa, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0xc, 0xc, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0, 0, 0, 0}, ++ {0x72, 0x22, 0x22, 0, 0}, ++ {0x73, 0x22, 0x22, 0, 0}, ++ {0x74, 0, 0, 1, 1}, ++ {0x75, 0xa, 0xa, 0, 0}, ++ {0x76, 0x1, 0x1, 0, 0}, ++ {0x77, 0x22, 0x22, 0, 0}, ++ {0x78, 0x30, 0x30, 0, 0}, ++ {0x79, 0, 0, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0x5, 0x5, 1, 1}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0} ++}; ++ ++static struct radio_regs regs_SYN_2056_rev7[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0x1, 0x1, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0x60, 0x60, 0, 0}, ++ {0x23, 0x6, 0x6, 0, 0}, ++ {0x24, 0xc, 0xc, 0, 0}, ++ {0x25, 0, 0, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0, 0, 0, 0}, ++ {0x28, 0x1, 0x1, 0, 0}, ++ {0x29, 0, 0, 0, 0}, ++ {0x2A, 0, 0, 0, 0}, ++ {0x2B, 0, 0, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0, 0, 0, 0}, ++ {0x2F, 0x1f, 0x1f, 0, 0}, ++ {0x30, 0x15, 0x15, 0, 0}, ++ {0x31, 0xf, 0xf, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0, 0, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0, 0, 0, 0}, ++ {0x38, 0, 0, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0, 0, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x13, 0x13, 0, 0}, ++ {0x3D, 0xf, 0xf, 0, 0}, ++ {0x3E, 0x18, 0x18, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x20, 0x20, 0, 0}, ++ {0x42, 0x20, 0x20, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x77, 0x77, 0, 0}, ++ {0x45, 0x7, 0x7, 0, 0}, ++ {0x46, 0x1, 0x1, 0, 0}, ++ {0x47, 0x4, 0x4, 0, 0}, ++ {0x48, 0xf, 0xf, 0, 0}, ++ {0x49, 0x30, 0x30, 0, 0}, ++ {0x4A, 0x32, 0x32, 0, 0}, ++ {0x4B, 0xd, 0xd, 0, 0}, ++ {0x4C, 0xd, 0xd, 0, 0}, ++ {0x4D, 0x4, 0x4, 0, 0}, ++ {0x4E, 0x6, 0x6, 0, 0}, ++ {0x4F, 0x1, 0x1, 0, 0}, ++ {0x50, 0x1c, 0x1c, 0, 0}, ++ {0x51, 0x2, 0x2, 0, 0}, ++ {0x52, 0x2, 0x2, 0, 0}, ++ {0x53, 0xf7, 0xf7, 1, 1}, ++ {0x54, 0xb4, 0xb4, 0, 0}, ++ {0x55, 0xd2, 0xd2, 0, 0}, ++ {0x56, 0, 0, 0, 0}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x4, 0x4, 0, 0}, ++ {0x59, 0x96, 0x96, 0, 0}, ++ {0x5A, 0x3e, 0x3e, 0, 0}, ++ {0x5B, 0x3e, 0x3e, 0, 0}, ++ {0x5C, 0x13, 0x13, 0, 0}, ++ {0x5D, 0x2, 0x2, 0, 0}, ++ {0x5E, 0, 0, 0, 0}, ++ {0x5F, 0x7, 0x7, 0, 0}, ++ {0x60, 0x7, 0x7, 1, 1}, ++ {0x61, 0x8, 0x8, 0, 0}, ++ {0x62, 0x3, 0x3, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0x40, 0x40, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0x1, 0x1, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0x60, 0x60, 0, 0}, ++ {0x71, 0x66, 0x66, 0, 0}, ++ {0x72, 0xc, 0xc, 0, 0}, ++ {0x73, 0x66, 0x66, 0, 0}, ++ {0x74, 0x8f, 0x8f, 1, 1}, ++ {0x75, 0, 0, 0, 0}, ++ {0x76, 0xcc, 0xcc, 0, 0}, ++ {0x77, 0x1, 0x1, 0, 0}, ++ {0x78, 0x66, 0x66, 0, 0}, ++ {0x79, 0x66, 0x66, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0xff, 0xff, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0x95, 0, 0, 0, 0}, ++ {0x96, 0, 0, 0, 0}, ++ {0x97, 0, 0, 0, 0}, ++ {0x98, 0, 0, 0, 0}, ++ {0x99, 0, 0, 0, 0}, ++ {0x9A, 0, 0, 0, 0}, ++ {0x9B, 0, 0, 0, 0}, ++ {0x9C, 0, 0, 0, 0}, ++ {0x9D, 0, 0, 0, 0}, ++ {0x9E, 0, 0, 0, 0}, ++ {0x9F, 0x6, 0x6, 0, 0}, ++ {0xA0, 0x66, 0x66, 0, 0}, ++ {0xA1, 0x66, 0x66, 0, 0}, ++ {0xA2, 0x66, 0x66, 0, 0}, ++ {0xA3, 0x66, 0x66, 0, 0}, ++ {0xA4, 0x66, 0x66, 0, 0}, ++ {0xA5, 0x66, 0x66, 0, 0}, ++ {0xA6, 0x66, 0x66, 0, 0}, ++ {0xA7, 0x66, 0x66, 0, 0}, ++ {0xA8, 0x66, 0x66, 0, 0}, ++ {0xA9, 0x66, 0x66, 0, 0}, ++ {0xAA, 0x66, 0x66, 0, 0}, ++ {0xAB, 0x66, 0x66, 0, 0}, ++ {0xAC, 0x66, 0x66, 0, 0}, ++ {0xAD, 0x66, 0x66, 0, 0}, ++ {0xAE, 0x66, 0x66, 0, 0}, ++ {0xAF, 0x66, 0x66, 0, 0}, ++ {0xB0, 0x66, 0x66, 0, 0}, ++ {0xB1, 0x66, 0x66, 0, 0}, ++ {0xB2, 0x66, 0x66, 0, 0}, ++ {0xB3, 0xa, 0xa, 0, 0}, ++ {0xB4, 0, 0, 0, 0}, ++ {0xB5, 0, 0, 0, 0}, ++ {0xB6, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static struct radio_regs regs_TX_2056_rev7[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0x88, 0x88, 0, 0}, ++ {0x22, 0x88, 0x88, 0, 0}, ++ {0x23, 0x88, 0x88, 0, 0}, ++ {0x24, 0x88, 0x88, 0, 0}, ++ {0x25, 0xc, 0xc, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0x3, 0x3, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0x3, 0x3, 0, 0}, ++ {0x2A, 0x37, 0x37, 0, 0}, ++ {0x2B, 0x3, 0x3, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0x1, 0x1, 0, 0}, ++ {0x2F, 0x1, 0x1, 0, 0}, ++ {0x30, 0, 0, 0, 0}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0x11, 0x11, 0, 0}, ++ {0x34, 0xee, 0xee, 1, 1}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0x3, 0x3, 0, 0}, ++ {0x38, 0x50, 0x50, 1, 1}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0x50, 0x50, 1, 1}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x6e, 0x6e, 0, 0}, ++ {0x3D, 0xf0, 0xf0, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x3, 0x3, 0, 0}, ++ {0x42, 0x3, 0x3, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x1e, 0x1e, 0, 0}, ++ {0x45, 0, 0, 0, 0}, ++ {0x46, 0x6e, 0x6e, 0, 0}, ++ {0x47, 0xf0, 0xf0, 1, 1}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x2, 0x2, 0, 0}, ++ {0x4A, 0xff, 0xff, 1, 1}, ++ {0x4B, 0xc, 0xc, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0x38, 0x38, 0, 0}, ++ {0x4E, 0x70, 0x70, 1, 1}, ++ {0x4F, 0x2, 0x2, 0, 0}, ++ {0x50, 0x88, 0x88, 0, 0}, ++ {0x51, 0xc, 0xc, 0, 0}, ++ {0x52, 0, 0, 0, 0}, ++ {0x53, 0x8, 0x8, 0, 0}, ++ {0x54, 0x70, 0x70, 1, 1}, ++ {0x55, 0x2, 0x2, 0, 0}, ++ {0x56, 0xff, 0xff, 1, 1}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x83, 0x83, 0, 0}, ++ {0x59, 0x77, 0x77, 1, 1}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x88, 0x88, 0, 0}, ++ {0x5D, 0, 0, 0, 0}, ++ {0x5E, 0x8, 0x8, 0, 0}, ++ {0x5F, 0x77, 0x77, 1, 1}, ++ {0x60, 0x1, 0x1, 0, 0}, ++ {0x61, 0, 0, 0, 0}, ++ {0x62, 0x7, 0x7, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0x7, 0x7, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 1, 1}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0xa, 0xa, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0x2, 0x2, 0, 0}, ++ {0x72, 0, 0, 0, 0}, ++ {0x73, 0, 0, 0, 0}, ++ {0x74, 0xe, 0xe, 0, 0}, ++ {0x75, 0xe, 0xe, 0, 0}, ++ {0x76, 0xe, 0xe, 0, 0}, ++ {0x77, 0x13, 0x13, 0, 0}, ++ {0x78, 0x13, 0x13, 0, 0}, ++ {0x79, 0x1b, 0x1b, 0, 0}, ++ {0x7A, 0x1b, 0x1b, 0, 0}, ++ {0x7B, 0x55, 0x55, 0, 0}, ++ {0x7C, 0x5b, 0x5b, 0, 0}, ++ {0x7D, 0x30, 0x30, 1, 1}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0x70, 0x70, 0, 0}, ++ {0x94, 0x70, 0x70, 0, 0}, ++ {0x95, 0x71, 0x71, 1, 1}, ++ {0x96, 0x71, 0x71, 1, 1}, ++ {0x97, 0x72, 0x72, 1, 1}, ++ {0x98, 0x73, 0x73, 1, 1}, ++ {0x99, 0x74, 0x74, 1, 1}, ++ {0x9A, 0x75, 0x75, 1, 1}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static struct radio_regs regs_RX_2056_rev7[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0x3, 0x3, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0, 0, 0, 0}, ++ {0x23, 0x90, 0x90, 0, 0}, ++ {0x24, 0x55, 0x55, 0, 0}, ++ {0x25, 0x15, 0x15, 0, 0}, ++ {0x26, 0x5, 0x5, 0, 0}, ++ {0x27, 0x15, 0x15, 0, 0}, ++ {0x28, 0x5, 0x5, 0, 0}, ++ {0x29, 0x20, 0x20, 0, 0}, ++ {0x2A, 0x11, 0x11, 0, 0}, ++ {0x2B, 0x90, 0x90, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0x88, 0x88, 0, 0}, ++ {0x2E, 0x32, 0x32, 0, 0}, ++ {0x2F, 0x77, 0x77, 0, 0}, ++ {0x30, 0x17, 0x17, 1, 1}, ++ {0x31, 0xff, 0xff, 1, 1}, ++ {0x32, 0x20, 0x20, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0x88, 0x88, 0, 0}, ++ {0x35, 0x32, 0x32, 0, 0}, ++ {0x36, 0x77, 0x77, 0, 0}, ++ {0x37, 0x17, 0x17, 1, 1}, ++ {0x38, 0xf0, 0xf0, 1, 1}, ++ {0x39, 0x20, 0x20, 0, 0}, ++ {0x3A, 0x8, 0x8, 0, 0}, ++ {0x3B, 0x55, 0x55, 1, 1}, ++ {0x3C, 0, 0, 0, 0}, ++ {0x3D, 0x88, 0x88, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 1, 1}, ++ {0x40, 0x7, 0x7, 1, 1}, ++ {0x41, 0x6, 0x6, 0, 0}, ++ {0x42, 0x4, 0x4, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x8, 0x8, 0, 0}, ++ {0x45, 0x55, 0x55, 1, 1}, ++ {0x46, 0, 0, 0, 0}, ++ {0x47, 0x11, 0x11, 0, 0}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0, 0, 1, 1}, ++ {0x4A, 0x7, 0x7, 0, 0}, ++ {0x4B, 0x6, 0x6, 0, 0}, ++ {0x4C, 0x4, 0x4, 0, 0}, ++ {0x4D, 0, 0, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0x26, 0x26, 1, 1}, ++ {0x50, 0x26, 0x26, 1, 1}, ++ {0x51, 0xf, 0xf, 1, 1}, ++ {0x52, 0xf, 0xf, 1, 1}, ++ {0x53, 0x44, 0x44, 0, 0}, ++ {0x54, 0, 0, 0, 0}, ++ {0x55, 0, 0, 0, 0}, ++ {0x56, 0x8, 0x8, 0, 0}, ++ {0x57, 0x8, 0x8, 0, 0}, ++ {0x58, 0x7, 0x7, 0, 0}, ++ {0x59, 0x22, 0x22, 0, 0}, ++ {0x5A, 0x22, 0x22, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x4, 0x4, 1, 1}, ++ {0x5D, 0x7, 0x7, 0, 0}, ++ {0x5E, 0x55, 0x55, 0, 0}, ++ {0x5F, 0x23, 0x23, 0, 0}, ++ {0x60, 0x41, 0x41, 0, 0}, ++ {0x61, 0x1, 0x1, 0, 0}, ++ {0x62, 0xa, 0xa, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0xc, 0xc, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0, 0, 0, 0}, ++ {0x72, 0x22, 0x22, 0, 0}, ++ {0x73, 0x22, 0x22, 0, 0}, ++ {0x74, 0, 0, 1, 1}, ++ {0x75, 0xa, 0xa, 0, 0}, ++ {0x76, 0x1, 0x1, 0, 0}, ++ {0x77, 0x22, 0x22, 0, 0}, ++ {0x78, 0x30, 0x30, 0, 0}, ++ {0x79, 0, 0, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static struct radio_regs regs_SYN_2056_rev8[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0x1, 0x1, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0x60, 0x60, 0, 0}, ++ {0x23, 0x6, 0x6, 0, 0}, ++ {0x24, 0xc, 0xc, 0, 0}, ++ {0x25, 0, 0, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0, 0, 0, 0}, ++ {0x28, 0x1, 0x1, 0, 0}, ++ {0x29, 0, 0, 0, 0}, ++ {0x2A, 0, 0, 0, 0}, ++ {0x2B, 0, 0, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0, 0, 0, 0}, ++ {0x2F, 0x1f, 0x1f, 0, 0}, ++ {0x30, 0x15, 0x15, 0, 0}, ++ {0x31, 0xf, 0xf, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0, 0, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0, 0, 0, 0}, ++ {0x38, 0, 0, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0, 0, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x13, 0x13, 0, 0}, ++ {0x3D, 0xf, 0xf, 0, 0}, ++ {0x3E, 0x18, 0x18, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x20, 0x20, 0, 0}, ++ {0x42, 0x20, 0x20, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x77, 0x77, 0, 0}, ++ {0x45, 0x7, 0x7, 0, 0}, ++ {0x46, 0x1, 0x1, 0, 0}, ++ {0x47, 0x4, 0x4, 0, 0}, ++ {0x48, 0xf, 0xf, 0, 0}, ++ {0x49, 0x30, 0x30, 0, 0}, ++ {0x4A, 0x32, 0x32, 0, 0}, ++ {0x4B, 0xd, 0xd, 0, 0}, ++ {0x4C, 0xd, 0xd, 0, 0}, ++ {0x4D, 0x4, 0x4, 0, 0}, ++ {0x4E, 0x6, 0x6, 0, 0}, ++ {0x4F, 0x1, 0x1, 0, 0}, ++ {0x50, 0x1c, 0x1c, 0, 0}, ++ {0x51, 0x2, 0x2, 0, 0}, ++ {0x52, 0x2, 0x2, 0, 0}, ++ {0x53, 0xf7, 0xf7, 1, 1}, ++ {0x54, 0xb4, 0xb4, 0, 0}, ++ {0x55, 0xd2, 0xd2, 0, 0}, ++ {0x56, 0, 0, 0, 0}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x4, 0x4, 0, 0}, ++ {0x59, 0x96, 0x96, 0, 0}, ++ {0x5A, 0x3e, 0x3e, 0, 0}, ++ {0x5B, 0x3e, 0x3e, 0, 0}, ++ {0x5C, 0x13, 0x13, 0, 0}, ++ {0x5D, 0x2, 0x2, 0, 0}, ++ {0x5E, 0, 0, 0, 0}, ++ {0x5F, 0x7, 0x7, 0, 0}, ++ {0x60, 0x7, 0x7, 1, 1}, ++ {0x61, 0x8, 0x8, 0, 0}, ++ {0x62, 0x3, 0x3, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0x40, 0x40, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0x1, 0x1, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0x60, 0x60, 0, 0}, ++ {0x71, 0x66, 0x66, 0, 0}, ++ {0x72, 0xc, 0xc, 0, 0}, ++ {0x73, 0x66, 0x66, 0, 0}, ++ {0x74, 0x8f, 0x8f, 1, 1}, ++ {0x75, 0, 0, 0, 0}, ++ {0x76, 0xcc, 0xcc, 0, 0}, ++ {0x77, 0x1, 0x1, 0, 0}, ++ {0x78, 0x66, 0x66, 0, 0}, ++ {0x79, 0x66, 0x66, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0xff, 0xff, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0x95, 0, 0, 0, 0}, ++ {0x96, 0, 0, 0, 0}, ++ {0x97, 0, 0, 0, 0}, ++ {0x98, 0, 0, 0, 0}, ++ {0x99, 0, 0, 0, 0}, ++ {0x9A, 0, 0, 0, 0}, ++ {0x9B, 0, 0, 0, 0}, ++ {0x9C, 0, 0, 0, 0}, ++ {0x9D, 0, 0, 0, 0}, ++ {0x9E, 0, 0, 0, 0}, ++ {0x9F, 0x6, 0x6, 0, 0}, ++ {0xA0, 0x66, 0x66, 0, 0}, ++ {0xA1, 0x66, 0x66, 0, 0}, ++ {0xA2, 0x66, 0x66, 0, 0}, ++ {0xA3, 0x66, 0x66, 0, 0}, ++ {0xA4, 0x66, 0x66, 0, 0}, ++ {0xA5, 0x66, 0x66, 0, 0}, ++ {0xA6, 0x66, 0x66, 0, 0}, ++ {0xA7, 0x66, 0x66, 0, 0}, ++ {0xA8, 0x66, 0x66, 0, 0}, ++ {0xA9, 0x66, 0x66, 0, 0}, ++ {0xAA, 0x66, 0x66, 0, 0}, ++ {0xAB, 0x66, 0x66, 0, 0}, ++ {0xAC, 0x66, 0x66, 0, 0}, ++ {0xAD, 0x66, 0x66, 0, 0}, ++ {0xAE, 0x66, 0x66, 0, 0}, ++ {0xAF, 0x66, 0x66, 0, 0}, ++ {0xB0, 0x66, 0x66, 0, 0}, ++ {0xB1, 0x66, 0x66, 0, 0}, ++ {0xB2, 0x66, 0x66, 0, 0}, ++ {0xB3, 0xa, 0xa, 0, 0}, ++ {0xB4, 0, 0, 0, 0}, ++ {0xB5, 0, 0, 0, 0}, ++ {0xB6, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static struct radio_regs regs_TX_2056_rev8[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0x88, 0x88, 0, 0}, ++ {0x22, 0x88, 0x88, 0, 0}, ++ {0x23, 0x88, 0x88, 0, 0}, ++ {0x24, 0x88, 0x88, 0, 0}, ++ {0x25, 0xc, 0xc, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0x3, 0x3, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0x3, 0x3, 0, 0}, ++ {0x2A, 0x37, 0x37, 0, 0}, ++ {0x2B, 0x3, 0x3, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0x1, 0x1, 0, 0}, ++ {0x2F, 0x1, 0x1, 0, 0}, ++ {0x30, 0, 0, 0, 0}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0x11, 0x11, 0, 0}, ++ {0x34, 0xee, 0xee, 1, 1}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0x3, 0x3, 0, 0}, ++ {0x38, 0x50, 0x50, 1, 1}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0x50, 0x50, 1, 1}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x6e, 0x6e, 0, 0}, ++ {0x3D, 0xf0, 0xf0, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x3, 0x3, 0, 0}, ++ {0x42, 0x3, 0x3, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x1e, 0x1e, 0, 0}, ++ {0x45, 0, 0, 0, 0}, ++ {0x46, 0x6e, 0x6e, 0, 0}, ++ {0x47, 0xf0, 0xf0, 1, 1}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x2, 0x2, 0, 0}, ++ {0x4A, 0xff, 0xff, 1, 1}, ++ {0x4B, 0xc, 0xc, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0x38, 0x38, 0, 0}, ++ {0x4E, 0x70, 0x70, 1, 1}, ++ {0x4F, 0x2, 0x2, 0, 0}, ++ {0x50, 0x88, 0x88, 0, 0}, ++ {0x51, 0xc, 0xc, 0, 0}, ++ {0x52, 0, 0, 0, 0}, ++ {0x53, 0x8, 0x8, 0, 0}, ++ {0x54, 0x70, 0x70, 1, 1}, ++ {0x55, 0x2, 0x2, 0, 0}, ++ {0x56, 0xff, 0xff, 1, 1}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x83, 0x83, 0, 0}, ++ {0x59, 0x77, 0x77, 1, 1}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x88, 0x88, 0, 0}, ++ {0x5D, 0, 0, 0, 0}, ++ {0x5E, 0x8, 0x8, 0, 0}, ++ {0x5F, 0x77, 0x77, 1, 1}, ++ {0x60, 0x1, 0x1, 0, 0}, ++ {0x61, 0, 0, 0, 0}, ++ {0x62, 0x7, 0x7, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0x7, 0x7, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 1, 1}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0xa, 0xa, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0x2, 0x2, 0, 0}, ++ {0x72, 0, 0, 0, 0}, ++ {0x73, 0, 0, 0, 0}, ++ {0x74, 0xe, 0xe, 0, 0}, ++ {0x75, 0xe, 0xe, 0, 0}, ++ {0x76, 0xe, 0xe, 0, 0}, ++ {0x77, 0x13, 0x13, 0, 0}, ++ {0x78, 0x13, 0x13, 0, 0}, ++ {0x79, 0x1b, 0x1b, 0, 0}, ++ {0x7A, 0x1b, 0x1b, 0, 0}, ++ {0x7B, 0x55, 0x55, 0, 0}, ++ {0x7C, 0x5b, 0x5b, 0, 0}, ++ {0x7D, 0x30, 0x30, 1, 1}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0x70, 0x70, 0, 0}, ++ {0x94, 0x70, 0x70, 0, 0}, ++ {0x95, 0x70, 0x70, 0, 0}, ++ {0x96, 0x70, 0x70, 0, 0}, ++ {0x97, 0x70, 0x70, 0, 0}, ++ {0x98, 0x70, 0x70, 0, 0}, ++ {0x99, 0x70, 0x70, 0, 0}, ++ {0x9A, 0x70, 0x70, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static struct radio_regs regs_RX_2056_rev8[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0x3, 0x3, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0, 0, 0, 0}, ++ {0x23, 0x90, 0x90, 0, 0}, ++ {0x24, 0x55, 0x55, 0, 0}, ++ {0x25, 0x15, 0x15, 0, 0}, ++ {0x26, 0x5, 0x5, 0, 0}, ++ {0x27, 0x15, 0x15, 0, 0}, ++ {0x28, 0x5, 0x5, 0, 0}, ++ {0x29, 0x20, 0x20, 0, 0}, ++ {0x2A, 0x11, 0x11, 0, 0}, ++ {0x2B, 0x90, 0x90, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0x88, 0x88, 0, 0}, ++ {0x2E, 0x32, 0x32, 0, 0}, ++ {0x2F, 0x77, 0x77, 0, 0}, ++ {0x30, 0x17, 0x17, 1, 1}, ++ {0x31, 0xff, 0xff, 1, 1}, ++ {0x32, 0x20, 0x20, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0x88, 0x88, 0, 0}, ++ {0x35, 0x32, 0x32, 0, 0}, ++ {0x36, 0x77, 0x77, 0, 0}, ++ {0x37, 0x17, 0x17, 1, 1}, ++ {0x38, 0xf0, 0xf0, 1, 1}, ++ {0x39, 0x20, 0x20, 0, 0}, ++ {0x3A, 0x8, 0x8, 0, 0}, ++ {0x3B, 0x55, 0x55, 1, 1}, ++ {0x3C, 0, 0, 0, 0}, ++ {0x3D, 0x88, 0x88, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0x44, 0x44, 0, 0}, ++ {0x40, 0x7, 0x7, 1, 1}, ++ {0x41, 0x6, 0x6, 0, 0}, ++ {0x42, 0x4, 0x4, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x8, 0x8, 0, 0}, ++ {0x45, 0x55, 0x55, 1, 1}, ++ {0x46, 0, 0, 0, 0}, ++ {0x47, 0x11, 0x11, 0, 0}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x44, 0x44, 0, 0}, ++ {0x4A, 0x7, 0x7, 0, 0}, ++ {0x4B, 0x6, 0x6, 0, 0}, ++ {0x4C, 0x4, 0x4, 0, 0}, ++ {0x4D, 0, 0, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0x26, 0x26, 1, 1}, ++ {0x50, 0x26, 0x26, 1, 1}, ++ {0x51, 0xf, 0xf, 1, 1}, ++ {0x52, 0xf, 0xf, 1, 1}, ++ {0x53, 0x44, 0x44, 0, 0}, ++ {0x54, 0, 0, 0, 0}, ++ {0x55, 0, 0, 0, 0}, ++ {0x56, 0x8, 0x8, 0, 0}, ++ {0x57, 0x8, 0x8, 0, 0}, ++ {0x58, 0x7, 0x7, 0, 0}, ++ {0x59, 0x22, 0x22, 0, 0}, ++ {0x5A, 0x22, 0x22, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x4, 0x4, 1, 1}, ++ {0x5D, 0x7, 0x7, 0, 0}, ++ {0x5E, 0x55, 0x55, 0, 0}, ++ {0x5F, 0x23, 0x23, 0, 0}, ++ {0x60, 0x41, 0x41, 0, 0}, ++ {0x61, 0x1, 0x1, 0, 0}, ++ {0x62, 0xa, 0xa, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0xc, 0xc, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0, 0, 0, 0}, ++ {0x72, 0x22, 0x22, 0, 0}, ++ {0x73, 0x22, 0x22, 0, 0}, ++ {0x74, 0, 0, 1, 1}, ++ {0x75, 0xa, 0xa, 0, 0}, ++ {0x76, 0x1, 0x1, 0, 0}, ++ {0x77, 0x22, 0x22, 0, 0}, ++ {0x78, 0x30, 0x30, 0, 0}, ++ {0x79, 0, 0, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0x5, 0x5, 1, 1}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static const struct radio_regs regs_SYN_2056_rev11[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0x1, 0x1, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0x60, 0x60, 0, 0}, ++ {0x23, 0x6, 0x6, 0, 0}, ++ {0x24, 0xc, 0xc, 0, 0}, ++ {0x25, 0, 0, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0, 0, 0, 0}, ++ {0x28, 0x1, 0x1, 0, 0}, ++ {0x29, 0, 0, 0, 0}, ++ {0x2A, 0, 0, 0, 0}, ++ {0x2B, 0, 0, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0, 0, 0, 0}, ++ {0x2F, 0x1f, 0x1f, 0, 0}, ++ {0x30, 0x15, 0x15, 0, 0}, ++ {0x31, 0xf, 0xf, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0, 0, 0, 0}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0, 0, 0, 0}, ++ {0x38, 0, 0, 0, 0}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0, 0, 0, 0}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x13, 0x13, 0, 0}, ++ {0x3D, 0xf, 0xf, 0, 0}, ++ {0x3E, 0x18, 0x18, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x20, 0x20, 0, 0}, ++ {0x42, 0x20, 0x20, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x77, 0x77, 0, 0}, ++ {0x45, 0x7, 0x7, 0, 0}, ++ {0x46, 0x1, 0x1, 0, 0}, ++ {0x47, 0x6, 0x6, 1, 1}, ++ {0x48, 0xf, 0xf, 0, 0}, ++ {0x49, 0x3f, 0x3f, 1, 1}, ++ {0x4A, 0x32, 0x32, 0, 0}, ++ {0x4B, 0x6, 0x6, 1, 1}, ++ {0x4C, 0x6, 0x6, 1, 1}, ++ {0x4D, 0x4, 0x4, 0, 0}, ++ {0x4E, 0x2b, 0x2b, 1, 1}, ++ {0x4F, 0x1, 0x1, 0, 0}, ++ {0x50, 0x1c, 0x1c, 0, 0}, ++ {0x51, 0x2, 0x2, 0, 0}, ++ {0x52, 0x2, 0x2, 0, 0}, ++ {0x53, 0xf7, 0xf7, 1, 1}, ++ {0x54, 0xb4, 0xb4, 0, 0}, ++ {0x55, 0xd2, 0xd2, 0, 0}, ++ {0x56, 0, 0, 0, 0}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x4, 0x4, 0, 0}, ++ {0x59, 0x96, 0x96, 0, 0}, ++ {0x5A, 0x3e, 0x3e, 0, 0}, ++ {0x5B, 0x3e, 0x3e, 0, 0}, ++ {0x5C, 0x13, 0x13, 0, 0}, ++ {0x5D, 0x2, 0x2, 0, 0}, ++ {0x5E, 0, 0, 0, 0}, ++ {0x5F, 0x7, 0x7, 0, 0}, ++ {0x60, 0x7, 0x7, 1, 1}, ++ {0x61, 0x8, 0x8, 0, 0}, ++ {0x62, 0x3, 0x3, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0x40, 0x40, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0x1, 0x1, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0x60, 0x60, 0, 0}, ++ {0x71, 0x66, 0x66, 0, 0}, ++ {0x72, 0xc, 0xc, 0, 0}, ++ {0x73, 0x66, 0x66, 0, 0}, ++ {0x74, 0x8f, 0x8f, 1, 1}, ++ {0x75, 0, 0, 0, 0}, ++ {0x76, 0xcc, 0xcc, 0, 0}, ++ {0x77, 0x1, 0x1, 0, 0}, ++ {0x78, 0x66, 0x66, 0, 0}, ++ {0x79, 0x66, 0x66, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0, 0, 0, 0}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0xff, 0xff, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0x95, 0, 0, 0, 0}, ++ {0x96, 0, 0, 0, 0}, ++ {0x97, 0, 0, 0, 0}, ++ {0x98, 0, 0, 0, 0}, ++ {0x99, 0, 0, 0, 0}, ++ {0x9A, 0, 0, 0, 0}, ++ {0x9B, 0, 0, 0, 0}, ++ {0x9C, 0, 0, 0, 0}, ++ {0x9D, 0, 0, 0, 0}, ++ {0x9E, 0, 0, 0, 0}, ++ {0x9F, 0x6, 0x6, 0, 0}, ++ {0xA0, 0x66, 0x66, 0, 0}, ++ {0xA1, 0x66, 0x66, 0, 0}, ++ {0xA2, 0x66, 0x66, 0, 0}, ++ {0xA3, 0x66, 0x66, 0, 0}, ++ {0xA4, 0x66, 0x66, 0, 0}, ++ {0xA5, 0x66, 0x66, 0, 0}, ++ {0xA6, 0x66, 0x66, 0, 0}, ++ {0xA7, 0x66, 0x66, 0, 0}, ++ {0xA8, 0x66, 0x66, 0, 0}, ++ {0xA9, 0x66, 0x66, 0, 0}, ++ {0xAA, 0x66, 0x66, 0, 0}, ++ {0xAB, 0x66, 0x66, 0, 0}, ++ {0xAC, 0x66, 0x66, 0, 0}, ++ {0xAD, 0x66, 0x66, 0, 0}, ++ {0xAE, 0x66, 0x66, 0, 0}, ++ {0xAF, 0x66, 0x66, 0, 0}, ++ {0xB0, 0x66, 0x66, 0, 0}, ++ {0xB1, 0x66, 0x66, 0, 0}, ++ {0xB2, 0x66, 0x66, 0, 0}, ++ {0xB3, 0xa, 0xa, 0, 0}, ++ {0xB4, 0, 0, 0, 0}, ++ {0xB5, 0, 0, 0, 0}, ++ {0xB6, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static const struct radio_regs regs_TX_2056_rev11[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0, 0, 0, 0}, ++ {0x21, 0x88, 0x88, 0, 0}, ++ {0x22, 0x88, 0x88, 0, 0}, ++ {0x23, 0x88, 0x88, 0, 0}, ++ {0x24, 0x88, 0x88, 0, 0}, ++ {0x25, 0xc, 0xc, 0, 0}, ++ {0x26, 0, 0, 0, 0}, ++ {0x27, 0x3, 0x3, 0, 0}, ++ {0x28, 0, 0, 0, 0}, ++ {0x29, 0x3, 0x3, 0, 0}, ++ {0x2A, 0x37, 0x37, 0, 0}, ++ {0x2B, 0x3, 0x3, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0, 0, 0, 0}, ++ {0x2E, 0x1, 0x1, 0, 0}, ++ {0x2F, 0x1, 0x1, 0, 0}, ++ {0x30, 0, 0, 0, 0}, ++ {0x31, 0, 0, 0, 0}, ++ {0x32, 0, 0, 0, 0}, ++ {0x33, 0x11, 0x11, 0, 0}, ++ {0x34, 0xee, 0xee, 1, 1}, ++ {0x35, 0, 0, 0, 0}, ++ {0x36, 0, 0, 0, 0}, ++ {0x37, 0x3, 0x3, 0, 0}, ++ {0x38, 0x50, 0x50, 1, 1}, ++ {0x39, 0, 0, 0, 0}, ++ {0x3A, 0x50, 0x50, 1, 1}, ++ {0x3B, 0, 0, 0, 0}, ++ {0x3C, 0x6e, 0x6e, 0, 0}, ++ {0x3D, 0xf0, 0xf0, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0, 0, 0, 0}, ++ {0x40, 0, 0, 0, 0}, ++ {0x41, 0x3, 0x3, 0, 0}, ++ {0x42, 0x3, 0x3, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x1e, 0x1e, 0, 0}, ++ {0x45, 0, 0, 0, 0}, ++ {0x46, 0x6e, 0x6e, 0, 0}, ++ {0x47, 0xf0, 0xf0, 1, 1}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x2, 0x2, 0, 0}, ++ {0x4A, 0xff, 0xff, 1, 1}, ++ {0x4B, 0xc, 0xc, 0, 0}, ++ {0x4C, 0, 0, 0, 0}, ++ {0x4D, 0x38, 0x38, 0, 0}, ++ {0x4E, 0x70, 0x70, 1, 1}, ++ {0x4F, 0x2, 0x2, 0, 0}, ++ {0x50, 0x88, 0x88, 0, 0}, ++ {0x51, 0xc, 0xc, 0, 0}, ++ {0x52, 0, 0, 0, 0}, ++ {0x53, 0x8, 0x8, 0, 0}, ++ {0x54, 0x70, 0x70, 1, 1}, ++ {0x55, 0x2, 0x2, 0, 0}, ++ {0x56, 0xff, 0xff, 1, 1}, ++ {0x57, 0, 0, 0, 0}, ++ {0x58, 0x83, 0x83, 0, 0}, ++ {0x59, 0x77, 0x77, 1, 1}, ++ {0x5A, 0, 0, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x88, 0x88, 0, 0}, ++ {0x5D, 0, 0, 0, 0}, ++ {0x5E, 0x8, 0x8, 0, 0}, ++ {0x5F, 0x77, 0x77, 1, 1}, ++ {0x60, 0x1, 0x1, 0, 0}, ++ {0x61, 0, 0, 0, 0}, ++ {0x62, 0x7, 0x7, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0x7, 0x7, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 1, 1}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0xa, 0xa, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0, 0, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0x2, 0x2, 0, 0}, ++ {0x72, 0, 0, 0, 0}, ++ {0x73, 0, 0, 0, 0}, ++ {0x74, 0xe, 0xe, 0, 0}, ++ {0x75, 0xe, 0xe, 0, 0}, ++ {0x76, 0xe, 0xe, 0, 0}, ++ {0x77, 0x13, 0x13, 0, 0}, ++ {0x78, 0x13, 0x13, 0, 0}, ++ {0x79, 0x1b, 0x1b, 0, 0}, ++ {0x7A, 0x1b, 0x1b, 0, 0}, ++ {0x7B, 0x55, 0x55, 0, 0}, ++ {0x7C, 0x5b, 0x5b, 0, 0}, ++ {0x7D, 0x30, 0x30, 1, 1}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0x70, 0x70, 0, 0}, ++ {0x94, 0x70, 0x70, 0, 0}, ++ {0x95, 0x70, 0x70, 0, 0}, ++ {0x96, 0x70, 0x70, 0, 0}, ++ {0x97, 0x70, 0x70, 0, 0}, ++ {0x98, 0x70, 0x70, 0, 0}, ++ {0x99, 0x70, 0x70, 0, 0}, ++ {0x9A, 0x70, 0x70, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static const struct radio_regs regs_RX_2056_rev11[] = { ++ {0x02, 0, 0, 0, 0}, ++ {0x03, 0, 0, 0, 0}, ++ {0x04, 0, 0, 0, 0}, ++ {0x05, 0, 0, 0, 0}, ++ {0x06, 0, 0, 0, 0}, ++ {0x07, 0, 0, 0, 0}, ++ {0x08, 0, 0, 0, 0}, ++ {0x09, 0, 0, 0, 0}, ++ {0x0A, 0, 0, 0, 0}, ++ {0x0B, 0, 0, 0, 0}, ++ {0x0C, 0, 0, 0, 0}, ++ {0x0D, 0, 0, 0, 0}, ++ {0x0E, 0, 0, 0, 0}, ++ {0x0F, 0, 0, 0, 0}, ++ {0x10, 0, 0, 0, 0}, ++ {0x11, 0, 0, 0, 0}, ++ {0x12, 0, 0, 0, 0}, ++ {0x13, 0, 0, 0, 0}, ++ {0x14, 0, 0, 0, 0}, ++ {0x15, 0, 0, 0, 0}, ++ {0x16, 0, 0, 0, 0}, ++ {0x17, 0, 0, 0, 0}, ++ {0x18, 0, 0, 0, 0}, ++ {0x19, 0, 0, 0, 0}, ++ {0x1A, 0, 0, 0, 0}, ++ {0x1B, 0, 0, 0, 0}, ++ {0x1C, 0, 0, 0, 0}, ++ {0x1D, 0, 0, 0, 0}, ++ {0x1E, 0, 0, 0, 0}, ++ {0x1F, 0, 0, 0, 0}, ++ {0x20, 0x3, 0x3, 0, 0}, ++ {0x21, 0, 0, 0, 0}, ++ {0x22, 0, 0, 0, 0}, ++ {0x23, 0x90, 0x90, 0, 0}, ++ {0x24, 0x55, 0x55, 0, 0}, ++ {0x25, 0x15, 0x15, 0, 0}, ++ {0x26, 0x5, 0x5, 0, 0}, ++ {0x27, 0x15, 0x15, 0, 0}, ++ {0x28, 0x5, 0x5, 0, 0}, ++ {0x29, 0x20, 0x20, 0, 0}, ++ {0x2A, 0x11, 0x11, 0, 0}, ++ {0x2B, 0x90, 0x90, 0, 0}, ++ {0x2C, 0, 0, 0, 0}, ++ {0x2D, 0x88, 0x88, 0, 0}, ++ {0x2E, 0x32, 0x32, 0, 0}, ++ {0x2F, 0x77, 0x77, 0, 0}, ++ {0x30, 0x17, 0x17, 1, 1}, ++ {0x31, 0xff, 0xff, 1, 1}, ++ {0x32, 0x20, 0x20, 0, 0}, ++ {0x33, 0, 0, 0, 0}, ++ {0x34, 0x88, 0x88, 0, 0}, ++ {0x35, 0x32, 0x32, 0, 0}, ++ {0x36, 0x77, 0x77, 0, 0}, ++ {0x37, 0x17, 0x17, 1, 1}, ++ {0x38, 0xf0, 0xf0, 1, 1}, ++ {0x39, 0x20, 0x20, 0, 0}, ++ {0x3A, 0x8, 0x8, 0, 0}, ++ {0x3B, 0x55, 0x55, 1, 1}, ++ {0x3C, 0, 0, 0, 0}, ++ {0x3D, 0x88, 0x88, 1, 1}, ++ {0x3E, 0, 0, 0, 0}, ++ {0x3F, 0x44, 0x44, 0, 0}, ++ {0x40, 0x7, 0x7, 1, 1}, ++ {0x41, 0x6, 0x6, 0, 0}, ++ {0x42, 0x4, 0x4, 0, 0}, ++ {0x43, 0, 0, 0, 0}, ++ {0x44, 0x8, 0x8, 0, 0}, ++ {0x45, 0x55, 0x55, 1, 1}, ++ {0x46, 0, 0, 0, 0}, ++ {0x47, 0x11, 0x11, 0, 0}, ++ {0x48, 0, 0, 0, 0}, ++ {0x49, 0x44, 0x44, 0, 0}, ++ {0x4A, 0x7, 0x7, 0, 0}, ++ {0x4B, 0x6, 0x6, 0, 0}, ++ {0x4C, 0x4, 0x4, 0, 0}, ++ {0x4D, 0, 0, 0, 0}, ++ {0x4E, 0, 0, 0, 0}, ++ {0x4F, 0x26, 0x26, 1, 1}, ++ {0x50, 0x26, 0x26, 1, 1}, ++ {0x51, 0xf, 0xf, 1, 1}, ++ {0x52, 0xf, 0xf, 1, 1}, ++ {0x53, 0x44, 0x44, 0, 0}, ++ {0x54, 0, 0, 0, 0}, ++ {0x55, 0, 0, 0, 0}, ++ {0x56, 0x8, 0x8, 0, 0}, ++ {0x57, 0x8, 0x8, 0, 0}, ++ {0x58, 0x7, 0x7, 0, 0}, ++ {0x59, 0x22, 0x22, 0, 0}, ++ {0x5A, 0x22, 0x22, 0, 0}, ++ {0x5B, 0x2, 0x2, 0, 0}, ++ {0x5C, 0x4, 0x4, 1, 1}, ++ {0x5D, 0x7, 0x7, 0, 0}, ++ {0x5E, 0x55, 0x55, 0, 0}, ++ {0x5F, 0x23, 0x23, 0, 0}, ++ {0x60, 0x41, 0x41, 0, 0}, ++ {0x61, 0x1, 0x1, 0, 0}, ++ {0x62, 0xa, 0xa, 0, 0}, ++ {0x63, 0, 0, 0, 0}, ++ {0x64, 0, 0, 0, 0}, ++ {0x65, 0, 0, 0, 0}, ++ {0x66, 0, 0, 0, 0}, ++ {0x67, 0, 0, 0, 0}, ++ {0x68, 0, 0, 0, 0}, ++ {0x69, 0, 0, 0, 0}, ++ {0x6A, 0, 0, 0, 0}, ++ {0x6B, 0xc, 0xc, 0, 0}, ++ {0x6C, 0, 0, 0, 0}, ++ {0x6D, 0, 0, 0, 0}, ++ {0x6E, 0, 0, 0, 0}, ++ {0x6F, 0, 0, 0, 0}, ++ {0x70, 0, 0, 0, 0}, ++ {0x71, 0, 0, 0, 0}, ++ {0x72, 0x22, 0x22, 0, 0}, ++ {0x73, 0x22, 0x22, 0, 0}, ++ {0x74, 0, 0, 1, 1}, ++ {0x75, 0xa, 0xa, 0, 0}, ++ {0x76, 0x1, 0x1, 0, 0}, ++ {0x77, 0x22, 0x22, 0, 0}, ++ {0x78, 0x30, 0x30, 0, 0}, ++ {0x79, 0, 0, 0, 0}, ++ {0x7A, 0, 0, 0, 0}, ++ {0x7B, 0, 0, 0, 0}, ++ {0x7C, 0, 0, 0, 0}, ++ {0x7D, 0x5, 0x5, 1, 1}, ++ {0x7E, 0, 0, 0, 0}, ++ {0x7F, 0, 0, 0, 0}, ++ {0x80, 0, 0, 0, 0}, ++ {0x81, 0, 0, 0, 0}, ++ {0x82, 0, 0, 0, 0}, ++ {0x83, 0, 0, 0, 0}, ++ {0x84, 0, 0, 0, 0}, ++ {0x85, 0, 0, 0, 0}, ++ {0x86, 0, 0, 0, 0}, ++ {0x87, 0, 0, 0, 0}, ++ {0x88, 0, 0, 0, 0}, ++ {0x89, 0, 0, 0, 0}, ++ {0x8A, 0, 0, 0, 0}, ++ {0x8B, 0, 0, 0, 0}, ++ {0x8C, 0, 0, 0, 0}, ++ {0x8D, 0, 0, 0, 0}, ++ {0x8E, 0, 0, 0, 0}, ++ {0x8F, 0, 0, 0, 0}, ++ {0x90, 0, 0, 0, 0}, ++ {0x91, 0, 0, 0, 0}, ++ {0x92, 0, 0, 0, 0}, ++ {0x93, 0, 0, 0, 0}, ++ {0x94, 0, 0, 0, 0}, ++ {0xFFFF, 0, 0, 0, 0}, ++}; ++ ++static struct radio_20xx_regs regs_2057_rev4[] = { ++ {0x00, 0x84, 0}, ++ {0x01, 0, 0}, ++ {0x02, 0x60, 0}, ++ {0x03, 0x1f, 0}, ++ {0x04, 0x4, 0}, ++ {0x05, 0x2, 0}, ++ {0x06, 0x1, 0}, ++ {0x07, 0x1, 0}, ++ {0x08, 0x1, 0}, ++ {0x09, 0x69, 0}, ++ {0x0A, 0x66, 0}, ++ {0x0B, 0x6, 0}, ++ {0x0C, 0x18, 0}, ++ {0x0D, 0x3, 0}, ++ {0x0E, 0x20, 1}, ++ {0x0F, 0x20, 0}, ++ {0x10, 0, 0}, ++ {0x11, 0x7c, 0}, ++ {0x12, 0x42, 0}, ++ {0x13, 0xbd, 0}, ++ {0x14, 0x7, 0}, ++ {0x15, 0xf7, 0}, ++ {0x16, 0x8, 0}, ++ {0x17, 0x17, 0}, ++ {0x18, 0x7, 0}, ++ {0x19, 0, 0}, ++ {0x1A, 0x2, 0}, ++ {0x1B, 0x13, 0}, ++ {0x1C, 0x3e, 0}, ++ {0x1D, 0x3e, 0}, ++ {0x1E, 0x96, 0}, ++ {0x1F, 0x4, 0}, ++ {0x20, 0, 0}, ++ {0x21, 0, 0}, ++ {0x22, 0x17, 0}, ++ {0x23, 0x4, 0}, ++ {0x24, 0x1, 0}, ++ {0x25, 0x6, 0}, ++ {0x26, 0x4, 0}, ++ {0x27, 0xd, 0}, ++ {0x28, 0xd, 0}, ++ {0x29, 0x30, 0}, ++ {0x2A, 0x32, 0}, ++ {0x2B, 0x8, 0}, ++ {0x2C, 0x1c, 0}, ++ {0x2D, 0x2, 0}, ++ {0x2E, 0x4, 0}, ++ {0x2F, 0x7f, 0}, ++ {0x30, 0x27, 0}, ++ {0x31, 0, 1}, ++ {0x32, 0, 1}, ++ {0x33, 0, 1}, ++ {0x34, 0, 0}, ++ {0x35, 0x26, 1}, ++ {0x36, 0x18, 0}, ++ {0x37, 0x7, 0}, ++ {0x38, 0x66, 0}, ++ {0x39, 0x66, 0}, ++ {0x3A, 0x66, 0}, ++ {0x3B, 0x66, 0}, ++ {0x3C, 0xff, 1}, ++ {0x3D, 0xff, 1}, ++ {0x3E, 0xff, 1}, ++ {0x3F, 0xff, 1}, ++ {0x40, 0x16, 0}, ++ {0x41, 0x7, 0}, ++ {0x42, 0x19, 0}, ++ {0x43, 0x7, 0}, ++ {0x44, 0x6, 0}, ++ {0x45, 0x3, 0}, ++ {0x46, 0x1, 0}, ++ {0x47, 0x7, 0}, ++ {0x48, 0x33, 0}, ++ {0x49, 0x5, 0}, ++ {0x4A, 0x77, 0}, ++ {0x4B, 0x66, 0}, ++ {0x4C, 0x66, 0}, ++ {0x4D, 0, 0}, ++ {0x4E, 0x4, 0}, ++ {0x4F, 0xc, 0}, ++ {0x50, 0, 0}, ++ {0x51, 0x75, 0}, ++ {0x56, 0x7, 0}, ++ {0x57, 0, 0}, ++ {0x58, 0, 0}, ++ {0x59, 0xa8, 0}, ++ {0x5A, 0, 0}, ++ {0x5B, 0x1f, 0}, ++ {0x5C, 0x30, 0}, ++ {0x5D, 0x1, 0}, ++ {0x5E, 0x30, 0}, ++ {0x5F, 0x70, 0}, ++ {0x60, 0, 0}, ++ {0x61, 0, 0}, ++ {0x62, 0x33, 1}, ++ {0x63, 0x19, 0}, ++ {0x64, 0x62, 0}, ++ {0x65, 0, 0}, ++ {0x66, 0x11, 0}, ++ {0x69, 0, 0}, ++ {0x6A, 0x7e, 0}, ++ {0x6B, 0x3f, 0}, ++ {0x6C, 0x7f, 0}, ++ {0x6D, 0x78, 0}, ++ {0x6E, 0xc8, 0}, ++ {0x6F, 0x88, 0}, ++ {0x70, 0x8, 0}, ++ {0x71, 0xf, 0}, ++ {0x72, 0xbc, 0}, ++ {0x73, 0x8, 0}, ++ {0x74, 0x60, 0}, ++ {0x75, 0x1e, 0}, ++ {0x76, 0x70, 0}, ++ {0x77, 0, 0}, ++ {0x78, 0, 0}, ++ {0x79, 0, 0}, ++ {0x7A, 0x33, 0}, ++ {0x7B, 0x1e, 0}, ++ {0x7C, 0x62, 0}, ++ {0x7D, 0x11, 0}, ++ {0x80, 0x3c, 0}, ++ {0x81, 0x9c, 0}, ++ {0x82, 0xa, 0}, ++ {0x83, 0x9d, 0}, ++ {0x84, 0xa, 0}, ++ {0x85, 0, 0}, ++ {0x86, 0x40, 0}, ++ {0x87, 0x40, 0}, ++ {0x88, 0x88, 0}, ++ {0x89, 0x10, 0}, ++ {0x8A, 0xf0, 1}, ++ {0x8B, 0x10, 1}, ++ {0x8C, 0xf0, 1}, ++ {0x8D, 0, 0}, ++ {0x8E, 0, 0}, ++ {0x8F, 0x10, 0}, ++ {0x90, 0x55, 0}, ++ {0x91, 0x3f, 1}, ++ {0x92, 0x36, 1}, ++ {0x93, 0, 0}, ++ {0x94, 0, 0}, ++ {0x95, 0, 0}, ++ {0x96, 0x87, 0}, ++ {0x97, 0x11, 0}, ++ {0x98, 0, 0}, ++ {0x99, 0x33, 0}, ++ {0x9A, 0x88, 0}, ++ {0x9B, 0, 0}, ++ {0x9C, 0x87, 0}, ++ {0x9D, 0x11, 0}, ++ {0x9E, 0, 0}, ++ {0x9F, 0x33, 0}, ++ {0xA0, 0x88, 0}, ++ {0xA1, 0xe1, 0}, ++ {0xA2, 0x3f, 0}, ++ {0xA3, 0x44, 0}, ++ {0xA4, 0x8c, 1}, ++ {0xA5, 0x6d, 0}, ++ {0xA6, 0x22, 0}, ++ {0xA7, 0xbe, 0}, ++ {0xA8, 0x55, 1}, ++ {0xA9, 0xc, 0}, ++ {0xAA, 0xc, 0}, ++ {0xAB, 0xaa, 0}, ++ {0xAC, 0x2, 0}, ++ {0xAD, 0, 0}, ++ {0xAE, 0x10, 0}, ++ {0xAF, 0x1, 1}, ++ {0xB0, 0, 0}, ++ {0xB1, 0, 0}, ++ {0xB2, 0x80, 0}, ++ {0xB3, 0x60, 0}, ++ {0xB4, 0x44, 0}, ++ {0xB5, 0x55, 0}, ++ {0xB6, 0x1, 0}, ++ {0xB7, 0x55, 0}, ++ {0xB8, 0x1, 0}, ++ {0xB9, 0x5, 0}, ++ {0xBA, 0x55, 0}, ++ {0xBB, 0x55, 0}, ++ {0xC1, 0, 0}, ++ {0xC2, 0, 0}, ++ {0xC3, 0, 0}, ++ {0xC4, 0, 0}, ++ {0xC5, 0, 0}, ++ {0xC6, 0, 0}, ++ {0xC7, 0, 0}, ++ {0xC8, 0, 0}, ++ {0xC9, 0, 0}, ++ {0xCA, 0, 0}, ++ {0xCB, 0, 0}, ++ {0xCC, 0, 0}, ++ {0xCD, 0, 0}, ++ {0xCE, 0x5e, 0}, ++ {0xCF, 0xc, 0}, ++ {0xD0, 0xc, 0}, ++ {0xD1, 0xc, 0}, ++ {0xD2, 0, 0}, ++ {0xD3, 0x2b, 0}, ++ {0xD4, 0xc, 0}, ++ {0xD5, 0, 0}, ++ {0xD6, 0x75, 0}, ++ {0xDB, 0x7, 0}, ++ {0xDC, 0, 0}, ++ {0xDD, 0, 0}, ++ {0xDE, 0xa8, 0}, ++ {0xDF, 0, 0}, ++ {0xE0, 0x1f, 0}, ++ {0xE1, 0x30, 0}, ++ {0xE2, 0x1, 0}, ++ {0xE3, 0x30, 0}, ++ {0xE4, 0x70, 0}, ++ {0xE5, 0, 0}, ++ {0xE6, 0, 0}, ++ {0xE7, 0x33, 0}, ++ {0xE8, 0x19, 0}, ++ {0xE9, 0x62, 0}, ++ {0xEA, 0, 0}, ++ {0xEB, 0x11, 0}, ++ {0xEE, 0, 0}, ++ {0xEF, 0x7e, 0}, ++ {0xF0, 0x3f, 0}, ++ {0xF1, 0x7f, 0}, ++ {0xF2, 0x78, 0}, ++ {0xF3, 0xc8, 0}, ++ {0xF4, 0x88, 0}, ++ {0xF5, 0x8, 0}, ++ {0xF6, 0xf, 0}, ++ {0xF7, 0xbc, 0}, ++ {0xF8, 0x8, 0}, ++ {0xF9, 0x60, 0}, ++ {0xFA, 0x1e, 0}, ++ {0xFB, 0x70, 0}, ++ {0xFC, 0, 0}, ++ {0xFD, 0, 0}, ++ {0xFE, 0, 0}, ++ {0xFF, 0x33, 0}, ++ {0x100, 0x1e, 0}, ++ {0x101, 0x62, 0}, ++ {0x102, 0x11, 0}, ++ {0x105, 0x3c, 0}, ++ {0x106, 0x9c, 0}, ++ {0x107, 0xa, 0}, ++ {0x108, 0x9d, 0}, ++ {0x109, 0xa, 0}, ++ {0x10A, 0, 0}, ++ {0x10B, 0x40, 0}, ++ {0x10C, 0x40, 0}, ++ {0x10D, 0x88, 0}, ++ {0x10E, 0x10, 0}, ++ {0x10F, 0xf0, 1}, ++ {0x110, 0x10, 1}, ++ {0x111, 0xf0, 1}, ++ {0x112, 0, 0}, ++ {0x113, 0, 0}, ++ {0x114, 0x10, 0}, ++ {0x115, 0x55, 0}, ++ {0x116, 0x3f, 1}, ++ {0x117, 0x36, 1}, ++ {0x118, 0, 0}, ++ {0x119, 0, 0}, ++ {0x11A, 0, 0}, ++ {0x11B, 0x87, 0}, ++ {0x11C, 0x11, 0}, ++ {0x11D, 0, 0}, ++ {0x11E, 0x33, 0}, ++ {0x11F, 0x88, 0}, ++ {0x120, 0, 0}, ++ {0x121, 0x87, 0}, ++ {0x122, 0x11, 0}, ++ {0x123, 0, 0}, ++ {0x124, 0x33, 0}, ++ {0x125, 0x88, 0}, ++ {0x126, 0xe1, 0}, ++ {0x127, 0x3f, 0}, ++ {0x128, 0x44, 0}, ++ {0x129, 0x8c, 1}, ++ {0x12A, 0x6d, 0}, ++ {0x12B, 0x22, 0}, ++ {0x12C, 0xbe, 0}, ++ {0x12D, 0x55, 1}, ++ {0x12E, 0xc, 0}, ++ {0x12F, 0xc, 0}, ++ {0x130, 0xaa, 0}, ++ {0x131, 0x2, 0}, ++ {0x132, 0, 0}, ++ {0x133, 0x10, 0}, ++ {0x134, 0x1, 1}, ++ {0x135, 0, 0}, ++ {0x136, 0, 0}, ++ {0x137, 0x80, 0}, ++ {0x138, 0x60, 0}, ++ {0x139, 0x44, 0}, ++ {0x13A, 0x55, 0}, ++ {0x13B, 0x1, 0}, ++ {0x13C, 0x55, 0}, ++ {0x13D, 0x1, 0}, ++ {0x13E, 0x5, 0}, ++ {0x13F, 0x55, 0}, ++ {0x140, 0x55, 0}, ++ {0x146, 0, 0}, ++ {0x147, 0, 0}, ++ {0x148, 0, 0}, ++ {0x149, 0, 0}, ++ {0x14A, 0, 0}, ++ {0x14B, 0, 0}, ++ {0x14C, 0, 0}, ++ {0x14D, 0, 0}, ++ {0x14E, 0, 0}, ++ {0x14F, 0, 0}, ++ {0x150, 0, 0}, ++ {0x151, 0, 0}, ++ {0x152, 0, 0}, ++ {0x153, 0, 0}, ++ {0x154, 0xc, 0}, ++ {0x155, 0xc, 0}, ++ {0x156, 0xc, 0}, ++ {0x157, 0, 0}, ++ {0x158, 0x2b, 0}, ++ {0x159, 0x84, 0}, ++ {0x15A, 0x15, 0}, ++ {0x15B, 0xf, 0}, ++ {0x15C, 0, 0}, ++ {0x15D, 0, 0}, ++ {0x15E, 0, 1}, ++ {0x15F, 0, 1}, ++ {0x160, 0, 1}, ++ {0x161, 0, 1}, ++ {0x162, 0, 1}, ++ {0x163, 0, 1}, ++ {0x164, 0, 0}, ++ {0x165, 0, 0}, ++ {0x166, 0, 0}, ++ {0x167, 0, 0}, ++ {0x168, 0, 0}, ++ {0x169, 0x2, 1}, ++ {0x16A, 0, 1}, ++ {0x16B, 0, 1}, ++ {0x16C, 0, 1}, ++ {0x16D, 0, 0}, ++ {0x170, 0, 0}, ++ {0x171, 0x77, 0}, ++ {0x172, 0x77, 0}, ++ {0x173, 0x77, 0}, ++ {0x174, 0x77, 0}, ++ {0x175, 0, 0}, ++ {0x176, 0x3, 0}, ++ {0x177, 0x37, 0}, ++ {0x178, 0x3, 0}, ++ {0x179, 0, 0}, ++ {0x17A, 0x21, 0}, ++ {0x17B, 0x21, 0}, ++ {0x17C, 0, 0}, ++ {0x17D, 0xaa, 0}, ++ {0x17E, 0, 0}, ++ {0x17F, 0xaa, 0}, ++ {0x180, 0, 0}, ++ {0x190, 0, 0}, ++ {0x191, 0x77, 0}, ++ {0x192, 0x77, 0}, ++ {0x193, 0x77, 0}, ++ {0x194, 0x77, 0}, ++ {0x195, 0, 0}, ++ {0x196, 0x3, 0}, ++ {0x197, 0x37, 0}, ++ {0x198, 0x3, 0}, ++ {0x199, 0, 0}, ++ {0x19A, 0x21, 0}, ++ {0x19B, 0x21, 0}, ++ {0x19C, 0, 0}, ++ {0x19D, 0xaa, 0}, ++ {0x19E, 0, 0}, ++ {0x19F, 0xaa, 0}, ++ {0x1A0, 0, 0}, ++ {0x1A1, 0x2, 0}, ++ {0x1A2, 0xf, 0}, ++ {0x1A3, 0xf, 0}, ++ {0x1A4, 0, 1}, ++ {0x1A5, 0, 1}, ++ {0x1A6, 0, 1}, ++ {0x1A7, 0x2, 0}, ++ {0x1A8, 0xf, 0}, ++ {0x1A9, 0xf, 0}, ++ {0x1AA, 0, 1}, ++ {0x1AB, 0, 1}, ++ {0x1AC, 0, 1}, ++ {0xFFFF, 0, 0}, ++}; ++ ++static struct radio_20xx_regs regs_2057_rev5[] = { ++ {0x00, 0, 1}, ++ {0x01, 0x57, 1}, ++ {0x02, 0x20, 1}, ++ {0x03, 0x1f, 0}, ++ {0x04, 0x4, 0}, ++ {0x05, 0x2, 0}, ++ {0x06, 0x1, 0}, ++ {0x07, 0x1, 0}, ++ {0x08, 0x1, 0}, ++ {0x09, 0x69, 0}, ++ {0x0A, 0x66, 0}, ++ {0x0B, 0x6, 0}, ++ {0x0C, 0x18, 0}, ++ {0x0D, 0x3, 0}, ++ {0x0E, 0x20, 0}, ++ {0x0F, 0x20, 0}, ++ {0x10, 0, 0}, ++ {0x11, 0x7c, 0}, ++ {0x12, 0x42, 0}, ++ {0x13, 0xbd, 0}, ++ {0x14, 0x7, 0}, ++ {0x15, 0x87, 0}, ++ {0x16, 0x8, 0}, ++ {0x17, 0x17, 0}, ++ {0x18, 0x7, 0}, ++ {0x19, 0, 0}, ++ {0x1A, 0x2, 0}, ++ {0x1B, 0x13, 0}, ++ {0x1C, 0x3e, 0}, ++ {0x1D, 0x3e, 0}, ++ {0x1E, 0x96, 0}, ++ {0x1F, 0x4, 0}, ++ {0x20, 0, 0}, ++ {0x21, 0, 0}, ++ {0x22, 0x17, 0}, ++ {0x23, 0x6, 1}, ++ {0x24, 0x1, 0}, ++ {0x25, 0x6, 0}, ++ {0x26, 0x4, 0}, ++ {0x27, 0xd, 0}, ++ {0x28, 0xd, 0}, ++ {0x29, 0x30, 0}, ++ {0x2A, 0x32, 0}, ++ {0x2B, 0x8, 0}, ++ {0x2C, 0x1c, 0}, ++ {0x2D, 0x2, 0}, ++ {0x2E, 0x4, 0}, ++ {0x2F, 0x7f, 0}, ++ {0x30, 0x27, 0}, ++ {0x31, 0, 1}, ++ {0x32, 0, 1}, ++ {0x33, 0, 1}, ++ {0x34, 0, 0}, ++ {0x35, 0x20, 0}, ++ {0x36, 0x18, 0}, ++ {0x37, 0x7, 0}, ++ {0x38, 0x66, 0}, ++ {0x39, 0x66, 0}, ++ {0x3C, 0xff, 0}, ++ {0x3D, 0xff, 0}, ++ {0x40, 0x16, 0}, ++ {0x41, 0x7, 0}, ++ {0x45, 0x3, 0}, ++ {0x46, 0x1, 0}, ++ {0x47, 0x7, 0}, ++ {0x4B, 0x66, 0}, ++ {0x4C, 0x66, 0}, ++ {0x4D, 0, 0}, ++ {0x4E, 0x4, 0}, ++ {0x4F, 0xc, 0}, ++ {0x50, 0, 0}, ++ {0x51, 0x70, 1}, ++ {0x56, 0x7, 0}, ++ {0x57, 0, 0}, ++ {0x58, 0, 0}, ++ {0x59, 0x88, 1}, ++ {0x5A, 0, 0}, ++ {0x5B, 0x1f, 0}, ++ {0x5C, 0x20, 1}, ++ {0x5D, 0x1, 0}, ++ {0x5E, 0x30, 0}, ++ {0x5F, 0x70, 0}, ++ {0x60, 0, 0}, ++ {0x61, 0, 0}, ++ {0x62, 0x33, 1}, ++ {0x63, 0xf, 1}, ++ {0x64, 0xf, 1}, ++ {0x65, 0, 0}, ++ {0x66, 0x11, 0}, ++ {0x80, 0x3c, 0}, ++ {0x81, 0x1, 1}, ++ {0x82, 0xa, 0}, ++ {0x85, 0, 0}, ++ {0x86, 0x40, 0}, ++ {0x87, 0x40, 0}, ++ {0x88, 0x88, 0}, ++ {0x89, 0x10, 0}, ++ {0x8A, 0xf0, 0}, ++ {0x8B, 0x10, 0}, ++ {0x8C, 0xf0, 0}, ++ {0x8F, 0x10, 0}, ++ {0x90, 0x55, 0}, ++ {0x91, 0x3f, 1}, ++ {0x92, 0x36, 1}, ++ {0x93, 0, 0}, ++ {0x94, 0, 0}, ++ {0x95, 0, 0}, ++ {0x96, 0x87, 0}, ++ {0x97, 0x11, 0}, ++ {0x98, 0, 0}, ++ {0x99, 0x33, 0}, ++ {0x9A, 0x88, 0}, ++ {0xA1, 0x20, 1}, ++ {0xA2, 0x3f, 0}, ++ {0xA3, 0x44, 0}, ++ {0xA4, 0x8c, 0}, ++ {0xA5, 0x6c, 0}, ++ {0xA6, 0x22, 0}, ++ {0xA7, 0xbe, 0}, ++ {0xA8, 0x55, 0}, ++ {0xAA, 0xc, 0}, ++ {0xAB, 0xaa, 0}, ++ {0xAC, 0x2, 0}, ++ {0xAD, 0, 0}, ++ {0xAE, 0x10, 0}, ++ {0xAF, 0x1, 0}, ++ {0xB0, 0, 0}, ++ {0xB1, 0, 0}, ++ {0xB2, 0x80, 0}, ++ {0xB3, 0x60, 0}, ++ {0xB4, 0x44, 0}, ++ {0xB5, 0x55, 0}, ++ {0xB6, 0x1, 0}, ++ {0xB7, 0x55, 0}, ++ {0xB8, 0x1, 0}, ++ {0xB9, 0x5, 0}, ++ {0xBA, 0x55, 0}, ++ {0xBB, 0x55, 0}, ++ {0xC3, 0, 0}, ++ {0xC4, 0, 0}, ++ {0xC5, 0, 0}, ++ {0xC6, 0, 0}, ++ {0xC7, 0, 0}, ++ {0xC8, 0, 0}, ++ {0xC9, 0, 0}, ++ {0xCA, 0, 0}, ++ {0xCB, 0, 0}, ++ {0xCD, 0, 0}, ++ {0xCE, 0x5e, 0}, ++ {0xCF, 0xc, 0}, ++ {0xD0, 0xc, 0}, ++ {0xD1, 0xc, 0}, ++ {0xD2, 0, 0}, ++ {0xD3, 0x2b, 0}, ++ {0xD4, 0xc, 0}, ++ {0xD5, 0, 0}, ++ {0xD6, 0x70, 1}, ++ {0xDB, 0x7, 0}, ++ {0xDC, 0, 0}, ++ {0xDD, 0, 0}, ++ {0xDE, 0x88, 1}, ++ {0xDF, 0, 0}, ++ {0xE0, 0x1f, 0}, ++ {0xE1, 0x20, 1}, ++ {0xE2, 0x1, 0}, ++ {0xE3, 0x30, 0}, ++ {0xE4, 0x70, 0}, ++ {0xE5, 0, 0}, ++ {0xE6, 0, 0}, ++ {0xE7, 0x33, 0}, ++ {0xE8, 0xf, 1}, ++ {0xE9, 0xf, 1}, ++ {0xEA, 0, 0}, ++ {0xEB, 0x11, 0}, ++ {0x105, 0x3c, 0}, ++ {0x106, 0x1, 1}, ++ {0x107, 0xa, 0}, ++ {0x10A, 0, 0}, ++ {0x10B, 0x40, 0}, ++ {0x10C, 0x40, 0}, ++ {0x10D, 0x88, 0}, ++ {0x10E, 0x10, 0}, ++ {0x10F, 0xf0, 0}, ++ {0x110, 0x10, 0}, ++ {0x111, 0xf0, 0}, ++ {0x114, 0x10, 0}, ++ {0x115, 0x55, 0}, ++ {0x116, 0x3f, 1}, ++ {0x117, 0x36, 1}, ++ {0x118, 0, 0}, ++ {0x119, 0, 0}, ++ {0x11A, 0, 0}, ++ {0x11B, 0x87, 0}, ++ {0x11C, 0x11, 0}, ++ {0x11D, 0, 0}, ++ {0x11E, 0x33, 0}, ++ {0x11F, 0x88, 0}, ++ {0x126, 0x20, 1}, ++ {0x127, 0x3f, 0}, ++ {0x128, 0x44, 0}, ++ {0x129, 0x8c, 0}, ++ {0x12A, 0x6c, 0}, ++ {0x12B, 0x22, 0}, ++ {0x12C, 0xbe, 0}, ++ {0x12D, 0x55, 0}, ++ {0x12F, 0xc, 0}, ++ {0x130, 0xaa, 0}, ++ {0x131, 0x2, 0}, ++ {0x132, 0, 0}, ++ {0x133, 0x10, 0}, ++ {0x134, 0x1, 0}, ++ {0x135, 0, 0}, ++ {0x136, 0, 0}, ++ {0x137, 0x80, 0}, ++ {0x138, 0x60, 0}, ++ {0x139, 0x44, 0}, ++ {0x13A, 0x55, 0}, ++ {0x13B, 0x1, 0}, ++ {0x13C, 0x55, 0}, ++ {0x13D, 0x1, 0}, ++ {0x13E, 0x5, 0}, ++ {0x13F, 0x55, 0}, ++ {0x140, 0x55, 0}, ++ {0x148, 0, 0}, ++ {0x149, 0, 0}, ++ {0x14A, 0, 0}, ++ {0x14B, 0, 0}, ++ {0x14C, 0, 0}, ++ {0x14D, 0, 0}, ++ {0x14E, 0, 0}, ++ {0x14F, 0, 0}, ++ {0x150, 0, 0}, ++ {0x154, 0xc, 0}, ++ {0x155, 0xc, 0}, ++ {0x156, 0xc, 0}, ++ {0x157, 0, 0}, ++ {0x158, 0x2b, 0}, ++ {0x159, 0x84, 0}, ++ {0x15A, 0x15, 0}, ++ {0x15B, 0xf, 0}, ++ {0x15C, 0, 0}, ++ {0x15D, 0, 0}, ++ {0x15E, 0, 1}, ++ {0x15F, 0, 1}, ++ {0x160, 0, 1}, ++ {0x161, 0, 1}, ++ {0x162, 0, 1}, ++ {0x163, 0, 1}, ++ {0x164, 0, 0}, ++ {0x165, 0, 0}, ++ {0x166, 0, 0}, ++ {0x167, 0, 0}, ++ {0x168, 0, 0}, ++ {0x169, 0, 0}, ++ {0x16A, 0, 1}, ++ {0x16B, 0, 1}, ++ {0x16C, 0, 1}, ++ {0x16D, 0, 0}, ++ {0x170, 0, 0}, ++ {0x171, 0x77, 0}, ++ {0x172, 0x77, 0}, ++ {0x173, 0x77, 0}, ++ {0x174, 0x77, 0}, ++ {0x175, 0, 0}, ++ {0x176, 0x3, 0}, ++ {0x177, 0x37, 0}, ++ {0x178, 0x3, 0}, ++ {0x179, 0, 0}, ++ {0x17B, 0x21, 0}, ++ {0x17C, 0, 0}, ++ {0x17D, 0xaa, 0}, ++ {0x17E, 0, 0}, ++ {0x190, 0, 0}, ++ {0x191, 0x77, 0}, ++ {0x192, 0x77, 0}, ++ {0x193, 0x77, 0}, ++ {0x194, 0x77, 0}, ++ {0x195, 0, 0}, ++ {0x196, 0x3, 0}, ++ {0x197, 0x37, 0}, ++ {0x198, 0x3, 0}, ++ {0x199, 0, 0}, ++ {0x19B, 0x21, 0}, ++ {0x19C, 0, 0}, ++ {0x19D, 0xaa, 0}, ++ {0x19E, 0, 0}, ++ {0x1A1, 0x2, 0}, ++ {0x1A2, 0xf, 0}, ++ {0x1A3, 0xf, 0}, ++ {0x1A4, 0, 1}, ++ {0x1A5, 0, 1}, ++ {0x1A6, 0, 1}, ++ {0x1A7, 0x2, 0}, ++ {0x1A8, 0xf, 0}, ++ {0x1A9, 0xf, 0}, ++ {0x1AA, 0, 1}, ++ {0x1AB, 0, 1}, ++ {0x1AC, 0, 1}, ++ {0x1AD, 0x84, 0}, ++ {0x1AE, 0x60, 0}, ++ {0x1AF, 0x47, 0}, ++ {0x1B0, 0x47, 0}, ++ {0x1B1, 0, 0}, ++ {0x1B2, 0, 0}, ++ {0x1B3, 0, 0}, ++ {0x1B4, 0, 0}, ++ {0x1B5, 0, 0}, ++ {0x1B6, 0, 0}, ++ {0x1B7, 0xc, 1}, ++ {0x1B8, 0, 0}, ++ {0x1B9, 0, 0}, ++ {0x1BA, 0, 0}, ++ {0x1BB, 0, 0}, ++ {0x1BC, 0, 0}, ++ {0x1BD, 0, 0}, ++ {0x1BE, 0, 0}, ++ {0x1BF, 0, 0}, ++ {0x1C0, 0, 0}, ++ {0x1C1, 0x1, 1}, ++ {0x1C2, 0x80, 1}, ++ {0x1C3, 0, 0}, ++ {0x1C4, 0, 0}, ++ {0x1C5, 0, 0}, ++ {0x1C6, 0, 0}, ++ {0x1C7, 0, 0}, ++ {0x1C8, 0, 0}, ++ {0x1C9, 0, 0}, ++ {0x1CA, 0, 0}, ++ {0xFFFF, 0, 0} ++}; ++ ++static struct radio_20xx_regs regs_2057_rev5v1[] = { ++ {0x00, 0x15, 1}, ++ {0x01, 0x57, 1}, ++ {0x02, 0x20, 1}, ++ {0x03, 0x1f, 0}, ++ {0x04, 0x4, 0}, ++ {0x05, 0x2, 0}, ++ {0x06, 0x1, 0}, ++ {0x07, 0x1, 0}, ++ {0x08, 0x1, 0}, ++ {0x09, 0x69, 0}, ++ {0x0A, 0x66, 0}, ++ {0x0B, 0x6, 0}, ++ {0x0C, 0x18, 0}, ++ {0x0D, 0x3, 0}, ++ {0x0E, 0x20, 0}, ++ {0x0F, 0x20, 0}, ++ {0x10, 0, 0}, ++ {0x11, 0x7c, 0}, ++ {0x12, 0x42, 0}, ++ {0x13, 0xbd, 0}, ++ {0x14, 0x7, 0}, ++ {0x15, 0x87, 0}, ++ {0x16, 0x8, 0}, ++ {0x17, 0x17, 0}, ++ {0x18, 0x7, 0}, ++ {0x19, 0, 0}, ++ {0x1A, 0x2, 0}, ++ {0x1B, 0x13, 0}, ++ {0x1C, 0x3e, 0}, ++ {0x1D, 0x3e, 0}, ++ {0x1E, 0x96, 0}, ++ {0x1F, 0x4, 0}, ++ {0x20, 0, 0}, ++ {0x21, 0, 0}, ++ {0x22, 0x17, 0}, ++ {0x23, 0x6, 1}, ++ {0x24, 0x1, 0}, ++ {0x25, 0x6, 0}, ++ {0x26, 0x4, 0}, ++ {0x27, 0xd, 0}, ++ {0x28, 0xd, 0}, ++ {0x29, 0x30, 0}, ++ {0x2A, 0x32, 0}, ++ {0x2B, 0x8, 0}, ++ {0x2C, 0x1c, 0}, ++ {0x2D, 0x2, 0}, ++ {0x2E, 0x4, 0}, ++ {0x2F, 0x7f, 0}, ++ {0x30, 0x27, 0}, ++ {0x31, 0, 1}, ++ {0x32, 0, 1}, ++ {0x33, 0, 1}, ++ {0x34, 0, 0}, ++ {0x35, 0x20, 0}, ++ {0x36, 0x18, 0}, ++ {0x37, 0x7, 0}, ++ {0x38, 0x66, 0}, ++ {0x39, 0x66, 0}, ++ {0x3C, 0xff, 0}, ++ {0x3D, 0xff, 0}, ++ {0x40, 0x16, 0}, ++ {0x41, 0x7, 0}, ++ {0x45, 0x3, 0}, ++ {0x46, 0x1, 0}, ++ {0x47, 0x7, 0}, ++ {0x4B, 0x66, 0}, ++ {0x4C, 0x66, 0}, ++ {0x4D, 0, 0}, ++ {0x4E, 0x4, 0}, ++ {0x4F, 0xc, 0}, ++ {0x50, 0, 0}, ++ {0x51, 0x70, 1}, ++ {0x56, 0x7, 0}, ++ {0x57, 0, 0}, ++ {0x58, 0, 0}, ++ {0x59, 0x88, 1}, ++ {0x5A, 0, 0}, ++ {0x5B, 0x1f, 0}, ++ {0x5C, 0x20, 1}, ++ {0x5D, 0x1, 0}, ++ {0x5E, 0x30, 0}, ++ {0x5F, 0x70, 0}, ++ {0x60, 0, 0}, ++ {0x61, 0, 0}, ++ {0x62, 0x33, 1}, ++ {0x63, 0xf, 1}, ++ {0x64, 0xf, 1}, ++ {0x65, 0, 0}, ++ {0x66, 0x11, 0}, ++ {0x80, 0x3c, 0}, ++ {0x81, 0x1, 1}, ++ {0x82, 0xa, 0}, ++ {0x85, 0, 0}, ++ {0x86, 0x40, 0}, ++ {0x87, 0x40, 0}, ++ {0x88, 0x88, 0}, ++ {0x89, 0x10, 0}, ++ {0x8A, 0xf0, 0}, ++ {0x8B, 0x10, 0}, ++ {0x8C, 0xf0, 0}, ++ {0x8F, 0x10, 0}, ++ {0x90, 0x55, 0}, ++ {0x91, 0x3f, 1}, ++ {0x92, 0x36, 1}, ++ {0x93, 0, 0}, ++ {0x94, 0, 0}, ++ {0x95, 0, 0}, ++ {0x96, 0x87, 0}, ++ {0x97, 0x11, 0}, ++ {0x98, 0, 0}, ++ {0x99, 0x33, 0}, ++ {0x9A, 0x88, 0}, ++ {0xA1, 0x20, 1}, ++ {0xA2, 0x3f, 0}, ++ {0xA3, 0x44, 0}, ++ {0xA4, 0x8c, 0}, ++ {0xA5, 0x6c, 0}, ++ {0xA6, 0x22, 0}, ++ {0xA7, 0xbe, 0}, ++ {0xA8, 0x55, 0}, ++ {0xAA, 0xc, 0}, ++ {0xAB, 0xaa, 0}, ++ {0xAC, 0x2, 0}, ++ {0xAD, 0, 0}, ++ {0xAE, 0x10, 0}, ++ {0xAF, 0x1, 0}, ++ {0xB0, 0, 0}, ++ {0xB1, 0, 0}, ++ {0xB2, 0x80, 0}, ++ {0xB3, 0x60, 0}, ++ {0xB4, 0x44, 0}, ++ {0xB5, 0x55, 0}, ++ {0xB6, 0x1, 0}, ++ {0xB7, 0x55, 0}, ++ {0xB8, 0x1, 0}, ++ {0xB9, 0x5, 0}, ++ {0xBA, 0x55, 0}, ++ {0xBB, 0x55, 0}, ++ {0xC3, 0, 0}, ++ {0xC4, 0, 0}, ++ {0xC5, 0, 0}, ++ {0xC6, 0, 0}, ++ {0xC7, 0, 0}, ++ {0xC8, 0, 0}, ++ {0xC9, 0x1, 1}, ++ {0xCA, 0, 0}, ++ {0xCB, 0, 0}, ++ {0xCD, 0, 0}, ++ {0xCE, 0x5e, 0}, ++ {0xCF, 0xc, 0}, ++ {0xD0, 0xc, 0}, ++ {0xD1, 0xc, 0}, ++ {0xD2, 0, 0}, ++ {0xD3, 0x2b, 0}, ++ {0xD4, 0xc, 0}, ++ {0xD5, 0, 0}, ++ {0xD6, 0x70, 1}, ++ {0xDB, 0x7, 0}, ++ {0xDC, 0, 0}, ++ {0xDD, 0, 0}, ++ {0xDE, 0x88, 1}, ++ {0xDF, 0, 0}, ++ {0xE0, 0x1f, 0}, ++ {0xE1, 0x20, 1}, ++ {0xE2, 0x1, 0}, ++ {0xE3, 0x30, 0}, ++ {0xE4, 0x70, 0}, ++ {0xE5, 0, 0}, ++ {0xE6, 0, 0}, ++ {0xE7, 0x33, 0}, ++ {0xE8, 0xf, 1}, ++ {0xE9, 0xf, 1}, ++ {0xEA, 0, 0}, ++ {0xEB, 0x11, 0}, ++ {0x105, 0x3c, 0}, ++ {0x106, 0x1, 1}, ++ {0x107, 0xa, 0}, ++ {0x10A, 0, 0}, ++ {0x10B, 0x40, 0}, ++ {0x10C, 0x40, 0}, ++ {0x10D, 0x88, 0}, ++ {0x10E, 0x10, 0}, ++ {0x10F, 0xf0, 0}, ++ {0x110, 0x10, 0}, ++ {0x111, 0xf0, 0}, ++ {0x114, 0x10, 0}, ++ {0x115, 0x55, 0}, ++ {0x116, 0x3f, 1}, ++ {0x117, 0x36, 1}, ++ {0x118, 0, 0}, ++ {0x119, 0, 0}, ++ {0x11A, 0, 0}, ++ {0x11B, 0x87, 0}, ++ {0x11C, 0x11, 0}, ++ {0x11D, 0, 0}, ++ {0x11E, 0x33, 0}, ++ {0x11F, 0x88, 0}, ++ {0x126, 0x20, 1}, ++ {0x127, 0x3f, 0}, ++ {0x128, 0x44, 0}, ++ {0x129, 0x8c, 0}, ++ {0x12A, 0x6c, 0}, ++ {0x12B, 0x22, 0}, ++ {0x12C, 0xbe, 0}, ++ {0x12D, 0x55, 0}, ++ {0x12F, 0xc, 0}, ++ {0x130, 0xaa, 0}, ++ {0x131, 0x2, 0}, ++ {0x132, 0, 0}, ++ {0x133, 0x10, 0}, ++ {0x134, 0x1, 0}, ++ {0x135, 0, 0}, ++ {0x136, 0, 0}, ++ {0x137, 0x80, 0}, ++ {0x138, 0x60, 0}, ++ {0x139, 0x44, 0}, ++ {0x13A, 0x55, 0}, ++ {0x13B, 0x1, 0}, ++ {0x13C, 0x55, 0}, ++ {0x13D, 0x1, 0}, ++ {0x13E, 0x5, 0}, ++ {0x13F, 0x55, 0}, ++ {0x140, 0x55, 0}, ++ {0x148, 0, 0}, ++ {0x149, 0, 0}, ++ {0x14A, 0, 0}, ++ {0x14B, 0, 0}, ++ {0x14C, 0, 0}, ++ {0x14D, 0, 0}, ++ {0x14E, 0x1, 1}, ++ {0x14F, 0, 0}, ++ {0x150, 0, 0}, ++ {0x154, 0xc, 0}, ++ {0x155, 0xc, 0}, ++ {0x156, 0xc, 0}, ++ {0x157, 0, 0}, ++ {0x158, 0x2b, 0}, ++ {0x159, 0x84, 0}, ++ {0x15A, 0x15, 0}, ++ {0x15B, 0xf, 0}, ++ {0x15C, 0, 0}, ++ {0x15D, 0, 0}, ++ {0x15E, 0, 1}, ++ {0x15F, 0, 1}, ++ {0x160, 0, 1}, ++ {0x161, 0, 1}, ++ {0x162, 0, 1}, ++ {0x163, 0, 1}, ++ {0x164, 0, 0}, ++ {0x165, 0, 0}, ++ {0x166, 0, 0}, ++ {0x167, 0, 0}, ++ {0x168, 0, 0}, ++ {0x169, 0, 0}, ++ {0x16A, 0, 1}, ++ {0x16B, 0, 1}, ++ {0x16C, 0, 1}, ++ {0x16D, 0, 0}, ++ {0x170, 0, 0}, ++ {0x171, 0x77, 0}, ++ {0x172, 0x77, 0}, ++ {0x173, 0x77, 0}, ++ {0x174, 0x77, 0}, ++ {0x175, 0, 0}, ++ {0x176, 0x3, 0}, ++ {0x177, 0x37, 0}, ++ {0x178, 0x3, 0}, ++ {0x179, 0, 0}, ++ {0x17B, 0x21, 0}, ++ {0x17C, 0, 0}, ++ {0x17D, 0xaa, 0}, ++ {0x17E, 0, 0}, ++ {0x190, 0, 0}, ++ {0x191, 0x77, 0}, ++ {0x192, 0x77, 0}, ++ {0x193, 0x77, 0}, ++ {0x194, 0x77, 0}, ++ {0x195, 0, 0}, ++ {0x196, 0x3, 0}, ++ {0x197, 0x37, 0}, ++ {0x198, 0x3, 0}, ++ {0x199, 0, 0}, ++ {0x19B, 0x21, 0}, ++ {0x19C, 0, 0}, ++ {0x19D, 0xaa, 0}, ++ {0x19E, 0, 0}, ++ {0x1A1, 0x2, 0}, ++ {0x1A2, 0xf, 0}, ++ {0x1A3, 0xf, 0}, ++ {0x1A4, 0, 1}, ++ {0x1A5, 0, 1}, ++ {0x1A6, 0, 1}, ++ {0x1A7, 0x2, 0}, ++ {0x1A8, 0xf, 0}, ++ {0x1A9, 0xf, 0}, ++ {0x1AA, 0, 1}, ++ {0x1AB, 0, 1}, ++ {0x1AC, 0, 1}, ++ {0x1AD, 0x84, 0}, ++ {0x1AE, 0x60, 0}, ++ {0x1AF, 0x47, 0}, ++ {0x1B0, 0x47, 0}, ++ {0x1B1, 0, 0}, ++ {0x1B2, 0, 0}, ++ {0x1B3, 0, 0}, ++ {0x1B4, 0, 0}, ++ {0x1B5, 0, 0}, ++ {0x1B6, 0, 0}, ++ {0x1B7, 0xc, 1}, ++ {0x1B8, 0, 0}, ++ {0x1B9, 0, 0}, ++ {0x1BA, 0, 0}, ++ {0x1BB, 0, 0}, ++ {0x1BC, 0, 0}, ++ {0x1BD, 0, 0}, ++ {0x1BE, 0, 0}, ++ {0x1BF, 0, 0}, ++ {0x1C0, 0, 0}, ++ {0x1C1, 0x1, 1}, ++ {0x1C2, 0x80, 1}, ++ {0x1C3, 0, 0}, ++ {0x1C4, 0, 0}, ++ {0x1C5, 0, 0}, ++ {0x1C6, 0, 0}, ++ {0x1C7, 0, 0}, ++ {0x1C8, 0, 0}, ++ {0x1C9, 0, 0}, ++ {0x1CA, 0, 0}, ++ {0xFFFF, 0, 0} ++}; ++ ++static struct radio_20xx_regs regs_2057_rev7[] = { ++ {0x00, 0, 1}, ++ {0x01, 0x57, 1}, ++ {0x02, 0x20, 1}, ++ {0x03, 0x1f, 0}, ++ {0x04, 0x4, 0}, ++ {0x05, 0x2, 0}, ++ {0x06, 0x1, 0}, ++ {0x07, 0x1, 0}, ++ {0x08, 0x1, 0}, ++ {0x09, 0x69, 0}, ++ {0x0A, 0x66, 0}, ++ {0x0B, 0x6, 0}, ++ {0x0C, 0x18, 0}, ++ {0x0D, 0x3, 0}, ++ {0x0E, 0x20, 0}, ++ {0x0F, 0x20, 0}, ++ {0x10, 0, 0}, ++ {0x11, 0x7c, 0}, ++ {0x12, 0x42, 0}, ++ {0x13, 0xbd, 0}, ++ {0x14, 0x7, 0}, ++ {0x15, 0x87, 0}, ++ {0x16, 0x8, 0}, ++ {0x17, 0x17, 0}, ++ {0x18, 0x7, 0}, ++ {0x19, 0, 0}, ++ {0x1A, 0x2, 0}, ++ {0x1B, 0x13, 0}, ++ {0x1C, 0x3e, 0}, ++ {0x1D, 0x3e, 0}, ++ {0x1E, 0x96, 0}, ++ {0x1F, 0x4, 0}, ++ {0x20, 0, 0}, ++ {0x21, 0, 0}, ++ {0x22, 0x17, 0}, ++ {0x23, 0x6, 0}, ++ {0x24, 0x1, 0}, ++ {0x25, 0x6, 0}, ++ {0x26, 0x4, 0}, ++ {0x27, 0xd, 0}, ++ {0x28, 0xd, 0}, ++ {0x29, 0x30, 0}, ++ {0x2A, 0x32, 0}, ++ {0x2B, 0x8, 0}, ++ {0x2C, 0x1c, 0}, ++ {0x2D, 0x2, 0}, ++ {0x2E, 0x4, 0}, ++ {0x2F, 0x7f, 0}, ++ {0x30, 0x27, 0}, ++ {0x31, 0, 1}, ++ {0x32, 0, 1}, ++ {0x33, 0, 1}, ++ {0x34, 0, 0}, ++ {0x35, 0x20, 0}, ++ {0x36, 0x18, 0}, ++ {0x37, 0x7, 0}, ++ {0x38, 0x66, 0}, ++ {0x39, 0x66, 0}, ++ {0x3A, 0x66, 0}, ++ {0x3B, 0x66, 0}, ++ {0x3C, 0xff, 0}, ++ {0x3D, 0xff, 0}, ++ {0x3E, 0xff, 0}, ++ {0x3F, 0xff, 0}, ++ {0x40, 0x16, 0}, ++ {0x41, 0x7, 0}, ++ {0x42, 0x19, 0}, ++ {0x43, 0x7, 0}, ++ {0x44, 0x6, 0}, ++ {0x45, 0x3, 0}, ++ {0x46, 0x1, 0}, ++ {0x47, 0x7, 0}, ++ {0x48, 0x33, 0}, ++ {0x49, 0x5, 0}, ++ {0x4A, 0x77, 0}, ++ {0x4B, 0x66, 0}, ++ {0x4C, 0x66, 0}, ++ {0x4D, 0, 0}, ++ {0x4E, 0x4, 0}, ++ {0x4F, 0xc, 0}, ++ {0x50, 0, 0}, ++ {0x51, 0x70, 1}, ++ {0x56, 0x7, 0}, ++ {0x57, 0, 0}, ++ {0x58, 0, 0}, ++ {0x59, 0x88, 1}, ++ {0x5A, 0, 0}, ++ {0x5B, 0x1f, 0}, ++ {0x5C, 0x20, 1}, ++ {0x5D, 0x1, 0}, ++ {0x5E, 0x30, 0}, ++ {0x5F, 0x70, 0}, ++ {0x60, 0, 0}, ++ {0x61, 0, 0}, ++ {0x62, 0x33, 1}, ++ {0x63, 0xf, 1}, ++ {0x64, 0x13, 1}, ++ {0x65, 0, 0}, ++ {0x66, 0xee, 1}, ++ {0x69, 0, 0}, ++ {0x6A, 0x7e, 0}, ++ {0x6B, 0x3f, 0}, ++ {0x6C, 0x7f, 0}, ++ {0x6D, 0x78, 0}, ++ {0x6E, 0x58, 1}, ++ {0x6F, 0x88, 0}, ++ {0x70, 0x8, 0}, ++ {0x71, 0xf, 0}, ++ {0x72, 0xbc, 0}, ++ {0x73, 0x8, 0}, ++ {0x74, 0x60, 0}, ++ {0x75, 0x13, 1}, ++ {0x76, 0x70, 0}, ++ {0x77, 0, 0}, ++ {0x78, 0, 0}, ++ {0x79, 0, 0}, ++ {0x7A, 0x33, 0}, ++ {0x7B, 0x13, 1}, ++ {0x7C, 0x14, 1}, ++ {0x7D, 0xee, 1}, ++ {0x80, 0x3c, 0}, ++ {0x81, 0x1, 1}, ++ {0x82, 0xa, 0}, ++ {0x83, 0x9d, 0}, ++ {0x84, 0xa, 0}, ++ {0x85, 0, 0}, ++ {0x86, 0x40, 0}, ++ {0x87, 0x40, 0}, ++ {0x88, 0x88, 0}, ++ {0x89, 0x10, 0}, ++ {0x8A, 0xf0, 0}, ++ {0x8B, 0x10, 0}, ++ {0x8C, 0xf0, 0}, ++ {0x8D, 0, 0}, ++ {0x8E, 0, 0}, ++ {0x8F, 0x10, 0}, ++ {0x90, 0x55, 0}, ++ {0x91, 0x3f, 1}, ++ {0x92, 0x36, 1}, ++ {0x93, 0, 0}, ++ {0x94, 0, 0}, ++ {0x95, 0, 0}, ++ {0x96, 0x87, 0}, ++ {0x97, 0x11, 0}, ++ {0x98, 0, 0}, ++ {0x99, 0x33, 0}, ++ {0x9A, 0x88, 0}, ++ {0x9B, 0, 0}, ++ {0x9C, 0x87, 0}, ++ {0x9D, 0x11, 0}, ++ {0x9E, 0, 0}, ++ {0x9F, 0x33, 0}, ++ {0xA0, 0x88, 0}, ++ {0xA1, 0x20, 1}, ++ {0xA2, 0x3f, 0}, ++ {0xA3, 0x44, 0}, ++ {0xA4, 0x8c, 0}, ++ {0xA5, 0x6c, 0}, ++ {0xA6, 0x22, 0}, ++ {0xA7, 0xbe, 0}, ++ {0xA8, 0x55, 0}, ++ {0xAA, 0xc, 0}, ++ {0xAB, 0xaa, 0}, ++ {0xAC, 0x2, 0}, ++ {0xAD, 0, 0}, ++ {0xAE, 0x10, 0}, ++ {0xAF, 0x1, 0}, ++ {0xB0, 0, 0}, ++ {0xB1, 0, 0}, ++ {0xB2, 0x80, 0}, ++ {0xB3, 0x60, 0}, ++ {0xB4, 0x44, 0}, ++ {0xB5, 0x55, 0}, ++ {0xB6, 0x1, 0}, ++ {0xB7, 0x55, 0}, ++ {0xB8, 0x1, 0}, ++ {0xB9, 0x5, 0}, ++ {0xBA, 0x55, 0}, ++ {0xBB, 0x55, 0}, ++ {0xC1, 0, 0}, ++ {0xC2, 0, 0}, ++ {0xC3, 0, 0}, ++ {0xC4, 0, 0}, ++ {0xC5, 0, 0}, ++ {0xC6, 0, 0}, ++ {0xC7, 0, 0}, ++ {0xC8, 0, 0}, ++ {0xC9, 0, 0}, ++ {0xCA, 0, 0}, ++ {0xCB, 0, 0}, ++ {0xCC, 0, 0}, ++ {0xCD, 0, 0}, ++ {0xCE, 0x5e, 0}, ++ {0xCF, 0xc, 0}, ++ {0xD0, 0xc, 0}, ++ {0xD1, 0xc, 0}, ++ {0xD2, 0, 0}, ++ {0xD3, 0x2b, 0}, ++ {0xD4, 0xc, 0}, ++ {0xD5, 0, 0}, ++ {0xD6, 0x70, 1}, ++ {0xDB, 0x7, 0}, ++ {0xDC, 0, 0}, ++ {0xDD, 0, 0}, ++ {0xDE, 0x88, 1}, ++ {0xDF, 0, 0}, ++ {0xE0, 0x1f, 0}, ++ {0xE1, 0x20, 1}, ++ {0xE2, 0x1, 0}, ++ {0xE3, 0x30, 0}, ++ {0xE4, 0x70, 0}, ++ {0xE5, 0, 0}, ++ {0xE6, 0, 0}, ++ {0xE7, 0x33, 0}, ++ {0xE8, 0xf, 1}, ++ {0xE9, 0x13, 1}, ++ {0xEA, 0, 0}, ++ {0xEB, 0xee, 1}, ++ {0xEE, 0, 0}, ++ {0xEF, 0x7e, 0}, ++ {0xF0, 0x3f, 0}, ++ {0xF1, 0x7f, 0}, ++ {0xF2, 0x78, 0}, ++ {0xF3, 0x58, 1}, ++ {0xF4, 0x88, 0}, ++ {0xF5, 0x8, 0}, ++ {0xF6, 0xf, 0}, ++ {0xF7, 0xbc, 0}, ++ {0xF8, 0x8, 0}, ++ {0xF9, 0x60, 0}, ++ {0xFA, 0x13, 1}, ++ {0xFB, 0x70, 0}, ++ {0xFC, 0, 0}, ++ {0xFD, 0, 0}, ++ {0xFE, 0, 0}, ++ {0xFF, 0x33, 0}, ++ {0x100, 0x13, 1}, ++ {0x101, 0x14, 1}, ++ {0x102, 0xee, 1}, ++ {0x105, 0x3c, 0}, ++ {0x106, 0x1, 1}, ++ {0x107, 0xa, 0}, ++ {0x108, 0x9d, 0}, ++ {0x109, 0xa, 0}, ++ {0x10A, 0, 0}, ++ {0x10B, 0x40, 0}, ++ {0x10C, 0x40, 0}, ++ {0x10D, 0x88, 0}, ++ {0x10E, 0x10, 0}, ++ {0x10F, 0xf0, 0}, ++ {0x110, 0x10, 0}, ++ {0x111, 0xf0, 0}, ++ {0x112, 0, 0}, ++ {0x113, 0, 0}, ++ {0x114, 0x10, 0}, ++ {0x115, 0x55, 0}, ++ {0x116, 0x3f, 1}, ++ {0x117, 0x36, 1}, ++ {0x118, 0, 0}, ++ {0x119, 0, 0}, ++ {0x11A, 0, 0}, ++ {0x11B, 0x87, 0}, ++ {0x11C, 0x11, 0}, ++ {0x11D, 0, 0}, ++ {0x11E, 0x33, 0}, ++ {0x11F, 0x88, 0}, ++ {0x120, 0, 0}, ++ {0x121, 0x87, 0}, ++ {0x122, 0x11, 0}, ++ {0x123, 0, 0}, ++ {0x124, 0x33, 0}, ++ {0x125, 0x88, 0}, ++ {0x126, 0x20, 1}, ++ {0x127, 0x3f, 0}, ++ {0x128, 0x44, 0}, ++ {0x129, 0x8c, 0}, ++ {0x12A, 0x6c, 0}, ++ {0x12B, 0x22, 0}, ++ {0x12C, 0xbe, 0}, ++ {0x12D, 0x55, 0}, ++ {0x12F, 0xc, 0}, ++ {0x130, 0xaa, 0}, ++ {0x131, 0x2, 0}, ++ {0x132, 0, 0}, ++ {0x133, 0x10, 0}, ++ {0x134, 0x1, 0}, ++ {0x135, 0, 0}, ++ {0x136, 0, 0}, ++ {0x137, 0x80, 0}, ++ {0x138, 0x60, 0}, ++ {0x139, 0x44, 0}, ++ {0x13A, 0x55, 0}, ++ {0x13B, 0x1, 0}, ++ {0x13C, 0x55, 0}, ++ {0x13D, 0x1, 0}, ++ {0x13E, 0x5, 0}, ++ {0x13F, 0x55, 0}, ++ {0x140, 0x55, 0}, ++ {0x146, 0, 0}, ++ {0x147, 0, 0}, ++ {0x148, 0, 0}, ++ {0x149, 0, 0}, ++ {0x14A, 0, 0}, ++ {0x14B, 0, 0}, ++ {0x14C, 0, 0}, ++ {0x14D, 0, 0}, ++ {0x14E, 0, 0}, ++ {0x14F, 0, 0}, ++ {0x150, 0, 0}, ++ {0x151, 0, 0}, ++ {0x154, 0xc, 0}, ++ {0x155, 0xc, 0}, ++ {0x156, 0xc, 0}, ++ {0x157, 0, 0}, ++ {0x158, 0x2b, 0}, ++ {0x159, 0x84, 0}, ++ {0x15A, 0x15, 0}, ++ {0x15B, 0xf, 0}, ++ {0x15C, 0, 0}, ++ {0x15D, 0, 0}, ++ {0x15E, 0, 1}, ++ {0x15F, 0, 1}, ++ {0x160, 0, 1}, ++ {0x161, 0, 1}, ++ {0x162, 0, 1}, ++ {0x163, 0, 1}, ++ {0x164, 0, 0}, ++ {0x165, 0, 0}, ++ {0x166, 0, 0}, ++ {0x167, 0, 0}, ++ {0x168, 0, 0}, ++ {0x169, 0, 0}, ++ {0x16A, 0, 1}, ++ {0x16B, 0, 1}, ++ {0x16C, 0, 1}, ++ {0x16D, 0, 0}, ++ {0x170, 0, 0}, ++ {0x171, 0x77, 0}, ++ {0x172, 0x77, 0}, ++ {0x173, 0x77, 0}, ++ {0x174, 0x77, 0}, ++ {0x175, 0, 0}, ++ {0x176, 0x3, 0}, ++ {0x177, 0x37, 0}, ++ {0x178, 0x3, 0}, ++ {0x179, 0, 0}, ++ {0x17A, 0x21, 0}, ++ {0x17B, 0x21, 0}, ++ {0x17C, 0, 0}, ++ {0x17D, 0xaa, 0}, ++ {0x17E, 0, 0}, ++ {0x17F, 0xaa, 0}, ++ {0x180, 0, 0}, ++ {0x190, 0, 0}, ++ {0x191, 0x77, 0}, ++ {0x192, 0x77, 0}, ++ {0x193, 0x77, 0}, ++ {0x194, 0x77, 0}, ++ {0x195, 0, 0}, ++ {0x196, 0x3, 0}, ++ {0x197, 0x37, 0}, ++ {0x198, 0x3, 0}, ++ {0x199, 0, 0}, ++ {0x19A, 0x21, 0}, ++ {0x19B, 0x21, 0}, ++ {0x19C, 0, 0}, ++ {0x19D, 0xaa, 0}, ++ {0x19E, 0, 0}, ++ {0x19F, 0xaa, 0}, ++ {0x1A0, 0, 0}, ++ {0x1A1, 0x2, 0}, ++ {0x1A2, 0xf, 0}, ++ {0x1A3, 0xf, 0}, ++ {0x1A4, 0, 1}, ++ {0x1A5, 0, 1}, ++ {0x1A6, 0, 1}, ++ {0x1A7, 0x2, 0}, ++ {0x1A8, 0xf, 0}, ++ {0x1A9, 0xf, 0}, ++ {0x1AA, 0, 1}, ++ {0x1AB, 0, 1}, ++ {0x1AC, 0, 1}, ++ {0x1AD, 0x84, 0}, ++ {0x1AE, 0x60, 0}, ++ {0x1AF, 0x47, 0}, ++ {0x1B0, 0x47, 0}, ++ {0x1B1, 0, 0}, ++ {0x1B2, 0, 0}, ++ {0x1B3, 0, 0}, ++ {0x1B4, 0, 0}, ++ {0x1B5, 0, 0}, ++ {0x1B6, 0, 0}, ++ {0x1B7, 0x5, 1}, ++ {0x1B8, 0, 0}, ++ {0x1B9, 0, 0}, ++ {0x1BA, 0, 0}, ++ {0x1BB, 0, 0}, ++ {0x1BC, 0, 0}, ++ {0x1BD, 0, 0}, ++ {0x1BE, 0, 0}, ++ {0x1BF, 0, 0}, ++ {0x1C0, 0, 0}, ++ {0x1C1, 0, 0}, ++ {0x1C2, 0xa0, 1}, ++ {0x1C3, 0, 0}, ++ {0x1C4, 0, 0}, ++ {0x1C5, 0, 0}, ++ {0x1C6, 0, 0}, ++ {0x1C7, 0, 0}, ++ {0x1C8, 0, 0}, ++ {0x1C9, 0, 0}, ++ {0x1CA, 0, 0}, ++ {0xFFFF, 0, 0} ++}; ++ ++static struct radio_20xx_regs regs_2057_rev8[] = { ++ {0x00, 0x8, 1}, ++ {0x01, 0x57, 1}, ++ {0x02, 0x20, 1}, ++ {0x03, 0x1f, 0}, ++ {0x04, 0x4, 0}, ++ {0x05, 0x2, 0}, ++ {0x06, 0x1, 0}, ++ {0x07, 0x1, 0}, ++ {0x08, 0x1, 0}, ++ {0x09, 0x69, 0}, ++ {0x0A, 0x66, 0}, ++ {0x0B, 0x6, 0}, ++ {0x0C, 0x18, 0}, ++ {0x0D, 0x3, 0}, ++ {0x0E, 0x20, 0}, ++ {0x0F, 0x20, 0}, ++ {0x10, 0, 0}, ++ {0x11, 0x7c, 0}, ++ {0x12, 0x42, 0}, ++ {0x13, 0xbd, 0}, ++ {0x14, 0x7, 0}, ++ {0x15, 0x87, 0}, ++ {0x16, 0x8, 0}, ++ {0x17, 0x17, 0}, ++ {0x18, 0x7, 0}, ++ {0x19, 0, 0}, ++ {0x1A, 0x2, 0}, ++ {0x1B, 0x13, 0}, ++ {0x1C, 0x3e, 0}, ++ {0x1D, 0x3e, 0}, ++ {0x1E, 0x96, 0}, ++ {0x1F, 0x4, 0}, ++ {0x20, 0, 0}, ++ {0x21, 0, 0}, ++ {0x22, 0x17, 0}, ++ {0x23, 0x6, 0}, ++ {0x24, 0x1, 0}, ++ {0x25, 0x6, 0}, ++ {0x26, 0x4, 0}, ++ {0x27, 0xd, 0}, ++ {0x28, 0xd, 0}, ++ {0x29, 0x30, 0}, ++ {0x2A, 0x32, 0}, ++ {0x2B, 0x8, 0}, ++ {0x2C, 0x1c, 0}, ++ {0x2D, 0x2, 0}, ++ {0x2E, 0x4, 0}, ++ {0x2F, 0x7f, 0}, ++ {0x30, 0x27, 0}, ++ {0x31, 0, 1}, ++ {0x32, 0, 1}, ++ {0x33, 0, 1}, ++ {0x34, 0, 0}, ++ {0x35, 0x20, 0}, ++ {0x36, 0x18, 0}, ++ {0x37, 0x7, 0}, ++ {0x38, 0x66, 0}, ++ {0x39, 0x66, 0}, ++ {0x3A, 0x66, 0}, ++ {0x3B, 0x66, 0}, ++ {0x3C, 0xff, 0}, ++ {0x3D, 0xff, 0}, ++ {0x3E, 0xff, 0}, ++ {0x3F, 0xff, 0}, ++ {0x40, 0x16, 0}, ++ {0x41, 0x7, 0}, ++ {0x42, 0x19, 0}, ++ {0x43, 0x7, 0}, ++ {0x44, 0x6, 0}, ++ {0x45, 0x3, 0}, ++ {0x46, 0x1, 0}, ++ {0x47, 0x7, 0}, ++ {0x48, 0x33, 0}, ++ {0x49, 0x5, 0}, ++ {0x4A, 0x77, 0}, ++ {0x4B, 0x66, 0}, ++ {0x4C, 0x66, 0}, ++ {0x4D, 0, 0}, ++ {0x4E, 0x4, 0}, ++ {0x4F, 0xc, 0}, ++ {0x50, 0, 0}, ++ {0x51, 0x70, 1}, ++ {0x56, 0x7, 0}, ++ {0x57, 0, 0}, ++ {0x58, 0, 0}, ++ {0x59, 0x88, 1}, ++ {0x5A, 0, 0}, ++ {0x5B, 0x1f, 0}, ++ {0x5C, 0x20, 1}, ++ {0x5D, 0x1, 0}, ++ {0x5E, 0x30, 0}, ++ {0x5F, 0x70, 0}, ++ {0x60, 0, 0}, ++ {0x61, 0, 0}, ++ {0x62, 0x33, 1}, ++ {0x63, 0xf, 1}, ++ {0x64, 0xf, 1}, ++ {0x65, 0, 0}, ++ {0x66, 0x11, 0}, ++ {0x69, 0, 0}, ++ {0x6A, 0x7e, 0}, ++ {0x6B, 0x3f, 0}, ++ {0x6C, 0x7f, 0}, ++ {0x6D, 0x78, 0}, ++ {0x6E, 0x58, 1}, ++ {0x6F, 0x88, 0}, ++ {0x70, 0x8, 0}, ++ {0x71, 0xf, 0}, ++ {0x72, 0xbc, 0}, ++ {0x73, 0x8, 0}, ++ {0x74, 0x60, 0}, ++ {0x75, 0x13, 1}, ++ {0x76, 0x70, 0}, ++ {0x77, 0, 0}, ++ {0x78, 0, 0}, ++ {0x79, 0, 0}, ++ {0x7A, 0x33, 0}, ++ {0x7B, 0x13, 1}, ++ {0x7C, 0xf, 1}, ++ {0x7D, 0xee, 1}, ++ {0x80, 0x3c, 0}, ++ {0x81, 0x1, 1}, ++ {0x82, 0xa, 0}, ++ {0x83, 0x9d, 0}, ++ {0x84, 0xa, 0}, ++ {0x85, 0, 0}, ++ {0x86, 0x40, 0}, ++ {0x87, 0x40, 0}, ++ {0x88, 0x88, 0}, ++ {0x89, 0x10, 0}, ++ {0x8A, 0xf0, 0}, ++ {0x8B, 0x10, 0}, ++ {0x8C, 0xf0, 0}, ++ {0x8D, 0, 0}, ++ {0x8E, 0, 0}, ++ {0x8F, 0x10, 0}, ++ {0x90, 0x55, 0}, ++ {0x91, 0x3f, 1}, ++ {0x92, 0x36, 1}, ++ {0x93, 0, 0}, ++ {0x94, 0, 0}, ++ {0x95, 0, 0}, ++ {0x96, 0x87, 0}, ++ {0x97, 0x11, 0}, ++ {0x98, 0, 0}, ++ {0x99, 0x33, 0}, ++ {0x9A, 0x88, 0}, ++ {0x9B, 0, 0}, ++ {0x9C, 0x87, 0}, ++ {0x9D, 0x11, 0}, ++ {0x9E, 0, 0}, ++ {0x9F, 0x33, 0}, ++ {0xA0, 0x88, 0}, ++ {0xA1, 0x20, 1}, ++ {0xA2, 0x3f, 0}, ++ {0xA3, 0x44, 0}, ++ {0xA4, 0x8c, 0}, ++ {0xA5, 0x6c, 0}, ++ {0xA6, 0x22, 0}, ++ {0xA7, 0xbe, 0}, ++ {0xA8, 0x55, 0}, ++ {0xAA, 0xc, 0}, ++ {0xAB, 0xaa, 0}, ++ {0xAC, 0x2, 0}, ++ {0xAD, 0, 0}, ++ {0xAE, 0x10, 0}, ++ {0xAF, 0x1, 0}, ++ {0xB0, 0, 0}, ++ {0xB1, 0, 0}, ++ {0xB2, 0x80, 0}, ++ {0xB3, 0x60, 0}, ++ {0xB4, 0x44, 0}, ++ {0xB5, 0x55, 0}, ++ {0xB6, 0x1, 0}, ++ {0xB7, 0x55, 0}, ++ {0xB8, 0x1, 0}, ++ {0xB9, 0x5, 0}, ++ {0xBA, 0x55, 0}, ++ {0xBB, 0x55, 0}, ++ {0xC1, 0, 0}, ++ {0xC2, 0, 0}, ++ {0xC3, 0, 0}, ++ {0xC4, 0, 0}, ++ {0xC5, 0, 0}, ++ {0xC6, 0, 0}, ++ {0xC7, 0, 0}, ++ {0xC8, 0, 0}, ++ {0xC9, 0x1, 1}, ++ {0xCA, 0, 0}, ++ {0xCB, 0, 0}, ++ {0xCC, 0, 0}, ++ {0xCD, 0, 0}, ++ {0xCE, 0x5e, 0}, ++ {0xCF, 0xc, 0}, ++ {0xD0, 0xc, 0}, ++ {0xD1, 0xc, 0}, ++ {0xD2, 0, 0}, ++ {0xD3, 0x2b, 0}, ++ {0xD4, 0xc, 0}, ++ {0xD5, 0, 0}, ++ {0xD6, 0x70, 1}, ++ {0xDB, 0x7, 0}, ++ {0xDC, 0, 0}, ++ {0xDD, 0, 0}, ++ {0xDE, 0x88, 1}, ++ {0xDF, 0, 0}, ++ {0xE0, 0x1f, 0}, ++ {0xE1, 0x20, 1}, ++ {0xE2, 0x1, 0}, ++ {0xE3, 0x30, 0}, ++ {0xE4, 0x70, 0}, ++ {0xE5, 0, 0}, ++ {0xE6, 0, 0}, ++ {0xE7, 0x33, 0}, ++ {0xE8, 0xf, 1}, ++ {0xE9, 0xf, 1}, ++ {0xEA, 0, 0}, ++ {0xEB, 0x11, 0}, ++ {0xEE, 0, 0}, ++ {0xEF, 0x7e, 0}, ++ {0xF0, 0x3f, 0}, ++ {0xF1, 0x7f, 0}, ++ {0xF2, 0x78, 0}, ++ {0xF3, 0x58, 1}, ++ {0xF4, 0x88, 0}, ++ {0xF5, 0x8, 0}, ++ {0xF6, 0xf, 0}, ++ {0xF7, 0xbc, 0}, ++ {0xF8, 0x8, 0}, ++ {0xF9, 0x60, 0}, ++ {0xFA, 0x13, 1}, ++ {0xFB, 0x70, 0}, ++ {0xFC, 0, 0}, ++ {0xFD, 0, 0}, ++ {0xFE, 0, 0}, ++ {0xFF, 0x33, 0}, ++ {0x100, 0x13, 1}, ++ {0x101, 0xf, 1}, ++ {0x102, 0xee, 1}, ++ {0x105, 0x3c, 0}, ++ {0x106, 0x1, 1}, ++ {0x107, 0xa, 0}, ++ {0x108, 0x9d, 0}, ++ {0x109, 0xa, 0}, ++ {0x10A, 0, 0}, ++ {0x10B, 0x40, 0}, ++ {0x10C, 0x40, 0}, ++ {0x10D, 0x88, 0}, ++ {0x10E, 0x10, 0}, ++ {0x10F, 0xf0, 0}, ++ {0x110, 0x10, 0}, ++ {0x111, 0xf0, 0}, ++ {0x112, 0, 0}, ++ {0x113, 0, 0}, ++ {0x114, 0x10, 0}, ++ {0x115, 0x55, 0}, ++ {0x116, 0x3f, 1}, ++ {0x117, 0x36, 1}, ++ {0x118, 0, 0}, ++ {0x119, 0, 0}, ++ {0x11A, 0, 0}, ++ {0x11B, 0x87, 0}, ++ {0x11C, 0x11, 0}, ++ {0x11D, 0, 0}, ++ {0x11E, 0x33, 0}, ++ {0x11F, 0x88, 0}, ++ {0x120, 0, 0}, ++ {0x121, 0x87, 0}, ++ {0x122, 0x11, 0}, ++ {0x123, 0, 0}, ++ {0x124, 0x33, 0}, ++ {0x125, 0x88, 0}, ++ {0x126, 0x20, 1}, ++ {0x127, 0x3f, 0}, ++ {0x128, 0x44, 0}, ++ {0x129, 0x8c, 0}, ++ {0x12A, 0x6c, 0}, ++ {0x12B, 0x22, 0}, ++ {0x12C, 0xbe, 0}, ++ {0x12D, 0x55, 0}, ++ {0x12F, 0xc, 0}, ++ {0x130, 0xaa, 0}, ++ {0x131, 0x2, 0}, ++ {0x132, 0, 0}, ++ {0x133, 0x10, 0}, ++ {0x134, 0x1, 0}, ++ {0x135, 0, 0}, ++ {0x136, 0, 0}, ++ {0x137, 0x80, 0}, ++ {0x138, 0x60, 0}, ++ {0x139, 0x44, 0}, ++ {0x13A, 0x55, 0}, ++ {0x13B, 0x1, 0}, ++ {0x13C, 0x55, 0}, ++ {0x13D, 0x1, 0}, ++ {0x13E, 0x5, 0}, ++ {0x13F, 0x55, 0}, ++ {0x140, 0x55, 0}, ++ {0x146, 0, 0}, ++ {0x147, 0, 0}, ++ {0x148, 0, 0}, ++ {0x149, 0, 0}, ++ {0x14A, 0, 0}, ++ {0x14B, 0, 0}, ++ {0x14C, 0, 0}, ++ {0x14D, 0, 0}, ++ {0x14E, 0x1, 1}, ++ {0x14F, 0, 0}, ++ {0x150, 0, 0}, ++ {0x151, 0, 0}, ++ {0x154, 0xc, 0}, ++ {0x155, 0xc, 0}, ++ {0x156, 0xc, 0}, ++ {0x157, 0, 0}, ++ {0x158, 0x2b, 0}, ++ {0x159, 0x84, 0}, ++ {0x15A, 0x15, 0}, ++ {0x15B, 0xf, 0}, ++ {0x15C, 0, 0}, ++ {0x15D, 0, 0}, ++ {0x15E, 0, 1}, ++ {0x15F, 0, 1}, ++ {0x160, 0, 1}, ++ {0x161, 0, 1}, ++ {0x162, 0, 1}, ++ {0x163, 0, 1}, ++ {0x164, 0, 0}, ++ {0x165, 0, 0}, ++ {0x166, 0, 0}, ++ {0x167, 0, 0}, ++ {0x168, 0, 0}, ++ {0x169, 0, 0}, ++ {0x16A, 0, 1}, ++ {0x16B, 0, 1}, ++ {0x16C, 0, 1}, ++ {0x16D, 0, 0}, ++ {0x170, 0, 0}, ++ {0x171, 0x77, 0}, ++ {0x172, 0x77, 0}, ++ {0x173, 0x77, 0}, ++ {0x174, 0x77, 0}, ++ {0x175, 0, 0}, ++ {0x176, 0x3, 0}, ++ {0x177, 0x37, 0}, ++ {0x178, 0x3, 0}, ++ {0x179, 0, 0}, ++ {0x17A, 0x21, 0}, ++ {0x17B, 0x21, 0}, ++ {0x17C, 0, 0}, ++ {0x17D, 0xaa, 0}, ++ {0x17E, 0, 0}, ++ {0x17F, 0xaa, 0}, ++ {0x180, 0, 0}, ++ {0x190, 0, 0}, ++ {0x191, 0x77, 0}, ++ {0x192, 0x77, 0}, ++ {0x193, 0x77, 0}, ++ {0x194, 0x77, 0}, ++ {0x195, 0, 0}, ++ {0x196, 0x3, 0}, ++ {0x197, 0x37, 0}, ++ {0x198, 0x3, 0}, ++ {0x199, 0, 0}, ++ {0x19A, 0x21, 0}, ++ {0x19B, 0x21, 0}, ++ {0x19C, 0, 0}, ++ {0x19D, 0xaa, 0}, ++ {0x19E, 0, 0}, ++ {0x19F, 0xaa, 0}, ++ {0x1A0, 0, 0}, ++ {0x1A1, 0x2, 0}, ++ {0x1A2, 0xf, 0}, ++ {0x1A3, 0xf, 0}, ++ {0x1A4, 0, 1}, ++ {0x1A5, 0, 1}, ++ {0x1A6, 0, 1}, ++ {0x1A7, 0x2, 0}, ++ {0x1A8, 0xf, 0}, ++ {0x1A9, 0xf, 0}, ++ {0x1AA, 0, 1}, ++ {0x1AB, 0, 1}, ++ {0x1AC, 0, 1}, ++ {0x1AD, 0x84, 0}, ++ {0x1AE, 0x60, 0}, ++ {0x1AF, 0x47, 0}, ++ {0x1B0, 0x47, 0}, ++ {0x1B1, 0, 0}, ++ {0x1B2, 0, 0}, ++ {0x1B3, 0, 0}, ++ {0x1B4, 0, 0}, ++ {0x1B5, 0, 0}, ++ {0x1B6, 0, 0}, ++ {0x1B7, 0x5, 1}, ++ {0x1B8, 0, 0}, ++ {0x1B9, 0, 0}, ++ {0x1BA, 0, 0}, ++ {0x1BB, 0, 0}, ++ {0x1BC, 0, 0}, ++ {0x1BD, 0, 0}, ++ {0x1BE, 0, 0}, ++ {0x1BF, 0, 0}, ++ {0x1C0, 0, 0}, ++ {0x1C1, 0, 0}, ++ {0x1C2, 0xa0, 1}, ++ {0x1C3, 0, 0}, ++ {0x1C4, 0, 0}, ++ {0x1C5, 0, 0}, ++ {0x1C6, 0, 0}, ++ {0x1C7, 0, 0}, ++ {0x1C8, 0, 0}, ++ {0x1C9, 0, 0}, ++ {0x1CA, 0, 0}, ++ {0xFFFF, 0, 0} ++}; ++ ++static s16 nphy_def_lnagains[] = { -2, 10, 19, 25 }; ++ ++static s32 nphy_lnagain_est0[] = { -315, 40370 }; ++static s32 nphy_lnagain_est1[] = { -224, 23242 }; ++ ++static const u16 tbl_iqcal_gainparams_nphy[2][NPHY_IQCAL_NUMGAINS][8] = { ++ { ++ {0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69}, ++ {0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69}, ++ {0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68}, ++ {0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67}, ++ {0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66}, ++ {0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65}, ++ {0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65}, ++ {0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65}, ++ {0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65} ++ }, ++ { ++ {0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79}, ++ {0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79}, ++ {0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79}, ++ {0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78}, ++ {0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78}, ++ {0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78}, ++ {0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78}, ++ {0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78}, ++ {0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78} ++ } ++}; ++ ++static const u32 nphy_tpc_txgain[] = { ++ 0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42, ++ 0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44, ++ 0x03c82a42, 0x03c82944, 0x03c82942, 0x03c82844, ++ 0x03c82842, 0x03c42b44, 0x03c42b42, 0x03c42a44, ++ 0x03c42a42, 0x03c42944, 0x03c42942, 0x03c42844, ++ 0x03c42842, 0x03c42744, 0x03c42742, 0x03c42644, ++ 0x03c42642, 0x03c42544, 0x03c42542, 0x03c42444, ++ 0x03c42442, 0x03c02b44, 0x03c02b42, 0x03c02a44, ++ 0x03c02a42, 0x03c02944, 0x03c02942, 0x03c02844, ++ 0x03c02842, 0x03c02744, 0x03c02742, 0x03b02b44, ++ 0x03b02b42, 0x03b02a44, 0x03b02a42, 0x03b02944, ++ 0x03b02942, 0x03b02844, 0x03b02842, 0x03b02744, ++ 0x03b02742, 0x03b02644, 0x03b02642, 0x03b02544, ++ 0x03b02542, 0x03a02b44, 0x03a02b42, 0x03a02a44, ++ 0x03a02a42, 0x03a02944, 0x03a02942, 0x03a02844, ++ 0x03a02842, 0x03a02744, 0x03a02742, 0x03902b44, ++ 0x03902b42, 0x03902a44, 0x03902a42, 0x03902944, ++ 0x03902942, 0x03902844, 0x03902842, 0x03902744, ++ 0x03902742, 0x03902644, 0x03902642, 0x03902544, ++ 0x03902542, 0x03802b44, 0x03802b42, 0x03802a44, ++ 0x03802a42, 0x03802944, 0x03802942, 0x03802844, ++ 0x03802842, 0x03802744, 0x03802742, 0x03802644, ++ 0x03802642, 0x03802544, 0x03802542, 0x03802444, ++ 0x03802442, 0x03802344, 0x03802342, 0x03802244, ++ 0x03802242, 0x03802144, 0x03802142, 0x03802044, ++ 0x03802042, 0x03801f44, 0x03801f42, 0x03801e44, ++ 0x03801e42, 0x03801d44, 0x03801d42, 0x03801c44, ++ 0x03801c42, 0x03801b44, 0x03801b42, 0x03801a44, ++ 0x03801a42, 0x03801944, 0x03801942, 0x03801844, ++ 0x03801842, 0x03801744, 0x03801742, 0x03801644, ++ 0x03801642, 0x03801544, 0x03801542, 0x03801444, ++ 0x03801442, 0x03801344, 0x03801342, 0x00002b00 ++}; ++ ++static const u16 nphy_tpc_loscale[] = { ++ 256, 256, 271, 271, 287, 256, 256, 271, ++ 271, 287, 287, 304, 304, 256, 256, 271, ++ 271, 287, 287, 304, 304, 322, 322, 341, ++ 341, 362, 362, 383, 383, 256, 256, 271, ++ 271, 287, 287, 304, 304, 322, 322, 256, ++ 256, 271, 271, 287, 287, 304, 304, 322, ++ 322, 341, 341, 362, 362, 256, 256, 271, ++ 271, 287, 287, 304, 304, 322, 322, 256, ++ 256, 271, 271, 287, 287, 304, 304, 322, ++ 322, 341, 341, 362, 362, 256, 256, 271, ++ 271, 287, 287, 304, 304, 322, 322, 341, ++ 341, 362, 362, 383, 383, 406, 406, 430, ++ 430, 455, 455, 482, 482, 511, 511, 541, ++ 541, 573, 573, 607, 607, 643, 643, 681, ++ 681, 722, 722, 764, 764, 810, 810, 858, ++ 858, 908, 908, 962, 962, 1019, 1019, 256 ++}; ++ ++static u32 nphy_tpc_txgain_ipa[] = { ++ 0x5ff7002d, 0x5ff7002b, 0x5ff7002a, 0x5ff70029, ++ 0x5ff70028, 0x5ff70027, 0x5ff70026, 0x5ff70025, ++ 0x5ef7002d, 0x5ef7002b, 0x5ef7002a, 0x5ef70029, ++ 0x5ef70028, 0x5ef70027, 0x5ef70026, 0x5ef70025, ++ 0x5df7002d, 0x5df7002b, 0x5df7002a, 0x5df70029, ++ 0x5df70028, 0x5df70027, 0x5df70026, 0x5df70025, ++ 0x5cf7002d, 0x5cf7002b, 0x5cf7002a, 0x5cf70029, ++ 0x5cf70028, 0x5cf70027, 0x5cf70026, 0x5cf70025, ++ 0x5bf7002d, 0x5bf7002b, 0x5bf7002a, 0x5bf70029, ++ 0x5bf70028, 0x5bf70027, 0x5bf70026, 0x5bf70025, ++ 0x5af7002d, 0x5af7002b, 0x5af7002a, 0x5af70029, ++ 0x5af70028, 0x5af70027, 0x5af70026, 0x5af70025, ++ 0x59f7002d, 0x59f7002b, 0x59f7002a, 0x59f70029, ++ 0x59f70028, 0x59f70027, 0x59f70026, 0x59f70025, ++ 0x58f7002d, 0x58f7002b, 0x58f7002a, 0x58f70029, ++ 0x58f70028, 0x58f70027, 0x58f70026, 0x58f70025, ++ 0x57f7002d, 0x57f7002b, 0x57f7002a, 0x57f70029, ++ 0x57f70028, 0x57f70027, 0x57f70026, 0x57f70025, ++ 0x56f7002d, 0x56f7002b, 0x56f7002a, 0x56f70029, ++ 0x56f70028, 0x56f70027, 0x56f70026, 0x56f70025, ++ 0x55f7002d, 0x55f7002b, 0x55f7002a, 0x55f70029, ++ 0x55f70028, 0x55f70027, 0x55f70026, 0x55f70025, ++ 0x54f7002d, 0x54f7002b, 0x54f7002a, 0x54f70029, ++ 0x54f70028, 0x54f70027, 0x54f70026, 0x54f70025, ++ 0x53f7002d, 0x53f7002b, 0x53f7002a, 0x53f70029, ++ 0x53f70028, 0x53f70027, 0x53f70026, 0x53f70025, ++ 0x52f7002d, 0x52f7002b, 0x52f7002a, 0x52f70029, ++ 0x52f70028, 0x52f70027, 0x52f70026, 0x52f70025, ++ 0x51f7002d, 0x51f7002b, 0x51f7002a, 0x51f70029, ++ 0x51f70028, 0x51f70027, 0x51f70026, 0x51f70025, ++ 0x50f7002d, 0x50f7002b, 0x50f7002a, 0x50f70029, ++ 0x50f70028, 0x50f70027, 0x50f70026, 0x50f70025 ++}; ++ ++static u32 nphy_tpc_txgain_ipa_rev5[] = { ++ 0x1ff7002d, 0x1ff7002b, 0x1ff7002a, 0x1ff70029, ++ 0x1ff70028, 0x1ff70027, 0x1ff70026, 0x1ff70025, ++ 0x1ef7002d, 0x1ef7002b, 0x1ef7002a, 0x1ef70029, ++ 0x1ef70028, 0x1ef70027, 0x1ef70026, 0x1ef70025, ++ 0x1df7002d, 0x1df7002b, 0x1df7002a, 0x1df70029, ++ 0x1df70028, 0x1df70027, 0x1df70026, 0x1df70025, ++ 0x1cf7002d, 0x1cf7002b, 0x1cf7002a, 0x1cf70029, ++ 0x1cf70028, 0x1cf70027, 0x1cf70026, 0x1cf70025, ++ 0x1bf7002d, 0x1bf7002b, 0x1bf7002a, 0x1bf70029, ++ 0x1bf70028, 0x1bf70027, 0x1bf70026, 0x1bf70025, ++ 0x1af7002d, 0x1af7002b, 0x1af7002a, 0x1af70029, ++ 0x1af70028, 0x1af70027, 0x1af70026, 0x1af70025, ++ 0x19f7002d, 0x19f7002b, 0x19f7002a, 0x19f70029, ++ 0x19f70028, 0x19f70027, 0x19f70026, 0x19f70025, ++ 0x18f7002d, 0x18f7002b, 0x18f7002a, 0x18f70029, ++ 0x18f70028, 0x18f70027, 0x18f70026, 0x18f70025, ++ 0x17f7002d, 0x17f7002b, 0x17f7002a, 0x17f70029, ++ 0x17f70028, 0x17f70027, 0x17f70026, 0x17f70025, ++ 0x16f7002d, 0x16f7002b, 0x16f7002a, 0x16f70029, ++ 0x16f70028, 0x16f70027, 0x16f70026, 0x16f70025, ++ 0x15f7002d, 0x15f7002b, 0x15f7002a, 0x15f70029, ++ 0x15f70028, 0x15f70027, 0x15f70026, 0x15f70025, ++ 0x14f7002d, 0x14f7002b, 0x14f7002a, 0x14f70029, ++ 0x14f70028, 0x14f70027, 0x14f70026, 0x14f70025, ++ 0x13f7002d, 0x13f7002b, 0x13f7002a, 0x13f70029, ++ 0x13f70028, 0x13f70027, 0x13f70026, 0x13f70025, ++ 0x12f7002d, 0x12f7002b, 0x12f7002a, 0x12f70029, ++ 0x12f70028, 0x12f70027, 0x12f70026, 0x12f70025, ++ 0x11f7002d, 0x11f7002b, 0x11f7002a, 0x11f70029, ++ 0x11f70028, 0x11f70027, 0x11f70026, 0x11f70025, ++ 0x10f7002d, 0x10f7002b, 0x10f7002a, 0x10f70029, ++ 0x10f70028, 0x10f70027, 0x10f70026, 0x10f70025 ++}; ++ ++static u32 nphy_tpc_txgain_ipa_rev6[] = { ++ 0x0ff7002d, 0x0ff7002b, 0x0ff7002a, 0x0ff70029, ++ 0x0ff70028, 0x0ff70027, 0x0ff70026, 0x0ff70025, ++ 0x0ef7002d, 0x0ef7002b, 0x0ef7002a, 0x0ef70029, ++ 0x0ef70028, 0x0ef70027, 0x0ef70026, 0x0ef70025, ++ 0x0df7002d, 0x0df7002b, 0x0df7002a, 0x0df70029, ++ 0x0df70028, 0x0df70027, 0x0df70026, 0x0df70025, ++ 0x0cf7002d, 0x0cf7002b, 0x0cf7002a, 0x0cf70029, ++ 0x0cf70028, 0x0cf70027, 0x0cf70026, 0x0cf70025, ++ 0x0bf7002d, 0x0bf7002b, 0x0bf7002a, 0x0bf70029, ++ 0x0bf70028, 0x0bf70027, 0x0bf70026, 0x0bf70025, ++ 0x0af7002d, 0x0af7002b, 0x0af7002a, 0x0af70029, ++ 0x0af70028, 0x0af70027, 0x0af70026, 0x0af70025, ++ 0x09f7002d, 0x09f7002b, 0x09f7002a, 0x09f70029, ++ 0x09f70028, 0x09f70027, 0x09f70026, 0x09f70025, ++ 0x08f7002d, 0x08f7002b, 0x08f7002a, 0x08f70029, ++ 0x08f70028, 0x08f70027, 0x08f70026, 0x08f70025, ++ 0x07f7002d, 0x07f7002b, 0x07f7002a, 0x07f70029, ++ 0x07f70028, 0x07f70027, 0x07f70026, 0x07f70025, ++ 0x06f7002d, 0x06f7002b, 0x06f7002a, 0x06f70029, ++ 0x06f70028, 0x06f70027, 0x06f70026, 0x06f70025, ++ 0x05f7002d, 0x05f7002b, 0x05f7002a, 0x05f70029, ++ 0x05f70028, 0x05f70027, 0x05f70026, 0x05f70025, ++ 0x04f7002d, 0x04f7002b, 0x04f7002a, 0x04f70029, ++ 0x04f70028, 0x04f70027, 0x04f70026, 0x04f70025, ++ 0x03f7002d, 0x03f7002b, 0x03f7002a, 0x03f70029, ++ 0x03f70028, 0x03f70027, 0x03f70026, 0x03f70025, ++ 0x02f7002d, 0x02f7002b, 0x02f7002a, 0x02f70029, ++ 0x02f70028, 0x02f70027, 0x02f70026, 0x02f70025, ++ 0x01f7002d, 0x01f7002b, 0x01f7002a, 0x01f70029, ++ 0x01f70028, 0x01f70027, 0x01f70026, 0x01f70025, ++ 0x00f7002d, 0x00f7002b, 0x00f7002a, 0x00f70029, ++ 0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025 ++}; ++ ++static u32 nphy_tpc_txgain_ipa_2g_2057rev3[] = { ++ 0x70ff0040, 0x70f7003e, 0x70ef003b, 0x70e70039, ++ 0x70df0037, 0x70d70036, 0x70cf0033, 0x70c70032, ++ 0x70bf0031, 0x70b7002f, 0x70af002e, 0x70a7002d, ++ 0x709f002d, 0x7097002c, 0x708f002c, 0x7087002c, ++ 0x707f002b, 0x7077002c, 0x706f002c, 0x7067002d, ++ 0x705f002e, 0x705f002b, 0x705f0029, 0x7057002a, ++ 0x70570028, 0x704f002a, 0x7047002c, 0x7047002a, ++ 0x70470028, 0x70470026, 0x70470024, 0x70470022, ++ 0x7047001f, 0x70370027, 0x70370024, 0x70370022, ++ 0x70370020, 0x7037001f, 0x7037001d, 0x7037001b, ++ 0x7037001a, 0x70370018, 0x70370017, 0x7027001e, ++ 0x7027001d, 0x7027001a, 0x701f0024, 0x701f0022, ++ 0x701f0020, 0x701f001f, 0x701f001d, 0x701f001b, ++ 0x701f001a, 0x701f0018, 0x701f0017, 0x701f0015, ++ 0x701f0014, 0x701f0013, 0x701f0012, 0x701f0011, ++ 0x70170019, 0x70170018, 0x70170016, 0x70170015, ++ 0x70170014, 0x70170013, 0x70170012, 0x70170010, ++ 0x70170010, 0x7017000f, 0x700f001d, 0x700f001b, ++ 0x700f001a, 0x700f0018, 0x700f0017, 0x700f0015, ++ 0x700f0015, 0x700f0013, 0x700f0013, 0x700f0011, ++ 0x700f0010, 0x700f0010, 0x700f000f, 0x700f000e, ++ 0x700f000d, 0x700f000c, 0x700f000b, 0x700f000b, ++ 0x700f000b, 0x700f000a, 0x700f0009, 0x700f0009, ++ 0x700f0009, 0x700f0008, 0x700f0007, 0x700f0007, ++ 0x700f0006, 0x700f0006, 0x700f0006, 0x700f0006, ++ 0x700f0005, 0x700f0005, 0x700f0005, 0x700f0004, ++ 0x700f0004, 0x700f0004, 0x700f0004, 0x700f0004, ++ 0x700f0004, 0x700f0003, 0x700f0003, 0x700f0003, ++ 0x700f0003, 0x700f0002, 0x700f0002, 0x700f0002, ++ 0x700f0002, 0x700f0002, 0x700f0002, 0x700f0001, ++ 0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001, ++ 0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001 ++}; ++ ++static u32 nphy_tpc_txgain_ipa_2g_2057rev4n6[] = { ++ 0xf0ff0040, 0xf0f7003e, 0xf0ef003b, 0xf0e70039, ++ 0xf0df0037, 0xf0d70036, 0xf0cf0033, 0xf0c70032, ++ 0xf0bf0031, 0xf0b7002f, 0xf0af002e, 0xf0a7002d, ++ 0xf09f002d, 0xf097002c, 0xf08f002c, 0xf087002c, ++ 0xf07f002b, 0xf077002c, 0xf06f002c, 0xf067002d, ++ 0xf05f002e, 0xf05f002b, 0xf05f0029, 0xf057002a, ++ 0xf0570028, 0xf04f002a, 0xf047002c, 0xf047002a, ++ 0xf0470028, 0xf0470026, 0xf0470024, 0xf0470022, ++ 0xf047001f, 0xf0370027, 0xf0370024, 0xf0370022, ++ 0xf0370020, 0xf037001f, 0xf037001d, 0xf037001b, ++ 0xf037001a, 0xf0370018, 0xf0370017, 0xf027001e, ++ 0xf027001d, 0xf027001a, 0xf01f0024, 0xf01f0022, ++ 0xf01f0020, 0xf01f001f, 0xf01f001d, 0xf01f001b, ++ 0xf01f001a, 0xf01f0018, 0xf01f0017, 0xf01f0015, ++ 0xf01f0014, 0xf01f0013, 0xf01f0012, 0xf01f0011, ++ 0xf0170019, 0xf0170018, 0xf0170016, 0xf0170015, ++ 0xf0170014, 0xf0170013, 0xf0170012, 0xf0170010, ++ 0xf0170010, 0xf017000f, 0xf00f001d, 0xf00f001b, ++ 0xf00f001a, 0xf00f0018, 0xf00f0017, 0xf00f0015, ++ 0xf00f0015, 0xf00f0013, 0xf00f0013, 0xf00f0011, ++ 0xf00f0010, 0xf00f0010, 0xf00f000f, 0xf00f000e, ++ 0xf00f000d, 0xf00f000c, 0xf00f000b, 0xf00f000b, ++ 0xf00f000b, 0xf00f000a, 0xf00f0009, 0xf00f0009, ++ 0xf00f0009, 0xf00f0008, 0xf00f0007, 0xf00f0007, ++ 0xf00f0006, 0xf00f0006, 0xf00f0006, 0xf00f0006, ++ 0xf00f0005, 0xf00f0005, 0xf00f0005, 0xf00f0004, ++ 0xf00f0004, 0xf00f0004, 0xf00f0004, 0xf00f0004, ++ 0xf00f0004, 0xf00f0003, 0xf00f0003, 0xf00f0003, ++ 0xf00f0003, 0xf00f0002, 0xf00f0002, 0xf00f0002, ++ 0xf00f0002, 0xf00f0002, 0xf00f0002, 0xf00f0001, ++ 0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001, ++ 0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001 ++}; ++ ++static u32 nphy_tpc_txgain_ipa_2g_2057rev5[] = { ++ 0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e, ++ 0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033, ++ 0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e, ++ 0x3067002e, 0x305f002f, 0x30570030, 0x3057002d, ++ 0x304f002e, 0x30470031, 0x3047002e, 0x3047002c, ++ 0x30470029, 0x303f002c, 0x303f0029, 0x3037002d, ++ 0x3037002a, 0x30370028, 0x302f002c, 0x302f002a, ++ 0x302f0028, 0x302f0026, 0x3027002c, 0x30270029, ++ 0x30270027, 0x30270025, 0x30270023, 0x301f002c, ++ 0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024, ++ 0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b, ++ 0x30170028, 0x30170026, 0x30170024, 0x30170022, ++ 0x30170020, 0x3017001e, 0x3017001d, 0x3017001b, ++ 0x3017001a, 0x30170018, 0x30170017, 0x30170015, ++ 0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024, ++ 0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d, ++ 0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017, ++ 0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215, ++ 0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715 ++}; ++ ++static u32 nphy_tpc_txgain_ipa_2g_2057rev7[] = { ++ 0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e, ++ 0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033, ++ 0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e, ++ 0x3067002e, 0x305f002f, 0x30570030, 0x3057002d, ++ 0x304f002e, 0x30470031, 0x3047002e, 0x3047002c, ++ 0x30470029, 0x303f002c, 0x303f0029, 0x3037002d, ++ 0x3037002a, 0x30370028, 0x302f002c, 0x302f002a, ++ 0x302f0028, 0x302f0026, 0x3027002c, 0x30270029, ++ 0x30270027, 0x30270025, 0x30270023, 0x301f002c, ++ 0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024, ++ 0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b, ++ 0x30170028, 0x30170026, 0x30170024, 0x30170022, ++ 0x30170020, 0x3017001e, 0x3017001d, 0x3017001b, ++ 0x3017001a, 0x30170018, 0x30170017, 0x30170015, ++ 0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024, ++ 0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d, ++ 0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017, ++ 0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215, ++ 0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715, ++ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715 ++}; ++ ++static u32 nphy_tpc_txgain_ipa_5g[] = { ++ 0x7ff70035, 0x7ff70033, 0x7ff70032, 0x7ff70031, ++ 0x7ff7002f, 0x7ff7002e, 0x7ff7002d, 0x7ff7002b, ++ 0x7ff7002a, 0x7ff70029, 0x7ff70028, 0x7ff70027, ++ 0x7ff70026, 0x7ff70024, 0x7ff70023, 0x7ff70022, ++ 0x7ef70028, 0x7ef70027, 0x7ef70026, 0x7ef70025, ++ 0x7ef70024, 0x7ef70023, 0x7df70028, 0x7df70027, ++ 0x7df70026, 0x7df70025, 0x7df70024, 0x7df70023, ++ 0x7df70022, 0x7cf70029, 0x7cf70028, 0x7cf70027, ++ 0x7cf70026, 0x7cf70025, 0x7cf70023, 0x7cf70022, ++ 0x7bf70029, 0x7bf70028, 0x7bf70026, 0x7bf70025, ++ 0x7bf70024, 0x7bf70023, 0x7bf70022, 0x7bf70021, ++ 0x7af70029, 0x7af70028, 0x7af70027, 0x7af70026, ++ 0x7af70025, 0x7af70024, 0x7af70023, 0x7af70022, ++ 0x79f70029, 0x79f70028, 0x79f70027, 0x79f70026, ++ 0x79f70025, 0x79f70024, 0x79f70023, 0x79f70022, ++ 0x78f70029, 0x78f70028, 0x78f70027, 0x78f70026, ++ 0x78f70025, 0x78f70024, 0x78f70023, 0x78f70022, ++ 0x77f70029, 0x77f70028, 0x77f70027, 0x77f70026, ++ 0x77f70025, 0x77f70024, 0x77f70023, 0x77f70022, ++ 0x76f70029, 0x76f70028, 0x76f70027, 0x76f70026, ++ 0x76f70024, 0x76f70023, 0x76f70022, 0x76f70021, ++ 0x75f70029, 0x75f70028, 0x75f70027, 0x75f70026, ++ 0x75f70025, 0x75f70024, 0x75f70023, 0x74f70029, ++ 0x74f70028, 0x74f70026, 0x74f70025, 0x74f70024, ++ 0x74f70023, 0x74f70022, 0x73f70029, 0x73f70027, ++ 0x73f70026, 0x73f70025, 0x73f70024, 0x73f70023, ++ 0x73f70022, 0x72f70028, 0x72f70027, 0x72f70026, ++ 0x72f70025, 0x72f70024, 0x72f70023, 0x72f70022, ++ 0x71f70028, 0x71f70027, 0x71f70026, 0x71f70025, ++ 0x71f70024, 0x71f70023, 0x70f70028, 0x70f70027, ++ 0x70f70026, 0x70f70024, 0x70f70023, 0x70f70022, ++ 0x70f70021, 0x70f70020, 0x70f70020, 0x70f7001f ++}; ++ ++static u32 nphy_tpc_txgain_ipa_5g_2057[] = { ++ 0x7f7f0044, 0x7f7f0040, 0x7f7f003c, 0x7f7f0039, ++ 0x7f7f0036, 0x7e7f003c, 0x7e7f0038, 0x7e7f0035, ++ 0x7d7f003c, 0x7d7f0039, 0x7d7f0036, 0x7d7f0033, ++ 0x7c7f003b, 0x7c7f0037, 0x7c7f0034, 0x7b7f003a, ++ 0x7b7f0036, 0x7b7f0033, 0x7a7f003c, 0x7a7f0039, ++ 0x7a7f0036, 0x7a7f0033, 0x797f003b, 0x797f0038, ++ 0x797f0035, 0x797f0032, 0x787f003b, 0x787f0038, ++ 0x787f0035, 0x787f0032, 0x777f003a, 0x777f0037, ++ 0x777f0034, 0x777f0031, 0x767f003a, 0x767f0036, ++ 0x767f0033, 0x767f0031, 0x757f003a, 0x757f0037, ++ 0x757f0034, 0x747f003c, 0x747f0039, 0x747f0036, ++ 0x747f0033, 0x737f003b, 0x737f0038, 0x737f0035, ++ 0x737f0032, 0x727f0039, 0x727f0036, 0x727f0033, ++ 0x727f0030, 0x717f003a, 0x717f0037, 0x717f0034, ++ 0x707f003b, 0x707f0038, 0x707f0035, 0x707f0032, ++ 0x707f002f, 0x707f002d, 0x707f002a, 0x707f0028, ++ 0x707f0025, 0x707f0023, 0x707f0021, 0x707f0020, ++ 0x707f001e, 0x707f001c, 0x707f001b, 0x707f0019, ++ 0x707f0018, 0x707f0016, 0x707f0015, 0x707f0014, ++ 0x707f0013, 0x707f0012, 0x707f0011, 0x707f0010, ++ 0x707f000f, 0x707f000e, 0x707f000d, 0x707f000d, ++ 0x707f000c, 0x707f000b, 0x707f000b, 0x707f000a, ++ 0x707f0009, 0x707f0009, 0x707f0008, 0x707f0008, ++ 0x707f0007, 0x707f0007, 0x707f0007, 0x707f0006, ++ 0x707f0006, 0x707f0006, 0x707f0005, 0x707f0005, ++ 0x707f0005, 0x707f0004, 0x707f0004, 0x707f0004, ++ 0x707f0004, 0x707f0004, 0x707f0003, 0x707f0003, ++ 0x707f0003, 0x707f0003, 0x707f0003, 0x707f0003, ++ 0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002, ++ 0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002, ++ 0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001, ++ 0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001 ++}; ++ ++static u32 nphy_tpc_txgain_ipa_5g_2057rev7[] = { ++ 0x6f7f0031, 0x6f7f002e, 0x6f7f002c, 0x6f7f002a, ++ 0x6f7f0027, 0x6e7f002e, 0x6e7f002c, 0x6e7f002a, ++ 0x6d7f0030, 0x6d7f002d, 0x6d7f002a, 0x6d7f0028, ++ 0x6c7f0030, 0x6c7f002d, 0x6c7f002b, 0x6b7f002e, ++ 0x6b7f002c, 0x6b7f002a, 0x6b7f0027, 0x6a7f002e, ++ 0x6a7f002c, 0x6a7f002a, 0x697f0030, 0x697f002e, ++ 0x697f002b, 0x697f0029, 0x687f002f, 0x687f002d, ++ 0x687f002a, 0x687f0027, 0x677f002f, 0x677f002d, ++ 0x677f002a, 0x667f0031, 0x667f002e, 0x667f002c, ++ 0x667f002a, 0x657f0030, 0x657f002e, 0x657f002b, ++ 0x657f0029, 0x647f0030, 0x647f002d, 0x647f002b, ++ 0x647f0029, 0x637f002f, 0x637f002d, 0x637f002a, ++ 0x627f0030, 0x627f002d, 0x627f002b, 0x627f0029, ++ 0x617f0030, 0x617f002e, 0x617f002b, 0x617f0029, ++ 0x607f002f, 0x607f002d, 0x607f002a, 0x607f0027, ++ 0x607f0026, 0x607f0023, 0x607f0021, 0x607f0020, ++ 0x607f001e, 0x607f001c, 0x607f001a, 0x607f0019, ++ 0x607f0018, 0x607f0016, 0x607f0015, 0x607f0014, ++ 0x607f0012, 0x607f0012, 0x607f0011, 0x607f000f, ++ 0x607f000f, 0x607f000e, 0x607f000d, 0x607f000c, ++ 0x607f000c, 0x607f000b, 0x607f000b, 0x607f000a, ++ 0x607f0009, 0x607f0009, 0x607f0008, 0x607f0008, ++ 0x607f0008, 0x607f0007, 0x607f0007, 0x607f0006, ++ 0x607f0006, 0x607f0005, 0x607f0005, 0x607f0005, ++ 0x607f0005, 0x607f0005, 0x607f0004, 0x607f0004, ++ 0x607f0004, 0x607f0004, 0x607f0003, 0x607f0003, ++ 0x607f0003, 0x607f0003, 0x607f0002, 0x607f0002, ++ 0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002, ++ 0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002, ++ 0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002, ++ 0x607f0002, 0x607f0001, 0x607f0001, 0x607f0001, ++ 0x607f0001, 0x607f0001, 0x607f0001, 0x607f0001 ++}; ++ ++static s8 nphy_papd_pga_gain_delta_ipa_2g[] = { ++ -114, -108, -98, -91, -84, -78, -70, -62, ++ -54, -46, -39, -31, -23, -15, -8, 0 ++}; ++ ++static s8 nphy_papd_pga_gain_delta_ipa_5g[] = { ++ -100, -95, -89, -83, -77, -70, -63, -56, ++ -48, -41, -33, -25, -19, -12, -6, 0 ++}; ++ ++static s16 nphy_papd_padgain_dlt_2g_2057rev3n4[] = { ++ -159, -113, -86, -72, -62, -54, -48, -43, ++ -39, -35, -31, -28, -25, -23, -20, -18, ++ -17, -15, -13, -11, -10, -8, -7, -6, ++ -5, -4, -3, -3, -2, -1, -1, 0 ++}; ++ ++static s16 nphy_papd_padgain_dlt_2g_2057rev5[] = { ++ -109, -109, -82, -68, -58, -50, -44, -39, ++ -35, -31, -28, -26, -23, -21, -19, -17, ++ -16, -14, -13, -11, -10, -9, -8, -7, ++ -5, -5, -4, -3, -2, -1, -1, 0 ++}; ++ ++static s16 nphy_papd_padgain_dlt_2g_2057rev7[] = { ++ -122, -122, -95, -80, -69, -61, -54, -49, ++ -43, -39, -35, -32, -28, -26, -23, -21, ++ -18, -16, -15, -13, -11, -10, -8, -7, ++ -6, -5, -4, -3, -2, -1, -1, 0 ++}; ++ ++static s8 nphy_papd_pgagain_dlt_5g_2057[] = { ++ -107, -101, -92, -85, -78, -71, -62, -55, ++ -47, -39, -32, -24, -19, -12, -6, 0 ++}; ++ ++static s8 nphy_papd_pgagain_dlt_5g_2057rev7[] = { ++ -110, -104, -95, -88, -81, -74, -66, -58, ++ -50, -44, -36, -28, -23, -15, -8, 0 ++}; ++ ++static u8 pad_gain_codes_used_2057rev5[] = { ++ 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, ++ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ++}; ++ ++static u8 pad_gain_codes_used_2057rev7[] = { ++ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, ++ 5, 4, 3, 2, 1 ++}; ++ ++static u8 pad_all_gain_codes_2057[] = { ++ 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, ++ 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, ++ 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, ++ 1, 0 ++}; ++ ++static u8 pga_all_gain_codes_2057[] = { ++ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ++}; ++ ++static u32 nphy_papd_scaltbl[] = { ++ 0x0ae2002f, 0x0a3b0032, 0x09a70035, 0x09220038, ++ 0x0887003c, 0x081f003f, 0x07a20043, 0x07340047, ++ 0x06d2004b, 0x067a004f, 0x06170054, 0x05bf0059, ++ 0x0571005e, 0x051e0064, 0x04d3006a, 0x04910070, ++ 0x044c0077, 0x040f007e, 0x03d90085, 0x03a1008d, ++ 0x036f0095, 0x033d009e, 0x030b00a8, 0x02e000b2, ++ 0x02b900bc, 0x029200c7, 0x026d00d3, 0x024900e0, ++ 0x022900ed, 0x020a00fb, 0x01ec010a, 0x01d0011a, ++ 0x01b7012a, 0x019e013c, 0x0187014f, 0x01720162, ++ 0x015d0177, 0x0149018e, 0x013701a5, 0x012601be, ++ 0x011501d9, 0x010501f5, 0x00f70212, 0x00e90232, ++ 0x00dc0253, 0x00d00276, 0x00c4029c, 0x00b902c3, ++ 0x00af02ed, 0x00a5031a, 0x009c0349, 0x0093037a, ++ 0x008b03af, 0x008303e7, 0x007c0422, 0x00750461, ++ 0x006e04a3, 0x006804ea, 0x00620534, 0x005d0583, ++ 0x005805d7, 0x0053062f, 0x004e068d, 0x004a06f1 ++}; ++ ++static u32 nphy_tpc_txgain_rev3[] = { ++ 0x1f410044, 0x1f410042, 0x1f410040, 0x1f41003e, ++ 0x1f41003c, 0x1f41003b, 0x1f410039, 0x1f410037, ++ 0x1e410044, 0x1e410042, 0x1e410040, 0x1e41003e, ++ 0x1e41003c, 0x1e41003b, 0x1e410039, 0x1e410037, ++ 0x1d410044, 0x1d410042, 0x1d410040, 0x1d41003e, ++ 0x1d41003c, 0x1d41003b, 0x1d410039, 0x1d410037, ++ 0x1c410044, 0x1c410042, 0x1c410040, 0x1c41003e, ++ 0x1c41003c, 0x1c41003b, 0x1c410039, 0x1c410037, ++ 0x1b410044, 0x1b410042, 0x1b410040, 0x1b41003e, ++ 0x1b41003c, 0x1b41003b, 0x1b410039, 0x1b410037, ++ 0x1a410044, 0x1a410042, 0x1a410040, 0x1a41003e, ++ 0x1a41003c, 0x1a41003b, 0x1a410039, 0x1a410037, ++ 0x19410044, 0x19410042, 0x19410040, 0x1941003e, ++ 0x1941003c, 0x1941003b, 0x19410039, 0x19410037, ++ 0x18410044, 0x18410042, 0x18410040, 0x1841003e, ++ 0x1841003c, 0x1841003b, 0x18410039, 0x18410037, ++ 0x17410044, 0x17410042, 0x17410040, 0x1741003e, ++ 0x1741003c, 0x1741003b, 0x17410039, 0x17410037, ++ 0x16410044, 0x16410042, 0x16410040, 0x1641003e, ++ 0x1641003c, 0x1641003b, 0x16410039, 0x16410037, ++ 0x15410044, 0x15410042, 0x15410040, 0x1541003e, ++ 0x1541003c, 0x1541003b, 0x15410039, 0x15410037, ++ 0x14410044, 0x14410042, 0x14410040, 0x1441003e, ++ 0x1441003c, 0x1441003b, 0x14410039, 0x14410037, ++ 0x13410044, 0x13410042, 0x13410040, 0x1341003e, ++ 0x1341003c, 0x1341003b, 0x13410039, 0x13410037, ++ 0x12410044, 0x12410042, 0x12410040, 0x1241003e, ++ 0x1241003c, 0x1241003b, 0x12410039, 0x12410037, ++ 0x11410044, 0x11410042, 0x11410040, 0x1141003e, ++ 0x1141003c, 0x1141003b, 0x11410039, 0x11410037, ++ 0x10410044, 0x10410042, 0x10410040, 0x1041003e, ++ 0x1041003c, 0x1041003b, 0x10410039, 0x10410037 ++}; ++ ++static u32 nphy_tpc_txgain_HiPwrEPA[] = { ++ 0x0f410044, 0x0f410042, 0x0f410040, 0x0f41003e, ++ 0x0f41003c, 0x0f41003b, 0x0f410039, 0x0f410037, ++ 0x0e410044, 0x0e410042, 0x0e410040, 0x0e41003e, ++ 0x0e41003c, 0x0e41003b, 0x0e410039, 0x0e410037, ++ 0x0d410044, 0x0d410042, 0x0d410040, 0x0d41003e, ++ 0x0d41003c, 0x0d41003b, 0x0d410039, 0x0d410037, ++ 0x0c410044, 0x0c410042, 0x0c410040, 0x0c41003e, ++ 0x0c41003c, 0x0c41003b, 0x0c410039, 0x0c410037, ++ 0x0b410044, 0x0b410042, 0x0b410040, 0x0b41003e, ++ 0x0b41003c, 0x0b41003b, 0x0b410039, 0x0b410037, ++ 0x0a410044, 0x0a410042, 0x0a410040, 0x0a41003e, ++ 0x0a41003c, 0x0a41003b, 0x0a410039, 0x0a410037, ++ 0x09410044, 0x09410042, 0x09410040, 0x0941003e, ++ 0x0941003c, 0x0941003b, 0x09410039, 0x09410037, ++ 0x08410044, 0x08410042, 0x08410040, 0x0841003e, ++ 0x0841003c, 0x0841003b, 0x08410039, 0x08410037, ++ 0x07410044, 0x07410042, 0x07410040, 0x0741003e, ++ 0x0741003c, 0x0741003b, 0x07410039, 0x07410037, ++ 0x06410044, 0x06410042, 0x06410040, 0x0641003e, ++ 0x0641003c, 0x0641003b, 0x06410039, 0x06410037, ++ 0x05410044, 0x05410042, 0x05410040, 0x0541003e, ++ 0x0541003c, 0x0541003b, 0x05410039, 0x05410037, ++ 0x04410044, 0x04410042, 0x04410040, 0x0441003e, ++ 0x0441003c, 0x0441003b, 0x04410039, 0x04410037, ++ 0x03410044, 0x03410042, 0x03410040, 0x0341003e, ++ 0x0341003c, 0x0341003b, 0x03410039, 0x03410037, ++ 0x02410044, 0x02410042, 0x02410040, 0x0241003e, ++ 0x0241003c, 0x0241003b, 0x02410039, 0x02410037, ++ 0x01410044, 0x01410042, 0x01410040, 0x0141003e, ++ 0x0141003c, 0x0141003b, 0x01410039, 0x01410037, ++ 0x00410044, 0x00410042, 0x00410040, 0x0041003e, ++ 0x0041003c, 0x0041003b, 0x00410039, 0x00410037 ++}; ++ ++static u32 nphy_tpc_txgain_epa_2057rev3[] = { ++ 0x80f90040, 0x80e10040, 0x80e1003c, 0x80c9003d, ++ 0x80b9003c, 0x80a9003d, 0x80a1003c, 0x8099003b, ++ 0x8091003b, 0x8089003a, 0x8081003a, 0x80790039, ++ 0x80710039, 0x8069003a, 0x8061003b, 0x8059003d, ++ 0x8051003f, 0x80490042, 0x8049003e, 0x8049003b, ++ 0x8041003e, 0x8041003b, 0x8039003e, 0x8039003b, ++ 0x80390038, 0x80390035, 0x8031003a, 0x80310036, ++ 0x80310033, 0x8029003a, 0x80290037, 0x80290034, ++ 0x80290031, 0x80210039, 0x80210036, 0x80210033, ++ 0x80210030, 0x8019003c, 0x80190039, 0x80190036, ++ 0x80190033, 0x80190030, 0x8019002d, 0x8019002b, ++ 0x80190028, 0x8011003a, 0x80110036, 0x80110033, ++ 0x80110030, 0x8011002e, 0x8011002b, 0x80110029, ++ 0x80110027, 0x80110024, 0x80110022, 0x80110020, ++ 0x8011001f, 0x8011001d, 0x8009003a, 0x80090037, ++ 0x80090034, 0x80090031, 0x8009002e, 0x8009002c, ++ 0x80090029, 0x80090027, 0x80090025, 0x80090023, ++ 0x80090021, 0x8009001f, 0x8009001d, 0x8009011d, ++ 0x8009021d, 0x8009031d, 0x8009041d, 0x8009051d, ++ 0x8009061d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d, ++ 0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d ++}; ++ ++static u32 nphy_tpc_txgain_epa_2057rev5[] = { ++ 0x10f90040, 0x10e10040, 0x10e1003c, 0x10c9003d, ++ 0x10b9003c, 0x10a9003d, 0x10a1003c, 0x1099003b, ++ 0x1091003b, 0x1089003a, 0x1081003a, 0x10790039, ++ 0x10710039, 0x1069003a, 0x1061003b, 0x1059003d, ++ 0x1051003f, 0x10490042, 0x1049003e, 0x1049003b, ++ 0x1041003e, 0x1041003b, 0x1039003e, 0x1039003b, ++ 0x10390038, 0x10390035, 0x1031003a, 0x10310036, ++ 0x10310033, 0x1029003a, 0x10290037, 0x10290034, ++ 0x10290031, 0x10210039, 0x10210036, 0x10210033, ++ 0x10210030, 0x1019003c, 0x10190039, 0x10190036, ++ 0x10190033, 0x10190030, 0x1019002d, 0x1019002b, ++ 0x10190028, 0x1011003a, 0x10110036, 0x10110033, ++ 0x10110030, 0x1011002e, 0x1011002b, 0x10110029, ++ 0x10110027, 0x10110024, 0x10110022, 0x10110020, ++ 0x1011001f, 0x1011001d, 0x1009003a, 0x10090037, ++ 0x10090034, 0x10090031, 0x1009002e, 0x1009002c, ++ 0x10090029, 0x10090027, 0x10090025, 0x10090023, ++ 0x10090021, 0x1009001f, 0x1009001d, 0x1009001b, ++ 0x1009001a, 0x10090018, 0x10090017, 0x10090016, ++ 0x10090015, 0x10090013, 0x10090012, 0x10090011, ++ 0x10090010, 0x1009000f, 0x1009000f, 0x1009000e, ++ 0x1009000d, 0x1009000c, 0x1009000c, 0x1009000b, ++ 0x1009000a, 0x1009000a, 0x10090009, 0x10090009, ++ 0x10090008, 0x10090008, 0x10090007, 0x10090007, ++ 0x10090007, 0x10090006, 0x10090006, 0x10090005, ++ 0x10090005, 0x10090005, 0x10090005, 0x10090004, ++ 0x10090004, 0x10090004, 0x10090004, 0x10090003, ++ 0x10090003, 0x10090003, 0x10090003, 0x10090003, ++ 0x10090003, 0x10090002, 0x10090002, 0x10090002, ++ 0x10090002, 0x10090002, 0x10090002, 0x10090002, ++ 0x10090002, 0x10090002, 0x10090001, 0x10090001, ++ 0x10090001, 0x10090001, 0x10090001, 0x10090001 ++}; ++ ++static u32 nphy_tpc_5GHz_txgain_rev3[] = { ++ 0xcff70044, 0xcff70042, 0xcff70040, 0xcff7003e, ++ 0xcff7003c, 0xcff7003b, 0xcff70039, 0xcff70037, ++ 0xcef70044, 0xcef70042, 0xcef70040, 0xcef7003e, ++ 0xcef7003c, 0xcef7003b, 0xcef70039, 0xcef70037, ++ 0xcdf70044, 0xcdf70042, 0xcdf70040, 0xcdf7003e, ++ 0xcdf7003c, 0xcdf7003b, 0xcdf70039, 0xcdf70037, ++ 0xccf70044, 0xccf70042, 0xccf70040, 0xccf7003e, ++ 0xccf7003c, 0xccf7003b, 0xccf70039, 0xccf70037, ++ 0xcbf70044, 0xcbf70042, 0xcbf70040, 0xcbf7003e, ++ 0xcbf7003c, 0xcbf7003b, 0xcbf70039, 0xcbf70037, ++ 0xcaf70044, 0xcaf70042, 0xcaf70040, 0xcaf7003e, ++ 0xcaf7003c, 0xcaf7003b, 0xcaf70039, 0xcaf70037, ++ 0xc9f70044, 0xc9f70042, 0xc9f70040, 0xc9f7003e, ++ 0xc9f7003c, 0xc9f7003b, 0xc9f70039, 0xc9f70037, ++ 0xc8f70044, 0xc8f70042, 0xc8f70040, 0xc8f7003e, ++ 0xc8f7003c, 0xc8f7003b, 0xc8f70039, 0xc8f70037, ++ 0xc7f70044, 0xc7f70042, 0xc7f70040, 0xc7f7003e, ++ 0xc7f7003c, 0xc7f7003b, 0xc7f70039, 0xc7f70037, ++ 0xc6f70044, 0xc6f70042, 0xc6f70040, 0xc6f7003e, ++ 0xc6f7003c, 0xc6f7003b, 0xc6f70039, 0xc6f70037, ++ 0xc5f70044, 0xc5f70042, 0xc5f70040, 0xc5f7003e, ++ 0xc5f7003c, 0xc5f7003b, 0xc5f70039, 0xc5f70037, ++ 0xc4f70044, 0xc4f70042, 0xc4f70040, 0xc4f7003e, ++ 0xc4f7003c, 0xc4f7003b, 0xc4f70039, 0xc4f70037, ++ 0xc3f70044, 0xc3f70042, 0xc3f70040, 0xc3f7003e, ++ 0xc3f7003c, 0xc3f7003b, 0xc3f70039, 0xc3f70037, ++ 0xc2f70044, 0xc2f70042, 0xc2f70040, 0xc2f7003e, ++ 0xc2f7003c, 0xc2f7003b, 0xc2f70039, 0xc2f70037, ++ 0xc1f70044, 0xc1f70042, 0xc1f70040, 0xc1f7003e, ++ 0xc1f7003c, 0xc1f7003b, 0xc1f70039, 0xc1f70037, ++ 0xc0f70044, 0xc0f70042, 0xc0f70040, 0xc0f7003e, ++ 0xc0f7003c, 0xc0f7003b, 0xc0f70039, 0xc0f70037 ++}; ++ ++static u32 nphy_tpc_5GHz_txgain_rev4[] = { ++ 0x2ff20044, 0x2ff20042, 0x2ff20040, 0x2ff2003e, ++ 0x2ff2003c, 0x2ff2003b, 0x2ff20039, 0x2ff20037, ++ 0x2ef20044, 0x2ef20042, 0x2ef20040, 0x2ef2003e, ++ 0x2ef2003c, 0x2ef2003b, 0x2ef20039, 0x2ef20037, ++ 0x2df20044, 0x2df20042, 0x2df20040, 0x2df2003e, ++ 0x2df2003c, 0x2df2003b, 0x2df20039, 0x2df20037, ++ 0x2cf20044, 0x2cf20042, 0x2cf20040, 0x2cf2003e, ++ 0x2cf2003c, 0x2cf2003b, 0x2cf20039, 0x2cf20037, ++ 0x2bf20044, 0x2bf20042, 0x2bf20040, 0x2bf2003e, ++ 0x2bf2003c, 0x2bf2003b, 0x2bf20039, 0x2bf20037, ++ 0x2af20044, 0x2af20042, 0x2af20040, 0x2af2003e, ++ 0x2af2003c, 0x2af2003b, 0x2af20039, 0x2af20037, ++ 0x29f20044, 0x29f20042, 0x29f20040, 0x29f2003e, ++ 0x29f2003c, 0x29f2003b, 0x29f20039, 0x29f20037, ++ 0x28f20044, 0x28f20042, 0x28f20040, 0x28f2003e, ++ 0x28f2003c, 0x28f2003b, 0x28f20039, 0x28f20037, ++ 0x27f20044, 0x27f20042, 0x27f20040, 0x27f2003e, ++ 0x27f2003c, 0x27f2003b, 0x27f20039, 0x27f20037, ++ 0x26f20044, 0x26f20042, 0x26f20040, 0x26f2003e, ++ 0x26f2003c, 0x26f2003b, 0x26f20039, 0x26f20037, ++ 0x25f20044, 0x25f20042, 0x25f20040, 0x25f2003e, ++ 0x25f2003c, 0x25f2003b, 0x25f20039, 0x25f20037, ++ 0x24f20044, 0x24f20042, 0x24f20040, 0x24f2003e, ++ 0x24f2003c, 0x24f2003b, 0x24f20039, 0x24f20038, ++ 0x23f20041, 0x23f20040, 0x23f2003f, 0x23f2003e, ++ 0x23f2003c, 0x23f2003b, 0x23f20039, 0x23f20037, ++ 0x22f20044, 0x22f20042, 0x22f20040, 0x22f2003e, ++ 0x22f2003c, 0x22f2003b, 0x22f20039, 0x22f20037, ++ 0x21f20044, 0x21f20042, 0x21f20040, 0x21f2003e, ++ 0x21f2003c, 0x21f2003b, 0x21f20039, 0x21f20037, ++ 0x20d20043, 0x20d20041, 0x20d2003e, 0x20d2003c, ++ 0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034 ++}; ++ ++static u32 nphy_tpc_5GHz_txgain_rev5[] = { ++ 0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044, ++ 0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c, ++ 0x0e620044, 0x0e620042, 0x0e620040, 0x0e62003e, ++ 0x0e62003c, 0x0e62003d, 0x0e62003b, 0x0e62003a, ++ 0x0d620043, 0x0d620041, 0x0d620040, 0x0d62003e, ++ 0x0d62003d, 0x0d62003c, 0x0d62003b, 0x0d62003a, ++ 0x0c620041, 0x0c620040, 0x0c62003f, 0x0c62003e, ++ 0x0c62003c, 0x0c62003b, 0x0c620039, 0x0c620037, ++ 0x0b620046, 0x0b620044, 0x0b620042, 0x0b620040, ++ 0x0b62003e, 0x0b62003c, 0x0b62003b, 0x0b62003a, ++ 0x0a620041, 0x0a620040, 0x0a62003e, 0x0a62003c, ++ 0x0a62003b, 0x0a62003a, 0x0a620039, 0x0a620038, ++ 0x0962003e, 0x0962003d, 0x0962003c, 0x0962003b, ++ 0x09620039, 0x09620037, 0x09620035, 0x09620033, ++ 0x08620044, 0x08620042, 0x08620040, 0x0862003e, ++ 0x0862003c, 0x0862003b, 0x0862003a, 0x08620039, ++ 0x07620043, 0x07620042, 0x07620040, 0x0762003f, ++ 0x0762003d, 0x0762003b, 0x0762003a, 0x07620039, ++ 0x0662003e, 0x0662003d, 0x0662003c, 0x0662003b, ++ 0x06620039, 0x06620037, 0x06620035, 0x06620033, ++ 0x05620046, 0x05620044, 0x05620042, 0x05620040, ++ 0x0562003e, 0x0562003c, 0x0562003b, 0x05620039, ++ 0x04620044, 0x04620042, 0x04620040, 0x0462003e, ++ 0x0462003c, 0x0462003b, 0x04620039, 0x04620038, ++ 0x0362003c, 0x0362003b, 0x0362003a, 0x03620039, ++ 0x03620038, 0x03620037, 0x03620035, 0x03620033, ++ 0x0262004c, 0x0262004a, 0x02620048, 0x02620047, ++ 0x02620046, 0x02620044, 0x02620043, 0x02620042, ++ 0x0162004a, 0x01620048, 0x01620046, 0x01620044, ++ 0x01620043, 0x01620042, 0x01620041, 0x01620040, ++ 0x00620042, 0x00620040, 0x0062003e, 0x0062003c, ++ 0x0062003b, 0x00620039, 0x00620037, 0x00620035 ++}; ++ ++static u32 nphy_tpc_5GHz_txgain_HiPwrEPA[] = { ++ 0x2ff10044, 0x2ff10042, 0x2ff10040, 0x2ff1003e, ++ 0x2ff1003c, 0x2ff1003b, 0x2ff10039, 0x2ff10037, ++ 0x2ef10044, 0x2ef10042, 0x2ef10040, 0x2ef1003e, ++ 0x2ef1003c, 0x2ef1003b, 0x2ef10039, 0x2ef10037, ++ 0x2df10044, 0x2df10042, 0x2df10040, 0x2df1003e, ++ 0x2df1003c, 0x2df1003b, 0x2df10039, 0x2df10037, ++ 0x2cf10044, 0x2cf10042, 0x2cf10040, 0x2cf1003e, ++ 0x2cf1003c, 0x2cf1003b, 0x2cf10039, 0x2cf10037, ++ 0x2bf10044, 0x2bf10042, 0x2bf10040, 0x2bf1003e, ++ 0x2bf1003c, 0x2bf1003b, 0x2bf10039, 0x2bf10037, ++ 0x2af10044, 0x2af10042, 0x2af10040, 0x2af1003e, ++ 0x2af1003c, 0x2af1003b, 0x2af10039, 0x2af10037, ++ 0x29f10044, 0x29f10042, 0x29f10040, 0x29f1003e, ++ 0x29f1003c, 0x29f1003b, 0x29f10039, 0x29f10037, ++ 0x28f10044, 0x28f10042, 0x28f10040, 0x28f1003e, ++ 0x28f1003c, 0x28f1003b, 0x28f10039, 0x28f10037, ++ 0x27f10044, 0x27f10042, 0x27f10040, 0x27f1003e, ++ 0x27f1003c, 0x27f1003b, 0x27f10039, 0x27f10037, ++ 0x26f10044, 0x26f10042, 0x26f10040, 0x26f1003e, ++ 0x26f1003c, 0x26f1003b, 0x26f10039, 0x26f10037, ++ 0x25f10044, 0x25f10042, 0x25f10040, 0x25f1003e, ++ 0x25f1003c, 0x25f1003b, 0x25f10039, 0x25f10037, ++ 0x24f10044, 0x24f10042, 0x24f10040, 0x24f1003e, ++ 0x24f1003c, 0x24f1003b, 0x24f10039, 0x24f10038, ++ 0x23f10041, 0x23f10040, 0x23f1003f, 0x23f1003e, ++ 0x23f1003c, 0x23f1003b, 0x23f10039, 0x23f10037, ++ 0x22f10044, 0x22f10042, 0x22f10040, 0x22f1003e, ++ 0x22f1003c, 0x22f1003b, 0x22f10039, 0x22f10037, ++ 0x21f10044, 0x21f10042, 0x21f10040, 0x21f1003e, ++ 0x21f1003c, 0x21f1003b, 0x21f10039, 0x21f10037, ++ 0x20d10043, 0x20d10041, 0x20d1003e, 0x20d1003c, ++ 0x20d1003a, 0x20d10038, 0x20d10036, 0x20d10034 ++}; ++ ++static u8 ant_sw_ctrl_tbl_rev8_2o3[] = { 0x14, 0x18 }; ++static u8 ant_sw_ctrl_tbl_rev8[] = { 0x4, 0x8, 0x4, 0x8, 0x11, 0x12 }; ++static u8 ant_sw_ctrl_tbl_rev8_2057v7_core0[] = { ++ 0x09, 0x0a, 0x15, 0x16, 0x09, 0x0a ++}; ++static u8 ant_sw_ctrl_tbl_rev8_2057v7_core1[] = { ++ 0x09, 0x0a, 0x09, 0x0a, 0x15, 0x16 ++}; ++ ++bool wlc_phy_bist_check_phy(struct brcms_phy_pub *pih) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ u32 phybist0, phybist1, phybist2, phybist3, phybist4; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 16)) ++ return true; ++ ++ phybist0 = read_phy_reg(pi, 0x0e); ++ phybist1 = read_phy_reg(pi, 0x0f); ++ phybist2 = read_phy_reg(pi, 0xea); ++ phybist3 = read_phy_reg(pi, 0xeb); ++ phybist4 = read_phy_reg(pi, 0x156); ++ ++ if ((phybist0 == 0) && (phybist1 == 0x4000) && (phybist2 == 0x1fe0) && ++ (phybist3 == 0) && (phybist4 == 0)) ++ return true; ++ ++ return false; ++} ++ ++static void wlc_phy_bphy_init_nphy(struct brcms_phy *pi) ++{ ++ u16 addr, val; ++ ++ val = 0x1e1f; ++ for (addr = (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT); ++ addr <= (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT_END); addr++) { ++ write_phy_reg(pi, addr, val); ++ if (addr == (NPHY_TO_BPHY_OFF + 0x97)) ++ val = 0x3e3f; ++ else ++ val -= 0x0202; ++ } ++ ++ write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_STEP, 0x668); ++} ++ ++void ++wlc_phy_table_write_nphy(struct brcms_phy *pi, u32 id, u32 len, u32 offset, ++ u32 width, const void *data) ++{ ++ struct phytbl_info tbl; ++ ++ tbl.tbl_id = id; ++ tbl.tbl_len = len; ++ tbl.tbl_offset = offset; ++ tbl.tbl_width = width; ++ tbl.tbl_ptr = data; ++ wlc_phy_write_table_nphy(pi, &tbl); ++} ++ ++void ++wlc_phy_table_read_nphy(struct brcms_phy *pi, u32 id, u32 len, u32 offset, ++ u32 width, void *data) ++{ ++ struct phytbl_info tbl; ++ ++ tbl.tbl_id = id; ++ tbl.tbl_len = len; ++ tbl.tbl_offset = offset; ++ tbl.tbl_width = width; ++ tbl.tbl_ptr = data; ++ wlc_phy_read_table_nphy(pi, &tbl); ++} ++ ++static void ++wlc_phy_static_table_download_nphy(struct brcms_phy *pi) ++{ ++ uint idx; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 16)) { ++ for (idx = 0; idx < mimophytbl_info_sz_rev16; idx++) ++ wlc_phy_write_table_nphy(pi, ++ &mimophytbl_info_rev16[idx]); ++ } else if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ for (idx = 0; idx < mimophytbl_info_sz_rev7; idx++) ++ wlc_phy_write_table_nphy(pi, ++ &mimophytbl_info_rev7[idx]); ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ for (idx = 0; idx < mimophytbl_info_sz_rev3; idx++) ++ wlc_phy_write_table_nphy(pi, ++ &mimophytbl_info_rev3[idx]); ++ } else { ++ for (idx = 0; idx < mimophytbl_info_sz_rev0; idx++) ++ wlc_phy_write_table_nphy(pi, ++ &mimophytbl_info_rev0[idx]); ++ } ++} ++ ++static void wlc_phy_tbl_init_nphy(struct brcms_phy *pi) ++{ ++ uint idx = 0; ++ u8 antswctrllut; ++ ++ if (pi->phy_init_por) ++ wlc_phy_static_table_download_nphy(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ? ++ pi->srom_fem2g.antswctrllut : pi->srom_fem5g. ++ antswctrllut; ++ ++ switch (antswctrllut) { ++ case 0: ++ ++ break; ++ ++ case 1: ++ ++ if (pi->aa2g == 7) ++ wlc_phy_table_write_nphy( ++ pi, ++ NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x21, 8, ++ &ant_sw_ctrl_tbl_rev8_2o3[0]); ++ else ++ wlc_phy_table_write_nphy( ++ pi, ++ NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x21, 8, ++ &ant_sw_ctrl_tbl_rev8 ++ [0]); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x25, 8, ++ &ant_sw_ctrl_tbl_rev8[2]); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x29, 8, ++ &ant_sw_ctrl_tbl_rev8[4]); ++ break; ++ ++ case 2: ++ ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x1, 8, ++ &ant_sw_ctrl_tbl_rev8_2057v7_core0[0]); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x5, 8, ++ &ant_sw_ctrl_tbl_rev8_2057v7_core0[2]); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x9, 8, ++ &ant_sw_ctrl_tbl_rev8_2057v7_core0[4]); ++ ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x21, 8, ++ &ant_sw_ctrl_tbl_rev8_2057v7_core1[0]); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x25, 8, ++ &ant_sw_ctrl_tbl_rev8_2057v7_core1[2]); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 2, 0x29, 8, ++ &ant_sw_ctrl_tbl_rev8_2057v7_core1[4]); ++ break; ++ ++ default: ++ break; ++ } ++ ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ for (idx = 0; idx < mimophytbl_info_sz_rev3_volatile; idx++) { ++ ++ if (idx == ANT_SWCTRL_TBL_REV3_IDX) { ++ antswctrllut = ++ CHSPEC_IS2G(pi->radio_chanspec) ? ++ pi->srom_fem2g.antswctrllut : ++ pi->srom_fem5g.antswctrllut; ++ switch (antswctrllut) { ++ case 0: ++ wlc_phy_write_table_nphy( ++ pi, ++ &mimophytbl_info_rev3_volatile ++ [idx]); ++ break; ++ case 1: ++ wlc_phy_write_table_nphy( ++ pi, ++ &mimophytbl_info_rev3_volatile1 ++ [idx]); ++ break; ++ case 2: ++ wlc_phy_write_table_nphy( ++ pi, ++ &mimophytbl_info_rev3_volatile2 ++ [idx]); ++ break; ++ case 3: ++ wlc_phy_write_table_nphy( ++ pi, ++ &mimophytbl_info_rev3_volatile3 ++ [idx]); ++ break; ++ default: ++ break; ++ } ++ } else { ++ wlc_phy_write_table_nphy( ++ pi, ++ &mimophytbl_info_rev3_volatile[idx]); ++ } ++ } ++ } else { ++ for (idx = 0; idx < mimophytbl_info_sz_rev0_volatile; idx++) ++ wlc_phy_write_table_nphy(pi, ++ &mimophytbl_info_rev0_volatile ++ [idx]); ++ } ++} ++ ++static void ++wlc_phy_write_txmacreg_nphy(struct brcms_phy *pi, u16 holdoff, u16 delay) ++{ ++ write_phy_reg(pi, 0x77, holdoff); ++ write_phy_reg(pi, 0xb4, delay); ++} ++ ++void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs) ++{ ++ u16 holdoff, delay; ++ ++ if (rifs) { ++ ++ holdoff = 0x10; ++ delay = 0x258; ++ } else { ++ ++ holdoff = 0x15; ++ delay = 0x320; ++ } ++ ++ wlc_phy_write_txmacreg_nphy(pi, holdoff, delay); ++ ++ if (pi && pi->sh && (pi->sh->_rifs_phy != rifs)) ++ pi->sh->_rifs_phy = rifs; ++} ++ ++static void wlc_phy_txpwrctrl_config_nphy(struct brcms_phy *pi) ++{ ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ pi->nphy_txpwrctrl = PHY_TPC_HW_ON; ++ pi->phy_5g_pwrgain = true; ++ return; ++ } ++ ++ pi->nphy_txpwrctrl = PHY_TPC_HW_OFF; ++ pi->phy_5g_pwrgain = false; ++ ++ if ((pi->sh->boardflags2 & BFL2_TXPWRCTRL_EN) && ++ NREV_GE(pi->pubpi.phy_rev, 2) && (pi->sh->sromrev >= 4)) ++ pi->nphy_txpwrctrl = PHY_TPC_HW_ON; ++ else if ((pi->sh->sromrev >= 4) ++ && (pi->sh->boardflags2 & BFL2_5G_PWRGAIN)) ++ pi->phy_5g_pwrgain = true; ++} ++ ++static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi) ++{ ++ u16 bw40po, cddpo, stbcpo, bwduppo; ++ uint band_num; ++ struct phy_shim_info *shim = pi->sh->physhim; ++ ++ if (pi->sh->sromrev >= 9) ++ return; ++ ++ bw40po = (u16) wlapi_getintvar(shim, BRCMS_SROM_BW40PO); ++ pi->bw402gpo = bw40po & 0xf; ++ pi->bw405gpo = (bw40po & 0xf0) >> 4; ++ pi->bw405glpo = (bw40po & 0xf00) >> 8; ++ pi->bw405ghpo = (bw40po & 0xf000) >> 12; ++ ++ cddpo = (u16) wlapi_getintvar(shim, BRCMS_SROM_CDDPO); ++ pi->cdd2gpo = cddpo & 0xf; ++ pi->cdd5gpo = (cddpo & 0xf0) >> 4; ++ pi->cdd5glpo = (cddpo & 0xf00) >> 8; ++ pi->cdd5ghpo = (cddpo & 0xf000) >> 12; ++ ++ stbcpo = (u16) wlapi_getintvar(shim, BRCMS_SROM_STBCPO); ++ pi->stbc2gpo = stbcpo & 0xf; ++ pi->stbc5gpo = (stbcpo & 0xf0) >> 4; ++ pi->stbc5glpo = (stbcpo & 0xf00) >> 8; ++ pi->stbc5ghpo = (stbcpo & 0xf000) >> 12; ++ ++ bwduppo = (u16) wlapi_getintvar(shim, BRCMS_SROM_BWDUPPO); ++ pi->bwdup2gpo = bwduppo & 0xf; ++ pi->bwdup5gpo = (bwduppo & 0xf0) >> 4; ++ pi->bwdup5glpo = (bwduppo & 0xf00) >> 8; ++ pi->bwdup5ghpo = (bwduppo & 0xf000) >> 12; ++ ++ for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); ++ band_num++) { ++ switch (band_num) { ++ case 0: ++ ++ pi->nphy_txpid2g[PHY_CORE_0] = ++ (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TXPID2GA0); ++ pi->nphy_txpid2g[PHY_CORE_1] = ++ (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TXPID2GA1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g = ++ (s8) wlapi_getintvar(shim, ++ BRCMS_SROM_MAXP2GA0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g = ++ (s8) wlapi_getintvar(shim, ++ BRCMS_SROM_MAXP2GA1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA2GW0A0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA2GW0A1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA2GW1A0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA2GW1A1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA2GW2A0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA2GW2A1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g = ++ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT2GA0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g = ++ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT2GA1); ++ ++ pi->cck2gpo = (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_CCK2GPO); ++ ++ pi->ofdm2gpo = ++ (u32) wlapi_getintvar(shim, ++ BRCMS_SROM_OFDM2GPO); ++ ++ pi->mcs2gpo[0] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO0); ++ pi->mcs2gpo[1] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO1); ++ pi->mcs2gpo[2] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO2); ++ pi->mcs2gpo[3] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO3); ++ pi->mcs2gpo[4] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO4); ++ pi->mcs2gpo[5] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO5); ++ pi->mcs2gpo[6] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO6); ++ pi->mcs2gpo[7] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS2GPO7); ++ break; ++ case 1: ++ ++ pi->nphy_txpid5g[PHY_CORE_0] = ++ (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TXPID5GA0); ++ pi->nphy_txpid5g[PHY_CORE_1] = ++ (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TXPID5GA1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm = ++ (s8) wlapi_getintvar(shim, BRCMS_SROM_MAXP5GA0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm = ++ (s8) wlapi_getintvar(shim, ++ BRCMS_SROM_MAXP5GA1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GW0A0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GW0A1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GW1A0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GW1A1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GW2A0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GW2A1); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm = ++ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT5GA0); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm = ++ (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT5GA1); ++ ++ pi->ofdm5gpo = ++ (u32) wlapi_getintvar(shim, ++ BRCMS_SROM_OFDM5GPO); ++ ++ pi->mcs5gpo[0] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GPO0); ++ pi->mcs5gpo[1] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GPO1); ++ pi->mcs5gpo[2] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GPO2); ++ pi->mcs5gpo[3] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GPO3); ++ pi->mcs5gpo[4] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GPO4); ++ pi->mcs5gpo[5] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GPO5); ++ pi->mcs5gpo[6] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GPO6); ++ pi->mcs5gpo[7] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GPO7); ++ break; ++ case 2: ++ ++ pi->nphy_txpid5gl[0] = ++ (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TXPID5GLA0); ++ pi->nphy_txpid5gl[1] = ++ (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TXPID5GLA1); ++ pi->nphy_pwrctrl_info[0].max_pwr_5gl = ++ (s8) wlapi_getintvar(shim, ++ BRCMS_SROM_MAXP5GLA0); ++ pi->nphy_pwrctrl_info[1].max_pwr_5gl = ++ (s8) wlapi_getintvar(shim, ++ BRCMS_SROM_MAXP5GLA1); ++ pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GLW0A0); ++ pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GLW0A1); ++ pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GLW1A0); ++ pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GLW1A1); ++ pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GLW2A0); ++ pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GLW2A1); ++ pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0; ++ pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0; ++ ++ pi->ofdm5glpo = ++ (u32) wlapi_getintvar(shim, ++ BRCMS_SROM_OFDM5GLPO); ++ ++ pi->mcs5glpo[0] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GLPO0); ++ pi->mcs5glpo[1] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GLPO1); ++ pi->mcs5glpo[2] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GLPO2); ++ pi->mcs5glpo[3] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GLPO3); ++ pi->mcs5glpo[4] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GLPO4); ++ pi->mcs5glpo[5] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GLPO5); ++ pi->mcs5glpo[6] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GLPO6); ++ pi->mcs5glpo[7] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GLPO7); ++ break; ++ case 3: ++ ++ pi->nphy_txpid5gh[0] = ++ (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TXPID5GHA0); ++ pi->nphy_txpid5gh[1] = ++ (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TXPID5GHA1); ++ pi->nphy_pwrctrl_info[0].max_pwr_5gh = ++ (s8) wlapi_getintvar(shim, ++ BRCMS_SROM_MAXP5GHA0); ++ pi->nphy_pwrctrl_info[1].max_pwr_5gh = ++ (s8) wlapi_getintvar(shim, ++ BRCMS_SROM_MAXP5GHA1); ++ pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GHW0A0); ++ pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GHW0A1); ++ pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GHW1A0); ++ pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GHW1A1); ++ pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GHW2A0); ++ pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 = ++ (s16) wlapi_getintvar(shim, ++ BRCMS_SROM_PA5GHW2A1); ++ pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0; ++ pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0; ++ ++ pi->ofdm5ghpo = ++ (u32) wlapi_getintvar(shim, ++ BRCMS_SROM_OFDM5GHPO); ++ ++ pi->mcs5ghpo[0] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GHPO0); ++ pi->mcs5ghpo[1] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GHPO1); ++ pi->mcs5ghpo[2] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GHPO2); ++ pi->mcs5ghpo[3] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GHPO3); ++ pi->mcs5ghpo[4] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GHPO4); ++ pi->mcs5ghpo[5] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GHPO5); ++ pi->mcs5ghpo[6] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GHPO6); ++ pi->mcs5ghpo[7] = ++ (u16) wlapi_getintvar(shim, ++ BRCMS_SROM_MCS5GHPO7); ++ break; ++ } ++ } ++ ++ wlc_phy_txpwr_apply_nphy(pi); ++} ++ ++static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi) ++{ ++ struct phy_shim_info *shim = pi->sh->physhim; ++ ++ pi->antswitch = (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWITCH); ++ pi->aa2g = (u8) wlapi_getintvar(shim, BRCMS_SROM_AA2G); ++ pi->aa5g = (u8) wlapi_getintvar(shim, BRCMS_SROM_AA5G); ++ ++ pi->srom_fem2g.tssipos = (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TSSIPOS2G); ++ pi->srom_fem2g.extpagain = (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_EXTPAGAIN2G); ++ pi->srom_fem2g.pdetrange = (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_PDETRANGE2G); ++ pi->srom_fem2g.triso = (u8) wlapi_getintvar(shim, BRCMS_SROM_TRISO2G); ++ pi->srom_fem2g.antswctrllut = ++ (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL2G); ++ ++ pi->srom_fem5g.tssipos = (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_TSSIPOS5G); ++ pi->srom_fem5g.extpagain = (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_EXTPAGAIN5G); ++ pi->srom_fem5g.pdetrange = (u8) wlapi_getintvar(shim, ++ BRCMS_SROM_PDETRANGE5G); ++ pi->srom_fem5g.triso = (u8) wlapi_getintvar(shim, BRCMS_SROM_TRISO5G); ++ if (wlapi_getvar(shim, BRCMS_SROM_ANTSWCTL5G)) ++ pi->srom_fem5g.antswctrllut = ++ (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL5G); ++ else ++ pi->srom_fem5g.antswctrllut = ++ (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL2G); ++ ++ wlc_phy_txpower_ipa_upd(pi); ++ ++ pi->phy_txcore_disable_temp = ++ (s16) wlapi_getintvar(shim, BRCMS_SROM_TEMPTHRESH); ++ if (pi->phy_txcore_disable_temp == 0) ++ pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP; ++ ++ pi->phy_tempsense_offset = (s8) wlapi_getintvar(shim, ++ BRCMS_SROM_TEMPOFFSET); ++ if (pi->phy_tempsense_offset != 0) { ++ if (pi->phy_tempsense_offset > ++ (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET)) ++ pi->phy_tempsense_offset = NPHY_SROM_MAXTEMPOFFSET; ++ else if (pi->phy_tempsense_offset < (NPHY_SROM_TEMPSHIFT + ++ NPHY_SROM_MINTEMPOFFSET)) ++ pi->phy_tempsense_offset = NPHY_SROM_MINTEMPOFFSET; ++ else ++ pi->phy_tempsense_offset -= NPHY_SROM_TEMPSHIFT; ++ } ++ ++ pi->phy_txcore_enable_temp = ++ pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP; ++ ++ pi->phycal_tempdelta = ++ (u8) wlapi_getintvar(shim, BRCMS_SROM_PHYCAL_TEMPDELTA); ++ if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA) ++ pi->phycal_tempdelta = 0; ++ ++ wlc_phy_txpwr_srom_read_ppr_nphy(pi); ++ ++ return true; ++} ++ ++bool wlc_phy_attach_nphy(struct brcms_phy *pi) ++{ ++ uint i; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 6)) ++ pi->phyhang_avoid = true; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) { ++ pi->nphy_gband_spurwar_en = true; ++ if (pi->sh->boardflags2 & BFL2_SPUR_WAR) ++ pi->nphy_aband_spurwar_en = true; ++ } ++ if (NREV_GE(pi->pubpi.phy_rev, 6) && NREV_LT(pi->pubpi.phy_rev, 7)) { ++ if (pi->sh->boardflags2 & BFL2_2G_SPUR_WAR) ++ pi->nphy_gband_spurwar2_en = true; ++ } ++ ++ pi->n_preamble_override = AUTO; ++ if (NREV_IS(pi->pubpi.phy_rev, 3) || NREV_IS(pi->pubpi.phy_rev, 4)) ++ pi->n_preamble_override = BRCMS_N_PREAMBLE_MIXEDMODE; ++ ++ pi->nphy_txrx_chain = AUTO; ++ pi->phy_scraminit = AUTO; ++ ++ pi->nphy_rxcalparams = 0x010100B5; ++ ++ pi->nphy_perical = PHY_PERICAL_MPHASE; ++ pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE; ++ pi->mphase_txcal_numcmds = MPHASE_TXCAL_NUMCMDS; ++ ++ pi->nphy_gain_boost = true; ++ pi->nphy_elna_gain_config = false; ++ pi->radio_is_on = false; ++ ++ for (i = 0; i < pi->pubpi.phy_corenum; i++) ++ pi->nphy_txpwrindex[i].index = AUTO; ++ ++ wlc_phy_txpwrctrl_config_nphy(pi); ++ if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON) ++ pi->hwpwrctrl_capable = true; ++ ++ pi->pi_fptr.init = wlc_phy_init_nphy; ++ pi->pi_fptr.calinit = wlc_phy_cal_init_nphy; ++ pi->pi_fptr.chanset = wlc_phy_chanspec_set_nphy; ++ pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_nphy; ++ ++ if (!wlc_phy_txpwr_srom_read_nphy(pi)) ++ return false; ++ ++ return true; ++} ++ ++static s32 get_rf_pwr_offset(struct brcms_phy *pi, s16 pga_gn, s16 pad_gn) ++{ ++ s32 rfpwr_offset = 0; ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if ((pi->pubpi.radiorev == 3) || ++ (pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) ++ rfpwr_offset = (s16) ++ nphy_papd_padgain_dlt_2g_2057rev3n4 ++ [pad_gn]; ++ else if (pi->pubpi.radiorev == 5) ++ rfpwr_offset = (s16) ++ nphy_papd_padgain_dlt_2g_2057rev5 ++ [pad_gn]; ++ else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == ++ 8)) ++ rfpwr_offset = (s16) ++ nphy_papd_padgain_dlt_2g_2057rev7 ++ [pad_gn]; ++ } else { ++ if ((pi->pubpi.radiorev == 3) || ++ (pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) ++ rfpwr_offset = (s16) ++ nphy_papd_pgagain_dlt_5g_2057 ++ [pga_gn]; ++ else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == ++ 8)) ++ rfpwr_offset = (s16) ++ nphy_papd_pgagain_dlt_5g_2057rev7 ++ [pga_gn]; ++ } ++ return rfpwr_offset; ++} ++ ++static void wlc_phy_update_mimoconfig_nphy(struct brcms_phy *pi, s32 preamble) ++{ ++ bool gf_preamble = false; ++ u16 val; ++ ++ if (preamble == BRCMS_N_PREAMBLE_GF) ++ gf_preamble = true; ++ ++ val = read_phy_reg(pi, 0xed); ++ ++ val |= RX_GF_MM_AUTO; ++ val &= ~RX_GF_OR_MM; ++ if (gf_preamble) ++ val |= RX_GF_OR_MM; ++ ++ write_phy_reg(pi, 0xed, val); ++} ++ ++static void wlc_phy_ipa_set_tx_digi_filts_nphy(struct brcms_phy *pi) ++{ ++ int j, type; ++ u16 addr_offset[] = { 0x186, 0x195, 0x2c5}; ++ ++ for (type = 0; type < 3; type++) { ++ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, addr_offset[type] + j, ++ NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]); ++ } ++ ++ if (pi->bw == WL_CHANSPEC_BW_40) { ++ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, 0x186 + j, ++ NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]); ++ } else { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, 0x186 + j, ++ NPHY_IPA_REV4_txdigi_filtcoeffs[5][j]); ++ } ++ ++ if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) { ++ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, 0x2c5 + j, ++ NPHY_IPA_REV4_txdigi_filtcoeffs[6][j]); ++ } ++ } ++} ++ ++static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi) ++{ ++ int j; ++ ++ if (pi->bw == WL_CHANSPEC_BW_40) { ++ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, 0x195 + j, ++ NPHY_IPA_REV4_txdigi_filtcoeffs[4][j]); ++ } else { ++ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, 0x186 + j, ++ NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]); ++ } ++} ++ ++static void ++wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *events, u8 *dlys, ++ u8 len) ++{ ++ u32 t1_offset, t2_offset; ++ u8 ctr; ++ u8 end_event = ++ NREV_GE(pi->pubpi.phy_rev, ++ 3) ? NPHY_REV3_RFSEQ_CMD_END : NPHY_RFSEQ_CMD_END; ++ u8 end_dly = 1; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ t1_offset = cmd << 4; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t1_offset, 8, ++ events); ++ t2_offset = t1_offset + 0x080; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t2_offset, 8, ++ dlys); ++ ++ for (ctr = len; ctr < 16; ctr++) { ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, ++ t1_offset + ctr, 8, &end_event); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, ++ t2_offset + ctr, 8, &end_dly); ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static u16 wlc_phy_read_lpf_bw_ctl_nphy(struct brcms_phy *pi, u16 offset) ++{ ++ u16 lpf_bw_ctl_val = 0; ++ u16 rx2tx_lpf_rc_lut_offset = 0; ++ ++ if (offset == 0) { ++ if (CHSPEC_IS40(pi->radio_chanspec)) ++ rx2tx_lpf_rc_lut_offset = 0x159; ++ else ++ rx2tx_lpf_rc_lut_offset = 0x154; ++ } else { ++ rx2tx_lpf_rc_lut_offset = offset; ++ } ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, ++ (u32) rx2tx_lpf_rc_lut_offset, 16, ++ &lpf_bw_ctl_val); ++ ++ lpf_bw_ctl_val = lpf_bw_ctl_val & 0x7; ++ ++ return lpf_bw_ctl_val; ++} ++ ++static void ++wlc_phy_rfctrl_override_nphy_rev7(struct brcms_phy *pi, u16 field, u16 value, ++ u8 core_mask, u8 off, u8 override_id) ++{ ++ u8 core_num; ++ u16 addr = 0, en_addr = 0, val_addr = 0, en_mask = 0, val_mask = 0; ++ u8 val_shift = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ en_mask = field; ++ for (core_num = 0; core_num < 2; core_num++) { ++ if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID0) { ++ ++ switch (field) { ++ case (0x1 << 2): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : ++ 0x7d; ++ val_mask = (0x1 << 1); ++ val_shift = 1; ++ break; ++ case (0x1 << 3): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : ++ 0x7d; ++ val_mask = (0x1 << 2); ++ val_shift = 2; ++ break; ++ case (0x1 << 4): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : ++ 0x7d; ++ val_mask = (0x1 << 4); ++ val_shift = 4; ++ break; ++ case (0x1 << 5): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : ++ 0x7d; ++ val_mask = (0x1 << 5); ++ val_shift = 5; ++ break; ++ case (0x1 << 6): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : ++ 0x7d; ++ val_mask = (0x1 << 6); ++ val_shift = 6; ++ break; ++ case (0x1 << 7): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : ++ 0x7d; ++ val_mask = (0x1 << 7); ++ val_shift = 7; ++ break; ++ case (0x1 << 10): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0xf8 : ++ 0xfa; ++ val_mask = (0x7 << 4); ++ val_shift = 4; ++ break; ++ case (0x1 << 11): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7b : ++ 0x7e; ++ val_mask = (0xffff << 0); ++ val_shift = 0; ++ break; ++ case (0x1 << 12): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7c : ++ 0x7f; ++ val_mask = (0xffff << 0); ++ val_shift = 0; ++ break; ++ case (0x3 << 13): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x348 : ++ 0x349; ++ val_mask = (0xff << 0); ++ val_shift = 0; ++ break; ++ case (0x1 << 13): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x348 : ++ 0x349; ++ val_mask = (0xf << 0); ++ val_shift = 0; ++ break; ++ default: ++ addr = 0xffff; ++ break; ++ } ++ } else if (override_id == ++ NPHY_REV7_RFCTRLOVERRIDE_ID1) { ++ ++ switch (field) { ++ case (0x1 << 1): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 1); ++ val_shift = 1; ++ break; ++ case (0x1 << 3): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 3); ++ val_shift = 3; ++ break; ++ case (0x1 << 5): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 5); ++ val_shift = 5; ++ break; ++ case (0x1 << 4): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 4); ++ val_shift = 4; ++ break; ++ case (0x1 << 2): ++ ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 2); ++ val_shift = 2; ++ break; ++ case (0x1 << 7): ++ ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x7 << 8); ++ val_shift = 8; ++ break; ++ case (0x1 << 11): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 14); ++ val_shift = 14; ++ break; ++ case (0x1 << 10): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 13); ++ val_shift = 13; ++ break; ++ case (0x1 << 9): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 12); ++ val_shift = 12; ++ break; ++ case (0x1 << 8): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 11); ++ val_shift = 11; ++ break; ++ case (0x1 << 6): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 6); ++ val_shift = 6; ++ break; ++ case (0x1 << 0): ++ en_addr = (core_num == 0) ? 0x342 : ++ 0x343; ++ val_addr = (core_num == 0) ? 0x340 : ++ 0x341; ++ val_mask = (0x1 << 0); ++ val_shift = 0; ++ break; ++ default: ++ addr = 0xffff; ++ break; ++ } ++ } else if (override_id == ++ NPHY_REV7_RFCTRLOVERRIDE_ID2) { ++ ++ switch (field) { ++ case (0x1 << 3): ++ en_addr = (core_num == 0) ? 0x346 : ++ 0x347; ++ val_addr = (core_num == 0) ? 0x344 : ++ 0x345; ++ val_mask = (0x1 << 3); ++ val_shift = 3; ++ break; ++ case (0x1 << 1): ++ en_addr = (core_num == 0) ? 0x346 : ++ 0x347; ++ val_addr = (core_num == 0) ? 0x344 : ++ 0x345; ++ val_mask = (0x1 << 1); ++ val_shift = 1; ++ break; ++ case (0x1 << 0): ++ en_addr = (core_num == 0) ? 0x346 : ++ 0x347; ++ val_addr = (core_num == 0) ? 0x344 : ++ 0x345; ++ val_mask = (0x1 << 0); ++ val_shift = 0; ++ break; ++ case (0x1 << 2): ++ en_addr = (core_num == 0) ? 0x346 : ++ 0x347; ++ val_addr = (core_num == 0) ? 0x344 : ++ 0x345; ++ val_mask = (0x1 << 2); ++ val_shift = 2; ++ break; ++ case (0x1 << 4): ++ en_addr = (core_num == 0) ? 0x346 : ++ 0x347; ++ val_addr = (core_num == 0) ? 0x344 : ++ 0x345; ++ val_mask = (0x1 << 4); ++ val_shift = 4; ++ break; ++ default: ++ addr = 0xffff; ++ break; ++ } ++ } ++ ++ if (off) { ++ and_phy_reg(pi, en_addr, ~en_mask); ++ and_phy_reg(pi, val_addr, ~val_mask); ++ } else { ++ ++ if ((core_mask == 0) ++ || (core_mask & (1 << core_num))) { ++ or_phy_reg(pi, en_addr, en_mask); ++ ++ if (addr != 0xffff) ++ mod_phy_reg(pi, val_addr, ++ val_mask, ++ (value << ++ val_shift)); ++ } ++ } ++ } ++ } ++} ++ ++static void wlc_phy_adjust_lnagaintbl_nphy(struct brcms_phy *pi) ++{ ++ uint core; ++ int ctr; ++ s16 gain_delta[2]; ++ u8 curr_channel; ++ u16 minmax_gain[2]; ++ u16 regval[4]; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ if (pi->nphy_gain_boost) { ++ if ((CHSPEC_IS2G(pi->radio_chanspec))) { ++ ++ gain_delta[0] = 6; ++ gain_delta[1] = 6; ++ } else { ++ ++ curr_channel = CHSPEC_CHANNEL(pi->radio_chanspec); ++ gain_delta[0] = ++ (s16) ++ PHY_HW_ROUND(((nphy_lnagain_est0[0] * ++ curr_channel) + ++ nphy_lnagain_est0[1]), 13); ++ gain_delta[1] = ++ (s16) ++ PHY_HW_ROUND(((nphy_lnagain_est1[0] * ++ curr_channel) + ++ nphy_lnagain_est1[1]), 13); ++ } ++ } else { ++ ++ gain_delta[0] = 0; ++ gain_delta[1] = 0; ++ } ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ if (pi->nphy_elna_gain_config) { ++ ++ regval[0] = nphy_def_lnagains[2] + gain_delta[core]; ++ regval[1] = nphy_def_lnagains[3] + gain_delta[core]; ++ regval[2] = nphy_def_lnagains[3] + gain_delta[core]; ++ regval[3] = nphy_def_lnagains[3] + gain_delta[core]; ++ } else { ++ for (ctr = 0; ctr < 4; ctr++) ++ regval[ctr] = ++ nphy_def_lnagains[ctr] + ++ gain_delta[core]; ++ } ++ wlc_phy_table_write_nphy(pi, core, 4, 8, 16, regval); ++ ++ minmax_gain[core] = ++ (u16) (nphy_def_lnagains[2] + gain_delta[core] + 4); ++ } ++ ++ mod_phy_reg(pi, 0x1e, (0xff << 0), (minmax_gain[0] << 0)); ++ mod_phy_reg(pi, 0x34, (0xff << 0), (minmax_gain[1] << 0)); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static void ++wlc_phy_war_force_trsw_to_R_cliplo_nphy(struct brcms_phy *pi, u8 core) ++{ ++ if (core == PHY_CORE_0) { ++ write_phy_reg(pi, 0x38, 0x4); ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ write_phy_reg(pi, 0x37, 0x0060); ++ else ++ write_phy_reg(pi, 0x37, 0x1080); ++ } else if (core == PHY_CORE_1) { ++ write_phy_reg(pi, 0x2ae, 0x4); ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ write_phy_reg(pi, 0x2ad, 0x0060); ++ else ++ write_phy_reg(pi, 0x2ad, 0x1080); ++ } ++} ++ ++static void wlc_phy_war_txchain_upd_nphy(struct brcms_phy *pi, u8 txchain) ++{ ++ u8 txchain0, txchain1; ++ ++ txchain0 = txchain & 0x1; ++ txchain1 = (txchain & 0x2) >> 1; ++ if (!txchain0) ++ wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0); ++ ++ if (!txchain1) ++ wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1); ++} ++ ++static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi) ++{ ++ s8 lna1_gain_db[] = { 8, 13, 17, 22 }; ++ s8 lna2_gain_db[] = { -2, 7, 11, 15 }; ++ s8 tia_gain_db[] = { -4, -1, 2, 5, 5, 5, 5, 5, 5, 5 }; ++ s8 tia_gainbits[] = { ++ 0x0, 0x01, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }; ++ ++ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13)); ++ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13)); ++ ++ mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0)); ++ ++ mod_phy_reg(pi, 0x283, (0xff << 0), (0x3c << 0)); ++ mod_phy_reg(pi, 0x280, (0xff << 0), (0x3c << 0)); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x8, 8, ++ lna1_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x8, 8, ++ lna1_gain_db); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, 8, ++ lna2_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, 8, ++ lna2_gain_db); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8, ++ tia_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8, ++ tia_gain_db); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8, ++ tia_gainbits); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8, ++ tia_gainbits); ++ ++ write_phy_reg(pi, 0x37, 0x74); ++ write_phy_reg(pi, 0x2ad, 0x74); ++ write_phy_reg(pi, 0x38, 0x18); ++ write_phy_reg(pi, 0x2ae, 0x18); ++ ++ write_phy_reg(pi, 0x2b, 0xe8); ++ write_phy_reg(pi, 0x41, 0xe8); ++ ++ if (CHSPEC_IS20(pi->radio_chanspec)) { ++ ++ mod_phy_reg(pi, 0x300, (0x3f << 0), (0x12 << 0)); ++ mod_phy_reg(pi, 0x301, (0x3f << 0), (0x12 << 0)); ++ } else { ++ ++ mod_phy_reg(pi, 0x300, (0x3f << 0), (0x10 << 0)); ++ mod_phy_reg(pi, 0x301, (0x3f << 0), (0x10 << 0)); ++ } ++} ++ ++static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) ++{ ++ u16 currband; ++ s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 }; ++ s8 *lna1_gain_db = NULL; ++ s8 *lna1_gain_db_2 = NULL; ++ s8 *lna2_gain_db = NULL; ++ s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 }; ++ s8 *tia_gain_db; ++ s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 }; ++ s8 *tia_gainbits; ++ u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f }; ++ u16 *rfseq_init_gain; ++ u16 init_gaincode; ++ u16 clip1hi_gaincode; ++ u16 clip1md_gaincode = 0; ++ u16 clip1md_gaincode_B; ++ u16 clip1lo_gaincode; ++ u16 clip1lo_gaincode_B; ++ u8 crsminl_th = 0; ++ u8 crsminu_th; ++ u16 nbclip_th = 0; ++ u8 w1clip_th; ++ u16 freq; ++ s8 nvar_baseline_offset0 = 0, nvar_baseline_offset1 = 0; ++ u8 chg_nbclip_th = 0; ++ ++ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13)); ++ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13)); ++ ++ currband = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; ++ if (currband == 0) { ++ ++ lna1_gain_db = lna1G_gain_db_rev7; ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8, ++ lna1_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8, ++ lna1_gain_db); ++ ++ mod_phy_reg(pi, 0x283, (0xff << 0), (0x40 << 0)); ++ ++ if (CHSPEC_IS40(pi->radio_chanspec)) { ++ mod_phy_reg(pi, 0x280, (0xff << 0), (0x3e << 0)); ++ mod_phy_reg(pi, 0x283, (0xff << 0), (0x3e << 0)); ++ } ++ ++ mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0)); ++ ++ if (CHSPEC_IS20(pi->radio_chanspec)) { ++ mod_phy_reg(pi, 0x300, (0x3f << 0), (13 << 0)); ++ mod_phy_reg(pi, 0x301, (0x3f << 0), (13 << 0)); ++ } ++ } else { ++ ++ init_gaincode = 0x9e; ++ clip1hi_gaincode = 0x9e; ++ clip1md_gaincode_B = 0x24; ++ clip1lo_gaincode = 0x8a; ++ clip1lo_gaincode_B = 8; ++ rfseq_init_gain = rfseqA_init_gain_rev7; ++ ++ tia_gain_db = tiaA_gain_db_rev7; ++ tia_gainbits = tiaA_gainbits_rev7; ++ ++ freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec)); ++ if (CHSPEC_IS20(pi->radio_chanspec)) { ++ ++ w1clip_th = 25; ++ clip1md_gaincode = 0x82; ++ ++ if ((freq <= 5080) || (freq == 5825)) { ++ ++ s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 }; ++ s8 lna1A_gain_db_2_rev7[] = { ++ 11, 17, 22, 25}; ++ s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; ++ ++ crsminu_th = 0x3e; ++ lna1_gain_db = lna1A_gain_db_rev7; ++ lna1_gain_db_2 = lna1A_gain_db_2_rev7; ++ lna2_gain_db = lna2A_gain_db_rev7; ++ } else if ((freq >= 5500) && (freq <= 5700)) { ++ ++ s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 }; ++ s8 lna1A_gain_db_2_rev7[] = { ++ 12, 18, 22, 26}; ++ s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 }; ++ ++ crsminu_th = 0x45; ++ clip1md_gaincode_B = 0x14; ++ nbclip_th = 0xff; ++ chg_nbclip_th = 1; ++ lna1_gain_db = lna1A_gain_db_rev7; ++ lna1_gain_db_2 = lna1A_gain_db_2_rev7; ++ lna2_gain_db = lna2A_gain_db_rev7; ++ } else { ++ ++ s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 }; ++ s8 lna1A_gain_db_2_rev7[] = { ++ 12, 18, 22, 26}; ++ s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; ++ ++ crsminu_th = 0x41; ++ lna1_gain_db = lna1A_gain_db_rev7; ++ lna1_gain_db_2 = lna1A_gain_db_2_rev7; ++ lna2_gain_db = lna2A_gain_db_rev7; ++ } ++ ++ if (freq <= 4920) { ++ nvar_baseline_offset0 = 5; ++ nvar_baseline_offset1 = 5; ++ } else if ((freq > 4920) && (freq <= 5320)) { ++ nvar_baseline_offset0 = 3; ++ nvar_baseline_offset1 = 5; ++ } else if ((freq > 5320) && (freq <= 5700)) { ++ nvar_baseline_offset0 = 3; ++ nvar_baseline_offset1 = 2; ++ } else { ++ nvar_baseline_offset0 = 4; ++ nvar_baseline_offset1 = 0; ++ } ++ } else { ++ ++ crsminu_th = 0x3a; ++ crsminl_th = 0x3a; ++ w1clip_th = 20; ++ ++ if ((freq >= 4920) && (freq <= 5320)) { ++ nvar_baseline_offset0 = 4; ++ nvar_baseline_offset1 = 5; ++ } else if ((freq > 5320) && (freq <= 5550)) { ++ nvar_baseline_offset0 = 4; ++ nvar_baseline_offset1 = 2; ++ } else { ++ nvar_baseline_offset0 = 5; ++ nvar_baseline_offset1 = 3; ++ } ++ } ++ ++ write_phy_reg(pi, 0x20, init_gaincode); ++ write_phy_reg(pi, 0x2a7, init_gaincode); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, ++ pi->pubpi.phy_corenum, 0x106, 16, ++ rfseq_init_gain); ++ ++ write_phy_reg(pi, 0x22, clip1hi_gaincode); ++ write_phy_reg(pi, 0x2a9, clip1hi_gaincode); ++ ++ write_phy_reg(pi, 0x36, clip1md_gaincode_B); ++ write_phy_reg(pi, 0x2ac, clip1md_gaincode_B); ++ ++ write_phy_reg(pi, 0x37, clip1lo_gaincode); ++ write_phy_reg(pi, 0x2ad, clip1lo_gaincode); ++ write_phy_reg(pi, 0x38, clip1lo_gaincode_B); ++ write_phy_reg(pi, 0x2ae, clip1lo_gaincode_B); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8, ++ tia_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8, ++ tia_gain_db); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8, ++ tia_gainbits); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8, ++ tia_gainbits); ++ ++ mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0)); ++ ++ if (chg_nbclip_th == 1) { ++ write_phy_reg(pi, 0x2b, nbclip_th); ++ write_phy_reg(pi, 0x41, nbclip_th); ++ } ++ ++ mod_phy_reg(pi, 0x300, (0x3f << 0), (w1clip_th << 0)); ++ mod_phy_reg(pi, 0x301, (0x3f << 0), (w1clip_th << 0)); ++ ++ mod_phy_reg(pi, 0x2e4, ++ (0x3f << 0), (nvar_baseline_offset0 << 0)); ++ ++ mod_phy_reg(pi, 0x2e4, ++ (0x3f << 6), (nvar_baseline_offset1 << 6)); ++ ++ if (CHSPEC_IS20(pi->radio_chanspec)) { ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8, ++ lna1_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8, ++ lna1_gain_db_2); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, ++ 8, lna2_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, ++ 8, lna2_gain_db); ++ ++ write_phy_reg(pi, 0x24, clip1md_gaincode); ++ write_phy_reg(pi, 0x2ab, clip1md_gaincode); ++ } else { ++ mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0)); ++ } ++ } ++} ++ ++static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) ++{ ++ u16 w1th, hpf_code, currband; ++ int ctr; ++ u8 rfseq_updategainu_events[] = { ++ NPHY_RFSEQ_CMD_RX_GAIN, ++ NPHY_RFSEQ_CMD_CLR_HIQ_DIS, ++ NPHY_RFSEQ_CMD_SET_HPF_BW ++ }; ++ u8 rfseq_updategainu_dlys[] = { 10, 30, 1 }; ++ s8 lna1G_gain_db[] = { 7, 11, 16, 23 }; ++ s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 }; ++ s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 }; ++ s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 }; ++ s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 }; ++ s8 lna1A_gain_db[] = { 7, 11, 17, 23 }; ++ s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 }; ++ s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 }; ++ s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 }; ++ s8 *lna1_gain_db = NULL; ++ s8 lna2G_gain_db[] = { -5, 6, 10, 14 }; ++ s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 }; ++ s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 }; ++ s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 }; ++ s8 lna2A_gain_db[] = { -6, 2, 6, 10 }; ++ s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 }; ++ s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 }; ++ s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 }; ++ s8 *lna2_gain_db = NULL; ++ s8 tiaG_gain_db[] = { ++ 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A }; ++ s8 tiaA_gain_db[] = { ++ 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 }; ++ s8 tiaA_gain_db_rev4[] = { ++ 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; ++ s8 tiaA_gain_db_rev5[] = { ++ 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; ++ s8 tiaA_gain_db_rev6[] = { ++ 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; ++ s8 *tia_gain_db; ++ s8 tiaG_gainbits[] = { ++ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }; ++ s8 tiaA_gainbits[] = { ++ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 }; ++ s8 tiaA_gainbits_rev4[] = { ++ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; ++ s8 tiaA_gainbits_rev5[] = { ++ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; ++ s8 tiaA_gainbits_rev6[] = { ++ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; ++ s8 *tia_gainbits; ++ s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 }; ++ s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 }; ++ u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f }; ++ u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f }; ++ u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f }; ++ u16 rfseqG_init_gain_rev5_elna[] = { ++ 0x013f, 0x013f, 0x013f, 0x013f }; ++ u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f }; ++ u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f }; ++ u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f }; ++ u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f }; ++ u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f }; ++ u16 rfseqA_init_gain_rev4_elna[] = { ++ 0x314f, 0x314f, 0x314f, 0x314f }; ++ u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f }; ++ u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f }; ++ u16 *rfseq_init_gain; ++ u16 initG_gaincode = 0x627e; ++ u16 initG_gaincode_rev4 = 0x527e; ++ u16 initG_gaincode_rev5 = 0x427e; ++ u16 initG_gaincode_rev5_elna = 0x027e; ++ u16 initG_gaincode_rev6 = 0x527e; ++ u16 initG_gaincode_rev6_224B0 = 0x427e; ++ u16 initG_gaincode_rev6_elna = 0x127e; ++ u16 initA_gaincode = 0x52de; ++ u16 initA_gaincode_rev4 = 0x629e; ++ u16 initA_gaincode_rev4_elna = 0x329e; ++ u16 initA_gaincode_rev5 = 0x729e; ++ u16 initA_gaincode_rev6 = 0x729e; ++ u16 init_gaincode; ++ u16 clip1hiG_gaincode = 0x107e; ++ u16 clip1hiG_gaincode_rev4 = 0x007e; ++ u16 clip1hiG_gaincode_rev5 = 0x1076; ++ u16 clip1hiG_gaincode_rev6 = 0x007e; ++ u16 clip1hiA_gaincode = 0x00de; ++ u16 clip1hiA_gaincode_rev4 = 0x029e; ++ u16 clip1hiA_gaincode_rev5 = 0x029e; ++ u16 clip1hiA_gaincode_rev6 = 0x029e; ++ u16 clip1hi_gaincode; ++ u16 clip1mdG_gaincode = 0x0066; ++ u16 clip1mdA_gaincode = 0x00ca; ++ u16 clip1mdA_gaincode_rev4 = 0x1084; ++ u16 clip1mdA_gaincode_rev5 = 0x2084; ++ u16 clip1mdA_gaincode_rev6 = 0x2084; ++ u16 clip1md_gaincode = 0; ++ u16 clip1loG_gaincode = 0x0074; ++ u16 clip1loG_gaincode_rev5[] = { ++ 0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c ++ }; ++ u16 clip1loG_gaincode_rev6[] = { ++ 0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e ++ }; ++ u16 clip1loG_gaincode_rev6_224B0 = 0x1074; ++ u16 clip1loA_gaincode = 0x00cc; ++ u16 clip1loA_gaincode_rev4 = 0x0086; ++ u16 clip1loA_gaincode_rev5 = 0x2086; ++ u16 clip1loA_gaincode_rev6 = 0x2086; ++ u16 clip1lo_gaincode; ++ u8 crsminG_th = 0x18; ++ u8 crsminG_th_rev5 = 0x18; ++ u8 crsminG_th_rev6 = 0x18; ++ u8 crsminA_th = 0x1e; ++ u8 crsminA_th_rev4 = 0x24; ++ u8 crsminA_th_rev5 = 0x24; ++ u8 crsminA_th_rev6 = 0x24; ++ u8 crsmin_th; ++ u8 crsminlG_th = 0x18; ++ u8 crsminlG_th_rev5 = 0x18; ++ u8 crsminlG_th_rev6 = 0x18; ++ u8 crsminlA_th = 0x1e; ++ u8 crsminlA_th_rev4 = 0x24; ++ u8 crsminlA_th_rev5 = 0x24; ++ u8 crsminlA_th_rev6 = 0x24; ++ u8 crsminl_th = 0; ++ u8 crsminuG_th = 0x18; ++ u8 crsminuG_th_rev5 = 0x18; ++ u8 crsminuG_th_rev6 = 0x18; ++ u8 crsminuA_th = 0x1e; ++ u8 crsminuA_th_rev4 = 0x24; ++ u8 crsminuA_th_rev5 = 0x24; ++ u8 crsminuA_th_rev6 = 0x24; ++ u8 crsminuA_th_rev6_224B0 = 0x2d; ++ u8 crsminu_th; ++ u16 nbclipG_th = 0x20d; ++ u16 nbclipG_th_rev4 = 0x1a1; ++ u16 nbclipG_th_rev5 = 0x1d0; ++ u16 nbclipG_th_rev6 = 0x1d0; ++ u16 nbclipA_th = 0x1a1; ++ u16 nbclipA_th_rev4 = 0x107; ++ u16 nbclipA_th_rev5 = 0x0a9; ++ u16 nbclipA_th_rev6 = 0x0f0; ++ u16 nbclip_th = 0; ++ u8 w1clipG_th = 5; ++ u8 w1clipG_th_rev5 = 9; ++ u8 w1clipG_th_rev6 = 5; ++ u8 w1clipA_th = 25, w1clip_th; ++ u8 rssi_gain_default = 0x50; ++ u8 rssiG_gain_rev6_224B0 = 0x50; ++ u8 rssiA_gain_rev5 = 0x90; ++ u8 rssiA_gain_rev6 = 0x90; ++ u8 rssi_gain; ++ u16 regval[21]; ++ u8 triso; ++ ++ triso = (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.triso : ++ pi->srom_fem2g.triso; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (pi->pubpi.radiorev == 5) { ++ wlc_phy_workarounds_nphy_gainctrl_2057_rev5(pi); ++ } else if (pi->pubpi.radiorev == 7) { ++ wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi); ++ ++ mod_phy_reg(pi, 0x283, (0xff << 0), (0x44 << 0)); ++ mod_phy_reg(pi, 0x280, (0xff << 0), (0x44 << 0)); ++ ++ } else if ((pi->pubpi.radiorev == 3) ++ || (pi->pubpi.radiorev == 8)) { ++ wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi); ++ ++ if (pi->pubpi.radiorev == 8) { ++ mod_phy_reg(pi, 0x283, ++ (0xff << 0), (0x44 << 0)); ++ mod_phy_reg(pi, 0x280, ++ (0xff << 0), (0x44 << 0)); ++ } ++ } else { ++ wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi); ++ } ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ mod_phy_reg(pi, 0xa0, (0x1 << 6), (1 << 6)); ++ ++ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13)); ++ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13)); ++ ++ currband = ++ read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; ++ if (currband == 0) { ++ if (NREV_GE(pi->pubpi.phy_rev, 6)) { ++ if (pi->pubpi.radiorev == 11) { ++ lna1_gain_db = lna1G_gain_db_rev6_224B0; ++ lna2_gain_db = lna2G_gain_db_rev6_224B0; ++ rfseq_init_gain = ++ rfseqG_init_gain_rev6_224B0; ++ init_gaincode = ++ initG_gaincode_rev6_224B0; ++ clip1hi_gaincode = ++ clip1hiG_gaincode_rev6; ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6_224B0; ++ nbclip_th = nbclipG_th_rev6; ++ w1clip_th = w1clipG_th_rev6; ++ crsmin_th = crsminG_th_rev6; ++ crsminl_th = crsminlG_th_rev6; ++ crsminu_th = crsminuG_th_rev6; ++ rssi_gain = rssiG_gain_rev6_224B0; ++ } else { ++ lna1_gain_db = lna1G_gain_db_rev6; ++ lna2_gain_db = lna2G_gain_db_rev6; ++ if (pi->sh->boardflags & BFL_EXTLNA) { ++ ++ rfseq_init_gain = ++ rfseqG_init_gain_rev6_elna; ++ init_gaincode = ++ initG_gaincode_rev6_elna; ++ } else { ++ rfseq_init_gain = ++ rfseqG_init_gain_rev6; ++ init_gaincode = ++ initG_gaincode_rev6; ++ } ++ clip1hi_gaincode = ++ clip1hiG_gaincode_rev6; ++ switch (triso) { ++ case 0: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6 ++ [0]; ++ break; ++ case 1: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6 ++ [1]; ++ break; ++ case 2: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6 ++ [2]; ++ break; ++ case 3: ++ default: ++ ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6 ++ [3]; ++ break; ++ case 4: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6 ++ [4]; ++ break; ++ case 5: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6 ++ [5]; ++ break; ++ case 6: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6 ++ [6]; ++ break; ++ case 7: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev6 ++ [7]; ++ break; ++ } ++ nbclip_th = nbclipG_th_rev6; ++ w1clip_th = w1clipG_th_rev6; ++ crsmin_th = crsminG_th_rev6; ++ crsminl_th = crsminlG_th_rev6; ++ crsminu_th = crsminuG_th_rev6; ++ rssi_gain = rssi_gain_default; ++ } ++ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { ++ lna1_gain_db = lna1G_gain_db_rev5; ++ lna2_gain_db = lna2G_gain_db_rev5; ++ if (pi->sh->boardflags & BFL_EXTLNA) { ++ ++ rfseq_init_gain = ++ rfseqG_init_gain_rev5_elna; ++ init_gaincode = ++ initG_gaincode_rev5_elna; ++ } else { ++ rfseq_init_gain = rfseqG_init_gain_rev5; ++ init_gaincode = initG_gaincode_rev5; ++ } ++ clip1hi_gaincode = clip1hiG_gaincode_rev5; ++ switch (triso) { ++ case 0: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[0]; ++ break; ++ case 1: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[1]; ++ break; ++ case 2: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[2]; ++ break; ++ case 3: ++ ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[3]; ++ break; ++ case 4: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[4]; ++ break; ++ case 5: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[5]; ++ break; ++ case 6: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[6]; ++ break; ++ case 7: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[7]; ++ break; ++ default: ++ clip1lo_gaincode = ++ clip1loG_gaincode_rev5[3]; ++ break; ++ } ++ nbclip_th = nbclipG_th_rev5; ++ w1clip_th = w1clipG_th_rev5; ++ crsmin_th = crsminG_th_rev5; ++ crsminl_th = crsminlG_th_rev5; ++ crsminu_th = crsminuG_th_rev5; ++ rssi_gain = rssi_gain_default; ++ } else if (NREV_IS(pi->pubpi.phy_rev, 4)) { ++ lna1_gain_db = lna1G_gain_db_rev4; ++ lna2_gain_db = lna2G_gain_db; ++ rfseq_init_gain = rfseqG_init_gain_rev4; ++ init_gaincode = initG_gaincode_rev4; ++ clip1hi_gaincode = clip1hiG_gaincode_rev4; ++ clip1lo_gaincode = clip1loG_gaincode; ++ nbclip_th = nbclipG_th_rev4; ++ w1clip_th = w1clipG_th; ++ crsmin_th = crsminG_th; ++ crsminl_th = crsminlG_th; ++ crsminu_th = crsminuG_th; ++ rssi_gain = rssi_gain_default; ++ } else { ++ lna1_gain_db = lna1G_gain_db; ++ lna2_gain_db = lna2G_gain_db; ++ rfseq_init_gain = rfseqG_init_gain; ++ init_gaincode = initG_gaincode; ++ clip1hi_gaincode = clip1hiG_gaincode; ++ clip1lo_gaincode = clip1loG_gaincode; ++ nbclip_th = nbclipG_th; ++ w1clip_th = w1clipG_th; ++ crsmin_th = crsminG_th; ++ crsminl_th = crsminlG_th; ++ crsminu_th = crsminuG_th; ++ rssi_gain = rssi_gain_default; ++ } ++ tia_gain_db = tiaG_gain_db; ++ tia_gainbits = tiaG_gainbits; ++ clip1md_gaincode = clip1mdG_gaincode; ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 6)) { ++ lna1_gain_db = lna1A_gain_db_rev6; ++ lna2_gain_db = lna2A_gain_db_rev6; ++ tia_gain_db = tiaA_gain_db_rev6; ++ tia_gainbits = tiaA_gainbits_rev6; ++ rfseq_init_gain = rfseqA_init_gain_rev6; ++ init_gaincode = initA_gaincode_rev6; ++ clip1hi_gaincode = clip1hiA_gaincode_rev6; ++ clip1md_gaincode = clip1mdA_gaincode_rev6; ++ clip1lo_gaincode = clip1loA_gaincode_rev6; ++ crsmin_th = crsminA_th_rev6; ++ crsminl_th = crsminlA_th_rev6; ++ if ((pi->pubpi.radiorev == 11) && ++ (CHSPEC_IS40(pi->radio_chanspec) == 0)) ++ crsminu_th = crsminuA_th_rev6_224B0; ++ else ++ crsminu_th = crsminuA_th_rev6; ++ ++ nbclip_th = nbclipA_th_rev6; ++ rssi_gain = rssiA_gain_rev6; ++ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { ++ lna1_gain_db = lna1A_gain_db_rev5; ++ lna2_gain_db = lna2A_gain_db_rev5; ++ tia_gain_db = tiaA_gain_db_rev5; ++ tia_gainbits = tiaA_gainbits_rev5; ++ rfseq_init_gain = rfseqA_init_gain_rev5; ++ init_gaincode = initA_gaincode_rev5; ++ clip1hi_gaincode = clip1hiA_gaincode_rev5; ++ clip1md_gaincode = clip1mdA_gaincode_rev5; ++ clip1lo_gaincode = clip1loA_gaincode_rev5; ++ crsmin_th = crsminA_th_rev5; ++ crsminl_th = crsminlA_th_rev5; ++ crsminu_th = crsminuA_th_rev5; ++ nbclip_th = nbclipA_th_rev5; ++ rssi_gain = rssiA_gain_rev5; ++ } else if (NREV_IS(pi->pubpi.phy_rev, 4)) { ++ lna1_gain_db = lna1A_gain_db_rev4; ++ lna2_gain_db = lna2A_gain_db_rev4; ++ tia_gain_db = tiaA_gain_db_rev4; ++ tia_gainbits = tiaA_gainbits_rev4; ++ if (pi->sh->boardflags & BFL_EXTLNA_5GHz) { ++ ++ rfseq_init_gain = ++ rfseqA_init_gain_rev4_elna; ++ init_gaincode = ++ initA_gaincode_rev4_elna; ++ } else { ++ rfseq_init_gain = rfseqA_init_gain_rev4; ++ init_gaincode = initA_gaincode_rev4; ++ } ++ clip1hi_gaincode = clip1hiA_gaincode_rev4; ++ clip1md_gaincode = clip1mdA_gaincode_rev4; ++ clip1lo_gaincode = clip1loA_gaincode_rev4; ++ crsmin_th = crsminA_th_rev4; ++ crsminl_th = crsminlA_th_rev4; ++ crsminu_th = crsminuA_th_rev4; ++ nbclip_th = nbclipA_th_rev4; ++ rssi_gain = rssi_gain_default; ++ } else { ++ lna1_gain_db = lna1A_gain_db; ++ lna2_gain_db = lna2A_gain_db; ++ tia_gain_db = tiaA_gain_db; ++ tia_gainbits = tiaA_gainbits; ++ rfseq_init_gain = rfseqA_init_gain; ++ init_gaincode = initA_gaincode; ++ clip1hi_gaincode = clip1hiA_gaincode; ++ clip1md_gaincode = clip1mdA_gaincode; ++ clip1lo_gaincode = clip1loA_gaincode; ++ crsmin_th = crsminA_th; ++ crsminl_th = crsminlA_th; ++ crsminu_th = crsminuA_th; ++ nbclip_th = nbclipA_th; ++ rssi_gain = rssi_gain_default; ++ } ++ w1clip_th = w1clipA_th; ++ } ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_BIASPOLE_LNAG1_IDAC | ++ RADIO_2056_RX0), 0x17); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_BIASPOLE_LNAG1_IDAC | ++ RADIO_2056_RX1), 0x17); ++ ++ write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX0), ++ 0xf0); ++ write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX1), ++ 0xf0); ++ ++ write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX0), ++ 0x0); ++ write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX1), ++ 0x0); ++ ++ write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX0), ++ rssi_gain); ++ write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX1), ++ rssi_gain); ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_BIASPOLE_LNAA1_IDAC | ++ RADIO_2056_RX0), 0x17); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_BIASPOLE_LNAA1_IDAC | ++ RADIO_2056_RX1), 0x17); ++ ++ write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX0), ++ 0xFF); ++ write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX1), ++ 0xFF); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, ++ 8, lna1_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, ++ 8, lna1_gain_db); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, ++ 8, lna2_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, ++ 8, lna2_gain_db); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, ++ 8, tia_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, ++ 8, tia_gain_db); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, ++ 8, tia_gainbits); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, ++ 8, tia_gainbits); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 6, 0x40, ++ 8, &lpf_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 6, 0x40, ++ 8, &lpf_gain_db); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 6, 0x40, ++ 8, &lpf_gainbits); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 6, 0x40, ++ 8, &lpf_gainbits); ++ ++ write_phy_reg(pi, 0x20, init_gaincode); ++ write_phy_reg(pi, 0x2a7, init_gaincode); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, ++ pi->pubpi.phy_corenum, 0x106, 16, ++ rfseq_init_gain); ++ ++ write_phy_reg(pi, 0x22, clip1hi_gaincode); ++ write_phy_reg(pi, 0x2a9, clip1hi_gaincode); ++ ++ write_phy_reg(pi, 0x24, clip1md_gaincode); ++ write_phy_reg(pi, 0x2ab, clip1md_gaincode); ++ ++ write_phy_reg(pi, 0x37, clip1lo_gaincode); ++ write_phy_reg(pi, 0x2ad, clip1lo_gaincode); ++ ++ mod_phy_reg(pi, 0x27d, (0xff << 0), (crsmin_th << 0)); ++ mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0)); ++ mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0)); ++ ++ write_phy_reg(pi, 0x2b, nbclip_th); ++ write_phy_reg(pi, 0x41, nbclip_th); ++ ++ mod_phy_reg(pi, 0x27, (0x3f << 0), (w1clip_th << 0)); ++ mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1clip_th << 0)); ++ ++ write_phy_reg(pi, 0x150, 0x809c); ++ ++ } else { ++ ++ mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13)); ++ mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13)); ++ ++ write_phy_reg(pi, 0x2b, 0x84); ++ write_phy_reg(pi, 0x41, 0x84); ++ ++ if (CHSPEC_IS20(pi->radio_chanspec)) { ++ write_phy_reg(pi, 0x6b, 0x2b); ++ write_phy_reg(pi, 0x6c, 0x2b); ++ write_phy_reg(pi, 0x6d, 0x9); ++ write_phy_reg(pi, 0x6e, 0x9); ++ } ++ ++ w1th = NPHY_RSSICAL_W1_TARGET - 4; ++ mod_phy_reg(pi, 0x27, (0x3f << 0), (w1th << 0)); ++ mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1th << 0)); ++ ++ if (CHSPEC_IS20(pi->radio_chanspec)) { ++ mod_phy_reg(pi, 0x1c, (0x1f << 0), (0x1 << 0)); ++ mod_phy_reg(pi, 0x32, (0x1f << 0), (0x1 << 0)); ++ ++ mod_phy_reg(pi, 0x1d, (0x1f << 0), (0x1 << 0)); ++ mod_phy_reg(pi, 0x33, (0x1f << 0), (0x1 << 0)); ++ } ++ ++ write_phy_reg(pi, 0x150, 0x809c); ++ ++ if (pi->nphy_gain_boost) ++ if ((CHSPEC_IS2G(pi->radio_chanspec)) && ++ (CHSPEC_IS40(pi->radio_chanspec))) ++ hpf_code = 4; ++ else ++ hpf_code = 5; ++ else if (CHSPEC_IS40(pi->radio_chanspec)) ++ hpf_code = 6; ++ else ++ hpf_code = 7; ++ ++ mod_phy_reg(pi, 0x20, (0x1f << 7), (hpf_code << 7)); ++ mod_phy_reg(pi, 0x36, (0x1f << 7), (hpf_code << 7)); ++ ++ for (ctr = 0; ctr < 4; ctr++) ++ regval[ctr] = (hpf_code << 8) | 0x7c; ++ wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval); ++ ++ wlc_phy_adjust_lnagaintbl_nphy(pi); ++ ++ if (pi->nphy_elna_gain_config) { ++ regval[0] = 0; ++ regval[1] = 1; ++ regval[2] = 1; ++ regval[3] = 1; ++ wlc_phy_table_write_nphy(pi, 2, 4, 8, 16, regval); ++ wlc_phy_table_write_nphy(pi, 3, 4, 8, 16, regval); ++ ++ for (ctr = 0; ctr < 4; ctr++) ++ regval[ctr] = (hpf_code << 8) | 0x74; ++ wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval); ++ } ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 2)) { ++ for (ctr = 0; ctr < 21; ctr++) ++ regval[ctr] = 3 * ctr; ++ wlc_phy_table_write_nphy(pi, 0, 21, 32, 16, regval); ++ wlc_phy_table_write_nphy(pi, 1, 21, 32, 16, regval); ++ ++ for (ctr = 0; ctr < 21; ctr++) ++ regval[ctr] = (u16) ctr; ++ wlc_phy_table_write_nphy(pi, 2, 21, 32, 16, regval); ++ wlc_phy_table_write_nphy(pi, 3, 21, 32, 16, regval); ++ } ++ ++ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_UPDATEGAINU, ++ rfseq_updategainu_events, ++ rfseq_updategainu_dlys, ++ sizeof(rfseq_updategainu_events) / ++ sizeof(rfseq_updategainu_events[0])); ++ ++ mod_phy_reg(pi, 0x153, (0xff << 8), (90 << 8)); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ mod_phy_reg(pi, ++ (NPHY_TO_BPHY_OFF + BPHY_OPTIONAL_MODES), ++ 0x7f, 0x4); ++ } ++} ++ ++static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) ++{ ++ u8 rfseq_rx2tx_events[] = { ++ NPHY_RFSEQ_CMD_NOP, ++ NPHY_RFSEQ_CMD_RXG_FBW, ++ NPHY_RFSEQ_CMD_TR_SWITCH, ++ NPHY_RFSEQ_CMD_CLR_HIQ_DIS, ++ NPHY_RFSEQ_CMD_RXPD_TXPD, ++ NPHY_RFSEQ_CMD_TX_GAIN, ++ NPHY_RFSEQ_CMD_EXT_PA ++ }; ++ u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 }; ++ u8 rfseq_tx2rx_events[] = { ++ NPHY_RFSEQ_CMD_NOP, ++ NPHY_RFSEQ_CMD_EXT_PA, ++ NPHY_RFSEQ_CMD_TX_GAIN, ++ NPHY_RFSEQ_CMD_RXPD_TXPD, ++ NPHY_RFSEQ_CMD_TR_SWITCH, ++ NPHY_RFSEQ_CMD_RXG_FBW, ++ NPHY_RFSEQ_CMD_CLR_HIQ_DIS ++ }; ++ u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 }; ++ u8 rfseq_tx2rx_events_rev3[] = { ++ NPHY_REV3_RFSEQ_CMD_EXT_PA, ++ NPHY_REV3_RFSEQ_CMD_INT_PA_PU, ++ NPHY_REV3_RFSEQ_CMD_TX_GAIN, ++ NPHY_REV3_RFSEQ_CMD_RXPD_TXPD, ++ NPHY_REV3_RFSEQ_CMD_TR_SWITCH, ++ NPHY_REV3_RFSEQ_CMD_RXG_FBW, ++ NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, ++ NPHY_REV3_RFSEQ_CMD_END ++ }; ++ u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 }; ++ u8 rfseq_rx2tx_events_rev3[] = { ++ NPHY_REV3_RFSEQ_CMD_NOP, ++ NPHY_REV3_RFSEQ_CMD_RXG_FBW, ++ NPHY_REV3_RFSEQ_CMD_TR_SWITCH, ++ NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, ++ NPHY_REV3_RFSEQ_CMD_RXPD_TXPD, ++ NPHY_REV3_RFSEQ_CMD_TX_GAIN, ++ NPHY_REV3_RFSEQ_CMD_INT_PA_PU, ++ NPHY_REV3_RFSEQ_CMD_EXT_PA, ++ NPHY_REV3_RFSEQ_CMD_END ++ }; ++ u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 }; ++ ++ u8 rfseq_rx2tx_events_rev3_ipa[] = { ++ NPHY_REV3_RFSEQ_CMD_NOP, ++ NPHY_REV3_RFSEQ_CMD_RXG_FBW, ++ NPHY_REV3_RFSEQ_CMD_TR_SWITCH, ++ NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, ++ NPHY_REV3_RFSEQ_CMD_RXPD_TXPD, ++ NPHY_REV3_RFSEQ_CMD_TX_GAIN, ++ NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS, ++ NPHY_REV3_RFSEQ_CMD_INT_PA_PU, ++ NPHY_REV3_RFSEQ_CMD_END ++ }; ++ u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; ++ u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f }; ++ ++ s16 alpha0, alpha1, alpha2; ++ s16 beta0, beta1, beta2; ++ u32 leg_data_weights, ht_data_weights, nss1_data_weights, ++ stbc_data_weights; ++ u8 chan_freq_range = 0; ++ u16 dac_control = 0x0002; ++ u16 aux_adc_vmid_rev7_core0[] = { 0x8e, 0x96, 0x96, 0x96 }; ++ u16 aux_adc_vmid_rev7_core1[] = { 0x8f, 0x9f, 0x9f, 0x96 }; ++ u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 }; ++ u16 aux_adc_vmid_rev3[] = { 0xa2, 0xb4, 0xb4, 0x89 }; ++ u16 *aux_adc_vmid; ++ u16 aux_adc_gain_rev7[] = { 0x02, 0x02, 0x02, 0x02 }; ++ u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 }; ++ u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 }; ++ u16 *aux_adc_gain; ++ u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 }; ++ u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 }; ++ s32 min_nvar_val = 0x18d; ++ s32 min_nvar_offset_6mbps = 20; ++ u8 pdetrange; ++ u8 triso; ++ u16 regval; ++ u16 afectrl_adc_ctrl1_rev7 = 0x20; ++ u16 afectrl_adc_ctrl2_rev7 = 0x0; ++ u16 rfseq_rx2tx_lpf_h_hpc_rev7 = 0x77; ++ u16 rfseq_tx2rx_lpf_h_hpc_rev7 = 0x77; ++ u16 rfseq_pktgn_lpf_h_hpc_rev7 = 0x77; ++ u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 }; ++ u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; ++ u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; ++ u16 ipalvlshift_3p3_war_en = 0; ++ u16 rccal_bcap_val, rccal_scap_val; ++ u16 rccal_tx20_11b_bcap = 0; ++ u16 rccal_tx20_11b_scap = 0; ++ u16 rccal_tx20_11n_bcap = 0; ++ u16 rccal_tx20_11n_scap = 0; ++ u16 rccal_tx40_11n_bcap = 0; ++ u16 rccal_tx40_11n_scap = 0; ++ u16 rx2tx_lpf_rc_lut_tx20_11b = 0; ++ u16 rx2tx_lpf_rc_lut_tx20_11n = 0; ++ u16 rx2tx_lpf_rc_lut_tx40_11n = 0; ++ u16 tx_lpf_bw_ofdm_20mhz = 0; ++ u16 tx_lpf_bw_ofdm_40mhz = 0; ++ u16 tx_lpf_bw_11b = 0; ++ u16 ipa2g_mainbias, ipa2g_casconv, ipa2g_biasfilt; ++ u16 txgm_idac_bleed = 0; ++ bool rccal_ovrd = false; ++ u16 freq; ++ int coreNum; ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) ++ wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 0); ++ else ++ wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 1); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ or_phy_reg(pi, 0xb1, NPHY_IQFlip_ADC1 | NPHY_IQFlip_ADC2); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7)) { ++ mod_phy_reg(pi, 0x221, (0x1 << 4), (1 << 4)); ++ ++ mod_phy_reg(pi, 0x160, (0x7f << 0), (32 << 0)); ++ mod_phy_reg(pi, 0x160, (0x7f << 8), (39 << 8)); ++ mod_phy_reg(pi, 0x161, (0x7f << 0), (46 << 0)); ++ mod_phy_reg(pi, 0x161, (0x7f << 8), (51 << 8)); ++ mod_phy_reg(pi, 0x162, (0x7f << 0), (55 << 0)); ++ mod_phy_reg(pi, 0x162, (0x7f << 8), (58 << 8)); ++ mod_phy_reg(pi, 0x163, (0x7f << 0), (60 << 0)); ++ mod_phy_reg(pi, 0x163, (0x7f << 8), (62 << 8)); ++ mod_phy_reg(pi, 0x164, (0x7f << 0), (62 << 0)); ++ mod_phy_reg(pi, 0x164, (0x7f << 8), (63 << 8)); ++ mod_phy_reg(pi, 0x165, (0x7f << 0), (63 << 0)); ++ mod_phy_reg(pi, 0x165, (0x7f << 8), (64 << 8)); ++ mod_phy_reg(pi, 0x166, (0x7f << 0), (64 << 0)); ++ mod_phy_reg(pi, 0x166, (0x7f << 8), (64 << 8)); ++ mod_phy_reg(pi, 0x167, (0x7f << 0), (64 << 0)); ++ mod_phy_reg(pi, 0x167, (0x7f << 8), (64 << 8)); ++ } ++ ++ if (NREV_LE(pi->pubpi.phy_rev, 8)) { ++ write_phy_reg(pi, 0x23f, 0x1b0); ++ write_phy_reg(pi, 0x240, 0x1b0); ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 8)) ++ mod_phy_reg(pi, 0xbd, (0xff << 0), (114 << 0)); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16, ++ &dac_control); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16, ++ &dac_control); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, ++ 1, 0, 32, &leg_data_weights); ++ leg_data_weights = leg_data_weights & 0xffffff; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, ++ 1, 0, 32, &leg_data_weights); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, ++ 2, 0x15e, 16, ++ rfseq_rx2tx_dacbufpu_rev7); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x16e, 16, ++ rfseq_rx2tx_dacbufpu_rev7); ++ ++ if (PHY_IPA(pi)) ++ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, ++ rfseq_rx2tx_events_rev3_ipa, ++ rfseq_rx2tx_dlys_rev3_ipa, ++ sizeof ++ (rfseq_rx2tx_events_rev3_ipa) / ++ sizeof ++ (rfseq_rx2tx_events_rev3_ipa ++ [0])); ++ ++ mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14)); ++ mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14)); ++ ++ tx_lpf_bw_ofdm_20mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x154); ++ tx_lpf_bw_ofdm_40mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x159); ++ tx_lpf_bw_11b = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x152); ++ ++ if (PHY_IPA(pi)) { ++ ++ if (((pi->pubpi.radiorev == 5) ++ && (CHSPEC_IS40(pi->radio_chanspec) == 1)) ++ || (pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) { ++ ++ rccal_bcap_val = ++ read_radio_reg( ++ pi, ++ RADIO_2057_RCCAL_BCAP_VAL); ++ rccal_scap_val = ++ read_radio_reg( ++ pi, ++ RADIO_2057_RCCAL_SCAP_VAL); ++ ++ rccal_tx20_11b_bcap = rccal_bcap_val; ++ rccal_tx20_11b_scap = rccal_scap_val; ++ ++ if ((pi->pubpi.radiorev == 5) && ++ (CHSPEC_IS40(pi->radio_chanspec) == 1)) { ++ ++ rccal_tx20_11n_bcap = rccal_bcap_val; ++ rccal_tx20_11n_scap = rccal_scap_val; ++ rccal_tx40_11n_bcap = 0xc; ++ rccal_tx40_11n_scap = 0xc; ++ ++ rccal_ovrd = true; ++ ++ } else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) { ++ ++ tx_lpf_bw_ofdm_20mhz = 4; ++ tx_lpf_bw_11b = 1; ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ rccal_tx20_11n_bcap = 0xc; ++ rccal_tx20_11n_scap = 0xc; ++ rccal_tx40_11n_bcap = 0xa; ++ rccal_tx40_11n_scap = 0xa; ++ } else { ++ rccal_tx20_11n_bcap = 0x14; ++ rccal_tx20_11n_scap = 0x14; ++ rccal_tx40_11n_bcap = 0xf; ++ rccal_tx40_11n_scap = 0xf; ++ } ++ ++ rccal_ovrd = true; ++ } ++ } ++ ++ } else { ++ ++ if (pi->pubpi.radiorev == 5) { ++ ++ tx_lpf_bw_ofdm_20mhz = 1; ++ tx_lpf_bw_ofdm_40mhz = 3; ++ ++ rccal_bcap_val = ++ read_radio_reg( ++ pi, ++ RADIO_2057_RCCAL_BCAP_VAL); ++ rccal_scap_val = ++ read_radio_reg( ++ pi, ++ RADIO_2057_RCCAL_SCAP_VAL); ++ ++ rccal_tx20_11b_bcap = rccal_bcap_val; ++ rccal_tx20_11b_scap = rccal_scap_val; ++ ++ rccal_tx20_11n_bcap = 0x13; ++ rccal_tx20_11n_scap = 0x11; ++ rccal_tx40_11n_bcap = 0x13; ++ rccal_tx40_11n_scap = 0x11; ++ ++ rccal_ovrd = true; ++ } ++ } ++ ++ if (rccal_ovrd) { ++ ++ rx2tx_lpf_rc_lut_tx20_11b = ++ (rccal_tx20_11b_bcap << 8) | ++ (rccal_tx20_11b_scap << 3) | ++ tx_lpf_bw_11b; ++ rx2tx_lpf_rc_lut_tx20_11n = ++ (rccal_tx20_11n_bcap << 8) | ++ (rccal_tx20_11n_scap << 3) | ++ tx_lpf_bw_ofdm_20mhz; ++ rx2tx_lpf_rc_lut_tx40_11n = ++ (rccal_tx40_11n_bcap << 8) | ++ (rccal_tx40_11n_scap << 3) | ++ tx_lpf_bw_ofdm_40mhz; ++ ++ for (coreNum = 0; coreNum <= 1; coreNum++) { ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_RFSEQ, ++ 1, ++ 0x152 + coreNum * 0x10, ++ 16, ++ &rx2tx_lpf_rc_lut_tx20_11b); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_RFSEQ, ++ 1, ++ 0x153 + coreNum * 0x10, ++ 16, ++ &rx2tx_lpf_rc_lut_tx20_11n); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_RFSEQ, ++ 1, ++ 0x154 + coreNum * 0x10, ++ 16, ++ &rx2tx_lpf_rc_lut_tx20_11n); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_RFSEQ, ++ 1, ++ 0x155 + coreNum * 0x10, ++ 16, ++ &rx2tx_lpf_rc_lut_tx40_11n); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_RFSEQ, ++ 1, ++ 0x156 + coreNum * 0x10, ++ 16, ++ &rx2tx_lpf_rc_lut_tx40_11n); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_RFSEQ, ++ 1, ++ 0x157 + coreNum * 0x10, ++ 16, ++ &rx2tx_lpf_rc_lut_tx40_11n); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_RFSEQ, ++ 1, ++ 0x158 + coreNum * 0x10, ++ 16, ++ &rx2tx_lpf_rc_lut_tx40_11n); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_RFSEQ, ++ 1, ++ 0x159 + coreNum * 0x10, ++ 16, ++ &rx2tx_lpf_rc_lut_tx40_11n); ++ } ++ ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 4), ++ 1, 0x3, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ } ++ ++ write_phy_reg(pi, 0x32f, 0x3); ++ ++ if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 2), ++ 1, 0x3, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ ++ if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) { ++ if ((pi->sh->sromrev >= 8) ++ && (pi->sh->boardflags2 & BFL2_IPALVLSHIFT_3P3)) ++ ipalvlshift_3p3_war_en = 1; ++ ++ if (ipalvlshift_3p3_war_en) { ++ write_radio_reg(pi, RADIO_2057_GPAIO_CONFIG, ++ 0x5); ++ write_radio_reg(pi, RADIO_2057_GPAIO_SEL1, ++ 0x30); ++ write_radio_reg(pi, RADIO_2057_GPAIO_SEL0, 0x0); ++ or_radio_reg(pi, ++ RADIO_2057_RXTXBIAS_CONFIG_CORE0, ++ 0x1); ++ or_radio_reg(pi, ++ RADIO_2057_RXTXBIAS_CONFIG_CORE1, ++ 0x1); ++ ++ ipa2g_mainbias = 0x1f; ++ ++ ipa2g_casconv = 0x6f; ++ ++ ipa2g_biasfilt = 0xaa; ++ } else { ++ ++ ipa2g_mainbias = 0x2b; ++ ++ ipa2g_casconv = 0x7f; ++ ++ ipa2g_biasfilt = 0xee; ++ } ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ for (coreNum = 0; coreNum <= 1; coreNum++) { ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, ++ coreNum, IPA2G_IMAIN, ++ ipa2g_mainbias); ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, ++ coreNum, IPA2G_CASCONV, ++ ipa2g_casconv); ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, ++ coreNum, ++ IPA2G_BIAS_FILTER, ++ ipa2g_biasfilt); ++ } ++ } ++ } ++ ++ if (PHY_IPA(pi)) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if ((pi->pubpi.radiorev == 3) ++ || (pi->pubpi.radiorev == 4) ++ || (pi->pubpi.radiorev == 6)) ++ txgm_idac_bleed = 0x7f; ++ ++ for (coreNum = 0; coreNum <= 1; coreNum++) { ++ if (txgm_idac_bleed != 0) ++ WRITE_RADIO_REG4( ++ pi, RADIO_2057, ++ CORE, coreNum, ++ TXGM_IDAC_BLEED, ++ txgm_idac_bleed); ++ } ++ ++ if (pi->pubpi.radiorev == 5) { ++ ++ for (coreNum = 0; coreNum <= 1; ++ coreNum++) { ++ WRITE_RADIO_REG4(pi, RADIO_2057, ++ CORE, coreNum, ++ IPA2G_CASCONV, ++ 0x13); ++ WRITE_RADIO_REG4(pi, RADIO_2057, ++ CORE, coreNum, ++ IPA2G_IMAIN, ++ 0x1f); ++ WRITE_RADIO_REG4( ++ pi, RADIO_2057, ++ CORE, coreNum, ++ IPA2G_BIAS_FILTER, ++ 0xee); ++ WRITE_RADIO_REG4(pi, RADIO_2057, ++ CORE, coreNum, ++ PAD2G_IDACS, ++ 0x8a); ++ WRITE_RADIO_REG4( ++ pi, RADIO_2057, ++ CORE, coreNum, ++ PAD_BIAS_FILTER_BWS, ++ 0x3e); ++ } ++ ++ } else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) { ++ ++ if (CHSPEC_IS40(pi->radio_chanspec) == ++ 0) { ++ WRITE_RADIO_REG4(pi, RADIO_2057, ++ CORE, 0, ++ IPA2G_IMAIN, ++ 0x14); ++ WRITE_RADIO_REG4(pi, RADIO_2057, ++ CORE, 1, ++ IPA2G_IMAIN, ++ 0x12); ++ } else { ++ WRITE_RADIO_REG4(pi, RADIO_2057, ++ CORE, 0, ++ IPA2G_IMAIN, ++ 0x16); ++ WRITE_RADIO_REG4(pi, RADIO_2057, ++ CORE, 1, ++ IPA2G_IMAIN, ++ 0x16); ++ } ++ } ++ ++ } else { ++ freq = CHAN5G_FREQ(CHSPEC_CHANNEL( ++ pi->radio_chanspec)); ++ if (((freq >= 5180) && (freq <= 5230)) ++ || ((freq >= 5745) && (freq <= 5805))) { ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, ++ 0, IPA5G_BIAS_FILTER, ++ 0xff); ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, ++ 1, IPA5G_BIAS_FILTER, ++ 0xff); ++ } ++ } ++ } else { ++ ++ if (pi->pubpi.radiorev != 5) { ++ for (coreNum = 0; coreNum <= 1; coreNum++) { ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, ++ coreNum, ++ TXMIX2G_TUNE_BOOST_PU, ++ 0x61); ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, ++ coreNum, ++ TXGM_IDAC_BLEED, 0x70); ++ } ++ } ++ } ++ ++ if (pi->pubpi.radiorev == 4) { ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, ++ 0x05, 16, ++ &afectrl_adc_ctrl1_rev7); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, ++ 0x15, 16, ++ &afectrl_adc_ctrl1_rev7); ++ ++ for (coreNum = 0; coreNum <= 1; coreNum++) { ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, ++ AFE_VCM_CAL_MASTER, 0x0); ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, ++ AFE_SET_VCM_I, 0x3f); ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, ++ AFE_SET_VCM_Q, 0x3f); ++ } ++ } else { ++ mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2)); ++ mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2)); ++ mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2)); ++ mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2)); ++ ++ mod_phy_reg(pi, 0xa6, (0x1 << 0), 0); ++ mod_phy_reg(pi, 0x8f, (0x1 << 0), (0x1 << 0)); ++ mod_phy_reg(pi, 0xa7, (0x1 << 0), 0); ++ mod_phy_reg(pi, 0xa5, (0x1 << 0), (0x1 << 0)); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, ++ 0x05, 16, ++ &afectrl_adc_ctrl2_rev7); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, ++ 0x15, 16, ++ &afectrl_adc_ctrl2_rev7); ++ ++ mod_phy_reg(pi, 0xa6, (0x1 << 2), 0); ++ mod_phy_reg(pi, 0x8f, (0x1 << 2), 0); ++ mod_phy_reg(pi, 0xa7, (0x1 << 2), 0); ++ mod_phy_reg(pi, 0xa5, (0x1 << 2), 0); ++ } ++ ++ write_phy_reg(pi, 0x6a, 0x2); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 256, 32, ++ &min_nvar_offset_6mbps); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x138, 16, ++ &rfseq_pktgn_lpf_hpc_rev7); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x141, 16, ++ &rfseq_pktgn_lpf_h_hpc_rev7); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 3, 0x133, 16, ++ &rfseq_htpktgn_lpf_hpc_rev7); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x146, 16, ++ &rfseq_cckpktgn_lpf_hpc_rev7); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x123, 16, ++ &rfseq_tx2rx_lpf_h_hpc_rev7); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x12A, 16, ++ &rfseq_rx2tx_lpf_h_hpc_rev7); ++ ++ if (CHSPEC_IS40(pi->radio_chanspec) == 0) { ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, ++ 32, &min_nvar_val); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, ++ 127, 32, &min_nvar_val); ++ } else { ++ min_nvar_val = noise_var_tbl_rev7[3]; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, ++ 32, &min_nvar_val); ++ ++ min_nvar_val = noise_var_tbl_rev7[127]; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, ++ 127, 32, &min_nvar_val); ++ } ++ ++ wlc_phy_workarounds_nphy_gainctrl(pi); ++ ++ pdetrange = ++ (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. ++ pdetrange : pi->srom_fem2g.pdetrange; ++ ++ if (pdetrange == 0) { ++ chan_freq_range = ++ wlc_phy_get_chan_freq_range_nphy(pi, 0); ++ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { ++ aux_adc_vmid_rev7_core0[3] = 0x70; ++ aux_adc_vmid_rev7_core1[3] = 0x70; ++ aux_adc_gain_rev7[3] = 2; ++ } else { ++ aux_adc_vmid_rev7_core0[3] = 0x80; ++ aux_adc_vmid_rev7_core1[3] = 0x80; ++ aux_adc_gain_rev7[3] = 3; ++ } ++ } else if (pdetrange == 1) { ++ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { ++ aux_adc_vmid_rev7_core0[3] = 0x7c; ++ aux_adc_vmid_rev7_core1[3] = 0x7c; ++ aux_adc_gain_rev7[3] = 2; ++ } else { ++ aux_adc_vmid_rev7_core0[3] = 0x8c; ++ aux_adc_vmid_rev7_core1[3] = 0x8c; ++ aux_adc_gain_rev7[3] = 1; ++ } ++ } else if (pdetrange == 2) { ++ if (pi->pubpi.radioid == BCM2057_ID) { ++ if ((pi->pubpi.radiorev == 5) ++ || (pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) { ++ if (chan_freq_range == ++ WL_CHAN_FREQ_RANGE_2G) { ++ aux_adc_vmid_rev7_core0[3] = ++ 0x8c; ++ aux_adc_vmid_rev7_core1[3] = ++ 0x8c; ++ aux_adc_gain_rev7[3] = 0; ++ } else { ++ aux_adc_vmid_rev7_core0[3] = ++ 0x96; ++ aux_adc_vmid_rev7_core1[3] = ++ 0x96; ++ aux_adc_gain_rev7[3] = 0; ++ } ++ } ++ } ++ ++ } else if (pdetrange == 3) { ++ if (chan_freq_range == WL_CHAN_FREQ_RANGE_2G) { ++ aux_adc_vmid_rev7_core0[3] = 0x89; ++ aux_adc_vmid_rev7_core1[3] = 0x89; ++ aux_adc_gain_rev7[3] = 0; ++ } ++ ++ } else if (pdetrange == 5) { ++ ++ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { ++ aux_adc_vmid_rev7_core0[3] = 0x80; ++ aux_adc_vmid_rev7_core1[3] = 0x80; ++ aux_adc_gain_rev7[3] = 3; ++ } else { ++ aux_adc_vmid_rev7_core0[3] = 0x70; ++ aux_adc_vmid_rev7_core1[3] = 0x70; ++ aux_adc_gain_rev7[3] = 2; ++ } ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x08, 16, ++ &aux_adc_vmid_rev7_core0); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x18, 16, ++ &aux_adc_vmid_rev7_core1); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x0c, 16, ++ &aux_adc_gain_rev7); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x1c, 16, ++ &aux_adc_gain_rev7); ++ ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ write_phy_reg(pi, 0x23f, 0x1f8); ++ write_phy_reg(pi, 0x240, 0x1f8); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, ++ 1, 0, 32, &leg_data_weights); ++ leg_data_weights = leg_data_weights & 0xffffff; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, ++ 1, 0, 32, &leg_data_weights); ++ ++ alpha0 = 293; ++ alpha1 = 435; ++ alpha2 = 261; ++ beta0 = 366; ++ beta1 = 205; ++ beta2 = 32; ++ write_phy_reg(pi, 0x145, alpha0); ++ write_phy_reg(pi, 0x146, alpha1); ++ write_phy_reg(pi, 0x147, alpha2); ++ write_phy_reg(pi, 0x148, beta0); ++ write_phy_reg(pi, 0x149, beta1); ++ write_phy_reg(pi, 0x14a, beta2); ++ ++ write_phy_reg(pi, 0x38, 0xC); ++ write_phy_reg(pi, 0x2ae, 0xC); ++ ++ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, ++ rfseq_tx2rx_events_rev3, ++ rfseq_tx2rx_dlys_rev3, ++ sizeof(rfseq_tx2rx_events_rev3) / ++ sizeof(rfseq_tx2rx_events_rev3[0])); ++ ++ if (PHY_IPA(pi)) ++ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, ++ rfseq_rx2tx_events_rev3_ipa, ++ rfseq_rx2tx_dlys_rev3_ipa, ++ sizeof ++ (rfseq_rx2tx_events_rev3_ipa) / ++ sizeof ++ (rfseq_rx2tx_events_rev3_ipa ++ [0])); ++ ++ if ((pi->sh->hw_phyrxchain != 0x3) && ++ (pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) { ++ ++ if (PHY_IPA(pi)) { ++ rfseq_rx2tx_dlys_rev3[5] = 59; ++ rfseq_rx2tx_dlys_rev3[6] = 1; ++ rfseq_rx2tx_events_rev3[7] = ++ NPHY_REV3_RFSEQ_CMD_END; ++ } ++ ++ wlc_phy_set_rfseq_nphy( ++ pi, NPHY_RFSEQ_RX2TX, ++ rfseq_rx2tx_events_rev3, ++ rfseq_rx2tx_dlys_rev3, ++ sizeof(rfseq_rx2tx_events_rev3) / ++ sizeof(rfseq_rx2tx_events_rev3[0])); ++ } ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ write_phy_reg(pi, 0x6a, 0x2); ++ else ++ write_phy_reg(pi, 0x6a, 0x9c40); ++ ++ mod_phy_reg(pi, 0x294, (0xf << 8), (7 << 8)); ++ ++ if (CHSPEC_IS40(pi->radio_chanspec) == 0) { ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, ++ 32, &min_nvar_val); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, ++ 127, 32, &min_nvar_val); ++ } else { ++ min_nvar_val = noise_var_tbl_rev3[3]; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3, ++ 32, &min_nvar_val); ++ ++ min_nvar_val = noise_var_tbl_rev3[127]; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, ++ 127, 32, &min_nvar_val); ++ } ++ ++ wlc_phy_workarounds_nphy_gainctrl(pi); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16, ++ &dac_control); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16, ++ &dac_control); ++ ++ pdetrange = ++ (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. ++ pdetrange : pi->srom_fem2g.pdetrange; ++ ++ if (pdetrange == 0) { ++ if (NREV_GE(pi->pubpi.phy_rev, 4)) { ++ aux_adc_vmid = aux_adc_vmid_rev4; ++ aux_adc_gain = aux_adc_gain_rev4; ++ } else { ++ aux_adc_vmid = aux_adc_vmid_rev3; ++ aux_adc_gain = aux_adc_gain_rev3; ++ } ++ chan_freq_range = ++ wlc_phy_get_chan_freq_range_nphy(pi, 0); ++ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { ++ switch (chan_freq_range) { ++ case WL_CHAN_FREQ_RANGE_5GL: ++ aux_adc_vmid[3] = 0x89; ++ aux_adc_gain[3] = 0; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GM: ++ aux_adc_vmid[3] = 0x89; ++ aux_adc_gain[3] = 0; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GH: ++ aux_adc_vmid[3] = 0x89; ++ aux_adc_gain[3] = 0; ++ break; ++ default: ++ break; ++ } ++ } ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x08, 16, aux_adc_vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x18, 16, aux_adc_vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x0c, 16, aux_adc_gain); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x1c, 16, aux_adc_gain); ++ } else if (pdetrange == 1) { ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x08, 16, sk_adc_vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x18, 16, sk_adc_vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x0c, 16, sk_adc_gain); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x1c, 16, sk_adc_gain); ++ } else if (pdetrange == 2) { ++ ++ u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x74 }; ++ u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x04 }; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 6)) { ++ chan_freq_range = ++ wlc_phy_get_chan_freq_range_nphy(pi, 0); ++ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { ++ bcm_adc_vmid[3] = 0x8e; ++ bcm_adc_gain[3] = 0x03; ++ } else { ++ bcm_adc_vmid[3] = 0x94; ++ bcm_adc_gain[3] = 0x03; ++ } ++ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { ++ bcm_adc_vmid[3] = 0x84; ++ bcm_adc_gain[3] = 0x02; ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x08, 16, bcm_adc_vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x18, 16, bcm_adc_vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x0c, 16, bcm_adc_gain); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x1c, 16, bcm_adc_gain); ++ } else if (pdetrange == 3) { ++ chan_freq_range = ++ wlc_phy_get_chan_freq_range_nphy(pi, 0); ++ if ((NREV_GE(pi->pubpi.phy_rev, 4)) ++ && (chan_freq_range == WL_CHAN_FREQ_RANGE_2G)) { ++ ++ u16 auxadc_vmid[] = { ++ 0xa2, 0xb4, 0xb4, 0x270 ++ }; ++ u16 auxadc_gain[] = { ++ 0x02, 0x02, 0x02, 0x00 ++ }; ++ ++ wlc_phy_table_write_nphy(pi, ++ NPHY_TBL_ID_AFECTRL, 4, ++ 0x08, 16, auxadc_vmid); ++ wlc_phy_table_write_nphy(pi, ++ NPHY_TBL_ID_AFECTRL, 4, ++ 0x18, 16, auxadc_vmid); ++ wlc_phy_table_write_nphy(pi, ++ NPHY_TBL_ID_AFECTRL, 4, ++ 0x0c, 16, auxadc_gain); ++ wlc_phy_table_write_nphy(pi, ++ NPHY_TBL_ID_AFECTRL, 4, ++ 0x1c, 16, auxadc_gain); ++ } ++ } else if ((pdetrange == 4) || (pdetrange == 5)) { ++ u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x0 }; ++ u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x0 }; ++ u16 Vmid[2], Av[2]; ++ ++ chan_freq_range = ++ wlc_phy_get_chan_freq_range_nphy(pi, 0); ++ if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) { ++ Vmid[0] = (pdetrange == 4) ? 0x8e : 0x89; ++ Vmid[1] = (pdetrange == 4) ? 0x96 : 0x89; ++ Av[0] = (pdetrange == 4) ? 2 : 0; ++ Av[1] = (pdetrange == 4) ? 2 : 0; ++ } else { ++ Vmid[0] = (pdetrange == 4) ? 0x89 : 0x74; ++ Vmid[1] = (pdetrange == 4) ? 0x8b : 0x70; ++ Av[0] = (pdetrange == 4) ? 2 : 0; ++ Av[1] = (pdetrange == 4) ? 2 : 0; ++ } ++ ++ bcm_adc_vmid[3] = Vmid[0]; ++ bcm_adc_gain[3] = Av[0]; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x08, 16, bcm_adc_vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x0c, 16, bcm_adc_gain); ++ ++ bcm_adc_vmid[3] = Vmid[1]; ++ bcm_adc_gain[3] = Av[1]; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x18, 16, bcm_adc_vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, ++ 0x1c, 16, bcm_adc_gain); ++ } ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX0), ++ 0x0); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX1), ++ 0x0); ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX0), ++ 0x6); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX1), ++ 0x6); ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX0), ++ 0x7); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX1), ++ 0x7); ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX0), ++ 0x88); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX1), ++ 0x88); ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX0), ++ 0x0); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX1), ++ 0x0); ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX0), ++ 0x0); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX1), ++ 0x0); ++ ++ triso = ++ (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g. ++ triso : pi->srom_fem2g.triso; ++ if (triso == 7) { ++ wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0); ++ wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1); ++ } ++ ++ wlc_phy_war_txchain_upd_nphy(pi, pi->sh->hw_phytxchain); ++ ++ if (((pi->sh->boardflags2 & BFL2_APLL_WAR) && ++ (CHSPEC_IS5G(pi->radio_chanspec))) || ++ (((pi->sh->boardflags2 & BFL2_GPLL_WAR) || ++ (pi->sh->boardflags2 & BFL2_GPLL_WAR2)) && ++ (CHSPEC_IS2G(pi->radio_chanspec)))) { ++ nss1_data_weights = 0x00088888; ++ ht_data_weights = 0x00088888; ++ stbc_data_weights = 0x00088888; ++ } else { ++ nss1_data_weights = 0x88888888; ++ ht_data_weights = 0x88888888; ++ stbc_data_weights = 0x88888888; ++ } ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, ++ 1, 1, 32, &nss1_data_weights); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, ++ 1, 2, 32, &ht_data_weights); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL, ++ 1, 3, 32, &stbc_data_weights); ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 4)) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ write_radio_reg(pi, ++ RADIO_2056_TX_GMBB_IDAC | ++ RADIO_2056_TX0, 0x70); ++ write_radio_reg(pi, ++ RADIO_2056_TX_GMBB_IDAC | ++ RADIO_2056_TX1, 0x70); ++ } ++ } ++ ++ if (!pi->edcrs_threshold_lock) { ++ write_phy_reg(pi, 0x224, 0x3eb); ++ write_phy_reg(pi, 0x225, 0x3eb); ++ write_phy_reg(pi, 0x226, 0x341); ++ write_phy_reg(pi, 0x227, 0x341); ++ write_phy_reg(pi, 0x228, 0x42b); ++ write_phy_reg(pi, 0x229, 0x42b); ++ write_phy_reg(pi, 0x22a, 0x381); ++ write_phy_reg(pi, 0x22b, 0x381); ++ write_phy_reg(pi, 0x22c, 0x42b); ++ write_phy_reg(pi, 0x22d, 0x42b); ++ write_phy_reg(pi, 0x22e, 0x381); ++ write_phy_reg(pi, 0x22f, 0x381); ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 6)) { ++ ++ if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK) ++ wlapi_bmac_mhf(pi->sh->physhim, MHF4, ++ MHF4_BPHY_TXCORE0, ++ MHF4_BPHY_TXCORE0, BRCM_BAND_ALL); ++ } ++ } else { ++ ++ if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD || ++ (pi->sh->boardtype == 0x8b)) { ++ uint i; ++ u8 war_dlys[] = { 1, 6, 6, 2, 4, 20, 1 }; ++ for (i = 0; i < ARRAY_SIZE(rfseq_rx2tx_dlys); i++) ++ rfseq_rx2tx_dlys[i] = war_dlys[i]; ++ } ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec) && pi->phy_5g_pwrgain) { ++ and_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0xf7); ++ and_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0xf7); ++ } else { ++ or_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0x8); ++ or_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0x8); ++ } ++ ++ regval = 0x000a; ++ wlc_phy_table_write_nphy(pi, 8, 1, 0, 16, ®val); ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x10, 16, ®val); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) { ++ regval = 0xcdaa; ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x02, 16, ®val); ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x12, 16, ®val); ++ } ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) { ++ regval = 0x0000; ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x08, 16, ®val); ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x18, 16, ®val); ++ ++ regval = 0x7aab; ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x07, 16, ®val); ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x17, 16, ®val); ++ ++ regval = 0x0800; ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x06, 16, ®val); ++ wlc_phy_table_write_nphy(pi, 8, 1, 0x16, 16, ®val); ++ } ++ ++ write_phy_reg(pi, 0xf8, 0x02d8); ++ write_phy_reg(pi, 0xf9, 0x0301); ++ write_phy_reg(pi, 0xfa, 0x02d8); ++ write_phy_reg(pi, 0xfb, 0x0301); ++ ++ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, rfseq_rx2tx_events, ++ rfseq_rx2tx_dlys, ++ sizeof(rfseq_rx2tx_events) / ++ sizeof(rfseq_rx2tx_events[0])); ++ ++ wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, rfseq_tx2rx_events, ++ rfseq_tx2rx_dlys, ++ sizeof(rfseq_tx2rx_events) / ++ sizeof(rfseq_tx2rx_events[0])); ++ ++ wlc_phy_workarounds_nphy_gainctrl(pi); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) { ++ ++ if (read_phy_reg(pi, 0xa0) & NPHY_MLenable) ++ wlapi_bmac_mhf(pi->sh->physhim, MHF3, ++ MHF3_NPHY_MLADV_WAR, ++ MHF3_NPHY_MLADV_WAR, ++ BRCM_BAND_ALL); ++ ++ } else if (NREV_IS(pi->pubpi.phy_rev, 2)) { ++ write_phy_reg(pi, 0x1e3, 0x0); ++ write_phy_reg(pi, 0x1e4, 0x0); ++ } ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) ++ mod_phy_reg(pi, 0x90, (0x1 << 7), 0); ++ ++ alpha0 = 293; ++ alpha1 = 435; ++ alpha2 = 261; ++ beta0 = 366; ++ beta1 = 205; ++ beta2 = 32; ++ write_phy_reg(pi, 0x145, alpha0); ++ write_phy_reg(pi, 0x146, alpha1); ++ write_phy_reg(pi, 0x147, alpha2); ++ write_phy_reg(pi, 0x148, beta0); ++ write_phy_reg(pi, 0x149, beta1); ++ write_phy_reg(pi, 0x14a, beta2); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) { ++ mod_phy_reg(pi, 0x142, (0xf << 12), 0); ++ ++ write_phy_reg(pi, 0x192, 0xb5); ++ write_phy_reg(pi, 0x193, 0xa4); ++ write_phy_reg(pi, 0x194, 0x0); ++ } ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 2)) ++ mod_phy_reg(pi, 0x221, ++ NPHY_FORCESIG_DECODEGATEDCLKS, ++ NPHY_FORCESIG_DECODEGATEDCLKS); ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static void wlc_phy_extpa_set_tx_digi_filts_nphy(struct brcms_phy *pi) ++{ ++ int j, type = 2; ++ u16 addr_offset = 0x2c5; ++ ++ for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) ++ write_phy_reg(pi, addr_offset + j, ++ NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]); ++} ++ ++static void wlc_phy_clip_det_nphy(struct brcms_phy *pi, u8 write, u16 *vals) ++{ ++ ++ if (write == 0) { ++ vals[0] = read_phy_reg(pi, 0x2c); ++ vals[1] = read_phy_reg(pi, 0x42); ++ } else { ++ write_phy_reg(pi, 0x2c, vals[0]); ++ write_phy_reg(pi, 0x42, vals[1]); ++ } ++} ++ ++static void wlc_phy_ipa_internal_tssi_setup_nphy(struct brcms_phy *pi) ++{ ++ u8 core; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MASTER, 0x5); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MUX, 0xe); ++ ++ if (pi->pubpi.radiorev != 5) ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, ++ core, TSSIA, 0); ++ ++ if (!NREV_IS(pi->pubpi.phy_rev, 7)) ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, ++ core, TSSIG, 0x1); ++ else ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, ++ core, TSSIG, 0x31); ++ } else { ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MASTER, 0x9); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MUX, 0xc); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSIG, 0); ++ ++ if (pi->pubpi.radiorev != 5) { ++ if (!NREV_IS(pi->pubpi.phy_rev, 7)) ++ WRITE_RADIO_REG3(pi, RADIO_2057, ++ TX, core, ++ TSSIA, 0x1); ++ else ++ WRITE_RADIO_REG3(pi, RADIO_2057, ++ TX, core, ++ TSSIA, 0x31); ++ } ++ } ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG, ++ 0); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC, ++ 0); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM, ++ 0x3); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1, ++ 0x0); ++ } ++ } else { ++ WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR31, ++ (CHSPEC_IS2G(pi->radio_chanspec)) ? 0x128 : ++ 0x80); ++ WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR30, 0x0); ++ WRITE_RADIO_SYN(pi, RADIO_2056, GPIO_MASTER1, 0x29); ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_VCM_HG, ++ 0x0); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_IDAC, ++ 0x0); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_VCM, ++ 0x3); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TX_AMP_DET, ++ 0x0); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC1, ++ 0x8); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC2, ++ 0x0); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC3, ++ 0x0); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ TX_SSI_MASTER, 0x5); ++ ++ if (pi->pubpi.radiorev != 5) ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, ++ core, TSSIA, 0x0); ++ if (NREV_GE(pi->pubpi.phy_rev, 5)) ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, ++ core, TSSIG, 0x31); ++ else ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, ++ core, TSSIG, 0x11); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ TX_SSI_MUX, 0xe); ++ } else { ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ TX_SSI_MASTER, 0x9); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ TSSIA, 0x31); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ TSSIG, 0x0); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ TX_SSI_MUX, 0xc); ++ } ++ } ++ } ++} ++ ++static void ++wlc_phy_rfctrl_override_nphy(struct brcms_phy *pi, u16 field, u16 value, ++ u8 core_mask, u8 off) ++{ ++ u8 core_num; ++ u16 addr = 0, mask = 0, en_addr = 0, val_addr = 0, en_mask = ++ 0, val_mask = 0; ++ u8 shift = 0, val_shift = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) { ++ ++ en_mask = field; ++ for (core_num = 0; core_num < 2; core_num++) { ++ ++ switch (field) { ++ case (0x1 << 1): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x1 << 0); ++ val_shift = 0; ++ break; ++ case (0x1 << 2): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x1 << 1); ++ val_shift = 1; ++ break; ++ case (0x1 << 3): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x1 << 2); ++ val_shift = 2; ++ break; ++ case (0x1 << 4): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x1 << 4); ++ val_shift = 4; ++ break; ++ case (0x1 << 5): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x1 << 5); ++ val_shift = 5; ++ break; ++ case (0x1 << 6): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x1 << 6); ++ val_shift = 6; ++ break; ++ case (0x1 << 7): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x1 << 7); ++ val_shift = 7; ++ break; ++ case (0x1 << 8): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x7 << 8); ++ val_shift = 8; ++ break; ++ case (0x1 << 11): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7a : 0x7d; ++ val_mask = (0x7 << 13); ++ val_shift = 13; ++ break; ++ ++ case (0x1 << 9): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0xf8 : 0xfa; ++ val_mask = (0x7 << 0); ++ val_shift = 0; ++ break; ++ ++ case (0x1 << 10): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0xf8 : 0xfa; ++ val_mask = (0x7 << 4); ++ val_shift = 4; ++ break; ++ ++ case (0x1 << 12): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7b : 0x7e; ++ val_mask = (0xffff << 0); ++ val_shift = 0; ++ break; ++ case (0x1 << 13): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0x7c : 0x7f; ++ val_mask = (0xffff << 0); ++ val_shift = 0; ++ break; ++ case (0x1 << 14): ++ en_addr = (core_num == 0) ? 0xe7 : 0xec; ++ val_addr = (core_num == 0) ? 0xf9 : 0xfb; ++ val_mask = (0x3 << 6); ++ val_shift = 6; ++ break; ++ case (0x1 << 0): ++ en_addr = (core_num == 0) ? 0xe5 : 0xe6; ++ val_addr = (core_num == 0) ? 0xf9 : 0xfb; ++ val_mask = (0x1 << 15); ++ val_shift = 15; ++ break; ++ default: ++ addr = 0xffff; ++ break; ++ } ++ ++ if (off) { ++ and_phy_reg(pi, en_addr, ~en_mask); ++ and_phy_reg(pi, val_addr, ~val_mask); ++ } else { ++ ++ if ((core_mask == 0) ++ || (core_mask & (1 << core_num))) { ++ or_phy_reg(pi, en_addr, en_mask); ++ ++ if (addr != 0xffff) ++ mod_phy_reg(pi, val_addr, ++ val_mask, ++ (value << ++ val_shift)); ++ } ++ } ++ } ++ } else { ++ ++ if (off) { ++ and_phy_reg(pi, 0xec, ~field); ++ value = 0x0; ++ } else { ++ or_phy_reg(pi, 0xec, field); ++ } ++ ++ for (core_num = 0; core_num < 2; core_num++) { ++ ++ switch (field) { ++ case (0x1 << 1): ++ case (0x1 << 9): ++ case (0x1 << 12): ++ case (0x1 << 13): ++ case (0x1 << 14): ++ addr = 0x78; ++ ++ core_mask = 0x1; ++ break; ++ case (0x1 << 2): ++ case (0x1 << 3): ++ case (0x1 << 4): ++ case (0x1 << 5): ++ case (0x1 << 6): ++ case (0x1 << 7): ++ case (0x1 << 8): ++ addr = (core_num == 0) ? 0x7a : 0x7d; ++ break; ++ case (0x1 << 10): ++ addr = (core_num == 0) ? 0x7b : 0x7e; ++ break; ++ case (0x1 << 11): ++ addr = (core_num == 0) ? 0x7c : 0x7f; ++ break; ++ default: ++ addr = 0xffff; ++ } ++ ++ switch (field) { ++ case (0x1 << 1): ++ mask = (0x7 << 3); ++ shift = 3; ++ break; ++ case (0x1 << 9): ++ mask = (0x1 << 2); ++ shift = 2; ++ break; ++ case (0x1 << 12): ++ mask = (0x1 << 8); ++ shift = 8; ++ break; ++ case (0x1 << 13): ++ mask = (0x1 << 9); ++ shift = 9; ++ break; ++ case (0x1 << 14): ++ mask = (0xf << 12); ++ shift = 12; ++ break; ++ case (0x1 << 2): ++ mask = (0x1 << 0); ++ shift = 0; ++ break; ++ case (0x1 << 3): ++ mask = (0x1 << 1); ++ shift = 1; ++ break; ++ case (0x1 << 4): ++ mask = (0x1 << 2); ++ shift = 2; ++ break; ++ case (0x1 << 5): ++ mask = (0x3 << 4); ++ shift = 4; ++ break; ++ case (0x1 << 6): ++ mask = (0x3 << 6); ++ shift = 6; ++ break; ++ case (0x1 << 7): ++ mask = (0x1 << 8); ++ shift = 8; ++ break; ++ case (0x1 << 8): ++ mask = (0x1 << 9); ++ shift = 9; ++ break; ++ case (0x1 << 10): ++ mask = 0x1fff; ++ shift = 0x0; ++ break; ++ case (0x1 << 11): ++ mask = 0x1fff; ++ shift = 0x0; ++ break; ++ default: ++ mask = 0x0; ++ shift = 0x0; ++ break; ++ } ++ ++ if ((addr != 0xffff) && (core_mask & (1 << core_num))) ++ mod_phy_reg(pi, addr, mask, (value << shift)); ++ } ++ ++ or_phy_reg(pi, 0xec, (0x1 << 0)); ++ or_phy_reg(pi, 0x78, (0x1 << 0)); ++ udelay(1); ++ and_phy_reg(pi, 0xec, ~(0x1 << 0)); ++ } ++} ++ ++static void wlc_phy_txpwrctrl_idle_tssi_nphy(struct brcms_phy *pi) ++{ ++ s32 rssi_buf[4]; ++ s32 int_val; ++ ++ if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) || PHY_MUTED(pi)) ++ ++ return; ++ ++ if (PHY_IPA(pi)) ++ wlc_phy_ipa_internal_tssi_setup_nphy(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), ++ 0, 0x3, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ else if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 0); ++ ++ wlc_phy_stopplayback_nphy(pi); ++ ++ wlc_phy_tx_tone_nphy(pi, 4000, 0, 0, 0, false); ++ ++ udelay(20); ++ int_val = ++ wlc_phy_poll_rssi_nphy(pi, (u8) NPHY_RSSI_SEL_TSSI_2G, rssi_buf, ++ 1); ++ wlc_phy_stopplayback_nphy(pi); ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, 0); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), ++ 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ else if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 1); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g = ++ (u8) ((int_val >> 24) & 0xff); ++ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g = ++ (u8) ((int_val >> 24) & 0xff); ++ ++ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g = ++ (u8) ((int_val >> 8) & 0xff); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g = ++ (u8) ((int_val >> 8) & 0xff); ++ } else { ++ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g = ++ (u8) ((int_val >> 24) & 0xff); ++ ++ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g = ++ (u8) ((int_val >> 8) & 0xff); ++ ++ pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g = ++ (u8) ((int_val >> 16) & 0xff); ++ pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g = ++ (u8) ((int_val) & 0xff); ++ } ++ ++} ++ ++static void wlc_phy_txpwr_limit_to_tbl_nphy(struct brcms_phy *pi) ++{ ++ u8 idx, idx2, i, delta_ind; ++ ++ for (idx = TXP_FIRST_CCK; idx <= TXP_LAST_CCK; idx++) ++ pi->adj_pwr_tbl_nphy[idx] = pi->tx_power_offset[idx]; ++ ++ for (i = 0; i < 4; i++) { ++ idx2 = 0; ++ ++ delta_ind = 0; ++ ++ switch (i) { ++ case 0: ++ ++ if (CHSPEC_IS40(pi->radio_chanspec) ++ && NPHY_IS_SROM_REINTERPRET) { ++ idx = TXP_FIRST_MCS_40_SISO; ++ } else { ++ idx = (CHSPEC_IS40(pi->radio_chanspec)) ? ++ TXP_FIRST_OFDM_40_SISO : TXP_FIRST_OFDM; ++ delta_ind = 1; ++ } ++ break; ++ ++ case 1: ++ ++ idx = (CHSPEC_IS40(pi->radio_chanspec)) ? ++ TXP_FIRST_MCS_40_CDD : TXP_FIRST_MCS_20_CDD; ++ break; ++ ++ case 2: ++ ++ idx = (CHSPEC_IS40(pi->radio_chanspec)) ? ++ TXP_FIRST_MCS_40_STBC : TXP_FIRST_MCS_20_STBC; ++ break; ++ ++ case 3: ++ ++ idx = (CHSPEC_IS40(pi->radio_chanspec)) ? ++ TXP_FIRST_MCS_40_SDM : TXP_FIRST_MCS_20_SDM; ++ break; ++ } ++ ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ idx = idx + delta_ind; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx++]; ++ ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx++]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx++]; ++ ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx++]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx++]; ++ ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx++]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ idx = idx + 1 - delta_ind; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] = ++ pi->tx_power_offset[idx]; ++ } ++} ++ ++static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) ++{ ++ u32 idx; ++ s16 a1[2], b0[2], b1[2]; ++ s8 target_pwr_qtrdbm[2]; ++ s32 num, den, pwr_est; ++ u8 chan_freq_range; ++ u8 idle_tssi[2]; ++ u32 tbl_id, tbl_len, tbl_offset; ++ u32 regval[64]; ++ u8 core; ++ ++ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) { ++ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK); ++ (void)R_REG(&pi->regs->maccontrol); ++ udelay(1); ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ or_phy_reg(pi, 0x122, (0x1 << 0)); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ and_phy_reg(pi, 0x1e7, (u16) (~(0x1 << 15))); ++ else ++ or_phy_reg(pi, 0x1e7, (0x1 << 15)); ++ ++ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) ++ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0); ++ ++ if (pi->sh->sromrev < 4) { ++ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g; ++ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g; ++ target_pwr_qtrdbm[0] = 13 * 4; ++ target_pwr_qtrdbm[1] = 13 * 4; ++ a1[0] = -424; ++ a1[1] = -424; ++ b0[0] = 5612; ++ b0[1] = 5612; ++ b1[1] = -1393; ++ b1[0] = -1393; ++ } else { ++ ++ chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0); ++ switch (chan_freq_range) { ++ case WL_CHAN_FREQ_RANGE_2G: ++ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g; ++ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g; ++ target_pwr_qtrdbm[0] = ++ pi->nphy_pwrctrl_info[0].max_pwr_2g; ++ target_pwr_qtrdbm[1] = ++ pi->nphy_pwrctrl_info[1].max_pwr_2g; ++ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_a1; ++ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_a1; ++ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b0; ++ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b0; ++ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b1; ++ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b1; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GL: ++ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; ++ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; ++ target_pwr_qtrdbm[0] = ++ pi->nphy_pwrctrl_info[0].max_pwr_5gl; ++ target_pwr_qtrdbm[1] = ++ pi->nphy_pwrctrl_info[1].max_pwr_5gl; ++ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1; ++ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1; ++ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0; ++ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0; ++ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1; ++ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GM: ++ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; ++ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; ++ target_pwr_qtrdbm[0] = ++ pi->nphy_pwrctrl_info[0].max_pwr_5gm; ++ target_pwr_qtrdbm[1] = ++ pi->nphy_pwrctrl_info[1].max_pwr_5gm; ++ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_a1; ++ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_a1; ++ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b0; ++ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b0; ++ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b1; ++ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b1; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GH: ++ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; ++ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; ++ target_pwr_qtrdbm[0] = ++ pi->nphy_pwrctrl_info[0].max_pwr_5gh; ++ target_pwr_qtrdbm[1] = ++ pi->nphy_pwrctrl_info[1].max_pwr_5gh; ++ a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1; ++ a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1; ++ b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0; ++ b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0; ++ b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1; ++ b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1; ++ break; ++ default: ++ idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g; ++ idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g; ++ target_pwr_qtrdbm[0] = 13 * 4; ++ target_pwr_qtrdbm[1] = 13 * 4; ++ a1[0] = -424; ++ a1[1] = -424; ++ b0[0] = 5612; ++ b0[1] = 5612; ++ b1[1] = -1393; ++ b1[0] = -1393; ++ break; ++ } ++ } ++ ++ target_pwr_qtrdbm[0] = (s8) pi->tx_power_max; ++ target_pwr_qtrdbm[1] = (s8) pi->tx_power_max; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (pi->srom_fem2g.tssipos) ++ or_phy_reg(pi, 0x1e9, (0x1 << 14)); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ for (core = 0; core <= 1; core++) { ++ if (PHY_IPA(pi)) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ WRITE_RADIO_REG3(pi, RADIO_2057, ++ TX, core, ++ TX_SSI_MUX, ++ 0xe); ++ else ++ WRITE_RADIO_REG3(pi, RADIO_2057, ++ TX, core, ++ TX_SSI_MUX, ++ 0xc); ++ } ++ } ++ } else { ++ if (PHY_IPA(pi)) { ++ ++ write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX | ++ RADIO_2056_TX0, ++ (CHSPEC_IS5G ++ (pi->radio_chanspec)) ? ++ 0xc : 0xe); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MUX | ++ RADIO_2056_TX1, ++ (CHSPEC_IS5G ++ (pi->radio_chanspec)) ? ++ 0xc : 0xe); ++ } else { ++ ++ write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX | ++ RADIO_2056_TX0, 0x11); ++ write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX | ++ RADIO_2056_TX1, 0x11); ++ } ++ } ++ } ++ ++ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) { ++ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK); ++ (void)R_REG(&pi->regs->maccontrol); ++ udelay(1); ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ mod_phy_reg(pi, 0x1e7, (0x7f << 0), ++ (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0)); ++ else ++ mod_phy_reg(pi, 0x1e7, (0x7f << 0), ++ (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0)); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ mod_phy_reg(pi, 0x222, (0xff << 0), ++ (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0)); ++ else if (NREV_GT(pi->pubpi.phy_rev, 1)) ++ mod_phy_reg(pi, 0x222, (0xff << 0), ++ (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0)); ++ ++ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) ++ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0); ++ ++ write_phy_reg(pi, 0x1e8, (0x3 << 8) | (240 << 0)); ++ ++ write_phy_reg(pi, 0x1e9, ++ (1 << 15) | (idle_tssi[0] << 0) | (idle_tssi[1] << 8)); ++ ++ write_phy_reg(pi, 0x1ea, ++ (target_pwr_qtrdbm[0] << 0) | ++ (target_pwr_qtrdbm[1] << 8)); ++ ++ tbl_len = 64; ++ tbl_offset = 0; ++ for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL; ++ tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) { ++ ++ for (idx = 0; idx < tbl_len; idx++) { ++ num = 8 * ++ (16 * b0[tbl_id - 26] + b1[tbl_id - 26] * idx); ++ den = 32768 + a1[tbl_id - 26] * idx; ++ pwr_est = max(((4 * num + den / 2) / den), -8); ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) { ++ if (idx <= ++ (uint) (31 - idle_tssi[tbl_id - 26] + 1)) ++ pwr_est = ++ max(pwr_est, ++ target_pwr_qtrdbm ++ [tbl_id - 26] + 1); ++ } ++ regval[idx] = (u32) pwr_est; ++ } ++ wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32, ++ regval); ++ } ++ ++ wlc_phy_txpwr_limit_to_tbl_nphy(pi); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64, 8, ++ pi->adj_pwr_tbl_nphy); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64, 8, ++ pi->adj_pwr_tbl_nphy); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static u32 *wlc_phy_get_ipa_gaintbl_nphy(struct brcms_phy *pi) ++{ ++ u32 *tx_pwrctrl_tbl = NULL; ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if ((pi->pubpi.radiorev == 4) ++ || (pi->pubpi.radiorev == 6)) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_ipa_2g_2057rev4n6; ++ else if (pi->pubpi.radiorev == 3) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_ipa_2g_2057rev3; ++ else if (pi->pubpi.radiorev == 5) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_ipa_2g_2057rev5; ++ else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_ipa_2g_2057rev7; ++ } else if (NREV_IS(pi->pubpi.phy_rev, 6)) { ++ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6; ++ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { ++ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5; ++ } else { ++ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa; ++ } ++ } else { ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if ((pi->pubpi.radiorev == 3) || ++ (pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) ++ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g_2057; ++ else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_ipa_5g_2057rev7; ++ } else { ++ tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g; ++ } ++ } ++ ++ return tx_pwrctrl_tbl; ++} ++ ++static void wlc_phy_restore_rssical_nphy(struct brcms_phy *pi) ++{ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (pi->nphy_rssical_chanspec_2G == 0) ++ return; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0, ++ RADIO_2057_VCM_MASK, ++ pi->rssical_cache. ++ rssical_radio_regs_2G[0]); ++ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1, ++ RADIO_2057_VCM_MASK, ++ pi->rssical_cache. ++ rssical_radio_regs_2G[1]); ++ } else { ++ mod_radio_reg(pi, ++ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0, ++ RADIO_2056_VCM_MASK, ++ pi->rssical_cache. ++ rssical_radio_regs_2G[0]); ++ mod_radio_reg(pi, ++ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1, ++ RADIO_2056_VCM_MASK, ++ pi->rssical_cache. ++ rssical_radio_regs_2G[1]); ++ } ++ ++ write_phy_reg(pi, 0x1a6, ++ pi->rssical_cache.rssical_phyregs_2G[0]); ++ write_phy_reg(pi, 0x1ac, ++ pi->rssical_cache.rssical_phyregs_2G[1]); ++ write_phy_reg(pi, 0x1b2, ++ pi->rssical_cache.rssical_phyregs_2G[2]); ++ write_phy_reg(pi, 0x1b8, ++ pi->rssical_cache.rssical_phyregs_2G[3]); ++ write_phy_reg(pi, 0x1a4, ++ pi->rssical_cache.rssical_phyregs_2G[4]); ++ write_phy_reg(pi, 0x1aa, ++ pi->rssical_cache.rssical_phyregs_2G[5]); ++ write_phy_reg(pi, 0x1b0, ++ pi->rssical_cache.rssical_phyregs_2G[6]); ++ write_phy_reg(pi, 0x1b6, ++ pi->rssical_cache.rssical_phyregs_2G[7]); ++ write_phy_reg(pi, 0x1a5, ++ pi->rssical_cache.rssical_phyregs_2G[8]); ++ write_phy_reg(pi, 0x1ab, ++ pi->rssical_cache.rssical_phyregs_2G[9]); ++ write_phy_reg(pi, 0x1b1, ++ pi->rssical_cache.rssical_phyregs_2G[10]); ++ write_phy_reg(pi, 0x1b7, ++ pi->rssical_cache.rssical_phyregs_2G[11]); ++ ++ } else { ++ if (pi->nphy_rssical_chanspec_5G == 0) ++ return; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0, ++ RADIO_2057_VCM_MASK, ++ pi->rssical_cache. ++ rssical_radio_regs_5G[0]); ++ mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1, ++ RADIO_2057_VCM_MASK, ++ pi->rssical_cache. ++ rssical_radio_regs_5G[1]); ++ } else { ++ mod_radio_reg(pi, ++ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0, ++ RADIO_2056_VCM_MASK, ++ pi->rssical_cache. ++ rssical_radio_regs_5G[0]); ++ mod_radio_reg(pi, ++ RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1, ++ RADIO_2056_VCM_MASK, ++ pi->rssical_cache. ++ rssical_radio_regs_5G[1]); ++ } ++ ++ write_phy_reg(pi, 0x1a6, ++ pi->rssical_cache.rssical_phyregs_5G[0]); ++ write_phy_reg(pi, 0x1ac, ++ pi->rssical_cache.rssical_phyregs_5G[1]); ++ write_phy_reg(pi, 0x1b2, ++ pi->rssical_cache.rssical_phyregs_5G[2]); ++ write_phy_reg(pi, 0x1b8, ++ pi->rssical_cache.rssical_phyregs_5G[3]); ++ write_phy_reg(pi, 0x1a4, ++ pi->rssical_cache.rssical_phyregs_5G[4]); ++ write_phy_reg(pi, 0x1aa, ++ pi->rssical_cache.rssical_phyregs_5G[5]); ++ write_phy_reg(pi, 0x1b0, ++ pi->rssical_cache.rssical_phyregs_5G[6]); ++ write_phy_reg(pi, 0x1b6, ++ pi->rssical_cache.rssical_phyregs_5G[7]); ++ write_phy_reg(pi, 0x1a5, ++ pi->rssical_cache.rssical_phyregs_5G[8]); ++ write_phy_reg(pi, 0x1ab, ++ pi->rssical_cache.rssical_phyregs_5G[9]); ++ write_phy_reg(pi, 0x1b1, ++ pi->rssical_cache.rssical_phyregs_5G[10]); ++ write_phy_reg(pi, 0x1b7, ++ pi->rssical_cache.rssical_phyregs_5G[11]); ++ } ++} ++ ++static void wlc_phy_internal_cal_txgain_nphy(struct brcms_phy *pi) ++{ ++ u16 txcal_gain[2]; ++ ++ pi->nphy_txcal_pwr_idx[0] = pi->nphy_cal_orig_pwr_idx[0]; ++ pi->nphy_txcal_pwr_idx[1] = pi->nphy_cal_orig_pwr_idx[0]; ++ wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true); ++ wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, ++ txcal_gain); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F40; ++ txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F40; ++ } else { ++ txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F60; ++ txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F60; ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, ++ txcal_gain); ++} ++ ++static void wlc_phy_precal_txgain_nphy(struct brcms_phy *pi) ++{ ++ bool save_bbmult = false; ++ u8 txcal_index_2057_rev5n7 = 0; ++ u8 txcal_index_2057_rev3n4n6 = 10; ++ ++ if (pi->use_int_tx_iqlo_cal_nphy) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if ((pi->pubpi.radiorev == 3) || ++ (pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) { ++ ++ pi->nphy_txcal_pwr_idx[0] = ++ txcal_index_2057_rev3n4n6; ++ pi->nphy_txcal_pwr_idx[1] = ++ txcal_index_2057_rev3n4n6; ++ wlc_phy_txpwr_index_nphy( ++ pi, 3, ++ txcal_index_2057_rev3n4n6, ++ false); ++ } else { ++ ++ pi->nphy_txcal_pwr_idx[0] = ++ txcal_index_2057_rev5n7; ++ pi->nphy_txcal_pwr_idx[1] = ++ txcal_index_2057_rev5n7; ++ wlc_phy_txpwr_index_nphy( ++ pi, 3, ++ txcal_index_2057_rev5n7, ++ false); ++ } ++ save_bbmult = true; ++ ++ } else if (NREV_LT(pi->pubpi.phy_rev, 5)) { ++ wlc_phy_cal_txgainctrl_nphy(pi, 11, false); ++ if (pi->sh->hw_phytxchain != 3) { ++ pi->nphy_txcal_pwr_idx[1] = ++ pi->nphy_txcal_pwr_idx[0]; ++ wlc_phy_txpwr_index_nphy(pi, 3, ++ pi-> ++ nphy_txcal_pwr_idx[0], ++ true); ++ save_bbmult = true; ++ } ++ ++ } else if (NREV_IS(pi->pubpi.phy_rev, 5)) { ++ if (PHY_IPA(pi)) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ wlc_phy_cal_txgainctrl_nphy(pi, 12, ++ false); ++ } else { ++ pi->nphy_txcal_pwr_idx[0] = 80; ++ pi->nphy_txcal_pwr_idx[1] = 80; ++ wlc_phy_txpwr_index_nphy(pi, 3, 80, ++ false); ++ save_bbmult = true; ++ } ++ } else { ++ wlc_phy_internal_cal_txgain_nphy(pi); ++ save_bbmult = true; ++ } ++ ++ } else if (NREV_IS(pi->pubpi.phy_rev, 6)) { ++ if (PHY_IPA(pi)) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ wlc_phy_cal_txgainctrl_nphy(pi, 12, ++ false); ++ else ++ wlc_phy_cal_txgainctrl_nphy(pi, 14, ++ false); ++ } else { ++ wlc_phy_internal_cal_txgain_nphy(pi); ++ save_bbmult = true; ++ } ++ } ++ ++ } else { ++ wlc_phy_cal_txgainctrl_nphy(pi, 10, false); ++ } ++ ++ if (save_bbmult) ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, ++ &pi->nphy_txcal_bbmult); ++} ++ ++static void ++wlc_phy_rfctrlintc_override_nphy(struct brcms_phy *pi, u8 field, u16 value, ++ u8 core_code) ++{ ++ u16 mask; ++ u16 val; ++ u8 core; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ if (core_code == RADIO_MIMO_CORESEL_CORE1 ++ && core == PHY_CORE_1) ++ continue; ++ else if (core_code == RADIO_MIMO_CORESEL_CORE2 ++ && core == PHY_CORE_0) ++ continue; ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 7)) { ++ ++ mask = (0x1 << 10); ++ val = 1 << 10; ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 : ++ 0x92, mask, val); ++ } ++ ++ if (field == NPHY_RfctrlIntc_override_OFF) { ++ ++ write_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 : ++ 0x92, 0); ++ ++ wlc_phy_force_rfseq_nphy(pi, ++ NPHY_RFSEQ_RESET2RX); ++ } else if (field == NPHY_RfctrlIntc_override_TRSW) { ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ mask = (0x1 << 6) | (0x1 << 7); ++ ++ val = value << 6; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ mask, val); ++ ++ or_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ (0x1 << 10)); ++ ++ and_phy_reg(pi, 0x2ff, (u16) ++ ~(0x3 << 14)); ++ or_phy_reg(pi, 0x2ff, (0x1 << 13)); ++ or_phy_reg(pi, 0x2ff, (0x1 << 0)); ++ } else { ++ ++ mask = (0x1 << 6) | ++ (0x1 << 7) | ++ (0x1 << 8) | (0x1 << 9); ++ val = value << 6; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ mask, val); ++ ++ mask = (0x1 << 0); ++ val = 1 << 0; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xe7 : 0xec, ++ mask, val); ++ ++ mask = (core == PHY_CORE_0) ? ++ (0x1 << 0) : (0x1 << 1); ++ val = 1 << ((core == PHY_CORE_0) ? ++ 0 : 1); ++ mod_phy_reg(pi, 0x78, mask, val); ++ ++ SPINWAIT(((read_phy_reg(pi, 0x78) & val) ++ != 0), 10000); ++ if (WARN(read_phy_reg(pi, 0x78) & val, ++ "HW error: override failed")) ++ return; ++ ++ mask = (0x1 << 0); ++ val = 0 << 0; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xe7 : 0xec, ++ mask, val); ++ } ++ } else if (field == NPHY_RfctrlIntc_override_PA) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ mask = (0x1 << 4) | (0x1 << 5); ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) ++ val = value << 5; ++ else ++ val = value << 4; ++ ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ mask, val); ++ ++ or_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ (0x1 << 12)); ++ } else { ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ mask = (0x1 << 5); ++ val = value << 5; ++ } else { ++ mask = (0x1 << 4); ++ val = value << 4; ++ } ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ mask, val); ++ } ++ } else if (field == ++ NPHY_RfctrlIntc_override_EXT_LNA_PU) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ ++ mask = (0x1 << 0); ++ val = value << 0; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 ++ : 0x92, mask, val); ++ ++ mask = (0x1 << 2); ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 ++ : 0x92, mask, 0); ++ } else { ++ ++ mask = (0x1 << 2); ++ val = value << 2; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 ++ : 0x92, mask, val); ++ ++ mask = (0x1 << 0); ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 ++ : 0x92, mask, 0); ++ } ++ ++ mask = (0x1 << 11); ++ val = 1 << 11; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ mask, val); ++ } else { ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ mask = (0x1 << 0); ++ val = value << 0; ++ } else { ++ mask = (0x1 << 2); ++ val = value << 2; ++ } ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ mask, val); ++ } ++ } else if (field == ++ NPHY_RfctrlIntc_override_EXT_LNA_GAIN) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ ++ mask = (0x1 << 1); ++ val = value << 1; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 ++ : 0x92, mask, val); ++ ++ mask = (0x1 << 3); ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 ++ : 0x92, mask, 0); ++ } else { ++ ++ mask = (0x1 << 3); ++ val = value << 3; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 ++ : 0x92, mask, val); ++ ++ mask = (0x1 << 1); ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 ++ : 0x92, mask, 0); ++ } ++ ++ mask = (0x1 << 11); ++ val = 1 << 11; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ mask, val); ++ } else { ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ mask = (0x1 << 1); ++ val = value << 1; ++ } else { ++ mask = (0x1 << 3); ++ val = value << 3; ++ } ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x91 : 0x92, ++ mask, val); ++ } ++ } ++ } ++ } ++} ++ ++void ++wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, s32 dBm_targetpower, ++ bool debug) ++{ ++ int gainctrl_loopidx; ++ uint core; ++ u16 m0m1, curr_m0m1; ++ s32 delta_power; ++ s32 txpwrindex; ++ s32 qdBm_power[2]; ++ u16 orig_BBConfig; ++ u16 phy_saveregs[4]; ++ u32 freq_test; ++ u16 ampl_test = 250; ++ uint stepsize; ++ bool phyhang_avoid_state = false; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ stepsize = 2; ++ else ++ stepsize = 1; ++ ++ if (CHSPEC_IS40(pi->radio_chanspec)) ++ freq_test = 5000; ++ else ++ freq_test = 2500; ++ ++ wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true); ++ wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ phyhang_avoid_state = pi->phyhang_avoid; ++ pi->phyhang_avoid = false; ++ ++ phy_saveregs[0] = read_phy_reg(pi, 0x91); ++ phy_saveregs[1] = read_phy_reg(pi, 0x92); ++ phy_saveregs[2] = read_phy_reg(pi, 0xe7); ++ phy_saveregs[3] = read_phy_reg(pi, 0xec); ++ wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 1, ++ RADIO_MIMO_CORESEL_CORE1 | ++ RADIO_MIMO_CORESEL_CORE2); ++ ++ if (!debug) { ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ 0x2, RADIO_MIMO_CORESEL_CORE1); ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ 0x8, RADIO_MIMO_CORESEL_CORE2); ++ } else { ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ 0x1, RADIO_MIMO_CORESEL_CORE1); ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ 0x7, RADIO_MIMO_CORESEL_CORE2); ++ } ++ ++ orig_BBConfig = read_phy_reg(pi, 0x01); ++ mod_phy_reg(pi, 0x01, (0x1 << 15), 0); ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1); ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ txpwrindex = (s32) pi->nphy_cal_orig_pwr_idx[core]; ++ ++ for (gainctrl_loopidx = 0; gainctrl_loopidx < 2; ++ gainctrl_loopidx++) { ++ wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0, ++ false); ++ ++ if (core == PHY_CORE_0) ++ curr_m0m1 = m0m1 & 0xff00; ++ else ++ curr_m0m1 = m0m1 & 0x00ff; ++ ++ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &curr_m0m1); ++ wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &curr_m0m1); ++ ++ udelay(50); ++ ++ wlc_phy_est_tonepwr_nphy(pi, qdBm_power, ++ NPHY_CAL_TSSISAMPS); ++ ++ pi->nphy_bb_mult_save = 0; ++ wlc_phy_stopplayback_nphy(pi); ++ ++ delta_power = (dBm_targetpower * 4) - qdBm_power[core]; ++ ++ txpwrindex -= stepsize * delta_power; ++ if (txpwrindex < 0) ++ txpwrindex = 0; ++ else if (txpwrindex > 127) ++ txpwrindex = 127; ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (NREV_IS(pi->pubpi.phy_rev, 4) && ++ (pi->srom_fem5g.extpagain == 3)) { ++ if (txpwrindex < 30) ++ txpwrindex = 30; ++ } ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 5) && ++ (pi->srom_fem2g.extpagain == 3)) { ++ if (txpwrindex < 50) ++ txpwrindex = 50; ++ } ++ } ++ ++ wlc_phy_txpwr_index_nphy(pi, (1 << core), ++ (u8) txpwrindex, true); ++ } ++ ++ pi->nphy_txcal_pwr_idx[core] = (u8) txpwrindex; ++ ++ if (debug) { ++ u16 radio_gain; ++ u16 dbg_m0m1; ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &dbg_m0m1); ++ ++ wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0, ++ false); ++ ++ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &dbg_m0m1); ++ wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &dbg_m0m1); ++ ++ udelay(100); ++ ++ wlc_phy_est_tonepwr_nphy(pi, qdBm_power, ++ NPHY_CAL_TSSISAMPS); ++ ++ wlc_phy_table_read_nphy(pi, 7, 1, (0x110 + core), 16, ++ &radio_gain); ++ ++ mdelay(4000); ++ pi->nphy_bb_mult_save = 0; ++ wlc_phy_stopplayback_nphy(pi); ++ } ++ } ++ ++ wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_txcal_pwr_idx[0], true); ++ wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_txcal_pwr_idx[1], true); ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &pi->nphy_txcal_bbmult); ++ ++ write_phy_reg(pi, 0x01, orig_BBConfig); ++ ++ write_phy_reg(pi, 0x91, phy_saveregs[0]); ++ write_phy_reg(pi, 0x92, phy_saveregs[1]); ++ write_phy_reg(pi, 0xe7, phy_saveregs[2]); ++ write_phy_reg(pi, 0xec, phy_saveregs[3]); ++ ++ pi->phyhang_avoid = phyhang_avoid_state; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static void wlc_phy_savecal_nphy(struct brcms_phy *pi) ++{ ++ void *tbl_ptr; ++ int coreNum; ++ u16 *txcal_radio_regs = NULL; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ ++ wlc_phy_rx_iq_coeffs_nphy(pi, 0, ++ &pi->calibration_cache. ++ rxcal_coeffs_2G); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ txcal_radio_regs = ++ pi->calibration_cache.txcal_radio_regs_2G; ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ pi->calibration_cache.txcal_radio_regs_2G[0] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_I | ++ RADIO_2056_TX0); ++ pi->calibration_cache.txcal_radio_regs_2G[1] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_Q | ++ RADIO_2056_TX0); ++ pi->calibration_cache.txcal_radio_regs_2G[2] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_I | ++ RADIO_2056_TX1); ++ pi->calibration_cache.txcal_radio_regs_2G[3] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_Q | ++ RADIO_2056_TX1); ++ ++ pi->calibration_cache.txcal_radio_regs_2G[4] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_I | ++ RADIO_2056_TX0); ++ pi->calibration_cache.txcal_radio_regs_2G[5] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_Q | ++ RADIO_2056_TX0); ++ pi->calibration_cache.txcal_radio_regs_2G[6] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_I | ++ RADIO_2056_TX1); ++ pi->calibration_cache.txcal_radio_regs_2G[7] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_Q | ++ RADIO_2056_TX1); ++ } else { ++ pi->calibration_cache.txcal_radio_regs_2G[0] = ++ read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL); ++ pi->calibration_cache.txcal_radio_regs_2G[1] = ++ read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL); ++ pi->calibration_cache.txcal_radio_regs_2G[2] = ++ read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM); ++ pi->calibration_cache.txcal_radio_regs_2G[3] = ++ read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM); ++ } ++ ++ pi->nphy_iqcal_chanspec_2G = pi->radio_chanspec; ++ tbl_ptr = pi->calibration_cache.txcal_coeffs_2G; ++ } else { ++ ++ wlc_phy_rx_iq_coeffs_nphy(pi, 0, ++ &pi->calibration_cache. ++ rxcal_coeffs_5G); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ txcal_radio_regs = ++ pi->calibration_cache.txcal_radio_regs_5G; ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ pi->calibration_cache.txcal_radio_regs_5G[0] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_I | ++ RADIO_2056_TX0); ++ pi->calibration_cache.txcal_radio_regs_5G[1] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_Q | ++ RADIO_2056_TX0); ++ pi->calibration_cache.txcal_radio_regs_5G[2] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_I | ++ RADIO_2056_TX1); ++ pi->calibration_cache.txcal_radio_regs_5G[3] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_Q | ++ RADIO_2056_TX1); ++ ++ pi->calibration_cache.txcal_radio_regs_5G[4] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_I | ++ RADIO_2056_TX0); ++ pi->calibration_cache.txcal_radio_regs_5G[5] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_Q | ++ RADIO_2056_TX0); ++ pi->calibration_cache.txcal_radio_regs_5G[6] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_I | ++ RADIO_2056_TX1); ++ pi->calibration_cache.txcal_radio_regs_5G[7] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_Q | ++ RADIO_2056_TX1); ++ } else { ++ pi->calibration_cache.txcal_radio_regs_5G[0] = ++ read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL); ++ pi->calibration_cache.txcal_radio_regs_5G[1] = ++ read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL); ++ pi->calibration_cache.txcal_radio_regs_5G[2] = ++ read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM); ++ pi->calibration_cache.txcal_radio_regs_5G[3] = ++ read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM); ++ } ++ ++ pi->nphy_iqcal_chanspec_5G = pi->radio_chanspec; ++ tbl_ptr = pi->calibration_cache.txcal_coeffs_5G; ++ } ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ for (coreNum = 0; coreNum <= 1; coreNum++) { ++ ++ txcal_radio_regs[2 * coreNum] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, ++ LOFT_FINE_I); ++ txcal_radio_regs[2 * coreNum + 1] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, ++ LOFT_FINE_Q); ++ ++ txcal_radio_regs[2 * coreNum + 4] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, ++ LOFT_COARSE_I); ++ txcal_radio_regs[2 * coreNum + 5] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum, ++ LOFT_COARSE_Q); ++ } ++ } ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 8, 80, 16, tbl_ptr); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static void wlc_phy_tx_iq_war_nphy(struct brcms_phy *pi) ++{ ++ struct nphy_iq_comp tx_comp; ++ ++ wlc_phy_table_read_nphy(pi, 15, 4, 0x50, 16, &tx_comp); ++ ++ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ, tx_comp.a0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 2, tx_comp.b0); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 4, tx_comp.a1); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 6, tx_comp.b1); ++} ++ ++static void wlc_phy_restorecal_nphy(struct brcms_phy *pi) ++{ ++ u16 *loft_comp; ++ u16 txcal_coeffs_bphy[4]; ++ u16 *tbl_ptr; ++ int coreNum; ++ u16 *txcal_radio_regs = NULL; ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (pi->nphy_iqcal_chanspec_2G == 0) ++ return; ++ ++ tbl_ptr = pi->calibration_cache.txcal_coeffs_2G; ++ loft_comp = &pi->calibration_cache.txcal_coeffs_2G[5]; ++ } else { ++ if (pi->nphy_iqcal_chanspec_5G == 0) ++ return; ++ ++ tbl_ptr = pi->calibration_cache.txcal_coeffs_5G; ++ loft_comp = &pi->calibration_cache.txcal_coeffs_5G[5]; ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, 16, tbl_ptr); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ txcal_coeffs_bphy[0] = tbl_ptr[0]; ++ txcal_coeffs_bphy[1] = tbl_ptr[1]; ++ txcal_coeffs_bphy[2] = tbl_ptr[2]; ++ txcal_coeffs_bphy[3] = tbl_ptr[3]; ++ } else { ++ txcal_coeffs_bphy[0] = 0; ++ txcal_coeffs_bphy[1] = 0; ++ txcal_coeffs_bphy[2] = 0; ++ txcal_coeffs_bphy[3] = 0; ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, 16, ++ txcal_coeffs_bphy); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, 16, loft_comp); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, 16, loft_comp); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) ++ wlc_phy_tx_iq_war_nphy(pi); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ txcal_radio_regs = ++ pi->calibration_cache.txcal_radio_regs_2G; ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_I | ++ RADIO_2056_TX0, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[0]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_Q | ++ RADIO_2056_TX0, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[1]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_I | ++ RADIO_2056_TX1, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[2]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_Q | ++ RADIO_2056_TX1, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[3]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_I | ++ RADIO_2056_TX0, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[4]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_Q | ++ RADIO_2056_TX0, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[5]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_I | ++ RADIO_2056_TX1, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[6]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_Q | ++ RADIO_2056_TX1, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[7]); ++ } else { ++ write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[0]); ++ write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[1]); ++ write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[2]); ++ write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, ++ pi->calibration_cache. ++ txcal_radio_regs_2G[3]); ++ } ++ ++ wlc_phy_rx_iq_coeffs_nphy(pi, 1, ++ &pi->calibration_cache. ++ rxcal_coeffs_2G); ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ txcal_radio_regs = ++ pi->calibration_cache.txcal_radio_regs_5G; ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_I | ++ RADIO_2056_TX0, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[0]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_Q | ++ RADIO_2056_TX0, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[1]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_I | ++ RADIO_2056_TX1, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[2]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_FINE_Q | ++ RADIO_2056_TX1, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[3]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_I | ++ RADIO_2056_TX0, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[4]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_Q | ++ RADIO_2056_TX0, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[5]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_I | ++ RADIO_2056_TX1, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[6]); ++ write_radio_reg(pi, ++ RADIO_2056_TX_LOFT_COARSE_Q | ++ RADIO_2056_TX1, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[7]); ++ } else { ++ write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[0]); ++ write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[1]); ++ write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[2]); ++ write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, ++ pi->calibration_cache. ++ txcal_radio_regs_5G[3]); ++ } ++ ++ wlc_phy_rx_iq_coeffs_nphy(pi, 1, ++ &pi->calibration_cache. ++ rxcal_coeffs_5G); ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ for (coreNum = 0; coreNum <= 1; coreNum++) { ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum, ++ LOFT_FINE_I, ++ txcal_radio_regs[2 * coreNum]); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum, ++ LOFT_FINE_Q, ++ txcal_radio_regs[2 * coreNum + 1]); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum, ++ LOFT_COARSE_I, ++ txcal_radio_regs[2 * coreNum + 4]); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum, ++ LOFT_COARSE_Q, ++ txcal_radio_regs[2 * coreNum + 5]); ++ } ++ } ++} ++ ++static void wlc_phy_txpwrctrl_coeff_setup_nphy(struct brcms_phy *pi) ++{ ++ u32 idx; ++ u16 iqloCalbuf[7]; ++ u32 iqcomp, locomp, curr_locomp; ++ s8 locomp_i, locomp_q; ++ s8 curr_locomp_i, curr_locomp_q; ++ u32 tbl_id, tbl_len, tbl_offset; ++ u32 regval[128]; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ wlc_phy_table_read_nphy(pi, 15, 7, 80, 16, iqloCalbuf); ++ ++ tbl_len = 128; ++ tbl_offset = 320; ++ for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL; ++ tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) { ++ iqcomp = ++ (tbl_id == ++ 26) ? (((u32) (iqloCalbuf[0] & 0x3ff)) << 10) | ++ (iqloCalbuf[1] & 0x3ff) ++ : (((u32) (iqloCalbuf[2] & 0x3ff)) << 10) | ++ (iqloCalbuf[3] & 0x3ff); ++ ++ for (idx = 0; idx < tbl_len; idx++) ++ regval[idx] = iqcomp; ++ wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32, ++ regval); ++ } ++ ++ tbl_offset = 448; ++ for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL; ++ tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) { ++ ++ locomp = ++ (u32) ((tbl_id == 26) ? iqloCalbuf[5] : iqloCalbuf[6]); ++ locomp_i = (s8) ((locomp >> 8) & 0xff); ++ locomp_q = (s8) ((locomp) & 0xff); ++ for (idx = 0; idx < tbl_len; idx++) { ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ curr_locomp_i = locomp_i; ++ curr_locomp_q = locomp_q; ++ } else { ++ curr_locomp_i = (s8) ((locomp_i * ++ nphy_tpc_loscale[idx] + ++ 128) >> 8); ++ curr_locomp_q = ++ (s8) ((locomp_q * ++ nphy_tpc_loscale[idx] + ++ 128) >> 8); ++ } ++ curr_locomp = (u32) ((curr_locomp_i & 0xff) << 8); ++ curr_locomp |= (u32) (curr_locomp_q & 0xff); ++ regval[idx] = curr_locomp; ++ } ++ wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32, ++ regval); ++ } ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) { ++ ++ wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX1, 0xFFFF); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX2, 0xFFFF); ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static void wlc_phy_txlpfbw_nphy(struct brcms_phy *pi) ++{ ++ u8 tx_lpf_bw = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) { ++ if (CHSPEC_IS40(pi->radio_chanspec)) ++ tx_lpf_bw = 3; ++ else ++ tx_lpf_bw = 1; ++ ++ if (PHY_IPA(pi)) { ++ if (CHSPEC_IS40(pi->radio_chanspec)) ++ tx_lpf_bw = 5; ++ else ++ tx_lpf_bw = 4; ++ } ++ ++ write_phy_reg(pi, 0xe8, ++ (tx_lpf_bw << 0) | ++ (tx_lpf_bw << 3) | ++ (tx_lpf_bw << 6) | (tx_lpf_bw << 9)); ++ ++ if (PHY_IPA(pi)) { ++ ++ if (CHSPEC_IS40(pi->radio_chanspec)) ++ tx_lpf_bw = 4; ++ else ++ tx_lpf_bw = 1; ++ ++ write_phy_reg(pi, 0xe9, ++ (tx_lpf_bw << 0) | ++ (tx_lpf_bw << 3) | ++ (tx_lpf_bw << 6) | (tx_lpf_bw << 9)); ++ } ++ } ++} ++ ++static void ++wlc_phy_adjust_rx_analpfbw_nphy(struct brcms_phy *pi, u16 reduction_factr) ++{ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) { ++ if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) && ++ CHSPEC_IS40(pi->radio_chanspec)) { ++ if (!pi->nphy_anarxlpf_adjusted) { ++ write_radio_reg(pi, ++ (RADIO_2056_RX_RXLPF_RCCAL_LPC | ++ RADIO_2056_RX0), ++ ((pi->nphy_rccal_value + ++ reduction_factr) | 0x80)); ++ ++ pi->nphy_anarxlpf_adjusted = true; ++ } ++ } else { ++ if (pi->nphy_anarxlpf_adjusted) { ++ write_radio_reg(pi, ++ (RADIO_2056_RX_RXLPF_RCCAL_LPC | ++ RADIO_2056_RX0), ++ (pi->nphy_rccal_value | 0x80)); ++ ++ pi->nphy_anarxlpf_adjusted = false; ++ } ++ } ++ } ++} ++ ++static void ++wlc_phy_adjust_min_noisevar_nphy(struct brcms_phy *pi, int ntones, ++ int *tone_id_buf, u32 *noise_var_buf) ++{ ++ int i; ++ u32 offset; ++ int tone_id; ++ int tbllen = ++ CHSPEC_IS40(pi->radio_chanspec) ? ++ NPHY_NOISEVAR_TBLLEN40 : NPHY_NOISEVAR_TBLLEN20; ++ ++ if (pi->nphy_noisevars_adjusted) { ++ for (i = 0; i < pi->nphy_saved_noisevars.bufcount; i++) { ++ tone_id = pi->nphy_saved_noisevars.tone_id[i]; ++ offset = (tone_id >= 0) ? ++ ((tone_id * ++ 2) + 1) : (tbllen + (tone_id * 2) + 1); ++ wlc_phy_table_write_nphy( ++ pi, NPHY_TBL_ID_NOISEVAR, 1, ++ offset, 32, ++ &pi->nphy_saved_noisevars.min_noise_vars[i]); ++ } ++ ++ pi->nphy_saved_noisevars.bufcount = 0; ++ pi->nphy_noisevars_adjusted = false; ++ } ++ ++ if ((noise_var_buf != NULL) && (tone_id_buf != NULL)) { ++ pi->nphy_saved_noisevars.bufcount = 0; ++ ++ for (i = 0; i < ntones; i++) { ++ tone_id = tone_id_buf[i]; ++ offset = (tone_id >= 0) ? ++ ((tone_id * 2) + 1) : ++ (tbllen + (tone_id * 2) + 1); ++ pi->nphy_saved_noisevars.tone_id[i] = tone_id; ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, ++ offset, 32, ++ &pi->nphy_saved_noisevars. ++ min_noise_vars[i]); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, ++ offset, 32, &noise_var_buf[i]); ++ pi->nphy_saved_noisevars.bufcount++; ++ } ++ ++ pi->nphy_noisevars_adjusted = true; ++ } ++} ++ ++static void wlc_phy_adjust_crsminpwr_nphy(struct brcms_phy *pi, u8 minpwr) ++{ ++ u16 regval; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) && ++ CHSPEC_IS40(pi->radio_chanspec)) { ++ if (!pi->nphy_crsminpwr_adjusted) { ++ regval = read_phy_reg(pi, 0x27d); ++ pi->nphy_crsminpwr[0] = regval & 0xff; ++ regval &= 0xff00; ++ regval |= (u16) minpwr; ++ write_phy_reg(pi, 0x27d, regval); ++ ++ regval = read_phy_reg(pi, 0x280); ++ pi->nphy_crsminpwr[1] = regval & 0xff; ++ regval &= 0xff00; ++ regval |= (u16) minpwr; ++ write_phy_reg(pi, 0x280, regval); ++ ++ regval = read_phy_reg(pi, 0x283); ++ pi->nphy_crsminpwr[2] = regval & 0xff; ++ regval &= 0xff00; ++ regval |= (u16) minpwr; ++ write_phy_reg(pi, 0x283, regval); ++ ++ pi->nphy_crsminpwr_adjusted = true; ++ } ++ } else { ++ if (pi->nphy_crsminpwr_adjusted) { ++ regval = read_phy_reg(pi, 0x27d); ++ regval &= 0xff00; ++ regval |= pi->nphy_crsminpwr[0]; ++ write_phy_reg(pi, 0x27d, regval); ++ ++ regval = read_phy_reg(pi, 0x280); ++ regval &= 0xff00; ++ regval |= pi->nphy_crsminpwr[1]; ++ write_phy_reg(pi, 0x280, regval); ++ ++ regval = read_phy_reg(pi, 0x283); ++ regval &= 0xff00; ++ regval |= pi->nphy_crsminpwr[2]; ++ write_phy_reg(pi, 0x283, regval); ++ ++ pi->nphy_crsminpwr_adjusted = false; ++ } ++ } ++ } ++} ++ ++static void wlc_phy_spurwar_nphy(struct brcms_phy *pi) ++{ ++ u16 cur_channel = 0; ++ int nphy_adj_tone_id_buf[] = { 57, 58 }; ++ u32 nphy_adj_noise_var_buf[] = { 0x3ff, 0x3ff }; ++ bool isAdjustNoiseVar = false; ++ uint numTonesAdjust = 0; ++ u32 tempval = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ cur_channel = CHSPEC_CHANNEL(pi->radio_chanspec); ++ ++ if (pi->nphy_gband_spurwar_en) { ++ ++ wlc_phy_adjust_rx_analpfbw_nphy( ++ pi, ++ NPHY_ANARXLPFBW_REDUCTIONFACT); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if ((cur_channel == 11) ++ && CHSPEC_IS40(pi->radio_chanspec)) ++ wlc_phy_adjust_min_noisevar_nphy( ++ pi, 2, ++ nphy_adj_tone_id_buf, ++ nphy_adj_noise_var_buf); ++ else ++ wlc_phy_adjust_min_noisevar_nphy(pi, 0, ++ NULL, ++ NULL); ++ } ++ ++ wlc_phy_adjust_crsminpwr_nphy(pi, ++ NPHY_ADJUSTED_MINCRSPOWER); ++ } ++ ++ if ((pi->nphy_gband_spurwar2_en) ++ && CHSPEC_IS2G(pi->radio_chanspec)) { ++ ++ if (CHSPEC_IS40(pi->radio_chanspec)) { ++ switch (cur_channel) { ++ case 3: ++ nphy_adj_tone_id_buf[0] = 57; ++ nphy_adj_tone_id_buf[1] = 58; ++ nphy_adj_noise_var_buf[0] = 0x22f; ++ nphy_adj_noise_var_buf[1] = 0x25f; ++ isAdjustNoiseVar = true; ++ break; ++ case 4: ++ nphy_adj_tone_id_buf[0] = 41; ++ nphy_adj_tone_id_buf[1] = 42; ++ nphy_adj_noise_var_buf[0] = 0x22f; ++ nphy_adj_noise_var_buf[1] = 0x25f; ++ isAdjustNoiseVar = true; ++ break; ++ case 5: ++ nphy_adj_tone_id_buf[0] = 25; ++ nphy_adj_tone_id_buf[1] = 26; ++ nphy_adj_noise_var_buf[0] = 0x24f; ++ nphy_adj_noise_var_buf[1] = 0x25f; ++ isAdjustNoiseVar = true; ++ break; ++ case 6: ++ nphy_adj_tone_id_buf[0] = 9; ++ nphy_adj_tone_id_buf[1] = 10; ++ nphy_adj_noise_var_buf[0] = 0x22f; ++ nphy_adj_noise_var_buf[1] = 0x24f; ++ isAdjustNoiseVar = true; ++ break; ++ case 7: ++ nphy_adj_tone_id_buf[0] = 121; ++ nphy_adj_tone_id_buf[1] = 122; ++ nphy_adj_noise_var_buf[0] = 0x18f; ++ nphy_adj_noise_var_buf[1] = 0x24f; ++ isAdjustNoiseVar = true; ++ break; ++ case 8: ++ nphy_adj_tone_id_buf[0] = 105; ++ nphy_adj_tone_id_buf[1] = 106; ++ nphy_adj_noise_var_buf[0] = 0x22f; ++ nphy_adj_noise_var_buf[1] = 0x25f; ++ isAdjustNoiseVar = true; ++ break; ++ case 9: ++ nphy_adj_tone_id_buf[0] = 89; ++ nphy_adj_tone_id_buf[1] = 90; ++ nphy_adj_noise_var_buf[0] = 0x22f; ++ nphy_adj_noise_var_buf[1] = 0x24f; ++ isAdjustNoiseVar = true; ++ break; ++ case 10: ++ nphy_adj_tone_id_buf[0] = 73; ++ nphy_adj_tone_id_buf[1] = 74; ++ nphy_adj_noise_var_buf[0] = 0x22f; ++ nphy_adj_noise_var_buf[1] = 0x24f; ++ isAdjustNoiseVar = true; ++ break; ++ default: ++ isAdjustNoiseVar = false; ++ break; ++ } ++ } ++ ++ if (isAdjustNoiseVar) { ++ numTonesAdjust = sizeof(nphy_adj_tone_id_buf) / ++ sizeof(nphy_adj_tone_id_buf[0]); ++ ++ wlc_phy_adjust_min_noisevar_nphy( ++ pi, ++ numTonesAdjust, ++ nphy_adj_tone_id_buf, ++ nphy_adj_noise_var_buf); ++ ++ tempval = 0; ++ ++ } else { ++ wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL, ++ NULL); ++ } ++ } ++ ++ if ((pi->nphy_aband_spurwar_en) && ++ (CHSPEC_IS5G(pi->radio_chanspec))) { ++ switch (cur_channel) { ++ case 54: ++ nphy_adj_tone_id_buf[0] = 32; ++ nphy_adj_noise_var_buf[0] = 0x25f; ++ break; ++ case 38: ++ case 102: ++ case 118: ++ nphy_adj_tone_id_buf[0] = 0; ++ nphy_adj_noise_var_buf[0] = 0x0; ++ break; ++ case 134: ++ nphy_adj_tone_id_buf[0] = 32; ++ nphy_adj_noise_var_buf[0] = 0x21f; ++ break; ++ case 151: ++ nphy_adj_tone_id_buf[0] = 16; ++ nphy_adj_noise_var_buf[0] = 0x23f; ++ break; ++ case 153: ++ case 161: ++ nphy_adj_tone_id_buf[0] = 48; ++ nphy_adj_noise_var_buf[0] = 0x23f; ++ break; ++ default: ++ nphy_adj_tone_id_buf[0] = 0; ++ nphy_adj_noise_var_buf[0] = 0x0; ++ break; ++ } ++ ++ if (nphy_adj_tone_id_buf[0] ++ && nphy_adj_noise_var_buf[0]) ++ wlc_phy_adjust_min_noisevar_nphy( ++ pi, 1, ++ nphy_adj_tone_id_buf, ++ nphy_adj_noise_var_buf); ++ else ++ wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL, ++ NULL); ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ } ++} ++ ++void wlc_phy_init_nphy(struct brcms_phy *pi) ++{ ++ u16 val; ++ u16 clip1_ths[2]; ++ struct nphy_txgains target_gain; ++ u8 tx_pwr_ctrl_state; ++ bool do_nphy_cal = false; ++ uint core; ++ uint origidx, intr_val; ++ struct d11regs __iomem *regs; ++ u32 d11_clk_ctl_st; ++ bool do_rssi_cal = false; ++ ++ core = 0; ++ ++ if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) ++ pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC; ++ ++ if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) && ++ ((pi->sh->chippkg == BCM4717_PKG_ID) || ++ (pi->sh->chippkg == BCM4718_PKG_ID))) { ++ if ((pi->sh->boardflags & BFL_EXTLNA) && ++ (CHSPEC_IS2G(pi->radio_chanspec))) ++ ai_corereg(pi->sh->sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol), ++ 0x40, 0x40); ++ } ++ ++ if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) && ++ CHSPEC_IS40(pi->radio_chanspec)) { ++ ++ regs = (struct d11regs __iomem *) ++ ai_switch_core(pi->sh->sih, ++ D11_CORE_ID, &origidx, ++ &intr_val); ++ d11_clk_ctl_st = R_REG(®s->clk_ctl_st); ++ AND_REG(®s->clk_ctl_st, ++ ~(CCS_FORCEHT | CCS_HTAREQ)); ++ ++ W_REG(®s->clk_ctl_st, d11_clk_ctl_st); ++ ++ ai_restore_core(pi->sh->sih, origidx, intr_val); ++ } ++ ++ pi->use_int_tx_iqlo_cal_nphy = ++ (PHY_IPA(pi) || ++ (NREV_GE(pi->pubpi.phy_rev, 7) || ++ (NREV_GE(pi->pubpi.phy_rev, 5) ++ && pi->sh->boardflags2 & BFL2_INTERNDET_TXIQCAL))); ++ ++ pi->internal_tx_iqlo_cal_tapoff_intpa_nphy = false; ++ ++ pi->nphy_deaf_count = 0; ++ ++ wlc_phy_tbl_init_nphy(pi); ++ ++ pi->nphy_crsminpwr_adjusted = false; ++ pi->nphy_noisevars_adjusted = false; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ write_phy_reg(pi, 0xe7, 0); ++ write_phy_reg(pi, 0xec, 0); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ write_phy_reg(pi, 0x342, 0); ++ write_phy_reg(pi, 0x343, 0); ++ write_phy_reg(pi, 0x346, 0); ++ write_phy_reg(pi, 0x347, 0); ++ } ++ write_phy_reg(pi, 0xe5, 0); ++ write_phy_reg(pi, 0xe6, 0); ++ } else { ++ write_phy_reg(pi, 0xec, 0); ++ } ++ ++ write_phy_reg(pi, 0x91, 0); ++ write_phy_reg(pi, 0x92, 0); ++ if (NREV_LT(pi->pubpi.phy_rev, 6)) { ++ write_phy_reg(pi, 0x93, 0); ++ write_phy_reg(pi, 0x94, 0); ++ } ++ ++ and_phy_reg(pi, 0xa1, ~3); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ write_phy_reg(pi, 0x8f, 0); ++ write_phy_reg(pi, 0xa5, 0); ++ } else { ++ write_phy_reg(pi, 0xa5, 0); ++ } ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 2)) ++ mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b); ++ else if (NREV_LT(pi->pubpi.phy_rev, 2)) ++ mod_phy_reg(pi, 0xdc, 0x00ff, 0x40); ++ ++ write_phy_reg(pi, 0x203, 32); ++ write_phy_reg(pi, 0x201, 32); ++ ++ if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD) ++ write_phy_reg(pi, 0x20d, 160); ++ else ++ write_phy_reg(pi, 0x20d, 184); ++ ++ write_phy_reg(pi, 0x13a, 200); ++ ++ write_phy_reg(pi, 0x70, 80); ++ ++ write_phy_reg(pi, 0x1ff, 48); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 8)) ++ wlc_phy_update_mimoconfig_nphy(pi, pi->n_preamble_override); ++ ++ wlc_phy_stf_chain_upd_nphy(pi); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) { ++ write_phy_reg(pi, 0x180, 0xaa8); ++ write_phy_reg(pi, 0x181, 0x9a4); ++ } ++ ++ if (PHY_IPA(pi)) { ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (1) << 0); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x298 : ++ 0x29c, (0x1ff << 7), ++ (pi->nphy_papd_epsilon_offset[core]) << 7); ++ ++ } ++ ++ wlc_phy_ipa_set_tx_digi_filts_nphy(pi); ++ } else if (NREV_GE(pi->pubpi.phy_rev, 5)) { ++ wlc_phy_extpa_set_tx_digi_filts_nphy(pi); ++ } ++ ++ wlc_phy_workarounds_nphy(pi); ++ ++ wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON); ++ ++ val = read_phy_reg(pi, 0x01); ++ write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA); ++ write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA)); ++ wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF); ++ ++ wlapi_bmac_macphyclk_set(pi->sh->physhim, ON); ++ ++ wlc_phy_pa_override_nphy(pi, OFF); ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX); ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); ++ wlc_phy_pa_override_nphy(pi, ON); ++ ++ wlc_phy_classifier_nphy(pi, 0, 0); ++ wlc_phy_clip_det_nphy(pi, 0, clip1_ths); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ wlc_phy_bphy_init_nphy(pi); ++ ++ tx_pwr_ctrl_state = pi->nphy_txpwrctrl; ++ wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF); ++ ++ wlc_phy_txpwr_fixpower_nphy(pi); ++ ++ wlc_phy_txpwrctrl_idle_tssi_nphy(pi); ++ ++ wlc_phy_txpwrctrl_pwr_setup_nphy(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ u32 *tx_pwrctrl_tbl = NULL; ++ u16 idx; ++ s16 pga_gn = 0; ++ s16 pad_gn = 0; ++ s32 rfpwr_offset; ++ ++ if (PHY_IPA(pi)) { ++ tx_pwrctrl_tbl = wlc_phy_get_ipa_gaintbl_nphy(pi); ++ } else { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (NREV_IS(pi->pubpi.phy_rev, 3)) ++ tx_pwrctrl_tbl = ++ nphy_tpc_5GHz_txgain_rev3; ++ else if (NREV_IS(pi->pubpi.phy_rev, 4)) ++ tx_pwrctrl_tbl = ++ (pi->srom_fem5g.extpagain == ++ 3) ? ++ nphy_tpc_5GHz_txgain_HiPwrEPA : ++ nphy_tpc_5GHz_txgain_rev4; ++ else ++ tx_pwrctrl_tbl = ++ nphy_tpc_5GHz_txgain_rev5; ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (pi->pubpi.radiorev == 5) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_epa_2057rev5; ++ else if (pi->pubpi.radiorev == 3) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_epa_2057rev3; ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 5) && ++ (pi->srom_fem2g.extpagain == 3)) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_HiPwrEPA; ++ else ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_rev3; ++ } ++ } ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128, ++ 192, 32, tx_pwrctrl_tbl); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128, ++ 192, 32, tx_pwrctrl_tbl); ++ ++ pi->nphy_gmval = (u16) ((*tx_pwrctrl_tbl >> 16) & 0x7000); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ for (idx = 0; idx < 128; idx++) { ++ pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf; ++ pad_gn = (tx_pwrctrl_tbl[idx] >> 19) & 0x1f; ++ rfpwr_offset = get_rf_pwr_offset(pi, pga_gn, ++ pad_gn); ++ wlc_phy_table_write_nphy( ++ pi, ++ NPHY_TBL_ID_CORE1TXPWRCTL, ++ 1, 576 + idx, 32, ++ &rfpwr_offset); ++ wlc_phy_table_write_nphy( ++ pi, ++ NPHY_TBL_ID_CORE2TXPWRCTL, ++ 1, 576 + idx, 32, ++ &rfpwr_offset); ++ } ++ } else { ++ ++ for (idx = 0; idx < 128; idx++) { ++ pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf; ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ rfpwr_offset = (s16) ++ nphy_papd_pga_gain_delta_ipa_2g ++ [pga_gn]; ++ else ++ rfpwr_offset = (s16) ++ nphy_papd_pga_gain_delta_ipa_5g ++ [pga_gn]; ++ ++ wlc_phy_table_write_nphy( ++ pi, ++ NPHY_TBL_ID_CORE1TXPWRCTL, ++ 1, 576 + idx, 32, ++ &rfpwr_offset); ++ wlc_phy_table_write_nphy( ++ pi, ++ NPHY_TBL_ID_CORE2TXPWRCTL, ++ 1, 576 + idx, 32, ++ &rfpwr_offset); ++ } ++ ++ } ++ } else { ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128, ++ 192, 32, nphy_tpc_txgain); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128, ++ 192, 32, nphy_tpc_txgain); ++ } ++ ++ if (pi->sh->phyrxchain != 0x3) ++ wlc_phy_rxcore_setstate_nphy((struct brcms_phy_pub *) pi, ++ pi->sh->phyrxchain); ++ ++ if (PHY_PERICAL_MPHASE_PENDING(pi)) ++ wlc_phy_cal_perical_mphase_restart(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ do_rssi_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ? ++ (pi->nphy_rssical_chanspec_2G == 0) : ++ (pi->nphy_rssical_chanspec_5G == 0); ++ ++ if (do_rssi_cal) ++ wlc_phy_rssi_cal_nphy(pi); ++ else ++ wlc_phy_restore_rssical_nphy(pi); ++ } else { ++ wlc_phy_rssi_cal_nphy(pi); ++ } ++ ++ if (!SCAN_RM_IN_PROGRESS(pi)) ++ do_nphy_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ? ++ (pi->nphy_iqcal_chanspec_2G == 0) : ++ (pi->nphy_iqcal_chanspec_5G == 0); ++ ++ if (!pi->do_initcal) ++ do_nphy_cal = false; ++ ++ if (do_nphy_cal) { ++ ++ target_gain = wlc_phy_get_tx_gain_nphy(pi); ++ ++ if (pi->antsel_type == ANTSEL_2x3) ++ wlc_phy_antsel_init((struct brcms_phy_pub *) pi, ++ true); ++ ++ if (pi->nphy_perical != PHY_PERICAL_MPHASE) { ++ wlc_phy_rssi_cal_nphy(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ pi->nphy_cal_orig_pwr_idx[0] = ++ pi->nphy_txpwrindex[PHY_CORE_0] ++ . ++ index_internal; ++ pi->nphy_cal_orig_pwr_idx[1] = ++ pi->nphy_txpwrindex[PHY_CORE_1] ++ . ++ index_internal; ++ ++ wlc_phy_precal_txgain_nphy(pi); ++ target_gain = ++ wlc_phy_get_tx_gain_nphy(pi); ++ } ++ ++ if (wlc_phy_cal_txiqlo_nphy ++ (pi, target_gain, true, ++ false) == 0) { ++ if (wlc_phy_cal_rxiq_nphy ++ (pi, target_gain, 2, ++ false) == 0) ++ wlc_phy_savecal_nphy(pi); ++ ++ } ++ } else if (pi->mphase_cal_phase_id == ++ MPHASE_CAL_STATE_IDLE) { ++ wlc_phy_cal_perical((struct brcms_phy_pub *) pi, ++ PHY_PERICAL_PHYINIT); ++ } ++ } else { ++ wlc_phy_restorecal_nphy(pi); ++ } ++ ++ wlc_phy_txpwrctrl_coeff_setup_nphy(pi); ++ ++ wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state); ++ ++ wlc_phy_nphy_tkip_rifs_war(pi, pi->sh->_rifs_phy); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LE(pi->pubpi.phy_rev, 6)) ++ ++ write_phy_reg(pi, 0x70, 50); ++ ++ wlc_phy_txlpfbw_nphy(pi); ++ ++ wlc_phy_spurwar_nphy(pi); ++ ++} ++ ++static void wlc_phy_resetcca_nphy(struct brcms_phy *pi) ++{ ++ u16 val; ++ ++ wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON); ++ ++ val = read_phy_reg(pi, 0x01); ++ write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA); ++ udelay(1); ++ write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA)); ++ ++ wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF); ++ ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); ++} ++ ++void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en) ++{ ++ u16 rfctrlintc_override_val; ++ ++ if (!en) { ++ ++ pi->rfctrlIntc1_save = read_phy_reg(pi, 0x91); ++ pi->rfctrlIntc2_save = read_phy_reg(pi, 0x92); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ rfctrlintc_override_val = 0x1480; ++ else if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ rfctrlintc_override_val = ++ CHSPEC_IS5G(pi->radio_chanspec) ? 0x600 : 0x480; ++ else ++ rfctrlintc_override_val = ++ CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120; ++ ++ write_phy_reg(pi, 0x91, rfctrlintc_override_val); ++ write_phy_reg(pi, 0x92, rfctrlintc_override_val); ++ } else { ++ write_phy_reg(pi, 0x91, pi->rfctrlIntc1_save); ++ write_phy_reg(pi, 0x92, pi->rfctrlIntc2_save); ++ } ++ ++} ++ ++void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi) ++{ ++ ++ u16 txrx_chain = ++ (NPHY_RfseqCoreActv_TxRxChain0 | NPHY_RfseqCoreActv_TxRxChain1); ++ bool CoreActv_override = false; ++ ++ if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN0) { ++ txrx_chain = NPHY_RfseqCoreActv_TxRxChain0; ++ CoreActv_override = true; ++ ++ if (NREV_LE(pi->pubpi.phy_rev, 2)) ++ and_phy_reg(pi, 0xa0, ~0x20); ++ } else if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN1) { ++ txrx_chain = NPHY_RfseqCoreActv_TxRxChain1; ++ CoreActv_override = true; ++ ++ if (NREV_LE(pi->pubpi.phy_rev, 2)) ++ or_phy_reg(pi, 0xa0, 0x20); ++ } ++ ++ mod_phy_reg(pi, 0xa2, ((0xf << 0) | (0xf << 4)), txrx_chain); ++ ++ if (CoreActv_override) { ++ pi->nphy_perical = PHY_PERICAL_DISABLE; ++ or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override); ++ } else { ++ pi->nphy_perical = PHY_PERICAL_MPHASE; ++ and_phy_reg(pi, 0xa1, ~NPHY_RfseqMode_CoreActv_override); ++ } ++} ++ ++void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, u8 rxcore_bitmask) ++{ ++ u16 regval; ++ u16 tbl_buf[16]; ++ uint i; ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ u16 tbl_opcode; ++ bool suspend; ++ ++ pi->sh->phyrxchain = rxcore_bitmask; ++ ++ if (!pi->sh->clk) ++ return; ++ ++ suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!suspend) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ regval = read_phy_reg(pi, 0xa2); ++ regval &= ~(0xf << 4); ++ regval |= ((u16) (rxcore_bitmask & 0x3)) << 4; ++ write_phy_reg(pi, 0xa2, regval); ++ ++ if ((rxcore_bitmask & 0x3) != 0x3) { ++ ++ write_phy_reg(pi, 0x20e, 1); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (pi->rx2tx_biasentry == -1) { ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, ++ ARRAY_SIZE(tbl_buf), 80, ++ 16, tbl_buf); ++ ++ for (i = 0; i < ARRAY_SIZE(tbl_buf); i++) { ++ if (tbl_buf[i] == ++ NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS) { ++ pi->rx2tx_biasentry = (u8) i; ++ tbl_opcode = ++ NPHY_REV3_RFSEQ_CMD_NOP; ++ wlc_phy_table_write_nphy( ++ pi, ++ NPHY_TBL_ID_RFSEQ, ++ 1, i, ++ 16, ++ &tbl_opcode); ++ break; ++ } else if (tbl_buf[i] == ++ NPHY_REV3_RFSEQ_CMD_END) ++ break; ++ } ++ } ++ } ++ } else { ++ ++ write_phy_reg(pi, 0x20e, 30); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (pi->rx2tx_biasentry != -1) { ++ tbl_opcode = NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, ++ 1, pi->rx2tx_biasentry, ++ 16, &tbl_opcode); ++ pi->rx2tx_biasentry = -1; ++ } ++ } ++ } ++ ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ ++ if (!suspend) ++ wlapi_enable_mac(pi->sh->physhim); ++} ++ ++u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih) ++{ ++ u16 regval, rxen_bits; ++ struct brcms_phy *pi = (struct brcms_phy *) pih; ++ ++ regval = read_phy_reg(pi, 0xa2); ++ rxen_bits = (regval >> 4) & 0xf; ++ ++ return (u8) rxen_bits; ++} ++ ++bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pi) ++{ ++ return PHY_IPA(pi); ++} ++ ++void wlc_phy_cal_init_nphy(struct brcms_phy *pi) ++{ ++} ++ ++static void wlc_phy_radio_preinit_205x(struct brcms_phy *pi) ++{ ++ ++ and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU); ++ and_phy_reg(pi, 0x78, RFCC_OE_POR_FORCE); ++ ++ or_phy_reg(pi, 0x78, ~RFCC_OE_POR_FORCE); ++ or_phy_reg(pi, 0x78, RFCC_CHIP0_PU); ++ ++} ++ ++static void wlc_phy_radio_init_2057(struct brcms_phy *pi) ++{ ++ struct radio_20xx_regs *regs_2057_ptr = NULL; ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7)) { ++ regs_2057_ptr = regs_2057_rev4; ++ } else if (NREV_IS(pi->pubpi.phy_rev, 8) ++ || NREV_IS(pi->pubpi.phy_rev, 9)) { ++ switch (pi->pubpi.radiorev) { ++ case 5: ++ ++ if (pi->pubpi.radiover == 0x0) ++ regs_2057_ptr = regs_2057_rev5; ++ else if (pi->pubpi.radiover == 0x1) ++ regs_2057_ptr = regs_2057_rev5v1; ++ else ++ break; ++ ++ case 7: ++ ++ regs_2057_ptr = regs_2057_rev7; ++ break; ++ ++ case 8: ++ ++ regs_2057_ptr = regs_2057_rev8; ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ wlc_phy_init_radio_regs_allbands(pi, regs_2057_ptr); ++} ++ ++static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi) ++{ ++ u16 rcal_reg = 0; ++ int i; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ if (pi->pubpi.radiorev == 5) { ++ ++ and_phy_reg(pi, 0x342, ~(0x1 << 1)); ++ ++ udelay(10); ++ ++ mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x1); ++ mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2, ++ 0x1); ++ } ++ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x1); ++ ++ udelay(10); ++ ++ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x3, 0x3); ++ ++ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { ++ rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS); ++ if (rcal_reg & 0x1) ++ break; ++ ++ udelay(100); ++ } ++ ++ if (WARN(i == MAX_205x_RCAL_WAITLOOPS, ++ "HW error: radio calib2")) ++ return 0; ++ ++ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x2, 0x0); ++ ++ rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS) & 0x3e; ++ ++ mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x0); ++ if (pi->pubpi.radiorev == 5) { ++ ++ mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x0); ++ mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2, ++ 0x0); ++ } ++ ++ if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) { ++ ++ mod_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x3c, ++ rcal_reg); ++ mod_radio_reg(pi, RADIO_2057_BANDGAP_RCAL_TRIM, 0xf0, ++ rcal_reg << 2); ++ } ++ ++ } else if (NREV_IS(pi->pubpi.phy_rev, 3)) { ++ u16 savereg; ++ ++ savereg = ++ read_radio_reg( ++ pi, ++ RADIO_2056_SYN_PLL_MAST2 | ++ RADIO_2056_SYN); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN, ++ savereg | 0x7); ++ udelay(10); ++ ++ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN, ++ 0x1); ++ udelay(10); ++ ++ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN, ++ 0x9); ++ ++ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { ++ rcal_reg = read_radio_reg( ++ pi, ++ RADIO_2056_SYN_RCAL_CODE_OUT | ++ RADIO_2056_SYN); ++ if (rcal_reg & 0x80) ++ break; ++ ++ udelay(100); ++ } ++ ++ if (WARN(i == MAX_205x_RCAL_WAITLOOPS, ++ "HW error: radio calib3")) ++ return 0; ++ ++ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN, ++ 0x1); ++ ++ rcal_reg = ++ read_radio_reg(pi, ++ RADIO_2056_SYN_RCAL_CODE_OUT | ++ RADIO_2056_SYN); ++ ++ write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN, ++ 0x0); ++ ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN, ++ savereg); ++ ++ return rcal_reg & 0x1f; ++ } ++ return rcal_reg & 0x3e; ++} ++ ++static u16 wlc_phy_radio2057_rccal(struct brcms_phy *pi) ++{ ++ u16 rccal_valid; ++ int i; ++ bool chip43226_6362A0; ++ ++ chip43226_6362A0 = ((pi->pubpi.radiorev == 3) ++ || (pi->pubpi.radiorev == 4) ++ || (pi->pubpi.radiorev == 6)); ++ ++ rccal_valid = 0; ++ if (chip43226_6362A0) { ++ write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x61); ++ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xc0); ++ } else { ++ write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x61); ++ ++ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xe9); ++ } ++ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e); ++ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55); ++ ++ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { ++ rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP); ++ if (rccal_valid & 0x2) ++ break; ++ ++ udelay(500); ++ } ++ ++ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15); ++ ++ rccal_valid = 0; ++ if (chip43226_6362A0) { ++ write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x69); ++ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0); ++ } else { ++ write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x69); ++ ++ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xd5); ++ } ++ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e); ++ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55); ++ ++ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { ++ rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP); ++ if (rccal_valid & 0x2) ++ break; ++ ++ udelay(500); ++ } ++ ++ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15); ++ ++ rccal_valid = 0; ++ if (chip43226_6362A0) { ++ write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x73); ++ ++ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x28); ++ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0); ++ } else { ++ write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x73); ++ write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e); ++ write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0x99); ++ } ++ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55); ++ ++ for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) { ++ rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP); ++ if (rccal_valid & 0x2) ++ break; ++ ++ udelay(500); ++ } ++ ++ if (WARN(!(rccal_valid & 0x2), "HW error: radio calib4")) ++ return 0; ++ ++ write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15); ++ ++ return rccal_valid; ++} ++ ++static void wlc_phy_radio_postinit_2057(struct brcms_phy *pi) ++{ ++ ++ mod_radio_reg(pi, RADIO_2057_XTALPUOVR_PINCTRL, 0x1, 0x1); ++ ++ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x78); ++ mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x80); ++ mdelay(2); ++ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x0); ++ mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x0); ++ ++ if (pi->phy_init_por) { ++ wlc_phy_radio205x_rcal(pi); ++ wlc_phy_radio2057_rccal(pi); ++ } ++ ++ mod_radio_reg(pi, RADIO_2057_RFPLL_MASTER, 0x8, 0x0); ++} ++ ++static void wlc_phy_radio_init_2056(struct brcms_phy *pi) ++{ ++ const struct radio_regs *regs_SYN_2056_ptr = NULL; ++ const struct radio_regs *regs_TX_2056_ptr = NULL; ++ const struct radio_regs *regs_RX_2056_ptr = NULL; ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 3)) { ++ regs_SYN_2056_ptr = regs_SYN_2056; ++ regs_TX_2056_ptr = regs_TX_2056; ++ regs_RX_2056_ptr = regs_RX_2056; ++ } else if (NREV_IS(pi->pubpi.phy_rev, 4)) { ++ regs_SYN_2056_ptr = regs_SYN_2056_A1; ++ regs_TX_2056_ptr = regs_TX_2056_A1; ++ regs_RX_2056_ptr = regs_RX_2056_A1; ++ } else { ++ switch (pi->pubpi.radiorev) { ++ case 5: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev5; ++ regs_TX_2056_ptr = regs_TX_2056_rev5; ++ regs_RX_2056_ptr = regs_RX_2056_rev5; ++ break; ++ ++ case 6: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev6; ++ regs_TX_2056_ptr = regs_TX_2056_rev6; ++ regs_RX_2056_ptr = regs_RX_2056_rev6; ++ break; ++ ++ case 7: ++ case 9: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev7; ++ regs_TX_2056_ptr = regs_TX_2056_rev7; ++ regs_RX_2056_ptr = regs_RX_2056_rev7; ++ break; ++ ++ case 8: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev8; ++ regs_TX_2056_ptr = regs_TX_2056_rev8; ++ regs_RX_2056_ptr = regs_RX_2056_rev8; ++ break; ++ ++ case 11: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev11; ++ regs_TX_2056_ptr = regs_TX_2056_rev11; ++ regs_RX_2056_ptr = regs_RX_2056_rev11; ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ wlc_phy_init_radio_regs(pi, regs_SYN_2056_ptr, (u16) RADIO_2056_SYN); ++ ++ wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX0); ++ ++ wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX1); ++ ++ wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX0); ++ ++ wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX1); ++} ++ ++static void wlc_phy_radio_postinit_2056(struct brcms_phy *pi) ++{ ++ mod_radio_reg(pi, RADIO_2056_SYN_COM_CTRL, 0xb, 0xb); ++ ++ mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x2); ++ mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x2); ++ udelay(1000); ++ mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x0); ++ ++ if ((pi->sh->boardflags2 & BFL2_LEGACY) ++ || (pi->sh->boardflags2 & BFL2_XTALBUFOUTEN)) ++ mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xf4, 0x0); ++ else ++ mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xfc, 0x0); ++ ++ mod_radio_reg(pi, RADIO_2056_SYN_RCCAL_CTRL0, 0x1, 0x0); ++ ++ if (pi->phy_init_por) ++ wlc_phy_radio205x_rcal(pi); ++} ++ ++static void wlc_phy_radio_preinit_2055(struct brcms_phy *pi) ++{ ++ ++ and_phy_reg(pi, 0x78, ~RFCC_POR_FORCE); ++ or_phy_reg(pi, 0x78, RFCC_CHIP0_PU | RFCC_OE_POR_FORCE); ++ ++ or_phy_reg(pi, 0x78, RFCC_POR_FORCE); ++} ++ ++static void wlc_phy_radio_init_2055(struct brcms_phy *pi) ++{ ++ wlc_phy_init_radio_regs(pi, regs_2055, RADIO_DEFAULT_CORE); ++} ++ ++static void wlc_phy_radio_postinit_2055(struct brcms_phy *pi) ++{ ++ ++ and_radio_reg(pi, RADIO_2055_MASTER_CNTRL1, ++ ~(RADIO_2055_JTAGCTRL_MASK | RADIO_2055_JTAGSYNC_MASK)); ++ ++ if (((pi->sh->sromrev >= 4) ++ && !(pi->sh->boardflags2 & BFL2_RXBB_INT_REG_DIS)) ++ || ((pi->sh->sromrev < 4))) { ++ and_radio_reg(pi, RADIO_2055_CORE1_RXBB_REGULATOR, 0x7F); ++ and_radio_reg(pi, RADIO_2055_CORE2_RXBB_REGULATOR, 0x7F); ++ } ++ ++ mod_radio_reg(pi, RADIO_2055_RRCCAL_N_OPT_SEL, 0x3F, 0x2C); ++ write_radio_reg(pi, RADIO_2055_CAL_MISC, 0x3C); ++ ++ and_radio_reg(pi, RADIO_2055_CAL_MISC, ++ ~(RADIO_2055_RRCAL_START | RADIO_2055_RRCAL_RST_N)); ++ ++ or_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL, RADIO_2055_CAL_LPO_ENABLE); ++ ++ or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_RST_N); ++ ++ udelay(1000); ++ ++ or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_START); ++ ++ SPINWAIT(((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) & ++ RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE), 2000); ++ ++ if (WARN((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) & ++ RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE, ++ "HW error: radio calibration1\n")) ++ return; ++ ++ and_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL, ++ ~(RADIO_2055_CAL_LPO_ENABLE)); ++ ++ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec); ++ ++ write_radio_reg(pi, RADIO_2055_CORE1_RXBB_LPF, 9); ++ write_radio_reg(pi, RADIO_2055_CORE2_RXBB_LPF, 9); ++ ++ write_radio_reg(pi, RADIO_2055_CORE1_RXBB_MIDAC_HIPAS, 0x83); ++ write_radio_reg(pi, RADIO_2055_CORE2_RXBB_MIDAC_HIPAS, 0x83); ++ ++ mod_radio_reg(pi, RADIO_2055_CORE1_LNA_GAINBST, ++ RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE); ++ mod_radio_reg(pi, RADIO_2055_CORE2_LNA_GAINBST, ++ RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE); ++ if (pi->nphy_gain_boost) { ++ and_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1, ++ ~(RADIO_2055_GAINBST_DISABLE)); ++ and_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1, ++ ~(RADIO_2055_GAINBST_DISABLE)); ++ } else { ++ or_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1, ++ RADIO_2055_GAINBST_DISABLE); ++ or_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1, ++ RADIO_2055_GAINBST_DISABLE); ++ } ++ ++ udelay(2); ++} ++ ++void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on) ++{ ++ if (on) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (!pi->radio_is_on) { ++ wlc_phy_radio_preinit_205x(pi); ++ wlc_phy_radio_init_2057(pi); ++ wlc_phy_radio_postinit_2057(pi); ++ } ++ ++ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, ++ pi->radio_chanspec); ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ wlc_phy_radio_preinit_205x(pi); ++ wlc_phy_radio_init_2056(pi); ++ wlc_phy_radio_postinit_2056(pi); ++ ++ wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, ++ pi->radio_chanspec); ++ } else { ++ wlc_phy_radio_preinit_2055(pi); ++ wlc_phy_radio_init_2055(pi); ++ wlc_phy_radio_postinit_2055(pi); ++ } ++ ++ pi->radio_is_on = true; ++ ++ } else { ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) ++ && NREV_LT(pi->pubpi.phy_rev, 7)) { ++ and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU); ++ mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x0); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_PADA_BOOST_TUNE | ++ RADIO_2056_TX0, 0); ++ write_radio_reg(pi, ++ RADIO_2056_TX_PADG_BOOST_TUNE | ++ RADIO_2056_TX0, 0); ++ write_radio_reg(pi, ++ RADIO_2056_TX_PGAA_BOOST_TUNE | ++ RADIO_2056_TX0, 0); ++ write_radio_reg(pi, ++ RADIO_2056_TX_PGAG_BOOST_TUNE | ++ RADIO_2056_TX0, 0); ++ mod_radio_reg(pi, ++ RADIO_2056_TX_MIXA_BOOST_TUNE | ++ RADIO_2056_TX0, 0xf0, 0); ++ write_radio_reg(pi, ++ RADIO_2056_TX_MIXG_BOOST_TUNE | ++ RADIO_2056_TX0, 0); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_PADA_BOOST_TUNE | ++ RADIO_2056_TX1, 0); ++ write_radio_reg(pi, ++ RADIO_2056_TX_PADG_BOOST_TUNE | ++ RADIO_2056_TX1, 0); ++ write_radio_reg(pi, ++ RADIO_2056_TX_PGAA_BOOST_TUNE | ++ RADIO_2056_TX1, 0); ++ write_radio_reg(pi, ++ RADIO_2056_TX_PGAG_BOOST_TUNE | ++ RADIO_2056_TX1, 0); ++ mod_radio_reg(pi, ++ RADIO_2056_TX_MIXA_BOOST_TUNE | ++ RADIO_2056_TX1, 0xf0, 0); ++ write_radio_reg(pi, ++ RADIO_2056_TX_MIXG_BOOST_TUNE | ++ RADIO_2056_TX1, 0); ++ ++ pi->radio_is_on = false; ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 8)) { ++ and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU); ++ pi->radio_is_on = false; ++ } ++ ++ } ++} ++ ++static bool ++wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f, ++ const struct chan_info_nphy_radio2057 **t0, ++ const struct chan_info_nphy_radio205x **t1, ++ const struct chan_info_nphy_radio2057_rev5 **t2, ++ const struct chan_info_nphy_2055 **t3) ++{ ++ uint i; ++ const struct chan_info_nphy_radio2057 *chan_info_tbl_p_0 = NULL; ++ const struct chan_info_nphy_radio205x *chan_info_tbl_p_1 = NULL; ++ const struct chan_info_nphy_radio2057_rev5 *chan_info_tbl_p_2 = NULL; ++ u32 tbl_len = 0; ++ ++ int freq = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7)) { ++ ++ chan_info_tbl_p_0 = chan_info_nphyrev7_2057_rev4; ++ tbl_len = ARRAY_SIZE(chan_info_nphyrev7_2057_rev4); ++ ++ } else if (NREV_IS(pi->pubpi.phy_rev, 8) ++ || NREV_IS(pi->pubpi.phy_rev, 9)) { ++ switch (pi->pubpi.radiorev) { ++ ++ case 5: ++ ++ if (pi->pubpi.radiover == 0x0) { ++ ++ chan_info_tbl_p_2 = ++ chan_info_nphyrev8_2057_rev5; ++ tbl_len = ARRAY_SIZE( ++ chan_info_nphyrev8_2057_rev5); ++ ++ } else if (pi->pubpi.radiover == 0x1) { ++ ++ chan_info_tbl_p_2 = ++ chan_info_nphyrev9_2057_rev5v1; ++ tbl_len = ARRAY_SIZE( ++ chan_info_nphyrev9_2057_rev5v1); ++ ++ } ++ break; ++ ++ case 7: ++ chan_info_tbl_p_0 = ++ chan_info_nphyrev8_2057_rev7; ++ tbl_len = ARRAY_SIZE( ++ chan_info_nphyrev8_2057_rev7); ++ break; ++ ++ case 8: ++ chan_info_tbl_p_0 = ++ chan_info_nphyrev8_2057_rev8; ++ tbl_len = ARRAY_SIZE( ++ chan_info_nphyrev8_2057_rev8); ++ break; ++ ++ default: ++ break; ++ } ++ } else if (NREV_IS(pi->pubpi.phy_rev, 16)) { ++ ++ chan_info_tbl_p_0 = chan_info_nphyrev8_2057_rev8; ++ tbl_len = ARRAY_SIZE(chan_info_nphyrev8_2057_rev8); ++ } else { ++ goto fail; ++ } ++ ++ for (i = 0; i < tbl_len; i++) { ++ if (pi->pubpi.radiorev == 5) { ++ ++ if (chan_info_tbl_p_2[i].chan == channel) ++ break; ++ } else { ++ ++ if (chan_info_tbl_p_0[i].chan == channel) ++ break; ++ } ++ } ++ ++ if (i >= tbl_len) ++ goto fail; ++ ++ if (pi->pubpi.radiorev == 5) { ++ *t2 = &chan_info_tbl_p_2[i]; ++ freq = chan_info_tbl_p_2[i].freq; ++ } else { ++ *t0 = &chan_info_tbl_p_0[i]; ++ freq = chan_info_tbl_p_0[i].freq; ++ } ++ ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (NREV_IS(pi->pubpi.phy_rev, 3)) { ++ chan_info_tbl_p_1 = chan_info_nphyrev3_2056; ++ tbl_len = ARRAY_SIZE(chan_info_nphyrev3_2056); ++ } else if (NREV_IS(pi->pubpi.phy_rev, 4)) { ++ chan_info_tbl_p_1 = chan_info_nphyrev4_2056_A1; ++ tbl_len = ARRAY_SIZE(chan_info_nphyrev4_2056_A1); ++ } else if (NREV_IS(pi->pubpi.phy_rev, 5) ++ || NREV_IS(pi->pubpi.phy_rev, 6)) { ++ switch (pi->pubpi.radiorev) { ++ case 5: ++ chan_info_tbl_p_1 = chan_info_nphyrev5_2056v5; ++ tbl_len = ARRAY_SIZE(chan_info_nphyrev5_2056v5); ++ break; ++ case 6: ++ chan_info_tbl_p_1 = chan_info_nphyrev6_2056v6; ++ tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v6); ++ break; ++ case 7: ++ case 9: ++ chan_info_tbl_p_1 = chan_info_nphyrev5n6_2056v7; ++ tbl_len = ++ ARRAY_SIZE(chan_info_nphyrev5n6_2056v7); ++ break; ++ case 8: ++ chan_info_tbl_p_1 = chan_info_nphyrev6_2056v8; ++ tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v8); ++ break; ++ case 11: ++ chan_info_tbl_p_1 = chan_info_nphyrev6_2056v11; ++ tbl_len = ARRAY_SIZE( ++ chan_info_nphyrev6_2056v11); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ for (i = 0; i < tbl_len; i++) { ++ if (chan_info_tbl_p_1[i].chan == channel) ++ break; ++ } ++ ++ if (i >= tbl_len) ++ goto fail; ++ ++ *t1 = &chan_info_tbl_p_1[i]; ++ freq = chan_info_tbl_p_1[i].freq; ++ ++ } else { ++ for (i = 0; i < ARRAY_SIZE(chan_info_nphy_2055); i++) ++ if (chan_info_nphy_2055[i].chan == channel) ++ break; ++ ++ if (i >= ARRAY_SIZE(chan_info_nphy_2055)) ++ goto fail; ++ ++ *t3 = &chan_info_nphy_2055[i]; ++ freq = chan_info_nphy_2055[i].freq; ++ } ++ ++ *f = freq; ++ return true; ++ ++fail: ++ *f = WL_CHAN_FREQ_RANGE_2G; ++ return false; ++} ++ ++u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint channel) ++{ ++ int freq; ++ const struct chan_info_nphy_radio2057 *t0 = NULL; ++ const struct chan_info_nphy_radio205x *t1 = NULL; ++ const struct chan_info_nphy_radio2057_rev5 *t2 = NULL; ++ const struct chan_info_nphy_2055 *t3 = NULL; ++ ++ if (channel == 0) ++ channel = CHSPEC_CHANNEL(pi->radio_chanspec); ++ ++ wlc_phy_chan2freq_nphy(pi, channel, &freq, &t0, &t1, &t2, &t3); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ return WL_CHAN_FREQ_RANGE_2G; ++ ++ if ((freq >= BASE_LOW_5G_CHAN) && (freq < BASE_MID_5G_CHAN)) ++ return WL_CHAN_FREQ_RANGE_5GL; ++ else if ((freq >= BASE_MID_5G_CHAN) && (freq < BASE_HIGH_5G_CHAN)) ++ return WL_CHAN_FREQ_RANGE_5GM; ++ else ++ return WL_CHAN_FREQ_RANGE_5GH; ++} ++ ++static void ++wlc_phy_chanspec_radio2055_setup(struct brcms_phy *pi, ++ const struct chan_info_nphy_2055 *ci) ++{ ++ ++ write_radio_reg(pi, RADIO_2055_PLL_REF, ci->RF_pll_ref); ++ write_radio_reg(pi, RADIO_2055_RF_PLL_MOD0, ci->RF_rf_pll_mod0); ++ write_radio_reg(pi, RADIO_2055_RF_PLL_MOD1, ci->RF_rf_pll_mod1); ++ write_radio_reg(pi, RADIO_2055_VCO_CAP_TAIL, ci->RF_vco_cap_tail); ++ ++ BRCMS_PHY_WAR_PR51571(pi); ++ ++ write_radio_reg(pi, RADIO_2055_VCO_CAL1, ci->RF_vco_cal1); ++ write_radio_reg(pi, RADIO_2055_VCO_CAL2, ci->RF_vco_cal2); ++ write_radio_reg(pi, RADIO_2055_PLL_LF_C1, ci->RF_pll_lf_c1); ++ write_radio_reg(pi, RADIO_2055_PLL_LF_R1, ci->RF_pll_lf_r1); ++ ++ BRCMS_PHY_WAR_PR51571(pi); ++ ++ write_radio_reg(pi, RADIO_2055_PLL_LF_C2, ci->RF_pll_lf_c2); ++ write_radio_reg(pi, RADIO_2055_LGBUF_CEN_BUF, ci->RF_lgbuf_cen_buf); ++ write_radio_reg(pi, RADIO_2055_LGEN_TUNE1, ci->RF_lgen_tune1); ++ write_radio_reg(pi, RADIO_2055_LGEN_TUNE2, ci->RF_lgen_tune2); ++ ++ BRCMS_PHY_WAR_PR51571(pi); ++ ++ write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_A_TUNE, ++ ci->RF_core1_lgbuf_a_tune); ++ write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_G_TUNE, ++ ci->RF_core1_lgbuf_g_tune); ++ write_radio_reg(pi, RADIO_2055_CORE1_RXRF_REG1, ci->RF_core1_rxrf_reg1); ++ write_radio_reg(pi, RADIO_2055_CORE1_TX_PGA_PAD_TN, ++ ci->RF_core1_tx_pga_pad_tn); ++ ++ BRCMS_PHY_WAR_PR51571(pi); ++ ++ write_radio_reg(pi, RADIO_2055_CORE1_TX_MX_BGTRIM, ++ ci->RF_core1_tx_mx_bgtrim); ++ write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_A_TUNE, ++ ci->RF_core2_lgbuf_a_tune); ++ write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_G_TUNE, ++ ci->RF_core2_lgbuf_g_tune); ++ write_radio_reg(pi, RADIO_2055_CORE2_RXRF_REG1, ci->RF_core2_rxrf_reg1); ++ ++ BRCMS_PHY_WAR_PR51571(pi); ++ ++ write_radio_reg(pi, RADIO_2055_CORE2_TX_PGA_PAD_TN, ++ ci->RF_core2_tx_pga_pad_tn); ++ write_radio_reg(pi, RADIO_2055_CORE2_TX_MX_BGTRIM, ++ ci->RF_core2_tx_mx_bgtrim); ++ ++ udelay(50); ++ ++ write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x05); ++ write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x45); ++ ++ BRCMS_PHY_WAR_PR51571(pi); ++ ++ write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x65); ++ ++ udelay(300); ++} ++ ++static void ++wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi, ++ const struct chan_info_nphy_radio205x *ci) ++{ ++ const struct radio_regs *regs_SYN_2056_ptr = NULL; ++ ++ write_radio_reg(pi, ++ RADIO_2056_SYN_PLL_VCOCAL1 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_vcocal1); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL2 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_vcocal2); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_REFDIV | RADIO_2056_SYN, ++ ci->RF_SYN_pll_refdiv); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD2 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_mmd2); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD1 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_mmd1); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_loopfilter1); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_loopfilter2); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER3 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_loopfilter3); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_loopfilter4); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER5 | RADIO_2056_SYN, ++ ci->RF_SYN_pll_loopfilter5); ++ write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR27 | RADIO_2056_SYN, ++ ci->RF_SYN_reserved_addr27); ++ write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR28 | RADIO_2056_SYN, ++ ci->RF_SYN_reserved_addr28); ++ write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR29 | RADIO_2056_SYN, ++ ci->RF_SYN_reserved_addr29); ++ write_radio_reg(pi, RADIO_2056_SYN_LOGEN_VCOBUF1 | RADIO_2056_SYN, ++ ci->RF_SYN_logen_VCOBUF1); ++ write_radio_reg(pi, RADIO_2056_SYN_LOGEN_MIXER2 | RADIO_2056_SYN, ++ ci->RF_SYN_logen_MIXER2); ++ write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF3 | RADIO_2056_SYN, ++ ci->RF_SYN_logen_BUF3); ++ write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF4 | RADIO_2056_SYN, ++ ci->RF_SYN_logen_BUF4); ++ ++ write_radio_reg(pi, ++ RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX0, ++ ci->RF_RX0_lnaa_tune); ++ write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX0, ++ ci->RF_RX0_lnag_tune); ++ write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX0, ++ ci->RF_TX0_intpaa_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX0, ++ ci->RF_TX0_intpag_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX0, ++ ci->RF_TX0_pada_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX0, ++ ci->RF_TX0_padg_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX0, ++ ci->RF_TX0_pgaa_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX0, ++ ci->RF_TX0_pgag_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX0, ++ ci->RF_TX0_mixa_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX0, ++ ci->RF_TX0_mixg_boost_tune); ++ ++ write_radio_reg(pi, ++ RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX1, ++ ci->RF_RX1_lnaa_tune); ++ write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX1, ++ ci->RF_RX1_lnag_tune); ++ write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX1, ++ ci->RF_TX1_intpaa_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX1, ++ ci->RF_TX1_intpag_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX1, ++ ci->RF_TX1_pada_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX1, ++ ci->RF_TX1_padg_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX1, ++ ci->RF_TX1_pgaa_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX1, ++ ci->RF_TX1_pgag_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX1, ++ ci->RF_TX1_mixa_boost_tune); ++ write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX1, ++ ci->RF_TX1_mixg_boost_tune); ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 3)) ++ regs_SYN_2056_ptr = regs_SYN_2056; ++ else if (NREV_IS(pi->pubpi.phy_rev, 4)) ++ regs_SYN_2056_ptr = regs_SYN_2056_A1; ++ else { ++ switch (pi->pubpi.radiorev) { ++ case 5: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev5; ++ break; ++ case 6: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev6; ++ break; ++ case 7: ++ case 9: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev7; ++ break; ++ case 8: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev8; ++ break; ++ case 11: ++ regs_SYN_2056_ptr = regs_SYN_2056_rev11; ++ break; ++ } ++ } ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | ++ RADIO_2056_SYN, ++ (u16) regs_SYN_2056_ptr[0x49 - 2].init_g); ++ else ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | ++ RADIO_2056_SYN, ++ (u16) regs_SYN_2056_ptr[0x49 - 2].init_a); ++ ++ if (pi->sh->boardflags2 & BFL2_GPLL_WAR) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 | ++ RADIO_2056_SYN, 0x1f); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | ++ RADIO_2056_SYN, 0x1f); ++ ++ write_radio_reg(pi, ++ RADIO_2056_SYN_PLL_LOOPFILTER4 | ++ RADIO_2056_SYN, 0xb); ++ write_radio_reg(pi, ++ RADIO_2056_SYN_PLL_CP2 | ++ RADIO_2056_SYN, 0x14); ++ } ++ } ++ ++ if ((pi->sh->boardflags2 & BFL2_GPLL_WAR2) && ++ (CHSPEC_IS2G(pi->radio_chanspec))) { ++ write_radio_reg(pi, ++ RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN, ++ 0x1f); ++ write_radio_reg(pi, ++ RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN, ++ 0x1f); ++ write_radio_reg(pi, ++ RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN, ++ 0xb); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | RADIO_2056_SYN, ++ 0x20); ++ } ++ ++ if (pi->sh->boardflags2 & BFL2_APLL_WAR) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 | ++ RADIO_2056_SYN, 0x1f); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | ++ RADIO_2056_SYN, 0x1f); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 | ++ RADIO_2056_SYN, 0x5); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | ++ RADIO_2056_SYN, 0xc); ++ } ++ } ++ ++ if (PHY_IPA(pi) && CHSPEC_IS2G(pi->radio_chanspec)) { ++ u16 pag_boost_tune; ++ u16 padg_boost_tune; ++ u16 pgag_boost_tune; ++ u16 mixg_boost_tune; ++ u16 bias, cascbias; ++ uint core; ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 5)) { ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ PADG_IDAC, 0xcc); ++ ++ bias = 0x25; ++ cascbias = 0x20; ++ ++ if ((pi->sh->chip == ++ BCM43224_CHIP_ID) ++ || (pi->sh->chip == ++ BCM43225_CHIP_ID)) { ++ if (pi->sh->chippkg == ++ BCM43224_FAB_SMIC) { ++ bias = 0x2a; ++ cascbias = 0x38; ++ } ++ } ++ ++ pag_boost_tune = 0x4; ++ pgag_boost_tune = 0x03; ++ padg_boost_tune = 0x77; ++ mixg_boost_tune = 0x65; ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_IMAIN_STAT, bias); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_IAUX_STAT, bias); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_CASCBIAS, cascbias); ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_BOOST_TUNE, ++ pag_boost_tune); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ PGAG_BOOST_TUNE, ++ pgag_boost_tune); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ PADG_BOOST_TUNE, ++ padg_boost_tune); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ MIXG_BOOST_TUNE, ++ mixg_boost_tune); ++ } else { ++ ++ bias = (pi->bw == WL_CHANSPEC_BW_40) ? ++ 0x40 : 0x20; ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_IMAIN_STAT, bias); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_IAUX_STAT, bias); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_CASCBIAS, 0x30); ++ } ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, PA_SPARE1, ++ 0xee); ++ } ++ } ++ ++ if (PHY_IPA(pi) && NREV_IS(pi->pubpi.phy_rev, 6) ++ && CHSPEC_IS5G(pi->radio_chanspec)) { ++ u16 paa_boost_tune; ++ u16 pada_boost_tune; ++ u16 pgaa_boost_tune; ++ u16 mixa_boost_tune; ++ u16 freq, pabias, cascbias; ++ uint core; ++ ++ freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec)); ++ ++ if (freq < 5150) { ++ ++ paa_boost_tune = 0xa; ++ pada_boost_tune = 0x77; ++ pgaa_boost_tune = 0xf; ++ mixa_boost_tune = 0xf; ++ } else if (freq < 5340) { ++ ++ paa_boost_tune = 0x8; ++ pada_boost_tune = 0x77; ++ pgaa_boost_tune = 0xfb; ++ mixa_boost_tune = 0xf; ++ } else if (freq < 5650) { ++ ++ paa_boost_tune = 0x0; ++ pada_boost_tune = 0x77; ++ pgaa_boost_tune = 0xb; ++ mixa_boost_tune = 0xf; ++ } else { ++ ++ paa_boost_tune = 0x0; ++ pada_boost_tune = 0x77; ++ if (freq != 5825) ++ pgaa_boost_tune = -(int)(freq - 18) / 36 + 168; ++ else ++ pgaa_boost_tune = 6; ++ ++ mixa_boost_tune = 0xf; ++ } ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAA_BOOST_TUNE, paa_boost_tune); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ PADA_BOOST_TUNE, pada_boost_tune); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ PGAA_BOOST_TUNE, pgaa_boost_tune); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ MIXA_BOOST_TUNE, mixa_boost_tune); ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ TXSPARE1, 0x30); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ PA_SPARE2, 0xee); ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ PADA_CASCBIAS, 0x3); ++ ++ cascbias = 0x30; ++ ++ if ((pi->sh->chip == BCM43224_CHIP_ID) || ++ (pi->sh->chip == BCM43225_CHIP_ID)) { ++ if (pi->sh->chippkg == BCM43224_FAB_SMIC) ++ cascbias = 0x35; ++ } ++ ++ pabias = (pi->phy_pabias == 0) ? 0x30 : pi->phy_pabias; ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAA_IAUX_STAT, pabias); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAA_IMAIN_STAT, pabias); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAA_CASCBIAS, cascbias); ++ } ++ } ++ ++ udelay(50); ++ ++ wlc_phy_radio205x_vcocal_nphy(pi); ++} ++ ++void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi) ++{ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x0); ++ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04, 0x0); ++ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04, ++ (1 << 2)); ++ mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x01); ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL12, 0x0); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x18); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38); ++ write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x39); ++ } ++ ++ udelay(300); ++} ++ ++static void ++wlc_phy_chanspec_radio2057_setup( ++ struct brcms_phy *pi, ++ const struct chan_info_nphy_radio2057 *ci, ++ const struct chan_info_nphy_radio2057_rev5 * ++ ci2) ++{ ++ int coreNum; ++ u16 txmix2g_tune_boost_pu = 0; ++ u16 pad2g_tune_pus = 0; ++ ++ if (pi->pubpi.radiorev == 5) { ++ ++ write_radio_reg(pi, ++ RADIO_2057_VCOCAL_COUNTVAL0, ++ ci2->RF_vcocal_countval0); ++ write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1, ++ ci2->RF_vcocal_countval1); ++ write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE, ++ ci2->RF_rfpll_refmaster_sparextalsize); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, ++ ci2->RF_rfpll_loopfilter_r1); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, ++ ci2->RF_rfpll_loopfilter_c2); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, ++ ci2->RF_rfpll_loopfilter_c1); ++ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, ++ ci2->RF_cp_kpd_idac); ++ write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci2->RF_rfpll_mmd0); ++ write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci2->RF_rfpll_mmd1); ++ write_radio_reg(pi, ++ RADIO_2057_VCOBUF_TUNE, ci2->RF_vcobuf_tune); ++ write_radio_reg(pi, ++ RADIO_2057_LOGEN_MX2G_TUNE, ++ ci2->RF_logen_mx2g_tune); ++ write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE, ++ ci2->RF_logen_indbuf2g_tune); ++ ++ write_radio_reg(pi, ++ RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0, ++ ci2->RF_txmix2g_tune_boost_pu_core0); ++ write_radio_reg(pi, ++ RADIO_2057_PAD2G_TUNE_PUS_CORE0, ++ ci2->RF_pad2g_tune_pus_core0); ++ write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0, ++ ci2->RF_lna2g_tune_core0); ++ ++ write_radio_reg(pi, ++ RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1, ++ ci2->RF_txmix2g_tune_boost_pu_core1); ++ write_radio_reg(pi, ++ RADIO_2057_PAD2G_TUNE_PUS_CORE1, ++ ci2->RF_pad2g_tune_pus_core1); ++ write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1, ++ ci2->RF_lna2g_tune_core1); ++ ++ } else { ++ ++ write_radio_reg(pi, ++ RADIO_2057_VCOCAL_COUNTVAL0, ++ ci->RF_vcocal_countval0); ++ write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1, ++ ci->RF_vcocal_countval1); ++ write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE, ++ ci->RF_rfpll_refmaster_sparextalsize); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, ++ ci->RF_rfpll_loopfilter_r1); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, ++ ci->RF_rfpll_loopfilter_c2); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, ++ ci->RF_rfpll_loopfilter_c1); ++ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, ci->RF_cp_kpd_idac); ++ write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci->RF_rfpll_mmd0); ++ write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci->RF_rfpll_mmd1); ++ write_radio_reg(pi, RADIO_2057_VCOBUF_TUNE, ci->RF_vcobuf_tune); ++ write_radio_reg(pi, ++ RADIO_2057_LOGEN_MX2G_TUNE, ++ ci->RF_logen_mx2g_tune); ++ write_radio_reg(pi, RADIO_2057_LOGEN_MX5G_TUNE, ++ ci->RF_logen_mx5g_tune); ++ write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE, ++ ci->RF_logen_indbuf2g_tune); ++ write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF5G_TUNE, ++ ci->RF_logen_indbuf5g_tune); ++ ++ write_radio_reg(pi, ++ RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0, ++ ci->RF_txmix2g_tune_boost_pu_core0); ++ write_radio_reg(pi, ++ RADIO_2057_PAD2G_TUNE_PUS_CORE0, ++ ci->RF_pad2g_tune_pus_core0); ++ write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE0, ++ ci->RF_pga_boost_tune_core0); ++ write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE0, ++ ci->RF_txmix5g_boost_tune_core0); ++ write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE0, ++ ci->RF_pad5g_tune_misc_pus_core0); ++ write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0, ++ ci->RF_lna2g_tune_core0); ++ write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE0, ++ ci->RF_lna5g_tune_core0); ++ ++ write_radio_reg(pi, ++ RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1, ++ ci->RF_txmix2g_tune_boost_pu_core1); ++ write_radio_reg(pi, ++ RADIO_2057_PAD2G_TUNE_PUS_CORE1, ++ ci->RF_pad2g_tune_pus_core1); ++ write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE1, ++ ci->RF_pga_boost_tune_core1); ++ write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE1, ++ ci->RF_txmix5g_boost_tune_core1); ++ write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE1, ++ ci->RF_pad5g_tune_misc_pus_core1); ++ write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1, ++ ci->RF_lna2g_tune_core1); ++ write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE1, ++ ci->RF_lna5g_tune_core1); ++ } ++ ++ if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) { ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, ++ 0x3f); ++ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, ++ 0x8); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, ++ 0x8); ++ } else { ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, ++ 0x1f); ++ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, ++ 0x8); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, ++ 0x8); ++ } ++ } else if ((pi->pubpi.radiorev == 5) || (pi->pubpi.radiorev == 7) || ++ (pi->pubpi.radiorev == 8)) { ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, ++ 0x1b); ++ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x30); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, ++ 0xa); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, ++ 0xa); ++ } else { ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1, ++ 0x1f); ++ write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1, ++ 0x8); ++ write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2, ++ 0x8); ++ } ++ ++ } ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (PHY_IPA(pi)) { ++ if (pi->pubpi.radiorev == 3) ++ txmix2g_tune_boost_pu = 0x6b; ++ ++ if (pi->pubpi.radiorev == 5) ++ pad2g_tune_pus = 0x73; ++ ++ } else { ++ if (pi->pubpi.radiorev != 5) { ++ pad2g_tune_pus = 0x3; ++ ++ txmix2g_tune_boost_pu = 0x61; ++ } ++ } ++ ++ for (coreNum = 0; coreNum <= 1; coreNum++) { ++ ++ if (txmix2g_tune_boost_pu != 0) ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, ++ TXMIX2G_TUNE_BOOST_PU, ++ txmix2g_tune_boost_pu); ++ ++ if (pad2g_tune_pus != 0) ++ WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum, ++ PAD2G_TUNE_PUS, ++ pad2g_tune_pus); ++ } ++ } ++ ++ udelay(50); ++ ++ wlc_phy_radio205x_vcocal_nphy(pi); ++} ++ ++static void ++wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, ++ const struct nphy_sfo_cfg *ci) ++{ ++ u16 val; ++ ++ val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; ++ if (CHSPEC_IS5G(chanspec) && !val) { ++ ++ val = R_REG(&pi->regs->psm_phy_hdr_param); ++ W_REG(&pi->regs->psm_phy_hdr_param, ++ (val | MAC_PHY_FORCE_CLK)); ++ ++ or_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG), ++ (BBCFG_RESETCCA | BBCFG_RESETRX)); ++ ++ W_REG(&pi->regs->psm_phy_hdr_param, val); ++ ++ or_phy_reg(pi, 0x09, NPHY_BandControl_currentBand); ++ } else if (!CHSPEC_IS5G(chanspec) && val) { ++ ++ and_phy_reg(pi, 0x09, ~NPHY_BandControl_currentBand); ++ ++ val = R_REG(&pi->regs->psm_phy_hdr_param); ++ W_REG(&pi->regs->psm_phy_hdr_param, ++ (val | MAC_PHY_FORCE_CLK)); ++ ++ and_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG), ++ (u16) (~(BBCFG_RESETCCA | BBCFG_RESETRX))); ++ ++ W_REG(&pi->regs->psm_phy_hdr_param, val); ++ } ++ ++ write_phy_reg(pi, 0x1ce, ci->PHY_BW1a); ++ write_phy_reg(pi, 0x1cf, ci->PHY_BW2); ++ write_phy_reg(pi, 0x1d0, ci->PHY_BW3); ++ ++ write_phy_reg(pi, 0x1d1, ci->PHY_BW4); ++ write_phy_reg(pi, 0x1d2, ci->PHY_BW5); ++ write_phy_reg(pi, 0x1d3, ci->PHY_BW6); ++ ++ if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) { ++ wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en, 0); ++ ++ or_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, 0x800); ++ } else { ++ wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en, ++ NPHY_ClassifierCtrl_ofdm_en); ++ ++ if (CHSPEC_IS2G(chanspec)) ++ and_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, ~0x840); ++ } ++ ++ if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) ++ wlc_phy_txpwr_fixpower_nphy(pi); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) ++ wlc_phy_adjust_lnagaintbl_nphy(pi); ++ ++ wlc_phy_txlpfbw_nphy(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3) ++ && (pi->phy_spuravoid != SPURAVOID_DISABLE)) { ++ u8 spuravoid = 0; ++ ++ val = CHSPEC_CHANNEL(chanspec); ++ if (!CHSPEC_IS40(pi->radio_chanspec)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if ((val == 13) || (val == 14) || (val == 153)) ++ spuravoid = 1; ++ } else if (((val >= 5) && (val <= 8)) || (val == 13) ++ || (val == 14)) { ++ spuravoid = 1; ++ } ++ } else if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (val == 54) ++ spuravoid = 1; ++ } else { ++ if (pi->nphy_aband_spurwar_en && ++ ((val == 38) || (val == 102) ++ || (val == 118))) ++ spuravoid = 1; ++ } ++ ++ if (pi->phy_spuravoid == SPURAVOID_FORCEON) ++ spuravoid = 1; ++ ++ wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false); ++ si_pmu_spuravoid(pi->sh->sih, spuravoid); ++ wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true); ++ ++ if ((pi->sh->chip == BCM43224_CHIP_ID) || ++ (pi->sh->chip == BCM43225_CHIP_ID)) { ++ ++ if (spuravoid == 1) { ++ ++ W_REG(&pi->regs->tsf_clk_frac_l, ++ 0x5341); ++ W_REG(&pi->regs->tsf_clk_frac_h, ++ 0x8); ++ } else { ++ ++ W_REG(&pi->regs->tsf_clk_frac_l, ++ 0x8889); ++ W_REG(&pi->regs->tsf_clk_frac_h, ++ 0x8); ++ } ++ } ++ ++ wlapi_bmac_core_phypll_reset(pi->sh->physhim); ++ ++ mod_phy_reg(pi, 0x01, (0x1 << 15), ++ ((spuravoid > 0) ? (0x1 << 15) : 0)); ++ ++ wlc_phy_resetcca_nphy(pi); ++ ++ pi->phy_isspuravoid = (spuravoid > 0); ++ } ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 7)) ++ write_phy_reg(pi, 0x17e, 0x3830); ++ ++ wlc_phy_spurwar_nphy(pi); ++} ++ ++void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, u16 chanspec) ++{ ++ int freq; ++ const struct chan_info_nphy_radio2057 *t0 = NULL; ++ const struct chan_info_nphy_radio205x *t1 = NULL; ++ const struct chan_info_nphy_radio2057_rev5 *t2 = NULL; ++ const struct chan_info_nphy_2055 *t3 = NULL; ++ ++ if (!wlc_phy_chan2freq_nphy ++ (pi, CHSPEC_CHANNEL(chanspec), &freq, &t0, &t1, &t2, &t3)) ++ return; ++ ++ wlc_phy_chanspec_radio_set((struct brcms_phy_pub *) pi, chanspec); ++ ++ if (CHSPEC_BW(chanspec) != pi->bw) ++ wlapi_bmac_bw_set(pi->sh->physhim, CHSPEC_BW(chanspec)); ++ ++ if (CHSPEC_IS40(chanspec)) { ++ if (CHSPEC_SB_UPPER(chanspec)) { ++ or_phy_reg(pi, 0xa0, BPHY_BAND_SEL_UP20); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ or_phy_reg(pi, 0x310, PRIM_SEL_UP20); ++ } else { ++ and_phy_reg(pi, 0xa0, ~BPHY_BAND_SEL_UP20); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ and_phy_reg(pi, 0x310, ++ (~PRIM_SEL_UP20 & 0xffff)); ++ } ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ if ((pi->pubpi.radiorev <= 4) ++ || (pi->pubpi.radiorev == 6)) { ++ mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE0, ++ 0x2, ++ (CHSPEC_IS5G(chanspec) ? (1 << 1) ++ : 0)); ++ mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE1, ++ 0x2, ++ (CHSPEC_IS5G(chanspec) ? (1 << 1) ++ : 0)); ++ } ++ ++ wlc_phy_chanspec_radio2057_setup(pi, t0, t2); ++ wlc_phy_chanspec_nphy_setup(pi, chanspec, ++ (pi->pubpi.radiorev == 5) ? ++ (const struct nphy_sfo_cfg *)&(t2->PHY_BW1a) : ++ (const struct nphy_sfo_cfg *)&(t0->PHY_BW1a)); ++ ++ } else { ++ ++ mod_radio_reg(pi, ++ RADIO_2056_SYN_COM_CTRL | RADIO_2056_SYN, ++ 0x4, ++ (CHSPEC_IS5G(chanspec) ? (0x1 << 2) : 0)); ++ wlc_phy_chanspec_radio2056_setup(pi, t1); ++ ++ wlc_phy_chanspec_nphy_setup(pi, chanspec, ++ (const struct nphy_sfo_cfg *) &(t1->PHY_BW1a)); ++ } ++ ++ } else { ++ ++ mod_radio_reg(pi, RADIO_2055_MASTER_CNTRL1, 0x70, ++ (CHSPEC_IS5G(chanspec) ? (0x02 << 4) ++ : (0x05 << 4))); ++ ++ wlc_phy_chanspec_radio2055_setup(pi, t3); ++ wlc_phy_chanspec_nphy_setup(pi, chanspec, ++ (const struct nphy_sfo_cfg *) ++ &(t3->PHY_BW1a)); ++ } ++ ++} ++ ++void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init) ++{ ++ struct brcms_phy *pi = (struct brcms_phy *) ppi; ++ u16 mask = 0xfc00; ++ u32 mc = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ return; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ u16 v0 = 0x211, v1 = 0x222, v2 = 0x144, v3 = 0x188; ++ ++ if (lut_init == false) ++ return; ++ ++ if (pi->srom_fem2g.antswctrllut == 0) { ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 1, 0x02, 16, &v0); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 1, 0x03, 16, &v1); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 1, 0x08, 16, &v2); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 1, 0x0C, 16, &v3); ++ } ++ ++ if (pi->srom_fem5g.antswctrllut == 0) { ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 1, 0x12, 16, &v0); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 1, 0x13, 16, &v1); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 1, 0x18, 16, &v2); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT, ++ 1, 0x1C, 16, &v3); ++ } ++ } else { ++ ++ write_phy_reg(pi, 0xc8, 0x0); ++ write_phy_reg(pi, 0xc9, 0x0); ++ ++ ai_gpiocontrol(pi->sh->sih, mask, mask, GPIO_DRV_PRIORITY); ++ ++ mc = R_REG(&pi->regs->maccontrol); ++ mc &= ~MCTL_GPOUT_SEL_MASK; ++ W_REG(&pi->regs->maccontrol, mc); ++ ++ OR_REG(&pi->regs->psm_gpio_oe, mask); ++ ++ AND_REG(&pi->regs->psm_gpio_out, ~mask); ++ ++ if (lut_init) { ++ write_phy_reg(pi, 0xf8, 0x02d8); ++ write_phy_reg(pi, 0xf9, 0x0301); ++ write_phy_reg(pi, 0xfa, 0x02d8); ++ write_phy_reg(pi, 0xfb, 0x0301); ++ } ++ } ++} ++ ++u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val) ++{ ++ u16 curr_ctl, new_ctl; ++ bool suspended = false; ++ ++ if (D11REV_IS(pi->sh->corerev, 16)) { ++ suspended = ++ (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ? ++ false : true; ++ if (!suspended) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ } ++ ++ curr_ctl = read_phy_reg(pi, 0xb0) & (0x7 << 0); ++ ++ new_ctl = (curr_ctl & (~mask)) | (val & mask); ++ ++ mod_phy_reg(pi, 0xb0, (0x7 << 0), new_ctl); ++ ++ if (D11REV_IS(pi->sh->corerev, 16) && !suspended) ++ wlapi_enable_mac(pi->sh->physhim); ++ ++ return new_ctl; ++} ++ ++void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd) ++{ ++ u16 trigger_mask, status_mask; ++ u16 orig_RfseqCoreActv; ++ ++ switch (cmd) { ++ case NPHY_RFSEQ_RX2TX: ++ trigger_mask = NPHY_RfseqTrigger_rx2tx; ++ status_mask = NPHY_RfseqStatus_rx2tx; ++ break; ++ case NPHY_RFSEQ_TX2RX: ++ trigger_mask = NPHY_RfseqTrigger_tx2rx; ++ status_mask = NPHY_RfseqStatus_tx2rx; ++ break; ++ case NPHY_RFSEQ_RESET2RX: ++ trigger_mask = NPHY_RfseqTrigger_reset2rx; ++ status_mask = NPHY_RfseqStatus_reset2rx; ++ break; ++ case NPHY_RFSEQ_UPDATEGAINH: ++ trigger_mask = NPHY_RfseqTrigger_updategainh; ++ status_mask = NPHY_RfseqStatus_updategainh; ++ break; ++ case NPHY_RFSEQ_UPDATEGAINL: ++ trigger_mask = NPHY_RfseqTrigger_updategainl; ++ status_mask = NPHY_RfseqStatus_updategainl; ++ break; ++ case NPHY_RFSEQ_UPDATEGAINU: ++ trigger_mask = NPHY_RfseqTrigger_updategainu; ++ status_mask = NPHY_RfseqStatus_updategainu; ++ break; ++ default: ++ return; ++ } ++ ++ orig_RfseqCoreActv = read_phy_reg(pi, 0xa1); ++ or_phy_reg(pi, 0xa1, ++ (NPHY_RfseqMode_CoreActv_override | ++ NPHY_RfseqMode_Trigger_override)); ++ or_phy_reg(pi, 0xa3, trigger_mask); ++ SPINWAIT((read_phy_reg(pi, 0xa4) & status_mask), 200000); ++ write_phy_reg(pi, 0xa1, orig_RfseqCoreActv); ++ WARN(read_phy_reg(pi, 0xa4) & status_mask, "HW error in rf"); ++} ++ ++static void ++wlc_phy_rfctrl_override_1tomany_nphy(struct brcms_phy *pi, u16 cmd, u16 value, ++ u8 core_mask, u8 off) ++{ ++ u16 rfmxgain = 0, lpfgain = 0; ++ u16 tgain = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ switch (cmd) { ++ case NPHY_REV7_RfctrlOverride_cmd_rxrf_pu: ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 5), ++ value, core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 4), value, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 3), value, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ break; ++ case NPHY_REV7_RfctrlOverride_cmd_rx_pu: ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 2), ++ value, core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 1), value, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 0), value, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 1), value, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 11), 0, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ break; ++ case NPHY_REV7_RfctrlOverride_cmd_tx_pu: ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 2), ++ value, core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 1), value, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 0), value, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 2), value, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 11), 1, ++ core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ break; ++ case NPHY_REV7_RfctrlOverride_cmd_rxgain: ++ rfmxgain = value & 0x000ff; ++ lpfgain = value & 0x0ff00; ++ lpfgain = lpfgain >> 8; ++ ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 11), ++ rfmxgain, core_mask, ++ off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x3 << 13), ++ lpfgain, core_mask, ++ off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ break; ++ case NPHY_REV7_RfctrlOverride_cmd_txgain: ++ tgain = value & 0x7fff; ++ lpfgain = value & 0x8000; ++ lpfgain = lpfgain >> 14; ++ ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 12), ++ tgain, core_mask, off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 13), ++ lpfgain, core_mask, ++ off, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ break; ++ } ++ } ++} ++ ++static void ++wlc_phy_scale_offset_rssi_nphy(struct brcms_phy *pi, u16 scale, s8 offset, ++ u8 coresel, u8 rail, u8 rssi_type) ++{ ++ u16 valuetostuff; ++ ++ offset = (offset > NPHY_RSSICAL_MAXREAD) ? ++ NPHY_RSSICAL_MAXREAD : offset; ++ offset = (offset < (-NPHY_RSSICAL_MAXREAD - 1)) ? ++ -NPHY_RSSICAL_MAXREAD - 1 : offset; ++ ++ valuetostuff = ((scale & 0x3f) << 8) | (offset & 0x3f); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) ++ write_phy_reg(pi, 0x1a6, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) ++ write_phy_reg(pi, 0x1ac, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) ++ write_phy_reg(pi, 0x1b2, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) ++ write_phy_reg(pi, 0x1b8, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) ++ write_phy_reg(pi, 0x1a4, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) ++ write_phy_reg(pi, 0x1aa, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) ++ write_phy_reg(pi, 0x1b0, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) ++ write_phy_reg(pi, 0x1b6, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) ++ write_phy_reg(pi, 0x1a5, valuetostuff); ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) ++ write_phy_reg(pi, 0x1ab, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) ++ write_phy_reg(pi, 0x1b1, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) ++ write_phy_reg(pi, 0x1b7, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) ++ write_phy_reg(pi, 0x1a7, valuetostuff); ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) ++ write_phy_reg(pi, 0x1ad, valuetostuff); ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) ++ write_phy_reg(pi, 0x1b3, valuetostuff); ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) ++ write_phy_reg(pi, 0x1b9, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) ++ write_phy_reg(pi, 0x1a8, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) ++ write_phy_reg(pi, 0x1ae, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) ++ write_phy_reg(pi, 0x1b4, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) ++ write_phy_reg(pi, 0x1ba, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) ++ write_phy_reg(pi, 0x1a9, valuetostuff); ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) ++ write_phy_reg(pi, 0x1b5, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE1) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) ++ write_phy_reg(pi, 0x1af, valuetostuff); ++ ++ if (((coresel == RADIO_MIMO_CORESEL_CORE2) || ++ (coresel == RADIO_MIMO_CORESEL_ALLRX)) && ++ (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) ++ write_phy_reg(pi, 0x1bb, valuetostuff); ++} ++ ++static void brcms_phy_wr_tx_mux(struct brcms_phy *pi, u8 core) ++{ ++ if (PHY_IPA(pi)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ write_radio_reg(pi, ++ ((core == PHY_CORE_0) ? ++ RADIO_2057_TX0_TX_SSI_MUX : ++ RADIO_2057_TX1_TX_SSI_MUX), ++ (CHSPEC_IS5G(pi->radio_chanspec) ? ++ 0xc : 0xe)); ++ else ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MUX | ++ ((core == PHY_CORE_0) ? ++ RADIO_2056_TX0 : RADIO_2056_TX1), ++ (CHSPEC_IS5G(pi->radio_chanspec) ? ++ 0xc : 0xe)); ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ write_radio_reg(pi, ++ ((core == PHY_CORE_0) ? ++ RADIO_2057_TX0_TX_SSI_MUX : ++ RADIO_2057_TX1_TX_SSI_MUX), ++ 0x11); ++ ++ if (pi->pubpi.radioid == BCM2057_ID) ++ write_radio_reg(pi, ++ RADIO_2057_IQTEST_SEL_PU, 0x1); ++ ++ } else { ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MUX | ++ ((core == PHY_CORE_0) ? ++ RADIO_2056_TX0 : RADIO_2056_TX1), ++ 0x11); ++ } ++ } ++} ++ ++void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type) ++{ ++ u16 mask, val; ++ u16 afectrlovr_rssi_val, rfctrlcmd_rxen_val, rfctrlcmd_coresel_val, ++ startseq; ++ u16 rfctrlovr_rssi_val, rfctrlovr_rxen_val, rfctrlovr_coresel_val, ++ rfctrlovr_trigger_val; ++ u16 afectrlovr_rssi_mask, rfctrlcmd_mask, rfctrlovr_mask; ++ u16 rfctrlcmd_val, rfctrlovr_val; ++ u8 core; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (core_code == RADIO_MIMO_CORESEL_OFF) { ++ mod_phy_reg(pi, 0x8f, (0x1 << 9), 0); ++ mod_phy_reg(pi, 0xa5, (0x1 << 9), 0); ++ ++ mod_phy_reg(pi, 0xa6, (0x3 << 8), 0); ++ mod_phy_reg(pi, 0xa7, (0x3 << 8), 0); ++ ++ mod_phy_reg(pi, 0xe5, (0x1 << 5), 0); ++ mod_phy_reg(pi, 0xe6, (0x1 << 5), 0); ++ ++ mask = (0x1 << 2) | ++ (0x1 << 3) | (0x1 << 4) | (0x1 << 5); ++ mod_phy_reg(pi, 0xf9, mask, 0); ++ mod_phy_reg(pi, 0xfb, mask, 0); ++ ++ } else { ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ if (core_code == RADIO_MIMO_CORESEL_CORE1 ++ && core == PHY_CORE_1) ++ continue; ++ else if (core_code == RADIO_MIMO_CORESEL_CORE2 ++ && core == PHY_CORE_0) ++ continue; ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0x8f : 0xa5, (0x1 << 9), 1 << 9); ++ ++ if (rssi_type == NPHY_RSSI_SEL_W1 || ++ rssi_type == NPHY_RSSI_SEL_W2 || ++ rssi_type == NPHY_RSSI_SEL_NB) { ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xa6 : 0xa7, ++ (0x3 << 8), 0); ++ ++ mask = (0x1 << 2) | ++ (0x1 << 3) | ++ (0x1 << 4) | (0x1 << 5); ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xf9 : 0xfb, ++ mask, 0); ++ ++ if (rssi_type == NPHY_RSSI_SEL_W1) { ++ if (CHSPEC_IS5G( ++ pi->radio_chanspec)) { ++ mask = (0x1 << 2); ++ val = 1 << 2; ++ } else { ++ mask = (0x1 << 3); ++ val = 1 << 3; ++ } ++ } else if (rssi_type == ++ NPHY_RSSI_SEL_W2) { ++ mask = (0x1 << 4); ++ val = 1 << 4; ++ } else { ++ mask = (0x1 << 5); ++ val = 1 << 5; ++ } ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xf9 : 0xfb, ++ mask, val); ++ ++ mask = (0x1 << 5); ++ val = 1 << 5; ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0xe5 : 0xe6, mask, val); ++ } else { ++ if (rssi_type == NPHY_RSSI_SEL_TBD) { ++ mask = (0x3 << 8); ++ val = 1 << 8; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xa6 ++ : 0xa7, mask, val); ++ mask = (0x3 << 10); ++ val = 1 << 10; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xa6 ++ : 0xa7, mask, val); ++ } else if (rssi_type == ++ NPHY_RSSI_SEL_IQ) { ++ mask = (0x3 << 8); ++ val = 2 << 8; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xa6 ++ : 0xa7, mask, val); ++ mask = (0x3 << 10); ++ val = 2 << 10; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xa6 ++ : 0xa7, mask, val); ++ } else { ++ mask = (0x3 << 8); ++ val = 3 << 8; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xa6 ++ : 0xa7, mask, val); ++ mask = (0x3 << 10); ++ val = 3 << 10; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0xa6 ++ : 0xa7, mask, val); ++ brcms_phy_wr_tx_mux(pi, core); ++ afectrlovr_rssi_val = 1 << 9; ++ mod_phy_reg(pi, ++ (core == ++ PHY_CORE_0) ? 0x8f ++ : 0xa5, (0x1 << 9), ++ afectrlovr_rssi_val); ++ } ++ } ++ } ++ } ++ } else { ++ ++ if ((rssi_type == NPHY_RSSI_SEL_W1) || ++ (rssi_type == NPHY_RSSI_SEL_W2) || ++ (rssi_type == NPHY_RSSI_SEL_NB)) ++ val = 0x0; ++ else if (rssi_type == NPHY_RSSI_SEL_TBD) ++ val = 0x1; ++ else if (rssi_type == NPHY_RSSI_SEL_IQ) ++ val = 0x2; ++ else ++ val = 0x3; ++ ++ mask = ((0x3 << 12) | (0x3 << 14)); ++ val = (val << 12) | (val << 14); ++ mod_phy_reg(pi, 0xa6, mask, val); ++ mod_phy_reg(pi, 0xa7, mask, val); ++ ++ if ((rssi_type == NPHY_RSSI_SEL_W1) || ++ (rssi_type == NPHY_RSSI_SEL_W2) || ++ (rssi_type == NPHY_RSSI_SEL_NB)) { ++ if (rssi_type == NPHY_RSSI_SEL_W1) ++ val = 0x1; ++ if (rssi_type == NPHY_RSSI_SEL_W2) ++ val = 0x2; ++ if (rssi_type == NPHY_RSSI_SEL_NB) ++ val = 0x3; ++ ++ mask = (0x3 << 4); ++ val = (val << 4); ++ mod_phy_reg(pi, 0x7a, mask, val); ++ mod_phy_reg(pi, 0x7d, mask, val); ++ } ++ ++ if (core_code == RADIO_MIMO_CORESEL_OFF) { ++ afectrlovr_rssi_val = 0; ++ rfctrlcmd_rxen_val = 0; ++ rfctrlcmd_coresel_val = 0; ++ rfctrlovr_rssi_val = 0; ++ rfctrlovr_rxen_val = 0; ++ rfctrlovr_coresel_val = 0; ++ rfctrlovr_trigger_val = 0; ++ startseq = 0; ++ } else { ++ afectrlovr_rssi_val = 1; ++ rfctrlcmd_rxen_val = 1; ++ rfctrlcmd_coresel_val = core_code; ++ rfctrlovr_rssi_val = 1; ++ rfctrlovr_rxen_val = 1; ++ rfctrlovr_coresel_val = 1; ++ rfctrlovr_trigger_val = 1; ++ startseq = 1; ++ } ++ ++ afectrlovr_rssi_mask = ((0x1 << 12) | (0x1 << 13)); ++ afectrlovr_rssi_val = (afectrlovr_rssi_val << ++ 12) | (afectrlovr_rssi_val << 13); ++ mod_phy_reg(pi, 0xa5, afectrlovr_rssi_mask, ++ afectrlovr_rssi_val); ++ ++ if ((rssi_type == NPHY_RSSI_SEL_W1) || ++ (rssi_type == NPHY_RSSI_SEL_W2) || ++ (rssi_type == NPHY_RSSI_SEL_NB)) { ++ rfctrlcmd_mask = ((0x1 << 8) | (0x7 << 3)); ++ rfctrlcmd_val = (rfctrlcmd_rxen_val << 8) | ++ (rfctrlcmd_coresel_val << 3); ++ ++ rfctrlovr_mask = ((0x1 << 5) | ++ (0x1 << 12) | ++ (0x1 << 1) | (0x1 << 0)); ++ rfctrlovr_val = (rfctrlovr_rssi_val << ++ 5) | ++ (rfctrlovr_rxen_val << 12) | ++ (rfctrlovr_coresel_val << 1) | ++ (rfctrlovr_trigger_val << 0); ++ ++ mod_phy_reg(pi, 0x78, rfctrlcmd_mask, rfctrlcmd_val); ++ mod_phy_reg(pi, 0xec, rfctrlovr_mask, rfctrlovr_val); ++ ++ mod_phy_reg(pi, 0x78, (0x1 << 0), (startseq << 0)); ++ udelay(20); ++ ++ mod_phy_reg(pi, 0xec, (0x1 << 0), 0); ++ } ++ } ++} ++ ++int ++wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, s32 *rssi_buf, ++ u8 nsamps) ++{ ++ s16 rssi0, rssi1; ++ u16 afectrlCore1_save = 0; ++ u16 afectrlCore2_save = 0; ++ u16 afectrlOverride1_save = 0; ++ u16 afectrlOverride2_save = 0; ++ u16 rfctrlOverrideAux0_save = 0; ++ u16 rfctrlOverrideAux1_save = 0; ++ u16 rfctrlMiscReg1_save = 0; ++ u16 rfctrlMiscReg2_save = 0; ++ u16 rfctrlcmd_save = 0; ++ u16 rfctrloverride_save = 0; ++ u16 rfctrlrssiothers1_save = 0; ++ u16 rfctrlrssiothers2_save = 0; ++ s8 tmp_buf[4]; ++ u8 ctr = 0, samp = 0; ++ s32 rssi_out_val; ++ u16 gpiosel_orig; ++ ++ afectrlCore1_save = read_phy_reg(pi, 0xa6); ++ afectrlCore2_save = read_phy_reg(pi, 0xa7); ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ rfctrlMiscReg1_save = read_phy_reg(pi, 0xf9); ++ rfctrlMiscReg2_save = read_phy_reg(pi, 0xfb); ++ afectrlOverride1_save = read_phy_reg(pi, 0x8f); ++ afectrlOverride2_save = read_phy_reg(pi, 0xa5); ++ rfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5); ++ rfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6); ++ } else { ++ afectrlOverride1_save = read_phy_reg(pi, 0xa5); ++ rfctrlcmd_save = read_phy_reg(pi, 0x78); ++ rfctrloverride_save = read_phy_reg(pi, 0xec); ++ rfctrlrssiothers1_save = read_phy_reg(pi, 0x7a); ++ rfctrlrssiothers2_save = read_phy_reg(pi, 0x7d); ++ } ++ ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type); ++ ++ gpiosel_orig = read_phy_reg(pi, 0xca); ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) ++ write_phy_reg(pi, 0xca, 5); ++ ++ for (ctr = 0; ctr < 4; ctr++) ++ rssi_buf[ctr] = 0; ++ ++ for (samp = 0; samp < nsamps; samp++) { ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) { ++ rssi0 = read_phy_reg(pi, 0x1c9); ++ rssi1 = read_phy_reg(pi, 0x1ca); ++ } else { ++ rssi0 = read_phy_reg(pi, 0x219); ++ rssi1 = read_phy_reg(pi, 0x21a); ++ } ++ ++ ctr = 0; ++ tmp_buf[ctr++] = ((s8) ((rssi0 & 0x3f) << 2)) >> 2; ++ tmp_buf[ctr++] = ((s8) (((rssi0 >> 8) & 0x3f) << 2)) >> 2; ++ tmp_buf[ctr++] = ((s8) ((rssi1 & 0x3f) << 2)) >> 2; ++ tmp_buf[ctr++] = ((s8) (((rssi1 >> 8) & 0x3f) << 2)) >> 2; ++ ++ for (ctr = 0; ctr < 4; ctr++) ++ rssi_buf[ctr] += tmp_buf[ctr]; ++ ++ } ++ ++ rssi_out_val = rssi_buf[3] & 0xff; ++ rssi_out_val |= (rssi_buf[2] & 0xff) << 8; ++ rssi_out_val |= (rssi_buf[1] & 0xff) << 16; ++ rssi_out_val |= (rssi_buf[0] & 0xff) << 24; ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) ++ write_phy_reg(pi, 0xca, gpiosel_orig); ++ ++ write_phy_reg(pi, 0xa6, afectrlCore1_save); ++ write_phy_reg(pi, 0xa7, afectrlCore2_save); ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ write_phy_reg(pi, 0xf9, rfctrlMiscReg1_save); ++ write_phy_reg(pi, 0xfb, rfctrlMiscReg2_save); ++ write_phy_reg(pi, 0x8f, afectrlOverride1_save); ++ write_phy_reg(pi, 0xa5, afectrlOverride2_save); ++ write_phy_reg(pi, 0xe5, rfctrlOverrideAux0_save); ++ write_phy_reg(pi, 0xe6, rfctrlOverrideAux1_save); ++ } else { ++ write_phy_reg(pi, 0xa5, afectrlOverride1_save); ++ write_phy_reg(pi, 0x78, rfctrlcmd_save); ++ write_phy_reg(pi, 0xec, rfctrloverride_save); ++ write_phy_reg(pi, 0x7a, rfctrlrssiothers1_save); ++ write_phy_reg(pi, 0x7d, rfctrlrssiothers2_save); ++ } ++ ++ return rssi_out_val; ++} ++ ++s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi) ++{ ++ u16 core1_txrf_iqcal1_save, core1_txrf_iqcal2_save; ++ u16 core2_txrf_iqcal1_save, core2_txrf_iqcal2_save; ++ u16 pwrdet_rxtx_core1_save; ++ u16 pwrdet_rxtx_core2_save; ++ u16 afectrlCore1_save; ++ u16 afectrlCore2_save; ++ u16 afectrlOverride_save; ++ u16 afectrlOverride2_save; ++ u16 pd_pll_ts_save; ++ u16 gpioSel_save; ++ s32 radio_temp[4]; ++ s32 radio_temp2[4]; ++ u16 syn_tempprocsense_save; ++ s16 offset = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ u16 auxADC_Vmid, auxADC_Av, auxADC_Vmid_save, auxADC_Av_save; ++ u16 auxADC_rssi_ctrlL_save, auxADC_rssi_ctrlH_save; ++ u16 auxADC_rssi_ctrlL, auxADC_rssi_ctrlH; ++ s32 auxADC_Vl; ++ u16 RfctrlOverride5_save, RfctrlOverride6_save; ++ u16 RfctrlMiscReg5_save, RfctrlMiscReg6_save; ++ u16 RSSIMultCoef0QPowerDet_save; ++ u16 tempsense_Rcal; ++ ++ syn_tempprocsense_save = ++ read_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG); ++ ++ afectrlCore1_save = read_phy_reg(pi, 0xa6); ++ afectrlCore2_save = read_phy_reg(pi, 0xa7); ++ afectrlOverride_save = read_phy_reg(pi, 0x8f); ++ afectrlOverride2_save = read_phy_reg(pi, 0xa5); ++ RSSIMultCoef0QPowerDet_save = read_phy_reg(pi, 0x1ae); ++ RfctrlOverride5_save = read_phy_reg(pi, 0x346); ++ RfctrlOverride6_save = read_phy_reg(pi, 0x347); ++ RfctrlMiscReg5_save = read_phy_reg(pi, 0x344); ++ RfctrlMiscReg6_save = read_phy_reg(pi, 0x345); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16, ++ &auxADC_Vmid_save); ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16, ++ &auxADC_Av_save); ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16, ++ &auxADC_rssi_ctrlL_save); ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16, ++ &auxADC_rssi_ctrlH_save); ++ ++ write_phy_reg(pi, 0x1ae, 0x0); ++ ++ auxADC_rssi_ctrlL = 0x0; ++ auxADC_rssi_ctrlH = 0x20; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16, ++ &auxADC_rssi_ctrlL); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16, ++ &auxADC_rssi_ctrlH); ++ ++ tempsense_Rcal = syn_tempprocsense_save & 0x1c; ++ ++ write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, ++ tempsense_Rcal | 0x01); ++ ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), ++ 1, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ mod_phy_reg(pi, 0xa6, (0x1 << 7), 0); ++ mod_phy_reg(pi, 0xa7, (0x1 << 7), 0); ++ mod_phy_reg(pi, 0x8f, (0x1 << 7), (0x1 << 7)); ++ mod_phy_reg(pi, 0xa5, (0x1 << 7), (0x1 << 7)); ++ ++ mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2)); ++ mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2)); ++ mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2)); ++ mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2)); ++ udelay(5); ++ mod_phy_reg(pi, 0xa6, (0x1 << 2), 0); ++ mod_phy_reg(pi, 0xa7, (0x1 << 2), 0); ++ mod_phy_reg(pi, 0xa6, (0x1 << 3), 0); ++ mod_phy_reg(pi, 0xa7, (0x1 << 3), 0); ++ mod_phy_reg(pi, 0x8f, (0x1 << 3), (0x1 << 3)); ++ mod_phy_reg(pi, 0xa5, (0x1 << 3), (0x1 << 3)); ++ mod_phy_reg(pi, 0xa6, (0x1 << 6), 0); ++ mod_phy_reg(pi, 0xa7, (0x1 << 6), 0); ++ mod_phy_reg(pi, 0x8f, (0x1 << 6), (0x1 << 6)); ++ mod_phy_reg(pi, 0xa5, (0x1 << 6), (0x1 << 6)); ++ ++ auxADC_Vmid = 0xA3; ++ auxADC_Av = 0x0; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16, ++ &auxADC_Vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16, ++ &auxADC_Av); ++ ++ udelay(3); ++ ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1); ++ write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, ++ tempsense_Rcal | 0x03); ++ ++ udelay(5); ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1); ++ ++ auxADC_Av = 0x7; ++ if (radio_temp[1] + radio_temp2[1] < -30) { ++ auxADC_Vmid = 0x45; ++ auxADC_Vl = 263; ++ } else if (radio_temp[1] + radio_temp2[1] < -9) { ++ auxADC_Vmid = 0x200; ++ auxADC_Vl = 467; ++ } else if (radio_temp[1] + radio_temp2[1] < 11) { ++ auxADC_Vmid = 0x266; ++ auxADC_Vl = 634; ++ } else { ++ auxADC_Vmid = 0x2D5; ++ auxADC_Vl = 816; ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16, ++ &auxADC_Vmid); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16, ++ &auxADC_Av); ++ ++ udelay(3); ++ ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1); ++ write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, ++ tempsense_Rcal | 0x01); ++ ++ udelay(5); ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1); ++ ++ write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, ++ syn_tempprocsense_save); ++ ++ write_phy_reg(pi, 0xa6, afectrlCore1_save); ++ write_phy_reg(pi, 0xa7, afectrlCore2_save); ++ write_phy_reg(pi, 0x8f, afectrlOverride_save); ++ write_phy_reg(pi, 0xa5, afectrlOverride2_save); ++ write_phy_reg(pi, 0x1ae, RSSIMultCoef0QPowerDet_save); ++ write_phy_reg(pi, 0x346, RfctrlOverride5_save); ++ write_phy_reg(pi, 0x347, RfctrlOverride6_save); ++ write_phy_reg(pi, 0x344, RfctrlMiscReg5_save); ++ write_phy_reg(pi, 0x345, RfctrlMiscReg5_save); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16, ++ &auxADC_Vmid_save); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16, ++ &auxADC_Av_save); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16, ++ &auxADC_rssi_ctrlL_save); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16, ++ &auxADC_rssi_ctrlH_save); ++ ++ radio_temp[0] = (179 * (radio_temp[1] + radio_temp2[1]) ++ + 82 * (auxADC_Vl) - 28861 + ++ 128) / 256; ++ ++ offset = (s16) pi->phy_tempsense_offset; ++ ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ syn_tempprocsense_save = ++ read_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE); ++ ++ afectrlCore1_save = read_phy_reg(pi, 0xa6); ++ afectrlCore2_save = read_phy_reg(pi, 0xa7); ++ afectrlOverride_save = read_phy_reg(pi, 0x8f); ++ afectrlOverride2_save = read_phy_reg(pi, 0xa5); ++ gpioSel_save = read_phy_reg(pi, 0xca); ++ ++ write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01); ++ ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1); ++ if (NREV_LT(pi->pubpi.phy_rev, 7)) ++ write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x05); ++ ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x01); ++ else ++ write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01); ++ ++ radio_temp[0] = ++ (126 * (radio_temp[1] + radio_temp2[1]) + 3987) / 64; ++ ++ write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, ++ syn_tempprocsense_save); ++ ++ write_phy_reg(pi, 0xca, gpioSel_save); ++ write_phy_reg(pi, 0xa6, afectrlCore1_save); ++ write_phy_reg(pi, 0xa7, afectrlCore2_save); ++ write_phy_reg(pi, 0x8f, afectrlOverride_save); ++ write_phy_reg(pi, 0xa5, afectrlOverride2_save); ++ ++ offset = (s16) pi->phy_tempsense_offset; ++ } else { ++ ++ pwrdet_rxtx_core1_save = ++ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1); ++ pwrdet_rxtx_core2_save = ++ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2); ++ core1_txrf_iqcal1_save = ++ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1); ++ core1_txrf_iqcal2_save = ++ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2); ++ core2_txrf_iqcal1_save = ++ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1); ++ core2_txrf_iqcal2_save = ++ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2); ++ pd_pll_ts_save = read_radio_reg(pi, RADIO_2055_PD_PLL_TS); ++ ++ afectrlCore1_save = read_phy_reg(pi, 0xa6); ++ afectrlCore2_save = read_phy_reg(pi, 0xa7); ++ afectrlOverride_save = read_phy_reg(pi, 0xa5); ++ gpioSel_save = read_phy_reg(pi, 0xca); ++ ++ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x01); ++ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x01); ++ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x08); ++ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x08); ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04); ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04); ++ write_radio_reg(pi, RADIO_2055_PD_PLL_TS, 0x00); ++ ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1); ++ xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80); ++ ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1); ++ xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80); ++ ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1); ++ xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80); ++ ++ radio_temp[0] = (radio_temp[0] + radio_temp2[0]); ++ radio_temp[1] = (radio_temp[1] + radio_temp2[1]); ++ radio_temp[2] = (radio_temp[2] + radio_temp2[2]); ++ radio_temp[3] = (radio_temp[3] + radio_temp2[3]); ++ ++ radio_temp[0] = ++ (radio_temp[0] + radio_temp[1] + radio_temp[2] + ++ radio_temp[3]); ++ ++ radio_temp[0] = ++ (radio_temp[0] + ++ (8 * 32)) * (950 - 350) / 63 + (350 * 8); ++ ++ radio_temp[0] = (radio_temp[0] - (8 * 420)) / 38; ++ ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, ++ pwrdet_rxtx_core1_save); ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, ++ pwrdet_rxtx_core2_save); ++ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, ++ core1_txrf_iqcal1_save); ++ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, ++ core2_txrf_iqcal1_save); ++ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, ++ core1_txrf_iqcal2_save); ++ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, ++ core2_txrf_iqcal2_save); ++ write_radio_reg(pi, RADIO_2055_PD_PLL_TS, pd_pll_ts_save); ++ ++ write_phy_reg(pi, 0xca, gpioSel_save); ++ write_phy_reg(pi, 0xa6, afectrlCore1_save); ++ write_phy_reg(pi, 0xa7, afectrlCore2_save); ++ write_phy_reg(pi, 0xa5, afectrlOverride_save); ++ } ++ ++ return (s16) radio_temp[0] + offset; ++} ++ ++static void ++wlc_phy_set_rssi_2055_vcm(struct brcms_phy *pi, u8 rssi_type, u8 *vcm_buf) ++{ ++ u8 core; ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ if (rssi_type == NPHY_RSSI_SEL_NB) { ++ if (core == PHY_CORE_0) { ++ mod_radio_reg(pi, ++ RADIO_2055_CORE1_B0_NBRSSI_VCM, ++ RADIO_2055_NBRSSI_VCM_I_MASK, ++ vcm_buf[2 * ++ core] << ++ RADIO_2055_NBRSSI_VCM_I_SHIFT); ++ mod_radio_reg(pi, ++ RADIO_2055_CORE1_RXBB_RSSI_CTRL5, ++ RADIO_2055_NBRSSI_VCM_Q_MASK, ++ vcm_buf[2 * core + ++ 1] << ++ RADIO_2055_NBRSSI_VCM_Q_SHIFT); ++ } else { ++ mod_radio_reg(pi, ++ RADIO_2055_CORE2_B0_NBRSSI_VCM, ++ RADIO_2055_NBRSSI_VCM_I_MASK, ++ vcm_buf[2 * ++ core] << ++ RADIO_2055_NBRSSI_VCM_I_SHIFT); ++ mod_radio_reg(pi, ++ RADIO_2055_CORE2_RXBB_RSSI_CTRL5, ++ RADIO_2055_NBRSSI_VCM_Q_MASK, ++ vcm_buf[2 * core + ++ 1] << ++ RADIO_2055_NBRSSI_VCM_Q_SHIFT); ++ } ++ } else { ++ if (core == PHY_CORE_0) ++ mod_radio_reg(pi, ++ RADIO_2055_CORE1_RXBB_RSSI_CTRL5, ++ RADIO_2055_WBRSSI_VCM_IQ_MASK, ++ vcm_buf[2 * ++ core] << ++ RADIO_2055_WBRSSI_VCM_IQ_SHIFT); ++ else ++ mod_radio_reg(pi, ++ RADIO_2055_CORE2_RXBB_RSSI_CTRL5, ++ RADIO_2055_WBRSSI_VCM_IQ_MASK, ++ vcm_buf[2 * ++ core] << ++ RADIO_2055_WBRSSI_VCM_IQ_SHIFT); ++ } ++ } ++} ++ ++static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi) ++{ ++ u16 classif_state; ++ u16 clip_state[2]; ++ u16 clip_off[] = { 0xffff, 0xffff }; ++ s32 target_code; ++ u8 vcm, min_vcm; ++ u8 vcm_final = 0; ++ u8 result_idx; ++ s32 poll_results[8][4] = { ++ {0, 0, 0, 0}, ++ {0, 0, 0, 0}, ++ {0, 0, 0, 0}, ++ {0, 0, 0, 0}, ++ {0, 0, 0, 0}, ++ {0, 0, 0, 0}, ++ {0, 0, 0, 0}, ++ {0, 0, 0, 0} ++ }; ++ s32 poll_result_core[4] = { 0, 0, 0, 0 }; ++ s32 min_d = NPHY_RSSICAL_MAXD, curr_d; ++ s32 fine_digital_offset[4]; ++ s32 poll_results_min[4] = { 0, 0, 0, 0 }; ++ s32 min_poll; ++ u8 vcm_level_max; ++ u8 core; ++ u8 wb_cnt; ++ u8 rssi_type; ++ u16 NPHY_Rfctrlintc1_save, NPHY_Rfctrlintc2_save; ++ u16 NPHY_AfectrlOverride1_save, NPHY_AfectrlOverride2_save; ++ u16 NPHY_AfectrlCore1_save, NPHY_AfectrlCore2_save; ++ u16 NPHY_RfctrlOverride0_save, NPHY_RfctrlOverride1_save; ++ u16 NPHY_RfctrlOverrideAux0_save, NPHY_RfctrlOverrideAux1_save; ++ u16 NPHY_RfctrlCmd_save; ++ u16 NPHY_RfctrlMiscReg1_save, NPHY_RfctrlMiscReg2_save; ++ u16 NPHY_RfctrlRSSIOTHERS1_save, NPHY_RfctrlRSSIOTHERS2_save; ++ u8 rxcore_state; ++ u16 NPHY_REV7_RfctrlOverride3_save, NPHY_REV7_RfctrlOverride4_save; ++ u16 NPHY_REV7_RfctrlOverride5_save, NPHY_REV7_RfctrlOverride6_save; ++ u16 NPHY_REV7_RfctrlMiscReg3_save, NPHY_REV7_RfctrlMiscReg4_save; ++ u16 NPHY_REV7_RfctrlMiscReg5_save, NPHY_REV7_RfctrlMiscReg6_save; ++ ++ NPHY_REV7_RfctrlOverride3_save = ++ NPHY_REV7_RfctrlOverride4_save = ++ NPHY_REV7_RfctrlOverride5_save = ++ NPHY_REV7_RfctrlOverride6_save = ++ NPHY_REV7_RfctrlMiscReg3_save = ++ NPHY_REV7_RfctrlMiscReg4_save = ++ NPHY_REV7_RfctrlMiscReg5_save = ++ NPHY_REV7_RfctrlMiscReg6_save = 0; ++ ++ classif_state = wlc_phy_classifier_nphy(pi, 0, 0); ++ wlc_phy_classifier_nphy(pi, (0x7 << 0), 4); ++ wlc_phy_clip_det_nphy(pi, 0, clip_state); ++ wlc_phy_clip_det_nphy(pi, 1, clip_off); ++ ++ NPHY_Rfctrlintc1_save = read_phy_reg(pi, 0x91); ++ NPHY_Rfctrlintc2_save = read_phy_reg(pi, 0x92); ++ NPHY_AfectrlOverride1_save = read_phy_reg(pi, 0x8f); ++ NPHY_AfectrlOverride2_save = read_phy_reg(pi, 0xa5); ++ NPHY_AfectrlCore1_save = read_phy_reg(pi, 0xa6); ++ NPHY_AfectrlCore2_save = read_phy_reg(pi, 0xa7); ++ NPHY_RfctrlOverride0_save = read_phy_reg(pi, 0xe7); ++ NPHY_RfctrlOverride1_save = read_phy_reg(pi, 0xec); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ NPHY_REV7_RfctrlOverride3_save = read_phy_reg(pi, 0x342); ++ NPHY_REV7_RfctrlOverride4_save = read_phy_reg(pi, 0x343); ++ NPHY_REV7_RfctrlOverride5_save = read_phy_reg(pi, 0x346); ++ NPHY_REV7_RfctrlOverride6_save = read_phy_reg(pi, 0x347); ++ } ++ NPHY_RfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5); ++ NPHY_RfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6); ++ NPHY_RfctrlCmd_save = read_phy_reg(pi, 0x78); ++ NPHY_RfctrlMiscReg1_save = read_phy_reg(pi, 0xf9); ++ NPHY_RfctrlMiscReg2_save = read_phy_reg(pi, 0xfb); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ NPHY_REV7_RfctrlMiscReg3_save = read_phy_reg(pi, 0x340); ++ NPHY_REV7_RfctrlMiscReg4_save = read_phy_reg(pi, 0x341); ++ NPHY_REV7_RfctrlMiscReg5_save = read_phy_reg(pi, 0x344); ++ NPHY_REV7_RfctrlMiscReg6_save = read_phy_reg(pi, 0x345); ++ } ++ NPHY_RfctrlRSSIOTHERS1_save = read_phy_reg(pi, 0x7a); ++ NPHY_RfctrlRSSIOTHERS2_save = read_phy_reg(pi, 0x7d); ++ ++ wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_OFF, 0, ++ RADIO_MIMO_CORESEL_ALLRXTX); ++ wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_TRSW, 1, ++ RADIO_MIMO_CORESEL_ALLRXTX); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_rxrf_pu, ++ 0, 0, 0); ++ else ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0, 0); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_rx_pu, ++ 1, 0, 0); ++ else ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0, 0); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), ++ 1, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 6), 1, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ } else { ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 7), 1, 0, 0); ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 6), 1, 0, 0); ++ } ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 5), ++ 0, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 4), 1, 0, ++ 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ } else { ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 0, 0, 0); ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 1, 0, 0); ++ } ++ ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 4), ++ 0, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 5), 1, 0, ++ 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ } else { ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 0, 0, 0); ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 1, 0, 0); ++ } ++ } ++ ++ rxcore_state = wlc_phy_rxcore_getstate_nphy( ++ (struct brcms_phy_pub *) pi); ++ ++ vcm_level_max = 8; ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ ++ if ((rxcore_state & (1 << core)) == 0) ++ continue; ++ ++ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, ++ core == ++ PHY_CORE_0 ? ++ RADIO_MIMO_CORESEL_CORE1 : ++ RADIO_MIMO_CORESEL_CORE2, ++ NPHY_RAIL_I, NPHY_RSSI_SEL_NB); ++ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, ++ core == ++ PHY_CORE_0 ? ++ RADIO_MIMO_CORESEL_CORE1 : ++ RADIO_MIMO_CORESEL_CORE2, ++ NPHY_RAIL_Q, NPHY_RSSI_SEL_NB); ++ ++ for (vcm = 0; vcm < vcm_level_max; vcm++) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ mod_radio_reg(pi, (core == PHY_CORE_0) ? ++ RADIO_2057_NB_MASTER_CORE0 : ++ RADIO_2057_NB_MASTER_CORE1, ++ RADIO_2057_VCM_MASK, vcm); ++ else ++ mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC | ++ ((core == ++ PHY_CORE_0) ? RADIO_2056_RX0 : ++ RADIO_2056_RX1), ++ RADIO_2056_VCM_MASK, ++ vcm << RADIO_2056_RSSI_VCM_SHIFT); ++ ++ wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_NB, ++ &poll_results[vcm][0], ++ NPHY_RSSICAL_NPOLL); ++ } ++ ++ for (result_idx = 0; result_idx < 4; result_idx++) { ++ if ((core == result_idx / 2) && ++ (result_idx % 2 == 0)) { ++ ++ min_d = NPHY_RSSICAL_MAXD; ++ min_vcm = 0; ++ min_poll = ++ NPHY_RSSICAL_MAXREAD * ++ NPHY_RSSICAL_NPOLL + 1; ++ for (vcm = 0; vcm < vcm_level_max; vcm++) { ++ curr_d = ++ poll_results[vcm][result_idx] * ++ poll_results[vcm][result_idx] + ++ poll_results[vcm][result_idx + ++ 1] * ++ poll_results[vcm][result_idx + ++ 1]; ++ if (curr_d < min_d) { ++ min_d = curr_d; ++ min_vcm = vcm; ++ } ++ if (poll_results[vcm][result_idx] < ++ min_poll) ++ min_poll = ++ poll_results[vcm] ++ [result_idx]; ++ } ++ vcm_final = min_vcm; ++ poll_results_min[result_idx] = min_poll; ++ } ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ mod_radio_reg(pi, (core == PHY_CORE_0) ? ++ RADIO_2057_NB_MASTER_CORE0 : ++ RADIO_2057_NB_MASTER_CORE1, ++ RADIO_2057_VCM_MASK, vcm_final); ++ else ++ mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC | ++ ((core == ++ PHY_CORE_0) ? RADIO_2056_RX0 : ++ RADIO_2056_RX1), RADIO_2056_VCM_MASK, ++ vcm_final << RADIO_2056_RSSI_VCM_SHIFT); ++ ++ for (result_idx = 0; result_idx < 4; result_idx++) { ++ if (core == result_idx / 2) { ++ fine_digital_offset[result_idx] = ++ (NPHY_RSSICAL_NB_TARGET * ++ NPHY_RSSICAL_NPOLL) - ++ poll_results[vcm_final][result_idx]; ++ if (fine_digital_offset[result_idx] < 0) { ++ fine_digital_offset[result_idx] = ++ abs(fine_digital_offset ++ [result_idx]); ++ fine_digital_offset[result_idx] += ++ (NPHY_RSSICAL_NPOLL / 2); ++ fine_digital_offset[result_idx] /= ++ NPHY_RSSICAL_NPOLL; ++ fine_digital_offset[result_idx] = ++ -fine_digital_offset[ ++ result_idx]; ++ } else { ++ fine_digital_offset[result_idx] += ++ (NPHY_RSSICAL_NPOLL / 2); ++ fine_digital_offset[result_idx] /= ++ NPHY_RSSICAL_NPOLL; ++ } ++ ++ if (poll_results_min[result_idx] == ++ NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) ++ fine_digital_offset[result_idx] = ++ (NPHY_RSSICAL_NB_TARGET - ++ NPHY_RSSICAL_MAXREAD - 1); ++ ++ wlc_phy_scale_offset_rssi_nphy( ++ pi, 0x0, ++ (s8) ++ fine_digital_offset ++ [result_idx], ++ (result_idx / 2 == 0) ? ++ RADIO_MIMO_CORESEL_CORE1 : ++ RADIO_MIMO_CORESEL_CORE2, ++ (result_idx % 2 == 0) ? ++ NPHY_RAIL_I : NPHY_RAIL_Q, ++ NPHY_RSSI_SEL_NB); ++ } ++ } ++ ++ } ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ ++ if ((rxcore_state & (1 << core)) == 0) ++ continue; ++ ++ for (wb_cnt = 0; wb_cnt < 2; wb_cnt++) { ++ if (wb_cnt == 0) { ++ rssi_type = NPHY_RSSI_SEL_W1; ++ target_code = NPHY_RSSICAL_W1_TARGET_REV3; ++ } else { ++ rssi_type = NPHY_RSSI_SEL_W2; ++ target_code = NPHY_RSSICAL_W2_TARGET_REV3; ++ } ++ ++ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, ++ core == ++ PHY_CORE_0 ? ++ RADIO_MIMO_CORESEL_CORE1 ++ : ++ RADIO_MIMO_CORESEL_CORE2, ++ NPHY_RAIL_I, rssi_type); ++ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, ++ core == ++ PHY_CORE_0 ? ++ RADIO_MIMO_CORESEL_CORE1 ++ : ++ RADIO_MIMO_CORESEL_CORE2, ++ NPHY_RAIL_Q, rssi_type); ++ ++ wlc_phy_poll_rssi_nphy(pi, rssi_type, poll_result_core, ++ NPHY_RSSICAL_NPOLL); ++ ++ for (result_idx = 0; result_idx < 4; result_idx++) { ++ if (core == result_idx / 2) { ++ fine_digital_offset[result_idx] = ++ (target_code * ++ NPHY_RSSICAL_NPOLL) - ++ poll_result_core[result_idx]; ++ if (fine_digital_offset[result_idx] < ++ 0) { ++ fine_digital_offset[result_idx] ++ = abs( ++ fine_digital_offset ++ [result_idx]); ++ fine_digital_offset[result_idx] ++ += (NPHY_RSSICAL_NPOLL ++ / 2); ++ fine_digital_offset[result_idx] ++ /= NPHY_RSSICAL_NPOLL; ++ fine_digital_offset[result_idx] ++ = -fine_digital_offset ++ [result_idx]; ++ } else { ++ fine_digital_offset[result_idx] ++ += (NPHY_RSSICAL_NPOLL ++ / 2); ++ fine_digital_offset[result_idx] ++ /= NPHY_RSSICAL_NPOLL; ++ } ++ ++ wlc_phy_scale_offset_rssi_nphy( ++ pi, 0x0, ++ (s8) ++ fine_digital_offset ++ [core * ++ 2], ++ (core == PHY_CORE_0) ? ++ RADIO_MIMO_CORESEL_CORE1 : ++ RADIO_MIMO_CORESEL_CORE2, ++ (result_idx % 2 == 0) ? ++ NPHY_RAIL_I : ++ NPHY_RAIL_Q, ++ rssi_type); ++ } ++ } ++ ++ } ++ } ++ ++ write_phy_reg(pi, 0x91, NPHY_Rfctrlintc1_save); ++ write_phy_reg(pi, 0x92, NPHY_Rfctrlintc2_save); ++ ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); ++ ++ mod_phy_reg(pi, 0xe7, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0x78, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0xe7, (0x1 << 0), 0); ++ ++ mod_phy_reg(pi, 0xec, (0x1 << 0), 1 << 0); ++ mod_phy_reg(pi, 0x78, (0x1 << 1), 1 << 1); ++ mod_phy_reg(pi, 0xec, (0x1 << 0), 0); ++ ++ write_phy_reg(pi, 0x8f, NPHY_AfectrlOverride1_save); ++ write_phy_reg(pi, 0xa5, NPHY_AfectrlOverride2_save); ++ write_phy_reg(pi, 0xa6, NPHY_AfectrlCore1_save); ++ write_phy_reg(pi, 0xa7, NPHY_AfectrlCore2_save); ++ write_phy_reg(pi, 0xe7, NPHY_RfctrlOverride0_save); ++ write_phy_reg(pi, 0xec, NPHY_RfctrlOverride1_save); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ write_phy_reg(pi, 0x342, NPHY_REV7_RfctrlOverride3_save); ++ write_phy_reg(pi, 0x343, NPHY_REV7_RfctrlOverride4_save); ++ write_phy_reg(pi, 0x346, NPHY_REV7_RfctrlOverride5_save); ++ write_phy_reg(pi, 0x347, NPHY_REV7_RfctrlOverride6_save); ++ } ++ write_phy_reg(pi, 0xe5, NPHY_RfctrlOverrideAux0_save); ++ write_phy_reg(pi, 0xe6, NPHY_RfctrlOverrideAux1_save); ++ write_phy_reg(pi, 0x78, NPHY_RfctrlCmd_save); ++ write_phy_reg(pi, 0xf9, NPHY_RfctrlMiscReg1_save); ++ write_phy_reg(pi, 0xfb, NPHY_RfctrlMiscReg2_save); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ write_phy_reg(pi, 0x340, NPHY_REV7_RfctrlMiscReg3_save); ++ write_phy_reg(pi, 0x341, NPHY_REV7_RfctrlMiscReg4_save); ++ write_phy_reg(pi, 0x344, NPHY_REV7_RfctrlMiscReg5_save); ++ write_phy_reg(pi, 0x345, NPHY_REV7_RfctrlMiscReg6_save); ++ } ++ write_phy_reg(pi, 0x7a, NPHY_RfctrlRSSIOTHERS1_save); ++ write_phy_reg(pi, 0x7d, NPHY_RfctrlRSSIOTHERS2_save); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ pi->rssical_cache.rssical_radio_regs_2G[0] = ++ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0); ++ pi->rssical_cache.rssical_radio_regs_2G[1] = ++ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1); ++ } else { ++ pi->rssical_cache.rssical_radio_regs_2G[0] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_RSSI_MISC | ++ RADIO_2056_RX0); ++ pi->rssical_cache.rssical_radio_regs_2G[1] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_RSSI_MISC | ++ RADIO_2056_RX1); ++ } ++ ++ pi->rssical_cache.rssical_phyregs_2G[0] = ++ read_phy_reg(pi, 0x1a6); ++ pi->rssical_cache.rssical_phyregs_2G[1] = ++ read_phy_reg(pi, 0x1ac); ++ pi->rssical_cache.rssical_phyregs_2G[2] = ++ read_phy_reg(pi, 0x1b2); ++ pi->rssical_cache.rssical_phyregs_2G[3] = ++ read_phy_reg(pi, 0x1b8); ++ pi->rssical_cache.rssical_phyregs_2G[4] = ++ read_phy_reg(pi, 0x1a4); ++ pi->rssical_cache.rssical_phyregs_2G[5] = ++ read_phy_reg(pi, 0x1aa); ++ pi->rssical_cache.rssical_phyregs_2G[6] = ++ read_phy_reg(pi, 0x1b0); ++ pi->rssical_cache.rssical_phyregs_2G[7] = ++ read_phy_reg(pi, 0x1b6); ++ pi->rssical_cache.rssical_phyregs_2G[8] = ++ read_phy_reg(pi, 0x1a5); ++ pi->rssical_cache.rssical_phyregs_2G[9] = ++ read_phy_reg(pi, 0x1ab); ++ pi->rssical_cache.rssical_phyregs_2G[10] = ++ read_phy_reg(pi, 0x1b1); ++ pi->rssical_cache.rssical_phyregs_2G[11] = ++ read_phy_reg(pi, 0x1b7); ++ ++ pi->nphy_rssical_chanspec_2G = pi->radio_chanspec; ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ pi->rssical_cache.rssical_radio_regs_5G[0] = ++ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0); ++ pi->rssical_cache.rssical_radio_regs_5G[1] = ++ read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1); ++ } else { ++ pi->rssical_cache.rssical_radio_regs_5G[0] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_RSSI_MISC | ++ RADIO_2056_RX0); ++ pi->rssical_cache.rssical_radio_regs_5G[1] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_RSSI_MISC | ++ RADIO_2056_RX1); ++ } ++ ++ pi->rssical_cache.rssical_phyregs_5G[0] = ++ read_phy_reg(pi, 0x1a6); ++ pi->rssical_cache.rssical_phyregs_5G[1] = ++ read_phy_reg(pi, 0x1ac); ++ pi->rssical_cache.rssical_phyregs_5G[2] = ++ read_phy_reg(pi, 0x1b2); ++ pi->rssical_cache.rssical_phyregs_5G[3] = ++ read_phy_reg(pi, 0x1b8); ++ pi->rssical_cache.rssical_phyregs_5G[4] = ++ read_phy_reg(pi, 0x1a4); ++ pi->rssical_cache.rssical_phyregs_5G[5] = ++ read_phy_reg(pi, 0x1aa); ++ pi->rssical_cache.rssical_phyregs_5G[6] = ++ read_phy_reg(pi, 0x1b0); ++ pi->rssical_cache.rssical_phyregs_5G[7] = ++ read_phy_reg(pi, 0x1b6); ++ pi->rssical_cache.rssical_phyregs_5G[8] = ++ read_phy_reg(pi, 0x1a5); ++ pi->rssical_cache.rssical_phyregs_5G[9] = ++ read_phy_reg(pi, 0x1ab); ++ pi->rssical_cache.rssical_phyregs_5G[10] = ++ read_phy_reg(pi, 0x1b1); ++ pi->rssical_cache.rssical_phyregs_5G[11] = ++ read_phy_reg(pi, 0x1b7); ++ ++ pi->nphy_rssical_chanspec_5G = pi->radio_chanspec; ++ } ++ ++ wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state); ++ wlc_phy_clip_det_nphy(pi, 1, clip_state); ++} ++ ++static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type) ++{ ++ s32 target_code; ++ u16 classif_state; ++ u16 clip_state[2]; ++ u16 rssi_ctrl_state[2], pd_state[2]; ++ u16 rfctrlintc_state[2], rfpdcorerxtx_state[2]; ++ u16 rfctrlintc_override_val; ++ u16 clip_off[] = { 0xffff, 0xffff }; ++ u16 rf_pd_val, pd_mask, rssi_ctrl_mask; ++ u8 vcm, min_vcm, vcm_tmp[4]; ++ u8 vcm_final[4] = { 0, 0, 0, 0 }; ++ u8 result_idx, ctr; ++ s32 poll_results[4][4] = { ++ {0, 0, 0, 0}, ++ {0, 0, 0, 0}, ++ {0, 0, 0, 0}, ++ {0, 0, 0, 0} ++ }; ++ s32 poll_miniq[4][2] = { ++ {0, 0}, ++ {0, 0}, ++ {0, 0}, ++ {0, 0} ++ }; ++ s32 min_d, curr_d; ++ s32 fine_digital_offset[4]; ++ s32 poll_results_min[4] = { 0, 0, 0, 0 }; ++ s32 min_poll; ++ ++ switch (rssi_type) { ++ case NPHY_RSSI_SEL_NB: ++ target_code = NPHY_RSSICAL_NB_TARGET; ++ break; ++ case NPHY_RSSI_SEL_W1: ++ target_code = NPHY_RSSICAL_W1_TARGET; ++ break; ++ case NPHY_RSSI_SEL_W2: ++ target_code = NPHY_RSSICAL_W2_TARGET; ++ break; ++ default: ++ return; ++ break; ++ } ++ ++ classif_state = wlc_phy_classifier_nphy(pi, 0, 0); ++ wlc_phy_classifier_nphy(pi, (0x7 << 0), 4); ++ wlc_phy_clip_det_nphy(pi, 0, clip_state); ++ wlc_phy_clip_det_nphy(pi, 1, clip_off); ++ ++ rf_pd_val = (rssi_type == NPHY_RSSI_SEL_NB) ? 0x6 : 0x4; ++ rfctrlintc_override_val = ++ CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 : 0x110; ++ ++ rfctrlintc_state[0] = read_phy_reg(pi, 0x91); ++ rfpdcorerxtx_state[0] = read_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX); ++ write_phy_reg(pi, 0x91, rfctrlintc_override_val); ++ write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rf_pd_val); ++ ++ rfctrlintc_state[1] = read_phy_reg(pi, 0x92); ++ rfpdcorerxtx_state[1] = read_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX); ++ write_phy_reg(pi, 0x92, rfctrlintc_override_val); ++ write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rf_pd_val); ++ ++ pd_mask = RADIO_2055_NBRSSI_PD | RADIO_2055_WBRSSI_G1_PD | ++ RADIO_2055_WBRSSI_G2_PD; ++ pd_state[0] = ++ read_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC) & pd_mask; ++ pd_state[1] = ++ read_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC) & pd_mask; ++ mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, 0); ++ mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, 0); ++ rssi_ctrl_mask = RADIO_2055_NBRSSI_SEL | RADIO_2055_WBRSSI_G1_SEL | ++ RADIO_2055_WBRSSI_G2_SEL; ++ rssi_ctrl_state[0] = ++ read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE1) & rssi_ctrl_mask; ++ rssi_ctrl_state[1] = ++ read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE2) & rssi_ctrl_mask; ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type); ++ ++ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX, ++ NPHY_RAIL_I, rssi_type); ++ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX, ++ NPHY_RAIL_Q, rssi_type); ++ ++ for (vcm = 0; vcm < 4; vcm++) { ++ ++ vcm_tmp[0] = vcm_tmp[1] = vcm_tmp[2] = vcm_tmp[3] = vcm; ++ if (rssi_type != NPHY_RSSI_SEL_W2) ++ wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_tmp); ++ ++ wlc_phy_poll_rssi_nphy(pi, rssi_type, &poll_results[vcm][0], ++ NPHY_RSSICAL_NPOLL); ++ ++ if ((rssi_type == NPHY_RSSI_SEL_W1) ++ || (rssi_type == NPHY_RSSI_SEL_W2)) { ++ for (ctr = 0; ctr < 2; ctr++) ++ poll_miniq[vcm][ctr] = ++ min(poll_results[vcm][ctr * 2 + 0], ++ poll_results[vcm][ctr * 2 + 1]); ++ } ++ } ++ ++ for (result_idx = 0; result_idx < 4; result_idx++) { ++ min_d = NPHY_RSSICAL_MAXD; ++ min_vcm = 0; ++ min_poll = NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL + 1; ++ for (vcm = 0; vcm < 4; vcm++) { ++ curr_d = abs(((rssi_type == NPHY_RSSI_SEL_NB) ? ++ poll_results[vcm][result_idx] : ++ poll_miniq[vcm][result_idx / 2]) - ++ (target_code * NPHY_RSSICAL_NPOLL)); ++ if (curr_d < min_d) { ++ min_d = curr_d; ++ min_vcm = vcm; ++ } ++ if (poll_results[vcm][result_idx] < min_poll) ++ min_poll = poll_results[vcm][result_idx]; ++ } ++ vcm_final[result_idx] = min_vcm; ++ poll_results_min[result_idx] = min_poll; ++ } ++ ++ if (rssi_type != NPHY_RSSI_SEL_W2) ++ wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_final); ++ ++ for (result_idx = 0; result_idx < 4; result_idx++) { ++ fine_digital_offset[result_idx] = ++ (target_code * NPHY_RSSICAL_NPOLL) - ++ poll_results[vcm_final[result_idx]][result_idx]; ++ if (fine_digital_offset[result_idx] < 0) { ++ fine_digital_offset[result_idx] = ++ abs(fine_digital_offset[result_idx]); ++ fine_digital_offset[result_idx] += ++ (NPHY_RSSICAL_NPOLL / 2); ++ fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL; ++ fine_digital_offset[result_idx] = ++ -fine_digital_offset[result_idx]; ++ } else { ++ fine_digital_offset[result_idx] += ++ (NPHY_RSSICAL_NPOLL / 2); ++ fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL; ++ } ++ ++ if (poll_results_min[result_idx] == ++ NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) ++ fine_digital_offset[result_idx] = ++ (target_code - NPHY_RSSICAL_MAXREAD - 1); ++ ++ wlc_phy_scale_offset_rssi_nphy(pi, 0x0, ++ (s8) ++ fine_digital_offset[result_idx], ++ (result_idx / 2 == ++ 0) ? RADIO_MIMO_CORESEL_CORE1 : ++ RADIO_MIMO_CORESEL_CORE2, ++ (result_idx % 2 == ++ 0) ? NPHY_RAIL_I : NPHY_RAIL_Q, ++ rssi_type); ++ } ++ ++ mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, pd_state[0]); ++ mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, pd_state[1]); ++ if (rssi_ctrl_state[0] == RADIO_2055_NBRSSI_SEL) ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1, ++ NPHY_RSSI_SEL_NB); ++ else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G1_SEL) ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1, ++ NPHY_RSSI_SEL_W1); ++ else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G2_SEL) ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1, ++ NPHY_RSSI_SEL_W2); ++ else ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1, ++ NPHY_RSSI_SEL_W2); ++ if (rssi_ctrl_state[1] == RADIO_2055_NBRSSI_SEL) ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2, ++ NPHY_RSSI_SEL_NB); ++ else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G1_SEL) ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2, ++ NPHY_RSSI_SEL_W1); ++ else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G2_SEL) ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2, ++ NPHY_RSSI_SEL_W2); ++ else ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2, ++ NPHY_RSSI_SEL_W2); ++ ++ wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, rssi_type); ++ ++ write_phy_reg(pi, 0x91, rfctrlintc_state[0]); ++ write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rfpdcorerxtx_state[0]); ++ write_phy_reg(pi, 0x92, rfctrlintc_state[1]); ++ write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rfpdcorerxtx_state[1]); ++ ++ wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state); ++ wlc_phy_clip_det_nphy(pi, 1, clip_state); ++ ++ wlc_phy_resetcca_nphy(pi); ++} ++ ++void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi) ++{ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ wlc_phy_rssi_cal_nphy_rev3(pi); ++ } else { ++ wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_NB); ++ wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W1); ++ wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W2); ++ } ++} ++ ++int ++wlc_phy_rssi_compute_nphy(struct brcms_phy *pi, struct d11rxhdr *rxh) ++{ ++ s16 rxpwr, rxpwr0, rxpwr1; ++ s16 phyRx0_l, phyRx2_l; ++ ++ rxpwr = 0; ++ rxpwr0 = rxh->PhyRxStatus_1 & PRXS1_nphy_PWR0_MASK; ++ rxpwr1 = (rxh->PhyRxStatus_1 & PRXS1_nphy_PWR1_MASK) >> 8; ++ ++ if (rxpwr0 > 127) ++ rxpwr0 -= 256; ++ if (rxpwr1 > 127) ++ rxpwr1 -= 256; ++ ++ phyRx0_l = rxh->PhyRxStatus_0 & 0x00ff; ++ phyRx2_l = rxh->PhyRxStatus_2 & 0x00ff; ++ if (phyRx2_l > 127) ++ phyRx2_l -= 256; ++ ++ if (((rxpwr0 == 16) || (rxpwr0 == 32))) { ++ rxpwr0 = rxpwr1; ++ rxpwr1 = phyRx2_l; ++ } ++ ++ if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MAX) ++ rxpwr = (rxpwr0 > rxpwr1) ? rxpwr0 : rxpwr1; ++ else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MIN) ++ rxpwr = (rxpwr0 < rxpwr1) ? rxpwr0 : rxpwr1; ++ else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_AVG) ++ rxpwr = (rxpwr0 + rxpwr1) >> 1; ++ ++ return rxpwr; ++} ++ ++static void ++wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, struct cordic_iq *tone_buf, ++ u16 num_samps) ++{ ++ u16 t; ++ u32 *data_buf = NULL; ++ ++ data_buf = kmalloc(sizeof(u32) * num_samps, GFP_ATOMIC); ++ if (data_buf == NULL) ++ return; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ for (t = 0; t < num_samps; t++) ++ data_buf[t] = ((((unsigned int)tone_buf[t].i) & 0x3ff) << 10) | ++ (((unsigned int)tone_buf[t].q) & 0x3ff); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SAMPLEPLAY, num_samps, 0, 32, ++ data_buf); ++ ++ kfree(data_buf); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static u16 ++wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, ++ u8 dac_test_mode) ++{ ++ u8 phy_bw, is_phybw40; ++ u16 num_samps, t, spur; ++ s32 theta = 0, rot = 0; ++ u32 tbl_len; ++ struct cordic_iq *tone_buf = NULL; ++ ++ is_phybw40 = CHSPEC_IS40(pi->radio_chanspec); ++ phy_bw = (is_phybw40 == 1) ? 40 : 20; ++ tbl_len = (phy_bw << 3); ++ ++ if (dac_test_mode == 1) { ++ spur = read_phy_reg(pi, 0x01); ++ spur = (spur >> 15) & 1; ++ phy_bw = (spur == 1) ? 82 : 80; ++ phy_bw = (is_phybw40 == 1) ? (phy_bw << 1) : phy_bw; ++ ++ tbl_len = (phy_bw << 1); ++ } ++ ++ tone_buf = kmalloc(sizeof(struct cordic_iq) * tbl_len, GFP_ATOMIC); ++ if (tone_buf == NULL) ++ return 0; ++ ++ num_samps = (u16) tbl_len; ++ rot = ((f_kHz * 36) / phy_bw) / 100; ++ theta = 0; ++ ++ for (t = 0; t < num_samps; t++) { ++ ++ tone_buf[t] = cordic_calc_iq(theta); ++ ++ theta += rot; ++ ++ tone_buf[t].q = (s32) FLOAT(tone_buf[t].q * max_val); ++ tone_buf[t].i = (s32) FLOAT(tone_buf[t].i * max_val); ++ } ++ ++ wlc_phy_loadsampletable_nphy(pi, tone_buf, num_samps); ++ ++ kfree(tone_buf); ++ ++ return num_samps; ++} ++ ++static void ++wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops, ++ u16 wait, u8 iqmode, u8 dac_test_mode, ++ bool modify_bbmult) ++{ ++ u16 bb_mult; ++ u8 phy_bw, sample_cmd; ++ u16 orig_RfseqCoreActv; ++ u16 lpf_bw_ctl_override3, lpf_bw_ctl_override4, lpf_bw_ctl_miscreg3, ++ lpf_bw_ctl_miscreg4; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ phy_bw = 20; ++ if (CHSPEC_IS40(pi->radio_chanspec)) ++ phy_bw = 40; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ lpf_bw_ctl_override3 = read_phy_reg(pi, 0x342) & (0x1 << 7); ++ lpf_bw_ctl_override4 = read_phy_reg(pi, 0x343) & (0x1 << 7); ++ if (lpf_bw_ctl_override3 | lpf_bw_ctl_override4) { ++ lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) & ++ (0x7 << 8); ++ lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) & ++ (0x7 << 8); ++ } else { ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, ++ (0x1 << 7), ++ wlc_phy_read_lpf_bw_ctl_nphy ++ (pi, ++ 0), 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ ++ pi->nphy_sample_play_lpf_bw_ctl_ovr = true; ++ ++ lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) & ++ (0x7 << 8); ++ lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) & ++ (0x7 << 8); ++ } ++ } ++ ++ if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) == 0) { ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16, ++ &bb_mult); ++ pi->nphy_bb_mult_save = ++ BB_MULT_VALID_MASK | (bb_mult & BB_MULT_MASK); ++ } ++ ++ if (modify_bbmult) { ++ bb_mult = (phy_bw == 20) ? 100 : 71; ++ bb_mult = (bb_mult << 8) + bb_mult; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16, ++ &bb_mult); ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ ++ write_phy_reg(pi, 0xc6, num_samps - 1); ++ ++ if (loops != 0xffff) ++ write_phy_reg(pi, 0xc4, loops - 1); ++ else ++ write_phy_reg(pi, 0xc4, loops); ++ ++ write_phy_reg(pi, 0xc5, wait); ++ ++ orig_RfseqCoreActv = read_phy_reg(pi, 0xa1); ++ or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override); ++ if (iqmode) { ++ ++ and_phy_reg(pi, 0xc2, 0x7FFF); ++ ++ or_phy_reg(pi, 0xc2, 0x8000); ++ } else { ++ ++ sample_cmd = (dac_test_mode == 1) ? 0x5 : 0x1; ++ write_phy_reg(pi, 0xc3, sample_cmd); ++ } ++ ++ SPINWAIT(((read_phy_reg(pi, 0xa4) & 0x1) == 1), 1000); ++ ++ write_phy_reg(pi, 0xa1, orig_RfseqCoreActv); ++} ++ ++int ++wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, ++ u8 iqmode, u8 dac_test_mode, bool modify_bbmult) ++{ ++ u16 num_samps; ++ u16 loops = 0xffff; ++ u16 wait = 0; ++ ++ num_samps = wlc_phy_gen_load_samples_nphy(pi, f_kHz, max_val, ++ dac_test_mode); ++ if (num_samps == 0) ++ return -EBADE; ++ ++ wlc_phy_runsamples_nphy(pi, num_samps, loops, wait, iqmode, ++ dac_test_mode, modify_bbmult); ++ ++ return 0; ++} ++ ++void wlc_phy_stopplayback_nphy(struct brcms_phy *pi) ++{ ++ u16 playback_status; ++ u16 bb_mult; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ playback_status = read_phy_reg(pi, 0xc7); ++ if (playback_status & 0x1) ++ or_phy_reg(pi, 0xc3, NPHY_sampleCmd_STOP); ++ else if (playback_status & 0x2) ++ and_phy_reg(pi, 0xc2, ++ (u16) ~NPHY_iqloCalCmdGctl_IQLO_CAL_EN); ++ ++ and_phy_reg(pi, 0xc3, (u16) ~(0x1 << 2)); ++ ++ if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) != 0) { ++ ++ bb_mult = pi->nphy_bb_mult_save & BB_MULT_MASK; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16, ++ &bb_mult); ++ ++ pi->nphy_bb_mult_save = 0; ++ } ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7) || NREV_GE(pi->pubpi.phy_rev, 8)) { ++ if (pi->nphy_sample_play_lpf_bw_ctl_ovr) { ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, ++ (0x1 << 7), ++ 0, 0, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ pi->nphy_sample_play_lpf_bw_ctl_ovr = false; ++ } ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static u32 *brcms_phy_get_tx_pwrctrl_tbl(struct brcms_phy *pi) ++{ ++ u32 *tx_pwrctrl_tbl = NULL; ++ uint phyrev = pi->pubpi.phy_rev; ++ ++ if (PHY_IPA(pi)) { ++ tx_pwrctrl_tbl = ++ wlc_phy_get_ipa_gaintbl_nphy(pi); ++ } else { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (NREV_IS(phyrev, 3)) ++ tx_pwrctrl_tbl = nphy_tpc_5GHz_txgain_rev3; ++ else if (NREV_IS(phyrev, 4)) ++ tx_pwrctrl_tbl = ++ (pi->srom_fem5g.extpagain == 3) ? ++ nphy_tpc_5GHz_txgain_HiPwrEPA : ++ nphy_tpc_5GHz_txgain_rev4; ++ else ++ tx_pwrctrl_tbl = nphy_tpc_5GHz_txgain_rev5; ++ } else { ++ if (NREV_GE(phyrev, 7)) { ++ if (pi->pubpi.radiorev == 3) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_epa_2057rev3; ++ else if (pi->pubpi.radiorev == 5) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_epa_2057rev5; ++ } else { ++ if (NREV_GE(phyrev, 5) && ++ (pi->srom_fem2g.extpagain == 3)) ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_HiPwrEPA; ++ else ++ tx_pwrctrl_tbl = ++ nphy_tpc_txgain_rev3; ++ } ++ } ++ } ++ return tx_pwrctrl_tbl; ++} ++ ++struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi) ++{ ++ u16 base_idx[2], curr_gain[2]; ++ u8 core_no; ++ struct nphy_txgains target_gain; ++ u32 *tx_pwrctrl_tbl = NULL; ++ ++ if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) { ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, ++ curr_gain); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ ++ for (core_no = 0; core_no < 2; core_no++) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ target_gain.ipa[core_no] = ++ curr_gain[core_no] & 0x0007; ++ target_gain.pad[core_no] = ++ ((curr_gain[core_no] & 0x00F8) >> 3); ++ target_gain.pga[core_no] = ++ ((curr_gain[core_no] & 0x0F00) >> 8); ++ target_gain.txgm[core_no] = ++ ((curr_gain[core_no] & 0x7000) >> 12); ++ target_gain.txlpf[core_no] = ++ ((curr_gain[core_no] & 0x8000) >> 15); ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ target_gain.ipa[core_no] = ++ curr_gain[core_no] & 0x000F; ++ target_gain.pad[core_no] = ++ ((curr_gain[core_no] & 0x00F0) >> 4); ++ target_gain.pga[core_no] = ++ ((curr_gain[core_no] & 0x0F00) >> 8); ++ target_gain.txgm[core_no] = ++ ((curr_gain[core_no] & 0x7000) >> 12); ++ } else { ++ target_gain.ipa[core_no] = ++ curr_gain[core_no] & 0x0003; ++ target_gain.pad[core_no] = ++ ((curr_gain[core_no] & 0x000C) >> 2); ++ target_gain.pga[core_no] = ++ ((curr_gain[core_no] & 0x0070) >> 4); ++ target_gain.txgm[core_no] = ++ ((curr_gain[core_no] & 0x0380) >> 7); ++ } ++ } ++ } else { ++ uint phyrev = pi->pubpi.phy_rev; ++ ++ base_idx[0] = (read_phy_reg(pi, 0x1ed) >> 8) & 0x7f; ++ base_idx[1] = (read_phy_reg(pi, 0x1ee) >> 8) & 0x7f; ++ for (core_no = 0; core_no < 2; core_no++) { ++ if (NREV_GE(phyrev, 3)) { ++ tx_pwrctrl_tbl = ++ brcms_phy_get_tx_pwrctrl_tbl(pi); ++ if (NREV_GE(phyrev, 7)) { ++ target_gain.ipa[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 16) & 0x7; ++ target_gain.pad[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 19) & 0x1f; ++ target_gain.pga[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 24) & 0xf; ++ target_gain.txgm[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 28) & 0x7; ++ target_gain.txlpf[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 31) & 0x1; ++ } else { ++ target_gain.ipa[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 16) & 0xf; ++ target_gain.pad[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 20) & 0xf; ++ target_gain.pga[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 24) & 0xf; ++ target_gain.txgm[core_no] = ++ (tx_pwrctrl_tbl ++ [base_idx[core_no]] ++ >> 28) & 0x7; ++ } ++ } else { ++ target_gain.ipa[core_no] = ++ (nphy_tpc_txgain[base_idx[core_no]] >> ++ 16) & 0x3; ++ target_gain.pad[core_no] = ++ (nphy_tpc_txgain[base_idx[core_no]] >> ++ 18) & 0x3; ++ target_gain.pga[core_no] = ++ (nphy_tpc_txgain[base_idx[core_no]] >> ++ 20) & 0x7; ++ target_gain.txgm[core_no] = ++ (nphy_tpc_txgain[base_idx[core_no]] >> ++ 23) & 0x7; ++ } ++ } ++ } ++ ++ return target_gain; ++} ++ ++static void ++wlc_phy_iqcal_gainparams_nphy(struct brcms_phy *pi, u16 core_no, ++ struct nphy_txgains target_gain, ++ struct nphy_iqcal_params *params) ++{ ++ u8 k; ++ int idx; ++ u16 gain_index; ++ u8 band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ params->txlpf = target_gain.txlpf[core_no]; ++ ++ params->txgm = target_gain.txgm[core_no]; ++ params->pga = target_gain.pga[core_no]; ++ params->pad = target_gain.pad[core_no]; ++ params->ipa = target_gain.ipa[core_no]; ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ params->cal_gain = ++ ((params->txlpf << 15) | (params->txgm << 12) | ++ (params->pga << 8) | ++ (params->pad << 3) | (params->ipa)); ++ else ++ params->cal_gain = ++ ((params->txgm << 12) | (params->pga << 8) | ++ (params->pad << 4) | (params->ipa)); ++ ++ params->ncorr[0] = 0x79; ++ params->ncorr[1] = 0x79; ++ params->ncorr[2] = 0x79; ++ params->ncorr[3] = 0x79; ++ params->ncorr[4] = 0x79; ++ } else { ++ ++ gain_index = ((target_gain.pad[core_no] << 0) | ++ (target_gain.pga[core_no] << 4) | ++ (target_gain.txgm[core_no] << 8)); ++ ++ idx = -1; ++ for (k = 0; k < NPHY_IQCAL_NUMGAINS; k++) { ++ if (tbl_iqcal_gainparams_nphy[band_idx][k][0] == ++ gain_index) { ++ idx = k; ++ break; ++ } ++ } ++ ++ params->txgm = tbl_iqcal_gainparams_nphy[band_idx][k][1]; ++ params->pga = tbl_iqcal_gainparams_nphy[band_idx][k][2]; ++ params->pad = tbl_iqcal_gainparams_nphy[band_idx][k][3]; ++ params->cal_gain = ((params->txgm << 7) | (params->pga << 4) | ++ (params->pad << 2)); ++ params->ncorr[0] = tbl_iqcal_gainparams_nphy[band_idx][k][4]; ++ params->ncorr[1] = tbl_iqcal_gainparams_nphy[band_idx][k][5]; ++ params->ncorr[2] = tbl_iqcal_gainparams_nphy[band_idx][k][6]; ++ params->ncorr[3] = tbl_iqcal_gainparams_nphy[band_idx][k][7]; ++ } ++} ++ ++static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi) ++{ ++ u16 jtag_core, core; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ for (core = 0; core <= 1; core++) { ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MASTER); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ IQCAL_VCM_HG); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ IQCAL_IDAC); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSI_VCM); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] = 0; ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MUX); ++ ++ if (pi->pubpi.radiorev != 5) ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, ++ core, ++ TSSIA); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSI_MISC1); ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MASTER, 0x0a); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ IQCAL_VCM_HG, 0x43); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ IQCAL_IDAC, 0x55); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSI_VCM, 0x00); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSIG, 0x00); ++ if (pi->use_int_tx_iqlo_cal_nphy) { ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, ++ core, TX_SSI_MUX, 0x4); ++ if (!(pi-> ++ internal_tx_iqlo_cal_tapoff_intpa_nphy)) ++ WRITE_RADIO_REG3(pi, RADIO_2057, ++ TX, core, ++ TSSIA, 0x31); ++ else ++ WRITE_RADIO_REG3(pi, RADIO_2057, ++ TX, core, ++ TSSIA, 0x21); ++ } ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSI_MISC1, 0x00); ++ } else { ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MASTER, 0x06); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ IQCAL_VCM_HG, 0x43); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ IQCAL_IDAC, 0x55); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSI_VCM, 0x00); ++ ++ if (pi->pubpi.radiorev != 5) ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, ++ core, TSSIA, 0x00); ++ if (pi->use_int_tx_iqlo_cal_nphy) { ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, ++ core, TX_SSI_MUX, ++ 0x06); ++ if (!(pi-> ++ internal_tx_iqlo_cal_tapoff_intpa_nphy)) ++ WRITE_RADIO_REG3(pi, RADIO_2057, ++ TX, core, ++ TSSIG, 0x31); ++ else ++ WRITE_RADIO_REG3(pi, RADIO_2057, ++ TX, core, ++ TSSIG, 0x21); ++ } ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSI_MISC1, 0x00); ++ } ++ } ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ for (core = 0; core <= 1; core++) { ++ jtag_core = ++ (core == ++ PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1; ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MASTER | ++ jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_IQCAL_VCM_HG | ++ jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_IQCAL_IDAC | ++ jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] = ++ read_radio_reg( ++ pi, ++ RADIO_2056_TX_TSSI_VCM | ++ jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TX_AMP_DET | ++ jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MUX | ++ jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TSSIA | jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TSSIG | jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC1 | ++ jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 9] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC2 | ++ jtag_core); ++ ++ pi->tx_rx_cal_radio_saveregs[(core * 11) + 10] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC3 | ++ jtag_core); ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MASTER | ++ jtag_core, 0x0a); ++ write_radio_reg(pi, ++ RADIO_2056_TX_IQCAL_VCM_HG | ++ jtag_core, 0x40); ++ write_radio_reg(pi, ++ RADIO_2056_TX_IQCAL_IDAC | ++ jtag_core, 0x55); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_VCM | ++ jtag_core, 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_AMP_DET | ++ jtag_core, 0x00); ++ ++ if (PHY_IPA(pi)) { ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TX_SSI_MUX ++ | jtag_core, 0x4); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSIA | ++ jtag_core, 0x1); ++ } else { ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TX_SSI_MUX ++ | jtag_core, 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSIA | ++ jtag_core, 0x2f); ++ } ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSIG | jtag_core, ++ 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC1 | ++ jtag_core, 0x00); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC2 | ++ jtag_core, 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC3 | ++ jtag_core, 0x00); ++ } else { ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MASTER | ++ jtag_core, 0x06); ++ write_radio_reg(pi, ++ RADIO_2056_TX_IQCAL_VCM_HG | ++ jtag_core, 0x40); ++ write_radio_reg(pi, ++ RADIO_2056_TX_IQCAL_IDAC | ++ jtag_core, 0x55); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_VCM | ++ jtag_core, 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_AMP_DET | ++ jtag_core, 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSIA | jtag_core, ++ 0x00); ++ ++ if (PHY_IPA(pi)) { ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TX_SSI_MUX ++ | jtag_core, 0x06); ++ if (NREV_LT(pi->pubpi.phy_rev, 5)) ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TSSIG ++ | jtag_core, ++ 0x11); ++ else ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TSSIG ++ | jtag_core, ++ 0x1); ++ } else { ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TX_SSI_MUX ++ | jtag_core, 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSIG | ++ jtag_core, 0x20); ++ } ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC1 | ++ jtag_core, 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC2 | ++ jtag_core, 0x00); ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC3 | ++ jtag_core, 0x00); ++ } ++ } ++ } else { ++ ++ pi->tx_rx_cal_radio_saveregs[0] = ++ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1); ++ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x29); ++ pi->tx_rx_cal_radio_saveregs[1] = ++ read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2); ++ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x54); ++ ++ pi->tx_rx_cal_radio_saveregs[2] = ++ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1); ++ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x29); ++ pi->tx_rx_cal_radio_saveregs[3] = ++ read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2); ++ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x54); ++ ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1); ++ pi->tx_rx_cal_radio_saveregs[5] = ++ read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2); ++ ++ if ((read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand) == ++ 0) { ++ ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04); ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04); ++ } else { ++ ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x20); ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x20); ++ } ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) { ++ ++ or_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0x20); ++ or_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0x20); ++ } else { ++ ++ and_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0xdf); ++ and_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0xdf); ++ } ++ } ++} ++ ++static void wlc_phy_txcal_radio_cleanup_nphy(struct brcms_phy *pi) ++{ ++ u16 jtag_core, core; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ for (core = 0; core <= 1; core++) { ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TX_SSI_MASTER, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 0]); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 1]); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 2]); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 3]); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TX_SSI_MUX, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 5]); ++ ++ if (pi->pubpi.radiorev != 5) ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TSSIA, ++ pi->tx_rx_cal_radio_saveregs ++ [(core * 11) + 6]); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 7]); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 8]); ++ } ++ } else if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ for (core = 0; core <= 1; core++) { ++ jtag_core = (core == PHY_CORE_0) ? ++ RADIO_2056_TX0 : RADIO_2056_TX1; ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MASTER | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 0]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_IQCAL_VCM_HG | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 1]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_IQCAL_IDAC | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 2]); ++ ++ write_radio_reg(pi, RADIO_2056_TX_TSSI_VCM | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 3]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_AMP_DET | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 4]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TX_SSI_MUX | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 5]); ++ ++ write_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 6]); ++ ++ write_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 7]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC1 | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 8]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC2 | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 9]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TSSI_MISC3 | jtag_core, ++ pi-> ++ tx_rx_cal_radio_saveregs[(core * 11) + ++ 10]); ++ } ++ } else { ++ ++ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, ++ pi->tx_rx_cal_radio_saveregs[0]); ++ write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, ++ pi->tx_rx_cal_radio_saveregs[1]); ++ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, ++ pi->tx_rx_cal_radio_saveregs[2]); ++ write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, ++ pi->tx_rx_cal_radio_saveregs[3]); ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, ++ pi->tx_rx_cal_radio_saveregs[4]); ++ write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, ++ pi->tx_rx_cal_radio_saveregs[5]); ++ } ++} ++ ++static void wlc_phy_txcal_physetup_nphy(struct brcms_phy *pi) ++{ ++ u16 val, mask; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6); ++ pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7); ++ ++ mask = ((0x3 << 8) | (0x3 << 10)); ++ val = (0x2 << 8); ++ val |= (0x2 << 10); ++ mod_phy_reg(pi, 0xa6, mask, val); ++ mod_phy_reg(pi, 0xa7, mask, val); ++ ++ val = read_phy_reg(pi, 0x8f); ++ pi->tx_rx_cal_phy_saveregs[2] = val; ++ val |= ((0x1 << 9) | (0x1 << 10)); ++ write_phy_reg(pi, 0x8f, val); ++ ++ val = read_phy_reg(pi, 0xa5); ++ pi->tx_rx_cal_phy_saveregs[3] = val; ++ val |= ((0x1 << 9) | (0x1 << 10)); ++ write_phy_reg(pi, 0xa5, val); ++ ++ pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x01); ++ mod_phy_reg(pi, 0x01, (0x1 << 15), 0); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16, ++ &val); ++ pi->tx_rx_cal_phy_saveregs[5] = val; ++ val = 0; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16, ++ &val); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16, ++ &val); ++ pi->tx_rx_cal_phy_saveregs[6] = val; ++ val = 0; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16, ++ &val); ++ ++ pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0x91); ++ pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0x92); ++ ++ if (!(pi->use_int_tx_iqlo_cal_nphy)) ++ wlc_phy_rfctrlintc_override_nphy( ++ pi, ++ NPHY_RfctrlIntc_override_PA, ++ 1, ++ RADIO_MIMO_CORESEL_CORE1 ++ | ++ RADIO_MIMO_CORESEL_CORE2); ++ else ++ wlc_phy_rfctrlintc_override_nphy( ++ pi, ++ NPHY_RfctrlIntc_override_PA, ++ 0, ++ RADIO_MIMO_CORESEL_CORE1 ++ | ++ RADIO_MIMO_CORESEL_CORE2); ++ ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ 0x2, RADIO_MIMO_CORESEL_CORE1); ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ 0x8, RADIO_MIMO_CORESEL_CORE2); ++ ++ pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297); ++ pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b); ++ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (0) << 0); ++ ++ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (0) << 0); ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7) ++ || NREV_GE(pi->pubpi.phy_rev, 8)) ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 7), ++ wlc_phy_read_lpf_bw_ctl_nphy ++ (pi, ++ 0), 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ ++ if (pi->use_int_tx_iqlo_cal_nphy ++ && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) { ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7)) { ++ ++ mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4, ++ 1 << 4); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ mod_radio_reg( ++ pi, ++ RADIO_2057_PAD2G_TUNE_PUS_CORE0, ++ 1, 0); ++ mod_radio_reg( ++ pi, ++ RADIO_2057_PAD2G_TUNE_PUS_CORE1, ++ 1, 0); ++ } else { ++ mod_radio_reg( ++ pi, ++ RADIO_2057_IPA5G_CASCOFFV_PU_CORE0, ++ 1, 0); ++ mod_radio_reg( ++ pi, ++ RADIO_2057_IPA5G_CASCOFFV_PU_CORE1, ++ 1, 0); ++ } ++ } else if (NREV_GE(pi->pubpi.phy_rev, 8)) { ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, ++ (0x1 << 3), 0, ++ 0x3, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ } ++ } ++ } else { ++ pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6); ++ pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7); ++ ++ mask = ((0x3 << 12) | (0x3 << 14)); ++ val = (0x2 << 12); ++ val |= (0x2 << 14); ++ mod_phy_reg(pi, 0xa6, mask, val); ++ mod_phy_reg(pi, 0xa7, mask, val); ++ ++ val = read_phy_reg(pi, 0xa5); ++ pi->tx_rx_cal_phy_saveregs[2] = val; ++ val |= ((0x1 << 12) | (0x1 << 13)); ++ write_phy_reg(pi, 0xa5, val); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16, ++ &val); ++ pi->tx_rx_cal_phy_saveregs[3] = val; ++ val |= 0x2000; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16, ++ &val); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16, ++ &val); ++ pi->tx_rx_cal_phy_saveregs[4] = val; ++ val |= 0x2000; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16, ++ &val); ++ ++ pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x91); ++ pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x92); ++ val = CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120; ++ write_phy_reg(pi, 0x91, val); ++ write_phy_reg(pi, 0x92, val); ++ } ++} ++ ++static void wlc_phy_txcal_phycleanup_nphy(struct brcms_phy *pi) ++{ ++ u16 mask; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ write_phy_reg(pi, 0xa6, pi->tx_rx_cal_phy_saveregs[0]); ++ write_phy_reg(pi, 0xa7, pi->tx_rx_cal_phy_saveregs[1]); ++ write_phy_reg(pi, 0x8f, pi->tx_rx_cal_phy_saveregs[2]); ++ write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[3]); ++ write_phy_reg(pi, 0x01, pi->tx_rx_cal_phy_saveregs[4]); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16, ++ &pi->tx_rx_cal_phy_saveregs[5]); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16, ++ &pi->tx_rx_cal_phy_saveregs[6]); ++ ++ write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[7]); ++ write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[8]); ++ ++ write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]); ++ write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]); ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7) ++ || NREV_GE(pi->pubpi.phy_rev, 8)) ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 7), 0, 0, ++ 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ ++ wlc_phy_resetcca_nphy(pi); ++ ++ if (pi->use_int_tx_iqlo_cal_nphy ++ && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) { ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7)) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ mod_radio_reg( ++ pi, ++ RADIO_2057_PAD2G_TUNE_PUS_CORE0, ++ 1, 1); ++ mod_radio_reg( ++ pi, ++ RADIO_2057_PAD2G_TUNE_PUS_CORE1, ++ 1, 1); ++ } else { ++ mod_radio_reg( ++ pi, ++ RADIO_2057_IPA5G_CASCOFFV_PU_CORE0, ++ 1, 1); ++ mod_radio_reg( ++ pi, ++ RADIO_2057_IPA5G_CASCOFFV_PU_CORE1, ++ 1, 1); ++ } ++ ++ mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4, ++ 0); ++ } else if (NREV_GE(pi->pubpi.phy_rev, 8)) { ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, ++ (0x1 << 3), 0, ++ 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ } ++ } ++ } else { ++ mask = ((0x3 << 12) | (0x3 << 14)); ++ mod_phy_reg(pi, 0xa6, mask, pi->tx_rx_cal_phy_saveregs[0]); ++ mod_phy_reg(pi, 0xa7, mask, pi->tx_rx_cal_phy_saveregs[1]); ++ write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[2]); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16, ++ &pi->tx_rx_cal_phy_saveregs[3]); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16, ++ &pi->tx_rx_cal_phy_saveregs[4]); ++ ++ write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[5]); ++ write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[6]); ++ } ++} ++ ++void ++wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, u8 num_samps) ++{ ++ u16 tssi_reg; ++ s32 temp, pwrindex[2]; ++ s32 idle_tssi[2]; ++ s32 rssi_buf[4]; ++ s32 tssival[2]; ++ u8 tssi_type; ++ ++ tssi_reg = read_phy_reg(pi, 0x1e9); ++ ++ temp = (s32) (tssi_reg & 0x3f); ++ idle_tssi[0] = (temp <= 31) ? temp : (temp - 64); ++ ++ temp = (s32) ((tssi_reg >> 8) & 0x3f); ++ idle_tssi[1] = (temp <= 31) ? temp : (temp - 64); ++ ++ tssi_type = ++ CHSPEC_IS5G(pi->radio_chanspec) ? ++ (u8)NPHY_RSSI_SEL_TSSI_5G : (u8)NPHY_RSSI_SEL_TSSI_2G; ++ ++ wlc_phy_poll_rssi_nphy(pi, tssi_type, rssi_buf, num_samps); ++ ++ tssival[0] = rssi_buf[0] / ((s32) num_samps); ++ tssival[1] = rssi_buf[2] / ((s32) num_samps); ++ ++ pwrindex[0] = idle_tssi[0] - tssival[0] + 64; ++ pwrindex[1] = idle_tssi[1] - tssival[1] + 64; ++ ++ if (pwrindex[0] < 0) ++ pwrindex[0] = 0; ++ else if (pwrindex[0] > 63) ++ pwrindex[0] = 63; ++ ++ if (pwrindex[1] < 0) ++ pwrindex[1] = 0; ++ else if (pwrindex[1] > 63) ++ pwrindex[1] = 63; ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 1, ++ (u32) pwrindex[0], 32, &qdBm_pwrbuf[0]); ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 1, ++ (u32) pwrindex[1], 32, &qdBm_pwrbuf[1]); ++} ++ ++static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core) ++{ ++ int index; ++ u32 bbmult_scale; ++ u16 bbmult; ++ u16 tblentry; ++ ++ struct nphy_txiqcal_ladder ladder_lo[] = { ++ {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0}, ++ {25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5}, ++ {25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7} ++ }; ++ ++ struct nphy_txiqcal_ladder ladder_iq[] = { ++ {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0}, ++ {25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1}, ++ {100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7} ++ }; ++ ++ bbmult = (core == PHY_CORE_0) ? ++ ((pi->nphy_txcal_bbmult >> 8) & 0xff) : ++ (pi->nphy_txcal_bbmult & 0xff); ++ ++ for (index = 0; index < 18; index++) { ++ bbmult_scale = ladder_lo[index].percent * bbmult; ++ bbmult_scale /= 100; ++ ++ tblentry = ++ ((bbmult_scale & 0xff) << 8) | ladder_lo[index].g_env; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index, 16, ++ &tblentry); ++ ++ bbmult_scale = ladder_iq[index].percent * bbmult; ++ bbmult_scale /= 100; ++ ++ tblentry = ++ ((bbmult_scale & 0xff) << 8) | ladder_iq[index].g_env; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index + 32, ++ 16, &tblentry); ++ } ++} ++ ++static u8 wlc_phy_txpwr_idx_cur_get_nphy(struct brcms_phy *pi, u8 core) ++{ ++ u16 tmp; ++ tmp = read_phy_reg(pi, ((core == PHY_CORE_0) ? 0x1ed : 0x1ee)); ++ ++ tmp = (tmp & (0x7f << 8)) >> 8; ++ return (u8) tmp; ++} ++ ++static void ++wlc_phy_txpwr_idx_cur_set_nphy(struct brcms_phy *pi, u8 idx0, u8 idx1) ++{ ++ mod_phy_reg(pi, 0x1e7, (0x7f << 0), idx0); ++ ++ if (NREV_GT(pi->pubpi.phy_rev, 1)) ++ mod_phy_reg(pi, 0x222, (0xff << 0), idx1); ++} ++ ++static u16 wlc_phy_ipa_get_bbmult_nphy(struct brcms_phy *pi) ++{ ++ u16 m0m1; ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1); ++ ++ return m0m1; ++} ++ ++static void wlc_phy_ipa_set_bbmult_nphy(struct brcms_phy *pi, u8 m0, u8 m1) ++{ ++ u16 m0m1 = (u16) ((m0 << 8) | m1); ++ ++ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m0m1); ++ wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &m0m1); ++} ++ ++static void ++wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi, ++ struct nphy_papd_restore_state *state, u8 core) ++{ ++ s32 tone_freq; ++ u8 off_core; ++ u16 mixgain = 0; ++ ++ off_core = core ^ 0x1; ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7) ++ || NREV_GE(pi->pubpi.phy_rev, 8)) ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 7), ++ wlc_phy_read_lpf_bw_ctl_nphy ++ (pi, ++ 0), 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (pi->pubpi.radiorev == 5) ++ mixgain = (core == 0) ? 0x20 : 0x00; ++ else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) ++ mixgain = 0x00; ++ else if ((pi->pubpi.radiorev <= 4) ++ || (pi->pubpi.radiorev == 6)) ++ mixgain = 0x00; ++ } else { ++ if ((pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) ++ mixgain = 0x50; ++ else if ((pi->pubpi.radiorev == 3) ++ || (pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) ++ mixgain = 0x0; ++ } ++ ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), ++ mixgain, (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_tx_pu, ++ 1, (1 << core), 0); ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_tx_pu, ++ 0, (1 << off_core), 0); ++ ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), ++ 0, 0x3, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, ++ (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, ++ (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, ++ (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0, ++ (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1, ++ (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0, ++ (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1, ++ (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), ++ 0, (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0, ++ (1 << core), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ ++ state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0xa6 : 0xa7); ++ state->afeoverride[core] = ++ read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5); ++ state->afectrl[off_core] = ++ read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa7 : 0xa6); ++ state->afeoverride[off_core] = ++ read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa5 : 0x8f); ++ ++ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7), ++ (0x1 << 2), 0); ++ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f : ++ 0xa5), (0x1 << 2), (0x1 << 2)); ++ ++ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa7 : 0xa6), ++ (0x1 << 2), (0x1 << 2)); ++ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa5 : ++ 0x8f), (0x1 << 2), (0x1 << 2)); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ state->pwrup[core] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_2G_PWRUP); ++ state->atten[core] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_2G_ATTEN); ++ state->pwrup[off_core] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, ++ TXRXCOUPLE_2G_PWRUP); ++ state->atten[off_core] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, ++ TXRXCOUPLE_2G_ATTEN); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_2G_PWRUP, 0xc); ++ ++ if ((pi->pubpi.radiorev == 3) || ++ (pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_2G_ATTEN, 0xf0); ++ else if (pi->pubpi.radiorev == 5) ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_2G_ATTEN, ++ (core == 0) ? 0xf7 : 0xf2); ++ else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_2G_ATTEN, 0xf0); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core, ++ TXRXCOUPLE_2G_PWRUP, 0x0); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core, ++ TXRXCOUPLE_2G_ATTEN, 0xff); ++ } else { ++ state->pwrup[core] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_5G_PWRUP); ++ state->atten[core] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_5G_ATTEN); ++ state->pwrup[off_core] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, ++ TXRXCOUPLE_5G_PWRUP); ++ state->atten[off_core] = ++ READ_RADIO_REG3(pi, RADIO_2057, TX, off_core, ++ TXRXCOUPLE_5G_ATTEN); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_5G_PWRUP, 0xc); ++ ++ if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_5G_ATTEN, 0xf4); ++ ++ else ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_5G_ATTEN, 0xf0); ++ ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core, ++ TXRXCOUPLE_5G_PWRUP, 0x0); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core, ++ TXRXCOUPLE_5G_ATTEN, 0xff); ++ } ++ ++ tone_freq = 4000; ++ ++ wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 13), (1) << 13); ++ ++ mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_OFF) << 0); ++ ++ mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 13), (0) << 13); ++ ++ } else { ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 0); ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0, 0); ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 0); ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 1, 0x3, 0); ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0x3, 0); ++ ++ state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0xa6 : 0xa7); ++ state->afeoverride[core] = ++ read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5); ++ ++ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7), ++ (0x1 << 0) | (0x1 << 1) | (0x1 << 2), 0); ++ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f : ++ 0xa5), ++ (0x1 << 0) | ++ (0x1 << 1) | ++ (0x1 << 2), (0x1 << 0) | (0x1 << 1) | (0x1 << 2)); ++ ++ state->vga_master[core] = ++ READ_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER); ++ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER, 0x2b); ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ state->fbmix[core] = ++ READ_RADIO_REG2(pi, RADIO_2056, RX, core, ++ TXFBMIX_G); ++ state->intpa_master[core] = ++ READ_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_MASTER); ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_G, ++ 0x03); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_MASTER, 0x04); ++ } else { ++ state->fbmix[core] = ++ READ_RADIO_REG2(pi, RADIO_2056, RX, core, ++ TXFBMIX_A); ++ state->intpa_master[core] = ++ READ_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAA_MASTER); ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_A, ++ 0x03); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAA_MASTER, 0x04); ++ ++ } ++ ++ tone_freq = 4000; ++ ++ wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (1) << 0); ++ ++ mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (0) << 0); ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0); ++ } ++} ++ ++static void ++wlc_phy_papd_cal_cleanup_nphy(struct brcms_phy *pi, ++ struct nphy_papd_restore_state *state) ++{ ++ u8 core; ++ ++ wlc_phy_stopplayback_nphy(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_2G_PWRUP, 0); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_2G_ATTEN, ++ state->atten[core]); ++ } else { ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_5G_PWRUP, 0); ++ WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, ++ TXRXCOUPLE_5G_ATTEN, ++ state->atten[core]); ++ } ++ } ++ ++ if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 2), ++ 1, 0x3, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ else ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 2), ++ 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), ++ 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0, 0x3, 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ ++ write_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0xa6 : 0xa7, state->afectrl[core]); ++ write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : ++ 0xa5, state->afeoverride[core]); ++ } ++ ++ wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff, ++ (state->mm & 0xff)); ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 7) ++ || NREV_GE(pi->pubpi.phy_rev, 8)) ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, (0x1 << 7), 0, 0, ++ 1, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ } else { ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1); ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 0x3, 1); ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 1); ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 0, 0x3, 1); ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 0, 0x3, 1); ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ ++ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER, ++ state->vga_master[core]); ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, ++ TXFBMIX_G, state->fbmix[core]); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAG_MASTER, ++ state->intpa_master[core]); ++ } else { ++ WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, ++ TXFBMIX_A, state->fbmix[core]); ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, ++ INTPAA_MASTER, ++ state->intpa_master[core]); ++ } ++ ++ write_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0xa6 : 0xa7, state->afectrl[core]); ++ write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : ++ 0xa5, state->afeoverride[core]); ++ } ++ ++ wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff, ++ (state->mm & 0xff)); ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 1); ++ } ++} ++ ++static void ++wlc_phy_a1_nphy(struct brcms_phy *pi, u8 core, u32 winsz, u32 start, ++ u32 end) ++{ ++ u32 *buf, *src, *dst, sz; ++ ++ sz = end - start + 1; ++ ++ buf = kmalloc(2 * sizeof(u32) * NPHY_PAPD_EPS_TBL_SIZE, GFP_ATOMIC); ++ if (NULL == buf) ++ return; ++ ++ src = buf; ++ dst = buf + NPHY_PAPD_EPS_TBL_SIZE; ++ ++ wlc_phy_table_read_nphy(pi, ++ (core == ++ PHY_CORE_0 ? NPHY_TBL_ID_EPSILONTBL0 : ++ NPHY_TBL_ID_EPSILONTBL1), ++ NPHY_PAPD_EPS_TBL_SIZE, 0, 32, src); ++ ++ do { ++ u32 phy_a1, phy_a2; ++ s32 phy_a3, phy_a4, phy_a5, phy_a6, phy_a7; ++ ++ phy_a1 = end - min(end, (winsz >> 1)); ++ phy_a2 = min_t(u32, NPHY_PAPD_EPS_TBL_SIZE - 1, ++ end + (winsz >> 1)); ++ phy_a3 = phy_a2 - phy_a1 + 1; ++ phy_a6 = 0; ++ phy_a7 = 0; ++ ++ do { ++ wlc_phy_papd_decode_epsilon(src[phy_a2], &phy_a4, ++ &phy_a5); ++ phy_a6 += phy_a4; ++ phy_a7 += phy_a5; ++ } while (phy_a2-- != phy_a1); ++ ++ phy_a6 /= phy_a3; ++ phy_a7 /= phy_a3; ++ dst[end] = ((u32) phy_a7 << 13) | ((u32) phy_a6 & 0x1fff); ++ } while (end-- != start); ++ ++ wlc_phy_table_write_nphy(pi, ++ (core == ++ PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 : ++ NPHY_TBL_ID_EPSILONTBL1, sz, start, 32, dst); ++ ++ kfree(buf); ++} ++ ++static void ++wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains, ++ enum phy_cal_mode cal_mode, u8 core) ++{ ++ u16 phy_a1, phy_a2, phy_a3; ++ u16 phy_a4, phy_a5; ++ bool phy_a6; ++ u8 phy_a7, m[2]; ++ u32 phy_a8 = 0; ++ struct nphy_txgains phy_a9; ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) ++ return; ++ ++ phy_a7 = (core == PHY_CORE_0) ? 1 : 0; ++ ++ phy_a6 = ((cal_mode == CAL_GCTRL) ++ || (cal_mode == CAL_SOFT)) ? true : false; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ phy_a9 = wlc_phy_get_tx_gain_nphy(pi); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ phy_a5 = ((phy_a9.txlpf[core] << 15) | ++ (phy_a9.txgm[core] << 12) | ++ (phy_a9.pga[core] << 8) | ++ (txgains->gains.pad[core] << 3) | ++ (phy_a9.ipa[core])); ++ else ++ phy_a5 = ((phy_a9.txlpf[core] << 15) | ++ (phy_a9.txgm[core] << 12) | ++ (txgains->gains.pga[core] << 8) | ++ (phy_a9.pad[core] << 3) | (phy_a9.ipa[core])); ++ ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_txgain, ++ phy_a5, (1 << core), 0); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if ((pi->pubpi.radiorev <= 4) ++ || (pi->pubpi.radiorev == 6)) ++ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? ++ 60 : 79; ++ else ++ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? ++ 45 : 64; ++ } else { ++ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 75 : 107; ++ } ++ ++ m[phy_a7] = 0; ++ wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]); ++ ++ phy_a2 = 63; ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if ((pi->pubpi.radiorev == 4) ++ || (pi->pubpi.radiorev == 6)) { ++ phy_a1 = 30; ++ phy_a3 = 30; ++ } else { ++ phy_a1 = 25; ++ phy_a3 = 25; ++ } ++ } else { ++ if ((pi->pubpi.radiorev == 5) ++ || (pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) { ++ phy_a1 = 25; ++ phy_a3 = 25; ++ } else { ++ phy_a1 = 35; ++ phy_a3 = 35; ++ } ++ } ++ ++ if (cal_mode == CAL_GCTRL) { ++ if ((pi->pubpi.radiorev == 5) ++ && (CHSPEC_IS2G(pi->radio_chanspec))) ++ phy_a1 = 55; ++ else if (((pi->pubpi.radiorev == 7) && ++ (CHSPEC_IS2G(pi->radio_chanspec))) || ++ ((pi->pubpi.radiorev == 8) && ++ (CHSPEC_IS2G(pi->radio_chanspec)))) ++ phy_a1 = 60; ++ else ++ phy_a1 = 63; ++ ++ } else if ((cal_mode != CAL_FULL) && (cal_mode != CAL_SOFT)) { ++ ++ phy_a1 = 35; ++ phy_a3 = 35; ++ } ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (1) << 0); ++ ++ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (0) << 0); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 13), (1) << 13); ++ ++ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 13), (0) << 13); ++ ++ write_phy_reg(pi, 0x2a1, 0x80); ++ write_phy_reg(pi, 0x2a2, 0x100); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x7 << 4), (11) << 4); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x7 << 8), (11) << 8); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x7 << 0), (0x3) << 0); ++ ++ write_phy_reg(pi, 0x2e5, 0x20); ++ ++ mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0); ++ ++ mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0); ++ ++ mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8); ++ ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), ++ 1, ((core == 0) ? 1 : 2), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), ++ 0, ((core == 0) ? 2 : 1), 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ ++ write_phy_reg(pi, 0x2be, 1); ++ SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000); ++ ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), ++ 0, 0x3, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ ++ wlc_phy_table_write_nphy(pi, ++ (core == ++ PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 ++ : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3, ++ 32, &phy_a8); ++ ++ if (cal_mode != CAL_GCTRL) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) ++ wlc_phy_a1_nphy(pi, core, 5, 0, 35); ++ } ++ ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_txgain, ++ phy_a5, (1 << core), 1); ++ ++ } else { ++ ++ if (txgains) { ++ if (txgains->useindex) { ++ phy_a4 = 15 - ((txgains->index) >> 3); ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 6)) ++ phy_a5 = 0x00f7 | (phy_a4 << 8); ++ ++ else ++ if (NREV_IS(pi->pubpi.phy_rev, 5)) ++ phy_a5 = 0x10f7 | (phy_a4 << 8); ++ else ++ phy_a5 = 0x50f7 | (phy_a4 << 8); ++ } else { ++ phy_a5 = 0x70f7 | (phy_a4 << 8); ++ } ++ wlc_phy_rfctrl_override_nphy(pi, ++ (0x1 << 13), ++ phy_a5, ++ (1 << core), 0); ++ } else { ++ wlc_phy_rfctrl_override_nphy(pi, ++ (0x1 << 13), ++ 0x5bf7, ++ (1 << core), 0); ++ } ++ } ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 45 : 64; ++ else ++ m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 75 : 107; ++ ++ m[phy_a7] = 0; ++ wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]); ++ ++ phy_a2 = 63; ++ ++ if (cal_mode == CAL_FULL) { ++ phy_a1 = 25; ++ phy_a3 = 25; ++ } else if (cal_mode == CAL_SOFT) { ++ phy_a1 = 25; ++ phy_a3 = 25; ++ } else if (cal_mode == CAL_GCTRL) { ++ phy_a1 = 63; ++ phy_a3 = 25; ++ } else { ++ ++ phy_a1 = 25; ++ phy_a3 = 25; ++ } ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (1) << 0); ++ ++ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (0) << 0); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 6)) { ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 13), (1) << 13); ++ ++ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 13), (0) << 13); ++ ++ write_phy_reg(pi, 0x2a1, 0x20); ++ write_phy_reg(pi, 0x2a2, 0x60); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0xf << 4), (9) << 4); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0xf << 8), (9) << 8); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0xf << 0), (0x2) << 0); ++ ++ write_phy_reg(pi, 0x2e5, 0x20); ++ } else { ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 11), (1) << 11); ++ ++ mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 11), (0) << 11); ++ ++ write_phy_reg(pi, 0x2a1, 0x80); ++ write_phy_reg(pi, 0x2a2, 0x600); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x7 << 4), (0) << 4); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x7 << 8), (0) << 8); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x7 << 0), (0x3) << 0); ++ ++ mod_phy_reg(pi, 0x2a0, (0x3f << 8), (0x20) << 8); ++ ++ } ++ ++ mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0); ++ ++ mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0); ++ ++ mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8); ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0x3, 0); ++ ++ write_phy_reg(pi, 0x2be, 1); ++ SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000); ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0); ++ ++ wlc_phy_table_write_nphy(pi, ++ (core == ++ PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 ++ : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3, ++ 32, &phy_a8); ++ ++ if (cal_mode != CAL_GCTRL) ++ wlc_phy_a1_nphy(pi, core, 5, 0, 40); ++ } ++} ++ ++static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core) ++{ ++ int phy_a1; ++ int phy_a2; ++ bool phy_a3; ++ struct nphy_ipa_txcalgains phy_a4; ++ bool phy_a5 = false; ++ bool phy_a6 = true; ++ s32 phy_a7, phy_a8; ++ u32 phy_a9; ++ int phy_a10; ++ bool phy_a11 = false; ++ int phy_a12; ++ u8 phy_a13 = 0; ++ u8 phy_a14; ++ u8 *phy_a15 = NULL; ++ ++ phy_a4.useindex = true; ++ phy_a12 = start_gain; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ phy_a2 = 20; ++ phy_a1 = 1; ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (pi->pubpi.radiorev == 5) { ++ ++ phy_a15 = pad_gain_codes_used_2057rev5; ++ phy_a13 = ++ sizeof(pad_gain_codes_used_2057rev5) / ++ sizeof(pad_gain_codes_used_2057rev5 ++ [0]) - 1; ++ ++ } else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) { ++ ++ phy_a15 = pad_gain_codes_used_2057rev7; ++ phy_a13 = ++ sizeof(pad_gain_codes_used_2057rev7) / ++ sizeof(pad_gain_codes_used_2057rev7 ++ [0]) - 1; ++ ++ } else { ++ ++ phy_a15 = pad_all_gain_codes_2057; ++ phy_a13 = sizeof(pad_all_gain_codes_2057) / ++ sizeof(pad_all_gain_codes_2057[0]) - ++ 1; ++ } ++ ++ } else { ++ ++ phy_a15 = pga_all_gain_codes_2057; ++ phy_a13 = sizeof(pga_all_gain_codes_2057) / ++ sizeof(pga_all_gain_codes_2057[0]) - 1; ++ } ++ ++ phy_a14 = 0; ++ ++ for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ phy_a4.gains.pad[core] = ++ (u16) phy_a15[phy_a12]; ++ else ++ phy_a4.gains.pga[core] = ++ (u16) phy_a15[phy_a12]; ++ ++ wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core); ++ ++ wlc_phy_table_read_nphy(pi, ++ (core == ++ PHY_CORE_0 ? ++ NPHY_TBL_ID_EPSILONTBL0 : ++ NPHY_TBL_ID_EPSILONTBL1), 1, ++ 63, 32, &phy_a9); ++ ++ wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8); ++ ++ phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) || ++ (phy_a8 == 4095) || (phy_a8 == -4096)); ++ ++ if (!phy_a6 && (phy_a3 != phy_a5)) { ++ if (!phy_a3) ++ phy_a12 -= (u8) phy_a1; ++ ++ phy_a11 = true; ++ break; ++ } ++ ++ if (phy_a3) ++ phy_a12 += (u8) phy_a1; ++ else ++ phy_a12 -= (u8) phy_a1; ++ ++ if ((phy_a12 < phy_a14) || (phy_a12 > phy_a13)) { ++ if (phy_a12 < phy_a14) ++ phy_a12 = phy_a14; ++ else ++ phy_a12 = phy_a13; ++ ++ phy_a11 = true; ++ break; ++ } ++ ++ phy_a6 = false; ++ phy_a5 = phy_a3; ++ } ++ ++ } else { ++ phy_a2 = 10; ++ phy_a1 = 8; ++ for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) { ++ phy_a4.index = (u8) phy_a12; ++ wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core); ++ ++ wlc_phy_table_read_nphy(pi, ++ (core == ++ PHY_CORE_0 ? ++ NPHY_TBL_ID_EPSILONTBL0 : ++ NPHY_TBL_ID_EPSILONTBL1), 1, ++ 63, 32, &phy_a9); ++ ++ wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8); ++ ++ phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) || ++ (phy_a8 == 4095) || (phy_a8 == -4096)); ++ ++ if (!phy_a6 && (phy_a3 != phy_a5)) { ++ if (!phy_a3) ++ phy_a12 -= (u8) phy_a1; ++ ++ phy_a11 = true; ++ break; ++ } ++ ++ if (phy_a3) ++ phy_a12 += (u8) phy_a1; ++ else ++ phy_a12 -= (u8) phy_a1; ++ ++ if ((phy_a12 < 0) || (phy_a12 > 127)) { ++ if (phy_a12 < 0) ++ phy_a12 = 0; ++ else ++ phy_a12 = 127; ++ ++ phy_a11 = true; ++ break; ++ } ++ ++ phy_a6 = false; ++ phy_a5 = phy_a3; ++ } ++ ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ return (u8) phy_a15[phy_a12]; ++ else ++ return (u8) phy_a12; ++ ++} ++ ++static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal) ++{ ++ struct nphy_ipa_txcalgains phy_b1[2]; ++ struct nphy_papd_restore_state phy_b2; ++ bool phy_b3; ++ u8 phy_b4; ++ u8 phy_b5; ++ s16 phy_b6, phy_b7, phy_b8; ++ u16 phy_b9; ++ s16 phy_b10, phy_b11, phy_b12; ++ ++ phy_b11 = 0; ++ phy_b12 = 0; ++ phy_b7 = 0; ++ phy_b8 = 0; ++ phy_b6 = 0; ++ ++ if (pi->nphy_papd_skip == 1) ++ return; ++ ++ phy_b3 = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)); ++ if (!phy_b3) ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ pi->nphy_force_papd_cal = false; ++ ++ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) ++ pi->nphy_papd_tx_gain_at_last_cal[phy_b5] = ++ wlc_phy_txpwr_idx_cur_get_nphy(pi, phy_b5); ++ ++ pi->nphy_papd_last_cal = pi->sh->now; ++ pi->nphy_papd_recal_counter++; ++ ++ phy_b4 = pi->nphy_txpwrctrl; ++ wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL0, 64, 0, 32, ++ nphy_papd_scaltbl); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL1, 64, 0, 32, ++ nphy_papd_scaltbl); ++ ++ phy_b9 = read_phy_reg(pi, 0x01); ++ mod_phy_reg(pi, 0x01, (0x1 << 15), 0); ++ ++ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) { ++ s32 i, val = 0; ++ for (i = 0; i < 64; i++) ++ wlc_phy_table_write_nphy(pi, ++ ((phy_b5 == ++ PHY_CORE_0) ? ++ NPHY_TBL_ID_EPSILONTBL0 : ++ NPHY_TBL_ID_EPSILONTBL1), 1, ++ i, 32, &val); ++ } ++ ++ wlc_phy_ipa_restore_tx_digi_filts_nphy(pi); ++ ++ phy_b2.mm = wlc_phy_ipa_get_bbmult_nphy(pi); ++ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) { ++ wlc_phy_papd_cal_setup_nphy(pi, &phy_b2, phy_b5); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if ((pi->pubpi.radiorev == 3) ++ || (pi->pubpi.radiorev == 4) ++ || (pi->pubpi.radiorev == 6)) { ++ pi->nphy_papd_cal_gain_index[phy_b5] = ++ 23; ++ } else if (pi->pubpi.radiorev == 5) { ++ pi->nphy_papd_cal_gain_index[phy_b5] = ++ 0; ++ pi->nphy_papd_cal_gain_index[phy_b5] = ++ wlc_phy_a3_nphy( ++ pi, ++ pi-> ++ nphy_papd_cal_gain_index ++ [phy_b5], ++ phy_b5); ++ ++ } else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) { ++ ++ pi->nphy_papd_cal_gain_index[phy_b5] = ++ 0; ++ pi->nphy_papd_cal_gain_index[phy_b5] = ++ wlc_phy_a3_nphy( ++ pi, ++ pi-> ++ nphy_papd_cal_gain_index ++ [phy_b5], ++ phy_b5); ++ ++ } ++ ++ phy_b1[phy_b5].gains.pad[phy_b5] = ++ pi->nphy_papd_cal_gain_index[phy_b5]; ++ ++ } else { ++ pi->nphy_papd_cal_gain_index[phy_b5] = 0; ++ pi->nphy_papd_cal_gain_index[phy_b5] = ++ wlc_phy_a3_nphy( ++ pi, ++ pi-> ++ nphy_papd_cal_gain_index ++ [phy_b5], phy_b5); ++ phy_b1[phy_b5].gains.pga[phy_b5] = ++ pi->nphy_papd_cal_gain_index[phy_b5]; ++ } ++ } else { ++ phy_b1[phy_b5].useindex = true; ++ phy_b1[phy_b5].index = 16; ++ phy_b1[phy_b5].index = ++ wlc_phy_a3_nphy(pi, phy_b1[phy_b5].index, ++ phy_b5); ++ ++ pi->nphy_papd_cal_gain_index[phy_b5] = ++ 15 - ((phy_b1[phy_b5].index) >> 3); ++ } ++ ++ switch (pi->nphy_papd_cal_type) { ++ case 0: ++ wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_FULL, phy_b5); ++ break; ++ case 1: ++ wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_SOFT, phy_b5); ++ break; ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2); ++ } ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 7)) ++ wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2); ++ ++ for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) { ++ int eps_offset = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ if (pi->pubpi.radiorev == 3) ++ eps_offset = -2; ++ else if (pi->pubpi.radiorev == 5) ++ eps_offset = 3; ++ else ++ eps_offset = -1; ++ } else { ++ eps_offset = 2; ++ } ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ phy_b8 = phy_b1[phy_b5].gains.pad[phy_b5]; ++ phy_b10 = 0; ++ if ((pi->pubpi.radiorev == 3) || ++ (pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) { ++ phy_b12 = -( ++ nphy_papd_padgain_dlt_2g_2057rev3n4 ++ [phy_b8] + 1) / 2; ++ phy_b10 = -1; ++ } else if (pi->pubpi.radiorev == 5) { ++ phy_b12 = -( ++ nphy_papd_padgain_dlt_2g_2057rev5 ++ [phy_b8] + 1) / 2; ++ } else if ((pi->pubpi.radiorev == 7) || ++ (pi->pubpi.radiorev == 8)) { ++ phy_b12 = -( ++ nphy_papd_padgain_dlt_2g_2057rev7 ++ [phy_b8] + 1) / 2; ++ } ++ } else { ++ phy_b7 = phy_b1[phy_b5].gains.pga[phy_b5]; ++ if ((pi->pubpi.radiorev == 3) || ++ (pi->pubpi.radiorev == 4) || ++ (pi->pubpi.radiorev == 6)) ++ phy_b11 = ++ -(nphy_papd_pgagain_dlt_5g_2057 ++ [phy_b7] ++ + 1) / 2; ++ else if ((pi->pubpi.radiorev == 7) ++ || (pi->pubpi.radiorev == 8)) ++ phy_b11 = -( ++ nphy_papd_pgagain_dlt_5g_2057rev7 ++ [phy_b7] + 1) / 2; ++ ++ phy_b10 = -9; ++ } ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) ++ phy_b6 = ++ -60 + 27 + eps_offset + phy_b12 + ++ phy_b10; ++ else ++ phy_b6 = ++ -60 + 27 + eps_offset + phy_b11 + ++ phy_b10; ++ ++ mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 : ++ 0x29c, (0x1ff << 7), (phy_b6) << 7); ++ ++ pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6; ++ } else { ++ if (NREV_LT(pi->pubpi.phy_rev, 5)) ++ eps_offset = 4; ++ else ++ eps_offset = 2; ++ ++ phy_b7 = 15 - ((phy_b1[phy_b5].index) >> 3); ++ ++ if (CHSPEC_IS2G(pi->radio_chanspec)) { ++ phy_b11 = ++ -(nphy_papd_pga_gain_delta_ipa_2g[ ++ phy_b7] + ++ 1) / 2; ++ phy_b10 = 0; ++ } else { ++ phy_b11 = ++ -(nphy_papd_pga_gain_delta_ipa_5g[ ++ phy_b7] + ++ 1) / 2; ++ phy_b10 = -9; ++ } ++ ++ phy_b6 = -60 + 27 + eps_offset + phy_b11 + phy_b10; ++ ++ mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 : ++ 0x29c, (0x1ff << 7), (phy_b6) << 7); ++ ++ pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6; ++ } ++ } ++ ++ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0); ++ ++ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 6)) { ++ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 13), (0) << 13); ++ ++ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 13), (0) << 13); ++ ++ } else { ++ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 11), (0) << 11); ++ ++ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 : ++ 0x2a4, (0x1 << 11), (0) << 11); ++ ++ } ++ pi->nphy_papdcomp = NPHY_PAPD_COMP_ON; ++ ++ write_phy_reg(pi, 0x01, phy_b9); ++ ++ wlc_phy_ipa_set_tx_digi_filts_nphy(pi); ++ ++ wlc_phy_txpwrctrl_enable_nphy(pi, phy_b4); ++ if (phy_b4 == PHY_TPC_HW_OFF) { ++ wlc_phy_txpwr_index_nphy(pi, (1 << 0), ++ (s8) (pi->nphy_txpwrindex[0]. ++ index_internal), false); ++ wlc_phy_txpwr_index_nphy(pi, (1 << 1), ++ (s8) (pi->nphy_txpwrindex[1]. ++ index_internal), false); ++ } ++ ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ ++ if (!phy_b3) ++ wlapi_enable_mac(pi->sh->physhim); ++} ++ ++void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype) ++{ ++ struct nphy_txgains target_gain; ++ u8 tx_pwr_ctrl_state; ++ bool fullcal = true; ++ bool restore_tx_gain = false; ++ bool mphase; ++ ++ if (PHY_MUTED(pi)) ++ return; ++ ++ if (caltype == PHY_PERICAL_AUTO) ++ fullcal = (pi->radio_chanspec != pi->nphy_txiqlocal_chanspec); ++ else if (caltype == PHY_PERICAL_PARTIAL) ++ fullcal = false; ++ ++ if (pi->cal_type_override != PHY_PERICAL_AUTO) ++ fullcal = ++ (pi->cal_type_override == ++ PHY_PERICAL_FULL) ? true : false; ++ ++ if ((pi->mphase_cal_phase_id > MPHASE_CAL_STATE_INIT)) { ++ if (pi->nphy_txiqlocal_chanspec != pi->radio_chanspec) ++ wlc_phy_cal_perical_mphase_restart(pi); ++ } ++ ++ if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_RXCAL)) ++ wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000); ++ ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ wlc_phyreg_enter((struct brcms_phy_pub *) pi); ++ ++ if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_IDLE) || ++ (pi->mphase_cal_phase_id == MPHASE_CAL_STATE_INIT)) { ++ pi->nphy_cal_orig_pwr_idx[0] = ++ (u8) ((read_phy_reg(pi, 0x1ed) >> 8) & 0x7f); ++ pi->nphy_cal_orig_pwr_idx[1] = ++ (u8) ((read_phy_reg(pi, 0x1ee) >> 8) & 0x7f); ++ ++ if (pi->nphy_txpwrctrl != PHY_TPC_HW_OFF) { ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, ++ 0x110, 16, ++ pi->nphy_cal_orig_tx_gain); ++ } else { ++ pi->nphy_cal_orig_tx_gain[0] = 0; ++ pi->nphy_cal_orig_tx_gain[1] = 0; ++ } ++ } ++ target_gain = wlc_phy_get_tx_gain_nphy(pi); ++ tx_pwr_ctrl_state = pi->nphy_txpwrctrl; ++ wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF); ++ ++ if (pi->antsel_type == ANTSEL_2x3) ++ wlc_phy_antsel_init((struct brcms_phy_pub *) pi, true); ++ ++ mphase = (pi->mphase_cal_phase_id != MPHASE_CAL_STATE_IDLE); ++ if (!mphase) { ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ wlc_phy_precal_txgain_nphy(pi); ++ pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi); ++ restore_tx_gain = true; ++ ++ target_gain = pi->nphy_cal_target_gain; ++ } ++ if (0 == ++ wlc_phy_cal_txiqlo_nphy(pi, target_gain, fullcal, ++ mphase)) { ++ if (PHY_IPA(pi)) ++ wlc_phy_a4(pi, true); ++ ++ wlc_phyreg_exit((struct brcms_phy_pub *) pi); ++ wlapi_enable_mac(pi->sh->physhim); ++ wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, ++ 10000); ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ wlc_phyreg_enter((struct brcms_phy_pub *) pi); ++ ++ if (0 == wlc_phy_cal_rxiq_nphy(pi, target_gain, ++ (pi->first_cal_after_assoc || ++ (pi->cal_type_override == ++ PHY_PERICAL_FULL)) ? 2 : 0, false)) { ++ wlc_phy_savecal_nphy(pi); ++ ++ wlc_phy_txpwrctrl_coeff_setup_nphy(pi); ++ ++ pi->nphy_perical_last = pi->sh->now; ++ } ++ } ++ if (caltype != PHY_PERICAL_AUTO) ++ wlc_phy_rssi_cal_nphy(pi); ++ ++ if (pi->first_cal_after_assoc ++ || (pi->cal_type_override == PHY_PERICAL_FULL)) { ++ pi->first_cal_after_assoc = false; ++ wlc_phy_txpwrctrl_idle_tssi_nphy(pi); ++ wlc_phy_txpwrctrl_pwr_setup_nphy(pi); ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ wlc_phy_radio205x_vcocal_nphy(pi); ++ } else { ++ switch (pi->mphase_cal_phase_id) { ++ case MPHASE_CAL_STATE_INIT: ++ pi->nphy_perical_last = pi->sh->now; ++ pi->nphy_txiqlocal_chanspec = pi->radio_chanspec; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ wlc_phy_precal_txgain_nphy(pi); ++ ++ pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi); ++ pi->mphase_cal_phase_id++; ++ break; ++ ++ case MPHASE_CAL_STATE_TXPHASE0: ++ case MPHASE_CAL_STATE_TXPHASE1: ++ case MPHASE_CAL_STATE_TXPHASE2: ++ case MPHASE_CAL_STATE_TXPHASE3: ++ case MPHASE_CAL_STATE_TXPHASE4: ++ case MPHASE_CAL_STATE_TXPHASE5: ++ if ((pi->radar_percal_mask & 0x10) != 0) ++ pi->nphy_rxcal_active = true; ++ ++ if (wlc_phy_cal_txiqlo_nphy ++ (pi, pi->nphy_cal_target_gain, fullcal, ++ true) != 0) { ++ ++ wlc_phy_cal_perical_mphase_reset(pi); ++ break; ++ } ++ ++ if (NREV_LE(pi->pubpi.phy_rev, 2) && ++ (pi->mphase_cal_phase_id == ++ MPHASE_CAL_STATE_TXPHASE4)) ++ pi->mphase_cal_phase_id += 2; ++ else ++ pi->mphase_cal_phase_id++; ++ break; ++ ++ case MPHASE_CAL_STATE_PAPDCAL: ++ if ((pi->radar_percal_mask & 0x2) != 0) ++ pi->nphy_rxcal_active = true; ++ ++ if (PHY_IPA(pi)) ++ wlc_phy_a4(pi, true); ++ ++ pi->mphase_cal_phase_id++; ++ break; ++ ++ case MPHASE_CAL_STATE_RXCAL: ++ if ((pi->radar_percal_mask & 0x1) != 0) ++ pi->nphy_rxcal_active = true; ++ if (wlc_phy_cal_rxiq_nphy(pi, target_gain, ++ (pi->first_cal_after_assoc || ++ (pi->cal_type_override == ++ PHY_PERICAL_FULL)) ? 2 : 0, ++ false) == 0) ++ wlc_phy_savecal_nphy(pi); ++ ++ pi->mphase_cal_phase_id++; ++ break; ++ ++ case MPHASE_CAL_STATE_RSSICAL: ++ if ((pi->radar_percal_mask & 0x4) != 0) ++ pi->nphy_rxcal_active = true; ++ wlc_phy_txpwrctrl_coeff_setup_nphy(pi); ++ wlc_phy_rssi_cal_nphy(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ wlc_phy_radio205x_vcocal_nphy(pi); ++ ++ restore_tx_gain = true; ++ ++ if (pi->first_cal_after_assoc) ++ pi->mphase_cal_phase_id++; ++ else ++ wlc_phy_cal_perical_mphase_reset(pi); ++ ++ break; ++ ++ case MPHASE_CAL_STATE_IDLETSSI: ++ if ((pi->radar_percal_mask & 0x8) != 0) ++ pi->nphy_rxcal_active = true; ++ ++ if (pi->first_cal_after_assoc) { ++ pi->first_cal_after_assoc = false; ++ wlc_phy_txpwrctrl_idle_tssi_nphy(pi); ++ wlc_phy_txpwrctrl_pwr_setup_nphy(pi); ++ } ++ ++ wlc_phy_cal_perical_mphase_reset(pi); ++ break; ++ ++ default: ++ wlc_phy_cal_perical_mphase_reset(pi); ++ break; ++ } ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if (restore_tx_gain) { ++ if (tx_pwr_ctrl_state != PHY_TPC_HW_OFF) { ++ ++ wlc_phy_txpwr_index_nphy(pi, 1, ++ pi-> ++ nphy_cal_orig_pwr_idx ++ [0], false); ++ wlc_phy_txpwr_index_nphy(pi, 2, ++ pi-> ++ nphy_cal_orig_pwr_idx ++ [1], false); ++ ++ pi->nphy_txpwrindex[0].index = -1; ++ pi->nphy_txpwrindex[1].index = -1; ++ } else { ++ wlc_phy_txpwr_index_nphy(pi, (1 << 0), ++ (s8) (pi-> ++ nphy_txpwrindex ++ [0]. ++ index_internal), ++ false); ++ wlc_phy_txpwr_index_nphy(pi, (1 << 1), ++ (s8) (pi-> ++ nphy_txpwrindex ++ [1]. ++ index_internal), ++ false); ++ } ++ } ++ } ++ ++ wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state); ++ wlc_phyreg_exit((struct brcms_phy_pub *) pi); ++ wlapi_enable_mac(pi->sh->physhim); ++} ++ ++int ++wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, ++ bool fullcal, bool mphase) ++{ ++ u16 val; ++ u16 tbl_buf[11]; ++ u8 cal_cnt; ++ u16 cal_cmd; ++ u8 num_cals, max_cal_cmds; ++ u16 core_no, cal_type; ++ u16 diq_start = 0; ++ u8 phy_bw; ++ u16 max_val; ++ u16 tone_freq; ++ u16 gain_save[2]; ++ u16 cal_gain[2]; ++ struct nphy_iqcal_params cal_params[2]; ++ u32 tbl_len; ++ void *tbl_ptr; ++ bool ladder_updated[2]; ++ u8 mphase_cal_lastphase = 0; ++ int bcmerror = 0; ++ bool phyhang_avoid_state = false; ++ ++ u16 tbl_tx_iqlo_cal_loft_ladder_20[] = { ++ 0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901, ++ 0x1902, ++ 0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607, ++ 0x6407 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = { ++ 0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400, ++ 0x3200, ++ 0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406, ++ 0x6407 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_loft_ladder_40[] = { ++ 0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201, ++ 0x1202, ++ 0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207, ++ 0x4707 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = { ++ 0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900, ++ 0x2300, ++ 0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706, ++ 0x4707 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_startcoefs[] = { ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ++ 0x0000 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_cmds_fullcal[] = { ++ 0x8123, 0x8264, 0x8086, 0x8245, 0x8056, ++ 0x9123, 0x9264, 0x9086, 0x9245, 0x9056 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_cmds_recal[] = { ++ 0x8101, 0x8253, 0x8053, 0x8234, 0x8034, ++ 0x9101, 0x9253, 0x9053, 0x9234, 0x9034 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = { ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ++ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ++ 0x0000 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = { ++ 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234, ++ 0x9434, 0x9334, 0x9084, 0x9267, 0x9056, 0x9234 ++ }; ++ ++ u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = { ++ 0x8423, 0x8323, 0x8073, 0x8256, 0x8045, 0x8223, ++ 0x9423, 0x9323, 0x9073, 0x9256, 0x9045, 0x9223 ++ }; ++ ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 4)) { ++ phyhang_avoid_state = pi->phyhang_avoid; ++ pi->phyhang_avoid = false; ++ } ++ ++ if (CHSPEC_IS40(pi->radio_chanspec)) ++ phy_bw = 40; ++ else ++ phy_bw = 20; ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save); ++ ++ for (core_no = 0; core_no <= 1; core_no++) { ++ wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain, ++ &cal_params[core_no]); ++ cal_gain[core_no] = cal_params[core_no].cal_gain; ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain); ++ ++ wlc_phy_txcal_radio_setup_nphy(pi); ++ ++ wlc_phy_txcal_physetup_nphy(pi); ++ ++ ladder_updated[0] = ladder_updated[1] = false; ++ if (!(NREV_GE(pi->pubpi.phy_rev, 6) || ++ (NREV_IS(pi->pubpi.phy_rev, 5) && PHY_IPA(pi) ++ && (CHSPEC_IS2G(pi->radio_chanspec))))) { ++ ++ if (phy_bw == 40) { ++ tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_40; ++ tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_40); ++ } else { ++ tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_20; ++ tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_20); ++ } ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 0, ++ 16, tbl_ptr); ++ ++ if (phy_bw == 40) { ++ tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_40; ++ tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_40); ++ } else { ++ tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_20; ++ tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_20); ++ } ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 32, ++ 16, tbl_ptr); ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ write_phy_reg(pi, 0xc2, 0x8ad9); ++ else ++ write_phy_reg(pi, 0xc2, 0x8aa9); ++ ++ max_val = 250; ++ tone_freq = (phy_bw == 20) ? 2500 : 5000; ++ ++ if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) { ++ wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff, 0, 1, 0, false); ++ bcmerror = 0; ++ } else { ++ bcmerror = ++ wlc_phy_tx_tone_nphy(pi, tone_freq, max_val, 1, 0, ++ false); ++ } ++ ++ if (bcmerror == 0) { ++ ++ if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) { ++ tbl_ptr = pi->mphase_txcal_bestcoeffs; ++ tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs); ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) ++ tbl_len -= 2; ++ } else { ++ if ((!fullcal) && (pi->nphy_txiqlocal_coeffsvalid)) { ++ ++ tbl_ptr = pi->nphy_txiqlocal_bestc; ++ tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc); ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) ++ tbl_len -= 2; ++ } else { ++ ++ fullcal = true; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ tbl_ptr = ++ tbl_tx_iqlo_cal_startcoefs_nphyrev3; ++ tbl_len = ARRAY_SIZE( ++ tbl_tx_iqlo_cal_startcoefs_nphyrev3); ++ } else { ++ tbl_ptr = tbl_tx_iqlo_cal_startcoefs; ++ tbl_len = ARRAY_SIZE( ++ tbl_tx_iqlo_cal_startcoefs); ++ } ++ } ++ } ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 64, ++ 16, tbl_ptr); ++ ++ if (fullcal) { ++ max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ? ++ ARRAY_SIZE( ++ tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3) : ++ ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal); ++ } else { ++ max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ? ++ ARRAY_SIZE( ++ tbl_tx_iqlo_cal_cmds_recal_nphyrev3) : ++ ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal); ++ } ++ ++ if (mphase) { ++ cal_cnt = pi->mphase_txcal_cmdidx; ++ if ((cal_cnt + pi->mphase_txcal_numcmds) < max_cal_cmds) ++ num_cals = cal_cnt + pi->mphase_txcal_numcmds; ++ else ++ num_cals = max_cal_cmds; ++ } else { ++ cal_cnt = 0; ++ num_cals = max_cal_cmds; ++ } ++ ++ for (; cal_cnt < num_cals; cal_cnt++) { ++ ++ if (fullcal) { ++ cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ? ++ tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3 ++ [cal_cnt] : ++ tbl_tx_iqlo_cal_cmds_fullcal[cal_cnt]; ++ } else { ++ cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ? ++ tbl_tx_iqlo_cal_cmds_recal_nphyrev3[ ++ cal_cnt] ++ : tbl_tx_iqlo_cal_cmds_recal[cal_cnt]; ++ } ++ ++ core_no = ((cal_cmd & 0x3000) >> 12); ++ cal_type = ((cal_cmd & 0x0F00) >> 8); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 6) || ++ (NREV_IS(pi->pubpi.phy_rev, 5) && ++ PHY_IPA(pi) ++ && (CHSPEC_IS2G(pi->radio_chanspec)))) { ++ if (!ladder_updated[core_no]) { ++ wlc_phy_update_txcal_ladder_nphy( ++ pi, ++ core_no); ++ ladder_updated[core_no] = true; ++ } ++ } ++ ++ val = ++ (cal_params[core_no]. ++ ncorr[cal_type] << 8) | NPHY_N_GCTL; ++ write_phy_reg(pi, 0xc1, val); ++ ++ if ((cal_type == 1) || (cal_type == 3) ++ || (cal_type == 4)) { ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, ++ 1, 69 + core_no, 16, ++ tbl_buf); ++ ++ diq_start = tbl_buf[0]; ++ ++ tbl_buf[0] = 0; ++ wlc_phy_table_write_nphy(pi, ++ NPHY_TBL_ID_IQLOCAL, 1, ++ 69 + core_no, 16, ++ tbl_buf); ++ } ++ ++ write_phy_reg(pi, 0xc0, cal_cmd); ++ ++ SPINWAIT(((read_phy_reg(pi, 0xc0) & 0xc000) != 0), ++ 20000); ++ if (WARN(read_phy_reg(pi, 0xc0) & 0xc000, ++ "HW error: txiq calib")) ++ return -EIO; ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, ++ tbl_len, 96, 16, tbl_buf); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, ++ tbl_len, 64, 16, tbl_buf); ++ ++ if ((cal_type == 1) || (cal_type == 3) ++ || (cal_type == 4)) { ++ ++ tbl_buf[0] = diq_start; ++ ++ } ++ ++ } ++ ++ if (mphase) { ++ pi->mphase_txcal_cmdidx = num_cals; ++ if (pi->mphase_txcal_cmdidx >= max_cal_cmds) ++ pi->mphase_txcal_cmdidx = 0; ++ } ++ ++ mphase_cal_lastphase = ++ (NREV_LE(pi->pubpi.phy_rev, 2)) ? ++ MPHASE_CAL_STATE_TXPHASE4 : MPHASE_CAL_STATE_TXPHASE5; ++ ++ if (!mphase ++ || (pi->mphase_cal_phase_id == mphase_cal_lastphase)) { ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 96, ++ 16, tbl_buf); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, ++ 16, tbl_buf); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) { ++ ++ tbl_buf[0] = 0; ++ tbl_buf[1] = 0; ++ tbl_buf[2] = 0; ++ tbl_buf[3] = 0; ++ ++ } ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, ++ 16, tbl_buf); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 101, ++ 16, tbl_buf); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, ++ 16, tbl_buf); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, ++ 16, tbl_buf); ++ ++ tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc); ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) ++ tbl_len -= 2; ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, ++ tbl_len, 96, 16, ++ pi->nphy_txiqlocal_bestc); ++ ++ pi->nphy_txiqlocal_coeffsvalid = true; ++ pi->nphy_txiqlocal_chanspec = pi->radio_chanspec; ++ } else { ++ tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs); ++ if (NREV_LT(pi->pubpi.phy_rev, 3)) ++ tbl_len -= 2; ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, ++ tbl_len, 96, 16, ++ pi->mphase_txcal_bestcoeffs); ++ } ++ ++ wlc_phy_stopplayback_nphy(pi); ++ ++ write_phy_reg(pi, 0xc2, 0x0000); ++ ++ } ++ ++ wlc_phy_txcal_phycleanup_nphy(pi); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, ++ gain_save); ++ ++ wlc_phy_txcal_radio_cleanup_nphy(pi); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) { ++ if (!mphase ++ || (pi->mphase_cal_phase_id == mphase_cal_lastphase)) ++ wlc_phy_tx_iq_war_nphy(pi); ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 4)) ++ pi->phyhang_avoid = phyhang_avoid_state; ++ ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ ++ return bcmerror; ++} ++ ++static void wlc_phy_reapply_txcal_coeffs_nphy(struct brcms_phy *pi) ++{ ++ u16 tbl_buf[7]; ++ ++ if ((pi->nphy_txiqlocal_chanspec == pi->radio_chanspec) && ++ (pi->nphy_txiqlocal_coeffsvalid)) { ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, ++ ARRAY_SIZE(tbl_buf), 80, 16, tbl_buf); ++ ++ if ((pi->nphy_txiqlocal_bestc[0] != tbl_buf[0]) || ++ (pi->nphy_txiqlocal_bestc[1] != tbl_buf[1]) || ++ (pi->nphy_txiqlocal_bestc[2] != tbl_buf[2]) || ++ (pi->nphy_txiqlocal_bestc[3] != tbl_buf[3])) { ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, ++ 16, pi->nphy_txiqlocal_bestc); ++ ++ tbl_buf[0] = 0; ++ tbl_buf[1] = 0; ++ tbl_buf[2] = 0; ++ tbl_buf[3] = 0; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, ++ 16, tbl_buf); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, ++ 16, ++ &pi->nphy_txiqlocal_bestc[5]); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, ++ 16, ++ &pi->nphy_txiqlocal_bestc[5]); ++ } ++ } ++} ++ ++void ++wlc_phy_rx_iq_coeffs_nphy(struct brcms_phy *pi, u8 write, ++ struct nphy_iq_comp *pcomp) ++{ ++ if (write) { ++ write_phy_reg(pi, 0x9a, pcomp->a0); ++ write_phy_reg(pi, 0x9b, pcomp->b0); ++ write_phy_reg(pi, 0x9c, pcomp->a1); ++ write_phy_reg(pi, 0x9d, pcomp->b1); ++ } else { ++ pcomp->a0 = read_phy_reg(pi, 0x9a); ++ pcomp->b0 = read_phy_reg(pi, 0x9b); ++ pcomp->a1 = read_phy_reg(pi, 0x9c); ++ pcomp->b1 = read_phy_reg(pi, 0x9d); ++ } ++} ++ ++void ++wlc_phy_rx_iq_est_nphy(struct brcms_phy *pi, struct phy_iq_est *est, ++ u16 num_samps, u8 wait_time, u8 wait_for_crs) ++{ ++ u8 core; ++ ++ write_phy_reg(pi, 0x12b, num_samps); ++ mod_phy_reg(pi, 0x12a, (0xff << 0), (wait_time << 0)); ++ mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqMode, ++ (wait_for_crs) ? NPHY_IqestCmd_iqMode : 0); ++ ++ mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqstart, NPHY_IqestCmd_iqstart); ++ ++ SPINWAIT(((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) != 0), ++ 10000); ++ if (WARN(read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart, ++ "HW error: rxiq est")) ++ return; ++ ++ if ((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) == 0) { ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ est[core].i_pwr = ++ (read_phy_reg(pi, ++ NPHY_IqestipwrAccHi(core)) << 16) ++ | read_phy_reg(pi, NPHY_IqestipwrAccLo(core)); ++ est[core].q_pwr = ++ (read_phy_reg(pi, ++ NPHY_IqestqpwrAccHi(core)) << 16) ++ | read_phy_reg(pi, NPHY_IqestqpwrAccLo(core)); ++ est[core].iq_prod = ++ (read_phy_reg(pi, ++ NPHY_IqestIqAccHi(core)) << 16) | ++ read_phy_reg(pi, NPHY_IqestIqAccLo(core)); ++ } ++ } ++} ++ ++#define CAL_RETRY_CNT 2 ++static void wlc_phy_calc_rx_iq_comp_nphy(struct brcms_phy *pi, u8 core_mask) ++{ ++ u8 curr_core; ++ struct phy_iq_est est[PHY_CORE_MAX]; ++ struct nphy_iq_comp old_comp, new_comp; ++ s32 iq = 0; ++ u32 ii = 0, qq = 0; ++ s16 iq_nbits, qq_nbits, brsh, arsh; ++ s32 a, b, temp; ++ int bcmerror = 0; ++ uint cal_retry = 0; ++ ++ if (core_mask == 0x0) ++ return; ++ ++ wlc_phy_rx_iq_coeffs_nphy(pi, 0, &old_comp); ++ new_comp.a0 = new_comp.b0 = new_comp.a1 = new_comp.b1 = 0x0; ++ wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp); ++ ++cal_try: ++ wlc_phy_rx_iq_est_nphy(pi, est, 0x4000, 32, 0); ++ ++ new_comp = old_comp; ++ ++ for (curr_core = 0; curr_core < pi->pubpi.phy_corenum; curr_core++) { ++ ++ if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) { ++ iq = est[curr_core].iq_prod; ++ ii = est[curr_core].i_pwr; ++ qq = est[curr_core].q_pwr; ++ } else if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) { ++ iq = est[curr_core].iq_prod; ++ ii = est[curr_core].i_pwr; ++ qq = est[curr_core].q_pwr; ++ } else { ++ continue; ++ } ++ ++ if ((ii + qq) < NPHY_MIN_RXIQ_PWR) { ++ bcmerror = -EBADE; ++ break; ++ } ++ ++ iq_nbits = wlc_phy_nbits(iq); ++ qq_nbits = wlc_phy_nbits(qq); ++ ++ arsh = 10 - (30 - iq_nbits); ++ if (arsh >= 0) { ++ a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh))); ++ temp = (s32) (ii >> arsh); ++ if (temp == 0) { ++ bcmerror = -EBADE; ++ break; ++ } ++ } else { ++ a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh))); ++ temp = (s32) (ii << -arsh); ++ if (temp == 0) { ++ bcmerror = -EBADE; ++ break; ++ } ++ } ++ ++ a /= temp; ++ ++ brsh = qq_nbits - 31 + 20; ++ if (brsh >= 0) { ++ b = (qq << (31 - qq_nbits)); ++ temp = (s32) (ii >> brsh); ++ if (temp == 0) { ++ bcmerror = -EBADE; ++ break; ++ } ++ } else { ++ b = (qq << (31 - qq_nbits)); ++ temp = (s32) (ii << -brsh); ++ if (temp == 0) { ++ bcmerror = -EBADE; ++ break; ++ } ++ } ++ b /= temp; ++ b -= a * a; ++ b = (s32) int_sqrt((unsigned long) b); ++ b -= (1 << 10); ++ ++ if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ new_comp.a0 = (s16) a & 0x3ff; ++ new_comp.b0 = (s16) b & 0x3ff; ++ } else { ++ ++ new_comp.a0 = (s16) b & 0x3ff; ++ new_comp.b0 = (s16) a & 0x3ff; ++ } ++ } ++ if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ new_comp.a1 = (s16) a & 0x3ff; ++ new_comp.b1 = (s16) b & 0x3ff; ++ } else { ++ ++ new_comp.a1 = (s16) b & 0x3ff; ++ new_comp.b1 = (s16) a & 0x3ff; ++ } ++ } ++ } ++ ++ if (bcmerror != 0) { ++ printk(KERN_DEBUG "%s: Failed, cnt = %d\n", __func__, ++ cal_retry); ++ ++ if (cal_retry < CAL_RETRY_CNT) { ++ cal_retry++; ++ goto cal_try; ++ } ++ ++ new_comp = old_comp; ++ } ++ ++ wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp); ++} ++ ++static void wlc_phy_rxcal_radio_setup_nphy(struct brcms_phy *pi, u8 rx_core) ++{ ++ u16 offtune_val; ++ u16 bias_g = 0; ++ u16 bias_a = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (rx_core == PHY_CORE_0) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ pi->tx_rx_cal_radio_saveregs[0] = ++ read_radio_reg(pi, ++ RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP); ++ pi->tx_rx_cal_radio_saveregs[1] = ++ read_radio_reg(pi, ++ RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN); ++ ++ write_radio_reg(pi, ++ RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP, ++ 0x3); ++ write_radio_reg(pi, ++ RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN, ++ 0xaf); ++ ++ } else { ++ pi->tx_rx_cal_radio_saveregs[0] = ++ read_radio_reg(pi, ++ RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP); ++ pi->tx_rx_cal_radio_saveregs[1] = ++ read_radio_reg(pi, ++ RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP, ++ 0x3); ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN, ++ 0x7f); ++ } ++ ++ } else { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ pi->tx_rx_cal_radio_saveregs[0] = ++ read_radio_reg(pi, ++ RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP); ++ pi->tx_rx_cal_radio_saveregs[1] = ++ read_radio_reg(pi, ++ RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP, ++ 0x3); ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN, ++ 0xaf); ++ ++ } else { ++ pi->tx_rx_cal_radio_saveregs[0] = ++ read_radio_reg(pi, ++ RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP); ++ pi->tx_rx_cal_radio_saveregs[1] = ++ read_radio_reg(pi, ++ RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN); ++ ++ write_radio_reg(pi, ++ RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP, ++ 0x3); ++ write_radio_reg(pi, ++ RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN, ++ 0x7f); ++ } ++ } ++ ++ } else { ++ if (rx_core == PHY_CORE_0) { ++ pi->tx_rx_cal_radio_saveregs[0] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_RXIQCAL_TXMUX | ++ RADIO_2056_TX1); ++ pi->tx_rx_cal_radio_saveregs[1] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_RXIQCAL_RXMUX | ++ RADIO_2056_RX0); ++ ++ if (pi->pubpi.radiorev >= 5) { ++ pi->tx_rx_cal_radio_saveregs[2] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_RXSPARE2 | ++ RADIO_2056_RX0); ++ pi->tx_rx_cal_radio_saveregs[3] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TXSPARE2 | ++ RADIO_2056_TX1); ++ } ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ ++ if (pi->pubpi.radiorev >= 5) { ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_LNAA_MASTER ++ | RADIO_2056_RX0); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAA_MASTER ++ | RADIO_2056_RX0, 0x40); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TXSPARE2 | ++ RADIO_2056_TX1, bias_a); ++ ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXSPARE2 | ++ RADIO_2056_RX0, bias_a); ++ } else { ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_LNAA_TUNE ++ | RADIO_2056_RX0); ++ ++ offtune_val = ++ (pi->tx_rx_cal_radio_saveregs ++ [2] & 0xF0) >> 8; ++ offtune_val = ++ (offtune_val <= 0x7) ? 0xF : 0; ++ ++ mod_radio_reg(pi, ++ RADIO_2056_RX_LNAA_TUNE | ++ RADIO_2056_RX0, 0xF0, ++ (offtune_val << 8)); ++ } ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_RXIQCAL_TXMUX | ++ RADIO_2056_TX1, 0x9); ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXIQCAL_RXMUX | ++ RADIO_2056_RX0, 0x9); ++ } else { ++ if (pi->pubpi.radiorev >= 5) { ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_MASTER ++ | RADIO_2056_RX0); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_MASTER ++ | RADIO_2056_RX0, 0x40); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TXSPARE2 ++ | ++ RADIO_2056_TX1, bias_g); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_RXSPARE2 ++ | ++ RADIO_2056_RX0, bias_g); ++ ++ } else { ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_TUNE ++ | RADIO_2056_RX0); ++ ++ offtune_val = ++ (pi-> ++ tx_rx_cal_radio_saveregs[2] & ++ 0xF0) >> 8; ++ offtune_val = ++ (offtune_val <= 0x7) ? 0xF : 0; ++ ++ mod_radio_reg(pi, ++ RADIO_2056_RX_LNAG_TUNE | ++ RADIO_2056_RX0, 0xF0, ++ (offtune_val << 8)); ++ } ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_RXIQCAL_TXMUX | ++ RADIO_2056_TX1, 0x6); ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXIQCAL_RXMUX | ++ RADIO_2056_RX0, 0x6); ++ } ++ ++ } else { ++ pi->tx_rx_cal_radio_saveregs[0] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_RXIQCAL_TXMUX | ++ RADIO_2056_TX0); ++ pi->tx_rx_cal_radio_saveregs[1] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_RXIQCAL_RXMUX | ++ RADIO_2056_RX1); ++ ++ if (pi->pubpi.radiorev >= 5) { ++ pi->tx_rx_cal_radio_saveregs[2] = ++ read_radio_reg(pi, ++ RADIO_2056_RX_RXSPARE2 | ++ RADIO_2056_RX1); ++ pi->tx_rx_cal_radio_saveregs[3] = ++ read_radio_reg(pi, ++ RADIO_2056_TX_TXSPARE2 | ++ RADIO_2056_TX0); ++ } ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ ++ if (pi->pubpi.radiorev >= 5) { ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAA_MASTER ++ | RADIO_2056_RX1); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAA_MASTER | ++ RADIO_2056_RX1, 0x40); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TXSPARE2 ++ | ++ RADIO_2056_TX0, bias_a); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_RXSPARE2 ++ | ++ RADIO_2056_RX1, bias_a); ++ } else { ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAA_TUNE ++ | RADIO_2056_RX1); ++ ++ offtune_val = ++ (pi-> ++ tx_rx_cal_radio_saveregs[2] & ++ 0xF0) >> 8; ++ offtune_val = ++ (offtune_val <= 0x7) ? 0xF : 0; ++ ++ mod_radio_reg(pi, ++ RADIO_2056_RX_LNAA_TUNE | ++ RADIO_2056_RX1, 0xF0, ++ (offtune_val << 8)); ++ } ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_RXIQCAL_TXMUX | ++ RADIO_2056_TX0, 0x9); ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXIQCAL_RXMUX | ++ RADIO_2056_RX1, 0x9); ++ } else { ++ if (pi->pubpi.radiorev >= 5) { ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_MASTER ++ | RADIO_2056_RX1); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_MASTER ++ | RADIO_2056_RX1, 0x40); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_TX_TXSPARE2 ++ | ++ RADIO_2056_TX0, bias_g); ++ ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_RXSPARE2 ++ | ++ RADIO_2056_RX1, bias_g); ++ } else { ++ pi->tx_rx_cal_radio_saveregs[4] = ++ read_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_TUNE ++ | RADIO_2056_RX1); ++ ++ offtune_val = ++ (pi-> ++ tx_rx_cal_radio_saveregs[2] & ++ 0xF0) >> 8; ++ offtune_val = ++ (offtune_val <= 0x7) ? 0xF : 0; ++ ++ mod_radio_reg(pi, ++ RADIO_2056_RX_LNAG_TUNE | ++ RADIO_2056_RX1, 0xF0, ++ (offtune_val << 8)); ++ } ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_RXIQCAL_TXMUX | ++ RADIO_2056_TX0, 0x6); ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXIQCAL_RXMUX | ++ RADIO_2056_RX1, 0x6); ++ } ++ } ++ } ++} ++ ++static void wlc_phy_rxcal_radio_cleanup_nphy(struct brcms_phy *pi, u8 rx_core) ++{ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ if (rx_core == PHY_CORE_0) { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP, ++ pi-> ++ tx_rx_cal_radio_saveregs[0]); ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN, ++ pi-> ++ tx_rx_cal_radio_saveregs[1]); ++ ++ } else { ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP, ++ pi-> ++ tx_rx_cal_radio_saveregs[0]); ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN, ++ pi-> ++ tx_rx_cal_radio_saveregs[1]); ++ } ++ ++ } else { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP, ++ pi-> ++ tx_rx_cal_radio_saveregs[0]); ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN, ++ pi-> ++ tx_rx_cal_radio_saveregs[1]); ++ ++ } else { ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP, ++ pi-> ++ tx_rx_cal_radio_saveregs[0]); ++ write_radio_reg( ++ pi, ++ RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN, ++ pi-> ++ tx_rx_cal_radio_saveregs[1]); ++ } ++ } ++ ++ } else { ++ if (rx_core == PHY_CORE_0) { ++ write_radio_reg(pi, ++ RADIO_2056_TX_RXIQCAL_TXMUX | ++ RADIO_2056_TX1, ++ pi->tx_rx_cal_radio_saveregs[0]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXIQCAL_RXMUX | ++ RADIO_2056_RX0, ++ pi->tx_rx_cal_radio_saveregs[1]); ++ ++ if (pi->pubpi.radiorev >= 5) { ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXSPARE2 | ++ RADIO_2056_RX0, ++ pi-> ++ tx_rx_cal_radio_saveregs[2]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TXSPARE2 | ++ RADIO_2056_TX1, ++ pi-> ++ tx_rx_cal_radio_saveregs[3]); ++ } ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (pi->pubpi.radiorev >= 5) ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAA_MASTER ++ | RADIO_2056_RX0, ++ pi-> ++ tx_rx_cal_radio_saveregs ++ [4]); ++ else ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAA_TUNE ++ | RADIO_2056_RX0, ++ pi-> ++ tx_rx_cal_radio_saveregs ++ [4]); ++ } else { ++ if (pi->pubpi.radiorev >= 5) ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_MASTER ++ | RADIO_2056_RX0, ++ pi-> ++ tx_rx_cal_radio_saveregs ++ [4]); ++ else ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_TUNE ++ | RADIO_2056_RX0, ++ pi-> ++ tx_rx_cal_radio_saveregs ++ [4]); ++ } ++ ++ } else { ++ write_radio_reg(pi, ++ RADIO_2056_TX_RXIQCAL_TXMUX | ++ RADIO_2056_TX0, ++ pi->tx_rx_cal_radio_saveregs[0]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXIQCAL_RXMUX | ++ RADIO_2056_RX1, ++ pi->tx_rx_cal_radio_saveregs[1]); ++ ++ if (pi->pubpi.radiorev >= 5) { ++ write_radio_reg(pi, ++ RADIO_2056_RX_RXSPARE2 | ++ RADIO_2056_RX1, ++ pi-> ++ tx_rx_cal_radio_saveregs[2]); ++ ++ write_radio_reg(pi, ++ RADIO_2056_TX_TXSPARE2 | ++ RADIO_2056_TX0, ++ pi-> ++ tx_rx_cal_radio_saveregs[3]); ++ } ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (pi->pubpi.radiorev >= 5) ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAA_MASTER ++ | RADIO_2056_RX1, ++ pi-> ++ tx_rx_cal_radio_saveregs ++ [4]); ++ else ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAA_TUNE ++ | RADIO_2056_RX1, ++ pi-> ++ tx_rx_cal_radio_saveregs ++ [4]); ++ } else { ++ if (pi->pubpi.radiorev >= 5) ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_MASTER ++ | RADIO_2056_RX1, ++ pi-> ++ tx_rx_cal_radio_saveregs ++ [4]); ++ else ++ write_radio_reg( ++ pi, ++ RADIO_2056_RX_LNAG_TUNE ++ | RADIO_2056_RX1, ++ pi-> ++ tx_rx_cal_radio_saveregs ++ [4]); ++ } ++ } ++ } ++} ++ ++static void wlc_phy_rxcal_physetup_nphy(struct brcms_phy *pi, u8 rx_core) ++{ ++ u8 tx_core; ++ u16 rx_antval, tx_antval; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ tx_core = rx_core; ++ else ++ tx_core = (rx_core == PHY_CORE_0) ? 1 : 0; ++ ++ pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa2); ++ pi->tx_rx_cal_phy_saveregs[1] = ++ read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7); ++ pi->tx_rx_cal_phy_saveregs[2] = ++ read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5); ++ pi->tx_rx_cal_phy_saveregs[3] = read_phy_reg(pi, 0x91); ++ pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x92); ++ pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x7a); ++ pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x7d); ++ pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0xe7); ++ pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0xec); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ pi->tx_rx_cal_phy_saveregs[11] = read_phy_reg(pi, 0x342); ++ pi->tx_rx_cal_phy_saveregs[12] = read_phy_reg(pi, 0x343); ++ pi->tx_rx_cal_phy_saveregs[13] = read_phy_reg(pi, 0x346); ++ pi->tx_rx_cal_phy_saveregs[14] = read_phy_reg(pi, 0x347); ++ } ++ ++ pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297); ++ pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b); ++ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (0) << 0); ++ ++ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 0), (0) << 0); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0); ++ ++ mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << (1 - rx_core)) << 12); ++ ++ } else { ++ ++ mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12); ++ mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0); ++ mod_phy_reg(pi, 0xa2, (0xf << 4), (1 << rx_core) << 4); ++ mod_phy_reg(pi, 0xa2, (0xf << 8), (1 << rx_core) << 8); ++ } ++ ++ mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7), (0x1 << 2), 0); ++ mod_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5, ++ (0x1 << 2), (0x1 << 2)); ++ if (NREV_LT(pi->pubpi.phy_rev, 7)) { ++ mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7), ++ (0x1 << 0) | (0x1 << 1), 0); ++ mod_phy_reg(pi, (rx_core == PHY_CORE_0) ? ++ 0x8f : 0xa5, ++ (0x1 << 0) | (0x1 << 1), (0x1 << 0) | (0x1 << 1)); ++ } ++ ++ wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 0, ++ RADIO_MIMO_CORESEL_CORE1 | ++ RADIO_MIMO_CORESEL_CORE2); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), ++ 0, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID0); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 0, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 1, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 1, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID2); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ if (CHSPEC_IS40(pi->radio_chanspec)) ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, ++ (0x1 << 7), ++ 2, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ else ++ wlc_phy_rfctrl_override_nphy_rev7( ++ pi, ++ (0x1 << 7), ++ 0, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), ++ 0, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0, 0, ++ NPHY_REV7_RFCTRLOVERRIDE_ID1); ++ } else { ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 3, 0); ++ } ++ ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ 0x1, rx_core + 1); ++ } else { ++ ++ if (rx_core == PHY_CORE_0) { ++ rx_antval = 0x1; ++ tx_antval = 0x8; ++ } else { ++ rx_antval = 0x4; ++ tx_antval = 0x2; ++ } ++ ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ rx_antval, rx_core + 1); ++ wlc_phy_rfctrlintc_override_nphy(pi, ++ NPHY_RfctrlIntc_override_TRSW, ++ tx_antval, tx_core + 1); ++ } ++} ++ ++static void wlc_phy_rxcal_phycleanup_nphy(struct brcms_phy *pi, u8 rx_core) ++{ ++ ++ write_phy_reg(pi, 0xa2, pi->tx_rx_cal_phy_saveregs[0]); ++ write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7, ++ pi->tx_rx_cal_phy_saveregs[1]); ++ write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5, ++ pi->tx_rx_cal_phy_saveregs[2]); ++ write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[3]); ++ write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[4]); ++ ++ write_phy_reg(pi, 0x7a, pi->tx_rx_cal_phy_saveregs[5]); ++ write_phy_reg(pi, 0x7d, pi->tx_rx_cal_phy_saveregs[6]); ++ write_phy_reg(pi, 0xe7, pi->tx_rx_cal_phy_saveregs[7]); ++ write_phy_reg(pi, 0xec, pi->tx_rx_cal_phy_saveregs[8]); ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ write_phy_reg(pi, 0x342, pi->tx_rx_cal_phy_saveregs[11]); ++ write_phy_reg(pi, 0x343, pi->tx_rx_cal_phy_saveregs[12]); ++ write_phy_reg(pi, 0x346, pi->tx_rx_cal_phy_saveregs[13]); ++ write_phy_reg(pi, 0x347, pi->tx_rx_cal_phy_saveregs[14]); ++ } ++ ++ write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]); ++ write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]); ++} ++ ++static void ++wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core, ++ u16 *rxgain, u8 cal_type) ++{ ++ ++ u16 num_samps; ++ struct phy_iq_est est[PHY_CORE_MAX]; ++ u8 tx_core; ++ struct nphy_iq_comp save_comp, zero_comp; ++ u32 i_pwr, q_pwr, curr_pwr, optim_pwr = 0, prev_pwr = 0, ++ thresh_pwr = 10000; ++ s16 desired_log2_pwr, actual_log2_pwr, delta_pwr; ++ bool gainctrl_done = false; ++ u8 mix_tia_gain = 3; ++ s8 optim_gaintbl_index = 0, prev_gaintbl_index = 0; ++ s8 curr_gaintbl_index = 3; ++ u8 gainctrl_dirn = NPHY_RXCAL_GAIN_INIT; ++ const struct nphy_ipa_txrxgain *nphy_rxcal_gaintbl; ++ u16 hpvga, lpf_biq1, lpf_biq0, lna2, lna1; ++ int fine_gain_idx; ++ s8 txpwrindex; ++ u16 nphy_rxcal_txgain[2]; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ tx_core = rx_core; ++ else ++ tx_core = 1 - rx_core; ++ ++ num_samps = 1024; ++ desired_log2_pwr = (cal_type == 0) ? 13 : 13; ++ ++ wlc_phy_rx_iq_coeffs_nphy(pi, 0, &save_comp); ++ zero_comp.a0 = zero_comp.b0 = zero_comp.a1 = zero_comp.b1 = 0x0; ++ wlc_phy_rx_iq_coeffs_nphy(pi, 1, &zero_comp); ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ mix_tia_gain = 3; ++ else if (NREV_GE(pi->pubpi.phy_rev, 4)) ++ mix_tia_gain = 4; ++ else ++ mix_tia_gain = 6; ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz_rev7; ++ else ++ nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz; ++ } else { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz_rev7; ++ else ++ nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz; ++ } ++ ++ do { ++ ++ hpvga = (NREV_GE(pi->pubpi.phy_rev, 7)) ? ++ 0 : nphy_rxcal_gaintbl[curr_gaintbl_index].hpvga; ++ lpf_biq1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq1; ++ lpf_biq0 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq0; ++ lna2 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna2; ++ lna1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna1; ++ txpwrindex = nphy_rxcal_gaintbl[curr_gaintbl_index].txpwrindex; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_rxgain, ++ ((lpf_biq1 << 12) | ++ (lpf_biq0 << 8) | ++ (mix_tia_gain << 4) | (lna2 << 2) ++ | lna1), 0x3, 0); ++ else ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), ++ ((hpvga << 12) | ++ (lpf_biq1 << 10) | ++ (lpf_biq0 << 8) | ++ (mix_tia_gain << 4) | ++ (lna2 << 2) | lna1), 0x3, ++ 0); ++ ++ pi->nphy_rxcal_pwr_idx[tx_core] = txpwrindex; ++ ++ if (txpwrindex == -1) { ++ nphy_rxcal_txgain[0] = 0x8ff0 | pi->nphy_gmval; ++ nphy_rxcal_txgain[1] = 0x8ff0 | pi->nphy_gmval; ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, ++ 2, 0x110, 16, ++ nphy_rxcal_txgain); ++ } else { ++ wlc_phy_txpwr_index_nphy(pi, tx_core + 1, txpwrindex, ++ false); ++ } ++ ++ wlc_phy_tx_tone_nphy(pi, (CHSPEC_IS40(pi->radio_chanspec)) ? ++ NPHY_RXCAL_TONEFREQ_40MHz : ++ NPHY_RXCAL_TONEFREQ_20MHz, ++ NPHY_RXCAL_TONEAMP, 0, cal_type, false); ++ ++ wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0); ++ i_pwr = (est[rx_core].i_pwr + num_samps / 2) / num_samps; ++ q_pwr = (est[rx_core].q_pwr + num_samps / 2) / num_samps; ++ curr_pwr = i_pwr + q_pwr; ++ ++ switch (gainctrl_dirn) { ++ case NPHY_RXCAL_GAIN_INIT: ++ if (curr_pwr > thresh_pwr) { ++ gainctrl_dirn = NPHY_RXCAL_GAIN_DOWN; ++ prev_gaintbl_index = curr_gaintbl_index; ++ curr_gaintbl_index--; ++ } else { ++ gainctrl_dirn = NPHY_RXCAL_GAIN_UP; ++ prev_gaintbl_index = curr_gaintbl_index; ++ curr_gaintbl_index++; ++ } ++ break; ++ ++ case NPHY_RXCAL_GAIN_UP: ++ if (curr_pwr > thresh_pwr) { ++ gainctrl_done = true; ++ optim_pwr = prev_pwr; ++ optim_gaintbl_index = prev_gaintbl_index; ++ } else { ++ prev_gaintbl_index = curr_gaintbl_index; ++ curr_gaintbl_index++; ++ } ++ break; ++ ++ case NPHY_RXCAL_GAIN_DOWN: ++ if (curr_pwr > thresh_pwr) { ++ prev_gaintbl_index = curr_gaintbl_index; ++ curr_gaintbl_index--; ++ } else { ++ gainctrl_done = true; ++ optim_pwr = curr_pwr; ++ optim_gaintbl_index = curr_gaintbl_index; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ if ((curr_gaintbl_index < 0) || ++ (curr_gaintbl_index > NPHY_IPA_RXCAL_MAXGAININDEX)) { ++ gainctrl_done = true; ++ optim_pwr = curr_pwr; ++ optim_gaintbl_index = prev_gaintbl_index; ++ } else { ++ prev_pwr = curr_pwr; ++ } ++ ++ wlc_phy_stopplayback_nphy(pi); ++ } while (!gainctrl_done); ++ ++ hpvga = nphy_rxcal_gaintbl[optim_gaintbl_index].hpvga; ++ lpf_biq1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq1; ++ lpf_biq0 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq0; ++ lna2 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna2; ++ lna1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna1; ++ txpwrindex = nphy_rxcal_gaintbl[optim_gaintbl_index].txpwrindex; ++ ++ actual_log2_pwr = wlc_phy_nbits(optim_pwr); ++ delta_pwr = desired_log2_pwr - actual_log2_pwr; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ fine_gain_idx = (int)lpf_biq1 + delta_pwr; ++ ++ if (fine_gain_idx + (int)lpf_biq0 > 10) ++ lpf_biq1 = 10 - lpf_biq0; ++ else ++ lpf_biq1 = (u16) max(fine_gain_idx, 0); ++ ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_rxgain, ++ ((lpf_biq1 << 12) | ++ (lpf_biq0 << 8) | ++ (mix_tia_gain << 4) | ++ (lna2 << 2) | lna1), 0x3, ++ 0); ++ } else { ++ hpvga = (u16) max(min(((int)hpvga) + delta_pwr, 10), 0); ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), ++ ((hpvga << 12) | ++ (lpf_biq1 << 10) | ++ (lpf_biq0 << 8) | ++ (mix_tia_gain << 4) | ++ (lna2 << 2) | ++ lna1), 0x3, 0); ++ } ++ ++ if (rxgain != NULL) { ++ *rxgain++ = lna1; ++ *rxgain++ = lna2; ++ *rxgain++ = mix_tia_gain; ++ *rxgain++ = lpf_biq0; ++ *rxgain++ = lpf_biq1; ++ *rxgain = hpvga; ++ } ++ ++ wlc_phy_rx_iq_coeffs_nphy(pi, 1, &save_comp); ++} ++ ++static void ++wlc_phy_rxcal_gainctrl_nphy(struct brcms_phy *pi, u8 rx_core, u16 *rxgain, ++ u8 cal_type) ++{ ++ wlc_phy_rxcal_gainctrl_nphy_rev5(pi, rx_core, rxgain, cal_type); ++} ++ ++static u8 ++wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type) ++{ ++ u32 target_bws[2] = { 9500, 21000 }; ++ u32 ref_tones[2] = { 3000, 6000 }; ++ u32 target_bw, ref_tone; ++ ++ u32 target_pwr_ratios[2] = { 28606, 18468 }; ++ u32 target_pwr_ratio, pwr_ratio, last_pwr_ratio = 0; ++ ++ u16 start_rccal_ovr_val = 128; ++ u16 txlpf_rccal_lpc_ovr_val = 128; ++ u16 rxlpf_rccal_hpc_ovr_val = 159; ++ ++ u16 orig_txlpf_rccal_lpc_ovr_val; ++ u16 orig_rxlpf_rccal_hpc_ovr_val; ++ u16 radio_addr_offset_rx; ++ u16 radio_addr_offset_tx; ++ u16 orig_dcBypass; ++ u16 orig_RxStrnFilt40Num[6]; ++ u16 orig_RxStrnFilt40Den[4]; ++ u16 orig_rfctrloverride[2]; ++ u16 orig_rfctrlauxreg[2]; ++ u16 orig_rfctrlrssiothers; ++ u16 tx_lpf_bw = 4; ++ ++ u16 rx_lpf_bw, rx_lpf_bws[2] = { 2, 4 }; ++ u16 lpf_hpc = 7, hpvga_hpc = 7; ++ ++ s8 rccal_stepsize; ++ u16 rccal_val, last_rccal_val = 0, best_rccal_val = 0; ++ u32 ref_iq_vals = 0, target_iq_vals = 0; ++ u16 num_samps, log_num_samps = 10; ++ struct phy_iq_est est[PHY_CORE_MAX]; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ return 0; ++ ++ num_samps = (1 << log_num_samps); ++ ++ if (CHSPEC_IS40(pi->radio_chanspec)) { ++ target_bw = target_bws[1]; ++ target_pwr_ratio = target_pwr_ratios[1]; ++ ref_tone = ref_tones[1]; ++ rx_lpf_bw = rx_lpf_bws[1]; ++ } else { ++ target_bw = target_bws[0]; ++ target_pwr_ratio = target_pwr_ratios[0]; ++ ref_tone = ref_tones[0]; ++ rx_lpf_bw = rx_lpf_bws[0]; ++ } ++ ++ if (core_idx == 0) { ++ radio_addr_offset_rx = RADIO_2056_RX0; ++ radio_addr_offset_tx = ++ (loopback_type == 0) ? RADIO_2056_TX0 : RADIO_2056_TX1; ++ } else { ++ radio_addr_offset_rx = RADIO_2056_RX1; ++ radio_addr_offset_tx = ++ (loopback_type == 0) ? RADIO_2056_TX1 : RADIO_2056_TX0; ++ } ++ ++ orig_txlpf_rccal_lpc_ovr_val = ++ read_radio_reg(pi, ++ (RADIO_2056_TX_TXLPF_RCCAL | ++ radio_addr_offset_tx)); ++ orig_rxlpf_rccal_hpc_ovr_val = ++ read_radio_reg(pi, ++ (RADIO_2056_RX_RXLPF_RCCAL_HPC | ++ radio_addr_offset_rx)); ++ ++ orig_dcBypass = ((read_phy_reg(pi, 0x48) >> 8) & 1); ++ ++ orig_RxStrnFilt40Num[0] = read_phy_reg(pi, 0x267); ++ orig_RxStrnFilt40Num[1] = read_phy_reg(pi, 0x268); ++ orig_RxStrnFilt40Num[2] = read_phy_reg(pi, 0x269); ++ orig_RxStrnFilt40Den[0] = read_phy_reg(pi, 0x26a); ++ orig_RxStrnFilt40Den[1] = read_phy_reg(pi, 0x26b); ++ orig_RxStrnFilt40Num[3] = read_phy_reg(pi, 0x26c); ++ orig_RxStrnFilt40Num[4] = read_phy_reg(pi, 0x26d); ++ orig_RxStrnFilt40Num[5] = read_phy_reg(pi, 0x26e); ++ orig_RxStrnFilt40Den[2] = read_phy_reg(pi, 0x26f); ++ orig_RxStrnFilt40Den[3] = read_phy_reg(pi, 0x270); ++ ++ orig_rfctrloverride[0] = read_phy_reg(pi, 0xe7); ++ orig_rfctrloverride[1] = read_phy_reg(pi, 0xec); ++ orig_rfctrlauxreg[0] = read_phy_reg(pi, 0xf8); ++ orig_rfctrlauxreg[1] = read_phy_reg(pi, 0xfa); ++ orig_rfctrlrssiothers = read_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d); ++ ++ write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx), ++ txlpf_rccal_lpc_ovr_val); ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx), ++ rxlpf_rccal_hpc_ovr_val); ++ ++ mod_phy_reg(pi, 0x48, (0x1 << 8), (0x1 << 8)); ++ ++ write_phy_reg(pi, 0x267, 0x02d4); ++ write_phy_reg(pi, 0x268, 0x0000); ++ write_phy_reg(pi, 0x269, 0x0000); ++ write_phy_reg(pi, 0x26a, 0x0000); ++ write_phy_reg(pi, 0x26b, 0x0000); ++ write_phy_reg(pi, 0x26c, 0x02d4); ++ write_phy_reg(pi, 0x26d, 0x0000); ++ write_phy_reg(pi, 0x26e, 0x0000); ++ write_phy_reg(pi, 0x26f, 0x0000); ++ write_phy_reg(pi, 0x270, 0x0000); ++ ++ or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 8)); ++ or_phy_reg(pi, (core_idx == 0) ? 0xec : 0xe7, (0x1 << 15)); ++ or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 9)); ++ or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 10)); ++ ++ mod_phy_reg(pi, (core_idx == 0) ? 0xfa : 0xf8, ++ (0x7 << 10), (tx_lpf_bw << 10)); ++ mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa, ++ (0x7 << 0), (hpvga_hpc << 0)); ++ mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa, ++ (0x7 << 4), (lpf_hpc << 4)); ++ mod_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d, ++ (0x7 << 8), (rx_lpf_bw << 8)); ++ ++ rccal_stepsize = 16; ++ rccal_val = start_rccal_ovr_val + rccal_stepsize; ++ ++ while (rccal_stepsize >= 0) { ++ write_radio_reg(pi, ++ (RADIO_2056_RX_RXLPF_RCCAL_LPC | ++ radio_addr_offset_rx), rccal_val); ++ ++ if (rccal_stepsize == 16) { ++ ++ wlc_phy_tx_tone_nphy(pi, ref_tone, NPHY_RXCAL_TONEAMP, ++ 0, 1, false); ++ udelay(2); ++ ++ wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0); ++ ++ if (core_idx == 0) ++ ref_iq_vals = ++ max_t(u32, (est[0].i_pwr + ++ est[0].q_pwr) >> ++ (log_num_samps + 1), ++ 1); ++ else ++ ref_iq_vals = ++ max_t(u32, (est[1].i_pwr + ++ est[1].q_pwr) >> ++ (log_num_samps + 1), ++ 1); ++ ++ wlc_phy_tx_tone_nphy(pi, target_bw, NPHY_RXCAL_TONEAMP, ++ 0, 1, false); ++ udelay(2); ++ } ++ ++ wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0); ++ ++ if (core_idx == 0) ++ target_iq_vals = (est[0].i_pwr + est[0].q_pwr) >> ++ (log_num_samps + 1); ++ else ++ target_iq_vals = ++ (est[1].i_pwr + ++ est[1].q_pwr) >> (log_num_samps + 1); ++ ++ pwr_ratio = (uint) ((target_iq_vals << 16) / ref_iq_vals); ++ ++ if (rccal_stepsize == 0) ++ rccal_stepsize--; ++ else if (rccal_stepsize == 1) { ++ last_rccal_val = rccal_val; ++ rccal_val += (pwr_ratio > target_pwr_ratio) ? 1 : -1; ++ last_pwr_ratio = pwr_ratio; ++ rccal_stepsize--; ++ } else { ++ rccal_stepsize = (rccal_stepsize >> 1); ++ rccal_val += ((pwr_ratio > target_pwr_ratio) ? ++ rccal_stepsize : (-rccal_stepsize)); ++ } ++ ++ if (rccal_stepsize == -1) { ++ best_rccal_val = ++ (abs((int)last_pwr_ratio - ++ (int)target_pwr_ratio) < ++ abs((int)pwr_ratio - ++ (int)target_pwr_ratio)) ? last_rccal_val : ++ rccal_val; ++ ++ if (CHSPEC_IS40(pi->radio_chanspec)) { ++ if ((best_rccal_val > 140) ++ || (best_rccal_val < 135)) ++ best_rccal_val = 138; ++ } else { ++ if ((best_rccal_val > 142) ++ || (best_rccal_val < 137)) ++ best_rccal_val = 140; ++ } ++ ++ write_radio_reg(pi, ++ (RADIO_2056_RX_RXLPF_RCCAL_LPC | ++ radio_addr_offset_rx), best_rccal_val); ++ } ++ } ++ ++ wlc_phy_stopplayback_nphy(pi); ++ ++ write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx), ++ orig_txlpf_rccal_lpc_ovr_val); ++ write_radio_reg(pi, ++ (RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx), ++ orig_rxlpf_rccal_hpc_ovr_val); ++ ++ mod_phy_reg(pi, 0x48, (0x1 << 8), (orig_dcBypass << 8)); ++ ++ write_phy_reg(pi, 0x267, orig_RxStrnFilt40Num[0]); ++ write_phy_reg(pi, 0x268, orig_RxStrnFilt40Num[1]); ++ write_phy_reg(pi, 0x269, orig_RxStrnFilt40Num[2]); ++ write_phy_reg(pi, 0x26a, orig_RxStrnFilt40Den[0]); ++ write_phy_reg(pi, 0x26b, orig_RxStrnFilt40Den[1]); ++ write_phy_reg(pi, 0x26c, orig_RxStrnFilt40Num[3]); ++ write_phy_reg(pi, 0x26d, orig_RxStrnFilt40Num[4]); ++ write_phy_reg(pi, 0x26e, orig_RxStrnFilt40Num[5]); ++ write_phy_reg(pi, 0x26f, orig_RxStrnFilt40Den[2]); ++ write_phy_reg(pi, 0x270, orig_RxStrnFilt40Den[3]); ++ ++ write_phy_reg(pi, 0xe7, orig_rfctrloverride[0]); ++ write_phy_reg(pi, 0xec, orig_rfctrloverride[1]); ++ write_phy_reg(pi, 0xf8, orig_rfctrlauxreg[0]); ++ write_phy_reg(pi, 0xfa, orig_rfctrlauxreg[1]); ++ write_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d, orig_rfctrlrssiothers); ++ ++ pi->nphy_anarxlpf_adjusted = false; ++ ++ return best_rccal_val - 0x80; ++} ++ ++#define WAIT_FOR_SCOPE 4000 ++static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi, ++ struct nphy_txgains target_gain, ++ u8 cal_type, bool debug) ++{ ++ u16 orig_BBConfig; ++ u8 core_no, rx_core; ++ u8 best_rccal[2]; ++ u16 gain_save[2]; ++ u16 cal_gain[2]; ++ struct nphy_iqcal_params cal_params[2]; ++ u8 rxcore_state; ++ s8 rxlpf_rccal_hpc, txlpf_rccal_lpc; ++ s8 txlpf_idac; ++ bool phyhang_avoid_state = false; ++ bool skip_rxiqcal = false; ++ ++ orig_BBConfig = read_phy_reg(pi, 0x01); ++ mod_phy_reg(pi, 0x01, (0x1 << 15), 0); ++ ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 4)) { ++ phyhang_avoid_state = pi->phyhang_avoid; ++ pi->phyhang_avoid = false; ++ } ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save); ++ ++ for (core_no = 0; core_no <= 1; core_no++) { ++ wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain, ++ &cal_params[core_no]); ++ cal_gain[core_no] = cal_params[core_no].cal_gain; ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain); ++ ++ rxcore_state = wlc_phy_rxcore_getstate_nphy( ++ (struct brcms_phy_pub *) pi); ++ ++ for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) { ++ ++ skip_rxiqcal = ++ ((rxcore_state & (1 << rx_core)) == 0) ? true : false; ++ ++ wlc_phy_rxcal_physetup_nphy(pi, rx_core); ++ ++ wlc_phy_rxcal_radio_setup_nphy(pi, rx_core); ++ ++ if ((!skip_rxiqcal) && ((cal_type == 0) || (cal_type == 2))) { ++ ++ wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL, 0); ++ ++ wlc_phy_tx_tone_nphy(pi, ++ (CHSPEC_IS40( ++ pi->radio_chanspec)) ? ++ NPHY_RXCAL_TONEFREQ_40MHz : ++ NPHY_RXCAL_TONEFREQ_20MHz, ++ NPHY_RXCAL_TONEAMP, 0, cal_type, ++ false); ++ ++ if (debug) ++ mdelay(WAIT_FOR_SCOPE); ++ ++ wlc_phy_calc_rx_iq_comp_nphy(pi, rx_core + 1); ++ wlc_phy_stopplayback_nphy(pi); ++ } ++ ++ if (((cal_type == 1) || (cal_type == 2)) ++ && NREV_LT(pi->pubpi.phy_rev, 7)) { ++ ++ if (rx_core == PHY_CORE_1) { ++ ++ if (rxcore_state == 1) ++ wlc_phy_rxcore_setstate_nphy( ++ (struct brcms_phy_pub *) pi, 3); ++ ++ wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL, ++ 1); ++ ++ best_rccal[rx_core] = ++ wlc_phy_rc_sweep_nphy(pi, rx_core, 1); ++ pi->nphy_rccal_value = best_rccal[rx_core]; ++ ++ if (rxcore_state == 1) ++ wlc_phy_rxcore_setstate_nphy( ++ (struct brcms_phy_pub *) pi, ++ rxcore_state); ++ } ++ } ++ ++ wlc_phy_rxcal_radio_cleanup_nphy(pi, rx_core); ++ ++ wlc_phy_rxcal_phycleanup_nphy(pi, rx_core); ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); ++ } ++ ++ if ((cal_type == 1) || (cal_type == 2)) { ++ ++ best_rccal[0] = best_rccal[1]; ++ write_radio_reg(pi, ++ (RADIO_2056_RX_RXLPF_RCCAL_LPC | ++ RADIO_2056_RX0), (best_rccal[0] | 0x80)); ++ ++ for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) { ++ rxlpf_rccal_hpc = ++ (((int)best_rccal[rx_core] - 12) >> 1) + 10; ++ txlpf_rccal_lpc = ((int)best_rccal[rx_core] - 12) + 10; ++ ++ if (PHY_IPA(pi)) { ++ txlpf_rccal_lpc += ++ (pi->bw == WL_CHANSPEC_BW_40) ? 24 : 12; ++ txlpf_idac = (pi->bw == WL_CHANSPEC_BW_40) ? ++ 0x0e : 0x13; ++ WRITE_RADIO_REG2(pi, RADIO_2056, TX, rx_core, ++ TXLPF_IDAC_4, txlpf_idac); ++ } ++ ++ rxlpf_rccal_hpc = max(min_t(u8, rxlpf_rccal_hpc, 31), ++ 0); ++ txlpf_rccal_lpc = max(min_t(u8, txlpf_rccal_lpc, 31), ++ 0); ++ ++ write_radio_reg(pi, (RADIO_2056_RX_RXLPF_RCCAL_HPC | ++ ((rx_core == ++ PHY_CORE_0) ? RADIO_2056_RX0 : ++ RADIO_2056_RX1)), ++ (rxlpf_rccal_hpc | 0x80)); ++ ++ write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | ++ ((rx_core == ++ PHY_CORE_0) ? RADIO_2056_TX0 : ++ RADIO_2056_TX1)), ++ (txlpf_rccal_lpc | 0x80)); ++ } ++ } ++ ++ write_phy_reg(pi, 0x01, orig_BBConfig); ++ ++ wlc_phy_resetcca_nphy(pi); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ wlc_phy_rfctrl_override_1tomany_nphy( ++ pi, ++ NPHY_REV7_RfctrlOverride_cmd_rxgain, ++ 0, 0x3, 1); ++ else ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1); ++ ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, ++ gain_save); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 4)) ++ pi->phyhang_avoid = phyhang_avoid_state; ++ ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ ++ return 0; ++} ++ ++static int ++wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi, ++ struct nphy_txgains target_gain, bool debug) ++{ ++ struct phy_iq_est est[PHY_CORE_MAX]; ++ u8 core_num, rx_core, tx_core; ++ u16 lna_vals[] = { 0x3, 0x3, 0x1 }; ++ u16 hpf1_vals[] = { 0x7, 0x2, 0x0 }; ++ u16 hpf2_vals[] = { 0x2, 0x0, 0x0 }; ++ s16 curr_hpf1, curr_hpf2, curr_hpf, curr_lna; ++ s16 desired_log2_pwr, actual_log2_pwr, hpf_change; ++ u16 orig_RfseqCoreActv, orig_AfectrlCore, orig_AfectrlOverride; ++ u16 orig_RfctrlIntcRx, orig_RfctrlIntcTx; ++ u16 num_samps; ++ u32 i_pwr, q_pwr, tot_pwr[3]; ++ u8 gain_pass, use_hpf_num; ++ u16 mask, val1, val2; ++ u16 core_no; ++ u16 gain_save[2]; ++ u16 cal_gain[2]; ++ struct nphy_iqcal_params cal_params[2]; ++ u8 phy_bw; ++ int bcmerror = 0; ++ bool first_playtone = true; ++ ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2)) ++ wlc_phy_reapply_txcal_coeffs_nphy(pi); ++ ++ wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save); ++ ++ for (core_no = 0; core_no <= 1; core_no++) { ++ wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain, ++ &cal_params[core_no]); ++ cal_gain[core_no] = cal_params[core_no].cal_gain; ++ } ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain); ++ ++ num_samps = 1024; ++ desired_log2_pwr = 13; ++ ++ for (core_num = 0; core_num < 2; core_num++) { ++ ++ rx_core = core_num; ++ tx_core = 1 - core_num; ++ ++ orig_RfseqCoreActv = read_phy_reg(pi, 0xa2); ++ orig_AfectrlCore = read_phy_reg(pi, (rx_core == PHY_CORE_0) ? ++ 0xa6 : 0xa7); ++ orig_AfectrlOverride = read_phy_reg(pi, 0xa5); ++ orig_RfctrlIntcRx = read_phy_reg(pi, (rx_core == PHY_CORE_0) ? ++ 0x91 : 0x92); ++ orig_RfctrlIntcTx = read_phy_reg(pi, (tx_core == PHY_CORE_0) ? ++ 0x91 : 0x92); ++ ++ mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12); ++ mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0); ++ ++ or_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7), ++ ((0x1 << 1) | (0x1 << 2))); ++ or_phy_reg(pi, 0xa5, ((0x1 << 1) | (0x1 << 2))); ++ ++ if (((pi->nphy_rxcalparams) & 0xff000000)) ++ write_phy_reg(pi, ++ (rx_core == PHY_CORE_0) ? 0x91 : 0x92, ++ (CHSPEC_IS5G(pi->radio_chanspec) ? ++ 0x140 : 0x110)); ++ else ++ write_phy_reg(pi, ++ (rx_core == PHY_CORE_0) ? 0x91 : 0x92, ++ (CHSPEC_IS5G(pi->radio_chanspec) ? ++ 0x180 : 0x120)); ++ ++ write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 : 0x92, ++ (CHSPEC_IS5G(pi->radio_chanspec) ? 0x148 : ++ 0x114)); ++ ++ mask = RADIO_2055_COUPLE_RX_MASK | RADIO_2055_COUPLE_TX_MASK; ++ if (rx_core == PHY_CORE_0) { ++ val1 = RADIO_2055_COUPLE_RX_MASK; ++ val2 = RADIO_2055_COUPLE_TX_MASK; ++ } else { ++ val1 = RADIO_2055_COUPLE_TX_MASK; ++ val2 = RADIO_2055_COUPLE_RX_MASK; ++ } ++ ++ if ((pi->nphy_rxcalparams & 0x10000)) { ++ mod_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, mask, ++ val1); ++ mod_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, mask, ++ val2); ++ } ++ ++ for (gain_pass = 0; gain_pass < 4; gain_pass++) { ++ ++ if (debug) ++ mdelay(WAIT_FOR_SCOPE); ++ ++ if (gain_pass < 3) { ++ curr_lna = lna_vals[gain_pass]; ++ curr_hpf1 = hpf1_vals[gain_pass]; ++ curr_hpf2 = hpf2_vals[gain_pass]; ++ } else { ++ ++ if (tot_pwr[1] > 10000) { ++ curr_lna = lna_vals[2]; ++ curr_hpf1 = hpf1_vals[2]; ++ curr_hpf2 = hpf2_vals[2]; ++ use_hpf_num = 1; ++ curr_hpf = curr_hpf1; ++ actual_log2_pwr = ++ wlc_phy_nbits(tot_pwr[2]); ++ } else { ++ if (tot_pwr[0] > 10000) { ++ curr_lna = lna_vals[1]; ++ curr_hpf1 = hpf1_vals[1]; ++ curr_hpf2 = hpf2_vals[1]; ++ use_hpf_num = 1; ++ curr_hpf = curr_hpf1; ++ actual_log2_pwr = ++ wlc_phy_nbits( ++ tot_pwr[1]); ++ } else { ++ curr_lna = lna_vals[0]; ++ curr_hpf1 = hpf1_vals[0]; ++ curr_hpf2 = hpf2_vals[0]; ++ use_hpf_num = 2; ++ curr_hpf = curr_hpf2; ++ actual_log2_pwr = ++ wlc_phy_nbits( ++ tot_pwr[0]); ++ } ++ } ++ ++ hpf_change = desired_log2_pwr - actual_log2_pwr; ++ curr_hpf += hpf_change; ++ curr_hpf = max(min_t(u16, curr_hpf, 10), 0); ++ if (use_hpf_num == 1) ++ curr_hpf1 = curr_hpf; ++ else ++ curr_hpf2 = curr_hpf; ++ } ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10), ++ ((curr_hpf2 << 8) | ++ (curr_hpf1 << 4) | ++ (curr_lna << 2)), 0x3, 0); ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); ++ ++ wlc_phy_stopplayback_nphy(pi); ++ ++ if (first_playtone) { ++ bcmerror = wlc_phy_tx_tone_nphy(pi, 4000, ++ (u16) (pi->nphy_rxcalparams & ++ 0xffff), 0, 0, true); ++ first_playtone = false; ++ } else { ++ phy_bw = (CHSPEC_IS40(pi->radio_chanspec)) ? ++ 40 : 20; ++ wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff, ++ 0, 0, 0, true); ++ } ++ ++ if (bcmerror == 0) { ++ if (gain_pass < 3) { ++ ++ wlc_phy_rx_iq_est_nphy(pi, est, ++ num_samps, 32, ++ 0); ++ i_pwr = (est[rx_core].i_pwr + ++ num_samps / 2) / num_samps; ++ q_pwr = (est[rx_core].q_pwr + ++ num_samps / 2) / num_samps; ++ tot_pwr[gain_pass] = i_pwr + q_pwr; ++ } else { ++ ++ wlc_phy_calc_rx_iq_comp_nphy(pi, ++ (1 << ++ rx_core)); ++ } ++ ++ wlc_phy_stopplayback_nphy(pi); ++ } ++ ++ if (bcmerror != 0) ++ break; ++ } ++ ++ and_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, ~mask); ++ and_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, ~mask); ++ ++ write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 : ++ 0x92, orig_RfctrlIntcTx); ++ write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x91 : ++ 0x92, orig_RfctrlIntcRx); ++ write_phy_reg(pi, 0xa5, orig_AfectrlOverride); ++ write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : ++ 0xa7, orig_AfectrlCore); ++ write_phy_reg(pi, 0xa2, orig_RfseqCoreActv); ++ ++ if (bcmerror != 0) ++ break; ++ } ++ ++ wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10), 0, 0x3, 1); ++ wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX); ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, ++ gain_save); ++ ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ ++ return bcmerror; ++} ++ ++int ++wlc_phy_cal_rxiq_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, ++ u8 cal_type, bool debug) ++{ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ cal_type = 0; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ return wlc_phy_cal_rxiq_nphy_rev3(pi, target_gain, cal_type, ++ debug); ++ else ++ return wlc_phy_cal_rxiq_nphy_rev2(pi, target_gain, debug); ++} ++ ++void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi) ++{ ++ uint core; ++ u32 txgain; ++ u16 rad_gain, dac_gain, bbmult, m1m2; ++ u8 txpi[2], chan_freq_range; ++ s32 rfpwr_offset; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ if (pi->sh->sromrev < 4) { ++ txpi[0] = txpi[1] = 72; ++ } else { ++ ++ chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0); ++ switch (chan_freq_range) { ++ case WL_CHAN_FREQ_RANGE_2G: ++ txpi[0] = pi->nphy_txpid2g[0]; ++ txpi[1] = pi->nphy_txpid2g[1]; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GL: ++ txpi[0] = pi->nphy_txpid5gl[0]; ++ txpi[1] = pi->nphy_txpid5gl[1]; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GM: ++ txpi[0] = pi->nphy_txpid5g[0]; ++ txpi[1] = pi->nphy_txpid5g[1]; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GH: ++ txpi[0] = pi->nphy_txpid5gh[0]; ++ txpi[1] = pi->nphy_txpid5gh[1]; ++ break; ++ default: ++ txpi[0] = txpi[1] = 91; ++ break; ++ } ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) ++ txpi[0] = txpi[1] = 30; ++ else if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ txpi[0] = txpi[1] = 40; ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 7)) { ++ ++ if ((txpi[0] < 40) || (txpi[0] > 100) || ++ (txpi[1] < 40) || (txpi[1] > 100)) ++ txpi[0] = txpi[1] = 91; ++ } ++ ++ pi->nphy_txpwrindex[PHY_CORE_0].index_internal = txpi[0]; ++ pi->nphy_txpwrindex[PHY_CORE_1].index_internal = txpi[1]; ++ pi->nphy_txpwrindex[PHY_CORE_0].index_internal_save = txpi[0]; ++ pi->nphy_txpwrindex[PHY_CORE_1].index_internal_save = txpi[1]; ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ uint phyrev = pi->pubpi.phy_rev; ++ ++ if (NREV_GE(phyrev, 3)) { ++ if (PHY_IPA(pi)) { ++ u32 *tx_gaintbl = ++ wlc_phy_get_ipa_gaintbl_nphy(pi); ++ txgain = tx_gaintbl[txpi[core]]; ++ } else { ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (NREV_IS(phyrev, 3)) { ++ txgain = ++ nphy_tpc_5GHz_txgain_rev3 ++ [txpi[core]]; ++ } else if (NREV_IS(phyrev, 4)) { ++ txgain = ( ++ pi->srom_fem5g.extpagain == ++ 3) ? ++ nphy_tpc_5GHz_txgain_HiPwrEPA ++ [txpi[core]] : ++ nphy_tpc_5GHz_txgain_rev4 ++ [txpi[core]]; ++ } else { ++ txgain = ++ nphy_tpc_5GHz_txgain_rev5 ++ [txpi[core]]; ++ } ++ } else { ++ if (NREV_GE(phyrev, 5) && ++ (pi->srom_fem2g.extpagain == 3)) { ++ txgain = ++ nphy_tpc_txgain_HiPwrEPA ++ [txpi[core]]; ++ } else { ++ txgain = nphy_tpc_txgain_rev3 ++ [txpi[core]]; ++ } ++ } ++ } ++ } else { ++ txgain = nphy_tpc_txgain[txpi[core]]; ++ } ++ ++ if (NREV_GE(phyrev, 3)) ++ rad_gain = (txgain >> 16) & ((1 << (32 - 16 + 1)) - 1); ++ else ++ rad_gain = (txgain >> 16) & ((1 << (28 - 16 + 1)) - 1); ++ ++ if (NREV_GE(phyrev, 7)) ++ dac_gain = (txgain >> 8) & ((1 << (10 - 8 + 1)) - 1); ++ else ++ dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1); ++ ++ bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1); ++ ++ if (NREV_GE(phyrev, 3)) ++ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f : ++ 0xa5), (0x1 << 8), (0x1 << 8)); ++ else ++ mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14)); ++ ++ write_phy_reg(pi, (core == PHY_CORE_0) ? 0xaa : 0xab, dac_gain); ++ ++ wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16, ++ &rad_gain); ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2); ++ m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00); ++ m1m2 |= ((core == PHY_CORE_0) ? (bbmult << 8) : (bbmult << 0)); ++ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2); ++ ++ if (PHY_IPA(pi)) { ++ wlc_phy_table_read_nphy(pi, ++ (core == ++ PHY_CORE_0 ? ++ NPHY_TBL_ID_CORE1TXPWRCTL : ++ NPHY_TBL_ID_CORE2TXPWRCTL), 1, ++ 576 + txpi[core], 32, ++ &rfpwr_offset); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1ff << 4), ++ ((s16) rfpwr_offset) << 4); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 2), (1) << 2); ++ ++ } ++ } ++ ++ and_phy_reg(pi, 0xbf, (u16) (~(0x1f << 0))); ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++static void ++wlc_phy_txpwr_nphy_srom_convert(u8 *srom_max, u16 *pwr_offset, ++ u8 tmp_max_pwr, u8 rate_start, ++ u8 rate_end) ++{ ++ u8 rate; ++ u8 word_num, nibble_num; ++ u8 tmp_nibble; ++ ++ for (rate = rate_start; rate <= rate_end; rate++) { ++ word_num = (rate - rate_start) >> 2; ++ nibble_num = (rate - rate_start) & 0x3; ++ tmp_nibble = (pwr_offset[word_num] >> 4 * nibble_num) & 0xf; ++ ++ srom_max[rate] = tmp_max_pwr - 2 * tmp_nibble; ++ } ++} ++ ++static void ++wlc_phy_txpwr_nphy_po_apply(u8 *srom_max, u8 pwr_offset, ++ u8 rate_start, u8 rate_end) ++{ ++ u8 rate; ++ ++ for (rate = rate_start; rate <= rate_end; rate++) ++ srom_max[rate] -= 2 * pwr_offset; ++} ++ ++void ++wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start, ++ u8 rate_mcs_end, u8 rate_ofdm_start) ++{ ++ u8 rate1, rate2; ++ ++ rate2 = rate_ofdm_start; ++ for (rate1 = rate_mcs_start; rate1 <= rate_mcs_end - 1; rate1++) { ++ power[rate1] = power[rate2]; ++ rate2 += (rate1 == rate_mcs_start) ? 2 : 1; ++ } ++ power[rate_mcs_end] = power[rate_mcs_end - 1]; ++} ++ ++void ++wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power, u8 rate_ofdm_start, ++ u8 rate_ofdm_end, u8 rate_mcs_start) ++{ ++ u8 rate1, rate2; ++ ++ for (rate1 = rate_ofdm_start, rate2 = rate_mcs_start; ++ rate1 <= rate_ofdm_end; rate1++, rate2++) { ++ power[rate1] = power[rate2]; ++ if (rate1 == rate_ofdm_start) ++ power[++rate1] = power[rate2]; ++ } ++} ++ ++void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi) ++{ ++ uint rate1, rate2, band_num; ++ u8 tmp_bw40po = 0, tmp_cddpo = 0, tmp_stbcpo = 0; ++ u8 tmp_max_pwr = 0; ++ u16 pwr_offsets1[2], *pwr_offsets2 = NULL; ++ u8 *tx_srom_max_rate = NULL; ++ ++ for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); ++ band_num++) { ++ switch (band_num) { ++ case 0: ++ ++ tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_2g, ++ pi->nphy_pwrctrl_info[1].max_pwr_2g); ++ ++ pwr_offsets1[0] = pi->cck2gpo; ++ wlc_phy_txpwr_nphy_srom_convert(pi->tx_srom_max_rate_2g, ++ pwr_offsets1, ++ tmp_max_pwr, ++ TXP_FIRST_CCK, ++ TXP_LAST_CCK); ++ ++ pwr_offsets1[0] = (u16) (pi->ofdm2gpo & 0xffff); ++ pwr_offsets1[1] = ++ (u16) (pi->ofdm2gpo >> 16) & 0xffff; ++ ++ pwr_offsets2 = pi->mcs2gpo; ++ ++ tmp_cddpo = pi->cdd2gpo; ++ tmp_stbcpo = pi->stbc2gpo; ++ tmp_bw40po = pi->bw402gpo; ++ ++ tx_srom_max_rate = pi->tx_srom_max_rate_2g; ++ break; ++ case 1: ++ ++ tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gm, ++ pi->nphy_pwrctrl_info[1].max_pwr_5gm); ++ ++ pwr_offsets1[0] = (u16) (pi->ofdm5gpo & 0xffff); ++ pwr_offsets1[1] = ++ (u16) (pi->ofdm5gpo >> 16) & 0xffff; ++ ++ pwr_offsets2 = pi->mcs5gpo; ++ ++ tmp_cddpo = pi->cdd5gpo; ++ tmp_stbcpo = pi->stbc5gpo; ++ tmp_bw40po = pi->bw405gpo; ++ ++ tx_srom_max_rate = pi->tx_srom_max_rate_5g_mid; ++ break; ++ case 2: ++ ++ tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gl, ++ pi->nphy_pwrctrl_info[1].max_pwr_5gl); ++ ++ pwr_offsets1[0] = (u16) (pi->ofdm5glpo & 0xffff); ++ pwr_offsets1[1] = ++ (u16) (pi->ofdm5glpo >> 16) & 0xffff; ++ ++ pwr_offsets2 = pi->mcs5glpo; ++ ++ tmp_cddpo = pi->cdd5glpo; ++ tmp_stbcpo = pi->stbc5glpo; ++ tmp_bw40po = pi->bw405glpo; ++ ++ tx_srom_max_rate = pi->tx_srom_max_rate_5g_low; ++ break; ++ case 3: ++ ++ tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gh, ++ pi->nphy_pwrctrl_info[1].max_pwr_5gh); ++ ++ pwr_offsets1[0] = (u16) (pi->ofdm5ghpo & 0xffff); ++ pwr_offsets1[1] = ++ (u16) (pi->ofdm5ghpo >> 16) & 0xffff; ++ ++ pwr_offsets2 = pi->mcs5ghpo; ++ ++ tmp_cddpo = pi->cdd5ghpo; ++ tmp_stbcpo = pi->stbc5ghpo; ++ tmp_bw40po = pi->bw405ghpo; ++ ++ tx_srom_max_rate = pi->tx_srom_max_rate_5g_hi; ++ break; ++ } ++ ++ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets1, ++ tmp_max_pwr, TXP_FIRST_OFDM, ++ TXP_LAST_OFDM); ++ ++ wlc_phy_ofdm_to_mcs_powers_nphy(tx_srom_max_rate, ++ TXP_FIRST_MCS_20_SISO, ++ TXP_LAST_MCS_20_SISO, ++ TXP_FIRST_OFDM); ++ ++ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets2, ++ tmp_max_pwr, ++ TXP_FIRST_MCS_20_CDD, ++ TXP_LAST_MCS_20_CDD); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo, ++ TXP_FIRST_MCS_20_CDD, ++ TXP_LAST_MCS_20_CDD); ++ ++ wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate, ++ TXP_FIRST_OFDM_20_CDD, ++ TXP_LAST_OFDM_20_CDD, ++ TXP_FIRST_MCS_20_CDD); ++ ++ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets2, ++ tmp_max_pwr, ++ TXP_FIRST_MCS_20_STBC, ++ TXP_LAST_MCS_20_STBC); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, ++ tmp_stbcpo, ++ TXP_FIRST_MCS_20_STBC, ++ TXP_LAST_MCS_20_STBC); ++ ++ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, ++ &pwr_offsets2[2], tmp_max_pwr, ++ TXP_FIRST_MCS_20_SDM, ++ TXP_LAST_MCS_20_SDM); ++ ++ if (NPHY_IS_SROM_REINTERPRET) { ++ ++ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, ++ &pwr_offsets2[4], ++ tmp_max_pwr, ++ TXP_FIRST_MCS_40_SISO, ++ TXP_LAST_MCS_40_SISO); ++ ++ wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate, ++ TXP_FIRST_OFDM_40_SISO, ++ TXP_LAST_OFDM_40_SISO, ++ TXP_FIRST_MCS_40_SISO); ++ ++ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, ++ &pwr_offsets2[4], ++ tmp_max_pwr, ++ TXP_FIRST_MCS_40_CDD, ++ TXP_LAST_MCS_40_CDD); ++ ++ wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo, ++ TXP_FIRST_MCS_40_CDD, ++ TXP_LAST_MCS_40_CDD); ++ ++ wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate, ++ TXP_FIRST_OFDM_40_CDD, ++ TXP_LAST_OFDM_40_CDD, ++ TXP_FIRST_MCS_40_CDD); ++ ++ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, ++ &pwr_offsets2[4], ++ tmp_max_pwr, ++ TXP_FIRST_MCS_40_STBC, ++ TXP_LAST_MCS_40_STBC); ++ ++ wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, ++ tmp_stbcpo, ++ TXP_FIRST_MCS_40_STBC, ++ TXP_LAST_MCS_40_STBC); ++ ++ wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, ++ &pwr_offsets2[6], ++ tmp_max_pwr, ++ TXP_FIRST_MCS_40_SDM, ++ TXP_LAST_MCS_40_SDM); ++ } else { ++ ++ for (rate1 = TXP_FIRST_OFDM_40_SISO, rate2 = ++ TXP_FIRST_OFDM; ++ rate1 <= TXP_LAST_MCS_40_SDM; ++ rate1++, rate2++) ++ tx_srom_max_rate[rate1] = ++ tx_srom_max_rate[rate2]; ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, ++ tmp_bw40po, ++ TXP_FIRST_OFDM_40_SISO, ++ TXP_LAST_MCS_40_SDM); ++ ++ tx_srom_max_rate[TXP_MCS_32] = ++ tx_srom_max_rate[TXP_FIRST_MCS_40_CDD]; ++ } ++ ++ return; ++} ++ ++void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi) ++{ ++ u8 tx_pwr_ctrl_state; ++ wlc_phy_txpwr_limit_to_tbl_nphy(pi); ++ wlc_phy_txpwrctrl_pwr_setup_nphy(pi); ++ ++ tx_pwr_ctrl_state = pi->nphy_txpwrctrl; ++ ++ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) { ++ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK); ++ (void)R_REG(&pi->regs->maccontrol); ++ udelay(1); ++ } ++ ++ wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state); ++ ++ if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) ++ wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0); ++} ++ ++static bool wlc_phy_txpwr_ison_nphy(struct brcms_phy *pi) ++{ ++ return read_phy_reg((pi), 0x1e7) & ((0x1 << 15) | ++ (0x1 << 14) | (0x1 << 13)); ++} ++ ++u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi) ++{ ++ u16 tmp; ++ u16 pwr_idx[2]; ++ ++ if (wlc_phy_txpwr_ison_nphy(pi)) { ++ pwr_idx[0] = wlc_phy_txpwr_idx_cur_get_nphy(pi, PHY_CORE_0); ++ pwr_idx[1] = wlc_phy_txpwr_idx_cur_get_nphy(pi, PHY_CORE_1); ++ ++ tmp = (pwr_idx[0] << 8) | pwr_idx[1]; ++ } else { ++ tmp = ((pi->nphy_txpwrindex[PHY_CORE_0].index_internal & 0xff) ++ << 8) | ++ (pi->nphy_txpwrindex[PHY_CORE_1].index_internal & 0xff); ++ } ++ ++ return tmp; ++} ++ ++void wlc_phy_txpwr_papd_cal_nphy(struct brcms_phy *pi) ++{ ++ if (PHY_IPA(pi) ++ && (pi->nphy_force_papd_cal ++ || (wlc_phy_txpwr_ison_nphy(pi) ++ && ++ (((u32) ++ abs(wlc_phy_txpwr_idx_cur_get_nphy(pi, 0) - ++ pi->nphy_papd_tx_gain_at_last_cal[0]) >= 4) ++ || ((u32) ++ abs(wlc_phy_txpwr_idx_cur_get_nphy(pi, 1) - ++ pi->nphy_papd_tx_gain_at_last_cal[1]) >= 4))))) ++ wlc_phy_a4(pi, true); ++} ++ ++void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type) ++{ ++ u16 mask = 0, val = 0, ishw = 0; ++ u8 ctr; ++ uint core; ++ u32 tbl_offset; ++ u32 tbl_len; ++ u16 regval[84]; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ switch (ctrl_type) { ++ case PHY_TPC_HW_OFF: ++ case PHY_TPC_HW_ON: ++ pi->nphy_txpwrctrl = ctrl_type; ++ break; ++ default: ++ break; ++ } ++ ++ if (ctrl_type == PHY_TPC_HW_OFF) { ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ ++ if (wlc_phy_txpwr_ison_nphy(pi)) { ++ for (core = 0; core < pi->pubpi.phy_corenum; ++ core++) ++ pi->nphy_txpwr_idx[core] = ++ wlc_phy_txpwr_idx_cur_get_nphy( ++ pi, ++ (u8) core); ++ } ++ ++ } ++ ++ tbl_len = 84; ++ tbl_offset = 64; ++ for (ctr = 0; ctr < tbl_len; ctr++) ++ regval[ctr] = 0; ++ wlc_phy_table_write_nphy(pi, 26, tbl_len, tbl_offset, 16, ++ regval); ++ wlc_phy_table_write_nphy(pi, 27, tbl_len, tbl_offset, 16, ++ regval); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ and_phy_reg(pi, 0x1e7, ++ (u16) (~((0x1 << 15) | ++ (0x1 << 14) | (0x1 << 13)))); ++ else ++ and_phy_reg(pi, 0x1e7, ++ (u16) (~((0x1 << 14) | (0x1 << 13)))); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ or_phy_reg(pi, 0x8f, (0x1 << 8)); ++ or_phy_reg(pi, 0xa5, (0x1 << 8)); ++ } else { ++ or_phy_reg(pi, 0xa5, (0x1 << 14)); ++ } ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 2)) ++ mod_phy_reg(pi, 0xdc, 0x00ff, 0x53); ++ else if (NREV_LT(pi->pubpi.phy_rev, 2)) ++ mod_phy_reg(pi, 0xdc, 0x00ff, 0x5a); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2) && ++ pi->bw == WL_CHANSPEC_BW_40) ++ wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR, ++ MHF1_IQSWAP_WAR, BRCM_BAND_ALL); ++ ++ } else { ++ ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64, ++ 8, pi->adj_pwr_tbl_nphy); ++ wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64, ++ 8, pi->adj_pwr_tbl_nphy); ++ ++ ishw = (ctrl_type == PHY_TPC_HW_ON) ? 0x1 : 0x0; ++ mask = (0x1 << 14) | (0x1 << 13); ++ val = (ishw << 14) | (ishw << 13); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ mask |= (0x1 << 15); ++ val |= (ishw << 15); ++ } ++ ++ mod_phy_reg(pi, 0x1e7, mask, val); ++ ++ if (CHSPEC_IS5G(pi->radio_chanspec)) { ++ if (NREV_GE(pi->pubpi.phy_rev, 7)) { ++ mod_phy_reg(pi, 0x1e7, (0x7f << 0), 0x32); ++ mod_phy_reg(pi, 0x222, (0xff << 0), 0x32); ++ } else { ++ mod_phy_reg(pi, 0x1e7, (0x7f << 0), 0x64); ++ if (NREV_GT(pi->pubpi.phy_rev, 1)) ++ mod_phy_reg(pi, 0x222, ++ (0xff << 0), 0x64); ++ } ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ if ((pi->nphy_txpwr_idx[0] != 128) ++ && (pi->nphy_txpwr_idx[1] != 128)) ++ wlc_phy_txpwr_idx_cur_set_nphy(pi, ++ pi-> ++ nphy_txpwr_idx ++ [0], ++ pi-> ++ nphy_txpwr_idx ++ [1]); ++ } ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ and_phy_reg(pi, 0x8f, ~(0x1 << 8)); ++ and_phy_reg(pi, 0xa5, ~(0x1 << 8)); ++ } else { ++ and_phy_reg(pi, 0xa5, ~(0x1 << 14)); ++ } ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 2)) ++ mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b); ++ else if (NREV_LT(pi->pubpi.phy_rev, 2)) ++ mod_phy_reg(pi, 0xdc, 0x00ff, 0x40); ++ ++ if (NREV_LT(pi->pubpi.phy_rev, 2) && ++ pi->bw == WL_CHANSPEC_BW_40) ++ wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR, ++ 0x0, BRCM_BAND_ALL); ++ ++ if (PHY_IPA(pi)) { ++ mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 2), (0) << 2); ++ ++ mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 2), (0) << 2); ++ ++ } ++ ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++void ++wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex, ++ bool restore_cals) ++{ ++ u8 core, txpwrctl_tbl; ++ u16 tx_ind0, iq_ind0, lo_ind0; ++ u16 m1m2; ++ u32 txgain; ++ u16 rad_gain, dac_gain; ++ u8 bbmult; ++ u32 iqcomp; ++ u16 iqcomp_a, iqcomp_b; ++ u32 locomp; ++ u16 tmpval; ++ u8 tx_pwr_ctrl_state; ++ s32 rfpwr_offset; ++ u16 regval[2]; ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ ++ tx_ind0 = 192; ++ iq_ind0 = 320; ++ lo_ind0 = 448; ++ ++ for (core = 0; core < pi->pubpi.phy_corenum; core++) { ++ ++ if ((core_mask & (1 << core)) == 0) ++ continue; ++ ++ txpwrctl_tbl = (core == PHY_CORE_0) ? 26 : 27; ++ ++ if (txpwrindex < 0) { ++ if (pi->nphy_txpwrindex[core].index < 0) ++ continue; ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ mod_phy_reg(pi, 0x8f, ++ (0x1 << 8), ++ pi->nphy_txpwrindex[core]. ++ AfectrlOverride); ++ mod_phy_reg(pi, 0xa5, (0x1 << 8), ++ pi->nphy_txpwrindex[core]. ++ AfectrlOverride); ++ } else { ++ mod_phy_reg(pi, 0xa5, ++ (0x1 << 14), ++ pi->nphy_txpwrindex[core]. ++ AfectrlOverride); ++ } ++ ++ write_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0xaa : 0xab, ++ pi->nphy_txpwrindex[core].AfeCtrlDacGain); ++ ++ wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16, ++ &pi->nphy_txpwrindex[core]. ++ rad_gain); ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2); ++ m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00); ++ m1m2 |= ((core == PHY_CORE_0) ? ++ (pi->nphy_txpwrindex[core].bbmult << 8) : ++ (pi->nphy_txpwrindex[core].bbmult << 0)); ++ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2); ++ ++ if (restore_cals) { ++ wlc_phy_table_write_nphy( ++ pi, 15, 2, (80 + 2 * core), 16, ++ &pi->nphy_txpwrindex[core].iqcomp_a); ++ wlc_phy_table_write_nphy( ++ pi, 15, 1, (85 + core), 16, ++ &pi->nphy_txpwrindex[core].locomp); ++ wlc_phy_table_write_nphy( ++ pi, 15, 1, (93 + core), 16, ++ &pi->nphy_txpwrindex[core].locomp); ++ } ++ ++ wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl); ++ ++ pi->nphy_txpwrindex[core].index_internal = ++ pi->nphy_txpwrindex[core].index_internal_save; ++ } else { ++ ++ if (pi->nphy_txpwrindex[core].index < 0) { ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) { ++ mod_phy_reg(pi, 0x8f, ++ (0x1 << 8), ++ pi->nphy_txpwrindex[core]. ++ AfectrlOverride); ++ mod_phy_reg(pi, 0xa5, (0x1 << 8), ++ pi->nphy_txpwrindex[core]. ++ AfectrlOverride); ++ } else { ++ pi->nphy_txpwrindex[core]. ++ AfectrlOverride = ++ read_phy_reg(pi, 0xa5); ++ } ++ ++ pi->nphy_txpwrindex[core].AfeCtrlDacGain = ++ read_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0xaa : 0xab); ++ ++ wlc_phy_table_read_nphy(pi, 7, 1, ++ (0x110 + core), 16, ++ &pi-> ++ nphy_txpwrindex[core]. ++ rad_gain); ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, ++ &tmpval); ++ tmpval >>= ((core == PHY_CORE_0) ? 8 : 0); ++ tmpval &= 0xff; ++ pi->nphy_txpwrindex[core].bbmult = (u8) tmpval; ++ ++ wlc_phy_table_read_nphy(pi, 15, 2, ++ (80 + 2 * core), 16, ++ &pi-> ++ nphy_txpwrindex[core]. ++ iqcomp_a); ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, (85 + core), ++ 16, ++ &pi-> ++ nphy_txpwrindex[core]. ++ locomp); ++ ++ pi->nphy_txpwrindex[core].index_internal_save = ++ pi->nphy_txpwrindex[core]. ++ index_internal; ++ } ++ ++ tx_pwr_ctrl_state = pi->nphy_txpwrctrl; ++ wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF); ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 1)) ++ wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON); ++ ++ wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1, ++ (tx_ind0 + txpwrindex), 32, ++ &txgain); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ rad_gain = (txgain >> 16) & ++ ((1 << (32 - 16 + 1)) - 1); ++ else ++ rad_gain = (txgain >> 16) & ++ ((1 << (28 - 16 + 1)) - 1); ++ ++ dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1); ++ bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1); ++ ++ if (NREV_GE(pi->pubpi.phy_rev, 3)) ++ mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f : ++ 0xa5), (0x1 << 8), (0x1 << 8)); ++ else ++ mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14)); ++ ++ write_phy_reg(pi, (core == PHY_CORE_0) ? ++ 0xaa : 0xab, dac_gain); ++ ++ wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16, ++ &rad_gain); ++ ++ wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2); ++ m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00); ++ m1m2 |= ((core == PHY_CORE_0) ? ++ (bbmult << 8) : (bbmult << 0)); ++ ++ wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2); ++ ++ wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1, ++ (iq_ind0 + txpwrindex), 32, ++ &iqcomp); ++ iqcomp_a = (iqcomp >> 10) & ((1 << (19 - 10 + 1)) - 1); ++ iqcomp_b = (iqcomp >> 0) & ((1 << (9 - 0 + 1)) - 1); ++ ++ if (restore_cals) { ++ regval[0] = (u16) iqcomp_a; ++ regval[1] = (u16) iqcomp_b; ++ wlc_phy_table_write_nphy(pi, 15, 2, ++ (80 + 2 * core), 16, ++ regval); ++ } ++ ++ wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1, ++ (lo_ind0 + txpwrindex), 32, ++ &locomp); ++ if (restore_cals) ++ wlc_phy_table_write_nphy(pi, 15, 1, (85 + core), ++ 16, &locomp); ++ ++ if (NREV_IS(pi->pubpi.phy_rev, 1)) ++ wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF); ++ ++ if (PHY_IPA(pi)) { ++ wlc_phy_table_read_nphy(pi, ++ (core == PHY_CORE_0 ? ++ NPHY_TBL_ID_CORE1TXPWRCTL : ++ NPHY_TBL_ID_CORE2TXPWRCTL), ++ 1, 576 + txpwrindex, 32, ++ &rfpwr_offset); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1ff << 4), ++ ((s16) rfpwr_offset) << 4); ++ ++ mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 : ++ 0x29b, (0x1 << 2), (1) << 2); ++ ++ } ++ ++ wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state); ++ } ++ ++ pi->nphy_txpwrindex[core].index = txpwrindex; ++ } ++ ++ if (pi->phyhang_avoid) ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++} ++ ++void ++wlc_phy_txpower_sromlimit_get_nphy(struct brcms_phy *pi, uint chan, u8 *max_pwr, ++ u8 txp_rate_idx) ++{ ++ u8 chan_freq_range; ++ ++ chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, chan); ++ switch (chan_freq_range) { ++ case WL_CHAN_FREQ_RANGE_2G: ++ *max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx]; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GM: ++ *max_pwr = pi->tx_srom_max_rate_5g_mid[txp_rate_idx]; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GL: ++ *max_pwr = pi->tx_srom_max_rate_5g_low[txp_rate_idx]; ++ break; ++ case WL_CHAN_FREQ_RANGE_5GH: ++ *max_pwr = pi->tx_srom_max_rate_5g_hi[txp_rate_idx]; ++ break; ++ default: ++ *max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx]; ++ break; ++ } ++ ++ return; ++} ++ ++void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi, bool enable) ++{ ++ u16 clip_off[] = { 0xffff, 0xffff }; ++ ++ if (enable) { ++ if (pi->nphy_deaf_count == 0) { ++ pi->classifier_state = ++ wlc_phy_classifier_nphy(pi, 0, 0); ++ wlc_phy_classifier_nphy(pi, (0x7 << 0), 4); ++ wlc_phy_clip_det_nphy(pi, 0, pi->clip_state); ++ wlc_phy_clip_det_nphy(pi, 1, clip_off); ++ } ++ ++ pi->nphy_deaf_count++; ++ ++ wlc_phy_resetcca_nphy(pi); ++ ++ } else { ++ pi->nphy_deaf_count--; ++ ++ if (pi->nphy_deaf_count == 0) { ++ wlc_phy_classifier_nphy(pi, (0x7 << 0), ++ pi->classifier_state); ++ wlc_phy_clip_det_nphy(pi, 1, pi->clip_state); ++ } ++ } ++} ++ ++void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode) ++{ ++ wlapi_suspend_mac_and_wait(pi->sh->physhim); ++ ++ if (mode) { ++ if (pi->nphy_deaf_count == 0) ++ wlc_phy_stay_in_carriersearch_nphy(pi, true); ++ } else if (pi->nphy_deaf_count > 0) { ++ wlc_phy_stay_in_carriersearch_nphy(pi, false); ++ } ++ ++ wlapi_enable_mac(pi->sh->physhim); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.c.orig 2011-11-09 13:46:58.276800245 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.c 2011-11-09 13:47:17.032565765 -0500 +@@ -0,0 +1,308 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include "phy_qmath.h" ++ ++/* ++ * Description: This function make 16 bit unsigned multiplication. ++ * To fit the output into 16 bits the 32 bit multiplication result is right ++ * shifted by 16 bits. ++ */ ++u16 qm_mulu16(u16 op1, u16 op2) ++{ ++ return (u16) (((u32) op1 * (u32) op2) >> 16); ++} ++ ++/* ++ * Description: This function make 16 bit multiplication and return the result ++ * in 16 bits. To fit the multiplication result into 16 bits the multiplication ++ * result is right shifted by 15 bits. Right shifting 15 bits instead of 16 bits ++ * is done to remove the extra sign bit formed due to the multiplication. ++ * When both the 16bit inputs are 0x8000 then the output is saturated to ++ * 0x7fffffff. ++ */ ++s16 qm_muls16(s16 op1, s16 op2) ++{ ++ s32 result; ++ if (op1 == (s16) 0x8000 && op2 == (s16) 0x8000) ++ result = 0x7fffffff; ++ else ++ result = ((s32) (op1) * (s32) (op2)); ++ ++ return (s16) (result >> 15); ++} ++ ++/* ++ * Description: This function add two 32 bit numbers and return the 32bit ++ * result. If the result overflow 32 bits, the output will be saturated to ++ * 32bits. ++ */ ++s32 qm_add32(s32 op1, s32 op2) ++{ ++ s32 result; ++ result = op1 + op2; ++ if (op1 < 0 && op2 < 0 && result > 0) ++ result = 0x80000000; ++ else if (op1 > 0 && op2 > 0 && result < 0) ++ result = 0x7fffffff; ++ ++ return result; ++} ++ ++/* ++ * Description: This function add two 16 bit numbers and return the 16bit ++ * result. If the result overflow 16 bits, the output will be saturated to ++ * 16bits. ++ */ ++s16 qm_add16(s16 op1, s16 op2) ++{ ++ s16 result; ++ s32 temp = (s32) op1 + (s32) op2; ++ if (temp > (s32) 0x7fff) ++ result = (s16) 0x7fff; ++ else if (temp < (s32) 0xffff8000) ++ result = (s16) 0xffff8000; ++ else ++ result = (s16) temp; ++ ++ return result; ++} ++ ++/* ++ * Description: This function make 16 bit subtraction and return the 16bit ++ * result. If the result overflow 16 bits, the output will be saturated to ++ * 16bits. ++ */ ++s16 qm_sub16(s16 op1, s16 op2) ++{ ++ s16 result; ++ s32 temp = (s32) op1 - (s32) op2; ++ if (temp > (s32) 0x7fff) ++ result = (s16) 0x7fff; ++ else if (temp < (s32) 0xffff8000) ++ result = (s16) 0xffff8000; ++ else ++ result = (s16) temp; ++ ++ return result; ++} ++ ++/* ++ * Description: This function make a 32 bit saturated left shift when the ++ * specified shift is +ve. This function will make a 32 bit right shift when ++ * the specified shift is -ve. This function return the result after shifting ++ * operation. ++ */ ++s32 qm_shl32(s32 op, int shift) ++{ ++ int i; ++ s32 result; ++ result = op; ++ if (shift > 31) ++ shift = 31; ++ else if (shift < -31) ++ shift = -31; ++ if (shift >= 0) { ++ for (i = 0; i < shift; i++) ++ result = qm_add32(result, result); ++ } else { ++ result = result >> (-shift); ++ } ++ ++ return result; ++} ++ ++/* ++ * Description: This function make a 16 bit saturated left shift when the ++ * specified shift is +ve. This function will make a 16 bit right shift when ++ * the specified shift is -ve. This function return the result after shifting ++ * operation. ++ */ ++s16 qm_shl16(s16 op, int shift) ++{ ++ int i; ++ s16 result; ++ result = op; ++ if (shift > 15) ++ shift = 15; ++ else if (shift < -15) ++ shift = -15; ++ if (shift > 0) { ++ for (i = 0; i < shift; i++) ++ result = qm_add16(result, result); ++ } else { ++ result = result >> (-shift); ++ } ++ ++ return result; ++} ++ ++/* ++ * Description: This function make a 16 bit right shift when shift is +ve. ++ * This function make a 16 bit saturated left shift when shift is -ve. This ++ * function return the result of the shift operation. ++ */ ++s16 qm_shr16(s16 op, int shift) ++{ ++ return qm_shl16(op, -shift); ++} ++ ++/* ++ * Description: This function return the number of redundant sign bits in a ++ * 32 bit number. Example: qm_norm32(0x00000080) = 23 ++ */ ++s16 qm_norm32(s32 op) ++{ ++ u16 u16extraSignBits; ++ if (op == 0) { ++ return 31; ++ } else { ++ u16extraSignBits = 0; ++ while ((op >> 31) == (op >> 30)) { ++ u16extraSignBits++; ++ op = op << 1; ++ } ++ } ++ return u16extraSignBits; ++} ++ ++/* This table is log2(1+(i/32)) where i=[0:1:31], in q.15 format */ ++static const s16 log_table[] = { ++ 0, ++ 1455, ++ 2866, ++ 4236, ++ 5568, ++ 6863, ++ 8124, ++ 9352, ++ 10549, ++ 11716, ++ 12855, ++ 13968, ++ 15055, ++ 16117, ++ 17156, ++ 18173, ++ 19168, ++ 20143, ++ 21098, ++ 22034, ++ 22952, ++ 23852, ++ 24736, ++ 25604, ++ 26455, ++ 27292, ++ 28114, ++ 28922, ++ 29717, ++ 30498, ++ 31267, ++ 32024 ++}; ++ ++#define LOG_TABLE_SIZE 32 /* log_table size */ ++#define LOG2_LOG_TABLE_SIZE 5 /* log2(log_table size) */ ++#define Q_LOG_TABLE 15 /* qformat of log_table */ ++#define LOG10_2 19728 /* log10(2) in q.16 */ ++ ++/* ++ * Description: ++ * This routine takes the input number N and its q format qN and compute ++ * the log10(N). This routine first normalizes the input no N. Then N is in ++ * mag*(2^x) format. mag is any number in the range 2^30-(2^31 - 1). ++ * Then log2(mag * 2^x) = log2(mag) + x is computed. From that ++ * log10(mag * 2^x) = log2(mag * 2^x) * log10(2) is computed. ++ * This routine looks the log2 value in the table considering ++ * LOG2_LOG_TABLE_SIZE+1 MSBs. As the MSB is always 1, only next ++ * LOG2_OF_LOG_TABLE_SIZE MSBs are used for table lookup. Next 16 MSBs are used ++ * for interpolation. ++ * Inputs: ++ * N - number to which log10 has to be found. ++ * qN - q format of N ++ * log10N - address where log10(N) will be written. ++ * qLog10N - address where log10N qformat will be written. ++ * Note/Problem: ++ * For accurate results input should be in normalized or near normalized form. ++ */ ++void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N) ++{ ++ s16 s16norm, s16tableIndex, s16errorApproximation; ++ u16 u16offset; ++ s32 s32log; ++ ++ /* normalize the N. */ ++ s16norm = qm_norm32(N); ++ N = N << s16norm; ++ ++ /* The qformat of N after normalization. ++ * -30 is added to treat the no as between 1.0 to 2.0 ++ * i.e. after adding the -30 to the qformat the decimal point will be ++ * just rigtht of the MSB. (i.e. after sign bit and 1st MSB). i.e. ++ * at the right side of 30th bit. ++ */ ++ qN = qN + s16norm - 30; ++ ++ /* take the table index as the LOG2_OF_LOG_TABLE_SIZE bits right of the ++ * MSB */ ++ s16tableIndex = (s16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE))); ++ ++ /* remove the MSB. the MSB is always 1 after normalization. */ ++ s16tableIndex = ++ s16tableIndex & (s16) ((1 << LOG2_LOG_TABLE_SIZE) - 1); ++ ++ /* remove the (1+LOG2_OF_LOG_TABLE_SIZE) MSBs in the N. */ ++ N = N & ((1 << (32 - (2 + LOG2_LOG_TABLE_SIZE))) - 1); ++ ++ /* take the offset as the 16 MSBS after table index. ++ */ ++ u16offset = (u16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE + 16))); ++ ++ /* look the log value in the table. */ ++ s32log = log_table[s16tableIndex]; /* q.15 format */ ++ ++ /* interpolate using the offset. q.15 format. */ ++ s16errorApproximation = (s16) qm_mulu16(u16offset, ++ (u16) (log_table[s16tableIndex + 1] - ++ log_table[s16tableIndex])); ++ ++ /* q.15 format */ ++ s32log = qm_add16((s16) s32log, s16errorApproximation); ++ ++ /* adjust for the qformat of the N as ++ * log2(mag * 2^x) = log2(mag) + x ++ */ ++ s32log = qm_add32(s32log, ((s32) -qN) << 15); /* q.15 format */ ++ ++ /* normalize the result. */ ++ s16norm = qm_norm32(s32log); ++ ++ /* bring all the important bits into lower 16 bits */ ++ /* q.15+s16norm-16 format */ ++ s32log = qm_shl32(s32log, s16norm - 16); ++ ++ /* compute the log10(N) by multiplying log2(N) with log10(2). ++ * as log10(mag * 2^x) = log2(mag * 2^x) * log10(2) ++ * log10N in q.15+s16norm-16+1 (LOG10_2 is in q.16) ++ */ ++ *log10N = qm_muls16((s16) s32log, (s16) LOG10_2); ++ ++ /* write the q format of the result. */ ++ *qLog10N = 15 + s16norm - 16 + 1; ++ ++ return; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.h.orig 2011-11-09 13:46:58.276800245 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_qmath.h 2011-11-09 13:47:17.032565765 -0500 +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_QMATH_H_ ++#define _BRCM_QMATH_H_ ++ ++#include ++ ++u16 qm_mulu16(u16 op1, u16 op2); ++ ++s16 qm_muls16(s16 op1, s16 op2); ++ ++s32 qm_add32(s32 op1, s32 op2); ++ ++s16 qm_add16(s16 op1, s16 op2); ++ ++s16 qm_sub16(s16 op1, s16 op2); ++ ++s32 qm_shl32(s32 op, int shift); ++ ++s16 qm_shl16(s16 op, int shift); ++ ++s16 qm_shr16(s16 op, int shift); ++ ++s16 qm_norm32(s32 op); ++ ++void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N); ++ ++#endif /* #ifndef _BRCM_QMATH_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_radio.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_radio.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_radio.h.orig 2011-11-09 13:46:58.277800233 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_radio.h 2011-11-09 13:47:17.035565729 -0500 +@@ -0,0 +1,1533 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_PHY_RADIO_H_ ++#define _BRCM_PHY_RADIO_H_ ++ ++#define RADIO_IDCODE 0x01 ++ ++#define RADIO_DEFAULT_CORE 0 ++ ++#define RXC0_RSSI_RST 0x80 ++#define RXC0_MODE_RSSI 0x40 ++#define RXC0_MODE_OFF 0x20 ++#define RXC0_MODE_CM 0x10 ++#define RXC0_LAN_LOAD 0x08 ++#define RXC0_OFF_ADJ_MASK 0x07 ++ ++#define TXC0_MODE_TXLPF 0x04 ++#define TXC0_PA_TSSI_EN 0x02 ++#define TXC0_TSSI_EN 0x01 ++ ++#define TXC1_PA_GAIN_MASK 0x60 ++#define TXC1_PA_GAIN_3DB 0x40 ++#define TXC1_PA_GAIN_2DB 0x20 ++#define TXC1_TX_MIX_GAIN 0x10 ++#define TXC1_OFF_I_MASK 0x0c ++#define TXC1_OFF_Q_MASK 0x03 ++ ++#define RADIO_2055_READ_OFF 0x100 ++#define RADIO_2057_READ_OFF 0x200 ++ ++#define RADIO_2055_GEN_SPARE 0x00 ++#define RADIO_2055_SP_PIN_PD 0x02 ++#define RADIO_2055_SP_RSSI_CORE1 0x03 ++#define RADIO_2055_SP_PD_MISC_CORE1 0x04 ++#define RADIO_2055_SP_RSSI_CORE2 0x05 ++#define RADIO_2055_SP_PD_MISC_CORE2 0x06 ++#define RADIO_2055_SP_RX_GC1_CORE1 0x07 ++#define RADIO_2055_SP_RX_GC2_CORE1 0x08 ++#define RADIO_2055_SP_RX_GC1_CORE2 0x09 ++#define RADIO_2055_SP_RX_GC2_CORE2 0x0a ++#define RADIO_2055_SP_LPF_BW_SELECT_CORE1 0x0b ++#define RADIO_2055_SP_LPF_BW_SELECT_CORE2 0x0c ++#define RADIO_2055_SP_TX_GC1_CORE1 0x0d ++#define RADIO_2055_SP_TX_GC2_CORE1 0x0e ++#define RADIO_2055_SP_TX_GC1_CORE2 0x0f ++#define RADIO_2055_SP_TX_GC2_CORE2 0x10 ++#define RADIO_2055_MASTER_CNTRL1 0x11 ++#define RADIO_2055_MASTER_CNTRL2 0x12 ++#define RADIO_2055_PD_LGEN 0x13 ++#define RADIO_2055_PD_PLL_TS 0x14 ++#define RADIO_2055_PD_CORE1_LGBUF 0x15 ++#define RADIO_2055_PD_CORE1_TX 0x16 ++#define RADIO_2055_PD_CORE1_RXTX 0x17 ++#define RADIO_2055_PD_CORE1_RSSI_MISC 0x18 ++#define RADIO_2055_PD_CORE2_LGBUF 0x19 ++#define RADIO_2055_PD_CORE2_TX 0x1a ++#define RADIO_2055_PD_CORE2_RXTX 0x1b ++#define RADIO_2055_PD_CORE2_RSSI_MISC 0x1c ++#define RADIO_2055_PWRDET_LGEN 0x1d ++#define RADIO_2055_PWRDET_LGBUF_CORE1 0x1e ++#define RADIO_2055_PWRDET_RXTX_CORE1 0x1f ++#define RADIO_2055_PWRDET_LGBUF_CORE2 0x20 ++#define RADIO_2055_PWRDET_RXTX_CORE2 0x21 ++#define RADIO_2055_RRCCAL_CNTRL_SPARE 0x22 ++#define RADIO_2055_RRCCAL_N_OPT_SEL 0x23 ++#define RADIO_2055_CAL_MISC 0x24 ++#define RADIO_2055_CAL_COUNTER_OUT 0x25 ++#define RADIO_2055_CAL_COUNTER_OUT2 0x26 ++#define RADIO_2055_CAL_CVAR_CNTRL 0x27 ++#define RADIO_2055_CAL_RVAR_CNTRL 0x28 ++#define RADIO_2055_CAL_LPO_CNTRL 0x29 ++#define RADIO_2055_CAL_TS 0x2a ++#define RADIO_2055_CAL_RCCAL_READ_TS 0x2b ++#define RADIO_2055_CAL_RCAL_READ_TS 0x2c ++#define RADIO_2055_PAD_DRIVER 0x2d ++#define RADIO_2055_XO_CNTRL1 0x2e ++#define RADIO_2055_XO_CNTRL2 0x2f ++#define RADIO_2055_XO_REGULATOR 0x30 ++#define RADIO_2055_XO_MISC 0x31 ++#define RADIO_2055_PLL_LF_C1 0x32 ++#define RADIO_2055_PLL_CAL_VTH 0x33 ++#define RADIO_2055_PLL_LF_C2 0x34 ++#define RADIO_2055_PLL_REF 0x35 ++#define RADIO_2055_PLL_LF_R1 0x36 ++#define RADIO_2055_PLL_PFD_CP 0x37 ++#define RADIO_2055_PLL_IDAC_CPOPAMP 0x38 ++#define RADIO_2055_PLL_CP_REGULATOR 0x39 ++#define RADIO_2055_PLL_RCAL 0x3a ++#define RADIO_2055_RF_PLL_MOD0 0x3b ++#define RADIO_2055_RF_PLL_MOD1 0x3c ++#define RADIO_2055_RF_MMD_IDAC1 0x3d ++#define RADIO_2055_RF_MMD_IDAC0 0x3e ++#define RADIO_2055_RF_MMD_SPARE 0x3f ++#define RADIO_2055_VCO_CAL1 0x40 ++#define RADIO_2055_VCO_CAL2 0x41 ++#define RADIO_2055_VCO_CAL3 0x42 ++#define RADIO_2055_VCO_CAL4 0x43 ++#define RADIO_2055_VCO_CAL5 0x44 ++#define RADIO_2055_VCO_CAL6 0x45 ++#define RADIO_2055_VCO_CAL7 0x46 ++#define RADIO_2055_VCO_CAL8 0x47 ++#define RADIO_2055_VCO_CAL9 0x48 ++#define RADIO_2055_VCO_CAL10 0x49 ++#define RADIO_2055_VCO_CAL11 0x4a ++#define RADIO_2055_VCO_CAL12 0x4b ++#define RADIO_2055_VCO_CAL13 0x4c ++#define RADIO_2055_VCO_CAL14 0x4d ++#define RADIO_2055_VCO_CAL15 0x4e ++#define RADIO_2055_VCO_CAL16 0x4f ++#define RADIO_2055_VCO_KVCO 0x50 ++#define RADIO_2055_VCO_CAP_TAIL 0x51 ++#define RADIO_2055_VCO_IDAC_VCO 0x52 ++#define RADIO_2055_VCO_REGULATOR 0x53 ++#define RADIO_2055_PLL_RF_VTH 0x54 ++#define RADIO_2055_LGBUF_CEN_BUF 0x55 ++#define RADIO_2055_LGEN_TUNE1 0x56 ++#define RADIO_2055_LGEN_TUNE2 0x57 ++#define RADIO_2055_LGEN_IDAC1 0x58 ++#define RADIO_2055_LGEN_IDAC2 0x59 ++#define RADIO_2055_LGEN_BIAS_CNT 0x5a ++#define RADIO_2055_LGEN_BIAS_IDAC 0x5b ++#define RADIO_2055_LGEN_RCAL 0x5c ++#define RADIO_2055_LGEN_DIV 0x5d ++#define RADIO_2055_LGEN_SPARE2 0x5e ++#define RADIO_2055_CORE1_LGBUF_A_TUNE 0x5f ++#define RADIO_2055_CORE1_LGBUF_G_TUNE 0x60 ++#define RADIO_2055_CORE1_LGBUF_DIV 0x61 ++#define RADIO_2055_CORE1_LGBUF_A_IDAC 0x62 ++#define RADIO_2055_CORE1_LGBUF_G_IDAC 0x63 ++#define RADIO_2055_CORE1_LGBUF_IDACFIL_OVR 0x64 ++#define RADIO_2055_CORE1_LGBUF_SPARE 0x65 ++#define RADIO_2055_CORE1_RXRF_SPC1 0x66 ++#define RADIO_2055_CORE1_RXRF_REG1 0x67 ++#define RADIO_2055_CORE1_RXRF_REG2 0x68 ++#define RADIO_2055_CORE1_RXRF_RCAL 0x69 ++#define RADIO_2055_CORE1_RXBB_BUFI_LPFCMP 0x6a ++#define RADIO_2055_CORE1_RXBB_LPF 0x6b ++#define RADIO_2055_CORE1_RXBB_MIDAC_HIPAS 0x6c ++#define RADIO_2055_CORE1_RXBB_VGA1_IDAC 0x6d ++#define RADIO_2055_CORE1_RXBB_VGA2_IDAC 0x6e ++#define RADIO_2055_CORE1_RXBB_VGA3_IDAC 0x6f ++#define RADIO_2055_CORE1_RXBB_BUFO_CTRL 0x70 ++#define RADIO_2055_CORE1_RXBB_RCCAL_CTRL 0x71 ++#define RADIO_2055_CORE1_RXBB_RSSI_CTRL1 0x72 ++#define RADIO_2055_CORE1_RXBB_RSSI_CTRL2 0x73 ++#define RADIO_2055_CORE1_RXBB_RSSI_CTRL3 0x74 ++#define RADIO_2055_CORE1_RXBB_RSSI_CTRL4 0x75 ++#define RADIO_2055_CORE1_RXBB_RSSI_CTRL5 0x76 ++#define RADIO_2055_CORE1_RXBB_REGULATOR 0x77 ++#define RADIO_2055_CORE1_RXBB_SPARE1 0x78 ++#define RADIO_2055_CORE1_RXTXBB_RCAL 0x79 ++#define RADIO_2055_CORE1_TXRF_SGM_PGA 0x7a ++#define RADIO_2055_CORE1_TXRF_SGM_PAD 0x7b ++#define RADIO_2055_CORE1_TXRF_CNTR_PGA1 0x7c ++#define RADIO_2055_CORE1_TXRF_CNTR_PAD1 0x7d ++#define RADIO_2055_CORE1_TX_RFPGA_IDAC 0x7e ++#define RADIO_2055_CORE1_TX_PGA_PAD_TN 0x7f ++#define RADIO_2055_CORE1_TX_PAD_IDAC1 0x80 ++#define RADIO_2055_CORE1_TX_PAD_IDAC2 0x81 ++#define RADIO_2055_CORE1_TX_MX_BGTRIM 0x82 ++#define RADIO_2055_CORE1_TXRF_RCAL 0x83 ++#define RADIO_2055_CORE1_TXRF_PAD_TSSI1 0x84 ++#define RADIO_2055_CORE1_TXRF_PAD_TSSI2 0x85 ++#define RADIO_2055_CORE1_TX_RF_SPARE 0x86 ++#define RADIO_2055_CORE1_TXRF_IQCAL1 0x87 ++#define RADIO_2055_CORE1_TXRF_IQCAL2 0x88 ++#define RADIO_2055_CORE1_TXBB_RCCAL_CTRL 0x89 ++#define RADIO_2055_CORE1_TXBB_LPF1 0x8a ++#define RADIO_2055_CORE1_TX_VOS_CNCL 0x8b ++#define RADIO_2055_CORE1_TX_LPF_MXGM_IDAC 0x8c ++#define RADIO_2055_CORE1_TX_BB_MXGM 0x8d ++#define RADIO_2055_CORE2_LGBUF_A_TUNE 0x8e ++#define RADIO_2055_CORE2_LGBUF_G_TUNE 0x8f ++#define RADIO_2055_CORE2_LGBUF_DIV 0x90 ++#define RADIO_2055_CORE2_LGBUF_A_IDAC 0x91 ++#define RADIO_2055_CORE2_LGBUF_G_IDAC 0x92 ++#define RADIO_2055_CORE2_LGBUF_IDACFIL_OVR 0x93 ++#define RADIO_2055_CORE2_LGBUF_SPARE 0x94 ++#define RADIO_2055_CORE2_RXRF_SPC1 0x95 ++#define RADIO_2055_CORE2_RXRF_REG1 0x96 ++#define RADIO_2055_CORE2_RXRF_REG2 0x97 ++#define RADIO_2055_CORE2_RXRF_RCAL 0x98 ++#define RADIO_2055_CORE2_RXBB_BUFI_LPFCMP 0x99 ++#define RADIO_2055_CORE2_RXBB_LPF 0x9a ++#define RADIO_2055_CORE2_RXBB_MIDAC_HIPAS 0x9b ++#define RADIO_2055_CORE2_RXBB_VGA1_IDAC 0x9c ++#define RADIO_2055_CORE2_RXBB_VGA2_IDAC 0x9d ++#define RADIO_2055_CORE2_RXBB_VGA3_IDAC 0x9e ++#define RADIO_2055_CORE2_RXBB_BUFO_CTRL 0x9f ++#define RADIO_2055_CORE2_RXBB_RCCAL_CTRL 0xa0 ++#define RADIO_2055_CORE2_RXBB_RSSI_CTRL1 0xa1 ++#define RADIO_2055_CORE2_RXBB_RSSI_CTRL2 0xa2 ++#define RADIO_2055_CORE2_RXBB_RSSI_CTRL3 0xa3 ++#define RADIO_2055_CORE2_RXBB_RSSI_CTRL4 0xa4 ++#define RADIO_2055_CORE2_RXBB_RSSI_CTRL5 0xa5 ++#define RADIO_2055_CORE2_RXBB_REGULATOR 0xa6 ++#define RADIO_2055_CORE2_RXBB_SPARE1 0xa7 ++#define RADIO_2055_CORE2_RXTXBB_RCAL 0xa8 ++#define RADIO_2055_CORE2_TXRF_SGM_PGA 0xa9 ++#define RADIO_2055_CORE2_TXRF_SGM_PAD 0xaa ++#define RADIO_2055_CORE2_TXRF_CNTR_PGA1 0xab ++#define RADIO_2055_CORE2_TXRF_CNTR_PAD1 0xac ++#define RADIO_2055_CORE2_TX_RFPGA_IDAC 0xad ++#define RADIO_2055_CORE2_TX_PGA_PAD_TN 0xae ++#define RADIO_2055_CORE2_TX_PAD_IDAC1 0xaf ++#define RADIO_2055_CORE2_TX_PAD_IDAC2 0xb0 ++#define RADIO_2055_CORE2_TX_MX_BGTRIM 0xb1 ++#define RADIO_2055_CORE2_TXRF_RCAL 0xb2 ++#define RADIO_2055_CORE2_TXRF_PAD_TSSI1 0xb3 ++#define RADIO_2055_CORE2_TXRF_PAD_TSSI2 0xb4 ++#define RADIO_2055_CORE2_TX_RF_SPARE 0xb5 ++#define RADIO_2055_CORE2_TXRF_IQCAL1 0xb6 ++#define RADIO_2055_CORE2_TXRF_IQCAL2 0xb7 ++#define RADIO_2055_CORE2_TXBB_RCCAL_CTRL 0xb8 ++#define RADIO_2055_CORE2_TXBB_LPF1 0xb9 ++#define RADIO_2055_CORE2_TX_VOS_CNCL 0xba ++#define RADIO_2055_CORE2_TX_LPF_MXGM_IDAC 0xbb ++#define RADIO_2055_CORE2_TX_BB_MXGM 0xbc ++#define RADIO_2055_PRG_GC_HPVGA23_21 0xbd ++#define RADIO_2055_PRG_GC_HPVGA23_22 0xbe ++#define RADIO_2055_PRG_GC_HPVGA23_23 0xbf ++#define RADIO_2055_PRG_GC_HPVGA23_24 0xc0 ++#define RADIO_2055_PRG_GC_HPVGA23_25 0xc1 ++#define RADIO_2055_PRG_GC_HPVGA23_26 0xc2 ++#define RADIO_2055_PRG_GC_HPVGA23_27 0xc3 ++#define RADIO_2055_PRG_GC_HPVGA23_28 0xc4 ++#define RADIO_2055_PRG_GC_HPVGA23_29 0xc5 ++#define RADIO_2055_PRG_GC_HPVGA23_30 0xc6 ++#define RADIO_2055_CORE1_LNA_GAINBST 0xcd ++#define RADIO_2055_CORE1_B0_NBRSSI_VCM 0xd2 ++#define RADIO_2055_CORE1_GEN_SPARE2 0xd6 ++#define RADIO_2055_CORE2_LNA_GAINBST 0xd9 ++#define RADIO_2055_CORE2_B0_NBRSSI_VCM 0xde ++#define RADIO_2055_CORE2_GEN_SPARE2 0xe2 ++ ++#define RADIO_2055_GAINBST_GAIN_DB 6 ++#define RADIO_2055_GAINBST_CODE 0x6 ++ ++#define RADIO_2055_JTAGCTRL_MASK 0x04 ++#define RADIO_2055_JTAGSYNC_MASK 0x08 ++#define RADIO_2055_RRCAL_START 0x40 ++#define RADIO_2055_RRCAL_RST_N 0x01 ++#define RADIO_2055_CAL_LPO_ENABLE 0x80 ++#define RADIO_2055_RCAL_DONE 0x80 ++#define RADIO_2055_NBRSSI_VCM_I_MASK 0x03 ++#define RADIO_2055_NBRSSI_VCM_I_SHIFT 0x00 ++#define RADIO_2055_NBRSSI_VCM_Q_MASK 0x03 ++#define RADIO_2055_NBRSSI_VCM_Q_SHIFT 0x00 ++#define RADIO_2055_WBRSSI_VCM_IQ_MASK 0x0c ++#define RADIO_2055_WBRSSI_VCM_IQ_SHIFT 0x02 ++#define RADIO_2055_NBRSSI_PD 0x01 ++#define RADIO_2055_WBRSSI_G1_PD 0x04 ++#define RADIO_2055_WBRSSI_G2_PD 0x02 ++#define RADIO_2055_NBRSSI_SEL 0x01 ++#define RADIO_2055_WBRSSI_G1_SEL 0x04 ++#define RADIO_2055_WBRSSI_G2_SEL 0x02 ++#define RADIO_2055_COUPLE_RX_MASK 0x01 ++#define RADIO_2055_COUPLE_TX_MASK 0x02 ++#define RADIO_2055_GAINBST_DISABLE 0x02 ++#define RADIO_2055_GAINBST_VAL_MASK 0x07 ++#define RADIO_2055_RXMX_GC_MASK 0x0c ++ ++#define RADIO_MIMO_CORESEL_OFF 0x0 ++#define RADIO_MIMO_CORESEL_CORE1 0x1 ++#define RADIO_MIMO_CORESEL_CORE2 0x2 ++#define RADIO_MIMO_CORESEL_CORE3 0x3 ++#define RADIO_MIMO_CORESEL_CORE4 0x4 ++#define RADIO_MIMO_CORESEL_ALLRX 0x5 ++#define RADIO_MIMO_CORESEL_ALLTX 0x6 ++#define RADIO_MIMO_CORESEL_ALLRXTX 0x7 ++ ++#define RADIO_2064_READ_OFF 0x200 ++ ++#define RADIO_2064_REG000 0x0 ++#define RADIO_2064_REG001 0x1 ++#define RADIO_2064_REG002 0x2 ++#define RADIO_2064_REG003 0x3 ++#define RADIO_2064_REG004 0x4 ++#define RADIO_2064_REG005 0x5 ++#define RADIO_2064_REG006 0x6 ++#define RADIO_2064_REG007 0x7 ++#define RADIO_2064_REG008 0x8 ++#define RADIO_2064_REG009 0x9 ++#define RADIO_2064_REG00A 0xa ++#define RADIO_2064_REG00B 0xb ++#define RADIO_2064_REG00C 0xc ++#define RADIO_2064_REG00D 0xd ++#define RADIO_2064_REG00E 0xe ++#define RADIO_2064_REG00F 0xf ++#define RADIO_2064_REG010 0x10 ++#define RADIO_2064_REG011 0x11 ++#define RADIO_2064_REG012 0x12 ++#define RADIO_2064_REG013 0x13 ++#define RADIO_2064_REG014 0x14 ++#define RADIO_2064_REG015 0x15 ++#define RADIO_2064_REG016 0x16 ++#define RADIO_2064_REG017 0x17 ++#define RADIO_2064_REG018 0x18 ++#define RADIO_2064_REG019 0x19 ++#define RADIO_2064_REG01A 0x1a ++#define RADIO_2064_REG01B 0x1b ++#define RADIO_2064_REG01C 0x1c ++#define RADIO_2064_REG01D 0x1d ++#define RADIO_2064_REG01E 0x1e ++#define RADIO_2064_REG01F 0x1f ++#define RADIO_2064_REG020 0x20 ++#define RADIO_2064_REG021 0x21 ++#define RADIO_2064_REG022 0x22 ++#define RADIO_2064_REG023 0x23 ++#define RADIO_2064_REG024 0x24 ++#define RADIO_2064_REG025 0x25 ++#define RADIO_2064_REG026 0x26 ++#define RADIO_2064_REG027 0x27 ++#define RADIO_2064_REG028 0x28 ++#define RADIO_2064_REG029 0x29 ++#define RADIO_2064_REG02A 0x2a ++#define RADIO_2064_REG02B 0x2b ++#define RADIO_2064_REG02C 0x2c ++#define RADIO_2064_REG02D 0x2d ++#define RADIO_2064_REG02E 0x2e ++#define RADIO_2064_REG02F 0x2f ++#define RADIO_2064_REG030 0x30 ++#define RADIO_2064_REG031 0x31 ++#define RADIO_2064_REG032 0x32 ++#define RADIO_2064_REG033 0x33 ++#define RADIO_2064_REG034 0x34 ++#define RADIO_2064_REG035 0x35 ++#define RADIO_2064_REG036 0x36 ++#define RADIO_2064_REG037 0x37 ++#define RADIO_2064_REG038 0x38 ++#define RADIO_2064_REG039 0x39 ++#define RADIO_2064_REG03A 0x3a ++#define RADIO_2064_REG03B 0x3b ++#define RADIO_2064_REG03C 0x3c ++#define RADIO_2064_REG03D 0x3d ++#define RADIO_2064_REG03E 0x3e ++#define RADIO_2064_REG03F 0x3f ++#define RADIO_2064_REG040 0x40 ++#define RADIO_2064_REG041 0x41 ++#define RADIO_2064_REG042 0x42 ++#define RADIO_2064_REG043 0x43 ++#define RADIO_2064_REG044 0x44 ++#define RADIO_2064_REG045 0x45 ++#define RADIO_2064_REG046 0x46 ++#define RADIO_2064_REG047 0x47 ++#define RADIO_2064_REG048 0x48 ++#define RADIO_2064_REG049 0x49 ++#define RADIO_2064_REG04A 0x4a ++#define RADIO_2064_REG04B 0x4b ++#define RADIO_2064_REG04C 0x4c ++#define RADIO_2064_REG04D 0x4d ++#define RADIO_2064_REG04E 0x4e ++#define RADIO_2064_REG04F 0x4f ++#define RADIO_2064_REG050 0x50 ++#define RADIO_2064_REG051 0x51 ++#define RADIO_2064_REG052 0x52 ++#define RADIO_2064_REG053 0x53 ++#define RADIO_2064_REG054 0x54 ++#define RADIO_2064_REG055 0x55 ++#define RADIO_2064_REG056 0x56 ++#define RADIO_2064_REG057 0x57 ++#define RADIO_2064_REG058 0x58 ++#define RADIO_2064_REG059 0x59 ++#define RADIO_2064_REG05A 0x5a ++#define RADIO_2064_REG05B 0x5b ++#define RADIO_2064_REG05C 0x5c ++#define RADIO_2064_REG05D 0x5d ++#define RADIO_2064_REG05E 0x5e ++#define RADIO_2064_REG05F 0x5f ++#define RADIO_2064_REG060 0x60 ++#define RADIO_2064_REG061 0x61 ++#define RADIO_2064_REG062 0x62 ++#define RADIO_2064_REG063 0x63 ++#define RADIO_2064_REG064 0x64 ++#define RADIO_2064_REG065 0x65 ++#define RADIO_2064_REG066 0x66 ++#define RADIO_2064_REG067 0x67 ++#define RADIO_2064_REG068 0x68 ++#define RADIO_2064_REG069 0x69 ++#define RADIO_2064_REG06A 0x6a ++#define RADIO_2064_REG06B 0x6b ++#define RADIO_2064_REG06C 0x6c ++#define RADIO_2064_REG06D 0x6d ++#define RADIO_2064_REG06E 0x6e ++#define RADIO_2064_REG06F 0x6f ++#define RADIO_2064_REG070 0x70 ++#define RADIO_2064_REG071 0x71 ++#define RADIO_2064_REG072 0x72 ++#define RADIO_2064_REG073 0x73 ++#define RADIO_2064_REG074 0x74 ++#define RADIO_2064_REG075 0x75 ++#define RADIO_2064_REG076 0x76 ++#define RADIO_2064_REG077 0x77 ++#define RADIO_2064_REG078 0x78 ++#define RADIO_2064_REG079 0x79 ++#define RADIO_2064_REG07A 0x7a ++#define RADIO_2064_REG07B 0x7b ++#define RADIO_2064_REG07C 0x7c ++#define RADIO_2064_REG07D 0x7d ++#define RADIO_2064_REG07E 0x7e ++#define RADIO_2064_REG07F 0x7f ++#define RADIO_2064_REG080 0x80 ++#define RADIO_2064_REG081 0x81 ++#define RADIO_2064_REG082 0x82 ++#define RADIO_2064_REG083 0x83 ++#define RADIO_2064_REG084 0x84 ++#define RADIO_2064_REG085 0x85 ++#define RADIO_2064_REG086 0x86 ++#define RADIO_2064_REG087 0x87 ++#define RADIO_2064_REG088 0x88 ++#define RADIO_2064_REG089 0x89 ++#define RADIO_2064_REG08A 0x8a ++#define RADIO_2064_REG08B 0x8b ++#define RADIO_2064_REG08C 0x8c ++#define RADIO_2064_REG08D 0x8d ++#define RADIO_2064_REG08E 0x8e ++#define RADIO_2064_REG08F 0x8f ++#define RADIO_2064_REG090 0x90 ++#define RADIO_2064_REG091 0x91 ++#define RADIO_2064_REG092 0x92 ++#define RADIO_2064_REG093 0x93 ++#define RADIO_2064_REG094 0x94 ++#define RADIO_2064_REG095 0x95 ++#define RADIO_2064_REG096 0x96 ++#define RADIO_2064_REG097 0x97 ++#define RADIO_2064_REG098 0x98 ++#define RADIO_2064_REG099 0x99 ++#define RADIO_2064_REG09A 0x9a ++#define RADIO_2064_REG09B 0x9b ++#define RADIO_2064_REG09C 0x9c ++#define RADIO_2064_REG09D 0x9d ++#define RADIO_2064_REG09E 0x9e ++#define RADIO_2064_REG09F 0x9f ++#define RADIO_2064_REG0A0 0xa0 ++#define RADIO_2064_REG0A1 0xa1 ++#define RADIO_2064_REG0A2 0xa2 ++#define RADIO_2064_REG0A3 0xa3 ++#define RADIO_2064_REG0A4 0xa4 ++#define RADIO_2064_REG0A5 0xa5 ++#define RADIO_2064_REG0A6 0xa6 ++#define RADIO_2064_REG0A7 0xa7 ++#define RADIO_2064_REG0A8 0xa8 ++#define RADIO_2064_REG0A9 0xa9 ++#define RADIO_2064_REG0AA 0xaa ++#define RADIO_2064_REG0AB 0xab ++#define RADIO_2064_REG0AC 0xac ++#define RADIO_2064_REG0AD 0xad ++#define RADIO_2064_REG0AE 0xae ++#define RADIO_2064_REG0AF 0xaf ++#define RADIO_2064_REG0B0 0xb0 ++#define RADIO_2064_REG0B1 0xb1 ++#define RADIO_2064_REG0B2 0xb2 ++#define RADIO_2064_REG0B3 0xb3 ++#define RADIO_2064_REG0B4 0xb4 ++#define RADIO_2064_REG0B5 0xb5 ++#define RADIO_2064_REG0B6 0xb6 ++#define RADIO_2064_REG0B7 0xb7 ++#define RADIO_2064_REG0B8 0xb8 ++#define RADIO_2064_REG0B9 0xb9 ++#define RADIO_2064_REG0BA 0xba ++#define RADIO_2064_REG0BB 0xbb ++#define RADIO_2064_REG0BC 0xbc ++#define RADIO_2064_REG0BD 0xbd ++#define RADIO_2064_REG0BE 0xbe ++#define RADIO_2064_REG0BF 0xbf ++#define RADIO_2064_REG0C0 0xc0 ++#define RADIO_2064_REG0C1 0xc1 ++#define RADIO_2064_REG0C2 0xc2 ++#define RADIO_2064_REG0C3 0xc3 ++#define RADIO_2064_REG0C4 0xc4 ++#define RADIO_2064_REG0C5 0xc5 ++#define RADIO_2064_REG0C6 0xc6 ++#define RADIO_2064_REG0C7 0xc7 ++#define RADIO_2064_REG0C8 0xc8 ++#define RADIO_2064_REG0C9 0xc9 ++#define RADIO_2064_REG0CA 0xca ++#define RADIO_2064_REG0CB 0xcb ++#define RADIO_2064_REG0CC 0xcc ++#define RADIO_2064_REG0CD 0xcd ++#define RADIO_2064_REG0CE 0xce ++#define RADIO_2064_REG0CF 0xcf ++#define RADIO_2064_REG0D0 0xd0 ++#define RADIO_2064_REG0D1 0xd1 ++#define RADIO_2064_REG0D2 0xd2 ++#define RADIO_2064_REG0D3 0xd3 ++#define RADIO_2064_REG0D4 0xd4 ++#define RADIO_2064_REG0D5 0xd5 ++#define RADIO_2064_REG0D6 0xd6 ++#define RADIO_2064_REG0D7 0xd7 ++#define RADIO_2064_REG0D8 0xd8 ++#define RADIO_2064_REG0D9 0xd9 ++#define RADIO_2064_REG0DA 0xda ++#define RADIO_2064_REG0DB 0xdb ++#define RADIO_2064_REG0DC 0xdc ++#define RADIO_2064_REG0DD 0xdd ++#define RADIO_2064_REG0DE 0xde ++#define RADIO_2064_REG0DF 0xdf ++#define RADIO_2064_REG0E0 0xe0 ++#define RADIO_2064_REG0E1 0xe1 ++#define RADIO_2064_REG0E2 0xe2 ++#define RADIO_2064_REG0E3 0xe3 ++#define RADIO_2064_REG0E4 0xe4 ++#define RADIO_2064_REG0E5 0xe5 ++#define RADIO_2064_REG0E6 0xe6 ++#define RADIO_2064_REG0E7 0xe7 ++#define RADIO_2064_REG0E8 0xe8 ++#define RADIO_2064_REG0E9 0xe9 ++#define RADIO_2064_REG0EA 0xea ++#define RADIO_2064_REG0EB 0xeb ++#define RADIO_2064_REG0EC 0xec ++#define RADIO_2064_REG0ED 0xed ++#define RADIO_2064_REG0EE 0xee ++#define RADIO_2064_REG0EF 0xef ++#define RADIO_2064_REG0F0 0xf0 ++#define RADIO_2064_REG0F1 0xf1 ++#define RADIO_2064_REG0F2 0xf2 ++#define RADIO_2064_REG0F3 0xf3 ++#define RADIO_2064_REG0F4 0xf4 ++#define RADIO_2064_REG0F5 0xf5 ++#define RADIO_2064_REG0F6 0xf6 ++#define RADIO_2064_REG0F7 0xf7 ++#define RADIO_2064_REG0F8 0xf8 ++#define RADIO_2064_REG0F9 0xf9 ++#define RADIO_2064_REG0FA 0xfa ++#define RADIO_2064_REG0FB 0xfb ++#define RADIO_2064_REG0FC 0xfc ++#define RADIO_2064_REG0FD 0xfd ++#define RADIO_2064_REG0FE 0xfe ++#define RADIO_2064_REG0FF 0xff ++#define RADIO_2064_REG100 0x100 ++#define RADIO_2064_REG101 0x101 ++#define RADIO_2064_REG102 0x102 ++#define RADIO_2064_REG103 0x103 ++#define RADIO_2064_REG104 0x104 ++#define RADIO_2064_REG105 0x105 ++#define RADIO_2064_REG106 0x106 ++#define RADIO_2064_REG107 0x107 ++#define RADIO_2064_REG108 0x108 ++#define RADIO_2064_REG109 0x109 ++#define RADIO_2064_REG10A 0x10a ++#define RADIO_2064_REG10B 0x10b ++#define RADIO_2064_REG10C 0x10c ++#define RADIO_2064_REG10D 0x10d ++#define RADIO_2064_REG10E 0x10e ++#define RADIO_2064_REG10F 0x10f ++#define RADIO_2064_REG110 0x110 ++#define RADIO_2064_REG111 0x111 ++#define RADIO_2064_REG112 0x112 ++#define RADIO_2064_REG113 0x113 ++#define RADIO_2064_REG114 0x114 ++#define RADIO_2064_REG115 0x115 ++#define RADIO_2064_REG116 0x116 ++#define RADIO_2064_REG117 0x117 ++#define RADIO_2064_REG118 0x118 ++#define RADIO_2064_REG119 0x119 ++#define RADIO_2064_REG11A 0x11a ++#define RADIO_2064_REG11B 0x11b ++#define RADIO_2064_REG11C 0x11c ++#define RADIO_2064_REG11D 0x11d ++#define RADIO_2064_REG11E 0x11e ++#define RADIO_2064_REG11F 0x11f ++#define RADIO_2064_REG120 0x120 ++#define RADIO_2064_REG121 0x121 ++#define RADIO_2064_REG122 0x122 ++#define RADIO_2064_REG123 0x123 ++#define RADIO_2064_REG124 0x124 ++#define RADIO_2064_REG125 0x125 ++#define RADIO_2064_REG126 0x126 ++#define RADIO_2064_REG127 0x127 ++#define RADIO_2064_REG128 0x128 ++#define RADIO_2064_REG129 0x129 ++#define RADIO_2064_REG12A 0x12a ++#define RADIO_2064_REG12B 0x12b ++#define RADIO_2064_REG12C 0x12c ++#define RADIO_2064_REG12D 0x12d ++#define RADIO_2064_REG12E 0x12e ++#define RADIO_2064_REG12F 0x12f ++#define RADIO_2064_REG130 0x130 ++ ++#define RADIO_2056_SYN (0x0 << 12) ++#define RADIO_2056_TX0 (0x2 << 12) ++#define RADIO_2056_TX1 (0x3 << 12) ++#define RADIO_2056_RX0 (0x6 << 12) ++#define RADIO_2056_RX1 (0x7 << 12) ++#define RADIO_2056_ALLTX (0xe << 12) ++#define RADIO_2056_ALLRX (0xf << 12) ++ ++#define RADIO_2056_SYN_RESERVED_ADDR0 0x0 ++#define RADIO_2056_SYN_IDCODE 0x1 ++#define RADIO_2056_SYN_RESERVED_ADDR2 0x2 ++#define RADIO_2056_SYN_RESERVED_ADDR3 0x3 ++#define RADIO_2056_SYN_RESERVED_ADDR4 0x4 ++#define RADIO_2056_SYN_RESERVED_ADDR5 0x5 ++#define RADIO_2056_SYN_RESERVED_ADDR6 0x6 ++#define RADIO_2056_SYN_RESERVED_ADDR7 0x7 ++#define RADIO_2056_SYN_COM_CTRL 0x8 ++#define RADIO_2056_SYN_COM_PU 0x9 ++#define RADIO_2056_SYN_COM_OVR 0xa ++#define RADIO_2056_SYN_COM_RESET 0xb ++#define RADIO_2056_SYN_COM_RCAL 0xc ++#define RADIO_2056_SYN_COM_RC_RXLPF 0xd ++#define RADIO_2056_SYN_COM_RC_TXLPF 0xe ++#define RADIO_2056_SYN_COM_RC_RXHPF 0xf ++#define RADIO_2056_SYN_RESERVED_ADDR16 0x10 ++#define RADIO_2056_SYN_RESERVED_ADDR17 0x11 ++#define RADIO_2056_SYN_RESERVED_ADDR18 0x12 ++#define RADIO_2056_SYN_RESERVED_ADDR19 0x13 ++#define RADIO_2056_SYN_RESERVED_ADDR20 0x14 ++#define RADIO_2056_SYN_RESERVED_ADDR21 0x15 ++#define RADIO_2056_SYN_RESERVED_ADDR22 0x16 ++#define RADIO_2056_SYN_RESERVED_ADDR23 0x17 ++#define RADIO_2056_SYN_RESERVED_ADDR24 0x18 ++#define RADIO_2056_SYN_RESERVED_ADDR25 0x19 ++#define RADIO_2056_SYN_RESERVED_ADDR26 0x1a ++#define RADIO_2056_SYN_RESERVED_ADDR27 0x1b ++#define RADIO_2056_SYN_RESERVED_ADDR28 0x1c ++#define RADIO_2056_SYN_RESERVED_ADDR29 0x1d ++#define RADIO_2056_SYN_RESERVED_ADDR30 0x1e ++#define RADIO_2056_SYN_RESERVED_ADDR31 0x1f ++#define RADIO_2056_SYN_GPIO_MASTER1 0x20 ++#define RADIO_2056_SYN_GPIO_MASTER2 0x21 ++#define RADIO_2056_SYN_TOPBIAS_MASTER 0x22 ++#define RADIO_2056_SYN_TOPBIAS_RCAL 0x23 ++#define RADIO_2056_SYN_AFEREG 0x24 ++#define RADIO_2056_SYN_TEMPPROCSENSE 0x25 ++#define RADIO_2056_SYN_TEMPPROCSENSEIDAC 0x26 ++#define RADIO_2056_SYN_TEMPPROCSENSERCAL 0x27 ++#define RADIO_2056_SYN_LPO 0x28 ++#define RADIO_2056_SYN_VDDCAL_MASTER 0x29 ++#define RADIO_2056_SYN_VDDCAL_IDAC 0x2a ++#define RADIO_2056_SYN_VDDCAL_STATUS 0x2b ++#define RADIO_2056_SYN_RCAL_MASTER 0x2c ++#define RADIO_2056_SYN_RCAL_CODE_OUT 0x2d ++#define RADIO_2056_SYN_RCCAL_CTRL0 0x2e ++#define RADIO_2056_SYN_RCCAL_CTRL1 0x2f ++#define RADIO_2056_SYN_RCCAL_CTRL2 0x30 ++#define RADIO_2056_SYN_RCCAL_CTRL3 0x31 ++#define RADIO_2056_SYN_RCCAL_CTRL4 0x32 ++#define RADIO_2056_SYN_RCCAL_CTRL5 0x33 ++#define RADIO_2056_SYN_RCCAL_CTRL6 0x34 ++#define RADIO_2056_SYN_RCCAL_CTRL7 0x35 ++#define RADIO_2056_SYN_RCCAL_CTRL8 0x36 ++#define RADIO_2056_SYN_RCCAL_CTRL9 0x37 ++#define RADIO_2056_SYN_RCCAL_CTRL10 0x38 ++#define RADIO_2056_SYN_RCCAL_CTRL11 0x39 ++#define RADIO_2056_SYN_ZCAL_SPARE1 0x3a ++#define RADIO_2056_SYN_ZCAL_SPARE2 0x3b ++#define RADIO_2056_SYN_PLL_MAST1 0x3c ++#define RADIO_2056_SYN_PLL_MAST2 0x3d ++#define RADIO_2056_SYN_PLL_MAST3 0x3e ++#define RADIO_2056_SYN_PLL_BIAS_RESET 0x3f ++#define RADIO_2056_SYN_PLL_XTAL0 0x40 ++#define RADIO_2056_SYN_PLL_XTAL1 0x41 ++#define RADIO_2056_SYN_PLL_XTAL3 0x42 ++#define RADIO_2056_SYN_PLL_XTAL4 0x43 ++#define RADIO_2056_SYN_PLL_XTAL5 0x44 ++#define RADIO_2056_SYN_PLL_XTAL6 0x45 ++#define RADIO_2056_SYN_PLL_REFDIV 0x46 ++#define RADIO_2056_SYN_PLL_PFD 0x47 ++#define RADIO_2056_SYN_PLL_CP1 0x48 ++#define RADIO_2056_SYN_PLL_CP2 0x49 ++#define RADIO_2056_SYN_PLL_CP3 0x4a ++#define RADIO_2056_SYN_PLL_LOOPFILTER1 0x4b ++#define RADIO_2056_SYN_PLL_LOOPFILTER2 0x4c ++#define RADIO_2056_SYN_PLL_LOOPFILTER3 0x4d ++#define RADIO_2056_SYN_PLL_LOOPFILTER4 0x4e ++#define RADIO_2056_SYN_PLL_LOOPFILTER5 0x4f ++#define RADIO_2056_SYN_PLL_MMD1 0x50 ++#define RADIO_2056_SYN_PLL_MMD2 0x51 ++#define RADIO_2056_SYN_PLL_VCO1 0x52 ++#define RADIO_2056_SYN_PLL_VCO2 0x53 ++#define RADIO_2056_SYN_PLL_MONITOR1 0x54 ++#define RADIO_2056_SYN_PLL_MONITOR2 0x55 ++#define RADIO_2056_SYN_PLL_VCOCAL1 0x56 ++#define RADIO_2056_SYN_PLL_VCOCAL2 0x57 ++#define RADIO_2056_SYN_PLL_VCOCAL4 0x58 ++#define RADIO_2056_SYN_PLL_VCOCAL5 0x59 ++#define RADIO_2056_SYN_PLL_VCOCAL6 0x5a ++#define RADIO_2056_SYN_PLL_VCOCAL7 0x5b ++#define RADIO_2056_SYN_PLL_VCOCAL8 0x5c ++#define RADIO_2056_SYN_PLL_VCOCAL9 0x5d ++#define RADIO_2056_SYN_PLL_VCOCAL10 0x5e ++#define RADIO_2056_SYN_PLL_VCOCAL11 0x5f ++#define RADIO_2056_SYN_PLL_VCOCAL12 0x60 ++#define RADIO_2056_SYN_PLL_VCOCAL13 0x61 ++#define RADIO_2056_SYN_PLL_VREG 0x62 ++#define RADIO_2056_SYN_PLL_STATUS1 0x63 ++#define RADIO_2056_SYN_PLL_STATUS2 0x64 ++#define RADIO_2056_SYN_PLL_STATUS3 0x65 ++#define RADIO_2056_SYN_LOGEN_PU0 0x66 ++#define RADIO_2056_SYN_LOGEN_PU1 0x67 ++#define RADIO_2056_SYN_LOGEN_PU2 0x68 ++#define RADIO_2056_SYN_LOGEN_PU3 0x69 ++#define RADIO_2056_SYN_LOGEN_PU5 0x6a ++#define RADIO_2056_SYN_LOGEN_PU6 0x6b ++#define RADIO_2056_SYN_LOGEN_PU7 0x6c ++#define RADIO_2056_SYN_LOGEN_PU8 0x6d ++#define RADIO_2056_SYN_LOGEN_BIAS_RESET 0x6e ++#define RADIO_2056_SYN_LOGEN_RCCR1 0x6f ++#define RADIO_2056_SYN_LOGEN_VCOBUF1 0x70 ++#define RADIO_2056_SYN_LOGEN_MIXER1 0x71 ++#define RADIO_2056_SYN_LOGEN_MIXER2 0x72 ++#define RADIO_2056_SYN_LOGEN_BUF1 0x73 ++#define RADIO_2056_SYN_LOGENBUF2 0x74 ++#define RADIO_2056_SYN_LOGEN_BUF3 0x75 ++#define RADIO_2056_SYN_LOGEN_BUF4 0x76 ++#define RADIO_2056_SYN_LOGEN_DIV1 0x77 ++#define RADIO_2056_SYN_LOGEN_DIV2 0x78 ++#define RADIO_2056_SYN_LOGEN_DIV3 0x79 ++#define RADIO_2056_SYN_LOGEN_ACL1 0x7a ++#define RADIO_2056_SYN_LOGEN_ACL2 0x7b ++#define RADIO_2056_SYN_LOGEN_ACL3 0x7c ++#define RADIO_2056_SYN_LOGEN_ACL4 0x7d ++#define RADIO_2056_SYN_LOGEN_ACL5 0x7e ++#define RADIO_2056_SYN_LOGEN_ACL6 0x7f ++#define RADIO_2056_SYN_LOGEN_ACLOUT 0x80 ++#define RADIO_2056_SYN_LOGEN_ACLCAL1 0x81 ++#define RADIO_2056_SYN_LOGEN_ACLCAL2 0x82 ++#define RADIO_2056_SYN_LOGEN_ACLCAL3 0x83 ++#define RADIO_2056_SYN_CALEN 0x84 ++#define RADIO_2056_SYN_LOGEN_PEAKDET1 0x85 ++#define RADIO_2056_SYN_LOGEN_CORE_ACL_OVR 0x86 ++#define RADIO_2056_SYN_LOGEN_RX_DIFF_ACL_OVR 0x87 ++#define RADIO_2056_SYN_LOGEN_TX_DIFF_ACL_OVR 0x88 ++#define RADIO_2056_SYN_LOGEN_RX_CMOS_ACL_OVR 0x89 ++#define RADIO_2056_SYN_LOGEN_TX_CMOS_ACL_OVR 0x8a ++#define RADIO_2056_SYN_LOGEN_VCOBUF2 0x8b ++#define RADIO_2056_SYN_LOGEN_MIXER3 0x8c ++#define RADIO_2056_SYN_LOGEN_BUF5 0x8d ++#define RADIO_2056_SYN_LOGEN_BUF6 0x8e ++#define RADIO_2056_SYN_LOGEN_CBUFRX1 0x8f ++#define RADIO_2056_SYN_LOGEN_CBUFRX2 0x90 ++#define RADIO_2056_SYN_LOGEN_CBUFRX3 0x91 ++#define RADIO_2056_SYN_LOGEN_CBUFRX4 0x92 ++#define RADIO_2056_SYN_LOGEN_CBUFTX1 0x93 ++#define RADIO_2056_SYN_LOGEN_CBUFTX2 0x94 ++#define RADIO_2056_SYN_LOGEN_CBUFTX3 0x95 ++#define RADIO_2056_SYN_LOGEN_CBUFTX4 0x96 ++#define RADIO_2056_SYN_LOGEN_CMOSRX1 0x97 ++#define RADIO_2056_SYN_LOGEN_CMOSRX2 0x98 ++#define RADIO_2056_SYN_LOGEN_CMOSRX3 0x99 ++#define RADIO_2056_SYN_LOGEN_CMOSRX4 0x9a ++#define RADIO_2056_SYN_LOGEN_CMOSTX1 0x9b ++#define RADIO_2056_SYN_LOGEN_CMOSTX2 0x9c ++#define RADIO_2056_SYN_LOGEN_CMOSTX3 0x9d ++#define RADIO_2056_SYN_LOGEN_CMOSTX4 0x9e ++#define RADIO_2056_SYN_LOGEN_VCOBUF2_OVRVAL 0x9f ++#define RADIO_2056_SYN_LOGEN_MIXER3_OVRVAL 0xa0 ++#define RADIO_2056_SYN_LOGEN_BUF5_OVRVAL 0xa1 ++#define RADIO_2056_SYN_LOGEN_BUF6_OVRVAL 0xa2 ++#define RADIO_2056_SYN_LOGEN_CBUFRX1_OVRVAL 0xa3 ++#define RADIO_2056_SYN_LOGEN_CBUFRX2_OVRVAL 0xa4 ++#define RADIO_2056_SYN_LOGEN_CBUFRX3_OVRVAL 0xa5 ++#define RADIO_2056_SYN_LOGEN_CBUFRX4_OVRVAL 0xa6 ++#define RADIO_2056_SYN_LOGEN_CBUFTX1_OVRVAL 0xa7 ++#define RADIO_2056_SYN_LOGEN_CBUFTX2_OVRVAL 0xa8 ++#define RADIO_2056_SYN_LOGEN_CBUFTX3_OVRVAL 0xa9 ++#define RADIO_2056_SYN_LOGEN_CBUFTX4_OVRVAL 0xaa ++#define RADIO_2056_SYN_LOGEN_CMOSRX1_OVRVAL 0xab ++#define RADIO_2056_SYN_LOGEN_CMOSRX2_OVRVAL 0xac ++#define RADIO_2056_SYN_LOGEN_CMOSRX3_OVRVAL 0xad ++#define RADIO_2056_SYN_LOGEN_CMOSRX4_OVRVAL 0xae ++#define RADIO_2056_SYN_LOGEN_CMOSTX1_OVRVAL 0xaf ++#define RADIO_2056_SYN_LOGEN_CMOSTX2_OVRVAL 0xb0 ++#define RADIO_2056_SYN_LOGEN_CMOSTX3_OVRVAL 0xb1 ++#define RADIO_2056_SYN_LOGEN_CMOSTX4_OVRVAL 0xb2 ++#define RADIO_2056_SYN_LOGEN_ACL_WAITCNT 0xb3 ++#define RADIO_2056_SYN_LOGEN_CORE_CALVALID 0xb4 ++#define RADIO_2056_SYN_LOGEN_RX_CMOS_CALVALID 0xb5 ++#define RADIO_2056_SYN_LOGEN_TX_CMOS_VALID 0xb6 ++ ++#define RADIO_2056_TX_RESERVED_ADDR0 0x0 ++#define RADIO_2056_TX_IDCODE 0x1 ++#define RADIO_2056_TX_RESERVED_ADDR2 0x2 ++#define RADIO_2056_TX_RESERVED_ADDR3 0x3 ++#define RADIO_2056_TX_RESERVED_ADDR4 0x4 ++#define RADIO_2056_TX_RESERVED_ADDR5 0x5 ++#define RADIO_2056_TX_RESERVED_ADDR6 0x6 ++#define RADIO_2056_TX_RESERVED_ADDR7 0x7 ++#define RADIO_2056_TX_COM_CTRL 0x8 ++#define RADIO_2056_TX_COM_PU 0x9 ++#define RADIO_2056_TX_COM_OVR 0xa ++#define RADIO_2056_TX_COM_RESET 0xb ++#define RADIO_2056_TX_COM_RCAL 0xc ++#define RADIO_2056_TX_COM_RC_RXLPF 0xd ++#define RADIO_2056_TX_COM_RC_TXLPF 0xe ++#define RADIO_2056_TX_COM_RC_RXHPF 0xf ++#define RADIO_2056_TX_RESERVED_ADDR16 0x10 ++#define RADIO_2056_TX_RESERVED_ADDR17 0x11 ++#define RADIO_2056_TX_RESERVED_ADDR18 0x12 ++#define RADIO_2056_TX_RESERVED_ADDR19 0x13 ++#define RADIO_2056_TX_RESERVED_ADDR20 0x14 ++#define RADIO_2056_TX_RESERVED_ADDR21 0x15 ++#define RADIO_2056_TX_RESERVED_ADDR22 0x16 ++#define RADIO_2056_TX_RESERVED_ADDR23 0x17 ++#define RADIO_2056_TX_RESERVED_ADDR24 0x18 ++#define RADIO_2056_TX_RESERVED_ADDR25 0x19 ++#define RADIO_2056_TX_RESERVED_ADDR26 0x1a ++#define RADIO_2056_TX_RESERVED_ADDR27 0x1b ++#define RADIO_2056_TX_RESERVED_ADDR28 0x1c ++#define RADIO_2056_TX_RESERVED_ADDR29 0x1d ++#define RADIO_2056_TX_RESERVED_ADDR30 0x1e ++#define RADIO_2056_TX_RESERVED_ADDR31 0x1f ++#define RADIO_2056_TX_IQCAL_GAIN_BW 0x20 ++#define RADIO_2056_TX_LOFT_FINE_I 0x21 ++#define RADIO_2056_TX_LOFT_FINE_Q 0x22 ++#define RADIO_2056_TX_LOFT_COARSE_I 0x23 ++#define RADIO_2056_TX_LOFT_COARSE_Q 0x24 ++#define RADIO_2056_TX_TX_COM_MASTER1 0x25 ++#define RADIO_2056_TX_TX_COM_MASTER2 0x26 ++#define RADIO_2056_TX_RXIQCAL_TXMUX 0x27 ++#define RADIO_2056_TX_TX_SSI_MASTER 0x28 ++#define RADIO_2056_TX_IQCAL_VCM_HG 0x29 ++#define RADIO_2056_TX_IQCAL_IDAC 0x2a ++#define RADIO_2056_TX_TSSI_VCM 0x2b ++#define RADIO_2056_TX_TX_AMP_DET 0x2c ++#define RADIO_2056_TX_TX_SSI_MUX 0x2d ++#define RADIO_2056_TX_TSSIA 0x2e ++#define RADIO_2056_TX_TSSIG 0x2f ++#define RADIO_2056_TX_TSSI_MISC1 0x30 ++#define RADIO_2056_TX_TSSI_MISC2 0x31 ++#define RADIO_2056_TX_TSSI_MISC3 0x32 ++#define RADIO_2056_TX_PA_SPARE1 0x33 ++#define RADIO_2056_TX_PA_SPARE2 0x34 ++#define RADIO_2056_TX_INTPAA_MASTER 0x35 ++#define RADIO_2056_TX_INTPAA_GAIN 0x36 ++#define RADIO_2056_TX_INTPAA_BOOST_TUNE 0x37 ++#define RADIO_2056_TX_INTPAA_IAUX_STAT 0x38 ++#define RADIO_2056_TX_INTPAA_IAUX_DYN 0x39 ++#define RADIO_2056_TX_INTPAA_IMAIN_STAT 0x3a ++#define RADIO_2056_TX_INTPAA_IMAIN_DYN 0x3b ++#define RADIO_2056_TX_INTPAA_CASCBIAS 0x3c ++#define RADIO_2056_TX_INTPAA_PASLOPE 0x3d ++#define RADIO_2056_TX_INTPAA_PA_MISC 0x3e ++#define RADIO_2056_TX_INTPAG_MASTER 0x3f ++#define RADIO_2056_TX_INTPAG_GAIN 0x40 ++#define RADIO_2056_TX_INTPAG_BOOST_TUNE 0x41 ++#define RADIO_2056_TX_INTPAG_IAUX_STAT 0x42 ++#define RADIO_2056_TX_INTPAG_IAUX_DYN 0x43 ++#define RADIO_2056_TX_INTPAG_IMAIN_STAT 0x44 ++#define RADIO_2056_TX_INTPAG_IMAIN_DYN 0x45 ++#define RADIO_2056_TX_INTPAG_CASCBIAS 0x46 ++#define RADIO_2056_TX_INTPAG_PASLOPE 0x47 ++#define RADIO_2056_TX_INTPAG_PA_MISC 0x48 ++#define RADIO_2056_TX_PADA_MASTER 0x49 ++#define RADIO_2056_TX_PADA_IDAC 0x4a ++#define RADIO_2056_TX_PADA_CASCBIAS 0x4b ++#define RADIO_2056_TX_PADA_GAIN 0x4c ++#define RADIO_2056_TX_PADA_BOOST_TUNE 0x4d ++#define RADIO_2056_TX_PADA_SLOPE 0x4e ++#define RADIO_2056_TX_PADG_MASTER 0x4f ++#define RADIO_2056_TX_PADG_IDAC 0x50 ++#define RADIO_2056_TX_PADG_CASCBIAS 0x51 ++#define RADIO_2056_TX_PADG_GAIN 0x52 ++#define RADIO_2056_TX_PADG_BOOST_TUNE 0x53 ++#define RADIO_2056_TX_PADG_SLOPE 0x54 ++#define RADIO_2056_TX_PGAA_MASTER 0x55 ++#define RADIO_2056_TX_PGAA_IDAC 0x56 ++#define RADIO_2056_TX_PGAA_GAIN 0x57 ++#define RADIO_2056_TX_PGAA_BOOST_TUNE 0x58 ++#define RADIO_2056_TX_PGAA_SLOPE 0x59 ++#define RADIO_2056_TX_PGAA_MISC 0x5a ++#define RADIO_2056_TX_PGAG_MASTER 0x5b ++#define RADIO_2056_TX_PGAG_IDAC 0x5c ++#define RADIO_2056_TX_PGAG_GAIN 0x5d ++#define RADIO_2056_TX_PGAG_BOOST_TUNE 0x5e ++#define RADIO_2056_TX_PGAG_SLOPE 0x5f ++#define RADIO_2056_TX_PGAG_MISC 0x60 ++#define RADIO_2056_TX_MIXA_MASTER 0x61 ++#define RADIO_2056_TX_MIXA_BOOST_TUNE 0x62 ++#define RADIO_2056_TX_MIXG 0x63 ++#define RADIO_2056_TX_MIXG_BOOST_TUNE 0x64 ++#define RADIO_2056_TX_BB_GM_MASTER 0x65 ++#define RADIO_2056_TX_GMBB_GM 0x66 ++#define RADIO_2056_TX_GMBB_IDAC 0x67 ++#define RADIO_2056_TX_TXLPF_MASTER 0x68 ++#define RADIO_2056_TX_TXLPF_RCCAL 0x69 ++#define RADIO_2056_TX_TXLPF_RCCAL_OFF0 0x6a ++#define RADIO_2056_TX_TXLPF_RCCAL_OFF1 0x6b ++#define RADIO_2056_TX_TXLPF_RCCAL_OFF2 0x6c ++#define RADIO_2056_TX_TXLPF_RCCAL_OFF3 0x6d ++#define RADIO_2056_TX_TXLPF_RCCAL_OFF4 0x6e ++#define RADIO_2056_TX_TXLPF_RCCAL_OFF5 0x6f ++#define RADIO_2056_TX_TXLPF_RCCAL_OFF6 0x70 ++#define RADIO_2056_TX_TXLPF_BW 0x71 ++#define RADIO_2056_TX_TXLPF_GAIN 0x72 ++#define RADIO_2056_TX_TXLPF_IDAC 0x73 ++#define RADIO_2056_TX_TXLPF_IDAC_0 0x74 ++#define RADIO_2056_TX_TXLPF_IDAC_1 0x75 ++#define RADIO_2056_TX_TXLPF_IDAC_2 0x76 ++#define RADIO_2056_TX_TXLPF_IDAC_3 0x77 ++#define RADIO_2056_TX_TXLPF_IDAC_4 0x78 ++#define RADIO_2056_TX_TXLPF_IDAC_5 0x79 ++#define RADIO_2056_TX_TXLPF_IDAC_6 0x7a ++#define RADIO_2056_TX_TXLPF_OPAMP_IDAC 0x7b ++#define RADIO_2056_TX_TXLPF_MISC 0x7c ++#define RADIO_2056_TX_TXSPARE1 0x7d ++#define RADIO_2056_TX_TXSPARE2 0x7e ++#define RADIO_2056_TX_TXSPARE3 0x7f ++#define RADIO_2056_TX_TXSPARE4 0x80 ++#define RADIO_2056_TX_TXSPARE5 0x81 ++#define RADIO_2056_TX_TXSPARE6 0x82 ++#define RADIO_2056_TX_TXSPARE7 0x83 ++#define RADIO_2056_TX_TXSPARE8 0x84 ++#define RADIO_2056_TX_TXSPARE9 0x85 ++#define RADIO_2056_TX_TXSPARE10 0x86 ++#define RADIO_2056_TX_TXSPARE11 0x87 ++#define RADIO_2056_TX_TXSPARE12 0x88 ++#define RADIO_2056_TX_TXSPARE13 0x89 ++#define RADIO_2056_TX_TXSPARE14 0x8a ++#define RADIO_2056_TX_TXSPARE15 0x8b ++#define RADIO_2056_TX_TXSPARE16 0x8c ++#define RADIO_2056_TX_STATUS_INTPA_GAIN 0x8d ++#define RADIO_2056_TX_STATUS_PAD_GAIN 0x8e ++#define RADIO_2056_TX_STATUS_PGA_GAIN 0x8f ++#define RADIO_2056_TX_STATUS_GM_TXLPF_GAIN 0x90 ++#define RADIO_2056_TX_STATUS_TXLPF_BW 0x91 ++#define RADIO_2056_TX_STATUS_TXLPF_RC 0x92 ++#define RADIO_2056_TX_GMBB_IDAC0 0x93 ++#define RADIO_2056_TX_GMBB_IDAC1 0x94 ++#define RADIO_2056_TX_GMBB_IDAC2 0x95 ++#define RADIO_2056_TX_GMBB_IDAC3 0x96 ++#define RADIO_2056_TX_GMBB_IDAC4 0x97 ++#define RADIO_2056_TX_GMBB_IDAC5 0x98 ++#define RADIO_2056_TX_GMBB_IDAC6 0x99 ++#define RADIO_2056_TX_GMBB_IDAC7 0x9a ++ ++#define RADIO_2056_RX_RESERVED_ADDR0 0x0 ++#define RADIO_2056_RX_IDCODE 0x1 ++#define RADIO_2056_RX_RESERVED_ADDR2 0x2 ++#define RADIO_2056_RX_RESERVED_ADDR3 0x3 ++#define RADIO_2056_RX_RESERVED_ADDR4 0x4 ++#define RADIO_2056_RX_RESERVED_ADDR5 0x5 ++#define RADIO_2056_RX_RESERVED_ADDR6 0x6 ++#define RADIO_2056_RX_RESERVED_ADDR7 0x7 ++#define RADIO_2056_RX_COM_CTRL 0x8 ++#define RADIO_2056_RX_COM_PU 0x9 ++#define RADIO_2056_RX_COM_OVR 0xa ++#define RADIO_2056_RX_COM_RESET 0xb ++#define RADIO_2056_RX_COM_RCAL 0xc ++#define RADIO_2056_RX_COM_RC_RXLPF 0xd ++#define RADIO_2056_RX_COM_RC_TXLPF 0xe ++#define RADIO_2056_RX_COM_RC_RXHPF 0xf ++#define RADIO_2056_RX_RESERVED_ADDR16 0x10 ++#define RADIO_2056_RX_RESERVED_ADDR17 0x11 ++#define RADIO_2056_RX_RESERVED_ADDR18 0x12 ++#define RADIO_2056_RX_RESERVED_ADDR19 0x13 ++#define RADIO_2056_RX_RESERVED_ADDR20 0x14 ++#define RADIO_2056_RX_RESERVED_ADDR21 0x15 ++#define RADIO_2056_RX_RESERVED_ADDR22 0x16 ++#define RADIO_2056_RX_RESERVED_ADDR23 0x17 ++#define RADIO_2056_RX_RESERVED_ADDR24 0x18 ++#define RADIO_2056_RX_RESERVED_ADDR25 0x19 ++#define RADIO_2056_RX_RESERVED_ADDR26 0x1a ++#define RADIO_2056_RX_RESERVED_ADDR27 0x1b ++#define RADIO_2056_RX_RESERVED_ADDR28 0x1c ++#define RADIO_2056_RX_RESERVED_ADDR29 0x1d ++#define RADIO_2056_RX_RESERVED_ADDR30 0x1e ++#define RADIO_2056_RX_RESERVED_ADDR31 0x1f ++#define RADIO_2056_RX_RXIQCAL_RXMUX 0x20 ++#define RADIO_2056_RX_RSSI_PU 0x21 ++#define RADIO_2056_RX_RSSI_SEL 0x22 ++#define RADIO_2056_RX_RSSI_GAIN 0x23 ++#define RADIO_2056_RX_RSSI_NB_IDAC 0x24 ++#define RADIO_2056_RX_RSSI_WB2I_IDAC_1 0x25 ++#define RADIO_2056_RX_RSSI_WB2I_IDAC_2 0x26 ++#define RADIO_2056_RX_RSSI_WB2Q_IDAC_1 0x27 ++#define RADIO_2056_RX_RSSI_WB2Q_IDAC_2 0x28 ++#define RADIO_2056_RX_RSSI_POLE 0x29 ++#define RADIO_2056_RX_RSSI_WB1_IDAC 0x2a ++#define RADIO_2056_RX_RSSI_MISC 0x2b ++#define RADIO_2056_RX_LNAA_MASTER 0x2c ++#define RADIO_2056_RX_LNAA_TUNE 0x2d ++#define RADIO_2056_RX_LNAA_GAIN 0x2e ++#define RADIO_2056_RX_LNA_A_SLOPE 0x2f ++#define RADIO_2056_RX_BIASPOLE_LNAA1_IDAC 0x30 ++#define RADIO_2056_RX_LNAA2_IDAC 0x31 ++#define RADIO_2056_RX_LNA1A_MISC 0x32 ++#define RADIO_2056_RX_LNAG_MASTER 0x33 ++#define RADIO_2056_RX_LNAG_TUNE 0x34 ++#define RADIO_2056_RX_LNAG_GAIN 0x35 ++#define RADIO_2056_RX_LNA_G_SLOPE 0x36 ++#define RADIO_2056_RX_BIASPOLE_LNAG1_IDAC 0x37 ++#define RADIO_2056_RX_LNAG2_IDAC 0x38 ++#define RADIO_2056_RX_LNA1G_MISC 0x39 ++#define RADIO_2056_RX_MIXA_MASTER 0x3a ++#define RADIO_2056_RX_MIXA_VCM 0x3b ++#define RADIO_2056_RX_MIXA_CTRLPTAT 0x3c ++#define RADIO_2056_RX_MIXA_LOB_BIAS 0x3d ++#define RADIO_2056_RX_MIXA_CORE_IDAC 0x3e ++#define RADIO_2056_RX_MIXA_CMFB_IDAC 0x3f ++#define RADIO_2056_RX_MIXA_BIAS_AUX 0x40 ++#define RADIO_2056_RX_MIXA_BIAS_MAIN 0x41 ++#define RADIO_2056_RX_MIXA_BIAS_MISC 0x42 ++#define RADIO_2056_RX_MIXA_MAST_BIAS 0x43 ++#define RADIO_2056_RX_MIXG_MASTER 0x44 ++#define RADIO_2056_RX_MIXG_VCM 0x45 ++#define RADIO_2056_RX_MIXG_CTRLPTAT 0x46 ++#define RADIO_2056_RX_MIXG_LOB_BIAS 0x47 ++#define RADIO_2056_RX_MIXG_CORE_IDAC 0x48 ++#define RADIO_2056_RX_MIXG_CMFB_IDAC 0x49 ++#define RADIO_2056_RX_MIXG_BIAS_AUX 0x4a ++#define RADIO_2056_RX_MIXG_BIAS_MAIN 0x4b ++#define RADIO_2056_RX_MIXG_BIAS_MISC 0x4c ++#define RADIO_2056_RX_MIXG_MAST_BIAS 0x4d ++#define RADIO_2056_RX_TIA_MASTER 0x4e ++#define RADIO_2056_RX_TIA_IOPAMP 0x4f ++#define RADIO_2056_RX_TIA_QOPAMP 0x50 ++#define RADIO_2056_RX_TIA_IMISC 0x51 ++#define RADIO_2056_RX_TIA_QMISC 0x52 ++#define RADIO_2056_RX_TIA_GAIN 0x53 ++#define RADIO_2056_RX_TIA_SPARE1 0x54 ++#define RADIO_2056_RX_TIA_SPARE2 0x55 ++#define RADIO_2056_RX_BB_LPF_MASTER 0x56 ++#define RADIO_2056_RX_AACI_MASTER 0x57 ++#define RADIO_2056_RX_RXLPF_IDAC 0x58 ++#define RADIO_2056_RX_RXLPF_OPAMPBIAS_LOWQ 0x59 ++#define RADIO_2056_RX_RXLPF_OPAMPBIAS_HIGHQ 0x5a ++#define RADIO_2056_RX_RXLPF_BIAS_DCCANCEL 0x5b ++#define RADIO_2056_RX_RXLPF_OUTVCM 0x5c ++#define RADIO_2056_RX_RXLPF_INVCM_BODY 0x5d ++#define RADIO_2056_RX_RXLPF_CC_OP 0x5e ++#define RADIO_2056_RX_RXLPF_GAIN 0x5f ++#define RADIO_2056_RX_RXLPF_Q_BW 0x60 ++#define RADIO_2056_RX_RXLPF_HP_CORNER_BW 0x61 ++#define RADIO_2056_RX_RXLPF_RCCAL_HPC 0x62 ++#define RADIO_2056_RX_RXHPF_OFF0 0x63 ++#define RADIO_2056_RX_RXHPF_OFF1 0x64 ++#define RADIO_2056_RX_RXHPF_OFF2 0x65 ++#define RADIO_2056_RX_RXHPF_OFF3 0x66 ++#define RADIO_2056_RX_RXHPF_OFF4 0x67 ++#define RADIO_2056_RX_RXHPF_OFF5 0x68 ++#define RADIO_2056_RX_RXHPF_OFF6 0x69 ++#define RADIO_2056_RX_RXHPF_OFF7 0x6a ++#define RADIO_2056_RX_RXLPF_RCCAL_LPC 0x6b ++#define RADIO_2056_RX_RXLPF_OFF_0 0x6c ++#define RADIO_2056_RX_RXLPF_OFF_1 0x6d ++#define RADIO_2056_RX_RXLPF_OFF_2 0x6e ++#define RADIO_2056_RX_RXLPF_OFF_3 0x6f ++#define RADIO_2056_RX_RXLPF_OFF_4 0x70 ++#define RADIO_2056_RX_UNUSED 0x71 ++#define RADIO_2056_RX_VGA_MASTER 0x72 ++#define RADIO_2056_RX_VGA_BIAS 0x73 ++#define RADIO_2056_RX_VGA_BIAS_DCCANCEL 0x74 ++#define RADIO_2056_RX_VGA_GAIN 0x75 ++#define RADIO_2056_RX_VGA_HP_CORNER_BW 0x76 ++#define RADIO_2056_RX_VGABUF_BIAS 0x77 ++#define RADIO_2056_RX_VGABUF_GAIN_BW 0x78 ++#define RADIO_2056_RX_TXFBMIX_A 0x79 ++#define RADIO_2056_RX_TXFBMIX_G 0x7a ++#define RADIO_2056_RX_RXSPARE1 0x7b ++#define RADIO_2056_RX_RXSPARE2 0x7c ++#define RADIO_2056_RX_RXSPARE3 0x7d ++#define RADIO_2056_RX_RXSPARE4 0x7e ++#define RADIO_2056_RX_RXSPARE5 0x7f ++#define RADIO_2056_RX_RXSPARE6 0x80 ++#define RADIO_2056_RX_RXSPARE7 0x81 ++#define RADIO_2056_RX_RXSPARE8 0x82 ++#define RADIO_2056_RX_RXSPARE9 0x83 ++#define RADIO_2056_RX_RXSPARE10 0x84 ++#define RADIO_2056_RX_RXSPARE11 0x85 ++#define RADIO_2056_RX_RXSPARE12 0x86 ++#define RADIO_2056_RX_RXSPARE13 0x87 ++#define RADIO_2056_RX_RXSPARE14 0x88 ++#define RADIO_2056_RX_RXSPARE15 0x89 ++#define RADIO_2056_RX_RXSPARE16 0x8a ++#define RADIO_2056_RX_STATUS_LNAA_GAIN 0x8b ++#define RADIO_2056_RX_STATUS_LNAG_GAIN 0x8c ++#define RADIO_2056_RX_STATUS_MIXTIA_GAIN 0x8d ++#define RADIO_2056_RX_STATUS_RXLPF_GAIN 0x8e ++#define RADIO_2056_RX_STATUS_VGA_BUF_GAIN 0x8f ++#define RADIO_2056_RX_STATUS_RXLPF_Q 0x90 ++#define RADIO_2056_RX_STATUS_RXLPF_BUF_BW 0x91 ++#define RADIO_2056_RX_STATUS_RXLPF_VGA_HPC 0x92 ++#define RADIO_2056_RX_STATUS_RXLPF_RC 0x93 ++#define RADIO_2056_RX_STATUS_HPC_RC 0x94 ++ ++#define RADIO_2056_LNA1_A_PU 0x01 ++#define RADIO_2056_LNA2_A_PU 0x02 ++#define RADIO_2056_LNA1_G_PU 0x01 ++#define RADIO_2056_LNA2_G_PU 0x02 ++#define RADIO_2056_MIXA_PU_I 0x01 ++#define RADIO_2056_MIXA_PU_Q 0x02 ++#define RADIO_2056_MIXA_PU_GM 0x10 ++#define RADIO_2056_MIXG_PU_I 0x01 ++#define RADIO_2056_MIXG_PU_Q 0x02 ++#define RADIO_2056_MIXG_PU_GM 0x10 ++#define RADIO_2056_TIA_PU 0x01 ++#define RADIO_2056_BB_LPF_PU 0x20 ++#define RADIO_2056_W1_PU 0x02 ++#define RADIO_2056_W2_PU 0x04 ++#define RADIO_2056_NB_PU 0x08 ++#define RADIO_2056_RSSI_W1_SEL 0x02 ++#define RADIO_2056_RSSI_W2_SEL 0x04 ++#define RADIO_2056_RSSI_NB_SEL 0x08 ++#define RADIO_2056_VCM_MASK 0x1c ++#define RADIO_2056_RSSI_VCM_SHIFT 0x02 ++ ++#define RADIO_2057_DACBUF_VINCM_CORE0 0x0 ++#define RADIO_2057_IDCODE 0x1 ++#define RADIO_2057_RCCAL_MASTER 0x2 ++#define RADIO_2057_RCCAL_CAP_SIZE 0x3 ++#define RADIO_2057_RCAL_CONFIG 0x4 ++#define RADIO_2057_GPAIO_CONFIG 0x5 ++#define RADIO_2057_GPAIO_SEL1 0x6 ++#define RADIO_2057_GPAIO_SEL0 0x7 ++#define RADIO_2057_CLPO_CONFIG 0x8 ++#define RADIO_2057_BANDGAP_CONFIG 0x9 ++#define RADIO_2057_BANDGAP_RCAL_TRIM 0xa ++#define RADIO_2057_AFEREG_CONFIG 0xb ++#define RADIO_2057_TEMPSENSE_CONFIG 0xc ++#define RADIO_2057_XTAL_CONFIG1 0xd ++#define RADIO_2057_XTAL_ICORE_SIZE 0xe ++#define RADIO_2057_XTAL_BUF_SIZE 0xf ++#define RADIO_2057_XTAL_PULLCAP_SIZE 0x10 ++#define RADIO_2057_RFPLL_MASTER 0x11 ++#define RADIO_2057_VCOMONITOR_VTH_L 0x12 ++#define RADIO_2057_VCOMONITOR_VTH_H 0x13 ++#define RADIO_2057_VCOCAL_BIASRESET_RFPLLREG_VOUT 0x14 ++#define RADIO_2057_VCO_VARCSIZE_IDAC 0x15 ++#define RADIO_2057_VCOCAL_COUNTVAL0 0x16 ++#define RADIO_2057_VCOCAL_COUNTVAL1 0x17 ++#define RADIO_2057_VCOCAL_INTCLK_COUNT 0x18 ++#define RADIO_2057_VCOCAL_MASTER 0x19 ++#define RADIO_2057_VCOCAL_NUMCAPCHANGE 0x1a ++#define RADIO_2057_VCOCAL_WINSIZE 0x1b ++#define RADIO_2057_VCOCAL_DELAY_AFTER_REFRESH 0x1c ++#define RADIO_2057_VCOCAL_DELAY_AFTER_CLOSELOOP 0x1d ++#define RADIO_2057_VCOCAL_DELAY_AFTER_OPENLOOP 0x1e ++#define RADIO_2057_VCOCAL_DELAY_BEFORE_OPENLOOP 0x1f ++#define RADIO_2057_VCO_FORCECAPEN_FORCECAP1 0x20 ++#define RADIO_2057_VCO_FORCECAP0 0x21 ++#define RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE 0x22 ++#define RADIO_2057_RFPLL_PFD_RESET_PW 0x23 ++#define RADIO_2057_RFPLL_LOOPFILTER_R2 0x24 ++#define RADIO_2057_RFPLL_LOOPFILTER_R1 0x25 ++#define RADIO_2057_RFPLL_LOOPFILTER_C3 0x26 ++#define RADIO_2057_RFPLL_LOOPFILTER_C2 0x27 ++#define RADIO_2057_RFPLL_LOOPFILTER_C1 0x28 ++#define RADIO_2057_CP_KPD_IDAC 0x29 ++#define RADIO_2057_RFPLL_IDACS 0x2a ++#define RADIO_2057_RFPLL_MISC_EN 0x2b ++#define RADIO_2057_RFPLL_MMD0 0x2c ++#define RADIO_2057_RFPLL_MMD1 0x2d ++#define RADIO_2057_RFPLL_MISC_CAL_RESETN 0x2e ++#define RADIO_2057_JTAGXTAL_SIZE_CPBIAS_FILTRES 0x2f ++#define RADIO_2057_VCO_ALCREF_BBPLLXTAL_SIZE 0x30 ++#define RADIO_2057_VCOCAL_READCAP0 0x31 ++#define RADIO_2057_VCOCAL_READCAP1 0x32 ++#define RADIO_2057_VCOCAL_STATUS 0x33 ++#define RADIO_2057_LOGEN_PUS 0x34 ++#define RADIO_2057_LOGEN_PTAT_RESETS 0x35 ++#define RADIO_2057_VCOBUF_IDACS 0x36 ++#define RADIO_2057_VCOBUF_TUNE 0x37 ++#define RADIO_2057_CMOSBUF_TX2GQ_IDACS 0x38 ++#define RADIO_2057_CMOSBUF_TX2GI_IDACS 0x39 ++#define RADIO_2057_CMOSBUF_TX5GQ_IDACS 0x3a ++#define RADIO_2057_CMOSBUF_TX5GI_IDACS 0x3b ++#define RADIO_2057_CMOSBUF_RX2GQ_IDACS 0x3c ++#define RADIO_2057_CMOSBUF_RX2GI_IDACS 0x3d ++#define RADIO_2057_CMOSBUF_RX5GQ_IDACS 0x3e ++#define RADIO_2057_CMOSBUF_RX5GI_IDACS 0x3f ++#define RADIO_2057_LOGEN_MX2G_IDACS 0x40 ++#define RADIO_2057_LOGEN_MX2G_TUNE 0x41 ++#define RADIO_2057_LOGEN_MX5G_IDACS 0x42 ++#define RADIO_2057_LOGEN_MX5G_TUNE 0x43 ++#define RADIO_2057_LOGEN_MX5G_RCCR 0x44 ++#define RADIO_2057_LOGEN_INDBUF2G_IDAC 0x45 ++#define RADIO_2057_LOGEN_INDBUF2G_IBOOST 0x46 ++#define RADIO_2057_LOGEN_INDBUF2G_TUNE 0x47 ++#define RADIO_2057_LOGEN_INDBUF5G_IDAC 0x48 ++#define RADIO_2057_LOGEN_INDBUF5G_IBOOST 0x49 ++#define RADIO_2057_LOGEN_INDBUF5G_TUNE 0x4a ++#define RADIO_2057_CMOSBUF_TX_RCCR 0x4b ++#define RADIO_2057_CMOSBUF_RX_RCCR 0x4c ++#define RADIO_2057_LOGEN_SEL_PKDET 0x4d ++#define RADIO_2057_CMOSBUF_SHAREIQ_PTAT 0x4e ++#define RADIO_2057_RXTXBIAS_CONFIG_CORE0 0x4f ++#define RADIO_2057_TXGM_TXRF_PUS_CORE0 0x50 ++#define RADIO_2057_TXGM_IDAC_BLEED_CORE0 0x51 ++#define RADIO_2057_TXGM_GAIN_CORE0 0x56 ++#define RADIO_2057_TXGM2G_PKDET_PUS_CORE0 0x57 ++#define RADIO_2057_PAD2G_PTATS_CORE0 0x58 ++#define RADIO_2057_PAD2G_IDACS_CORE0 0x59 ++#define RADIO_2057_PAD2G_BOOST_PU_CORE0 0x5a ++#define RADIO_2057_PAD2G_CASCV_GAIN_CORE0 0x5b ++#define RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0 0x5c ++#define RADIO_2057_TXMIX2G_LODC_CORE0 0x5d ++#define RADIO_2057_PAD2G_TUNE_PUS_CORE0 0x5e ++#define RADIO_2057_IPA2G_GAIN_CORE0 0x5f ++#define RADIO_2057_TSSI2G_SPARE1_CORE0 0x60 ++#define RADIO_2057_TSSI2G_SPARE2_CORE0 0x61 ++#define RADIO_2057_IPA2G_TUNEV_CASCV_PTAT_CORE0 0x62 ++#define RADIO_2057_IPA2G_IMAIN_CORE0 0x63 ++#define RADIO_2057_IPA2G_CASCONV_CORE0 0x64 ++#define RADIO_2057_IPA2G_CASCOFFV_CORE0 0x65 ++#define RADIO_2057_IPA2G_BIAS_FILTER_CORE0 0x66 ++#define RADIO_2057_TX5G_PKDET_CORE0 0x69 ++#define RADIO_2057_PGA_PTAT_TXGM5G_PU_CORE0 0x6a ++#define RADIO_2057_PAD5G_PTATS1_CORE0 0x6b ++#define RADIO_2057_PAD5G_CLASS_PTATS2_CORE0 0x6c ++#define RADIO_2057_PGA_BOOSTPTAT_IMAIN_CORE0 0x6d ++#define RADIO_2057_PAD5G_CASCV_IMAIN_CORE0 0x6e ++#define RADIO_2057_TXMIX5G_IBOOST_PAD_IAUX_CORE0 0x6f ++#define RADIO_2057_PGA_BOOST_TUNE_CORE0 0x70 ++#define RADIO_2057_PGA_GAIN_CORE0 0x71 ++#define RADIO_2057_PAD5G_CASCOFFV_GAIN_PUS_CORE0 0x72 ++#define RADIO_2057_TXMIX5G_BOOST_TUNE_CORE0 0x73 ++#define RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE0 0x74 ++#define RADIO_2057_IPA5G_IAUX_CORE0 0x75 ++#define RADIO_2057_IPA5G_GAIN_CORE0 0x76 ++#define RADIO_2057_TSSI5G_SPARE1_CORE0 0x77 ++#define RADIO_2057_TSSI5G_SPARE2_CORE0 0x78 ++#define RADIO_2057_IPA5G_CASCOFFV_PU_CORE0 0x79 ++#define RADIO_2057_IPA5G_PTAT_CORE0 0x7a ++#define RADIO_2057_IPA5G_IMAIN_CORE0 0x7b ++#define RADIO_2057_IPA5G_CASCONV_CORE0 0x7c ++#define RADIO_2057_IPA5G_BIAS_FILTER_CORE0 0x7d ++#define RADIO_2057_PAD_BIAS_FILTER_BWS_CORE0 0x80 ++#define RADIO_2057_TR2G_CONFIG1_CORE0_NU 0x81 ++#define RADIO_2057_TR2G_CONFIG2_CORE0_NU 0x82 ++#define RADIO_2057_LNA5G_RFEN_CORE0 0x83 ++#define RADIO_2057_TR5G_CONFIG2_CORE0_NU 0x84 ++#define RADIO_2057_RXRFBIAS_IBOOST_PU_CORE0 0x85 ++#define RADIO_2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE0 0x86 ++#define RADIO_2057_RXGM_CMFBITAIL_AUXPTAT_CORE0 0x87 ++#define RADIO_2057_RXMIX_ICORE_RXGM_IAUX_CORE0 0x88 ++#define RADIO_2057_RXMIX_CMFBITAIL_PU_CORE0 0x89 ++#define RADIO_2057_LNA2_IMAIN_PTAT_PU_CORE0 0x8a ++#define RADIO_2057_LNA2_IAUX_PTAT_CORE0 0x8b ++#define RADIO_2057_LNA1_IMAIN_PTAT_PU_CORE0 0x8c ++#define RADIO_2057_LNA15G_INPUT_MATCH_TUNE_CORE0 0x8d ++#define RADIO_2057_RXRFBIAS_BANDSEL_CORE0 0x8e ++#define RADIO_2057_TIA_CONFIG_CORE0 0x8f ++#define RADIO_2057_TIA_IQGAIN_CORE0 0x90 ++#define RADIO_2057_TIA_IBIAS2_CORE0 0x91 ++#define RADIO_2057_TIA_IBIAS1_CORE0 0x92 ++#define RADIO_2057_TIA_SPARE_Q_CORE0 0x93 ++#define RADIO_2057_TIA_SPARE_I_CORE0 0x94 ++#define RADIO_2057_RXMIX2G_PUS_CORE0 0x95 ++#define RADIO_2057_RXMIX2G_VCMREFS_CORE0 0x96 ++#define RADIO_2057_RXMIX2G_LODC_QI_CORE0 0x97 ++#define RADIO_2057_W12G_BW_LNA2G_PUS_CORE0 0x98 ++#define RADIO_2057_LNA2G_GAIN_CORE0 0x99 ++#define RADIO_2057_LNA2G_TUNE_CORE0 0x9a ++#define RADIO_2057_RXMIX5G_PUS_CORE0 0x9b ++#define RADIO_2057_RXMIX5G_VCMREFS_CORE0 0x9c ++#define RADIO_2057_RXMIX5G_LODC_QI_CORE0 0x9d ++#define RADIO_2057_W15G_BW_LNA5G_PUS_CORE0 0x9e ++#define RADIO_2057_LNA5G_GAIN_CORE0 0x9f ++#define RADIO_2057_LNA5G_TUNE_CORE0 0xa0 ++#define RADIO_2057_LPFSEL_TXRX_RXBB_PUS_CORE0 0xa1 ++#define RADIO_2057_RXBB_BIAS_MASTER_CORE0 0xa2 ++#define RADIO_2057_RXBB_VGABUF_IDACS_CORE0 0xa3 ++#define RADIO_2057_LPF_VCMREF_TXBUF_VCMREF_CORE0 0xa4 ++#define RADIO_2057_TXBUF_VINCM_CORE0 0xa5 ++#define RADIO_2057_TXBUF_IDACS_CORE0 0xa6 ++#define RADIO_2057_LPF_RESP_RXBUF_BW_CORE0 0xa7 ++#define RADIO_2057_RXBB_CC_CORE0 0xa8 ++#define RADIO_2057_RXBB_SPARE3_CORE0 0xa9 ++#define RADIO_2057_RXBB_RCCAL_HPC_CORE0 0xaa ++#define RADIO_2057_LPF_IDACS_CORE0 0xab ++#define RADIO_2057_LPFBYP_DCLOOP_BYP_IDAC_CORE0 0xac ++#define RADIO_2057_TXBUF_GAIN_CORE0 0xad ++#define RADIO_2057_AFELOOPBACK_AACI_RESP_CORE0 0xae ++#define RADIO_2057_RXBUF_DEGEN_CORE0 0xaf ++#define RADIO_2057_RXBB_SPARE2_CORE0 0xb0 ++#define RADIO_2057_RXBB_SPARE1_CORE0 0xb1 ++#define RADIO_2057_RSSI_MASTER_CORE0 0xb2 ++#define RADIO_2057_W2_MASTER_CORE0 0xb3 ++#define RADIO_2057_NB_MASTER_CORE0 0xb4 ++#define RADIO_2057_W2_IDACS0_Q_CORE0 0xb5 ++#define RADIO_2057_W2_IDACS1_Q_CORE0 0xb6 ++#define RADIO_2057_W2_IDACS0_I_CORE0 0xb7 ++#define RADIO_2057_W2_IDACS1_I_CORE0 0xb8 ++#define RADIO_2057_RSSI_GPAIOSEL_W1_IDACS_CORE0 0xb9 ++#define RADIO_2057_NB_IDACS_Q_CORE0 0xba ++#define RADIO_2057_NB_IDACS_I_CORE0 0xbb ++#define RADIO_2057_BACKUP4_CORE0 0xc1 ++#define RADIO_2057_BACKUP3_CORE0 0xc2 ++#define RADIO_2057_BACKUP2_CORE0 0xc3 ++#define RADIO_2057_BACKUP1_CORE0 0xc4 ++#define RADIO_2057_SPARE16_CORE0 0xc5 ++#define RADIO_2057_SPARE15_CORE0 0xc6 ++#define RADIO_2057_SPARE14_CORE0 0xc7 ++#define RADIO_2057_SPARE13_CORE0 0xc8 ++#define RADIO_2057_SPARE12_CORE0 0xc9 ++#define RADIO_2057_SPARE11_CORE0 0xca ++#define RADIO_2057_TX2G_BIAS_RESETS_CORE0 0xcb ++#define RADIO_2057_TX5G_BIAS_RESETS_CORE0 0xcc ++#define RADIO_2057_IQTEST_SEL_PU 0xcd ++#define RADIO_2057_XTAL_CONFIG2 0xce ++#define RADIO_2057_BUFS_MISC_LPFBW_CORE0 0xcf ++#define RADIO_2057_TXLPF_RCCAL_CORE0 0xd0 ++#define RADIO_2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0xd1 ++#define RADIO_2057_LPF_GAIN_CORE0 0xd2 ++#define RADIO_2057_DACBUF_IDACS_BW_CORE0 0xd3 ++#define RADIO_2057_RXTXBIAS_CONFIG_CORE1 0xd4 ++#define RADIO_2057_TXGM_TXRF_PUS_CORE1 0xd5 ++#define RADIO_2057_TXGM_IDAC_BLEED_CORE1 0xd6 ++#define RADIO_2057_TXGM_GAIN_CORE1 0xdb ++#define RADIO_2057_TXGM2G_PKDET_PUS_CORE1 0xdc ++#define RADIO_2057_PAD2G_PTATS_CORE1 0xdd ++#define RADIO_2057_PAD2G_IDACS_CORE1 0xde ++#define RADIO_2057_PAD2G_BOOST_PU_CORE1 0xdf ++#define RADIO_2057_PAD2G_CASCV_GAIN_CORE1 0xe0 ++#define RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1 0xe1 ++#define RADIO_2057_TXMIX2G_LODC_CORE1 0xe2 ++#define RADIO_2057_PAD2G_TUNE_PUS_CORE1 0xe3 ++#define RADIO_2057_IPA2G_GAIN_CORE1 0xe4 ++#define RADIO_2057_TSSI2G_SPARE1_CORE1 0xe5 ++#define RADIO_2057_TSSI2G_SPARE2_CORE1 0xe6 ++#define RADIO_2057_IPA2G_TUNEV_CASCV_PTAT_CORE1 0xe7 ++#define RADIO_2057_IPA2G_IMAIN_CORE1 0xe8 ++#define RADIO_2057_IPA2G_CASCONV_CORE1 0xe9 ++#define RADIO_2057_IPA2G_CASCOFFV_CORE1 0xea ++#define RADIO_2057_IPA2G_BIAS_FILTER_CORE1 0xeb ++#define RADIO_2057_TX5G_PKDET_CORE1 0xee ++#define RADIO_2057_PGA_PTAT_TXGM5G_PU_CORE1 0xef ++#define RADIO_2057_PAD5G_PTATS1_CORE1 0xf0 ++#define RADIO_2057_PAD5G_CLASS_PTATS2_CORE1 0xf1 ++#define RADIO_2057_PGA_BOOSTPTAT_IMAIN_CORE1 0xf2 ++#define RADIO_2057_PAD5G_CASCV_IMAIN_CORE1 0xf3 ++#define RADIO_2057_TXMIX5G_IBOOST_PAD_IAUX_CORE1 0xf4 ++#define RADIO_2057_PGA_BOOST_TUNE_CORE1 0xf5 ++#define RADIO_2057_PGA_GAIN_CORE1 0xf6 ++#define RADIO_2057_PAD5G_CASCOFFV_GAIN_PUS_CORE1 0xf7 ++#define RADIO_2057_TXMIX5G_BOOST_TUNE_CORE1 0xf8 ++#define RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE1 0xf9 ++#define RADIO_2057_IPA5G_IAUX_CORE1 0xfa ++#define RADIO_2057_IPA5G_GAIN_CORE1 0xfb ++#define RADIO_2057_TSSI5G_SPARE1_CORE1 0xfc ++#define RADIO_2057_TSSI5G_SPARE2_CORE1 0xfd ++#define RADIO_2057_IPA5G_CASCOFFV_PU_CORE1 0xfe ++#define RADIO_2057_IPA5G_PTAT_CORE1 0xff ++#define RADIO_2057_IPA5G_IMAIN_CORE1 0x100 ++#define RADIO_2057_IPA5G_CASCONV_CORE1 0x101 ++#define RADIO_2057_IPA5G_BIAS_FILTER_CORE1 0x102 ++#define RADIO_2057_PAD_BIAS_FILTER_BWS_CORE1 0x105 ++#define RADIO_2057_TR2G_CONFIG1_CORE1_NU 0x106 ++#define RADIO_2057_TR2G_CONFIG2_CORE1_NU 0x107 ++#define RADIO_2057_LNA5G_RFEN_CORE1 0x108 ++#define RADIO_2057_TR5G_CONFIG2_CORE1_NU 0x109 ++#define RADIO_2057_RXRFBIAS_IBOOST_PU_CORE1 0x10a ++#define RADIO_2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE1 0x10b ++#define RADIO_2057_RXGM_CMFBITAIL_AUXPTAT_CORE1 0x10c ++#define RADIO_2057_RXMIX_ICORE_RXGM_IAUX_CORE1 0x10d ++#define RADIO_2057_RXMIX_CMFBITAIL_PU_CORE1 0x10e ++#define RADIO_2057_LNA2_IMAIN_PTAT_PU_CORE1 0x10f ++#define RADIO_2057_LNA2_IAUX_PTAT_CORE1 0x110 ++#define RADIO_2057_LNA1_IMAIN_PTAT_PU_CORE1 0x111 ++#define RADIO_2057_LNA15G_INPUT_MATCH_TUNE_CORE1 0x112 ++#define RADIO_2057_RXRFBIAS_BANDSEL_CORE1 0x113 ++#define RADIO_2057_TIA_CONFIG_CORE1 0x114 ++#define RADIO_2057_TIA_IQGAIN_CORE1 0x115 ++#define RADIO_2057_TIA_IBIAS2_CORE1 0x116 ++#define RADIO_2057_TIA_IBIAS1_CORE1 0x117 ++#define RADIO_2057_TIA_SPARE_Q_CORE1 0x118 ++#define RADIO_2057_TIA_SPARE_I_CORE1 0x119 ++#define RADIO_2057_RXMIX2G_PUS_CORE1 0x11a ++#define RADIO_2057_RXMIX2G_VCMREFS_CORE1 0x11b ++#define RADIO_2057_RXMIX2G_LODC_QI_CORE1 0x11c ++#define RADIO_2057_W12G_BW_LNA2G_PUS_CORE1 0x11d ++#define RADIO_2057_LNA2G_GAIN_CORE1 0x11e ++#define RADIO_2057_LNA2G_TUNE_CORE1 0x11f ++#define RADIO_2057_RXMIX5G_PUS_CORE1 0x120 ++#define RADIO_2057_RXMIX5G_VCMREFS_CORE1 0x121 ++#define RADIO_2057_RXMIX5G_LODC_QI_CORE1 0x122 ++#define RADIO_2057_W15G_BW_LNA5G_PUS_CORE1 0x123 ++#define RADIO_2057_LNA5G_GAIN_CORE1 0x124 ++#define RADIO_2057_LNA5G_TUNE_CORE1 0x125 ++#define RADIO_2057_LPFSEL_TXRX_RXBB_PUS_CORE1 0x126 ++#define RADIO_2057_RXBB_BIAS_MASTER_CORE1 0x127 ++#define RADIO_2057_RXBB_VGABUF_IDACS_CORE1 0x128 ++#define RADIO_2057_LPF_VCMREF_TXBUF_VCMREF_CORE1 0x129 ++#define RADIO_2057_TXBUF_VINCM_CORE1 0x12a ++#define RADIO_2057_TXBUF_IDACS_CORE1 0x12b ++#define RADIO_2057_LPF_RESP_RXBUF_BW_CORE1 0x12c ++#define RADIO_2057_RXBB_CC_CORE1 0x12d ++#define RADIO_2057_RXBB_SPARE3_CORE1 0x12e ++#define RADIO_2057_RXBB_RCCAL_HPC_CORE1 0x12f ++#define RADIO_2057_LPF_IDACS_CORE1 0x130 ++#define RADIO_2057_LPFBYP_DCLOOP_BYP_IDAC_CORE1 0x131 ++#define RADIO_2057_TXBUF_GAIN_CORE1 0x132 ++#define RADIO_2057_AFELOOPBACK_AACI_RESP_CORE1 0x133 ++#define RADIO_2057_RXBUF_DEGEN_CORE1 0x134 ++#define RADIO_2057_RXBB_SPARE2_CORE1 0x135 ++#define RADIO_2057_RXBB_SPARE1_CORE1 0x136 ++#define RADIO_2057_RSSI_MASTER_CORE1 0x137 ++#define RADIO_2057_W2_MASTER_CORE1 0x138 ++#define RADIO_2057_NB_MASTER_CORE1 0x139 ++#define RADIO_2057_W2_IDACS0_Q_CORE1 0x13a ++#define RADIO_2057_W2_IDACS1_Q_CORE1 0x13b ++#define RADIO_2057_W2_IDACS0_I_CORE1 0x13c ++#define RADIO_2057_W2_IDACS1_I_CORE1 0x13d ++#define RADIO_2057_RSSI_GPAIOSEL_W1_IDACS_CORE1 0x13e ++#define RADIO_2057_NB_IDACS_Q_CORE1 0x13f ++#define RADIO_2057_NB_IDACS_I_CORE1 0x140 ++#define RADIO_2057_BACKUP4_CORE1 0x146 ++#define RADIO_2057_BACKUP3_CORE1 0x147 ++#define RADIO_2057_BACKUP2_CORE1 0x148 ++#define RADIO_2057_BACKUP1_CORE1 0x149 ++#define RADIO_2057_SPARE16_CORE1 0x14a ++#define RADIO_2057_SPARE15_CORE1 0x14b ++#define RADIO_2057_SPARE14_CORE1 0x14c ++#define RADIO_2057_SPARE13_CORE1 0x14d ++#define RADIO_2057_SPARE12_CORE1 0x14e ++#define RADIO_2057_SPARE11_CORE1 0x14f ++#define RADIO_2057_TX2G_BIAS_RESETS_CORE1 0x150 ++#define RADIO_2057_TX5G_BIAS_RESETS_CORE1 0x151 ++#define RADIO_2057_SPARE8_CORE1 0x152 ++#define RADIO_2057_SPARE7_CORE1 0x153 ++#define RADIO_2057_BUFS_MISC_LPFBW_CORE1 0x154 ++#define RADIO_2057_TXLPF_RCCAL_CORE1 0x155 ++#define RADIO_2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156 ++#define RADIO_2057_LPF_GAIN_CORE1 0x157 ++#define RADIO_2057_DACBUF_IDACS_BW_CORE1 0x158 ++#define RADIO_2057_DACBUF_VINCM_CORE1 0x159 ++#define RADIO_2057_RCCAL_START_R1_Q1_P1 0x15a ++#define RADIO_2057_RCCAL_X1 0x15b ++#define RADIO_2057_RCCAL_TRC0 0x15c ++#define RADIO_2057_RCCAL_TRC1 0x15d ++#define RADIO_2057_RCCAL_DONE_OSCCAP 0x15e ++#define RADIO_2057_RCCAL_N0_0 0x15f ++#define RADIO_2057_RCCAL_N0_1 0x160 ++#define RADIO_2057_RCCAL_N1_0 0x161 ++#define RADIO_2057_RCCAL_N1_1 0x162 ++#define RADIO_2057_RCAL_STATUS 0x163 ++#define RADIO_2057_XTALPUOVR_PINCTRL 0x164 ++#define RADIO_2057_OVR_REG0 0x165 ++#define RADIO_2057_OVR_REG1 0x166 ++#define RADIO_2057_OVR_REG2 0x167 ++#define RADIO_2057_OVR_REG3 0x168 ++#define RADIO_2057_OVR_REG4 0x169 ++#define RADIO_2057_RCCAL_SCAP_VAL 0x16a ++#define RADIO_2057_RCCAL_BCAP_VAL 0x16b ++#define RADIO_2057_RCCAL_HPC_VAL 0x16c ++#define RADIO_2057_RCCAL_OVERRIDES 0x16d ++#define RADIO_2057_TX0_IQCAL_GAIN_BW 0x170 ++#define RADIO_2057_TX0_LOFT_FINE_I 0x171 ++#define RADIO_2057_TX0_LOFT_FINE_Q 0x172 ++#define RADIO_2057_TX0_LOFT_COARSE_I 0x173 ++#define RADIO_2057_TX0_LOFT_COARSE_Q 0x174 ++#define RADIO_2057_TX0_TX_SSI_MASTER 0x175 ++#define RADIO_2057_TX0_IQCAL_VCM_HG 0x176 ++#define RADIO_2057_TX0_IQCAL_IDAC 0x177 ++#define RADIO_2057_TX0_TSSI_VCM 0x178 ++#define RADIO_2057_TX0_TX_SSI_MUX 0x179 ++#define RADIO_2057_TX0_TSSIA 0x17a ++#define RADIO_2057_TX0_TSSIG 0x17b ++#define RADIO_2057_TX0_TSSI_MISC1 0x17c ++#define RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN 0x17d ++#define RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP 0x17e ++#define RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN 0x17f ++#define RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP 0x180 ++#define RADIO_2057_TX1_IQCAL_GAIN_BW 0x190 ++#define RADIO_2057_TX1_LOFT_FINE_I 0x191 ++#define RADIO_2057_TX1_LOFT_FINE_Q 0x192 ++#define RADIO_2057_TX1_LOFT_COARSE_I 0x193 ++#define RADIO_2057_TX1_LOFT_COARSE_Q 0x194 ++#define RADIO_2057_TX1_TX_SSI_MASTER 0x195 ++#define RADIO_2057_TX1_IQCAL_VCM_HG 0x196 ++#define RADIO_2057_TX1_IQCAL_IDAC 0x197 ++#define RADIO_2057_TX1_TSSI_VCM 0x198 ++#define RADIO_2057_TX1_TX_SSI_MUX 0x199 ++#define RADIO_2057_TX1_TSSIA 0x19a ++#define RADIO_2057_TX1_TSSIG 0x19b ++#define RADIO_2057_TX1_TSSI_MISC1 0x19c ++#define RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN 0x19d ++#define RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP 0x19e ++#define RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN 0x19f ++#define RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP 0x1a0 ++#define RADIO_2057_AFE_VCM_CAL_MASTER_CORE0 0x1a1 ++#define RADIO_2057_AFE_SET_VCM_I_CORE0 0x1a2 ++#define RADIO_2057_AFE_SET_VCM_Q_CORE0 0x1a3 ++#define RADIO_2057_AFE_STATUS_VCM_IQADC_CORE0 0x1a4 ++#define RADIO_2057_AFE_STATUS_VCM_I_CORE0 0x1a5 ++#define RADIO_2057_AFE_STATUS_VCM_Q_CORE0 0x1a6 ++#define RADIO_2057_AFE_VCM_CAL_MASTER_CORE1 0x1a7 ++#define RADIO_2057_AFE_SET_VCM_I_CORE1 0x1a8 ++#define RADIO_2057_AFE_SET_VCM_Q_CORE1 0x1a9 ++#define RADIO_2057_AFE_STATUS_VCM_IQADC_CORE1 0x1aa ++#define RADIO_2057_AFE_STATUS_VCM_I_CORE1 0x1ab ++#define RADIO_2057_AFE_STATUS_VCM_Q_CORE1 0x1ac ++ ++#define RADIO_2057v7_DACBUF_VINCM_CORE0 0x1ad ++#define RADIO_2057v7_RCCAL_MASTER 0x1ae ++#define RADIO_2057v7_TR2G_CONFIG3_CORE0_NU 0x1af ++#define RADIO_2057v7_TR2G_CONFIG3_CORE1_NU 0x1b0 ++#define RADIO_2057v7_LOGEN_PUS1 0x1b1 ++#define RADIO_2057v7_OVR_REG5 0x1b2 ++#define RADIO_2057v7_OVR_REG6 0x1b3 ++#define RADIO_2057v7_OVR_REG7 0x1b4 ++#define RADIO_2057v7_OVR_REG8 0x1b5 ++#define RADIO_2057v7_OVR_REG9 0x1b6 ++#define RADIO_2057v7_OVR_REG10 0x1b7 ++#define RADIO_2057v7_OVR_REG11 0x1b8 ++#define RADIO_2057v7_OVR_REG12 0x1b9 ++#define RADIO_2057v7_OVR_REG13 0x1ba ++#define RADIO_2057v7_OVR_REG14 0x1bb ++#define RADIO_2057v7_OVR_REG15 0x1bc ++#define RADIO_2057v7_OVR_REG16 0x1bd ++#define RADIO_2057v7_OVR_REG1 0x1be ++#define RADIO_2057v7_OVR_REG18 0x1bf ++#define RADIO_2057v7_OVR_REG19 0x1c0 ++#define RADIO_2057v7_OVR_REG20 0x1c1 ++#define RADIO_2057v7_OVR_REG21 0x1c2 ++#define RADIO_2057v7_OVR_REG2 0x1c3 ++#define RADIO_2057v7_OVR_REG23 0x1c4 ++#define RADIO_2057v7_OVR_REG24 0x1c5 ++#define RADIO_2057v7_OVR_REG25 0x1c6 ++#define RADIO_2057v7_OVR_REG26 0x1c7 ++#define RADIO_2057v7_OVR_REG27 0x1c8 ++#define RADIO_2057v7_OVR_REG28 0x1c9 ++#define RADIO_2057v7_IQTEST_SEL_PU2 0x1ca ++ ++#define RADIO_2057_VCM_MASK 0x7 ++ ++#endif /* _BRCM_PHY_RADIO_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phyreg_n.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phyreg_n.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phyreg_n.h.orig 2011-11-09 13:46:58.277800233 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phyreg_n.h 2011-11-09 13:47:17.035565729 -0500 +@@ -0,0 +1,167 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#define NPHY_TBL_ID_GAIN1 0 ++#define NPHY_TBL_ID_GAIN2 1 ++#define NPHY_TBL_ID_GAINBITS1 2 ++#define NPHY_TBL_ID_GAINBITS2 3 ++#define NPHY_TBL_ID_GAINLIMIT 4 ++#define NPHY_TBL_ID_WRSSIGainLimit 5 ++#define NPHY_TBL_ID_RFSEQ 7 ++#define NPHY_TBL_ID_AFECTRL 8 ++#define NPHY_TBL_ID_ANTSWCTRLLUT 9 ++#define NPHY_TBL_ID_IQLOCAL 15 ++#define NPHY_TBL_ID_NOISEVAR 16 ++#define NPHY_TBL_ID_SAMPLEPLAY 17 ++#define NPHY_TBL_ID_CORE1TXPWRCTL 26 ++#define NPHY_TBL_ID_CORE2TXPWRCTL 27 ++#define NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL 30 ++ ++#define NPHY_TBL_ID_EPSILONTBL0 31 ++#define NPHY_TBL_ID_SCALARTBL0 32 ++#define NPHY_TBL_ID_EPSILONTBL1 33 ++#define NPHY_TBL_ID_SCALARTBL1 34 ++ ++#define NPHY_TO_BPHY_OFF 0xc00 ++ ++#define NPHY_BandControl_currentBand 0x0001 ++#define RFCC_CHIP0_PU 0x0400 ++#define RFCC_POR_FORCE 0x0040 ++#define RFCC_OE_POR_FORCE 0x0080 ++#define NPHY_RfctrlIntc_override_OFF 0 ++#define NPHY_RfctrlIntc_override_TRSW 1 ++#define NPHY_RfctrlIntc_override_PA 2 ++#define NPHY_RfctrlIntc_override_EXT_LNA_PU 3 ++#define NPHY_RfctrlIntc_override_EXT_LNA_GAIN 4 ++#define RIFS_ENABLE 0x80 ++#define BPHY_BAND_SEL_UP20 0x10 ++#define NPHY_MLenable 0x02 ++ ++#define NPHY_RfseqMode_CoreActv_override 0x0001 ++#define NPHY_RfseqMode_Trigger_override 0x0002 ++#define NPHY_RfseqCoreActv_TxRxChain0 (0x11) ++#define NPHY_RfseqCoreActv_TxRxChain1 (0x22) ++ ++#define NPHY_RfseqTrigger_rx2tx 0x0001 ++#define NPHY_RfseqTrigger_tx2rx 0x0002 ++#define NPHY_RfseqTrigger_updategainh 0x0004 ++#define NPHY_RfseqTrigger_updategainl 0x0008 ++#define NPHY_RfseqTrigger_updategainu 0x0010 ++#define NPHY_RfseqTrigger_reset2rx 0x0020 ++#define NPHY_RfseqStatus_rx2tx 0x0001 ++#define NPHY_RfseqStatus_tx2rx 0x0002 ++#define NPHY_RfseqStatus_updategainh 0x0004 ++#define NPHY_RfseqStatus_updategainl 0x0008 ++#define NPHY_RfseqStatus_updategainu 0x0010 ++#define NPHY_RfseqStatus_reset2rx 0x0020 ++#define NPHY_ClassifierCtrl_cck_en 0x1 ++#define NPHY_ClassifierCtrl_ofdm_en 0x2 ++#define NPHY_ClassifierCtrl_waited_en 0x4 ++#define NPHY_IQFlip_ADC1 0x0001 ++#define NPHY_IQFlip_ADC2 0x0010 ++#define NPHY_sampleCmd_STOP 0x0002 ++ ++#define RX_GF_OR_MM 0x0004 ++#define RX_GF_MM_AUTO 0x0100 ++ ++#define NPHY_iqloCalCmdGctl_IQLO_CAL_EN 0x8000 ++ ++#define NPHY_IqestCmd_iqstart 0x1 ++#define NPHY_IqestCmd_iqMode 0x2 ++ ++#define NPHY_TxPwrCtrlCmd_pwrIndex_init 0x40 ++#define NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 0x19 ++ ++#define PRIM_SEL_UP20 0x8000 ++ ++#define NPHY_RFSEQ_RX2TX 0x0 ++#define NPHY_RFSEQ_TX2RX 0x1 ++#define NPHY_RFSEQ_RESET2RX 0x2 ++#define NPHY_RFSEQ_UPDATEGAINH 0x3 ++#define NPHY_RFSEQ_UPDATEGAINL 0x4 ++#define NPHY_RFSEQ_UPDATEGAINU 0x5 ++ ++#define NPHY_RFSEQ_CMD_NOP 0x0 ++#define NPHY_RFSEQ_CMD_RXG_FBW 0x1 ++#define NPHY_RFSEQ_CMD_TR_SWITCH 0x2 ++#define NPHY_RFSEQ_CMD_EXT_PA 0x3 ++#define NPHY_RFSEQ_CMD_RXPD_TXPD 0x4 ++#define NPHY_RFSEQ_CMD_TX_GAIN 0x5 ++#define NPHY_RFSEQ_CMD_RX_GAIN 0x6 ++#define NPHY_RFSEQ_CMD_SET_HPF_BW 0x7 ++#define NPHY_RFSEQ_CMD_CLR_HIQ_DIS 0x8 ++#define NPHY_RFSEQ_CMD_END 0xf ++ ++#define NPHY_REV3_RFSEQ_CMD_NOP 0x0 ++#define NPHY_REV3_RFSEQ_CMD_RXG_FBW 0x1 ++#define NPHY_REV3_RFSEQ_CMD_TR_SWITCH 0x2 ++#define NPHY_REV3_RFSEQ_CMD_INT_PA_PU 0x3 ++#define NPHY_REV3_RFSEQ_CMD_EXT_PA 0x4 ++#define NPHY_REV3_RFSEQ_CMD_RXPD_TXPD 0x5 ++#define NPHY_REV3_RFSEQ_CMD_TX_GAIN 0x6 ++#define NPHY_REV3_RFSEQ_CMD_RX_GAIN 0x7 ++#define NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS 0x8 ++#define NPHY_REV3_RFSEQ_CMD_SET_HPF_H_HPC 0x9 ++#define NPHY_REV3_RFSEQ_CMD_SET_LPF_H_HPC 0xa ++#define NPHY_REV3_RFSEQ_CMD_SET_HPF_M_HPC 0xb ++#define NPHY_REV3_RFSEQ_CMD_SET_LPF_M_HPC 0xc ++#define NPHY_REV3_RFSEQ_CMD_SET_HPF_L_HPC 0xd ++#define NPHY_REV3_RFSEQ_CMD_SET_LPF_L_HPC 0xe ++#define NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS 0xf ++#define NPHY_REV3_RFSEQ_CMD_END 0x1f ++ ++#define NPHY_RSSI_SEL_W1 0x0 ++#define NPHY_RSSI_SEL_W2 0x1 ++#define NPHY_RSSI_SEL_NB 0x2 ++#define NPHY_RSSI_SEL_IQ 0x3 ++#define NPHY_RSSI_SEL_TSSI_2G 0x4 ++#define NPHY_RSSI_SEL_TSSI_5G 0x5 ++#define NPHY_RSSI_SEL_TBD 0x6 ++ ++#define NPHY_RAIL_I 0x0 ++#define NPHY_RAIL_Q 0x1 ++ ++#define NPHY_FORCESIG_DECODEGATEDCLKS 0x8 ++ ++#define NPHY_REV7_RfctrlOverride_cmd_rxrf_pu 0x0 ++#define NPHY_REV7_RfctrlOverride_cmd_rx_pu 0x1 ++#define NPHY_REV7_RfctrlOverride_cmd_tx_pu 0x2 ++#define NPHY_REV7_RfctrlOverride_cmd_rxgain 0x3 ++#define NPHY_REV7_RfctrlOverride_cmd_txgain 0x4 ++ ++#define NPHY_REV7_RXGAINCODE_RFMXGAIN_MASK 0x000ff ++#define NPHY_REV7_RXGAINCODE_LPFGAIN_MASK 0x0ff00 ++#define NPHY_REV7_RXGAINCODE_DVGAGAIN_MASK 0xf0000 ++ ++#define NPHY_REV7_TXGAINCODE_TGAIN_MASK 0x7fff ++#define NPHY_REV7_TXGAINCODE_LPFGAIN_MASK 0x8000 ++#define NPHY_REV7_TXGAINCODE_BIQ0GAIN_SHIFT 14 ++ ++#define NPHY_REV7_RFCTRLOVERRIDE_ID0 0x0 ++#define NPHY_REV7_RFCTRLOVERRIDE_ID1 0x1 ++#define NPHY_REV7_RFCTRLOVERRIDE_ID2 0x2 ++ ++#define NPHY_IqestIqAccLo(core) ((core == 0) ? 0x12c : 0x134) ++ ++#define NPHY_IqestIqAccHi(core) ((core == 0) ? 0x12d : 0x135) ++ ++#define NPHY_IqestipwrAccLo(core) ((core == 0) ? 0x12e : 0x136) ++ ++#define NPHY_IqestipwrAccHi(core) ((core == 0) ? 0x12f : 0x137) ++ ++#define NPHY_IqestqpwrAccLo(core) ((core == 0) ? 0x130 : 0x138) ++ ++#define NPHY_IqestqpwrAccHi(core) ((core == 0) ? 0x131 : 0x139) +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c.orig 2011-11-09 13:46:58.278800221 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c 2011-11-09 13:47:17.036565717 -0500 +@@ -0,0 +1,3250 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include "phytbl_lcn.h" ++ ++static const u32 dot11lcn_gain_tbl_rev0[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000004, ++ 0x00000000, ++ 0x00000004, ++ 0x00000008, ++ 0x00000001, ++ 0x00000005, ++ 0x00000009, ++ 0x0000000d, ++ 0x0000004d, ++ 0x0000008d, ++ 0x0000000d, ++ 0x0000004d, ++ 0x0000008d, ++ 0x000000cd, ++ 0x0000004f, ++ 0x0000008f, ++ 0x000000cf, ++ 0x000000d3, ++ 0x00000113, ++ 0x00000513, ++ 0x00000913, ++ 0x00000953, ++ 0x00000d53, ++ 0x00001153, ++ 0x00001193, ++ 0x00005193, ++ 0x00009193, ++ 0x0000d193, ++ 0x00011193, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000004, ++ 0x00000000, ++ 0x00000004, ++ 0x00000008, ++ 0x00000001, ++ 0x00000005, ++ 0x00000009, ++ 0x0000000d, ++ 0x0000004d, ++ 0x0000008d, ++ 0x0000000d, ++ 0x0000004d, ++ 0x0000008d, ++ 0x000000cd, ++ 0x0000004f, ++ 0x0000008f, ++ 0x000000cf, ++ 0x000000d3, ++ 0x00000113, ++ 0x00000513, ++ 0x00000913, ++ 0x00000953, ++ 0x00000d53, ++ 0x00001153, ++ 0x00005153, ++ 0x00009153, ++ 0x0000d153, ++ 0x00011153, ++ 0x00015153, ++ 0x00019153, ++ 0x0001d153, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 dot11lcn_gain_tbl_rev1[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000008, ++ 0x00000004, ++ 0x00000008, ++ 0x00000001, ++ 0x00000005, ++ 0x00000009, ++ 0x0000000D, ++ 0x00000011, ++ 0x00000051, ++ 0x00000091, ++ 0x00000011, ++ 0x00000051, ++ 0x00000091, ++ 0x000000d1, ++ 0x00000053, ++ 0x00000093, ++ 0x000000d3, ++ 0x000000d7, ++ 0x00000117, ++ 0x00000517, ++ 0x00000917, ++ 0x00000957, ++ 0x00000d57, ++ 0x00001157, ++ 0x00001197, ++ 0x00005197, ++ 0x00009197, ++ 0x0000d197, ++ 0x00011197, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000008, ++ 0x00000004, ++ 0x00000008, ++ 0x00000001, ++ 0x00000005, ++ 0x00000009, ++ 0x0000000D, ++ 0x00000011, ++ 0x00000051, ++ 0x00000091, ++ 0x00000011, ++ 0x00000051, ++ 0x00000091, ++ 0x000000d1, ++ 0x00000053, ++ 0x00000093, ++ 0x000000d3, ++ 0x000000d7, ++ 0x00000117, ++ 0x00000517, ++ 0x00000917, ++ 0x00000957, ++ 0x00000d57, ++ 0x00001157, ++ 0x00005157, ++ 0x00009157, ++ 0x0000d157, ++ 0x00011157, ++ 0x00015157, ++ 0x00019157, ++ 0x0001d157, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u16 dot11lcn_aux_gain_idx_tbl_rev0[] = { ++ 0x0401, ++ 0x0402, ++ 0x0403, ++ 0x0404, ++ 0x0405, ++ 0x0406, ++ 0x0407, ++ 0x0408, ++ 0x0409, ++ 0x040a, ++ 0x058b, ++ 0x058c, ++ 0x058d, ++ 0x058e, ++ 0x058f, ++ 0x0090, ++ 0x0091, ++ 0x0092, ++ 0x0193, ++ 0x0194, ++ 0x0195, ++ 0x0196, ++ 0x0197, ++ 0x0198, ++ 0x0199, ++ 0x019a, ++ 0x019b, ++ 0x019c, ++ 0x019d, ++ 0x019e, ++ 0x019f, ++ 0x01a0, ++ 0x01a1, ++ 0x01a2, ++ 0x01a3, ++ 0x01a4, ++ 0x01a5, ++ 0x0000, ++}; ++ ++static const u32 dot11lcn_gain_idx_tbl_rev0[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x10000000, ++ 0x00000000, ++ 0x20000000, ++ 0x00000000, ++ 0x30000000, ++ 0x00000000, ++ 0x40000000, ++ 0x00000000, ++ 0x50000000, ++ 0x00000000, ++ 0x60000000, ++ 0x00000000, ++ 0x70000000, ++ 0x00000000, ++ 0x80000000, ++ 0x00000000, ++ 0x90000000, ++ 0x00000008, ++ 0xa0000000, ++ 0x00000008, ++ 0xb0000000, ++ 0x00000008, ++ 0xc0000000, ++ 0x00000008, ++ 0xd0000000, ++ 0x00000008, ++ 0xe0000000, ++ 0x00000008, ++ 0xf0000000, ++ 0x00000008, ++ 0x00000000, ++ 0x00000009, ++ 0x10000000, ++ 0x00000009, ++ 0x20000000, ++ 0x00000019, ++ 0x30000000, ++ 0x00000019, ++ 0x40000000, ++ 0x00000019, ++ 0x50000000, ++ 0x00000019, ++ 0x60000000, ++ 0x00000019, ++ 0x70000000, ++ 0x00000019, ++ 0x80000000, ++ 0x00000019, ++ 0x90000000, ++ 0x00000019, ++ 0xa0000000, ++ 0x00000019, ++ 0xb0000000, ++ 0x00000019, ++ 0xc0000000, ++ 0x00000019, ++ 0xd0000000, ++ 0x00000019, ++ 0xe0000000, ++ 0x00000019, ++ 0xf0000000, ++ 0x00000019, ++ 0x00000000, ++ 0x0000001a, ++ 0x10000000, ++ 0x0000001a, ++ 0x20000000, ++ 0x0000001a, ++ 0x30000000, ++ 0x0000001a, ++ 0x40000000, ++ 0x0000001a, ++ 0x50000000, ++ 0x00000002, ++ 0x60000000, ++ 0x00000002, ++ 0x70000000, ++ 0x00000002, ++ 0x80000000, ++ 0x00000002, ++ 0x90000000, ++ 0x00000002, ++ 0xa0000000, ++ 0x00000002, ++ 0xb0000000, ++ 0x00000002, ++ 0xc0000000, ++ 0x0000000a, ++ 0xd0000000, ++ 0x0000000a, ++ 0xe0000000, ++ 0x0000000a, ++ 0xf0000000, ++ 0x0000000a, ++ 0x00000000, ++ 0x0000000b, ++ 0x10000000, ++ 0x0000000b, ++ 0x20000000, ++ 0x0000000b, ++ 0x30000000, ++ 0x0000000b, ++ 0x40000000, ++ 0x0000000b, ++ 0x50000000, ++ 0x0000001b, ++ 0x60000000, ++ 0x0000001b, ++ 0x70000000, ++ 0x0000001b, ++ 0x80000000, ++ 0x0000001b, ++ 0x90000000, ++ 0x0000001b, ++ 0xa0000000, ++ 0x0000001b, ++ 0xb0000000, ++ 0x0000001b, ++ 0xc0000000, ++ 0x0000001b, ++ 0xd0000000, ++ 0x0000001b, ++ 0xe0000000, ++ 0x0000001b, ++ 0xf0000000, ++ 0x0000001b, ++ 0x00000000, ++ 0x0000001c, ++ 0x10000000, ++ 0x0000001c, ++ 0x20000000, ++ 0x0000001c, ++ 0x30000000, ++ 0x0000001c, ++ 0x40000000, ++ 0x0000001c, ++ 0x50000000, ++ 0x0000001c, ++ 0x60000000, ++ 0x0000001c, ++ 0x70000000, ++ 0x0000001c, ++ 0x80000000, ++ 0x0000001c, ++ 0x90000000, ++ 0x0000001c, ++}; ++ ++static const u16 dot11lcn_aux_gain_idx_tbl_2G[] = { ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0001, ++ 0x0080, ++ 0x0081, ++ 0x0100, ++ 0x0101, ++ 0x0180, ++ 0x0181, ++ 0x0182, ++ 0x0183, ++ 0x0184, ++ 0x0185, ++ 0x0186, ++ 0x0187, ++ 0x0188, ++ 0x0285, ++ 0x0289, ++ 0x028a, ++ 0x028b, ++ 0x028c, ++ 0x028d, ++ 0x028e, ++ 0x028f, ++ 0x0290, ++ 0x0291, ++ 0x0292, ++ 0x0293, ++ 0x0294, ++ 0x0295, ++ 0x0296, ++ 0x0297, ++ 0x0298, ++ 0x0299, ++ 0x029a, ++ 0x0000 ++}; ++ ++static const u8 dot11lcn_gain_val_tbl_2G[] = { ++ 0xfc, ++ 0x02, ++ 0x08, ++ 0x0e, ++ 0x13, ++ 0x1b, ++ 0xfc, ++ 0x02, ++ 0x08, ++ 0x0e, ++ 0x13, ++ 0x1b, ++ 0xfc, ++ 0x00, ++ 0x0c, ++ 0x03, ++ 0xeb, ++ 0xfe, ++ 0x07, ++ 0x0b, ++ 0x0f, ++ 0xfb, ++ 0xfe, ++ 0x01, ++ 0x05, ++ 0x08, ++ 0x0b, ++ 0x0e, ++ 0x11, ++ 0x14, ++ 0x17, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x15, ++ 0x18, ++ 0x1b, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00 ++}; ++ ++static const u32 dot11lcn_gain_idx_tbl_2G[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x10000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000008, ++ 0x10000000, ++ 0x00000008, ++ 0x00000000, ++ 0x00000010, ++ 0x10000000, ++ 0x00000010, ++ 0x00000000, ++ 0x00000018, ++ 0x10000000, ++ 0x00000018, ++ 0x20000000, ++ 0x00000018, ++ 0x30000000, ++ 0x00000018, ++ 0x40000000, ++ 0x00000018, ++ 0x50000000, ++ 0x00000018, ++ 0x60000000, ++ 0x00000018, ++ 0x70000000, ++ 0x00000018, ++ 0x80000000, ++ 0x00000018, ++ 0x50000000, ++ 0x00000028, ++ 0x90000000, ++ 0x00000028, ++ 0xa0000000, ++ 0x00000028, ++ 0xb0000000, ++ 0x00000028, ++ 0xc0000000, ++ 0x00000028, ++ 0xd0000000, ++ 0x00000028, ++ 0xe0000000, ++ 0x00000028, ++ 0xf0000000, ++ 0x00000028, ++ 0x00000000, ++ 0x00000029, ++ 0x10000000, ++ 0x00000029, ++ 0x20000000, ++ 0x00000029, ++ 0x30000000, ++ 0x00000029, ++ 0x40000000, ++ 0x00000029, ++ 0x50000000, ++ 0x00000029, ++ 0x60000000, ++ 0x00000029, ++ 0x70000000, ++ 0x00000029, ++ 0x80000000, ++ 0x00000029, ++ 0x90000000, ++ 0x00000029, ++ 0xa0000000, ++ 0x00000029, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x10000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000008, ++ 0x10000000, ++ 0x00000008, ++ 0x00000000, ++ 0x00000010, ++ 0x10000000, ++ 0x00000010, ++ 0x00000000, ++ 0x00000018, ++ 0x10000000, ++ 0x00000018, ++ 0x20000000, ++ 0x00000018, ++ 0x30000000, ++ 0x00000018, ++ 0x40000000, ++ 0x00000018, ++ 0x50000000, ++ 0x00000018, ++ 0x60000000, ++ 0x00000018, ++ 0x70000000, ++ 0x00000018, ++ 0x80000000, ++ 0x00000018, ++ 0x50000000, ++ 0x00000028, ++ 0x90000000, ++ 0x00000028, ++ 0xa0000000, ++ 0x00000028, ++ 0xb0000000, ++ 0x00000028, ++ 0xc0000000, ++ 0x00000028, ++ 0xd0000000, ++ 0x00000028, ++ 0xe0000000, ++ 0x00000028, ++ 0xf0000000, ++ 0x00000028, ++ 0x00000000, ++ 0x00000029, ++ 0x10000000, ++ 0x00000029, ++ 0x20000000, ++ 0x00000029, ++ 0x30000000, ++ 0x00000029, ++ 0x40000000, ++ 0x00000029, ++ 0x50000000, ++ 0x00000029, ++ 0x60000000, ++ 0x00000029, ++ 0x70000000, ++ 0x00000029, ++ 0x80000000, ++ 0x00000029, ++ 0x90000000, ++ 0x00000029, ++ 0xa0000000, ++ 0x00000029, ++ 0xb0000000, ++ 0x00000029, ++ 0xc0000000, ++ 0x00000029, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000 ++}; ++ ++static const u32 dot11lcn_gain_tbl_2G[] = { ++ 0x00000000, ++ 0x00000004, ++ 0x00000008, ++ 0x00000001, ++ 0x00000005, ++ 0x00000009, ++ 0x0000000d, ++ 0x0000004d, ++ 0x0000008d, ++ 0x00000049, ++ 0x00000089, ++ 0x000000c9, ++ 0x0000004b, ++ 0x0000008b, ++ 0x000000cb, ++ 0x000000cf, ++ 0x0000010f, ++ 0x0000050f, ++ 0x0000090f, ++ 0x0000094f, ++ 0x00000d4f, ++ 0x0000114f, ++ 0x0000118f, ++ 0x0000518f, ++ 0x0000918f, ++ 0x0000d18f, ++ 0x0001118f, ++ 0x0001518f, ++ 0x0001918f, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000 ++}; ++ ++static const u32 dot11lcn_gain_tbl_extlna_2G[] = { ++ 0x00000000, ++ 0x00000004, ++ 0x00000008, ++ 0x00000001, ++ 0x00000005, ++ 0x00000009, ++ 0x0000000d, ++ 0x00000003, ++ 0x00000007, ++ 0x0000000b, ++ 0x0000000f, ++ 0x0000004f, ++ 0x0000008f, ++ 0x000000cf, ++ 0x0000010f, ++ 0x0000014f, ++ 0x0000018f, ++ 0x0000058f, ++ 0x0000098f, ++ 0x00000d8f, ++ 0x00008000, ++ 0x00008004, ++ 0x00008008, ++ 0x00008001, ++ 0x00008005, ++ 0x00008009, ++ 0x0000800d, ++ 0x00008003, ++ 0x00008007, ++ 0x0000800b, ++ 0x0000800f, ++ 0x0000804f, ++ 0x0000808f, ++ 0x000080cf, ++ 0x0000810f, ++ 0x0000814f, ++ 0x0000818f, ++ 0x0000858f, ++ 0x0000898f, ++ 0x00008d8f, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000 ++}; ++ ++static const u16 dot11lcn_aux_gain_idx_tbl_extlna_2G[] = { ++ 0x0400, ++ 0x0400, ++ 0x0400, ++ 0x0400, ++ 0x0400, ++ 0x0400, ++ 0x0400, ++ 0x0400, ++ 0x0400, ++ 0x0401, ++ 0x0402, ++ 0x0403, ++ 0x0404, ++ 0x0483, ++ 0x0484, ++ 0x0485, ++ 0x0486, ++ 0x0583, ++ 0x0584, ++ 0x0585, ++ 0x0587, ++ 0x0588, ++ 0x0589, ++ 0x058a, ++ 0x0687, ++ 0x0688, ++ 0x0689, ++ 0x068a, ++ 0x068b, ++ 0x068c, ++ 0x068d, ++ 0x068e, ++ 0x068f, ++ 0x0690, ++ 0x0691, ++ 0x0692, ++ 0x0693, ++ 0x0000 ++}; ++ ++static const u8 dot11lcn_gain_val_tbl_extlna_2G[] = { ++ 0xfc, ++ 0x02, ++ 0x08, ++ 0x0e, ++ 0x13, ++ 0x1b, ++ 0xfc, ++ 0x02, ++ 0x08, ++ 0x0e, ++ 0x13, ++ 0x1b, ++ 0xfc, ++ 0x00, ++ 0x0f, ++ 0x03, ++ 0xeb, ++ 0xfe, ++ 0x07, ++ 0x0b, ++ 0x0f, ++ 0xfb, ++ 0xfe, ++ 0x01, ++ 0x05, ++ 0x08, ++ 0x0b, ++ 0x0e, ++ 0x11, ++ 0x14, ++ 0x17, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x15, ++ 0x18, ++ 0x1b, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00 ++}; ++ ++static const u32 dot11lcn_gain_idx_tbl_extlna_2G[] = { ++ 0x00000000, ++ 0x00000040, ++ 0x00000000, ++ 0x00000040, ++ 0x00000000, ++ 0x00000040, ++ 0x00000000, ++ 0x00000040, ++ 0x00000000, ++ 0x00000040, ++ 0x00000000, ++ 0x00000040, ++ 0x00000000, ++ 0x00000040, ++ 0x00000000, ++ 0x00000040, ++ 0x00000000, ++ 0x00000040, ++ 0x10000000, ++ 0x00000040, ++ 0x20000000, ++ 0x00000040, ++ 0x30000000, ++ 0x00000040, ++ 0x40000000, ++ 0x00000040, ++ 0x30000000, ++ 0x00000048, ++ 0x40000000, ++ 0x00000048, ++ 0x50000000, ++ 0x00000048, ++ 0x60000000, ++ 0x00000048, ++ 0x30000000, ++ 0x00000058, ++ 0x40000000, ++ 0x00000058, ++ 0x50000000, ++ 0x00000058, ++ 0x70000000, ++ 0x00000058, ++ 0x80000000, ++ 0x00000058, ++ 0x90000000, ++ 0x00000058, ++ 0xa0000000, ++ 0x00000058, ++ 0x70000000, ++ 0x00000068, ++ 0x80000000, ++ 0x00000068, ++ 0x90000000, ++ 0x00000068, ++ 0xa0000000, ++ 0x00000068, ++ 0xb0000000, ++ 0x00000068, ++ 0xc0000000, ++ 0x00000068, ++ 0xd0000000, ++ 0x00000068, ++ 0xe0000000, ++ 0x00000068, ++ 0xf0000000, ++ 0x00000068, ++ 0x00000000, ++ 0x00000069, ++ 0x10000000, ++ 0x00000069, ++ 0x20000000, ++ 0x00000069, ++ 0x30000000, ++ 0x00000069, ++ 0x40000000, ++ 0x00000041, ++ 0x40000000, ++ 0x00000041, ++ 0x40000000, ++ 0x00000041, ++ 0x40000000, ++ 0x00000041, ++ 0x40000000, ++ 0x00000041, ++ 0x40000000, ++ 0x00000041, ++ 0x40000000, ++ 0x00000041, ++ 0x40000000, ++ 0x00000041, ++ 0x40000000, ++ 0x00000041, ++ 0x50000000, ++ 0x00000041, ++ 0x60000000, ++ 0x00000041, ++ 0x70000000, ++ 0x00000041, ++ 0x80000000, ++ 0x00000041, ++ 0x70000000, ++ 0x00000049, ++ 0x80000000, ++ 0x00000049, ++ 0x90000000, ++ 0x00000049, ++ 0xa0000000, ++ 0x00000049, ++ 0x70000000, ++ 0x00000059, ++ 0x80000000, ++ 0x00000059, ++ 0x90000000, ++ 0x00000059, ++ 0xb0000000, ++ 0x00000059, ++ 0xc0000000, ++ 0x00000059, ++ 0xd0000000, ++ 0x00000059, ++ 0xe0000000, ++ 0x00000059, ++ 0xb0000000, ++ 0x00000069, ++ 0xc0000000, ++ 0x00000069, ++ 0xd0000000, ++ 0x00000069, ++ 0xe0000000, ++ 0x00000069, ++ 0xf0000000, ++ 0x00000069, ++ 0x00000000, ++ 0x0000006a, ++ 0x10000000, ++ 0x0000006a, ++ 0x20000000, ++ 0x0000006a, ++ 0x30000000, ++ 0x0000006a, ++ 0x40000000, ++ 0x0000006a, ++ 0x50000000, ++ 0x0000006a, ++ 0x60000000, ++ 0x0000006a, ++ 0x70000000, ++ 0x0000006a, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000 ++}; ++ ++static const u32 dot11lcn_aux_gain_idx_tbl_5G[] = { ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0001, ++ 0x0002, ++ 0x0003, ++ 0x0004, ++ 0x0083, ++ 0x0084, ++ 0x0085, ++ 0x0086, ++ 0x0087, ++ 0x0186, ++ 0x0187, ++ 0x0188, ++ 0x0189, ++ 0x018a, ++ 0x018b, ++ 0x018c, ++ 0x018d, ++ 0x018e, ++ 0x018f, ++ 0x0190, ++ 0x0191, ++ 0x0192, ++ 0x0193, ++ 0x0194, ++ 0x0195, ++ 0x0196, ++ 0x0197, ++ 0x0198, ++ 0x0199, ++ 0x019a, ++ 0x019b, ++ 0x019c, ++ 0x019d, ++ 0x0000 ++}; ++ ++static const u32 dot11lcn_gain_val_tbl_5G[] = { ++ 0xf7, ++ 0xfd, ++ 0x00, ++ 0x04, ++ 0x04, ++ 0x04, ++ 0xf7, ++ 0xfd, ++ 0x00, ++ 0x04, ++ 0x04, ++ 0x04, ++ 0xf6, ++ 0x00, ++ 0x0c, ++ 0x03, ++ 0xeb, ++ 0xfe, ++ 0x06, ++ 0x0a, ++ 0x10, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x15, ++ 0x18, ++ 0x1b, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x15, ++ 0x18, ++ 0x1b, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00 ++}; ++ ++static const u32 dot11lcn_gain_idx_tbl_5G[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x10000000, ++ 0x00000000, ++ 0x20000000, ++ 0x00000000, ++ 0x30000000, ++ 0x00000000, ++ 0x40000000, ++ 0x00000000, ++ 0x30000000, ++ 0x00000008, ++ 0x40000000, ++ 0x00000008, ++ 0x50000000, ++ 0x00000008, ++ 0x60000000, ++ 0x00000008, ++ 0x70000000, ++ 0x00000008, ++ 0x60000000, ++ 0x00000018, ++ 0x70000000, ++ 0x00000018, ++ 0x80000000, ++ 0x00000018, ++ 0x90000000, ++ 0x00000018, ++ 0xa0000000, ++ 0x00000018, ++ 0xb0000000, ++ 0x00000018, ++ 0xc0000000, ++ 0x00000018, ++ 0xd0000000, ++ 0x00000018, ++ 0xe0000000, ++ 0x00000018, ++ 0xf0000000, ++ 0x00000018, ++ 0x00000000, ++ 0x00000019, ++ 0x10000000, ++ 0x00000019, ++ 0x20000000, ++ 0x00000019, ++ 0x30000000, ++ 0x00000019, ++ 0x40000000, ++ 0x00000019, ++ 0x50000000, ++ 0x00000019, ++ 0x60000000, ++ 0x00000019, ++ 0x70000000, ++ 0x00000019, ++ 0x80000000, ++ 0x00000019, ++ 0x90000000, ++ 0x00000019, ++ 0xa0000000, ++ 0x00000019, ++ 0xb0000000, ++ 0x00000019, ++ 0xc0000000, ++ 0x00000019, ++ 0xd0000000, ++ 0x00000019, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000 ++}; ++ ++static const u32 dot11lcn_gain_tbl_5G[] = { ++ 0x00000000, ++ 0x00000040, ++ 0x00000080, ++ 0x00000001, ++ 0x00000005, ++ 0x00000009, ++ 0x0000000d, ++ 0x00000011, ++ 0x00000015, ++ 0x00000055, ++ 0x00000095, ++ 0x00000017, ++ 0x0000001b, ++ 0x0000005b, ++ 0x0000009b, ++ 0x000000db, ++ 0x0000011b, ++ 0x0000015b, ++ 0x0000019b, ++ 0x0000059b, ++ 0x0000099b, ++ 0x00000d9b, ++ 0x0000119b, ++ 0x0000519b, ++ 0x0000919b, ++ 0x0000d19b, ++ 0x0001119b, ++ 0x0001519b, ++ 0x0001919b, ++ 0x0001d19b, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000 ++}; ++ ++const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev0[] = { ++ {&dot11lcn_gain_tbl_rev0, ++ sizeof(dot11lcn_gain_tbl_rev0) / sizeof(dot11lcn_gain_tbl_rev0[0]), 18, ++ 0, 32} ++ , ++ {&dot11lcn_aux_gain_idx_tbl_rev0, ++ sizeof(dot11lcn_aux_gain_idx_tbl_rev0) / ++ sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16} ++ , ++ {&dot11lcn_gain_idx_tbl_rev0, ++ sizeof(dot11lcn_gain_idx_tbl_rev0) / ++ sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32} ++ , ++}; ++ ++static const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev1[] = { ++ {&dot11lcn_gain_tbl_rev1, ++ sizeof(dot11lcn_gain_tbl_rev1) / sizeof(dot11lcn_gain_tbl_rev1[0]), 18, ++ 0, 32} ++ , ++ {&dot11lcn_aux_gain_idx_tbl_rev0, ++ sizeof(dot11lcn_aux_gain_idx_tbl_rev0) / ++ sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16} ++ , ++ {&dot11lcn_gain_idx_tbl_rev0, ++ sizeof(dot11lcn_gain_idx_tbl_rev0) / ++ sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32} ++ , ++}; ++ ++const struct phytbl_info dot11lcnphytbl_rx_gain_info_2G_rev2[] = { ++ {&dot11lcn_gain_tbl_2G, ++ sizeof(dot11lcn_gain_tbl_2G) / sizeof(dot11lcn_gain_tbl_2G[0]), 18, 0, ++ 32} ++ , ++ {&dot11lcn_aux_gain_idx_tbl_2G, ++ sizeof(dot11lcn_aux_gain_idx_tbl_2G) / ++ sizeof(dot11lcn_aux_gain_idx_tbl_2G[0]), 14, 0, 16} ++ , ++ {&dot11lcn_gain_idx_tbl_2G, ++ sizeof(dot11lcn_gain_idx_tbl_2G) / sizeof(dot11lcn_gain_idx_tbl_2G[0]), ++ 13, 0, 32} ++ , ++ {&dot11lcn_gain_val_tbl_2G, ++ sizeof(dot11lcn_gain_val_tbl_2G) / sizeof(dot11lcn_gain_val_tbl_2G[0]), ++ 17, 0, 8} ++}; ++ ++const struct phytbl_info dot11lcnphytbl_rx_gain_info_5G_rev2[] = { ++ {&dot11lcn_gain_tbl_5G, ++ sizeof(dot11lcn_gain_tbl_5G) / sizeof(dot11lcn_gain_tbl_5G[0]), 18, 0, ++ 32} ++ , ++ {&dot11lcn_aux_gain_idx_tbl_5G, ++ sizeof(dot11lcn_aux_gain_idx_tbl_5G) / ++ sizeof(dot11lcn_aux_gain_idx_tbl_5G[0]), 14, 0, 16} ++ , ++ {&dot11lcn_gain_idx_tbl_5G, ++ sizeof(dot11lcn_gain_idx_tbl_5G) / sizeof(dot11lcn_gain_idx_tbl_5G[0]), ++ 13, 0, 32} ++ , ++ {&dot11lcn_gain_val_tbl_5G, ++ sizeof(dot11lcn_gain_val_tbl_5G) / sizeof(dot11lcn_gain_val_tbl_5G[0]), ++ 17, 0, 8} ++}; ++ ++const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[] = { ++ {&dot11lcn_gain_tbl_extlna_2G, ++ sizeof(dot11lcn_gain_tbl_extlna_2G) / ++ sizeof(dot11lcn_gain_tbl_extlna_2G[0]), 18, 0, 32} ++ , ++ {&dot11lcn_aux_gain_idx_tbl_extlna_2G, ++ sizeof(dot11lcn_aux_gain_idx_tbl_extlna_2G) / ++ sizeof(dot11lcn_aux_gain_idx_tbl_extlna_2G[0]), 14, 0, 16} ++ , ++ {&dot11lcn_gain_idx_tbl_extlna_2G, ++ sizeof(dot11lcn_gain_idx_tbl_extlna_2G) / ++ sizeof(dot11lcn_gain_idx_tbl_extlna_2G[0]), 13, 0, 32} ++ , ++ {&dot11lcn_gain_val_tbl_extlna_2G, ++ sizeof(dot11lcn_gain_val_tbl_extlna_2G) / ++ sizeof(dot11lcn_gain_val_tbl_extlna_2G[0]), 17, 0, 8} ++}; ++ ++const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[] = { ++ {&dot11lcn_gain_tbl_5G, ++ sizeof(dot11lcn_gain_tbl_5G) / sizeof(dot11lcn_gain_tbl_5G[0]), 18, 0, ++ 32} ++ , ++ {&dot11lcn_aux_gain_idx_tbl_5G, ++ sizeof(dot11lcn_aux_gain_idx_tbl_5G) / ++ sizeof(dot11lcn_aux_gain_idx_tbl_5G[0]), 14, 0, 16} ++ , ++ {&dot11lcn_gain_idx_tbl_5G, ++ sizeof(dot11lcn_gain_idx_tbl_5G) / sizeof(dot11lcn_gain_idx_tbl_5G[0]), ++ 13, 0, 32} ++ , ++ {&dot11lcn_gain_val_tbl_5G, ++ sizeof(dot11lcn_gain_val_tbl_5G) / sizeof(dot11lcn_gain_val_tbl_5G[0]), ++ 17, 0, 8} ++}; ++ ++const u32 dot11lcnphytbl_rx_gain_info_sz_rev0 = ++ sizeof(dot11lcnphytbl_rx_gain_info_rev0) / ++ sizeof(dot11lcnphytbl_rx_gain_info_rev0[0]); ++ ++const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz = ++ sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2) / ++ sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2[0]); ++ ++const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz = ++ sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2) / ++ sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2[0]); ++ ++static const u16 dot11lcn_min_sig_sq_tbl_rev0[] = { ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++ 0x014d, ++}; ++ ++static const u16 dot11lcn_noise_scale_tbl_rev0[] = { ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++}; ++ ++static const u32 dot11lcn_fltr_ctrl_tbl_rev0[] = { ++ 0x000141f8, ++ 0x000021f8, ++ 0x000021fb, ++ 0x000041fb, ++ 0x0001fe4b, ++ 0x0000217b, ++ 0x00002133, ++ 0x000040eb, ++ 0x0001fea3, ++ 0x0000024b, ++}; ++ ++static const u32 dot11lcn_ps_ctrl_tbl_rev0[] = { ++ 0x00100001, ++ 0x00200010, ++ 0x00300001, ++ 0x00400010, ++ 0x00500022, ++ 0x00600122, ++ 0x00700222, ++ 0x00800322, ++ 0x00900422, ++ 0x00a00522, ++ 0x00b00622, ++ 0x00c00722, ++ 0x00d00822, ++ 0x00f00922, ++ 0x00100a22, ++ 0x00200b22, ++ 0x00300c22, ++ 0x00400d22, ++ 0x00500e22, ++ 0x00600f22, ++}; ++ ++static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[] = { ++ 0x0007, ++ 0x0005, ++ 0x0006, ++ 0x0004, ++ 0x0007, ++ 0x0005, ++ 0x0006, ++ 0x0004, ++ 0x0007, ++ 0x0005, ++ 0x0006, ++ 0x0004, ++ 0x0007, ++ 0x0005, ++ 0x0006, ++ 0x0004, ++ 0x000b, ++ 0x000b, ++ 0x000a, ++ 0x000a, ++ 0x000b, ++ 0x000b, ++ 0x000a, ++ 0x000a, ++ 0x000b, ++ 0x000b, ++ 0x000a, ++ 0x000a, ++ 0x000b, ++ 0x000b, ++ 0x000a, ++ 0x000a, ++ 0x0007, ++ 0x0005, ++ 0x0006, ++ 0x0004, ++ 0x0007, ++ 0x0005, ++ 0x0006, ++ 0x0004, ++ 0x0007, ++ 0x0005, ++ 0x0006, ++ 0x0004, ++ 0x0007, ++ 0x0005, ++ 0x0006, ++ 0x0004, ++ 0x000b, ++ 0x000b, ++ 0x000a, ++ 0x000a, ++ 0x000b, ++ 0x000b, ++ 0x000a, ++ 0x000a, ++ 0x000b, ++ 0x000b, ++ 0x000a, ++ 0x000a, ++ 0x000b, ++ 0x000b, ++ 0x000a, ++ 0x000a, ++ ++}; ++ ++static const u16 dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[] = { ++ 0x0007, ++ 0x0005, ++ 0x0002, ++ 0x0000, ++ 0x0007, ++ 0x0005, ++ 0x0002, ++ 0x0000, ++ 0x0007, ++ 0x0005, ++ 0x0002, ++ 0x0000, ++ 0x0007, ++ 0x0005, ++ 0x0002, ++ 0x0000, ++ 0x0007, ++ 0x0007, ++ 0x0002, ++ 0x0002, ++ 0x0007, ++ 0x0007, ++ 0x0002, ++ 0x0002, ++ 0x0007, ++ 0x0007, ++ 0x0002, ++ 0x0002, ++ 0x0007, ++ 0x0007, ++ 0x0002, ++ 0x0002, ++ 0x0007, ++ 0x0005, ++ 0x0002, ++ 0x0000, ++ 0x0007, ++ 0x0005, ++ 0x0002, ++ 0x0000, ++ 0x0007, ++ 0x0005, ++ 0x0002, ++ 0x0000, ++ 0x0007, ++ 0x0005, ++ 0x0002, ++ 0x0000, ++ 0x0007, ++ 0x0007, ++ 0x0002, ++ 0x0002, ++ 0x0007, ++ 0x0007, ++ 0x0002, ++ 0x0002, ++ 0x0007, ++ 0x0007, ++ 0x0002, ++ 0x0002, ++ 0x0007, ++ 0x0007, ++ 0x0002, ++ 0x0002, ++}; ++ ++static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = { ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++ 0x0002, ++ 0x0008, ++ 0x0004, ++ 0x0001, ++}; ++ ++static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = { ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++ 0x000a, ++ 0x0009, ++ 0x0006, ++ 0x0005, ++}; ++ ++static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = { ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++ 0x0004, ++ 0x0004, ++ 0x0002, ++ 0x0002, ++}; ++ ++static const u8 dot11lcn_nf_table_rev0[] = { ++ 0x5f, ++ 0x36, ++ 0x29, ++ 0x1f, ++ 0x5f, ++ 0x36, ++ 0x29, ++ 0x1f, ++ 0x5f, ++ 0x36, ++ 0x29, ++ 0x1f, ++ 0x5f, ++ 0x36, ++ 0x29, ++ 0x1f, ++}; ++ ++static const u8 dot11lcn_gain_val_tbl_rev0[] = { ++ 0x09, ++ 0x0f, ++ 0x14, ++ 0x18, ++ 0xfe, ++ 0x07, ++ 0x0b, ++ 0x0f, ++ 0xfb, ++ 0xfe, ++ 0x01, ++ 0x05, ++ 0x08, ++ 0x0b, ++ 0x0e, ++ 0x11, ++ 0x14, ++ 0x17, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0x06, ++ 0x09, ++ 0x0c, ++ 0x0f, ++ 0x12, ++ 0x15, ++ 0x18, ++ 0x1b, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x03, ++ 0xeb, ++ 0x00, ++ 0x00, ++}; ++ ++static const u8 dot11lcn_spur_tbl_rev0[] = { ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x02, ++ 0x03, ++ 0x01, ++ 0x03, ++ 0x02, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x02, ++ 0x03, ++ 0x01, ++ 0x03, ++ 0x02, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++ 0x01, ++}; ++ ++static const u16 dot11lcn_unsup_mcs_tbl_rev0[] = { ++ 0x001a, ++ 0x0034, ++ 0x004e, ++ 0x0068, ++ 0x009c, ++ 0x00d0, ++ 0x00ea, ++ 0x0104, ++ 0x0034, ++ 0x0068, ++ 0x009c, ++ 0x00d0, ++ 0x0138, ++ 0x01a0, ++ 0x01d4, ++ 0x0208, ++ 0x004e, ++ 0x009c, ++ 0x00ea, ++ 0x0138, ++ 0x01d4, ++ 0x0270, ++ 0x02be, ++ 0x030c, ++ 0x0068, ++ 0x00d0, ++ 0x0138, ++ 0x01a0, ++ 0x0270, ++ 0x0340, ++ 0x03a8, ++ 0x0410, ++ 0x0018, ++ 0x009c, ++ 0x00d0, ++ 0x0104, ++ 0x00ea, ++ 0x0138, ++ 0x0186, ++ 0x00d0, ++ 0x0104, ++ 0x0104, ++ 0x0138, ++ 0x016c, ++ 0x016c, ++ 0x01a0, ++ 0x0138, ++ 0x0186, ++ 0x0186, ++ 0x01d4, ++ 0x0222, ++ 0x0222, ++ 0x0270, ++ 0x0104, ++ 0x0138, ++ 0x016c, ++ 0x0138, ++ 0x016c, ++ 0x01a0, ++ 0x01d4, ++ 0x01a0, ++ 0x01d4, ++ 0x0208, ++ 0x0208, ++ 0x023c, ++ 0x0186, ++ 0x01d4, ++ 0x0222, ++ 0x01d4, ++ 0x0222, ++ 0x0270, ++ 0x02be, ++ 0x0270, ++ 0x02be, ++ 0x030c, ++ 0x030c, ++ 0x035a, ++ 0x0036, ++ 0x006c, ++ 0x00a2, ++ 0x00d8, ++ 0x0144, ++ 0x01b0, ++ 0x01e6, ++ 0x021c, ++ 0x006c, ++ 0x00d8, ++ 0x0144, ++ 0x01b0, ++ 0x0288, ++ 0x0360, ++ 0x03cc, ++ 0x0438, ++ 0x00a2, ++ 0x0144, ++ 0x01e6, ++ 0x0288, ++ 0x03cc, ++ 0x0510, ++ 0x05b2, ++ 0x0654, ++ 0x00d8, ++ 0x01b0, ++ 0x0288, ++ 0x0360, ++ 0x0510, ++ 0x06c0, ++ 0x0798, ++ 0x0870, ++ 0x0018, ++ 0x0144, ++ 0x01b0, ++ 0x021c, ++ 0x01e6, ++ 0x0288, ++ 0x032a, ++ 0x01b0, ++ 0x021c, ++ 0x021c, ++ 0x0288, ++ 0x02f4, ++ 0x02f4, ++ 0x0360, ++ 0x0288, ++ 0x032a, ++ 0x032a, ++ 0x03cc, ++ 0x046e, ++ 0x046e, ++ 0x0510, ++ 0x021c, ++ 0x0288, ++ 0x02f4, ++ 0x0288, ++ 0x02f4, ++ 0x0360, ++ 0x03cc, ++ 0x0360, ++ 0x03cc, ++ 0x0438, ++ 0x0438, ++ 0x04a4, ++ 0x032a, ++ 0x03cc, ++ 0x046e, ++ 0x03cc, ++ 0x046e, ++ 0x0510, ++ 0x05b2, ++ 0x0510, ++ 0x05b2, ++ 0x0654, ++ 0x0654, ++ 0x06f6, ++}; ++ ++static const u16 dot11lcn_iq_local_tbl_rev0[] = { ++ 0x0200, ++ 0x0300, ++ 0x0400, ++ 0x0600, ++ 0x0800, ++ 0x0b00, ++ 0x1000, ++ 0x1001, ++ 0x1002, ++ 0x1003, ++ 0x1004, ++ 0x1005, ++ 0x1006, ++ 0x1007, ++ 0x1707, ++ 0x2007, ++ 0x2d07, ++ 0x4007, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0200, ++ 0x0300, ++ 0x0400, ++ 0x0600, ++ 0x0800, ++ 0x0b00, ++ 0x1000, ++ 0x1001, ++ 0x1002, ++ 0x1003, ++ 0x1004, ++ 0x1005, ++ 0x1006, ++ 0x1007, ++ 0x1707, ++ 0x2007, ++ 0x2d07, ++ 0x4007, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x4000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++}; ++ ++static const u32 dot11lcn_papd_compdelta_tbl_rev0[] = { ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++ 0x00080000, ++}; ++ ++const struct phytbl_info dot11lcnphytbl_info_rev0[] = { ++ {&dot11lcn_min_sig_sq_tbl_rev0, ++ sizeof(dot11lcn_min_sig_sq_tbl_rev0) / ++ sizeof(dot11lcn_min_sig_sq_tbl_rev0[0]), 2, 0, 16} ++ , ++ {&dot11lcn_noise_scale_tbl_rev0, ++ sizeof(dot11lcn_noise_scale_tbl_rev0) / ++ sizeof(dot11lcn_noise_scale_tbl_rev0[0]), 1, 0, 16} ++ , ++ {&dot11lcn_fltr_ctrl_tbl_rev0, ++ sizeof(dot11lcn_fltr_ctrl_tbl_rev0) / ++ sizeof(dot11lcn_fltr_ctrl_tbl_rev0[0]), 11, 0, 32} ++ , ++ {&dot11lcn_ps_ctrl_tbl_rev0, ++ sizeof(dot11lcn_ps_ctrl_tbl_rev0) / ++ sizeof(dot11lcn_ps_ctrl_tbl_rev0[0]), 12, 0, 32} ++ , ++ {&dot11lcn_gain_idx_tbl_rev0, ++ sizeof(dot11lcn_gain_idx_tbl_rev0) / ++ sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32} ++ , ++ {&dot11lcn_aux_gain_idx_tbl_rev0, ++ sizeof(dot11lcn_aux_gain_idx_tbl_rev0) / ++ sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16} ++ , ++ {&dot11lcn_sw_ctrl_tbl_rev0, ++ sizeof(dot11lcn_sw_ctrl_tbl_rev0) / ++ sizeof(dot11lcn_sw_ctrl_tbl_rev0[0]), 15, 0, 16} ++ , ++ {&dot11lcn_nf_table_rev0, ++ sizeof(dot11lcn_nf_table_rev0) / sizeof(dot11lcn_nf_table_rev0[0]), 16, ++ 0, 8} ++ , ++ {&dot11lcn_gain_val_tbl_rev0, ++ sizeof(dot11lcn_gain_val_tbl_rev0) / ++ sizeof(dot11lcn_gain_val_tbl_rev0[0]), 17, 0, 8} ++ , ++ {&dot11lcn_gain_tbl_rev0, ++ sizeof(dot11lcn_gain_tbl_rev0) / sizeof(dot11lcn_gain_tbl_rev0[0]), 18, ++ 0, 32} ++ , ++ {&dot11lcn_spur_tbl_rev0, ++ sizeof(dot11lcn_spur_tbl_rev0) / sizeof(dot11lcn_spur_tbl_rev0[0]), 20, ++ 0, 8} ++ , ++ {&dot11lcn_unsup_mcs_tbl_rev0, ++ sizeof(dot11lcn_unsup_mcs_tbl_rev0) / ++ sizeof(dot11lcn_unsup_mcs_tbl_rev0[0]), 23, 0, 16} ++ , ++ {&dot11lcn_iq_local_tbl_rev0, ++ sizeof(dot11lcn_iq_local_tbl_rev0) / ++ sizeof(dot11lcn_iq_local_tbl_rev0[0]), 0, 0, 16} ++ , ++ {&dot11lcn_papd_compdelta_tbl_rev0, ++ sizeof(dot11lcn_papd_compdelta_tbl_rev0) / ++ sizeof(dot11lcn_papd_compdelta_tbl_rev0[0]), 24, 0, 32} ++ , ++}; ++ ++const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313 = { ++ &dot11lcn_sw_ctrl_tbl_4313_rev0, ++ sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0) / ++ sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0[0]), 15, 0, 16 ++}; ++ ++const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa = { ++ &dot11lcn_sw_ctrl_tbl_4313_epa_rev0, ++ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0) / ++ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0[0]), 15, 0, 16 ++}; ++ ++const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa = { ++ &dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo, ++ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo) / ++ sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[0]), 15, 0, 16 ++}; ++ ++const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250 = { ++ &dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0, ++ sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0) / ++ sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[0]), 15, 0, 16 ++}; ++ ++const u32 dot11lcnphytbl_info_sz_rev0 = ++ sizeof(dot11lcnphytbl_info_rev0) / sizeof(dot11lcnphytbl_info_rev0[0]); ++ ++const struct lcnphy_tx_gain_tbl_entry ++dot11lcnphy_2GHz_extPA_gaintable_rev0[128] = { ++ {3, 0, 31, 0, 72}, ++ {3, 0, 31, 0, 70}, ++ {3, 0, 31, 0, 68}, ++ {3, 0, 30, 0, 67}, ++ {3, 0, 29, 0, 68}, ++ {3, 0, 28, 0, 68}, ++ {3, 0, 27, 0, 69}, ++ {3, 0, 26, 0, 70}, ++ {3, 0, 25, 0, 70}, ++ {3, 0, 24, 0, 71}, ++ {3, 0, 23, 0, 72}, ++ {3, 0, 23, 0, 70}, ++ {3, 0, 22, 0, 71}, ++ {3, 0, 21, 0, 72}, ++ {3, 0, 21, 0, 70}, ++ {3, 0, 21, 0, 68}, ++ {3, 0, 21, 0, 66}, ++ {3, 0, 21, 0, 64}, ++ {3, 0, 21, 0, 63}, ++ {3, 0, 20, 0, 64}, ++ {3, 0, 19, 0, 65}, ++ {3, 0, 19, 0, 64}, ++ {3, 0, 18, 0, 65}, ++ {3, 0, 18, 0, 64}, ++ {3, 0, 17, 0, 65}, ++ {3, 0, 17, 0, 64}, ++ {3, 0, 16, 0, 65}, ++ {3, 0, 16, 0, 64}, ++ {3, 0, 16, 0, 62}, ++ {3, 0, 16, 0, 60}, ++ {3, 0, 16, 0, 58}, ++ {3, 0, 15, 0, 61}, ++ {3, 0, 15, 0, 59}, ++ {3, 0, 14, 0, 61}, ++ {3, 0, 14, 0, 60}, ++ {3, 0, 14, 0, 58}, ++ {3, 0, 13, 0, 60}, ++ {3, 0, 13, 0, 59}, ++ {3, 0, 12, 0, 62}, ++ {3, 0, 12, 0, 60}, ++ {3, 0, 12, 0, 58}, ++ {3, 0, 11, 0, 62}, ++ {3, 0, 11, 0, 60}, ++ {3, 0, 11, 0, 59}, ++ {3, 0, 11, 0, 57}, ++ {3, 0, 10, 0, 61}, ++ {3, 0, 10, 0, 59}, ++ {3, 0, 10, 0, 57}, ++ {3, 0, 9, 0, 62}, ++ {3, 0, 9, 0, 60}, ++ {3, 0, 9, 0, 58}, ++ {3, 0, 9, 0, 57}, ++ {3, 0, 8, 0, 62}, ++ {3, 0, 8, 0, 60}, ++ {3, 0, 8, 0, 58}, ++ {3, 0, 8, 0, 57}, ++ {3, 0, 8, 0, 55}, ++ {3, 0, 7, 0, 61}, ++ {3, 0, 7, 0, 60}, ++ {3, 0, 7, 0, 58}, ++ {3, 0, 7, 0, 56}, ++ {3, 0, 7, 0, 55}, ++ {3, 0, 6, 0, 62}, ++ {3, 0, 6, 0, 60}, ++ {3, 0, 6, 0, 58}, ++ {3, 0, 6, 0, 57}, ++ {3, 0, 6, 0, 55}, ++ {3, 0, 6, 0, 54}, ++ {3, 0, 6, 0, 52}, ++ {3, 0, 5, 0, 61}, ++ {3, 0, 5, 0, 59}, ++ {3, 0, 5, 0, 57}, ++ {3, 0, 5, 0, 56}, ++ {3, 0, 5, 0, 54}, ++ {3, 0, 5, 0, 53}, ++ {3, 0, 5, 0, 51}, ++ {3, 0, 4, 0, 62}, ++ {3, 0, 4, 0, 60}, ++ {3, 0, 4, 0, 58}, ++ {3, 0, 4, 0, 57}, ++ {3, 0, 4, 0, 55}, ++ {3, 0, 4, 0, 54}, ++ {3, 0, 4, 0, 52}, ++ {3, 0, 4, 0, 51}, ++ {3, 0, 4, 0, 49}, ++ {3, 0, 4, 0, 48}, ++ {3, 0, 4, 0, 46}, ++ {3, 0, 3, 0, 60}, ++ {3, 0, 3, 0, 58}, ++ {3, 0, 3, 0, 57}, ++ {3, 0, 3, 0, 55}, ++ {3, 0, 3, 0, 54}, ++ {3, 0, 3, 0, 52}, ++ {3, 0, 3, 0, 51}, ++ {3, 0, 3, 0, 49}, ++ {3, 0, 3, 0, 48}, ++ {3, 0, 3, 0, 46}, ++ {3, 0, 3, 0, 45}, ++ {3, 0, 3, 0, 44}, ++ {3, 0, 3, 0, 43}, ++ {3, 0, 3, 0, 41}, ++ {3, 0, 2, 0, 61}, ++ {3, 0, 2, 0, 59}, ++ {3, 0, 2, 0, 57}, ++ {3, 0, 2, 0, 56}, ++ {3, 0, 2, 0, 54}, ++ {3, 0, 2, 0, 53}, ++ {3, 0, 2, 0, 51}, ++ {3, 0, 2, 0, 50}, ++ {3, 0, 2, 0, 48}, ++ {3, 0, 2, 0, 47}, ++ {3, 0, 2, 0, 46}, ++ {3, 0, 2, 0, 44}, ++ {3, 0, 2, 0, 43}, ++ {3, 0, 2, 0, 42}, ++ {3, 0, 2, 0, 41}, ++ {3, 0, 2, 0, 39}, ++ {3, 0, 2, 0, 38}, ++ {3, 0, 2, 0, 37}, ++ {3, 0, 2, 0, 36}, ++ {3, 0, 2, 0, 35}, ++ {3, 0, 2, 0, 34}, ++ {3, 0, 2, 0, 33}, ++ {3, 0, 2, 0, 32}, ++ {3, 0, 1, 0, 63}, ++ {3, 0, 1, 0, 61}, ++ {3, 0, 1, 0, 59}, ++ {3, 0, 1, 0, 57}, ++}; ++ ++const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[128] = { ++ {7, 0, 31, 0, 72}, ++ {7, 0, 31, 0, 70}, ++ {7, 0, 31, 0, 68}, ++ {7, 0, 30, 0, 67}, ++ {7, 0, 29, 0, 68}, ++ {7, 0, 28, 0, 68}, ++ {7, 0, 27, 0, 69}, ++ {7, 0, 26, 0, 70}, ++ {7, 0, 25, 0, 70}, ++ {7, 0, 24, 0, 71}, ++ {7, 0, 23, 0, 72}, ++ {7, 0, 23, 0, 70}, ++ {7, 0, 22, 0, 71}, ++ {7, 0, 21, 0, 72}, ++ {7, 0, 21, 0, 70}, ++ {7, 0, 21, 0, 68}, ++ {7, 0, 21, 0, 66}, ++ {7, 0, 21, 0, 64}, ++ {7, 0, 21, 0, 63}, ++ {7, 0, 20, 0, 64}, ++ {7, 0, 19, 0, 65}, ++ {7, 0, 19, 0, 64}, ++ {7, 0, 18, 0, 65}, ++ {7, 0, 18, 0, 64}, ++ {7, 0, 17, 0, 65}, ++ {7, 0, 17, 0, 64}, ++ {7, 0, 16, 0, 65}, ++ {7, 0, 16, 0, 64}, ++ {7, 0, 16, 0, 62}, ++ {7, 0, 16, 0, 60}, ++ {7, 0, 16, 0, 58}, ++ {7, 0, 15, 0, 61}, ++ {7, 0, 15, 0, 59}, ++ {7, 0, 14, 0, 61}, ++ {7, 0, 14, 0, 60}, ++ {7, 0, 14, 0, 58}, ++ {7, 0, 13, 0, 60}, ++ {7, 0, 13, 0, 59}, ++ {7, 0, 12, 0, 62}, ++ {7, 0, 12, 0, 60}, ++ {7, 0, 12, 0, 58}, ++ {7, 0, 11, 0, 62}, ++ {7, 0, 11, 0, 60}, ++ {7, 0, 11, 0, 59}, ++ {7, 0, 11, 0, 57}, ++ {7, 0, 10, 0, 61}, ++ {7, 0, 10, 0, 59}, ++ {7, 0, 10, 0, 57}, ++ {7, 0, 9, 0, 62}, ++ {7, 0, 9, 0, 60}, ++ {7, 0, 9, 0, 58}, ++ {7, 0, 9, 0, 57}, ++ {7, 0, 8, 0, 62}, ++ {7, 0, 8, 0, 60}, ++ {7, 0, 8, 0, 58}, ++ {7, 0, 8, 0, 57}, ++ {7, 0, 8, 0, 55}, ++ {7, 0, 7, 0, 61}, ++ {7, 0, 7, 0, 60}, ++ {7, 0, 7, 0, 58}, ++ {7, 0, 7, 0, 56}, ++ {7, 0, 7, 0, 55}, ++ {7, 0, 6, 0, 62}, ++ {7, 0, 6, 0, 60}, ++ {7, 0, 6, 0, 58}, ++ {7, 0, 6, 0, 57}, ++ {7, 0, 6, 0, 55}, ++ {7, 0, 6, 0, 54}, ++ {7, 0, 6, 0, 52}, ++ {7, 0, 5, 0, 61}, ++ {7, 0, 5, 0, 59}, ++ {7, 0, 5, 0, 57}, ++ {7, 0, 5, 0, 56}, ++ {7, 0, 5, 0, 54}, ++ {7, 0, 5, 0, 53}, ++ {7, 0, 5, 0, 51}, ++ {7, 0, 4, 0, 62}, ++ {7, 0, 4, 0, 60}, ++ {7, 0, 4, 0, 58}, ++ {7, 0, 4, 0, 57}, ++ {7, 0, 4, 0, 55}, ++ {7, 0, 4, 0, 54}, ++ {7, 0, 4, 0, 52}, ++ {7, 0, 4, 0, 51}, ++ {7, 0, 4, 0, 49}, ++ {7, 0, 4, 0, 48}, ++ {7, 0, 4, 0, 46}, ++ {7, 0, 3, 0, 60}, ++ {7, 0, 3, 0, 58}, ++ {7, 0, 3, 0, 57}, ++ {7, 0, 3, 0, 55}, ++ {7, 0, 3, 0, 54}, ++ {7, 0, 3, 0, 52}, ++ {7, 0, 3, 0, 51}, ++ {7, 0, 3, 0, 49}, ++ {7, 0, 3, 0, 48}, ++ {7, 0, 3, 0, 46}, ++ {7, 0, 3, 0, 45}, ++ {7, 0, 3, 0, 44}, ++ {7, 0, 3, 0, 43}, ++ {7, 0, 3, 0, 41}, ++ {7, 0, 2, 0, 61}, ++ {7, 0, 2, 0, 59}, ++ {7, 0, 2, 0, 57}, ++ {7, 0, 2, 0, 56}, ++ {7, 0, 2, 0, 54}, ++ {7, 0, 2, 0, 53}, ++ {7, 0, 2, 0, 51}, ++ {7, 0, 2, 0, 50}, ++ {7, 0, 2, 0, 48}, ++ {7, 0, 2, 0, 47}, ++ {7, 0, 2, 0, 46}, ++ {7, 0, 2, 0, 44}, ++ {7, 0, 2, 0, 43}, ++ {7, 0, 2, 0, 42}, ++ {7, 0, 2, 0, 41}, ++ {7, 0, 2, 0, 39}, ++ {7, 0, 2, 0, 38}, ++ {7, 0, 2, 0, 37}, ++ {7, 0, 2, 0, 36}, ++ {7, 0, 2, 0, 35}, ++ {7, 0, 2, 0, 34}, ++ {7, 0, 2, 0, 33}, ++ {7, 0, 2, 0, 32}, ++ {7, 0, 1, 0, 63}, ++ {7, 0, 1, 0, 61}, ++ {7, 0, 1, 0, 59}, ++ {7, 0, 1, 0, 57}, ++}; ++ ++const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[128] = { ++ {255, 255, 0xf0, 0, 152}, ++ {255, 255, 0xf0, 0, 147}, ++ {255, 255, 0xf0, 0, 143}, ++ {255, 255, 0xf0, 0, 139}, ++ {255, 255, 0xf0, 0, 135}, ++ {255, 255, 0xf0, 0, 131}, ++ {255, 255, 0xf0, 0, 128}, ++ {255, 255, 0xf0, 0, 124}, ++ {255, 255, 0xf0, 0, 121}, ++ {255, 255, 0xf0, 0, 117}, ++ {255, 255, 0xf0, 0, 114}, ++ {255, 255, 0xf0, 0, 111}, ++ {255, 255, 0xf0, 0, 107}, ++ {255, 255, 0xf0, 0, 104}, ++ {255, 255, 0xf0, 0, 101}, ++ {255, 255, 0xf0, 0, 99}, ++ {255, 255, 0xf0, 0, 96}, ++ {255, 255, 0xf0, 0, 93}, ++ {255, 255, 0xf0, 0, 90}, ++ {255, 255, 0xf0, 0, 88}, ++ {255, 255, 0xf0, 0, 85}, ++ {255, 255, 0xf0, 0, 83}, ++ {255, 255, 0xf0, 0, 81}, ++ {255, 255, 0xf0, 0, 78}, ++ {255, 255, 0xf0, 0, 76}, ++ {255, 255, 0xf0, 0, 74}, ++ {255, 255, 0xf0, 0, 72}, ++ {255, 255, 0xf0, 0, 70}, ++ {255, 255, 0xf0, 0, 68}, ++ {255, 255, 0xf0, 0, 66}, ++ {255, 255, 0xf0, 0, 64}, ++ {255, 248, 0xf0, 0, 64}, ++ {255, 241, 0xf0, 0, 64}, ++ {255, 251, 0xe0, 0, 64}, ++ {255, 244, 0xe0, 0, 64}, ++ {255, 254, 0xd0, 0, 64}, ++ {255, 246, 0xd0, 0, 64}, ++ {255, 239, 0xd0, 0, 64}, ++ {255, 249, 0xc0, 0, 64}, ++ {255, 242, 0xc0, 0, 64}, ++ {255, 255, 0xb0, 0, 64}, ++ {255, 248, 0xb0, 0, 64}, ++ {255, 241, 0xb0, 0, 64}, ++ {255, 254, 0xa0, 0, 64}, ++ {255, 246, 0xa0, 0, 64}, ++ {255, 239, 0xa0, 0, 64}, ++ {255, 255, 0x90, 0, 64}, ++ {255, 248, 0x90, 0, 64}, ++ {255, 241, 0x90, 0, 64}, ++ {255, 234, 0x90, 0, 64}, ++ {255, 255, 0x80, 0, 64}, ++ {255, 248, 0x80, 0, 64}, ++ {255, 241, 0x80, 0, 64}, ++ {255, 234, 0x80, 0, 64}, ++ {255, 255, 0x70, 0, 64}, ++ {255, 248, 0x70, 0, 64}, ++ {255, 241, 0x70, 0, 64}, ++ {255, 234, 0x70, 0, 64}, ++ {255, 227, 0x70, 0, 64}, ++ {255, 221, 0x70, 0, 64}, ++ {255, 215, 0x70, 0, 64}, ++ {255, 208, 0x70, 0, 64}, ++ {255, 203, 0x70, 0, 64}, ++ {255, 197, 0x70, 0, 64}, ++ {255, 255, 0x60, 0, 64}, ++ {255, 248, 0x60, 0, 64}, ++ {255, 241, 0x60, 0, 64}, ++ {255, 234, 0x60, 0, 64}, ++ {255, 227, 0x60, 0, 64}, ++ {255, 221, 0x60, 0, 64}, ++ {255, 255, 0x50, 0, 64}, ++ {255, 248, 0x50, 0, 64}, ++ {255, 241, 0x50, 0, 64}, ++ {255, 234, 0x50, 0, 64}, ++ {255, 227, 0x50, 0, 64}, ++ {255, 221, 0x50, 0, 64}, ++ {255, 215, 0x50, 0, 64}, ++ {255, 208, 0x50, 0, 64}, ++ {255, 255, 0x40, 0, 64}, ++ {255, 248, 0x40, 0, 64}, ++ {255, 241, 0x40, 0, 64}, ++ {255, 234, 0x40, 0, 64}, ++ {255, 227, 0x40, 0, 64}, ++ {255, 221, 0x40, 0, 64}, ++ {255, 215, 0x40, 0, 64}, ++ {255, 208, 0x40, 0, 64}, ++ {255, 203, 0x40, 0, 64}, ++ {255, 197, 0x40, 0, 64}, ++ {255, 255, 0x30, 0, 64}, ++ {255, 248, 0x30, 0, 64}, ++ {255, 241, 0x30, 0, 64}, ++ {255, 234, 0x30, 0, 64}, ++ {255, 227, 0x30, 0, 64}, ++ {255, 221, 0x30, 0, 64}, ++ {255, 215, 0x30, 0, 64}, ++ {255, 208, 0x30, 0, 64}, ++ {255, 203, 0x30, 0, 64}, ++ {255, 197, 0x30, 0, 64}, ++ {255, 191, 0x30, 0, 64}, ++ {255, 186, 0x30, 0, 64}, ++ {255, 181, 0x30, 0, 64}, ++ {255, 175, 0x30, 0, 64}, ++ {255, 255, 0x20, 0, 64}, ++ {255, 248, 0x20, 0, 64}, ++ {255, 241, 0x20, 0, 64}, ++ {255, 234, 0x20, 0, 64}, ++ {255, 227, 0x20, 0, 64}, ++ {255, 221, 0x20, 0, 64}, ++ {255, 215, 0x20, 0, 64}, ++ {255, 208, 0x20, 0, 64}, ++ {255, 203, 0x20, 0, 64}, ++ {255, 197, 0x20, 0, 64}, ++ {255, 191, 0x20, 0, 64}, ++ {255, 186, 0x20, 0, 64}, ++ {255, 181, 0x20, 0, 64}, ++ {255, 175, 0x20, 0, 64}, ++ {255, 170, 0x20, 0, 64}, ++ {255, 166, 0x20, 0, 64}, ++ {255, 161, 0x20, 0, 64}, ++ {255, 156, 0x20, 0, 64}, ++ {255, 152, 0x20, 0, 64}, ++ {255, 148, 0x20, 0, 64}, ++ {255, 143, 0x20, 0, 64}, ++ {255, 139, 0x20, 0, 64}, ++ {255, 135, 0x20, 0, 64}, ++ {255, 132, 0x20, 0, 64}, ++ {255, 255, 0x10, 0, 64}, ++ {255, 248, 0x10, 0, 64}, ++}; +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h.orig 2011-11-09 13:46:58.278800221 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.h 2011-11-09 13:47:17.036565717 -0500 +@@ -0,0 +1,54 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include "phy_int.h" ++ ++extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev0[]; ++extern const u32 dot11lcnphytbl_rx_gain_info_sz_rev0; ++extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313; ++extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa; ++extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa_combo; ++extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa; ++extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250; ++ ++extern const struct phytbl_info dot11lcnphytbl_info_rev0[]; ++extern const u32 dot11lcnphytbl_info_sz_rev0; ++ ++extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_2G_rev2[]; ++extern const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz; ++ ++extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_5G_rev2[]; ++extern const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz; ++ ++extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[]; ++ ++extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[]; ++ ++struct lcnphy_tx_gain_tbl_entry { ++ unsigned char gm; ++ unsigned char pga; ++ unsigned char pad; ++ unsigned char dac; ++ unsigned char bb_mult; ++}; ++ ++extern const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[]; ++ ++extern const struct ++lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_extPA_gaintable_rev0[]; ++ ++extern const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[]; +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.c.orig 2011-11-09 13:46:58.282800170 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.c 2011-11-09 13:47:17.040565666 -0500 +@@ -0,0 +1,10630 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include "phytbl_n.h" ++ ++static const u32 frame_struct_rev0[] = { ++ 0x08004a04, ++ 0x00100000, ++ 0x01000a05, ++ 0x00100020, ++ 0x09804506, ++ 0x00100030, ++ 0x09804507, ++ 0x00100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x08004a0c, ++ 0x00100004, ++ 0x01000a0d, ++ 0x00100024, ++ 0x0980450e, ++ 0x00100034, ++ 0x0980450f, ++ 0x00100034, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000a04, ++ 0x00100000, ++ 0x11008a05, ++ 0x00100020, ++ 0x1980c506, ++ 0x00100030, ++ 0x21810506, ++ 0x00100030, ++ 0x21810506, ++ 0x00100030, ++ 0x01800504, ++ 0x00100030, ++ 0x11808505, ++ 0x00100030, ++ 0x29814507, ++ 0x01100030, ++ 0x00000a04, ++ 0x00100000, ++ 0x11008a05, ++ 0x00100020, ++ 0x21810506, ++ 0x00100030, ++ 0x21810506, ++ 0x00100030, ++ 0x29814507, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000a0c, ++ 0x00100008, ++ 0x11008a0d, ++ 0x00100028, ++ 0x1980c50e, ++ 0x00100038, ++ 0x2181050e, ++ 0x00100038, ++ 0x2181050e, ++ 0x00100038, ++ 0x0180050c, ++ 0x00100038, ++ 0x1180850d, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000a0c, ++ 0x00100008, ++ 0x11008a0d, ++ 0x00100028, ++ 0x2181050e, ++ 0x00100038, ++ 0x2181050e, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x08004a04, ++ 0x00100000, ++ 0x01000a05, ++ 0x00100020, ++ 0x1980c506, ++ 0x00100030, ++ 0x1980c506, ++ 0x00100030, ++ 0x11808504, ++ 0x00100030, ++ 0x3981ca05, ++ 0x00100030, ++ 0x29814507, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x10008a04, ++ 0x00100000, ++ 0x3981ca05, ++ 0x00100030, ++ 0x1980c506, ++ 0x00100030, ++ 0x29814507, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x08004a0c, ++ 0x00100008, ++ 0x01000a0d, ++ 0x00100028, ++ 0x1980c50e, ++ 0x00100038, ++ 0x1980c50e, ++ 0x00100038, ++ 0x1180850c, ++ 0x00100038, ++ 0x3981ca0d, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x10008a0c, ++ 0x00100008, ++ 0x3981ca0d, ++ 0x00100038, ++ 0x1980c50e, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x40021404, ++ 0x00100000, ++ 0x02001405, ++ 0x00100040, ++ 0x0b004a06, ++ 0x01900060, ++ 0x13008a06, ++ 0x01900060, ++ 0x13008a06, ++ 0x01900060, ++ 0x43020a04, ++ 0x00100060, ++ 0x1b00ca05, ++ 0x00100060, ++ 0x23010a07, ++ 0x01500060, ++ 0x40021404, ++ 0x00100000, ++ 0x1a00d405, ++ 0x00100040, ++ 0x13008a06, ++ 0x01900060, ++ 0x13008a06, ++ 0x01900060, ++ 0x23010a07, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100010, ++ 0x0200140d, ++ 0x00100050, ++ 0x0b004a0e, ++ 0x01900070, ++ 0x13008a0e, ++ 0x01900070, ++ 0x13008a0e, ++ 0x01900070, ++ 0x43020a0c, ++ 0x00100070, ++ 0x1b00ca0d, ++ 0x00100070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x4002140c, ++ 0x00100010, ++ 0x1a00d40d, ++ 0x00100050, ++ 0x13008a0e, ++ 0x01900070, ++ 0x13008a0e, ++ 0x01900070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x50029404, ++ 0x00100000, ++ 0x32019405, ++ 0x00100040, ++ 0x0b004a06, ++ 0x01900060, ++ 0x0b004a06, ++ 0x01900060, ++ 0x5b02ca04, ++ 0x00100060, ++ 0x3b01d405, ++ 0x00100060, ++ 0x23010a07, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x5802d404, ++ 0x00100000, ++ 0x3b01d405, ++ 0x00100060, ++ 0x0b004a06, ++ 0x01900060, ++ 0x23010a07, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x5002940c, ++ 0x00100010, ++ 0x3201940d, ++ 0x00100050, ++ 0x0b004a0e, ++ 0x01900070, ++ 0x0b004a0e, ++ 0x01900070, ++ 0x5b02ca0c, ++ 0x00100070, ++ 0x3b01d40d, ++ 0x00100070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x5802d40c, ++ 0x00100010, ++ 0x3b01d40d, ++ 0x00100070, ++ 0x0b004a0e, ++ 0x01900070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x40021404, ++ 0x000f4800, ++ 0x62031405, ++ 0x00100040, ++ 0x53028a06, ++ 0x01900060, ++ 0x53028a07, ++ 0x01900060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x000f4808, ++ 0x6203140d, ++ 0x00100048, ++ 0x53028a0e, ++ 0x01900068, ++ 0x53028a0f, ++ 0x01900068, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000a0c, ++ 0x00100004, ++ 0x11008a0d, ++ 0x00100024, ++ 0x1980c50e, ++ 0x00100034, ++ 0x2181050e, ++ 0x00100034, ++ 0x2181050e, ++ 0x00100034, ++ 0x0180050c, ++ 0x00100038, ++ 0x1180850d, ++ 0x00100038, ++ 0x1181850d, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000a0c, ++ 0x00100008, ++ 0x11008a0d, ++ 0x00100028, ++ 0x2181050e, ++ 0x00100038, ++ 0x2181050e, ++ 0x00100038, ++ 0x1181850d, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x08004a04, ++ 0x00100000, ++ 0x01000a05, ++ 0x00100020, ++ 0x0180c506, ++ 0x00100030, ++ 0x0180c506, ++ 0x00100030, ++ 0x2180c50c, ++ 0x00100030, ++ 0x49820a0d, ++ 0x0016a130, ++ 0x41824a0d, ++ 0x0016a130, ++ 0x2981450f, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x2000ca0c, ++ 0x00100000, ++ 0x49820a0d, ++ 0x0016a130, ++ 0x1980c50e, ++ 0x00100030, ++ 0x41824a0d, ++ 0x0016a130, ++ 0x2981450f, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100008, ++ 0x0200140d, ++ 0x00100048, ++ 0x0b004a0e, ++ 0x01900068, ++ 0x13008a0e, ++ 0x01900068, ++ 0x13008a0e, ++ 0x01900068, ++ 0x43020a0c, ++ 0x00100070, ++ 0x1b00ca0d, ++ 0x00100070, ++ 0x1b014a0d, ++ 0x00100070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100010, ++ 0x1a00d40d, ++ 0x00100050, ++ 0x13008a0e, ++ 0x01900070, ++ 0x13008a0e, ++ 0x01900070, ++ 0x1b014a0d, ++ 0x00100070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x50029404, ++ 0x00100000, ++ 0x32019405, ++ 0x00100040, ++ 0x03004a06, ++ 0x01900060, ++ 0x03004a06, ++ 0x01900060, ++ 0x6b030a0c, ++ 0x00100060, ++ 0x4b02140d, ++ 0x0016a160, ++ 0x4302540d, ++ 0x0016a160, ++ 0x23010a0f, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x6b03140c, ++ 0x00100060, ++ 0x4b02140d, ++ 0x0016a160, ++ 0x0b004a0e, ++ 0x01900060, ++ 0x4302540d, ++ 0x0016a160, ++ 0x23010a0f, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x40021404, ++ 0x00100000, ++ 0x1a00d405, ++ 0x00100040, ++ 0x53028a06, ++ 0x01900060, ++ 0x5b02ca06, ++ 0x01900060, ++ 0x5b02ca06, ++ 0x01900060, ++ 0x43020a04, ++ 0x00100060, ++ 0x1b00ca05, ++ 0x00100060, ++ 0x53028a07, ++ 0x0190c060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100010, ++ 0x1a00d40d, ++ 0x00100050, ++ 0x53028a0e, ++ 0x01900070, ++ 0x5b02ca0e, ++ 0x01900070, ++ 0x5b02ca0e, ++ 0x01900070, ++ 0x43020a0c, ++ 0x00100070, ++ 0x1b00ca0d, ++ 0x00100070, ++ 0x53028a0f, ++ 0x0190c070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x40021404, ++ 0x00100000, ++ 0x1a00d405, ++ 0x00100040, ++ 0x5b02ca06, ++ 0x01900060, ++ 0x5b02ca06, ++ 0x01900060, ++ 0x53028a07, ++ 0x0190c060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100010, ++ 0x1a00d40d, ++ 0x00100050, ++ 0x5b02ca0e, ++ 0x01900070, ++ 0x5b02ca0e, ++ 0x01900070, ++ 0x53028a0f, ++ 0x0190c070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u8 frame_lut_rev0[] = { ++ 0x02, ++ 0x04, ++ 0x14, ++ 0x14, ++ 0x03, ++ 0x05, ++ 0x16, ++ 0x16, ++ 0x0a, ++ 0x0c, ++ 0x1c, ++ 0x1c, ++ 0x0b, ++ 0x0d, ++ 0x1e, ++ 0x1e, ++ 0x06, ++ 0x08, ++ 0x18, ++ 0x18, ++ 0x07, ++ 0x09, ++ 0x1a, ++ 0x1a, ++ 0x0e, ++ 0x10, ++ 0x20, ++ 0x28, ++ 0x0f, ++ 0x11, ++ 0x22, ++ 0x2a, ++}; ++ ++static const u32 tmap_tbl_rev0[] = { ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x000aa888, ++ 0x88880000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa2222220, ++ 0x22222222, ++ 0x22c22222, ++ 0x00000222, ++ 0x22000000, ++ 0x2222a222, ++ 0x22222222, ++ 0x222222a2, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00011111, ++ 0x11110000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0xa8aa88a0, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x00088aaa, ++ 0xaaaa0000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xaaa8aaa0, ++ 0x8aaa8aaa, ++ 0xaa8a8a8a, ++ 0x000aaa88, ++ 0x8aaa0000, ++ 0xaaa8a888, ++ 0x8aa88a8a, ++ 0x8a88a888, ++ 0x08080a00, ++ 0x0a08080a, ++ 0x080a0a08, ++ 0x00080808, ++ 0x080a0000, ++ 0x080a0808, ++ 0x080a0808, ++ 0x0a0a0a08, ++ 0xa0a0a0a0, ++ 0x80a0a080, ++ 0x8080a0a0, ++ 0x00008080, ++ 0x80a00000, ++ 0x80a080a0, ++ 0xa080a0a0, ++ 0x8080a0a0, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x99999000, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb90, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00aaa888, ++ 0x22000000, ++ 0x2222b222, ++ 0x22222222, ++ 0x222222b2, ++ 0xb2222220, ++ 0x22222222, ++ 0x22d22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x33000000, ++ 0x3333b333, ++ 0x33333333, ++ 0x333333b3, ++ 0xb3333330, ++ 0x33333333, ++ 0x33d33333, ++ 0x00000333, ++ 0x22000000, ++ 0x2222a222, ++ 0x22222222, ++ 0x222222a2, ++ 0xa2222220, ++ 0x22222222, ++ 0x22c22222, ++ 0x00000222, ++ 0x99b99b00, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb99, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x08aaa888, ++ 0x22222200, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0x22222222, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x11111111, ++ 0xf1111111, ++ 0x11111111, ++ 0x11f11111, ++ 0x01111111, ++ 0xbb9bb900, ++ 0xb9b9bb99, ++ 0xb99bbbbb, ++ 0xbbbb9b9b, ++ 0xb9bb99bb, ++ 0xb99999b9, ++ 0xb9b9b99b, ++ 0x00000bbb, ++ 0xaa000000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xa8aa88aa, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x0a888aaa, ++ 0xaa000000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xa8aa88a0, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x00000aaa, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0xbbbbbb00, ++ 0x999bbbbb, ++ 0x9bb99b9b, ++ 0xb9b9b9bb, ++ 0xb9b99bbb, ++ 0xb9b9b9bb, ++ 0xb9bb9b99, ++ 0x00000999, ++ 0x8a000000, ++ 0xaa88a888, ++ 0xa88888aa, ++ 0xa88a8a88, ++ 0xa88aa88a, ++ 0x88a8aaaa, ++ 0xa8aa8aaa, ++ 0x0888a88a, ++ 0x0b0b0b00, ++ 0x090b0b0b, ++ 0x0b090b0b, ++ 0x0909090b, ++ 0x09090b0b, ++ 0x09090b0b, ++ 0x09090b09, ++ 0x00000909, ++ 0x0a000000, ++ 0x0a080808, ++ 0x080a080a, ++ 0x080a0a08, ++ 0x080a080a, ++ 0x0808080a, ++ 0x0a0a0a08, ++ 0x0808080a, ++ 0xb0b0b000, ++ 0x9090b0b0, ++ 0x90b09090, ++ 0xb0b0b090, ++ 0xb0b090b0, ++ 0x90b0b0b0, ++ 0xb0b09090, ++ 0x00000090, ++ 0x80000000, ++ 0xa080a080, ++ 0xa08080a0, ++ 0xa0808080, ++ 0xa080a080, ++ 0x80a0a0a0, ++ 0xa0a080a0, ++ 0x00a0a0a0, ++ 0x22000000, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0xf2222220, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00000111, ++ 0x33000000, ++ 0x3333f333, ++ 0x33333333, ++ 0x333333f3, ++ 0xf3333330, ++ 0x33333333, ++ 0x33f33333, ++ 0x00000333, ++ 0x22000000, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0xf2222220, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x99000000, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb90, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88888000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00aaa888, ++ 0x88a88a00, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x08aaa888, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 tdtrn_tbl_rev0[] = { ++ 0x061c061c, ++ 0x0050ee68, ++ 0xf592fe36, ++ 0xfe5212f6, ++ 0x00000c38, ++ 0xfe5212f6, ++ 0xf592fe36, ++ 0x0050ee68, ++ 0x061c061c, ++ 0xee680050, ++ 0xfe36f592, ++ 0x12f6fe52, ++ 0x0c380000, ++ 0x12f6fe52, ++ 0xfe36f592, ++ 0xee680050, ++ 0x061c061c, ++ 0x0050ee68, ++ 0xf592fe36, ++ 0xfe5212f6, ++ 0x00000c38, ++ 0xfe5212f6, ++ 0xf592fe36, ++ 0x0050ee68, ++ 0x061c061c, ++ 0xee680050, ++ 0xfe36f592, ++ 0x12f6fe52, ++ 0x0c380000, ++ 0x12f6fe52, ++ 0xfe36f592, ++ 0xee680050, ++ 0x05e305e3, ++ 0x004def0c, ++ 0xf5f3fe47, ++ 0xfe611246, ++ 0x00000bc7, ++ 0xfe611246, ++ 0xf5f3fe47, ++ 0x004def0c, ++ 0x05e305e3, ++ 0xef0c004d, ++ 0xfe47f5f3, ++ 0x1246fe61, ++ 0x0bc70000, ++ 0x1246fe61, ++ 0xfe47f5f3, ++ 0xef0c004d, ++ 0x05e305e3, ++ 0x004def0c, ++ 0xf5f3fe47, ++ 0xfe611246, ++ 0x00000bc7, ++ 0xfe611246, ++ 0xf5f3fe47, ++ 0x004def0c, ++ 0x05e305e3, ++ 0xef0c004d, ++ 0xfe47f5f3, ++ 0x1246fe61, ++ 0x0bc70000, ++ 0x1246fe61, ++ 0xfe47f5f3, ++ 0xef0c004d, ++ 0xfa58fa58, ++ 0xf895043b, ++ 0xff4c09c0, ++ 0xfbc6ffa8, ++ 0xfb84f384, ++ 0x0798f6f9, ++ 0x05760122, ++ 0x058409f6, ++ 0x0b500000, ++ 0x05b7f542, ++ 0x08860432, ++ 0x06ddfee7, ++ 0xfb84f384, ++ 0xf9d90664, ++ 0xf7e8025c, ++ 0x00fff7bd, ++ 0x05a805a8, ++ 0xf7bd00ff, ++ 0x025cf7e8, ++ 0x0664f9d9, ++ 0xf384fb84, ++ 0xfee706dd, ++ 0x04320886, ++ 0xf54205b7, ++ 0x00000b50, ++ 0x09f60584, ++ 0x01220576, ++ 0xf6f90798, ++ 0xf384fb84, ++ 0xffa8fbc6, ++ 0x09c0ff4c, ++ 0x043bf895, ++ 0x02d402d4, ++ 0x07de0270, ++ 0xfc96079c, ++ 0xf90afe94, ++ 0xfe00ff2c, ++ 0x02d4065d, ++ 0x092a0096, ++ 0x0014fbb8, ++ 0xfd2cfd2c, ++ 0x076afb3c, ++ 0x0096f752, ++ 0xf991fd87, ++ 0xfb2c0200, ++ 0xfeb8f960, ++ 0x08e0fc96, ++ 0x049802a8, ++ 0xfd2cfd2c, ++ 0x02a80498, ++ 0xfc9608e0, ++ 0xf960feb8, ++ 0x0200fb2c, ++ 0xfd87f991, ++ 0xf7520096, ++ 0xfb3c076a, ++ 0xfd2cfd2c, ++ 0xfbb80014, ++ 0x0096092a, ++ 0x065d02d4, ++ 0xff2cfe00, ++ 0xfe94f90a, ++ 0x079cfc96, ++ 0x027007de, ++ 0x02d402d4, ++ 0x027007de, ++ 0x079cfc96, ++ 0xfe94f90a, ++ 0xff2cfe00, ++ 0x065d02d4, ++ 0x0096092a, ++ 0xfbb80014, ++ 0xfd2cfd2c, ++ 0xfb3c076a, ++ 0xf7520096, ++ 0xfd87f991, ++ 0x0200fb2c, ++ 0xf960feb8, ++ 0xfc9608e0, ++ 0x02a80498, ++ 0xfd2cfd2c, ++ 0x049802a8, ++ 0x08e0fc96, ++ 0xfeb8f960, ++ 0xfb2c0200, ++ 0xf991fd87, ++ 0x0096f752, ++ 0x076afb3c, ++ 0xfd2cfd2c, ++ 0x0014fbb8, ++ 0x092a0096, ++ 0x02d4065d, ++ 0xfe00ff2c, ++ 0xf90afe94, ++ 0xfc96079c, ++ 0x07de0270, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x062a0000, ++ 0xfefa0759, ++ 0x08b80908, ++ 0xf396fc2d, ++ 0xf9d6045c, ++ 0xfc4ef608, ++ 0xf748f596, ++ 0x07b207bf, ++ 0x062a062a, ++ 0xf84ef841, ++ 0xf748f596, ++ 0x03b209f8, ++ 0xf9d6045c, ++ 0x0c6a03d3, ++ 0x08b80908, ++ 0x0106f8a7, ++ 0x062a0000, ++ 0xfefaf8a7, ++ 0x08b8f6f8, ++ 0xf39603d3, ++ 0xf9d6fba4, ++ 0xfc4e09f8, ++ 0xf7480a6a, ++ 0x07b2f841, ++ 0x062af9d6, ++ 0xf84e07bf, ++ 0xf7480a6a, ++ 0x03b2f608, ++ 0xf9d6fba4, ++ 0x0c6afc2d, ++ 0x08b8f6f8, ++ 0x01060759, ++ 0x062a0000, ++ 0xfefa0759, ++ 0x08b80908, ++ 0xf396fc2d, ++ 0xf9d6045c, ++ 0xfc4ef608, ++ 0xf748f596, ++ 0x07b207bf, ++ 0x062a062a, ++ 0xf84ef841, ++ 0xf748f596, ++ 0x03b209f8, ++ 0xf9d6045c, ++ 0x0c6a03d3, ++ 0x08b80908, ++ 0x0106f8a7, ++ 0x062a0000, ++ 0xfefaf8a7, ++ 0x08b8f6f8, ++ 0xf39603d3, ++ 0xf9d6fba4, ++ 0xfc4e09f8, ++ 0xf7480a6a, ++ 0x07b2f841, ++ 0x062af9d6, ++ 0xf84e07bf, ++ 0xf7480a6a, ++ 0x03b2f608, ++ 0xf9d6fba4, ++ 0x0c6afc2d, ++ 0x08b8f6f8, ++ 0x01060759, ++ 0x061c061c, ++ 0xff30009d, ++ 0xffb21141, ++ 0xfd87fb54, ++ 0xf65dfe59, ++ 0x02eef99e, ++ 0x0166f03c, ++ 0xfff809b6, ++ 0x000008a4, ++ 0x000af42b, ++ 0x00eff577, ++ 0xfa840bf2, ++ 0xfc02ff51, ++ 0x08260f67, ++ 0xfff0036f, ++ 0x0842f9c3, ++ 0x00000000, ++ 0x063df7be, ++ 0xfc910010, ++ 0xf099f7da, ++ 0x00af03fe, ++ 0xf40e057c, ++ 0x0a89ff11, ++ 0x0bd5fff6, ++ 0xf75c0000, ++ 0xf64a0008, ++ 0x0fc4fe9a, ++ 0x0662fd12, ++ 0x01a709a3, ++ 0x04ac0279, ++ 0xeebf004e, ++ 0xff6300d0, ++ 0xf9e4f9e4, ++ 0x00d0ff63, ++ 0x004eeebf, ++ 0x027904ac, ++ 0x09a301a7, ++ 0xfd120662, ++ 0xfe9a0fc4, ++ 0x0008f64a, ++ 0x0000f75c, ++ 0xfff60bd5, ++ 0xff110a89, ++ 0x057cf40e, ++ 0x03fe00af, ++ 0xf7daf099, ++ 0x0010fc91, ++ 0xf7be063d, ++ 0x00000000, ++ 0xf9c30842, ++ 0x036ffff0, ++ 0x0f670826, ++ 0xff51fc02, ++ 0x0bf2fa84, ++ 0xf57700ef, ++ 0xf42b000a, ++ 0x08a40000, ++ 0x09b6fff8, ++ 0xf03c0166, ++ 0xf99e02ee, ++ 0xfe59f65d, ++ 0xfb54fd87, ++ 0x1141ffb2, ++ 0x009dff30, ++ 0x05e30000, ++ 0xff060705, ++ 0x085408a0, ++ 0xf425fc59, ++ 0xfa1d042a, ++ 0xfc78f67a, ++ 0xf7acf60e, ++ 0x075a0766, ++ 0x05e305e3, ++ 0xf8a6f89a, ++ 0xf7acf60e, ++ 0x03880986, ++ 0xfa1d042a, ++ 0x0bdb03a7, ++ 0x085408a0, ++ 0x00faf8fb, ++ 0x05e30000, ++ 0xff06f8fb, ++ 0x0854f760, ++ 0xf42503a7, ++ 0xfa1dfbd6, ++ 0xfc780986, ++ 0xf7ac09f2, ++ 0x075af89a, ++ 0x05e3fa1d, ++ 0xf8a60766, ++ 0xf7ac09f2, ++ 0x0388f67a, ++ 0xfa1dfbd6, ++ 0x0bdbfc59, ++ 0x0854f760, ++ 0x00fa0705, ++ 0x05e30000, ++ 0xff060705, ++ 0x085408a0, ++ 0xf425fc59, ++ 0xfa1d042a, ++ 0xfc78f67a, ++ 0xf7acf60e, ++ 0x075a0766, ++ 0x05e305e3, ++ 0xf8a6f89a, ++ 0xf7acf60e, ++ 0x03880986, ++ 0xfa1d042a, ++ 0x0bdb03a7, ++ 0x085408a0, ++ 0x00faf8fb, ++ 0x05e30000, ++ 0xff06f8fb, ++ 0x0854f760, ++ 0xf42503a7, ++ 0xfa1dfbd6, ++ 0xfc780986, ++ 0xf7ac09f2, ++ 0x075af89a, ++ 0x05e3fa1d, ++ 0xf8a60766, ++ 0xf7ac09f2, ++ 0x0388f67a, ++ 0xfa1dfbd6, ++ 0x0bdbfc59, ++ 0x0854f760, ++ 0x00fa0705, ++ 0xfa58fa58, ++ 0xf8f0fe00, ++ 0x0448073d, ++ 0xfdc9fe46, ++ 0xf9910258, ++ 0x089d0407, ++ 0xfd5cf71a, ++ 0x02affde0, ++ 0x083e0496, ++ 0xff5a0740, ++ 0xff7afd97, ++ 0x00fe01f1, ++ 0x0009082e, ++ 0xfa94ff75, ++ 0xfecdf8ea, ++ 0xffb0f693, ++ 0xfd2cfa58, ++ 0x0433ff16, ++ 0xfba405dd, ++ 0xfa610341, ++ 0x06a606cb, ++ 0x0039fd2d, ++ 0x0677fa97, ++ 0x01fa05e0, ++ 0xf896003e, ++ 0x075a068b, ++ 0x012cfc3e, ++ 0xfa23f98d, ++ 0xfc7cfd43, ++ 0xff90fc0d, ++ 0x01c10982, ++ 0x00c601d6, ++ 0xfd2cfd2c, ++ 0x01d600c6, ++ 0x098201c1, ++ 0xfc0dff90, ++ 0xfd43fc7c, ++ 0xf98dfa23, ++ 0xfc3e012c, ++ 0x068b075a, ++ 0x003ef896, ++ 0x05e001fa, ++ 0xfa970677, ++ 0xfd2d0039, ++ 0x06cb06a6, ++ 0x0341fa61, ++ 0x05ddfba4, ++ 0xff160433, ++ 0xfa58fd2c, ++ 0xf693ffb0, ++ 0xf8eafecd, ++ 0xff75fa94, ++ 0x082e0009, ++ 0x01f100fe, ++ 0xfd97ff7a, ++ 0x0740ff5a, ++ 0x0496083e, ++ 0xfde002af, ++ 0xf71afd5c, ++ 0x0407089d, ++ 0x0258f991, ++ 0xfe46fdc9, ++ 0x073d0448, ++ 0xfe00f8f0, ++ 0xfd2cfd2c, ++ 0xfce00500, ++ 0xfc09fddc, ++ 0xfe680157, ++ 0x04c70571, ++ 0xfc3aff21, ++ 0xfcd70228, ++ 0x056d0277, ++ 0x0200fe00, ++ 0x0022f927, ++ 0xfe3c032b, ++ 0xfc44ff3c, ++ 0x03e9fbdb, ++ 0x04570313, ++ 0x04c9ff5c, ++ 0x000d03b8, ++ 0xfa580000, ++ 0xfbe900d2, ++ 0xf9d0fe0b, ++ 0x0125fdf9, ++ 0x042501bf, ++ 0x0328fa2b, ++ 0xffa902f0, ++ 0xfa250157, ++ 0x0200fe00, ++ 0x03740438, ++ 0xff0405fd, ++ 0x030cfe52, ++ 0x0037fb39, ++ 0xff6904c5, ++ 0x04f8fd23, ++ 0xfd31fc1b, ++ 0xfd2cfd2c, ++ 0xfc1bfd31, ++ 0xfd2304f8, ++ 0x04c5ff69, ++ 0xfb390037, ++ 0xfe52030c, ++ 0x05fdff04, ++ 0x04380374, ++ 0xfe000200, ++ 0x0157fa25, ++ 0x02f0ffa9, ++ 0xfa2b0328, ++ 0x01bf0425, ++ 0xfdf90125, ++ 0xfe0bf9d0, ++ 0x00d2fbe9, ++ 0x0000fa58, ++ 0x03b8000d, ++ 0xff5c04c9, ++ 0x03130457, ++ 0xfbdb03e9, ++ 0xff3cfc44, ++ 0x032bfe3c, ++ 0xf9270022, ++ 0xfe000200, ++ 0x0277056d, ++ 0x0228fcd7, ++ 0xff21fc3a, ++ 0x057104c7, ++ 0x0157fe68, ++ 0xfddcfc09, ++ 0x0500fce0, ++ 0xfd2cfd2c, ++ 0x0500fce0, ++ 0xfddcfc09, ++ 0x0157fe68, ++ 0x057104c7, ++ 0xff21fc3a, ++ 0x0228fcd7, ++ 0x0277056d, ++ 0xfe000200, ++ 0xf9270022, ++ 0x032bfe3c, ++ 0xff3cfc44, ++ 0xfbdb03e9, ++ 0x03130457, ++ 0xff5c04c9, ++ 0x03b8000d, ++ 0x0000fa58, ++ 0x00d2fbe9, ++ 0xfe0bf9d0, ++ 0xfdf90125, ++ 0x01bf0425, ++ 0xfa2b0328, ++ 0x02f0ffa9, ++ 0x0157fa25, ++ 0xfe000200, ++ 0x04380374, ++ 0x05fdff04, ++ 0xfe52030c, ++ 0xfb390037, ++ 0x04c5ff69, ++ 0xfd2304f8, ++ 0xfc1bfd31, ++ 0xfd2cfd2c, ++ 0xfd31fc1b, ++ 0x04f8fd23, ++ 0xff6904c5, ++ 0x0037fb39, ++ 0x030cfe52, ++ 0xff0405fd, ++ 0x03740438, ++ 0x0200fe00, ++ 0xfa250157, ++ 0xffa902f0, ++ 0x0328fa2b, ++ 0x042501bf, ++ 0x0125fdf9, ++ 0xf9d0fe0b, ++ 0xfbe900d2, ++ 0xfa580000, ++ 0x000d03b8, ++ 0x04c9ff5c, ++ 0x04570313, ++ 0x03e9fbdb, ++ 0xfc44ff3c, ++ 0xfe3c032b, ++ 0x0022f927, ++ 0x0200fe00, ++ 0x056d0277, ++ 0xfcd70228, ++ 0xfc3aff21, ++ 0x04c70571, ++ 0xfe680157, ++ 0xfc09fddc, ++ 0xfce00500, ++ 0x05a80000, ++ 0xff1006be, ++ 0x0800084a, ++ 0xf49cfc7e, ++ 0xfa580400, ++ 0xfc9cf6da, ++ 0xf800f672, ++ 0x0710071c, ++ 0x05a805a8, ++ 0xf8f0f8e4, ++ 0xf800f672, ++ 0x03640926, ++ 0xfa580400, ++ 0x0b640382, ++ 0x0800084a, ++ 0x00f0f942, ++ 0x05a80000, ++ 0xff10f942, ++ 0x0800f7b6, ++ 0xf49c0382, ++ 0xfa58fc00, ++ 0xfc9c0926, ++ 0xf800098e, ++ 0x0710f8e4, ++ 0x05a8fa58, ++ 0xf8f0071c, ++ 0xf800098e, ++ 0x0364f6da, ++ 0xfa58fc00, ++ 0x0b64fc7e, ++ 0x0800f7b6, ++ 0x00f006be, ++ 0x05a80000, ++ 0xff1006be, ++ 0x0800084a, ++ 0xf49cfc7e, ++ 0xfa580400, ++ 0xfc9cf6da, ++ 0xf800f672, ++ 0x0710071c, ++ 0x05a805a8, ++ 0xf8f0f8e4, ++ 0xf800f672, ++ 0x03640926, ++ 0xfa580400, ++ 0x0b640382, ++ 0x0800084a, ++ 0x00f0f942, ++ 0x05a80000, ++ 0xff10f942, ++ 0x0800f7b6, ++ 0xf49c0382, ++ 0xfa58fc00, ++ 0xfc9c0926, ++ 0xf800098e, ++ 0x0710f8e4, ++ 0x05a8fa58, ++ 0xf8f0071c, ++ 0xf800098e, ++ 0x0364f6da, ++ 0xfa58fc00, ++ 0x0b64fc7e, ++ 0x0800f7b6, ++ 0x00f006be, ++}; ++ ++static const u32 intlv_tbl_rev0[] = { ++ 0x00802070, ++ 0x0671188d, ++ 0x0a60192c, ++ 0x0a300e46, ++ 0x00c1188d, ++ 0x080024d2, ++ 0x00000070, ++}; ++ ++static const u16 pilot_tbl_rev0[] = { ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0xff0a, ++ 0xff82, ++ 0xffa0, ++ 0xff28, ++ 0xffff, ++ 0xffff, ++ 0xffff, ++ 0xffff, ++ 0xff82, ++ 0xffa0, ++ 0xff28, ++ 0xff0a, ++ 0xffff, ++ 0xffff, ++ 0xffff, ++ 0xffff, ++ 0xf83f, ++ 0xfa1f, ++ 0xfa97, ++ 0xfab5, ++ 0xf2bd, ++ 0xf0bf, ++ 0xffff, ++ 0xffff, ++ 0xf017, ++ 0xf815, ++ 0xf215, ++ 0xf095, ++ 0xf035, ++ 0xf01d, ++ 0xffff, ++ 0xffff, ++ 0xff08, ++ 0xff02, ++ 0xff80, ++ 0xff20, ++ 0xff08, ++ 0xff02, ++ 0xff80, ++ 0xff20, ++ 0xf01f, ++ 0xf817, ++ 0xfa15, ++ 0xf295, ++ 0xf0b5, ++ 0xf03d, ++ 0xffff, ++ 0xffff, ++ 0xf82a, ++ 0xfa0a, ++ 0xfa82, ++ 0xfaa0, ++ 0xf2a8, ++ 0xf0aa, ++ 0xffff, ++ 0xffff, ++ 0xf002, ++ 0xf800, ++ 0xf200, ++ 0xf080, ++ 0xf020, ++ 0xf008, ++ 0xffff, ++ 0xffff, ++ 0xf00a, ++ 0xf802, ++ 0xfa00, ++ 0xf280, ++ 0xf0a0, ++ 0xf028, ++ 0xffff, ++ 0xffff, ++}; ++ ++static const u32 pltlut_tbl_rev0[] = { ++ 0x76540123, ++ 0x62407351, ++ 0x76543201, ++ 0x76540213, ++ 0x76540123, ++ 0x76430521, ++}; ++ ++static const u32 tdi_tbl20_ant0_rev0[] = { ++ 0x00091226, ++ 0x000a1429, ++ 0x000b56ad, ++ 0x000c58b0, ++ 0x000d5ab3, ++ 0x000e9cb6, ++ 0x000f9eba, ++ 0x0000c13d, ++ 0x00020301, ++ 0x00030504, ++ 0x00040708, ++ 0x0005090b, ++ 0x00064b8e, ++ 0x00095291, ++ 0x000a5494, ++ 0x000b9718, ++ 0x000c9927, ++ 0x000d9b2a, ++ 0x000edd2e, ++ 0x000fdf31, ++ 0x000101b4, ++ 0x000243b7, ++ 0x000345bb, ++ 0x000447be, ++ 0x00058982, ++ 0x00068c05, ++ 0x00099309, ++ 0x000a950c, ++ 0x000bd78f, ++ 0x000cd992, ++ 0x000ddb96, ++ 0x000f1d99, ++ 0x00005fa8, ++ 0x0001422c, ++ 0x0002842f, ++ 0x00038632, ++ 0x00048835, ++ 0x0005ca38, ++ 0x0006ccbc, ++ 0x0009d3bf, ++ 0x000b1603, ++ 0x000c1806, ++ 0x000d1a0a, ++ 0x000e1c0d, ++ 0x000f5e10, ++ 0x00008093, ++ 0x00018297, ++ 0x0002c49a, ++ 0x0003c680, ++ 0x0004c880, ++ 0x00060b00, ++ 0x00070d00, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 tdi_tbl20_ant1_rev0[] = { ++ 0x00014b26, ++ 0x00028d29, ++ 0x000393ad, ++ 0x00049630, ++ 0x0005d833, ++ 0x0006da36, ++ 0x00099c3a, ++ 0x000a9e3d, ++ 0x000bc081, ++ 0x000cc284, ++ 0x000dc488, ++ 0x000f068b, ++ 0x0000488e, ++ 0x00018b91, ++ 0x0002d214, ++ 0x0003d418, ++ 0x0004d6a7, ++ 0x000618aa, ++ 0x00071aae, ++ 0x0009dcb1, ++ 0x000b1eb4, ++ 0x000c0137, ++ 0x000d033b, ++ 0x000e053e, ++ 0x000f4702, ++ 0x00008905, ++ 0x00020c09, ++ 0x0003128c, ++ 0x0004148f, ++ 0x00051712, ++ 0x00065916, ++ 0x00091b19, ++ 0x000a1d28, ++ 0x000b5f2c, ++ 0x000c41af, ++ 0x000d43b2, ++ 0x000e85b5, ++ 0x000f87b8, ++ 0x0000c9bc, ++ 0x00024cbf, ++ 0x00035303, ++ 0x00045506, ++ 0x0005978a, ++ 0x0006998d, ++ 0x00095b90, ++ 0x000a5d93, ++ 0x000b9f97, ++ 0x000c821a, ++ 0x000d8400, ++ 0x000ec600, ++ 0x000fc800, ++ 0x00010a00, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 tdi_tbl40_ant0_rev0[] = { ++ 0x0011a346, ++ 0x00136ccf, ++ 0x0014f5d9, ++ 0x001641e2, ++ 0x0017cb6b, ++ 0x00195475, ++ 0x001b2383, ++ 0x001cad0c, ++ 0x001e7616, ++ 0x0000821f, ++ 0x00020ba8, ++ 0x0003d4b2, ++ 0x00056447, ++ 0x00072dd0, ++ 0x0008b6da, ++ 0x000a02e3, ++ 0x000b8c6c, ++ 0x000d15f6, ++ 0x0011e484, ++ 0x0013ae0d, ++ 0x00153717, ++ 0x00168320, ++ 0x00180ca9, ++ 0x00199633, ++ 0x001b6548, ++ 0x001ceed1, ++ 0x001eb7db, ++ 0x0000c3e4, ++ 0x00024d6d, ++ 0x000416f7, ++ 0x0005a585, ++ 0x00076f0f, ++ 0x0008f818, ++ 0x000a4421, ++ 0x000bcdab, ++ 0x000d9734, ++ 0x00122649, ++ 0x0013efd2, ++ 0x001578dc, ++ 0x0016c4e5, ++ 0x00184e6e, ++ 0x001a17f8, ++ 0x001ba686, ++ 0x001d3010, ++ 0x001ef999, ++ 0x00010522, ++ 0x00028eac, ++ 0x00045835, ++ 0x0005e74a, ++ 0x0007b0d3, ++ 0x00093a5d, ++ 0x000a85e6, ++ 0x000c0f6f, ++ 0x000dd8f9, ++ 0x00126787, ++ 0x00143111, ++ 0x0015ba9a, ++ 0x00170623, ++ 0x00188fad, ++ 0x001a5936, ++ 0x001be84b, ++ 0x001db1d4, ++ 0x001f3b5e, ++ 0x000146e7, ++ 0x00031070, ++ 0x000499fa, ++ 0x00062888, ++ 0x0007f212, ++ 0x00097b9b, ++ 0x000ac7a4, ++ 0x000c50ae, ++ 0x000e1a37, ++ 0x0012a94c, ++ 0x001472d5, ++ 0x0015fc5f, ++ 0x00174868, ++ 0x0018d171, ++ 0x001a9afb, ++ 0x001c2989, ++ 0x001df313, ++ 0x001f7c9c, ++ 0x000188a5, ++ 0x000351af, ++ 0x0004db38, ++ 0x0006aa4d, ++ 0x000833d7, ++ 0x0009bd60, ++ 0x000b0969, ++ 0x000c9273, ++ 0x000e5bfc, ++ 0x00132a8a, ++ 0x0014b414, ++ 0x00163d9d, ++ 0x001789a6, ++ 0x001912b0, ++ 0x001adc39, ++ 0x001c6bce, ++ 0x001e34d8, ++ 0x001fbe61, ++ 0x0001ca6a, ++ 0x00039374, ++ 0x00051cfd, ++ 0x0006ec0b, ++ 0x00087515, ++ 0x0009fe9e, ++ 0x000b4aa7, ++ 0x000cd3b1, ++ 0x000e9d3a, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 tdi_tbl40_ant1_rev0[] = { ++ 0x001edb36, ++ 0x000129ca, ++ 0x0002b353, ++ 0x00047cdd, ++ 0x0005c8e6, ++ 0x000791ef, ++ 0x00091bf9, ++ 0x000aaa07, ++ 0x000c3391, ++ 0x000dfd1a, ++ 0x00120923, ++ 0x0013d22d, ++ 0x00155c37, ++ 0x0016eacb, ++ 0x00187454, ++ 0x001a3dde, ++ 0x001b89e7, ++ 0x001d12f0, ++ 0x001f1cfa, ++ 0x00016b88, ++ 0x00033492, ++ 0x0004be1b, ++ 0x00060a24, ++ 0x0007d32e, ++ 0x00095d38, ++ 0x000aec4c, ++ 0x000c7555, ++ 0x000e3edf, ++ 0x00124ae8, ++ 0x001413f1, ++ 0x0015a37b, ++ 0x00172c89, ++ 0x0018b593, ++ 0x001a419c, ++ 0x001bcb25, ++ 0x001d942f, ++ 0x001f63b9, ++ 0x0001ad4d, ++ 0x00037657, ++ 0x0004c260, ++ 0x00068be9, ++ 0x000814f3, ++ 0x0009a47c, ++ 0x000b2d8a, ++ 0x000cb694, ++ 0x000e429d, ++ 0x00128c26, ++ 0x001455b0, ++ 0x0015e4ba, ++ 0x00176e4e, ++ 0x0018f758, ++ 0x001a8361, ++ 0x001c0cea, ++ 0x001dd674, ++ 0x001fa57d, ++ 0x0001ee8b, ++ 0x0003b795, ++ 0x0005039e, ++ 0x0006cd27, ++ 0x000856b1, ++ 0x0009e5c6, ++ 0x000b6f4f, ++ 0x000cf859, ++ 0x000e8462, ++ 0x00130deb, ++ 0x00149775, ++ 0x00162603, ++ 0x0017af8c, ++ 0x00193896, ++ 0x001ac49f, ++ 0x001c4e28, ++ 0x001e17b2, ++ 0x0000a6c7, ++ 0x00023050, ++ 0x0003f9da, ++ 0x00054563, ++ 0x00070eec, ++ 0x00089876, ++ 0x000a2704, ++ 0x000bb08d, ++ 0x000d3a17, ++ 0x001185a0, ++ 0x00134f29, ++ 0x0014d8b3, ++ 0x001667c8, ++ 0x0017f151, ++ 0x00197adb, ++ 0x001b0664, ++ 0x001c8fed, ++ 0x001e5977, ++ 0x0000e805, ++ 0x0002718f, ++ 0x00043b18, ++ 0x000586a1, ++ 0x0007502b, ++ 0x0008d9b4, ++ 0x000a68c9, ++ 0x000bf252, ++ 0x000dbbdc, ++ 0x0011c7e5, ++ 0x001390ee, ++ 0x00151a78, ++ 0x0016a906, ++ 0x00183290, ++ 0x0019bc19, ++ 0x001b4822, ++ 0x001cd12c, ++ 0x001e9ab5, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u16 bdi_tbl_rev0[] = { ++ 0x0070, ++ 0x0126, ++ 0x012c, ++ 0x0246, ++ 0x048d, ++ 0x04d2, ++}; ++ ++static const u32 chanest_tbl_rev0[] = { ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++}; ++ ++static const u8 mcs_tbl_rev0[] = { ++ 0x00, ++ 0x08, ++ 0x0a, ++ 0x10, ++ 0x12, ++ 0x19, ++ 0x1a, ++ 0x1c, ++ 0x40, ++ 0x48, ++ 0x4a, ++ 0x50, ++ 0x52, ++ 0x59, ++ 0x5a, ++ 0x5c, ++ 0x80, ++ 0x88, ++ 0x8a, ++ 0x90, ++ 0x92, ++ 0x99, ++ 0x9a, ++ 0x9c, ++ 0xc0, ++ 0xc8, ++ 0xca, ++ 0xd0, ++ 0xd2, ++ 0xd9, ++ 0xda, ++ 0xdc, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x01, ++ 0x02, ++ 0x04, ++ 0x08, ++ 0x09, ++ 0x0a, ++ 0x0c, ++ 0x10, ++ 0x11, ++ 0x12, ++ 0x14, ++ 0x18, ++ 0x19, ++ 0x1a, ++ 0x1c, ++ 0x20, ++ 0x21, ++ 0x22, ++ 0x24, ++ 0x40, ++ 0x41, ++ 0x42, ++ 0x44, ++ 0x48, ++ 0x49, ++ 0x4a, ++ 0x4c, ++ 0x50, ++ 0x51, ++ 0x52, ++ 0x54, ++ 0x58, ++ 0x59, ++ 0x5a, ++ 0x5c, ++ 0x60, ++ 0x61, ++ 0x62, ++ 0x64, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++}; ++ ++static const u32 noise_var_tbl0_rev0[] = { ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++}; ++ ++static const u32 noise_var_tbl1_rev0[] = { ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++}; ++ ++static const u8 est_pwr_lut_core0_rev0[] = { ++ 0x50, ++ 0x4f, ++ 0x4e, ++ 0x4d, ++ 0x4c, ++ 0x4b, ++ 0x4a, ++ 0x49, ++ 0x48, ++ 0x47, ++ 0x46, ++ 0x45, ++ 0x44, ++ 0x43, ++ 0x42, ++ 0x41, ++ 0x40, ++ 0x3f, ++ 0x3e, ++ 0x3d, ++ 0x3c, ++ 0x3b, ++ 0x3a, ++ 0x39, ++ 0x38, ++ 0x37, ++ 0x36, ++ 0x35, ++ 0x34, ++ 0x33, ++ 0x32, ++ 0x31, ++ 0x30, ++ 0x2f, ++ 0x2e, ++ 0x2d, ++ 0x2c, ++ 0x2b, ++ 0x2a, ++ 0x29, ++ 0x28, ++ 0x27, ++ 0x26, ++ 0x25, ++ 0x24, ++ 0x23, ++ 0x22, ++ 0x21, ++ 0x20, ++ 0x1f, ++ 0x1e, ++ 0x1d, ++ 0x1c, ++ 0x1b, ++ 0x1a, ++ 0x19, ++ 0x18, ++ 0x17, ++ 0x16, ++ 0x15, ++ 0x14, ++ 0x13, ++ 0x12, ++ 0x11, ++}; ++ ++static const u8 est_pwr_lut_core1_rev0[] = { ++ 0x50, ++ 0x4f, ++ 0x4e, ++ 0x4d, ++ 0x4c, ++ 0x4b, ++ 0x4a, ++ 0x49, ++ 0x48, ++ 0x47, ++ 0x46, ++ 0x45, ++ 0x44, ++ 0x43, ++ 0x42, ++ 0x41, ++ 0x40, ++ 0x3f, ++ 0x3e, ++ 0x3d, ++ 0x3c, ++ 0x3b, ++ 0x3a, ++ 0x39, ++ 0x38, ++ 0x37, ++ 0x36, ++ 0x35, ++ 0x34, ++ 0x33, ++ 0x32, ++ 0x31, ++ 0x30, ++ 0x2f, ++ 0x2e, ++ 0x2d, ++ 0x2c, ++ 0x2b, ++ 0x2a, ++ 0x29, ++ 0x28, ++ 0x27, ++ 0x26, ++ 0x25, ++ 0x24, ++ 0x23, ++ 0x22, ++ 0x21, ++ 0x20, ++ 0x1f, ++ 0x1e, ++ 0x1d, ++ 0x1c, ++ 0x1b, ++ 0x1a, ++ 0x19, ++ 0x18, ++ 0x17, ++ 0x16, ++ 0x15, ++ 0x14, ++ 0x13, ++ 0x12, ++ 0x11, ++}; ++ ++static const u8 adj_pwr_lut_core0_rev0[] = { ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++}; ++ ++static const u8 adj_pwr_lut_core1_rev0[] = { ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++}; ++ ++static const u32 gainctrl_lut_core0_rev0[] = { ++ 0x03cc2b44, ++ 0x03cc2b42, ++ 0x03cc2b40, ++ 0x03cc2b3e, ++ 0x03cc2b3d, ++ 0x03cc2b3b, ++ 0x03c82b44, ++ 0x03c82b42, ++ 0x03c82b40, ++ 0x03c82b3e, ++ 0x03c82b3d, ++ 0x03c82b3b, ++ 0x03c82b39, ++ 0x03c82b38, ++ 0x03c82b36, ++ 0x03c82b34, ++ 0x03c42b44, ++ 0x03c42b42, ++ 0x03c42b40, ++ 0x03c42b3e, ++ 0x03c42b3d, ++ 0x03c42b3b, ++ 0x03c42b39, ++ 0x03c42b38, ++ 0x03c42b36, ++ 0x03c42b34, ++ 0x03c42b33, ++ 0x03c42b32, ++ 0x03c42b30, ++ 0x03c42b2f, ++ 0x03c42b2d, ++ 0x03c02b44, ++ 0x03c02b42, ++ 0x03c02b40, ++ 0x03c02b3e, ++ 0x03c02b3d, ++ 0x03c02b3b, ++ 0x03c02b39, ++ 0x03c02b38, ++ 0x03c02b36, ++ 0x03c02b34, ++ 0x03b02b44, ++ 0x03b02b42, ++ 0x03b02b40, ++ 0x03b02b3e, ++ 0x03b02b3d, ++ 0x03b02b3b, ++ 0x03b02b39, ++ 0x03b02b38, ++ 0x03b02b36, ++ 0x03b02b34, ++ 0x03b02b33, ++ 0x03b02b32, ++ 0x03b02b30, ++ 0x03b02b2f, ++ 0x03b02b2d, ++ 0x03a02b44, ++ 0x03a02b42, ++ 0x03a02b40, ++ 0x03a02b3e, ++ 0x03a02b3d, ++ 0x03a02b3b, ++ 0x03a02b39, ++ 0x03a02b38, ++ 0x03a02b36, ++ 0x03a02b34, ++ 0x03902b44, ++ 0x03902b42, ++ 0x03902b40, ++ 0x03902b3e, ++ 0x03902b3d, ++ 0x03902b3b, ++ 0x03902b39, ++ 0x03902b38, ++ 0x03902b36, ++ 0x03902b34, ++ 0x03902b33, ++ 0x03902b32, ++ 0x03902b30, ++ 0x03802b44, ++ 0x03802b42, ++ 0x03802b40, ++ 0x03802b3e, ++ 0x03802b3d, ++ 0x03802b3b, ++ 0x03802b39, ++ 0x03802b38, ++ 0x03802b36, ++ 0x03802b34, ++ 0x03802b33, ++ 0x03802b32, ++ 0x03802b30, ++ 0x03802b2f, ++ 0x03802b2d, ++ 0x03802b2c, ++ 0x03802b2b, ++ 0x03802b2a, ++ 0x03802b29, ++ 0x03802b27, ++ 0x03802b26, ++ 0x03802b25, ++ 0x03802b24, ++ 0x03802b23, ++ 0x03802b22, ++ 0x03802b21, ++ 0x03802b20, ++ 0x03802b1f, ++ 0x03802b1e, ++ 0x03802b1e, ++ 0x03802b1d, ++ 0x03802b1c, ++ 0x03802b1b, ++ 0x03802b1a, ++ 0x03802b1a, ++ 0x03802b19, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x00002b00, ++}; ++ ++static const u32 gainctrl_lut_core1_rev0[] = { ++ 0x03cc2b44, ++ 0x03cc2b42, ++ 0x03cc2b40, ++ 0x03cc2b3e, ++ 0x03cc2b3d, ++ 0x03cc2b3b, ++ 0x03c82b44, ++ 0x03c82b42, ++ 0x03c82b40, ++ 0x03c82b3e, ++ 0x03c82b3d, ++ 0x03c82b3b, ++ 0x03c82b39, ++ 0x03c82b38, ++ 0x03c82b36, ++ 0x03c82b34, ++ 0x03c42b44, ++ 0x03c42b42, ++ 0x03c42b40, ++ 0x03c42b3e, ++ 0x03c42b3d, ++ 0x03c42b3b, ++ 0x03c42b39, ++ 0x03c42b38, ++ 0x03c42b36, ++ 0x03c42b34, ++ 0x03c42b33, ++ 0x03c42b32, ++ 0x03c42b30, ++ 0x03c42b2f, ++ 0x03c42b2d, ++ 0x03c02b44, ++ 0x03c02b42, ++ 0x03c02b40, ++ 0x03c02b3e, ++ 0x03c02b3d, ++ 0x03c02b3b, ++ 0x03c02b39, ++ 0x03c02b38, ++ 0x03c02b36, ++ 0x03c02b34, ++ 0x03b02b44, ++ 0x03b02b42, ++ 0x03b02b40, ++ 0x03b02b3e, ++ 0x03b02b3d, ++ 0x03b02b3b, ++ 0x03b02b39, ++ 0x03b02b38, ++ 0x03b02b36, ++ 0x03b02b34, ++ 0x03b02b33, ++ 0x03b02b32, ++ 0x03b02b30, ++ 0x03b02b2f, ++ 0x03b02b2d, ++ 0x03a02b44, ++ 0x03a02b42, ++ 0x03a02b40, ++ 0x03a02b3e, ++ 0x03a02b3d, ++ 0x03a02b3b, ++ 0x03a02b39, ++ 0x03a02b38, ++ 0x03a02b36, ++ 0x03a02b34, ++ 0x03902b44, ++ 0x03902b42, ++ 0x03902b40, ++ 0x03902b3e, ++ 0x03902b3d, ++ 0x03902b3b, ++ 0x03902b39, ++ 0x03902b38, ++ 0x03902b36, ++ 0x03902b34, ++ 0x03902b33, ++ 0x03902b32, ++ 0x03902b30, ++ 0x03802b44, ++ 0x03802b42, ++ 0x03802b40, ++ 0x03802b3e, ++ 0x03802b3d, ++ 0x03802b3b, ++ 0x03802b39, ++ 0x03802b38, ++ 0x03802b36, ++ 0x03802b34, ++ 0x03802b33, ++ 0x03802b32, ++ 0x03802b30, ++ 0x03802b2f, ++ 0x03802b2d, ++ 0x03802b2c, ++ 0x03802b2b, ++ 0x03802b2a, ++ 0x03802b29, ++ 0x03802b27, ++ 0x03802b26, ++ 0x03802b25, ++ 0x03802b24, ++ 0x03802b23, ++ 0x03802b22, ++ 0x03802b21, ++ 0x03802b20, ++ 0x03802b1f, ++ 0x03802b1e, ++ 0x03802b1e, ++ 0x03802b1d, ++ 0x03802b1c, ++ 0x03802b1b, ++ 0x03802b1a, ++ 0x03802b1a, ++ 0x03802b19, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x03802b18, ++ 0x00002b00, ++}; ++ ++static const u32 iq_lut_core0_rev0[] = { ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++}; ++ ++static const u32 iq_lut_core1_rev0[] = { ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++ 0x0000007f, ++}; ++ ++static const u16 loft_lut_core0_rev0[] = { ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++}; ++ ++static const u16 loft_lut_core1_rev0[] = { ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++ 0x0000, ++ 0x0101, ++ 0x0002, ++ 0x0103, ++}; ++ ++const struct phytbl_info mimophytbl_info_rev0_volatile[] = { ++ {&bdi_tbl_rev0, sizeof(bdi_tbl_rev0) / sizeof(bdi_tbl_rev0[0]), 21, 0, ++ 16} ++ , ++ {&pltlut_tbl_rev0, sizeof(pltlut_tbl_rev0) / sizeof(pltlut_tbl_rev0[0]), ++ 20, 0, 32} ++ , ++ {&gainctrl_lut_core0_rev0, ++ sizeof(gainctrl_lut_core0_rev0) / sizeof(gainctrl_lut_core0_rev0[0]), ++ 26, 192, 32} ++ , ++ {&gainctrl_lut_core1_rev0, ++ sizeof(gainctrl_lut_core1_rev0) / sizeof(gainctrl_lut_core1_rev0[0]), ++ 27, 192, 32} ++ , ++ ++ {&est_pwr_lut_core0_rev0, ++ sizeof(est_pwr_lut_core0_rev0) / sizeof(est_pwr_lut_core0_rev0[0]), 26, ++ 0, 8} ++ , ++ {&est_pwr_lut_core1_rev0, ++ sizeof(est_pwr_lut_core1_rev0) / sizeof(est_pwr_lut_core1_rev0[0]), 27, ++ 0, 8} ++ , ++ {&adj_pwr_lut_core0_rev0, ++ sizeof(adj_pwr_lut_core0_rev0) / sizeof(adj_pwr_lut_core0_rev0[0]), 26, ++ 64, 8} ++ , ++ {&adj_pwr_lut_core1_rev0, ++ sizeof(adj_pwr_lut_core1_rev0) / sizeof(adj_pwr_lut_core1_rev0[0]), 27, ++ 64, 8} ++ , ++ {&iq_lut_core0_rev0, ++ sizeof(iq_lut_core0_rev0) / sizeof(iq_lut_core0_rev0[0]), 26, 320, 32} ++ , ++ {&iq_lut_core1_rev0, ++ sizeof(iq_lut_core1_rev0) / sizeof(iq_lut_core1_rev0[0]), 27, 320, 32} ++ , ++ {&loft_lut_core0_rev0, ++ sizeof(loft_lut_core0_rev0) / sizeof(loft_lut_core0_rev0[0]), 26, 448, ++ 16} ++ , ++ {&loft_lut_core1_rev0, ++ sizeof(loft_lut_core1_rev0) / sizeof(loft_lut_core1_rev0[0]), 27, 448, ++ 16} ++ , ++}; ++ ++const struct phytbl_info mimophytbl_info_rev0[] = { ++ {&frame_struct_rev0, ++ sizeof(frame_struct_rev0) / sizeof(frame_struct_rev0[0]), 10, 0, 32} ++ , ++ {&frame_lut_rev0, sizeof(frame_lut_rev0) / sizeof(frame_lut_rev0[0]), ++ 24, 0, 8} ++ , ++ {&tmap_tbl_rev0, sizeof(tmap_tbl_rev0) / sizeof(tmap_tbl_rev0[0]), 12, ++ 0, 32} ++ , ++ {&tdtrn_tbl_rev0, sizeof(tdtrn_tbl_rev0) / sizeof(tdtrn_tbl_rev0[0]), ++ 14, 0, 32} ++ , ++ {&intlv_tbl_rev0, sizeof(intlv_tbl_rev0) / sizeof(intlv_tbl_rev0[0]), ++ 13, 0, 32} ++ , ++ {&pilot_tbl_rev0, sizeof(pilot_tbl_rev0) / sizeof(pilot_tbl_rev0[0]), ++ 11, 0, 16} ++ , ++ {&tdi_tbl20_ant0_rev0, ++ sizeof(tdi_tbl20_ant0_rev0) / sizeof(tdi_tbl20_ant0_rev0[0]), 19, 128, ++ 32} ++ , ++ {&tdi_tbl20_ant1_rev0, ++ sizeof(tdi_tbl20_ant1_rev0) / sizeof(tdi_tbl20_ant1_rev0[0]), 19, 256, ++ 32} ++ , ++ {&tdi_tbl40_ant0_rev0, ++ sizeof(tdi_tbl40_ant0_rev0) / sizeof(tdi_tbl40_ant0_rev0[0]), 19, 640, ++ 32} ++ , ++ {&tdi_tbl40_ant1_rev0, ++ sizeof(tdi_tbl40_ant1_rev0) / sizeof(tdi_tbl40_ant1_rev0[0]), 19, 768, ++ 32} ++ , ++ {&chanest_tbl_rev0, ++ sizeof(chanest_tbl_rev0) / sizeof(chanest_tbl_rev0[0]), 22, 0, 32} ++ , ++ {&mcs_tbl_rev0, sizeof(mcs_tbl_rev0) / sizeof(mcs_tbl_rev0[0]), 18, 0, ++ 8} ++ , ++ {&noise_var_tbl0_rev0, ++ sizeof(noise_var_tbl0_rev0) / sizeof(noise_var_tbl0_rev0[0]), 16, 0, ++ 32} ++ , ++ {&noise_var_tbl1_rev0, ++ sizeof(noise_var_tbl1_rev0) / sizeof(noise_var_tbl1_rev0[0]), 16, 128, ++ 32} ++ , ++}; ++ ++const u32 mimophytbl_info_sz_rev0 = ++ sizeof(mimophytbl_info_rev0) / sizeof(mimophytbl_info_rev0[0]); ++const u32 mimophytbl_info_sz_rev0_volatile = ++ sizeof(mimophytbl_info_rev0_volatile) / ++ sizeof(mimophytbl_info_rev0_volatile[0]); ++ ++static const u16 ant_swctrl_tbl_rev3[] = { ++ 0x0082, ++ 0x0082, ++ 0x0211, ++ 0x0222, ++ 0x0328, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0144, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0188, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0082, ++ 0x0082, ++ 0x0211, ++ 0x0222, ++ 0x0328, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0144, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0188, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++}; ++ ++static const u16 ant_swctrl_tbl_rev3_1[] = { ++ 0x0022, ++ 0x0022, ++ 0x0011, ++ 0x0022, ++ 0x0022, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0011, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0022, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0022, ++ 0x0022, ++ 0x0011, ++ 0x0022, ++ 0x0022, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0011, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0022, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++}; ++ ++static const u16 ant_swctrl_tbl_rev3_2[] = { ++ 0x0088, ++ 0x0088, ++ 0x0044, ++ 0x0088, ++ 0x0088, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0044, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0088, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0088, ++ 0x0088, ++ 0x0044, ++ 0x0088, ++ 0x0088, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0044, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0088, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++}; ++ ++static const u16 ant_swctrl_tbl_rev3_3[] = { ++ 0x022, ++ 0x022, ++ 0x011, ++ 0x022, ++ 0x000, ++ 0x000, ++ 0x000, ++ 0x000, ++ 0x011, ++ 0x000, ++ 0x000, ++ 0x000, ++ 0x022, ++ 0x000, ++ 0x000, ++ 0x3cc, ++ 0x022, ++ 0x022, ++ 0x011, ++ 0x022, ++ 0x000, ++ 0x000, ++ 0x000, ++ 0x000, ++ 0x011, ++ 0x000, ++ 0x000, ++ 0x000, ++ 0x022, ++ 0x000, ++ 0x000, ++ 0x3cc ++}; ++ ++static const u32 frame_struct_rev3[] = { ++ 0x08004a04, ++ 0x00100000, ++ 0x01000a05, ++ 0x00100020, ++ 0x09804506, ++ 0x00100030, ++ 0x09804507, ++ 0x00100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x08004a0c, ++ 0x00100004, ++ 0x01000a0d, ++ 0x00100024, ++ 0x0980450e, ++ 0x00100034, ++ 0x0980450f, ++ 0x00100034, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000a04, ++ 0x00100000, ++ 0x11008a05, ++ 0x00100020, ++ 0x1980c506, ++ 0x00100030, ++ 0x21810506, ++ 0x00100030, ++ 0x21810506, ++ 0x00100030, ++ 0x01800504, ++ 0x00100030, ++ 0x11808505, ++ 0x00100030, ++ 0x29814507, ++ 0x01100030, ++ 0x00000a04, ++ 0x00100000, ++ 0x11008a05, ++ 0x00100020, ++ 0x21810506, ++ 0x00100030, ++ 0x21810506, ++ 0x00100030, ++ 0x29814507, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000a0c, ++ 0x00100008, ++ 0x11008a0d, ++ 0x00100028, ++ 0x1980c50e, ++ 0x00100038, ++ 0x2181050e, ++ 0x00100038, ++ 0x2181050e, ++ 0x00100038, ++ 0x0180050c, ++ 0x00100038, ++ 0x1180850d, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000a0c, ++ 0x00100008, ++ 0x11008a0d, ++ 0x00100028, ++ 0x2181050e, ++ 0x00100038, ++ 0x2181050e, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x08004a04, ++ 0x00100000, ++ 0x01000a05, ++ 0x00100020, ++ 0x1980c506, ++ 0x00100030, ++ 0x1980c506, ++ 0x00100030, ++ 0x11808504, ++ 0x00100030, ++ 0x3981ca05, ++ 0x00100030, ++ 0x29814507, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x10008a04, ++ 0x00100000, ++ 0x3981ca05, ++ 0x00100030, ++ 0x1980c506, ++ 0x00100030, ++ 0x29814507, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x08004a0c, ++ 0x00100008, ++ 0x01000a0d, ++ 0x00100028, ++ 0x1980c50e, ++ 0x00100038, ++ 0x1980c50e, ++ 0x00100038, ++ 0x1180850c, ++ 0x00100038, ++ 0x3981ca0d, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x10008a0c, ++ 0x00100008, ++ 0x3981ca0d, ++ 0x00100038, ++ 0x1980c50e, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x40021404, ++ 0x00100000, ++ 0x02001405, ++ 0x00100040, ++ 0x0b004a06, ++ 0x01900060, ++ 0x13008a06, ++ 0x01900060, ++ 0x13008a06, ++ 0x01900060, ++ 0x43020a04, ++ 0x00100060, ++ 0x1b00ca05, ++ 0x00100060, ++ 0x23010a07, ++ 0x01500060, ++ 0x40021404, ++ 0x00100000, ++ 0x1a00d405, ++ 0x00100040, ++ 0x13008a06, ++ 0x01900060, ++ 0x13008a06, ++ 0x01900060, ++ 0x23010a07, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100010, ++ 0x0200140d, ++ 0x00100050, ++ 0x0b004a0e, ++ 0x01900070, ++ 0x13008a0e, ++ 0x01900070, ++ 0x13008a0e, ++ 0x01900070, ++ 0x43020a0c, ++ 0x00100070, ++ 0x1b00ca0d, ++ 0x00100070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x4002140c, ++ 0x00100010, ++ 0x1a00d40d, ++ 0x00100050, ++ 0x13008a0e, ++ 0x01900070, ++ 0x13008a0e, ++ 0x01900070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x50029404, ++ 0x00100000, ++ 0x32019405, ++ 0x00100040, ++ 0x0b004a06, ++ 0x01900060, ++ 0x0b004a06, ++ 0x01900060, ++ 0x5b02ca04, ++ 0x00100060, ++ 0x3b01d405, ++ 0x00100060, ++ 0x23010a07, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x5802d404, ++ 0x00100000, ++ 0x3b01d405, ++ 0x00100060, ++ 0x0b004a06, ++ 0x01900060, ++ 0x23010a07, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x5002940c, ++ 0x00100010, ++ 0x3201940d, ++ 0x00100050, ++ 0x0b004a0e, ++ 0x01900070, ++ 0x0b004a0e, ++ 0x01900070, ++ 0x5b02ca0c, ++ 0x00100070, ++ 0x3b01d40d, ++ 0x00100070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x5802d40c, ++ 0x00100010, ++ 0x3b01d40d, ++ 0x00100070, ++ 0x0b004a0e, ++ 0x01900070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x40021404, ++ 0x000f4800, ++ 0x62031405, ++ 0x00100040, ++ 0x53028a06, ++ 0x01900060, ++ 0x53028a07, ++ 0x01900060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x000f4808, ++ 0x6203140d, ++ 0x00100048, ++ 0x53028a0e, ++ 0x01900068, ++ 0x53028a0f, ++ 0x01900068, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000a0c, ++ 0x00100004, ++ 0x11008a0d, ++ 0x00100024, ++ 0x1980c50e, ++ 0x00100034, ++ 0x2181050e, ++ 0x00100034, ++ 0x2181050e, ++ 0x00100034, ++ 0x0180050c, ++ 0x00100038, ++ 0x1180850d, ++ 0x00100038, ++ 0x1181850d, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000a0c, ++ 0x00100008, ++ 0x11008a0d, ++ 0x00100028, ++ 0x2181050e, ++ 0x00100038, ++ 0x2181050e, ++ 0x00100038, ++ 0x1181850d, ++ 0x00100038, ++ 0x2981450f, ++ 0x01100038, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x08004a04, ++ 0x00100000, ++ 0x01000a05, ++ 0x00100020, ++ 0x0180c506, ++ 0x00100030, ++ 0x0180c506, ++ 0x00100030, ++ 0x2180c50c, ++ 0x00100030, ++ 0x49820a0d, ++ 0x0016a130, ++ 0x41824a0d, ++ 0x0016a130, ++ 0x2981450f, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x2000ca0c, ++ 0x00100000, ++ 0x49820a0d, ++ 0x0016a130, ++ 0x1980c50e, ++ 0x00100030, ++ 0x41824a0d, ++ 0x0016a130, ++ 0x2981450f, ++ 0x01100030, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100008, ++ 0x0200140d, ++ 0x00100048, ++ 0x0b004a0e, ++ 0x01900068, ++ 0x13008a0e, ++ 0x01900068, ++ 0x13008a0e, ++ 0x01900068, ++ 0x43020a0c, ++ 0x00100070, ++ 0x1b00ca0d, ++ 0x00100070, ++ 0x1b014a0d, ++ 0x00100070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100010, ++ 0x1a00d40d, ++ 0x00100050, ++ 0x13008a0e, ++ 0x01900070, ++ 0x13008a0e, ++ 0x01900070, ++ 0x1b014a0d, ++ 0x00100070, ++ 0x23010a0f, ++ 0x01500070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x50029404, ++ 0x00100000, ++ 0x32019405, ++ 0x00100040, ++ 0x03004a06, ++ 0x01900060, ++ 0x03004a06, ++ 0x01900060, ++ 0x6b030a0c, ++ 0x00100060, ++ 0x4b02140d, ++ 0x0016a160, ++ 0x4302540d, ++ 0x0016a160, ++ 0x23010a0f, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x6b03140c, ++ 0x00100060, ++ 0x4b02140d, ++ 0x0016a160, ++ 0x0b004a0e, ++ 0x01900060, ++ 0x4302540d, ++ 0x0016a160, ++ 0x23010a0f, ++ 0x01500060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x40021404, ++ 0x00100000, ++ 0x1a00d405, ++ 0x00100040, ++ 0x53028a06, ++ 0x01900060, ++ 0x5b02ca06, ++ 0x01900060, ++ 0x5b02ca06, ++ 0x01900060, ++ 0x43020a04, ++ 0x00100060, ++ 0x1b00ca05, ++ 0x00100060, ++ 0x53028a07, ++ 0x0190c060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100010, ++ 0x1a00d40d, ++ 0x00100050, ++ 0x53028a0e, ++ 0x01900070, ++ 0x5b02ca0e, ++ 0x01900070, ++ 0x5b02ca0e, ++ 0x01900070, ++ 0x43020a0c, ++ 0x00100070, ++ 0x1b00ca0d, ++ 0x00100070, ++ 0x53028a0f, ++ 0x0190c070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x40021404, ++ 0x00100000, ++ 0x1a00d405, ++ 0x00100040, ++ 0x5b02ca06, ++ 0x01900060, ++ 0x5b02ca06, ++ 0x01900060, ++ 0x53028a07, ++ 0x0190c060, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x4002140c, ++ 0x00100010, ++ 0x1a00d40d, ++ 0x00100050, ++ 0x5b02ca0e, ++ 0x01900070, ++ 0x5b02ca0e, ++ 0x01900070, ++ 0x53028a0f, ++ 0x0190c070, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u16 pilot_tbl_rev3[] = { ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0xff08, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0x80d5, ++ 0xff0a, ++ 0xff82, ++ 0xffa0, ++ 0xff28, ++ 0xffff, ++ 0xffff, ++ 0xffff, ++ 0xffff, ++ 0xff82, ++ 0xffa0, ++ 0xff28, ++ 0xff0a, ++ 0xffff, ++ 0xffff, ++ 0xffff, ++ 0xffff, ++ 0xf83f, ++ 0xfa1f, ++ 0xfa97, ++ 0xfab5, ++ 0xf2bd, ++ 0xf0bf, ++ 0xffff, ++ 0xffff, ++ 0xf017, ++ 0xf815, ++ 0xf215, ++ 0xf095, ++ 0xf035, ++ 0xf01d, ++ 0xffff, ++ 0xffff, ++ 0xff08, ++ 0xff02, ++ 0xff80, ++ 0xff20, ++ 0xff08, ++ 0xff02, ++ 0xff80, ++ 0xff20, ++ 0xf01f, ++ 0xf817, ++ 0xfa15, ++ 0xf295, ++ 0xf0b5, ++ 0xf03d, ++ 0xffff, ++ 0xffff, ++ 0xf82a, ++ 0xfa0a, ++ 0xfa82, ++ 0xfaa0, ++ 0xf2a8, ++ 0xf0aa, ++ 0xffff, ++ 0xffff, ++ 0xf002, ++ 0xf800, ++ 0xf200, ++ 0xf080, ++ 0xf020, ++ 0xf008, ++ 0xffff, ++ 0xffff, ++ 0xf00a, ++ 0xf802, ++ 0xfa00, ++ 0xf280, ++ 0xf0a0, ++ 0xf028, ++ 0xffff, ++ 0xffff, ++}; ++ ++static const u32 tmap_tbl_rev3[] = { ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x000aa888, ++ 0x88880000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa2222220, ++ 0x22222222, ++ 0x22c22222, ++ 0x00000222, ++ 0x22000000, ++ 0x2222a222, ++ 0x22222222, ++ 0x222222a2, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00011111, ++ 0x11110000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0xa8aa88a0, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x00088aaa, ++ 0xaaaa0000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xaaa8aaa0, ++ 0x8aaa8aaa, ++ 0xaa8a8a8a, ++ 0x000aaa88, ++ 0x8aaa0000, ++ 0xaaa8a888, ++ 0x8aa88a8a, ++ 0x8a88a888, ++ 0x08080a00, ++ 0x0a08080a, ++ 0x080a0a08, ++ 0x00080808, ++ 0x080a0000, ++ 0x080a0808, ++ 0x080a0808, ++ 0x0a0a0a08, ++ 0xa0a0a0a0, ++ 0x80a0a080, ++ 0x8080a0a0, ++ 0x00008080, ++ 0x80a00000, ++ 0x80a080a0, ++ 0xa080a0a0, ++ 0x8080a0a0, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x99999000, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb90, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00aaa888, ++ 0x22000000, ++ 0x2222b222, ++ 0x22222222, ++ 0x222222b2, ++ 0xb2222220, ++ 0x22222222, ++ 0x22d22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x33000000, ++ 0x3333b333, ++ 0x33333333, ++ 0x333333b3, ++ 0xb3333330, ++ 0x33333333, ++ 0x33d33333, ++ 0x00000333, ++ 0x22000000, ++ 0x2222a222, ++ 0x22222222, ++ 0x222222a2, ++ 0xa2222220, ++ 0x22222222, ++ 0x22c22222, ++ 0x00000222, ++ 0x99b99b00, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb99, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x08aaa888, ++ 0x22222200, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0x22222222, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x11111111, ++ 0xf1111111, ++ 0x11111111, ++ 0x11f11111, ++ 0x01111111, ++ 0xbb9bb900, ++ 0xb9b9bb99, ++ 0xb99bbbbb, ++ 0xbbbb9b9b, ++ 0xb9bb99bb, ++ 0xb99999b9, ++ 0xb9b9b99b, ++ 0x00000bbb, ++ 0xaa000000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xa8aa88aa, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x0a888aaa, ++ 0xaa000000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xa8aa88a0, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x00000aaa, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0xbbbbbb00, ++ 0x999bbbbb, ++ 0x9bb99b9b, ++ 0xb9b9b9bb, ++ 0xb9b99bbb, ++ 0xb9b9b9bb, ++ 0xb9bb9b99, ++ 0x00000999, ++ 0x8a000000, ++ 0xaa88a888, ++ 0xa88888aa, ++ 0xa88a8a88, ++ 0xa88aa88a, ++ 0x88a8aaaa, ++ 0xa8aa8aaa, ++ 0x0888a88a, ++ 0x0b0b0b00, ++ 0x090b0b0b, ++ 0x0b090b0b, ++ 0x0909090b, ++ 0x09090b0b, ++ 0x09090b0b, ++ 0x09090b09, ++ 0x00000909, ++ 0x0a000000, ++ 0x0a080808, ++ 0x080a080a, ++ 0x080a0a08, ++ 0x080a080a, ++ 0x0808080a, ++ 0x0a0a0a08, ++ 0x0808080a, ++ 0xb0b0b000, ++ 0x9090b0b0, ++ 0x90b09090, ++ 0xb0b0b090, ++ 0xb0b090b0, ++ 0x90b0b0b0, ++ 0xb0b09090, ++ 0x00000090, ++ 0x80000000, ++ 0xa080a080, ++ 0xa08080a0, ++ 0xa0808080, ++ 0xa080a080, ++ 0x80a0a0a0, ++ 0xa0a080a0, ++ 0x00a0a0a0, ++ 0x22000000, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0xf2222220, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00000111, ++ 0x33000000, ++ 0x3333f333, ++ 0x33333333, ++ 0x333333f3, ++ 0xf3333330, ++ 0x33333333, ++ 0x33f33333, ++ 0x00000333, ++ 0x22000000, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0xf2222220, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x99000000, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb90, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88888000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00aaa888, ++ 0x88a88a00, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x08aaa888, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 intlv_tbl_rev3[] = { ++ 0x00802070, ++ 0x0671188d, ++ 0x0a60192c, ++ 0x0a300e46, ++ 0x00c1188d, ++ 0x080024d2, ++ 0x00000070, ++}; ++ ++static const u32 tdtrn_tbl_rev3[] = { ++ 0x061c061c, ++ 0x0050ee68, ++ 0xf592fe36, ++ 0xfe5212f6, ++ 0x00000c38, ++ 0xfe5212f6, ++ 0xf592fe36, ++ 0x0050ee68, ++ 0x061c061c, ++ 0xee680050, ++ 0xfe36f592, ++ 0x12f6fe52, ++ 0x0c380000, ++ 0x12f6fe52, ++ 0xfe36f592, ++ 0xee680050, ++ 0x061c061c, ++ 0x0050ee68, ++ 0xf592fe36, ++ 0xfe5212f6, ++ 0x00000c38, ++ 0xfe5212f6, ++ 0xf592fe36, ++ 0x0050ee68, ++ 0x061c061c, ++ 0xee680050, ++ 0xfe36f592, ++ 0x12f6fe52, ++ 0x0c380000, ++ 0x12f6fe52, ++ 0xfe36f592, ++ 0xee680050, ++ 0x05e305e3, ++ 0x004def0c, ++ 0xf5f3fe47, ++ 0xfe611246, ++ 0x00000bc7, ++ 0xfe611246, ++ 0xf5f3fe47, ++ 0x004def0c, ++ 0x05e305e3, ++ 0xef0c004d, ++ 0xfe47f5f3, ++ 0x1246fe61, ++ 0x0bc70000, ++ 0x1246fe61, ++ 0xfe47f5f3, ++ 0xef0c004d, ++ 0x05e305e3, ++ 0x004def0c, ++ 0xf5f3fe47, ++ 0xfe611246, ++ 0x00000bc7, ++ 0xfe611246, ++ 0xf5f3fe47, ++ 0x004def0c, ++ 0x05e305e3, ++ 0xef0c004d, ++ 0xfe47f5f3, ++ 0x1246fe61, ++ 0x0bc70000, ++ 0x1246fe61, ++ 0xfe47f5f3, ++ 0xef0c004d, ++ 0xfa58fa58, ++ 0xf895043b, ++ 0xff4c09c0, ++ 0xfbc6ffa8, ++ 0xfb84f384, ++ 0x0798f6f9, ++ 0x05760122, ++ 0x058409f6, ++ 0x0b500000, ++ 0x05b7f542, ++ 0x08860432, ++ 0x06ddfee7, ++ 0xfb84f384, ++ 0xf9d90664, ++ 0xf7e8025c, ++ 0x00fff7bd, ++ 0x05a805a8, ++ 0xf7bd00ff, ++ 0x025cf7e8, ++ 0x0664f9d9, ++ 0xf384fb84, ++ 0xfee706dd, ++ 0x04320886, ++ 0xf54205b7, ++ 0x00000b50, ++ 0x09f60584, ++ 0x01220576, ++ 0xf6f90798, ++ 0xf384fb84, ++ 0xffa8fbc6, ++ 0x09c0ff4c, ++ 0x043bf895, ++ 0x02d402d4, ++ 0x07de0270, ++ 0xfc96079c, ++ 0xf90afe94, ++ 0xfe00ff2c, ++ 0x02d4065d, ++ 0x092a0096, ++ 0x0014fbb8, ++ 0xfd2cfd2c, ++ 0x076afb3c, ++ 0x0096f752, ++ 0xf991fd87, ++ 0xfb2c0200, ++ 0xfeb8f960, ++ 0x08e0fc96, ++ 0x049802a8, ++ 0xfd2cfd2c, ++ 0x02a80498, ++ 0xfc9608e0, ++ 0xf960feb8, ++ 0x0200fb2c, ++ 0xfd87f991, ++ 0xf7520096, ++ 0xfb3c076a, ++ 0xfd2cfd2c, ++ 0xfbb80014, ++ 0x0096092a, ++ 0x065d02d4, ++ 0xff2cfe00, ++ 0xfe94f90a, ++ 0x079cfc96, ++ 0x027007de, ++ 0x02d402d4, ++ 0x027007de, ++ 0x079cfc96, ++ 0xfe94f90a, ++ 0xff2cfe00, ++ 0x065d02d4, ++ 0x0096092a, ++ 0xfbb80014, ++ 0xfd2cfd2c, ++ 0xfb3c076a, ++ 0xf7520096, ++ 0xfd87f991, ++ 0x0200fb2c, ++ 0xf960feb8, ++ 0xfc9608e0, ++ 0x02a80498, ++ 0xfd2cfd2c, ++ 0x049802a8, ++ 0x08e0fc96, ++ 0xfeb8f960, ++ 0xfb2c0200, ++ 0xf991fd87, ++ 0x0096f752, ++ 0x076afb3c, ++ 0xfd2cfd2c, ++ 0x0014fbb8, ++ 0x092a0096, ++ 0x02d4065d, ++ 0xfe00ff2c, ++ 0xf90afe94, ++ 0xfc96079c, ++ 0x07de0270, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x062a0000, ++ 0xfefa0759, ++ 0x08b80908, ++ 0xf396fc2d, ++ 0xf9d6045c, ++ 0xfc4ef608, ++ 0xf748f596, ++ 0x07b207bf, ++ 0x062a062a, ++ 0xf84ef841, ++ 0xf748f596, ++ 0x03b209f8, ++ 0xf9d6045c, ++ 0x0c6a03d3, ++ 0x08b80908, ++ 0x0106f8a7, ++ 0x062a0000, ++ 0xfefaf8a7, ++ 0x08b8f6f8, ++ 0xf39603d3, ++ 0xf9d6fba4, ++ 0xfc4e09f8, ++ 0xf7480a6a, ++ 0x07b2f841, ++ 0x062af9d6, ++ 0xf84e07bf, ++ 0xf7480a6a, ++ 0x03b2f608, ++ 0xf9d6fba4, ++ 0x0c6afc2d, ++ 0x08b8f6f8, ++ 0x01060759, ++ 0x062a0000, ++ 0xfefa0759, ++ 0x08b80908, ++ 0xf396fc2d, ++ 0xf9d6045c, ++ 0xfc4ef608, ++ 0xf748f596, ++ 0x07b207bf, ++ 0x062a062a, ++ 0xf84ef841, ++ 0xf748f596, ++ 0x03b209f8, ++ 0xf9d6045c, ++ 0x0c6a03d3, ++ 0x08b80908, ++ 0x0106f8a7, ++ 0x062a0000, ++ 0xfefaf8a7, ++ 0x08b8f6f8, ++ 0xf39603d3, ++ 0xf9d6fba4, ++ 0xfc4e09f8, ++ 0xf7480a6a, ++ 0x07b2f841, ++ 0x062af9d6, ++ 0xf84e07bf, ++ 0xf7480a6a, ++ 0x03b2f608, ++ 0xf9d6fba4, ++ 0x0c6afc2d, ++ 0x08b8f6f8, ++ 0x01060759, ++ 0x061c061c, ++ 0xff30009d, ++ 0xffb21141, ++ 0xfd87fb54, ++ 0xf65dfe59, ++ 0x02eef99e, ++ 0x0166f03c, ++ 0xfff809b6, ++ 0x000008a4, ++ 0x000af42b, ++ 0x00eff577, ++ 0xfa840bf2, ++ 0xfc02ff51, ++ 0x08260f67, ++ 0xfff0036f, ++ 0x0842f9c3, ++ 0x00000000, ++ 0x063df7be, ++ 0xfc910010, ++ 0xf099f7da, ++ 0x00af03fe, ++ 0xf40e057c, ++ 0x0a89ff11, ++ 0x0bd5fff6, ++ 0xf75c0000, ++ 0xf64a0008, ++ 0x0fc4fe9a, ++ 0x0662fd12, ++ 0x01a709a3, ++ 0x04ac0279, ++ 0xeebf004e, ++ 0xff6300d0, ++ 0xf9e4f9e4, ++ 0x00d0ff63, ++ 0x004eeebf, ++ 0x027904ac, ++ 0x09a301a7, ++ 0xfd120662, ++ 0xfe9a0fc4, ++ 0x0008f64a, ++ 0x0000f75c, ++ 0xfff60bd5, ++ 0xff110a89, ++ 0x057cf40e, ++ 0x03fe00af, ++ 0xf7daf099, ++ 0x0010fc91, ++ 0xf7be063d, ++ 0x00000000, ++ 0xf9c30842, ++ 0x036ffff0, ++ 0x0f670826, ++ 0xff51fc02, ++ 0x0bf2fa84, ++ 0xf57700ef, ++ 0xf42b000a, ++ 0x08a40000, ++ 0x09b6fff8, ++ 0xf03c0166, ++ 0xf99e02ee, ++ 0xfe59f65d, ++ 0xfb54fd87, ++ 0x1141ffb2, ++ 0x009dff30, ++ 0x05e30000, ++ 0xff060705, ++ 0x085408a0, ++ 0xf425fc59, ++ 0xfa1d042a, ++ 0xfc78f67a, ++ 0xf7acf60e, ++ 0x075a0766, ++ 0x05e305e3, ++ 0xf8a6f89a, ++ 0xf7acf60e, ++ 0x03880986, ++ 0xfa1d042a, ++ 0x0bdb03a7, ++ 0x085408a0, ++ 0x00faf8fb, ++ 0x05e30000, ++ 0xff06f8fb, ++ 0x0854f760, ++ 0xf42503a7, ++ 0xfa1dfbd6, ++ 0xfc780986, ++ 0xf7ac09f2, ++ 0x075af89a, ++ 0x05e3fa1d, ++ 0xf8a60766, ++ 0xf7ac09f2, ++ 0x0388f67a, ++ 0xfa1dfbd6, ++ 0x0bdbfc59, ++ 0x0854f760, ++ 0x00fa0705, ++ 0x05e30000, ++ 0xff060705, ++ 0x085408a0, ++ 0xf425fc59, ++ 0xfa1d042a, ++ 0xfc78f67a, ++ 0xf7acf60e, ++ 0x075a0766, ++ 0x05e305e3, ++ 0xf8a6f89a, ++ 0xf7acf60e, ++ 0x03880986, ++ 0xfa1d042a, ++ 0x0bdb03a7, ++ 0x085408a0, ++ 0x00faf8fb, ++ 0x05e30000, ++ 0xff06f8fb, ++ 0x0854f760, ++ 0xf42503a7, ++ 0xfa1dfbd6, ++ 0xfc780986, ++ 0xf7ac09f2, ++ 0x075af89a, ++ 0x05e3fa1d, ++ 0xf8a60766, ++ 0xf7ac09f2, ++ 0x0388f67a, ++ 0xfa1dfbd6, ++ 0x0bdbfc59, ++ 0x0854f760, ++ 0x00fa0705, ++ 0xfa58fa58, ++ 0xf8f0fe00, ++ 0x0448073d, ++ 0xfdc9fe46, ++ 0xf9910258, ++ 0x089d0407, ++ 0xfd5cf71a, ++ 0x02affde0, ++ 0x083e0496, ++ 0xff5a0740, ++ 0xff7afd97, ++ 0x00fe01f1, ++ 0x0009082e, ++ 0xfa94ff75, ++ 0xfecdf8ea, ++ 0xffb0f693, ++ 0xfd2cfa58, ++ 0x0433ff16, ++ 0xfba405dd, ++ 0xfa610341, ++ 0x06a606cb, ++ 0x0039fd2d, ++ 0x0677fa97, ++ 0x01fa05e0, ++ 0xf896003e, ++ 0x075a068b, ++ 0x012cfc3e, ++ 0xfa23f98d, ++ 0xfc7cfd43, ++ 0xff90fc0d, ++ 0x01c10982, ++ 0x00c601d6, ++ 0xfd2cfd2c, ++ 0x01d600c6, ++ 0x098201c1, ++ 0xfc0dff90, ++ 0xfd43fc7c, ++ 0xf98dfa23, ++ 0xfc3e012c, ++ 0x068b075a, ++ 0x003ef896, ++ 0x05e001fa, ++ 0xfa970677, ++ 0xfd2d0039, ++ 0x06cb06a6, ++ 0x0341fa61, ++ 0x05ddfba4, ++ 0xff160433, ++ 0xfa58fd2c, ++ 0xf693ffb0, ++ 0xf8eafecd, ++ 0xff75fa94, ++ 0x082e0009, ++ 0x01f100fe, ++ 0xfd97ff7a, ++ 0x0740ff5a, ++ 0x0496083e, ++ 0xfde002af, ++ 0xf71afd5c, ++ 0x0407089d, ++ 0x0258f991, ++ 0xfe46fdc9, ++ 0x073d0448, ++ 0xfe00f8f0, ++ 0xfd2cfd2c, ++ 0xfce00500, ++ 0xfc09fddc, ++ 0xfe680157, ++ 0x04c70571, ++ 0xfc3aff21, ++ 0xfcd70228, ++ 0x056d0277, ++ 0x0200fe00, ++ 0x0022f927, ++ 0xfe3c032b, ++ 0xfc44ff3c, ++ 0x03e9fbdb, ++ 0x04570313, ++ 0x04c9ff5c, ++ 0x000d03b8, ++ 0xfa580000, ++ 0xfbe900d2, ++ 0xf9d0fe0b, ++ 0x0125fdf9, ++ 0x042501bf, ++ 0x0328fa2b, ++ 0xffa902f0, ++ 0xfa250157, ++ 0x0200fe00, ++ 0x03740438, ++ 0xff0405fd, ++ 0x030cfe52, ++ 0x0037fb39, ++ 0xff6904c5, ++ 0x04f8fd23, ++ 0xfd31fc1b, ++ 0xfd2cfd2c, ++ 0xfc1bfd31, ++ 0xfd2304f8, ++ 0x04c5ff69, ++ 0xfb390037, ++ 0xfe52030c, ++ 0x05fdff04, ++ 0x04380374, ++ 0xfe000200, ++ 0x0157fa25, ++ 0x02f0ffa9, ++ 0xfa2b0328, ++ 0x01bf0425, ++ 0xfdf90125, ++ 0xfe0bf9d0, ++ 0x00d2fbe9, ++ 0x0000fa58, ++ 0x03b8000d, ++ 0xff5c04c9, ++ 0x03130457, ++ 0xfbdb03e9, ++ 0xff3cfc44, ++ 0x032bfe3c, ++ 0xf9270022, ++ 0xfe000200, ++ 0x0277056d, ++ 0x0228fcd7, ++ 0xff21fc3a, ++ 0x057104c7, ++ 0x0157fe68, ++ 0xfddcfc09, ++ 0x0500fce0, ++ 0xfd2cfd2c, ++ 0x0500fce0, ++ 0xfddcfc09, ++ 0x0157fe68, ++ 0x057104c7, ++ 0xff21fc3a, ++ 0x0228fcd7, ++ 0x0277056d, ++ 0xfe000200, ++ 0xf9270022, ++ 0x032bfe3c, ++ 0xff3cfc44, ++ 0xfbdb03e9, ++ 0x03130457, ++ 0xff5c04c9, ++ 0x03b8000d, ++ 0x0000fa58, ++ 0x00d2fbe9, ++ 0xfe0bf9d0, ++ 0xfdf90125, ++ 0x01bf0425, ++ 0xfa2b0328, ++ 0x02f0ffa9, ++ 0x0157fa25, ++ 0xfe000200, ++ 0x04380374, ++ 0x05fdff04, ++ 0xfe52030c, ++ 0xfb390037, ++ 0x04c5ff69, ++ 0xfd2304f8, ++ 0xfc1bfd31, ++ 0xfd2cfd2c, ++ 0xfd31fc1b, ++ 0x04f8fd23, ++ 0xff6904c5, ++ 0x0037fb39, ++ 0x030cfe52, ++ 0xff0405fd, ++ 0x03740438, ++ 0x0200fe00, ++ 0xfa250157, ++ 0xffa902f0, ++ 0x0328fa2b, ++ 0x042501bf, ++ 0x0125fdf9, ++ 0xf9d0fe0b, ++ 0xfbe900d2, ++ 0xfa580000, ++ 0x000d03b8, ++ 0x04c9ff5c, ++ 0x04570313, ++ 0x03e9fbdb, ++ 0xfc44ff3c, ++ 0xfe3c032b, ++ 0x0022f927, ++ 0x0200fe00, ++ 0x056d0277, ++ 0xfcd70228, ++ 0xfc3aff21, ++ 0x04c70571, ++ 0xfe680157, ++ 0xfc09fddc, ++ 0xfce00500, ++ 0x05a80000, ++ 0xff1006be, ++ 0x0800084a, ++ 0xf49cfc7e, ++ 0xfa580400, ++ 0xfc9cf6da, ++ 0xf800f672, ++ 0x0710071c, ++ 0x05a805a8, ++ 0xf8f0f8e4, ++ 0xf800f672, ++ 0x03640926, ++ 0xfa580400, ++ 0x0b640382, ++ 0x0800084a, ++ 0x00f0f942, ++ 0x05a80000, ++ 0xff10f942, ++ 0x0800f7b6, ++ 0xf49c0382, ++ 0xfa58fc00, ++ 0xfc9c0926, ++ 0xf800098e, ++ 0x0710f8e4, ++ 0x05a8fa58, ++ 0xf8f0071c, ++ 0xf800098e, ++ 0x0364f6da, ++ 0xfa58fc00, ++ 0x0b64fc7e, ++ 0x0800f7b6, ++ 0x00f006be, ++ 0x05a80000, ++ 0xff1006be, ++ 0x0800084a, ++ 0xf49cfc7e, ++ 0xfa580400, ++ 0xfc9cf6da, ++ 0xf800f672, ++ 0x0710071c, ++ 0x05a805a8, ++ 0xf8f0f8e4, ++ 0xf800f672, ++ 0x03640926, ++ 0xfa580400, ++ 0x0b640382, ++ 0x0800084a, ++ 0x00f0f942, ++ 0x05a80000, ++ 0xff10f942, ++ 0x0800f7b6, ++ 0xf49c0382, ++ 0xfa58fc00, ++ 0xfc9c0926, ++ 0xf800098e, ++ 0x0710f8e4, ++ 0x05a8fa58, ++ 0xf8f0071c, ++ 0xf800098e, ++ 0x0364f6da, ++ 0xfa58fc00, ++ 0x0b64fc7e, ++ 0x0800f7b6, ++ 0x00f006be, ++}; ++ ++const u32 noise_var_tbl_rev3[] = { ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++ 0x02110211, ++ 0x0000014d, ++}; ++ ++static const u16 mcs_tbl_rev3[] = { ++ 0x0000, ++ 0x0008, ++ 0x000a, ++ 0x0010, ++ 0x0012, ++ 0x0019, ++ 0x001a, ++ 0x001c, ++ 0x0080, ++ 0x0088, ++ 0x008a, ++ 0x0090, ++ 0x0092, ++ 0x0099, ++ 0x009a, ++ 0x009c, ++ 0x0100, ++ 0x0108, ++ 0x010a, ++ 0x0110, ++ 0x0112, ++ 0x0119, ++ 0x011a, ++ 0x011c, ++ 0x0180, ++ 0x0188, ++ 0x018a, ++ 0x0190, ++ 0x0192, ++ 0x0199, ++ 0x019a, ++ 0x019c, ++ 0x0000, ++ 0x0098, ++ 0x00a0, ++ 0x00a8, ++ 0x009a, ++ 0x00a2, ++ 0x00aa, ++ 0x0120, ++ 0x0128, ++ 0x0128, ++ 0x0130, ++ 0x0138, ++ 0x0138, ++ 0x0140, ++ 0x0122, ++ 0x012a, ++ 0x012a, ++ 0x0132, ++ 0x013a, ++ 0x013a, ++ 0x0142, ++ 0x01a8, ++ 0x01b0, ++ 0x01b8, ++ 0x01b0, ++ 0x01b8, ++ 0x01c0, ++ 0x01c8, ++ 0x01c0, ++ 0x01c8, ++ 0x01d0, ++ 0x01d0, ++ 0x01d8, ++ 0x01aa, ++ 0x01b2, ++ 0x01ba, ++ 0x01b2, ++ 0x01ba, ++ 0x01c2, ++ 0x01ca, ++ 0x01c2, ++ 0x01ca, ++ 0x01d2, ++ 0x01d2, ++ 0x01da, ++ 0x0001, ++ 0x0002, ++ 0x0004, ++ 0x0009, ++ 0x000c, ++ 0x0011, ++ 0x0014, ++ 0x0018, ++ 0x0020, ++ 0x0021, ++ 0x0022, ++ 0x0024, ++ 0x0081, ++ 0x0082, ++ 0x0084, ++ 0x0089, ++ 0x008c, ++ 0x0091, ++ 0x0094, ++ 0x0098, ++ 0x00a0, ++ 0x00a1, ++ 0x00a2, ++ 0x00a4, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++ 0x0007, ++}; ++ ++static const u32 tdi_tbl20_ant0_rev3[] = { ++ 0x00091226, ++ 0x000a1429, ++ 0x000b56ad, ++ 0x000c58b0, ++ 0x000d5ab3, ++ 0x000e9cb6, ++ 0x000f9eba, ++ 0x0000c13d, ++ 0x00020301, ++ 0x00030504, ++ 0x00040708, ++ 0x0005090b, ++ 0x00064b8e, ++ 0x00095291, ++ 0x000a5494, ++ 0x000b9718, ++ 0x000c9927, ++ 0x000d9b2a, ++ 0x000edd2e, ++ 0x000fdf31, ++ 0x000101b4, ++ 0x000243b7, ++ 0x000345bb, ++ 0x000447be, ++ 0x00058982, ++ 0x00068c05, ++ 0x00099309, ++ 0x000a950c, ++ 0x000bd78f, ++ 0x000cd992, ++ 0x000ddb96, ++ 0x000f1d99, ++ 0x00005fa8, ++ 0x0001422c, ++ 0x0002842f, ++ 0x00038632, ++ 0x00048835, ++ 0x0005ca38, ++ 0x0006ccbc, ++ 0x0009d3bf, ++ 0x000b1603, ++ 0x000c1806, ++ 0x000d1a0a, ++ 0x000e1c0d, ++ 0x000f5e10, ++ 0x00008093, ++ 0x00018297, ++ 0x0002c49a, ++ 0x0003c680, ++ 0x0004c880, ++ 0x00060b00, ++ 0x00070d00, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 tdi_tbl20_ant1_rev3[] = { ++ 0x00014b26, ++ 0x00028d29, ++ 0x000393ad, ++ 0x00049630, ++ 0x0005d833, ++ 0x0006da36, ++ 0x00099c3a, ++ 0x000a9e3d, ++ 0x000bc081, ++ 0x000cc284, ++ 0x000dc488, ++ 0x000f068b, ++ 0x0000488e, ++ 0x00018b91, ++ 0x0002d214, ++ 0x0003d418, ++ 0x0004d6a7, ++ 0x000618aa, ++ 0x00071aae, ++ 0x0009dcb1, ++ 0x000b1eb4, ++ 0x000c0137, ++ 0x000d033b, ++ 0x000e053e, ++ 0x000f4702, ++ 0x00008905, ++ 0x00020c09, ++ 0x0003128c, ++ 0x0004148f, ++ 0x00051712, ++ 0x00065916, ++ 0x00091b19, ++ 0x000a1d28, ++ 0x000b5f2c, ++ 0x000c41af, ++ 0x000d43b2, ++ 0x000e85b5, ++ 0x000f87b8, ++ 0x0000c9bc, ++ 0x00024cbf, ++ 0x00035303, ++ 0x00045506, ++ 0x0005978a, ++ 0x0006998d, ++ 0x00095b90, ++ 0x000a5d93, ++ 0x000b9f97, ++ 0x000c821a, ++ 0x000d8400, ++ 0x000ec600, ++ 0x000fc800, ++ 0x00010a00, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 tdi_tbl40_ant0_rev3[] = { ++ 0x0011a346, ++ 0x00136ccf, ++ 0x0014f5d9, ++ 0x001641e2, ++ 0x0017cb6b, ++ 0x00195475, ++ 0x001b2383, ++ 0x001cad0c, ++ 0x001e7616, ++ 0x0000821f, ++ 0x00020ba8, ++ 0x0003d4b2, ++ 0x00056447, ++ 0x00072dd0, ++ 0x0008b6da, ++ 0x000a02e3, ++ 0x000b8c6c, ++ 0x000d15f6, ++ 0x0011e484, ++ 0x0013ae0d, ++ 0x00153717, ++ 0x00168320, ++ 0x00180ca9, ++ 0x00199633, ++ 0x001b6548, ++ 0x001ceed1, ++ 0x001eb7db, ++ 0x0000c3e4, ++ 0x00024d6d, ++ 0x000416f7, ++ 0x0005a585, ++ 0x00076f0f, ++ 0x0008f818, ++ 0x000a4421, ++ 0x000bcdab, ++ 0x000d9734, ++ 0x00122649, ++ 0x0013efd2, ++ 0x001578dc, ++ 0x0016c4e5, ++ 0x00184e6e, ++ 0x001a17f8, ++ 0x001ba686, ++ 0x001d3010, ++ 0x001ef999, ++ 0x00010522, ++ 0x00028eac, ++ 0x00045835, ++ 0x0005e74a, ++ 0x0007b0d3, ++ 0x00093a5d, ++ 0x000a85e6, ++ 0x000c0f6f, ++ 0x000dd8f9, ++ 0x00126787, ++ 0x00143111, ++ 0x0015ba9a, ++ 0x00170623, ++ 0x00188fad, ++ 0x001a5936, ++ 0x001be84b, ++ 0x001db1d4, ++ 0x001f3b5e, ++ 0x000146e7, ++ 0x00031070, ++ 0x000499fa, ++ 0x00062888, ++ 0x0007f212, ++ 0x00097b9b, ++ 0x000ac7a4, ++ 0x000c50ae, ++ 0x000e1a37, ++ 0x0012a94c, ++ 0x001472d5, ++ 0x0015fc5f, ++ 0x00174868, ++ 0x0018d171, ++ 0x001a9afb, ++ 0x001c2989, ++ 0x001df313, ++ 0x001f7c9c, ++ 0x000188a5, ++ 0x000351af, ++ 0x0004db38, ++ 0x0006aa4d, ++ 0x000833d7, ++ 0x0009bd60, ++ 0x000b0969, ++ 0x000c9273, ++ 0x000e5bfc, ++ 0x00132a8a, ++ 0x0014b414, ++ 0x00163d9d, ++ 0x001789a6, ++ 0x001912b0, ++ 0x001adc39, ++ 0x001c6bce, ++ 0x001e34d8, ++ 0x001fbe61, ++ 0x0001ca6a, ++ 0x00039374, ++ 0x00051cfd, ++ 0x0006ec0b, ++ 0x00087515, ++ 0x0009fe9e, ++ 0x000b4aa7, ++ 0x000cd3b1, ++ 0x000e9d3a, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 tdi_tbl40_ant1_rev3[] = { ++ 0x001edb36, ++ 0x000129ca, ++ 0x0002b353, ++ 0x00047cdd, ++ 0x0005c8e6, ++ 0x000791ef, ++ 0x00091bf9, ++ 0x000aaa07, ++ 0x000c3391, ++ 0x000dfd1a, ++ 0x00120923, ++ 0x0013d22d, ++ 0x00155c37, ++ 0x0016eacb, ++ 0x00187454, ++ 0x001a3dde, ++ 0x001b89e7, ++ 0x001d12f0, ++ 0x001f1cfa, ++ 0x00016b88, ++ 0x00033492, ++ 0x0004be1b, ++ 0x00060a24, ++ 0x0007d32e, ++ 0x00095d38, ++ 0x000aec4c, ++ 0x000c7555, ++ 0x000e3edf, ++ 0x00124ae8, ++ 0x001413f1, ++ 0x0015a37b, ++ 0x00172c89, ++ 0x0018b593, ++ 0x001a419c, ++ 0x001bcb25, ++ 0x001d942f, ++ 0x001f63b9, ++ 0x0001ad4d, ++ 0x00037657, ++ 0x0004c260, ++ 0x00068be9, ++ 0x000814f3, ++ 0x0009a47c, ++ 0x000b2d8a, ++ 0x000cb694, ++ 0x000e429d, ++ 0x00128c26, ++ 0x001455b0, ++ 0x0015e4ba, ++ 0x00176e4e, ++ 0x0018f758, ++ 0x001a8361, ++ 0x001c0cea, ++ 0x001dd674, ++ 0x001fa57d, ++ 0x0001ee8b, ++ 0x0003b795, ++ 0x0005039e, ++ 0x0006cd27, ++ 0x000856b1, ++ 0x0009e5c6, ++ 0x000b6f4f, ++ 0x000cf859, ++ 0x000e8462, ++ 0x00130deb, ++ 0x00149775, ++ 0x00162603, ++ 0x0017af8c, ++ 0x00193896, ++ 0x001ac49f, ++ 0x001c4e28, ++ 0x001e17b2, ++ 0x0000a6c7, ++ 0x00023050, ++ 0x0003f9da, ++ 0x00054563, ++ 0x00070eec, ++ 0x00089876, ++ 0x000a2704, ++ 0x000bb08d, ++ 0x000d3a17, ++ 0x001185a0, ++ 0x00134f29, ++ 0x0014d8b3, ++ 0x001667c8, ++ 0x0017f151, ++ 0x00197adb, ++ 0x001b0664, ++ 0x001c8fed, ++ 0x001e5977, ++ 0x0000e805, ++ 0x0002718f, ++ 0x00043b18, ++ 0x000586a1, ++ 0x0007502b, ++ 0x0008d9b4, ++ 0x000a68c9, ++ 0x000bf252, ++ 0x000dbbdc, ++ 0x0011c7e5, ++ 0x001390ee, ++ 0x00151a78, ++ 0x0016a906, ++ 0x00183290, ++ 0x0019bc19, ++ 0x001b4822, ++ 0x001cd12c, ++ 0x001e9ab5, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 pltlut_tbl_rev3[] = { ++ 0x76540213, ++ 0x62407351, ++ 0x76543210, ++ 0x76540213, ++ 0x76540213, ++ 0x76430521, ++}; ++ ++static const u32 chanest_tbl_rev3[] = { ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x44444444, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++ 0x10101010, ++}; ++ ++static const u8 frame_lut_rev3[] = { ++ 0x02, ++ 0x04, ++ 0x14, ++ 0x14, ++ 0x03, ++ 0x05, ++ 0x16, ++ 0x16, ++ 0x0a, ++ 0x0c, ++ 0x1c, ++ 0x1c, ++ 0x0b, ++ 0x0d, ++ 0x1e, ++ 0x1e, ++ 0x06, ++ 0x08, ++ 0x18, ++ 0x18, ++ 0x07, ++ 0x09, ++ 0x1a, ++ 0x1a, ++ 0x0e, ++ 0x10, ++ 0x20, ++ 0x28, ++ 0x0f, ++ 0x11, ++ 0x22, ++ 0x2a, ++}; ++ ++static const u8 est_pwr_lut_core0_rev3[] = { ++ 0x55, ++ 0x54, ++ 0x54, ++ 0x53, ++ 0x52, ++ 0x52, ++ 0x51, ++ 0x51, ++ 0x50, ++ 0x4f, ++ 0x4f, ++ 0x4e, ++ 0x4e, ++ 0x4d, ++ 0x4c, ++ 0x4c, ++ 0x4b, ++ 0x4a, ++ 0x49, ++ 0x49, ++ 0x48, ++ 0x47, ++ 0x46, ++ 0x46, ++ 0x45, ++ 0x44, ++ 0x43, ++ 0x42, ++ 0x41, ++ 0x40, ++ 0x40, ++ 0x3f, ++ 0x3e, ++ 0x3d, ++ 0x3c, ++ 0x3a, ++ 0x39, ++ 0x38, ++ 0x37, ++ 0x36, ++ 0x35, ++ 0x33, ++ 0x32, ++ 0x31, ++ 0x2f, ++ 0x2e, ++ 0x2c, ++ 0x2b, ++ 0x29, ++ 0x27, ++ 0x25, ++ 0x23, ++ 0x21, ++ 0x1f, ++ 0x1d, ++ 0x1a, ++ 0x18, ++ 0x15, ++ 0x12, ++ 0x0e, ++ 0x0b, ++ 0x07, ++ 0x02, ++ 0xfd, ++}; ++ ++static const u8 est_pwr_lut_core1_rev3[] = { ++ 0x55, ++ 0x54, ++ 0x54, ++ 0x53, ++ 0x52, ++ 0x52, ++ 0x51, ++ 0x51, ++ 0x50, ++ 0x4f, ++ 0x4f, ++ 0x4e, ++ 0x4e, ++ 0x4d, ++ 0x4c, ++ 0x4c, ++ 0x4b, ++ 0x4a, ++ 0x49, ++ 0x49, ++ 0x48, ++ 0x47, ++ 0x46, ++ 0x46, ++ 0x45, ++ 0x44, ++ 0x43, ++ 0x42, ++ 0x41, ++ 0x40, ++ 0x40, ++ 0x3f, ++ 0x3e, ++ 0x3d, ++ 0x3c, ++ 0x3a, ++ 0x39, ++ 0x38, ++ 0x37, ++ 0x36, ++ 0x35, ++ 0x33, ++ 0x32, ++ 0x31, ++ 0x2f, ++ 0x2e, ++ 0x2c, ++ 0x2b, ++ 0x29, ++ 0x27, ++ 0x25, ++ 0x23, ++ 0x21, ++ 0x1f, ++ 0x1d, ++ 0x1a, ++ 0x18, ++ 0x15, ++ 0x12, ++ 0x0e, ++ 0x0b, ++ 0x07, ++ 0x02, ++ 0xfd, ++}; ++ ++static const u8 adj_pwr_lut_core0_rev3[] = { ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++}; ++ ++static const u8 adj_pwr_lut_core1_rev3[] = { ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++ 0x00, ++}; ++ ++static const u32 gainctrl_lut_core0_rev3[] = { ++ 0x5bf70044, ++ 0x5bf70042, ++ 0x5bf70040, ++ 0x5bf7003e, ++ 0x5bf7003c, ++ 0x5bf7003b, ++ 0x5bf70039, ++ 0x5bf70037, ++ 0x5bf70036, ++ 0x5bf70034, ++ 0x5bf70033, ++ 0x5bf70031, ++ 0x5bf70030, ++ 0x5ba70044, ++ 0x5ba70042, ++ 0x5ba70040, ++ 0x5ba7003e, ++ 0x5ba7003c, ++ 0x5ba7003b, ++ 0x5ba70039, ++ 0x5ba70037, ++ 0x5ba70036, ++ 0x5ba70034, ++ 0x5ba70033, ++ 0x5b770044, ++ 0x5b770042, ++ 0x5b770040, ++ 0x5b77003e, ++ 0x5b77003c, ++ 0x5b77003b, ++ 0x5b770039, ++ 0x5b770037, ++ 0x5b770036, ++ 0x5b770034, ++ 0x5b770033, ++ 0x5b770031, ++ 0x5b770030, ++ 0x5b77002f, ++ 0x5b77002d, ++ 0x5b77002c, ++ 0x5b470044, ++ 0x5b470042, ++ 0x5b470040, ++ 0x5b47003e, ++ 0x5b47003c, ++ 0x5b47003b, ++ 0x5b470039, ++ 0x5b470037, ++ 0x5b470036, ++ 0x5b470034, ++ 0x5b470033, ++ 0x5b470031, ++ 0x5b470030, ++ 0x5b47002f, ++ 0x5b47002d, ++ 0x5b47002c, ++ 0x5b47002b, ++ 0x5b47002a, ++ 0x5b270044, ++ 0x5b270042, ++ 0x5b270040, ++ 0x5b27003e, ++ 0x5b27003c, ++ 0x5b27003b, ++ 0x5b270039, ++ 0x5b270037, ++ 0x5b270036, ++ 0x5b270034, ++ 0x5b270033, ++ 0x5b270031, ++ 0x5b270030, ++ 0x5b27002f, ++ 0x5b170044, ++ 0x5b170042, ++ 0x5b170040, ++ 0x5b17003e, ++ 0x5b17003c, ++ 0x5b17003b, ++ 0x5b170039, ++ 0x5b170037, ++ 0x5b170036, ++ 0x5b170034, ++ 0x5b170033, ++ 0x5b170031, ++ 0x5b170030, ++ 0x5b17002f, ++ 0x5b17002d, ++ 0x5b17002c, ++ 0x5b17002b, ++ 0x5b17002a, ++ 0x5b170028, ++ 0x5b170027, ++ 0x5b170026, ++ 0x5b170025, ++ 0x5b170024, ++ 0x5b170023, ++ 0x5b070044, ++ 0x5b070042, ++ 0x5b070040, ++ 0x5b07003e, ++ 0x5b07003c, ++ 0x5b07003b, ++ 0x5b070039, ++ 0x5b070037, ++ 0x5b070036, ++ 0x5b070034, ++ 0x5b070033, ++ 0x5b070031, ++ 0x5b070030, ++ 0x5b07002f, ++ 0x5b07002d, ++ 0x5b07002c, ++ 0x5b07002b, ++ 0x5b07002a, ++ 0x5b070028, ++ 0x5b070027, ++ 0x5b070026, ++ 0x5b070025, ++ 0x5b070024, ++ 0x5b070023, ++ 0x5b070022, ++ 0x5b070021, ++ 0x5b070020, ++ 0x5b07001f, ++ 0x5b07001e, ++ 0x5b07001d, ++ 0x5b07001d, ++ 0x5b07001c, ++}; ++ ++static const u32 gainctrl_lut_core1_rev3[] = { ++ 0x5bf70044, ++ 0x5bf70042, ++ 0x5bf70040, ++ 0x5bf7003e, ++ 0x5bf7003c, ++ 0x5bf7003b, ++ 0x5bf70039, ++ 0x5bf70037, ++ 0x5bf70036, ++ 0x5bf70034, ++ 0x5bf70033, ++ 0x5bf70031, ++ 0x5bf70030, ++ 0x5ba70044, ++ 0x5ba70042, ++ 0x5ba70040, ++ 0x5ba7003e, ++ 0x5ba7003c, ++ 0x5ba7003b, ++ 0x5ba70039, ++ 0x5ba70037, ++ 0x5ba70036, ++ 0x5ba70034, ++ 0x5ba70033, ++ 0x5b770044, ++ 0x5b770042, ++ 0x5b770040, ++ 0x5b77003e, ++ 0x5b77003c, ++ 0x5b77003b, ++ 0x5b770039, ++ 0x5b770037, ++ 0x5b770036, ++ 0x5b770034, ++ 0x5b770033, ++ 0x5b770031, ++ 0x5b770030, ++ 0x5b77002f, ++ 0x5b77002d, ++ 0x5b77002c, ++ 0x5b470044, ++ 0x5b470042, ++ 0x5b470040, ++ 0x5b47003e, ++ 0x5b47003c, ++ 0x5b47003b, ++ 0x5b470039, ++ 0x5b470037, ++ 0x5b470036, ++ 0x5b470034, ++ 0x5b470033, ++ 0x5b470031, ++ 0x5b470030, ++ 0x5b47002f, ++ 0x5b47002d, ++ 0x5b47002c, ++ 0x5b47002b, ++ 0x5b47002a, ++ 0x5b270044, ++ 0x5b270042, ++ 0x5b270040, ++ 0x5b27003e, ++ 0x5b27003c, ++ 0x5b27003b, ++ 0x5b270039, ++ 0x5b270037, ++ 0x5b270036, ++ 0x5b270034, ++ 0x5b270033, ++ 0x5b270031, ++ 0x5b270030, ++ 0x5b27002f, ++ 0x5b170044, ++ 0x5b170042, ++ 0x5b170040, ++ 0x5b17003e, ++ 0x5b17003c, ++ 0x5b17003b, ++ 0x5b170039, ++ 0x5b170037, ++ 0x5b170036, ++ 0x5b170034, ++ 0x5b170033, ++ 0x5b170031, ++ 0x5b170030, ++ 0x5b17002f, ++ 0x5b17002d, ++ 0x5b17002c, ++ 0x5b17002b, ++ 0x5b17002a, ++ 0x5b170028, ++ 0x5b170027, ++ 0x5b170026, ++ 0x5b170025, ++ 0x5b170024, ++ 0x5b170023, ++ 0x5b070044, ++ 0x5b070042, ++ 0x5b070040, ++ 0x5b07003e, ++ 0x5b07003c, ++ 0x5b07003b, ++ 0x5b070039, ++ 0x5b070037, ++ 0x5b070036, ++ 0x5b070034, ++ 0x5b070033, ++ 0x5b070031, ++ 0x5b070030, ++ 0x5b07002f, ++ 0x5b07002d, ++ 0x5b07002c, ++ 0x5b07002b, ++ 0x5b07002a, ++ 0x5b070028, ++ 0x5b070027, ++ 0x5b070026, ++ 0x5b070025, ++ 0x5b070024, ++ 0x5b070023, ++ 0x5b070022, ++ 0x5b070021, ++ 0x5b070020, ++ 0x5b07001f, ++ 0x5b07001e, ++ 0x5b07001d, ++ 0x5b07001d, ++ 0x5b07001c, ++}; ++ ++static const u32 iq_lut_core0_rev3[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u32 iq_lut_core1_rev3[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++static const u16 loft_lut_core0_rev3[] = { ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++}; ++ ++static const u16 loft_lut_core1_rev3[] = { ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++}; ++ ++static const u16 papd_comp_rfpwr_tbl_core0_rev3[] = { ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++}; ++ ++static const u16 papd_comp_rfpwr_tbl_core1_rev3[] = { ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x0036, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x002a, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x001e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x000e, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01fc, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01ee, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++ 0x01d6, ++}; ++ ++static const u32 papd_comp_epsilon_tbl_core0_rev3[] = { ++ 0x00000000, ++ 0x00001fa0, ++ 0x00019f78, ++ 0x0001df7e, ++ 0x03fa9f86, ++ 0x03fd1f90, ++ 0x03fe5f8a, ++ 0x03fb1f94, ++ 0x03fd9fa0, ++ 0x00009f98, ++ 0x03fd1fac, ++ 0x03ff9fa2, ++ 0x03fe9fae, ++ 0x00001fae, ++ 0x03fddfb4, ++ 0x03ff1fb8, ++ 0x03ff9fbc, ++ 0x03ffdfbe, ++ 0x03fe9fc2, ++ 0x03fedfc6, ++ 0x03fedfc6, ++ 0x03ff9fc8, ++ 0x03ff5fc6, ++ 0x03fedfc2, ++ 0x03ff9fc0, ++ 0x03ff5fac, ++ 0x03ff5fac, ++ 0x03ff9fa2, ++ 0x03ff9fa6, ++ 0x03ff9faa, ++ 0x03ff5fb0, ++ 0x03ff5fb4, ++ 0x03ff1fca, ++ 0x03ff5fce, ++ 0x03fcdfdc, ++ 0x03fb4006, ++ 0x00000030, ++ 0x03ff808a, ++ 0x03ff80da, ++ 0x0000016c, ++ 0x03ff8318, ++ 0x03ff063a, ++ 0x03fd8bd6, ++ 0x00014ffe, ++ 0x00034ffe, ++ 0x00034ffe, ++ 0x0003cffe, ++ 0x00040ffe, ++ 0x00040ffe, ++ 0x0003cffe, ++ 0x0003cffe, ++ 0x00020ffe, ++ 0x03fe0ffe, ++ 0x03fdcffe, ++ 0x03f94ffe, ++ 0x03f54ffe, ++ 0x03f44ffe, ++ 0x03ef8ffe, ++ 0x03ee0ffe, ++ 0x03ebcffe, ++ 0x03e8cffe, ++ 0x03e74ffe, ++ 0x03e4cffe, ++ 0x03e38ffe, ++}; ++ ++static const u32 papd_cal_scalars_tbl_core0_rev3[] = { ++ 0x05af005a, ++ 0x0571005e, ++ 0x05040066, ++ 0x04bd006c, ++ 0x047d0072, ++ 0x04430078, ++ 0x03f70081, ++ 0x03cb0087, ++ 0x03870091, ++ 0x035e0098, ++ 0x032e00a1, ++ 0x030300aa, ++ 0x02d800b4, ++ 0x02ae00bf, ++ 0x028900ca, ++ 0x026400d6, ++ 0x024100e3, ++ 0x022200f0, ++ 0x020200ff, ++ 0x01e5010e, ++ 0x01ca011e, ++ 0x01b0012f, ++ 0x01990140, ++ 0x01830153, ++ 0x016c0168, ++ 0x0158017d, ++ 0x01450193, ++ 0x013301ab, ++ 0x012101c5, ++ 0x011101e0, ++ 0x010201fc, ++ 0x00f4021a, ++ 0x00e6011d, ++ 0x00d9012e, ++ 0x00cd0140, ++ 0x00c20153, ++ 0x00b70167, ++ 0x00ac017c, ++ 0x00a30193, ++ 0x009a01ab, ++ 0x009101c4, ++ 0x008901df, ++ 0x008101fb, ++ 0x007a0219, ++ 0x00730239, ++ 0x006d025b, ++ 0x0067027e, ++ 0x006102a4, ++ 0x005c02cc, ++ 0x005602f6, ++ 0x00520323, ++ 0x004d0353, ++ 0x00490385, ++ 0x004503bb, ++ 0x004103f3, ++ 0x003d042f, ++ 0x003a046f, ++ 0x003704b2, ++ 0x003404f9, ++ 0x00310545, ++ 0x002e0596, ++ 0x002b05f5, ++ 0x00290640, ++ 0x002606a4, ++}; ++ ++static const u32 papd_comp_epsilon_tbl_core1_rev3[] = { ++ 0x00000000, ++ 0x00001fa0, ++ 0x00019f78, ++ 0x0001df7e, ++ 0x03fa9f86, ++ 0x03fd1f90, ++ 0x03fe5f8a, ++ 0x03fb1f94, ++ 0x03fd9fa0, ++ 0x00009f98, ++ 0x03fd1fac, ++ 0x03ff9fa2, ++ 0x03fe9fae, ++ 0x00001fae, ++ 0x03fddfb4, ++ 0x03ff1fb8, ++ 0x03ff9fbc, ++ 0x03ffdfbe, ++ 0x03fe9fc2, ++ 0x03fedfc6, ++ 0x03fedfc6, ++ 0x03ff9fc8, ++ 0x03ff5fc6, ++ 0x03fedfc2, ++ 0x03ff9fc0, ++ 0x03ff5fac, ++ 0x03ff5fac, ++ 0x03ff9fa2, ++ 0x03ff9fa6, ++ 0x03ff9faa, ++ 0x03ff5fb0, ++ 0x03ff5fb4, ++ 0x03ff1fca, ++ 0x03ff5fce, ++ 0x03fcdfdc, ++ 0x03fb4006, ++ 0x00000030, ++ 0x03ff808a, ++ 0x03ff80da, ++ 0x0000016c, ++ 0x03ff8318, ++ 0x03ff063a, ++ 0x03fd8bd6, ++ 0x00014ffe, ++ 0x00034ffe, ++ 0x00034ffe, ++ 0x0003cffe, ++ 0x00040ffe, ++ 0x00040ffe, ++ 0x0003cffe, ++ 0x0003cffe, ++ 0x00020ffe, ++ 0x03fe0ffe, ++ 0x03fdcffe, ++ 0x03f94ffe, ++ 0x03f54ffe, ++ 0x03f44ffe, ++ 0x03ef8ffe, ++ 0x03ee0ffe, ++ 0x03ebcffe, ++ 0x03e8cffe, ++ 0x03e74ffe, ++ 0x03e4cffe, ++ 0x03e38ffe, ++}; ++ ++static const u32 papd_cal_scalars_tbl_core1_rev3[] = { ++ 0x05af005a, ++ 0x0571005e, ++ 0x05040066, ++ 0x04bd006c, ++ 0x047d0072, ++ 0x04430078, ++ 0x03f70081, ++ 0x03cb0087, ++ 0x03870091, ++ 0x035e0098, ++ 0x032e00a1, ++ 0x030300aa, ++ 0x02d800b4, ++ 0x02ae00bf, ++ 0x028900ca, ++ 0x026400d6, ++ 0x024100e3, ++ 0x022200f0, ++ 0x020200ff, ++ 0x01e5010e, ++ 0x01ca011e, ++ 0x01b0012f, ++ 0x01990140, ++ 0x01830153, ++ 0x016c0168, ++ 0x0158017d, ++ 0x01450193, ++ 0x013301ab, ++ 0x012101c5, ++ 0x011101e0, ++ 0x010201fc, ++ 0x00f4021a, ++ 0x00e6011d, ++ 0x00d9012e, ++ 0x00cd0140, ++ 0x00c20153, ++ 0x00b70167, ++ 0x00ac017c, ++ 0x00a30193, ++ 0x009a01ab, ++ 0x009101c4, ++ 0x008901df, ++ 0x008101fb, ++ 0x007a0219, ++ 0x00730239, ++ 0x006d025b, ++ 0x0067027e, ++ 0x006102a4, ++ 0x005c02cc, ++ 0x005602f6, ++ 0x00520323, ++ 0x004d0353, ++ 0x00490385, ++ 0x004503bb, ++ 0x004103f3, ++ 0x003d042f, ++ 0x003a046f, ++ 0x003704b2, ++ 0x003404f9, ++ 0x00310545, ++ 0x002e0596, ++ 0x002b05f5, ++ 0x00290640, ++ 0x002606a4, ++}; ++ ++const struct phytbl_info mimophytbl_info_rev3_volatile[] = { ++ {&ant_swctrl_tbl_rev3, ++ sizeof(ant_swctrl_tbl_rev3) / sizeof(ant_swctrl_tbl_rev3[0]), 9, 0, 16} ++ , ++}; ++ ++const struct phytbl_info mimophytbl_info_rev3_volatile1[] = { ++ {&ant_swctrl_tbl_rev3_1, ++ sizeof(ant_swctrl_tbl_rev3_1) / sizeof(ant_swctrl_tbl_rev3_1[0]), 9, 0, ++ 16} ++ , ++}; ++ ++const struct phytbl_info mimophytbl_info_rev3_volatile2[] = { ++ {&ant_swctrl_tbl_rev3_2, ++ sizeof(ant_swctrl_tbl_rev3_2) / sizeof(ant_swctrl_tbl_rev3_2[0]), 9, 0, ++ 16} ++ , ++}; ++ ++const struct phytbl_info mimophytbl_info_rev3_volatile3[] = { ++ {&ant_swctrl_tbl_rev3_3, ++ sizeof(ant_swctrl_tbl_rev3_3) / sizeof(ant_swctrl_tbl_rev3_3[0]), 9, 0, ++ 16} ++ , ++}; ++ ++const struct phytbl_info mimophytbl_info_rev3[] = { ++ {&frame_struct_rev3, ++ sizeof(frame_struct_rev3) / sizeof(frame_struct_rev3[0]), 10, 0, 32} ++ , ++ {&pilot_tbl_rev3, sizeof(pilot_tbl_rev3) / sizeof(pilot_tbl_rev3[0]), ++ 11, 0, 16} ++ , ++ {&tmap_tbl_rev3, sizeof(tmap_tbl_rev3) / sizeof(tmap_tbl_rev3[0]), 12, ++ 0, 32} ++ , ++ {&intlv_tbl_rev3, sizeof(intlv_tbl_rev3) / sizeof(intlv_tbl_rev3[0]), ++ 13, 0, 32} ++ , ++ {&tdtrn_tbl_rev3, sizeof(tdtrn_tbl_rev3) / sizeof(tdtrn_tbl_rev3[0]), ++ 14, 0, 32} ++ , ++ {&noise_var_tbl_rev3, ++ sizeof(noise_var_tbl_rev3) / sizeof(noise_var_tbl_rev3[0]), 16, 0, 32} ++ , ++ {&mcs_tbl_rev3, sizeof(mcs_tbl_rev3) / sizeof(mcs_tbl_rev3[0]), 18, 0, ++ 16} ++ , ++ {&tdi_tbl20_ant0_rev3, ++ sizeof(tdi_tbl20_ant0_rev3) / sizeof(tdi_tbl20_ant0_rev3[0]), 19, 128, ++ 32} ++ , ++ {&tdi_tbl20_ant1_rev3, ++ sizeof(tdi_tbl20_ant1_rev3) / sizeof(tdi_tbl20_ant1_rev3[0]), 19, 256, ++ 32} ++ , ++ {&tdi_tbl40_ant0_rev3, ++ sizeof(tdi_tbl40_ant0_rev3) / sizeof(tdi_tbl40_ant0_rev3[0]), 19, 640, ++ 32} ++ , ++ {&tdi_tbl40_ant1_rev3, ++ sizeof(tdi_tbl40_ant1_rev3) / sizeof(tdi_tbl40_ant1_rev3[0]), 19, 768, ++ 32} ++ , ++ {&pltlut_tbl_rev3, sizeof(pltlut_tbl_rev3) / sizeof(pltlut_tbl_rev3[0]), ++ 20, 0, 32} ++ , ++ {&chanest_tbl_rev3, ++ sizeof(chanest_tbl_rev3) / sizeof(chanest_tbl_rev3[0]), 22, 0, 32} ++ , ++ {&frame_lut_rev3, sizeof(frame_lut_rev3) / sizeof(frame_lut_rev3[0]), ++ 24, 0, 8} ++ , ++ {&est_pwr_lut_core0_rev3, ++ sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26, ++ 0, 8} ++ , ++ {&est_pwr_lut_core1_rev3, ++ sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27, ++ 0, 8} ++ , ++ {&adj_pwr_lut_core0_rev3, ++ sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26, ++ 64, 8} ++ , ++ {&adj_pwr_lut_core1_rev3, ++ sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27, ++ 64, 8} ++ , ++ {&gainctrl_lut_core0_rev3, ++ sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]), ++ 26, 192, 32} ++ , ++ {&gainctrl_lut_core1_rev3, ++ sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]), ++ 27, 192, 32} ++ , ++ {&iq_lut_core0_rev3, ++ sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32} ++ , ++ {&iq_lut_core1_rev3, ++ sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32} ++ , ++ {&loft_lut_core0_rev3, ++ sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448, ++ 16} ++ , ++ {&loft_lut_core1_rev3, ++ sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448, ++ 16} ++}; ++ ++const u32 mimophytbl_info_sz_rev3 = ++ sizeof(mimophytbl_info_rev3) / sizeof(mimophytbl_info_rev3[0]); ++const u32 mimophytbl_info_sz_rev3_volatile = ++ sizeof(mimophytbl_info_rev3_volatile) / ++ sizeof(mimophytbl_info_rev3_volatile[0]); ++const u32 mimophytbl_info_sz_rev3_volatile1 = ++ sizeof(mimophytbl_info_rev3_volatile1) / ++ sizeof(mimophytbl_info_rev3_volatile1[0]); ++const u32 mimophytbl_info_sz_rev3_volatile2 = ++ sizeof(mimophytbl_info_rev3_volatile2) / ++ sizeof(mimophytbl_info_rev3_volatile2[0]); ++const u32 mimophytbl_info_sz_rev3_volatile3 = ++ sizeof(mimophytbl_info_rev3_volatile3) / ++ sizeof(mimophytbl_info_rev3_volatile3[0]); ++ ++static const u32 tmap_tbl_rev7[] = { ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x000aa888, ++ 0x88880000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa2222220, ++ 0x22222222, ++ 0x22c22222, ++ 0x00000222, ++ 0x22000000, ++ 0x2222a222, ++ 0x22222222, ++ 0x222222a2, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00011111, ++ 0x11110000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0xa8aa88a0, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x00088aaa, ++ 0xaaaa0000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xaaa8aaa0, ++ 0x8aaa8aaa, ++ 0xaa8a8a8a, ++ 0x000aaa88, ++ 0x8aaa0000, ++ 0xaaa8a888, ++ 0x8aa88a8a, ++ 0x8a88a888, ++ 0x08080a00, ++ 0x0a08080a, ++ 0x080a0a08, ++ 0x00080808, ++ 0x080a0000, ++ 0x080a0808, ++ 0x080a0808, ++ 0x0a0a0a08, ++ 0xa0a0a0a0, ++ 0x80a0a080, ++ 0x8080a0a0, ++ 0x00008080, ++ 0x80a00000, ++ 0x80a080a0, ++ 0xa080a0a0, ++ 0x8080a0a0, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x99999000, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb90, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00aaa888, ++ 0x22000000, ++ 0x2222b222, ++ 0x22222222, ++ 0x222222b2, ++ 0xb2222220, ++ 0x22222222, ++ 0x22d22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x33000000, ++ 0x3333b333, ++ 0x33333333, ++ 0x333333b3, ++ 0xb3333330, ++ 0x33333333, ++ 0x33d33333, ++ 0x00000333, ++ 0x22000000, ++ 0x2222a222, ++ 0x22222222, ++ 0x222222a2, ++ 0xa2222220, ++ 0x22222222, ++ 0x22c22222, ++ 0x00000222, ++ 0x99b99b00, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb99, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x08aaa888, ++ 0x22222200, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0x22222222, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x11111111, ++ 0xf1111111, ++ 0x11111111, ++ 0x11f11111, ++ 0x01111111, ++ 0xbb9bb900, ++ 0xb9b9bb99, ++ 0xb99bbbbb, ++ 0xbbbb9b9b, ++ 0xb9bb99bb, ++ 0xb99999b9, ++ 0xb9b9b99b, ++ 0x00000bbb, ++ 0xaa000000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xa8aa88aa, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x0a888aaa, ++ 0xaa000000, ++ 0xa8a8aa88, ++ 0xa88aaaaa, ++ 0xaaaa8a8a, ++ 0xa8aa88a0, ++ 0xa88888a8, ++ 0xa8a8a88a, ++ 0x00000aaa, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0xbbbbbb00, ++ 0x999bbbbb, ++ 0x9bb99b9b, ++ 0xb9b9b9bb, ++ 0xb9b99bbb, ++ 0xb9b9b9bb, ++ 0xb9bb9b99, ++ 0x00000999, ++ 0x8a000000, ++ 0xaa88a888, ++ 0xa88888aa, ++ 0xa88a8a88, ++ 0xa88aa88a, ++ 0x88a8aaaa, ++ 0xa8aa8aaa, ++ 0x0888a88a, ++ 0x0b0b0b00, ++ 0x090b0b0b, ++ 0x0b090b0b, ++ 0x0909090b, ++ 0x09090b0b, ++ 0x09090b0b, ++ 0x09090b09, ++ 0x00000909, ++ 0x0a000000, ++ 0x0a080808, ++ 0x080a080a, ++ 0x080a0a08, ++ 0x080a080a, ++ 0x0808080a, ++ 0x0a0a0a08, ++ 0x0808080a, ++ 0xb0b0b000, ++ 0x9090b0b0, ++ 0x90b09090, ++ 0xb0b0b090, ++ 0xb0b090b0, ++ 0x90b0b0b0, ++ 0xb0b09090, ++ 0x00000090, ++ 0x80000000, ++ 0xa080a080, ++ 0xa08080a0, ++ 0xa0808080, ++ 0xa080a080, ++ 0x80a0a0a0, ++ 0xa0a080a0, ++ 0x00a0a0a0, ++ 0x22000000, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0xf2222220, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x11000000, ++ 0x1111f111, ++ 0x11111111, ++ 0x111111f1, ++ 0xf1111110, ++ 0x11111111, ++ 0x11f11111, ++ 0x00000111, ++ 0x33000000, ++ 0x3333f333, ++ 0x33333333, ++ 0x333333f3, ++ 0xf3333330, ++ 0x33333333, ++ 0x33f33333, ++ 0x00000333, ++ 0x22000000, ++ 0x2222f222, ++ 0x22222222, ++ 0x222222f2, ++ 0xf2222220, ++ 0x22222222, ++ 0x22f22222, ++ 0x00000222, ++ 0x99000000, ++ 0x9b9b99bb, ++ 0x9bb99999, ++ 0x9999b9b9, ++ 0x9b99bb90, ++ 0x9bbbbb9b, ++ 0x9b9b9bb9, ++ 0x00000999, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88888000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00aaa888, ++ 0x88a88a00, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x000aa888, ++ 0x88880000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa88, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x08aaa888, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x11000000, ++ 0x1111a111, ++ 0x11111111, ++ 0x111111a1, ++ 0xa1111110, ++ 0x11111111, ++ 0x11c11111, ++ 0x00000111, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x88000000, ++ 0x8a8a88aa, ++ 0x8aa88888, ++ 0x8888a8a8, ++ 0x8a88aa80, ++ 0x8aaaaa8a, ++ 0x8a8a8aa8, ++ 0x00000888, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++}; ++ ++const u32 noise_var_tbl_rev7[] = { ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++ 0x020c020c, ++ 0x0000014d, ++}; ++ ++static const u32 papd_comp_epsilon_tbl_core0_rev7[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00016023, ++ 0x00006028, ++ 0x00034036, ++ 0x0003402e, ++ 0x0007203c, ++ 0x0006e037, ++ 0x00070030, ++ 0x0009401f, ++ 0x0009a00f, ++ 0x000b600d, ++ 0x000c8007, ++ 0x000ce007, ++ 0x00101fff, ++ 0x00121ff9, ++ 0x0012e004, ++ 0x0014dffc, ++ 0x0016dff6, ++ 0x0018dfe9, ++ 0x001b3fe5, ++ 0x001c5fd0, ++ 0x001ddfc2, ++ 0x001f1fb6, ++ 0x00207fa4, ++ 0x00219f8f, ++ 0x0022ff7d, ++ 0x00247f6c, ++ 0x0024df5b, ++ 0x00267f4b, ++ 0x0027df3b, ++ 0x0029bf3b, ++ 0x002b5f2f, ++ 0x002d3f2e, ++ 0x002f5f2a, ++ 0x002fff15, ++ 0x00315f0b, ++ 0x0032defa, ++ 0x0033beeb, ++ 0x0034fed9, ++ 0x00353ec5, ++ 0x00361eb0, ++ 0x00363e9b, ++ 0x0036be87, ++ 0x0036be70, ++ 0x0038fe67, ++ 0x0044beb2, ++ 0x00513ef3, ++ 0x00595f11, ++ 0x00669f3d, ++ 0x0078dfdf, ++ 0x00a143aa, ++ 0x01642fff, ++ 0x0162afff, ++ 0x01620fff, ++ 0x0160cfff, ++ 0x015f0fff, ++ 0x015dafff, ++ 0x015bcfff, ++ 0x015bcfff, ++ 0x015b4fff, ++ 0x015acfff, ++ 0x01590fff, ++ 0x0156cfff, ++}; ++ ++static const u32 papd_cal_scalars_tbl_core0_rev7[] = { ++ 0x0b5e002d, ++ 0x0ae2002f, ++ 0x0a3b0032, ++ 0x09a70035, ++ 0x09220038, ++ 0x08ab003b, ++ 0x081f003f, ++ 0x07a20043, ++ 0x07340047, ++ 0x06d2004b, ++ 0x067a004f, ++ 0x06170054, ++ 0x05bf0059, ++ 0x0571005e, ++ 0x051e0064, ++ 0x04d3006a, ++ 0x04910070, ++ 0x044c0077, ++ 0x040f007e, ++ 0x03d90085, ++ 0x03a1008d, ++ 0x036f0095, ++ 0x033d009e, ++ 0x030b00a8, ++ 0x02e000b2, ++ 0x02b900bc, ++ 0x029200c7, ++ 0x026d00d3, ++ 0x024900e0, ++ 0x022900ed, ++ 0x020a00fb, ++ 0x01ec010a, ++ 0x01d20119, ++ 0x01b7012a, ++ 0x019e013c, ++ 0x0188014e, ++ 0x01720162, ++ 0x015d0177, ++ 0x0149018e, ++ 0x013701a5, ++ 0x012601be, ++ 0x011501d8, ++ 0x010601f4, ++ 0x00f70212, ++ 0x00e90231, ++ 0x00dc0253, ++ 0x00d00276, ++ 0x00c4029b, ++ 0x00b902c3, ++ 0x00af02ed, ++ 0x00a50319, ++ 0x009c0348, ++ 0x0093037a, ++ 0x008b03af, ++ 0x008303e6, ++ 0x007c0422, ++ 0x00750460, ++ 0x006e04a3, ++ 0x006804e9, ++ 0x00620533, ++ 0x005d0582, ++ 0x005805d6, ++ 0x0053062e, ++ 0x004e068c, ++}; ++ ++static const u32 papd_comp_epsilon_tbl_core1_rev7[] = { ++ 0x00000000, ++ 0x00000000, ++ 0x00016023, ++ 0x00006028, ++ 0x00034036, ++ 0x0003402e, ++ 0x0007203c, ++ 0x0006e037, ++ 0x00070030, ++ 0x0009401f, ++ 0x0009a00f, ++ 0x000b600d, ++ 0x000c8007, ++ 0x000ce007, ++ 0x00101fff, ++ 0x00121ff9, ++ 0x0012e004, ++ 0x0014dffc, ++ 0x0016dff6, ++ 0x0018dfe9, ++ 0x001b3fe5, ++ 0x001c5fd0, ++ 0x001ddfc2, ++ 0x001f1fb6, ++ 0x00207fa4, ++ 0x00219f8f, ++ 0x0022ff7d, ++ 0x00247f6c, ++ 0x0024df5b, ++ 0x00267f4b, ++ 0x0027df3b, ++ 0x0029bf3b, ++ 0x002b5f2f, ++ 0x002d3f2e, ++ 0x002f5f2a, ++ 0x002fff15, ++ 0x00315f0b, ++ 0x0032defa, ++ 0x0033beeb, ++ 0x0034fed9, ++ 0x00353ec5, ++ 0x00361eb0, ++ 0x00363e9b, ++ 0x0036be87, ++ 0x0036be70, ++ 0x0038fe67, ++ 0x0044beb2, ++ 0x00513ef3, ++ 0x00595f11, ++ 0x00669f3d, ++ 0x0078dfdf, ++ 0x00a143aa, ++ 0x01642fff, ++ 0x0162afff, ++ 0x01620fff, ++ 0x0160cfff, ++ 0x015f0fff, ++ 0x015dafff, ++ 0x015bcfff, ++ 0x015bcfff, ++ 0x015b4fff, ++ 0x015acfff, ++ 0x01590fff, ++ 0x0156cfff, ++}; ++ ++static const u32 papd_cal_scalars_tbl_core1_rev7[] = { ++ 0x0b5e002d, ++ 0x0ae2002f, ++ 0x0a3b0032, ++ 0x09a70035, ++ 0x09220038, ++ 0x08ab003b, ++ 0x081f003f, ++ 0x07a20043, ++ 0x07340047, ++ 0x06d2004b, ++ 0x067a004f, ++ 0x06170054, ++ 0x05bf0059, ++ 0x0571005e, ++ 0x051e0064, ++ 0x04d3006a, ++ 0x04910070, ++ 0x044c0077, ++ 0x040f007e, ++ 0x03d90085, ++ 0x03a1008d, ++ 0x036f0095, ++ 0x033d009e, ++ 0x030b00a8, ++ 0x02e000b2, ++ 0x02b900bc, ++ 0x029200c7, ++ 0x026d00d3, ++ 0x024900e0, ++ 0x022900ed, ++ 0x020a00fb, ++ 0x01ec010a, ++ 0x01d20119, ++ 0x01b7012a, ++ 0x019e013c, ++ 0x0188014e, ++ 0x01720162, ++ 0x015d0177, ++ 0x0149018e, ++ 0x013701a5, ++ 0x012601be, ++ 0x011501d8, ++ 0x010601f4, ++ 0x00f70212, ++ 0x00e90231, ++ 0x00dc0253, ++ 0x00d00276, ++ 0x00c4029b, ++ 0x00b902c3, ++ 0x00af02ed, ++ 0x00a50319, ++ 0x009c0348, ++ 0x0093037a, ++ 0x008b03af, ++ 0x008303e6, ++ 0x007c0422, ++ 0x00750460, ++ 0x006e04a3, ++ 0x006804e9, ++ 0x00620533, ++ 0x005d0582, ++ 0x005805d6, ++ 0x0053062e, ++ 0x004e068c, ++}; ++ ++const struct phytbl_info mimophytbl_info_rev7[] = { ++ {&frame_struct_rev3, ++ sizeof(frame_struct_rev3) / sizeof(frame_struct_rev3[0]), 10, 0, 32} ++ , ++ {&pilot_tbl_rev3, sizeof(pilot_tbl_rev3) / sizeof(pilot_tbl_rev3[0]), ++ 11, 0, 16} ++ , ++ {&tmap_tbl_rev7, sizeof(tmap_tbl_rev7) / sizeof(tmap_tbl_rev7[0]), 12, ++ 0, 32} ++ , ++ {&intlv_tbl_rev3, sizeof(intlv_tbl_rev3) / sizeof(intlv_tbl_rev3[0]), ++ 13, 0, 32} ++ , ++ {&tdtrn_tbl_rev3, sizeof(tdtrn_tbl_rev3) / sizeof(tdtrn_tbl_rev3[0]), ++ 14, 0, 32} ++ , ++ {&noise_var_tbl_rev7, ++ sizeof(noise_var_tbl_rev7) / sizeof(noise_var_tbl_rev7[0]), 16, 0, 32} ++ , ++ {&mcs_tbl_rev3, sizeof(mcs_tbl_rev3) / sizeof(mcs_tbl_rev3[0]), 18, 0, ++ 16} ++ , ++ {&tdi_tbl20_ant0_rev3, ++ sizeof(tdi_tbl20_ant0_rev3) / sizeof(tdi_tbl20_ant0_rev3[0]), 19, 128, ++ 32} ++ , ++ {&tdi_tbl20_ant1_rev3, ++ sizeof(tdi_tbl20_ant1_rev3) / sizeof(tdi_tbl20_ant1_rev3[0]), 19, 256, ++ 32} ++ , ++ {&tdi_tbl40_ant0_rev3, ++ sizeof(tdi_tbl40_ant0_rev3) / sizeof(tdi_tbl40_ant0_rev3[0]), 19, 640, ++ 32} ++ , ++ {&tdi_tbl40_ant1_rev3, ++ sizeof(tdi_tbl40_ant1_rev3) / sizeof(tdi_tbl40_ant1_rev3[0]), 19, 768, ++ 32} ++ , ++ {&pltlut_tbl_rev3, sizeof(pltlut_tbl_rev3) / sizeof(pltlut_tbl_rev3[0]), ++ 20, 0, 32} ++ , ++ {&chanest_tbl_rev3, ++ sizeof(chanest_tbl_rev3) / sizeof(chanest_tbl_rev3[0]), 22, 0, 32} ++ , ++ {&frame_lut_rev3, sizeof(frame_lut_rev3) / sizeof(frame_lut_rev3[0]), ++ 24, 0, 8} ++ , ++ {&est_pwr_lut_core0_rev3, ++ sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26, ++ 0, 8} ++ , ++ {&est_pwr_lut_core1_rev3, ++ sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27, ++ 0, 8} ++ , ++ {&adj_pwr_lut_core0_rev3, ++ sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26, ++ 64, 8} ++ , ++ {&adj_pwr_lut_core1_rev3, ++ sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27, ++ 64, 8} ++ , ++ {&gainctrl_lut_core0_rev3, ++ sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]), ++ 26, 192, 32} ++ , ++ {&gainctrl_lut_core1_rev3, ++ sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]), ++ 27, 192, 32} ++ , ++ {&iq_lut_core0_rev3, ++ sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32} ++ , ++ {&iq_lut_core1_rev3, ++ sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32} ++ , ++ {&loft_lut_core0_rev3, ++ sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448, ++ 16} ++ , ++ {&loft_lut_core1_rev3, ++ sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448, ++ 16} ++ , ++ {&papd_comp_rfpwr_tbl_core0_rev3, ++ sizeof(papd_comp_rfpwr_tbl_core0_rev3) / ++ sizeof(papd_comp_rfpwr_tbl_core0_rev3[0]), 26, 576, 16} ++ , ++ {&papd_comp_rfpwr_tbl_core1_rev3, ++ sizeof(papd_comp_rfpwr_tbl_core1_rev3) / ++ sizeof(papd_comp_rfpwr_tbl_core1_rev3[0]), 27, 576, 16} ++ , ++ {&papd_comp_epsilon_tbl_core0_rev7, ++ sizeof(papd_comp_epsilon_tbl_core0_rev7) / ++ sizeof(papd_comp_epsilon_tbl_core0_rev7[0]), 31, 0, 32} ++ , ++ {&papd_cal_scalars_tbl_core0_rev7, ++ sizeof(papd_cal_scalars_tbl_core0_rev7) / ++ sizeof(papd_cal_scalars_tbl_core0_rev7[0]), 32, 0, 32} ++ , ++ {&papd_comp_epsilon_tbl_core1_rev7, ++ sizeof(papd_comp_epsilon_tbl_core1_rev7) / ++ sizeof(papd_comp_epsilon_tbl_core1_rev7[0]), 33, 0, 32} ++ , ++ {&papd_cal_scalars_tbl_core1_rev7, ++ sizeof(papd_cal_scalars_tbl_core1_rev7) / ++ sizeof(papd_cal_scalars_tbl_core1_rev7[0]), 34, 0, 32} ++ , ++}; ++ ++const u32 mimophytbl_info_sz_rev7 = ++ sizeof(mimophytbl_info_rev7) / sizeof(mimophytbl_info_rev7[0]); ++ ++const struct phytbl_info mimophytbl_info_rev16[] = { ++ {&noise_var_tbl_rev7, ++ sizeof(noise_var_tbl_rev7) / sizeof(noise_var_tbl_rev7[0]), 16, 0, 32} ++ , ++ {&est_pwr_lut_core0_rev3, ++ sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26, ++ 0, 8} ++ , ++ {&est_pwr_lut_core1_rev3, ++ sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27, ++ 0, 8} ++ , ++ {&adj_pwr_lut_core0_rev3, ++ sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26, ++ 64, 8} ++ , ++ {&adj_pwr_lut_core1_rev3, ++ sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27, ++ 64, 8} ++ , ++ {&gainctrl_lut_core0_rev3, ++ sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]), ++ 26, 192, 32} ++ , ++ {&gainctrl_lut_core1_rev3, ++ sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]), ++ 27, 192, 32} ++ , ++ {&iq_lut_core0_rev3, ++ sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32} ++ , ++ {&iq_lut_core1_rev3, ++ sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32} ++ , ++ {&loft_lut_core0_rev3, ++ sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448, ++ 16} ++ , ++ {&loft_lut_core1_rev3, ++ sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448, ++ 16} ++ , ++}; ++ ++const u32 mimophytbl_info_sz_rev16 = ++ sizeof(mimophytbl_info_rev16) / sizeof(mimophytbl_info_rev16[0]); +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.h.orig 2011-11-09 13:46:58.282800170 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_n.h 2011-11-09 13:47:17.040565666 -0500 +@@ -0,0 +1,50 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#define ANT_SWCTRL_TBL_REV3_IDX (0) ++ ++#include ++#include "phy_int.h" ++ ++extern const struct phytbl_info mimophytbl_info_rev0[], ++ mimophytbl_info_rev0_volatile[]; ++ ++extern const u32 mimophytbl_info_sz_rev0, ++ mimophytbl_info_sz_rev0_volatile; ++ ++extern const struct phytbl_info mimophytbl_info_rev3[], ++ mimophytbl_info_rev3_volatile[], ++ mimophytbl_info_rev3_volatile1[], ++ mimophytbl_info_rev3_volatile2[], ++ mimophytbl_info_rev3_volatile3[]; ++ ++extern const u32 mimophytbl_info_sz_rev3, ++ mimophytbl_info_sz_rev3_volatile, ++ mimophytbl_info_sz_rev3_volatile1, ++ mimophytbl_info_sz_rev3_volatile2, ++ mimophytbl_info_sz_rev3_volatile3; ++ ++extern const u32 noise_var_tbl_rev3[]; ++ ++extern const struct phytbl_info mimophytbl_info_rev7[]; ++ ++extern const u32 mimophytbl_info_sz_rev7; ++ ++extern const u32 noise_var_tbl_rev7[]; ++ ++extern const struct phytbl_info mimophytbl_info_rev16[]; ++ ++extern const u32 mimophytbl_info_sz_rev16; +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c.orig 2011-11-09 13:46:58.282800170 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c 2011-11-09 13:47:17.040565666 -0500 +@@ -0,0 +1,225 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/* ++ * This is "two-way" interface, acting as the SHIM layer between driver ++ * and PHY layer. The driver can optionally call this translation layer ++ * to do some preprocessing, then reach PHY. On the PHY->driver direction, ++ * all calls go through this layer since PHY doesn't have access to the ++ * driver's brcms_hardware pointer. ++ */ ++#include ++#include ++ ++#include "main.h" ++#include "mac80211_if.h" ++#include "phy_shim.h" ++ ++/* PHY SHIM module specific state */ ++struct phy_shim_info { ++ struct brcms_hardware *wlc_hw; /* pointer to main wlc_hw structure */ ++ struct brcms_c_info *wlc; /* pointer to main wlc structure */ ++ struct brcms_info *wl; /* pointer to os-specific private state */ ++}; ++ ++struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw, ++ struct brcms_info *wl, ++ struct brcms_c_info *wlc) { ++ struct phy_shim_info *physhim = NULL; ++ ++ physhim = kzalloc(sizeof(struct phy_shim_info), GFP_ATOMIC); ++ if (!physhim) ++ return NULL; ++ ++ physhim->wlc_hw = wlc_hw; ++ physhim->wlc = wlc; ++ physhim->wl = wl; ++ ++ return physhim; ++} ++ ++void wlc_phy_shim_detach(struct phy_shim_info *physhim) ++{ ++ kfree(physhim); ++} ++ ++struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim, ++ void (*fn)(struct brcms_phy *pi), ++ void *arg, const char *name) ++{ ++ return (struct wlapi_timer *) ++ brcms_init_timer(physhim->wl, (void (*)(void *))fn, ++ arg, name); ++} ++ ++void wlapi_free_timer(struct wlapi_timer *t) ++{ ++ brcms_free_timer((struct brcms_timer *)t); ++} ++ ++void ++wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic) ++{ ++ brcms_add_timer((struct brcms_timer *)t, ms, periodic); ++} ++ ++bool wlapi_del_timer(struct wlapi_timer *t) ++{ ++ return brcms_del_timer((struct brcms_timer *)t); ++} ++ ++void wlapi_intrson(struct phy_shim_info *physhim) ++{ ++ brcms_intrson(physhim->wl); ++} ++ ++u32 wlapi_intrsoff(struct phy_shim_info *physhim) ++{ ++ return brcms_intrsoff(physhim->wl); ++} ++ ++void wlapi_intrsrestore(struct phy_shim_info *physhim, u32 macintmask) ++{ ++ brcms_intrsrestore(physhim->wl, macintmask); ++} ++ ++void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset, u16 v) ++{ ++ brcms_b_write_shm(physhim->wlc_hw, offset, v); ++} ++ ++u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset) ++{ ++ return brcms_b_read_shm(physhim->wlc_hw, offset); ++} ++ ++void ++wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx, u16 mask, ++ u16 val, int bands) ++{ ++ brcms_b_mhf(physhim->wlc_hw, idx, mask, val, bands); ++} ++ ++void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags) ++{ ++ brcms_b_corereset(physhim->wlc_hw, flags); ++} ++ ++void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim) ++{ ++ brcms_c_suspend_mac_and_wait(physhim->wlc); ++} ++ ++void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode) ++{ ++ brcms_b_switch_macfreq(physhim->wlc_hw, spurmode); ++} ++ ++void wlapi_enable_mac(struct phy_shim_info *physhim) ++{ ++ brcms_c_enable_mac(physhim->wlc); ++} ++ ++void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask, u32 val) ++{ ++ brcms_b_mctrl(physhim->wlc_hw, mask, val); ++} ++ ++void wlapi_bmac_phy_reset(struct phy_shim_info *physhim) ++{ ++ brcms_b_phy_reset(physhim->wlc_hw); ++} ++ ++void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw) ++{ ++ brcms_b_bw_set(physhim->wlc_hw, bw); ++} ++ ++u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim) ++{ ++ return brcms_b_get_txant(physhim->wlc_hw); ++} ++ ++void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk) ++{ ++ brcms_b_phyclk_fgc(physhim->wlc_hw, clk); ++} ++ ++void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk) ++{ ++ brcms_b_macphyclk_set(physhim->wlc_hw, clk); ++} ++ ++void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on) ++{ ++ brcms_b_core_phypll_ctl(physhim->wlc_hw, on); ++} ++ ++void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim) ++{ ++ brcms_b_core_phypll_reset(physhim->wlc_hw); ++} ++ ++void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info *physhim) ++{ ++ brcms_c_ucode_wake_override_set(physhim->wlc_hw, ++ BRCMS_WAKE_OVERRIDE_PHYREG); ++} ++ ++void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info *physhim) ++{ ++ brcms_c_ucode_wake_override_clear(physhim->wlc_hw, ++ BRCMS_WAKE_OVERRIDE_PHYREG); ++} ++ ++void ++wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int offset, ++ int len, void *buf) ++{ ++ brcms_b_write_template_ram(physhim->wlc_hw, offset, len, buf); ++} ++ ++u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim, u8 rate) ++{ ++ return brcms_b_rate_shm_offset(physhim->wlc_hw, rate); ++} ++ ++void wlapi_ucode_sample_init(struct phy_shim_info *physhim) ++{ ++} ++ ++void ++wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint offset, void *buf, ++ int len, u32 sel) ++{ ++ brcms_b_copyfrom_objmem(physhim->wlc_hw, offset, buf, len, sel); ++} ++ ++void ++wlapi_copyto_objmem(struct phy_shim_info *physhim, uint offset, const void *buf, ++ int l, u32 sel) ++{ ++ brcms_b_copyto_objmem(physhim->wlc_hw, offset, buf, l, sel); ++} ++ ++char *wlapi_getvar(struct phy_shim_info *physhim, enum brcms_srom_id id) ++{ ++ return getvar(physhim->wlc_hw->sih, id); ++} ++int wlapi_getintvar(struct phy_shim_info *physhim, enum brcms_srom_id id) ++{ ++ return getintvar(physhim->wlc_hw->sih, id); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h.orig 2011-11-09 13:46:58.282800170 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h 2011-11-09 13:47:17.041565653 -0500 +@@ -0,0 +1,182 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/* ++ * phy_shim.h: stuff defined in phy_shim.c and included only by the phy ++ */ ++ ++#ifndef _BRCM_PHY_SHIM_H_ ++#define _BRCM_PHY_SHIM_H_ ++ ++#include "types.h" ++ ++#define RADAR_TYPE_NONE 0 /* Radar type None */ ++#define RADAR_TYPE_ETSI_1 1 /* ETSI 1 Radar type */ ++#define RADAR_TYPE_ETSI_2 2 /* ETSI 2 Radar type */ ++#define RADAR_TYPE_ETSI_3 3 /* ETSI 3 Radar type */ ++#define RADAR_TYPE_ITU_E 4 /* ITU E Radar type */ ++#define RADAR_TYPE_ITU_K 5 /* ITU K Radar type */ ++#define RADAR_TYPE_UNCLASSIFIED 6 /* Unclassified Radar type */ ++#define RADAR_TYPE_BIN5 7 /* long pulse radar type */ ++#define RADAR_TYPE_STG2 8 /* staggered-2 radar */ ++#define RADAR_TYPE_STG3 9 /* staggered-3 radar */ ++#define RADAR_TYPE_FRA 10 /* French radar */ ++ ++/* French radar pulse widths */ ++#define FRA_T1_20MHZ 52770 ++#define FRA_T2_20MHZ 61538 ++#define FRA_T3_20MHZ 66002 ++#define FRA_T1_40MHZ 105541 ++#define FRA_T2_40MHZ 123077 ++#define FRA_T3_40MHZ 132004 ++#define FRA_ERR_20MHZ 60 ++#define FRA_ERR_40MHZ 120 ++ ++#define ANTSEL_NA 0 /* No boardlevel selection available */ ++#define ANTSEL_2x4 1 /* 2x4 boardlevel selection available */ ++#define ANTSEL_2x3 2 /* 2x3 CB2 boardlevel selection available */ ++ ++/* Rx Antenna diversity control values */ ++#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */ ++#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */ ++#define ANT_RX_DIV_START_1 2 /* Choose starting with 1 */ ++#define ANT_RX_DIV_START_0 3 /* Choose starting with 0 */ ++#define ANT_RX_DIV_ENABLE 3 /* APHY bbConfig Enable RX Diversity */ ++#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0 /* default antdiv setting */ ++ ++#define WL_ANT_RX_MAX 2 /* max 2 receive antennas */ ++#define WL_ANT_HT_RX_MAX 3 /* max 3 receive antennas/cores */ ++#define WL_ANT_IDX_1 0 /* antenna index 1 */ ++#define WL_ANT_IDX_2 1 /* antenna index 2 */ ++ ++/* values for n_preamble_type */ ++#define BRCMS_N_PREAMBLE_MIXEDMODE 0 ++#define BRCMS_N_PREAMBLE_GF 1 ++#define BRCMS_N_PREAMBLE_GF_BRCM 2 ++ ++#define WL_TX_POWER_RATES_LEGACY 45 ++#define WL_TX_POWER_MCS20_FIRST 12 ++#define WL_TX_POWER_MCS20_NUM 16 ++#define WL_TX_POWER_MCS40_FIRST 28 ++#define WL_TX_POWER_MCS40_NUM 17 ++ ++ ++#define WL_TX_POWER_RATES 101 ++#define WL_TX_POWER_CCK_FIRST 0 ++#define WL_TX_POWER_CCK_NUM 4 ++/* Index for first 20MHz OFDM SISO rate */ ++#define WL_TX_POWER_OFDM_FIRST 4 ++/* Index for first 20MHz OFDM CDD rate */ ++#define WL_TX_POWER_OFDM20_CDD_FIRST 12 ++/* Index for first 40MHz OFDM SISO rate */ ++#define WL_TX_POWER_OFDM40_SISO_FIRST 52 ++/* Index for first 40MHz OFDM CDD rate */ ++#define WL_TX_POWER_OFDM40_CDD_FIRST 60 ++#define WL_TX_POWER_OFDM_NUM 8 ++/* Index for first 20MHz MCS SISO rate */ ++#define WL_TX_POWER_MCS20_SISO_FIRST 20 ++/* Index for first 20MHz MCS CDD rate */ ++#define WL_TX_POWER_MCS20_CDD_FIRST 28 ++/* Index for first 20MHz MCS STBC rate */ ++#define WL_TX_POWER_MCS20_STBC_FIRST 36 ++/* Index for first 20MHz MCS SDM rate */ ++#define WL_TX_POWER_MCS20_SDM_FIRST 44 ++/* Index for first 40MHz MCS SISO rate */ ++#define WL_TX_POWER_MCS40_SISO_FIRST 68 ++/* Index for first 40MHz MCS CDD rate */ ++#define WL_TX_POWER_MCS40_CDD_FIRST 76 ++/* Index for first 40MHz MCS STBC rate */ ++#define WL_TX_POWER_MCS40_STBC_FIRST 84 ++/* Index for first 40MHz MCS SDM rate */ ++#define WL_TX_POWER_MCS40_SDM_FIRST 92 ++#define WL_TX_POWER_MCS_1_STREAM_NUM 8 ++#define WL_TX_POWER_MCS_2_STREAM_NUM 8 ++/* Index for 40MHz rate MCS 32 */ ++#define WL_TX_POWER_MCS_32 100 ++#define WL_TX_POWER_MCS_32_NUM 1 ++ ++/* sslpnphy specifics */ ++/* Index for first 20MHz MCS SISO rate */ ++#define WL_TX_POWER_MCS20_SISO_FIRST_SSN 12 ++ ++/* struct tx_power::flags bits */ ++#define WL_TX_POWER_F_ENABLED 1 ++#define WL_TX_POWER_F_HW 2 ++#define WL_TX_POWER_F_MIMO 4 ++#define WL_TX_POWER_F_SISO 8 ++ ++/* values to force tx/rx chain */ ++#define BRCMS_N_TXRX_CHAIN0 0 ++#define BRCMS_N_TXRX_CHAIN1 1 ++ ++struct brcms_phy; ++ ++extern struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw, ++ struct brcms_info *wl, ++ struct brcms_c_info *wlc); ++extern void wlc_phy_shim_detach(struct phy_shim_info *physhim); ++ ++/* PHY to WL utility functions */ ++extern struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim, ++ void (*fn) (struct brcms_phy *pi), ++ void *arg, const char *name); ++extern void wlapi_free_timer(struct wlapi_timer *t); ++extern void wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic); ++extern bool wlapi_del_timer(struct wlapi_timer *t); ++extern void wlapi_intrson(struct phy_shim_info *physhim); ++extern u32 wlapi_intrsoff(struct phy_shim_info *physhim); ++extern void wlapi_intrsrestore(struct phy_shim_info *physhim, ++ u32 macintmask); ++ ++extern void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset, ++ u16 v); ++extern u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset); ++extern void wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx, ++ u16 mask, u16 val, int bands); ++extern void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags); ++extern void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim); ++extern void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode); ++extern void wlapi_enable_mac(struct phy_shim_info *physhim); ++extern void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask, ++ u32 val); ++extern void wlapi_bmac_phy_reset(struct phy_shim_info *physhim); ++extern void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw); ++extern void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk); ++extern void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk); ++extern void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on); ++extern void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim); ++extern void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info * ++ physhim); ++extern void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info * ++ physhim); ++extern void wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int o, ++ int len, void *buf); ++extern u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim, ++ u8 rate); ++extern void wlapi_ucode_sample_init(struct phy_shim_info *physhim); ++extern void wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint, ++ void *buf, int, u32 sel); ++extern void wlapi_copyto_objmem(struct phy_shim_info *physhim, uint, ++ const void *buf, int, u32); ++ ++extern void wlapi_high_update_phy_mode(struct phy_shim_info *physhim, ++ u32 phy_mode); ++extern u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim); ++extern char *wlapi_getvar(struct phy_shim_info *physhim, enum brcms_srom_id id); ++extern int wlapi_getintvar(struct phy_shim_info *physhim, ++ enum brcms_srom_id id); ++ ++#endif /* _BRCM_PHY_SHIM_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.c.orig 2011-11-09 13:46:58.283800157 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.c 2011-11-09 13:47:17.041565653 -0500 +@@ -0,0 +1,458 @@ ++/* ++ * Copyright (c) 2011 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include "pub.h" ++#include "aiutils.h" ++#include "pmu.h" ++ ++/* ++ * external LPO crystal frequency ++ */ ++#define EXT_ILP_HZ 32768 ++ ++/* ++ * Duration for ILP clock frequency measurment in milliseconds ++ * ++ * remark: 1000 must be an integer multiple of this duration ++ */ ++#define ILP_CALC_DUR 10 ++ ++/* Fields in pmucontrol */ ++#define PCTL_ILP_DIV_MASK 0xffff0000 ++#define PCTL_ILP_DIV_SHIFT 16 ++#define PCTL_PLL_PLLCTL_UPD 0x00000400 /* rev 2 */ ++#define PCTL_NOILP_ON_WAIT 0x00000200 /* rev 1 */ ++#define PCTL_HT_REQ_EN 0x00000100 ++#define PCTL_ALP_REQ_EN 0x00000080 ++#define PCTL_XTALFREQ_MASK 0x0000007c ++#define PCTL_XTALFREQ_SHIFT 2 ++#define PCTL_ILP_DIV_EN 0x00000002 ++#define PCTL_LPO_SEL 0x00000001 ++ ++/* ILP clock */ ++#define ILP_CLOCK 32000 ++ ++/* ALP clock on pre-PMU chips */ ++#define ALP_CLOCK 20000000 ++ ++/* pmustatus */ ++#define PST_EXTLPOAVAIL 0x0100 ++#define PST_WDRESET 0x0080 ++#define PST_INTPEND 0x0040 ++#define PST_SBCLKST 0x0030 ++#define PST_SBCLKST_ILP 0x0010 ++#define PST_SBCLKST_ALP 0x0020 ++#define PST_SBCLKST_HT 0x0030 ++#define PST_ALPAVAIL 0x0008 ++#define PST_HTAVAIL 0x0004 ++#define PST_RESINIT 0x0003 ++ ++/* PMU resource bit position */ ++#define PMURES_BIT(bit) (1 << (bit)) ++ ++/* PMU corerev and chip specific PLL controls. ++ * PMU_PLL_XX where is PMU corerev and is an arbitrary ++ * number to differentiate different PLLs controlled by the same PMU rev. ++ */ ++/* pllcontrol registers: ++ * ndiv_pwrdn, pwrdn_ch, refcomp_pwrdn, dly_ch, ++ * p1div, p2div, _bypass_sdmod ++ */ ++#define PMU1_PLL0_PLLCTL0 0 ++#define PMU1_PLL0_PLLCTL1 1 ++#define PMU1_PLL0_PLLCTL2 2 ++#define PMU1_PLL0_PLLCTL3 3 ++#define PMU1_PLL0_PLLCTL4 4 ++#define PMU1_PLL0_PLLCTL5 5 ++ ++/* pmu XtalFreqRatio */ ++#define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF ++#define PMU_XTALFREQ_REG_MEASURE_MASK 0x80000000 ++#define PMU_XTALFREQ_REG_MEASURE_SHIFT 31 ++ ++/* 4313 resources */ ++#define RES4313_BB_PU_RSRC 0 ++#define RES4313_ILP_REQ_RSRC 1 ++#define RES4313_XTAL_PU_RSRC 2 ++#define RES4313_ALP_AVAIL_RSRC 3 ++#define RES4313_RADIO_PU_RSRC 4 ++#define RES4313_BG_PU_RSRC 5 ++#define RES4313_VREG1P4_PU_RSRC 6 ++#define RES4313_AFE_PWRSW_RSRC 7 ++#define RES4313_RX_PWRSW_RSRC 8 ++#define RES4313_TX_PWRSW_RSRC 9 ++#define RES4313_BB_PWRSW_RSRC 10 ++#define RES4313_SYNTH_PWRSW_RSRC 11 ++#define RES4313_MISC_PWRSW_RSRC 12 ++#define RES4313_BB_PLL_PWRSW_RSRC 13 ++#define RES4313_HT_AVAIL_RSRC 14 ++#define RES4313_MACPHY_CLK_AVAIL_RSRC 15 ++ ++/* Determine min/max rsrc masks. Value 0 leaves hardware at default. */ ++static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax) ++{ ++ u32 min_mask = 0, max_mask = 0; ++ uint rsrcs; ++ ++ /* # resources */ ++ rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT; ++ ++ /* determine min/max rsrc masks */ ++ switch (sih->chip) { ++ case BCM43224_CHIP_ID: ++ case BCM43225_CHIP_ID: ++ /* ??? */ ++ break; ++ ++ case BCM4313_CHIP_ID: ++ min_mask = PMURES_BIT(RES4313_BB_PU_RSRC) | ++ PMURES_BIT(RES4313_XTAL_PU_RSRC) | ++ PMURES_BIT(RES4313_ALP_AVAIL_RSRC) | ++ PMURES_BIT(RES4313_BB_PLL_PWRSW_RSRC); ++ max_mask = 0xffff; ++ break; ++ default: ++ break; ++ } ++ ++ *pmin = min_mask; ++ *pmax = max_mask; ++} ++ ++static void ++si_pmu_spuravoid_pllupdate(struct si_pub *sih, struct chipcregs __iomem *cc, ++ u8 spuravoid) ++{ ++ u32 tmp = 0; ++ ++ switch (sih->chip) { ++ case BCM43224_CHIP_ID: ++ case BCM43225_CHIP_ID: ++ if (spuravoid == 1) { ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0); ++ W_REG(&cc->pllcontrol_data, 0x11500010); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1); ++ W_REG(&cc->pllcontrol_data, 0x000C0C06); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2); ++ W_REG(&cc->pllcontrol_data, 0x0F600a08); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3); ++ W_REG(&cc->pllcontrol_data, 0x00000000); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4); ++ W_REG(&cc->pllcontrol_data, 0x2001E920); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5); ++ W_REG(&cc->pllcontrol_data, 0x88888815); ++ } else { ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0); ++ W_REG(&cc->pllcontrol_data, 0x11100010); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1); ++ W_REG(&cc->pllcontrol_data, 0x000c0c06); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2); ++ W_REG(&cc->pllcontrol_data, 0x03000a08); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3); ++ W_REG(&cc->pllcontrol_data, 0x00000000); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4); ++ W_REG(&cc->pllcontrol_data, 0x200005c0); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5); ++ W_REG(&cc->pllcontrol_data, 0x88888815); ++ } ++ tmp = 1 << 10; ++ break; ++ ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0); ++ W_REG(&cc->pllcontrol_data, 0x11100008); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1); ++ W_REG(&cc->pllcontrol_data, 0x0c000c06); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2); ++ W_REG(&cc->pllcontrol_data, 0x03000a08); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3); ++ W_REG(&cc->pllcontrol_data, 0x00000000); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4); ++ W_REG(&cc->pllcontrol_data, 0x200005c0); ++ W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5); ++ W_REG(&cc->pllcontrol_data, 0x88888855); ++ ++ tmp = 1 << 10; ++ break; ++ ++ default: ++ /* bail out */ ++ return; ++ } ++ ++ tmp |= R_REG(&cc->pmucontrol); ++ W_REG(&cc->pmucontrol, tmp); ++} ++ ++u16 si_pmu_fast_pwrup_delay(struct si_pub *sih) ++{ ++ uint delay = PMU_MAX_TRANSITION_DLY; ++ ++ switch (sih->chip) { ++ case BCM43224_CHIP_ID: ++ case BCM43225_CHIP_ID: ++ case BCM4313_CHIP_ID: ++ delay = 3700; ++ break; ++ default: ++ break; ++ } ++ ++ return (u16) delay; ++} ++ ++void si_pmu_sprom_enable(struct si_pub *sih, bool enable) ++{ ++ struct chipcregs __iomem *cc; ++ uint origidx; ++ ++ /* Remember original core before switch to chipc */ ++ origidx = ai_coreidx(sih); ++ cc = ai_setcoreidx(sih, SI_CC_IDX); ++ ++ /* Return to original core */ ++ ai_setcoreidx(sih, origidx); ++} ++ ++/* Read/write a chipcontrol reg */ ++u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) ++{ ++ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol_addr), ++ ~0, reg); ++ return ai_corereg(sih, SI_CC_IDX, ++ offsetof(struct chipcregs, chipcontrol_data), mask, ++ val); ++} ++ ++/* Read/write a regcontrol reg */ ++u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) ++{ ++ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, regcontrol_addr), ++ ~0, reg); ++ return ai_corereg(sih, SI_CC_IDX, ++ offsetof(struct chipcregs, regcontrol_data), mask, ++ val); ++} ++ ++/* Read/write a pllcontrol reg */ ++u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) ++{ ++ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pllcontrol_addr), ++ ~0, reg); ++ return ai_corereg(sih, SI_CC_IDX, ++ offsetof(struct chipcregs, pllcontrol_data), mask, ++ val); ++} ++ ++/* PMU PLL update */ ++void si_pmu_pllupd(struct si_pub *sih) ++{ ++ ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pmucontrol), ++ PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD); ++} ++ ++/* query alp/xtal clock frequency */ ++u32 si_pmu_alp_clock(struct si_pub *sih) ++{ ++ u32 clock = ALP_CLOCK; ++ ++ /* bail out with default */ ++ if (!(sih->cccaps & CC_CAP_PMU)) ++ return clock; ++ ++ switch (sih->chip) { ++ case BCM43224_CHIP_ID: ++ case BCM43225_CHIP_ID: ++ case BCM4313_CHIP_ID: ++ /* always 20Mhz */ ++ clock = 20000 * 1000; ++ break; ++ default: ++ break; ++ } ++ ++ return clock; ++} ++ ++void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid) ++{ ++ struct chipcregs __iomem *cc; ++ uint origidx, intr_val; ++ ++ /* Remember original core before switch to chipc */ ++ cc = (struct chipcregs __iomem *) ++ ai_switch_core(sih, CC_CORE_ID, &origidx, &intr_val); ++ ++ /* update the pll changes */ ++ si_pmu_spuravoid_pllupdate(sih, cc, spuravoid); ++ ++ /* Return to original core */ ++ ai_restore_core(sih, origidx, intr_val); ++} ++ ++/* initialize PMU */ ++void si_pmu_init(struct si_pub *sih) ++{ ++ struct chipcregs __iomem *cc; ++ uint origidx; ++ ++ /* Remember original core before switch to chipc */ ++ origidx = ai_coreidx(sih); ++ cc = ai_setcoreidx(sih, SI_CC_IDX); ++ ++ if (sih->pmurev == 1) ++ AND_REG(&cc->pmucontrol, ~PCTL_NOILP_ON_WAIT); ++ else if (sih->pmurev >= 2) ++ OR_REG(&cc->pmucontrol, PCTL_NOILP_ON_WAIT); ++ ++ /* Return to original core */ ++ ai_setcoreidx(sih, origidx); ++} ++ ++/* initialize PMU chip controls and other chip level stuff */ ++void si_pmu_chip_init(struct si_pub *sih) ++{ ++ uint origidx; ++ ++ /* Gate off SPROM clock and chip select signals */ ++ si_pmu_sprom_enable(sih, false); ++ ++ /* Remember original core */ ++ origidx = ai_coreidx(sih); ++ ++ /* Return to original core */ ++ ai_setcoreidx(sih, origidx); ++} ++ ++/* initialize PMU switch/regulators */ ++void si_pmu_swreg_init(struct si_pub *sih) ++{ ++} ++ ++/* initialize PLL */ ++void si_pmu_pll_init(struct si_pub *sih, uint xtalfreq) ++{ ++ struct chipcregs __iomem *cc; ++ uint origidx; ++ ++ /* Remember original core before switch to chipc */ ++ origidx = ai_coreidx(sih); ++ cc = ai_setcoreidx(sih, SI_CC_IDX); ++ ++ switch (sih->chip) { ++ case BCM4313_CHIP_ID: ++ case BCM43224_CHIP_ID: ++ case BCM43225_CHIP_ID: ++ /* ??? */ ++ break; ++ default: ++ break; ++ } ++ ++ /* Return to original core */ ++ ai_setcoreidx(sih, origidx); ++} ++ ++/* initialize PMU resources */ ++void si_pmu_res_init(struct si_pub *sih) ++{ ++ struct chipcregs __iomem *cc; ++ uint origidx; ++ u32 min_mask = 0, max_mask = 0; ++ ++ /* Remember original core before switch to chipc */ ++ origidx = ai_coreidx(sih); ++ cc = ai_setcoreidx(sih, SI_CC_IDX); ++ ++ /* Determine min/max rsrc masks */ ++ si_pmu_res_masks(sih, &min_mask, &max_mask); ++ ++ /* It is required to program max_mask first and then min_mask */ ++ ++ /* Program max resource mask */ ++ ++ if (max_mask) ++ W_REG(&cc->max_res_mask, max_mask); ++ ++ /* Program min resource mask */ ++ ++ if (min_mask) ++ W_REG(&cc->min_res_mask, min_mask); ++ ++ /* Add some delay; allow resources to come up and settle. */ ++ mdelay(2); ++ ++ /* Return to original core */ ++ ai_setcoreidx(sih, origidx); ++} ++ ++u32 si_pmu_measure_alpclk(struct si_pub *sih) ++{ ++ struct chipcregs __iomem *cc; ++ uint origidx; ++ u32 alp_khz; ++ ++ if (sih->pmurev < 10) ++ return 0; ++ ++ /* Remember original core before switch to chipc */ ++ origidx = ai_coreidx(sih); ++ cc = ai_setcoreidx(sih, SI_CC_IDX); ++ ++ if (R_REG(&cc->pmustatus) & PST_EXTLPOAVAIL) { ++ u32 ilp_ctr, alp_hz; ++ ++ /* ++ * Enable the reg to measure the freq, ++ * in case it was disabled before ++ */ ++ W_REG(&cc->pmu_xtalfreq, ++ 1U << PMU_XTALFREQ_REG_MEASURE_SHIFT); ++ ++ /* Delay for well over 4 ILP clocks */ ++ udelay(1000); ++ ++ /* Read the latched number of ALP ticks per 4 ILP ticks */ ++ ilp_ctr = ++ R_REG(&cc->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK; ++ ++ /* ++ * Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT ++ * bit to save power ++ */ ++ W_REG(&cc->pmu_xtalfreq, 0); ++ ++ /* Calculate ALP frequency */ ++ alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4; ++ ++ /* ++ * Round to nearest 100KHz, and at ++ * the same time convert to KHz ++ */ ++ alp_khz = (alp_hz + 50000) / 100000 * 100; ++ } else ++ alp_khz = 0; ++ ++ /* Return to original core */ ++ ai_setcoreidx(sih, origidx); ++ ++ return alp_khz; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.h.orig 2011-11-09 13:46:58.283800157 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pmu.h 2011-11-09 13:47:17.041565653 -0500 +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef _BRCM_PMU_H_ ++#define _BRCM_PMU_H_ ++ ++#include "types.h" ++ ++extern u16 si_pmu_fast_pwrup_delay(struct si_pub *sih); ++extern void si_pmu_sprom_enable(struct si_pub *sih, bool enable); ++extern u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); ++extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); ++extern u32 si_pmu_alp_clock(struct si_pub *sih); ++extern void si_pmu_pllupd(struct si_pub *sih); ++extern void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid); ++extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); ++extern void si_pmu_init(struct si_pub *sih); ++extern void si_pmu_chip_init(struct si_pub *sih); ++extern void si_pmu_pll_init(struct si_pub *sih, u32 xtalfreq); ++extern void si_pmu_res_init(struct si_pub *sih); ++extern void si_pmu_swreg_init(struct si_pub *sih); ++extern u32 si_pmu_measure_alpclk(struct si_pub *sih); ++ ++#endif /* _BRCM_PMU_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pub.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pub.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pub.h.orig 2011-11-09 13:46:58.283800157 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/pub.h 2011-11-09 13:47:17.042565640 -0500 +@@ -0,0 +1,634 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_PUB_H_ ++#define _BRCM_PUB_H_ ++ ++#include ++#include "types.h" ++#include "defs.h" ++ ++enum brcms_srom_id { ++ BRCMS_SROM_NULL, ++ BRCMS_SROM_CONT, ++ BRCMS_SROM_AA2G, ++ BRCMS_SROM_AA5G, ++ BRCMS_SROM_AG0, ++ BRCMS_SROM_AG1, ++ BRCMS_SROM_AG2, ++ BRCMS_SROM_AG3, ++ BRCMS_SROM_ANTSWCTL2G, ++ BRCMS_SROM_ANTSWCTL5G, ++ BRCMS_SROM_ANTSWITCH, ++ BRCMS_SROM_BOARDFLAGS2, ++ BRCMS_SROM_BOARDFLAGS, ++ BRCMS_SROM_BOARDNUM, ++ BRCMS_SROM_BOARDREV, ++ BRCMS_SROM_BOARDTYPE, ++ BRCMS_SROM_BW40PO, ++ BRCMS_SROM_BWDUPPO, ++ BRCMS_SROM_BXA2G, ++ BRCMS_SROM_BXA5G, ++ BRCMS_SROM_CC, ++ BRCMS_SROM_CCK2GPO, ++ BRCMS_SROM_CCKBW202GPO, ++ BRCMS_SROM_CCKBW20UL2GPO, ++ BRCMS_SROM_CCODE, ++ BRCMS_SROM_CDDPO, ++ BRCMS_SROM_DEVID, ++ BRCMS_SROM_ET1MACADDR, ++ BRCMS_SROM_EXTPAGAIN2G, ++ BRCMS_SROM_EXTPAGAIN5G, ++ BRCMS_SROM_FREQOFFSET_CORR, ++ BRCMS_SROM_HW_IQCAL_EN, ++ BRCMS_SROM_IL0MACADDR, ++ BRCMS_SROM_IQCAL_SWP_DIS, ++ BRCMS_SROM_LEDBH0, ++ BRCMS_SROM_LEDBH1, ++ BRCMS_SROM_LEDBH2, ++ BRCMS_SROM_LEDBH3, ++ BRCMS_SROM_LEDDC, ++ BRCMS_SROM_LEGOFDM40DUPPO, ++ BRCMS_SROM_LEGOFDMBW202GPO, ++ BRCMS_SROM_LEGOFDMBW205GHPO, ++ BRCMS_SROM_LEGOFDMBW205GLPO, ++ BRCMS_SROM_LEGOFDMBW205GMPO, ++ BRCMS_SROM_LEGOFDMBW20UL2GPO, ++ BRCMS_SROM_LEGOFDMBW20UL5GHPO, ++ BRCMS_SROM_LEGOFDMBW20UL5GLPO, ++ BRCMS_SROM_LEGOFDMBW20UL5GMPO, ++ BRCMS_SROM_MACADDR, ++ BRCMS_SROM_MCS2GPO0, ++ BRCMS_SROM_MCS2GPO1, ++ BRCMS_SROM_MCS2GPO2, ++ BRCMS_SROM_MCS2GPO3, ++ BRCMS_SROM_MCS2GPO4, ++ BRCMS_SROM_MCS2GPO5, ++ BRCMS_SROM_MCS2GPO6, ++ BRCMS_SROM_MCS2GPO7, ++ BRCMS_SROM_MCS32PO, ++ BRCMS_SROM_MCS5GHPO0, ++ BRCMS_SROM_MCS5GHPO1, ++ BRCMS_SROM_MCS5GHPO2, ++ BRCMS_SROM_MCS5GHPO3, ++ BRCMS_SROM_MCS5GHPO4, ++ BRCMS_SROM_MCS5GHPO5, ++ BRCMS_SROM_MCS5GHPO6, ++ BRCMS_SROM_MCS5GHPO7, ++ BRCMS_SROM_MCS5GLPO0, ++ BRCMS_SROM_MCS5GLPO1, ++ BRCMS_SROM_MCS5GLPO2, ++ BRCMS_SROM_MCS5GLPO3, ++ BRCMS_SROM_MCS5GLPO4, ++ BRCMS_SROM_MCS5GLPO5, ++ BRCMS_SROM_MCS5GLPO6, ++ BRCMS_SROM_MCS5GLPO7, ++ BRCMS_SROM_MCS5GPO0, ++ BRCMS_SROM_MCS5GPO1, ++ BRCMS_SROM_MCS5GPO2, ++ BRCMS_SROM_MCS5GPO3, ++ BRCMS_SROM_MCS5GPO4, ++ BRCMS_SROM_MCS5GPO5, ++ BRCMS_SROM_MCS5GPO6, ++ BRCMS_SROM_MCS5GPO7, ++ BRCMS_SROM_MCSBW202GPO, ++ BRCMS_SROM_MCSBW205GHPO, ++ BRCMS_SROM_MCSBW205GLPO, ++ BRCMS_SROM_MCSBW205GMPO, ++ BRCMS_SROM_MCSBW20UL2GPO, ++ BRCMS_SROM_MCSBW20UL5GHPO, ++ BRCMS_SROM_MCSBW20UL5GLPO, ++ BRCMS_SROM_MCSBW20UL5GMPO, ++ BRCMS_SROM_MCSBW402GPO, ++ BRCMS_SROM_MCSBW405GHPO, ++ BRCMS_SROM_MCSBW405GLPO, ++ BRCMS_SROM_MCSBW405GMPO, ++ BRCMS_SROM_MEASPOWER, ++ BRCMS_SROM_OFDM2GPO, ++ BRCMS_SROM_OFDM5GHPO, ++ BRCMS_SROM_OFDM5GLPO, ++ BRCMS_SROM_OFDM5GPO, ++ BRCMS_SROM_OPO, ++ BRCMS_SROM_PA0B0, ++ BRCMS_SROM_PA0B1, ++ BRCMS_SROM_PA0B2, ++ BRCMS_SROM_PA0ITSSIT, ++ BRCMS_SROM_PA0MAXPWR, ++ BRCMS_SROM_PA1B0, ++ BRCMS_SROM_PA1B1, ++ BRCMS_SROM_PA1B2, ++ BRCMS_SROM_PA1HIB0, ++ BRCMS_SROM_PA1HIB1, ++ BRCMS_SROM_PA1HIB2, ++ BRCMS_SROM_PA1HIMAXPWR, ++ BRCMS_SROM_PA1ITSSIT, ++ BRCMS_SROM_PA1LOB0, ++ BRCMS_SROM_PA1LOB1, ++ BRCMS_SROM_PA1LOB2, ++ BRCMS_SROM_PA1LOMAXPWR, ++ BRCMS_SROM_PA1MAXPWR, ++ BRCMS_SROM_PDETRANGE2G, ++ BRCMS_SROM_PDETRANGE5G, ++ BRCMS_SROM_PHYCAL_TEMPDELTA, ++ BRCMS_SROM_RAWTEMPSENSE, ++ BRCMS_SROM_REGREV, ++ BRCMS_SROM_REV, ++ BRCMS_SROM_RSSISAV2G, ++ BRCMS_SROM_RSSISAV5G, ++ BRCMS_SROM_RSSISMC2G, ++ BRCMS_SROM_RSSISMC5G, ++ BRCMS_SROM_RSSISMF2G, ++ BRCMS_SROM_RSSISMF5G, ++ BRCMS_SROM_RXCHAIN, ++ BRCMS_SROM_RXPO2G, ++ BRCMS_SROM_RXPO5G, ++ BRCMS_SROM_STBCPO, ++ BRCMS_SROM_TEMPCORRX, ++ BRCMS_SROM_TEMPOFFSET, ++ BRCMS_SROM_TEMPSENSE_OPTION, ++ BRCMS_SROM_TEMPSENSE_SLOPE, ++ BRCMS_SROM_TEMPTHRESH, ++ BRCMS_SROM_TRI2G, ++ BRCMS_SROM_TRI5GH, ++ BRCMS_SROM_TRI5GL, ++ BRCMS_SROM_TRI5G, ++ BRCMS_SROM_TRISO2G, ++ BRCMS_SROM_TRISO5G, ++ BRCMS_SROM_TSSIPOS2G, ++ BRCMS_SROM_TSSIPOS5G, ++ BRCMS_SROM_TXCHAIN, ++ BRCMS_SROM_TXPID2GA0, ++ BRCMS_SROM_TXPID2GA1, ++ BRCMS_SROM_TXPID2GA2, ++ BRCMS_SROM_TXPID2GA3, ++ BRCMS_SROM_TXPID5GA0, ++ BRCMS_SROM_TXPID5GA1, ++ BRCMS_SROM_TXPID5GA2, ++ BRCMS_SROM_TXPID5GA3, ++ BRCMS_SROM_TXPID5GHA0, ++ BRCMS_SROM_TXPID5GHA1, ++ BRCMS_SROM_TXPID5GHA2, ++ BRCMS_SROM_TXPID5GHA3, ++ BRCMS_SROM_TXPID5GLA0, ++ BRCMS_SROM_TXPID5GLA1, ++ BRCMS_SROM_TXPID5GLA2, ++ BRCMS_SROM_TXPID5GLA3, ++ /* ++ * per-path identifiers (see srom.c) ++ */ ++ BRCMS_SROM_ITT2GA0, ++ BRCMS_SROM_ITT2GA1, ++ BRCMS_SROM_ITT2GA2, ++ BRCMS_SROM_ITT2GA3, ++ BRCMS_SROM_ITT5GA0, ++ BRCMS_SROM_ITT5GA1, ++ BRCMS_SROM_ITT5GA2, ++ BRCMS_SROM_ITT5GA3, ++ BRCMS_SROM_MAXP2GA0, ++ BRCMS_SROM_MAXP2GA1, ++ BRCMS_SROM_MAXP2GA2, ++ BRCMS_SROM_MAXP2GA3, ++ BRCMS_SROM_MAXP5GA0, ++ BRCMS_SROM_MAXP5GA1, ++ BRCMS_SROM_MAXP5GA2, ++ BRCMS_SROM_MAXP5GA3, ++ BRCMS_SROM_MAXP5GHA0, ++ BRCMS_SROM_MAXP5GHA1, ++ BRCMS_SROM_MAXP5GHA2, ++ BRCMS_SROM_MAXP5GHA3, ++ BRCMS_SROM_MAXP5GLA0, ++ BRCMS_SROM_MAXP5GLA1, ++ BRCMS_SROM_MAXP5GLA2, ++ BRCMS_SROM_MAXP5GLA3, ++ BRCMS_SROM_PA2GW0A0, ++ BRCMS_SROM_PA2GW0A1, ++ BRCMS_SROM_PA2GW0A2, ++ BRCMS_SROM_PA2GW0A3, ++ BRCMS_SROM_PA2GW1A0, ++ BRCMS_SROM_PA2GW1A1, ++ BRCMS_SROM_PA2GW1A2, ++ BRCMS_SROM_PA2GW1A3, ++ BRCMS_SROM_PA2GW2A0, ++ BRCMS_SROM_PA2GW2A1, ++ BRCMS_SROM_PA2GW2A2, ++ BRCMS_SROM_PA2GW2A3, ++ BRCMS_SROM_PA2GW3A0, ++ BRCMS_SROM_PA2GW3A1, ++ BRCMS_SROM_PA2GW3A2, ++ BRCMS_SROM_PA2GW3A3, ++ BRCMS_SROM_PA5GHW0A0, ++ BRCMS_SROM_PA5GHW0A1, ++ BRCMS_SROM_PA5GHW0A2, ++ BRCMS_SROM_PA5GHW0A3, ++ BRCMS_SROM_PA5GHW1A0, ++ BRCMS_SROM_PA5GHW1A1, ++ BRCMS_SROM_PA5GHW1A2, ++ BRCMS_SROM_PA5GHW1A3, ++ BRCMS_SROM_PA5GHW2A0, ++ BRCMS_SROM_PA5GHW2A1, ++ BRCMS_SROM_PA5GHW2A2, ++ BRCMS_SROM_PA5GHW2A3, ++ BRCMS_SROM_PA5GHW3A0, ++ BRCMS_SROM_PA5GHW3A1, ++ BRCMS_SROM_PA5GHW3A2, ++ BRCMS_SROM_PA5GHW3A3, ++ BRCMS_SROM_PA5GLW0A0, ++ BRCMS_SROM_PA5GLW0A1, ++ BRCMS_SROM_PA5GLW0A2, ++ BRCMS_SROM_PA5GLW0A3, ++ BRCMS_SROM_PA5GLW1A0, ++ BRCMS_SROM_PA5GLW1A1, ++ BRCMS_SROM_PA5GLW1A2, ++ BRCMS_SROM_PA5GLW1A3, ++ BRCMS_SROM_PA5GLW2A0, ++ BRCMS_SROM_PA5GLW2A1, ++ BRCMS_SROM_PA5GLW2A2, ++ BRCMS_SROM_PA5GLW2A3, ++ BRCMS_SROM_PA5GLW3A0, ++ BRCMS_SROM_PA5GLW3A1, ++ BRCMS_SROM_PA5GLW3A2, ++ BRCMS_SROM_PA5GLW3A3, ++ BRCMS_SROM_PA5GW0A0, ++ BRCMS_SROM_PA5GW0A1, ++ BRCMS_SROM_PA5GW0A2, ++ BRCMS_SROM_PA5GW0A3, ++ BRCMS_SROM_PA5GW1A0, ++ BRCMS_SROM_PA5GW1A1, ++ BRCMS_SROM_PA5GW1A2, ++ BRCMS_SROM_PA5GW1A3, ++ BRCMS_SROM_PA5GW2A0, ++ BRCMS_SROM_PA5GW2A1, ++ BRCMS_SROM_PA5GW2A2, ++ BRCMS_SROM_PA5GW2A3, ++ BRCMS_SROM_PA5GW3A0, ++ BRCMS_SROM_PA5GW3A1, ++ BRCMS_SROM_PA5GW3A2, ++ BRCMS_SROM_PA5GW3A3, ++}; ++ ++#define BRCMS_NUMRATES 16 /* max # of rates in a rateset */ ++#define D11_PHY_HDR_LEN 6 /* Phy header length - 6 bytes */ ++ ++/* phy types */ ++#define PHY_TYPE_A 0 /* Phy type A */ ++#define PHY_TYPE_G 2 /* Phy type G */ ++#define PHY_TYPE_N 4 /* Phy type N */ ++#define PHY_TYPE_LP 5 /* Phy type Low Power A/B/G */ ++#define PHY_TYPE_SSN 6 /* Phy type Single Stream N */ ++#define PHY_TYPE_LCN 8 /* Phy type Single Stream N */ ++#define PHY_TYPE_LCNXN 9 /* Phy type 2-stream N */ ++#define PHY_TYPE_HT 7 /* Phy type 3-Stream N */ ++ ++/* bw */ ++#define BRCMS_10_MHZ 10 /* 10Mhz nphy channel bandwidth */ ++#define BRCMS_20_MHZ 20 /* 20Mhz nphy channel bandwidth */ ++#define BRCMS_40_MHZ 40 /* 40Mhz nphy channel bandwidth */ ++ ++#define BRCMS_RSSI_MINVAL -200 /* Low value, e.g. for forcing roam */ ++#define BRCMS_RSSI_NO_SIGNAL -91 /* NDIS RSSI link quality cutoffs */ ++#define BRCMS_RSSI_VERY_LOW -80 /* Very low quality cutoffs */ ++#define BRCMS_RSSI_LOW -70 /* Low quality cutoffs */ ++#define BRCMS_RSSI_GOOD -68 /* Good quality cutoffs */ ++#define BRCMS_RSSI_VERY_GOOD -58 /* Very good quality cutoffs */ ++#define BRCMS_RSSI_EXCELLENT -57 /* Excellent quality cutoffs */ ++ ++/* a large TX Power as an init value to factor out of min() calculations, ++ * keep low enough to fit in an s8, units are .25 dBm ++ */ ++#define BRCMS_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */ ++ ++/* rate related definitions */ ++#define BRCMS_RATE_FLAG 0x80 /* Flag to indicate it is a basic rate */ ++#define BRCMS_RATE_MASK 0x7f /* Rate value mask w/o basic rate flag */ ++ ++/* legacy rx Antenna diversity for SISO rates */ ++#define ANT_RX_DIV_FORCE_0 0 /* Use antenna 0 */ ++#define ANT_RX_DIV_FORCE_1 1 /* Use antenna 1 */ ++#define ANT_RX_DIV_START_1 2 /* Choose starting with 1 */ ++#define ANT_RX_DIV_START_0 3 /* Choose starting with 0 */ ++#define ANT_RX_DIV_ENABLE 3 /* APHY bbConfig Enable RX Diversity */ ++/* default antdiv setting */ ++#define ANT_RX_DIV_DEF ANT_RX_DIV_START_0 ++ ++/* legacy rx Antenna diversity for SISO rates */ ++/* Tx on antenna 0, "legacy term Main" */ ++#define ANT_TX_FORCE_0 0 ++/* Tx on antenna 1, "legacy term Aux" */ ++#define ANT_TX_FORCE_1 1 ++/* Tx on phy's last good Rx antenna */ ++#define ANT_TX_LAST_RX 3 ++/* driver's default tx antenna setting */ ++#define ANT_TX_DEF 3 ++ ++/* Tx Chain values */ ++/* def bitmap of txchain */ ++#define TXCHAIN_DEF 0x1 ++/* default bitmap of tx chains for nphy */ ++#define TXCHAIN_DEF_NPHY 0x3 ++/* default bitmap of tx chains for nphy */ ++#define TXCHAIN_DEF_HTPHY 0x7 ++/* def bitmap of rxchain */ ++#define RXCHAIN_DEF 0x1 ++/* default bitmap of rx chains for nphy */ ++#define RXCHAIN_DEF_NPHY 0x3 ++/* default bitmap of rx chains for nphy */ ++#define RXCHAIN_DEF_HTPHY 0x7 ++/* no antenna switch */ ++#define ANTSWITCH_NONE 0 ++/* antenna switch on 4321CB2, 2of3 */ ++#define ANTSWITCH_TYPE_1 1 ++/* antenna switch on 4321MPCI, 2of3 */ ++#define ANTSWITCH_TYPE_2 2 ++/* antenna switch on 4322, 2of3 */ ++#define ANTSWITCH_TYPE_3 3 ++ ++#define RXBUFSZ PKTBUFSZ ++ ++#define MAX_STREAMS_SUPPORTED 4 /* max number of streams supported */ ++ ++struct brcm_rateset { ++ /* # rates in this set */ ++ u32 count; ++ /* rates in 500kbps units w/hi bit set if basic */ ++ u8 rates[WL_NUMRATES]; ++}; ++ ++struct brcms_c_rateset { ++ uint count; /* number of rates in rates[] */ ++ /* rates in 500kbps units w/hi bit set if basic */ ++ u8 rates[BRCMS_NUMRATES]; ++ u8 htphy_membership; /* HT PHY Membership */ ++ u8 mcs[MCSSET_LEN]; /* supported mcs index bit map */ ++}; ++ ++/* All the HT-specific default advertised capabilities (including AMPDU) ++ * should be grouped here at one place ++ */ ++#define AMPDU_DEF_MPDU_DENSITY 6 /* default mpdu density (110 ==> 4us) */ ++ ++/* wlc internal bss_info */ ++struct brcms_bss_info { ++ u8 BSSID[ETH_ALEN]; /* network BSSID */ ++ u16 flags; /* flags for internal attributes */ ++ u8 SSID_len; /* the length of SSID */ ++ u8 SSID[32]; /* SSID string */ ++ s16 RSSI; /* receive signal strength (in dBm) */ ++ s16 SNR; /* receive signal SNR in dB */ ++ u16 beacon_period; /* units are Kusec */ ++ u16 chanspec; /* Channel num, bw, ctrl_sb and band */ ++ struct brcms_c_rateset rateset; /* supported rates */ ++}; ++ ++#define MAC80211_PROMISC_BCNS (1 << 0) ++#define MAC80211_SCAN (1 << 1) ++ ++/* ++ * Public portion of common driver state structure. ++ * The wlc handle points at this. ++ */ ++struct brcms_pub { ++ struct brcms_c_info *wlc; ++ struct ieee80211_hw *ieee_hw; ++ struct scb_ampdu *global_ampdu; ++ uint mac80211_state; ++ uint unit; /* device instance number */ ++ uint corerev; /* core revision */ ++ struct si_pub *sih; /* SI handle (cookie for siutils calls) */ ++ bool up; /* interface up and running */ ++ bool hw_off; /* HW is off */ ++ bool hw_up; /* one time hw up/down */ ++ bool _piomode; /* true if pio mode */ ++ uint _nbands; /* # bands supported */ ++ uint now; /* # elapsed seconds */ ++ ++ bool promisc; /* promiscuous destination address */ ++ bool delayed_down; /* down delayed */ ++ bool associated; /* true:part of [I]BSS, false: not */ ++ /* (union of stas_associated, aps_associated) */ ++ bool _ampdu; /* ampdu enabled or not */ ++ u8 _n_enab; /* bitmap of 11N + HT support */ ++ ++ u8 cur_etheraddr[ETH_ALEN]; /* our local ethernet address */ ++ ++ int bcmerror; /* last bcm error */ ++ ++ u32 radio_disabled; /* bit vector for radio disabled reasons */ ++ ++ u16 boardrev; /* version # of particular board */ ++ u8 sromrev; /* version # of the srom */ ++ char srom_ccode[BRCM_CNTRY_BUF_SZ]; /* Country Code in SROM */ ++ u32 boardflags; /* Board specific flags from srom */ ++ u32 boardflags2; /* More board flags if sromrev >= 4 */ ++ bool phy_11ncapable; /* the PHY/HW is capable of 802.11N */ ++ ++ struct wl_cnt *_cnt; /* low-level counters in driver */ ++}; ++ ++enum wlc_par_id { ++ IOV_MPC = 1, ++ IOV_RTSTHRESH, ++ IOV_QTXPOWER, ++ IOV_BCN_LI_BCN /* Beacon listen interval in # of beacons */ ++}; ++ ++/*********************************************** ++ * Feature-related macros to optimize out code * ++ * ********************************************* ++ */ ++ ++#define ENAB_1x1 0x01 ++#define ENAB_2x2 0x02 ++#define ENAB_3x3 0x04 ++#define ENAB_4x4 0x08 ++#define SUPPORT_11N (ENAB_1x1|ENAB_2x2) ++#define SUPPORT_HT (ENAB_1x1|ENAB_2x2|ENAB_3x3) ++ ++/* WL11N Support */ ++#define AMPDU_AGG_HOST 1 ++ ++/* pri is priority encoded in the packet. This maps the Packet priority to ++ * enqueue precedence as defined in wlc_prec_map ++ */ ++extern const u8 wlc_prio2prec_map[]; ++#define BRCMS_PRIO_TO_PREC(pri) wlc_prio2prec_map[(pri) & 7] ++ ++#define BRCMS_PREC_COUNT 16 /* Max precedence level implemented */ ++ ++/* Mask to describe all precedence levels */ ++#define BRCMS_PREC_BMP_ALL MAXBITVAL(BRCMS_PREC_COUNT) ++ ++/* ++ * This maps priority to one precedence higher - Used by PS-Poll response ++ * packets to simulate enqueue-at-head operation, but still maintain the ++ * order on the queue ++ */ ++#define BRCMS_PRIO_TO_HI_PREC(pri) min(BRCMS_PRIO_TO_PREC(pri) + 1,\ ++ BRCMS_PREC_COUNT - 1) ++ ++/* Define a bitmap of precedences comprised by each AC */ ++#define BRCMS_PREC_BMP_AC_BE (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BE)) | \ ++ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BE)) | \ ++ NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_EE)) | \ ++ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_EE))) ++#define BRCMS_PREC_BMP_AC_BK (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_BK)) | \ ++ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_BK)) | \ ++ NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NONE)) | \ ++ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NONE))) ++#define BRCMS_PREC_BMP_AC_VI (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_CL)) | \ ++ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_CL)) | \ ++ NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VI)) | \ ++ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VI))) ++#define BRCMS_PREC_BMP_AC_VO (NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_VO)) | \ ++ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_VO)) | \ ++ NBITVAL(BRCMS_PRIO_TO_PREC(PRIO_8021D_NC)) | \ ++ NBITVAL(BRCMS_PRIO_TO_HI_PREC(PRIO_8021D_NC))) ++ ++/* network protection config */ ++#define BRCMS_PROT_G_SPEC 1 /* SPEC g protection */ ++#define BRCMS_PROT_G_OVR 2 /* SPEC g prot override */ ++#define BRCMS_PROT_G_USER 3 /* gmode specified by user */ ++#define BRCMS_PROT_OVERLAP 4 /* overlap */ ++#define BRCMS_PROT_N_USER 10 /* nmode specified by user */ ++#define BRCMS_PROT_N_CFG 11 /* n protection */ ++#define BRCMS_PROT_N_CFG_OVR 12 /* n protection override */ ++#define BRCMS_PROT_N_NONGF 13 /* non-GF protection */ ++#define BRCMS_PROT_N_NONGF_OVR 14 /* non-GF protection override */ ++#define BRCMS_PROT_N_PAM_OVR 15 /* n preamble override */ ++#define BRCMS_PROT_N_OBSS 16 /* non-HT OBSS present */ ++ ++/* ++ * 54g modes (basic bits may still be overridden) ++ * ++ * GMODE_LEGACY_B ++ * Rateset: 1b, 2b, 5.5, 11 ++ * Preamble: Long ++ * Shortslot: Off ++ * GMODE_AUTO ++ * Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 ++ * Extended Rateset: 6, 9, 12, 48 ++ * Preamble: Long ++ * Shortslot: Auto ++ * GMODE_ONLY ++ * Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54 ++ * Extended Rateset: 6b, 9, 12b, 48 ++ * Preamble: Short required ++ * Shortslot: Auto ++ * GMODE_B_DEFERRED ++ * Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 ++ * Extended Rateset: 6, 9, 12, 48 ++ * Preamble: Long ++ * Shortslot: On ++ * GMODE_PERFORMANCE ++ * Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54 ++ * Preamble: Short required ++ * Shortslot: On and required ++ * GMODE_LRS ++ * Rateset: 1b, 2b, 5.5b, 11b ++ * Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54 ++ * Preamble: Long ++ * Shortslot: Auto ++ */ ++#define GMODE_LEGACY_B 0 ++#define GMODE_AUTO 1 ++#define GMODE_ONLY 2 ++#define GMODE_B_DEFERRED 3 ++#define GMODE_PERFORMANCE 4 ++#define GMODE_LRS 5 ++#define GMODE_MAX 6 ++ ++/* MCS values greater than this enable multiple streams */ ++#define HIGHEST_SINGLE_STREAM_MCS 7 ++ ++#define MAXBANDS 2 /* Maximum #of bands */ ++ ++/* max number of antenna configurations */ ++#define ANT_SELCFG_MAX 4 ++ ++struct brcms_antselcfg { ++ u8 ant_config[ANT_SELCFG_MAX]; /* antenna configuration */ ++ u8 num_antcfg; /* number of available antenna configurations */ ++}; ++ ++/* common functions for every port */ ++extern struct brcms_c_info * ++brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit, ++ bool piomode, void __iomem *regsva, struct pci_dev *btparam, ++ uint *perr); ++extern uint brcms_c_detach(struct brcms_c_info *wlc); ++extern int brcms_c_up(struct brcms_c_info *wlc); ++extern uint brcms_c_down(struct brcms_c_info *wlc); ++ ++extern bool brcms_c_chipmatch(u16 vendor, u16 device); ++extern void brcms_c_init(struct brcms_c_info *wlc); ++extern void brcms_c_reset(struct brcms_c_info *wlc); ++ ++extern void brcms_c_intrson(struct brcms_c_info *wlc); ++extern u32 brcms_c_intrsoff(struct brcms_c_info *wlc); ++extern void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask); ++extern bool brcms_c_intrsupd(struct brcms_c_info *wlc); ++extern bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc); ++extern bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded); ++extern void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, ++ struct sk_buff *sdu, ++ struct ieee80211_hw *hw); ++extern bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid); ++extern void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, ++ int val); ++extern int brcms_c_get_header_len(void); ++extern void brcms_c_set_addrmatch(struct brcms_c_info *wlc, ++ int match_reg_offset, ++ const u8 *addr); ++extern void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci, ++ const struct ieee80211_tx_queue_params *arg, ++ bool suspend); ++extern struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc); ++extern void brcms_c_ampdu_flush(struct brcms_c_info *wlc, ++ struct ieee80211_sta *sta, u16 tid); ++extern void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, ++ u8 ba_wsize, uint max_rx_ampdu_bytes); ++extern char *getvar(struct si_pub *sih, enum brcms_srom_id id); ++extern int getintvar(struct si_pub *sih, enum brcms_srom_id id); ++extern int brcms_c_module_register(struct brcms_pub *pub, ++ const char *name, struct brcms_info *hdl, ++ int (*down_fn)(void *handle)); ++extern int brcms_c_module_unregister(struct brcms_pub *pub, const char *name, ++ struct brcms_info *hdl); ++extern void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc); ++extern void brcms_c_enable_mac(struct brcms_c_info *wlc); ++extern void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state); ++extern void brcms_c_scan_start(struct brcms_c_info *wlc); ++extern void brcms_c_scan_stop(struct brcms_c_info *wlc); ++extern int brcms_c_get_curband(struct brcms_c_info *wlc); ++extern void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, ++ bool drop); ++extern int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel); ++extern int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl); ++extern void brcms_c_get_current_rateset(struct brcms_c_info *wlc, ++ struct brcm_rateset *currs); ++extern int brcms_c_set_rateset(struct brcms_c_info *wlc, ++ struct brcm_rateset *rs); ++extern int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period); ++extern u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx); ++extern void brcms_c_set_shortslot_override(struct brcms_c_info *wlc, ++ s8 sslot_override); ++extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, ++ u8 interval); ++extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr); ++extern int brcms_c_get_tx_power(struct brcms_c_info *wlc); ++extern void brcms_c_set_radio_mpc(struct brcms_c_info *wlc, bool mpc); ++extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc); ++ ++#endif /* _BRCM_PUB_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.c.orig 2011-11-09 13:46:58.284800145 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.c 2011-11-09 13:47:17.042565640 -0500 +@@ -0,0 +1,514 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include "d11.h" ++#include "pub.h" ++#include "rate.h" ++ ++/* ++ * Rate info per rate: It tells whether a rate is ofdm or not and its phy_rate ++ * value ++ */ ++const u8 rate_info[BRCM_MAXRATE + 1] = { ++ /* 0 1 2 3 4 5 6 7 8 9 */ ++/* 0 */ 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, ++/* 10 */ 0x00, 0x37, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00, ++/* 20 */ 0x00, 0x00, 0x6e, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, ++/* 30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, ++/* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, ++/* 50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++/* 60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++/* 70 */ 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++/* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++/* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, ++/* 100 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c ++}; ++ ++/* rates are in units of Kbps */ ++const struct brcms_mcs_info mcs_table[MCS_TABLE_SIZE] = { ++ /* MCS 0: SS 1, MOD: BPSK, CR 1/2 */ ++ {6500, 13500, CEIL(6500 * 10, 9), CEIL(13500 * 10, 9), 0x00, ++ BRCM_RATE_6M}, ++ /* MCS 1: SS 1, MOD: QPSK, CR 1/2 */ ++ {13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x08, ++ BRCM_RATE_12M}, ++ /* MCS 2: SS 1, MOD: QPSK, CR 3/4 */ ++ {19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x0A, ++ BRCM_RATE_18M}, ++ /* MCS 3: SS 1, MOD: 16QAM, CR 1/2 */ ++ {26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x10, ++ BRCM_RATE_24M}, ++ /* MCS 4: SS 1, MOD: 16QAM, CR 3/4 */ ++ {39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x12, ++ BRCM_RATE_36M}, ++ /* MCS 5: SS 1, MOD: 64QAM, CR 2/3 */ ++ {52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x19, ++ BRCM_RATE_48M}, ++ /* MCS 6: SS 1, MOD: 64QAM, CR 3/4 */ ++ {58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x1A, ++ BRCM_RATE_54M}, ++ /* MCS 7: SS 1, MOD: 64QAM, CR 5/6 */ ++ {65000, 135000, CEIL(65000 * 10, 9), CEIL(135000 * 10, 9), 0x1C, ++ BRCM_RATE_54M}, ++ /* MCS 8: SS 2, MOD: BPSK, CR 1/2 */ ++ {13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x40, ++ BRCM_RATE_6M}, ++ /* MCS 9: SS 2, MOD: QPSK, CR 1/2 */ ++ {26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x48, ++ BRCM_RATE_12M}, ++ /* MCS 10: SS 2, MOD: QPSK, CR 3/4 */ ++ {39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x4A, ++ BRCM_RATE_18M}, ++ /* MCS 11: SS 2, MOD: 16QAM, CR 1/2 */ ++ {52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x50, ++ BRCM_RATE_24M}, ++ /* MCS 12: SS 2, MOD: 16QAM, CR 3/4 */ ++ {78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x52, ++ BRCM_RATE_36M}, ++ /* MCS 13: SS 2, MOD: 64QAM, CR 2/3 */ ++ {104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0x59, ++ BRCM_RATE_48M}, ++ /* MCS 14: SS 2, MOD: 64QAM, CR 3/4 */ ++ {117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x5A, ++ BRCM_RATE_54M}, ++ /* MCS 15: SS 2, MOD: 64QAM, CR 5/6 */ ++ {130000, 270000, CEIL(130000 * 10, 9), CEIL(270000 * 10, 9), 0x5C, ++ BRCM_RATE_54M}, ++ /* MCS 16: SS 3, MOD: BPSK, CR 1/2 */ ++ {19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x80, ++ BRCM_RATE_6M}, ++ /* MCS 17: SS 3, MOD: QPSK, CR 1/2 */ ++ {39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x88, ++ BRCM_RATE_12M}, ++ /* MCS 18: SS 3, MOD: QPSK, CR 3/4 */ ++ {58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x8A, ++ BRCM_RATE_18M}, ++ /* MCS 19: SS 3, MOD: 16QAM, CR 1/2 */ ++ {78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x90, ++ BRCM_RATE_24M}, ++ /* MCS 20: SS 3, MOD: 16QAM, CR 3/4 */ ++ {117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x92, ++ BRCM_RATE_36M}, ++ /* MCS 21: SS 3, MOD: 64QAM, CR 2/3 */ ++ {156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0x99, ++ BRCM_RATE_48M}, ++ /* MCS 22: SS 3, MOD: 64QAM, CR 3/4 */ ++ {175500, 364500, CEIL(175500 * 10, 9), CEIL(364500 * 10, 9), 0x9A, ++ BRCM_RATE_54M}, ++ /* MCS 23: SS 3, MOD: 64QAM, CR 5/6 */ ++ {195000, 405000, CEIL(195000 * 10, 9), CEIL(405000 * 10, 9), 0x9B, ++ BRCM_RATE_54M}, ++ /* MCS 24: SS 4, MOD: BPSK, CR 1/2 */ ++ {26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0xC0, ++ BRCM_RATE_6M}, ++ /* MCS 25: SS 4, MOD: QPSK, CR 1/2 */ ++ {52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0xC8, ++ BRCM_RATE_12M}, ++ /* MCS 26: SS 4, MOD: QPSK, CR 3/4 */ ++ {78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0xCA, ++ BRCM_RATE_18M}, ++ /* MCS 27: SS 4, MOD: 16QAM, CR 1/2 */ ++ {104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0xD0, ++ BRCM_RATE_24M}, ++ /* MCS 28: SS 4, MOD: 16QAM, CR 3/4 */ ++ {156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0xD2, ++ BRCM_RATE_36M}, ++ /* MCS 29: SS 4, MOD: 64QAM, CR 2/3 */ ++ {208000, 432000, CEIL(208000 * 10, 9), CEIL(432000 * 10, 9), 0xD9, ++ BRCM_RATE_48M}, ++ /* MCS 30: SS 4, MOD: 64QAM, CR 3/4 */ ++ {234000, 486000, CEIL(234000 * 10, 9), CEIL(486000 * 10, 9), 0xDA, ++ BRCM_RATE_54M}, ++ /* MCS 31: SS 4, MOD: 64QAM, CR 5/6 */ ++ {260000, 540000, CEIL(260000 * 10, 9), CEIL(540000 * 10, 9), 0xDB, ++ BRCM_RATE_54M}, ++ /* MCS 32: SS 1, MOD: BPSK, CR 1/2 */ ++ {0, 6000, 0, CEIL(6000 * 10, 9), 0x00, BRCM_RATE_6M}, ++}; ++ ++/* ++ * phycfg for legacy OFDM frames: code rate, modulation scheme, spatial streams ++ * Number of spatial streams: always 1 other fields: refer to table 78 of ++ * section 17.3.2.2 of the original .11a standard ++ */ ++struct legacy_phycfg { ++ u32 rate_ofdm; /* ofdm mac rate */ ++ /* phy ctl byte 3, code rate, modulation type, # of streams */ ++ u8 tx_phy_ctl3; ++}; ++ ++/* Number of legacy_rate_cfg entries in the table */ ++#define LEGACY_PHYCFG_TABLE_SIZE 12 ++ ++/* ++ * In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate ++ * Eventually MIMOPHY would also be converted to this format ++ * 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps ++ */ ++static const struct ++legacy_phycfg legacy_phycfg_table[LEGACY_PHYCFG_TABLE_SIZE] = { ++ {BRCM_RATE_1M, 0x00}, /* CCK 1Mbps, data rate 0 */ ++ {BRCM_RATE_2M, 0x08}, /* CCK 2Mbps, data rate 1 */ ++ {BRCM_RATE_5M5, 0x10}, /* CCK 5.5Mbps, data rate 2 */ ++ {BRCM_RATE_11M, 0x18}, /* CCK 11Mbps, data rate 3 */ ++ /* OFDM 6Mbps, code rate 1/2, BPSK, 1 spatial stream */ ++ {BRCM_RATE_6M, 0x00}, ++ /* OFDM 9Mbps, code rate 3/4, BPSK, 1 spatial stream */ ++ {BRCM_RATE_9M, 0x02}, ++ /* OFDM 12Mbps, code rate 1/2, QPSK, 1 spatial stream */ ++ {BRCM_RATE_12M, 0x08}, ++ /* OFDM 18Mbps, code rate 3/4, QPSK, 1 spatial stream */ ++ {BRCM_RATE_18M, 0x0A}, ++ /* OFDM 24Mbps, code rate 1/2, 16-QAM, 1 spatial stream */ ++ {BRCM_RATE_24M, 0x10}, ++ /* OFDM 36Mbps, code rate 3/4, 16-QAM, 1 spatial stream */ ++ {BRCM_RATE_36M, 0x12}, ++ /* OFDM 48Mbps, code rate 2/3, 64-QAM, 1 spatial stream */ ++ {BRCM_RATE_48M, 0x19}, ++ /* OFDM 54Mbps, code rate 3/4, 64-QAM, 1 spatial stream */ ++ {BRCM_RATE_54M, 0x1A}, ++}; ++ ++/* Hardware rates (also encodes default basic rates) */ ++ ++const struct brcms_c_rateset cck_ofdm_mimo_rates = { ++ 12, ++ /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, */ ++ { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, ++ /* 54 Mbps */ ++ 0x6c}, ++ 0x00, ++ { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00} ++}; ++ ++const struct brcms_c_rateset ofdm_mimo_rates = { ++ 8, ++ /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */ ++ { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c}, ++ 0x00, ++ { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* Default ratesets that include MCS32 for 40BW channels */ ++static const struct brcms_c_rateset cck_ofdm_40bw_mimo_rates = { ++ 12, ++ /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48 */ ++ { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, ++ /* 54 Mbps */ ++ 0x6c}, ++ 0x00, ++ { 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00} ++}; ++ ++static const struct brcms_c_rateset ofdm_40bw_mimo_rates = { ++ 8, ++ /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */ ++ { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c}, ++ 0x00, ++ { 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00} ++}; ++ ++const struct brcms_c_rateset cck_ofdm_rates = { ++ 12, ++ /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48,*/ ++ { 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, ++ /*54 Mbps */ ++ 0x6c}, ++ 0x00, ++ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00} ++}; ++ ++const struct brcms_c_rateset gphy_legacy_rates = { ++ 4, ++ /* 1b, 2b, 5.5b, 11b Mbps */ ++ { 0x82, 0x84, 0x8b, 0x96}, ++ 0x00, ++ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00} ++}; ++ ++const struct brcms_c_rateset ofdm_rates = { ++ 8, ++ /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */ ++ { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c}, ++ 0x00, ++ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00} ++}; ++ ++const struct brcms_c_rateset cck_rates = { ++ 4, ++ /* 1b, 2b, 5.5, 11 Mbps */ ++ { 0x82, 0x84, 0x0b, 0x16}, ++ 0x00, ++ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00} ++}; ++ ++/* check if rateset is valid. ++ * if check_brate is true, rateset without a basic rate is considered NOT valid. ++ */ ++static bool brcms_c_rateset_valid(struct brcms_c_rateset *rs, bool check_brate) ++{ ++ uint idx; ++ ++ if (!rs->count) ++ return false; ++ ++ if (!check_brate) ++ return true; ++ ++ /* error if no basic rates */ ++ for (idx = 0; idx < rs->count; idx++) { ++ if (rs->rates[idx] & BRCMS_RATE_FLAG) ++ return true; ++ } ++ return false; ++} ++ ++void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams) ++{ ++ int i; ++ for (i = txstreams; i < MAX_STREAMS_SUPPORTED; i++) ++ rs->mcs[i] = 0; ++} ++ ++/* ++ * filter based on hardware rateset, and sort filtered rateset with basic ++ * bit(s) preserved, and check if resulting rateset is valid. ++*/ ++bool ++brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs, ++ const struct brcms_c_rateset *hw_rs, ++ bool check_brate, u8 txstreams) ++{ ++ u8 rateset[BRCM_MAXRATE + 1]; ++ u8 r; ++ uint count; ++ uint i; ++ ++ memset(rateset, 0, sizeof(rateset)); ++ count = rs->count; ++ ++ for (i = 0; i < count; i++) { ++ /* mask off "basic rate" bit, BRCMS_RATE_FLAG */ ++ r = (int)rs->rates[i] & BRCMS_RATE_MASK; ++ if ((r > BRCM_MAXRATE) || (rate_info[r] == 0)) ++ continue; ++ rateset[r] = rs->rates[i]; /* preserve basic bit! */ ++ } ++ ++ /* fill out the rates in order, looking at only supported rates */ ++ count = 0; ++ for (i = 0; i < hw_rs->count; i++) { ++ r = hw_rs->rates[i] & BRCMS_RATE_MASK; ++ if (rateset[r]) ++ rs->rates[count++] = rateset[r]; ++ } ++ ++ rs->count = count; ++ ++ /* only set the mcs rate bit if the equivalent hw mcs bit is set */ ++ for (i = 0; i < MCSSET_LEN; i++) ++ rs->mcs[i] = (rs->mcs[i] & hw_rs->mcs[i]); ++ ++ if (brcms_c_rateset_valid(rs, check_brate)) ++ return true; ++ else ++ return false; ++} ++ ++/* calculate the rate of a rx'd frame and return it as a ratespec */ ++u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp) ++{ ++ int phy_type; ++ u32 rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT; ++ ++ phy_type = ++ ((rxh->RxChan & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT); ++ ++ if ((phy_type == PHY_TYPE_N) || (phy_type == PHY_TYPE_SSN) || ++ (phy_type == PHY_TYPE_LCN) || (phy_type == PHY_TYPE_HT)) { ++ switch (rxh->PhyRxStatus_0 & PRXS0_FT_MASK) { ++ case PRXS0_CCK: ++ rspec = ++ cck_phy2mac_rate( ++ ((struct cck_phy_hdr *) plcp)->signal); ++ break; ++ case PRXS0_OFDM: ++ rspec = ++ ofdm_phy2mac_rate( ++ ((struct ofdm_phy_hdr *) plcp)->rlpt[0]); ++ break; ++ case PRXS0_PREN: ++ rspec = (plcp[0] & MIMO_PLCP_MCS_MASK) | RSPEC_MIMORATE; ++ if (plcp[0] & MIMO_PLCP_40MHZ) { ++ /* indicate rspec is for 40 MHz mode */ ++ rspec &= ~RSPEC_BW_MASK; ++ rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT); ++ } ++ break; ++ case PRXS0_STDN: ++ /* fallthru */ ++ default: ++ /* not supported, error condition */ ++ break; ++ } ++ if (plcp3_issgi(plcp[3])) ++ rspec |= RSPEC_SHORT_GI; ++ } else ++ if ((phy_type == PHY_TYPE_A) || (rxh->PhyRxStatus_0 & PRXS0_OFDM)) ++ rspec = ofdm_phy2mac_rate( ++ ((struct ofdm_phy_hdr *) plcp)->rlpt[0]); ++ else ++ rspec = cck_phy2mac_rate( ++ ((struct cck_phy_hdr *) plcp)->signal); ++ ++ return rspec; ++} ++ ++/* copy rateset src to dst as-is (no masking or sorting) */ ++void brcms_c_rateset_copy(const struct brcms_c_rateset *src, ++ struct brcms_c_rateset *dst) ++{ ++ memcpy(dst, src, sizeof(struct brcms_c_rateset)); ++} ++ ++/* ++ * Copy and selectively filter one rateset to another. ++ * 'basic_only' means only copy basic rates. ++ * 'rates' indicates cck (11b) and ofdm rates combinations. ++ * - 0: cck and ofdm ++ * - 1: cck only ++ * - 2: ofdm only ++ * 'xmask' is the copy mask (typically 0x7f or 0xff). ++ */ ++void ++brcms_c_rateset_filter(struct brcms_c_rateset *src, struct brcms_c_rateset *dst, ++ bool basic_only, u8 rates, uint xmask, bool mcsallow) ++{ ++ uint i; ++ uint r; ++ uint count; ++ ++ count = 0; ++ for (i = 0; i < src->count; i++) { ++ r = src->rates[i]; ++ if (basic_only && !(r & BRCMS_RATE_FLAG)) ++ continue; ++ if (rates == BRCMS_RATES_CCK && ++ is_ofdm_rate((r & BRCMS_RATE_MASK))) ++ continue; ++ if (rates == BRCMS_RATES_OFDM && ++ is_cck_rate((r & BRCMS_RATE_MASK))) ++ continue; ++ dst->rates[count++] = r & xmask; ++ } ++ dst->count = count; ++ dst->htphy_membership = src->htphy_membership; ++ ++ if (mcsallow && rates != BRCMS_RATES_CCK) ++ memcpy(&dst->mcs[0], &src->mcs[0], MCSSET_LEN); ++ else ++ brcms_c_rateset_mcs_clear(dst); ++} ++ ++/* select rateset for a given phy_type and bandtype and filter it, sort it ++ * and fill rs_tgt with result ++ */ ++void ++brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt, ++ const struct brcms_c_rateset *rs_hw, ++ uint phy_type, int bandtype, bool cck_only, ++ uint rate_mask, bool mcsallow, u8 bw, u8 txstreams) ++{ ++ const struct brcms_c_rateset *rs_dflt; ++ struct brcms_c_rateset rs_sel; ++ if ((PHYTYPE_IS(phy_type, PHY_TYPE_HT)) || ++ (PHYTYPE_IS(phy_type, PHY_TYPE_N)) || ++ (PHYTYPE_IS(phy_type, PHY_TYPE_LCN)) || ++ (PHYTYPE_IS(phy_type, PHY_TYPE_SSN))) { ++ if (bandtype == BRCM_BAND_5G) ++ rs_dflt = (bw == BRCMS_20_MHZ ? ++ &ofdm_mimo_rates : &ofdm_40bw_mimo_rates); ++ else ++ rs_dflt = (bw == BRCMS_20_MHZ ? ++ &cck_ofdm_mimo_rates : ++ &cck_ofdm_40bw_mimo_rates); ++ } else if (PHYTYPE_IS(phy_type, PHY_TYPE_LP)) { ++ rs_dflt = (bandtype == BRCM_BAND_5G) ? ++ &ofdm_rates : &cck_ofdm_rates; ++ } else if (PHYTYPE_IS(phy_type, PHY_TYPE_A)) { ++ rs_dflt = &ofdm_rates; ++ } else if (PHYTYPE_IS(phy_type, PHY_TYPE_G)) { ++ rs_dflt = &cck_ofdm_rates; ++ } else { ++ /* should not happen, error condition */ ++ rs_dflt = &cck_rates; /* force cck */ ++ } ++ ++ /* if hw rateset is not supplied, assign selected rateset to it */ ++ if (!rs_hw) ++ rs_hw = rs_dflt; ++ ++ brcms_c_rateset_copy(rs_dflt, &rs_sel); ++ brcms_c_rateset_mcs_upd(&rs_sel, txstreams); ++ brcms_c_rateset_filter(&rs_sel, rs_tgt, false, ++ cck_only ? BRCMS_RATES_CCK : BRCMS_RATES_CCK_OFDM, ++ rate_mask, mcsallow); ++ brcms_c_rate_hwrs_filter_sort_validate(rs_tgt, rs_hw, false, ++ mcsallow ? txstreams : 1); ++} ++ ++s16 brcms_c_rate_legacy_phyctl(uint rate) ++{ ++ uint i; ++ for (i = 0; i < LEGACY_PHYCFG_TABLE_SIZE; i++) ++ if (rate == legacy_phycfg_table[i].rate_ofdm) ++ return legacy_phycfg_table[i].tx_phy_ctl3; ++ ++ return -1; ++} ++ ++void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset) ++{ ++ uint i; ++ for (i = 0; i < MCSSET_LEN; i++) ++ rateset->mcs[i] = 0; ++} ++ ++void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, u8 txstreams) ++{ ++ memcpy(&rateset->mcs[0], &cck_ofdm_mimo_rates.mcs[0], MCSSET_LEN); ++ brcms_c_rateset_mcs_upd(rateset, txstreams); ++} ++ ++/* Based on bandwidth passed, allow/disallow MCS 32 in the rateset */ ++void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, u8 bw) ++{ ++ if (bw == BRCMS_40_MHZ) ++ setbit(rateset->mcs, 32); ++ else ++ clrbit(rateset->mcs, 32); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.h.orig 2011-11-09 13:46:58.284800145 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/rate.h 2011-11-09 13:47:17.043565628 -0500 +@@ -0,0 +1,250 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_RATE_H_ ++#define _BRCM_RATE_H_ ++ ++#include "types.h" ++#include "d11.h" ++ ++extern const u8 rate_info[]; ++extern const struct brcms_c_rateset cck_ofdm_mimo_rates; ++extern const struct brcms_c_rateset ofdm_mimo_rates; ++extern const struct brcms_c_rateset cck_ofdm_rates; ++extern const struct brcms_c_rateset ofdm_rates; ++extern const struct brcms_c_rateset cck_rates; ++extern const struct brcms_c_rateset gphy_legacy_rates; ++extern const struct brcms_c_rateset rate_limit_1_2; ++ ++struct brcms_mcs_info { ++ /* phy rate in kbps [20Mhz] */ ++ u32 phy_rate_20; ++ /* phy rate in kbps [40Mhz] */ ++ u32 phy_rate_40; ++ /* phy rate in kbps [20Mhz] with SGI */ ++ u32 phy_rate_20_sgi; ++ /* phy rate in kbps [40Mhz] with SGI */ ++ u32 phy_rate_40_sgi; ++ /* phy ctl byte 3, code rate, modulation type, # of streams */ ++ u8 tx_phy_ctl3; ++ /* matching legacy ofdm rate in 500bkps */ ++ u8 leg_ofdm; ++}; ++ ++#define BRCMS_MAXMCS 32 /* max valid mcs index */ ++#define MCS_TABLE_SIZE 33 /* Number of mcs entries in the table */ ++extern const struct brcms_mcs_info mcs_table[]; ++ ++#define MCS_TXS_MASK 0xc0 /* num tx streams - 1 bit mask */ ++#define MCS_TXS_SHIFT 6 /* num tx streams - 1 bit shift */ ++ ++/* returns num tx streams - 1 */ ++static inline u8 mcs_2_txstreams(u8 mcs) ++{ ++ return (mcs_table[mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT; ++} ++ ++static inline uint mcs_2_rate(u8 mcs, bool is40, bool sgi) ++{ ++ if (sgi) { ++ if (is40) ++ return mcs_table[mcs].phy_rate_40_sgi; ++ return mcs_table[mcs].phy_rate_20_sgi; ++ } ++ if (is40) ++ return mcs_table[mcs].phy_rate_40; ++ ++ return mcs_table[mcs].phy_rate_20; ++} ++ ++/* Macro to use the rate_info table */ ++#define BRCMS_RATE_MASK_FULL 0xff /* Rate value mask with basic rate flag */ ++ ++/* ++ * rate spec : holds rate and mode specific information required to generate a ++ * tx frame. Legacy CCK and OFDM information is held in the same manner as was ++ * done in the past (in the lower byte) the upper 3 bytes primarily hold MIMO ++ * specific information ++ */ ++ ++/* rate spec bit fields */ ++ ++/* Either 500Kbps units or MIMO MCS idx */ ++#define RSPEC_RATE_MASK 0x0000007F ++/* mimo MCS is stored in RSPEC_RATE_MASK */ ++#define RSPEC_MIMORATE 0x08000000 ++/* mimo bw mask */ ++#define RSPEC_BW_MASK 0x00000700 ++/* mimo bw shift */ ++#define RSPEC_BW_SHIFT 8 ++/* mimo Space/Time/Frequency mode mask */ ++#define RSPEC_STF_MASK 0x00003800 ++/* mimo Space/Time/Frequency mode shift */ ++#define RSPEC_STF_SHIFT 11 ++/* mimo coding type mask */ ++#define RSPEC_CT_MASK 0x0000C000 ++/* mimo coding type shift */ ++#define RSPEC_CT_SHIFT 14 ++/* mimo num STC streams per PLCP defn. */ ++#define RSPEC_STC_MASK 0x00300000 ++/* mimo num STC streams per PLCP defn. */ ++#define RSPEC_STC_SHIFT 20 ++/* mimo bit indicates adv coding in use */ ++#define RSPEC_LDPC_CODING 0x00400000 ++/* mimo bit indicates short GI in use */ ++#define RSPEC_SHORT_GI 0x00800000 ++/* bit indicates override both rate & mode */ ++#define RSPEC_OVERRIDE 0x80000000 ++/* bit indicates override rate only */ ++#define RSPEC_OVERRIDE_MCS_ONLY 0x40000000 ++ ++static inline bool rspec_active(u32 rspec) ++{ ++ return rspec & (RSPEC_RATE_MASK | RSPEC_MIMORATE); ++} ++ ++static inline u8 rspec_phytxbyte2(u32 rspec) ++{ ++ return (rspec & 0xff00) >> 8; ++} ++ ++static inline u32 rspec_get_bw(u32 rspec) ++{ ++ return (rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT; ++} ++ ++static inline bool rspec_issgi(u32 rspec) ++{ ++ return (rspec & RSPEC_SHORT_GI) == RSPEC_SHORT_GI; ++} ++ ++static inline bool rspec_is40mhz(u32 rspec) ++{ ++ u32 bw = rspec_get_bw(rspec); ++ ++ return bw == PHY_TXC1_BW_40MHZ || bw == PHY_TXC1_BW_40MHZ_DUP; ++} ++ ++static inline uint rspec2rate(u32 rspec) ++{ ++ if (rspec & RSPEC_MIMORATE) ++ return mcs_2_rate(rspec & RSPEC_RATE_MASK, rspec_is40mhz(rspec), ++ rspec_issgi(rspec)); ++ return rspec & RSPEC_RATE_MASK; ++} ++ ++static inline u8 rspec_mimoplcp3(u32 rspec) ++{ ++ return (rspec & 0xf00000) >> 16; ++} ++ ++static inline bool plcp3_issgi(u8 plcp) ++{ ++ return (plcp & (RSPEC_SHORT_GI >> 16)) != 0; ++} ++ ++static inline uint rspec_stc(u32 rspec) ++{ ++ return (rspec & RSPEC_STC_MASK) >> RSPEC_STC_SHIFT; ++} ++ ++static inline uint rspec_stf(u32 rspec) ++{ ++ return (rspec & RSPEC_STF_MASK) >> RSPEC_STF_SHIFT; ++} ++ ++static inline bool is_mcs_rate(u32 ratespec) ++{ ++ return (ratespec & RSPEC_MIMORATE) != 0; ++} ++ ++static inline bool is_ofdm_rate(u32 ratespec) ++{ ++ return !is_mcs_rate(ratespec) && ++ (rate_info[ratespec & RSPEC_RATE_MASK] & BRCMS_RATE_FLAG); ++} ++ ++static inline bool is_cck_rate(u32 ratespec) ++{ ++ u32 rate = (ratespec & BRCMS_RATE_MASK); ++ ++ return !is_mcs_rate(ratespec) && ( ++ rate == BRCM_RATE_1M || rate == BRCM_RATE_2M || ++ rate == BRCM_RATE_5M5 || rate == BRCM_RATE_11M); ++} ++ ++static inline bool is_single_stream(u8 mcs) ++{ ++ return mcs <= HIGHEST_SINGLE_STREAM_MCS || mcs == 32; ++} ++ ++static inline u8 cck_rspec(u8 cck) ++{ ++ return cck & RSPEC_RATE_MASK; ++} ++ ++/* Convert encoded rate value in plcp header to numerical rates in 500 KHz ++ * increments */ ++extern const u8 ofdm_rate_lookup[]; ++ ++static inline u8 ofdm_phy2mac_rate(u8 rlpt) ++{ ++ return ofdm_rate_lookup[rlpt & 0x7]; ++} ++ ++static inline u8 cck_phy2mac_rate(u8 signal) ++{ ++ return signal/5; ++} ++ ++/* Rates specified in brcms_c_rateset_filter() */ ++#define BRCMS_RATES_CCK_OFDM 0 ++#define BRCMS_RATES_CCK 1 ++#define BRCMS_RATES_OFDM 2 ++ ++/* sanitize, and sort a rateset with the basic bit(s) preserved, validate ++ * rateset */ ++extern bool ++brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs, ++ const struct brcms_c_rateset *hw_rs, ++ bool check_brate, u8 txstreams); ++/* copy rateset src to dst as-is (no masking or sorting) */ ++extern void brcms_c_rateset_copy(const struct brcms_c_rateset *src, ++ struct brcms_c_rateset *dst); ++ ++/* would be nice to have these documented ... */ ++extern u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp); ++ ++extern void brcms_c_rateset_filter(struct brcms_c_rateset *src, ++ struct brcms_c_rateset *dst, bool basic_only, u8 rates, uint xmask, ++ bool mcsallow); ++ ++extern void ++brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt, ++ const struct brcms_c_rateset *rs_hw, uint phy_type, ++ int bandtype, bool cck_only, uint rate_mask, ++ bool mcsallow, u8 bw, u8 txstreams); ++ ++extern s16 brcms_c_rate_legacy_phyctl(uint rate); ++ ++extern void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams); ++extern void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset); ++extern void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, ++ u8 txstreams); ++extern void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, ++ u8 bw); ++ ++#endif /* _BRCM_RATE_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/scb.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/scb.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/scb.h.orig 2011-11-09 13:46:58.284800145 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/scb.h 2011-11-09 13:47:17.043565628 -0500 +@@ -0,0 +1,82 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_SCB_H_ ++#define _BRCM_SCB_H_ ++ ++#include ++#include ++#include ++#include "types.h" ++ ++#define AMPDU_TX_BA_MAX_WSIZE 64 /* max Tx ba window size (in pdu) */ ++ ++#define AMPDU_MAX_SCB_TID NUMPRIO ++ ++/* scb flags */ ++#define SCB_WMECAP 0x0040 ++#define SCB_HTCAP 0x10000 /* HT (MIMO) capable device */ ++#define SCB_IS40 0x80000 /* 40MHz capable */ ++#define SCB_STBCCAP 0x40000000 /* STBC Capable */ ++ ++#define SCB_MAGIC 0xbeefcafe ++ ++/* structure to store per-tid state for the ampdu initiator */ ++struct scb_ampdu_tid_ini { ++ u8 tx_in_transit; /* number of pending mpdus in transit in driver */ ++ u8 tid; /* initiator tid for easy lookup */ ++ /* tx retry count; indexed by seq modulo */ ++ u8 txretry[AMPDU_TX_BA_MAX_WSIZE]; ++ struct scb *scb; /* backptr for easy lookup */ ++ u8 ba_wsize; /* negotiated ba window size (in pdu) */ ++}; ++ ++struct scb_ampdu { ++ struct scb *scb; /* back pointer for easy reference */ ++ u8 mpdu_density; /* mpdu density */ ++ u8 max_pdu; /* max pdus allowed in ampdu */ ++ u8 release; /* # of mpdus released at a time */ ++ u16 min_len; /* min mpdu len to support the density */ ++ u32 max_rx_ampdu_bytes; /* max ampdu rcv length; 8k, 16k, 32k, 64k */ ++ ++ /* ++ * This could easily be a ini[] pointer and we keep this info in wl ++ * itself instead of having mac80211 hold it for us. Also could be made ++ * dynamic per tid instead of static. ++ */ ++ /* initiator info - per tid (NUMPRIO): */ ++ struct scb_ampdu_tid_ini ini[AMPDU_MAX_SCB_TID]; ++}; ++ ++/* station control block - one per remote MAC address */ ++struct scb { ++ u32 magic; ++ u32 flags; /* various bit flags as defined below */ ++ u32 flags2; /* various bit flags2 as defined below */ ++ u8 state; /* current state bitfield of auth/assoc process */ ++ u8 ea[ETH_ALEN]; /* station address */ ++ uint fragresid[NUMPRIO];/* #bytes unused in frag buffer per prio */ ++ ++ u16 seqctl[NUMPRIO]; /* seqctl of last received frame (for dups) */ ++ /* seqctl of last received frame (for dups) for non-QoS data and ++ * management */ ++ u16 seqctl_nonqos; ++ u16 seqnum[NUMPRIO];/* WME: driver maintained sw seqnum per priority */ ++ ++ struct scb_ampdu scb_ampdu; /* AMPDU state including per tid info */ ++}; ++ ++#endif /* _BRCM_SCB_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.c.orig 2011-11-09 13:46:58.285800133 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.c 2011-11-09 13:47:17.044565616 -0500 +@@ -0,0 +1,1298 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include "pub.h" ++#include "nicpci.h" ++#include "aiutils.h" ++#include "otp.h" ++#include "srom.h" ++ ++/* ++ * SROM CRC8 polynomial value: ++ * ++ * x^8 + x^7 +x^6 + x^4 + x^2 + 1 ++ */ ++#define SROM_CRC8_POLY 0xAB ++ ++/* Maximum srom: 6 Kilobits == 768 bytes */ ++#define SROM_MAX 768 ++ ++/* PCI fields */ ++#define PCI_F0DEVID 48 ++ ++#define SROM_WORDS 64 ++ ++#define SROM_SSID 2 ++ ++#define SROM_WL1LHMAXP 29 ++ ++#define SROM_WL1LPAB0 30 ++#define SROM_WL1LPAB1 31 ++#define SROM_WL1LPAB2 32 ++ ++#define SROM_WL1HPAB0 33 ++#define SROM_WL1HPAB1 34 ++#define SROM_WL1HPAB2 35 ++ ++#define SROM_MACHI_IL0 36 ++#define SROM_MACMID_IL0 37 ++#define SROM_MACLO_IL0 38 ++#define SROM_MACHI_ET1 42 ++#define SROM_MACMID_ET1 43 ++#define SROM_MACLO_ET1 44 ++#define SROM3_MACHI 37 ++#define SROM3_MACMID 38 ++#define SROM3_MACLO 39 ++ ++#define SROM_BXARSSI2G 40 ++#define SROM_BXARSSI5G 41 ++ ++#define SROM_TRI52G 42 ++#define SROM_TRI5GHL 43 ++ ++#define SROM_RXPO52G 45 ++ ++#define SROM_AABREV 46 ++/* Fields in AABREV */ ++#define SROM_BR_MASK 0x00ff ++#define SROM_CC_MASK 0x0f00 ++#define SROM_CC_SHIFT 8 ++#define SROM_AA0_MASK 0x3000 ++#define SROM_AA0_SHIFT 12 ++#define SROM_AA1_MASK 0xc000 ++#define SROM_AA1_SHIFT 14 ++ ++#define SROM_WL0PAB0 47 ++#define SROM_WL0PAB1 48 ++#define SROM_WL0PAB2 49 ++ ++#define SROM_LEDBH10 50 ++#define SROM_LEDBH32 51 ++ ++#define SROM_WL10MAXP 52 ++ ++#define SROM_WL1PAB0 53 ++#define SROM_WL1PAB1 54 ++#define SROM_WL1PAB2 55 ++ ++#define SROM_ITT 56 ++ ++#define SROM_BFL 57 ++#define SROM_BFL2 28 ++#define SROM3_BFL2 61 ++ ++#define SROM_AG10 58 ++ ++#define SROM_CCODE 59 ++ ++#define SROM_OPO 60 ++ ++#define SROM3_LEDDC 62 ++ ++#define SROM_CRCREV 63 ++ ++/* SROM Rev 4: Reallocate the software part of the srom to accommodate ++ * MIMO features. It assumes up to two PCIE functions and 440 bytes ++ * of usable srom i.e. the usable storage in chips with OTP that ++ * implements hardware redundancy. ++ */ ++ ++#define SROM4_WORDS 220 ++ ++#define SROM4_SIGN 32 ++#define SROM4_SIGNATURE 0x5372 ++ ++#define SROM4_BREV 33 ++ ++#define SROM4_BFL0 34 ++#define SROM4_BFL1 35 ++#define SROM4_BFL2 36 ++#define SROM4_BFL3 37 ++#define SROM5_BFL0 37 ++#define SROM5_BFL1 38 ++#define SROM5_BFL2 39 ++#define SROM5_BFL3 40 ++ ++#define SROM4_MACHI 38 ++#define SROM4_MACMID 39 ++#define SROM4_MACLO 40 ++#define SROM5_MACHI 41 ++#define SROM5_MACMID 42 ++#define SROM5_MACLO 43 ++ ++#define SROM4_CCODE 41 ++#define SROM4_REGREV 42 ++#define SROM5_CCODE 34 ++#define SROM5_REGREV 35 ++ ++#define SROM4_LEDBH10 43 ++#define SROM4_LEDBH32 44 ++#define SROM5_LEDBH10 59 ++#define SROM5_LEDBH32 60 ++ ++#define SROM4_LEDDC 45 ++#define SROM5_LEDDC 45 ++ ++#define SROM4_AA 46 ++ ++#define SROM4_AG10 47 ++#define SROM4_AG32 48 ++ ++#define SROM4_TXPID2G 49 ++#define SROM4_TXPID5G 51 ++#define SROM4_TXPID5GL 53 ++#define SROM4_TXPID5GH 55 ++ ++#define SROM4_TXRXC 61 ++#define SROM4_TXCHAIN_MASK 0x000f ++#define SROM4_TXCHAIN_SHIFT 0 ++#define SROM4_RXCHAIN_MASK 0x00f0 ++#define SROM4_RXCHAIN_SHIFT 4 ++#define SROM4_SWITCH_MASK 0xff00 ++#define SROM4_SWITCH_SHIFT 8 ++ ++/* Per-path fields */ ++#define MAX_PATH_SROM 4 ++#define SROM4_PATH0 64 ++#define SROM4_PATH1 87 ++#define SROM4_PATH2 110 ++#define SROM4_PATH3 133 ++ ++#define SROM4_2G_ITT_MAXP 0 ++#define SROM4_2G_PA 1 ++#define SROM4_5G_ITT_MAXP 5 ++#define SROM4_5GLH_MAXP 6 ++#define SROM4_5G_PA 7 ++#define SROM4_5GL_PA 11 ++#define SROM4_5GH_PA 15 ++ ++/* All the miriad power offsets */ ++#define SROM4_2G_CCKPO 156 ++#define SROM4_2G_OFDMPO 157 ++#define SROM4_5G_OFDMPO 159 ++#define SROM4_5GL_OFDMPO 161 ++#define SROM4_5GH_OFDMPO 163 ++#define SROM4_2G_MCSPO 165 ++#define SROM4_5G_MCSPO 173 ++#define SROM4_5GL_MCSPO 181 ++#define SROM4_5GH_MCSPO 189 ++#define SROM4_CDDPO 197 ++#define SROM4_STBCPO 198 ++#define SROM4_BW40PO 199 ++#define SROM4_BWDUPPO 200 ++ ++#define SROM4_CRCREV 219 ++ ++/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6. ++ * This is acombined srom for both MIMO and SISO boards, usable in ++ * the .130 4Kilobit OTP with hardware redundancy. ++ */ ++#define SROM8_BREV 65 ++ ++#define SROM8_BFL0 66 ++#define SROM8_BFL1 67 ++#define SROM8_BFL2 68 ++#define SROM8_BFL3 69 ++ ++#define SROM8_MACHI 70 ++#define SROM8_MACMID 71 ++#define SROM8_MACLO 72 ++ ++#define SROM8_CCODE 73 ++#define SROM8_REGREV 74 ++ ++#define SROM8_LEDBH10 75 ++#define SROM8_LEDBH32 76 ++ ++#define SROM8_LEDDC 77 ++ ++#define SROM8_AA 78 ++ ++#define SROM8_AG10 79 ++#define SROM8_AG32 80 ++ ++#define SROM8_TXRXC 81 ++ ++#define SROM8_BXARSSI2G 82 ++#define SROM8_BXARSSI5G 83 ++#define SROM8_TRI52G 84 ++#define SROM8_TRI5GHL 85 ++#define SROM8_RXPO52G 86 ++ ++#define SROM8_FEM2G 87 ++#define SROM8_FEM5G 88 ++#define SROM8_FEM_ANTSWLUT_MASK 0xf800 ++#define SROM8_FEM_ANTSWLUT_SHIFT 11 ++#define SROM8_FEM_TR_ISO_MASK 0x0700 ++#define SROM8_FEM_TR_ISO_SHIFT 8 ++#define SROM8_FEM_PDET_RANGE_MASK 0x00f8 ++#define SROM8_FEM_PDET_RANGE_SHIFT 3 ++#define SROM8_FEM_EXTPA_GAIN_MASK 0x0006 ++#define SROM8_FEM_EXTPA_GAIN_SHIFT 1 ++#define SROM8_FEM_TSSIPOS_MASK 0x0001 ++#define SROM8_FEM_TSSIPOS_SHIFT 0 ++ ++#define SROM8_THERMAL 89 ++ ++/* Temp sense related entries */ ++#define SROM8_MPWR_RAWTS 90 ++#define SROM8_TS_SLP_OPT_CORRX 91 ++/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, ++ * IQSWP: IQ CAL swap disable */ ++#define SROM8_FOC_HWIQ_IQSWP 92 ++ ++/* Temperature delta for PHY calibration */ ++#define SROM8_PHYCAL_TEMPDELTA 93 ++ ++/* Per-path offsets & fields */ ++#define SROM8_PATH0 96 ++#define SROM8_PATH1 112 ++#define SROM8_PATH2 128 ++#define SROM8_PATH3 144 ++ ++#define SROM8_2G_ITT_MAXP 0 ++#define SROM8_2G_PA 1 ++#define SROM8_5G_ITT_MAXP 4 ++#define SROM8_5GLH_MAXP 5 ++#define SROM8_5G_PA 6 ++#define SROM8_5GL_PA 9 ++#define SROM8_5GH_PA 12 ++ ++/* All the miriad power offsets */ ++#define SROM8_2G_CCKPO 160 ++ ++#define SROM8_2G_OFDMPO 161 ++#define SROM8_5G_OFDMPO 163 ++#define SROM8_5GL_OFDMPO 165 ++#define SROM8_5GH_OFDMPO 167 ++ ++#define SROM8_2G_MCSPO 169 ++#define SROM8_5G_MCSPO 177 ++#define SROM8_5GL_MCSPO 185 ++#define SROM8_5GH_MCSPO 193 ++ ++#define SROM8_CDDPO 201 ++#define SROM8_STBCPO 202 ++#define SROM8_BW40PO 203 ++#define SROM8_BWDUPPO 204 ++ ++/* SISO PA parameters are in the path0 spaces */ ++#define SROM8_SISO 96 ++ ++/* Legacy names for SISO PA paramters */ ++#define SROM8_W0_ITTMAXP (SROM8_SISO + SROM8_2G_ITT_MAXP) ++#define SROM8_W0_PAB0 (SROM8_SISO + SROM8_2G_PA) ++#define SROM8_W0_PAB1 (SROM8_SISO + SROM8_2G_PA + 1) ++#define SROM8_W0_PAB2 (SROM8_SISO + SROM8_2G_PA + 2) ++#define SROM8_W1_ITTMAXP (SROM8_SISO + SROM8_5G_ITT_MAXP) ++#define SROM8_W1_MAXP_LCHC (SROM8_SISO + SROM8_5GLH_MAXP) ++#define SROM8_W1_PAB0 (SROM8_SISO + SROM8_5G_PA) ++#define SROM8_W1_PAB1 (SROM8_SISO + SROM8_5G_PA + 1) ++#define SROM8_W1_PAB2 (SROM8_SISO + SROM8_5G_PA + 2) ++#define SROM8_W1_PAB0_LC (SROM8_SISO + SROM8_5GL_PA) ++#define SROM8_W1_PAB1_LC (SROM8_SISO + SROM8_5GL_PA + 1) ++#define SROM8_W1_PAB2_LC (SROM8_SISO + SROM8_5GL_PA + 2) ++#define SROM8_W1_PAB0_HC (SROM8_SISO + SROM8_5GH_PA) ++#define SROM8_W1_PAB1_HC (SROM8_SISO + SROM8_5GH_PA + 1) ++#define SROM8_W1_PAB2_HC (SROM8_SISO + SROM8_5GH_PA + 2) ++ ++/* SROM REV 9 */ ++#define SROM9_2GPO_CCKBW20 160 ++#define SROM9_2GPO_CCKBW20UL 161 ++#define SROM9_2GPO_LOFDMBW20 162 ++#define SROM9_2GPO_LOFDMBW20UL 164 ++ ++#define SROM9_5GLPO_LOFDMBW20 166 ++#define SROM9_5GLPO_LOFDMBW20UL 168 ++#define SROM9_5GMPO_LOFDMBW20 170 ++#define SROM9_5GMPO_LOFDMBW20UL 172 ++#define SROM9_5GHPO_LOFDMBW20 174 ++#define SROM9_5GHPO_LOFDMBW20UL 176 ++ ++#define SROM9_2GPO_MCSBW20 178 ++#define SROM9_2GPO_MCSBW20UL 180 ++#define SROM9_2GPO_MCSBW40 182 ++ ++#define SROM9_5GLPO_MCSBW20 184 ++#define SROM9_5GLPO_MCSBW20UL 186 ++#define SROM9_5GLPO_MCSBW40 188 ++#define SROM9_5GMPO_MCSBW20 190 ++#define SROM9_5GMPO_MCSBW20UL 192 ++#define SROM9_5GMPO_MCSBW40 194 ++#define SROM9_5GHPO_MCSBW20 196 ++#define SROM9_5GHPO_MCSBW20UL 198 ++#define SROM9_5GHPO_MCSBW40 200 ++ ++#define SROM9_PO_MCS32 202 ++#define SROM9_PO_LOFDM40DUP 203 ++ ++/* SROM flags (see sromvar_t) */ ++ ++/* value continues as described by the next entry */ ++#define SRFL_MORE 1 ++#define SRFL_NOFFS 2 /* value bits can't be all one's */ ++#define SRFL_PRHEX 4 /* value is in hexdecimal format */ ++#define SRFL_PRSIGN 8 /* value is in signed decimal format */ ++#define SRFL_CCODE 0x10 /* value is in country code format */ ++#define SRFL_ETHADDR 0x20 /* value is an Ethernet address */ ++#define SRFL_LEDDC 0x40 /* value is an LED duty cycle */ ++/* do not generate a nvram param, entry is for mfgc */ ++#define SRFL_NOVAR 0x80 ++ ++/* Max. nvram variable table size */ ++#define MAXSZ_NVRAM_VARS 4096 ++ ++/* ++ * indicates type of value. ++ */ ++enum brcms_srom_var_type { ++ BRCMS_SROM_STRING, ++ BRCMS_SROM_SNUMBER, ++ BRCMS_SROM_UNUMBER ++}; ++ ++/* ++ * storage type for srom variable. ++ * ++ * var_list: for linked list operations. ++ * varid: identifier of the variable. ++ * var_type: type of variable. ++ * buf: variable value when var_type == BRCMS_SROM_STRING. ++ * uval: unsigned variable value when var_type == BRCMS_SROM_UNUMBER. ++ * sval: signed variable value when var_type == BRCMS_SROM_SNUMBER. ++ */ ++struct brcms_srom_list_head { ++ struct list_head var_list; ++ enum brcms_srom_id varid; ++ enum brcms_srom_var_type var_type; ++ union { ++ char buf[0]; ++ u32 uval; ++ s32 sval; ++ }; ++}; ++ ++struct brcms_sromvar { ++ enum brcms_srom_id varid; ++ u32 revmask; ++ u32 flags; ++ u16 off; ++ u16 mask; ++}; ++ ++struct brcms_varbuf { ++ char *base; /* pointer to buffer base */ ++ char *buf; /* pointer to current position */ ++ unsigned int size; /* current (residual) size in bytes */ ++}; ++ ++/* ++ * Assumptions: ++ * - Ethernet address spans across 3 consecutive words ++ * ++ * Table rules: ++ * - Add multiple entries next to each other if a value spans across multiple ++ * words (even multiple fields in the same word) with each entry except the ++ * last having it's SRFL_MORE bit set. ++ * - Ethernet address entry does not follow above rule and must not have ++ * SRFL_MORE bit set. Its SRFL_ETHADDR bit implies it takes multiple words. ++ * - The last entry's name field must be NULL to indicate the end of the table. ++ * Other entries must have non-NULL name. ++ */ ++static const struct brcms_sromvar pci_sromvars[] = { ++ {BRCMS_SROM_DEVID, 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID, ++ 0xffff}, ++ {BRCMS_SROM_BOARDREV, 0x0000000e, SRFL_PRHEX, SROM_AABREV, ++ SROM_BR_MASK}, ++ {BRCMS_SROM_BOARDREV, 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff}, ++ {BRCMS_SROM_BOARDREV, 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS, 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS, 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM_BFL2, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS, 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM3_BFL2, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS, 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM4_BFL1, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS, 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM5_BFL1, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM8_BFL1, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS2, 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM4_BFL3, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS2, 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM5_BFL3, 0xffff}, ++ {BRCMS_SROM_BOARDFLAGS2, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM8_BFL3, 0xffff}, ++ {BRCMS_SROM_BOARDTYPE, 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff}, ++ {BRCMS_SROM_BOARDNUM, 0x00000006, 0, SROM_MACLO_IL0, 0xffff}, ++ {BRCMS_SROM_BOARDNUM, 0x00000008, 0, SROM3_MACLO, 0xffff}, ++ {BRCMS_SROM_BOARDNUM, 0x00000010, 0, SROM4_MACLO, 0xffff}, ++ {BRCMS_SROM_BOARDNUM, 0x000000e0, 0, SROM5_MACLO, 0xffff}, ++ {BRCMS_SROM_BOARDNUM, 0xffffff00, 0, SROM8_MACLO, 0xffff}, ++ {BRCMS_SROM_CC, 0x00000002, 0, SROM_AABREV, SROM_CC_MASK}, ++ {BRCMS_SROM_REGREV, 0x00000008, 0, SROM_OPO, 0xff00}, ++ {BRCMS_SROM_REGREV, 0x00000010, 0, SROM4_REGREV, 0x00ff}, ++ {BRCMS_SROM_REGREV, 0x000000e0, 0, SROM5_REGREV, 0x00ff}, ++ {BRCMS_SROM_REGREV, 0xffffff00, 0, SROM8_REGREV, 0x00ff}, ++ {BRCMS_SROM_LEDBH0, 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff}, ++ {BRCMS_SROM_LEDBH1, 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00}, ++ {BRCMS_SROM_LEDBH2, 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff}, ++ {BRCMS_SROM_LEDBH3, 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00}, ++ {BRCMS_SROM_LEDBH0, 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff}, ++ {BRCMS_SROM_LEDBH1, 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00}, ++ {BRCMS_SROM_LEDBH2, 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff}, ++ {BRCMS_SROM_LEDBH3, 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00}, ++ {BRCMS_SROM_LEDBH0, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff}, ++ {BRCMS_SROM_LEDBH1, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00}, ++ {BRCMS_SROM_LEDBH2, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff}, ++ {BRCMS_SROM_LEDBH3, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00}, ++ {BRCMS_SROM_LEDBH0, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff}, ++ {BRCMS_SROM_LEDBH1, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00}, ++ {BRCMS_SROM_LEDBH2, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff}, ++ {BRCMS_SROM_LEDBH3, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00}, ++ {BRCMS_SROM_PA0B0, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff}, ++ {BRCMS_SROM_PA0B1, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff}, ++ {BRCMS_SROM_PA0B2, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff}, ++ {BRCMS_SROM_PA0ITSSIT, 0x0000000e, 0, SROM_ITT, 0x00ff}, ++ {BRCMS_SROM_PA0MAXPWR, 0x0000000e, 0, SROM_WL10MAXP, 0x00ff}, ++ {BRCMS_SROM_PA0B0, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff}, ++ {BRCMS_SROM_PA0B1, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff}, ++ {BRCMS_SROM_PA0B2, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff}, ++ {BRCMS_SROM_PA0ITSSIT, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00}, ++ {BRCMS_SROM_PA0MAXPWR, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff}, ++ {BRCMS_SROM_OPO, 0x0000000c, 0, SROM_OPO, 0x00ff}, ++ {BRCMS_SROM_OPO, 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff}, ++ {BRCMS_SROM_AA2G, 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK}, ++ {BRCMS_SROM_AA2G, 0x000000f0, 0, SROM4_AA, 0x00ff}, ++ {BRCMS_SROM_AA2G, 0xffffff00, 0, SROM8_AA, 0x00ff}, ++ {BRCMS_SROM_AA5G, 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK}, ++ {BRCMS_SROM_AA5G, 0x000000f0, 0, SROM4_AA, 0xff00}, ++ {BRCMS_SROM_AA5G, 0xffffff00, 0, SROM8_AA, 0xff00}, ++ {BRCMS_SROM_AG0, 0x0000000e, 0, SROM_AG10, 0x00ff}, ++ {BRCMS_SROM_AG1, 0x0000000e, 0, SROM_AG10, 0xff00}, ++ {BRCMS_SROM_AG0, 0x000000f0, 0, SROM4_AG10, 0x00ff}, ++ {BRCMS_SROM_AG1, 0x000000f0, 0, SROM4_AG10, 0xff00}, ++ {BRCMS_SROM_AG2, 0x000000f0, 0, SROM4_AG32, 0x00ff}, ++ {BRCMS_SROM_AG3, 0x000000f0, 0, SROM4_AG32, 0xff00}, ++ {BRCMS_SROM_AG0, 0xffffff00, 0, SROM8_AG10, 0x00ff}, ++ {BRCMS_SROM_AG1, 0xffffff00, 0, SROM8_AG10, 0xff00}, ++ {BRCMS_SROM_AG2, 0xffffff00, 0, SROM8_AG32, 0x00ff}, ++ {BRCMS_SROM_AG3, 0xffffff00, 0, SROM8_AG32, 0xff00}, ++ {BRCMS_SROM_PA1B0, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff}, ++ {BRCMS_SROM_PA1B1, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff}, ++ {BRCMS_SROM_PA1B2, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff}, ++ {BRCMS_SROM_PA1LOB0, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff}, ++ {BRCMS_SROM_PA1LOB1, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff}, ++ {BRCMS_SROM_PA1LOB2, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff}, ++ {BRCMS_SROM_PA1HIB0, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff}, ++ {BRCMS_SROM_PA1HIB1, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff}, ++ {BRCMS_SROM_PA1HIB2, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff}, ++ {BRCMS_SROM_PA1ITSSIT, 0x0000000e, 0, SROM_ITT, 0xff00}, ++ {BRCMS_SROM_PA1MAXPWR, 0x0000000e, 0, SROM_WL10MAXP, 0xff00}, ++ {BRCMS_SROM_PA1LOMAXPWR, 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00}, ++ {BRCMS_SROM_PA1HIMAXPWR, 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff}, ++ {BRCMS_SROM_PA1B0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff}, ++ {BRCMS_SROM_PA1B1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff}, ++ {BRCMS_SROM_PA1B2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff}, ++ {BRCMS_SROM_PA1LOB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff}, ++ {BRCMS_SROM_PA1LOB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff}, ++ {BRCMS_SROM_PA1LOB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff}, ++ {BRCMS_SROM_PA1HIB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff}, ++ {BRCMS_SROM_PA1HIB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff}, ++ {BRCMS_SROM_PA1HIB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff}, ++ {BRCMS_SROM_PA1ITSSIT, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00}, ++ {BRCMS_SROM_PA1MAXPWR, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff}, ++ {BRCMS_SROM_PA1LOMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00}, ++ {BRCMS_SROM_PA1HIMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff}, ++ {BRCMS_SROM_BXA2G, 0x00000008, 0, SROM_BXARSSI2G, 0x1800}, ++ {BRCMS_SROM_RSSISAV2G, 0x00000008, 0, SROM_BXARSSI2G, 0x0700}, ++ {BRCMS_SROM_RSSISMC2G, 0x00000008, 0, SROM_BXARSSI2G, 0x00f0}, ++ {BRCMS_SROM_RSSISMF2G, 0x00000008, 0, SROM_BXARSSI2G, 0x000f}, ++ {BRCMS_SROM_BXA2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800}, ++ {BRCMS_SROM_RSSISAV2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700}, ++ {BRCMS_SROM_RSSISMC2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0}, ++ {BRCMS_SROM_RSSISMF2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f}, ++ {BRCMS_SROM_BXA5G, 0x00000008, 0, SROM_BXARSSI5G, 0x1800}, ++ {BRCMS_SROM_RSSISAV5G, 0x00000008, 0, SROM_BXARSSI5G, 0x0700}, ++ {BRCMS_SROM_RSSISMC5G, 0x00000008, 0, SROM_BXARSSI5G, 0x00f0}, ++ {BRCMS_SROM_RSSISMF5G, 0x00000008, 0, SROM_BXARSSI5G, 0x000f}, ++ {BRCMS_SROM_BXA5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800}, ++ {BRCMS_SROM_RSSISAV5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700}, ++ {BRCMS_SROM_RSSISMC5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0}, ++ {BRCMS_SROM_RSSISMF5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f}, ++ {BRCMS_SROM_TRI2G, 0x00000008, 0, SROM_TRI52G, 0x00ff}, ++ {BRCMS_SROM_TRI5G, 0x00000008, 0, SROM_TRI52G, 0xff00}, ++ {BRCMS_SROM_TRI5GL, 0x00000008, 0, SROM_TRI5GHL, 0x00ff}, ++ {BRCMS_SROM_TRI5GH, 0x00000008, 0, SROM_TRI5GHL, 0xff00}, ++ {BRCMS_SROM_TRI2G, 0xffffff00, 0, SROM8_TRI52G, 0x00ff}, ++ {BRCMS_SROM_TRI5G, 0xffffff00, 0, SROM8_TRI52G, 0xff00}, ++ {BRCMS_SROM_TRI5GL, 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff}, ++ {BRCMS_SROM_TRI5GH, 0xffffff00, 0, SROM8_TRI5GHL, 0xff00}, ++ {BRCMS_SROM_RXPO2G, 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff}, ++ {BRCMS_SROM_RXPO5G, 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00}, ++ {BRCMS_SROM_RXPO2G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff}, ++ {BRCMS_SROM_RXPO5G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00}, ++ {BRCMS_SROM_TXCHAIN, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, ++ SROM4_TXCHAIN_MASK}, ++ {BRCMS_SROM_RXCHAIN, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, ++ SROM4_RXCHAIN_MASK}, ++ {BRCMS_SROM_ANTSWITCH, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, ++ SROM4_SWITCH_MASK}, ++ {BRCMS_SROM_TXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, ++ SROM4_TXCHAIN_MASK}, ++ {BRCMS_SROM_RXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, ++ SROM4_RXCHAIN_MASK}, ++ {BRCMS_SROM_ANTSWITCH, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, ++ SROM4_SWITCH_MASK}, ++ {BRCMS_SROM_TSSIPOS2G, 0xffffff00, 0, SROM8_FEM2G, ++ SROM8_FEM_TSSIPOS_MASK}, ++ {BRCMS_SROM_EXTPAGAIN2G, 0xffffff00, 0, SROM8_FEM2G, ++ SROM8_FEM_EXTPA_GAIN_MASK}, ++ {BRCMS_SROM_PDETRANGE2G, 0xffffff00, 0, SROM8_FEM2G, ++ SROM8_FEM_PDET_RANGE_MASK}, ++ {BRCMS_SROM_TRISO2G, 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK}, ++ {BRCMS_SROM_ANTSWCTL2G, 0xffffff00, 0, SROM8_FEM2G, ++ SROM8_FEM_ANTSWLUT_MASK}, ++ {BRCMS_SROM_TSSIPOS5G, 0xffffff00, 0, SROM8_FEM5G, ++ SROM8_FEM_TSSIPOS_MASK}, ++ {BRCMS_SROM_EXTPAGAIN5G, 0xffffff00, 0, SROM8_FEM5G, ++ SROM8_FEM_EXTPA_GAIN_MASK}, ++ {BRCMS_SROM_PDETRANGE5G, 0xffffff00, 0, SROM8_FEM5G, ++ SROM8_FEM_PDET_RANGE_MASK}, ++ {BRCMS_SROM_TRISO5G, 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK}, ++ {BRCMS_SROM_ANTSWCTL5G, 0xffffff00, 0, SROM8_FEM5G, ++ SROM8_FEM_ANTSWLUT_MASK}, ++ {BRCMS_SROM_TEMPTHRESH, 0xffffff00, 0, SROM8_THERMAL, 0xff00}, ++ {BRCMS_SROM_TEMPOFFSET, 0xffffff00, 0, SROM8_THERMAL, 0x00ff}, ++ {BRCMS_SROM_TXPID2GA0, 0x000000f0, 0, SROM4_TXPID2G, 0x00ff}, ++ {BRCMS_SROM_TXPID2GA1, 0x000000f0, 0, SROM4_TXPID2G, 0xff00}, ++ {BRCMS_SROM_TXPID2GA2, 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff}, ++ {BRCMS_SROM_TXPID2GA3, 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00}, ++ {BRCMS_SROM_TXPID5GA0, 0x000000f0, 0, SROM4_TXPID5G, 0x00ff}, ++ {BRCMS_SROM_TXPID5GA1, 0x000000f0, 0, SROM4_TXPID5G, 0xff00}, ++ {BRCMS_SROM_TXPID5GA2, 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff}, ++ {BRCMS_SROM_TXPID5GA3, 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00}, ++ {BRCMS_SROM_TXPID5GLA0, 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff}, ++ {BRCMS_SROM_TXPID5GLA1, 0x000000f0, 0, SROM4_TXPID5GL, 0xff00}, ++ {BRCMS_SROM_TXPID5GLA2, 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff}, ++ {BRCMS_SROM_TXPID5GLA3, 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00}, ++ {BRCMS_SROM_TXPID5GHA0, 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff}, ++ {BRCMS_SROM_TXPID5GHA1, 0x000000f0, 0, SROM4_TXPID5GH, 0xff00}, ++ {BRCMS_SROM_TXPID5GHA2, 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff}, ++ {BRCMS_SROM_TXPID5GHA3, 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00}, ++ ++ {BRCMS_SROM_CCODE, 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff}, ++ {BRCMS_SROM_CCODE, 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff}, ++ {BRCMS_SROM_CCODE, 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff}, ++ {BRCMS_SROM_CCODE, 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff}, ++ {BRCMS_SROM_MACADDR, 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff}, ++ {BRCMS_SROM_MACADDR, 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff}, ++ {BRCMS_SROM_MACADDR, 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff}, ++ {BRCMS_SROM_MACADDR, 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff}, ++ {BRCMS_SROM_IL0MACADDR, 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, ++ 0xffff}, ++ {BRCMS_SROM_ET1MACADDR, 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, ++ 0xffff}, ++ {BRCMS_SROM_LEDDC, 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC, ++ 0xffff}, ++ {BRCMS_SROM_LEDDC, 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC, ++ 0xffff}, ++ {BRCMS_SROM_LEDDC, 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC, ++ 0xffff}, ++ {BRCMS_SROM_LEDDC, 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC, ++ 0xffff}, ++ {BRCMS_SROM_RAWTEMPSENSE, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, ++ 0x01ff}, ++ {BRCMS_SROM_MEASPOWER, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, ++ 0xfe00}, ++ {BRCMS_SROM_TEMPSENSE_SLOPE, 0xffffff00, SRFL_PRHEX, ++ SROM8_TS_SLP_OPT_CORRX, 0x00ff}, ++ {BRCMS_SROM_TEMPCORRX, 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, ++ 0xfc00}, ++ {BRCMS_SROM_TEMPSENSE_OPTION, 0xffffff00, SRFL_PRHEX, ++ SROM8_TS_SLP_OPT_CORRX, 0x0300}, ++ {BRCMS_SROM_FREQOFFSET_CORR, 0xffffff00, SRFL_PRHEX, ++ SROM8_FOC_HWIQ_IQSWP, 0x000f}, ++ {BRCMS_SROM_IQCAL_SWP_DIS, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, ++ 0x0010}, ++ {BRCMS_SROM_HW_IQCAL_EN, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, ++ 0x0020}, ++ {BRCMS_SROM_PHYCAL_TEMPDELTA, 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA, ++ 0x00ff}, ++ ++ {BRCMS_SROM_CCK2GPO, 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff}, ++ {BRCMS_SROM_CCK2GPO, 0x00000100, 0, SROM8_2G_CCKPO, 0xffff}, ++ {BRCMS_SROM_OFDM2GPO, 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM4_2G_OFDMPO + 1, 0xffff}, ++ {BRCMS_SROM_OFDM5GPO, 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM4_5G_OFDMPO + 1, 0xffff}, ++ {BRCMS_SROM_OFDM5GLPO, 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff}, ++ {BRCMS_SROM_OFDM5GHPO, 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff}, ++ {BRCMS_SROM_OFDM2GPO, 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM8_2G_OFDMPO + 1, 0xffff}, ++ {BRCMS_SROM_OFDM5GPO, 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM8_5G_OFDMPO + 1, 0xffff}, ++ {BRCMS_SROM_OFDM5GLPO, 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff}, ++ {BRCMS_SROM_OFDM5GHPO, 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS2GPO0, 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff}, ++ {BRCMS_SROM_MCS2GPO1, 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS2GPO2, 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff}, ++ {BRCMS_SROM_MCS2GPO3, 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff}, ++ {BRCMS_SROM_MCS2GPO4, 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff}, ++ {BRCMS_SROM_MCS2GPO5, 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff}, ++ {BRCMS_SROM_MCS2GPO6, 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff}, ++ {BRCMS_SROM_MCS2GPO7, 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff}, ++ {BRCMS_SROM_MCS5GPO0, 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff}, ++ {BRCMS_SROM_MCS5GPO1, 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS5GPO2, 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff}, ++ {BRCMS_SROM_MCS5GPO3, 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff}, ++ {BRCMS_SROM_MCS5GPO4, 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff}, ++ {BRCMS_SROM_MCS5GPO5, 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff}, ++ {BRCMS_SROM_MCS5GPO6, 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff}, ++ {BRCMS_SROM_MCS5GPO7, 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO0, 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO1, 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO2, 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO3, 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO4, 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO5, 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO6, 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO7, 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO0, 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO1, 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO2, 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO3, 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO4, 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO5, 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO6, 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO7, 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff}, ++ {BRCMS_SROM_MCS2GPO0, 0x00000100, 0, SROM8_2G_MCSPO, 0xffff}, ++ {BRCMS_SROM_MCS2GPO1, 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS2GPO2, 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff}, ++ {BRCMS_SROM_MCS2GPO3, 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff}, ++ {BRCMS_SROM_MCS2GPO4, 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff}, ++ {BRCMS_SROM_MCS2GPO5, 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff}, ++ {BRCMS_SROM_MCS2GPO6, 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff}, ++ {BRCMS_SROM_MCS2GPO7, 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff}, ++ {BRCMS_SROM_MCS5GPO0, 0x00000100, 0, SROM8_5G_MCSPO, 0xffff}, ++ {BRCMS_SROM_MCS5GPO1, 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS5GPO2, 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff}, ++ {BRCMS_SROM_MCS5GPO3, 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff}, ++ {BRCMS_SROM_MCS5GPO4, 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff}, ++ {BRCMS_SROM_MCS5GPO5, 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff}, ++ {BRCMS_SROM_MCS5GPO6, 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff}, ++ {BRCMS_SROM_MCS5GPO7, 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO0, 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO1, 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO2, 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO3, 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO4, 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO5, 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO6, 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff}, ++ {BRCMS_SROM_MCS5GLPO7, 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO0, 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO1, 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO2, 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO3, 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO4, 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO5, 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO6, 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff}, ++ {BRCMS_SROM_MCS5GHPO7, 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff}, ++ {BRCMS_SROM_CDDPO, 0x000000f0, 0, SROM4_CDDPO, 0xffff}, ++ {BRCMS_SROM_STBCPO, 0x000000f0, 0, SROM4_STBCPO, 0xffff}, ++ {BRCMS_SROM_BW40PO, 0x000000f0, 0, SROM4_BW40PO, 0xffff}, ++ {BRCMS_SROM_BWDUPPO, 0x000000f0, 0, SROM4_BWDUPPO, 0xffff}, ++ {BRCMS_SROM_CDDPO, 0x00000100, 0, SROM8_CDDPO, 0xffff}, ++ {BRCMS_SROM_STBCPO, 0x00000100, 0, SROM8_STBCPO, 0xffff}, ++ {BRCMS_SROM_BW40PO, 0x00000100, 0, SROM8_BW40PO, 0xffff}, ++ {BRCMS_SROM_BWDUPPO, 0x00000100, 0, SROM8_BWDUPPO, 0xffff}, ++ ++ /* power per rate from sromrev 9 */ ++ {BRCMS_SROM_CCKBW202GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff}, ++ {BRCMS_SROM_CCKBW20UL2GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff}, ++ {BRCMS_SROM_LEGOFDMBW202GPO, 0xfffffe00, SRFL_MORE, ++ SROM9_2GPO_LOFDMBW20, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff}, ++ {BRCMS_SROM_LEGOFDMBW20UL2GPO, 0xfffffe00, SRFL_MORE, ++ SROM9_2GPO_LOFDMBW20UL, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff}, ++ {BRCMS_SROM_LEGOFDMBW205GLPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GLPO_LOFDMBW20, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff}, ++ {BRCMS_SROM_LEGOFDMBW20UL5GLPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GLPO_LOFDMBW20UL, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff}, ++ {BRCMS_SROM_LEGOFDMBW205GMPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GMPO_LOFDMBW20, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff}, ++ {BRCMS_SROM_LEGOFDMBW20UL5GMPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GMPO_LOFDMBW20UL, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff}, ++ {BRCMS_SROM_LEGOFDMBW205GHPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GHPO_LOFDMBW20, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff}, ++ {BRCMS_SROM_LEGOFDMBW20UL5GHPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GHPO_LOFDMBW20UL, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW202GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW20UL2GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW402GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW205GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW20UL5GLPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GLPO_MCSBW20UL, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW405GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW205GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW20UL5GMPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GMPO_MCSBW20UL, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW405GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW205GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW20UL5GHPO, 0xfffffe00, SRFL_MORE, ++ SROM9_5GHPO_MCSBW20UL, 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff}, ++ {BRCMS_SROM_MCSBW405GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40, ++ 0xffff}, ++ {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff}, ++ {BRCMS_SROM_MCS32PO, 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff}, ++ {BRCMS_SROM_LEGOFDM40DUPPO, 0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff}, ++ ++ {BRCMS_SROM_NULL, 0, 0, 0, 0} ++}; ++ ++static const struct brcms_sromvar perpath_pci_sromvars[] = { ++ {BRCMS_SROM_MAXP2GA0, 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff}, ++ {BRCMS_SROM_ITT2GA0, 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00}, ++ {BRCMS_SROM_ITT5GA0, 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00}, ++ {BRCMS_SROM_PA2GW0A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff}, ++ {BRCMS_SROM_PA2GW1A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff}, ++ {BRCMS_SROM_PA2GW2A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff}, ++ {BRCMS_SROM_PA2GW3A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff}, ++ {BRCMS_SROM_MAXP5GA0, 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff}, ++ {BRCMS_SROM_MAXP5GHA0, 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff}, ++ {BRCMS_SROM_MAXP5GLA0, 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00}, ++ {BRCMS_SROM_PA5GW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff}, ++ {BRCMS_SROM_PA5GW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff}, ++ {BRCMS_SROM_PA5GW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff}, ++ {BRCMS_SROM_PA5GW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff}, ++ {BRCMS_SROM_PA5GLW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff}, ++ {BRCMS_SROM_PA5GLW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1, ++ 0xffff}, ++ {BRCMS_SROM_PA5GLW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2, ++ 0xffff}, ++ {BRCMS_SROM_PA5GLW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3, ++ 0xffff}, ++ {BRCMS_SROM_PA5GHW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff}, ++ {BRCMS_SROM_PA5GHW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1, ++ 0xffff}, ++ {BRCMS_SROM_PA5GHW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2, ++ 0xffff}, ++ {BRCMS_SROM_PA5GHW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3, ++ 0xffff}, ++ {BRCMS_SROM_MAXP2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff}, ++ {BRCMS_SROM_ITT2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00}, ++ {BRCMS_SROM_ITT5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00}, ++ {BRCMS_SROM_PA2GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff}, ++ {BRCMS_SROM_PA2GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff}, ++ {BRCMS_SROM_PA2GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff}, ++ {BRCMS_SROM_MAXP5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff}, ++ {BRCMS_SROM_MAXP5GHA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff}, ++ {BRCMS_SROM_MAXP5GLA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00}, ++ {BRCMS_SROM_PA5GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff}, ++ {BRCMS_SROM_PA5GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff}, ++ {BRCMS_SROM_PA5GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff}, ++ {BRCMS_SROM_PA5GLW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff}, ++ {BRCMS_SROM_PA5GLW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1, ++ 0xffff}, ++ {BRCMS_SROM_PA5GLW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2, ++ 0xffff}, ++ {BRCMS_SROM_PA5GHW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff}, ++ {BRCMS_SROM_PA5GHW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1, ++ 0xffff}, ++ {BRCMS_SROM_PA5GHW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2, ++ 0xffff}, ++ {BRCMS_SROM_NULL, 0, 0, 0, 0} ++}; ++ ++/* crc table has the same contents for every device instance, so it can be ++ * shared between devices. */ ++static u8 brcms_srom_crc8_table[CRC8_TABLE_SIZE]; ++ ++static u16 __iomem * ++srom_window_address(struct si_pub *sih, u8 __iomem *curmap) ++{ ++ if (sih->ccrev < 32) ++ return (u16 __iomem *)(curmap + PCI_BAR0_SPROM_OFFSET); ++ if (sih->cccaps & CC_CAP_SROM) ++ return (u16 __iomem *) ++ (curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP); ++ ++ return NULL; ++} ++ ++/* Parse SROM and create name=value pairs. 'srom' points to ++ * the SROM word array. 'off' specifies the offset of the ++ * first word 'srom' points to, which should be either 0 or ++ * SROM3_SWRG_OFF (full SROM or software region). ++ */ ++ ++static uint mask_shift(u16 mask) ++{ ++ uint i; ++ for (i = 0; i < (sizeof(mask) << 3); i++) { ++ if (mask & (1 << i)) ++ return i; ++ } ++ return 0; ++} ++ ++static uint mask_width(u16 mask) ++{ ++ int i; ++ for (i = (sizeof(mask) << 3) - 1; i >= 0; i--) { ++ if (mask & (1 << i)) ++ return (uint) (i - mask_shift(mask) + 1); ++ } ++ return 0; ++} ++ ++static inline void ltoh16_buf(u16 *buf, unsigned int size) ++{ ++ size /= 2; ++ while (size--) ++ *(buf + size) = le16_to_cpu(*(__le16 *)(buf + size)); ++} ++ ++static inline void htol16_buf(u16 *buf, unsigned int size) ++{ ++ size /= 2; ++ while (size--) ++ *(__le16 *)(buf + size) = cpu_to_le16(*(buf + size)); ++} ++ ++/* ++ * convert binary srom data into linked list of srom variable items. ++ */ ++static void ++_initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list) ++{ ++ struct brcms_srom_list_head *entry; ++ enum brcms_srom_id id; ++ u16 w; ++ u32 val; ++ const struct brcms_sromvar *srv; ++ uint width; ++ uint flags; ++ u32 sr = (1 << sromrev); ++ ++ /* first store the srom revision */ ++ entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL); ++ entry->varid = BRCMS_SROM_REV; ++ entry->var_type = BRCMS_SROM_UNUMBER; ++ entry->uval = sromrev; ++ list_add(&entry->var_list, var_list); ++ ++ for (srv = pci_sromvars; srv->varid != BRCMS_SROM_NULL; srv++) { ++ enum brcms_srom_var_type type; ++ u8 ea[ETH_ALEN]; ++ u8 extra_space = 0; ++ ++ if ((srv->revmask & sr) == 0) ++ continue; ++ ++ flags = srv->flags; ++ id = srv->varid; ++ ++ /* This entry is for mfgc only. Don't generate param for it, */ ++ if (flags & SRFL_NOVAR) ++ continue; ++ ++ if (flags & SRFL_ETHADDR) { ++ /* ++ * stored in string format XX:XX:XX:XX:XX:XX (17 chars) ++ */ ++ ea[0] = (srom[srv->off] >> 8) & 0xff; ++ ea[1] = srom[srv->off] & 0xff; ++ ea[2] = (srom[srv->off + 1] >> 8) & 0xff; ++ ea[3] = srom[srv->off + 1] & 0xff; ++ ea[4] = (srom[srv->off + 2] >> 8) & 0xff; ++ ea[5] = srom[srv->off + 2] & 0xff; ++ /* 17 characters + string terminator - union size */ ++ extra_space = 18 - sizeof(s32); ++ type = BRCMS_SROM_STRING; ++ } else { ++ w = srom[srv->off]; ++ val = (w & srv->mask) >> mask_shift(srv->mask); ++ width = mask_width(srv->mask); ++ ++ while (srv->flags & SRFL_MORE) { ++ srv++; ++ if (srv->off == 0) ++ continue; ++ ++ w = srom[srv->off]; ++ val += ++ ((w & srv->mask) >> mask_shift(srv-> ++ mask)) << ++ width; ++ width += mask_width(srv->mask); ++ } ++ ++ if ((flags & SRFL_NOFFS) ++ && ((int)val == (1 << width) - 1)) ++ continue; ++ ++ if (flags & SRFL_CCODE) { ++ type = BRCMS_SROM_STRING; ++ } else if (flags & SRFL_LEDDC) { ++ /* LED Powersave duty cycle has to be scaled: ++ *(oncount >> 24) (offcount >> 8) ++ */ ++ u32 w32 = /* oncount */ ++ (((val >> 8) & 0xff) << 24) | ++ /* offcount */ ++ (((val & 0xff)) << 8); ++ type = BRCMS_SROM_UNUMBER; ++ val = w32; ++ } else if ((flags & SRFL_PRSIGN) ++ && (val & (1 << (width - 1)))) { ++ type = BRCMS_SROM_SNUMBER; ++ val |= ~0 << width; ++ } else ++ type = BRCMS_SROM_UNUMBER; ++ } ++ ++ entry = kzalloc(sizeof(struct brcms_srom_list_head) + ++ extra_space, GFP_KERNEL); ++ entry->varid = id; ++ entry->var_type = type; ++ if (flags & SRFL_ETHADDR) { ++ snprintf(entry->buf, 18, "%pM", ea); ++ } else if (flags & SRFL_CCODE) { ++ if (val == 0) ++ entry->buf[0] = '\0'; ++ else ++ snprintf(entry->buf, 3, "%c%c", ++ (val >> 8), (val & 0xff)); ++ } else { ++ entry->uval = val; ++ } ++ ++ list_add(&entry->var_list, var_list); ++ } ++ ++ if (sromrev >= 4) { ++ /* Do per-path variables */ ++ uint p, pb, psz; ++ ++ if (sromrev >= 8) { ++ pb = SROM8_PATH0; ++ psz = SROM8_PATH1 - SROM8_PATH0; ++ } else { ++ pb = SROM4_PATH0; ++ psz = SROM4_PATH1 - SROM4_PATH0; ++ } ++ ++ for (p = 0; p < MAX_PATH_SROM; p++) { ++ for (srv = perpath_pci_sromvars; ++ srv->varid != BRCMS_SROM_NULL; srv++) { ++ if ((srv->revmask & sr) == 0) ++ continue; ++ ++ if (srv->flags & SRFL_NOVAR) ++ continue; ++ ++ w = srom[pb + srv->off]; ++ val = (w & srv->mask) >> mask_shift(srv->mask); ++ width = mask_width(srv->mask); ++ ++ /* Cheating: no per-path var is more than ++ * 1 word */ ++ if ((srv->flags & SRFL_NOFFS) ++ && ((int)val == (1 << width) - 1)) ++ continue; ++ ++ entry = ++ kzalloc(sizeof(struct brcms_srom_list_head), ++ GFP_KERNEL); ++ entry->varid = srv->varid+p; ++ entry->var_type = BRCMS_SROM_UNUMBER; ++ entry->uval = val; ++ list_add(&entry->var_list, var_list); ++ } ++ pb += psz; ++ } ++ } ++} ++ ++/* ++ * Read in and validate sprom. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++sprom_read_pci(struct si_pub *sih, u16 __iomem *sprom, uint wordoff, ++ u16 *buf, uint nwords, bool check_crc) ++{ ++ int err = 0; ++ uint i; ++ ++ /* read the sprom */ ++ for (i = 0; i < nwords; i++) ++ buf[i] = R_REG(&sprom[wordoff + i]); ++ ++ if (check_crc) { ++ ++ if (buf[0] == 0xffff) ++ /* ++ * The hardware thinks that an srom that starts with ++ * 0xffff is blank, regardless of the rest of the ++ * content, so declare it bad. ++ */ ++ return -ENODATA; ++ ++ /* fixup the endianness so crc8 will pass */ ++ htol16_buf(buf, nwords * 2); ++ if (crc8(brcms_srom_crc8_table, (u8 *) buf, nwords * 2, ++ CRC8_INIT_VALUE) != ++ CRC8_GOOD_VALUE(brcms_srom_crc8_table)) ++ /* DBG only pci always read srom4 first, then srom8/9 */ ++ err = -EIO; ++ ++ /* now correct the endianness of the byte array */ ++ ltoh16_buf(buf, nwords * 2); ++ } ++ return err; ++} ++ ++static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz) ++{ ++ u8 *otp; ++ uint sz = OTP_SZ_MAX / 2; /* size in words */ ++ int err = 0; ++ ++ otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC); ++ if (otp == NULL) ++ return -ENOMEM; ++ ++ err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz); ++ ++ memcpy(buf, otp, bufsz); ++ ++ kfree(otp); ++ ++ /* Check CRC */ ++ if (buf[0] == 0xffff) ++ /* The hardware thinks that an srom that starts with 0xffff ++ * is blank, regardless of the rest of the content, so declare ++ * it bad. ++ */ ++ return -ENODATA; ++ ++ /* fixup the endianness so crc8 will pass */ ++ htol16_buf(buf, bufsz); ++ if (crc8(brcms_srom_crc8_table, (u8 *) buf, SROM4_WORDS * 2, ++ CRC8_INIT_VALUE) != CRC8_GOOD_VALUE(brcms_srom_crc8_table)) ++ err = -EIO; ++ ++ /* now correct the endianness of the byte array */ ++ ltoh16_buf(buf, bufsz); ++ ++ return err; ++} ++ ++/* ++ * Initialize nonvolatile variable table from sprom. ++ * Return 0 on success, nonzero on error. ++ */ ++static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap) ++{ ++ u16 *srom; ++ u16 __iomem *sromwindow; ++ u8 sromrev = 0; ++ u32 sr; ++ int err = 0; ++ ++ /* ++ * Apply CRC over SROM content regardless SROM is present or not. ++ */ ++ srom = kmalloc(SROM_MAX, GFP_ATOMIC); ++ if (!srom) ++ return -ENOMEM; ++ ++ sromwindow = srom_window_address(sih, curmap); ++ ++ crc8_populate_lsb(brcms_srom_crc8_table, SROM_CRC8_POLY); ++ if (ai_is_sprom_available(sih)) { ++ err = sprom_read_pci(sih, sromwindow, 0, srom, SROM_WORDS, ++ true); ++ ++ if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) || ++ (((sih->buscoretype == PCIE_CORE_ID) ++ && (sih->buscorerev >= 6)) ++ || ((sih->buscoretype == PCI_CORE_ID) ++ && (sih->buscorerev >= 0xe)))) { ++ /* sromrev >= 4, read more */ ++ err = sprom_read_pci(sih, sromwindow, 0, srom, ++ SROM4_WORDS, true); ++ sromrev = srom[SROM4_CRCREV] & 0xff; ++ } else if (err == 0) { ++ /* srom is good and is rev < 4 */ ++ /* top word of sprom contains version and crc8 */ ++ sromrev = srom[SROM_CRCREV] & 0xff; ++ /* bcm4401 sroms misprogrammed */ ++ if (sromrev == 0x10) ++ sromrev = 1; ++ } ++ } else { ++ /* Use OTP if SPROM not available */ ++ err = otp_read_pci(sih, srom, SROM_MAX); ++ if (err == 0) ++ /* OTP only contain SROM rev8/rev9 for now */ ++ sromrev = srom[SROM4_CRCREV] & 0xff; ++ } ++ ++ if (!err) { ++ struct si_info *sii = (struct si_info *)sih; ++ ++ /* Bitmask for the sromrev */ ++ sr = 1 << sromrev; ++ ++ /* ++ * srom version check: Current valid versions: 1, 2, 3, 4, 5, 8, ++ * 9 ++ */ ++ if ((sr & 0x33e) == 0) { ++ err = -EINVAL; ++ goto errout; ++ } ++ ++ INIT_LIST_HEAD(&sii->var_list); ++ ++ /* parse SROM into name=value pairs. */ ++ _initvars_srom_pci(sromrev, srom, &sii->var_list); ++ } ++ ++errout: ++ kfree(srom); ++ return err; ++} ++ ++void srom_free_vars(struct si_pub *sih) ++{ ++ struct si_info *sii; ++ struct brcms_srom_list_head *entry, *next; ++ ++ sii = (struct si_info *)sih; ++ list_for_each_entry_safe(entry, next, &sii->var_list, var_list) { ++ list_del(&entry->var_list); ++ kfree(entry); ++ } ++} ++/* ++ * Initialize local vars from the right source for this platform. ++ * Return 0 on success, nonzero on error. ++ */ ++int srom_var_init(struct si_pub *sih, void __iomem *curmap) ++{ ++ uint len; ++ ++ len = 0; ++ ++ if (curmap != NULL) ++ return initvars_srom_pci(sih, curmap); ++ ++ return -EINVAL; ++} ++ ++/* ++ * Search the name=value vars for a specific one and return its value. ++ * Returns NULL if not found. ++ */ ++char *getvar(struct si_pub *sih, enum brcms_srom_id id) ++{ ++ struct si_info *sii; ++ struct brcms_srom_list_head *entry; ++ ++ sii = (struct si_info *)sih; ++ ++ list_for_each_entry(entry, &sii->var_list, var_list) ++ if (entry->varid == id) ++ return &entry->buf[0]; ++ ++ /* nothing found */ ++ return NULL; ++} ++ ++/* ++ * Search the vars for a specific one and return its value as ++ * an integer. Returns 0 if not found.- ++ */ ++int getintvar(struct si_pub *sih, enum brcms_srom_id id) ++{ ++ struct si_info *sii; ++ struct brcms_srom_list_head *entry; ++ unsigned long res; ++ ++ sii = (struct si_info *)sih; ++ ++ list_for_each_entry(entry, &sii->var_list, var_list) ++ if (entry->varid == id) { ++ if (entry->var_type == BRCMS_SROM_SNUMBER || ++ entry->var_type == BRCMS_SROM_UNUMBER) ++ return (int)entry->sval; ++ else if (!kstrtoul(&entry->buf[0], 0, &res)) ++ return (int)res; ++ } ++ ++ return 0; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.h.orig 2011-11-09 13:46:58.285800133 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/srom.h 2011-11-09 13:47:17.044565616 -0500 +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_SROM_H_ ++#define _BRCM_SROM_H_ ++ ++#include "types.h" ++ ++/* Prototypes */ ++extern int srom_var_init(struct si_pub *sih, void __iomem *curmap); ++extern void srom_free_vars(struct si_pub *sih); ++ ++extern int srom_read(struct si_pub *sih, uint bus, void *curmap, ++ uint byteoff, uint nbytes, u16 *buf, bool check_crc); ++ ++/* parse standard PCMCIA cis, normally used by SB/PCMCIA/SDIO/SPI/OTP ++ * and extract from it into name=value pairs ++ */ ++extern int srom_parsecis(u8 **pcis, uint ciscnt, ++ char **vars, uint *count); ++#endif /* _BRCM_SROM_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.c.orig 2011-11-09 13:46:58.286800121 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.c 2011-11-09 13:47:17.045565604 -0500 +@@ -0,0 +1,436 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++ ++#include "types.h" ++#include "d11.h" ++#include "rate.h" ++#include "phy/phy_hal.h" ++#include "channel.h" ++#include "main.h" ++#include "stf.h" ++ ++#define MIN_SPATIAL_EXPANSION 0 ++#define MAX_SPATIAL_EXPANSION 1 ++ ++#define BRCMS_STF_SS_STBC_RX(wlc) (BRCMS_ISNPHY(wlc->band) && \ ++ NREV_GT(wlc->band->phyrev, 3) && NREV_LE(wlc->band->phyrev, 6)) ++ ++#define NSTS_1 1 ++#define NSTS_2 2 ++#define NSTS_3 3 ++#define NSTS_4 4 ++ ++static const u8 txcore_default[5] = { ++ (0), /* bitmap of the core enabled */ ++ (0x01), /* For Nsts = 1, enable core 1 */ ++ (0x03), /* For Nsts = 2, enable core 1 & 2 */ ++ (0x07), /* For Nsts = 3, enable core 1, 2 & 3 */ ++ (0x0f) /* For Nsts = 4, enable all cores */ ++}; ++ ++static void brcms_c_stf_stbc_rx_ht_update(struct brcms_c_info *wlc, int val) ++{ ++ /* MIMOPHYs rev3-6 cannot receive STBC with only one rx core active */ ++ if (BRCMS_STF_SS_STBC_RX(wlc)) { ++ if ((wlc->stf->rxstreams == 1) && (val != HT_CAP_RX_STBC_NO)) ++ return; ++ } ++ ++ if (wlc->pub->up) { ++ brcms_c_update_beacon(wlc); ++ brcms_c_update_probe_resp(wlc, true); ++ } ++} ++ ++/* ++ * every WLC_TEMPSENSE_PERIOD seconds temperature check to decide whether to ++ * turn on/off txchain. ++ */ ++void brcms_c_tempsense_upd(struct brcms_c_info *wlc) ++{ ++ struct brcms_phy_pub *pi = wlc->band->pi; ++ uint active_chains, txchain; ++ ++ /* Check if the chip is too hot. Disable one Tx chain, if it is */ ++ /* high 4 bits are for Rx chain, low 4 bits are for Tx chain */ ++ active_chains = wlc_phy_stf_chain_active_get(pi); ++ txchain = active_chains & 0xf; ++ ++ if (wlc->stf->txchain == wlc->stf->hw_txchain) { ++ if (txchain && (txchain < wlc->stf->hw_txchain)) ++ /* turn off 1 tx chain */ ++ brcms_c_stf_txchain_set(wlc, txchain, true); ++ } else if (wlc->stf->txchain < wlc->stf->hw_txchain) { ++ if (txchain == wlc->stf->hw_txchain) ++ /* turn back on txchain */ ++ brcms_c_stf_txchain_set(wlc, txchain, true); ++ } ++} ++ ++void ++brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel, ++ u16 chanspec) ++{ ++ struct tx_power power; ++ u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id; ++ ++ /* Clear previous settings */ ++ *ss_algo_channel = 0; ++ ++ if (!wlc->pub->up) { ++ *ss_algo_channel = (u16) -1; ++ return; ++ } ++ ++ wlc_phy_txpower_get_current(wlc->band->pi, &power, ++ CHSPEC_CHANNEL(chanspec)); ++ ++ siso_mcs_id = (CHSPEC_IS40(chanspec)) ? ++ WL_TX_POWER_MCS40_SISO_FIRST : WL_TX_POWER_MCS20_SISO_FIRST; ++ cdd_mcs_id = (CHSPEC_IS40(chanspec)) ? ++ WL_TX_POWER_MCS40_CDD_FIRST : WL_TX_POWER_MCS20_CDD_FIRST; ++ stbc_mcs_id = (CHSPEC_IS40(chanspec)) ? ++ WL_TX_POWER_MCS40_STBC_FIRST : WL_TX_POWER_MCS20_STBC_FIRST; ++ ++ /* criteria to choose stf mode */ ++ ++ /* ++ * the "+3dbm (12 0.25db units)" is to account for the fact that with ++ * CDD, tx occurs on both chains ++ */ ++ if (power.target[siso_mcs_id] > (power.target[cdd_mcs_id] + 12)) ++ setbit(ss_algo_channel, PHY_TXC1_MODE_SISO); ++ else ++ setbit(ss_algo_channel, PHY_TXC1_MODE_CDD); ++ ++ /* ++ * STBC is ORed into to algo channel as STBC requires per-packet SCB ++ * capability check so cannot be default mode of operation. One of ++ * SISO, CDD have to be set ++ */ ++ if (power.target[siso_mcs_id] <= (power.target[stbc_mcs_id] + 12)) ++ setbit(ss_algo_channel, PHY_TXC1_MODE_STBC); ++} ++ ++static bool brcms_c_stf_stbc_tx_set(struct brcms_c_info *wlc, s32 int_val) ++{ ++ if ((int_val != AUTO) && (int_val != OFF) && (int_val != ON)) ++ return false; ++ ++ if ((int_val == ON) && (wlc->stf->txstreams == 1)) ++ return false; ++ ++ wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = (s8) int_val; ++ wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = (s8) int_val; ++ ++ return true; ++} ++ ++bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val) ++{ ++ if ((int_val != HT_CAP_RX_STBC_NO) ++ && (int_val != HT_CAP_RX_STBC_ONE_STREAM)) ++ return false; ++ ++ if (BRCMS_STF_SS_STBC_RX(wlc)) { ++ if ((int_val != HT_CAP_RX_STBC_NO) ++ && (wlc->stf->rxstreams == 1)) ++ return false; ++ } ++ ++ brcms_c_stf_stbc_rx_ht_update(wlc, int_val); ++ return true; ++} ++ ++static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts, ++ u8 core_mask) ++{ ++ BCMMSG(wlc->wiphy, "wl%d: Nsts %d core_mask %x\n", ++ wlc->pub->unit, Nsts, core_mask); ++ ++ if (hweight8(core_mask) > wlc->stf->txstreams) ++ core_mask = 0; ++ ++ if ((hweight8(core_mask) == wlc->stf->txstreams) && ++ ((core_mask & ~wlc->stf->txchain) ++ || !(core_mask & wlc->stf->txchain))) ++ core_mask = wlc->stf->txchain; ++ ++ wlc->stf->txcore[Nsts] = core_mask; ++ /* Nsts = 1..4, txcore index = 1..4 */ ++ if (Nsts == 1) { ++ /* Needs to update beacon and ucode generated response ++ * frames when 1 stream core map changed ++ */ ++ wlc->stf->phytxant = core_mask << PHY_TXC_ANT_SHIFT; ++ brcms_b_txant_set(wlc->hw, wlc->stf->phytxant); ++ if (wlc->clk) { ++ brcms_c_suspend_mac_and_wait(wlc); ++ brcms_c_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec); ++ brcms_c_enable_mac(wlc); ++ } ++ } ++ ++ return 0; ++} ++ ++static int brcms_c_stf_spatial_policy_set(struct brcms_c_info *wlc, int val) ++{ ++ int i; ++ u8 core_mask = 0; ++ ++ BCMMSG(wlc->wiphy, "wl%d: val %x\n", wlc->pub->unit, val); ++ ++ wlc->stf->spatial_policy = (s8) val; ++ for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) { ++ core_mask = (val == MAX_SPATIAL_EXPANSION) ? ++ wlc->stf->txchain : txcore_default[i]; ++ brcms_c_stf_txcore_set(wlc, (u8) i, core_mask); ++ } ++ return 0; ++} ++ ++/* ++ * Centralized txant update function. call it whenever wlc->stf->txant and/or ++ * wlc->stf->txchain change. ++ * ++ * Antennas are controlled by ucode indirectly, which drives PHY or GPIO to ++ * achieve various tx/rx antenna selection schemes ++ * ++ * legacy phy, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 ++ * means auto(last rx). ++ * for NREV<3, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 ++ * means last rx and do tx-antenna selection for SISO transmissions ++ * for NREV=3, bit 6 and bit _8_ means antenna 0 and 1 respectively, bit6+bit7 ++ * means last rx and do tx-antenna selection for SISO transmissions ++ * for NREV>=7, bit 6 and bit 7 mean antenna 0 and 1 respectively, nit6+bit7 ++ * means both cores active ++*/ ++static void _brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc) ++{ ++ s8 txant; ++ ++ txant = (s8) wlc->stf->txant; ++ if (BRCMS_PHY_11N_CAP(wlc->band)) { ++ if (txant == ANT_TX_FORCE_0) { ++ wlc->stf->phytxant = PHY_TXC_ANT_0; ++ } else if (txant == ANT_TX_FORCE_1) { ++ wlc->stf->phytxant = PHY_TXC_ANT_1; ++ ++ if (BRCMS_ISNPHY(wlc->band) && ++ NREV_GE(wlc->band->phyrev, 3) ++ && NREV_LT(wlc->band->phyrev, 7)) ++ wlc->stf->phytxant = PHY_TXC_ANT_2; ++ } else { ++ if (BRCMS_ISLCNPHY(wlc->band) || ++ BRCMS_ISSSLPNPHY(wlc->band)) ++ wlc->stf->phytxant = PHY_TXC_LCNPHY_ANT_LAST; ++ else { ++ /* catch out of sync wlc->stf->txcore */ ++ WARN_ON(wlc->stf->txchain <= 0); ++ wlc->stf->phytxant = ++ wlc->stf->txchain << PHY_TXC_ANT_SHIFT; ++ } ++ } ++ } else { ++ if (txant == ANT_TX_FORCE_0) ++ wlc->stf->phytxant = PHY_TXC_OLD_ANT_0; ++ else if (txant == ANT_TX_FORCE_1) ++ wlc->stf->phytxant = PHY_TXC_OLD_ANT_1; ++ else ++ wlc->stf->phytxant = PHY_TXC_OLD_ANT_LAST; ++ } ++ ++ brcms_b_txant_set(wlc->hw, wlc->stf->phytxant); ++} ++ ++int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force) ++{ ++ u8 txchain = (u8) int_val; ++ u8 txstreams; ++ uint i; ++ ++ if (wlc->stf->txchain == txchain) ++ return 0; ++ ++ if ((txchain & ~wlc->stf->hw_txchain) ++ || !(txchain & wlc->stf->hw_txchain)) ++ return -EINVAL; ++ ++ /* ++ * if nrate override is configured to be non-SISO STF mode, reject ++ * reducing txchain to 1 ++ */ ++ txstreams = (u8) hweight8(txchain); ++ if (txstreams > MAX_STREAMS_SUPPORTED) ++ return -EINVAL; ++ ++ wlc->stf->txchain = txchain; ++ wlc->stf->txstreams = txstreams; ++ brcms_c_stf_stbc_tx_set(wlc, wlc->band->band_stf_stbc_tx); ++ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]); ++ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]); ++ wlc->stf->txant = ++ (wlc->stf->txstreams == 1) ? ANT_TX_FORCE_0 : ANT_TX_DEF; ++ _brcms_c_stf_phy_txant_upd(wlc); ++ ++ wlc_phy_stf_chain_set(wlc->band->pi, wlc->stf->txchain, ++ wlc->stf->rxchain); ++ ++ for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) ++ brcms_c_stf_txcore_set(wlc, (u8) i, txcore_default[i]); ++ ++ return 0; ++} ++ ++/* ++ * update wlc->stf->ss_opmode which represents the operational stf_ss mode ++ * we're using ++ */ ++int brcms_c_stf_ss_update(struct brcms_c_info *wlc, struct brcms_band *band) ++{ ++ int ret_code = 0; ++ u8 prev_stf_ss; ++ u8 upd_stf_ss; ++ ++ prev_stf_ss = wlc->stf->ss_opmode; ++ ++ /* ++ * NOTE: opmode can only be SISO or CDD as STBC is decided on a ++ * per-packet basis ++ */ ++ if (BRCMS_STBC_CAP_PHY(wlc) && ++ wlc->stf->ss_algosel_auto ++ && (wlc->stf->ss_algo_channel != (u16) -1)) { ++ upd_stf_ss = (wlc->stf->txstreams == 1 || ++ isset(&wlc->stf->ss_algo_channel, ++ PHY_TXC1_MODE_SISO)) ? ++ PHY_TXC1_MODE_SISO : PHY_TXC1_MODE_CDD; ++ } else { ++ if (wlc->band != band) ++ return ret_code; ++ upd_stf_ss = (wlc->stf->txstreams == 1) ? ++ PHY_TXC1_MODE_SISO : band->band_stf_ss_mode; ++ } ++ if (prev_stf_ss != upd_stf_ss) { ++ wlc->stf->ss_opmode = upd_stf_ss; ++ brcms_b_band_stf_ss_set(wlc->hw, upd_stf_ss); ++ } ++ ++ return ret_code; ++} ++ ++int brcms_c_stf_attach(struct brcms_c_info *wlc) ++{ ++ wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_SISO; ++ wlc->bandstate[BAND_5G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_CDD; ++ ++ if (BRCMS_ISNPHY(wlc->band) && ++ (wlc_phy_txpower_hw_ctrl_get(wlc->band->pi) != PHY_TPC_HW_ON)) ++ wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode = ++ PHY_TXC1_MODE_CDD; ++ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]); ++ brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]); ++ ++ brcms_c_stf_stbc_rx_ht_update(wlc, HT_CAP_RX_STBC_NO); ++ wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = OFF; ++ wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = OFF; ++ ++ if (BRCMS_STBC_CAP_PHY(wlc)) { ++ wlc->stf->ss_algosel_auto = true; ++ /* Init the default value */ ++ wlc->stf->ss_algo_channel = (u16) -1; ++ } ++ return 0; ++} ++ ++void brcms_c_stf_detach(struct brcms_c_info *wlc) ++{ ++} ++ ++void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc) ++{ ++ _brcms_c_stf_phy_txant_upd(wlc); ++} ++ ++void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc) ++{ ++ /* get available rx/tx chains */ ++ wlc->stf->hw_txchain = (u8) getintvar(wlc->hw->sih, BRCMS_SROM_TXCHAIN); ++ wlc->stf->hw_rxchain = (u8) getintvar(wlc->hw->sih, BRCMS_SROM_RXCHAIN); ++ ++ /* these parameter are intended to be used for all PHY types */ ++ if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) { ++ if (BRCMS_ISNPHY(wlc->band)) ++ wlc->stf->hw_txchain = TXCHAIN_DEF_NPHY; ++ else ++ wlc->stf->hw_txchain = TXCHAIN_DEF; ++ } ++ ++ wlc->stf->txchain = wlc->stf->hw_txchain; ++ wlc->stf->txstreams = (u8) hweight8(wlc->stf->hw_txchain); ++ ++ if (wlc->stf->hw_rxchain == 0 || wlc->stf->hw_rxchain == 0xf) { ++ if (BRCMS_ISNPHY(wlc->band)) ++ wlc->stf->hw_rxchain = RXCHAIN_DEF_NPHY; ++ else ++ wlc->stf->hw_rxchain = RXCHAIN_DEF; ++ } ++ ++ wlc->stf->rxchain = wlc->stf->hw_rxchain; ++ wlc->stf->rxstreams = (u8) hweight8(wlc->stf->hw_rxchain); ++ ++ /* initialize the txcore table */ ++ memcpy(wlc->stf->txcore, txcore_default, sizeof(wlc->stf->txcore)); ++ ++ /* default spatial_policy */ ++ wlc->stf->spatial_policy = MIN_SPATIAL_EXPANSION; ++ brcms_c_stf_spatial_policy_set(wlc, MIN_SPATIAL_EXPANSION); ++} ++ ++static u16 _brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, ++ u32 rspec) ++{ ++ u16 phytxant = wlc->stf->phytxant; ++ ++ if (rspec_stf(rspec) != PHY_TXC1_MODE_SISO) ++ phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT; ++ else if (wlc->stf->txant == ANT_TX_DEF) ++ phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT; ++ phytxant &= PHY_TXC_ANT_MASK; ++ return phytxant; ++} ++ ++u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, u32 rspec) ++{ ++ return _brcms_c_stf_phytxchain_sel(wlc, rspec); ++} ++ ++u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, u32 rspec) ++{ ++ u16 phytxant = wlc->stf->phytxant; ++ u16 mask = PHY_TXC_ANT_MASK; ++ ++ /* for non-siso rates or default setting, use the available chains */ ++ if (BRCMS_ISNPHY(wlc->band)) { ++ phytxant = _brcms_c_stf_phytxchain_sel(wlc, rspec); ++ mask = PHY_TXC_HTANT_MASK; ++ } ++ phytxant |= phytxant & mask; ++ return phytxant; ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.h.orig 2011-11-09 13:46:58.286800121 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/stf.h 2011-11-09 13:47:17.045565604 -0500 +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_STF_H_ ++#define _BRCM_STF_H_ ++ ++#include "types.h" ++ ++extern int brcms_c_stf_attach(struct brcms_c_info *wlc); ++extern void brcms_c_stf_detach(struct brcms_c_info *wlc); ++ ++extern void brcms_c_tempsense_upd(struct brcms_c_info *wlc); ++extern void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, ++ u16 *ss_algo_channel, ++ u16 chanspec); ++extern int brcms_c_stf_ss_update(struct brcms_c_info *wlc, ++ struct brcms_band *band); ++extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc); ++extern int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, ++ bool force); ++extern bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val); ++extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc); ++extern void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc); ++extern u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, ++ u32 rspec); ++extern u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, ++ u32 rspec); ++ ++#endif /* _BRCM_STF_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/types.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/types.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/types.h.orig 2011-11-09 13:46:58.286800121 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/types.h 2011-11-09 13:47:17.045565604 -0500 +@@ -0,0 +1,352 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_TYPES_H_ ++#define _BRCM_TYPES_H_ ++ ++#include ++#include ++ ++#define WL_CHAN_FREQ_RANGE_2G 0 ++#define WL_CHAN_FREQ_RANGE_5GL 1 ++#define WL_CHAN_FREQ_RANGE_5GM 2 ++#define WL_CHAN_FREQ_RANGE_5GH 3 ++ ++/* boardflags */ ++ ++/* Board has gpio 9 controlling the PA */ ++#define BFL_PACTRL 0x00000002 ++/* Not ok to power down the chip pll and oscillator */ ++#define BFL_NOPLLDOWN 0x00000020 ++/* Board supports the Front End Module */ ++#define BFL_FEM 0x00000800 ++/* Board has an external LNA in 2.4GHz band */ ++#define BFL_EXTLNA 0x00001000 ++/* Board has no PA */ ++#define BFL_NOPA 0x00010000 ++/* Power topology uses BUCKBOOST */ ++#define BFL_BUCKBOOST 0x00200000 ++/* Board has FEM and switch to share antenna w/ BT */ ++#define BFL_FEM_BT 0x00400000 ++/* Power topology doesn't use CBUCK */ ++#define BFL_NOCBUCK 0x00800000 ++/* Power topology uses PALDO */ ++#define BFL_PALDO 0x02000000 ++/* Board has an external LNA in 5GHz band */ ++#define BFL_EXTLNA_5GHz 0x10000000 ++ ++/* boardflags2 */ ++ ++/* Board has an external rxbb regulator */ ++#define BFL2_RXBB_INT_REG_DIS 0x00000001 ++/* Flag to implement alternative A-band PLL settings */ ++#define BFL2_APLL_WAR 0x00000002 ++/* Board permits enabling TX Power Control */ ++#define BFL2_TXPWRCTRL_EN 0x00000004 ++/* Board supports the 2X4 diversity switch */ ++#define BFL2_2X4_DIV 0x00000008 ++/* Board supports 5G band power gain */ ++#define BFL2_5G_PWRGAIN 0x00000010 ++/* Board overrides ASPM and Clkreq settings */ ++#define BFL2_PCIEWAR_OVR 0x00000020 ++#define BFL2_LEGACY 0x00000080 ++/* 4321mcm93 board uses Skyworks FEM */ ++#define BFL2_SKWRKFEM_BRD 0x00000100 ++/* Board has a WAR for clock-harmonic spurs */ ++#define BFL2_SPUR_WAR 0x00000200 ++/* Flag to narrow G-band PLL loop b/w */ ++#define BFL2_GPLL_WAR 0x00000400 ++/* Tx CCK pkts on Ant 0 only */ ++#define BFL2_SINGLEANT_CCK 0x00001000 ++/* WAR to reduce and avoid clock-harmonic spurs in 2G */ ++#define BFL2_2G_SPUR_WAR 0x00002000 ++/* Flag to widen G-band PLL loop b/w */ ++#define BFL2_GPLL_WAR2 0x00010000 ++#define BFL2_IPALVLSHIFT_3P3 0x00020000 ++/* Use internal envelope detector for TX IQCAL */ ++#define BFL2_INTERNDET_TXIQCAL 0x00040000 ++/* Keep the buffered Xtal output from radio "ON". Most drivers will turn it ++ * off without this flag to save power. */ ++#define BFL2_XTALBUFOUTEN 0x00080000 ++ ++/* ++ * board specific GPIO assignment, gpio 0-3 are also customer-configurable ++ * led ++ */ ++ ++/* bit 9 controls the PA on new 4306 boards */ ++#define BOARD_GPIO_PACTRL 0x200 ++#define BOARD_GPIO_12 0x1000 ++#define BOARD_GPIO_13 0x2000 ++ ++/* **** Core type/rev defaults **** */ ++#define D11CONF 0x0fffffb0 /* Supported D11 revs: 4, 5, 7-27 ++ * also need to update wlc.h MAXCOREREV ++ */ ++ ++#define NCONF 0x000001ff /* Supported nphy revs: ++ * 0 4321a0 ++ * 1 4321a1 ++ * 2 4321b0/b1/c0/c1 ++ * 3 4322a0 ++ * 4 4322a1 ++ * 5 4716a0 ++ * 6 43222a0, 43224a0 ++ * 7 43226a0 ++ * 8 5357a0, 43236a0 ++ */ ++ ++#define LCNCONF 0x00000007 /* Supported lcnphy revs: ++ * 0 4313a0, 4336a0, 4330a0 ++ * 1 ++ * 2 4330a0 ++ */ ++ ++#define SSLPNCONF 0x0000000f /* Supported sslpnphy revs: ++ * 0 4329a0/k0 ++ * 1 4329b0/4329C0 ++ * 2 4319a0 ++ * 3 5356a0 ++ */ ++ ++/******************************************************************** ++ * Phy/Core Configuration. Defines macros to to check core phy/rev * ++ * compile-time configuration. Defines default core support. * ++ * ****************************************************************** ++ */ ++ ++/* Basic macros to check a configuration bitmask */ ++ ++#define CONF_HAS(config, val) ((config) & (1 << (val))) ++#define CONF_MSK(config, mask) ((config) & (mask)) ++#define MSK_RANGE(low, hi) ((1 << ((hi)+1)) - (1 << (low))) ++#define CONF_RANGE(config, low, hi) (CONF_MSK(config, MSK_RANGE(low, high))) ++ ++#define CONF_IS(config, val) ((config) == (1 << (val))) ++#define CONF_GE(config, val) ((config) & (0-(1 << (val)))) ++#define CONF_GT(config, val) ((config) & (0-2*(1 << (val)))) ++#define CONF_LT(config, val) ((config) & ((1 << (val))-1)) ++#define CONF_LE(config, val) ((config) & (2*(1 << (val))-1)) ++ ++/* Wrappers for some of the above, specific to config constants */ ++ ++#define NCONF_HAS(val) CONF_HAS(NCONF, val) ++#define NCONF_MSK(mask) CONF_MSK(NCONF, mask) ++#define NCONF_IS(val) CONF_IS(NCONF, val) ++#define NCONF_GE(val) CONF_GE(NCONF, val) ++#define NCONF_GT(val) CONF_GT(NCONF, val) ++#define NCONF_LT(val) CONF_LT(NCONF, val) ++#define NCONF_LE(val) CONF_LE(NCONF, val) ++ ++#define LCNCONF_HAS(val) CONF_HAS(LCNCONF, val) ++#define LCNCONF_MSK(mask) CONF_MSK(LCNCONF, mask) ++#define LCNCONF_IS(val) CONF_IS(LCNCONF, val) ++#define LCNCONF_GE(val) CONF_GE(LCNCONF, val) ++#define LCNCONF_GT(val) CONF_GT(LCNCONF, val) ++#define LCNCONF_LT(val) CONF_LT(LCNCONF, val) ++#define LCNCONF_LE(val) CONF_LE(LCNCONF, val) ++ ++#define D11CONF_HAS(val) CONF_HAS(D11CONF, val) ++#define D11CONF_MSK(mask) CONF_MSK(D11CONF, mask) ++#define D11CONF_IS(val) CONF_IS(D11CONF, val) ++#define D11CONF_GE(val) CONF_GE(D11CONF, val) ++#define D11CONF_GT(val) CONF_GT(D11CONF, val) ++#define D11CONF_LT(val) CONF_LT(D11CONF, val) ++#define D11CONF_LE(val) CONF_LE(D11CONF, val) ++ ++#define PHYCONF_HAS(val) CONF_HAS(PHYTYPE, val) ++#define PHYCONF_IS(val) CONF_IS(PHYTYPE, val) ++ ++#define NREV_IS(var, val) \ ++ (NCONF_HAS(val) && (NCONF_IS(val) || ((var) == (val)))) ++ ++#define NREV_GE(var, val) \ ++ (NCONF_GE(val) && (!NCONF_LT(val) || ((var) >= (val)))) ++ ++#define NREV_GT(var, val) \ ++ (NCONF_GT(val) && (!NCONF_LE(val) || ((var) > (val)))) ++ ++#define NREV_LT(var, val) \ ++ (NCONF_LT(val) && (!NCONF_GE(val) || ((var) < (val)))) ++ ++#define NREV_LE(var, val) \ ++ (NCONF_LE(val) && (!NCONF_GT(val) || ((var) <= (val)))) ++ ++#define LCNREV_IS(var, val) \ ++ (LCNCONF_HAS(val) && (LCNCONF_IS(val) || ((var) == (val)))) ++ ++#define LCNREV_GE(var, val) \ ++ (LCNCONF_GE(val) && (!LCNCONF_LT(val) || ((var) >= (val)))) ++ ++#define LCNREV_GT(var, val) \ ++ (LCNCONF_GT(val) && (!LCNCONF_LE(val) || ((var) > (val)))) ++ ++#define LCNREV_LT(var, val) \ ++ (LCNCONF_LT(val) && (!LCNCONF_GE(val) || ((var) < (val)))) ++ ++#define LCNREV_LE(var, val) \ ++ (LCNCONF_LE(val) && (!LCNCONF_GT(val) || ((var) <= (val)))) ++ ++#define D11REV_IS(var, val) \ ++ (D11CONF_HAS(val) && (D11CONF_IS(val) || ((var) == (val)))) ++ ++#define D11REV_GE(var, val) \ ++ (D11CONF_GE(val) && (!D11CONF_LT(val) || ((var) >= (val)))) ++ ++#define D11REV_GT(var, val) \ ++ (D11CONF_GT(val) && (!D11CONF_LE(val) || ((var) > (val)))) ++ ++#define D11REV_LT(var, val) \ ++ (D11CONF_LT(val) && (!D11CONF_GE(val) || ((var) < (val)))) ++ ++#define D11REV_LE(var, val) \ ++ (D11CONF_LE(val) && (!D11CONF_GT(val) || ((var) <= (val)))) ++ ++#define PHYTYPE_IS(var, val)\ ++ (PHYCONF_HAS(val) && (PHYCONF_IS(val) || ((var) == (val)))) ++ ++/* Set up PHYTYPE automatically: (depends on PHY_TYPE_X, from d11.h) */ ++ ++#define _PHYCONF_N (1 << PHY_TYPE_N) ++#define _PHYCONF_LCN (1 << PHY_TYPE_LCN) ++#define _PHYCONF_SSLPN (1 << PHY_TYPE_SSN) ++ ++#define PHYTYPE (_PHYCONF_N | _PHYCONF_LCN | _PHYCONF_SSLPN) ++ ++/* Utility macro to identify 802.11n (HT) capable PHYs */ ++#define PHYTYPE_11N_CAP(phytype) \ ++ (PHYTYPE_IS(phytype, PHY_TYPE_N) || \ ++ PHYTYPE_IS(phytype, PHY_TYPE_LCN) || \ ++ PHYTYPE_IS(phytype, PHY_TYPE_SSN)) ++ ++/* Last but not least: shorter wlc-specific var checks */ ++#define BRCMS_ISNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_N) ++#define BRCMS_ISLCNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_LCN) ++#define BRCMS_ISSSLPNPHY(band) PHYTYPE_IS((band)->phytype, PHY_TYPE_SSN) ++ ++#define BRCMS_PHY_11N_CAP(band) PHYTYPE_11N_CAP((band)->phytype) ++ ++/********************************************************************** ++ * ------------- End of Core phy/rev configuration. ----------------- * ++ * ******************************************************************** ++ */ ++ ++#define BCMMSG(dev, fmt, args...) \ ++do { \ ++ if (brcm_msg_level & LOG_TRACE_VAL) \ ++ wiphy_err(dev, "%s: " fmt, __func__, ##args); \ ++} while (0) ++ ++/* ++ * Register access macros. ++ * ++ * These macro's take a pointer to the address to read as one of their ++ * arguments. The macro itself deduces the size of the IO transaction (u8, u16 ++ * or u32). Advantage of this approach in combination with using a struct to ++ * define the registers in a register block, is that access size and access ++ * location are defined in only one spot. This reduces the risk of the ++ * programmer trying to use an unsupported transaction size on a register. ++ * ++ */ ++ ++#define R_REG(r) \ ++ ({ \ ++ __typeof(*(r)) __osl_v; \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(u8): \ ++ __osl_v = readb((u8 __iomem *)(r)); \ ++ break; \ ++ case sizeof(u16): \ ++ __osl_v = readw((u16 __iomem *)(r)); \ ++ break; \ ++ case sizeof(u32): \ ++ __osl_v = readl((u32 __iomem *)(r)); \ ++ break; \ ++ } \ ++ __osl_v; \ ++ }) ++ ++#define W_REG(r, v) do { \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(u8): \ ++ writeb((u8)((v) & 0xFF), (u8 __iomem *)(r)); \ ++ break; \ ++ case sizeof(u16): \ ++ writew((u16)((v) & 0xFFFF), (u16 __iomem *)(r)); \ ++ break; \ ++ case sizeof(u32): \ ++ writel((u32)(v), (u32 __iomem *)(r)); \ ++ break; \ ++ } \ ++ } while (0) ++ ++#ifdef CONFIG_BCM47XX ++/* ++ * bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder ++ * transactions. As a fix, a read after write is performed on certain places ++ * in the code. Older chips and the newer 5357 family don't require this fix. ++ */ ++#define W_REG_FLUSH(r, v) ({ W_REG((r), (v)); (void)R_REG(r); }) ++#else ++#define W_REG_FLUSH(r, v) W_REG((r), (v)) ++#endif /* CONFIG_BCM47XX */ ++ ++#define AND_REG(r, v) W_REG((r), R_REG(r) & (v)) ++#define OR_REG(r, v) W_REG((r), R_REG(r) | (v)) ++ ++#define SET_REG(r, mask, val) \ ++ W_REG((r), ((R_REG(r) & ~(mask)) | (val))) ++ ++/* multi-bool data type: set of bools, mbool is true if any is set */ ++ ++/* set one bool */ ++#define mboolset(mb, bit) ((mb) |= (bit)) ++/* clear one bool */ ++#define mboolclr(mb, bit) ((mb) &= ~(bit)) ++/* true if one bool is set */ ++#define mboolisset(mb, bit) (((mb) & (bit)) != 0) ++#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val))) ++ ++#define CEIL(x, y) (((x) + ((y)-1)) / (y)) ++ ++/* forward declarations */ ++struct wiphy; ++struct ieee80211_sta; ++struct ieee80211_tx_queue_params; ++struct brcms_info; ++struct brcms_c_info; ++struct brcms_hardware; ++struct brcms_txq_info; ++struct brcms_band; ++struct dma_pub; ++struct si_pub; ++struct tx_status; ++struct d11rxhdr; ++struct txpwr_limits; ++ ++/* iovar structure */ ++struct brcmu_iovar { ++ const char *name; /* name for lookup and display */ ++ u16 varid; /* id for switch */ ++ u16 flags; /* driver-specific flag bits */ ++ u16 type; /* base type of argument */ ++ u16 minlen; /* min length for buffer vars */ ++}; ++ ++/* brcm_msg_level is a bit vector with defs in defs.h */ ++extern u32 brcm_msg_level; ++ ++#endif /* _BRCM_TYPES_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.c.orig 2011-11-09 13:46:58.286800121 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.c 2011-11-09 13:47:17.045565604 -0500 +@@ -0,0 +1,109 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include "types.h" ++#include ++ ++enum { ++ D11UCODE_NAMETAG_START = 0, ++ D11LCN0BSINITVALS24, ++ D11LCN0INITVALS24, ++ D11LCN1BSINITVALS24, ++ D11LCN1INITVALS24, ++ D11LCN2BSINITVALS24, ++ D11LCN2INITVALS24, ++ D11N0ABSINITVALS16, ++ D11N0BSINITVALS16, ++ D11N0INITVALS16, ++ D11UCODE_OVERSIGHT16_MIMO, ++ D11UCODE_OVERSIGHT16_MIMOSZ, ++ D11UCODE_OVERSIGHT24_LCN, ++ D11UCODE_OVERSIGHT24_LCNSZ, ++ D11UCODE_OVERSIGHT_BOMMAJOR, ++ D11UCODE_OVERSIGHT_BOMMINOR ++}; ++ ++int brcms_ucode_data_init(struct brcms_info *wl, struct brcms_ucode *ucode) ++{ ++ int rc; ++ ++ rc = brcms_check_firmwares(wl); ++ ++ rc = rc < 0 ? rc : ++ brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn0bsinitvals24, ++ D11LCN0BSINITVALS24); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn0initvals24, ++ D11LCN0INITVALS24); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn1bsinitvals24, ++ D11LCN1BSINITVALS24); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn1initvals24, ++ D11LCN1INITVALS24); ++ rc = rc < 0 ? rc : ++ brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn2bsinitvals24, ++ D11LCN2BSINITVALS24); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn2initvals24, ++ D11LCN2INITVALS24); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0absinitvals16, ++ D11N0ABSINITVALS16); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0bsinitvals16, ++ D11N0BSINITVALS16); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0initvals16, ++ D11N0INITVALS16); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_16_mimo, ++ D11UCODE_OVERSIGHT16_MIMO); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_uint(wl, &ucode->bcm43xx_16_mimosz, ++ D11UCODE_OVERSIGHT16_MIMOSZ); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_24_lcn, ++ D11UCODE_OVERSIGHT24_LCN); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_uint(wl, &ucode->bcm43xx_24_lcnsz, ++ D11UCODE_OVERSIGHT24_LCNSZ); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_bommajor, ++ D11UCODE_OVERSIGHT_BOMMAJOR); ++ rc = rc < 0 ? ++ rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_bomminor, ++ D11UCODE_OVERSIGHT_BOMMINOR); ++ return rc; ++} ++ ++void brcms_ucode_data_free(struct brcms_ucode *ucode) ++{ ++ brcms_ucode_free_buf((void *)ucode->d11lcn0bsinitvals24); ++ brcms_ucode_free_buf((void *)ucode->d11lcn0initvals24); ++ brcms_ucode_free_buf((void *)ucode->d11lcn1bsinitvals24); ++ brcms_ucode_free_buf((void *)ucode->d11lcn1initvals24); ++ brcms_ucode_free_buf((void *)ucode->d11lcn2bsinitvals24); ++ brcms_ucode_free_buf((void *)ucode->d11lcn2initvals24); ++ brcms_ucode_free_buf((void *)ucode->d11n0absinitvals16); ++ brcms_ucode_free_buf((void *)ucode->d11n0bsinitvals16); ++ brcms_ucode_free_buf((void *)ucode->d11n0initvals16); ++ brcms_ucode_free_buf((void *)ucode->bcm43xx_16_mimo); ++ brcms_ucode_free_buf((void *)ucode->bcm43xx_24_lcn); ++ brcms_ucode_free_buf((void *)ucode->bcm43xx_bommajor); ++ brcms_ucode_free_buf((void *)ucode->bcm43xx_bomminor); ++} +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h.orig 2011-11-09 13:46:58.287800109 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h 2011-11-09 13:47:17.046565592 -0500 +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef _BRCM_UCODE_H_ ++#define _BRCM_UCODE_H_ ++ ++#include "types.h" /* forward structure declarations */ ++ ++#define MIN_FW_SIZE 40000 /* minimum firmware file size in bytes */ ++#define MAX_FW_SIZE 150000 ++ ++#define UCODE_LOADER_API_VER 0 ++ ++struct d11init; ++ ++struct brcms_ucode { ++ struct d11init *d11lcn0bsinitvals24; ++ struct d11init *d11lcn0initvals24; ++ struct d11init *d11lcn1bsinitvals24; ++ struct d11init *d11lcn1initvals24; ++ struct d11init *d11lcn2bsinitvals24; ++ struct d11init *d11lcn2initvals24; ++ struct d11init *d11n0absinitvals16; ++ struct d11init *d11n0bsinitvals16; ++ struct d11init *d11n0initvals16; ++ __le32 *bcm43xx_16_mimo; ++ size_t bcm43xx_16_mimosz; ++ __le32 *bcm43xx_24_lcn; ++ size_t bcm43xx_24_lcnsz; ++ u32 *bcm43xx_bommajor; ++ u32 *bcm43xx_bomminor; ++}; ++ ++extern int ++brcms_ucode_data_init(struct brcms_info *wl, struct brcms_ucode *ucode); ++ ++extern void brcms_ucode_data_free(struct brcms_ucode *ucode); ++ ++extern int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, ++ unsigned int idx); ++extern int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, ++ unsigned int idx); ++extern void brcms_ucode_free_buf(void *); ++extern int brcms_check_firmwares(struct brcms_info *wl); ++ ++#endif /* _BRCM_UCODE_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/Makefile.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/Makefile +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/Makefile.orig 2011-11-09 13:46:58.287800109 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/Makefile 2011-11-09 13:47:17.046565592 -0500 +@@ -0,0 +1,28 @@ ++# ++# Makefile fragment for Broadcom 802.11n Networking Device Driver Utilities ++# ++# Copyright (c) 2011 Broadcom Corporation ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++ccflags-y := \ ++ -Idrivers/net/wireless/brcm80211/brcmutil \ ++ -Idrivers/net/wireless/brcm80211/include ++ ++BRCMUTIL_OFILES := \ ++ utils.o ++ ++MODULEPFX := brcmutil ++ ++obj-$(CONFIG_BRCMUTIL) += $(MODULEPFX).o ++$(MODULEPFX)-objs = $(BRCMUTIL_OFILES) +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/utils.c.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/utils.c +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/utils.c.orig 2011-11-09 13:46:58.287800109 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/brcmutil/utils.c 2011-11-09 13:47:17.046565592 -0500 +@@ -0,0 +1,386 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver utilities."); ++MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards"); ++MODULE_LICENSE("Dual BSD/GPL"); ++ ++struct sk_buff *brcmu_pkt_buf_get_skb(uint len) ++{ ++ struct sk_buff *skb; ++ ++ skb = dev_alloc_skb(len); ++ if (skb) { ++ skb_put(skb, len); ++ skb->priority = 0; ++ } ++ ++ return skb; ++} ++EXPORT_SYMBOL(brcmu_pkt_buf_get_skb); ++ ++/* Free the driver packet. Free the tag if present */ ++void brcmu_pkt_buf_free_skb(struct sk_buff *skb) ++{ ++ struct sk_buff *nskb; ++ int nest = 0; ++ ++ /* perversion: we use skb->next to chain multi-skb packets */ ++ while (skb) { ++ nskb = skb->next; ++ skb->next = NULL; ++ ++ if (skb->destructor) ++ /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if ++ * destructor exists ++ */ ++ dev_kfree_skb_any(skb); ++ else ++ /* can free immediately (even in_irq()) if destructor ++ * does not exist ++ */ ++ dev_kfree_skb(skb); ++ ++ nest++; ++ skb = nskb; ++ } ++} ++EXPORT_SYMBOL(brcmu_pkt_buf_free_skb); ++ ++ ++/* copy a buffer into a pkt buffer chain */ ++uint brcmu_pktfrombuf(struct sk_buff *p, uint offset, int len, ++ unsigned char *buf) ++{ ++ uint n, ret = 0; ++ ++ /* skip 'offset' bytes */ ++ for (; p && offset; p = p->next) { ++ if (offset < (uint) (p->len)) ++ break; ++ offset -= p->len; ++ } ++ ++ if (!p) ++ return 0; ++ ++ /* copy the data */ ++ for (; p && len; p = p->next) { ++ n = min((uint) (p->len) - offset, (uint) len); ++ memcpy(p->data + offset, buf, n); ++ buf += n; ++ len -= n; ++ ret += n; ++ offset = 0; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL(brcmu_pktfrombuf); ++ ++/* return total length of buffer chain */ ++uint brcmu_pkttotlen(struct sk_buff *p) ++{ ++ uint total; ++ ++ total = 0; ++ for (; p; p = p->next) ++ total += p->len; ++ return total; ++} ++EXPORT_SYMBOL(brcmu_pkttotlen); ++ ++/* ++ * osl multiple-precedence packet queue ++ * hi_prec is always >= the number of the highest non-empty precedence ++ */ ++struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec, ++ struct sk_buff *p) ++{ ++ struct pktq_prec *q; ++ ++ if (pktq_full(pq) || pktq_pfull(pq, prec)) ++ return NULL; ++ ++ q = &pq->q[prec]; ++ ++ if (q->head) ++ q->tail->prev = p; ++ else ++ q->head = p; ++ ++ q->tail = p; ++ q->len++; ++ ++ pq->len++; ++ ++ if (pq->hi_prec < prec) ++ pq->hi_prec = (u8) prec; ++ ++ return p; ++} ++EXPORT_SYMBOL(brcmu_pktq_penq); ++ ++struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec, ++ struct sk_buff *p) ++{ ++ struct pktq_prec *q; ++ ++ if (pktq_full(pq) || pktq_pfull(pq, prec)) ++ return NULL; ++ ++ q = &pq->q[prec]; ++ ++ if (q->head == NULL) ++ q->tail = p; ++ ++ p->prev = q->head; ++ q->head = p; ++ q->len++; ++ ++ pq->len++; ++ ++ if (pq->hi_prec < prec) ++ pq->hi_prec = (u8) prec; ++ ++ return p; ++} ++EXPORT_SYMBOL(brcmu_pktq_penq_head); ++ ++struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec) ++{ ++ struct pktq_prec *q; ++ struct sk_buff *p; ++ ++ q = &pq->q[prec]; ++ ++ p = q->head; ++ if (p == NULL) ++ return NULL; ++ ++ q->head = p->prev; ++ if (q->head == NULL) ++ q->tail = NULL; ++ ++ q->len--; ++ ++ pq->len--; ++ ++ p->prev = NULL; ++ ++ return p; ++} ++EXPORT_SYMBOL(brcmu_pktq_pdeq); ++ ++struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec) ++{ ++ struct pktq_prec *q; ++ struct sk_buff *p, *prev; ++ ++ q = &pq->q[prec]; ++ ++ p = q->head; ++ if (p == NULL) ++ return NULL; ++ ++ for (prev = NULL; p != q->tail; p = p->prev) ++ prev = p; ++ ++ if (prev) ++ prev->prev = NULL; ++ else ++ q->head = NULL; ++ ++ q->tail = prev; ++ q->len--; ++ ++ pq->len--; ++ ++ return p; ++} ++EXPORT_SYMBOL(brcmu_pktq_pdeq_tail); ++ ++void ++brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir, ++ bool (*fn)(struct sk_buff *, void *), void *arg) ++{ ++ struct pktq_prec *q; ++ struct sk_buff *p, *prev = NULL; ++ ++ q = &pq->q[prec]; ++ p = q->head; ++ while (p) { ++ if (fn == NULL || (*fn) (p, arg)) { ++ bool head = (p == q->head); ++ if (head) ++ q->head = p->prev; ++ else ++ prev->prev = p->prev; ++ p->prev = NULL; ++ brcmu_pkt_buf_free_skb(p); ++ q->len--; ++ pq->len--; ++ p = (head ? q->head : prev->prev); ++ } else { ++ prev = p; ++ p = p->prev; ++ } ++ } ++ ++ if (q->head == NULL) ++ q->tail = NULL; ++} ++EXPORT_SYMBOL(brcmu_pktq_pflush); ++ ++void brcmu_pktq_flush(struct pktq *pq, bool dir, ++ bool (*fn)(struct sk_buff *, void *), void *arg) ++{ ++ int prec; ++ for (prec = 0; prec < pq->num_prec; prec++) ++ brcmu_pktq_pflush(pq, prec, dir, fn, arg); ++} ++EXPORT_SYMBOL(brcmu_pktq_flush); ++ ++void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len) ++{ ++ int prec; ++ ++ /* pq is variable size; only zero out what's requested */ ++ memset(pq, 0, ++ offsetof(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec)); ++ ++ pq->num_prec = (u16) num_prec; ++ ++ pq->max = (u16) max_len; ++ ++ for (prec = 0; prec < num_prec; prec++) ++ pq->q[prec].max = pq->max; ++} ++EXPORT_SYMBOL(brcmu_pktq_init); ++ ++struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out) ++{ ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ for (prec = 0; prec < pq->hi_prec; prec++) ++ if (pq->q[prec].head) ++ break; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ return pq->q[prec].tail; ++} ++EXPORT_SYMBOL(brcmu_pktq_peek_tail); ++ ++/* Return sum of lengths of a specific set of precedences */ ++int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp) ++{ ++ int prec, len; ++ ++ len = 0; ++ ++ for (prec = 0; prec <= pq->hi_prec; prec++) ++ if (prec_bmp & (1 << prec)) ++ len += pq->q[prec].len; ++ ++ return len; ++} ++EXPORT_SYMBOL(brcmu_pktq_mlen); ++ ++/* Priority dequeue from a specific set of precedences */ ++struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp, ++ int *prec_out) ++{ ++ struct pktq_prec *q; ++ struct sk_buff *p; ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL) ++ if (prec-- == 0) ++ return NULL; ++ ++ q = &pq->q[prec]; ++ ++ p = q->head; ++ if (p == NULL) ++ return NULL; ++ ++ q->head = p->prev; ++ if (q->head == NULL) ++ q->tail = NULL; ++ ++ q->len--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ pq->len--; ++ ++ p->prev = NULL; ++ ++ return p; ++} ++EXPORT_SYMBOL(brcmu_pktq_mdeq); ++ ++#if defined(BCMDBG) ++/* pretty hex print a pkt buffer chain */ ++void brcmu_prpkt(const char *msg, struct sk_buff *p0) ++{ ++ struct sk_buff *p; ++ ++ if (msg && (msg[0] != '\0')) ++ printk(KERN_DEBUG "%s:\n", msg); ++ ++ for (p = p0; p; p = p->next) ++ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, p->data, p->len); ++} ++EXPORT_SYMBOL(brcmu_prpkt); ++#endif /* defined(BCMDBG) */ ++ ++#if defined(BCMDBG) ++/* ++ * print bytes formatted as hex to a string. return the resulting ++ * string length ++ */ ++int brcmu_format_hex(char *str, const void *bytes, int len) ++{ ++ int i; ++ char *p = str; ++ const u8 *src = (const u8 *)bytes; ++ ++ for (i = 0; i < len; i++) { ++ p += snprintf(p, 3, "%02X", *src); ++ src++; ++ } ++ return (int)(p - str); ++} ++EXPORT_SYMBOL(brcmu_format_hex); ++#endif /* defined(BCMDBG) */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h.orig 2011-11-09 13:46:58.287800109 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h 2011-11-09 13:47:17.046565592 -0500 +@@ -0,0 +1,59 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_HW_IDS_H_ ++#define _BRCM_HW_IDS_H_ ++ ++#define BCM4325_D11DUAL_ID 0x431b ++#define BCM4325_D11G_ID 0x431c ++#define BCM4325_D11A_ID 0x431d ++ ++#define BCM4329_D11N2G_ID 0x432f /* 4329 802.11n 2.4G device */ ++#define BCM4329_D11N5G_ID 0x4330 /* 4329 802.11n 5G device */ ++#define BCM4329_D11NDUAL_ID 0x432e ++ ++#define BCM4319_D11N_ID 0x4337 /* 4319 802.11n dualband device */ ++#define BCM4319_D11N2G_ID 0x4338 /* 4319 802.11n 2.4G device */ ++#define BCM4319_D11N5G_ID 0x4339 /* 4319 802.11n 5G device */ ++ ++#define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */ ++#define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db */ ++ ++#define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */ ++ ++#define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */ ++#define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */ ++ ++#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ ++ ++/* Chip IDs */ ++#define BCM4313_CHIP_ID 0x4313 /* 4313 chip id */ ++#define BCM4319_CHIP_ID 0x4319 /* 4319 chip id */ ++ ++#define BCM43224_CHIP_ID 43224 /* 43224 chipcommon chipid */ ++#define BCM43225_CHIP_ID 43225 /* 43225 chipcommon chipid */ ++#define BCM43421_CHIP_ID 43421 /* 43421 chipcommon chipid */ ++#define BCM43235_CHIP_ID 43235 /* 43235 chipcommon chipid */ ++#define BCM43236_CHIP_ID 43236 /* 43236 chipcommon chipid */ ++#define BCM43238_CHIP_ID 43238 /* 43238 chipcommon chipid */ ++#define BCM4329_CHIP_ID 0x4329 /* 4329 chipcommon chipid */ ++#define BCM4325_CHIP_ID 0x4325 /* 4325 chipcommon chipid */ ++#define BCM4331_CHIP_ID 0x4331 /* 4331 chipcommon chipid */ ++#define BCM4336_CHIP_ID 0x4336 /* 4336 chipcommon chipid */ ++#define BCM4330_CHIP_ID 0x4330 /* 4330 chipcommon chipid */ ++#define BCM6362_CHIP_ID 0x6362 /* 6362 chipcommon chipid */ ++ ++#endif /* _BRCM_HW_IDS_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_utils.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_utils.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_utils.h.orig 2011-11-09 13:46:58.288800096 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_utils.h 2011-11-09 13:47:17.047565580 -0500 +@@ -0,0 +1,195 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCMU_UTILS_H_ ++#define _BRCMU_UTILS_H_ ++ ++#include ++ ++/* ++ * Spin at most 'us' microseconds while 'exp' is true. ++ * Caller should explicitly test 'exp' when this completes ++ * and take appropriate error action if 'exp' is still true. ++ */ ++#define SPINWAIT(exp, us) { \ ++ uint countdown = (us) + 9; \ ++ while ((exp) && (countdown >= 10)) {\ ++ udelay(10); \ ++ countdown -= 10; \ ++ } \ ++} ++ ++/* osl multi-precedence packet queue */ ++#define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */ ++#define PKTQ_MAX_PREC 16 /* Maximum precedence levels */ ++ ++#define BCME_STRLEN 64 /* Max string length for BCM errors */ ++ ++/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */ ++#define PKTBUFSZ 2048 ++ ++#ifndef setbit ++#ifndef NBBY /* the BSD family defines NBBY */ ++#define NBBY 8 /* 8 bits per byte */ ++#endif /* #ifndef NBBY */ ++#define setbit(a, i) (((u8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY)) ++#define clrbit(a, i) (((u8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) ++#define isset(a, i) (((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) ++#define isclr(a, i) ((((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) ++#endif /* setbit */ ++ ++#define NBITS(type) (sizeof(type) * 8) ++#define NBITVAL(nbits) (1 << (nbits)) ++#define MAXBITVAL(nbits) ((1 << (nbits)) - 1) ++#define NBITMASK(nbits) MAXBITVAL(nbits) ++#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8) ++ ++/* crc defines */ ++#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */ ++#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */ ++ ++/* 18-bytes of Ethernet address buffer length */ ++#define ETHER_ADDR_STR_LEN 18 ++ ++struct pktq_prec { ++ struct sk_buff *head; /* first packet to dequeue */ ++ struct sk_buff *tail; /* last packet to dequeue */ ++ u16 len; /* number of queued packets */ ++ u16 max; /* maximum number of queued packets */ ++}; ++ ++/* multi-priority pkt queue */ ++struct pktq { ++ u16 num_prec; /* number of precedences in use */ ++ u16 hi_prec; /* rapid dequeue hint (>= highest non-empty prec) */ ++ u16 max; /* total max packets */ ++ u16 len; /* total number of packets */ ++ /* ++ * q array must be last since # of elements can be either ++ * PKTQ_MAX_PREC or 1 ++ */ ++ struct pktq_prec q[PKTQ_MAX_PREC]; ++}; ++ ++/* operations on a specific precedence in packet queue */ ++ ++static inline int pktq_plen(struct pktq *pq, int prec) ++{ ++ return pq->q[prec].len; ++} ++ ++static inline int pktq_pavail(struct pktq *pq, int prec) ++{ ++ return pq->q[prec].max - pq->q[prec].len; ++} ++ ++static inline bool pktq_pfull(struct pktq *pq, int prec) ++{ ++ return pq->q[prec].len >= pq->q[prec].max; ++} ++ ++static inline bool pktq_pempty(struct pktq *pq, int prec) ++{ ++ return pq->q[prec].len == 0; ++} ++ ++static inline struct sk_buff *pktq_ppeek(struct pktq *pq, int prec) ++{ ++ return pq->q[prec].head; ++} ++ ++static inline struct sk_buff *pktq_ppeek_tail(struct pktq *pq, int prec) ++{ ++ return pq->q[prec].tail; ++} ++ ++extern struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec, ++ struct sk_buff *p); ++extern struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec, ++ struct sk_buff *p); ++extern struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec); ++extern struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec); ++ ++/* packet primitives */ ++extern struct sk_buff *brcmu_pkt_buf_get_skb(uint len); ++extern void brcmu_pkt_buf_free_skb(struct sk_buff *skb); ++ ++/* Empty the queue at particular precedence level */ ++/* callback function fn(pkt, arg) returns true if pkt belongs to if */ ++extern void brcmu_pktq_pflush(struct pktq *pq, int prec, ++ bool dir, bool (*fn)(struct sk_buff *, void *), void *arg); ++ ++/* operations on a set of precedences in packet queue */ ++ ++extern int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp); ++extern struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp, ++ int *prec_out); ++ ++/* operations on packet queue as a whole */ ++ ++static inline int pktq_len(struct pktq *pq) ++{ ++ return (int)pq->len; ++} ++ ++static inline int pktq_max(struct pktq *pq) ++{ ++ return (int)pq->max; ++} ++ ++static inline int pktq_avail(struct pktq *pq) ++{ ++ return (int)(pq->max - pq->len); ++} ++ ++static inline bool pktq_full(struct pktq *pq) ++{ ++ return pq->len >= pq->max; ++} ++ ++static inline bool pktq_empty(struct pktq *pq) ++{ ++ return pq->len == 0; ++} ++ ++extern void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len); ++/* prec_out may be NULL if caller is not interested in return value */ ++extern struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out); ++extern void brcmu_pktq_flush(struct pktq *pq, bool dir, ++ bool (*fn)(struct sk_buff *, void *), void *arg); ++ ++/* externs */ ++/* packet */ ++extern uint brcmu_pktfrombuf(struct sk_buff *p, ++ uint offset, int len, unsigned char *buf); ++extern uint brcmu_pkttotlen(struct sk_buff *p); ++ ++/* ip address */ ++struct ipv4_addr; ++ ++#ifdef BCMDBG ++extern void brcmu_prpkt(const char *msg, struct sk_buff *p0); ++#else ++#define brcmu_prpkt(a, b) ++#endif /* BCMDBG */ ++ ++/* externs */ ++/* format/print */ ++#if defined(BCMDBG) ++extern int brcmu_format_hex(char *str, const void *bytes, int len); ++#endif ++ ++#endif /* _BRCMU_UTILS_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_wifi.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_wifi.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_wifi.h.orig 2011-11-09 13:46:58.288800096 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/brcmu_wifi.h 2011-11-09 13:47:17.047565580 -0500 +@@ -0,0 +1,239 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCMU_WIFI_H_ ++#define _BRCMU_WIFI_H_ ++ ++#include /* for ETH_ALEN */ ++#include /* for WLAN_PMKID_LEN */ ++ ++/* ++ * A chanspec (u16) holds the channel number, band, bandwidth and control ++ * sideband ++ */ ++ ++/* channel defines */ ++#define CH_UPPER_SB 0x01 ++#define CH_LOWER_SB 0x02 ++#define CH_EWA_VALID 0x04 ++#define CH_20MHZ_APART 4 ++#define CH_10MHZ_APART 2 ++#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ ++#define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ ++#define BRCM_MAX_2G_CHANNEL CH_MAX_2G_CHANNEL /* legacy define */ ++ ++/* bandstate array indices */ ++#define BAND_2G_INDEX 0 /* wlc->bandstate[x] index */ ++#define BAND_5G_INDEX 1 /* wlc->bandstate[x] index */ ++ ++/* ++ * max # supported channels. The max channel no is 216, this is that + 1 ++ * rounded up to a multiple of NBBY (8). DO NOT MAKE it > 255: channels are ++ * u8's all over ++*/ ++#define MAXCHANNEL 224 ++ ++#define WL_CHANSPEC_CHAN_MASK 0x00ff ++#define WL_CHANSPEC_CHAN_SHIFT 0 ++ ++#define WL_CHANSPEC_CTL_SB_MASK 0x0300 ++#define WL_CHANSPEC_CTL_SB_SHIFT 8 ++#define WL_CHANSPEC_CTL_SB_LOWER 0x0100 ++#define WL_CHANSPEC_CTL_SB_UPPER 0x0200 ++#define WL_CHANSPEC_CTL_SB_NONE 0x0300 ++ ++#define WL_CHANSPEC_BW_MASK 0x0C00 ++#define WL_CHANSPEC_BW_SHIFT 10 ++#define WL_CHANSPEC_BW_10 0x0400 ++#define WL_CHANSPEC_BW_20 0x0800 ++#define WL_CHANSPEC_BW_40 0x0C00 ++ ++#define WL_CHANSPEC_BAND_MASK 0xf000 ++#define WL_CHANSPEC_BAND_SHIFT 12 ++#define WL_CHANSPEC_BAND_5G 0x1000 ++#define WL_CHANSPEC_BAND_2G 0x2000 ++#define INVCHANSPEC 255 ++ ++/* used to calculate the chan_freq = chan_factor * 500Mhz + 5 * chan_number */ ++#define WF_CHAN_FACTOR_2_4_G 4814 /* 2.4 GHz band, 2407 MHz */ ++#define WF_CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */ ++#define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */ ++ ++#define CHSPEC_CHANNEL(chspec) ((u8)((chspec) & WL_CHANSPEC_CHAN_MASK)) ++#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) ++ ++#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) ++#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) ++ ++#define CHSPEC_IS10(chspec) \ ++ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) ++ ++#define CHSPEC_IS20(chspec) \ ++ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) ++ ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) \ ++ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) ++#endif ++ ++#define CHSPEC_IS5G(chspec) \ ++ (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) ++ ++#define CHSPEC_IS2G(chspec) \ ++ (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) ++ ++#define CHSPEC_SB_NONE(chspec) \ ++ (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE) ++ ++#define CHSPEC_SB_UPPER(chspec) \ ++ (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) ++ ++#define CHSPEC_SB_LOWER(chspec) \ ++ (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) ++ ++#define CHSPEC_CTL_CHAN(chspec) \ ++ ((CHSPEC_SB_LOWER(chspec)) ? \ ++ (lower_20_sb(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \ ++ (upper_20_sb(((chspec) & WL_CHANSPEC_CHAN_MASK)))) ++ ++#define CHSPEC2BAND(chspec) (CHSPEC_IS5G(chspec) ? BRCM_BAND_5G : BRCM_BAND_2G) ++ ++#define CHANSPEC_STR_LEN 8 ++ ++static inline int lower_20_sb(int channel) ++{ ++ return channel > CH_10MHZ_APART ? (channel - CH_10MHZ_APART) : 0; ++} ++ ++static inline int upper_20_sb(int channel) ++{ ++ return (channel < (MAXCHANNEL - CH_10MHZ_APART)) ? ++ channel + CH_10MHZ_APART : 0; ++} ++ ++static inline int chspec_bandunit(u16 chspec) ++{ ++ return CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX; ++} ++ ++static inline u16 ch20mhz_chspec(int channel) ++{ ++ u16 rc = channel <= CH_MAX_2G_CHANNEL ? ++ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G; ++ ++ return (u16)((u16)channel | WL_CHANSPEC_BW_20 | ++ WL_CHANSPEC_CTL_SB_NONE | rc); ++} ++ ++static inline int next_20mhz_chan(int channel) ++{ ++ return channel < (MAXCHANNEL - CH_20MHZ_APART) ? ++ channel + CH_20MHZ_APART : 0; ++} ++ ++/* defined rate in 500kbps */ ++#define BRCM_MAXRATE 108 /* in 500kbps units */ ++#define BRCM_RATE_1M 2 /* in 500kbps units */ ++#define BRCM_RATE_2M 4 /* in 500kbps units */ ++#define BRCM_RATE_5M5 11 /* in 500kbps units */ ++#define BRCM_RATE_11M 22 /* in 500kbps units */ ++#define BRCM_RATE_6M 12 /* in 500kbps units */ ++#define BRCM_RATE_9M 18 /* in 500kbps units */ ++#define BRCM_RATE_12M 24 /* in 500kbps units */ ++#define BRCM_RATE_18M 36 /* in 500kbps units */ ++#define BRCM_RATE_24M 48 /* in 500kbps units */ ++#define BRCM_RATE_36M 72 /* in 500kbps units */ ++#define BRCM_RATE_48M 96 /* in 500kbps units */ ++#define BRCM_RATE_54M 108 /* in 500kbps units */ ++ ++#define BRCM_2G_25MHZ_OFFSET 5 /* 2.4GHz band channel offset */ ++ ++#define MCSSET_LEN 16 ++ ++static inline bool ac_bitmap_tst(u8 bitmap, int prec) ++{ ++ return (bitmap & (1 << (prec))) != 0; ++} ++ ++/* Enumerate crypto algorithms */ ++#define CRYPTO_ALGO_OFF 0 ++#define CRYPTO_ALGO_WEP1 1 ++#define CRYPTO_ALGO_TKIP 2 ++#define CRYPTO_ALGO_WEP128 3 ++#define CRYPTO_ALGO_AES_CCM 4 ++#define CRYPTO_ALGO_AES_RESERVED1 5 ++#define CRYPTO_ALGO_AES_RESERVED2 6 ++#define CRYPTO_ALGO_NALG 7 ++ ++/* wireless security bitvec */ ++ ++#define WEP_ENABLED 0x0001 ++#define TKIP_ENABLED 0x0002 ++#define AES_ENABLED 0x0004 ++#define WSEC_SWFLAG 0x0008 ++/* to go into transition mode without setting wep */ ++#define SES_OW_ENABLED 0x0040 ++ ++/* WPA authentication mode bitvec */ ++#define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */ ++#define WPA_AUTH_NONE 0x0001 /* none (IBSS) */ ++#define WPA_AUTH_UNSPECIFIED 0x0002 /* over 802.1x */ ++#define WPA_AUTH_PSK 0x0004 /* Pre-shared key */ ++#define WPA_AUTH_RESERVED1 0x0008 ++#define WPA_AUTH_RESERVED2 0x0010 ++ ++#define WPA2_AUTH_RESERVED1 0x0020 ++#define WPA2_AUTH_UNSPECIFIED 0x0040 /* over 802.1x */ ++#define WPA2_AUTH_PSK 0x0080 /* Pre-shared key */ ++#define WPA2_AUTH_RESERVED3 0x0200 ++#define WPA2_AUTH_RESERVED4 0x0400 ++#define WPA2_AUTH_RESERVED5 0x0800 ++ ++/* pmkid */ ++#define MAXPMKID 16 ++ ++#define DOT11_DEFAULT_RTS_LEN 2347 ++#define DOT11_DEFAULT_FRAG_LEN 2346 ++ ++#define DOT11_ICV_AES_LEN 8 ++#define DOT11_QOS_LEN 2 ++#define DOT11_IV_MAX_LEN 8 ++#define DOT11_A4_HDR_LEN 30 ++ ++#define HT_CAP_RX_STBC_NO 0x0 ++#define HT_CAP_RX_STBC_ONE_STREAM 0x1 ++ ++struct pmkid { ++ u8 BSSID[ETH_ALEN]; ++ u8 PMKID[WLAN_PMKID_LEN]; ++}; ++ ++struct pmkid_list { ++ __le32 npmkid; ++ struct pmkid pmkid[1]; ++}; ++ ++struct pmkid_cand { ++ u8 BSSID[ETH_ALEN]; ++ u8 preauth; ++}; ++ ++struct pmkid_cand_list { ++ u32 npmkid_cand; ++ struct pmkid_cand pmkid_cand[1]; ++}; ++ ++#endif /* _BRCMU_WIFI_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/chipcommon.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/chipcommon.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/chipcommon.h.orig 2011-11-09 13:46:58.288800096 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/chipcommon.h 2011-11-09 13:47:17.047565580 -0500 +@@ -0,0 +1,284 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _SBCHIPC_H ++#define _SBCHIPC_H ++ ++#include "defs.h" /* for PAD macro */ ++ ++struct chipcregs { ++ u32 chipid; /* 0x0 */ ++ u32 capabilities; ++ u32 corecontrol; /* corerev >= 1 */ ++ u32 bist; ++ ++ /* OTP */ ++ u32 otpstatus; /* 0x10, corerev >= 10 */ ++ u32 otpcontrol; ++ u32 otpprog; ++ u32 otplayout; /* corerev >= 23 */ ++ ++ /* Interrupt control */ ++ u32 intstatus; /* 0x20 */ ++ u32 intmask; ++ ++ /* Chip specific regs */ ++ u32 chipcontrol; /* 0x28, rev >= 11 */ ++ u32 chipstatus; /* 0x2c, rev >= 11 */ ++ ++ /* Jtag Master */ ++ u32 jtagcmd; /* 0x30, rev >= 10 */ ++ u32 jtagir; ++ u32 jtagdr; ++ u32 jtagctrl; ++ ++ /* serial flash interface registers */ ++ u32 flashcontrol; /* 0x40 */ ++ u32 flashaddress; ++ u32 flashdata; ++ u32 PAD[1]; ++ ++ /* Silicon backplane configuration broadcast control */ ++ u32 broadcastaddress; /* 0x50 */ ++ u32 broadcastdata; ++ ++ /* gpio - cleared only by power-on-reset */ ++ u32 gpiopullup; /* 0x58, corerev >= 20 */ ++ u32 gpiopulldown; /* 0x5c, corerev >= 20 */ ++ u32 gpioin; /* 0x60 */ ++ u32 gpioout; /* 0x64 */ ++ u32 gpioouten; /* 0x68 */ ++ u32 gpiocontrol; /* 0x6C */ ++ u32 gpiointpolarity; /* 0x70 */ ++ u32 gpiointmask; /* 0x74 */ ++ ++ /* GPIO events corerev >= 11 */ ++ u32 gpioevent; ++ u32 gpioeventintmask; ++ ++ /* Watchdog timer */ ++ u32 watchdog; /* 0x80 */ ++ ++ /* GPIO events corerev >= 11 */ ++ u32 gpioeventintpolarity; ++ ++ /* GPIO based LED powersave registers corerev >= 16 */ ++ u32 gpiotimerval; /* 0x88 */ ++ u32 gpiotimeroutmask; ++ ++ /* clock control */ ++ u32 clockcontrol_n; /* 0x90 */ ++ u32 clockcontrol_sb; /* aka m0 */ ++ u32 clockcontrol_pci; /* aka m1 */ ++ u32 clockcontrol_m2; /* mii/uart/mipsref */ ++ u32 clockcontrol_m3; /* cpu */ ++ u32 clkdiv; /* corerev >= 3 */ ++ u32 gpiodebugsel; /* corerev >= 28 */ ++ u32 capabilities_ext; /* 0xac */ ++ ++ /* pll delay registers (corerev >= 4) */ ++ u32 pll_on_delay; /* 0xb0 */ ++ u32 fref_sel_delay; ++ u32 slow_clk_ctl; /* 5 < corerev < 10 */ ++ u32 PAD; ++ ++ /* Instaclock registers (corerev >= 10) */ ++ u32 system_clk_ctl; /* 0xc0 */ ++ u32 clkstatestretch; ++ u32 PAD[2]; ++ ++ /* Indirect backplane access (corerev >= 22) */ ++ u32 bp_addrlow; /* 0xd0 */ ++ u32 bp_addrhigh; ++ u32 bp_data; ++ u32 PAD; ++ u32 bp_indaccess; ++ u32 PAD[3]; ++ ++ /* More clock dividers (corerev >= 32) */ ++ u32 clkdiv2; ++ u32 PAD[2]; ++ ++ /* In AI chips, pointer to erom */ ++ u32 eromptr; /* 0xfc */ ++ ++ /* ExtBus control registers (corerev >= 3) */ ++ u32 pcmcia_config; /* 0x100 */ ++ u32 pcmcia_memwait; ++ u32 pcmcia_attrwait; ++ u32 pcmcia_iowait; ++ u32 ide_config; ++ u32 ide_memwait; ++ u32 ide_attrwait; ++ u32 ide_iowait; ++ u32 prog_config; ++ u32 prog_waitcount; ++ u32 flash_config; ++ u32 flash_waitcount; ++ u32 SECI_config; /* 0x130 SECI configuration */ ++ u32 PAD[3]; ++ ++ /* Enhanced Coexistence Interface (ECI) registers (corerev >= 21) */ ++ u32 eci_output; /* 0x140 */ ++ u32 eci_control; ++ u32 eci_inputlo; ++ u32 eci_inputmi; ++ u32 eci_inputhi; ++ u32 eci_inputintpolaritylo; ++ u32 eci_inputintpolaritymi; ++ u32 eci_inputintpolarityhi; ++ u32 eci_intmasklo; ++ u32 eci_intmaskmi; ++ u32 eci_intmaskhi; ++ u32 eci_eventlo; ++ u32 eci_eventmi; ++ u32 eci_eventhi; ++ u32 eci_eventmasklo; ++ u32 eci_eventmaskmi; ++ u32 eci_eventmaskhi; ++ u32 PAD[3]; ++ ++ /* SROM interface (corerev >= 32) */ ++ u32 sromcontrol; /* 0x190 */ ++ u32 sromaddress; ++ u32 sromdata; ++ u32 PAD[17]; ++ ++ /* Clock control and hardware workarounds (corerev >= 20) */ ++ u32 clk_ctl_st; /* 0x1e0 */ ++ u32 hw_war; ++ u32 PAD[70]; ++ ++ /* UARTs */ ++ u8 uart0data; /* 0x300 */ ++ u8 uart0imr; ++ u8 uart0fcr; ++ u8 uart0lcr; ++ u8 uart0mcr; ++ u8 uart0lsr; ++ u8 uart0msr; ++ u8 uart0scratch; ++ u8 PAD[248]; /* corerev >= 1 */ ++ ++ u8 uart1data; /* 0x400 */ ++ u8 uart1imr; ++ u8 uart1fcr; ++ u8 uart1lcr; ++ u8 uart1mcr; ++ u8 uart1lsr; ++ u8 uart1msr; ++ u8 uart1scratch; ++ u32 PAD[126]; ++ ++ /* PMU registers (corerev >= 20) */ ++ u32 pmucontrol; /* 0x600 */ ++ u32 pmucapabilities; ++ u32 pmustatus; ++ u32 res_state; ++ u32 res_pending; ++ u32 pmutimer; ++ u32 min_res_mask; ++ u32 max_res_mask; ++ u32 res_table_sel; ++ u32 res_dep_mask; ++ u32 res_updn_timer; ++ u32 res_timer; ++ u32 clkstretch; ++ u32 pmuwatchdog; ++ u32 gpiosel; /* 0x638, rev >= 1 */ ++ u32 gpioenable; /* 0x63c, rev >= 1 */ ++ u32 res_req_timer_sel; ++ u32 res_req_timer; ++ u32 res_req_mask; ++ u32 PAD; ++ u32 chipcontrol_addr; /* 0x650 */ ++ u32 chipcontrol_data; /* 0x654 */ ++ u32 regcontrol_addr; ++ u32 regcontrol_data; ++ u32 pllcontrol_addr; ++ u32 pllcontrol_data; ++ u32 pmustrapopt; /* 0x668, corerev >= 28 */ ++ u32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */ ++ u32 PAD[100]; ++ u16 sromotp[768]; ++}; ++ ++/* chipid */ ++#define CID_ID_MASK 0x0000ffff /* Chip Id mask */ ++#define CID_REV_MASK 0x000f0000 /* Chip Revision mask */ ++#define CID_REV_SHIFT 16 /* Chip Revision shift */ ++#define CID_PKG_MASK 0x00f00000 /* Package Option mask */ ++#define CID_PKG_SHIFT 20 /* Package Option shift */ ++#define CID_CC_MASK 0x0f000000 /* CoreCount (corerev >= 4) */ ++#define CID_CC_SHIFT 24 ++#define CID_TYPE_MASK 0xf0000000 /* Chip Type */ ++#define CID_TYPE_SHIFT 28 ++ ++/* capabilities */ ++#define CC_CAP_UARTS_MASK 0x00000003 /* Number of UARTs */ ++#define CC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */ ++#define CC_CAP_UCLKSEL 0x00000018 /* UARTs clock select */ ++/* UARTs are driven by internal divided clock */ ++#define CC_CAP_UINTCLK 0x00000008 ++#define CC_CAP_UARTGPIO 0x00000020 /* UARTs own GPIOs 15:12 */ ++#define CC_CAP_EXTBUS_MASK 0x000000c0 /* External bus mask */ ++#define CC_CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */ ++#define CC_CAP_EXTBUS_FULL 0x00000040 /* ExtBus: PCMCIA, IDE & Prog */ ++#define CC_CAP_EXTBUS_PROG 0x00000080 /* ExtBus: ProgIf only */ ++#define CC_CAP_FLASH_MASK 0x00000700 /* Type of flash */ ++#define CC_CAP_PLL_MASK 0x00038000 /* Type of PLL */ ++#define CC_CAP_PWR_CTL 0x00040000 /* Power control */ ++#define CC_CAP_OTPSIZE 0x00380000 /* OTP Size (0 = none) */ ++#define CC_CAP_OTPSIZE_SHIFT 19 /* OTP Size shift */ ++#define CC_CAP_OTPSIZE_BASE 5 /* OTP Size base */ ++#define CC_CAP_JTAGP 0x00400000 /* JTAG Master Present */ ++#define CC_CAP_ROM 0x00800000 /* Internal boot rom active */ ++#define CC_CAP_BKPLN64 0x08000000 /* 64-bit backplane */ ++#define CC_CAP_PMU 0x10000000 /* PMU Present, rev >= 20 */ ++#define CC_CAP_SROM 0x40000000 /* Srom Present, rev >= 32 */ ++/* Nand flash present, rev >= 35 */ ++#define CC_CAP_NFLASH 0x80000000 ++ ++#define CC_CAP2_SECI 0x00000001 /* SECI Present, rev >= 36 */ ++/* GSIO (spi/i2c) present, rev >= 37 */ ++#define CC_CAP2_GSIO 0x00000002 ++ ++/* pmucapabilities */ ++#define PCAP_REV_MASK 0x000000ff ++#define PCAP_RC_MASK 0x00001f00 ++#define PCAP_RC_SHIFT 8 ++#define PCAP_TC_MASK 0x0001e000 ++#define PCAP_TC_SHIFT 13 ++#define PCAP_PC_MASK 0x001e0000 ++#define PCAP_PC_SHIFT 17 ++#define PCAP_VC_MASK 0x01e00000 ++#define PCAP_VC_SHIFT 21 ++#define PCAP_CC_MASK 0x1e000000 ++#define PCAP_CC_SHIFT 25 ++#define PCAP5_PC_MASK 0x003e0000 /* PMU corerev >= 5 */ ++#define PCAP5_PC_SHIFT 17 ++#define PCAP5_VC_MASK 0x07c00000 ++#define PCAP5_VC_SHIFT 22 ++#define PCAP5_CC_MASK 0xf8000000 ++#define PCAP5_CC_SHIFT 27 ++ ++/* ++* Maximum delay for the PMU state transition in us. ++* This is an upper bound intended for spinwaits etc. ++*/ ++#define PMU_MAX_TRANSITION_DLY 15000 ++ ++#endif /* _SBCHIPC_H */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/defs.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/defs.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/defs.h.orig 2011-11-09 13:46:58.288800096 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/defs.h 2011-11-09 13:47:17.047565580 -0500 +@@ -0,0 +1,104 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_DEFS_H_ ++#define _BRCM_DEFS_H_ ++ ++#include ++ ++#define SI_BUS 0 ++#define PCI_BUS 1 ++#define PCMCIA_BUS 2 ++#define SDIO_BUS 3 ++#define JTAG_BUS 4 ++#define USB_BUS 5 ++#define SPI_BUS 6 ++ ++#define OFF 0 ++#define ON 1 /* ON = 1 */ ++#define AUTO (-1) /* Auto = -1 */ ++ ++/* ++ * Priority definitions according 802.1D ++ */ ++#define PRIO_8021D_NONE 2 ++#define PRIO_8021D_BK 1 ++#define PRIO_8021D_BE 0 ++#define PRIO_8021D_EE 3 ++#define PRIO_8021D_CL 4 ++#define PRIO_8021D_VI 5 ++#define PRIO_8021D_VO 6 ++#define PRIO_8021D_NC 7 ++ ++#define MAXPRIO 7 ++#define NUMPRIO (MAXPRIO + 1) ++ ++#define WL_NUMRATES 16 /* max # of rates in a rateset */ ++ ++#define BRCM_CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NUL */ ++ ++#define BRCM_SET_CHANNEL 30 ++#define BRCM_SET_SRL 32 ++#define BRCM_SET_LRL 34 ++#define BRCM_SET_BCNPRD 76 ++ ++#define BRCM_GET_CURR_RATESET 114 /* current rateset */ ++#define BRCM_GET_PHYLIST 180 ++ ++/* Bit masks for radio disabled status - returned by WL_GET_RADIO */ ++ ++#define WL_RADIO_SW_DISABLE (1<<0) ++#define WL_RADIO_HW_DISABLE (1<<1) ++#define WL_RADIO_MPC_DISABLE (1<<2) ++/* some countries don't support any channel */ ++#define WL_RADIO_COUNTRY_DISABLE (1<<3) ++ ++/* Override bit for SET_TXPWR. if set, ignore other level limits */ ++#define WL_TXPWR_OVERRIDE (1U<<31) ++ ++/* band types */ ++#define BRCM_BAND_AUTO 0 /* auto-select */ ++#define BRCM_BAND_5G 1 /* 5 Ghz */ ++#define BRCM_BAND_2G 2 /* 2.4 Ghz */ ++#define BRCM_BAND_ALL 3 /* all bands */ ++ ++/* Values for PM */ ++#define PM_OFF 0 ++#define PM_MAX 1 ++ ++/* Message levels */ ++#define LOG_ERROR_VAL 0x00000001 ++#define LOG_TRACE_VAL 0x00000002 ++ ++#define PM_OFF 0 ++#define PM_MAX 1 ++#define PM_FAST 2 ++ ++/* ++ * Sonics Configuration Space Registers. ++ */ ++ ++/* core sbconfig regs are top 256bytes of regs */ ++#define SBCONFIGOFF 0xf00 ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif ++ ++#endif /* _BRCM_DEFS_H_ */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/soc.h.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/soc.h +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/soc.h.orig 2011-11-09 13:46:58.288800096 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/include/soc.h 2011-11-09 13:47:17.048565567 -0500 +@@ -0,0 +1,90 @@ ++/* ++ * Copyright (c) 2010 Broadcom Corporation ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BRCM_SOC_H ++#define _BRCM_SOC_H ++ ++#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */ ++ ++/* core codes */ ++#define NODEV_CORE_ID 0x700 /* Invalid coreid */ ++#define CC_CORE_ID 0x800 /* chipcommon core */ ++#define ILINE20_CORE_ID 0x801 /* iline20 core */ ++#define SRAM_CORE_ID 0x802 /* sram core */ ++#define SDRAM_CORE_ID 0x803 /* sdram core */ ++#define PCI_CORE_ID 0x804 /* pci core */ ++#define MIPS_CORE_ID 0x805 /* mips core */ ++#define ENET_CORE_ID 0x806 /* enet mac core */ ++#define CODEC_CORE_ID 0x807 /* v90 codec core */ ++#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */ ++#define ADSL_CORE_ID 0x809 /* ADSL core */ ++#define ILINE100_CORE_ID 0x80a /* iline100 core */ ++#define IPSEC_CORE_ID 0x80b /* ipsec core */ ++#define UTOPIA_CORE_ID 0x80c /* utopia core */ ++#define PCMCIA_CORE_ID 0x80d /* pcmcia core */ ++#define SOCRAM_CORE_ID 0x80e /* internal memory core */ ++#define MEMC_CORE_ID 0x80f /* memc sdram core */ ++#define OFDM_CORE_ID 0x810 /* OFDM phy core */ ++#define EXTIF_CORE_ID 0x811 /* external interface core */ ++#define D11_CORE_ID 0x812 /* 802.11 MAC core */ ++#define APHY_CORE_ID 0x813 /* 802.11a phy core */ ++#define BPHY_CORE_ID 0x814 /* 802.11b phy core */ ++#define GPHY_CORE_ID 0x815 /* 802.11g phy core */ ++#define MIPS33_CORE_ID 0x816 /* mips3302 core */ ++#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */ ++#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */ ++#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */ ++#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */ ++#define SDIOH_CORE_ID 0x81b /* sdio host core */ ++#define ROBO_CORE_ID 0x81c /* roboswitch core */ ++#define ATA100_CORE_ID 0x81d /* parallel ATA core */ ++#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */ ++#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */ ++#define PCIE_CORE_ID 0x820 /* pci express core */ ++#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */ ++#define SRAMC_CORE_ID 0x822 /* SRAM controller core */ ++#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */ ++#define ARM11_CORE_ID 0x824 /* ARM 1176 core */ ++#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */ ++#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */ ++#define PMU_CORE_ID 0x827 /* PMU core */ ++#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */ ++#define SDIOD_CORE_ID 0x829 /* SDIO device core */ ++#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */ ++#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */ ++#define MIPS74K_CORE_ID 0x82c /* mips 74k core */ ++#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */ ++#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */ ++#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */ ++#define SC_CORE_ID 0x831 /* shared common core */ ++#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */ ++#define SPIH_CORE_ID 0x833 /* SPI host core */ ++#define I2S_CORE_ID 0x834 /* I2S core */ ++#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */ ++#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */ ++#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */ ++/* Default component, in ai chips it maps all unused address ranges */ ++#define DEF_AI_COMP 0xfff ++ ++/* Common core control flags */ ++#define SICF_BIST_EN 0x8000 ++#define SICF_PME_EN 0x4000 ++#define SICF_CORE_BITS 0x3ffc ++#define SICF_FGC 0x0002 ++#define SICF_CLOCK_EN 0x0001 ++ ++#endif /* _BRCM_SOC_H */ +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig 2011-11-09 13:46:58.289800083 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig 2011-11-09 13:47:17.048565567 -0500 +@@ -0,0 +1,35 @@ ++config BRCMUTIL ++ tristate ++ ++config BRCMSMAC ++ tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" ++ depends on PCI ++ depends on MAC80211 ++ depends on BCMA=n ++ select BRCMUTIL ++ select FW_LOADER ++ select CRC_CCITT ++ select CRC8 ++ select CORDIC ++ ---help--- ++ This module adds support for PCIe wireless adapters based on Broadcom ++ IEEE802.11n SoftMAC chipsets. If you choose to build a module, it'll ++ be called brcmsmac.ko. ++ ++config BRCMFMAC ++ tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver" ++ depends on MMC ++ depends on CFG80211 ++ select BRCMUTIL ++ select FW_LOADER ++ ---help--- ++ This module adds support for embedded wireless adapters based on ++ Broadcom IEEE802.11n FullMAC chipsets. This driver uses the kernel's ++ wireless extensions subsystem. If you choose to build a module, ++ it'll be called brcmfmac.ko. ++ ++config BRCMDBG ++ bool "Broadcom driver debug functions" ++ depends on BRCMSMAC || BRCMFMAC ++ ---help--- ++ Selecting this enables additional code for debug purposes. +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/Makefile.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/Makefile +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/Makefile.orig 2011-11-09 13:46:58.289800083 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/Makefile 2011-11-09 13:47:17.048565567 -0500 +@@ -0,0 +1,23 @@ ++# ++# Makefile fragment for Broadcom 802.11n Networking Device Driver ++# ++# Copyright (c) 2010 Broadcom Corporation ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ ++# common flags ++subdir-ccflags-$(CONFIG_BRCMDBG) += -DBCMDBG ++ ++obj-$(CONFIG_BRCMUTIL) += brcmutil/ ++obj-$(CONFIG_BRCMFMAC) += brcmfmac/ ++obj-$(CONFIG_BRCMSMAC) += brcmsmac/ +diff -up linux-3.1.x86_64/drivers/net/wireless/Kconfig.orig linux-3.1.x86_64/drivers/net/wireless/Kconfig +--- linux-3.1.x86_64/drivers/net/wireless/Kconfig.orig 2011-11-09 13:48:16.411823422 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/Kconfig 2011-11-09 13:48:24.808718444 -0500 +@@ -271,6 +271,7 @@ config MWL8K + source "drivers/net/wireless/ath/Kconfig" + source "drivers/net/wireless/b43/Kconfig" + source "drivers/net/wireless/b43legacy/Kconfig" ++source "drivers/net/wireless/brcm80211/Kconfig" + source "drivers/net/wireless/hostap/Kconfig" + source "drivers/net/wireless/ipw2x00/Kconfig" + source "drivers/net/wireless/iwlwifi/Kconfig" +diff -up linux-3.1.x86_64/drivers/net/wireless/Makefile.orig linux-3.1.x86_64/drivers/net/wireless/Makefile +--- linux-3.1.x86_64/drivers/net/wireless/Makefile.orig 2011-11-09 13:47:55.028090756 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/Makefile 2011-11-09 13:47:49.856155362 -0500 +@@ -58,3 +58,6 @@ obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl + obj-$(CONFIG_IWM) += iwmc3200wifi/ + + obj-$(CONFIG_MWIFIEX) += mwifiex/ ++ ++obj-$(CONFIG_BRCMFMAC) += brcm80211/ ++obj-$(CONFIG_BRCMSMAC) += brcm80211/ diff --git a/config-generic b/config-generic index 973a1be00..35b31d8ca 100644 --- a/config-generic +++ b/config-generic @@ -1573,6 +1573,10 @@ CONFIG_RTL8192DE=m CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m +CONFIG_BRCMFMAC=m +CONFIG_BRCMSMAC=m +# CONFIG_BRCMDBG is not set + # # Token Ring devices # @@ -4396,8 +4400,6 @@ CONFIG_USB_ATMEL=m # CONFIG_ALTERA_STAPL is not set # CONFIG_DVB_CXD2099 is not set # CONFIG_USBIP_CORE is not set -# CONFIG_BRCMSMAC is not set -# CONFIG_BRCMFMAC is not set # CONFIG_INTEL_MEI is not set # CONFIG_ZCACHE is not set diff --git a/kernel.spec b/kernel.spec index 8003d5a7c..9d59bac48 100644 --- a/kernel.spec +++ b/kernel.spec @@ -780,6 +780,9 @@ Patch21063: mac80211-config-hw-when-going-back-on-channel.patch #rhbz752176 Patch21080: sysfs-msi-irq-per-device.patch + +#backport brcm80211 from 3.2-rc1 +Patch21090: brcm80211.patch %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1441,6 +1444,9 @@ ApplyPatch mac80211-config-hw-when-going-back-on-channel.patch #rhbz 752176 ApplyPatch sysfs-msi-irq-per-device.patch +#backport brcm80211 from 3.2-rc1 +ApplyPatch brcm80211.patch + # END OF PATCH APPLICATIONS %endif @@ -2142,6 +2148,9 @@ fi # and build. %changelog +* Wed Nov 09 2011 John W. Linville +- Backport brcm80211 from 3.2-rc1 + * Tue Nov 08 2011 Neil Horman - Add msi irq ennumeration per device in sysfs (rhbz 752176) From dabe57bb092f9fc8e70667f8ca94710e0f193d74 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 9 Nov 2011 21:14:46 -0500 Subject: [PATCH 132/487] Linux 3.1.1-rc1 Comment out merged patches, will drop when release is final: ums-realtek-driver-uses-stack-memory-for-DMA.patch epoll-fix-spurious-lockdep-warnings.patch crypto-register-cryptd-first.patch add-macbookair41-keyboard.patch powerpc-Fix-deadlock-in-icswx-code.patch iwlagn-fix-ht_params-NULL-pointer-dereference.patch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch media-DiBcom-protect-the-I2C-bufer-access.patch media-dib0700-protect-the-dib0700-buffer-access.patch WMI-properly-cleanup-devices-to-avoid-crashes.patch mac80211-fix-remain_off_channel-regression.patch mac80211-config-hw-when-going-back-on-channel.patch --- config-generic | 3 +- kernel.spec | 46 ++++++++++----- sources | 1 + usb-add-quirk-for-logitech-webcams.patch | 71 ++---------------------- 4 files changed, 39 insertions(+), 82 deletions(-) diff --git a/config-generic b/config-generic index 35b31d8ca..879a09b50 100644 --- a/config-generic +++ b/config-generic @@ -3105,6 +3105,7 @@ CONFIG_USB_STORAGE_ONETOUCH=m CONFIG_USB_STORAGE_ALAUDA=m CONFIG_USB_STORAGE_KARMA=m CONFIG_USB_STORAGE_REALTEK=m +CONFIG_REALTEK_AUTOPM=y CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set CONFIG_USB_UAS=m @@ -3158,7 +3159,6 @@ CONFIG_HID_TOPSEED=m CONFIG_HID_THRUSTMASTER=m CONFIG_HID_ZEROPLUS=m CONFIG_HID_ZYDACRON=m -CONFIG_HID_ACRUX_FF=m CONFIG_HID_EMS_FF=m CONFIG_HID_ELECOM=m CONFIG_HID_UCLOGIC=m @@ -3166,6 +3166,7 @@ CONFIG_HID_WALTOP=m CONFIG_HID_ROCCAT_PYRA=m CONFIG_HID_ROCCAT_KONEPLUS=m CONFIG_HID_ACRUX=m +CONFIG_HID_ACRUX_FF=y CONFIG_HID_KEYTOUCH=m CONFIG_HID_LCPOWER=m CONFIG_HID_ROCCAT_ARVO=m diff --git a/kernel.spec b/kernel.spec index 9d59bac48..5ae046555 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 10 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -63,9 +63,9 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 0 +%define stable_update 1 # Is it a -stable RC? -%define stable_rc 0 +%define stable_rc 1 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -1384,14 +1384,14 @@ ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch add-appleir-usb-driver.patch ApplyPatch udlfb-bind-framebuffer-to-interface.patch -ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch -ApplyPatch epoll-fix-spurious-lockdep-warnings.patch +#ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch +#ApplyPatch epoll-fix-spurious-lockdep-warnings.patch ApplyPatch epoll-limit-paths.patch ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch ApplyPatch block-stray-block-put-after-teardown.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch -ApplyPatch crypto-register-cryptd-first.patch +#ApplyPatch crypto-register-cryptd-first.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -1399,19 +1399,19 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch revert-efi-rtclock.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch -ApplyPatch add-macbookair41-keyboard.patch +#ApplyPatch add-macbookair41-keyboard.patch ApplyPatch hvcs_pi_buf_alloc.patch -ApplyPatch powerpc-Fix-deadlock-in-icswx-code.patch +#ApplyPatch powerpc-Fix-deadlock-in-icswx-code.patch -ApplyPatch iwlagn-fix-ht_params-NULL-pointer-dereference.patch +#ApplyPatch iwlagn-fix-ht_params-NULL-pointer-dereference.patch #rhbz #722509 -ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch +#ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch -ApplyPatch media-DiBcom-protect-the-I2C-bufer-access.patch -ApplyPatch media-dib0700-protect-the-dib0700-buffer-access.patch +#ApplyPatch media-DiBcom-protect-the-I2C-bufer-access.patch +#ApplyPatch media-dib0700-protect-the-dib0700-buffer-access.patch ApplyPatch media-dib0700-correct-error-message.patch # utrace. @@ -1429,7 +1429,7 @@ ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch ApplyPatch oom-fix-integer-overflow-of-points.patch #rhbz 706574 -ApplyPatch WMI-properly-cleanup-devices-to-avoid-crashes.patch +#ApplyPatch WMI-properly-cleanup-devices-to-avoid-crashes.patch #rhbz 728607 ApplyPatch elantech.patch @@ -1438,8 +1438,8 @@ ApplyPatch elantech.patch ApplyPatch ideapad-Check-if-acpi-already-handle-backlight.patch #rhbz 731365 -ApplyPatch mac80211-fix-remain_off_channel-regression.patch -ApplyPatch mac80211-config-hw-when-going-back-on-channel.patch +#ApplyPatch mac80211-fix-remain_off_channel-regression.patch +#ApplyPatch mac80211-config-hw-when-going-back-on-channel.patch #rhbz 752176 ApplyPatch sysfs-msi-irq-per-device.patch @@ -2148,6 +2148,22 @@ fi # and build. %changelog +* Wed Nov 09 2011 Chuck Ebbert 3.1.1-1.rc1 +- Linux 3.1.1-rc1 +- Comment out merged patches, will drop when release is final: + ums-realtek-driver-uses-stack-memory-for-DMA.patch + epoll-fix-spurious-lockdep-warnings.patch + crypto-register-cryptd-first.patch + add-macbookair41-keyboard.patch + powerpc-Fix-deadlock-in-icswx-code.patch + iwlagn-fix-ht_params-NULL-pointer-dereference.patch + mmc-Always-check-for-lower-base-frequency-quirk-for-.patch + media-DiBcom-protect-the-I2C-bufer-access.patch + media-dib0700-protect-the-dib0700-buffer-access.patch + WMI-properly-cleanup-devices-to-avoid-crashes.patch + mac80211-fix-remain_off_channel-regression.patch + mac80211-config-hw-when-going-back-on-channel.patch + * Wed Nov 09 2011 John W. Linville - Backport brcm80211 from 3.2-rc1 diff --git a/sources b/sources index 9529d7a05..da0608dfe 100644 --- a/sources +++ b/sources @@ -1 +1,2 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 +0582554c78b9979dc91223e3f4e4ec22 patch-3.1.1-rc1.bz2 diff --git a/usb-add-quirk-for-logitech-webcams.patch b/usb-add-quirk-for-logitech-webcams.patch index 052a27e73..b4c795133 100644 --- a/usb-add-quirk-for-logitech-webcams.patch +++ b/usb-add-quirk-for-logitech-webcams.patch @@ -1,75 +1,14 @@ -From d5446509abd85b6845d91a319a033c5bd17e494d Mon Sep 17 00:00:00 2001 -From: Oliver Neukum -Date: Tue, 13 Sep 2011 08:42:21 +0200 -Subject: [PATCH] USB:add RESET_RESUME for webcams shown to be quirky - -From 6f673c5ef819548b2cbaf7bb607779af6fdbe731 Mon Sep 17 00:00:00 2001 -From: Oliver Neukum -Date: Tue, 30 Aug 2011 15:34:32 +0200 -Subject: [PATCH] USB:add RESET_RESUME for webcams shown to be quirky - -The new runtime PM code has shown that many webcams suffer -from a race condition that may crash them upon resume. -Runtime PM is especially prone to show the problem because -it retains power to the cameras at all times. However -system suspension may also crash the devices and retain -power to the devices. -The only way to solve this problem without races is in -usbcore with the RESET_RESUME quirk. - -Signed-off-by: Oliver Neukum - -Add C300 ID from patch in rhbz #742010 Add C600 ID from rhbz #742010 --- - drivers/usb/core/quirks.c | 27 +++++++++++++++++++++++++++ - 1 files changed, 27 insertions(+), 0 deletions(-) - -diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c -index 81ce6a8..caa1991 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c -@@ -38,6 +38,30 @@ static const struct usb_device_id usb_quirk_list[] = { - /* Creative SB Audigy 2 NX */ - { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, +@@ -38,6 +38,9 @@ static const struct usb_device_id usb_quirk_list[] = { + /* Logitech Webcam B/C500 */ + { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME }, -+ /* Logitech Webcam C200 */ -+ { USB_DEVICE(0x046d, 0x0802), .driver_info = USB_QUIRK_RESET_RESUME }, -+ -+ /* Logitech Webcam C250 */ -+ { USB_DEVICE(0x046d, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, -+ -+ /* Logitech Webcam C300 */ -+ { USB_DEVICE(0x046d, 0x0805), .driver_info = USB_QUIRK_RESET_RESUME }, -+ -+ /* Logitech Webcam B/C500 */ -+ { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME }, -+ + /* Logitech Webcam C600 */ + { USB_DEVICE(0x046d, 0x0808), .driver_info = USB_QUIRK_RESET_RESUME }, + -+ /* Logitech Webcam Pro 9000 */ -+ { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME }, -+ -+ /* Logitech Webcam C310 */ -+ { USB_DEVICE(0x046d, 0x081b), .driver_info = USB_QUIRK_RESET_RESUME }, -+ -+ /* Logitech Webcam C270 */ -+ { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME }, -+ - /* Logitech Harmony 700-series */ - { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, + /* Logitech Webcam Pro 9000 */ + { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME }, -@@ -69,6 +93,9 @@ static const struct usb_device_id usb_quirk_list[] = { - { USB_DEVICE(0x06a3, 0x0006), .driver_info = - USB_QUIRK_CONFIG_INTF_STRINGS }, - -+ /* Guillemot Webcam Hercules Dualpix Exchange*/ -+ { USB_DEVICE(0x06f8, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, -+ - /* M-Systems Flash Disk Pioneers */ - { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, - --- -1.7.6.4 - From e52a782db96c384d0897ec9a5a57b698dca7f897 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 10 Nov 2011 22:02:49 -0500 Subject: [PATCH 133/487] Sync samsung-laptop driver with what's in 3.2 (rhbz 747560) --- kernel.spec | 11 +- kernel.spec.orig | 2620 +++++++++++++++++++++ samsung-laptop-brightness-fixes-3.2.patch | 238 ++ 3 files changed, 2868 insertions(+), 1 deletion(-) create mode 100644 kernel.spec.orig create mode 100644 samsung-laptop-brightness-fixes-3.2.patch diff --git a/kernel.spec b/kernel.spec index 5ae046555..0454637eb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -673,6 +673,9 @@ Patch700: linux-2.6-e1000-ich9-montevina.patch Patch800: linux-2.6-crash-driver.patch +# Platform +Patch900: samsung-laptop-brightness-fixes-3.2.patch + # crypto/ # virt + ksm patches @@ -1376,6 +1379,9 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-update.patch ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch #ApplyPatch linux-2.6-v4l-dvb-uvcvideo-update.patch +# Platform fixes not sent for -stable +ApplyPatch samsung-laptop-brightness-fixes-3.2.patch + # Patches headed upstream ApplyPatch rcutree-avoid-false-quiescent-states.patch @@ -2148,6 +2154,9 @@ fi # and build. %changelog +* Thu Nov 10 2011 Chuck Ebbert +- Sync samsung-laptop driver with what's in 3.2 (rhbz 747560) + * Wed Nov 09 2011 Chuck Ebbert 3.1.1-1.rc1 - Linux 3.1.1-rc1 - Comment out merged patches, will drop when release is final: diff --git a/kernel.spec.orig b/kernel.spec.orig new file mode 100644 index 000000000..5ae046555 --- /dev/null +++ b/kernel.spec.orig @@ -0,0 +1,2620 @@ +# We have to override the new %%install behavior because, well... the kernel is special. +%global __spec_install_pre %{___build_pre} + +Summary: The Linux kernel + +# For a stable, released kernel, released_kernel should be 1. For rawhide +# and/or a kernel built from an rc or git snapshot, released_kernel should +# be 0. +%global released_kernel 1 + +# Save original buildid for later if it's defined +%if 0%{?buildid:1} +%global orig_buildid %{buildid} +%undefine buildid +%endif + +################################################################### +# Polite request for people who spin their own kernel rpms: +# please modify the "buildid" define in a way that identifies +# that the kernel isn't the stock distribution kernel, for example, +# by setting the define to ".local" or ".bz123456". This will be +# appended to the full kernel version. +# +# (Uncomment the '#' and both spaces below to set the buildid.) +# +# % define buildid .local +################################################################### + +# The buildid can also be specified on the rpmbuild command line +# by adding --define="buildid .whatever". If both the specfile and +# the environment define a buildid they will be concatenated together. +%if 0%{?orig_buildid:1} +%if 0%{?buildid:1} +%global srpm_buildid %{buildid} +%define buildid %{srpm_buildid}%{orig_buildid} +%else +%define buildid %{orig_buildid} +%endif +%endif + +# baserelease defines which build revision of this kernel version we're +# building. We used to call this fedora_build, but the magical name +# baserelease is matched by the rpmdev-bumpspec tool, which you should use. +# +# We used to have some extra magic weirdness to bump this automatically, +# but now we don't. Just use: rpmdev-bumpspec -c 'comment for changelog' +# When changing base_sublevel below or going from rc to a final kernel, +# reset this by hand to 1 (or to 0 and then use rpmdev-bumpspec). +# scripts/rebase.sh should be made to do that for you, actually. +# +# For non-released -rc kernels, this will be prepended with "0.", so +# for example a 3 here will become 0.3 +# +%global baserelease 1 +%global fedora_build %{baserelease} + +# base_sublevel is the kernel version we're starting with and patching +# on top of -- for example, 2.6.22-rc7-git1 starts with a 2.6.21 base, +# which yields a base_sublevel of 21. +%define base_sublevel 1 + +## If this is a released kernel ## +%if 0%{?released_kernel} + +# Do we have a -stable update to apply? +%define stable_update 1 +# Is it a -stable RC? +%define stable_rc 1 +# Set rpm version accordingly +%if 0%{?stable_update} +%define stablerev %{stable_update} +%define stable_base %{stable_update} +%if 0%{?stable_rc} +# stable RCs are incremental patches, so we need the previous stable patch +%define stable_base %(echo $((%{stable_update} - 1))) +%endif +%endif +%define rpmversion 3.%{base_sublevel}.%{stable_update} + +## The not-released-kernel case ## +%else +# The next upstream release sublevel (base_sublevel+1) +%define upstream_sublevel %(echo $((%{base_sublevel} + 1))) +# The rc snapshot level +%define rcrev 10 +# The git snapshot level +%define gitrev 1 +# Set rpm version accordingly +%define rpmversion 3.%{upstream_sublevel}.0 +%endif +# Nb: The above rcrev and gitrev values automagically define Patch00 and Patch01 below. + +# What parts do we want to build? We must build at least one kernel. +# These are the kernels that are built IF the architecture allows it. +# All should default to 1 (enabled) and be flipped to 0 (disabled) +# by later arch-specific checks. + +# The following build options are enabled by default. +# Use either --without in your rpmbuild command or force values +# to 0 in here to disable them. +# +# standard kernel +%define with_up %{?_without_up: 0} %{?!_without_up: 1} +# kernel-smp (only valid for ppc 32-bit) +%define with_smp %{?_without_smp: 0} %{?!_without_smp: 1} +# kernel-PAE (only valid for i686) +%define with_pae %{?_without_pae: 0} %{?!_without_pae: 1} +# kernel-debug +%define with_debug %{?_without_debug: 0} %{?!_without_debug: 1} +# kernel-doc +%define with_doc %{?_without_doc: 0} %{?!_without_doc: 1} +# kernel-headers +%define with_headers %{?_without_headers: 0} %{?!_without_headers: 1} +# kernel-firmware +%define with_firmware %{?_with_firmware: 1} %{?!_with_firmware: 0} +# tools +%define with_tools %{?_without_tools: 0} %{?!_without_tools: 1} +# kernel-debuginfo +%define with_debuginfo %{?_without_debuginfo: 0} %{?!_without_debuginfo: 1} +# kernel-bootwrapper (for creating zImages from kernel + initrd) +%define with_bootwrapper %{?_without_bootwrapper: 0} %{?!_without_bootwrapper: 1} +# Want to build a the vsdo directories installed +%define with_vdso_install %{?_without_vdso_install: 0} %{?!_without_vdso_install: 1} +# ARM OMAP (Beagle/Panda Board) +%define with_omap %{?_without_omap: 0} %{?!_without_omap: 1} +# kernel-tegra (only valid for arm) +%define with_tegra %{?_without_tegra: 0} %{?!_without_tegra: 1} + +# Build the kernel-doc package, but don't fail the build if it botches. +# Here "true" means "continue" and "false" means "fail the build". +%if 0%{?released_kernel} +%define doc_build_fail false +%else +%define doc_build_fail true +%endif + +%define rawhide_skip_docs 0 +%if 0%{?rawhide_skip_docs} +%define with_doc 0 +%define doc_build_fail true +%endif + +# Additional options for user-friendly one-off kernel building: +# +# Only build the base kernel (--with baseonly): +%define with_baseonly %{?_with_baseonly: 1} %{?!_with_baseonly: 0} +# Only build the smp kernel (--with smponly): +%define with_smponly %{?_with_smponly: 1} %{?!_with_smponly: 0} +# Only build the pae kernel (--with paeonly): +%define with_paeonly %{?_with_paeonly: 1} %{?!_with_paeonly: 0} +# Only build the debug kernel (--with dbgonly): +%define with_dbgonly %{?_with_dbgonly: 1} %{?!_with_dbgonly: 0} + +# should we do C=1 builds with sparse +%define with_sparse %{?_with_sparse: 1} %{?!_with_sparse: 0} + +# Set debugbuildsenabled to 1 for production (build separate debug kernels) +# and 0 for rawhide (all kernels are debug kernels). +# See also 'make debug' and 'make release'. +%define debugbuildsenabled 1 + +# Want to build a vanilla kernel build without any non-upstream patches? +%define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} + +# pkg_release is what we'll fill in for the rpm Release: field +%if 0%{?released_kernel} + +%if 0%{?stable_rc} +%define stable_rctag .rc%{stable_rc} +%endif +%define pkg_release %{fedora_build}%{?stable_rctag}%{?buildid}%{?dist} + +%else + +# non-released_kernel +%if 0%{?rcrev} +%define rctag .rc%rcrev +%else +%define rctag .rc0 +%endif +%if 0%{?gitrev} +%define gittag .git%gitrev +%else +%define gittag .git0 +%endif +%define pkg_release 0%{?rctag}%{?gittag}.%{fedora_build}%{?buildid}%{?dist} + +%endif + +# The kernel tarball/base version +%define kversion 3.%{base_sublevel} + +%define make_target bzImage + +%define KVERREL %{version}-%{release}.%{_target_cpu} +%define hdrarch %_target_cpu +%define asmarch %_target_cpu + +%if 0%{!?nopatches:1} +%define nopatches 0 +%endif + +%if %{with_vanilla} +%define nopatches 1 +%endif + +%if %{nopatches} +%define with_bootwrapper 0 +%define variant -vanilla +%else +%define variant_fedora -fedora +%endif + +%define using_upstream_branch 0 +%if 0%{?upstream_branch:1} +%define stable_update 0 +%define using_upstream_branch 1 +%define variant -%{upstream_branch}%{?variant_fedora} +%define pkg_release 0.%{fedora_build}%{upstream_branch_tag}%{?buildid}%{?dist} +%endif + +%if !%{debugbuildsenabled} +%define with_debug 0 +%endif + +%if !%{with_debuginfo} +%define _enable_debug_packages 0 +%endif +%define debuginfodir /usr/lib/debug + +# kernel-PAE is only built on i686. +%ifnarch i686 +%define with_pae 0 +%endif + +# kernel-tegra and omap is only built on armv7 hard and softfp +%ifnarch armv7hl armv7l +%define with_tegra 0 +%define with_omap 0 +%endif + +# if requested, only build base kernel +%if %{with_baseonly} +%define with_smp 0 +%define with_pae 0 +%define with_debug 0 +%endif + +# if requested, only build smp kernel +%if %{with_smponly} +%define with_up 0 +%define with_pae 0 +%define with_debug 0 +%endif + +# if requested, only build pae kernel +%if %{with_paeonly} +%define with_up 0 +%define with_smp 0 +%define with_debug 0 +%endif + +# if requested, only build debug kernel +%if %{with_dbgonly} +%if %{debugbuildsenabled} +%define with_up 0 +%define with_pae 0 +%endif +%define with_smp 0 +%define with_pae 0 +%define with_tools 0 +%endif + +%define all_x86 i386 i686 + +%if %{with_vdso_install} +# These arches install vdso/ directories. +%define vdso_arches %{all_x86} x86_64 ppc ppc64 +%endif + +# Overrides for generic default options + +# only ppc and alphav56 need separate smp kernels +%ifnarch ppc alphaev56 +%define with_smp 0 +%endif + +# don't do debug builds on anything but i686 and x86_64 +%ifnarch i686 x86_64 +%define with_debug 0 +%endif + +# only package docs noarch +%ifnarch noarch +%define with_doc 0 +%endif + +# don't build noarch kernels or headers (duh) +%ifarch noarch +%define with_up 0 +%define with_headers 0 +%define with_tools 0 +%define all_arch_configs kernel-%{version}-*.config +%define with_firmware %{?_with_firmware: 1} %{?!_with_firmware: 0} +%endif + +# bootwrapper is only on ppc +%ifnarch ppc ppc64 +%define with_bootwrapper 0 +%endif + +# sparse blows up on ppc64 alpha and sparc64 +%ifarch ppc64 ppc alpha sparc64 +%define with_sparse 0 +%endif + +# Per-arch tweaks + +%ifarch %{all_x86} +%define asmarch x86 +%define hdrarch i386 +%define all_arch_configs kernel-%{version}-i?86*.config +%define image_install_path boot +%define kernel_image arch/x86/boot/bzImage +%endif + +%ifarch x86_64 +%define asmarch x86 +%define all_arch_configs kernel-%{version}-x86_64*.config +%define image_install_path boot +%define kernel_image arch/x86/boot/bzImage +%endif + +%ifarch ppc64 +%define asmarch powerpc +%define hdrarch powerpc +%define all_arch_configs kernel-%{version}-ppc64*.config +%define image_install_path boot +%define make_target vmlinux +%define kernel_image vmlinux +%define kernel_image_elf 1 +%endif + +%ifarch s390x +%define asmarch s390 +%define hdrarch s390 +%define all_arch_configs kernel-%{version}-s390x.config +%define image_install_path boot +%define make_target image +%define kernel_image arch/s390/boot/image +%define with_tools 0 +%endif + +%ifarch sparc64 +%define asmarch sparc +%define all_arch_configs kernel-%{version}-sparc64*.config +%define make_target vmlinux +%define kernel_image vmlinux +%define image_install_path boot +%define with_tools 0 +%endif + +%ifarch sparcv9 +%define hdrarch sparc +%endif + +%ifarch ppc +%define asmarch powerpc +%define hdrarch powerpc +%define all_arch_configs kernel-%{version}-ppc{-,.}*config +%define image_install_path boot +%define make_target vmlinux +%define kernel_image vmlinux +%define kernel_image_elf 1 +%endif + +%ifarch ia64 +%define all_arch_configs kernel-%{version}-ia64*.config +%define image_install_path boot/efi/EFI/redhat +%define make_target compressed +%define kernel_image vmlinux.gz +%endif + +%ifarch alpha alphaev56 +%define all_arch_configs kernel-%{version}-alpha*.config +%define image_install_path boot +%define make_target vmlinux +%define kernel_image vmlinux +%endif + +%ifarch %{arm} +%define all_arch_configs kernel-%{version}-arm*.config +%define image_install_path boot +%define asmarch arm +%define hdrarch arm +%define make_target bzImage +%define kernel_image arch/arm/boot/zImage +# we build a up kernel on armv5tel. its used for qemu. +%ifnarch armv5tel +%define with_up 0 +%define with_perf 0 +%endif +# we only build headers on the base arm arches +# just like we used to only build them on i386 for x86 +%ifnarch armv5tel armv7hl +%define with_headers 0 +%endif +%endif + +%if %{nopatches} +# XXX temporary until last vdso patches are upstream +%define vdso_arches ppc ppc64 +%endif + +# Should make listnewconfig fail if there's config options +# printed out? +%if %{nopatches}%{using_upstream_branch} +%define listnewconfig_fail 0 +%else +%define listnewconfig_fail 1 +%endif + +# To temporarily exclude an architecture from being built, add it to +# %%nobuildarches. Do _NOT_ use the ExclusiveArch: line, because if we +# don't build kernel-headers then the new build system will no longer let +# us use the previous build of that package -- it'll just be completely AWOL. +# Which is a BadThing(tm). + +# We only build kernel-headers on the following... +%define nobuildarches i386 s390 sparc sparcv9 + +%ifarch %nobuildarches +%define with_up 0 +%define with_smp 0 +%define with_pae 0 +%define with_debuginfo 0 +%define with_tools 0 +%define _enable_debug_packages 0 +%endif + +%define with_pae_debug 0 +%if %{with_pae} +%define with_pae_debug %{with_debug} +%endif + +# Architectures we build tools/cpupower on +%define cpupowerarchs %{ix86} x86_64 ppc ppc64 + +# +# Three sets of minimum package version requirements in the form of Conflicts: +# to versions below the minimum +# + +# +# First the general kernel 2.6 required versions as per +# Documentation/Changes +# +%define kernel_dot_org_conflicts ppp < 2.4.3-3, isdn4k-utils < 3.2-32, nfs-utils < 1.0.7-12, e2fsprogs < 1.37-4, util-linux < 2.12, jfsutils < 1.1.7-2, reiserfs-utils < 3.6.19-2, xfsprogs < 2.6.13-4, procps < 3.2.5-6.3, oprofile < 0.9.1-2, device-mapper-libs < 1.02.63-2, mdadm < 3.2.1-5 + +# +# Then a series of requirements that are distribution specific, either +# because we add patches for something, or the older versions have +# problems with the newer kernel or lack certain things that make +# integration in the distro harder than needed. +# +%define package_conflicts initscripts < 7.23, udev < 063-6, iptables < 1.3.2-1, ipw2200-firmware < 2.4, iwl4965-firmware < 228.57.2, selinux-policy-targeted < 1.25.3-14, squashfs-tools < 4.0, wireless-tools < 29-3 + +# We moved the drm include files into kernel-headers, make sure there's +# a recent enough libdrm-devel on the system that doesn't have those. +%define kernel_headers_conflicts libdrm-devel < 2.4.0-0.15 + +# +# Packages that need to be installed before the kernel is, because the %%post +# scripts use them. +# +%define kernel_prereq fileutils, module-init-tools >= 3.16-2, initscripts >= 8.11.1-1, grubby >= 8.3-1 +%define initrd_prereq dracut >= 001-7 + +# +# This macro does requires, provides, conflicts, obsoletes for a kernel package. +# %%kernel_reqprovconf +# It uses any kernel__conflicts and kernel__obsoletes +# macros defined above. +# +%define kernel_reqprovconf \ +Provides: kernel = %{rpmversion}-%{pkg_release}\ +Provides: kernel-%{_target_cpu} = %{rpmversion}-%{pkg_release}%{?1:.%{1}}\ +Provides: kernel-drm = 4.3.0\ +Provides: kernel-drm-nouveau = 16\ +Provides: kernel-modeset = 1\ +Provides: kernel-uname-r = %{KVERREL}%{?1:.%{1}}\ +Requires(pre): %{kernel_prereq}\ +Requires(pre): %{initrd_prereq}\ +%if %{with_firmware}\ +Requires(pre): kernel-firmware >= %{rpmversion}-%{pkg_release}\ +%else\ +Requires(pre): linux-firmware >= 20100806-2\ +%endif\ +Requires(post): /sbin/new-kernel-pkg\ +Requires(preun): /sbin/new-kernel-pkg\ +Conflicts: %{kernel_dot_org_conflicts}\ +Conflicts: %{package_conflicts}\ +%{expand:%%{?kernel%{?1:_%{1}}_conflicts:Conflicts: %%{kernel%{?1:_%{1}}_conflicts}}}\ +%{expand:%%{?kernel%{?1:_%{1}}_obsoletes:Obsoletes: %%{kernel%{?1:_%{1}}_obsoletes}}}\ +%{expand:%%{?kernel%{?1:_%{1}}_provides:Provides: %%{kernel%{?1:_%{1}}_provides}}}\ +# We can't let RPM do the dependencies automatic because it'll then pick up\ +# a correct but undesirable perl dependency from the module headers which\ +# isn't required for the kernel proper to function\ +AutoReq: no\ +AutoProv: yes\ +%{nil} + +Name: kernel%{?variant} +Group: System Environment/Kernel +License: GPLv2 +URL: http://www.kernel.org/ +Version: %{rpmversion} +Release: %{pkg_release} +# DO NOT CHANGE THE 'ExclusiveArch' LINE TO TEMPORARILY EXCLUDE AN ARCHITECTURE BUILD. +# SET %%nobuildarches (ABOVE) INSTEAD +ExclusiveArch: noarch %{all_x86} x86_64 ppc ppc64 ia64 %{sparc} s390 s390x alpha alphaev56 %{arm} +ExclusiveOS: Linux + +%kernel_reqprovconf + +# +# List the packages used during the kernel build +# +BuildRequires: module-init-tools, patch >= 2.5.4, bash >= 2.03, sh-utils, tar +BuildRequires: bzip2, findutils, gzip, m4, perl, make >= 3.78, diffutils, gawk +BuildRequires: gcc >= 3.4.2, binutils >= 2.12, redhat-rpm-config +BuildRequires: net-tools +BuildRequires: xmlto, asciidoc +%if %{with_sparse} +BuildRequires: sparse >= 0.4.1 +%endif +%if %{with_tools} +BuildRequires: elfutils-devel zlib-devel binutils-devel newt-devel python-devel perl(ExtUtils::Embed) pciutils-devel gettext +%endif +BuildConflicts: rhbuildsys(DiskFree) < 500Mb + +%define fancy_debuginfo 0 +%if %{with_debuginfo} +%if 0%{?fedora} >= 8 || 0%{?rhel} >= 6 +%define fancy_debuginfo 1 +%endif +%endif + +%if %{fancy_debuginfo} +# Fancy new debuginfo generation introduced in Fedora 8. +BuildRequires: rpm-build >= 4.4.2.1-4 +%define debuginfo_args --strict-build-id +%endif + +Source0: ftp://ftp.kernel.org/pub/linux/kernel/v3.0/linux-%{kversion}.tar.bz2 + +Source11: genkey +Source14: find-provides +Source15: merge.pl + +Source20: Makefile.config +Source21: config-debug +Source22: config-nodebug +Source23: config-generic +Source24: config-rhel-generic + +Source30: config-x86-generic +Source31: config-i686-PAE +Source32: config-x86-32-generic + +Source40: config-x86_64-generic + +Source50: config-powerpc-generic +Source51: config-powerpc32-generic +Source52: config-powerpc32-smp +Source53: config-powerpc64 + +Source60: config-ia64-generic + +Source70: config-s390x + +Source90: config-sparc64-generic + +Source100: config-arm-generic +Source110: config-arm-omap-generic +Source111: config-arm-tegra + +# This file is intentionally left empty in the stock kernel. Its a nicety +# added for those wanting to do custom rebuilds with altered config opts. +Source1000: config-local + +# Sources for kernel-tools +Source2000: cpupower.service +Source2001: cpupower.config + +# Here should be only the patches up to the upstream canonical Linus tree. + +# For a stable release kernel +%if 0%{?stable_update} +%if 0%{?stable_base} +%define stable_patch_00 patch-3.%{base_sublevel}.%{stable_base}.bz2 +Patch00: %{stable_patch_00} +%endif +%if 0%{?stable_rc} +%define stable_patch_01 patch-3.%{base_sublevel}.%{stable_update}-rc%{stable_rc}.bz2 +Patch01: %{stable_patch_01} +%endif + +# non-released_kernel case +# These are automagically defined by the rcrev and gitrev values set up +# near the top of this spec file. +%else +%if 0%{?rcrev} +Patch00: patch-3.%{upstream_sublevel}-rc%{rcrev}.bz2 +%if 0%{?gitrev} +Patch01: patch-3.%{upstream_sublevel}-rc%{rcrev}-git%{gitrev}.bz2 +%endif +%else +# pre-{base_sublevel+1}-rc1 case +%if 0%{?gitrev} +Patch00: patch-3.%{base_sublevel}-git%{gitrev}.bz2 +%endif +%endif +%endif + +%if %{using_upstream_branch} +### BRANCH PATCH ### +%endif + +Patch02: git-linus.diff + +# we also need compile fixes for -vanilla +Patch04: linux-2.6-compile-fixes.patch + +# build tweak for build ID magic, even for -vanilla +Patch05: linux-2.6-makefile-after_link.patch + +%if !%{nopatches} + + +# revert upstream patches we get via other methods +Patch09: linux-2.6-upstream-reverts.patch +# Git trees. + +# Standalone patches + +Patch100: taint-vbox.patch +Patch160: linux-2.6-32bit-mmap-exec-randomization.patch +Patch161: linux-2.6-i386-nx-emulation.patch + +Patch202: linux-2.6-debug-taint-vm.patch + +Patch383: linux-2.6-defaults-aspm.patch + +Patch390: linux-2.6-defaults-acpi-video.patch +Patch391: linux-2.6-acpi-video-dos.patch +Patch394: linux-2.6-acpi-debug-infinite-loop.patch +Patch395: acpi-ensure-thermal-limits-match-cpu-freq.patch +Patch396: acpi-sony-nonvs-blacklist.patch + +Patch450: linux-2.6-input-kill-stupid-messages.patch +Patch452: linux-2.6.30-no-pcspkr-modalias.patch + +Patch460: linux-2.6-serial-460800.patch + +Patch470: die-floppy-die.patch +Patch471: floppy-drop-disable_hlt-warning.patch + +Patch510: linux-2.6-silence-noise.patch +Patch530: linux-2.6-silence-fbcon-logo.patch + +Patch700: linux-2.6-e1000-ich9-montevina.patch + +Patch800: linux-2.6-crash-driver.patch + +# crypto/ + +# virt + ksm patches +Patch1500: fix_xen_guest_on_old_EC2.patch + +# DRM + +# nouveau + drm fixes +Patch1810: drm-nouveau-updates.patch +# intel drm is all merged upstream +Patch1824: drm-intel-next.patch +# make sure the lvds comes back on lid open +Patch1825: drm-intel-make-lvds-work.patch +# hush the i915 fbc noise +Patch1826: drm-i915-fbc-stfu.patch +# rhbz#729882, https://bugs.freedesktop.org/attachment.cgi?id=49069 +Patch1827: drm-i915-sdvo-lvds-is-digital.patch + +Patch1850: drm-lower-severity-radeon-lockup.diff + +Patch1900: linux-2.6-intel-iommu-igfx.patch + +# Quiet boot fixes +# silence the ACPI blacklist code +Patch2802: linux-2.6-silence-acpi-blacklist.patch + +# media patches +Patch2899: linux-2.6-v4l-dvb-fixes.patch +Patch2900: linux-2.6-v4l-dvb-update.patch +Patch2901: linux-2.6-v4l-dvb-experimental.patch +Patch2902: linux-2.6-v4l-dvb-uvcvideo-update.patch + +Patch2903: media-DiBcom-protect-the-I2C-bufer-access.patch +Patch2904: media-dib0700-protect-the-dib0700-buffer-access.patch +Patch2905: media-dib0700-correct-error-message.patch + +Patch3000: rcutree-avoid-false-quiescent-states.patch + +# fs fixes + +# NFSv4 + +# patches headed upstream +Patch12010: add-appleir-usb-driver.patch + +Patch12016: disable-i8042-check-on-apple-mac.patch + +Patch12021: udlfb-bind-framebuffer-to-interface.patch + +Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch +Patch12024: epoll-fix-spurious-lockdep-warnings.patch +Patch12025: rcu-avoid-just-onlined-cpu-resched.patch +Patch12026: block-stray-block-put-after-teardown.patch +Patch12027: usb-add-quirk-for-logitech-webcams.patch +Patch12029: crypto-register-cryptd-first.patch +Patch12030: epoll-limit-paths.patch + +Patch12303: dmar-disable-when-ricoh-multifunction.patch + +Patch13002: revert-efi-rtclock.patch +Patch13003: efi-dont-map-boot-services-on-32bit.patch + +Patch13007: add-macbookair41-keyboard.patch + +Patch13009: hvcs_pi_buf_alloc.patch + +Patch13013: powerpc-Fix-deadlock-in-icswx-code.patch + +Patch13014: iwlagn-fix-ht_params-NULL-pointer-dereference.patch + +Patch20000: utrace.patch + +# Flattened devicetree support +Patch21000: arm-omap-dt-compat.patch +Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch + +#rhbz #722509 +Patch21002: mmc-Always-check-for-lower-base-frequency-quirk-for-.patch + +#rhbz #735946 +Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch +Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch + +#rhbz 748691 +Patch21030: be2net-non-member-vlan-pkts-not-received-in-promisco.patch +Patch21031: benet-remove-bogus-unlikely-on-vlan-check.patch + +#rhbz 749166 +Patch21050: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch + +Patch21070: oom-fix-integer-overflow-of-points.patch + +#rhbz 706574 +Patch21071: WMI-properly-cleanup-devices-to-avoid-crashes.patch + +#rhbz 728607 +Patch21060: elantech.patch + +#rhbz 748210 +Patch21061: ideapad-Check-if-acpi-already-handle-backlight.patch + +#rhbz 731365 +Patch21062: mac80211-fix-remain_off_channel-regression.patch +Patch21063: mac80211-config-hw-when-going-back-on-channel.patch + +#rhbz752176 +Patch21080: sysfs-msi-irq-per-device.patch + +#backport brcm80211 from 3.2-rc1 +Patch21090: brcm80211.patch +%endif + +BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root + +%description +The kernel package contains the Linux kernel (vmlinuz), the core of any +Linux operating system. The kernel handles the basic functions +of the operating system: memory allocation, process allocation, device +input and output, etc. + + +%package doc +Summary: Various documentation bits found in the kernel source +Group: Documentation +%description doc +This package contains documentation files from the kernel +source. Various bits of information about the Linux kernel and the +device drivers shipped with it are documented in these files. + +You'll want to install this package if you need a reference to the +options that can be passed to Linux kernel modules at load time. + + +%package headers +Summary: Header files for the Linux kernel for use by glibc +Group: Development/System +Obsoletes: glibc-kernheaders < 3.0-46 +Provides: glibc-kernheaders = 3.0-46 +%description headers +Kernel-headers includes the C header files that specify the interface +between the Linux kernel and userspace libraries and programs. The +header files define structures and constants that are needed for +building most standard programs and are also needed for rebuilding the +glibc package. + +%package firmware +Summary: Firmware files used by the Linux kernel +Group: Development/System +# This is... complicated. +# Look at the WHENCE file. +License: GPL+ and GPLv2+ and MIT and Redistributable, no modification permitted +%if "x%{?variant}" != "x" +Provides: kernel-firmware = %{rpmversion}-%{pkg_release} +%endif +%description firmware +Kernel-firmware includes firmware files required for some devices to +operate. + +%package bootwrapper +Summary: Boot wrapper files for generating combined kernel + initrd images +Group: Development/System +Requires: gzip binutils +%description bootwrapper +Kernel-bootwrapper contains the wrapper code which makes bootable "zImage" +files combining both kernel and initial ramdisk. + +%package debuginfo-common-%{_target_cpu} +Summary: Kernel source files used by %{name}-debuginfo packages +Group: Development/Debug +%description debuginfo-common-%{_target_cpu} +This package is required by %{name}-debuginfo subpackages. +It provides the kernel source files common to all builds. + +%if %{with_tools} +%package -n kernel-tools +Summary: Assortment of tools for the Linux kernel +Group: Development/System +License: GPLv2 +Obsoletes: perf +Provides: perf +Provides: cpupowerutils = 1:009-0.6.p1 +Obsoletes: cpupowerutils < 1:009-0.6.p1 +Provides: cpufreq-utils = 1:009-0.6.p1 +Provides: cpufrequtils = 1:009-0.6.p1 +Obsoletes: cpufreq-utils < 1:009-0.6.p1 +Obsoletes: cpufrequtils < 1:009-0.6.p1 +Obsoletes: cpuspeed < 1:1.5-16 +%description -n kernel-tools +This package contains the tools/ directory from the kernel source +- the perf tool and the supporting documentation. + +%package -n kernel-tools-devel +Summary: Assortment of tools for the Linux kernel +Group: Development/System +License: GPLv2 +Requires: kernel-tools = %{version}-%{release} +Provides: cpupowerutils-devel = 1:009-0.6.p1 +Obsoletes: cpupowerutils-devel < 1:009-0.6.p1 +%description -n kernel-tools-devel +This package contains the development files for the tools/ directory from +the kernel source. + +%package -n kernel-tools-debuginfo +Summary: Debug information for package kernel-tools +Group: Development/Debug +Requires: %{name}-debuginfo-common-%{_target_cpu} = %{version}-%{release} +AutoReqProv: no +%description -n kernel-tools-debuginfo +This package provides debug information for package kernel-tools. + +# Note that this pattern only works right to match the .build-id +# symlinks because of the trailing nonmatching alternation and +# the leading .*, because of find-debuginfo.sh's buggy handling +# of matching the pattern against the symlinks file. +%{expand:%%global debuginfo_args %{?debuginfo_args} -p '.*%%{_bindir}/perf(\.debug)?|.*%%{_libexecdir}/perf-core/.*|.*%%{_bindir}/centrino-decode(\.debug)?|.*%%{_bindir}/powernow-k8-decode(\.debug)?|.*%%{_bindir}/cpupower(\.debug)?|.*%%{_libdir}/libcpupower.*|XXX' -o kernel-tools-debuginfo.list} +%endif + + +# +# This macro creates a kernel--debuginfo package. +# %%kernel_debuginfo_package +# +%define kernel_debuginfo_package() \ +%package %{?1:%{1}-}debuginfo\ +Summary: Debug information for package %{name}%{?1:-%{1}}\ +Group: Development/Debug\ +Requires: %{name}-debuginfo-common-%{_target_cpu} = %{version}-%{release}\ +Provides: %{name}%{?1:-%{1}}-debuginfo-%{_target_cpu} = %{version}-%{release}\ +AutoReqProv: no\ +%description -n %{name}%{?1:-%{1}}-debuginfo\ +This package provides debug information for package %{name}%{?1:-%{1}}.\ +This is required to use SystemTap with %{name}%{?1:-%{1}}-%{KVERREL}.\ +%{expand:%%global debuginfo_args %{?debuginfo_args} -p '/.*/%%{KVERREL}%{?1:\.%{1}}/.*|/.*%%{KVERREL}%{?1:\.%{1}}(\.debug)?' -o debuginfo%{?1}.list}\ +%{nil} + +# +# This macro creates a kernel--devel package. +# %%kernel_devel_package +# +%define kernel_devel_package() \ +%package %{?1:%{1}-}devel\ +Summary: Development package for building kernel modules to match the %{?2:%{2} }kernel\ +Group: System Environment/Kernel\ +Provides: kernel%{?1:-%{1}}-devel-%{_target_cpu} = %{version}-%{release}\ +Provides: kernel-devel-%{_target_cpu} = %{version}-%{release}%{?1:.%{1}}\ +Provides: kernel-devel = %{version}-%{release}%{?1:.%{1}}\ +Provides: kernel-devel-uname-r = %{KVERREL}%{?1:.%{1}}\ +AutoReqProv: no\ +Requires(pre): /usr/bin/find\ +Requires: perl\ +%description -n kernel%{?variant}%{?1:-%{1}}-devel\ +This package provides kernel headers and makefiles sufficient to build modules\ +against the %{?2:%{2} }kernel package.\ +%{nil} + +# +# This macro creates a kernel- and its -devel and -debuginfo too. +# %%define variant_summary The Linux kernel compiled for +# %%kernel_variant_package [-n ] +# +%define kernel_variant_package(n:) \ +%package %1\ +Summary: %{variant_summary}\ +Group: System Environment/Kernel\ +%kernel_reqprovconf\ +%{expand:%%kernel_devel_package %1 %{!?-n:%1}%{?-n:%{-n*}}}\ +%{expand:%%kernel_debuginfo_package %1}\ +%{nil} + + +# First the auxiliary packages of the main kernel package. +%kernel_devel_package +%kernel_debuginfo_package + + +# Now, each variant package. + +%define variant_summary The Linux kernel compiled for SMP machines +%kernel_variant_package -n SMP smp +%description smp +This package includes a SMP version of the Linux kernel. It is +required only on machines with two or more CPUs as well as machines with +hyperthreading technology. + +Install the kernel-smp package if your machine uses two or more CPUs. + + +%define variant_summary The Linux kernel compiled for PAE capable machines +%kernel_variant_package PAE +%description PAE +This package includes a version of the Linux kernel with support for up to +64GB of high memory. It requires a CPU with Physical Address Extensions (PAE). +The non-PAE kernel can only address up to 4GB of memory. +Install the kernel-PAE package if your machine has more than 4GB of memory. + + +%define variant_summary The Linux kernel compiled with extra debugging enabled for PAE capable machines +%kernel_variant_package PAEdebug +Obsoletes: kernel-PAE-debug +%description PAEdebug +This package includes a version of the Linux kernel with support for up to +64GB of high memory. It requires a CPU with Physical Address Extensions (PAE). +The non-PAE kernel can only address up to 4GB of memory. +Install the kernel-PAE package if your machine has more than 4GB of memory. + +This variant of the kernel has numerous debugging options enabled. +It should only be installed when trying to gather additional information +on kernel bugs, as some of these options impact performance noticably. + + +%define variant_summary The Linux kernel compiled with extra debugging enabled +%kernel_variant_package debug +%description debug +The kernel package contains the Linux kernel (vmlinuz), the core of any +Linux operating system. The kernel handles the basic functions +of the operating system: memory allocation, process allocation, device +input and output, etc. + +This variant of the kernel has numerous debugging options enabled. +It should only be installed when trying to gather additional information +on kernel bugs, as some of these options impact performance noticably. + + +%define variant_summary The Linux kernel compiled for TI-OMAP boards +%kernel_variant_package omap +%description omap +This package includes a version of the Linux kernel with support for +TI-OMAP based systems, i.e., BeagleBoard-xM. + +%define variant_summary The Linux kernel compiled for tegra boards +%kernel_variant_package tegra +%description tegra +This package includes a version of the Linux kernel with support for +nvidia tegra based systems, i.e., trimslice, ac-100. + + +%prep +# do a few sanity-checks for --with *only builds +%if %{with_baseonly} +%if !%{with_up}%{with_pae} +echo "Cannot build --with baseonly, up build is disabled" +exit 1 +%endif +%endif + +%if %{with_smponly} +%if !%{with_smp} +echo "Cannot build --with smponly, smp build is disabled" +exit 1 +%endif +%endif + +# more sanity checking; do it quietly +if [ "%{patches}" != "%%{patches}" ] ; then + for patch in %{patches} ; do + if [ ! -f $patch ] ; then + echo "ERROR: Patch ${patch##/*/} listed in specfile but is missing" + exit 1 + fi + done +fi 2>/dev/null + +patch_command='patch -p1 -F1 -s' +ApplyPatch() +{ + local patch=$1 + shift + if [ ! -f $RPM_SOURCE_DIR/$patch ]; then + exit 1 + fi +%if !%{using_upstream_branch} + if ! grep -E "^Patch[0-9]+: $patch\$" %{_specdir}/${RPM_PACKAGE_NAME%%%%%{?variant}}.spec ; then + if [ "${patch:0:8}" != "patch-3." ] ; then + echo "ERROR: Patch $patch not listed as a source patch in specfile" + exit 1 + fi + fi 2>/dev/null +%endif + case "$patch" in + *.bz2) bunzip2 < "$RPM_SOURCE_DIR/$patch" | $patch_command ${1+"$@"} ;; + *.gz) gunzip < "$RPM_SOURCE_DIR/$patch" | $patch_command ${1+"$@"} ;; + *) $patch_command ${1+"$@"} < "$RPM_SOURCE_DIR/$patch" ;; + esac +} + +# don't apply patch if it's empty +ApplyOptionalPatch() +{ + local patch=$1 + shift + if [ ! -f $RPM_SOURCE_DIR/$patch ]; then + exit 1 + fi + local C=$(wc -l $RPM_SOURCE_DIR/$patch | awk '{print $1}') + if [ "$C" -gt 9 ]; then + ApplyPatch $patch ${1+"$@"} + fi +} + +# we don't want a .config file when building firmware: it just confuses the build system +%define build_firmware \ + mv .config .config.firmware_save \ + make INSTALL_FW_PATH=$RPM_BUILD_ROOT/lib/firmware firmware_install \ + mv .config.firmware_save .config + +# First we unpack the kernel tarball. +# If this isn't the first make prep, we use links to the existing clean tarball +# which speeds things up quite a bit. + +# Update to latest upstream. +%if 0%{?released_kernel} +%define vanillaversion 3.%{base_sublevel} +# non-released_kernel case +%else +%if 0%{?rcrev} +%define vanillaversion 3.%{upstream_sublevel}-rc%{rcrev} +%if 0%{?gitrev} +%define vanillaversion 3.%{upstream_sublevel}-rc%{rcrev}-git%{gitrev} +%endif +%else +# pre-{base_sublevel+1}-rc1 case +%if 0%{?gitrev} +%define vanillaversion 3.%{base_sublevel}-git%{gitrev} +%else +%define vanillaversion 3.%{base_sublevel} +%endif +%endif +%endif + +# %%{vanillaversion} : the full version name, e.g. 2.6.35-rc6-git3 +# %%{kversion} : the base version, e.g. 2.6.34 + +# Use kernel-%%{kversion}%%{?dist} as the top-level directory name +# so we can prep different trees within a single git directory. + +# Build a list of the other top-level kernel tree directories. +# This will be used to hardlink identical vanilla subdirs. +sharedirs=$(find "$PWD" -maxdepth 1 -type d -name 'kernel-3.*' \ + | grep -x -v "$PWD"/kernel-%{kversion}%{?dist}) ||: + +if [ ! -d kernel-%{kversion}%{?dist}/vanilla-%{vanillaversion} ]; then + + if [ -d kernel-%{kversion}%{?dist}/vanilla-%{kversion} ]; then + + # The base vanilla version already exists. + cd kernel-%{kversion}%{?dist} + + # Any vanilla-* directories other than the base one are stale. + for dir in vanilla-*; do + [ "$dir" = vanilla-%{kversion} ] || rm -rf $dir & + done + + else + + rm -f pax_global_header + # Look for an identical base vanilla dir that can be hardlinked. + for sharedir in $sharedirs ; do + if [[ ! -z $sharedir && -d $sharedir/vanilla-%{kversion} ]] ; then + break + fi + done + if [[ ! -z $sharedir && -d $sharedir/vanilla-%{kversion} ]] ; then +%setup -q -n kernel-%{kversion}%{?dist} -c -T + cp -rl $sharedir/vanilla-%{kversion} . + else +%setup -q -n kernel-%{kversion}%{?dist} -c + mv linux-%{kversion} vanilla-%{kversion} + fi + + fi + +%if "%{kversion}" != "%{vanillaversion}" + + for sharedir in $sharedirs ; do + if [[ ! -z $sharedir && -d $sharedir/vanilla-%{vanillaversion} ]] ; then + break + fi + done + if [[ ! -z $sharedir && -d $sharedir/vanilla-%{vanillaversion} ]] ; then + + cp -rl $sharedir/vanilla-%{vanillaversion} . + + else + + # Need to apply patches to the base vanilla version. + cp -rl vanilla-%{kversion} vanilla-%{vanillaversion} + cd vanilla-%{vanillaversion} + +# Update vanilla to the latest upstream. +# (non-released_kernel case only) +%if 0%{?rcrev} + ApplyPatch patch-3.%{upstream_sublevel}-rc%{rcrev}.bz2 +%if 0%{?gitrev} + ApplyPatch patch-3.%{upstream_sublevel}-rc%{rcrev}-git%{gitrev}.bz2 +%endif +%else +# pre-{base_sublevel+1}-rc1 case +%if 0%{?gitrev} + ApplyPatch patch-3.%{base_sublevel}-git%{gitrev}.bz2 +%endif +%endif + + cd .. + + fi + +%endif + +else + + # We already have all vanilla dirs, just change to the top-level directory. + cd kernel-%{kversion}%{?dist} + +fi + +# Now build the fedora kernel tree. +if [ -d linux-%{kversion}.%{_target_cpu} ]; then + # Just in case we ctrl-c'd a prep already + rm -rf deleteme.%{_target_cpu} + # Move away the stale away, and delete in background. + mv linux-%{kversion}.%{_target_cpu} deleteme.%{_target_cpu} + rm -rf deleteme.%{_target_cpu} & +fi + +cp -rl vanilla-%{vanillaversion} linux-%{kversion}.%{_target_cpu} + +cd linux-%{kversion}.%{_target_cpu} + +# released_kernel with possible stable updates +%if 0%{?stable_base} +ApplyPatch %{stable_patch_00} +%endif +%if 0%{?stable_rc} +ApplyPatch %{stable_patch_01} +%endif + +%if %{using_upstream_branch} +### BRANCH APPLY ### +%endif + +# Drop some necessary files from the source dir into the buildroot +cp $RPM_SOURCE_DIR/config-* . +cp %{SOURCE15} . + +# Dynamically generate kernel .config files from config-* files +make -f %{SOURCE20} VERSION=%{version} configs + +%if %{?all_arch_configs:1}%{!?all_arch_configs:0} +#if a rhel kernel, apply the rhel config options +%if 0%{?rhel} + for i in %{all_arch_configs} + do + mv $i $i.tmp + ./merge.pl config-rhel-generic $i.tmp > $i + rm $i.tmp + done +%endif + +# Merge in any user-provided local config option changes +for i in %{all_arch_configs} +do + mv $i $i.tmp + ./merge.pl %{SOURCE1000} $i.tmp > $i + rm $i.tmp +done +%endif + +ApplyOptionalPatch git-linus.diff + +ApplyPatch linux-2.6-makefile-after_link.patch + +# +# misc small stuff to make things compile +# +ApplyOptionalPatch linux-2.6-compile-fixes.patch + +%if !%{nopatches} + +# revert patches from upstream that conflict or that we get via other means +ApplyOptionalPatch linux-2.6-upstream-reverts.patch -R + + +# Architecture patches +# x86(-64) + +# +# ARM +# +ApplyPatch arm-omap-dt-compat.patch +ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch + +ApplyPatch taint-vbox.patch +# +# NX Emulation +# +ApplyPatch linux-2.6-32bit-mmap-exec-randomization.patch +ApplyPatch linux-2.6-i386-nx-emulation.patch + +# +# bugfixes to drivers and filesystems +# + +# ext4 + +# xfs +ApplyPatch xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch + +# btrfs + + +# eCryptfs + +# NFSv4 + +# USB + +# WMI + +# ACPI +ApplyPatch linux-2.6-defaults-acpi-video.patch +ApplyPatch linux-2.6-acpi-video-dos.patch +ApplyPatch linux-2.6-acpi-debug-infinite-loop.patch +ApplyPatch acpi-ensure-thermal-limits-match-cpu-freq.patch +ApplyPatch acpi-sony-nonvs-blacklist.patch + +# Various low-impact patches to aid debugging. +ApplyPatch linux-2.6-debug-taint-vm.patch + +# +# PCI +# +# enable ASPM by default on hardware we expect to work +ApplyPatch linux-2.6-defaults-aspm.patch + +# +# SCSI Bits. +# + +# ACPI + +# ALSA + +# Networking + + +# Misc fixes +# The input layer spews crap no-one cares about. +ApplyPatch linux-2.6-input-kill-stupid-messages.patch + +# stop floppy.ko from autoloading during udev... +ApplyPatch die-floppy-die.patch +ApplyPatch floppy-drop-disable_hlt-warning.patch + +ApplyPatch linux-2.6.30-no-pcspkr-modalias.patch + +# Allow to use 480600 baud on 16C950 UARTs +ApplyPatch linux-2.6-serial-460800.patch + +# Silence some useless messages that still get printed with 'quiet' +ApplyPatch linux-2.6-silence-noise.patch + +# Make fbcon not show the penguins with 'quiet' +ApplyPatch linux-2.6-silence-fbcon-logo.patch + +# Changes to upstream defaults. + + +# /dev/crash driver. +ApplyPatch linux-2.6-crash-driver.patch + +# Hack e1000e to work on Montevina SDV +ApplyPatch linux-2.6-e1000-ich9-montevina.patch + +# crypto/ + +# Assorted Virt Fixes +ApplyPatch fix_xen_guest_on_old_EC2.patch + +# DRM core + +# Nouveau DRM +ApplyOptionalPatch drm-nouveau-updates.patch + +# Intel DRM +ApplyOptionalPatch drm-intel-next.patch +ApplyPatch drm-intel-make-lvds-work.patch +ApplyPatch drm-i915-fbc-stfu.patch +ApplyPatch drm-i915-sdvo-lvds-is-digital.patch + +ApplyPatch drm-lower-severity-radeon-lockup.diff + +ApplyPatch linux-2.6-intel-iommu-igfx.patch + +# silence the ACPI blacklist code +ApplyPatch linux-2.6-silence-acpi-blacklist.patch + +# V4L/DVB updates/fixes/experimental drivers +# apply if non-empty +ApplyOptionalPatch linux-2.6-v4l-dvb-fixes.patch +ApplyOptionalPatch linux-2.6-v4l-dvb-update.patch +ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch +#ApplyPatch linux-2.6-v4l-dvb-uvcvideo-update.patch + +# Patches headed upstream +ApplyPatch rcutree-avoid-false-quiescent-states.patch + +ApplyPatch disable-i8042-check-on-apple-mac.patch + +ApplyPatch add-appleir-usb-driver.patch + +ApplyPatch udlfb-bind-framebuffer-to-interface.patch +#ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch +#ApplyPatch epoll-fix-spurious-lockdep-warnings.patch +ApplyPatch epoll-limit-paths.patch +ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch +ApplyPatch block-stray-block-put-after-teardown.patch +ApplyPatch usb-add-quirk-for-logitech-webcams.patch + +#ApplyPatch crypto-register-cryptd-first.patch + +# rhbz#605888 +ApplyPatch dmar-disable-when-ricoh-multifunction.patch + +ApplyPatch revert-efi-rtclock.patch +ApplyPatch efi-dont-map-boot-services-on-32bit.patch + +#ApplyPatch add-macbookair41-keyboard.patch + +ApplyPatch hvcs_pi_buf_alloc.patch + +#ApplyPatch powerpc-Fix-deadlock-in-icswx-code.patch + +#ApplyPatch iwlagn-fix-ht_params-NULL-pointer-dereference.patch + +#rhbz #722509 +#ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch + +#ApplyPatch media-DiBcom-protect-the-I2C-bufer-access.patch +#ApplyPatch media-dib0700-protect-the-dib0700-buffer-access.patch +ApplyPatch media-dib0700-correct-error-message.patch + +# utrace. +ApplyPatch utrace.patch + +#rhbz #735946 +ApplyPatch 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch +ApplyPatch 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch + +#rhbz 748691 +ApplyPatch be2net-non-member-vlan-pkts-not-received-in-promisco.patch +ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch + +#rhbz 750402 +ApplyPatch oom-fix-integer-overflow-of-points.patch + +#rhbz 706574 +#ApplyPatch WMI-properly-cleanup-devices-to-avoid-crashes.patch + +#rhbz 728607 +ApplyPatch elantech.patch + +#rhbz 748210 +ApplyPatch ideapad-Check-if-acpi-already-handle-backlight.patch + +#rhbz 731365 +#ApplyPatch mac80211-fix-remain_off_channel-regression.patch +#ApplyPatch mac80211-config-hw-when-going-back-on-channel.patch + +#rhbz 752176 +ApplyPatch sysfs-msi-irq-per-device.patch + +#backport brcm80211 from 3.2-rc1 +ApplyPatch brcm80211.patch + +# END OF PATCH APPLICATIONS + +%endif + +# Any further pre-build tree manipulations happen here. + +chmod +x scripts/checkpatch.pl + +# This Prevents scripts/setlocalversion from mucking with our version numbers. +touch .scmversion + +# only deal with configs if we are going to build for the arch +%ifnarch %nobuildarches + +mkdir configs + +# Remove configs not for the buildarch +for cfg in kernel-%{version}-*.config; do + if [ `echo %{all_arch_configs} | grep -c $cfg` -eq 0 ]; then + rm -f $cfg + fi +done + +%if !%{debugbuildsenabled} +rm -f kernel-%{version}-*debug.config +%endif + +# now run oldconfig over all the config files +for i in *.config +do + mv $i .config + Arch=`head -1 .config | cut -b 3-` + make ARCH=$Arch listnewconfig | grep -E '^CONFIG_' >.newoptions || true +%if %{listnewconfig_fail} + if [ -s .newoptions ]; then + cat .newoptions + exit 1 + fi +%endif + rm -f .newoptions + make ARCH=$Arch oldnoconfig + echo "# $Arch" > configs/$i + cat .config >> configs/$i +done +# end of kernel config +%endif + +# get rid of unwanted files resulting from patch fuzz +find . \( -name "*.orig" -o -name "*~" \) -exec rm -f {} \; >/dev/null + +# remove unnecessary SCM files +find . -name .gitignore -exec rm -f {} \; >/dev/null + +cd .. + +### +### build +### +%build + +%if %{with_sparse} +%define sparse_mflags C=1 +%endif + +%if %{fancy_debuginfo} +# This override tweaks the kernel makefiles so that we run debugedit on an +# object before embedding it. When we later run find-debuginfo.sh, it will +# run debugedit again. The edits it does change the build ID bits embedded +# in the stripped object, but repeating debugedit is a no-op. We do it +# beforehand to get the proper final build ID bits into the embedded image. +# This affects the vDSO images in vmlinux, and the vmlinux image in bzImage. +export AFTER_LINK=\ +'sh -xc "/usr/lib/rpm/debugedit -b $$RPM_BUILD_DIR -d /usr/src/debug \ + -i $@ > $@.id"' +%endif + +cp_vmlinux() +{ + eu-strip --remove-comment -o "$2" "$1" +} + +BuildKernel() { + MakeTarget=$1 + KernelImage=$2 + Flavour=$3 + InstallName=${4:-vmlinuz} + + # Pick the right config file for the kernel we're building + Config=kernel-%{version}-%{_target_cpu}${Flavour:+-${Flavour}}.config + DevelDir=/usr/src/kernels/%{KVERREL}${Flavour:+.${Flavour}} + + # When the bootable image is just the ELF kernel, strip it. + # We already copy the unstripped file into the debuginfo package. + if [ "$KernelImage" = vmlinux ]; then + CopyKernel=cp_vmlinux + else + CopyKernel=cp + fi + + KernelVer=%{version}-%{release}.%{_target_cpu}${Flavour:+.${Flavour}} + echo BUILDING A KERNEL FOR ${Flavour} %{_target_cpu}... + + %if 0%{?stable_update} + # make sure SUBLEVEL is incremented on a stable release. Sigh 3.x. + perl -p -i -e "s/^SUBLEVEL.*/SUBLEVEL = %{?stablerev}/" Makefile + %endif + + # make sure EXTRAVERSION says what we want it to say + perl -p -i -e "s/^EXTRAVERSION.*/EXTRAVERSION = -%{release}.%{_target_cpu}${Flavour:+.${Flavour}}/" Makefile + + # if pre-rc1 devel kernel, must fix up PATCHLEVEL for our versioning scheme + %if !0%{?rcrev} + %if 0%{?gitrev} + perl -p -i -e 's/^PATCHLEVEL.*/PATCHLEVEL = %{upstream_sublevel}/' Makefile + %endif + %endif + + # and now to start the build process + + make -s mrproper + cp configs/$Config .config + + Arch=`head -1 .config | cut -b 3-` + echo USING ARCH=$Arch + + make -s ARCH=$Arch oldnoconfig >/dev/null + make -s ARCH=$Arch V=1 %{?_smp_mflags} $MakeTarget %{?sparse_mflags} + make -s ARCH=$Arch V=1 %{?_smp_mflags} modules %{?sparse_mflags} || exit 1 + + # Start installing the results +%if %{with_debuginfo} + mkdir -p $RPM_BUILD_ROOT%{debuginfodir}/boot + mkdir -p $RPM_BUILD_ROOT%{debuginfodir}/%{image_install_path} +%endif + mkdir -p $RPM_BUILD_ROOT/%{image_install_path} + install -m 644 .config $RPM_BUILD_ROOT/boot/config-$KernelVer + install -m 644 System.map $RPM_BUILD_ROOT/boot/System.map-$KernelVer + + # We estimate the size of the initramfs because rpm needs to take this size + # into consideration when performing disk space calculations. (See bz #530778) + dd if=/dev/zero of=$RPM_BUILD_ROOT/boot/initramfs-$KernelVer.img bs=1M count=20 + + if [ -f arch/$Arch/boot/zImage.stub ]; then + cp arch/$Arch/boot/zImage.stub $RPM_BUILD_ROOT/%{image_install_path}/zImage.stub-$KernelVer || : + fi + $CopyKernel $KernelImage \ + $RPM_BUILD_ROOT/%{image_install_path}/$InstallName-$KernelVer + chmod 755 $RPM_BUILD_ROOT/%{image_install_path}/$InstallName-$KernelVer + + mkdir -p $RPM_BUILD_ROOT/lib/modules/$KernelVer + # Override $(mod-fw) because we don't want it to install any firmware + # We'll do that ourselves with 'make firmware_install' + make -s ARCH=$Arch INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_install KERNELRELEASE=$KernelVer mod-fw= +%ifarch %{vdso_arches} + make -s ARCH=$Arch INSTALL_MOD_PATH=$RPM_BUILD_ROOT vdso_install KERNELRELEASE=$KernelVer + if [ ! -s ldconfig-kernel.conf ]; then + echo > ldconfig-kernel.conf "\ +# Placeholder file, no vDSO hwcap entries used in this kernel." + fi + %{__install} -D -m 444 ldconfig-kernel.conf \ + $RPM_BUILD_ROOT/etc/ld.so.conf.d/kernel-$KernelVer.conf +%endif + + # And save the headers/makefiles etc for building modules against + # + # This all looks scary, but the end result is supposed to be: + # * all arch relevant include/ files + # * all Makefile/Kconfig files + # * all script/ files + + rm -f $RPM_BUILD_ROOT/lib/modules/$KernelVer/build + rm -f $RPM_BUILD_ROOT/lib/modules/$KernelVer/source + mkdir -p $RPM_BUILD_ROOT/lib/modules/$KernelVer/build + (cd $RPM_BUILD_ROOT/lib/modules/$KernelVer ; ln -s build source) + # dirs for additional modules per module-init-tools, kbuild/modules.txt + mkdir -p $RPM_BUILD_ROOT/lib/modules/$KernelVer/extra + mkdir -p $RPM_BUILD_ROOT/lib/modules/$KernelVer/updates + # first copy everything + cp --parents `find -type f -name "Makefile*" -o -name "Kconfig*"` $RPM_BUILD_ROOT/lib/modules/$KernelVer/build + cp Module.symvers $RPM_BUILD_ROOT/lib/modules/$KernelVer/build + cp System.map $RPM_BUILD_ROOT/lib/modules/$KernelVer/build + if [ -s Module.markers ]; then + cp Module.markers $RPM_BUILD_ROOT/lib/modules/$KernelVer/build + fi + # then drop all but the needed Makefiles/Kconfig files + rm -rf $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/Documentation + rm -rf $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/scripts + rm -rf $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/include + cp .config $RPM_BUILD_ROOT/lib/modules/$KernelVer/build + cp -a scripts $RPM_BUILD_ROOT/lib/modules/$KernelVer/build + if [ -d arch/$Arch/scripts ]; then + cp -a arch/$Arch/scripts $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/arch/%{_arch} || : + fi + if [ -f arch/$Arch/*lds ]; then + cp -a arch/$Arch/*lds $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/arch/%{_arch}/ || : + fi + rm -f $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/scripts/*.o + rm -f $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/scripts/*/*.o +%ifarch ppc + cp -a --parents arch/powerpc/lib/crtsavres.[So] $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/ +%endif + if [ -d arch/%{asmarch}/include ]; then + cp -a --parents arch/%{asmarch}/include $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/ + fi + cp -a include $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/include + + # Make sure the Makefile and version.h have a matching timestamp so that + # external modules can be built + touch -r $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/Makefile $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/include/linux/version.h + touch -r $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/.config $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/include/linux/autoconf.h + # Copy .config to include/config/auto.conf so "make prepare" is unnecessary. + cp $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/.config $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/include/config/auto.conf + +%if %{fancy_debuginfo} + if test -s vmlinux.id; then + cp vmlinux.id $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/vmlinux.id + else + echo >&2 "*** ERROR *** no vmlinux build ID! ***" + exit 1 + fi +%endif + + # + # save the vmlinux file for kernel debugging into the kernel-debuginfo rpm + # +%if %{with_debuginfo} + mkdir -p $RPM_BUILD_ROOT%{debuginfodir}/lib/modules/$KernelVer + cp vmlinux $RPM_BUILD_ROOT%{debuginfodir}/lib/modules/$KernelVer +%endif + + find $RPM_BUILD_ROOT/lib/modules/$KernelVer -name "*.ko" -type f >modnames + + # mark modules executable so that strip-to-file can strip them + xargs --no-run-if-empty chmod u+x < modnames + + # Generate a list of modules for block and networking. + + grep -F /drivers/ modnames | xargs --no-run-if-empty nm -upA | + sed -n 's,^.*/\([^/]*\.ko\): *U \(.*\)$,\1 \2,p' > drivers.undef + + collect_modules_list() + { + sed -r -n -e "s/^([^ ]+) \\.?($2)\$/\\1/p" drivers.undef | + LC_ALL=C sort -u > $RPM_BUILD_ROOT/lib/modules/$KernelVer/modules.$1 + } + + collect_modules_list networking \ + 'register_netdev|ieee80211_register_hw|usbnet_probe|phy_driver_register|rt2x00(pci|usb)_probe' + collect_modules_list block \ + 'ata_scsi_ioctl|scsi_add_host|scsi_add_host_with_dma|blk_init_queue|register_mtd_blktrans|scsi_esp_register|scsi_register_device_handler' + collect_modules_list drm \ + 'drm_open|drm_init' + collect_modules_list modesetting \ + 'drm_crtc_init' + + # detect missing or incorrect license tags + rm -f modinfo + while read i + do + echo -n "${i#$RPM_BUILD_ROOT/lib/modules/$KernelVer/} " >> modinfo + /sbin/modinfo -l $i >> modinfo + done < modnames + + grep -E -v \ + 'GPL( v2)?$|Dual BSD/GPL$|Dual MPL/GPL$|GPL and additional rights$' \ + modinfo && exit 1 + + rm -f modinfo modnames + + # remove files that will be auto generated by depmod at rpm -i time + for i in alias alias.bin builtin.bin ccwmap dep dep.bin ieee1394map inputmap isapnpmap ofmap pcimap seriomap symbols symbols.bin usbmap + do + rm -f $RPM_BUILD_ROOT/lib/modules/$KernelVer/modules.$i + done + + # Move the devel headers out of the root file system + mkdir -p $RPM_BUILD_ROOT/usr/src/kernels + mv $RPM_BUILD_ROOT/lib/modules/$KernelVer/build $RPM_BUILD_ROOT/$DevelDir + ln -sf ../../..$DevelDir $RPM_BUILD_ROOT/lib/modules/$KernelVer/build + + # prune junk from kernel-devel + find $RPM_BUILD_ROOT/usr/src/kernels -name ".*.cmd" -exec rm -f {} \; +} + +### +# DO it... +### + +# prepare directories +rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT/boot +mkdir -p $RPM_BUILD_ROOT%{_libexecdir} + +cd linux-%{kversion}.%{_target_cpu} + +%if %{with_debug} +BuildKernel %make_target %kernel_image debug +%endif + +%if %{with_pae_debug} +BuildKernel %make_target %kernel_image PAEdebug +%endif + +%if %{with_pae} +BuildKernel %make_target %kernel_image PAE +%endif + +%if %{with_omap} +BuildKernel %make_target %kernel_image omap +%endif + +%if %{with_tegra} +BuildKernel %make_target %kernel_image tegra +%endif + +%if %{with_up} +BuildKernel %make_target %kernel_image +%endif + +%if %{with_smp} +BuildKernel %make_target %kernel_image smp +%endif + +%if %{with_tools} +# perf +make %{?_smp_mflags} -C tools/perf -s V=1 HAVE_CPLUS_DEMANGLE=1 prefix=%{_prefix} all +make %{?_smp_mflags} -C tools/perf -s V=1 prefix=%{_prefix} man || %{doc_build_fail} + +%ifarch %{cpupowerarchs} +# cpupower +# make sure version-gen.sh is executable. +chmod +x tools/power/cpupower/utils/version-gen.sh +make %{?_smp_mflags} -C tools/power/cpupower CPUFREQ_BENCH=false +%ifarch %{ix86} + cd tools/power/cpupower/debug/i386 + make %{?_smp_mflags} centrino-decode powernow-k8-decode + cd - +%endif +%ifarch x86_64 + cd tools/power/cpupower/debug/x86_64 + make %{?_smp_mflags} centrino-decode powernow-k8-decode + cd - +%endif +%endif +%endif + +%if %{with_doc} +# Make the HTML and man pages. +make htmldocs mandocs || %{doc_build_fail} + +# sometimes non-world-readable files sneak into the kernel source tree +chmod -R a=rX Documentation +find Documentation -type d | xargs chmod u+w +%endif + +### +### Special hacks for debuginfo subpackages. +### + +# This macro is used by %%install, so we must redefine it before that. +%define debug_package %{nil} + +%if %{fancy_debuginfo} +%define __debug_install_post \ + /usr/lib/rpm/find-debuginfo.sh %{debuginfo_args} %{_builddir}/%{?buildsubdir}\ +%{nil} +%endif + +%if %{with_debuginfo} +%ifnarch noarch +%global __debug_package 1 +%files -f debugfiles.list debuginfo-common-%{_target_cpu} +%defattr(-,root,root) +%endif +%endif + +### +### install +### + +%install + +cd linux-%{kversion}.%{_target_cpu} + +%if %{with_doc} +docdir=$RPM_BUILD_ROOT%{_datadir}/doc/kernel-doc-%{rpmversion} +man9dir=$RPM_BUILD_ROOT%{_datadir}/man/man9 + +# copy the source over +mkdir -p $docdir +tar -f - --exclude=man --exclude='.*' -c Documentation | tar xf - -C $docdir + +# Install man pages for the kernel API. +mkdir -p $man9dir +find Documentation/DocBook/man -name '*.9.gz' -print0 | +xargs -0 --no-run-if-empty %{__install} -m 444 -t $man9dir $m +ls $man9dir | grep -q '' || > $man9dir/BROKEN +%endif # with_doc + +# We have to do the headers install before the tools install because the +# kernel headers_install will remove any header files in /usr/include that +# it doesn't install itself. + +%if %{with_headers} +# Install kernel headers +make ARCH=%{hdrarch} INSTALL_HDR_PATH=$RPM_BUILD_ROOT/usr headers_install + +# Do headers_check but don't die if it fails. +make ARCH=%{hdrarch} INSTALL_HDR_PATH=$RPM_BUILD_ROOT/usr headers_check \ + > hdrwarnings.txt || : +if grep -q exist hdrwarnings.txt; then + sed s:^$RPM_BUILD_ROOT/usr/include/:: hdrwarnings.txt + # Temporarily cause a build failure if header inconsistencies. + # exit 1 +fi + +find $RPM_BUILD_ROOT/usr/include \ + \( -name .install -o -name .check -o \ + -name ..install.cmd -o -name ..check.cmd \) | xargs rm -f + +# glibc provides scsi headers for itself, for now +rm -rf $RPM_BUILD_ROOT/usr/include/scsi +rm -f $RPM_BUILD_ROOT/usr/include/asm*/atomic.h +rm -f $RPM_BUILD_ROOT/usr/include/asm*/io.h +rm -f $RPM_BUILD_ROOT/usr/include/asm*/irq.h +%endif + +%if %{with_tools} +# perf tool binary and supporting scripts/binaries +make -C tools/perf -s V=1 DESTDIR=$RPM_BUILD_ROOT HAVE_CPLUS_DEMANGLE=1 prefix=%{_prefix} install + +# perf man pages (note: implicit rpm magic compresses them later) +make -C tools/perf -s V=1 DESTDIR=$RPM_BUILD_ROOT HAVE_CPLUS_DEMANGLE=1 prefix=%{_prefix} install-man || %{doc_build_fail} + +%ifarch %{cpupowerarchs} +make -C tools/power/cpupower DESTDIR=$RPM_BUILD_ROOT libdir=%{_libdir} mandir=%{_mandir} CPUFREQ_BENCH=false install +rm -f %{buildroot}%{_libdir}/*.{a,la} +%find_lang cpupower +mv cpupower.lang ../ +%ifarch %{ix86} + cd tools/power/cpupower/debug/i386 + install -m755 centrino-decode %{buildroot}%{_bindir}/centrino-decode + install -m755 powernow-k8-decode %{buildroot}%{_bindir}/powernow-k8-decode + cd - +%endif +%ifarch x86_64 + cd tools/power/cpupower/debug/x86_64 + install -m755 centrino-decode %{buildroot}%{_bindir}/centrino-decode + install -m755 powernow-k8-decode %{buildroot}%{_bindir}/powernow-k8-decode + cd - +%endif +chmod 0755 %{buildroot}%{_libdir}/libcpupower.so* +mkdir -p %{buildroot}%{_unitdir} %{buildroot}%{_sysconfdir}/sysconfig +install -m644 %{SOURCE2000} %{buildroot}%{_unitdir}/cpupower.service +install -m644 %{SOURCE2001} %{buildroot}%{_sysconfdir}/sysconfig/cpupower +%endif + +%endif + +%if %{with_firmware} +%{build_firmware} +%endif + +%if %{with_bootwrapper} +make DESTDIR=$RPM_BUILD_ROOT bootwrapper_install WRAPPER_OBJDIR=%{_libdir}/kernel-wrapper WRAPPER_DTSDIR=%{_libdir}/kernel-wrapper/dts +%endif + + +### +### clean +### + +%clean +rm -rf $RPM_BUILD_ROOT + +### +### scripts +### + +%if %{with_tools} +%post -n kernel-tools +/sbin/ldconfig + +%postun -n kernel-tools +/sbin/ldconfig +%endif + +# +# This macro defines a %%post script for a kernel*-devel package. +# %%kernel_devel_post [] +# +%define kernel_devel_post() \ +%{expand:%%post %{?1:%{1}-}devel}\ +if [ -f /etc/sysconfig/kernel ]\ +then\ + . /etc/sysconfig/kernel || exit $?\ +fi\ +if [ "$HARDLINK" != "no" -a -x /usr/sbin/hardlink ]\ +then\ + (cd /usr/src/kernels/%{KVERREL}%{?1:.%{1}} &&\ + /usr/bin/find . -type f | while read f; do\ + hardlink -c /usr/src/kernels/*.fc*.*/$f $f\ + done)\ +fi\ +%{nil} + + +# This macro defines a %%posttrans script for a kernel package. +# %%kernel_variant_posttrans [] +# More text can follow to go at the end of this variant's %%post. +# +%define kernel_variant_posttrans() \ +%{expand:%%posttrans %{?1}}\ +/sbin/new-kernel-pkg --package kernel%{?-v:-%{-v*}} --mkinitrd --dracut --depmod --update %{KVERREL}%{?-v:.%{-v*}} || exit $?\ +/sbin/new-kernel-pkg --package kernel%{?1:-%{1}} --rpmposttrans %{KVERREL}%{?1:.%{1}} || exit $?\ +%{nil} + +# +# This macro defines a %%post script for a kernel package and its devel package. +# %%kernel_variant_post [-v ] [-r ] +# More text can follow to go at the end of this variant's %%post. +# +%define kernel_variant_post(v:r:) \ +%{expand:%%kernel_devel_post %{?-v*}}\ +%{expand:%%kernel_variant_posttrans %{?-v*}}\ +%{expand:%%post %{?-v*}}\ +%{-r:\ +if [ `uname -i` == "x86_64" -o `uname -i` == "i386" ] &&\ + [ -f /etc/sysconfig/kernel ]; then\ + /bin/sed -r -i -e 's/^DEFAULTKERNEL=%{-r*}$/DEFAULTKERNEL=kernel%{?-v:-%{-v*}}/' /etc/sysconfig/kernel || exit $?\ +fi}\ +%{expand:\ +/sbin/new-kernel-pkg --package kernel%{?-v:-%{-v*}} --install %{KVERREL}%{?-v:.%{-v*}} || exit $?\ +}\ +%{nil} + +# +# This macro defines a %%preun script for a kernel package. +# %%kernel_variant_preun +# +%define kernel_variant_preun() \ +%{expand:%%preun %{?1}}\ +/sbin/new-kernel-pkg --rminitrd --rmmoddep --remove %{KVERREL}%{?1:.%{1}} || exit $?\ +%{nil} + +%kernel_variant_preun +%kernel_variant_post -r kernel-smp + +%kernel_variant_preun smp +%kernel_variant_post -v smp + +%kernel_variant_preun PAE +%kernel_variant_post -v PAE -r (kernel|kernel-smp) + +%kernel_variant_preun debug +%kernel_variant_post -v debug + +%kernel_variant_post -v PAEdebug -r (kernel|kernel-smp) +%kernel_variant_preun PAEdebug + +%kernel_variant_preun omap +%kernel_variant_post -v omap + +%kernel_variant_preun tegra +%kernel_variant_post -v tegra + +if [ -x /sbin/ldconfig ] +then + /sbin/ldconfig -X || exit $? +fi + +### +### file lists +### + +%if %{with_headers} +%files headers +%defattr(-,root,root) +/usr/include/* +%endif + +%if %{with_firmware} +%files firmware +%defattr(-,root,root) +/lib/firmware/* +%doc linux-%{kversion}.%{_target_cpu}/firmware/WHENCE +%endif + +%if %{with_bootwrapper} +%files bootwrapper +%defattr(-,root,root) +/usr/sbin/* +%{_libdir}/kernel-wrapper +%endif + +# only some architecture builds need kernel-doc +%if %{with_doc} +%files doc +%defattr(-,root,root) +%{_datadir}/doc/kernel-doc-%{rpmversion}/Documentation/* +%dir %{_datadir}/doc/kernel-doc-%{rpmversion}/Documentation +%dir %{_datadir}/doc/kernel-doc-%{rpmversion} +%{_datadir}/man/man9/* +%endif + +%if %{with_tools} +%files -n kernel-tools -f cpupower.lang +%defattr(-,root,root) +%{_bindir}/perf +%dir %{_libexecdir}/perf-core +%{_libexecdir}/perf-core/* +%{_mandir}/man[1-8]/* + +%ifarch %{cpupowerarchs} +%{_bindir}/cpupower +%ifarch %{ix86} x86_64 +%{_bindir}/centrino-decode +%{_bindir}/powernow-k8-decode +%endif +%{_libdir}/libcpupower.so.0 +%{_libdir}/libcpupower.so.0.0.0 +%{_unitdir}/cpupower.service +%config(noreplace) %{_sysconfdir}/sysconfig/cpupower +%endif + +%if %{with_debuginfo} +%files -f kernel-tools-debuginfo.list -n kernel-tools-debuginfo +%defattr(-,root,root) +%endif + +%ifarch %{cpupowerarchs} +%files -n kernel-tools-devel +%{_libdir}/libcpupower.so +%{_includedir}/cpufreq.h +%endif +%endif + +# This is %%{image_install_path} on an arch where that includes ELF files, +# or empty otherwise. +%define elf_image_install_path %{?kernel_image_elf:%{image_install_path}} + +# +# This macro defines the %%files sections for a kernel package +# and its devel and debuginfo packages. +# %%kernel_variant_files [-k vmlinux] +# +%define kernel_variant_files(k:) \ +%if %{1}\ +%{expand:%%files %{?2}}\ +%defattr(-,root,root)\ +/%{image_install_path}/%{?-k:%{-k*}}%{!?-k:vmlinuz}-%{KVERREL}%{?2:.%{2}}\ +%attr(600,root,root) /boot/System.map-%{KVERREL}%{?2:.%{2}}\ +/boot/config-%{KVERREL}%{?2:.%{2}}\ +%dir /lib/modules/%{KVERREL}%{?2:.%{2}}\ +/lib/modules/%{KVERREL}%{?2:.%{2}}/kernel\ +/lib/modules/%{KVERREL}%{?2:.%{2}}/build\ +/lib/modules/%{KVERREL}%{?2:.%{2}}/source\ +/lib/modules/%{KVERREL}%{?2:.%{2}}/extra\ +/lib/modules/%{KVERREL}%{?2:.%{2}}/updates\ +%ifarch %{vdso_arches}\ +/lib/modules/%{KVERREL}%{?2:.%{2}}/vdso\ +/etc/ld.so.conf.d/kernel-%{KVERREL}%{?2:.%{2}}.conf\ +%endif\ +/lib/modules/%{KVERREL}%{?2:.%{2}}/modules.*\ +%ghost /boot/initramfs-%{KVERREL}%{?2:.%{2}}.img\ +%{expand:%%files %{?2:%{2}-}devel}\ +%defattr(-,root,root)\ +/usr/src/kernels/%{KVERREL}%{?2:.%{2}}\ +%if %{with_debuginfo}\ +%ifnarch noarch\ +%if %{fancy_debuginfo}\ +%{expand:%%files -f debuginfo%{?2}.list %{?2:%{2}-}debuginfo}\ +%else\ +%{expand:%%files %{?2:%{2}-}debuginfo}\ +%endif\ +%defattr(-,root,root)\ +%if !%{fancy_debuginfo}\ +%if "%{elf_image_install_path}" != ""\ +%{debuginfodir}/%{elf_image_install_path}/*-%{KVERREL}%{?2:.%{2}}.debug\ +%endif\ +%{debuginfodir}/lib/modules/%{KVERREL}%{?2:.%{2}}\ +%{debuginfodir}/usr/src/kernels/%{KVERREL}%{?2:.%{2}}\ +%endif\ +%endif\ +%endif\ +%endif\ +%{nil} + + +%kernel_variant_files %{with_up} +%kernel_variant_files %{with_smp} smp +%kernel_variant_files %{with_debug} debug +%kernel_variant_files %{with_pae} PAE +%kernel_variant_files %{with_pae_debug} PAEdebug +%kernel_variant_files %{with_omap} omap +%kernel_variant_files %{with_tegra} tegra + +# plz don't put in a version string unless you're going to tag +# and build. + +%changelog +* Wed Nov 09 2011 Chuck Ebbert 3.1.1-1.rc1 +- Linux 3.1.1-rc1 +- Comment out merged patches, will drop when release is final: + ums-realtek-driver-uses-stack-memory-for-DMA.patch + epoll-fix-spurious-lockdep-warnings.patch + crypto-register-cryptd-first.patch + add-macbookair41-keyboard.patch + powerpc-Fix-deadlock-in-icswx-code.patch + iwlagn-fix-ht_params-NULL-pointer-dereference.patch + mmc-Always-check-for-lower-base-frequency-quirk-for-.patch + media-DiBcom-protect-the-I2C-bufer-access.patch + media-dib0700-protect-the-dib0700-buffer-access.patch + WMI-properly-cleanup-devices-to-avoid-crashes.patch + mac80211-fix-remain_off_channel-regression.patch + mac80211-config-hw-when-going-back-on-channel.patch + +* Wed Nov 09 2011 John W. Linville +- Backport brcm80211 from 3.2-rc1 + +* Tue Nov 08 2011 Neil Horman +- Add msi irq ennumeration per device in sysfs (rhbz 752176) + +* Mon Nov 07 2011 Josh Boyer +- Add two patches to fix mac80211 issues (rhbz 731365) + +* Thu Nov 03 2011 Josh Boyer +- Add commits queued for 3.2 for elantech driver (rhbz 728607) +- Fix crash when setting brightness via Fn keys on ideapads (rhbz 748210) + +* Wed Nov 02 2011 Josh Boyer +- Add patch to fix oops when removing wmi module (rhbz 706574) + +* Tue Nov 01 2011 Dave Jones 3.1.0-8 +- allow building the perf rpm for ARM (rhbz 741325) + +* Tue Nov 01 2011 Dave Jones 3.1.0-8 +- Add another Sony laptop to the nonvs blacklist. (rhbz 641789) + +* Tue Nov 1 2011 Josh Boyer 3.1.0-7 +- Drop x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid (rhbz 748516) + +* Mon Oct 31 2011 Josh Boyer +- CVE-2011-4097: oom_badness() integer overflow (rhbz 750402) + +* Fri Oct 28 2011 Josh Boyer +- Add patch to prevent tracebacks on a warning in floppy.c (rhbz 749887) + +* Wed Oct 26 2011 Fedora Release Engineering - 3.1.0-5 +- Rebuilt for glibc bug#747377 + +* Wed Oct 26 2011 Josh Boyer +- CVE-2011-4077: xfs: potential buffer overflow in xfs_readlink() (rhbz 749166) + +* Tue Oct 25 2011 Josh Boyer +- CVE-2011-3347: be2net: promiscuous mode and non-member VLAN packets DoS (rhbz 748691) +- CVE-2011-1083: excessive in kernel CPU consumption when creating large nested epoll structures (rhbz 748668) + +* Mon Oct 24 2011 Josh Boyer +- Backport 3 fixed from linux-next to fix dib0700 playback (rhbz 733827) + +* Mon Oct 24 2011 Chuck Ebbert 3.1.0-1 +- Linux 3.1 + +* Fri Oct 21 2011 Chuck Ebbert 3.1.0-0.rc10.git1.1 +- Update to upstream HEAD (v3.1-rc10-42-g2efd7c0) + +* Fri Oct 21 2011 Dave Jones +- Lower severity of Radeon lockup messages. + +* Wed Oct 19 2011 Dave Jones +- Add Sony VGN-FW21E to nonvs blacklist. (rhbz 641789) + +* Wed Oct 19 2011 Chuck Ebbert 3.1.0-0.rc10.git0.1 +- Fix divide-by-zero in nouveau driver (rhbz #747129) + +* Tue Oct 18 2011 Chuck Ebbert +- Fix lock inversion causing hangs in 3.1-rc9 (rhbz #746485) +- Linux 3.1-rc10 + +* Tue Oct 18 2011 Josh Boyer +- Add patch to fix invalid EFI remap calls from Matt Fleming + +* Mon Oct 17 2011 Josh Boyer +- Add two patches to fix stalls in khugepaged (rhbz 735946) + +* Thu Oct 13 2011 Josh Boyer +- Update usb-add-quirk-for-logitech-webcams.patch with C600 ID (rhbz 742010) + +* Thu Oct 13 2011 Adam Jackson +- drm/i915: Treat SDVO LVDS as digital when parsing EDID (#729882) + +* Thu Oct 13 2011 Josh Boyer +- Add patch from Stanislaw Gruszka to fix iwlagn NULL dereference (rhbz 744155) + +* Tue Oct 11 2011 Josh Boyer +- Disable CONFIG_XEN_BALLOON_MEMORY_HOTPLUG (rhbz 744408) + +* Thu Oct 06 2011 Josh Boyer +- Add patch to fix base frequency check for Ricoh e823 devices (rhbz 722509) + +* Thu Oct 06 2011 Dave Jones +- Taint if virtualbox modules have been loaded. + +* Wed Oct 05 2011 Chuck Ebbert 3.1.0-0.rc9.git0.0 +- Linux 3.1-rc9 + +* Mon Oct 03 2011 Chuck Ebbert 3.1.0-0.rc8.git0.1 +- block: Free queue resources at blk_release_queue() + +* Thu Sep 29 2011 Chuck Ebbert +- Require grubby >= 8.3-1 so initrd line gets added (rhbz #725185) + +* Thu Sep 29 2011 Josh Boyer +- Update logitech USB quirk patch + +* Tue Sep 27 2011 Chuck Ebbert 3.1.0-0.rc8.git0.0 +- Linux 3.1-rc8 +- New option: CONFIG_ARM_ERRATA_764369 is not set +- Fix up utrace.patch to apply after commit f9d81f61c + +* Thu Sep 22 2011 Dave Jones +- Make CONFIG_XEN_PLATFORM_PCI=y (rhbz 740664) + +* Thu Sep 22 2011 Dennis Gilmore +- build vmlinux image for sparc64 + +* Wed Sep 21 2011 Josh Boyer +- Linux 3.1-rc7 + +* Tue Sep 20 2011 Dave Jones +- Limit 32-bit x86 kernels to 32 processors. + +* Tue Sep 20 2011 Ben Skeggs 3.1.0-0.rc6.git0.4.fc16 +- nouveau: patch in updates queued for 3.2, mostly new hw support (GF116/GF119) + +* Fri Sep 16 2011 Josh Boyer 3.1.0-0.rc6.git0.3.fc16 +- Add patch to fix deadlock in ipw2x00 (rhbz 738387) +- Fixup kernel-tools file section for ppc/ppc64 + +* Thu Sep 15 2011 Josh Boyer +- CVE-2011-3191: cifs: fix possible memory corruption in CIFSFindNext + +* Wed Sep 14 2011 Josh Boyer +- Add patch to fix deadlock in ppc64 icswx (rhbz 737984) + +* Wed Sep 14 2011 Neil Horman +- Enable CONFIG_IP_VS_IPV6 (bz 738194) + +* Wed Sep 14 2011 Josh Boyer +- Add support for Macbook Air 4,1 keyboard, trackpad, and bluetooth +- Add patch to fix HVCS on ppc64 (rhbz 738096) +- Add various ibmveth driver fixes (rhbz 733766) + +* Tue Sep 13 2011 Adam Jackson +- drm/i915: Shut the fbc messages up when drm.debug & 4 + +* Mon Sep 12 2011 Josh Boyer 3.1.0-0.rc6.git0.0 +- Linux 3.1-rc6 (contains the fix for 737076) +- Disable debug builds + +* Fri Sep 09 2011 Josh Boyer +- Change to 64K page size for ppc64 kernels (rhbz 736751) + +* Fri Sep 09 2011 Josh Boyer 3.1.0-0.rc5.git0.0 +- Linux 3.1-rc5 + +* Wed Sep 07 2011 Josh Boyer +- Add patch to fix oops when linking entities in ucvideo (rhbz 735437) + +* Fri Sep 02 2011 Dave Jones +- Apply patch to fix lockdep reports from ext4 (rhbz 732572) + +* Thu Sep 01 2011 Dave Jones +- utrace: s390: fix the compile problem with traps.c (rhbz 735118) + +* Tue Aug 30 2011 Dave Jones +- Revert "x86: Serialize EFI time accesses on rtc_lock" (rhbz 732755) + +* Tue Aug 30 2011 Josh Boyer +- Add patch to fix rhbz 606017 + +* Mon Aug 29 2011 Josh Boyer +- Linux 3.1-rc4 + +* Sat Aug 27 2011 Dave Jones +- Fix get_gate_vma usage in i386 NX emulation +- Bring back the 32bit mmap randomization patch for now. + NX emulation is still too dependant upon it. + +* Fri Aug 26 2011 Dave Jones +- Enable CONFIG_DETECT_HUNG_TASK for debug builds & rawhide. + +* Fri Aug 26 2011 Dave Jones +- Drop linux-2.6-debug-vm-would-have-oomkilled.patch + The oom-killer heuristics have improved enough that this should + never be necessary (and it probably doesn't dtrt any more) + +* Fri Aug 26 2011 Dave Jones +- Drop linux-2.6-32bit-mmap-exec-randomization.patch + Outlived it's usefulness (and made of ugly) + +* Fri Aug 26 2011 Dave Jones +- Drop acpi-ec-add-delay-before-write.patch (rhbz 733690) + +* Fri Aug 26 2011 Josh Boyer +- Linux 3.1-rc3-git5 + +* Wed Aug 24 2011 Josh Boyer +- Revert 'iwlwifi: advertise max aggregate size'. (rhbz 708747) + +* Mon Aug 22 2011 Josh Boyer +- Linux 3.1-rc3 +- Add patch to fix duplicate backlight registration (rhbz 732202) + +* Mon Aug 22 2011 Dave Jones +- Avoid false quiescent states in rcutree with CONFIG_RCU_FAST_NO_HZ. (rhbz 577968) + +* Sat Aug 20 2011 Josh Boyer +- Linux 3.1-rc2-git7 +- Add a provides/obsoletes for cpupowerutils-devel + +* Fri Aug 19 2011 Josh Boyer +- Add patch from upstream to fix 64-bit divide error in btrfs +- Add BuildRequires on gettext for cpupowerutils translations + +* Fri Aug 19 2011 Josh Boyer +- Linux 3.1-rc2-git5 +- Change XHCI to builtin (rhbz 731706) +- Add patch to fix race between cryptd and aesni (rhbz 721002) + +* Thu Aug 18 2011 Josh Boyer +- Adjust provides/obsoletes to replace the cpupowerutils package + +* Wed Aug 17 2011 Josh Boyer +- Create the kernel-tools subpackages based on a start by davej + +* Tue Aug 16 2011 Dave Jones +- Prepare for packaging more of tools/ by renaming 'perf' subpackage + to kernel-tools + +* Tue Aug 16 2011 Dennis Gilmore +- add config for arm tegra devices +- setup kernel to build omap image (patch from David Marlin) +- setup kernel to build tegra image based on omap work +- add arm device tree patches + +* Sat Aug 13 2011 Dave Jones +- CPU_FREQ drivers should now be built-in on x86-64. + +* Thu Aug 11 2011 Josh Boyer +- Add patch davej applied to f15 for rhbz 729340 +- Add munged together patch for rhbz 729269 +- Build ide_pmac as a module (rhbz 730039) + +* Tue Aug 09 2011 Josh Boyer +- Add Makefile.config and ARM config changes from David Marlin + +* Tue Aug 09 2011 Josh Boyer +- Add patch davej applied to f15 for rhbz 728872 + +* Tue Aug 09 2011 Dave Jones +- ptrace_report_syscall: check if TIF_SYSCALL_EMU is defined + +* Tue Aug 09 2011 Dave Jones +- Enable CONFIG_SAMSUNG_LAPTOP (rhbz 729363) + +* Mon Aug 08 2011 Josh Boyer +- Bring in utrace fixes davej applied to f15. (rhbz 728379) + +* Fri Aug 05 2011 Josh Boyer +- Adjust Makefile munging for new 3.x numbering scheme + +* Fri Aug 05 2011 Dave Jones +- Deselect CONFIG_DECNET. Unmaintained, and rubbish. + +* Fri Aug 05 2011 Josh Boyer +- 3.0.1 + +* Fri Aug 05 2011 Josh Boyer +- Add patch for rhbz 726701 from Matthew Garrett + +* Thu Aug 04 2011 Dave Jones +- Drop neuter_intel_microcode_load.patch (rhbz 690930) + +* Wed Aug 03 2011 John W. Linville +- Disable CONFIG_BCMA since no driver currently uses it (rhbz 727796) + +* Wed Aug 03 2011 Josh Boyer +- Add patch to fix backtrace in cdc_ncm driver (rhbz 720128) +- Add patch to fix backtrace in usm-realtek driver (rhbz 720054) + +* Tue Aug 02 2011 Josh Boyer +- Add patch to fix HFSPlus filesystem mounting (rhbz 720771) + +* Tue Aug 02 2011 Dave Jones +- Change USB_SERIAL_OPTION back to modular. (rhbz 727680) + +* Tue Aug 02 2011 Josh Boyer +- Fix epoll recursive lockdep warnings (rhbz 722472) +- Turn debug builds back on + +* Tue Aug 02 2011 Josh Boyer +- Add change from Yanko Kaneti to get the rt2x00 drivers in modules.networking + (rhbz 708314) + +* Fri Jul 29 2011 Dave Jones +- Fix scsi_dispatch_cmd oops (USB eject problems, etc). + +* Thu Jul 28 2011 Dave Jones +- module-init-tools needs to be a prereq, not a conflict. + +* Thu Jul 28 2011 Josh Boyer +- Backport patch to correct udlfb removal events (rhbz 726163) + +* Wed Jul 27 2011 Dave Jones +- Turn off debug builds. + +* Fri Jul 22 2011 Dave Jones +- bootwrapper needs objcopy. Add it to requires: (wwoods) + +* Fri Jul 22 2011 Kyle McMartin 3.0.0-1 +- Linux 3.0, but really 3.0.0 (sigh) + +* Thu Jul 21 2011 Chuck Ebbert 3.0-0.rc7.git10.1 +- 3.0-rc7-git10 +- Use ext4 for ext2 and ext3 filesystems (CONFIG_EXT4_USE_FOR_EXT23=y) + +* Thu Jul 21 2011 Dave Jones +- Switch BLK_DEV_RAM to be modular (rhbz 720833) + +* Wed Jul 20 2011 Chuck Ebbert 3.0-0.rc7.git8.1 +- 3.0-rc7-git8 + +* Fri Jul 15 2011 Dave Jones 3.0-0.rc7.git3.1 +- 3.0-rc7-git3 + +* Fri Jul 15 2011 Dave Jones +- Bring back utrace until uprobes gets merged upstream. + +* Wed Jul 13 2011 Kyle McMartin 3.0-0.rc7.git1.1 +- Update to snapshot 3.0-rc7-git1 for intel drm fixes. + +* Tue Jul 12 2011 John W. Linville +- zd1211rw: fix invalid signal values from device (rhbz 720093) + +* Tue Jul 12 2011 John W. Linville +- rt2x00: Add device ID for RT539F device. (rhbz 720594) + +* Tue Jul 12 2011 Kyle McMartin 3.0-0.rc7.git0.1 +- Linux 3.0-rc7, hopefully the last before the Great Renumbering becomes + official. + +* Mon Jul 11 2011 Dave Jones +- Change BINFMT_MISC to be modular. (rhbz 695415) + +* Sun Jul 10 2011 Kyle McMartin 3.0-0.rc6.git6.1 +- Linux 3.0-rc6-git6 +- iwlagn-fix-dma-direction.patch: drop. +- Revert CONFIG_X86_RESERVE_LOW=640, it breaks booting on x86_64. + +* Thu Jul 07 2011 Dave Jones +- Centralise CPU_FREQ options into config-generic. + Switch to using ondemand by default. (rhbz 713572) + +* Wed Jul 06 2011 Chuck Ebbert +- Set CONFIG_X86_RESERVE_LOW=640 as requested by mjg + +* Mon Jul 04 2011 Kyle McMartin 3.0-0.rc6.git0.1 +- Linux 3.0-rc6 +- [generic] SCSI_ISCI=m, because why not + +* Sat Jul 02 2011 Kyle McMartin 3.0-0.rc5.git5.1 +- Linux 3.0-rc5-git5 + +* Mon Jun 27 2011 Kyle McMartin 3.0-0.rc5.git0.1 +- Linux 3.0-rc5 + +* Mon Jun 27 2011 Dave Jones +- Disable CONFIG_CRYPTO_MANAGER_DISABLE_TESTS, as this also disables FIPS (rhbz 716942) + +* Thu Jun 23 2011 Kyle McMartin 3.0-0.rc4.git3.1 +- Linux 3.0-rc4-git3 +- Drop linux-3.0-fix-uts-release.patch, and instead just perl the Makefile +- linux-2.6-silence-noise.patch: fix context +- iwlagn-fix-dma-direction.patch: fix DMAR errors (for me at least) + +* Wed Jun 22 2011 Kyle McMartin 3.0-0.rc4.git0.2 +- Re-enable debuginfo generation. Thanks to Richard Jones for noticing... no + wonder builds had been so quick lately. + +* Tue Jun 21 2011 Kyle McMartin 3.0-0.rc4.git0.1 +- Linux 3.0-rc4 (getting closer...) + +* Fri Jun 17 2011 Kyle McMartin 3.0-0.rc3.git6.1 +- Update to 3.0-rc3-git6 + +* Fri Jun 17 2011 Dave Jones +- drop qcserial 'compile fix' that was just duplicating an include. +- drop struct sizeof debug patch. (no real value. not upstreamable) +- drop linux-2.6-debug-always-inline-kzalloc.patch. + Can't recall why this was added. Can easily re-add if deemed necessary. + +* Fri Jun 17 2011 Kyle McMartin +- linux-2.6-defaults-pci_no_msi.patch: drop, haven't toggled the default + in many moons. +- linux-2.6-defaults-pci_use_crs.patch: ditto. +- linux-2.6-selinux-mprotect-checks.patch: upstream a while ago. +- drm-i915-gen4-has-non-power-of-two-strides.patch: drop buggy bugfix +- drop some more unapplied crud. +- We haven't applied firewire patches in a dogs age. + +* Fri Jun 17 2011 Kyle McMartin 3.0-0.rc3.git5.1 +- Try updating to a git snapshot for the first time in 3.0-rc, + update to 3.0-rc3-git5 +- Fix a subtle bug I introduced in 3.0-rc1, "patch-3." is 9 letters, not 10. + +* Thu Jun 16 2011 Kyle McMartin +- Disable mm patches which had been submitted against 2.6.39, as Rik reports + they seem to aggravate a VM_BUG_ON. More investigation is necessary. + +* Wed Jun 15 2011 Kyle McMartin +- Conflict with pre-3.2.1-5 versions of mdadm. (#710646) + +* Wed Jun 15 2011 Kyle McMartin +- Build in aesni-intel on i686 for symmetry with 64-bit. + +* Tue Jun 14 2011 Kyle McMartin 3.0-0.rc3.git0.3 +- Fix libdm conflict (whose bright idea was it to give subpackages differing + version numbers?) + +* Tue Jun 14 2011 Kyle McMartin +- Update to 3.0-rc3, add another conflicts to deal with 2 digit + versions (libdm.) +- Simplify linux-3.0-fix-uts-release.patch now that SUBLEVEL is optional. +- revert-ftrace-remove-unnecessary-disabling-of-irqs.patch: drop upstreamed + patch. +- drm-intel-eeebox-eb1007-quirk.patch: ditto. +- ath5k-disable-fast-channel-switching-by-default.patch: ditto. + +* Thu Jun 09 2011 Kyle McMartin +- ath5k-disable-fast-channel-switching-by-default.patch (rhbz#709122) + (korgbz#34992) [a99168ee in wireless-next] + +* Thu Jun 09 2011 Kyle McMartin 3.0-0.rc2.git0.2 +- rhbz#710921: revert-ftrace-remove-unnecessary-disabling-of-irqs.patch + +* Wed Jun 08 2011 Kyle McMartin 3.0-0.rc2.git0.1 +- Update to 3.0-rc2, rebase utsname fix. +- Build IPv6 into the kernel for a variety of reasons + (http://lists.fedoraproject.org/pipermail/kernel/2011-June/003105.html) + +* Mon Jun 06 2011 Kyle McMartin 3.0-0.rc1.git0.3 +- Conflict with module-init-tools older than 3.13 to ensure the + 3.0 transition is handled correctly. + +* Wed Jun 01 2011 Kyle McMartin 3.0-0.rc1.git0.2 +- Fix utsname for 3.0-rc1 + +* Mon May 30 2011 Kyle McMartin 3.0-0.rc1.git0.1 +- Linux 3.0-rc1 (won't build until module-init-tools gets an update.) + +* Mon May 30 2011 Kyle McMartin +- Trimmed changelog, see fedpkg git for earlier history. + +### +# The following Emacs magic makes C-c C-e use UTC dates. +# Local Variables: +# rpm-change-log-uses-utc: t +# End: +### diff --git a/samsung-laptop-brightness-fixes-3.2.patch b/samsung-laptop-brightness-fixes-3.2.patch new file mode 100644 index 000000000..61032176b --- /dev/null +++ b/samsung-laptop-brightness-fixes-3.2.patch @@ -0,0 +1,238 @@ +From: Jason Stubbs +Date: Tue, 20 Sep 2011 16:16:13 +0000 (-0700) +Subject: Platform: Brightness quirk for samsung laptop driver +X-Git-Tag: v3.2-rc1~111^2~41 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=ac080523141d5bfa5f60ef2436480f645f915e9c + +Platform: Brightness quirk for samsung laptop driver + +On some Samsung laptops the brightness regulation works slightly different. +All SABI commands except for set_brightness work as expected. The behaviour +of set_brightness is as follows: + +- Setting a new brightness will only step one level toward the new brightness + level. For example, setting a level of 5 when the current level is 2 will + result in a brightness level of 3. +- A spurious KEY_BRIGHTNESS_UP or KEY_BRIGHTNESS_DOWN event is also generated + along with the change in brightness. +- Neither of the above two issues occur when changing from/to brightness + level 0. + +This patch adds detection and a non-intrusive workaround for the above issues. + +Signed-off-by: Jason Stubbs +Tested-by: David Herrmann +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Matthew Garrett +--- + +diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c +index 4d3bed4..6474e42 100644 +--- a/drivers/platform/x86/samsung-laptop.c ++++ b/drivers/platform/x86/samsung-laptop.c +@@ -226,6 +226,7 @@ static struct backlight_device *backlight_device; + static struct mutex sabi_mutex; + static struct platform_device *sdev; + static struct rfkill *rfk; ++static bool has_stepping_quirk; + + static int force; + module_param(force, bool, 0); +@@ -382,6 +383,17 @@ static void set_brightness(u8 user_brightness) + { + u8 user_level = user_brightness + sabi_config->min_brightness; + ++ if (has_stepping_quirk && user_level != 0) { ++ /* ++ * short circuit if the specified level is what's already set ++ * to prevent the screen from flickering needlessly ++ */ ++ if (user_brightness == read_brightness()) ++ return; ++ ++ sabi_set_command(sabi_config->commands.set_brightness, 0); ++ } ++ + sabi_set_command(sabi_config->commands.set_brightness, user_level); + } + +@@ -390,6 +402,34 @@ static int get_brightness(struct backlight_device *bd) + return (int)read_brightness(); + } + ++static void check_for_stepping_quirk(void) ++{ ++ u8 initial_level = read_brightness(); ++ u8 check_level; ++ ++ /* ++ * Some laptops exhibit the strange behaviour of stepping toward ++ * (rather than setting) the brightness except when changing to/from ++ * brightness level 0. This behaviour is checked for here and worked ++ * around in set_brightness. ++ */ ++ ++ if (initial_level <= 2) ++ check_level = initial_level + 2; ++ else ++ check_level = initial_level - 2; ++ ++ has_stepping_quirk = false; ++ set_brightness(check_level); ++ ++ if (read_brightness() != check_level) { ++ has_stepping_quirk = true; ++ pr_info("enabled workaround for brightness stepping quirk\n"); ++ } ++ ++ set_brightness(initial_level); ++} ++ + static int update_status(struct backlight_device *bd) + { + set_brightness(bd->props.brightness); +@@ -805,6 +845,9 @@ static int __init samsung_init(void) + } + } + ++ /* Check for stepping quirk */ ++ check_for_stepping_quirk(); ++ + /* knock up a platform device to hang stuff off of */ + sdev = platform_device_register_simple("samsung", -1, NULL, 0); + if (IS_ERR(sdev)) +From: Jason Stubbs +Date: Tue, 20 Sep 2011 16:16:14 +0000 (-0700) +Subject: Platform: Samsung laptop DMI info for NC210/NC110 +X-Git-Tag: v3.2-rc1~111^2~40 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=7b3c257ce4267e004a7c7e68c05d1eb70da8c972 + +Platform: Samsung laptop DMI info for NC210/NC110 + +This patch just adds the DMI info for the samsung laptop driver to work with +the NC210/NC110. It needs the brightness quirk patch for proper support. + +Signed-off-by: Jason Stubbs +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Matthew Garrett +--- + +diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c +index 6474e42..8ffab50 100644 +--- a/drivers/platform/x86/samsung-laptop.c ++++ b/drivers/platform/x86/samsung-laptop.c +@@ -737,6 +737,15 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { + }, + .callback = dmi_check_cb, + }, ++ { ++ .ident = "NC210/NC110", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"), ++ DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"), ++ }, ++ .callback = dmi_check_cb, ++ }, + { }, + }; + MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); +From: Raul Gutierrez Segales +Date: Tue, 20 Sep 2011 16:16:15 +0000 (-0700) +Subject: Platform: fix samsung-laptop DMI identification for N220 model +X-Git-Tag: v3.2-rc1~111^2~39 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=f689c875c13c9d62b3c4de09cd5dad66549f700d + +Platform: fix samsung-laptop DMI identification for N220 model + +This is a follow-up for commit 78a7539b, which didn't cover the +Samsung N220 laptop. With this backlight brightness works nicely +on the N220 netbook. + +Signed-off-by: Raul Gutierrez Segales +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Matthew Garrett +--- + +diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c +index 8ffab50..1e436eb 100644 +--- a/drivers/platform/x86/samsung-laptop.c ++++ b/drivers/platform/x86/samsung-laptop.c +@@ -663,6 +663,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { + .callback = dmi_check_cb, + }, + { ++ .ident = "N220", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, ++ "SAMSUNG ELECTRONICS CO., LTD."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "N220"), ++ DMI_MATCH(DMI_BOARD_NAME, "N220"), ++ }, ++ .callback = dmi_check_cb, ++ }, ++ { + .ident = "N150/N210/N220/N230", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, +From: John Serock +Date: Thu, 13 Oct 2011 10:42:01 +0000 (-0400) +Subject: Platform: Detect samsung laptop quirk when initial level is zero +X-Git-Tag: v3.2-rc1~111^2~29 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=ba05b237372bad82533d1f717569d1d817ff3c27 + +Platform: Detect samsung laptop quirk when initial level is zero + +This patch depends on the "Platform: Brightness quirk for samsung +laptop driver" patch from Jason Stubbs. This patch adds a check for an +initial brightness level of 0; if the level is 0, this patch changes +the brightness level to 1 before the driver attempts to detect the +brightness quirk. + +The Samsung N150 netbook experiences the brightness quirk. Without +Jason's patch, the only brightness levels available on the N150 are 0, +1, and 8. This patch ensures that, when the initial brightness level +is 0, the samsang-laptop driver detects the brightness quirk on the +N150, thereby making brightness levels 0 through 8 available. + +Signed-off-by: John Serock +Acked-by: Jason Stubbs +Signed-off-by: Matthew Garrett +--- + +diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c +index 1e436eb..31ddd57 100644 +--- a/drivers/platform/x86/samsung-laptop.c ++++ b/drivers/platform/x86/samsung-laptop.c +@@ -404,8 +404,9 @@ static int get_brightness(struct backlight_device *bd) + + static void check_for_stepping_quirk(void) + { +- u8 initial_level = read_brightness(); ++ u8 initial_level; + u8 check_level; ++ u8 orig_level = read_brightness(); + + /* + * Some laptops exhibit the strange behaviour of stepping toward +@@ -414,6 +415,11 @@ static void check_for_stepping_quirk(void) + * around in set_brightness. + */ + ++ if (orig_level == 0) ++ set_brightness(1); ++ ++ initial_level = read_brightness(); ++ + if (initial_level <= 2) + check_level = initial_level + 2; + else +@@ -427,7 +433,7 @@ static void check_for_stepping_quirk(void) + pr_info("enabled workaround for brightness stepping quirk\n"); + } + +- set_brightness(initial_level); ++ set_brightness(orig_level); + } + + static int update_status(struct backlight_device *bd) From 1e1645a5275c945043678ec901cda3fc49bbf671 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 10 Nov 2011 22:05:16 -0500 Subject: [PATCH 134/487] remove stray .orig file --- kernel.spec.orig | 2620 ---------------------------------------------- 1 file changed, 2620 deletions(-) delete mode 100644 kernel.spec.orig diff --git a/kernel.spec.orig b/kernel.spec.orig deleted file mode 100644 index 5ae046555..000000000 --- a/kernel.spec.orig +++ /dev/null @@ -1,2620 +0,0 @@ -# We have to override the new %%install behavior because, well... the kernel is special. -%global __spec_install_pre %{___build_pre} - -Summary: The Linux kernel - -# For a stable, released kernel, released_kernel should be 1. For rawhide -# and/or a kernel built from an rc or git snapshot, released_kernel should -# be 0. -%global released_kernel 1 - -# Save original buildid for later if it's defined -%if 0%{?buildid:1} -%global orig_buildid %{buildid} -%undefine buildid -%endif - -################################################################### -# Polite request for people who spin their own kernel rpms: -# please modify the "buildid" define in a way that identifies -# that the kernel isn't the stock distribution kernel, for example, -# by setting the define to ".local" or ".bz123456". This will be -# appended to the full kernel version. -# -# (Uncomment the '#' and both spaces below to set the buildid.) -# -# % define buildid .local -################################################################### - -# The buildid can also be specified on the rpmbuild command line -# by adding --define="buildid .whatever". If both the specfile and -# the environment define a buildid they will be concatenated together. -%if 0%{?orig_buildid:1} -%if 0%{?buildid:1} -%global srpm_buildid %{buildid} -%define buildid %{srpm_buildid}%{orig_buildid} -%else -%define buildid %{orig_buildid} -%endif -%endif - -# baserelease defines which build revision of this kernel version we're -# building. We used to call this fedora_build, but the magical name -# baserelease is matched by the rpmdev-bumpspec tool, which you should use. -# -# We used to have some extra magic weirdness to bump this automatically, -# but now we don't. Just use: rpmdev-bumpspec -c 'comment for changelog' -# When changing base_sublevel below or going from rc to a final kernel, -# reset this by hand to 1 (or to 0 and then use rpmdev-bumpspec). -# scripts/rebase.sh should be made to do that for you, actually. -# -# For non-released -rc kernels, this will be prepended with "0.", so -# for example a 3 here will become 0.3 -# -%global baserelease 1 -%global fedora_build %{baserelease} - -# base_sublevel is the kernel version we're starting with and patching -# on top of -- for example, 2.6.22-rc7-git1 starts with a 2.6.21 base, -# which yields a base_sublevel of 21. -%define base_sublevel 1 - -## If this is a released kernel ## -%if 0%{?released_kernel} - -# Do we have a -stable update to apply? -%define stable_update 1 -# Is it a -stable RC? -%define stable_rc 1 -# Set rpm version accordingly -%if 0%{?stable_update} -%define stablerev %{stable_update} -%define stable_base %{stable_update} -%if 0%{?stable_rc} -# stable RCs are incremental patches, so we need the previous stable patch -%define stable_base %(echo $((%{stable_update} - 1))) -%endif -%endif -%define rpmversion 3.%{base_sublevel}.%{stable_update} - -## The not-released-kernel case ## -%else -# The next upstream release sublevel (base_sublevel+1) -%define upstream_sublevel %(echo $((%{base_sublevel} + 1))) -# The rc snapshot level -%define rcrev 10 -# The git snapshot level -%define gitrev 1 -# Set rpm version accordingly -%define rpmversion 3.%{upstream_sublevel}.0 -%endif -# Nb: The above rcrev and gitrev values automagically define Patch00 and Patch01 below. - -# What parts do we want to build? We must build at least one kernel. -# These are the kernels that are built IF the architecture allows it. -# All should default to 1 (enabled) and be flipped to 0 (disabled) -# by later arch-specific checks. - -# The following build options are enabled by default. -# Use either --without in your rpmbuild command or force values -# to 0 in here to disable them. -# -# standard kernel -%define with_up %{?_without_up: 0} %{?!_without_up: 1} -# kernel-smp (only valid for ppc 32-bit) -%define with_smp %{?_without_smp: 0} %{?!_without_smp: 1} -# kernel-PAE (only valid for i686) -%define with_pae %{?_without_pae: 0} %{?!_without_pae: 1} -# kernel-debug -%define with_debug %{?_without_debug: 0} %{?!_without_debug: 1} -# kernel-doc -%define with_doc %{?_without_doc: 0} %{?!_without_doc: 1} -# kernel-headers -%define with_headers %{?_without_headers: 0} %{?!_without_headers: 1} -# kernel-firmware -%define with_firmware %{?_with_firmware: 1} %{?!_with_firmware: 0} -# tools -%define with_tools %{?_without_tools: 0} %{?!_without_tools: 1} -# kernel-debuginfo -%define with_debuginfo %{?_without_debuginfo: 0} %{?!_without_debuginfo: 1} -# kernel-bootwrapper (for creating zImages from kernel + initrd) -%define with_bootwrapper %{?_without_bootwrapper: 0} %{?!_without_bootwrapper: 1} -# Want to build a the vsdo directories installed -%define with_vdso_install %{?_without_vdso_install: 0} %{?!_without_vdso_install: 1} -# ARM OMAP (Beagle/Panda Board) -%define with_omap %{?_without_omap: 0} %{?!_without_omap: 1} -# kernel-tegra (only valid for arm) -%define with_tegra %{?_without_tegra: 0} %{?!_without_tegra: 1} - -# Build the kernel-doc package, but don't fail the build if it botches. -# Here "true" means "continue" and "false" means "fail the build". -%if 0%{?released_kernel} -%define doc_build_fail false -%else -%define doc_build_fail true -%endif - -%define rawhide_skip_docs 0 -%if 0%{?rawhide_skip_docs} -%define with_doc 0 -%define doc_build_fail true -%endif - -# Additional options for user-friendly one-off kernel building: -# -# Only build the base kernel (--with baseonly): -%define with_baseonly %{?_with_baseonly: 1} %{?!_with_baseonly: 0} -# Only build the smp kernel (--with smponly): -%define with_smponly %{?_with_smponly: 1} %{?!_with_smponly: 0} -# Only build the pae kernel (--with paeonly): -%define with_paeonly %{?_with_paeonly: 1} %{?!_with_paeonly: 0} -# Only build the debug kernel (--with dbgonly): -%define with_dbgonly %{?_with_dbgonly: 1} %{?!_with_dbgonly: 0} - -# should we do C=1 builds with sparse -%define with_sparse %{?_with_sparse: 1} %{?!_with_sparse: 0} - -# Set debugbuildsenabled to 1 for production (build separate debug kernels) -# and 0 for rawhide (all kernels are debug kernels). -# See also 'make debug' and 'make release'. -%define debugbuildsenabled 1 - -# Want to build a vanilla kernel build without any non-upstream patches? -%define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} - -# pkg_release is what we'll fill in for the rpm Release: field -%if 0%{?released_kernel} - -%if 0%{?stable_rc} -%define stable_rctag .rc%{stable_rc} -%endif -%define pkg_release %{fedora_build}%{?stable_rctag}%{?buildid}%{?dist} - -%else - -# non-released_kernel -%if 0%{?rcrev} -%define rctag .rc%rcrev -%else -%define rctag .rc0 -%endif -%if 0%{?gitrev} -%define gittag .git%gitrev -%else -%define gittag .git0 -%endif -%define pkg_release 0%{?rctag}%{?gittag}.%{fedora_build}%{?buildid}%{?dist} - -%endif - -# The kernel tarball/base version -%define kversion 3.%{base_sublevel} - -%define make_target bzImage - -%define KVERREL %{version}-%{release}.%{_target_cpu} -%define hdrarch %_target_cpu -%define asmarch %_target_cpu - -%if 0%{!?nopatches:1} -%define nopatches 0 -%endif - -%if %{with_vanilla} -%define nopatches 1 -%endif - -%if %{nopatches} -%define with_bootwrapper 0 -%define variant -vanilla -%else -%define variant_fedora -fedora -%endif - -%define using_upstream_branch 0 -%if 0%{?upstream_branch:1} -%define stable_update 0 -%define using_upstream_branch 1 -%define variant -%{upstream_branch}%{?variant_fedora} -%define pkg_release 0.%{fedora_build}%{upstream_branch_tag}%{?buildid}%{?dist} -%endif - -%if !%{debugbuildsenabled} -%define with_debug 0 -%endif - -%if !%{with_debuginfo} -%define _enable_debug_packages 0 -%endif -%define debuginfodir /usr/lib/debug - -# kernel-PAE is only built on i686. -%ifnarch i686 -%define with_pae 0 -%endif - -# kernel-tegra and omap is only built on armv7 hard and softfp -%ifnarch armv7hl armv7l -%define with_tegra 0 -%define with_omap 0 -%endif - -# if requested, only build base kernel -%if %{with_baseonly} -%define with_smp 0 -%define with_pae 0 -%define with_debug 0 -%endif - -# if requested, only build smp kernel -%if %{with_smponly} -%define with_up 0 -%define with_pae 0 -%define with_debug 0 -%endif - -# if requested, only build pae kernel -%if %{with_paeonly} -%define with_up 0 -%define with_smp 0 -%define with_debug 0 -%endif - -# if requested, only build debug kernel -%if %{with_dbgonly} -%if %{debugbuildsenabled} -%define with_up 0 -%define with_pae 0 -%endif -%define with_smp 0 -%define with_pae 0 -%define with_tools 0 -%endif - -%define all_x86 i386 i686 - -%if %{with_vdso_install} -# These arches install vdso/ directories. -%define vdso_arches %{all_x86} x86_64 ppc ppc64 -%endif - -# Overrides for generic default options - -# only ppc and alphav56 need separate smp kernels -%ifnarch ppc alphaev56 -%define with_smp 0 -%endif - -# don't do debug builds on anything but i686 and x86_64 -%ifnarch i686 x86_64 -%define with_debug 0 -%endif - -# only package docs noarch -%ifnarch noarch -%define with_doc 0 -%endif - -# don't build noarch kernels or headers (duh) -%ifarch noarch -%define with_up 0 -%define with_headers 0 -%define with_tools 0 -%define all_arch_configs kernel-%{version}-*.config -%define with_firmware %{?_with_firmware: 1} %{?!_with_firmware: 0} -%endif - -# bootwrapper is only on ppc -%ifnarch ppc ppc64 -%define with_bootwrapper 0 -%endif - -# sparse blows up on ppc64 alpha and sparc64 -%ifarch ppc64 ppc alpha sparc64 -%define with_sparse 0 -%endif - -# Per-arch tweaks - -%ifarch %{all_x86} -%define asmarch x86 -%define hdrarch i386 -%define all_arch_configs kernel-%{version}-i?86*.config -%define image_install_path boot -%define kernel_image arch/x86/boot/bzImage -%endif - -%ifarch x86_64 -%define asmarch x86 -%define all_arch_configs kernel-%{version}-x86_64*.config -%define image_install_path boot -%define kernel_image arch/x86/boot/bzImage -%endif - -%ifarch ppc64 -%define asmarch powerpc -%define hdrarch powerpc -%define all_arch_configs kernel-%{version}-ppc64*.config -%define image_install_path boot -%define make_target vmlinux -%define kernel_image vmlinux -%define kernel_image_elf 1 -%endif - -%ifarch s390x -%define asmarch s390 -%define hdrarch s390 -%define all_arch_configs kernel-%{version}-s390x.config -%define image_install_path boot -%define make_target image -%define kernel_image arch/s390/boot/image -%define with_tools 0 -%endif - -%ifarch sparc64 -%define asmarch sparc -%define all_arch_configs kernel-%{version}-sparc64*.config -%define make_target vmlinux -%define kernel_image vmlinux -%define image_install_path boot -%define with_tools 0 -%endif - -%ifarch sparcv9 -%define hdrarch sparc -%endif - -%ifarch ppc -%define asmarch powerpc -%define hdrarch powerpc -%define all_arch_configs kernel-%{version}-ppc{-,.}*config -%define image_install_path boot -%define make_target vmlinux -%define kernel_image vmlinux -%define kernel_image_elf 1 -%endif - -%ifarch ia64 -%define all_arch_configs kernel-%{version}-ia64*.config -%define image_install_path boot/efi/EFI/redhat -%define make_target compressed -%define kernel_image vmlinux.gz -%endif - -%ifarch alpha alphaev56 -%define all_arch_configs kernel-%{version}-alpha*.config -%define image_install_path boot -%define make_target vmlinux -%define kernel_image vmlinux -%endif - -%ifarch %{arm} -%define all_arch_configs kernel-%{version}-arm*.config -%define image_install_path boot -%define asmarch arm -%define hdrarch arm -%define make_target bzImage -%define kernel_image arch/arm/boot/zImage -# we build a up kernel on armv5tel. its used for qemu. -%ifnarch armv5tel -%define with_up 0 -%define with_perf 0 -%endif -# we only build headers on the base arm arches -# just like we used to only build them on i386 for x86 -%ifnarch armv5tel armv7hl -%define with_headers 0 -%endif -%endif - -%if %{nopatches} -# XXX temporary until last vdso patches are upstream -%define vdso_arches ppc ppc64 -%endif - -# Should make listnewconfig fail if there's config options -# printed out? -%if %{nopatches}%{using_upstream_branch} -%define listnewconfig_fail 0 -%else -%define listnewconfig_fail 1 -%endif - -# To temporarily exclude an architecture from being built, add it to -# %%nobuildarches. Do _NOT_ use the ExclusiveArch: line, because if we -# don't build kernel-headers then the new build system will no longer let -# us use the previous build of that package -- it'll just be completely AWOL. -# Which is a BadThing(tm). - -# We only build kernel-headers on the following... -%define nobuildarches i386 s390 sparc sparcv9 - -%ifarch %nobuildarches -%define with_up 0 -%define with_smp 0 -%define with_pae 0 -%define with_debuginfo 0 -%define with_tools 0 -%define _enable_debug_packages 0 -%endif - -%define with_pae_debug 0 -%if %{with_pae} -%define with_pae_debug %{with_debug} -%endif - -# Architectures we build tools/cpupower on -%define cpupowerarchs %{ix86} x86_64 ppc ppc64 - -# -# Three sets of minimum package version requirements in the form of Conflicts: -# to versions below the minimum -# - -# -# First the general kernel 2.6 required versions as per -# Documentation/Changes -# -%define kernel_dot_org_conflicts ppp < 2.4.3-3, isdn4k-utils < 3.2-32, nfs-utils < 1.0.7-12, e2fsprogs < 1.37-4, util-linux < 2.12, jfsutils < 1.1.7-2, reiserfs-utils < 3.6.19-2, xfsprogs < 2.6.13-4, procps < 3.2.5-6.3, oprofile < 0.9.1-2, device-mapper-libs < 1.02.63-2, mdadm < 3.2.1-5 - -# -# Then a series of requirements that are distribution specific, either -# because we add patches for something, or the older versions have -# problems with the newer kernel or lack certain things that make -# integration in the distro harder than needed. -# -%define package_conflicts initscripts < 7.23, udev < 063-6, iptables < 1.3.2-1, ipw2200-firmware < 2.4, iwl4965-firmware < 228.57.2, selinux-policy-targeted < 1.25.3-14, squashfs-tools < 4.0, wireless-tools < 29-3 - -# We moved the drm include files into kernel-headers, make sure there's -# a recent enough libdrm-devel on the system that doesn't have those. -%define kernel_headers_conflicts libdrm-devel < 2.4.0-0.15 - -# -# Packages that need to be installed before the kernel is, because the %%post -# scripts use them. -# -%define kernel_prereq fileutils, module-init-tools >= 3.16-2, initscripts >= 8.11.1-1, grubby >= 8.3-1 -%define initrd_prereq dracut >= 001-7 - -# -# This macro does requires, provides, conflicts, obsoletes for a kernel package. -# %%kernel_reqprovconf -# It uses any kernel__conflicts and kernel__obsoletes -# macros defined above. -# -%define kernel_reqprovconf \ -Provides: kernel = %{rpmversion}-%{pkg_release}\ -Provides: kernel-%{_target_cpu} = %{rpmversion}-%{pkg_release}%{?1:.%{1}}\ -Provides: kernel-drm = 4.3.0\ -Provides: kernel-drm-nouveau = 16\ -Provides: kernel-modeset = 1\ -Provides: kernel-uname-r = %{KVERREL}%{?1:.%{1}}\ -Requires(pre): %{kernel_prereq}\ -Requires(pre): %{initrd_prereq}\ -%if %{with_firmware}\ -Requires(pre): kernel-firmware >= %{rpmversion}-%{pkg_release}\ -%else\ -Requires(pre): linux-firmware >= 20100806-2\ -%endif\ -Requires(post): /sbin/new-kernel-pkg\ -Requires(preun): /sbin/new-kernel-pkg\ -Conflicts: %{kernel_dot_org_conflicts}\ -Conflicts: %{package_conflicts}\ -%{expand:%%{?kernel%{?1:_%{1}}_conflicts:Conflicts: %%{kernel%{?1:_%{1}}_conflicts}}}\ -%{expand:%%{?kernel%{?1:_%{1}}_obsoletes:Obsoletes: %%{kernel%{?1:_%{1}}_obsoletes}}}\ -%{expand:%%{?kernel%{?1:_%{1}}_provides:Provides: %%{kernel%{?1:_%{1}}_provides}}}\ -# We can't let RPM do the dependencies automatic because it'll then pick up\ -# a correct but undesirable perl dependency from the module headers which\ -# isn't required for the kernel proper to function\ -AutoReq: no\ -AutoProv: yes\ -%{nil} - -Name: kernel%{?variant} -Group: System Environment/Kernel -License: GPLv2 -URL: http://www.kernel.org/ -Version: %{rpmversion} -Release: %{pkg_release} -# DO NOT CHANGE THE 'ExclusiveArch' LINE TO TEMPORARILY EXCLUDE AN ARCHITECTURE BUILD. -# SET %%nobuildarches (ABOVE) INSTEAD -ExclusiveArch: noarch %{all_x86} x86_64 ppc ppc64 ia64 %{sparc} s390 s390x alpha alphaev56 %{arm} -ExclusiveOS: Linux - -%kernel_reqprovconf - -# -# List the packages used during the kernel build -# -BuildRequires: module-init-tools, patch >= 2.5.4, bash >= 2.03, sh-utils, tar -BuildRequires: bzip2, findutils, gzip, m4, perl, make >= 3.78, diffutils, gawk -BuildRequires: gcc >= 3.4.2, binutils >= 2.12, redhat-rpm-config -BuildRequires: net-tools -BuildRequires: xmlto, asciidoc -%if %{with_sparse} -BuildRequires: sparse >= 0.4.1 -%endif -%if %{with_tools} -BuildRequires: elfutils-devel zlib-devel binutils-devel newt-devel python-devel perl(ExtUtils::Embed) pciutils-devel gettext -%endif -BuildConflicts: rhbuildsys(DiskFree) < 500Mb - -%define fancy_debuginfo 0 -%if %{with_debuginfo} -%if 0%{?fedora} >= 8 || 0%{?rhel} >= 6 -%define fancy_debuginfo 1 -%endif -%endif - -%if %{fancy_debuginfo} -# Fancy new debuginfo generation introduced in Fedora 8. -BuildRequires: rpm-build >= 4.4.2.1-4 -%define debuginfo_args --strict-build-id -%endif - -Source0: ftp://ftp.kernel.org/pub/linux/kernel/v3.0/linux-%{kversion}.tar.bz2 - -Source11: genkey -Source14: find-provides -Source15: merge.pl - -Source20: Makefile.config -Source21: config-debug -Source22: config-nodebug -Source23: config-generic -Source24: config-rhel-generic - -Source30: config-x86-generic -Source31: config-i686-PAE -Source32: config-x86-32-generic - -Source40: config-x86_64-generic - -Source50: config-powerpc-generic -Source51: config-powerpc32-generic -Source52: config-powerpc32-smp -Source53: config-powerpc64 - -Source60: config-ia64-generic - -Source70: config-s390x - -Source90: config-sparc64-generic - -Source100: config-arm-generic -Source110: config-arm-omap-generic -Source111: config-arm-tegra - -# This file is intentionally left empty in the stock kernel. Its a nicety -# added for those wanting to do custom rebuilds with altered config opts. -Source1000: config-local - -# Sources for kernel-tools -Source2000: cpupower.service -Source2001: cpupower.config - -# Here should be only the patches up to the upstream canonical Linus tree. - -# For a stable release kernel -%if 0%{?stable_update} -%if 0%{?stable_base} -%define stable_patch_00 patch-3.%{base_sublevel}.%{stable_base}.bz2 -Patch00: %{stable_patch_00} -%endif -%if 0%{?stable_rc} -%define stable_patch_01 patch-3.%{base_sublevel}.%{stable_update}-rc%{stable_rc}.bz2 -Patch01: %{stable_patch_01} -%endif - -# non-released_kernel case -# These are automagically defined by the rcrev and gitrev values set up -# near the top of this spec file. -%else -%if 0%{?rcrev} -Patch00: patch-3.%{upstream_sublevel}-rc%{rcrev}.bz2 -%if 0%{?gitrev} -Patch01: patch-3.%{upstream_sublevel}-rc%{rcrev}-git%{gitrev}.bz2 -%endif -%else -# pre-{base_sublevel+1}-rc1 case -%if 0%{?gitrev} -Patch00: patch-3.%{base_sublevel}-git%{gitrev}.bz2 -%endif -%endif -%endif - -%if %{using_upstream_branch} -### BRANCH PATCH ### -%endif - -Patch02: git-linus.diff - -# we also need compile fixes for -vanilla -Patch04: linux-2.6-compile-fixes.patch - -# build tweak for build ID magic, even for -vanilla -Patch05: linux-2.6-makefile-after_link.patch - -%if !%{nopatches} - - -# revert upstream patches we get via other methods -Patch09: linux-2.6-upstream-reverts.patch -# Git trees. - -# Standalone patches - -Patch100: taint-vbox.patch -Patch160: linux-2.6-32bit-mmap-exec-randomization.patch -Patch161: linux-2.6-i386-nx-emulation.patch - -Patch202: linux-2.6-debug-taint-vm.patch - -Patch383: linux-2.6-defaults-aspm.patch - -Patch390: linux-2.6-defaults-acpi-video.patch -Patch391: linux-2.6-acpi-video-dos.patch -Patch394: linux-2.6-acpi-debug-infinite-loop.patch -Patch395: acpi-ensure-thermal-limits-match-cpu-freq.patch -Patch396: acpi-sony-nonvs-blacklist.patch - -Patch450: linux-2.6-input-kill-stupid-messages.patch -Patch452: linux-2.6.30-no-pcspkr-modalias.patch - -Patch460: linux-2.6-serial-460800.patch - -Patch470: die-floppy-die.patch -Patch471: floppy-drop-disable_hlt-warning.patch - -Patch510: linux-2.6-silence-noise.patch -Patch530: linux-2.6-silence-fbcon-logo.patch - -Patch700: linux-2.6-e1000-ich9-montevina.patch - -Patch800: linux-2.6-crash-driver.patch - -# crypto/ - -# virt + ksm patches -Patch1500: fix_xen_guest_on_old_EC2.patch - -# DRM - -# nouveau + drm fixes -Patch1810: drm-nouveau-updates.patch -# intel drm is all merged upstream -Patch1824: drm-intel-next.patch -# make sure the lvds comes back on lid open -Patch1825: drm-intel-make-lvds-work.patch -# hush the i915 fbc noise -Patch1826: drm-i915-fbc-stfu.patch -# rhbz#729882, https://bugs.freedesktop.org/attachment.cgi?id=49069 -Patch1827: drm-i915-sdvo-lvds-is-digital.patch - -Patch1850: drm-lower-severity-radeon-lockup.diff - -Patch1900: linux-2.6-intel-iommu-igfx.patch - -# Quiet boot fixes -# silence the ACPI blacklist code -Patch2802: linux-2.6-silence-acpi-blacklist.patch - -# media patches -Patch2899: linux-2.6-v4l-dvb-fixes.patch -Patch2900: linux-2.6-v4l-dvb-update.patch -Patch2901: linux-2.6-v4l-dvb-experimental.patch -Patch2902: linux-2.6-v4l-dvb-uvcvideo-update.patch - -Patch2903: media-DiBcom-protect-the-I2C-bufer-access.patch -Patch2904: media-dib0700-protect-the-dib0700-buffer-access.patch -Patch2905: media-dib0700-correct-error-message.patch - -Patch3000: rcutree-avoid-false-quiescent-states.patch - -# fs fixes - -# NFSv4 - -# patches headed upstream -Patch12010: add-appleir-usb-driver.patch - -Patch12016: disable-i8042-check-on-apple-mac.patch - -Patch12021: udlfb-bind-framebuffer-to-interface.patch - -Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch -Patch12024: epoll-fix-spurious-lockdep-warnings.patch -Patch12025: rcu-avoid-just-onlined-cpu-resched.patch -Patch12026: block-stray-block-put-after-teardown.patch -Patch12027: usb-add-quirk-for-logitech-webcams.patch -Patch12029: crypto-register-cryptd-first.patch -Patch12030: epoll-limit-paths.patch - -Patch12303: dmar-disable-when-ricoh-multifunction.patch - -Patch13002: revert-efi-rtclock.patch -Patch13003: efi-dont-map-boot-services-on-32bit.patch - -Patch13007: add-macbookair41-keyboard.patch - -Patch13009: hvcs_pi_buf_alloc.patch - -Patch13013: powerpc-Fix-deadlock-in-icswx-code.patch - -Patch13014: iwlagn-fix-ht_params-NULL-pointer-dereference.patch - -Patch20000: utrace.patch - -# Flattened devicetree support -Patch21000: arm-omap-dt-compat.patch -Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch - -#rhbz #722509 -Patch21002: mmc-Always-check-for-lower-base-frequency-quirk-for-.patch - -#rhbz #735946 -Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch -Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch - -#rhbz 748691 -Patch21030: be2net-non-member-vlan-pkts-not-received-in-promisco.patch -Patch21031: benet-remove-bogus-unlikely-on-vlan-check.patch - -#rhbz 749166 -Patch21050: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch - -Patch21070: oom-fix-integer-overflow-of-points.patch - -#rhbz 706574 -Patch21071: WMI-properly-cleanup-devices-to-avoid-crashes.patch - -#rhbz 728607 -Patch21060: elantech.patch - -#rhbz 748210 -Patch21061: ideapad-Check-if-acpi-already-handle-backlight.patch - -#rhbz 731365 -Patch21062: mac80211-fix-remain_off_channel-regression.patch -Patch21063: mac80211-config-hw-when-going-back-on-channel.patch - -#rhbz752176 -Patch21080: sysfs-msi-irq-per-device.patch - -#backport brcm80211 from 3.2-rc1 -Patch21090: brcm80211.patch -%endif - -BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root - -%description -The kernel package contains the Linux kernel (vmlinuz), the core of any -Linux operating system. The kernel handles the basic functions -of the operating system: memory allocation, process allocation, device -input and output, etc. - - -%package doc -Summary: Various documentation bits found in the kernel source -Group: Documentation -%description doc -This package contains documentation files from the kernel -source. Various bits of information about the Linux kernel and the -device drivers shipped with it are documented in these files. - -You'll want to install this package if you need a reference to the -options that can be passed to Linux kernel modules at load time. - - -%package headers -Summary: Header files for the Linux kernel for use by glibc -Group: Development/System -Obsoletes: glibc-kernheaders < 3.0-46 -Provides: glibc-kernheaders = 3.0-46 -%description headers -Kernel-headers includes the C header files that specify the interface -between the Linux kernel and userspace libraries and programs. The -header files define structures and constants that are needed for -building most standard programs and are also needed for rebuilding the -glibc package. - -%package firmware -Summary: Firmware files used by the Linux kernel -Group: Development/System -# This is... complicated. -# Look at the WHENCE file. -License: GPL+ and GPLv2+ and MIT and Redistributable, no modification permitted -%if "x%{?variant}" != "x" -Provides: kernel-firmware = %{rpmversion}-%{pkg_release} -%endif -%description firmware -Kernel-firmware includes firmware files required for some devices to -operate. - -%package bootwrapper -Summary: Boot wrapper files for generating combined kernel + initrd images -Group: Development/System -Requires: gzip binutils -%description bootwrapper -Kernel-bootwrapper contains the wrapper code which makes bootable "zImage" -files combining both kernel and initial ramdisk. - -%package debuginfo-common-%{_target_cpu} -Summary: Kernel source files used by %{name}-debuginfo packages -Group: Development/Debug -%description debuginfo-common-%{_target_cpu} -This package is required by %{name}-debuginfo subpackages. -It provides the kernel source files common to all builds. - -%if %{with_tools} -%package -n kernel-tools -Summary: Assortment of tools for the Linux kernel -Group: Development/System -License: GPLv2 -Obsoletes: perf -Provides: perf -Provides: cpupowerutils = 1:009-0.6.p1 -Obsoletes: cpupowerutils < 1:009-0.6.p1 -Provides: cpufreq-utils = 1:009-0.6.p1 -Provides: cpufrequtils = 1:009-0.6.p1 -Obsoletes: cpufreq-utils < 1:009-0.6.p1 -Obsoletes: cpufrequtils < 1:009-0.6.p1 -Obsoletes: cpuspeed < 1:1.5-16 -%description -n kernel-tools -This package contains the tools/ directory from the kernel source -- the perf tool and the supporting documentation. - -%package -n kernel-tools-devel -Summary: Assortment of tools for the Linux kernel -Group: Development/System -License: GPLv2 -Requires: kernel-tools = %{version}-%{release} -Provides: cpupowerutils-devel = 1:009-0.6.p1 -Obsoletes: cpupowerutils-devel < 1:009-0.6.p1 -%description -n kernel-tools-devel -This package contains the development files for the tools/ directory from -the kernel source. - -%package -n kernel-tools-debuginfo -Summary: Debug information for package kernel-tools -Group: Development/Debug -Requires: %{name}-debuginfo-common-%{_target_cpu} = %{version}-%{release} -AutoReqProv: no -%description -n kernel-tools-debuginfo -This package provides debug information for package kernel-tools. - -# Note that this pattern only works right to match the .build-id -# symlinks because of the trailing nonmatching alternation and -# the leading .*, because of find-debuginfo.sh's buggy handling -# of matching the pattern against the symlinks file. -%{expand:%%global debuginfo_args %{?debuginfo_args} -p '.*%%{_bindir}/perf(\.debug)?|.*%%{_libexecdir}/perf-core/.*|.*%%{_bindir}/centrino-decode(\.debug)?|.*%%{_bindir}/powernow-k8-decode(\.debug)?|.*%%{_bindir}/cpupower(\.debug)?|.*%%{_libdir}/libcpupower.*|XXX' -o kernel-tools-debuginfo.list} -%endif - - -# -# This macro creates a kernel--debuginfo package. -# %%kernel_debuginfo_package -# -%define kernel_debuginfo_package() \ -%package %{?1:%{1}-}debuginfo\ -Summary: Debug information for package %{name}%{?1:-%{1}}\ -Group: Development/Debug\ -Requires: %{name}-debuginfo-common-%{_target_cpu} = %{version}-%{release}\ -Provides: %{name}%{?1:-%{1}}-debuginfo-%{_target_cpu} = %{version}-%{release}\ -AutoReqProv: no\ -%description -n %{name}%{?1:-%{1}}-debuginfo\ -This package provides debug information for package %{name}%{?1:-%{1}}.\ -This is required to use SystemTap with %{name}%{?1:-%{1}}-%{KVERREL}.\ -%{expand:%%global debuginfo_args %{?debuginfo_args} -p '/.*/%%{KVERREL}%{?1:\.%{1}}/.*|/.*%%{KVERREL}%{?1:\.%{1}}(\.debug)?' -o debuginfo%{?1}.list}\ -%{nil} - -# -# This macro creates a kernel--devel package. -# %%kernel_devel_package -# -%define kernel_devel_package() \ -%package %{?1:%{1}-}devel\ -Summary: Development package for building kernel modules to match the %{?2:%{2} }kernel\ -Group: System Environment/Kernel\ -Provides: kernel%{?1:-%{1}}-devel-%{_target_cpu} = %{version}-%{release}\ -Provides: kernel-devel-%{_target_cpu} = %{version}-%{release}%{?1:.%{1}}\ -Provides: kernel-devel = %{version}-%{release}%{?1:.%{1}}\ -Provides: kernel-devel-uname-r = %{KVERREL}%{?1:.%{1}}\ -AutoReqProv: no\ -Requires(pre): /usr/bin/find\ -Requires: perl\ -%description -n kernel%{?variant}%{?1:-%{1}}-devel\ -This package provides kernel headers and makefiles sufficient to build modules\ -against the %{?2:%{2} }kernel package.\ -%{nil} - -# -# This macro creates a kernel- and its -devel and -debuginfo too. -# %%define variant_summary The Linux kernel compiled for -# %%kernel_variant_package [-n ] -# -%define kernel_variant_package(n:) \ -%package %1\ -Summary: %{variant_summary}\ -Group: System Environment/Kernel\ -%kernel_reqprovconf\ -%{expand:%%kernel_devel_package %1 %{!?-n:%1}%{?-n:%{-n*}}}\ -%{expand:%%kernel_debuginfo_package %1}\ -%{nil} - - -# First the auxiliary packages of the main kernel package. -%kernel_devel_package -%kernel_debuginfo_package - - -# Now, each variant package. - -%define variant_summary The Linux kernel compiled for SMP machines -%kernel_variant_package -n SMP smp -%description smp -This package includes a SMP version of the Linux kernel. It is -required only on machines with two or more CPUs as well as machines with -hyperthreading technology. - -Install the kernel-smp package if your machine uses two or more CPUs. - - -%define variant_summary The Linux kernel compiled for PAE capable machines -%kernel_variant_package PAE -%description PAE -This package includes a version of the Linux kernel with support for up to -64GB of high memory. It requires a CPU with Physical Address Extensions (PAE). -The non-PAE kernel can only address up to 4GB of memory. -Install the kernel-PAE package if your machine has more than 4GB of memory. - - -%define variant_summary The Linux kernel compiled with extra debugging enabled for PAE capable machines -%kernel_variant_package PAEdebug -Obsoletes: kernel-PAE-debug -%description PAEdebug -This package includes a version of the Linux kernel with support for up to -64GB of high memory. It requires a CPU with Physical Address Extensions (PAE). -The non-PAE kernel can only address up to 4GB of memory. -Install the kernel-PAE package if your machine has more than 4GB of memory. - -This variant of the kernel has numerous debugging options enabled. -It should only be installed when trying to gather additional information -on kernel bugs, as some of these options impact performance noticably. - - -%define variant_summary The Linux kernel compiled with extra debugging enabled -%kernel_variant_package debug -%description debug -The kernel package contains the Linux kernel (vmlinuz), the core of any -Linux operating system. The kernel handles the basic functions -of the operating system: memory allocation, process allocation, device -input and output, etc. - -This variant of the kernel has numerous debugging options enabled. -It should only be installed when trying to gather additional information -on kernel bugs, as some of these options impact performance noticably. - - -%define variant_summary The Linux kernel compiled for TI-OMAP boards -%kernel_variant_package omap -%description omap -This package includes a version of the Linux kernel with support for -TI-OMAP based systems, i.e., BeagleBoard-xM. - -%define variant_summary The Linux kernel compiled for tegra boards -%kernel_variant_package tegra -%description tegra -This package includes a version of the Linux kernel with support for -nvidia tegra based systems, i.e., trimslice, ac-100. - - -%prep -# do a few sanity-checks for --with *only builds -%if %{with_baseonly} -%if !%{with_up}%{with_pae} -echo "Cannot build --with baseonly, up build is disabled" -exit 1 -%endif -%endif - -%if %{with_smponly} -%if !%{with_smp} -echo "Cannot build --with smponly, smp build is disabled" -exit 1 -%endif -%endif - -# more sanity checking; do it quietly -if [ "%{patches}" != "%%{patches}" ] ; then - for patch in %{patches} ; do - if [ ! -f $patch ] ; then - echo "ERROR: Patch ${patch##/*/} listed in specfile but is missing" - exit 1 - fi - done -fi 2>/dev/null - -patch_command='patch -p1 -F1 -s' -ApplyPatch() -{ - local patch=$1 - shift - if [ ! -f $RPM_SOURCE_DIR/$patch ]; then - exit 1 - fi -%if !%{using_upstream_branch} - if ! grep -E "^Patch[0-9]+: $patch\$" %{_specdir}/${RPM_PACKAGE_NAME%%%%%{?variant}}.spec ; then - if [ "${patch:0:8}" != "patch-3." ] ; then - echo "ERROR: Patch $patch not listed as a source patch in specfile" - exit 1 - fi - fi 2>/dev/null -%endif - case "$patch" in - *.bz2) bunzip2 < "$RPM_SOURCE_DIR/$patch" | $patch_command ${1+"$@"} ;; - *.gz) gunzip < "$RPM_SOURCE_DIR/$patch" | $patch_command ${1+"$@"} ;; - *) $patch_command ${1+"$@"} < "$RPM_SOURCE_DIR/$patch" ;; - esac -} - -# don't apply patch if it's empty -ApplyOptionalPatch() -{ - local patch=$1 - shift - if [ ! -f $RPM_SOURCE_DIR/$patch ]; then - exit 1 - fi - local C=$(wc -l $RPM_SOURCE_DIR/$patch | awk '{print $1}') - if [ "$C" -gt 9 ]; then - ApplyPatch $patch ${1+"$@"} - fi -} - -# we don't want a .config file when building firmware: it just confuses the build system -%define build_firmware \ - mv .config .config.firmware_save \ - make INSTALL_FW_PATH=$RPM_BUILD_ROOT/lib/firmware firmware_install \ - mv .config.firmware_save .config - -# First we unpack the kernel tarball. -# If this isn't the first make prep, we use links to the existing clean tarball -# which speeds things up quite a bit. - -# Update to latest upstream. -%if 0%{?released_kernel} -%define vanillaversion 3.%{base_sublevel} -# non-released_kernel case -%else -%if 0%{?rcrev} -%define vanillaversion 3.%{upstream_sublevel}-rc%{rcrev} -%if 0%{?gitrev} -%define vanillaversion 3.%{upstream_sublevel}-rc%{rcrev}-git%{gitrev} -%endif -%else -# pre-{base_sublevel+1}-rc1 case -%if 0%{?gitrev} -%define vanillaversion 3.%{base_sublevel}-git%{gitrev} -%else -%define vanillaversion 3.%{base_sublevel} -%endif -%endif -%endif - -# %%{vanillaversion} : the full version name, e.g. 2.6.35-rc6-git3 -# %%{kversion} : the base version, e.g. 2.6.34 - -# Use kernel-%%{kversion}%%{?dist} as the top-level directory name -# so we can prep different trees within a single git directory. - -# Build a list of the other top-level kernel tree directories. -# This will be used to hardlink identical vanilla subdirs. -sharedirs=$(find "$PWD" -maxdepth 1 -type d -name 'kernel-3.*' \ - | grep -x -v "$PWD"/kernel-%{kversion}%{?dist}) ||: - -if [ ! -d kernel-%{kversion}%{?dist}/vanilla-%{vanillaversion} ]; then - - if [ -d kernel-%{kversion}%{?dist}/vanilla-%{kversion} ]; then - - # The base vanilla version already exists. - cd kernel-%{kversion}%{?dist} - - # Any vanilla-* directories other than the base one are stale. - for dir in vanilla-*; do - [ "$dir" = vanilla-%{kversion} ] || rm -rf $dir & - done - - else - - rm -f pax_global_header - # Look for an identical base vanilla dir that can be hardlinked. - for sharedir in $sharedirs ; do - if [[ ! -z $sharedir && -d $sharedir/vanilla-%{kversion} ]] ; then - break - fi - done - if [[ ! -z $sharedir && -d $sharedir/vanilla-%{kversion} ]] ; then -%setup -q -n kernel-%{kversion}%{?dist} -c -T - cp -rl $sharedir/vanilla-%{kversion} . - else -%setup -q -n kernel-%{kversion}%{?dist} -c - mv linux-%{kversion} vanilla-%{kversion} - fi - - fi - -%if "%{kversion}" != "%{vanillaversion}" - - for sharedir in $sharedirs ; do - if [[ ! -z $sharedir && -d $sharedir/vanilla-%{vanillaversion} ]] ; then - break - fi - done - if [[ ! -z $sharedir && -d $sharedir/vanilla-%{vanillaversion} ]] ; then - - cp -rl $sharedir/vanilla-%{vanillaversion} . - - else - - # Need to apply patches to the base vanilla version. - cp -rl vanilla-%{kversion} vanilla-%{vanillaversion} - cd vanilla-%{vanillaversion} - -# Update vanilla to the latest upstream. -# (non-released_kernel case only) -%if 0%{?rcrev} - ApplyPatch patch-3.%{upstream_sublevel}-rc%{rcrev}.bz2 -%if 0%{?gitrev} - ApplyPatch patch-3.%{upstream_sublevel}-rc%{rcrev}-git%{gitrev}.bz2 -%endif -%else -# pre-{base_sublevel+1}-rc1 case -%if 0%{?gitrev} - ApplyPatch patch-3.%{base_sublevel}-git%{gitrev}.bz2 -%endif -%endif - - cd .. - - fi - -%endif - -else - - # We already have all vanilla dirs, just change to the top-level directory. - cd kernel-%{kversion}%{?dist} - -fi - -# Now build the fedora kernel tree. -if [ -d linux-%{kversion}.%{_target_cpu} ]; then - # Just in case we ctrl-c'd a prep already - rm -rf deleteme.%{_target_cpu} - # Move away the stale away, and delete in background. - mv linux-%{kversion}.%{_target_cpu} deleteme.%{_target_cpu} - rm -rf deleteme.%{_target_cpu} & -fi - -cp -rl vanilla-%{vanillaversion} linux-%{kversion}.%{_target_cpu} - -cd linux-%{kversion}.%{_target_cpu} - -# released_kernel with possible stable updates -%if 0%{?stable_base} -ApplyPatch %{stable_patch_00} -%endif -%if 0%{?stable_rc} -ApplyPatch %{stable_patch_01} -%endif - -%if %{using_upstream_branch} -### BRANCH APPLY ### -%endif - -# Drop some necessary files from the source dir into the buildroot -cp $RPM_SOURCE_DIR/config-* . -cp %{SOURCE15} . - -# Dynamically generate kernel .config files from config-* files -make -f %{SOURCE20} VERSION=%{version} configs - -%if %{?all_arch_configs:1}%{!?all_arch_configs:0} -#if a rhel kernel, apply the rhel config options -%if 0%{?rhel} - for i in %{all_arch_configs} - do - mv $i $i.tmp - ./merge.pl config-rhel-generic $i.tmp > $i - rm $i.tmp - done -%endif - -# Merge in any user-provided local config option changes -for i in %{all_arch_configs} -do - mv $i $i.tmp - ./merge.pl %{SOURCE1000} $i.tmp > $i - rm $i.tmp -done -%endif - -ApplyOptionalPatch git-linus.diff - -ApplyPatch linux-2.6-makefile-after_link.patch - -# -# misc small stuff to make things compile -# -ApplyOptionalPatch linux-2.6-compile-fixes.patch - -%if !%{nopatches} - -# revert patches from upstream that conflict or that we get via other means -ApplyOptionalPatch linux-2.6-upstream-reverts.patch -R - - -# Architecture patches -# x86(-64) - -# -# ARM -# -ApplyPatch arm-omap-dt-compat.patch -ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch - -ApplyPatch taint-vbox.patch -# -# NX Emulation -# -ApplyPatch linux-2.6-32bit-mmap-exec-randomization.patch -ApplyPatch linux-2.6-i386-nx-emulation.patch - -# -# bugfixes to drivers and filesystems -# - -# ext4 - -# xfs -ApplyPatch xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch - -# btrfs - - -# eCryptfs - -# NFSv4 - -# USB - -# WMI - -# ACPI -ApplyPatch linux-2.6-defaults-acpi-video.patch -ApplyPatch linux-2.6-acpi-video-dos.patch -ApplyPatch linux-2.6-acpi-debug-infinite-loop.patch -ApplyPatch acpi-ensure-thermal-limits-match-cpu-freq.patch -ApplyPatch acpi-sony-nonvs-blacklist.patch - -# Various low-impact patches to aid debugging. -ApplyPatch linux-2.6-debug-taint-vm.patch - -# -# PCI -# -# enable ASPM by default on hardware we expect to work -ApplyPatch linux-2.6-defaults-aspm.patch - -# -# SCSI Bits. -# - -# ACPI - -# ALSA - -# Networking - - -# Misc fixes -# The input layer spews crap no-one cares about. -ApplyPatch linux-2.6-input-kill-stupid-messages.patch - -# stop floppy.ko from autoloading during udev... -ApplyPatch die-floppy-die.patch -ApplyPatch floppy-drop-disable_hlt-warning.patch - -ApplyPatch linux-2.6.30-no-pcspkr-modalias.patch - -# Allow to use 480600 baud on 16C950 UARTs -ApplyPatch linux-2.6-serial-460800.patch - -# Silence some useless messages that still get printed with 'quiet' -ApplyPatch linux-2.6-silence-noise.patch - -# Make fbcon not show the penguins with 'quiet' -ApplyPatch linux-2.6-silence-fbcon-logo.patch - -# Changes to upstream defaults. - - -# /dev/crash driver. -ApplyPatch linux-2.6-crash-driver.patch - -# Hack e1000e to work on Montevina SDV -ApplyPatch linux-2.6-e1000-ich9-montevina.patch - -# crypto/ - -# Assorted Virt Fixes -ApplyPatch fix_xen_guest_on_old_EC2.patch - -# DRM core - -# Nouveau DRM -ApplyOptionalPatch drm-nouveau-updates.patch - -# Intel DRM -ApplyOptionalPatch drm-intel-next.patch -ApplyPatch drm-intel-make-lvds-work.patch -ApplyPatch drm-i915-fbc-stfu.patch -ApplyPatch drm-i915-sdvo-lvds-is-digital.patch - -ApplyPatch drm-lower-severity-radeon-lockup.diff - -ApplyPatch linux-2.6-intel-iommu-igfx.patch - -# silence the ACPI blacklist code -ApplyPatch linux-2.6-silence-acpi-blacklist.patch - -# V4L/DVB updates/fixes/experimental drivers -# apply if non-empty -ApplyOptionalPatch linux-2.6-v4l-dvb-fixes.patch -ApplyOptionalPatch linux-2.6-v4l-dvb-update.patch -ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch -#ApplyPatch linux-2.6-v4l-dvb-uvcvideo-update.patch - -# Patches headed upstream -ApplyPatch rcutree-avoid-false-quiescent-states.patch - -ApplyPatch disable-i8042-check-on-apple-mac.patch - -ApplyPatch add-appleir-usb-driver.patch - -ApplyPatch udlfb-bind-framebuffer-to-interface.patch -#ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch -#ApplyPatch epoll-fix-spurious-lockdep-warnings.patch -ApplyPatch epoll-limit-paths.patch -ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch -ApplyPatch block-stray-block-put-after-teardown.patch -ApplyPatch usb-add-quirk-for-logitech-webcams.patch - -#ApplyPatch crypto-register-cryptd-first.patch - -# rhbz#605888 -ApplyPatch dmar-disable-when-ricoh-multifunction.patch - -ApplyPatch revert-efi-rtclock.patch -ApplyPatch efi-dont-map-boot-services-on-32bit.patch - -#ApplyPatch add-macbookair41-keyboard.patch - -ApplyPatch hvcs_pi_buf_alloc.patch - -#ApplyPatch powerpc-Fix-deadlock-in-icswx-code.patch - -#ApplyPatch iwlagn-fix-ht_params-NULL-pointer-dereference.patch - -#rhbz #722509 -#ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch - -#ApplyPatch media-DiBcom-protect-the-I2C-bufer-access.patch -#ApplyPatch media-dib0700-protect-the-dib0700-buffer-access.patch -ApplyPatch media-dib0700-correct-error-message.patch - -# utrace. -ApplyPatch utrace.patch - -#rhbz #735946 -ApplyPatch 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch -ApplyPatch 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch - -#rhbz 748691 -ApplyPatch be2net-non-member-vlan-pkts-not-received-in-promisco.patch -ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch - -#rhbz 750402 -ApplyPatch oom-fix-integer-overflow-of-points.patch - -#rhbz 706574 -#ApplyPatch WMI-properly-cleanup-devices-to-avoid-crashes.patch - -#rhbz 728607 -ApplyPatch elantech.patch - -#rhbz 748210 -ApplyPatch ideapad-Check-if-acpi-already-handle-backlight.patch - -#rhbz 731365 -#ApplyPatch mac80211-fix-remain_off_channel-regression.patch -#ApplyPatch mac80211-config-hw-when-going-back-on-channel.patch - -#rhbz 752176 -ApplyPatch sysfs-msi-irq-per-device.patch - -#backport brcm80211 from 3.2-rc1 -ApplyPatch brcm80211.patch - -# END OF PATCH APPLICATIONS - -%endif - -# Any further pre-build tree manipulations happen here. - -chmod +x scripts/checkpatch.pl - -# This Prevents scripts/setlocalversion from mucking with our version numbers. -touch .scmversion - -# only deal with configs if we are going to build for the arch -%ifnarch %nobuildarches - -mkdir configs - -# Remove configs not for the buildarch -for cfg in kernel-%{version}-*.config; do - if [ `echo %{all_arch_configs} | grep -c $cfg` -eq 0 ]; then - rm -f $cfg - fi -done - -%if !%{debugbuildsenabled} -rm -f kernel-%{version}-*debug.config -%endif - -# now run oldconfig over all the config files -for i in *.config -do - mv $i .config - Arch=`head -1 .config | cut -b 3-` - make ARCH=$Arch listnewconfig | grep -E '^CONFIG_' >.newoptions || true -%if %{listnewconfig_fail} - if [ -s .newoptions ]; then - cat .newoptions - exit 1 - fi -%endif - rm -f .newoptions - make ARCH=$Arch oldnoconfig - echo "# $Arch" > configs/$i - cat .config >> configs/$i -done -# end of kernel config -%endif - -# get rid of unwanted files resulting from patch fuzz -find . \( -name "*.orig" -o -name "*~" \) -exec rm -f {} \; >/dev/null - -# remove unnecessary SCM files -find . -name .gitignore -exec rm -f {} \; >/dev/null - -cd .. - -### -### build -### -%build - -%if %{with_sparse} -%define sparse_mflags C=1 -%endif - -%if %{fancy_debuginfo} -# This override tweaks the kernel makefiles so that we run debugedit on an -# object before embedding it. When we later run find-debuginfo.sh, it will -# run debugedit again. The edits it does change the build ID bits embedded -# in the stripped object, but repeating debugedit is a no-op. We do it -# beforehand to get the proper final build ID bits into the embedded image. -# This affects the vDSO images in vmlinux, and the vmlinux image in bzImage. -export AFTER_LINK=\ -'sh -xc "/usr/lib/rpm/debugedit -b $$RPM_BUILD_DIR -d /usr/src/debug \ - -i $@ > $@.id"' -%endif - -cp_vmlinux() -{ - eu-strip --remove-comment -o "$2" "$1" -} - -BuildKernel() { - MakeTarget=$1 - KernelImage=$2 - Flavour=$3 - InstallName=${4:-vmlinuz} - - # Pick the right config file for the kernel we're building - Config=kernel-%{version}-%{_target_cpu}${Flavour:+-${Flavour}}.config - DevelDir=/usr/src/kernels/%{KVERREL}${Flavour:+.${Flavour}} - - # When the bootable image is just the ELF kernel, strip it. - # We already copy the unstripped file into the debuginfo package. - if [ "$KernelImage" = vmlinux ]; then - CopyKernel=cp_vmlinux - else - CopyKernel=cp - fi - - KernelVer=%{version}-%{release}.%{_target_cpu}${Flavour:+.${Flavour}} - echo BUILDING A KERNEL FOR ${Flavour} %{_target_cpu}... - - %if 0%{?stable_update} - # make sure SUBLEVEL is incremented on a stable release. Sigh 3.x. - perl -p -i -e "s/^SUBLEVEL.*/SUBLEVEL = %{?stablerev}/" Makefile - %endif - - # make sure EXTRAVERSION says what we want it to say - perl -p -i -e "s/^EXTRAVERSION.*/EXTRAVERSION = -%{release}.%{_target_cpu}${Flavour:+.${Flavour}}/" Makefile - - # if pre-rc1 devel kernel, must fix up PATCHLEVEL for our versioning scheme - %if !0%{?rcrev} - %if 0%{?gitrev} - perl -p -i -e 's/^PATCHLEVEL.*/PATCHLEVEL = %{upstream_sublevel}/' Makefile - %endif - %endif - - # and now to start the build process - - make -s mrproper - cp configs/$Config .config - - Arch=`head -1 .config | cut -b 3-` - echo USING ARCH=$Arch - - make -s ARCH=$Arch oldnoconfig >/dev/null - make -s ARCH=$Arch V=1 %{?_smp_mflags} $MakeTarget %{?sparse_mflags} - make -s ARCH=$Arch V=1 %{?_smp_mflags} modules %{?sparse_mflags} || exit 1 - - # Start installing the results -%if %{with_debuginfo} - mkdir -p $RPM_BUILD_ROOT%{debuginfodir}/boot - mkdir -p $RPM_BUILD_ROOT%{debuginfodir}/%{image_install_path} -%endif - mkdir -p $RPM_BUILD_ROOT/%{image_install_path} - install -m 644 .config $RPM_BUILD_ROOT/boot/config-$KernelVer - install -m 644 System.map $RPM_BUILD_ROOT/boot/System.map-$KernelVer - - # We estimate the size of the initramfs because rpm needs to take this size - # into consideration when performing disk space calculations. (See bz #530778) - dd if=/dev/zero of=$RPM_BUILD_ROOT/boot/initramfs-$KernelVer.img bs=1M count=20 - - if [ -f arch/$Arch/boot/zImage.stub ]; then - cp arch/$Arch/boot/zImage.stub $RPM_BUILD_ROOT/%{image_install_path}/zImage.stub-$KernelVer || : - fi - $CopyKernel $KernelImage \ - $RPM_BUILD_ROOT/%{image_install_path}/$InstallName-$KernelVer - chmod 755 $RPM_BUILD_ROOT/%{image_install_path}/$InstallName-$KernelVer - - mkdir -p $RPM_BUILD_ROOT/lib/modules/$KernelVer - # Override $(mod-fw) because we don't want it to install any firmware - # We'll do that ourselves with 'make firmware_install' - make -s ARCH=$Arch INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_install KERNELRELEASE=$KernelVer mod-fw= -%ifarch %{vdso_arches} - make -s ARCH=$Arch INSTALL_MOD_PATH=$RPM_BUILD_ROOT vdso_install KERNELRELEASE=$KernelVer - if [ ! -s ldconfig-kernel.conf ]; then - echo > ldconfig-kernel.conf "\ -# Placeholder file, no vDSO hwcap entries used in this kernel." - fi - %{__install} -D -m 444 ldconfig-kernel.conf \ - $RPM_BUILD_ROOT/etc/ld.so.conf.d/kernel-$KernelVer.conf -%endif - - # And save the headers/makefiles etc for building modules against - # - # This all looks scary, but the end result is supposed to be: - # * all arch relevant include/ files - # * all Makefile/Kconfig files - # * all script/ files - - rm -f $RPM_BUILD_ROOT/lib/modules/$KernelVer/build - rm -f $RPM_BUILD_ROOT/lib/modules/$KernelVer/source - mkdir -p $RPM_BUILD_ROOT/lib/modules/$KernelVer/build - (cd $RPM_BUILD_ROOT/lib/modules/$KernelVer ; ln -s build source) - # dirs for additional modules per module-init-tools, kbuild/modules.txt - mkdir -p $RPM_BUILD_ROOT/lib/modules/$KernelVer/extra - mkdir -p $RPM_BUILD_ROOT/lib/modules/$KernelVer/updates - # first copy everything - cp --parents `find -type f -name "Makefile*" -o -name "Kconfig*"` $RPM_BUILD_ROOT/lib/modules/$KernelVer/build - cp Module.symvers $RPM_BUILD_ROOT/lib/modules/$KernelVer/build - cp System.map $RPM_BUILD_ROOT/lib/modules/$KernelVer/build - if [ -s Module.markers ]; then - cp Module.markers $RPM_BUILD_ROOT/lib/modules/$KernelVer/build - fi - # then drop all but the needed Makefiles/Kconfig files - rm -rf $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/Documentation - rm -rf $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/scripts - rm -rf $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/include - cp .config $RPM_BUILD_ROOT/lib/modules/$KernelVer/build - cp -a scripts $RPM_BUILD_ROOT/lib/modules/$KernelVer/build - if [ -d arch/$Arch/scripts ]; then - cp -a arch/$Arch/scripts $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/arch/%{_arch} || : - fi - if [ -f arch/$Arch/*lds ]; then - cp -a arch/$Arch/*lds $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/arch/%{_arch}/ || : - fi - rm -f $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/scripts/*.o - rm -f $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/scripts/*/*.o -%ifarch ppc - cp -a --parents arch/powerpc/lib/crtsavres.[So] $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/ -%endif - if [ -d arch/%{asmarch}/include ]; then - cp -a --parents arch/%{asmarch}/include $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/ - fi - cp -a include $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/include - - # Make sure the Makefile and version.h have a matching timestamp so that - # external modules can be built - touch -r $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/Makefile $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/include/linux/version.h - touch -r $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/.config $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/include/linux/autoconf.h - # Copy .config to include/config/auto.conf so "make prepare" is unnecessary. - cp $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/.config $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/include/config/auto.conf - -%if %{fancy_debuginfo} - if test -s vmlinux.id; then - cp vmlinux.id $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/vmlinux.id - else - echo >&2 "*** ERROR *** no vmlinux build ID! ***" - exit 1 - fi -%endif - - # - # save the vmlinux file for kernel debugging into the kernel-debuginfo rpm - # -%if %{with_debuginfo} - mkdir -p $RPM_BUILD_ROOT%{debuginfodir}/lib/modules/$KernelVer - cp vmlinux $RPM_BUILD_ROOT%{debuginfodir}/lib/modules/$KernelVer -%endif - - find $RPM_BUILD_ROOT/lib/modules/$KernelVer -name "*.ko" -type f >modnames - - # mark modules executable so that strip-to-file can strip them - xargs --no-run-if-empty chmod u+x < modnames - - # Generate a list of modules for block and networking. - - grep -F /drivers/ modnames | xargs --no-run-if-empty nm -upA | - sed -n 's,^.*/\([^/]*\.ko\): *U \(.*\)$,\1 \2,p' > drivers.undef - - collect_modules_list() - { - sed -r -n -e "s/^([^ ]+) \\.?($2)\$/\\1/p" drivers.undef | - LC_ALL=C sort -u > $RPM_BUILD_ROOT/lib/modules/$KernelVer/modules.$1 - } - - collect_modules_list networking \ - 'register_netdev|ieee80211_register_hw|usbnet_probe|phy_driver_register|rt2x00(pci|usb)_probe' - collect_modules_list block \ - 'ata_scsi_ioctl|scsi_add_host|scsi_add_host_with_dma|blk_init_queue|register_mtd_blktrans|scsi_esp_register|scsi_register_device_handler' - collect_modules_list drm \ - 'drm_open|drm_init' - collect_modules_list modesetting \ - 'drm_crtc_init' - - # detect missing or incorrect license tags - rm -f modinfo - while read i - do - echo -n "${i#$RPM_BUILD_ROOT/lib/modules/$KernelVer/} " >> modinfo - /sbin/modinfo -l $i >> modinfo - done < modnames - - grep -E -v \ - 'GPL( v2)?$|Dual BSD/GPL$|Dual MPL/GPL$|GPL and additional rights$' \ - modinfo && exit 1 - - rm -f modinfo modnames - - # remove files that will be auto generated by depmod at rpm -i time - for i in alias alias.bin builtin.bin ccwmap dep dep.bin ieee1394map inputmap isapnpmap ofmap pcimap seriomap symbols symbols.bin usbmap - do - rm -f $RPM_BUILD_ROOT/lib/modules/$KernelVer/modules.$i - done - - # Move the devel headers out of the root file system - mkdir -p $RPM_BUILD_ROOT/usr/src/kernels - mv $RPM_BUILD_ROOT/lib/modules/$KernelVer/build $RPM_BUILD_ROOT/$DevelDir - ln -sf ../../..$DevelDir $RPM_BUILD_ROOT/lib/modules/$KernelVer/build - - # prune junk from kernel-devel - find $RPM_BUILD_ROOT/usr/src/kernels -name ".*.cmd" -exec rm -f {} \; -} - -### -# DO it... -### - -# prepare directories -rm -rf $RPM_BUILD_ROOT -mkdir -p $RPM_BUILD_ROOT/boot -mkdir -p $RPM_BUILD_ROOT%{_libexecdir} - -cd linux-%{kversion}.%{_target_cpu} - -%if %{with_debug} -BuildKernel %make_target %kernel_image debug -%endif - -%if %{with_pae_debug} -BuildKernel %make_target %kernel_image PAEdebug -%endif - -%if %{with_pae} -BuildKernel %make_target %kernel_image PAE -%endif - -%if %{with_omap} -BuildKernel %make_target %kernel_image omap -%endif - -%if %{with_tegra} -BuildKernel %make_target %kernel_image tegra -%endif - -%if %{with_up} -BuildKernel %make_target %kernel_image -%endif - -%if %{with_smp} -BuildKernel %make_target %kernel_image smp -%endif - -%if %{with_tools} -# perf -make %{?_smp_mflags} -C tools/perf -s V=1 HAVE_CPLUS_DEMANGLE=1 prefix=%{_prefix} all -make %{?_smp_mflags} -C tools/perf -s V=1 prefix=%{_prefix} man || %{doc_build_fail} - -%ifarch %{cpupowerarchs} -# cpupower -# make sure version-gen.sh is executable. -chmod +x tools/power/cpupower/utils/version-gen.sh -make %{?_smp_mflags} -C tools/power/cpupower CPUFREQ_BENCH=false -%ifarch %{ix86} - cd tools/power/cpupower/debug/i386 - make %{?_smp_mflags} centrino-decode powernow-k8-decode - cd - -%endif -%ifarch x86_64 - cd tools/power/cpupower/debug/x86_64 - make %{?_smp_mflags} centrino-decode powernow-k8-decode - cd - -%endif -%endif -%endif - -%if %{with_doc} -# Make the HTML and man pages. -make htmldocs mandocs || %{doc_build_fail} - -# sometimes non-world-readable files sneak into the kernel source tree -chmod -R a=rX Documentation -find Documentation -type d | xargs chmod u+w -%endif - -### -### Special hacks for debuginfo subpackages. -### - -# This macro is used by %%install, so we must redefine it before that. -%define debug_package %{nil} - -%if %{fancy_debuginfo} -%define __debug_install_post \ - /usr/lib/rpm/find-debuginfo.sh %{debuginfo_args} %{_builddir}/%{?buildsubdir}\ -%{nil} -%endif - -%if %{with_debuginfo} -%ifnarch noarch -%global __debug_package 1 -%files -f debugfiles.list debuginfo-common-%{_target_cpu} -%defattr(-,root,root) -%endif -%endif - -### -### install -### - -%install - -cd linux-%{kversion}.%{_target_cpu} - -%if %{with_doc} -docdir=$RPM_BUILD_ROOT%{_datadir}/doc/kernel-doc-%{rpmversion} -man9dir=$RPM_BUILD_ROOT%{_datadir}/man/man9 - -# copy the source over -mkdir -p $docdir -tar -f - --exclude=man --exclude='.*' -c Documentation | tar xf - -C $docdir - -# Install man pages for the kernel API. -mkdir -p $man9dir -find Documentation/DocBook/man -name '*.9.gz' -print0 | -xargs -0 --no-run-if-empty %{__install} -m 444 -t $man9dir $m -ls $man9dir | grep -q '' || > $man9dir/BROKEN -%endif # with_doc - -# We have to do the headers install before the tools install because the -# kernel headers_install will remove any header files in /usr/include that -# it doesn't install itself. - -%if %{with_headers} -# Install kernel headers -make ARCH=%{hdrarch} INSTALL_HDR_PATH=$RPM_BUILD_ROOT/usr headers_install - -# Do headers_check but don't die if it fails. -make ARCH=%{hdrarch} INSTALL_HDR_PATH=$RPM_BUILD_ROOT/usr headers_check \ - > hdrwarnings.txt || : -if grep -q exist hdrwarnings.txt; then - sed s:^$RPM_BUILD_ROOT/usr/include/:: hdrwarnings.txt - # Temporarily cause a build failure if header inconsistencies. - # exit 1 -fi - -find $RPM_BUILD_ROOT/usr/include \ - \( -name .install -o -name .check -o \ - -name ..install.cmd -o -name ..check.cmd \) | xargs rm -f - -# glibc provides scsi headers for itself, for now -rm -rf $RPM_BUILD_ROOT/usr/include/scsi -rm -f $RPM_BUILD_ROOT/usr/include/asm*/atomic.h -rm -f $RPM_BUILD_ROOT/usr/include/asm*/io.h -rm -f $RPM_BUILD_ROOT/usr/include/asm*/irq.h -%endif - -%if %{with_tools} -# perf tool binary and supporting scripts/binaries -make -C tools/perf -s V=1 DESTDIR=$RPM_BUILD_ROOT HAVE_CPLUS_DEMANGLE=1 prefix=%{_prefix} install - -# perf man pages (note: implicit rpm magic compresses them later) -make -C tools/perf -s V=1 DESTDIR=$RPM_BUILD_ROOT HAVE_CPLUS_DEMANGLE=1 prefix=%{_prefix} install-man || %{doc_build_fail} - -%ifarch %{cpupowerarchs} -make -C tools/power/cpupower DESTDIR=$RPM_BUILD_ROOT libdir=%{_libdir} mandir=%{_mandir} CPUFREQ_BENCH=false install -rm -f %{buildroot}%{_libdir}/*.{a,la} -%find_lang cpupower -mv cpupower.lang ../ -%ifarch %{ix86} - cd tools/power/cpupower/debug/i386 - install -m755 centrino-decode %{buildroot}%{_bindir}/centrino-decode - install -m755 powernow-k8-decode %{buildroot}%{_bindir}/powernow-k8-decode - cd - -%endif -%ifarch x86_64 - cd tools/power/cpupower/debug/x86_64 - install -m755 centrino-decode %{buildroot}%{_bindir}/centrino-decode - install -m755 powernow-k8-decode %{buildroot}%{_bindir}/powernow-k8-decode - cd - -%endif -chmod 0755 %{buildroot}%{_libdir}/libcpupower.so* -mkdir -p %{buildroot}%{_unitdir} %{buildroot}%{_sysconfdir}/sysconfig -install -m644 %{SOURCE2000} %{buildroot}%{_unitdir}/cpupower.service -install -m644 %{SOURCE2001} %{buildroot}%{_sysconfdir}/sysconfig/cpupower -%endif - -%endif - -%if %{with_firmware} -%{build_firmware} -%endif - -%if %{with_bootwrapper} -make DESTDIR=$RPM_BUILD_ROOT bootwrapper_install WRAPPER_OBJDIR=%{_libdir}/kernel-wrapper WRAPPER_DTSDIR=%{_libdir}/kernel-wrapper/dts -%endif - - -### -### clean -### - -%clean -rm -rf $RPM_BUILD_ROOT - -### -### scripts -### - -%if %{with_tools} -%post -n kernel-tools -/sbin/ldconfig - -%postun -n kernel-tools -/sbin/ldconfig -%endif - -# -# This macro defines a %%post script for a kernel*-devel package. -# %%kernel_devel_post [] -# -%define kernel_devel_post() \ -%{expand:%%post %{?1:%{1}-}devel}\ -if [ -f /etc/sysconfig/kernel ]\ -then\ - . /etc/sysconfig/kernel || exit $?\ -fi\ -if [ "$HARDLINK" != "no" -a -x /usr/sbin/hardlink ]\ -then\ - (cd /usr/src/kernels/%{KVERREL}%{?1:.%{1}} &&\ - /usr/bin/find . -type f | while read f; do\ - hardlink -c /usr/src/kernels/*.fc*.*/$f $f\ - done)\ -fi\ -%{nil} - - -# This macro defines a %%posttrans script for a kernel package. -# %%kernel_variant_posttrans [] -# More text can follow to go at the end of this variant's %%post. -# -%define kernel_variant_posttrans() \ -%{expand:%%posttrans %{?1}}\ -/sbin/new-kernel-pkg --package kernel%{?-v:-%{-v*}} --mkinitrd --dracut --depmod --update %{KVERREL}%{?-v:.%{-v*}} || exit $?\ -/sbin/new-kernel-pkg --package kernel%{?1:-%{1}} --rpmposttrans %{KVERREL}%{?1:.%{1}} || exit $?\ -%{nil} - -# -# This macro defines a %%post script for a kernel package and its devel package. -# %%kernel_variant_post [-v ] [-r ] -# More text can follow to go at the end of this variant's %%post. -# -%define kernel_variant_post(v:r:) \ -%{expand:%%kernel_devel_post %{?-v*}}\ -%{expand:%%kernel_variant_posttrans %{?-v*}}\ -%{expand:%%post %{?-v*}}\ -%{-r:\ -if [ `uname -i` == "x86_64" -o `uname -i` == "i386" ] &&\ - [ -f /etc/sysconfig/kernel ]; then\ - /bin/sed -r -i -e 's/^DEFAULTKERNEL=%{-r*}$/DEFAULTKERNEL=kernel%{?-v:-%{-v*}}/' /etc/sysconfig/kernel || exit $?\ -fi}\ -%{expand:\ -/sbin/new-kernel-pkg --package kernel%{?-v:-%{-v*}} --install %{KVERREL}%{?-v:.%{-v*}} || exit $?\ -}\ -%{nil} - -# -# This macro defines a %%preun script for a kernel package. -# %%kernel_variant_preun -# -%define kernel_variant_preun() \ -%{expand:%%preun %{?1}}\ -/sbin/new-kernel-pkg --rminitrd --rmmoddep --remove %{KVERREL}%{?1:.%{1}} || exit $?\ -%{nil} - -%kernel_variant_preun -%kernel_variant_post -r kernel-smp - -%kernel_variant_preun smp -%kernel_variant_post -v smp - -%kernel_variant_preun PAE -%kernel_variant_post -v PAE -r (kernel|kernel-smp) - -%kernel_variant_preun debug -%kernel_variant_post -v debug - -%kernel_variant_post -v PAEdebug -r (kernel|kernel-smp) -%kernel_variant_preun PAEdebug - -%kernel_variant_preun omap -%kernel_variant_post -v omap - -%kernel_variant_preun tegra -%kernel_variant_post -v tegra - -if [ -x /sbin/ldconfig ] -then - /sbin/ldconfig -X || exit $? -fi - -### -### file lists -### - -%if %{with_headers} -%files headers -%defattr(-,root,root) -/usr/include/* -%endif - -%if %{with_firmware} -%files firmware -%defattr(-,root,root) -/lib/firmware/* -%doc linux-%{kversion}.%{_target_cpu}/firmware/WHENCE -%endif - -%if %{with_bootwrapper} -%files bootwrapper -%defattr(-,root,root) -/usr/sbin/* -%{_libdir}/kernel-wrapper -%endif - -# only some architecture builds need kernel-doc -%if %{with_doc} -%files doc -%defattr(-,root,root) -%{_datadir}/doc/kernel-doc-%{rpmversion}/Documentation/* -%dir %{_datadir}/doc/kernel-doc-%{rpmversion}/Documentation -%dir %{_datadir}/doc/kernel-doc-%{rpmversion} -%{_datadir}/man/man9/* -%endif - -%if %{with_tools} -%files -n kernel-tools -f cpupower.lang -%defattr(-,root,root) -%{_bindir}/perf -%dir %{_libexecdir}/perf-core -%{_libexecdir}/perf-core/* -%{_mandir}/man[1-8]/* - -%ifarch %{cpupowerarchs} -%{_bindir}/cpupower -%ifarch %{ix86} x86_64 -%{_bindir}/centrino-decode -%{_bindir}/powernow-k8-decode -%endif -%{_libdir}/libcpupower.so.0 -%{_libdir}/libcpupower.so.0.0.0 -%{_unitdir}/cpupower.service -%config(noreplace) %{_sysconfdir}/sysconfig/cpupower -%endif - -%if %{with_debuginfo} -%files -f kernel-tools-debuginfo.list -n kernel-tools-debuginfo -%defattr(-,root,root) -%endif - -%ifarch %{cpupowerarchs} -%files -n kernel-tools-devel -%{_libdir}/libcpupower.so -%{_includedir}/cpufreq.h -%endif -%endif - -# This is %%{image_install_path} on an arch where that includes ELF files, -# or empty otherwise. -%define elf_image_install_path %{?kernel_image_elf:%{image_install_path}} - -# -# This macro defines the %%files sections for a kernel package -# and its devel and debuginfo packages. -# %%kernel_variant_files [-k vmlinux] -# -%define kernel_variant_files(k:) \ -%if %{1}\ -%{expand:%%files %{?2}}\ -%defattr(-,root,root)\ -/%{image_install_path}/%{?-k:%{-k*}}%{!?-k:vmlinuz}-%{KVERREL}%{?2:.%{2}}\ -%attr(600,root,root) /boot/System.map-%{KVERREL}%{?2:.%{2}}\ -/boot/config-%{KVERREL}%{?2:.%{2}}\ -%dir /lib/modules/%{KVERREL}%{?2:.%{2}}\ -/lib/modules/%{KVERREL}%{?2:.%{2}}/kernel\ -/lib/modules/%{KVERREL}%{?2:.%{2}}/build\ -/lib/modules/%{KVERREL}%{?2:.%{2}}/source\ -/lib/modules/%{KVERREL}%{?2:.%{2}}/extra\ -/lib/modules/%{KVERREL}%{?2:.%{2}}/updates\ -%ifarch %{vdso_arches}\ -/lib/modules/%{KVERREL}%{?2:.%{2}}/vdso\ -/etc/ld.so.conf.d/kernel-%{KVERREL}%{?2:.%{2}}.conf\ -%endif\ -/lib/modules/%{KVERREL}%{?2:.%{2}}/modules.*\ -%ghost /boot/initramfs-%{KVERREL}%{?2:.%{2}}.img\ -%{expand:%%files %{?2:%{2}-}devel}\ -%defattr(-,root,root)\ -/usr/src/kernels/%{KVERREL}%{?2:.%{2}}\ -%if %{with_debuginfo}\ -%ifnarch noarch\ -%if %{fancy_debuginfo}\ -%{expand:%%files -f debuginfo%{?2}.list %{?2:%{2}-}debuginfo}\ -%else\ -%{expand:%%files %{?2:%{2}-}debuginfo}\ -%endif\ -%defattr(-,root,root)\ -%if !%{fancy_debuginfo}\ -%if "%{elf_image_install_path}" != ""\ -%{debuginfodir}/%{elf_image_install_path}/*-%{KVERREL}%{?2:.%{2}}.debug\ -%endif\ -%{debuginfodir}/lib/modules/%{KVERREL}%{?2:.%{2}}\ -%{debuginfodir}/usr/src/kernels/%{KVERREL}%{?2:.%{2}}\ -%endif\ -%endif\ -%endif\ -%endif\ -%{nil} - - -%kernel_variant_files %{with_up} -%kernel_variant_files %{with_smp} smp -%kernel_variant_files %{with_debug} debug -%kernel_variant_files %{with_pae} PAE -%kernel_variant_files %{with_pae_debug} PAEdebug -%kernel_variant_files %{with_omap} omap -%kernel_variant_files %{with_tegra} tegra - -# plz don't put in a version string unless you're going to tag -# and build. - -%changelog -* Wed Nov 09 2011 Chuck Ebbert 3.1.1-1.rc1 -- Linux 3.1.1-rc1 -- Comment out merged patches, will drop when release is final: - ums-realtek-driver-uses-stack-memory-for-DMA.patch - epoll-fix-spurious-lockdep-warnings.patch - crypto-register-cryptd-first.patch - add-macbookair41-keyboard.patch - powerpc-Fix-deadlock-in-icswx-code.patch - iwlagn-fix-ht_params-NULL-pointer-dereference.patch - mmc-Always-check-for-lower-base-frequency-quirk-for-.patch - media-DiBcom-protect-the-I2C-bufer-access.patch - media-dib0700-protect-the-dib0700-buffer-access.patch - WMI-properly-cleanup-devices-to-avoid-crashes.patch - mac80211-fix-remain_off_channel-regression.patch - mac80211-config-hw-when-going-back-on-channel.patch - -* Wed Nov 09 2011 John W. Linville -- Backport brcm80211 from 3.2-rc1 - -* Tue Nov 08 2011 Neil Horman -- Add msi irq ennumeration per device in sysfs (rhbz 752176) - -* Mon Nov 07 2011 Josh Boyer -- Add two patches to fix mac80211 issues (rhbz 731365) - -* Thu Nov 03 2011 Josh Boyer -- Add commits queued for 3.2 for elantech driver (rhbz 728607) -- Fix crash when setting brightness via Fn keys on ideapads (rhbz 748210) - -* Wed Nov 02 2011 Josh Boyer -- Add patch to fix oops when removing wmi module (rhbz 706574) - -* Tue Nov 01 2011 Dave Jones 3.1.0-8 -- allow building the perf rpm for ARM (rhbz 741325) - -* Tue Nov 01 2011 Dave Jones 3.1.0-8 -- Add another Sony laptop to the nonvs blacklist. (rhbz 641789) - -* Tue Nov 1 2011 Josh Boyer 3.1.0-7 -- Drop x86-efi-Calling-__pa-with-an-ioremap-address-is-invalid (rhbz 748516) - -* Mon Oct 31 2011 Josh Boyer -- CVE-2011-4097: oom_badness() integer overflow (rhbz 750402) - -* Fri Oct 28 2011 Josh Boyer -- Add patch to prevent tracebacks on a warning in floppy.c (rhbz 749887) - -* Wed Oct 26 2011 Fedora Release Engineering - 3.1.0-5 -- Rebuilt for glibc bug#747377 - -* Wed Oct 26 2011 Josh Boyer -- CVE-2011-4077: xfs: potential buffer overflow in xfs_readlink() (rhbz 749166) - -* Tue Oct 25 2011 Josh Boyer -- CVE-2011-3347: be2net: promiscuous mode and non-member VLAN packets DoS (rhbz 748691) -- CVE-2011-1083: excessive in kernel CPU consumption when creating large nested epoll structures (rhbz 748668) - -* Mon Oct 24 2011 Josh Boyer -- Backport 3 fixed from linux-next to fix dib0700 playback (rhbz 733827) - -* Mon Oct 24 2011 Chuck Ebbert 3.1.0-1 -- Linux 3.1 - -* Fri Oct 21 2011 Chuck Ebbert 3.1.0-0.rc10.git1.1 -- Update to upstream HEAD (v3.1-rc10-42-g2efd7c0) - -* Fri Oct 21 2011 Dave Jones -- Lower severity of Radeon lockup messages. - -* Wed Oct 19 2011 Dave Jones -- Add Sony VGN-FW21E to nonvs blacklist. (rhbz 641789) - -* Wed Oct 19 2011 Chuck Ebbert 3.1.0-0.rc10.git0.1 -- Fix divide-by-zero in nouveau driver (rhbz #747129) - -* Tue Oct 18 2011 Chuck Ebbert -- Fix lock inversion causing hangs in 3.1-rc9 (rhbz #746485) -- Linux 3.1-rc10 - -* Tue Oct 18 2011 Josh Boyer -- Add patch to fix invalid EFI remap calls from Matt Fleming - -* Mon Oct 17 2011 Josh Boyer -- Add two patches to fix stalls in khugepaged (rhbz 735946) - -* Thu Oct 13 2011 Josh Boyer -- Update usb-add-quirk-for-logitech-webcams.patch with C600 ID (rhbz 742010) - -* Thu Oct 13 2011 Adam Jackson -- drm/i915: Treat SDVO LVDS as digital when parsing EDID (#729882) - -* Thu Oct 13 2011 Josh Boyer -- Add patch from Stanislaw Gruszka to fix iwlagn NULL dereference (rhbz 744155) - -* Tue Oct 11 2011 Josh Boyer -- Disable CONFIG_XEN_BALLOON_MEMORY_HOTPLUG (rhbz 744408) - -* Thu Oct 06 2011 Josh Boyer -- Add patch to fix base frequency check for Ricoh e823 devices (rhbz 722509) - -* Thu Oct 06 2011 Dave Jones -- Taint if virtualbox modules have been loaded. - -* Wed Oct 05 2011 Chuck Ebbert 3.1.0-0.rc9.git0.0 -- Linux 3.1-rc9 - -* Mon Oct 03 2011 Chuck Ebbert 3.1.0-0.rc8.git0.1 -- block: Free queue resources at blk_release_queue() - -* Thu Sep 29 2011 Chuck Ebbert -- Require grubby >= 8.3-1 so initrd line gets added (rhbz #725185) - -* Thu Sep 29 2011 Josh Boyer -- Update logitech USB quirk patch - -* Tue Sep 27 2011 Chuck Ebbert 3.1.0-0.rc8.git0.0 -- Linux 3.1-rc8 -- New option: CONFIG_ARM_ERRATA_764369 is not set -- Fix up utrace.patch to apply after commit f9d81f61c - -* Thu Sep 22 2011 Dave Jones -- Make CONFIG_XEN_PLATFORM_PCI=y (rhbz 740664) - -* Thu Sep 22 2011 Dennis Gilmore -- build vmlinux image for sparc64 - -* Wed Sep 21 2011 Josh Boyer -- Linux 3.1-rc7 - -* Tue Sep 20 2011 Dave Jones -- Limit 32-bit x86 kernels to 32 processors. - -* Tue Sep 20 2011 Ben Skeggs 3.1.0-0.rc6.git0.4.fc16 -- nouveau: patch in updates queued for 3.2, mostly new hw support (GF116/GF119) - -* Fri Sep 16 2011 Josh Boyer 3.1.0-0.rc6.git0.3.fc16 -- Add patch to fix deadlock in ipw2x00 (rhbz 738387) -- Fixup kernel-tools file section for ppc/ppc64 - -* Thu Sep 15 2011 Josh Boyer -- CVE-2011-3191: cifs: fix possible memory corruption in CIFSFindNext - -* Wed Sep 14 2011 Josh Boyer -- Add patch to fix deadlock in ppc64 icswx (rhbz 737984) - -* Wed Sep 14 2011 Neil Horman -- Enable CONFIG_IP_VS_IPV6 (bz 738194) - -* Wed Sep 14 2011 Josh Boyer -- Add support for Macbook Air 4,1 keyboard, trackpad, and bluetooth -- Add patch to fix HVCS on ppc64 (rhbz 738096) -- Add various ibmveth driver fixes (rhbz 733766) - -* Tue Sep 13 2011 Adam Jackson -- drm/i915: Shut the fbc messages up when drm.debug & 4 - -* Mon Sep 12 2011 Josh Boyer 3.1.0-0.rc6.git0.0 -- Linux 3.1-rc6 (contains the fix for 737076) -- Disable debug builds - -* Fri Sep 09 2011 Josh Boyer -- Change to 64K page size for ppc64 kernels (rhbz 736751) - -* Fri Sep 09 2011 Josh Boyer 3.1.0-0.rc5.git0.0 -- Linux 3.1-rc5 - -* Wed Sep 07 2011 Josh Boyer -- Add patch to fix oops when linking entities in ucvideo (rhbz 735437) - -* Fri Sep 02 2011 Dave Jones -- Apply patch to fix lockdep reports from ext4 (rhbz 732572) - -* Thu Sep 01 2011 Dave Jones -- utrace: s390: fix the compile problem with traps.c (rhbz 735118) - -* Tue Aug 30 2011 Dave Jones -- Revert "x86: Serialize EFI time accesses on rtc_lock" (rhbz 732755) - -* Tue Aug 30 2011 Josh Boyer -- Add patch to fix rhbz 606017 - -* Mon Aug 29 2011 Josh Boyer -- Linux 3.1-rc4 - -* Sat Aug 27 2011 Dave Jones -- Fix get_gate_vma usage in i386 NX emulation -- Bring back the 32bit mmap randomization patch for now. - NX emulation is still too dependant upon it. - -* Fri Aug 26 2011 Dave Jones -- Enable CONFIG_DETECT_HUNG_TASK for debug builds & rawhide. - -* Fri Aug 26 2011 Dave Jones -- Drop linux-2.6-debug-vm-would-have-oomkilled.patch - The oom-killer heuristics have improved enough that this should - never be necessary (and it probably doesn't dtrt any more) - -* Fri Aug 26 2011 Dave Jones -- Drop linux-2.6-32bit-mmap-exec-randomization.patch - Outlived it's usefulness (and made of ugly) - -* Fri Aug 26 2011 Dave Jones -- Drop acpi-ec-add-delay-before-write.patch (rhbz 733690) - -* Fri Aug 26 2011 Josh Boyer -- Linux 3.1-rc3-git5 - -* Wed Aug 24 2011 Josh Boyer -- Revert 'iwlwifi: advertise max aggregate size'. (rhbz 708747) - -* Mon Aug 22 2011 Josh Boyer -- Linux 3.1-rc3 -- Add patch to fix duplicate backlight registration (rhbz 732202) - -* Mon Aug 22 2011 Dave Jones -- Avoid false quiescent states in rcutree with CONFIG_RCU_FAST_NO_HZ. (rhbz 577968) - -* Sat Aug 20 2011 Josh Boyer -- Linux 3.1-rc2-git7 -- Add a provides/obsoletes for cpupowerutils-devel - -* Fri Aug 19 2011 Josh Boyer -- Add patch from upstream to fix 64-bit divide error in btrfs -- Add BuildRequires on gettext for cpupowerutils translations - -* Fri Aug 19 2011 Josh Boyer -- Linux 3.1-rc2-git5 -- Change XHCI to builtin (rhbz 731706) -- Add patch to fix race between cryptd and aesni (rhbz 721002) - -* Thu Aug 18 2011 Josh Boyer -- Adjust provides/obsoletes to replace the cpupowerutils package - -* Wed Aug 17 2011 Josh Boyer -- Create the kernel-tools subpackages based on a start by davej - -* Tue Aug 16 2011 Dave Jones -- Prepare for packaging more of tools/ by renaming 'perf' subpackage - to kernel-tools - -* Tue Aug 16 2011 Dennis Gilmore -- add config for arm tegra devices -- setup kernel to build omap image (patch from David Marlin) -- setup kernel to build tegra image based on omap work -- add arm device tree patches - -* Sat Aug 13 2011 Dave Jones -- CPU_FREQ drivers should now be built-in on x86-64. - -* Thu Aug 11 2011 Josh Boyer -- Add patch davej applied to f15 for rhbz 729340 -- Add munged together patch for rhbz 729269 -- Build ide_pmac as a module (rhbz 730039) - -* Tue Aug 09 2011 Josh Boyer -- Add Makefile.config and ARM config changes from David Marlin - -* Tue Aug 09 2011 Josh Boyer -- Add patch davej applied to f15 for rhbz 728872 - -* Tue Aug 09 2011 Dave Jones -- ptrace_report_syscall: check if TIF_SYSCALL_EMU is defined - -* Tue Aug 09 2011 Dave Jones -- Enable CONFIG_SAMSUNG_LAPTOP (rhbz 729363) - -* Mon Aug 08 2011 Josh Boyer -- Bring in utrace fixes davej applied to f15. (rhbz 728379) - -* Fri Aug 05 2011 Josh Boyer -- Adjust Makefile munging for new 3.x numbering scheme - -* Fri Aug 05 2011 Dave Jones -- Deselect CONFIG_DECNET. Unmaintained, and rubbish. - -* Fri Aug 05 2011 Josh Boyer -- 3.0.1 - -* Fri Aug 05 2011 Josh Boyer -- Add patch for rhbz 726701 from Matthew Garrett - -* Thu Aug 04 2011 Dave Jones -- Drop neuter_intel_microcode_load.patch (rhbz 690930) - -* Wed Aug 03 2011 John W. Linville -- Disable CONFIG_BCMA since no driver currently uses it (rhbz 727796) - -* Wed Aug 03 2011 Josh Boyer -- Add patch to fix backtrace in cdc_ncm driver (rhbz 720128) -- Add patch to fix backtrace in usm-realtek driver (rhbz 720054) - -* Tue Aug 02 2011 Josh Boyer -- Add patch to fix HFSPlus filesystem mounting (rhbz 720771) - -* Tue Aug 02 2011 Dave Jones -- Change USB_SERIAL_OPTION back to modular. (rhbz 727680) - -* Tue Aug 02 2011 Josh Boyer -- Fix epoll recursive lockdep warnings (rhbz 722472) -- Turn debug builds back on - -* Tue Aug 02 2011 Josh Boyer -- Add change from Yanko Kaneti to get the rt2x00 drivers in modules.networking - (rhbz 708314) - -* Fri Jul 29 2011 Dave Jones -- Fix scsi_dispatch_cmd oops (USB eject problems, etc). - -* Thu Jul 28 2011 Dave Jones -- module-init-tools needs to be a prereq, not a conflict. - -* Thu Jul 28 2011 Josh Boyer -- Backport patch to correct udlfb removal events (rhbz 726163) - -* Wed Jul 27 2011 Dave Jones -- Turn off debug builds. - -* Fri Jul 22 2011 Dave Jones -- bootwrapper needs objcopy. Add it to requires: (wwoods) - -* Fri Jul 22 2011 Kyle McMartin 3.0.0-1 -- Linux 3.0, but really 3.0.0 (sigh) - -* Thu Jul 21 2011 Chuck Ebbert 3.0-0.rc7.git10.1 -- 3.0-rc7-git10 -- Use ext4 for ext2 and ext3 filesystems (CONFIG_EXT4_USE_FOR_EXT23=y) - -* Thu Jul 21 2011 Dave Jones -- Switch BLK_DEV_RAM to be modular (rhbz 720833) - -* Wed Jul 20 2011 Chuck Ebbert 3.0-0.rc7.git8.1 -- 3.0-rc7-git8 - -* Fri Jul 15 2011 Dave Jones 3.0-0.rc7.git3.1 -- 3.0-rc7-git3 - -* Fri Jul 15 2011 Dave Jones -- Bring back utrace until uprobes gets merged upstream. - -* Wed Jul 13 2011 Kyle McMartin 3.0-0.rc7.git1.1 -- Update to snapshot 3.0-rc7-git1 for intel drm fixes. - -* Tue Jul 12 2011 John W. Linville -- zd1211rw: fix invalid signal values from device (rhbz 720093) - -* Tue Jul 12 2011 John W. Linville -- rt2x00: Add device ID for RT539F device. (rhbz 720594) - -* Tue Jul 12 2011 Kyle McMartin 3.0-0.rc7.git0.1 -- Linux 3.0-rc7, hopefully the last before the Great Renumbering becomes - official. - -* Mon Jul 11 2011 Dave Jones -- Change BINFMT_MISC to be modular. (rhbz 695415) - -* Sun Jul 10 2011 Kyle McMartin 3.0-0.rc6.git6.1 -- Linux 3.0-rc6-git6 -- iwlagn-fix-dma-direction.patch: drop. -- Revert CONFIG_X86_RESERVE_LOW=640, it breaks booting on x86_64. - -* Thu Jul 07 2011 Dave Jones -- Centralise CPU_FREQ options into config-generic. - Switch to using ondemand by default. (rhbz 713572) - -* Wed Jul 06 2011 Chuck Ebbert -- Set CONFIG_X86_RESERVE_LOW=640 as requested by mjg - -* Mon Jul 04 2011 Kyle McMartin 3.0-0.rc6.git0.1 -- Linux 3.0-rc6 -- [generic] SCSI_ISCI=m, because why not - -* Sat Jul 02 2011 Kyle McMartin 3.0-0.rc5.git5.1 -- Linux 3.0-rc5-git5 - -* Mon Jun 27 2011 Kyle McMartin 3.0-0.rc5.git0.1 -- Linux 3.0-rc5 - -* Mon Jun 27 2011 Dave Jones -- Disable CONFIG_CRYPTO_MANAGER_DISABLE_TESTS, as this also disables FIPS (rhbz 716942) - -* Thu Jun 23 2011 Kyle McMartin 3.0-0.rc4.git3.1 -- Linux 3.0-rc4-git3 -- Drop linux-3.0-fix-uts-release.patch, and instead just perl the Makefile -- linux-2.6-silence-noise.patch: fix context -- iwlagn-fix-dma-direction.patch: fix DMAR errors (for me at least) - -* Wed Jun 22 2011 Kyle McMartin 3.0-0.rc4.git0.2 -- Re-enable debuginfo generation. Thanks to Richard Jones for noticing... no - wonder builds had been so quick lately. - -* Tue Jun 21 2011 Kyle McMartin 3.0-0.rc4.git0.1 -- Linux 3.0-rc4 (getting closer...) - -* Fri Jun 17 2011 Kyle McMartin 3.0-0.rc3.git6.1 -- Update to 3.0-rc3-git6 - -* Fri Jun 17 2011 Dave Jones -- drop qcserial 'compile fix' that was just duplicating an include. -- drop struct sizeof debug patch. (no real value. not upstreamable) -- drop linux-2.6-debug-always-inline-kzalloc.patch. - Can't recall why this was added. Can easily re-add if deemed necessary. - -* Fri Jun 17 2011 Kyle McMartin -- linux-2.6-defaults-pci_no_msi.patch: drop, haven't toggled the default - in many moons. -- linux-2.6-defaults-pci_use_crs.patch: ditto. -- linux-2.6-selinux-mprotect-checks.patch: upstream a while ago. -- drm-i915-gen4-has-non-power-of-two-strides.patch: drop buggy bugfix -- drop some more unapplied crud. -- We haven't applied firewire patches in a dogs age. - -* Fri Jun 17 2011 Kyle McMartin 3.0-0.rc3.git5.1 -- Try updating to a git snapshot for the first time in 3.0-rc, - update to 3.0-rc3-git5 -- Fix a subtle bug I introduced in 3.0-rc1, "patch-3." is 9 letters, not 10. - -* Thu Jun 16 2011 Kyle McMartin -- Disable mm patches which had been submitted against 2.6.39, as Rik reports - they seem to aggravate a VM_BUG_ON. More investigation is necessary. - -* Wed Jun 15 2011 Kyle McMartin -- Conflict with pre-3.2.1-5 versions of mdadm. (#710646) - -* Wed Jun 15 2011 Kyle McMartin -- Build in aesni-intel on i686 for symmetry with 64-bit. - -* Tue Jun 14 2011 Kyle McMartin 3.0-0.rc3.git0.3 -- Fix libdm conflict (whose bright idea was it to give subpackages differing - version numbers?) - -* Tue Jun 14 2011 Kyle McMartin -- Update to 3.0-rc3, add another conflicts to deal with 2 digit - versions (libdm.) -- Simplify linux-3.0-fix-uts-release.patch now that SUBLEVEL is optional. -- revert-ftrace-remove-unnecessary-disabling-of-irqs.patch: drop upstreamed - patch. -- drm-intel-eeebox-eb1007-quirk.patch: ditto. -- ath5k-disable-fast-channel-switching-by-default.patch: ditto. - -* Thu Jun 09 2011 Kyle McMartin -- ath5k-disable-fast-channel-switching-by-default.patch (rhbz#709122) - (korgbz#34992) [a99168ee in wireless-next] - -* Thu Jun 09 2011 Kyle McMartin 3.0-0.rc2.git0.2 -- rhbz#710921: revert-ftrace-remove-unnecessary-disabling-of-irqs.patch - -* Wed Jun 08 2011 Kyle McMartin 3.0-0.rc2.git0.1 -- Update to 3.0-rc2, rebase utsname fix. -- Build IPv6 into the kernel for a variety of reasons - (http://lists.fedoraproject.org/pipermail/kernel/2011-June/003105.html) - -* Mon Jun 06 2011 Kyle McMartin 3.0-0.rc1.git0.3 -- Conflict with module-init-tools older than 3.13 to ensure the - 3.0 transition is handled correctly. - -* Wed Jun 01 2011 Kyle McMartin 3.0-0.rc1.git0.2 -- Fix utsname for 3.0-rc1 - -* Mon May 30 2011 Kyle McMartin 3.0-0.rc1.git0.1 -- Linux 3.0-rc1 (won't build until module-init-tools gets an update.) - -* Mon May 30 2011 Kyle McMartin -- Trimmed changelog, see fedpkg git for earlier history. - -### -# The following Emacs magic makes C-c C-e use UTC dates. -# Local Variables: -# rpm-change-log-uses-utc: t -# End: -### From a20eace265bc0427a237967c4643a27016923a17 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 11 Nov 2011 10:03:43 -0500 Subject: [PATCH 135/487] Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 --- bcma-brcmsmac-compat.patch | 35 +++++++++++++++++++++++++++++++++++ config-generic | 7 ++++++- kernel.spec | 7 +++++++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 bcma-brcmsmac-compat.patch diff --git a/bcma-brcmsmac-compat.patch b/bcma-brcmsmac-compat.patch new file mode 100644 index 000000000..e16e5b0c5 --- /dev/null +++ b/bcma-brcmsmac-compat.patch @@ -0,0 +1,35 @@ +Simple patch to remove the overlap between the bcma (i.e. b43) driver +and the brcmsmac driver. David Woodhouse +confirmed that this patch restores functionality of bcm4331 devices. + +-- John W. Linville + +diff -up linux-3.1.x86_64/drivers/bcma/host_pci.c.orig linux-3.1.x86_64/drivers/bcma/host_pci.c +--- linux-3.1.x86_64/drivers/bcma/host_pci.c.orig 2011-11-10 11:41:26.829742757 -0500 ++++ linux-3.1.x86_64/drivers/bcma/host_pci.c 2011-11-10 11:41:22.884792078 -0500 +@@ -225,11 +225,13 @@ static void bcma_host_pci_remove(struct + } + + static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { +- { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, ++#if 0 /* Not in Fedora... */ ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, ++#endif + { 0, }, + }; + MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl); +diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig +--- linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig 2011-11-10 11:42:31.764930961 -0500 ++++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig 2011-11-10 11:42:33.613907846 -0500 +@@ -5,7 +5,6 @@ config BRCMSMAC + tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" + depends on PCI + depends on MAC80211 +- depends on BCMA=n + select BRCMUTIL + select FW_LOADER + select CRC_CCITT diff --git a/config-generic b/config-generic index 879a09b50..65c01a8ae 100644 --- a/config-generic +++ b/config-generic @@ -1462,6 +1462,7 @@ CONFIG_B43=m CONFIG_B43_PCMCIA=y CONFIG_B43_SDIO=y CONFIG_B43_BCMA=y +CONFIG_B43_BCMA_PIO=y # CONFIG_B43_DEBUG is not set CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y @@ -4576,7 +4577,11 @@ CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 CONFIG_TEST_KSTRTOX=m -# CONFIG_BCMA is not set +CONFIG_BCMA=m +CONFIG_BCMA_BLOCKIO=y +CONFIG_BCMA_HOST_PCI_POSSIBLE=y +CONFIG_BCMA_HOST_PCI=y +# CONFIG_BCMA_DEBUG is not set # CONFIG_GOOGLE_FIRMWARE is not set CONFIG_INTEL_MID_PTI=m diff --git a/kernel.spec b/kernel.spec index 0454637eb..447940bec 100644 --- a/kernel.spec +++ b/kernel.spec @@ -786,6 +786,8 @@ Patch21080: sysfs-msi-irq-per-device.patch #backport brcm80211 from 3.2-rc1 Patch21090: brcm80211.patch +Patch21091: bcma-brcmsmac-compat.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1452,6 +1454,8 @@ ApplyPatch sysfs-msi-irq-per-device.patch #backport brcm80211 from 3.2-rc1 ApplyPatch brcm80211.patch +# Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 +ApplyPatch bcma-brcmsmac-compat.patch # END OF PATCH APPLICATIONS @@ -2154,6 +2158,9 @@ fi # and build. %changelog +* Fri Nov 11 2011 John W. Linville +- Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 + * Thu Nov 10 2011 Chuck Ebbert - Sync samsung-laptop driver with what's in 3.2 (rhbz 747560) From a596f94913476f4f4c5a5b09b9bebd40eeab5205 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 11 Nov 2011 16:13:25 -0500 Subject: [PATCH 136/487] Linux 3.1.1 Drop the patches Chuck so nicely listed for me --- ...rly-cleanup-devices-to-avoid-crashes.patch | 41 - add-macbookair41-keyboard.patch | 119 -- crypto-register-cryptd-first.patch | 26 - epoll-fix-spurious-lockdep-warnings.patch | 116 -- ...x-ht_params-NULL-pointer-dereference.patch | 43 - kernel.spec | 51 +- ...config-hw-when-going-back-on-channel.patch | 40 - ...11-fix-remain_off_channel-regression.patch | 44 - ...-DiBcom-protect-the-I2C-bufer-access.patch | 1150 ----------------- ...00-protect-the-dib0700-buffer-access.patch | 248 ---- ...-for-lower-base-frequency-quirk-for-.patch | 73 -- powerpc-Fix-deadlock-in-icswx-code.patch | 74 -- sources | 2 +- ...tek-driver-uses-stack-memory-for-DMA.patch | 143 -- 14 files changed, 6 insertions(+), 2164 deletions(-) delete mode 100644 WMI-properly-cleanup-devices-to-avoid-crashes.patch delete mode 100644 add-macbookair41-keyboard.patch delete mode 100644 crypto-register-cryptd-first.patch delete mode 100644 epoll-fix-spurious-lockdep-warnings.patch delete mode 100644 iwlagn-fix-ht_params-NULL-pointer-dereference.patch delete mode 100644 mac80211-config-hw-when-going-back-on-channel.patch delete mode 100644 mac80211-fix-remain_off_channel-regression.patch delete mode 100644 media-DiBcom-protect-the-I2C-bufer-access.patch delete mode 100644 media-dib0700-protect-the-dib0700-buffer-access.patch delete mode 100644 mmc-Always-check-for-lower-base-frequency-quirk-for-.patch delete mode 100644 powerpc-Fix-deadlock-in-icswx-code.patch delete mode 100644 ums-realtek-driver-uses-stack-memory-for-DMA.patch diff --git a/WMI-properly-cleanup-devices-to-avoid-crashes.patch b/WMI-properly-cleanup-devices-to-avoid-crashes.patch deleted file mode 100644 index 1119d25f5..000000000 --- a/WMI-properly-cleanup-devices-to-avoid-crashes.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 023b9565972a4a5e0f01b9aa32680af6e9b5c388 Mon Sep 17 00:00:00 2001 -From: Dmitry Torokhov -Date: Wed, 7 Sep 2011 15:00:02 -0700 -Subject: [PATCH] WMI: properly cleanup devices to avoid crashes - -We need to remove devices that we destroy from the list, otherwise -we'll crash if there are more than one "_WDG" methods in DSDT. - -This fixes https://bugzilla.kernel.org/show_bug.cgi?id=32052 - -Tested-by: Ilya Tumaykin -Cc: stable@kernel.org -Signed-off-by: Dmitry Torokhov -Acked-by: Carlos Corbacho -Signed-off-by: Matthew Garrett ---- - drivers/platform/x86/wmi.c | 6 +++++- - 1 files changed, 5 insertions(+), 1 deletions(-) - -diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c -index f23d5a8..9b88be4 100644 ---- a/drivers/platform/x86/wmi.c -+++ b/drivers/platform/x86/wmi.c -@@ -754,9 +754,13 @@ static void wmi_free_devices(void) - struct wmi_block *wblock, *next; - - /* Delete devices for all the GUIDs */ -- list_for_each_entry_safe(wblock, next, &wmi_block_list, list) -+ list_for_each_entry_safe(wblock, next, &wmi_block_list, list) { -+ list_del(&wblock->list); - if (wblock->dev.class) - device_unregister(&wblock->dev); -+ else -+ kfree(wblock); -+ } - } - - static bool guid_already_parsed(const char *guid_string) --- -1.7.6.4 - diff --git a/add-macbookair41-keyboard.patch b/add-macbookair41-keyboard.patch deleted file mode 100644 index bd5afdafe..000000000 --- a/add-macbookair41-keyboard.patch +++ /dev/null @@ -1,119 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Pieter-Augustijn Van Malleghem -Newsgroups: gmane.linux.kernel.input -Subject: [PATCH] Add MacBookAir4,1 keyboard support -Date: Wed, 7 Sep 2011 16:15:52 -0400 -Lines: 72 -Approved: news@gmane.org -Message-ID: <20110907201552.GA1962@Caligula> -NNTP-Posting-Host: lo.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Trace: dough.gmane.org 1315426570 11003 80.91.229.12 (7 Sep 2011 20:16:10 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Wed, 7 Sep 2011 20:16:10 +0000 (UTC) -To: linux-input@vger.kernel.org -Original-X-From: linux-input-owner@vger.kernel.org Wed Sep 07 22:16:06 2011 -Return-path: -Envelope-to: glki-linux-input-2@lo.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1R1OXV-0007QX-Ll - for glki-linux-input-2@lo.gmane.org; Wed, 07 Sep 2011 22:16:06 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1751419Ab1IGUQE (ORCPT ); - Wed, 7 Sep 2011 16:16:04 -0400 -Original-Received: from mail-vx0-f174.google.com ([209.85.220.174]:57168 "EHLO - mail-vx0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1751237Ab1IGUQC (ORCPT - ); Wed, 7 Sep 2011 16:16:02 -0400 -Original-Received: by vxj15 with SMTP id 15so31147vxj.19 - for ; Wed, 07 Sep 2011 13:16:02 -0700 (PDT) -Original-Received: by 10.52.69.210 with SMTP id g18mr64348vdu.133.1315426562281; - Wed, 07 Sep 2011 13:16:02 -0700 (PDT) -Original-Received: from Caligula ([140.247.246.50]) - by mx.google.com with ESMTPS id ch2sm944169vdc.19.2011.09.07.13.16.01 - (version=TLSv1/SSLv3 cipher=OTHER); - Wed, 07 Sep 2011 13:16:01 -0700 (PDT) -Content-Disposition: inline -User-Agent: Mutt/1.5.21 (2010-09-15) -Original-Sender: linux-input-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-input@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel.input:21462 -Archived-At: - -This patch adds support for the Apple MacBookAir4,1 released in July -2011. It was inspired by Joshua Dillon's patch for the MacBookAir4,2 -posted on http://www.almostsure.com/mba42/hid-apple-dkms.patch. - -Signed-off-by: Pieter-Augustijn Van Malleghem -diff -uNr linux/drivers/hid/hid-apple.c patched/drivers/hid/hid-apple.c ---- linux/drivers/hid/hid-apple.c 2011-09-06 23:41:58.000000000 -0400 -+++ patched/drivers/hid/hid-apple.c 2011-09-06 23:53:05.000000000 -0400 -@@ -183,6 +183,9 @@ - if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI && - hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) - table = macbookair_fn_keys; -+ else if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI && -+ hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) -+ table = apple_fn_keys; - else if (hid->product < 0x21d || hid->product >= 0x300) - table = powerbook_fn_keys; - else -@@ -493,6 +499,12 @@ - .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), - .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI), -+ .driver_data = APPLE_HAS_FN }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO), -+ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS), -+ .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), -diff -uNr linux/drivers/hid/hid-core.c patched/drivers/hid/hid-core.c ---- linux/drivers/hid/hid-core.c 2011-09-06 23:41:58.000000000 -0400 -+++ patched/drivers/hid/hid-core.c 2011-09-06 23:56:22.000000000 -0400 -@@ -1340,6 +1340,9 @@ - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS) }, -@@ -1892,6 +1895,9 @@ - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, - { } -diff -uNr linux/drivers/hid/hid-ids.h patched/drivers/hid/hid-ids.h ---- linux/drivers/hid/hid-ids.h 2011-09-06 23:41:58.000000000 -0400 -+++ patched/drivers/hid/hid-ids.h 2011-09-06 23:57:39.000000000 -0400 -@@ -109,6 +109,9 @@ - #define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 - #define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 - #define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 -+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249 -+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a -+#define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b - #define USB_DEVICE_ID_APPLE_ALU_REVB_ANSI 0x024f - #define USB_DEVICE_ID_APPLE_ALU_REVB_ISO 0x0250 - #define USB_DEVICE_ID_APPLE_ALU_REVB_JIS 0x0251 --- -To unsubscribe from this list: send the line "unsubscribe linux-input" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - diff --git a/crypto-register-cryptd-first.patch b/crypto-register-cryptd-first.patch deleted file mode 100644 index 0cd55d6fc..000000000 --- a/crypto-register-cryptd-first.patch +++ /dev/null @@ -1,26 +0,0 @@ -commit 9d4c522a113f6caa8b792ae829a25490fa87b1a2 -Author: Herbert Xu -Date: Fri Aug 19 16:11:23 2011 +0800 - - crypto: cryptd - Use subsys_initcall to prevent races with aesni - - As cryptd is depeneded on by other algorithms such as aesni-intel, - it needs to be registered before them. When everything is built - as modules, this occurs naturally. However, for this to work when - they are built-in, we need to use subsys_initcall in cryptd. - - Signed-off-by: Herbert Xu - -diff --git a/crypto/cryptd.c b/crypto/cryptd.c -index e46d21a..671d4d6 100644 ---- a/crypto/cryptd.c -+++ b/crypto/cryptd.c -@@ -945,7 +945,7 @@ static void __exit cryptd_exit(void) - crypto_unregister_template(&cryptd_tmpl); - } - --module_init(cryptd_init); -+subsys_initcall(cryptd_init); - module_exit(cryptd_exit); - - MODULE_LICENSE("GPL"); diff --git a/epoll-fix-spurious-lockdep-warnings.patch b/epoll-fix-spurious-lockdep-warnings.patch deleted file mode 100644 index c163a86d7..000000000 --- a/epoll-fix-spurious-lockdep-warnings.patch +++ /dev/null @@ -1,116 +0,0 @@ -epoll can acquire multiple ep->mutex on multiple "struct eventpoll"s -at once in the case where one epoll fd is monitoring another epoll -fd. This is perfectly OK, since we're careful about the lock ordering, -but causes spurious lockdep warnings. Annotate the recursion using -mutex_lock_nested, and add a comment explaining the nesting rules for -good measure. - -Reported-by: Paul Bolle -Signed-off-by: Nelson Elhage ---- - I've tested this on a synthetic epoll test case, that just adds e1 to - e2 and then does an epoll_wait(). I verified that it caused lockdep - problems on 3.0 and that this patch fixed it, but I haven't done more - extensive testing. Paul, are you able to test systemd against this? - - fs/eventpoll.c | 25 ++++++++++++++++++------- - 1 files changed, 18 insertions(+), 7 deletions(-) - -diff --git a/fs/eventpoll.c b/fs/eventpoll.c -index f9cfd16..0cb7bc6 100644 ---- a/fs/eventpoll.c -+++ b/fs/eventpoll.c -@@ -76,6 +76,15 @@ - * Events that require holding "epmutex" are very rare, while for - * normal operations the epoll private "ep->mtx" will guarantee - * a better scalability. -+ * It is possible to acquire multiple "ep->mtx"es at once in the case -+ * when one epoll fd is added to another. In this case, we always -+ * acquire the locks in the order of nesting (i.e. after epoll_ctl(e1, -+ * EPOLL_CTL_ADD, e2), e1->mtx will always be acquired before -+ * e2->mtx). Since we disallow cycles of epoll file descriptors, this -+ * ensures that the mutexes are well-ordered. In order to communicate -+ * this nesting to lockdep, when walking a tree of epoll file -+ * descriptors, we use the current recursion depth as the lockdep -+ * subkey. - */ - - /* Epoll private bits inside the event mask */ -@@ -464,13 +473,15 @@ static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi) - * @ep: Pointer to the epoll private data structure. - * @sproc: Pointer to the scan callback. - * @priv: Private opaque data passed to the @sproc callback. -+ * @depth: The current depth of recursive f_op->poll calls. - * - * Returns: The same integer error code returned by the @sproc callback. - */ - static int ep_scan_ready_list(struct eventpoll *ep, - int (*sproc)(struct eventpoll *, - struct list_head *, void *), -- void *priv) -+ void *priv, -+ int depth) - { - int error, pwake = 0; - unsigned long flags; -@@ -481,7 +492,7 @@ static int ep_scan_ready_list(struct eventpoll *ep, - * We need to lock this because we could be hit by - * eventpoll_release_file() and epoll_ctl(). - */ -- mutex_lock(&ep->mtx); -+ mutex_lock_nested(&ep->mtx, depth); - - /* - * Steal the ready list, and re-init the original one to the -@@ -670,7 +681,7 @@ static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head, - - static int ep_poll_readyevents_proc(void *priv, void *cookie, int call_nests) - { -- return ep_scan_ready_list(priv, ep_read_events_proc, NULL); -+ return ep_scan_ready_list(priv, ep_read_events_proc, NULL, call_nests + 1); - } - - static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait) -@@ -737,7 +748,7 @@ void eventpoll_release_file(struct file *file) - - ep = epi->ep; - list_del_init(&epi->fllink); -- mutex_lock(&ep->mtx); -+ mutex_lock_nested(&ep->mtx, 0); - ep_remove(ep, epi); - mutex_unlock(&ep->mtx); - } -@@ -1134,7 +1145,7 @@ static int ep_send_events(struct eventpoll *ep, - esed.maxevents = maxevents; - esed.events = events; - -- return ep_scan_ready_list(ep, ep_send_events_proc, &esed); -+ return ep_scan_ready_list(ep, ep_send_events_proc, &esed, 0); - } - - static inline struct timespec ep_set_mstimeout(long ms) -@@ -1267,7 +1278,7 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests) - struct rb_node *rbp; - struct epitem *epi; - -- mutex_lock(&ep->mtx); -+ mutex_lock_nested(&ep->mtx, call_nests + 1); - for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) { - epi = rb_entry(rbp, struct epitem, rbn); - if (unlikely(is_file_epoll(epi->ffd.file))) { -@@ -1409,7 +1420,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, - } - - -- mutex_lock(&ep->mtx); -+ mutex_lock_nested(&ep->mtx, 0); - - /* - * Try to lookup the file inside our RB tree, Since we grabbed "mtx" --- -1.7.4.1 - --- -To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/iwlagn-fix-ht_params-NULL-pointer-dereference.patch b/iwlagn-fix-ht_params-NULL-pointer-dereference.patch deleted file mode 100644 index 4dcf490bb..000000000 --- a/iwlagn-fix-ht_params-NULL-pointer-dereference.patch +++ /dev/null @@ -1,43 +0,0 @@ -This fix regression introduced by commit: - -commit 15b3f3b006b42a678523cad989bfd60b76bf4403 -Author: Wey-Yi Guy -Date: Fri Jun 3 07:54:13 2011 -0700 - - iwlagn: set smps mode after assoc for 1000 device - -Also remove unneeded brackets on the way. - -Address: -https://bugzilla.redhat.com/show_bug.cgi?id=744155 - -If fix will not get 3.1 release, it should be applied in 3.1 stable. - -Cc: stable@kernel.org # 3.1+ -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -index ca632f9..5004342 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -@@ -296,8 +296,8 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv, - return ret; - } - -- if ((ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION) && -- priv->cfg->ht_params->smps_mode) -+ if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION && -+ priv->cfg->ht_params && priv->cfg->ht_params->smps_mode) - ieee80211_request_smps(ctx->vif, - priv->cfg->ht_params->smps_mode); - --- -1.7.1 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index 447940bec..26ecb0248 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -65,7 +65,7 @@ Summary: The Linux kernel # Do we have a -stable update to apply? %define stable_update 1 # Is it a -stable RC? -%define stable_rc 1 +%define stable_rc 0 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -708,8 +708,6 @@ Patch2900: linux-2.6-v4l-dvb-update.patch Patch2901: linux-2.6-v4l-dvb-experimental.patch Patch2902: linux-2.6-v4l-dvb-uvcvideo-update.patch -Patch2903: media-DiBcom-protect-the-I2C-bufer-access.patch -Patch2904: media-dib0700-protect-the-dib0700-buffer-access.patch Patch2905: media-dib0700-correct-error-message.patch Patch3000: rcutree-avoid-false-quiescent-states.patch @@ -725,12 +723,9 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12021: udlfb-bind-framebuffer-to-interface.patch -Patch12023: ums-realtek-driver-uses-stack-memory-for-DMA.patch -Patch12024: epoll-fix-spurious-lockdep-warnings.patch Patch12025: rcu-avoid-just-onlined-cpu-resched.patch Patch12026: block-stray-block-put-after-teardown.patch Patch12027: usb-add-quirk-for-logitech-webcams.patch -Patch12029: crypto-register-cryptd-first.patch Patch12030: epoll-limit-paths.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch @@ -738,23 +733,14 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13002: revert-efi-rtclock.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch -Patch13007: add-macbookair41-keyboard.patch - Patch13009: hvcs_pi_buf_alloc.patch -Patch13013: powerpc-Fix-deadlock-in-icswx-code.patch - -Patch13014: iwlagn-fix-ht_params-NULL-pointer-dereference.patch - Patch20000: utrace.patch # Flattened devicetree support Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch -#rhbz #722509 -Patch21002: mmc-Always-check-for-lower-base-frequency-quirk-for-.patch - #rhbz #735946 Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch @@ -768,19 +754,12 @@ Patch21050: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch Patch21070: oom-fix-integer-overflow-of-points.patch -#rhbz 706574 -Patch21071: WMI-properly-cleanup-devices-to-avoid-crashes.patch - #rhbz 728607 Patch21060: elantech.patch #rhbz 748210 Patch21061: ideapad-Check-if-acpi-already-handle-backlight.patch -#rhbz 731365 -Patch21062: mac80211-fix-remain_off_channel-regression.patch -Patch21063: mac80211-config-hw-when-going-back-on-channel.patch - #rhbz752176 Patch21080: sysfs-msi-irq-per-device.patch @@ -1379,7 +1358,6 @@ ApplyPatch linux-2.6-silence-acpi-blacklist.patch ApplyOptionalPatch linux-2.6-v4l-dvb-fixes.patch ApplyOptionalPatch linux-2.6-v4l-dvb-update.patch ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch -#ApplyPatch linux-2.6-v4l-dvb-uvcvideo-update.patch # Platform fixes not sent for -stable ApplyPatch samsung-laptop-brightness-fixes-3.2.patch @@ -1392,34 +1370,19 @@ ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch add-appleir-usb-driver.patch ApplyPatch udlfb-bind-framebuffer-to-interface.patch -#ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch -#ApplyPatch epoll-fix-spurious-lockdep-warnings.patch ApplyPatch epoll-limit-paths.patch ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch ApplyPatch block-stray-block-put-after-teardown.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch -#ApplyPatch crypto-register-cryptd-first.patch - # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch revert-efi-rtclock.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch -#ApplyPatch add-macbookair41-keyboard.patch - ApplyPatch hvcs_pi_buf_alloc.patch -#ApplyPatch powerpc-Fix-deadlock-in-icswx-code.patch - -#ApplyPatch iwlagn-fix-ht_params-NULL-pointer-dereference.patch - -#rhbz #722509 -#ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch - -#ApplyPatch media-DiBcom-protect-the-I2C-bufer-access.patch -#ApplyPatch media-dib0700-protect-the-dib0700-buffer-access.patch ApplyPatch media-dib0700-correct-error-message.patch # utrace. @@ -1436,19 +1399,12 @@ ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch #rhbz 750402 ApplyPatch oom-fix-integer-overflow-of-points.patch -#rhbz 706574 -#ApplyPatch WMI-properly-cleanup-devices-to-avoid-crashes.patch - #rhbz 728607 ApplyPatch elantech.patch #rhbz 748210 ApplyPatch ideapad-Check-if-acpi-already-handle-backlight.patch -#rhbz 731365 -#ApplyPatch mac80211-fix-remain_off_channel-regression.patch -#ApplyPatch mac80211-config-hw-when-going-back-on-channel.patch - #rhbz 752176 ApplyPatch sysfs-msi-irq-per-device.patch @@ -2158,6 +2114,9 @@ fi # and build. %changelog +* Fri Nov 11 2011 Josh Boyer 3.1.1-1 +- Linux 3.1.1 + * Fri Nov 11 2011 John W. Linville - Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 diff --git a/mac80211-config-hw-when-going-back-on-channel.patch b/mac80211-config-hw-when-going-back-on-channel.patch deleted file mode 100644 index 351082744..000000000 --- a/mac80211-config-hw-when-going-back-on-channel.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 776308dd5fa8a41e8bbb79818a66bd68a7db757e Mon Sep 17 00:00:00 2001 -From: Eliad Peller -Date: Thu, 20 Oct 2011 19:05:50 +0200 -Subject: [PATCH] mac80211: config hw when going back on-channel - -When going back on-channel, we should reconfigure -the hw iff the hardware is not already configured -to the operational channel. - -Signed-off-by: Eliad Peller -Cc: stable@kernel.org # 2.6.39+ -Signed-off-by: John W. Linville ---- - net/mac80211/work.c | 3 +-- - 1 files changed, 1 insertions(+), 2 deletions(-) - -diff --git a/net/mac80211/work.c b/net/mac80211/work.c -index bf5be22..6c53b6d 100644 ---- a/net/mac80211/work.c -+++ b/net/mac80211/work.c -@@ -1091,7 +1091,6 @@ static void ieee80211_work_work(struct work_struct *work) - } - - if (!remain_off_channel && local->tmp_channel) { -- bool on_oper_chan = ieee80211_cfg_on_oper_channel(local); - local->tmp_channel = NULL; - /* If tmp_channel wasn't operating channel, then - * we need to go back on-channel. -@@ -1101,7 +1100,7 @@ static void ieee80211_work_work(struct work_struct *work) - * we still need to do a hardware config. Currently, - * we cannot be here while scanning, however. - */ -- if (ieee80211_cfg_on_oper_channel(local) && !on_oper_chan) -+ if (!ieee80211_cfg_on_oper_channel(local)) - ieee80211_hw_config(local, 0); - - /* At the least, we need to disable offchannel_ps, --- -1.7.6.2 - diff --git a/mac80211-fix-remain_off_channel-regression.patch b/mac80211-fix-remain_off_channel-regression.patch deleted file mode 100644 index 9f5d8f687..000000000 --- a/mac80211-fix-remain_off_channel-regression.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 682ba5a44516529b29fc780c055e06104d36e31e Mon Sep 17 00:00:00 2001 -From: Eliad Peller -Date: Thu, 20 Oct 2011 19:05:49 +0200 -Subject: [PATCH] mac80211: fix remain_off_channel regression - -The offchannel code is currently broken - we should -remain_off_channel if the work was started, and -the work's channel and channel_type are the same -as local->tmp_channel and local->tmp_channel_type. - -However, if wk->chan_type and local->tmp_channel_type -coexist (e.g. have the same channel type), we won't -remain_off_channel. - -This behavior was introduced by commit da2fd1f -("mac80211: Allow work items to use existing -channel type.") - -Tested-by: Ben Greear -Signed-off-by: Eliad Peller -Cc: stable@kernel.org # 2.6.39+ -Signed-off-by: John W. Linville ---- - net/mac80211/work.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/net/mac80211/work.c b/net/mac80211/work.c -index 94472eb..bf5be22 100644 ---- a/net/mac80211/work.c -+++ b/net/mac80211/work.c -@@ -1084,8 +1084,8 @@ static void ieee80211_work_work(struct work_struct *work) - continue; - if (wk->chan != local->tmp_channel) - continue; -- if (ieee80211_work_ct_coexists(wk->chan_type, -- local->tmp_channel_type)) -+ if (!ieee80211_work_ct_coexists(wk->chan_type, -+ local->tmp_channel_type)) - continue; - remain_off_channel = true; - } --- -1.7.6.2 - diff --git a/media-DiBcom-protect-the-I2C-bufer-access.patch b/media-DiBcom-protect-the-I2C-bufer-access.patch deleted file mode 100644 index 1b2a54b86..000000000 --- a/media-DiBcom-protect-the-I2C-bufer-access.patch +++ /dev/null @@ -1,1150 +0,0 @@ -From: Patrick Boettcher -Date: Wed, 3 Aug 2011 15:08:21 +0000 (-0300) -Subject: [media] DiBcom: protect the I2C bufer access -X-Git-Tag: next-20110927~67^2~4^2~225 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=79fcce3230b140f7675f8529ee53fe2f9644f902 - -[media] DiBcom: protect the I2C bufer access - -This patch protects the I2C buffer access in order to manage concurrent -access. This protection is done using mutex. -Furthermore, for the dib9000, if a pid filtering command is -received during the tuning, this pid filtering command is delayed to -avoid any concurrent access issue. - -Cc: Mauro Carvalho Chehab -Cc: Florian Mickler -Cc: stable@kernel.org -Signed-off-by: Olivier Grenie -Signed-off-by: Patrick Boettcher -Signed-off-by: Mauro Carvalho Chehab ---- - -diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c -index 1d47d4d..dc1cb17 100644 ---- a/drivers/media/dvb/frontends/dib0070.c -+++ b/drivers/media/dvb/frontends/dib0070.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - - #include "dvb_frontend.h" - -@@ -78,10 +79,18 @@ struct dib0070_state { - struct i2c_msg msg[2]; - u8 i2c_write_buffer[3]; - u8 i2c_read_buffer[2]; -+ struct mutex i2c_buffer_lock; - }; - --static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) -+static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg) - { -+ u16 ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return 0; -+ } -+ - state->i2c_write_buffer[0] = reg; - - memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); -@@ -96,13 +105,23 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) - - if (i2c_transfer(state->i2c, state->msg, 2) != 2) { - printk(KERN_WARNING "DiB0070 I2C read failed\n"); -- return 0; -- } -- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ ret = 0; -+ } else -+ ret = (state->i2c_read_buffer[0] << 8) -+ | state->i2c_read_buffer[1]; -+ -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - - static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) - { -+ int ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } - state->i2c_write_buffer[0] = reg; - state->i2c_write_buffer[1] = val >> 8; - state->i2c_write_buffer[2] = val & 0xff; -@@ -115,9 +134,12 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) - - if (i2c_transfer(state->i2c, state->msg, 1) != 1) { - printk(KERN_WARNING "DiB0070 I2C write failed\n"); -- return -EREMOTEIO; -- } -- return 0; -+ ret = -EREMOTEIO; -+ } else -+ ret = 0; -+ -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - - #define HARD_RESET(state) do { \ -@@ -734,6 +756,7 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter - state->cfg = cfg; - state->i2c = i2c; - state->fe = fe; -+ mutex_init(&state->i2c_buffer_lock); - fe->tuner_priv = state; - - if (dib0070_reset(fe) != 0) -diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c -index c9c935a..b174d1c 100644 ---- a/drivers/media/dvb/frontends/dib0090.c -+++ b/drivers/media/dvb/frontends/dib0090.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - - #include "dvb_frontend.h" - -@@ -196,6 +197,7 @@ struct dib0090_state { - struct i2c_msg msg[2]; - u8 i2c_write_buffer[3]; - u8 i2c_read_buffer[2]; -+ struct mutex i2c_buffer_lock; - }; - - struct dib0090_fw_state { -@@ -208,10 +210,18 @@ struct dib0090_fw_state { - struct i2c_msg msg; - u8 i2c_write_buffer[2]; - u8 i2c_read_buffer[2]; -+ struct mutex i2c_buffer_lock; - }; - - static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) - { -+ u16 ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return 0; -+ } -+ - state->i2c_write_buffer[0] = reg; - - memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); -@@ -226,14 +236,24 @@ static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) - - if (i2c_transfer(state->i2c, state->msg, 2) != 2) { - printk(KERN_WARNING "DiB0090 I2C read failed\n"); -- return 0; -- } -+ ret = 0; -+ } else -+ ret = (state->i2c_read_buffer[0] << 8) -+ | state->i2c_read_buffer[1]; - -- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - - static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) - { -+ int ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ - state->i2c_write_buffer[0] = reg & 0xff; - state->i2c_write_buffer[1] = val >> 8; - state->i2c_write_buffer[2] = val & 0xff; -@@ -246,13 +266,23 @@ static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) - - if (i2c_transfer(state->i2c, state->msg, 1) != 1) { - printk(KERN_WARNING "DiB0090 I2C write failed\n"); -- return -EREMOTEIO; -- } -- return 0; -+ ret = -EREMOTEIO; -+ } else -+ ret = 0; -+ -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - - static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg) - { -+ u16 ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return 0; -+ } -+ - state->i2c_write_buffer[0] = reg; - - memset(&state->msg, 0, sizeof(struct i2c_msg)); -@@ -262,13 +292,24 @@ static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg) - state->msg.len = 2; - if (i2c_transfer(state->i2c, &state->msg, 1) != 1) { - printk(KERN_WARNING "DiB0090 I2C read failed\n"); -- return 0; -- } -- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ ret = 0; -+ } else -+ ret = (state->i2c_read_buffer[0] << 8) -+ | state->i2c_read_buffer[1]; -+ -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - - static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val) - { -+ int ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ - state->i2c_write_buffer[0] = val >> 8; - state->i2c_write_buffer[1] = val & 0xff; - -@@ -279,9 +320,12 @@ static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val) - state->msg.len = 2; - if (i2c_transfer(state->i2c, &state->msg, 1) != 1) { - printk(KERN_WARNING "DiB0090 I2C write failed\n"); -- return -EREMOTEIO; -- } -- return 0; -+ ret = -EREMOTEIO; -+ } else -+ ret = 0; -+ -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - - #define HARD_RESET(state) do { if (cfg->reset) { if (cfg->sleep) cfg->sleep(fe, 0); msleep(10); cfg->reset(fe, 1); msleep(10); cfg->reset(fe, 0); msleep(10); } } while (0) -@@ -2440,6 +2484,7 @@ struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapte - st->config = config; - st->i2c = i2c; - st->fe = fe; -+ mutex_init(&st->i2c_buffer_lock); - fe->tuner_priv = st; - - if (config->wbd == NULL) -@@ -2471,6 +2516,7 @@ struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_ada - st->config = config; - st->i2c = i2c; - st->fe = fe; -+ mutex_init(&st->i2c_buffer_lock); - fe->tuner_priv = st; - - if (dib0090_fw_reset_digital(fe, st->config) != 0) -diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c -index 79cb1c2..dbb76d7 100644 ---- a/drivers/media/dvb/frontends/dib7000m.c -+++ b/drivers/media/dvb/frontends/dib7000m.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - - #include "dvb_frontend.h" - -@@ -55,6 +56,7 @@ struct dib7000m_state { - struct i2c_msg msg[2]; - u8 i2c_write_buffer[4]; - u8 i2c_read_buffer[2]; -+ struct mutex i2c_buffer_lock; - }; - - enum dib7000m_power_mode { -@@ -69,6 +71,13 @@ enum dib7000m_power_mode { - - static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) - { -+ u16 ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return 0; -+ } -+ - state->i2c_write_buffer[0] = (reg >> 8) | 0x80; - state->i2c_write_buffer[1] = reg & 0xff; - -@@ -85,11 +94,21 @@ static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) - if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2) - dprintk("i2c read error on %d",reg); - -- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ mutex_unlock(&state->i2c_buffer_lock); -+ -+ return ret; - } - - static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) - { -+ int ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ - state->i2c_write_buffer[0] = (reg >> 8) & 0xff; - state->i2c_write_buffer[1] = reg & 0xff; - state->i2c_write_buffer[2] = (val >> 8) & 0xff; -@@ -101,7 +120,10 @@ static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) - state->msg[0].buf = state->i2c_write_buffer; - state->msg[0].len = 4; - -- return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; -+ ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -+ -EREMOTEIO : 0); -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf) - { -@@ -1385,6 +1407,7 @@ struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, - demod = &st->demod; - demod->demodulator_priv = st; - memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops)); -+ mutex_init(&st->i2c_buffer_lock); - - st->timf_default = cfg->bw->timf; - -diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c -index a64a538..4eb9c2b 100644 ---- a/drivers/media/dvb/frontends/dib7000p.c -+++ b/drivers/media/dvb/frontends/dib7000p.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - #include "dvb_math.h" - #include "dvb_frontend.h" -@@ -68,6 +69,7 @@ struct dib7000p_state { - struct i2c_msg msg[2]; - u8 i2c_write_buffer[4]; - u8 i2c_read_buffer[2]; -+ struct mutex i2c_buffer_lock; - }; - - enum dib7000p_power_mode { -@@ -81,6 +83,13 @@ static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff); - - static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) - { -+ u16 ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return 0; -+ } -+ - state->i2c_write_buffer[0] = reg >> 8; - state->i2c_write_buffer[1] = reg & 0xff; - -@@ -97,11 +106,20 @@ static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) - if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2) - dprintk("i2c read error on %d", reg); - -- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - - static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) - { -+ int ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ - state->i2c_write_buffer[0] = (reg >> 8) & 0xff; - state->i2c_write_buffer[1] = reg & 0xff; - state->i2c_write_buffer[2] = (val >> 8) & 0xff; -@@ -113,7 +131,10 @@ static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) - state->msg[0].buf = state->i2c_write_buffer; - state->msg[0].len = 4; - -- return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; -+ ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -+ -EREMOTEIO : 0); -+ mutex_unlock(&state->i2c_buffer_lock); -+ return ret; - } - - static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf) -@@ -1646,6 +1667,7 @@ int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau - return -ENOMEM; - - dpst->i2c_adap = i2c; -+ mutex_init(&dpst->i2c_buffer_lock); - - for (k = no_of_demods - 1; k >= 0; k--) { - dpst->cfg = cfg[k]; -@@ -2324,6 +2346,7 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, - demod = &st->demod; - demod->demodulator_priv = st; - memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops)); -+ mutex_init(&st->i2c_buffer_lock); - - dib7000p_write_word(st, 1287, 0x0003); /* sram lead in, rdy */ - -@@ -2333,8 +2356,9 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, - st->version = dib7000p_read_word(st, 897); - - /* FIXME: make sure the dev.parent field is initialized, or else -- request_firmware() will hit an OOPS (this should be moved somewhere -- more common) */ -+ request_firmware() will hit an OOPS (this should be moved somewhere -+ more common) */ -+ st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent; - - /* FIXME: make sure the dev.parent field is initialized, or else - request_firmware() will hit an OOPS (this should be moved somewhere -diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c -index 7d2ea11..fe284d5 100644 ---- a/drivers/media/dvb/frontends/dib8000.c -+++ b/drivers/media/dvb/frontends/dib8000.c -@@ -10,6 +10,8 @@ - #include - #include - #include -+#include -+ - #include "dvb_math.h" - - #include "dvb_frontend.h" -@@ -37,6 +39,7 @@ struct i2c_device { - u8 addr; - u8 *i2c_write_buffer; - u8 *i2c_read_buffer; -+ struct mutex *i2c_buffer_lock; - }; - - struct dib8000_state { -@@ -77,6 +80,7 @@ struct dib8000_state { - struct i2c_msg msg[2]; - u8 i2c_write_buffer[4]; - u8 i2c_read_buffer[2]; -+ struct mutex i2c_buffer_lock; - }; - - enum dib8000_power_mode { -@@ -86,24 +90,39 @@ enum dib8000_power_mode { - - static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg) - { -+ u16 ret; - struct i2c_msg msg[2] = { -- {.addr = i2c->addr >> 1, .flags = 0, -- .buf = i2c->i2c_write_buffer, .len = 2}, -- {.addr = i2c->addr >> 1, .flags = I2C_M_RD, -- .buf = i2c->i2c_read_buffer, .len = 2}, -+ {.addr = i2c->addr >> 1, .flags = 0, .len = 2}, -+ {.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2}, - }; - -+ if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return 0; -+ } -+ -+ msg[0].buf = i2c->i2c_write_buffer; - msg[0].buf[0] = reg >> 8; - msg[0].buf[1] = reg & 0xff; -+ msg[1].buf = i2c->i2c_read_buffer; - - if (i2c_transfer(i2c->adap, msg, 2) != 2) - dprintk("i2c read error on %d", reg); - -- return (msg[1].buf[0] << 8) | msg[1].buf[1]; -+ ret = (msg[1].buf[0] << 8) | msg[1].buf[1]; -+ mutex_unlock(i2c->i2c_buffer_lock); -+ return ret; - } - - static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) - { -+ u16 ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return 0; -+ } -+ - state->i2c_write_buffer[0] = reg >> 8; - state->i2c_write_buffer[1] = reg & 0xff; - -@@ -120,7 +139,10 @@ static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) - if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2) - dprintk("i2c read error on %d", reg); - -- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; -+ mutex_unlock(&state->i2c_buffer_lock); -+ -+ return ret; - } - - static u32 dib8000_read32(struct dib8000_state *state, u16 reg) -@@ -135,22 +157,35 @@ static u32 dib8000_read32(struct dib8000_state *state, u16 reg) - - static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val) - { -- struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, -- .buf = i2c->i2c_write_buffer, .len = 4}; -+ struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4}; - int ret = 0; - -+ if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ -+ msg.buf = i2c->i2c_write_buffer; - msg.buf[0] = (reg >> 8) & 0xff; - msg.buf[1] = reg & 0xff; - msg.buf[2] = (val >> 8) & 0xff; - msg.buf[3] = val & 0xff; - - ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0; -+ mutex_unlock(i2c->i2c_buffer_lock); - - return ret; - } - - static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) - { -+ int ret; -+ -+ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ - state->i2c_write_buffer[0] = (reg >> 8) & 0xff; - state->i2c_write_buffer[1] = reg & 0xff; - state->i2c_write_buffer[2] = (val >> 8) & 0xff; -@@ -162,7 +197,11 @@ static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) - state->msg[0].buf = state->i2c_write_buffer; - state->msg[0].len = 4; - -- return i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; -+ ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -+ -EREMOTEIO : 0); -+ mutex_unlock(&state->i2c_buffer_lock); -+ -+ return ret; - } - - static const s16 coeff_2k_sb_1seg_dqpsk[8] = { -@@ -2434,8 +2473,15 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau - if (!client.i2c_read_buffer) { - dprintk("%s: not enough memory", __func__); - ret = -ENOMEM; -- goto error_memory; -+ goto error_memory_read; -+ } -+ client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL); -+ if (!client.i2c_buffer_lock) { -+ dprintk("%s: not enough memory", __func__); -+ ret = -ENOMEM; -+ goto error_memory_lock; - } -+ mutex_init(client.i2c_buffer_lock); - - for (k = no_of_demods - 1; k >= 0; k--) { - /* designated i2c address */ -@@ -2476,8 +2522,10 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau - } - - error: -+ kfree(client.i2c_buffer_lock); -+error_memory_lock: - kfree(client.i2c_read_buffer); --error_memory: -+error_memory_read: - kfree(client.i2c_write_buffer); - - return ret; -@@ -2581,6 +2629,8 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s - state->i2c.addr = i2c_addr; - state->i2c.i2c_write_buffer = state->i2c_write_buffer; - state->i2c.i2c_read_buffer = state->i2c_read_buffer; -+ mutex_init(&state->i2c_buffer_lock); -+ state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock; - state->gpio_val = cfg->gpio_val; - state->gpio_dir = cfg->gpio_dir; - -diff --git a/drivers/media/dvb/frontends/dib9000.c b/drivers/media/dvb/frontends/dib9000.c -index a085588..b931074 100644 ---- a/drivers/media/dvb/frontends/dib9000.c -+++ b/drivers/media/dvb/frontends/dib9000.c -@@ -38,6 +38,15 @@ struct i2c_device { - #define DibInitLock(lock) mutex_init(lock) - #define DibFreeLock(lock) - -+struct dib9000_pid_ctrl { -+#define DIB9000_PID_FILTER_CTRL 0 -+#define DIB9000_PID_FILTER 1 -+ u8 cmd; -+ u8 id; -+ u16 pid; -+ u8 onoff; -+}; -+ - struct dib9000_state { - struct i2c_device i2c; - -@@ -99,6 +108,10 @@ struct dib9000_state { - struct i2c_msg msg[2]; - u8 i2c_write_buffer[255]; - u8 i2c_read_buffer[255]; -+ DIB_LOCK demod_lock; -+ u8 get_frontend_internal; -+ struct dib9000_pid_ctrl pid_ctrl[10]; -+ s8 pid_ctrl_index; /* -1: empty list; -2: do not use the list */ - }; - - static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -@@ -1743,19 +1756,56 @@ EXPORT_SYMBOL(dib9000_set_gpio); - int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) - { - struct dib9000_state *state = fe->demodulator_priv; -- u16 val = dib9000_read_word(state, 294 + 1) & 0xffef; -+ u16 val; -+ int ret; -+ -+ if ((state->pid_ctrl_index != -2) && (state->pid_ctrl_index < 9)) { -+ /* postpone the pid filtering cmd */ -+ dprintk("pid filter cmd postpone"); -+ state->pid_ctrl_index++; -+ state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER_CTRL; -+ state->pid_ctrl[state->pid_ctrl_index].onoff = onoff; -+ return 0; -+ } -+ -+ DibAcquireLock(&state->demod_lock); -+ -+ val = dib9000_read_word(state, 294 + 1) & 0xffef; - val |= (onoff & 0x1) << 4; - - dprintk("PID filter enabled %d", onoff); -- return dib9000_write_word(state, 294 + 1, val); -+ ret = dib9000_write_word(state, 294 + 1, val); -+ DibReleaseLock(&state->demod_lock); -+ return ret; -+ - } - EXPORT_SYMBOL(dib9000_fw_pid_filter_ctrl); - - int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) - { - struct dib9000_state *state = fe->demodulator_priv; -+ int ret; -+ -+ if (state->pid_ctrl_index != -2) { -+ /* postpone the pid filtering cmd */ -+ dprintk("pid filter postpone"); -+ if (state->pid_ctrl_index < 9) { -+ state->pid_ctrl_index++; -+ state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER; -+ state->pid_ctrl[state->pid_ctrl_index].id = id; -+ state->pid_ctrl[state->pid_ctrl_index].pid = pid; -+ state->pid_ctrl[state->pid_ctrl_index].onoff = onoff; -+ } else -+ dprintk("can not add any more pid ctrl cmd"); -+ return 0; -+ } -+ -+ DibAcquireLock(&state->demod_lock); - dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff); -- return dib9000_write_word(state, 300 + 1 + id, onoff ? (1 << 13) | pid : 0); -+ ret = dib9000_write_word(state, 300 + 1 + id, -+ onoff ? (1 << 13) | pid : 0); -+ DibReleaseLock(&state->demod_lock); -+ return ret; - } - EXPORT_SYMBOL(dib9000_fw_pid_filter); - -@@ -1778,6 +1828,7 @@ static void dib9000_release(struct dvb_frontend *demod) - DibFreeLock(&state->platform.risc.mbx_lock); - DibFreeLock(&state->platform.risc.mem_lock); - DibFreeLock(&state->platform.risc.mem_mbx_lock); -+ DibFreeLock(&state->demod_lock); - dibx000_exit_i2c_master(&st->i2c_master); - - i2c_del_adapter(&st->tuner_adap); -@@ -1795,14 +1846,19 @@ static int dib9000_sleep(struct dvb_frontend *fe) - { - struct dib9000_state *state = fe->demodulator_priv; - u8 index_frontend; -- int ret; -+ int ret = 0; - -+ DibAcquireLock(&state->demod_lock); - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]); - if (ret < 0) -- return ret; -+ goto error; - } -- return dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0); -+ ret = dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0); -+ -+error: -+ DibReleaseLock(&state->demod_lock); -+ return ret; - } - - static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune) -@@ -1816,7 +1872,10 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par - struct dib9000_state *state = fe->demodulator_priv; - u8 index_frontend, sub_index_frontend; - fe_status_t stat; -- int ret; -+ int ret = 0; -+ -+ if (state->get_frontend_internal == 0) -+ DibAcquireLock(&state->demod_lock); - - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat); -@@ -1846,14 +1905,15 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par - state->fe[index_frontend]->dtv_property_cache.rolloff; - } - } -- return 0; -+ ret = 0; -+ goto return_value; - } - } - - /* get the channel from master chip */ - ret = dib9000_fw_get_channel(fe, fep); - if (ret != 0) -- return ret; -+ goto return_value; - - /* synchronize the cache with the other frontends */ - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { -@@ -1866,8 +1926,12 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par - state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP; - state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff; - } -+ ret = 0; - -- return 0; -+return_value: -+ if (state->get_frontend_internal == 0) -+ DibReleaseLock(&state->demod_lock); -+ return ret; - } - - static int dib9000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) -@@ -1912,6 +1976,10 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par - dprintk("dib9000: must specify bandwidth "); - return 0; - } -+ -+ state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */ -+ DibAcquireLock(&state->demod_lock); -+ - fe->dtv_property_cache.delivery_system = SYS_DVBT; - - /* set the master status */ -@@ -1974,13 +2042,18 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par - /* check the tune result */ - if (exit_condition == 1) { /* tune failed */ - dprintk("tune failed"); -+ DibReleaseLock(&state->demod_lock); -+ /* tune failed; put all the pid filtering cmd to junk */ -+ state->pid_ctrl_index = -1; - return 0; - } - - dprintk("tune success on frontend%i", index_frontend_success); - - /* synchronize all the channel cache */ -+ state->get_frontend_internal = 1; - dib9000_get_frontend(state->fe[0], fep); -+ state->get_frontend_internal = 0; - - /* retune the other frontends with the found channel */ - channel_status.status = CHANNEL_STATUS_PARAMETERS_SET; -@@ -2025,6 +2098,28 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par - /* turn off the diversity for the last frontend */ - dib9000_fw_set_diversity_in(state->fe[index_frontend - 1], 0); - -+ DibReleaseLock(&state->demod_lock); -+ if (state->pid_ctrl_index >= 0) { -+ u8 index_pid_filter_cmd; -+ u8 pid_ctrl_index = state->pid_ctrl_index; -+ -+ state->pid_ctrl_index = -2; -+ for (index_pid_filter_cmd = 0; -+ index_pid_filter_cmd <= pid_ctrl_index; -+ index_pid_filter_cmd++) { -+ if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER_CTRL) -+ dib9000_fw_pid_filter_ctrl(state->fe[0], -+ state->pid_ctrl[index_pid_filter_cmd].onoff); -+ else if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER) -+ dib9000_fw_pid_filter(state->fe[0], -+ state->pid_ctrl[index_pid_filter_cmd].id, -+ state->pid_ctrl[index_pid_filter_cmd].pid, -+ state->pid_ctrl[index_pid_filter_cmd].onoff); -+ } -+ } -+ /* do not postpone any more the pid filtering */ -+ state->pid_ctrl_index = -2; -+ - return 0; - } - -@@ -2041,6 +2136,7 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat) - u8 index_frontend; - u16 lock = 0, lock_slave = 0; - -+ DibAcquireLock(&state->demod_lock); - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) - lock_slave |= dib9000_read_lock(state->fe[index_frontend]); - -@@ -2059,6 +2155,8 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat) - if ((lock & 0x0008) || (lock_slave & 0x0008)) - *stat |= FE_HAS_LOCK; - -+ DibReleaseLock(&state->demod_lock); -+ - return 0; - } - -@@ -2066,10 +2164,14 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber) - { - struct dib9000_state *state = fe->demodulator_priv; - u16 *c; -+ int ret = 0; - -+ DibAcquireLock(&state->demod_lock); - DibAcquireLock(&state->platform.risc.mem_mbx_lock); -- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) -- return -EIO; -+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { -+ ret = -EIO; -+ goto error; -+ } - dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, - state->i2c_read_buffer, 16 * 2); - DibReleaseLock(&state->platform.risc.mem_mbx_lock); -@@ -2077,7 +2179,10 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber) - c = (u16 *)state->i2c_read_buffer; - - *ber = c[10] << 16 | c[11]; -- return 0; -+ -+error: -+ DibReleaseLock(&state->demod_lock); -+ return ret; - } - - static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) -@@ -2086,7 +2191,9 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) - u8 index_frontend; - u16 *c = (u16 *)state->i2c_read_buffer; - u16 val; -+ int ret = 0; - -+ DibAcquireLock(&state->demod_lock); - *strength = 0; - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val); -@@ -2097,8 +2204,10 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) - } - - DibAcquireLock(&state->platform.risc.mem_mbx_lock); -- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) -- return -EIO; -+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { -+ ret = -EIO; -+ goto error; -+ } - dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); - DibReleaseLock(&state->platform.risc.mem_mbx_lock); - -@@ -2107,7 +2216,10 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) - *strength = 65535; - else - *strength += val; -- return 0; -+ -+error: -+ DibReleaseLock(&state->demod_lock); -+ return ret; - } - - static u32 dib9000_get_snr(struct dvb_frontend *fe) -@@ -2151,6 +2263,7 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr) - u8 index_frontend; - u32 snr_master; - -+ DibAcquireLock(&state->demod_lock); - snr_master = dib9000_get_snr(fe); - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) - snr_master += dib9000_get_snr(state->fe[index_frontend]); -@@ -2161,6 +2274,8 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr) - } else - *snr = 0; - -+ DibReleaseLock(&state->demod_lock); -+ - return 0; - } - -@@ -2168,15 +2283,22 @@ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) - { - struct dib9000_state *state = fe->demodulator_priv; - u16 *c = (u16 *)state->i2c_read_buffer; -+ int ret = 0; - -+ DibAcquireLock(&state->demod_lock); - DibAcquireLock(&state->platform.risc.mem_mbx_lock); -- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) -- return -EIO; -+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { -+ ret = -EIO; -+ goto error; -+ } - dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); - DibReleaseLock(&state->platform.risc.mem_mbx_lock); - - *unc = c[12]; -- return 0; -+ -+error: -+ DibReleaseLock(&state->demod_lock); -+ return ret; - } - - int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr) -@@ -2322,6 +2444,10 @@ struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, c - DibInitLock(&st->platform.risc.mbx_lock); - DibInitLock(&st->platform.risc.mem_lock); - DibInitLock(&st->platform.risc.mem_mbx_lock); -+ DibInitLock(&st->demod_lock); -+ st->get_frontend_internal = 0; -+ -+ st->pid_ctrl_index = -2; - - st->fe[0] = fe; - fe->demodulator_priv = st; -diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c -index dc5d17a..774d507 100644 ---- a/drivers/media/dvb/frontends/dibx000_common.c -+++ b/drivers/media/dvb/frontends/dibx000_common.c -@@ -1,4 +1,5 @@ - #include -+#include - - #include "dibx000_common.h" - -@@ -10,6 +11,13 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); - - static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) - { -+ int ret; -+ -+ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ - mst->i2c_write_buffer[0] = (reg >> 8) & 0xff; - mst->i2c_write_buffer[1] = reg & 0xff; - mst->i2c_write_buffer[2] = (val >> 8) & 0xff; -@@ -21,11 +29,21 @@ static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) - mst->msg[0].buf = mst->i2c_write_buffer; - mst->msg[0].len = 4; - -- return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0; -+ ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0; -+ mutex_unlock(&mst->i2c_buffer_lock); -+ -+ return ret; - } - - static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg) - { -+ u16 ret; -+ -+ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return 0; -+ } -+ - mst->i2c_write_buffer[0] = reg >> 8; - mst->i2c_write_buffer[1] = reg & 0xff; - -@@ -42,7 +60,10 @@ static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg) - if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2) - dprintk("i2c read error on %d", reg); - -- return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1]; -+ ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1]; -+ mutex_unlock(&mst->i2c_buffer_lock); -+ -+ return ret; - } - - static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst) -@@ -257,6 +278,7 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg msg[], int num) - { - struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); -+ int ret; - - if (num > 32) { - dprintk("%s: too much I2C message to be transmitted (%i).\ -@@ -264,10 +286,15 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, - return -ENOMEM; - } - -- memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); -- - dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7); - -+ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ -+ memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); -+ - /* open the gate */ - dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); - mst->msg[0].addr = mst->i2c_addr; -@@ -282,7 +309,11 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, - mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; - mst->msg[num + 1].len = 4; - -- return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO; -+ ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? -+ num : -EIO); -+ -+ mutex_unlock(&mst->i2c_buffer_lock); -+ return ret; - } - - static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = { -@@ -294,6 +325,7 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg msg[], int num) - { - struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); -+ int ret; - - if (num > 32) { - dprintk("%s: too much I2C message to be transmitted (%i).\ -@@ -301,10 +333,14 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, - return -ENOMEM; - } - -- memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); -- - dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); - -+ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); -+ - /* open the gate */ - dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); - mst->msg[0].addr = mst->i2c_addr; -@@ -319,7 +355,10 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, - mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; - mst->msg[num + 1].len = 4; - -- return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO; -+ ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? -+ num : -EIO); -+ mutex_unlock(&mst->i2c_buffer_lock); -+ return ret; - } - - static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = { -@@ -390,8 +429,18 @@ static int i2c_adapter_init(struct i2c_adapter *i2c_adap, - int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, - struct i2c_adapter *i2c_adap, u8 i2c_addr) - { -- u8 tx[4]; -- struct i2c_msg m = {.addr = i2c_addr >> 1,.buf = tx,.len = 4 }; -+ int ret; -+ -+ mutex_init(&mst->i2c_buffer_lock); -+ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { -+ dprintk("could not acquire lock"); -+ return -EINVAL; -+ } -+ memset(mst->msg, 0, sizeof(struct i2c_msg)); -+ mst->msg[0].addr = i2c_addr >> 1; -+ mst->msg[0].flags = 0; -+ mst->msg[0].buf = mst->i2c_write_buffer; -+ mst->msg[0].len = 4; - - mst->device_rev = device_rev; - mst->i2c_adap = i2c_adap; -@@ -431,9 +480,12 @@ int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, - "DiBX000: could not initialize the master i2c_adapter\n"); - - /* initialize the i2c-master by closing the gate */ -- dibx000_i2c_gate_ctrl(mst, tx, 0, 0); -+ dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0); -+ -+ ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1); -+ mutex_unlock(&mst->i2c_buffer_lock); - -- return i2c_transfer(i2c_adap, &m, 1) == 1; -+ return ret; - } - - EXPORT_SYMBOL(dibx000_init_i2c_master); -diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h -index f031165..5e01147 100644 ---- a/drivers/media/dvb/frontends/dibx000_common.h -+++ b/drivers/media/dvb/frontends/dibx000_common.h -@@ -33,6 +33,7 @@ struct dibx000_i2c_master { - struct i2c_msg msg[34]; - u8 i2c_write_buffer[8]; - u8 i2c_read_buffer[2]; -+ struct mutex i2c_buffer_lock; - }; - - extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, diff --git a/media-dib0700-protect-the-dib0700-buffer-access.patch b/media-dib0700-protect-the-dib0700-buffer-access.patch deleted file mode 100644 index 109cab8ec..000000000 --- a/media-dib0700-protect-the-dib0700-buffer-access.patch +++ /dev/null @@ -1,248 +0,0 @@ -From: Olivier Grenie -Date: Mon, 1 Aug 2011 15:45:58 +0000 (-0300) -Subject: [media] dib0700: protect the dib0700 buffer access -X-Git-Tag: next-20110927~67^2~4^2~224 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=bff469f4167fdabfe15294f375577d7eadbaa1bb - -[media] dib0700: protect the dib0700 buffer access - -This patch protects the common buffer access inside the dib0700 in order -to manage concurrent access. This protection is done using mutex. - -Cc: Mauro Carvalho Chehab -Cc: Florian Mickler -Cc: stable@kernel.org -Signed-off-by: Javier Marcet -Signed-off-by: Olivier Grenie -Signed-off-by: Patrick Boettcher -[mchehab@redhat.com: dprint requires 3 arguments. Replaced by dib_info] -Signed-off-by: Mauro Carvalho Chehab ---- - -diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c -index 5eb91b4..a224e94 100644 ---- a/drivers/media/dvb/dvb-usb/dib0700_core.c -+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c -@@ -30,6 +30,11 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, - struct dib0700_state *st = d->priv; - int ret; - -+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } -+ - ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), - REQUEST_GET_VERSION, - USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, -@@ -46,6 +51,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, - if (fwtype != NULL) - *fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) | - (st->buf[14] << 8) | st->buf[15]; -+ mutex_unlock(&d->usb_mutex); - return ret; - } - -@@ -108,7 +114,12 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen - int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val) - { - struct dib0700_state *st = d->priv; -- s16 ret; -+ int ret; -+ -+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } - - st->buf[0] = REQUEST_SET_GPIO; - st->buf[1] = gpio; -@@ -116,6 +127,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ - - ret = dib0700_ctrl_wr(d, st->buf, 3); - -+ mutex_unlock(&d->usb_mutex); - return ret; - } - -@@ -125,6 +137,11 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) - int ret; - - if (st->fw_version >= 0x10201) { -+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } -+ - st->buf[0] = REQUEST_SET_USB_XFER_LEN; - st->buf[1] = (nb_ts_packets >> 8) & 0xff; - st->buf[2] = nb_ts_packets & 0xff; -@@ -132,6 +149,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) - deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets); - - ret = dib0700_ctrl_wr(d, st->buf, 3); -+ mutex_unlock(&d->usb_mutex); - } else { - deb_info("this firmware does not allow to change the USB xfer len\n"); - ret = -EIO; -@@ -208,6 +226,10 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, - - } else { - /* Write request */ -+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } - st->buf[0] = REQUEST_NEW_I2C_WRITE; - st->buf[1] = msg[i].addr << 1; - st->buf[2] = (en_start << 7) | (en_stop << 6) | -@@ -227,6 +249,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, - USB_TYPE_VENDOR | USB_DIR_OUT, - 0, 0, st->buf, msg[i].len + 4, - USB_CTRL_GET_TIMEOUT); -+ mutex_unlock(&d->usb_mutex); - if (result < 0) { - deb_info("i2c write error (status = %d)\n", result); - break; -@@ -249,6 +272,10 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, - - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; -+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } - - for (i = 0; i < num; i++) { - /* fill in the address */ -@@ -279,6 +306,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, - break; - } - } -+ mutex_unlock(&d->usb_mutex); - mutex_unlock(&d->i2c_mutex); - - return i; -@@ -337,7 +365,12 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, - u16 pll_loopdiv, u16 free_div, u16 dsuScaler) - { - struct dib0700_state *st = d->priv; -- s16 ret; -+ int ret; -+ -+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } - - st->buf[0] = REQUEST_SET_CLOCK; - st->buf[1] = (en_pll << 7) | (pll_src << 6) | -@@ -352,6 +385,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, - st->buf[9] = dsuScaler & 0xff; /* LSB */ - - ret = dib0700_ctrl_wr(d, st->buf, 10); -+ mutex_unlock(&d->usb_mutex); - - return ret; - } -@@ -360,10 +394,16 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) - { - struct dib0700_state *st = d->priv; - u16 divider; -+ int ret; - - if (scl_kHz == 0) - return -EINVAL; - -+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } -+ - st->buf[0] = REQUEST_SET_I2C_PARAM; - divider = (u16) (30000 / scl_kHz); - st->buf[1] = 0; -@@ -379,7 +419,11 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) - deb_info("setting I2C speed: %04x %04x %04x (%d kHz).", - (st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) | - st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz); -- return dib0700_ctrl_wr(d, st->buf, 8); -+ -+ ret = dib0700_ctrl_wr(d, st->buf, 8); -+ mutex_unlock(&d->usb_mutex); -+ -+ return ret; - } - - -@@ -515,6 +559,11 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) - } - } - -+ if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } -+ - st->buf[0] = REQUEST_ENABLE_VIDEO; - /* this bit gives a kind of command, - * rather than enabling something or not */ -@@ -548,7 +597,10 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) - - deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]); - -- return dib0700_ctrl_wr(adap->dev, st->buf, 4); -+ ret = dib0700_ctrl_wr(adap->dev, st->buf, 4); -+ mutex_unlock(&adap->dev->usb_mutex); -+ -+ return ret; - } - - int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) -@@ -557,6 +609,11 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) - struct dib0700_state *st = d->priv; - int new_proto, ret; - -+ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -+ deb_info("could not acquire lock"); -+ return 0; -+ } -+ - st->buf[0] = REQUEST_SET_RC; - st->buf[1] = 0; - st->buf[2] = 0; -@@ -567,23 +624,29 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) - else if (rc_type == RC_TYPE_NEC) - new_proto = 0; - else if (rc_type == RC_TYPE_RC6) { -- if (st->fw_version < 0x10200) -- return -EINVAL; -+ if (st->fw_version < 0x10200) { -+ ret = -EINVAL; -+ goto out; -+ } - - new_proto = 2; -- } else -- return -EINVAL; -+ } else { -+ ret = -EINVAL; -+ goto out; -+ } - - st->buf[1] = new_proto; - - ret = dib0700_ctrl_wr(d, st->buf, 3); - if (ret < 0) { - err("ir protocol setup failed"); -- return ret; -+ goto out; - } - - d->props.rc.core.protocol = rc_type; - -+out: -+ mutex_unlock(&d->usb_mutex); - return ret; - } - diff --git a/mmc-Always-check-for-lower-base-frequency-quirk-for-.patch b/mmc-Always-check-for-lower-base-frequency-quirk-for-.patch deleted file mode 100644 index 2d7caad83..000000000 --- a/mmc-Always-check-for-lower-base-frequency-quirk-for-.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 65ff02dff67bf26a9c27d9aa11a30eaf3d28469e Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Wed, 5 Oct 2011 11:29:57 -0400 -Subject: [PATCH] mmc: Always check for lower base frequency quirk for Ricoh - 1180:e823 - -Commit 15bed0f2f added a quirk for the e823 Ricoh card reader to lower the -base frequency. However, the quirk first checks to see if the proprietary -MMC controller is disabled, and returns if so. On some devices, such as the -Lenovo X220, the MMC controller is already disabled by firmware it seems, -but the frequency change is still needed so sdhci-pci can talk to the cards. -Since the MMC controller is disabled, the frequency fixup was never being run -on these machines. - -This moves the e823 check above the MMC controller check so that it always -gets run. - -This fixes https://bugzilla.redhat.com/show_bug.cgi?id=722509 - -Signed-off-by: Josh Boyer ---- - drivers/pci/quirks.c | 28 ++++++++++++++-------------- - 1 files changed, 14 insertions(+), 14 deletions(-) - -diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c -index 1196f61..cec4629 100644 ---- a/drivers/pci/quirks.c -+++ b/drivers/pci/quirks.c -@@ -2745,20 +2745,6 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) - /* disable must be done via function #0 */ - if (PCI_FUNC(dev->devfn)) - return; -- -- pci_read_config_byte(dev, 0xCB, &disable); -- -- if (disable & 0x02) -- return; -- -- pci_read_config_byte(dev, 0xCA, &write_enable); -- pci_write_config_byte(dev, 0xCA, 0x57); -- pci_write_config_byte(dev, 0xCB, disable | 0x02); -- pci_write_config_byte(dev, 0xCA, write_enable); -- -- dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n"); -- dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n"); -- - /* - * RICOH 0xe823 SD/MMC card reader fails to recognize - * certain types of SD/MMC cards. Lowering the SD base -@@ -2781,6 +2767,20 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) - - dev_notice(&dev->dev, "MMC controller base frequency changed to 50Mhz.\n"); - } -+ -+ pci_read_config_byte(dev, 0xCB, &disable); -+ -+ if (disable & 0x02) -+ return; -+ -+ pci_read_config_byte(dev, 0xCA, &write_enable); -+ pci_write_config_byte(dev, 0xCA, 0x57); -+ pci_write_config_byte(dev, 0xCB, disable | 0x02); -+ pci_write_config_byte(dev, 0xCA, write_enable); -+ -+ dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n"); -+ dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n"); -+ - } - DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); - DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); --- -1.7.6.4 - diff --git a/powerpc-Fix-deadlock-in-icswx-code.patch b/powerpc-Fix-deadlock-in-icswx-code.patch deleted file mode 100644 index a2ce3cf76..000000000 --- a/powerpc-Fix-deadlock-in-icswx-code.patch +++ /dev/null @@ -1,74 +0,0 @@ -From patchwork Wed Sep 14 19:43:15 2011 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: powerpc: Fix deadlock in icswx code -Date: Wed, 14 Sep 2011 09:43:15 -0000 -From: Anton Blanchard -X-Patchwork-Id: 114701 -Message-Id: <20110915054315.5e5ae062@kryten> -To: benh@kernel.crashing.org, paulus@samba.org -Cc: linuxppc-dev@lists.ozlabs.org - -The icswx code introduced an A-B B-A deadlock: - - CPU0 CPU1 - ---- ---- -lock(&anon_vma->mutex); - lock(&mm->mmap_sem); - lock(&anon_vma->mutex); -lock(&mm->mmap_sem); - -Instead of using the mmap_sem to keep mm_users constant, take the -page table spinlock. - -Signed-off-by: Anton Blanchard -Cc: - ---- - - -diff --git a/arch/powerpc/mm/mmu_context_hash64.c b/arch/powerpc/mm/mmu_context_hash64.c -index 3bafc3d..4ff587e 100644 ---- a/arch/powerpc/mm/mmu_context_hash64.c -+++ b/arch/powerpc/mm/mmu_context_hash64.c -@@ -136,8 +136,8 @@ int use_cop(unsigned long acop, struct mm_struct *mm) - if (!mm || !acop) - return -EINVAL; - -- /* We need to make sure mm_users doesn't change */ -- down_read(&mm->mmap_sem); -+ /* The page_table_lock ensures mm_users won't change under us */ -+ spin_lock(&mm->page_table_lock); - spin_lock(mm->context.cop_lockp); - - if (mm->context.cop_pid == COP_PID_NONE) { -@@ -164,7 +164,7 @@ int use_cop(unsigned long acop, struct mm_struct *mm) - - out: - spin_unlock(mm->context.cop_lockp); -- up_read(&mm->mmap_sem); -+ spin_unlock(&mm->page_table_lock); - - return ret; - } -@@ -185,8 +185,8 @@ void drop_cop(unsigned long acop, struct mm_struct *mm) - if (WARN_ON_ONCE(!mm)) - return; - -- /* We need to make sure mm_users doesn't change */ -- down_read(&mm->mmap_sem); -+ /* The page_table_lock ensures mm_users won't change under us */ -+ spin_lock(&mm->page_table_lock); - spin_lock(mm->context.cop_lockp); - - mm->context.acop &= ~acop; -@@ -213,7 +213,7 @@ void drop_cop(unsigned long acop, struct mm_struct *mm) - } - - spin_unlock(mm->context.cop_lockp); -- up_read(&mm->mmap_sem); -+ spin_unlock(&mm->page_table_lock); - } - EXPORT_SYMBOL_GPL(drop_cop); - diff --git a/sources b/sources index da0608dfe..07784d488 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 -0582554c78b9979dc91223e3f4e4ec22 patch-3.1.1-rc1.bz2 +8eb92cc70e7f8d1d18a349ba8c029d7d patch-3.1.1.bz2 diff --git a/ums-realtek-driver-uses-stack-memory-for-DMA.patch b/ums-realtek-driver-uses-stack-memory-for-DMA.patch deleted file mode 100644 index 98c8b0cf9..000000000 --- a/ums-realtek-driver-uses-stack-memory-for-DMA.patch +++ /dev/null @@ -1,143 +0,0 @@ -From patchwork Tue Aug 2 05:04:11 2011 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 8bit -Subject: ums-realtek driver uses stack memory for DMA -Date: Tue, 02 Aug 2011 05:04:11 -0000 -From: Adam Cozzette -X-Patchwork-Id: 1028062 -Message-Id: <20110802050411.GC3857@[192.168.0.12]> -To: Josh Boyer -Cc: edwin_rong , wwang , - Greg Kroah-Hartman , linux-usb@vger.kernel.org, - linux-kernel@vger.kernel.org - -On Mon, Aug 01, 2011 at 05:09:06PM -0400, Josh Boyer wrote: -> Hello, -> -> We have a report that the ums-realtek driver is generating a backtrace -> due to using stack variables for DMA buffers. The backtrace is below -> and you can view the bug report here: -> https://bugzilla.redhat.com/show_bug.cgi?id=720054 -> -> Looking through the code, it seems that every call to rts51x_read_mem, -> rts51x_write_mem, and rts51x_read_status passes a stack variable to -> rts51x_bulk_transport, which then calls usb_stor_bulk_transfer_buf with -> this and generates the backtrace. It is my understanding that the -> driver should be passing variables that are not on the stack and have -> been allocated with memory that will be suitable for the DMA api (e.g. -> kmalloc). -> -> Was this missed during the initial review and is anyone working on -> adapting the driver to be compliant? - -Could you try out this patch if it looks ok to you? I have not tested it because -unfortunately I don't have the hardware. Right now it generates some compile -warnings like this one: - -drivers/usb/storage/realtek_cr.c:419:40: warning: ‘buf[0]’ may be used uninitialized in this function [-Wuninitialized] - -It think they are harmless but I didn't see an obvious way to get rid of them, -so if you have any suggestions I would be glad to hear them. - -This patch changed rts51x_read_mem, rts51x_write_mem, and rts51x_read_status to -allocate temporary buffers with kmalloc. This way stack addresses are not used -for DMA when these functions call rts51x_bulk_transport. - -Signed-off-by: Adam Cozzette - ---- -realtek_cr.c | 35 ++++++++++++++++++++++++++++++----- - 1 file changed, 30 insertions(+), 5 deletions(-) - --- -To unsubscribe from this list: send the line "unsubscribe linux-kernel" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html -Please read the FAQ at http://www.tux.org/lkml/ - -diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c -index 34adc4b..232167a 100644 ---- a/drivers/usb/storage/realtek_cr.c -+++ b/drivers/usb/storage/realtek_cr.c -@@ -320,6 +320,11 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) - { - int retval; - u8 cmnd[12] = { 0 }; -+ u8 *buf; -+ -+ buf = kmalloc(len, GFP_NOIO); -+ if (buf == NULL) -+ return USB_STOR_TRANSPORT_ERROR; - - US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); - -@@ -331,10 +336,14 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len) - cmnd[5] = (u8) len; - - retval = rts51x_bulk_transport(us, 0, cmnd, 12, -- data, len, DMA_FROM_DEVICE, NULL); -- if (retval != USB_STOR_TRANSPORT_GOOD) -+ buf, len, DMA_FROM_DEVICE, NULL); -+ if (retval != USB_STOR_TRANSPORT_GOOD) { -+ kfree(buf); - return -EIO; -+ } - -+ memcpy(data, buf, len); -+ kfree(buf); - return 0; - } - -@@ -342,6 +351,12 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) - { - int retval; - u8 cmnd[12] = { 0 }; -+ u8 *buf; -+ -+ buf = kmalloc(len, GFP_NOIO); -+ if (buf == NULL) -+ return USB_STOR_TRANSPORT_ERROR; -+ memcpy(buf, data, len); - - US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); - -@@ -353,7 +368,8 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len) - cmnd[5] = (u8) len; - - retval = rts51x_bulk_transport(us, 0, cmnd, 12, -- data, len, DMA_TO_DEVICE, NULL); -+ buf, len, DMA_TO_DEVICE, NULL); -+ kfree(buf); - if (retval != USB_STOR_TRANSPORT_GOOD) - return -EIO; - -@@ -365,6 +381,11 @@ static int rts51x_read_status(struct us_data *us, - { - int retval; - u8 cmnd[12] = { 0 }; -+ u8 *buf; -+ -+ buf = kmalloc(len, GFP_NOIO); -+ if (buf == NULL) -+ return USB_STOR_TRANSPORT_ERROR; - - US_DEBUGP("%s, lun = %d\n", __func__, lun); - -@@ -372,10 +393,14 @@ static int rts51x_read_status(struct us_data *us, - cmnd[1] = 0x09; - - retval = rts51x_bulk_transport(us, lun, cmnd, 12, -- status, len, DMA_FROM_DEVICE, actlen); -- if (retval != USB_STOR_TRANSPORT_GOOD) -+ buf, len, DMA_FROM_DEVICE, actlen); -+ if (retval != USB_STOR_TRANSPORT_GOOD) { -+ kfree(buf); - return -EIO; -+ } - -+ memcpy(status, buf, len); -+ kfree(buf); - return 0; - } - From 955d50cbe0d23995c2fdc351d218dd5adb12c0de Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 11 Nov 2011 19:29:51 -0500 Subject: [PATCH 137/487] copy baserelease sanity check from rawhide --- .gitignore | 1 + kernel.spec | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 2a459583a..98392fa4d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ linux-*.tar.bz2 patch-*.bz2 clog *.rpm +*.orig kernel-[23].*/ diff --git a/kernel.spec b/kernel.spec index 26ecb0248..05fd6e629 100644 --- a/kernel.spec +++ b/kernel.spec @@ -48,8 +48,11 @@ Summary: The Linux kernel # reset this by hand to 1 (or to 0 and then use rpmdev-bumpspec). # scripts/rebase.sh should be made to do that for you, actually. # -# For non-released -rc kernels, this will be prepended with "0.", so -# for example a 3 here will become 0.3 +# NOTE: baserelease must be > 0 or bad things will happen if you switch +# to a released kernel (released version will be < rc version) +# +# For non-released -rc kernels, this will be appended after the rcX and +# gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # %global baserelease 1 %global fedora_build %{baserelease} @@ -1009,6 +1012,11 @@ exit 1 %endif %endif +%if !%{baserelease} +echo "baserelease must be greater than zero" +exit 1 +%endif + # more sanity checking; do it quietly if [ "%{patches}" != "%%{patches}" ] ; then for patch in %{patches} ; do From 4220aaf744fb4fd42b720dc6b81bafc937ffad72 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 11 Nov 2011 19:44:33 -0500 Subject: [PATCH 138/487] Use the same naming scheme as rawhide for -stable RC kernels (e.g. 3.1.1-0.rc1.1 instead of 3.1.1-1.rc1) --- kernel.spec | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 05fd6e629..49cdf4e5e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -170,8 +170,10 @@ Summary: The Linux kernel %if 0%{?stable_rc} %define stable_rctag .rc%{stable_rc} +%define pkg_release 0%{stable_rctag}.%{fedora_build}%{?buildid}%{?dist} +%else +%define pkg_release %{fedora_build}%{?buildid}%{?dist} %endif -%define pkg_release %{fedora_build}%{?stable_rctag}%{?buildid}%{?dist} %else @@ -2122,6 +2124,10 @@ fi # and build. %changelog +* Fri Nov 11 2011 Chuck Ebbert +- Use the same naming scheme as rawhide for -stable RC kernels + (e.g. 3.1.1-0.rc1.1 instead of 3.1.1-1.rc1) + * Fri Nov 11 2011 Josh Boyer 3.1.1-1 - Linux 3.1.1 From 68b031c163448494779e02f48d72cc79fdeef30b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 14 Nov 2011 10:03:45 -0500 Subject: [PATCH 139/487] Fix 2 CVEs CVE-2011-4131: nfs4_getfacl decoding kernel oops (rhbz 753236) CVE-2011-4132: jbd/jbd2: invalid value of first log block leads to oops (rhbz 753346) --- ...e-sb-s_first-in-journal_get_superblo.patch | 95 ++++++++++++++ kernel.spec | 15 ++- ...include-bitmap-in-nfsv4_get_acl_data.patch | 118 ++++++++++++++++++ 3 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch create mode 100644 nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch diff --git a/jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch b/jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch new file mode 100644 index 000000000..f5d82914f --- /dev/null +++ b/jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch @@ -0,0 +1,95 @@ +From 8762202dd0d6e46854f786bdb6fb3780a1625efe Mon Sep 17 00:00:00 2001 +From: Eryu Guan +Date: Tue, 1 Nov 2011 19:04:59 -0400 +Subject: [PATCH] jbd/jbd2: validate sb->s_first in journal_get_superblock() + +I hit a J_ASSERT(blocknr != 0) failure in cleanup_journal_tail() when +mounting a fsfuzzed ext3 image. It turns out that the corrupted ext3 +image has s_first = 0 in journal superblock, and the 0 is passed to +journal->j_head in journal_reset(), then to blocknr in +cleanup_journal_tail(), in the end the J_ASSERT failed. + +So validate s_first after reading journal superblock from disk in +journal_get_superblock() to ensure s_first is valid. + +The following script could reproduce it: + +fstype=ext3 +blocksize=1024 +img=$fstype.img +offset=0 +found=0 +magic="c0 3b 39 98" + +dd if=/dev/zero of=$img bs=1M count=8 +mkfs -t $fstype -b $blocksize -F $img +filesize=`stat -c %s $img` +while [ $offset -lt $filesize ] +do + if od -j $offset -N 4 -t x1 $img | grep -i "$magic";then + echo "Found journal: $offset" + found=1 + break + fi + offset=`echo "$offset+$blocksize" | bc` +done + +if [ $found -ne 1 ];then + echo "Magic \"$magic\" not found" + exit 1 +fi + +dd if=/dev/zero of=$img seek=$(($offset+23)) conv=notrunc bs=1 count=1 + +mkdir -p ./mnt +mount -o loop $img ./mnt + +Cc: Jan Kara +Signed-off-by: Eryu Guan +Signed-off-by: "Theodore Ts'o" +--- + fs/jbd/journal.c | 8 ++++++++ + fs/jbd2/journal.c | 8 ++++++++ + 2 files changed, 16 insertions(+), 0 deletions(-) + +diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c +index 9fe061f..fea8dd6 100644 +--- a/fs/jbd/journal.c ++++ b/fs/jbd/journal.c +@@ -1135,6 +1135,14 @@ static int journal_get_superblock(journal_t *journal) + goto out; + } + ++ if (be32_to_cpu(sb->s_first) == 0 || ++ be32_to_cpu(sb->s_first) >= journal->j_maxlen) { ++ printk(KERN_WARNING ++ "JBD: Invalid start block of journal: %u\n", ++ be32_to_cpu(sb->s_first)); ++ goto out; ++ } ++ + return 0; + + out: +diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c +index f24df13..d6e93d0 100644 +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -1251,6 +1251,14 @@ static int journal_get_superblock(journal_t *journal) + goto out; + } + ++ if (be32_to_cpu(sb->s_first) == 0 || ++ be32_to_cpu(sb->s_first) >= journal->j_maxlen) { ++ printk(KERN_WARNING ++ "JBD2: Invalid start block of journal: %u\n", ++ be32_to_cpu(sb->s_first)); ++ goto out; ++ } ++ + return 0; + + out: +-- +1.7.7.1 + diff --git a/kernel.spec b/kernel.spec index 49cdf4e5e..40d3bf25d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -719,8 +719,14 @@ Patch3000: rcutree-avoid-false-quiescent-states.patch # fs fixes +#rhbz 753346 +Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch + # NFSv4 +#rhbz 753236 +Patch4000: nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch + # patches headed upstream Patch12010: add-appleir-usb-driver.patch @@ -1270,6 +1276,8 @@ ApplyPatch linux-2.6-i386-nx-emulation.patch # # ext4 +#rhbz 753346 +ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # xfs ApplyPatch xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch @@ -1280,6 +1288,7 @@ ApplyPatch xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch # eCryptfs # NFSv4 +ApplyPatch nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch # USB @@ -2124,6 +2133,10 @@ fi # and build. %changelog +* Mon Nov 14 2011 Josh Boyer 3.1.1-2 +- CVE-2011-4131: nfs4_getfacl decoding kernel oops (rhbz 753236) +- CVE-2011-4132: jbd/jbd2: invalid value of first log block leads to oops (rhbz 753346) + * Fri Nov 11 2011 Chuck Ebbert - Use the same naming scheme as rawhide for -stable RC kernels (e.g. 3.1.1-0.rc1.1 instead of 3.1.1-1.rc1) diff --git a/nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch b/nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch new file mode 100644 index 000000000..1b795e97f --- /dev/null +++ b/nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch @@ -0,0 +1,118 @@ +From: Andy Adamson + +The NFSv4 bitmap size is unbounded: a server can return an arbitrary +sized bitmap in an FATTR4_WORD0_ACL request. Replace using the +nfs4_fattr_bitmap_maxsz as a guess to the maximum bitmask returned by a server +with the inclusion of the bitmap (xdr length plus bitmasks) and the acl data +xdr length to the (cached) acl page data. + +This is a general solution to commit e5012d1f "NFSv4.1: update +nfs4_fattr_bitmap_maxsz" and fixes hitting a BUG_ON in xdr_shrink_bufhead +when getting ACLs. + +Cc:stable@xxxxxxxxxx +Signed-off-by: Andy Adamson +--- + fs/nfs/nfs4proc.c | 20 ++++++++++++++++++-- + fs/nfs/nfs4xdr.c | 15 ++++++++++++--- + 2 files changed, 30 insertions(+), 5 deletions(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index deb88d9..97014dd 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -3671,6 +3671,22 @@ static void nfs4_zap_acl_attr(struct inode *inode) + nfs4_set_cached_acl(inode, NULL); + } + ++/* ++ * The bitmap xdr length, bitmasks, and the attr xdr length are stored in ++ * the acl cache to handle variable length bitmasks. Just copy the acl data. ++ */ ++static void nfs4_copy_acl(char *buf, char *acl_data, size_t acl_len) ++{ ++ __be32 *q, *p = (__be32 *)acl_data; ++ int32_t len; ++ ++ len = be32_to_cpup(p); /* number of bitmasks */ ++ len += 2; /* add words for bitmap and attr xdr len */ ++ q = p + len; ++ len = len << 2; /* convert to bytes for acl_len math */ ++ memcpy(buf, (char *)q, acl_len - len); ++} ++ + static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_t buflen) + { + struct nfs_inode *nfsi = NFS_I(inode); +@@ -3688,7 +3704,7 @@ static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_ + ret = -ERANGE; /* see getxattr(2) man page */ + if (acl->len > buflen) + goto out; +- memcpy(buf, acl->data, acl->len); ++ nfs4_copy_acl(buf, acl->data, acl->len); + out_len: + ret = acl->len; + out: +@@ -3763,7 +3779,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu + if (res.acl_len > buflen) + goto out_free; + if (localpage) +- memcpy(buf, resp_buf, res.acl_len); ++ nfs4_copy_acl(buf, resp_buf, res.acl_len); + } + ret = res.acl_len; + out_free: +diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c +index f9fd96d..9c07380 100644 +--- a/fs/nfs/nfs4xdr.c ++++ b/fs/nfs/nfs4xdr.c +@@ -2513,7 +2513,7 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, + encode_compound_hdr(xdr, req, &hdr); + encode_sequence(xdr, &args->seq_args, &hdr); + encode_putfh(xdr, args->fh, &hdr); +- replen = hdr.replen + op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz + 1; ++ replen = hdr.replen + op_decode_hdr_maxsz + 1; + encode_getattr_two(xdr, FATTR4_WORD0_ACL, 0, &hdr); + + xdr_inline_pages(&req->rq_rcv_buf, replen << 2, +@@ -4955,7 +4955,7 @@ decode_restorefh(struct xdr_stream *xdr) + static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, + size_t *acl_len) + { +- __be32 *savep; ++ __be32 *savep, *bm_p; + uint32_t attrlen, + bitmap[3] = {0}; + struct kvec *iov = req->rq_rcv_buf.head; +@@ -4964,6 +4964,7 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, + *acl_len = 0; + if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) + goto out; ++ bm_p = xdr->p; + if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) + goto out; + if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) +@@ -4972,12 +4973,20 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, + if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U))) + return -EIO; + if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { +- size_t hdrlen; ++ size_t hdrlen, len; + u32 recvd; + ++ /*The bitmap (xdr len + bitmasks) and the attr xdr len words ++ * are stored with the acl data to handle the problem of ++ * variable length bitmasks.*/ ++ xdr->p = bm_p; ++ len = be32_to_cpup(bm_p); ++ len += 2; /* add bitmap and attr xdr len words */ ++ + /* We ignore &savep and don't do consistency checks on + * the attr length. Let userspace figure it out.... */ + hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; ++ attrlen += len << 2; /* attrlen is in bytes */ + recvd = req->rq_rcv_buf.len - hdrlen; + if (attrlen > recvd) { + dprintk("NFS: server cheating in getattr" +-- +1.7.6.4 From 9dce7b4f5050ad232ef8c1e54b04b85564e4b288 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 14 Nov 2011 13:09:12 -0500 Subject: [PATCH 140/487] Patch from Joshua Roys to add rtl8192* to modules.networking (rhbz 753645) --- kernel.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 40d3bf25d..c0d80dce0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1679,7 +1679,7 @@ BuildKernel() { } collect_modules_list networking \ - 'register_netdev|ieee80211_register_hw|usbnet_probe|phy_driver_register|rt2x00(pci|usb)_probe' + 'register_netdev|ieee80211_register_hw|usbnet_probe|phy_driver_register|rt(l_|2x00)(pci|usb)_probe' collect_modules_list block \ 'ata_scsi_ioctl|scsi_add_host|scsi_add_host_with_dma|blk_init_queue|register_mtd_blktrans|scsi_esp_register|scsi_register_device_handler' collect_modules_list drm \ @@ -2133,6 +2133,9 @@ fi # and build. %changelog +* Mon Nov 14 2011 Josh Boyer +- Patch from Joshua Roys to add rtl8192* to modules.networking (rhbz 753645) + * Mon Nov 14 2011 Josh Boyer 3.1.1-2 - CVE-2011-4131: nfs4_getfacl decoding kernel oops (rhbz 753236) - CVE-2011-4132: jbd/jbd2: invalid value of first log block leads to oops (rhbz 753346) From aeb6369d31eb5bc7ce2dd839833ba77c248a1ba3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 14 Nov 2011 13:19:24 -0500 Subject: [PATCH 141/487] Add patch for wacom tablets for Bastien Nocera (upstream 3797ef6b6) --- ...m-Set-input-bits-before-registration.patch | 131 ++++++++++++++++++ kernel.spec | 5 +- 2 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 HID-wacom-Set-input-bits-before-registration.patch diff --git a/HID-wacom-Set-input-bits-before-registration.patch b/HID-wacom-Set-input-bits-before-registration.patch new file mode 100644 index 000000000..3cd178631 --- /dev/null +++ b/HID-wacom-Set-input-bits-before-registration.patch @@ -0,0 +1,131 @@ +From b28ae436288861916de0019a81b9817366fe35a9 Mon Sep 17 00:00:00 2001 +From: David Herrmann +Date: Sat, 8 Oct 2011 23:20:17 +0200 +Subject: [PATCH] HID: wacom: Set input bits before registration + +We shouldn't change the event flags of input devices after they get registered. +Otherwise, udev will not get notified of these flags and cannot setup the +devices properly. +This fixes the probing to set the input event flags on the input_mapped callback +instead of the probe function. + +Reported-by: Bastien Nocera +Signed-off-by: David Herrmann +Tested-by: Bastien Nocera +Signed-off-by: Bastien Nocera +Signed-off-by: Jiri Kosina +--- + drivers/hid/hid-wacom.c | 80 +++++++++++++++++++++++++--------------------- + 1 files changed, 43 insertions(+), 37 deletions(-) + +diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c +index 72ca689..1492728 100644 +--- a/drivers/hid/hid-wacom.c ++++ b/drivers/hid/hid-wacom.c +@@ -304,11 +304,51 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, + return 1; + } + ++static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, ++ struct hid_field *field, struct hid_usage *usage, unsigned long **bit, ++ int *max) ++{ ++ struct input_dev *input = hi->input; ++ ++ __set_bit(INPUT_PROP_POINTER, input->propbit); ++ ++ /* Basics */ ++ input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL); ++ ++ __set_bit(REL_WHEEL, input->relbit); ++ ++ __set_bit(BTN_TOOL_PEN, input->keybit); ++ __set_bit(BTN_TOUCH, input->keybit); ++ __set_bit(BTN_STYLUS, input->keybit); ++ __set_bit(BTN_STYLUS2, input->keybit); ++ __set_bit(BTN_LEFT, input->keybit); ++ __set_bit(BTN_RIGHT, input->keybit); ++ __set_bit(BTN_MIDDLE, input->keybit); ++ ++ /* Pad */ ++ input->evbit[0] |= BIT(EV_MSC); ++ ++ __set_bit(MSC_SERIAL, input->mscbit); ++ ++ __set_bit(BTN_0, input->keybit); ++ __set_bit(BTN_1, input->keybit); ++ __set_bit(BTN_TOOL_FINGER, input->keybit); ++ ++ /* Distance, rubber and mouse */ ++ __set_bit(BTN_TOOL_RUBBER, input->keybit); ++ __set_bit(BTN_TOOL_MOUSE, input->keybit); ++ ++ input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); ++ input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); ++ input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); ++ input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); ++ ++ return 0; ++} ++ + static int wacom_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { +- struct hid_input *hidinput; +- struct input_dev *input; + struct wacom_data *wdata; + int ret; + +@@ -370,41 +410,6 @@ static int wacom_probe(struct hid_device *hdev, + goto err_ac; + } + #endif +- hidinput = list_entry(hdev->inputs.next, struct hid_input, list); +- input = hidinput->input; +- +- __set_bit(INPUT_PROP_POINTER, input->propbit); +- +- /* Basics */ +- input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL); +- +- __set_bit(REL_WHEEL, input->relbit); +- +- __set_bit(BTN_TOOL_PEN, input->keybit); +- __set_bit(BTN_TOUCH, input->keybit); +- __set_bit(BTN_STYLUS, input->keybit); +- __set_bit(BTN_STYLUS2, input->keybit); +- __set_bit(BTN_LEFT, input->keybit); +- __set_bit(BTN_RIGHT, input->keybit); +- __set_bit(BTN_MIDDLE, input->keybit); +- +- /* Pad */ +- input->evbit[0] |= BIT(EV_MSC); +- +- __set_bit(MSC_SERIAL, input->mscbit); +- +- __set_bit(BTN_0, input->keybit); +- __set_bit(BTN_1, input->keybit); +- __set_bit(BTN_TOOL_FINGER, input->keybit); +- +- /* Distance, rubber and mouse */ +- __set_bit(BTN_TOOL_RUBBER, input->keybit); +- __set_bit(BTN_TOOL_MOUSE, input->keybit); +- +- input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); +- input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); +- input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); +- input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); + + return 0; + +@@ -448,6 +453,7 @@ static struct hid_driver wacom_driver = { + .probe = wacom_probe, + .remove = wacom_remove, + .raw_event = wacom_raw_event, ++ .input_mapped = wacom_input_mapped, + }; + + static int __init wacom_init(void) +-- +1.7.7.1 + diff --git a/kernel.spec b/kernel.spec index c0d80dce0..d7ea3cbe1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -738,6 +738,7 @@ Patch12025: rcu-avoid-just-onlined-cpu-resched.patch Patch12026: block-stray-block-put-after-teardown.patch Patch12027: usb-add-quirk-for-logitech-webcams.patch Patch12030: epoll-limit-paths.patch +Patch12031: HID-wacom-Set-input-bits-before-registration.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch @@ -1393,6 +1394,7 @@ ApplyPatch epoll-limit-paths.patch ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch ApplyPatch block-stray-block-put-after-teardown.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch +ApplyPatch HID-wacom-Set-input-bits-before-registration.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -2135,6 +2137,7 @@ fi %changelog * Mon Nov 14 2011 Josh Boyer - Patch from Joshua Roys to add rtl8192* to modules.networking (rhbz 753645) +- Add patch for wacom tablets for Bastien Nocera (upstream 3797ef6b6) * Mon Nov 14 2011 Josh Boyer 3.1.1-2 - CVE-2011-4131: nfs4_getfacl decoding kernel oops (rhbz 753236) From 5046e8a2018c5e39a96b769289de739546b9d67b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 14 Nov 2011 13:56:46 -0500 Subject: [PATCH 142/487] Add patch to fix ip6_tunnel naming (rhbz 751165) --- ...-parms.name-after-register_netdevice.patch | 76 +++++++++++++++++++ kernel.spec | 7 ++ 2 files changed, 83 insertions(+) create mode 100644 ip6_tunnel-copy-parms.name-after-register_netdevice.patch diff --git a/ip6_tunnel-copy-parms.name-after-register_netdevice.patch b/ip6_tunnel-copy-parms.name-after-register_netdevice.patch new file mode 100644 index 000000000..d3bb6a24e --- /dev/null +++ b/ip6_tunnel-copy-parms.name-after-register_netdevice.patch @@ -0,0 +1,76 @@ +From 731abb9cb27aef6013ce60808a04e04a545f3f4e Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Thu, 10 Nov 2011 15:10:23 +0000 +Subject: [PATCH] ip6_tunnel: copy parms.name after register_netdevice + +Commit 1c5cae815d removed an explicit call to dev_alloc_name in ip6_tnl_create +because register_netdevice will now create a valid name. This works for the +net_device itself. + +However the tunnel keeps a copy of the name in the parms structure for the +ip6_tnl associated with the tunnel. parms.name is set by copying the net_device +name in ip6_tnl_dev_init_gen. That function is called from ip6_tnl_dev_init in +ip6_tnl_create, but it is done before register_netdevice is called so the name +is set to a bogus value in the parms.name structure. + +This shows up if you do a simple tunnel add, followed by a tunnel show: + +[root@localhost ~]# ip -6 tunnel add remote fec0::100 local fec0::200 +[root@localhost ~]# ip -6 tunnel show +ip6tnl0: ipv6/ipv6 remote :: local :: encaplimit 0 hoplimit 0 tclass 0x00 flowlabel 0x00000 (flowinfo 0x00000000) +ip6tnl%d: ipv6/ipv6 remote fec0::100 local fec0::200 encaplimit 4 hoplimit 64 tclass 0x00 flowlabel 0x00000 (flowinfo 0x00000000) +[root@localhost ~]# + +Fix this by moving the strcpy out of ip6_tnl_dev_init_gen, and calling it after +register_netdevice has successfully returned. + +Cc: stable@vger.kernel.org +Signed-off-by: Josh Boyer +Signed-off-by: David S. Miller +--- + net/ipv6/ip6_tunnel.c | 8 +++++++- + 1 files changed, 7 insertions(+), 1 deletions(-) + +diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c +index bdc15c9..4e2e9ff 100644 +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -289,6 +289,8 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct ip6_tnl_parm *p) + if ((err = register_netdevice(dev)) < 0) + goto failed_free; + ++ strcpy(t->parms.name, dev->name); ++ + dev_hold(dev); + ip6_tnl_link(ip6n, t); + return t; +@@ -1407,7 +1409,6 @@ ip6_tnl_dev_init_gen(struct net_device *dev) + struct ip6_tnl *t = netdev_priv(dev); + + t->dev = dev; +- strcpy(t->parms.name, dev->name); + dev->tstats = alloc_percpu(struct pcpu_tstats); + if (!dev->tstats) + return -ENOMEM; +@@ -1487,6 +1488,7 @@ static void __net_exit ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) + static int __net_init ip6_tnl_init_net(struct net *net) + { + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); ++ struct ip6_tnl *t = NULL; + int err; + + ip6n->tnls[0] = ip6n->tnls_wc; +@@ -1507,6 +1509,10 @@ static int __net_init ip6_tnl_init_net(struct net *net) + err = register_netdev(ip6n->fb_tnl_dev); + if (err < 0) + goto err_register; ++ ++ t = netdev_priv(ip6n->fb_tnl_dev); ++ ++ strcpy(t->parms.name, ip6n->fb_tnl_dev->name); + return 0; + + err_register: +-- +1.7.6.2 + diff --git a/kernel.spec b/kernel.spec index d7ea3cbe1..1b7cbaa24 100644 --- a/kernel.spec +++ b/kernel.spec @@ -747,6 +747,9 @@ Patch13003: efi-dont-map-boot-services-on-32bit.patch Patch13009: hvcs_pi_buf_alloc.patch +#rhbz 751165 +Patch13010: ip6_tunnel-copy-parms.name-after-register_netdevice.patch + Patch20000: utrace.patch # Flattened devicetree support @@ -1404,6 +1407,9 @@ ApplyPatch efi-dont-map-boot-services-on-32bit.patch ApplyPatch hvcs_pi_buf_alloc.patch +#rhbz 751165 +ApplyPatch ip6_tunnel-copy-parms.name-after-register_netdevice.patch + ApplyPatch media-dib0700-correct-error-message.patch # utrace. @@ -2138,6 +2144,7 @@ fi * Mon Nov 14 2011 Josh Boyer - Patch from Joshua Roys to add rtl8192* to modules.networking (rhbz 753645) - Add patch for wacom tablets for Bastien Nocera (upstream 3797ef6b6) +- Add patch to fix ip6_tunnel naming (rhbz 751165) * Mon Nov 14 2011 Josh Boyer 3.1.1-2 - CVE-2011-4131: nfs4_getfacl decoding kernel oops (rhbz 753236) From 058b0767d6525a25ec51926a0e3291aefb621e3a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 14 Nov 2011 14:26:26 -0500 Subject: [PATCH 143/487] Quite a warning in apm_cpu_idle (rhbz 753776) WARN_ONCE is now the top thing on my "BIGGEST WASTE OF TIME" list. It changes daily though. --- kernel.spec | 3 +++ quite-apm.patch | 13 +++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 quite-apm.patch diff --git a/kernel.spec b/kernel.spec index 1b7cbaa24..12e466eec 100644 --- a/kernel.spec +++ b/kernel.spec @@ -672,6 +672,7 @@ Patch470: die-floppy-die.patch Patch471: floppy-drop-disable_hlt-warning.patch Patch510: linux-2.6-silence-noise.patch +Patch520: quite-apm.patch Patch530: linux-2.6-silence-fbcon-logo.patch Patch700: linux-2.6-e1000-ich9-montevina.patch @@ -1375,6 +1376,7 @@ ApplyPatch linux-2.6-intel-iommu-igfx.patch # silence the ACPI blacklist code ApplyPatch linux-2.6-silence-acpi-blacklist.patch +ApplyPatch quite-apm.patch # V4L/DVB updates/fixes/experimental drivers # apply if non-empty @@ -2145,6 +2147,7 @@ fi - Patch from Joshua Roys to add rtl8192* to modules.networking (rhbz 753645) - Add patch for wacom tablets for Bastien Nocera (upstream 3797ef6b6) - Add patch to fix ip6_tunnel naming (rhbz 751165) +- Quite warning in apm_cpu_idle (rhbz 753776) * Mon Nov 14 2011 Josh Boyer 3.1.1-2 - CVE-2011-4131: nfs4_getfacl decoding kernel oops (rhbz 753236) diff --git a/quite-apm.patch b/quite-apm.patch new file mode 100644 index 000000000..9325ae55b --- /dev/null +++ b/quite-apm.patch @@ -0,0 +1,13 @@ +diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c +index a46bd38..416dd12 100644 +--- a/arch/x86/kernel/apm_32.c ++++ b/arch/x86/kernel/apm_32.c +@@ -903,7 +903,7 @@ static void apm_cpu_idle(void) + unsigned int jiffies_since_last_check = jiffies - last_jiffies; + unsigned int bucket; + +- WARN_ONCE(1, "deprecated apm_cpu_idle will be deleted in 2012"); ++ printk(KERN_INFO "deprecated apm_cpu_idle will be deleted in 2012"); + recalc: + if (jiffies_since_last_check > IDLE_CALC_LIMIT) { + use_apm_idle = 0; From 917075f21e970d24f8efa600318b17839e0e1ef3 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 15 Nov 2011 14:48:26 -0500 Subject: [PATCH 144/487] Backport asus-laptop changes from 3.2 (rhbz 754214) --- asus-laptop-3.2-backport.patch | 592 +++++++++++++++++++++++++++++++++ kernel.spec | 5 + 2 files changed, 597 insertions(+) create mode 100644 asus-laptop-3.2-backport.patch diff --git a/asus-laptop-3.2-backport.patch b/asus-laptop-3.2-backport.patch new file mode 100644 index 000000000..ea161f688 --- /dev/null +++ b/asus-laptop-3.2-backport.patch @@ -0,0 +1,592 @@ +Backport from 3.2 (754214) + +Andy Ross (4): + asus-laptop: Platform detection for Pegatron Lucid + asus-laptop: Pegatron Lucid ALS sensor + asus-laptop: allow boot time control of Pegatron ALS sensor + asus-laptop: Pegatron Lucid accelerometer + +Anisse Astier (2): + asus-laptop: pega_accel - Report accelerometer orientation change through udev + asus-laptop: Add rfkill support for Pegatron Lucid tablet + +Axel Lin (1): + platform-drivers-x86: asus-laptop: fix wrong test for successful registered led_classdev + +Corentin Chary (2): + asus-laptop: hide leds on Pegatron Lucid + asus-laptop: fix module description + +diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c +index fa6d7ec..edaccad 100644 +--- a/drivers/platform/x86/asus-laptop.c ++++ b/drivers/platform/x86/asus-laptop.c +@@ -4,6 +4,7 @@ + * + * Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor + * Copyright (C) 2006-2007 Corentin Chary ++ * Copyright (C) 2011 Wind River Systems + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -48,6 +49,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -83,26 +85,32 @@ static int wlan_status = 1; + static int bluetooth_status = 1; + static int wimax_status = -1; + static int wwan_status = -1; ++static int als_status; + + module_param(wlan_status, int, 0444); + MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot " + "(0 = disabled, 1 = enabled, -1 = don't do anything). " +- "default is 1"); ++ "default is -1"); + + module_param(bluetooth_status, int, 0444); + MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " + "(0 = disabled, 1 = enabled, -1 = don't do anything). " +- "default is 1"); ++ "default is -1"); + + module_param(wimax_status, int, 0444); + MODULE_PARM_DESC(wimax_status, "Set the wireless status on boot " + "(0 = disabled, 1 = enabled, -1 = don't do anything). " +- "default is 1"); ++ "default is -1"); + + module_param(wwan_status, int, 0444); + MODULE_PARM_DESC(wwan_status, "Set the wireless status on boot " + "(0 = disabled, 1 = enabled, -1 = don't do anything). " +- "default is 1"); ++ "default is -1"); ++ ++module_param(als_status, int, 0444); ++MODULE_PARM_DESC(als_status, "Set the ALS status on boot " ++ "(0 = disabled, 1 = enabled). " ++ "default is 0"); + + /* + * Some events we use, same for all Asus +@@ -173,6 +181,29 @@ MODULE_PARM_DESC(wwan_status, "Set the wireless status on boot " + #define METHOD_KBD_LIGHT_SET "SLKB" + #define METHOD_KBD_LIGHT_GET "GLKB" + ++/* For Pegatron Lucid tablet */ ++#define DEVICE_NAME_PEGA "Lucid" ++ ++#define METHOD_PEGA_ENABLE "ENPR" ++#define METHOD_PEGA_DISABLE "DAPR" ++#define PEGA_WLAN 0x00 ++#define PEGA_BLUETOOTH 0x01 ++#define PEGA_WWAN 0x02 ++#define PEGA_ALS 0x04 ++#define PEGA_ALS_POWER 0x05 ++ ++#define METHOD_PEGA_READ "RDLN" ++#define PEGA_READ_ALS_H 0x02 ++#define PEGA_READ_ALS_L 0x03 ++ ++#define PEGA_ACCEL_NAME "pega_accel" ++#define PEGA_ACCEL_DESC "Pegatron Lucid Tablet Accelerometer" ++#define METHOD_XLRX "XLRX" ++#define METHOD_XLRY "XLRY" ++#define METHOD_XLRZ "XLRZ" ++#define PEGA_ACC_CLAMP 512 /* 1G accel is reported as ~256, so clamp to 2G */ ++#define PEGA_ACC_RETRIES 3 ++ + /* + * Define a specific led structure to keep the main structure clean + */ +@@ -185,6 +216,15 @@ struct asus_led { + }; + + /* ++ * Same thing for rfkill ++ */ ++struct asus_pega_rfkill { ++ int control_id; /* type of control. Maps to PEGA_* values */ ++ struct rfkill *rfkill; ++ struct asus_laptop *asus; ++}; ++ ++/* + * This is the main structure, we can use it to store anything interesting + * about the hotk device + */ +@@ -198,6 +238,7 @@ struct asus_laptop { + + struct input_dev *inputdev; + struct key_entry *keymap; ++ struct input_polled_dev *pega_accel_poll; + + struct asus_led mled; + struct asus_led tled; +@@ -209,9 +250,18 @@ struct asus_laptop { + + int wireless_status; + bool have_rsts; ++ bool is_pega_lucid; ++ bool pega_acc_live; ++ int pega_acc_x; ++ int pega_acc_y; ++ int pega_acc_z; + + struct rfkill *gps_rfkill; + ++ struct asus_pega_rfkill wlanrfk; ++ struct asus_pega_rfkill btrfk; ++ struct asus_pega_rfkill wwanrfk; ++ + acpi_handle handle; /* the handle of the hotk device */ + u32 ledd_status; /* status of the LED display */ + u8 light_level; /* light sensor level */ +@@ -323,6 +373,127 @@ static int acpi_check_handle(acpi_handle handle, const char *method, + return 0; + } + ++static bool asus_check_pega_lucid(struct asus_laptop *asus) ++{ ++ return !strcmp(asus->name, DEVICE_NAME_PEGA) && ++ !acpi_check_handle(asus->handle, METHOD_PEGA_ENABLE, NULL) && ++ !acpi_check_handle(asus->handle, METHOD_PEGA_DISABLE, NULL) && ++ !acpi_check_handle(asus->handle, METHOD_PEGA_READ, NULL); ++} ++ ++static int asus_pega_lucid_set(struct asus_laptop *asus, int unit, bool enable) ++{ ++ char *method = enable ? METHOD_PEGA_ENABLE : METHOD_PEGA_DISABLE; ++ return write_acpi_int(asus->handle, method, unit); ++} ++ ++static int pega_acc_axis(struct asus_laptop *asus, int curr, char *method) ++{ ++ int i, delta; ++ unsigned long long val; ++ for (i = 0; i < PEGA_ACC_RETRIES; i++) { ++ acpi_evaluate_integer(asus->handle, method, NULL, &val); ++ ++ /* The output is noisy. From reading the ASL ++ * dissassembly, timeout errors are returned with 1's ++ * in the high word, and the lack of locking around ++ * thei hi/lo byte reads means that a transition ++ * between (for example) -1 and 0 could be read as ++ * 0xff00 or 0x00ff. */ ++ delta = abs(curr - (short)val); ++ if (delta < 128 && !(val & ~0xffff)) ++ break; ++ } ++ return clamp_val((short)val, -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP); ++} ++ ++static void pega_accel_poll(struct input_polled_dev *ipd) ++{ ++ struct device *parent = ipd->input->dev.parent; ++ struct asus_laptop *asus = dev_get_drvdata(parent); ++ ++ /* In some cases, the very first call to poll causes a ++ * recursive fault under the polldev worker. This is ++ * apparently related to very early userspace access to the ++ * device, and perhaps a firmware bug. Fake the first report. */ ++ if (!asus->pega_acc_live) { ++ asus->pega_acc_live = true; ++ input_report_abs(ipd->input, ABS_X, 0); ++ input_report_abs(ipd->input, ABS_Y, 0); ++ input_report_abs(ipd->input, ABS_Z, 0); ++ input_sync(ipd->input); ++ return; ++ } ++ ++ asus->pega_acc_x = pega_acc_axis(asus, asus->pega_acc_x, METHOD_XLRX); ++ asus->pega_acc_y = pega_acc_axis(asus, asus->pega_acc_y, METHOD_XLRY); ++ asus->pega_acc_z = pega_acc_axis(asus, asus->pega_acc_z, METHOD_XLRZ); ++ ++ /* Note transform, convert to "right/up/out" in the native ++ * landscape orientation (i.e. the vector is the direction of ++ * "real up" in the device's cartiesian coordinates). */ ++ input_report_abs(ipd->input, ABS_X, -asus->pega_acc_x); ++ input_report_abs(ipd->input, ABS_Y, -asus->pega_acc_y); ++ input_report_abs(ipd->input, ABS_Z, asus->pega_acc_z); ++ input_sync(ipd->input); ++} ++ ++static void pega_accel_exit(struct asus_laptop *asus) ++{ ++ if (asus->pega_accel_poll) { ++ input_unregister_polled_device(asus->pega_accel_poll); ++ input_free_polled_device(asus->pega_accel_poll); ++ } ++ asus->pega_accel_poll = NULL; ++} ++ ++static int pega_accel_init(struct asus_laptop *asus) ++{ ++ int err; ++ struct input_polled_dev *ipd; ++ ++ if (!asus->is_pega_lucid) ++ return -ENODEV; ++ ++ if (acpi_check_handle(asus->handle, METHOD_XLRX, NULL) || ++ acpi_check_handle(asus->handle, METHOD_XLRY, NULL) || ++ acpi_check_handle(asus->handle, METHOD_XLRZ, NULL)) ++ return -ENODEV; ++ ++ ipd = input_allocate_polled_device(); ++ if (!ipd) ++ return -ENOMEM; ++ ++ ipd->poll = pega_accel_poll; ++ ipd->poll_interval = 125; ++ ipd->poll_interval_min = 50; ++ ipd->poll_interval_max = 2000; ++ ++ ipd->input->name = PEGA_ACCEL_DESC; ++ ipd->input->phys = PEGA_ACCEL_NAME "/input0"; ++ ipd->input->dev.parent = &asus->platform_device->dev; ++ ipd->input->id.bustype = BUS_HOST; ++ ++ set_bit(EV_ABS, ipd->input->evbit); ++ input_set_abs_params(ipd->input, ABS_X, ++ -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0); ++ input_set_abs_params(ipd->input, ABS_Y, ++ -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0); ++ input_set_abs_params(ipd->input, ABS_Z, ++ -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0); ++ ++ err = input_register_polled_device(ipd); ++ if (err) ++ goto exit; ++ ++ asus->pega_accel_poll = ipd; ++ return 0; ++ ++exit: ++ input_free_polled_device(ipd); ++ return err; ++} ++ + /* Generic LED function */ + static int asus_led_set(struct asus_laptop *asus, const char *method, + int value) +@@ -430,17 +601,17 @@ static enum led_brightness asus_kled_cdev_get(struct led_classdev *led_cdev) + + static void asus_led_exit(struct asus_laptop *asus) + { +- if (asus->mled.led.dev) ++ if (!IS_ERR_OR_NULL(asus->mled.led.dev)) + led_classdev_unregister(&asus->mled.led); +- if (asus->tled.led.dev) ++ if (!IS_ERR_OR_NULL(asus->tled.led.dev)) + led_classdev_unregister(&asus->tled.led); +- if (asus->pled.led.dev) ++ if (!IS_ERR_OR_NULL(asus->pled.led.dev)) + led_classdev_unregister(&asus->pled.led); +- if (asus->rled.led.dev) ++ if (!IS_ERR_OR_NULL(asus->rled.led.dev)) + led_classdev_unregister(&asus->rled.led); +- if (asus->gled.led.dev) ++ if (!IS_ERR_OR_NULL(asus->gled.led.dev)) + led_classdev_unregister(&asus->gled.led); +- if (asus->kled.led.dev) ++ if (!IS_ERR_OR_NULL(asus->kled.led.dev)) + led_classdev_unregister(&asus->kled.led); + if (asus->led_workqueue) { + destroy_workqueue(asus->led_workqueue); +@@ -474,6 +645,13 @@ static int asus_led_init(struct asus_laptop *asus) + int r; + + /* ++ * The Pegatron Lucid has no physical leds, but all methods are ++ * available in the DSDT... ++ */ ++ if (asus->is_pega_lucid) ++ return 0; ++ ++ /* + * Functions that actually update the LED's are called from a + * workqueue. By doing this as separate work rather than when the LED + * subsystem asks, we avoid messing with the Asus ACPI stuff during a +@@ -907,8 +1085,18 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr, + */ + static void asus_als_switch(struct asus_laptop *asus, int value) + { +- if (write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value)) +- pr_warn("Error setting light sensor switch\n"); ++ int ret; ++ ++ if (asus->is_pega_lucid) { ++ ret = asus_pega_lucid_set(asus, PEGA_ALS, value); ++ if (!ret) ++ ret = asus_pega_lucid_set(asus, PEGA_ALS_POWER, value); ++ } else { ++ ret = write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value); ++ } ++ if (ret) ++ pr_warning("Error setting light sensor switch\n"); ++ + asus->light_switch = value; + } + +@@ -964,6 +1152,35 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, + return rv; + } + ++static int pega_int_read(struct asus_laptop *asus, int arg, int *result) ++{ ++ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; ++ int err = write_acpi_int_ret(asus->handle, METHOD_PEGA_READ, arg, ++ &buffer); ++ if (!err) { ++ union acpi_object *obj = buffer.pointer; ++ if (obj && obj->type == ACPI_TYPE_INTEGER) ++ *result = obj->integer.value; ++ else ++ err = -EIO; ++ } ++ return err; ++} ++ ++static ssize_t show_lsvalue(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct asus_laptop *asus = dev_get_drvdata(dev); ++ int err, hi, lo; ++ ++ err = pega_int_read(asus, PEGA_READ_ALS_H, &hi); ++ if (!err) ++ err = pega_int_read(asus, PEGA_READ_ALS_L, &lo); ++ if (!err) ++ return sprintf(buf, "%d\n", 10 * hi + lo); ++ return err; ++} ++ + /* + * GPS + */ +@@ -1062,6 +1279,86 @@ static int asus_rfkill_init(struct asus_laptop *asus) + return result; + } + ++static int pega_rfkill_set(void *data, bool blocked) ++{ ++ struct asus_pega_rfkill *pega_rfk = data; ++ ++ int ret = asus_pega_lucid_set(pega_rfk->asus, pega_rfk->control_id, !blocked); ++ pr_warn("Setting rfkill %d, to %d; returned %d\n", pega_rfk->control_id, !blocked, ret); ++ ++ return ret; ++} ++ ++static const struct rfkill_ops pega_rfkill_ops = { ++ .set_block = pega_rfkill_set, ++}; ++ ++static void pega_rfkill_terminate(struct asus_pega_rfkill *pega_rfk) ++{ ++ pr_warn("Terminating %d\n", pega_rfk->control_id); ++ if (pega_rfk->rfkill) { ++ rfkill_unregister(pega_rfk->rfkill); ++ rfkill_destroy(pega_rfk->rfkill); ++ pega_rfk->rfkill = NULL; ++ } ++} ++ ++static void pega_rfkill_exit(struct asus_laptop *asus) ++{ ++ pega_rfkill_terminate(&asus->wwanrfk); ++ pega_rfkill_terminate(&asus->btrfk); ++ pega_rfkill_terminate(&asus->wlanrfk); ++} ++ ++static int pega_rfkill_setup(struct asus_laptop *asus, struct asus_pega_rfkill *pega_rfk, ++ const char *name, int controlid, int rfkill_type) ++{ ++ int result; ++ ++ pr_warn("Setting up rfk %s, control %d, type %d\n", name, controlid, rfkill_type); ++ pega_rfk->control_id = controlid; ++ pega_rfk->asus = asus; ++ pega_rfk->rfkill = rfkill_alloc(name, &asus->platform_device->dev, ++ rfkill_type, &pega_rfkill_ops, pega_rfk); ++ if (!pega_rfk->rfkill) ++ return -EINVAL; ++ ++ result = rfkill_register(pega_rfk->rfkill); ++ if (result) { ++ rfkill_destroy(pega_rfk->rfkill); ++ pega_rfk->rfkill = NULL; ++ } ++ ++ return result; ++} ++ ++static int pega_rfkill_init(struct asus_laptop *asus) ++{ ++ int ret = 0; ++ ++ if(!asus->is_pega_lucid) ++ return -ENODEV; ++ ++ ret = pega_rfkill_setup(asus, &asus->wlanrfk, "pega-wlan", PEGA_WLAN, RFKILL_TYPE_WLAN); ++ if(ret) ++ return ret; ++ ret = pega_rfkill_setup(asus, &asus->btrfk, "pega-bt", PEGA_BLUETOOTH, RFKILL_TYPE_BLUETOOTH); ++ if(ret) ++ goto err_btrfk; ++ ret = pega_rfkill_setup(asus, &asus->wwanrfk, "pega-wwan", PEGA_WWAN, RFKILL_TYPE_WWAN); ++ if(ret) ++ goto err_wwanrfk; ++ ++ pr_warn("Pega rfkill init succeeded\n"); ++ return 0; ++err_wwanrfk: ++ pega_rfkill_terminate(&asus->btrfk); ++err_btrfk: ++ pega_rfkill_terminate(&asus->wlanrfk); ++ ++ return ret; ++} ++ + /* + * Input device (i.e. hotkeys) + */ +@@ -1141,6 +1438,14 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event) + } + return ; + } ++ ++ /* Accelerometer "coarse orientation change" event */ ++ if (asus->pega_accel_poll && event == 0xEA) { ++ kobject_uevent(&asus->pega_accel_poll->input->dev.kobj, ++ KOBJ_CHANGE); ++ return ; ++ } ++ + asus_input_notify(asus, event); + } + +@@ -1152,6 +1457,7 @@ static DEVICE_ATTR(wimax, S_IRUGO | S_IWUSR, show_wimax, store_wimax); + static DEVICE_ATTR(wwan, S_IRUGO | S_IWUSR, show_wwan, store_wwan); + static DEVICE_ATTR(display, S_IWUSR, NULL, store_disp); + static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd); ++static DEVICE_ATTR(ls_value, S_IRUGO, show_lsvalue, NULL); + static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl); + static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw); + static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps); +@@ -1164,6 +1470,7 @@ static struct attribute *asus_attributes[] = { + &dev_attr_wwan.attr, + &dev_attr_display.attr, + &dev_attr_ledd.attr, ++ &dev_attr_ls_value.attr, + &dev_attr_ls_level.attr, + &dev_attr_ls_switch.attr, + &dev_attr_gps.attr, +@@ -1180,6 +1487,19 @@ static mode_t asus_sysfs_is_visible(struct kobject *kobj, + acpi_handle handle = asus->handle; + bool supported; + ++ if (asus->is_pega_lucid) { ++ /* no ls_level interface on the Lucid */ ++ if (attr == &dev_attr_ls_switch.attr) ++ supported = true; ++ else if (attr == &dev_attr_ls_level.attr) ++ supported = false; ++ else ++ goto normal; ++ ++ return supported; ++ } ++ ++normal: + if (attr == &dev_attr_wlan.attr) { + supported = !acpi_check_handle(handle, METHOD_WLAN, NULL); + +@@ -1202,8 +1522,9 @@ static mode_t asus_sysfs_is_visible(struct kobject *kobj, + } else if (attr == &dev_attr_ls_switch.attr || + attr == &dev_attr_ls_level.attr) { + supported = !acpi_check_handle(handle, METHOD_ALS_CONTROL, NULL) && +- !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL); +- ++ !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL); ++ } else if (attr == &dev_attr_ls_value.attr) { ++ supported = asus->is_pega_lucid; + } else if (attr == &dev_attr_gps.attr) { + supported = !acpi_check_handle(handle, METHOD_GPS_ON, NULL) && + !acpi_check_handle(handle, METHOD_GPS_OFF, NULL) && +@@ -1258,7 +1579,7 @@ static struct platform_driver platform_driver = { + .driver = { + .name = ASUS_LAPTOP_FILE, + .owner = THIS_MODULE, +- } ++ }, + }; + + /* +@@ -1388,11 +1709,13 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) + asus->ledd_status = 0xFFF; + + /* Set initial values of light sensor and level */ +- asus->light_switch = 0; /* Default to light sensor disabled */ ++ asus->light_switch = !!als_status; + asus->light_level = 5; /* level 5 for sensor sensitivity */ + +- if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) && +- !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) { ++ if (asus->is_pega_lucid) { ++ asus_als_switch(asus, asus->light_switch); ++ } else if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) && ++ !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) { + asus_als_switch(asus, asus->light_switch); + asus_als_level(asus, asus->light_level); + } +@@ -1439,9 +1762,10 @@ static int __devinit asus_acpi_add(struct acpi_device *device) + goto fail_platform; + + /* +- * Register the platform device first. It is used as a parent for the +- * sub-devices below. ++ * Need platform type detection first, then the platform ++ * device. It is used as a parent for the sub-devices below. + */ ++ asus->is_pega_lucid = asus_check_pega_lucid(asus); + result = asus_platform_init(asus); + if (result) + goto fail_platform; +@@ -1465,9 +1789,21 @@ static int __devinit asus_acpi_add(struct acpi_device *device) + if (result) + goto fail_rfkill; + ++ result = pega_accel_init(asus); ++ if (result && result != -ENODEV) ++ goto fail_pega_accel; ++ ++ result = pega_rfkill_init(asus); ++ if (result && result != -ENODEV) ++ goto fail_pega_rfkill; ++ + asus_device_present = true; + return 0; + ++fail_pega_rfkill: ++ pega_accel_exit(asus); ++fail_pega_accel: ++ asus_rfkill_exit(asus); + fail_rfkill: + asus_led_exit(asus); + fail_led: +@@ -1491,6 +1827,8 @@ static int asus_acpi_remove(struct acpi_device *device, int type) + asus_rfkill_exit(asus); + asus_led_exit(asus); + asus_input_exit(asus); ++ pega_accel_exit(asus); ++ pega_rfkill_exit(asus); + asus_platform_exit(asus); + + kfree(asus->name); diff --git a/kernel.spec b/kernel.spec index 12e466eec..ff76107fc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -681,6 +681,7 @@ Patch800: linux-2.6-crash-driver.patch # Platform Patch900: samsung-laptop-brightness-fixes-3.2.patch +Patch901: asus-laptop-3.2-backport.patch # crypto/ @@ -1386,6 +1387,7 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch # Platform fixes not sent for -stable ApplyPatch samsung-laptop-brightness-fixes-3.2.patch +ApplyPatch asus-laptop-3.2-backport.patch # Patches headed upstream ApplyPatch rcutree-avoid-false-quiescent-states.patch @@ -2143,6 +2145,9 @@ fi # and build. %changelog +* Tue Nov 15 2011 Dave Jones +- Backport asus-laptop changes from 3.2 (rhbz 754214) + * Mon Nov 14 2011 Josh Boyer - Patch from Joshua Roys to add rtl8192* to modules.networking (rhbz 753645) - Add patch for wacom tablets for Bastien Nocera (upstream 3797ef6b6) From f0fb214f6a85be05a70801a55cb999ceefe1aff6 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 15 Nov 2011 17:12:22 -0500 Subject: [PATCH 145/487] mm: Do not stall in synchronous compaction for THP allocations --- kernel.spec | 5 + ...onous-compaction-for-THP-allocations.patch | 115 ++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch diff --git a/kernel.spec b/kernel.spec index ff76107fc..c37666063 100644 --- a/kernel.spec +++ b/kernel.spec @@ -761,6 +761,7 @@ Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch #rhbz #735946 Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch +Patch21022: mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch #rhbz 748691 Patch21030: be2net-non-member-vlan-pkts-not-received-in-promisco.patch @@ -1422,6 +1423,7 @@ ApplyPatch utrace.patch #rhbz #735946 ApplyPatch 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch ApplyPatch 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch +ApplyPatch mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch #rhbz 748691 ApplyPatch be2net-non-member-vlan-pkts-not-received-in-promisco.patch @@ -2145,6 +2147,9 @@ fi # and build. %changelog +* Tue Nov 15 2011 Dave Jones +- mm: Do not stall in synchronous compaction for THP allocations + * Tue Nov 15 2011 Dave Jones - Backport asus-laptop changes from 3.2 (rhbz 754214) diff --git a/mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch b/mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch new file mode 100644 index 000000000..6202341ae --- /dev/null +++ b/mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch @@ -0,0 +1,115 @@ +https://lkml.org/lkml/2011/11/10/173 + +Date Thu, 10 Nov 2011 10:06:16 +0000 +From Mel Gorman <> +Subject [PATCH] mm: Do not stall in synchronous compaction for THP allocations + + +Occasionally during large file copies to slow storage, there are still +reports of user-visible stalls when THP is enabled. Reports on this +have been intermittent and not reliable to reproduce locally but; + +Andy Isaacson reported a problem copying to VFAT on SD Card + https://lkml.org/lkml/2011/11/7/2 + + In this case, it was stuck in munmap for betwen 20 and 60 + seconds in compaction. It is also possible that khugepaged + was holding mmap_sem on this process if CONFIG_NUMA was set. + +Johannes Weiner reported stalls on USB + https://lkml.org/lkml/2011/7/25/378 + + In this case, there is no stack trace but it looks like the + same problem. The USB stick may have been using NTFS as a + filesystem based on other work done related to writing back + to USB around the same time. + +Internally in SUSE, I received a bug report related to stalls in firefox + when using Java and Flash heavily while copying from NFS + to VFAT on USB. It has not been confirmed to be the same problem + but if it looks like a duck and quacks like a duck..... +In the past, commit [11bc82d6: mm: compaction: Use async migration for +__GFP_NO_KSWAPD and enforce no writeback] forced that sync compaction +would never be used for THP allocations. This was reverted in commit +[c6a140bf: mm/compaction: reverse the change that forbade sync +migraton with __GFP_NO_KSWAPD] on the grounds that it was uncertain +it was beneficial. + +While user-visible stalls do not happen for me when writing to USB, +I setup a test running postmark while short-lived processes created +anonymous mapping. The objective was to exercise the paths that +allocate transparent huge pages. I then logged when processes were +stalled for more than 1 second, recorded a stack strace and did some +analysis to aggregate unique "stall events" which revealed + +Time stalled in this event: 47369 ms +Event count: 20 +usemem sleep_on_page 3690 ms +usemem sleep_on_page 2148 ms +usemem sleep_on_page 1534 ms +usemem sleep_on_page 1518 ms +usemem sleep_on_page 1225 ms +usemem sleep_on_page 2205 ms +usemem sleep_on_page 2399 ms +usemem sleep_on_page 2398 ms +usemem sleep_on_page 3760 ms +usemem sleep_on_page 1861 ms +usemem sleep_on_page 2948 ms +usemem sleep_on_page 1515 ms +usemem sleep_on_page 1386 ms +usemem sleep_on_page 1882 ms +usemem sleep_on_page 1850 ms +usemem sleep_on_page 3715 ms +usemem sleep_on_page 3716 ms +usemem sleep_on_page 4846 ms +usemem sleep_on_page 1306 ms +usemem sleep_on_page 1467 ms +[] wait_on_page_bit+0x6c/0x80 +[] unmap_and_move+0x1bf/0x360 +[] migrate_pages+0xa2/0x1b0 +[] compact_zone+0x1f3/0x2f0 +[] compact_zone_order+0xa8/0xf0 +[] try_to_compact_pages+0xdf/0x110 +[] __alloc_pages_direct_compact+0xda/0x1a0 +[] __alloc_pages_slowpath+0x55d/0x7a0 +[] __alloc_pages_nodemask+0x1b1/0x1c0 +[] alloc_pages_vma+0x9b/0x160 +[] do_huge_pmd_anonymous_page+0x160/0x270 +[] do_page_fault+0x207/0x4c0 +[] page_fault+0x25/0x30 +The stall times are approximate at best but the estimates represent 25% +of the worst stalls and even if the estimates are off by a factor of +10, it's severe. + +This patch once again prevents sync migration for transparent +hugepage allocations as it is preferable to fail a THP allocation +than stall. It was suggested that __GFP_NORETRY be used instead of +__GFP_NO_KSWAPD. This would look less like a special case but would +still cause compaction to run at least once with sync compaction. + +If accepted, this is a -stable candidate. + +Reported-by: Andy Isaacson +Reported-by: Johannes Weiner +Signed-off-by: Mel Gorman +--- + +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index 9dd443d..84bf962 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -2168,7 +2168,13 @@ rebalance: + sync_migration); + if (page) + goto got_pg; +- sync_migration = true; ++ ++ /* ++ * Do not use sync migration for transparent hugepage allocations as ++ * it could stall writing back pages which is far worse than simply ++ * failing to promote a page. ++ */ ++ sync_migration = !(gfp_mask & __GFP_NO_KSWAPD); + + /* Try direct reclaim and then allocating */ + page = __alloc_pages_direct_reclaim(gfp_mask, order, From cc0eb00182dae4fe4212fcc13bc606f9a33b3084 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 16 Nov 2011 15:28:37 -0500 Subject: [PATCH 146/487] Add compat-wireless as an option for kernel build --- .gitignore | 1 + kernel.spec | 41 +++++++++++++++++++++++++++++++++++++++++ sources | 1 + 3 files changed, 43 insertions(+) diff --git a/.gitignore b/.gitignore index 98392fa4d..54fc49100 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ clog *.rpm *.orig kernel-[23].*/ +/compat-wireless-3.2-rc1-1.tar.bz2 diff --git a/kernel.spec b/kernel.spec index c37666063..4a3575af2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -157,6 +157,9 @@ Summary: The Linux kernel # should we do C=1 builds with sparse %define with_sparse %{?_with_sparse: 1} %{?!_with_sparse: 0} +# Include driver backports (e.g. compat-wireless) in the kernel build. +%define with_backports %{?_with_backports: 1} %{?!_with_backports: 0} + # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. @@ -195,6 +198,10 @@ Summary: The Linux kernel # The kernel tarball/base version %define kversion 3.%{base_sublevel} +# The compat-wireless version +# (If this is less than kversion, make sure with_backports is turned-off.) +%define cwversion 3.2-rc1-1 + %define make_target bzImage %define KVERREL %{version}-%{release}.%{_target_cpu} @@ -558,6 +565,7 @@ BuildRequires: rpm-build >= 4.4.2.1-4 %endif Source0: ftp://ftp.kernel.org/pub/linux/kernel/v3.0/linux-%{kversion}.tar.bz2 +Source1: compat-wireless-%{cwversion}.tar.bz2 Source11: genkey Source14: find-provides @@ -1501,6 +1509,13 @@ find . -name .gitignore -exec rm -f {} \; >/dev/null cd .. +%if %{with_backports} + +# Extract the compat-wireless bits +%setup -q -n kernel-%{kversion}%{?dist} -T -D -a 1 + +%endif + ### ### build ### @@ -1623,6 +1638,9 @@ BuildKernel() { # dirs for additional modules per module-init-tools, kbuild/modules.txt mkdir -p $RPM_BUILD_ROOT/lib/modules/$KernelVer/extra mkdir -p $RPM_BUILD_ROOT/lib/modules/$KernelVer/updates +%if %{with_backports} + mkdir -p $RPM_BUILD_ROOT/lib/modules/$KernelVer/backports +%endif # first copy everything cp --parents `find -type f -name "Makefile*" -o -name "Kconfig*"` $RPM_BUILD_ROOT/lib/modules/$KernelVer/build cp Module.symvers $RPM_BUILD_ROOT/lib/modules/$KernelVer/build @@ -1728,6 +1746,23 @@ BuildKernel() { # prune junk from kernel-devel find $RPM_BUILD_ROOT/usr/src/kernels -name ".*.cmd" -exec rm -f {} \; + +%if %{with_backports} + + cd ../compat-wireless-%{cwversion}/ + make clean + + make KLIB_BUILD=../linux-%{kversion}.%{_target_cpu} \ + KMODPATH_ARG="INSTALL_MOD_PATH=$RPM_BUILD_ROOT" \ + KMODDIR="backports" install-modules + + # mark modules executable so that strip-to-file can strip them + find $RPM_BUILD_ROOT/lib/modules/$KernelVer/backports -name "*.ko" \ + -type f | xargs --no-run-if-empty chmod u+x + + cd - + +%endif } ### @@ -2105,6 +2140,9 @@ fi /lib/modules/%{KVERREL}%{?2:.%{2}}/source\ /lib/modules/%{KVERREL}%{?2:.%{2}}/extra\ /lib/modules/%{KVERREL}%{?2:.%{2}}/updates\ +%if %{with_backports}\ +/lib/modules/%{KVERREL}%{?2:.%{2}}/backports\ +%endif\ %ifarch %{vdso_arches}\ /lib/modules/%{KVERREL}%{?2:.%{2}}/vdso\ /etc/ld.so.conf.d/kernel-%{KVERREL}%{?2:.%{2}}.conf\ @@ -2147,6 +2185,9 @@ fi # and build. %changelog +* Wed Nov 16 2011 John W. Linville +- Add compat-wireless as an option for kernel build + * Tue Nov 15 2011 Dave Jones - mm: Do not stall in synchronous compaction for THP allocations diff --git a/sources b/sources index 07784d488..ea504b912 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 8eb92cc70e7f8d1d18a349ba8c029d7d patch-3.1.1.bz2 +6693d8c42055f83f5701d9b65d47208a compat-wireless-3.2-rc1-1.tar.bz2 From 75c0588edad03f418940692418e7edfd4f04dd37 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sat, 19 Nov 2011 04:17:33 -0500 Subject: [PATCH 147/487] Linux 3.1.2-rc1 --- kernel.spec | 9 ++++++--- sources | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 4a3575af2..373e2ca45 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,9 +66,9 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 1 +%define stable_update 2 # Is it a -stable RC? -%define stable_rc 0 +%define stable_rc 1 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -2185,6 +2185,9 @@ fi # and build. %changelog +* Sat Nov 19 2011 Chuck Ebbert 3.1.2-0.rc1.1 +- Linux 3.1.2-rc1 + * Wed Nov 16 2011 John W. Linville - Add compat-wireless as an option for kernel build diff --git a/sources b/sources index ea504b912..1f2bd5e11 100644 --- a/sources +++ b/sources @@ -1,3 +1,4 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 8eb92cc70e7f8d1d18a349ba8c029d7d patch-3.1.1.bz2 6693d8c42055f83f5701d9b65d47208a compat-wireless-3.2-rc1-1.tar.bz2 +24339b23f92d963d851ee042564cdb1c patch-3.1.2-rc1.bz2 From 3b1a645f8a013f818160a3eba09cdf5b9893b266 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Tue, 22 Nov 2011 03:24:00 -0500 Subject: [PATCH 148/487] Linux 3.1.2 --- kernel.spec | 5 ++++- sources | 3 +-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 373e2ca45..46e2a4601 100644 --- a/kernel.spec +++ b/kernel.spec @@ -68,7 +68,7 @@ Summary: The Linux kernel # Do we have a -stable update to apply? %define stable_update 2 # Is it a -stable RC? -%define stable_rc 1 +%define stable_rc 0 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -2185,6 +2185,9 @@ fi # and build. %changelog +* Tue Nov 22 2011 Chuck Ebbert 3.1.2-1 +- Linux 3.1.2 + * Sat Nov 19 2011 Chuck Ebbert 3.1.2-0.rc1.1 - Linux 3.1.2-rc1 diff --git a/sources b/sources index 1f2bd5e11..f8c57b892 100644 --- a/sources +++ b/sources @@ -1,4 +1,3 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 -8eb92cc70e7f8d1d18a349ba8c029d7d patch-3.1.1.bz2 6693d8c42055f83f5701d9b65d47208a compat-wireless-3.2-rc1-1.tar.bz2 -24339b23f92d963d851ee042564cdb1c patch-3.1.2-rc1.bz2 +7487d8e6f00c077f6e15d6f4f9947c30 patch-3.1.2.bz2 From fd1443c8c7fe9b7a21fecb7d925a1a6267d69a82 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 22 Nov 2011 10:36:27 -0500 Subject: [PATCH 149/487] Fix the baserelease sanity check We need to explicitly check for 0, so that we can do things like setting baserelease to 1.1 for scratch builds, etc. --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 46e2a4601..4aa6ba8ab 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1035,7 +1035,7 @@ exit 1 %endif %endif -%if !%{baserelease} +%if "%{baserelease}" == "0" echo "baserelease must be greater than zero" exit 1 %endif From 9de42b3c88ea529ed96861576e9fd457b0577807 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 23 Nov 2011 00:50:53 -0500 Subject: [PATCH 150/487] Linux 3.1.3-rc1 Comment out merged patches: usb-add-quirk-for-logitech-webcams.patch ip6_tunnel-copy-parms.name-after-register_netdevice.patch --- kernel.spec | 14 ++++++++++---- sources | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/kernel.spec b/kernel.spec index 4aa6ba8ab..cf09158d0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -66,9 +66,9 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 2 +%define stable_update 3 # Is it a -stable RC? -%define stable_rc 0 +%define stable_rc 1 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -1409,7 +1409,7 @@ ApplyPatch udlfb-bind-framebuffer-to-interface.patch ApplyPatch epoll-limit-paths.patch ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch ApplyPatch block-stray-block-put-after-teardown.patch -ApplyPatch usb-add-quirk-for-logitech-webcams.patch +#ApplyPatch usb-add-quirk-for-logitech-webcams.patch ApplyPatch HID-wacom-Set-input-bits-before-registration.patch # rhbz#605888 @@ -1421,7 +1421,7 @@ ApplyPatch efi-dont-map-boot-services-on-32bit.patch ApplyPatch hvcs_pi_buf_alloc.patch #rhbz 751165 -ApplyPatch ip6_tunnel-copy-parms.name-after-register_netdevice.patch +#ApplyPatch ip6_tunnel-copy-parms.name-after-register_netdevice.patch ApplyPatch media-dib0700-correct-error-message.patch @@ -2185,6 +2185,12 @@ fi # and build. %changelog +* Wed Nov 23 2011 Chuck Ebbert 3.1.3-0.rc1.1 +- Linux 3.1.3-rc1 +- Comment out merged patches: + usb-add-quirk-for-logitech-webcams.patch + ip6_tunnel-copy-parms.name-after-register_netdevice.patch + * Tue Nov 22 2011 Chuck Ebbert 3.1.2-1 - Linux 3.1.2 diff --git a/sources b/sources index f8c57b892..94640adc6 100644 --- a/sources +++ b/sources @@ -1,3 +1,4 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 6693d8c42055f83f5701d9b65d47208a compat-wireless-3.2-rc1-1.tar.bz2 7487d8e6f00c077f6e15d6f4f9947c30 patch-3.1.2.bz2 +756c229f0565dd6073605c8654fee4b9 patch-3.1.3-rc1.bz2 From ab31f808d5e78a4f110cb0e2f0225434a2238566 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 23 Nov 2011 08:53:48 -0500 Subject: [PATCH 151/487] Ignore all .bz2 files --- .gitignore | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 54fc49100..edb6bec0a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,5 @@ -linux-*.tar.bz2 -patch-*.bz2 clog +*.bz2 *.rpm *.orig kernel-[23].*/ -/compat-wireless-3.2-rc1-1.tar.bz2 From a54c47b488fef6a77ea7fd69e41d62790550c25f Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sun, 27 Nov 2011 14:57:00 -0500 Subject: [PATCH 152/487] linux 3.1.3 --- ...-parms.name-after-register_netdevice.patch | 76 ------------------- kernel.spec | 13 +--- sources | 3 +- usb-add-quirk-for-logitech-webcams.patch | 14 ---- 4 files changed, 5 insertions(+), 101 deletions(-) delete mode 100644 ip6_tunnel-copy-parms.name-after-register_netdevice.patch delete mode 100644 usb-add-quirk-for-logitech-webcams.patch diff --git a/ip6_tunnel-copy-parms.name-after-register_netdevice.patch b/ip6_tunnel-copy-parms.name-after-register_netdevice.patch deleted file mode 100644 index d3bb6a24e..000000000 --- a/ip6_tunnel-copy-parms.name-after-register_netdevice.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 731abb9cb27aef6013ce60808a04e04a545f3f4e Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Thu, 10 Nov 2011 15:10:23 +0000 -Subject: [PATCH] ip6_tunnel: copy parms.name after register_netdevice - -Commit 1c5cae815d removed an explicit call to dev_alloc_name in ip6_tnl_create -because register_netdevice will now create a valid name. This works for the -net_device itself. - -However the tunnel keeps a copy of the name in the parms structure for the -ip6_tnl associated with the tunnel. parms.name is set by copying the net_device -name in ip6_tnl_dev_init_gen. That function is called from ip6_tnl_dev_init in -ip6_tnl_create, but it is done before register_netdevice is called so the name -is set to a bogus value in the parms.name structure. - -This shows up if you do a simple tunnel add, followed by a tunnel show: - -[root@localhost ~]# ip -6 tunnel add remote fec0::100 local fec0::200 -[root@localhost ~]# ip -6 tunnel show -ip6tnl0: ipv6/ipv6 remote :: local :: encaplimit 0 hoplimit 0 tclass 0x00 flowlabel 0x00000 (flowinfo 0x00000000) -ip6tnl%d: ipv6/ipv6 remote fec0::100 local fec0::200 encaplimit 4 hoplimit 64 tclass 0x00 flowlabel 0x00000 (flowinfo 0x00000000) -[root@localhost ~]# - -Fix this by moving the strcpy out of ip6_tnl_dev_init_gen, and calling it after -register_netdevice has successfully returned. - -Cc: stable@vger.kernel.org -Signed-off-by: Josh Boyer -Signed-off-by: David S. Miller ---- - net/ipv6/ip6_tunnel.c | 8 +++++++- - 1 files changed, 7 insertions(+), 1 deletions(-) - -diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c -index bdc15c9..4e2e9ff 100644 ---- a/net/ipv6/ip6_tunnel.c -+++ b/net/ipv6/ip6_tunnel.c -@@ -289,6 +289,8 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct ip6_tnl_parm *p) - if ((err = register_netdevice(dev)) < 0) - goto failed_free; - -+ strcpy(t->parms.name, dev->name); -+ - dev_hold(dev); - ip6_tnl_link(ip6n, t); - return t; -@@ -1407,7 +1409,6 @@ ip6_tnl_dev_init_gen(struct net_device *dev) - struct ip6_tnl *t = netdev_priv(dev); - - t->dev = dev; -- strcpy(t->parms.name, dev->name); - dev->tstats = alloc_percpu(struct pcpu_tstats); - if (!dev->tstats) - return -ENOMEM; -@@ -1487,6 +1488,7 @@ static void __net_exit ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) - static int __net_init ip6_tnl_init_net(struct net *net) - { - struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); -+ struct ip6_tnl *t = NULL; - int err; - - ip6n->tnls[0] = ip6n->tnls_wc; -@@ -1507,6 +1509,10 @@ static int __net_init ip6_tnl_init_net(struct net *net) - err = register_netdev(ip6n->fb_tnl_dev); - if (err < 0) - goto err_register; -+ -+ t = netdev_priv(ip6n->fb_tnl_dev); -+ -+ strcpy(t->parms.name, ip6n->fb_tnl_dev->name); - return 0; - - err_register: --- -1.7.6.2 - diff --git a/kernel.spec b/kernel.spec index cf09158d0..d233d3f35 100644 --- a/kernel.spec +++ b/kernel.spec @@ -68,7 +68,7 @@ Summary: The Linux kernel # Do we have a -stable update to apply? %define stable_update 3 # Is it a -stable RC? -%define stable_rc 1 +%define stable_rc 0 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -746,7 +746,6 @@ Patch12021: udlfb-bind-framebuffer-to-interface.patch Patch12025: rcu-avoid-just-onlined-cpu-resched.patch Patch12026: block-stray-block-put-after-teardown.patch -Patch12027: usb-add-quirk-for-logitech-webcams.patch Patch12030: epoll-limit-paths.patch Patch12031: HID-wacom-Set-input-bits-before-registration.patch @@ -757,9 +756,6 @@ Patch13003: efi-dont-map-boot-services-on-32bit.patch Patch13009: hvcs_pi_buf_alloc.patch -#rhbz 751165 -Patch13010: ip6_tunnel-copy-parms.name-after-register_netdevice.patch - Patch20000: utrace.patch # Flattened devicetree support @@ -1409,7 +1405,6 @@ ApplyPatch udlfb-bind-framebuffer-to-interface.patch ApplyPatch epoll-limit-paths.patch ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch ApplyPatch block-stray-block-put-after-teardown.patch -#ApplyPatch usb-add-quirk-for-logitech-webcams.patch ApplyPatch HID-wacom-Set-input-bits-before-registration.patch # rhbz#605888 @@ -1420,9 +1415,6 @@ ApplyPatch efi-dont-map-boot-services-on-32bit.patch ApplyPatch hvcs_pi_buf_alloc.patch -#rhbz 751165 -#ApplyPatch ip6_tunnel-copy-parms.name-after-register_netdevice.patch - ApplyPatch media-dib0700-correct-error-message.patch # utrace. @@ -2185,6 +2177,9 @@ fi # and build. %changelog +* Sun Nov 26 2011 Chuck Ebbert 3.1.3-1 +- Linux 3.1.3 + * Wed Nov 23 2011 Chuck Ebbert 3.1.3-0.rc1.1 - Linux 3.1.3-rc1 - Comment out merged patches: diff --git a/sources b/sources index 94640adc6..f834ec4a4 100644 --- a/sources +++ b/sources @@ -1,4 +1,3 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 6693d8c42055f83f5701d9b65d47208a compat-wireless-3.2-rc1-1.tar.bz2 -7487d8e6f00c077f6e15d6f4f9947c30 patch-3.1.2.bz2 -756c229f0565dd6073605c8654fee4b9 patch-3.1.3-rc1.bz2 +1efc18287f740528226af94a28349e11 patch-3.1.3.bz2 diff --git a/usb-add-quirk-for-logitech-webcams.patch b/usb-add-quirk-for-logitech-webcams.patch deleted file mode 100644 index b4c795133..000000000 --- a/usb-add-quirk-for-logitech-webcams.patch +++ /dev/null @@ -1,14 +0,0 @@ -Add C600 ID from rhbz #742010 ---- ---- a/drivers/usb/core/quirks.c -+++ b/drivers/usb/core/quirks.c -@@ -38,6 +38,9 @@ static const struct usb_device_id usb_quirk_list[] = { - /* Logitech Webcam B/C500 */ - { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME }, - -+ /* Logitech Webcam C600 */ -+ { USB_DEVICE(0x046d, 0x0808), .driver_info = USB_QUIRK_RESET_RESUME }, -+ - /* Logitech Webcam Pro 9000 */ - { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME }, - From 708ec89f8a0ded52b4144399d3db470328269ec9 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 28 Nov 2011 12:10:12 +1000 Subject: [PATCH 153/487] nouveau: fix two instances of an oops in ttm clear() (rhbz#751753) --- drm-nouveau-updates.patch | 1024 ++++++++++++++++++------------------- kernel.spec | 5 +- 2 files changed, 511 insertions(+), 518 deletions(-) diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index 1e7c9279e..cd9bded11 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -781,10 +781,10 @@ index 890d50e..7226f41 100644 else page_shift = 12; diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c -index b0d753f..a319d56 100644 +index 0e3241c..bb6ec9e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c -@@ -411,13 +411,17 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, +@@ -412,13 +412,17 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, return ret; init->channel = chan->id; @@ -960,12 +960,19 @@ diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouv index 7beb82a..de5efe7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c -@@ -28,418 +28,619 @@ +@@ -28,557 +28,669 @@ #include "nouveau_i2c.h" #include "nouveau_connector.h" #include "nouveau_encoder.h" +#include "nouveau_crtc.h" -+ + +-static int +-auxch_rd(struct drm_encoder *encoder, int address, uint8_t *buf, int size) +-{ +- struct drm_device *dev = encoder->dev; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct nouveau_i2c_chan *auxch; +- int ret; +/****************************************************************************** + * aux channel util functions + *****************************************************************************/ @@ -975,22 +982,7 @@ index 7beb82a..de5efe7 100644 + } \ +} while (0) +#define AUX_ERR(fmt, args...) NV_ERROR(dev, "AUXCH(%d): " fmt, ch, ##args) -+ -+static void -+auxch_fini(struct drm_device *dev, int ch) -+{ -+ nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000); -+} - static int --auxch_rd(struct drm_encoder *encoder, int address, uint8_t *buf, int size) -+auxch_init(struct drm_device *dev, int ch) - { -- struct drm_device *dev = encoder->dev; -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- struct nouveau_i2c_chan *auxch; -- int ret; -- - auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); - if (!auxch) - return -ENODEV; @@ -998,11 +990,30 @@ index 7beb82a..de5efe7 100644 - ret = nouveau_dp_auxch(auxch, 9, address, buf, size); - if (ret) - return ret; +- +- return 0; ++static void ++auxch_fini(struct drm_device *dev, int ch) ++{ ++ nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000); + } + + static int +-auxch_wr(struct drm_encoder *encoder, int address, uint8_t *buf, int size) ++auxch_init(struct drm_device *dev, int ch) + { +- struct drm_device *dev = encoder->dev; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct nouveau_i2c_chan *auxch; +- int ret; + const u32 unksel = 1; /* nfi which to use, or if it matters.. */ + const u32 ureq = unksel ? 0x00100000 : 0x00200000; + const u32 urep = unksel ? 0x01000000 : 0x02000000; + u32 ctrl, timeout; -+ + +- auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); +- if (!auxch) +- return -ENODEV; + /* wait up to 1ms for any previous transaction to be done... */ + timeout = 1000; + do { @@ -1013,7 +1024,9 @@ index 7beb82a..de5efe7 100644 + return -EBUSY; + } + } while (ctrl & 0x03010000); -+ + +- ret = nouveau_dp_auxch(auxch, 8, address, buf, size); +- return ret; + /* set some magic, and wait up to 1ms for it to appear */ + nv_mask(dev, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq); + timeout = 1000; @@ -1026,42 +1039,22 @@ index 7beb82a..de5efe7 100644 + return -EBUSY; + } + } while ((ctrl & 0x03000000) != urep); - - return 0; ++ ++ return 0; } static int --auxch_wr(struct drm_encoder *encoder, int address, uint8_t *buf, int size) +-nouveau_dp_lane_count_set(struct drm_encoder *encoder, uint8_t cmd) +auxch_tx(struct drm_device *dev, int ch, u8 type, u32 addr, u8 *data, u8 size) { - struct drm_device *dev = encoder->dev; - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- struct nouveau_i2c_chan *auxch; -- int ret; +- uint32_t tmp; +- int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); + u32 ctrl, stat, timeout, retries; + u32 xbuf[4] = {}; + int ret, i; -- auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); -- if (!auxch) -- return -ENODEV; -+ AUX_DBG("%d: 0x%08x %d\n", type, addr, size); - -- ret = nouveau_dp_auxch(auxch, 8, address, buf, size); -- return ret; --} -+ ret = auxch_init(dev, ch); -+ if (ret) -+ goto out; - --static int --nouveau_dp_lane_count_set(struct drm_encoder *encoder, uint8_t cmd) --{ -- struct drm_device *dev = encoder->dev; -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- uint32_t tmp; -- int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); -- - tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); - tmp &= ~(NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED | - NV50_SOR_DP_CTRL_LANE_MASK); @@ -1069,15 +1062,13 @@ index 7beb82a..de5efe7 100644 - if (cmd & DP_LANE_COUNT_ENHANCED_FRAME_EN) - tmp |= NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED; - nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp); -- ++ AUX_DBG("%d: 0x%08x %d\n", type, addr, size); + - return auxch_wr(encoder, DP_LANE_COUNT_SET, &cmd, 1); -} -+ stat = nv_rd32(dev, 0x00e4e8 + (ch * 0x50)); -+ if (!(stat & 0x10000000)) { -+ AUX_DBG("sink not detected\n"); -+ ret = -ENXIO; ++ ret = auxch_init(dev, ch); ++ if (ret) + goto out; -+ } -static int -nouveau_dp_link_bw_set(struct drm_encoder *encoder, uint8_t cmd) @@ -1086,6 +1077,18 @@ index 7beb82a..de5efe7 100644 - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - uint32_t tmp; - int reg = 0x614300 + (nv_encoder->or * 0x800); ++ stat = nv_rd32(dev, 0x00e4e8 + (ch * 0x50)); ++ if (!(stat & 0x10000000)) { ++ AUX_DBG("sink not detected\n"); ++ ret = -ENXIO; ++ goto out; ++ } + +- tmp = nv_rd32(dev, reg); +- tmp &= 0xfff3ffff; +- if (cmd == DP_LINK_BW_2_7) +- tmp |= 0x00040000; +- nv_wr32(dev, reg, tmp); + if (!(type & 1)) { + memcpy(xbuf, data, size); + for (i = 0; i < 16; i += 4) { @@ -1094,47 +1097,13 @@ index 7beb82a..de5efe7 100644 + } + } -- tmp = nv_rd32(dev, reg); -- tmp &= 0xfff3ffff; -- if (cmd == DP_LINK_BW_2_7) -- tmp |= 0x00040000; -- nv_wr32(dev, reg, tmp); +- return auxch_wr(encoder, DP_LINK_BW_SET, &cmd, 1); +-} + ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); + ctrl &= ~0x0001f0ff; + ctrl |= type << 12; + ctrl |= size - 1; + nv_wr32(dev, 0x00e4e0 + (ch * 0x50), addr); -+ -+ /* retry transaction a number of times on failure... */ -+ ret = -EREMOTEIO; -+ for (retries = 0; retries < 32; retries++) { -+ /* reset, and delay a while if this is a retry */ -+ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); -+ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); -+ if (retries) -+ udelay(400); -+ -+ /* transaction request, wait up to 1ms for it to complete */ -+ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl); -+ -+ timeout = 1000; -+ do { -+ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); -+ udelay(1); -+ if (!timeout--) { -+ AUX_ERR("tx req timeout 0x%08x\n", ctrl); -+ goto out; -+ } -+ } while (ctrl & 0x00010000); - -- return auxch_wr(encoder, DP_LINK_BW_SET, &cmd, 1); --} -+ /* read status, and check if transaction completed ok */ -+ stat = nv_mask(dev, 0x00e4e8 + (ch * 0x50), 0, 0); -+ if (!(stat & 0x000f0f00)) { -+ ret = 0; -+ break; -+ } -static int -nouveau_dp_link_train_set(struct drm_encoder *encoder, int pattern) @@ -1145,20 +1114,21 @@ index 7beb82a..de5efe7 100644 - uint8_t cmd; - int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); - int ret; -+ AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); -+ } ++ /* retry transaction a number of times on failure... */ ++ ret = -EREMOTEIO; ++ for (retries = 0; retries < 32; retries++) { ++ /* reset, and delay a while if this is a retry */ ++ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); ++ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); ++ if (retries) ++ udelay(400); - tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); - tmp &= ~NV50_SOR_DP_CTRL_TRAINING_PATTERN; - tmp |= (pattern << 24); - nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp); -+ if (type & 1) { -+ for (i = 0; i < 16; i += 4) { -+ xbuf[i / 4] = nv_rd32(dev, 0x00e4d0 + (ch * 0x50) + i); -+ AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); -+ } -+ memcpy(data, xbuf, size); -+ } ++ /* transaction request, wait up to 1ms for it to complete */ ++ nv_wr32(dev, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl); - ret = auxch_rd(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1); - if (ret) @@ -1166,13 +1136,58 @@ index 7beb82a..de5efe7 100644 - cmd &= ~DP_TRAINING_PATTERN_MASK; - cmd |= (pattern & DP_TRAINING_PATTERN_MASK); - return auxch_wr(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1); +-} ++ timeout = 1000; ++ do { ++ ctrl = nv_rd32(dev, 0x00e4e4 + (ch * 0x50)); ++ udelay(1); ++ if (!timeout--) { ++ AUX_ERR("tx req timeout 0x%08x\n", ctrl); ++ goto out; ++ } ++ } while (ctrl & 0x00010000); + +-static int +-nouveau_dp_max_voltage_swing(struct drm_encoder *encoder) +-{ +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct drm_device *dev = encoder->dev; +- struct bit_displayport_encoder_table_entry *dpse; +- struct bit_displayport_encoder_table *dpe; +- int i, dpe_headerlen, max_vs = 0; ++ /* read status, and check if transaction completed ok */ ++ stat = nv_mask(dev, 0x00e4e8 + (ch * 0x50), 0, 0); ++ if (!(stat & 0x000f0f00)) { ++ ret = 0; ++ break; ++ } + +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) +- return false; +- dpse = (void *)((char *)dpe + dpe_headerlen); ++ AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); ++ } + +- for (i = 0; i < dpe_headerlen; i++, dpse++) { +- if (dpse->vs_level > max_vs) +- max_vs = dpse->vs_level; ++ if (type & 1) { ++ for (i = 0; i < 16; i += 4) { ++ xbuf[i / 4] = nv_rd32(dev, 0x00e4d0 + (ch * 0x50) + i); ++ AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); ++ } ++ memcpy(data, xbuf, size); + } + +- return max_vs; +out: + auxch_fini(dev, ch); + return ret; } -static int --nouveau_dp_max_voltage_swing(struct drm_encoder *encoder) +-nouveau_dp_max_pre_emphasis(struct drm_encoder *encoder, int vs) +static u32 +dp_link_bw_get(struct drm_device *dev, int or, int link) { @@ -1180,21 +1195,24 @@ index 7beb82a..de5efe7 100644 - struct drm_device *dev = encoder->dev; - struct bit_displayport_encoder_table_entry *dpse; - struct bit_displayport_encoder_table *dpe; -- int i, dpe_headerlen, max_vs = 0; +- int i, dpe_headerlen, max_pre = 0; - - dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); - if (!dpe) - return false; - dpse = (void *)((char *)dpe + dpe_headerlen); +- +- for (i = 0; i < dpe_headerlen; i++, dpse++) { +- if (dpse->vs_level != vs) +- continue; + u32 ctrl = nv_rd32(dev, 0x614300 + (or * 0x800)); + if (!(ctrl & 0x000c0000)) + return 162000; + return 270000; +} -- for (i = 0; i < dpe_headerlen; i++, dpse++) { -- if (dpse->vs_level > max_vs) -- max_vs = dpse->vs_level; +- if (dpse->pre_level > max_pre) +- max_pre = dpse->pre_level; +static int +dp_lane_count_get(struct drm_device *dev, int or, int link) +{ @@ -1206,40 +1224,52 @@ index 7beb82a..de5efe7 100644 + return 4; } - -- return max_vs; +- return max_pre; } --static int --nouveau_dp_max_pre_emphasis(struct drm_encoder *encoder, int vs) +-static bool +-nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config) +void +nouveau_dp_tu_update(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) { - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct drm_device *dev = encoder->dev; -- struct bit_displayport_encoder_table_entry *dpse; - struct bit_displayport_encoder_table *dpe; -- int i, dpe_headerlen, max_pre = 0; +- int ret, i, dpe_headerlen, vs = 0, pre = 0; +- uint8_t request[2]; + const u32 symbol = 100000; + int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0; + int TU, VTUi, VTUf, VTUa; + u64 link_data_rate, link_ratio, unk; + u32 best_diff = 64 * symbol; + u32 link_nr, link_bw, r; -+ + +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) +- return false; + /* calculate packed data rate for each lane */ + link_nr = dp_lane_count_get(dev, or, link); + link_data_rate = (clk * bpp / 8) / link_nr; -+ + +- ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2); +- if (ret) +- return false; + /* calculate ratio of packed data rate to link symbol rate */ + link_bw = dp_link_bw_get(dev, or, link); + link_ratio = link_data_rate * symbol; + r = do_div(link_ratio, link_bw); -+ + +- NV_DEBUG_KMS(dev, "\t\tadjust 0x%02x 0x%02x\n", request[0], request[1]); + for (TU = 64; TU >= 32; TU--) { + /* calculate average number of valid symbols in each TU */ + u32 tu_valid = link_ratio * TU; + u32 calc, diff; -+ + +- /* Keep all lanes at the same level.. */ +- for (i = 0; i < nv_encoder->dp.link_nr; i++) { +- int lane_req = (request[i >> 1] >> ((i & 1) << 2)) & 0xf; +- int lane_vs = lane_req & 3; +- int lane_pre = (lane_req >> 2) & 3; + /* find a hw representation for the fraction.. */ + VTUi = tu_valid / symbol; + calc = VTUi * symbol; @@ -1249,7 +1279,12 @@ index 7beb82a..de5efe7 100644 + VTUf = symbol / (symbol - diff); + if (symbol - (VTUf * diff)) + VTUf++; -+ + +- if (lane_vs > vs) +- vs = lane_vs; +- if (lane_pre > pre) +- pre = lane_pre; +- } + if (VTUf <= 15) { + VTUa = 1; + calc += symbol - (symbol / VTUf); @@ -1264,10 +1299,9 @@ index 7beb82a..de5efe7 100644 + calc += symbol / VTUf; + } -- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); -- if (!dpe) -- return false; -- dpse = (void *)((char *)dpe + dpe_headerlen); +- if (vs >= nouveau_dp_max_voltage_swing(encoder)) { +- vs = nouveau_dp_max_voltage_swing(encoder); +- vs |= 4; + diff = calc - tu_valid; + } else { + /* no remainder, but the hw doesn't like the fractional @@ -1278,10 +1312,7 @@ index 7beb82a..de5efe7 100644 + VTUf = 1; + VTUi--; + } - -- for (i = 0; i < dpe_headerlen; i++, dpse++) { -- if (dpse->vs_level != vs) -- continue; ++ + if (diff < best_diff) { + best_diff = diff; + bestTU = TU; @@ -1291,23 +1322,27 @@ index 7beb82a..de5efe7 100644 + if (diff == 0) + break; + } -+ } + } -- if (dpse->pre_level > max_pre) -- max_pre = dpse->pre_level; +- if (pre >= nouveau_dp_max_pre_emphasis(encoder, vs & 3)) { +- pre = nouveau_dp_max_pre_emphasis(encoder, vs & 3); +- pre |= 4; + if (!bestTU) { + NV_ERROR(dev, "DP: unable to find suitable config\n"); + return; } -- return max_pre; +- /* Update the configuration for all lanes.. */ +- for (i = 0; i < nv_encoder->dp.link_nr; i++) +- config[i] = (pre << 3) | vs; + /* XXX close to vbios numbers, but not right */ + unk = (symbol - link_ratio) * bestTU; + unk *= link_ratio; + r = do_div(unk, symbol); + r = do_div(unk, symbol); + unk += 6; -+ + +- return true; + nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x000001fc, bestTU << 2); + nv_mask(dev, NV50_SOR_DP_SCFG(or, link), 0x010f7f3f, bestVTUa << 24 | + bestVTUf << 16 | @@ -1316,63 +1351,63 @@ index 7beb82a..de5efe7 100644 } -static bool --nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config) +-nouveau_dp_link_train_commit(struct drm_encoder *encoder, uint8_t *config) +u8 * +nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) { - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct drm_device *dev = encoder->dev; +- struct bit_displayport_encoder_table_entry *dpse; - struct bit_displayport_encoder_table *dpe; -- int ret, i, dpe_headerlen, vs = 0, pre = 0; -- uint8_t request[2]; +- int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); +- int dpe_headerlen, ret, i; - -- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); -- if (!dpe) -- return false; -- -- ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2); -- if (ret) -- return false; -- -- NV_DEBUG_KMS(dev, "\t\tadjust 0x%02x 0x%02x\n", request[0], request[1]); -- -- /* Keep all lanes at the same level.. */ -- for (i = 0; i < nv_encoder->dp.link_nr; i++) { -- int lane_req = (request[i >> 1] >> ((i & 1) << 2)) & 0xf; -- int lane_vs = lane_req & 3; -- int lane_pre = (lane_req >> 2) & 3; +- NV_DEBUG_KMS(dev, "\t\tconfig 0x%02x 0x%02x 0x%02x 0x%02x\n", +- config[0], config[1], config[2], config[3]); + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->vbios; + struct bit_entry d; + u8 *table; + int i; -+ + +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) +- return false; +- dpse = (void *)((char *)dpe + dpe_headerlen); + if (bit_table(dev, 'd', &d)) { + NV_ERROR(dev, "BIT 'd' table not found\n"); + return NULL; + } -- if (lane_vs > vs) -- vs = lane_vs; -- if (lane_pre > pre) -- pre = lane_pre; +- for (i = 0; i < dpe->record_nr; i++, dpse++) { +- if (dpse->vs_level == (config[0] & 3) && +- dpse->pre_level == ((config[0] >> 3) & 3)) +- break; + if (d.version != 1) { + NV_ERROR(dev, "BIT 'd' table version %d unknown\n", d.version); + return NULL; } +- BUG_ON(i == dpe->record_nr); -- if (vs >= nouveau_dp_max_voltage_swing(encoder)) { -- vs = nouveau_dp_max_voltage_swing(encoder); -- vs |= 4; +- for (i = 0; i < nv_encoder->dp.link_nr; i++) { +- const int shift[4] = { 16, 8, 0, 24 }; +- uint32_t mask = 0xff << shift[i]; +- uint32_t reg0, reg1, reg2; + table = ROMPTR(bios, d.data[0]); + if (!table) { + NV_ERROR(dev, "displayport table pointer invalid\n"); + return NULL; - } ++ } -- if (pre >= nouveau_dp_max_pre_emphasis(encoder, vs & 3)) { -- pre = nouveau_dp_max_pre_emphasis(encoder, vs & 3); -- pre |= 4; +- reg0 = nv_rd32(dev, NV50_SOR_DP_UNK118(or, link)) & ~mask; +- reg0 |= (dpse->reg0 << shift[i]); +- reg1 = nv_rd32(dev, NV50_SOR_DP_UNK120(or, link)) & ~mask; +- reg1 |= (dpse->reg1 << shift[i]); +- reg2 = nv_rd32(dev, NV50_SOR_DP_UNK130(or, link)) & 0xffff00ff; +- reg2 |= (dpse->reg2 << 8); +- nv_wr32(dev, NV50_SOR_DP_UNK118(or, link), reg0); +- nv_wr32(dev, NV50_SOR_DP_UNK120(or, link), reg1); +- nv_wr32(dev, NV50_SOR_DP_UNK130(or, link), reg2); + switch (table[0]) { + case 0x20: + case 0x21: @@ -1383,9 +1418,9 @@ index 7beb82a..de5efe7 100644 + return NULL; } -- /* Update the configuration for all lanes.. */ -- for (i = 0; i < nv_encoder->dp.link_nr; i++) -- config[i] = (pre << 3) | vs; +- ret = auxch_wr(encoder, DP_TRAINING_LANE0_SET, config, 4); +- if (ret) +- return false; + for (i = 0; i < table[3]; i++) { + *entry = ROMPTR(bios, table[table[1] + (i * table[2])]); + if (*entry && bios_encoder_match(dcb, ROM32((*entry)[0]))) @@ -1397,15 +1432,8 @@ index 7beb82a..de5efe7 100644 + return NULL; } --static bool --nouveau_dp_link_train_commit(struct drm_encoder *encoder, uint8_t *config) --{ -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- struct drm_device *dev = encoder->dev; -- struct bit_displayport_encoder_table_entry *dpse; -- struct bit_displayport_encoder_table *dpe; -- int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); -- int dpe_headerlen, ret, i; +-bool +-nouveau_dp_link_train(struct drm_encoder *encoder) +/****************************************************************************** + * link training + *****************************************************************************/ @@ -1423,20 +1451,36 @@ index 7beb82a..de5efe7 100644 + u8 stat[6]; + u8 conf[4]; +}; - -- NV_DEBUG_KMS(dev, "\t\tconfig 0x%02x 0x%02x 0x%02x 0x%02x\n", -- config[0], config[1], config[2], config[3]); ++ +static void +dp_set_link_config(struct drm_device *dev, struct dp_state *dp) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; + { +- struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; +- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +- struct nouveau_connector *nv_connector; +- struct bit_displayport_encoder_table *dpe; +- int dpe_headerlen; +- uint8_t config[4], status[3]; +- bool cr_done, cr_max_vs, eq_done, hpd_state; +- int ret = 0, i, tries, voltage; + int or = dp->or, link = dp->link; + u8 *entry, sink[2]; + u32 dp_ctrl; + u16 script; -+ + +- NV_DEBUG_KMS(dev, "link training!!\n"); + NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); -+ + +- nv_connector = nouveau_encoder_connector_get(nv_encoder); +- if (!nv_connector) +- return false; +- +- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); +- if (!dpe) { +- NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or); +- return false; + /* set selected link rate on source */ + switch (dp->link_bw) { + case 270000: @@ -1447,16 +1491,15 @@ index 7beb82a..de5efe7 100644 + nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00000000); + sink[0] = DP_LINK_BW_1_62; + break; -+ } + } -- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); -- if (!dpe) -- return false; -- dpse = (void *)((char *)dpe + dpe_headerlen); +- /* disable hotplug detect, this flips around on some panels during +- * link training. + /* offset +0x0a of each dp encoder table entry is a pointer to another + * table, that has (among other things) pointers to more scripts that + * need to be executed, this time depending on link speed. -+ */ + */ +- hpd_state = pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); + entry = ROMPTR(&dev_priv->vbios, dp->entry[10]); + if (entry) { + if (dp->table[0] < 0x30) { @@ -1469,90 +1512,77 @@ index 7beb82a..de5efe7 100644 + script = ROM16(entry[1]); + } -- for (i = 0; i < dpe->record_nr; i++, dpse++) { -- if (dpse->vs_level == (config[0] & 3) && -- dpse->pre_level == ((config[0] >> 3) & 3)) -- break; +- if (dpe->script0) { +- NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); +- nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0), +- nv_encoder->dcb); + nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc); } -- BUG_ON(i == dpe->record_nr); -- -- for (i = 0; i < nv_encoder->dp.link_nr; i++) { -- const int shift[4] = { 16, 8, 0, 24 }; -- uint32_t mask = 0xff << shift[i]; -- uint32_t reg0, reg1, reg2; -- -- reg0 = nv_rd32(dev, NV50_SOR_DP_UNK118(or, link)) & ~mask; -- reg0 |= (dpse->reg0 << shift[i]); -- reg1 = nv_rd32(dev, NV50_SOR_DP_UNK120(or, link)) & ~mask; -- reg1 |= (dpse->reg1 << shift[i]); -- reg2 = nv_rd32(dev, NV50_SOR_DP_UNK130(or, link)) & 0xffff00ff; -- reg2 |= (dpse->reg2 << 8); -- nv_wr32(dev, NV50_SOR_DP_UNK118(or, link), reg0); -- nv_wr32(dev, NV50_SOR_DP_UNK120(or, link), reg1); -- nv_wr32(dev, NV50_SOR_DP_UNK130(or, link), reg2); -+ + +-train: +- cr_done = eq_done = false; + /* configure lane count on the source */ + dp_ctrl = ((1 << dp->link_nr) - 1) << 16; + sink[1] = dp->link_nr; + if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) { + dp_ctrl |= 0x00004000; + sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; - } ++ } -- ret = auxch_wr(encoder, DP_TRAINING_LANE0_SET, config, 4); -- if (ret) -- return false; +- /* set link configuration */ +- NV_DEBUG_KMS(dev, "\tbegin train: bw %d, lanes %d\n", +- nv_encoder->dp.link_bw, nv_encoder->dp.link_nr); + nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x001f4000, dp_ctrl); -- return true; +- ret = nouveau_dp_link_bw_set(encoder, nv_encoder->dp.link_bw); +- if (ret) +- return false; + /* inform the sink of the new configuration */ + auxch_tx(dev, dp->auxch, 8, DP_LINK_BW_SET, sink, 2); - } ++} --bool --nouveau_dp_link_train(struct drm_encoder *encoder) +- config[0] = nv_encoder->dp.link_nr; +- if (nv_encoder->dp.dpcd_version >= 0x11 && +- nv_encoder->dp.enhanced_frame) +- config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; +static void +dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 tp) - { -- struct drm_device *dev = encoder->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- struct nouveau_connector *nv_connector; -- struct bit_displayport_encoder_table *dpe; -- int dpe_headerlen; -- uint8_t config[4], status[3]; -- bool cr_done, cr_max_vs, eq_done, hpd_state; -- int ret = 0, i, tries, voltage; ++{ + u8 sink_tp; -- NV_DEBUG_KMS(dev, "link training!!\n"); +- ret = nouveau_dp_lane_count_set(encoder, config[0]); +- if (ret) +- return false; + NV_DEBUG_KMS(dev, "training pattern %d\n", tp); -- nv_connector = nouveau_encoder_connector_get(nv_encoder); -- if (!nv_connector) -- return false; +- /* clock recovery */ +- NV_DEBUG_KMS(dev, "\tbegin cr\n"); +- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_1); +- if (ret) +- goto stop; + nv_mask(dev, NV50_SOR_DP_CTRL(dp->or, dp->link), 0x0f000000, tp << 24); -- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); -- if (!dpe) { -- NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or); -- return false; -- } +- tries = 0; +- voltage = -1; +- memset(config, 0x00, sizeof(config)); +- for (;;) { +- if (!nouveau_dp_link_train_commit(encoder, config)) +- break; + auxch_tx(dev, dp->auxch, 9, DP_TRAINING_PATTERN_SET, &sink_tp, 1); + sink_tp &= ~DP_TRAINING_PATTERN_MASK; + sink_tp |= tp; + auxch_tx(dev, dp->auxch, 8, DP_TRAINING_PATTERN_SET, &sink_tp, 1); +} -- /* disable hotplug detect, this flips around on some panels during -- * link training. -- */ -- hpd_state = pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); +- udelay(100); +static const u8 nv50_lane_map[] = { 16, 8, 0, 24 }; +static const u8 nvaf_lane_map[] = { 24, 16, 8, 0 }; -+ + +- ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 2); +- if (ret) +- break; +- NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n", +- status[0], status[1]); +static int +dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) +{ @@ -1562,12 +1592,21 @@ index 7beb82a..de5efe7 100644 + int link = dp->link; + int or = dp->or; + int i; -+ + +- cr_done = true; +- cr_max_vs = false; +- for (i = 0; i < nv_encoder->dp.link_nr; i++) { +- int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf; + if (dev_priv->chipset != 0xaf) + shifts = nv50_lane_map; + else + shifts = nvaf_lane_map; -+ + +- if (!(lane & DP_LANE_CR_DONE)) { +- cr_done = false; +- if (config[i] & DP_TRAIN_MAX_PRE_EMPHASIS_REACHED) +- cr_max_vs = true; +- break; + for (i = 0; i < dp->link_nr; i++) { + u8 *conf = dp->entry + dp->table[4]; + u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf; @@ -1591,8 +1630,13 @@ index 7beb82a..de5efe7 100644 + conf += dp->table[5]; + if (conf >= last) + return -EINVAL; -+ } -+ + } +- } + +- if ((config[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { +- voltage = config[0] & DP_TRAIN_VOLTAGE_SWING_MASK; +- tries = 0; +- } + conf += 2; + } else { + /* no lookup table anymore, set entries for each @@ -1605,69 +1649,57 @@ index 7beb82a..de5efe7 100644 + case 2: lpre += 7; break; + case 3: lpre += 9; break; + } -+ + +- if (cr_done || cr_max_vs || (++tries == 5)) +- break; + conf = conf + (lpre * dp->table[5]); + conf++; + } -- if (dpe->script0) { -- NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); -- nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0), -- nv_encoder->dcb); +- if (!nouveau_dp_link_train_adjust(encoder, config)) +- break; + drv |= conf[0] << shifts[i]; + pre |= conf[1] << shifts[i]; + unk = (unk & ~0x0000ff00) | (conf[2] << 8); } --train: -- cr_done = eq_done = false; +- if (!cr_done) +- goto stop; + nv_mask(dev, NV50_SOR_DP_UNK118(or, link), mask, drv); + nv_mask(dev, NV50_SOR_DP_UNK120(or, link), mask, pre); + nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000ff0f, unk); - -- /* set link configuration */ -- NV_DEBUG_KMS(dev, "\tbegin train: bw %d, lanes %d\n", -- nv_encoder->dp.link_bw, nv_encoder->dp.link_nr); ++ + return auxch_tx(dev, dp->auxch, 8, DP_TRAINING_LANE0_SET, dp->conf, 4); +} - -- ret = nouveau_dp_link_bw_set(encoder, nv_encoder->dp.link_bw); -- if (ret) -- return false; ++ +static int +dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay) +{ + int ret; - -- config[0] = nv_encoder->dp.link_nr; -- if (nv_encoder->dp.dpcd_version >= 0x11 && -- nv_encoder->dp.enhanced_frame) -- config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; ++ + udelay(delay); -- ret = nouveau_dp_lane_count_set(encoder, config[0]); +- /* channel equalisation */ +- NV_DEBUG_KMS(dev, "\tbegin eq\n"); +- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_2); + ret = auxch_tx(dev, dp->auxch, 9, DP_LANE0_1_STATUS, dp->stat, 6); if (ret) -- return false; +- goto stop; + return ret; -- /* clock recovery */ -- NV_DEBUG_KMS(dev, "\tbegin cr\n"); -- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_1); -- if (ret) -- goto stop; +- for (tries = 0; tries <= 5; tries++) { +- udelay(400); + NV_DEBUG_KMS(dev, "status %02x %02x %02x %02x %02x %02x\n", + dp->stat[0], dp->stat[1], dp->stat[2], dp->stat[3], + dp->stat[4], dp->stat[5]); + return 0; +} -- tries = 0; -- voltage = -1; -- memset(config, 0x00, sizeof(config)); -- for (;;) { -- if (!nouveau_dp_link_train_commit(encoder, config)) +- ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 3); +- if (ret) - break; +- NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n", +- status[0], status[1]); +static int +dp_link_train_cr(struct drm_device *dev, struct dp_state *dp) +{ @@ -1675,136 +1707,61 @@ index 7beb82a..de5efe7 100644 + int voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK; + int tries = 0, i; -- udelay(100); +- eq_done = true; +- if (!(status[2] & DP_INTERLANE_ALIGN_DONE)) +- eq_done = false; + dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_1); -- ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 2); -- if (ret) +- for (i = 0; eq_done && i < nv_encoder->dp.link_nr; i++) { +- int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf; + do { + if (dp_link_train_commit(dev, dp) || + dp_link_train_update(dev, dp, 100)) - break; -- NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n", -- status[0], status[1]); ++ break; - cr_done = true; -- cr_max_vs = false; -- for (i = 0; i < nv_encoder->dp.link_nr; i++) { -- int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf; -- ++ cr_done = true; + for (i = 0; i < dp->link_nr; i++) { + u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; if (!(lane & DP_LANE_CR_DONE)) { cr_done = false; -- if (config[i] & DP_TRAIN_MAX_PRE_EMPHASIS_REACHED) -- cr_max_vs = true; + if (dp->conf[i] & DP_TRAIN_MAX_SWING_REACHED) + abort = true; break; } - } ++ } -- if ((config[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { -- voltage = config[0] & DP_TRAIN_VOLTAGE_SWING_MASK; +- if (!(lane & DP_LANE_CHANNEL_EQ_DONE) || +- !(lane & DP_LANE_SYMBOL_LOCKED)) { +- eq_done = false; +- break; +- } + if ((dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { + voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK; - tries = 0; ++ tries = 0; } + } while (!cr_done && !abort && ++tries < 5); -- if (cr_done || cr_max_vs || (++tries == 5)) +- if (eq_done || !cr_done) - break; -- -- if (!nouveau_dp_link_train_adjust(encoder, config)) -- break; -- } -- -- if (!cr_done) -- goto stop; + return cr_done ? 0 : -1; +} -- /* channel equalisation */ -- NV_DEBUG_KMS(dev, "\tbegin eq\n"); -- ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_2); -- if (ret) -- goto stop; +- if (!nouveau_dp_link_train_adjust(encoder, config) || +- !nouveau_dp_link_train_commit(encoder, config)) +- break; +- } +static int +dp_link_train_eq(struct drm_device *dev, struct dp_state *dp) +{ + bool eq_done, cr_done = true; + int tries = 0, i; -- for (tries = 0; tries <= 5; tries++) { -- udelay(400); -+ dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_2); - -- ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 3); -- if (ret) -+ do { -+ if (dp_link_train_update(dev, dp, 400)) - break; -- NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n", -- status[0], status[1]); - -- eq_done = true; -- if (!(status[2] & DP_INTERLANE_ALIGN_DONE)) -- eq_done = false; -- -- for (i = 0; eq_done && i < nv_encoder->dp.link_nr; i++) { -- int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf; -- -- if (!(lane & DP_LANE_CR_DONE)) { -+ eq_done = !!(dp->stat[2] & DP_INTERLANE_ALIGN_DONE); -+ for (i = 0; i < dp->link_nr && eq_done; i++) { -+ u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; -+ if (!(lane & DP_LANE_CR_DONE)) - cr_done = false; -- break; -- } -- - if (!(lane & DP_LANE_CHANNEL_EQ_DONE) || -- !(lane & DP_LANE_SYMBOL_LOCKED)) { -+ !(lane & DP_LANE_SYMBOL_LOCKED)) - eq_done = false; -- break; -- } - } - -- if (eq_done || !cr_done) -+ if (dp_link_train_commit(dev, dp)) - break; -+ } while (!eq_done && cr_done && ++tries <= 5); - -- if (!nouveau_dp_link_train_adjust(encoder, config) || -- !nouveau_dp_link_train_commit(encoder, config)) -- break; -- } -+ return eq_done ? 0 : -1; -+} - -stop: - /* end link training */ - ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_DISABLE); - if (ret) -+bool -+nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) -+{ -+ struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; -+ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); -+ struct nouveau_connector *nv_connector = -+ nouveau_encoder_connector_get(nv_encoder); -+ struct drm_device *dev = encoder->dev; -+ struct nouveau_i2c_chan *auxch; -+ const u32 bw_list[] = { 270000, 162000, 0 }; -+ const u32 *link_bw = bw_list; -+ struct dp_state dp; -+ -+ auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); -+ if (!auxch) - return false; +- return false; ++ dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_2); - /* retry at a lower setting, if possible */ - if (!ret && !(eq_done && cr_done)) { @@ -1814,90 +1771,53 @@ index 7beb82a..de5efe7 100644 - nv_encoder->dp.link_bw = DP_LINK_BW_1_62; - goto train; - } -+ dp.table = nouveau_dp_bios_data(dev, nv_encoder->dcb, &dp.entry); -+ if (!dp.table) -+ return -EINVAL; -+ -+ dp.dcb = nv_encoder->dcb; -+ dp.crtc = nv_crtc->index; -+ dp.auxch = auxch->rd; -+ dp.or = nv_encoder->or; -+ dp.link = !(nv_encoder->dcb->sorconf.link & 1); -+ dp.dpcd = nv_encoder->dp.dpcd; -+ -+ /* some sinks toggle hotplug in response to some of the actions -+ * we take during link training (DP_SET_POWER is one), we need -+ * to ignore them for the moment to avoid races. -+ */ -+ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); -+ -+ /* enable down-spreading, if possible */ -+ if (dp.table[1] >= 16) { -+ u16 script = ROM16(dp.entry[14]); -+ if (nv_encoder->dp.dpcd[3] & 1) -+ script = ROM16(dp.entry[12]); -+ -+ nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc); - } +- } ++ do { ++ if (dp_link_train_update(dev, dp, 400)) ++ break; - if (dpe->script1) { - NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or); - nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1), - nv_encoder->dcb); -+ /* execute pre-train script from vbios */ -+ nouveau_bios_run_init_table(dev, ROM16(dp.entry[6]), dp.dcb, dp.crtc); -+ -+ /* start off at highest link rate supported by encoder and display */ -+ while (*link_bw > nv_encoder->dp.link_bw) -+ link_bw++; -+ -+ while (link_bw[0]) { -+ /* find minimum required lane count at this link rate */ -+ dp.link_nr = nv_encoder->dp.link_nr; -+ while ((dp.link_nr >> 1) * link_bw[0] > datarate) -+ dp.link_nr >>= 1; -+ -+ /* drop link rate to minimum with this lane count */ -+ while ((link_bw[1] * dp.link_nr) > datarate) -+ link_bw++; -+ dp.link_bw = link_bw[0]; -+ -+ /* program selected link configuration */ -+ dp_set_link_config(dev, &dp); -+ -+ /* attempt to train the link at this configuration */ -+ memset(dp.stat, 0x00, sizeof(dp.stat)); -+ if (!dp_link_train_cr(dev, &dp) && -+ !dp_link_train_eq(dev, &dp)) -+ break; -+ -+ /* retry at lower rate */ -+ link_bw++; - } +- } ++ eq_done = !!(dp->stat[2] & DP_INTERLANE_ALIGN_DONE); ++ for (i = 0; i < dp->link_nr && eq_done; i++) { ++ u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; ++ if (!(lane & DP_LANE_CR_DONE)) ++ cr_done = false; ++ if (!(lane & DP_LANE_CHANNEL_EQ_DONE) || ++ !(lane & DP_LANE_SYMBOL_LOCKED)) ++ eq_done = false; ++ } - /* re-enable hotplug detect */ - pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, hpd_state); -+ /* finish link training */ -+ dp_set_training_pattern(dev, &dp, DP_TRAINING_PATTERN_DISABLE); ++ if (dp_link_train_commit(dev, dp)) ++ break; ++ } while (!eq_done && cr_done && ++tries <= 5); - return eq_done; -+ /* execute post-train script from vbios */ -+ nouveau_bios_run_init_table(dev, ROM16(dp.entry[8]), dp.dcb, dp.crtc); -+ -+ /* re-enable hotplug detect */ -+ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true); -+ return true; ++ return eq_done ? 0 : -1; } bool -@@ -447,31 +648,34 @@ nouveau_dp_detect(struct drm_encoder *encoder) +-nouveau_dp_detect(struct drm_encoder *encoder) ++nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) { ++ struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; ++ struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); ++ struct nouveau_connector *nv_connector = ++ nouveau_encoder_connector_get(nv_encoder); struct drm_device *dev = encoder->dev; - uint8_t dpcd[4]; +- int ret; + struct nouveau_i2c_chan *auxch; -+ u8 *dpcd = nv_encoder->dp.dpcd; - int ret; ++ const u32 bw_list[] = { 270000, 162000, 0 }; ++ const u32 *link_bw = bw_list; ++ struct dp_state dp; - ret = auxch_rd(encoder, 0x0000, dpcd, 4); - if (ret) @@ -1910,47 +1830,64 @@ index 7beb82a..de5efe7 100644 - nv_encoder->dcb->dpconf.link_bw, - nv_encoder->dcb->dpconf.link_nr, - dpcd[1], dpcd[2] & 0x0f, dpcd[0]); -+ ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8); -+ if (ret) -+ return false; ++ dp.table = nouveau_dp_bios_data(dev, nv_encoder->dcb, &dp.entry); ++ if (!dp.table) ++ return -EINVAL; - nv_encoder->dp.dpcd_version = dpcd[0]; -+ nv_encoder->dp.link_bw = 27000 * dpcd[1]; -+ nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; ++ dp.dcb = nv_encoder->dcb; ++ dp.crtc = nv_crtc->index; ++ dp.auxch = auxch->rd; ++ dp.or = nv_encoder->or; ++ dp.link = !(nv_encoder->dcb->sorconf.link & 1); ++ dp.dpcd = nv_encoder->dp.dpcd; - nv_encoder->dp.link_bw = dpcd[1]; - if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62 && - !nv_encoder->dcb->dpconf.link_bw) - nv_encoder->dp.link_bw = DP_LINK_BW_1_62; -+ NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n", -+ nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); -+ NV_DEBUG_KMS(dev, "encoder: %dx%d\n", -+ nv_encoder->dcb->dpconf.link_nr, -+ nv_encoder->dcb->dpconf.link_bw); ++ /* some sinks toggle hotplug in response to some of the actions ++ * we take during link training (DP_SET_POWER is one), we need ++ * to ignore them for the moment to avoid races. ++ */ ++ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); - nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; - if (nv_encoder->dp.link_nr > nv_encoder->dcb->dpconf.link_nr) -+ if (nv_encoder->dcb->dpconf.link_nr < nv_encoder->dp.link_nr) - nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr; -+ if (nv_encoder->dcb->dpconf.link_bw < nv_encoder->dp.link_bw) -+ nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw; +- nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr; ++ /* enable down-spreading, if possible */ ++ if (dp.table[1] >= 16) { ++ u16 script = ROM16(dp.entry[14]); ++ if (nv_encoder->dp.dpcd[3] & 1) ++ script = ROM16(dp.entry[12]); - nv_encoder->dp.enhanced_frame = (dpcd[2] & DP_ENHANCED_FRAME_CAP); -+ NV_DEBUG_KMS(dev, "maximum: %dx%d\n", -+ nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); ++ nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc); ++ } - return true; - } -@@ -480,105 +684,13 @@ int - nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, - uint8_t *data, int data_nr) - { +- return true; +-} ++ /* execute pre-train script from vbios */ ++ nouveau_bios_run_init_table(dev, ROM16(dp.entry[6]), dp.dcb, dp.crtc); + +-int +-nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, +- uint8_t *data, int data_nr) +-{ - struct drm_device *dev = auxch->dev; - uint32_t tmp, ctrl, stat = 0, data32[4] = {}; - int ret = 0, i, index = auxch->rd; -- ++ /* start off at highest link rate supported by encoder and display */ ++ while (*link_bw > nv_encoder->dp.link_bw) ++ link_bw++; + - NV_DEBUG_KMS(dev, "ch %d cmd %d addr 0x%x len %d\n", index, cmd, addr, data_nr); -- ++ while (link_bw[0]) { ++ /* find minimum required lane count at this link rate */ ++ dp.link_nr = nv_encoder->dp.link_nr; ++ while ((dp.link_nr >> 1) * link_bw[0] > datarate) ++ dp.link_nr >>= 1; + - tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); - nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp | 0x00100000); - tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); @@ -1959,19 +1896,32 @@ index 7beb82a..de5efe7 100644 - ret = -EIO; - goto out; - } -- ++ /* drop link rate to minimum with this lane count */ ++ while ((link_bw[1] * dp.link_nr) > datarate) ++ link_bw++; ++ dp.link_bw = link_bw[0]; ++ ++ /* program selected link configuration */ ++ dp_set_link_config(dev, &dp); + - for (i = 0; i < 3; i++) { - tmp = nv_rd32(dev, NV50_AUXCH_STAT(auxch->rd)); - if (tmp & NV50_AUXCH_STAT_STATE_READY) -- break; ++ /* attempt to train the link at this configuration */ ++ memset(dp.stat, 0x00, sizeof(dp.stat)); ++ if (!dp_link_train_cr(dev, &dp) && ++ !dp_link_train_eq(dev, &dp)) + break; - udelay(100); - } -- + - if (i == 3) { - ret = -EBUSY; - goto out; -- } -- ++ /* retry at lower rate */ ++ link_bw++; + } + - if (!(cmd & 1)) { - memcpy(data32, data, data_nr); - for (i = 0; i < 4; i++) { @@ -1979,13 +1929,17 @@ index 7beb82a..de5efe7 100644 - nv_wr32(dev, NV50_AUXCH_DATA_OUT(index, i), data32[i]); - } - } -- ++ /* finish link training */ ++ dp_set_training_pattern(dev, &dp, DP_TRAINING_PATTERN_DISABLE); + - nv_wr32(dev, NV50_AUXCH_ADDR(index), addr); - ctrl = nv_rd32(dev, NV50_AUXCH_CTRL(index)); - ctrl &= ~(NV50_AUXCH_CTRL_CMD | NV50_AUXCH_CTRL_LEN); - ctrl |= (cmd << NV50_AUXCH_CTRL_CMD_SHIFT); - ctrl |= ((data_nr - 1) << NV50_AUXCH_CTRL_LEN_SHIFT); -- ++ /* execute post-train script from vbios */ ++ nouveau_bios_run_init_table(dev, ROM16(dp.entry[8]), dp.dcb, dp.crtc); + - for (i = 0; i < 16; i++) { - nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x80000000); - nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl); @@ -1997,34 +1951,64 @@ index 7beb82a..de5efe7 100644 - ret = -EBUSY; - goto out; - } -- ++ /* re-enable hotplug detect */ ++ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true); ++ return true; ++} ++ ++bool ++nouveau_dp_detect(struct drm_encoder *encoder) ++{ ++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); ++ struct drm_device *dev = encoder->dev; ++ struct nouveau_i2c_chan *auxch; ++ u8 *dpcd = nv_encoder->dp.dpcd; ++ int ret; + - udelay(400); -- ++ auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); ++ if (!auxch) ++ return false; + - stat = nv_rd32(dev, NV50_AUXCH_STAT(index)); - if ((stat & NV50_AUXCH_STAT_REPLY_AUX) != - NV50_AUXCH_STAT_REPLY_AUX_DEFER) - break; - } -- ++ ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8); ++ if (ret) ++ return false; + - if (i == 16) { - NV_ERROR(dev, "auxch DEFER too many times, bailing\n"); - ret = -EREMOTEIO; - goto out; - } -- ++ nv_encoder->dp.link_bw = 27000 * dpcd[1]; ++ nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; + - if (cmd & 1) { - if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) { - ret = -EREMOTEIO; - goto out; - } -- ++ NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n", ++ nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); ++ NV_DEBUG_KMS(dev, "encoder: %dx%d\n", ++ nv_encoder->dcb->dpconf.link_nr, ++ nv_encoder->dcb->dpconf.link_bw); + - for (i = 0; i < 4; i++) { - data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i)); - NV_DEBUG_KMS(dev, "rd %d: 0x%08x\n", i, data32[i]); - } - memcpy(data, data32, data_nr); - } -- ++ if (nv_encoder->dcb->dpconf.link_nr < nv_encoder->dp.link_nr) ++ nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr; ++ if (nv_encoder->dcb->dpconf.link_bw < nv_encoder->dp.link_bw) ++ nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw; + -out: - tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); - nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp & ~0x00100000); @@ -2033,10 +2017,18 @@ index 7beb82a..de5efe7 100644 - NV_ERROR(dev, "expected bit 24 == 0, got 0x%08x\n", tmp); - ret = -EIO; - } -- ++ NV_DEBUG_KMS(dev, "maximum: %dx%d\n", ++ nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); + - udelay(400); -- ++ return true; ++} + - return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY); ++int ++nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, ++ uint8_t *data, int data_nr) ++{ + return auxch_tx(auxch->dev, auxch->rd, cmd, addr, data, data_nr); } @@ -2165,9 +2157,6 @@ index d7d51de..29837da 100644 u32 shader; - u32 unk05; - u32 unk0a; -- -- u8 voltage; -- u8 fanspeed; + u32 rop; + u32 copy; + u32 daemon; @@ -2177,7 +2166,9 @@ index d7d51de..29837da 100644 + u32 hub01; /* nvc0- */ + u32 hub06; /* nvc0- */ + u32 hub07; /* nvc0- */ -+ + +- u8 voltage; +- u8 fanspeed; + u32 volt_min; /* microvolts */ + u32 volt_max; + u8 fanspeed; @@ -2410,7 +2401,7 @@ index ae69b61..e5d6e3f 100644 - #endif /* __NOUVEAU_ENCODER_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c -index c919cfc..81116cf 100644 +index ae22dfa..2f6daae 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -519,7 +519,7 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) @@ -2848,7 +2839,9 @@ index f9ae2fc..36bec48 100644 - /* XXX: reg_100240? */ - } timing->id = i; -- ++ timing->WR = entry[0]; ++ timing->CL = entry[2]; + - NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i, - timing->reg_100220, timing->reg_100224, - timing->reg_100228, timing->reg_10022c); @@ -2856,9 +2849,6 @@ index f9ae2fc..36bec48 100644 - timing->reg_100230, timing->reg_100234, - timing->reg_100238, timing->reg_10023c); - NV_DEBUG(dev, " 240: %08x\n", timing->reg_100240); -+ timing->WR = entry[0]; -+ timing->CL = entry[2]; -+ + if(dev_priv->card_type <= NV_40) { + nv40_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]); + } else if(dev_priv->card_type == NV_50){ @@ -2993,7 +2983,12 @@ index 1640dec..b29ffb3 100644 - struct nouveau_mm *rmm; - struct nouveau_mm_node *heap; + struct nouveau_mm_node *node; -+ + +- heap = kzalloc(sizeof(*heap), GFP_KERNEL); +- if (!heap) +- return -ENOMEM; +- heap->offset = roundup(offset, block); +- heap->length = rounddown(offset + length, block) - heap->offset; + if (block) { + mutex_init(&mm->mutex); + INIT_LIST_HEAD(&mm->nodes); @@ -3002,20 +2997,12 @@ index 1640dec..b29ffb3 100644 + mm->heap_nodes = 0; + } -- heap = kzalloc(sizeof(*heap), GFP_KERNEL); -- if (!heap) -+ node = kzalloc(sizeof(*node), GFP_KERNEL); -+ if (!node) - return -ENOMEM; -- heap->offset = roundup(offset, block); -- heap->length = rounddown(offset + length, block) - heap->offset; -+ node->offset = roundup(offset, mm->block_size); -+ node->length = rounddown(offset + length, mm->block_size) - node->offset; - - rmm = kzalloc(sizeof(*rmm), GFP_KERNEL); - if (!rmm) { - kfree(heap); -- return -ENOMEM; ++ node = kzalloc(sizeof(*node), GFP_KERNEL); ++ if (!node) + return -ENOMEM; - } - rmm->block_size = block; - mutex_init(&rmm->mutex); @@ -3023,7 +3010,9 @@ index 1640dec..b29ffb3 100644 - INIT_LIST_HEAD(&rmm->free); - list_add(&heap->nl_entry, &rmm->nodes); - list_add(&heap->fl_entry, &rmm->free); -- ++ node->offset = roundup(offset, mm->block_size); ++ node->length = rounddown(offset + length, mm->block_size) - node->offset; + - *prmm = rmm; + list_add_tail(&node->nl_entry, &mm->nodes); + list_add_tail(&node->fl_entry, &mm->free); @@ -3038,15 +3027,14 @@ index 1640dec..b29ffb3 100644 - struct nouveau_mm *rmm = *prmm; struct nouveau_mm_node *node, *heap = - list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry); -- ++ list_first_entry(&mm->nodes, struct nouveau_mm_node, nl_entry); ++ int nodes = 0; + - if (!list_is_singular(&rmm->nodes)) { - printk(KERN_ERR "nouveau_mm not empty at destroy time!\n"); - list_for_each_entry(node, &rmm->nodes, nl_entry) { - printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n", - node->type, node->offset, node->length); -+ list_first_entry(&mm->nodes, struct nouveau_mm_node, nl_entry); -+ int nodes = 0; -+ + list_for_each_entry(node, &mm->nodes, nl_entry) { + if (nodes++ == mm->heap_nodes) { + printk(KERN_ERR "nouveau_mm in use at destroy time!\n"); @@ -3621,7 +3609,7 @@ index f18cdfc..43a96b9 100644 #define NV50_PDISPLAY_USER(i) ((i) * 0x1000 + 0x00640000) diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c -index 2706cb3..b75258a 100644 +index 2706cb3..c8a463b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -12,8 +12,8 @@ struct nouveau_sgdma_be { @@ -3693,7 +3681,7 @@ index 2706cb3..b75258a 100644 } return 0; -@@ -72,25 +57,16 @@ static void +@@ -72,26 +57,20 @@ static void nouveau_sgdma_clear(struct ttm_backend *be) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; @@ -3721,9 +3709,13 @@ index 2706cb3..b75258a 100644 - nvbe->pages = NULL; - nvbe->ttm_alloced = NULL; - nvbe->nr_pages = 0; ++ nvbe->unmap_pages = false; } ++ ++ nvbe->pages = NULL; } + static void diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 10656e4..82478e0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c @@ -5809,9 +5801,8 @@ index d43c46c..8c979b3 100644 -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int i; -- -- NV_DEBUG(dev, "\n"); +- NV_DEBUG(dev, "\n"); + /* upload context program, initialise ctxctl defaults */ + nv_wr32(dev, 0x400324, 0x00000000); + for (i = 0; i < pgraph->ctxprog_size; i++) @@ -5823,7 +5814,7 @@ index d43c46c..8c979b3 100644 + nv_wr32(dev, 0x400724, 0x00000000); + nv_wr32(dev, 0x40032c, 0x00000000); + nv_wr32(dev, 0x400320, 4); /* CTXCTL_CMD = NEWCTXDMA */ -+ + + /* some unknown zcull magic */ switch (dev_priv->chipset & 0xf0) { case 0x50: @@ -6088,14 +6079,13 @@ index e4b2b9e..618c144 100644 - 0x00, 0x00 - }; - const u32 *map = pll_map; -- ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 sctl, sdiv, sclk; + - while (map[1]) { - if (id == map[1]) - return map[0]; - map += 2; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ u32 sctl, sdiv, sclk; -+ + /* refclk for the 0xe8xx plls is a fixed frequency */ + if (clk >= 0x40) { + if (dev_priv->chipset == 0xaf) { @@ -6178,8 +6168,7 @@ index e4b2b9e..618c144 100644 + NV_DEBUG(dev, "no clock for 0x%04x/0x%02x\n", pll, clk); + return 0; + } - -- ret = get_pll_limits(dev, id, &pll); ++ + switch (khz) { + case 27000: + reg->clk = 0x00000100; @@ -6209,7 +6198,8 @@ index e4b2b9e..618c144 100644 + return oclk; + } + } -+ + +- ret = get_pll_limits(dev, id, &pll); + if (!pll) { + NV_ERROR(dev, "bad freq %02x: %d %d\n", clk, khz, sclk); + return -ERANGE; @@ -6325,23 +6315,20 @@ index e4b2b9e..618c144 100644 + int ret; - ret = get_pll_limits(dev, id, &limits); +- if (ret < 0) +- return (ret == -ENOENT) ? NULL : ERR_PTR(ret); + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return ERR_PTR(-ENOMEM); -+ -+ ret = calc_clk(dev, 0x10, 0x4200, perflvl->core, &info->nclk); - if (ret < 0) -- return (ret == -ENOENT) ? NULL : ERR_PTR(ret); -+ goto out; - off = nva3_pm_pll_offset(id); - if (id < 0) - return ERR_PTR(-EINVAL); -+ ret = calc_clk(dev, 0x11, 0x4220, perflvl->shader, &info->sclk); ++ ret = calc_clk(dev, 0x10, 0x4200, perflvl->core, &info->nclk); + if (ret < 0) + goto out; -+ ret = calc_clk(dev, 0x12, 0x4000, perflvl->memory, &info->mclk); ++ ret = calc_clk(dev, 0x11, 0x4220, perflvl->shader, &info->sclk); + if (ret < 0) + goto out; @@ -6353,7 +6340,10 @@ index e4b2b9e..618c144 100644 - pll->src1 = 0x004160 + (off * 4); - pll->ctrl = limits.reg + 0; - pll->coef = limits.reg + 4; -- ++ ret = calc_clk(dev, 0x12, 0x4000, perflvl->memory, &info->mclk); ++ if (ret < 0) ++ goto out; + - /* If target clock is within [-2, 3) MHz of a divisor, we'll - * use that instead of calculating MNP values - */ diff --git a/kernel.spec b/kernel.spec index d233d3f35..b6b0ed53b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2177,6 +2177,9 @@ fi # and build. %changelog +* Mon Nov 28 2011 Ben Skeggs 3.1.3-2 +- nouveau: fix two instances of an oops in ttm clear() (rhbz#751753) + * Sun Nov 26 2011 Chuck Ebbert 3.1.3-1 - Linux 3.1.3 From 81538f6e8405ff521f674308de7d9765fe90dbc7 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 28 Nov 2011 16:26:35 -0500 Subject: [PATCH 154/487] Fix IRQ error preventing load of cciss module (rhbz#754907) --- cciss-fix-irqf-shared.patch | 39 +++++++++++++++++++++++++++++++++++++ hpsa-add-irqf-shared.patch | 34 ++++++++++++++++++++++++++++++++ kernel.spec | 13 ++++++++++++- 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 cciss-fix-irqf-shared.patch create mode 100644 hpsa-add-irqf-shared.patch diff --git a/cciss-fix-irqf-shared.patch b/cciss-fix-irqf-shared.patch new file mode 100644 index 000000000..d6de3d7c2 --- /dev/null +++ b/cciss-fix-irqf-shared.patch @@ -0,0 +1,39 @@ +cciss: Add IRQF_SHARED back in for the non-MSI(X) interrupt handler + +From: Stephen M. Cameron + +[ 3.1.x backport ] + +IRQF_SHARED is required for older controllers that don't support MSI(X) +and which may end up sharing an interrupt. + +Also remove deprecated IRQF_DISABLED. + +Signed-off-by: Stephen M. Cameron +--- + drivers/block/cciss.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +RHBZ 754907 +diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c +index 8004ac3..6f22ed0 100644 +--- a/drivers/block/cciss.c ++++ b/drivers/block/cciss.c +@@ -4880,7 +4880,7 @@ static int cciss_request_irq(ctlr_info_t *h, + { + if (h->msix_vector || h->msi_vector) { + if (!request_irq(h->intr[PERF_MODE_INT], msixhandler, +- IRQF_DISABLED, h->devname, h)) ++ 0, h->devname, h)) + return 0; + dev_err(&h->pdev->dev, "Unable to get msi irq %d" + " for %s\n", h->intr[h->intr_mode], +@@ -4889,7 +4889,7 @@ static int cciss_request_irq(ctlr_info_t *h, + } + + if (!request_irq(h->intr[PERF_MODE_INT], intxhandler, +- IRQF_DISABLED, h->devname, h)) ++ IRQF_SHARED, h->devname, h)) + return 0; + dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n", + h->intr[h->intr_mode], h->devname); diff --git a/hpsa-add-irqf-shared.patch b/hpsa-add-irqf-shared.patch new file mode 100644 index 000000000..d29e2353e --- /dev/null +++ b/hpsa-add-irqf-shared.patch @@ -0,0 +1,34 @@ +hpsa: Add IRQF_SHARED back in for the non-MSI(X) interrupt handler + +From: Stephen M. Cameron + +IRQF_SHARED is required for older controllers that don't support MSI(X) +and which may end up sharing an interrupt. All the controllers hpsa +normally supports have MSI(X) capability, but older controllers may be +encountered via the hpsa_allow_any=1 module parameter. + +Also remove deprecated IRQF_DISABLED. + +Signed-off-by: Stephen M. Cameron +--- + drivers/scsi/hpsa.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +RHBZ 754907 +diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c +index 865d452..594ce83 100644 +--- a/drivers/scsi/hpsa.c ++++ b/drivers/scsi/hpsa.c +@@ -4072,10 +4072,10 @@ static int hpsa_request_irq(struct ctlr_info *h, + + if (h->msix_vector || h->msi_vector) + rc = request_irq(h->intr[h->intr_mode], msixhandler, +- IRQF_DISABLED, h->devname, h); ++ 0, h->devname, h); + else + rc = request_irq(h->intr[h->intr_mode], intxhandler, +- IRQF_DISABLED, h->devname, h); ++ IRQF_SHARED, h->devname, h); + if (rc) { + dev_err(&h->pdev->dev, "unable to get irq %d for %s\n", + h->intr[h->intr_mode], h->devname); diff --git a/kernel.spec b/kernel.spec index b6b0ed53b..662adb116 100644 --- a/kernel.spec +++ b/kernel.spec @@ -789,6 +789,10 @@ Patch21080: sysfs-msi-irq-per-device.patch Patch21090: brcm80211.patch Patch21091: bcma-brcmsmac-compat.patch +# rhbz 754907 +Patch21100: cciss-fix-irqf-shared.patch +Patch21101: hpsa-add-irqf-shared.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1446,6 +1450,10 @@ ApplyPatch brcm80211.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch +# rhbz 754907 +ApplyPatch cciss-fix-irqf-shared.patch +ApplyPatch hpsa-add-irqf-shared.patch + # END OF PATCH APPLICATIONS %endif @@ -2177,10 +2185,13 @@ fi # and build. %changelog +* Mon Nov 28 2011 Chuck Ebbert +- Fix IRQ error preventing load of cciss module (rhbz#754907) + * Mon Nov 28 2011 Ben Skeggs 3.1.3-2 - nouveau: fix two instances of an oops in ttm clear() (rhbz#751753) -* Sun Nov 26 2011 Chuck Ebbert 3.1.3-1 +* Sun Nov 27 2011 Chuck Ebbert 3.1.3-1 - Linux 3.1.3 * Wed Nov 23 2011 Chuck Ebbert 3.1.3-0.rc1.1 From 6d28fee6c9990b748e07d4260a2e608bb89d5f28 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 28 Nov 2011 20:24:35 -0500 Subject: [PATCH 155/487] Linux 3.1.4 --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 662adb116..a1f252dce 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 3 +%define stable_update 4 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2185,6 +2185,9 @@ fi # and build. %changelog +* Mon Nov 28 2011 Chuck Ebbert 3.1.4-1 +- Linux 3.1.4 + * Mon Nov 28 2011 Chuck Ebbert - Fix IRQ error preventing load of cciss module (rhbz#754907) diff --git a/sources b/sources index f834ec4a4..b8c0593a0 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 6693d8c42055f83f5701d9b65d47208a compat-wireless-3.2-rc1-1.tar.bz2 -1efc18287f740528226af94a28349e11 patch-3.1.3.bz2 +b8b14bdfbf76cfef8e042e7d1a385fca patch-3.1.4.bz2 From b151c2bd4c7f9b0e61aecb8678d0e3a64dc36f02 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 29 Nov 2011 10:29:39 -0500 Subject: [PATCH 156/487] Add patch to fix deadlock in rtlwifi (rhbz #755154) --- kernel.spec | 11 +- rtlwifi-fix-lps_lock-deadlock.patch | 224 ++++++++++++++++++++++++++++ 2 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 rtlwifi-fix-lps_lock-deadlock.patch diff --git a/kernel.spec b/kernel.spec index a1f252dce..ad55589de 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -793,6 +793,9 @@ Patch21091: bcma-brcmsmac-compat.patch Patch21100: cciss-fix-irqf-shared.patch Patch21101: hpsa-add-irqf-shared.patch +#rhbz 755154 +Patch21200: rtlwifi-fix-lps_lock-deadlock.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1454,6 +1457,9 @@ ApplyPatch bcma-brcmsmac-compat.patch ApplyPatch cciss-fix-irqf-shared.patch ApplyPatch hpsa-add-irqf-shared.patch +#rhbz 755154 +ApplyPatch rtlwifi-fix-lps_lock-deadlock.patch + # END OF PATCH APPLICATIONS %endif @@ -2185,6 +2191,9 @@ fi # and build. %changelog +* Tue Nov 29 2011 Josh Boyer +- Add patch to fix deadlock in rtlwifi (rhbz #755154) + * Mon Nov 28 2011 Chuck Ebbert 3.1.4-1 - Linux 3.1.4 diff --git a/rtlwifi-fix-lps_lock-deadlock.patch b/rtlwifi-fix-lps_lock-deadlock.patch new file mode 100644 index 000000000..4e31ee9b7 --- /dev/null +++ b/rtlwifi-fix-lps_lock-deadlock.patch @@ -0,0 +1,224 @@ +Path: news.gmane.org!not-for-mail +From: Stanislaw Gruszka +Newsgroups: gmane.linux.kernel.wireless.general +Subject: [PATCH v2] rtlwifi: fix lps_lock deadlock +Date: Mon, 28 Nov 2011 10:33:40 +0100 +Lines: 169 +Approved: news@gmane.org +Message-ID: <20111128093339.GC2372@redhat.com> +References: <1322219327-23148-1-git-send-email-sgruszka@redhat.com> + <4ECFD1BF.4070503@lwfinger.net> + <20111128092308.GB2372@redhat.com> +NNTP-Posting-Host: lo.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +X-Trace: dough.gmane.org 1322472712 10173 80.91.229.12 (28 Nov 2011 09:31:52 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Mon, 28 Nov 2011 09:31:52 +0000 (UTC) +Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, + Chaoming Li +To: Larry Finger , + "John W. Linville" +Original-X-From: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Mon Nov 28 10:31:45 2011 +Return-path: +Envelope-to: glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1RUxYu-0002H1-AY + for glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Mon, 28 Nov 2011 10:31:44 +0100 +Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand + id S1751698Ab1K1Jbm (ORCPT + ); + Mon, 28 Nov 2011 04:31:42 -0500 +Original-Received: from mx1.redhat.com ([209.132.183.28]:62078 "EHLO mx1.redhat.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1751434Ab1K1Jbl (ORCPT ); + Mon, 28 Nov 2011 04:31:41 -0500 +Original-Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id pAS9VSak003418 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Mon, 28 Nov 2011 04:31:28 -0500 +Original-Received: from localhost (vpn1-4-194.ams2.redhat.com [10.36.4.194]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id pAS9VQNG013260; + Mon, 28 Nov 2011 04:31:27 -0500 +Content-Disposition: inline +In-Reply-To: <20111128092308.GB2372-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> +User-Agent: Mutt/1.5.20 (2009-12-10) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Original-Sender: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Xref: news.gmane.org gmane.linux.kernel.wireless.general:81657 +Archived-At: + +rtl_lps_leave can be called from interrupt context, so we have to +disable interrupts when taking lps_lock. + +Below is full lockdep info about deadlock: + +[ 93.815269] ================================= +[ 93.815390] [ INFO: inconsistent lock state ] +[ 93.815472] 2.6.41.1-3.offch.fc15.x86_64.debug #1 +[ 93.815556] --------------------------------- +[ 93.815635] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. +[ 93.815743] swapper/0 [HC0[0]:SC1[1]:HE1:SE0] takes: +[ 93.815832] (&(&rtlpriv->locks.lps_lock)->rlock){+.?...}, at: [] rtl_lps_leave+0x26/0x103 [rtlwifi] +[ 93.815947] {SOFTIRQ-ON-W} state was registered at: +[ 93.815947] [] __lock_acquire+0x369/0xd0c +[ 93.815947] [] lock_acquire+0xf3/0x13e +[ 93.815947] [] _raw_spin_lock+0x45/0x79 +[ 93.815947] [] rtl_swlps_rf_awake+0x5a/0x76 [rtlwifi] +[ 93.815947] [] rtl_op_config+0x12a/0x32a [rtlwifi] +[ 93.815947] [] ieee80211_hw_config+0x124/0x129 [mac80211] +[ 93.815947] [] ieee80211_dynamic_ps_disable_work+0x32/0x47 [mac80211] +[ 93.815947] [] process_one_work+0x205/0x3e7 +[ 93.815947] [] worker_thread+0xda/0x15d +[ 93.815947] [] kthread+0xa8/0xb0 +[ 93.815947] [] kernel_thread_helper+0x4/0x10 +[ 93.815947] irq event stamp: 547822 +[ 93.815947] hardirqs last enabled at (547822): [] _raw_spin_unlock_irqrestore+0x45/0x61 +[ 93.815947] hardirqs last disabled at (547821): [] _raw_spin_lock_irqsave+0x22/0x8e +[ 93.815947] softirqs last enabled at (547790): [] _local_bh_enable+0x13/0x15 +[ 93.815947] softirqs last disabled at (547791): [] call_softirq+0x1c/0x30 +[ 93.815947] +[ 93.815947] other info that might help us debug this: +[ 93.815947] Possible unsafe locking scenario: +[ 93.815947] +[ 93.815947] CPU0 +[ 93.815947] ---- +[ 93.815947] lock(&(&rtlpriv->locks.lps_lock)->rlock); +[ 93.815947] +[ 93.815947] lock(&(&rtlpriv->locks.lps_lock)->rlock); +[ 93.815947] +[ 93.815947] *** DEADLOCK *** +[ 93.815947] +[ 93.815947] no locks held by swapper/0. +[ 93.815947] +[ 93.815947] stack backtrace: +[ 93.815947] Pid: 0, comm: swapper Not tainted 2.6.41.1-3.offch.fc15.x86_64.debug #1 +[ 93.815947] Call Trace: +[ 93.815947] [] print_usage_bug+0x1e7/0x1f8 +[ 93.815947] [] ? save_stack_trace+0x2c/0x49 +[ 93.815947] [] ? print_irq_inversion_bug.part.18+0x1a0/0x1a0 +[ 93.815947] [] mark_lock+0x106/0x220 +[ 93.815947] [] __lock_acquire+0x2f5/0xd0c +[ 93.815947] [] ? native_sched_clock+0x34/0x36 +[ 93.830125] [] ? sched_clock+0x9/0xd +[ 93.830125] [] ? sched_clock_local+0x12/0x75 +[ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] +[ 93.830125] [] lock_acquire+0xf3/0x13e +[ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] +[ 93.830125] [] _raw_spin_lock+0x45/0x79 +[ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] +[ 93.830125] [] ? skb_dequeue+0x62/0x6d +[ 93.830125] [] rtl_lps_leave+0x26/0x103 [rtlwifi] +[ 93.830125] [] _rtl_pci_ips_leave_tasklet+0xe/0x10 [rtlwifi] +[ 93.830125] [] tasklet_action+0x8d/0xee +[ 93.830125] [] __do_softirq+0x112/0x25a +[ 93.830125] [] call_softirq+0x1c/0x30 +[ 93.830125] [] do_softirq+0x4b/0xa1 +[ 93.830125] [] irq_exit+0x5d/0xcf +[ 93.830125] [] do_IRQ+0x8e/0xa5 +[ 93.830125] [] common_interrupt+0x73/0x73 +[ 93.830125] [] ? trace_hardirqs_off+0xd/0xf +[ 93.830125] [] ? intel_idle+0xe5/0x10c +[ 93.830125] [] ? intel_idle+0xe1/0x10c +[ 93.830125] [] cpuidle_idle_call+0x11c/0x1fe +[ 93.830125] [] cpu_idle+0xab/0x101 +[ 93.830125] [] rest_init+0xd7/0xde +[ 93.830125] [] ? csum_partial_copy_generic+0x16c/0x16c +[ 93.830125] [] start_kernel+0x3dd/0x3ea +[ 93.830125] [] x86_64_start_reservations+0xaf/0xb3 +[ 93.830125] [] ? early_idt_handlers+0x140/0x140 +[ 93.830125] [] x86_64_start_kernel+0x102/0x111 + +Resolves: +https://bugzilla.redhat.com/show_bug.cgi?id=755154 + +Reported-by: vjain02-9geRo0GdX4mblYp+tMVdN4dd74u8MsAO@public.gmane.org +Reported-and-tested-by: Oliver Paukstadt +Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Acked-by: Larry Finger +Signed-off-by: Stanislaw Gruszka +--- +v1 -> v2: add bug report reference + + drivers/net/wireless/rtlwifi/ps.c | 17 +++++++++-------- + 1 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c +index db52628..55c8e50 100644 +--- a/drivers/net/wireless/rtlwifi/ps.c ++++ b/drivers/net/wireless/rtlwifi/ps.c +@@ -395,7 +395,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) + if (mac->link_state != MAC80211_LINKED) + return; + +- spin_lock(&rtlpriv->locks.lps_lock); ++ spin_lock_irq(&rtlpriv->locks.lps_lock); + + /* Idle for a while if we connect to AP a while ago. */ + if (mac->cnt_after_linked >= 2) { +@@ -407,7 +407,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) + } + } + +- spin_unlock(&rtlpriv->locks.lps_lock); ++ spin_unlock_irq(&rtlpriv->locks.lps_lock); + } + + /*Leave the leisure power save mode.*/ +@@ -416,8 +416,9 @@ void rtl_lps_leave(struct ieee80211_hw *hw) + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); ++ unsigned long flags; + +- spin_lock(&rtlpriv->locks.lps_lock); ++ spin_lock_irqsave(&rtlpriv->locks.lps_lock, flags); + + if (ppsc->fwctrl_lps) { + if (ppsc->dot11_psmode != EACTIVE) { +@@ -438,7 +439,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw) + rtl_lps_set_psmode(hw, EACTIVE); + } + } +- spin_unlock(&rtlpriv->locks.lps_lock); ++ spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flags); + } + + /* For sw LPS*/ +@@ -539,9 +540,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw) + RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); + } + +- spin_lock(&rtlpriv->locks.lps_lock); ++ spin_lock_irq(&rtlpriv->locks.lps_lock); + rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS); +- spin_unlock(&rtlpriv->locks.lps_lock); ++ spin_unlock_irq(&rtlpriv->locks.lps_lock); + } + + void rtl_swlps_rfon_wq_callback(void *data) +@@ -574,9 +575,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw) + if (rtlpriv->link_info.busytraffic) + return; + +- spin_lock(&rtlpriv->locks.lps_lock); ++ spin_lock_irq(&rtlpriv->locks.lps_lock); + rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS); +- spin_unlock(&rtlpriv->locks.lps_lock); ++ spin_unlock_irq(&rtlpriv->locks.lps_lock); + + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && + !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { +-- +1.7.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + From da334a5ce324cb942e014c8d11b55dc2ad8196ff Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 29 Nov 2011 11:19:12 -0500 Subject: [PATCH 157/487] Drop drm-intel-make-lvds-work.patch (rhbz #731296) Discussed this with mjg59 and ajax. This fix was supposed to go upstream, but never actually made it. Since it's breaking xrandr, we're dropping it. --- drm-intel-make-lvds-work.patch | 18 ------------------ kernel.spec | 4 +--- 2 files changed, 1 insertion(+), 21 deletions(-) delete mode 100644 drm-intel-make-lvds-work.patch diff --git a/drm-intel-make-lvds-work.patch b/drm-intel-make-lvds-work.patch deleted file mode 100644 index 89f4e2d48..000000000 --- a/drm-intel-make-lvds-work.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -5821,7 +5821,6 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, - struct intel_load_detect_pipe *old) - { - struct drm_encoder *encoder = &intel_encoder->base; -- struct drm_device *dev = encoder->dev; - struct drm_crtc *crtc = encoder->crtc; - struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; - struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -@@ -5832,7 +5831,6 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, - - if (old->load_detect_temp) { - connector->encoder = NULL; -- drm_helper_disable_unused_functions(dev); - - if (old->release_fb) - old->release_fb->funcs->destroy(old->release_fb); diff --git a/kernel.spec b/kernel.spec index ad55589de..4fe3e41dc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -702,8 +702,6 @@ Patch1500: fix_xen_guest_on_old_EC2.patch Patch1810: drm-nouveau-updates.patch # intel drm is all merged upstream Patch1824: drm-intel-next.patch -# make sure the lvds comes back on lid open -Patch1825: drm-intel-make-lvds-work.patch # hush the i915 fbc noise Patch1826: drm-i915-fbc-stfu.patch # rhbz#729882, https://bugs.freedesktop.org/attachment.cgi?id=49069 @@ -1379,7 +1377,6 @@ ApplyOptionalPatch drm-nouveau-updates.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch -ApplyPatch drm-intel-make-lvds-work.patch ApplyPatch drm-i915-fbc-stfu.patch ApplyPatch drm-i915-sdvo-lvds-is-digital.patch @@ -2193,6 +2190,7 @@ fi %changelog * Tue Nov 29 2011 Josh Boyer - Add patch to fix deadlock in rtlwifi (rhbz #755154) +- Drop drm-intel-make-lvds-work.patch (rhbz #731296) * Mon Nov 28 2011 Chuck Ebbert 3.1.4-1 - Linux 3.1.4 From a6a5351a6faf6ad95d35ccccdc074ba943800a2c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 30 Nov 2011 10:32:45 -0500 Subject: [PATCH 158/487] Include commit 3940d6185 from JJ Ding in elantech.patch --- elantech.patch | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 5 +++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/elantech.patch b/elantech.patch index 255efd2b6..fa7c67fec 100644 --- a/elantech.patch +++ b/elantech.patch @@ -2114,3 +2114,67 @@ index c2d91eb..25290b3 100644 -- 1.7.6.4 +From 3940d6185a982a970ff562e085caccbdd62f40bb Mon Sep 17 00:00:00 2001 +From: JJ Ding +Date: Tue, 8 Nov 2011 22:13:14 -0800 +Subject: [PATCH] Input: elantech - adjust hw_version detection logic +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch fixes some v3 hardware (fw_version: 0x150500) wrongly detected +as v2 hardware. + +Reported-by: Marc Dietrich +Signed-off-by: JJ Ding +Tested-By: Marc Dietrich +Acked-by: Éric Piel +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/elantech.c | 26 ++++++++++++++++++-------- + 1 files changed, 18 insertions(+), 8 deletions(-) + +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 09b93b1..e2a9867 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -1210,18 +1210,28 @@ static int elantech_reconnect(struct psmouse *psmouse) + */ + static int elantech_set_properties(struct elantech_data *etd) + { ++ /* This represents the version of IC body. */ + int ver = (etd->fw_version & 0x0f0000) >> 16; + ++ /* Early version of Elan touchpads doesn't obey the rule. */ + if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) + etd->hw_version = 1; +- else if (etd->fw_version < 0x150600) +- etd->hw_version = 2; +- else if (ver == 5) +- etd->hw_version = 3; +- else if (ver == 6) +- etd->hw_version = 4; +- else +- return -1; ++ else { ++ switch (ver) { ++ case 2: ++ case 4: ++ etd->hw_version = 2; ++ break; ++ case 5: ++ etd->hw_version = 3; ++ break; ++ case 6: ++ etd->hw_version = 4; ++ break; ++ default: ++ return -1; ++ } ++ } + + /* + * Turn on packet checking by default. +-- +1.7.7.3 + diff --git a/kernel.spec b/kernel.spec index 4fe3e41dc..d60e4692a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2188,6 +2188,9 @@ fi # and build. %changelog +* Wed Nov 30 2011 Josh Boyer +- Include commit 3940d6185 from JJ Ding in elantech.patch + * Tue Nov 29 2011 Josh Boyer - Add patch to fix deadlock in rtlwifi (rhbz #755154) - Drop drm-intel-make-lvds-work.patch (rhbz #731296) From 67de50b811ecec877c8ca1a9309f0567141b9269 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 1 Dec 2011 09:10:14 -0500 Subject: [PATCH 159/487] Apply patch to revert mac80211 scan optimizations (rhbz #731365) --- kernel.spec | 11 +- mac80211_offchannel_rework_revert.patch | 594 ++++++++++++++++++++++++ 2 files changed, 604 insertions(+), 1 deletion(-) create mode 100644 mac80211_offchannel_rework_revert.patch diff --git a/kernel.spec b/kernel.spec index d60e4692a..ddef92524 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -794,6 +794,9 @@ Patch21101: hpsa-add-irqf-shared.patch #rhbz 755154 Patch21200: rtlwifi-fix-lps_lock-deadlock.patch +#rhbz 731365 +Patch21220: mac80211_offchannel_rework_revert.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1457,6 +1460,9 @@ ApplyPatch hpsa-add-irqf-shared.patch #rhbz 755154 ApplyPatch rtlwifi-fix-lps_lock-deadlock.patch +#rhbz 731365 +ApplyPatch mac80211_offchannel_rework_revert.patch + # END OF PATCH APPLICATIONS %endif @@ -2188,6 +2194,9 @@ fi # and build. %changelog +* Thu Dec 01 2011 Josh Boyer +- Apply patch to revert mac80211 scan optimizations (rhbz #731365) + * Wed Nov 30 2011 Josh Boyer - Include commit 3940d6185 from JJ Ding in elantech.patch diff --git a/mac80211_offchannel_rework_revert.patch b/mac80211_offchannel_rework_revert.patch new file mode 100644 index 000000000..859799714 --- /dev/null +++ b/mac80211_offchannel_rework_revert.patch @@ -0,0 +1,594 @@ +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 9fab144..4f8cf7f 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -694,6 +694,8 @@ struct tpt_led_trigger { + * well be on the operating channel + * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to + * determine if we are on the operating channel or not ++ * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning, ++ * gets only set in conjunction with SCAN_SW_SCANNING + * @SCAN_COMPLETED: Set for our scan work function when the driver reported + * that the scan completed. + * @SCAN_ABORTED: Set for our scan work function when the driver reported +@@ -702,6 +704,7 @@ struct tpt_led_trigger { + enum { + SCAN_SW_SCANNING, + SCAN_HW_SCANNING, ++ SCAN_OFF_CHANNEL, + SCAN_COMPLETED, + SCAN_ABORTED, + }; +@@ -1197,14 +1200,10 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); + void ieee80211_sched_scan_stopped_work(struct work_struct *work); + + /* off-channel helpers */ +-bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local); +-void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, +- bool tell_ap); +-void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, +- bool offchannel_ps_enable); ++void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local); ++void ieee80211_offchannel_stop_station(struct ieee80211_local *local); + void ieee80211_offchannel_return(struct ieee80211_local *local, +- bool enable_beaconing, +- bool offchannel_ps_disable); ++ bool enable_beaconing); + void ieee80211_hw_roc_setup(struct ieee80211_local *local); + + /* interface handling */ +diff --git a/net/mac80211/main.c b/net/mac80211/main.c +index acb4423..2d607e5 100644 +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -92,47 +92,6 @@ static void ieee80211_reconfig_filter(struct work_struct *work) + ieee80211_configure_filter(local); + } + +-/* +- * Returns true if we are logically configured to be on +- * the operating channel AND the hardware-conf is currently +- * configured on the operating channel. Compares channel-type +- * as well. +- */ +-bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local) +-{ +- struct ieee80211_channel *chan, *scan_chan; +- enum nl80211_channel_type channel_type; +- +- /* This logic needs to match logic in ieee80211_hw_config */ +- if (local->scan_channel) { +- chan = local->scan_channel; +- /* If scanning on oper channel, use whatever channel-type +- * is currently in use. +- */ +- if (chan == local->oper_channel) +- channel_type = local->_oper_channel_type; +- else +- channel_type = NL80211_CHAN_NO_HT; +- } else if (local->tmp_channel) { +- chan = scan_chan = local->tmp_channel; +- channel_type = local->tmp_channel_type; +- } else { +- chan = local->oper_channel; +- channel_type = local->_oper_channel_type; +- } +- +- if (chan != local->oper_channel || +- channel_type != local->_oper_channel_type) +- return false; +- +- /* Check current hardware-config against oper_channel. */ +- if ((local->oper_channel != local->hw.conf.channel) || +- (local->_oper_channel_type != local->hw.conf.channel_type)) +- return false; +- +- return true; +-} +- + int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) + { + struct ieee80211_channel *chan, *scan_chan; +@@ -145,9 +104,6 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) + + scan_chan = local->scan_channel; + +- /* If this off-channel logic ever changes, ieee80211_on_oper_channel +- * may need to change as well. +- */ + offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; + if (scan_chan) { + chan = scan_chan; +@@ -158,19 +114,17 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) + channel_type = local->_oper_channel_type; + else + channel_type = NL80211_CHAN_NO_HT; +- } else if (local->tmp_channel) { ++ local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; ++ } else if (local->tmp_channel && ++ local->oper_channel != local->tmp_channel) { + chan = scan_chan = local->tmp_channel; + channel_type = local->tmp_channel_type; ++ local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; + } else { + chan = local->oper_channel; + channel_type = local->_oper_channel_type; +- } +- +- if (chan != local->oper_channel || +- channel_type != local->_oper_channel_type) +- local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; +- else + local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; ++ } + + offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; + +@@ -279,7 +233,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, + + if (changed & BSS_CHANGED_BEACON_ENABLED) { + if (local->quiescing || !ieee80211_sdata_running(sdata) || +- test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) { ++ test_bit(SCAN_SW_SCANNING, &local->scanning)) { + sdata->vif.bss_conf.enable_beacon = false; + } else { + /* +diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c +index 13427b1..b4e5267 100644 +--- a/net/mac80211/offchannel.c ++++ b/net/mac80211/offchannel.c +@@ -17,14 +17,10 @@ + #include "driver-trace.h" + + /* +- * Tell our hardware to disable PS. +- * Optionally inform AP that we will go to sleep so that it will buffer +- * the frames while we are doing off-channel work. This is optional +- * because we *may* be doing work on-operating channel, and want our +- * hardware unconditionally awake, but still let the AP send us normal frames. ++ * inform AP that we will go to sleep so that it will buffer the frames ++ * while we scan + */ +-static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata, +- bool tell_ap) ++static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) + { + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; +@@ -45,8 +41,8 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata, + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + } + +- if (tell_ap && (!local->offchannel_ps_enabled || +- !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))) ++ if (!(local->offchannel_ps_enabled) || ++ !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) + /* + * If power save was enabled, no need to send a nullfunc + * frame because AP knows that we are sleeping. But if the +@@ -81,9 +77,6 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) + * we are sleeping, let's just enable power save mode in + * hardware. + */ +- /* TODO: Only set hardware if CONF_PS changed? +- * TODO: Should we set offchannel_ps_enabled to false? +- */ + local->hw.conf.flags |= IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + } else if (local->hw.conf.dynamic_ps_timeout > 0) { +@@ -102,61 +95,63 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) + ieee80211_sta_reset_conn_monitor(sdata); + } + +-void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, +- bool offchannel_ps_enable) ++void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) + { + struct ieee80211_sub_if_data *sdata; + +- /* +- * notify the AP about us leaving the channel and stop all +- * STA interfaces. +- */ + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata, &local->interfaces, list) { + if (!ieee80211_sdata_running(sdata)) + continue; + +- if (sdata->vif.type != NL80211_IFTYPE_MONITOR) +- set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); +- +- /* Check to see if we should disable beaconing. */ ++ /* disable beaconing */ + if (sdata->vif.type == NL80211_IFTYPE_AP || + sdata->vif.type == NL80211_IFTYPE_ADHOC || + sdata->vif.type == NL80211_IFTYPE_MESH_POINT) + ieee80211_bss_info_change_notify( + sdata, BSS_CHANGED_BEACON_ENABLED); + +- if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { ++ /* ++ * only handle non-STA interfaces here, STA interfaces ++ * are handled in ieee80211_offchannel_stop_station(), ++ * e.g., from the background scan state machine. ++ * ++ * In addition, do not stop monitor interface to allow it to be ++ * used from user space controlled off-channel operations. ++ */ ++ if (sdata->vif.type != NL80211_IFTYPE_STATION && ++ sdata->vif.type != NL80211_IFTYPE_MONITOR) { ++ set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); + netif_tx_stop_all_queues(sdata->dev); +- if (offchannel_ps_enable && +- (sdata->vif.type == NL80211_IFTYPE_STATION) && +- sdata->u.mgd.associated) +- ieee80211_offchannel_ps_enable(sdata, true); + } + } + mutex_unlock(&local->iflist_mtx); + } + +-void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, +- bool tell_ap) ++void ieee80211_offchannel_stop_station(struct ieee80211_local *local) + { + struct ieee80211_sub_if_data *sdata; + ++ /* ++ * notify the AP about us leaving the channel and stop all STA interfaces ++ */ + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata, &local->interfaces, list) { + if (!ieee80211_sdata_running(sdata)) + continue; + +- if (sdata->vif.type == NL80211_IFTYPE_STATION && +- sdata->u.mgd.associated) +- ieee80211_offchannel_ps_enable(sdata, tell_ap); ++ if (sdata->vif.type == NL80211_IFTYPE_STATION) { ++ set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); ++ netif_tx_stop_all_queues(sdata->dev); ++ if (sdata->u.mgd.associated) ++ ieee80211_offchannel_ps_enable(sdata); ++ } + } + mutex_unlock(&local->iflist_mtx); + } + + void ieee80211_offchannel_return(struct ieee80211_local *local, +- bool enable_beaconing, +- bool offchannel_ps_disable) ++ bool enable_beaconing) + { + struct ieee80211_sub_if_data *sdata; + +@@ -166,8 +161,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, + continue; + + /* Tell AP we're back */ +- if (offchannel_ps_disable && +- sdata->vif.type == NL80211_IFTYPE_STATION) { ++ if (sdata->vif.type == NL80211_IFTYPE_STATION) { + if (sdata->u.mgd.associated) + ieee80211_offchannel_ps_disable(sdata); + } +@@ -187,7 +181,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, + netif_tx_wake_all_queues(sdata->dev); + } + +- /* Check to see if we should re-enable beaconing */ ++ /* re-enable beaconing */ + if (enable_beaconing && + (sdata->vif.type == NL80211_IFTYPE_AP || + sdata->vif.type == NL80211_IFTYPE_ADHOC || +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index fe2c2a7..b46880e 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -417,10 +417,16 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) + return RX_CONTINUE; + + if (test_bit(SCAN_HW_SCANNING, &local->scanning) || +- test_bit(SCAN_SW_SCANNING, &local->scanning) || + local->sched_scanning) + return ieee80211_scan_rx(rx->sdata, skb); + ++ if (test_bit(SCAN_SW_SCANNING, &local->scanning)) { ++ /* drop all the other packets during a software scan anyway */ ++ if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED) ++ dev_kfree_skb(skb); ++ return RX_QUEUED; ++ } ++ + /* scanning finished during invoking of handlers */ + I802_DEBUG_INC(local->rx_handlers_drop_passive_scan); + return RX_DROP_UNUSABLE; +@@ -2771,7 +2777,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, + local->dot11ReceivedFragmentCount++; + + if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || +- test_bit(SCAN_SW_SCANNING, &local->scanning))) ++ test_bit(SCAN_OFF_CHANNEL, &local->scanning))) + status->rx_flags |= IEEE80211_RX_IN_SCAN; + + if (ieee80211_is_mgmt(fc)) +diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c +index 6f09eca..2ba4977 100644 +--- a/net/mac80211/scan.c ++++ b/net/mac80211/scan.c +@@ -212,14 +212,6 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) + if (bss) + ieee80211_rx_bss_put(sdata->local, bss); + +- /* If we are on-operating-channel, and this packet is for the +- * current channel, pass the pkt on up the stack so that +- * the rest of the stack can make use of it. +- */ +- if (ieee80211_cfg_on_oper_channel(sdata->local) +- && (channel == sdata->local->oper_channel)) +- return RX_CONTINUE; +- + dev_kfree_skb(skb); + return RX_QUEUED; + } +@@ -262,8 +254,6 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, + bool was_hw_scan) + { + struct ieee80211_local *local = hw_to_local(hw); +- bool on_oper_chan; +- bool enable_beacons = false; + + lockdep_assert_held(&local->mtx); + +@@ -296,25 +286,11 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, + local->scanning = 0; + local->scan_channel = NULL; + +- on_oper_chan = ieee80211_cfg_on_oper_channel(local); +- +- if (was_hw_scan || !on_oper_chan) +- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); +- else +- /* Set power back to normal operating levels. */ +- ieee80211_hw_config(local, 0); +- ++ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); + if (!was_hw_scan) { +- bool on_oper_chan2; + ieee80211_configure_filter(local); + drv_sw_scan_complete(local); +- on_oper_chan2 = ieee80211_cfg_on_oper_channel(local); +- /* We should always be on-channel at this point. */ +- WARN_ON(!on_oper_chan2); +- if (on_oper_chan2 && (on_oper_chan != on_oper_chan2)) +- enable_beacons = true; +- +- ieee80211_offchannel_return(local, enable_beacons, true); ++ ieee80211_offchannel_return(local, true); + } + + ieee80211_recalc_idle(local); +@@ -355,15 +331,13 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) + */ + drv_sw_scan_start(local); + ++ ieee80211_offchannel_stop_beaconing(local); ++ + local->leave_oper_channel_time = 0; + local->next_scan_state = SCAN_DECISION; + local->scan_channel_idx = 0; + +- /* We always want to use off-channel PS, even if we +- * are not really leaving oper-channel. Don't +- * tell the AP though, as long as we are on-channel. +- */ +- ieee80211_offchannel_enable_all_ps(local, false); ++ drv_flush(local, false); + + ieee80211_configure_filter(local); + +@@ -506,20 +480,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, + } + mutex_unlock(&local->iflist_mtx); + +- next_chan = local->scan_req->channels[local->scan_channel_idx]; +- +- if (ieee80211_cfg_on_oper_channel(local)) { +- /* We're currently on operating channel. */ +- if (next_chan == local->oper_channel) +- /* We don't need to move off of operating channel. */ +- local->next_scan_state = SCAN_SET_CHANNEL; +- else +- /* +- * We do need to leave operating channel, as next +- * scan is somewhere else. +- */ +- local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; +- } else { ++ if (local->scan_channel) { + /* + * we're currently scanning a different channel, let's + * see if we can scan another channel without interfering +@@ -535,6 +496,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, + * + * Otherwise switch back to the operating channel. + */ ++ next_chan = local->scan_req->channels[local->scan_channel_idx]; + + bad_latency = time_after(jiffies + + ieee80211_scan_get_channel_time(next_chan), +@@ -552,6 +514,12 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, + local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; + else + local->next_scan_state = SCAN_SET_CHANNEL; ++ } else { ++ /* ++ * we're on the operating channel currently, let's ++ * leave that channel now to scan another one ++ */ ++ local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; + } + + *next_delay = 0; +@@ -560,10 +528,9 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, + static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, + unsigned long *next_delay) + { +- /* PS will already be in off-channel mode, +- * we do that once at the beginning of scanning. +- */ +- ieee80211_offchannel_stop_vifs(local, false); ++ ieee80211_offchannel_stop_station(local); ++ ++ __set_bit(SCAN_OFF_CHANNEL, &local->scanning); + + /* + * What if the nullfunc frames didn't arrive? +@@ -586,15 +553,15 @@ static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *loca + { + /* switch back to the operating channel */ + local->scan_channel = NULL; +- if (!ieee80211_cfg_on_oper_channel(local)) +- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); ++ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); + + /* +- * Re-enable vifs and beaconing. Leave PS +- * in off-channel state..will put that back +- * on-channel at the end of scanning. ++ * Only re-enable station mode interface now; beaconing will be ++ * re-enabled once the full scan has been completed. + */ +- ieee80211_offchannel_return(local, true, false); ++ ieee80211_offchannel_return(local, false); ++ ++ __clear_bit(SCAN_OFF_CHANNEL, &local->scanning); + + *next_delay = HZ / 5; + local->next_scan_state = SCAN_DECISION; +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index 8cb0d2d..54ea022 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -258,8 +258,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) + if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) + return TX_CONTINUE; + +- if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) && +- test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) && ++ if (unlikely(test_bit(SCAN_OFF_CHANNEL, &tx->local->scanning)) && + !ieee80211_is_probe_req(hdr->frame_control) && + !ieee80211_is_nullfunc(hdr->frame_control)) + /* +diff --git a/net/mac80211/work.c b/net/mac80211/work.c +index 7737f20..b76bf33 100644 +--- a/net/mac80211/work.c ++++ b/net/mac80211/work.c +@@ -901,26 +901,6 @@ static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct, + return false; + } + +-static enum nl80211_channel_type +-ieee80211_calc_ct(enum nl80211_channel_type wk_ct, +- enum nl80211_channel_type oper_ct) +-{ +- switch (wk_ct) { +- case NL80211_CHAN_NO_HT: +- return oper_ct; +- case NL80211_CHAN_HT20: +- if (oper_ct != NL80211_CHAN_NO_HT) +- return oper_ct; +- return wk_ct; +- case NL80211_CHAN_HT40MINUS: +- case NL80211_CHAN_HT40PLUS: +- return wk_ct; +- } +- WARN_ON(1); /* shouldn't get here */ +- return wk_ct; +-} +- +- + static void ieee80211_work_timer(unsigned long data) + { + struct ieee80211_local *local = (void *) data; +@@ -971,52 +951,18 @@ static void ieee80211_work_work(struct work_struct *work) + } + + if (!started && !local->tmp_channel) { +- bool on_oper_chan; +- bool tmp_chan_changed = false; +- bool on_oper_chan2; +- enum nl80211_channel_type wk_ct; +- on_oper_chan = ieee80211_cfg_on_oper_channel(local); +- +- /* Work with existing channel type if possible. */ +- wk_ct = wk->chan_type; +- if (wk->chan == local->hw.conf.channel) +- wk_ct = ieee80211_calc_ct(wk->chan_type, +- local->hw.conf.channel_type); +- +- if (local->tmp_channel) +- if ((local->tmp_channel != wk->chan) || +- (local->tmp_channel_type != wk_ct)) +- tmp_chan_changed = true; +- +- local->tmp_channel = wk->chan; +- local->tmp_channel_type = wk_ct; + /* +- * Leave the station vifs in awake mode if they +- * happen to be on the same channel as +- * the requested channel. ++ * TODO: could optimize this by leaving the ++ * station vifs in awake mode if they ++ * happen to be on the same channel as ++ * the requested channel + */ +- on_oper_chan2 = ieee80211_cfg_on_oper_channel(local); +- if (on_oper_chan != on_oper_chan2) { +- if (on_oper_chan2) { +- /* going off oper channel, PS too */ +- ieee80211_offchannel_stop_vifs(local, +- true); +- ieee80211_hw_config(local, 0); +- } else { +- /* going on channel, but leave PS +- * off-channel. */ +- ieee80211_hw_config(local, 0); +- ieee80211_offchannel_return(local, +- true, +- false); +- } +- } else if (tmp_chan_changed) +- /* Still off-channel, but on some other +- * channel, so update hardware. +- * PS should already be off-channel. +- */ +- ieee80211_hw_config(local, 0); ++ ieee80211_offchannel_stop_beaconing(local); ++ ieee80211_offchannel_stop_station(local); + ++ local->tmp_channel = wk->chan; ++ local->tmp_channel_type = wk->chan_type; ++ ieee80211_hw_config(local, 0); + started = true; + wk->timeout = jiffies; + } +@@ -1102,8 +1048,7 @@ static void ieee80211_work_work(struct work_struct *work) + * we still need to do a hardware config. Currently, + * we cannot be here while scanning, however. + */ +- if (!ieee80211_cfg_on_oper_channel(local)) +- ieee80211_hw_config(local, 0); ++ ieee80211_hw_config(local, 0); + + /* At the least, we need to disable offchannel_ps, + * so just go ahead and run the entire offchannel +@@ -1111,7 +1056,7 @@ static void ieee80211_work_work(struct work_struct *work) + * beaconing if we were already on-oper-channel + * as a future optimization. + */ +- ieee80211_offchannel_return(local, true, true); ++ ieee80211_offchannel_return(local, true); + + /* give connection some time to breathe */ + run_again(local, jiffies + HZ/2); From caf149f8ee6f4697b185a866ea18da55675de453 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 1 Dec 2011 10:05:32 -0500 Subject: [PATCH 160/487] Disable the existing brcm80211 staging drivers (rhbz #759109) --- brcm80211.patch | 235 ++++++++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 1 + 2 files changed, 236 insertions(+) diff --git a/brcm80211.patch b/brcm80211.patch index 73c577f6d..00bd05f02 100644 --- a/brcm80211.patch +++ b/brcm80211.patch @@ -96989,3 +96989,238 @@ diff -up linux-3.1.x86_64/drivers/net/wireless/Makefile.orig linux-3.1.x86_64/dr + +obj-$(CONFIG_BRCMFMAC) += brcm80211/ +obj-$(CONFIG_BRCMSMAC) += brcm80211/ +diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig +index 06c9081..e2c3532 100644 +--- a/drivers/staging/Kconfig ++++ b/drivers/staging/Kconfig +@@ -44,8 +44,6 @@ source "drivers/staging/wlan-ng/Kconfig" + + source "drivers/staging/echo/Kconfig" + +-source "drivers/staging/brcm80211/Kconfig" +- + source "drivers/staging/comedi/Kconfig" + + source "drivers/staging/olpc_dcon/Kconfig" +diff --git a/drivers/staging/brcm80211/Kconfig b/drivers/staging/brcm80211/Kconfig +deleted file mode 100644 +index 379cf16..0000000 +--- a/drivers/staging/brcm80211/Kconfig ++++ /dev/null +@@ -1,40 +0,0 @@ +-config BRCMUTIL +- tristate +- default n +- +-config BRCMSMAC +- tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" +- default n +- depends on PCI +- depends on WLAN && MAC80211 +- depends on X86 || MIPS +- select BRCMUTIL +- select FW_LOADER +- select CRC_CCITT +- ---help--- +- This module adds support for PCIe wireless adapters based on Broadcom +- IEEE802.11n SoftMAC chipsets. If you choose to build a module, it'll +- be called brcmsmac.ko. +- +-config BRCMFMAC +- tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver" +- default n +- depends on MMC +- depends on WLAN && CFG80211 +- depends on X86 || MIPS +- select BRCMUTIL +- select FW_LOADER +- select WIRELESS_EXT +- select WEXT_PRIV +- ---help--- +- This module adds support for embedded wireless adapters based on +- Broadcom IEEE802.11n FullMAC chipsets. This driver uses the kernel's +- wireless extensions subsystem. If you choose to build a module, +- it'll be called brcmfmac.ko. +- +-config BRCMDBG +- bool "Broadcom driver debug functions" +- default n +- depends on BRCMSMAC || BRCMFMAC +- ---help--- +- Selecting this enables additional code for debug purposes. +diff --git a/drivers/staging/brcm80211/Makefile b/drivers/staging/brcm80211/Makefile +deleted file mode 100644 +index 8b01f5e..0000000 +--- a/drivers/staging/brcm80211/Makefile ++++ /dev/null +@@ -1,24 +0,0 @@ +-# +-# Makefile fragment for Broadcom 802.11n Networking Device Driver +-# +-# Copyright (c) 2010 Broadcom Corporation +-# +-# Permission to use, copy, modify, and/or distribute this software for any +-# purpose with or without fee is hereby granted, provided that the above +-# copyright notice and this permission notice appear in all copies. +-# +-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- +-# common flags +-subdir-ccflags-y := -DBCMDMA32 +-subdir-ccflags-$(CONFIG_BRCMDBG) += -DBCMDBG +- +-obj-$(CONFIG_BRCMUTIL) += brcmutil/ +-obj-$(CONFIG_BRCMFMAC) += brcmfmac/ +-obj-$(CONFIG_BRCMSMAC) += brcmsmac/ +diff --git a/drivers/staging/brcm80211/brcmfmac/Makefile b/drivers/staging/brcm80211/brcmfmac/Makefile +deleted file mode 100644 +index da3c805..0000000 +--- a/drivers/staging/brcm80211/brcmfmac/Makefile ++++ /dev/null +@@ -1,39 +0,0 @@ +-# +-# Makefile fragment for Broadcom 802.11n Networking Device Driver +-# +-# Copyright (c) 2010 Broadcom Corporation +-# +-# Permission to use, copy, modify, and/or distribute this software for any +-# purpose with or without fee is hereby granted, provided that the above +-# copyright notice and this permission notice appear in all copies. +-# +-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- +-ccflags-y := \ +- -DBRCMF_FIRSTREAD=64 \ +- -DBRCMF_SDALIGN=64 \ +- -DMAX_HDR_READ=64 +- +-ccflags-$(CONFIG_BRCMDBG) += -DSHOW_EVENTS +- +-ccflags-y += \ +- -Idrivers/staging/brcm80211/brcmfmac \ +- -Idrivers/staging/brcm80211/include +- +-DHDOFILES = \ +- wl_cfg80211.o \ +- dhd_cdc.o \ +- dhd_common.o \ +- dhd_sdio.o \ +- dhd_linux.o \ +- bcmsdh.o \ +- bcmsdh_sdmmc.o +- +-obj-$(CONFIG_BRCMFMAC) += brcmfmac.o +-brcmfmac-objs += $(DHDOFILES) +diff --git a/drivers/staging/brcm80211/brcmsmac/Makefile b/drivers/staging/brcm80211/brcmsmac/Makefile +deleted file mode 100644 +index 1ea3e0c..0000000 +--- a/drivers/staging/brcm80211/brcmsmac/Makefile ++++ /dev/null +@@ -1,58 +0,0 @@ +-# +-# Makefile fragment for Broadcom 802.11n Networking Device Driver +-# +-# Copyright (c) 2010 Broadcom Corporation +-# +-# Permission to use, copy, modify, and/or distribute this software for any +-# purpose with or without fee is hereby granted, provided that the above +-# copyright notice and this permission notice appear in all copies. +-# +-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- +-ccflags-y := \ +- -DWLC_HIGH \ +- -DWLC_LOW \ +- -DSTA \ +- -DWME \ +- -DWL11N \ +- -DDBAND \ +- -DBCMNVRAMR \ +- -Idrivers/staging/brcm80211/brcmsmac \ +- -Idrivers/staging/brcm80211/brcmsmac/phy \ +- -Idrivers/staging/brcm80211/include +- +-BRCMSMAC_OFILES := \ +- mac80211_if.o \ +- ucode_loader.o \ +- alloc.o \ +- ampdu.o \ +- antsel.o \ +- bmac.o \ +- channel.o \ +- main.o \ +- phy_shim.o \ +- pmu.o \ +- rate.o \ +- stf.o \ +- aiutils.o \ +- phy/phy_cmn.o \ +- phy/phy_lcn.o \ +- phy/phy_n.o \ +- phy/phytbl_lcn.o \ +- phy/phytbl_n.o \ +- phy/phy_qmath.o \ +- otp.o \ +- srom.o \ +- dma.o \ +- nicpci.o +- +-MODULEPFX := brcmsmac +- +-obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o +-$(MODULEPFX)-objs = $(BRCMSMAC_OFILES) +diff --git a/drivers/staging/brcm80211/brcmutil/Makefile b/drivers/staging/brcm80211/brcmutil/Makefile +deleted file mode 100644 +index 6403423..0000000 +--- a/drivers/staging/brcm80211/brcmutil/Makefile ++++ /dev/null +@@ -1,29 +0,0 @@ +-# +-# Makefile fragment for Broadcom 802.11n Networking Device Driver Utilities +-# +-# Copyright (c) 2011 Broadcom Corporation +-# +-# Permission to use, copy, modify, and/or distribute this software for any +-# purpose with or without fee is hereby granted, provided that the above +-# copyright notice and this permission notice appear in all copies. +-# +-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- +-ccflags-y := \ +- -Idrivers/staging/brcm80211/brcmutil \ +- -Idrivers/staging/brcm80211/include +- +-BRCMUTIL_OFILES := \ +- utils.o \ +- wifi.o +- +-MODULEPFX := brcmutil +- +-obj-$(CONFIG_BRCMUTIL) += $(MODULEPFX).o +-$(MODULEPFX)-objs = $(BRCMUTIL_OFILES) +-- +1.7.7.3 diff --git a/kernel.spec b/kernel.spec index ddef92524..878fd2267 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2196,6 +2196,7 @@ fi %changelog * Thu Dec 01 2011 Josh Boyer - Apply patch to revert mac80211 scan optimizations (rhbz #731365) +- Disable the existing brcm80211 staging drivers (rhbz #759109) * Wed Nov 30 2011 Josh Boyer - Include commit 3940d6185 from JJ Ding in elantech.patch From 820b81af2049ce90f5edc0fda38ac61057eaed8c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 1 Dec 2011 11:07:19 -0500 Subject: [PATCH 161/487] Fixup brcm80211 staging neutering Need to drop references in drivers/staging/Makefile too, or 'make mrproper' fails. Doh. --- brcm80211.patch | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/brcm80211.patch b/brcm80211.patch index 00bd05f02..7c6d42e76 100644 --- a/brcm80211.patch +++ b/brcm80211.patch @@ -97223,4 +97223,16 @@ index 6403423..0000000 -obj-$(CONFIG_BRCMUTIL) += $(MODULEPFX).o -$(MODULEPFX)-objs = $(BRCMUTIL_OFILES) -- -1.7.7.3 +diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile +index f3c5e33..f2c2209 100644 +--- a/drivers/staging/Makefile ++++ b/drivers/staging/Makefile +@@ -14,8 +14,6 @@ obj-$(CONFIG_USBIP_CORE) += usbip/ + obj-$(CONFIG_W35UND) += winbond/ + obj-$(CONFIG_PRISM2_USB) += wlan-ng/ + obj-$(CONFIG_ECHO) += echo/ +-obj-$(CONFIG_BRCMSMAC) += brcm80211/ +-obj-$(CONFIG_BRCMFMAC) += brcm80211/ + obj-$(CONFIG_COMEDI) += comedi/ + obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/ + obj-$(CONFIG_ASUS_OLED) += asus_oled/ From acb2fd5ebea7272bb64fc64fb34870b47238ef91 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 5 Dec 2011 16:02:54 -0500 Subject: [PATCH 162/487] Switch from -Os to -O2 --- config-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 65c01a8ae..0fc16d85a 100644 --- a/config-generic +++ b/config-generic @@ -3770,7 +3770,7 @@ CONFIG_FRAME_WARN=1024 CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_INFO=y CONFIG_FRAME_POINTER=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_DEBUG_DRIVER is not set CONFIG_HEADERS_CHECK=y # CONFIG_RCU_TORTURE_TEST is not set diff --git a/kernel.spec b/kernel.spec index 878fd2267..8012cb230 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2194,6 +2194,9 @@ fi # and build. %changelog +* Mon Dec 05 2011 Dave Jones +- Switch from -Os to -O2 + * Thu Dec 01 2011 Josh Boyer - Apply patch to revert mac80211 scan optimizations (rhbz #731365) - Disable the existing brcm80211 staging drivers (rhbz #759109) From ac24e81de8309549c0f43f1eee78bd0b9868d6fd Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 5 Dec 2011 16:50:31 -0500 Subject: [PATCH 163/487] Only print the apm_cpu_idle message once (rhbz #760341) --- kernel.spec | 5 ++++- quite-apm.patch | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 8012cb230..b3b130adb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2194,6 +2194,9 @@ fi # and build. %changelog +* Mon Dec 05 2011 Josh Boyer +- Only print the apm_cpu_idle message once (rhbz #760341) + * Mon Dec 05 2011 Dave Jones - Switch from -Os to -O2 diff --git a/quite-apm.patch b/quite-apm.patch index 9325ae55b..c38511c41 100644 --- a/quite-apm.patch +++ b/quite-apm.patch @@ -7,7 +7,7 @@ index a46bd38..416dd12 100644 unsigned int bucket; - WARN_ONCE(1, "deprecated apm_cpu_idle will be deleted in 2012"); -+ printk(KERN_INFO "deprecated apm_cpu_idle will be deleted in 2012"); ++ printk_once(KERN_INFO "deprecated apm_cpu_idle will be deleted in 2012"); recalc: if (jiffies_since_last_check > IDLE_CALC_LIMIT) { use_apm_idle = 0; From 54e4e60a8beae30cc2389437967d17d55da02731 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 6 Dec 2011 13:01:59 -0500 Subject: [PATCH 164/487] Add reworked pci ASPM patch from Matthew Garrett --- kernel.spec | 7 + pci-Rework-ASPM-disable-code.patch | 287 +++++++++++++++++++++++++++++ 2 files changed, 294 insertions(+) create mode 100644 pci-Rework-ASPM-disable-code.patch diff --git a/kernel.spec b/kernel.spec index b3b130adb..22762e6bf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -797,6 +797,8 @@ Patch21200: rtlwifi-fix-lps_lock-deadlock.patch #rhbz 731365 Patch21220: mac80211_offchannel_rework_revert.patch +Patch21225: pci-Rework-ASPM-disable-code.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1463,6 +1465,8 @@ ApplyPatch rtlwifi-fix-lps_lock-deadlock.patch #rhbz 731365 ApplyPatch mac80211_offchannel_rework_revert.patch +ApplyPatch pci-Rework-ASPM-disable-code.patch + # END OF PATCH APPLICATIONS %endif @@ -2194,6 +2198,9 @@ fi # and build. %changelog +* Tue Dec 06 2011 Josh Boyer +- Add reworked pci ASPM patch from Matthew Garrett + * Mon Dec 05 2011 Josh Boyer - Only print the apm_cpu_idle message once (rhbz #760341) diff --git a/pci-Rework-ASPM-disable-code.patch b/pci-Rework-ASPM-disable-code.patch new file mode 100644 index 000000000..d6fb24320 --- /dev/null +++ b/pci-Rework-ASPM-disable-code.patch @@ -0,0 +1,287 @@ +Path: news.gmane.org!not-for-mail +From: Matthew Garrett +Newsgroups: gmane.linux.acpi.devel,gmane.linux.kernel.pci,gmane.linux.kernel +Subject: [PATCH] pci: Rework ASPM disable code +Date: Thu, 10 Nov 2011 16:38:33 -0500 +Lines: 232 +Approved: news@gmane.org +Message-ID: <1320961113-5050-1-git-send-email-mjg@redhat.com> +NNTP-Posting-Host: lo.gmane.org +X-Trace: dough.gmane.org 1320961145 13112 80.91.229.12 (10 Nov 2011 21:39:05 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Thu, 10 Nov 2011 21:39:05 +0000 (UTC) +Cc: linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, + linux-kernel@vger.kernel.org, Matthew Garrett +To: jbarnes@virtuousgeek.org +Original-X-From: linux-acpi-owner@vger.kernel.org Thu Nov 10 22:38:57 2011 +Return-path: +Envelope-to: glad-acpi-devel@lo.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1ROcKm-0003jN-CL + for glad-acpi-devel@lo.gmane.org; Thu, 10 Nov 2011 22:38:56 +0100 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1751342Ab1KJViu (ORCPT ); + Thu, 10 Nov 2011 16:38:50 -0500 +Original-Received: from mx1.redhat.com ([209.132.183.28]:32030 "EHLO mx1.redhat.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1750805Ab1KJVit (ORCPT ); + Thu, 10 Nov 2011 16:38:49 -0500 +Original-Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id pAALcmdw013333 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Thu, 10 Nov 2011 16:38:49 -0500 +Original-Received: from cavan.codon.org.uk (ovpn-113-157.phx2.redhat.com [10.3.113.157]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id pAALclkW022022 + (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NO); + Thu, 10 Nov 2011 16:38:48 -0500 +Original-Received: from 209-6-41-104.c3-0.smr-ubr1.sbo-smr.ma.cable.rcn.com ([209.6.41.104] helo=localhost.localdomain) + by cavan.codon.org.uk with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) + (Exim 4.72) + (envelope-from ) + id 1ROcKa-0000F4-E4; Thu, 10 Nov 2011 21:38:44 +0000 +X-SA-Do-Not-Run: Yes +X-SA-Exim-Connect-IP: 209.6.41.104 +X-SA-Exim-Mail-From: mjg@redhat.com +X-SA-Exim-Scanned: No (on cavan.codon.org.uk); SAEximRunCond expanded to false +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Original-Sender: linux-acpi-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-acpi@vger.kernel.org +Xref: news.gmane.org gmane.linux.acpi.devel:51182 gmane.linux.kernel.pci:12503 gmane.linux.kernel:1214427 +Archived-At: + +Right now we forcibly clear ASPM state on all devices if the BIOS indicates +that the feature isn't supported. Based on the Microsoft presentation +"PCI Express In Depth for Windows Vista and Beyond", I'm starting to think +that this may be an error. The implication is that unless the platform +grants full control via _OSC, Windows will not touch any PCIe features - +including ASPM. In that case clearing ASPM state would be an error unless +the platform has granted us that control. + +This patch reworks the ASPM disabling code such that the actual clearing +of state is triggered by a successful handoff of PCIe control to the OS. +The general ASPM code undergoes some changes in order to ensure that the +ability to clear the bits isn't overridden by ASPM having already been +disabled. Further, this theoretically now allows for situations where +only a subset of PCIe roots hand over control, leaving the others in the +BIOS state. + +It's difficult to know for sure that this is the right thing to do - +there's zero public documentation on the interaction between all of these +components. But enough vendors enable ASPM on platforms and then set this +bit that it seems likely that they're expecting the OS to leave them alone. + +Measured to save around 5W on an idle Thinkpad X220. + +Signed-off-by: Matthew Garrett +--- + drivers/acpi/pci_root.c | 7 +++++ + drivers/pci/pci-acpi.c | 1 - + drivers/pci/pcie/aspm.c | 58 +++++++++++++++++++++++++++++---------------- + include/linux/pci-aspm.h | 4 +- + 4 files changed, 46 insertions(+), 24 deletions(-) + +diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c +index 2672c79..7aff631 100644 +--- a/drivers/acpi/pci_root.c ++++ b/drivers/acpi/pci_root.c +@@ -596,6 +596,13 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) + if (ACPI_SUCCESS(status)) { + dev_info(root->bus->bridge, + "ACPI _OSC control (0x%02x) granted\n", flags); ++ if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { ++ /* ++ * We have ASPM control, but the FADT indicates ++ * that it's unsupported. Clear it. ++ */ ++ pcie_clear_aspm(root->bus); ++ } + } else { + dev_info(root->bus->bridge, + "ACPI _OSC request failed (%s), " +diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c +index 4ecb640..c8e7585 100644 +--- a/drivers/pci/pci-acpi.c ++++ b/drivers/pci/pci-acpi.c +@@ -395,7 +395,6 @@ static int __init acpi_pci_init(void) + + if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { + printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n"); +- pcie_clear_aspm(); + pcie_no_aspm(); + } + +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index cbfbab1..1cfbf22 100644 +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -68,7 +68,7 @@ struct pcie_link_state { + struct aspm_latency acceptable[8]; + }; + +-static int aspm_disabled, aspm_force, aspm_clear_state; ++static int aspm_disabled, aspm_force; + static bool aspm_support_enabled = true; + static DEFINE_MUTEX(aspm_lock); + static LIST_HEAD(link_list); +@@ -500,9 +500,6 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) + int pos; + u32 reg32; + +- if (aspm_clear_state) +- return -EINVAL; +- + /* + * Some functions in a slot might not all be PCIe functions, + * very strange. Disable ASPM for the whole slot +@@ -574,9 +571,6 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) + pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) + return; + +- if (aspm_disabled && !aspm_clear_state) +- return; +- + /* VIA has a strange chipset, root port is under a bridge */ + if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT && + pdev->bus->self) +@@ -608,7 +602,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) + * the BIOS's expectation, we'll do so once pci_enable_device() is + * called. + */ +- if (aspm_policy != POLICY_POWERSAVE || aspm_clear_state) { ++ if (aspm_policy != POLICY_POWERSAVE) { + pcie_config_aspm_path(link); + pcie_set_clkpm(link, policy_to_clkpm_state(link)); + } +@@ -649,8 +643,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) + struct pci_dev *parent = pdev->bus->self; + struct pcie_link_state *link, *root, *parent_link; + +- if ((aspm_disabled && !aspm_clear_state) || !pci_is_pcie(pdev) || +- !parent || !parent->link_state) ++ if (!pci_is_pcie(pdev) || !parent || !parent->link_state) + return; + if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && + (parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) +@@ -734,13 +727,18 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev) + * pci_disable_link_state - disable pci device's link state, so the link will + * never enter specific states + */ +-static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) ++static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem, ++ bool force) + { + struct pci_dev *parent = pdev->bus->self; + struct pcie_link_state *link; + +- if (aspm_disabled || !pci_is_pcie(pdev)) ++ if (aspm_disabled && !force) ++ return; ++ ++ if (!pci_is_pcie(pdev)) + return; ++ + if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT || + pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) + parent = pdev; +@@ -768,16 +766,31 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) + + void pci_disable_link_state_locked(struct pci_dev *pdev, int state) + { +- __pci_disable_link_state(pdev, state, false); ++ __pci_disable_link_state(pdev, state, false, false); + } + EXPORT_SYMBOL(pci_disable_link_state_locked); + + void pci_disable_link_state(struct pci_dev *pdev, int state) + { +- __pci_disable_link_state(pdev, state, true); ++ __pci_disable_link_state(pdev, state, true, false); + } + EXPORT_SYMBOL(pci_disable_link_state); + ++void pcie_clear_aspm(struct pci_bus *bus) ++{ ++ struct pci_dev *child; ++ ++ /* ++ * Clear any ASPM setup that the firmware has carried out on this bus ++ */ ++ list_for_each_entry(child, &bus->devices, bus_list) { ++ __pci_disable_link_state(child, PCIE_LINK_STATE_L0S | ++ PCIE_LINK_STATE_L1 | ++ PCIE_LINK_STATE_CLKPM, ++ false, true); ++ } ++} ++ + static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp) + { + int i; +@@ -935,6 +948,7 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) + static int __init pcie_aspm_disable(char *str) + { + if (!strcmp(str, "off")) { ++ aspm_policy = POLICY_DEFAULT; + aspm_disabled = 1; + aspm_support_enabled = false; + printk(KERN_INFO "PCIe ASPM is disabled\n"); +@@ -947,16 +961,18 @@ static int __init pcie_aspm_disable(char *str) + + __setup("pcie_aspm=", pcie_aspm_disable); + +-void pcie_clear_aspm(void) +-{ +- if (!aspm_force) +- aspm_clear_state = 1; +-} +- + void pcie_no_aspm(void) + { +- if (!aspm_force) ++ /* ++ * Disabling ASPM is intended to prevent the kernel from modifying ++ * existing hardware state, not to clear existing state. To that end: ++ * (a) set policy to POLICY_DEFAULT in order to avoid changing state ++ * (b) prevent userspace from changing policy ++ */ ++ if (!aspm_force) { ++ aspm_policy = POLICY_DEFAULT; + aspm_disabled = 1; ++ } + } + + /** +diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h +index 7cea7b6..c832014 100644 +--- a/include/linux/pci-aspm.h ++++ b/include/linux/pci-aspm.h +@@ -29,7 +29,7 @@ extern void pcie_aspm_pm_state_change(struct pci_dev *pdev); + extern void pcie_aspm_powersave_config_link(struct pci_dev *pdev); + extern void pci_disable_link_state(struct pci_dev *pdev, int state); + extern void pci_disable_link_state_locked(struct pci_dev *pdev, int state); +-extern void pcie_clear_aspm(void); ++extern void pcie_clear_aspm(struct pci_bus *bus); + extern void pcie_no_aspm(void); + #else + static inline void pcie_aspm_init_link_state(struct pci_dev *pdev) +@@ -47,7 +47,7 @@ static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev) + static inline void pci_disable_link_state(struct pci_dev *pdev, int state) + { + } +-static inline void pcie_clear_aspm(void) ++static inline void pcie_clear_aspm(struct pci_bus *bus) + { + } + static inline void pcie_no_aspm(void) +-- +1.7.7.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-acpi" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + From 4553808497fdd4a12071417f9ed9cfc0bc5da087 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Tue, 6 Dec 2011 14:16:57 -0500 Subject: [PATCH 165/487] Disable uas until someone can fix it (rhbz #717633) --- config-generic | 3 ++- kernel.spec | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 0fc16d85a..8ae85a234 100644 --- a/config-generic +++ b/config-generic @@ -3109,7 +3109,8 @@ CONFIG_USB_STORAGE_REALTEK=m CONFIG_REALTEK_AUTOPM=y CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set -CONFIG_USB_UAS=m +# uas is broken (#717633, #744099) +# CONFIG_USB_UAS is not set # diff --git a/kernel.spec b/kernel.spec index 22762e6bf..8eff462ba 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2198,6 +2198,9 @@ fi # and build. %changelog +* Tue Dec 06 2011 Chuck Ebbert +- Disable uas until someone can fix it (rhbz #717633) + * Tue Dec 06 2011 Josh Boyer - Add reworked pci ASPM patch from Matthew Garrett From 8ed136869acaf7af99a9d29eaf580f3f073d73dd Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 7 Dec 2011 11:38:39 -0500 Subject: [PATCH 166/487] Linux 3.1.5-rc1 Comment out merged patches: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch rtlwifi-fix-lps_lock-deadlock.patch --- config-arm-omap-generic | 1 + config-arm-tegra | 1 + kernel.spec | 16 +++++++++++----- sources | 1 + 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/config-arm-omap-generic b/config-arm-omap-generic index 8c3ae6a24..b4163bc5a 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -121,6 +121,7 @@ CONFIG_ARM_ERRATA_430973=y # CONFIG_ARM_ERRATA_742230 is not set # CONFIG_ARM_ERRATA_742231 is not set CONFIG_PL310_ERRATA_588369=y +CONFIG_PL310_ERRATA_769419=y CONFIG_ARM_ERRATA_720789=y # CONFIG_ARM_ERRATA_743622 is not set # CONFIG_ARM_ERRATA_751472 is not set diff --git a/config-arm-tegra b/config-arm-tegra index 910b39f81..b131978d2 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -34,6 +34,7 @@ CONFIG_ARM_ERRATA_430973=y CONFIG_ARM_ERRATA_742230=y # CONFIG_ARM_ERRATA_742231 is not set CONFIG_PL310_ERRATA_588369=y +CONFIG_PL310_ERRATA_769419=y CONFIG_ARM_ERRATA_720789=y # CONFIG_PL310_ERRATA_727915 is not set # CONFIG_ARM_ERRATA_743622 is not set diff --git a/kernel.spec b/kernel.spec index 8eff462ba..523bb424a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 5 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,9 +66,9 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 4 +%define stable_update 5 # Is it a -stable RC? -%define stable_rc 0 +%define stable_rc 1 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -1301,7 +1301,7 @@ ApplyPatch linux-2.6-i386-nx-emulation.patch ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # xfs -ApplyPatch xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch +#ApplyPatch xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch # btrfs @@ -1460,7 +1460,7 @@ ApplyPatch cciss-fix-irqf-shared.patch ApplyPatch hpsa-add-irqf-shared.patch #rhbz 755154 -ApplyPatch rtlwifi-fix-lps_lock-deadlock.patch +#ApplyPatch rtlwifi-fix-lps_lock-deadlock.patch #rhbz 731365 ApplyPatch mac80211_offchannel_rework_revert.patch @@ -2198,6 +2198,12 @@ fi # and build. %changelog +* Wed Dec 07 2011 Chuck Ebbert 3.1.5-0.rc1.1 +- Linux 3.1.5-rc1 +- Comment out merged patches: + xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch + rtlwifi-fix-lps_lock-deadlock.patch + * Tue Dec 06 2011 Chuck Ebbert - Disable uas until someone can fix it (rhbz #717633) diff --git a/sources b/sources index b8c0593a0..2a313cf69 100644 --- a/sources +++ b/sources @@ -1,3 +1,4 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 6693d8c42055f83f5701d9b65d47208a compat-wireless-3.2-rc1-1.tar.bz2 b8b14bdfbf76cfef8e042e7d1a385fca patch-3.1.4.bz2 +cb4154af3daf6279680b808b6affc374 patch-3.1.5-rc1.bz2 From 5a7d4b130b111cc6da283a680b70883e1e6a4fa9 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 8 Dec 2011 10:42:31 +1000 Subject: [PATCH 167/487] nouveau: fix accel on GF108 and enable on GF108/GF110 --- drm-nouveau-gf108.patch | 151 ++++++++++++++++++++++++++++++++++++++++ kernel.spec | 7 +- 2 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 drm-nouveau-gf108.patch diff --git a/drm-nouveau-gf108.patch b/drm-nouveau-gf108.patch new file mode 100644 index 000000000..80f0d9b29 --- /dev/null +++ b/drm-nouveau-gf108.patch @@ -0,0 +1,151 @@ +diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c +index 82478e0..d8831ab 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_state.c ++++ b/drivers/gpu/drm/nouveau/nouveau_state.c +@@ -579,6 +579,14 @@ nouveau_card_init(struct drm_device *dev) + if (ret) + goto out_display_early; + ++ /* workaround an odd issue on nvc1 by disabling the device's ++ * nosnoop capability. hopefully won't cause issues until a ++ * better fix is found - assuming there is one... ++ */ ++ if (dev_priv->chipset == 0xc1) { ++ nv_mask(dev, 0x00088080, 0x00000800, 0x00000000); ++ } ++ + nouveau_pm_init(dev); + + ret = engine->vram.init(dev); +@@ -1102,12 +1110,13 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) + dev_priv->noaccel = !!nouveau_noaccel; + if (nouveau_noaccel == -1) { + switch (dev_priv->chipset) { +- case 0xc1: /* known broken */ +- case 0xc8: /* never tested */ ++#if 0 ++ case 0xXX: /* known broken */ + NV_INFO(dev, "acceleration disabled by default, pass " + "noaccel=0 to force enable\n"); + dev_priv->noaccel = true; + break; ++#endif + default: + dev_priv->noaccel = false; + break; +diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c +index 4b8d0b3..3cc1c60 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_graph.c ++++ b/drivers/gpu/drm/nouveau/nvc0_graph.c +@@ -156,8 +156,8 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) + struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); + struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; + struct drm_device *dev = chan->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; + int i = 0, gpc, tp, ret; +- u32 magic; + + ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM, + &grch->unk408004); +@@ -206,14 +206,37 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) + nv_wo32(grch->mmio, i++ * 4, 0x0041880c); + nv_wo32(grch->mmio, i++ * 4, 0x80000018); + +- magic = 0x02180000; +- nv_wo32(grch->mmio, i++ * 4, 0x00405830); +- nv_wo32(grch->mmio, i++ * 4, magic); +- for (gpc = 0; gpc < priv->gpc_nr; gpc++) { +- for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x0324) { +- u32 reg = 0x504520 + (gpc * 0x8000) + (tp * 0x0800); +- nv_wo32(grch->mmio, i++ * 4, reg); +- nv_wo32(grch->mmio, i++ * 4, magic); ++ if (dev_priv->chipset != 0xc1) { ++ u32 magic = 0x02180000; ++ nv_wo32(grch->mmio, i++ * 4, 0x00405830); ++ nv_wo32(grch->mmio, i++ * 4, magic); ++ for (gpc = 0; gpc < priv->gpc_nr; gpc++) { ++ for (tp = 0; tp < priv->tp_nr[gpc]; tp++) { ++ u32 reg = TP_UNIT(gpc, tp, 0x520); ++ nv_wo32(grch->mmio, i++ * 4, reg); ++ nv_wo32(grch->mmio, i++ * 4, magic); ++ magic += 0x0324; ++ } ++ } ++ } else { ++ u32 magic = 0x02180000; ++ nv_wo32(grch->mmio, i++ * 4, 0x00405830); ++ nv_wo32(grch->mmio, i++ * 4, magic | 0x0000218); ++ nv_wo32(grch->mmio, i++ * 4, 0x004064c4); ++ nv_wo32(grch->mmio, i++ * 4, 0x0086ffff); ++ for (gpc = 0; gpc < priv->gpc_nr; gpc++) { ++ for (tp = 0; tp < priv->tp_nr[gpc]; tp++) { ++ u32 reg = TP_UNIT(gpc, tp, 0x520); ++ nv_wo32(grch->mmio, i++ * 4, reg); ++ nv_wo32(grch->mmio, i++ * 4, (1 << 28) | magic); ++ magic += 0x0324; ++ } ++ for (tp = 0; tp < priv->tp_nr[gpc]; tp++) { ++ u32 reg = TP_UNIT(gpc, tp, 0x544); ++ nv_wo32(grch->mmio, i++ * 4, reg); ++ nv_wo32(grch->mmio, i++ * 4, magic); ++ magic += 0x0324; ++ } + } + } + +diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c +index dd0e6a7..96b0b93d 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_grctx.c ++++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c +@@ -1812,6 +1812,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) + /* calculate first set of magics */ + memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); + ++ gpc = -1; + for (tp = 0; tp < priv->tp_total; tp++) { + do { + gpc = (gpc + 1) % priv->gpc_nr; +@@ -1861,30 +1862,26 @@ nvc0_grctx_generate(struct nouveau_channel *chan) + + if (1) { + u32 tp_mask = 0, tp_set = 0; +- u8 tpnr[GPC_MAX]; ++ u8 tpnr[GPC_MAX], a, b; + + memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); + for (gpc = 0; gpc < priv->gpc_nr; gpc++) + tp_mask |= ((1 << priv->tp_nr[gpc]) - 1) << (gpc * 8); + +- gpc = -1; +- for (i = 0, gpc = -1; i < 32; i++) { +- int ltp = i * (priv->tp_total - 1) / 32; +- +- do { +- gpc = (gpc + 1) % priv->gpc_nr; +- } while (!tpnr[gpc]); +- tp = priv->tp_nr[gpc] - tpnr[gpc]--; ++ for (i = 0, gpc = -1, b = -1; i < 32; i++) { ++ a = (i * (priv->tp_total - 1)) / 32; ++ if (a != b) { ++ b = a; ++ do { ++ gpc = (gpc + 1) % priv->gpc_nr; ++ } while (!tpnr[gpc]); ++ tp = priv->tp_nr[gpc] - tpnr[gpc]--; + +- tp_set |= 1 << ((gpc * 8) + tp); ++ tp_set |= 1 << ((gpc * 8) + tp); ++ } + +- do { +- nv_wr32(dev, 0x406800 + (i * 0x20), tp_set); +- tp_set ^= tp_mask; +- nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set); +- tp_set ^= tp_mask; +- } while (ltp == (++i * (priv->tp_total - 1) / 32)); +- i--; ++ nv_wr32(dev, 0x406800 + (i * 0x20), tp_set); ++ nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set ^ tp_mask); + } + } + diff --git a/kernel.spec b/kernel.spec index 523bb424a..4e5f07b45 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -700,6 +700,7 @@ Patch1500: fix_xen_guest_on_old_EC2.patch # nouveau + drm fixes Patch1810: drm-nouveau-updates.patch +Patch1811: drm-nouveau-gf108.patch # intel drm is all merged upstream Patch1824: drm-intel-next.patch # hush the i915 fbc noise @@ -1379,6 +1380,7 @@ ApplyPatch fix_xen_guest_on_old_EC2.patch # Nouveau DRM ApplyOptionalPatch drm-nouveau-updates.patch +ApplyPatch drm-nouveau-gf108.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch @@ -2198,6 +2200,9 @@ fi # and build. %changelog +* Thu Dec 08 2011 Ben Skeggs 3.1.5-0.rc1.2 +- nouveau: fix accel on GF108 and enable on GF108/GF110 + * Wed Dec 07 2011 Chuck Ebbert 3.1.5-0.rc1.1 - Linux 3.1.5-rc1 - Comment out merged patches: From cafbe33b9221436fd67d686c758bbf602cbc7c99 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 8 Dec 2011 11:58:24 -0500 Subject: [PATCH 168/487] Linux 3.1.5-rc2 Drop obsolete changelog, set rcrev and gitrev to 0 so they're less distracting. --- kernel.spec | 15 +- patch-3.1-rc10-git1.log | 804 ---------------------------------------- sources | 2 +- 3 files changed, 11 insertions(+), 810 deletions(-) delete mode 100644 patch-3.1-rc10-git1.log diff --git a/kernel.spec b/kernel.spec index 4e5f07b45..049b00644 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -68,7 +68,7 @@ Summary: The Linux kernel # Do we have a -stable update to apply? %define stable_update 5 # Is it a -stable RC? -%define stable_rc 1 +%define stable_rc 2 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -85,9 +85,9 @@ Summary: The Linux kernel # The next upstream release sublevel (base_sublevel+1) %define upstream_sublevel %(echo $((%{base_sublevel} + 1))) # The rc snapshot level -%define rcrev 10 +%define rcrev 0 # The git snapshot level -%define gitrev 1 +%define gitrev 0 # Set rpm version accordingly %define rpmversion 3.%{upstream_sublevel}.0 %endif @@ -2200,10 +2200,15 @@ fi # and build. %changelog +* Thu Dec 08 2011 Chuck Ebbert 3.1.5-0.rc2.1 +- Linux 3.1.5-rc2 +- Drop obsolete changelog, set rcrev and gitrev to 0 so they're + less distracting. + * Thu Dec 08 2011 Ben Skeggs 3.1.5-0.rc1.2 - nouveau: fix accel on GF108 and enable on GF108/GF110 -* Wed Dec 07 2011 Chuck Ebbert 3.1.5-0.rc1.1 +* Wed Dec 07 2011 Chuck Ebbert - Linux 3.1.5-rc1 - Comment out merged patches: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch diff --git a/patch-3.1-rc10-git1.log b/patch-3.1-rc10-git1.log deleted file mode 100644 index ba8dfd171..000000000 --- a/patch-3.1-rc10-git1.log +++ /dev/null @@ -1,804 +0,0 @@ -commit 2efd7c0fdcbe041173e248ccc2d9c91df7f84ce5 -Merge: 62ddc00 7ed47b7 -Author: Linus Torvalds -Date: Fri Oct 21 17:02:18 2011 +0300 - - Merge git://github.com/herbertx/crypto - - * git://github.com/herbertx/crypto: - crypto: ghash - Avoid null pointer dereference if no key is set - -commit 62ddc0046eae6b8e8374f0ac3b27b12a57baa2f6 -Merge: fd11e15 ca201c0 -Author: Linus Torvalds -Date: Fri Oct 21 17:01:21 2011 +0300 - - Merge branch 'fix/hda' of git://github.com/tiwai/sound - - * 'fix/hda' of git://github.com/tiwai/sound: - ALSA: HDA: conexant support for Lenovo T520/W520 - ALSA: hda - Add position_fix quirk for Dell Inspiron 1010 - -commit 7ed47b7d142ec99ad6880bbbec51e9f12b3af74c -Author: Nick Bowler -Date: Thu Oct 20 14:16:55 2011 +0200 - - crypto: ghash - Avoid null pointer dereference if no key is set - - The ghash_update function passes a pointer to gf128mul_4k_lle which will - be NULL if ghash_setkey is not called or if the most recent call to - ghash_setkey failed to allocate memory. This causes an oops. Fix this - up by returning an error code in the null case. - - This is trivially triggered from unprivileged userspace through the - AF_ALG interface by simply writing to the socket without setting a key. - - The ghash_final function has a similar issue, but triggering it requires - a memory allocation failure in ghash_setkey _after_ at least one - successful call to ghash_update. - - BUG: unable to handle kernel NULL pointer dereference at 00000670 - IP: [] gf128mul_4k_lle+0x23/0x60 [gf128mul] - *pde = 00000000 - Oops: 0000 [#1] PREEMPT SMP - Modules linked in: ghash_generic gf128mul algif_hash af_alg nfs lockd nfs_acl sunrpc bridge ipv6 stp llc - - Pid: 1502, comm: hashatron Tainted: G W 3.1.0-rc9-00085-ge9308cf #32 Bochs Bochs - EIP: 0060:[] EFLAGS: 00000202 CPU: 0 - EIP is at gf128mul_4k_lle+0x23/0x60 [gf128mul] - EAX: d69db1f0 EBX: d6b8ddac ECX: 00000004 EDX: 00000000 - ESI: 00000670 EDI: d6b8ddac EBP: d6b8ddc8 ESP: d6b8dda4 - DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 - Process hashatron (pid: 1502, ti=d6b8c000 task=d6810000 task.ti=d6b8c000) - Stack: - 00000000 d69db1f0 00000163 00000000 d6b8ddc8 c101a520 d69db1f0 d52aa000 - 00000ff0 d6b8dde8 d88d310f d6b8a3f8 d52aa000 00001000 d88d502c d6b8ddfc - 00001000 d6b8ddf4 c11676ed d69db1e8 d6b8de24 c11679ad d52aa000 00000000 - Call Trace: - [] ? kmap_atomic_prot+0x37/0xa6 - [] ghash_update+0x85/0xbe [ghash_generic] - [] crypto_shash_update+0x18/0x1b - [] shash_ahash_update+0x22/0x36 - [] shash_async_update+0xb/0xd - [] hash_sendpage+0xba/0xf2 [algif_hash] - [] kernel_sendpage+0x39/0x4e - [] ? 0xd88cdfff - [] sock_sendpage+0x37/0x3e - [] ? kernel_sendpage+0x4e/0x4e - [] pipe_to_sendpage+0x56/0x61 - [] splice_from_pipe_feed+0x58/0xcd - [] ? splice_from_pipe_begin+0x10/0x10 - [] __splice_from_pipe+0x36/0x55 - [] ? splice_from_pipe_begin+0x10/0x10 - [] splice_from_pipe+0x51/0x64 - [] ? default_file_splice_write+0x2c/0x2c - [] generic_splice_sendpage+0x13/0x15 - [] ? splice_from_pipe_begin+0x10/0x10 - [] do_splice_from+0x5d/0x67 - [] sys_splice+0x2bf/0x363 - [] ? sysenter_exit+0xf/0x16 - [] ? trace_hardirqs_on_caller+0x10e/0x13f - [] sysenter_do_call+0x12/0x32 - Code: 83 c4 0c 5b 5e 5f c9 c3 55 b9 04 00 00 00 89 e5 57 8d 7d e4 56 53 8d 5d e4 83 ec 18 89 45 e0 89 55 dc 0f b6 70 0f c1 e6 04 01 d6 a5 be 0f 00 00 00 4e 89 d8 e8 48 ff ff ff 8b 45 e0 89 da 0f - EIP: [] gf128mul_4k_lle+0x23/0x60 [gf128mul] SS:ESP 0068:d6b8dda4 - CR2: 0000000000000670 - ---[ end trace 4eaa2a86a8e2da24 ]--- - note: hashatron[1502] exited with preempt_count 1 - BUG: scheduling while atomic: hashatron/1502/0x10000002 - INFO: lockdep is turned off. - [...] - - Signed-off-by: Nick Bowler - Cc: stable@kernel.org [2.6.37+] - Signed-off-by: Herbert Xu - -commit fd11e153b82ad1c84ccc71ba1cfedc222465198c -Merge: 505f48b aad4564 -Author: Linus Torvalds -Date: Thu Oct 20 22:16:28 2011 +0300 - - Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc - - * git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc: - sparc: Add alignment flag to PCI expansion resources - sparc: Avoid calling sigprocmask() - sparc: Use set_current_blocked() - sparc32,leon: SRMMU MMU Table probe fix - -commit 505f48b53478d3816d1f3b001815703cfd7afa09 -Merge: 486cf46 afaef73 -Author: Linus Torvalds -Date: Thu Oct 20 22:15:20 2011 +0300 - - Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net - - * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: - fib_rules: fix unresolved_rules counting - r8169: fix wrong eee setting for rlt8111evl - r8169: fix driver shutdown WoL regression. - ehea: Change maintainer to me - pptp: pptp_rcv_core() misses pskb_may_pull() call - tproxy: copy transparent flag when creating a time wait - pptp: fix skb leak in pptp_xmit() - bonding: use local function pointer of bond->recv_probe in bond_handle_frame - smsc911x: Add support for SMSC LAN89218 - tg3: negate USE_PHYLIB flag check - netconsole: enable netconsole can make net_device refcnt incorrent - bluetooth: Properly clone LSM attributes to newly created child connections - l2tp: fix a potential skb leak in l2tp_xmit_skb() - bridge: fix hang on removal of bridge via netlink - x25: Prevent skb overreads when checking call user data - x25: Handle undersized/fragmented skbs - x25: Validate incoming call user data lengths - udplite: fast-path computation of checksum coverage - IPVS netns shutdown/startup dead-lock - netfilter: nf_conntrack: fix event flooding in GRE protocol tracker - -commit 486cf46f3f9be5f2a966016c1a8fe01e32cde09e -Author: Hugh Dickins -Date: Wed Oct 19 12:50:35 2011 -0700 - - mm: fix race between mremap and removing migration entry - - I don't usually pay much attention to the stale "? " addresses in - stack backtraces, but this lucky report from Pawel Sikora hints that - mremap's move_ptes() has inadequate locking against page migration. - - 3.0 BUG_ON(!PageLocked(p)) in migration_entry_to_page(): - kernel BUG at include/linux/swapops.h:105! - RIP: 0010:[] [] - migration_entry_wait+0x156/0x160 - [] handle_pte_fault+0xae1/0xaf0 - [] ? __pte_alloc+0x42/0x120 - [] ? do_huge_pmd_anonymous_page+0xab/0x310 - [] handle_mm_fault+0x181/0x310 - [] ? vma_adjust+0x537/0x570 - [] do_page_fault+0x11d/0x4e0 - [] ? do_mremap+0x2d5/0x570 - [] page_fault+0x1f/0x30 - - mremap's down_write of mmap_sem, together with i_mmap_mutex or lock, - and pagetable locks, were good enough before page migration (with its - requirement that every migration entry be found) came in, and enough - while migration always held mmap_sem; but not enough nowadays, when - there's memory hotremove and compaction. - - The danger is that move_ptes() lets a migration entry dodge around - behind remove_migration_pte()'s back, so it's in the old location when - looking at the new, then in the new location when looking at the old. - - Either mremap's move_ptes() must additionally take anon_vma lock(), or - migration's remove_migration_pte() must stop peeking for is_swap_entry() - before it takes pagetable lock. - - Consensus chooses the latter: we prefer to add overhead to migration - than to mremapping, which gets used by JVMs and by exec stack setup. - - Reported-and-tested-by: Paweł Sikora - Signed-off-by: Hugh Dickins - Acked-by: Andrea Arcangeli - Acked-by: Mel Gorman - Cc: stable@vger.kernel.org - Signed-off-by: Linus Torvalds - -commit aad4564498dcb0aad769a79e5e2aa9a661dfb51f -Author: Kjetil Oftedal -Date: Wed Oct 19 16:20:50 2011 -0700 - - sparc: Add alignment flag to PCI expansion resources - - Currently no type of alignment is specified for PCI expansion roms while - parsing the openfirmware tree. This causes calls to pci_map_rom() to fail. - IORESOURCE_SIZEALIGN is the default alignment used for rom resouces in - pci/probe.c, and has been verified to work with various cards on a ultra 10. - - Signed-off-By: Kjetil Oftedal - Signed-off-by: David S. Miller - -commit afaef734e5f0004916d07ecf7d86292cdd00d59b -Author: Yan, Zheng -Date: Mon Oct 17 15:20:28 2011 +0000 - - fib_rules: fix unresolved_rules counting - - we should decrease ops->unresolved_rules when deleting a unresolved rule. - - Signed-off-by: Zheng Yan - Acked-by: Eric Dumazet - Signed-off-by: David S. Miller - -commit 1b23a3e3d1b969e285c57a2d38f3739283ecfb80 -Author: hayeswang -Date: Thu Oct 13 20:14:37 2011 +0000 - - r8169: fix wrong eee setting for rlt8111evl - - Correct the wrong parameter for setting EEE for RTL8111E-VL. - - Signed-off-by: Hayes Wang - Signed-off-by: David S. Miller - -commit 649b3b8c4e8681de443b4dc9e387c3036369e02e -Author: françois romieu -Date: Fri Oct 14 00:57:45 2011 +0000 - - r8169: fix driver shutdown WoL regression. - - Due to commit 92fc43b4159b518f5baae57301f26d770b0834c9 ("r8169: modify the - flow of the hw reset."), rtl8169_hw_reset stomps during driver shutdown on - RxConfig bits which are needed for WOL on some versions of the hardware. - - As these bits were formerly set from the r81{0x, 68}_pll_power_down methods, - factor them out for use in the driver shutdown (rtl_shutdown) handler. - - I favored __rtl8169_get_wol() -hardware state indication- over - RTL_FEATURE_WOL as the latter has become a good candidate for removal. - - Signed-off-by: Francois Romieu - Cc: Hayes - Tested-by: Marc Ballarin - Signed-off-by: David S. Miller - -commit 34b1901abdf8793cd679d0e48012d3d7570f88d6 -Author: Thadeu Lima de Souza Cascardo -Date: Thu Oct 13 09:56:19 2011 +0000 - - ehea: Change maintainer to me - - Breno Leitao has passed the maintainership to me. - - Signed-off-by: Thadeu Lima de Souza Cascardo - Cc: Breno Leitao - Acked-by: Breno Leitão - Signed-off-by: David S. Miller - -commit e4fcd69c9e4e273352e0f87cabd9648606da0c3e -Merge: f91f6cf e58fced -Author: Linus Torvalds -Date: Wed Oct 19 06:44:11 2011 -0700 - - Merge branch 'v4l_for_linus' of git://linuxtv.org/mchehab/for_linus - - * 'v4l_for_linus' of git://linuxtv.org/mchehab/for_linus: - [media] videodev: fix a NULL pointer dereference in v4l2_device_release() - -commit f91f6cfd4f9ea794dc3d0bbd54cb1d29d6ef3843 -Merge: bcd5cff 5a6e848 -Author: Linus Torvalds -Date: Wed Oct 19 06:43:24 2011 -0700 - - Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux - - * 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: - drm/radeon/kms/atom: fix handling of FB scratch indices - drm/radeon/kms/DCE4.1: fix Select_CrtcSource EncodeMode setting for DP bridges (v2) - drm/radeon/kms/DCE4.1: ss is not supported on the internal pplls - drm/radeon/kms/DCE4.1: fix dig encoder to transmitter mapping - ttm: Fix error-path using an uninitialized value - -commit e58fced201ad6e6cb673f07499919c3b20792d94 -Author: Antonio Ospite -Date: Wed Oct 12 17:59:26 2011 -0300 - - [media] videodev: fix a NULL pointer dereference in v4l2_device_release() - - The change in 8280b66 does not cover the case when v4l2_dev is already - NULL, fix that. - - With a Kinect sensor, seen as an USB camera using GSPCA in this context, - a NULL pointer dereference BUG can be triggered by just unplugging the - device after the camera driver has been loaded. - - Signed-off-by: Antonio Ospite - Signed-off-by: Mauro Carvalho Chehab - -commit 5a6e8482a16e61250a9121fc9ec719ab0529e760 -Author: Alex Deucher -Date: Tue Oct 18 20:10:05 2011 -0400 - - drm/radeon/kms/atom: fix handling of FB scratch indices - - FB scratch indices are dword indices, but we were treating - them as byte indices. As such, we were getting the wrong - FB scratch data for non-0 indices. Fix the indices and - guard the indexing against indices larger than the scratch - allocation. - - Fixes memory corruption on some boards if data was written - past the end of the FB scratch array. - - Signed-off-by: Alex Deucher - Reported-by: Dave Airlie - Tested-by: Dave Airlie - Cc: stable@kernel.org - Signed-off-by: Dave Airlie - -commit 4ea2739ea89883ddf79980a8aa27d5e57093e464 -Author: Eric Dumazet -Date: Mon Oct 17 17:59:53 2011 +0000 - - pptp: pptp_rcv_core() misses pskb_may_pull() call - - e1000e uses paged frags, so any layer incorrectly pulling bytes from skb - can trigger a BUG in skb_pull() - - [951.142737] [] skb_pull+0x15/0x17 - [951.142737] [] pptp_rcv_core+0x126/0x19a [pptp] - [951.152725] [] sk_receive_skb+0x69/0x105 - [951.163558] [] pptp_rcv+0xc8/0xdc [pptp] - [951.165092] [] gre_rcv+0x62/0x75 [gre] - [951.165092] [] ip_local_deliver_finish+0x150/0x1c1 - [951.177599] [] ? ip_local_deliver_finish+0x0/0x1c1 - [951.177599] [] NF_HOOK.clone.7+0x51/0x58 - [951.177599] [] ip_local_deliver+0x51/0x55 - [951.177599] [] ip_rcv_finish+0x31a/0x33e - [951.177599] [] ? ip_rcv_finish+0x0/0x33e - [951.204898] [] NF_HOOK.clone.7+0x51/0x58 - [951.214651] [] ip_rcv+0x21b/0x246 - - pptp_rcv_core() is a nice example of a function assuming everything it - needs is available in skb head. - - Reported-by: Bradley Peterson - Signed-off-by: Eric Dumazet - Signed-off-by: David S. Miller - -commit 58af19e387d8821927e49be3f467da5e6a0aa8fd -Author: KOVACS Krisztian -Date: Tue Oct 18 10:17:35 2011 +0000 - - tproxy: copy transparent flag when creating a time wait - - The transparent socket option setting was not copied to the time wait - socket when an inet socket was being replaced by a time wait socket. This - broke the --transparent option of the socket match and may have caused - that FIN packets belonging to sockets in FIN_WAIT2 or TIME_WAIT state - were being dropped by the packet filter. - - Signed-off-by: KOVACS Krisztian - Signed-off-by: David S. Miller - -commit 8bae8bd6cb24eecad9fda3e125d36ab9c67d3fd7 -Author: Eric Dumazet -Date: Mon Oct 17 17:01:47 2011 +0000 - - pptp: fix skb leak in pptp_xmit() - - In case we cant transmit skb, we must free it - - Signed-off-by: Eric Dumazet - CC: Dmitry Kozlov - Signed-off-by: David S. Miller - -commit 4d97480b1806e883eb1c7889d4e7a87e936e06d9 -Author: Mitsuo Hayasaka -Date: Wed Oct 12 16:04:29 2011 +0000 - - bonding: use local function pointer of bond->recv_probe in bond_handle_frame - - The bond->recv_probe is called in bond_handle_frame() when - a packet is received, but bond_close() sets it to NULL. So, - a panic occurs when both functions work in parallel. - - Why this happen: - After null pointer check of bond->recv_probe, an sk_buff is - duplicated and bond->recv_probe is called in bond_handle_frame. - So, a panic occurs when bond_close() is called between the - check and call of bond->recv_probe. - - Patch: - This patch uses a local function pointer of bond->recv_probe - in bond_handle_frame(). So, it can avoid the null pointer - dereference. - - Signed-off-by: Mitsuo Hayasaka - Cc: Jay Vosburgh - Cc: Andy Gospodarek - Cc: Eric Dumazet - Cc: WANG Cong - Acked-by: Eric Dumazet - Signed-off-by: David S. Miller - -commit 28c213793c994e4aac5f669ce856b5682a549bbb -Author: Phil Edworthy -Date: Wed Oct 12 02:29:39 2011 +0000 - - smsc911x: Add support for SMSC LAN89218 - - LAN89218 is register compatible with LAN911x. - - Signed-off-by: Phil Edworthy - Signed-off-by: David S. Miller - -commit e730c82347b9dc75914da998c44c3f348965db41 -Author: Jiri Pirko -Date: Tue Oct 11 23:00:41 2011 +0000 - - tg3: negate USE_PHYLIB flag check - - USE_PHYLIB flag in tg3_remove_one() is being checked incorrectly. This - results tg3_phy_fini->phy_disconnect is never called and when tg3 module - is removed. - - In my case this resulted in panics in phy_state_machine calling function - phydev->adjust_link. - - So correct this check. - - Signed-off-by: Jiri Pirko - Acked-by: Matt Carlson - Signed-off-by: David S. Miller - -commit d5123480b1d6f7d1a5fe1a13520cef88fb5d4c84 -Author: Gao feng -Date: Tue Oct 11 16:08:11 2011 +0000 - - netconsole: enable netconsole can make net_device refcnt incorrent - - There is no check if netconsole is enabled current. - so when exec echo 1 > enabled; - the reference of net_device will increment always. - - Signed-off-by: Gao feng - Acked-by: Flavio Leitner - Signed-off-by: David S. Miller - -commit 6230c9b4f8957c8938ee4cf2d03166d3c2dc89de -Author: Paul Moore -Date: Fri Oct 7 09:40:59 2011 +0000 - - bluetooth: Properly clone LSM attributes to newly created child connections - - The Bluetooth stack has internal connection handlers for all of the various - Bluetooth protocols, and unfortunately, they are currently lacking the LSM - hooks found in the core network stack's connection handlers. I say - unfortunately, because this can cause problems for users who have have an - LSM enabled and are using certain Bluetooth devices. See one problem - report below: - - * http://bugzilla.redhat.com/show_bug.cgi?id=741703 - - In order to keep things simple at this point in time, this patch fixes the - problem by cloning the parent socket's LSM attributes to the newly created - child socket. If we decide we need a more elaborate LSM marking mechanism - for Bluetooth (I somewhat doubt this) we can always revisit this decision - in the future. - - Reported-by: James M. Cape - Signed-off-by: Paul Moore - Acked-by: James Morris - Signed-off-by: David S. Miller - -commit 835acf5da239b91edb9f7ebe36516999e156e6ee -Author: Eric Dumazet -Date: Fri Oct 7 05:35:46 2011 +0000 - - l2tp: fix a potential skb leak in l2tp_xmit_skb() - - l2tp_xmit_skb() can leak one skb if skb_cow_head() returns an error. - - Signed-off-by: Eric Dumazet - Signed-off-by: David S. Miller - -commit 1ce5cce895309862d2c35d922816adebe094fe4a -Author: stephen hemminger -Date: Thu Oct 6 11:19:41 2011 +0000 - - bridge: fix hang on removal of bridge via netlink - - Need to cleanup bridge device timers and ports when being bridge - device is being removed via netlink. - - This fixes the problem of observed when doing: - ip link add br0 type bridge - ip link set dev eth1 master br0 - ip link set br0 up - ip link del br0 - - which would cause br0 to hang in unregister_netdev because - of leftover reference count. - - Reported-by: Sridhar Samudrala - Signed-off-by: Stephen Hemminger - Acked-by: Sridhar Samudrala - Signed-off-by: David S. Miller - -commit bcd5cff7216f9b2de0a148cc355eac199dc6f1cf -Author: Peter Zijlstra -Date: Mon Oct 17 11:50:30 2011 +0200 - - cputimer: Cure lock inversion - - There's a lock inversion between the cputimer->lock and rq->lock; - notably the two callchains involved are: - - update_rlimit_cpu() - sighand->siglock - set_process_cpu_timer() - cpu_timer_sample_group() - thread_group_cputimer() - cputimer->lock - thread_group_cputime() - task_sched_runtime() - ->pi_lock - rq->lock - - scheduler_tick() - rq->lock - task_tick_fair() - update_curr() - account_group_exec() - cputimer->lock - - Where the first one is enabling a CLOCK_PROCESS_CPUTIME_ID timer, and - the second one is keeping up-to-date. - - This problem was introduced by e8abccb7193 ("posix-cpu-timers: Cure - SMP accounting oddities"). - - Cure the problem by removing the cputimer->lock and rq->lock nesting, - this leaves concurrent enablers doing duplicate work, but the time - wasted should be on the same order otherwise wasted spinning on the - lock and the greater-than assignment filter should ensure we preserve - monotonicity. - - Reported-by: Dave Jones - Reported-by: Simon Kirby - Signed-off-by: Peter Zijlstra - Cc: stable@kernel.org - Cc: Linus Torvalds - Cc: Martin Schwidefsky - Link: http://lkml.kernel.org/r/1318928713.21167.4.camel@twins - Signed-off-by: Thomas Gleixner - -commit a4863ca93ccc52a83e7fbfc068b411b7faa03805 -Author: Alex Deucher -Date: Wed Oct 12 18:49:53 2011 -0400 - - drm/radeon/kms/DCE4.1: fix Select_CrtcSource EncodeMode setting for DP bridges (v2) - - Settings in this table reflect the physical panel/connector rather - than the internal dig encoding. - - v2: fix typo for DRM_MODE_CONNECTOR_VGA case. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 09cc6506f9e234b2ead60398ebb88c4b44421a93 -Author: Alex Deucher -Date: Wed Oct 12 18:44:33 2011 -0400 - - drm/radeon/kms/DCE4.1: ss is not supported on the internal pplls - - It's handled via external clock. It should already be protected - by the external ss flag, but add an explicit check just in case. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 3a6dea31453a101bd5e9e9c89a79f4fcb6b0342e -Author: Alex Deucher -Date: Wed Oct 12 18:44:32 2011 -0400 - - drm/radeon/kms/DCE4.1: fix dig encoder to transmitter mapping - - llano has fully routeable dig encoders similar to DCE3.2 while - ontario has a hardcoded mapping similar to DCE4.0. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit ca201c096269ee2d40037fea96a59fd0695888c4 -Author: Daniel Suchy -Date: Tue Oct 18 11:09:44 2011 +0200 - - ALSA: HDA: conexant support for Lenovo T520/W520 - - This is patch for Conexant codec of Intel HDA driver, adding new quirk - for Lenovo Thinkpad T520 and W520. Conexant autodetection works fine for - T520 (similar subsystem ID is used also in W520 model) and detects more - mixer features compared to generic (fallback) Lenovo quirk with - hardcoded options in Conexant codec. - - Patch was activelly tested with Linux 3.0.4, 3.0.6 and 3.0.7 without any - problems. - - Signed-off-by: Daniel Suchy - Cc: [3.0+] - Signed-off-by: Takashi Iwai - -commit 051a8cb6550d917225ead1cd008b5966350f6d53 -Author: Takashi Iwai -Date: Tue Oct 18 10:44:05 2011 +0200 - - ALSA: hda - Add position_fix quirk for Dell Inspiron 1010 - - The previous fix for the position-buffer check gives yet another - regression on a Dell laptop. The safest fix right now is to add a - static quirk for this device (and better to apply it for stable - kernels too). - - Reported-by: Éric Piel - Cc: - Signed-off-by: Takashi Iwai - -commit e22469ca88a8f1f6fe47adbf5e5ce0906aec07cd -Author: Thomas Hellstrom -Date: Mon Oct 17 13:27:34 2011 +0200 - - ttm: Fix error-path using an uninitialized value - - Pointed out by Michel Daenzer. - - Signed-off-by: Thomas Hellstrom - Signed-off-by: Dave Airlie - -commit ae2a4583154a5b985ed4a81c6259c55bafe6d810 -Merge: 7f81e25 ae1d48b -Author: David S. Miller -Date: Mon Oct 17 19:38:03 2011 -0400 - - Merge branch 'nf' of git://1984.lsi.us.es/net - -commit 7f81e25befdfb3272345a2e775f520e1d515fa20 -Author: Matthew Daley -Date: Fri Oct 14 18:45:05 2011 +0000 - - x25: Prevent skb overreads when checking call user data - - x25_find_listener does not check that the amount of call user data given - in the skb is big enough in per-socket comparisons, hence buffer - overreads may occur. Fix this by adding a check. - - Signed-off-by: Matthew Daley - Cc: Eric Dumazet - Cc: Andrew Hendry - Cc: stable - Acked-by: Andrew Hendry - Signed-off-by: David S. Miller - -commit cb101ed2c3c7c0224d16953fe77bfb9d6c2cb9df -Author: Matthew Daley -Date: Fri Oct 14 18:45:04 2011 +0000 - - x25: Handle undersized/fragmented skbs - - There are multiple locations in the X.25 packet layer where a skb is - assumed to be of at least a certain size and that all its data is - currently available at skb->data. These assumptions are not checked, - hence buffer overreads may occur. Use pskb_may_pull to check these - minimal size assumptions and ensure that data is available at skb->data - when necessary, as well as use skb_copy_bits where needed. - - Signed-off-by: Matthew Daley - Cc: Eric Dumazet - Cc: Andrew Hendry - Cc: stable - Acked-by: Andrew Hendry - Signed-off-by: David S. Miller - -commit c7fd0d48bde943e228e9c28ce971a22d6a1744c4 -Author: Matthew Daley -Date: Fri Oct 14 18:45:03 2011 +0000 - - x25: Validate incoming call user data lengths - - X.25 call user data is being copied in its entirety from incoming messages - without consideration to the size of the destination buffers, leading to - possible buffer overflows. Validate incoming call user data lengths before - these copies are performed. - - It appears this issue was noticed some time ago, however nothing seemed to - come of it: see http://www.spinics.net/lists/linux-x25/msg00043.html and - commit 8db09f26f912f7c90c764806e804b558da520d4f. - - Signed-off-by: Matthew Daley - Acked-by: Eric Dumazet - Tested-by: Andrew Hendry - Cc: stable - Signed-off-by: David S. Miller - -commit f36c23bb9f822904dacf83a329518d0a5fde7968 -Author: Gerrit Renker -Date: Mon Oct 17 19:07:30 2011 -0400 - - udplite: fast-path computation of checksum coverage - - Commit 903ab86d195cca295379699299c5fc10beba31c7 of 1 March this year ("udp: Add - lockless transmit path") introduced a new fast TX path that broke the checksum - coverage computation of UDP-lite, which so far depended on up->len (only set - if the socket is locked and 0 in the fast path). - - Fixed by providing both fast- and slow-path computation of checksum coverage. - The latter can be removed when UDP(-lite)v6 also uses a lockless transmit path. - - Reported-by: Thomas Volkert - Signed-off-by: Gerrit Renker - Signed-off-by: David S. Miller - -commit 27f20dca01b00eac445e5193565dd185548e7e34 -Author: David S. Miller -Date: Wed Oct 12 12:27:35 2011 -0700 - - sparc: Avoid calling sigprocmask() - - Use set_current_blocked() instead. - - Signed-off-by: David S. Miller - -commit faddf598f0ba98ba329bb83acad51aea40313c2a -Author: Matt Fleming -Date: Thu Aug 11 14:57:02 2011 +0100 - - sparc: Use set_current_blocked() - - As described in e6fa16ab ("signal: sigprocmask() should do - retarget_shared_pending()") the modification of current->blocked is - incorrect as we need to check whether the signal we're about to block - is pending in the shared queue. - - Cc: Oleg Nesterov - Cc: "David S. Miller" - Signed-off-by: Matt Fleming - Signed-off-by: David S. Miller - -commit ae1d48b23d5e79efbcf0cef4f0ebb9742361af59 -Author: Hans Schillstrom -Date: Tue Oct 11 10:54:35 2011 +0900 - - IPVS netns shutdown/startup dead-lock - - ip_vs_mutext is used by both netns shutdown code and startup - and both implicit uses sk_lock-AF_INET mutex. - - cleanup CPU-1 startup CPU-2 - ip_vs_dst_event() ip_vs_genl_set_cmd() - sk_lock-AF_INET __ip_vs_mutex - sk_lock-AF_INET - __ip_vs_mutex - * DEAD LOCK * - - A new mutex placed in ip_vs netns struct called sync_mutex is added. - - Comments from Julian and Simon added. - This patch has been running for more than 3 month now and it seems to work. - - Ver. 3 - IP_VS_SO_GET_DAEMON in do_ip_vs_get_ctl protected by sync_mutex - instead of __ip_vs_mutex as sugested by Julian. - - Signed-off-by: Hans Schillstrom - Acked-by: Julian Anastasov - Signed-off-by: Simon Horman - Signed-off-by: Pablo Neira Ayuso - -commit f22ed71cd60210d2f476986c0266004e4db45f34 -Author: Daniel Hellstrom -Date: Thu Sep 8 03:11:15 2011 +0000 - - sparc32,leon: SRMMU MMU Table probe fix - - The LEON MMU Model (SRMMU) does not implement MMu Table probing - in hardware, instead it is implemented in software. However the - software implementation does not return the PTE as it should which - always results in INVALID entires and the PROM mappings are not - inherited as they should during startup. The following patch - removes the masking of the PTE. - - Signed-off-by: Daniel Hellstrom - Signed-off-by: David S. Miller - -commit 98d9ae841ad620045d653fb05764e4a899f42dbd -Author: Florian Westphal -Date: Fri Sep 30 16:38:29 2011 +0200 - - netfilter: nf_conntrack: fix event flooding in GRE protocol tracker - - GRE connections cause ctnetlink event flood because the ASSURED event - is set for every packet received. - - Reported-by: Denys Fedoryshchenko - Tested-by: Denys Fedoryshchenko - Signed-off-by: Florian Westphal - Signed-off-by: Pablo Neira Ayuso diff --git a/sources b/sources index 2a313cf69..eae38904e 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 6693d8c42055f83f5701d9b65d47208a compat-wireless-3.2-rc1-1.tar.bz2 b8b14bdfbf76cfef8e042e7d1a385fca patch-3.1.4.bz2 -cb4154af3daf6279680b808b6affc374 patch-3.1.5-rc1.bz2 +c3b84ad19528dd670288e0b0bad8fdac patch-3.1.5-rc2.bz2 From 4398b86860173c2359d672b2724fb9dece0f29d1 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 8 Dec 2011 20:27:18 -0500 Subject: [PATCH 169/487] Fix wrong link speed on some sky2 network adapters (rhbz #757839) --- kernel.spec | 7 +++++ net-sky2-88e8059-fix-link-speed.patch | 42 +++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 net-sky2-88e8059-fix-link-speed.patch diff --git a/kernel.spec b/kernel.spec index 049b00644..f7c2d7fae 100644 --- a/kernel.spec +++ b/kernel.spec @@ -800,6 +800,9 @@ Patch21220: mac80211_offchannel_rework_revert.patch Patch21225: pci-Rework-ASPM-disable-code.patch +#rhbz #757839 +Patch21230: net-sky2-88e8059-fix-link-speed.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1469,6 +1472,9 @@ ApplyPatch mac80211_offchannel_rework_revert.patch ApplyPatch pci-Rework-ASPM-disable-code.patch +#rhbz #757839 +ApplyPatch net-sky2-88e8059-fix-link-speed.patch + # END OF PATCH APPLICATIONS %endif @@ -2204,6 +2210,7 @@ fi - Linux 3.1.5-rc2 - Drop obsolete changelog, set rcrev and gitrev to 0 so they're less distracting. +- Fix wrong link speed on some sky2 network adapters (rhbz #757839) * Thu Dec 08 2011 Ben Skeggs 3.1.5-0.rc1.2 - nouveau: fix accel on GF108 and enable on GF108/GF110 diff --git a/net-sky2-88e8059-fix-link-speed.patch b/net-sky2-88e8059-fix-link-speed.patch new file mode 100644 index 000000000..61e1c75df --- /dev/null +++ b/net-sky2-88e8059-fix-link-speed.patch @@ -0,0 +1,42 @@ +commit 27d240fdae2808d727ad9ce48ec029731a457524 +Author: stephen hemminger +Date: Fri Nov 4 12:17:17 2011 +0000 + + sky2: fix regression on Yukon Optima + + [ backport to 3.1 ] + + Changes to support other Optima types, introduced an accidental + regression that caused 88E8059 to come up in 10Mbit/sec. + + The Yukon Optima supports a reverse auto-negotiation feature that + was incorrectly setup, and not needed. The feature could be used to + allow wake-on-lan at higher speeds. But doing it correctly would require + other changes to initialization. + + Reported-by: Pavel Mateja + Signed-off-by: Stephen Hemminger + Signed-off-by: David S. Miller + +diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c +index cbd026f..fdc6c39 100644 +--- a/drivers/net/sky2.c ++++ b/drivers/net/sky2.c +@@ -366,17 +366,6 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) + gm_phy_write(hw, port, PHY_MARV_FE_SPEC_2, spec); + } + } else { +- if (hw->chip_id >= CHIP_ID_YUKON_OPT) { +- u16 ctrl2 = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL_2); +- +- /* enable PHY Reverse Auto-Negotiation */ +- ctrl2 |= 1u << 13; +- +- /* Write PHY changes (SW-reset must follow) */ +- gm_phy_write(hw, port, PHY_MARV_EXT_CTRL_2, ctrl2); +- } +- +- + /* disable energy detect */ + ctrl &= ~PHY_M_PC_EN_DET_MSK; + From e501d10166db898b5041838356e4bc5459e41744 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 9 Dec 2011 12:30:53 -0500 Subject: [PATCH 170/487] Linux 3.1.5 --- kernel.spec | 5 ++++- sources | 3 +-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index f7c2d7fae..55627e736 100644 --- a/kernel.spec +++ b/kernel.spec @@ -68,7 +68,7 @@ Summary: The Linux kernel # Do we have a -stable update to apply? %define stable_update 5 # Is it a -stable RC? -%define stable_rc 2 +%define stable_rc 0 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -2206,6 +2206,9 @@ fi # and build. %changelog +* Fri Dec 09 2011 Josh Boyer 3.1.5-1 +- Linux 3.1.5 + * Thu Dec 08 2011 Chuck Ebbert 3.1.5-0.rc2.1 - Linux 3.1.5-rc2 - Drop obsolete changelog, set rcrev and gitrev to 0 so they're diff --git a/sources b/sources index eae38904e..f6c7fc19c 100644 --- a/sources +++ b/sources @@ -1,4 +1,3 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 6693d8c42055f83f5701d9b65d47208a compat-wireless-3.2-rc1-1.tar.bz2 -b8b14bdfbf76cfef8e042e7d1a385fca patch-3.1.4.bz2 -c3b84ad19528dd670288e0b0bad8fdac patch-3.1.5-rc2.bz2 +84c040bb8c4f46d351731cb0c05d9474 patch-3.1.5.bz2 From 260881f05b0ec12518d87530f52f064a60dffff5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 9 Dec 2011 16:31:35 -0500 Subject: [PATCH 171/487] spec cleanup: drop commented out patches --- kernel.spec | 12 +- rtlwifi-fix-lps_lock-deadlock.patch | 224 ------------------ ...le-memory-corruption-in-xfs_readlink.patch | 77 ------ 3 files changed, 1 insertion(+), 312 deletions(-) delete mode 100644 rtlwifi-fix-lps_lock-deadlock.patch delete mode 100644 xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch diff --git a/kernel.spec b/kernel.spec index 55627e736..4357972cf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -770,9 +770,6 @@ Patch21022: mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch Patch21030: be2net-non-member-vlan-pkts-not-received-in-promisco.patch Patch21031: benet-remove-bogus-unlikely-on-vlan-check.patch -#rhbz 749166 -Patch21050: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch - Patch21070: oom-fix-integer-overflow-of-points.patch #rhbz 728607 @@ -792,9 +789,6 @@ Patch21091: bcma-brcmsmac-compat.patch Patch21100: cciss-fix-irqf-shared.patch Patch21101: hpsa-add-irqf-shared.patch -#rhbz 755154 -Patch21200: rtlwifi-fix-lps_lock-deadlock.patch - #rhbz 731365 Patch21220: mac80211_offchannel_rework_revert.patch @@ -1305,7 +1299,6 @@ ApplyPatch linux-2.6-i386-nx-emulation.patch ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # xfs -#ApplyPatch xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch # btrfs @@ -1464,9 +1457,6 @@ ApplyPatch bcma-brcmsmac-compat.patch ApplyPatch cciss-fix-irqf-shared.patch ApplyPatch hpsa-add-irqf-shared.patch -#rhbz 755154 -#ApplyPatch rtlwifi-fix-lps_lock-deadlock.patch - #rhbz 731365 ApplyPatch mac80211_offchannel_rework_revert.patch diff --git a/rtlwifi-fix-lps_lock-deadlock.patch b/rtlwifi-fix-lps_lock-deadlock.patch deleted file mode 100644 index 4e31ee9b7..000000000 --- a/rtlwifi-fix-lps_lock-deadlock.patch +++ /dev/null @@ -1,224 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Stanislaw Gruszka -Newsgroups: gmane.linux.kernel.wireless.general -Subject: [PATCH v2] rtlwifi: fix lps_lock deadlock -Date: Mon, 28 Nov 2011 10:33:40 +0100 -Lines: 169 -Approved: news@gmane.org -Message-ID: <20111128093339.GC2372@redhat.com> -References: <1322219327-23148-1-git-send-email-sgruszka@redhat.com> - <4ECFD1BF.4070503@lwfinger.net> - <20111128092308.GB2372@redhat.com> -NNTP-Posting-Host: lo.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Trace: dough.gmane.org 1322472712 10173 80.91.229.12 (28 Nov 2011 09:31:52 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Mon, 28 Nov 2011 09:31:52 +0000 (UTC) -Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, - Chaoming Li -To: Larry Finger , - "John W. Linville" -Original-X-From: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Mon Nov 28 10:31:45 2011 -Return-path: -Envelope-to: glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1RUxYu-0002H1-AY - for glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Mon, 28 Nov 2011 10:31:44 +0100 -Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand - id S1751698Ab1K1Jbm (ORCPT - ); - Mon, 28 Nov 2011 04:31:42 -0500 -Original-Received: from mx1.redhat.com ([209.132.183.28]:62078 "EHLO mx1.redhat.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1751434Ab1K1Jbl (ORCPT ); - Mon, 28 Nov 2011 04:31:41 -0500 -Original-Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id pAS9VSak003418 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); - Mon, 28 Nov 2011 04:31:28 -0500 -Original-Received: from localhost (vpn1-4-194.ams2.redhat.com [10.36.4.194]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id pAS9VQNG013260; - Mon, 28 Nov 2011 04:31:27 -0500 -Content-Disposition: inline -In-Reply-To: <20111128092308.GB2372-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> -User-Agent: Mutt/1.5.20 (2009-12-10) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Original-Sender: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Xref: news.gmane.org gmane.linux.kernel.wireless.general:81657 -Archived-At: - -rtl_lps_leave can be called from interrupt context, so we have to -disable interrupts when taking lps_lock. - -Below is full lockdep info about deadlock: - -[ 93.815269] ================================= -[ 93.815390] [ INFO: inconsistent lock state ] -[ 93.815472] 2.6.41.1-3.offch.fc15.x86_64.debug #1 -[ 93.815556] --------------------------------- -[ 93.815635] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. -[ 93.815743] swapper/0 [HC0[0]:SC1[1]:HE1:SE0] takes: -[ 93.815832] (&(&rtlpriv->locks.lps_lock)->rlock){+.?...}, at: [] rtl_lps_leave+0x26/0x103 [rtlwifi] -[ 93.815947] {SOFTIRQ-ON-W} state was registered at: -[ 93.815947] [] __lock_acquire+0x369/0xd0c -[ 93.815947] [] lock_acquire+0xf3/0x13e -[ 93.815947] [] _raw_spin_lock+0x45/0x79 -[ 93.815947] [] rtl_swlps_rf_awake+0x5a/0x76 [rtlwifi] -[ 93.815947] [] rtl_op_config+0x12a/0x32a [rtlwifi] -[ 93.815947] [] ieee80211_hw_config+0x124/0x129 [mac80211] -[ 93.815947] [] ieee80211_dynamic_ps_disable_work+0x32/0x47 [mac80211] -[ 93.815947] [] process_one_work+0x205/0x3e7 -[ 93.815947] [] worker_thread+0xda/0x15d -[ 93.815947] [] kthread+0xa8/0xb0 -[ 93.815947] [] kernel_thread_helper+0x4/0x10 -[ 93.815947] irq event stamp: 547822 -[ 93.815947] hardirqs last enabled at (547822): [] _raw_spin_unlock_irqrestore+0x45/0x61 -[ 93.815947] hardirqs last disabled at (547821): [] _raw_spin_lock_irqsave+0x22/0x8e -[ 93.815947] softirqs last enabled at (547790): [] _local_bh_enable+0x13/0x15 -[ 93.815947] softirqs last disabled at (547791): [] call_softirq+0x1c/0x30 -[ 93.815947] -[ 93.815947] other info that might help us debug this: -[ 93.815947] Possible unsafe locking scenario: -[ 93.815947] -[ 93.815947] CPU0 -[ 93.815947] ---- -[ 93.815947] lock(&(&rtlpriv->locks.lps_lock)->rlock); -[ 93.815947] -[ 93.815947] lock(&(&rtlpriv->locks.lps_lock)->rlock); -[ 93.815947] -[ 93.815947] *** DEADLOCK *** -[ 93.815947] -[ 93.815947] no locks held by swapper/0. -[ 93.815947] -[ 93.815947] stack backtrace: -[ 93.815947] Pid: 0, comm: swapper Not tainted 2.6.41.1-3.offch.fc15.x86_64.debug #1 -[ 93.815947] Call Trace: -[ 93.815947] [] print_usage_bug+0x1e7/0x1f8 -[ 93.815947] [] ? save_stack_trace+0x2c/0x49 -[ 93.815947] [] ? print_irq_inversion_bug.part.18+0x1a0/0x1a0 -[ 93.815947] [] mark_lock+0x106/0x220 -[ 93.815947] [] __lock_acquire+0x2f5/0xd0c -[ 93.815947] [] ? native_sched_clock+0x34/0x36 -[ 93.830125] [] ? sched_clock+0x9/0xd -[ 93.830125] [] ? sched_clock_local+0x12/0x75 -[ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] -[ 93.830125] [] lock_acquire+0xf3/0x13e -[ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] -[ 93.830125] [] _raw_spin_lock+0x45/0x79 -[ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] -[ 93.830125] [] ? skb_dequeue+0x62/0x6d -[ 93.830125] [] rtl_lps_leave+0x26/0x103 [rtlwifi] -[ 93.830125] [] _rtl_pci_ips_leave_tasklet+0xe/0x10 [rtlwifi] -[ 93.830125] [] tasklet_action+0x8d/0xee -[ 93.830125] [] __do_softirq+0x112/0x25a -[ 93.830125] [] call_softirq+0x1c/0x30 -[ 93.830125] [] do_softirq+0x4b/0xa1 -[ 93.830125] [] irq_exit+0x5d/0xcf -[ 93.830125] [] do_IRQ+0x8e/0xa5 -[ 93.830125] [] common_interrupt+0x73/0x73 -[ 93.830125] [] ? trace_hardirqs_off+0xd/0xf -[ 93.830125] [] ? intel_idle+0xe5/0x10c -[ 93.830125] [] ? intel_idle+0xe1/0x10c -[ 93.830125] [] cpuidle_idle_call+0x11c/0x1fe -[ 93.830125] [] cpu_idle+0xab/0x101 -[ 93.830125] [] rest_init+0xd7/0xde -[ 93.830125] [] ? csum_partial_copy_generic+0x16c/0x16c -[ 93.830125] [] start_kernel+0x3dd/0x3ea -[ 93.830125] [] x86_64_start_reservations+0xaf/0xb3 -[ 93.830125] [] ? early_idt_handlers+0x140/0x140 -[ 93.830125] [] x86_64_start_kernel+0x102/0x111 - -Resolves: -https://bugzilla.redhat.com/show_bug.cgi?id=755154 - -Reported-by: vjain02-9geRo0GdX4mblYp+tMVdN4dd74u8MsAO@public.gmane.org -Reported-and-tested-by: Oliver Paukstadt -Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Acked-by: Larry Finger -Signed-off-by: Stanislaw Gruszka ---- -v1 -> v2: add bug report reference - - drivers/net/wireless/rtlwifi/ps.c | 17 +++++++++-------- - 1 files changed, 9 insertions(+), 8 deletions(-) - -diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c -index db52628..55c8e50 100644 ---- a/drivers/net/wireless/rtlwifi/ps.c -+++ b/drivers/net/wireless/rtlwifi/ps.c -@@ -395,7 +395,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) - if (mac->link_state != MAC80211_LINKED) - return; - -- spin_lock(&rtlpriv->locks.lps_lock); -+ spin_lock_irq(&rtlpriv->locks.lps_lock); - - /* Idle for a while if we connect to AP a while ago. */ - if (mac->cnt_after_linked >= 2) { -@@ -407,7 +407,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) - } - } - -- spin_unlock(&rtlpriv->locks.lps_lock); -+ spin_unlock_irq(&rtlpriv->locks.lps_lock); - } - - /*Leave the leisure power save mode.*/ -@@ -416,8 +416,9 @@ void rtl_lps_leave(struct ieee80211_hw *hw) - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ unsigned long flags; - -- spin_lock(&rtlpriv->locks.lps_lock); -+ spin_lock_irqsave(&rtlpriv->locks.lps_lock, flags); - - if (ppsc->fwctrl_lps) { - if (ppsc->dot11_psmode != EACTIVE) { -@@ -438,7 +439,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw) - rtl_lps_set_psmode(hw, EACTIVE); - } - } -- spin_unlock(&rtlpriv->locks.lps_lock); -+ spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flags); - } - - /* For sw LPS*/ -@@ -539,9 +540,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw) - RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); - } - -- spin_lock(&rtlpriv->locks.lps_lock); -+ spin_lock_irq(&rtlpriv->locks.lps_lock); - rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS); -- spin_unlock(&rtlpriv->locks.lps_lock); -+ spin_unlock_irq(&rtlpriv->locks.lps_lock); - } - - void rtl_swlps_rfon_wq_callback(void *data) -@@ -574,9 +575,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw) - if (rtlpriv->link_info.busytraffic) - return; - -- spin_lock(&rtlpriv->locks.lps_lock); -+ spin_lock_irq(&rtlpriv->locks.lps_lock); - rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS); -- spin_unlock(&rtlpriv->locks.lps_lock); -+ spin_unlock_irq(&rtlpriv->locks.lps_lock); - - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && - !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { --- -1.7.1 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - diff --git a/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch b/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch deleted file mode 100644 index 9e810dba8..000000000 --- a/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch +++ /dev/null @@ -1,77 +0,0 @@ -X-Spam-Checker-Version: SpamAssassin 3.4.0-r929098 (2010-03-30) on oss.sgi.com -X-Spam-Level: -X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,J_CHICKENPOX_64 - autolearn=no version=3.4.0-r929098 -Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) - by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id p9I1KBVD036341 - for ; Mon, 17 Oct 2011 20:20:11 -0500 -X-ASG-Debug-ID: 1318901280-3911029d0000-NocioJ -X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi -Received: from hades.usersys.redhat.com (localhost [127.0.0.1]) - by cuda.sgi.com (Spam Firewall) with ESMTP id B9D1DF75F0A - for ; Mon, 17 Oct 2011 18:28:01 -0700 (PDT) -Received: from hades.usersys.redhat.com ([187.60.101.4]) by cuda.sgi.com with ESMTP id 81CuyNdYBqrtvtnD for ; Mon, 17 Oct 2011 18:28:01 -0700 (PDT) -Received: by hades.usersys.redhat.com (Postfix, from userid 500) - id 5B763E089B; Tue, 18 Oct 2011 02:18:59 -0200 (BRST) -From: Carlos Maiolino -To: xfs@oss.sgi.com -Cc: Carlos Maiolino -X-ASG-Orig-Subj: [PATCH] Fix possible memory corruption in xfs_readlink -Subject: [PATCH] Fix possible memory corruption in xfs_readlink -Date: Tue, 18 Oct 2011 02:18:58 -0200 -Message-Id: <1318911538-9174-1-git-send-email-cmaiolino@redhat.com> -X-Mailer: git-send-email 1.7.6.2 -X-Barracuda-Connect: UNKNOWN[187.60.101.4] -X-Barracuda-Start-Time: 1318901282 -X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 -X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com -X-Barracuda-Spam-Score: -1.42 -X-Barracuda-Spam-Status: No, SCORE=-1.42 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=BSF_SC5_MJ1963, RDNS_NONE -X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.2.77645 - Rule breakdown below - pts rule name description - ---- ---------------------- -------------------------------------------------- - 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS - 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 -X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com -X-Virus-Status: Clean - -Fixes a possible memory corruption when the link is larger than -MAXPATHLEN and XFS_DEBUG is not enabled. This also remove the -S_ISLNK assert, since the inode mode is checked previously in -xfs_readlink_by_handle() and via VFS. - -Signed-off-by: Carlos Maiolino ---- - fs/xfs/xfs_vnodeops.c | 11 ++++++++--- - 1 files changed, 8 insertions(+), 3 deletions(-) - -diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c -index 51fc429..c3288be 100644 ---- a/fs/xfs/xfs_vnodeops.c -+++ b/fs/xfs/xfs_vnodeops.c -@@ -123,13 +123,18 @@ xfs_readlink( - - xfs_ilock(ip, XFS_ILOCK_SHARED); - -- ASSERT(S_ISLNK(ip->i_d.di_mode)); -- ASSERT(ip->i_d.di_size <= MAXPATHLEN); -- - pathlen = ip->i_d.di_size; - if (!pathlen) - goto out; - -+ if (pathlen > MAXPATHLEN) { -+ xfs_alert(mp, "%s: inode (%llu) symlink length (%d) too long", -+ __func__, (unsigned long long)ip->i_ino, pathlen); -+ ASSERT(0); -+ return XFS_ERROR(EFSCORRUPTED); -+ } -+ -+ - if (ip->i_df.if_flags & XFS_IFINLINE) { - memcpy(link, ip->i_df.if_u1.if_data, pathlen); - link[pathlen] = '\0'; --- -1.7.6.2 - From 3a228cfea459b489ad387fa1a6953b0b84f2814c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 8 Dec 2011 10:14:55 -0500 Subject: [PATCH 172/487] Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735) --- kernel.spec | 9 ++ nfs-client-freezer.patch | 299 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 308 insertions(+) create mode 100644 nfs-client-freezer.patch diff --git a/kernel.spec b/kernel.spec index 4357972cf..ba4599c55 100644 --- a/kernel.spec +++ b/kernel.spec @@ -797,6 +797,9 @@ Patch21225: pci-Rework-ASPM-disable-code.patch #rhbz #757839 Patch21230: net-sky2-88e8059-fix-link-speed.patch +#rhbz 717735 +Patch21045: nfs-client-freezer.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1465,6 +1468,9 @@ ApplyPatch pci-Rework-ASPM-disable-code.patch #rhbz #757839 ApplyPatch net-sky2-88e8059-fix-link-speed.patch +#rhbz 717735 +ApplyPatch nfs-client-freezer.patch + # END OF PATCH APPLICATIONS %endif @@ -2196,6 +2202,9 @@ fi # and build. %changelog +* Mon Dec 12 2011 Josh Boyer +- Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735) + * Fri Dec 09 2011 Josh Boyer 3.1.5-1 - Linux 3.1.5 diff --git a/nfs-client-freezer.patch b/nfs-client-freezer.patch new file mode 100644 index 000000000..6b4d34d8a --- /dev/null +++ b/nfs-client-freezer.patch @@ -0,0 +1,299 @@ +@@ -, +, @@ + fs/cifs/transport.c | 3 ++- + include/linux/freezer.h | 19 +++++++++++++++++-- + 2 files changed, 19 insertions(+), 3 deletions(-) +--- a/fs/cifs/transport.c ++++ a/fs/cifs/transport.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -324,7 +325,7 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) + { + int error; + +- error = wait_event_killable(server->response_q, ++ error = wait_event_freezekillable(server->response_q, + midQ->midState != MID_REQUEST_SUBMITTED); + if (error < 0) + return -ERESTARTSYS; +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -134,10 +134,25 @@ static inline void set_freezable_with_signal(void) + } + + /* +- * Freezer-friendly wrappers around wait_event_interruptible() and +- * wait_event_interruptible_timeout(), originally defined in ++ * Freezer-friendly wrappers around wait_event_interruptible(), ++ * wait_event_killable() and wait_event_interruptible_timeout(), originally ++ * defined in + */ + ++#define wait_event_freezekillable(wq, condition) \ ++({ \ ++ int __retval; \ ++ do { \ ++ __retval = wait_event_killable(wq, \ ++ (condition) || freezing(current)); \ ++ if (__retval && !freezing(current)) \ ++ break; \ ++ else if (!(condition)) \ ++ __retval = -ERESTARTSYS; \ ++ } while (try_to_freeze()); \ ++ __retval; \ ++}) ++ + #define wait_event_freezable(wq, condition) \ + ({ \ + int __retval; \ + include/linux/freezer.h | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -143,7 +143,7 @@ static inline void set_freezable_with_signal(void) + ({ \ + int __retval; \ + do { \ +- __retval = wait_event_killable(wq, \ ++ __retval = wait_event_killable(wq, \ + (condition) || freezing(current)); \ + if (__retval && !freezing(current)) \ + break; \ + include/linux/freezer.h | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -203,6 +203,9 @@ static inline void set_freezable_with_signal(void) {} + #define wait_event_freezable_timeout(wq, condition, timeout) \ + wait_event_interruptible_timeout(wq, condition, timeout) + ++#define wait_event_freezekillable(wq, condition) \ ++ wait_event_killable(wq, condition) ++ + #endif /* !CONFIG_FREEZER */ + + #endif /* FREEZER_H_INCLUDED */ + description on Rafael's request.] + include/linux/freezer.h | 11 +++-------- + 1 files changed, 3 insertions(+), 8 deletions(-) +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -142,14 +142,9 @@ static inline void set_freezable_with_signal(void) + #define wait_event_freezekillable(wq, condition) \ + ({ \ + int __retval; \ +- do { \ +- __retval = wait_event_killable(wq, \ +- (condition) || freezing(current)); \ +- if (__retval && !freezing(current)) \ +- break; \ +- else if (!(condition)) \ +- __retval = -ERESTARTSYS; \ +- } while (try_to_freeze()); \ ++ freezer_do_not_count(); \ ++ __retval = wait_event_killable(wq, (condition)); \ ++ freezer_count(); \ + __retval; \ + }) + + fs/nfs/inode.c | 3 ++- + fs/nfs/nfs3proc.c | 3 ++- + fs/nfs/nfs4proc.c | 5 +++-- + fs/nfs/proc.c | 3 ++- + include/linux/freezer.h | 28 ++++++++++++++++++++++++++++ + net/sunrpc/sched.c | 3 ++- + 6 files changed, 39 insertions(+), 6 deletions(-) +--- a/fs/nfs/inode.c ++++ a/fs/nfs/inode.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -77,7 +78,7 @@ int nfs_wait_bit_killable(void *word) + { + if (fatal_signal_pending(current)) + return -ERESTARTSYS; +- schedule(); ++ freezable_schedule(); + return 0; + } + +--- a/fs/nfs/nfs3proc.c ++++ a/fs/nfs/nfs3proc.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + #include "iostat.h" + #include "internal.h" +@@ -32,7 +33,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) + res = rpc_call_sync(clnt, msg, flags); + if (res != -EJUKEBOX && res != -EKEYEXPIRED) + break; +- schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); ++ freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); + res = -ERESTARTSYS; + } while (!fatal_signal_pending(current)); + return res; +--- a/fs/nfs/nfs4proc.c ++++ a/fs/nfs/nfs4proc.c +@@ -53,6 +53,7 @@ + #include + #include + #include ++#include + + #include "nfs4_fs.h" + #include "delegation.h" +@@ -244,7 +245,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) + *timeout = NFS4_POLL_RETRY_MIN; + if (*timeout > NFS4_POLL_RETRY_MAX) + *timeout = NFS4_POLL_RETRY_MAX; +- schedule_timeout_killable(*timeout); ++ freezable_schedule_timeout_killable(*timeout); + if (fatal_signal_pending(current)) + res = -ERESTARTSYS; + *timeout <<= 1; +@@ -3970,7 +3971,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 + static unsigned long + nfs4_set_lock_task_retry(unsigned long timeout) + { +- schedule_timeout_killable(timeout); ++ freezable_schedule_timeout_killable(timeout); + timeout <<= 1; + if (timeout > NFS4_LOCK_MAXTIMEOUT) + return NFS4_LOCK_MAXTIMEOUT; +--- a/fs/nfs/proc.c ++++ a/fs/nfs/proc.c +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include + #include "internal.h" + + #define NFSDBG_FACILITY NFSDBG_PROC +@@ -59,7 +60,7 @@ nfs_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) + res = rpc_call_sync(clnt, msg, flags); + if (res != -EKEYEXPIRED) + break; +- schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); ++ freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); + res = -ERESTARTSYS; + } while (!fatal_signal_pending(current)); + return res; +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -134,6 +134,29 @@ static inline void set_freezable_with_signal(void) + } + + /* ++ * These macros are intended to be used whenever you want allow a task that's ++ * sleeping in TASK_UNINTERRUPTIBLE or TASK_KILLABLE state to be frozen. Note ++ * that neither return any clear indication of whether a freeze event happened ++ * while in this function. ++ */ ++ ++/* Like schedule(), but should not block the freezer. */ ++#define freezable_schedule() \ ++({ \ ++ freezer_do_not_count(); \ ++ schedule(); \ ++ freezer_count(); \ ++}) ++ ++/* Like schedule_timeout_killable(), but should not block the freezer. */ ++#define freezable_schedule_timeout_killable(timeout) \ ++({ \ ++ freezer_do_not_count(); \ ++ schedule_timeout_killable(timeout); \ ++ freezer_count(); \ ++}) ++ ++/* + * Freezer-friendly wrappers around wait_event_interruptible(), + * wait_event_killable() and wait_event_interruptible_timeout(), originally + * defined in +@@ -192,6 +215,11 @@ static inline int freezer_should_skip(struct task_struct *p) { return 0; } + static inline void set_freezable(void) {} + static inline void set_freezable_with_signal(void) {} + ++#define freezable_schedule() schedule() ++ ++#define freezable_schedule_timeout_killable(timeout) \ ++ schedule_timeout_killable(timeout) ++ + #define wait_event_freezable(wq, condition) \ + wait_event_interruptible(wq, condition) + +--- a/net/sunrpc/sched.c ++++ a/net/sunrpc/sched.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #include + +@@ -231,7 +232,7 @@ static int rpc_wait_bit_killable(void *word) + { + if (fatal_signal_pending(current)) + return -ERESTARTSYS; +- schedule(); ++ freezable_schedule(); + return 0; + } + + include/linux/freezer.h | 21 ++++++++++++++++++--- + 1 files changed, 18 insertions(+), 3 deletions(-) +--- a/include/linux/freezer.h ++++ a/include/linux/freezer.h +@@ -140,18 +140,33 @@ static inline void set_freezable_with_signal(void) + * while in this function. + */ + +-/* Like schedule(), but should not block the freezer. */ ++/* ++ * Like schedule(), but should not block the freezer. It may return immediately ++ * if it ends up racing with the freezer. Callers must be able to deal with ++ * spurious wakeups. ++ */ + #define freezable_schedule() \ + ({ \ + freezer_do_not_count(); \ +- schedule(); \ ++ if (!try_to_freeze()) \ ++ schedule(); \ + freezer_count(); \ + }) + +-/* Like schedule_timeout_killable(), but should not block the freezer. */ ++/* ++ * Like schedule_timeout_killable(), but should not block the freezer. It may ++ * end up returning immediately if it ends up racing with the freezer. Callers ++ * must be able to deal with the loose wakeup timing that can occur when the ++ * freezer races in. When that occurs, this function will return the timeout ++ * value instead of 0. ++ */ + #define freezable_schedule_timeout_killable(timeout) \ + ({ \ + freezer_do_not_count(); \ ++ if (try_to_freeze()) { \ ++ freezer_count(); \ ++ return timeout; \ ++ } \ + schedule_timeout_killable(timeout); \ + freezer_count(); \ + }) From 002cf4b18143789929813adf9bc420cedd82eb48 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 2 Dec 2011 15:57:37 -0500 Subject: [PATCH 173/487] Backport ALPS touchpad patches from input/next branch (rhbz #590880) --- alps.patch | 1990 +++++++++++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 7 + 2 files changed, 1997 insertions(+) create mode 100644 alps.patch diff --git a/alps.patch b/alps.patch new file mode 100644 index 000000000..e76dc5477 --- /dev/null +++ b/alps.patch @@ -0,0 +1,1990 @@ +From ed11aa781242216bc72f1cd7d757a4f40be10329 Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Mon, 7 Nov 2011 19:53:15 -0800 +Subject: [PATCH 1/7] Input: ALPS - move protocol information to Documentation + +In preparation for new protocol support, move the protocol +information currently documented in alps.c to +Documentation/input/alps.txt, where it can be expanded without +cluttering up the driver. + +Signed-off-by: Seth Forshee +Acked-by: Chase Douglas +Signed-off-by: Dmitry Torokhov +--- + Documentation/input/alps.txt | 75 ++++++++++++++++++++++++++++++++++++++++++ + drivers/input/mouse/alps.c | 37 +-------------------- + 2 files changed, 76 insertions(+), 36 deletions(-) + create mode 100644 Documentation/input/alps.txt + +diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt +new file mode 100644 +index 0000000..ab5478f +--- /dev/null ++++ b/Documentation/input/alps.txt +@@ -0,0 +1,75 @@ ++ALPS Touchpad Protocol ++---------------------- ++ ++Introduction ++------------ ++ ++Currently the ALPS touchpad driver supports two protocol versions in use by ++ALPS touchpads, the "old" and "new" protocol versions. Fundamentally these ++differ only in the format of their event packets (in reality many features may ++be found on new protocol devices that aren't found on the old protocol ++devices, but these are handled transparently as feature differences rather ++than protocol differences). ++ ++Detection ++--------- ++ ++All ALPS touchpads should respond to the "E6 report" command sequence: ++E8-E6-E6-E6-E9. An ALPS touchpad should respond with either 00-00-0A or ++00-00-64. ++ ++If the E6 report is successful, the touchpad model is identified using the "E7 ++report" sequence: E8-E7-E7-E7-E9. The response is the model signature and is ++matched against known models in the alps_model_data_array. ++ ++Packet Format ++------------- ++ ++In the following tables, the following notation us used. ++ ++ CAPITALS = stick, miniscules = touchpad ++ ++?'s can have different meanings on different models, such as wheel rotation, ++extra buttons, stick buttons on a dualpoint, etc. ++ ++PS/2 packet format ++------------------ ++ ++ byte 0: 0 0 YSGN XSGN 1 M R L ++ byte 1: X7 X6 X5 X4 X3 X2 X1 X0 ++ byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 ++ ++Note that the device never signals overflow condition. ++ ++ALPS Absolute Mode - Old Format ++------------------------------- ++ ++ byte 0: 1 0 0 0 1 x9 x8 x7 ++ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 ++ byte 2: 0 ? ? l r ? fin ges ++ byte 3: 0 ? ? ? ? y9 y8 y7 ++ byte 4: 0 y6 y5 y4 y3 y2 y1 y0 ++ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 ++ ++ALPS Absolute Mode - New Format ++------------------------------- ++ ++ byte 0: 1 ? ? ? 1 ? ? ? ++ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 ++ byte 2: 0 x10 x9 x8 x7 ? fin ges ++ byte 3: 0 y9 y8 y7 1 M R L ++ byte 4: 0 y6 y5 y4 y3 y2 y1 y0 ++ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 ++ ++Dualpoint device -- interleaved packet format ++--------------------------------------------- ++ ++ byte 0: 1 1 0 0 1 1 1 1 ++ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 ++ byte 2: 0 x10 x9 x8 x7 0 fin ges ++ byte 3: 0 0 YSGN XSGN 1 1 1 1 ++ byte 4: X7 X6 X5 X4 X3 X2 X1 X0 ++ byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 ++ byte 6: 0 y9 y8 y7 1 m r l ++ byte 7: 0 y6 y5 y4 y3 y2 y1 y0 ++ byte 8: 0 z6 z5 z4 z3 z2 z1 z0 +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 99d5876..ad15e7c 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -74,42 +74,7 @@ static const struct alps_model_info alps_model_data[] = { + * isn't valid per PS/2 spec. + */ + +-/* +- * PS/2 packet format +- * +- * byte 0: 0 0 YSGN XSGN 1 M R L +- * byte 1: X7 X6 X5 X4 X3 X2 X1 X0 +- * byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 +- * +- * Note that the device never signals overflow condition. +- * +- * ALPS absolute Mode - new format +- * +- * byte 0: 1 ? ? ? 1 ? ? ? +- * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 +- * byte 2: 0 x10 x9 x8 x7 ? fin ges +- * byte 3: 0 y9 y8 y7 1 M R L +- * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 +- * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 +- * +- * Dualpoint device -- interleaved packet format +- * +- * byte 0: 1 1 0 0 1 1 1 1 +- * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 +- * byte 2: 0 x10 x9 x8 x7 0 fin ges +- * byte 3: 0 0 YSGN XSGN 1 1 1 1 +- * byte 4: X7 X6 X5 X4 X3 X2 X1 X0 +- * byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 +- * byte 6: 0 y9 y8 y7 1 m r l +- * byte 7: 0 y6 y5 y4 y3 y2 y1 y0 +- * byte 8: 0 z6 z5 z4 z3 z2 z1 z0 +- * +- * CAPITALS = stick, miniscules = touchpad +- * +- * ?'s can have different meanings on different models, +- * such as wheel rotation, extra buttons, stick buttons +- * on a dualpoint, etc. +- */ ++/* Packet formats are described in Documentation/input/alps.txt */ + + static bool alps_is_valid_first_byte(const struct alps_model_info *model, + unsigned char data) +-- +1.7.7.3 + + +From 27b8ed51ee660e9a59cf325d6339f38b216fbb31 Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Mon, 7 Nov 2011 19:53:24 -0800 +Subject: [PATCH 2/7] Input: ALPS - add protocol version field in + alps_model_info + +In preparation for adding support for more ALPS protocol versions, +add a field for the protocol version to the model info instead of +using a field in the flags. OLDPROTO and !OLDPROTO are now called +version 1 and version 2, repsectively. + +Signed-off-by: Seth Forshee +Acked-by: Chase Douglas +Signed-off-by: Dmitry Torokhov + +Conflicts: + + drivers/input/mouse/alps.c +--- + drivers/input/mouse/alps.c | 47 +++++++++++++++++++++---------------------- + drivers/input/mouse/alps.h | 4 +++ + 2 files changed, 27 insertions(+), 24 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index ad15e7c..572cb21 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -30,7 +30,6 @@ + #define dbg(format, arg...) do {} while (0) + #endif + +-#define ALPS_OLDPROTO 0x01 /* old style input */ + #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ + #define ALPS_PASS 0x04 /* device has a pass-through port */ + +@@ -42,30 +41,30 @@ + 6-byte ALPS packet */ + + static const struct alps_model_info alps_model_data[] = { +- { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ +- { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ +- { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, +- { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, +- { { 0x60, 0x03, 0xc8 }, 0xf8, 0xf8, 0 }, /* HP ze1115 */ +- { { 0x63, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, +- { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, +- { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ +- { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ +- { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ +- { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, +- { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ +- { { 0x73, 0x00, 0x0a }, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ +- { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, +- { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ +- { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ +- { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, +- { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ ++ { { 0x32, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ ++ { { 0x33, 0x02, 0x0a }, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ ++ { { 0x53, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x53, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x60, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ ++ { { 0x63, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x63, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x63, 0x02, 0x28 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ ++ { { 0x63, 0x02, 0x3c }, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ ++ { { 0x63, 0x02, 0x50 }, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ ++ { { 0x63, 0x02, 0x64 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x63, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ ++ { { 0x73, 0x00, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ ++ { { 0x73, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x73, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ ++ { { 0x20, 0x02, 0x0e }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ ++ { { 0x22, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, ++ { { 0x22, 0x02, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ + /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ +- { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ++ { { 0x62, 0x02, 0x14 }, ALPS_PROTO_V2, 0xcf, 0xcf, + ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, +- { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ +- { { 0x52, 0x01, 0x14 }, 0xff, 0xff, +- ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ ++ { { 0x73, 0x02, 0x50 }, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ ++ { { 0x52, 0x01, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, ++ ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ + }; + + /* +@@ -119,7 +118,7 @@ static void alps_process_packet(struct psmouse *psmouse) + int x, y, z, ges, fin, left, right, middle; + int back = 0, forward = 0; + +- if (model->flags & ALPS_OLDPROTO) { ++ if (model->proto_version == ALPS_PROTO_V1) { + left = packet[2] & 0x10; + right = packet[2] & 0x08; + middle = 0; +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index 904ed8b..4ce9bba 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -12,8 +12,12 @@ + #ifndef _ALPS_H + #define _ALPS_H + ++#define ALPS_PROTO_V1 0 ++#define ALPS_PROTO_V2 1 ++ + struct alps_model_info { + unsigned char signature[3]; ++ unsigned char proto_version; + unsigned char byte0, mask0; + unsigned char flags; + }; +-- +1.7.7.3 + + +From dfab9d3e073f2a58e4ba3837a726e9a0e33ea5df Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Mon, 7 Nov 2011 19:53:30 -0800 +Subject: [PATCH 3/7] Input: ALPS - remove assumptions about packet size + +In preparation for version 4 protocol support, which has 8-byte +data packets, remove all hard-coded assumptions about packet size +and use psmouse->pktsize instead. + +Signed-off-by: Seth Forshee +Acked-by: Chase Douglas +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 10 +++++----- + 1 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 572cb21..f699698 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -315,7 +315,7 @@ static void alps_flush_packet(unsigned long data) + + serio_pause_rx(psmouse->ps2dev.serio); + +- if (psmouse->pktcnt == 6) { ++ if (psmouse->pktcnt == psmouse->pktsize) { + + /* + * We did not any more data in reasonable amount of time. +@@ -365,15 +365,15 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) + return PSMOUSE_BAD_DATA; + } + +- /* Bytes 2 - 6 should have 0 in the highest bit */ +- if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && ++ /* Bytes 2 - pktsize should have 0 in the highest bit */ ++ if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && + (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { + dbg("refusing packet[%i] = %x\n", + psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]); + return PSMOUSE_BAD_DATA; + } + +- if (psmouse->pktcnt == 6) { ++ if (psmouse->pktcnt == psmouse->pktsize) { + alps_process_packet(psmouse); + return PSMOUSE_FULL_PACKET; + } +@@ -531,7 +531,7 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable) + static int alps_poll(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; +- unsigned char buf[6]; ++ unsigned char buf[sizeof(psmouse->packet)]; + bool poll_failed; + + if (priv->i->flags & ALPS_PASS) +-- +1.7.7.3 + + +From 35f17ba201d7a8b8adc59811effafe62a331fd9e Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Mon, 7 Nov 2011 19:53:36 -0800 +Subject: [PATCH 4/7] Input: ALPS - add support for protocol versions 3 and 4 + +This patch adds support for two ALPS touchpad protocols not +supported currently by the driver, which I am arbitrarily naming +version 3 and version 4. Support is single-touch only at this time, +although both protocols are capable of limited multitouch support. + +Thanks to Andrew Skalski, who did the initial reverse-engineering +of the v3 protocol. + +Signed-off-by: Seth Forshee +Acked-by: Chase Douglas +Signed-off-by: Dmitry Torokhov + +Conflicts: + + drivers/input/mouse/alps.c +--- + drivers/input/mouse/alps.c | 790 +++++++++++++++++++++++++++++++++++++++-- + drivers/input/mouse/alps.h | 14 + + drivers/input/mouse/psmouse.h | 1 + + 3 files changed, 767 insertions(+), 38 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index f699698..b2bc8ca 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -30,6 +30,49 @@ + #define dbg(format, arg...) do {} while (0) + #endif + ++/* ++ * Definitions for ALPS version 3 and 4 command mode protocol ++ */ ++#define ALPS_CMD_NIBBLE_10 0x01f2 ++ ++static const struct alps_nibble_commands alps_v3_nibble_commands[] = { ++ { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */ ++ { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ ++ { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ ++ { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ ++ { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ ++ { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ ++ { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ ++ { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ ++ { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ ++ { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ ++ { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ ++ { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ ++ { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ ++ { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ ++ { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ ++ { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ ++}; ++ ++static const struct alps_nibble_commands alps_v4_nibble_commands[] = { ++ { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */ ++ { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ ++ { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ ++ { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ ++ { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ ++ { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ ++ { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ ++ { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ ++ { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ ++ { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ ++ { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ ++ { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ ++ { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ ++ { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ ++ { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ ++ { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ ++}; ++ + #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ + #define ALPS_PASS 0x04 /* device has a pass-through port */ + +@@ -41,30 +84,33 @@ + 6-byte ALPS packet */ + + static const struct alps_model_info alps_model_data[] = { +- { { 0x32, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ +- { { 0x33, 0x02, 0x0a }, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ +- { { 0x53, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, +- { { 0x53, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, +- { { 0x60, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ +- { { 0x63, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, +- { { 0x63, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, +- { { 0x63, 0x02, 0x28 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ +- { { 0x63, 0x02, 0x3c }, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ +- { { 0x63, 0x02, 0x50 }, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ +- { { 0x63, 0x02, 0x64 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, +- { { 0x63, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ +- { { 0x73, 0x00, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ +- { { 0x73, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, +- { { 0x73, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ +- { { 0x20, 0x02, 0x0e }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ +- { { 0x22, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, +- { { 0x22, 0x02, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ ++ { { 0x32, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ ++ { { 0x33, 0x02, 0x0a }, 0x00, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ ++ { { 0x53, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x53, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x60, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ ++ { { 0x63, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x63, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x63, 0x02, 0x28 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ ++ { { 0x63, 0x02, 0x3c }, 0x00, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ ++ { { 0x63, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ ++ { { 0x63, 0x02, 0x64 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x63, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ ++ { { 0x73, 0x00, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ ++ { { 0x73, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, ++ { { 0x73, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ ++ { { 0x20, 0x02, 0x0e }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ ++ { { 0x22, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, ++ { { 0x22, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ + /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ +- { { 0x62, 0x02, 0x14 }, ALPS_PROTO_V2, 0xcf, 0xcf, ++ { { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, + ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, +- { { 0x73, 0x02, 0x50 }, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ +- { { 0x52, 0x01, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, +- ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ ++ { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ ++ { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, ++ ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ ++ { { 0x73, 0x02, 0x64 }, 0x9b, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, ++ { { 0x73, 0x02, 0x64 }, 0x9d, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, ++ { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, + }; + + /* +@@ -108,7 +154,7 @@ static void alps_report_buttons(struct psmouse *psmouse, + input_sync(dev2); + } + +-static void alps_process_packet(struct psmouse *psmouse) ++static void alps_process_packet_v1_v2(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; + const struct alps_model_info *model = priv->i; +@@ -210,6 +256,224 @@ static void alps_process_packet(struct psmouse *psmouse) + input_sync(dev); + } + ++static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ unsigned char *packet = psmouse->packet; ++ struct input_dev *dev = priv->dev2; ++ int x, y, z, left, right, middle; ++ ++ /* Sanity check packet */ ++ if (!(packet[0] & 0x40)) { ++ psmouse_dbg(psmouse, "Bad trackstick packet, discarding\n"); ++ return; ++ } ++ ++ /* ++ * There's a special packet that seems to indicate the end ++ * of a stream of trackstick data. Filter these out. ++ */ ++ if (packet[1] == 0x7f && packet[2] == 0x7f && packet[4] == 0x7f) ++ return; ++ ++ x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f)); ++ y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f)); ++ z = (packet[4] & 0x7c) >> 2; ++ ++ /* ++ * The x and y values tend to be quite large, and when used ++ * alone the trackstick is difficult to use. Scale them down ++ * to compensate. ++ */ ++ x /= 8; ++ y /= 8; ++ ++ input_report_rel(dev, REL_X, x); ++ input_report_rel(dev, REL_Y, -y); ++ ++ /* ++ * Most ALPS models report the trackstick buttons in the touchpad ++ * packets, but a few report them here. No reliable way has been ++ * found to differentiate between the models upfront, so we enable ++ * the quirk in response to seeing a button press in the trackstick ++ * packet. ++ */ ++ left = packet[3] & 0x01; ++ right = packet[3] & 0x02; ++ middle = packet[3] & 0x04; ++ ++ if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) && ++ (left || right || middle)) ++ priv->quirks |= ALPS_QUIRK_TRACKSTICK_BUTTONS; ++ ++ if (priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) { ++ input_report_key(dev, BTN_LEFT, left); ++ input_report_key(dev, BTN_RIGHT, right); ++ input_report_key(dev, BTN_MIDDLE, middle); ++ } ++ ++ input_sync(dev); ++ return; ++} ++ ++static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ unsigned char *packet = psmouse->packet; ++ struct input_dev *dev = psmouse->dev; ++ struct input_dev *dev2 = priv->dev2; ++ int x, y, z; ++ int left, right, middle; ++ ++ /* ++ * There's no single feature of touchpad position and bitmap ++ * packets that can be used to distinguish between them. We ++ * rely on the fact that a bitmap packet should always follow ++ * a position packet with bit 6 of packet[4] set. ++ */ ++ if (priv->multi_packet) { ++ priv->multi_packet = 0; ++ ++ /* ++ * Sometimes a position packet will indicate a multi-packet ++ * sequence, but then what follows is another position ++ * packet. Check for this, and when it happens process the ++ * position packet as usual. ++ */ ++ if (packet[0] & 0x40) { ++ /* ++ * Bitmap packets are not yet supported, so for now ++ * just ignore them. ++ */ ++ return; ++ } ++ } ++ ++ if (!priv->multi_packet && (packet[4] & 0x40)) ++ priv->multi_packet = 1; ++ else ++ priv->multi_packet = 0; ++ ++ left = packet[3] & 0x01; ++ right = packet[3] & 0x02; ++ middle = packet[3] & 0x04; ++ ++ x = ((packet[1] & 0x7f) << 4) | ((packet[4] & 0x30) >> 2) | ++ ((packet[0] & 0x30) >> 4); ++ y = ((packet[2] & 0x7f) << 4) | (packet[4] & 0x0f); ++ z = packet[5] & 0x7f; ++ ++ /* ++ * Sometimes the hardware sends a single packet with z = 0 ++ * in the middle of a stream. Real releases generate packets ++ * with x, y, and z all zero, so these seem to be flukes. ++ * Ignore them. ++ */ ++ if (x && y && !z) ++ return; ++ ++ if (z >= 64) ++ input_report_key(dev, BTN_TOUCH, 1); ++ else ++ input_report_key(dev, BTN_TOUCH, 0); ++ ++ if (z > 0) { ++ input_report_abs(dev, ABS_X, x); ++ input_report_abs(dev, ABS_Y, y); ++ } ++ input_report_abs(dev, ABS_PRESSURE, z); ++ ++ input_report_key(dev, BTN_TOOL_FINGER, z > 0); ++ input_report_key(dev, BTN_LEFT, left); ++ input_report_key(dev, BTN_RIGHT, right); ++ input_report_key(dev, BTN_MIDDLE, middle); ++ ++ input_sync(dev); ++ ++ if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { ++ left = packet[3] & 0x10; ++ right = packet[3] & 0x20; ++ middle = packet[3] & 0x40; ++ ++ input_report_key(dev2, BTN_LEFT, left); ++ input_report_key(dev2, BTN_RIGHT, right); ++ input_report_key(dev2, BTN_MIDDLE, middle); ++ input_sync(dev2); ++ } ++} ++ ++static void alps_process_packet_v3(struct psmouse *psmouse) ++{ ++ unsigned char *packet = psmouse->packet; ++ ++ /* ++ * v3 protocol packets come in three types, two representing ++ * touchpad data and one representing trackstick data. ++ * Trackstick packets seem to be distinguished by always ++ * having 0x3f in the last byte. This value has never been ++ * observed in the last byte of either of the other types ++ * of packets. ++ */ ++ if (packet[5] == 0x3f) { ++ alps_process_trackstick_packet_v3(psmouse); ++ return; ++ } ++ ++ alps_process_touchpad_packet_v3(psmouse); ++} ++ ++static void alps_process_packet_v4(struct psmouse *psmouse) ++{ ++ unsigned char *packet = psmouse->packet; ++ struct input_dev *dev = psmouse->dev; ++ int x, y, z; ++ int left, right; ++ ++ left = packet[4] & 0x01; ++ right = packet[4] & 0x02; ++ ++ x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) | ++ ((packet[0] & 0x30) >> 4); ++ y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f); ++ z = packet[5] & 0x7f; ++ ++ if (z >= 64) ++ input_report_key(dev, BTN_TOUCH, 1); ++ else ++ input_report_key(dev, BTN_TOUCH, 0); ++ ++ if (z > 0) { ++ input_report_abs(dev, ABS_X, x); ++ input_report_abs(dev, ABS_Y, y); ++ } ++ input_report_abs(dev, ABS_PRESSURE, z); ++ ++ input_report_key(dev, BTN_TOOL_FINGER, z > 0); ++ input_report_key(dev, BTN_LEFT, left); ++ input_report_key(dev, BTN_RIGHT, right); ++ ++ input_sync(dev); ++} ++ ++static void alps_process_packet(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ const struct alps_model_info *model = priv->i; ++ ++ switch (model->proto_version) { ++ case ALPS_PROTO_V1: ++ case ALPS_PROTO_V2: ++ alps_process_packet_v1_v2(psmouse); ++ break; ++ case ALPS_PROTO_V3: ++ alps_process_packet_v3(psmouse); ++ break; ++ case ALPS_PROTO_V4: ++ alps_process_packet_v4(psmouse); ++ break; ++ } ++} ++ + static void alps_report_bare_ps2_packet(struct psmouse *psmouse, + unsigned char packet[], + bool report_buttons) +@@ -381,11 +645,127 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) + return PSMOUSE_GOOD_DATA; + } + ++static int alps_command_mode_send_nibble(struct psmouse *psmouse, int nibble) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ struct alps_data *priv = psmouse->private; ++ int command; ++ unsigned char *param; ++ unsigned char dummy[4]; ++ ++ BUG_ON(nibble > 0xf); ++ ++ command = priv->nibble_commands[nibble].command; ++ param = (command & 0x0f00) ? ++ dummy : (unsigned char *)&priv->nibble_commands[nibble].data; ++ ++ if (ps2_command(ps2dev, param, command)) ++ return -1; ++ ++ return 0; ++} ++ ++static int alps_command_mode_set_addr(struct psmouse *psmouse, int addr) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ struct alps_data *priv = psmouse->private; ++ int i, nibble; ++ ++ if (ps2_command(ps2dev, NULL, priv->addr_command)) ++ return -1; ++ ++ for (i = 12; i >= 0; i -= 4) { ++ nibble = (addr >> i) & 0xf; ++ if (alps_command_mode_send_nibble(psmouse, nibble)) ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int __alps_command_mode_read_reg(struct psmouse *psmouse, int addr) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ unsigned char param[4]; ++ ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) ++ return -1; ++ ++ /* ++ * The address being read is returned in the first two bytes ++ * of the result. Check that this address matches the expected ++ * address. ++ */ ++ if (addr != ((param[0] << 8) | param[1])) ++ return -1; ++ ++ return param[2]; ++} ++ ++static int alps_command_mode_read_reg(struct psmouse *psmouse, int addr) ++{ ++ if (alps_command_mode_set_addr(psmouse, addr)) ++ return -1; ++ return __alps_command_mode_read_reg(psmouse, addr); ++} ++ ++static int __alps_command_mode_write_reg(struct psmouse *psmouse, u8 value) ++{ ++ if (alps_command_mode_send_nibble(psmouse, (value >> 4) & 0xf)) ++ return -1; ++ if (alps_command_mode_send_nibble(psmouse, value & 0xf)) ++ return -1; ++ return 0; ++} ++ ++static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr, ++ u8 value) ++{ ++ if (alps_command_mode_set_addr(psmouse, addr)) ++ return -1; ++ return __alps_command_mode_write_reg(psmouse, value); ++} ++ ++static int alps_enter_command_mode(struct psmouse *psmouse, ++ unsigned char *resp) ++{ ++ unsigned char param[4]; ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ ++ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || ++ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { ++ psmouse_err(psmouse, "failed to enter command mode\n"); ++ return -1; ++ } ++ ++ if (param[0] != 0x88 && param[1] != 0x07) { ++ psmouse_dbg(psmouse, ++ "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", ++ param[0], param[1], param[2]); ++ return -1; ++ } ++ ++ if (resp) ++ *resp = param[2]; ++ return 0; ++} ++ ++static inline int alps_exit_command_mode(struct psmouse *psmouse) ++{ ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) ++ return -1; ++ return 0; ++} ++ + static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) + { + struct ps2dev *ps2dev = &psmouse->ps2dev; + static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; + unsigned char param[4]; ++ const struct alps_model_info *model = NULL; + int i; + + /* +@@ -431,12 +811,41 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int + *version = (param[0] << 8) | (param[1] << 4) | i; + } + +- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) ++ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { + if (!memcmp(param, alps_model_data[i].signature, +- sizeof(alps_model_data[i].signature))) +- return alps_model_data + i; ++ sizeof(alps_model_data[i].signature))) { ++ model = alps_model_data + i; ++ break; ++ } ++ } + +- return NULL; ++ if (model && model->proto_version > ALPS_PROTO_V2) { ++ /* ++ * Need to check command mode response to identify ++ * model ++ */ ++ model = NULL; ++ if (alps_enter_command_mode(psmouse, param)) { ++ psmouse_warn(psmouse, ++ "touchpad failed to enter command mode\n"); ++ } else { ++ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { ++ if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && ++ alps_model_data[i].command_mode_resp == param[0]) { ++ model = alps_model_data + i; ++ break; ++ } ++ } ++ alps_exit_command_mode(psmouse); ++ ++ if (!model) ++ psmouse_dbg(psmouse, ++ "Unknown command mode response %2.2x\n", ++ param[0]); ++ } ++ } ++ ++ return model; + } + + /* +@@ -444,7 +853,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int + * subsequent commands. It looks like glidepad is behind stickpointer, + * I'd thought it would be other way around... + */ +-static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) ++static int alps_passthrough_mode_v2(struct psmouse *psmouse, bool enable) + { + struct ps2dev *ps2dev = &psmouse->ps2dev; + int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; +@@ -461,7 +870,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) + return 0; + } + +-static int alps_absolute_mode(struct psmouse *psmouse) ++static int alps_absolute_mode_v1_v2(struct psmouse *psmouse) + { + struct ps2dev *ps2dev = &psmouse->ps2dev; + +@@ -535,13 +944,13 @@ static int alps_poll(struct psmouse *psmouse) + bool poll_failed; + + if (priv->i->flags & ALPS_PASS) +- alps_passthrough_mode(psmouse, true); ++ alps_passthrough_mode_v2(psmouse, true); + + poll_failed = ps2_command(&psmouse->ps2dev, buf, + PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; + + if (priv->i->flags & ALPS_PASS) +- alps_passthrough_mode(psmouse, false); ++ alps_passthrough_mode_v2(psmouse, false); + + if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) + return -1; +@@ -558,13 +967,13 @@ static int alps_poll(struct psmouse *psmouse) + return 0; + } + +-static int alps_hw_init(struct psmouse *psmouse) ++static int alps_hw_init_v1_v2(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; + const struct alps_model_info *model = priv->i; + + if ((model->flags & ALPS_PASS) && +- alps_passthrough_mode(psmouse, true)) { ++ alps_passthrough_mode_v2(psmouse, true)) { + return -1; + } + +@@ -573,13 +982,13 @@ static int alps_hw_init(struct psmouse *psmouse) + return -1; + } + +- if (alps_absolute_mode(psmouse)) { ++ if (alps_absolute_mode_v1_v2(psmouse)) { + printk(KERN_ERR "alps.c: Failed to enable absolute mode\n"); + return -1; + } + + if ((model->flags & ALPS_PASS) && +- alps_passthrough_mode(psmouse, false)) { ++ alps_passthrough_mode_v2(psmouse, false)) { + return -1; + } + +@@ -592,6 +1001,297 @@ static int alps_hw_init(struct psmouse *psmouse) + return 0; + } + ++/* ++ * Enable or disable passthrough mode to the trackstick. Must be in ++ * command mode when calling this function. ++ */ ++static int alps_passthrough_mode_v3(struct psmouse *psmouse, bool enable) ++{ ++ int reg_val; ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0008); ++ if (reg_val == -1) ++ return -1; ++ ++ if (enable) ++ reg_val |= 0x01; ++ else ++ reg_val &= ~0x01; ++ ++ if (__alps_command_mode_write_reg(psmouse, reg_val)) ++ return -1; ++ ++ return 0; ++} ++ ++/* Must be in command mode when calling this function */ ++static int alps_absolute_mode_v3(struct psmouse *psmouse) ++{ ++ int reg_val; ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0004); ++ if (reg_val == -1) ++ return -1; ++ ++ reg_val |= 0x06; ++ if (__alps_command_mode_write_reg(psmouse, reg_val)) ++ return -1; ++ ++ return 0; ++} ++ ++static int alps_hw_init_v3(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ int reg_val; ++ unsigned char param[4]; ++ ++ priv->nibble_commands = alps_v3_nibble_commands; ++ priv->addr_command = PSMOUSE_CMD_RESET_WRAP; ++ ++ if (alps_enter_command_mode(psmouse, NULL)) ++ goto error; ++ ++ /* Check for trackstick */ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0008); ++ if (reg_val == -1) ++ goto error; ++ if (reg_val & 0x80) { ++ if (alps_passthrough_mode_v3(psmouse, true)) ++ goto error; ++ if (alps_exit_command_mode(psmouse)) ++ goto error; ++ ++ /* ++ * E7 report for the trackstick ++ * ++ * There have been reports of failures to seem to trace back ++ * to the above trackstick check failing. When these occur ++ * this E7 report fails, so when that happens we continue ++ * with the assumption that there isn't a trackstick after ++ * all. ++ */ ++ param[0] = 0x64; ++ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || ++ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { ++ psmouse_warn(psmouse, "trackstick E7 report failed\n"); ++ } else { ++ psmouse_dbg(psmouse, ++ "trackstick E7 report: %2.2x %2.2x %2.2x\n", ++ param[0], param[1], param[2]); ++ ++ /* ++ * Not sure what this does, but it is absolutely ++ * essential. Without it, the touchpad does not ++ * work at all and the trackstick just emits normal ++ * PS/2 packets. ++ */ ++ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ++ alps_command_mode_send_nibble(psmouse, 0x9) || ++ alps_command_mode_send_nibble(psmouse, 0x4)) { ++ psmouse_err(psmouse, ++ "Error sending magic E6 sequence\n"); ++ goto error_passthrough; ++ } ++ } ++ ++ if (alps_enter_command_mode(psmouse, NULL)) ++ goto error_passthrough; ++ if (alps_passthrough_mode_v3(psmouse, false)) ++ goto error; ++ } ++ ++ if (alps_absolute_mode_v3(psmouse)) { ++ psmouse_err(psmouse, "Failed to enter absolute mode\n"); ++ goto error; ++ } ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0006); ++ if (reg_val == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) ++ goto error; ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0007); ++ if (reg_val == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) ++ goto error; ++ ++ if (alps_command_mode_read_reg(psmouse, 0x0144) == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, 0x04)) ++ goto error; ++ ++ if (alps_command_mode_read_reg(psmouse, 0x0159) == -1) ++ goto error; ++ if (__alps_command_mode_write_reg(psmouse, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_read_reg(psmouse, 0x0163) == -1) ++ goto error; ++ if (alps_command_mode_write_reg(psmouse, 0x0163, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_read_reg(psmouse, 0x0162) == -1) ++ goto error; ++ if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04)) ++ goto error; ++ ++ /* ++ * This ensures the trackstick packets are in the format ++ * supported by this driver. If bit 1 isn't set the packet ++ * format is different. ++ */ ++ if (alps_command_mode_write_reg(psmouse, 0x0008, 0x82)) ++ goto error; ++ ++ alps_exit_command_mode(psmouse); ++ ++ /* Set rate and enable data reporting */ ++ param[0] = 0x64; ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { ++ psmouse_err(psmouse, "Failed to enable data reporting\n"); ++ return -1; ++ } ++ ++ return 0; ++ ++error_passthrough: ++ /* Something failed while in passthrough mode, so try to get out */ ++ if (!alps_enter_command_mode(psmouse, NULL)) ++ alps_passthrough_mode_v3(psmouse, false); ++error: ++ /* ++ * Leaving the touchpad in command mode will essentially render ++ * it unusable until the machine reboots, so exit it here just ++ * to be safe ++ */ ++ alps_exit_command_mode(psmouse); ++ return -1; ++} ++ ++/* Must be in command mode when calling this function */ ++static int alps_absolute_mode_v4(struct psmouse *psmouse) ++{ ++ int reg_val; ++ ++ reg_val = alps_command_mode_read_reg(psmouse, 0x0004); ++ if (reg_val == -1) ++ return -1; ++ ++ reg_val |= 0x02; ++ if (__alps_command_mode_write_reg(psmouse, reg_val)) ++ return -1; ++ ++ return 0; ++} ++ ++static int alps_hw_init_v4(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ struct ps2dev *ps2dev = &psmouse->ps2dev; ++ unsigned char param[4]; ++ ++ priv->nibble_commands = alps_v4_nibble_commands; ++ priv->addr_command = PSMOUSE_CMD_DISABLE; ++ ++ if (alps_enter_command_mode(psmouse, NULL)) ++ goto error; ++ ++ if (alps_absolute_mode_v4(psmouse)) { ++ psmouse_err(psmouse, "Failed to enter absolute mode\n"); ++ goto error; ++ } ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0007, 0x8c)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0149, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0160, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x017f, 0x15)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0151, 0x01)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0168, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x014a, 0x03)) ++ goto error; ++ ++ if (alps_command_mode_write_reg(psmouse, 0x0161, 0x03)) ++ goto error; ++ ++ alps_exit_command_mode(psmouse); ++ ++ /* ++ * This sequence changes the output from a 9-byte to an ++ * 8-byte format. All the same data seems to be present, ++ * just in a more compact format. ++ */ ++ param[0] = 0xc8; ++ param[1] = 0x64; ++ param[2] = 0x50; ++ if (ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || ++ ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE) || ++ ps2_command(ps2dev, ¶m[2], PSMOUSE_CMD_SETRATE) || ++ ps2_command(ps2dev, param, PSMOUSE_CMD_GETID)) ++ return -1; ++ ++ /* Set rate and enable data reporting */ ++ param[0] = 0x64; ++ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || ++ ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { ++ psmouse_err(psmouse, "Failed to enable data reporting\n"); ++ return -1; ++ } ++ ++ return 0; ++ ++error: ++ /* ++ * Leaving the touchpad in command mode will essentially render ++ * it unusable until the machine reboots, so exit it here just ++ * to be safe ++ */ ++ alps_exit_command_mode(psmouse); ++ return -1; ++} ++ ++static int alps_hw_init(struct psmouse *psmouse) ++{ ++ struct alps_data *priv = psmouse->private; ++ const struct alps_model_info *model = priv->i; ++ int ret = -1; ++ ++ switch (model->proto_version) { ++ case ALPS_PROTO_V1: ++ case ALPS_PROTO_V2: ++ ret = alps_hw_init_v1_v2(psmouse); ++ break; ++ case ALPS_PROTO_V3: ++ ret = alps_hw_init_v3(psmouse); ++ break; ++ case ALPS_PROTO_V4: ++ ret = alps_hw_init_v4(psmouse); ++ break; ++ } ++ ++ return ret; ++} ++ + static int alps_reconnect(struct psmouse *psmouse) + { + const struct alps_model_info *model; +@@ -632,6 +1332,8 @@ int alps_init(struct psmouse *psmouse) + + psmouse->private = priv; + ++ psmouse_reset(psmouse); ++ + model = alps_get_model(psmouse, &version); + if (!model) + goto init_fail; +@@ -659,8 +1361,20 @@ int alps_init(struct psmouse *psmouse) + BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); + + dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); +- input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); +- input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); ++ ++ switch (model->proto_version) { ++ case ALPS_PROTO_V1: ++ case ALPS_PROTO_V2: ++ input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); ++ input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); ++ break; ++ case ALPS_PROTO_V3: ++ case ALPS_PROTO_V4: ++ input_set_abs_params(dev1, ABS_X, 0, 2000, 0, 0); ++ input_set_abs_params(dev1, ABS_Y, 0, 1400, 0, 0); ++ break; ++ } ++ + input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); + + if (model->flags & ALPS_WHEEL) { +@@ -703,7 +1417,7 @@ int alps_init(struct psmouse *psmouse) + psmouse->poll = alps_poll; + psmouse->disconnect = alps_disconnect; + psmouse->reconnect = alps_reconnect; +- psmouse->pktsize = 6; ++ psmouse->pktsize = model->proto_version == ALPS_PROTO_V4 ? 8 : 6; + + /* We are having trouble resyncing ALPS touchpads so disable it for now */ + psmouse->resync_time = 0; +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index 4ce9bba..62db7f4 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -14,22 +14,36 @@ + + #define ALPS_PROTO_V1 0 + #define ALPS_PROTO_V2 1 ++#define ALPS_PROTO_V3 2 ++#define ALPS_PROTO_V4 3 + + struct alps_model_info { + unsigned char signature[3]; ++ unsigned char command_mode_resp; /* v3/v4 only */ + unsigned char proto_version; + unsigned char byte0, mask0; + unsigned char flags; + }; + ++struct alps_nibble_commands { ++ int command; ++ unsigned char data; ++}; ++ + struct alps_data { + struct input_dev *dev2; /* Relative device */ + char phys[32]; /* Phys */ + const struct alps_model_info *i;/* Info */ ++ const struct alps_nibble_commands *nibble_commands; ++ int addr_command; /* Command to set register address */ + int prev_fin; /* Finger bit from previous packet */ ++ int multi_packet; /* Multi-packet data in progress */ ++ u8 quirks; + struct timer_list timer; + }; + ++#define ALPS_QUIRK_TRACKSTICK_BUTTONS 1 /* trakcstick buttons in trackstick packet */ ++ + #ifdef CONFIG_MOUSE_PS2_ALPS + int alps_detect(struct psmouse *psmouse, bool set_properties); + int alps_init(struct psmouse *psmouse); +diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h +index 593e910..c2b5aa6 100644 +--- a/drivers/input/mouse/psmouse.h ++++ b/drivers/input/mouse/psmouse.h +@@ -8,6 +8,7 @@ + #define PSMOUSE_CMD_SETSTREAM 0x00ea + #define PSMOUSE_CMD_SETPOLL 0x00f0 + #define PSMOUSE_CMD_POLL 0x00eb /* caller sets number of bytes to receive */ ++#define PSMOUSE_CMD_RESET_WRAP 0x00ec + #define PSMOUSE_CMD_GETID 0x02f2 + #define PSMOUSE_CMD_SETRATE 0x10f3 + #define PSMOUSE_CMD_ENABLE 0x00f4 +-- +1.7.7.3 + + +From 8a2d5b12d0a47daf178a842ca009eaf344033cf8 Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Mon, 7 Nov 2011 19:54:13 -0800 +Subject: [PATCH 5/7] Input: ALPS - add semi-MT support for v3 protocol + +Signed-off-by: Seth Forshee +Acked-by: Chase Douglas +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/alps.c | 233 ++++++++++++++++++++++++++++++++++++++++---- + drivers/input/mouse/alps.h | 1 + + 2 files changed, 215 insertions(+), 19 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index b2bc8ca..15383e1 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -17,6 +17,7 @@ + + #include + #include ++#include + #include + #include + +@@ -33,6 +34,12 @@ + /* + * Definitions for ALPS version 3 and 4 command mode protocol + */ ++#define ALPS_V3_X_MAX 2000 ++#define ALPS_V3_Y_MAX 1400 ++ ++#define ALPS_BITMAP_X_BITS 15 ++#define ALPS_BITMAP_Y_BITS 11 ++ + #define ALPS_CMD_NIBBLE_10 0x01f2 + + static const struct alps_nibble_commands alps_v3_nibble_commands[] = { +@@ -256,6 +263,137 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) + input_sync(dev); + } + ++/* ++ * Process bitmap data from v3 and v4 protocols. Returns the number of ++ * fingers detected. A return value of 0 means at least one of the ++ * bitmaps was empty. ++ * ++ * The bitmaps don't have enough data to track fingers, so this function ++ * only generates points representing a bounding box of all contacts. ++ * These points are returned in x1, y1, x2, and y2 when the return value ++ * is greater than 0. ++ */ ++static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, ++ int *x1, int *y1, int *x2, int *y2) ++{ ++ struct alps_bitmap_point { ++ int start_bit; ++ int num_bits; ++ }; ++ ++ int fingers_x = 0, fingers_y = 0, fingers; ++ int i, bit, prev_bit; ++ struct alps_bitmap_point x_low = {0,}, x_high = {0,}; ++ struct alps_bitmap_point y_low = {0,}, y_high = {0,}; ++ struct alps_bitmap_point *point; ++ ++ if (!x_map || !y_map) ++ return 0; ++ ++ *x1 = *y1 = *x2 = *y2 = 0; ++ ++ prev_bit = 0; ++ point = &x_low; ++ for (i = 0; x_map != 0; i++, x_map >>= 1) { ++ bit = x_map & 1; ++ if (bit) { ++ if (!prev_bit) { ++ point->start_bit = i; ++ fingers_x++; ++ } ++ point->num_bits++; ++ } else { ++ if (prev_bit) ++ point = &x_high; ++ else ++ point->num_bits = 0; ++ } ++ prev_bit = bit; ++ } ++ ++ /* ++ * y bitmap is reversed for what we need (lower positions are in ++ * higher bits), so we process from the top end. ++ */ ++ y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - ALPS_BITMAP_Y_BITS); ++ prev_bit = 0; ++ point = &y_low; ++ for (i = 0; y_map != 0; i++, y_map <<= 1) { ++ bit = y_map & (1 << (sizeof(y_map) * BITS_PER_BYTE - 1)); ++ if (bit) { ++ if (!prev_bit) { ++ point->start_bit = i; ++ fingers_y++; ++ } ++ point->num_bits++; ++ } else { ++ if (prev_bit) ++ point = &y_high; ++ else ++ point->num_bits = 0; ++ } ++ prev_bit = bit; ++ } ++ ++ /* ++ * Fingers can overlap, so we use the maximum count of fingers ++ * on either axis as the finger count. ++ */ ++ fingers = max(fingers_x, fingers_y); ++ ++ /* ++ * If total fingers is > 1 but either axis reports only a single ++ * contact, we have overlapping or adjacent fingers. For the ++ * purposes of creating a bounding box, divide the single contact ++ * (roughly) equally between the two points. ++ */ ++ if (fingers > 1) { ++ if (fingers_x == 1) { ++ i = x_low.num_bits / 2; ++ x_low.num_bits = x_low.num_bits - i; ++ x_high.start_bit = x_low.start_bit + i; ++ x_high.num_bits = max(i, 1); ++ } else if (fingers_y == 1) { ++ i = y_low.num_bits / 2; ++ y_low.num_bits = y_low.num_bits - i; ++ y_high.start_bit = y_low.start_bit + i; ++ y_high.num_bits = max(i, 1); ++ } ++ } ++ ++ *x1 = (ALPS_V3_X_MAX * (2 * x_low.start_bit + x_low.num_bits - 1)) / ++ (2 * (ALPS_BITMAP_X_BITS - 1)); ++ *y1 = (ALPS_V3_Y_MAX * (2 * y_low.start_bit + y_low.num_bits - 1)) / ++ (2 * (ALPS_BITMAP_Y_BITS - 1)); ++ ++ if (fingers > 1) { ++ *x2 = (ALPS_V3_X_MAX * (2 * x_high.start_bit + x_high.num_bits - 1)) / ++ (2 * (ALPS_BITMAP_X_BITS - 1)); ++ *y2 = (ALPS_V3_Y_MAX * (2 * y_high.start_bit + y_high.num_bits - 1)) / ++ (2 * (ALPS_BITMAP_Y_BITS - 1)); ++ } ++ ++ return fingers; ++} ++ ++static void alps_set_slot(struct input_dev *dev, int slot, bool active, ++ int x, int y) ++{ ++ input_mt_slot(dev, slot); ++ input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); ++ if (active) { ++ input_report_abs(dev, ABS_MT_POSITION_X, x); ++ input_report_abs(dev, ABS_MT_POSITION_Y, y); ++ } ++} ++ ++static void alps_report_semi_mt_data(struct input_dev *dev, int num_fingers, ++ int x1, int y1, int x2, int y2) ++{ ++ alps_set_slot(dev, 0, num_fingers != 0, x1, y1); ++ alps_set_slot(dev, 1, num_fingers == 2, x2, y2); ++} ++ + static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; +@@ -324,16 +462,17 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + struct input_dev *dev2 = priv->dev2; + int x, y, z; + int left, right, middle; ++ int x1 = 0, y1 = 0, x2 = 0, y2 = 0; ++ int fingers = 0, bmap_fingers; ++ unsigned int x_bitmap, y_bitmap; + + /* +- * There's no single feature of touchpad position and bitmap +- * packets that can be used to distinguish between them. We +- * rely on the fact that a bitmap packet should always follow +- * a position packet with bit 6 of packet[4] set. ++ * There's no single feature of touchpad position and bitmap packets ++ * that can be used to distinguish between them. We rely on the fact ++ * that a bitmap packet should always follow a position packet with ++ * bit 6 of packet[4] set. + */ + if (priv->multi_packet) { +- priv->multi_packet = 0; +- + /* + * Sometimes a position packet will indicate a multi-packet + * sequence, but then what follows is another position +@@ -341,18 +480,49 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + * position packet as usual. + */ + if (packet[0] & 0x40) { ++ fingers = (packet[5] & 0x3) + 1; ++ x_bitmap = ((packet[4] & 0x7e) << 8) | ++ ((packet[1] & 0x7f) << 2) | ++ ((packet[0] & 0x30) >> 4); ++ y_bitmap = ((packet[3] & 0x70) << 4) | ++ ((packet[2] & 0x7f) << 1) | ++ (packet[4] & 0x01); ++ ++ bmap_fingers = alps_process_bitmap(x_bitmap, y_bitmap, ++ &x1, &y1, &x2, &y2); ++ + /* +- * Bitmap packets are not yet supported, so for now +- * just ignore them. ++ * We shouldn't report more than one finger if ++ * we don't have two coordinates. + */ +- return; ++ if (fingers > 1 && bmap_fingers < 2) ++ fingers = bmap_fingers; ++ ++ /* Now process position packet */ ++ packet = priv->multi_data; ++ } else { ++ priv->multi_packet = 0; + } + } + +- if (!priv->multi_packet && (packet[4] & 0x40)) ++ /* ++ * Bit 6 of byte 0 is not usually set in position packets. The only ++ * times it seems to be set is in situations where the data is ++ * suspect anyway, e.g. a palm resting flat on the touchpad. Given ++ * this combined with the fact that this bit is useful for filtering ++ * out misidentified bitmap packets, we reject anything with this ++ * bit set. ++ */ ++ if (packet[0] & 0x40) ++ return; ++ ++ if (!priv->multi_packet && (packet[4] & 0x40)) { + priv->multi_packet = 1; +- else +- priv->multi_packet = 0; ++ memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); ++ return; ++ } ++ ++ priv->multi_packet = 0; + + left = packet[3] & 0x01; + right = packet[3] & 0x02; +@@ -372,22 +542,38 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) + if (x && y && !z) + return; + ++ /* ++ * If we don't have MT data or the bitmaps were empty, we have ++ * to rely on ST data. ++ */ ++ if (!fingers) { ++ x1 = x; ++ y1 = y; ++ fingers = z > 0 ? 1 : 0; ++ } ++ + if (z >= 64) + input_report_key(dev, BTN_TOUCH, 1); + else + input_report_key(dev, BTN_TOUCH, 0); + ++ alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); ++ ++ input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); ++ input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); ++ input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); ++ input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4); ++ ++ input_report_key(dev, BTN_LEFT, left); ++ input_report_key(dev, BTN_RIGHT, right); ++ input_report_key(dev, BTN_MIDDLE, middle); ++ + if (z > 0) { + input_report_abs(dev, ABS_X, x); + input_report_abs(dev, ABS_Y, y); + } + input_report_abs(dev, ABS_PRESSURE, z); + +- input_report_key(dev, BTN_TOOL_FINGER, z > 0); +- input_report_key(dev, BTN_LEFT, left); +- input_report_key(dev, BTN_RIGHT, right); +- input_report_key(dev, BTN_MIDDLE, middle); +- + input_sync(dev); + + if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { +@@ -1369,9 +1555,18 @@ int alps_init(struct psmouse *psmouse) + input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); + break; + case ALPS_PROTO_V3: ++ set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); ++ input_mt_init_slots(dev1, 2); ++ input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); ++ input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); ++ ++ set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); ++ set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); ++ set_bit(BTN_TOOL_QUADTAP, dev1->keybit); ++ /* fall through */ + case ALPS_PROTO_V4: +- input_set_abs_params(dev1, ABS_X, 0, 2000, 0, 0); +- input_set_abs_params(dev1, ABS_Y, 0, 1400, 0, 0); ++ input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); ++ input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); + break; + } + +diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h +index 62db7f4..a00a4ab 100644 +--- a/drivers/input/mouse/alps.h ++++ b/drivers/input/mouse/alps.h +@@ -38,6 +38,7 @@ struct alps_data { + int addr_command; /* Command to set register address */ + int prev_fin; /* Finger bit from previous packet */ + int multi_packet; /* Multi-packet data in progress */ ++ unsigned char multi_data[6]; /* Saved multi-packet data */ + u8 quirks; + struct timer_list timer; + }; +-- +1.7.7.3 + + +From 281688737cb83dd113cfab809b2c78841451ba32 Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Mon, 7 Nov 2011 19:54:35 -0800 +Subject: [PATCH 6/7] Input: ALPS - add documentation for protocol versions 3 + and 4 + +Also converts from using "old" and "new" to describe the already-known +protocols to using "version 1" and "version 2" to match the code. + +Signed-off-by: Seth Forshee +Acked-by: Chase Douglas +Signed-off-by: Dmitry Torokhov +--- + Documentation/input/alps.txt | 135 ++++++++++++++++++++++++++++++++++++++---- + 1 files changed, 124 insertions(+), 11 deletions(-) + +diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt +index ab5478f..f274c28 100644 +--- a/Documentation/input/alps.txt ++++ b/Documentation/input/alps.txt +@@ -4,12 +4,9 @@ ALPS Touchpad Protocol + Introduction + ------------ + +-Currently the ALPS touchpad driver supports two protocol versions in use by +-ALPS touchpads, the "old" and "new" protocol versions. Fundamentally these +-differ only in the format of their event packets (in reality many features may +-be found on new protocol devices that aren't found on the old protocol +-devices, but these are handled transparently as feature differences rather +-than protocol differences). ++Currently the ALPS touchpad driver supports four protocol versions in use by ++ALPS touchpads, called versions 1, 2, 3, and 4. Information about the various ++protocol versions is contained in the following sections. + + Detection + --------- +@@ -22,10 +19,37 @@ If the E6 report is successful, the touchpad model is identified using the "E7 + report" sequence: E8-E7-E7-E7-E9. The response is the model signature and is + matched against known models in the alps_model_data_array. + ++With protocol versions 3 and 4, the E7 report model signature is always ++73-02-64. To differentiate between these versions, the response from the ++"Enter Command Mode" sequence must be inspected as described below. ++ ++Command Mode ++------------ ++ ++Protocol versions 3 and 4 have a command mode that is used to read and write ++one-byte device registers in a 16-bit address space. The command sequence ++EC-EC-EC-E9 places the device in command mode, and the device will respond ++with 88-07 followed by a third byte. This third byte can be used to determine ++whether the devices uses the version 3 or 4 protocol. ++ ++To exit command mode, PSMOUSE_CMD_SETSTREAM (EA) is sent to the touchpad. ++ ++While in command mode, register addresses can be set by first sending a ++specific command, either EC for v3 devices or F5 for v4 devices. Then the ++address is sent one nibble at a time, where each nibble is encoded as a ++command with optional data. This enoding differs slightly between the v3 and ++v4 protocols. ++ ++Once an address has been set, the addressed register can be read by sending ++PSMOUSE_CMD_GETINFO (E9). The first two bytes of the response contains the ++address of the register being read, and the third contains the value of the ++register. Registers are written by writing the value one nibble at a time ++using the same encoding used for addresses. ++ + Packet Format + ------------- + +-In the following tables, the following notation us used. ++In the following tables, the following notation is used. + + CAPITALS = stick, miniscules = touchpad + +@@ -41,8 +65,8 @@ PS/2 packet format + + Note that the device never signals overflow condition. + +-ALPS Absolute Mode - Old Format +-------------------------------- ++ALPS Absolute Mode - Protocol Verion 1 ++-------------------------------------- + + byte 0: 1 0 0 0 1 x9 x8 x7 + byte 1: 0 x6 x5 x4 x3 x2 x1 x0 +@@ -51,8 +75,8 @@ ALPS Absolute Mode - Old Format + byte 4: 0 y6 y5 y4 y3 y2 y1 y0 + byte 5: 0 z6 z5 z4 z3 z2 z1 z0 + +-ALPS Absolute Mode - New Format +-------------------------------- ++ALPS Absolute Mode - Protocol Version 2 ++--------------------------------------- + + byte 0: 1 ? ? ? 1 ? ? ? + byte 1: 0 x6 x5 x4 x3 x2 x1 x0 +@@ -73,3 +97,92 @@ Dualpoint device -- interleaved packet format + byte 6: 0 y9 y8 y7 1 m r l + byte 7: 0 y6 y5 y4 y3 y2 y1 y0 + byte 8: 0 z6 z5 z4 z3 z2 z1 z0 ++ ++ALPS Absolute Mode - Protocol Version 3 ++--------------------------------------- ++ ++ALPS protocol version 3 has three different packet formats. The first two are ++associated with touchpad events, and the third is associatd with trackstick ++events. ++ ++The first type is the touchpad position packet. ++ ++ byte 0: 1 ? x1 x0 1 1 1 1 ++ byte 1: 0 x10 x9 x8 x7 x6 x5 x4 ++ byte 2: 0 y10 y9 y8 y7 y6 y5 y4 ++ byte 3: 0 M R L 1 m r l ++ byte 4: 0 mt x3 x2 y3 y2 y1 y0 ++ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 ++ ++Note that for some devices the trackstick buttons are reported in this packet, ++and on others it is reported in the trackstick packets. ++ ++The second packet type contains bitmaps representing the x and y axes. In the ++bitmaps a given bit is set if there is a finger covering that position on the ++given axis. Thus the bitmap packet can be used for low-resolution multi-touch ++data, although finger tracking is not possible. This packet also encodes the ++number of contacts (f1 and f0 in the table below). ++ ++ byte 0: 1 1 x1 x0 1 1 1 1 ++ byte 1: 0 x8 x7 x6 x5 x4 x3 x2 ++ byte 2: 0 y7 y6 y5 y4 y3 y2 y1 ++ byte 3: 0 y10 y9 y8 1 1 1 1 ++ byte 4: 0 x14 x13 x12 x11 x10 x9 y0 ++ byte 5: 0 1 ? ? ? ? f1 f0 ++ ++This packet only appears after a position packet with the mt bit set, and ++ususally only appears when there are two or more contacts (although ++ocassionally it's seen with only a single contact). ++ ++The final v3 packet type is the trackstick packet. ++ ++ byte 0: 1 1 x7 y7 1 1 1 1 ++ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 ++ byte 2: 0 y6 y5 y4 y3 y2 y1 y0 ++ byte 3: 0 1 0 0 1 0 0 0 ++ byte 4: 0 z4 z3 z2 z1 z0 ? ? ++ byte 5: 0 0 1 1 1 1 1 1 ++ ++ALPS Absolute Mode - Protocol Version 4 ++--------------------------------------- ++ ++Protocol version 4 has an 8-byte packet format. ++ ++ byte 0: 1 ? x1 x0 1 1 1 1 ++ byte 1: 0 x10 x9 x8 x7 x6 x5 x4 ++ byte 2: 0 y10 y9 y8 y7 y6 y5 y4 ++ byte 3: 0 1 x3 x2 y3 y2 y1 y0 ++ byte 4: 0 ? ? ? 1 ? r l ++ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 ++ byte 6: bitmap data (described below) ++ byte 7: bitmap data (described below) ++ ++The last two bytes represent a partial bitmap packet, with 3 full packets ++required to construct a complete bitmap packet. Once assembled, the 6-byte ++bitmap packet has the following format: ++ ++ byte 0: 0 1 x7 x6 x5 x4 x3 x2 ++ byte 1: 0 x1 x0 y4 y3 y2 y1 y0 ++ byte 2: 0 0 ? x14 x13 x12 x11 x10 ++ byte 3: 0 x9 x8 y9 y8 y7 y6 y5 ++ byte 4: 0 0 0 0 0 0 0 0 ++ byte 5: 0 0 0 0 0 0 0 y10 ++ ++There are several things worth noting here. ++ ++ 1) In the bitmap data, bit 6 of byte 0 serves as a sync byte to ++ identify the first fragment of a bitmap packet. ++ ++ 2) The bitmaps represent the same data as in the v3 bitmap packets, although ++ the packet layout is different. ++ ++ 3) There doesn't seem to be a count of the contact points anywhere in the v4 ++ protocol packets. Deriving a count of contact points must be done by ++ analyzing the bitmaps. ++ ++ 4) There is a 3 to 1 ratio of position packets to bitmap packets. Therefore ++ MT position can only be updated for every third ST position update, and ++ the count of contact points can only be updated every third packet as ++ well. ++ ++So far no v4 devices with tracksticks have been encountered. +-- +1.7.7.3 + + +From 8114d422321fa6bb724a03faf25b101868d6e03d Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Mon, 12 Dec 2011 15:12:00 -0500 +Subject: [PATCH 7/7] Revert psmouse_* print format changes from the + backported patches. Sigh + +Signed-off-by: Josh Boyer +--- + drivers/input/mouse/alps.c | 29 ++++++++++++----------------- + 1 files changed, 12 insertions(+), 17 deletions(-) + +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index 15383e1..4925a63 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -403,7 +403,7 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) + + /* Sanity check packet */ + if (!(packet[0] & 0x40)) { +- psmouse_dbg(psmouse, "Bad trackstick packet, discarding\n"); ++ dbg("Bad trackstick packet, discarding\n"); + return; + } + +@@ -922,13 +922,12 @@ static int alps_enter_command_mode(struct psmouse *psmouse, + ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || + ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { +- psmouse_err(psmouse, "failed to enter command mode\n"); ++ printk(KERN_ERR "alps.c: failed to enter command mode\n"); + return -1; + } + + if (param[0] != 0x88 && param[1] != 0x07) { +- psmouse_dbg(psmouse, +- "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", ++ dbg("unknown response while entering command mode: %2.2x %2.2x %2.2x\n", + param[0], param[1], param[2]); + return -1; + } +@@ -1012,8 +1011,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int + */ + model = NULL; + if (alps_enter_command_mode(psmouse, param)) { +- psmouse_warn(psmouse, +- "touchpad failed to enter command mode\n"); ++ printk(KERN_WARNING "alps.c: touchpad failed to enter command mode\n"); + } else { + for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { + if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && +@@ -1025,8 +1023,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int + alps_exit_command_mode(psmouse); + + if (!model) +- psmouse_dbg(psmouse, +- "Unknown command mode response %2.2x\n", ++ dbg("Unknown command mode response %2.2x\n", + param[0]); + } + } +@@ -1263,10 +1260,9 @@ static int alps_hw_init_v3(struct psmouse *psmouse) + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || + ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { +- psmouse_warn(psmouse, "trackstick E7 report failed\n"); ++ printk(KERN_WARNING "alps.c: trackstick E7 report failed\n"); + } else { +- psmouse_dbg(psmouse, +- "trackstick E7 report: %2.2x %2.2x %2.2x\n", ++ dbg("trackstick E7 report: %2.2x %2.2x %2.2x\n", + param[0], param[1], param[2]); + + /* +@@ -1280,8 +1276,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || + alps_command_mode_send_nibble(psmouse, 0x9) || + alps_command_mode_send_nibble(psmouse, 0x4)) { +- psmouse_err(psmouse, +- "Error sending magic E6 sequence\n"); ++ printk(KERN_ERR "alps.c: Error sending magic E6 sequence\n"); + goto error_passthrough; + } + } +@@ -1293,7 +1288,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) + } + + if (alps_absolute_mode_v3(psmouse)) { +- psmouse_err(psmouse, "Failed to enter absolute mode\n"); ++ printk(KERN_ERR "alps.c: Failed to enter absolute mode\n"); + goto error; + } + +@@ -1343,7 +1338,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) + param[0] = 0x64; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { +- psmouse_err(psmouse, "Failed to enable data reporting\n"); ++ printk(KERN_ERR "alps.c: Failed to enable data reporting\n"); + return -1; + } + +@@ -1392,7 +1387,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse) + goto error; + + if (alps_absolute_mode_v4(psmouse)) { +- psmouse_err(psmouse, "Failed to enter absolute mode\n"); ++ printk(KERN_ERR "alps.c: Failed to enter absolute mode\n"); + goto error; + } + +@@ -1440,7 +1435,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse) + param[0] = 0x64; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { +- psmouse_err(psmouse, "Failed to enable data reporting\n"); ++ printk(KERN_ERR "alps.c: Failed to enable data reporting\n"); + return -1; + } + +-- +1.7.7.3 + diff --git a/kernel.spec b/kernel.spec index ba4599c55..558ce909f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -800,6 +800,9 @@ Patch21230: net-sky2-88e8059-fix-link-speed.patch #rhbz 717735 Patch21045: nfs-client-freezer.patch +#rhbz 590880 +Patch21046: alps.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1471,6 +1474,9 @@ ApplyPatch net-sky2-88e8059-fix-link-speed.patch #rhbz 717735 ApplyPatch nfs-client-freezer.patch +#rhbz 590880 +ApplyPatch alps.patch + # END OF PATCH APPLICATIONS %endif @@ -2204,6 +2210,7 @@ fi %changelog * Mon Dec 12 2011 Josh Boyer - Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735) +- Backport ALPS touchpad patches from input/next branch (rhbz #590880) * Fri Dec 09 2011 Josh Boyer 3.1.5-1 - Linux 3.1.5 From c63c5b8281a254df63fbbb83f8071e4dedee9f02 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 13 Dec 2011 11:00:37 -0500 Subject: [PATCH 174/487] Remove extraneous settings and enable Radeon KMS for powerpc (via Will Woods) --- config-powerpc-generic | 7 ------- kernel.spec | 5 ++++- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/config-powerpc-generic b/config-powerpc-generic index ec2ff7c8e..5ecaf0e5d 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -38,22 +38,17 @@ CONFIG_AGP_UNINORTH=y CONFIG_FB_OF=y # CONFIG_FB_CONTROL is not set CONFIG_FB_IBM_GXT4500=y -CONFIG_FB_RADEON=y CONFIG_FB_MATROX=y -CONFIG_FB_NVIDIA=m # CONFIG_FB_VGA16 is not set CONFIG_FB_ATY128_BACKLIGHT=y CONFIG_FB_ATY_BACKLIGHT=y -CONFIG_FB_RADEON_BACKLIGHT=y CONFIG_FB_RIVA_BACKLIGHT=y -CONFIG_FB_NVIDIA_BACKLIGHT=y # FIXME: Do we care about this hardware ? CONFIG_FB_MB862XX=m CONFIG_FB_MB862XX_PCI_GDC=y CONFIG_FB_MB862XX_LIME=y CONFIG_FB_MB862XX_I2C=y - CONFIG_SND_POWERMAC=m CONFIG_SND_POWERMAC_AUTO_DRC=y CONFIG_SND_AOA=m @@ -278,8 +273,6 @@ CONFIG_GPIO_PCF857X=m # CONFIG_USB_FHCI_HCD is not set # CONFIG_FHCI_DEBUG is not set -# CONFIG_DRM_RADEON_KMS is not set - # CONFIG_AMIGAONE is not set CONFIG_PPC_OF_BOOT_TRAMPOLINE=y diff --git a/kernel.spec b/kernel.spec index 558ce909f..7ee050496 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2208,6 +2208,9 @@ fi # and build. %changelog +* Tue Dec 13 2011 Josh Boyer +- Remove extraneous settings and enable Radeon KMS for powerpc (via Will Woods) + * Mon Dec 12 2011 Josh Boyer - Add patch from Jeff Layton to fix suspend with NFS (rhbz #717735) - Backport ALPS touchpad patches from input/next branch (rhbz #590880) From 386df52ea29a88529838d5c95c975a4458926966 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 14 Dec 2011 20:23:20 -0500 Subject: [PATCH 175/487] Disable Intel IOMMU by default. --- config-x86-generic | 2 +- kernel.spec | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/config-x86-generic b/config-x86-generic index e1d81cfd6..45fda3b7c 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -39,7 +39,7 @@ CONFIG_FB_EFI=y CONFIG_DMAR=y CONFIG_DMAR_BROKEN_GFX_WA=y CONFIG_DMAR_FLOPPY_WA=y -CONFIG_DMAR_DEFAULT_ON=y +# CONFIG_DMAR_DEFAULT_ON is not set CONFIG_SCSI_ADVANSYS=m CONFIG_SECCOMP=y diff --git a/kernel.spec b/kernel.spec index 7ee050496..ce9308edf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2208,6 +2208,9 @@ fi # and build. %changelog +* Thu Dec 15 2011 Dave Jones - 3.1.5-4 +- Disable Intel IOMMU by default. + * Tue Dec 13 2011 Josh Boyer - Remove extraneous settings and enable Radeon KMS for powerpc (via Will Woods) From 6a7c0501a485fa37f3fa5d9ab232e37ff04e2155 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 14 Dec 2011 22:42:08 -0500 Subject: [PATCH 176/487] Change configfs to be built-in. (rhbz 767857) --- config-generic | 2 +- kernel.spec | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/config-generic b/config-generic index 8ae85a234..b620c953e 100644 --- a/config-generic +++ b/config-generic @@ -3677,7 +3677,7 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m CONFIG_BTRFS_FS=m CONFIG_BTRFS_FS_POSIX_ACL=y -CONFIG_CONFIGFS_FS=m +CONFIG_CONFIGFS_FS=y CONFIG_DLM=m CONFIG_DLM_DEBUG=y diff --git a/kernel.spec b/kernel.spec index ce9308edf..1ea18dba8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2208,6 +2208,9 @@ fi # and build. %changelog +* Thu Dec 15 2011 Dave Jones - 3.1.5-5 +- Change configfs to be built-in. (rhbz 767857) + * Thu Dec 15 2011 Dave Jones - 3.1.5-4 - Disable Intel IOMMU by default. From 53562963441a135f962e2b79b360b334da8c8c06 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 15 Dec 2011 10:21:49 -0500 Subject: [PATCH 177/487] Add patch to fix Intel wifi regression in 3.1.5 (rhbz 767173) --- ...-to-switch-to-HT40-if-not-associated.patch | 38 +++++++++++++++++++ kernel.spec | 11 +++++- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch diff --git a/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch b/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch new file mode 100644 index 000000000..08c9e443b --- /dev/null +++ b/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch @@ -0,0 +1,38 @@ +My previous patch +34a5b4b6af104cf18eb50748509528b9bdbc4036 iwlwifi: do not re-configure +HT40 after associated + +Fix the case of HT40 after association on specified AP, but it break the +association for some APs and cause not able to establish connection. +We need to address HT40 before and after addociation. + +CC: stable@vger.kernel.org #3.0+ +Reported-by: Andrej Gelenberg +Signed-off-by: Wey-Yi Guy +Tested-by: Andrej Gelenberg +--- + drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +index a7a6def..5c7c17c 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +@@ -606,8 +606,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) + if (ctx->ht.enabled) { + /* if HT40 is used, it should not change + * after associated except channel switch */ +- if (iwl_is_associated_ctx(ctx) && +- !ctx->ht.is_40mhz) ++ if (!ctx->ht.is_40mhz || ++ !iwl_is_associated_ctx(ctx)) + iwlagn_config_ht40(conf, ctx); + } else + ctx->ht.is_40mhz = false; +-- +1.7.0.4 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index 1ea18dba8..9406cb826 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 5 +%global baserelease 6 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -803,6 +803,9 @@ Patch21045: nfs-client-freezer.patch #rhbz 590880 Patch21046: alps.patch +#rhbz 767173 +Patch21047: iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1477,6 +1480,9 @@ ApplyPatch nfs-client-freezer.patch #rhbz 590880 ApplyPatch alps.patch +#rhbz 767173 +ApplyPatch iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch + # END OF PATCH APPLICATIONS %endif @@ -2208,6 +2214,9 @@ fi # and build. %changelog +* Thu Dec 15 2011 Josh Boyer - 3.1.5-6 +- Add patch to fix Intel wifi regression in 3.1.5 (rhbz 767173) + * Thu Dec 15 2011 Dave Jones - 3.1.5-5 - Change configfs to be built-in. (rhbz 767857) From 9d2d81fc04489f16264db08c4d60426b3b509bd0 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 16 Dec 2011 14:11:46 +1000 Subject: [PATCH 178/487] drm: try harder to fix bad edids --- ...-try-harder-to-fix-up-broken-headers.patch | 47 +++++++++++++++++++ kernel.spec | 7 ++- 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 drm-edid-try-harder-to-fix-up-broken-headers.patch diff --git a/drm-edid-try-harder-to-fix-up-broken-headers.patch b/drm-edid-try-harder-to-fix-up-broken-headers.patch new file mode 100644 index 000000000..26660d767 --- /dev/null +++ b/drm-edid-try-harder-to-fix-up-broken-headers.patch @@ -0,0 +1,47 @@ +From 115cb7ab7d3b87fe43b1fe9b05ec894b1fcfb5cf Mon Sep 17 00:00:00 2001 +From: Adam Jackson +Date: Wed, 7 Dec 2011 18:26:23 -0500 +Subject: [PATCH] drm/edid: Try harder to fix up broken headers + +There's no reason to force the first byte to be correct if we're already +scoring how correct the header is. + +See also: https://bugzilla.redhat.com/show_bug.cgi?id=722909 + +Signed-off-by: Adam Jackson +--- + drivers/gpu/drm/drm_edid.c | 18 ++++++++---------- + 1 files changed, 8 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index 7425e5c..8b16a49 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -154,16 +154,14 @@ drm_edid_block_valid(u8 *raw_edid) + int i; + u8 csum = 0; + struct edid *edid = (struct edid *)raw_edid; +- +- if (raw_edid[0] == 0x00) { +- int score = drm_edid_header_is_valid(raw_edid); +- if (score == 8) ; +- else if (score >= 6) { +- DRM_DEBUG("Fixing EDID header, your hardware may be failing\n"); +- memcpy(raw_edid, edid_header, sizeof(edid_header)); +- } else { +- goto bad; +- } ++ int score = drm_edid_header_is_valid(raw_edid); ++ ++ if (score == 8) ; ++ else if (score >= 6) { ++ DRM_DEBUG("Fixing EDID header, your hardware may be failing\n"); ++ memcpy(raw_edid, edid_header, sizeof(edid_header)); ++ } else { ++ goto bad; + } + + for (i = 0; i < EDID_LENGTH; i++) +-- +1.7.7.3 + diff --git a/kernel.spec b/kernel.spec index 9406cb826..49a317cb9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 6 +%global baserelease 7 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -697,6 +697,7 @@ Patch901: asus-laptop-3.2-backport.patch Patch1500: fix_xen_guest_on_old_EC2.patch # DRM +Patch1700: drm-edid-try-harder-to-fix-up-broken-headers.patch # nouveau + drm fixes Patch1810: drm-nouveau-updates.patch @@ -1382,6 +1383,7 @@ ApplyPatch linux-2.6-e1000-ich9-montevina.patch ApplyPatch fix_xen_guest_on_old_EC2.patch # DRM core +ApplyPatch drm-edid-try-harder-to-fix-up-broken-headers.patch # Nouveau DRM ApplyOptionalPatch drm-nouveau-updates.patch @@ -2214,6 +2216,9 @@ fi # and build. %changelog +* Fri Dec 16 2011 Ben Skeggs - 3.1.5-7 +- Add patch to do a better job of dealing with busted EDID headers (rhbz#751589) + * Thu Dec 15 2011 Josh Boyer - 3.1.5-6 - Add patch to fix Intel wifi regression in 3.1.5 (rhbz 767173) From 117c274f5d5ba3fc2dcc01682a02d0f2339cad03 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 19 Dec 2011 19:03:00 -0500 Subject: [PATCH 179/487] x86, dumpstack: Fix code bytes breakage due to missing KERN_CONT --- kernel.spec | 8 ++++ x86-code-dump-fix-truncation.patch | 73 ++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 x86-code-dump-fix-truncation.patch diff --git a/kernel.spec b/kernel.spec index 49a317cb9..080777a45 100644 --- a/kernel.spec +++ b/kernel.spec @@ -771,6 +771,8 @@ Patch21022: mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch Patch21030: be2net-non-member-vlan-pkts-not-received-in-promisco.patch Patch21031: benet-remove-bogus-unlikely-on-vlan-check.patch +Patch21040: x86-code-dump-fix-truncation.patch + Patch21070: oom-fix-integer-overflow-of-points.patch #rhbz 728607 @@ -1447,6 +1449,9 @@ ApplyPatch mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch ApplyPatch be2net-non-member-vlan-pkts-not-received-in-promisco.patch ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch +#rhbz 736815 +ApplyPatch x86-code-dump-fix-truncation.patch + #rhbz 750402 ApplyPatch oom-fix-integer-overflow-of-points.patch @@ -2216,6 +2221,9 @@ fi # and build. %changelog +* Mon Dec 19 2011 Dave Jones +- x86, dumpstack: Fix code bytes breakage due to missing KERN_CONT + * Fri Dec 16 2011 Ben Skeggs - 3.1.5-7 - Add patch to do a better job of dealing with busted EDID headers (rhbz#751589) diff --git a/x86-code-dump-fix-truncation.patch b/x86-code-dump-fix-truncation.patch new file mode 100644 index 000000000..dcd5a815c --- /dev/null +++ b/x86-code-dump-fix-truncation.patch @@ -0,0 +1,73 @@ +From: Clemens Ladisch +Date: Mon, 19 Dec 2011 21:07:58 +0000 (+0100) +Subject: x86, dumpstack: Fix code bytes breakage due to missing KERN_CONT +X-Git-Url: https://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftip%2Ftip.git;a=commitdiff_plain;h=13f541c10b30fc6529200d7f9a0073217709622f + +x86, dumpstack: Fix code bytes breakage due to missing KERN_CONT + +When printing the code bytes in show_registers(), the markers around the +byte at the fault address could make the printk() format string look +like a valid log level and facility code. This would prevent this byte +from being printed and result in a spurious newline: + +[ 7555.765589] Code: 8b 32 e9 94 00 00 00 81 7d 00 ff 00 00 00 0f 87 96 00 00 00 48 8b 83 c0 00 00 00 44 89 e2 44 89 e6 48 89 df 48 8b 80 d8 02 00 00 +[ 7555.765683] 8b 48 28 48 89 d0 81 e2 ff 0f 00 00 48 c1 e8 0c 48 c1 e0 04 + +Add KERN_CONT where needed, and elsewhere in show_registers() for +consistency. + +Signed-off-by: Clemens Ladisch +Link: http://lkml.kernel.org/r/4EEFA7AE.9020407@ladisch.de +Signed-off-by: H. Peter Anvin +--- + +diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c +index 3b97a80..c99f9ed 100644 +--- a/arch/x86/kernel/dumpstack_32.c ++++ b/arch/x86/kernel/dumpstack_32.c +@@ -116,16 +116,16 @@ void show_registers(struct pt_regs *regs) + for (i = 0; i < code_len; i++, ip++) { + if (ip < (u8 *)PAGE_OFFSET || + probe_kernel_address(ip, c)) { +- printk(" Bad EIP value."); ++ printk(KERN_CONT " Bad EIP value."); + break; + } + if (ip == (u8 *)regs->ip) +- printk("<%02x> ", c); ++ printk(KERN_CONT "<%02x> ", c); + else +- printk("%02x ", c); ++ printk(KERN_CONT "%02x ", c); + } + } +- printk("\n"); ++ printk(KERN_CONT "\n"); + } + + int is_valid_bugaddr(unsigned long ip) +diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c +index 19853ad..6d728d9 100644 +--- a/arch/x86/kernel/dumpstack_64.c ++++ b/arch/x86/kernel/dumpstack_64.c +@@ -284,16 +284,16 @@ void show_registers(struct pt_regs *regs) + for (i = 0; i < code_len; i++, ip++) { + if (ip < (u8 *)PAGE_OFFSET || + probe_kernel_address(ip, c)) { +- printk(" Bad RIP value."); ++ printk(KERN_CONT " Bad RIP value."); + break; + } + if (ip == (u8 *)regs->ip) +- printk("<%02x> ", c); ++ printk(KERN_CONT "<%02x> ", c); + else +- printk("%02x ", c); ++ printk(KERN_CONT "%02x ", c); + } + } +- printk("\n"); ++ printk(KERN_CONT "\n"); + } + + int is_valid_bugaddr(unsigned long ip) From 62a0dcc84768b134f0e792b4badbdad94037585b Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 19 Dec 2011 19:27:44 -0500 Subject: [PATCH 180/487] Add versioned Obsoletes and Provides for kernel-tools -> perf --- kernel.spec | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/kernel.spec b/kernel.spec index 080777a45..b57257fea 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 7 +%global baserelease 8 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -119,7 +119,7 @@ Summary: The Linux kernel # tools %define with_tools %{?_without_tools: 0} %{?!_without_tools: 1} # kernel-debuginfo -%define with_debuginfo %{?_without_debuginfo: 0} %{?!_without_debuginfo: 1} +%define with_debuginfo %{?_without_debuginfo: 0} %{?!_without_debuginfo: 0} # kernel-bootwrapper (for creating zImages from kernel + initrd) %define with_bootwrapper %{?_without_bootwrapper: 0} %{?!_without_bootwrapper: 1} # Want to build a the vsdo directories installed @@ -163,7 +163,7 @@ Summary: The Linux kernel # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. -%define debugbuildsenabled 1 +%define debugbuildsenabled 0 # Want to build a vanilla kernel build without any non-upstream patches? %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} @@ -877,8 +877,8 @@ It provides the kernel source files common to all builds. Summary: Assortment of tools for the Linux kernel Group: Development/System License: GPLv2 -Obsoletes: perf -Provides: perf +Obsoletes: perf < 3.1.0-0.rc2.git7.2 +Provides: perf = %{version}-%{release} Provides: cpupowerutils = 1:009-0.6.p1 Obsoletes: cpupowerutils < 1:009-0.6.p1 Provides: cpufreq-utils = 1:009-0.6.p1 @@ -2221,6 +2221,11 @@ fi # and build. %changelog +* Mon Dec 19 2011 Kyle McMartin - 3.1.5-8 +- Add versioned Obsoletes and Provides for kernel-tools -> perf, hopefully + this should allow upgrades from kernel-tools to perf+kernel-tools in rawhide + from F-16. + * Mon Dec 19 2011 Dave Jones - x86, dumpstack: Fix code bytes breakage due to missing KERN_CONT From e3dc5c9709b86f1810ebb006034a1a7a9a54af0c Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 19 Dec 2011 20:14:15 -0500 Subject: [PATCH 181/487] Re-enable debuginfo/debug. Le sigh. --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index b57257fea..504fdc82f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -119,7 +119,7 @@ Summary: The Linux kernel # tools %define with_tools %{?_without_tools: 0} %{?!_without_tools: 1} # kernel-debuginfo -%define with_debuginfo %{?_without_debuginfo: 0} %{?!_without_debuginfo: 0} +%define with_debuginfo %{?_without_debuginfo: 0} %{?!_without_debuginfo: 1} # kernel-bootwrapper (for creating zImages from kernel + initrd) %define with_bootwrapper %{?_without_bootwrapper: 0} %{?!_without_bootwrapper: 1} # Want to build a the vsdo directories installed @@ -163,7 +163,7 @@ Summary: The Linux kernel # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. -%define debugbuildsenabled 0 +%define debugbuildsenabled 1 # Want to build a vanilla kernel build without any non-upstream patches? %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} From b769afb634571279b4d0892580a94b16b8d8ae54 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 20 Dec 2011 09:17:31 -0500 Subject: [PATCH 182/487] Backport upstream fix for b44_poll oops (rhbz #741117) --- b44-Use-dev_kfree_skb_irq-in-b44_tx.patch | 62 +++++++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 b44-Use-dev_kfree_skb_irq-in-b44_tx.patch diff --git a/b44-Use-dev_kfree_skb_irq-in-b44_tx.patch b/b44-Use-dev_kfree_skb_irq-in-b44_tx.patch new file mode 100644 index 000000000..ff50bd534 --- /dev/null +++ b/b44-Use-dev_kfree_skb_irq-in-b44_tx.patch @@ -0,0 +1,62 @@ +From 15ac2b08a2fd0f4aacbe8ae39788252fea6fbe63 Mon Sep 17 00:00:00 2001 +From: Xander Hover +Date: Wed, 23 Nov 2011 16:40:31 -0500 +Subject: [PATCH] b44: Use dev_kfree_skb_irq() in b44_tx() + +Reported issues when using dev_kfree_skb() on UP systems and +systems with low numbers of cores. dev_kfree_skb_irq() will +properly save IRQ state before freeing the skb. + +Tested on 3.1.1 and 3.2_rc2 + +Example of reproducible trace of kernel 3.1.1 +------------[ cut here ]------------ + WARNING: at kernel/softirq.c:159 local_bh_enable+0x32/0x79() + ... + Pid: 0, comm: swapper Not tainted 3.1.1-gentoo #1 + Call Trace: + [] warn_slowpath_common+0x65/0x7a + [] ? local_bh_enable+0x32/0x79 + [] warn_slowpath_null+0xf/0x13 + [] local_bh_enable+0x32/0x79 + [] destroy_conntrack+0x7c/0x9b + [] nf_conntrack_destroy+0x1f/0x26 + [] skb_release_head_state+0x74/0x83 + [] __kfree_skb+0xb/0x6b + [] consume_skb+0x24/0x26 + [] b44_poll+0xaa/0x449 + [] net_rx_action+0x3f/0xea + [] __do_softirq+0x5f/0xd5 + [] ? local_bh_enable+0x79/0x79 + [] ? irq_exit+0x34/0x8d + [] ? do_IRQ+0x74/0x87 + [] ? common_interrupt+0x29/0x30 + [] ? default_idle+0x29/0x3e + [] ? cpu_idle+0x2f/0x5d + [] ? rest_init+0x79/0x7b + [] ? start_kernel+0x297/0x29c + [] ? i386_start_kernel+0xb0/0xb7 + ---[ end trace 583f33bb1aa207a9 ]--- + +Signed-off-by: Xander Hover +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/broadcom/b44.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/b44.c b/drivers/net/b44.c +index 4cf835d..3fb66d0 100644 +--- a/drivers/net/b44.c ++++ b/drivers/net/b44.c +@@ -608,7 +608,7 @@ static void b44_tx(struct b44 *bp) + skb->len, + DMA_TO_DEVICE); + rp->skb = NULL; +- dev_kfree_skb(skb); ++ dev_kfree_skb_irq(skb); + } + + bp->tx_cons = cons; +-- +1.7.7.4 + diff --git a/kernel.spec b/kernel.spec index 504fdc82f..f163f0eee 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 8 +%global baserelease 9 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -809,6 +809,9 @@ Patch21046: alps.patch #rhbz 767173 Patch21047: iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch +#rhbz 741117 +Patch21048: b44-Use-dev_kfree_skb_irq-in-b44_tx.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1490,6 +1493,9 @@ ApplyPatch alps.patch #rhbz 767173 ApplyPatch iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch +#rhbz 741117 +ApplyPatch b44-Use-dev_kfree_skb_irq-in-b44_tx.patch + # END OF PATCH APPLICATIONS %endif @@ -2221,6 +2227,9 @@ fi # and build. %changelog +* Tue Dec 20 2011 Josh Boyer +- Backport upstream fix for b44_poll oops (rhbz #741117) + * Mon Dec 19 2011 Kyle McMartin - 3.1.5-8 - Add versioned Obsoletes and Provides for kernel-tools -> perf, hopefully this should allow upgrades from kernel-tools to perf+kernel-tools in rawhide From e3f2c2aa950cb583606d59681a64e7ede0ff8176 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 20 Dec 2011 14:51:53 -0500 Subject: [PATCH 183/487] Include crtsaves.o for ppc64 as well (rhbz #769415) --- kernel.spec | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index f163f0eee..c97b235e1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 9 +%global baserelease 10 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -1704,7 +1704,7 @@ BuildKernel() { fi rm -f $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/scripts/*.o rm -f $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/scripts/*/*.o -%ifarch ppc +%ifarch ppc ppc64 cp -a --parents arch/powerpc/lib/crtsavres.[So] $RPM_BUILD_ROOT/lib/modules/$KernelVer/build/ %endif if [ -d arch/%{asmarch}/include ]; then @@ -2229,6 +2229,7 @@ fi %changelog * Tue Dec 20 2011 Josh Boyer - Backport upstream fix for b44_poll oops (rhbz #741117) +- Include crtsaves.o for ppc64 as well (rhbz #769415) * Mon Dec 19 2011 Kyle McMartin - 3.1.5-8 - Add versioned Obsoletes and Provides for kernel-tools -> perf, hopefully From 40d1402b490798710d5d1e97262a45cb7fcbb095 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 20 Dec 2011 15:21:46 -0500 Subject: [PATCH 184/487] Drop EDID headers patch from 751589 for now (rhbz #769103) --- kernel.spec | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index c97b235e1..5c2ffacdf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -697,7 +697,7 @@ Patch901: asus-laptop-3.2-backport.patch Patch1500: fix_xen_guest_on_old_EC2.patch # DRM -Patch1700: drm-edid-try-harder-to-fix-up-broken-headers.patch +#atch1700: drm-edid-try-harder-to-fix-up-broken-headers.patch # nouveau + drm fixes Patch1810: drm-nouveau-updates.patch @@ -1388,7 +1388,7 @@ ApplyPatch linux-2.6-e1000-ich9-montevina.patch ApplyPatch fix_xen_guest_on_old_EC2.patch # DRM core -ApplyPatch drm-edid-try-harder-to-fix-up-broken-headers.patch +#ApplyPatch drm-edid-try-harder-to-fix-up-broken-headers.patch # Nouveau DRM ApplyOptionalPatch drm-nouveau-updates.patch @@ -2230,6 +2230,7 @@ fi * Tue Dec 20 2011 Josh Boyer - Backport upstream fix for b44_poll oops (rhbz #741117) - Include crtsaves.o for ppc64 as well (rhbz #769415) +- Drop EDID headers patch from 751589 for now (rhbz #769103) * Mon Dec 19 2011 Kyle McMartin - 3.1.5-8 - Add versioned Obsoletes and Provides for kernel-tools -> perf, hopefully From e091c2ac6ef1f6c450d5bd3527026cb24c5bd0e5 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 20 Dec 2011 18:22:00 -0500 Subject: [PATCH 185/487] Delay after aborting command in tpm_tis (rhbz #746097) --- kernel.spec | 9 +++++++++ tpm_tis-delay-after-aborting-cmd.patch | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tpm_tis-delay-after-aborting-cmd.patch diff --git a/kernel.spec b/kernel.spec index 5c2ffacdf..2aa57e4e7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -812,6 +812,9 @@ Patch21047: iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch #rhbz 741117 Patch21048: b44-Use-dev_kfree_skb_irq-in-b44_tx.patch +#rhbz 746097 +Patch21049: tpm_tis-delay-after-aborting-cmd.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1496,6 +1499,9 @@ ApplyPatch iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch #rhbz 741117 ApplyPatch b44-Use-dev_kfree_skb_irq-in-b44_tx.patch +#rhbz 746097 +ApplyPatch tpm_tis-delay-after-aborting-cmd.patch + # END OF PATCH APPLICATIONS %endif @@ -2227,6 +2233,9 @@ fi # and build. %changelog +* Tue Dec 20 2011 Dave Jones +- Delay after aborting command in tpm_tis (rhbz #746097) + * Tue Dec 20 2011 Josh Boyer - Backport upstream fix for b44_poll oops (rhbz #741117) - Include crtsaves.o for ppc64 as well (rhbz #769415) diff --git a/tpm_tis-delay-after-aborting-cmd.patch b/tpm_tis-delay-after-aborting-cmd.patch new file mode 100644 index 000000000..315284f50 --- /dev/null +++ b/tpm_tis-delay-after-aborting-cmd.patch @@ -0,0 +1,17 @@ +This patch adds a delay after aborting a command. Some TPMs need +this and will not process the subsequent command correctly otherwise. + +Signed-off-by: Stefan Berger + +--- linux-3.1.noarch/drivers/char/tpm/tpm_tis.c~ 2011-12-20 18:08:01.654464487 -0500 ++++ linux-3.1.noarch/drivers/char/tpm/tpm_tis.c 2011-12-20 18:08:23.476380364 -0500 +@@ -432,6 +432,9 @@ static int probe_itpm(struct tpm_chip *c + out: + itpm = rem_itpm; + tpm_tis_ready(chip); ++ /* some TPMs need a break here otherwise they will not work ++ * correctly on the immediately subsequent command */ ++ msleep(chip->vendor.timeout_b); + release_locality(chip, chip->vendor.locality, 0); + + return rc; From 98c21d3e9c208c589faec4ab1cd5e4675ad3449f Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 22 Nov 2011 16:16:30 -0500 Subject: [PATCH 186/487] - Revise compat-wireless configuration - Enable with-backports by default - Update compat-wireless snaptshot from verstion 3.2-rc6-3 --- ...-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch | 29 +++++++++ compat-wireless-config-fixups.patch | 64 +++++++++++++++++++ config-backports | 19 ++++++ kernel.spec | 55 ++++++++++++++-- sources | 2 +- 5 files changed, 163 insertions(+), 6 deletions(-) create mode 100644 compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch create mode 100644 compat-wireless-config-fixups.patch create mode 100644 config-backports diff --git a/compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch b/compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch new file mode 100644 index 000000000..98caeb56f --- /dev/null +++ b/compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch @@ -0,0 +1,29 @@ +From c5cfdf2d138ba20a648990d9615c44942eef5fd3 Mon Sep 17 00:00:00 2001 +From: John W. Linville +Date: Fri, 18 Nov 2011 13:46:18 -0500 +Subject: [PATCH] compat-wireless: change CONFIG_IWLAGN -> CONFIG_IWLWIFI + +This Kconfig option changed in the 2.6.32 timeframe. + +Signed-off-by: John W. Linville +Signed-off-by: Luis R. Rodriguez +--- + config.mk | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/config.mk b/config.mk +index 0e964a5..05edb79 100644 +--- a/config.mk ++++ b/config.mk +@@ -285,7 +285,7 @@ ifdef CONFIG_PCI + CONFIG_ATH5K_PCI=y + CONFIG_ATH9K_PCI=y + +-CONFIG_IWLAGN=m ++CONFIG_IWLWIFI=m + # CONFIG_IWLWIFI_DEBUG=y + # CONFIG_IWLWIFI_DEBUGFS=y + # CONFIG_IWLWIFI_DEVICE_TRACING=y +-- +1.7.4.4 + diff --git a/compat-wireless-config-fixups.patch b/compat-wireless-config-fixups.patch new file mode 100644 index 000000000..411ee40c6 --- /dev/null +++ b/compat-wireless-config-fixups.patch @@ -0,0 +1,64 @@ +diff -up compat-wireless-3.2-rc1-1/config.mk.orig compat-wireless-3.2-rc1-1/config.mk +--- compat-wireless-3.2-rc1-1/config.mk.orig 2011-11-22 13:09:50.422879313 -0500 ++++ compat-wireless-3.2-rc1-1/config.mk 2011-11-22 13:10:28.870398679 -0500 +@@ -14,6 +14,9 @@ else + include $(KLIB_BUILD)/.config + endif + ++# Enable SSB module (needs to be visible in compat_autoconf.h) ++CONFIG_SSB=m ++ + ifneq ($(wildcard $(KLIB_BUILD)/Makefile),) + + COMPAT_LATEST_VERSION = 1 +diff -up compat-wireless-3.2-rc1-1/drivers/misc/eeprom/Makefile.orig compat-wireless-3.2-rc1-1/drivers/misc/eeprom/Makefile +--- compat-wireless-3.2-rc1-1/drivers/misc/eeprom/Makefile.orig 2011-11-22 13:09:50.423879301 -0500 ++++ compat-wireless-3.2-rc1-1/drivers/misc/eeprom/Makefile 2011-11-22 13:10:28.871398662 -0500 +@@ -1,3 +1,3 @@ +-obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o ++#obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o + obj-$(CONFIG_EEPROM_93XX46) += eeprom_93xx46.o + obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o +diff -up compat-wireless-3.2-rc1-1/drivers/net/ethernet/atheros/Makefile.orig compat-wireless-3.2-rc1-1/drivers/net/ethernet/atheros/Makefile +--- compat-wireless-3.2-rc1-1/drivers/net/ethernet/atheros/Makefile.orig 2011-11-22 13:09:50.423879301 -0500 ++++ compat-wireless-3.2-rc1-1/drivers/net/ethernet/atheros/Makefile 2011-11-22 13:10:28.871398662 -0500 +@@ -2,7 +2,7 @@ + # Makefile for the Atheros network device drivers. + # + +-obj-$(CONFIG_ATL1) += atlx/ +-obj-$(CONFIG_ATL2) += atlx/ +-obj-$(CONFIG_ATL1E) += atl1e/ +-obj-$(CONFIG_ATL1C) += atl1c/ ++#obj-$(CONFIG_ATL1) += atlx/ ++#obj-$(CONFIG_ATL2) += atlx/ ++#obj-$(CONFIG_ATL1E) += atl1e/ ++#obj-$(CONFIG_ATL1C) += atl1c/ +diff -up compat-wireless-3.2-rc1-1/drivers/net/usb/Makefile.orig compat-wireless-3.2-rc1-1/drivers/net/usb/Makefile +--- compat-wireless-3.2-rc1-1/drivers/net/usb/Makefile.orig 2011-11-22 13:09:50.424879289 -0500 ++++ compat-wireless-3.2-rc1-1/drivers/net/usb/Makefile 2011-11-22 13:10:28.872398646 -0500 +@@ -2,7 +2,7 @@ + # Makefile for USB Network drivers + # + +-obj-$(CONFIG_USB_NET_COMPAT_CDCETHER) += cdc_ether.o +-obj-$(CONFIG_USB_NET_COMPAT_RNDIS_HOST) += rndis_host.o +-obj-$(CONFIG_USB_COMPAT_USBNET) += usbnet.o ++#obj-$(CONFIG_USB_NET_COMPAT_CDCETHER) += cdc_ether.o ++#obj-$(CONFIG_USB_NET_COMPAT_RNDIS_HOST) += rndis_host.o ++#obj-$(CONFIG_USB_COMPAT_USBNET) += usbnet.o + +diff -up compat-wireless-3.2-rc1-1/Makefile.orig compat-wireless-3.2-rc1-1/Makefile +--- compat-wireless-3.2-rc1-1/Makefile.orig 2011-11-22 13:10:37.165294951 -0500 ++++ compat-wireless-3.2-rc1-1/Makefile 2011-11-22 13:10:47.335167758 -0500 +@@ -41,8 +41,8 @@ endif + + endif + +-obj-$(CONFIG_COMPAT_BLUETOOTH) += net/bluetooth/ +-obj-$(CONFIG_COMPAT_BLUETOOTH_MODULES) += drivers/bluetooth/ ++#obj-$(CONFIG_COMPAT_BLUETOOTH) += net/bluetooth/ ++#obj-$(CONFIG_COMPAT_BLUETOOTH_MODULES) += drivers/bluetooth/ + + else + diff --git a/config-backports b/config-backports new file mode 100644 index 000000000..c1b178176 --- /dev/null +++ b/config-backports @@ -0,0 +1,19 @@ +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# CONFIG_MAC80211 is not set + +# CONFIG_BCMA is not set + +# +# ssb and b44 share infrastructure with b43 +# +# CONFIG_SSB is not set +# CONFIG_B44 is not set + +# +# These have to be turned-on again since compat-wireless does not +# provide them... +# +CONFIG_CRC7=m +CONFIG_AVERAGE=y diff --git a/kernel.spec b/kernel.spec index 2aa57e4e7..b7f1ef583 100644 --- a/kernel.spec +++ b/kernel.spec @@ -158,7 +158,7 @@ Summary: The Linux kernel %define with_sparse %{?_with_sparse: 1} %{?!_with_sparse: 0} # Include driver backports (e.g. compat-wireless) in the kernel build. -%define with_backports %{?_with_backports: 1} %{?!_with_backports: 0} +%define with_backports %{?_without_backports: 0} %{?!_without_backports: 1} # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). @@ -199,8 +199,18 @@ Summary: The Linux kernel %define kversion 3.%{base_sublevel} # The compat-wireless version -# (If this is less than kversion, make sure with_backports is turned-off.) -%define cwversion 3.2-rc1-1 +%define cwversion 3.2-rc6-3 + +####################################################################### +# If cwversion is less than kversion, make sure with_backports is +# turned-off. +# +# For rawhide, disable with_backports immediately after a rebase... +# +# (Uncomment the '#' and both spaces below to disable with_backports.) +# +# % define with_backports 0 +####################################################################### %define make_target bzImage @@ -485,7 +495,7 @@ Summary: The Linux kernel # Packages that need to be installed before the kernel is, because the %%post # scripts use them. # -%define kernel_prereq fileutils, module-init-tools >= 3.16-2, initscripts >= 8.11.1-1, grubby >= 8.3-1 +%define kernel_prereq fileutils, module-init-tools >= 3.16-5, initscripts >= 8.11.1-1, grubby >= 8.3-1 %define initrd_prereq dracut >= 001-7 # @@ -598,6 +608,8 @@ Source100: config-arm-generic Source110: config-arm-omap-generic Source111: config-arm-tegra +Source200: config-backports + # This file is intentionally left empty in the stock kernel. Its a nicety # added for those wanting to do custom rebuilds with altered config opts. Source1000: config-local @@ -815,6 +827,10 @@ Patch21048: b44-Use-dev_kfree_skb_irq-in-b44_tx.patch #rhbz 746097 Patch21049: tpm_tis-delay-after-aborting-cmd.patch +# compat-wireless patches +Patch50000: compat-wireless-config-fixups.patch +Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1257,6 +1273,16 @@ cp %{SOURCE15} . # Dynamically generate kernel .config files from config-* files make -f %{SOURCE20} VERSION=%{version} configs +%if %{with_backports} +# Turn-off bits provided by compat-wireless +for i in %{all_arch_configs} +do + mv $i $i.tmp + ./merge.pl %{SOURCE200} $i.tmp > $i + rm $i.tmp +done +%endif + %if %{?all_arch_configs:1}%{!?all_arch_configs:0} #if a rhel kernel, apply the rhel config options %if 0%{?rhel} @@ -1470,10 +1496,12 @@ ApplyPatch ideapad-Check-if-acpi-already-handle-backlight.patch #rhbz 752176 ApplyPatch sysfs-msi-irq-per-device.patch +%if !%{with_backports} #backport brcm80211 from 3.2-rc1 ApplyPatch brcm80211.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch +%endif # rhbz 754907 ApplyPatch cciss-fix-irqf-shared.patch @@ -1559,9 +1587,22 @@ cd .. %if %{with_backports} +# Always start fresh +rm -rf compat-wireless-%{cwversion} + # Extract the compat-wireless bits %setup -q -n kernel-%{kversion}%{?dist} -T -D -a 1 +cd compat-wireless-%{cwversion} + +ApplyPatch compat-wireless-config-fixups.patch +ApplyPatch compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch + +# Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 +ApplyPatch bcma-brcmsmac-compat.patch + +cd .. + %endif ### @@ -1798,7 +1839,6 @@ BuildKernel() { %if %{with_backports} cd ../compat-wireless-%{cwversion}/ - make clean make KLIB_BUILD=../linux-%{kversion}.%{_target_cpu} \ KMODPATH_ARG="INSTALL_MOD_PATH=$RPM_BUILD_ROOT" \ @@ -2233,6 +2273,11 @@ fi # and build. %changelog +* Wed Dec 21 2011 John W. Linville +- Revise compat-wireless configuration +- Enable with-backports by default +- Update compat-wireless snaptshot from verstion 3.2-rc6-3 + * Tue Dec 20 2011 Dave Jones - Delay after aborting command in tpm_tis (rhbz #746097) diff --git a/sources b/sources index f6c7fc19c..86944d85b 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 -6693d8c42055f83f5701d9b65d47208a compat-wireless-3.2-rc1-1.tar.bz2 84c040bb8c4f46d351731cb0c05d9474 patch-3.1.5.bz2 +656f2b85102dc935039e867abd08b880 compat-wireless-3.2-rc6-3.tar.bz2 From c419e42152ac2c95e09027416bb34b7ea5ffc94b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 21 Dec 2011 14:21:35 -0500 Subject: [PATCH 187/487] Reinstate the route cache garbage collector. --- kernel.spec | 7 + route-cache-garbage-collector.patch | 201 ++++++++++++++++++++++++++++ 2 files changed, 208 insertions(+) create mode 100644 route-cache-garbage-collector.patch diff --git a/kernel.spec b/kernel.spec index b7f1ef583..091cf1b32 100644 --- a/kernel.spec +++ b/kernel.spec @@ -831,6 +831,8 @@ Patch21049: tpm_tis-delay-after-aborting-cmd.patch Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch +Patch22000: route-cache-garbage-collector.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1530,6 +1532,8 @@ ApplyPatch b44-Use-dev_kfree_skb_irq-in-b44_tx.patch #rhbz 746097 ApplyPatch tpm_tis-delay-after-aborting-cmd.patch +ApplyPatch route-cache-garbage-collector.patch + # END OF PATCH APPLICATIONS %endif @@ -2273,6 +2277,9 @@ fi # and build. %changelog +* Wed Dec 21 2011 Dave Jones 3.1.5-10 +- Reinstate the route cache garbage collector. + * Wed Dec 21 2011 John W. Linville - Revise compat-wireless configuration - Enable with-backports by default diff --git a/route-cache-garbage-collector.patch b/route-cache-garbage-collector.patch new file mode 100644 index 000000000..6ea6e5e9b --- /dev/null +++ b/route-cache-garbage-collector.patch @@ -0,0 +1,201 @@ +Message-ID: <1324461072.2728.19.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC> +Subject: Re: Kernel-DOS error in arp mechanism =?UTF-8?Q?=E2=80=93?= no delete off incomplete arp adresses +From: Eric Dumazet +To: David Miller +Cc: richard.weinberger@gmail.com, gladewitz@gmx.de, + linux-kernel@vger.kernel.org, netdev@vger.kernel.org +Date: Wed, 21 Dec 2011 10:51:12 +0100 +In-Reply-To: <20111221.030727.1528369698756365464.davem@davemloft.net> +References: <4EEC5286.3070408@gmx.de> + + <1324453467.2610.20.camel@edumazet-laptop> + <20111221.030727.1528369698756365464.davem@davemloft.net> +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit +Sender: linux-kernel-owner@vger.kernel.org +List-ID: + +Le mercredi 21 décembre 2011 à 03:07 -0500, David Miller a écrit : +> From: Eric Dumazet +> Date: Wed, 21 Dec 2011 08:44:27 +0100 +> +> > David, I suggest we add back the garbage collector for current kernels, +> > we'll remove it when route cache really disappear ? +> > +> > I'll send a patch today. +> +> Yes, it's the best idea. +> +> We can actually remove it again as early as when when route neigh's +> are ref-less. + +Here is the patch I successfully tested in the neighbour stress +situation. This is a stable candidate (2.6.39+) + +Thanks ! + +[PATCH] ipv4: reintroduce route cache garbage collector + +Commit 2c8cec5c10b (ipv4: Cache learned PMTU information in inetpeer) +removed IP route cache garbage collector a bit too soon, as this gc was +responsible for expired routes cleanup, releasing their neighbour +reference. + +As pointed out by Robert Gladewitz, recent kernels can fill and exhaust +their neighbour cache. + +Reintroduce the garbage collection, since we'll have to wait our +neighbour lookups become refcount-less to not depend on this stuff. + +Reported-by: Robert Gladewitz +Signed-off-by: Eric Dumazet +--- + net/ipv4/route.c | 107 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 107 insertions(+) + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 46af623..252c512 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -133,6 +134,9 @@ static int ip_rt_min_advmss __read_mostly = 256; + static int rt_chain_length_max __read_mostly = 20; + static int redirect_genid; + ++static struct delayed_work expires_work; ++static unsigned long expires_ljiffies; ++ + /* + * Interface to generic destination cache. + */ +@@ -830,6 +834,97 @@ static int has_noalias(const struct rtable *head, const struct rtable *rth) + return ONE; + } + ++static void rt_check_expire(void) ++{ ++ static unsigned int rover; ++ unsigned int i = rover, goal; ++ struct rtable *rth; ++ struct rtable __rcu **rthp; ++ unsigned long samples = 0; ++ unsigned long sum = 0, sum2 = 0; ++ unsigned long delta; ++ u64 mult; ++ ++ delta = jiffies - expires_ljiffies; ++ expires_ljiffies = jiffies; ++ mult = ((u64)delta) << rt_hash_log; ++ if (ip_rt_gc_timeout > 1) ++ do_div(mult, ip_rt_gc_timeout); ++ goal = (unsigned int)mult; ++ if (goal > rt_hash_mask) ++ goal = rt_hash_mask + 1; ++ for (; goal > 0; goal--) { ++ unsigned long tmo = ip_rt_gc_timeout; ++ unsigned long length; ++ ++ i = (i + 1) & rt_hash_mask; ++ rthp = &rt_hash_table[i].chain; ++ ++ if (need_resched()) ++ cond_resched(); ++ ++ samples++; ++ ++ if (rcu_dereference_raw(*rthp) == NULL) ++ continue; ++ length = 0; ++ spin_lock_bh(rt_hash_lock_addr(i)); ++ while ((rth = rcu_dereference_protected(*rthp, ++ lockdep_is_held(rt_hash_lock_addr(i)))) != NULL) { ++ prefetch(rth->dst.rt_next); ++ if (rt_is_expired(rth)) { ++ *rthp = rth->dst.rt_next; ++ rt_free(rth); ++ continue; ++ } ++ if (rth->dst.expires) { ++ /* Entry is expired even if it is in use */ ++ if (time_before_eq(jiffies, rth->dst.expires)) { ++nofree: ++ tmo >>= 1; ++ rthp = &rth->dst.rt_next; ++ /* ++ * We only count entries on ++ * a chain with equal hash inputs once ++ * so that entries for different QOS ++ * levels, and other non-hash input ++ * attributes don't unfairly skew ++ * the length computation ++ */ ++ length += has_noalias(rt_hash_table[i].chain, rth); ++ continue; ++ } ++ } else if (!rt_may_expire(rth, tmo, ip_rt_gc_timeout)) ++ goto nofree; ++ ++ /* Cleanup aged off entries. */ ++ *rthp = rth->dst.rt_next; ++ rt_free(rth); ++ } ++ spin_unlock_bh(rt_hash_lock_addr(i)); ++ sum += length; ++ sum2 += length*length; ++ } ++ if (samples) { ++ unsigned long avg = sum / samples; ++ unsigned long sd = int_sqrt(sum2 / samples - avg*avg); ++ rt_chain_length_max = max_t(unsigned long, ++ ip_rt_gc_elasticity, ++ (avg + 4*sd) >> FRACT_BITS); ++ } ++ rover = i; ++} ++ ++/* ++ * rt_worker_func() is run in process context. ++ * we call rt_check_expire() to scan part of the hash table ++ */ ++static void rt_worker_func(struct work_struct *work) ++{ ++ rt_check_expire(); ++ schedule_delayed_work(&expires_work, ip_rt_gc_interval); ++} ++ + /* + * Perturbation of rt_genid by a small quantity [1..256] + * Using 8 bits of shuffling ensure we can call rt_cache_invalidate() +@@ -3179,6 +3274,13 @@ static ctl_table ipv4_route_table[] = { + .proc_handler = proc_dointvec_jiffies, + }, + { ++ .procname = "gc_interval", ++ .data = &ip_rt_gc_interval, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_jiffies, ++ }, ++ { + .procname = "redirect_load", + .data = &ip_rt_redirect_load, + .maxlen = sizeof(int), +@@ -3388,6 +3490,11 @@ int __init ip_rt_init(void) + devinet_init(); + ip_fib_init(); + ++ INIT_DELAYED_WORK_DEFERRABLE(&expires_work, rt_worker_func); ++ expires_ljiffies = jiffies; ++ schedule_delayed_work(&expires_work, ++ net_random() % ip_rt_gc_interval + ip_rt_gc_interval); ++ + if (ip_rt_proc_init()) + printk(KERN_ERR "Unable to create route proc files\n"); + #ifdef CONFIG_XFRM + + +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ + From dd40e894db395fb9d26a02428b24ecfa0cd969e1 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 21 Dec 2011 14:24:42 -0500 Subject: [PATCH 188/487] fix up versions. --- kernel.spec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 091cf1b32..b4a11046c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 10 +%global baserelease 11 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2277,7 +2277,7 @@ fi # and build. %changelog -* Wed Dec 21 2011 Dave Jones 3.1.5-10 +* Wed Dec 21 2011 Dave Jones 3.1.5-11 - Reinstate the route cache garbage collector. * Wed Dec 21 2011 John W. Linville @@ -2285,7 +2285,7 @@ fi - Enable with-backports by default - Update compat-wireless snaptshot from verstion 3.2-rc6-3 -* Tue Dec 20 2011 Dave Jones +* Tue Dec 20 2011 Dave Jones 3.1.5-10 - Delay after aborting command in tpm_tis (rhbz #746097) * Tue Dec 20 2011 Josh Boyer From 02606c8511ed53f3653cfc59204b1d6603b6d0de Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 21 Dec 2011 14:32:55 -0500 Subject: [PATCH 189/487] Apply some iwlwifi regression fixes not in the 3.2-rc6 wireless snapshot Turn-off with_backports for s390x --- ...-to-switch-to-HT40-if-not-associated.patch | 12 ++--- iwlwifi-tx_sync-only-on-PAN-context.patch | 44 +++++++++++++++++++ kernel.spec | 10 +++++ 3 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 iwlwifi-tx_sync-only-on-PAN-context.patch diff --git a/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch b/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch index 08c9e443b..7ded9c83a 100644 --- a/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch +++ b/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch @@ -1,3 +1,8 @@ +From 78feb35b8161acd95c33a703ed6ab6f554d29387 Mon Sep 17 00:00:00 2001 +From: Wey-Yi Guy +Date: Wed, 14 Dec 2011 08:22:36 -0800 +Subject: [PATCH 2/2] iwlwifi: allow to switch to HT40 if not associated + My previous patch 34a5b4b6af104cf18eb50748509528b9bdbc4036 iwlwifi: do not re-configure HT40 after associated @@ -10,6 +15,7 @@ CC: stable@vger.kernel.org #3.0+ Reported-by: Andrej Gelenberg Signed-off-by: Wey-Yi Guy Tested-by: Andrej Gelenberg +Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) @@ -30,9 +36,5 @@ index a7a6def..5c7c17c 100644 } else ctx->ht.is_40mhz = false; -- -1.7.0.4 +1.7.4.4 --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/iwlwifi-tx_sync-only-on-PAN-context.patch b/iwlwifi-tx_sync-only-on-PAN-context.patch new file mode 100644 index 000000000..16086c0fa --- /dev/null +++ b/iwlwifi-tx_sync-only-on-PAN-context.patch @@ -0,0 +1,44 @@ +From 81670a491849127cd5f86defd2cd03cef1b08d07 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 14 Dec 2011 08:22:35 -0800 +Subject: [PATCH 1/2] iwlwifi: tx_sync only on PAN context + +Ted reported that he couldn't connect to some APs +and bisected it to the tx_sync implementation. +Disable it for the BSS context to fix this issue. + +Reported-by: Ted Ts'o +Signed-off-by: Johannes Berg +Signed-off-by: Wey-Yi Guy +Signed-off-by: John W. Linville +--- + drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ++++++ + 1 files changed, 6 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c +index bacc06c..e0e9a3d 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn.c +@@ -2850,6 +2850,9 @@ static int iwlagn_mac_tx_sync(struct ieee80211_hw *hw, + int ret; + u8 sta_id; + ++ if (ctx->ctxid != IWL_RXON_CTX_PAN) ++ return 0; ++ + IWL_DEBUG_MAC80211(priv, "enter\n"); + mutex_lock(&priv->shrd->mutex); + +@@ -2898,6 +2901,9 @@ static void iwlagn_mac_finish_tx_sync(struct ieee80211_hw *hw, + struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; + struct iwl_rxon_context *ctx = vif_priv->ctx; + ++ if (ctx->ctxid != IWL_RXON_CTX_PAN) ++ return; ++ + IWL_DEBUG_MAC80211(priv, "enter\n"); + mutex_lock(&priv->shrd->mutex); + +-- +1.7.4.4 + diff --git a/kernel.spec b/kernel.spec index b4a11046c..0f5101aae 100644 --- a/kernel.spec +++ b/kernel.spec @@ -371,6 +371,7 @@ Summary: The Linux kernel %define make_target image %define kernel_image arch/s390/boot/image %define with_tools 0 +%define with_backports 0 %endif %ifarch sparc64 @@ -830,6 +831,7 @@ Patch21049: tpm_tis-delay-after-aborting-cmd.patch # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch +Patch50100: iwlwifi-tx_sync-only-on-PAN-context.patch Patch22000: route-cache-garbage-collector.patch @@ -1605,6 +1607,10 @@ ApplyPatch compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch +# Apply some iwlwifi regression fixes not in the 3.2-rc6 wireless snapshot +ApplyPatch iwlwifi-tx_sync-only-on-PAN-context.patch +ApplyPatch iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch + cd .. %endif @@ -2277,6 +2283,10 @@ fi # and build. %changelog +* Wed Dec 21 2011 John W. Linville +- Apply some iwlwifi regression fixes not in the 3.2-rc6 wireless snapshot +- Turn-off with_backports for s390x + * Wed Dec 21 2011 Dave Jones 3.1.5-11 - Reinstate the route cache garbage collector. From e1481910fdcd83044d300ab1243792a3c5ab7861 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 21 Dec 2011 17:12:53 -0500 Subject: [PATCH 190/487] Linux 3.1.6 --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 0f5101aae..bb92a1344 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 11 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 5 +%define stable_update 6 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2283,6 +2283,9 @@ fi # and build. %changelog +* Wed Dec 21 2011 Dave Jones 3.1.6-1 +- Linux 3.1.6 + * Wed Dec 21 2011 John W. Linville - Apply some iwlwifi regression fixes not in the 3.2-rc6 wireless snapshot - Turn-off with_backports for s390x diff --git a/sources b/sources index 86944d85b..4f88bd4c8 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 -84c040bb8c4f46d351731cb0c05d9474 patch-3.1.5.bz2 656f2b85102dc935039e867abd08b880 compat-wireless-3.2-rc6-3.tar.bz2 +b815dda0a05f7774a0ed0b705b8cfd4c patch-3.1.6.bz2 From 2e7bab382217ef947c8016501132091da337baeb Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 22 Dec 2011 09:34:47 -0500 Subject: [PATCH 191/487] iwlwifi: do not set the sequence control bit is not needed ath9k: fix max phy rate at rate control init mwifiex: avoid double list_del in command cancel path iwlwifi: update SCD BC table for all SCD queues --- ...ix-max-phy-rate-at-rate-control-init.patch | 37 ++++++++++++ ...et-the-sequence-control-bit-is-not-n.patch | 37 ++++++++++++ ...date-SCD-BC-table-for-all-SCD-queues.patch | 36 +++++++++++ kernel.spec | 14 +++++ ...uble-list_del-in-command-cancel-path.patch | 59 +++++++++++++++++++ 5 files changed, 183 insertions(+) create mode 100644 ath9k-fix-max-phy-rate-at-rate-control-init.patch create mode 100644 iwlwifi-do-not-set-the-sequence-control-bit-is-not-n.patch create mode 100644 iwlwifi-update-SCD-BC-table-for-all-SCD-queues.patch create mode 100644 mwifiex-avoid-double-list_del-in-command-cancel-path.patch diff --git a/ath9k-fix-max-phy-rate-at-rate-control-init.patch b/ath9k-fix-max-phy-rate-at-rate-control-init.patch new file mode 100644 index 000000000..cb0719b7c --- /dev/null +++ b/ath9k-fix-max-phy-rate-at-rate-control-init.patch @@ -0,0 +1,37 @@ +From 10636bc2d60942254bda149827b922c41f4cb4af Mon Sep 17 00:00:00 2001 +From: Rajkumar Manoharan +Date: Sat, 10 Dec 2011 18:59:43 +0530 +Subject: [PATCH 03/10] ath9k: fix max phy rate at rate control init + +The stations always chooses 1Mbps for all trasmitting frames, +whenever the AP is configured to lock the supported rates. +As the max phy rate is always set with the 4th from highest phy rate, +this assumption might be wrong if we have less than that. Fix that. + +Cc: stable@kernel.org +Cc: Paul Stewart +Reported-by: Ajay Gummalla +Signed-off-by: Rajkumar Manoharan +Signed-off-by: John W. Linville +--- + drivers/net/wireless/ath/ath9k/rc.c | 4 +++- + 1 files changed, 3 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c +index 8448281..cc5703b 100644 +--- a/drivers/net/wireless/ath/ath9k/rc.c ++++ b/drivers/net/wireless/ath/ath9k/rc.c +@@ -1270,7 +1270,9 @@ static void ath_rc_init(struct ath_softc *sc, + + ath_rc_priv->max_valid_rate = k; + ath_rc_sort_validrates(rate_table, ath_rc_priv); +- ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4]; ++ ath_rc_priv->rate_max_phy = (k > 4) ? ++ ath_rc_priv->valid_rate_index[k-4] : ++ ath_rc_priv->valid_rate_index[k-1]; + ath_rc_priv->rate_table = rate_table; + + ath_dbg(common, ATH_DBG_CONFIG, +-- +1.7.4.4 + diff --git a/iwlwifi-do-not-set-the-sequence-control-bit-is-not-n.patch b/iwlwifi-do-not-set-the-sequence-control-bit-is-not-n.patch new file mode 100644 index 000000000..d65d1a790 --- /dev/null +++ b/iwlwifi-do-not-set-the-sequence-control-bit-is-not-n.patch @@ -0,0 +1,37 @@ +From 123877b80ed62c3b897c53357b622574c023b642 Mon Sep 17 00:00:00 2001 +From: Wey-Yi Guy +Date: Thu, 8 Dec 2011 15:52:00 -0800 +Subject: [PATCH 01/10] iwlwifi: do not set the sequence control bit is not + needed + +Check the IEEE80211_TX_CTL_ASSIGN_SEQ flag from mac80211, then decide how to +set the TX_CMD_FLG_SEQ_CTL_MSK bit. Setting the wrong bit in BAR frame whill +make the firmware to increment the sequence number which is incorrect and +cause unknown behavior. + +CC: stable@vger.kernel.org #3.0+ +Signed-off-by: Wey-Yi Guy +Signed-off-by: John W. Linville +--- + drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 5 ++++- + 1 files changed, 4 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +index 35a6b71..df1540c 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +@@ -91,7 +91,10 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, + tx_cmd->tid_tspec = qc[0] & 0xf; + tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; + } else { +- tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; ++ if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) ++ tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; ++ else ++ tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; + } + + iwlagn_tx_cmd_protection(priv, info, fc, &tx_flags); +-- +1.7.4.4 + diff --git a/iwlwifi-update-SCD-BC-table-for-all-SCD-queues.patch b/iwlwifi-update-SCD-BC-table-for-all-SCD-queues.patch new file mode 100644 index 000000000..f25d6e043 --- /dev/null +++ b/iwlwifi-update-SCD-BC-table-for-all-SCD-queues.patch @@ -0,0 +1,36 @@ +From 96f1f05af76b601ab21a7dc603ae0a1cea4efc3d Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Fri, 16 Dec 2011 07:53:18 -0800 +Subject: [PATCH 10/10] iwlwifi: update SCD BC table for all SCD queues + +Since we configure all the queues as CHAINABLE, we need to update the +byte count for all the queues, not only the AGGREGATABLE ones. + +Not doing so can confuse the SCD and make the fw assert. + +Cc: stable@vger.kernel.org +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Wey-Yi Guy +Signed-off-by: John W. Linville +--- + drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 4 +--- + 1 files changed, 1 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +index ce91898..5f17ab8 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c ++++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +@@ -1197,9 +1197,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, + iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); + + /* Set up entry for this TFD in Tx byte-count array */ +- if (is_agg) +- iwl_trans_txq_update_byte_cnt_tbl(trans, txq, +- le16_to_cpu(tx_cmd->len)); ++ iwl_trans_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len)); + + dma_sync_single_for_device(bus(trans)->dev, txcmd_phys, firstlen, + DMA_BIDIRECTIONAL); +-- +1.7.4.4 + diff --git a/kernel.spec b/kernel.spec index bb92a1344..167c8764f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -832,6 +832,10 @@ Patch21049: tpm_tis-delay-after-aborting-cmd.patch Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch Patch50100: iwlwifi-tx_sync-only-on-PAN-context.patch +Patch50101: ath9k-fix-max-phy-rate-at-rate-control-init.patch +Patch50102: iwlwifi-do-not-set-the-sequence-control-bit-is-not-n.patch +Patch50103: iwlwifi-update-SCD-BC-table-for-all-SCD-queues.patch +Patch50104: mwifiex-avoid-double-list_del-in-command-cancel-path.patch Patch22000: route-cache-garbage-collector.patch @@ -1608,8 +1612,12 @@ ApplyPatch compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch ApplyPatch bcma-brcmsmac-compat.patch # Apply some iwlwifi regression fixes not in the 3.2-rc6 wireless snapshot +ApplyPatch iwlwifi-do-not-set-the-sequence-control-bit-is-not-n.patch +ApplyPatch ath9k-fix-max-phy-rate-at-rate-control-init.patch +ApplyPatch mwifiex-avoid-double-list_del-in-command-cancel-path.patch ApplyPatch iwlwifi-tx_sync-only-on-PAN-context.patch ApplyPatch iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch +ApplyPatch iwlwifi-update-SCD-BC-table-for-all-SCD-queues.patch cd .. @@ -2283,6 +2291,12 @@ fi # and build. %changelog +* Thu Dec 22 2011 John W. Linville +- iwlwifi: do not set the sequence control bit is not needed +- ath9k: fix max phy rate at rate control init +- mwifiex: avoid double list_del in command cancel path +- iwlwifi: update SCD BC table for all SCD queues + * Wed Dec 21 2011 Dave Jones 3.1.6-1 - Linux 3.1.6 diff --git a/mwifiex-avoid-double-list_del-in-command-cancel-path.patch b/mwifiex-avoid-double-list_del-in-command-cancel-path.patch new file mode 100644 index 000000000..90b695723 --- /dev/null +++ b/mwifiex-avoid-double-list_del-in-command-cancel-path.patch @@ -0,0 +1,59 @@ +From 51e708c1049e721b9c5c48d026bc97ca8497d39a Mon Sep 17 00:00:00 2001 +From: Yogesh Ashok Powar +Date: Tue, 13 Dec 2011 20:43:16 -0800 +Subject: [PATCH 04/10] mwifiex: avoid double list_del in command cancel path + +Command cancel path cancels the current command and moves +it to free command queue. While doing that it deletes the +command entry from the pending list. This is not correct +as the entry has been already deleted from the pending +list at 'mwifiex_exec_next_cmd'. Fixing it. + +Also making sure the stale command pointer is cleaned and +unaccessible for later use. + +Signed-off-by: Yogesh Ashok Powar +Signed-off-by: Bing Zhao +Signed-off-by: John W. Linville +--- + drivers/net/wireless/mwifiex/cmdevt.c | 9 ++------- + 1 files changed, 2 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c +index ac27815..6e0a3ea 100644 +--- a/drivers/net/wireless/mwifiex/cmdevt.c ++++ b/drivers/net/wireless/mwifiex/cmdevt.c +@@ -939,7 +939,6 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) + { + struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; + unsigned long cmd_flags; +- unsigned long cmd_pending_q_flags; + unsigned long scan_pending_q_flags; + uint16_t cancel_scan_cmd = false; + +@@ -949,12 +948,9 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) + cmd_node = adapter->curr_cmd; + cmd_node->wait_q_enabled = false; + cmd_node->cmd_flag |= CMD_F_CANCELED; +- spin_lock_irqsave(&adapter->cmd_pending_q_lock, +- cmd_pending_q_flags); +- list_del(&cmd_node->list); +- spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, +- cmd_pending_q_flags); + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); ++ mwifiex_complete_cmd(adapter, adapter->curr_cmd); ++ adapter->curr_cmd = NULL; + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); + } + +@@ -981,7 +977,6 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); + } + adapter->cmd_wait_q.status = -1; +- mwifiex_complete_cmd(adapter, adapter->curr_cmd); + } + + /* +-- +1.7.4.4 + From b105242376ffc2acfade3df6bf9ee0918622ae6f Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Fri, 9 Dec 2011 13:40:09 -0600 Subject: [PATCH 192/487] initial support for building imx highbank and kirkwood kernels for arm --- Makefile.config | 26 ++++++++++++++++ config-arm-highbank | 3 ++ config-arm-imx | 75 +++++++++++++++++++++++++++++++++++++++++++++ config-arm-kirkwood | 43 ++++++++++++++++++++++++++ kernel.spec | 59 ++++++++++++++++++++++++++++++++++- 5 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 config-arm-highbank create mode 100644 config-arm-imx create mode 100644 config-arm-kirkwood diff --git a/Makefile.config b/Makefile.config index ccb035d77..223c793fe 100644 --- a/Makefile.config +++ b/Makefile.config @@ -10,7 +10,9 @@ CONFIGFILES = \ $(CFG)-x86_64.config $(CFG)-x86_64-debug.config \ $(CFG)-s390x.config \ $(CFG)-arm.config $(CFG)-armv5tel.config \ + $(CFG)-armv5tel-kirkwood.config $(CFG)-armv7l-imx.config \ $(CFG)-armv7l-omap.config $(CFG)-armv7l-tegra.config \ + $(CFG)-armv7hl-imx.config $(CFG)-armv7hl-highbank.config \ $(CFG)-armv7hl-omap.config $(CFG)-armv7hl-tegra.config \ $(CFG)-ppc.config $(CFG)-ppc-smp.config \ $(CFG)-sparc64.config \ @@ -44,6 +46,15 @@ temp-armv7l-omap-generic: config-arm-omap-generic temp-arm-generic temp-armv7l-tegra: config-arm-tegra temp-arm-generic perl merge.pl $^ > $@ +temp-armv5tel-kirkwood: config-arm-kirkwood temp-arm-generic + perl merge.pl $^ > $@ + +temp-armv7l-imx: config-arm-imx temp-arm-generic + perl merge.pl $^ > $@ + +temp-armv7l-highbank: config-arm-highbank temp-arm-generic + perl merge.pl $^ > $@ + temp-x86-32: config-x86-32-generic config-x86-generic perl merge.pl $^ > $@ @@ -116,12 +127,27 @@ kernel-$(VERSION)-arm.config: /dev/null temp-arm-generic kernel-$(VERSION)-armv5tel.config: /dev/null temp-arm-generic perl merge.pl $^ arm > $@ +kernel-$(VERSION)-armv5tel-kirkwood.config: /dev/null temp-armv5tel-kirkwood + perl merge.pl $^ arm > $@ + +kernel-$(VERSION)-armv7l-imx.config: /dev/null temp-armv7l-imx + perl merge.pl $^ arm > $@ + +kernel-$(VERSION)-armv7l-highbank.config: /dev/null temp-armv7l-highbank + perl merge.pl $^ arm > $@ + kernel-$(VERSION)-armv7l-omap.config: /dev/null temp-armv7l-omap-generic perl merge.pl $^ arm > $@ kernel-$(VERSION)-armv7l-tegra.config: /dev/null temp-armv7l-tegra perl merge.pl $^ arm > $@ +kernel-$(VERSION)-armv7hl-imx.config: /dev/null temp-armv7l-imx + perl merge.pl $^ arm > $@ + +kernel-$(VERSION)-armv7hl-highbank.config: /dev/null temp-armv7l-highbank + perl merge.pl $^ arm > $@ + kernel-$(VERSION)-armv7hl-omap.config: /dev/null temp-armv7l-omap-generic perl merge.pl $^ arm > $@ diff --git a/config-arm-highbank b/config-arm-highbank new file mode 100644 index 000000000..18fc0c4cc --- /dev/null +++ b/config-arm-highbank @@ -0,0 +1,3 @@ +ONFIG_ARCH_HIGHBANK=y +CONFIG_VFP=y +CONFIG_NEON=y diff --git a/config-arm-imx b/config-arm-imx new file mode 100644 index 000000000..a491b8cab --- /dev/null +++ b/config-arm-imx @@ -0,0 +1,75 @@ +CONFIG_ARCH_MXC=y +CONFIG_ARCH_MX51=y +CONFIG_MACH_MX51_BABBAGE=y +CONFIG_MACH_MX51_3DS=y +CONFIG_MACH_EUKREA_CPUIMX51=y +CONFIG_VFP=y +CONFIG_NEON=y + +CONFIG_MACH_MX31ADS=y +CONFIG_MACH_MX31LILLY=y +CONFIG_MACH_MX31LITE=y +CONFIG_MACH_PCM037=y +CONFIG_MACH_MX31_3DS=y +CONFIG_MACH_MX31MOBOARD=y +CONFIG_MACH_QONG=y +CONFIG_MACH_ARMADILLO5X0=y +CONFIG_MACH_KZM_ARM11_01=y +CONFIG_MACH_BUG=y +CONFIG_MACH_PCM043=y +CONFIG_MACH_MX35_3DS=y +CONFIG_MACH_EUKREA_CPUIMX35=y +CONFIG_MACH_VPR200=y +CONFIG_SOC_IMX6Q=y +CONFIG_MXC_IRQ_PRIOR=y +CONFIG_MXC_PWM=m +CONFIG_MXC_DEBUG_BOARD=y +# CONFIG_CPU_BPREDICT_DISABLE is not set +# CONFIG_CACHE_L2X0 is not set +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_ARM_ERRATA_411920=y +CONFIG_PL310_ERRATA_588369=y +CONFIG_PL310_ERRATA_727915=y +CONFIG_ARM_ERRATA_364296=y +CONFIG_HW_PERF_EVENTS=y +CONFIG_RFKILL_GPIO=m +CONFIG_PATA_IMX=m +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_BROADCOM=y +CONFIG_NET_VENDOR_FREESCALE=y +CONFIG_FEC=y +CONFIG_KEYBOARD_IMX=m +CONFIG_SERIAL_IMX=y +CONFIG_HW_RANDOM_MXC_RNGA=m +CONFIG_I2C_IMX=m +CONFIG_GPIO_GENERIC_PLATFORM=y +CONFIG_GPIO_MCP23S08=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_PLL=m +CONFIG_SND_IMX_SOC=m +CONFIG_USB_EHCI_MXC=y +CONFIG_USB_IMX21_HCD=m +CONFIG_MMC_SDHCI_ESDHC_IMX=m +CONFIG_MMC_MXC=m +CONFIG_RTC_MXC=m + +CONFIG_BACKLIGHT_PWM=m +CONFIG_LEDS_PWM=m + +CONFIG_MACH_PCM037_EET=y +# CONFIG_MACH_MX31_3DS_MXC_NAND_USE_BBT is not set +CONFIG_MXC_USE_EPIT=y +CONFIG_ARM_THUMBEE=y +CONFIG_ARM_ERRATA_430973=y +CONFIG_ARM_ERRATA_458693=y +CONFIG_ARM_ERRATA_460075=y +CONFIG_ARM_ERRATA_743622=y +CONFIG_ARM_ERRATA_754322=y +CONFIG_CAN_FLEXCAN=m +CONFIG_MTD_NAND_MXC=m +CONFIG_INPUT_PWM_BEEPER=m +CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_IMX2_WDT=m +CONFIG_SND_SOC_PHYCORE_AC97=m +CONFIG_SND_SOC_EUKREA_TLV320=m + diff --git a/config-arm-kirkwood b/config-arm-kirkwood new file mode 100644 index 000000000..6aa045cd9 --- /dev/null +++ b/config-arm-kirkwood @@ -0,0 +1,43 @@ +CONFIG_ARCH_KIRKWOOD=y +CONFIG_MACH_DB88F6281_BP=y +CONFIG_MACH_RD88F6192_NAS=y +CONFIG_MACH_RD88F6281=y +CONFIG_MACH_MV88F6281GTW_GE=y +CONFIG_MACH_SHEEVAPLUG=y +CONFIG_MACH_ESATA_SHEEVAPLUG=y +CONFIG_MACH_GURUPLUG=y +CONFIG_MACH_DOCKSTAR=y +CONFIG_MACH_TS219=y +CONFIG_MACH_TS41X=y +CONFIG_MACH_OPENRD_BASE=y +CONFIG_MACH_OPENRD_CLIENT=y +CONFIG_MACH_OPENRD_ULTIMATE=y +CONFIG_MACH_NETSPACE_V2=y +CONFIG_MACH_INETSPACE_V2=y +CONFIG_MACH_NETSPACE_MAX_V2=y +CONFIG_MACH_D2NET_V2=y +CONFIG_MACH_NET2BIG_V2=y +CONFIG_MACH_NET5BIG_V2=y +CONFIG_MACH_T5325=y +# CONFIG_CPU_FEROCEON_OLD_ID is not set + + +CONFIG_CACHE_FEROCEON_L2=y +CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH=y +CONFIG_MTD_NAND_ORION=m +CONFIG_MV643XX_ETH=m +CONFIG_I2C_MV64XXX=m +CONFIG_GPIO_GENERIC_PLATFORM=y +CONFIG_GPIO_MCP23S08=m +CONFIG_ORION_WATCHDOG=m +CONFIG_SND_KIRKWOOD_SOC=m +CONFIG_SND_KIRKWOOD_SOC_OPENRD=m +CONFIG_SND_KIRKWOOD_SOC_T5325=m +CONFIG_MMC_MVSDIO=m +CONFIG_LEDS_NS2=m +CONFIG_LEDS_NETXBIG=m +CONFIG_RTC_DRV_MV=m +CONFIG_MV_XOR=y +CONFIG_CRYPTO_DEV_MV_CESA=m + + diff --git a/kernel.spec b/kernel.spec index 167c8764f..1f9c892f1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -128,6 +128,12 @@ Summary: The Linux kernel %define with_omap %{?_without_omap: 0} %{?!_without_omap: 1} # kernel-tegra (only valid for arm) %define with_tegra %{?_without_tegra: 0} %{?!_without_tegra: 1} +# kernel-kirkwood (only valid for arm) +%define with_kirkwood %{?_without_kirkwood: 0} %{?!_without_kirkwood: 1} +# kernel-imx (only valid for arm) +%define with_imx %{?_without_imx: 0} %{?!_without_imx: 1} +# kernel-highbank (only valid for arm) +%define with_highbank %{?_without_highbank: 0} %{?!_without_highbank: 1} # Build the kernel-doc package, but don't fail the build if it botches. # Here "true" means "continue" and "false" means "fail the build". @@ -255,10 +261,17 @@ Summary: The Linux kernel %define with_pae 0 %endif -# kernel-tegra and omap is only built on armv7 hard and softfp +# kernel-tegra, omap, imx and highbank are only built on armv7 hard and softfp %ifnarch armv7hl armv7l %define with_tegra 0 %define with_omap 0 +%define with_imx 0 +%define with_highbank 0 +%endif + +# kernel-kirkwood is only built for armv5 +%ifnarch armv5tel +%define with_kirkwood 0 %endif # if requested, only build base kernel @@ -608,6 +621,9 @@ Source90: config-sparc64-generic Source100: config-arm-generic Source110: config-arm-omap-generic Source111: config-arm-tegra +Source112: config-arm-kirkwood +Source113: config-arm-imx +Source114: config-arm-highbank Source200: config-backports @@ -1051,6 +1067,23 @@ This variant of the kernel has numerous debugging options enabled. It should only be installed when trying to gather additional information on kernel bugs, as some of these options impact performance noticably. +%define variant_summary The Linux kernel compiled for marvell kirkwood boards +%kernel_variant_package kirkwood +%description kirkwood +This package includes a version of the Linux kernel with support for +marvell kirkwood based systems, i.e., guruplug, sheevaplug + +%define variant_summary The Linux kernel compiled for freescale boards +%kernel_variant_package imx +%description imx +This package includes a version of the Linux kernel with support for +freescale based systems, i.e., efika smartbook. + +%define variant_summary The Linux kernel compiled for Calxeda boards +%kernel_variant_package highbank +%description highbank +This package includes a version of the Linux kernel with support for +Calxeda based systems, i.e., HP arm servers. %define variant_summary The Linux kernel compiled for TI-OMAP boards %kernel_variant_package omap @@ -1894,6 +1927,18 @@ BuildKernel %make_target %kernel_image PAEdebug BuildKernel %make_target %kernel_image PAE %endif +%if %{with_kirkwood} +BuildKernel %make_target %kernel_image kirkwood +%endif + +%if %{with_imx} +BuildKernel %make_target %kernel_image imx +%endif + +%if %{with_highbank} +BuildKernel %make_target %kernel_image highbank +%endif + %if %{with_omap} BuildKernel %make_target %kernel_image omap %endif @@ -2147,6 +2192,15 @@ fi}\ %kernel_variant_post -v PAEdebug -r (kernel|kernel-smp) %kernel_variant_preun PAEdebug +%kernel_variant_preun kirkwood +%kernel_variant_post -v kirkwood + +%kernel_variant_preun imx +%kernel_variant_post -v imx + +%kernel_variant_preun highbank +%kernel_variant_post -v highbank + %kernel_variant_preun omap %kernel_variant_post -v omap @@ -2284,6 +2338,9 @@ fi %kernel_variant_files %{with_debug} debug %kernel_variant_files %{with_pae} PAE %kernel_variant_files %{with_pae_debug} PAEdebug +%kernel_variant_files %{with_kirkwood} kirkwood +%kernel_variant_files %{with_imx} imx +%kernel_variant_files %{with_highbank} highbank %kernel_variant_files %{with_omap} omap %kernel_variant_files %{with_tegra} tegra From 7330c5a5b61af261a625637440871ff854000a7a Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Fri, 23 Dec 2011 10:58:33 -0600 Subject: [PATCH 193/487] clean up imx config --- config-arm-imx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/config-arm-imx b/config-arm-imx index a491b8cab..5ed7ae2ed 100644 --- a/config-arm-imx +++ b/config-arm-imx @@ -6,6 +6,14 @@ CONFIG_MACH_EUKREA_CPUIMX51=y CONFIG_VFP=y CONFIG_NEON=y +CONFIG_MACH_EUKREA_CPUIMX51SD=y +CONFIG_MACH_MX51_EFIKAMX=y +CONFIG_MACH_MX51_EFIKASB=y +# CONFIG_SWP_EMULATE is not set +# CONFIG_THUMB2_KERNEL is not set +CONFIG_CPU_FREQ_IMX=y +CONFIG_W1_MASTER_MXC=m +CONFIG_IMX_SDMA=y CONFIG_MACH_MX31ADS=y CONFIG_MACH_MX31LILLY=y CONFIG_MACH_MX31LITE=y @@ -73,3 +81,15 @@ CONFIG_IMX2_WDT=m CONFIG_SND_SOC_PHYCORE_AC97=m CONFIG_SND_SOC_EUKREA_TLV320=m +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEBUG=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_STAT_DETAILS=y From 4ca5087fa321b21fc2679d095993d32034bdc382 Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Fri, 23 Dec 2011 11:00:04 -0600 Subject: [PATCH 194/487] build imx highbank and kirkwood kernels for arm --- kernel.spec | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel.spec b/kernel.spec index 1f9c892f1..f934e7853 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2348,6 +2348,9 @@ fi # and build. %changelog +* Fri Dec 23 2011 Dennis Gilmore +- build imx highbank and kirkwood kernels for arm + * Thu Dec 22 2011 John W. Linville - iwlwifi: do not set the sequence control bit is not needed - ath9k: fix max phy rate at rate control init From 2da15d95218328771a3b5620002d175ce71a64e6 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 29 Dec 2011 13:10:57 -0500 Subject: [PATCH 195/487] Create a blacklist for pci=nocrs Add Dell Studio 1536 to it. --- kernel.spec | 10 +++++++++- pci-crs-blacklist.patch | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 pci-crs-blacklist.patch diff --git a/kernel.spec b/kernel.spec index f934e7853..7ce7f0f07 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -826,6 +826,8 @@ Patch21220: mac80211_offchannel_rework_revert.patch Patch21225: pci-Rework-ASPM-disable-code.patch +Patch21226: pci-crs-blacklist.patch + #rhbz #757839 Patch21230: net-sky2-88e8059-fix-link-speed.patch @@ -1553,6 +1555,8 @@ ApplyPatch mac80211_offchannel_rework_revert.patch ApplyPatch pci-Rework-ASPM-disable-code.patch +ApplyPatch pci-crs-blacklist.patch + #rhbz #757839 ApplyPatch net-sky2-88e8059-fix-link-speed.patch @@ -2348,6 +2352,10 @@ fi # and build. %changelog +* Thu Dec 29 2011 Dave Jones 3.1.6-2 +- Create a blacklist for pci=nocrs + Add Dell Studio 1536 to it. + * Fri Dec 23 2011 Dennis Gilmore - build imx highbank and kirkwood kernels for arm diff --git a/pci-crs-blacklist.patch b/pci-crs-blacklist.patch new file mode 100644 index 000000000..bc17d54a5 --- /dev/null +++ b/pci-crs-blacklist.patch @@ -0,0 +1,36 @@ +diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c +index 404f21a..2704a9c 100644 +--- a/arch/x86/pci/acpi.c ++++ b/arch/x86/pci/acpi.c +@@ -24,6 +24,12 @@ static int __init set_use_crs(const struct dmi_system_id *id) + return 0; + } + ++static int __init set_nouse_crs(const struct dmi_system_id *id) ++{ ++ pci_use_crs = false; ++ return 0; ++} ++ + static const struct dmi_system_id pci_use_crs_table[] __initconst = { + /* http://bugzilla.kernel.org/show_bug.cgi?id=14183 */ + { +@@ -54,6 +60,18 @@ static const struct dmi_system_id pci_use_crs_table[] __initconst = { + DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), + }, + }, ++ ++ /* Now for the blacklist.. */ ++ ++ /* https://bugzilla.redhat.com/show_bug.cgi?id=770308 */ ++ { ++ .callback = set_nouse_crs, ++ .ident = "Dell Studio 1536", ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_BOARD_NAME, "0M273C"), ++ }, ++ }, + {} + }; + From cd152b3a6c81dfe2987bb456c6c135da616ba329 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 3 Jan 2012 09:49:11 -0500 Subject: [PATCH 196/487] Re-enable CONFIG_RT2800PCI_RT53XX in compat-wireless build (rhbz #720594) --- compat-wireless-config-fixups.patch | 48 ++++++++++++++++++++--------- kernel.spec | 3 ++ 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/compat-wireless-config-fixups.patch b/compat-wireless-config-fixups.patch index 411ee40c6..15566c35f 100644 --- a/compat-wireless-config-fixups.patch +++ b/compat-wireless-config-fixups.patch @@ -1,6 +1,6 @@ -diff -up compat-wireless-3.2-rc1-1/config.mk.orig compat-wireless-3.2-rc1-1/config.mk ---- compat-wireless-3.2-rc1-1/config.mk.orig 2011-11-22 13:09:50.422879313 -0500 -+++ compat-wireless-3.2-rc1-1/config.mk 2011-11-22 13:10:28.870398679 -0500 +diff -up compat-wireless-3.2-rc6-3/config.mk.orig compat-wireless-3.2-rc6-3/config.mk +--- compat-wireless-3.2-rc6-3/config.mk.orig 2012-01-03 09:41:57.090827042 -0500 ++++ compat-wireless-3.2-rc6-3/config.mk 2012-01-03 09:42:19.259549896 -0500 @@ -14,6 +14,9 @@ else include $(KLIB_BUILD)/.config endif @@ -11,17 +11,35 @@ diff -up compat-wireless-3.2-rc1-1/config.mk.orig compat-wireless-3.2-rc1-1/conf ifneq ($(wildcard $(KLIB_BUILD)/Makefile),) COMPAT_LATEST_VERSION = 1 -diff -up compat-wireless-3.2-rc1-1/drivers/misc/eeprom/Makefile.orig compat-wireless-3.2-rc1-1/drivers/misc/eeprom/Makefile ---- compat-wireless-3.2-rc1-1/drivers/misc/eeprom/Makefile.orig 2011-11-22 13:09:50.423879301 -0500 -+++ compat-wireless-3.2-rc1-1/drivers/misc/eeprom/Makefile 2011-11-22 13:10:28.871398662 -0500 +@@ -353,7 +356,7 @@ ifdef CONFIG_CRC_CCITT + CONFIG_RT2800PCI=m + CONFIG_RT2800PCI_RT33XX=y + CONFIG_RT2800PCI_RT35XX=y +-# CONFIG_RT2800PCI_RT53XX=y ++CONFIG_RT2800PCI_RT53XX=y + endif #CONFIG_CRC_CCITT + NEED_RT2X00=y + +@@ -481,7 +484,7 @@ ifdef CONFIG_CRC_CCITT + CONFIG_RT2800USB=m + CONFIG_RT2800USB_RT33XX=y + CONFIG_RT2800USB_RT35XX=y +-# CONFIG_RT2800USB_RT53XX=y ++CONFIG_RT2800USB_RT53XX=y + CONFIG_RT2800USB_UNKNOWN=y + endif #CONFIG_CRC_CCITT + CONFIG_RT2X00_LIB_USB=m +diff -up compat-wireless-3.2-rc6-3/drivers/misc/eeprom/Makefile.orig compat-wireless-3.2-rc6-3/drivers/misc/eeprom/Makefile +--- compat-wireless-3.2-rc6-3/drivers/misc/eeprom/Makefile.orig 2012-01-03 09:41:57.104826867 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/misc/eeprom/Makefile 2012-01-03 09:42:03.468747311 -0500 @@ -1,3 +1,3 @@ -obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o +#obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o obj-$(CONFIG_EEPROM_93XX46) += eeprom_93xx46.o obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o -diff -up compat-wireless-3.2-rc1-1/drivers/net/ethernet/atheros/Makefile.orig compat-wireless-3.2-rc1-1/drivers/net/ethernet/atheros/Makefile ---- compat-wireless-3.2-rc1-1/drivers/net/ethernet/atheros/Makefile.orig 2011-11-22 13:09:50.423879301 -0500 -+++ compat-wireless-3.2-rc1-1/drivers/net/ethernet/atheros/Makefile 2011-11-22 13:10:28.871398662 -0500 +diff -up compat-wireless-3.2-rc6-3/drivers/net/ethernet/atheros/Makefile.orig compat-wireless-3.2-rc6-3/drivers/net/ethernet/atheros/Makefile +--- compat-wireless-3.2-rc6-3/drivers/net/ethernet/atheros/Makefile.orig 2012-01-03 09:41:57.107826831 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/ethernet/atheros/Makefile 2012-01-03 09:42:03.469747299 -0500 @@ -2,7 +2,7 @@ # Makefile for the Atheros network device drivers. # @@ -34,9 +52,9 @@ diff -up compat-wireless-3.2-rc1-1/drivers/net/ethernet/atheros/Makefile.orig co +#obj-$(CONFIG_ATL2) += atlx/ +#obj-$(CONFIG_ATL1E) += atl1e/ +#obj-$(CONFIG_ATL1C) += atl1c/ -diff -up compat-wireless-3.2-rc1-1/drivers/net/usb/Makefile.orig compat-wireless-3.2-rc1-1/drivers/net/usb/Makefile ---- compat-wireless-3.2-rc1-1/drivers/net/usb/Makefile.orig 2011-11-22 13:09:50.424879289 -0500 -+++ compat-wireless-3.2-rc1-1/drivers/net/usb/Makefile 2011-11-22 13:10:28.872398646 -0500 +diff -up compat-wireless-3.2-rc6-3/drivers/net/usb/Makefile.orig compat-wireless-3.2-rc6-3/drivers/net/usb/Makefile +--- compat-wireless-3.2-rc6-3/drivers/net/usb/Makefile.orig 2012-01-03 09:41:57.108826819 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/usb/Makefile 2012-01-03 09:42:03.469747299 -0500 @@ -2,7 +2,7 @@ # Makefile for USB Network drivers # @@ -48,9 +66,9 @@ diff -up compat-wireless-3.2-rc1-1/drivers/net/usb/Makefile.orig compat-wireless +#obj-$(CONFIG_USB_NET_COMPAT_RNDIS_HOST) += rndis_host.o +#obj-$(CONFIG_USB_COMPAT_USBNET) += usbnet.o -diff -up compat-wireless-3.2-rc1-1/Makefile.orig compat-wireless-3.2-rc1-1/Makefile ---- compat-wireless-3.2-rc1-1/Makefile.orig 2011-11-22 13:10:37.165294951 -0500 -+++ compat-wireless-3.2-rc1-1/Makefile 2011-11-22 13:10:47.335167758 -0500 +diff -up compat-wireless-3.2-rc6-3/Makefile.orig compat-wireless-3.2-rc6-3/Makefile +--- compat-wireless-3.2-rc6-3/Makefile.orig 2012-01-03 09:41:57.109826807 -0500 ++++ compat-wireless-3.2-rc6-3/Makefile 2012-01-03 09:42:03.470747287 -0500 @@ -41,8 +41,8 @@ endif endif diff --git a/kernel.spec b/kernel.spec index 7ce7f0f07..ed65792f0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2352,6 +2352,9 @@ fi # and build. %changelog +* Tue Jan 3 2012 John W. Linville +- Re-enable CONFIG_RT2800PCI_RT53XX in compat-wireless build (rhbz #720594) + * Thu Dec 29 2011 Dave Jones 3.1.6-2 - Create a blacklist for pci=nocrs Add Dell Studio 1536 to it. From 2205c1a917064d60ac6981e733b51001e1d08b40 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 3 Jan 2012 10:22:41 -0500 Subject: [PATCH 197/487] thp: reduce khugepaged freezing latency (rhbz 771006) --- kernel.spec | 9 ++++ thp-reduce-khugepaged-freezing-latency.patch | 54 ++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 thp-reduce-khugepaged-freezing-latency.patch diff --git a/kernel.spec b/kernel.spec index ed65792f0..822afc33c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -846,6 +846,9 @@ Patch21048: b44-Use-dev_kfree_skb_irq-in-b44_tx.patch #rhbz 746097 Patch21049: tpm_tis-delay-after-aborting-cmd.patch +#rhbz 771006 +Patch21050: thp-reduce-khugepaged-freezing-latency.patch + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch @@ -1575,6 +1578,9 @@ ApplyPatch b44-Use-dev_kfree_skb_irq-in-b44_tx.patch #rhbz 746097 ApplyPatch tpm_tis-delay-after-aborting-cmd.patch +#rhbz 771006 +ApplyPatch thp-reduce-khugepaged-freezing-latency.patch + ApplyPatch route-cache-garbage-collector.patch # END OF PATCH APPLICATIONS @@ -2352,6 +2358,9 @@ fi # and build. %changelog +* Tue Jan 03 2012 Dave Jones +- thp: reduce khugepaged freezing latency (rhbz 771006) + * Tue Jan 3 2012 John W. Linville - Re-enable CONFIG_RT2800PCI_RT53XX in compat-wireless build (rhbz #720594) diff --git a/thp-reduce-khugepaged-freezing-latency.patch b/thp-reduce-khugepaged-freezing-latency.patch new file mode 100644 index 000000000..b7b205177 --- /dev/null +++ b/thp-reduce-khugepaged-freezing-latency.patch @@ -0,0 +1,54 @@ +From: Andrea Arcangeli +Subject: thp: reduce khugepaged freezing latency + +Use wait_event_freezable_timeout() instead of +schedule_timeout_interruptible() to avoid missing freezer wakeups. A +try_to_freeze() would have been needed in the +khugepaged_alloc_hugepage tight loop too in case of the allocation +failing repeatedly, and wait_event_freezable_timeout will provide it +too. + +khugepaged would still freeze just fine by trying again the next +minute but it's better if it freezes immediately. + +Reported-by: Jiri Slaby +Signed-off-by: Andrea Arcangeli + +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index 4298aba..fd925d0 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -2259,12 +2259,9 @@ static void khugepaged_do_scan(struct page **hpage) + + static void khugepaged_alloc_sleep(void) + { +- DEFINE_WAIT(wait); +- add_wait_queue(&khugepaged_wait, &wait); +- schedule_timeout_interruptible( +- msecs_to_jiffies( +- khugepaged_alloc_sleep_millisecs)); +- remove_wait_queue(&khugepaged_wait, &wait); ++ wait_event_freezable_timeout(khugepaged_wait, false, ++ msecs_to_jiffies( ++ khugepaged_alloc_sleep_millisecs)); + } + + #ifndef CONFIG_NUMA +@@ -2313,14 +2310,11 @@ static void khugepaged_loop(void) + if (unlikely(kthread_should_stop())) + break; + if (khugepaged_has_work()) { +- DEFINE_WAIT(wait); + if (!khugepaged_scan_sleep_millisecs) + continue; +- add_wait_queue(&khugepaged_wait, &wait); +- schedule_timeout_interruptible( ++ wait_event_freezable_timeout(khugepaged_wait, false, + msecs_to_jiffies( + khugepaged_scan_sleep_millisecs)); +- remove_wait_queue(&khugepaged_wait, &wait); + } else if (khugepaged_enabled()) + wait_event_freezable(khugepaged_wait, + khugepaged_wait_event()); + + From 5dc9ec6f005c484c538cf8e18ceccd90f479f46a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 3 Jan 2012 10:27:26 -0500 Subject: [PATCH 198/487] CVE-2011-4622 kvm: pit timer with no irqchip crashes the system (rhbz 771387) --- ...tarting-PIT-timers-in-the-absence-of.patch | 69 +++++++++++++++++++ kernel.spec | 11 ++- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch diff --git a/KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch b/KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch new file mode 100644 index 000000000..07ef3e71b --- /dev/null +++ b/KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch @@ -0,0 +1,69 @@ +From 0924ab2cfa98b1ece26c033d696651fd62896c69 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka +Date: Wed, 14 Dec 2011 19:25:13 +0100 +Subject: [PATCH] KVM: x86: Prevent starting PIT timers in the absence of + irqchip support + +User space may create the PIT and forgets about setting up the irqchips. +In that case, firing PIT IRQs will crash the host: + +BUG: unable to handle kernel NULL pointer dereference at 0000000000000128 +IP: [] kvm_set_irq+0x30/0x170 [kvm] +... +Call Trace: + [] pit_do_work+0x51/0xd0 [kvm] + [] process_one_work+0x111/0x4d0 + [] worker_thread+0x152/0x340 + [] kthread+0x7e/0x90 + [] kernel_thread_helper+0x4/0x10 + +Prevent this by checking the irqchip mode before starting a timer. We +can't deny creating the PIT if the irqchips aren't set up yet as +current user land expects this order to work. + +Signed-off-by: Jan Kiszka +Signed-off-by: Marcelo Tosatti +--- + arch/x86/kvm/i8254.c | 10 +++++++--- + 1 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c +index 76e3f1c..405f262 100644 +--- a/arch/x86/kvm/i8254.c ++++ b/arch/x86/kvm/i8254.c +@@ -338,11 +338,15 @@ static enum hrtimer_restart pit_timer_fn(struct hrtimer *data) + return HRTIMER_NORESTART; + } + +-static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period) ++static void create_pit_timer(struct kvm *kvm, u32 val, int is_period) + { ++ struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state; + struct kvm_timer *pt = &ps->pit_timer; + s64 interval; + ++ if (!irqchip_in_kernel(kvm)) ++ return; ++ + interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ); + + pr_debug("create pit timer, interval is %llu nsec\n", interval); +@@ -394,13 +398,13 @@ static void pit_load_count(struct kvm *kvm, int channel, u32 val) + /* FIXME: enhance mode 4 precision */ + case 4: + if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)) { +- create_pit_timer(ps, val, 0); ++ create_pit_timer(kvm, val, 0); + } + break; + case 2: + case 3: + if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)){ +- create_pit_timer(ps, val, 1); ++ create_pit_timer(kvm, val, 1); + } + break; + default: +-- +1.7.6.2 + diff --git a/kernel.spec b/kernel.spec index 822afc33c..7b3869cca 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -849,6 +849,9 @@ Patch21049: tpm_tis-delay-after-aborting-cmd.patch #rhbz 771006 Patch21050: thp-reduce-khugepaged-freezing-latency.patch +#rhbz 771387 +Patch21055: KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch @@ -1583,6 +1586,9 @@ ApplyPatch thp-reduce-khugepaged-freezing-latency.patch ApplyPatch route-cache-garbage-collector.patch +#rhbz 771387 +ApplyPatch KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch + # END OF PATCH APPLICATIONS %endif @@ -2358,6 +2364,9 @@ fi # and build. %changelog +* Tue Jan 03 2012 Josh Boyer +- CVE-2011-4622 kvm: pit timer with no irqchip crashes the system (rhbz 771387) + * Tue Jan 03 2012 Dave Jones - thp: reduce khugepaged freezing latency (rhbz 771006) From 7749b4d14a09b5598d18b294af27b8fb067b56d8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 3 Jan 2012 10:42:33 -0500 Subject: [PATCH 199/487] Add bluetooth support for BCM20102A0 (rhbz 770233) --- Bluetooth-Add-support-for-BCM20702A0.patch | 15 +++++++++++++++ kernel.spec | 7 +++++++ 2 files changed, 22 insertions(+) create mode 100644 Bluetooth-Add-support-for-BCM20702A0.patch diff --git a/Bluetooth-Add-support-for-BCM20702A0.patch b/Bluetooth-Add-support-for-BCM20702A0.patch new file mode 100644 index 000000000..1e579342c --- /dev/null +++ b/Bluetooth-Add-support-for-BCM20702A0.patch @@ -0,0 +1,15 @@ +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index f9b7260..28a5876 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -100,6 +100,10 @@ static struct usb_device_id btusb_table[] = { + /* Canyon CN-BTU1 with HID interfaces */ + { USB_DEVICE(0x0c10, 0x0000) }, + ++ /* Broadcom BCM20702A0 */ ++ { USB_DEVICE(0x0a5c, 0x21e3) }, ++ { USB_DEVICE(0x413c, 0x8197) }, ++ + { } /* Terminating entry */ + }; + diff --git a/kernel.spec b/kernel.spec index 7b3869cca..1241cbde3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -852,6 +852,9 @@ Patch21050: thp-reduce-khugepaged-freezing-latency.patch #rhbz 771387 Patch21055: KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch +#rhbz 770233 +Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch @@ -1589,6 +1592,9 @@ ApplyPatch route-cache-garbage-collector.patch #rhbz 771387 ApplyPatch KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch +#rhbz 770233 +ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch + # END OF PATCH APPLICATIONS %endif @@ -2366,6 +2372,7 @@ fi %changelog * Tue Jan 03 2012 Josh Boyer - CVE-2011-4622 kvm: pit timer with no irqchip crashes the system (rhbz 771387) +- Add bluetooth support for BCM20102A0 (rhbz 770233) * Tue Jan 03 2012 Dave Jones - thp: reduce khugepaged freezing latency (rhbz 771006) From 534bbc8050e412761f4cd3405c7f1d230001be45 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 3 Jan 2012 13:06:46 -0500 Subject: [PATCH 200/487] Add Thinkpad SL510 to the pci=nocrs blacklist. --- kernel.spec | 3 +++ pci-crs-blacklist.patch | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/kernel.spec b/kernel.spec index 1241cbde3..51f50bae4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2370,6 +2370,9 @@ fi # and build. %changelog +* Tue Jan 03 2012 Dave Jones +- Add Thinkpad SL510 to the pci=nocrs blacklist. + * Tue Jan 03 2012 Josh Boyer - CVE-2011-4622 kvm: pit timer with no irqchip crashes the system (rhbz 771387) - Add bluetooth support for BCM20102A0 (rhbz 770233) diff --git a/pci-crs-blacklist.patch b/pci-crs-blacklist.patch index bc17d54a5..b41e7c999 100644 --- a/pci-crs-blacklist.patch +++ b/pci-crs-blacklist.patch @@ -34,3 +34,22 @@ index 404f21a..2704a9c 100644 {} }; +--- linux-3.1.noarch/arch/x86/pci/acpi.c~ 2011-12-30 14:42:43.495717907 -0500 ++++ linux-3.1.noarch/arch/x86/pci/acpi.c 2011-12-30 14:45:09.296198024 -0500 +@@ -72,6 +72,16 @@ static const struct dmi_system_id pci_us + DMI_MATCH(DMI_BOARD_NAME, "0M273C"), + }, + }, ++ /* https://bugzilla.redhat.com/show_bug.cgi?id=769657 */ ++ { ++ .callback = set_nouse_crs, ++ .ident = "Thinkpad SL510", ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_BOARD_NAME, "2847DFG"), ++ DMI_MATCH(DMI_BIOS_VERSION, "6JET85WW (1.43 )"), ++ }, ++ }, + {} + }; + From 13eb970aa711abf5b5159278204a00815bc1b5e1 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 3 Jan 2012 13:43:28 -0500 Subject: [PATCH 201/487] Avoid unnecessary modprobe invocations during compat-wireless build --- compat-wireless-config-fixups.patch | 11 +++++++++++ kernel.spec | 3 +++ 2 files changed, 14 insertions(+) diff --git a/compat-wireless-config-fixups.patch b/compat-wireless-config-fixups.patch index 15566c35f..2e99b5d0f 100644 --- a/compat-wireless-config-fixups.patch +++ b/compat-wireless-config-fixups.patch @@ -69,6 +69,17 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/usb/Makefile.orig compat-wireless diff -up compat-wireless-3.2-rc6-3/Makefile.orig compat-wireless-3.2-rc6-3/Makefile --- compat-wireless-3.2-rc6-3/Makefile.orig 2012-01-03 09:41:57.109826807 -0500 +++ compat-wireless-3.2-rc6-3/Makefile 2012-01-03 09:42:03.470747287 -0500 +@@ -8,8 +8,8 @@ endif + export KLIB_BUILD ?= $(KLIB)/build + # Sometimes not available in the path + MODPROBE := /sbin/modprobe +-MADWIFI=$(shell $(MODPROBE) -l ath_pci) +-OLD_IWL=$(shell $(MODPROBE) -l iwl4965) ++MADWIFI="" ++OLD_IWL="" + + DESTDIR?= + @@ -41,8 +41,8 @@ endif endif diff --git a/kernel.spec b/kernel.spec index 51f50bae4..a1a83227c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2370,6 +2370,9 @@ fi # and build. %changelog +* Tue Jan 03 2012 John W. Linville +- Avoid unnecessary modprobe invocations during compat-wireless build + * Tue Jan 03 2012 Dave Jones - Add Thinkpad SL510 to the pci=nocrs blacklist. From 987f996218990ed2dceb818ba86ba792876eb4d6 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 3 Jan 2012 14:16:34 -0500 Subject: [PATCH 202/487] Linux 3.1.7 Should fix rhbz 767248 and possibly other 'fails to resume' bugs --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index a1a83227c..1ceb3fc00 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 6 +%define stable_update 7 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2370,6 +2370,9 @@ fi # and build. %changelog +* Tue Jan 03 2012 Josh Boyer 3.1.7-1 +- Linux 3.1.7 + * Tue Jan 03 2012 John W. Linville - Avoid unnecessary modprobe invocations during compat-wireless build diff --git a/sources b/sources index 4f88bd4c8..487e13e13 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 656f2b85102dc935039e867abd08b880 compat-wireless-3.2-rc6-3.tar.bz2 -b815dda0a05f7774a0ed0b705b8cfd4c patch-3.1.6.bz2 +13ea1e611a0a580138b8203e6f1353ed patch-3.1.7.bz2 From a8b9f7674811343fb92fbb8504ae988583477dde Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 4 Jan 2012 10:36:23 -0500 Subject: [PATCH 203/487] CVE-2011-4347 kvm: device assignment DoS (rhbz 771678) --- KVM-fix-device-assignment-permissions.patch | 206 ++++++++++++++++++++ kernel.spec | 11 +- 2 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 KVM-fix-device-assignment-permissions.patch diff --git a/KVM-fix-device-assignment-permissions.patch b/KVM-fix-device-assignment-permissions.patch new file mode 100644 index 000000000..208948200 --- /dev/null +++ b/KVM-fix-device-assignment-permissions.patch @@ -0,0 +1,206 @@ +From 423873736b78f549fbfa2f715f2e4de7e6c5e1e9 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Tue, 20 Dec 2011 21:59:03 -0700 +Subject: [PATCH 1/2] KVM: Remove ability to assign a device without iommu + support + +This option has no users and it exposes a security hole that we +can allow devices to be assigned without iommu protection. Make +KVM_DEV_ASSIGN_ENABLE_IOMMU a mandatory option. + +Signed-off-by: Alex Williamson +Signed-off-by: Marcelo Tosatti +--- + virt/kvm/assigned-dev.c | 18 +++++++++--------- + 1 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c +index 3ad0925..a251a28 100644 +--- a/virt/kvm/assigned-dev.c ++++ b/virt/kvm/assigned-dev.c +@@ -487,6 +487,9 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, + struct kvm_assigned_dev_kernel *match; + struct pci_dev *dev; + ++ if (!(assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU)) ++ return -EINVAL; ++ + mutex_lock(&kvm->lock); + idx = srcu_read_lock(&kvm->srcu); + +@@ -544,16 +547,14 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, + + list_add(&match->list, &kvm->arch.assigned_dev_head); + +- if (assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) { +- if (!kvm->arch.iommu_domain) { +- r = kvm_iommu_map_guest(kvm); +- if (r) +- goto out_list_del; +- } +- r = kvm_assign_device(kvm, match); ++ if (!kvm->arch.iommu_domain) { ++ r = kvm_iommu_map_guest(kvm); + if (r) + goto out_list_del; + } ++ r = kvm_assign_device(kvm, match); ++ if (r) ++ goto out_list_del; + + out: + srcu_read_unlock(&kvm->srcu, idx); +@@ -593,8 +594,7 @@ static int kvm_vm_ioctl_deassign_device(struct kvm *kvm, + goto out; + } + +- if (match->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) +- kvm_deassign_device(kvm, match); ++ kvm_deassign_device(kvm, match); + + kvm_free_assigned_device(kvm, match); + +-- +1.7.7.5 + + +From 3d27e23b17010c668db311140b17bbbb70c78fb9 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Tue, 20 Dec 2011 21:59:09 -0700 +Subject: [PATCH 2/2] KVM: Device assignment permission checks + +Only allow KVM device assignment to attach to devices which: + + - Are not bridges + - Have BAR resources (assume others are special devices) + - The user has permissions to use + +Assigning a bridge is a configuration error, it's not supported, and +typically doesn't result in the behavior the user is expecting anyway. +Devices without BAR resources are typically chipset components that +also don't have host drivers. We don't want users to hold such devices +captive or cause system problems by fencing them off into an iommu +domain. We determine "permission to use" by testing whether the user +has access to the PCI sysfs resource files. By default a normal user +will not have access to these files, so it provides a good indication +that an administration agent has granted the user access to the device. + +[Yang Bai: add missing #include] +[avi: fix comment style] + +Signed-off-by: Alex Williamson +Signed-off-by: Yang Bai +Signed-off-by: Marcelo Tosatti +--- + virt/kvm/assigned-dev.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 75 insertions(+), 0 deletions(-) + +diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c +index a251a28..758e3b3 100644 +--- a/virt/kvm/assigned-dev.c ++++ b/virt/kvm/assigned-dev.c +@@ -17,6 +17,8 @@ + #include + #include + #include ++#include ++#include + #include "irq.h" + + static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head, +@@ -480,12 +482,73 @@ out: + return r; + } + ++/* ++ * We want to test whether the caller has been granted permissions to ++ * use this device. To be able to configure and control the device, ++ * the user needs access to PCI configuration space and BAR resources. ++ * These are accessed through PCI sysfs. PCI config space is often ++ * passed to the process calling this ioctl via file descriptor, so we ++ * can't rely on access to that file. We can check for permissions ++ * on each of the BAR resource files, which is a pretty clear ++ * indicator that the user has been granted access to the device. ++ */ ++static int probe_sysfs_permissions(struct pci_dev *dev) ++{ ++#ifdef CONFIG_SYSFS ++ int i; ++ bool bar_found = false; ++ ++ for (i = PCI_STD_RESOURCES; i <= PCI_STD_RESOURCE_END; i++) { ++ char *kpath, *syspath; ++ struct path path; ++ struct inode *inode; ++ int r; ++ ++ if (!pci_resource_len(dev, i)) ++ continue; ++ ++ kpath = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); ++ if (!kpath) ++ return -ENOMEM; ++ ++ /* Per sysfs-rules, sysfs is always at /sys */ ++ syspath = kasprintf(GFP_KERNEL, "/sys%s/resource%d", kpath, i); ++ kfree(kpath); ++ if (!syspath) ++ return -ENOMEM; ++ ++ r = kern_path(syspath, LOOKUP_FOLLOW, &path); ++ kfree(syspath); ++ if (r) ++ return r; ++ ++ inode = path.dentry->d_inode; ++ ++ r = inode_permission(inode, MAY_READ | MAY_WRITE | MAY_ACCESS); ++ path_put(&path); ++ if (r) ++ return r; ++ ++ bar_found = true; ++ } ++ ++ /* If no resources, probably something special */ ++ if (!bar_found) ++ return -EPERM; ++ ++ return 0; ++#else ++ return -EINVAL; /* No way to control the device without sysfs */ ++#endif ++} ++ + static int kvm_vm_ioctl_assign_device(struct kvm *kvm, + struct kvm_assigned_pci_dev *assigned_dev) + { + int r = 0, idx; + struct kvm_assigned_dev_kernel *match; + struct pci_dev *dev; ++ u8 header_type; + + if (!(assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU)) + return -EINVAL; +@@ -516,6 +579,18 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, + r = -EINVAL; + goto out_free; + } ++ ++ /* Don't allow bridges to be assigned */ ++ pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); ++ if ((header_type & PCI_HEADER_TYPE) != PCI_HEADER_TYPE_NORMAL) { ++ r = -EPERM; ++ goto out_put; ++ } ++ ++ r = probe_sysfs_permissions(dev); ++ if (r) ++ goto out_put; ++ + if (pci_enable_device(dev)) { + printk(KERN_INFO "%s: Could not enable PCI device\n", __func__); + r = -EBUSY; +-- +1.7.7.5 + diff --git a/kernel.spec b/kernel.spec index 1ceb3fc00..a932a29f4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -852,6 +852,9 @@ Patch21050: thp-reduce-khugepaged-freezing-latency.patch #rhbz 771387 Patch21055: KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch +#rhbz 771678 +Patch21056: KVM-fix-device-assignment-permissions.patch + #rhbz 770233 Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch @@ -1595,6 +1598,9 @@ ApplyPatch KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch #rhbz 770233 ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch +#rhbz 771678 +ApplyPatch KVM-fix-device-assignment-permissions.patch + # END OF PATCH APPLICATIONS %endif @@ -2370,6 +2376,9 @@ fi # and build. %changelog +* Wed Jan 04 2012 Josh Boyer +- CVE-2011-4347 kvm: device assignment DoS (rhbz 771678) + * Tue Jan 03 2012 Josh Boyer 3.1.7-1 - Linux 3.1.7 From c7ebc6df232af088d4774ce2ecc6d021bfb4ce91 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 4 Jan 2012 11:27:38 -0500 Subject: [PATCH 204/487] Add Dell Studio 1557 to pci=nocrs blacklist. (rhbz 769657) --- kernel.spec | 3 +++ pci-crs-blacklist.patch | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/kernel.spec b/kernel.spec index a932a29f4..9444c218b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2376,6 +2376,9 @@ fi # and build. %changelog +* Wed Jan 04 2012 Dave Jones +- Add Dell Studio 1557 to pci=nocrs blacklist. (rhbz 769657) + * Wed Jan 04 2012 Josh Boyer - CVE-2011-4347 kvm: device assignment DoS (rhbz 771678) diff --git a/pci-crs-blacklist.patch b/pci-crs-blacklist.patch index b41e7c999..6b821ebc4 100644 --- a/pci-crs-blacklist.patch +++ b/pci-crs-blacklist.patch @@ -53,3 +53,22 @@ index 404f21a..2704a9c 100644 {} }; +--- linux-3.1.noarch/arch/x86/pci/acpi.c~ 2012-01-04 11:19:36.783664477 -0500 ++++ linux-3.1.noarch/arch/x86/pci/acpi.c 2012-01-04 11:23:42.403666272 -0500 +@@ -75,6 +75,16 @@ static const struct dmi_system_id pci_us + /* https://bugzilla.redhat.com/show_bug.cgi?id=769657 */ + { + .callback = set_nouse_crs, ++ .ident = "Dell Studio 1557", ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1557"); ++ DMI_MATCH(DMI_BIOS_VERSION, "A09"), ++ }, ++ }, ++ /* https://bugzilla.redhat.com/show_bug.cgi?id=769657 */ ++ { ++ .callback = set_nouse_crs, + .ident = "Thinkpad SL510", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), From 114a35487e42b55901c6ee295fd5efce1b98d586 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 4 Jan 2012 16:05:07 -0500 Subject: [PATCH 205/487] Resolves: bz 771058 --- kernel.spec | 9 ++++ msi-irq-sysfs-warning.patch | 87 +++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 msi-irq-sysfs-warning.patch diff --git a/kernel.spec b/kernel.spec index 9444c218b..6e191dd06 100644 --- a/kernel.spec +++ b/kernel.spec @@ -869,6 +869,9 @@ Patch50104: mwifiex-avoid-double-list_del-in-command-cancel-path.patch Patch22000: route-cache-garbage-collector.patch +#rhbz 771058 +Patch22100: msi-irq-sysfs-warning.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1601,6 +1604,9 @@ ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch #rhbz 771678 ApplyPatch KVM-fix-device-assignment-permissions.patch +#rhbz 771058 +ApplyPatch msi-irq-sysfs-warning.patch + # END OF PATCH APPLICATIONS %endif @@ -2376,6 +2382,9 @@ fi # and build. %changelog +* Wed Jan 04 2012 Neil Horman +- Fix warning about msi sysfs refcount (bz 771058) + * Wed Jan 04 2012 Dave Jones - Add Dell Studio 1557 to pci=nocrs blacklist. (rhbz 769657) diff --git a/msi-irq-sysfs-warning.patch b/msi-irq-sysfs-warning.patch new file mode 100644 index 000000000..dce440e4a --- /dev/null +++ b/msi-irq-sysfs-warning.patch @@ -0,0 +1,87 @@ +commit 3ff0e97a1bc3059bfbcc1d864c5d4ff5f8d3c2b9 +Author: Neil Horman +Date: Tue Jan 3 10:17:21 2012 -0500 + + msi: fix imbalanced refcount of msi irq sysfs objects + + This warning was recently reported to me: + + ------------[ cut here ]------------ + WARNING: at lib/kobject.c:595 kobject_put+0x50/0x60() + Hardware name: VMware Virtual Platform + kobject: '(null)' (ffff880027b0df40): is not initialized, yet kobject_put() is + being called. + Modules linked in: vmxnet3(+) vmw_balloon i2c_piix4 i2c_core shpchp raid10 + vmw_pvscsi + Pid: 630, comm: modprobe Tainted: G W 3.1.6-1.fc16.x86_64 #1 + Call Trace: + [] warn_slowpath_common+0x7f/0xc0 + [] warn_slowpath_fmt+0x46/0x50 + [] ? free_desc+0x63/0x70 + [] kobject_put+0x50/0x60 + [] free_msi_irqs+0xd5/0x120 + [] pci_enable_msi_block+0x24c/0x2c0 + [] vmxnet3_alloc_intr_resources+0x173/0x240 [vmxnet3] + [] vmxnet3_probe_device+0x615/0x834 [vmxnet3] + [] local_pci_probe+0x5c/0xd0 + [] pci_device_probe+0x109/0x130 + [] driver_probe_device+0x9c/0x2b0 + [] __driver_attach+0xab/0xb0 + [] ? driver_probe_device+0x2b0/0x2b0 + [] ? driver_probe_device+0x2b0/0x2b0 + [] bus_for_each_dev+0x5c/0x90 + [] driver_attach+0x1e/0x20 + [] bus_add_driver+0x1b0/0x2a0 + [] ? 0xffffffffa0187fff + [] driver_register+0x76/0x140 + [] ? printk+0x51/0x53 + [] ? 0xffffffffa0187fff + [] __pci_register_driver+0x56/0xd0 + [] vmxnet3_init_module+0x3a/0x3c [vmxnet3] + [] do_one_initcall+0x42/0x180 + [] sys_init_module+0x91/0x200 + [] system_call_fastpath+0x16/0x1b + ---[ end trace 44593438a59a9558 ]--- + Using INTx interrupt, #Rx queues: 1. + + It occurs when populate_msi_sysfs fails, which in turn causes free_msi_irqs to + be called. Because populate_msi_sysfs fails, we never registered any of the + msi irq sysfs objects, but free_msi_irqs still calls kobject_del and kobject_put + on each of them, which gets flagged in the above stack trace. + + The fix is pretty straightforward. We can key of the parent pointer in the + kobject. It is only set if the kobject_init_and_add succededs in + populate_msi_sysfs. If anything fails there, each kobject has its parent reset + to NULL + + Signed-off-by: Neil Horman + CC: Jesse Barnes + CC: Bjorn Helgaas + CC: Greg Kroah-Hartman + CC: linux-pci@vger.kernel.org + +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index 337e16a..82de95e 100644 +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -323,8 +323,18 @@ static void free_msi_irqs(struct pci_dev *dev) + if (list_is_last(&entry->list, &dev->msi_list)) + iounmap(entry->mask_base); + } +- kobject_del(&entry->kobj); +- kobject_put(&entry->kobj); ++ ++ /* ++ * Its possible that we get into this path ++ * When populate_msi_sysfs fails, which means the entries ++ * were not registered with sysfs. In that case don't ++ * unregister them. ++ */ ++ if (entry->kobj.parent) { ++ kobject_del(&entry->kobj); ++ kobject_put(&entry->kobj); ++ } ++ + list_del(&entry->list); + kfree(entry); + } From 94ce6750fb66788c4392843708b9d4141a226b88 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 4 Jan 2012 18:56:53 -0500 Subject: [PATCH 206/487] Disable PCI CRS blacklist patch Try alternative approach from Bjorn Helgaas to work around MCFG quirks on some laptops. --- dell-mmconfig-quirk.patch | 205 ++++++++++++++++++++++++++++++++++++++ kernel.spec | 9 +- 2 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 dell-mmconfig-quirk.patch diff --git a/dell-mmconfig-quirk.patch b/dell-mmconfig-quirk.patch new file mode 100644 index 000000000..6ee6b73ba --- /dev/null +++ b/dell-mmconfig-quirk.patch @@ -0,0 +1,205 @@ + x86, amd: factor out MMCONFIG discovery + + This factors out the AMD native MMCONFIG discovery so we can use it + outside amd_bus.c. + + amd_bus.c reads AMD MSRs so it can remove the MMCONFIG area from the + PCI resources. We may also need the MMCONFIG information to work + around BIOS defects in the ACPI MCFG table. + + Signed-off-by: Bjorn Helgaas +--- a/arch/x86/include/asm/amd_nb.h ++++ a/arch/x86/include/asm/amd_nb.h +@@ -13,6 +13,7 @@ extern const struct pci_device_id amd_nb_misc_ids[]; + extern const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[]; + + extern bool early_is_amd_nb(u32 value); ++extern void amd_get_mmconfig_range(u64 *start, u64 *end); + extern int amd_cache_northbridges(void); + extern void amd_flush_garts(void); + extern int amd_numa_init(void); +--- a/arch/x86/kernel/amd_nb.c ++++ a/arch/x86/kernel/amd_nb.c +@@ -119,6 +119,38 @@ bool __init early_is_amd_nb(u32 device) + return false; + } + ++void amd_get_mmconfig_range(u64 *start, u64 *end) ++{ ++ u32 address; ++ u64 base, msr; ++ unsigned segn_busn_bits; ++ ++ *start = 0; ++ *end = 0; ++ ++ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) ++ return; ++ ++ /* assume all cpus from fam10h have mmconfig */ ++ if (boot_cpu_data.x86 < 0x10) ++ return; ++ ++ address = MSR_FAM10H_MMIO_CONF_BASE; ++ rdmsrl(address, msr); ++ ++ /* mmconfig is not enabled */ ++ if (!(msr & FAM10H_MMIO_CONF_ENABLE)) ++ return; ++ ++ base = msr & (FAM10H_MMIO_CONF_BASE_MASK<> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) & ++ FAM10H_MMIO_CONF_BUSRANGE_MASK; ++ ++ *start = base; ++ *end = base + (1ULL<<(segn_busn_bits + 20)) - 1; ++} ++ + int amd_get_subcaches(int cpu) + { + struct pci_dev *link = node_to_amd_nb(amd_get_nb_id(cpu))->link; +--- a/arch/x86/pci/amd_bus.c ++++ a/arch/x86/pci/amd_bus.c +@@ -30,34 +30,6 @@ static struct pci_hostbridge_probe pci_probes[] __initdata = { + { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1300 }, + }; + +-static u64 __initdata fam10h_mmconf_start; +-static u64 __initdata fam10h_mmconf_end; +-static void __init get_pci_mmcfg_amd_fam10h_range(void) +-{ +- u32 address; +- u64 base, msr; +- unsigned segn_busn_bits; +- +- /* assume all cpus from fam10h have mmconf */ +- if (boot_cpu_data.x86 < 0x10) +- return; +- +- address = MSR_FAM10H_MMIO_CONF_BASE; +- rdmsrl(address, msr); +- +- /* mmconfig is not enable */ +- if (!(msr & FAM10H_MMIO_CONF_ENABLE)) +- return; +- +- base = msr & (FAM10H_MMIO_CONF_BASE_MASK<> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) & +- FAM10H_MMIO_CONF_BUSRANGE_MASK; +- +- fam10h_mmconf_start = base; +- fam10h_mmconf_end = base + (1ULL<<(segn_busn_bits + 20)) - 1; +-} +- + #define RANGE_NUM 16 + + /** +@@ -85,6 +57,8 @@ static int __init early_fill_mp_bus_info(void) + u64 val; + u32 address; + bool found; ++ u64 fam10h_mmconf_start; ++ u64 fam10h_mmconf_end; + + if (!early_pci_allowed()) + return -1; +@@ -211,7 +185,7 @@ static int __init early_fill_mp_bus_info(void) + subtract_range(range, RANGE_NUM, 0, end); + + /* get mmconfig */ +- get_pci_mmcfg_amd_fam10h_range(); ++ amd_get_mmconfig_range(&fam10h_mmconf_start, &fam10h_mmconf_end); + /* need to take out mmconf range */ + if (fam10h_mmconf_end) { + printk(KERN_DEBUG "Fam 10h mmconf [%llx, %llx]\n", fam10h_mmconf_start, fam10h_mmconf_end); + + + + + PNP: work around Dell 1536/1546 BIOS MMCONFIG bug that breaks USB + + Some Dell BIOSes have MCFG tables that don't report the entire + MMCONFIG area claimed by the chipset. If we move PCI devices into + that claimed-but-unreported area, they don't work. + + This quirk reads the AMD MMCONFIG MSRs and adds PNP0C01 resources as + needed to cover the entire area. + + Example problem scenario: + + BIOS-e820: 00000000cfec5400 - 00000000d4000000 (reserved) + Fam 10h mmconf [d0000000, dfffffff] + PCI: MMCONFIG for domain 0000 [bus 00-3f] at [mem 0xd0000000-0xd3ffffff] (base 0xd0000000) + pnp 00:0c: [mem 0xd0000000-0xd3ffffff] + pci 0000:00:12.0: reg 10: [mem 0xffb00000-0xffb00fff] + pci 0000:00:12.0: no compatible bridge window for [mem 0xffb00000-0xffb00fff] + pci 0000:00:12.0: BAR 0: assigned [mem 0xd4000000-0xd40000ff] + + Reported-by: Lisa Salimbas + Reported-by: + References: https://bugzilla.kernel.org/show_bug.cgi?id=31602 + References: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/647043 + References: https://bugzilla.redhat.com/show_bug.cgi?id=770308 + Cc: stable@kernel.org # 2.6.34+ + Signed-off-by: Bjorn Helgaas +--- a/drivers/pnp/quirks.c ++++ a/drivers/pnp/quirks.c +@@ -295,6 +295,46 @@ static void quirk_system_pci_resources(struct pnp_dev *dev) + } + } + ++#ifdef CONFIG_AMD_NB ++ ++#include ++ ++static void quirk_amd_mmconfig_area(struct pnp_dev *dev) ++{ ++ u64 mmconfig_start, mmconfig_end; ++ resource_size_t start, end; ++ struct pnp_resource *pnp_res; ++ struct resource *res; ++ ++ amd_get_mmconfig_range(&mmconfig_start, &mmconfig_end); ++ if (!mmconfig_end) ++ return; ++ ++ list_for_each_entry(pnp_res, &dev->resources, list) { ++ res = &pnp_res->res; ++ if (res->end < mmconfig_start || res->start > mmconfig_end || ++ (res->start == mmconfig_start && res->end == mmconfig_end)) ++ continue; ++ ++ dev_warn(&dev->dev, FW_BUG ++ "%pR covers only part of AMD MMCONFIG area [mem %#010llx-%#010llx]; adding more reservations\n", ++ res, (unsigned long long) mmconfig_start, ++ (unsigned long long) mmconfig_end); ++ if (mmconfig_start < res->start) { ++ start = mmconfig_start; ++ end = res->start - 1; ++ pnp_add_mem_resource(dev, start, end, 0); ++ } ++ if (mmconfig_end > res->end) { ++ start = res->end + 1; ++ end = mmconfig_end; ++ pnp_add_mem_resource(dev, start, end, 0); ++ } ++ break; ++ } ++} ++#endif ++ + /* + * PnP Quirks + * Cards or devices that need some tweaking due to incomplete resource info +@@ -322,6 +362,9 @@ static struct pnp_fixup pnp_fixups[] = { + /* PnP resources that might overlap PCI BARs */ + {"PNP0c01", quirk_system_pci_resources}, + {"PNP0c02", quirk_system_pci_resources}, ++#ifdef CONFIG_AMD_NB ++ {"PNP0c01", quirk_amd_mmconfig_area}, ++#endif + {""} + }; + diff --git a/kernel.spec b/kernel.spec index 6e191dd06..76dfdf14c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -827,6 +827,7 @@ Patch21220: mac80211_offchannel_rework_revert.patch Patch21225: pci-Rework-ASPM-disable-code.patch Patch21226: pci-crs-blacklist.patch +Patch21227: dell-mmconfig-quirk.patch #rhbz #757839 Patch21230: net-sky2-88e8059-fix-link-speed.patch @@ -1570,7 +1571,8 @@ ApplyPatch mac80211_offchannel_rework_revert.patch ApplyPatch pci-Rework-ASPM-disable-code.patch -ApplyPatch pci-crs-blacklist.patch +#ApplyPatch pci-crs-blacklist.patch +ApplyPatch dell-mmconfig-quirk.patch #rhbz #757839 ApplyPatch net-sky2-88e8059-fix-link-speed.patch @@ -2385,6 +2387,11 @@ fi * Wed Jan 04 2012 Neil Horman - Fix warning about msi sysfs refcount (bz 771058) +* Wed Jan 04 2012 Dave Jones +- Disable PCI CRS blacklist patch +- Try alternative approach from Bjorn Helgaas to work around + MCFG quirks on some laptops. + * Wed Jan 04 2012 Dave Jones - Add Dell Studio 1557 to pci=nocrs blacklist. (rhbz 769657) From 8f76b141c974752e4dc6ca755bd32a332a11778c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 4 Jan 2012 19:26:13 -0500 Subject: [PATCH 207/487] fix up typo in case this gets re-enabled. --- pci-crs-blacklist.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pci-crs-blacklist.patch b/pci-crs-blacklist.patch index 6b821ebc4..76dc22caa 100644 --- a/pci-crs-blacklist.patch +++ b/pci-crs-blacklist.patch @@ -62,7 +62,7 @@ index 404f21a..2704a9c 100644 + .ident = "Dell Studio 1557", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Dell Inc."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1557"); ++ DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1557"), + DMI_MATCH(DMI_BIOS_VERSION, "A09"), + }, + }, From e0bcc4d2287fbbf031bafcc64fd7376eaeb62efe Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 5 Jan 2012 13:38:54 -0500 Subject: [PATCH 208/487] Move the depmod file removal below the compat-wireless build to make sure we clean them all out --- kernel.spec | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/kernel.spec b/kernel.spec index 76dfdf14c..4a737aa09 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -1909,12 +1909,6 @@ BuildKernel() { rm -f modinfo modnames - # remove files that will be auto generated by depmod at rpm -i time - for i in alias alias.bin builtin.bin ccwmap dep dep.bin ieee1394map inputmap isapnpmap ofmap pcimap seriomap symbols symbols.bin usbmap - do - rm -f $RPM_BUILD_ROOT/lib/modules/$KernelVer/modules.$i - done - # Move the devel headers out of the root file system mkdir -p $RPM_BUILD_ROOT/usr/src/kernels mv $RPM_BUILD_ROOT/lib/modules/$KernelVer/build $RPM_BUILD_ROOT/$DevelDir @@ -1938,6 +1932,13 @@ BuildKernel() { cd - %endif + + # remove files that will be auto generated by depmod at rpm -i time + for i in alias alias.bin builtin.bin ccwmap dep dep.bin ieee1394map inputmap isapnpmap ofmap pcimap seriomap symbols symbols.bin usbmap + do + rm -f $RPM_BUILD_ROOT/lib/modules/$KernelVer/modules.$i + done + } ### @@ -2384,6 +2385,10 @@ fi # and build. %changelog +* Thu Jan 05 2012 Josh Boyer +- Move the depmod file removal below the compat-wireless build to make sure we + clean them all out + * Wed Jan 04 2012 Neil Horman - Fix warning about msi sysfs refcount (bz 771058) From be48fc0c69d2d07a64dc55061f34b9de5fab0752 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 5 Jan 2012 14:26:22 -0500 Subject: [PATCH 209/487] Patch compat-wireless build to avoid "pr_fmt redefined" warnings Include compat-wireless in removal of files resulting from patch fuzz --- ...at-wireless-pr_fmt-warning-avoidance.patch | 690 ++++++++++++++++++ kernel.spec | 12 +- 2 files changed, 699 insertions(+), 3 deletions(-) create mode 100644 compat-wireless-pr_fmt-warning-avoidance.patch diff --git a/compat-wireless-pr_fmt-warning-avoidance.patch b/compat-wireless-pr_fmt-warning-avoidance.patch new file mode 100644 index 000000000..9403b1b68 --- /dev/null +++ b/compat-wireless-pr_fmt-warning-avoidance.patch @@ -0,0 +1,690 @@ +diff -up compat-wireless-3.2-rc6-3/compat/crc8.c.orig compat-wireless-3.2-rc6-3/compat/crc8.c +--- compat-wireless-3.2-rc6-3/compat/crc8.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/compat/crc8.c 2012-01-05 14:17:19.613363481 -0500 +@@ -14,6 +14,7 @@ + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/bcma/bcma_private.h.orig compat-wireless-3.2-rc6-3/drivers/bcma/bcma_private.h +--- compat-wireless-3.2-rc6-3/drivers/bcma/bcma_private.h.orig 2011-12-19 22:45:13.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/bcma/bcma_private.h 2012-01-05 14:17:19.614363468 -0500 +@@ -1,6 +1,7 @@ + #ifndef LINUX_BCMA_PRIVATE_H_ + #define LINUX_BCMA_PRIVATE_H_ + ++#undef pr_fmt + #ifndef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #endif +diff -up compat-wireless-3.2-rc6-3/drivers/net/ethernet/broadcom/b44.c.orig compat-wireless-3.2-rc6-3/drivers/net/ethernet/broadcom/b44.c +--- compat-wireless-3.2-rc6-3/drivers/net/ethernet/broadcom/b44.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/ethernet/broadcom/b44.c 2012-01-05 14:17:19.615363455 -0500 +@@ -10,6 +10,7 @@ + * Distribute under GPL. + */ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/brcm80211/brcmsmac/dma.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/brcm80211/brcmsmac/dma.c +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl3945-base.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl3945-base.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl3945-base.c.orig 2012-01-05 14:19:37.561638888 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl3945-base.c 2012-01-05 14:19:45.500539640 -0500 +@@ -27,6 +27,7 @@ + * + *****************************************************************************/ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl4965-base.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl4965-base.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl4965-base.c.orig 2012-01-05 14:19:25.875784981 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl4965-base.c 2012-01-05 14:19:31.017720699 -0500 +@@ -27,6 +27,7 @@ + * + *****************************************************************************/ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/cfg.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/cfg.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/cfg.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/cfg.c 2012-01-05 14:17:22.706324811 -0500 +@@ -6,6 +6,7 @@ + * + */ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_cs.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_cs.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_cs.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_cs.c 2012-01-05 14:17:22.707324799 -0500 +@@ -21,6 +21,7 @@ + + */ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_sdio.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_sdio.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_sdio.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_sdio.c 2012-01-05 14:17:22.709324775 -0500 +@@ -26,6 +26,7 @@ + * if_sdio_card_to_host() to pad the data. + */ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_spi.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_spi.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_spi.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_spi.c 2012-01-05 14:17:22.710324763 -0500 +@@ -17,6 +17,7 @@ + * (at your option) any later version. + */ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_usb.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_usb.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_usb.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_usb.c 2012-01-05 14:17:22.711324751 -0500 +@@ -2,6 +2,7 @@ + * This file contains functions used in USB interface module. + */ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/main.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/main.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/main.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/main.c 2012-01-05 14:17:22.712324738 -0500 +@@ -4,6 +4,7 @@ + * thread etc.. + */ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/mesh.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/mesh.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/mesh.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/mesh.c 2012-01-05 14:17:22.713324725 -0500 +@@ -1,3 +1,4 @@ ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/rx.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/rx.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/rx.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/rx.c 2012-01-05 14:17:22.714324712 -0500 +@@ -2,6 +2,7 @@ + * This file contains the handling of RX in wlan driver. + */ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/cmd.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/cmd.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/cmd.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/cmd.c 2012-01-05 14:17:22.715324699 -0500 +@@ -7,6 +7,7 @@ + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/if_usb.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/if_usb.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/if_usb.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/if_usb.c 2012-01-05 14:17:22.716324687 -0500 +@@ -9,6 +9,7 @@ + */ + #define DRV_NAME "lbtf_usb" + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include "libertas_tf.h" +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/main.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/main.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/main.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/main.c 2012-01-05 14:17:22.717324675 -0500 +@@ -7,6 +7,7 @@ + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/base.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/base.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/base.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/base.c 2012-01-05 14:17:22.719324651 -0500 +@@ -27,6 +27,7 @@ + * + *****************************************************************************/ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/cam.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/cam.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/cam.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/cam.c 2012-01-05 14:17:22.719324651 -0500 +@@ -27,6 +27,7 @@ + * + *****************************************************************************/ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-05 14:17:22.720324638 -0500 +@@ -27,6 +27,7 @@ + * + *****************************************************************************/ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c 2012-01-05 14:17:22.722324612 -0500 +@@ -27,6 +27,7 @@ + * + *****************************************************************************/ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include "../wifi.h" +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c 2012-01-05 14:17:22.724324587 -0500 +@@ -27,6 +27,7 @@ + * + ****************************************************************************/ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192de/sw.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192de/sw.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192de/sw.c 2012-01-05 14:17:22.724324587 -0500 +@@ -27,6 +27,7 @@ + * + *****************************************************************************/ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/hw.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/hw.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/hw.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/hw.c 2012-01-05 14:17:22.725324575 -0500 +@@ -27,6 +27,7 @@ + * + *****************************************************************************/ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include "../wifi.h" +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/phy.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/phy.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/phy.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/phy.c 2012-01-05 14:17:22.726324563 -0500 +@@ -27,6 +27,7 @@ + * + *****************************************************************************/ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include "../wifi.h" +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/rf.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/rf.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/rf.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/rf.c 2012-01-05 14:17:22.726324563 -0500 +@@ -27,6 +27,7 @@ + * + *****************************************************************************/ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include "../wifi.h" +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/sw.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/sw.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/sw.c 2012-01-05 14:17:22.726324563 -0500 +@@ -27,6 +27,7 @@ + * + *****************************************************************************/ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/usb.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/usb.c +--- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/usb.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/usb.c 2012-01-05 14:17:22.727324551 -0500 +@@ -25,6 +25,7 @@ + * + *****************************************************************************/ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/net/wireless/core.c.orig compat-wireless-3.2-rc6-3/net/wireless/core.c +--- compat-wireless-3.2-rc6-3/net/wireless/core.c.orig 2011-12-19 22:45:14.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/net/wireless/core.c 2012-01-05 14:17:22.727324551 -0500 +@@ -4,6 +4,7 @@ + * Copyright 2006-2010 Johannes Berg + */ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/net/wireless/lib80211.c.orig compat-wireless-3.2-rc6-3/net/wireless/lib80211.c +--- compat-wireless-3.2-rc6-3/net/wireless/lib80211.c.orig 2011-12-19 22:45:13.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/net/wireless/lib80211.c 2012-01-05 14:17:22.727324551 -0500 +@@ -13,6 +13,7 @@ + * + */ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/net/wireless/lib80211_crypt_tkip.c.orig compat-wireless-3.2-rc6-3/net/wireless/lib80211_crypt_tkip.c +--- compat-wireless-3.2-rc6-3/net/wireless/lib80211_crypt_tkip.c.orig 2011-12-19 22:45:13.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/net/wireless/lib80211_crypt_tkip.c 2012-01-05 14:17:22.727324551 -0500 +@@ -10,6 +10,7 @@ + * more details. + */ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/net/wireless/reg.c.orig compat-wireless-3.2-rc6-3/net/wireless/reg.c +--- compat-wireless-3.2-rc6-3/net/wireless/reg.c.orig 2011-12-19 22:45:13.000000000 -0500 ++++ compat-wireless-3.2-rc6-3/net/wireless/reg.c 2012-01-05 14:17:22.728324538 -0500 +@@ -33,6 +33,7 @@ + * + */ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-3.2-rc6-3/patches/98-pr_fmt.patch.orig compat-wireless-3.2-rc6-3/patches/98-pr_fmt.patch +--- compat-wireless-3.2-rc6-3/patches/98-pr_fmt.patch.orig 2012-01-05 14:17:22.728324538 -0500 ++++ compat-wireless-3.2-rc6-3/patches/98-pr_fmt.patch 2012-01-05 14:17:22.728324538 -0500 +@@ -0,0 +1,346 @@ ++The way the compat-* header files are included causes the default ++pr_fmt definition from to be evaluated for every file. ++Files that define pr_fmt then generate a lot of build SPAM about ++pr_fmt being redefined. ++ ++Eliminate the build noise by preemptively undefining pr_fmt in those ++files that define it. ++ ++diff -up compat-wireless-3.2-rc1-1/compat/crc8.c.pr_fmt compat-wireless-3.2-rc1-1/compat/crc8.c ++--- compat-wireless-3.2-rc1-1/compat/crc8.c.pr_fmt 2011-11-18 15:08:04.497812086 -0500 +++++ compat-wireless-3.2-rc1-1/compat/crc8.c 2011-11-18 15:20:09.450522691 -0500 ++@@ -14,6 +14,7 @@ ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/bcma/bcma_private.h.pr_fmt compat-wireless-3.2-rc1-1/drivers/bcma/bcma_private.h ++--- compat-wireless-3.2-rc1-1/drivers/bcma/bcma_private.h.pr_fmt 2011-11-18 15:08:04.522323679 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/bcma/bcma_private.h 2011-11-18 15:20:09.451522757 -0500 ++@@ -1,6 +1,7 @@ ++ #ifndef LINUX_BCMA_PRIVATE_H_ ++ #define LINUX_BCMA_PRIVATE_H_ ++ +++#undef pr_fmt ++ #ifndef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ #endif ++diff -up compat-wireless-3.2-rc1-1/drivers/net/ethernet/broadcom/b44.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/ethernet/broadcom/b44.c ++--- compat-wireless-3.2-rc1-1/drivers/net/ethernet/broadcom/b44.c.pr_fmt 2011-11-18 15:08:04.529757401 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/ethernet/broadcom/b44.c 2011-11-18 15:20:09.453522618 -0500 ++@@ -10,6 +10,7 @@ ++ * Distribute under GPL. ++ */ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/iwlegacy/iwl3945-base.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/iwlegacy/iwl3945-base.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/iwlegacy/iwl3945-base.c.pr_fmt 2011-11-18 15:08:04.531811389 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/iwlegacy/iwl3945-base.c 2011-11-18 15:20:09.455522411 -0500 ++@@ -27,6 +27,7 @@ ++ * ++ *****************************************************************************/ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/iwlegacy/iwl4965-base.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/iwlegacy/iwl4965-base.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/iwlegacy/iwl4965-base.c.pr_fmt 2011-11-18 15:08:04.533811528 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/iwlegacy/iwl4965-base.c 2011-11-18 15:20:09.456520247 -0500 ++@@ -27,6 +27,7 @@ ++ * ++ *****************************************************************************/ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/cfg.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/cfg.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/cfg.c.pr_fmt 2011-11-18 15:08:04.534811319 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/cfg.c 2011-11-18 15:20:09.456520247 -0500 ++@@ -6,6 +6,7 @@ ++ * ++ */ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_cs.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_cs.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_cs.c.pr_fmt 2011-11-18 15:08:04.534811319 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_cs.c 2011-11-18 15:20:09.457520945 -0500 ++@@ -21,6 +21,7 @@ ++ ++ */ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_sdio.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_sdio.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_sdio.c.pr_fmt 2011-11-18 15:08:04.535829198 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_sdio.c 2011-11-18 15:20:09.457520945 -0500 ++@@ -26,6 +26,7 @@ ++ * if_sdio_card_to_host() to pad the data. ++ */ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_spi.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_spi.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_spi.c.pr_fmt 2011-11-18 15:08:04.536811878 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_spi.c 2011-11-18 15:20:09.457520945 -0500 ++@@ -17,6 +17,7 @@ ++ * (at your option) any later version. ++ */ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_usb.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_usb.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_usb.c.pr_fmt 2011-11-18 15:08:04.536811878 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_usb.c 2011-11-18 15:20:09.458521084 -0500 ++@@ -2,6 +2,7 @@ ++ * This file contains functions used in USB interface module. ++ */ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/main.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/main.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/main.c.pr_fmt 2011-11-18 15:08:04.537812436 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/main.c 2011-11-18 15:20:09.458521084 -0500 ++@@ -4,6 +4,7 @@ ++ * thread etc.. ++ */ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/mesh.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/mesh.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/mesh.c.pr_fmt 2011-11-18 15:08:04.537812436 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/mesh.c 2011-11-18 15:20:09.458521084 -0500 ++@@ -1,3 +1,4 @@ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/rx.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/rx.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/rx.c.pr_fmt 2011-11-18 15:08:04.538812017 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/rx.c 2011-11-18 15:20:09.459520455 -0500 ++@@ -2,6 +2,7 @@ ++ * This file contains the handling of RX in wlan driver. ++ */ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/cmd.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/cmd.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/cmd.c.pr_fmt 2011-11-18 15:08:04.544819700 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/cmd.c 2011-11-18 15:20:09.459520455 -0500 ++@@ -7,6 +7,7 @@ ++ * the Free Software Foundation; either version 2 of the License, or (at ++ * your option) any later version. ++ */ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/if_usb.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/if_usb.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/if_usb.c.pr_fmt 2011-11-18 15:08:04.545747064 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/if_usb.c 2011-11-18 15:20:09.459520455 -0500 ++@@ -9,6 +9,7 @@ ++ */ ++ #define DRV_NAME "lbtf_usb" ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include "libertas_tf.h" ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/main.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/main.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/main.c.pr_fmt 2011-11-18 15:08:04.545747064 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/main.c 2011-11-18 15:20:09.459520455 -0500 ++@@ -7,6 +7,7 @@ ++ * the Free Software Foundation; either version 2 of the License, or (at ++ * your option) any later version. ++ */ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/base.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/base.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/base.c.pr_fmt 2011-11-18 15:08:04.565011903 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/base.c 2011-11-18 15:20:55.315644844 -0500 ++@@ -27,6 +27,7 @@ ++ * ++ *****************************************************************************/ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/cam.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/cam.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/cam.c.pr_fmt 2011-11-18 15:08:04.565812364 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/cam.c 2011-11-18 15:20:55.322652946 -0500 ++@@ -27,6 +27,7 @@ ++ * ++ *****************************************************************************/ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c.pr_fmt 2011-11-18 15:08:04.565812364 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2011-11-18 15:20:55.334647078 -0500 ++@@ -27,6 +27,7 @@ ++ * ++ *****************************************************************************/ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c.pr_fmt 2011-11-18 15:08:04.567811877 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c 2011-11-18 15:20:55.341625637 -0500 ++@@ -27,6 +27,7 @@ ++ * ++ *****************************************************************************/ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include "../wifi.h" ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c.pr_fmt 2011-11-18 15:08:04.567811877 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c 2011-11-18 15:20:55.342644635 -0500 ++@@ -27,6 +27,7 @@ ++ * ++ ****************************************************************************/ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192de/sw.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192de/sw.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192de/sw.c.pr_fmt 2011-11-18 15:08:04.568814042 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192de/sw.c 2011-11-18 15:20:55.350617325 -0500 ++@@ -27,6 +27,7 @@ ++ * ++ *****************************************************************************/ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/hw.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/hw.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/hw.c.pr_fmt 2011-11-18 15:08:04.569828848 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/hw.c 2011-11-18 15:20:55.358645682 -0500 ++@@ -27,6 +27,7 @@ ++ * ++ *****************************************************************************/ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include "../wifi.h" ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/phy.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/phy.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/phy.c.pr_fmt 2011-11-18 15:08:04.570818023 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/phy.c 2011-11-18 15:20:55.365635904 -0500 ++@@ -27,6 +27,7 @@ ++ * ++ *****************************************************************************/ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include "../wifi.h" ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/rf.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/rf.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/rf.c.pr_fmt 2011-11-18 15:08:04.571812156 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/rf.c 2011-11-18 15:20:55.371549230 -0500 ++@@ -27,6 +27,7 @@ ++ * ++ *****************************************************************************/ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include "../wifi.h" ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/sw.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/sw.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/sw.c.pr_fmt 2011-11-18 15:08:04.571812156 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/sw.c 2011-11-18 15:20:55.379720621 -0500 ++@@ -27,6 +27,7 @@ ++ * ++ *****************************************************************************/ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/usb.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/usb.c ++--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/usb.c.pr_fmt 2011-11-18 15:08:04.572718638 -0500 +++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/usb.c 2011-11-18 15:20:55.389173129 -0500 ++@@ -25,6 +25,7 @@ ++ * ++ *****************************************************************************/ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/net/wireless/core.c.pr_fmt compat-wireless-3.2-rc1-1/net/wireless/core.c ++--- compat-wireless-3.2-rc1-1/net/wireless/core.c.pr_fmt 2011-11-18 15:08:04.573774302 -0500 +++++ compat-wireless-3.2-rc1-1/net/wireless/core.c 2011-11-18 15:20:55.395647078 -0500 ++@@ -4,6 +4,7 @@ ++ * Copyright 2006-2010 Johannes Berg ++ */ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/net/wireless/lib80211.c.pr_fmt compat-wireless-3.2-rc1-1/net/wireless/lib80211.c ++--- compat-wireless-3.2-rc1-1/net/wireless/lib80211.c.pr_fmt 2011-11-18 15:08:04.573774302 -0500 +++++ compat-wireless-3.2-rc1-1/net/wireless/lib80211.c 2011-11-18 15:20:55.405646450 -0500 ++@@ -13,6 +13,7 @@ ++ * ++ */ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/net/wireless/lib80211_crypt_tkip.c.pr_fmt compat-wireless-3.2-rc1-1/net/wireless/lib80211_crypt_tkip.c ++--- compat-wireless-3.2-rc1-1/net/wireless/lib80211_crypt_tkip.c.pr_fmt 2011-11-18 15:08:04.574811667 -0500 +++++ compat-wireless-3.2-rc1-1/net/wireless/lib80211_crypt_tkip.c 2011-11-18 15:20:55.406648475 -0500 ++@@ -10,6 +10,7 @@ ++ * more details. ++ */ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include ++diff -up compat-wireless-3.2-rc1-1/net/wireless/reg.c.pr_fmt compat-wireless-3.2-rc1-1/net/wireless/reg.c ++--- compat-wireless-3.2-rc1-1/net/wireless/reg.c.pr_fmt 2011-11-18 15:08:04.575716473 -0500 +++++ compat-wireless-3.2-rc1-1/net/wireless/reg.c 2011-11-18 15:20:55.408647986 -0500 ++@@ -33,6 +33,7 @@ ++ * ++ */ ++ +++#undef pr_fmt ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ #include diff --git a/kernel.spec b/kernel.spec index 4a737aa09..148566d69 100644 --- a/kernel.spec +++ b/kernel.spec @@ -862,6 +862,7 @@ Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch +Patch50002: compat-wireless-pr_fmt-warning-avoidance.patch Patch50100: iwlwifi-tx_sync-only-on-PAN-context.patch Patch50101: ath9k-fix-max-phy-rate-at-rate-control-init.patch Patch50102: iwlwifi-do-not-set-the-sequence-control-bit-is-not-n.patch @@ -1656,9 +1657,6 @@ done # end of kernel config %endif -# get rid of unwanted files resulting from patch fuzz -find . \( -name "*.orig" -o -name "*~" \) -exec rm -f {} \; >/dev/null - # remove unnecessary SCM files find . -name .gitignore -exec rm -f {} \; >/dev/null @@ -1676,6 +1674,7 @@ cd compat-wireless-%{cwversion} ApplyPatch compat-wireless-config-fixups.patch ApplyPatch compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch +ApplyPatch compat-wireless-pr_fmt-warning-avoidance.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch @@ -1692,6 +1691,9 @@ cd .. %endif +# get rid of unwanted files resulting from patch fuzz +find . \( -name "*.orig" -o -name "*~" \) -exec rm -f {} \; >/dev/null + ### ### build ### @@ -2385,6 +2387,10 @@ fi # and build. %changelog +* Thu Jan 05 2012 John W. Linville +- Patch compat-wireless build to avoid "pr_fmt redefined" warnings +- Include compat-wireless in removal of files resulting from patch fuzz + * Thu Jan 05 2012 Josh Boyer - Move the depmod file removal below the compat-wireless build to make sure we clean them all out From 19c6b8e07305375c201e0a2feb7a0d2257222b6e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 12 Dec 2011 14:36:14 -0500 Subject: [PATCH 210/487] Disable backports on arches where we don't actually build a kernel (or config) --- kernel.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 148566d69..49c0d666b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -471,6 +471,7 @@ Summary: The Linux kernel %define with_pae 0 %define with_debuginfo 0 %define with_tools 0 +%define with_backports 0 %define _enable_debug_packages 0 %endif @@ -2387,6 +2388,9 @@ fi # and build. %changelog +* Fri Jan 06 2012 Josh Boyer +- Disable backports on arches where we don't actually build a kernel (or config) + * Thu Jan 05 2012 John W. Linville - Patch compat-wireless build to avoid "pr_fmt redefined" warnings - Include compat-wireless in removal of files resulting from patch fuzz From 2aece3db380eaff11d3fd9e852bdf0a7e6ed5412 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 6 Jan 2012 21:40:42 -0500 Subject: [PATCH 211/487] Linux 3.1.8 --- ...-to-switch-to-HT40-if-not-associated.patch | 40 ---- kernel.spec | 23 +- oom-fix-integer-overflow-of-points.patch | 100 --------- route-cache-garbage-collector.patch | 201 ------------------ sources | 2 +- 5 files changed, 5 insertions(+), 361 deletions(-) delete mode 100644 iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch delete mode 100644 oom-fix-integer-overflow-of-points.patch delete mode 100644 route-cache-garbage-collector.patch diff --git a/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch b/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch deleted file mode 100644 index 7ded9c83a..000000000 --- a/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 78feb35b8161acd95c33a703ed6ab6f554d29387 Mon Sep 17 00:00:00 2001 -From: Wey-Yi Guy -Date: Wed, 14 Dec 2011 08:22:36 -0800 -Subject: [PATCH 2/2] iwlwifi: allow to switch to HT40 if not associated - -My previous patch -34a5b4b6af104cf18eb50748509528b9bdbc4036 iwlwifi: do not re-configure -HT40 after associated - -Fix the case of HT40 after association on specified AP, but it break the -association for some APs and cause not able to establish connection. -We need to address HT40 before and after addociation. - -CC: stable@vger.kernel.org #3.0+ -Reported-by: Andrej Gelenberg -Signed-off-by: Wey-Yi Guy -Tested-by: Andrej Gelenberg -Signed-off-by: John W. Linville ---- - drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -index a7a6def..5c7c17c 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -@@ -606,8 +606,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) - if (ctx->ht.enabled) { - /* if HT40 is used, it should not change - * after associated except channel switch */ -- if (iwl_is_associated_ctx(ctx) && -- !ctx->ht.is_40mhz) -+ if (!ctx->ht.is_40mhz || -+ !iwl_is_associated_ctx(ctx)) - iwlagn_config_ht40(conf, ctx); - } else - ctx->ht.is_40mhz = false; --- -1.7.4.4 - diff --git a/kernel.spec b/kernel.spec index 49c0d666b..c7d05627a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 7 +%define stable_update 8 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -803,8 +803,6 @@ Patch21031: benet-remove-bogus-unlikely-on-vlan-check.patch Patch21040: x86-code-dump-fix-truncation.patch -Patch21070: oom-fix-integer-overflow-of-points.patch - #rhbz 728607 Patch21060: elantech.patch @@ -839,9 +837,6 @@ Patch21045: nfs-client-freezer.patch #rhbz 590880 Patch21046: alps.patch -#rhbz 767173 -Patch21047: iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch - #rhbz 741117 Patch21048: b44-Use-dev_kfree_skb_irq-in-b44_tx.patch @@ -870,8 +865,6 @@ Patch50102: iwlwifi-do-not-set-the-sequence-control-bit-is-not-n.patch Patch50103: iwlwifi-update-SCD-BC-table-for-all-SCD-queues.patch Patch50104: mwifiex-avoid-double-list_del-in-command-cancel-path.patch -Patch22000: route-cache-garbage-collector.patch - #rhbz 771058 Patch22100: msi-irq-sysfs-warning.patch @@ -1545,9 +1538,6 @@ ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch #rhbz 736815 ApplyPatch x86-code-dump-fix-truncation.patch -#rhbz 750402 -ApplyPatch oom-fix-integer-overflow-of-points.patch - #rhbz 728607 ApplyPatch elantech.patch @@ -1585,9 +1575,6 @@ ApplyPatch nfs-client-freezer.patch #rhbz 590880 ApplyPatch alps.patch -#rhbz 767173 -ApplyPatch iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch - #rhbz 741117 ApplyPatch b44-Use-dev_kfree_skb_irq-in-b44_tx.patch @@ -1597,8 +1584,6 @@ ApplyPatch tpm_tis-delay-after-aborting-cmd.patch #rhbz 771006 ApplyPatch thp-reduce-khugepaged-freezing-latency.patch -ApplyPatch route-cache-garbage-collector.patch - #rhbz 771387 ApplyPatch KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch @@ -1685,7 +1670,6 @@ ApplyPatch iwlwifi-do-not-set-the-sequence-control-bit-is-not-n.patch ApplyPatch ath9k-fix-max-phy-rate-at-rate-control-init.patch ApplyPatch mwifiex-avoid-double-list_del-in-command-cancel-path.patch ApplyPatch iwlwifi-tx_sync-only-on-PAN-context.patch -ApplyPatch iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch ApplyPatch iwlwifi-update-SCD-BC-table-for-all-SCD-queues.patch cd .. @@ -2388,8 +2372,9 @@ fi # and build. %changelog -* Fri Jan 06 2012 Josh Boyer +* Fri Jan 06 2012 Josh Boyer 3.1.8-1 - Disable backports on arches where we don't actually build a kernel (or config) +- Linux 3.1.8 * Thu Jan 05 2012 John W. Linville - Patch compat-wireless build to avoid "pr_fmt redefined" warnings diff --git a/oom-fix-integer-overflow-of-points.patch b/oom-fix-integer-overflow-of-points.patch deleted file mode 100644 index 02f6a8f72..000000000 --- a/oom-fix-integer-overflow-of-points.patch +++ /dev/null @@ -1,100 +0,0 @@ - -Delivered-To: jwboyer@gmail.com -Received: by 10.220.45.11 with SMTP id c11cs62970vcf; - Mon, 31 Oct 2011 08:56:49 -0700 (PDT) -Received: by 10.101.15.19 with SMTP id s19mr2706064ani.103.1320076596057; - Mon, 31 Oct 2011 08:56:36 -0700 (PDT) -Return-Path: -Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) - by mx.google.com with ESMTP id x8si7676575ani.27.2011.10.31.08.56.32; - Mon, 31 Oct 2011 08:56:36 -0700 (PDT) -Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; -Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=linux-kernel-owner@vger.kernel.org -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S934545Ab1JaP4X (ORCPT + 99 others); - Mon, 31 Oct 2011 11:56:23 -0400 -Received: from mx1.redhat.com ([209.132.183.28]:23653 "EHLO mx1.redhat.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S934538Ab1JaP4X (ORCPT ); - Mon, 31 Oct 2011 11:56:23 -0400 -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p9VFuHOO027543 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); - Mon, 31 Oct 2011 11:56:18 -0400 -Received: from dhcp-26-164.brq.redhat.com (dhcp-26-164.brq.redhat.com [10.34.26.164]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p9VFuEK3018476; - Mon, 31 Oct 2011 11:56:15 -0400 -From: Frantisek Hrbata -To: rientjes@google.com -Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, - akpm@linux-foundation.org, kosaki.motohiro@jp.fujitsu.com, - oleg@redhat.com, minchan.kim@gmail.com, stable@kernel.org, - eteo@redhat.com, pmatouse@redhat.com -Subject: [PATCH v2] oom: fix integer overflow of points in oom_badness -Date: Mon, 31 Oct 2011 16:56:09 +0100 -Message-Id: <1320076569-23872-1-git-send-email-fhrbata@redhat.com> -In-Reply-To: <1320048865-13175-1-git-send-email-fhrbata@redhat.com> -References: <1320048865-13175-1-git-send-email-fhrbata@redhat.com> -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org - -An integer overflow will happen on 64bit archs if task's sum of rss, swapents -and nr_ptes exceeds (2^31)/1000 value. This was introduced by commit - -f755a04 oom: use pte pages in OOM score - -where the oom score computation was divided into several steps and it's no -longer computed as one expression in unsigned long(rss, swapents, nr_pte are -unsigned long), where the result value assigned to points(int) is in -range(1..1000). So there could be an int overflow while computing - -176 points *= 1000; - -and points may have negative value. Meaning the oom score for a mem hog task -will be one. - -196 if (points <= 0) -197 return 1; - -For example: -[ 3366] 0 3366 35390480 24303939 5 0 0 oom01 -Out of memory: Kill process 3366 (oom01) score 1 or sacrifice child - -Here the oom1 process consumes more than 24303939(rss)*4096~=92GB physical -memory, but it's oom score is one. - -In this situation the mem hog task is skipped and oom killer kills another and -most probably innocent task with oom score greater than one. - -The points variable should be of type long instead of int to prevent the int -overflow. - -Signed-off-by: Frantisek Hrbata ---- - mm/oom_kill.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/mm/oom_kill.c b/mm/oom_kill.c -index 626303b..e9a1785 100644 ---- a/mm/oom_kill.c -+++ b/mm/oom_kill.c -@@ -162,7 +162,7 @@ static bool oom_unkillable_task(struct task_struct *p, - unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem, - const nodemask_t *nodemask, unsigned long totalpages) - { -- int points; -+ long points; - - if (oom_unkillable_task(p, mem, nodemask)) - return 0; --- -1.7.6.4 - --- -To unsubscribe from this list: send the line "unsubscribe linux-kernel" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html -Please read the FAQ at http://www.tux.org/lkml/ diff --git a/route-cache-garbage-collector.patch b/route-cache-garbage-collector.patch deleted file mode 100644 index 6ea6e5e9b..000000000 --- a/route-cache-garbage-collector.patch +++ /dev/null @@ -1,201 +0,0 @@ -Message-ID: <1324461072.2728.19.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC> -Subject: Re: Kernel-DOS error in arp mechanism =?UTF-8?Q?=E2=80=93?= no delete off incomplete arp adresses -From: Eric Dumazet -To: David Miller -Cc: richard.weinberger@gmail.com, gladewitz@gmx.de, - linux-kernel@vger.kernel.org, netdev@vger.kernel.org -Date: Wed, 21 Dec 2011 10:51:12 +0100 -In-Reply-To: <20111221.030727.1528369698756365464.davem@davemloft.net> -References: <4EEC5286.3070408@gmx.de> - - <1324453467.2610.20.camel@edumazet-laptop> - <20111221.030727.1528369698756365464.davem@davemloft.net> -Content-Type: text/plain; charset="UTF-8" -Content-Transfer-Encoding: 8bit -Sender: linux-kernel-owner@vger.kernel.org -List-ID: - -Le mercredi 21 décembre 2011 à 03:07 -0500, David Miller a écrit : -> From: Eric Dumazet -> Date: Wed, 21 Dec 2011 08:44:27 +0100 -> -> > David, I suggest we add back the garbage collector for current kernels, -> > we'll remove it when route cache really disappear ? -> > -> > I'll send a patch today. -> -> Yes, it's the best idea. -> -> We can actually remove it again as early as when when route neigh's -> are ref-less. - -Here is the patch I successfully tested in the neighbour stress -situation. This is a stable candidate (2.6.39+) - -Thanks ! - -[PATCH] ipv4: reintroduce route cache garbage collector - -Commit 2c8cec5c10b (ipv4: Cache learned PMTU information in inetpeer) -removed IP route cache garbage collector a bit too soon, as this gc was -responsible for expired routes cleanup, releasing their neighbour -reference. - -As pointed out by Robert Gladewitz, recent kernels can fill and exhaust -their neighbour cache. - -Reintroduce the garbage collection, since we'll have to wait our -neighbour lookups become refcount-less to not depend on this stuff. - -Reported-by: Robert Gladewitz -Signed-off-by: Eric Dumazet ---- - net/ipv4/route.c | 107 +++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 107 insertions(+) - -diff --git a/net/ipv4/route.c b/net/ipv4/route.c -index 46af623..252c512 100644 ---- a/net/ipv4/route.c -+++ b/net/ipv4/route.c -@@ -133,6 +134,9 @@ static int ip_rt_min_advmss __read_mostly = 256; - static int rt_chain_length_max __read_mostly = 20; - static int redirect_genid; - -+static struct delayed_work expires_work; -+static unsigned long expires_ljiffies; -+ - /* - * Interface to generic destination cache. - */ -@@ -830,6 +834,97 @@ static int has_noalias(const struct rtable *head, const struct rtable *rth) - return ONE; - } - -+static void rt_check_expire(void) -+{ -+ static unsigned int rover; -+ unsigned int i = rover, goal; -+ struct rtable *rth; -+ struct rtable __rcu **rthp; -+ unsigned long samples = 0; -+ unsigned long sum = 0, sum2 = 0; -+ unsigned long delta; -+ u64 mult; -+ -+ delta = jiffies - expires_ljiffies; -+ expires_ljiffies = jiffies; -+ mult = ((u64)delta) << rt_hash_log; -+ if (ip_rt_gc_timeout > 1) -+ do_div(mult, ip_rt_gc_timeout); -+ goal = (unsigned int)mult; -+ if (goal > rt_hash_mask) -+ goal = rt_hash_mask + 1; -+ for (; goal > 0; goal--) { -+ unsigned long tmo = ip_rt_gc_timeout; -+ unsigned long length; -+ -+ i = (i + 1) & rt_hash_mask; -+ rthp = &rt_hash_table[i].chain; -+ -+ if (need_resched()) -+ cond_resched(); -+ -+ samples++; -+ -+ if (rcu_dereference_raw(*rthp) == NULL) -+ continue; -+ length = 0; -+ spin_lock_bh(rt_hash_lock_addr(i)); -+ while ((rth = rcu_dereference_protected(*rthp, -+ lockdep_is_held(rt_hash_lock_addr(i)))) != NULL) { -+ prefetch(rth->dst.rt_next); -+ if (rt_is_expired(rth)) { -+ *rthp = rth->dst.rt_next; -+ rt_free(rth); -+ continue; -+ } -+ if (rth->dst.expires) { -+ /* Entry is expired even if it is in use */ -+ if (time_before_eq(jiffies, rth->dst.expires)) { -+nofree: -+ tmo >>= 1; -+ rthp = &rth->dst.rt_next; -+ /* -+ * We only count entries on -+ * a chain with equal hash inputs once -+ * so that entries for different QOS -+ * levels, and other non-hash input -+ * attributes don't unfairly skew -+ * the length computation -+ */ -+ length += has_noalias(rt_hash_table[i].chain, rth); -+ continue; -+ } -+ } else if (!rt_may_expire(rth, tmo, ip_rt_gc_timeout)) -+ goto nofree; -+ -+ /* Cleanup aged off entries. */ -+ *rthp = rth->dst.rt_next; -+ rt_free(rth); -+ } -+ spin_unlock_bh(rt_hash_lock_addr(i)); -+ sum += length; -+ sum2 += length*length; -+ } -+ if (samples) { -+ unsigned long avg = sum / samples; -+ unsigned long sd = int_sqrt(sum2 / samples - avg*avg); -+ rt_chain_length_max = max_t(unsigned long, -+ ip_rt_gc_elasticity, -+ (avg + 4*sd) >> FRACT_BITS); -+ } -+ rover = i; -+} -+ -+/* -+ * rt_worker_func() is run in process context. -+ * we call rt_check_expire() to scan part of the hash table -+ */ -+static void rt_worker_func(struct work_struct *work) -+{ -+ rt_check_expire(); -+ schedule_delayed_work(&expires_work, ip_rt_gc_interval); -+} -+ - /* - * Perturbation of rt_genid by a small quantity [1..256] - * Using 8 bits of shuffling ensure we can call rt_cache_invalidate() -@@ -3179,6 +3274,13 @@ static ctl_table ipv4_route_table[] = { - .proc_handler = proc_dointvec_jiffies, - }, - { -+ .procname = "gc_interval", -+ .data = &ip_rt_gc_interval, -+ .maxlen = sizeof(int), -+ .mode = 0644, -+ .proc_handler = proc_dointvec_jiffies, -+ }, -+ { - .procname = "redirect_load", - .data = &ip_rt_redirect_load, - .maxlen = sizeof(int), -@@ -3388,6 +3490,11 @@ int __init ip_rt_init(void) - devinet_init(); - ip_fib_init(); - -+ INIT_DELAYED_WORK_DEFERRABLE(&expires_work, rt_worker_func); -+ expires_ljiffies = jiffies; -+ schedule_delayed_work(&expires_work, -+ net_random() % ip_rt_gc_interval + ip_rt_gc_interval); -+ - if (ip_rt_proc_init()) - printk(KERN_ERR "Unable to create route proc files\n"); - #ifdef CONFIG_XFRM - - --- -To unsubscribe from this list: send the line "unsubscribe linux-kernel" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html -Please read the FAQ at http://www.tux.org/lkml/ - diff --git a/sources b/sources index 487e13e13..d3d58a5d7 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 656f2b85102dc935039e867abd08b880 compat-wireless-3.2-rc6-3.tar.bz2 -13ea1e611a0a580138b8203e6f1353ed patch-3.1.7.bz2 +54fac8e4b0b55201e012ef0337a6cc87 patch-3.1.8.bz2 From 343c19468fb09466f616dd94beb99030fe3a97ec Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sat, 7 Jan 2012 08:05:12 -0500 Subject: [PATCH 212/487] Add iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch back to compat-wireless --- ...-to-switch-to-HT40-if-not-associated.patch | 40 +++++++++++++++++++ kernel.spec | 8 +++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch diff --git a/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch b/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch new file mode 100644 index 000000000..7ded9c83a --- /dev/null +++ b/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch @@ -0,0 +1,40 @@ +From 78feb35b8161acd95c33a703ed6ab6f554d29387 Mon Sep 17 00:00:00 2001 +From: Wey-Yi Guy +Date: Wed, 14 Dec 2011 08:22:36 -0800 +Subject: [PATCH 2/2] iwlwifi: allow to switch to HT40 if not associated + +My previous patch +34a5b4b6af104cf18eb50748509528b9bdbc4036 iwlwifi: do not re-configure +HT40 after associated + +Fix the case of HT40 after association on specified AP, but it break the +association for some APs and cause not able to establish connection. +We need to address HT40 before and after addociation. + +CC: stable@vger.kernel.org #3.0+ +Reported-by: Andrej Gelenberg +Signed-off-by: Wey-Yi Guy +Tested-by: Andrej Gelenberg +Signed-off-by: John W. Linville +--- + drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +index a7a6def..5c7c17c 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +@@ -606,8 +606,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) + if (ctx->ht.enabled) { + /* if HT40 is used, it should not change + * after associated except channel switch */ +- if (iwl_is_associated_ctx(ctx) && +- !ctx->ht.is_40mhz) ++ if (!ctx->ht.is_40mhz || ++ !iwl_is_associated_ctx(ctx)) + iwlagn_config_ht40(conf, ctx); + } else + ctx->ht.is_40mhz = false; +-- +1.7.4.4 + diff --git a/kernel.spec b/kernel.spec index c7d05627a..c188e9810 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -864,6 +864,7 @@ Patch50101: ath9k-fix-max-phy-rate-at-rate-control-init.patch Patch50102: iwlwifi-do-not-set-the-sequence-control-bit-is-not-n.patch Patch50103: iwlwifi-update-SCD-BC-table-for-all-SCD-queues.patch Patch50104: mwifiex-avoid-double-list_del-in-command-cancel-path.patch +Patch50105: iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch #rhbz 771058 Patch22100: msi-irq-sysfs-warning.patch @@ -1670,6 +1671,7 @@ ApplyPatch iwlwifi-do-not-set-the-sequence-control-bit-is-not-n.patch ApplyPatch ath9k-fix-max-phy-rate-at-rate-control-init.patch ApplyPatch mwifiex-avoid-double-list_del-in-command-cancel-path.patch ApplyPatch iwlwifi-tx_sync-only-on-PAN-context.patch +ApplyPatch iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch ApplyPatch iwlwifi-update-SCD-BC-table-for-all-SCD-queues.patch cd .. @@ -2372,6 +2374,10 @@ fi # and build. %changelog +* Sat Jan 07 2012 Josh Boyer 3.1.8-2 +- Add iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch back to + compat-wireless + * Fri Jan 06 2012 Josh Boyer 3.1.8-1 - Disable backports on arches where we don't actually build a kernel (or config) - Linux 3.1.8 From 94fe9fa3125781146ad1abdd560bc4b84a547cd6 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 10 Jan 2012 13:17:37 -0500 Subject: [PATCH 213/487] Add patch to fix ext4 compatibility with ext2 mount option (rhbz 770172) --- ...ort-check-none-nocheck-mount-options.patch | 51 +++++++++++++++++++ kernel.spec | 9 +++- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 ext4-Support-check-none-nocheck-mount-options.patch diff --git a/ext4-Support-check-none-nocheck-mount-options.patch b/ext4-Support-check-none-nocheck-mount-options.patch new file mode 100644 index 000000000..281e4237a --- /dev/null +++ b/ext4-Support-check-none-nocheck-mount-options.patch @@ -0,0 +1,51 @@ +From ea75f7357e3a881bd1bd0db5e483fc6a8681567b Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Tue, 10 Jan 2012 09:39:02 -0500 +Subject: [PATCH] ext4: Support "check=none" "nocheck" mount options + +The ext2/ext3 filesystems supported "check=none" and "nocheck" as mount options +even though that was already the default behavior and it essentially did +nothing. When using ext4 to mount ext2/ext3 filesystems, that mount option +causes the mount to fail. That isn't as backward compatible as it could be, +so add support to ext4 to accept the option. + +Signed-off-by: Josh Boyer +--- + fs/ext4/super.c | 7 ++++++- + 1 files changed, 6 insertions(+), 1 deletions(-) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 3e1329e..5ff09e7 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -1333,7 +1333,7 @@ enum { + Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, + Opt_inode_readahead_blks, Opt_journal_ioprio, + Opt_dioread_nolock, Opt_dioread_lock, +- Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable, ++ Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable, Opt_nocheck, + }; + + static const match_table_t tokens = { +@@ -1409,6 +1409,8 @@ static const match_table_t tokens = { + {Opt_init_itable, "init_itable=%u"}, + {Opt_init_itable, "init_itable"}, + {Opt_noinit_itable, "noinit_itable"}, ++ {Opt_nocheck, "check=none"}, ++ {Opt_nocheck, "nocheck"}, + {Opt_err, NULL}, + }; + +@@ -1905,6 +1907,9 @@ set_qf_format: + case Opt_noinit_itable: + clear_opt(sb, INIT_INODE_TABLE); + break; ++ case Opt_nocheck: ++ /* ext2/ext3 used to "support" this option. Silently eat it */ ++ break; + default: + ext4_msg(sb, KERN_ERR, + "Unrecognized mount option \"%s\" " +-- +1.7.7.5 + diff --git a/kernel.spec b/kernel.spec index c188e9810..fbbcd0333 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -855,6 +855,8 @@ Patch21056: KVM-fix-device-assignment-permissions.patch #rhbz 770233 Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch +Patch21070: ext4-Support-check-none-nocheck-mount-options.patch + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch @@ -1597,6 +1599,8 @@ ApplyPatch KVM-fix-device-assignment-permissions.patch #rhbz 771058 ApplyPatch msi-irq-sysfs-warning.patch +ApplyPatch ext4-Support-check-none-nocheck-mount-options.patch + # END OF PATCH APPLICATIONS %endif @@ -2374,6 +2378,9 @@ fi # and build. %changelog +* Tue Jan 10 2012 Josh Boyer +- Add patch to fix ext4 compatibility with ext2 mount option (rhbz 770172) + * Sat Jan 07 2012 Josh Boyer 3.1.8-2 - Add iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch back to compat-wireless From 61eda14a103d763cfc2b04e6612a84099b9abc95 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 10 Jan 2012 14:08:28 -0500 Subject: [PATCH 214/487] Fix ext4 corrupted bitmap error path (pointed out by Eric Sandeen) --- ...-handling-on-inode-bitmap-corruption.patch | 19 +++++++++++++++++++ kernel.spec | 4 ++++ 2 files changed, 23 insertions(+) create mode 100644 ext4-Fix-error-handling-on-inode-bitmap-corruption.patch diff --git a/ext4-Fix-error-handling-on-inode-bitmap-corruption.patch b/ext4-Fix-error-handling-on-inode-bitmap-corruption.patch new file mode 100644 index 000000000..e22a2b4ff --- /dev/null +++ b/ext4-Fix-error-handling-on-inode-bitmap-corruption.patch @@ -0,0 +1,19 @@ +diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c +index 00beb4f..8fb6844 100644 +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -885,8 +885,12 @@ got: + if (IS_DIRSYNC(inode)) + ext4_handle_sync(handle); + if (insert_inode_locked(inode) < 0) { +- err = -EINVAL; +- goto fail_drop; ++ /* ++ * Likely a bitmap corruption causing inode to be allocated ++ * twice. ++ */ ++ err = -EIO; ++ goto fail; + } + spin_lock(&sbi->s_next_gen_lock); + inode->i_generation = sbi->s_next_generation++; diff --git a/kernel.spec b/kernel.spec index fbbcd0333..416476a47 100644 --- a/kernel.spec +++ b/kernel.spec @@ -856,6 +856,7 @@ Patch21056: KVM-fix-device-assignment-permissions.patch Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch Patch21070: ext4-Support-check-none-nocheck-mount-options.patch +Patch21071: ext4-Fix-error-handling-on-inode-bitmap-corruption.patch # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch @@ -1601,6 +1602,8 @@ ApplyPatch msi-irq-sysfs-warning.patch ApplyPatch ext4-Support-check-none-nocheck-mount-options.patch +ApplyPatch ext4-Fix-error-handling-on-inode-bitmap-corruption.patch + # END OF PATCH APPLICATIONS %endif @@ -2380,6 +2383,7 @@ fi %changelog * Tue Jan 10 2012 Josh Boyer - Add patch to fix ext4 compatibility with ext2 mount option (rhbz 770172) +- Fix ext4 corrupted bitmap error path (pointed out by Eric Sandeen) * Sat Jan 07 2012 Josh Boyer 3.1.8-2 - Add iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch back to From bd6ef13e8ad65fe266b9d337a84d6c4dc9e00a67 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 10 Jan 2012 14:29:39 -0500 Subject: [PATCH 215/487] Update compat-wireless snapshot to version 3.2-1 --- ...ix-max-phy-rate-at-rate-control-init.patch | 37 ------------ ...-to-switch-to-HT40-if-not-associated.patch | 40 ------------- ...et-the-sequence-control-bit-is-not-n.patch | 37 ------------ iwlwifi-tx_sync-only-on-PAN-context.patch | 44 -------------- ...date-SCD-BC-table-for-all-SCD-queues.patch | 36 ----------- kernel.spec | 19 ++---- ...uble-list_del-in-command-cancel-path.patch | 59 ------------------- sources | 2 +- 8 files changed, 5 insertions(+), 269 deletions(-) delete mode 100644 ath9k-fix-max-phy-rate-at-rate-control-init.patch delete mode 100644 iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch delete mode 100644 iwlwifi-do-not-set-the-sequence-control-bit-is-not-n.patch delete mode 100644 iwlwifi-tx_sync-only-on-PAN-context.patch delete mode 100644 iwlwifi-update-SCD-BC-table-for-all-SCD-queues.patch delete mode 100644 mwifiex-avoid-double-list_del-in-command-cancel-path.patch diff --git a/ath9k-fix-max-phy-rate-at-rate-control-init.patch b/ath9k-fix-max-phy-rate-at-rate-control-init.patch deleted file mode 100644 index cb0719b7c..000000000 --- a/ath9k-fix-max-phy-rate-at-rate-control-init.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 10636bc2d60942254bda149827b922c41f4cb4af Mon Sep 17 00:00:00 2001 -From: Rajkumar Manoharan -Date: Sat, 10 Dec 2011 18:59:43 +0530 -Subject: [PATCH 03/10] ath9k: fix max phy rate at rate control init - -The stations always chooses 1Mbps for all trasmitting frames, -whenever the AP is configured to lock the supported rates. -As the max phy rate is always set with the 4th from highest phy rate, -this assumption might be wrong if we have less than that. Fix that. - -Cc: stable@kernel.org -Cc: Paul Stewart -Reported-by: Ajay Gummalla -Signed-off-by: Rajkumar Manoharan -Signed-off-by: John W. Linville ---- - drivers/net/wireless/ath/ath9k/rc.c | 4 +++- - 1 files changed, 3 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c -index 8448281..cc5703b 100644 ---- a/drivers/net/wireless/ath/ath9k/rc.c -+++ b/drivers/net/wireless/ath/ath9k/rc.c -@@ -1270,7 +1270,9 @@ static void ath_rc_init(struct ath_softc *sc, - - ath_rc_priv->max_valid_rate = k; - ath_rc_sort_validrates(rate_table, ath_rc_priv); -- ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4]; -+ ath_rc_priv->rate_max_phy = (k > 4) ? -+ ath_rc_priv->valid_rate_index[k-4] : -+ ath_rc_priv->valid_rate_index[k-1]; - ath_rc_priv->rate_table = rate_table; - - ath_dbg(common, ATH_DBG_CONFIG, --- -1.7.4.4 - diff --git a/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch b/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch deleted file mode 100644 index 7ded9c83a..000000000 --- a/iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 78feb35b8161acd95c33a703ed6ab6f554d29387 Mon Sep 17 00:00:00 2001 -From: Wey-Yi Guy -Date: Wed, 14 Dec 2011 08:22:36 -0800 -Subject: [PATCH 2/2] iwlwifi: allow to switch to HT40 if not associated - -My previous patch -34a5b4b6af104cf18eb50748509528b9bdbc4036 iwlwifi: do not re-configure -HT40 after associated - -Fix the case of HT40 after association on specified AP, but it break the -association for some APs and cause not able to establish connection. -We need to address HT40 before and after addociation. - -CC: stable@vger.kernel.org #3.0+ -Reported-by: Andrej Gelenberg -Signed-off-by: Wey-Yi Guy -Tested-by: Andrej Gelenberg -Signed-off-by: John W. Linville ---- - drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -index a7a6def..5c7c17c 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -@@ -606,8 +606,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) - if (ctx->ht.enabled) { - /* if HT40 is used, it should not change - * after associated except channel switch */ -- if (iwl_is_associated_ctx(ctx) && -- !ctx->ht.is_40mhz) -+ if (!ctx->ht.is_40mhz || -+ !iwl_is_associated_ctx(ctx)) - iwlagn_config_ht40(conf, ctx); - } else - ctx->ht.is_40mhz = false; --- -1.7.4.4 - diff --git a/iwlwifi-do-not-set-the-sequence-control-bit-is-not-n.patch b/iwlwifi-do-not-set-the-sequence-control-bit-is-not-n.patch deleted file mode 100644 index d65d1a790..000000000 --- a/iwlwifi-do-not-set-the-sequence-control-bit-is-not-n.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 123877b80ed62c3b897c53357b622574c023b642 Mon Sep 17 00:00:00 2001 -From: Wey-Yi Guy -Date: Thu, 8 Dec 2011 15:52:00 -0800 -Subject: [PATCH 01/10] iwlwifi: do not set the sequence control bit is not - needed - -Check the IEEE80211_TX_CTL_ASSIGN_SEQ flag from mac80211, then decide how to -set the TX_CMD_FLG_SEQ_CTL_MSK bit. Setting the wrong bit in BAR frame whill -make the firmware to increment the sequence number which is incorrect and -cause unknown behavior. - -CC: stable@vger.kernel.org #3.0+ -Signed-off-by: Wey-Yi Guy -Signed-off-by: John W. Linville ---- - drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 5 ++++- - 1 files changed, 4 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c -index 35a6b71..df1540c 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c -@@ -91,7 +91,10 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, - tx_cmd->tid_tspec = qc[0] & 0xf; - tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; - } else { -- tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; -+ if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) -+ tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; -+ else -+ tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; - } - - iwlagn_tx_cmd_protection(priv, info, fc, &tx_flags); --- -1.7.4.4 - diff --git a/iwlwifi-tx_sync-only-on-PAN-context.patch b/iwlwifi-tx_sync-only-on-PAN-context.patch deleted file mode 100644 index 16086c0fa..000000000 --- a/iwlwifi-tx_sync-only-on-PAN-context.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 81670a491849127cd5f86defd2cd03cef1b08d07 Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Wed, 14 Dec 2011 08:22:35 -0800 -Subject: [PATCH 1/2] iwlwifi: tx_sync only on PAN context - -Ted reported that he couldn't connect to some APs -and bisected it to the tx_sync implementation. -Disable it for the BSS context to fix this issue. - -Reported-by: Ted Ts'o -Signed-off-by: Johannes Berg -Signed-off-by: Wey-Yi Guy -Signed-off-by: John W. Linville ---- - drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ++++++ - 1 files changed, 6 insertions(+), 0 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c -index bacc06c..e0e9a3d 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c -@@ -2850,6 +2850,9 @@ static int iwlagn_mac_tx_sync(struct ieee80211_hw *hw, - int ret; - u8 sta_id; - -+ if (ctx->ctxid != IWL_RXON_CTX_PAN) -+ return 0; -+ - IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->shrd->mutex); - -@@ -2898,6 +2901,9 @@ static void iwlagn_mac_finish_tx_sync(struct ieee80211_hw *hw, - struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; - struct iwl_rxon_context *ctx = vif_priv->ctx; - -+ if (ctx->ctxid != IWL_RXON_CTX_PAN) -+ return; -+ - IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->shrd->mutex); - --- -1.7.4.4 - diff --git a/iwlwifi-update-SCD-BC-table-for-all-SCD-queues.patch b/iwlwifi-update-SCD-BC-table-for-all-SCD-queues.patch deleted file mode 100644 index f25d6e043..000000000 --- a/iwlwifi-update-SCD-BC-table-for-all-SCD-queues.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 96f1f05af76b601ab21a7dc603ae0a1cea4efc3d Mon Sep 17 00:00:00 2001 -From: Emmanuel Grumbach -Date: Fri, 16 Dec 2011 07:53:18 -0800 -Subject: [PATCH 10/10] iwlwifi: update SCD BC table for all SCD queues - -Since we configure all the queues as CHAINABLE, we need to update the -byte count for all the queues, not only the AGGREGATABLE ones. - -Not doing so can confuse the SCD and make the fw assert. - -Cc: stable@vger.kernel.org -Signed-off-by: Emmanuel Grumbach -Signed-off-by: Wey-Yi Guy -Signed-off-by: John W. Linville ---- - drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 4 +--- - 1 files changed, 1 insertions(+), 3 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c -index ce91898..5f17ab8 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c -+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c -@@ -1197,9 +1197,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, - iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); - - /* Set up entry for this TFD in Tx byte-count array */ -- if (is_agg) -- iwl_trans_txq_update_byte_cnt_tbl(trans, txq, -- le16_to_cpu(tx_cmd->len)); -+ iwl_trans_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len)); - - dma_sync_single_for_device(bus(trans)->dev, txcmd_phys, firstlen, - DMA_BIDIRECTIONAL); --- -1.7.4.4 - diff --git a/kernel.spec b/kernel.spec index 416476a47..9624022a8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -205,7 +205,7 @@ Summary: The Linux kernel %define kversion 3.%{base_sublevel} # The compat-wireless version -%define cwversion 3.2-rc6-3 +%define cwversion 3.2-1 ####################################################################### # If cwversion is less than kversion, make sure with_backports is @@ -862,12 +862,6 @@ Patch21071: ext4-Fix-error-handling-on-inode-bitmap-corruption.patch Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch Patch50002: compat-wireless-pr_fmt-warning-avoidance.patch -Patch50100: iwlwifi-tx_sync-only-on-PAN-context.patch -Patch50101: ath9k-fix-max-phy-rate-at-rate-control-init.patch -Patch50102: iwlwifi-do-not-set-the-sequence-control-bit-is-not-n.patch -Patch50103: iwlwifi-update-SCD-BC-table-for-all-SCD-queues.patch -Patch50104: mwifiex-avoid-double-list_del-in-command-cancel-path.patch -Patch50105: iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch #rhbz 771058 Patch22100: msi-irq-sysfs-warning.patch @@ -1673,14 +1667,6 @@ ApplyPatch compat-wireless-pr_fmt-warning-avoidance.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch -# Apply some iwlwifi regression fixes not in the 3.2-rc6 wireless snapshot -ApplyPatch iwlwifi-do-not-set-the-sequence-control-bit-is-not-n.patch -ApplyPatch ath9k-fix-max-phy-rate-at-rate-control-init.patch -ApplyPatch mwifiex-avoid-double-list_del-in-command-cancel-path.patch -ApplyPatch iwlwifi-tx_sync-only-on-PAN-context.patch -ApplyPatch iwlwifi-allow-to-switch-to-HT40-if-not-associated.patch -ApplyPatch iwlwifi-update-SCD-BC-table-for-all-SCD-queues.patch - cd .. %endif @@ -2381,6 +2367,9 @@ fi # and build. %changelog +* Tue Jan 10 2012 John W. Linville +- Update compat-wireless snapshot to version 3.2-1 + * Tue Jan 10 2012 Josh Boyer - Add patch to fix ext4 compatibility with ext2 mount option (rhbz 770172) - Fix ext4 corrupted bitmap error path (pointed out by Eric Sandeen) diff --git a/mwifiex-avoid-double-list_del-in-command-cancel-path.patch b/mwifiex-avoid-double-list_del-in-command-cancel-path.patch deleted file mode 100644 index 90b695723..000000000 --- a/mwifiex-avoid-double-list_del-in-command-cancel-path.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 51e708c1049e721b9c5c48d026bc97ca8497d39a Mon Sep 17 00:00:00 2001 -From: Yogesh Ashok Powar -Date: Tue, 13 Dec 2011 20:43:16 -0800 -Subject: [PATCH 04/10] mwifiex: avoid double list_del in command cancel path - -Command cancel path cancels the current command and moves -it to free command queue. While doing that it deletes the -command entry from the pending list. This is not correct -as the entry has been already deleted from the pending -list at 'mwifiex_exec_next_cmd'. Fixing it. - -Also making sure the stale command pointer is cleaned and -unaccessible for later use. - -Signed-off-by: Yogesh Ashok Powar -Signed-off-by: Bing Zhao -Signed-off-by: John W. Linville ---- - drivers/net/wireless/mwifiex/cmdevt.c | 9 ++------- - 1 files changed, 2 insertions(+), 7 deletions(-) - -diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c -index ac27815..6e0a3ea 100644 ---- a/drivers/net/wireless/mwifiex/cmdevt.c -+++ b/drivers/net/wireless/mwifiex/cmdevt.c -@@ -939,7 +939,6 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) - { - struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; - unsigned long cmd_flags; -- unsigned long cmd_pending_q_flags; - unsigned long scan_pending_q_flags; - uint16_t cancel_scan_cmd = false; - -@@ -949,12 +948,9 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) - cmd_node = adapter->curr_cmd; - cmd_node->wait_q_enabled = false; - cmd_node->cmd_flag |= CMD_F_CANCELED; -- spin_lock_irqsave(&adapter->cmd_pending_q_lock, -- cmd_pending_q_flags); -- list_del(&cmd_node->list); -- spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, -- cmd_pending_q_flags); - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); -+ mwifiex_complete_cmd(adapter, adapter->curr_cmd); -+ adapter->curr_cmd = NULL; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - } - -@@ -981,7 +977,6 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - } - adapter->cmd_wait_q.status = -1; -- mwifiex_complete_cmd(adapter, adapter->curr_cmd); - } - - /* --- -1.7.4.4 - diff --git a/sources b/sources index d3d58a5d7..41792bfcb 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 -656f2b85102dc935039e867abd08b880 compat-wireless-3.2-rc6-3.tar.bz2 54fac8e4b0b55201e012ef0337a6cc87 patch-3.1.8.bz2 +204381bc537b689edcb15df0efed6467 compat-wireless-3.2-1.tar.bz2 From 7829934f47724d7d3b0b1be3603ea6c7bf9f08f8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 11 Jan 2012 11:12:31 -0500 Subject: [PATCH 216/487] Patch from Stanislaw Gruszka to fix NULL ptr deref in mac80211 (rhbz 769766) --- kernel.spec | 10 +++- ...y-NULL-ptr-deref-in-promiscuous-mode.patch | 47 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch diff --git a/kernel.spec b/kernel.spec index 9624022a8..5f46d6fee 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -858,6 +858,9 @@ Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch Patch21070: ext4-Support-check-none-nocheck-mount-options.patch Patch21071: ext4-Fix-error-handling-on-inode-bitmap-corruption.patch +#rhbz 769766 +Patch21072: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch @@ -1598,6 +1601,8 @@ ApplyPatch ext4-Support-check-none-nocheck-mount-options.patch ApplyPatch ext4-Fix-error-handling-on-inode-bitmap-corruption.patch +ApplyPatch mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch + # END OF PATCH APPLICATIONS %endif @@ -2367,6 +2372,9 @@ fi # and build. %changelog +* Wed Jan 11 2012 Josh Boyer +- Patch from Stanislaw Gruszka to fix NULL ptr deref in mac80211 (rhbz 769766) + * Tue Jan 10 2012 John W. Linville - Update compat-wireless snapshot to version 3.2-1 diff --git a/mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch b/mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch new file mode 100644 index 000000000..abacee637 --- /dev/null +++ b/mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch @@ -0,0 +1,47 @@ +Since: + +commit 816c04fe7ef01dd9649f5ccfe796474db8708be5 +Author: Christian Lamparter +Date: Sat Apr 30 15:24:30 2011 +0200 + + mac80211: consolidate MIC failure report handling + +is possible to that we dereference rx->key == NULL when driver set +RX_FLAG_MMIC_STRIPPED and not RX_FLAG_IV_STRIPPED and we are in +promiscuous mode. This happen with rt73usb and rt61pci at least. + +Before the commit we always check rx->key against NULL, so I assume +fix should be done in mac80211 (also mic_fail path has similar check). + +References: +https://bugzilla.redhat.com/show_bug.cgi?id=769766 +http://rt2x00.serialmonkey.com/pipermail/users_rt2x00.serialmonkey.com/2012-January/004395.html + +Cc: stable@vger.kernel.org # 3.0+ +Reported-by: Stuart D Gathman +Reported-by: Kai Wohlfahrt +Signed-off-by: Stanislaw Gruszka +--- + net/mac80211/wpa.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c +index 93aab07..422b798 100644 +--- a/net/mac80211/wpa.c ++++ b/net/mac80211/wpa.c +@@ -106,7 +106,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) + if (status->flag & RX_FLAG_MMIC_ERROR) + goto mic_fail; + +- if (!(status->flag & RX_FLAG_IV_STRIPPED)) ++ if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key) + goto update_iv; + + return RX_CONTINUE; +-- +1.7.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file From 8c9ba0738b2060076146a7a3022356dca27111df Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 13 Jan 2012 11:09:52 -0500 Subject: [PATCH 217/487] Fix CVE-2012-0045 (rhbz 773392) and update to Linux 3.1.9 --- ...truct-x86_emulate_ops-with-get_cpuid.patch | 78 ++++++++++ ...-missing-checks-in-syscall-emulation.patch | 144 ++++++++++++++++++ kernel.spec | 17 ++- sources | 2 +- 4 files changed, 238 insertions(+), 3 deletions(-) create mode 100644 KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch create mode 100644 KVM-x86-fix-missing-checks-in-syscall-emulation.patch diff --git a/KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch b/KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch new file mode 100644 index 000000000..f9dbaa014 --- /dev/null +++ b/KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch @@ -0,0 +1,78 @@ +From 0769c5de24621141c953fbe1f943582d37cb4244 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stephan=20B=C3=A4rwolf?= +Date: Thu, 12 Jan 2012 16:43:03 +0100 +Subject: [PATCH 1/2] KVM: x86: extend "struct x86_emulate_ops" with + "get_cpuid" + +In order to be able to proceed checks on CPU-specific properties +within the emulator, function "get_cpuid" is introduced. +With "get_cpuid" it is possible to virtually call the guests +"cpuid"-opcode without changing the VM's context. + +[mtosatti: cleanup/beautify code] + +Signed-off-by: Stephan Baerwolf +Signed-off-by: Marcelo Tosatti +--- + arch/x86/include/asm/kvm_emulate.h | 3 +++ + arch/x86/kvm/x86.c | 23 +++++++++++++++++++++++ + 2 files changed, 26 insertions(+), 0 deletions(-) + +diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h +index ab4092e..c8b2868 100644 +--- a/arch/x86/include/asm/kvm_emulate.h ++++ b/arch/x86/include/asm/kvm_emulate.h +@@ -190,6 +190,9 @@ struct x86_emulate_ops { + int (*intercept)(struct x86_emulate_ctxt *ctxt, + struct x86_instruction_info *info, + enum x86_intercept_stage stage); ++ ++ bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt, ++ u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); + }; + + typedef u32 __attribute__((vector_size(16))) sse128_t; +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index f0fa3fb..c95ca2d 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -4205,6 +4205,28 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt, + return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage); + } + ++static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt, ++ u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) ++{ ++ struct kvm_cpuid_entry2 *cpuid = NULL; ++ ++ if (eax && ecx) ++ cpuid = kvm_find_cpuid_entry(emul_to_vcpu(ctxt), ++ *eax, *ecx); ++ ++ if (cpuid) { ++ *eax = cpuid->eax; ++ *ecx = cpuid->ecx; ++ if (ebx) ++ *ebx = cpuid->ebx; ++ if (edx) ++ *edx = cpuid->edx; ++ return true; ++ } ++ ++ return false; ++} ++ + static struct x86_emulate_ops emulate_ops = { + .read_std = kvm_read_guest_virt_system, + .write_std = kvm_write_guest_virt_system, +@@ -4236,6 +4258,7 @@ static struct x86_emulate_ops emulate_ops = { + .get_fpu = emulator_get_fpu, + .put_fpu = emulator_put_fpu, + .intercept = emulator_intercept, ++ .get_cpuid = emulator_get_cpuid, + }; + + static void cache_all_regs(struct kvm_vcpu *vcpu) +-- +1.7.7.5 + diff --git a/KVM-x86-fix-missing-checks-in-syscall-emulation.patch b/KVM-x86-fix-missing-checks-in-syscall-emulation.patch new file mode 100644 index 000000000..933a13431 --- /dev/null +++ b/KVM-x86-fix-missing-checks-in-syscall-emulation.patch @@ -0,0 +1,144 @@ +From e28ba7bb020f07193bc000453c8775e9d2c0dda7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stephan=20B=C3=A4rwolf?= +Date: Thu, 12 Jan 2012 16:43:04 +0100 +Subject: [PATCH 2/2] KVM: x86: fix missing checks in syscall emulation + +On hosts without this patch, 32bit guests will crash (and 64bit guests +may behave in a wrong way) for example by simply executing following +nasm-demo-application: + + [bits 32] + global _start + SECTION .text + _start: syscall + +(I tested it with winxp and linux - both always crashed) + + Disassembly of section .text: + + 00000000 <_start>: + 0: 0f 05 syscall + +The reason seems a missing "invalid opcode"-trap (int6) for the +syscall opcode "0f05", which is not available on Intel CPUs +within non-longmodes, as also on some AMD CPUs within legacy-mode. +(depending on CPU vendor, MSR_EFER and cpuid) + +Because previous mentioned OSs may not engage corresponding +syscall target-registers (STAR, LSTAR, CSTAR), they remain +NULL and (non trapping) syscalls are leading to multiple +faults and finally crashs. + +Depending on the architecture (AMD or Intel) pretended by +guests, various checks according to vendor's documentation +are implemented to overcome the current issue and behave +like the CPUs physical counterparts. + +[mtosatti: cleanup/beautify code] + +Signed-off-by: Stephan Baerwolf +Signed-off-by: Marcelo Tosatti +--- + arch/x86/include/asm/kvm_emulate.h | 13 +++++++++ + arch/x86/kvm/emulate.c | 51 ++++++++++++++++++++++++++++++++++++ + 2 files changed, 64 insertions(+), 0 deletions(-) + +diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h +index c8b2868..7b9cfc4 100644 +--- a/arch/x86/include/asm/kvm_emulate.h ++++ b/arch/x86/include/asm/kvm_emulate.h +@@ -301,6 +301,19 @@ struct x86_emulate_ctxt { + #define X86EMUL_MODE_PROT (X86EMUL_MODE_PROT16|X86EMUL_MODE_PROT32| \ + X86EMUL_MODE_PROT64) + ++/* CPUID vendors */ ++#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx 0x68747541 ++#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx 0x444d4163 ++#define X86EMUL_CPUID_VENDOR_AuthenticAMD_edx 0x69746e65 ++ ++#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx 0x69444d41 ++#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx 0x21726574 ++#define X86EMUL_CPUID_VENDOR_AMDisbetterI_edx 0x74656273 ++ ++#define X86EMUL_CPUID_VENDOR_GenuineIntel_ebx 0x756e6547 ++#define X86EMUL_CPUID_VENDOR_GenuineIntel_ecx 0x6c65746e ++#define X86EMUL_CPUID_VENDOR_GenuineIntel_edx 0x49656e69 ++ + enum x86_intercept_stage { + X86_ICTP_NONE = 0, /* Allow zero-init to not match anything */ + X86_ICPT_PRE_EXCEPT, +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index 05a562b..0982507 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -1891,6 +1891,51 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt, + ss->p = 1; + } + ++static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt) ++{ ++ struct x86_emulate_ops *ops = ctxt->ops; ++ u32 eax, ebx, ecx, edx; ++ ++ /* ++ * syscall should always be enabled in longmode - so only become ++ * vendor specific (cpuid) if other modes are active... ++ */ ++ if (ctxt->mode == X86EMUL_MODE_PROT64) ++ return true; ++ ++ eax = 0x00000000; ++ ecx = 0x00000000; ++ if (ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)) { ++ /* ++ * Intel ("GenuineIntel") ++ * remark: Intel CPUs only support "syscall" in 64bit ++ * longmode. Also an 64bit guest with a ++ * 32bit compat-app running will #UD !! While this ++ * behaviour can be fixed (by emulating) into AMD ++ * response - CPUs of AMD can't behave like Intel. ++ */ ++ if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx && ++ ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx && ++ edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx) ++ return false; ++ ++ /* AMD ("AuthenticAMD") */ ++ if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx && ++ ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx && ++ edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx) ++ return true; ++ ++ /* AMD ("AMDisbetter!") */ ++ if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx && ++ ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx && ++ edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx) ++ return true; ++ } ++ ++ /* default: (not Intel, not AMD), apply Intel's stricter rules... */ ++ return false; ++} ++ + static int em_syscall(struct x86_emulate_ctxt *ctxt) + { + struct x86_emulate_ops *ops = ctxt->ops; +@@ -1904,9 +1949,15 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt) + ctxt->mode == X86EMUL_MODE_VM86) + return emulate_ud(ctxt); + ++ if (!(em_syscall_is_enabled(ctxt))) ++ return emulate_ud(ctxt); ++ + ops->get_msr(ctxt, MSR_EFER, &efer); + setup_syscalls_segments(ctxt, &cs, &ss); + ++ if (!(efer & EFER_SCE)) ++ return emulate_ud(ctxt); ++ + ops->get_msr(ctxt, MSR_STAR, &msr_data); + msr_data >>= 32; + cs_sel = (u16)(msr_data & 0xfffc); +-- +1.7.7.5 + diff --git a/kernel.spec b/kernel.spec index 5f46d6fee..97deee0d4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 8 +%define stable_update 9 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -861,6 +861,11 @@ Patch21071: ext4-Fix-error-handling-on-inode-bitmap-corruption.patch #rhbz 769766 Patch21072: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch +#rhbz 773392 +Patch21073: KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch +Patch21074: KVM-x86-fix-missing-checks-in-syscall-emulation.patch + + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch @@ -1603,6 +1608,10 @@ ApplyPatch ext4-Fix-error-handling-on-inode-bitmap-corruption.patch ApplyPatch mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch +#rhbz 773392 +ApplyPatch KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch +ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch + # END OF PATCH APPLICATIONS %endif @@ -2372,6 +2381,10 @@ fi # and build. %changelog +* Fri Jan 13 2012 Josh Boyer 3.1.9-1 +- Linux 3.1.9 +- CVE-2012-0045 kvm: syscall instruction induced guest panic (rhbz 773392) + * Wed Jan 11 2012 Josh Boyer - Patch from Stanislaw Gruszka to fix NULL ptr deref in mac80211 (rhbz 769766) diff --git a/sources b/sources index 41792bfcb..af7cbe4e2 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 -54fac8e4b0b55201e012ef0337a6cc87 patch-3.1.8.bz2 204381bc537b689edcb15df0efed6467 compat-wireless-3.2-1.tar.bz2 +fae6176f187628bcc5b330cdadc60f9e patch-3.1.9.bz2 From 76da9b0851896424f1a3792cc8fbb04994ad8cd9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 13 Jan 2012 11:53:59 -0500 Subject: [PATCH 218/487] Fix verbose logging messages in the rtl8192cu driver (rhbz 728740) --- ...8192cu-Fix-WARNING-on-suspend-resume.patch | 163 ++++++++++++++++++ kernel.spec | 13 +- rtl8192cu-Fix-WARNING-on-suspend-resume.patch | 163 ++++++++++++++++++ 3 files changed, 338 insertions(+), 1 deletion(-) create mode 100644 compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch create mode 100644 rtl8192cu-Fix-WARNING-on-suspend-resume.patch diff --git a/compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch b/compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch new file mode 100644 index 000000000..bdc8a5492 --- /dev/null +++ b/compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch @@ -0,0 +1,163 @@ +A recent LKML thread (http://lkml.indiana.edu/hypermail/linux/kernel/1112.3/00965.html) +discusses warnings that occur during a suspend/resume cycle. The driver +attempts to read the firmware file before userspace is ready, leading to the +following warning: + +WARNING: at drivers/base/firmware_class.c:537 _request_firmware+0x3f6/0x420() + +For rtl8192cu, the problem is fixed by storing the firmware in a global buffer +rather than one allocated per device. The usage count is increased when +suspending and decreased when resuming. This way, the firmware is retained +through a suspend/resume cycle, and does not have to be reread. + +This patch should fix the bug reported in +https://bugzilla.redhat.com/show_bug.cgi?id=771002. + +Note: This patch also touches rtl8192ce as the "firmware" loaded message +is now printed in the wrong place. +Note: This patch also touches rtl8192ce as the "firmware" loaded message +is now printed in the wrong place. + +Reported-by: Mohammed Arafa +Reported-by: Dave Jones +Signed-off-by: Larry Finger +Cc: Linus Torvalds +Cc: Stable + +--- + drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 1 - + drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 1 + + drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 58 +++++++++++++++++---- + 3 files changed, 49 insertions(+), 11 deletions(-) + +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:07:58.830625006 -0500 ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:08:06.825439927 -0500 +@@ -227,7 +227,6 @@ int rtl92c_download_fw(struct ieee80211_ + u32 fwsize; + enum version_8192c version = rtlhal->version; + +- pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); + if (!rtlhal->pfirmware) + return 1; + +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +@@ -186,6 +186,7 @@ int rtl92c_init_sw_vars(struct ieee80211 + memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); + rtlpriv->rtlhal.fwsize = firmware->size; + release_firmware(firmware); ++ pr_info("rtl8192ce: Loaded firmware file %s\n", rtlpriv->cfg->fw_name); + + return 0; + } +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +@@ -43,6 +43,8 @@ + #include "hw.h" + #include + #include ++#include ++#include + + MODULE_AUTHOR("Georgia "); + MODULE_AUTHOR("Ziv Huang "); +@@ -51,6 +53,10 @@ MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless"); + MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); + ++static char *rtl8192cu_firmware; /* pointer to firmware */ ++static int firmware_size; ++static atomic_t usage_count; ++ + static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) + { + struct rtl_priv *rtlpriv = rtl_priv(hw); +@@ -62,12 +68,21 @@ static int rtl92cu_init_sw_vars(struct i + rtlpriv->dm.disable_framebursting = false; + rtlpriv->dm.thermalvalue = 0; + rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; +- rtlpriv->rtlhal.pfirmware = vmalloc(0x4000); +- if (!rtlpriv->rtlhal.pfirmware) { ++ ++ if (rtl8192cu_firmware) { ++ /* firmware already loaded - true for suspend/resume ++ * and multiple instances of the device */ ++ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware; ++ rtlpriv->rtlhal.fwsize = firmware_size; ++ return 0; ++ } ++ rtl8192cu_firmware = vzalloc(0x4000); ++ if (!rtl8192cu_firmware) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Can't alloc buffer for fw.\n")); + return 1; + } ++ + /* request fw */ + err = request_firmware(&firmware, rtlpriv->cfg->fw_name, + rtlpriv->io.dev); +@@ -82,9 +97,14 @@ static int rtl92cu_init_sw_vars(struct i + release_firmware(firmware); + return 1; + } +- memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); ++ pr_info("rtl8192cu: Loaded firmware from file %s\n", ++ rtlpriv->cfg->fw_name); ++ memcpy(rtl8192cu_firmware, firmware->data, firmware->size); ++ firmware_size = firmware->size; + rtlpriv->rtlhal.fwsize = firmware->size; ++ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware; + release_firmware(firmware); ++ atomic_inc(&usage_count); + + return 0; + } +@@ -93,12 +113,30 @@ static void rtl92cu_deinit_sw_vars(struc + { + struct rtl_priv *rtlpriv = rtl_priv(hw); + +- if (rtlpriv->rtlhal.pfirmware) { +- vfree(rtlpriv->rtlhal.pfirmware); ++ atomic_dec(&usage_count); ++ if (!atomic_read(&usage_count) && rtlpriv->rtlhal.pfirmware) { ++ vfree(rtl8192cu_firmware); ++ rtl8192cu_firmware = NULL; + rtlpriv->rtlhal.pfirmware = NULL; + } + } + ++#ifdef CONFIG_PM_SLEEP ++static int rtl8192cu_usb_suspend(struct usb_interface *pusb_intf, ++ pm_message_t message) ++{ ++ /* Increase usage_count to Save loaded fw across suspend/resume */ ++ atomic_inc(&usage_count); ++ return 0; ++} ++ ++static int rtl8192cu_usb_resume(struct usb_interface *pusb_intf) ++{ ++ atomic_dec(&usage_count); /* after resume, decrease usage count */ ++ return 0; ++} ++#endif ++ + static struct rtl_hal_ops rtl8192cu_hal_ops = { + .init_sw_vars = rtl92cu_init_sw_vars, + .deinit_sw_vars = rtl92cu_deinit_sw_vars, +@@ -374,11 +412,10 @@ static struct usb_driver rtl8192cu_drive + .disconnect = rtl_usb_disconnect, + .id_table = rtl8192c_usb_ids, + +-#ifdef CONFIG_PM +- /* .suspend = rtl_usb_suspend, */ +- /* .resume = rtl_usb_resume, */ +- /* .reset_resume = rtl8192c_resume, */ +-#endif /* CONFIG_PM */ ++#ifdef CONFIG_PM_SLEEP ++ .suspend = rtl8192cu_usb_suspend, ++ .resume = rtl8192cu_usb_resume, ++#endif /* CONFIG_PM_SLEEP */ + #ifdef CONFIG_AUTOSUSPEND + .supports_autosuspend = 1, + #endif diff --git a/kernel.spec b/kernel.spec index 97deee0d4..d7e10b019 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -870,10 +870,14 @@ Patch21074: KVM-x86-fix-missing-checks-in-syscall-emulation.patch Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch Patch50002: compat-wireless-pr_fmt-warning-avoidance.patch +Patch50003: compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch #rhbz 771058 Patch22100: msi-irq-sysfs-warning.patch +#rhbz 728740 +Patch21076: rtl8192cu-Fix-WARNING-on-suspend-resume.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1612,6 +1616,9 @@ ApplyPatch mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch ApplyPatch KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch +#rhbz 728740 +ApplyPatch rtl8192cu-Fix-WARNING-on-suspend-resume.patch + # END OF PATCH APPLICATIONS %endif @@ -1677,6 +1684,7 @@ cd compat-wireless-%{cwversion} ApplyPatch compat-wireless-config-fixups.patch ApplyPatch compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch ApplyPatch compat-wireless-pr_fmt-warning-avoidance.patch +ApplyPatch compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch @@ -2381,6 +2389,9 @@ fi # and build. %changelog +* Fri Jan 13 2012 Josh Boyer +- Fix verbose logging messages in the rtl8192cu driver (rhbz 728740) + * Fri Jan 13 2012 Josh Boyer 3.1.9-1 - Linux 3.1.9 - CVE-2012-0045 kvm: syscall instruction induced guest panic (rhbz 773392) diff --git a/rtl8192cu-Fix-WARNING-on-suspend-resume.patch b/rtl8192cu-Fix-WARNING-on-suspend-resume.patch new file mode 100644 index 000000000..bdc8a5492 --- /dev/null +++ b/rtl8192cu-Fix-WARNING-on-suspend-resume.patch @@ -0,0 +1,163 @@ +A recent LKML thread (http://lkml.indiana.edu/hypermail/linux/kernel/1112.3/00965.html) +discusses warnings that occur during a suspend/resume cycle. The driver +attempts to read the firmware file before userspace is ready, leading to the +following warning: + +WARNING: at drivers/base/firmware_class.c:537 _request_firmware+0x3f6/0x420() + +For rtl8192cu, the problem is fixed by storing the firmware in a global buffer +rather than one allocated per device. The usage count is increased when +suspending and decreased when resuming. This way, the firmware is retained +through a suspend/resume cycle, and does not have to be reread. + +This patch should fix the bug reported in +https://bugzilla.redhat.com/show_bug.cgi?id=771002. + +Note: This patch also touches rtl8192ce as the "firmware" loaded message +is now printed in the wrong place. +Note: This patch also touches rtl8192ce as the "firmware" loaded message +is now printed in the wrong place. + +Reported-by: Mohammed Arafa +Reported-by: Dave Jones +Signed-off-by: Larry Finger +Cc: Linus Torvalds +Cc: Stable + +--- + drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 1 - + drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 1 + + drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 58 +++++++++++++++++---- + 3 files changed, 49 insertions(+), 11 deletions(-) + +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:07:58.830625006 -0500 ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:08:06.825439927 -0500 +@@ -227,7 +227,6 @@ int rtl92c_download_fw(struct ieee80211_ + u32 fwsize; + enum version_8192c version = rtlhal->version; + +- pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); + if (!rtlhal->pfirmware) + return 1; + +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +@@ -186,6 +186,7 @@ int rtl92c_init_sw_vars(struct ieee80211 + memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); + rtlpriv->rtlhal.fwsize = firmware->size; + release_firmware(firmware); ++ pr_info("rtl8192ce: Loaded firmware file %s\n", rtlpriv->cfg->fw_name); + + return 0; + } +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +@@ -43,6 +43,8 @@ + #include "hw.h" + #include + #include ++#include ++#include + + MODULE_AUTHOR("Georgia "); + MODULE_AUTHOR("Ziv Huang "); +@@ -51,6 +53,10 @@ MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless"); + MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); + ++static char *rtl8192cu_firmware; /* pointer to firmware */ ++static int firmware_size; ++static atomic_t usage_count; ++ + static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) + { + struct rtl_priv *rtlpriv = rtl_priv(hw); +@@ -62,12 +68,21 @@ static int rtl92cu_init_sw_vars(struct i + rtlpriv->dm.disable_framebursting = false; + rtlpriv->dm.thermalvalue = 0; + rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; +- rtlpriv->rtlhal.pfirmware = vmalloc(0x4000); +- if (!rtlpriv->rtlhal.pfirmware) { ++ ++ if (rtl8192cu_firmware) { ++ /* firmware already loaded - true for suspend/resume ++ * and multiple instances of the device */ ++ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware; ++ rtlpriv->rtlhal.fwsize = firmware_size; ++ return 0; ++ } ++ rtl8192cu_firmware = vzalloc(0x4000); ++ if (!rtl8192cu_firmware) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Can't alloc buffer for fw.\n")); + return 1; + } ++ + /* request fw */ + err = request_firmware(&firmware, rtlpriv->cfg->fw_name, + rtlpriv->io.dev); +@@ -82,9 +97,14 @@ static int rtl92cu_init_sw_vars(struct i + release_firmware(firmware); + return 1; + } +- memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); ++ pr_info("rtl8192cu: Loaded firmware from file %s\n", ++ rtlpriv->cfg->fw_name); ++ memcpy(rtl8192cu_firmware, firmware->data, firmware->size); ++ firmware_size = firmware->size; + rtlpriv->rtlhal.fwsize = firmware->size; ++ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware; + release_firmware(firmware); ++ atomic_inc(&usage_count); + + return 0; + } +@@ -93,12 +113,30 @@ static void rtl92cu_deinit_sw_vars(struc + { + struct rtl_priv *rtlpriv = rtl_priv(hw); + +- if (rtlpriv->rtlhal.pfirmware) { +- vfree(rtlpriv->rtlhal.pfirmware); ++ atomic_dec(&usage_count); ++ if (!atomic_read(&usage_count) && rtlpriv->rtlhal.pfirmware) { ++ vfree(rtl8192cu_firmware); ++ rtl8192cu_firmware = NULL; + rtlpriv->rtlhal.pfirmware = NULL; + } + } + ++#ifdef CONFIG_PM_SLEEP ++static int rtl8192cu_usb_suspend(struct usb_interface *pusb_intf, ++ pm_message_t message) ++{ ++ /* Increase usage_count to Save loaded fw across suspend/resume */ ++ atomic_inc(&usage_count); ++ return 0; ++} ++ ++static int rtl8192cu_usb_resume(struct usb_interface *pusb_intf) ++{ ++ atomic_dec(&usage_count); /* after resume, decrease usage count */ ++ return 0; ++} ++#endif ++ + static struct rtl_hal_ops rtl8192cu_hal_ops = { + .init_sw_vars = rtl92cu_init_sw_vars, + .deinit_sw_vars = rtl92cu_deinit_sw_vars, +@@ -374,11 +412,10 @@ static struct usb_driver rtl8192cu_drive + .disconnect = rtl_usb_disconnect, + .id_table = rtl8192c_usb_ids, + +-#ifdef CONFIG_PM +- /* .suspend = rtl_usb_suspend, */ +- /* .resume = rtl_usb_resume, */ +- /* .reset_resume = rtl8192c_resume, */ +-#endif /* CONFIG_PM */ ++#ifdef CONFIG_PM_SLEEP ++ .suspend = rtl8192cu_usb_suspend, ++ .resume = rtl8192cu_usb_resume, ++#endif /* CONFIG_PM_SLEEP */ + #ifdef CONFIG_AUTOSUSPEND + .supports_autosuspend = 1, + #endif From b23da04d3eff871bf940a8b2366a7b521f073d66 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 13 Jan 2012 13:45:20 -0500 Subject: [PATCH 219/487] Fix rtl8192cu-Fix-WARNING-on-suspend-resume.patch so it actually applies --- rtl8192cu-Fix-WARNING-on-suspend-resume.patch | 54 ++++++++++++------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/rtl8192cu-Fix-WARNING-on-suspend-resume.patch b/rtl8192cu-Fix-WARNING-on-suspend-resume.patch index bdc8a5492..e784b1632 100644 --- a/rtl8192cu-Fix-WARNING-on-suspend-resume.patch +++ b/rtl8192cu-Fix-WARNING-on-suspend-resume.patch @@ -1,3 +1,8 @@ +From e234ca17f2d5ce23606fceef2df6c02f8555547e Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Wed, 11 Jan 2012 13:35:33 -0500 +Subject: [PATCH] rtl8192cu: Fix WARNING on suspend/resume + A recent LKML thread (http://lkml.indiana.edu/hypermail/linux/kernel/1112.3/00965.html) discusses warnings that occur during a suspend/resume cycle. The driver attempts to read the firmware file before userspace is ready, leading to the @@ -13,8 +18,6 @@ through a suspend/resume cycle, and does not have to be reread. This patch should fix the bug reported in https://bugzilla.redhat.com/show_bug.cgi?id=771002. -Note: This patch also touches rtl8192ce as the "firmware" loaded message -is now printed in the wrong place. Note: This patch also touches rtl8192ce as the "firmware" loaded message is now printed in the wrong place. @@ -24,25 +27,30 @@ Signed-off-by: Larry Finger Cc: Linus Torvalds Cc: Stable +Backported to Fedora 3.1.x. --- drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 1 - drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 1 + drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 58 +++++++++++++++++---- 3 files changed, 49 insertions(+), 11 deletions(-) ---- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:07:58.830625006 -0500 -+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:08:06.825439927 -0500 -@@ -227,7 +227,6 @@ int rtl92c_download_fw(struct ieee80211_ +diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +index 49a064b..e3c4ac7 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +@@ -226,7 +226,6 @@ int rtl92c_download_fw(struct ieee80211_hw *hw) u32 fwsize; enum version_8192c version = rtlhal->version; - pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); if (!rtlhal->pfirmware) return 1; - ---- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c -+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c -@@ -186,6 +186,7 @@ int rtl92c_init_sw_vars(struct ieee80211 + +diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +index 373dc78..9c3a8f1 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +@@ -171,6 +171,7 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); rtlpriv->rtlhal.fwsize = firmware->size; release_firmware(firmware); @@ -50,18 +58,21 @@ Cc: Stable return 0; } ---- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c -+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c -@@ -43,6 +43,8 @@ +diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +index ef63c0d..f4230dd 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +@@ -42,6 +42,9 @@ + #include "led.h" #include "hw.h" #include - #include +#include +#include ++ MODULE_AUTHOR("Georgia "); MODULE_AUTHOR("Ziv Huang "); -@@ -51,6 +53,10 @@ MODULE_LICENSE("GPL"); +@@ -50,6 +53,10 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless"); MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); @@ -72,10 +83,10 @@ Cc: Stable static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); -@@ -62,12 +68,21 @@ static int rtl92cu_init_sw_vars(struct i - rtlpriv->dm.disable_framebursting = false; +@@ -60,12 +67,21 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) + rtlpriv->dm.dm_flag = 0; + rtlpriv->dm.disable_framebursting = 0; rtlpriv->dm.thermalvalue = 0; - rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; - rtlpriv->rtlhal.pfirmware = vmalloc(0x4000); - if (!rtlpriv->rtlhal.pfirmware) { + @@ -96,7 +107,7 @@ Cc: Stable /* request fw */ err = request_firmware(&firmware, rtlpriv->cfg->fw_name, rtlpriv->io.dev); -@@ -82,9 +97,14 @@ static int rtl92cu_init_sw_vars(struct i +@@ -80,9 +96,14 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) release_firmware(firmware); return 1; } @@ -112,7 +123,7 @@ Cc: Stable return 0; } -@@ -93,12 +113,30 @@ static void rtl92cu_deinit_sw_vars(struc +@@ -91,12 +112,30 @@ static void rtl92cu_deinit_sw_vars(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -145,7 +156,7 @@ Cc: Stable static struct rtl_hal_ops rtl8192cu_hal_ops = { .init_sw_vars = rtl92cu_init_sw_vars, .deinit_sw_vars = rtl92cu_deinit_sw_vars, -@@ -374,11 +412,10 @@ static struct usb_driver rtl8192cu_drive +@@ -338,11 +377,10 @@ static struct usb_driver rtl8192cu_driver = { .disconnect = rtl_usb_disconnect, .id_table = rtl8192c_usb_ids, @@ -161,3 +172,6 @@ Cc: Stable #ifdef CONFIG_AUTOSUSPEND .supports_autosuspend = 1, #endif +-- +1.7.7.5 + From 7c77270a54683b61723fe8d97db3f96e39f5868a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sun, 15 Jan 2012 15:48:57 -0500 Subject: [PATCH 220/487] Avoid packaging symlinks for kernel-doc files (rhbz 767351) --- kernel.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index d7e10b019..fa1364919 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2063,7 +2063,7 @@ man9dir=$RPM_BUILD_ROOT%{_datadir}/man/man9 # copy the source over mkdir -p $docdir -tar -f - --exclude=man --exclude='.*' -c Documentation | tar xf - -C $docdir +tar -h -f - --exclude=man --exclude='.*' -c Documentation | tar xf - -C $docdir # Install man pages for the kernel API. mkdir -p $man9dir @@ -2389,6 +2389,9 @@ fi # and build. %changelog +* Sun Jan 15 2012 Josh Boyer +- Avoid packaging symlinks for kernel-doc files (rhbz 767351) + * Fri Jan 13 2012 Josh Boyer - Fix verbose logging messages in the rtl8192cu driver (rhbz 728740) From dff5d862651236a1c7b8a96a1b64cc8c70abd3b0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sun, 15 Jan 2012 16:23:28 -0500 Subject: [PATCH 221/487] Apply mac80211 NULL ptr deref fix to compat-wireless too (rhbz 769766) --- kernel.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel.spec b/kernel.spec index fa1364919..0b2e30ff2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1685,6 +1685,7 @@ ApplyPatch compat-wireless-config-fixups.patch ApplyPatch compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch ApplyPatch compat-wireless-pr_fmt-warning-avoidance.patch ApplyPatch compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch +ApplyPatch mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch @@ -2391,6 +2392,7 @@ fi %changelog * Sun Jan 15 2012 Josh Boyer - Avoid packaging symlinks for kernel-doc files (rhbz 767351) +- Apply mac80211 NULL ptr deref fix to compat-wireless too (rhbz 769766) * Fri Jan 13 2012 Josh Boyer - Fix verbose logging messages in the rtl8192cu driver (rhbz 728740) From 853134cbcd2e81ccfddf4a869b141e44ecab8c19 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 16 Jan 2012 13:07:54 -0500 Subject: [PATCH 222/487] Re-apply patch to revert mac80211 scan optimizations (rhbz #731365, #773271) --- kernel.spec | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel.spec b/kernel.spec index 0b2e30ff2..727959344 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1687,6 +1687,9 @@ ApplyPatch compat-wireless-pr_fmt-warning-avoidance.patch ApplyPatch compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch ApplyPatch mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch +#rhbz 731365, 773271 +ApplyPatch mac80211_offchannel_rework_revert.patch + # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch @@ -2390,6 +2393,9 @@ fi # and build. %changelog +* Mon Jan 16 2012 John W. Linville +- Re-apply patch to revert mac80211 scan optimizations (rhbz #731365, #773271) + * Sun Jan 15 2012 Josh Boyer - Avoid packaging symlinks for kernel-doc files (rhbz 767351) - Apply mac80211 NULL ptr deref fix to compat-wireless too (rhbz 769766) From 51e3e67b67a92233b5e44f992ad2d3b736366646 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 17 Jan 2012 15:30:50 -0500 Subject: [PATCH 223/487] CVE-2011-4127 possible privilege escalation via SG_IO ioctl (rhbz 769911) --- 01-block-add-and-use-scsi_blk_cmd_ioctl.patch | 166 ++++++++++++++++++ ...passthrough-ioctls-on-partition-devs.patch | 165 +++++++++++++++++ ...wd-ioctls-from-LVs-to-underlying-dev.patch | 91 ++++++++++ kernel.spec | 15 +- 4 files changed, 436 insertions(+), 1 deletion(-) create mode 100644 01-block-add-and-use-scsi_blk_cmd_ioctl.patch create mode 100644 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch create mode 100644 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch diff --git a/01-block-add-and-use-scsi_blk_cmd_ioctl.patch b/01-block-add-and-use-scsi_blk_cmd_ioctl.patch new file mode 100644 index 000000000..fdf4c5039 --- /dev/null +++ b/01-block-add-and-use-scsi_blk_cmd_ioctl.patch @@ -0,0 +1,166 @@ +From 6051b3759d3d4b70d33a7be70ab6b86ed3559224 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 16 Jan 2012 17:12:58 +0100 +Subject: [PATCH 1/3] block: add and use scsi_blk_cmd_ioctl + +Introduce a wrapper around scsi_cmd_ioctl that takes a block device. + +The function will then be enhanced to detect partition block devices +and, in that case, subject the ioctls to whitelisting. + +[ Cherry picked from 6ad62f051ef784a48a6103af289f91b5c472e955 ] + +Cc: stable@kernel.org +Cc: linux-scsi@vger.kernel.org +Cc: Jens Axboe +Cc: James Bottomley +Signed-off-by: Paolo Bonzini +Signed-off-by: Linus Torvalds +--- + block/scsi_ioctl.c | 7 +++++++ + drivers/block/cciss.c | 6 +++--- + drivers/block/ub.c | 3 +-- + drivers/block/virtio_blk.c | 4 ++-- + drivers/cdrom/cdrom.c | 3 +-- + drivers/ide/ide-floppy_ioctl.c | 3 +-- + drivers/scsi/sd.c | 2 +- + include/linux/blkdev.h | 2 ++ + 8 files changed, 18 insertions(+), 12 deletions(-) + +diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c +index 4f4230b..57ac937 100644 +--- a/block/scsi_ioctl.c ++++ b/block/scsi_ioctl.c +@@ -691,6 +691,13 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod + } + EXPORT_SYMBOL(scsi_cmd_ioctl); + ++int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode, ++ unsigned int cmd, void __user *arg) ++{ ++ return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg); ++} ++EXPORT_SYMBOL(scsi_cmd_blk_ioctl); ++ + static int __init blk_scsi_ioctl_init(void) + { + blk_set_cmd_filter_defaults(&blk_default_cmd_filter); +diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c +index c2f9b3e..1dab802 100644 +--- a/drivers/block/cciss.c ++++ b/drivers/block/cciss.c +@@ -1716,7 +1716,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, + case CCISS_BIG_PASSTHRU: + return cciss_bigpassthru(h, argp); + +- /* scsi_cmd_ioctl handles these, below, though some are not */ ++ /* scsi_cmd_blk_ioctl handles these, below, though some are not */ + /* very meaningful for cciss. SG_IO is the main one people want. */ + + case SG_GET_VERSION_NUM: +@@ -1727,9 +1727,9 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, + case SG_EMULATED_HOST: + case SG_IO: + case SCSI_IOCTL_SEND_COMMAND: +- return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp); ++ return scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); + +- /* scsi_cmd_ioctl would normally handle these, below, but */ ++ /* scsi_cmd_blk_ioctl would normally handle these, below, but */ + /* they aren't a good fit for cciss, as CD-ROMs are */ + /* not supported, and we don't have any bus/target/lun */ + /* which we present to the kernel. */ +diff --git a/drivers/block/ub.c b/drivers/block/ub.c +index 0e376d4..7333b9e 100644 +--- a/drivers/block/ub.c ++++ b/drivers/block/ub.c +@@ -1744,12 +1744,11 @@ static int ub_bd_release(struct gendisk *disk, fmode_t mode) + static int ub_bd_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) + { +- struct gendisk *disk = bdev->bd_disk; + void __user *usermem = (void __user *) arg; + int ret; + + mutex_lock(&ub_mutex); +- ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, usermem); ++ ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, usermem); + mutex_unlock(&ub_mutex); + + return ret; +diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c +index 079c088..5d7a934 100644 +--- a/drivers/block/virtio_blk.c ++++ b/drivers/block/virtio_blk.c +@@ -236,8 +236,8 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, + if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI)) + return -ENOTTY; + +- return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, +- (void __user *)data); ++ return scsi_cmd_blk_ioctl(bdev, mode, cmd, ++ (void __user *)data); + } + + /* We provide getgeo only to please some old bootloader/partitioning tools */ +diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c +index f997c27..cedb231 100644 +--- a/drivers/cdrom/cdrom.c ++++ b/drivers/cdrom/cdrom.c +@@ -2747,12 +2747,11 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev, + { + void __user *argp = (void __user *)arg; + int ret; +- struct gendisk *disk = bdev->bd_disk; + + /* + * Try the generic SCSI command ioctl's first. + */ +- ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp); ++ ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); + if (ret != -ENOTTY) + return ret; + +diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c +index d267b7a..a22ca84 100644 +--- a/drivers/ide/ide-floppy_ioctl.c ++++ b/drivers/ide/ide-floppy_ioctl.c +@@ -292,8 +292,7 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev, + * and CDROM_SEND_PACKET (legacy) ioctls + */ + if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND) +- err = scsi_cmd_ioctl(bdev->bd_disk->queue, bdev->bd_disk, +- mode, cmd, argp); ++ err = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); + + if (err == -ENOTTY) + err = generic_ide_ioctl(drive, bdev, cmd, arg); +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index 953773c..c88885d 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -1095,7 +1095,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, + error = scsi_ioctl(sdp, cmd, p); + break; + default: +- error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p); ++ error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p); + if (error != -ENOTTY) + break; + error = scsi_ioctl(sdp, cmd, p); +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index 5e30b45..aa829a4 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -675,6 +675,8 @@ extern int blk_insert_cloned_request(struct request_queue *q, + struct request *rq); + extern void blk_delay_queue(struct request_queue *, unsigned long); + extern void blk_recount_segments(struct request_queue *, struct bio *); ++extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t, ++ unsigned int, void __user *); + extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t, + unsigned int, void __user *); + extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t, +-- +1.7.7.5 + diff --git a/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch b/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch new file mode 100644 index 000000000..942e2a007 --- /dev/null +++ b/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch @@ -0,0 +1,165 @@ +From e773daff833c61e0ce22d62b7d1bb7b82f4222d0 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 16 Jan 2012 17:12:59 +0100 +Subject: [PATCH 2/3] block: fail SCSI passthrough ioctls on partition devices + +Linux allows executing the SG_IO ioctl on a partition or LVM volume, and +will pass the command to the underlying block device. This is +well-known, but it is also a large security problem when (via Unix +permissions, ACLs, SELinux or a combination thereof) a program or user +needs to be granted access only to part of the disk. + +This patch lets partitions forward a small set of harmless ioctls; +others are logged with printk so that we can see which ioctls are +actually sent. In my tests only CDROM_GET_CAPABILITY actually occurred. +Of course it was being sent to a (partition on a) hard disk, so it would +have failed with ENOTTY and the patch isn't changing anything in +practice. Still, I'm treating it specially to avoid spamming the logs. + +In principle, this restriction should include programs running with +CAP_SYS_RAWIO. If for example I let a program access /dev/sda2 and +/dev/sdb, it still should not be able to read/write outside the +boundaries of /dev/sda2 independent of the capabilities. However, for +now programs with CAP_SYS_RAWIO will still be allowed to send the +ioctls. Their actions will still be logged. + +This patch does not affect the non-libata IDE driver. That driver +however already tests for bd != bd->bd_contains before issuing some +ioctl; it could be restricted further to forbid these ioctls even for +programs running with CAP_SYS_ADMIN/CAP_SYS_RAWIO. + +[ Cherry picked from 3ed4e7ba4be8c72051d87dcb2dec279d97a18d41 + + Changes with respect to 3.3: return -ENOTTY from scsi_verify_blk_ioctl + and -ENOIOCTLCMD from sd_compat_ioctl. ] + +Cc: stable@kernel.org +Cc: linux-scsi@vger.kernel.org +Cc: Jens Axboe +Cc: James Bottomley +Signed-off-by: Paolo Bonzini +[ Make it also print the command name when warning - Linus ] +Signed-off-by: Linus Torvalds +--- + block/scsi_ioctl.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ + drivers/scsi/sd.c | 11 +++++++++-- + include/linux/blkdev.h | 1 + + 3 files changed, 55 insertions(+), 2 deletions(-) + +diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c +index 57ac937..5ef1f4c 100644 +--- a/block/scsi_ioctl.c ++++ b/block/scsi_ioctl.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -691,9 +692,53 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod + } + EXPORT_SYMBOL(scsi_cmd_ioctl); + ++int scsi_verify_blk_ioctl(struct block_device *bd, unsigned int cmd) ++{ ++ if (bd && bd == bd->bd_contains) ++ return 0; ++ ++ /* Actually none of these is particularly useful on a partition, ++ * but they are safe. ++ */ ++ switch (cmd) { ++ case SCSI_IOCTL_GET_IDLUN: ++ case SCSI_IOCTL_GET_BUS_NUMBER: ++ case SCSI_IOCTL_GET_PCI: ++ case SCSI_IOCTL_PROBE_HOST: ++ case SG_GET_VERSION_NUM: ++ case SG_SET_TIMEOUT: ++ case SG_GET_TIMEOUT: ++ case SG_GET_RESERVED_SIZE: ++ case SG_SET_RESERVED_SIZE: ++ case SG_EMULATED_HOST: ++ return 0; ++ case CDROM_GET_CAPABILITY: ++ /* Keep this until we remove the printk below. udev sends it ++ * and we do not want to spam dmesg about it. CD-ROMs do ++ * not have partitions, so we get here only for disks. ++ */ ++ return -ENOTTY; ++ default: ++ break; ++ } ++ ++ /* In particular, rule out all resets and host-specific ioctls. */ ++ printk_ratelimited(KERN_WARNING ++ "%s: sending ioctl %x to a partition!\n", current->comm, cmd); ++ ++ return capable(CAP_SYS_RAWIO) ? 0 : -ENOTTY; ++} ++EXPORT_SYMBOL(scsi_verify_blk_ioctl); ++ + int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode, + unsigned int cmd, void __user *arg) + { ++ int ret; ++ ++ ret = scsi_verify_blk_ioctl(bd, cmd); ++ if (ret < 0) ++ return ret; ++ + return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg); + } + EXPORT_SYMBOL(scsi_cmd_blk_ioctl); +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index c88885d..7d8b5d8 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -1073,6 +1073,10 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, + SCSI_LOG_IOCTL(1, printk("sd_ioctl: disk=%s, cmd=0x%x\n", + disk->disk_name, cmd)); + ++ error = scsi_verify_blk_ioctl(bdev, cmd); ++ if (error < 0) ++ return error; ++ + /* + * If we are in the middle of error recovery, don't let anyone + * else try and use this device. Also, if error recovery fails, it +@@ -1265,6 +1269,11 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) + { + struct scsi_device *sdev = scsi_disk(bdev->bd_disk)->device; ++ int ret; ++ ++ ret = scsi_verify_blk_ioctl(bdev, cmd); ++ if (ret < 0) ++ return -ENOIOCTLCMD; + + /* + * If we are in the middle of error recovery, don't let anyone +@@ -1276,8 +1285,6 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, + return -ENODEV; + + if (sdev->host->hostt->compat_ioctl) { +- int ret; +- + ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg); + + return ret; +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index aa829a4..8b7a19e 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -675,6 +675,7 @@ extern int blk_insert_cloned_request(struct request_queue *q, + struct request *rq); + extern void blk_delay_queue(struct request_queue *, unsigned long); + extern void blk_recount_segments(struct request_queue *, struct bio *); ++extern int scsi_verify_blk_ioctl(struct block_device *, unsigned int); + extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t, + unsigned int, void __user *); + extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t, +-- +1.7.7.5 + diff --git a/03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch b/03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch new file mode 100644 index 000000000..129edd974 --- /dev/null +++ b/03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch @@ -0,0 +1,91 @@ +From bf50a5715cac3b85f3bd33f184f7c031debabe0b Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 16 Jan 2012 17:13:00 +0100 +Subject: [PATCH 3/3] dm: do not forward ioctls from logical volumes to the + underlying device + +A logical volume can map to just part of underlying physical volume. +In this case, it must be treated like a partition. + +Based on a patch from Alasdair G Kergon. + +[ Cherry picked from 95113a17a2a1eb06151dc698dca9bcc4a29e4fbb ] + +Cc: stable@kernel.org +Cc: Alasdair G Kergon +Cc: dm-devel@redhat.com +Cc: linux-scsi@vger.kernel.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Linus Torvalds +--- + drivers/md/dm-flakey.c | 11 ++++++++++- + drivers/md/dm-linear.c | 12 +++++++++++- + drivers/md/dm-mpath.c | 6 ++++++ + 3 files changed, 27 insertions(+), 2 deletions(-) + +diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c +index f84c080..9fb18c1 100644 +--- a/drivers/md/dm-flakey.c ++++ b/drivers/md/dm-flakey.c +@@ -368,8 +368,17 @@ static int flakey_status(struct dm_target *ti, status_type_t type, + static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg) + { + struct flakey_c *fc = ti->private; ++ struct dm_dev *dev = fc->dev; ++ int r = 0; + +- return __blkdev_driver_ioctl(fc->dev->bdev, fc->dev->mode, cmd, arg); ++ /* ++ * Only pass ioctls through if the device sizes match exactly. ++ */ ++ if (fc->start || ++ ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) ++ r = scsi_verify_blk_ioctl(NULL, cmd); ++ ++ return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg); + } + + static int flakey_merge(struct dm_target *ti, struct bvec_merge_data *bvm, +diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c +index 3921e3b..9728839 100644 +--- a/drivers/md/dm-linear.c ++++ b/drivers/md/dm-linear.c +@@ -116,7 +116,17 @@ static int linear_ioctl(struct dm_target *ti, unsigned int cmd, + unsigned long arg) + { + struct linear_c *lc = (struct linear_c *) ti->private; +- return __blkdev_driver_ioctl(lc->dev->bdev, lc->dev->mode, cmd, arg); ++ struct dm_dev *dev = lc->dev; ++ int r = 0; ++ ++ /* ++ * Only pass ioctls through if the device sizes match exactly. ++ */ ++ if (lc->start || ++ ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) ++ r = scsi_verify_blk_ioctl(NULL, cmd); ++ ++ return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg); + } + + static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm, +diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c +index 5e0090e..801d92d 100644 +--- a/drivers/md/dm-mpath.c ++++ b/drivers/md/dm-mpath.c +@@ -1520,6 +1520,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, + + spin_unlock_irqrestore(&m->lock, flags); + ++ /* ++ * Only pass ioctls through if the device sizes match exactly. ++ */ ++ if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) ++ r = scsi_verify_blk_ioctl(NULL, cmd); ++ + return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); + } + +-- +1.7.7.5 + diff --git a/kernel.spec b/kernel.spec index 727959344..0a7e87cba 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -878,6 +878,11 @@ Patch22100: msi-irq-sysfs-warning.patch #rhbz 728740 Patch21076: rtl8192cu-Fix-WARNING-on-suspend-resume.patch +Patch21077: 01-block-add-and-use-scsi_blk_cmd_ioctl.patch +Patch21078: 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch +Patch21079: 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch + + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1619,6 +1624,11 @@ ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch #rhbz 728740 ApplyPatch rtl8192cu-Fix-WARNING-on-suspend-resume.patch +#rhbz 769911 +ApplyPatch 01-block-add-and-use-scsi_blk_cmd_ioctl.patch +ApplyPatch 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch +ApplyPatch 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch + # END OF PATCH APPLICATIONS %endif @@ -2393,6 +2403,9 @@ fi # and build. %changelog +* Tue Jan 17 2012 Josh Boyer +- CVE-2011-4127 possible privilege escalation via SG_IO ioctl (rhbz 769911) + * Mon Jan 16 2012 John W. Linville - Re-apply patch to revert mac80211 scan optimizations (rhbz #731365, #773271) From feea98915e65b138ec42f60f35fe41ee06ed2982 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 18 Jan 2012 10:08:53 -0500 Subject: [PATCH 224/487] CVE-2012-0056 proc: clean up and fix /proc//mem (rhbz 782681) --- kernel.spec | 9 + ...ean-up-and-fix-proc-pid-mem-handling.patch | 268 ++++++++++++++++++ 2 files changed, 277 insertions(+) create mode 100644 proc-clean-up-and-fix-proc-pid-mem-handling.patch diff --git a/kernel.spec b/kernel.spec index 0a7e87cba..14a45acc7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -882,6 +882,9 @@ Patch21077: 01-block-add-and-use-scsi_blk_cmd_ioctl.patch Patch21078: 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch Patch21079: 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch +#rhbz 782681 +Patch21085: proc-clean-up-and-fix-proc-pid-mem-handling.patch + %endif @@ -1629,6 +1632,9 @@ ApplyPatch 01-block-add-and-use-scsi_blk_cmd_ioctl.patch ApplyPatch 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch ApplyPatch 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch +#rhbz 782681 +ApplyPatch proc-clean-up-and-fix-proc-pid-mem-handling.patch + # END OF PATCH APPLICATIONS %endif @@ -2403,6 +2409,9 @@ fi # and build. %changelog +* Wed Jan 18 2012 Josh Boyer +- CVE-2012-0056 proc: clean up and fix /proc//mem (rhbz 782681) + * Tue Jan 17 2012 Josh Boyer - CVE-2011-4127 possible privilege escalation via SG_IO ioctl (rhbz 769911) diff --git a/proc-clean-up-and-fix-proc-pid-mem-handling.patch b/proc-clean-up-and-fix-proc-pid-mem-handling.patch new file mode 100644 index 000000000..c793475d2 --- /dev/null +++ b/proc-clean-up-and-fix-proc-pid-mem-handling.patch @@ -0,0 +1,268 @@ +From e268337dfe26dfc7efd422a804dbb27977a3cccc Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Tue, 17 Jan 2012 15:21:19 -0800 +Subject: [PATCH] proc: clean up and fix /proc//mem handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Jüri Aedla reported that the /proc//mem handling really isn't very +robust, and it also doesn't match the permission checking of any of the +other related files. + +This changes it to do the permission checks at open time, and instead of +tracking the process, it tracks the VM at the time of the open. That +simplifies the code a lot, but does mean that if you hold the file +descriptor open over an execve(), you'll continue to read from the _old_ +VM. + +That is different from our previous behavior, but much simpler. If +somebody actually finds a load where this matters, we'll need to revert +this commit. + +I suspect that nobody will ever notice - because the process mapping +addresses will also have changed as part of the execve. So you cannot +actually usefully access the fd across a VM change simply because all +the offsets for IO would have changed too. + +Reported-by: Jüri Aedla +Cc: Al Viro +Signed-off-by: Linus Torvalds +--- + fs/proc/base.c | 145 +++++++++++++++----------------------------------------- + 1 files changed, 39 insertions(+), 106 deletions(-) + +diff --git a/fs/proc/base.c b/fs/proc/base.c +index 5485a53..662ddf2 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -198,65 +198,7 @@ static int proc_root_link(struct dentry *dentry, struct path *path) + return result; + } + +-static struct mm_struct *__check_mem_permission(struct task_struct *task) +-{ +- struct mm_struct *mm; +- +- mm = get_task_mm(task); +- if (!mm) +- return ERR_PTR(-EINVAL); +- +- /* +- * A task can always look at itself, in case it chooses +- * to use system calls instead of load instructions. +- */ +- if (task == current) +- return mm; +- +- /* +- * If current is actively ptrace'ing, and would also be +- * permitted to freshly attach with ptrace now, permit it. +- */ +- if (task_is_stopped_or_traced(task)) { +- int match; +- rcu_read_lock(); +- match = (ptrace_parent(task) == current); +- rcu_read_unlock(); +- if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH)) +- return mm; +- } +- +- /* +- * No one else is allowed. +- */ +- mmput(mm); +- return ERR_PTR(-EPERM); +-} +- +-/* +- * If current may access user memory in @task return a reference to the +- * corresponding mm, otherwise ERR_PTR. +- */ +-static struct mm_struct *check_mem_permission(struct task_struct *task) +-{ +- struct mm_struct *mm; +- int err; +- +- /* +- * Avoid racing if task exec's as we might get a new mm but validate +- * against old credentials. +- */ +- err = mutex_lock_killable(&task->signal->cred_guard_mutex); +- if (err) +- return ERR_PTR(err); +- +- mm = __check_mem_permission(task); +- mutex_unlock(&task->signal->cred_guard_mutex); +- +- return mm; +-} +- +-struct mm_struct *mm_for_maps(struct task_struct *task) ++static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) + { + struct mm_struct *mm; + int err; +@@ -267,7 +209,7 @@ struct mm_struct *mm_for_maps(struct task_struct *task) + + mm = get_task_mm(task); + if (mm && mm != current->mm && +- !ptrace_may_access(task, PTRACE_MODE_READ)) { ++ !ptrace_may_access(task, mode)) { + mmput(mm); + mm = ERR_PTR(-EACCES); + } +@@ -276,6 +218,11 @@ struct mm_struct *mm_for_maps(struct task_struct *task) + return mm; + } + ++struct mm_struct *mm_for_maps(struct task_struct *task) ++{ ++ return mm_access(task, PTRACE_MODE_READ); ++} ++ + static int proc_pid_cmdline(struct task_struct *task, char * buffer) + { + int res = 0; +@@ -752,38 +699,39 @@ static const struct file_operations proc_single_file_operations = { + + static int mem_open(struct inode* inode, struct file* file) + { +- file->private_data = (void*)((long)current->self_exec_id); ++ struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); ++ struct mm_struct *mm; ++ ++ if (!task) ++ return -ESRCH; ++ ++ mm = mm_access(task, PTRACE_MODE_ATTACH); ++ put_task_struct(task); ++ ++ if (IS_ERR(mm)) ++ return PTR_ERR(mm); ++ + /* OK to pass negative loff_t, we can catch out-of-range */ + file->f_mode |= FMODE_UNSIGNED_OFFSET; ++ file->private_data = mm; ++ + return 0; + } + + static ssize_t mem_read(struct file * file, char __user * buf, + size_t count, loff_t *ppos) + { +- struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); ++ int ret; + char *page; + unsigned long src = *ppos; +- int ret = -ESRCH; +- struct mm_struct *mm; ++ struct mm_struct *mm = file->private_data; + +- if (!task) +- goto out_no_task; ++ if (!mm) ++ return 0; + +- ret = -ENOMEM; + page = (char *)__get_free_page(GFP_TEMPORARY); + if (!page) +- goto out; +- +- mm = check_mem_permission(task); +- ret = PTR_ERR(mm); +- if (IS_ERR(mm)) +- goto out_free; +- +- ret = -EIO; +- +- if (file->private_data != (void*)((long)current->self_exec_id)) +- goto out_put; ++ return -ENOMEM; + + ret = 0; + +@@ -810,13 +758,7 @@ static ssize_t mem_read(struct file * file, char __user * buf, + } + *ppos = src; + +-out_put: +- mmput(mm); +-out_free: + free_page((unsigned long) page); +-out: +- put_task_struct(task); +-out_no_task: + return ret; + } + +@@ -825,27 +767,15 @@ static ssize_t mem_write(struct file * file, const char __user *buf, + { + int copied; + char *page; +- struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); + unsigned long dst = *ppos; +- struct mm_struct *mm; ++ struct mm_struct *mm = file->private_data; + +- copied = -ESRCH; +- if (!task) +- goto out_no_task; ++ if (!mm) ++ return 0; + +- copied = -ENOMEM; + page = (char *)__get_free_page(GFP_TEMPORARY); + if (!page) +- goto out_task; +- +- mm = check_mem_permission(task); +- copied = PTR_ERR(mm); +- if (IS_ERR(mm)) +- goto out_free; +- +- copied = -EIO; +- if (file->private_data != (void *)((long)current->self_exec_id)) +- goto out_mm; ++ return -ENOMEM; + + copied = 0; + while (count > 0) { +@@ -869,13 +799,7 @@ static ssize_t mem_write(struct file * file, const char __user *buf, + } + *ppos = dst; + +-out_mm: +- mmput(mm); +-out_free: + free_page((unsigned long) page); +-out_task: +- put_task_struct(task); +-out_no_task: + return copied; + } + +@@ -895,11 +819,20 @@ loff_t mem_lseek(struct file *file, loff_t offset, int orig) + return file->f_pos; + } + ++static int mem_release(struct inode *inode, struct file *file) ++{ ++ struct mm_struct *mm = file->private_data; ++ ++ mmput(mm); ++ return 0; ++} ++ + static const struct file_operations proc_mem_operations = { + .llseek = mem_lseek, + .read = mem_read, + .write = mem_write, + .open = mem_open, ++ .release = mem_release, + }; + + static ssize_t environ_read(struct file *file, char __user *buf, +-- +1.7.7.5 + From 4a39227a1540ae4d4d4968c5d31c7d1dd0c37734 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 18 Jan 2012 10:23:39 -0500 Subject: [PATCH 225/487] loop: prevent information leak after failed read (rhbz 782687) --- kernel.spec | 6 +++ ...t-information-leak-after-failed-read.patch | 41 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 loop-prevent-information-leak-after-failed-read.patch diff --git a/kernel.spec b/kernel.spec index 14a45acc7..d566c586f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -885,6 +885,8 @@ Patch21079: 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch #rhbz 782681 Patch21085: proc-clean-up-and-fix-proc-pid-mem-handling.patch +#rhbz 782687 +Patch21086: loop-prevent-information-leak-after-failed-read.patch %endif @@ -1635,6 +1637,9 @@ ApplyPatch 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch #rhbz 782681 ApplyPatch proc-clean-up-and-fix-proc-pid-mem-handling.patch +#rhbz 782687 +ApplyPatch loop-prevent-information-leak-after-failed-read.patch + # END OF PATCH APPLICATIONS %endif @@ -2411,6 +2416,7 @@ fi %changelog * Wed Jan 18 2012 Josh Boyer - CVE-2012-0056 proc: clean up and fix /proc//mem (rhbz 782681) +- loop: prevent information leak after failed read (rhbz 782687) * Tue Jan 17 2012 Josh Boyer - CVE-2011-4127 possible privilege escalation via SG_IO ioctl (rhbz 769911) diff --git a/loop-prevent-information-leak-after-failed-read.patch b/loop-prevent-information-leak-after-failed-read.patch new file mode 100644 index 000000000..040a234c3 --- /dev/null +++ b/loop-prevent-information-leak-after-failed-read.patch @@ -0,0 +1,41 @@ +From 3bb9068278ea524581237abadd41377a14717e7d Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Wed, 16 Nov 2011 09:21:48 +0100 +Subject: [PATCH] loop: prevent information leak after failed read + +If read was not fully successful we have to fail whole bio to prevent +information leak of old pages + +##Testcase_begin +dd if=/dev/zero of=./file bs=1M count=1 +losetup /dev/loop0 ./file -o 4096 +truncate -s 0 ./file +# OOps loop offset is now beyond i_size, so read will silently fail. +# So bio's pages would not be cleared, may which result in information leak. +hexdump -C /dev/loop0 +##testcase_end + +Signed-off-by: Dmitry Monakhov +Signed-off-by: Andrew Morton +Signed-off-by: Jens Axboe +--- + drivers/block/loop.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/drivers/block/loop.c b/drivers/block/loop.c +index 3d80682..0d56739 100644 +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -372,7 +372,8 @@ do_lo_receive(struct loop_device *lo, + + if (retval < 0) + return retval; +- ++ if (retval != bvec->bv_len) ++ return -EIO; + return 0; + } + +-- +1.7.7.5 + From e9822a3383aefe089b3585c19ff97f1d42df3063 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 18 Jan 2012 11:45:38 -0500 Subject: [PATCH 226/487] Update to Linux 3.1.10 --- KVM-fix-device-assignment-permissions.patch | 206 ------------------ ...tarting-PIT-timers-in-the-absence-of.patch | 69 ------ dell-mmconfig-quirk.patch | 205 ----------------- ...eck-if-acpi-already-handle-backlight.patch | 31 --- kernel.spec | 33 +-- ...include-bitmap-in-nfsv4_get_acl_data.patch | 118 ---------- sources | 2 +- 7 files changed, 5 insertions(+), 659 deletions(-) delete mode 100644 KVM-fix-device-assignment-permissions.patch delete mode 100644 KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch delete mode 100644 dell-mmconfig-quirk.patch delete mode 100644 ideapad-Check-if-acpi-already-handle-backlight.patch delete mode 100644 nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch diff --git a/KVM-fix-device-assignment-permissions.patch b/KVM-fix-device-assignment-permissions.patch deleted file mode 100644 index 208948200..000000000 --- a/KVM-fix-device-assignment-permissions.patch +++ /dev/null @@ -1,206 +0,0 @@ -From 423873736b78f549fbfa2f715f2e4de7e6c5e1e9 Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Tue, 20 Dec 2011 21:59:03 -0700 -Subject: [PATCH 1/2] KVM: Remove ability to assign a device without iommu - support - -This option has no users and it exposes a security hole that we -can allow devices to be assigned without iommu protection. Make -KVM_DEV_ASSIGN_ENABLE_IOMMU a mandatory option. - -Signed-off-by: Alex Williamson -Signed-off-by: Marcelo Tosatti ---- - virt/kvm/assigned-dev.c | 18 +++++++++--------- - 1 files changed, 9 insertions(+), 9 deletions(-) - -diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c -index 3ad0925..a251a28 100644 ---- a/virt/kvm/assigned-dev.c -+++ b/virt/kvm/assigned-dev.c -@@ -487,6 +487,9 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, - struct kvm_assigned_dev_kernel *match; - struct pci_dev *dev; - -+ if (!(assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU)) -+ return -EINVAL; -+ - mutex_lock(&kvm->lock); - idx = srcu_read_lock(&kvm->srcu); - -@@ -544,16 +547,14 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, - - list_add(&match->list, &kvm->arch.assigned_dev_head); - -- if (assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) { -- if (!kvm->arch.iommu_domain) { -- r = kvm_iommu_map_guest(kvm); -- if (r) -- goto out_list_del; -- } -- r = kvm_assign_device(kvm, match); -+ if (!kvm->arch.iommu_domain) { -+ r = kvm_iommu_map_guest(kvm); - if (r) - goto out_list_del; - } -+ r = kvm_assign_device(kvm, match); -+ if (r) -+ goto out_list_del; - - out: - srcu_read_unlock(&kvm->srcu, idx); -@@ -593,8 +594,7 @@ static int kvm_vm_ioctl_deassign_device(struct kvm *kvm, - goto out; - } - -- if (match->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) -- kvm_deassign_device(kvm, match); -+ kvm_deassign_device(kvm, match); - - kvm_free_assigned_device(kvm, match); - --- -1.7.7.5 - - -From 3d27e23b17010c668db311140b17bbbb70c78fb9 Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Tue, 20 Dec 2011 21:59:09 -0700 -Subject: [PATCH 2/2] KVM: Device assignment permission checks - -Only allow KVM device assignment to attach to devices which: - - - Are not bridges - - Have BAR resources (assume others are special devices) - - The user has permissions to use - -Assigning a bridge is a configuration error, it's not supported, and -typically doesn't result in the behavior the user is expecting anyway. -Devices without BAR resources are typically chipset components that -also don't have host drivers. We don't want users to hold such devices -captive or cause system problems by fencing them off into an iommu -domain. We determine "permission to use" by testing whether the user -has access to the PCI sysfs resource files. By default a normal user -will not have access to these files, so it provides a good indication -that an administration agent has granted the user access to the device. - -[Yang Bai: add missing #include] -[avi: fix comment style] - -Signed-off-by: Alex Williamson -Signed-off-by: Yang Bai -Signed-off-by: Marcelo Tosatti ---- - virt/kvm/assigned-dev.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++ - 1 files changed, 75 insertions(+), 0 deletions(-) - -diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c -index a251a28..758e3b3 100644 ---- a/virt/kvm/assigned-dev.c -+++ b/virt/kvm/assigned-dev.c -@@ -17,6 +17,8 @@ - #include - #include - #include -+#include -+#include - #include "irq.h" - - static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head, -@@ -480,12 +482,73 @@ out: - return r; - } - -+/* -+ * We want to test whether the caller has been granted permissions to -+ * use this device. To be able to configure and control the device, -+ * the user needs access to PCI configuration space and BAR resources. -+ * These are accessed through PCI sysfs. PCI config space is often -+ * passed to the process calling this ioctl via file descriptor, so we -+ * can't rely on access to that file. We can check for permissions -+ * on each of the BAR resource files, which is a pretty clear -+ * indicator that the user has been granted access to the device. -+ */ -+static int probe_sysfs_permissions(struct pci_dev *dev) -+{ -+#ifdef CONFIG_SYSFS -+ int i; -+ bool bar_found = false; -+ -+ for (i = PCI_STD_RESOURCES; i <= PCI_STD_RESOURCE_END; i++) { -+ char *kpath, *syspath; -+ struct path path; -+ struct inode *inode; -+ int r; -+ -+ if (!pci_resource_len(dev, i)) -+ continue; -+ -+ kpath = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); -+ if (!kpath) -+ return -ENOMEM; -+ -+ /* Per sysfs-rules, sysfs is always at /sys */ -+ syspath = kasprintf(GFP_KERNEL, "/sys%s/resource%d", kpath, i); -+ kfree(kpath); -+ if (!syspath) -+ return -ENOMEM; -+ -+ r = kern_path(syspath, LOOKUP_FOLLOW, &path); -+ kfree(syspath); -+ if (r) -+ return r; -+ -+ inode = path.dentry->d_inode; -+ -+ r = inode_permission(inode, MAY_READ | MAY_WRITE | MAY_ACCESS); -+ path_put(&path); -+ if (r) -+ return r; -+ -+ bar_found = true; -+ } -+ -+ /* If no resources, probably something special */ -+ if (!bar_found) -+ return -EPERM; -+ -+ return 0; -+#else -+ return -EINVAL; /* No way to control the device without sysfs */ -+#endif -+} -+ - static int kvm_vm_ioctl_assign_device(struct kvm *kvm, - struct kvm_assigned_pci_dev *assigned_dev) - { - int r = 0, idx; - struct kvm_assigned_dev_kernel *match; - struct pci_dev *dev; -+ u8 header_type; - - if (!(assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU)) - return -EINVAL; -@@ -516,6 +579,18 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, - r = -EINVAL; - goto out_free; - } -+ -+ /* Don't allow bridges to be assigned */ -+ pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); -+ if ((header_type & PCI_HEADER_TYPE) != PCI_HEADER_TYPE_NORMAL) { -+ r = -EPERM; -+ goto out_put; -+ } -+ -+ r = probe_sysfs_permissions(dev); -+ if (r) -+ goto out_put; -+ - if (pci_enable_device(dev)) { - printk(KERN_INFO "%s: Could not enable PCI device\n", __func__); - r = -EBUSY; --- -1.7.7.5 - diff --git a/KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch b/KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch deleted file mode 100644 index 07ef3e71b..000000000 --- a/KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0924ab2cfa98b1ece26c033d696651fd62896c69 Mon Sep 17 00:00:00 2001 -From: Jan Kiszka -Date: Wed, 14 Dec 2011 19:25:13 +0100 -Subject: [PATCH] KVM: x86: Prevent starting PIT timers in the absence of - irqchip support - -User space may create the PIT and forgets about setting up the irqchips. -In that case, firing PIT IRQs will crash the host: - -BUG: unable to handle kernel NULL pointer dereference at 0000000000000128 -IP: [] kvm_set_irq+0x30/0x170 [kvm] -... -Call Trace: - [] pit_do_work+0x51/0xd0 [kvm] - [] process_one_work+0x111/0x4d0 - [] worker_thread+0x152/0x340 - [] kthread+0x7e/0x90 - [] kernel_thread_helper+0x4/0x10 - -Prevent this by checking the irqchip mode before starting a timer. We -can't deny creating the PIT if the irqchips aren't set up yet as -current user land expects this order to work. - -Signed-off-by: Jan Kiszka -Signed-off-by: Marcelo Tosatti ---- - arch/x86/kvm/i8254.c | 10 +++++++--- - 1 files changed, 7 insertions(+), 3 deletions(-) - -diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c -index 76e3f1c..405f262 100644 ---- a/arch/x86/kvm/i8254.c -+++ b/arch/x86/kvm/i8254.c -@@ -338,11 +338,15 @@ static enum hrtimer_restart pit_timer_fn(struct hrtimer *data) - return HRTIMER_NORESTART; - } - --static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period) -+static void create_pit_timer(struct kvm *kvm, u32 val, int is_period) - { -+ struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state; - struct kvm_timer *pt = &ps->pit_timer; - s64 interval; - -+ if (!irqchip_in_kernel(kvm)) -+ return; -+ - interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ); - - pr_debug("create pit timer, interval is %llu nsec\n", interval); -@@ -394,13 +398,13 @@ static void pit_load_count(struct kvm *kvm, int channel, u32 val) - /* FIXME: enhance mode 4 precision */ - case 4: - if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)) { -- create_pit_timer(ps, val, 0); -+ create_pit_timer(kvm, val, 0); - } - break; - case 2: - case 3: - if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)){ -- create_pit_timer(ps, val, 1); -+ create_pit_timer(kvm, val, 1); - } - break; - default: --- -1.7.6.2 - diff --git a/dell-mmconfig-quirk.patch b/dell-mmconfig-quirk.patch deleted file mode 100644 index 6ee6b73ba..000000000 --- a/dell-mmconfig-quirk.patch +++ /dev/null @@ -1,205 +0,0 @@ - x86, amd: factor out MMCONFIG discovery - - This factors out the AMD native MMCONFIG discovery so we can use it - outside amd_bus.c. - - amd_bus.c reads AMD MSRs so it can remove the MMCONFIG area from the - PCI resources. We may also need the MMCONFIG information to work - around BIOS defects in the ACPI MCFG table. - - Signed-off-by: Bjorn Helgaas ---- a/arch/x86/include/asm/amd_nb.h -+++ a/arch/x86/include/asm/amd_nb.h -@@ -13,6 +13,7 @@ extern const struct pci_device_id amd_nb_misc_ids[]; - extern const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[]; - - extern bool early_is_amd_nb(u32 value); -+extern void amd_get_mmconfig_range(u64 *start, u64 *end); - extern int amd_cache_northbridges(void); - extern void amd_flush_garts(void); - extern int amd_numa_init(void); ---- a/arch/x86/kernel/amd_nb.c -+++ a/arch/x86/kernel/amd_nb.c -@@ -119,6 +119,38 @@ bool __init early_is_amd_nb(u32 device) - return false; - } - -+void amd_get_mmconfig_range(u64 *start, u64 *end) -+{ -+ u32 address; -+ u64 base, msr; -+ unsigned segn_busn_bits; -+ -+ *start = 0; -+ *end = 0; -+ -+ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) -+ return; -+ -+ /* assume all cpus from fam10h have mmconfig */ -+ if (boot_cpu_data.x86 < 0x10) -+ return; -+ -+ address = MSR_FAM10H_MMIO_CONF_BASE; -+ rdmsrl(address, msr); -+ -+ /* mmconfig is not enabled */ -+ if (!(msr & FAM10H_MMIO_CONF_ENABLE)) -+ return; -+ -+ base = msr & (FAM10H_MMIO_CONF_BASE_MASK<> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) & -+ FAM10H_MMIO_CONF_BUSRANGE_MASK; -+ -+ *start = base; -+ *end = base + (1ULL<<(segn_busn_bits + 20)) - 1; -+} -+ - int amd_get_subcaches(int cpu) - { - struct pci_dev *link = node_to_amd_nb(amd_get_nb_id(cpu))->link; ---- a/arch/x86/pci/amd_bus.c -+++ a/arch/x86/pci/amd_bus.c -@@ -30,34 +30,6 @@ static struct pci_hostbridge_probe pci_probes[] __initdata = { - { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1300 }, - }; - --static u64 __initdata fam10h_mmconf_start; --static u64 __initdata fam10h_mmconf_end; --static void __init get_pci_mmcfg_amd_fam10h_range(void) --{ -- u32 address; -- u64 base, msr; -- unsigned segn_busn_bits; -- -- /* assume all cpus from fam10h have mmconf */ -- if (boot_cpu_data.x86 < 0x10) -- return; -- -- address = MSR_FAM10H_MMIO_CONF_BASE; -- rdmsrl(address, msr); -- -- /* mmconfig is not enable */ -- if (!(msr & FAM10H_MMIO_CONF_ENABLE)) -- return; -- -- base = msr & (FAM10H_MMIO_CONF_BASE_MASK<> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) & -- FAM10H_MMIO_CONF_BUSRANGE_MASK; -- -- fam10h_mmconf_start = base; -- fam10h_mmconf_end = base + (1ULL<<(segn_busn_bits + 20)) - 1; --} -- - #define RANGE_NUM 16 - - /** -@@ -85,6 +57,8 @@ static int __init early_fill_mp_bus_info(void) - u64 val; - u32 address; - bool found; -+ u64 fam10h_mmconf_start; -+ u64 fam10h_mmconf_end; - - if (!early_pci_allowed()) - return -1; -@@ -211,7 +185,7 @@ static int __init early_fill_mp_bus_info(void) - subtract_range(range, RANGE_NUM, 0, end); - - /* get mmconfig */ -- get_pci_mmcfg_amd_fam10h_range(); -+ amd_get_mmconfig_range(&fam10h_mmconf_start, &fam10h_mmconf_end); - /* need to take out mmconf range */ - if (fam10h_mmconf_end) { - printk(KERN_DEBUG "Fam 10h mmconf [%llx, %llx]\n", fam10h_mmconf_start, fam10h_mmconf_end); - - - - - PNP: work around Dell 1536/1546 BIOS MMCONFIG bug that breaks USB - - Some Dell BIOSes have MCFG tables that don't report the entire - MMCONFIG area claimed by the chipset. If we move PCI devices into - that claimed-but-unreported area, they don't work. - - This quirk reads the AMD MMCONFIG MSRs and adds PNP0C01 resources as - needed to cover the entire area. - - Example problem scenario: - - BIOS-e820: 00000000cfec5400 - 00000000d4000000 (reserved) - Fam 10h mmconf [d0000000, dfffffff] - PCI: MMCONFIG for domain 0000 [bus 00-3f] at [mem 0xd0000000-0xd3ffffff] (base 0xd0000000) - pnp 00:0c: [mem 0xd0000000-0xd3ffffff] - pci 0000:00:12.0: reg 10: [mem 0xffb00000-0xffb00fff] - pci 0000:00:12.0: no compatible bridge window for [mem 0xffb00000-0xffb00fff] - pci 0000:00:12.0: BAR 0: assigned [mem 0xd4000000-0xd40000ff] - - Reported-by: Lisa Salimbas - Reported-by: - References: https://bugzilla.kernel.org/show_bug.cgi?id=31602 - References: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/647043 - References: https://bugzilla.redhat.com/show_bug.cgi?id=770308 - Cc: stable@kernel.org # 2.6.34+ - Signed-off-by: Bjorn Helgaas ---- a/drivers/pnp/quirks.c -+++ a/drivers/pnp/quirks.c -@@ -295,6 +295,46 @@ static void quirk_system_pci_resources(struct pnp_dev *dev) - } - } - -+#ifdef CONFIG_AMD_NB -+ -+#include -+ -+static void quirk_amd_mmconfig_area(struct pnp_dev *dev) -+{ -+ u64 mmconfig_start, mmconfig_end; -+ resource_size_t start, end; -+ struct pnp_resource *pnp_res; -+ struct resource *res; -+ -+ amd_get_mmconfig_range(&mmconfig_start, &mmconfig_end); -+ if (!mmconfig_end) -+ return; -+ -+ list_for_each_entry(pnp_res, &dev->resources, list) { -+ res = &pnp_res->res; -+ if (res->end < mmconfig_start || res->start > mmconfig_end || -+ (res->start == mmconfig_start && res->end == mmconfig_end)) -+ continue; -+ -+ dev_warn(&dev->dev, FW_BUG -+ "%pR covers only part of AMD MMCONFIG area [mem %#010llx-%#010llx]; adding more reservations\n", -+ res, (unsigned long long) mmconfig_start, -+ (unsigned long long) mmconfig_end); -+ if (mmconfig_start < res->start) { -+ start = mmconfig_start; -+ end = res->start - 1; -+ pnp_add_mem_resource(dev, start, end, 0); -+ } -+ if (mmconfig_end > res->end) { -+ start = res->end + 1; -+ end = mmconfig_end; -+ pnp_add_mem_resource(dev, start, end, 0); -+ } -+ break; -+ } -+} -+#endif -+ - /* - * PnP Quirks - * Cards or devices that need some tweaking due to incomplete resource info -@@ -322,6 +362,9 @@ static struct pnp_fixup pnp_fixups[] = { - /* PnP resources that might overlap PCI BARs */ - {"PNP0c01", quirk_system_pci_resources}, - {"PNP0c02", quirk_system_pci_resources}, -+#ifdef CONFIG_AMD_NB -+ {"PNP0c01", quirk_amd_mmconfig_area}, -+#endif - {""} - }; - diff --git a/ideapad-Check-if-acpi-already-handle-backlight.patch b/ideapad-Check-if-acpi-already-handle-backlight.patch deleted file mode 100644 index 713e005d8..000000000 --- a/ideapad-Check-if-acpi-already-handle-backlight.patch +++ /dev/null @@ -1,31 +0,0 @@ -From d4afc7754a60b885b63ef23fd194984e2d53a4e6 Mon Sep 17 00:00:00 2001 -From: Rene Bollford -Date: Sun, 23 Oct 2011 09:56:42 +0200 -Subject: [PATCH] [PATCH] ideapad: Check if acpi already handle backlight - power to avoid a page fault - -This patch avoid a page fault in the ideapad-laptop extras when -turning the backlight power on or off. - -Signed-off-by: Rene Bolldorf -Signed-off-by: Matthew Garrett ---- - drivers/platform/x86/ideapad-laptop.c | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) - -diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c -index 0c59541..0d94eec 100644 ---- a/drivers/platform/x86/ideapad-laptop.c -+++ b/drivers/platform/x86/ideapad-laptop.c -@@ -493,6 +493,8 @@ static void ideapad_backlight_notify_power(struct ideapad_private *priv) - unsigned long power; - struct backlight_device *blightdev = priv->blightdev; - -+ if (!blightdev) -+ return; - if (read_ec_data(ideapad_handle, 0x18, &power)) - return; - blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; --- -1.7.6.4 - diff --git a/kernel.spec b/kernel.spec index d566c586f..d77ba82f2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 9 +%define stable_update 10 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -764,9 +764,6 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # NFSv4 -#rhbz 753236 -Patch4000: nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch - # patches headed upstream Patch12010: add-appleir-usb-driver.patch @@ -806,9 +803,6 @@ Patch21040: x86-code-dump-fix-truncation.patch #rhbz 728607 Patch21060: elantech.patch -#rhbz 748210 -Patch21061: ideapad-Check-if-acpi-already-handle-backlight.patch - #rhbz752176 Patch21080: sysfs-msi-irq-per-device.patch @@ -826,7 +820,6 @@ Patch21220: mac80211_offchannel_rework_revert.patch Patch21225: pci-Rework-ASPM-disable-code.patch Patch21226: pci-crs-blacklist.patch -Patch21227: dell-mmconfig-quirk.patch #rhbz #757839 Patch21230: net-sky2-88e8059-fix-link-speed.patch @@ -846,12 +839,6 @@ Patch21049: tpm_tis-delay-after-aborting-cmd.patch #rhbz 771006 Patch21050: thp-reduce-khugepaged-freezing-latency.patch -#rhbz 771387 -Patch21055: KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch - -#rhbz 771678 -Patch21056: KVM-fix-device-assignment-permissions.patch - #rhbz 770233 Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch @@ -1424,7 +1411,6 @@ ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # eCryptfs # NFSv4 -ApplyPatch nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch # USB @@ -1561,9 +1547,6 @@ ApplyPatch x86-code-dump-fix-truncation.patch #rhbz 728607 ApplyPatch elantech.patch -#rhbz 748210 -ApplyPatch ideapad-Check-if-acpi-already-handle-backlight.patch - #rhbz 752176 ApplyPatch sysfs-msi-irq-per-device.patch @@ -1584,7 +1567,6 @@ ApplyPatch mac80211_offchannel_rework_revert.patch ApplyPatch pci-Rework-ASPM-disable-code.patch #ApplyPatch pci-crs-blacklist.patch -ApplyPatch dell-mmconfig-quirk.patch #rhbz #757839 ApplyPatch net-sky2-88e8059-fix-link-speed.patch @@ -1604,15 +1586,9 @@ ApplyPatch tpm_tis-delay-after-aborting-cmd.patch #rhbz 771006 ApplyPatch thp-reduce-khugepaged-freezing-latency.patch -#rhbz 771387 -ApplyPatch KVM-x86-Prevent-starting-PIT-timers-in-the-absence-of.patch - #rhbz 770233 ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch -#rhbz 771678 -ApplyPatch KVM-fix-device-assignment-permissions.patch - #rhbz 771058 ApplyPatch msi-irq-sysfs-warning.patch @@ -1620,8 +1596,6 @@ ApplyPatch ext4-Support-check-none-nocheck-mount-options.patch ApplyPatch ext4-Fix-error-handling-on-inode-bitmap-corruption.patch -ApplyPatch mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch - #rhbz 773392 ApplyPatch KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch @@ -2414,7 +2388,8 @@ fi # and build. %changelog -* Wed Jan 18 2012 Josh Boyer +* Wed Jan 18 2012 Josh Boyer 3.1.10-1 +- Linux 3.1.10 - CVE-2012-0056 proc: clean up and fix /proc//mem (rhbz 782681) - loop: prevent information leak after failed read (rhbz 782687) diff --git a/nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch b/nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch deleted file mode 100644 index 1b795e97f..000000000 --- a/nfsv4-include-bitmap-in-nfsv4_get_acl_data.patch +++ /dev/null @@ -1,118 +0,0 @@ -From: Andy Adamson - -The NFSv4 bitmap size is unbounded: a server can return an arbitrary -sized bitmap in an FATTR4_WORD0_ACL request. Replace using the -nfs4_fattr_bitmap_maxsz as a guess to the maximum bitmask returned by a server -with the inclusion of the bitmap (xdr length plus bitmasks) and the acl data -xdr length to the (cached) acl page data. - -This is a general solution to commit e5012d1f "NFSv4.1: update -nfs4_fattr_bitmap_maxsz" and fixes hitting a BUG_ON in xdr_shrink_bufhead -when getting ACLs. - -Cc:stable@xxxxxxxxxx -Signed-off-by: Andy Adamson ---- - fs/nfs/nfs4proc.c | 20 ++++++++++++++++++-- - fs/nfs/nfs4xdr.c | 15 ++++++++++++--- - 2 files changed, 30 insertions(+), 5 deletions(-) - -diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c -index deb88d9..97014dd 100644 ---- a/fs/nfs/nfs4proc.c -+++ b/fs/nfs/nfs4proc.c -@@ -3671,6 +3671,22 @@ static void nfs4_zap_acl_attr(struct inode *inode) - nfs4_set_cached_acl(inode, NULL); - } - -+/* -+ * The bitmap xdr length, bitmasks, and the attr xdr length are stored in -+ * the acl cache to handle variable length bitmasks. Just copy the acl data. -+ */ -+static void nfs4_copy_acl(char *buf, char *acl_data, size_t acl_len) -+{ -+ __be32 *q, *p = (__be32 *)acl_data; -+ int32_t len; -+ -+ len = be32_to_cpup(p); /* number of bitmasks */ -+ len += 2; /* add words for bitmap and attr xdr len */ -+ q = p + len; -+ len = len << 2; /* convert to bytes for acl_len math */ -+ memcpy(buf, (char *)q, acl_len - len); -+} -+ - static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_t buflen) - { - struct nfs_inode *nfsi = NFS_I(inode); -@@ -3688,7 +3704,7 @@ static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_ - ret = -ERANGE; /* see getxattr(2) man page */ - if (acl->len > buflen) - goto out; -- memcpy(buf, acl->data, acl->len); -+ nfs4_copy_acl(buf, acl->data, acl->len); - out_len: - ret = acl->len; - out: -@@ -3763,7 +3779,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu - if (res.acl_len > buflen) - goto out_free; - if (localpage) -- memcpy(buf, resp_buf, res.acl_len); -+ nfs4_copy_acl(buf, resp_buf, res.acl_len); - } - ret = res.acl_len; - out_free: -diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c -index f9fd96d..9c07380 100644 ---- a/fs/nfs/nfs4xdr.c -+++ b/fs/nfs/nfs4xdr.c -@@ -2513,7 +2513,7 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, - encode_compound_hdr(xdr, req, &hdr); - encode_sequence(xdr, &args->seq_args, &hdr); - encode_putfh(xdr, args->fh, &hdr); -- replen = hdr.replen + op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz + 1; -+ replen = hdr.replen + op_decode_hdr_maxsz + 1; - encode_getattr_two(xdr, FATTR4_WORD0_ACL, 0, &hdr); - - xdr_inline_pages(&req->rq_rcv_buf, replen << 2, -@@ -4955,7 +4955,7 @@ decode_restorefh(struct xdr_stream *xdr) - static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, - size_t *acl_len) - { -- __be32 *savep; -+ __be32 *savep, *bm_p; - uint32_t attrlen, - bitmap[3] = {0}; - struct kvec *iov = req->rq_rcv_buf.head; -@@ -4964,6 +4964,7 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, - *acl_len = 0; - if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) - goto out; -+ bm_p = xdr->p; - if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) - goto out; - if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) -@@ -4972,12 +4973,20 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, - if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U))) - return -EIO; - if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { -- size_t hdrlen; -+ size_t hdrlen, len; - u32 recvd; - -+ /*The bitmap (xdr len + bitmasks) and the attr xdr len words -+ * are stored with the acl data to handle the problem of -+ * variable length bitmasks.*/ -+ xdr->p = bm_p; -+ len = be32_to_cpup(bm_p); -+ len += 2; /* add bitmap and attr xdr len words */ -+ - /* We ignore &savep and don't do consistency checks on - * the attr length. Let userspace figure it out.... */ - hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; -+ attrlen += len << 2; /* attrlen is in bytes */ - recvd = req->rq_rcv_buf.len - hdrlen; - if (attrlen > recvd) { - dprintk("NFS: server cheating in getattr" --- -1.7.6.4 diff --git a/sources b/sources index af7cbe4e2..58831534a 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 204381bc537b689edcb15df0efed6467 compat-wireless-3.2-1.tar.bz2 -fae6176f187628bcc5b330cdadc60f9e patch-3.1.9.bz2 +a8e1c25a93a685ec2a1c3a808715fe9d patch-3.1.10.bz2 From 872d2983fcd65973adc610246001f9276ca4c5b1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 18 Jan 2012 13:22:40 -0500 Subject: [PATCH 227/487] /proc/pid/* information leak (rhbz 782686) --- kernel.spec | 11 + ...pointer-deref-in-proc_pid_permission.patch | 44 +++ ...fs-add-hidepid-and-gid-mount-options.patch | 342 ++++++++++++++++++ procfs-parse-mount-options.patch | 173 +++++++++ 4 files changed, 570 insertions(+) create mode 100644 proc-fix-null-pointer-deref-in-proc_pid_permission.patch create mode 100644 procfs-add-hidepid-and-gid-mount-options.patch create mode 100644 procfs-parse-mount-options.patch diff --git a/kernel.spec b/kernel.spec index d77ba82f2..bda9dbf32 100644 --- a/kernel.spec +++ b/kernel.spec @@ -869,6 +869,11 @@ Patch21077: 01-block-add-and-use-scsi_blk_cmd_ioctl.patch Patch21078: 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch Patch21079: 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch +#rhbz 782686 +Patch21082: procfs-parse-mount-options.patch +Patch21083: procfs-add-hidepid-and-gid-mount-options.patch +Patch21084: proc-fix-null-pointer-deref-in-proc_pid_permission.patch + #rhbz 782681 Patch21085: proc-clean-up-and-fix-proc-pid-mem-handling.patch @@ -1608,6 +1613,11 @@ ApplyPatch 01-block-add-and-use-scsi_blk_cmd_ioctl.patch ApplyPatch 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch ApplyPatch 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch +#rhbz 782686 +ApplyPatch procfs-parse-mount-options.patch +ApplyPatch procfs-add-hidepid-and-gid-mount-options.patch +ApplyPatch proc-fix-null-pointer-deref-in-proc_pid_permission.patch + #rhbz 782681 ApplyPatch proc-clean-up-and-fix-proc-pid-mem-handling.patch @@ -2390,6 +2400,7 @@ fi %changelog * Wed Jan 18 2012 Josh Boyer 3.1.10-1 - Linux 3.1.10 +- /proc/pid/* information leak (rhbz 782686) - CVE-2012-0056 proc: clean up and fix /proc//mem (rhbz 782681) - loop: prevent information leak after failed read (rhbz 782687) diff --git a/proc-fix-null-pointer-deref-in-proc_pid_permission.patch b/proc-fix-null-pointer-deref-in-proc_pid_permission.patch new file mode 100644 index 000000000..62d2fb21a --- /dev/null +++ b/proc-fix-null-pointer-deref-in-proc_pid_permission.patch @@ -0,0 +1,44 @@ +From a2ef990ab5a6705a356d146dd773a3b359787497 Mon Sep 17 00:00:00 2001 +From: Xiaotian Feng +Date: Thu, 12 Jan 2012 17:17:08 -0800 +Subject: [PATCH] proc: fix null pointer deref in proc_pid_permission() + +get_proc_task() can fail to search the task and return NULL, +put_task_struct() will then bomb the kernel with following oops: + + BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 + IP: [] proc_pid_permission+0x64/0xe0 + PGD 112075067 PUD 112814067 PMD 0 + Oops: 0002 [#1] PREEMPT SMP + +This is a regression introduced by commit 0499680a ("procfs: add hidepid= +and gid= mount options"). The kernel should return -ESRCH if +get_proc_task() failed. + +Signed-off-by: Xiaotian Feng +Cc: Al Viro +Cc: Vasiliy Kulikov +Cc: Stephen Wilson +Acked-by: David Rientjes +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + fs/proc/base.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/fs/proc/base.c b/fs/proc/base.c +index 8173dfd..5485a53 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -654,6 +654,8 @@ static int proc_pid_permission(struct inode *inode, int mask) + bool has_perms; + + task = get_proc_task(inode); ++ if (!task) ++ return -ESRCH; + has_perms = has_pid_permissions(pid, task, 1); + put_task_struct(task); + +-- +1.7.7.5 + diff --git a/procfs-add-hidepid-and-gid-mount-options.patch b/procfs-add-hidepid-and-gid-mount-options.patch new file mode 100644 index 000000000..24156b0dc --- /dev/null +++ b/procfs-add-hidepid-and-gid-mount-options.patch @@ -0,0 +1,342 @@ +From 0499680a42141d86417a8fbaa8c8db806bea1201 Mon Sep 17 00:00:00 2001 +From: Vasiliy Kulikov +Date: Tue, 10 Jan 2012 15:11:31 -0800 +Subject: [PATCH] procfs: add hidepid= and gid= mount options + +Add support for mount options to restrict access to /proc/PID/ +directories. The default backward-compatible "relaxed" behaviour is left +untouched. + +The first mount option is called "hidepid" and its value defines how much +info about processes we want to be available for non-owners: + +hidepid=0 (default) means the old behavior - anybody may read all +world-readable /proc/PID/* files. + +hidepid=1 means users may not access any /proc// directories, but +their own. Sensitive files like cmdline, sched*, status are now protected +against other users. As permission checking done in proc_pid_permission() +and files' permissions are left untouched, programs expecting specific +files' modes are not confused. + +hidepid=2 means hidepid=1 plus all /proc/PID/ will be invisible to other +users. It doesn't mean that it hides whether a process exists (it can be +learned by other means, e.g. by kill -0 $PID), but it hides process' euid +and egid. It compicates intruder's task of gathering info about running +processes, whether some daemon runs with elevated privileges, whether +another user runs some sensitive program, whether other users run any +program at all, etc. + +gid=XXX defines a group that will be able to gather all processes' info +(as in hidepid=0 mode). This group should be used instead of putting +nonroot user in sudoers file or something. However, untrusted users (like +daemons, etc.) which are not supposed to monitor the tasks in the whole +system should not be added to the group. + +hidepid=1 or higher is designed to restrict access to procfs files, which +might reveal some sensitive private information like precise keystrokes +timings: + +http://www.openwall.com/lists/oss-security/2011/11/05/3 + +hidepid=1/2 doesn't break monitoring userspace tools. ps, top, pgrep, and +conky gracefully handle EPERM/ENOENT and behave as if the current user is +the only user running processes. pstree shows the process subtree which +contains "pstree" process. + +Note: the patch doesn't deal with setuid/setgid issues of keeping +preopened descriptors of procfs files (like +https://lkml.org/lkml/2011/2/7/368). We rely on that the leaked +information like the scheduling counters of setuid apps doesn't threaten +anybody's privacy - only the user started the setuid program may read the +counters. + +Signed-off-by: Vasiliy Kulikov +Cc: Alexey Dobriyan +Cc: Al Viro +Cc: Randy Dunlap +Cc: "H. Peter Anvin" +Cc: Greg KH +Cc: Theodore Tso +Cc: Alan Cox +Cc: James Morris +Cc: Oleg Nesterov +Cc: Hugh Dickins +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + Documentation/filesystems/proc.txt | 39 ++++++++++++++++++++ + fs/proc/base.c | 69 +++++++++++++++++++++++++++++++++++- + fs/proc/inode.c | 8 ++++ + fs/proc/root.c | 21 +++++++++-- + include/linux/pid_namespace.h | 2 + + 5 files changed, 135 insertions(+), 4 deletions(-) + +diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt +index 0ec91f0..12fee13 100644 +--- a/Documentation/filesystems/proc.txt ++++ b/Documentation/filesystems/proc.txt +@@ -41,6 +41,8 @@ Table of Contents + 3.5 /proc//mountinfo - Information about mounts + 3.6 /proc//comm & /proc//task//comm + ++ 4 Configuring procfs ++ 4.1 Mount options + + ------------------------------------------------------------------------------ + Preface +@@ -1542,3 +1544,40 @@ a task to set its own or one of its thread siblings comm value. The comm value + is limited in size compared to the cmdline value, so writing anything longer + then the kernel's TASK_COMM_LEN (currently 16 chars) will result in a truncated + comm value. ++ ++ ++------------------------------------------------------------------------------ ++Configuring procfs ++------------------------------------------------------------------------------ ++ ++4.1 Mount options ++--------------------- ++ ++The following mount options are supported: ++ ++ hidepid= Set /proc// access mode. ++ gid= Set the group authorized to learn processes information. ++ ++hidepid=0 means classic mode - everybody may access all /proc// directories ++(default). ++ ++hidepid=1 means users may not access any /proc// directories but their ++own. Sensitive files like cmdline, sched*, status are now protected against ++other users. This makes it impossible to learn whether any user runs ++specific program (given the program doesn't reveal itself by its behaviour). ++As an additional bonus, as /proc//cmdline is unaccessible for other users, ++poorly written programs passing sensitive information via program arguments are ++now protected against local eavesdroppers. ++ ++hidepid=2 means hidepid=1 plus all /proc// will be fully invisible to other ++users. It doesn't mean that it hides a fact whether a process with a specific ++pid value exists (it can be learned by other means, e.g. by "kill -0 $PID"), ++but it hides process' uid and gid, which may be learned by stat()'ing ++/proc// otherwise. It greatly complicates an intruder's task of gathering ++information about running processes, whether some daemon runs with elevated ++privileges, whether other user runs some sensitive program, whether other users ++run any program at all, etc. ++ ++gid= defines a group authorized to learn processes information otherwise ++prohibited by hidepid=. If you use some daemon like identd which needs to learn ++information about processes information, just add identd to this group. +diff --git a/fs/proc/base.c b/fs/proc/base.c +index 4d755fe..8173dfd 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -631,6 +631,50 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr) + return 0; + } + ++/* ++ * May current process learn task's sched/cmdline info (for hide_pid_min=1) ++ * or euid/egid (for hide_pid_min=2)? ++ */ ++static bool has_pid_permissions(struct pid_namespace *pid, ++ struct task_struct *task, ++ int hide_pid_min) ++{ ++ if (pid->hide_pid < hide_pid_min) ++ return true; ++ if (in_group_p(pid->pid_gid)) ++ return true; ++ return ptrace_may_access(task, PTRACE_MODE_READ); ++} ++ ++ ++static int proc_pid_permission(struct inode *inode, int mask) ++{ ++ struct pid_namespace *pid = inode->i_sb->s_fs_info; ++ struct task_struct *task; ++ bool has_perms; ++ ++ task = get_proc_task(inode); ++ has_perms = has_pid_permissions(pid, task, 1); ++ put_task_struct(task); ++ ++ if (!has_perms) { ++ if (pid->hide_pid == 2) { ++ /* ++ * Let's make getdents(), stat(), and open() ++ * consistent with each other. If a process ++ * may not stat() a file, it shouldn't be seen ++ * in procfs at all. ++ */ ++ return -ENOENT; ++ } ++ ++ return -EPERM; ++ } ++ return generic_permission(inode, mask); ++} ++ ++ ++ + static const struct inode_operations proc_def_inode_operations = { + .setattr = proc_setattr, + }; +@@ -1615,6 +1659,7 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) + struct inode *inode = dentry->d_inode; + struct task_struct *task; + const struct cred *cred; ++ struct pid_namespace *pid = dentry->d_sb->s_fs_info; + + generic_fillattr(inode, stat); + +@@ -1623,6 +1668,14 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) + stat->gid = 0; + task = pid_task(proc_pid(inode), PIDTYPE_PID); + if (task) { ++ if (!has_pid_permissions(pid, task, 2)) { ++ rcu_read_unlock(); ++ /* ++ * This doesn't prevent learning whether PID exists, ++ * it only makes getattr() consistent with readdir(). ++ */ ++ return -ENOENT; ++ } + if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || + task_dumpable(task)) { + cred = __task_cred(task); +@@ -3119,6 +3172,7 @@ static const struct inode_operations proc_tgid_base_inode_operations = { + .lookup = proc_tgid_base_lookup, + .getattr = pid_getattr, + .setattr = proc_setattr, ++ .permission = proc_pid_permission, + }; + + static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid) +@@ -3322,6 +3376,12 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi + proc_pid_instantiate, iter.task, NULL); + } + ++static int fake_filldir(void *buf, const char *name, int namelen, ++ loff_t offset, u64 ino, unsigned d_type) ++{ ++ return 0; ++} ++ + /* for the /proc/ directory itself, after non-process stuff has been done */ + int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) + { +@@ -3329,6 +3389,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) + struct task_struct *reaper; + struct tgid_iter iter; + struct pid_namespace *ns; ++ filldir_t __filldir; + + if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET) + goto out_no_task; +@@ -3350,8 +3411,13 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) + for (iter = next_tgid(ns, iter); + iter.task; + iter.tgid += 1, iter = next_tgid(ns, iter)) { ++ if (has_pid_permissions(ns, iter.task, 2)) ++ __filldir = filldir; ++ else ++ __filldir = fake_filldir; ++ + filp->f_pos = iter.tgid + TGID_OFFSET; +- if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) { ++ if (proc_pid_fill_cache(filp, dirent, __filldir, iter) < 0) { + put_task_struct(iter.task); + goto out; + } +@@ -3686,6 +3752,7 @@ static const struct inode_operations proc_task_inode_operations = { + .lookup = proc_task_lookup, + .getattr = proc_task_getattr, + .setattr = proc_setattr, ++ .permission = proc_pid_permission, + }; + + static const struct file_operations proc_task_operations = { +diff --git a/fs/proc/inode.c b/fs/proc/inode.c +index 27c762f..84fd323 100644 +--- a/fs/proc/inode.c ++++ b/fs/proc/inode.c +@@ -106,6 +106,14 @@ void __init proc_init_inodecache(void) + + static int proc_show_options(struct seq_file *seq, struct dentry *root) + { ++ struct super_block *sb = root->d_sb; ++ struct pid_namespace *pid = sb->s_fs_info; ++ ++ if (pid->pid_gid) ++ seq_printf(seq, ",gid=%lu", (unsigned long)pid->pid_gid); ++ if (pid->hide_pid != 0) ++ seq_printf(seq, ",hidepid=%u", pid->hide_pid); ++ + return 0; + } + +diff --git a/fs/proc/root.c b/fs/proc/root.c +index 6a8ac1d..46a15d8 100644 +--- a/fs/proc/root.c ++++ b/fs/proc/root.c +@@ -38,10 +38,12 @@ static int proc_set_super(struct super_block *sb, void *data) + } + + enum { +- Opt_err, ++ Opt_gid, Opt_hidepid, Opt_err, + }; + + static const match_table_t tokens = { ++ {Opt_hidepid, "hidepid=%u"}, ++ {Opt_gid, "gid=%u"}, + {Opt_err, NULL}, + }; + +@@ -49,8 +51,7 @@ static int proc_parse_options(char *options, struct pid_namespace *pid) + { + char *p; + substring_t args[MAX_OPT_ARGS]; +- +- pr_debug("proc: options = %s\n", options); ++ int option; + + if (!options) + return 1; +@@ -63,6 +64,20 @@ static int proc_parse_options(char *options, struct pid_namespace *pid) + args[0].to = args[0].from = 0; + token = match_token(p, tokens, args); + switch (token) { ++ case Opt_gid: ++ if (match_int(&args[0], &option)) ++ return 0; ++ pid->pid_gid = option; ++ break; ++ case Opt_hidepid: ++ if (match_int(&args[0], &option)) ++ return 0; ++ if (option < 0 || option > 2) { ++ pr_err("proc: hidepid value must be between 0 and 2.\n"); ++ return 0; ++ } ++ pid->hide_pid = option; ++ break; + default: + pr_err("proc: unrecognized mount option \"%s\" " + "or missing value\n", p); +diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h +index 38d1032..e7cf666 100644 +--- a/include/linux/pid_namespace.h ++++ b/include/linux/pid_namespace.h +@@ -30,6 +30,8 @@ struct pid_namespace { + #ifdef CONFIG_BSD_PROCESS_ACCT + struct bsd_acct_struct *bacct; + #endif ++ gid_t pid_gid; ++ int hide_pid; + }; + + extern struct pid_namespace init_pid_ns; +-- +1.7.7.5 + diff --git a/procfs-parse-mount-options.patch b/procfs-parse-mount-options.patch new file mode 100644 index 000000000..99684c4bd --- /dev/null +++ b/procfs-parse-mount-options.patch @@ -0,0 +1,173 @@ +From 97412950b10e64f347aec4a9b759395c2465adf6 Mon Sep 17 00:00:00 2001 +From: Vasiliy Kulikov +Date: Tue, 10 Jan 2012 15:11:27 -0800 +Subject: [PATCH] procfs: parse mount options + +Add support for procfs mount options. Actual mount options are coming in +the next patches. + +Signed-off-by: Vasiliy Kulikov +Cc: Alexey Dobriyan +Cc: Al Viro +Cc: Randy Dunlap +Cc: "H. Peter Anvin" +Cc: Greg KH +Cc: Theodore Tso +Cc: Alan Cox +Cc: James Morris +Cc: Oleg Nesterov +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + fs/proc/inode.c | 10 +++++++++ + fs/proc/internal.h | 1 + + fs/proc/root.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 64 insertions(+), 2 deletions(-) + +diff --git a/fs/proc/inode.c b/fs/proc/inode.c +index 51a1766..27c762f 100644 +--- a/fs/proc/inode.c ++++ b/fs/proc/inode.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -17,7 +18,9 @@ + #include + #include + #include ++#include + #include ++#include + + #include + #include +@@ -101,12 +104,19 @@ void __init proc_init_inodecache(void) + init_once); + } + ++static int proc_show_options(struct seq_file *seq, struct dentry *root) ++{ ++ return 0; ++} ++ + static const struct super_operations proc_sops = { + .alloc_inode = proc_alloc_inode, + .destroy_inode = proc_destroy_inode, + .drop_inode = generic_delete_inode, + .evict_inode = proc_evict_inode, + .statfs = simple_statfs, ++ .remount_fs = proc_remount, ++ .show_options = proc_show_options, + }; + + static void __pde_users_dec(struct proc_dir_entry *pde) +diff --git a/fs/proc/internal.h b/fs/proc/internal.h +index 7838e5c..2925775 100644 +--- a/fs/proc/internal.h ++++ b/fs/proc/internal.h +@@ -117,6 +117,7 @@ void pde_put(struct proc_dir_entry *pde); + + int proc_fill_super(struct super_block *); + struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *); ++int proc_remount(struct super_block *sb, int *flags, char *data); + + /* + * These are generic /proc routines that use the internal +diff --git a/fs/proc/root.c b/fs/proc/root.c +index 03102d9..6a8ac1d 100644 +--- a/fs/proc/root.c ++++ b/fs/proc/root.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #include "internal.h" + +@@ -36,6 +37,48 @@ static int proc_set_super(struct super_block *sb, void *data) + return err; + } + ++enum { ++ Opt_err, ++}; ++ ++static const match_table_t tokens = { ++ {Opt_err, NULL}, ++}; ++ ++static int proc_parse_options(char *options, struct pid_namespace *pid) ++{ ++ char *p; ++ substring_t args[MAX_OPT_ARGS]; ++ ++ pr_debug("proc: options = %s\n", options); ++ ++ if (!options) ++ return 1; ++ ++ while ((p = strsep(&options, ",")) != NULL) { ++ int token; ++ if (!*p) ++ continue; ++ ++ args[0].to = args[0].from = 0; ++ token = match_token(p, tokens, args); ++ switch (token) { ++ default: ++ pr_err("proc: unrecognized mount option \"%s\" " ++ "or missing value\n", p); ++ return 0; ++ } ++ } ++ ++ return 1; ++} ++ ++int proc_remount(struct super_block *sb, int *flags, char *data) ++{ ++ struct pid_namespace *pid = sb->s_fs_info; ++ return !proc_parse_options(data, pid); ++} ++ + static struct dentry *proc_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data) + { +@@ -43,11 +86,15 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, + struct super_block *sb; + struct pid_namespace *ns; + struct proc_inode *ei; ++ char *options; + +- if (flags & MS_KERNMOUNT) ++ if (flags & MS_KERNMOUNT) { + ns = (struct pid_namespace *)data; +- else ++ options = NULL; ++ } else { + ns = current->nsproxy->pid_ns; ++ options = data; ++ } + + sb = sget(fs_type, proc_test_super, proc_set_super, ns); + if (IS_ERR(sb)) +@@ -55,6 +102,10 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, + + if (!sb->s_root) { + sb->s_flags = flags; ++ if (!proc_parse_options(options, ns)) { ++ deactivate_locked_super(sb); ++ return ERR_PTR(-EINVAL); ++ } + err = proc_fill_super(sb); + if (err) { + deactivate_locked_super(sb); +-- +1.7.7.5 + From 70bec5f650c3b9f38be13d21530aa4fe893bb352 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 18 Jan 2012 20:00:25 -0500 Subject: [PATCH 228/487] Fix broken procfs backport (rhbz 782961) --- kernel.spec | 5 ++++- procfs-add-hidepid-and-gid-mount-options.patch | 4 ++-- procfs-parse-mount-options.patch | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/kernel.spec b/kernel.spec index bda9dbf32..3dd83a415 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2398,6 +2398,9 @@ fi # and build. %changelog +* Wed Jan 18 2012 Josh Boyer 3.1.10-2 +- Fix broken procfs backport (rhbz 782961) + * Wed Jan 18 2012 Josh Boyer 3.1.10-1 - Linux 3.1.10 - /proc/pid/* information leak (rhbz 782686) diff --git a/procfs-add-hidepid-and-gid-mount-options.patch b/procfs-add-hidepid-and-gid-mount-options.patch index 24156b0dc..803f77d4c 100644 --- a/procfs-add-hidepid-and-gid-mount-options.patch +++ b/procfs-add-hidepid-and-gid-mount-options.patch @@ -262,9 +262,9 @@ index 27c762f..84fd323 100644 +++ b/fs/proc/inode.c @@ -106,6 +106,14 @@ void __init proc_init_inodecache(void) - static int proc_show_options(struct seq_file *seq, struct dentry *root) + static int proc_show_options(struct seq_file *seq, struct vfsmount *vfs) { -+ struct super_block *sb = root->d_sb; ++ struct super_block *sb = vfs->mnt_sb; + struct pid_namespace *pid = sb->s_fs_info; + + if (pid->pid_gid) diff --git a/procfs-parse-mount-options.patch b/procfs-parse-mount-options.patch index 99684c4bd..0187a1d44 100644 --- a/procfs-parse-mount-options.patch +++ b/procfs-parse-mount-options.patch @@ -50,7 +50,7 @@ index 51a1766..27c762f 100644 init_once); } -+static int proc_show_options(struct seq_file *seq, struct dentry *root) ++static int proc_show_options(struct seq_file *seq, struct vfsmount *vfs) +{ + return 0; +} From 9f353831c7abcf21c2200b8edb487e0ac2e12b49 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 19 Jan 2012 10:15:41 -0500 Subject: [PATCH 229/487] Pass the same make options to compat-wireless as to the base kernel --- kernel.spec | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 3dd83a415..4c328ea89 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1934,9 +1934,10 @@ BuildKernel() { cd ../compat-wireless-%{cwversion}/ - make KLIB_BUILD=../linux-%{kversion}.%{_target_cpu} \ + make -s ARCH=$Arch V=1 %{?_smp_mflags} \ + KLIB_BUILD=../linux-%{kversion}.%{_target_cpu} \ KMODPATH_ARG="INSTALL_MOD_PATH=$RPM_BUILD_ROOT" \ - KMODDIR="backports" install-modules + KMODDIR="backports" install-modules %{?sparse_mflags} # mark modules executable so that strip-to-file can strip them find $RPM_BUILD_ROOT/lib/modules/$KernelVer/backports -name "*.ko" \ @@ -2398,6 +2399,9 @@ fi # and build. %changelog +* Thu Jan 19 2012 John W. Linville +- Pass the same make options to compat-wireless as to the base kernel + * Wed Jan 18 2012 Josh Boyer 3.1.10-2 - Fix broken procfs backport (rhbz 782961) From 1045154ecffe73ae898099f24ffab89f5ff62a70 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 19 Jan 2012 21:29:56 -0500 Subject: [PATCH 230/487] Rebase to 3.2.1 --- .gitignore | 1 + ...direct-reclaim-for-higher-order-allo.patch | 54 - ...passthrough-ioctls-on-partition-devs.patch | 165 -- Bluetooth-Add-support-for-BCM20702A0.patch | 15 - ...m-Set-input-bits-before-registration.patch | 131 - Makefile | 177 +- Makefile.config | 11 +- add-appleir-usb-driver.patch | 701 ------ alps.patch | 243 +- asus-laptop-3.2-backport.patch | 592 ----- b44-Use-dev_kfree_skb_irq-in-b44_tx.patch | 62 - ...r-vlan-pkts-not-received-in-promisco.patch | 63 - cciss-fix-irqf-shared.patch | 39 - compat-wireless-config-fixups.patch | 40 +- ...at-wireless-pr_fmt-warning-avoidance.patch | 216 +- ...8192cu-Fix-WARNING-on-suspend-resume.patch | 48 +- config-arm-generic | 29 +- config-arm-highbank | 13 + config-arm-imx | 3 + config-arm-kirkwood | 2 +- config-arm-omap-generic | 64 +- config-arm-tegra | 7 + config-backports | 5 + config-debug | 5 +- config-generic | 994 ++++---- config-ia64-generic | 204 -- config-nodebug | 5 +- config-powerpc-generic | 75 +- config-powerpc32-generic | 64 +- config-powerpc64 | 67 +- config-s390x | 2 + config-sparc64-generic | 1 + config-x86-32-generic | 9 +- config-x86-generic | 17 +- config-x86_64-generic | 15 +- drm-i915-sdvo-lvds-is-digital.patch | 83 - drm-lower-severity-radeon-lockup.diff | 13 - elantech.patch | 2180 ----------------- epoll-limit-paths.patch | 8 +- hvcs_pi_buf_alloc.patch | 43 - kernel.spec | 162 +- linux-2.6-32bit-mmap-exec-randomization.patch | 27 +- linux-2.6-debug-taint-vm.patch | 51 - linux-2.6-e1000-ich9-montevina.patch | 28 +- linux-2.6-i386-nx-emulation.patch | 22 - linux-2.6-intel-iommu-igfx.patch | 35 +- ...t-information-leak-after-failed-read.patch | 41 - media-dib0700-correct-error-message.patch | 103 - net-sky2-88e8059-fix-link-speed.patch | 42 - nfs-client-freezer.patch | 112 +- rcu-avoid-just-onlined-cpu-resched.patch | 47 - rcutree-avoid-false-quiescent-states.patch | 67 - rtl8192cu-Fix-WARNING-on-suspend-resume.patch | 54 +- samsung-laptop-brightness-fixes-3.2.patch | 238 -- sources | 4 +- udlfb-bind-framebuffer-to-interface.patch | 33 - utrace.patch | 1652 ++++++------- x86-code-dump-fix-truncation.patch | 73 - 58 files changed, 1748 insertions(+), 7509 deletions(-) delete mode 100644 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch delete mode 100644 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch delete mode 100644 Bluetooth-Add-support-for-BCM20702A0.patch delete mode 100644 HID-wacom-Set-input-bits-before-registration.patch delete mode 100644 add-appleir-usb-driver.patch delete mode 100644 asus-laptop-3.2-backport.patch delete mode 100644 b44-Use-dev_kfree_skb_irq-in-b44_tx.patch delete mode 100644 be2net-non-member-vlan-pkts-not-received-in-promisco.patch delete mode 100644 cciss-fix-irqf-shared.patch delete mode 100644 config-ia64-generic delete mode 100644 drm-i915-sdvo-lvds-is-digital.patch delete mode 100644 drm-lower-severity-radeon-lockup.diff delete mode 100644 elantech.patch delete mode 100644 hvcs_pi_buf_alloc.patch delete mode 100644 linux-2.6-debug-taint-vm.patch delete mode 100644 loop-prevent-information-leak-after-failed-read.patch delete mode 100644 media-dib0700-correct-error-message.patch delete mode 100644 net-sky2-88e8059-fix-link-speed.patch delete mode 100644 rcu-avoid-just-onlined-cpu-resched.patch delete mode 100644 rcutree-avoid-false-quiescent-states.patch delete mode 100644 samsung-laptop-brightness-fixes-3.2.patch delete mode 100644 udlfb-bind-framebuffer-to-interface.patch delete mode 100644 x86-code-dump-fix-truncation.patch diff --git a/.gitignore b/.gitignore index edb6bec0a..a23ef2db8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ clog +*.xz *.bz2 *.rpm *.orig diff --git a/0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch b/0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch deleted file mode 100644 index 77777f012..000000000 --- a/0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 6b7025ea927d290a59d2772828435c1893f0267f Mon Sep 17 00:00:00 2001 -From: Rik van Riel -Date: Fri, 7 Oct 2011 16:17:22 +0100 -Subject: [PATCH 1/2] mm: vmscan: Limit direct reclaim for higher order - allocations - -When suffering from memory fragmentation due to unfreeable pages, -THP page faults will repeatedly try to compact memory. Due to the -unfreeable pages, compaction fails. - -Needless to say, at that point page reclaim also fails to create -free contiguous 2MB areas. However, that doesn't stop the current -code from trying, over and over again, and freeing a minimum of 4MB -(2UL << sc->order pages) at every single invocation. - -This resulted in my 12GB system having 2-3GB free memory, a -corresponding amount of used swap and very sluggish response times. - -This can be avoided by having the direct reclaim code not reclaim from -zones that already have plenty of free memory available for compaction. - -If compaction still fails due to unmovable memory, doing additional -reclaim will only hurt the system, not help. - -Signed-off-by: Rik van Riel -Signed-off-by: Mel Gorman ---- - mm/vmscan.c | 10 ++++++++++ - 1 files changed, 10 insertions(+), 0 deletions(-) - -diff --git a/mm/vmscan.c b/mm/vmscan.c -index 6072d74..8c03534 100644 ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -2022,6 +2022,16 @@ static void shrink_zones(int priority, struct zonelist *zonelist, - continue; - if (zone->all_unreclaimable && priority != DEF_PRIORITY) - continue; /* Let kswapd poll it */ -+ if (COMPACTION_BUILD) { -+ /* -+ * If we already have plenty of memory free -+ * for compaction, don't free any more. -+ */ -+ if (sc->order > PAGE_ALLOC_COSTLY_ORDER && -+ (compaction_suitable(zone, sc->order) || -+ compaction_deferred(zone))) -+ continue; -+ } - /* - * This steals pages from memory cgroups over softlimit - * and returns the number of reclaimed pages and --- -1.7.6.4 - diff --git a/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch b/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch deleted file mode 100644 index 942e2a007..000000000 --- a/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch +++ /dev/null @@ -1,165 +0,0 @@ -From e773daff833c61e0ce22d62b7d1bb7b82f4222d0 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 16 Jan 2012 17:12:59 +0100 -Subject: [PATCH 2/3] block: fail SCSI passthrough ioctls on partition devices - -Linux allows executing the SG_IO ioctl on a partition or LVM volume, and -will pass the command to the underlying block device. This is -well-known, but it is also a large security problem when (via Unix -permissions, ACLs, SELinux or a combination thereof) a program or user -needs to be granted access only to part of the disk. - -This patch lets partitions forward a small set of harmless ioctls; -others are logged with printk so that we can see which ioctls are -actually sent. In my tests only CDROM_GET_CAPABILITY actually occurred. -Of course it was being sent to a (partition on a) hard disk, so it would -have failed with ENOTTY and the patch isn't changing anything in -practice. Still, I'm treating it specially to avoid spamming the logs. - -In principle, this restriction should include programs running with -CAP_SYS_RAWIO. If for example I let a program access /dev/sda2 and -/dev/sdb, it still should not be able to read/write outside the -boundaries of /dev/sda2 independent of the capabilities. However, for -now programs with CAP_SYS_RAWIO will still be allowed to send the -ioctls. Their actions will still be logged. - -This patch does not affect the non-libata IDE driver. That driver -however already tests for bd != bd->bd_contains before issuing some -ioctl; it could be restricted further to forbid these ioctls even for -programs running with CAP_SYS_ADMIN/CAP_SYS_RAWIO. - -[ Cherry picked from 3ed4e7ba4be8c72051d87dcb2dec279d97a18d41 - - Changes with respect to 3.3: return -ENOTTY from scsi_verify_blk_ioctl - and -ENOIOCTLCMD from sd_compat_ioctl. ] - -Cc: stable@kernel.org -Cc: linux-scsi@vger.kernel.org -Cc: Jens Axboe -Cc: James Bottomley -Signed-off-by: Paolo Bonzini -[ Make it also print the command name when warning - Linus ] -Signed-off-by: Linus Torvalds ---- - block/scsi_ioctl.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ - drivers/scsi/sd.c | 11 +++++++++-- - include/linux/blkdev.h | 1 + - 3 files changed, 55 insertions(+), 2 deletions(-) - -diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c -index 57ac937..5ef1f4c 100644 ---- a/block/scsi_ioctl.c -+++ b/block/scsi_ioctl.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -691,9 +692,53 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod - } - EXPORT_SYMBOL(scsi_cmd_ioctl); - -+int scsi_verify_blk_ioctl(struct block_device *bd, unsigned int cmd) -+{ -+ if (bd && bd == bd->bd_contains) -+ return 0; -+ -+ /* Actually none of these is particularly useful on a partition, -+ * but they are safe. -+ */ -+ switch (cmd) { -+ case SCSI_IOCTL_GET_IDLUN: -+ case SCSI_IOCTL_GET_BUS_NUMBER: -+ case SCSI_IOCTL_GET_PCI: -+ case SCSI_IOCTL_PROBE_HOST: -+ case SG_GET_VERSION_NUM: -+ case SG_SET_TIMEOUT: -+ case SG_GET_TIMEOUT: -+ case SG_GET_RESERVED_SIZE: -+ case SG_SET_RESERVED_SIZE: -+ case SG_EMULATED_HOST: -+ return 0; -+ case CDROM_GET_CAPABILITY: -+ /* Keep this until we remove the printk below. udev sends it -+ * and we do not want to spam dmesg about it. CD-ROMs do -+ * not have partitions, so we get here only for disks. -+ */ -+ return -ENOTTY; -+ default: -+ break; -+ } -+ -+ /* In particular, rule out all resets and host-specific ioctls. */ -+ printk_ratelimited(KERN_WARNING -+ "%s: sending ioctl %x to a partition!\n", current->comm, cmd); -+ -+ return capable(CAP_SYS_RAWIO) ? 0 : -ENOTTY; -+} -+EXPORT_SYMBOL(scsi_verify_blk_ioctl); -+ - int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode, - unsigned int cmd, void __user *arg) - { -+ int ret; -+ -+ ret = scsi_verify_blk_ioctl(bd, cmd); -+ if (ret < 0) -+ return ret; -+ - return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg); - } - EXPORT_SYMBOL(scsi_cmd_blk_ioctl); -diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c -index c88885d..7d8b5d8 100644 ---- a/drivers/scsi/sd.c -+++ b/drivers/scsi/sd.c -@@ -1073,6 +1073,10 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, - SCSI_LOG_IOCTL(1, printk("sd_ioctl: disk=%s, cmd=0x%x\n", - disk->disk_name, cmd)); - -+ error = scsi_verify_blk_ioctl(bdev, cmd); -+ if (error < 0) -+ return error; -+ - /* - * If we are in the middle of error recovery, don't let anyone - * else try and use this device. Also, if error recovery fails, it -@@ -1265,6 +1269,11 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) - { - struct scsi_device *sdev = scsi_disk(bdev->bd_disk)->device; -+ int ret; -+ -+ ret = scsi_verify_blk_ioctl(bdev, cmd); -+ if (ret < 0) -+ return -ENOIOCTLCMD; - - /* - * If we are in the middle of error recovery, don't let anyone -@@ -1276,8 +1285,6 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, - return -ENODEV; - - if (sdev->host->hostt->compat_ioctl) { -- int ret; -- - ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg); - - return ret; -diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h -index aa829a4..8b7a19e 100644 ---- a/include/linux/blkdev.h -+++ b/include/linux/blkdev.h -@@ -675,6 +675,7 @@ extern int blk_insert_cloned_request(struct request_queue *q, - struct request *rq); - extern void blk_delay_queue(struct request_queue *, unsigned long); - extern void blk_recount_segments(struct request_queue *, struct bio *); -+extern int scsi_verify_blk_ioctl(struct block_device *, unsigned int); - extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t, - unsigned int, void __user *); - extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t, --- -1.7.7.5 - diff --git a/Bluetooth-Add-support-for-BCM20702A0.patch b/Bluetooth-Add-support-for-BCM20702A0.patch deleted file mode 100644 index 1e579342c..000000000 --- a/Bluetooth-Add-support-for-BCM20702A0.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c -index f9b7260..28a5876 100644 ---- a/drivers/bluetooth/btusb.c -+++ b/drivers/bluetooth/btusb.c -@@ -100,6 +100,10 @@ static struct usb_device_id btusb_table[] = { - /* Canyon CN-BTU1 with HID interfaces */ - { USB_DEVICE(0x0c10, 0x0000) }, - -+ /* Broadcom BCM20702A0 */ -+ { USB_DEVICE(0x0a5c, 0x21e3) }, -+ { USB_DEVICE(0x413c, 0x8197) }, -+ - { } /* Terminating entry */ - }; - diff --git a/HID-wacom-Set-input-bits-before-registration.patch b/HID-wacom-Set-input-bits-before-registration.patch deleted file mode 100644 index 3cd178631..000000000 --- a/HID-wacom-Set-input-bits-before-registration.patch +++ /dev/null @@ -1,131 +0,0 @@ -From b28ae436288861916de0019a81b9817366fe35a9 Mon Sep 17 00:00:00 2001 -From: David Herrmann -Date: Sat, 8 Oct 2011 23:20:17 +0200 -Subject: [PATCH] HID: wacom: Set input bits before registration - -We shouldn't change the event flags of input devices after they get registered. -Otherwise, udev will not get notified of these flags and cannot setup the -devices properly. -This fixes the probing to set the input event flags on the input_mapped callback -instead of the probe function. - -Reported-by: Bastien Nocera -Signed-off-by: David Herrmann -Tested-by: Bastien Nocera -Signed-off-by: Bastien Nocera -Signed-off-by: Jiri Kosina ---- - drivers/hid/hid-wacom.c | 80 +++++++++++++++++++++++++--------------------- - 1 files changed, 43 insertions(+), 37 deletions(-) - -diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c -index 72ca689..1492728 100644 ---- a/drivers/hid/hid-wacom.c -+++ b/drivers/hid/hid-wacom.c -@@ -304,11 +304,51 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, - return 1; - } - -+static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, -+ struct hid_field *field, struct hid_usage *usage, unsigned long **bit, -+ int *max) -+{ -+ struct input_dev *input = hi->input; -+ -+ __set_bit(INPUT_PROP_POINTER, input->propbit); -+ -+ /* Basics */ -+ input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL); -+ -+ __set_bit(REL_WHEEL, input->relbit); -+ -+ __set_bit(BTN_TOOL_PEN, input->keybit); -+ __set_bit(BTN_TOUCH, input->keybit); -+ __set_bit(BTN_STYLUS, input->keybit); -+ __set_bit(BTN_STYLUS2, input->keybit); -+ __set_bit(BTN_LEFT, input->keybit); -+ __set_bit(BTN_RIGHT, input->keybit); -+ __set_bit(BTN_MIDDLE, input->keybit); -+ -+ /* Pad */ -+ input->evbit[0] |= BIT(EV_MSC); -+ -+ __set_bit(MSC_SERIAL, input->mscbit); -+ -+ __set_bit(BTN_0, input->keybit); -+ __set_bit(BTN_1, input->keybit); -+ __set_bit(BTN_TOOL_FINGER, input->keybit); -+ -+ /* Distance, rubber and mouse */ -+ __set_bit(BTN_TOOL_RUBBER, input->keybit); -+ __set_bit(BTN_TOOL_MOUSE, input->keybit); -+ -+ input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); -+ input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); -+ input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); -+ input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); -+ -+ return 0; -+} -+ - static int wacom_probe(struct hid_device *hdev, - const struct hid_device_id *id) - { -- struct hid_input *hidinput; -- struct input_dev *input; - struct wacom_data *wdata; - int ret; - -@@ -370,41 +410,6 @@ static int wacom_probe(struct hid_device *hdev, - goto err_ac; - } - #endif -- hidinput = list_entry(hdev->inputs.next, struct hid_input, list); -- input = hidinput->input; -- -- __set_bit(INPUT_PROP_POINTER, input->propbit); -- -- /* Basics */ -- input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL); -- -- __set_bit(REL_WHEEL, input->relbit); -- -- __set_bit(BTN_TOOL_PEN, input->keybit); -- __set_bit(BTN_TOUCH, input->keybit); -- __set_bit(BTN_STYLUS, input->keybit); -- __set_bit(BTN_STYLUS2, input->keybit); -- __set_bit(BTN_LEFT, input->keybit); -- __set_bit(BTN_RIGHT, input->keybit); -- __set_bit(BTN_MIDDLE, input->keybit); -- -- /* Pad */ -- input->evbit[0] |= BIT(EV_MSC); -- -- __set_bit(MSC_SERIAL, input->mscbit); -- -- __set_bit(BTN_0, input->keybit); -- __set_bit(BTN_1, input->keybit); -- __set_bit(BTN_TOOL_FINGER, input->keybit); -- -- /* Distance, rubber and mouse */ -- __set_bit(BTN_TOOL_RUBBER, input->keybit); -- __set_bit(BTN_TOOL_MOUSE, input->keybit); -- -- input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); -- input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); -- input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); -- input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); - - return 0; - -@@ -448,6 +453,7 @@ static struct hid_driver wacom_driver = { - .probe = wacom_probe, - .remove = wacom_remove, - .raw_event = wacom_raw_event, -+ .input_mapped = wacom_input_mapped, - }; - - static int __init wacom_init(void) --- -1.7.7.1 - diff --git a/Makefile b/Makefile index 3e9e3a8fa..5b7b72450 100644 --- a/Makefile +++ b/Makefile @@ -17,15 +17,16 @@ help: include Makefile.config -ifndef KVERSION -KVERSION := $(shell awk '$$1 == "%define" && $$2 == "base_sublevel" { \ - print "2.6." $$3 \ - }' $(SPECFILE)) -endif - prep: fedpkg -v prep --arch=$(PREPARCH) +noarch: + fedpkg -v local --arch=noarch + +# 'make local' also needs to build the noarch firmware package +local: noarch + fedpkg -v local + extremedebug: @perl -pi -e 's/# CONFIG_DEBUG_PAGEALLOC is not set/CONFIG_DEBUG_PAGEALLOC=y/' config-nodebug @@ -46,6 +47,7 @@ debug: @perl -pi -e 's/# CONFIG_FAIL_PAGE_ALLOC is not set/CONFIG_FAIL_PAGE_ALLOC=y/' config-nodebug @perl -pi -e 's/# CONFIG_FAIL_IO_TIMEOUT is not set/CONFIG_FAIL_IO_TIMEOUT=y/' config-nodebug @perl -pi -e 's/# CONFIG_FAIL_MAKE_REQUEST is not set/CONFIG_FAIL_MAKE_REQUEST=y/' config-nodebug + @perl -pi -e 's/# CONFIG_FAIL_MMC_REQUEST is not set/CONFIG_FAIL_MMC_REQUEST=y/' config-nodebug @perl -pi -e 's/# CONFIG_FAULT_INJECTION_DEBUG_FS is not set/CONFIG_FAULT_INJECTION_DEBUG_FS=y/' config-nodebug @perl -pi -e 's/# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set/CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_SG is not set/CONFIG_DEBUG_SG=y/' config-nodebug @@ -79,7 +81,6 @@ debug: @perl -pi -e 's/# CONFIG_ATH_DEBUG is not set/CONFIG_ATH_DEBUG=y/' config-nodebug @perl -pi -e 's/# CONFIG_CARL9170_DEBUGFS is not set/CONFIG_CARL9170_DEBUGFS=y/' config-nodebug @perl -pi -e 's/# CONFIG_IWLWIFI_DEVICE_TRACING is not set/CONFIG_IWLWIFI_DEVICE_TRACING=y/' config-nodebug - @perl -pi -e 's/# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set/CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y/' config-nodebug @perl -pi -e 's/# CONFIG_DMADEVICES_DEBUG is not set/CONFIG_DMADEVICES_DEBUG=y/' config-nodebug @perl -pi -e 's/# CONFIG_DMADEVICES_VDEBUG is not set/CONFIG_DMADEVICES_VDEBUG=y/' config-nodebug @perl -pi -e 's/# CONFIG_CEPH_LIB_PRETTYDEBUG is not set/CONFIG_CEPH_LIB_PRETTYDEBUG=y/' config-nodebug @@ -91,21 +92,21 @@ debug: @perl -pi -e 's/# CONFIG_TEST_LIST_SORT is not set/CONFIG_TEST_LIST_SORT=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_ATOMIC_SLEEP is not set/CONFIG_DEBUG_ATOMIC_SLEEP=y/' config-nodebug @perl -pi -e 's/# CONFIG_DETECT_HUNG_TASK is not set/CONFIG_DETECT_HUNG_TASK=y/' config-nodebug - - @perl -pi -e 's/# CONFIG_DEBUG_SET_MODULE_RONX is not set/CONFIG_DEBUG_SET_MODULE_RONX=y/' config-nodebug + @perl -pi -e 's/# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set/CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y/' config-nodebug + @perl -pi -e 's/# CONFIG_DEBUG_KMEMLEAK is not set/CONFIG_DEBUG_KMEMLEAK=y/' config-nodebug @# just in case we're going from extremedebug -> debug @perl -pi -e 's/CONFIG_DEBUG_PAGEALLOC=y/# CONFIG_DEBUG_PAGEALLOC is not set/' config-nodebug - @perl -pi -e 's/CONFIG_NR_CPUS=256/CONFIG_NR_CPUS=512/' config-x86_64-generic + @perl -pi -e 's/# CONFIG_MAXSMP is not set/CONFIG_MAXSMP=y/' config-x86-generic + + # Try out UAS in rawhide builds. + @perl -pi -e 's/# CONFIG_USB_UAS is not set/CONFIG_USB_UAS=m/' config-generic @perl -pi -e 's/^%define debugbuildsenabled 1/%define debugbuildsenabled 0/' kernel.spec @perl -pi -e 's/^%define rawhide_skip_docs 0/%define rawhide_skip_docs 1/' kernel.spec + @rpmdev-bumpspec -c "Reenable debugging options." kernel.spec -nodebuginfo: - @perl -pi -e 's/^%define with_debuginfo %\{\?_without_debuginfo: 0\} %\{\?\!_without_debuginfo: 1\}/%define with_debuginfo %\{\?_without_debuginfo: 0\} %\{\?\!_without_debuginfo: 0\}/' kernel.spec -nodebug: release - @perl -pi -e 's/^%define debugbuildsenabled 1/%define debugbuildsenabled 0/' kernel.spec release: @perl -pi -e 's/CONFIG_SLUB_DEBUG_ON=y/# CONFIG_SLUB_DEBUG_ON is not set/' config-nodebug @perl -pi -e 's/CONFIG_LOCK_STAT=y/# CONFIG_LOCK_STAT is not set/' config-nodebug @@ -123,6 +124,7 @@ release: @perl -pi -e 's/CONFIG_FAIL_PAGE_ALLOC=y/# CONFIG_FAIL_PAGE_ALLOC is not set/' config-nodebug @perl -pi -e 's/CONFIG_FAIL_IO_TIMEOUT=y/# CONFIG_FAIL_IO_TIMEOUT is not set/' config-nodebug @perl -pi -e 's/CONFIG_FAIL_MAKE_REQUEST=y/# CONFIG_FAIL_MAKE_REQUEST is not set/' config-nodebug + @perl -pi -e 's/CONFIG_FAIL_MMC_REQUEST=y/# CONFIG_FAIL_MMC_REQUEST is not set/' config-nodebug @perl -pi -e 's/CONFIG_FAULT_INJECTION_DEBUG_FS=y/# CONFIG_FAULT_INJECTION_DEBUG_FS is not set/' config-nodebug @perl -pi -e 's/CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y/# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_SG=y/# CONFIG_DEBUG_SG is not set/' config-nodebug @@ -156,7 +158,6 @@ release: @perl -pi -e 's/CONFIG_ATH_DEBUG=y/# CONFIG_ATH_DEBUG is not set/' config-nodebug @perl -pi -e 's/CONFIG_CARL9170_DEBUGFS=y/# CONFIG_CARL9170_DEBUGFS is not set/' config-nodebug @perl -pi -e 's/CONFIG_IWLWIFI_DEVICE_TRACING=y/# CONFIG_IWLWIFI_DEVICE_TRACING is not set/' config-nodebug - @perl -pi -e 's/CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y/# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set/' config-nodebug @perl -pi -e 's/CONFIG_DMADEVICES_DEBUG=y/# CONFIG_DMADEVICES_DEBUG is not set/' config-nodebug @perl -pi -e 's/CONFIG_DMADEVICES_VDEBUG=y/# CONFIG_DMADEVICES_VDEBUG is not set/' config-nodebug @perl -pi -e 's/CONFIG_CEPH_LIB_PRETTYDEBUG=y/# CONFIG_CEPH_LIB_PRETTYDEBUG is not set/' config-nodebug @@ -168,144 +169,36 @@ release: @perl -pi -e 's/CONFIG_TEST_LIST_SORT=y/# CONFIG_TEST_LIST_SORT is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_ATOMIC_SLEEP=y/# CONFIG_DEBUG_ATOMIC_SLEEP is not set/' config-nodebug @perl -pi -e 's/CONFIG_DETECT_HUNG_TASK=y/# CONFIG_DETECT_HUNG_TASK is not set/' config-nodebug + @perl -pi -e 's/CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y/# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set/' config-nodebug + @perl -pi -e 's/CONFIG_DEBUG_KMEMLEAK=y/# CONFIG_DEBUG_KMEMLEAK is not set/' config-nodebug - @perl -pi -e 's/CONFIG_DEBUG_SET_MODULE_RONX=y/# CONFIG_DEBUG_SET_MODULE_RONX is not set/' config-nodebug - + # Undo anything that make extremedebug might have set @perl -pi -e 's/CONFIG_DEBUG_PAGEALLOC=y/# CONFIG_DEBUG_PAGEALLOC is not set/' config-debug @perl -pi -e 's/CONFIG_DEBUG_PAGEALLOC=y/# CONFIG_DEBUG_PAGEALLOC is not set/' config-nodebug - @perl -pi -e 's/CONFIG_NR_CPUS=512/CONFIG_NR_CPUS=256/' config-x86_64-generic + # Change defaults back to sane things. + @perl -pi -e 's/CONFIG_MAXSMP=y/# CONFIG_MAXSMP is not set/' config-x86-generic + + # Disable UAS for release until it's ready. (#717633, #744099) + @perl -pi -e 's/CONFIG_USB_UAS=m/# CONFIG_USB_UAS is not set/' config-generic @perl -pi -e 's/^%define debugbuildsenabled 0/%define debugbuildsenabled 1/' kernel.spec @perl -pi -e 's/^%define rawhide_skip_docs 1/%define rawhide_skip_docs 0/' kernel.spec + @rpmdev-bumpspec -c "Disable debugging options." kernel.spec -reconfig: - @rm -f kernel-*-config - @VERSION=$(KVERSION) make -f Makefile.config configs - @scripts/reconfig.sh +nodebuginfo: + @perl -pi -e 's/^%define with_debuginfo %\{\?_without_debuginfo: 0\} %\{\?\!_without_debuginfo: 1\}/%define with_debuginfo %\{\?_without_debuginfo: 0\} %\{\?\!_without_debuginfo: 0\}/' kernel.spec +nodebug: release + @perl -pi -e 's/^%define debugbuildsenabled 1/%define debugbuildsenabled 0/' kernel.spec unused-kernel-patches: @for f in *.patch; do if [ -e $$f ]; then (egrep -q "^Patch[[:digit:]]+:[[:space:]]+$$f" $(SPECFILE) || echo "Unused: $$f") && egrep -q "^ApplyPatch[[:space:]]+$$f|^ApplyOptionalPatch[[:space:]]+$$f" $(SPECFILE) || echo "Unapplied: $$f"; fi; done -# since i386 isn't a target... -compile compile-short: DIST_DEFINES += --target $(shell uname -m) +ifeq ($(MAKECMDGOALS),me a sandwich) +.PHONY: me a sandwich +me a: + @: -# 'make local' also needs to build the noarch firmware package -local: noarch - -# -# Hacks for building vanilla (unpatched) kernel rpms. -# Use "make vanilla-TARGET" like "make TARGET" (make vanilla-scratch-build). -# -vanilla-%: $(SPECFILE:.spec=-vanilla.spec) - @$(MAKE) $* SPECFILE=$< - -$(SPECFILE:.spec=-vanilla.spec): $(SPECFILE) - @rm -f $@ - (echo %define nopatches 1; cat $<) > $@ - -#scratch-build: NAME = $(shell rpm $(RPM_DEFINES) $(DIST_DEFINES) -q --qf "%{NAME}\n" --specfile $(SPECFILE)| head -1) -#scratch-build: test-srpm -# $(BUILD_CLIENT) build $(BUILD_FLAGS) --scratch $(TARGET) \ -# $(SRCRPMDIR)/$(NAME)-$(VERSION)-$(RELEASE).src.rpm - -# Dismal kludge for building via brew from cvs after "make vanilla-tag". -ifdef BEEHIVE_SRPM_BUILD -export CHECKOUT_TAG ?= $(shell sed s/^.// CVS/Tag) -tag-pattern = $(TAG_NAME)-$(TAG_VERSION)-0_%_$(TAG_RELEASE) -ifeq (,$(filter-out $(tag-pattern),$(CHECKOUT_TAG))) -variant := $(patsubst $(tag-pattern),%,$(CHECKOUT_TAG)) -srpm: SPECFILE := $(wildcard $(SPECFILE:.spec=-$(variant).spec) \ - $(SPECFILE:.spec=.t.$(variant).spec)) -srpm beehive-sprm: RELEASE := 0.$(variant).$(RELEASE) -endif -endif - -# -# Hacks for building kernel rpms from upstream code plus local GIT branches. -# Use "make git/BRANCH/TARGET" like "make TARGET". -# Use "make git/BRANCH-fedora/TARGET" to include Fedora patches on top. -# -ifndef GIT_SPEC -git/%: - @$(MAKE) GIT_SPEC=$(subst /,-,$(*D)) git-$(*F) -else -git-%: $(SPECFILE:.spec=.t.$(GIT_SPEC).spec) - @$(MAKE) GIT_SPEC= $* SPECFILE=$< -endif - -# -# Your git-branches.mk file can define GIT_DIR, e.g.: -# GIT_DIR = ${HOME}/kernel/.git -# Make sure GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL are also set -# or your rpm changelogs will look like crap. -# -# For each branch it can define a variable branch-BRANCH or tag-BRANCH -# giving the parent of BRANCH to diff against in a separate patch. If -# the parent is unknown, it will use $(branch-upstream) defaulting to -# "refs/remotes/upstream/master". -# -# Defining tag-BRANCH means the tag corresponds to an upstream patch in -# the sources file, so that is used instead of generating a patch with -# git. If there is no tag-upstream defined, it will figure out a vNNN -# tag or vNNN-gitN pseudo-tag from the last patch in the sources file. -# For example: -# tag-some-hacks = v2.6.21-rc5 -# branch-more-hacks = some-hacks -# Leads to patches: -# git diff v2.6.21-rc5..more-hacks > linux-2.6.21-rc5-some-hacks.patch -# git diff some-hacks..more-hacks > linux-2.6.21-rc5-more-hacks.patch -# Whereas having no git-branches.mk at all but doing -# "make GIT_DIR=... git/mybranch/test-srpm" does: -# id=`cat patch-2.6.21-rc5-git4.id` # auto-fetched via upstream file -# git diff $id..upstream > linux-2.6.21-rc5-git4-upstream.patch -# git diff upstream..mybranch > linux-2.6.21-rc5-git4-mybranch.patch -# If the upstream patch (or any branch patch) is empty it's left out. -# -git-branches.mk:; --include git-branches.mk - -branch-upstream ?= refs/remotes/upstream/master - -ifdef GIT_DIR -export GIT_DIR -export GIT_AUTHOR_NAME -export GIT_AUTHOR_EMAIL -gen-patches ?= gen-patches - -ifndef havespec -$(SPECFILE:.spec=.t.%-fedora.spec): $(SPECFILE) $(gen-patches) FORCE - ./$(gen-patches) --fedora < $< > $@ $(gen-patches-args) -$(SPECFILE:.spec=.t.%.spec): $(SPECFILE) $(gen-patches) FORCE - ./$(gen-patches) < $< > $@ $(gen-patches-args) -.PRECIOUS: $(SPECFILE:.spec=.t.%.spec) $(SPECFILE:.spec=.t.%-fedora.spec) -endif - -spec-%: $(SPECFILE:.spec=.t.%.spec) ; -$(SPECFILE):; -FORCE:; - -branch-of-* = $(firstword $(head-$*) $*) -gen-patches-args = --name $* v$(KVERSION) $(call heads,$(branch-of-*)) -define heads -$(if $(tag-$1),$(filter-out v$(KVERSION),$(tag-$1)),\ - $(call heads,$(firstword $(branch-$1) $(branch-upstream)))) $1 -endef - -files-%-fedora: - @echo $(SPECFILE:.spec=.t.$*-fedora.spec) - @$(call list-patches,$(branch-of-*)) -files-%: - @echo $(SPECFILE:.spec=.t.$*.spec) - @$(call list-patches,$(branch-of-*)) -define list-patches -$(if $(tag-$1),version=$(patsubst v%,%,$(tag-$1)),\ - $(call list-patches,$(firstword $(branch-$1) $(branch-upstream)))); \ -echo linux-$${version}-$(patsubst refs/remotes/%/master,%,$1).patch -endef - -ifndef tag-$(branch-upstream) -tag-$(branch-upstream) := $(shell \ - sed -n 's/^.* *//;s/\.bz2$$//;s/patch-/v/;/^v/h;$${g;p}' sources) -endif +sandwich: + @[ `id -u` -ne 0 ] && echo "What? Make it yourself." || echo Okay. endif diff --git a/Makefile.config b/Makefile.config index 223c793fe..331aa46b9 100644 --- a/Makefile.config +++ b/Makefile.config @@ -16,10 +16,9 @@ CONFIGFILES = \ $(CFG)-armv7hl-omap.config $(CFG)-armv7hl-tegra.config \ $(CFG)-ppc.config $(CFG)-ppc-smp.config \ $(CFG)-sparc64.config \ - $(CFG)-ppc64.config $(CFG)-ppc64-debug.config \ - $(CFG)-ia64.config + $(CFG)-ppc64.config $(CFG)-ppc64-debug.config -PLATFORMS = x86 x86_64 powerpc powerpc32 powerpc64 s390x ia64 sparc64 +PLATFORMS = x86 x86_64 powerpc powerpc32 powerpc64 s390x sparc64 TEMPFILES = $(addprefix temp-, $(addsuffix -generic, $(PLATFORMS))) configs: $(CONFIGFILES) @@ -88,9 +87,6 @@ temp-powerpc32-generic: config-powerpc32-generic temp-powerpc-generic temp-s390-generic: config-s390x temp-generic perl merge.pl $^ > $@ -temp-ia64-generic: config-ia64-generic temp-generic - perl merge.pl $^ > $@ - kernel-$(VERSION)-i686-PAE.config: config-i686-PAE temp-x86-32-generic perl merge.pl $^ i386 > $@ @@ -159,6 +155,3 @@ kernel-$(VERSION)-ppc.config: /dev/null temp-powerpc32-generic kernel-$(VERSION)-ppc-smp.config: config-powerpc32-smp temp-powerpc32-generic perl merge.pl $^ powerpc > $@ - -kernel-$(VERSION)-ia64.config: /dev/null temp-ia64-generic - perl merge.pl $^ ia64 > $@ diff --git a/add-appleir-usb-driver.patch b/add-appleir-usb-driver.patch deleted file mode 100644 index 0ab0ed6f4..000000000 --- a/add-appleir-usb-driver.patch +++ /dev/null @@ -1,701 +0,0 @@ -From e11e9e78799a7641fe0dc5289f35f2604a4b71a3 Mon Sep 17 00:00:00 2001 -From: Bastien Nocera -Date: Sun, 17 Jan 2010 00:40:15 +0000 -Subject: [PATCH] Input: add appleir USB driver - -This driver was originally written by James McKenzie, updated by -Greg Kroah-Hartman, further updated by myself, with suspend support -added. - -More recent versions of the IR receiver are also supported through -a patch by Alex Karpenko. The patch also adds support for the 2nd -and 5th generation of the controller, and the menu key on newer -brushed metal remotes. - -Tested on a MacbookAir1,1 - -Signed-off-by: Bastien Nocera ---- - Documentation/input/appleir.txt | 46 ++++ - drivers/hid/hid-apple.c | 4 - - drivers/hid/hid-core.c | 7 +- - drivers/hid/hid-ids.h | 5 +- - drivers/input/misc/Kconfig | 13 + - drivers/input/misc/Makefile | 1 + - drivers/input/misc/appleir.c | 519 +++++++++++++++++++++++++++++++++++++++ - 7 files changed, 588 insertions(+), 7 deletions(-) - create mode 100644 Documentation/input/appleir.txt - create mode 100644 drivers/input/misc/appleir.c - -diff --git a/Documentation/input/appleir.txt b/Documentation/input/appleir.txt -new file mode 100644 -index 0000000..db637fb ---- /dev/null -+++ b/Documentation/input/appleir.txt -@@ -0,0 +1,46 @@ -+Apple IR receiver Driver (appleir) -+---------------------------------- -+ Copyright (C) 2009 Bastien Nocera -+ -+The appleir driver is a kernel input driver to handle Apple's IR -+receivers (and associated remotes) in the kernel. -+ -+The driver is an input driver which only handles "official" remotes -+as built and sold by Apple. -+ -+Authors -+------- -+ -+James McKenzie (original driver) -+Alex Karpenko (05ac:8242 support) -+Greg Kroah-Hartman (cleanups and original submission) -+Bastien Nocera (further cleanups, brushed metal "enter" -+button support and suspend support) -+ -+Supported hardware -+------------------ -+ -+- All Apple laptops and desktops from 2005 onwards, except: -+ - the unibody Macbook (2009) -+ - Mac Pro (all versions) -+- Apple TV (all revisions prior to September 2010) -+ -+The remote will only support the 6 (old white) or 7 (brushed metal) buttons -+of the remotes as sold by Apple. See the next section if you want to use -+other remotes or want to use lirc with the device instead of the kernel driver. -+ -+Using lirc (native) instead of the kernel driver -+------------------------------------------------ -+ -+First, you will need to disable the kernel driver for the receiver. -+ -+This can be achieved by passing quirks to the usbhid driver. -+The quirk line would be: -+usbhid.quirks=0x05ac:0x8242:0x40000010 -+ -+With 0x05ac being the vendor ID (Apple, you shouldn't need to change this) -+With 0x8242 being the product ID (check the output of lsusb for your hardware) -+And 0x10 being "HID_QUIRK_HIDDEV_FORCE" and 0x40000000 being "HID_QUIRK_NO_IGNORE" -+ -+This should force the creation of a hiddev device for the receiver, and -+make it usable under lirc. -diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c -index bba05d0..0059d5a 100644 ---- a/drivers/hid/hid-apple.c -+++ b/drivers/hid/hid-apple.c -@@ -361,10 +361,6 @@ static void apple_remove(struct hid_device *hdev) - } - - static const struct hid_device_id apple_devices[] = { -- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL), -- .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT }, -- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4), -- .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE), - .driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL }, - -diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c -index baa25ad..abc5bd7 100644 ---- a/drivers/hid/hid-core.c -+++ b/drivers/hid/hid-core.c -@@ -1244,8 +1244,6 @@ static const struct hid_device_id hid_blacklist[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, USB_DEVICE_ID_ACTIONSTAR_1011) }, -- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) }, -- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) }, -@@ -1577,6 +1575,11 @@ static const struct hid_device_id hid_ignore_list[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)}, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)}, - { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, -diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h -index 11af537..360a5ca 100644 ---- a/drivers/hid/hid-ids.h -+++ b/drivers/hid/hid-ids.h -@@ -100,8 +100,11 @@ - #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b - #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a - #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b --#define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241 -+#define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 -+#define USB_DEVICE_ID_APPLE_IRCONTROL2 0x1440 -+#define USB_DEVICE_ID_APPLE_IRCONTROL3 0x8241 - #define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242 -+#define USB_DEVICE_ID_APPLE_IRCONTROL5 0x8243 - - #define USB_VENDOR_ID_ASUS 0x0486 - #define USB_DEVICE_ID_ASUS_T91MT 0x0185 -diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig -index 60de906..2f2f2e7 100644 ---- a/drivers/input/misc/Kconfig -+++ b/drivers/input/misc/Kconfig - help - Say Y here if you need accelerometer to work in polling mode. - -+config INPUT_APPLEIR -+ tristate "Apple infrared receiver (built in)" -+ depends on USB_ARCH_HAS_HCD -+ select USB -+ help -+ Say Y here if you want to use a Apple infrared remote control. All -+ the Apple computers from 2005 onwards include such a port, except -+ the unibody Macbook (2009), and Mac Pros. This receiver is also -+ used in the Apple TV set-top box prior to the 2010 model. -+ -+ To compile this driver as a module, choose M here: the module will -+ be called appleir. -+ - config INPUT_POWERMATE - tristate "Griffin PowerMate and Contour Jog support" - depends on USB_ARCH_HAS_HCD -diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile -index 1fe1f6c..d5ef2b9 100644 ---- a/drivers/input/misc/Makefile -+++ b/drivers/input/misc/Makefile -@@ -13,6 +13,7 @@ obj-$(CONFIG_INPUT_ADXL34X) += adxl34x.o - obj-$(CONFIG_INPUT_ADXL34X_I2C) += adxl34x-i2c.o - obj-$(CONFIG_INPUT_ADXL34X_SPI) += adxl34x-spi.o - obj-$(CONFIG_INPUT_APANEL) += apanel.o -+obj-$(CONFIG_INPUT_APPLEIR) += appleir.o - obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o - obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o - obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o -diff --git a/drivers/input/misc/appleir.c b/drivers/input/misc/appleir.c -new file mode 100644 -index 0000000..3817a3c ---- /dev/null -+++ b/drivers/input/misc/appleir.c -@@ -0,0 +1,519 @@ -+/* -+ * appleir: USB driver for the apple ir device -+ * -+ * Original driver written by James McKenzie -+ * Ported to recent 2.6 kernel versions by Greg Kroah-Hartman -+ * -+ * Copyright (C) 2006 James McKenzie -+ * Copyright (C) 2008 Greg Kroah-Hartman -+ * Copyright (C) 2008 Novell Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the Free -+ * Software Foundation, version 2. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_VERSION "v1.2" -+#define DRIVER_AUTHOR "James McKenzie" -+#define DRIVER_DESC "Apple infrared receiver driver" -+#define DRIVER_LICENSE "GPL" -+ -+MODULE_AUTHOR(DRIVER_AUTHOR); -+MODULE_DESCRIPTION(DRIVER_DESC); -+MODULE_LICENSE(DRIVER_LICENSE); -+ -+#define USB_VENDOR_ID_APPLE 0x05ac -+#define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 -+#define USB_DEVICE_ID_APPLE_IRCONTROL2 0x1440 -+#define USB_DEVICE_ID_APPLE_IRCONTROL3 0x8241 -+#define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242 -+#define USB_DEVICE_ID_APPLE_IRCONTROL5 0x8243 -+ -+#define URB_SIZE 32 -+ -+#define MAX_KEYS 9 -+#define MAX_KEYS_MASK (MAX_KEYS - 1) -+ -+#define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) -+ -+static int debug; -+module_param(debug, int, 0644); -+MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); -+ -+/* I have two devices both of which report the following */ -+/* 25 87 ee 83 0a + */ -+/* 25 87 ee 83 0c - */ -+/* 25 87 ee 83 09 << */ -+/* 25 87 ee 83 06 >> */ -+/* 25 87 ee 83 05 >" */ -+/* 25 87 ee 83 03 menu */ -+/* 26 00 00 00 00 for key repeat*/ -+ -+/* Thomas Glanzmann reports the following responses */ -+/* 25 87 ee ca 0b + */ -+/* 25 87 ee ca 0d - */ -+/* 25 87 ee ca 08 << */ -+/* 25 87 ee ca 07 >> */ -+/* 25 87 ee ca 04 >" */ -+/* 25 87 ee ca 02 menu */ -+/* 26 00 00 00 00 for key repeat*/ -+/* He also observes the following event sometimes */ -+/* sent after a key is release, which I interpret */ -+/* as a flat battery message */ -+/* 25 87 e0 ca 06 flat battery */ -+ -+/* Alexandre Karpenko reports the following responses for Device ID 0x8242 */ -+/* 25 87 ee 47 0b + */ -+/* 25 87 ee 47 0d - */ -+/* 25 87 ee 47 08 << */ -+/* 25 87 ee 47 07 >> */ -+/* 25 87 ee 47 04 >" */ -+/* 25 87 ee 47 02 menu */ -+/* 26 87 ee 47 ** for key repeat (** is the code of the key being held) */ -+ -+/* Bastien Nocera's "new" remote */ -+/* 25 87 ee 91 5f followed by -+ * 25 87 ee 91 05 gives you >" -+ * -+ * 25 87 ee 91 5c followed by -+ * 25 87 ee 91 05 gives you the middle button */ -+ -+static const unsigned short appleir_key_table[] = { -+ KEY_RESERVED, -+ KEY_MENU, -+ KEY_PLAYPAUSE, -+ KEY_FORWARD, -+ KEY_BACK, -+ KEY_VOLUMEUP, -+ KEY_VOLUMEDOWN, -+ KEY_ENTER, -+ KEY_RESERVED, -+}; -+ -+struct appleir { -+ struct input_dev *input_dev; -+ unsigned short keymap[ARRAY_SIZE(appleir_key_table)]; -+ u8 *data; -+ dma_addr_t dma_buf; -+ struct usb_device *usbdev; -+ unsigned int flags; -+ struct urb *urb; -+ struct timer_list key_up_timer; -+ int current_key; -+ int prev_key_idx; -+ char phys[32]; -+}; -+ -+static DEFINE_MUTEX(appleir_mutex); -+ -+enum { -+ APPLEIR_OPENED = 0x1, -+ APPLEIR_SUSPENDED = 0x2, -+}; -+ -+static struct usb_device_id appleir_ids[] = { -+ { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) }, -+ { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) }, -+ { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) }, -+ { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, -+ { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) }, -+ {} -+}; -+MODULE_DEVICE_TABLE(usb, appleir_ids); -+ -+static void dump_packet(struct appleir *appleir, char *msg, u8 *data, int len) -+{ -+ int i; -+ -+ printk(KERN_ERR "appleir: %s (%d bytes)", msg, len); -+ -+ for (i = 0; i < len; ++i) -+ printk(" %02x", data[i]); -+ printk(" (should be command %d)\n", (data[4] >> 1) & MAX_KEYS_MASK); -+} -+ -+static int get_key(int data) -+{ -+ switch (data) { -+ case 0x02: -+ case 0x03: -+ /* menu */ -+ return 1; -+ case 0x04: -+ case 0x05: -+ /* >" */ -+ return 2; -+ case 0x06: -+ case 0x07: -+ /* >> */ -+ return 3; -+ case 0x08: -+ case 0x09: -+ /* << */ -+ return 4; -+ case 0x0a: -+ case 0x0b: -+ /* + */ -+ return 5; -+ case 0x0c: -+ case 0x0d: -+ /* - */ -+ return 6; -+ case 0x5c: -+ /* Middle button, on newer remotes, -+ * part of a 2 packet-command */ -+ return -7; -+ default: -+ return -1; -+ } -+} -+ -+static void key_up(struct appleir *appleir, int key) -+{ -+ dbginfo(&appleir->input_dev->dev, "key %d up\n", key); -+ input_report_key(appleir->input_dev, key, 0); -+ input_sync(appleir->input_dev); -+} -+ -+static void key_down(struct appleir *appleir, int key) -+{ -+ dbginfo(&appleir->input_dev->dev, "key %d down\n", key); -+ input_report_key(appleir->input_dev, key, 1); -+ input_sync(appleir->input_dev); -+} -+ -+static void battery_flat(struct appleir *appleir) -+{ -+ dev_err(&appleir->input_dev->dev, "possible flat battery?\n"); -+} -+ -+static void key_up_tick(unsigned long data) -+{ -+ struct appleir *appleir = (struct appleir *)data; -+ -+ if (appleir->current_key) { -+ key_up(appleir, appleir->current_key); -+ appleir->current_key = 0; -+ } -+} -+ -+static void new_data(struct appleir *appleir, u8 *data, int len) -+{ -+ static const u8 keydown[] = { 0x25, 0x87, 0xee }; -+ static const u8 keyrepeat[] = { 0x26, }; -+ static const u8 flatbattery[] = { 0x25, 0x87, 0xe0 }; -+ -+ if (debug) -+ dump_packet(appleir, "received", data, len); -+ -+ if (len != 5) -+ return; -+ -+ if (!memcmp(data, keydown, sizeof(keydown))) { -+ int index; -+ -+ /* If we already have a key down, take it up before marking -+ this one down */ -+ if (appleir->current_key) -+ key_up(appleir, appleir->current_key); -+ -+ /* Handle dual packet commands */ -+ if (appleir->prev_key_idx > 0) -+ index = appleir->prev_key_idx; -+ else -+ index = get_key(data[4]); -+ -+ if (index > 0) { -+ appleir->current_key = appleir->keymap[index]; -+ -+ key_down(appleir, appleir->current_key); -+ /* Remote doesn't do key up, either pull them up, in the test -+ above, or here set a timer which pulls them up after 1/8 s */ -+ mod_timer(&appleir->key_up_timer, jiffies + HZ / 8); -+ appleir->prev_key_idx = 0; -+ return; -+ } else if (index == -7) { -+ /* Remember key for next packet */ -+ appleir->prev_key_idx = 0 - index; -+ return; -+ } -+ } -+ -+ appleir->prev_key_idx = 0; -+ -+ if (!memcmp(data, keyrepeat, sizeof(keyrepeat))) { -+ key_down(appleir, appleir->current_key); -+ /* Remote doesn't do key up, either pull them up, in the test -+ above, or here set a timer which pulls them up after 1/8 s */ -+ mod_timer(&appleir->key_up_timer, jiffies + HZ / 8); -+ return; -+ } -+ -+ if (!memcmp(data, flatbattery, sizeof(flatbattery))) { -+ battery_flat(appleir); -+ /* Fall through */ -+ } -+ -+ dump_packet(appleir, "unknown packet", data, len); -+} -+ -+static void appleir_urb(struct urb *urb) -+{ -+ struct appleir *appleir = urb->context; -+ int status = urb->status; -+ int retval; -+ -+ switch (status) { -+ case 0: -+ new_data(appleir, urb->transfer_buffer, urb->actual_length); -+ break; -+ case -ECONNRESET: -+ case -ENOENT: -+ case -ESHUTDOWN: -+ /* This urb is terminated, clean up */ -+ dbginfo(&appleir->input_dev->dev, "%s - urb shutting down with status: %d", __func__, -+ urb->status); -+ return; -+ default: -+ dbginfo(&appleir->input_dev->dev, "%s - nonzero urb status received: %d", __func__, -+ urb->status); -+ } -+ -+ retval = usb_submit_urb(urb, GFP_ATOMIC); -+ if (retval) -+ err("%s - usb_submit_urb failed with result %d", __func__, -+ retval); -+} -+ -+static int appleir_open(struct input_dev *dev) -+{ -+ struct appleir *appleir = input_get_drvdata(dev); -+ struct usb_interface *intf = usb_ifnum_to_if(appleir->usbdev, 0); -+ int r; -+ -+ r = usb_autopm_get_interface(intf); -+ if (r) { -+ dev_err(&intf->dev, -+ "%s(): usb_autopm_get_interface() = %d\n", __func__, r); -+ return r; -+ } -+ -+ mutex_lock(&appleir_mutex); -+ -+ if (usb_submit_urb(appleir->urb, GFP_ATOMIC)) { -+ r = -EIO; -+ goto fail; -+ } -+ -+ appleir->flags |= APPLEIR_OPENED; -+ -+ mutex_unlock(&appleir_mutex); -+ -+ usb_autopm_put_interface(intf); -+ -+ return 0; -+fail: -+ mutex_unlock(&appleir_mutex); -+ usb_autopm_put_interface(intf); -+ return r; -+} -+ -+static void appleir_close(struct input_dev *dev) -+{ -+ struct appleir *appleir = input_get_drvdata(dev); -+ -+ mutex_lock(&appleir_mutex); -+ -+ if (!(appleir->flags & APPLEIR_SUSPENDED)) { -+ usb_kill_urb(appleir->urb); -+ del_timer_sync(&appleir->key_up_timer); -+ } -+ -+ appleir->flags &= ~APPLEIR_OPENED; -+ -+ mutex_unlock(&appleir_mutex); -+} -+ -+static int appleir_probe(struct usb_interface *intf, -+ const struct usb_device_id *id) -+{ -+ struct usb_device *dev = interface_to_usbdev(intf); -+ struct usb_endpoint_descriptor *endpoint; -+ struct appleir *appleir = NULL; -+ struct input_dev *input_dev; -+ int retval = -ENOMEM; -+ int i; -+ -+ appleir = kzalloc(sizeof(struct appleir), GFP_KERNEL); -+ if (!appleir) -+ goto allocfail; -+ -+ appleir->data = usb_alloc_coherent(dev, URB_SIZE, GFP_KERNEL, -+ &appleir->dma_buf); -+ if (!appleir->data) -+ goto usbfail; -+ -+ appleir->urb = usb_alloc_urb(0, GFP_KERNEL); -+ if (!appleir->urb) -+ goto urbfail; -+ -+ appleir->usbdev = dev; -+ -+ input_dev = input_allocate_device(); -+ if (!input_dev) -+ goto inputfail; -+ -+ appleir->input_dev = input_dev; -+ -+ usb_make_path(dev, appleir->phys, sizeof(appleir->phys)); -+ strlcpy(appleir->phys, "/input0", sizeof(appleir->phys)); -+ -+ input_dev->name = "Apple Infrared Remote Controller"; -+ input_dev->phys = appleir->phys; -+ usb_to_input_id(dev, &input_dev->id); -+ input_dev->dev.parent = &intf->dev; -+ input_dev->keycode = appleir->keymap; -+ input_dev->keycodesize = sizeof(unsigned short); -+ input_dev->keycodemax = ARRAY_SIZE(appleir->keymap); -+ -+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); -+ -+ memcpy(appleir->keymap, appleir_key_table, sizeof(appleir->keymap)); -+ for (i = 0; i < ARRAY_SIZE(appleir_key_table); i++) -+ set_bit(appleir->keymap[i], input_dev->keybit); -+ clear_bit(KEY_RESERVED, input_dev->keybit); -+ -+ input_set_drvdata(input_dev, appleir); -+ input_dev->open = appleir_open; -+ input_dev->close = appleir_close; -+ -+ endpoint = &intf->cur_altsetting->endpoint[0].desc; -+ -+ usb_fill_int_urb(appleir->urb, dev, -+ usb_rcvintpipe(dev, endpoint->bEndpointAddress), -+ appleir->data, 8, -+ appleir_urb, appleir, endpoint->bInterval); -+ -+ appleir->urb->transfer_dma = appleir->dma_buf; -+ appleir->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; -+ -+ setup_timer(&appleir->key_up_timer, -+ key_up_tick, (unsigned long) appleir); -+ -+ retval = input_register_device(appleir->input_dev); -+ if (retval) -+ goto inputfail; -+ -+ usb_set_intfdata(intf, appleir); -+ -+ return 0; -+ -+inputfail: -+ input_free_device(appleir->input_dev); -+ -+urbfail: -+ usb_free_urb(appleir->urb); -+ -+usbfail: -+ usb_free_coherent(dev, URB_SIZE, appleir->data, -+ appleir->dma_buf); -+ -+allocfail: -+ kfree(appleir); -+ -+ return retval; -+} -+ -+static void appleir_disconnect(struct usb_interface *intf) -+{ -+ struct appleir *appleir = usb_get_intfdata(intf); -+ -+ usb_set_intfdata(intf, NULL); -+ input_unregister_device(appleir->input_dev); -+ usb_free_urb(appleir->urb); -+ usb_free_coherent(interface_to_usbdev(intf), URB_SIZE, -+ appleir->data, appleir->dma_buf); -+ kfree(appleir); -+} -+ -+static int appleir_suspend(struct usb_interface *interface, -+ pm_message_t message) -+{ -+ struct appleir *appleir = usb_get_intfdata(interface); -+ -+ mutex_lock(&appleir_mutex); -+ if (appleir->flags & APPLEIR_OPENED) -+ usb_kill_urb(appleir->urb); -+ -+ appleir->flags |= APPLEIR_SUSPENDED; -+ -+ mutex_unlock(&appleir_mutex); -+ -+ return 0; -+} -+ -+static int appleir_resume(struct usb_interface *interface) -+{ -+ struct appleir *appleir; -+ int r = 0; -+ -+ appleir = usb_get_intfdata(interface); -+ -+ mutex_lock(&appleir_mutex); -+ if (appleir->flags & APPLEIR_OPENED) { -+ struct usb_endpoint_descriptor *endpoint; -+ -+ endpoint = &interface->cur_altsetting->endpoint[0].desc; -+ usb_fill_int_urb(appleir->urb, appleir->usbdev, -+ usb_rcvintpipe(appleir->usbdev, endpoint->bEndpointAddress), -+ appleir->data, 8, -+ appleir_urb, appleir, endpoint->bInterval); -+ appleir->urb->transfer_dma = appleir->dma_buf; -+ appleir->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; -+ -+ /* And reset the USB device */ -+ if (usb_submit_urb(appleir->urb, GFP_ATOMIC)) -+ r = -EIO; -+ } -+ -+ appleir->flags &= ~APPLEIR_SUSPENDED; -+ -+ mutex_unlock(&appleir_mutex); -+ -+ return r; -+} -+ -+static struct usb_driver appleir_driver = { -+ .name = "appleir", -+ .probe = appleir_probe, -+ .disconnect = appleir_disconnect, -+ .suspend = appleir_suspend, -+ .resume = appleir_resume, -+ .reset_resume = appleir_resume, -+ .id_table = appleir_ids, -+}; -+ -+static int __init appleir_init(void) -+{ -+ return usb_register(&appleir_driver); -+} -+ -+static void __exit appleir_exit(void) -+{ -+ usb_deregister(&appleir_driver); -+} -+ -+module_init(appleir_init); -+module_exit(appleir_exit); --- -1.7.2.2 - diff --git a/alps.patch b/alps.patch index e76dc5477..331716d3b 100644 --- a/alps.patch +++ b/alps.patch @@ -1,7 +1,7 @@ -From ed11aa781242216bc72f1cd7d757a4f40be10329 Mon Sep 17 00:00:00 2001 +From d4b347b29b4d14647c7394f7167bf6785dc98e50 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Mon, 7 Nov 2011 19:53:15 -0800 -Subject: [PATCH 1/7] Input: ALPS - move protocol information to Documentation +Subject: [PATCH 1/6] Input: ALPS - move protocol information to Documentation In preparation for new protocol support, move the protocol information currently documented in alps.c to @@ -99,10 +99,10 @@ index 0000000..ab5478f + byte 7: 0 y6 y5 y4 y3 y2 y1 y0 + byte 8: 0 z6 z5 z4 z3 z2 z1 z0 diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 99d5876..ad15e7c 100644 +index 003587c..19d0943 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c -@@ -74,42 +74,7 @@ static const struct alps_model_info alps_model_data[] = { +@@ -67,42 +67,7 @@ static const struct alps_model_info alps_model_data[] = { * isn't valid per PS/2 spec. */ @@ -150,10 +150,10 @@ index 99d5876..ad15e7c 100644 1.7.7.3 -From 27b8ed51ee660e9a59cf325d6339f38b216fbb31 Mon Sep 17 00:00:00 2001 +From fa629ef5222193214da9a2b3c94369f79353bec9 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Mon, 7 Nov 2011 19:53:24 -0800 -Subject: [PATCH 2/7] Input: ALPS - add protocol version field in +Subject: [PATCH 2/6] Input: ALPS - add protocol version field in alps_model_info In preparation for adding support for more ALPS protocol versions, @@ -164,28 +164,24 @@ version 1 and version 2, repsectively. Signed-off-by: Seth Forshee Acked-by: Chase Douglas Signed-off-by: Dmitry Torokhov - -Conflicts: - - drivers/input/mouse/alps.c --- drivers/input/mouse/alps.c | 47 +++++++++++++++++++++---------------------- drivers/input/mouse/alps.h | 4 +++ 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index ad15e7c..572cb21 100644 +index 19d0943..77b776d 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c -@@ -30,7 +30,6 @@ - #define dbg(format, arg...) do {} while (0) - #endif +@@ -23,7 +23,6 @@ + #include "psmouse.h" + #include "alps.h" -#define ALPS_OLDPROTO 0x01 /* old style input */ #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ #define ALPS_PASS 0x04 /* device has a pass-through port */ -@@ -42,30 +41,30 @@ +@@ -35,30 +34,30 @@ 6-byte ALPS packet */ static const struct alps_model_info alps_model_data[] = { @@ -238,7 +234,7 @@ index ad15e7c..572cb21 100644 }; /* -@@ -119,7 +118,7 @@ static void alps_process_packet(struct psmouse *psmouse) +@@ -112,7 +111,7 @@ static void alps_process_packet(struct psmouse *psmouse) int x, y, z, ges, fin, left, right, middle; int back = 0, forward = 0; @@ -268,10 +264,10 @@ index 904ed8b..4ce9bba 100644 1.7.7.3 -From dfab9d3e073f2a58e4ba3837a726e9a0e33ea5df Mon Sep 17 00:00:00 2001 +From b46615fe9215214ac00e26d35fc54dbe1c510803 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Mon, 7 Nov 2011 19:53:30 -0800 -Subject: [PATCH 3/7] Input: ALPS - remove assumptions about packet size +Subject: [PATCH 3/6] Input: ALPS - remove assumptions about packet size In preparation for version 4 protocol support, which has 8-byte data packets, remove all hard-coded assumptions about packet size @@ -285,10 +281,10 @@ Signed-off-by: Dmitry Torokhov 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 572cb21..f699698 100644 +index 77b776d..44a0a71 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c -@@ -315,7 +315,7 @@ static void alps_flush_packet(unsigned long data) +@@ -308,7 +308,7 @@ static void alps_flush_packet(unsigned long data) serio_pause_rx(psmouse->ps2dev.serio); @@ -297,7 +293,7 @@ index 572cb21..f699698 100644 /* * We did not any more data in reasonable amount of time. -@@ -365,15 +365,15 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) +@@ -359,8 +359,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) return PSMOUSE_BAD_DATA; } @@ -306,8 +302,9 @@ index 572cb21..f699698 100644 + /* Bytes 2 - pktsize should have 0 in the highest bit */ + if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { - dbg("refusing packet[%i] = %x\n", - psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]); + psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", + psmouse->pktcnt - 1, +@@ -368,7 +368,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) return PSMOUSE_BAD_DATA; } @@ -316,7 +313,7 @@ index 572cb21..f699698 100644 alps_process_packet(psmouse); return PSMOUSE_FULL_PACKET; } -@@ -531,7 +531,7 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable) +@@ -529,7 +529,7 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable) static int alps_poll(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; @@ -329,10 +326,10 @@ index 572cb21..f699698 100644 1.7.7.3 -From 35f17ba201d7a8b8adc59811effafe62a331fd9e Mon Sep 17 00:00:00 2001 +From 25bded7cd60fa460e520e9f819bd06f4c5cb53f0 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Mon, 7 Nov 2011 19:53:36 -0800 -Subject: [PATCH 4/7] Input: ALPS - add support for protocol versions 3 and 4 +Subject: [PATCH 4/6] Input: ALPS - add support for protocol versions 3 and 4 This patch adds support for two ALPS touchpad protocols not supported currently by the driver, which I am arbitrarily naming @@ -345,23 +342,19 @@ of the v3 protocol. Signed-off-by: Seth Forshee Acked-by: Chase Douglas Signed-off-by: Dmitry Torokhov - -Conflicts: - - drivers/input/mouse/alps.c --- - drivers/input/mouse/alps.c | 790 +++++++++++++++++++++++++++++++++++++++-- + drivers/input/mouse/alps.c | 791 +++++++++++++++++++++++++++++++++++++++-- drivers/input/mouse/alps.h | 14 + drivers/input/mouse/psmouse.h | 1 + - 3 files changed, 767 insertions(+), 38 deletions(-) + 3 files changed, 768 insertions(+), 38 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index f699698..b2bc8ca 100644 +index 44a0a71..a0248fd 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c -@@ -30,6 +30,49 @@ - #define dbg(format, arg...) do {} while (0) - #endif +@@ -23,6 +23,50 @@ + #include "psmouse.h" + #include "alps.h" +/* + * Definitions for ALPS version 3 and 4 command mode protocol @@ -405,11 +398,12 @@ index f699698..b2bc8ca 100644 + { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ + { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ +}; ++ + #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ #define ALPS_PASS 0x04 /* device has a pass-through port */ -@@ -41,30 +84,33 @@ +@@ -34,30 +78,33 @@ 6-byte ALPS packet */ static const struct alps_model_info alps_model_data[] = { @@ -465,7 +459,7 @@ index f699698..b2bc8ca 100644 }; /* -@@ -108,7 +154,7 @@ static void alps_report_buttons(struct psmouse *psmouse, +@@ -101,7 +148,7 @@ static void alps_report_buttons(struct psmouse *psmouse, input_sync(dev2); } @@ -474,7 +468,7 @@ index f699698..b2bc8ca 100644 { struct alps_data *priv = psmouse->private; const struct alps_model_info *model = priv->i; -@@ -210,6 +256,224 @@ static void alps_process_packet(struct psmouse *psmouse) +@@ -203,6 +250,224 @@ static void alps_process_packet(struct psmouse *psmouse) input_sync(dev); } @@ -699,7 +693,7 @@ index f699698..b2bc8ca 100644 static void alps_report_bare_ps2_packet(struct psmouse *psmouse, unsigned char packet[], bool report_buttons) -@@ -381,11 +645,127 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) +@@ -376,11 +641,127 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) return PSMOUSE_GOOD_DATA; } @@ -827,7 +821,7 @@ index f699698..b2bc8ca 100644 int i; /* -@@ -431,12 +811,41 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int +@@ -428,12 +809,41 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version = (param[0] << 8) | (param[1] << 4) | i; } @@ -873,7 +867,7 @@ index f699698..b2bc8ca 100644 } /* -@@ -444,7 +853,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int +@@ -441,7 +851,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int * subsequent commands. It looks like glidepad is behind stickpointer, * I'd thought it would be other way around... */ @@ -882,7 +876,7 @@ index f699698..b2bc8ca 100644 { struct ps2dev *ps2dev = &psmouse->ps2dev; int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; -@@ -461,7 +870,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) +@@ -458,7 +868,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) return 0; } @@ -891,7 +885,7 @@ index f699698..b2bc8ca 100644 { struct ps2dev *ps2dev = &psmouse->ps2dev; -@@ -535,13 +944,13 @@ static int alps_poll(struct psmouse *psmouse) +@@ -533,13 +943,13 @@ static int alps_poll(struct psmouse *psmouse) bool poll_failed; if (priv->i->flags & ALPS_PASS) @@ -907,7 +901,7 @@ index f699698..b2bc8ca 100644 if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) return -1; -@@ -558,13 +967,13 @@ static int alps_poll(struct psmouse *psmouse) +@@ -556,13 +966,13 @@ static int alps_poll(struct psmouse *psmouse) return 0; } @@ -923,13 +917,13 @@ index f699698..b2bc8ca 100644 return -1; } -@@ -573,13 +982,13 @@ static int alps_hw_init(struct psmouse *psmouse) +@@ -571,13 +981,13 @@ static int alps_hw_init(struct psmouse *psmouse) return -1; } - if (alps_absolute_mode(psmouse)) { + if (alps_absolute_mode_v1_v2(psmouse)) { - printk(KERN_ERR "alps.c: Failed to enable absolute mode\n"); + psmouse_err(psmouse, "Failed to enable absolute mode\n"); return -1; } @@ -939,7 +933,7 @@ index f699698..b2bc8ca 100644 return -1; } -@@ -592,6 +1001,297 @@ static int alps_hw_init(struct psmouse *psmouse) +@@ -590,6 +1000,297 @@ static int alps_hw_init(struct psmouse *psmouse) return 0; } @@ -1237,7 +1231,7 @@ index f699698..b2bc8ca 100644 static int alps_reconnect(struct psmouse *psmouse) { const struct alps_model_info *model; -@@ -632,6 +1332,8 @@ int alps_init(struct psmouse *psmouse) +@@ -630,6 +1331,8 @@ int alps_init(struct psmouse *psmouse) psmouse->private = priv; @@ -1246,7 +1240,7 @@ index f699698..b2bc8ca 100644 model = alps_get_model(psmouse, &version); if (!model) goto init_fail; -@@ -659,8 +1361,20 @@ int alps_init(struct psmouse *psmouse) +@@ -657,8 +1360,20 @@ int alps_init(struct psmouse *psmouse) BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); @@ -1269,7 +1263,7 @@ index f699698..b2bc8ca 100644 input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); if (model->flags & ALPS_WHEEL) { -@@ -703,7 +1417,7 @@ int alps_init(struct psmouse *psmouse) +@@ -701,7 +1416,7 @@ int alps_init(struct psmouse *psmouse) psmouse->poll = alps_poll; psmouse->disconnect = alps_disconnect; psmouse->reconnect = alps_reconnect; @@ -1320,7 +1314,7 @@ index 4ce9bba..62db7f4 100644 int alps_detect(struct psmouse *psmouse, bool set_properties); int alps_init(struct psmouse *psmouse); diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h -index 593e910..c2b5aa6 100644 +index 9b84b0c..11a9c6c 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -8,6 +8,7 @@ @@ -1335,10 +1329,10 @@ index 593e910..c2b5aa6 100644 1.7.7.3 -From 8a2d5b12d0a47daf178a842ca009eaf344033cf8 Mon Sep 17 00:00:00 2001 +From 01ce661fc83005947dc958a5739c153843af8a73 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Mon, 7 Nov 2011 19:54:13 -0800 -Subject: [PATCH 5/7] Input: ALPS - add semi-MT support for v3 protocol +Subject: [PATCH 5/6] Input: ALPS - add semi-MT support for v3 protocol Signed-off-by: Seth Forshee Acked-by: Chase Douglas @@ -1349,7 +1343,7 @@ Signed-off-by: Dmitry Torokhov 2 files changed, 215 insertions(+), 19 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index b2bc8ca..15383e1 100644 +index a0248fd..bd87380 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -17,6 +17,7 @@ @@ -1360,7 +1354,7 @@ index b2bc8ca..15383e1 100644 #include #include -@@ -33,6 +34,12 @@ +@@ -26,6 +27,12 @@ /* * Definitions for ALPS version 3 and 4 command mode protocol */ @@ -1373,7 +1367,7 @@ index b2bc8ca..15383e1 100644 #define ALPS_CMD_NIBBLE_10 0x01f2 static const struct alps_nibble_commands alps_v3_nibble_commands[] = { -@@ -256,6 +263,137 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) +@@ -250,6 +257,137 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) input_sync(dev); } @@ -1511,7 +1505,7 @@ index b2bc8ca..15383e1 100644 static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; -@@ -324,16 +462,17 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) +@@ -318,16 +456,17 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) struct input_dev *dev2 = priv->dev2; int x, y, z; int left, right, middle; @@ -1535,7 +1529,7 @@ index b2bc8ca..15383e1 100644 /* * Sometimes a position packet will indicate a multi-packet * sequence, but then what follows is another position -@@ -341,18 +480,49 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) +@@ -335,18 +474,49 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) * position packet as usual. */ if (packet[0] & 0x40) { @@ -1591,7 +1585,7 @@ index b2bc8ca..15383e1 100644 left = packet[3] & 0x01; right = packet[3] & 0x02; -@@ -372,22 +542,38 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) +@@ -366,22 +536,38 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) if (x && y && !z) return; @@ -1635,7 +1629,7 @@ index b2bc8ca..15383e1 100644 input_sync(dev); if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { -@@ -1369,9 +1555,18 @@ int alps_init(struct psmouse *psmouse) +@@ -1368,9 +1554,18 @@ int alps_init(struct psmouse *psmouse) input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); break; case ALPS_PROTO_V3: @@ -1672,10 +1666,10 @@ index 62db7f4..a00a4ab 100644 1.7.7.3 -From 281688737cb83dd113cfab809b2c78841451ba32 Mon Sep 17 00:00:00 2001 +From 7cf801cfc0774b777aa6861cf4a43a90b112b1ed Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Mon, 7 Nov 2011 19:54:35 -0800 -Subject: [PATCH 6/7] Input: ALPS - add documentation for protocol versions 3 +Subject: [PATCH 6/6] Input: ALPS - add documentation for protocol versions 3 and 4 Also converts from using "old" and "new" to describe the already-known @@ -1865,126 +1859,3 @@ index ab5478f..f274c28 100644 -- 1.7.7.3 - -From 8114d422321fa6bb724a03faf25b101868d6e03d Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Mon, 12 Dec 2011 15:12:00 -0500 -Subject: [PATCH 7/7] Revert psmouse_* print format changes from the - backported patches. Sigh - -Signed-off-by: Josh Boyer ---- - drivers/input/mouse/alps.c | 29 ++++++++++++----------------- - 1 files changed, 12 insertions(+), 17 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 15383e1..4925a63 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -403,7 +403,7 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) - - /* Sanity check packet */ - if (!(packet[0] & 0x40)) { -- psmouse_dbg(psmouse, "Bad trackstick packet, discarding\n"); -+ dbg("Bad trackstick packet, discarding\n"); - return; - } - -@@ -922,13 +922,12 @@ static int alps_enter_command_mode(struct psmouse *psmouse, - ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || - ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { -- psmouse_err(psmouse, "failed to enter command mode\n"); -+ printk(KERN_ERR "alps.c: failed to enter command mode\n"); - return -1; - } - - if (param[0] != 0x88 && param[1] != 0x07) { -- psmouse_dbg(psmouse, -- "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", -+ dbg("unknown response while entering command mode: %2.2x %2.2x %2.2x\n", - param[0], param[1], param[2]); - return -1; - } -@@ -1012,8 +1011,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int - */ - model = NULL; - if (alps_enter_command_mode(psmouse, param)) { -- psmouse_warn(psmouse, -- "touchpad failed to enter command mode\n"); -+ printk(KERN_WARNING "alps.c: touchpad failed to enter command mode\n"); - } else { - for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { - if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && -@@ -1025,8 +1023,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int - alps_exit_command_mode(psmouse); - - if (!model) -- psmouse_dbg(psmouse, -- "Unknown command mode response %2.2x\n", -+ dbg("Unknown command mode response %2.2x\n", - param[0]); - } - } -@@ -1263,10 +1260,9 @@ static int alps_hw_init_v3(struct psmouse *psmouse) - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { -- psmouse_warn(psmouse, "trackstick E7 report failed\n"); -+ printk(KERN_WARNING "alps.c: trackstick E7 report failed\n"); - } else { -- psmouse_dbg(psmouse, -- "trackstick E7 report: %2.2x %2.2x %2.2x\n", -+ dbg("trackstick E7 report: %2.2x %2.2x %2.2x\n", - param[0], param[1], param[2]); - - /* -@@ -1280,8 +1276,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - alps_command_mode_send_nibble(psmouse, 0x9) || - alps_command_mode_send_nibble(psmouse, 0x4)) { -- psmouse_err(psmouse, -- "Error sending magic E6 sequence\n"); -+ printk(KERN_ERR "alps.c: Error sending magic E6 sequence\n"); - goto error_passthrough; - } - } -@@ -1293,7 +1288,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) - } - - if (alps_absolute_mode_v3(psmouse)) { -- psmouse_err(psmouse, "Failed to enter absolute mode\n"); -+ printk(KERN_ERR "alps.c: Failed to enter absolute mode\n"); - goto error; - } - -@@ -1343,7 +1338,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) - param[0] = 0x64; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { -- psmouse_err(psmouse, "Failed to enable data reporting\n"); -+ printk(KERN_ERR "alps.c: Failed to enable data reporting\n"); - return -1; - } - -@@ -1392,7 +1387,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse) - goto error; - - if (alps_absolute_mode_v4(psmouse)) { -- psmouse_err(psmouse, "Failed to enter absolute mode\n"); -+ printk(KERN_ERR "alps.c: Failed to enter absolute mode\n"); - goto error; - } - -@@ -1440,7 +1435,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse) - param[0] = 0x64; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { -- psmouse_err(psmouse, "Failed to enable data reporting\n"); -+ printk(KERN_ERR "alps.c: Failed to enable data reporting\n"); - return -1; - } - --- -1.7.7.3 - diff --git a/asus-laptop-3.2-backport.patch b/asus-laptop-3.2-backport.patch deleted file mode 100644 index ea161f688..000000000 --- a/asus-laptop-3.2-backport.patch +++ /dev/null @@ -1,592 +0,0 @@ -Backport from 3.2 (754214) - -Andy Ross (4): - asus-laptop: Platform detection for Pegatron Lucid - asus-laptop: Pegatron Lucid ALS sensor - asus-laptop: allow boot time control of Pegatron ALS sensor - asus-laptop: Pegatron Lucid accelerometer - -Anisse Astier (2): - asus-laptop: pega_accel - Report accelerometer orientation change through udev - asus-laptop: Add rfkill support for Pegatron Lucid tablet - -Axel Lin (1): - platform-drivers-x86: asus-laptop: fix wrong test for successful registered led_classdev - -Corentin Chary (2): - asus-laptop: hide leds on Pegatron Lucid - asus-laptop: fix module description - -diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c -index fa6d7ec..edaccad 100644 ---- a/drivers/platform/x86/asus-laptop.c -+++ b/drivers/platform/x86/asus-laptop.c -@@ -4,6 +4,7 @@ - * - * Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor - * Copyright (C) 2006-2007 Corentin Chary -+ * Copyright (C) 2011 Wind River Systems - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -48,6 +49,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -83,26 +85,32 @@ static int wlan_status = 1; - static int bluetooth_status = 1; - static int wimax_status = -1; - static int wwan_status = -1; -+static int als_status; - - module_param(wlan_status, int, 0444); - MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot " - "(0 = disabled, 1 = enabled, -1 = don't do anything). " -- "default is 1"); -+ "default is -1"); - - module_param(bluetooth_status, int, 0444); - MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " - "(0 = disabled, 1 = enabled, -1 = don't do anything). " -- "default is 1"); -+ "default is -1"); - - module_param(wimax_status, int, 0444); - MODULE_PARM_DESC(wimax_status, "Set the wireless status on boot " - "(0 = disabled, 1 = enabled, -1 = don't do anything). " -- "default is 1"); -+ "default is -1"); - - module_param(wwan_status, int, 0444); - MODULE_PARM_DESC(wwan_status, "Set the wireless status on boot " - "(0 = disabled, 1 = enabled, -1 = don't do anything). " -- "default is 1"); -+ "default is -1"); -+ -+module_param(als_status, int, 0444); -+MODULE_PARM_DESC(als_status, "Set the ALS status on boot " -+ "(0 = disabled, 1 = enabled). " -+ "default is 0"); - - /* - * Some events we use, same for all Asus -@@ -173,6 +181,29 @@ MODULE_PARM_DESC(wwan_status, "Set the wireless status on boot " - #define METHOD_KBD_LIGHT_SET "SLKB" - #define METHOD_KBD_LIGHT_GET "GLKB" - -+/* For Pegatron Lucid tablet */ -+#define DEVICE_NAME_PEGA "Lucid" -+ -+#define METHOD_PEGA_ENABLE "ENPR" -+#define METHOD_PEGA_DISABLE "DAPR" -+#define PEGA_WLAN 0x00 -+#define PEGA_BLUETOOTH 0x01 -+#define PEGA_WWAN 0x02 -+#define PEGA_ALS 0x04 -+#define PEGA_ALS_POWER 0x05 -+ -+#define METHOD_PEGA_READ "RDLN" -+#define PEGA_READ_ALS_H 0x02 -+#define PEGA_READ_ALS_L 0x03 -+ -+#define PEGA_ACCEL_NAME "pega_accel" -+#define PEGA_ACCEL_DESC "Pegatron Lucid Tablet Accelerometer" -+#define METHOD_XLRX "XLRX" -+#define METHOD_XLRY "XLRY" -+#define METHOD_XLRZ "XLRZ" -+#define PEGA_ACC_CLAMP 512 /* 1G accel is reported as ~256, so clamp to 2G */ -+#define PEGA_ACC_RETRIES 3 -+ - /* - * Define a specific led structure to keep the main structure clean - */ -@@ -185,6 +216,15 @@ struct asus_led { - }; - - /* -+ * Same thing for rfkill -+ */ -+struct asus_pega_rfkill { -+ int control_id; /* type of control. Maps to PEGA_* values */ -+ struct rfkill *rfkill; -+ struct asus_laptop *asus; -+}; -+ -+/* - * This is the main structure, we can use it to store anything interesting - * about the hotk device - */ -@@ -198,6 +238,7 @@ struct asus_laptop { - - struct input_dev *inputdev; - struct key_entry *keymap; -+ struct input_polled_dev *pega_accel_poll; - - struct asus_led mled; - struct asus_led tled; -@@ -209,9 +250,18 @@ struct asus_laptop { - - int wireless_status; - bool have_rsts; -+ bool is_pega_lucid; -+ bool pega_acc_live; -+ int pega_acc_x; -+ int pega_acc_y; -+ int pega_acc_z; - - struct rfkill *gps_rfkill; - -+ struct asus_pega_rfkill wlanrfk; -+ struct asus_pega_rfkill btrfk; -+ struct asus_pega_rfkill wwanrfk; -+ - acpi_handle handle; /* the handle of the hotk device */ - u32 ledd_status; /* status of the LED display */ - u8 light_level; /* light sensor level */ -@@ -323,6 +373,127 @@ static int acpi_check_handle(acpi_handle handle, const char *method, - return 0; - } - -+static bool asus_check_pega_lucid(struct asus_laptop *asus) -+{ -+ return !strcmp(asus->name, DEVICE_NAME_PEGA) && -+ !acpi_check_handle(asus->handle, METHOD_PEGA_ENABLE, NULL) && -+ !acpi_check_handle(asus->handle, METHOD_PEGA_DISABLE, NULL) && -+ !acpi_check_handle(asus->handle, METHOD_PEGA_READ, NULL); -+} -+ -+static int asus_pega_lucid_set(struct asus_laptop *asus, int unit, bool enable) -+{ -+ char *method = enable ? METHOD_PEGA_ENABLE : METHOD_PEGA_DISABLE; -+ return write_acpi_int(asus->handle, method, unit); -+} -+ -+static int pega_acc_axis(struct asus_laptop *asus, int curr, char *method) -+{ -+ int i, delta; -+ unsigned long long val; -+ for (i = 0; i < PEGA_ACC_RETRIES; i++) { -+ acpi_evaluate_integer(asus->handle, method, NULL, &val); -+ -+ /* The output is noisy. From reading the ASL -+ * dissassembly, timeout errors are returned with 1's -+ * in the high word, and the lack of locking around -+ * thei hi/lo byte reads means that a transition -+ * between (for example) -1 and 0 could be read as -+ * 0xff00 or 0x00ff. */ -+ delta = abs(curr - (short)val); -+ if (delta < 128 && !(val & ~0xffff)) -+ break; -+ } -+ return clamp_val((short)val, -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP); -+} -+ -+static void pega_accel_poll(struct input_polled_dev *ipd) -+{ -+ struct device *parent = ipd->input->dev.parent; -+ struct asus_laptop *asus = dev_get_drvdata(parent); -+ -+ /* In some cases, the very first call to poll causes a -+ * recursive fault under the polldev worker. This is -+ * apparently related to very early userspace access to the -+ * device, and perhaps a firmware bug. Fake the first report. */ -+ if (!asus->pega_acc_live) { -+ asus->pega_acc_live = true; -+ input_report_abs(ipd->input, ABS_X, 0); -+ input_report_abs(ipd->input, ABS_Y, 0); -+ input_report_abs(ipd->input, ABS_Z, 0); -+ input_sync(ipd->input); -+ return; -+ } -+ -+ asus->pega_acc_x = pega_acc_axis(asus, asus->pega_acc_x, METHOD_XLRX); -+ asus->pega_acc_y = pega_acc_axis(asus, asus->pega_acc_y, METHOD_XLRY); -+ asus->pega_acc_z = pega_acc_axis(asus, asus->pega_acc_z, METHOD_XLRZ); -+ -+ /* Note transform, convert to "right/up/out" in the native -+ * landscape orientation (i.e. the vector is the direction of -+ * "real up" in the device's cartiesian coordinates). */ -+ input_report_abs(ipd->input, ABS_X, -asus->pega_acc_x); -+ input_report_abs(ipd->input, ABS_Y, -asus->pega_acc_y); -+ input_report_abs(ipd->input, ABS_Z, asus->pega_acc_z); -+ input_sync(ipd->input); -+} -+ -+static void pega_accel_exit(struct asus_laptop *asus) -+{ -+ if (asus->pega_accel_poll) { -+ input_unregister_polled_device(asus->pega_accel_poll); -+ input_free_polled_device(asus->pega_accel_poll); -+ } -+ asus->pega_accel_poll = NULL; -+} -+ -+static int pega_accel_init(struct asus_laptop *asus) -+{ -+ int err; -+ struct input_polled_dev *ipd; -+ -+ if (!asus->is_pega_lucid) -+ return -ENODEV; -+ -+ if (acpi_check_handle(asus->handle, METHOD_XLRX, NULL) || -+ acpi_check_handle(asus->handle, METHOD_XLRY, NULL) || -+ acpi_check_handle(asus->handle, METHOD_XLRZ, NULL)) -+ return -ENODEV; -+ -+ ipd = input_allocate_polled_device(); -+ if (!ipd) -+ return -ENOMEM; -+ -+ ipd->poll = pega_accel_poll; -+ ipd->poll_interval = 125; -+ ipd->poll_interval_min = 50; -+ ipd->poll_interval_max = 2000; -+ -+ ipd->input->name = PEGA_ACCEL_DESC; -+ ipd->input->phys = PEGA_ACCEL_NAME "/input0"; -+ ipd->input->dev.parent = &asus->platform_device->dev; -+ ipd->input->id.bustype = BUS_HOST; -+ -+ set_bit(EV_ABS, ipd->input->evbit); -+ input_set_abs_params(ipd->input, ABS_X, -+ -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0); -+ input_set_abs_params(ipd->input, ABS_Y, -+ -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0); -+ input_set_abs_params(ipd->input, ABS_Z, -+ -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0); -+ -+ err = input_register_polled_device(ipd); -+ if (err) -+ goto exit; -+ -+ asus->pega_accel_poll = ipd; -+ return 0; -+ -+exit: -+ input_free_polled_device(ipd); -+ return err; -+} -+ - /* Generic LED function */ - static int asus_led_set(struct asus_laptop *asus, const char *method, - int value) -@@ -430,17 +601,17 @@ static enum led_brightness asus_kled_cdev_get(struct led_classdev *led_cdev) - - static void asus_led_exit(struct asus_laptop *asus) - { -- if (asus->mled.led.dev) -+ if (!IS_ERR_OR_NULL(asus->mled.led.dev)) - led_classdev_unregister(&asus->mled.led); -- if (asus->tled.led.dev) -+ if (!IS_ERR_OR_NULL(asus->tled.led.dev)) - led_classdev_unregister(&asus->tled.led); -- if (asus->pled.led.dev) -+ if (!IS_ERR_OR_NULL(asus->pled.led.dev)) - led_classdev_unregister(&asus->pled.led); -- if (asus->rled.led.dev) -+ if (!IS_ERR_OR_NULL(asus->rled.led.dev)) - led_classdev_unregister(&asus->rled.led); -- if (asus->gled.led.dev) -+ if (!IS_ERR_OR_NULL(asus->gled.led.dev)) - led_classdev_unregister(&asus->gled.led); -- if (asus->kled.led.dev) -+ if (!IS_ERR_OR_NULL(asus->kled.led.dev)) - led_classdev_unregister(&asus->kled.led); - if (asus->led_workqueue) { - destroy_workqueue(asus->led_workqueue); -@@ -474,6 +645,13 @@ static int asus_led_init(struct asus_laptop *asus) - int r; - - /* -+ * The Pegatron Lucid has no physical leds, but all methods are -+ * available in the DSDT... -+ */ -+ if (asus->is_pega_lucid) -+ return 0; -+ -+ /* - * Functions that actually update the LED's are called from a - * workqueue. By doing this as separate work rather than when the LED - * subsystem asks, we avoid messing with the Asus ACPI stuff during a -@@ -907,8 +1085,18 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr, - */ - static void asus_als_switch(struct asus_laptop *asus, int value) - { -- if (write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value)) -- pr_warn("Error setting light sensor switch\n"); -+ int ret; -+ -+ if (asus->is_pega_lucid) { -+ ret = asus_pega_lucid_set(asus, PEGA_ALS, value); -+ if (!ret) -+ ret = asus_pega_lucid_set(asus, PEGA_ALS_POWER, value); -+ } else { -+ ret = write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value); -+ } -+ if (ret) -+ pr_warning("Error setting light sensor switch\n"); -+ - asus->light_switch = value; - } - -@@ -964,6 +1152,35 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, - return rv; - } - -+static int pega_int_read(struct asus_laptop *asus, int arg, int *result) -+{ -+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; -+ int err = write_acpi_int_ret(asus->handle, METHOD_PEGA_READ, arg, -+ &buffer); -+ if (!err) { -+ union acpi_object *obj = buffer.pointer; -+ if (obj && obj->type == ACPI_TYPE_INTEGER) -+ *result = obj->integer.value; -+ else -+ err = -EIO; -+ } -+ return err; -+} -+ -+static ssize_t show_lsvalue(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct asus_laptop *asus = dev_get_drvdata(dev); -+ int err, hi, lo; -+ -+ err = pega_int_read(asus, PEGA_READ_ALS_H, &hi); -+ if (!err) -+ err = pega_int_read(asus, PEGA_READ_ALS_L, &lo); -+ if (!err) -+ return sprintf(buf, "%d\n", 10 * hi + lo); -+ return err; -+} -+ - /* - * GPS - */ -@@ -1062,6 +1279,86 @@ static int asus_rfkill_init(struct asus_laptop *asus) - return result; - } - -+static int pega_rfkill_set(void *data, bool blocked) -+{ -+ struct asus_pega_rfkill *pega_rfk = data; -+ -+ int ret = asus_pega_lucid_set(pega_rfk->asus, pega_rfk->control_id, !blocked); -+ pr_warn("Setting rfkill %d, to %d; returned %d\n", pega_rfk->control_id, !blocked, ret); -+ -+ return ret; -+} -+ -+static const struct rfkill_ops pega_rfkill_ops = { -+ .set_block = pega_rfkill_set, -+}; -+ -+static void pega_rfkill_terminate(struct asus_pega_rfkill *pega_rfk) -+{ -+ pr_warn("Terminating %d\n", pega_rfk->control_id); -+ if (pega_rfk->rfkill) { -+ rfkill_unregister(pega_rfk->rfkill); -+ rfkill_destroy(pega_rfk->rfkill); -+ pega_rfk->rfkill = NULL; -+ } -+} -+ -+static void pega_rfkill_exit(struct asus_laptop *asus) -+{ -+ pega_rfkill_terminate(&asus->wwanrfk); -+ pega_rfkill_terminate(&asus->btrfk); -+ pega_rfkill_terminate(&asus->wlanrfk); -+} -+ -+static int pega_rfkill_setup(struct asus_laptop *asus, struct asus_pega_rfkill *pega_rfk, -+ const char *name, int controlid, int rfkill_type) -+{ -+ int result; -+ -+ pr_warn("Setting up rfk %s, control %d, type %d\n", name, controlid, rfkill_type); -+ pega_rfk->control_id = controlid; -+ pega_rfk->asus = asus; -+ pega_rfk->rfkill = rfkill_alloc(name, &asus->platform_device->dev, -+ rfkill_type, &pega_rfkill_ops, pega_rfk); -+ if (!pega_rfk->rfkill) -+ return -EINVAL; -+ -+ result = rfkill_register(pega_rfk->rfkill); -+ if (result) { -+ rfkill_destroy(pega_rfk->rfkill); -+ pega_rfk->rfkill = NULL; -+ } -+ -+ return result; -+} -+ -+static int pega_rfkill_init(struct asus_laptop *asus) -+{ -+ int ret = 0; -+ -+ if(!asus->is_pega_lucid) -+ return -ENODEV; -+ -+ ret = pega_rfkill_setup(asus, &asus->wlanrfk, "pega-wlan", PEGA_WLAN, RFKILL_TYPE_WLAN); -+ if(ret) -+ return ret; -+ ret = pega_rfkill_setup(asus, &asus->btrfk, "pega-bt", PEGA_BLUETOOTH, RFKILL_TYPE_BLUETOOTH); -+ if(ret) -+ goto err_btrfk; -+ ret = pega_rfkill_setup(asus, &asus->wwanrfk, "pega-wwan", PEGA_WWAN, RFKILL_TYPE_WWAN); -+ if(ret) -+ goto err_wwanrfk; -+ -+ pr_warn("Pega rfkill init succeeded\n"); -+ return 0; -+err_wwanrfk: -+ pega_rfkill_terminate(&asus->btrfk); -+err_btrfk: -+ pega_rfkill_terminate(&asus->wlanrfk); -+ -+ return ret; -+} -+ - /* - * Input device (i.e. hotkeys) - */ -@@ -1141,6 +1438,14 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event) - } - return ; - } -+ -+ /* Accelerometer "coarse orientation change" event */ -+ if (asus->pega_accel_poll && event == 0xEA) { -+ kobject_uevent(&asus->pega_accel_poll->input->dev.kobj, -+ KOBJ_CHANGE); -+ return ; -+ } -+ - asus_input_notify(asus, event); - } - -@@ -1152,6 +1457,7 @@ static DEVICE_ATTR(wimax, S_IRUGO | S_IWUSR, show_wimax, store_wimax); - static DEVICE_ATTR(wwan, S_IRUGO | S_IWUSR, show_wwan, store_wwan); - static DEVICE_ATTR(display, S_IWUSR, NULL, store_disp); - static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd); -+static DEVICE_ATTR(ls_value, S_IRUGO, show_lsvalue, NULL); - static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl); - static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw); - static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps); -@@ -1164,6 +1470,7 @@ static struct attribute *asus_attributes[] = { - &dev_attr_wwan.attr, - &dev_attr_display.attr, - &dev_attr_ledd.attr, -+ &dev_attr_ls_value.attr, - &dev_attr_ls_level.attr, - &dev_attr_ls_switch.attr, - &dev_attr_gps.attr, -@@ -1180,6 +1487,19 @@ static mode_t asus_sysfs_is_visible(struct kobject *kobj, - acpi_handle handle = asus->handle; - bool supported; - -+ if (asus->is_pega_lucid) { -+ /* no ls_level interface on the Lucid */ -+ if (attr == &dev_attr_ls_switch.attr) -+ supported = true; -+ else if (attr == &dev_attr_ls_level.attr) -+ supported = false; -+ else -+ goto normal; -+ -+ return supported; -+ } -+ -+normal: - if (attr == &dev_attr_wlan.attr) { - supported = !acpi_check_handle(handle, METHOD_WLAN, NULL); - -@@ -1202,8 +1522,9 @@ static mode_t asus_sysfs_is_visible(struct kobject *kobj, - } else if (attr == &dev_attr_ls_switch.attr || - attr == &dev_attr_ls_level.attr) { - supported = !acpi_check_handle(handle, METHOD_ALS_CONTROL, NULL) && -- !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL); -- -+ !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL); -+ } else if (attr == &dev_attr_ls_value.attr) { -+ supported = asus->is_pega_lucid; - } else if (attr == &dev_attr_gps.attr) { - supported = !acpi_check_handle(handle, METHOD_GPS_ON, NULL) && - !acpi_check_handle(handle, METHOD_GPS_OFF, NULL) && -@@ -1258,7 +1579,7 @@ static struct platform_driver platform_driver = { - .driver = { - .name = ASUS_LAPTOP_FILE, - .owner = THIS_MODULE, -- } -+ }, - }; - - /* -@@ -1388,11 +1709,13 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) - asus->ledd_status = 0xFFF; - - /* Set initial values of light sensor and level */ -- asus->light_switch = 0; /* Default to light sensor disabled */ -+ asus->light_switch = !!als_status; - asus->light_level = 5; /* level 5 for sensor sensitivity */ - -- if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) && -- !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) { -+ if (asus->is_pega_lucid) { -+ asus_als_switch(asus, asus->light_switch); -+ } else if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) && -+ !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) { - asus_als_switch(asus, asus->light_switch); - asus_als_level(asus, asus->light_level); - } -@@ -1439,9 +1762,10 @@ static int __devinit asus_acpi_add(struct acpi_device *device) - goto fail_platform; - - /* -- * Register the platform device first. It is used as a parent for the -- * sub-devices below. -+ * Need platform type detection first, then the platform -+ * device. It is used as a parent for the sub-devices below. - */ -+ asus->is_pega_lucid = asus_check_pega_lucid(asus); - result = asus_platform_init(asus); - if (result) - goto fail_platform; -@@ -1465,9 +1789,21 @@ static int __devinit asus_acpi_add(struct acpi_device *device) - if (result) - goto fail_rfkill; - -+ result = pega_accel_init(asus); -+ if (result && result != -ENODEV) -+ goto fail_pega_accel; -+ -+ result = pega_rfkill_init(asus); -+ if (result && result != -ENODEV) -+ goto fail_pega_rfkill; -+ - asus_device_present = true; - return 0; - -+fail_pega_rfkill: -+ pega_accel_exit(asus); -+fail_pega_accel: -+ asus_rfkill_exit(asus); - fail_rfkill: - asus_led_exit(asus); - fail_led: -@@ -1491,6 +1827,8 @@ static int asus_acpi_remove(struct acpi_device *device, int type) - asus_rfkill_exit(asus); - asus_led_exit(asus); - asus_input_exit(asus); -+ pega_accel_exit(asus); -+ pega_rfkill_exit(asus); - asus_platform_exit(asus); - - kfree(asus->name); diff --git a/b44-Use-dev_kfree_skb_irq-in-b44_tx.patch b/b44-Use-dev_kfree_skb_irq-in-b44_tx.patch deleted file mode 100644 index ff50bd534..000000000 --- a/b44-Use-dev_kfree_skb_irq-in-b44_tx.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 15ac2b08a2fd0f4aacbe8ae39788252fea6fbe63 Mon Sep 17 00:00:00 2001 -From: Xander Hover -Date: Wed, 23 Nov 2011 16:40:31 -0500 -Subject: [PATCH] b44: Use dev_kfree_skb_irq() in b44_tx() - -Reported issues when using dev_kfree_skb() on UP systems and -systems with low numbers of cores. dev_kfree_skb_irq() will -properly save IRQ state before freeing the skb. - -Tested on 3.1.1 and 3.2_rc2 - -Example of reproducible trace of kernel 3.1.1 -------------[ cut here ]------------ - WARNING: at kernel/softirq.c:159 local_bh_enable+0x32/0x79() - ... - Pid: 0, comm: swapper Not tainted 3.1.1-gentoo #1 - Call Trace: - [] warn_slowpath_common+0x65/0x7a - [] ? local_bh_enable+0x32/0x79 - [] warn_slowpath_null+0xf/0x13 - [] local_bh_enable+0x32/0x79 - [] destroy_conntrack+0x7c/0x9b - [] nf_conntrack_destroy+0x1f/0x26 - [] skb_release_head_state+0x74/0x83 - [] __kfree_skb+0xb/0x6b - [] consume_skb+0x24/0x26 - [] b44_poll+0xaa/0x449 - [] net_rx_action+0x3f/0xea - [] __do_softirq+0x5f/0xd5 - [] ? local_bh_enable+0x79/0x79 - [] ? irq_exit+0x34/0x8d - [] ? do_IRQ+0x74/0x87 - [] ? common_interrupt+0x29/0x30 - [] ? default_idle+0x29/0x3e - [] ? cpu_idle+0x2f/0x5d - [] ? rest_init+0x79/0x7b - [] ? start_kernel+0x297/0x29c - [] ? i386_start_kernel+0xb0/0xb7 - ---[ end trace 583f33bb1aa207a9 ]--- - -Signed-off-by: Xander Hover -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/broadcom/b44.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/b44.c b/drivers/net/b44.c -index 4cf835d..3fb66d0 100644 ---- a/drivers/net/b44.c -+++ b/drivers/net/b44.c -@@ -608,7 +608,7 @@ static void b44_tx(struct b44 *bp) - skb->len, - DMA_TO_DEVICE); - rp->skb = NULL; -- dev_kfree_skb(skb); -+ dev_kfree_skb_irq(skb); - } - - bp->tx_cons = cons; --- -1.7.7.4 - diff --git a/be2net-non-member-vlan-pkts-not-received-in-promisco.patch b/be2net-non-member-vlan-pkts-not-received-in-promisco.patch deleted file mode 100644 index 866473efd..000000000 --- a/be2net-non-member-vlan-pkts-not-received-in-promisco.patch +++ /dev/null @@ -1,63 +0,0 @@ -From c0e64ef4899df4cedc872871e54e2c069d29e519 Mon Sep 17 00:00:00 2001 -From: Sathya Perla -Date: Tue, 2 Aug 2011 19:57:43 +0000 -Subject: [PATCH] be2net: non-member vlan pkts not received in promiscous mode - -While configuring promiscous mode, explicitly set the -VLAN_PROMISCOUS bit to make this happen. When switching off -promiscous mode, re-program the vids. - -Signed-off-by: Xavier Selvin -Signed-off-by: Sathya Perla -Signed-off-by: David S. Miller ---- - drivers/net/benet/be_cmds.c | 6 ++++-- - drivers/net/benet/be_main.c | 7 +++++++ - 2 files changed, 11 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c -index 1c25dbd..73fd949 100644 ---- a/drivers/net/benet/be_cmds.c -+++ b/drivers/net/benet/be_cmds.c -@@ -1586,9 +1586,11 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, bool en) - OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req)); - - req->if_id = cpu_to_le32(adapter->if_handle); -- req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS); -+ req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS -+ | BE_IF_FLAGS_VLAN_PROMISCUOUS); - if (en) -- req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS); -+ req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS -+ | BE_IF_FLAGS_VLAN_PROMISCUOUS); - - sge->pa_hi = cpu_to_le32(upper_32_bits(promiscous_cmd.dma)); - sge->pa_lo = cpu_to_le32(promiscous_cmd.dma & 0xFFFFFFFF); -diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c -index 3b2c5e6..32a5b11 100644 ---- a/drivers/net/benet/be_main.c -+++ b/drivers/net/benet/be_main.c -@@ -728,6 +728,10 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num) - status = be_cmd_vlan_config(adapter, if_handle, vtag, 1, 1, 0); - } - -+ /* No need to further configure vids if in promiscuous mode */ -+ if (adapter->promiscuous) -+ return 0; -+ - if (adapter->vlans_added <= adapter->max_vlans) { - /* Construct VLAN Table to give to HW */ - for (i = 0; i < VLAN_N_VID; i++) { -@@ -787,6 +791,9 @@ static void be_set_multicast_list(struct net_device *netdev) - if (adapter->promiscuous) { - adapter->promiscuous = false; - be_cmd_promiscuous_config(adapter, false); -+ -+ if (adapter->vlans_added) -+ be_vid_config(adapter, false, 0); - } - - /* Enable multicast promisc if num configured exceeds what we support */ --- -1.7.6.4 - diff --git a/cciss-fix-irqf-shared.patch b/cciss-fix-irqf-shared.patch deleted file mode 100644 index d6de3d7c2..000000000 --- a/cciss-fix-irqf-shared.patch +++ /dev/null @@ -1,39 +0,0 @@ -cciss: Add IRQF_SHARED back in for the non-MSI(X) interrupt handler - -From: Stephen M. Cameron - -[ 3.1.x backport ] - -IRQF_SHARED is required for older controllers that don't support MSI(X) -and which may end up sharing an interrupt. - -Also remove deprecated IRQF_DISABLED. - -Signed-off-by: Stephen M. Cameron ---- - drivers/block/cciss.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -RHBZ 754907 -diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c -index 8004ac3..6f22ed0 100644 ---- a/drivers/block/cciss.c -+++ b/drivers/block/cciss.c -@@ -4880,7 +4880,7 @@ static int cciss_request_irq(ctlr_info_t *h, - { - if (h->msix_vector || h->msi_vector) { - if (!request_irq(h->intr[PERF_MODE_INT], msixhandler, -- IRQF_DISABLED, h->devname, h)) -+ 0, h->devname, h)) - return 0; - dev_err(&h->pdev->dev, "Unable to get msi irq %d" - " for %s\n", h->intr[h->intr_mode], -@@ -4889,7 +4889,7 @@ static int cciss_request_irq(ctlr_info_t *h, - } - - if (!request_irq(h->intr[PERF_MODE_INT], intxhandler, -- IRQF_DISABLED, h->devname, h)) -+ IRQF_SHARED, h->devname, h)) - return 0; - dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n", - h->intr[h->intr_mode], h->devname); diff --git a/compat-wireless-config-fixups.patch b/compat-wireless-config-fixups.patch index 2e99b5d0f..938f35c5c 100644 --- a/compat-wireless-config-fixups.patch +++ b/compat-wireless-config-fixups.patch @@ -1,6 +1,6 @@ -diff -up compat-wireless-3.2-rc6-3/config.mk.orig compat-wireless-3.2-rc6-3/config.mk ---- compat-wireless-3.2-rc6-3/config.mk.orig 2012-01-03 09:41:57.090827042 -0500 -+++ compat-wireless-3.2-rc6-3/config.mk 2012-01-03 09:42:19.259549896 -0500 +diff -up compat-wireless-2011-12-18/config.mk.orig compat-wireless-2011-12-18/config.mk +--- compat-wireless-2011-12-18/config.mk.orig 2012-01-05 13:54:21.214595837 -0500 ++++ compat-wireless-2011-12-18/config.mk 2012-01-05 13:54:35.668415136 -0500 @@ -14,6 +14,9 @@ else include $(KLIB_BUILD)/.config endif @@ -10,8 +10,8 @@ diff -up compat-wireless-3.2-rc6-3/config.mk.orig compat-wireless-3.2-rc6-3/conf + ifneq ($(wildcard $(KLIB_BUILD)/Makefile),) - COMPAT_LATEST_VERSION = 1 -@@ -353,7 +356,7 @@ ifdef CONFIG_CRC_CCITT + COMPAT_LATEST_VERSION = 3 +@@ -395,7 +398,7 @@ ifdef CONFIG_CRC_CCITT CONFIG_RT2800PCI=m CONFIG_RT2800PCI_RT33XX=y CONFIG_RT2800PCI_RT35XX=y @@ -20,7 +20,7 @@ diff -up compat-wireless-3.2-rc6-3/config.mk.orig compat-wireless-3.2-rc6-3/conf endif #CONFIG_CRC_CCITT NEED_RT2X00=y -@@ -481,7 +484,7 @@ ifdef CONFIG_CRC_CCITT +@@ -525,7 +528,7 @@ ifdef CONFIG_CRC_CCITT CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y @@ -29,17 +29,15 @@ diff -up compat-wireless-3.2-rc6-3/config.mk.orig compat-wireless-3.2-rc6-3/conf CONFIG_RT2800USB_UNKNOWN=y endif #CONFIG_CRC_CCITT CONFIG_RT2X00_LIB_USB=m -diff -up compat-wireless-3.2-rc6-3/drivers/misc/eeprom/Makefile.orig compat-wireless-3.2-rc6-3/drivers/misc/eeprom/Makefile ---- compat-wireless-3.2-rc6-3/drivers/misc/eeprom/Makefile.orig 2012-01-03 09:41:57.104826867 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/misc/eeprom/Makefile 2012-01-03 09:42:03.468747311 -0500 -@@ -1,3 +1,3 @@ +diff -up compat-wireless-2011-12-18/drivers/misc/eeprom/Makefile.orig compat-wireless-2011-12-18/drivers/misc/eeprom/Makefile +--- compat-wireless-2011-12-18/drivers/misc/eeprom/Makefile.orig 2012-01-05 13:54:21.214595837 -0500 ++++ compat-wireless-2011-12-18/drivers/misc/eeprom/Makefile 2012-01-05 13:54:27.274520077 -0500 +@@ -1 +1 @@ -obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o +#obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o - obj-$(CONFIG_EEPROM_93XX46) += eeprom_93xx46.o - obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o -diff -up compat-wireless-3.2-rc6-3/drivers/net/ethernet/atheros/Makefile.orig compat-wireless-3.2-rc6-3/drivers/net/ethernet/atheros/Makefile ---- compat-wireless-3.2-rc6-3/drivers/net/ethernet/atheros/Makefile.orig 2012-01-03 09:41:57.107826831 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/ethernet/atheros/Makefile 2012-01-03 09:42:03.469747299 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/ethernet/atheros/Makefile.orig compat-wireless-2011-12-18/drivers/net/ethernet/atheros/Makefile +--- compat-wireless-2011-12-18/drivers/net/ethernet/atheros/Makefile.orig 2012-01-05 13:54:21.215595824 -0500 ++++ compat-wireless-2011-12-18/drivers/net/ethernet/atheros/Makefile 2012-01-05 13:54:27.275520064 -0500 @@ -2,7 +2,7 @@ # Makefile for the Atheros network device drivers. # @@ -52,9 +50,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/ethernet/atheros/Makefile.orig co +#obj-$(CONFIG_ATL2) += atlx/ +#obj-$(CONFIG_ATL1E) += atl1e/ +#obj-$(CONFIG_ATL1C) += atl1c/ -diff -up compat-wireless-3.2-rc6-3/drivers/net/usb/Makefile.orig compat-wireless-3.2-rc6-3/drivers/net/usb/Makefile ---- compat-wireless-3.2-rc6-3/drivers/net/usb/Makefile.orig 2012-01-03 09:41:57.108826819 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/usb/Makefile 2012-01-03 09:42:03.469747299 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/usb/Makefile.orig compat-wireless-2011-12-18/drivers/net/usb/Makefile +--- compat-wireless-2011-12-18/drivers/net/usb/Makefile.orig 2012-01-05 13:54:21.215595824 -0500 ++++ compat-wireless-2011-12-18/drivers/net/usb/Makefile 2012-01-05 13:54:27.275520064 -0500 @@ -2,7 +2,7 @@ # Makefile for USB Network drivers # @@ -66,9 +64,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/usb/Makefile.orig compat-wireless +#obj-$(CONFIG_USB_NET_COMPAT_RNDIS_HOST) += rndis_host.o +#obj-$(CONFIG_USB_COMPAT_USBNET) += usbnet.o -diff -up compat-wireless-3.2-rc6-3/Makefile.orig compat-wireless-3.2-rc6-3/Makefile ---- compat-wireless-3.2-rc6-3/Makefile.orig 2012-01-03 09:41:57.109826807 -0500 -+++ compat-wireless-3.2-rc6-3/Makefile 2012-01-03 09:42:03.470747287 -0500 +diff -up compat-wireless-2011-12-18/Makefile.orig compat-wireless-2011-12-18/Makefile +--- compat-wireless-2011-12-18/Makefile.orig 2012-01-05 13:54:21.216595811 -0500 ++++ compat-wireless-2011-12-18/Makefile 2012-01-05 13:54:27.276520051 -0500 @@ -8,8 +8,8 @@ endif export KLIB_BUILD ?= $(KLIB)/build # Sometimes not available in the path diff --git a/compat-wireless-pr_fmt-warning-avoidance.patch b/compat-wireless-pr_fmt-warning-avoidance.patch index 9403b1b68..7ca8f02fc 100644 --- a/compat-wireless-pr_fmt-warning-avoidance.patch +++ b/compat-wireless-pr_fmt-warning-avoidance.patch @@ -1,6 +1,6 @@ -diff -up compat-wireless-3.2-rc6-3/compat/crc8.c.orig compat-wireless-3.2-rc6-3/compat/crc8.c ---- compat-wireless-3.2-rc6-3/compat/crc8.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/compat/crc8.c 2012-01-05 14:17:19.613363481 -0500 +diff -up compat-wireless-2011-12-18/compat/crc8.c.orig compat-wireless-2011-12-18/compat/crc8.c +--- compat-wireless-2011-12-18/compat/crc8.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/compat/crc8.c 2012-01-05 13:40:29.271996550 -0500 @@ -14,6 +14,7 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ @@ -9,9 +9,9 @@ diff -up compat-wireless-3.2-rc6-3/compat/crc8.c.orig compat-wireless-3.2-rc6-3/ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/bcma/bcma_private.h.orig compat-wireless-3.2-rc6-3/drivers/bcma/bcma_private.h ---- compat-wireless-3.2-rc6-3/drivers/bcma/bcma_private.h.orig 2011-12-19 22:45:13.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/bcma/bcma_private.h 2012-01-05 14:17:19.614363468 -0500 +diff -up compat-wireless-2011-12-18/drivers/bcma/bcma_private.h.orig compat-wireless-2011-12-18/drivers/bcma/bcma_private.h +--- compat-wireless-2011-12-18/drivers/bcma/bcma_private.h.orig 2011-12-18 16:10:34.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/bcma/bcma_private.h 2012-01-05 13:40:29.271996550 -0500 @@ -1,6 +1,7 @@ #ifndef LINUX_BCMA_PRIVATE_H_ #define LINUX_BCMA_PRIVATE_H_ @@ -20,9 +20,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/bcma/bcma_private.h.orig compat-wirel #ifndef pr_fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #endif -diff -up compat-wireless-3.2-rc6-3/drivers/net/ethernet/broadcom/b44.c.orig compat-wireless-3.2-rc6-3/drivers/net/ethernet/broadcom/b44.c ---- compat-wireless-3.2-rc6-3/drivers/net/ethernet/broadcom/b44.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/ethernet/broadcom/b44.c 2012-01-05 14:17:19.615363455 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/ethernet/broadcom/b44.c.orig compat-wireless-2011-12-18/drivers/net/ethernet/broadcom/b44.c +--- compat-wireless-2011-12-18/drivers/net/ethernet/broadcom/b44.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/ethernet/broadcom/b44.c 2012-01-05 13:40:29.273996525 -0500 @@ -10,6 +10,7 @@ * Distribute under GPL. */ @@ -31,11 +31,31 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/ethernet/broadcom/b44.c.orig comp #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/brcm80211/brcmsmac/dma.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/brcm80211/brcmsmac/dma.c -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl3945-base.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl3945-base.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl3945-base.c.orig 2012-01-05 14:19:37.561638888 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl3945-base.c 2012-01-05 14:19:45.500539640 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c.orig compat-wireless-2011-12-18/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c +--- compat-wireless-2011-12-18/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c.orig 2012-01-05 13:44:54.137685272 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c 2012-01-05 13:44:56.589654617 -0500 +@@ -16,6 +16,7 @@ + * File contents: support functions for PCI/PCIe + */ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-2011-12-18/drivers/net/wireless/brcm80211/brcmsmac/dma.c.orig compat-wireless-2011-12-18/drivers/net/wireless/brcm80211/brcmsmac/dma.c +--- compat-wireless-2011-12-18/drivers/net/wireless/brcm80211/brcmsmac/dma.c.orig 2012-01-05 13:44:23.579067307 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/brcm80211/brcmsmac/dma.c 2012-01-05 13:44:43.324820451 -0500 +@@ -14,6 +14,7 @@ + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + ++#undef pr_fmt + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include +diff -up compat-wireless-2011-12-18/drivers/net/wireless/iwlegacy/3945-mac.c.orig compat-wireless-2011-12-18/drivers/net/wireless/iwlegacy/3945-mac.c +--- compat-wireless-2011-12-18/drivers/net/wireless/iwlegacy/3945-mac.c.orig 2012-01-05 13:41:22.852326703 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/iwlegacy/3945-mac.c 2012-01-05 13:41:31.209222227 -0500 @@ -27,6 +27,7 @@ * *****************************************************************************/ @@ -44,9 +64,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl3945-base.c. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl4965-base.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl4965-base.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl4965-base.c.orig 2012-01-05 14:19:25.875784981 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl4965-base.c 2012-01-05 14:19:31.017720699 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/iwlegacy/4965-mac.c.orig compat-wireless-2011-12-18/drivers/net/wireless/iwlegacy/4965-mac.c +--- compat-wireless-2011-12-18/drivers/net/wireless/iwlegacy/4965-mac.c.orig 2012-01-05 13:41:47.962012787 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/iwlegacy/4965-mac.c 2012-01-05 13:41:41.547092984 -0500 @@ -27,6 +27,7 @@ * *****************************************************************************/ @@ -55,9 +75,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/iwlegacy/iwl4965-base.c. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/cfg.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/cfg.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/cfg.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/cfg.c 2012-01-05 14:17:22.706324811 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas/cfg.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas/cfg.c +--- compat-wireless-2011-12-18/drivers/net/wireless/libertas/cfg.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/libertas/cfg.c 2012-01-05 13:40:44.681803897 -0500 @@ -6,6 +6,7 @@ * */ @@ -66,9 +86,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/cfg.c.orig comp #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_cs.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_cs.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_cs.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_cs.c 2012-01-05 14:17:22.707324799 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_cs.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_cs.c +--- compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_cs.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_cs.c 2012-01-05 13:40:44.682803885 -0500 @@ -21,6 +21,7 @@ */ @@ -77,9 +97,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_cs.c.orig co #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_sdio.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_sdio.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_sdio.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_sdio.c 2012-01-05 14:17:22.709324775 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_sdio.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_sdio.c +--- compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_sdio.c.orig 2011-12-18 16:10:36.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_sdio.c 2012-01-05 13:40:44.683803873 -0500 @@ -26,6 +26,7 @@ * if_sdio_card_to_host() to pad the data. */ @@ -88,9 +108,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_sdio.c.orig #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_spi.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_spi.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_spi.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_spi.c 2012-01-05 14:17:22.710324763 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_spi.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_spi.c +--- compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_spi.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_spi.c 2012-01-05 13:40:44.685803849 -0500 @@ -17,6 +17,7 @@ * (at your option) any later version. */ @@ -99,9 +119,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_spi.c.orig c #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_usb.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_usb.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_usb.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_usb.c 2012-01-05 14:17:22.711324751 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_usb.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_usb.c +--- compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_usb.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_usb.c 2012-01-05 13:40:44.686803837 -0500 @@ -2,6 +2,7 @@ * This file contains functions used in USB interface module. */ @@ -110,9 +130,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/if_usb.c.orig c #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/main.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/main.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/main.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/main.c 2012-01-05 14:17:22.712324738 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas/main.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas/main.c +--- compat-wireless-2011-12-18/drivers/net/wireless/libertas/main.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/libertas/main.c 2012-01-05 13:40:44.687803825 -0500 @@ -4,6 +4,7 @@ * thread etc.. */ @@ -121,17 +141,17 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/main.c.orig com #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/mesh.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/mesh.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/mesh.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/mesh.c 2012-01-05 14:17:22.713324725 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas/mesh.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas/mesh.c +--- compat-wireless-2011-12-18/drivers/net/wireless/libertas/mesh.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/libertas/mesh.c 2012-01-05 13:40:44.688803813 -0500 @@ -1,3 +1,4 @@ +#undef pr_fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/rx.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/rx.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/rx.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/rx.c 2012-01-05 14:17:22.714324712 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas/rx.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas/rx.c +--- compat-wireless-2011-12-18/drivers/net/wireless/libertas/rx.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/libertas/rx.c 2012-01-05 13:40:44.689803801 -0500 @@ -2,6 +2,7 @@ * This file contains the handling of RX in wlan driver. */ @@ -140,9 +160,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas/rx.c.orig compa #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/cmd.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/cmd.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/cmd.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/cmd.c 2012-01-05 14:17:22.715324699 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/cmd.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/cmd.c +--- compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/cmd.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/cmd.c 2012-01-05 13:40:44.690803789 -0500 @@ -7,6 +7,7 @@ * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. @@ -151,9 +171,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/cmd.c.orig c #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/if_usb.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/if_usb.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/if_usb.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/if_usb.c 2012-01-05 14:17:22.716324687 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/if_usb.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/if_usb.c +--- compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/if_usb.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/if_usb.c 2012-01-05 13:40:44.691803776 -0500 @@ -9,6 +9,7 @@ */ #define DRV_NAME "lbtf_usb" @@ -162,9 +182,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/if_usb.c.ori #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include "libertas_tf.h" -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/main.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/main.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/main.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/main.c 2012-01-05 14:17:22.717324675 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/main.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/main.c +--- compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/main.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/main.c 2012-01-05 13:40:44.692803763 -0500 @@ -7,6 +7,7 @@ * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. @@ -173,9 +193,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/libertas_tf/main.c.orig #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/base.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/base.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/base.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/base.c 2012-01-05 14:17:22.719324651 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/base.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/base.c +--- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/base.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/base.c 2012-01-05 13:40:44.693803750 -0500 @@ -27,6 +27,7 @@ * *****************************************************************************/ @@ -184,9 +204,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/base.c.orig comp #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/cam.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/cam.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/cam.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/cam.c 2012-01-05 14:17:22.719324651 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/cam.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/cam.c +--- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/cam.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/cam.c 2012-01-05 13:40:44.694803737 -0500 @@ -27,6 +27,7 @@ * *****************************************************************************/ @@ -195,9 +215,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/cam.c.orig compa #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-05 14:17:22.720324638 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +--- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-05 13:40:44.694803737 -0500 @@ -27,6 +27,7 @@ * *****************************************************************************/ @@ -206,9 +226,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192c/fw_comm #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c 2012-01-05 14:17:22.722324612 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +--- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c 2012-01-05 13:40:44.695803725 -0500 @@ -27,6 +27,7 @@ * *****************************************************************************/ @@ -217,9 +237,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c.o #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include "../wifi.h" -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c 2012-01-05 14:17:22.724324587 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c +--- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c 2012-01-05 13:40:44.695803725 -0500 @@ -27,6 +27,7 @@ * ****************************************************************************/ @@ -228,9 +248,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192de/sw.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192de/sw.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192de/sw.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192de/sw.c 2012-01-05 14:17:22.724324587 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192de/sw.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +--- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192de/sw.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192de/sw.c 2012-01-05 13:40:44.695803725 -0500 @@ -27,6 +27,7 @@ * *****************************************************************************/ @@ -239,9 +259,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192de/sw.c.o #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/hw.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/hw.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/hw.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/hw.c 2012-01-05 14:17:22.725324575 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/hw.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/hw.c +--- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/hw.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/hw.c 2012-01-05 13:40:44.696803713 -0500 @@ -27,6 +27,7 @@ * *****************************************************************************/ @@ -250,9 +270,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/hw.c.o #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include "../wifi.h" -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/phy.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/phy.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/phy.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/phy.c 2012-01-05 14:17:22.726324563 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/phy.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/phy.c +--- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/phy.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/phy.c 2012-01-05 13:40:44.696803713 -0500 @@ -27,6 +27,7 @@ * *****************************************************************************/ @@ -261,9 +281,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/phy.c. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include "../wifi.h" -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/rf.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/rf.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/rf.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/rf.c 2012-01-05 14:17:22.726324563 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/rf.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/rf.c +--- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/rf.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/rf.c 2012-01-05 13:40:44.697803701 -0500 @@ -27,6 +27,7 @@ * *****************************************************************************/ @@ -272,9 +292,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/rf.c.o #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include "../wifi.h" -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/sw.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/sw.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/sw.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/sw.c 2012-01-05 14:17:22.726324563 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/sw.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +--- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/sw.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/sw.c 2012-01-05 13:40:44.697803701 -0500 @@ -27,6 +27,7 @@ * *****************************************************************************/ @@ -283,9 +303,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/rtl8192se/sw.c.o #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/usb.c.orig compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/usb.c ---- compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/usb.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/usb.c 2012-01-05 14:17:22.727324551 -0500 +diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/usb.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/usb.c +--- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/usb.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/usb.c 2012-01-05 13:40:44.697803701 -0500 @@ -25,6 +25,7 @@ * *****************************************************************************/ @@ -294,9 +314,9 @@ diff -up compat-wireless-3.2-rc6-3/drivers/net/wireless/rtlwifi/usb.c.orig compa #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/net/wireless/core.c.orig compat-wireless-3.2-rc6-3/net/wireless/core.c ---- compat-wireless-3.2-rc6-3/net/wireless/core.c.orig 2011-12-19 22:45:14.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/net/wireless/core.c 2012-01-05 14:17:22.727324551 -0500 +diff -up compat-wireless-2011-12-18/net/wireless/core.c.orig compat-wireless-2011-12-18/net/wireless/core.c +--- compat-wireless-2011-12-18/net/wireless/core.c.orig 2011-12-18 16:10:35.000000000 -0500 ++++ compat-wireless-2011-12-18/net/wireless/core.c 2012-01-05 13:40:44.698803689 -0500 @@ -4,6 +4,7 @@ * Copyright 2006-2010 Johannes Berg */ @@ -305,9 +325,9 @@ diff -up compat-wireless-3.2-rc6-3/net/wireless/core.c.orig compat-wireless-3.2- #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/net/wireless/lib80211.c.orig compat-wireless-3.2-rc6-3/net/wireless/lib80211.c ---- compat-wireless-3.2-rc6-3/net/wireless/lib80211.c.orig 2011-12-19 22:45:13.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/net/wireless/lib80211.c 2012-01-05 14:17:22.727324551 -0500 +diff -up compat-wireless-2011-12-18/net/wireless/lib80211.c.orig compat-wireless-2011-12-18/net/wireless/lib80211.c +--- compat-wireless-2011-12-18/net/wireless/lib80211.c.orig 2011-12-18 16:10:34.000000000 -0500 ++++ compat-wireless-2011-12-18/net/wireless/lib80211.c 2012-01-05 13:40:44.698803689 -0500 @@ -13,6 +13,7 @@ * */ @@ -316,9 +336,9 @@ diff -up compat-wireless-3.2-rc6-3/net/wireless/lib80211.c.orig compat-wireless- #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/net/wireless/lib80211_crypt_tkip.c.orig compat-wireless-3.2-rc6-3/net/wireless/lib80211_crypt_tkip.c ---- compat-wireless-3.2-rc6-3/net/wireless/lib80211_crypt_tkip.c.orig 2011-12-19 22:45:13.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/net/wireless/lib80211_crypt_tkip.c 2012-01-05 14:17:22.727324551 -0500 +diff -up compat-wireless-2011-12-18/net/wireless/lib80211_crypt_tkip.c.orig compat-wireless-2011-12-18/net/wireless/lib80211_crypt_tkip.c +--- compat-wireless-2011-12-18/net/wireless/lib80211_crypt_tkip.c.orig 2011-12-18 16:10:34.000000000 -0500 ++++ compat-wireless-2011-12-18/net/wireless/lib80211_crypt_tkip.c 2012-01-05 13:40:44.698803689 -0500 @@ -10,6 +10,7 @@ * more details. */ @@ -327,9 +347,9 @@ diff -up compat-wireless-3.2-rc6-3/net/wireless/lib80211_crypt_tkip.c.orig compa #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/net/wireless/reg.c.orig compat-wireless-3.2-rc6-3/net/wireless/reg.c ---- compat-wireless-3.2-rc6-3/net/wireless/reg.c.orig 2011-12-19 22:45:13.000000000 -0500 -+++ compat-wireless-3.2-rc6-3/net/wireless/reg.c 2012-01-05 14:17:22.728324538 -0500 +diff -up compat-wireless-2011-12-18/net/wireless/reg.c.orig compat-wireless-2011-12-18/net/wireless/reg.c +--- compat-wireless-2011-12-18/net/wireless/reg.c.orig 2011-12-18 16:10:34.000000000 -0500 ++++ compat-wireless-2011-12-18/net/wireless/reg.c 2012-01-05 13:40:44.699803676 -0500 @@ -33,6 +33,7 @@ * */ @@ -338,9 +358,9 @@ diff -up compat-wireless-3.2-rc6-3/net/wireless/reg.c.orig compat-wireless-3.2-r #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -diff -up compat-wireless-3.2-rc6-3/patches/98-pr_fmt.patch.orig compat-wireless-3.2-rc6-3/patches/98-pr_fmt.patch ---- compat-wireless-3.2-rc6-3/patches/98-pr_fmt.patch.orig 2012-01-05 14:17:22.728324538 -0500 -+++ compat-wireless-3.2-rc6-3/patches/98-pr_fmt.patch 2012-01-05 14:17:22.728324538 -0500 +diff -up compat-wireless-2011-12-18/patches/98-pr_fmt.patch.orig compat-wireless-2011-12-18/patches/98-pr_fmt.patch +--- compat-wireless-2011-12-18/patches/98-pr_fmt.patch.orig 2012-01-05 13:39:36.552655633 -0500 ++++ compat-wireless-2011-12-18/patches/98-pr_fmt.patch 2012-01-05 13:39:36.553655620 -0500 @@ -0,0 +1,346 @@ +The way the compat-* header files are included causes the default +pr_fmt definition from to be evaluated for every file. diff --git a/compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch b/compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch index bdc8a5492..7a3792c25 100644 --- a/compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch +++ b/compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch @@ -1,45 +1,13 @@ -A recent LKML thread (http://lkml.indiana.edu/hypermail/linux/kernel/1112.3/00965.html) -discusses warnings that occur during a suspend/resume cycle. The driver -attempts to read the firmware file before userspace is ready, leading to the -following warning: - -WARNING: at drivers/base/firmware_class.c:537 _request_firmware+0x3f6/0x420() - -For rtl8192cu, the problem is fixed by storing the firmware in a global buffer -rather than one allocated per device. The usage count is increased when -suspending and decreased when resuming. This way, the firmware is retained -through a suspend/resume cycle, and does not have to be reread. - -This patch should fix the bug reported in -https://bugzilla.redhat.com/show_bug.cgi?id=771002. - -Note: This patch also touches rtl8192ce as the "firmware" loaded message -is now printed in the wrong place. -Note: This patch also touches rtl8192ce as the "firmware" loaded message -is now printed in the wrong place. - -Reported-by: Mohammed Arafa -Reported-by: Dave Jones -Signed-off-by: Larry Finger -Cc: Linus Torvalds -Cc: Stable - ---- - drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 1 - - drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 1 + - drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 58 +++++++++++++++++---- - 3 files changed, 49 insertions(+), 11 deletions(-) - ---- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:07:58.830625006 -0500 -+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:08:06.825439927 -0500 -@@ -227,7 +227,6 @@ int rtl92c_download_fw(struct ieee80211_ - u32 fwsize; - enum version_8192c version = rtlhal->version; - -- pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +@@ -265,7 +265,6 @@ int rtl92c_download_fw(struct ieee80211_ if (!rtlhal->pfirmware) return 1; - + +- pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); + pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; + pfwdata = (u8 *) rtlhal->pfirmware; + fwsize = rtlhal->fwsize; --- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -186,6 +186,7 @@ int rtl92c_init_sw_vars(struct ieee80211 diff --git a/config-arm-generic b/config-arm-generic index 307c66d68..558c7c4d0 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -142,8 +142,6 @@ CONFIG_SPARSE_IRQ=y # CONFIG_ARM_PATCH_PHYS_VIRT is not set -CONFIG_FTMAC100=m - CONFIG_HWSPINLOCK_OMAP=m CONFIG_USE_OF=y @@ -154,7 +152,17 @@ CONFIG_MMC_SDHCI_OF=m CONFIG_MMC_SDHCI_PXAV3=m CONFIG_MMC_SDHCI_PXAV2=m -CONFIG_FTGMAC100=m +CONFIG_ARM_APPENDED_DTB=y +CONFIG_MTD_OF_PARTS=y +CONFIG_PL330_DMA=y +# CONFIG_ARM_KPROBES_TEST is not set +# CONFIG_ARM_ATAG_DTB_COMPAT is not set + +# CONFIG_FTGMAC100 is not set +# CONFIG_FTMAC100 is not set +# +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +CONFIG_LSM_MMAP_MIN_ADDR=32768 # disable TPM on arm at least on the trimslices it causes havoc # CONFIG_TCG_TPM is not set @@ -171,3 +179,18 @@ CONFIG_FTGMAC100=m # CONFIG_DRM_RADEON is not set # CONFIG_ATM_HE is not set # CONFIG_SCSI_ACARD is not set + +# these all currently fail due to missing symbols __bad_udelay or +# error: implicit declaration of function ‘iowrite32be’ +# CONFIG_SND_ALI5451 is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_MLX4_EN is not set + +# FIXME: Guesses, need checking +# CONFIG_MACH_EUKREA_CPUIMX35SD is not set +CONFIG_ARM_ERRATA_720789=y +CONFIG_ARM_ERRATA_751472=y +# CONFIG_FB_MX3 is not set +# CONFIG_MX3_IPU is not set +# CONFIG_MX3_IPU_IRQS is not set + diff --git a/config-arm-highbank b/config-arm-highbank index 18fc0c4cc..d4aca8222 100644 --- a/config-arm-highbank +++ b/config-arm-highbank @@ -1,3 +1,16 @@ ONFIG_ARCH_HIGHBANK=y CONFIG_VFP=y CONFIG_NEON=y + +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEBUG=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_STAT_DETAILS=y diff --git a/config-arm-imx b/config-arm-imx index 5ed7ae2ed..2dbe10a1f 100644 --- a/config-arm-imx +++ b/config-arm-imx @@ -93,3 +93,6 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m CONFIG_CPU_FREQ_TABLE=y CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y + +CONFIG_PL310_ERRATA_769419=y +CONFIG_LEDS_RENESAS_TPU=y diff --git a/config-arm-kirkwood b/config-arm-kirkwood index 6aa045cd9..415e822dc 100644 --- a/config-arm-kirkwood +++ b/config-arm-kirkwood @@ -40,4 +40,4 @@ CONFIG_RTC_DRV_MV=m CONFIG_MV_XOR=y CONFIG_CRYPTO_DEV_MV_CESA=m - +# CONFIG_TOUCHSCREEN_EETI is not set diff --git a/config-arm-omap-generic b/config-arm-omap-generic index b4163bc5a..d623e1817 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -148,7 +148,6 @@ CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y CONFIG_HW_PERF_EVENTS=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_KSM is not set -CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 # CONFIG_CC_STACKPROTECTOR is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 @@ -183,10 +182,6 @@ CONFIG_PM_SLEEP_SMP=y # CONFIG_APM_EMULATION is not set CONFIG_ARCH_HAS_OPP=y CONFIG_PM_OPP=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPGRE_DEMUX is not set # CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set # CONFIG_ARPD is not set @@ -412,7 +407,6 @@ CONFIG_SERIAL_8250_DETECT_IRQ=y CONFIG_SERIAL_OMAP=y CONFIG_SERIAL_OMAP_CONSOLE=y # CONFIG_SERIAL_IFX6X60 is not set -# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM_TIMERIOMEM is not set # CONFIG_R3964 is not set @@ -448,7 +442,6 @@ CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y # CONFIG_DEBUG_GPIO is not set CONFIG_GPIO_SYSFS=y -# CONFIG_GPIO_GENERIC_PLATFORM is not set # # Memory mapped GPIO expanders: @@ -624,12 +617,6 @@ CONFIG_REGULATOR_TWL4030=y # CONFIG_REGULATOR_ISL6271A is not set # CONFIG_REGULATOR_AD5398 is not set # CONFIG_REGULATOR_TPS6524X is not set -CONFIG_MEDIA_SUPPORT=y -CONFIG_RC_CORE=y -CONFIG_LIRC=y -CONFIG_IR_RC5_SZ_DECODER=y -CONFIG_IR_LIRC_CODEC=y -# CONFIG_RC_LOOPBACK is not set CONFIG_VIDEOBUF_DMA_CONTIG=m CONFIG_V4L2_MEM2MEM_DEV=m # CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set @@ -806,25 +793,6 @@ CONFIG_SND_SOC_TLV320AIC3X=y CONFIG_SND_SOC_TWL4030=y CONFIG_SND_SOC_TWL6040=y # CONFIG_SOUND_PRIME is not set -CONFIG_HID=y -CONFIG_HID_3M_PCT=m -CONFIG_HID_A4TECH=m -# CONFIG_HID_ACRUX is not set -CONFIG_HID_APPLE=m -CONFIG_HID_BELKIN=m -CONFIG_HID_CHERRY=m -CONFIG_HID_CHICONY=m -CONFIG_HID_CYPRESS=m -CONFIG_HID_EZKEY=m -CONFIG_HID_KYE=m -CONFIG_HID_KENSINGTON=m -CONFIG_HID_LOGITECH=m -CONFIG_HID_MICROSOFT=m -CONFIG_HID_MOSART=m -CONFIG_HID_MONTEREY=m -CONFIG_HID_NTRIG=m -CONFIG_HID_QUANTA=m -CONFIG_HID_STANTUM=m # CONFIG_HID_TIVO_SLIDE is not set # CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set # CONFIG_USB_DEVICEFS is not set @@ -991,11 +959,6 @@ CONFIG_QUOTA_TREE=m CONFIG_QFMT_V1=m CONFIG_QFMT_V2=m CONFIG_AUTOFS4_FS=m -CONFIG_ISO9660_FS=m -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_NTFS_DEBUG is not set # CONFIG_NTFS_RW is not set # CONFIG_JFFS2_SUMMARY is not set @@ -1063,9 +1026,6 @@ CONFIG_EARLY_PRINTK=y # CONFIG_DEBUG_ICEDCC is not set CONFIG_OC_ETM=y # CONFIG_KEYS_DEBUG_PROC_KEYS is not set -# CONFIG_SECURITY_NETWORK_XFRM is not set -CONFIG_LSM_MMAP_MIN_ADDR=0 -CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0 # CONFIG_IMA is not set CONFIG_CRYPTO_AEAD=m CONFIG_CRYPTO_RNG=m @@ -1099,3 +1059,27 @@ CONFIG_LIBCRC32C=y # CONFIG_USB_HSO is not set CONFIG_CRYSTALHD=m + +CONFIG_GPIO_GENERIC_PLATFORM=y + +CONFIG_MACH_OMAP_GENERIC=y +CONFIG_PL310_ERRATA_753970=y +CONFIG_ARM_CPU_TOPOLOGY=y +CONFIG_SCHED_MC=y +CONFIG_SCHED_SMT=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_BROADCOM=y +CONFIG_NET_VENDOR_MICROCHIP=y +CONFIG_SENSORS_AD7314=m +CONFIG_REGULATOR_GPIO=y +CONFIG_VIDEO_MT9P031=m +CONFIG_VIDEO_MT9T001=m +CONFIG_VIDEO_S5K6AA=m +CONFIG_PANEL_DVI=m +CONFIG_PANEL_PICODLP=m +CONFIG_USB_RENESAS_USBHS=m +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +CONFIG_LEDS_RENESAS_TPU=y +# CONFIG_OMAP_IOMMU is not set +CONFIG_USB_RENESAS_USBHS_HCD=m + diff --git a/config-arm-tegra b/config-arm-tegra index b131978d2..495e91e65 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -83,3 +83,10 @@ CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y CONFIG_CRYSTALHD=m + +CONFIG_MACH_VENTANA=y +CONFIG_PL310_ERRATA_753970=y +CONFIG_ARM_CPU_TOPOLOGY=y +CONFIG_SCHED_MC=y +CONFIG_SCHED_SMT=y +CONFIG_LEDS_RENESAS_TPU=y diff --git a/config-backports b/config-backports index c1b178176..33a3adcce 100644 --- a/config-backports +++ b/config-backports @@ -11,6 +11,11 @@ # CONFIG_SSB is not set # CONFIG_B44 is not set +# +# Prevent b43 and brcmsmac from competing +# +# CONFIG_B43_BCMA is not set + # # These have to be turned-on again since compat-wireless does not # provide them... diff --git a/config-debug b/config-debug index a25239038..19ae4656f 100644 --- a/config-debug +++ b/config-debug @@ -24,6 +24,7 @@ CONFIG_FAIL_MAKE_REQUEST=y CONFIG_FAULT_INJECTION_DEBUG_FS=y CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y CONFIG_FAIL_IO_TIMEOUT=y +CONFIG_FAIL_MMC_REQUEST=y CONFIG_SLUB_DEBUG_ON=y @@ -81,7 +82,6 @@ CONFIG_CARL9170_DEBUGFS=y CONFIG_IWLWIFI_DEVICE_TRACING=y CONFIG_DEBUG_OBJECTS_WORK=y -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set CONFIG_DMADEVICES_DEBUG=y CONFIG_DMADEVICES_VDEBUG=y @@ -99,9 +99,8 @@ CONFIG_KDB_KEYBOARD=y CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y CONFIG_TEST_LIST_SORT=y -CONFIG_DEBUG_SET_MODULE_RONX=y - CONFIG_DETECT_HUNG_TASK=y CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y diff --git a/config-generic b/config-generic index b620c953e..7c327d4a2 100644 --- a/config-generic +++ b/config-generic @@ -32,7 +32,7 @@ CONFIG_KERNEL_GZIP=y CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_BSD_PROCESS_ACCT=y -# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_FHANDLE=y CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y @@ -68,6 +68,7 @@ CONFIG_SLUB=y CONFIG_MISC_DEVICES=y # CONFIG_AD525X_DPOT is not set +# CONFIG_ATMEL_PWM is not set CONFIG_IWMC3200TOP=m # CONFIG_IWMC3200TOP_DEBUG is not set CONFIG_IWMC3200TOP_DEBUGFS=y @@ -80,7 +81,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_LOAD is not set # -- MODULE_FORCE_UNLOAD is controlled by config-debug/nodebug # CONFIG_MODVERSIONS is not set -CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_MODULE_SRCVERSION_ALL is not set # # Bus options (PCI, PCMCIA, EISA, MCA, ISA) @@ -89,6 +90,8 @@ CONFIG_PCI=y # CONFIG_PCI_DEBUG is not set CONFIG_PCI_STUB=y CONFIG_PCI_IOV=y +CONFIG_PCI_PRI=y +CONFIG_PCI_PASID=y CONFIG_HT_IRQ=y CONFIG_PCI_MSI=y CONFIG_PCIEPORTBUS=y @@ -157,6 +160,7 @@ CONFIG_INFINIBAND_AMSO1100=m # CONFIG_INFINIBAND_AMSO1100_DEBUG is not set CONFIG_INFINIBAND_CXGB3=m CONFIG_INFINIBAND_CXGB4=m +CONFIG_SCSI_CXGB3_ISCSI=m CONFIG_SCSI_CXGB4_ISCSI=m # CONFIG_INFINIBAND_CXGB3_DEBUG is not set CONFIG_MLX4_INFINIBAND=m @@ -273,6 +277,7 @@ CONFIG_MTDRAM_ERASE_SIZE=128 # CONFIG_MTD_DOCPROBE is not set # CONFIG_MTD_DOCPROBE_ADVANCED is not set # CONFIG_MTD_DOCPROBE_ADDRESS is not set +# CONFIG_MTD_DOCG3 is not set # # NAND Flash Device Drivers @@ -351,6 +356,7 @@ CONFIG_BLK_CPQ_DA=m CONFIG_BLK_CPQ_CISS_DA=m CONFIG_CISS_SCSI_TAPE=y CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_DRBD=m CONFIG_BLK_DEV_UMEM=m CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 @@ -432,6 +438,7 @@ CONFIG_BLK_DEV_IDEDMA=y CONFIG_VIRTIO_BLK=m CONFIG_VIRTIO_PCI=y CONFIG_VIRTIO_BALLOON=m +CONFIG_VIRTIO_MMIO=m CONFIG_VIRTIO_NET=m CONFIG_VMXNET3=m CONFIG_HW_RANDOM_VIRTIO=m @@ -498,15 +505,13 @@ CONFIG_SCSI_3W_9XXX=m CONFIG_SCSI_ACARD=m CONFIG_SCSI_AACRAID=m CONFIG_SCSI_AIC7XXX=m -CONFIG_SCSI_AIC94XX=m -# CONFIG_AIC94XX_DEBUG is not set +CONFIG_SCSI_AIC7XXX_OLD=m CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 CONFIG_AIC7XXX_RESET_DELAY_MS=15000 # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set # CONFIG_AIC7XXX_DEBUG_ENABLE is not set CONFIG_AIC7XXX_DEBUG_MASK=0 # CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set -CONFIG_SCSI_AIC7XXX_OLD=m CONFIG_SCSI_AIC79XX=m CONFIG_AIC79XX_CMDS_PER_DEVICE=4 CONFIG_AIC79XX_RESET_DELAY_MS=15000 @@ -514,6 +519,8 @@ CONFIG_AIC79XX_RESET_DELAY_MS=15000 # CONFIG_AIC79XX_DEBUG_ENABLE is not set CONFIG_AIC79XX_DEBUG_MASK=0 # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC94XX=m +# CONFIG_AIC94XX_DEBUG is not set # CONFIG_SCSI_ADVANSYS is not set CONFIG_SCSI_BFA_FC=m CONFIG_MEGARAID_NEWGEN=y @@ -528,6 +535,8 @@ CONFIG_SCSI_MPT2SAS=m CONFIG_SCSI_MPT2SAS_MAX_SGE=128 CONFIG_SCSI_MPT2SAS_LOGGING=y +CONFIG_SCSI_MVUMI=m + CONFIG_SCSI_OSD_INITIATOR=m CONFIG_SCSI_OSD_ULD=m CONFIG_SCSI_OSD_DPRINT_SENSE=1 @@ -543,6 +552,59 @@ CONFIG_SCSI_PM8001=m CONFIG_VMWARE_PVSCSI=m CONFIG_VMWARE_BALLOON=m +# CONFIG_SCSI_ARCMSR is not set +CONFIG_SCSI_BUSLOGIC=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_FLASHPOINT=y +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INIA100=m +# CONFIG_SCSI_PPA is not set +# CONFIG_SCSI_IMM is not set +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_STEX=m +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_DC395x=m +# CONFIG_SCSI_NSP32 is not set +CONFIG_SCSI_DEBUG=m +CONFIG_SCSI_DC390T=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_QLA_ISCSI=m +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_DPT_I2O is not set +CONFIG_SCSI_LPFC=m +# CONFIG_SCSI_LPFC_DEBUG_FS is not set + +# PCMCIA SCSI adapter support +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set + +# ISA SCSI Controllers. Sorry your life sucks. +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_ULTRASTOR is not set + + CONFIG_ATA=y CONFIG_ATA_BMDMA=y CONFIG_ATA_VERBOSE_ERROR=y @@ -622,48 +684,6 @@ CONFIG_PATA_VIA=m CONFIG_PATA_WINBOND=m CONFIG_PATA_ATP867X=m -CONFIG_SCSI_BUSLOGIC=m -CONFIG_SCSI_INITIO=m -CONFIG_SCSI_FLASHPOINT=y -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -CONFIG_SCSI_GDTH=m -CONFIG_SCSI_HPTIOP=m -CONFIG_SCSI_IPS=m -CONFIG_SCSI_INIA100=m -CONFIG_SCSI_PPA=m -CONFIG_SCSI_IMM=m -# CONFIG_SCSI_IZIP_EPP16 is not set -# CONFIG_SCSI_IZIP_SLOW_CTR is not set -CONFIG_SCSI_STEX=m -CONFIG_SCSI_SYM53C8XX_2=m -CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 -CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 -CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -CONFIG_SCSI_SYM53C8XX_MMIO=y -CONFIG_SCSI_QLOGIC_1280=m -CONFIG_SCSI_DC395x=m -# CONFIG_SCSI_NSP32 is not set -CONFIG_SCSI_DEBUG=m -CONFIG_SCSI_DC390T=m -CONFIG_SCSI_QLA_FC=m -CONFIG_SCSI_QLA_ISCSI=m -# CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_DPT_I2O is not set -CONFIG_SCSI_LPFC=m - -# -# PCMCIA SCSI adapter support -# -CONFIG_SCSI_LOWLEVEL_PCMCIA=y -CONFIG_PCMCIA_AHA152X=m -# CONFIG_PCMCIA_FDOMAIN is not set -CONFIG_PCMCIA_NINJA_SCSI=m -CONFIG_PCMCIA_QLOGIC=m -CONFIG_PCMCIA_SYM53C500=m - # # Multi-device support (RAID and LVM) @@ -687,6 +707,9 @@ CONFIG_DM_DEBUG=y CONFIG_DM_MIRROR=y CONFIG_DM_MULTIPATH=m CONFIG_DM_SNAPSHOT=y +CONFIG_DM_THIN_PROVISIONING=m +# CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set +# CONFIG_DM_DEBUG_SPACE_MAPS is not set CONFIG_DM_UEVENT=y CONFIG_DM_ZERO=y CONFIG_DM_LOG_USERSPACE=m @@ -737,6 +760,8 @@ CONFIG_FIREWIRE_NOSY=m # CONFIG_NET=y +CONFIG_NET_DMA=y + CONFIG_TCP_CONG_ADVANCED=y CONFIG_TCP_CONG_BIC=m CONFIG_TCP_CONG_CUBIC=y @@ -801,6 +826,7 @@ CONFIG_IP_VS_PROTO_UDP=y CONFIG_IP_VS_PROTO_ESP=y CONFIG_IP_VS_PROTO_AH=y CONFIG_IP_VS_PROTO_SCTP=y +CONFIG_IP_VS_IPV6=y CONFIG_IP_VS_RR=m CONFIG_IP_VS_WRR=m CONFIG_IP_VS_LC=m @@ -845,21 +871,31 @@ CONFIG_NET_9P_RDMA=m # CONFIG_DECNET is not set CONFIG_BRIDGE=m CONFIG_BRIDGE_IGMP_SNOOPING=y + +# PHY timestamping adds overhead # CONFIG_NETWORK_PHY_TIMESTAMPING is not set + CONFIG_NETFILTER=y CONFIG_NETFILTER_ADVANCED=y CONFIG_NF_CONNTRACK=m CONFIG_NETFILTER_NETLINK=m CONFIG_NETFILTER_NETLINK_QUEUE=m CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_TPROXY=m CONFIG_NETFILTER_XTABLES=y CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_MARK=m CONFIG_NETFILTER_XT_CONNMARK=m + +CONFIG_NETFILTER_XT_TARGET_AUDIT=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m CONFIG_NETFILTER_XT_TARGET_CONNMARK=m CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m CONFIG_NETFILTER_XT_TARGET_MARK=m CONFIG_NETFILTER_XT_TARGET_NFLOG=m CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m @@ -870,24 +906,31 @@ CONFIG_NETFILTER_XT_TARGET_TCPMSS=m CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER_XT_TARGET_TEE=m -CONFIG_NETFILTER_XT_TARGET_LED=m -CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m + +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CPU=m CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m CONFIG_NETFILTER_XT_MATCH_CONNMARK=m CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m CONFIG_NETFILTER_XT_MATCH_DSCP=m CONFIG_NETFILTER_XT_MATCH_ESP=m CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_HL=m CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m CONFIG_NETFILTER_XT_MATCH_LENGTH=m CONFIG_NETFILTER_XT_MATCH_LIMIT=m CONFIG_NETFILTER_XT_MATCH_MAC=m CONFIG_NETFILTER_XT_MATCH_MARK=m CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m CONFIG_NETFILTER_XT_MATCH_OWNER=m CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m @@ -895,23 +938,15 @@ CONFIG_NETFILTER_XT_MATCH_POLICY=m CONFIG_NETFILTER_XT_MATCH_QUOTA=m CONFIG_NETFILTER_XT_MATCH_RATEEST=m CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m CONFIG_NETFILTER_XT_MATCH_STATE=y CONFIG_NETFILTER_XT_MATCH_STATISTIC=m CONFIG_NETFILTER_XT_MATCH_STRING=m CONFIG_NETFILTER_XT_MATCH_TCPMSS=m CONFIG_NETFILTER_XT_MATCH_TIME=m CONFIG_NETFILTER_XT_MATCH_U32=m -CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -CONFIG_NETFILTER_XT_MATCH_HL=m -CONFIG_NETFILTER_XT_MATCH_OSF=m -CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m -CONFIG_NETFILTER_XT_MATCH_CPU=m -CONFIG_NETFILTER_XT_MATCH_IPVS=m -CONFIG_NETFILTER_XT_TARGET_AUDIT=m -CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m -CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m # CONFIG_NETFILTER_DEBUG is not set CONFIG_BRIDGE_NETFILTER=y @@ -1058,7 +1093,7 @@ CONFIG_LLC=m CONFIG_IPX=m # CONFIG_IPX_INTERN is not set CONFIG_ATALK=m -CONFIG_DEV_APPLETALK=y +CONFIG_DEV_APPLETALK=m CONFIG_IPDDP=m CONFIG_IPDDP_ENCAP=y CONFIG_IPDDP_DECAP=y @@ -1072,7 +1107,7 @@ CONFIG_IP_DCCP_CCID2=m CONFIG_IP_DCCP_CCID3=y # CONFIG_IP_DCCP_CCID3_DEBUG is not set # CONFIG_IP_DCCP_DEBUG is not set -CONFIG_NET_DCCPPROBE=m +# CONFIG_NET_DCCPPROBE is not set # # TIPC Configuration (EXPERIMENTAL) @@ -1102,6 +1137,7 @@ CONFIG_NET_SCH_TBF=m CONFIG_NET_SCH_TEQL=m CONFIG_NET_SCH_SFB=m CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_MULTIQ=m CONFIG_NET_SCH_CHOKE=m CONFIG_NET_SCH_QFQ=m CONFIG_NET_CLS=y @@ -1127,6 +1163,7 @@ CONFIG_NET_EMATCH_STACK=32 CONFIG_NET_EMATCH_TEXT=m CONFIG_NET_EMATCH_U32=m +CONFIG_NET_ACT_CSUM=m CONFIG_NET_ACT_GACT=m CONFIG_GACT_PROB=y CONFIG_NET_ACT_IPT=m @@ -1135,7 +1172,7 @@ CONFIG_NET_ACT_NAT=m CONFIG_NET_ACT_PEDIT=m CONFIG_NET_ACT_POLICE=m CONFIG_NET_ACT_SIMP=m -CONFIG_NET_ACT_CSUM=m +CONFIG_NET_ACT_SKBEDIT=m CONFIG_DCB=y @@ -1221,10 +1258,191 @@ CONFIG_RFKILL_INPUT=y # # Ethernet (10 or 100Mbit) # -CONFIG_NETDEV_1000=y -CONFIG_NETDEV_10000=y -CONFIG_NET_ETHERNET=y -CONFIG_PHYLIB=m + +CONFIG_NET_VENDOR_ADAPTEC=y +CONFIG_ADAPTEC_STARFIRE=m + +CONFIG_NET_VENDOR_ALTEON=y +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set + +CONFIG_NET_VENDOR_AMD=y +# CONFIG_LANCE is not set +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_PCMCIA_NMCLAN=m + +CONFIG_NET_VENDOR_ATHEROS=y +CONFIG_ATL2=m +CONFIG_ATL1=m +CONFIG_ATL1C=m +CONFIG_ATL1E=m + +CONFIG_NET_VENDOR_BROCADE=y +CONFIG_BNA=m + +CONFIG_NET_VENDOR_CHELSIO=y +CONFIG_CHELSIO_T1=m +CONFIG_CHELSIO_T1_1G=y +CONFIG_CHELSIO_T3=m +CONFIG_CHELSIO_T4=m +CONFIG_CHELSIO_T4VF=m + +# CONFIG_NET_VENDOR_CIRRUS is not set +# +CONFIG_NET_VENDOR_CISCO=y +CONFIG_ENIC=m + +CONFIG_NET_VENDOR_DEC=y +CONFIG_EWRK3=m +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_DE2104X_DSL=0 +CONFIG_TULIP=m +# CONFIG_TULIP_NAPI is not set +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_NI5010 is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_PCMCIA_XIRCOM=m +CONFIG_ULI526X=m + +CONFIG_NET_VENDOR_DLINK=y +CONFIG_DE600=m +CONFIG_DE620=m +CONFIG_DL2K=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set + +CONFIG_NET_VENDOR_EMULEX=y +CONFIG_BE2NET=m + +CONFIG_NET_VENDOR_EXAR=y +CONFIG_S2IO=m +CONFIG_VXGE=m +# CONFIG_VXGE_DEBUG_TRACE_ALL is not set + +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_FUJITSU is not set +# CONFIG_NET_VENDOR_HP is not set +CONFIG_NET_VENDOR_INTEL=y +CONFIG_E100=m +CONFIG_E1000=m +CONFIG_E1000E=m +CONFIG_IGB=m +CONFIG_IGB_DCA=y +CONFIG_IGBVF=m +CONFIG_IXGB=m +CONFIG_IXGBEVF=m +CONFIG_IXGBE=m +CONFIG_IXGBE_DCA=y +CONFIG_IXGBE_DCB=y + +# CONFIG_NET_VENDOR_I825XX is not set +CONFIG_NET_VENDOR_MARVELL=y +CONFIG_SKGE=m +# CONFIG_SKGE_DEBUG is not set +CONFIG_SKGE_GENESIS=y +CONFIG_SKY2=m +# CONFIG_SKY2_DEBUG is not set + +CONFIG_NET_VENDOR_MICREL=y +CONFIG_KSZ884X_PCI=m +# CONFIG_KS8842 is not set +# CONFIG_KS8851_MLL is not set + +CONFIG_NET_VENDOR_MYRI=y +CONFIG_MYRI10GE=m +CONFIG_MYRI10GE_DCA=y + +CONFIG_NET_VENDOR_NATSEMI=y +CONFIG_NATSEMI=m +CONFIG_NS83820=m + +CONFIG_NET_VENDOR_8390=y +# CONFIG_AC3200 is not set +CONFIG_PCMCIA_AXNET=m +CONFIG_NE2K_PCI=m +CONFIG_NE3210=m +CONFIG_PCMCIA_PCNET=m + +CONFIG_NET_VENDOR_NVIDIA=y +CONFIG_FORCEDETH=m + +CONFIG_NET_VENDOR_OKI=y +# CONFIG_PCH_GBE is not set + +CONFIG_NET_PACKET_ENGINE=y +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m + +CONFIG_NET_VENDOR_QLOGIC=y +CONFIG_QLA3XXX=m +CONFIG_QLCNIC=m +CONFIG_QLGE=m +CONFIG_NETXEN_NIC=m + +CONFIG_NET_VENDOR_REALTEK=y +CONFIG_ATP=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_R8169=m + +CONFIG_NET_VENDOR_RDC=y +CONFIG_R6040=m + +# CONFIG_NET_VENDOR_SEEQ is not set + +CONFIG_NET_VENDOR_SILAN=y +CONFIG_SC92031=m + +CONFIG_NET_VENDOR_SIS=y +CONFIG_SIS900=m +CONFIG_SIS190=m + +CONFIG_NET_VENDOR_SMSC=y +# CONFIG_SMC9194 is not set +CONFIG_PCMCIA_SMC91C92=m +CONFIG_EPIC100=m +CONFIG_SMSC9420=m + +CONFIG_NET_VENDOR_STMICRO=y +CONFIG_STMMAC_ETH=m +# CONFIG_STMMAC_DA is not set +# CONFIG_STMMAC_DUAL_MAC is not set +# CONFIG_STMMAC_TIMER is not set +# CONFIG_STMMAC_DEBUG_FS is not set + +CONFIG_NET_VENDOR_SUN=y +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NIU=m + +CONFIG_NET_VENDOR_TEHUTI=y +CONFIG_TEHUTI=m + +CONFIG_NET_VENDOR_TI=y +CONFIG_TLAN=m + +CONFIG_NET_VENDOR_VIA=y +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_VELOCITY=m + +CONFIG_NET_VENDOR_XIRCOM=y +CONFIG_PCMCIA_XIRC2PS=m + +CONFIG_PHYLIB=y CONFIG_BROADCOM_PHY=m CONFIG_CICADA_PHY=m CONFIG_DAVICOM_PHY=m @@ -1244,144 +1462,43 @@ CONFIG_VITESSE_PHY=m CONFIG_MICREL_PHY=m CONFIG_MII=m -CONFIG_HAPPYMEAL=m -CONFIG_SUNGEM=m CONFIG_NET_VENDOR_3COM=y CONFIG_VORTEX=m CONFIG_TYPHOON=m CONFIG_DNET=m -CONFIG_STMMAC_ETH=m -# CONFIG_STMMAC_DA is not set -# CONFIG_STMMAC_DUAL_MAC is not set -# CONFIG_STMMAC_TIMER is not set -# CONFIG_PCH_GBE is not set -# -# Tulip family network device support -# -CONFIG_NET_TULIP=y -CONFIG_DE2104X=m -CONFIG_DE2104X_DSL=0 -CONFIG_TULIP=m -# CONFIG_TULIP_NAPI is not set -# CONFIG_TULIP_MWI is not set -CONFIG_TULIP_MMIO=y -# CONFIG_NI5010 is not set -CONFIG_DE4X5=m -CONFIG_WINBOND_840=m -CONFIG_DM9102=m -CONFIG_PCMCIA_XIRCOM=m -CONFIG_ULI526X=m -# CONFIG_HP100 is not set CONFIG_LNE390=m -CONFIG_NE3210=m CONFIG_ES3210=m CONFIG_NET_PCI=y -CONFIG_PCNET32=m -CONFIG_AMD8111_ETH=m -CONFIG_ADAPTEC_STARFIRE=m -CONFIG_KSZ884X_PCI=m CONFIG_B44=m CONFIG_B44_PCI=y CONFIG_BNX2=m CONFIG_CNIC=m -CONFIG_QLA3XXX=m -CONFIG_ATL1=m -CONFIG_ATL1C=m -CONFIG_ATL2=m -CONFIG_ATL1E=m -CONFIG_E100=m CONFIG_FEALNX=m -CONFIG_FORCEDETH=m -CONFIG_NATSEMI=m -CONFIG_NE2K_PCI=m -CONFIG_8139CP=m -CONFIG_8139TOO=m -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -CONFIG_8139TOO_8129=y -# CONFIG_8139_OLD_RX_RESET is not set -CONFIG_SIS900=m -CONFIG_SIS190=m -CONFIG_EPIC100=m -CONFIG_SC92031=m -CONFIG_SMSC9420=m -CONFIG_SUNDANCE=m -# CONFIG_SUNDANCE_MMIO is not set -CONFIG_TLAN=m -CONFIG_VIA_RHINE=m -CONFIG_VIA_RHINE_MMIO=y -CONFIG_VIA_VELOCITY=m CONFIG_NET_POCKET=y -CONFIG_ATP=m -CONFIG_DE600=m -CONFIG_DE620=m -CONFIG_CASSINI=m CONFIG_ETHOC=m -# CONFIG_KS8842 is not set -# CONFIG_KS8851_MLL is not set # # Ethernet (1000 Mbit) # -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_DL2K=m -CONFIG_E1000=m -CONFIG_E1000E=m -CONFIG_IGB=m -CONFIG_IGB_DCA=y -CONFIG_IGBVF=m -CONFIG_NS83820=m -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m -CONFIG_R8169=m -CONFIG_SKGE=m -# CONFIG_SKGE_DEBUG is not set -CONFIG_SKGE_GENESIS=y CONFIG_TIGON3=m -CONFIG_SKY2=m -# CONFIG_SKY2_DEBUG is not set CONFIG_JME=m # # Ethernet (10000 Mbit) # -CONFIG_CHELSIO_T1=m -CONFIG_CHELSIO_T1_1G=y -CONFIG_CHELSIO_T3=m -CONFIG_CHELSIO_T4=m -CONFIG_CHELSIO_T4VF=m CONFIG_IP1000=m -CONFIG_IXGB=m -CONFIG_IXGBEVF=m -CONFIG_IXGBE=m -CONFIG_IXGBE_DCA=y -CONFIG_IXGBE_DCB=y -CONFIG_MYRI10GE=m -CONFIG_MYRI10GE_DCA=y -CONFIG_NETXEN_NIC=m -CONFIG_NIU=m -CONFIG_S2IO=m -CONFIG_VXGE=m -# CONFIG_VXGE_DEBUG_TRACE_ALL is not set -CONFIG_TEHUTI=m -CONFIG_ENIC=m CONFIG_MLX4_EN=m # CONFIG_MLX4_DEBUG is not set -CONFIG_QLCNIC=m -CONFIG_QLGE=m -CONFIG_BNA=m CONFIG_SFC=m CONFIG_SFC_MTD=y -CONFIG_BE2NET=m -CONFIG_FDDI=y +# CONFIG_FDDI is not set # CONFIG_DEFXX is not set -CONFIG_SKFP=m +# CONFIG_SKFP is not set # CONFIG_HIPPI is not set -CONFIG_PLIP=m +# CONFIG_PLIP is not set CONFIG_PPP=m CONFIG_PPP_MULTILINK=y CONFIG_PPP_FILTER=y @@ -1389,13 +1506,10 @@ CONFIG_PPP_ASYNC=m CONFIG_PPP_SYNC_TTY=m CONFIG_PPP_DEFLATE=m CONFIG_IPPP_FILTER=y -# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_BSDCOMP=y CONFIG_PPPOE=m CONFIG_PPP_MPPE=m -CONFIG_SLIP=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -# CONFIG_SLIP_MODE_SLIP6 is not set +# CONFIG_SLIP is not set # # Wireless LAN @@ -1444,6 +1558,8 @@ CONFIG_ATH_COMMON=m CONFIG_ATH5K=m CONFIG_ATH5K_DEBUG=y # CONFIG_ATH5K_TRACER is not set +CONFIG_ATH6KL=m +CONFIG_ATH6KL_DEBUG=y CONFIG_ATH9K=m CONFIG_ATH9K_PCI=y CONFIG_ATH9K_AHB=y @@ -1454,6 +1570,7 @@ CONFIG_ATH9K_HTC=m CONFIG_ATH9K_RATE_CONTROL=y CONFIG_CARL9170=m CONFIG_CARL9170_LEDS=y +# CONFIG_CARL9170_HWRNG is not set CONFIG_AT76C50X_USB=m CONFIG_AIRO=m CONFIG_AIRO_CS=m @@ -1466,6 +1583,7 @@ CONFIG_B43_BCMA_PIO=y # CONFIG_B43_DEBUG is not set CONFIG_B43_PHY_LP=y CONFIG_B43_PHY_N=y +CONFIG_B43_PHY_HT=y # CONFIG_B43_FORCE_PIO is not set CONFIG_B43LEGACY=m # CONFIG_B43LEGACY_DEBUG is not set @@ -1474,6 +1592,9 @@ CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y # CONFIG_B43LEGACY_DMA_MODE is not set # CONFIG_B43LEGACY_PIO_MODE is not set +CONFIG_BRCMSMAC=m +CONFIG_BRCMFMAC=m +# CONFIG_BRCMDBG is not set CONFIG_HERMES=m CONFIG_HERMES_CACHE_FW_ON_INIT=y # CONFIG_HERMES_PRISM is not set @@ -1573,24 +1694,12 @@ CONFIG_RTL8192DE=m CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m - -CONFIG_BRCMFMAC=m -CONFIG_BRCMSMAC=m -# CONFIG_BRCMDBG is not set +CONFIG_MWIFIEX_PCIE=m # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_IBMOL is not set -# CONFIG_3C359 is not set -# Broken with gcc4.1 -# CONFIG_TMS380TR is not set -# CONFIG_TMSPCI is not set -# CONFIG_ABYSS is not set -# CONFIG_IBMLS is not set -# CONFIG_PCMCIA_IBMTR is not set - CONFIG_NET_FC=y @@ -1606,11 +1715,6 @@ CONFIG_NET_PCMCIA=y CONFIG_PCMCIA_3C589=m CONFIG_PCMCIA_3C574=m CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -CONFIG_PCMCIA_AXNET=m # # Amateur Radio support @@ -1618,27 +1722,9 @@ CONFIG_PCMCIA_AXNET=m CONFIG_HAMRADIO=y CONFIG_AX25=m CONFIG_AX25_DAMA_SLAVE=y -CONFIG_CAN=m -CONFIG_CAN_RAW=m -CONFIG_CAN_BCM=m -CONFIG_CAN_VCAN=m -CONFIG_CAN_DEV=m -CONFIG_CAN_CALC_BITTIMING=y -CONFIG_CAN_SJA1000=m -CONFIG_CAN_SJA1000_ISA=m -CONFIG_CAN_SJA1000_PLATFORM=m -CONFIG_CAN_EMS_PCI=m -CONFIG_CAN_EMS_USB=m -CONFIG_CAN_ESD_USB2=m -CONFIG_CAN_KVASER_PCI=m -CONFIG_CAN_PLX_PCI=m -CONFIG_CAN_TSCAN1=m -CONFIG_CAN_SLCAN=m -CONFIG_CAN_SOFTING=m -CONFIG_CAN_SOFTING_CS=m -CONFIG_CAN_C_CAN=m -CONFIG_CAN_C_CAN_PLATFORM=m -# CONFIG_PCH_CAN is not set + +# CONFIG_CAN is not set + CONFIG_NETROM=m CONFIG_ROSE=m CONFIG_MKISS=m @@ -1654,7 +1740,7 @@ CONFIG_BAYCOM_PAR=m CONFIG_BAYCOM_EPP=m CONFIG_YAM=m -CONFIG_NFC=m +# CONFIG_NFC is not set # # IrDA (infrared) support @@ -1887,6 +1973,7 @@ CONFIG_INPUT_CM109=m CONFIG_INPUT_POLLDEV=m CONFIG_INPUT_SPARSEKMAP=m # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_BMA150 is not set CONFIG_INPUT_CMA3000=m CONFIG_INPUT_CMA3000_I2C=m @@ -1989,6 +2076,7 @@ CONFIG_TOUCHSCREEN_MCS5000=m CONFIG_TOUCHSCREEN_MK712=m CONFIG_TOUCHSCREEN_PENMOUNT=m # CONFIG_TOUCHSCREEN_TPS6507X is not set +CONFIG_TOUCHSCREEN_TSC_SERIO=m CONFIG_TOUCHSCREEN_TSC2007=m CONFIG_TOUCHSCREEN_TOUCHIT213=m CONFIG_TOUCHSCREEN_TOUCHRIGHT=m @@ -2010,7 +2098,6 @@ CONFIG_INPUT_UINPUT=m CONFIG_INPUT_WISTRON_BTNS=m CONFIG_INPUT_ATLAS_BTNS=m -CONFIG_INPUT_ATI_REMOTE=m CONFIG_INPUT_ATI_REMOTE2=m CONFIG_INPUT_KEYSPAN_REMOTE=m @@ -2065,6 +2152,7 @@ CONFIG_SERIAL_8250_MANY_PORTS=y CONFIG_SERIAL_8250_SHARE_IRQ=y # CONFIG_SERIAL_8250_DETECT_IRQ is not set CONFIG_SERIAL_8250_RSA=y +# CONFIG_SERIAL_8250_DW is not set CONFIG_CYCLADES=m # CONFIG_CYZ_INTR is not set # CONFIG_MOXA_INTELLIO is not set @@ -2274,12 +2362,14 @@ CONFIG_SENSORS_MAX6642=m CONFIG_SENSORS_ADM1275=m CONFIG_SENSORS_UCD9000=m CONFIG_SENSORS_UCD9200=m +CONFIG_SENSORS_ZL6100=m CONFIG_SENSORS_EMC6W201=m CONFIG_PMBUS=m CONFIG_SENSORS_PMBUS=m CONFIG_SENSORS_MAX16064=m CONFIG_SENSORS_LM25066=m +CONFIG_SENSORS_LTC2978=m CONFIG_SENSORS_MAX34440=m CONFIG_SENSORS_MAX8688=m CONFIG_SENSORS_MAX1668=m @@ -2290,25 +2380,7 @@ CONFIG_SENSORS_MAX1668=m # CONFIG_SERIAL_PCH_UART is not set # CONFIG_USB_SWITCH_FSA9480 is not set -CONFIG_W1=m -CONFIG_W1_CON=y -# This is busted. -# If we enable it, it steals Matrox cards, and the -# framebuffer drivers stop working. -# CONFIG_W1_MASTER_MATROX is not set -CONFIG_W1_MASTER_DS2482=m -CONFIG_W1_MASTER_DS2490=m -CONFIG_W1_MASTER_DS1WM=m -CONFIG_W1_SLAVE_THERM=m -CONFIG_W1_SLAVE_SMEM=m -CONFIG_W1_SLAVE_DS2431=m -CONFIG_W1_SLAVE_DS2433=m -CONFIG_W1_SLAVE_DS2433_CRC=y -CONFIG_W1_SLAVE_DS2760=m -CONFIG_W1_SLAVE_DS2423=m -CONFIG_W1_SLAVE_DS2408=m -CONFIG_W1_SLAVE_DS2780=m -CONFIG_W1_SLAVE_BQ27000=m +# CONFIG_W1 is not set # # Mice @@ -2345,6 +2417,7 @@ CONFIG_MACHZ_WDT=m # CONFIG_SC520_WDT is not set CONFIG_ALIM7101_WDT=m CONFIG_ALIM1535_WDT=m +CONFIG_IT87_WDT=m CONFIG_ITCO_WDT=m CONFIG_ITCO_VENDOR_SUPPORT=y # CONFIG_SC1200_WDT is not set @@ -2358,12 +2431,15 @@ CONFIG_IT8712F_WDT=m CONFIG_SMSC_SCH311X_WDT=m CONFIG_W83977F_WDT=m CONFIG_PCIPCWATCHDOG=m +# CONFIG_PCWATCHDOG is not set CONFIG_USBPCWATCHDOG=m # CONFIG_SBC_EPX_C3_WATCHDOG is not set CONFIG_WM8350_WATCHDOG=m CONFIG_WM831X_WATCHDOG=m # CONFIG_MAX63XX_WATCHDOG is not set # CONFIG_DW_WATCHDOG is not set +CONFIG_W83697UG_WDT=m +# CONFIG_WDT is not set CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_TIMERIOMEM=m @@ -2380,6 +2456,7 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set CONFIG_RTC_DRV_CMOS=y CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1511=m CONFIG_RTC_DRV_DS1553=m CONFIG_RTC_DRV_DS1672=m CONFIG_RTC_DRV_DS1742=m @@ -2434,24 +2511,31 @@ CONFIG_AGP_SIS=y CONFIG_AGP_SWORKS=y CONFIG_AGP_VIA=y CONFIG_AGP_EFFICEON=y + CONFIG_VGA_ARB=y CONFIG_VGA_ARB_MAX_GPUS=16 -CONFIG_STUB_POULSBO=m + +# CONFIG_STUB_POULSBO is not set + CONFIG_DRM=m -CONFIG_DRM_TDFX=m -CONFIG_DRM_R128=m +# CONFIG_DRM_TDFX is not set +# CONFIG_DRM_R128 is not set CONFIG_DRM_RADEON=m CONFIG_DRM_RADEON_KMS=y -CONFIG_DRM_I810=m -CONFIG_DRM_MGA=m -CONFIG_DRM_SIS=m -CONFIG_DRM_SAVAGE=m +# CONFIG_DRM_I810 is not set +# CONFIG_DRM_MGA is not set +# CONFIG_DRM_SIS is not set +# CONFIG_DRM_SAVAGE is not set CONFIG_DRM_I915=m CONFIG_DRM_I915_KMS=y -CONFIG_DRM_VIA=m +# CONFIG_DRM_VIA is not set CONFIG_DRM_NOUVEAU=m CONFIG_DRM_NOUVEAU_BACKLIGHT=y CONFIG_DRM_NOUVEAU_DEBUG=y +CONFIG_DRM_PSB=m +# CONFIG_DRM_PSB_MRST is not set +# CONFIG_DRM_PSB_MFLD is not set +# CONFIG_DRM_PSB_CDV is not set CONFIG_DRM_I2C_CH7006=m CONFIG_DRM_I2C_SIL164=m CONFIG_DRM_VMWGFX=m @@ -2501,7 +2585,7 @@ CONFIG_VIDEO_CAFE_CCIC=m CONFIG_VIDEO_CPIA2=m CONFIG_VIDEO_CQCAM=m CONFIG_VIDEO_CX23885=m -# CONFIG_MEDIA_ALTERA_CI is not set +CONFIG_MEDIA_ALTERA_CI=m CONFIG_VIDEO_CX18=m CONFIG_VIDEO_CX18_ALSA=m CONFIG_VIDEO_CX88=m @@ -2523,6 +2607,7 @@ CONFIG_VIDEO_IVTV=m CONFIG_VIDEO_MEYE=m CONFIG_VIDEO_MXB=m CONFIG_VIDEO_PVRUSB2_DVB=y +# CONFIG_VIDEO_PMS is not set CONFIG_VIDEO_HDPVR=m CONFIG_VIDEO_SAA6588=m CONFIG_VIDEO_SAA7134=m @@ -2541,6 +2626,9 @@ CONFIG_VIDEO_ZORAN_LML33R10=m CONFIG_VIDEO_ZORAN_ZR36060=m CONFIG_VIDEO_FB_IVTV=m CONFIG_VIDEO_SAA7164=m +CONFIG_VIDEO_TM6000=m +CONFIG_VIDEO_TM6000_ALSA=m +CONFIG_VIDEO_TM6000_DVB=m CONFIG_VIDEO_TLG2300=m # CONFIG_VIDEO_TIMBERDALE is not set # CONFIG_VIDEO_M5MOLS is not set @@ -2668,6 +2756,13 @@ CONFIG_DVB_USB_ANYSEE=m CONFIG_DVB_USB_DW2102=m CONFIG_DVB_USB_FRIIO=m CONFIG_DVB_USB_EC168=m +CONFIG_DVB_USB_PCTV452E=m +CONFIG_DVB_USB_IT913X=m +CONFIG_DVB_USB_MXL111SF=m +CONFIG_DVB_TDA10071=m +CONFIG_DVB_LNBP22=m +CONFIG_DVB_A8293=m +CONFIG_DVB_IT913X_FE=m CONFIG_DVB_DM1105=m CONFIG_DVB_S921=m CONFIG_DVB_ISL6405=m @@ -2747,6 +2842,7 @@ CONFIG_VIDEO_PVRUSB2_SYSFS=y CONFIG_RC_CORE=m CONFIG_RC_LOOPBACK=m CONFIG_RC_MAP=m +CONFIG_RC_ATI_REMOTE=m CONFIG_IR_NEC_DECODER=m CONFIG_IR_RC5_DECODER=m CONFIG_IR_RC6_DECODER=m @@ -2761,6 +2857,9 @@ CONFIG_IR_ITE_CIR=m CONFIG_IR_NUVOTON=m CONFIG_IR_FINTEK=m CONFIG_IR_REDRAT3=m +CONFIG_IR_ENE=m +CONFIG_IR_STREAMZAP=m +CONFIG_IR_WINBOND_CIR=m CONFIG_V4L_MEM2MEM_DRIVERS=y # CONFIG_VIDEO_MEM2MEM_TESTDEV is not set @@ -2779,19 +2878,16 @@ CONFIG_VIDEO_OUTPUT_CONTROL=m CONFIG_FB=y # CONFIG_FB_FOREIGN_ENDIAN is not set -CONFIG_FB_3DFX=m -CONFIG_FB_3DFX_ACCEL=y -CONFIG_FB_3DFX_I2C=y +# CONFIG_FB_3DFX is not set # CONFIG_FB_ARC is not set # CONFIG_FB_ARK is not set -CONFIG_FB_ATY128=m -CONFIG_FB_ATY=m -CONFIG_FB_ATY_CT=y -CONFIG_FB_ATY_GX=y -CONFIG_FB_ATY_GENERIC_LCD=y +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_ATY_CT is not set +# CONFIG_FB_ATY_GX is not set # CONFIG_FB_ASILIANT is not set # CONFIG_FB_CARMINE is not set -CONFIG_FB_CIRRUS=m +# CONFIG_FB_CIRRUS is not set # CONFIG_FB_CYBER2000 is not set # CONFIG_FB_GEODE is not set # CONFIG_FB_HECUBA is not set @@ -2803,39 +2899,34 @@ CONFIG_FB_I810_I2C=y # CONFIG_FB_INTEL is not set # CONFIG_FB_INTEL_DEBUG is not set # CONFIG_FB_INTEL_I2C is not set -CONFIG_FB_KYRO=m +# CONFIG_FB_KYRO is not set # CONFIG_FB_LE80578 is not set -CONFIG_FB_MATROX=m -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G=y -CONFIG_FB_MATROX_I2C=m -CONFIG_FB_MATROX_MAVEN=m -CONFIG_FB_NEOMAGIC=m -CONFIG_FB_NVIDIA=m +# CONFIG_FB_MATROX is not set +# CONFIG_FB_MATROX_MILLENIUM is not set +# CONFIG_FB_MATROX_MYSTIQUE is not set +# CONFIG_FB_MATROX_G is not set +# CONFIG_FB_MATROX_I2C is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_NVIDIA_I2C is not set # CONFIG_FB_NVIDIA_DEBUG is not set -CONFIG_FB_NVIDIA_I2C=y # CONFIG_FB_PM2 is not set # CONFIG_FB_PM2_FIFO_DISCONNECT is not set # CONFIG_FB_PM3 is not set -CONFIG_FB_RADEON=m +# CONFIG_FB_RADEON is not set +# CONFIG_FB_RADEON_I2C is not set # CONFIG_FB_RADEON_DEBUG is not set -CONFIG_FB_RADEON_I2C=y -CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA is not set # CONFIG_FB_RIVA_DEBUG is not set # CONFIG_FB_RIVA_I2C is not set # CONFIG_FB_S1D13XXX is not set -CONFIG_FB_S3=m -CONFIG_FB_S3_DDC=y -CONFIG_FB_SAVAGE=m -CONFIG_FB_SAVAGE_I2C=y -CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set # CONFIG_FB_SIS is not set -CONFIG_FB_SIS_300=y -CONFIG_FB_SIS_315=y -CONFIG_FB_SM501=m +# CONFIG_FB_SM501 is not set +# CONFIG_FB_SMSCUFX is not set CONFIG_FB_TILEBLITTING=y -CONFIG_FB_TRIDENT=m +# CONFIG_FB_TRIDENT is not set # CONFIG_FB_UVESA is not set CONFIG_FB_VESA=y CONFIG_FB_VGA16=m @@ -2843,14 +2934,14 @@ CONFIG_FB_VIRTUAL=m CONFIG_FB_VOODOO1=m # CONFIG_FB_VT8623 is not set CONFIG_FB_EFI=y -CONFIG_FB_VIA=m -CONFIG_FB_VIA_X_COMPATIBILITY=y +# CONFIG_FB_VIA is not set # CONFIG_FB_VIA_DIRECT_PROCFS is not set -CONFIG_FB_METRONOME=m +# CONFIG_FB_METRONOME is not set # CONFIG_FB_MB862XX is not set # CONFIG_FB_PRE_INIT_FB is not set # CONFIG_FB_TMIO is not set # CONFIG_FB_BROADSHEET is not set +CONFIG_FB_UDL=m # CONFIG_FIRMWARE_EDID is not set @@ -3032,9 +3123,7 @@ CONFIG_SND_USB_6FIRE=m # # PCMCIA devices # -CONFIG_SND_PCMCIA=y -CONFIG_SND_VXPOCKET=m -CONFIG_SND_PDAUDIOCF=m +# CONFIG_SND_PCMCIA is not set CONFIG_SND_FIREWIRE=y CONFIG_SND_FIREWIRE_SPEAKERS=m @@ -3109,7 +3198,6 @@ CONFIG_USB_STORAGE_REALTEK=m CONFIG_REALTEK_AUTOPM=y CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set -# uas is broken (#717633, #744099) # CONFIG_USB_UAS is not set @@ -3125,6 +3213,7 @@ CONFIG_HID=m CONFIG_HIDRAW=y CONFIG_HID_PID=y CONFIG_LOGITECH_FF=y +CONFIG_HID_LOGITECH_DJ=m CONFIG_LOGIWII_FF=y CONFIG_LOGIRUMBLEPAD2_FF=y CONFIG_PANTHERLORD_FF=y @@ -3138,10 +3227,12 @@ CONFIG_DRAGONRISE_FF=y CONFIG_GREENASIA_FF=y CONFIG_SMARTJOYPLUS_FF=y CONFIG_LOGIG940_FF=y +CONFIG_LOGIWHEELS_FF=y CONFIG_HID_MAGICMOUSE=y CONFIG_HID_MULTITOUCH=m CONFIG_HID_NTRIG=y CONFIG_HID_QUANTA=y +CONFIG_HID_PRIMAX=m CONFIG_HID_PRODIKEYS=m CONFIG_HID_DRAGONRISE=m CONFIG_HID_GYRATION=m @@ -3218,6 +3309,7 @@ CONFIG_USB_GSPCA_SPCA561=m CONFIG_USB_GSPCA_STK014=m CONFIG_USB_GSPCA_SUNPLUS=m CONFIG_USB_GSPCA_T613=m +CONFIG_USB_GSPCA_TOPRO=m CONFIG_USB_GSPCA_TV8532=m CONFIG_USB_GSPCA_VC032X=m CONFIG_USB_GSPCA_ZC3XX=m @@ -3241,22 +3333,7 @@ CONFIG_USB_S2255=m # CONFIG_VIDEO_SH_MOBILE_CSI2 is not set # CONFIG_USB_SN9C102 is not set CONFIG_USB_ZR364XX=m -CONFIG_SOC_CAMERA=m -CONFIG_SOC_CAMERA_MT9M001=m -CONFIG_SOC_CAMERA_MT9V022=m -CONFIG_SOC_CAMERA_PLATFORM=m -CONFIG_SOC_CAMERA_MT9M111=m -CONFIG_SOC_CAMERA_MT9T031=m -CONFIG_SOC_CAMERA_TW9910=m -CONFIG_SOC_CAMERA_OV772X=m -CONFIG_SOC_CAMERA_MT9T112=m -CONFIG_SOC_CAMERA_RJ54N1=m -CONFIG_SOC_CAMERA_OV9640=m -CONFIG_SOC_CAMERA_OV6650=m -CONFIG_SOC_CAMERA_OV5642=m -CONFIG_SOC_CAMERA_IMX074=m -CONFIG_SOC_CAMERA_OV2640=m -CONFIG_SOC_CAMERA_OV9740=m +# CONFIG_SOC_CAMERA is not set # # USB Network adaptors @@ -3361,6 +3438,7 @@ CONFIG_USB_SERIAL_OTI6858=m CONFIG_USB_SERIAL_OPTICON=m CONFIG_USB_SERIAL_OMNINET=m CONFIG_USB_SERIAL_PL2303=m +# CONFIG_USB_SERIAL_QUATECH2 is not set CONFIG_USB_SERIAL_SAFE=m CONFIG_USB_SERIAL_SAFE_PADDED=y CONFIG_USB_SERIAL_SIERRAWIRELESS=m @@ -3401,6 +3479,7 @@ CONFIG_USB_FTDI_ELAN=m CONFIG_USB_FILE_STORAGE=m # CONFIG_USB_FILE_STORAGE_TEST is not set # CONFIG_USB_GADGET is not set +# CONFIG_USB_DWC3 is not set # CONFIG_USB_GADGETFS is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set @@ -3482,6 +3561,11 @@ CONFIG_MFD_WM8400=m # CONFIG_MFD_JANZ_CMODIO is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_WL1273_CORE is not set # # File systems @@ -3526,13 +3610,14 @@ CONFIG_DNOTIFY=y # Autofsv3 is obsolete. # systemd is dependant upon AUTOFS, so build it in. CONFIG_AUTOFS4_FS=y -CONFIG_EXOFS_FS=m +# CONFIG_EXOFS_FS is not set # CONFIG_EXOFS_DEBUG is not set -CONFIG_NILFS2_FS=m -CONFIG_LOGFS=m +# CONFIG_NILFS2_FS is not set +# CONFIG_LOGFS is not set CONFIG_CEPH_FS=m CONFIG_BLK_DEV_RBD=m CONFIG_CEPH_LIB=m +# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set CONFIG_FSCACHE=m CONFIG_FSCACHE_STATS=y @@ -3585,27 +3670,21 @@ CONFIG_HFS_FS=m CONFIG_HFSPLUS_FS=m CONFIG_BEFS_FS=m # CONFIG_BEFS_DEBUG is not set -CONFIG_BFS_FS=m -CONFIG_EFS_FS=m -CONFIG_JFFS2_FS=m -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set -CONFIG_JFFS2_FS_WRITEBUFFER=y -# CONFIG_JFFS2_FS_WBUF_VERIFY is not set -CONFIG_JFFS2_SUMMARY=y -CONFIG_JFFS2_FS_XATTR=y -CONFIG_JFFS2_FS_POSIX_ACL=y -CONFIG_JFFS2_FS_SECURITY=y +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set + CONFIG_CRAMFS=m CONFIG_SQUASHFS=m CONFIG_SQUASHFS_XATTR=y CONFIG_SQUASHFS_LZO=y CONFIG_SQUASHFS_XZ=y CONFIG_SQUASHFS_ZLIB=y +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set # CONFIG_SQUASHFS_EMBEDDED is not set -CONFIG_VXFS_FS=m +# CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_QNX4FS_FS=m +# CONFIG_QNX4FS_FS is not set CONFIG_SYSV_FS=m CONFIG_UFS_FS=m # CONFIG_UFS_FS_WRITE is not set @@ -3614,7 +3693,7 @@ CONFIG_9P_FS=m CONFIG_9P_FSCACHE=y CONFIG_9P_FS_POSIX_ACL=y CONFIG_FUSE_FS=m -CONFIG_OMFS_FS=m +# CONFIG_OMFS_FS is not set CONFIG_CUSE=m # @@ -3684,10 +3763,7 @@ CONFIG_DLM_DEBUG=y CONFIG_GFS2_FS=m CONFIG_GFS2_FS_LOCKING_DLM=y -CONFIG_UBIFS_FS=m -CONFIG_UBIFS_FS_XATTR=y -# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set -# CONFIG_UBIFS_FS_DEBUG is not set +# CONFIG_UBIFS_FS is not set # # Partition Types @@ -3774,24 +3850,68 @@ CONFIG_FRAME_POINTER=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_DEBUG_DRIVER is not set CONFIG_HEADERS_CHECK=y -# CONFIG_RCU_TORTURE_TEST is not set -# CONFIG_RCU_TRACE is not set # CONFIG_LKDTM is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_LOCKDEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# DEBUG options that don't get enabled/disabled with 'make debug/release' +# +# Kmemleak still produces a lot of false positives. +# CONFIG_DEBUG_KMEMLEAK is not set +# +# This generates a huge amount of dmesg spew +# CONFIG_DEBUG_KOBJECT is not set +# +# +# These debug options are deliberatly left on (even in 'make release' kernels). +# They aren't that much of a performance impact, and the value +# from getting useful bug-reports makes it worth leaving them on. +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_HIGHMEM=y +CONFIG_BOOT_PRINTK_DELAY=y +CONFIG_DEBUG_LIST=y +CONFIG_DEBUG_SHIRQ=y +CONFIG_DEBUG_DEVRES=y +CONFIG_DEBUG_RODATA_TEST=y +CONFIG_DEBUG_NX_TEST=m +CONFIG_DEBUG_SET_MODULE_RONX=y +CONFIG_DEBUG_BOOT_PARAMS=y +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set +CONFIG_LOCKUP_DETECTOR=y +# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set +CONFIG_ATOMIC64_SELFTEST=y +CONFIG_MEMORY_FAILURE=y +CONFIG_HWPOISON_INJECT=m +# CONFIG_DEBUG_SECTION_MISMATCH is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +CONFIG_LATENCYTOP=y +CONFIG_RESOURCE_COUNTERS=y +# CONFIG_COMPAT_BRK is not set +# CONFIG_DEBUG_VIRTUAL is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +CONFIG_EARLY_PRINTK_DBGP=y +# CONFIG_PAGE_POISONING is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_CRASH is not set +# CONFIG_GCOV_KERNEL is not set +# CONFIG_RAMOOPS is not set + CONFIG_KGDB=y CONFIG_KGDB_SERIAL_CONSOLE=y CONFIG_KGDB_TESTS=y CONFIG_KGDB_LOW_LEVEL_TRAP=y # CONFIG_KGDB_TESTS_ON_BOOT is not set + # # Security options # CONFIG_SECURITY=y +CONFIG_SECURITYFS=y # CONFIG_SECURITY_DMESG_RESTRICT is not set CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_NETWORK_XFRM=y @@ -3803,6 +3923,7 @@ CONFIG_SECURITY_SELINUX_DEVELOP=y CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 CONFIG_SECURITY_SELINUX_AVC_STATS=y +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set # CONFIG_SECURITY_SMACK is not set # CONFIG_SECURITY_TOMOYO is not set # CONFIG_SECURITY_APPARMOR is not set @@ -3877,6 +3998,9 @@ CONFIG_CRYPTO_ANSI_CPRNG=m CONFIG_CRYPTO_DEV_HIFN_795X=m CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y CONFIG_CRYPTO_PCRYPT=m +CONFIG_CRYPTO_USER=m + + # Random number generation @@ -3889,6 +4013,7 @@ CONFIG_CRC_CCITT=m CONFIG_CRC_ITU_T=m CONFIG_CRC_T10DIF=m CONFIG_CRC8=m +# CONFIG_CRC7 is not set CONFIG_CORDIC=m CONFIG_CRYPTO_ZLIB=m @@ -3925,6 +4050,7 @@ CONFIG_LCD_PLATFORM=m CONFIG_SCHEDSTATS=y CONFIG_SCHED_DEBUG=y CONFIG_FAIR_GROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y CONFIG_SCHED_OMIT_FRAME_POINTER=y CONFIG_RT_GROUP_SCHED=y CONFIG_SCHED_AUTOGROUP=y @@ -3943,7 +4069,6 @@ CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y # XXX disabled by default, pass 'swapaccount' # CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED is not set CONFIG_CGROUP_PERF=y CONFIG_BLK_CGROUP=y -# CONFIG_DEBUG_BLK_CGROUP is not set # CONFIG_SYSFS_DEPRECATED is not set # CONFIG_SYSFS_DEPRECATED_V2 is not set @@ -3958,6 +4083,8 @@ CONFIG_KEXEC=y CONFIG_HWMON=y # CONFIG_HWMON_DEBUG_CHIP is not set +CONFIG_THERMAL_HWMON=y + CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y @@ -3968,8 +4095,10 @@ CONFIG_IBMASR=m CONFIG_PM_DEBUG=y CONFIG_PM_TRACE=y +CONFIG_PM_TRACE_RTC=y # CONFIG_PM_TEST_SUSPEND is not set CONFIG_PM_RUNTIME=y +# CONFIG_PM_OPP is not set CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_GOV_PERFORMANCE=y @@ -3990,53 +4119,22 @@ CONFIG_I82365=m # CONFIG_LTPC is not set # CONFIG_COPS is not set -CONFIG_SCSI_AHA152X=m -CONFIG_SCSI_AHA1542=m -# CONFIG_SCSI_IN2000 is not set -CONFIG_SCSI_ARCMSR=m -CONFIG_SCSI_ARCMSR_AER=y -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_ULTRASTOR is not set # CONFIG_EL1 is not set # CONFIG_EL2 is not set -# CONFIG_ELPLUS is not set -# CONFIG_EL16 is not set CONFIG_EL3=m # CONFIG_3C515 is not set -# CONFIG_LANCE is not set CONFIG_NET_VENDOR_SMC=y # CONFIG_WD80x3 is not set CONFIG_ULTRA=m -# CONFIG_SMC9194 is not set # CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_NI52 is not set # CONFIG_NI65 is not set -# CONFIG_AT1700 is not set # CONFIG_DEPCA is not set CONFIG_NET_ISA=y CONFIG_NE2000=m # CONFIG_E2100 is not set -CONFIG_EWRK3=m -# CONFIG_EEXPRESS is not set -# CONFIG_EEXPRESS_PRO is not set # CONFIG_HPLAN_PLUS is not set # CONFIG_HPLAN is not set -# CONFIG_LP486E is not set -# CONFIG_ETH16I is not set -# CONFIG_ZNET is not set -# CONFIG_SEEQ8005 is not set -# CONFIG_AC3200 is not set -# CONFIG_APRICOT is not set -# CONFIG_CS89x0 is not set # CONFIG_IBMTR is not set # CONFIG_SKISA is not set # CONFIG_PROTEON is not set @@ -4069,24 +4167,7 @@ CONFIG_EWRK3=m # CONFIG_SERIAL_8250_HUB6 is not set # CONFIG_SERIAL_8250_EXAR_ST16C554 is not set -# CONFIG_PCWATCHDOG is not set -# CONFIG_WDT is not set - -# CONFIG_VIDEO_PMS is not set -CONFIG_RADIO_ADAPTERS=y -# CONFIG_RADIO_CADET is not set -# CONFIG_RADIO_RTRACK is not set -# CONFIG_RADIO_RTRACK2 is not set -# CONFIG_RADIO_AZTECH is not set -# CONFIG_RADIO_GEMTEK is not set -# CONFIG_RADIO_SF16FMI is not set -# CONFIG_RADIO_SF16FMR2 is not set -# CONFIG_RADIO_TERRATEC is not set -# CONFIG_RADIO_TRUST is not set -# CONFIG_RADIO_TEA5764 is not set -# CONFIG_RADIO_TYPHOON is not set -# CONFIG_RADIO_ZOLTRIX is not set -# CONFIG_RADIO_SAA7706H is not set +# CONFIG_RADIO_ADAPTERS is not set # CONFIG_SND_OPL4_LIB is not set # CONFIG_SND_AD1816A is not set @@ -4151,22 +4232,22 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=m CONFIG_LEDS_TRIGGER_BACKLIGHT=m CONFIG_LEDS_TRIGGER_DEFAULT_ON=m CONFIG_LEDS_ALIX2=m -CONFIG_LEDS_WM8350=m -CONFIG_LEDS_LP3944=m -CONFIG_LEDS_WM831X_STATUS=m -CONFIG_LEDS_REGULATOR=m -CONFIG_LEDS_LT3593=m -CONFIG_LEDS_TRIGGER_GPIO=m +CONFIG_LEDS_CLEVO_MAIL=m CONFIG_LEDS_INTEL_SS4200=m +CONFIG_LEDS_LM3530=m +CONFIG_LEDS_LP3944=m CONFIG_LEDS_LP5521=m CONFIG_LEDS_LP5523=m -CONFIG_LEDS_LM3530=m +CONFIG_LEDS_LT3593=m +CONFIG_LEDS_REGULATOR=m +CONFIG_LEDS_TRIGGER_GPIO=m +CONFIG_LEDS_WM8350=m +CONFIG_LEDS_WM831X_STATUS=m CONFIG_DMADEVICES=y CONFIG_DMA_ENGINE=y CONFIG_DW_DMAC=m # CONFIG_TIMB_DMA is not set -CONFIG_NET_DMA=y # CONFIG_DMATEST is not set CONFIG_ASYNC_TX_DMA=y @@ -4187,13 +4268,14 @@ CONFIG_FUNCTION_PROFILER=y CONFIG_RING_BUFFER_BENCHMARK=m CONFIG_FUNCTION_TRACER=y CONFIG_STACK_TRACER=y +# CONFIG_FUNCTION_GRAPH_TRACER is not set CONFIG_KPROBES=y +CONFIG_KPROBE_EVENT=y +# CONFIG_KPROBES_SANITY_TEST is not set CONFIG_JUMP_LABEL=y CONFIG_OPTPROBES=y -# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set - CONFIG_HZ_1000=y CONFIG_TIMER_STATS=y @@ -4209,22 +4291,26 @@ CONFIG_CFAG12864B_RATE=20 CONFIG_POWER_SUPPLY=m # CONFIG_POWER_SUPPLY_DEBUG is not set + # CONFIG_TEST_POWER is not set CONFIG_APM_POWER=m # CONFIG_WM831X_POWER is not set + # CONFIG_BATTERY_DS2760 is not set # CONFIG_BATTERY_DS2782 is not set # CONFIG_BATTERY_BQ20Z75 is not set # CONFIG_BATTERY_DS2780 is not set -# CONFIG_CHARGER_ISP1704 is not set -# CONFIG_CHARGER_MAX8903 is not set # CONFIG_BATTERY_BQ27x00 is not set # CONFIG_BATTERY_MAX17040 is not set -# CONFIG_PDA_POWER is not set -# CONFIG_CHARGER_GPIO is not set # CONFIG_BATTERY_MAX17042 is not set + +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_GPIO is not set # CONFIG_CHARGER_PCF50633 is not set +# CONFIG_PDA_POWER is not set + CONFIG_AUXDISPLAY=y CONFIG_UIO=m @@ -4236,7 +4322,6 @@ CONFIG_UIO_SERCOS3=m CONFIG_UIO_PCI_GENERIC=m # CONFIG_UIO_NETX is not set -# CONFIG_CRC7 is not set # LIRC @@ -4256,30 +4341,17 @@ CONFIG_LIRC_TTUSBIR=m # CONFIG_DEVKMEM is not set -CONFIG_PM_TRACE_RTC=y -CONFIG_R6040=m - CONFIG_BNX2X=m CONFIG_SCSI_BNX2X_FCOE=m CONFIG_NOZOMI=m # CONFIG_TPS65010 is not set -# CONFIG_DEBUG_SECTION_MISMATCH is not set -# CONFIG_KPROBES_SANITY_TEST is not set -# CONFIG_BACKTRACE_SELF_TEST is not set -CONFIG_LATENCYTOP=y -CONFIG_RESOURCE_COUNTERS=y -# CONFIG_COMPAT_BRK is not set - -#FIXME: x86 generic? -CONFIG_LEDS_CLEVO_MAIL=m CONFIG_INPUT_APANEL=m # CONFIG_INTEL_MENLOW is not set CONFIG_ENCLOSURE_SERVICES=m CONFIG_IPWIRELESS=m -CONFIG_RTC_DRV_DS1511=m # CONFIG_BLK_DEV_XIP is not set CONFIG_MEMSTICK=m @@ -4297,40 +4369,26 @@ CONFIG_A11Y_BRAILLE_CONSOLE=y # MT9V022_PCA9536_SWITCH is not set -CONFIG_THERMAL_HWMON=y - CONFIG_OPTIMIZE_INLINING=y # FIXME: This should be x86/ia64 only # CONFIG_HP_ILO is not set # CONFIG_GPIOLIB is not set - - -CONFIG_NETFILTER_TPROXY=m -CONFIG_NETFILTER_XT_TARGET_TPROXY=m -CONFIG_NETFILTER_XT_MATCH_RECENT=m -CONFIG_NETFILTER_XT_MATCH_SOCKET=m - -CONFIG_IP_VS_IPV6=y +# CONFIG_PINCTRL is not set CONFIG_NET_DSA=y CONFIG_NET_DSA_MV88E6060=y CONFIG_NET_DSA_MV88E6131=y CONFIG_NET_DSA_MV88E6123_61_65=y -CONFIG_NET_SCH_MULTIQ=m -CONFIG_NET_ACT_SKBEDIT=m +# Used by Maemo, we don't care. +# CONFIG_PHONET is not set -CONFIG_PHONET=m +# CONFIG_ICS932S401 is not set -CONFIG_ICS932S401=m # CONFIG_C2PORT is not set - -CONFIG_IT87_WDT=m -CONFIG_W83697UG_WDT=m - # CONFIG_REGULATOR is not set # CONFIG_REGULATOR_DEBUG is not set @@ -4350,9 +4408,9 @@ CONFIG_UWB_WHCI=m CONFIG_UWB_I1480U=m CONFIG_STAGING=y +# CONFIG_STAGING_MEDIA is not set # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set -# CONFIG_VIDEO_TM6000 is not set # CONFIG_WLAGS49_H2 is not set # CONFIG_WLAGS49_H25 is not set # CONFIG_VIDEO_DT3155 is not set @@ -4379,7 +4437,6 @@ CONFIG_USB_ATMEL=m # CONFIG_RTL8192E is not set # CONFIG_INPUT_GPIO is not set # CONFIG_VIDEO_CX25821 is not set -# CONFIG_HYPERV is not set # CONFIG_R8187SE is not set # CONFIG_RTL8192U is not set # CONFIG_BATMAN_ADV is not set @@ -4399,51 +4456,41 @@ CONFIG_USB_ATMEL=m # CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set # CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set # CONFIG_RTS_PSTOR is not set -# CONFIG_DRM_PSB is not set -# CONFIG_ALTERA_STAPL is not set +CONFIG_ALTERA_STAPL=m # CONFIG_DVB_CXD2099 is not set # CONFIG_USBIP_CORE is not set # CONFIG_INTEL_MEI is not set # CONFIG_ZCACHE is not set - -# -# Android +# CONFIG_RTS5139 is not set +# CONFIG_NVEC_LEDS is not set +# CONFIG_VT6655 is not set # +# END OF STAGING -# CONFIG_DEBUG_VIRTUAL is not set -# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set -# CONFIG_FUNCTION_GRAPH_TRACER is not set -CONFIG_EARLY_PRINTK_DBGP=y - -CONFIG_SECURITYFS=y - -CONFIG_SCSI_CXGB3_ISCSI=m CONFIG_LIBFC=m CONFIG_LIBFCOE=m CONFIG_FCOE=m CONFIG_FCOE_FNIC=m -# CONFIG_SCSI_LPFC_DEBUG_FS is not set CONFIG_NOP_USB_XCEIV=m -CONFIG_IMA=y +# CONFIG_IMA is not set CONFIG_IMA_MEASURE_PCR_IDX=10 CONFIG_IMA_AUDIT=y CONFIG_IMA_LSM_RULES=y +# CONFIG_EVM is not set + CONFIG_LSM_MMAP_MIN_ADDR=65536 -# CONFIG_PAGE_POISONING is not set - - -# CONFIG_CRASH_DUMP is not set -# CONFIG_CRASH is not set - CONFIG_STRIP_ASM_SYMS=y # CONFIG_RCU_FANOUT_EXACT is not set CONFIG_RCU_FAST_NO_HZ=y CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_TRACE is not set +CONFIG_SPARSE_RCU_POINTER=y CONFIG_KSM=y CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -4453,62 +4500,29 @@ CONFIG_FANOTIFY=y CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y CONFIG_IEEE802154=m +CONFIG_IEEE802154_6LOWPAN=m CONFIG_IEEE802154_DRIVERS=m CONFIG_IEEE802154_FAKEHARD=m -# CONFIG_GCOV_KERNEL is not set - CONFIG_PPS=m # CONFIG_PPS_CLIENT_KTIMER is not set CONFIG_PPS_CLIENT_LDISC=m # CONFIG_PPS_DEBUG is not set CONFIG_PPS_CLIENT_PARPORT=m CONFIG_PPS_GENERATOR_PARPORT=m +CONFIG_PPS_CLIENT_GPIO=m CONFIG_NTP_PPS=y CONFIG_PTP_1588_CLOCK=m -# CONFIG_USB_SERIAL_QUATECH2 is not set -# CONFIG_VT6655 is not set -CONFIG_FB_UDL=m - -# DEBUG options that don't get enabled/disabled with 'make debug/release' -# -# Kmemleak still produces a lot of false positives. -# CONFIG_DEBUG_KMEMLEAK is not set -# -# This generates a huge amount of dmesg spew -# CONFIG_DEBUG_KOBJECT is not set -# -# -# These debug options are deliberatly left on (even in 'make release' kernels). -# They aren't that much of a performance impact, and the value -# from getting useful bug-reports makes it worth leaving them on. -CONFIG_DYNAMIC_DEBUG=y -CONFIG_DEBUG_HIGHMEM=y -CONFIG_BOOT_PRINTK_DELAY=y -CONFIG_DEBUG_LIST=y -CONFIG_DEBUG_SHIRQ=y -CONFIG_DEBUG_DEVRES=y -CONFIG_DEBUG_RODATA_TEST=y -CONFIG_DEBUG_NX_TEST=m -CONFIG_DEBUG_BOOT_PARAMS=y -CONFIG_LOCKUP_DETECTOR=y -# CONFIG_DEBUG_INFO_REDUCED is not set -# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set -# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set -CONFIG_ATOMIC64_SELFTEST=y - -CONFIG_MEMORY_FAILURE=y -CONFIG_HWPOISON_INJECT=m CONFIG_CLEANCACHE=y -CONFIG_BLK_DEV_DRBD=m - # CONFIG_MDIO_GPIO is not set # CONFIG_KEYBOARD_GPIO is not set # CONFIG_KEYBOARD_GPIO_POLLED is not set # CONFIG_MOUSE_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_DESIGNWARE_PCI is not set # CONFIG_I2C_GPIO is not set # CONFIG_DEBUG_GPIO is not set # CONFIG_W1_MASTER_GPIO is not set @@ -4532,32 +4546,14 @@ CONFIG_GPIO_SYSFS=y # CONFIG_GPIO_PCH is not set # CONFIG_GPIO_ML_IOH is not set -CONFIG_KPROBE_EVENT=y - -# CONFIG_RAMOOPS is not set - -CONFIG_IR_ENE=m -CONFIG_IR_STREAMZAP=m -CONFIG_IR_WINBOND_CIR=m - # CONFIG_GPIO_SX150X is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_MAX8998 is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TC3589X is not set - -CONFIG_SPARSE_RCU_POINTER=y - -# CONFIG_PM_OPP is not set - +# FIXME: Why? CONFIG_EVENT_POWER_TRACING_DEPRECATED=y +CONFIG_TEST_KSTRTOX=y # CONFIG_XZ_DEC_TEST is not set -CONFIG_PN544_NFC=m -CONFIG_NFC_PN533=m - CONFIG_TARGET_CORE=m CONFIG_ISCSI_TARGET=m CONFIG_LOOPBACK_TARGET=m @@ -4576,8 +4572,6 @@ CONFIG_PSTORE=y CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 -CONFIG_TEST_KSTRTOX=m - CONFIG_BCMA=m CONFIG_BCMA_BLOCKIO=y CONFIG_BCMA_HOST_PCI_POSSIBLE=y @@ -4586,6 +4580,6 @@ CONFIG_BCMA_HOST_PCI=y # CONFIG_GOOGLE_FIRMWARE is not set CONFIG_INTEL_MID_PTI=m - CONFIG_IOMMU_SUPPORT=y +# CONFIG_PM_DEVFREQ is not set diff --git a/config-ia64-generic b/config-ia64-generic deleted file mode 100644 index 52900a8e7..000000000 --- a/config-ia64-generic +++ /dev/null @@ -1,204 +0,0 @@ -# -# Automatically generated make config: don't edit -# - -# -# Processor type and features -# -CONFIG_IA64=y -CONFIG_64BIT=y -# CONFIG_XEN is not set -CONFIG_MMU=y -CONFIG_EFI=y -# CONFIG_ITANIUM is not set -CONFIG_MCKINLEY=y -CONFIG_IA64_GENERIC=y -CONFIG_DMAR=y -# CONFIG_IA64_DIG is not set -# CONFIG_IA64_HP_ZX1 is not set -# CONFIG_IA64_SGI_SN2 is not set -CONFIG_IA64_ESI=y -CONFIG_IA64_HP_AML_NFW=y -CONFIG_MSPEC=y -# CONFIG_IA64_HP_SIM is not set -# CONFIG_IA64_PAGE_SIZE_4KB is not set -# CONFIG_IA64_PAGE_SIZE_8KB is not set -CONFIG_IA64_PAGE_SIZE_16KB=y -# CONFIG_IA64_PAGE_SIZE_64KB is not set -CONFIG_IA64_L1_CACHE_SHIFT=7 -CONFIG_NUMA=y -# CONFIG_VIRTUAL_MEM_MAP is not set -CONFIG_SPARSEMEM_MANUAL=y -CONFIG_SPARSEMEM=y -CONFIG_MEMORY_HOTPLUG=y -CONFIG_MEMORY_HOTREMOVE=y -CONFIG_IA64_MCA_RECOVERY=m -CONFIG_IA64_CYCLONE=y -CONFIG_MMTIMER=y -CONFIG_IOSAPIC=y -CONFIG_FORCE_MAX_ZONEORDER=18 -CONFIG_NR_CPUS=1024 -# CONFIG_IA32_SUPPORT is not set -# CONFIG_COMPAT is not set -CONFIG_PERFMON=y -CONFIG_IA64_PALINFO=y -CONFIG_EFI_VARS=y -CONFIG_SERIAL_8250_RUNTIME_UARTS=16 -CONFIG_EFI_PCDP=y -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_BLK_DEV_SGIIOC4=y - -# -# Character devices -# -CONFIG_TCG_INFINEON=m - -# -# Watchdog Cards -# -# CONFIG_HW_RANDOM is not set -# CONFIG_GEN_RTC is not set -CONFIG_EFI_RTC=y -CONFIG_RTC_DRV_EFI=y - - -# -# AGP -# -CONFIG_AGP_I460=y -CONFIG_AGP_HP_ZX1=y -CONFIG_AGP_SGI_TIOCA=y - -# -# HP Simulator drivers -# -# CONFIG_HP_SIMETH is not set -# CONFIG_HP_SIMSERIAL is not set -# CONFIG_HP_SIMSCSI is not set - -# -# Kernel hacking -# -# CONFIG_IA64_PRINT_HAZARDS is not set -# CONFIG_DISABLE_VHPT is not set -# CONFIG_IA64_DEBUG_CMPXCHG is not set -# CONFIG_IA64_DEBUG_IRQ is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# SGI -# -CONFIG_SGI_SNSC=y -CONFIG_SGI_TIOCX=y -CONFIG_SGI_MBCS=m -CONFIG_SGI_IOC3=m -CONFIG_SGI_IOC4=y -CONFIG_SGI_XP=m -CONFIG_SGI_GRU=m -# CONFIG_SGI_GRU_DEBUG is not set -CONFIG_SERIAL_SGI_L1_CONSOLE=y -CONFIG_SERIAL_SGI_IOC3=m -CONFIG_SERIAL_SGI_IOC4=m - - -# -# SCSI low-level drivers -# -# CONFIG_SCSI_BUSLOGIC is not set - -# -CONFIG_ACPI=y -CONFIG_ACPI_AC=y -# CONFIG_ACPI_ASUS is not set -CONFIG_ACPI_PROCFS_POWER=y -CONFIG_ACPI_SYSFS_POWER=y -# CONFIG_ACPI_BATTERY is not set -CONFIG_ACPI_BLACKLIST_YEAR=0 -CONFIG_ACPI_BUTTON=y -# CONFIG_ACPI_DOCK is not set -CONFIG_ACPI_FAN=y -CONFIG_ACPI_HOTPLUG_MEMORY=y -CONFIG_ACPI_NUMA=y -CONFIG_ACPI_POWER=y -CONFIG_ACPI_PROCESSOR=y -CONFIG_ACPI_PROCFS=y -CONFIG_ACPI_SLEEP=y -CONFIG_ACPI_THERMAL=y -# CONFIG_ACPI_TOSHIBA is not set -CONFIG_ACPI_VIDEO=m -# CONFIG_ACPI_PROC_EVENT is not set -CONFIG_ACPI_HED=m -CONFIG_ACPI_EC_DEBUGFS=m -CONFIG_ACPI_IPMI=m -CONFIG_ACPI_CUSTOM_METHOD=m -CONFIG_SENSORS_ACPI_POWER=m - -CONFIG_PM=y -CONFIG_HOTPLUG_PCI=y -# CONFIG_HPET is not set -# CONFIG_HOTPLUG_PCI_CPCI is not set -CONFIG_HOTPLUG_PCI_SHPC=m -CONFIG_HOTPLUG_PCI_SGI=m -CONFIG_PNPACPI=y - -CONFIG_SCHED_SMT=y - -CONFIG_ARCH_DISCONTIGMEM_ENABLE=y - -CONFIG_IA64_ACPI_CPUFREQ=m - -# CONFIG_PERMIT_BSP_REMOVE is not set -# CONFIG_FORCE_CPEI_RETARGET is not set - -CONFIG_NODES_SHIFT=10 - - -CONFIG_HW_RANDOM_INTEL=m - -CONFIG_CRASH_DUMP=y -CONFIG_PROC_VMCORE=y - -# drivers/media/video/usbvision/usbvision-i2c.c:64:39: error: macro "outb" passed 4 arguments, but takes just 2 -# CONFIG_VIDEO_USBVISION is not set - -# CONFIG_IA64_MC_ERR_INJECT is not set - -CONFIG_DMIID=y -CONFIG_DMI_SYSFS=y - -CONFIG_SENSORS_I5K_AMB=m - -CONFIG_SPARSEMEM_VMEMMAP=y - -CONFIG_FRAME_WARN=2048 - -CONFIG_VIRT_CPU_ACCOUNTING=y -CONFIG_VIRTUALIZATION=y -CONFIG_KVM=m -CONFIG_KVM_INTEL=m - -CONFIG_HP_ILO=m - -CONFIG_PARAVIRT_GUEST=y -CONFIG_PARAVIRT=y -CONFIG_PARAVIRT_TIME_ACCOUNTING=y - -CONFIG_DMAR_DEFAULT_ON=y - -CONFIG_RCU_FANOUT=64 - -CONFIG_ACPI_POWER_METER=m -CONFIG_I2C_SCMI=m - -# CONFIG_HP_ACCEL is not set diff --git a/config-nodebug b/config-nodebug index 084f88e2e..0f70aa0ae 100644 --- a/config-nodebug +++ b/config-nodebug @@ -24,6 +24,7 @@ CONFIG_CPUMASK_OFFSTACK=y # CONFIG_FAULT_INJECTION_DEBUG_FS is not set # CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set # CONFIG_FAIL_IO_TIMEOUT is not set +# CONFIG_FAIL_MMC_REQUEST is not set # CONFIG_SLUB_DEBUG_ON is not set @@ -81,7 +82,6 @@ CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 # CONFIG_IWLWIFI_DEVICE_TRACING is not set # CONFIG_DEBUG_OBJECTS_WORK is not set -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DMADEVICES_DEBUG is not set # CONFIG_DMADEVICES_VDEBUG is not set @@ -99,9 +99,8 @@ CONFIG_KDB_KEYBOARD=y # CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set # CONFIG_TEST_LIST_SORT is not set -# CONFIG_DEBUG_SET_MODULE_RONX is not set - # CONFIG_DETECT_HUNG_TASK is not set CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set diff --git a/config-powerpc-generic b/config-powerpc-generic index 5ecaf0e5d..2ca0c3e83 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -43,11 +43,11 @@ CONFIG_FB_MATROX=y CONFIG_FB_ATY128_BACKLIGHT=y CONFIG_FB_ATY_BACKLIGHT=y CONFIG_FB_RIVA_BACKLIGHT=y -# FIXME: Do we care about this hardware ? -CONFIG_FB_MB862XX=m -CONFIG_FB_MB862XX_PCI_GDC=y -CONFIG_FB_MB862XX_LIME=y -CONFIG_FB_MB862XX_I2C=y +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_MB862XX_PCI_GDC is not set +# CONFIG_FB_MB862XX_LIME is not set +# CONFIG_FB_MB862XX_I2C is not set + CONFIG_SND_POWERMAC=m CONFIG_SND_POWERMAC_AUTO_DRC=y @@ -182,8 +182,8 @@ CONFIG_EDAC_PASEMI=m CONFIG_EDAC_AMD8131=m CONFIG_EDAC_AMD8111=m -CONFIG_AXON_RAM=m -CONFIG_OPROFILE_CELL=y +# CONFIG_AXON_RAM is not set +# CONFIG_OPROFILE_CELL is not set CONFIG_SUSPEND_FREEZER=y # CONFIG_IDEPCI_PCIBUS_ORDER is not set @@ -204,9 +204,9 @@ CONFIG_DMADEVICES=y CONFIG_SND_PPC=y -CONFIG_PPC_82xx=y -CONFIG_PPC_83xx=y -CONFIG_PPC_86xx=y +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +# CONFIG_PPC_86xx is not set CONFIG_EXTRA_TARGETS="" # CONFIG_CODE_PATCHING_SELFTEST is not set # CONFIG_FTR_FIXUP_SELFTEST is not set @@ -220,27 +220,28 @@ CONFIG_EXTRA_TARGETS="" # CONFIG_SERIAL_QE is not set # CONFIG_I2C_CPM is not set +CONFIG_NET_VENDOR_IBM=y -CONFIG_SERIO_XILINX_XPS_PS2=m +# CONFIG_SERIO_XILINX_XPS_PS2 is not set # CONFIG_PPC_SMLPAR is not set -CONFIG_MGCOGE=y -CONFIG_GEF_SBC610=y -CONFIG_GEF_PPC9A=y -CONFIG_GEF_SBC310=y +# CONFIG_MGCOGE is not set +# CONFIG_GEF_SBC610 is not set +# CONFIG_GEF_PPC9A is not set +# CONFIG_GEF_SBC310 is not set -CONFIG_QUICC_ENGINE=y -CONFIG_QE_GPIO=y -CONFIG_MPC8xxx_GPIO=y +# CONFIG_QUICC_ENGINE is not set +# CONFIG_QE_GPIO is not set +# CONFIG_MPC8xxx_GPIO is not set CONFIG_IDE_GD=y CONFIG_IDE_GD_ATA=y CONFIG_IDE_GD_ATAPI=y -CONFIG_MCU_MPC8349EMITX=m +# CONFIG_MCU_MPC8349EMITX is not set -CONFIG_GPIO_XILINX=y +# CONFIG_GPIO_XILINX is not set CONFIG_PMIC_DA903X=y CONFIG_BACKLIGHT_DA903X=m @@ -261,11 +262,11 @@ CONFIG_TOUCHSCREEN_DA9034=m CONFIG_SIMPLE_GPIO=y -CONFIG_FSL_PQ_MDIO=m +# CONFIG_FSL_PQ_MDIO is not set -CONFIG_PS3_VRAM=m +# CONFIG_PS3_VRAM is not set CONFIG_MDIO_GPIO=m -CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL=m +# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set # CONFIG_DEBUG_GPIO is not set CONFIG_GPIO_PCA953X=m CONFIG_GPIO_PCF857X=m @@ -293,20 +294,20 @@ CONFIG_SWIOTLB=y CONFIG_PPC_DISABLE_WERROR=y -CONFIG_XILINX_LL_TEMAC=m -CONFIG_XILINX_EMACLITE=m +# CONFIG_XILINX_LL_TEMAC is not set +# CONFIG_XILINX_EMACLITE is not set CONFIG_GPIO_WM831X=m # CONFIG_GPIO_LANGWELL is not set # CONFIG_GPIO_UCB1400 is not set -CONFIG_EDAC_MPC85XX=m +# CONFIG_EDAC_MPC85XX is not set CONFIG_NR_IRQS=512 CONFIG_SPARSE_IRQ=y -CONFIG_PPC_MPC5200_LPBFIFO=m -CONFIG_CAN_MSCAN=m -CONFIG_CAN_MPC5XXX=m +# CONFIG_PPC_MPC5200_LPBFIFO is not set +# CONFIG_CAN_MSCAN is not set +# CONFIG_CAN_MPC5XXX is not set CONFIG_PATA_MACIO=m CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m # CONFIG_PMIC_ADP5520 is not set @@ -327,7 +328,7 @@ CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m # CONFIG_PPC_MPC512x is not set # CONFIG_RTC_DRV_MPC5121 is not set -CONFIG_MPC512X_DMA=m +# CONFIG_MPC512X_DMA is not set CONFIG_KVM_GUEST=y @@ -338,15 +339,17 @@ CONFIG_I2C_MPC=m CONFIG_RFKILL_GPIO=m -CONFIG_CRYPTO_DEV_FSL_CAAM=m -CONFIG_CRYPTO_DEV_FSL_CAAM_RINGSIZE=9 -CONFIG_CRYPTO_DEV_FSL_CAAM_INTC=y -CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_COUNT_THLD=255 -CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD=2048 -CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=m +# CONFIG_CRYPTO_DEV_FSL_CAAM is not set # CONFIG_GPIO_GENERIC_PLATFORM is not set # CONFIG_GPIO_MCP23S08 is not set +# CONFIG_CAN_FLEXCAN is not set +# CONFIG_NET_VENDOR_XILINX is not set +# CONFIG_PPC_EPAPR_HV_BYTECHAN is not set +# CONFIG_IBM_EMAC is not set +# CONFIG_NET_VENDOR_PASEMI is not set +# CONFIG_NET_VENDOR_TOSHIBA is not set + # Disable btrfs until it is shown to work with 64k pages (rhbz 747079) # CONFIG_BTRFS_FS is not set diff --git a/config-powerpc32-generic b/config-powerpc32-generic index 31c399e65..e856b9ff0 100644 --- a/config-powerpc32-generic +++ b/config-powerpc32-generic @@ -7,17 +7,17 @@ CONFIG_PPC32=y CONFIG_CPU_FREQ_PMAC=y CONFIG_PPC_CHRP=y CONFIG_PPC_PMAC=y -CONFIG_PPC_MPC52xx=y +# CONFIG_PPC_MPC52xx is not set CONFIG_PPC_PREP=y # CONFIG_PPC_MPC5200_SIMPLE is not set -CONFIG_SATA_FSL=m +# CONFIG_SATA_FSL is not set # CONFIG_SATA_NV is not set # busted in .28git1 # ERROR: "cacheable_memzero" [drivers/net/gianfar_driver.ko] undefined! # CONFIG_GIANFAR is not set -CONFIG_USB_EHCI_FSL=y +# CONFIG_USB_EHCI_FSL is not set CONFIG_PMAC_APM_EMU=y CONFIG_PMAC_BACKLIGHT=y @@ -41,6 +41,7 @@ CONFIG_ADB_PMU_LED=y CONFIG_ADB_PMU_LED_IDE=y CONFIG_PMAC_MEDIABAY=y +CONFIG_NET_VENDOR_APPLE=y CONFIG_BMAC=m CONFIG_MACE=m # CONFIG_MACE_AAUI_PORT is not set @@ -72,24 +73,20 @@ CONFIG_BRIQ_PANEL=m # CONFIG_ATA_PIIX is not set # CONFIG_PATA_AMD is not set # CONFIG_PATA_ATIIXP is not set -CONFIG_PATA_MPC52xx=m +# CONFIG_PATA_MPC52xx is not set # CONFIG_PATA_MPIIX is not set # CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_OPTI is not set # CONFIG_PATA_SERVERWORKS is not set -CONFIG_SERIAL_MPC52xx=y -CONFIG_SERIAL_MPC52xx_CONSOLE=y -CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200 +# CONFIG_SERIAL_MPC52xx is not set # CONFIG_MPC5200_WDT is not set CONFIG_8xxx_WDT=m CONFIG_GEF_WDT=m -CONFIG_PPC_MPC5200_BUGFIX=y -CONFIG_FEC_MPC52xx=m +# CONFIG_PPC_MPC5200_BUGFIX is not set +# CONFIG_NET_VENDOR_FREESCALE is not set #CHECK: This may later become a tristate. -CONFIG_FEC_MPC52xx_MDIO=y -CONFIG_PPC_MPC5200_GPIO=y CONFIG_MDIO_GPIO=m CONFIG_SERIAL_OF_PLATFORM=y @@ -144,26 +141,28 @@ CONFIG_VIRTUALIZATION=y CONFIG_SND_ISA=y CONFIG_CRYPTO_DEV_TALITOS=m -CONFIG_FSL_EMB_PERFMON=y -CONFIG_MPC8272_ADS=y -CONFIG_PQ2FADS=y -CONFIG_EP8248E=y -CONFIG_MPC830x_RDB=y -CONFIG_MPC831x_RDB=y -CONFIG_MPC832x_MDS=y -CONFIG_MPC832x_RDB=y -CONFIG_MPC834x_MDS=y -CONFIG_MPC834x_ITX=y -CONFIG_MPC836x_MDS=y -CONFIG_MPC836x_RDK=y -CONFIG_MPC837x_MDS=y -CONFIG_MPC837x_RDB=y -CONFIG_SBC834x=y -CONFIG_ASP834x=y -CONFIG_KMETER1=y -CONFIG_MPC8641_HPCN=y -CONFIG_SBC8641D=y -CONFIG_MPC8610_HPCD=y +# CONFIG_FSL_EMB_PERFMON is not set +# CONFIG_MPC8272_ADS is not set +# CONFIG_PQ2FADS is not set +# CONFIG_EP8248E is not set +# CONFIG_MPC830x_RDB is not set +# CONFIG_MPC831x_RDB is not set +# CONFIG_MPC832x_MDS is not set +# CONFIG_MPC832x_RDB is not set +# CONFIG_MPC834x_MDS is not set +# CONFIG_MPC834x_ITX is not set +# CONFIG_MPC836x_MDS is not set +# CONFIG_MPC836x_RDK is not set +# CONFIG_MPC837x_MDS is not set +# CONFIG_MPC837x_RDB is not set +# CONFIG_SBC834x is not set +# CONFIG_ASP834x is not set +# CONFIG_KMETER1 is not set +# CONFIG_MPC8641_HPCN is not set +# CONFIG_SBC8641D is not set +# CONFIG_MPC8610_HPCD is not set +# CONFIG_FSL_LBC is not set +# CONFIG_MTD_NAND_FSL_UPM is not set # CONFIG_USB_MUSB_HDRC is not set @@ -172,8 +171,6 @@ CONFIG_MPC8610_HPCD=y # drivers/mtd/maps/sbc8240.c:172: warning: passing argument 1 of 'simple_map_init' from incompatible pointer type # drivers/mtd/maps/sbc8240.c:177: error: 'struct mtd_info' has no member named 'module' -CONFIG_MTD_NAND_FSL_UPM=m - CONFIG_RCU_FANOUT=32 CONFIG_PERF_COUNTERS=y @@ -185,3 +182,4 @@ CONFIG_KVM_BOOK3S_32=m # CONFIG_SCSI_QLA_ISCSI is not set CONFIG_BATTERY_PMU=m + diff --git a/config-powerpc64 b/config-powerpc64 index 29ea23201..42b501675 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -2,42 +2,23 @@ CONFIG_WINDFARM_PM81=y CONFIG_WINDFARM_PM91=y CONFIG_WINDFARM_PM121=y CONFIG_PPC_PMAC64=y -CONFIG_PPC_MAPLE=y -CONFIG_PPC_CELL=y -CONFIG_PPC_IBM_CELL_BLADE=y +# CONFIG_PPC_MAPLE is not set +# CONFIG_PPC_CELL is not set +# CONFIG_PPC_IBM_CELL_BLADE is not set CONFIG_PPC_ISERIES=y CONFIG_PPC_PSERIES=y CONFIG_PPC_PMAC=y -CONFIG_PPC_PASEMI=y +CONFIG_PPC_POWERNV=y +CONFIG_PPC_POWERNV_RTAS=y +# CONFIG_PPC_PASEMI is not set # CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE is not set -CONFIG_PPC_PS3=y -CONFIG_PPC_CELLEB=y -CONFIG_PPC_CELL_QPACE=y -CONFIG_PS3_HTAB_SIZE=20 -# CONFIG_PS3_DYNAMIC_DMA is not set -CONFIG_PS3_ADVANCED=y -CONFIG_PS3_HTAB_SIZE=20 -# CONFIG_PS3_DYNAMIC_DMA is not set -CONFIG_PS3_VUART=y -CONFIG_PS3_PS3AV=y -CONFIG_PS3_STORAGE=m -CONFIG_PS3_DISK=m -CONFIG_PS3_ROM=m -CONFIG_PS3_FLASH=m -CONFIG_PS3_LPM=y -CONFIG_SND_PS3=m -CONFIG_SND_PS3_DEFAULT_START_DELAY=1000 -CONFIG_GELIC_NET=m -CONFIG_GELIC_WIRELESS=y -CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE=y -CONFIG_CBE_THERM=m -CONFIG_CBE_CPUFREQ=m -CONFIG_CBE_CPUFREQ_PMI=m -CONFIG_CBE_CPUFREQ_PMI_ENABLE=y +# CONFIG_PPC_PS3 is not set +# CONFIG_PPC_CELLEB is not set +# CONFIG_PPC_CELL_QPACE is not set CONFIG_PMAC_RACKMETER=m CONFIG_IBMEBUS=y -CONFIG_SPU_FS=m CONFIG_RTAS_FLASH=y +# CONFIG_UDBG_RTAS_CONSOLE is not set CONFIG_PPC_SPLPAR=y CONFIG_SCANLOG=y CONFIG_LPARCFG=y @@ -60,10 +41,9 @@ CONFIG_CPU_FREQ_PMAC64=y CONFIG_SCSI_IPR=m CONFIG_SCSI_IPR_TRACE=y CONFIG_SCSI_IPR_DUMP=y -CONFIG_SPIDER_NET=m CONFIG_HVC_RTAS=y CONFIG_HVC_ISERIES=y -CONFIG_CBE_RAS=y +CONFIG_HVC_OPAL=y # iSeries device drivers # @@ -75,19 +55,13 @@ CONFIG_VIOTAPE=m CONFIG_PASEMI_MAC=m CONFIG_SERIAL_OF_PLATFORM=m -CONFIG_PPC_PASEMI_IOMMU=y CONFIG_SERIAL_TXX9=y CONFIG_SERIAL_TXX9_NR_UARTS=6 CONFIG_SERIAL_TXX9_CONSOLE=y CONFIG_HVC_BEAT=y -CONFIG_FB_PS3=y -CONFIG_FB_PS3_DEFAULT_SIZE_M=18 - CONFIG_PPC_PMI=m -CONFIG_PS3_SYS_MANAGER=y -# CONFIG_BLK_DEV_CELLEB is not set CONFIG_PATA_SCC=m @@ -138,19 +112,9 @@ CONFIG_SECCOMP=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y # CONFIG_BLK_DEV_PLATFORM is not set -CONFIG_IBM_NEW_EMAC=m -CONFIG_IBM_NEW_EMAC_RXB=128 -CONFIG_IBM_NEW_EMAC_TXB=64 -CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32 -CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256 -CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0 -# CONFIG_IBM_NEW_EMAC_DEBUG is not set # CONFIG_VIRQ_DEBUG is not set -CONFIG_ELECTRA_CF=m -CONFIG_MTD_NAND_PASEMI=m -CONFIG_EDAC_CELL=m CONFIG_EDAC_CPC925=m CONFIG_FRAME_WARN=2048 @@ -164,14 +128,6 @@ CONFIG_SCSI_IBMVFC=m # CONFIG_SCSI_IBMVFC_TRACE is not set CONFIG_IBM_BSR=m -CONFIG_SERIO_XILINX_XPS_PS2=m - -CONFIG_PPC_IBM_CELL_RESETBUTTON=y -CONFIG_PPC_IBM_CELL_POWERBUTTON=m -CONFIG_CBE_CPUFREQ_SPU_GOVERNOR=m - -CONFIG_RTC_DRV_PS3=y - CONFIG_CRASH_DUMP=y CONFIG_RELOCATABLE=y @@ -202,4 +158,3 @@ CONFIG_IO_EVENT_IRQ=y CONFIG_HW_RANDOM_AMD=m CONFIG_BPF_JIT=y -CONFIG_CPU_FREQ_MAPLE=y diff --git a/config-s390x b/config-s390x index 5251b5b32..f03942191 100644 --- a/config-s390x +++ b/config-s390x @@ -237,3 +237,5 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_WARN_DYNAMIC_STACK is not set CONFIG_CRYPTO_GHASH_S390=m +CONFIG_NET_CORE=y +CONFIG_ETHERNET=y diff --git a/config-sparc64-generic b/config-sparc64-generic index e5ee2c4b9..e9b66f6d6 100644 --- a/config-sparc64-generic +++ b/config-sparc64-generic @@ -43,6 +43,7 @@ CONFIG_I2C_ALI1535=m # CONFIG_VGASTATE is not set # CONFIG_FB_DDC is not set # CONFIG_FB_BW2 is not set +# CONFIG_FB_GRVGA is not set CONFIG_FB_CG3=y CONFIG_FB_CG6=y # CONFIG_FB_RIVA is not set diff --git a/config-x86-32-generic b/config-x86-32-generic index caeae9398..3b55ae521 100644 --- a/config-x86-32-generic +++ b/config-x86-32-generic @@ -57,9 +57,6 @@ CONFIG_FB_GEODE_GX=y # CONFIG_PCI_GOMMCONFIG is not set CONFIG_PCI_GOANY=y -# FIXME: wtf? "x86 specific drivers" -CONFIG_PCMCIA_FDOMAIN=m -CONFIG_SCSI_FUTURE_DOMAIN=m CONFIG_IBM_ASM=m # @@ -138,8 +135,6 @@ CONFIG_CRYPTO_TWOFISH_586=m CONFIG_VIDEO_CAFE_CCIC=m -CONFIG_VMI=y - CONFIG_XEN_MAX_DOMAIN_MEMORY=8 CONFIG_MTD_NAND_CAFE=m @@ -155,6 +150,7 @@ CONFIG_OLPC_XO1_PM=y CONFIG_OLPC_XO15_SCI=y CONFIG_OLPC_XO1_RTC=y CONFIG_OLPC_XO1_SCI=y +# CONFIG_ALIX is not set # staging # CONFIG_FB_OLPC_DCON is not set @@ -204,3 +200,6 @@ CONFIG_I2O_EXT_ADAPTEC=y CONFIG_I2O_CONFIG_OLD_IOCTL=y CONFIG_I2O_BUS=m +# CONFIG_EDAC_SBRIDGE is not set + +# CONFIG_X86_WANT_INTEL_MID is not set diff --git a/config-x86-generic b/config-x86-generic index 45fda3b7c..fec30ea87 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -36,10 +36,10 @@ CONFIG_FB_EFI=y # FIXME: 32bit only? # CONFIG_FB_N411 is not set -CONFIG_DMAR=y +CONFIG_INTEL_IOMMU=y CONFIG_DMAR_BROKEN_GFX_WA=y -CONFIG_DMAR_FLOPPY_WA=y -# CONFIG_DMAR_DEFAULT_ON is not set +CONFIG_INTEL_IOMMU_FLOPPY_WA=y +# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set CONFIG_SCSI_ADVANSYS=m CONFIG_SECCOMP=y @@ -59,7 +59,6 @@ CONFIG_DEBUG_STACKOVERFLOW=y CONFIG_ACPI=y CONFIG_ACPI_AC=y # CONFIG_ACPI_ASUS is not set -CONFIG_ACPI_PROCFS_POWER=y CONFIG_ACPI_BATTERY=y CONFIG_ACPI_BUTTON=y CONFIG_ACPI_CONTAINER=m @@ -73,6 +72,8 @@ CONFIG_ACPI_SLEEP=y CONFIG_ACPI_THERMAL=y CONFIG_ACPI_TOSHIBA=m CONFIG_ACPI_VIDEO=m +# FIXME: Next two are deprecated. Remove them when they disappear upstream +# CONFIG_ACPI_PROCFS_POWER is not set # CONFIG_ACPI_PROC_EVENT is not set CONFIG_PNPACPI=y CONFIG_ACPI_PROCESSOR_AGGREGATOR=m @@ -227,8 +228,7 @@ CONFIG_PARAVIRT=y CONFIG_PARAVIRT_TIME_ACCOUNTING=y # CONFIG_PARAVIRT_DEBUG is not set -# PARAVIRT_SPINLOCKS has a 5% perf hit -# FIXME: Still true ? References? +# PARAVIRT_SPINLOCKS has a 5% perf hit on native hw (see kconfig) # CONFIG_PARAVIRT_SPINLOCKS is not set CONFIG_KVM_CLOCK=y @@ -310,7 +310,7 @@ CONFIG_HP_ILO=m CONFIG_BACKLIGHT_APPLE=m -# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set +CONFIG_X86_CHECK_BIOS_CORRUPTION=y # CONFIG_CMDLINE_BOOL is not set @@ -381,3 +381,6 @@ CONFIG_HP_ACCEL=m CONFIG_SCHED_SMT=y CONFIG_CC_STACKPROTECTOR=y CONFIG_RELOCATABLE=y + +# CONFIG_HYPERV is not set + diff --git a/config-x86_64-generic b/config-x86_64-generic index 693c3a8b6..f5b440a73 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -22,8 +22,7 @@ CONFIG_AMD_IOMMU=y CONFIG_AMD_IOMMU_STATS=y # CONFIG_IOMMU_DEBUG is not set CONFIG_SWIOTLB=y -CONFIG_CALGARY_IOMMU=y -CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y +# CONFIG_CALGARY_IOMMU is not set CONFIG_KEXEC_JUMP=y @@ -44,6 +43,9 @@ CONFIG_CRYPTO_AES_X86_64=y CONFIG_CRYPTO_TWOFISH_X86_64=m CONFIG_CRYPTO_SALSA20_X86_64=m CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m +CONFIG_CRYPTO_SHA1_SSSE3=m +CONFIG_CRYPTO_BLOWFISH_X86_64=m +CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=m # CONFIG_I2C_ALI1535 is not set # CONFIG_I2C_ALI1563 is not set @@ -53,6 +55,7 @@ CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m CONFIG_EDAC_AMD64=m # CONFIG_EDAC_AMD64_ERROR_INJECTION is not set +CONFIG_EDAC_SBRIDGE=m # CONFIG_PC8736x_GPIO is not set @@ -62,8 +65,8 @@ CONFIG_SPARSEMEM=y CONFIG_HAVE_MEMORY_PRESENT=y CONFIG_SPARSEMEM_EXTREME=y CONFIG_SPARSEMEM_VMEMMAP=y -CONFIG_MEMORY_HOTPLUG=y -CONFIG_MEMORY_HOTREMOVE=y +# CONFIG_MEMORY_HOTPLUG is not set +# CONFIG_MEMORY_HOTREMOVE is not set # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_RZ1000 is not set @@ -79,7 +82,7 @@ CONFIG_SGI_GRU=m # CONFIG_VIDEO_CAFE_CCIC is not set -CONFIG_XEN_MAX_DOMAIN_MEMORY=32 +CONFIG_XEN_MAX_DOMAIN_MEMORY=128 # CONFIG_XEN_BALLOON_MEMORY_HOTPLUG is not set CONFIG_XEN_DEV_EVTCHN=m CONFIG_XEN_SYS_HYPERVISOR=y @@ -95,7 +98,7 @@ CONFIG_DIRECT_GBPAGES=y CONFIG_X86_MPPARSE=y CONFIG_I7300_IDLE=m -CONFIG_INTR_REMAP=y +CONFIG_IRQ_REMAP=y CONFIG_X86_X2APIC=y CONFIG_SPARSE_IRQ=y diff --git a/drm-i915-sdvo-lvds-is-digital.patch b/drm-i915-sdvo-lvds-is-digital.patch deleted file mode 100644 index 68d0c4b31..000000000 --- a/drm-i915-sdvo-lvds-is-digital.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 64015d6d16d7ed5b6ffcec95dc13e8694bd2a4d6 Mon Sep 17 00:00:00 2001 -From: Chris Wilson -Date: Mon, 20 Jun 2011 22:35:24 +0100 -Subject: [PATCH] drm/i915/sdvo: Include LVDS panels for the IS_DIGITAL check - -We were checking whether the supplied edid matched the connector it was -read from. We do this in case a DDC read returns an EDID for another -device on a multifunction or otherwise interesting card. However, we -failed to include LVDS as a digital device and so rejecting an otherwise -valid EDID. - -Fixes the detection of the secondary SDVO LVDS panel on the Libretto -W105. - -Signed-off-by: Chris Wilson ---- - drivers/gpu/drm/i915/intel_sdvo.c | 28 ++++++++++++++++++++-------- - 1 files changed, 20 insertions(+), 8 deletions(-) - -diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c -index f96975c..26eff9f 100644 ---- a/drivers/gpu/drm/i915/intel_sdvo.c -+++ b/drivers/gpu/drm/i915/intel_sdvo.c -@@ -49,6 +49,7 @@ - #define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK) - #define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK) - #define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK)) -+#define IS_DIGITAL(c) (c->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK)) - - - static const char *tv_format_names[] = { -@@ -1363,6 +1364,18 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) - return status; - } - -+static bool -+intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo, -+ struct edid *edid) -+{ -+ bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); -+ bool connector_is_digital = !!IS_DIGITAL(sdvo); -+ -+ DRM_DEBUG_KMS("connector_is_digital? %d, monitor_is_digital? %d\n", -+ connector_is_digital, monitor_is_digital); -+ return connector_is_digital == monitor_is_digital; -+} -+ - static enum drm_connector_status - intel_sdvo_detect(struct drm_connector *connector, bool force) - { -@@ -1407,10 +1420,12 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) - if (edid == NULL) - edid = intel_sdvo_get_analog_edid(connector); - if (edid != NULL) { -- if (edid->input & DRM_EDID_INPUT_DIGITAL) -- ret = connector_status_disconnected; -- else -+ if (intel_sdvo_connector_matches_edid(intel_sdvo_connector, -+ edid)) - ret = connector_status_connected; -+ else -+ ret = connector_status_disconnected; -+ - connector->display_info.raw_edid = NULL; - kfree(edid); - } else -@@ -1451,11 +1466,8 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) - edid = intel_sdvo_get_analog_edid(connector); - - if (edid != NULL) { -- struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); -- bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); -- bool connector_is_digital = !!IS_TMDS(intel_sdvo_connector); -- -- if (connector_is_digital == monitor_is_digital) { -+ if (intel_sdvo_connector_matches_edid(to_intel_sdvo_connector(connector), -+ edid)) { - drm_mode_connector_update_edid_property(connector, edid); - drm_add_edid_modes(connector, edid); - } --- -1.7.5.4 - diff --git a/drm-lower-severity-radeon-lockup.diff b/drm-lower-severity-radeon-lockup.diff deleted file mode 100644 index 1302c92ea..000000000 --- a/drm-lower-severity-radeon-lockup.diff +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c -index 7fd4e3e..a488b50 100644 ---- a/drivers/gpu/drm/radeon/radeon_fence.c -+++ b/drivers/gpu/drm/radeon/radeon_fence.c -@@ -263,7 +263,7 @@ retry: - */ - if (seq == rdev->fence_drv.last_seq && radeon_gpu_is_lockup(rdev)) { - /* good news we believe it's a lockup */ -- WARN(1, "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n", -+ printk(KERN_WARNING "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n", - fence->seq, seq); - /* FIXME: what should we do ? marking everyone - * as signaled for now diff --git a/elantech.patch b/elantech.patch deleted file mode 100644 index fa7c67fec..000000000 --- a/elantech.patch +++ /dev/null @@ -1,2180 +0,0 @@ -From 13ac768d9a8731c8b3bab7d6c86520f290272fe7 Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Fri, 9 Sep 2011 10:22:19 -0700 -Subject: Input: elantech - correct x, y value range for v2 hardware -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -x, y values are actually 12-bit long. Also update protocol document to -reflect the change. - -Signed-off-by: JJ Ding -Acked-by: Daniel Kurtz -Acked-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - Documentation/input/elantech.txt | 8 ++++---- - drivers/input/mouse/elantech.c | 8 ++++---- - 2 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt -index db798af..bce9941 100644 ---- a/Documentation/input/elantech.txt -+++ b/Documentation/input/elantech.txt -@@ -389,14 +389,14 @@ byte 0: - byte 1: - - bit 7 6 5 4 3 2 1 0 -- p7 p6 p5 p4 . x10 x9 x8 -+ p7 p6 p5 p4 x11 x10 x9 x8 - - byte 2: - - bit 7 6 5 4 3 2 1 0 - x7 x6 x5 x4 x3 x2 x1 x0 - -- x10..x0 = absolute x value (horizontal) -+ x11..x0 = absolute x value (horizontal) - - byte 3: - -@@ -420,7 +420,7 @@ byte 3: - byte 4: - - bit 7 6 5 4 3 2 1 0 -- p3 p1 p2 p0 . . y9 y8 -+ p3 p1 p2 p0 y11 y10 y9 y8 - - p7..p0 = pressure (not EF113) - -@@ -429,7 +429,7 @@ byte 5: - bit 7 6 5 4 3 2 1 0 - y7 y6 y5 y4 y3 y2 y1 y0 - -- y9..y0 = absolute y value (vertical) -+ y11..y0 = absolute y value (vertical) - - - 4.2.2 Two finger touch -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index 3250356..da161da 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -290,15 +290,15 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - /* pass through... */ - case 1: - /* -- * byte 1: . . . . . x10 x9 x8 -+ * byte 1: . . . . x11 x10 x9 x8 - * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 - */ -- x1 = ((packet[1] & 0x07) << 8) | packet[2]; -+ x1 = ((packet[1] & 0x0f) << 8) | packet[2]; - /* -- * byte 4: . . . . . . y9 y8 -+ * byte 4: . . . . y11 y10 y9 y8 - * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 - */ -- y1 = ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5]); -+ y1 = ETP_YMAX_V2 - (((packet[4] & 0x0f) << 8) | packet[5]); - - input_report_abs(dev, ABS_X, x1); - input_report_abs(dev, ABS_Y, y1); --- -1.7.6.4 - - -From c47c9334b4ebb6ecb565d9bf834df170fcd09484 Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Fri, 9 Sep 2011 10:22:58 -0700 -Subject: Input: elantech - get rid of ETP_2FT_* in elantech.h -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -For two finger touches the coordinate of each finger gets reported -separately but with reduced resolution. - -With this change, we now have the same range for ST and MT data and -scale MT data because it has lower resolution to match ST. - -Suggested-by: Dmitry Torokhov -Signed-off-by: JJ Ding -Acked-by: Daniel Kurtz -Acked-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/elantech.c | 28 +++++++++++++--------------- - drivers/input/mouse/elantech.h | 11 ----------- - 2 files changed, 13 insertions(+), 26 deletions(-) - -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index da161da..cd8e2e5 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -273,11 +273,11 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - struct elantech_data *etd = psmouse->private; - struct input_dev *dev = psmouse->dev; - unsigned char *packet = psmouse->packet; -- unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0, width = 0, pres = 0; -+ unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0; -+ unsigned int width = 0, pres = 0; - - /* byte 0: n1 n0 . . . . R L */ - fingers = (packet[0] & 0xc0) >> 6; -- input_report_key(dev, BTN_TOUCH, fingers != 0); - - switch (fingers) { - case 3: -@@ -300,9 +300,6 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - */ - y1 = ETP_YMAX_V2 - (((packet[4] & 0x0f) << 8) | packet[5]); - -- input_report_abs(dev, ABS_X, x1); -- input_report_abs(dev, ABS_Y, y1); -- - pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); - width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); - break; -@@ -314,22 +311,18 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - * byte 0: . . ay8 ax8 . . . . - * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 - */ -- x1 = ((packet[0] & 0x10) << 4) | packet[1]; -+ x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2; - /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ -- y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); -+ y1 = ETP_YMAX_V2 - -+ ((((packet[0] & 0x20) << 3) | packet[2]) << 2); - /* - * byte 3: . . by8 bx8 . . . . - * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 - */ -- x2 = ((packet[3] & 0x10) << 4) | packet[4]; -+ x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2; - /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ -- y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); -- /* -- * For compatibility with the X Synaptics driver scale up -- * one coordinate and report as ordinary mouse movent -- */ -- input_report_abs(dev, ABS_X, x1 << 2); -- input_report_abs(dev, ABS_Y, y1 << 2); -+ y2 = ETP_YMAX_V2 - -+ ((((packet[3] & 0x20) << 3) | packet[5]) << 2); - - /* Unknown so just report sensible values */ - pres = 127; -@@ -337,6 +330,11 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - break; - } - -+ input_report_key(dev, BTN_TOUCH, fingers != 0); -+ if (fingers != 0) { -+ input_report_abs(dev, ABS_X, x1); -+ input_report_abs(dev, ABS_Y, y1); -+ } - elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); - input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); - input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); -diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h -index fabb2b9..1c5894e 100644 ---- a/drivers/input/mouse/elantech.h -+++ b/drivers/input/mouse/elantech.h -@@ -82,17 +82,6 @@ - #define ETP_WMIN_V2 0 - #define ETP_WMAX_V2 15 - --/* -- * For two finger touches the coordinate of each finger gets reported -- * separately but with reduced resolution. -- */ --#define ETP_2FT_FUZZ 4 -- --#define ETP_2FT_XMIN ( 0 + ETP_2FT_FUZZ) --#define ETP_2FT_XMAX (288 - ETP_2FT_FUZZ) --#define ETP_2FT_YMIN ( 0 + ETP_2FT_FUZZ) --#define ETP_2FT_YMAX (192 - ETP_2FT_FUZZ) -- - struct elantech_data { - unsigned char reg_10; - unsigned char reg_11; --- -1.7.6.4 - - -From aa719e391c1769c93ec42a30daffa4ffa2a8503c Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Fri, 9 Sep 2011 10:26:16 -0700 -Subject: Input: elantech - use firmware provided x, y ranges -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -With newer hardware, the touchpad provides range info. -Let's use it. - -Signed-off-by: JJ Ding -Acked-by: Daniel Kurtz -Acked-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/elantech.c | 71 +++++++++++++++++++++++++++++++-------- - drivers/input/mouse/elantech.h | 3 +- - 2 files changed, 58 insertions(+), 16 deletions(-) - -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index cd8e2e5..296b6a6 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -223,7 +223,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) - input_report_abs(dev, ABS_X, - ((packet[1] & 0x0c) << 6) | packet[2]); - input_report_abs(dev, ABS_Y, -- ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3])); -+ etd->y_max - (((packet[1] & 0x03) << 8) | packet[3])); - } - - input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); -@@ -233,7 +233,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) - input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); - - if (etd->fw_version < 0x020000 && -- (etd->capabilities & ETP_CAP_HAS_ROCKER)) { -+ (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) { - /* rocker up */ - input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); - /* rocker down */ -@@ -298,7 +298,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - * byte 4: . . . . y11 y10 y9 y8 - * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 - */ -- y1 = ETP_YMAX_V2 - (((packet[4] & 0x0f) << 8) | packet[5]); -+ y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); - - pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); - width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); -@@ -313,7 +313,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - */ - x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2; - /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ -- y1 = ETP_YMAX_V2 - -+ y1 = etd->y_max - - ((((packet[0] & 0x20) << 3) | packet[2]) << 2); - /* - * byte 3: . . by8 bx8 . . . . -@@ -321,7 +321,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - */ - x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2; - /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ -- y2 = ETP_YMAX_V2 - -+ y2 = etd->y_max - - ((((packet[3] & 0x20) << 3) | packet[5]) << 2); - - /* Unknown so just report sensible values */ -@@ -468,6 +468,41 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) - return rc; - } - -+static void elantech_set_range(struct psmouse *psmouse, -+ unsigned int *x_min, unsigned int *y_min, -+ unsigned int *x_max, unsigned int *y_max) -+{ -+ struct elantech_data *etd = psmouse->private; -+ int i; -+ -+ switch (etd->hw_version) { -+ case 1: -+ *x_min = ETP_XMIN_V1; -+ *y_min = ETP_YMIN_V1; -+ *x_max = ETP_XMAX_V1; -+ *y_max = ETP_YMAX_V1; -+ break; -+ -+ case 2: -+ if (etd->fw_version == 0x020800 || -+ etd->fw_version == 0x020b00 || -+ etd->fw_version == 0x020030) { -+ *x_min = ETP_XMIN_V2; -+ *y_min = ETP_YMIN_V2; -+ *x_max = ETP_XMAX_V2; -+ *y_max = ETP_YMAX_V2; -+ } else { -+ i = (etd->fw_version > 0x020800 && -+ etd->fw_version < 0x020900) ? 1 : 2; -+ *x_min = 0; -+ *y_min = 0; -+ *x_max = (etd->capabilities[1] - i) * 64; -+ *y_max = (etd->capabilities[2] - i) * 64; -+ } -+ break; -+ } -+} -+ - /* - * Set the appropriate event bits for the input subsystem - */ -@@ -475,6 +510,9 @@ static void elantech_set_input_params(struct psmouse *psmouse) - { - struct input_dev *dev = psmouse->dev; - struct elantech_data *etd = psmouse->private; -+ unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0; -+ -+ elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max); - - __set_bit(EV_KEY, dev->evbit); - __set_bit(EV_ABS, dev->evbit); -@@ -492,18 +530,18 @@ static void elantech_set_input_params(struct psmouse *psmouse) - case 1: - /* Rocker button */ - if (etd->fw_version < 0x020000 && -- (etd->capabilities & ETP_CAP_HAS_ROCKER)) { -+ (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) { - __set_bit(BTN_FORWARD, dev->keybit); - __set_bit(BTN_BACK, dev->keybit); - } -- input_set_abs_params(dev, ABS_X, ETP_XMIN_V1, ETP_XMAX_V1, 0, 0); -- input_set_abs_params(dev, ABS_Y, ETP_YMIN_V1, ETP_YMAX_V1, 0, 0); -+ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); -+ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); - break; - - case 2: - __set_bit(BTN_TOOL_QUADTAP, dev->keybit); -- input_set_abs_params(dev, ABS_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); -- input_set_abs_params(dev, ABS_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); -+ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); -+ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); - if (etd->reports_pressure) { - input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, - ETP_PMAX_V2, 0, 0); -@@ -512,10 +550,12 @@ static void elantech_set_input_params(struct psmouse *psmouse) - } - __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); - input_mt_init_slots(dev, 2); -- input_set_abs_params(dev, ABS_MT_POSITION_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); -- input_set_abs_params(dev, ABS_MT_POSITION_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); -+ input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); -+ input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); - break; - } -+ -+ etd->y_max = y_max; - } - - struct elantech_attr_data { -@@ -769,13 +809,14 @@ int elantech_init(struct psmouse *psmouse) - pr_info("assuming hardware version %d, firmware version %d.%d.%d\n", - etd->hw_version, param[0], param[1], param[2]); - -- if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) { -+ if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, -+ etd->capabilities)) { - pr_err("failed to query capabilities.\n"); - goto init_fail; - } - pr_info("Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n", -- param[0], param[1], param[2]); -- etd->capabilities = param[0]; -+ etd->capabilities[0], etd->capabilities[1], -+ etd->capabilities[2]); - - /* - * This firmware suffers from misreporting coordinates when -diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h -index 1c5894e..b54ea27 100644 ---- a/drivers/input/mouse/elantech.h -+++ b/drivers/input/mouse/elantech.h -@@ -93,13 +93,14 @@ struct elantech_data { - unsigned char reg_25; - unsigned char reg_26; - unsigned char debug; -- unsigned char capabilities; -+ unsigned char capabilities[3]; - bool paritycheck; - bool jumpy_cursor; - bool reports_pressure; - unsigned char hw_version; - unsigned int fw_version; - unsigned int single_finger_reports; -+ unsigned int y_max; - unsigned char parity[256]; - }; - --- -1.7.6.4 - - -From 91f395e84dc83707b01c69e297894dbf992a566e Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Fri, 9 Sep 2011 10:27:42 -0700 -Subject: Input: elantech - remove ETP_EDGE_FUZZ_V2 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Don't try to be too clever and remove ETP_EDGE_FUZZ_V2. X, Y ranges -should be just the raw resolution of the device. Otherwise, they can -cause underflow on the Y axis. - -Suggested-by: Éric Piel -Signed-off-by: JJ Ding -Acked-by: Daniel Kurtz -Acked-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/elantech.h | 15 ++++++--------- - 1 files changed, 6 insertions(+), 9 deletions(-) - -diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h -index b54ea27..d9e6144 100644 ---- a/drivers/input/mouse/elantech.h -+++ b/drivers/input/mouse/elantech.h -@@ -66,16 +66,13 @@ - #define ETP_YMAX_V1 (384 - ETP_EDGE_FUZZ_V1) - - /* -- * It seems the resolution for hardware version 2 doubled. -- * Hence the X and Y ranges are doubled too. -- * The bezel around the pad also appears to be smaller -+ * The resolution for older v2 hardware doubled. -+ * (newer v2's firmware provides command so we can query) - */ --#define ETP_EDGE_FUZZ_V2 8 -- --#define ETP_XMIN_V2 ( 0 + ETP_EDGE_FUZZ_V2) --#define ETP_XMAX_V2 (1152 - ETP_EDGE_FUZZ_V2) --#define ETP_YMIN_V2 ( 0 + ETP_EDGE_FUZZ_V2) --#define ETP_YMAX_V2 ( 768 - ETP_EDGE_FUZZ_V2) -+#define ETP_XMIN_V2 0 -+#define ETP_XMAX_V2 1152 -+#define ETP_YMIN_V2 0 -+#define ETP_YMAX_V2 768 - - #define ETP_PMIN_V2 0 - #define ETP_PMAX_V2 255 --- -1.7.6.4 - - -From cc66bde05d267cce5a6f64d877e63036505cc31e Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Fri, 9 Sep 2011 10:28:04 -0700 -Subject: Input: elantech - packet checking for v2 hardware -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -For v2 hardware, there is no real parity check, but we can still check -some constant bits for data integrity. - -Also rename elantech_check_parity_v1 to elantech_packet_check_v1 to make -these packet checking function names consistent. - -Signed-off-by: JJ Ding -Acked-by: Daniel Kurtz -Acked-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/elantech.c | 39 ++++++++++++++++++++++++++++++++++----- - 1 files changed, 34 insertions(+), 5 deletions(-) - -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index 296b6a6..f2e3a2b 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -350,7 +350,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - input_sync(dev); - } - --static int elantech_check_parity_v1(struct psmouse *psmouse) -+static int elantech_packet_check_v1(struct psmouse *psmouse) - { - struct elantech_data *etd = psmouse->private; - unsigned char *packet = psmouse->packet; -@@ -374,6 +374,34 @@ static int elantech_check_parity_v1(struct psmouse *psmouse) - etd->parity[packet[3]] == p3; - } - -+static int elantech_packet_check_v2(struct psmouse *psmouse) -+{ -+ struct elantech_data *etd = psmouse->private; -+ unsigned char *packet = psmouse->packet; -+ -+ /* -+ * V2 hardware has two flavors. Older ones that do not report pressure, -+ * and newer ones that reports pressure and width. With newer ones, all -+ * packets (1, 2, 3 finger touch) have the same constant bits. With -+ * older ones, 1/3 finger touch packets and 2 finger touch packets -+ * have different constant bits. -+ * With all three cases, if the constant bits are not exactly what I -+ * expected, I consider them invalid. -+ */ -+ if (etd->reports_pressure) -+ return (packet[0] & 0x0c) == 0x04 && -+ (packet[3] & 0x0f) == 0x02; -+ -+ if ((packet[0] & 0xc0) == 0x80) -+ return (packet[0] & 0x0c) == 0x0c && -+ (packet[3] & 0x0e) == 0x08; -+ -+ return (packet[0] & 0x3c) == 0x3c && -+ (packet[1] & 0xf0) == 0x00 && -+ (packet[3] & 0x3e) == 0x38 && -+ (packet[4] & 0xf0) == 0x00; -+} -+ - /* - * Process byte stream from mouse and handle complete packets - */ -@@ -389,14 +417,16 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) - - switch (etd->hw_version) { - case 1: -- if (etd->paritycheck && !elantech_check_parity_v1(psmouse)) -+ if (etd->paritycheck && !elantech_packet_check_v1(psmouse)) - return PSMOUSE_BAD_DATA; - - elantech_report_absolute_v1(psmouse); - break; - - case 2: -- /* We don't know how to check parity in protocol v2 */ -+ if (etd->paritycheck && !elantech_packet_check_v2(psmouse)) -+ return PSMOUSE_BAD_DATA; -+ - elantech_report_absolute_v2(psmouse); - break; - } -@@ -795,8 +825,7 @@ int elantech_init(struct psmouse *psmouse) - etd->hw_version = 2; - /* For now show extra debug information */ - etd->debug = 1; -- /* Don't know how to do parity checking for version 2 */ -- etd->paritycheck = 0; -+ etd->paritycheck = 1; - - if (etd->fw_version >= 0x020800) - etd->reports_pressure = true; --- -1.7.6.4 - - -From 7e1abba14d70426b251ee58451ab1671af425409 Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Fri, 9 Sep 2011 10:28:19 -0700 -Subject: Input: elantech - clean up elantech_init -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Group property setting code into elantech_set_properties. - -Signed-off-by: JJ Ding -Acked-by: Daniel Kurtz -Acked-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/elantech.c | 69 ++++++++++++++++++++++----------------- - 1 files changed, 39 insertions(+), 30 deletions(-) - -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index f2e3a2b..1ab1c14 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -791,6 +791,42 @@ static int elantech_reconnect(struct psmouse *psmouse) - } - - /* -+ * determine hardware version and set some properties according to it. -+ */ -+static void elantech_set_properties(struct elantech_data *etd) -+{ -+ /* -+ * Assume every version greater than 0x020030 is new EeePC style -+ * hardware with 6 byte packets, except 0x020600 -+ */ -+ if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) -+ etd->hw_version = 1; -+ else -+ etd->hw_version = 2; -+ -+ /* -+ * Turn on packet checking by default. -+ */ -+ etd->paritycheck = 1; -+ -+ /* -+ * This firmware suffers from misreporting coordinates when -+ * a touch action starts causing the mouse cursor or scrolled page -+ * to jump. Enable a workaround. -+ */ -+ etd->jumpy_cursor = -+ (etd->fw_version == 0x020022 || etd->fw_version == 0x020600); -+ -+ if (etd->hw_version == 2) { -+ /* For now show extra debug information */ -+ etd->debug = 1; -+ -+ if (etd->fw_version >= 0x020800) -+ etd->reports_pressure = true; -+ } -+} -+ -+/* - * Initialize the touchpad and create sysfs entries - */ - int elantech_init(struct psmouse *psmouse) -@@ -816,26 +852,9 @@ int elantech_init(struct psmouse *psmouse) - } - - etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; -- -- /* -- * Assume every version greater than this is new EeePC style -- * hardware with 6 byte packets -- */ -- if (etd->fw_version >= 0x020030) { -- etd->hw_version = 2; -- /* For now show extra debug information */ -- etd->debug = 1; -- etd->paritycheck = 1; -- -- if (etd->fw_version >= 0x020800) -- etd->reports_pressure = true; -- -- } else { -- etd->hw_version = 1; -- etd->paritycheck = 1; -- } -- -- pr_info("assuming hardware version %d, firmware version %d.%d.%d\n", -+ elantech_set_properties(etd); -+ pr_info("assuming hardware version %d " -+ "(with firmware version 0x%02x%02x%02x)\n", - etd->hw_version, param[0], param[1], param[2]); - - if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, -@@ -847,16 +866,6 @@ int elantech_init(struct psmouse *psmouse) - etd->capabilities[0], etd->capabilities[1], - etd->capabilities[2]); - -- /* -- * This firmware suffers from misreporting coordinates when -- * a touch action starts causing the mouse cursor or scrolled page -- * to jump. Enable a workaround. -- */ -- if (etd->fw_version == 0x020022 || etd->fw_version == 0x020600) { -- pr_info("firmware version 2.0.34/2.6.0 detected, enabling jumpy cursor workaround\n"); -- etd->jumpy_cursor = true; -- } -- - if (elantech_set_absolute_mode(psmouse)) { - pr_err("failed to put touchpad into absolute mode.\n"); - goto init_fail; --- -1.7.6.4 - - -From 709d9ebd2853032df0599c30d5ac61c8397679f3 Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Fri, 9 Sep 2011 10:30:31 -0700 -Subject: Input: elantech - add v3 hardware support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -v3 hardware's packet format is almost identical to v2 (one/three finger touch), -except when sensing two finger touch, the hardware sends 12 bytes of data. - -Signed-off-by: JJ Ding -Acked-by: Daniel Kurtz -Acked-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - Documentation/input/elantech.txt | 117 +++++++++++++++++++-- - drivers/input/mouse/elantech.c | 208 ++++++++++++++++++++++++++++++++++---- - drivers/input/mouse/elantech.h | 12 ++ - 3 files changed, 306 insertions(+), 31 deletions(-) - -diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt -index bce9941..cee08ee 100644 ---- a/Documentation/input/elantech.txt -+++ b/Documentation/input/elantech.txt -@@ -16,15 +16,22 @@ Contents - - 1. Introduction - 2. Extra knobs -- 3. Hardware version 1 -- 3.1 Registers -- 3.2 Native relative mode 4 byte packet format -- 3.3 Native absolute mode 4 byte packet format -- 4. Hardware version 2 -+ 3. Differentiating hardware versions -+ 4. Hardware version 1 - 4.1 Registers -- 4.2 Native absolute mode 6 byte packet format -- 4.2.1 One finger touch -- 4.2.2 Two finger touch -+ 4.2 Native relative mode 4 byte packet format -+ 4.3 Native absolute mode 4 byte packet format -+ 5. Hardware version 2 -+ 5.1 Registers -+ 5.2 Native absolute mode 6 byte packet format -+ 5.2.1 Parity checking and packet re-synchronization -+ 5.2.2 One/Three finger touch -+ 5.2.3 Two finger touch -+ 6. Hardware version 3 -+ 6.1 Registers -+ 6.2 Native absolute mode 6 byte packet format -+ 6.2.1 One/Three finger touch -+ 6.2.2 Two finger touch - - - -@@ -375,7 +382,7 @@ For all the other ones, there are just a few constant bits: - - In case an error is detected, all the packets are shifted by one (and packet[0] is discarded). - --5.2.1 One/Three finger touch -+5.2.2 One/Three finger touch - ~~~~~~~~~~~~~~~~ - - byte 0: -@@ -384,7 +391,7 @@ byte 0: - n1 n0 w3 w2 . . R L - - L, R = 1 when Left, Right mouse button pressed -- n1..n0 = numbers of fingers on touchpad -+ n1..n0 = number of fingers on touchpad - - byte 1: - -@@ -432,7 +439,7 @@ byte 5: - y11..y0 = absolute y value (vertical) - - --4.2.2 Two finger touch -+5.2.3 Two finger touch - ~~~~~~~~~~~~~~~~ - - Note that the two pairs of coordinates are not exactly the coordinates of the -@@ -446,7 +453,7 @@ byte 0: - n1 n0 ay8 ax8 . . R L - - L, R = 1 when Left, Right mouse button pressed -- n1..n0 = numbers of fingers on touchpad -+ n1..n0 = number of fingers on touchpad - - byte 1: - -@@ -480,3 +487,89 @@ byte 5: - by7 by8 by5 by4 by3 by2 by1 by0 - - by8..by0 = upper-right finger absolute y value -+ -+///////////////////////////////////////////////////////////////////////////// -+ -+6. Hardware version 3 -+ ================== -+ -+6.1 Registers -+ ~~~~~~~~~ -+* reg_10 -+ -+ bit 7 6 5 4 3 2 1 0 -+ 0 0 0 0 0 0 0 A -+ -+ A: 1 = enable absolute tracking -+ -+6.2 Native absolute mode 6 byte packet format -+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+1 and 3 finger touch shares the same 6-byte packet format, except that -+3 finger touch only reports the position of the center of all three fingers. -+ -+Firmware would send 12 bytes of data for 2 finger touch. -+ -+Note on debounce: -+In case the box has unstable power supply or other electricity issues, or -+when number of finger changes, F/W would send "debounce packet" to inform -+driver that the hardware is in debounce status. -+The debouce packet has the following signature: -+ byte 0: 0xc4 -+ byte 1: 0xff -+ byte 2: 0xff -+ byte 3: 0x02 -+ byte 4: 0xff -+ byte 5: 0xff -+When we encounter this kind of packet, we just ignore it. -+ -+6.2.1 One/Three finger touch -+ ~~~~~~~~~~~~~~~~~~~~~~ -+ -+byte 0: -+ -+ bit 7 6 5 4 3 2 1 0 -+ n1 n0 w3 w2 0 1 R L -+ -+ L, R = 1 when Left, Right mouse button pressed -+ n1..n0 = number of fingers on touchpad -+ -+byte 1: -+ -+ bit 7 6 5 4 3 2 1 0 -+ p7 p6 p5 p4 x11 x10 x9 x8 -+ -+byte 2: -+ -+ bit 7 6 5 4 3 2 1 0 -+ x7 x6 x5 x4 x3 x2 x1 x0 -+ -+ x11..x0 = absolute x value (horizontal) -+ -+byte 3: -+ -+ bit 7 6 5 4 3 2 1 0 -+ 0 0 w1 w0 0 0 1 0 -+ -+ w3..w0 = width of the finger touch -+ -+byte 4: -+ -+ bit 7 6 5 4 3 2 1 0 -+ p3 p1 p2 p0 y11 y10 y9 y8 -+ -+ p7..p0 = pressure -+ -+byte 5: -+ -+ bit 7 6 5 4 3 2 1 0 -+ y7 y6 y5 y4 y3 y2 y1 y0 -+ -+ y11..y0 = absolute y value (vertical) -+ -+6.2.2 Two finger touch -+ ~~~~~~~~~~~~~~~~ -+ -+The packet format is exactly the same for two finger touch, except the hardware -+sends two 6 byte packets. The first packet contains data for the first finger, -+the second packet has data for the second finger. So for two finger touch a -+total of 12 bytes are sent. -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index 1ab1c14..9cfc70a 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -108,6 +108,16 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, - rc = -1; - } - break; -+ -+ case 3: -+ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || -+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, reg) || -+ elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) { -+ rc = -1; -+ } -+ break; - } - - if (rc) -@@ -154,6 +164,18 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, - rc = -1; - } - break; -+ -+ case 3: -+ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || -+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, reg) || -+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, val) || -+ elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { -+ rc = -1; -+ } -+ break; - } - - if (rc) -@@ -350,6 +372,84 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) - input_sync(dev); - } - -+/* -+ * Interpret complete data packets and report absolute mode input events for -+ * hardware version 3. (12 byte packets for two fingers) -+ */ -+static void elantech_report_absolute_v3(struct psmouse *psmouse, -+ int packet_type) -+{ -+ struct input_dev *dev = psmouse->dev; -+ struct elantech_data *etd = psmouse->private; -+ unsigned char *packet = psmouse->packet; -+ unsigned int fingers = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0; -+ unsigned int width = 0, pres = 0; -+ -+ /* byte 0: n1 n0 . . . . R L */ -+ fingers = (packet[0] & 0xc0) >> 6; -+ -+ switch (fingers) { -+ case 3: -+ case 1: -+ /* -+ * byte 1: . . . . x11 x10 x9 x8 -+ * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 -+ */ -+ x1 = ((packet[1] & 0x0f) << 8) | packet[2]; -+ /* -+ * byte 4: . . . . y11 y10 y9 y8 -+ * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 -+ */ -+ y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); -+ break; -+ -+ case 2: -+ if (packet_type == PACKET_V3_HEAD) { -+ /* -+ * byte 1: . . . . ax11 ax10 ax9 ax8 -+ * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 -+ */ -+ etd->prev_x = ((packet[1] & 0x0f) << 8) | packet[2]; -+ /* -+ * byte 4: . . . . ay11 ay10 ay9 ay8 -+ * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 -+ */ -+ etd->prev_y = etd->y_max - -+ (((packet[4] & 0x0f) << 8) | packet[5]); -+ /* -+ * wait for next packet -+ */ -+ return; -+ } -+ -+ /* packet_type == PACKET_V3_TAIL */ -+ x1 = etd->prev_x; -+ y1 = etd->prev_y; -+ x2 = ((packet[1] & 0x0f) << 8) | packet[2]; -+ y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); -+ break; -+ } -+ -+ pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); -+ width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); -+ -+ input_report_key(dev, BTN_TOUCH, fingers != 0); -+ if (fingers != 0) { -+ input_report_abs(dev, ABS_X, x1); -+ input_report_abs(dev, ABS_Y, y1); -+ } -+ elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); -+ input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); -+ input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); -+ input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); -+ input_report_key(dev, BTN_LEFT, packet[0] & 0x01); -+ input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); -+ input_report_abs(dev, ABS_PRESSURE, pres); -+ input_report_abs(dev, ABS_TOOL_WIDTH, width); -+ -+ input_sync(dev); -+} -+ - static int elantech_packet_check_v1(struct psmouse *psmouse) - { - struct elantech_data *etd = psmouse->private; -@@ -403,11 +503,37 @@ static int elantech_packet_check_v2(struct psmouse *psmouse) - } - - /* -+ * We check the constant bits to determine what packet type we get, -+ * so packet checking is mandatory for v3 hardware. -+ */ -+static int elantech_packet_check_v3(struct psmouse *psmouse) -+{ -+ const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff }; -+ unsigned char *packet = psmouse->packet; -+ -+ /* -+ * check debounce first, it has the same signature in byte 0 -+ * and byte 3 as PACKET_V3_HEAD. -+ */ -+ if (!memcmp(packet, debounce_packet, sizeof(debounce_packet))) -+ return PACKET_DEBOUNCE; -+ -+ if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02) -+ return PACKET_V3_HEAD; -+ -+ if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) -+ return PACKET_V3_TAIL; -+ -+ return PACKET_UNKNOWN; -+} -+ -+/* - * Process byte stream from mouse and handle complete packets - */ - static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) - { - struct elantech_data *etd = psmouse->private; -+ int packet_type; - - if (psmouse->pktcnt < psmouse->pktsize) - return PSMOUSE_GOOD_DATA; -@@ -429,6 +555,18 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) - - elantech_report_absolute_v2(psmouse); - break; -+ -+ case 3: -+ packet_type = elantech_packet_check_v3(psmouse); -+ /* ignore debounce */ -+ if (packet_type == PACKET_DEBOUNCE) -+ return PSMOUSE_FULL_PACKET; -+ -+ if (packet_type == PACKET_UNKNOWN) -+ return PSMOUSE_BAD_DATA; -+ -+ elantech_report_absolute_v3(psmouse, packet_type); -+ break; - } - - return PSMOUSE_FULL_PACKET; -@@ -463,8 +601,15 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) - elantech_write_reg(psmouse, 0x11, etd->reg_11) || - elantech_write_reg(psmouse, 0x21, etd->reg_21)) { - rc = -1; -- break; - } -+ break; -+ -+ case 3: -+ etd->reg_10 = 0x0b; -+ if (elantech_write_reg(psmouse, 0x10, etd->reg_10)) -+ rc = -1; -+ -+ break; - } - - if (rc == 0) { -@@ -498,11 +643,12 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) - return rc; - } - --static void elantech_set_range(struct psmouse *psmouse, -- unsigned int *x_min, unsigned int *y_min, -- unsigned int *x_max, unsigned int *y_max) -+static int elantech_set_range(struct psmouse *psmouse, -+ unsigned int *x_min, unsigned int *y_min, -+ unsigned int *x_max, unsigned int *y_max) - { - struct elantech_data *etd = psmouse->private; -+ unsigned char param[3]; - int i; - - switch (etd->hw_version) { -@@ -530,19 +676,30 @@ static void elantech_set_range(struct psmouse *psmouse, - *y_max = (etd->capabilities[2] - i) * 64; - } - break; -+ -+ case 3: -+ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) -+ return -1; -+ -+ *x_max = (0x0f & param[0]) << 8 | param[1]; -+ *y_max = (0xf0 & param[0]) << 4 | param[2]; -+ break; - } -+ -+ return 0; - } - - /* - * Set the appropriate event bits for the input subsystem - */ --static void elantech_set_input_params(struct psmouse *psmouse) -+static int elantech_set_input_params(struct psmouse *psmouse) - { - struct input_dev *dev = psmouse->dev; - struct elantech_data *etd = psmouse->private; - unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0; - -- elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max); -+ if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max)) -+ return -1; - - __set_bit(EV_KEY, dev->evbit); - __set_bit(EV_ABS, dev->evbit); -@@ -570,6 +727,9 @@ static void elantech_set_input_params(struct psmouse *psmouse) - - case 2: - __set_bit(BTN_TOOL_QUADTAP, dev->keybit); -+ __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); -+ /* fall through */ -+ case 3: - input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); - input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); - if (etd->reports_pressure) { -@@ -578,7 +738,6 @@ static void elantech_set_input_params(struct psmouse *psmouse) - input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, - ETP_WMAX_V2, 0, 0); - } -- __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); - input_mt_init_slots(dev, 2); - input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); - input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); -@@ -586,6 +745,8 @@ static void elantech_set_input_params(struct psmouse *psmouse) - } - - etd->y_max = y_max; -+ -+ return 0; - } - - struct elantech_attr_data { -@@ -727,7 +888,8 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) - * Report this in case there are Elantech models that use a different - * set of magic numbers - */ -- if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) { -+ if (param[0] != 0x3c || param[1] != 0x03 || -+ (param[2] != 0xc8 && param[2] != 0x00)) { - pr_debug("unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", - param[0], param[1], param[2]); - return -1; -@@ -793,16 +955,16 @@ static int elantech_reconnect(struct psmouse *psmouse) - /* - * determine hardware version and set some properties according to it. - */ --static void elantech_set_properties(struct elantech_data *etd) -+static int elantech_set_properties(struct elantech_data *etd) - { -- /* -- * Assume every version greater than 0x020030 is new EeePC style -- * hardware with 6 byte packets, except 0x020600 -- */ - if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) - etd->hw_version = 1; -- else -+ else if (etd->fw_version < 0x150600) - etd->hw_version = 2; -+ else if ((etd->fw_version & 0x0f0000) >> 16 == 5) -+ etd->hw_version = 3; -+ else -+ return -1; - - /* - * Turn on packet checking by default. -@@ -817,13 +979,15 @@ static void elantech_set_properties(struct elantech_data *etd) - etd->jumpy_cursor = - (etd->fw_version == 0x020022 || etd->fw_version == 0x020600); - -- if (etd->hw_version == 2) { -+ if (etd->hw_version > 1) { - /* For now show extra debug information */ - etd->debug = 1; - - if (etd->fw_version >= 0x020800) - etd->reports_pressure = true; - } -+ -+ return 0; - } - - /* -@@ -850,9 +1014,12 @@ int elantech_init(struct psmouse *psmouse) - pr_err("failed to query firmware version.\n"); - goto init_fail; - } -- - etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; -- elantech_set_properties(etd); -+ -+ if (elantech_set_properties(etd)) { -+ pr_err("unknown hardware version, aborting...\n"); -+ goto init_fail; -+ } - pr_info("assuming hardware version %d " - "(with firmware version 0x%02x%02x%02x)\n", - etd->hw_version, param[0], param[1], param[2]); -@@ -871,7 +1038,10 @@ int elantech_init(struct psmouse *psmouse) - goto init_fail; - } - -- elantech_set_input_params(psmouse); -+ if (elantech_set_input_params(psmouse)) { -+ pr_err("failed to query touchpad range.\n"); -+ goto init_fail; -+ } - - error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, - &elantech_attr_group); -@@ -883,7 +1053,7 @@ int elantech_init(struct psmouse *psmouse) - psmouse->protocol_handler = elantech_process_byte; - psmouse->disconnect = elantech_disconnect; - psmouse->reconnect = elantech_reconnect; -- psmouse->pktsize = etd->hw_version == 2 ? 6 : 4; -+ psmouse->pktsize = etd->hw_version > 1 ? 6 : 4; - - return 0; - -diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h -index d9e6144..236c33c 100644 ---- a/drivers/input/mouse/elantech.h -+++ b/drivers/input/mouse/elantech.h -@@ -16,6 +16,7 @@ - /* - * Command values for Synaptics style queries - */ -+#define ETP_FW_ID_QUERY 0x00 - #define ETP_FW_VERSION_QUERY 0x01 - #define ETP_CAPABILITIES_QUERY 0x02 - -@@ -24,6 +25,7 @@ - */ - #define ETP_REGISTER_READ 0x10 - #define ETP_REGISTER_WRITE 0x11 -+#define ETP_REGISTER_READWRITE 0x00 - - /* - * Hardware version 2 custom PS/2 command value -@@ -79,6 +81,14 @@ - #define ETP_WMIN_V2 0 - #define ETP_WMAX_V2 15 - -+/* -+ * v3 hardware has 2 kinds of packet types. -+ */ -+#define PACKET_UNKNOWN 0x01 -+#define PACKET_DEBOUNCE 0x02 -+#define PACKET_V3_HEAD 0x03 -+#define PACKET_V3_TAIL 0x04 -+ - struct elantech_data { - unsigned char reg_10; - unsigned char reg_11; -@@ -98,6 +108,8 @@ struct elantech_data { - unsigned int fw_version; - unsigned int single_finger_reports; - unsigned int y_max; -+ unsigned int prev_x; -+ unsigned int prev_y; - unsigned char parity[256]; - }; - --- -1.7.6.4 - - -From 5936f37c68ab27b24d6f2faf23268a9aefd3092e Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Fri, 9 Sep 2011 10:31:58 -0700 -Subject: Input: elantech - add v4 hardware support - -v4 hardware is a true multitouch capable touchpad (up to 5 fingers). -The packet format is quite complex, please see protocol document for -reference. - -Signed-off-by: JJ Ding -Signed-off-by: Dmitry Torokhov ---- - Documentation/input/elantech.txt | 170 ++++++++++++++++++++++++++ - drivers/input/mouse/elantech.c | 249 ++++++++++++++++++++++++++++++++++++-- - drivers/input/mouse/elantech.h | 29 ++++- - 3 files changed, 432 insertions(+), 16 deletions(-) - -diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt -index cee08ee..5602eb7 100644 ---- a/Documentation/input/elantech.txt -+++ b/Documentation/input/elantech.txt -@@ -32,6 +32,12 @@ Contents - 6.2 Native absolute mode 6 byte packet format - 6.2.1 One/Three finger touch - 6.2.2 Two finger touch -+ 7. Hardware version 4 -+ 7.1 Registers -+ 7.2 Native absolute mode 6 byte packet format -+ 7.2.1 Status packet -+ 7.2.2 Head packet -+ 7.2.3 Motion packet - - - -@@ -573,3 +579,167 @@ The packet format is exactly the same for two finger touch, except the hardware - sends two 6 byte packets. The first packet contains data for the first finger, - the second packet has data for the second finger. So for two finger touch a - total of 12 bytes are sent. -+ -+///////////////////////////////////////////////////////////////////////////// -+ -+7. Hardware version 4 -+ ================== -+ -+7.1 Registers -+ ~~~~~~~~~ -+* reg_07 -+ -+ bit 7 6 5 4 3 2 1 0 -+ 0 0 0 0 0 0 0 A -+ -+ A: 1 = enable absolute tracking -+ -+7.2 Native absolute mode 6 byte packet format -+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers. -+Unfortunately, due to PS/2's limited bandwidth, its packet format is rather -+complex. -+ -+Whenever the numbers or identities of the fingers changes, the hardware sends a -+status packet to indicate how many and which fingers is on touchpad, followed by -+head packets or motion packets. A head packet contains data of finger id, finger -+position (absolute x, y values), width, and pressure. A motion packet contains -+two fingers' position delta. -+ -+For example, when status packet tells there are 2 fingers on touchpad, then we -+can expect two following head packets. If the finger status doesn't change, -+the following packets would be motion packets, only sending delta of finger -+position, until we receive a status packet. -+ -+One exception is one finger touch. when a status packet tells us there is only -+one finger, the hardware would just send head packets afterwards. -+ -+7.2.1 Status packet -+ ~~~~~~~~~~~~~ -+ -+byte 0: -+ -+ bit 7 6 5 4 3 2 1 0 -+ . . . . 0 1 R L -+ -+ L, R = 1 when Left, Right mouse button pressed -+ -+byte 1: -+ -+ bit 7 6 5 4 3 2 1 0 -+ . . . ft4 ft3 ft2 ft1 ft0 -+ -+ ft4 ft3 ft2 ft1 ft0 ftn = 1 when finger n is on touchpad -+ -+byte 2: not used -+ -+byte 3: -+ -+ bit 7 6 5 4 3 2 1 0 -+ . . . 1 0 0 0 0 -+ -+ constant bits -+ -+byte 4: -+ -+ bit 7 6 5 4 3 2 1 0 -+ p . . . . . . . -+ -+ p = 1 for palm -+ -+byte 5: not used -+ -+7.2.2 Head packet -+ ~~~~~~~~~~~ -+ -+byte 0: -+ -+ bit 7 6 5 4 3 2 1 0 -+ w3 w2 w1 w0 0 1 R L -+ -+ L, R = 1 when Left, Right mouse button pressed -+ w3..w0 = finger width (spans how many trace lines) -+ -+byte 1: -+ -+ bit 7 6 5 4 3 2 1 0 -+ p7 p6 p5 p4 x11 x10 x9 x8 -+ -+byte 2: -+ -+ bit 7 6 5 4 3 2 1 0 -+ x7 x6 x5 x4 x3 x2 x1 x0 -+ -+ x11..x0 = absolute x value (horizontal) -+ -+byte 3: -+ -+ bit 7 6 5 4 3 2 1 0 -+ id2 id1 id0 1 0 0 0 1 -+ -+ id2..id0 = finger id -+ -+byte 4: -+ -+ bit 7 6 5 4 3 2 1 0 -+ p3 p1 p2 p0 y11 y10 y9 y8 -+ -+ p7..p0 = pressure -+ -+byte 5: -+ -+ bit 7 6 5 4 3 2 1 0 -+ y7 y6 y5 y4 y3 y2 y1 y0 -+ -+ y11..y0 = absolute y value (vertical) -+ -+7.2.3 Motion packet -+ ~~~~~~~~~~~~~ -+ -+byte 0: -+ -+ bit 7 6 5 4 3 2 1 0 -+ id2 id1 id0 w 0 1 R L -+ -+ L, R = 1 when Left, Right mouse button pressed -+ id2..id0 = finger id -+ w = 1 when delta overflows (> 127 or < -128), in this case -+ firmware sends us (delta x / 5) and (delta y / 5) -+ -+byte 1: -+ -+ bit 7 6 5 4 3 2 1 0 -+ x7 x6 x5 x4 x3 x2 x1 x0 -+ -+ x7..x0 = delta x (two's complement) -+ -+byte 2: -+ -+ bit 7 6 5 4 3 2 1 0 -+ y7 y6 y5 y4 y3 y2 y1 y0 -+ -+ y7..y0 = delta y (two's complement) -+ -+byte 3: -+ -+ bit 7 6 5 4 3 2 1 0 -+ id2 id1 id0 1 0 0 1 0 -+ -+ id2..id0 = finger id -+ -+byte 4: -+ -+ bit 7 6 5 4 3 2 1 0 -+ x7 x6 x5 x4 x3 x2 x1 x0 -+ -+ x7..x0 = delta x (two's complement) -+ -+byte 5: -+ -+ bit 7 6 5 4 3 2 1 0 -+ y7 y6 y5 y4 y3 y2 y1 y0 -+ -+ y7..y0 = delta y (two's complement) -+ -+ byte 0 ~ 2 for one finger -+ byte 3 ~ 5 for another -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index 9cfc70a..b8733b3 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -84,7 +84,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, - unsigned char param[3]; - int rc = 0; - -- if (reg < 0x10 || reg > 0x26) -+ if (reg < 0x07 || reg > 0x26) - return -1; - - if (reg > 0x11 && reg < 0x20) -@@ -109,7 +109,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, - } - break; - -- case 3: -+ case 3 ... 4: - if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || - elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || - elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -@@ -122,8 +122,10 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, - - if (rc) - pr_err("failed to read register 0x%02x.\n", reg); -- else -+ else if (etd->hw_version != 4) - *val = param[0]; -+ else -+ *val = param[1]; - - return rc; - } -@@ -137,7 +139,7 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, - struct elantech_data *etd = psmouse->private; - int rc = 0; - -- if (reg < 0x10 || reg > 0x26) -+ if (reg < 0x07 || reg > 0x26) - return -1; - - if (reg > 0x11 && reg < 0x20) -@@ -176,6 +178,20 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, - rc = -1; - } - break; -+ -+ case 4: -+ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || -+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, reg) || -+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || -+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || -+ elantech_ps2_command(psmouse, NULL, val) || -+ elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { -+ rc = -1; -+ } -+ break; - } - - if (rc) -@@ -409,12 +425,12 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, - * byte 1: . . . . ax11 ax10 ax9 ax8 - * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 - */ -- etd->prev_x = ((packet[1] & 0x0f) << 8) | packet[2]; -+ etd->mt[0].x = ((packet[1] & 0x0f) << 8) | packet[2]; - /* - * byte 4: . . . . ay11 ay10 ay9 ay8 - * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 - */ -- etd->prev_y = etd->y_max - -+ etd->mt[0].y = etd->y_max - - (((packet[4] & 0x0f) << 8) | packet[5]); - /* - * wait for next packet -@@ -423,8 +439,8 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, - } - - /* packet_type == PACKET_V3_TAIL */ -- x1 = etd->prev_x; -- y1 = etd->prev_y; -+ x1 = etd->mt[0].x; -+ y1 = etd->mt[0].y; - x2 = ((packet[1] & 0x0f) << 8) | packet[2]; - y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); - break; -@@ -450,6 +466,129 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, - input_sync(dev); - } - -+static void elantech_input_sync_v4(struct psmouse *psmouse) -+{ -+ struct input_dev *dev = psmouse->dev; -+ unsigned char *packet = psmouse->packet; -+ -+ input_report_key(dev, BTN_LEFT, packet[0] & 0x01); -+ input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); -+ input_mt_report_pointer_emulation(dev, true); -+ input_sync(dev); -+} -+ -+static void process_packet_status_v4(struct psmouse *psmouse) -+{ -+ struct input_dev *dev = psmouse->dev; -+ unsigned char *packet = psmouse->packet; -+ unsigned fingers; -+ int i; -+ -+ /* notify finger state change */ -+ fingers = packet[1] & 0x1f; -+ for (i = 0; i < ETP_MAX_FINGERS; i++) { -+ if ((fingers & (1 << i)) == 0) { -+ input_mt_slot(dev, i); -+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, false); -+ } -+ } -+ -+ elantech_input_sync_v4(psmouse); -+} -+ -+static void process_packet_head_v4(struct psmouse *psmouse) -+{ -+ struct input_dev *dev = psmouse->dev; -+ struct elantech_data *etd = psmouse->private; -+ unsigned char *packet = psmouse->packet; -+ int id = ((packet[3] & 0xe0) >> 5) - 1; -+ int pres, traces; -+ -+ if (id < 0) -+ return; -+ -+ etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2]; -+ etd->mt[id].y = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); -+ pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); -+ traces = (packet[0] & 0xf0) >> 4; -+ -+ input_mt_slot(dev, id); -+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); -+ -+ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); -+ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); -+ input_report_abs(dev, ABS_MT_PRESSURE, pres); -+ input_report_abs(dev, ABS_MT_TOUCH_MAJOR, traces * etd->width); -+ /* report this for backwards compatibility */ -+ input_report_abs(dev, ABS_TOOL_WIDTH, traces); -+ -+ elantech_input_sync_v4(psmouse); -+} -+ -+static void process_packet_motion_v4(struct psmouse *psmouse) -+{ -+ struct input_dev *dev = psmouse->dev; -+ struct elantech_data *etd = psmouse->private; -+ unsigned char *packet = psmouse->packet; -+ int weight, delta_x1 = 0, delta_y1 = 0, delta_x2 = 0, delta_y2 = 0; -+ int id, sid; -+ -+ id = ((packet[0] & 0xe0) >> 5) - 1; -+ if (id < 0) -+ return; -+ -+ sid = ((packet[3] & 0xe0) >> 5) - 1; -+ weight = (packet[0] & 0x10) ? ETP_WEIGHT_VALUE : 1; -+ /* -+ * Motion packets give us the delta of x, y values of specific fingers, -+ * but in two's complement. Let the compiler do the conversion for us. -+ * Also _enlarge_ the numbers to int, in case of overflow. -+ */ -+ delta_x1 = (signed char)packet[1]; -+ delta_y1 = (signed char)packet[2]; -+ delta_x2 = (signed char)packet[4]; -+ delta_y2 = (signed char)packet[5]; -+ -+ etd->mt[id].x += delta_x1 * weight; -+ etd->mt[id].y -= delta_y1 * weight; -+ input_mt_slot(dev, id); -+ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); -+ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); -+ -+ if (sid >= 0) { -+ etd->mt[sid].x += delta_x2 * weight; -+ etd->mt[sid].y -= delta_y2 * weight; -+ input_mt_slot(dev, sid); -+ input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[sid].x); -+ input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[sid].y); -+ } -+ -+ elantech_input_sync_v4(psmouse); -+} -+ -+static void elantech_report_absolute_v4(struct psmouse *psmouse, -+ int packet_type) -+{ -+ switch (packet_type) { -+ case PACKET_V4_STATUS: -+ process_packet_status_v4(psmouse); -+ break; -+ -+ case PACKET_V4_HEAD: -+ process_packet_head_v4(psmouse); -+ break; -+ -+ case PACKET_V4_MOTION: -+ process_packet_motion_v4(psmouse); -+ break; -+ -+ case PACKET_UNKNOWN: -+ default: -+ /* impossible to get here */ -+ break; -+ } -+} -+ - static int elantech_packet_check_v1(struct psmouse *psmouse) - { - struct elantech_data *etd = psmouse->private; -@@ -504,7 +643,7 @@ static int elantech_packet_check_v2(struct psmouse *psmouse) - - /* - * We check the constant bits to determine what packet type we get, -- * so packet checking is mandatory for v3 hardware. -+ * so packet checking is mandatory for v3 and later hardware. - */ - static int elantech_packet_check_v3(struct psmouse *psmouse) - { -@@ -527,6 +666,25 @@ static int elantech_packet_check_v3(struct psmouse *psmouse) - return PACKET_UNKNOWN; - } - -+static int elantech_packet_check_v4(struct psmouse *psmouse) -+{ -+ unsigned char *packet = psmouse->packet; -+ -+ if ((packet[0] & 0x0c) == 0x04 && -+ (packet[3] & 0x1f) == 0x11) -+ return PACKET_V4_HEAD; -+ -+ if ((packet[0] & 0x0c) == 0x04 && -+ (packet[3] & 0x1f) == 0x12) -+ return PACKET_V4_MOTION; -+ -+ if ((packet[0] & 0x0c) == 0x04 && -+ (packet[3] & 0x1f) == 0x10) -+ return PACKET_V4_STATUS; -+ -+ return PACKET_UNKNOWN; -+} -+ - /* - * Process byte stream from mouse and handle complete packets - */ -@@ -567,6 +725,14 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) - - elantech_report_absolute_v3(psmouse, packet_type); - break; -+ -+ case 4: -+ packet_type = elantech_packet_check_v4(psmouse); -+ if (packet_type == PACKET_UNKNOWN) -+ return PSMOUSE_BAD_DATA; -+ -+ elantech_report_absolute_v4(psmouse, packet_type); -+ break; - } - - return PSMOUSE_FULL_PACKET; -@@ -610,6 +776,13 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) - rc = -1; - - break; -+ -+ case 4: -+ etd->reg_07 = 0x01; -+ if (elantech_write_reg(psmouse, 0x07, etd->reg_07)) -+ rc = -1; -+ -+ goto skip_readback_reg_10; /* v4 has no reg 0x10 to read */ - } - - if (rc == 0) { -@@ -637,6 +810,7 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) - } - } - -+ skip_readback_reg_10: - if (rc) - pr_err("failed to initialise registers.\n"); - -@@ -645,10 +819,12 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) - - static int elantech_set_range(struct psmouse *psmouse, - unsigned int *x_min, unsigned int *y_min, -- unsigned int *x_max, unsigned int *y_max) -+ unsigned int *x_max, unsigned int *y_max, -+ unsigned int *width) - { - struct elantech_data *etd = psmouse->private; - unsigned char param[3]; -+ unsigned char traces; - int i; - - switch (etd->hw_version) { -@@ -684,6 +860,19 @@ static int elantech_set_range(struct psmouse *psmouse, - *x_max = (0x0f & param[0]) << 8 | param[1]; - *y_max = (0xf0 & param[0]) << 4 | param[2]; - break; -+ -+ case 4: -+ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) -+ return -1; -+ -+ *x_max = (0x0f & param[0]) << 8 | param[1]; -+ *y_max = (0xf0 & param[0]) << 4 | param[2]; -+ traces = etd->capabilities[1]; -+ if ((traces < 2) || (traces > *x_max)) -+ return -1; -+ -+ *width = *x_max / (traces - 1); -+ break; - } - - return 0; -@@ -696,9 +885,9 @@ static int elantech_set_input_params(struct psmouse *psmouse) - { - struct input_dev *dev = psmouse->dev; - struct elantech_data *etd = psmouse->private; -- unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0; -+ unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0; - -- if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max)) -+ if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width)) - return -1; - - __set_bit(EV_KEY, dev->evbit); -@@ -742,9 +931,37 @@ static int elantech_set_input_params(struct psmouse *psmouse) - input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); - input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); - break; -+ -+ case 4: -+ __set_bit(BTN_TOOL_QUADTAP, dev->keybit); -+ /* For X to recognize me as touchpad. */ -+ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); -+ input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); -+ /* -+ * range of pressure and width is the same as v2, -+ * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility. -+ */ -+ input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, -+ ETP_PMAX_V2, 0, 0); -+ input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, -+ ETP_WMAX_V2, 0, 0); -+ /* Multitouch capable pad, up to 5 fingers. */ -+ input_mt_init_slots(dev, ETP_MAX_FINGERS); -+ input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); -+ input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); -+ input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2, -+ ETP_PMAX_V2, 0, 0); -+ /* -+ * The firmware reports how many trace lines the finger spans, -+ * convert to surface unit as Protocol-B requires. -+ */ -+ input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0, -+ ETP_WMAX_V2 * width, 0, 0); -+ break; - } - - etd->y_max = y_max; -+ etd->width = width; - - return 0; - } -@@ -816,6 +1033,7 @@ static ssize_t elantech_set_int_attr(struct psmouse *psmouse, - elantech_show_int_attr, \ - elantech_set_int_attr) - -+ELANTECH_INT_ATTR(reg_07, 0x07); - ELANTECH_INT_ATTR(reg_10, 0x10); - ELANTECH_INT_ATTR(reg_11, 0x11); - ELANTECH_INT_ATTR(reg_20, 0x20); -@@ -829,6 +1047,7 @@ ELANTECH_INT_ATTR(debug, 0); - ELANTECH_INT_ATTR(paritycheck, 0); - - static struct attribute *elantech_attrs[] = { -+ &psmouse_attr_reg_07.dattr.attr, - &psmouse_attr_reg_10.dattr.attr, - &psmouse_attr_reg_11.dattr.attr, - &psmouse_attr_reg_20.dattr.attr, -@@ -957,12 +1176,16 @@ static int elantech_reconnect(struct psmouse *psmouse) - */ - static int elantech_set_properties(struct elantech_data *etd) - { -+ int ver = (etd->fw_version & 0x0f0000) >> 16; -+ - if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) - etd->hw_version = 1; - else if (etd->fw_version < 0x150600) - etd->hw_version = 2; -- else if ((etd->fw_version & 0x0f0000) >> 16 == 5) -+ else if (ver == 5) - etd->hw_version = 3; -+ else if (ver == 6) -+ etd->hw_version = 4; - else - return -1; - -diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h -index 236c33c..7ecaef0 100644 ---- a/drivers/input/mouse/elantech.h -+++ b/drivers/input/mouse/elantech.h -@@ -82,14 +82,37 @@ - #define ETP_WMAX_V2 15 - - /* -- * v3 hardware has 2 kinds of packet types. -+ * v3 hardware has 2 kinds of packet types, -+ * v4 hardware has 3. - */ - #define PACKET_UNKNOWN 0x01 - #define PACKET_DEBOUNCE 0x02 - #define PACKET_V3_HEAD 0x03 - #define PACKET_V3_TAIL 0x04 -+#define PACKET_V4_HEAD 0x05 -+#define PACKET_V4_MOTION 0x06 -+#define PACKET_V4_STATUS 0x07 -+ -+/* -+ * track up to 5 fingers for v4 hardware -+ */ -+#define ETP_MAX_FINGERS 5 -+ -+/* -+ * weight value for v4 hardware -+ */ -+#define ETP_WEIGHT_VALUE 5 -+ -+/* -+ * The base position for one finger, v4 hardware -+ */ -+struct finger_pos { -+ unsigned int x; -+ unsigned int y; -+}; - - struct elantech_data { -+ unsigned char reg_07; - unsigned char reg_10; - unsigned char reg_11; - unsigned char reg_20; -@@ -108,8 +131,8 @@ struct elantech_data { - unsigned int fw_version; - unsigned int single_finger_reports; - unsigned int y_max; -- unsigned int prev_x; -- unsigned int prev_y; -+ unsigned int width; -+ struct finger_pos mt[ETP_MAX_FINGERS]; - unsigned char parity[256]; - }; - --- -1.7.6.4 - - -From 3c09085f371a68f09147abb59b35db928fe3950f Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Tue, 20 Sep 2011 22:42:51 -0700 -Subject: Input: elantech - better support all those v2 variants -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -V2 hardware has many variants. This patch adddresses two issues: - - - some model also has debounce packets, but with a different signature - than v3. Now we just check debounce for all v2 hardware. - - - due to different scanning methods the hardware uses, x and y ranges have - to be calculated differently. And for some specific versions, we can just - see them as custom-made, so set {x, y} the same values as Windows driver - does. - -Signed-off-by: JJ Ding -Tested-by: Richard Schütz -Reviewed-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/elantech.c | 46 +++++++++++++++++++++++++++++++++++---- - drivers/input/mouse/elantech.h | 1 + - 2 files changed, 42 insertions(+), 5 deletions(-) - -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index b8733b3..c2d91eb 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -613,6 +613,18 @@ static int elantech_packet_check_v1(struct psmouse *psmouse) - etd->parity[packet[3]] == p3; - } - -+static int elantech_debounce_check_v2(struct psmouse *psmouse) -+{ -+ /* -+ * When we encounter packet that matches this exactly, it means the -+ * hardware is in debounce status. Just ignore the whole packet. -+ */ -+ const u8 debounce_packet[] = { 0x84, 0xff, 0xff, 0x02, 0xff, 0xff }; -+ unsigned char *packet = psmouse->packet; -+ -+ return !memcmp(packet, debounce_packet, sizeof(debounce_packet)); -+} -+ - static int elantech_packet_check_v2(struct psmouse *psmouse) - { - struct elantech_data *etd = psmouse->private; -@@ -708,6 +720,10 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) - break; - - case 2: -+ /* ignore debounce */ -+ if (elantech_debounce_check_v2(psmouse)) -+ return PSMOUSE_FULL_PACKET; -+ - if (etd->paritycheck && !elantech_packet_check_v2(psmouse)) - return PSMOUSE_BAD_DATA; - -@@ -825,7 +841,6 @@ static int elantech_set_range(struct psmouse *psmouse, - struct elantech_data *etd = psmouse->private; - unsigned char param[3]; - unsigned char traces; -- int i; - - switch (etd->hw_version) { - case 1: -@@ -844,12 +859,33 @@ static int elantech_set_range(struct psmouse *psmouse, - *x_max = ETP_XMAX_V2; - *y_max = ETP_YMAX_V2; - } else { -+ int i; -+ int fixed_dpi; -+ - i = (etd->fw_version > 0x020800 && - etd->fw_version < 0x020900) ? 1 : 2; -- *x_min = 0; -- *y_min = 0; -- *x_max = (etd->capabilities[1] - i) * 64; -- *y_max = (etd->capabilities[2] - i) * 64; -+ -+ if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) -+ return -1; -+ -+ fixed_dpi = param[1] & 0x10; -+ -+ if (((etd->fw_version >> 16) == 0x14) && fixed_dpi) { -+ if (synaptics_send_cmd(psmouse, ETP_SAMPLE_QUERY, param)) -+ return -1; -+ -+ *x_max = (etd->capabilities[1] - i) * param[1] / 2; -+ *y_max = (etd->capabilities[2] - i) * param[2] / 2; -+ } else if (etd->fw_version == 0x040216) { -+ *x_max = 819; -+ *y_max = 405; -+ } else if (etd->fw_version == 0x040219 || etd->fw_version == 0x040215) { -+ *x_max = 900; -+ *y_max = 500; -+ } else { -+ *x_max = (etd->capabilities[1] - i) * 64; -+ *y_max = (etd->capabilities[2] - i) * 64; -+ } - } - break; - -diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h -index 7ecaef0..9e5f1aa 100644 ---- a/drivers/input/mouse/elantech.h -+++ b/drivers/input/mouse/elantech.h -@@ -19,6 +19,7 @@ - #define ETP_FW_ID_QUERY 0x00 - #define ETP_FW_VERSION_QUERY 0x01 - #define ETP_CAPABILITIES_QUERY 0x02 -+#define ETP_SAMPLE_QUERY 0x03 - - /* - * Command values for register reading or writing --- -1.7.6.4 - - -From 6c0ec284648f0346e96b0079999cb7af055f58ab Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Tue, 20 Sep 2011 22:42:51 -0700 -Subject: Input: elantech - remove module parameter force_elantech -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This essentially reverts commit f81bc788ff91d4efd4baf88b2c29713838caa8e5. - -With recent work on elantech driver, I believe we now have complete support -for all elantech touchpads. So remove this hack. - -Signed-off-by: JJ Ding -Reviewed-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/elantech.c | 12 ++---------- - 1 files changed, 2 insertions(+), 10 deletions(-) - -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index c2d91eb..25290b3 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -28,10 +28,6 @@ - printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \ - } while (0) - --static bool force_elantech; --module_param_named(force_elantech, force_elantech, bool, 0644); --MODULE_PARM_DESC(force_elantech, "Force the Elantech PS/2 protocol extension to be used, 1 = enabled, 0 = disabled (default)."); -- - /* - * Send a Synaptics style sliced query command - */ -@@ -1164,12 +1160,8 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) - param[0], param[1], param[2]); - - if (!elantech_is_signature_valid(param)) { -- if (!force_elantech) { -- pr_debug("Probably not a real Elantech touchpad. Aborting.\n"); -- return -1; -- } -- -- pr_debug("Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n"); -+ pr_debug("Probably not a real Elantech touchpad. Aborting.\n"); -+ return -1; - } - - if (set_properties) { --- -1.7.6.4 - -From 3940d6185a982a970ff562e085caccbdd62f40bb Mon Sep 17 00:00:00 2001 -From: JJ Ding -Date: Tue, 8 Nov 2011 22:13:14 -0800 -Subject: [PATCH] Input: elantech - adjust hw_version detection logic -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This patch fixes some v3 hardware (fw_version: 0x150500) wrongly detected -as v2 hardware. - -Reported-by: Marc Dietrich -Signed-off-by: JJ Ding -Tested-By: Marc Dietrich -Acked-by: Éric Piel -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/elantech.c | 26 ++++++++++++++++++-------- - 1 files changed, 18 insertions(+), 8 deletions(-) - -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index 09b93b1..e2a9867 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -1210,18 +1210,28 @@ static int elantech_reconnect(struct psmouse *psmouse) - */ - static int elantech_set_properties(struct elantech_data *etd) - { -+ /* This represents the version of IC body. */ - int ver = (etd->fw_version & 0x0f0000) >> 16; - -+ /* Early version of Elan touchpads doesn't obey the rule. */ - if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) - etd->hw_version = 1; -- else if (etd->fw_version < 0x150600) -- etd->hw_version = 2; -- else if (ver == 5) -- etd->hw_version = 3; -- else if (ver == 6) -- etd->hw_version = 4; -- else -- return -1; -+ else { -+ switch (ver) { -+ case 2: -+ case 4: -+ etd->hw_version = 2; -+ break; -+ case 5: -+ etd->hw_version = 3; -+ break; -+ case 6: -+ etd->hw_version = 4; -+ break; -+ default: -+ return -1; -+ } -+ } - - /* - * Turn on packet checking by default. --- -1.7.7.3 - diff --git a/epoll-limit-paths.patch b/epoll-limit-paths.patch index 440db27b9..4ed306af4 100644 --- a/epoll-limit-paths.patch +++ b/epoll-limit-paths.patch @@ -1,4 +1,4 @@ -From 6a4ca79652219cf22da800d990e5b46feaea1ad9 Mon Sep 17 00:00:00 2001 +From 0a6cc45426fe3baaf231efd7efe4300fd879efc8 Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Mon, 24 Oct 2011 14:59:02 +1100 Subject: [PATCH] epoll: limit paths @@ -91,7 +91,7 @@ Signed-off-by: Andrew Morton 3 files changed, 203 insertions(+), 25 deletions(-) diff --git a/fs/eventpoll.c b/fs/eventpoll.c -index 4a53743..414ac74 100644 +index b84fad9..414ac74 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -197,6 +197,12 @@ struct eventpoll { @@ -137,7 +137,7 @@ index 4a53743..414ac74 100644 .llseek = noop_llseek, }; --/* Fast test to see if the file is an evenpoll file */ +-/* Fast test to see if the file is an eventpoll file */ -static inline int is_file_epoll(struct file *f) -{ - return f->f_op == &eventpoll_fops; @@ -449,7 +449,7 @@ index f362733..657ab55 100644 diff --git a/include/linux/fs.h b/include/linux/fs.h -index 277f497..93778e0 100644 +index ba98668..d393a68 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -985,6 +985,7 @@ struct file { diff --git a/hvcs_pi_buf_alloc.patch b/hvcs_pi_buf_alloc.patch deleted file mode 100644 index ecabe49b1..000000000 --- a/hvcs_pi_buf_alloc.patch +++ /dev/null @@ -1,43 +0,0 @@ - -The Power platform requires the partner info buffer to be page aligned -otherwise it will fail the partner info hcall with H_PARAMETER. Switch -from using kmalloc to allocate this buffer to __get_free_page to ensure -page alignment. - -Signed-off-by: Brian King ---- - - drivers/tty/hvc/hvcs.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff -puN drivers/tty/hvc/hvcs.c~hvcs_pi_buf_alloc drivers/tty/hvc/hvcs.c ---- linux-2.6/drivers/tty/hvc/hvcs.c~hvcs_pi_buf_alloc 2011-09-09 16:00:25.000000000 -0500 -+++ linux-2.6-bjking1/drivers/tty/hvc/hvcs.c 2011-09-09 16:07:08.000000000 -0500 -@@ -1532,7 +1532,7 @@ static int __devinit hvcs_initialize(voi - goto register_fail; - } - -- hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL); -+ hvcs_pi_buff = (unsigned long *) __get_free_page(GFP_KERNEL); - if (!hvcs_pi_buff) { - rc = -ENOMEM; - goto buff_alloc_fail; -@@ -1548,7 +1548,7 @@ static int __devinit hvcs_initialize(voi - return 0; - - kthread_fail: -- kfree(hvcs_pi_buff); -+ free_page((unsigned long)hvcs_pi_buff); - buff_alloc_fail: - tty_unregister_driver(hvcs_tty_driver); - register_fail: -@@ -1597,7 +1597,7 @@ static void __exit hvcs_module_exit(void - kthread_stop(hvcs_task); - - spin_lock(&hvcs_pi_lock); -- kfree(hvcs_pi_buff); -+ free_page((unsigned long)hvcs_pi_buff); - hvcs_pi_buff = NULL; - spin_unlock(&hvcs_pi_lock); - -_ diff --git a/kernel.spec b/kernel.spec index 4c328ea89..1d03eda7a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,19 +54,19 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching # on top of -- for example, 2.6.22-rc7-git1 starts with a 2.6.21 base, # which yields a base_sublevel of 21. -%define base_sublevel 1 +%define base_sublevel 2 ## If this is a released kernel ## %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 10 +%define stable_update 1 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -215,7 +215,7 @@ Summary: The Linux kernel # # (Uncomment the '#' and both spaces below to disable with_backports.) # -# % define with_backports 0 +%define with_backports 0 ####################################################################### %define make_target bzImage @@ -410,13 +410,6 @@ Summary: The Linux kernel %define kernel_image_elf 1 %endif -%ifarch ia64 -%define all_arch_configs kernel-%{version}-ia64*.config -%define image_install_path boot/efi/EFI/redhat -%define make_target compressed -%define kernel_image vmlinux.gz -%endif - %ifarch alpha alphaev56 %define all_arch_configs kernel-%{version}-alpha*.config %define image_install_path boot @@ -555,7 +548,7 @@ Version: %{rpmversion} Release: %{pkg_release} # DO NOT CHANGE THE 'ExclusiveArch' LINE TO TEMPORARILY EXCLUDE AN ARCHITECTURE BUILD. # SET %%nobuildarches (ABOVE) INSTEAD -ExclusiveArch: noarch %{all_x86} x86_64 ppc ppc64 ia64 %{sparc} s390 s390x alpha alphaev56 %{arm} +ExclusiveArch: noarch %{all_x86} x86_64 ppc ppc64 %{sparc} s390 s390x alpha alphaev56 %{arm} ExclusiveOS: Linux %kernel_reqprovconf @@ -564,7 +557,7 @@ ExclusiveOS: Linux # List the packages used during the kernel build # BuildRequires: module-init-tools, patch >= 2.5.4, bash >= 2.03, sh-utils, tar -BuildRequires: bzip2, findutils, gzip, m4, perl, make >= 3.78, diffutils, gawk +BuildRequires: bzip2, xz, findutils, gzip, m4, perl, make >= 3.78, diffutils, gawk BuildRequires: gcc >= 3.4.2, binutils >= 2.12, redhat-rpm-config BuildRequires: net-tools BuildRequires: xmlto, asciidoc @@ -589,7 +582,7 @@ BuildRequires: rpm-build >= 4.4.2.1-4 %define debuginfo_args --strict-build-id %endif -Source0: ftp://ftp.kernel.org/pub/linux/kernel/v3.0/linux-%{kversion}.tar.bz2 +Source0: ftp://ftp.kernel.org/pub/linux/kernel/v3.0/linux-%{kversion}.tar.xz Source1: compat-wireless-%{cwversion}.tar.bz2 Source11: genkey @@ -613,8 +606,6 @@ Source51: config-powerpc32-generic Source52: config-powerpc32-smp Source53: config-powerpc64 -Source60: config-ia64-generic - Source70: config-s390x Source90: config-sparc64-generic @@ -641,11 +632,11 @@ Source2001: cpupower.config # For a stable release kernel %if 0%{?stable_update} %if 0%{?stable_base} -%define stable_patch_00 patch-3.%{base_sublevel}.%{stable_base}.bz2 +%define stable_patch_00 patch-3.%{base_sublevel}.%{stable_base}.xz Patch00: %{stable_patch_00} %endif %if 0%{?stable_rc} -%define stable_patch_01 patch-3.%{base_sublevel}.%{stable_update}-rc%{stable_rc}.bz2 +%define stable_patch_01 patch-3.%{base_sublevel}.%{stable_update}-rc%{stable_rc}.xz Patch01: %{stable_patch_01} %endif @@ -654,9 +645,9 @@ Patch01: %{stable_patch_01} # near the top of this spec file. %else %if 0%{?rcrev} -Patch00: patch-3.%{upstream_sublevel}-rc%{rcrev}.bz2 +Patch00: patch-3.%{upstream_sublevel}-rc%{rcrev}.xz %if 0%{?gitrev} -Patch01: patch-3.%{upstream_sublevel}-rc%{rcrev}-git%{gitrev}.bz2 +Patch01: patch-3.%{upstream_sublevel}-rc%{rcrev}-git%{gitrev}.xz %endif %else # pre-{base_sublevel+1}-rc1 case @@ -691,8 +682,6 @@ Patch100: taint-vbox.patch Patch160: linux-2.6-32bit-mmap-exec-randomization.patch Patch161: linux-2.6-i386-nx-emulation.patch -Patch202: linux-2.6-debug-taint-vm.patch - Patch383: linux-2.6-defaults-aspm.patch Patch390: linux-2.6-defaults-acpi-video.patch @@ -717,10 +706,6 @@ Patch700: linux-2.6-e1000-ich9-montevina.patch Patch800: linux-2.6-crash-driver.patch -# Platform -Patch900: samsung-laptop-brightness-fixes-3.2.patch -Patch901: asus-laptop-3.2-backport.patch - # crypto/ # virt + ksm patches @@ -729,17 +714,10 @@ Patch1500: fix_xen_guest_on_old_EC2.patch # DRM #atch1700: drm-edid-try-harder-to-fix-up-broken-headers.patch -# nouveau + drm fixes -Patch1810: drm-nouveau-updates.patch -Patch1811: drm-nouveau-gf108.patch # intel drm is all merged upstream Patch1824: drm-intel-next.patch # hush the i915 fbc noise Patch1826: drm-i915-fbc-stfu.patch -# rhbz#729882, https://bugs.freedesktop.org/attachment.cgi?id=49069 -Patch1827: drm-i915-sdvo-lvds-is-digital.patch - -Patch1850: drm-lower-severity-radeon-lockup.diff Patch1900: linux-2.6-intel-iommu-igfx.patch @@ -753,10 +731,6 @@ Patch2900: linux-2.6-v4l-dvb-update.patch Patch2901: linux-2.6-v4l-dvb-experimental.patch Patch2902: linux-2.6-v4l-dvb-uvcvideo-update.patch -Patch2905: media-dib0700-correct-error-message.patch - -Patch3000: rcutree-avoid-false-quiescent-states.patch - # fs fixes #rhbz 753346 @@ -765,53 +739,31 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # NFSv4 # patches headed upstream -Patch12010: add-appleir-usb-driver.patch Patch12016: disable-i8042-check-on-apple-mac.patch -Patch12021: udlfb-bind-framebuffer-to-interface.patch - -Patch12025: rcu-avoid-just-onlined-cpu-resched.patch Patch12026: block-stray-block-put-after-teardown.patch Patch12030: epoll-limit-paths.patch -Patch12031: HID-wacom-Set-input-bits-before-registration.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13002: revert-efi-rtclock.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch -Patch13009: hvcs_pi_buf_alloc.patch - Patch20000: utrace.patch # Flattened devicetree support Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch -#rhbz #735946 -Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch Patch21022: mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch -#rhbz 748691 -Patch21030: be2net-non-member-vlan-pkts-not-received-in-promisco.patch -Patch21031: benet-remove-bogus-unlikely-on-vlan-check.patch - -Patch21040: x86-code-dump-fix-truncation.patch - -#rhbz 728607 -Patch21060: elantech.patch - #rhbz752176 Patch21080: sysfs-msi-irq-per-device.patch -#backport brcm80211 from 3.2-rc1 -Patch21090: brcm80211.patch -Patch21091: bcma-brcmsmac-compat.patch # rhbz 754907 -Patch21100: cciss-fix-irqf-shared.patch Patch21101: hpsa-add-irqf-shared.patch #rhbz 731365 @@ -821,27 +773,15 @@ Patch21225: pci-Rework-ASPM-disable-code.patch Patch21226: pci-crs-blacklist.patch -#rhbz #757839 -Patch21230: net-sky2-88e8059-fix-link-speed.patch - #rhbz 717735 Patch21045: nfs-client-freezer.patch #rhbz 590880 Patch21046: alps.patch -#rhbz 741117 -Patch21048: b44-Use-dev_kfree_skb_irq-in-b44_tx.patch - #rhbz 746097 Patch21049: tpm_tis-delay-after-aborting-cmd.patch -#rhbz 771006 -Patch21050: thp-reduce-khugepaged-freezing-latency.patch - -#rhbz 770233 -Patch21065: Bluetooth-Add-support-for-BCM20702A0.patch - Patch21070: ext4-Support-check-none-nocheck-mount-options.patch Patch21071: ext4-Fix-error-handling-on-inode-bitmap-corruption.patch @@ -865,10 +805,6 @@ Patch22100: msi-irq-sysfs-warning.patch #rhbz 728740 Patch21076: rtl8192cu-Fix-WARNING-on-suspend-resume.patch -Patch21077: 01-block-add-and-use-scsi_blk_cmd_ioctl.patch -Patch21078: 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch -Patch21079: 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch - #rhbz 782686 Patch21082: procfs-parse-mount-options.patch Patch21083: procfs-add-hidepid-and-gid-mount-options.patch @@ -877,9 +813,6 @@ Patch21084: proc-fix-null-pointer-deref-in-proc_pid_permission.patch #rhbz 782681 Patch21085: proc-clean-up-and-fix-proc-pid-mem-handling.patch -#rhbz 782687 -Patch21086: loop-prevent-information-leak-after-failed-read.patch - %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1172,7 +1105,8 @@ ApplyPatch() %endif case "$patch" in *.bz2) bunzip2 < "$RPM_SOURCE_DIR/$patch" | $patch_command ${1+"$@"} ;; - *.gz) gunzip < "$RPM_SOURCE_DIR/$patch" | $patch_command ${1+"$@"} ;; + *.gz) gunzip < "$RPM_SOURCE_DIR/$patch" | $patch_command ${1+"$@"} ;; + *.xz) unxz < "$RPM_SOURCE_DIR/$patch" | $patch_command ${1+"$@"} ;; *) $patch_command ${1+"$@"} < "$RPM_SOURCE_DIR/$patch" ;; esac } @@ -1428,9 +1362,6 @@ ApplyPatch linux-2.6-acpi-debug-infinite-loop.patch ApplyPatch acpi-ensure-thermal-limits-match-cpu-freq.patch ApplyPatch acpi-sony-nonvs-blacklist.patch -# Various low-impact patches to aid debugging. -ApplyPatch linux-2.6-debug-taint-vm.patch - # # PCI # @@ -1484,16 +1415,9 @@ ApplyPatch fix_xen_guest_on_old_EC2.patch # DRM core #ApplyPatch drm-edid-try-harder-to-fix-up-broken-headers.patch -# Nouveau DRM -ApplyOptionalPatch drm-nouveau-updates.patch -ApplyPatch drm-nouveau-gf108.patch - # Intel DRM ApplyOptionalPatch drm-intel-next.patch ApplyPatch drm-i915-fbc-stfu.patch -ApplyPatch drm-i915-sdvo-lvds-is-digital.patch - -ApplyPatch drm-lower-severity-radeon-lockup.diff ApplyPatch linux-2.6-intel-iommu-igfx.patch @@ -1507,22 +1431,12 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-fixes.patch ApplyOptionalPatch linux-2.6-v4l-dvb-update.patch ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch -# Platform fixes not sent for -stable -ApplyPatch samsung-laptop-brightness-fixes-3.2.patch -ApplyPatch asus-laptop-3.2-backport.patch - # Patches headed upstream -ApplyPatch rcutree-avoid-false-quiescent-states.patch ApplyPatch disable-i8042-check-on-apple-mac.patch -ApplyPatch add-appleir-usb-driver.patch - -ApplyPatch udlfb-bind-framebuffer-to-interface.patch ApplyPatch epoll-limit-paths.patch -ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch ApplyPatch block-stray-block-put-after-teardown.patch -ApplyPatch HID-wacom-Set-input-bits-before-registration.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -1530,40 +1444,13 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch revert-efi-rtclock.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch -ApplyPatch hvcs_pi_buf_alloc.patch - -ApplyPatch media-dib0700-correct-error-message.patch - # utrace. ApplyPatch utrace.patch -#rhbz #735946 -ApplyPatch 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch -ApplyPatch 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch -ApplyPatch mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch - -#rhbz 748691 -ApplyPatch be2net-non-member-vlan-pkts-not-received-in-promisco.patch -ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch - -#rhbz 736815 -ApplyPatch x86-code-dump-fix-truncation.patch - -#rhbz 728607 -ApplyPatch elantech.patch - #rhbz 752176 ApplyPatch sysfs-msi-irq-per-device.patch -%if !%{with_backports} -#backport brcm80211 from 3.2-rc1 -ApplyPatch brcm80211.patch -# Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 -ApplyPatch bcma-brcmsmac-compat.patch -%endif - # rhbz 754907 -ApplyPatch cciss-fix-irqf-shared.patch ApplyPatch hpsa-add-irqf-shared.patch #rhbz 731365 @@ -1573,27 +1460,15 @@ ApplyPatch pci-Rework-ASPM-disable-code.patch #ApplyPatch pci-crs-blacklist.patch -#rhbz #757839 -ApplyPatch net-sky2-88e8059-fix-link-speed.patch - #rhbz 717735 ApplyPatch nfs-client-freezer.patch #rhbz 590880 ApplyPatch alps.patch -#rhbz 741117 -ApplyPatch b44-Use-dev_kfree_skb_irq-in-b44_tx.patch - #rhbz 746097 ApplyPatch tpm_tis-delay-after-aborting-cmd.patch -#rhbz 771006 -ApplyPatch thp-reduce-khugepaged-freezing-latency.patch - -#rhbz 770233 -ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch - #rhbz 771058 ApplyPatch msi-irq-sysfs-warning.patch @@ -1608,11 +1483,6 @@ ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch #rhbz 728740 ApplyPatch rtl8192cu-Fix-WARNING-on-suspend-resume.patch -#rhbz 769911 -ApplyPatch 01-block-add-and-use-scsi_blk_cmd_ioctl.patch -ApplyPatch 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch -ApplyPatch 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch - #rhbz 782686 ApplyPatch procfs-parse-mount-options.patch ApplyPatch procfs-add-hidepid-and-gid-mount-options.patch @@ -1621,9 +1491,6 @@ ApplyPatch proc-fix-null-pointer-deref-in-proc_pid_permission.patch #rhbz 782681 ApplyPatch proc-clean-up-and-fix-proc-pid-mem-handling.patch -#rhbz 782687 -ApplyPatch loop-prevent-information-leak-after-failed-read.patch - # END OF PATCH APPLICATIONS %endif @@ -2399,6 +2266,9 @@ fi # and build. %changelog +* Thu Jan 19 2012 Dave Jones 3.2.1-1 +- Rebase to Linux 3.2.1 + * Thu Jan 19 2012 John W. Linville - Pass the same make options to compat-wireless as to the base kernel diff --git a/linux-2.6-32bit-mmap-exec-randomization.patch b/linux-2.6-32bit-mmap-exec-randomization.patch index 6008173b0..c25323323 100644 --- a/linux-2.6-32bit-mmap-exec-randomization.patch +++ b/linux-2.6-32bit-mmap-exec-randomization.patch @@ -152,7 +152,7 @@ Main executable randomisation (PIE) : 12 bits (guessed) struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) --- a/arch/x86/mm/mmap.c +++ b/arch/x86/mm/mmap.c -@@ -124,13 +124,16 @@ static unsigned long mmap_legacy_base(void) +@@ -124,13 +124,19 @@ static unsigned long mmap_legacy_base(void) */ void arch_pick_mmap_layout(struct mm_struct *mm) { @@ -163,9 +163,12 @@ Main executable randomisation (PIE) : 12 bits (guessed) } else { mm->mmap_base = mmap_base(); mm->get_unmapped_area = arch_get_unmapped_area_topdown; ++#ifdef CONFIG_X86_32 + if (!(current->personality & READ_IMPLIES_EXEC) ++ && !(__supported_pte_mask & _PAGE_NX) + && mmap_is_ia32()) + mm->get_unmapped_exec_area = arch_get_unmapped_exec_area; ++#endif mm->unmap_area = arch_unmap_area_topdown; } } @@ -224,3 +227,25 @@ Main executable randomisation (PIE) : 12 bits (guessed) if (new_addr & ~PAGE_MASK) { ret = new_addr; goto out; +diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c +index 57d1868..29c0c35 100644 +--- a/arch/x86/kernel/process.c ++++ b/arch/x86/kernel/process.c +@@ -669,6 +669,16 @@ unsigned long arch_align_stack(unsigned long sp) + unsigned long arch_randomize_brk(struct mm_struct *mm) + { + unsigned long range_end = mm->brk + 0x02000000; +- return randomize_range(mm->brk, range_end, 0) ? : mm->brk; ++ unsigned long bump = 0; ++#ifdef CONFIG_X86_32 ++ /* in the case of NX emulation, shove the brk segment way out of the ++ way of the exec randomization area, since it can collide with ++ future allocations if not. */ ++ if ( (mm->get_unmapped_exec_area == arch_get_unmapped_exec_area) && ++ (mm->brk < 0x08000000) ) { ++ bump = (TASK_SIZE/6); ++ } ++#endif ++ return bump + (randomize_range(mm->brk, range_end, 0) ? : mm->brk); + } + diff --git a/linux-2.6-debug-taint-vm.patch b/linux-2.6-debug-taint-vm.patch deleted file mode 100644 index 672509db2..000000000 --- a/linux-2.6-debug-taint-vm.patch +++ /dev/null @@ -1,51 +0,0 @@ -diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index 4e8985a..70d0853 100644 ---- a/mm/page_alloc.c -+++ b/mm/page_alloc.c -@@ -318,6 +318,7 @@ static void bad_page(struct page *page) - current->comm, page_to_pfn(page)); - dump_page(page); - -+ print_modules(); - dump_stack(); - out: - /* Leave bad fields for debug, except PageBuddy could make trouble */ -diff --git a/mm/slab.c b/mm/slab.c -index d96e223..6f8905b 100644 ---- a/mm/slab.c -+++ b/mm/slab.c -@@ -1886,8 +1886,8 @@ static void check_poison_obj(struct kmem_cache *cachep, void *objp) - /* Print header */ - if (lines == 0) { - printk(KERN_ERR -- "Slab corruption: %s start=%p, len=%d\n", -- cachep->name, realobj, size); -+ "Slab corruption (%s): %s start=%p, len=%d\n", -+ print_tainted(), cachep->name, realobj, size); - print_objinfo(cachep, objp, 0); - } - /* Hexdump the affected line */ -@@ -2985,8 +2985,8 @@ static void check_slabp(struct kmem_cache *cachep, struct slab *slabp) - if (entries != cachep->num - slabp->inuse) { - bad: - printk(KERN_ERR "slab: Internal list corruption detected in " -- "cache '%s'(%d), slabp %p(%d). Hexdump:\n", -- cachep->name, cachep->num, slabp, slabp->inuse); -+ "cache '%s'(%d), slabp %p(%d). Tainted(%s). Hexdump:\n", -+ cachep->name, cachep->num, slabp, slabp->inuse, print_tainted()); - for (i = 0; - i < sizeof(*slabp) + cachep->num * sizeof(kmem_bufctl_t); - i++) { -diff --git a/mm/slub.c b/mm/slub.c -index 35f351f..e7ccb39 100644 ---- a/mm/slub.c -+++ b/mm/slub.c -@@ -472,7 +472,7 @@ static void slab_bug(struct kmem_cache *s, char *fmt, ...) - va_end(args); - printk(KERN_ERR "========================================" - "=====================================\n"); -- printk(KERN_ERR "BUG %s: %s\n", s->name, buf); -+ printk(KERN_ERR "BUG %s (%s): %s\n", s->name, print_tainted(), buf); - printk(KERN_ERR "----------------------------------------" - "-------------------------------------\n\n"); - } diff --git a/linux-2.6-e1000-ich9-montevina.patch b/linux-2.6-e1000-ich9-montevina.patch index d45fd5673..ec38a3902 100644 --- a/linux-2.6-e1000-ich9-montevina.patch +++ b/linux-2.6-e1000-ich9-montevina.patch @@ -1,11 +1,22 @@ +From 802e6d8c8477a553a677b23a247d6d2638e01958 Mon Sep 17 00:00:00 2001 +From: Dave Jones +Date: Wed, 26 Oct 2011 13:31:47 -0400 +Subject: [PATCH] e1000e: ich9 montevina + This only showed up in one SDV (Montevina). The PCIE slots don't seem to like network cards, so this is the only hope to get networking working. It's never going upstream, but it's low impact enough to carry just to keep those SDVs working. +--- + drivers/net/ethernet/intel/e1000e/ich8lan.c | 6 ++++++ + drivers/net/ethernet/intel/e1000e/netdev.c | 1 + + 2 files changed, 7 insertions(+), 0 deletions(-) ---- linux-2.6.35.noarch/drivers/net/e1000e/ich8lan.c~ 2010-09-29 17:53:13.000000000 -0400 -+++ linux-2.6.35.noarch/drivers/net/e1000e/ich8lan.c 2010-09-29 17:54:00.000000000 -0400 -@@ -424,6 +424,12 @@ static s32 e1000_init_phy_params_ich8lan +diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c +index 6a17c62..0e40975 100644 +--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c ++++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c +@@ -452,6 +452,12 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) /* Verify phy id */ switch (phy->id) { @@ -18,9 +29,11 @@ enough to carry just to keep those SDVs working. case IGP03E1000_E_PHY_ID: phy->type = e1000_phy_igp_3; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; ---- linux-2.6.35.noarch/drivers/net/e1000e/netdev.c~ 2010-09-29 17:54:07.000000000 -0400 -+++ linux-2.6.35.noarch/drivers/net/e1000e/netdev.c 2010-09-29 17:54:29.000000000 -0400 -@@ -5994,6 +5994,7 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci +diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c +index a855db1..edac30b 100644 +--- a/drivers/net/ethernet/intel/e1000e/netdev.c ++++ b/drivers/net/ethernet/intel/e1000e/netdev.c +@@ -6359,6 +6359,7 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M), board_ich9lan }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_AMT), board_ich9lan }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_V), board_ich9lan }, @@ -28,3 +41,6 @@ enough to carry just to keep those SDVs working. { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LM), board_ich9lan }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LF), board_ich9lan }, +-- +1.7.6.4 + diff --git a/linux-2.6-i386-nx-emulation.patch b/linux-2.6-i386-nx-emulation.patch index fb58c612e..07a0faec8 100644 --- a/linux-2.6-i386-nx-emulation.patch +++ b/linux-2.6-i386-nx-emulation.patch @@ -592,25 +592,3 @@ mmu_notifier_invalidate_range_start(mm, start, end); if (is_vm_hugetlb_page(vma)) hugetlb_change_protection(vma, start, end, vma->vm_page_prot); -diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c -index 57d1868..29c0c35 100644 ---- a/arch/x86/kernel/process.c -+++ b/arch/x86/kernel/process.c -@@ -669,6 +669,16 @@ unsigned long arch_align_stack(unsigned long sp) - unsigned long arch_randomize_brk(struct mm_struct *mm) - { - unsigned long range_end = mm->brk + 0x02000000; -- return randomize_range(mm->brk, range_end, 0) ? : mm->brk; -+ unsigned long bump = 0; -+#ifdef CONFIG_X86_32 -+ /* in the case of NX emulation, shove the brk segment way out of the -+ way of the exec randomization area, since it can collide with -+ future allocations if not. */ -+ if ( (mm->get_unmapped_exec_area == arch_get_unmapped_exec_area) && -+ (mm->brk < 0x08000000) ) { -+ bump = (TASK_SIZE/6); -+ } -+#endif -+ return bump + (randomize_range(mm->brk, range_end, 0) ? : mm->brk); - } - diff --git a/linux-2.6-intel-iommu-igfx.patch b/linux-2.6-intel-iommu-igfx.patch index b2f8f19e3..3a45abaec 100644 --- a/linux-2.6-intel-iommu-igfx.patch +++ b/linux-2.6-intel-iommu-igfx.patch @@ -1,6 +1,7 @@ -Subject: [PATCH] [intel_iommu] Default to igfx_off +From 602e1f209dd983e40d989e871cd253e8187899b8 Mon Sep 17 00:00:00 2001 From: drago01 -To: fedora-kernel-list +Date: Wed, 26 Oct 2011 13:37:27 -0400 +Subject: [PATCH] Default to igfx_off This option seems to causes way to many issues, it is being investigated by Intel's chipset team for months now and @@ -16,14 +17,14 @@ Signed-off-by: Adel Gadllah Reviewed-by: Adam Jackson --- Documentation/kernel-parameters.txt | 11 +++++------ - drivers/pci/intel-iommu.c | 9 +++++---- + drivers/iommu/intel-iommu.c | 9 +++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index e7848a0..9914485 100644 +index 81c287f..ee5693b 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt -@@ -992,12 +992,11 @@ and is between 256 and 4096 characters. It is defined in the file +@@ -1014,12 +1014,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Enable intel iommu driver. off Disable intel iommu driver. @@ -40,22 +41,22 @@ index e7848a0..9914485 100644 + mapped as normal device. forcedac [x86_64] With this option iommu will not optimize to look - for io virtual address below 32 bit forcing dual -diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c -index 4173125..8f36786 100644 + for io virtual address below 32-bit forcing dual +diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c +index bdc447f..240db6b 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c -@@ -340,7 +340,8 @@ int dmar_disabled = 0; - int dmar_disabled = 1; - #endif /*CONFIG_DMAR_DEFAULT_ON*/ - +@@ -408,7 +408,8 @@ int dmar_disabled = 1; + int intel_iommu_enabled = 0; + EXPORT_SYMBOL_GPL(intel_iommu_enabled); + -static int dmar_map_gfx = 1; +/* disabled by default; causes way too many issues */ +static int dmar_map_gfx = 0; static int dmar_forcedac; static int intel_iommu_strict; - -@@ -361,10 +362,10 @@ static int __init intel_iommu_setup(char *str) + static int intel_iommu_superpage = 1; +@@ -433,10 +434,10 @@ static int __init intel_iommu_setup(char *str) } else if (!strncmp(str, "off", 3)) { dmar_disabled = 1; printk(KERN_INFO "Intel-IOMMU: disabled\n"); @@ -70,9 +71,5 @@ index 4173125..8f36786 100644 printk(KERN_INFO "Intel-IOMMU: Forcing DAC for PCI devices\n"); -- -1.6.6.1 -_______________________________________________ -kernel mailing list -kernel@lists.fedoraproject.org -https://admin.fedoraproject.org/mailman/listinfo/kernel +1.7.7.4 diff --git a/loop-prevent-information-leak-after-failed-read.patch b/loop-prevent-information-leak-after-failed-read.patch deleted file mode 100644 index 040a234c3..000000000 --- a/loop-prevent-information-leak-after-failed-read.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 3bb9068278ea524581237abadd41377a14717e7d Mon Sep 17 00:00:00 2001 -From: Dmitry Monakhov -Date: Wed, 16 Nov 2011 09:21:48 +0100 -Subject: [PATCH] loop: prevent information leak after failed read - -If read was not fully successful we have to fail whole bio to prevent -information leak of old pages - -##Testcase_begin -dd if=/dev/zero of=./file bs=1M count=1 -losetup /dev/loop0 ./file -o 4096 -truncate -s 0 ./file -# OOps loop offset is now beyond i_size, so read will silently fail. -# So bio's pages would not be cleared, may which result in information leak. -hexdump -C /dev/loop0 -##testcase_end - -Signed-off-by: Dmitry Monakhov -Signed-off-by: Andrew Morton -Signed-off-by: Jens Axboe ---- - drivers/block/loop.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/drivers/block/loop.c b/drivers/block/loop.c -index 3d80682..0d56739 100644 ---- a/drivers/block/loop.c -+++ b/drivers/block/loop.c -@@ -372,7 +372,8 @@ do_lo_receive(struct loop_device *lo, - - if (retval < 0) - return retval; -- -+ if (retval != bvec->bv_len) -+ return -EIO; - return 0; - } - --- -1.7.7.5 - diff --git a/media-dib0700-correct-error-message.patch b/media-dib0700-correct-error-message.patch deleted file mode 100644 index 5e5d3bfa2..000000000 --- a/media-dib0700-correct-error-message.patch +++ /dev/null @@ -1,103 +0,0 @@ -From: Olivier Grenie -Date: Thu, 4 Aug 2011 16:10:03 +0000 (-0300) -Subject: [media] dib0700: correct error message -X-Git-Tag: next-20110927~67^2~4^2~223 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=680417bb318adc5f1f8f392730776176fbcdedd8 - -[media] dib0700: correct error message - -The goal of this patch is to correct a previous patch. In case of error, -the err() function should be used instead of dprintk() function. - -[mchehab@redhat.com: as I've replaced dprintk by deb_info, on the the - previous patch, to avoid breaking bisect, I had to fix a merge conflict - on this one] -Signed-off-by: Olivier Grenie -Signed-off-by: Mauro Carvalho Chehab ---- - -diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c -index a224e94..b693ed1 100644 ---- a/drivers/media/dvb/dvb-usb/dib0700_core.c -+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c -@@ -31,7 +31,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, - int ret; - - if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - -@@ -117,7 +117,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ - int ret; - - if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - -@@ -138,7 +138,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) - - if (st->fw_version >= 0x10201) { - if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - -@@ -227,7 +227,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, - } else { - /* Write request */ - if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - st->buf[0] = REQUEST_NEW_I2C_WRITE; -@@ -273,7 +273,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; - if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - -@@ -368,7 +368,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, - int ret; - - if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - -@@ -400,7 +400,7 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) - return -EINVAL; - - if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - -@@ -560,7 +560,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) - } - - if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - -@@ -610,7 +610,7 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) - int new_proto, ret; - - if (mutex_lock_interruptible(&d->usb_mutex) < 0) { -- deb_info("could not acquire lock"); -+ err("could not acquire lock"); - return 0; - } - diff --git a/net-sky2-88e8059-fix-link-speed.patch b/net-sky2-88e8059-fix-link-speed.patch deleted file mode 100644 index 61e1c75df..000000000 --- a/net-sky2-88e8059-fix-link-speed.patch +++ /dev/null @@ -1,42 +0,0 @@ -commit 27d240fdae2808d727ad9ce48ec029731a457524 -Author: stephen hemminger -Date: Fri Nov 4 12:17:17 2011 +0000 - - sky2: fix regression on Yukon Optima - - [ backport to 3.1 ] - - Changes to support other Optima types, introduced an accidental - regression that caused 88E8059 to come up in 10Mbit/sec. - - The Yukon Optima supports a reverse auto-negotiation feature that - was incorrectly setup, and not needed. The feature could be used to - allow wake-on-lan at higher speeds. But doing it correctly would require - other changes to initialization. - - Reported-by: Pavel Mateja - Signed-off-by: Stephen Hemminger - Signed-off-by: David S. Miller - -diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c -index cbd026f..fdc6c39 100644 ---- a/drivers/net/sky2.c -+++ b/drivers/net/sky2.c -@@ -366,17 +366,6 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) - gm_phy_write(hw, port, PHY_MARV_FE_SPEC_2, spec); - } - } else { -- if (hw->chip_id >= CHIP_ID_YUKON_OPT) { -- u16 ctrl2 = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL_2); -- -- /* enable PHY Reverse Auto-Negotiation */ -- ctrl2 |= 1u << 13; -- -- /* Write PHY changes (SW-reset must follow) */ -- gm_phy_write(hw, port, PHY_MARV_EXT_CTRL_2, ctrl2); -- } -- -- - /* disable energy detect */ - ctrl &= ~PHY_M_PC_EN_DET_MSK; - diff --git a/nfs-client-freezer.patch b/nfs-client-freezer.patch index 6b4d34d8a..5f5b0836e 100644 --- a/nfs-client-freezer.patch +++ b/nfs-client-freezer.patch @@ -1,106 +1,4 @@ @@ -, +, @@ - fs/cifs/transport.c | 3 ++- - include/linux/freezer.h | 19 +++++++++++++++++-- - 2 files changed, 19 insertions(+), 3 deletions(-) ---- a/fs/cifs/transport.c -+++ a/fs/cifs/transport.c -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -324,7 +325,7 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) - { - int error; - -- error = wait_event_killable(server->response_q, -+ error = wait_event_freezekillable(server->response_q, - midQ->midState != MID_REQUEST_SUBMITTED); - if (error < 0) - return -ERESTARTSYS; ---- a/include/linux/freezer.h -+++ a/include/linux/freezer.h -@@ -134,10 +134,25 @@ static inline void set_freezable_with_signal(void) - } - - /* -- * Freezer-friendly wrappers around wait_event_interruptible() and -- * wait_event_interruptible_timeout(), originally defined in -+ * Freezer-friendly wrappers around wait_event_interruptible(), -+ * wait_event_killable() and wait_event_interruptible_timeout(), originally -+ * defined in - */ - -+#define wait_event_freezekillable(wq, condition) \ -+({ \ -+ int __retval; \ -+ do { \ -+ __retval = wait_event_killable(wq, \ -+ (condition) || freezing(current)); \ -+ if (__retval && !freezing(current)) \ -+ break; \ -+ else if (!(condition)) \ -+ __retval = -ERESTARTSYS; \ -+ } while (try_to_freeze()); \ -+ __retval; \ -+}) -+ - #define wait_event_freezable(wq, condition) \ - ({ \ - int __retval; \ - include/linux/freezer.h | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) ---- a/include/linux/freezer.h -+++ a/include/linux/freezer.h -@@ -143,7 +143,7 @@ static inline void set_freezable_with_signal(void) - ({ \ - int __retval; \ - do { \ -- __retval = wait_event_killable(wq, \ -+ __retval = wait_event_killable(wq, \ - (condition) || freezing(current)); \ - if (__retval && !freezing(current)) \ - break; \ - include/linux/freezer.h | 3 +++ - 1 files changed, 3 insertions(+), 0 deletions(-) ---- a/include/linux/freezer.h -+++ a/include/linux/freezer.h -@@ -203,6 +203,9 @@ static inline void set_freezable_with_signal(void) {} - #define wait_event_freezable_timeout(wq, condition, timeout) \ - wait_event_interruptible_timeout(wq, condition, timeout) - -+#define wait_event_freezekillable(wq, condition) \ -+ wait_event_killable(wq, condition) -+ - #endif /* !CONFIG_FREEZER */ - - #endif /* FREEZER_H_INCLUDED */ - description on Rafael's request.] - include/linux/freezer.h | 11 +++-------- - 1 files changed, 3 insertions(+), 8 deletions(-) ---- a/include/linux/freezer.h -+++ a/include/linux/freezer.h -@@ -142,14 +142,9 @@ static inline void set_freezable_with_signal(void) - #define wait_event_freezekillable(wq, condition) \ - ({ \ - int __retval; \ -- do { \ -- __retval = wait_event_killable(wq, \ -- (condition) || freezing(current)); \ -- if (__retval && !freezing(current)) \ -- break; \ -- else if (!(condition)) \ -- __retval = -ERESTARTSYS; \ -- } while (try_to_freeze()); \ -+ freezer_do_not_count(); \ -+ __retval = wait_event_killable(wq, (condition)); \ -+ freezer_count(); \ - __retval; \ - }) - fs/nfs/inode.c | 3 ++- fs/nfs/nfs3proc.c | 3 ++- fs/nfs/nfs4proc.c | 5 +++-- @@ -156,7 +54,7 @@ #include "nfs4_fs.h" #include "delegation.h" -@@ -244,7 +245,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) +@@ -241,7 +242,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) *timeout = NFS4_POLL_RETRY_MIN; if (*timeout > NFS4_POLL_RETRY_MAX) *timeout = NFS4_POLL_RETRY_MAX; @@ -165,7 +63,7 @@ if (fatal_signal_pending(current)) res = -ERESTARTSYS; *timeout <<= 1; -@@ -3970,7 +3971,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 +@@ -3950,7 +3951,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 static unsigned long nfs4_set_lock_task_retry(unsigned long timeout) { @@ -195,7 +93,7 @@ return res; --- a/include/linux/freezer.h +++ a/include/linux/freezer.h -@@ -134,6 +134,29 @@ static inline void set_freezable_with_signal(void) +@@ -135,6 +135,29 @@ static inline void set_freezable_with_signal(void) } /* @@ -225,7 +123,7 @@ * Freezer-friendly wrappers around wait_event_interruptible(), * wait_event_killable() and wait_event_interruptible_timeout(), originally * defined in -@@ -192,6 +215,11 @@ static inline int freezer_should_skip(struct task_struct *p) { return 0; } +@@ -194,6 +217,11 @@ static inline int freezer_should_skip(struct task_struct *p) { return 0; } static inline void set_freezable(void) {} static inline void set_freezable_with_signal(void) {} @@ -260,7 +158,7 @@ 1 files changed, 18 insertions(+), 3 deletions(-) --- a/include/linux/freezer.h +++ a/include/linux/freezer.h -@@ -140,18 +140,33 @@ static inline void set_freezable_with_signal(void) +@@ -141,18 +141,33 @@ static inline void set_freezable_with_signal(void) * while in this function. */ diff --git a/rcu-avoid-just-onlined-cpu-resched.patch b/rcu-avoid-just-onlined-cpu-resched.patch deleted file mode 100644 index 517f37591..000000000 --- a/rcu-avoid-just-onlined-cpu-resched.patch +++ /dev/null @@ -1,47 +0,0 @@ -rcu: Avoid having just-onlined CPU resched itself when RCU is idle - -CPUs set rdp->qs_pending when coming online to resolve races with -grace-period start. However, this means that if RCU is idle, the -just-onlined CPU might needlessly send itself resched IPIs. Adjust -the online-CPU initialization to avoid this, and also to correctly -cause the CPU to respond to the current grace period if needed. - -Signed-off-by: Paul E. McKenney ---- - kernel/rcutree.c | 13 +++++++++---- - 1 files changed, 9 insertions(+), 4 deletions(-) - -diff --git a/kernel/rcutree.c b/kernel/rcutree.c -index ba06207..472d6b2 100644 ---- a/kernel/rcutree.c -+++ b/kernel/rcutree.c -@@ -1865,8 +1865,6 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible) - - /* Set up local state, ensuring consistent view of global state. */ - raw_spin_lock_irqsave(&rnp->lock, flags); -- rdp->passed_quiesc = 0; /* We could be racing with new GP, */ -- rdp->qs_pending = 1; /* so set up to respond to current GP. */ - rdp->beenonline = 1; /* We have now been online. */ - rdp->preemptible = preemptible; - rdp->qlen_last_fqs_check = 0; -@@ -1891,8 +1889,15 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible) - rnp->qsmaskinit |= mask; - mask = rnp->grpmask; - if (rnp == rdp->mynode) { -- rdp->gpnum = rnp->completed; /* if GP in progress... */ -- rdp->completed = rnp->completed; -+ /* -+ * If there is a grace period in progress, we will -+ * set up to wait for it next time we run the -+ * RCU core code. -+ */ -+ rdp->gpnum = rnp->completed; -+ rdp->completed = rnp->completed; -+ rdp->passed_quiesc = 0; -+ rdp->qs_pending = 0; - rdp->passed_quiesc_completed = rnp->completed - 1; - } - raw_spin_unlock(&rnp->lock); /* irqs already disabled. */ --- -1.7.6 - diff --git a/rcutree-avoid-false-quiescent-states.patch b/rcutree-avoid-false-quiescent-states.patch deleted file mode 100644 index 9c7ffea34..000000000 --- a/rcutree-avoid-false-quiescent-states.patch +++ /dev/null @@ -1,67 +0,0 @@ -diff --git a/kernel/rcutree.c b/kernel/rcutree.c -index ba06207..c38a882 100644 ---- a/kernel/rcutree.c -+++ b/kernel/rcutree.c -@@ -1476,9 +1476,6 @@ static void rcu_process_callbacks(struct softirq_action *unused) - &__get_cpu_var(rcu_sched_data)); - __rcu_process_callbacks(&rcu_bh_state, &__get_cpu_var(rcu_bh_data)); - rcu_preempt_process_callbacks(); -- -- /* If we are last CPU on way to dyntick-idle mode, accelerate it. */ -- rcu_needs_cpu_flush(); - } - - /* -diff --git a/kernel/rcutree.h b/kernel/rcutree.h -index 01b2ccd..795f7fc 100644 ---- a/kernel/rcutree.h -+++ b/kernel/rcutree.h -@@ -450,7 +450,6 @@ static int rcu_preempt_needs_cpu(int cpu); - static void __cpuinit rcu_preempt_init_percpu_data(int cpu); - static void rcu_preempt_send_cbs_to_online(void); - static void __init __rcu_init_preempt(void); --static void rcu_needs_cpu_flush(void); - static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags); - static void rcu_preempt_boost_start_gp(struct rcu_node *rnp); - static void invoke_rcu_callbacks_kthread(void); -diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h -index 8aafbb8..b0254de 100644 ---- a/kernel/rcutree_plugin.h -+++ b/kernel/rcutree_plugin.h -@@ -1907,15 +1907,6 @@ int rcu_needs_cpu(int cpu) - return rcu_needs_cpu_quick_check(cpu); - } - --/* -- * Check to see if we need to continue a callback-flush operations to -- * allow the last CPU to enter dyntick-idle mode. But fast dyntick-idle -- * entry is not configured, so we never do need to. -- */ --static void rcu_needs_cpu_flush(void) --{ --} -- - #else /* #if !defined(CONFIG_RCU_FAST_NO_HZ) */ - - #define RCU_NEEDS_CPU_FLUSHES 5 -@@ -1991,20 +1982,4 @@ int rcu_needs_cpu(int cpu) - return c; - } - --/* -- * Check to see if we need to continue a callback-flush operations to -- * allow the last CPU to enter dyntick-idle mode. -- */ --static void rcu_needs_cpu_flush(void) --{ -- int cpu = smp_processor_id(); -- unsigned long flags; -- -- if (per_cpu(rcu_dyntick_drain, cpu) <= 0) -- return; -- local_irq_save(flags); -- (void)rcu_needs_cpu(cpu); -- local_irq_restore(flags); --} -- - #endif /* #else #if !defined(CONFIG_RCU_FAST_NO_HZ) */ diff --git a/rtl8192cu-Fix-WARNING-on-suspend-resume.patch b/rtl8192cu-Fix-WARNING-on-suspend-resume.patch index e784b1632..bdc8a5492 100644 --- a/rtl8192cu-Fix-WARNING-on-suspend-resume.patch +++ b/rtl8192cu-Fix-WARNING-on-suspend-resume.patch @@ -1,8 +1,3 @@ -From e234ca17f2d5ce23606fceef2df6c02f8555547e Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Wed, 11 Jan 2012 13:35:33 -0500 -Subject: [PATCH] rtl8192cu: Fix WARNING on suspend/resume - A recent LKML thread (http://lkml.indiana.edu/hypermail/linux/kernel/1112.3/00965.html) discusses warnings that occur during a suspend/resume cycle. The driver attempts to read the firmware file before userspace is ready, leading to the @@ -18,6 +13,8 @@ through a suspend/resume cycle, and does not have to be reread. This patch should fix the bug reported in https://bugzilla.redhat.com/show_bug.cgi?id=771002. +Note: This patch also touches rtl8192ce as the "firmware" loaded message +is now printed in the wrong place. Note: This patch also touches rtl8192ce as the "firmware" loaded message is now printed in the wrong place. @@ -27,30 +24,25 @@ Signed-off-by: Larry Finger Cc: Linus Torvalds Cc: Stable -Backported to Fedora 3.1.x. --- drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 1 - drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 1 + drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 58 +++++++++++++++++---- 3 files changed, 49 insertions(+), 11 deletions(-) -diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c -index 49a064b..e3c4ac7 100644 ---- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c -+++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c -@@ -226,7 +226,6 @@ int rtl92c_download_fw(struct ieee80211_hw *hw) +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:07:58.830625006 -0500 ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:08:06.825439927 -0500 +@@ -227,7 +227,6 @@ int rtl92c_download_fw(struct ieee80211_ u32 fwsize; enum version_8192c version = rtlhal->version; - pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); if (!rtlhal->pfirmware) return 1; - -diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c -index 373dc78..9c3a8f1 100644 ---- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c -+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c -@@ -171,6 +171,7 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) + +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +@@ -186,6 +186,7 @@ int rtl92c_init_sw_vars(struct ieee80211 memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); rtlpriv->rtlhal.fwsize = firmware->size; release_firmware(firmware); @@ -58,21 +50,18 @@ index 373dc78..9c3a8f1 100644 return 0; } -diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c -index ef63c0d..f4230dd 100644 ---- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c -+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c -@@ -42,6 +42,9 @@ - #include "led.h" +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +@@ -43,6 +43,8 @@ #include "hw.h" #include + #include +#include +#include -+ MODULE_AUTHOR("Georgia "); MODULE_AUTHOR("Ziv Huang "); -@@ -50,6 +53,10 @@ MODULE_LICENSE("GPL"); +@@ -51,6 +53,10 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless"); MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); @@ -83,10 +72,10 @@ index ef63c0d..f4230dd 100644 static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); -@@ -60,12 +67,21 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) - rtlpriv->dm.dm_flag = 0; - rtlpriv->dm.disable_framebursting = 0; +@@ -62,12 +68,21 @@ static int rtl92cu_init_sw_vars(struct i + rtlpriv->dm.disable_framebursting = false; rtlpriv->dm.thermalvalue = 0; + rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; - rtlpriv->rtlhal.pfirmware = vmalloc(0x4000); - if (!rtlpriv->rtlhal.pfirmware) { + @@ -107,7 +96,7 @@ index ef63c0d..f4230dd 100644 /* request fw */ err = request_firmware(&firmware, rtlpriv->cfg->fw_name, rtlpriv->io.dev); -@@ -80,9 +96,14 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) +@@ -82,9 +97,14 @@ static int rtl92cu_init_sw_vars(struct i release_firmware(firmware); return 1; } @@ -123,7 +112,7 @@ index ef63c0d..f4230dd 100644 return 0; } -@@ -91,12 +112,30 @@ static void rtl92cu_deinit_sw_vars(struct ieee80211_hw *hw) +@@ -93,12 +113,30 @@ static void rtl92cu_deinit_sw_vars(struc { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -156,7 +145,7 @@ index ef63c0d..f4230dd 100644 static struct rtl_hal_ops rtl8192cu_hal_ops = { .init_sw_vars = rtl92cu_init_sw_vars, .deinit_sw_vars = rtl92cu_deinit_sw_vars, -@@ -338,11 +377,10 @@ static struct usb_driver rtl8192cu_driver = { +@@ -374,11 +412,10 @@ static struct usb_driver rtl8192cu_drive .disconnect = rtl_usb_disconnect, .id_table = rtl8192c_usb_ids, @@ -172,6 +161,3 @@ index ef63c0d..f4230dd 100644 #ifdef CONFIG_AUTOSUSPEND .supports_autosuspend = 1, #endif --- -1.7.7.5 - diff --git a/samsung-laptop-brightness-fixes-3.2.patch b/samsung-laptop-brightness-fixes-3.2.patch deleted file mode 100644 index 61032176b..000000000 --- a/samsung-laptop-brightness-fixes-3.2.patch +++ /dev/null @@ -1,238 +0,0 @@ -From: Jason Stubbs -Date: Tue, 20 Sep 2011 16:16:13 +0000 (-0700) -Subject: Platform: Brightness quirk for samsung laptop driver -X-Git-Tag: v3.2-rc1~111^2~41 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=ac080523141d5bfa5f60ef2436480f645f915e9c - -Platform: Brightness quirk for samsung laptop driver - -On some Samsung laptops the brightness regulation works slightly different. -All SABI commands except for set_brightness work as expected. The behaviour -of set_brightness is as follows: - -- Setting a new brightness will only step one level toward the new brightness - level. For example, setting a level of 5 when the current level is 2 will - result in a brightness level of 3. -- A spurious KEY_BRIGHTNESS_UP or KEY_BRIGHTNESS_DOWN event is also generated - along with the change in brightness. -- Neither of the above two issues occur when changing from/to brightness - level 0. - -This patch adds detection and a non-intrusive workaround for the above issues. - -Signed-off-by: Jason Stubbs -Tested-by: David Herrmann -Signed-off-by: Greg Kroah-Hartman -Signed-off-by: Matthew Garrett ---- - -diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c -index 4d3bed4..6474e42 100644 ---- a/drivers/platform/x86/samsung-laptop.c -+++ b/drivers/platform/x86/samsung-laptop.c -@@ -226,6 +226,7 @@ static struct backlight_device *backlight_device; - static struct mutex sabi_mutex; - static struct platform_device *sdev; - static struct rfkill *rfk; -+static bool has_stepping_quirk; - - static int force; - module_param(force, bool, 0); -@@ -382,6 +383,17 @@ static void set_brightness(u8 user_brightness) - { - u8 user_level = user_brightness + sabi_config->min_brightness; - -+ if (has_stepping_quirk && user_level != 0) { -+ /* -+ * short circuit if the specified level is what's already set -+ * to prevent the screen from flickering needlessly -+ */ -+ if (user_brightness == read_brightness()) -+ return; -+ -+ sabi_set_command(sabi_config->commands.set_brightness, 0); -+ } -+ - sabi_set_command(sabi_config->commands.set_brightness, user_level); - } - -@@ -390,6 +402,34 @@ static int get_brightness(struct backlight_device *bd) - return (int)read_brightness(); - } - -+static void check_for_stepping_quirk(void) -+{ -+ u8 initial_level = read_brightness(); -+ u8 check_level; -+ -+ /* -+ * Some laptops exhibit the strange behaviour of stepping toward -+ * (rather than setting) the brightness except when changing to/from -+ * brightness level 0. This behaviour is checked for here and worked -+ * around in set_brightness. -+ */ -+ -+ if (initial_level <= 2) -+ check_level = initial_level + 2; -+ else -+ check_level = initial_level - 2; -+ -+ has_stepping_quirk = false; -+ set_brightness(check_level); -+ -+ if (read_brightness() != check_level) { -+ has_stepping_quirk = true; -+ pr_info("enabled workaround for brightness stepping quirk\n"); -+ } -+ -+ set_brightness(initial_level); -+} -+ - static int update_status(struct backlight_device *bd) - { - set_brightness(bd->props.brightness); -@@ -805,6 +845,9 @@ static int __init samsung_init(void) - } - } - -+ /* Check for stepping quirk */ -+ check_for_stepping_quirk(); -+ - /* knock up a platform device to hang stuff off of */ - sdev = platform_device_register_simple("samsung", -1, NULL, 0); - if (IS_ERR(sdev)) -From: Jason Stubbs -Date: Tue, 20 Sep 2011 16:16:14 +0000 (-0700) -Subject: Platform: Samsung laptop DMI info for NC210/NC110 -X-Git-Tag: v3.2-rc1~111^2~40 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=7b3c257ce4267e004a7c7e68c05d1eb70da8c972 - -Platform: Samsung laptop DMI info for NC210/NC110 - -This patch just adds the DMI info for the samsung laptop driver to work with -the NC210/NC110. It needs the brightness quirk patch for proper support. - -Signed-off-by: Jason Stubbs -Signed-off-by: Greg Kroah-Hartman -Signed-off-by: Matthew Garrett ---- - -diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c -index 6474e42..8ffab50 100644 ---- a/drivers/platform/x86/samsung-laptop.c -+++ b/drivers/platform/x86/samsung-laptop.c -@@ -737,6 +737,15 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { - }, - .callback = dmi_check_cb, - }, -+ { -+ .ident = "NC210/NC110", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"), -+ DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"), -+ }, -+ .callback = dmi_check_cb, -+ }, - { }, - }; - MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); -From: Raul Gutierrez Segales -Date: Tue, 20 Sep 2011 16:16:15 +0000 (-0700) -Subject: Platform: fix samsung-laptop DMI identification for N220 model -X-Git-Tag: v3.2-rc1~111^2~39 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=f689c875c13c9d62b3c4de09cd5dad66549f700d - -Platform: fix samsung-laptop DMI identification for N220 model - -This is a follow-up for commit 78a7539b, which didn't cover the -Samsung N220 laptop. With this backlight brightness works nicely -on the N220 netbook. - -Signed-off-by: Raul Gutierrez Segales -Signed-off-by: Greg Kroah-Hartman -Signed-off-by: Matthew Garrett ---- - -diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c -index 8ffab50..1e436eb 100644 ---- a/drivers/platform/x86/samsung-laptop.c -+++ b/drivers/platform/x86/samsung-laptop.c -@@ -663,6 +663,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { - .callback = dmi_check_cb, - }, - { -+ .ident = "N220", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, -+ "SAMSUNG ELECTRONICS CO., LTD."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "N220"), -+ DMI_MATCH(DMI_BOARD_NAME, "N220"), -+ }, -+ .callback = dmi_check_cb, -+ }, -+ { - .ident = "N150/N210/N220/N230", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, -From: John Serock -Date: Thu, 13 Oct 2011 10:42:01 +0000 (-0400) -Subject: Platform: Detect samsung laptop quirk when initial level is zero -X-Git-Tag: v3.2-rc1~111^2~29 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=ba05b237372bad82533d1f717569d1d817ff3c27 - -Platform: Detect samsung laptop quirk when initial level is zero - -This patch depends on the "Platform: Brightness quirk for samsung -laptop driver" patch from Jason Stubbs. This patch adds a check for an -initial brightness level of 0; if the level is 0, this patch changes -the brightness level to 1 before the driver attempts to detect the -brightness quirk. - -The Samsung N150 netbook experiences the brightness quirk. Without -Jason's patch, the only brightness levels available on the N150 are 0, -1, and 8. This patch ensures that, when the initial brightness level -is 0, the samsang-laptop driver detects the brightness quirk on the -N150, thereby making brightness levels 0 through 8 available. - -Signed-off-by: John Serock -Acked-by: Jason Stubbs -Signed-off-by: Matthew Garrett ---- - -diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c -index 1e436eb..31ddd57 100644 ---- a/drivers/platform/x86/samsung-laptop.c -+++ b/drivers/platform/x86/samsung-laptop.c -@@ -404,8 +404,9 @@ static int get_brightness(struct backlight_device *bd) - - static void check_for_stepping_quirk(void) - { -- u8 initial_level = read_brightness(); -+ u8 initial_level; - u8 check_level; -+ u8 orig_level = read_brightness(); - - /* - * Some laptops exhibit the strange behaviour of stepping toward -@@ -414,6 +415,11 @@ static void check_for_stepping_quirk(void) - * around in set_brightness. - */ - -+ if (orig_level == 0) -+ set_brightness(1); -+ -+ initial_level = read_brightness(); -+ - if (initial_level <= 2) - check_level = initial_level + 2; - else -@@ -427,7 +433,7 @@ static void check_for_stepping_quirk(void) - pr_info("enabled workaround for brightness stepping quirk\n"); - } - -- set_brightness(initial_level); -+ set_brightness(orig_level); - } - - static int update_status(struct backlight_device *bd) diff --git a/sources b/sources index 58831534a..7401701d6 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -8d43453f8159b2332ad410b19d86a931 linux-3.1.tar.bz2 +364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz 204381bc537b689edcb15df0efed6467 compat-wireless-3.2-1.tar.bz2 -a8e1c25a93a685ec2a1c3a808715fe9d patch-3.1.10.bz2 +62ac6ac9b870162f693ecf5e8606423a patch-3.2.1.xz diff --git a/udlfb-bind-framebuffer-to-interface.patch b/udlfb-bind-framebuffer-to-interface.patch deleted file mode 100644 index 1c5c6df9b..000000000 --- a/udlfb-bind-framebuffer-to-interface.patch +++ /dev/null @@ -1,33 +0,0 @@ -From c91a793f66d5b06292aa431ae3a36c8aca991fa3 Mon Sep 17 00:00:00 2001 -From: Kay Sievers -Date: Tue, 5 Jul 2011 17:04:11 -0700 -Subject: [PATCH] drivers/video/udlfb bind framebuffer to interface. - -Udlfb has been binding the framebuffer device to its parent, which -isn't correct and causes confusion with operations like udev remove. - -Coming plug and play multiseat support is dependent on this fix. - -Signed-off-by: Kay Sievers -Signed-off-by: Bernie Thompson -Signed-off-by: Paul Mundt ---- - drivers/video/udlfb.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c -index 816a4fd..c6584c9 100644 ---- a/drivers/video/udlfb.c -+++ b/drivers/video/udlfb.c -@@ -1549,7 +1549,7 @@ static int dlfb_usb_probe(struct usb_interface *interface, - /* We don't register a new USB class. Our client interface is fbdev */ - - /* allocates framebuffer driver structure, not framebuffer memory */ -- info = framebuffer_alloc(0, &usbdev->dev); -+ info = framebuffer_alloc(0, &interface->dev); - if (!info) { - retval = -ENOMEM; - pr_err("framebuffer_alloc failed\n"); --- -1.7.4.4 - diff --git a/utrace.patch b/utrace.patch index 576c737f3..060d351e5 100644 --- a/utrace.patch +++ b/utrace.patch @@ -1,39 +1,38 @@ From davej Wed Aug 3 15:16:11 2011 +From oleg@redhat.com Mon Nov 21 15:06:14 2011 Return-Path: oleg@redhat.com -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:11 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:37 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:14 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 92D6F9D8C5; - Wed, 3 Aug 2011 15:12:08 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id RRq2PiCBdMzK; Wed, 3 Aug 2011 15:12:08 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 75C149D898; - Wed, 3 Aug 2011 15:12:08 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9A1F8D50F1; + Mon, 21 Nov 2011 15:06:14 -0500 (EST) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id gJzpul4rDNnA; Mon, 21 Nov 2011 15:06:14 -0500 (EST) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7DD4BD50EA; + Mon, 21 Nov 2011 15:06:14 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JC01d029136; - Wed, 3 Aug 2011 15:12:01 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6BJJ022074; + Mon, 21 Nov 2011 15:06:12 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:28 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:26 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:32 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:30 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 01/31] utrace core -Message-ID: <20110803190926.GA30903@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 01/33] utrace core +Message-ID: <20111121200130.GA27756@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO Content-Length: 139951 Lines: 3867 @@ -711,10 +710,10 @@ index 3a1dafd..f0c0ea2 100644 if (p->files) fdt = files_fdtable(p->files); diff --git a/include/linux/sched.h b/include/linux/sched.h -index 20b03bf..c6d79af 100644 +index 68daf4f..4d45f93 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h -@@ -1406,6 +1406,11 @@ struct task_struct { +@@ -1403,6 +1403,11 @@ struct task_struct { #endif seccomp_t seccomp; @@ -1425,7 +1424,7 @@ index 0000000..f251efe + +#endif /* linux/utrace.h */ diff --git a/init/Kconfig b/init/Kconfig -index d627783..7afce1f 100644 +index 43298f9..3f670e5 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -372,6 +372,15 @@ config AUDIT_TREE @@ -1445,7 +1444,7 @@ index d627783..7afce1f 100644 menu "RCU Subsystem" diff --git a/kernel/Makefile b/kernel/Makefile -index d06467f..85828da 100644 +index e898c5b..e43bbfb 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o @@ -3906,47 +3905,40 @@ index 0000000..ef856c9 1.5.5.1 -From davej Wed Aug 3 15:16:13 2011 +From oleg@redhat.com Mon Nov 21 15:06:17 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:13 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:37 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:17 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 419B39D8CF; - Wed, 3 Aug 2011 15:12:11 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1CCED128D6B; + Mon, 21 Nov 2011 15:06:17 -0500 (EST) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id AmaThyCcp1K4; Wed, 3 Aug 2011 15:12:11 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2A0B29CE59; - Wed, 3 Aug 2011 15:12:11 -0400 (EDT) + with ESMTP id FWdJDV74o-ay; Mon, 21 Nov 2011 15:06:17 -0500 (EST) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 082081285E4; + Mon, 21 Nov 2011 15:06:17 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JC3DW023262; - Wed, 3 Aug 2011 15:12:04 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6E7d015251; + Mon, 21 Nov 2011 15:06:15 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:31 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:29 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:35 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:33 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 02/31] utrace: add utrace_init_task/utrace_free_task calls -Message-ID: <20110803190929.GA30907@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 02/33] utrace: add utrace_init_task/utrace_free_task calls +Message-ID: <20111121200133.GA27759@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO Content-Length: 1295 Lines: 47 @@ -3966,7 +3958,7 @@ Signed-off-by: Oleg Nesterov 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/kernel/fork.c b/kernel/fork.c -index e7ceaca..a9891da 100644 +index ba0d172..b8719c2 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -66,6 +66,7 @@ @@ -3986,7 +3978,7 @@ index e7ceaca..a9891da 100644 free_task_struct(tsk); } EXPORT_SYMBOL(free_task); -@@ -1096,6 +1099,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, +@@ -1093,6 +1096,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, if (!p) goto fork_out; @@ -3999,47 +3991,40 @@ index e7ceaca..a9891da 100644 1.5.5.1 -From davej Wed Aug 3 15:16:18 2011 +From oleg@redhat.com Mon Nov 21 15:06:20 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:18 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:07 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:20 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F28379DE70; - Wed, 3 Aug 2011 15:12:13 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id p92IDp0LZ5jX; Wed, 3 Aug 2011 15:12:13 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D4E339DE68; - Wed, 3 Aug 2011 15:12:13 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8779AD87BC; + Mon, 21 Nov 2011 15:06:20 -0500 (EST) +Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id umzAMwRd7rMt; Mon, 21 Nov 2011 15:06:20 -0500 (EST) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 72C98D8707; + Mon, 21 Nov 2011 15:06:20 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JC6IA023283; - Wed, 3 Aug 2011 15:12:07 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6HAj015261; + Mon, 21 Nov 2011 15:06:18 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:34 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:32 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:39 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:36 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 03/31] tracehooks: add utrace hooks -Message-ID: <20110803190932.GA30915@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 03/33] tracehooks: add utrace hooks +Message-ID: <20111121200136.GA27766@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO Content-Length: 2310 Lines: 75 @@ -4120,48 +4105,41 @@ index a71a292..8cc28bc 100644 1.5.5.1 -From davej Wed Aug 3 15:16:14 2011 +From oleg@redhat.com Mon Nov 21 15:06:23 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:14 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:37 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:23 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 92FCA9D8FA; - Wed, 3 Aug 2011 15:12:16 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id lQaZCHUpw8DT; Wed, 3 Aug 2011 15:12:16 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7479B9D8C9; - Wed, 3 Aug 2011 15:12:16 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6559BD4FDE; + Mon, 21 Nov 2011 15:06:23 -0500 (EST) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 6BjISiO+cS1U; Mon, 21 Nov 2011 15:06:23 -0500 (EST) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 50366D4C39; + Mon, 21 Nov 2011 15:06:23 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JC91G023308; - Wed, 3 Aug 2011 15:12:09 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6KT9017533; + Mon, 21 Nov 2011 15:06:21 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:37 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:35 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:42 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:39 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 04/31] tracehooks: reintroduce +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 04/33] tracehooks: reintroduce tracehook_consider_fatal_signal() -Message-ID: <20110803190935.GA30918@redhat.com> +Message-ID: <20111121200139.GA27769@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO Content-Length: 3257 Lines: 90 @@ -4177,7 +4155,7 @@ Signed-off-by: Oleg Nesterov 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c -index ffabcd9..1018ab6 100644 +index a9807dd..f506e1b 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -329,7 +329,7 @@ void __kprobes do_per_trap(struct pt_regs *regs) @@ -4189,7 +4167,7 @@ index ffabcd9..1018ab6 100644 return; info.si_signo = SIGTRAP; info.si_errno = 0; -@@ -428,7 +428,7 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code, +@@ -429,7 +429,7 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code, if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) return; if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) { @@ -4232,7 +4210,7 @@ index 8cc28bc..ec2af67 100644 /** * set_notify_resume - cause tracehook_notify_resume() to be called diff --git a/kernel/signal.c b/kernel/signal.c -index 291c970..d7ef0da 100644 +index b3f78d0..d7b90cd 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -494,7 +494,7 @@ int unhandled_signal(struct task_struct *tsk, int sig) @@ -4257,46 +4235,39 @@ index 291c970..d7ef0da 100644 1.5.5.1 -From davej Wed Aug 3 15:16:20 2011 +From oleg@redhat.com Mon Nov 21 15:06:26 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:20 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:08 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:25 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 374FE9DE74; - Wed, 3 Aug 2011 15:12:19 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E7A2DD498A; + Mon, 21 Nov 2011 15:06:25 -0500 (EST) Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id Sun0Twp72xGV; Wed, 3 Aug 2011 15:12:19 -0400 (EDT) + with ESMTP id 4L9zskFVsr4I; Mon, 21 Nov 2011 15:06:25 -0500 (EST) Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 223E39DD25; - Wed, 3 Aug 2011 15:12:19 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D3487D4C39; + Mon, 21 Nov 2011 15:06:25 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCBgK008326; - Wed, 3 Aug 2011 15:12:12 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6Nnp017552; + Mon, 21 Nov 2011 15:06:24 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:39 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:37 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:44 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:42 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 05/31] add utrace hooks into sig_ignored() and +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 05/33] add utrace hooks into sig_ignored() and recalc_sigpending() -Message-ID: <20110803190937.GA30926@redhat.com> +Message-ID: <20111121200142.GA27777@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO @@ -4327,7 +4298,7 @@ index f251efe..1b8da1c 100644 /* diff --git a/kernel/signal.c b/kernel/signal.c -index d7ef0da..0f9af0b 100644 +index d7b90cd..8594cb2 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -87,7 +87,7 @@ static int sig_ignored(struct task_struct *t, int sig, int from_ancestor_ns) @@ -4355,45 +4326,38 @@ index d7ef0da..0f9af0b 100644 1.5.5.1 -From davej Wed Aug 3 15:16:21 2011 +From oleg@redhat.com Mon Nov 21 15:06:28 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:21 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:09 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:28 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 054279DE7D; - Wed, 3 Aug 2011 15:12:22 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6E4A6D4F4A; + Mon, 21 Nov 2011 15:06:28 -0500 (EST) Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 1BosZIzYSIW0; Wed, 3 Aug 2011 15:12:21 -0400 (EDT) + with ESMTP id vEeGLyK1+rX9; Mon, 21 Nov 2011 15:06:28 -0500 (EST) Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E41DC9DE7B; - Wed, 3 Aug 2011 15:12:21 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5AD50D4C39; + Mon, 21 Nov 2011 15:06:28 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JCEgD022264; - Wed, 3 Aug 2011 15:12:15 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6QOB029543; + Mon, 21 Nov 2011 15:06:26 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:42 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:40 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:47 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:45 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 06/31] restore the EXEC/EXIT/CLONE utrace hooks -Message-ID: <20110803190940.GA30929@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 06/33] restore the EXEC/EXIT/CLONE utrace hooks +Message-ID: <20111121200145.GA27780@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO @@ -4412,10 +4376,10 @@ Signed-off-by: Oleg Nesterov 4 files changed, 15 insertions(+), 1 deletions(-) diff --git a/fs/exec.c b/fs/exec.c -index da80612..a0814cd 100644 +index 3625464..7d8f8bd 100644 --- a/fs/exec.c +++ b/fs/exec.c -@@ -1401,9 +1401,12 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) +@@ -1397,9 +1397,12 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) */ bprm->recursion_depth = depth; if (retval >= 0) { @@ -4447,10 +4411,10 @@ index 1b8da1c..9ac0b1b 100644 /* diff --git a/kernel/exit.c b/kernel/exit.c -index 2913b35..c1b0ab6 100644 +index d0b7d98..f5eba3b 100644 --- a/kernel/exit.c +++ b/kernel/exit.c -@@ -913,6 +913,7 @@ NORET_TYPE void do_exit(long code) +@@ -911,6 +911,7 @@ NORET_TYPE void do_exit(long code) */ set_fs(USER_DS); @@ -4459,10 +4423,10 @@ index 2913b35..c1b0ab6 100644 validate_creds_for_do_exit(tsk); diff --git a/kernel/fork.c b/kernel/fork.c -index a9891da..37f4a07 100644 +index b8719c2..09d5049 100644 --- a/kernel/fork.c +++ b/kernel/fork.c -@@ -1539,6 +1539,8 @@ long do_fork(unsigned long clone_flags, +@@ -1535,6 +1535,8 @@ long do_fork(unsigned long clone_flags, audit_finish_fork(p); @@ -4471,7 +4435,7 @@ index a9891da..37f4a07 100644 /* * We set PF_STARTING at creation in case tracing wants to * use this to distinguish a fully live task from one that -@@ -1550,6 +1552,8 @@ long do_fork(unsigned long clone_flags, +@@ -1546,6 +1548,8 @@ long do_fork(unsigned long clone_flags, wake_up_new_task(p); /* forking complete and child started to run, tell ptracer */ @@ -4484,48 +4448,41 @@ index a9891da..37f4a07 100644 1.5.5.1 -From davej Wed Aug 3 15:16:23 2011 +From oleg@redhat.com Mon Nov 21 15:06:30 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:23 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:13 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:30 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B36EC9DE82; - Wed, 3 Aug 2011 15:12:24 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 7Qqv+lXfqHw6; Wed, 3 Aug 2011 15:12:24 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9F8AF9DD25; - Wed, 3 Aug 2011 15:12:24 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D248D1284E0; + Mon, 21 Nov 2011 15:06:30 -0500 (EST) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id divvekTmLScS; Mon, 21 Nov 2011 15:06:30 -0500 (EST) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BDC9412800E; + Mon, 21 Nov 2011 15:06:30 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCH0U023349; - Wed, 3 Aug 2011 15:12:17 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6Shj029546; + Mon, 21 Nov 2011 15:06:29 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:45 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:43 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:49 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:47 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 07/31] utrace: utrace_report_death() can use +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 07/33] utrace: utrace_report_death() can use task_utrace_struct() -Message-ID: <20110803190943.GA30936@redhat.com> +Message-ID: <20111121200147.GA27787@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO Content-Length: 1692 Lines: 44 @@ -4575,45 +4532,38 @@ index ef856c9..1e750ad 100644 1.5.5.1 -From davej Wed Aug 3 15:16:15 2011 +From oleg@redhat.com Mon Nov 21 15:06:33 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:15 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:39 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:33 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 76DA49D9C7; - Wed, 3 Aug 2011 15:12:27 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 25xHJjCTouA4; Wed, 3 Aug 2011 15:12:27 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 62E1BD50A3; + Mon, 21 Nov 2011 15:06:33 -0500 (EST) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id FB36YkOAHDc5; Mon, 21 Nov 2011 15:06:33 -0500 (EST) Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 490E79D9AB; - Wed, 3 Aug 2011 15:12:27 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4D161D4C39; + Mon, 21 Nov 2011 15:06:33 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCKXo023360; - Wed, 3 Aug 2011 15:12:20 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6VBW022130; + Mon, 21 Nov 2011 15:06:31 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:47 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:45 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:52 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:50 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 08/31] restore the DEATH/REAP utrace hooks -Message-ID: <20110803190945.GA30939@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 08/33] restore the DEATH/REAP utrace hooks +Message-ID: <20111121200150.GA27790@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO @@ -4666,7 +4616,7 @@ index 9a2e2f4..cf13839 100644 + #endif /* linux/utrace.h */ diff --git a/kernel/exit.c b/kernel/exit.c -index c1b0ab6..ba5ba22 100644 +index f5eba3b..746c5df 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -168,6 +168,8 @@ void release_task(struct task_struct * p) @@ -4678,7 +4628,7 @@ index c1b0ab6..ba5ba22 100644 /* don't need to get the RCU readlock here - the process is dead and * can't be modifying its own credentials. But shut RCU-lockdep up */ rcu_read_lock(); -@@ -860,6 +862,8 @@ static void exit_notify(struct task_struct *tsk, int group_dead) +@@ -858,6 +860,8 @@ static void exit_notify(struct task_struct *tsk, int group_dead) wake_up_process(tsk->signal->group_exit_task); write_unlock_irq(&tasklist_lock); @@ -4691,47 +4641,40 @@ index c1b0ab6..ba5ba22 100644 1.5.5.1 -From davej Wed Aug 3 15:22:02 2011 +From oleg@redhat.com Mon Nov 21 15:06:35 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:22:02 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:17:16 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:35 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 26DB69DE8C; - Wed, 3 Aug 2011 15:12:30 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id DbxGfmFvtTiR; Wed, 3 Aug 2011 15:12:30 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 0A30A9DE91; - Wed, 3 Aug 2011 15:12:30 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D4AB3D8761; + Mon, 21 Nov 2011 15:06:35 -0500 (EST) +Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id TiShkH1f6rnj; Mon, 21 Nov 2011 15:06:35 -0500 (EST) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BCB85D877F; + Mon, 21 Nov 2011 15:06:35 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCMDQ008389; - Wed, 3 Aug 2011 15:12:23 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6XNu015312; + Mon, 21 Nov 2011 15:06:34 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:50 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:48 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:54 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:52 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 09/31] utrace: remove jobctl bits -Message-ID: <20110803190948.GA30942@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 09/33] utrace: remove jobctl bits +Message-ID: <20111121200152.GA27793@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO Content-Length: 1888 Lines: 56 @@ -4793,47 +4736,40 @@ index 1e750ad..5d3974e 100644 1.5.5.1 -From davej Wed Aug 3 15:16:17 2011 +From oleg@redhat.com Mon Nov 21 15:06:38 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:17 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:52 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:38 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id AB6E39DA46; - Wed, 3 Aug 2011 15:12:32 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id LkzmRGslEelr; Wed, 3 Aug 2011 15:12:32 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 959659DA60; - Wed, 3 Aug 2011 15:12:32 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 425CED8707; + Mon, 21 Nov 2011 15:06:38 -0500 (EST) +Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 9paRC+dwSflh; Mon, 21 Nov 2011 15:06:38 -0500 (EST) +Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2DDBCD8410; + Mon, 21 Nov 2011 15:06:38 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCPx7023400; - Wed, 3 Aug 2011 15:12:25 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6a31031355; + Mon, 21 Nov 2011 15:06:36 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:53 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:51 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:56 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:55 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 10/31] ptrace: take ->siglock around s/TRACED/RUNNING/ -Message-ID: <20110803190951.GA30949@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 10/33] ptrace: take ->siglock around s/TRACED/RUNNING/ +Message-ID: <20111121200155.GA27801@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO Content-Length: 1624 Lines: 56 @@ -4851,7 +4787,7 @@ Signed-off-by: Oleg Nesterov 2 files changed, 10 insertions(+), 1 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 9de3ecf..56b8fc1 100644 +index 24d0447..daf47bc 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -589,6 +589,8 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info) @@ -4877,10 +4813,10 @@ index 9de3ecf..56b8fc1 100644 return 0; } diff --git a/kernel/signal.c b/kernel/signal.c -index 0f9af0b..71f5cca 100644 +index 8594cb2..4512bb4 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -1878,7 +1878,10 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1886,7 +1886,10 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) if (gstop_done) do_notify_parent_cldstop(current, false, why); @@ -4895,47 +4831,40 @@ index 0f9af0b..71f5cca 100644 1.5.5.1 -From davej Wed Aug 3 15:16:37 2011 +From oleg@redhat.com Mon Nov 21 15:06:40 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:37 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:29 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:40 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5034E9DEA4; - Wed, 3 Aug 2011 15:12:35 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 8BhFlmqmXy8l; Wed, 3 Aug 2011 15:12:35 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 31AEE9DEAB; - Wed, 3 Aug 2011 15:12:35 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B0D19D877F; + Mon, 21 Nov 2011 15:06:40 -0500 (EST) +Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 3jv-cDBpMP5B; Mon, 21 Nov 2011 15:06:40 -0500 (EST) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9C98DD8410; + Mon, 21 Nov 2011 15:06:40 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCRCZ008434; - Wed, 3 Aug 2011 15:12:28 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6cHF029573; + Mon, 21 Nov 2011 15:06:39 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:55 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:53 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:01:59 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:57 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 11/31] introduce wake_up_quiescent() -Message-ID: <20110803190953.GA30952@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 11/33] introduce wake_up_quiescent() +Message-ID: <20111121200157.GA27805@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO Content-Length: 3186 Lines: 93 @@ -4968,7 +4897,7 @@ index a822300..2be3712 100644 extern int do_send_sig_info(int sig, struct siginfo *info, struct task_struct *p, bool group); diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 56b8fc1..4194664 100644 +index daf47bc..8439ef1 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -621,7 +621,7 @@ static int ptrace_resume(struct task_struct *child, long request, @@ -4981,7 +4910,7 @@ index 56b8fc1..4194664 100644 } diff --git a/kernel/signal.c b/kernel/signal.c -index 71f5cca..3e8e0b1 100644 +index 4512bb4..99a6008 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -702,6 +702,14 @@ void signal_wake_up(struct task_struct *t, int resume) @@ -5008,7 +4937,7 @@ index 71f5cca..3e8e0b1 100644 else ptrace_trap_notify(t); } while_each_thread(p, t); -@@ -1879,7 +1887,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1887,7 +1895,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) do_notify_parent_cldstop(current, false, why); spin_lock_irq(¤t->sighand->siglock); @@ -5034,49 +4963,42 @@ index 5d3974e..cebc390 100644 1.5.5.1 -From davej Wed Aug 3 15:22:01 2011 +From oleg@redhat.com Mon Nov 21 15:06:43 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:22:01 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:17:15 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:43 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F2DE19DC07; - Wed, 3 Aug 2011 15:12:37 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id IYfqfx8GhNWc; Wed, 3 Aug 2011 15:12:37 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D645E9DAF7; - Wed, 3 Aug 2011 15:12:37 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6488BD514C; + Mon, 21 Nov 2011 15:06:43 -0500 (EST) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id TKQUj5mU4NYM; Mon, 21 Nov 2011 15:06:43 -0500 (EST) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4EC82D5000; + Mon, 21 Nov 2011 15:06:43 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCUNh008446; - Wed, 3 Aug 2011 15:12:31 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6fp6015343; + Mon, 21 Nov 2011 15:06:41 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:09:58 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:56 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:02 +0100 (CET) +Date: Mon, 21 Nov 2011 21:01:59 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 12/31] introduce ptrace_signal_wake_up() -Message-ID: <20110803190956.GA30959@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 12/33] introduce ptrace_signal_wake_up() +Message-ID: <20111121200159.GA27812@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO -Content-Length: 3667 +Content-Length: 3670 Lines: 113 Add the new helper, ptrace_signal_wake_up(), change ptrace.c/signal.c @@ -5118,7 +5040,7 @@ index 800f113..6d9282a 100644 extern long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data); diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 4194664..1a50090 100644 +index 8439ef1..a464ab5 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -25,6 +25,18 @@ @@ -5167,7 +5089,7 @@ index 4194664..1a50090 100644 unlock_task_sighand(child, &flags); ret = 0; -@@ -760,7 +772,7 @@ int ptrace_request(struct task_struct *child, long request, +@@ -757,7 +769,7 @@ int ptrace_request(struct task_struct *child, long request, * start of this trap and now. Trigger re-trap. */ if (child->jobctl & JOBCTL_TRAP_NOTIFY) @@ -5177,7 +5099,7 @@ index 4194664..1a50090 100644 } unlock_task_sighand(child, &flags); diff --git a/kernel/signal.c b/kernel/signal.c -index 3e8e0b1..0dc6abb 100644 +index 99a6008..7a47a93 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -854,7 +854,7 @@ static void ptrace_trap_notify(struct task_struct *t) @@ -5193,48 +5115,41 @@ index 3e8e0b1..0dc6abb 100644 1.5.5.1 -From davej Wed Aug 3 15:15:58 2011 +From oleg@redhat.com Mon Nov 21 15:06:46 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:15:58 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:13:17 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:46 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8FF88DA558; - Wed, 3 Aug 2011 15:12:40 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 3A7AED8410; + Mon, 21 Nov 2011 15:06:46 -0500 (EST) Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 1cOfIyuaRoO3; Wed, 3 Aug 2011 15:12:40 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7B6E8DA4A9; - Wed, 3 Aug 2011 15:12:40 -0400 (EDT) + with ESMTP id jhYAwDyYmdhg; Mon, 21 Nov 2011 15:06:46 -0500 (EST) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 25D5FD889A; + Mon, 21 Nov 2011 15:06:46 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCXpn023459; - Wed, 3 Aug 2011 15:12:33 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6h29029619; + Mon, 21 Nov 2011 15:06:44 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:01 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:09:59 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:04 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:02 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 13/31] wait_task_inactive: treat task->state and +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 13/33] wait_task_inactive: treat task->state and match_state as bitmasks -Message-ID: <20110803190959.GA30962@redhat.com> +Message-ID: <20111121200202.GA27816@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO Content-Length: 1558 Lines: 39 @@ -5263,10 +5178,10 @@ Signed-off-by: Oleg Nesterov 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c -index ccacdbd..66ef2fb 100644 +index 0e9344a..84ecc0a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c -@@ -2289,7 +2289,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) +@@ -2443,7 +2443,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) * is actually now running somewhere else! */ while (task_running(rq, p)) { @@ -5279,47 +5194,40 @@ index ccacdbd..66ef2fb 100644 1.5.5.1 -From davej Wed Aug 3 15:16:24 2011 +From oleg@redhat.com Mon Nov 21 15:06:48 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:24 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:21 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:48 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 34C189DC30; - Wed, 3 Aug 2011 15:12:43 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id RHggq6bqo+Q9; Wed, 3 Aug 2011 15:12:43 -0400 (EDT) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 210D59DC14; - Wed, 3 Aug 2011 15:12:43 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C2934D5000; + Mon, 21 Nov 2011 15:06:48 -0500 (EST) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id ThT2PyhztDpQ; Mon, 21 Nov 2011 15:06:48 -0500 (EST) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id ACE02D4F84; + Mon, 21 Nov 2011 15:06:48 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JCZsD022395; - Wed, 3 Aug 2011 15:12:36 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6kdb022201; + Mon, 21 Nov 2011 15:06:47 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:03 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:01 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:07 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:05 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 14/31] introduce TASK_UTRACED state -Message-ID: <20110803191001.GA30969@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 14/33] introduce TASK_UTRACED state +Message-ID: <20111121200205.GA27823@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO Content-Length: 2913 Lines: 84 @@ -5358,10 +5266,10 @@ index f0c0ea2..e0daec4 100644 static inline const char *get_task_state(struct task_struct *tsk) diff --git a/include/linux/sched.h b/include/linux/sched.h -index c6d79af..f3f0a77 100644 +index 4d45f93..746b4d3 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h -@@ -184,16 +184,17 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) +@@ -185,16 +185,17 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) #define TASK_UNINTERRUPTIBLE 2 #define __TASK_STOPPED 4 #define __TASK_TRACED 8 @@ -5386,7 +5294,7 @@ index c6d79af..f3f0a77 100644 extern char ___assert_task_state[1 - 2*!!( sizeof(TASK_STATE_TO_CHAR_STR)-1 != ilog2(TASK_STATE_MAX)+1)]; -@@ -202,15 +203,16 @@ extern char ___assert_task_state[1 - 2*!!( +@@ -203,15 +204,16 @@ extern char ___assert_task_state[1 - 2*!!( #define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE) #define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED) #define TASK_TRACED (TASK_WAKEKILL | __TASK_TRACED) @@ -5409,47 +5317,40 @@ index c6d79af..f3f0a77 100644 1.5.5.1 -From davej Wed Aug 3 15:16:02 2011 +From oleg@redhat.com Mon Nov 21 15:06:51 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:02 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:13:18 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:51 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D7FFADA44E; - Wed, 3 Aug 2011 15:12:45 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 48F35D889C; + Mon, 21 Nov 2011 15:06:51 -0500 (EST) Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id LFGdvSMswLJT; Wed, 3 Aug 2011 15:12:45 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BA46CDA441; - Wed, 3 Aug 2011 15:12:45 -0400 (EDT) + with ESMTP id ZXkDvXaDg0cN; Mon, 21 Nov 2011 15:06:51 -0500 (EST) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 34485D889A; + Mon, 21 Nov 2011 15:06:51 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCcpZ029424; - Wed, 3 Aug 2011 15:12:39 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6nlT022211; + Mon, 21 Nov 2011 15:06:49 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:06 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:04 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:09 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:08 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 15/31] utrace: use TASK_UTRACED instead of TASK_TRACED -Message-ID: <20110803191004.GA30972@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 15/33] utrace: use TASK_UTRACED instead of TASK_TRACED +Message-ID: <20111121200208.GA27826@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO Content-Length: 4316 Lines: 130 @@ -5585,48 +5486,41 @@ index cebc390..2097103 100644 1.5.5.1 -From davej Wed Aug 3 15:21:40 2011 +From oleg@redhat.com Mon Nov 21 15:06:53 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:21:40 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:42 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:53 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7035E9DECC; - Wed, 3 Aug 2011 15:12:48 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B8F54D5296; + Mon, 21 Nov 2011 15:06:53 -0500 (EST) Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id rmRalMQFlNua; Wed, 3 Aug 2011 15:12:48 -0400 (EDT) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5CC809DEC9; - Wed, 3 Aug 2011 15:12:48 -0400 (EDT) + with ESMTP id PX4Y3H1mw0hD; Mon, 21 Nov 2011 15:06:53 -0500 (EST) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A4B5CD528E; + Mon, 21 Nov 2011 15:06:53 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JCfwv010344; - Wed, 3 Aug 2011 15:12:41 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6pXd029643; + Mon, 21 Nov 2011 15:06:52 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:09 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:07 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:12 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:10 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 16/31] reintroduce tracehook_finish_jctl() as +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 16/33] reintroduce tracehook_finish_jctl() as utrace_end_stop() -Message-ID: <20110803191007.GA30979@redhat.com> +Message-ID: <20111121200210.GA27829@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO Content-Length: 2401 Lines: 77 @@ -5670,10 +5564,10 @@ index cf13839..0279c74 100644 + #endif /* linux/utrace.h */ diff --git a/kernel/signal.c b/kernel/signal.c -index 0dc6abb..a625309 100644 +index 7a47a93..ba46eab 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -1895,6 +1895,8 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1903,6 +1903,8 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) read_unlock(&tasklist_lock); } @@ -5682,7 +5576,7 @@ index 0dc6abb..a625309 100644 /* * While in TASK_TRACED, we were considered "frozen enough". * Now that we woke up, it's crucial if we're supposed to be -@@ -2059,6 +2061,9 @@ static bool do_signal_stop(int signr) +@@ -2067,6 +2069,9 @@ static bool do_signal_stop(int signr) /* Now we don't run again until woken by SIGCONT or SIGKILL */ schedule(); @@ -5709,47 +5603,40 @@ index 2097103..d41b982 100644 1.5.5.1 -From davej Wed Aug 3 15:21:41 2011 +From oleg@redhat.com Mon Nov 21 15:06:56 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:21:41 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:42 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:56 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 153719DD18; - Wed, 3 Aug 2011 15:12:51 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id ffM0oM8RRtgL; Wed, 3 Aug 2011 15:12:51 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 0253E9DEC9; - Wed, 3 Aug 2011 15:12:51 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4A487D83A1; + Mon, 21 Nov 2011 15:06:56 -0500 (EST) +Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 3vHogPyhojlJ; Mon, 21 Nov 2011 15:06:56 -0500 (EST) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 358A0D88B0; + Mon, 21 Nov 2011 15:06:56 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCh9Z023559; - Wed, 3 Aug 2011 15:12:44 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6sHk017679; + Mon, 21 Nov 2011 15:06:54 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:11 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:09 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:14 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:12 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 17/31] teach wake_up_quiescent() to do "selective" wake_up -Message-ID: <20110803191009.GA30982@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 17/33] teach wake_up_quiescent() to do "selective" wake_up +Message-ID: <20111121200212.GA27836@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO Content-Length: 1335 Lines: 46 @@ -5767,7 +5654,7 @@ Signed-off-by: Oleg Nesterov 1 files changed, 15 insertions(+), 0 deletions(-) diff --git a/kernel/signal.c b/kernel/signal.c -index a625309..0d1675a 100644 +index ba46eab..e06f795 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -701,11 +701,26 @@ void signal_wake_up(struct task_struct *t, int resume) @@ -5801,48 +5688,41 @@ index a625309..0d1675a 100644 1.5.5.1 -From davej Wed Aug 3 15:21:43 2011 +From oleg@redhat.com Mon Nov 21 15:06:59 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:21:43 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:43 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:06:58 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B0E899DECF; - Wed, 3 Aug 2011 15:12:53 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C88E2D528B; + Mon, 21 Nov 2011 15:06:58 -0500 (EST) Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id s0bDFhAmsQWN; Wed, 3 Aug 2011 15:12:53 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9DC6E9DEC9; - Wed, 3 Aug 2011 15:12:53 -0400 (EDT) + with ESMTP id nNrAxBD5KOME; Mon, 21 Nov 2011 15:06:58 -0500 (EST) +Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B2114D51C1; + Mon, 21 Nov 2011 15:06:58 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCkUr029453; - Wed, 3 Aug 2011 15:12:46 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6uQQ031440; + Mon, 21 Nov 2011 15:06:57 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:14 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:12 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:17 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:15 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 18/31] ptrace_stop: do not assume the task is running after +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 18/33] ptrace_stop: do not assume the task is running after wake_up_quiescent() -Message-ID: <20110803191012.GA30985@redhat.com> +Message-ID: <20111121200215.GA27839@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO Content-Length: 956 Lines: 31 @@ -5857,10 +5737,10 @@ Signed-off-by: Oleg Nesterov 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/kernel/signal.c b/kernel/signal.c -index 0d1675a..249760f 100644 +index e06f795..9348da6 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -1908,6 +1908,14 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1916,6 +1916,14 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) if (clear_code) current->exit_code = 0; read_unlock(&tasklist_lock); @@ -5879,48 +5759,41 @@ index 0d1675a..249760f 100644 1.5.5.1 -From davej Wed Aug 3 15:16:26 2011 +From oleg@redhat.com Mon Nov 21 15:07:01 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:26 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:22 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:01 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 69B489DC62; - Wed, 3 Aug 2011 15:12:56 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 4BNNeoYSdCTc; Wed, 3 Aug 2011 15:12:56 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4A9899DC14; - Wed, 3 Aug 2011 15:12:56 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4BF37D889A; + Mon, 21 Nov 2011 15:07:01 -0500 (EST) +Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 5p8tvlXAqUHr; Mon, 21 Nov 2011 15:07:01 -0500 (EST) +Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 37C22D8757; + Mon, 21 Nov 2011 15:07:01 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCnRf023575; - Wed, 3 Aug 2011 15:12:49 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6xFJ031449; + Mon, 21 Nov 2011 15:06:59 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:16 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:14 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:19 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:18 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 19/31] get_signal_to_deliver: restore/restructure +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 19/33] get_signal_to_deliver: restore/restructure utrace/ptrace signal reporting -Message-ID: <20110803191014.GA30992@redhat.com> +Message-ID: <20111121200218.GA27846@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO Content-Length: 3556 Lines: 115 @@ -5986,10 +5859,10 @@ index 0279c74..63103e2 100644 + #endif /* linux/utrace.h */ diff --git a/kernel/signal.c b/kernel/signal.c -index 249760f..3c783d3 100644 +index 9348da6..38ea4e6 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -2234,17 +2234,27 @@ relock: +@@ -2242,17 +2242,27 @@ relock: for (;;) { struct k_sigaction *ka; @@ -6025,7 +5898,7 @@ index 249760f..3c783d3 100644 if (!signr) break; /* will return 0 */ -@@ -2254,9 +2264,9 @@ relock: +@@ -2262,9 +2272,9 @@ relock: regs, cookie); if (!signr) continue; @@ -6041,46 +5914,39 @@ index 249760f..3c783d3 100644 1.5.5.1 -From davej Wed Aug 3 15:16:27 2011 +From oleg@redhat.com Mon Nov 21 15:07:03 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:27 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:22 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:03 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 119589DC72; - Wed, 3 Aug 2011 15:12:59 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id Vxp8fnt8hEcf; Wed, 3 Aug 2011 15:12:59 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id CB362D89E9; + Mon, 21 Nov 2011 15:07:03 -0500 (EST) +Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id wm2JqccPnhsV; Mon, 21 Nov 2011 15:07:03 -0500 (EST) Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F22049DCAE; - Wed, 3 Aug 2011 15:12:58 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B6D25D89DE; + Mon, 21 Nov 2011 15:07:03 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JCpO4010401; - Wed, 3 Aug 2011 15:12:52 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK715f031455; + Mon, 21 Nov 2011 15:07:02 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:19 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:17 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:22 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:20 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 20/31] utrace_get_signal: +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 20/33] utrace_get_signal: s/JOBCTL_STOP_PENDING/JOBCTL_PENDING_MASK/ -Message-ID: <20110803191017.GA30995@redhat.com> +Message-ID: <20111121200220.GA27849@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO @@ -6121,47 +5987,40 @@ index d41b982..0bb0a06 100644 1.5.5.1 -From davej Wed Aug 3 15:16:03 2011 +From oleg@redhat.com Mon Nov 21 15:07:07 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:03 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:13:19 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:06 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A9253DA3CB; - Wed, 3 Aug 2011 15:13:01 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id HLlRhTJ2MbYS; Wed, 3 Aug 2011 15:13:01 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9582C4C43B; - Wed, 3 Aug 2011 15:13:01 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8C14BD4F84; + Mon, 21 Nov 2011 15:07:06 -0500 (EST) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 39eM-KKZxrZ3; Mon, 21 Nov 2011 15:07:06 -0500 (EST) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7628FD4FF4; + Mon, 21 Nov 2011 15:07:06 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCsFX008586; - Wed, 3 Aug 2011 15:12:54 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK74dN022253; + Mon, 21 Nov 2011 15:07:04 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:22 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:20 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:25 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:23 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 21/31] introduce ptrace_set_syscall_trace() -Message-ID: <20110803191020.GA31002@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 21/33] introduce ptrace_set_syscall_trace() +Message-ID: <20111121200223.GA27856@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO Content-Length: 1549 Lines: 52 @@ -6176,7 +6035,7 @@ Signed-off-by: Oleg Nesterov 1 files changed, 10 insertions(+), 5 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 1a50090..dc2ad34 100644 +index a464ab5..43357e5 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -38,6 +38,14 @@ void ptrace_signal_wake_up(struct task_struct *p, int quiescent) @@ -6219,47 +6078,40 @@ index 1a50090..dc2ad34 100644 1.5.5.1 -From davej Wed Aug 3 15:21:45 2011 +From oleg@redhat.com Mon Nov 21 15:07:09 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:21:45 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:43 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:09 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5C4889DEE6; - Wed, 3 Aug 2011 15:13:04 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id eXIPU4nVv+7Z; Wed, 3 Aug 2011 15:13:04 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 3F82C9DED6; - Wed, 3 Aug 2011 15:13:04 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1ADF01285E4; + Mon, 21 Nov 2011 15:07:09 -0500 (EST) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id rF+XegsxVXnL; Mon, 21 Nov 2011 15:07:09 -0500 (EST) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 067E41287D0; + Mon, 21 Nov 2011 15:07:09 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCueo029507; - Wed, 3 Aug 2011 15:12:57 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK76tD022270; + Mon, 21 Nov 2011 15:07:07 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:24 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:22 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:27 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:25 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 22/31] introduce PT_SYSCALL_TRACE flag -Message-ID: <20110803191022.GA31005@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 22/33] introduce PT_SYSCALL_TRACE flag +Message-ID: <20111121200225.GA27860@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO Content-Length: 2268 Lines: 73 @@ -6315,7 +6167,7 @@ index ec2af67..eb9fe30 100644 ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index dc2ad34..7deb292 100644 +index 43357e5..1ac03eb 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -40,10 +40,13 @@ void ptrace_signal_wake_up(struct task_struct *p, int quiescent) @@ -6338,48 +6190,41 @@ index dc2ad34..7deb292 100644 1.5.5.1 -From davej Wed Aug 3 15:16:05 2011 +From oleg@redhat.com Mon Nov 21 15:07:11 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:05 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:13:20 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:11 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E516ADA488; - Wed, 3 Aug 2011 15:13:06 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id rP7Um8DZjclX; Wed, 3 Aug 2011 15:13:06 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D155EDA3F8; - Wed, 3 Aug 2011 15:13:06 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B7D62D4DCC; + Mon, 21 Nov 2011 15:07:11 -0500 (EST) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 1ENpGO166I-W; Mon, 21 Nov 2011 15:07:11 -0500 (EST) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A3A55D498A; + Mon, 21 Nov 2011 15:07:11 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JCxfF029532; - Wed, 3 Aug 2011 15:13:00 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK79AS017728; + Mon, 21 Nov 2011 15:07:10 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:27 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:25 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:30 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:28 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 23/31] utrace: don't clear TIF_SYSCALL_TRACE if it is +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 23/33] utrace: don't clear TIF_SYSCALL_TRACE if it is needed by ptrace -Message-ID: <20110803191025.GA31012@redhat.com> +Message-ID: <20111121200228.GA27863@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO Content-Length: 797 Lines: 24 @@ -6409,47 +6254,40 @@ index 0bb0a06..bebf6de 100644 1.5.5.1 -From davej Wed Aug 3 15:16:08 2011 +From oleg@redhat.com Mon Nov 21 15:07:14 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:08 -0400 (EDT) Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:15:29 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:14 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 80872DA4B2; - Wed, 3 Aug 2011 15:13:09 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5376AD8774; + Mon, 21 Nov 2011 15:07:14 -0500 (EST) Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id AbpC0Wk1ZhtT; Wed, 3 Aug 2011 15:13:09 -0400 (EDT) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6D97DDA3F8; - Wed, 3 Aug 2011 15:13:09 -0400 (EDT) + with ESMTP id 5Oc8ErfFfJSs; Mon, 21 Nov 2011 15:07:14 -0500 (EST) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 3F2CFD81E9; + Mon, 21 Nov 2011 15:07:14 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JD2RU022591; - Wed, 3 Aug 2011 15:13:02 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7Cw3015467; + Mon, 21 Nov 2011 15:07:12 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:30 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:28 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:32 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:30 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 24/31] introduce task_utrace_lock/task_utrace_unlock -Message-ID: <20110803191028.GA31015@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 24/33] introduce task_utrace_lock/task_utrace_unlock +Message-ID: <20111121200230.GA27870@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO Content-Length: 2190 Lines: 81 @@ -6536,48 +6374,41 @@ index bebf6de..960dd9e 100644 1.5.5.1 -From davej Wed Aug 3 15:21:46 2011 +From oleg@redhat.com Mon Nov 21 15:07:17 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:21:46 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:43 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:17 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 24B3E9DEF6; - Wed, 3 Aug 2011 15:13:12 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 01034D498A; + Mon, 21 Nov 2011 15:07:17 -0500 (EST) Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 2jg9j3-p4bHL; Wed, 3 Aug 2011 15:13:12 -0400 (EDT) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 119759DEF9; - Wed, 3 Aug 2011 15:13:12 -0400 (EDT) + with ESMTP id BglmrU3H2hJr; Mon, 21 Nov 2011 15:07:16 -0500 (EST) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E0D31D4FF4; + Mon, 21 Nov 2011 15:07:16 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JD485022603; - Wed, 3 Aug 2011 15:13:05 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7Egx015474; + Mon, 21 Nov 2011 15:07:15 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:32 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:30 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:35 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:33 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 25/31] teach ptrace_set_syscall_trace() to play well with +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 25/33] teach ptrace_set_syscall_trace() to play well with utrace -Message-ID: <20110803191030.GA31018@redhat.com> +Message-ID: <20111121200233.GA27873@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO Content-Length: 1545 Lines: 49 @@ -6599,7 +6430,7 @@ Signed-off-by: Oleg Nesterov 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 7deb292..69850e9 100644 +index 1ac03eb..739183a 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -24,6 +24,7 @@ @@ -6632,45 +6463,38 @@ index 7deb292..69850e9 100644 1.5.5.1 -From davej Wed Aug 3 15:16:29 2011 +From oleg@redhat.com Mon Nov 21 15:07:19 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:28 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:24 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:19 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 062709DE55; - Wed, 3 Aug 2011 15:13:15 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8F87F128EAA; + Mon, 21 Nov 2011 15:07:19 -0500 (EST) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id lhwVoEywGaPJ; Wed, 3 Aug 2011 15:13:14 -0400 (EDT) + with ESMTP id yittEjCd+X4F; Mon, 21 Nov 2011 15:07:19 -0500 (EST) Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E4C139DE11; - Wed, 3 Aug 2011 15:13:14 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7BC701287D0; + Mon, 21 Nov 2011 15:07:19 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JD7Go010523; - Wed, 3 Aug 2011 15:13:08 -0400 + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK7HbH031553; + Mon, 21 Nov 2011 15:07:18 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:35 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:33 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:38 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:36 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 26/31] introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK -Message-ID: <20110803191033.GA31025@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 26/33] introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK +Message-ID: <20111121200236.GA27880@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Status: RO @@ -6762,7 +6586,7 @@ index eb9fe30..21c8ca2 100644 } diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 69850e9..d250a71 100644 +index 739183a..792080d 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -630,13 +630,16 @@ static int ptrace_resume(struct task_struct *child, long request, @@ -6786,48 +6610,41 @@ index 69850e9..d250a71 100644 1.5.5.1 -From davej Wed Aug 3 15:16:30 2011 +From oleg@redhat.com Mon Nov 21 15:07:22 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:30 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:25 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:22 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B3BF49DE11; - Wed, 3 Aug 2011 15:13:17 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 0C136128FB0; + Mon, 21 Nov 2011 15:07:22 -0500 (EST) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id zC72ecV9Jz07; Wed, 3 Aug 2011 15:13:17 -0400 (EDT) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 98ACE9DE59; - Wed, 3 Aug 2011 15:13:17 -0400 (EDT) + with ESMTP id GNbS20gY5Jq9; Mon, 21 Nov 2011 15:07:21 -0500 (EST) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id EB5821287D0; + Mon, 21 Nov 2011 15:07:21 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JDATh023726; - Wed, 3 Aug 2011 15:13:10 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK7Kn1029766; + Mon, 21 Nov 2011 15:07:20 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:38 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:36 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:40 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:38 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 27/31] utrace: finish_resume_report: don't do +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 27/33] utrace: finish_resume_report: don't do user_xxx_step() if ptrace_wants_step() -Message-ID: <20110803191036.GA31028@redhat.com> +Message-ID: <20111121200238.GA27883@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO Content-Length: 2741 Lines: 84 @@ -6917,48 +6734,41 @@ index 960dd9e..05e8532 100644 1.5.5.1 -From davej Wed Aug 3 15:16:32 2011 +From oleg@redhat.com Mon Nov 21 15:07:24 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:32 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:25 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:24 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 614CD9DE73; - Wed, 3 Aug 2011 15:13:20 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8954F12914D; + Mon, 21 Nov 2011 15:07:24 -0500 (EST) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id jcWOXzUaaIYu; Wed, 3 Aug 2011 15:13:20 -0400 (EDT) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 438889DE59; - Wed, 3 Aug 2011 15:13:20 -0400 (EDT) + with ESMTP id 0lU8wXKC78yu; Mon, 21 Nov 2011 15:07:24 -0500 (EST) +Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 759B61287D0; + Mon, 21 Nov 2011 15:07:24 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JDDZ7029595; - Wed, 3 Aug 2011 15:13:13 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7Mi7022329; + Mon, 21 Nov 2011 15:07:23 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:40 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:38 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:43 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:41 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 28/31] ptrace: shift user_*_step() from ptrace_resume() to +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 28/33] ptrace: shift user_*_step() from ptrace_resume() to ptrace_stop() -Message-ID: <20110803191038.GA31035@redhat.com> +Message-ID: <20111121200241.GA27890@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO Content-Length: 2374 Lines: 70 @@ -6990,7 +6800,7 @@ Signed-off-by: Oleg Nesterov 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index d250a71..d1ef124 100644 +index 792080d..eba9a22 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -635,14 +635,10 @@ static int ptrace_resume(struct task_struct *child, long request, @@ -7009,10 +6819,10 @@ index d250a71..d1ef124 100644 child->exit_code = data; diff --git a/kernel/signal.c b/kernel/signal.c -index 3c783d3..43a3e77 100644 +index 38ea4e6..b13d2bc 100644 --- a/kernel/signal.c +++ b/kernel/signal.c -@@ -1920,6 +1920,17 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +@@ -1928,6 +1928,17 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) utrace_end_stop(); @@ -7034,45 +6844,38 @@ index 3c783d3..43a3e77 100644 1.5.5.1 -From davej Wed Aug 3 15:16:34 2011 +From oleg@redhat.com Mon Nov 21 15:07:27 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:16:34 -0400 (EDT) Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:25 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:27 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1A6019DE59; - Wed, 3 Aug 2011 15:13:23 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 043581287D0; + Mon, 21 Nov 2011 15:07:27 -0500 (EST) Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id db2hhAqFwsPu; Wed, 3 Aug 2011 15:13:23 -0400 (EDT) + with ESMTP id 4WO1El1jiIrJ; Mon, 21 Nov 2011 15:07:26 -0500 (EST) Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 034739DE83; - Wed, 3 Aug 2011 15:13:23 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E3FCA129045; + Mon, 21 Nov 2011 15:07:26 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JDFNp008715; - Wed, 3 Aug 2011 15:13:16 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7OdV017836; + Mon, 21 Nov 2011 15:07:25 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:43 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:41 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:45 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:43 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 29/31] ptrace_disable: no need to disable stepping -Message-ID: <20110803191041.GA31039@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 29/33] ptrace_disable: no need to disable stepping +Message-ID: <20111121200243.GA27893@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO @@ -7109,47 +6912,40 @@ index d1557dc..96d315a 100644 1.5.5.1 -From davej Wed Aug 3 15:21:48 2011 +From oleg@redhat.com Mon Nov 21 15:07:29 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:21:48 -0400 (EDT) Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:52 -0400 (EDT) + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:29 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 95706917AF; - Wed, 3 Aug 2011 15:13:25 -0400 (EDT) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8A6E8D4C39; + Mon, 21 Nov 2011 15:07:29 -0500 (EST) Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id ctq4DF3wXncJ; Wed, 3 Aug 2011 15:13:25 -0400 (EDT) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7FD14914AF; - Wed, 3 Aug 2011 15:13:25 -0400 (EDT) + with ESMTP id NLURBx2yQes5; Mon, 21 Nov 2011 15:07:29 -0500 (EST) +Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7660DD498A; + Mon, 21 Nov 2011 15:07:29 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p73JDIRO010579; - Wed, 3 Aug 2011 15:13:18 -0400 + by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7RnP015578; + Mon, 21 Nov 2011 15:07:27 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:46 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:44 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:48 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:46 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 30/31] ptrace_report_syscall: check TIF_SYSCALL_EMU -Message-ID: <20110803191044.GA31046@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 30/33] ptrace_report_syscall: check TIF_SYSCALL_EMU +Message-ID: <20111121200246.GA27896@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Status: RO Content-Length: 858 Lines: 28 @@ -7183,46 +6979,39 @@ index b6812d4..90ca578 100644 1.5.5.1 -From davej Wed Aug 3 15:21:49 2011 +From oleg@redhat.com Mon Nov 21 15:07:32 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Wed, 03 Aug 2011 15:21:49 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Wed, 3 Aug 2011 15:16:52 -0400 (EDT) +Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO + zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:32 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 400F49191F; - Wed, 3 Aug 2011 15:13:28 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id UeLOLM29JRc7; Wed, 3 Aug 2011 15:13:28 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 10D1312916C; + Mon, 21 Nov 2011 15:07:32 -0500 (EST) +Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id Z14plX1oxaYL; Mon, 21 Nov 2011 15:07:32 -0500 (EST) Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2D05C903F6; - Wed, 3 Aug 2011 15:13:28 -0400 (EDT) + by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F12FF128E1D; + Mon, 21 Nov 2011 15:07:31 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id p73JDKCA023784; - Wed, 3 Aug 2011 15:13:21 -0400 + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7T0q022460; + Mon, 21 Nov 2011 15:07:30 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 3 Aug 2011 21:10:48 +0200 (CEST) -Date: Wed, 3 Aug 2011 21:10:46 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:50 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:48 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH 31/31] utrace_resume: check irqs_disabled() to shut up +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 31/33] utrace_resume: check irqs_disabled() to shut up lockdep -Message-ID: <20110803191046.GA31049@redhat.com> +Message-ID: <20111121200248.GA27903@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Status: RO @@ -7256,49 +7045,41 @@ index 05e8532..c817a46 100644 1.5.5.1 -From davej Tue Aug 9 13:39:54 2011 +From oleg@redhat.com Mon Nov 21 15:07:34 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.51] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Tue, 09 Aug 2011 13:39:54 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - mail04.corp.redhat.com with LMTP; Tue, 9 Aug 2011 13:39:44 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:34 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5FCAC12983C; - Tue, 9 Aug 2011 13:39:44 -0400 (EDT) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id nDWbqog6fbHK; Tue, 9 Aug 2011 13:39:44 -0400 (EDT) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4BEF712983B; - Tue, 9 Aug 2011 13:39:44 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 860BCD8A3E; + Mon, 21 Nov 2011 15:07:34 -0500 (EST) +Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id pVTbN1oF62dg; Mon, 21 Nov 2011 15:07:34 -0500 (EST) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6FBFFD87A3; + Mon, 21 Nov 2011 15:07:34 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p79HdahY022801; - Tue, 9 Aug 2011 13:39:37 -0400 + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK7W0B029871; + Mon, 21 Nov 2011 15:07:32 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Tue, 9 Aug 2011 19:36:58 +0200 (CEST) -Date: Tue, 9 Aug 2011 19:36:56 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:53 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:51 +0100 From: Oleg Nesterov To: Dave Jones , "Frank Ch. Eigler" , Josh Boyer , Josh Stone , Kyle McMartin -Cc: kernel@lists.fedoraproject.org, utrace-devel@redhat.com -Subject: [PATCH utrace-3.1 32/31] ptrace_report_syscall: check if - TIF_SYSCALL_EMU is defined -Message-ID: <20110809173656.GC26443@redhat.com> -References: <20110802174514.GA23073@redhat.com> <20110803190806.GA30619@redhat.com> +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 32/33] ptrace_report_syscall: check if TIF_SYSCALL_EMU is + defined +Message-ID: <20111121200251.GA27906@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -In-Reply-To: <20110803190806.GA30619@redhat.com> +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Status: RO Content-Length: 839 Lines: 31 @@ -7335,50 +7116,43 @@ index 90ca578..a1bac95 100644 1.5.5.1 -From davej Thu Sep 1 14:14:49 2011 +From oleg@redhat.com Mon Nov 21 15:07:37 2011 Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk with IMAP (fetchmail-6.3.20) - for (single-drop); Thu, 01 Sep 2011 14:14:49 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail04.corp.redhat.com with LMTP; Thu, 1 Sep 2011 14:13:55 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 + 15:07:37 -0500 (EST) Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1BA199C63F; - Thu, 1 Sep 2011 14:13:55 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 0vQx9zlcQB36; Thu, 1 Sep 2011 14:13:55 -0400 (EDT) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 009959C63D; - Thu, 1 Sep 2011 14:13:55 -0400 (EDT) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 33405D8A50; + Mon, 21 Nov 2011 15:07:37 -0500 (EST) +Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 3WH8FhvizjEA; Mon, 21 Nov 2011 15:07:37 -0500 (EST) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1274FD89BB; + Mon, 21 Nov 2011 15:07:37 -0500 (EST) Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p81IDrDX015389; - Thu, 1 Sep 2011 14:13:54 -0400 + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7YHr017898; + Mon, 21 Nov 2011 15:07:35 -0500 Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Thu, 1 Sep 2011 20:10:54 +0200 (CEST) -Date: Thu, 1 Sep 2011 20:10:53 +0200 + oleg@redhat.com; Mon, 21 Nov 2011 21:02:55 +0100 (CET) +Date: Mon, 21 Nov 2011 21:02:53 +0100 From: Oleg Nesterov -To: Dave Jones -Cc: kernel@lists.fedoraproject.org, cebbert@redhat.com -Subject: [PATCH F-16] bz735118: utrace: s390: fix the compile problem with - traps.c -Message-ID: <20110901181053.GA24990@redhat.com> +To: Dave Jones , "Frank Ch. Eigler" , + Josh Boyer , Josh Stone , + Kyle McMartin +Cc: kernel@lists.fedoraproject.org +Subject: [PATCH 33/33] utrace: s390: fix the compile problem with traps.c +Message-ID: <20111121200253.GA27913@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline +In-Reply-To: <20111121200039.GA27699@redhat.com> User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Status: RO -Content-Length: 777 -Lines: 27 - -https://bugzilla.redhat.com/show_bug.cgi?id=735118 +Content-Length: 725 +Lines: 25 d99e60e5 "tracehooks: reintroduce tracehook_consider_fatal_signal()" breaks the compilation of arch/s390/kernel/traps.c. Restore the @@ -7390,7 +7164,7 @@ Signed-off-by: Oleg Nesterov 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c -index 1018ab6..50e975d 100644 +index f506e1b..3132498 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -18,7 +18,7 @@ diff --git a/x86-code-dump-fix-truncation.patch b/x86-code-dump-fix-truncation.patch deleted file mode 100644 index dcd5a815c..000000000 --- a/x86-code-dump-fix-truncation.patch +++ /dev/null @@ -1,73 +0,0 @@ -From: Clemens Ladisch -Date: Mon, 19 Dec 2011 21:07:58 +0000 (+0100) -Subject: x86, dumpstack: Fix code bytes breakage due to missing KERN_CONT -X-Git-Url: https://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftip%2Ftip.git;a=commitdiff_plain;h=13f541c10b30fc6529200d7f9a0073217709622f - -x86, dumpstack: Fix code bytes breakage due to missing KERN_CONT - -When printing the code bytes in show_registers(), the markers around the -byte at the fault address could make the printk() format string look -like a valid log level and facility code. This would prevent this byte -from being printed and result in a spurious newline: - -[ 7555.765589] Code: 8b 32 e9 94 00 00 00 81 7d 00 ff 00 00 00 0f 87 96 00 00 00 48 8b 83 c0 00 00 00 44 89 e2 44 89 e6 48 89 df 48 8b 80 d8 02 00 00 -[ 7555.765683] 8b 48 28 48 89 d0 81 e2 ff 0f 00 00 48 c1 e8 0c 48 c1 e0 04 - -Add KERN_CONT where needed, and elsewhere in show_registers() for -consistency. - -Signed-off-by: Clemens Ladisch -Link: http://lkml.kernel.org/r/4EEFA7AE.9020407@ladisch.de -Signed-off-by: H. Peter Anvin ---- - -diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c -index 3b97a80..c99f9ed 100644 ---- a/arch/x86/kernel/dumpstack_32.c -+++ b/arch/x86/kernel/dumpstack_32.c -@@ -116,16 +116,16 @@ void show_registers(struct pt_regs *regs) - for (i = 0; i < code_len; i++, ip++) { - if (ip < (u8 *)PAGE_OFFSET || - probe_kernel_address(ip, c)) { -- printk(" Bad EIP value."); -+ printk(KERN_CONT " Bad EIP value."); - break; - } - if (ip == (u8 *)regs->ip) -- printk("<%02x> ", c); -+ printk(KERN_CONT "<%02x> ", c); - else -- printk("%02x ", c); -+ printk(KERN_CONT "%02x ", c); - } - } -- printk("\n"); -+ printk(KERN_CONT "\n"); - } - - int is_valid_bugaddr(unsigned long ip) -diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c -index 19853ad..6d728d9 100644 ---- a/arch/x86/kernel/dumpstack_64.c -+++ b/arch/x86/kernel/dumpstack_64.c -@@ -284,16 +284,16 @@ void show_registers(struct pt_regs *regs) - for (i = 0; i < code_len; i++, ip++) { - if (ip < (u8 *)PAGE_OFFSET || - probe_kernel_address(ip, c)) { -- printk(" Bad RIP value."); -+ printk(KERN_CONT " Bad RIP value."); - break; - } - if (ip == (u8 *)regs->ip) -- printk("<%02x> ", c); -+ printk(KERN_CONT "<%02x> ", c); - else -- printk("%02x ", c); -+ printk(KERN_CONT "%02x ", c); - } - } -- printk("\n"); -+ printk(KERN_CONT "\n"); - } - - int is_valid_bugaddr(unsigned long ip) From e520b1ec1d5c4bab6440f0d4016e989b92d54e6b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 20 Jan 2012 09:33:43 -0500 Subject: [PATCH 231/487] Put patches in numerical order again Josh's brain can't cope with random ordering. FIGHT THE CHAOS. --- kernel.spec | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/kernel.spec b/kernel.spec index 1d03eda7a..cb52b690b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -759,20 +759,6 @@ Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch Patch21022: mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch -#rhbz752176 -Patch21080: sysfs-msi-irq-per-device.patch - - -# rhbz 754907 -Patch21101: hpsa-add-irqf-shared.patch - -#rhbz 731365 -Patch21220: mac80211_offchannel_rework_revert.patch - -Patch21225: pci-Rework-ASPM-disable-code.patch - -Patch21226: pci-crs-blacklist.patch - #rhbz 717735 Patch21045: nfs-client-freezer.patch @@ -792,19 +778,12 @@ Patch21072: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch Patch21073: KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch Patch21074: KVM-x86-fix-missing-checks-in-syscall-emulation.patch - -# compat-wireless patches -Patch50000: compat-wireless-config-fixups.patch -Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch -Patch50002: compat-wireless-pr_fmt-warning-avoidance.patch -Patch50003: compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch - -#rhbz 771058 -Patch22100: msi-irq-sysfs-warning.patch - #rhbz 728740 Patch21076: rtl8192cu-Fix-WARNING-on-suspend-resume.patch +#rhbz752176 +Patch21080: sysfs-msi-irq-per-device.patch + #rhbz 782686 Patch21082: procfs-parse-mount-options.patch Patch21083: procfs-add-hidepid-and-gid-mount-options.patch @@ -813,6 +792,25 @@ Patch21084: proc-fix-null-pointer-deref-in-proc_pid_permission.patch #rhbz 782681 Patch21085: proc-clean-up-and-fix-proc-pid-mem-handling.patch +#rhbz 771058 +Patch22100: msi-irq-sysfs-warning.patch + +# rhbz 754907 +Patch21101: hpsa-add-irqf-shared.patch + +#rhbz 731365 +Patch21220: mac80211_offchannel_rework_revert.patch + +Patch21225: pci-Rework-ASPM-disable-code.patch + +Patch21226: pci-crs-blacklist.patch + +# compat-wireless patches +Patch50000: compat-wireless-config-fixups.patch +Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch +Patch50002: compat-wireless-pr_fmt-warning-avoidance.patch +Patch50003: compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root From 030861b3417fde77f6a8c3710dbbaa8dbdcaf9ad Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 20 Jan 2012 09:38:57 -0500 Subject: [PATCH 232/487] Add mac80211 deauth fix pointed out by Stanislaw Gruszka --- kernel.spec | 10 +- ...1-fix-work-removal-on-deauth-request.patch | 154 ++++++++++++++++++ 2 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 mac80211-fix-work-removal-on-deauth-request.patch diff --git a/kernel.spec b/kernel.spec index cb52b690b..8abd851b8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -805,6 +805,8 @@ Patch21225: pci-Rework-ASPM-disable-code.patch Patch21226: pci-crs-blacklist.patch +Patch21227: mac80211-fix-work-removal-on-deauth-request.patch + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch @@ -1489,6 +1491,8 @@ ApplyPatch proc-fix-null-pointer-deref-in-proc_pid_permission.patch #rhbz 782681 ApplyPatch proc-clean-up-and-fix-proc-pid-mem-handling.patch +ApplyPatch mac80211-fix-work-removal-on-deauth-request.patch + # END OF PATCH APPLICATIONS %endif @@ -1556,6 +1560,7 @@ ApplyPatch compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch ApplyPatch compat-wireless-pr_fmt-warning-avoidance.patch ApplyPatch compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch ApplyPatch mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch +ApplyPatch mac80211-fix-work-removal-on-deauth-request.patch #rhbz 731365, 773271 ApplyPatch mac80211_offchannel_rework_revert.patch @@ -2264,6 +2269,9 @@ fi # and build. %changelog +* Fri Jan 20 2012 Josh Boyer +- Add mac80211 deauth fix pointed out by Stanislaw Gruszka + * Thu Jan 19 2012 Dave Jones 3.2.1-1 - Rebase to Linux 3.2.1 diff --git a/mac80211-fix-work-removal-on-deauth-request.patch b/mac80211-fix-work-removal-on-deauth-request.patch new file mode 100644 index 000000000..60b91d3cf --- /dev/null +++ b/mac80211-fix-work-removal-on-deauth-request.patch @@ -0,0 +1,154 @@ +Path: news.gmane.org!not-for-mail +From: Johannes Berg +Newsgroups: gmane.linux.kernel.wireless.general +Subject: [PATCH 3.3] mac80211: fix work removal on deauth request +Date: Wed, 18 Jan 2012 14:10:25 +0100 +Lines: 107 +Approved: news@gmane.org +Message-ID: <1326892225.4778.5.camel@jlt3.sipsolutions.net> +NNTP-Posting-Host: lo.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 7bit +X-Trace: dough.gmane.org 1326892249 18013 80.91.229.12 (18 Jan 2012 13:10:49 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Wed, 18 Jan 2012 13:10:49 +0000 (UTC) +Cc: linux-wireless , + Pontus Fuchs +To: John Linville +Original-X-From: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Wed Jan 18 14:10:44 2012 +Return-path: +Envelope-to: glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1RnVHo-00044l-Aq + for glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Wed, 18 Jan 2012 14:10:44 +0100 +Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand + id S1757410Ab2ARNK3 (ORCPT + ); + Wed, 18 Jan 2012 08:10:29 -0500 +Original-Received: from he.sipsolutions.net ([78.46.109.217]:45023 "EHLO + sipsolutions.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1754365Ab2ARNK2 (ORCPT + ); + Wed, 18 Jan 2012 08:10:28 -0500 +Original-Received: by sipsolutions.net with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) + (Exim 4.77) + (envelope-from ) + id 1RnVHW-0004hf-Lx; Wed, 18 Jan 2012 14:10:26 +0100 +X-Mailer: Evolution 2.30.3 +Original-Sender: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Xref: news.gmane.org gmane.linux.kernel.wireless.general:84095 +Archived-At: + +From: Johannes Berg + +When deauth is requested while an auth or assoc +work item is in progress, we currently delete it +without regard for any state it might need to +clean up. Fix it by cleaning up for those items. + +In the case Pontus found, the problem manifested +itself as such: + +authenticate with 00:23:69:aa:dd:7b (try 1) +authenticated +failed to insert Dummy STA entry for the AP (error -17) +deauthenticating from 00:23:69:aa:dd:7b by local choice (reason=2) + +It could also happen differently if the driver +uses the tx_sync callback. + +We can't just call the ->done() method of the work +items because that will lock up due to the locking +in cfg80211. This fix isn't very clean, but that +seems acceptable since I have patches pending to +remove this code completely. + +Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Reported-by: Pontus Fuchs +Tested-by: Pontus Fuchs +Signed-off-by: Johannes Berg +--- + net/mac80211/mlme.c | 38 +++++++++++++++++++++++++++----------- + 1 file changed, 27 insertions(+), 11 deletions(-) + +--- a/net/mac80211/mlme.c 2012-01-18 14:04:33.000000000 +0100 ++++ b/net/mac80211/mlme.c 2012-01-18 14:04:34.000000000 +0100 +@@ -2750,7 +2750,6 @@ int ieee80211_mgd_deauth(struct ieee8021 + { + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; +- struct ieee80211_work *wk; + u8 bssid[ETH_ALEN]; + bool assoc_bss = false; + +@@ -2763,30 +2762,47 @@ int ieee80211_mgd_deauth(struct ieee8021 + assoc_bss = true; + } else { + bool not_auth_yet = false; ++ struct ieee80211_work *tmp, *wk = NULL; + + mutex_unlock(&ifmgd->mtx); + + mutex_lock(&local->mtx); +- list_for_each_entry(wk, &local->work_list, list) { +- if (wk->sdata != sdata) ++ list_for_each_entry(tmp, &local->work_list, list) { ++ if (tmp->sdata != sdata) + continue; + +- if (wk->type != IEEE80211_WORK_DIRECT_PROBE && +- wk->type != IEEE80211_WORK_AUTH && +- wk->type != IEEE80211_WORK_ASSOC && +- wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) ++ if (tmp->type != IEEE80211_WORK_DIRECT_PROBE && ++ tmp->type != IEEE80211_WORK_AUTH && ++ tmp->type != IEEE80211_WORK_ASSOC && ++ tmp->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) + continue; + +- if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN)) ++ if (memcmp(req->bss->bssid, tmp->filter_ta, ETH_ALEN)) + continue; + +- not_auth_yet = wk->type == IEEE80211_WORK_DIRECT_PROBE; +- list_del_rcu(&wk->list); +- free_work(wk); ++ not_auth_yet = tmp->type == IEEE80211_WORK_DIRECT_PROBE; ++ list_del_rcu(&tmp->list); ++ synchronize_rcu(); ++ wk = tmp; + break; + } + mutex_unlock(&local->mtx); + ++ if (wk && wk->type == IEEE80211_WORK_ASSOC) { ++ /* clean up dummy sta & TX sync */ ++ sta_info_destroy_addr(wk->sdata, wk->filter_ta); ++ if (wk->assoc.synced) ++ drv_finish_tx_sync(local, wk->sdata, ++ wk->filter_ta, ++ IEEE80211_TX_SYNC_ASSOC); ++ } else if (wk && wk->type == IEEE80211_WORK_AUTH) { ++ if (wk->probe_auth.synced) ++ drv_finish_tx_sync(local, wk->sdata, ++ wk->filter_ta, ++ IEEE80211_TX_SYNC_AUTH); ++ } ++ kfree(wk); ++ + /* + * If somebody requests authentication and we haven't + * sent out an auth frame yet there's no need to send + + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + From f027dafaed73c1cd11ec9a656c59a37d0a37e7eb Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 20 Jan 2012 16:58:05 -0500 Subject: [PATCH 233/487] net: reintroduce missing rcu_assign_pointer() calls --- kernel.spec | 8 + rcu-reintroduce-missing-calls.patch | 632 ++++++++++++++++++++++++++++ 2 files changed, 640 insertions(+) create mode 100644 rcu-reintroduce-missing-calls.patch diff --git a/kernel.spec b/kernel.spec index 8abd851b8..5c3e51165 100644 --- a/kernel.spec +++ b/kernel.spec @@ -807,6 +807,9 @@ Patch21226: pci-crs-blacklist.patch Patch21227: mac80211-fix-work-removal-on-deauth-request.patch +Patch22000: rcu-reintroduce-missing-calls.patch + + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch @@ -1493,6 +1496,8 @@ ApplyPatch proc-clean-up-and-fix-proc-pid-mem-handling.patch ApplyPatch mac80211-fix-work-removal-on-deauth-request.patch +ApplyPatch rcu-reintroduce-missing-calls.patch + # END OF PATCH APPLICATIONS %endif @@ -2269,6 +2274,9 @@ fi # and build. %changelog +* Fri Jan 20 2012 Dave Jones +- net: reintroduce missing rcu_assign_pointer() calls + * Fri Jan 20 2012 Josh Boyer - Add mac80211 deauth fix pointed out by Stanislaw Gruszka diff --git a/rcu-reintroduce-missing-calls.patch b/rcu-reintroduce-missing-calls.patch new file mode 100644 index 000000000..b887df750 --- /dev/null +++ b/rcu-reintroduce-missing-calls.patch @@ -0,0 +1,632 @@ +commit cf778b00e96df6d64f8e21b8395d1f8a859ecdc7 +Author: Eric Dumazet +Date: Thu Jan 12 04:41:32 2012 +0000 + + net: reintroduce missing rcu_assign_pointer() calls + + commit a9b3cd7f32 (rcu: convert uses of rcu_assign_pointer(x, NULL) to + RCU_INIT_POINTER) did a lot of incorrect changes, since it did a + complete conversion of rcu_assign_pointer(x, y) to RCU_INIT_POINTER(x, + y). + + We miss needed barriers, even on x86, when y is not NULL. + + Signed-off-by: Eric Dumazet + CC: Stephen Hemminger + CC: Paul E. McKenney + Signed-off-by: David S. Miller + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/core/netpoll.c linux-3.2.net/net/core/netpoll.c +--- linux-3.2.noarch/net/core/netpoll.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/core/netpoll.c 2012-01-20 16:50:26.761797929 -0500 +@@ -763,7 +763,7 @@ int __netpoll_setup(struct netpoll *np) + } + + /* last thing to do is link it to the net device structure */ +- RCU_INIT_POINTER(ndev->npinfo, npinfo); ++ rcu_assign_pointer(ndev->npinfo, npinfo); + + return 0; + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/core/net-sysfs.c linux-3.2.net/net/core/net-sysfs.c +--- linux-3.2.noarch/net/core/net-sysfs.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/core/net-sysfs.c 2012-01-20 16:50:26.730798974 -0500 +@@ -990,9 +990,9 @@ static ssize_t store_xps_map(struct netd + nonempty = 1; + } + +- if (nonempty) +- RCU_INIT_POINTER(dev->xps_maps, new_dev_maps); +- else { ++ if (nonempty) { ++ rcu_assign_pointer(dev->xps_maps, new_dev_maps); ++ } else { + kfree(new_dev_maps); + RCU_INIT_POINTER(dev->xps_maps, NULL); + } +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/decnet/dn_dev.c linux-3.2.net/net/decnet/dn_dev.c +--- linux-3.2.noarch/net/decnet/dn_dev.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/decnet/dn_dev.c 2012-01-20 16:50:26.793796851 -0500 +@@ -388,7 +388,7 @@ static int dn_dev_insert_ifa(struct dn_d + } + + ifa->ifa_next = dn_db->ifa_list; +- RCU_INIT_POINTER(dn_db->ifa_list, ifa); ++ rcu_assign_pointer(dn_db->ifa_list, ifa); + + dn_ifaddr_notify(RTM_NEWADDR, ifa); + blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa); +@@ -1093,7 +1093,7 @@ static struct dn_dev *dn_dev_create(stru + + memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms)); + +- RCU_INIT_POINTER(dev->dn_ptr, dn_db); ++ rcu_assign_pointer(dev->dn_ptr, dn_db); + dn_db->dev = dev; + init_timer(&dn_db->timer); + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv4/devinet.c linux-3.2.net/net/ipv4/devinet.c +--- linux-3.2.noarch/net/ipv4/devinet.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/ipv4/devinet.c 2012-01-20 16:50:26.829795637 -0500 +@@ -258,7 +258,7 @@ static struct in_device *inetdev_init(st + ip_mc_up(in_dev); + + /* we can receive as soon as ip_ptr is set -- do this last */ +- RCU_INIT_POINTER(dev->ip_ptr, in_dev); ++ rcu_assign_pointer(dev->ip_ptr, in_dev); + out: + return in_dev; + out_kfree: +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv4/fib_trie.c linux-3.2.net/net/ipv4/fib_trie.c +--- linux-3.2.noarch/net/ipv4/fib_trie.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/ipv4/fib_trie.c 2012-01-20 16:50:26.865794425 -0500 +@@ -205,7 +205,7 @@ static inline struct tnode *node_parent_ + return (struct tnode *)(parent & ~NODE_TYPE_MASK); + } + +-/* Same as RCU_INIT_POINTER ++/* Same as rcu_assign_pointer + * but that macro() assumes that value is a pointer. + */ + static inline void node_set_parent(struct rt_trie_node *node, struct tnode *ptr) +@@ -529,7 +529,7 @@ static void tnode_put_child_reorg(struct + if (n) + node_set_parent(n, tn); + +- RCU_INIT_POINTER(tn->child[i], n); ++ rcu_assign_pointer(tn->child[i], n); + } + + #define MAX_WORK 10 +@@ -1015,7 +1015,7 @@ static void trie_rebalance(struct trie * + + tp = node_parent((struct rt_trie_node *) tn); + if (!tp) +- RCU_INIT_POINTER(t->trie, (struct rt_trie_node *)tn); ++ rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); + + tnode_free_flush(); + if (!tp) +@@ -1027,7 +1027,7 @@ static void trie_rebalance(struct trie * + if (IS_TNODE(tn)) + tn = (struct tnode *)resize(t, (struct tnode *)tn); + +- RCU_INIT_POINTER(t->trie, (struct rt_trie_node *)tn); ++ rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); + tnode_free_flush(); + } + +@@ -1164,7 +1164,7 @@ static struct list_head *fib_insert_node + put_child(t, (struct tnode *)tp, cindex, + (struct rt_trie_node *)tn); + } else { +- RCU_INIT_POINTER(t->trie, (struct rt_trie_node *)tn); ++ rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); + tp = tn; + } + } +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv4/igmp.c linux-3.2.net/net/ipv4/igmp.c +--- linux-3.2.noarch/net/ipv4/igmp.c 2012-01-20 16:22:44.923961882 -0500 ++++ linux-3.2.net/net/ipv4/igmp.c 2012-01-20 16:50:26.898793315 -0500 +@@ -1244,7 +1244,7 @@ void ip_mc_inc_group(struct in_device *i + + im->next_rcu = in_dev->mc_list; + in_dev->mc_count++; +- RCU_INIT_POINTER(in_dev->mc_list, im); ++ rcu_assign_pointer(in_dev->mc_list, im); + + #ifdef CONFIG_IP_MULTICAST + igmpv3_del_delrec(in_dev, im->multiaddr); +@@ -1816,7 +1816,7 @@ int ip_mc_join_group(struct sock *sk , s + iml->next_rcu = inet->mc_list; + iml->sflist = NULL; + iml->sfmode = MCAST_EXCLUDE; +- RCU_INIT_POINTER(inet->mc_list, iml); ++ rcu_assign_pointer(inet->mc_list, iml); + ip_mc_inc_group(in_dev, addr); + err = 0; + done: +@@ -2003,7 +2003,7 @@ int ip_mc_source(int add, int omode, str + atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc); + kfree_rcu(psl, rcu); + } +- RCU_INIT_POINTER(pmc->sflist, newpsl); ++ rcu_assign_pointer(pmc->sflist, newpsl); + psl = newpsl; + } + rv = 1; /* > 0 for insert logic below if sl_count is 0 */ +@@ -2106,7 +2106,7 @@ int ip_mc_msfilter(struct sock *sk, stru + } else + (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode, + 0, NULL, 0); +- RCU_INIT_POINTER(pmc->sflist, newpsl); ++ rcu_assign_pointer(pmc->sflist, newpsl); + pmc->sfmode = msf->imsf_fmode; + err = 0; + done: +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv4/ipip.c linux-3.2.net/net/ipv4/ipip.c +--- linux-3.2.noarch/net/ipv4/ipip.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/ipv4/ipip.c 2012-01-20 16:50:26.916792707 -0500 +@@ -231,7 +231,7 @@ static void ipip_tunnel_unlink(struct ip + (iter = rtnl_dereference(*tp)) != NULL; + tp = &iter->next) { + if (t == iter) { +- RCU_INIT_POINTER(*tp, t->next); ++ rcu_assign_pointer(*tp, t->next); + break; + } + } +@@ -241,8 +241,8 @@ static void ipip_tunnel_link(struct ipip + { + struct ip_tunnel __rcu **tp = ipip_bucket(ipn, t); + +- RCU_INIT_POINTER(t->next, rtnl_dereference(*tp)); +- RCU_INIT_POINTER(*tp, t); ++ rcu_assign_pointer(t->next, rtnl_dereference(*tp)); ++ rcu_assign_pointer(*tp, t); + } + + static struct ip_tunnel * ipip_tunnel_locate(struct net *net, +@@ -792,7 +792,7 @@ static int __net_init ipip_fb_tunnel_ini + return -ENOMEM; + + dev_hold(dev); +- RCU_INIT_POINTER(ipn->tunnels_wc[0], tunnel); ++ rcu_assign_pointer(ipn->tunnels_wc[0], tunnel); + return 0; + } + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv4/ipmr.c linux-3.2.net/net/ipv4/ipmr.c +--- linux-3.2.noarch/net/ipv4/ipmr.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/ipv4/ipmr.c 2012-01-20 16:50:26.946791698 -0500 +@@ -1225,7 +1225,7 @@ int ip_mroute_setsockopt(struct sock *sk + + ret = ip_ra_control(sk, 1, mrtsock_destruct); + if (ret == 0) { +- RCU_INIT_POINTER(mrt->mroute_sk, sk); ++ rcu_assign_pointer(mrt->mroute_sk, sk); + IPV4_DEVCONF_ALL(net, MC_FORWARDING)++; + } + rtnl_unlock(); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv6/addrconf.c linux-3.2.net/net/ipv6/addrconf.c +--- linux-3.2.noarch/net/ipv6/addrconf.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/ipv6/addrconf.c 2012-01-20 16:50:26.977790653 -0500 +@@ -429,7 +429,7 @@ static struct inet6_dev * ipv6_add_dev(s + ndev->tstamp = jiffies; + addrconf_sysctl_register(ndev); + /* protected by rtnl_lock */ +- RCU_INIT_POINTER(dev->ip6_ptr, ndev); ++ rcu_assign_pointer(dev->ip6_ptr, ndev); + + /* Join all-node multicast group */ + ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv6/ip6_tunnel.c linux-3.2.net/net/ipv6/ip6_tunnel.c +--- linux-3.2.noarch/net/ipv6/ip6_tunnel.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/ipv6/ip6_tunnel.c 2012-01-20 16:50:27.004789743 -0500 +@@ -218,8 +218,8 @@ ip6_tnl_link(struct ip6_tnl_net *ip6n, s + { + struct ip6_tnl __rcu **tp = ip6_tnl_bucket(ip6n, &t->parms); + +- RCU_INIT_POINTER(t->next , rtnl_dereference(*tp)); +- RCU_INIT_POINTER(*tp, t); ++ rcu_assign_pointer(t->next , rtnl_dereference(*tp)); ++ rcu_assign_pointer(*tp, t); + } + + /** +@@ -237,7 +237,7 @@ ip6_tnl_unlink(struct ip6_tnl_net *ip6n, + (iter = rtnl_dereference(*tp)) != NULL; + tp = &iter->next) { + if (t == iter) { +- RCU_INIT_POINTER(*tp, t->next); ++ rcu_assign_pointer(*tp, t->next); + break; + } + } +@@ -1450,7 +1450,7 @@ static int __net_init ip6_fb_tnl_dev_ini + + t->parms.proto = IPPROTO_IPV6; + dev_hold(dev); +- RCU_INIT_POINTER(ip6n->tnls_wc[0], t); ++ rcu_assign_pointer(ip6n->tnls_wc[0], t); + return 0; + } + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv6/raw.c linux-3.2.net/net/ipv6/raw.c +--- linux-3.2.noarch/net/ipv6/raw.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/ipv6/raw.c 2012-01-20 16:50:27.022789138 -0500 +@@ -131,7 +131,7 @@ static mh_filter_t __rcu *mh_filter __re + + int rawv6_mh_filter_register(mh_filter_t filter) + { +- RCU_INIT_POINTER(mh_filter, filter); ++ rcu_assign_pointer(mh_filter, filter); + return 0; + } + EXPORT_SYMBOL(rawv6_mh_filter_register); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv6/sit.c linux-3.2.net/net/ipv6/sit.c +--- linux-3.2.noarch/net/ipv6/sit.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/ipv6/sit.c 2012-01-20 16:50:27.042788464 -0500 +@@ -182,7 +182,7 @@ static void ipip6_tunnel_unlink(struct s + (iter = rtnl_dereference(*tp)) != NULL; + tp = &iter->next) { + if (t == iter) { +- RCU_INIT_POINTER(*tp, t->next); ++ rcu_assign_pointer(*tp, t->next); + break; + } + } +@@ -192,8 +192,8 @@ static void ipip6_tunnel_link(struct sit + { + struct ip_tunnel __rcu **tp = ipip6_bucket(sitn, t); + +- RCU_INIT_POINTER(t->next, rtnl_dereference(*tp)); +- RCU_INIT_POINTER(*tp, t); ++ rcu_assign_pointer(t->next, rtnl_dereference(*tp)); ++ rcu_assign_pointer(*tp, t); + } + + static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn) +@@ -393,7 +393,7 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t + p->addr = a->addr; + p->flags = a->flags; + t->prl_count++; +- RCU_INIT_POINTER(t->prl, p); ++ rcu_assign_pointer(t->prl, p); + out: + return err; + } +@@ -1177,7 +1177,7 @@ static int __net_init ipip6_fb_tunnel_in + if (!dev->tstats) + return -ENOMEM; + dev_hold(dev); +- RCU_INIT_POINTER(sitn->tunnels_wc[0], tunnel); ++ rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); + return 0; + } + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/mac80211/agg-rx.c linux-3.2.net/net/mac80211/agg-rx.c +--- linux-3.2.noarch/net/mac80211/agg-rx.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/mac80211/agg-rx.c 2012-01-20 16:50:27.058787924 -0500 +@@ -326,7 +326,7 @@ void ieee80211_process_addba_request(str + status = WLAN_STATUS_SUCCESS; + + /* activate it for RX */ +- RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx); ++ rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx); + + if (timeout) + mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout)); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/mac80211/cfg.c linux-3.2.net/net/mac80211/cfg.c +--- linux-3.2.noarch/net/mac80211/cfg.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/mac80211/cfg.c 2012-01-20 16:50:27.082787116 -0500 +@@ -575,7 +575,7 @@ static int ieee80211_config_beacon(struc + + sdata->vif.bss_conf.dtim_period = new->dtim_period; + +- RCU_INIT_POINTER(sdata->u.ap.beacon, new); ++ rcu_assign_pointer(sdata->u.ap.beacon, new); + + synchronize_rcu(); + +@@ -922,7 +922,7 @@ static int ieee80211_change_station(stru + return -EBUSY; + } + +- RCU_INIT_POINTER(vlansdata->u.vlan.sta, sta); ++ rcu_assign_pointer(vlansdata->u.vlan.sta, sta); + } + + sta->sdata = vlansdata; +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/mac80211/ibss.c linux-3.2.net/net/mac80211/ibss.c +--- linux-3.2.noarch/net/mac80211/ibss.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/mac80211/ibss.c 2012-01-20 16:50:27.102786444 -0500 +@@ -184,7 +184,7 @@ static void __ieee80211_sta_join_ibss(st + *pos++ = 0; /* U-APSD no in use */ + } + +- RCU_INIT_POINTER(ifibss->presp, skb); ++ rcu_assign_pointer(ifibss->presp, skb); + + sdata->vif.bss_conf.beacon_int = beacon_int; + sdata->vif.bss_conf.basic_rates = basic_rates; +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/mac80211/sta_info.c linux-3.2.net/net/mac80211/sta_info.c +--- linux-3.2.noarch/net/mac80211/sta_info.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/mac80211/sta_info.c 2012-01-20 16:50:27.131785466 -0500 +@@ -73,7 +73,7 @@ static int sta_info_hash_del(struct ieee + if (!s) + return -ENOENT; + if (s == sta) { +- RCU_INIT_POINTER(local->sta_hash[STA_HASH(sta->sta.addr)], ++ rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], + s->hnext); + return 0; + } +@@ -83,7 +83,7 @@ static int sta_info_hash_del(struct ieee + s = rcu_dereference_protected(s->hnext, + lockdep_is_held(&local->sta_lock)); + if (rcu_access_pointer(s->hnext)) { +- RCU_INIT_POINTER(s->hnext, sta->hnext); ++ rcu_assign_pointer(s->hnext, sta->hnext); + return 0; + } + +@@ -232,7 +232,7 @@ static void sta_info_hash_add(struct iee + struct sta_info *sta) + { + sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)]; +- RCU_INIT_POINTER(local->sta_hash[STA_HASH(sta->sta.addr)], sta); ++ rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta); + } + + static void sta_unblock(struct work_struct *wk) +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_conntrack_core.c linux-3.2.net/net/netfilter/nf_conntrack_core.c +--- linux-3.2.noarch/net/netfilter/nf_conntrack_core.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netfilter/nf_conntrack_core.c 2012-01-20 16:50:27.169784186 -0500 +@@ -776,7 +776,7 @@ init_conntrack(struct net *net, struct n + if (exp->helper) { + help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); + if (help) +- RCU_INIT_POINTER(help->helper, exp->helper); ++ rcu_assign_pointer(help->helper, exp->helper); + } + + #ifdef CONFIG_NF_CONNTRACK_MARK +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_conntrack_ecache.c linux-3.2.net/net/netfilter/nf_conntrack_ecache.c +--- linux-3.2.noarch/net/netfilter/nf_conntrack_ecache.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netfilter/nf_conntrack_ecache.c 2012-01-20 16:50:27.187783578 -0500 +@@ -91,7 +91,7 @@ int nf_conntrack_register_notifier(struc + ret = -EBUSY; + goto out_unlock; + } +- RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, new); ++ rcu_assign_pointer(net->ct.nf_conntrack_event_cb, new); + mutex_unlock(&nf_ct_ecache_mutex); + return ret; + +@@ -128,7 +128,7 @@ int nf_ct_expect_register_notifier(struc + ret = -EBUSY; + goto out_unlock; + } +- RCU_INIT_POINTER(net->ct.nf_expect_event_cb, new); ++ rcu_assign_pointer(net->ct.nf_expect_event_cb, new); + mutex_unlock(&nf_ct_ecache_mutex); + return ret; + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_conntrack_extend.c linux-3.2.net/net/netfilter/nf_conntrack_extend.c +--- linux-3.2.noarch/net/netfilter/nf_conntrack_extend.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netfilter/nf_conntrack_extend.c 2012-01-20 16:50:27.204783008 -0500 +@@ -169,7 +169,7 @@ int nf_ct_extend_register(struct nf_ct_e + before updating alloc_size */ + type->alloc_size = ALIGN(sizeof(struct nf_ct_ext), type->align) + + type->len; +- RCU_INIT_POINTER(nf_ct_ext_types[type->id], type); ++ rcu_assign_pointer(nf_ct_ext_types[type->id], type); + update_alloc_size(type); + out: + mutex_unlock(&nf_ct_ext_type_mutex); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_conntrack_helper.c linux-3.2.net/net/netfilter/nf_conntrack_helper.c +--- linux-3.2.noarch/net/netfilter/nf_conntrack_helper.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netfilter/nf_conntrack_helper.c 2012-01-20 16:50:27.227782232 -0500 +@@ -145,7 +145,7 @@ int __nf_ct_try_assign_helper(struct nf_ + memset(&help->help, 0, sizeof(help->help)); + } + +- RCU_INIT_POINTER(help->helper, helper); ++ rcu_assign_pointer(help->helper, helper); + out: + return ret; + } +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_conntrack_netlink.c linux-3.2.net/net/netfilter/nf_conntrack_netlink.c +--- linux-3.2.noarch/net/netfilter/nf_conntrack_netlink.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netfilter/nf_conntrack_netlink.c 2012-01-20 16:50:27.271780750 -0500 +@@ -1163,7 +1163,7 @@ ctnetlink_change_helper(struct nf_conn * + return -EOPNOTSUPP; + } + +- RCU_INIT_POINTER(help->helper, helper); ++ rcu_assign_pointer(help->helper, helper); + + return 0; + } +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_log.c linux-3.2.net/net/netfilter/nf_log.c +--- linux-3.2.noarch/net/netfilter/nf_log.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netfilter/nf_log.c 2012-01-20 16:50:27.280780448 -0500 +@@ -55,7 +55,7 @@ int nf_log_register(u_int8_t pf, struct + llog = rcu_dereference_protected(nf_loggers[pf], + lockdep_is_held(&nf_log_mutex)); + if (llog == NULL) +- RCU_INIT_POINTER(nf_loggers[pf], logger); ++ rcu_assign_pointer(nf_loggers[pf], logger); + } + + mutex_unlock(&nf_log_mutex); +@@ -92,7 +92,7 @@ int nf_log_bind_pf(u_int8_t pf, const st + mutex_unlock(&nf_log_mutex); + return -ENOENT; + } +- RCU_INIT_POINTER(nf_loggers[pf], logger); ++ rcu_assign_pointer(nf_loggers[pf], logger); + mutex_unlock(&nf_log_mutex); + return 0; + } +@@ -250,7 +250,7 @@ static int nf_log_proc_dostring(ctl_tabl + mutex_unlock(&nf_log_mutex); + return -ENOENT; + } +- RCU_INIT_POINTER(nf_loggers[tindex], logger); ++ rcu_assign_pointer(nf_loggers[tindex], logger); + mutex_unlock(&nf_log_mutex); + } else { + mutex_lock(&nf_log_mutex); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nfnetlink.c linux-3.2.net/net/netfilter/nfnetlink.c +--- linux-3.2.noarch/net/netfilter/nfnetlink.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netfilter/nfnetlink.c 2012-01-20 16:50:27.302779705 -0500 +@@ -59,7 +59,7 @@ int nfnetlink_subsys_register(const stru + nfnl_unlock(); + return -EBUSY; + } +- RCU_INIT_POINTER(subsys_table[n->subsys_id], n); ++ rcu_assign_pointer(subsys_table[n->subsys_id], n); + nfnl_unlock(); + + return 0; +@@ -210,7 +210,7 @@ static int __net_init nfnetlink_net_init + if (!nfnl) + return -ENOMEM; + net->nfnl_stash = nfnl; +- RCU_INIT_POINTER(net->nfnl, nfnl); ++ rcu_assign_pointer(net->nfnl, nfnl); + return 0; + } + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_queue.c linux-3.2.net/net/netfilter/nf_queue.c +--- linux-3.2.noarch/net/netfilter/nf_queue.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netfilter/nf_queue.c 2012-01-20 16:50:27.293780010 -0500 +@@ -40,7 +40,7 @@ int nf_register_queue_handler(u_int8_t p + else if (old) + ret = -EBUSY; + else { +- RCU_INIT_POINTER(queue_handler[pf], qh); ++ rcu_assign_pointer(queue_handler[pf], qh); + ret = 0; + } + mutex_unlock(&queue_handler_mutex); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netlabel/netlabel_domainhash.c linux-3.2.net/net/netlabel/netlabel_domainhash.c +--- linux-3.2.noarch/net/netlabel/netlabel_domainhash.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netlabel/netlabel_domainhash.c 2012-01-20 16:50:27.311779402 -0500 +@@ -282,7 +282,7 @@ int __init netlbl_domhsh_init(u32 size) + INIT_LIST_HEAD(&hsh_tbl->tbl[iter]); + + spin_lock(&netlbl_domhsh_lock); +- RCU_INIT_POINTER(netlbl_domhsh, hsh_tbl); ++ rcu_assign_pointer(netlbl_domhsh, hsh_tbl); + spin_unlock(&netlbl_domhsh_lock); + + return 0; +@@ -330,7 +330,7 @@ int netlbl_domhsh_add(struct netlbl_dom_ + &rcu_dereference(netlbl_domhsh)->tbl[bkt]); + } else { + INIT_LIST_HEAD(&entry->list); +- RCU_INIT_POINTER(netlbl_domhsh_def, entry); ++ rcu_assign_pointer(netlbl_domhsh_def, entry); + } + + if (entry->type == NETLBL_NLTYPE_ADDRSELECT) { +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netlabel/netlabel_unlabeled.c linux-3.2.net/net/netlabel/netlabel_unlabeled.c +--- linux-3.2.noarch/net/netlabel/netlabel_unlabeled.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/netlabel/netlabel_unlabeled.c 2012-01-20 16:50:27.327778863 -0500 +@@ -354,7 +354,7 @@ static struct netlbl_unlhsh_iface *netlb + INIT_LIST_HEAD(&iface->list); + if (netlbl_unlhsh_rcu_deref(netlbl_unlhsh_def) != NULL) + goto add_iface_failure; +- RCU_INIT_POINTER(netlbl_unlhsh_def, iface); ++ rcu_assign_pointer(netlbl_unlhsh_def, iface); + } + spin_unlock(&netlbl_unlhsh_lock); + +@@ -1447,11 +1447,9 @@ int __init netlbl_unlabel_init(u32 size) + for (iter = 0; iter < hsh_tbl->size; iter++) + INIT_LIST_HEAD(&hsh_tbl->tbl[iter]); + +- rcu_read_lock(); + spin_lock(&netlbl_unlhsh_lock); +- RCU_INIT_POINTER(netlbl_unlhsh, hsh_tbl); ++ rcu_assign_pointer(netlbl_unlhsh, hsh_tbl); + spin_unlock(&netlbl_unlhsh_lock); +- rcu_read_unlock(); + + register_netdevice_notifier(&netlbl_unlhsh_netdev_notifier); + +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/phonet/af_phonet.c linux-3.2.net/net/phonet/af_phonet.c +--- linux-3.2.noarch/net/phonet/af_phonet.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/phonet/af_phonet.c 2012-01-20 16:50:27.345778258 -0500 +@@ -480,7 +480,7 @@ int __init_or_module phonet_proto_regist + if (proto_tab[protocol]) + err = -EBUSY; + else +- RCU_INIT_POINTER(proto_tab[protocol], pp); ++ rcu_assign_pointer(proto_tab[protocol], pp); + mutex_unlock(&proto_tab_lock); + + return err; +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/phonet/pn_dev.c linux-3.2.net/net/phonet/pn_dev.c +--- linux-3.2.noarch/net/phonet/pn_dev.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/phonet/pn_dev.c 2012-01-20 16:50:27.353777988 -0500 +@@ -390,7 +390,7 @@ int phonet_route_add(struct net_device * + daddr = daddr >> 2; + mutex_lock(&routes->lock); + if (routes->table[daddr] == NULL) { +- RCU_INIT_POINTER(routes->table[daddr], dev); ++ rcu_assign_pointer(routes->table[daddr], dev); + dev_hold(dev); + err = 0; + } +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/phonet/socket.c linux-3.2.net/net/phonet/socket.c +--- linux-3.2.noarch/net/phonet/socket.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/phonet/socket.c 2012-01-20 16:50:27.365777583 -0500 +@@ -680,7 +680,7 @@ int pn_sock_bind_res(struct sock *sk, u8 + mutex_lock(&resource_mutex); + if (pnres.sk[res] == NULL) { + sock_hold(sk); +- RCU_INIT_POINTER(pnres.sk[res], sk); ++ rcu_assign_pointer(pnres.sk[res], sk); + ret = 0; + } + mutex_unlock(&resource_mutex); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/socket.c linux-3.2.net/net/socket.c +--- linux-3.2.noarch/net/socket.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/socket.c 2012-01-20 16:50:27.410776068 -0500 +@@ -2472,7 +2472,7 @@ int sock_register(const struct net_proto + lockdep_is_held(&net_family_lock))) + err = -EEXIST; + else { +- RCU_INIT_POINTER(net_families[ops->family], ops); ++ rcu_assign_pointer(net_families[ops->family], ops); + err = 0; + } + spin_unlock(&net_family_lock); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/sunrpc/auth_gss/auth_gss.c linux-3.2.net/net/sunrpc/auth_gss/auth_gss.c +--- linux-3.2.noarch/net/sunrpc/auth_gss/auth_gss.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/sunrpc/auth_gss/auth_gss.c 2012-01-20 16:50:27.428775461 -0500 +@@ -122,7 +122,7 @@ gss_cred_set_ctx(struct rpc_cred *cred, + if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)) + return; + gss_get_ctx(ctx); +- RCU_INIT_POINTER(gss_cred->gc_ctx, ctx); ++ rcu_assign_pointer(gss_cred->gc_ctx, ctx); + set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); + smp_mb__before_clear_bit(); + clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags); +diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/xfrm/xfrm_user.c linux-3.2.net/net/xfrm/xfrm_user.c +--- linux-3.2.noarch/net/xfrm/xfrm_user.c 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.net/net/xfrm/xfrm_user.c 2012-01-20 16:50:27.449774754 -0500 +@@ -2927,7 +2927,7 @@ static int __net_init xfrm_user_net_init + if (nlsk == NULL) + return -ENOMEM; + net->xfrm.nlsk_stash = nlsk; /* Don't set to NULL */ +- RCU_INIT_POINTER(net->xfrm.nlsk, nlsk); ++ rcu_assign_pointer(net->xfrm.nlsk, nlsk); + return 0; + } + From 7f50a05c33776325193d3ba9c9dc9eccbec37e67 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 23 Jan 2012 09:41:28 -0500 Subject: [PATCH 234/487] Fix NULL pointer dereference in sym53c8xx module (rhbz 781625) --- ...ix-NULL-pointer-dereference-in-slave.patch | 35 +++++++++++++++++++ kernel.spec | 9 +++++ 2 files changed, 44 insertions(+) create mode 100644 SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch diff --git a/SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch b/SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch new file mode 100644 index 000000000..369012744 --- /dev/null +++ b/SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch @@ -0,0 +1,35 @@ +From cced5041ed5a2d1352186510944b0ddfbdbe4c0b Mon Sep 17 00:00:00 2001 +From: Stratos Psomadakis +Date: Sun, 4 Dec 2011 02:23:54 +0200 +Subject: [PATCH] [SCSI] sym53c8xx: Fix NULL pointer dereference in + slave_destroy + +sym53c8xx_slave_destroy unconditionally assumes that sym53c8xx_slave_alloc has +succesesfully allocated a sym_lcb. This can lead to a NULL pointer dereference +(exposed by commit 4e6c82b). + +Signed-off-by: Stratos Psomadakis +Cc: stable@vger.kernel.org +Signed-off-by: James Bottomley +--- + drivers/scsi/sym53c8xx_2/sym_glue.c | 4 ++++ + 1 files changed, 4 insertions(+), 0 deletions(-) + +diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c +index b4543f5..36d1ed7 100644 +--- a/drivers/scsi/sym53c8xx_2/sym_glue.c ++++ b/drivers/scsi/sym53c8xx_2/sym_glue.c +@@ -839,6 +839,10 @@ static void sym53c8xx_slave_destroy(struct scsi_device *sdev) + struct sym_lcb *lp = sym_lp(tp, sdev->lun); + unsigned long flags; + ++ /* if slave_alloc returned before allocating a sym_lcb, return */ ++ if (!lp) ++ return; ++ + spin_lock_irqsave(np->s.host->host_lock, flags); + + if (lp->busy_itlq || lp->busy_itl) { +-- +1.7.7.5 + diff --git a/kernel.spec b/kernel.spec index 5c3e51165..87308e0c9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -807,6 +807,9 @@ Patch21226: pci-crs-blacklist.patch Patch21227: mac80211-fix-work-removal-on-deauth-request.patch +#rhbz 781625 +Patch21228: SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch + Patch22000: rcu-reintroduce-missing-calls.patch @@ -1496,6 +1499,9 @@ ApplyPatch proc-clean-up-and-fix-proc-pid-mem-handling.patch ApplyPatch mac80211-fix-work-removal-on-deauth-request.patch +#rhbz 781625 +ApplyPatch SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch + ApplyPatch rcu-reintroduce-missing-calls.patch # END OF PATCH APPLICATIONS @@ -2274,6 +2280,9 @@ fi # and build. %changelog +* Mon Jan 23 2012 Josh Boyer +- Fix NULL pointer dereference in sym53c8xx module (rhbz 781625) + * Fri Jan 20 2012 Dave Jones - net: reintroduce missing rcu_assign_pointer() calls From e4e2bcb5072584569af1a7d8ba5fc707b79247c9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 23 Jan 2012 09:53:44 -0500 Subject: [PATCH 235/487] Fix oops in iwlwifi/iwlagn driver (rhbz 766071) --- iwlagn-check-for-SMPS-mode.patch | 43 ++++++++++++++++++++++++++++++++ kernel.spec | 9 ++++++- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 iwlagn-check-for-SMPS-mode.patch diff --git a/iwlagn-check-for-SMPS-mode.patch b/iwlagn-check-for-SMPS-mode.patch new file mode 100644 index 000000000..ae42747ea --- /dev/null +++ b/iwlagn-check-for-SMPS-mode.patch @@ -0,0 +1,43 @@ +From b2ccccdca46273c7b321ecf5041c362cd950da20 Mon Sep 17 00:00:00 2001 +From: Wey-Yi Guy +Date: Thu, 10 Nov 2011 06:55:04 -0800 +Subject: [PATCH] iwlagn: check for SMPS mode + +Check and report WARN only when its invalid + +Signed-off-by: Wey-Yi Guy +Signed-off-by: John W. Linville +--- + drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 1 + + drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 3 +++ + 2 files changed, 4 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +index 1a52ed2..6465983 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +@@ -827,6 +827,7 @@ static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) + case IEEE80211_SMPS_STATIC: + case IEEE80211_SMPS_DYNAMIC: + return IWL_NUM_IDLE_CHAINS_SINGLE; ++ case IEEE80211_SMPS_AUTOMATIC: + case IEEE80211_SMPS_OFF: + return active_cnt; + default: +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +index 4c52bee..8e45fba 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +@@ -542,6 +542,9 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) + + mutex_lock(&priv->shrd->mutex); + ++ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) ++ goto out; ++ + if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) { + IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); + goto out; +-- +1.7.7.5 + diff --git a/kernel.spec b/kernel.spec index 87308e0c9..3ca8d4dfc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -810,6 +810,9 @@ Patch21227: mac80211-fix-work-removal-on-deauth-request.patch #rhbz 781625 Patch21228: SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch +#rhbz 766071 +Patch21229: iwlagn-check-for-SMPS-mode.patch + Patch22000: rcu-reintroduce-missing-calls.patch @@ -1502,6 +1505,9 @@ ApplyPatch mac80211-fix-work-removal-on-deauth-request.patch #rhbz 781625 ApplyPatch SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch +#rhbz 766071 +ApplyPatch iwlagn-check-for-SMPS-mode.patch + ApplyPatch rcu-reintroduce-missing-calls.patch # END OF PATCH APPLICATIONS @@ -2281,6 +2287,7 @@ fi %changelog * Mon Jan 23 2012 Josh Boyer +- Fix oops in iwlwifi/iwlagn driver (rhbz 766071) - Fix NULL pointer dereference in sym53c8xx module (rhbz 781625) * Fri Jan 20 2012 Dave Jones From 08d7191c407cf62ac124af4e02c070264e129c11 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 23 Jan 2012 10:14:21 -0500 Subject: [PATCH 236/487] Add version number for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 3ca8d4dfc..b41b0fca0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2286,7 +2286,7 @@ fi # and build. %changelog -* Mon Jan 23 2012 Josh Boyer +* Mon Jan 23 2012 Josh Boyer 3.2.1-3 - Fix oops in iwlwifi/iwlagn driver (rhbz 766071) - Fix NULL pointer dereference in sym53c8xx module (rhbz 781625) From 9353f32ca8df29996fc3e0fbb30439b36a94bf1c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 24 Jan 2012 09:43:21 -0500 Subject: [PATCH 237/487] Re-enable the ARCMSR module (rhbz 784287) --- config-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 7c327d4a2..5cf25778f 100644 --- a/config-generic +++ b/config-generic @@ -552,7 +552,7 @@ CONFIG_SCSI_PM8001=m CONFIG_VMWARE_PVSCSI=m CONFIG_VMWARE_BALLOON=m -# CONFIG_SCSI_ARCMSR is not set +CONFIG_SCSI_ARCMSR=m CONFIG_SCSI_BUSLOGIC=m CONFIG_SCSI_INITIO=m CONFIG_SCSI_FLASHPOINT=y diff --git a/kernel.spec b/kernel.spec index b41b0fca0..952be2b6c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2286,6 +2286,9 @@ fi # and build. %changelog +* Tue Jan 24 2012 Josh Boyer +- Re-enable the ARCMSR module (rhbz 784287) + * Mon Jan 23 2012 Josh Boyer 3.2.1-3 - Fix oops in iwlwifi/iwlagn driver (rhbz 766071) - Fix NULL pointer dereference in sym53c8xx module (rhbz 781625) From b652ddfbcbd290c65a78da8f68a9ede7f431f3c9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 24 Jan 2012 10:54:25 -0500 Subject: [PATCH 238/487] Add back a set of patches that were erroneously dropped during the rebase --- 01-block-add-and-use-scsi_blk_cmd_ioctl.patch | 24 +-- ...passthrough-ioctls-on-partition-devs.patch | 165 ++++++++++++++++++ ...wd-ioctls-from-LVs-to-underlying-dev.patch | 4 +- kernel.spec | 12 +- 4 files changed, 190 insertions(+), 15 deletions(-) create mode 100644 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch diff --git a/01-block-add-and-use-scsi_blk_cmd_ioctl.patch b/01-block-add-and-use-scsi_blk_cmd_ioctl.patch index fdf4c5039..259bf6912 100644 --- a/01-block-add-and-use-scsi_blk_cmd_ioctl.patch +++ b/01-block-add-and-use-scsi_blk_cmd_ioctl.patch @@ -1,4 +1,4 @@ -From 6051b3759d3d4b70d33a7be70ab6b86ed3559224 Mon Sep 17 00:00:00 2001 +From a7f3cbff409dde86b6bded8978f71bc193022427 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 16 Jan 2012 17:12:58 +0100 Subject: [PATCH 1/3] block: add and use scsi_blk_cmd_ioctl @@ -28,10 +28,10 @@ Signed-off-by: Linus Torvalds 8 files changed, 18 insertions(+), 12 deletions(-) diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c -index 4f4230b..57ac937 100644 +index fbdf0d8..a2c11f3 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c -@@ -691,6 +691,13 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod +@@ -690,6 +690,13 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod } EXPORT_SYMBOL(scsi_cmd_ioctl); @@ -46,10 +46,10 @@ index 4f4230b..57ac937 100644 { blk_set_cmd_filter_defaults(&blk_default_cmd_filter); diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c -index c2f9b3e..1dab802 100644 +index 587cce5..b0f553b 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c -@@ -1716,7 +1716,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, +@@ -1735,7 +1735,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, case CCISS_BIG_PASSTHRU: return cciss_bigpassthru(h, argp); @@ -58,7 +58,7 @@ index c2f9b3e..1dab802 100644 /* very meaningful for cciss. SG_IO is the main one people want. */ case SG_GET_VERSION_NUM: -@@ -1727,9 +1727,9 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, +@@ -1746,9 +1746,9 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, case SG_EMULATED_HOST: case SG_IO: case SCSI_IOCTL_SEND_COMMAND: @@ -89,10 +89,10 @@ index 0e376d4..7333b9e 100644 return ret; diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c -index 079c088..5d7a934 100644 +index 4d0b70a..e46f2f7 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c -@@ -236,8 +236,8 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, +@@ -243,8 +243,8 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI)) return -ENOTTY; @@ -136,10 +136,10 @@ index d267b7a..a22ca84 100644 if (err == -ENOTTY) err = generic_ide_ioctl(drive, bdev, cmd, arg); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c -index 953773c..c88885d 100644 +index fa3a591..ffa1c79 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c -@@ -1095,7 +1095,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, +@@ -1096,7 +1096,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, error = scsi_ioctl(sdp, cmd, p); break; default: @@ -149,7 +149,7 @@ index 953773c..c88885d 100644 break; error = scsi_ioctl(sdp, cmd, p); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h -index 5e30b45..aa829a4 100644 +index 94acd81..ca7b869 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -675,6 +675,8 @@ extern int blk_insert_cloned_request(struct request_queue *q, @@ -162,5 +162,5 @@ index 5e30b45..aa829a4 100644 unsigned int, void __user *); extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t, -- -1.7.7.5 +1.7.7.6 diff --git a/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch b/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch new file mode 100644 index 000000000..ce3e50a5d --- /dev/null +++ b/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch @@ -0,0 +1,165 @@ +From 51c6b870e10bbf60ee6a115216cfa7549addfce0 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 16 Jan 2012 17:12:59 +0100 +Subject: [PATCH 2/3] block: fail SCSI passthrough ioctls on partition devices + +Linux allows executing the SG_IO ioctl on a partition or LVM volume, and +will pass the command to the underlying block device. This is +well-known, but it is also a large security problem when (via Unix +permissions, ACLs, SELinux or a combination thereof) a program or user +needs to be granted access only to part of the disk. + +This patch lets partitions forward a small set of harmless ioctls; +others are logged with printk so that we can see which ioctls are +actually sent. In my tests only CDROM_GET_CAPABILITY actually occurred. +Of course it was being sent to a (partition on a) hard disk, so it would +have failed with ENOTTY and the patch isn't changing anything in +practice. Still, I'm treating it specially to avoid spamming the logs. + +In principle, this restriction should include programs running with +CAP_SYS_RAWIO. If for example I let a program access /dev/sda2 and +/dev/sdb, it still should not be able to read/write outside the +boundaries of /dev/sda2 independent of the capabilities. However, for +now programs with CAP_SYS_RAWIO will still be allowed to send the +ioctls. Their actions will still be logged. + +This patch does not affect the non-libata IDE driver. That driver +however already tests for bd != bd->bd_contains before issuing some +ioctl; it could be restricted further to forbid these ioctls even for +programs running with CAP_SYS_ADMIN/CAP_SYS_RAWIO. + +[ Cherry picked from 3ed4e7ba4be8c72051d87dcb2dec279d97a18d41 + + Changes with respect to 3.3: return -ENOTTY from scsi_verify_blk_ioctl + and -ENOIOCTLCMD from sd_compat_ioctl. ] + +Cc: stable@kernel.org +Cc: linux-scsi@vger.kernel.org +Cc: Jens Axboe +Cc: James Bottomley +Signed-off-by: Paolo Bonzini +[ Make it also print the command name when warning - Linus ] +Signed-off-by: Linus Torvalds +--- + block/scsi_ioctl.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ + drivers/scsi/sd.c | 11 +++++++++-- + include/linux/blkdev.h | 1 + + 3 files changed, 55 insertions(+), 2 deletions(-) + +diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c +index a2c11f3..688be8a 100644 +--- a/block/scsi_ioctl.c ++++ b/block/scsi_ioctl.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -690,9 +691,53 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod + } + EXPORT_SYMBOL(scsi_cmd_ioctl); + ++int scsi_verify_blk_ioctl(struct block_device *bd, unsigned int cmd) ++{ ++ if (bd && bd == bd->bd_contains) ++ return 0; ++ ++ /* Actually none of these is particularly useful on a partition, ++ * but they are safe. ++ */ ++ switch (cmd) { ++ case SCSI_IOCTL_GET_IDLUN: ++ case SCSI_IOCTL_GET_BUS_NUMBER: ++ case SCSI_IOCTL_GET_PCI: ++ case SCSI_IOCTL_PROBE_HOST: ++ case SG_GET_VERSION_NUM: ++ case SG_SET_TIMEOUT: ++ case SG_GET_TIMEOUT: ++ case SG_GET_RESERVED_SIZE: ++ case SG_SET_RESERVED_SIZE: ++ case SG_EMULATED_HOST: ++ return 0; ++ case CDROM_GET_CAPABILITY: ++ /* Keep this until we remove the printk below. udev sends it ++ * and we do not want to spam dmesg about it. CD-ROMs do ++ * not have partitions, so we get here only for disks. ++ */ ++ return -ENOTTY; ++ default: ++ break; ++ } ++ ++ /* In particular, rule out all resets and host-specific ioctls. */ ++ printk_ratelimited(KERN_WARNING ++ "%s: sending ioctl %x to a partition!\n", current->comm, cmd); ++ ++ return capable(CAP_SYS_RAWIO) ? 0 : -ENOTTY; ++} ++EXPORT_SYMBOL(scsi_verify_blk_ioctl); ++ + int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode, + unsigned int cmd, void __user *arg) + { ++ int ret; ++ ++ ret = scsi_verify_blk_ioctl(bd, cmd); ++ if (ret < 0) ++ return ret; ++ + return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg); + } + EXPORT_SYMBOL(scsi_cmd_blk_ioctl); +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index ffa1c79..4b63c73 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -1074,6 +1074,10 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, + SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, " + "cmd=0x%x\n", disk->disk_name, cmd)); + ++ error = scsi_verify_blk_ioctl(bdev, cmd); ++ if (error < 0) ++ return error; ++ + /* + * If we are in the middle of error recovery, don't let anyone + * else try and use this device. Also, if error recovery fails, it +@@ -1266,6 +1270,11 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) + { + struct scsi_device *sdev = scsi_disk(bdev->bd_disk)->device; ++ int ret; ++ ++ ret = scsi_verify_blk_ioctl(bdev, cmd); ++ if (ret < 0) ++ return -ENOIOCTLCMD; + + /* + * If we are in the middle of error recovery, don't let anyone +@@ -1277,8 +1286,6 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, + return -ENODEV; + + if (sdev->host->hostt->compat_ioctl) { +- int ret; +- + ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg); + + return ret; +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index ca7b869..0ed1eb0 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -675,6 +675,7 @@ extern int blk_insert_cloned_request(struct request_queue *q, + struct request *rq); + extern void blk_delay_queue(struct request_queue *, unsigned long); + extern void blk_recount_segments(struct request_queue *, struct bio *); ++extern int scsi_verify_blk_ioctl(struct block_device *, unsigned int); + extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t, + unsigned int, void __user *); + extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t, +-- +1.7.7.6 + diff --git a/03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch b/03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch index 129edd974..e13255091 100644 --- a/03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch +++ b/03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch @@ -1,4 +1,4 @@ -From bf50a5715cac3b85f3bd33f184f7c031debabe0b Mon Sep 17 00:00:00 2001 +From 0d18592f2fcd3891e5955362565ea12d0846bf9f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 16 Jan 2012 17:13:00 +0100 Subject: [PATCH 3/3] dm: do not forward ioctls from logical volumes to the @@ -87,5 +87,5 @@ index 5e0090e..801d92d 100644 } -- -1.7.7.5 +1.7.7.6 diff --git a/kernel.spec b/kernel.spec index 952be2b6c..c254a99db 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -781,6 +781,10 @@ Patch21074: KVM-x86-fix-missing-checks-in-syscall-emulation.patch #rhbz 728740 Patch21076: rtl8192cu-Fix-WARNING-on-suspend-resume.patch +Patch21077: 01-block-add-and-use-scsi_blk_cmd_ioctl.patch +Patch21078: 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch +Patch21079: 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch + #rhbz752176 Patch21080: sysfs-msi-irq-per-device.patch @@ -1492,6 +1496,11 @@ ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch #rhbz 728740 ApplyPatch rtl8192cu-Fix-WARNING-on-suspend-resume.patch +#rhbz 769911 +ApplyPatch 01-block-add-and-use-scsi_blk_cmd_ioctl.patch +ApplyPatch 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch +ApplyPatch 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch + #rhbz 782686 ApplyPatch procfs-parse-mount-options.patch ApplyPatch procfs-add-hidepid-and-gid-mount-options.patch @@ -2288,6 +2297,7 @@ fi %changelog * Tue Jan 24 2012 Josh Boyer - Re-enable the ARCMSR module (rhbz 784287) +- Add back a set of patches that were erroneously dropped during the rebase * Mon Jan 23 2012 Josh Boyer 3.2.1-3 - Fix oops in iwlwifi/iwlagn driver (rhbz 766071) From bb1165406c967187c01391de51bb170064112ee9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 24 Jan 2012 14:33:03 -0500 Subject: [PATCH 239/487] Re-enable the LIRC_STAGING drivers (rhbz 784398) --- config-generic | 3 ++- kernel.spec | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 5cf25778f..bd2c47654 100644 --- a/config-generic +++ b/config-generic @@ -4408,7 +4408,8 @@ CONFIG_UWB_WHCI=m CONFIG_UWB_I1480U=m CONFIG_STAGING=y -# CONFIG_STAGING_MEDIA is not set +CONFIG_STAGING_MEDIA=y +# CONFIG_DVB_AS102 is not set # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set # CONFIG_WLAGS49_H2 is not set diff --git a/kernel.spec b/kernel.spec index c254a99db..ef9e2ea07 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2298,6 +2298,7 @@ fi * Tue Jan 24 2012 Josh Boyer - Re-enable the ARCMSR module (rhbz 784287) - Add back a set of patches that were erroneously dropped during the rebase +- Re-enable the LIRC_STAGING drivers (rhbz 784398) * Mon Jan 23 2012 Josh Boyer 3.2.1-3 - Fix oops in iwlwifi/iwlagn driver (rhbz 766071) From 8879a2cf41d3d64941bf10e2e98a272c0394ba8d Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 24 Jan 2012 15:27:32 -0500 Subject: [PATCH 240/487] Update compat-wireless snapshot to version 3.3-rc1-2 --- ...o-avoid-duplicating-device-support-w.patch | 47 +++++++++++++++ bcma-brcmsmac-compat.patch | 35 ----------- ...-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch | 29 ---------- compat-wireless-config-fixups.patch | 58 +++++++------------ kernel.spec | 24 ++++---- sources | 2 +- 6 files changed, 80 insertions(+), 115 deletions(-) create mode 100644 b43-add-option-to-avoid-duplicating-device-support-w.patch delete mode 100644 bcma-brcmsmac-compat.patch delete mode 100644 compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch diff --git a/b43-add-option-to-avoid-duplicating-device-support-w.patch b/b43-add-option-to-avoid-duplicating-device-support-w.patch new file mode 100644 index 000000000..63d28cdea --- /dev/null +++ b/b43-add-option-to-avoid-duplicating-device-support-w.patch @@ -0,0 +1,47 @@ +From 4f3d09de38d234ce7ffba5ec5a7e6704f983d375 Mon Sep 17 00:00:00 2001 +From: John W. Linville +Date: Wed, 11 Jan 2012 15:50:15 -0500 +Subject: [PATCH] b43: add option to avoid duplicating device support with + brcmsmac + +Signed-off-by: John W. Linville +--- + drivers/net/wireless/b43/Kconfig | 6 ++++++ + drivers/net/wireless/b43/main.c | 2 ++ + 2 files changed, 8 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig +index b97a40e..3876c7e 100644 +--- a/drivers/net/wireless/b43/Kconfig ++++ b/drivers/net/wireless/b43/Kconfig +@@ -31,6 +31,12 @@ config B43_BCMA + depends on B43 && BCMA + default y + ++config B43_BCMA_EXTRA ++ bool "Hardware support that overlaps with the brcmsmac driver" ++ depends on B43_BCMA ++ default n if BRCMSMAC || BRCMSMAC_MODULE ++ default y ++ + config B43_SSB + bool + depends on B43 && SSB +diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c +index b91f28e..23ffb1b 100644 +--- a/drivers/net/wireless/b43/main.c ++++ b/drivers/net/wireless/b43/main.c +@@ -116,8 +116,10 @@ MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO"); + #ifdef CONFIG_B43_BCMA + static const struct bcma_device_id b43_bcma_tbl[] = { + BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS), ++#ifdef CONFIG_B43_BCMA_EXTRA + BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS), + BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS), ++#endif + BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS), + BCMA_CORETABLE_END + }; +-- +1.7.4.4 + diff --git a/bcma-brcmsmac-compat.patch b/bcma-brcmsmac-compat.patch deleted file mode 100644 index e16e5b0c5..000000000 --- a/bcma-brcmsmac-compat.patch +++ /dev/null @@ -1,35 +0,0 @@ -Simple patch to remove the overlap between the bcma (i.e. b43) driver -and the brcmsmac driver. David Woodhouse -confirmed that this patch restores functionality of bcm4331 devices. - --- John W. Linville - -diff -up linux-3.1.x86_64/drivers/bcma/host_pci.c.orig linux-3.1.x86_64/drivers/bcma/host_pci.c ---- linux-3.1.x86_64/drivers/bcma/host_pci.c.orig 2011-11-10 11:41:26.829742757 -0500 -+++ linux-3.1.x86_64/drivers/bcma/host_pci.c 2011-11-10 11:41:22.884792078 -0500 -@@ -225,11 +225,13 @@ static void bcma_host_pci_remove(struct - } - - static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { -- { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, -+#if 0 /* Not in Fedora... */ -+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, -+#endif - { 0, }, - }; - MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl); -diff -up linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig ---- linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig.orig 2011-11-10 11:42:31.764930961 -0500 -+++ linux-3.1.x86_64/drivers/net/wireless/brcm80211/Kconfig 2011-11-10 11:42:33.613907846 -0500 -@@ -5,7 +5,6 @@ config BRCMSMAC - tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" - depends on PCI - depends on MAC80211 -- depends on BCMA=n - select BRCMUTIL - select FW_LOADER - select CRC_CCITT diff --git a/compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch b/compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch deleted file mode 100644 index 98caeb56f..000000000 --- a/compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch +++ /dev/null @@ -1,29 +0,0 @@ -From c5cfdf2d138ba20a648990d9615c44942eef5fd3 Mon Sep 17 00:00:00 2001 -From: John W. Linville -Date: Fri, 18 Nov 2011 13:46:18 -0500 -Subject: [PATCH] compat-wireless: change CONFIG_IWLAGN -> CONFIG_IWLWIFI - -This Kconfig option changed in the 2.6.32 timeframe. - -Signed-off-by: John W. Linville -Signed-off-by: Luis R. Rodriguez ---- - config.mk | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/config.mk b/config.mk -index 0e964a5..05edb79 100644 ---- a/config.mk -+++ b/config.mk -@@ -285,7 +285,7 @@ ifdef CONFIG_PCI - CONFIG_ATH5K_PCI=y - CONFIG_ATH9K_PCI=y - --CONFIG_IWLAGN=m -+CONFIG_IWLWIFI=m - # CONFIG_IWLWIFI_DEBUG=y - # CONFIG_IWLWIFI_DEBUGFS=y - # CONFIG_IWLWIFI_DEVICE_TRACING=y --- -1.7.4.4 - diff --git a/compat-wireless-config-fixups.patch b/compat-wireless-config-fixups.patch index 938f35c5c..722c6c820 100644 --- a/compat-wireless-config-fixups.patch +++ b/compat-wireless-config-fixups.patch @@ -1,6 +1,6 @@ -diff -up compat-wireless-2011-12-18/config.mk.orig compat-wireless-2011-12-18/config.mk ---- compat-wireless-2011-12-18/config.mk.orig 2012-01-05 13:54:21.214595837 -0500 -+++ compat-wireless-2011-12-18/config.mk 2012-01-05 13:54:35.668415136 -0500 +diff -up compat-wireless-3.3-rc1-2/config.mk.orig compat-wireless-3.3-rc1-2/config.mk +--- compat-wireless-3.3-rc1-2/config.mk.orig 2012-01-21 02:00:21.000000000 -0500 ++++ compat-wireless-3.3-rc1-2/config.mk 2012-01-24 15:16:38.204409844 -0500 @@ -14,6 +14,9 @@ else include $(KLIB_BUILD)/.config endif @@ -11,33 +11,15 @@ diff -up compat-wireless-2011-12-18/config.mk.orig compat-wireless-2011-12-18/co ifneq ($(wildcard $(KLIB_BUILD)/Makefile),) COMPAT_LATEST_VERSION = 3 -@@ -395,7 +398,7 @@ ifdef CONFIG_CRC_CCITT - CONFIG_RT2800PCI=m - CONFIG_RT2800PCI_RT33XX=y - CONFIG_RT2800PCI_RT35XX=y --# CONFIG_RT2800PCI_RT53XX=y -+CONFIG_RT2800PCI_RT53XX=y - endif #CONFIG_CRC_CCITT - NEED_RT2X00=y - -@@ -525,7 +528,7 @@ ifdef CONFIG_CRC_CCITT - CONFIG_RT2800USB=m - CONFIG_RT2800USB_RT33XX=y - CONFIG_RT2800USB_RT35XX=y --# CONFIG_RT2800USB_RT53XX=y -+CONFIG_RT2800USB_RT53XX=y - CONFIG_RT2800USB_UNKNOWN=y - endif #CONFIG_CRC_CCITT - CONFIG_RT2X00_LIB_USB=m -diff -up compat-wireless-2011-12-18/drivers/misc/eeprom/Makefile.orig compat-wireless-2011-12-18/drivers/misc/eeprom/Makefile ---- compat-wireless-2011-12-18/drivers/misc/eeprom/Makefile.orig 2012-01-05 13:54:21.214595837 -0500 -+++ compat-wireless-2011-12-18/drivers/misc/eeprom/Makefile 2012-01-05 13:54:27.274520077 -0500 +diff -up compat-wireless-3.3-rc1-2/drivers/misc/eeprom/Makefile.orig compat-wireless-3.3-rc1-2/drivers/misc/eeprom/Makefile +--- compat-wireless-3.3-rc1-2/drivers/misc/eeprom/Makefile.orig 2012-01-21 02:08:39.000000000 -0500 ++++ compat-wireless-3.3-rc1-2/drivers/misc/eeprom/Makefile 2012-01-24 15:16:38.204409844 -0500 @@ -1 +1 @@ -obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o +#obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o -diff -up compat-wireless-2011-12-18/drivers/net/ethernet/atheros/Makefile.orig compat-wireless-2011-12-18/drivers/net/ethernet/atheros/Makefile ---- compat-wireless-2011-12-18/drivers/net/ethernet/atheros/Makefile.orig 2012-01-05 13:54:21.215595824 -0500 -+++ compat-wireless-2011-12-18/drivers/net/ethernet/atheros/Makefile 2012-01-05 13:54:27.275520064 -0500 +diff -up compat-wireless-3.3-rc1-2/drivers/net/ethernet/atheros/Makefile.orig compat-wireless-3.3-rc1-2/drivers/net/ethernet/atheros/Makefile +--- compat-wireless-3.3-rc1-2/drivers/net/ethernet/atheros/Makefile.orig 2012-01-21 02:08:39.000000000 -0500 ++++ compat-wireless-3.3-rc1-2/drivers/net/ethernet/atheros/Makefile 2012-01-24 15:16:38.204409844 -0500 @@ -2,7 +2,7 @@ # Makefile for the Atheros network device drivers. # @@ -50,9 +32,9 @@ diff -up compat-wireless-2011-12-18/drivers/net/ethernet/atheros/Makefile.orig c +#obj-$(CONFIG_ATL2) += atlx/ +#obj-$(CONFIG_ATL1E) += atl1e/ +#obj-$(CONFIG_ATL1C) += atl1c/ -diff -up compat-wireless-2011-12-18/drivers/net/usb/Makefile.orig compat-wireless-2011-12-18/drivers/net/usb/Makefile ---- compat-wireless-2011-12-18/drivers/net/usb/Makefile.orig 2012-01-05 13:54:21.215595824 -0500 -+++ compat-wireless-2011-12-18/drivers/net/usb/Makefile 2012-01-05 13:54:27.275520064 -0500 +diff -up compat-wireless-3.3-rc1-2/drivers/net/usb/Makefile.orig compat-wireless-3.3-rc1-2/drivers/net/usb/Makefile +--- compat-wireless-3.3-rc1-2/drivers/net/usb/Makefile.orig 2012-01-21 02:08:39.000000000 -0500 ++++ compat-wireless-3.3-rc1-2/drivers/net/usb/Makefile 2012-01-24 15:16:38.205409832 -0500 @@ -2,7 +2,7 @@ # Makefile for USB Network drivers # @@ -64,21 +46,21 @@ diff -up compat-wireless-2011-12-18/drivers/net/usb/Makefile.orig compat-wireles +#obj-$(CONFIG_USB_NET_COMPAT_RNDIS_HOST) += rndis_host.o +#obj-$(CONFIG_USB_COMPAT_USBNET) += usbnet.o -diff -up compat-wireless-2011-12-18/Makefile.orig compat-wireless-2011-12-18/Makefile ---- compat-wireless-2011-12-18/Makefile.orig 2012-01-05 13:54:21.216595811 -0500 -+++ compat-wireless-2011-12-18/Makefile 2012-01-05 13:54:27.276520051 -0500 -@@ -8,8 +8,8 @@ endif - export KLIB_BUILD ?= $(KLIB)/build - # Sometimes not available in the path +diff -up compat-wireless-3.3-rc1-2/Makefile.orig compat-wireless-3.3-rc1-2/Makefile +--- compat-wireless-3.3-rc1-2/Makefile.orig 2012-01-21 02:00:21.000000000 -0500 ++++ compat-wireless-3.3-rc1-2/Makefile 2012-01-24 15:17:34.524705743 -0500 +@@ -10,8 +10,8 @@ export KLIB_BUILD ?= $(KLIB)/build MODPROBE := /sbin/modprobe + + ifneq ($(wildcard $(MODPROBE)),) -MADWIFI=$(shell $(MODPROBE) -l ath_pci) -OLD_IWL=$(shell $(MODPROBE) -l iwl4965) +MADWIFI="" +OLD_IWL="" + endif DESTDIR?= - -@@ -41,8 +41,8 @@ endif +@@ -44,8 +44,8 @@ endif endif diff --git a/kernel.spec b/kernel.spec index ef9e2ea07..95da15653 100644 --- a/kernel.spec +++ b/kernel.spec @@ -205,7 +205,7 @@ Summary: The Linux kernel %define kversion 3.%{base_sublevel} # The compat-wireless version -%define cwversion 3.2-1 +%define cwversion 3.3-rc1-2 ####################################################################### # If cwversion is less than kversion, make sure with_backports is @@ -215,7 +215,7 @@ Summary: The Linux kernel # # (Uncomment the '#' and both spaces below to disable with_backports.) # -%define with_backports 0 +# % define with_backports 0 ####################################################################### %define make_target bzImage @@ -822,9 +822,11 @@ Patch22000: rcu-reintroduce-missing-calls.patch # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch -Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch -Patch50002: compat-wireless-pr_fmt-warning-avoidance.patch -Patch50003: compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch +Patch50001: compat-wireless-pr_fmt-warning-avoidance.patch +Patch50002: compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch + +# Remove overlapping hardware support between b43 and brcmsmac +Patch50100: b43-add-option-to-avoid-duplicating-device-support-w.patch %endif @@ -1582,17 +1584,12 @@ rm -rf compat-wireless-%{cwversion} cd compat-wireless-%{cwversion} ApplyPatch compat-wireless-config-fixups.patch -ApplyPatch compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch ApplyPatch compat-wireless-pr_fmt-warning-avoidance.patch ApplyPatch compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch -ApplyPatch mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch ApplyPatch mac80211-fix-work-removal-on-deauth-request.patch -#rhbz 731365, 773271 -ApplyPatch mac80211_offchannel_rework_revert.patch - -# Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 -ApplyPatch bcma-brcmsmac-compat.patch +# Remove overlapping hardware support between b43 and brcmsmac +ApplyPatch b43-add-option-to-avoid-duplicating-device-support-w.patch cd .. @@ -2295,6 +2292,9 @@ fi # and build. %changelog +* Tue Jan 24 2012 John W. Linville +- Update compat-wireless snapshot to version 3.3-rc1-2 + * Tue Jan 24 2012 Josh Boyer - Re-enable the ARCMSR module (rhbz 784287) - Add back a set of patches that were erroneously dropped during the rebase diff --git a/sources b/sources index 7401701d6..dfe5aaeb3 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz -204381bc537b689edcb15df0efed6467 compat-wireless-3.2-1.tar.bz2 62ac6ac9b870162f693ecf5e8606423a patch-3.2.1.xz +8cfe037a7a7a356278ec3638e25ad506 compat-wireless-3.3-rc1-2.tar.bz2 From fb68683a8ff418b75a8088761feffbbd6e71c2a0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 24 Jan 2012 22:48:56 -0500 Subject: [PATCH 241/487] Backport patch to fix oops in rds (rhbz 718790) --- kernel.spec | 9 ++ ...ds_sock_lock-BH-rather-than-IRQ-safe.patch | 116 ++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch diff --git a/kernel.spec b/kernel.spec index 95da15653..b7a4ec68c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -817,6 +817,9 @@ Patch21228: SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch #rhbz 766071 Patch21229: iwlagn-check-for-SMPS-mode.patch +#rhbz 718790 +Patch21230: rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch + Patch22000: rcu-reintroduce-missing-calls.patch @@ -1521,6 +1524,9 @@ ApplyPatch iwlagn-check-for-SMPS-mode.patch ApplyPatch rcu-reintroduce-missing-calls.patch +#rhbz 718790 +ApplyPatch rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch + # END OF PATCH APPLICATIONS %endif @@ -2292,6 +2298,9 @@ fi # and build. %changelog +* Wed Jan 25 2012 Josh Boyer +- Backport patch to fix oops in rds (rhbz 718790) + * Tue Jan 24 2012 John W. Linville - Update compat-wireless snapshot to version 3.3-rc1-2 diff --git a/rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch b/rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch new file mode 100644 index 000000000..0946aad6b --- /dev/null +++ b/rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch @@ -0,0 +1,116 @@ +From efc3dbc37412c027e363736b4f4c74ee5e8ecffc Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Tue, 24 Jan 2012 17:03:44 -0500 +Subject: [PATCH] rds: Make rds_sock_lock BH rather than IRQ safe. + +rds_sock_info() triggers locking warnings because we try to perform a +local_bh_enable() (via sock_i_ino()) while hardware interrupts are +disabled (via taking rds_sock_lock). + +There is no reason for rds_sock_lock to be a hardware IRQ disabling +lock, none of these access paths run in hardware interrupt context. + +Therefore making it a BH disabling lock is safe and sufficient to +fix this bug. + +Reported-by: Kumar Sanghvi +Reported-by: Josh Boyer +Signed-off-by: David S. Miller +--- + net/rds/af_rds.c | 20 ++++++++------------ + 1 files changed, 8 insertions(+), 12 deletions(-) + +diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c +index bb6ad81..424ff62 100644 +--- a/net/rds/af_rds.c ++++ b/net/rds/af_rds.c +@@ -68,7 +68,6 @@ static int rds_release(struct socket *sock) + { + struct sock *sk = sock->sk; + struct rds_sock *rs; +- unsigned long flags; + + if (!sk) + goto out; +@@ -94,10 +93,10 @@ static int rds_release(struct socket *sock) + rds_rdma_drop_keys(rs); + rds_notify_queue_get(rs, NULL); + +- spin_lock_irqsave(&rds_sock_lock, flags); ++ spin_lock_bh(&rds_sock_lock); + list_del_init(&rs->rs_item); + rds_sock_count--; +- spin_unlock_irqrestore(&rds_sock_lock, flags); ++ spin_unlock_bh(&rds_sock_lock); + + rds_trans_put(rs->rs_transport); + +@@ -409,7 +408,6 @@ static const struct proto_ops rds_proto_ops = { + + static int __rds_create(struct socket *sock, struct sock *sk, int protocol) + { +- unsigned long flags; + struct rds_sock *rs; + + sock_init_data(sock, sk); +@@ -426,10 +424,10 @@ static int __rds_create(struct socket *sock, struct sock *sk, int protocol) + spin_lock_init(&rs->rs_rdma_lock); + rs->rs_rdma_keys = RB_ROOT; + +- spin_lock_irqsave(&rds_sock_lock, flags); ++ spin_lock_bh(&rds_sock_lock); + list_add_tail(&rs->rs_item, &rds_sock_list); + rds_sock_count++; +- spin_unlock_irqrestore(&rds_sock_lock, flags); ++ spin_unlock_bh(&rds_sock_lock); + + return 0; + } +@@ -471,12 +469,11 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len, + { + struct rds_sock *rs; + struct rds_incoming *inc; +- unsigned long flags; + unsigned int total = 0; + + len /= sizeof(struct rds_info_message); + +- spin_lock_irqsave(&rds_sock_lock, flags); ++ spin_lock_bh(&rds_sock_lock); + + list_for_each_entry(rs, &rds_sock_list, rs_item) { + read_lock(&rs->rs_recv_lock); +@@ -492,7 +489,7 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len, + read_unlock(&rs->rs_recv_lock); + } + +- spin_unlock_irqrestore(&rds_sock_lock, flags); ++ spin_unlock_bh(&rds_sock_lock); + + lens->nr = total; + lens->each = sizeof(struct rds_info_message); +@@ -504,11 +501,10 @@ static void rds_sock_info(struct socket *sock, unsigned int len, + { + struct rds_info_socket sinfo; + struct rds_sock *rs; +- unsigned long flags; + + len /= sizeof(struct rds_info_socket); + +- spin_lock_irqsave(&rds_sock_lock, flags); ++ spin_lock_bh(&rds_sock_lock); + + if (len < rds_sock_count) + goto out; +@@ -529,7 +525,7 @@ out: + lens->nr = rds_sock_count; + lens->each = sizeof(struct rds_info_socket); + +- spin_unlock_irqrestore(&rds_sock_lock, flags); ++ spin_unlock_bh(&rds_sock_lock); + } + + static void rds_exit(void) +-- +1.7.7.6 + From 6d0a652dcdd974ea05e5492cad055de602b82929 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 25 Jan 2012 15:49:38 -0500 Subject: [PATCH 242/487] modpost: add option to allow external modules to avoid taint Make integrated compat-wireless take advantage of the above --- compat-wireless-integrated-build.patch | 12 +++ kernel.spec | 16 +++- ...on-to-allow-external-modules-to-avoi.patch | 80 +++++++++++++++++++ 3 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 compat-wireless-integrated-build.patch create mode 100644 modpost-add-option-to-allow-external-modules-to-avoi.patch diff --git a/compat-wireless-integrated-build.patch b/compat-wireless-integrated-build.patch new file mode 100644 index 000000000..1d08e4b58 --- /dev/null +++ b/compat-wireless-integrated-build.patch @@ -0,0 +1,12 @@ +diff -up compat-wireless-2011-12-01/Makefile.orig compat-wireless-2011-12-01/Makefile +--- compat-wireless-2011-12-01/Makefile.orig 2011-12-14 09:10:01.377297637 -0500 ++++ compat-wireless-2011-12-01/Makefile 2011-12-14 09:47:36.834100534 -0500 +@@ -68,7 +68,7 @@ all: modules + + modules: $(CREL_CHECK) + @./scripts/check_config.sh +- $(MAKE) -C $(KLIB_BUILD) M=$(PWD) modules ++ $(MAKE) -C $(KLIB_BUILD) M=$(PWD) INTEGRATED_BUILD=1 modules + @touch $@ + + bt: $(CREL_CHECK) diff --git a/kernel.spec b/kernel.spec index b7a4ec68c..f5ea9bd26 100644 --- a/kernel.spec +++ b/kernel.spec @@ -701,6 +701,7 @@ Patch471: floppy-drop-disable_hlt-warning.patch Patch510: linux-2.6-silence-noise.patch Patch520: quite-apm.patch Patch530: linux-2.6-silence-fbcon-logo.patch +Patch540: modpost-add-option-to-allow-external-modules-to-avoi.patch Patch700: linux-2.6-e1000-ich9-montevina.patch @@ -826,10 +827,12 @@ Patch22000: rcu-reintroduce-missing-calls.patch # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-pr_fmt-warning-avoidance.patch -Patch50002: compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch +Patch50002: compat-wireless-integrated-build.patch + +Patch50100: compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch # Remove overlapping hardware support between b43 and brcmsmac -Patch50100: b43-add-option-to-avoid-duplicating-device-support-w.patch +Patch50101: b43-add-option-to-avoid-duplicating-device-support-w.patch %endif @@ -1416,6 +1419,11 @@ ApplyPatch linux-2.6-silence-noise.patch # Make fbcon not show the penguins with 'quiet' ApplyPatch linux-2.6-silence-fbcon-logo.patch +%if %{with_backports} +# modpost: add option to allow external modules to avoid taint +ApplyPatch modpost-add-option-to-allow-external-modules-to-avoi.patch +%endif + # Changes to upstream defaults. @@ -2298,6 +2306,10 @@ fi # and build. %changelog +* Wed Jan 25 2012 John W. Linville +- modpost: add option to allow external modules to avoid taint +- Make integrated compat-wireless take advantage of the above + * Wed Jan 25 2012 Josh Boyer - Backport patch to fix oops in rds (rhbz 718790) diff --git a/modpost-add-option-to-allow-external-modules-to-avoi.patch b/modpost-add-option-to-allow-external-modules-to-avoi.patch new file mode 100644 index 000000000..d20385457 --- /dev/null +++ b/modpost-add-option-to-allow-external-modules-to-avoi.patch @@ -0,0 +1,80 @@ +From 69f63a67165da5e9f08c1132521598701d914573 Mon Sep 17 00:00:00 2001 +From: John W. Linville +Date: Wed, 14 Dec 2011 11:09:04 -0500 +Subject: [PATCH] modpost: add option to allow external modules to avoid taint + +In some cases, it might be desirable to package a module from an +external source tree alongside the base kernel. In those cases, it +might also be desirable to not have those modules tainting the kernel. + +This patch provides a mechanism for an external module build to declare +itself as an "integrated build". Such a module is then treated the same +as an intree module. + +Signed-off-by: John W. Linville +--- +Any thoughts on this? I'm thinking of adding this to Fedora kernels, +where I have been working to integrate the compat-wireless package as +part of the base kernel RPM. + + scripts/Makefile.modpost | 1 + + scripts/mod/modpost.c | 10 ++++++++-- + 2 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost +index 08dce14..160c6fb 100644 +--- a/scripts/Makefile.modpost ++++ b/scripts/Makefile.modpost +@@ -81,6 +81,7 @@ modpost = scripts/mod/modpost \ + $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ + $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \ + $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \ ++ $(if $(INTEGRATED_BUILD),-B) \ + $(if $(cross_build),-c) + + quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules +diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c +index 2bd594e..5d077f9 100644 +--- a/scripts/mod/modpost.c ++++ b/scripts/mod/modpost.c +@@ -43,6 +43,9 @@ static int warn_unresolved = 0; + static int sec_mismatch_count = 0; + static int sec_mismatch_verbose = 1; + ++/* Is this a module being built as part of an integrated package? */ ++static int integrated_build = 0; ++ + enum export { + export_plain, export_unused, export_gpl, + export_unused_gpl, export_gpl_future, export_unknown +@@ -1851,7 +1854,7 @@ static void add_header(struct buffer *b, struct module *mod) + + static void add_intree_flag(struct buffer *b, int is_intree) + { +- if (is_intree) ++ if (is_intree || integrated_build) + buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n"); + } + +@@ -2101,7 +2104,7 @@ int main(int argc, char **argv) + struct ext_sym_list *extsym_iter; + struct ext_sym_list *extsym_start = NULL; + +- while ((opt = getopt(argc, argv, "i:I:e:cmsSo:awM:K:")) != -1) { ++ while ((opt = getopt(argc, argv, "i:I:e:cmsSo:awM:K:B")) != -1) { + switch (opt) { + case 'i': + kernel_read = optarg; +@@ -2139,6 +2142,9 @@ int main(int argc, char **argv) + case 'w': + warn_unresolved = 1; + break; ++ case 'B': ++ integrated_build = 1; ++ break; + default: + exit(1); + } +-- +1.7.4.4 + From 8f7167dc2950e1a8c6a4b00e6dd3c1d70d6fd1fb Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 25 Jan 2012 17:08:55 -0500 Subject: [PATCH 243/487] Add patch to invalidate parent cache when fsync is called on a partition (rhbz 783211) --- ...block-device-if-fsync-called-on-part.patch | 106 ++++++++++++++++++ kernel.spec | 12 +- 2 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch diff --git a/fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch b/fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch new file mode 100644 index 000000000..5bab4f4ad --- /dev/null +++ b/fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch @@ -0,0 +1,106 @@ +Path: news.gmane.org!not-for-mail +From: Niels de Vos +Newsgroups: gmane.linux.kernel,gmane.linux.file-systems +Subject: [PATCH v2] fs: Invalidate the cache for a parent block-device if fsync() is called for a partition +Date: Mon, 23 Jan 2012 10:38:29 +0000 +Lines: 58 +Approved: news@gmane.org +Message-ID: <1327315109-7740-1-git-send-email-ndevos@redhat.com> +References: <4F19356E.3020708@redhat.com> +NNTP-Posting-Host: lo.gmane.org +X-Trace: dough.gmane.org 1327315263 30652 80.91.229.12 (23 Jan 2012 10:41:03 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Mon, 23 Jan 2012 10:41:03 +0000 (UTC) +Cc: linux-kernel@vger.kernel.org, Niels de Vos , + "Bryn M. Reeves" , + Mikulas Patocka +To: linux-fsdevel@vger.kernel.org +Original-X-From: linux-kernel-owner@vger.kernel.org Mon Jan 23 11:40:58 2012 +Return-path: +Envelope-to: glk-linux-kernel-3@lo.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by lo.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1RpHKb-0008Bu-Fh + for glk-linux-kernel-3@lo.gmane.org; Mon, 23 Jan 2012 11:40:57 +0100 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1753263Ab2AWKkt (ORCPT ); + Mon, 23 Jan 2012 05:40:49 -0500 +Original-Received: from mx1.redhat.com ([209.132.183.28]:58739 "EHLO mx1.redhat.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1751990Ab2AWKks (ORCPT ); + Mon, 23 Jan 2012 05:40:48 -0500 +Original-Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q0NAelMx027033 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Mon, 23 Jan 2012 05:40:47 -0500 +Original-Received: from ndevos.usersys.redhat.com (dhcp-1-51.fab.redhat.com [10.33.1.51]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q0NAejLn013691; + Mon, 23 Jan 2012 05:40:46 -0500 +In-Reply-To: <4F19356E.3020708@redhat.com> +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +Original-Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel:1242432 gmane.linux.file-systems:60751 +Archived-At: + +Executing an fsync() on a file-descriptor of a partition flushes the +caches for that partition by calling blkdev_issue_flush(). However, it +seems that reading data through the parent device will still return the +old cached data. + +The cache for the block-device is not synced if the block-device is kept +open (due to a mounted partition, for example). Only when all users for +the disk have exited, the cache for the disk is made consistent again. + +Calling invalidate_bdev() on the parent block-device in case +blkdev_fsync() was called for a partition, fixes this. + +The problem can be worked around by forcing the caches to be flushed +with either + # blockdev --flushbufs ${dev_disk} +or + # echo 3 > /proc/sys/vm/drop_caches + +CC: Bryn M. Reeves +CC: Mikulas Patocka +Signed-off-by: Niels de Vos + +--- +v2: +- Do not call invalidate_bdev() from blkdev_issue_flush() and prevent + performance degration with journalled filesystems. + + Suggested was to call invalidate_bdev() in fsync_bdev(), but this is + not in the call-path of mkfs.ext3 and similar tools. Hence the issue + persists. + +- Correct phrasing a little, changing ioctl-BLKFLSBUF is not required. + +- This issue also occurs when doing an ioctl-BLKFLSBUF on a partition. + Reading the whole disk will still return cached data. If this is an + issue, it will need a seperate patch. +--- + fs/block_dev.c | 4 ++++ + 1 files changed, 4 insertions(+), 0 deletions(-) + +diff --git a/fs/block_dev.c b/fs/block_dev.c +index 0e575d1..433c4de 100644 +--- a/fs/block_dev.c ++++ b/fs/block_dev.c +@@ -424,6 +424,10 @@ int blkdev_fsync(struct file *filp, loff_t start, loff_t end, int datasync) + if (error == -EOPNOTSUPP) + error = 0; + ++ /* invalidate parent block_device */ ++ if (!error && bdev != bdev->bd_contains) ++ invalidate_bdev(bdev->bd_contains); ++ + return error; + } + EXPORT_SYMBOL(blkdev_fsync); +-- +1.7.6.5 + diff --git a/kernel.spec b/kernel.spec index f5ea9bd26..d6207a7c1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -797,6 +797,9 @@ Patch21084: proc-fix-null-pointer-deref-in-proc_pid_permission.patch #rhbz 782681 Patch21085: proc-clean-up-and-fix-proc-pid-mem-handling.patch +#rhbz 783211 +Patch21087: fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch + #rhbz 771058 Patch22100: msi-irq-sysfs-warning.patch @@ -823,7 +826,6 @@ Patch21230: rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch Patch22000: rcu-reintroduce-missing-calls.patch - # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-pr_fmt-warning-avoidance.patch @@ -834,6 +836,7 @@ Patch50100: compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch # Remove overlapping hardware support between b43 and brcmsmac Patch50101: b43-add-option-to-avoid-duplicating-device-support-w.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1535,6 +1538,9 @@ ApplyPatch rcu-reintroduce-missing-calls.patch #rhbz 718790 ApplyPatch rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch +#rhbz 783211 +ApplyPatch fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch + # END OF PATCH APPLICATIONS %endif @@ -2306,6 +2312,10 @@ fi # and build. %changelog +* Wed Jan 25 2012 Josh Boyer +- Add patch to invalidate parent cache when fsync is called on a partition + (rhbz 783211) + * Wed Jan 25 2012 John W. Linville - modpost: add option to allow external modules to avoid taint - Make integrated compat-wireless take advantage of the above From 95885cbd27b9cb30828f76aab9bd515c19ae59a0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 25 Jan 2012 20:00:28 -0500 Subject: [PATCH 244/487] Linux 3.2.2 --- 01-block-add-and-use-scsi_blk_cmd_ioctl.patch | 166 ----- ...passthrough-ioctls-on-partition-devs.patch | 165 ----- ...wd-ioctls-from-LVs-to-underlying-dev.patch | 91 --- ...ix-NULL-pointer-dereference-in-slave.patch | 35 -- iwlagn-check-for-SMPS-mode.patch | 43 -- kernel.spec | 40 +- mac80211_offchannel_rework_revert.patch | 594 ------------------ ...ean-up-and-fix-proc-pid-mem-handling.patch | 268 -------- sources | 2 +- 9 files changed, 5 insertions(+), 1399 deletions(-) delete mode 100644 01-block-add-and-use-scsi_blk_cmd_ioctl.patch delete mode 100644 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch delete mode 100644 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch delete mode 100644 SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch delete mode 100644 iwlagn-check-for-SMPS-mode.patch delete mode 100644 mac80211_offchannel_rework_revert.patch delete mode 100644 proc-clean-up-and-fix-proc-pid-mem-handling.patch diff --git a/01-block-add-and-use-scsi_blk_cmd_ioctl.patch b/01-block-add-and-use-scsi_blk_cmd_ioctl.patch deleted file mode 100644 index 259bf6912..000000000 --- a/01-block-add-and-use-scsi_blk_cmd_ioctl.patch +++ /dev/null @@ -1,166 +0,0 @@ -From a7f3cbff409dde86b6bded8978f71bc193022427 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 16 Jan 2012 17:12:58 +0100 -Subject: [PATCH 1/3] block: add and use scsi_blk_cmd_ioctl - -Introduce a wrapper around scsi_cmd_ioctl that takes a block device. - -The function will then be enhanced to detect partition block devices -and, in that case, subject the ioctls to whitelisting. - -[ Cherry picked from 6ad62f051ef784a48a6103af289f91b5c472e955 ] - -Cc: stable@kernel.org -Cc: linux-scsi@vger.kernel.org -Cc: Jens Axboe -Cc: James Bottomley -Signed-off-by: Paolo Bonzini -Signed-off-by: Linus Torvalds ---- - block/scsi_ioctl.c | 7 +++++++ - drivers/block/cciss.c | 6 +++--- - drivers/block/ub.c | 3 +-- - drivers/block/virtio_blk.c | 4 ++-- - drivers/cdrom/cdrom.c | 3 +-- - drivers/ide/ide-floppy_ioctl.c | 3 +-- - drivers/scsi/sd.c | 2 +- - include/linux/blkdev.h | 2 ++ - 8 files changed, 18 insertions(+), 12 deletions(-) - -diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c -index fbdf0d8..a2c11f3 100644 ---- a/block/scsi_ioctl.c -+++ b/block/scsi_ioctl.c -@@ -690,6 +690,13 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod - } - EXPORT_SYMBOL(scsi_cmd_ioctl); - -+int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode, -+ unsigned int cmd, void __user *arg) -+{ -+ return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg); -+} -+EXPORT_SYMBOL(scsi_cmd_blk_ioctl); -+ - static int __init blk_scsi_ioctl_init(void) - { - blk_set_cmd_filter_defaults(&blk_default_cmd_filter); -diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c -index 587cce5..b0f553b 100644 ---- a/drivers/block/cciss.c -+++ b/drivers/block/cciss.c -@@ -1735,7 +1735,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, - case CCISS_BIG_PASSTHRU: - return cciss_bigpassthru(h, argp); - -- /* scsi_cmd_ioctl handles these, below, though some are not */ -+ /* scsi_cmd_blk_ioctl handles these, below, though some are not */ - /* very meaningful for cciss. SG_IO is the main one people want. */ - - case SG_GET_VERSION_NUM: -@@ -1746,9 +1746,9 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, - case SG_EMULATED_HOST: - case SG_IO: - case SCSI_IOCTL_SEND_COMMAND: -- return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp); -+ return scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); - -- /* scsi_cmd_ioctl would normally handle these, below, but */ -+ /* scsi_cmd_blk_ioctl would normally handle these, below, but */ - /* they aren't a good fit for cciss, as CD-ROMs are */ - /* not supported, and we don't have any bus/target/lun */ - /* which we present to the kernel. */ -diff --git a/drivers/block/ub.c b/drivers/block/ub.c -index 0e376d4..7333b9e 100644 ---- a/drivers/block/ub.c -+++ b/drivers/block/ub.c -@@ -1744,12 +1744,11 @@ static int ub_bd_release(struct gendisk *disk, fmode_t mode) - static int ub_bd_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) - { -- struct gendisk *disk = bdev->bd_disk; - void __user *usermem = (void __user *) arg; - int ret; - - mutex_lock(&ub_mutex); -- ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, usermem); -+ ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, usermem); - mutex_unlock(&ub_mutex); - - return ret; -diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c -index 4d0b70a..e46f2f7 100644 ---- a/drivers/block/virtio_blk.c -+++ b/drivers/block/virtio_blk.c -@@ -243,8 +243,8 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, - if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI)) - return -ENOTTY; - -- return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, -- (void __user *)data); -+ return scsi_cmd_blk_ioctl(bdev, mode, cmd, -+ (void __user *)data); - } - - /* We provide getgeo only to please some old bootloader/partitioning tools */ -diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c -index f997c27..cedb231 100644 ---- a/drivers/cdrom/cdrom.c -+++ b/drivers/cdrom/cdrom.c -@@ -2747,12 +2747,11 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev, - { - void __user *argp = (void __user *)arg; - int ret; -- struct gendisk *disk = bdev->bd_disk; - - /* - * Try the generic SCSI command ioctl's first. - */ -- ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp); -+ ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); - if (ret != -ENOTTY) - return ret; - -diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c -index d267b7a..a22ca84 100644 ---- a/drivers/ide/ide-floppy_ioctl.c -+++ b/drivers/ide/ide-floppy_ioctl.c -@@ -292,8 +292,7 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev, - * and CDROM_SEND_PACKET (legacy) ioctls - */ - if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND) -- err = scsi_cmd_ioctl(bdev->bd_disk->queue, bdev->bd_disk, -- mode, cmd, argp); -+ err = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); - - if (err == -ENOTTY) - err = generic_ide_ioctl(drive, bdev, cmd, arg); -diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c -index fa3a591..ffa1c79 100644 ---- a/drivers/scsi/sd.c -+++ b/drivers/scsi/sd.c -@@ -1096,7 +1096,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, - error = scsi_ioctl(sdp, cmd, p); - break; - default: -- error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p); -+ error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p); - if (error != -ENOTTY) - break; - error = scsi_ioctl(sdp, cmd, p); -diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h -index 94acd81..ca7b869 100644 ---- a/include/linux/blkdev.h -+++ b/include/linux/blkdev.h -@@ -675,6 +675,8 @@ extern int blk_insert_cloned_request(struct request_queue *q, - struct request *rq); - extern void blk_delay_queue(struct request_queue *, unsigned long); - extern void blk_recount_segments(struct request_queue *, struct bio *); -+extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t, -+ unsigned int, void __user *); - extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t, - unsigned int, void __user *); - extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t, --- -1.7.7.6 - diff --git a/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch b/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch deleted file mode 100644 index ce3e50a5d..000000000 --- a/02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch +++ /dev/null @@ -1,165 +0,0 @@ -From 51c6b870e10bbf60ee6a115216cfa7549addfce0 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 16 Jan 2012 17:12:59 +0100 -Subject: [PATCH 2/3] block: fail SCSI passthrough ioctls on partition devices - -Linux allows executing the SG_IO ioctl on a partition or LVM volume, and -will pass the command to the underlying block device. This is -well-known, but it is also a large security problem when (via Unix -permissions, ACLs, SELinux or a combination thereof) a program or user -needs to be granted access only to part of the disk. - -This patch lets partitions forward a small set of harmless ioctls; -others are logged with printk so that we can see which ioctls are -actually sent. In my tests only CDROM_GET_CAPABILITY actually occurred. -Of course it was being sent to a (partition on a) hard disk, so it would -have failed with ENOTTY and the patch isn't changing anything in -practice. Still, I'm treating it specially to avoid spamming the logs. - -In principle, this restriction should include programs running with -CAP_SYS_RAWIO. If for example I let a program access /dev/sda2 and -/dev/sdb, it still should not be able to read/write outside the -boundaries of /dev/sda2 independent of the capabilities. However, for -now programs with CAP_SYS_RAWIO will still be allowed to send the -ioctls. Their actions will still be logged. - -This patch does not affect the non-libata IDE driver. That driver -however already tests for bd != bd->bd_contains before issuing some -ioctl; it could be restricted further to forbid these ioctls even for -programs running with CAP_SYS_ADMIN/CAP_SYS_RAWIO. - -[ Cherry picked from 3ed4e7ba4be8c72051d87dcb2dec279d97a18d41 - - Changes with respect to 3.3: return -ENOTTY from scsi_verify_blk_ioctl - and -ENOIOCTLCMD from sd_compat_ioctl. ] - -Cc: stable@kernel.org -Cc: linux-scsi@vger.kernel.org -Cc: Jens Axboe -Cc: James Bottomley -Signed-off-by: Paolo Bonzini -[ Make it also print the command name when warning - Linus ] -Signed-off-by: Linus Torvalds ---- - block/scsi_ioctl.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ - drivers/scsi/sd.c | 11 +++++++++-- - include/linux/blkdev.h | 1 + - 3 files changed, 55 insertions(+), 2 deletions(-) - -diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c -index a2c11f3..688be8a 100644 ---- a/block/scsi_ioctl.c -+++ b/block/scsi_ioctl.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -690,9 +691,53 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod - } - EXPORT_SYMBOL(scsi_cmd_ioctl); - -+int scsi_verify_blk_ioctl(struct block_device *bd, unsigned int cmd) -+{ -+ if (bd && bd == bd->bd_contains) -+ return 0; -+ -+ /* Actually none of these is particularly useful on a partition, -+ * but they are safe. -+ */ -+ switch (cmd) { -+ case SCSI_IOCTL_GET_IDLUN: -+ case SCSI_IOCTL_GET_BUS_NUMBER: -+ case SCSI_IOCTL_GET_PCI: -+ case SCSI_IOCTL_PROBE_HOST: -+ case SG_GET_VERSION_NUM: -+ case SG_SET_TIMEOUT: -+ case SG_GET_TIMEOUT: -+ case SG_GET_RESERVED_SIZE: -+ case SG_SET_RESERVED_SIZE: -+ case SG_EMULATED_HOST: -+ return 0; -+ case CDROM_GET_CAPABILITY: -+ /* Keep this until we remove the printk below. udev sends it -+ * and we do not want to spam dmesg about it. CD-ROMs do -+ * not have partitions, so we get here only for disks. -+ */ -+ return -ENOTTY; -+ default: -+ break; -+ } -+ -+ /* In particular, rule out all resets and host-specific ioctls. */ -+ printk_ratelimited(KERN_WARNING -+ "%s: sending ioctl %x to a partition!\n", current->comm, cmd); -+ -+ return capable(CAP_SYS_RAWIO) ? 0 : -ENOTTY; -+} -+EXPORT_SYMBOL(scsi_verify_blk_ioctl); -+ - int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode, - unsigned int cmd, void __user *arg) - { -+ int ret; -+ -+ ret = scsi_verify_blk_ioctl(bd, cmd); -+ if (ret < 0) -+ return ret; -+ - return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg); - } - EXPORT_SYMBOL(scsi_cmd_blk_ioctl); -diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c -index ffa1c79..4b63c73 100644 ---- a/drivers/scsi/sd.c -+++ b/drivers/scsi/sd.c -@@ -1074,6 +1074,10 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, - SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, " - "cmd=0x%x\n", disk->disk_name, cmd)); - -+ error = scsi_verify_blk_ioctl(bdev, cmd); -+ if (error < 0) -+ return error; -+ - /* - * If we are in the middle of error recovery, don't let anyone - * else try and use this device. Also, if error recovery fails, it -@@ -1266,6 +1270,11 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) - { - struct scsi_device *sdev = scsi_disk(bdev->bd_disk)->device; -+ int ret; -+ -+ ret = scsi_verify_blk_ioctl(bdev, cmd); -+ if (ret < 0) -+ return -ENOIOCTLCMD; - - /* - * If we are in the middle of error recovery, don't let anyone -@@ -1277,8 +1286,6 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, - return -ENODEV; - - if (sdev->host->hostt->compat_ioctl) { -- int ret; -- - ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg); - - return ret; -diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h -index ca7b869..0ed1eb0 100644 ---- a/include/linux/blkdev.h -+++ b/include/linux/blkdev.h -@@ -675,6 +675,7 @@ extern int blk_insert_cloned_request(struct request_queue *q, - struct request *rq); - extern void blk_delay_queue(struct request_queue *, unsigned long); - extern void blk_recount_segments(struct request_queue *, struct bio *); -+extern int scsi_verify_blk_ioctl(struct block_device *, unsigned int); - extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t, - unsigned int, void __user *); - extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t, --- -1.7.7.6 - diff --git a/03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch b/03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch deleted file mode 100644 index e13255091..000000000 --- a/03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 0d18592f2fcd3891e5955362565ea12d0846bf9f Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 16 Jan 2012 17:13:00 +0100 -Subject: [PATCH 3/3] dm: do not forward ioctls from logical volumes to the - underlying device - -A logical volume can map to just part of underlying physical volume. -In this case, it must be treated like a partition. - -Based on a patch from Alasdair G Kergon. - -[ Cherry picked from 95113a17a2a1eb06151dc698dca9bcc4a29e4fbb ] - -Cc: stable@kernel.org -Cc: Alasdair G Kergon -Cc: dm-devel@redhat.com -Cc: linux-scsi@vger.kernel.org -Signed-off-by: Paolo Bonzini -Signed-off-by: Linus Torvalds ---- - drivers/md/dm-flakey.c | 11 ++++++++++- - drivers/md/dm-linear.c | 12 +++++++++++- - drivers/md/dm-mpath.c | 6 ++++++ - 3 files changed, 27 insertions(+), 2 deletions(-) - -diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c -index f84c080..9fb18c1 100644 ---- a/drivers/md/dm-flakey.c -+++ b/drivers/md/dm-flakey.c -@@ -368,8 +368,17 @@ static int flakey_status(struct dm_target *ti, status_type_t type, - static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg) - { - struct flakey_c *fc = ti->private; -+ struct dm_dev *dev = fc->dev; -+ int r = 0; - -- return __blkdev_driver_ioctl(fc->dev->bdev, fc->dev->mode, cmd, arg); -+ /* -+ * Only pass ioctls through if the device sizes match exactly. -+ */ -+ if (fc->start || -+ ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) -+ r = scsi_verify_blk_ioctl(NULL, cmd); -+ -+ return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg); - } - - static int flakey_merge(struct dm_target *ti, struct bvec_merge_data *bvm, -diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c -index 3921e3b..9728839 100644 ---- a/drivers/md/dm-linear.c -+++ b/drivers/md/dm-linear.c -@@ -116,7 +116,17 @@ static int linear_ioctl(struct dm_target *ti, unsigned int cmd, - unsigned long arg) - { - struct linear_c *lc = (struct linear_c *) ti->private; -- return __blkdev_driver_ioctl(lc->dev->bdev, lc->dev->mode, cmd, arg); -+ struct dm_dev *dev = lc->dev; -+ int r = 0; -+ -+ /* -+ * Only pass ioctls through if the device sizes match exactly. -+ */ -+ if (lc->start || -+ ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) -+ r = scsi_verify_blk_ioctl(NULL, cmd); -+ -+ return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg); - } - - static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm, -diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c -index 5e0090e..801d92d 100644 ---- a/drivers/md/dm-mpath.c -+++ b/drivers/md/dm-mpath.c -@@ -1520,6 +1520,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, - - spin_unlock_irqrestore(&m->lock, flags); - -+ /* -+ * Only pass ioctls through if the device sizes match exactly. -+ */ -+ if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) -+ r = scsi_verify_blk_ioctl(NULL, cmd); -+ - return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); - } - --- -1.7.7.6 - diff --git a/SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch b/SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch deleted file mode 100644 index 369012744..000000000 --- a/SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch +++ /dev/null @@ -1,35 +0,0 @@ -From cced5041ed5a2d1352186510944b0ddfbdbe4c0b Mon Sep 17 00:00:00 2001 -From: Stratos Psomadakis -Date: Sun, 4 Dec 2011 02:23:54 +0200 -Subject: [PATCH] [SCSI] sym53c8xx: Fix NULL pointer dereference in - slave_destroy - -sym53c8xx_slave_destroy unconditionally assumes that sym53c8xx_slave_alloc has -succesesfully allocated a sym_lcb. This can lead to a NULL pointer dereference -(exposed by commit 4e6c82b). - -Signed-off-by: Stratos Psomadakis -Cc: stable@vger.kernel.org -Signed-off-by: James Bottomley ---- - drivers/scsi/sym53c8xx_2/sym_glue.c | 4 ++++ - 1 files changed, 4 insertions(+), 0 deletions(-) - -diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c -index b4543f5..36d1ed7 100644 ---- a/drivers/scsi/sym53c8xx_2/sym_glue.c -+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c -@@ -839,6 +839,10 @@ static void sym53c8xx_slave_destroy(struct scsi_device *sdev) - struct sym_lcb *lp = sym_lp(tp, sdev->lun); - unsigned long flags; - -+ /* if slave_alloc returned before allocating a sym_lcb, return */ -+ if (!lp) -+ return; -+ - spin_lock_irqsave(np->s.host->host_lock, flags); - - if (lp->busy_itlq || lp->busy_itl) { --- -1.7.7.5 - diff --git a/iwlagn-check-for-SMPS-mode.patch b/iwlagn-check-for-SMPS-mode.patch deleted file mode 100644 index ae42747ea..000000000 --- a/iwlagn-check-for-SMPS-mode.patch +++ /dev/null @@ -1,43 +0,0 @@ -From b2ccccdca46273c7b321ecf5041c362cd950da20 Mon Sep 17 00:00:00 2001 -From: Wey-Yi Guy -Date: Thu, 10 Nov 2011 06:55:04 -0800 -Subject: [PATCH] iwlagn: check for SMPS mode - -Check and report WARN only when its invalid - -Signed-off-by: Wey-Yi Guy -Signed-off-by: John W. Linville ---- - drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 1 + - drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 3 +++ - 2 files changed, 4 insertions(+), 0 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c -index 1a52ed2..6465983 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c -@@ -827,6 +827,7 @@ static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) - case IEEE80211_SMPS_STATIC: - case IEEE80211_SMPS_DYNAMIC: - return IWL_NUM_IDLE_CHAINS_SINGLE; -+ case IEEE80211_SMPS_AUTOMATIC: - case IEEE80211_SMPS_OFF: - return active_cnt; - default: -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -index 4c52bee..8e45fba 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -@@ -542,6 +542,9 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) - - mutex_lock(&priv->shrd->mutex); - -+ if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) -+ goto out; -+ - if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) { - IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); - goto out; --- -1.7.7.5 - diff --git a/kernel.spec b/kernel.spec index d6207a7c1..5b7b8c978 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 1 +%define stable_update 2 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -782,10 +782,6 @@ Patch21074: KVM-x86-fix-missing-checks-in-syscall-emulation.patch #rhbz 728740 Patch21076: rtl8192cu-Fix-WARNING-on-suspend-resume.patch -Patch21077: 01-block-add-and-use-scsi_blk_cmd_ioctl.patch -Patch21078: 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch -Patch21079: 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch - #rhbz752176 Patch21080: sysfs-msi-irq-per-device.patch @@ -794,9 +790,6 @@ Patch21082: procfs-parse-mount-options.patch Patch21083: procfs-add-hidepid-and-gid-mount-options.patch Patch21084: proc-fix-null-pointer-deref-in-proc_pid_permission.patch -#rhbz 782681 -Patch21085: proc-clean-up-and-fix-proc-pid-mem-handling.patch - #rhbz 783211 Patch21087: fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch @@ -806,21 +799,12 @@ Patch22100: msi-irq-sysfs-warning.patch # rhbz 754907 Patch21101: hpsa-add-irqf-shared.patch -#rhbz 731365 -Patch21220: mac80211_offchannel_rework_revert.patch - Patch21225: pci-Rework-ASPM-disable-code.patch Patch21226: pci-crs-blacklist.patch Patch21227: mac80211-fix-work-removal-on-deauth-request.patch -#rhbz 781625 -Patch21228: SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch - -#rhbz 766071 -Patch21229: iwlagn-check-for-SMPS-mode.patch - #rhbz 718790 Patch21230: rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch @@ -1482,9 +1466,6 @@ ApplyPatch sysfs-msi-irq-per-device.patch # rhbz 754907 ApplyPatch hpsa-add-irqf-shared.patch -#rhbz 731365 -ApplyPatch mac80211_offchannel_rework_revert.patch - ApplyPatch pci-Rework-ASPM-disable-code.patch #ApplyPatch pci-crs-blacklist.patch @@ -1512,27 +1493,13 @@ ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch #rhbz 728740 ApplyPatch rtl8192cu-Fix-WARNING-on-suspend-resume.patch -#rhbz 769911 -ApplyPatch 01-block-add-and-use-scsi_blk_cmd_ioctl.patch -ApplyPatch 02-block-fail-SCSI-passthrough-ioctls-on-partition-devs.patch -ApplyPatch 03-dm-dont-fwd-ioctls-from-LVs-to-underlying-dev.patch - #rhbz 782686 ApplyPatch procfs-parse-mount-options.patch ApplyPatch procfs-add-hidepid-and-gid-mount-options.patch ApplyPatch proc-fix-null-pointer-deref-in-proc_pid_permission.patch -#rhbz 782681 -ApplyPatch proc-clean-up-and-fix-proc-pid-mem-handling.patch - ApplyPatch mac80211-fix-work-removal-on-deauth-request.patch -#rhbz 781625 -ApplyPatch SCSI-sym53c8xx-Fix-NULL-pointer-dereference-in-slave.patch - -#rhbz 766071 -ApplyPatch iwlagn-check-for-SMPS-mode.patch - ApplyPatch rcu-reintroduce-missing-calls.patch #rhbz 718790 @@ -2312,7 +2279,8 @@ fi # and build. %changelog -* Wed Jan 25 2012 Josh Boyer +* Wed Jan 25 2012 Josh Boyer - 3.2.2-1 +- Linux 3.2.2 - Add patch to invalidate parent cache when fsync is called on a partition (rhbz 783211) diff --git a/mac80211_offchannel_rework_revert.patch b/mac80211_offchannel_rework_revert.patch deleted file mode 100644 index 859799714..000000000 --- a/mac80211_offchannel_rework_revert.patch +++ /dev/null @@ -1,594 +0,0 @@ -diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h -index 9fab144..4f8cf7f 100644 ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -694,6 +694,8 @@ struct tpt_led_trigger { - * well be on the operating channel - * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to - * determine if we are on the operating channel or not -+ * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning, -+ * gets only set in conjunction with SCAN_SW_SCANNING - * @SCAN_COMPLETED: Set for our scan work function when the driver reported - * that the scan completed. - * @SCAN_ABORTED: Set for our scan work function when the driver reported -@@ -702,6 +704,7 @@ struct tpt_led_trigger { - enum { - SCAN_SW_SCANNING, - SCAN_HW_SCANNING, -+ SCAN_OFF_CHANNEL, - SCAN_COMPLETED, - SCAN_ABORTED, - }; -@@ -1197,14 +1200,10 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); - void ieee80211_sched_scan_stopped_work(struct work_struct *work); - - /* off-channel helpers */ --bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local); --void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, -- bool tell_ap); --void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, -- bool offchannel_ps_enable); -+void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local); -+void ieee80211_offchannel_stop_station(struct ieee80211_local *local); - void ieee80211_offchannel_return(struct ieee80211_local *local, -- bool enable_beaconing, -- bool offchannel_ps_disable); -+ bool enable_beaconing); - void ieee80211_hw_roc_setup(struct ieee80211_local *local); - - /* interface handling */ -diff --git a/net/mac80211/main.c b/net/mac80211/main.c -index acb4423..2d607e5 100644 ---- a/net/mac80211/main.c -+++ b/net/mac80211/main.c -@@ -92,47 +92,6 @@ static void ieee80211_reconfig_filter(struct work_struct *work) - ieee80211_configure_filter(local); - } - --/* -- * Returns true if we are logically configured to be on -- * the operating channel AND the hardware-conf is currently -- * configured on the operating channel. Compares channel-type -- * as well. -- */ --bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local) --{ -- struct ieee80211_channel *chan, *scan_chan; -- enum nl80211_channel_type channel_type; -- -- /* This logic needs to match logic in ieee80211_hw_config */ -- if (local->scan_channel) { -- chan = local->scan_channel; -- /* If scanning on oper channel, use whatever channel-type -- * is currently in use. -- */ -- if (chan == local->oper_channel) -- channel_type = local->_oper_channel_type; -- else -- channel_type = NL80211_CHAN_NO_HT; -- } else if (local->tmp_channel) { -- chan = scan_chan = local->tmp_channel; -- channel_type = local->tmp_channel_type; -- } else { -- chan = local->oper_channel; -- channel_type = local->_oper_channel_type; -- } -- -- if (chan != local->oper_channel || -- channel_type != local->_oper_channel_type) -- return false; -- -- /* Check current hardware-config against oper_channel. */ -- if ((local->oper_channel != local->hw.conf.channel) || -- (local->_oper_channel_type != local->hw.conf.channel_type)) -- return false; -- -- return true; --} -- - int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) - { - struct ieee80211_channel *chan, *scan_chan; -@@ -145,9 +104,6 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) - - scan_chan = local->scan_channel; - -- /* If this off-channel logic ever changes, ieee80211_on_oper_channel -- * may need to change as well. -- */ - offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; - if (scan_chan) { - chan = scan_chan; -@@ -158,19 +114,17 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) - channel_type = local->_oper_channel_type; - else - channel_type = NL80211_CHAN_NO_HT; -- } else if (local->tmp_channel) { -+ local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; -+ } else if (local->tmp_channel && -+ local->oper_channel != local->tmp_channel) { - chan = scan_chan = local->tmp_channel; - channel_type = local->tmp_channel_type; -+ local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; - } else { - chan = local->oper_channel; - channel_type = local->_oper_channel_type; -- } -- -- if (chan != local->oper_channel || -- channel_type != local->_oper_channel_type) -- local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; -- else - local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; -+ } - - offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; - -@@ -279,7 +233,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, - - if (changed & BSS_CHANGED_BEACON_ENABLED) { - if (local->quiescing || !ieee80211_sdata_running(sdata) || -- test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) { -+ test_bit(SCAN_SW_SCANNING, &local->scanning)) { - sdata->vif.bss_conf.enable_beacon = false; - } else { - /* -diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c -index 13427b1..b4e5267 100644 ---- a/net/mac80211/offchannel.c -+++ b/net/mac80211/offchannel.c -@@ -17,14 +17,10 @@ - #include "driver-trace.h" - - /* -- * Tell our hardware to disable PS. -- * Optionally inform AP that we will go to sleep so that it will buffer -- * the frames while we are doing off-channel work. This is optional -- * because we *may* be doing work on-operating channel, and want our -- * hardware unconditionally awake, but still let the AP send us normal frames. -+ * inform AP that we will go to sleep so that it will buffer the frames -+ * while we scan - */ --static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata, -- bool tell_ap) -+static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) - { - struct ieee80211_local *local = sdata->local; - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; -@@ -45,8 +41,8 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata, - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); - } - -- if (tell_ap && (!local->offchannel_ps_enabled || -- !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))) -+ if (!(local->offchannel_ps_enabled) || -+ !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) - /* - * If power save was enabled, no need to send a nullfunc - * frame because AP knows that we are sleeping. But if the -@@ -81,9 +77,6 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) - * we are sleeping, let's just enable power save mode in - * hardware. - */ -- /* TODO: Only set hardware if CONF_PS changed? -- * TODO: Should we set offchannel_ps_enabled to false? -- */ - local->hw.conf.flags |= IEEE80211_CONF_PS; - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); - } else if (local->hw.conf.dynamic_ps_timeout > 0) { -@@ -102,61 +95,63 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) - ieee80211_sta_reset_conn_monitor(sdata); - } - --void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, -- bool offchannel_ps_enable) -+void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) - { - struct ieee80211_sub_if_data *sdata; - -- /* -- * notify the AP about us leaving the channel and stop all -- * STA interfaces. -- */ - mutex_lock(&local->iflist_mtx); - list_for_each_entry(sdata, &local->interfaces, list) { - if (!ieee80211_sdata_running(sdata)) - continue; - -- if (sdata->vif.type != NL80211_IFTYPE_MONITOR) -- set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); -- -- /* Check to see if we should disable beaconing. */ -+ /* disable beaconing */ - if (sdata->vif.type == NL80211_IFTYPE_AP || - sdata->vif.type == NL80211_IFTYPE_ADHOC || - sdata->vif.type == NL80211_IFTYPE_MESH_POINT) - ieee80211_bss_info_change_notify( - sdata, BSS_CHANGED_BEACON_ENABLED); - -- if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { -+ /* -+ * only handle non-STA interfaces here, STA interfaces -+ * are handled in ieee80211_offchannel_stop_station(), -+ * e.g., from the background scan state machine. -+ * -+ * In addition, do not stop monitor interface to allow it to be -+ * used from user space controlled off-channel operations. -+ */ -+ if (sdata->vif.type != NL80211_IFTYPE_STATION && -+ sdata->vif.type != NL80211_IFTYPE_MONITOR) { -+ set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); - netif_tx_stop_all_queues(sdata->dev); -- if (offchannel_ps_enable && -- (sdata->vif.type == NL80211_IFTYPE_STATION) && -- sdata->u.mgd.associated) -- ieee80211_offchannel_ps_enable(sdata, true); - } - } - mutex_unlock(&local->iflist_mtx); - } - --void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, -- bool tell_ap) -+void ieee80211_offchannel_stop_station(struct ieee80211_local *local) - { - struct ieee80211_sub_if_data *sdata; - -+ /* -+ * notify the AP about us leaving the channel and stop all STA interfaces -+ */ - mutex_lock(&local->iflist_mtx); - list_for_each_entry(sdata, &local->interfaces, list) { - if (!ieee80211_sdata_running(sdata)) - continue; - -- if (sdata->vif.type == NL80211_IFTYPE_STATION && -- sdata->u.mgd.associated) -- ieee80211_offchannel_ps_enable(sdata, tell_ap); -+ if (sdata->vif.type == NL80211_IFTYPE_STATION) { -+ set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); -+ netif_tx_stop_all_queues(sdata->dev); -+ if (sdata->u.mgd.associated) -+ ieee80211_offchannel_ps_enable(sdata); -+ } - } - mutex_unlock(&local->iflist_mtx); - } - - void ieee80211_offchannel_return(struct ieee80211_local *local, -- bool enable_beaconing, -- bool offchannel_ps_disable) -+ bool enable_beaconing) - { - struct ieee80211_sub_if_data *sdata; - -@@ -166,8 +161,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, - continue; - - /* Tell AP we're back */ -- if (offchannel_ps_disable && -- sdata->vif.type == NL80211_IFTYPE_STATION) { -+ if (sdata->vif.type == NL80211_IFTYPE_STATION) { - if (sdata->u.mgd.associated) - ieee80211_offchannel_ps_disable(sdata); - } -@@ -187,7 +181,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, - netif_tx_wake_all_queues(sdata->dev); - } - -- /* Check to see if we should re-enable beaconing */ -+ /* re-enable beaconing */ - if (enable_beaconing && - (sdata->vif.type == NL80211_IFTYPE_AP || - sdata->vif.type == NL80211_IFTYPE_ADHOC || -diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c -index fe2c2a7..b46880e 100644 ---- a/net/mac80211/rx.c -+++ b/net/mac80211/rx.c -@@ -417,10 +417,16 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) - return RX_CONTINUE; - - if (test_bit(SCAN_HW_SCANNING, &local->scanning) || -- test_bit(SCAN_SW_SCANNING, &local->scanning) || - local->sched_scanning) - return ieee80211_scan_rx(rx->sdata, skb); - -+ if (test_bit(SCAN_SW_SCANNING, &local->scanning)) { -+ /* drop all the other packets during a software scan anyway */ -+ if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED) -+ dev_kfree_skb(skb); -+ return RX_QUEUED; -+ } -+ - /* scanning finished during invoking of handlers */ - I802_DEBUG_INC(local->rx_handlers_drop_passive_scan); - return RX_DROP_UNUSABLE; -@@ -2771,7 +2777,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, - local->dot11ReceivedFragmentCount++; - - if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || -- test_bit(SCAN_SW_SCANNING, &local->scanning))) -+ test_bit(SCAN_OFF_CHANNEL, &local->scanning))) - status->rx_flags |= IEEE80211_RX_IN_SCAN; - - if (ieee80211_is_mgmt(fc)) -diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c -index 6f09eca..2ba4977 100644 ---- a/net/mac80211/scan.c -+++ b/net/mac80211/scan.c -@@ -212,14 +212,6 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) - if (bss) - ieee80211_rx_bss_put(sdata->local, bss); - -- /* If we are on-operating-channel, and this packet is for the -- * current channel, pass the pkt on up the stack so that -- * the rest of the stack can make use of it. -- */ -- if (ieee80211_cfg_on_oper_channel(sdata->local) -- && (channel == sdata->local->oper_channel)) -- return RX_CONTINUE; -- - dev_kfree_skb(skb); - return RX_QUEUED; - } -@@ -262,8 +254,6 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, - bool was_hw_scan) - { - struct ieee80211_local *local = hw_to_local(hw); -- bool on_oper_chan; -- bool enable_beacons = false; - - lockdep_assert_held(&local->mtx); - -@@ -296,25 +286,11 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, - local->scanning = 0; - local->scan_channel = NULL; - -- on_oper_chan = ieee80211_cfg_on_oper_channel(local); -- -- if (was_hw_scan || !on_oper_chan) -- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); -- else -- /* Set power back to normal operating levels. */ -- ieee80211_hw_config(local, 0); -- -+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); - if (!was_hw_scan) { -- bool on_oper_chan2; - ieee80211_configure_filter(local); - drv_sw_scan_complete(local); -- on_oper_chan2 = ieee80211_cfg_on_oper_channel(local); -- /* We should always be on-channel at this point. */ -- WARN_ON(!on_oper_chan2); -- if (on_oper_chan2 && (on_oper_chan != on_oper_chan2)) -- enable_beacons = true; -- -- ieee80211_offchannel_return(local, enable_beacons, true); -+ ieee80211_offchannel_return(local, true); - } - - ieee80211_recalc_idle(local); -@@ -355,15 +331,13 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) - */ - drv_sw_scan_start(local); - -+ ieee80211_offchannel_stop_beaconing(local); -+ - local->leave_oper_channel_time = 0; - local->next_scan_state = SCAN_DECISION; - local->scan_channel_idx = 0; - -- /* We always want to use off-channel PS, even if we -- * are not really leaving oper-channel. Don't -- * tell the AP though, as long as we are on-channel. -- */ -- ieee80211_offchannel_enable_all_ps(local, false); -+ drv_flush(local, false); - - ieee80211_configure_filter(local); - -@@ -506,20 +480,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, - } - mutex_unlock(&local->iflist_mtx); - -- next_chan = local->scan_req->channels[local->scan_channel_idx]; -- -- if (ieee80211_cfg_on_oper_channel(local)) { -- /* We're currently on operating channel. */ -- if (next_chan == local->oper_channel) -- /* We don't need to move off of operating channel. */ -- local->next_scan_state = SCAN_SET_CHANNEL; -- else -- /* -- * We do need to leave operating channel, as next -- * scan is somewhere else. -- */ -- local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; -- } else { -+ if (local->scan_channel) { - /* - * we're currently scanning a different channel, let's - * see if we can scan another channel without interfering -@@ -535,6 +496,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, - * - * Otherwise switch back to the operating channel. - */ -+ next_chan = local->scan_req->channels[local->scan_channel_idx]; - - bad_latency = time_after(jiffies + - ieee80211_scan_get_channel_time(next_chan), -@@ -552,6 +514,12 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, - local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; - else - local->next_scan_state = SCAN_SET_CHANNEL; -+ } else { -+ /* -+ * we're on the operating channel currently, let's -+ * leave that channel now to scan another one -+ */ -+ local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; - } - - *next_delay = 0; -@@ -560,10 +528,9 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, - static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, - unsigned long *next_delay) - { -- /* PS will already be in off-channel mode, -- * we do that once at the beginning of scanning. -- */ -- ieee80211_offchannel_stop_vifs(local, false); -+ ieee80211_offchannel_stop_station(local); -+ -+ __set_bit(SCAN_OFF_CHANNEL, &local->scanning); - - /* - * What if the nullfunc frames didn't arrive? -@@ -586,15 +553,15 @@ static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *loca - { - /* switch back to the operating channel */ - local->scan_channel = NULL; -- if (!ieee80211_cfg_on_oper_channel(local)) -- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); -+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); - - /* -- * Re-enable vifs and beaconing. Leave PS -- * in off-channel state..will put that back -- * on-channel at the end of scanning. -+ * Only re-enable station mode interface now; beaconing will be -+ * re-enabled once the full scan has been completed. - */ -- ieee80211_offchannel_return(local, true, false); -+ ieee80211_offchannel_return(local, false); -+ -+ __clear_bit(SCAN_OFF_CHANNEL, &local->scanning); - - *next_delay = HZ / 5; - local->next_scan_state = SCAN_DECISION; -diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c -index 8cb0d2d..54ea022 100644 ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -258,8 +258,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) - if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) - return TX_CONTINUE; - -- if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) && -- test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) && -+ if (unlikely(test_bit(SCAN_OFF_CHANNEL, &tx->local->scanning)) && - !ieee80211_is_probe_req(hdr->frame_control) && - !ieee80211_is_nullfunc(hdr->frame_control)) - /* -diff --git a/net/mac80211/work.c b/net/mac80211/work.c -index 7737f20..b76bf33 100644 ---- a/net/mac80211/work.c -+++ b/net/mac80211/work.c -@@ -901,26 +901,6 @@ static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct, - return false; - } - --static enum nl80211_channel_type --ieee80211_calc_ct(enum nl80211_channel_type wk_ct, -- enum nl80211_channel_type oper_ct) --{ -- switch (wk_ct) { -- case NL80211_CHAN_NO_HT: -- return oper_ct; -- case NL80211_CHAN_HT20: -- if (oper_ct != NL80211_CHAN_NO_HT) -- return oper_ct; -- return wk_ct; -- case NL80211_CHAN_HT40MINUS: -- case NL80211_CHAN_HT40PLUS: -- return wk_ct; -- } -- WARN_ON(1); /* shouldn't get here */ -- return wk_ct; --} -- -- - static void ieee80211_work_timer(unsigned long data) - { - struct ieee80211_local *local = (void *) data; -@@ -971,52 +951,18 @@ static void ieee80211_work_work(struct work_struct *work) - } - - if (!started && !local->tmp_channel) { -- bool on_oper_chan; -- bool tmp_chan_changed = false; -- bool on_oper_chan2; -- enum nl80211_channel_type wk_ct; -- on_oper_chan = ieee80211_cfg_on_oper_channel(local); -- -- /* Work with existing channel type if possible. */ -- wk_ct = wk->chan_type; -- if (wk->chan == local->hw.conf.channel) -- wk_ct = ieee80211_calc_ct(wk->chan_type, -- local->hw.conf.channel_type); -- -- if (local->tmp_channel) -- if ((local->tmp_channel != wk->chan) || -- (local->tmp_channel_type != wk_ct)) -- tmp_chan_changed = true; -- -- local->tmp_channel = wk->chan; -- local->tmp_channel_type = wk_ct; - /* -- * Leave the station vifs in awake mode if they -- * happen to be on the same channel as -- * the requested channel. -+ * TODO: could optimize this by leaving the -+ * station vifs in awake mode if they -+ * happen to be on the same channel as -+ * the requested channel - */ -- on_oper_chan2 = ieee80211_cfg_on_oper_channel(local); -- if (on_oper_chan != on_oper_chan2) { -- if (on_oper_chan2) { -- /* going off oper channel, PS too */ -- ieee80211_offchannel_stop_vifs(local, -- true); -- ieee80211_hw_config(local, 0); -- } else { -- /* going on channel, but leave PS -- * off-channel. */ -- ieee80211_hw_config(local, 0); -- ieee80211_offchannel_return(local, -- true, -- false); -- } -- } else if (tmp_chan_changed) -- /* Still off-channel, but on some other -- * channel, so update hardware. -- * PS should already be off-channel. -- */ -- ieee80211_hw_config(local, 0); -+ ieee80211_offchannel_stop_beaconing(local); -+ ieee80211_offchannel_stop_station(local); - -+ local->tmp_channel = wk->chan; -+ local->tmp_channel_type = wk->chan_type; -+ ieee80211_hw_config(local, 0); - started = true; - wk->timeout = jiffies; - } -@@ -1102,8 +1048,7 @@ static void ieee80211_work_work(struct work_struct *work) - * we still need to do a hardware config. Currently, - * we cannot be here while scanning, however. - */ -- if (!ieee80211_cfg_on_oper_channel(local)) -- ieee80211_hw_config(local, 0); -+ ieee80211_hw_config(local, 0); - - /* At the least, we need to disable offchannel_ps, - * so just go ahead and run the entire offchannel -@@ -1111,7 +1056,7 @@ static void ieee80211_work_work(struct work_struct *work) - * beaconing if we were already on-oper-channel - * as a future optimization. - */ -- ieee80211_offchannel_return(local, true, true); -+ ieee80211_offchannel_return(local, true); - - /* give connection some time to breathe */ - run_again(local, jiffies + HZ/2); diff --git a/proc-clean-up-and-fix-proc-pid-mem-handling.patch b/proc-clean-up-and-fix-proc-pid-mem-handling.patch deleted file mode 100644 index c793475d2..000000000 --- a/proc-clean-up-and-fix-proc-pid-mem-handling.patch +++ /dev/null @@ -1,268 +0,0 @@ -From e268337dfe26dfc7efd422a804dbb27977a3cccc Mon Sep 17 00:00:00 2001 -From: Linus Torvalds -Date: Tue, 17 Jan 2012 15:21:19 -0800 -Subject: [PATCH] proc: clean up and fix /proc//mem handling -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Jüri Aedla reported that the /proc//mem handling really isn't very -robust, and it also doesn't match the permission checking of any of the -other related files. - -This changes it to do the permission checks at open time, and instead of -tracking the process, it tracks the VM at the time of the open. That -simplifies the code a lot, but does mean that if you hold the file -descriptor open over an execve(), you'll continue to read from the _old_ -VM. - -That is different from our previous behavior, but much simpler. If -somebody actually finds a load where this matters, we'll need to revert -this commit. - -I suspect that nobody will ever notice - because the process mapping -addresses will also have changed as part of the execve. So you cannot -actually usefully access the fd across a VM change simply because all -the offsets for IO would have changed too. - -Reported-by: Jüri Aedla -Cc: Al Viro -Signed-off-by: Linus Torvalds ---- - fs/proc/base.c | 145 +++++++++++++++----------------------------------------- - 1 files changed, 39 insertions(+), 106 deletions(-) - -diff --git a/fs/proc/base.c b/fs/proc/base.c -index 5485a53..662ddf2 100644 ---- a/fs/proc/base.c -+++ b/fs/proc/base.c -@@ -198,65 +198,7 @@ static int proc_root_link(struct dentry *dentry, struct path *path) - return result; - } - --static struct mm_struct *__check_mem_permission(struct task_struct *task) --{ -- struct mm_struct *mm; -- -- mm = get_task_mm(task); -- if (!mm) -- return ERR_PTR(-EINVAL); -- -- /* -- * A task can always look at itself, in case it chooses -- * to use system calls instead of load instructions. -- */ -- if (task == current) -- return mm; -- -- /* -- * If current is actively ptrace'ing, and would also be -- * permitted to freshly attach with ptrace now, permit it. -- */ -- if (task_is_stopped_or_traced(task)) { -- int match; -- rcu_read_lock(); -- match = (ptrace_parent(task) == current); -- rcu_read_unlock(); -- if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH)) -- return mm; -- } -- -- /* -- * No one else is allowed. -- */ -- mmput(mm); -- return ERR_PTR(-EPERM); --} -- --/* -- * If current may access user memory in @task return a reference to the -- * corresponding mm, otherwise ERR_PTR. -- */ --static struct mm_struct *check_mem_permission(struct task_struct *task) --{ -- struct mm_struct *mm; -- int err; -- -- /* -- * Avoid racing if task exec's as we might get a new mm but validate -- * against old credentials. -- */ -- err = mutex_lock_killable(&task->signal->cred_guard_mutex); -- if (err) -- return ERR_PTR(err); -- -- mm = __check_mem_permission(task); -- mutex_unlock(&task->signal->cred_guard_mutex); -- -- return mm; --} -- --struct mm_struct *mm_for_maps(struct task_struct *task) -+static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) - { - struct mm_struct *mm; - int err; -@@ -267,7 +209,7 @@ struct mm_struct *mm_for_maps(struct task_struct *task) - - mm = get_task_mm(task); - if (mm && mm != current->mm && -- !ptrace_may_access(task, PTRACE_MODE_READ)) { -+ !ptrace_may_access(task, mode)) { - mmput(mm); - mm = ERR_PTR(-EACCES); - } -@@ -276,6 +218,11 @@ struct mm_struct *mm_for_maps(struct task_struct *task) - return mm; - } - -+struct mm_struct *mm_for_maps(struct task_struct *task) -+{ -+ return mm_access(task, PTRACE_MODE_READ); -+} -+ - static int proc_pid_cmdline(struct task_struct *task, char * buffer) - { - int res = 0; -@@ -752,38 +699,39 @@ static const struct file_operations proc_single_file_operations = { - - static int mem_open(struct inode* inode, struct file* file) - { -- file->private_data = (void*)((long)current->self_exec_id); -+ struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); -+ struct mm_struct *mm; -+ -+ if (!task) -+ return -ESRCH; -+ -+ mm = mm_access(task, PTRACE_MODE_ATTACH); -+ put_task_struct(task); -+ -+ if (IS_ERR(mm)) -+ return PTR_ERR(mm); -+ - /* OK to pass negative loff_t, we can catch out-of-range */ - file->f_mode |= FMODE_UNSIGNED_OFFSET; -+ file->private_data = mm; -+ - return 0; - } - - static ssize_t mem_read(struct file * file, char __user * buf, - size_t count, loff_t *ppos) - { -- struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); -+ int ret; - char *page; - unsigned long src = *ppos; -- int ret = -ESRCH; -- struct mm_struct *mm; -+ struct mm_struct *mm = file->private_data; - -- if (!task) -- goto out_no_task; -+ if (!mm) -+ return 0; - -- ret = -ENOMEM; - page = (char *)__get_free_page(GFP_TEMPORARY); - if (!page) -- goto out; -- -- mm = check_mem_permission(task); -- ret = PTR_ERR(mm); -- if (IS_ERR(mm)) -- goto out_free; -- -- ret = -EIO; -- -- if (file->private_data != (void*)((long)current->self_exec_id)) -- goto out_put; -+ return -ENOMEM; - - ret = 0; - -@@ -810,13 +758,7 @@ static ssize_t mem_read(struct file * file, char __user * buf, - } - *ppos = src; - --out_put: -- mmput(mm); --out_free: - free_page((unsigned long) page); --out: -- put_task_struct(task); --out_no_task: - return ret; - } - -@@ -825,27 +767,15 @@ static ssize_t mem_write(struct file * file, const char __user *buf, - { - int copied; - char *page; -- struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); - unsigned long dst = *ppos; -- struct mm_struct *mm; -+ struct mm_struct *mm = file->private_data; - -- copied = -ESRCH; -- if (!task) -- goto out_no_task; -+ if (!mm) -+ return 0; - -- copied = -ENOMEM; - page = (char *)__get_free_page(GFP_TEMPORARY); - if (!page) -- goto out_task; -- -- mm = check_mem_permission(task); -- copied = PTR_ERR(mm); -- if (IS_ERR(mm)) -- goto out_free; -- -- copied = -EIO; -- if (file->private_data != (void *)((long)current->self_exec_id)) -- goto out_mm; -+ return -ENOMEM; - - copied = 0; - while (count > 0) { -@@ -869,13 +799,7 @@ static ssize_t mem_write(struct file * file, const char __user *buf, - } - *ppos = dst; - --out_mm: -- mmput(mm); --out_free: - free_page((unsigned long) page); --out_task: -- put_task_struct(task); --out_no_task: - return copied; - } - -@@ -895,11 +819,20 @@ loff_t mem_lseek(struct file *file, loff_t offset, int orig) - return file->f_pos; - } - -+static int mem_release(struct inode *inode, struct file *file) -+{ -+ struct mm_struct *mm = file->private_data; -+ -+ mmput(mm); -+ return 0; -+} -+ - static const struct file_operations proc_mem_operations = { - .llseek = mem_lseek, - .read = mem_read, - .write = mem_write, - .open = mem_open, -+ .release = mem_release, - }; - - static ssize_t environ_read(struct file *file, char __user *buf, --- -1.7.7.5 - diff --git a/sources b/sources index dfe5aaeb3..66fa5b1a2 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz -62ac6ac9b870162f693ecf5e8606423a patch-3.2.1.xz 8cfe037a7a7a356278ec3638e25ad506 compat-wireless-3.3-rc1-2.tar.bz2 +5e53edbf75fcaa3a8d1697f3a053102d patch-3.2.2.xz From 8d85deadf798b961b4684875791ce919faad48bf Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 25 Jan 2012 20:15:56 -0500 Subject: [PATCH 245/487] Test fix for realtek_async_autopm oops from Stanislaw Gruszka (rhbz 784345) --- kernel.spec | 7 +++++++ realtek_async_autopm.patch | 13 +++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 realtek_async_autopm.patch diff --git a/kernel.spec b/kernel.spec index 5b7b8c978..e383af97f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -808,6 +808,9 @@ Patch21227: mac80211-fix-work-removal-on-deauth-request.patch #rhbz 718790 Patch21230: rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch +#rhbz 784345 +Patch21231: realtek_async_autopm.patch + Patch22000: rcu-reintroduce-missing-calls.patch # compat-wireless patches @@ -1508,6 +1511,9 @@ ApplyPatch rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch #rhbz 783211 ApplyPatch fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch +#rhbz 784345 +ApplyPatch realtek_async_autopm.patch + # END OF PATCH APPLICATIONS %endif @@ -2283,6 +2289,7 @@ fi - Linux 3.2.2 - Add patch to invalidate parent cache when fsync is called on a partition (rhbz 783211) +- Test fix for realtek_async_autopm oops from Stanislaw Gruszka (rhbz 784345) * Wed Jan 25 2012 John W. Linville - modpost: add option to allow external modules to avoid taint diff --git a/realtek_async_autopm.patch b/realtek_async_autopm.patch new file mode 100644 index 000000000..3c6b45cca --- /dev/null +++ b/realtek_async_autopm.patch @@ -0,0 +1,13 @@ +diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c +index 1f62723..d32f720 100644 +--- a/drivers/usb/storage/realtek_cr.c ++++ b/drivers/usb/storage/realtek_cr.c +@@ -789,7 +789,7 @@ static void rts51x_suspend_timer_fn(unsigned long data) + rts51x_set_stat(chip, RTS51X_STAT_SS); + /* ignore mass storage interface's children */ + pm_suspend_ignore_children(&us->pusb_intf->dev, true); +- usb_autopm_put_interface(us->pusb_intf); ++ usb_autopm_put_interface_async(us->pusb_intf); + US_DEBUGP("%s: RTS51X_STAT_SS 01," + "intf->pm_usage_cnt:%d, power.usage:%d\n", + __func__, From ecbaf0800786253b82968b76f6928981fd567734 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 27 Jan 2012 14:00:38 -0500 Subject: [PATCH 246/487] Include config.mk from compat-wireless build in files for installation --- kernel.spec | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel.spec b/kernel.spec index e383af97f..0db6ce671 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1820,6 +1820,9 @@ BuildKernel() { cd ../compat-wireless-%{cwversion}/ + install -m 644 config.mk \ + $RPM_BUILD_ROOT/boot/config.mk-compat-wireless-%{cwversion}-$KernelVer + make -s ARCH=$Arch V=1 %{?_smp_mflags} \ KLIB_BUILD=../linux-%{kversion}.%{_target_cpu} \ KMODPATH_ARG="INSTALL_MOD_PATH=$RPM_BUILD_ROOT" \ @@ -2238,6 +2241,7 @@ fi /lib/modules/%{KVERREL}%{?2:.%{2}}/extra\ /lib/modules/%{KVERREL}%{?2:.%{2}}/updates\ %if %{with_backports}\ +/boot/config.mk-compat-wireless-%{cwversion}-%{KVERREL}%{?2:.%{2}}\ /lib/modules/%{KVERREL}%{?2:.%{2}}/backports\ %endif\ %ifarch %{vdso_arches}\ @@ -2285,6 +2289,9 @@ fi # and build. %changelog +* Fri Jan 27 2012 John W. Linville +- Include config.mk from compat-wireless build in files for installation + * Wed Jan 25 2012 Josh Boyer - 3.2.2-1 - Linux 3.2.2 - Add patch to invalidate parent cache when fsync is called on a partition From 2cad290c4564dd3a0cc8eaeb65c99bc7e49f4500 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 30 Jan 2012 10:27:28 -0500 Subject: [PATCH 247/487] Use the eeprom_93cx6 driver from the compat-wireless package --- compat-wireless-config-fixups.patch | 6 ------ config-backports | 5 +++++ kernel.spec | 3 +++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/compat-wireless-config-fixups.patch b/compat-wireless-config-fixups.patch index 722c6c820..7bb19bcdc 100644 --- a/compat-wireless-config-fixups.patch +++ b/compat-wireless-config-fixups.patch @@ -11,12 +11,6 @@ diff -up compat-wireless-3.3-rc1-2/config.mk.orig compat-wireless-3.3-rc1-2/conf ifneq ($(wildcard $(KLIB_BUILD)/Makefile),) COMPAT_LATEST_VERSION = 3 -diff -up compat-wireless-3.3-rc1-2/drivers/misc/eeprom/Makefile.orig compat-wireless-3.3-rc1-2/drivers/misc/eeprom/Makefile ---- compat-wireless-3.3-rc1-2/drivers/misc/eeprom/Makefile.orig 2012-01-21 02:08:39.000000000 -0500 -+++ compat-wireless-3.3-rc1-2/drivers/misc/eeprom/Makefile 2012-01-24 15:16:38.204409844 -0500 -@@ -1 +1 @@ --obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o -+#obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o diff -up compat-wireless-3.3-rc1-2/drivers/net/ethernet/atheros/Makefile.orig compat-wireless-3.3-rc1-2/drivers/net/ethernet/atheros/Makefile --- compat-wireless-3.3-rc1-2/drivers/net/ethernet/atheros/Makefile.orig 2012-01-21 02:08:39.000000000 -0500 +++ compat-wireless-3.3-rc1-2/drivers/net/ethernet/atheros/Makefile 2012-01-24 15:16:38.204409844 -0500 diff --git a/config-backports b/config-backports index 33a3adcce..c9ccf2033 100644 --- a/config-backports +++ b/config-backports @@ -16,6 +16,11 @@ # # CONFIG_B43_BCMA is not set +# +# Several wireless drivers have this chip, use the backported driver version +# +# CONFIG_EEPROM_93CX6 is not set + # # These have to be turned-on again since compat-wireless does not # provide them... diff --git a/kernel.spec b/kernel.spec index 0db6ce671..88d41007d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2289,6 +2289,9 @@ fi # and build. %changelog +* Mon Jan 30 2012 John W. Linville +- Use the eeprom_93cx6 driver from the compat-wireless package + * Fri Jan 27 2012 John W. Linville - Include config.mk from compat-wireless build in files for installation From a43c59fbeeac2aea17ad7f750db331c325605322 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 30 Jan 2012 10:41:26 -0500 Subject: [PATCH 248/487] mac80211: fix debugfs key->station symlink brcmsmac: fix tx queue flush infinite loop mac80211: Use the right headroom size for mesh mgmt frames mac80211: fix work removal on deauth request b43: add option to avoid duplicating device support with brcmsmac mac80211: update oper_channel on ibss join mac80211: set bss_conf.idle when vif is connected iwlwifi: fix PCI-E transport "inta" race --- ...o-avoid-duplicating-device-support-w.patch | 2 +- ...mac-fix-tx-queue-flush-infinite-loop.patch | 51 ++++++++++++ iwlwifi-fix-PCI-E-transport-inta-race.patch | 51 ++++++++++++ kernel.spec | 30 +++++-- ...-right-headroom-size-for-mesh-mgmt-f.patch | 83 +++++++++++++++++++ ...0211-fix-debugfs-key-station-symlink.patch | 43 ++++++++++ ...1-fix-work-removal-on-deauth-request.patch | 79 ++++-------------- ...-bss_conf.idle-when-vif-is-connected.patch | 37 +++++++++ ...211-update-oper_channel-on-ibss-join.patch | 31 +++++++ 9 files changed, 339 insertions(+), 68 deletions(-) create mode 100644 brcmsmac-fix-tx-queue-flush-infinite-loop.patch create mode 100644 iwlwifi-fix-PCI-E-transport-inta-race.patch create mode 100644 mac80211-Use-the-right-headroom-size-for-mesh-mgmt-f.patch create mode 100644 mac80211-fix-debugfs-key-station-symlink.patch create mode 100644 mac80211-set-bss_conf.idle-when-vif-is-connected.patch create mode 100644 mac80211-update-oper_channel-on-ibss-join.patch diff --git a/b43-add-option-to-avoid-duplicating-device-support-w.patch b/b43-add-option-to-avoid-duplicating-device-support-w.patch index 63d28cdea..ca820dfe0 100644 --- a/b43-add-option-to-avoid-duplicating-device-support-w.patch +++ b/b43-add-option-to-avoid-duplicating-device-support-w.patch @@ -1,7 +1,7 @@ From 4f3d09de38d234ce7ffba5ec5a7e6704f983d375 Mon Sep 17 00:00:00 2001 From: John W. Linville Date: Wed, 11 Jan 2012 15:50:15 -0500 -Subject: [PATCH] b43: add option to avoid duplicating device support with +Subject: [PATCH 5/8] b43: add option to avoid duplicating device support with brcmsmac Signed-off-by: John W. Linville diff --git a/brcmsmac-fix-tx-queue-flush-infinite-loop.patch b/brcmsmac-fix-tx-queue-flush-infinite-loop.patch new file mode 100644 index 000000000..c5d69d467 --- /dev/null +++ b/brcmsmac-fix-tx-queue-flush-infinite-loop.patch @@ -0,0 +1,51 @@ +From f96b08a7e6f69c0f0a576554df3df5b1b519c479 Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Tue, 17 Jan 2012 12:38:50 +0100 +Subject: [PATCH 2/8] brcmsmac: fix tx queue flush infinite loop + +This patch workaround live deadlock problem caused by infinite loop +in brcms_c_wait_for_tx_completion(). I do not consider the patch as +the proper fix, which should fix the real reason of tx queue flush +failure, but patch helps with system lockup. + +Reference: +https://bugzilla.kernel.org/show_bug.cgi?id=42576 + +Reported-and-tested-by: Patrick +Cc: stable@vger.kernel.org # 3.2+ +Signed-off-by: Stanislaw Gruszka +Signed-off-by: John W. Linville +--- + drivers/net/wireless/brcm80211/brcmsmac/main.c | 10 +++++++++- + 1 files changed, 9 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c +index f7ed340..f6affc6 100644 +--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c +@@ -7981,13 +7981,21 @@ int brcms_c_get_curband(struct brcms_c_info *wlc) + + void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop) + { ++ int timeout = 20; ++ + /* flush packet queue when requested */ + if (drop) + brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL); + + /* wait for queue and DMA fifos to run dry */ +- while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0) ++ while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0) { + brcms_msleep(wlc->wl, 1); ++ ++ if (--timeout == 0) ++ break; ++ } ++ ++ WARN_ON_ONCE(timeout == 0); + } + + void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval) +-- +1.7.4.4 + diff --git a/iwlwifi-fix-PCI-E-transport-inta-race.patch b/iwlwifi-fix-PCI-E-transport-inta-race.patch new file mode 100644 index 000000000..b17e5ec7b --- /dev/null +++ b/iwlwifi-fix-PCI-E-transport-inta-race.patch @@ -0,0 +1,51 @@ +From b49ba04a3a0382e7314d990707c21094c410425a Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Thu, 19 Jan 2012 08:20:57 -0800 +Subject: [PATCH 8/8] iwlwifi: fix PCI-E transport "inta" race + +When an interrupt comes in, we read the reason +bits and collect them into "trans_pcie->inta". +This happens with the spinlock held. However, +there's a bug resetting this variable -- that +happens after the spinlock has been released. +This means that it is possible for interrupts +to be missed if the reset happens after some +other interrupt reasons were already added to +the variable. + +I found this by code inspection, looking for a +reason that we sometimes see random commands +time out. It seems possible that this causes +such behaviour, but I can't say for sure right +now since it happens extremely infrequently on +my test systems. + +Cc: stable@vger.kernel.org [3.2] +Signed-off-by: Johannes Berg +Signed-off-by: Wey-Yi Guy +Signed-off-by: John W. Linville +--- + drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +index 752493f..65d1f05 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c ++++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +@@ -972,11 +972,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans) + } + #endif + +- spin_unlock_irqrestore(&trans->shrd->lock, flags); +- + /* saved interrupt in inta variable now we can reset trans_pcie->inta */ + trans_pcie->inta = 0; + ++ spin_unlock_irqrestore(&trans->shrd->lock, flags); ++ + /* Now service all interrupt bits discovered above. */ + if (inta & CSR_INT_BIT_HW_ERR) { + IWL_ERR(trans, "Hardware error detected. Restarting.\n"); +-- +1.7.4.4 + diff --git a/kernel.spec b/kernel.spec index 88d41007d..bd6703c56 100644 --- a/kernel.spec +++ b/kernel.spec @@ -820,9 +820,15 @@ Patch50002: compat-wireless-integrated-build.patch Patch50100: compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch -# Remove overlapping hardware support between b43 and brcmsmac -Patch50101: b43-add-option-to-avoid-duplicating-device-support-w.patch - +# Pending upstream fixes +Patch50101: mac80211-fix-debugfs-key-station-symlink.patch +Patch50102: brcmsmac-fix-tx-queue-flush-infinite-loop.patch +Patch50103: mac80211-Use-the-right-headroom-size-for-mesh-mgmt-f.patch +Patch50104: mac80211-fix-work-removal-on-deauth-request.patch +Patch50105: b43-add-option-to-avoid-duplicating-device-support-w.patch +Patch50106: mac80211-update-oper_channel-on-ibss-join.patch +Patch50107: mac80211-set-bss_conf.idle-when-vif-is-connected.patch +Patch50108: iwlwifi-fix-PCI-E-transport-inta-race.patch %endif @@ -1579,10 +1585,16 @@ cd compat-wireless-%{cwversion} ApplyPatch compat-wireless-config-fixups.patch ApplyPatch compat-wireless-pr_fmt-warning-avoidance.patch ApplyPatch compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch -ApplyPatch mac80211-fix-work-removal-on-deauth-request.patch -# Remove overlapping hardware support between b43 and brcmsmac +# Pending upstream fixes +ApplyPatch mac80211-fix-debugfs-key-station-symlink.patch +ApplyPatch brcmsmac-fix-tx-queue-flush-infinite-loop.patch +ApplyPatch mac80211-Use-the-right-headroom-size-for-mesh-mgmt-f.patch +ApplyPatch mac80211-fix-work-removal-on-deauth-request.patch ApplyPatch b43-add-option-to-avoid-duplicating-device-support-w.patch +ApplyPatch mac80211-update-oper_channel-on-ibss-join.patch +ApplyPatch mac80211-set-bss_conf.idle-when-vif-is-connected.patch +ApplyPatch iwlwifi-fix-PCI-E-transport-inta-race.patch cd .. @@ -2291,6 +2303,14 @@ fi %changelog * Mon Jan 30 2012 John W. Linville - Use the eeprom_93cx6 driver from the compat-wireless package +- mac80211: fix debugfs key->station symlink +- brcmsmac: fix tx queue flush infinite loop +- mac80211: Use the right headroom size for mesh mgmt frames +- mac80211: fix work removal on deauth request +- b43: add option to avoid duplicating device support with brcmsmac +- mac80211: update oper_channel on ibss join +- mac80211: set bss_conf.idle when vif is connected +- iwlwifi: fix PCI-E transport "inta" race * Fri Jan 27 2012 John W. Linville - Include config.mk from compat-wireless build in files for installation diff --git a/mac80211-Use-the-right-headroom-size-for-mesh-mgmt-f.patch b/mac80211-Use-the-right-headroom-size-for-mesh-mgmt-f.patch new file mode 100644 index 000000000..9096effdd --- /dev/null +++ b/mac80211-Use-the-right-headroom-size-for-mesh-mgmt-f.patch @@ -0,0 +1,83 @@ +From 65e8b0ccb6cf176f8eddb1b05534be46580da9dd Mon Sep 17 00:00:00 2001 +From: Javier Cardona +Date: Tue, 17 Jan 2012 18:17:46 -0800 +Subject: [PATCH 3/8] mac80211: Use the right headroom size for mesh mgmt + frames + +Use local->tx_headroom instad of local->hw.extra_tx_headroom. +local->tx_headroom is the max of hw.extra_tx_headroom required by the +driver and the headroom required by mac80211 for status reporting. On +drivers where hw.extra_tx_headroom is smaller than what mac80211 +requires (e.g. ath5k), we would not reserve sufficient buffer space to +report tx status. + +Also, don't reserve local->tx_headroom + local->hw.extra_tx_headroom. + +Reported-by: Simon Morgenthaler +Reported-by: Kai Scharwies +Signed-off-by: Javier Cardona +Signed-off-by: John W. Linville +--- + net/mac80211/mesh_hwmp.c | 8 ++++---- + net/mac80211/mesh_plink.c | 4 ++-- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c +index 73abb75..54df1b2 100644 +--- a/net/mac80211/mesh_hwmp.c ++++ b/net/mac80211/mesh_hwmp.c +@@ -119,12 +119,12 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, + int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) + + sizeof(mgmt->u.action.u.mesh_action); + +- skb = dev_alloc_skb(local->hw.extra_tx_headroom + ++ skb = dev_alloc_skb(local->tx_headroom + + hdr_len + + 2 + 37); /* max HWMP IE */ + if (!skb) + return -1; +- skb_reserve(skb, local->hw.extra_tx_headroom); ++ skb_reserve(skb, local->tx_headroom); + mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); + memset(mgmt, 0, hdr_len); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | +@@ -250,12 +250,12 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, + if (time_before(jiffies, ifmsh->next_perr)) + return -EAGAIN; + +- skb = dev_alloc_skb(local->hw.extra_tx_headroom + ++ skb = dev_alloc_skb(local->tx_headroom + + hdr_len + + 2 + 15 /* PERR IE */); + if (!skb) + return -1; +- skb_reserve(skb, local->tx_headroom + local->hw.extra_tx_headroom); ++ skb_reserve(skb, local->tx_headroom); + mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); + memset(mgmt, 0, hdr_len); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | +diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c +index 41ef1b4..a172517 100644 +--- a/net/mac80211/mesh_plink.c ++++ b/net/mac80211/mesh_plink.c +@@ -172,7 +172,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, + int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) + + sizeof(mgmt->u.action.u.self_prot); + +- skb = dev_alloc_skb(local->hw.extra_tx_headroom + ++ skb = dev_alloc_skb(local->tx_headroom + + hdr_len + + 2 + /* capability info */ + 2 + /* AID */ +@@ -186,7 +186,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, + sdata->u.mesh.ie_len); + if (!skb) + return -1; +- skb_reserve(skb, local->hw.extra_tx_headroom); ++ skb_reserve(skb, local->tx_headroom); + mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); + memset(mgmt, 0, hdr_len); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | +-- +1.7.4.4 + diff --git a/mac80211-fix-debugfs-key-station-symlink.patch b/mac80211-fix-debugfs-key-station-symlink.patch new file mode 100644 index 000000000..d98f2c99b --- /dev/null +++ b/mac80211-fix-debugfs-key-station-symlink.patch @@ -0,0 +1,43 @@ +From 9446f3efc53512e5ad9e0966539021a2a41fe5a0 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 17 Jan 2012 10:32:01 +0100 +Subject: [PATCH 1/8] mac80211: fix debugfs key->station symlink + +Since stations moved into a virtual interface +subdirectory, this link has been broken. Fix it. + +Signed-off-by: Johannes Berg +Signed-off-by: John W. Linville +--- + net/mac80211/debugfs_key.c | 7 ++++--- + 1 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c +index 38e6101..59edcd9 100644 +--- a/net/mac80211/debugfs_key.c ++++ b/net/mac80211/debugfs_key.c +@@ -225,9 +225,9 @@ KEY_OPS(key); + key, &key_##name##_ops); + + void ieee80211_debugfs_key_add(struct ieee80211_key *key) +- { ++{ + static int keycount; +- char buf[50]; ++ char buf[100]; + struct sta_info *sta; + + if (!key->local->debugfs.keys) +@@ -244,7 +244,8 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key) + + sta = key->sta; + if (sta) { +- sprintf(buf, "../../stations/%pM", sta->sta.addr); ++ sprintf(buf, "../../netdev:%s/stations/%pM", ++ sta->sdata->name, sta->sta.addr); + key->debugfs.stalink = + debugfs_create_symlink("station", key->debugfs.dir, buf); + } +-- +1.7.4.4 + diff --git a/mac80211-fix-work-removal-on-deauth-request.patch b/mac80211-fix-work-removal-on-deauth-request.patch index 60b91d3cf..941b51861 100644 --- a/mac80211-fix-work-removal-on-deauth-request.patch +++ b/mac80211-fix-work-removal-on-deauth-request.patch @@ -1,51 +1,7 @@ -Path: news.gmane.org!not-for-mail -From: Johannes Berg -Newsgroups: gmane.linux.kernel.wireless.general -Subject: [PATCH 3.3] mac80211: fix work removal on deauth request +From bc4934bc61d0a11fd62c5187ff83645628f8be8b Mon Sep 17 00:00:00 2001 +From: Johannes Berg Date: Wed, 18 Jan 2012 14:10:25 +0100 -Lines: 107 -Approved: news@gmane.org -Message-ID: <1326892225.4778.5.camel@jlt3.sipsolutions.net> -NNTP-Posting-Host: lo.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset="UTF-8" -Content-Transfer-Encoding: 7bit -X-Trace: dough.gmane.org 1326892249 18013 80.91.229.12 (18 Jan 2012 13:10:49 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Wed, 18 Jan 2012 13:10:49 +0000 (UTC) -Cc: linux-wireless , - Pontus Fuchs -To: John Linville -Original-X-From: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Wed Jan 18 14:10:44 2012 -Return-path: -Envelope-to: glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1RnVHo-00044l-Aq - for glkwg-linux-wireless-1dZseelyfdZg9hUCZPvPmw@public.gmane.org; Wed, 18 Jan 2012 14:10:44 +0100 -Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand - id S1757410Ab2ARNK3 (ORCPT - ); - Wed, 18 Jan 2012 08:10:29 -0500 -Original-Received: from he.sipsolutions.net ([78.46.109.217]:45023 "EHLO - sipsolutions.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1754365Ab2ARNK2 (ORCPT - ); - Wed, 18 Jan 2012 08:10:28 -0500 -Original-Received: by sipsolutions.net with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) - (Exim 4.77) - (envelope-from ) - id 1RnVHW-0004hf-Lx; Wed, 18 Jan 2012 14:10:26 +0100 -X-Mailer: Evolution 2.30.3 -Original-Sender: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Xref: news.gmane.org gmane.linux.kernel.wireless.general:84095 -Archived-At: - -From: Johannes Berg +Subject: [PATCH 4/8] mac80211: fix work removal on deauth request When deauth is requested while an auth or assoc work item is in progress, we currently delete it @@ -69,17 +25,20 @@ in cfg80211. This fix isn't very clean, but that seems acceptable since I have patches pending to remove this code completely. -Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Reported-by: Pontus Fuchs -Tested-by: Pontus Fuchs -Signed-off-by: Johannes Berg +Cc: stable@vger.kernel.org +Reported-by: Pontus Fuchs +Tested-by: Pontus Fuchs +Signed-off-by: Johannes Berg +Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 38 +++++++++++++++++++++++++++----------- - 1 file changed, 27 insertions(+), 11 deletions(-) + 1 files changed, 27 insertions(+), 11 deletions(-) ---- a/net/mac80211/mlme.c 2012-01-18 14:04:33.000000000 +0100 -+++ b/net/mac80211/mlme.c 2012-01-18 14:04:34.000000000 +0100 -@@ -2750,7 +2750,6 @@ int ieee80211_mgd_deauth(struct ieee8021 +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index ecb4c84..295be92 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -2750,7 +2750,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; @@ -87,7 +46,7 @@ Signed-off-by: Johannes Berg +Date: Wed, 11 Jan 2012 13:11:50 +0200 +Subject: [PATCH 7/8] mac80211: set bss_conf.idle when vif is connected + +__ieee80211_recalc_idle() iterates through the vifs, +sets bss_conf.idle = true if they are disconnected, +and increases "count" if they are not (which later +gets evaluated in order to determine whether the +device is idle). + +However, the loop doesn't set bss_conf.idle = false +(along with increasing "count"), causing the device +idle state and the vif idle state to get out of sync +in some cases. + +Signed-off-by: Eliad Peller +Signed-off-by: John W. Linville +--- + net/mac80211/iface.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index e47768c..01a21c2 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -1314,6 +1314,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) + continue; + } + /* count everything else */ ++ sdata->vif.bss_conf.idle = false; + count++; + } + +-- +1.7.4.4 + diff --git a/mac80211-update-oper_channel-on-ibss-join.patch b/mac80211-update-oper_channel-on-ibss-join.patch new file mode 100644 index 000000000..1a0d93249 --- /dev/null +++ b/mac80211-update-oper_channel-on-ibss-join.patch @@ -0,0 +1,31 @@ +From ba1960257c5980f9b58057995ce3394bd8e48ca3 Mon Sep 17 00:00:00 2001 +From: Eliad Peller +Date: Tue, 10 Jan 2012 15:19:54 +0200 +Subject: [PATCH 6/8] mac80211: update oper_channel on ibss join + +Commit 13c40c5 ("mac80211: Add HT operation modes for IBSS") broke +ibss operation by mistakenly removing the local->oper_channel +update (causing ibss to start on the wrong channel). fix it. + +Signed-off-by: Eliad Peller +Acked-by: Simon Wunderlich +Signed-off-by: John W. Linville +--- + net/mac80211/ibss.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c +index b3d76b7..a464396 100644 +--- a/net/mac80211/ibss.c ++++ b/net/mac80211/ibss.c +@@ -106,6 +106,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, + + sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; + ++ local->oper_channel = chan; + channel_type = ifibss->channel_type; + if (channel_type > NL80211_CHAN_HT20 && + !cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) +-- +1.7.4.4 + From 8377903fd0d90e2915c41e60a51e3319ece07e8f Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 30 Jan 2012 11:08:12 -0500 Subject: [PATCH 249/487] ath9k: use WARN_ON_ONCE in ath_rc_get_highest_rix --- ...RN_ON_ONCE-in-ath_rc_get_highest_rix.patch | 29 +++++++++++++++++++ kernel.spec | 5 ++++ 2 files changed, 34 insertions(+) create mode 100644 ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch diff --git a/ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch b/ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch new file mode 100644 index 000000000..7d5c9a5c8 --- /dev/null +++ b/ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch @@ -0,0 +1,29 @@ +From 41b2d62702730b0c6bc5a40722e423bb0338311a Mon Sep 17 00:00:00 2001 +From: John W. Linville +Date: Mon, 30 Jan 2012 10:53:55 -0500 +Subject: [PATCH] ath9k: use WARN_ON_ONCE in ath_rc_get_highest_rix + +The device seems to survive the issue, so no need to flood the logs +about it... + +Signed-off-by: John W. Linville +--- + drivers/net/wireless/ath/ath9k/rc.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c +index b3c3798..635b592 100644 +--- a/drivers/net/wireless/ath/ath9k/rc.c ++++ b/drivers/net/wireless/ath/ath9k/rc.c +@@ -694,7 +694,7 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc, + return rate; + + /* This should not happen */ +- WARN_ON(1); ++ WARN_ON_ONCE(1); + + rate = ath_rc_priv->valid_rate_index[0]; + +-- +1.7.4.4 + diff --git a/kernel.spec b/kernel.spec index bd6703c56..7c2bd3bc2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -830,6 +830,8 @@ Patch50106: mac80211-update-oper_channel-on-ibss-join.patch Patch50107: mac80211-set-bss_conf.idle-when-vif-is-connected.patch Patch50108: iwlwifi-fix-PCI-E-transport-inta-race.patch +Patch50200: ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1596,6 +1598,8 @@ ApplyPatch mac80211-update-oper_channel-on-ibss-join.patch ApplyPatch mac80211-set-bss_conf.idle-when-vif-is-connected.patch ApplyPatch iwlwifi-fix-PCI-E-transport-inta-race.patch +ApplyPatch ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch + cd .. %endif @@ -2311,6 +2315,7 @@ fi - mac80211: update oper_channel on ibss join - mac80211: set bss_conf.idle when vif is connected - iwlwifi: fix PCI-E transport "inta" race +- ath9k: use WARN_ON_ONCE in ath_rc_get_highest_rix * Fri Jan 27 2012 John W. Linville - Include config.mk from compat-wireless build in files for installation From 2f9ac97623fc5ff5e2b3744261ccae2fee35f3a0 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 30 Jan 2012 12:59:49 -0500 Subject: [PATCH 250/487] Restore the Savage DRM and several others that were accidentally early-deprecated. --- config-generic | 24 +++++++++--------------- kernel.spec | 4 ++++ 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/config-generic b/config-generic index bd2c47654..025b58cde 100644 --- a/config-generic +++ b/config-generic @@ -2511,31 +2511,25 @@ CONFIG_AGP_SIS=y CONFIG_AGP_SWORKS=y CONFIG_AGP_VIA=y CONFIG_AGP_EFFICEON=y - CONFIG_VGA_ARB=y CONFIG_VGA_ARB_MAX_GPUS=16 - -# CONFIG_STUB_POULSBO is not set - +CONFIG_STUB_POULSBO=m +# CONFIG_DRM_PSB is not set CONFIG_DRM=m -# CONFIG_DRM_TDFX is not set -# CONFIG_DRM_R128 is not set +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m CONFIG_DRM_RADEON=m CONFIG_DRM_RADEON_KMS=y -# CONFIG_DRM_I810 is not set -# CONFIG_DRM_MGA is not set -# CONFIG_DRM_SIS is not set -# CONFIG_DRM_SAVAGE is not set +CONFIG_DRM_I810=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_SAVAGE=m CONFIG_DRM_I915=m CONFIG_DRM_I915_KMS=y -# CONFIG_DRM_VIA is not set +CONFIG_DRM_VIA=m CONFIG_DRM_NOUVEAU=m CONFIG_DRM_NOUVEAU_BACKLIGHT=y CONFIG_DRM_NOUVEAU_DEBUG=y -CONFIG_DRM_PSB=m -# CONFIG_DRM_PSB_MRST is not set -# CONFIG_DRM_PSB_MFLD is not set -# CONFIG_DRM_PSB_CDV is not set CONFIG_DRM_I2C_CH7006=m CONFIG_DRM_I2C_SIL164=m CONFIG_DRM_VMWGFX=m diff --git a/kernel.spec b/kernel.spec index 7c2bd3bc2..a391201a0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2305,6 +2305,10 @@ fi # and build. %changelog +* Mon Jan 30 2012 Dave Jones +- Restore the Savage DRM and several others that were accidentally + early-deprecated. + * Mon Jan 30 2012 John W. Linville - Use the eeprom_93cx6 driver from the compat-wireless package - mac80211: fix debugfs key->station symlink From 3296402d4814b96b5913c6f356f0d8f930822120 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 30 Jan 2012 13:06:39 -0500 Subject: [PATCH 251/487] Fix "warning: File listed twice: mac80211-fix-work-removal-on-deauth-request.patch" --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index a391201a0..2a73963a8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -824,7 +824,7 @@ Patch50100: compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch Patch50101: mac80211-fix-debugfs-key-station-symlink.patch Patch50102: brcmsmac-fix-tx-queue-flush-infinite-loop.patch Patch50103: mac80211-Use-the-right-headroom-size-for-mesh-mgmt-f.patch -Patch50104: mac80211-fix-work-removal-on-deauth-request.patch +# mac80211-fix-work-removal-on-deauth-request.patch is patch 21227 Patch50105: b43-add-option-to-avoid-duplicating-device-support-w.patch Patch50106: mac80211-update-oper_channel-on-ibss-join.patch Patch50107: mac80211-set-bss_conf.idle-when-vif-is-connected.patch From ec7325df627e1a288556627fa54c7f25e87f5144 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 30 Jan 2012 13:59:58 -0500 Subject: [PATCH 252/487] Enable kmemleak (off by default) in kernel-debug (rhbz 782419) --- config-debug | 5 +++++ kernel.spec | 3 +++ 2 files changed, 8 insertions(+) diff --git a/config-debug b/config-debug index 19ae4656f..e3c1e6e44 100644 --- a/config-debug +++ b/config-debug @@ -104,3 +104,8 @@ CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y + +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 +# CONFIG_DEBUG_KMEMLEAK_TEST is not set +CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y diff --git a/kernel.spec b/kernel.spec index 2a73963a8..d6c5293cd 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2305,6 +2305,9 @@ fi # and build. %changelog +* Mon Jan 30 2012 Dave Jones +- Enable kmemleak (off by default) in kernel-debug (rhbz 782419) + * Mon Jan 30 2012 Dave Jones - Restore the Savage DRM and several others that were accidentally early-deprecated. From 2fd5228fc78416a19e742fad0a4d9838e1a294c8 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 30 Jan 2012 14:16:25 -0500 Subject: [PATCH 253/487] remove unreferenced patches --- ...-compaction-if-compaction-can-procee.patch | 81 ------------ kernel.spec | 3 - ...onous-compaction-for-THP-allocations.patch | 115 ------------------ 3 files changed, 199 deletions(-) delete mode 100644 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch delete mode 100644 mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch diff --git a/0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch b/0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch deleted file mode 100644 index e74b64d91..000000000 --- a/0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch +++ /dev/null @@ -1,81 +0,0 @@ -From c01043c9aa51a63bd01c60e53494ca4a7e994542 Mon Sep 17 00:00:00 2001 -From: Mel Gorman -Date: Fri, 7 Oct 2011 16:17:23 +0100 -Subject: [PATCH 2/2] mm: Abort reclaim/compaction if compaction can proceed - -If compaction can proceed, shrink_zones() stops doing any work but -the callers still shrink_slab(), raises the priority and potentially -sleeps. This patch aborts direct reclaim/compaction entirely if -compaction can proceed. - -Signed-off-by: Mel Gorman ---- - mm/vmscan.c | 20 ++++++++++++++++---- - 1 files changed, 16 insertions(+), 4 deletions(-) - -diff --git a/mm/vmscan.c b/mm/vmscan.c -index 8c03534..b295a38 100644 ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -2000,14 +2000,19 @@ restart: - * - * If a zone is deemed to be full of pinned pages then just give it a light - * scan then give up on it. -+ * -+ * This function returns true if a zone is being reclaimed for a costly -+ * high-order allocation and compaction is either ready to begin or deferred. -+ * This indicates to the caller that it should retry the allocation or fail. - */ --static void shrink_zones(int priority, struct zonelist *zonelist, -+static bool shrink_zones(int priority, struct zonelist *zonelist, - struct scan_control *sc) - { - struct zoneref *z; - struct zone *zone; - unsigned long nr_soft_reclaimed; - unsigned long nr_soft_scanned; -+ bool should_abort_reclaim = false; - - for_each_zone_zonelist_nodemask(zone, z, zonelist, - gfp_zone(sc->gfp_mask), sc->nodemask) { -@@ -2025,12 +2030,15 @@ static void shrink_zones(int priority, struct zonelist *zonelist, - if (COMPACTION_BUILD) { - /* - * If we already have plenty of memory free -- * for compaction, don't free any more. -+ * for compaction in this zone , don't free any -+ * more. - */ - if (sc->order > PAGE_ALLOC_COSTLY_ORDER && - (compaction_suitable(zone, sc->order) || -- compaction_deferred(zone))) -+ compaction_deferred(zone))) { -+ should_abort_reclaim = true; - continue; -+ } - } - /* - * This steals pages from memory cgroups over softlimit -@@ -2049,6 +2057,8 @@ static void shrink_zones(int priority, struct zonelist *zonelist, - - shrink_zone(priority, zone, sc); - } -+ -+ return should_abort_reclaim; - } - - static bool zone_reclaimable(struct zone *zone) -@@ -2113,7 +2123,9 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, - sc->nr_scanned = 0; - if (!priority) - disable_swap_token(sc->mem_cgroup); -- shrink_zones(priority, zonelist, sc); -+ if (shrink_zones(priority, zonelist, sc)) -+ break; -+ - /* - * Don't shrink slabs when reclaiming memory from - * over limit cgroups --- -1.7.6.4 - diff --git a/kernel.spec b/kernel.spec index d6c5293cd..1e10d2701 100644 --- a/kernel.spec +++ b/kernel.spec @@ -757,9 +757,6 @@ Patch20000: utrace.patch Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch -Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch -Patch21022: mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch - #rhbz 717735 Patch21045: nfs-client-freezer.patch diff --git a/mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch b/mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch deleted file mode 100644 index 6202341ae..000000000 --- a/mm-do-not-stall-in-synchronous-compaction-for-THP-allocations.patch +++ /dev/null @@ -1,115 +0,0 @@ -https://lkml.org/lkml/2011/11/10/173 - -Date Thu, 10 Nov 2011 10:06:16 +0000 -From Mel Gorman <> -Subject [PATCH] mm: Do not stall in synchronous compaction for THP allocations - - -Occasionally during large file copies to slow storage, there are still -reports of user-visible stalls when THP is enabled. Reports on this -have been intermittent and not reliable to reproduce locally but; - -Andy Isaacson reported a problem copying to VFAT on SD Card - https://lkml.org/lkml/2011/11/7/2 - - In this case, it was stuck in munmap for betwen 20 and 60 - seconds in compaction. It is also possible that khugepaged - was holding mmap_sem on this process if CONFIG_NUMA was set. - -Johannes Weiner reported stalls on USB - https://lkml.org/lkml/2011/7/25/378 - - In this case, there is no stack trace but it looks like the - same problem. The USB stick may have been using NTFS as a - filesystem based on other work done related to writing back - to USB around the same time. - -Internally in SUSE, I received a bug report related to stalls in firefox - when using Java and Flash heavily while copying from NFS - to VFAT on USB. It has not been confirmed to be the same problem - but if it looks like a duck and quacks like a duck..... -In the past, commit [11bc82d6: mm: compaction: Use async migration for -__GFP_NO_KSWAPD and enforce no writeback] forced that sync compaction -would never be used for THP allocations. This was reverted in commit -[c6a140bf: mm/compaction: reverse the change that forbade sync -migraton with __GFP_NO_KSWAPD] on the grounds that it was uncertain -it was beneficial. - -While user-visible stalls do not happen for me when writing to USB, -I setup a test running postmark while short-lived processes created -anonymous mapping. The objective was to exercise the paths that -allocate transparent huge pages. I then logged when processes were -stalled for more than 1 second, recorded a stack strace and did some -analysis to aggregate unique "stall events" which revealed - -Time stalled in this event: 47369 ms -Event count: 20 -usemem sleep_on_page 3690 ms -usemem sleep_on_page 2148 ms -usemem sleep_on_page 1534 ms -usemem sleep_on_page 1518 ms -usemem sleep_on_page 1225 ms -usemem sleep_on_page 2205 ms -usemem sleep_on_page 2399 ms -usemem sleep_on_page 2398 ms -usemem sleep_on_page 3760 ms -usemem sleep_on_page 1861 ms -usemem sleep_on_page 2948 ms -usemem sleep_on_page 1515 ms -usemem sleep_on_page 1386 ms -usemem sleep_on_page 1882 ms -usemem sleep_on_page 1850 ms -usemem sleep_on_page 3715 ms -usemem sleep_on_page 3716 ms -usemem sleep_on_page 4846 ms -usemem sleep_on_page 1306 ms -usemem sleep_on_page 1467 ms -[] wait_on_page_bit+0x6c/0x80 -[] unmap_and_move+0x1bf/0x360 -[] migrate_pages+0xa2/0x1b0 -[] compact_zone+0x1f3/0x2f0 -[] compact_zone_order+0xa8/0xf0 -[] try_to_compact_pages+0xdf/0x110 -[] __alloc_pages_direct_compact+0xda/0x1a0 -[] __alloc_pages_slowpath+0x55d/0x7a0 -[] __alloc_pages_nodemask+0x1b1/0x1c0 -[] alloc_pages_vma+0x9b/0x160 -[] do_huge_pmd_anonymous_page+0x160/0x270 -[] do_page_fault+0x207/0x4c0 -[] page_fault+0x25/0x30 -The stall times are approximate at best but the estimates represent 25% -of the worst stalls and even if the estimates are off by a factor of -10, it's severe. - -This patch once again prevents sync migration for transparent -hugepage allocations as it is preferable to fail a THP allocation -than stall. It was suggested that __GFP_NORETRY be used instead of -__GFP_NO_KSWAPD. This would look less like a special case but would -still cause compaction to run at least once with sync compaction. - -If accepted, this is a -stable candidate. - -Reported-by: Andy Isaacson -Reported-by: Johannes Weiner -Signed-off-by: Mel Gorman ---- - -diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index 9dd443d..84bf962 100644 ---- a/mm/page_alloc.c -+++ b/mm/page_alloc.c -@@ -2168,7 +2168,13 @@ rebalance: - sync_migration); - if (page) - goto got_pg; -- sync_migration = true; -+ -+ /* -+ * Do not use sync migration for transparent hugepage allocations as -+ * it could stall writing back pages which is far worse than simply -+ * failing to promote a page. -+ */ -+ sync_migration = !(gfp_mask & __GFP_NO_KSWAPD); - - /* Try direct reclaim and then allocating */ - page = __alloc_pages_direct_reclaim(gfp_mask, order, From cfb68d5e1cb2448037a89fd58b9259b74c539b66 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 31 Jan 2012 14:42:19 -0500 Subject: [PATCH 254/487] Apply iwlwifi patch for TID issue (rhbz 785561) --- iwlwifi-bz785561.patch | 50 ++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 6 +++++ 2 files changed, 56 insertions(+) create mode 100644 iwlwifi-bz785561.patch diff --git a/iwlwifi-bz785561.patch b/iwlwifi-bz785561.patch new file mode 100644 index 000000000..1c9a9d5cb --- /dev/null +++ b/iwlwifi-bz785561.patch @@ -0,0 +1,50 @@ +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +index d9d758e..1b70048 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +@@ -95,6 +95,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, + tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; + else + tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; ++ tx_cmd->tid_tspec = IWL_MAX_TID_COUNT; + } + + iwlagn_tx_cmd_protection(priv, info, fc, &tx_flags); +@@ -808,6 +809,8 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, + u32 status = le16_to_cpu(tx_resp->status.status); + int i; + ++ WARN_ON(tid == IWL_MAX_TID_COUNT); ++ + if (agg->wait_for_ba) + IWL_DEBUG_TX_REPLY(priv, + "got tx response w/o block-ack\n"); +@@ -1035,10 +1038,12 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, + } + + __skb_queue_head_init(&skbs); +- priv->tid_data[sta_id][tid].next_reclaimed = next_reclaimed; + +- IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d", +- next_reclaimed); ++ if (tid != IWL_MAX_TID_COUNT) { ++ priv->tid_data[sta_id][tid].next_reclaimed = next_reclaimed; ++ IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d", ++ next_reclaimed); ++ } + + /*we can free until ssn % q.n_bd not inclusive */ + WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id, +diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +index aa87994..fa1b369 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c ++++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +@@ -1551,7 +1551,7 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, + + txq->time_stamp = jiffies; + +- if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE && ++ if (unlikely(tid != IWL_MAX_TID_COUNT && txq_id >= IWLAGN_FIRST_AMPDU_QUEUE && + txq_id != trans_pcie->agg_txq[sta_id][tid])) { + /* + * FIXME: this is a uCode bug which need to be addressed, diff --git a/kernel.spec b/kernel.spec index 1e10d2701..395bec481 100644 --- a/kernel.spec +++ b/kernel.spec @@ -828,6 +828,7 @@ Patch50107: mac80211-set-bss_conf.idle-when-vif-is-connected.patch Patch50108: iwlwifi-fix-PCI-E-transport-inta-race.patch Patch50200: ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch +Patch50201: iwlwifi-bz785561.patch %endif @@ -1597,6 +1598,8 @@ ApplyPatch iwlwifi-fix-PCI-E-transport-inta-race.patch ApplyPatch ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch +ApplyPatch iwlwifi-bz785561.patch + cd .. %endif @@ -2302,6 +2305,9 @@ fi # and build. %changelog +* Tue Jan 31 2012 John W. Linville +- Apply iwlwifi patch for TID issue (rhbz 785561) + * Mon Jan 30 2012 Dave Jones - Enable kmemleak (off by default) in kernel-debug (rhbz 782419) From d35a7646d0df1201d0ade58a45b165c999eb5b6a Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 1 Feb 2012 16:00:49 -0500 Subject: [PATCH 255/487] Use "iwlwifi: don't mess up QoS counters with non-QoS frames" (rhbz 785561) Actually apply patch to make integrated compat-wireless avoid taint... --- iwlwifi-bz785561.patch | 50 ----------- ...ss-up-QoS-counters-with-non-QoS-fram.patch | 89 +++++++++++++++++++ kernel.spec | 10 ++- 3 files changed, 97 insertions(+), 52 deletions(-) delete mode 100644 iwlwifi-bz785561.patch create mode 100644 iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch diff --git a/iwlwifi-bz785561.patch b/iwlwifi-bz785561.patch deleted file mode 100644 index 1c9a9d5cb..000000000 --- a/iwlwifi-bz785561.patch +++ /dev/null @@ -1,50 +0,0 @@ -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c -index d9d758e..1b70048 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c -@@ -95,6 +95,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, - tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; - else - tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; -+ tx_cmd->tid_tspec = IWL_MAX_TID_COUNT; - } - - iwlagn_tx_cmd_protection(priv, info, fc, &tx_flags); -@@ -808,6 +809,8 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, - u32 status = le16_to_cpu(tx_resp->status.status); - int i; - -+ WARN_ON(tid == IWL_MAX_TID_COUNT); -+ - if (agg->wait_for_ba) - IWL_DEBUG_TX_REPLY(priv, - "got tx response w/o block-ack\n"); -@@ -1035,10 +1038,12 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, - } - - __skb_queue_head_init(&skbs); -- priv->tid_data[sta_id][tid].next_reclaimed = next_reclaimed; - -- IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d", -- next_reclaimed); -+ if (tid != IWL_MAX_TID_COUNT) { -+ priv->tid_data[sta_id][tid].next_reclaimed = next_reclaimed; -+ IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d", -+ next_reclaimed); -+ } - - /*we can free until ssn % q.n_bd not inclusive */ - WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id, -diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c -index aa87994..fa1b369 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c -+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c -@@ -1551,7 +1551,7 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, - - txq->time_stamp = jiffies; - -- if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE && -+ if (unlikely(tid != IWL_MAX_TID_COUNT && txq_id >= IWLAGN_FIRST_AMPDU_QUEUE && - txq_id != trans_pcie->agg_txq[sta_id][tid])) { - /* - * FIXME: this is a uCode bug which need to be addressed, diff --git a/iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch b/iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch new file mode 100644 index 000000000..5be686b84 --- /dev/null +++ b/iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch @@ -0,0 +1,89 @@ +From 3d29dd9b5b160ba4542a9b8f869a220559e633a0 Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Wed, 1 Feb 2012 07:01:32 -0800 +Subject: [PATCH] iwlwifi: don't mess up QoS counters with non-QoS frames + +In my AMPDU rework, I rely on the sequence numbers of frames. But +I didn't check that the frame has a valid tid before updating the +tracking counters. As a result, the Tx queues were stalled. People +who hit this bug saw that we simply didn't let any data out. + +This bug was introduced in 3.3. + +This patch fixes that and checks that the frame is a QoS frame before +looking at its tid and changing the counters. + +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Wey-Yi Guy +Signed-off-by: John W. Linville +--- + drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 12 +++++++++--- + drivers/net/wireless/iwlwifi/iwl-commands.h | 1 + + drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 1 + + 3 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +index 339e8d9..63bbc60 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +@@ -91,6 +91,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, + tx_cmd->tid_tspec = qc[0] & 0xf; + tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; + } else { ++ tx_cmd->tid_tspec = IWL_TID_NON_QOS; + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) + tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; + else +@@ -808,6 +809,8 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, + u32 status = le16_to_cpu(tx_resp->status.status); + int i; + ++ WARN_ON(tid == IWL_TID_NON_QOS); ++ + if (agg->wait_for_ba) + IWL_DEBUG_TX_REPLY(priv, + "got tx response w/o block-ack\n"); +@@ -1035,10 +1038,13 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, + } + + __skb_queue_head_init(&skbs); +- priv->tid_data[sta_id][tid].next_reclaimed = next_reclaimed; + +- IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d", +- next_reclaimed); ++ if (tid != IWL_TID_NON_QOS) { ++ priv->tid_data[sta_id][tid].next_reclaimed = ++ next_reclaimed; ++ IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d", ++ next_reclaimed); ++ } + + /*we can free until ssn % q.n_bd not inclusive */ + WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id, +diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h +index 265de39..f822ac4 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-commands.h ++++ b/drivers/net/wireless/iwlwifi/iwl-commands.h +@@ -815,6 +815,7 @@ struct iwl_qosparam_cmd { + + #define IWL_INVALID_STATION 255 + #define IWL_MAX_TID_COUNT 8 ++#define IWL_TID_NON_QOS IWL_MAX_TID_COUNT + + #define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) + #define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8) +diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +index 67d6e32..324d06d 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c ++++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +@@ -1262,6 +1262,7 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, + txq->time_stamp = jiffies; + + if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE && ++ tid != IWL_TID_NON_QOS && + txq_id != trans_pcie->agg_txq[sta_id][tid])) { + /* + * FIXME: this is a uCode bug which need to be addressed, +-- +1.7.4.4 + diff --git a/kernel.spec b/kernel.spec index 395bec481..3ce671149 100644 --- a/kernel.spec +++ b/kernel.spec @@ -828,7 +828,7 @@ Patch50107: mac80211-set-bss_conf.idle-when-vif-is-connected.patch Patch50108: iwlwifi-fix-PCI-E-transport-inta-race.patch Patch50200: ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch -Patch50201: iwlwifi-bz785561.patch +Patch50201: iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch %endif @@ -1584,6 +1584,8 @@ cd compat-wireless-%{cwversion} ApplyPatch compat-wireless-config-fixups.patch ApplyPatch compat-wireless-pr_fmt-warning-avoidance.patch +ApplyPatch compat-wireless-integrated-build.patch + ApplyPatch compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch # Pending upstream fixes @@ -1598,7 +1600,7 @@ ApplyPatch iwlwifi-fix-PCI-E-transport-inta-race.patch ApplyPatch ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch -ApplyPatch iwlwifi-bz785561.patch +ApplyPatch iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch cd .. @@ -2305,6 +2307,10 @@ fi # and build. %changelog +* Wed Feb 1 2012 John W. Linville +- Use "iwlwifi: don't mess up QoS counters with non-QoS frames" (rhbz 785561) +- Actually apply patch to make integrated compat-wireless avoid taint... + * Tue Jan 31 2012 John W. Linville - Apply iwlwifi patch for TID issue (rhbz 785561) From 6f8f5cde6537690c13e9dbc569c1d77f66913908 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 1 Feb 2012 16:03:00 -0500 Subject: [PATCH 256/487] Correct some bugzilla references... --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 3ce671149..929086f9e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2308,11 +2308,11 @@ fi %changelog * Wed Feb 1 2012 John W. Linville -- Use "iwlwifi: don't mess up QoS counters with non-QoS frames" (rhbz 785561) +- Use "iwlwifi: don't mess up QoS counters with non-QoS frames" (rhbz 785239) - Actually apply patch to make integrated compat-wireless avoid taint... * Tue Jan 31 2012 John W. Linville -- Apply iwlwifi patch for TID issue (rhbz 785561) +- Apply iwlwifi patch for TID issue (rhbz 785239) * Mon Jan 30 2012 Dave Jones - Enable kmemleak (off by default) in kernel-debug (rhbz 782419) From ef90ec92786a466eebf220c90096e20595546bce Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 3 Feb 2012 09:38:21 -0500 Subject: [PATCH 257/487] Patch from Jakub Kicinski to fix rt2x00 MCU requests (rhbz 772772) --- kernel.spec | 10 ++ rt2x00_fix_MCU_request_failures.patch | 136 ++++++++++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 rt2x00_fix_MCU_request_failures.patch diff --git a/kernel.spec b/kernel.spec index 929086f9e..57fa8be39 100644 --- a/kernel.spec +++ b/kernel.spec @@ -808,6 +808,9 @@ Patch21230: rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch #rhbz 784345 Patch21231: realtek_async_autopm.patch +#rhbz 772772 +Patch21232: rt2x00_fix_MCU_request_failures.patch + Patch22000: rcu-reintroduce-missing-calls.patch # compat-wireless patches @@ -1520,6 +1523,9 @@ ApplyPatch fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch #rhbz 784345 ApplyPatch realtek_async_autopm.patch +#rhbz 772772 +ApplyPatch rt2x00_fix_MCU_request_failures.patch + # END OF PATCH APPLICATIONS %endif @@ -1601,6 +1607,7 @@ ApplyPatch iwlwifi-fix-PCI-E-transport-inta-race.patch ApplyPatch ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch ApplyPatch iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch +ApplyPatch rt2x00_fix_MCU_request_failures.patch cd .. @@ -2307,6 +2314,9 @@ fi # and build. %changelog +* Fri Feb 03 2012 Josh Boyer +- Patch from Jakub Kicinski to fix rt2x00 MCU requests (rhbz 772772) + * Wed Feb 1 2012 John W. Linville - Use "iwlwifi: don't mess up QoS counters with non-QoS frames" (rhbz 785239) - Actually apply patch to make integrated compat-wireless avoid taint... diff --git a/rt2x00_fix_MCU_request_failures.patch b/rt2x00_fix_MCU_request_failures.patch new file mode 100644 index 000000000..f7b8a6a4c --- /dev/null +++ b/rt2x00_fix_MCU_request_failures.patch @@ -0,0 +1,136 @@ +diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h +index 2571a2f..822f9e5 100644 +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -1627,6 +1627,7 @@ struct mac_iveiv_entry { + + /* + * H2M_MAILBOX_CSR: Host-to-MCU Mailbox. ++ * CMD_TOKEN: Command id, 0xff disable status reporting + */ + #define H2M_MAILBOX_CSR 0x7010 + #define H2M_MAILBOX_CSR_ARG0 FIELD32(0x000000ff) +@@ -1636,6 +1637,8 @@ struct mac_iveiv_entry { + + /* + * H2M_MAILBOX_CID: ++ * Free slots contain 0xff. MCU will store command's token to lowest free slot. ++ * If all slots are occupied status will be dropped. + */ + #define H2M_MAILBOX_CID 0x7014 + #define H2M_MAILBOX_CID_CMD0 FIELD32(0x000000ff) +@@ -1645,6 +1648,7 @@ struct mac_iveiv_entry { + + /* + * H2M_MAILBOX_STATUS: ++ * Command status will be saved to same slot as command id. + */ + #define H2M_MAILBOX_STATUS 0x701c + +@@ -2259,6 +2263,12 @@ struct mac_iveiv_entry { + + /* + * MCU mailbox commands. ++ * MCU_SLEEP - go to power-save mode. ++ * arg1: 1: save as much power as possible, 0: save less power ++ * status: 1: success, 2: already asleep, ++ * 3: maybe MAC is busy so can't finish this task ++ * MCU_RADIO_OFF ++ * arg0: 0: do power-saving, NOT turn off radio + */ + #define MCU_SLEEP 0x30 + #define MCU_WAKEUP 0x31 +@@ -2279,7 +2289,9 @@ struct mac_iveiv_entry { + /* + * MCU mailbox tokens + */ +-#define TOKEN_WAKUP 3 ++#define TOKEN_SLEEP 1 ++#define TOKEN_RADIO_OFF 2 ++#define TOKEN_WAKEUP 3 + + /* + * DMA descriptor defines. +diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c +index dc88bae..9ac3017 100644 +--- a/drivers/net/wireless/rt2x00/rt2800pci.c ++++ b/drivers/net/wireless/rt2x00/rt2800pci.c +@@ -517,23 +517,6 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) + } + } + +-static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, +- enum dev_state state) +-{ +- if (state == STATE_AWAKE) { +- rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0x02); +- rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP); +- } else if (state == STATE_SLEEP) { +- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, +- 0xffffffff); +- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, +- 0xffffffff); +- rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0x01, 0xff, 0x01); +- } +- +- return 0; +-} +- + static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, + enum dev_state state) + { +@@ -541,14 +524,20 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, + + switch (state) { + case STATE_RADIO_ON: +- /* +- * Before the radio can be enabled, the device first has +- * to be woken up. After that it needs a bit of time +- * to be fully awake and then the radio can be enabled. +- */ +- rt2800pci_set_state(rt2x00dev, STATE_AWAKE); +- msleep(1); ++ /* Initialise all registers and send MCU_BOOT_SIGNAL. */ + retval = rt2800pci_enable_radio(rt2x00dev); ++ ++ /* After resume MCU_BOOT_SIGNAL will trash those. */ ++ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); ++ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); ++ ++ /* Finish initialization procedure. */ ++ rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, ++ 0xff, 0x02); ++ rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF); ++ ++ rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKEUP, 0, 0); ++ rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP); + break; + case STATE_RADIO_OFF: + /* +@@ -556,7 +545,7 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, + * be put to sleep for powersaving. + */ + rt2800pci_disable_radio(rt2x00dev); +- rt2800pci_set_state(rt2x00dev, STATE_SLEEP); ++ rt2800pci_set_device_state(rt2x00dev, STATE_SLEEP); + break; + case STATE_RADIO_IRQ_ON: + case STATE_RADIO_IRQ_OFF: +@@ -565,8 +554,16 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, + case STATE_DEEP_SLEEP: + case STATE_SLEEP: + case STATE_STANDBY: ++ /* PCIe devices won't report status after SLEEP request. */ ++ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); ++ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); ++ rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP, ++ 0xff, 0x01); ++ break; + case STATE_AWAKE: +- retval = rt2800pci_set_state(rt2x00dev, state); ++ rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKEUP, ++ 0, 0x02); ++ rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP); + break; + default: + retval = -ENOTSUPP; From 6d8eefbb611d8d362ab0160ff4f076faea2cff9b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 3 Feb 2012 13:27:57 -0500 Subject: [PATCH 258/487] Linux 3.2.3 --- kernel.spec | 33 +- ...1-fix-work-removal-on-deauth-request.patch | 109 --- rcu-reintroduce-missing-calls.patch | 632 ------------------ ...ds_sock_lock-BH-rather-than-IRQ-safe.patch | 116 ---- realtek_async_autopm.patch | 13 - sources | 1 + tpm_tis-delay-after-aborting-cmd.patch | 17 - 7 files changed, 5 insertions(+), 916 deletions(-) delete mode 100644 mac80211-fix-work-removal-on-deauth-request.patch delete mode 100644 rcu-reintroduce-missing-calls.patch delete mode 100644 rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch delete mode 100644 realtek_async_autopm.patch delete mode 100644 tpm_tis-delay-after-aborting-cmd.patch diff --git a/kernel.spec b/kernel.spec index 57fa8be39..31ad2d3ef 100644 --- a/kernel.spec +++ b/kernel.spec @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 2 +%define stable_update 3 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -763,9 +763,6 @@ Patch21045: nfs-client-freezer.patch #rhbz 590880 Patch21046: alps.patch -#rhbz 746097 -Patch21049: tpm_tis-delay-after-aborting-cmd.patch - Patch21070: ext4-Support-check-none-nocheck-mount-options.patch Patch21071: ext4-Fix-error-handling-on-inode-bitmap-corruption.patch @@ -800,19 +797,9 @@ Patch21225: pci-Rework-ASPM-disable-code.patch Patch21226: pci-crs-blacklist.patch -Patch21227: mac80211-fix-work-removal-on-deauth-request.patch - -#rhbz 718790 -Patch21230: rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch - -#rhbz 784345 -Patch21231: realtek_async_autopm.patch - #rhbz 772772 Patch21232: rt2x00_fix_MCU_request_failures.patch -Patch22000: rcu-reintroduce-missing-calls.patch - # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-pr_fmt-warning-avoidance.patch @@ -824,7 +811,6 @@ Patch50100: compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch Patch50101: mac80211-fix-debugfs-key-station-symlink.patch Patch50102: brcmsmac-fix-tx-queue-flush-infinite-loop.patch Patch50103: mac80211-Use-the-right-headroom-size-for-mesh-mgmt-f.patch -# mac80211-fix-work-removal-on-deauth-request.patch is patch 21227 Patch50105: b43-add-option-to-avoid-duplicating-device-support-w.patch Patch50106: mac80211-update-oper_channel-on-ibss-join.patch Patch50107: mac80211-set-bss_conf.idle-when-vif-is-connected.patch @@ -1488,9 +1474,6 @@ ApplyPatch nfs-client-freezer.patch #rhbz 590880 ApplyPatch alps.patch -#rhbz 746097 -ApplyPatch tpm_tis-delay-after-aborting-cmd.patch - #rhbz 771058 ApplyPatch msi-irq-sysfs-warning.patch @@ -1510,19 +1493,9 @@ ApplyPatch procfs-parse-mount-options.patch ApplyPatch procfs-add-hidepid-and-gid-mount-options.patch ApplyPatch proc-fix-null-pointer-deref-in-proc_pid_permission.patch -ApplyPatch mac80211-fix-work-removal-on-deauth-request.patch - -ApplyPatch rcu-reintroduce-missing-calls.patch - -#rhbz 718790 -ApplyPatch rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch - #rhbz 783211 ApplyPatch fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch -#rhbz 784345 -ApplyPatch realtek_async_autopm.patch - #rhbz 772772 ApplyPatch rt2x00_fix_MCU_request_failures.patch @@ -1598,7 +1571,6 @@ ApplyPatch compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch ApplyPatch mac80211-fix-debugfs-key-station-symlink.patch ApplyPatch brcmsmac-fix-tx-queue-flush-infinite-loop.patch ApplyPatch mac80211-Use-the-right-headroom-size-for-mesh-mgmt-f.patch -ApplyPatch mac80211-fix-work-removal-on-deauth-request.patch ApplyPatch b43-add-option-to-avoid-duplicating-device-support-w.patch ApplyPatch mac80211-update-oper_channel-on-ibss-join.patch ApplyPatch mac80211-set-bss_conf.idle-when-vif-is-connected.patch @@ -2314,6 +2286,9 @@ fi # and build. %changelog +* Fri Feb 03 2012 Dave Jones +- Linux 3.2.3 + * Fri Feb 03 2012 Josh Boyer - Patch from Jakub Kicinski to fix rt2x00 MCU requests (rhbz 772772) diff --git a/mac80211-fix-work-removal-on-deauth-request.patch b/mac80211-fix-work-removal-on-deauth-request.patch deleted file mode 100644 index 941b51861..000000000 --- a/mac80211-fix-work-removal-on-deauth-request.patch +++ /dev/null @@ -1,109 +0,0 @@ -From bc4934bc61d0a11fd62c5187ff83645628f8be8b Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Wed, 18 Jan 2012 14:10:25 +0100 -Subject: [PATCH 4/8] mac80211: fix work removal on deauth request - -When deauth is requested while an auth or assoc -work item is in progress, we currently delete it -without regard for any state it might need to -clean up. Fix it by cleaning up for those items. - -In the case Pontus found, the problem manifested -itself as such: - -authenticate with 00:23:69:aa:dd:7b (try 1) -authenticated -failed to insert Dummy STA entry for the AP (error -17) -deauthenticating from 00:23:69:aa:dd:7b by local choice (reason=2) - -It could also happen differently if the driver -uses the tx_sync callback. - -We can't just call the ->done() method of the work -items because that will lock up due to the locking -in cfg80211. This fix isn't very clean, but that -seems acceptable since I have patches pending to -remove this code completely. - -Cc: stable@vger.kernel.org -Reported-by: Pontus Fuchs -Tested-by: Pontus Fuchs -Signed-off-by: Johannes Berg -Signed-off-by: John W. Linville ---- - net/mac80211/mlme.c | 38 +++++++++++++++++++++++++++----------- - 1 files changed, 27 insertions(+), 11 deletions(-) - -diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index ecb4c84..295be92 100644 ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -2750,7 +2750,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, - { - struct ieee80211_local *local = sdata->local; - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; -- struct ieee80211_work *wk; - u8 bssid[ETH_ALEN]; - bool assoc_bss = false; - -@@ -2763,30 +2762,47 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, - assoc_bss = true; - } else { - bool not_auth_yet = false; -+ struct ieee80211_work *tmp, *wk = NULL; - - mutex_unlock(&ifmgd->mtx); - - mutex_lock(&local->mtx); -- list_for_each_entry(wk, &local->work_list, list) { -- if (wk->sdata != sdata) -+ list_for_each_entry(tmp, &local->work_list, list) { -+ if (tmp->sdata != sdata) - continue; - -- if (wk->type != IEEE80211_WORK_DIRECT_PROBE && -- wk->type != IEEE80211_WORK_AUTH && -- wk->type != IEEE80211_WORK_ASSOC && -- wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) -+ if (tmp->type != IEEE80211_WORK_DIRECT_PROBE && -+ tmp->type != IEEE80211_WORK_AUTH && -+ tmp->type != IEEE80211_WORK_ASSOC && -+ tmp->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) - continue; - -- if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN)) -+ if (memcmp(req->bss->bssid, tmp->filter_ta, ETH_ALEN)) - continue; - -- not_auth_yet = wk->type == IEEE80211_WORK_DIRECT_PROBE; -- list_del_rcu(&wk->list); -- free_work(wk); -+ not_auth_yet = tmp->type == IEEE80211_WORK_DIRECT_PROBE; -+ list_del_rcu(&tmp->list); -+ synchronize_rcu(); -+ wk = tmp; - break; - } - mutex_unlock(&local->mtx); - -+ if (wk && wk->type == IEEE80211_WORK_ASSOC) { -+ /* clean up dummy sta & TX sync */ -+ sta_info_destroy_addr(wk->sdata, wk->filter_ta); -+ if (wk->assoc.synced) -+ drv_finish_tx_sync(local, wk->sdata, -+ wk->filter_ta, -+ IEEE80211_TX_SYNC_ASSOC); -+ } else if (wk && wk->type == IEEE80211_WORK_AUTH) { -+ if (wk->probe_auth.synced) -+ drv_finish_tx_sync(local, wk->sdata, -+ wk->filter_ta, -+ IEEE80211_TX_SYNC_AUTH); -+ } -+ kfree(wk); -+ - /* - * If somebody requests authentication and we haven't - * sent out an auth frame yet there's no need to send --- -1.7.4.4 - diff --git a/rcu-reintroduce-missing-calls.patch b/rcu-reintroduce-missing-calls.patch deleted file mode 100644 index b887df750..000000000 --- a/rcu-reintroduce-missing-calls.patch +++ /dev/null @@ -1,632 +0,0 @@ -commit cf778b00e96df6d64f8e21b8395d1f8a859ecdc7 -Author: Eric Dumazet -Date: Thu Jan 12 04:41:32 2012 +0000 - - net: reintroduce missing rcu_assign_pointer() calls - - commit a9b3cd7f32 (rcu: convert uses of rcu_assign_pointer(x, NULL) to - RCU_INIT_POINTER) did a lot of incorrect changes, since it did a - complete conversion of rcu_assign_pointer(x, y) to RCU_INIT_POINTER(x, - y). - - We miss needed barriers, even on x86, when y is not NULL. - - Signed-off-by: Eric Dumazet - CC: Stephen Hemminger - CC: Paul E. McKenney - Signed-off-by: David S. Miller - -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/core/netpoll.c linux-3.2.net/net/core/netpoll.c ---- linux-3.2.noarch/net/core/netpoll.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/core/netpoll.c 2012-01-20 16:50:26.761797929 -0500 -@@ -763,7 +763,7 @@ int __netpoll_setup(struct netpoll *np) - } - - /* last thing to do is link it to the net device structure */ -- RCU_INIT_POINTER(ndev->npinfo, npinfo); -+ rcu_assign_pointer(ndev->npinfo, npinfo); - - return 0; - -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/core/net-sysfs.c linux-3.2.net/net/core/net-sysfs.c ---- linux-3.2.noarch/net/core/net-sysfs.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/core/net-sysfs.c 2012-01-20 16:50:26.730798974 -0500 -@@ -990,9 +990,9 @@ static ssize_t store_xps_map(struct netd - nonempty = 1; - } - -- if (nonempty) -- RCU_INIT_POINTER(dev->xps_maps, new_dev_maps); -- else { -+ if (nonempty) { -+ rcu_assign_pointer(dev->xps_maps, new_dev_maps); -+ } else { - kfree(new_dev_maps); - RCU_INIT_POINTER(dev->xps_maps, NULL); - } -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/decnet/dn_dev.c linux-3.2.net/net/decnet/dn_dev.c ---- linux-3.2.noarch/net/decnet/dn_dev.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/decnet/dn_dev.c 2012-01-20 16:50:26.793796851 -0500 -@@ -388,7 +388,7 @@ static int dn_dev_insert_ifa(struct dn_d - } - - ifa->ifa_next = dn_db->ifa_list; -- RCU_INIT_POINTER(dn_db->ifa_list, ifa); -+ rcu_assign_pointer(dn_db->ifa_list, ifa); - - dn_ifaddr_notify(RTM_NEWADDR, ifa); - blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa); -@@ -1093,7 +1093,7 @@ static struct dn_dev *dn_dev_create(stru - - memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms)); - -- RCU_INIT_POINTER(dev->dn_ptr, dn_db); -+ rcu_assign_pointer(dev->dn_ptr, dn_db); - dn_db->dev = dev; - init_timer(&dn_db->timer); - -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv4/devinet.c linux-3.2.net/net/ipv4/devinet.c ---- linux-3.2.noarch/net/ipv4/devinet.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/ipv4/devinet.c 2012-01-20 16:50:26.829795637 -0500 -@@ -258,7 +258,7 @@ static struct in_device *inetdev_init(st - ip_mc_up(in_dev); - - /* we can receive as soon as ip_ptr is set -- do this last */ -- RCU_INIT_POINTER(dev->ip_ptr, in_dev); -+ rcu_assign_pointer(dev->ip_ptr, in_dev); - out: - return in_dev; - out_kfree: -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv4/fib_trie.c linux-3.2.net/net/ipv4/fib_trie.c ---- linux-3.2.noarch/net/ipv4/fib_trie.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/ipv4/fib_trie.c 2012-01-20 16:50:26.865794425 -0500 -@@ -205,7 +205,7 @@ static inline struct tnode *node_parent_ - return (struct tnode *)(parent & ~NODE_TYPE_MASK); - } - --/* Same as RCU_INIT_POINTER -+/* Same as rcu_assign_pointer - * but that macro() assumes that value is a pointer. - */ - static inline void node_set_parent(struct rt_trie_node *node, struct tnode *ptr) -@@ -529,7 +529,7 @@ static void tnode_put_child_reorg(struct - if (n) - node_set_parent(n, tn); - -- RCU_INIT_POINTER(tn->child[i], n); -+ rcu_assign_pointer(tn->child[i], n); - } - - #define MAX_WORK 10 -@@ -1015,7 +1015,7 @@ static void trie_rebalance(struct trie * - - tp = node_parent((struct rt_trie_node *) tn); - if (!tp) -- RCU_INIT_POINTER(t->trie, (struct rt_trie_node *)tn); -+ rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); - - tnode_free_flush(); - if (!tp) -@@ -1027,7 +1027,7 @@ static void trie_rebalance(struct trie * - if (IS_TNODE(tn)) - tn = (struct tnode *)resize(t, (struct tnode *)tn); - -- RCU_INIT_POINTER(t->trie, (struct rt_trie_node *)tn); -+ rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); - tnode_free_flush(); - } - -@@ -1164,7 +1164,7 @@ static struct list_head *fib_insert_node - put_child(t, (struct tnode *)tp, cindex, - (struct rt_trie_node *)tn); - } else { -- RCU_INIT_POINTER(t->trie, (struct rt_trie_node *)tn); -+ rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); - tp = tn; - } - } -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv4/igmp.c linux-3.2.net/net/ipv4/igmp.c ---- linux-3.2.noarch/net/ipv4/igmp.c 2012-01-20 16:22:44.923961882 -0500 -+++ linux-3.2.net/net/ipv4/igmp.c 2012-01-20 16:50:26.898793315 -0500 -@@ -1244,7 +1244,7 @@ void ip_mc_inc_group(struct in_device *i - - im->next_rcu = in_dev->mc_list; - in_dev->mc_count++; -- RCU_INIT_POINTER(in_dev->mc_list, im); -+ rcu_assign_pointer(in_dev->mc_list, im); - - #ifdef CONFIG_IP_MULTICAST - igmpv3_del_delrec(in_dev, im->multiaddr); -@@ -1816,7 +1816,7 @@ int ip_mc_join_group(struct sock *sk , s - iml->next_rcu = inet->mc_list; - iml->sflist = NULL; - iml->sfmode = MCAST_EXCLUDE; -- RCU_INIT_POINTER(inet->mc_list, iml); -+ rcu_assign_pointer(inet->mc_list, iml); - ip_mc_inc_group(in_dev, addr); - err = 0; - done: -@@ -2003,7 +2003,7 @@ int ip_mc_source(int add, int omode, str - atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc); - kfree_rcu(psl, rcu); - } -- RCU_INIT_POINTER(pmc->sflist, newpsl); -+ rcu_assign_pointer(pmc->sflist, newpsl); - psl = newpsl; - } - rv = 1; /* > 0 for insert logic below if sl_count is 0 */ -@@ -2106,7 +2106,7 @@ int ip_mc_msfilter(struct sock *sk, stru - } else - (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode, - 0, NULL, 0); -- RCU_INIT_POINTER(pmc->sflist, newpsl); -+ rcu_assign_pointer(pmc->sflist, newpsl); - pmc->sfmode = msf->imsf_fmode; - err = 0; - done: -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv4/ipip.c linux-3.2.net/net/ipv4/ipip.c ---- linux-3.2.noarch/net/ipv4/ipip.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/ipv4/ipip.c 2012-01-20 16:50:26.916792707 -0500 -@@ -231,7 +231,7 @@ static void ipip_tunnel_unlink(struct ip - (iter = rtnl_dereference(*tp)) != NULL; - tp = &iter->next) { - if (t == iter) { -- RCU_INIT_POINTER(*tp, t->next); -+ rcu_assign_pointer(*tp, t->next); - break; - } - } -@@ -241,8 +241,8 @@ static void ipip_tunnel_link(struct ipip - { - struct ip_tunnel __rcu **tp = ipip_bucket(ipn, t); - -- RCU_INIT_POINTER(t->next, rtnl_dereference(*tp)); -- RCU_INIT_POINTER(*tp, t); -+ rcu_assign_pointer(t->next, rtnl_dereference(*tp)); -+ rcu_assign_pointer(*tp, t); - } - - static struct ip_tunnel * ipip_tunnel_locate(struct net *net, -@@ -792,7 +792,7 @@ static int __net_init ipip_fb_tunnel_ini - return -ENOMEM; - - dev_hold(dev); -- RCU_INIT_POINTER(ipn->tunnels_wc[0], tunnel); -+ rcu_assign_pointer(ipn->tunnels_wc[0], tunnel); - return 0; - } - -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv4/ipmr.c linux-3.2.net/net/ipv4/ipmr.c ---- linux-3.2.noarch/net/ipv4/ipmr.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/ipv4/ipmr.c 2012-01-20 16:50:26.946791698 -0500 -@@ -1225,7 +1225,7 @@ int ip_mroute_setsockopt(struct sock *sk - - ret = ip_ra_control(sk, 1, mrtsock_destruct); - if (ret == 0) { -- RCU_INIT_POINTER(mrt->mroute_sk, sk); -+ rcu_assign_pointer(mrt->mroute_sk, sk); - IPV4_DEVCONF_ALL(net, MC_FORWARDING)++; - } - rtnl_unlock(); -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv6/addrconf.c linux-3.2.net/net/ipv6/addrconf.c ---- linux-3.2.noarch/net/ipv6/addrconf.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/ipv6/addrconf.c 2012-01-20 16:50:26.977790653 -0500 -@@ -429,7 +429,7 @@ static struct inet6_dev * ipv6_add_dev(s - ndev->tstamp = jiffies; - addrconf_sysctl_register(ndev); - /* protected by rtnl_lock */ -- RCU_INIT_POINTER(dev->ip6_ptr, ndev); -+ rcu_assign_pointer(dev->ip6_ptr, ndev); - - /* Join all-node multicast group */ - ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes); -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv6/ip6_tunnel.c linux-3.2.net/net/ipv6/ip6_tunnel.c ---- linux-3.2.noarch/net/ipv6/ip6_tunnel.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/ipv6/ip6_tunnel.c 2012-01-20 16:50:27.004789743 -0500 -@@ -218,8 +218,8 @@ ip6_tnl_link(struct ip6_tnl_net *ip6n, s - { - struct ip6_tnl __rcu **tp = ip6_tnl_bucket(ip6n, &t->parms); - -- RCU_INIT_POINTER(t->next , rtnl_dereference(*tp)); -- RCU_INIT_POINTER(*tp, t); -+ rcu_assign_pointer(t->next , rtnl_dereference(*tp)); -+ rcu_assign_pointer(*tp, t); - } - - /** -@@ -237,7 +237,7 @@ ip6_tnl_unlink(struct ip6_tnl_net *ip6n, - (iter = rtnl_dereference(*tp)) != NULL; - tp = &iter->next) { - if (t == iter) { -- RCU_INIT_POINTER(*tp, t->next); -+ rcu_assign_pointer(*tp, t->next); - break; - } - } -@@ -1450,7 +1450,7 @@ static int __net_init ip6_fb_tnl_dev_ini - - t->parms.proto = IPPROTO_IPV6; - dev_hold(dev); -- RCU_INIT_POINTER(ip6n->tnls_wc[0], t); -+ rcu_assign_pointer(ip6n->tnls_wc[0], t); - return 0; - } - -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv6/raw.c linux-3.2.net/net/ipv6/raw.c ---- linux-3.2.noarch/net/ipv6/raw.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/ipv6/raw.c 2012-01-20 16:50:27.022789138 -0500 -@@ -131,7 +131,7 @@ static mh_filter_t __rcu *mh_filter __re - - int rawv6_mh_filter_register(mh_filter_t filter) - { -- RCU_INIT_POINTER(mh_filter, filter); -+ rcu_assign_pointer(mh_filter, filter); - return 0; - } - EXPORT_SYMBOL(rawv6_mh_filter_register); -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/ipv6/sit.c linux-3.2.net/net/ipv6/sit.c ---- linux-3.2.noarch/net/ipv6/sit.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/ipv6/sit.c 2012-01-20 16:50:27.042788464 -0500 -@@ -182,7 +182,7 @@ static void ipip6_tunnel_unlink(struct s - (iter = rtnl_dereference(*tp)) != NULL; - tp = &iter->next) { - if (t == iter) { -- RCU_INIT_POINTER(*tp, t->next); -+ rcu_assign_pointer(*tp, t->next); - break; - } - } -@@ -192,8 +192,8 @@ static void ipip6_tunnel_link(struct sit - { - struct ip_tunnel __rcu **tp = ipip6_bucket(sitn, t); - -- RCU_INIT_POINTER(t->next, rtnl_dereference(*tp)); -- RCU_INIT_POINTER(*tp, t); -+ rcu_assign_pointer(t->next, rtnl_dereference(*tp)); -+ rcu_assign_pointer(*tp, t); - } - - static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn) -@@ -393,7 +393,7 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t - p->addr = a->addr; - p->flags = a->flags; - t->prl_count++; -- RCU_INIT_POINTER(t->prl, p); -+ rcu_assign_pointer(t->prl, p); - out: - return err; - } -@@ -1177,7 +1177,7 @@ static int __net_init ipip6_fb_tunnel_in - if (!dev->tstats) - return -ENOMEM; - dev_hold(dev); -- RCU_INIT_POINTER(sitn->tunnels_wc[0], tunnel); -+ rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); - return 0; - } - -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/mac80211/agg-rx.c linux-3.2.net/net/mac80211/agg-rx.c ---- linux-3.2.noarch/net/mac80211/agg-rx.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/mac80211/agg-rx.c 2012-01-20 16:50:27.058787924 -0500 -@@ -326,7 +326,7 @@ void ieee80211_process_addba_request(str - status = WLAN_STATUS_SUCCESS; - - /* activate it for RX */ -- RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx); -+ rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx); - - if (timeout) - mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout)); -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/mac80211/cfg.c linux-3.2.net/net/mac80211/cfg.c ---- linux-3.2.noarch/net/mac80211/cfg.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/mac80211/cfg.c 2012-01-20 16:50:27.082787116 -0500 -@@ -575,7 +575,7 @@ static int ieee80211_config_beacon(struc - - sdata->vif.bss_conf.dtim_period = new->dtim_period; - -- RCU_INIT_POINTER(sdata->u.ap.beacon, new); -+ rcu_assign_pointer(sdata->u.ap.beacon, new); - - synchronize_rcu(); - -@@ -922,7 +922,7 @@ static int ieee80211_change_station(stru - return -EBUSY; - } - -- RCU_INIT_POINTER(vlansdata->u.vlan.sta, sta); -+ rcu_assign_pointer(vlansdata->u.vlan.sta, sta); - } - - sta->sdata = vlansdata; -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/mac80211/ibss.c linux-3.2.net/net/mac80211/ibss.c ---- linux-3.2.noarch/net/mac80211/ibss.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/mac80211/ibss.c 2012-01-20 16:50:27.102786444 -0500 -@@ -184,7 +184,7 @@ static void __ieee80211_sta_join_ibss(st - *pos++ = 0; /* U-APSD no in use */ - } - -- RCU_INIT_POINTER(ifibss->presp, skb); -+ rcu_assign_pointer(ifibss->presp, skb); - - sdata->vif.bss_conf.beacon_int = beacon_int; - sdata->vif.bss_conf.basic_rates = basic_rates; -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/mac80211/sta_info.c linux-3.2.net/net/mac80211/sta_info.c ---- linux-3.2.noarch/net/mac80211/sta_info.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/mac80211/sta_info.c 2012-01-20 16:50:27.131785466 -0500 -@@ -73,7 +73,7 @@ static int sta_info_hash_del(struct ieee - if (!s) - return -ENOENT; - if (s == sta) { -- RCU_INIT_POINTER(local->sta_hash[STA_HASH(sta->sta.addr)], -+ rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], - s->hnext); - return 0; - } -@@ -83,7 +83,7 @@ static int sta_info_hash_del(struct ieee - s = rcu_dereference_protected(s->hnext, - lockdep_is_held(&local->sta_lock)); - if (rcu_access_pointer(s->hnext)) { -- RCU_INIT_POINTER(s->hnext, sta->hnext); -+ rcu_assign_pointer(s->hnext, sta->hnext); - return 0; - } - -@@ -232,7 +232,7 @@ static void sta_info_hash_add(struct iee - struct sta_info *sta) - { - sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)]; -- RCU_INIT_POINTER(local->sta_hash[STA_HASH(sta->sta.addr)], sta); -+ rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta); - } - - static void sta_unblock(struct work_struct *wk) -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_conntrack_core.c linux-3.2.net/net/netfilter/nf_conntrack_core.c ---- linux-3.2.noarch/net/netfilter/nf_conntrack_core.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/netfilter/nf_conntrack_core.c 2012-01-20 16:50:27.169784186 -0500 -@@ -776,7 +776,7 @@ init_conntrack(struct net *net, struct n - if (exp->helper) { - help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); - if (help) -- RCU_INIT_POINTER(help->helper, exp->helper); -+ rcu_assign_pointer(help->helper, exp->helper); - } - - #ifdef CONFIG_NF_CONNTRACK_MARK -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_conntrack_ecache.c linux-3.2.net/net/netfilter/nf_conntrack_ecache.c ---- linux-3.2.noarch/net/netfilter/nf_conntrack_ecache.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/netfilter/nf_conntrack_ecache.c 2012-01-20 16:50:27.187783578 -0500 -@@ -91,7 +91,7 @@ int nf_conntrack_register_notifier(struc - ret = -EBUSY; - goto out_unlock; - } -- RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, new); -+ rcu_assign_pointer(net->ct.nf_conntrack_event_cb, new); - mutex_unlock(&nf_ct_ecache_mutex); - return ret; - -@@ -128,7 +128,7 @@ int nf_ct_expect_register_notifier(struc - ret = -EBUSY; - goto out_unlock; - } -- RCU_INIT_POINTER(net->ct.nf_expect_event_cb, new); -+ rcu_assign_pointer(net->ct.nf_expect_event_cb, new); - mutex_unlock(&nf_ct_ecache_mutex); - return ret; - -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_conntrack_extend.c linux-3.2.net/net/netfilter/nf_conntrack_extend.c ---- linux-3.2.noarch/net/netfilter/nf_conntrack_extend.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/netfilter/nf_conntrack_extend.c 2012-01-20 16:50:27.204783008 -0500 -@@ -169,7 +169,7 @@ int nf_ct_extend_register(struct nf_ct_e - before updating alloc_size */ - type->alloc_size = ALIGN(sizeof(struct nf_ct_ext), type->align) - + type->len; -- RCU_INIT_POINTER(nf_ct_ext_types[type->id], type); -+ rcu_assign_pointer(nf_ct_ext_types[type->id], type); - update_alloc_size(type); - out: - mutex_unlock(&nf_ct_ext_type_mutex); -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_conntrack_helper.c linux-3.2.net/net/netfilter/nf_conntrack_helper.c ---- linux-3.2.noarch/net/netfilter/nf_conntrack_helper.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/netfilter/nf_conntrack_helper.c 2012-01-20 16:50:27.227782232 -0500 -@@ -145,7 +145,7 @@ int __nf_ct_try_assign_helper(struct nf_ - memset(&help->help, 0, sizeof(help->help)); - } - -- RCU_INIT_POINTER(help->helper, helper); -+ rcu_assign_pointer(help->helper, helper); - out: - return ret; - } -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_conntrack_netlink.c linux-3.2.net/net/netfilter/nf_conntrack_netlink.c ---- linux-3.2.noarch/net/netfilter/nf_conntrack_netlink.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/netfilter/nf_conntrack_netlink.c 2012-01-20 16:50:27.271780750 -0500 -@@ -1163,7 +1163,7 @@ ctnetlink_change_helper(struct nf_conn * - return -EOPNOTSUPP; - } - -- RCU_INIT_POINTER(help->helper, helper); -+ rcu_assign_pointer(help->helper, helper); - - return 0; - } -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_log.c linux-3.2.net/net/netfilter/nf_log.c ---- linux-3.2.noarch/net/netfilter/nf_log.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/netfilter/nf_log.c 2012-01-20 16:50:27.280780448 -0500 -@@ -55,7 +55,7 @@ int nf_log_register(u_int8_t pf, struct - llog = rcu_dereference_protected(nf_loggers[pf], - lockdep_is_held(&nf_log_mutex)); - if (llog == NULL) -- RCU_INIT_POINTER(nf_loggers[pf], logger); -+ rcu_assign_pointer(nf_loggers[pf], logger); - } - - mutex_unlock(&nf_log_mutex); -@@ -92,7 +92,7 @@ int nf_log_bind_pf(u_int8_t pf, const st - mutex_unlock(&nf_log_mutex); - return -ENOENT; - } -- RCU_INIT_POINTER(nf_loggers[pf], logger); -+ rcu_assign_pointer(nf_loggers[pf], logger); - mutex_unlock(&nf_log_mutex); - return 0; - } -@@ -250,7 +250,7 @@ static int nf_log_proc_dostring(ctl_tabl - mutex_unlock(&nf_log_mutex); - return -ENOENT; - } -- RCU_INIT_POINTER(nf_loggers[tindex], logger); -+ rcu_assign_pointer(nf_loggers[tindex], logger); - mutex_unlock(&nf_log_mutex); - } else { - mutex_lock(&nf_log_mutex); -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nfnetlink.c linux-3.2.net/net/netfilter/nfnetlink.c ---- linux-3.2.noarch/net/netfilter/nfnetlink.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/netfilter/nfnetlink.c 2012-01-20 16:50:27.302779705 -0500 -@@ -59,7 +59,7 @@ int nfnetlink_subsys_register(const stru - nfnl_unlock(); - return -EBUSY; - } -- RCU_INIT_POINTER(subsys_table[n->subsys_id], n); -+ rcu_assign_pointer(subsys_table[n->subsys_id], n); - nfnl_unlock(); - - return 0; -@@ -210,7 +210,7 @@ static int __net_init nfnetlink_net_init - if (!nfnl) - return -ENOMEM; - net->nfnl_stash = nfnl; -- RCU_INIT_POINTER(net->nfnl, nfnl); -+ rcu_assign_pointer(net->nfnl, nfnl); - return 0; - } - -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netfilter/nf_queue.c linux-3.2.net/net/netfilter/nf_queue.c ---- linux-3.2.noarch/net/netfilter/nf_queue.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/netfilter/nf_queue.c 2012-01-20 16:50:27.293780010 -0500 -@@ -40,7 +40,7 @@ int nf_register_queue_handler(u_int8_t p - else if (old) - ret = -EBUSY; - else { -- RCU_INIT_POINTER(queue_handler[pf], qh); -+ rcu_assign_pointer(queue_handler[pf], qh); - ret = 0; - } - mutex_unlock(&queue_handler_mutex); -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netlabel/netlabel_domainhash.c linux-3.2.net/net/netlabel/netlabel_domainhash.c ---- linux-3.2.noarch/net/netlabel/netlabel_domainhash.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/netlabel/netlabel_domainhash.c 2012-01-20 16:50:27.311779402 -0500 -@@ -282,7 +282,7 @@ int __init netlbl_domhsh_init(u32 size) - INIT_LIST_HEAD(&hsh_tbl->tbl[iter]); - - spin_lock(&netlbl_domhsh_lock); -- RCU_INIT_POINTER(netlbl_domhsh, hsh_tbl); -+ rcu_assign_pointer(netlbl_domhsh, hsh_tbl); - spin_unlock(&netlbl_domhsh_lock); - - return 0; -@@ -330,7 +330,7 @@ int netlbl_domhsh_add(struct netlbl_dom_ - &rcu_dereference(netlbl_domhsh)->tbl[bkt]); - } else { - INIT_LIST_HEAD(&entry->list); -- RCU_INIT_POINTER(netlbl_domhsh_def, entry); -+ rcu_assign_pointer(netlbl_domhsh_def, entry); - } - - if (entry->type == NETLBL_NLTYPE_ADDRSELECT) { -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/netlabel/netlabel_unlabeled.c linux-3.2.net/net/netlabel/netlabel_unlabeled.c ---- linux-3.2.noarch/net/netlabel/netlabel_unlabeled.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/netlabel/netlabel_unlabeled.c 2012-01-20 16:50:27.327778863 -0500 -@@ -354,7 +354,7 @@ static struct netlbl_unlhsh_iface *netlb - INIT_LIST_HEAD(&iface->list); - if (netlbl_unlhsh_rcu_deref(netlbl_unlhsh_def) != NULL) - goto add_iface_failure; -- RCU_INIT_POINTER(netlbl_unlhsh_def, iface); -+ rcu_assign_pointer(netlbl_unlhsh_def, iface); - } - spin_unlock(&netlbl_unlhsh_lock); - -@@ -1447,11 +1447,9 @@ int __init netlbl_unlabel_init(u32 size) - for (iter = 0; iter < hsh_tbl->size; iter++) - INIT_LIST_HEAD(&hsh_tbl->tbl[iter]); - -- rcu_read_lock(); - spin_lock(&netlbl_unlhsh_lock); -- RCU_INIT_POINTER(netlbl_unlhsh, hsh_tbl); -+ rcu_assign_pointer(netlbl_unlhsh, hsh_tbl); - spin_unlock(&netlbl_unlhsh_lock); -- rcu_read_unlock(); - - register_netdevice_notifier(&netlbl_unlhsh_netdev_notifier); - -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/phonet/af_phonet.c linux-3.2.net/net/phonet/af_phonet.c ---- linux-3.2.noarch/net/phonet/af_phonet.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/phonet/af_phonet.c 2012-01-20 16:50:27.345778258 -0500 -@@ -480,7 +480,7 @@ int __init_or_module phonet_proto_regist - if (proto_tab[protocol]) - err = -EBUSY; - else -- RCU_INIT_POINTER(proto_tab[protocol], pp); -+ rcu_assign_pointer(proto_tab[protocol], pp); - mutex_unlock(&proto_tab_lock); - - return err; -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/phonet/pn_dev.c linux-3.2.net/net/phonet/pn_dev.c ---- linux-3.2.noarch/net/phonet/pn_dev.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/phonet/pn_dev.c 2012-01-20 16:50:27.353777988 -0500 -@@ -390,7 +390,7 @@ int phonet_route_add(struct net_device * - daddr = daddr >> 2; - mutex_lock(&routes->lock); - if (routes->table[daddr] == NULL) { -- RCU_INIT_POINTER(routes->table[daddr], dev); -+ rcu_assign_pointer(routes->table[daddr], dev); - dev_hold(dev); - err = 0; - } -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/phonet/socket.c linux-3.2.net/net/phonet/socket.c ---- linux-3.2.noarch/net/phonet/socket.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/phonet/socket.c 2012-01-20 16:50:27.365777583 -0500 -@@ -680,7 +680,7 @@ int pn_sock_bind_res(struct sock *sk, u8 - mutex_lock(&resource_mutex); - if (pnres.sk[res] == NULL) { - sock_hold(sk); -- RCU_INIT_POINTER(pnres.sk[res], sk); -+ rcu_assign_pointer(pnres.sk[res], sk); - ret = 0; - } - mutex_unlock(&resource_mutex); -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/socket.c linux-3.2.net/net/socket.c ---- linux-3.2.noarch/net/socket.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/socket.c 2012-01-20 16:50:27.410776068 -0500 -@@ -2472,7 +2472,7 @@ int sock_register(const struct net_proto - lockdep_is_held(&net_family_lock))) - err = -EEXIST; - else { -- RCU_INIT_POINTER(net_families[ops->family], ops); -+ rcu_assign_pointer(net_families[ops->family], ops); - err = 0; - } - spin_unlock(&net_family_lock); -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/sunrpc/auth_gss/auth_gss.c linux-3.2.net/net/sunrpc/auth_gss/auth_gss.c ---- linux-3.2.noarch/net/sunrpc/auth_gss/auth_gss.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/sunrpc/auth_gss/auth_gss.c 2012-01-20 16:50:27.428775461 -0500 -@@ -122,7 +122,7 @@ gss_cred_set_ctx(struct rpc_cred *cred, - if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)) - return; - gss_get_ctx(ctx); -- RCU_INIT_POINTER(gss_cred->gc_ctx, ctx); -+ rcu_assign_pointer(gss_cred->gc_ctx, ctx); - set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); - smp_mb__before_clear_bit(); - clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags); -diff -durpN '--exclude-from=/home/davej/.exclude' linux-3.2.noarch/net/xfrm/xfrm_user.c linux-3.2.net/net/xfrm/xfrm_user.c ---- linux-3.2.noarch/net/xfrm/xfrm_user.c 2012-01-04 18:55:44.000000000 -0500 -+++ linux-3.2.net/net/xfrm/xfrm_user.c 2012-01-20 16:50:27.449774754 -0500 -@@ -2927,7 +2927,7 @@ static int __net_init xfrm_user_net_init - if (nlsk == NULL) - return -ENOMEM; - net->xfrm.nlsk_stash = nlsk; /* Don't set to NULL */ -- RCU_INIT_POINTER(net->xfrm.nlsk, nlsk); -+ rcu_assign_pointer(net->xfrm.nlsk, nlsk); - return 0; - } - diff --git a/rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch b/rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch deleted file mode 100644 index 0946aad6b..000000000 --- a/rds-Make-rds_sock_lock-BH-rather-than-IRQ-safe.patch +++ /dev/null @@ -1,116 +0,0 @@ -From efc3dbc37412c027e363736b4f4c74ee5e8ecffc Mon Sep 17 00:00:00 2001 -From: "David S. Miller" -Date: Tue, 24 Jan 2012 17:03:44 -0500 -Subject: [PATCH] rds: Make rds_sock_lock BH rather than IRQ safe. - -rds_sock_info() triggers locking warnings because we try to perform a -local_bh_enable() (via sock_i_ino()) while hardware interrupts are -disabled (via taking rds_sock_lock). - -There is no reason for rds_sock_lock to be a hardware IRQ disabling -lock, none of these access paths run in hardware interrupt context. - -Therefore making it a BH disabling lock is safe and sufficient to -fix this bug. - -Reported-by: Kumar Sanghvi -Reported-by: Josh Boyer -Signed-off-by: David S. Miller ---- - net/rds/af_rds.c | 20 ++++++++------------ - 1 files changed, 8 insertions(+), 12 deletions(-) - -diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c -index bb6ad81..424ff62 100644 ---- a/net/rds/af_rds.c -+++ b/net/rds/af_rds.c -@@ -68,7 +68,6 @@ static int rds_release(struct socket *sock) - { - struct sock *sk = sock->sk; - struct rds_sock *rs; -- unsigned long flags; - - if (!sk) - goto out; -@@ -94,10 +93,10 @@ static int rds_release(struct socket *sock) - rds_rdma_drop_keys(rs); - rds_notify_queue_get(rs, NULL); - -- spin_lock_irqsave(&rds_sock_lock, flags); -+ spin_lock_bh(&rds_sock_lock); - list_del_init(&rs->rs_item); - rds_sock_count--; -- spin_unlock_irqrestore(&rds_sock_lock, flags); -+ spin_unlock_bh(&rds_sock_lock); - - rds_trans_put(rs->rs_transport); - -@@ -409,7 +408,6 @@ static const struct proto_ops rds_proto_ops = { - - static int __rds_create(struct socket *sock, struct sock *sk, int protocol) - { -- unsigned long flags; - struct rds_sock *rs; - - sock_init_data(sock, sk); -@@ -426,10 +424,10 @@ static int __rds_create(struct socket *sock, struct sock *sk, int protocol) - spin_lock_init(&rs->rs_rdma_lock); - rs->rs_rdma_keys = RB_ROOT; - -- spin_lock_irqsave(&rds_sock_lock, flags); -+ spin_lock_bh(&rds_sock_lock); - list_add_tail(&rs->rs_item, &rds_sock_list); - rds_sock_count++; -- spin_unlock_irqrestore(&rds_sock_lock, flags); -+ spin_unlock_bh(&rds_sock_lock); - - return 0; - } -@@ -471,12 +469,11 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len, - { - struct rds_sock *rs; - struct rds_incoming *inc; -- unsigned long flags; - unsigned int total = 0; - - len /= sizeof(struct rds_info_message); - -- spin_lock_irqsave(&rds_sock_lock, flags); -+ spin_lock_bh(&rds_sock_lock); - - list_for_each_entry(rs, &rds_sock_list, rs_item) { - read_lock(&rs->rs_recv_lock); -@@ -492,7 +489,7 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len, - read_unlock(&rs->rs_recv_lock); - } - -- spin_unlock_irqrestore(&rds_sock_lock, flags); -+ spin_unlock_bh(&rds_sock_lock); - - lens->nr = total; - lens->each = sizeof(struct rds_info_message); -@@ -504,11 +501,10 @@ static void rds_sock_info(struct socket *sock, unsigned int len, - { - struct rds_info_socket sinfo; - struct rds_sock *rs; -- unsigned long flags; - - len /= sizeof(struct rds_info_socket); - -- spin_lock_irqsave(&rds_sock_lock, flags); -+ spin_lock_bh(&rds_sock_lock); - - if (len < rds_sock_count) - goto out; -@@ -529,7 +525,7 @@ out: - lens->nr = rds_sock_count; - lens->each = sizeof(struct rds_info_socket); - -- spin_unlock_irqrestore(&rds_sock_lock, flags); -+ spin_unlock_bh(&rds_sock_lock); - } - - static void rds_exit(void) --- -1.7.7.6 - diff --git a/realtek_async_autopm.patch b/realtek_async_autopm.patch deleted file mode 100644 index 3c6b45cca..000000000 --- a/realtek_async_autopm.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c -index 1f62723..d32f720 100644 ---- a/drivers/usb/storage/realtek_cr.c -+++ b/drivers/usb/storage/realtek_cr.c -@@ -789,7 +789,7 @@ static void rts51x_suspend_timer_fn(unsigned long data) - rts51x_set_stat(chip, RTS51X_STAT_SS); - /* ignore mass storage interface's children */ - pm_suspend_ignore_children(&us->pusb_intf->dev, true); -- usb_autopm_put_interface(us->pusb_intf); -+ usb_autopm_put_interface_async(us->pusb_intf); - US_DEBUGP("%s: RTS51X_STAT_SS 01," - "intf->pm_usage_cnt:%d, power.usage:%d\n", - __func__, diff --git a/sources b/sources index 66fa5b1a2..312a6a0d7 100644 --- a/sources +++ b/sources @@ -1,3 +1,4 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz 8cfe037a7a7a356278ec3638e25ad506 compat-wireless-3.3-rc1-2.tar.bz2 5e53edbf75fcaa3a8d1697f3a053102d patch-3.2.2.xz +4ffcd30b95b4d2435be40405507319dd patch-3.2.3.xz diff --git a/tpm_tis-delay-after-aborting-cmd.patch b/tpm_tis-delay-after-aborting-cmd.patch deleted file mode 100644 index 315284f50..000000000 --- a/tpm_tis-delay-after-aborting-cmd.patch +++ /dev/null @@ -1,17 +0,0 @@ -This patch adds a delay after aborting a command. Some TPMs need -this and will not process the subsequent command correctly otherwise. - -Signed-off-by: Stefan Berger - ---- linux-3.1.noarch/drivers/char/tpm/tpm_tis.c~ 2011-12-20 18:08:01.654464487 -0500 -+++ linux-3.1.noarch/drivers/char/tpm/tpm_tis.c 2011-12-20 18:08:23.476380364 -0500 -@@ -432,6 +432,9 @@ static int probe_itpm(struct tpm_chip *c - out: - itpm = rem_itpm; - tpm_tis_ready(chip); -+ /* some TPMs need a break here otherwise they will not work -+ * correctly on the immediately subsequent command */ -+ msleep(chip->vendor.timeout_b); - release_locality(chip, chip->vendor.locality, 0); - - return rc; From 3ad4b3ec23236546e5b56e2b0ad7109af04abd1b Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 3 Feb 2012 13:38:35 -0500 Subject: [PATCH 259/487] bcma: Fix mem leak in bcma_bus_scan() rt2800lib: fix wrong -128dBm when signal is stronger than -12dBm iwlwifi: make "Tx aggregation enabled on ra =" be at DEBUG level ssb: fix cardbus slot in hostmode mac80211: timeout a single frame in the rx reorder buffer --- bcma-Fix-mem-leak-in-bcma_bus_scan.patch | 51 +++++++++++++++++ ...aggregation-enabled-on-ra-be-at-DEBU.patch | 30 ++++++++++ kernel.spec | 21 ++++++- ...-a-single-frame-in-the-rx-reorder-bu.patch | 33 +++++++++++ ...ong-128dBm-when-signal-is-stronger-t.patch | 55 +++++++++++++++++++ ssb-fix-cardbus-slot-in-hostmode.patch | 34 ++++++++++++ 6 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 bcma-Fix-mem-leak-in-bcma_bus_scan.patch create mode 100644 iwlwifi-make-Tx-aggregation-enabled-on-ra-be-at-DEBU.patch create mode 100644 mac80211-timeout-a-single-frame-in-the-rx-reorder-bu.patch create mode 100644 rt2800lib-fix-wrong-128dBm-when-signal-is-stronger-t.patch create mode 100644 ssb-fix-cardbus-slot-in-hostmode.patch diff --git a/bcma-Fix-mem-leak-in-bcma_bus_scan.patch b/bcma-Fix-mem-leak-in-bcma_bus_scan.patch new file mode 100644 index 000000000..d888e8c8b --- /dev/null +++ b/bcma-Fix-mem-leak-in-bcma_bus_scan.patch @@ -0,0 +1,51 @@ +From f9721ed2707661af75a414d09cdcd71f99a13f62 Mon Sep 17 00:00:00 2001 +From: Jesper Juhl +Date: Sun, 29 Jan 2012 21:34:04 +0100 +Subject: [PATCH] bcma: Fix mem leak in bcma_bus_scan() + +bcma_bus_scan() leaks 'struct bcma_device' bytes if +bcma_get_next_core() returns error. + +Restructure the code so we always kfree() the memory we allocate to +the variable 'core' before it goes out of scope. + +Signed-off-by: Jesper Juhl +Signed-off-by: John W. Linville +--- + drivers/bcma/scan.c | 19 +++++++++++-------- + 1 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c +index cad9948..3a2f672 100644 +--- a/drivers/bcma/scan.c ++++ b/drivers/bcma/scan.c +@@ -399,15 +399,18 @@ int bcma_bus_scan(struct bcma_bus *bus) + core->bus = bus; + + err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core); +- if (err == -ENODEV) { +- core_num++; +- continue; +- } else if (err == -ENXIO) +- continue; +- else if (err == -ESPIPE) +- break; +- else if (err < 0) ++ if (err < 0) { ++ kfree(core); ++ if (err == -ENODEV) { ++ core_num++; ++ continue; ++ } else if (err == -ENXIO) { ++ continue; ++ } else if (err == -ESPIPE) { ++ break; ++ } + return err; ++ } + + core->core_index = core_num++; + bus->nr_cores++; +-- +1.7.4.4 + diff --git a/iwlwifi-make-Tx-aggregation-enabled-on-ra-be-at-DEBU.patch b/iwlwifi-make-Tx-aggregation-enabled-on-ra-be-at-DEBU.patch new file mode 100644 index 000000000..0537e8133 --- /dev/null +++ b/iwlwifi-make-Tx-aggregation-enabled-on-ra-be-at-DEBU.patch @@ -0,0 +1,30 @@ +From 5fb8c182d26472ea24cbbadb6a3e355d7621cca4 Mon Sep 17 00:00:00 2001 +From: John W. Linville +Date: Tue, 31 Jan 2012 14:40:49 -0500 +Subject: [PATCH] iwlwifi: make "Tx aggregation enabled on ra =" be at DEBUG + level + +Average users either don't care or they think that message indicates a +problem... + +Signed-off-by: John W. Linville +--- + drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +index c664c27..339e8d9 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +@@ -620,7 +620,7 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, + sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit = + sta_priv->max_agg_bufsize; + +- IWL_INFO(priv, "Tx aggregation enabled on ra = %pM tid = %d\n", ++ IWL_DEBUG_HT(priv, "Tx aggregation enabled on ra = %pM tid = %d\n", + sta->addr, tid); + + return iwl_send_lq_cmd(priv, ctx, +-- +1.7.4.4 + diff --git a/kernel.spec b/kernel.spec index 31ad2d3ef..96d222af6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -815,9 +815,14 @@ Patch50105: b43-add-option-to-avoid-duplicating-device-support-w.patch Patch50106: mac80211-update-oper_channel-on-ibss-join.patch Patch50107: mac80211-set-bss_conf.idle-when-vif-is-connected.patch Patch50108: iwlwifi-fix-PCI-E-transport-inta-race.patch +Patch50109: bcma-Fix-mem-leak-in-bcma_bus_scan.patch +Patch50110: rt2800lib-fix-wrong-128dBm-when-signal-is-stronger-t.patch +Patch50111: iwlwifi-make-Tx-aggregation-enabled-on-ra-be-at-DEBU.patch +Patch50112: ssb-fix-cardbus-slot-in-hostmode.patch +Patch50113: iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch +Patch50114: mac80211-timeout-a-single-frame-in-the-rx-reorder-bu.patch Patch50200: ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch -Patch50201: iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch %endif @@ -1575,10 +1580,15 @@ ApplyPatch b43-add-option-to-avoid-duplicating-device-support-w.patch ApplyPatch mac80211-update-oper_channel-on-ibss-join.patch ApplyPatch mac80211-set-bss_conf.idle-when-vif-is-connected.patch ApplyPatch iwlwifi-fix-PCI-E-transport-inta-race.patch +ApplyPatch bcma-Fix-mem-leak-in-bcma_bus_scan.patch +ApplyPatch rt2800lib-fix-wrong-128dBm-when-signal-is-stronger-t.patch +ApplyPatch iwlwifi-make-Tx-aggregation-enabled-on-ra-be-at-DEBU.patch +ApplyPatch ssb-fix-cardbus-slot-in-hostmode.patch +ApplyPatch iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch +ApplyPatch mac80211-timeout-a-single-frame-in-the-rx-reorder-bu.patch ApplyPatch ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch -ApplyPatch iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch ApplyPatch rt2x00_fix_MCU_request_failures.patch cd .. @@ -2286,6 +2296,13 @@ fi # and build. %changelog +* Fri Feb 3 2012 John W. Linville +- bcma: Fix mem leak in bcma_bus_scan() +- rt2800lib: fix wrong -128dBm when signal is stronger than -12dBm +- iwlwifi: make "Tx aggregation enabled on ra =" be at DEBUG level +- ssb: fix cardbus slot in hostmode +- mac80211: timeout a single frame in the rx reorder buffer + * Fri Feb 03 2012 Dave Jones - Linux 3.2.3 diff --git a/mac80211-timeout-a-single-frame-in-the-rx-reorder-bu.patch b/mac80211-timeout-a-single-frame-in-the-rx-reorder-bu.patch new file mode 100644 index 000000000..8d836d2bb --- /dev/null +++ b/mac80211-timeout-a-single-frame-in-the-rx-reorder-bu.patch @@ -0,0 +1,33 @@ +From 07ae2dfcf4f7143ce191c6436da1c33f179af0d6 Mon Sep 17 00:00:00 2001 +From: Eliad Peller +Date: Wed, 1 Feb 2012 18:48:09 +0200 +Subject: [PATCH] mac80211: timeout a single frame in the rx reorder buffer + +The current code checks for stored_mpdu_num > 1, causing +the reorder_timer to be triggered indefinitely, but the +frame is never timed-out (until the next packet is received) + +Signed-off-by: Eliad Peller +Cc: +Acked-by: Johannes Berg +Signed-off-by: John W. Linville +--- + net/mac80211/rx.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 7514091..5a5e504 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -611,7 +611,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, + index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % + tid_agg_rx->buf_size; + if (!tid_agg_rx->reorder_buf[index] && +- tid_agg_rx->stored_mpdu_num > 1) { ++ tid_agg_rx->stored_mpdu_num) { + /* + * No buffers ready to be released, but check whether any + * frames in the reorder buffer have timed out. +-- +1.7.4.4 + diff --git a/rt2800lib-fix-wrong-128dBm-when-signal-is-stronger-t.patch b/rt2800lib-fix-wrong-128dBm-when-signal-is-stronger-t.patch new file mode 100644 index 000000000..7fc6c20d0 --- /dev/null +++ b/rt2800lib-fix-wrong-128dBm-when-signal-is-stronger-t.patch @@ -0,0 +1,55 @@ +From 7fc417556473f15efac269523c17eb92103c6484 Mon Sep 17 00:00:00 2001 +From: Luigi Tarenga +Date: Tue, 31 Jan 2012 18:51:23 +0100 +Subject: [PATCH] rt2800lib: fix wrong -128dBm when signal is stronger than + -12dBm + +This patch correct the type of variables containing the rssi +values read from the rxwi. + +In function rt2800_agc_to_rssi() 3 variables (rssi0, rssi1, rss2) +defined as int was assigned a 16bit signed values as unsigned. +From a test with a hi-gain antenna I verified that the rxwi +contains signed rssi values in the range -13/+81 (inclusive) +with 0 as an error condition. In case of negative values a +condition is triggered and the function return -128dBm while +the signal is at its maximum. This patch correct the cast so +negative values are not treated as very high positive values +(ex. -13 does not become 243). + +Signed-off-by: Luigi Tarenga +Reviewed-by: Stanislaw Gruszka +Signed-off-by: John W. Linville +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 8 ++++---- + 1 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c +index 22a1a8f..7bef66d 100644 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -514,9 +514,9 @@ EXPORT_SYMBOL_GPL(rt2800_write_tx_data); + + static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2) + { +- int rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0); +- int rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1); +- int rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2); ++ s8 rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0); ++ s8 rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1); ++ s8 rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2); + u16 eeprom; + u8 offset0; + u8 offset1; +@@ -552,7 +552,7 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2) + * which gives less energy... + */ + rssi0 = max(rssi0, rssi1); +- return max(rssi0, rssi2); ++ return (int)max(rssi0, rssi2); + } + + void rt2800_process_rxwi(struct queue_entry *entry, +-- +1.7.4.4 + diff --git a/ssb-fix-cardbus-slot-in-hostmode.patch b/ssb-fix-cardbus-slot-in-hostmode.patch new file mode 100644 index 000000000..ed5de4da2 --- /dev/null +++ b/ssb-fix-cardbus-slot-in-hostmode.patch @@ -0,0 +1,34 @@ +From a6c84622b7fa3ea5417a9d1d0ce0bc3e7fbe3be1 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Wed, 1 Feb 2012 00:13:53 +0100 +Subject: [PATCH] ssb: fix cardbus slot in hostmode + +ssb supports one extra device on the cardbus. This results in two +devices in total, one beeing the host controller itself and the other +the external device connected to the hostcontroller over cardbus. + +This makes the cardbus slot work on the Linksys WRT150N. + +Reported-by: Aaron Z +Signed-off-by: Hauke Mehrtens +Signed-off-by: John W. Linville +--- + drivers/ssb/driver_pcicore.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c +index 520e828..49d2091 100644 +--- a/drivers/ssb/driver_pcicore.c ++++ b/drivers/ssb/driver_pcicore.c +@@ -75,7 +75,7 @@ static u32 get_cfgspace_addr(struct ssb_pcicore *pc, + u32 tmp; + + /* We do only have one cardbus device behind the bridge. */ +- if (pc->cardbusmode && (dev >= 1)) ++ if (pc->cardbusmode && (dev > 1)) + goto out; + + if (bus == 0) { +-- +1.7.4.4 + From 1ed3146ef87cbcbcc9b72ec829c94e754dca530c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 3 Feb 2012 14:10:52 -0500 Subject: [PATCH 260/487] Drop patch that was NAKed upstream (rhbz 783211) --- ...block-device-if-fsync-called-on-part.patch | 106 ------------------ kernel.spec | 9 +- 2 files changed, 3 insertions(+), 112 deletions(-) delete mode 100644 fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch diff --git a/fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch b/fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch deleted file mode 100644 index 5bab4f4ad..000000000 --- a/fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch +++ /dev/null @@ -1,106 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Niels de Vos -Newsgroups: gmane.linux.kernel,gmane.linux.file-systems -Subject: [PATCH v2] fs: Invalidate the cache for a parent block-device if fsync() is called for a partition -Date: Mon, 23 Jan 2012 10:38:29 +0000 -Lines: 58 -Approved: news@gmane.org -Message-ID: <1327315109-7740-1-git-send-email-ndevos@redhat.com> -References: <4F19356E.3020708@redhat.com> -NNTP-Posting-Host: lo.gmane.org -X-Trace: dough.gmane.org 1327315263 30652 80.91.229.12 (23 Jan 2012 10:41:03 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Mon, 23 Jan 2012 10:41:03 +0000 (UTC) -Cc: linux-kernel@vger.kernel.org, Niels de Vos , - "Bryn M. Reeves" , - Mikulas Patocka -To: linux-fsdevel@vger.kernel.org -Original-X-From: linux-kernel-owner@vger.kernel.org Mon Jan 23 11:40:58 2012 -Return-path: -Envelope-to: glk-linux-kernel-3@lo.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1RpHKb-0008Bu-Fh - for glk-linux-kernel-3@lo.gmane.org; Mon, 23 Jan 2012 11:40:57 +0100 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1753263Ab2AWKkt (ORCPT ); - Mon, 23 Jan 2012 05:40:49 -0500 -Original-Received: from mx1.redhat.com ([209.132.183.28]:58739 "EHLO mx1.redhat.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1751990Ab2AWKks (ORCPT ); - Mon, 23 Jan 2012 05:40:48 -0500 -Original-Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q0NAelMx027033 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); - Mon, 23 Jan 2012 05:40:47 -0500 -Original-Received: from ndevos.usersys.redhat.com (dhcp-1-51.fab.redhat.com [10.33.1.51]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q0NAejLn013691; - Mon, 23 Jan 2012 05:40:46 -0500 -In-Reply-To: <4F19356E.3020708@redhat.com> -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Original-Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel:1242432 gmane.linux.file-systems:60751 -Archived-At: - -Executing an fsync() on a file-descriptor of a partition flushes the -caches for that partition by calling blkdev_issue_flush(). However, it -seems that reading data through the parent device will still return the -old cached data. - -The cache for the block-device is not synced if the block-device is kept -open (due to a mounted partition, for example). Only when all users for -the disk have exited, the cache for the disk is made consistent again. - -Calling invalidate_bdev() on the parent block-device in case -blkdev_fsync() was called for a partition, fixes this. - -The problem can be worked around by forcing the caches to be flushed -with either - # blockdev --flushbufs ${dev_disk} -or - # echo 3 > /proc/sys/vm/drop_caches - -CC: Bryn M. Reeves -CC: Mikulas Patocka -Signed-off-by: Niels de Vos - ---- -v2: -- Do not call invalidate_bdev() from blkdev_issue_flush() and prevent - performance degration with journalled filesystems. - - Suggested was to call invalidate_bdev() in fsync_bdev(), but this is - not in the call-path of mkfs.ext3 and similar tools. Hence the issue - persists. - -- Correct phrasing a little, changing ioctl-BLKFLSBUF is not required. - -- This issue also occurs when doing an ioctl-BLKFLSBUF on a partition. - Reading the whole disk will still return cached data. If this is an - issue, it will need a seperate patch. ---- - fs/block_dev.c | 4 ++++ - 1 files changed, 4 insertions(+), 0 deletions(-) - -diff --git a/fs/block_dev.c b/fs/block_dev.c -index 0e575d1..433c4de 100644 ---- a/fs/block_dev.c -+++ b/fs/block_dev.c -@@ -424,6 +424,10 @@ int blkdev_fsync(struct file *filp, loff_t start, loff_t end, int datasync) - if (error == -EOPNOTSUPP) - error = 0; - -+ /* invalidate parent block_device */ -+ if (!error && bdev != bdev->bd_contains) -+ invalidate_bdev(bdev->bd_contains); -+ - return error; - } - EXPORT_SYMBOL(blkdev_fsync); --- -1.7.6.5 - diff --git a/kernel.spec b/kernel.spec index 96d222af6..9f7d9a53c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -784,9 +784,6 @@ Patch21082: procfs-parse-mount-options.patch Patch21083: procfs-add-hidepid-and-gid-mount-options.patch Patch21084: proc-fix-null-pointer-deref-in-proc_pid_permission.patch -#rhbz 783211 -Patch21087: fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch - #rhbz 771058 Patch22100: msi-irq-sysfs-warning.patch @@ -1498,9 +1495,6 @@ ApplyPatch procfs-parse-mount-options.patch ApplyPatch procfs-add-hidepid-and-gid-mount-options.patch ApplyPatch proc-fix-null-pointer-deref-in-proc_pid_permission.patch -#rhbz 783211 -ApplyPatch fs-Inval-cache-for-parent-block-device-if-fsync-called-on-part.patch - #rhbz 772772 ApplyPatch rt2x00_fix_MCU_request_failures.patch @@ -2296,6 +2290,9 @@ fi # and build. %changelog +* Fri Feb 03 2012 Josh Boyer +- Drop patch that was NAKed upstream (rhbz 783211) + * Fri Feb 3 2012 John W. Linville - bcma: Fix mem leak in bcma_bus_scan() - rt2800lib: fix wrong -128dBm when signal is stronger than -12dBm From 0f78fbf07308bf847a1a3d2af11e89e2230cd818 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 3 Feb 2012 14:29:13 -0500 Subject: [PATCH 261/487] remove old entry --- sources | 1 - 1 file changed, 1 deletion(-) diff --git a/sources b/sources index 312a6a0d7..0a6ecb347 100644 --- a/sources +++ b/sources @@ -1,4 +1,3 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz 8cfe037a7a7a356278ec3638e25ad506 compat-wireless-3.3-rc1-2.tar.bz2 -5e53edbf75fcaa3a8d1697f3a053102d patch-3.2.2.xz 4ffcd30b95b4d2435be40405507319dd patch-3.2.3.xz From 337ebb66d9cf201554c2d4af3d9b69dd7d79ce32 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 3 Feb 2012 14:29:44 -0500 Subject: [PATCH 262/487] add version that I forgot.. --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 9f7d9a53c..20f09f16e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2300,7 +2300,7 @@ fi - ssb: fix cardbus slot in hostmode - mac80211: timeout a single frame in the rx reorder buffer -* Fri Feb 03 2012 Dave Jones +* Fri Feb 03 2012 Dave Jones 3.2.3-1 - Linux 3.2.3 * Fri Feb 03 2012 Josh Boyer From 1e38741de6bd3c37261376ee2be8cd1ab805ea15 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 3 Feb 2012 14:33:36 -0500 Subject: [PATCH 263/487] bump for rebuild --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 20f09f16e..ac2780fb0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2290,7 +2290,7 @@ fi # and build. %changelog -* Fri Feb 03 2012 Josh Boyer +* Fri Feb 03 2012 Josh Boyer 3.2.3-2 - Drop patch that was NAKed upstream (rhbz 783211) * Fri Feb 3 2012 John W. Linville From 69d2ad30b8c9a671b232f1cefc9d6022dbcac318 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 5 Feb 2012 16:48:34 -0500 Subject: [PATCH 264/487] readahead: fix pipeline break caused by block plug Also, remove unnecessary block-stray-block-put-after-teardown.patch --- block-readahead-block-plug.patch | 92 ++++++++++++++++++++++ block-stray-block-put-after-teardown.patch | 11 --- kernel.spec | 9 ++- 3 files changed, 99 insertions(+), 13 deletions(-) create mode 100644 block-readahead-block-plug.patch delete mode 100644 block-stray-block-put-after-teardown.patch diff --git a/block-readahead-block-plug.patch b/block-readahead-block-plug.patch new file mode 100644 index 000000000..0b7bca650 --- /dev/null +++ b/block-readahead-block-plug.patch @@ -0,0 +1,92 @@ +commit 3deaa7190a8da38453c4fabd9dec7f66d17fff67 +Author: Shaohua Li +Date: Fri Feb 3 15:37:17 2012 -0800 + + readahead: fix pipeline break caused by block plug + + Herbert Poetzl reported a performance regression since 2.6.39. The test + is a simple dd read, but with big block size. The reason is: + + T1: ra (A, A+128k), (A+128k, A+256k) + T2: lock_page for page A, submit the 256k + T3: hit page A+128K, ra (A+256k, A+384). the range isn't submitted + because of plug and there isn't any lock_page till we hit page A+256k + because all pages from A to A+256k is in memory + T4: hit page A+256k, ra (A+384, A+ 512). Because of plug, the range isn't + submitted again. + T5: lock_page A+256k, so (A+256k, A+512k) will be submitted. The task is + waitting for (A+256k, A+512k) finish. + + There is no request to disk in T3 and T4, so readahead pipeline breaks. + + We really don't need block plug for generic_file_aio_read() for buffered + I/O. The readahead already has plug and has fine grained control when I/O + should be submitted. Deleting plug for buffered I/O fixes the regression. + + One side effect is plug makes the request size 256k, the size is 128k + without it. This is because default ra size is 128k and not a reason we + need plug here. + + Vivek said: + + : We submit some readahead IO to device request queue but because of nested + : plug, queue never gets unplugged. When read logic reaches a page which is + : not in page cache, it waits for page to be read from the disk + : (lock_page_killable()) and that time we flush the plug list. + : + : So effectively read ahead logic is kind of broken in parts because of + : nested plugging. Removing top level plug (generic_file_aio_read()) for + : buffered reads, will allow unplugging queue earlier for readahead. + + Signed-off-by: Shaohua Li + Signed-off-by: Wu Fengguang + Reported-by: Herbert Poetzl + Tested-by: Eric Dumazet + Cc: Christoph Hellwig + Cc: Jens Axboe + Cc: Vivek Goyal + Cc: + Signed-off-by: Andrew Morton + Signed-off-by: Linus Torvalds + +diff --git a/mm/filemap.c b/mm/filemap.c +index 97f49ed..b662757 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -1400,15 +1400,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, + unsigned long seg = 0; + size_t count; + loff_t *ppos = &iocb->ki_pos; +- struct blk_plug plug; + + count = 0; + retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE); + if (retval) + return retval; + +- blk_start_plug(&plug); +- + /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ + if (filp->f_flags & O_DIRECT) { + loff_t size; +@@ -1424,8 +1421,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, + retval = filemap_write_and_wait_range(mapping, pos, + pos + iov_length(iov, nr_segs) - 1); + if (!retval) { ++ struct blk_plug plug; ++ ++ blk_start_plug(&plug); + retval = mapping->a_ops->direct_IO(READ, iocb, + iov, pos, nr_segs); ++ blk_finish_plug(&plug); + } + if (retval > 0) { + *ppos = pos + retval; +@@ -1481,7 +1482,6 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, + break; + } + out: +- blk_finish_plug(&plug); + return retval; + } + EXPORT_SYMBOL(generic_file_aio_read); diff --git a/block-stray-block-put-after-teardown.patch b/block-stray-block-put-after-teardown.patch deleted file mode 100644 index f4bf9c40c..000000000 --- a/block-stray-block-put-after-teardown.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- linux-2.6.39.noarch/block/elevator.c~ 2011-08-09 10:07:41.532774872 -0400 -+++ linux-2.6.39.noarch/block/elevator.c 2011-08-09 10:07:56.131724173 -0400 -@@ -815,7 +815,7 @@ void elv_completed_request(struct reques - */ - if (blk_account_rq(rq)) { - q->in_flight[rq_is_sync(rq)]--; -- if ((rq->cmd_flags & REQ_SORTED) && -+ if ((rq->cmd_flags & REQ_SORTED) && e->ops && - e->ops->elevator_completed_req_fn) - e->ops->elevator_completed_req_fn(q, rq); - } diff --git a/kernel.spec b/kernel.spec index ac2780fb0..84f278c71 100644 --- a/kernel.spec +++ b/kernel.spec @@ -743,7 +743,8 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch Patch12016: disable-i8042-check-on-apple-mac.patch -Patch12026: block-stray-block-put-after-teardown.patch +Patch12025: block-readahead-block-plug.patch + Patch12030: epoll-limit-paths.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch @@ -1449,7 +1450,7 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch epoll-limit-paths.patch -ApplyPatch block-stray-block-put-after-teardown.patch +ApplyPatch block-readahead-block-plug.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -2290,6 +2291,10 @@ fi # and build. %changelog +* Sun Feb 05 2012 Dave Jones +- Remove unnecessary block-stray-block-put-after-teardown.patch +- readahead: fix pipeline break caused by block plug + * Fri Feb 03 2012 Josh Boyer 3.2.3-2 - Drop patch that was NAKed upstream (rhbz 783211) From 5edcb3f1d26991119352a33729d0e837b2a9ef89 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 6 Feb 2012 11:30:40 -0500 Subject: [PATCH 265/487] ath9k: fix a WEP crypto related regression ath9k_hw: fix a RTS/CTS timeout regression --- ...-fix-a-WEP-crypto-related-regression.patch | 66 ++++++++++++++++ ..._hw-fix-a-RTS-CTS-timeout-regression.patch | 75 +++++++++++++++++++ kernel.spec | 8 ++ 3 files changed, 149 insertions(+) create mode 100644 ath9k-fix-a-WEP-crypto-related-regression.patch create mode 100644 ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch diff --git a/ath9k-fix-a-WEP-crypto-related-regression.patch b/ath9k-fix-a-WEP-crypto-related-regression.patch new file mode 100644 index 000000000..0ddbbe0f6 --- /dev/null +++ b/ath9k-fix-a-WEP-crypto-related-regression.patch @@ -0,0 +1,66 @@ +From nbd@nbd.name Sun Feb 5 15:15:47 2012 +Return-path: +Envelope-to: linville@tuxdriver.com +Delivery-date: Sun, 05 Feb 2012 15:15:47 -0500 +Received: from [2a01:4f8:131:30e2::2] (helo=nbd.name) + by smtp.tuxdriver.com with esmtps (TLSv1:AES256-SHA:256) + (Exim 4.63) + (envelope-from ) + id 1Ru8Um-0004mD-I2 + for linville@tuxdriver.com; Sun, 05 Feb 2012 15:15:47 -0500 +Received: by nf.local (Postfix, from userid 501) + id 12D0F5BDE1DC; Sun, 5 Feb 2012 21:15:18 +0100 (CET) +From: Felix Fietkau +To: linux-wireless@vger.kernel.org +Cc: linville@tuxdriver.com, + mcgrof@qca.qualcomm.com, + mohammed@qca.qualcomm.com +Subject: [PATCH 3.3 1/2] ath9k: fix a WEP crypto related regression +Date: Sun, 5 Feb 2012 21:15:17 +0100 +Message-Id: <1328472918-30012-1-git-send-email-nbd@openwrt.org> +X-Mailer: git-send-email 1.7.3.2 +X-Spam-Score: -1.1 (-) +X-Spam-Status: No +Status: RO +Content-Length: 1381 +Lines: 38 + +commit b4a82a0 "ath9k_hw: fix interpretation of the rx KeyMiss flag" +fixed the interpretation of the KeyMiss flag for keycache based lookups, +however WEP encryption uses a static index, so KeyMiss is always asserted +for it, even though frames are decrypted properly. +Fix this by clearing the ATH9K_RXERR_KEYMISS flag if no keycache based +lookup was performed. + +Signed-off-by: Felix Fietkau +Cc: stable@vger.kernel.org +Reported-by: Laurent Bonnans +Reported-by: Jurica Vukadin +--- + drivers/net/wireless/ath/ath9k/recv.c | 8 ++++++++ + 1 files changed, 8 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c +index 0e666fb..7e1a91a 100644 +--- a/drivers/net/wireless/ath/ath9k/recv.c ++++ b/drivers/net/wireless/ath/ath9k/recv.c +@@ -822,6 +822,14 @@ static bool ath9k_rx_accept(struct ath_common *common, + (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC | + ATH9K_RXERR_KEYMISS)); + ++ /* ++ * Key miss events are only relevant for pairwise keys where the ++ * descriptor does contain a valid key index. This has been observed ++ * mostly with CCMP encryption. ++ */ ++ if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID) ++ rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS; ++ + if (!rx_stats->rs_datalen) + return false; + /* +-- +1.7.3.2 + + + diff --git a/ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch b/ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch new file mode 100644 index 000000000..2ad65747e --- /dev/null +++ b/ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch @@ -0,0 +1,75 @@ +From nbd@nbd.name Sun Feb 5 15:15:46 2012 +Return-path: +Envelope-to: linville@tuxdriver.com +Delivery-date: Sun, 05 Feb 2012 15:15:46 -0500 +Received: from [2a01:4f8:131:30e2::2] (helo=nbd.name) + by smtp.tuxdriver.com with esmtps (TLSv1:AES256-SHA:256) + (Exim 4.63) + (envelope-from ) + id 1Ru8Um-0004mE-I0 + for linville@tuxdriver.com; Sun, 05 Feb 2012 15:15:44 -0500 +Received: by nf.local (Postfix, from userid 501) + id 1926D5BDE1DD; Sun, 5 Feb 2012 21:15:18 +0100 (CET) +From: Felix Fietkau +To: linux-wireless@vger.kernel.org +Cc: linville@tuxdriver.com, + mcgrof@qca.qualcomm.com, + mohammed@qca.qualcomm.com +Subject: [PATCH 3.3 2/2] ath9k_hw: fix a RTS/CTS timeout regression +Date: Sun, 5 Feb 2012 21:15:18 +0100 +Message-Id: <1328472918-30012-2-git-send-email-nbd@openwrt.org> +X-Mailer: git-send-email 1.7.3.2 +In-Reply-To: <1328472918-30012-1-git-send-email-nbd@openwrt.org> +References: <1328472918-30012-1-git-send-email-nbd@openwrt.org> +X-Spam-Score: -1.1 (-) +X-Spam-Status: No +Status: RO +Content-Length: 1749 +Lines: 45 + +commit adb5066 "ath9k_hw: do not apply the 2.4 ghz ack timeout +workaround to cts" reduced the hardware CTS timeout to the normal +values specified by the standard, but it turns out while it doesn't +need the same extra time that it needs for the ACK timeout, it +does need more than the value specified in the standard, but only +for 2.4 GHz. + +This patch brings the CTS timeout value in sync with the initialization +values, while still allowing adjustment for bigger distances. + +Signed-off-by: Felix Fietkau +Cc: stable@vger.kernel.org +Reported-by: Seth Forshee +Reported-by: Marek Lindner +--- + drivers/net/wireless/ath/ath9k/hw.c | 7 +++++-- + 1 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c +index ee77595..87db1ee 100644 +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -1037,13 +1037,16 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) + + /* + * Workaround for early ACK timeouts, add an offset to match the +- * initval's 64us ack timeout value. ++ * initval's 64us ack timeout value. Use 48us for the CTS timeout. + * This was initially only meant to work around an issue with delayed + * BA frames in some implementations, but it has been found to fix ACK + * timeout issues in other cases as well. + */ +- if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) ++ if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) { + acktimeout += 64 - sifstime - ah->slottime; ++ ctstimeout += 48 - sifstime - ah->slottime; ++ } ++ + + ath9k_hw_set_sifs_time(ah, sifstime); + ath9k_hw_setslottime(ah, slottime); +-- +1.7.3.2 + + + diff --git a/kernel.spec b/kernel.spec index 84f278c71..30d53bab2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -821,6 +821,8 @@ Patch50113: iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch Patch50114: mac80211-timeout-a-single-frame-in-the-rx-reorder-bu.patch Patch50200: ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch +Patch50201: ath9k-fix-a-WEP-crypto-related-regression.patch +Patch50202: ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch %endif @@ -1583,6 +1585,8 @@ ApplyPatch iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch ApplyPatch mac80211-timeout-a-single-frame-in-the-rx-reorder-bu.patch ApplyPatch ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch +ApplyPatch ath9k-fix-a-WEP-crypto-related-regression.patch +ApplyPatch ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch ApplyPatch rt2x00_fix_MCU_request_failures.patch @@ -2291,6 +2295,10 @@ fi # and build. %changelog +* Mon Feb 06 2012 John W. Linville +- ath9k: fix a WEP crypto related regression +- ath9k_hw: fix a RTS/CTS timeout regression + * Sun Feb 05 2012 Dave Jones - Remove unnecessary block-stray-block-put-after-teardown.patch - readahead: fix pipeline break caused by block plug From a19409b9ccac084e46cdc9a63761ce8283e91e81 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 6 Feb 2012 21:37:07 -0500 Subject: [PATCH 266/487] Linux 3.2.5 --- kernel.spec | 11 +- pci-Rework-ASPM-disable-code.patch | 287 ----------------------------- sources | 2 +- 3 files changed, 6 insertions(+), 294 deletions(-) delete mode 100644 pci-Rework-ASPM-disable-code.patch diff --git a/kernel.spec b/kernel.spec index 30d53bab2..2ae6543eb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 3 +%define stable_update 5 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -791,8 +791,6 @@ Patch22100: msi-irq-sysfs-warning.patch # rhbz 754907 Patch21101: hpsa-add-irqf-shared.patch -Patch21225: pci-Rework-ASPM-disable-code.patch - Patch21226: pci-crs-blacklist.patch #rhbz 772772 @@ -1469,8 +1467,6 @@ ApplyPatch sysfs-msi-irq-per-device.patch # rhbz 754907 ApplyPatch hpsa-add-irqf-shared.patch -ApplyPatch pci-Rework-ASPM-disable-code.patch - #ApplyPatch pci-crs-blacklist.patch #rhbz 717735 @@ -2295,6 +2291,9 @@ fi # and build. %changelog +* Mon Feb 06 2012 Josh Boyer +- Linux 3.2.5. Happy Birthday + * Mon Feb 06 2012 John W. Linville - ath9k: fix a WEP crypto related regression - ath9k_hw: fix a RTS/CTS timeout regression diff --git a/pci-Rework-ASPM-disable-code.patch b/pci-Rework-ASPM-disable-code.patch deleted file mode 100644 index d6fb24320..000000000 --- a/pci-Rework-ASPM-disable-code.patch +++ /dev/null @@ -1,287 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Matthew Garrett -Newsgroups: gmane.linux.acpi.devel,gmane.linux.kernel.pci,gmane.linux.kernel -Subject: [PATCH] pci: Rework ASPM disable code -Date: Thu, 10 Nov 2011 16:38:33 -0500 -Lines: 232 -Approved: news@gmane.org -Message-ID: <1320961113-5050-1-git-send-email-mjg@redhat.com> -NNTP-Posting-Host: lo.gmane.org -X-Trace: dough.gmane.org 1320961145 13112 80.91.229.12 (10 Nov 2011 21:39:05 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Thu, 10 Nov 2011 21:39:05 +0000 (UTC) -Cc: linux-pci@vger.kernel.org, linux-acpi@vger.kernel.org, - linux-kernel@vger.kernel.org, Matthew Garrett -To: jbarnes@virtuousgeek.org -Original-X-From: linux-acpi-owner@vger.kernel.org Thu Nov 10 22:38:57 2011 -Return-path: -Envelope-to: glad-acpi-devel@lo.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by lo.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1ROcKm-0003jN-CL - for glad-acpi-devel@lo.gmane.org; Thu, 10 Nov 2011 22:38:56 +0100 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1751342Ab1KJViu (ORCPT ); - Thu, 10 Nov 2011 16:38:50 -0500 -Original-Received: from mx1.redhat.com ([209.132.183.28]:32030 "EHLO mx1.redhat.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1750805Ab1KJVit (ORCPT ); - Thu, 10 Nov 2011 16:38:49 -0500 -Original-Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id pAALcmdw013333 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); - Thu, 10 Nov 2011 16:38:49 -0500 -Original-Received: from cavan.codon.org.uk (ovpn-113-157.phx2.redhat.com [10.3.113.157]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id pAALclkW022022 - (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NO); - Thu, 10 Nov 2011 16:38:48 -0500 -Original-Received: from 209-6-41-104.c3-0.smr-ubr1.sbo-smr.ma.cable.rcn.com ([209.6.41.104] helo=localhost.localdomain) - by cavan.codon.org.uk with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) - (Exim 4.72) - (envelope-from ) - id 1ROcKa-0000F4-E4; Thu, 10 Nov 2011 21:38:44 +0000 -X-SA-Do-Not-Run: Yes -X-SA-Exim-Connect-IP: 209.6.41.104 -X-SA-Exim-Mail-From: mjg@redhat.com -X-SA-Exim-Scanned: No (on cavan.codon.org.uk); SAEximRunCond expanded to false -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Original-Sender: linux-acpi-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-acpi@vger.kernel.org -Xref: news.gmane.org gmane.linux.acpi.devel:51182 gmane.linux.kernel.pci:12503 gmane.linux.kernel:1214427 -Archived-At: - -Right now we forcibly clear ASPM state on all devices if the BIOS indicates -that the feature isn't supported. Based on the Microsoft presentation -"PCI Express In Depth for Windows Vista and Beyond", I'm starting to think -that this may be an error. The implication is that unless the platform -grants full control via _OSC, Windows will not touch any PCIe features - -including ASPM. In that case clearing ASPM state would be an error unless -the platform has granted us that control. - -This patch reworks the ASPM disabling code such that the actual clearing -of state is triggered by a successful handoff of PCIe control to the OS. -The general ASPM code undergoes some changes in order to ensure that the -ability to clear the bits isn't overridden by ASPM having already been -disabled. Further, this theoretically now allows for situations where -only a subset of PCIe roots hand over control, leaving the others in the -BIOS state. - -It's difficult to know for sure that this is the right thing to do - -there's zero public documentation on the interaction between all of these -components. But enough vendors enable ASPM on platforms and then set this -bit that it seems likely that they're expecting the OS to leave them alone. - -Measured to save around 5W on an idle Thinkpad X220. - -Signed-off-by: Matthew Garrett ---- - drivers/acpi/pci_root.c | 7 +++++ - drivers/pci/pci-acpi.c | 1 - - drivers/pci/pcie/aspm.c | 58 +++++++++++++++++++++++++++++---------------- - include/linux/pci-aspm.h | 4 +- - 4 files changed, 46 insertions(+), 24 deletions(-) - -diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c -index 2672c79..7aff631 100644 ---- a/drivers/acpi/pci_root.c -+++ b/drivers/acpi/pci_root.c -@@ -596,6 +596,13 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) - if (ACPI_SUCCESS(status)) { - dev_info(root->bus->bridge, - "ACPI _OSC control (0x%02x) granted\n", flags); -+ if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { -+ /* -+ * We have ASPM control, but the FADT indicates -+ * that it's unsupported. Clear it. -+ */ -+ pcie_clear_aspm(root->bus); -+ } - } else { - dev_info(root->bus->bridge, - "ACPI _OSC request failed (%s), " -diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c -index 4ecb640..c8e7585 100644 ---- a/drivers/pci/pci-acpi.c -+++ b/drivers/pci/pci-acpi.c -@@ -395,7 +395,6 @@ static int __init acpi_pci_init(void) - - if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { - printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n"); -- pcie_clear_aspm(); - pcie_no_aspm(); - } - -diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c -index cbfbab1..1cfbf22 100644 ---- a/drivers/pci/pcie/aspm.c -+++ b/drivers/pci/pcie/aspm.c -@@ -68,7 +68,7 @@ struct pcie_link_state { - struct aspm_latency acceptable[8]; - }; - --static int aspm_disabled, aspm_force, aspm_clear_state; -+static int aspm_disabled, aspm_force; - static bool aspm_support_enabled = true; - static DEFINE_MUTEX(aspm_lock); - static LIST_HEAD(link_list); -@@ -500,9 +500,6 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) - int pos; - u32 reg32; - -- if (aspm_clear_state) -- return -EINVAL; -- - /* - * Some functions in a slot might not all be PCIe functions, - * very strange. Disable ASPM for the whole slot -@@ -574,9 +571,6 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) - pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) - return; - -- if (aspm_disabled && !aspm_clear_state) -- return; -- - /* VIA has a strange chipset, root port is under a bridge */ - if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT && - pdev->bus->self) -@@ -608,7 +602,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) - * the BIOS's expectation, we'll do so once pci_enable_device() is - * called. - */ -- if (aspm_policy != POLICY_POWERSAVE || aspm_clear_state) { -+ if (aspm_policy != POLICY_POWERSAVE) { - pcie_config_aspm_path(link); - pcie_set_clkpm(link, policy_to_clkpm_state(link)); - } -@@ -649,8 +643,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) - struct pci_dev *parent = pdev->bus->self; - struct pcie_link_state *link, *root, *parent_link; - -- if ((aspm_disabled && !aspm_clear_state) || !pci_is_pcie(pdev) || -- !parent || !parent->link_state) -+ if (!pci_is_pcie(pdev) || !parent || !parent->link_state) - return; - if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && - (parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) -@@ -734,13 +727,18 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev) - * pci_disable_link_state - disable pci device's link state, so the link will - * never enter specific states - */ --static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) -+static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem, -+ bool force) - { - struct pci_dev *parent = pdev->bus->self; - struct pcie_link_state *link; - -- if (aspm_disabled || !pci_is_pcie(pdev)) -+ if (aspm_disabled && !force) -+ return; -+ -+ if (!pci_is_pcie(pdev)) - return; -+ - if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT || - pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) - parent = pdev; -@@ -768,16 +766,31 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) - - void pci_disable_link_state_locked(struct pci_dev *pdev, int state) - { -- __pci_disable_link_state(pdev, state, false); -+ __pci_disable_link_state(pdev, state, false, false); - } - EXPORT_SYMBOL(pci_disable_link_state_locked); - - void pci_disable_link_state(struct pci_dev *pdev, int state) - { -- __pci_disable_link_state(pdev, state, true); -+ __pci_disable_link_state(pdev, state, true, false); - } - EXPORT_SYMBOL(pci_disable_link_state); - -+void pcie_clear_aspm(struct pci_bus *bus) -+{ -+ struct pci_dev *child; -+ -+ /* -+ * Clear any ASPM setup that the firmware has carried out on this bus -+ */ -+ list_for_each_entry(child, &bus->devices, bus_list) { -+ __pci_disable_link_state(child, PCIE_LINK_STATE_L0S | -+ PCIE_LINK_STATE_L1 | -+ PCIE_LINK_STATE_CLKPM, -+ false, true); -+ } -+} -+ - static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp) - { - int i; -@@ -935,6 +948,7 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) - static int __init pcie_aspm_disable(char *str) - { - if (!strcmp(str, "off")) { -+ aspm_policy = POLICY_DEFAULT; - aspm_disabled = 1; - aspm_support_enabled = false; - printk(KERN_INFO "PCIe ASPM is disabled\n"); -@@ -947,16 +961,18 @@ static int __init pcie_aspm_disable(char *str) - - __setup("pcie_aspm=", pcie_aspm_disable); - --void pcie_clear_aspm(void) --{ -- if (!aspm_force) -- aspm_clear_state = 1; --} -- - void pcie_no_aspm(void) - { -- if (!aspm_force) -+ /* -+ * Disabling ASPM is intended to prevent the kernel from modifying -+ * existing hardware state, not to clear existing state. To that end: -+ * (a) set policy to POLICY_DEFAULT in order to avoid changing state -+ * (b) prevent userspace from changing policy -+ */ -+ if (!aspm_force) { -+ aspm_policy = POLICY_DEFAULT; - aspm_disabled = 1; -+ } - } - - /** -diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h -index 7cea7b6..c832014 100644 ---- a/include/linux/pci-aspm.h -+++ b/include/linux/pci-aspm.h -@@ -29,7 +29,7 @@ extern void pcie_aspm_pm_state_change(struct pci_dev *pdev); - extern void pcie_aspm_powersave_config_link(struct pci_dev *pdev); - extern void pci_disable_link_state(struct pci_dev *pdev, int state); - extern void pci_disable_link_state_locked(struct pci_dev *pdev, int state); --extern void pcie_clear_aspm(void); -+extern void pcie_clear_aspm(struct pci_bus *bus); - extern void pcie_no_aspm(void); - #else - static inline void pcie_aspm_init_link_state(struct pci_dev *pdev) -@@ -47,7 +47,7 @@ static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev) - static inline void pci_disable_link_state(struct pci_dev *pdev, int state) - { - } --static inline void pcie_clear_aspm(void) -+static inline void pcie_clear_aspm(struct pci_bus *bus) - { - } - static inline void pcie_no_aspm(void) --- -1.7.7.1 - --- -To unsubscribe from this list: send the line "unsubscribe linux-acpi" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - diff --git a/sources b/sources index 0a6ecb347..06e37eb44 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz 8cfe037a7a7a356278ec3638e25ad506 compat-wireless-3.3-rc1-2.tar.bz2 -4ffcd30b95b4d2435be40405507319dd patch-3.2.3.xz +89cb9fb7ed01dccb15510435fb1e5024 patch-3.2.5.xz From 5c09f390685de94f48dc02fdb2595b22a172d511 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 7 Feb 2012 09:42:52 -0500 Subject: [PATCH 267/487] Turn maple support back on in ppc64 The powerstation is (sadly) a maple based platform. I like it when my machines boot... --- config-powerpc64 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config-powerpc64 b/config-powerpc64 index 42b501675..548bf468a 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -2,7 +2,7 @@ CONFIG_WINDFARM_PM81=y CONFIG_WINDFARM_PM91=y CONFIG_WINDFARM_PM121=y CONFIG_PPC_PMAC64=y -# CONFIG_PPC_MAPLE is not set +CONFIG_PPC_MAPLE=y # CONFIG_PPC_CELL is not set # CONFIG_PPC_IBM_CELL_BLADE is not set CONFIG_PPC_ISERIES=y @@ -38,6 +38,7 @@ CONFIG_ADB_PMU_LED=y CONFIG_ADB_PMU_LED_IDE=y CONFIG_PMAC_SMU=y CONFIG_CPU_FREQ_PMAC64=y +CONFIG_CPU_FREQ_MAPLE=y CONFIG_SCSI_IPR=m CONFIG_SCSI_IPR_TRACE=y CONFIG_SCSI_IPR_DUMP=y From 2165bab1eb7d05e38dd635ac5609c9fab4c580fa Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 7 Feb 2012 12:02:45 -0500 Subject: [PATCH 268/487] Make build/ point to /usr/src/kernels instead of being relative (rhbz 788125) --- kernel.spec | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 2ae6543eb..c80d13233 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -1813,7 +1813,12 @@ BuildKernel() { # Move the devel headers out of the root file system mkdir -p $RPM_BUILD_ROOT/usr/src/kernels mv $RPM_BUILD_ROOT/lib/modules/$KernelVer/build $RPM_BUILD_ROOT/$DevelDir - ln -sf ../../..$DevelDir $RPM_BUILD_ROOT/lib/modules/$KernelVer/build + + # This is going to create a broken link during the build, but we don't use + # it after this point. We need the link to actually point to something + # when kernel-devel is installed, and a relative link doesn't work across + # the F17 UsrMove feature. + ln -sf $DevelDir $RPM_BUILD_ROOT/lib/modules/$KernelVer/build # prune junk from kernel-devel find $RPM_BUILD_ROOT/usr/src/kernels -name ".*.cmd" -exec rm -f {} \; @@ -2291,6 +2296,9 @@ fi # and build. %changelog +* Tue Feb 07 2012 Josh Boyer +- Make build/ point to /usr/src/kernels instead of being relative (rhbz 788125) + * Mon Feb 06 2012 Josh Boyer - Linux 3.2.5. Happy Birthday From 7c061194a0a5348b25b5192f7796dd018b4828bb Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 8 Feb 2012 08:37:23 -0500 Subject: [PATCH 269/487] CVE-2011-4086 jbd2: unmapped buffer with _Unwritten or _Delay flags set can lead to DoS (rhbz 788260) --- ...nd-BH_Unwritten-in-journal_unmap_buf.patch | 91 +++++++++++++++++++ kernel.spec | 12 ++- 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch diff --git a/jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch b/jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch new file mode 100644 index 000000000..5ea8ccc10 --- /dev/null +++ b/jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch @@ -0,0 +1,91 @@ +Path: news.gmane.org!not-for-mail +From: Eric Sandeen +Newsgroups: gmane.comp.file-systems.ext4 +Subject: [PATCH] jbd2: clear BH_Delay & BH_Unwritten in journal_unmap_buffer +Date: Tue, 07 Feb 2012 16:07:20 -0600 +Lines: 42 +Approved: news@gmane.org +Message-ID: <4F31A098.4050601@redhat.com> +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 7bit +X-Trace: dough.gmane.org 1328656072 12026 80.91.229.3 (7 Feb 2012 23:07:52 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Tue, 7 Feb 2012 23:07:52 +0000 (UTC) +To: ext4 development +Original-X-From: linux-ext4-owner@vger.kernel.org Wed Feb 08 00:07:52 2012 +Return-path: +Envelope-to: gcfe-linux-ext4@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1Ruu8d-0000lK-5P + for gcfe-linux-ext4@plane.gmane.org; Wed, 08 Feb 2012 00:07:51 +0100 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1756187Ab2BGXHt (ORCPT ); + Tue, 7 Feb 2012 18:07:49 -0500 +Original-Received: from mx1.redhat.com ([209.132.183.28]:19432 "EHLO mx1.redhat.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1753992Ab2BGXHs (ORCPT ); + Tue, 7 Feb 2012 18:07:48 -0500 +Original-Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q17N7dj0027622 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) + for ; Tue, 7 Feb 2012 18:07:48 -0500 +Original-Received: from liberator.sandeen.net (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q17M7Kgt001990 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) + for ; Tue, 7 Feb 2012 17:07:21 -0500 +User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:10.0) Gecko/20120129 Thunderbird/10.0 +X-Enigmail-Version: 1.3.5 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +Original-Sender: linux-ext4-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-ext4@vger.kernel.org +Xref: news.gmane.org gmane.comp.file-systems.ext4:30623 +Archived-At: + +journal_unmap_buffer()'s zap_buffer: code clears a lot of buffer head +state ala discard_buffer(), but does not touch _Delay or _Unwritten +as discard_buffer() does. + +This can be problematic in some areas of the ext4 code which assume +that if they have found a buffer marked unwritten or delay, then it's +a live one. Perhaps those spots should check whether it is mapped +as well, but if jbd2 is going to tear down a buffer, let's really +tear it down completely. + +Without this I get some fsx failures on sub-page-block filesystems +up until v3.2, at which point 4e96b2dbbf1d7e81f22047a50f862555a6cb87cb +and 189e868fa8fdca702eb9db9d8afc46b5cb9144c9 make the failures go +away, because buried within that large change is some more flag +clearing. I still think it's worth doing in jbd2, since +->invalidatepage leads here directly, and it's the right place +to clear away these flags. + +Signed-off-by: Eric Sandeen +Cc: stable@vger.kernel.org +--- + +diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c +index 35ae096..52653306 100644 +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -1949,6 +1949,8 @@ zap_buffer_unlocked: + clear_buffer_mapped(bh); + clear_buffer_req(bh); + clear_buffer_new(bh); ++ clear_buffer_delay(bh); ++ clear_buffer_unwritten(bh); + bh->b_bdev = NULL; + return may_free; + } + + +-- +To unsubscribe from this list: send the line "unsubscribe linux-ext4" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + diff --git a/kernel.spec b/kernel.spec index c80d13233..3f7be4c4a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -796,6 +796,9 @@ Patch21226: pci-crs-blacklist.patch #rhbz 772772 Patch21232: rt2x00_fix_MCU_request_failures.patch +#rhbz 788260 +Patch21233: jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-pr_fmt-warning-avoidance.patch @@ -1497,6 +1500,9 @@ ApplyPatch proc-fix-null-pointer-deref-in-proc_pid_permission.patch #rhbz 772772 ApplyPatch rt2x00_fix_MCU_request_failures.patch +#rhbz 788269 +ApplyPatch jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch + # END OF PATCH APPLICATIONS %endif @@ -2296,6 +2302,10 @@ fi # and build. %changelog +* Wed Feb 08 2012 Josh Boyer +- CVE-2011-4086 jbd2: unmapped buffer with _Unwritten or _Delay flags set can + lead to DoS (rhbz 788260) + * Tue Feb 07 2012 Josh Boyer - Make build/ point to /usr/src/kernels instead of being relative (rhbz 788125) From 88335999c756ece76081ee73e94e2b2181e1f3df Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 8 Feb 2012 10:51:51 -0500 Subject: [PATCH 270/487] Fix e1000e Tx hang check (rhbz 785806) --- e1000e-Avoid-wrong-check-on-TX-hang.patch | 95 +++++++++++++++++++++++ kernel.spec | 7 ++ 2 files changed, 102 insertions(+) create mode 100644 e1000e-Avoid-wrong-check-on-TX-hang.patch diff --git a/e1000e-Avoid-wrong-check-on-TX-hang.patch b/e1000e-Avoid-wrong-check-on-TX-hang.patch new file mode 100644 index 000000000..6064ddde8 --- /dev/null +++ b/e1000e-Avoid-wrong-check-on-TX-hang.patch @@ -0,0 +1,95 @@ +From 09357b00255c233705b1cf6d76a8d147340545b8 Mon Sep 17 00:00:00 2001 +From: Jeff Kirsher +Date: Fri, 18 Nov 2011 14:25:00 +0000 +Subject: [PATCH] e1000e: Avoid wrong check on TX hang + +Based on the original patch submitted my Michael Wang +. +Descriptors may not be write-back while checking TX hang with flag +FLAG2_DMA_BURST on. +So when we detect hang, we just flush the descriptor and detect +again for once. + +-v2 change 1 to true and 0 to false and remove extra () + +CC: Michael Wang +CC: Flavio Leitner +Acked-by: Jesse Brandeburg +Tested-by: Aaron Brown +Signed-off-by: Jeff Kirsher +--- + drivers/net/ethernet/intel/e1000e/e1000.h | 1 + + drivers/net/ethernet/intel/e1000e/netdev.c | 23 ++++++++++++++++++++--- + 2 files changed, 21 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h +index 9fe18d1..f478a22 100644 +--- a/drivers/net/ethernet/intel/e1000e/e1000.h ++++ b/drivers/net/ethernet/intel/e1000e/e1000.h +@@ -309,6 +309,7 @@ struct e1000_adapter { + u32 txd_cmd; + + bool detect_tx_hung; ++ bool tx_hang_recheck; + u8 tx_timeout_factor; + + u32 tx_int_delay; +diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c +index c6e9763..c12df69 100644 +--- a/drivers/net/ethernet/intel/e1000e/netdev.c ++++ b/drivers/net/ethernet/intel/e1000e/netdev.c +@@ -1014,6 +1014,7 @@ static void e1000_print_hw_hang(struct work_struct *work) + struct e1000_adapter *adapter = container_of(work, + struct e1000_adapter, + print_hang_task); ++ struct net_device *netdev = adapter->netdev; + struct e1000_ring *tx_ring = adapter->tx_ring; + unsigned int i = tx_ring->next_to_clean; + unsigned int eop = tx_ring->buffer_info[i].next_to_watch; +@@ -1025,6 +1026,21 @@ static void e1000_print_hw_hang(struct work_struct *work) + if (test_bit(__E1000_DOWN, &adapter->state)) + return; + ++ if (!adapter->tx_hang_recheck && ++ (adapter->flags2 & FLAG2_DMA_BURST)) { ++ /* May be block on write-back, flush and detect again ++ * flush pending descriptor writebacks to memory ++ */ ++ ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); ++ /* execute the writes immediately */ ++ e1e_flush(); ++ adapter->tx_hang_recheck = true; ++ return; ++ } ++ /* Real hang detected */ ++ adapter->tx_hang_recheck = false; ++ netif_stop_queue(netdev); ++ + e1e_rphy(hw, PHY_STATUS, &phy_status); + e1e_rphy(hw, PHY_1000T_STATUS, &phy_1000t_status); + e1e_rphy(hw, PHY_EXT_STATUS, &phy_ext_status); +@@ -1145,10 +1161,10 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) + if (tx_ring->buffer_info[i].time_stamp && + time_after(jiffies, tx_ring->buffer_info[i].time_stamp + + (adapter->tx_timeout_factor * HZ)) && +- !(er32(STATUS) & E1000_STATUS_TXOFF)) { ++ !(er32(STATUS) & E1000_STATUS_TXOFF)) + schedule_work(&adapter->print_hang_task); +- netif_stop_queue(netdev); +- } ++ else ++ adapter->tx_hang_recheck = false; + } + adapter->total_tx_bytes += total_tx_bytes; + adapter->total_tx_packets += total_tx_packets; +@@ -3838,6 +3854,7 @@ static int e1000_open(struct net_device *netdev) + + e1000_irq_enable(adapter); + ++ adapter->tx_hang_recheck = false; + netif_start_queue(netdev); + + adapter->idle_check = true; +-- +1.7.9 + diff --git a/kernel.spec b/kernel.spec index 3f7be4c4a..041c1b4c3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -799,6 +799,9 @@ Patch21232: rt2x00_fix_MCU_request_failures.patch #rhbz 788260 Patch21233: jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch +#rhbz 785806 +Patch21234: e1000e-Avoid-wrong-check-on-TX-hang.patch + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-pr_fmt-warning-avoidance.patch @@ -1503,6 +1506,9 @@ ApplyPatch rt2x00_fix_MCU_request_failures.patch #rhbz 788269 ApplyPatch jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch +#rhbz 785806 +ApplyPatch e1000e-Avoid-wrong-check-on-TX-hang.patch + # END OF PATCH APPLICATIONS %endif @@ -2303,6 +2309,7 @@ fi %changelog * Wed Feb 08 2012 Josh Boyer +- Fix e1000e Tx hang check (rhbz 785806) - CVE-2011-4086 jbd2: unmapped buffer with _Unwritten or _Delay flags set can lead to DoS (rhbz 788260) From e16649a5ae70c3fb25628aa542185f6ecccb7623 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 9 Feb 2012 15:42:58 -0500 Subject: [PATCH 271/487] bsg: fix sysfs link remove warning (#787862) --- bsg-fix-sysfs-link-remove-warning.patch | 16 ++++++++++++++++ kernel.spec | 7 +++++++ 2 files changed, 23 insertions(+) create mode 100644 bsg-fix-sysfs-link-remove-warning.patch diff --git a/bsg-fix-sysfs-link-remove-warning.patch b/bsg-fix-sysfs-link-remove-warning.patch new file mode 100644 index 000000000..6e7625327 --- /dev/null +++ b/bsg-fix-sysfs-link-remove-warning.patch @@ -0,0 +1,16 @@ +diff --git a/block/bsg.c b/block/bsg.c +index 4cf703f..ff64ae3 100644 +--- a/block/bsg.c ++++ b/block/bsg.c +@@ -983,7 +983,8 @@ void bsg_unregister_queue(struct request_queue *q) + + mutex_lock(&bsg_mutex); + idr_remove(&bsg_minor_idr, bcd->minor); +- sysfs_remove_link(&q->kobj, "bsg"); ++ if (q->kobj.sd) ++ sysfs_remove_link(&q->kobj, "bsg"); + device_unregister(bcd->class_dev); + bcd->class_dev = NULL; + kref_put(&bcd->ref, bsg_kref_release_function); +-- +1.7.4.4 diff --git a/kernel.spec b/kernel.spec index 041c1b4c3..1ba1d9111 100644 --- a/kernel.spec +++ b/kernel.spec @@ -745,6 +745,8 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12025: block-readahead-block-plug.patch +Patch12026: bsg-fix-sysfs-link-remove-warning.patch + Patch12030: epoll-limit-paths.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch @@ -1458,6 +1460,8 @@ ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch epoll-limit-paths.patch ApplyPatch block-readahead-block-plug.patch +ApplyPatch bsg-fix-sysfs-link-remove-warning.patch + # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -2308,6 +2312,9 @@ fi # and build. %changelog +* Thu Feb 09 2012 Dave Jones +- bsg: fix sysfs link remove warning (#787862) + * Wed Feb 08 2012 Josh Boyer - Fix e1000e Tx hang check (rhbz 785806) - CVE-2011-4086 jbd2: unmapped buffer with _Unwritten or _Delay flags set can From 59b9e679903b5db423a6f8a65f9ad36216e1ee6b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 10 Feb 2012 14:56:13 -0500 Subject: [PATCH 272/487] Patch to prevent NULL pointer dereference in sd_revalidate_disk (rhbz 754518) --- kernel.spec | 10 ++++++++- ...validate_disk-prevent-NULL-ptr-deref.patch | 22 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch diff --git a/kernel.spec b/kernel.spec index 1ba1d9111..662e512c9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -804,11 +804,13 @@ Patch21233: jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch #rhbz 785806 Patch21234: e1000e-Avoid-wrong-check-on-TX-hang.patch +#rhbz 754518 +Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-pr_fmt-warning-avoidance.patch Patch50002: compat-wireless-integrated-build.patch - Patch50100: compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch # Pending upstream fixes @@ -1513,6 +1515,9 @@ ApplyPatch jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch #rhbz 785806 ApplyPatch e1000e-Avoid-wrong-check-on-TX-hang.patch +#rhbz 754518 +ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch + # END OF PATCH APPLICATIONS %endif @@ -2312,6 +2317,9 @@ fi # and build. %changelog +* Fri Feb 10 2012 Josh Boyer +- Patch to prevent NULL pointer dereference in sd_revalidate_disk (rhbz 754518) + * Thu Feb 09 2012 Dave Jones - bsg: fix sysfs link remove warning (#787862) diff --git a/scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch b/scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch new file mode 100644 index 000000000..492376d78 --- /dev/null +++ b/scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -0,0 +1,22 @@ +--- a/drivers/scsi/sd.c ++++ a/drivers/scsi/sd.c +@@ -2362,13 +2362,18 @@ static int sd_try_extended_inquiry(struct scsi_device *sdp) + static int sd_revalidate_disk(struct gendisk *disk) + { + struct scsi_disk *sdkp = scsi_disk(disk); +- struct scsi_device *sdp = sdkp->device; ++ struct scsi_device *sdp; + unsigned char *buffer; + unsigned flush = 0; + + SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, + "sd_revalidate_disk\n")); + ++ if (!sdkp) ++ goto out; ++ ++ sdp = sdkp->device; ++ + /* + * If the device is offline, don't try and read capacity or any + * of the other niceties. From bbd9ebeceeb500488b084df22ab62acc2ee4e90b Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 13 Feb 2012 11:20:54 -0500 Subject: [PATCH 273/487] mwifiex: handle association failure case correctly ath9k: Fix kernel panic during driver initilization mwifiex: add NULL checks in driver unload path bcma: don't fail for bad SPROM CRC zd1211rw: firmware needs duration_id set to zero for non-pspoll frames mac80211: Fix a rwlock bad magic bug rtlwifi: Modify rtl_pci_init to return 0 on success --- ...el-panic-during-driver-initilization.patch | 94 +++++++++++++++++++ ...-fix-a-WEP-crypto-related-regression.patch | 33 +------ ..._hw-fix-a-RTS-CTS-timeout-regression.patch | 35 +------ bcma-don-t-fail-for-bad-SPROM-CRC.patch | 36 +++++++ kernel.spec | 31 +++++- mac80211-Fix-a-rwlock-bad-magic-bug.patch | 89 ++++++++++++++++++ ...dd-NULL-checks-in-driver-unload-path.patch | 66 +++++++++++++ ...e-association-failure-case-correctly.patch | 67 +++++++++++++ ...-rtl_pci_init-to-return-0-on-success.patch | 40 ++++++++ ...e-needs-duration_id-set-to-zero-for-.patch | 51 ++++++++++ 10 files changed, 479 insertions(+), 63 deletions(-) create mode 100644 ath9k-Fix-kernel-panic-during-driver-initilization.patch create mode 100644 bcma-don-t-fail-for-bad-SPROM-CRC.patch create mode 100644 mac80211-Fix-a-rwlock-bad-magic-bug.patch create mode 100644 mwifiex-add-NULL-checks-in-driver-unload-path.patch create mode 100644 mwifiex-handle-association-failure-case-correctly.patch create mode 100644 rtlwifi-Modify-rtl_pci_init-to-return-0-on-success.patch create mode 100644 zd1211rw-firmware-needs-duration_id-set-to-zero-for-.patch diff --git a/ath9k-Fix-kernel-panic-during-driver-initilization.patch b/ath9k-Fix-kernel-panic-during-driver-initilization.patch new file mode 100644 index 000000000..385f39cd9 --- /dev/null +++ b/ath9k-Fix-kernel-panic-during-driver-initilization.patch @@ -0,0 +1,94 @@ +From 07445f688218a48bde72316aed9de4fdcc173131 Mon Sep 17 00:00:00 2001 +From: Mohammed Shafi Shajakhan +Date: Thu, 2 Feb 2012 16:29:05 +0530 +Subject: [PATCH] ath9k: Fix kernel panic during driver initilization + +all works need to be initialized before ieee80211_register_hw +to prevent mac80211 call backs such as drv_start, drv_config +getting started. otherwise we would queue/cancel works before +initializing them and it leads to kernel panic. +this issue can be recreated with the following script +in Chrome laptops with AR928X cards, with background scan +running (or) Network manager is running + +while true +do +sudo modprobe -v ath9k +sleep 3 +sudo modprobe -r ath9k +sleep 3 +done + + EIP: [<81040a47>] __cancel_work_timer+0xb8/0xe1 SS:ESP 0068:f6be9d70 + ---[ end trace 4f86d6139a9900ef ]--- + Registered led device: ath9k-phy0 + ieee80211 phy0: Atheros AR9280 Rev:2 mem=0xf88a0000, + irq=16 + Kernel panic - not syncing: Fatal exception + Pid: 456, comm: wpa_supplicant Tainted: G D + 3.0.13 #1 + Call Trace: + [<81379e21>] panic+0x53/0x14a + [<81004a30>] oops_end+0x73/0x81 + [<81004b53>] die+0x4c/0x55 + [<81002710>] do_trap+0x7c/0x83 + [<81002855>] ? do_bounds+0x58/0x58 + [<810028cc>] do_invalid_op+0x77/0x81 + [<81040a47>] ? __cancel_work_timer+0xb8/0xe1 + [<810489ec>] ? sched_clock_cpu+0x81/0x11f + [<8103f809>] ? wait_on_work+0xe2/0xf7 + [<8137f807>] error_code+0x67/0x6c + [<810300d8>] ? wait_consider_task+0x4ba/0x84c + [<81040a47>] ? __cancel_work_timer+0xb8/0xe1 + [<810380c9>] ? try_to_del_timer_sync+0x5f/0x67 + [<81040a91>] cancel_work_sync+0xf/0x11 + [] ath_set_channel+0x62/0x25c [ath9k] + [] ? ath9k_tx_last_beacon+0x26a/0x85c [ath9k] + [] ath_radio_disable+0x3f1/0x68e [ath9k] + [] ieee80211_hw_config+0x111/0x116 [mac80211] + [] __ieee80211_recalc_idle+0x919/0xa37 [mac80211] + [] __ieee80211_recalc_idle+0xa33/0xa37 [mac80211] + [<812dbed8>] __dev_open+0x82/0xab + +Cc: +Cc: Gary Morain +Cc: Paul Stewart +Cc: Vasanthakumar Thiagarajan +Tested-by: Mohammed Shafi Shajakhan +Signed-off-by: Rajkumar Manoharan +Signed-off-by: Mohammed Shafi Shajakhan +Signed-off-by: John W. Linville +--- + drivers/net/wireless/ath/ath9k/init.c | 9 +++++---- + 1 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c +index abf9435..53a005d 100644 +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -822,6 +822,11 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, + ARRAY_SIZE(ath9k_tpt_blink)); + #endif + ++ INIT_WORK(&sc->hw_reset_work, ath_reset_work); ++ INIT_WORK(&sc->hw_check_work, ath_hw_check); ++ INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); ++ INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); ++ + /* Register with mac80211 */ + error = ieee80211_register_hw(hw); + if (error) +@@ -840,10 +845,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, + goto error_world; + } + +- INIT_WORK(&sc->hw_reset_work, ath_reset_work); +- INIT_WORK(&sc->hw_check_work, ath_hw_check); +- INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); +- INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); + sc->last_rssi = ATH_RSSI_DUMMY_MARKER; + + ath_init_leds(sc); +-- +1.7.4.4 + diff --git a/ath9k-fix-a-WEP-crypto-related-regression.patch b/ath9k-fix-a-WEP-crypto-related-regression.patch index 0ddbbe0f6..54f603980 100644 --- a/ath9k-fix-a-WEP-crypto-related-regression.patch +++ b/ath9k-fix-a-WEP-crypto-related-regression.patch @@ -1,29 +1,7 @@ -From nbd@nbd.name Sun Feb 5 15:15:47 2012 -Return-path: -Envelope-to: linville@tuxdriver.com -Delivery-date: Sun, 05 Feb 2012 15:15:47 -0500 -Received: from [2a01:4f8:131:30e2::2] (helo=nbd.name) - by smtp.tuxdriver.com with esmtps (TLSv1:AES256-SHA:256) - (Exim 4.63) - (envelope-from ) - id 1Ru8Um-0004mD-I2 - for linville@tuxdriver.com; Sun, 05 Feb 2012 15:15:47 -0500 -Received: by nf.local (Postfix, from userid 501) - id 12D0F5BDE1DC; Sun, 5 Feb 2012 21:15:18 +0100 (CET) +From f88373fa47f3ce6590fdfaa742d0ddacc2ae017f Mon Sep 17 00:00:00 2001 From: Felix Fietkau -To: linux-wireless@vger.kernel.org -Cc: linville@tuxdriver.com, - mcgrof@qca.qualcomm.com, - mohammed@qca.qualcomm.com -Subject: [PATCH 3.3 1/2] ath9k: fix a WEP crypto related regression -Date: Sun, 5 Feb 2012 21:15:17 +0100 -Message-Id: <1328472918-30012-1-git-send-email-nbd@openwrt.org> -X-Mailer: git-send-email 1.7.3.2 -X-Spam-Score: -1.1 (-) -X-Spam-Status: No -Status: RO -Content-Length: 1381 -Lines: 38 +Date: Sun, 5 Feb 2012 21:15:17 +0100 +Subject: [PATCH] ath9k: fix a WEP crypto related regression commit b4a82a0 "ath9k_hw: fix interpretation of the rx KeyMiss flag" fixed the interpretation of the KeyMiss flag for keycache based lookups, @@ -36,6 +14,7 @@ Signed-off-by: Felix Fietkau Cc: stable@vger.kernel.org Reported-by: Laurent Bonnans Reported-by: Jurica Vukadin +Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/recv.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) @@ -60,7 +39,5 @@ index 0e666fb..7e1a91a 100644 return false; /* -- -1.7.3.2 - - +1.7.4.4 diff --git a/ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch b/ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch index 2ad65747e..8aa5b2fc1 100644 --- a/ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch +++ b/ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch @@ -1,31 +1,7 @@ -From nbd@nbd.name Sun Feb 5 15:15:46 2012 -Return-path: -Envelope-to: linville@tuxdriver.com -Delivery-date: Sun, 05 Feb 2012 15:15:46 -0500 -Received: from [2a01:4f8:131:30e2::2] (helo=nbd.name) - by smtp.tuxdriver.com with esmtps (TLSv1:AES256-SHA:256) - (Exim 4.63) - (envelope-from ) - id 1Ru8Um-0004mE-I0 - for linville@tuxdriver.com; Sun, 05 Feb 2012 15:15:44 -0500 -Received: by nf.local (Postfix, from userid 501) - id 1926D5BDE1DD; Sun, 5 Feb 2012 21:15:18 +0100 (CET) +From 55a2bb4a6d5e8c7b324d003e130fd9aaf33be4e6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau -To: linux-wireless@vger.kernel.org -Cc: linville@tuxdriver.com, - mcgrof@qca.qualcomm.com, - mohammed@qca.qualcomm.com -Subject: [PATCH 3.3 2/2] ath9k_hw: fix a RTS/CTS timeout regression -Date: Sun, 5 Feb 2012 21:15:18 +0100 -Message-Id: <1328472918-30012-2-git-send-email-nbd@openwrt.org> -X-Mailer: git-send-email 1.7.3.2 -In-Reply-To: <1328472918-30012-1-git-send-email-nbd@openwrt.org> -References: <1328472918-30012-1-git-send-email-nbd@openwrt.org> -X-Spam-Score: -1.1 (-) -X-Spam-Status: No -Status: RO -Content-Length: 1749 -Lines: 45 +Date: Sun, 5 Feb 2012 21:15:18 +0100 +Subject: [PATCH] ath9k_hw: fix a RTS/CTS timeout regression commit adb5066 "ath9k_hw: do not apply the 2.4 ghz ack timeout workaround to cts" reduced the hardware CTS timeout to the normal @@ -41,6 +17,7 @@ Signed-off-by: Felix Fietkau Cc: stable@vger.kernel.org Reported-by: Seth Forshee Reported-by: Marek Lindner +Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-) @@ -69,7 +46,5 @@ index ee77595..87db1ee 100644 ath9k_hw_set_sifs_time(ah, sifstime); ath9k_hw_setslottime(ah, slottime); -- -1.7.3.2 - - +1.7.4.4 diff --git a/bcma-don-t-fail-for-bad-SPROM-CRC.patch b/bcma-don-t-fail-for-bad-SPROM-CRC.patch new file mode 100644 index 000000000..6769c2b34 --- /dev/null +++ b/bcma-don-t-fail-for-bad-SPROM-CRC.patch @@ -0,0 +1,36 @@ +From 2e6b411971de727a5bcea4323331fdaa70a81b11 Mon Sep 17 00:00:00 2001 +From: Henrik Rydberg +Date: Tue, 31 Jan 2012 14:22:15 -0500 +Subject: [PATCH] bcma: don't fail for bad SPROM CRC + +The brcmsmac driver is now using the bcma SPROM CRC check, which does +not recognize all chipsets that were functional prior to the switch. In +particular, the current code bails out on odd CRC errors in recent +Macbooks. This patch ignores those errors, with the argument that an +unrecognized SPROM should be treated similarly to a non-existing one. + +Signed-off-by: Henrik Rydberg +Signed-off-by: John W. Linville +--- + drivers/bcma/main.c | 4 +--- + 1 files changed, 1 insertions(+), 3 deletions(-) + +diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c +index febbc0a..ec31f7d 100644 +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -169,10 +169,8 @@ int bcma_bus_register(struct bcma_bus *bus) + err = bcma_sprom_get(bus); + if (err == -ENOENT) { + pr_err("No SPROM available\n"); +- } else if (err) { ++ } else if (err) + pr_err("Failed to get SPROM: %d\n", err); +- return -ENOENT; +- } + + /* Register found cores */ + bcma_register_cores(bus); +-- +1.7.4.4 + diff --git a/kernel.spec b/kernel.spec index 662e512c9..8e9ca0a09 100644 --- a/kernel.spec +++ b/kernel.spec @@ -827,10 +827,16 @@ Patch50111: iwlwifi-make-Tx-aggregation-enabled-on-ra-be-at-DEBU.patch Patch50112: ssb-fix-cardbus-slot-in-hostmode.patch Patch50113: iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch Patch50114: mac80211-timeout-a-single-frame-in-the-rx-reorder-bu.patch - -Patch50200: ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch -Patch50201: ath9k-fix-a-WEP-crypto-related-regression.patch -Patch50202: ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch +Patch50115: ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch +Patch50116: mwifiex-handle-association-failure-case-correctly.patch +Patch50117: ath9k-Fix-kernel-panic-during-driver-initilization.patch +Patch50118: mwifiex-add-NULL-checks-in-driver-unload-path.patch +Patch50119: ath9k-fix-a-WEP-crypto-related-regression.patch +Patch50120: ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch +Patch50121: bcma-don-t-fail-for-bad-SPROM-CRC.patch +Patch50122: zd1211rw-firmware-needs-duration_id-set-to-zero-for-.patch +Patch50123: mac80211-Fix-a-rwlock-bad-magic-bug.patch +Patch50124: rtlwifi-Modify-rtl_pci_init-to-return-0-on-success.patch %endif @@ -1600,10 +1606,16 @@ ApplyPatch iwlwifi-make-Tx-aggregation-enabled-on-ra-be-at-DEBU.patch ApplyPatch ssb-fix-cardbus-slot-in-hostmode.patch ApplyPatch iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch ApplyPatch mac80211-timeout-a-single-frame-in-the-rx-reorder-bu.patch - ApplyPatch ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch +ApplyPatch mwifiex-handle-association-failure-case-correctly.patch +ApplyPatch ath9k-Fix-kernel-panic-during-driver-initilization.patch +ApplyPatch mwifiex-add-NULL-checks-in-driver-unload-path.patch ApplyPatch ath9k-fix-a-WEP-crypto-related-regression.patch ApplyPatch ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch +ApplyPatch bcma-don-t-fail-for-bad-SPROM-CRC.patch +ApplyPatch zd1211rw-firmware-needs-duration_id-set-to-zero-for-.patch +ApplyPatch mac80211-Fix-a-rwlock-bad-magic-bug.patch +ApplyPatch rtlwifi-Modify-rtl_pci_init-to-return-0-on-success.patch ApplyPatch rt2x00_fix_MCU_request_failures.patch @@ -2317,6 +2329,15 @@ fi # and build. %changelog +* Mon Feb 13 2012 John W. Linville +- mwifiex: handle association failure case correctly +- ath9k: Fix kernel panic during driver initilization +- mwifiex: add NULL checks in driver unload path +- bcma: don't fail for bad SPROM CRC +- zd1211rw: firmware needs duration_id set to zero for non-pspoll frames +- mac80211: Fix a rwlock bad magic bug +- rtlwifi: Modify rtl_pci_init to return 0 on success + * Fri Feb 10 2012 Josh Boyer - Patch to prevent NULL pointer dereference in sd_revalidate_disk (rhbz 754518) diff --git a/mac80211-Fix-a-rwlock-bad-magic-bug.patch b/mac80211-Fix-a-rwlock-bad-magic-bug.patch new file mode 100644 index 000000000..822b0dd54 --- /dev/null +++ b/mac80211-Fix-a-rwlock-bad-magic-bug.patch @@ -0,0 +1,89 @@ +From b57e6b560fc2a2742910ac5ca0eb2c46e45aeac2 Mon Sep 17 00:00:00 2001 +From: Mohammed Shafi Shajakhan +Date: Thu, 9 Feb 2012 19:59:43 +0530 +Subject: [PATCH] mac80211: Fix a rwlock bad magic bug + +read_lock(&tpt_trig->trig.leddev_list_lock) is accessed via the path +ieee80211_open (->) ieee80211_do_open (->) ieee80211_mod_tpt_led_trig +(->) ieee80211_start_tpt_led_trig (->) tpt_trig_timer before initializing +it. +the intilization of this read/write lock happens via the path +ieee80211_led_init (->) led_trigger_register, but we are doing +'ieee80211_led_init' after 'ieeee80211_if_add' where we +register netdev_ops. +so we access leddev_list_lock before initializing it and causes the +following bug in chrome laptops with AR928X cards with the following +script + +while true +do +sudo modprobe -v ath9k +sleep 3 +sudo modprobe -r ath9k +sleep 3 +done + + BUG: rwlock bad magic on CPU#1, wpa_supplicant/358, f5b9eccc + Pid: 358, comm: wpa_supplicant Not tainted 3.0.13 #1 + Call Trace: + + [<8137b9df>] rwlock_bug+0x3d/0x47 + [<81179830>] do_raw_read_lock+0x19/0x29 + [<8137f063>] _raw_read_lock+0xd/0xf + [] tpt_trig_timer+0xc3/0x145 [mac80211] + [] ieee80211_mod_tpt_led_trig+0x152/0x174 [mac80211] + [] ieee80211_do_open+0x11e/0x42e [mac80211] + [] ? ieee80211_check_concurrent_iface+0x26/0x13c [mac80211] + [] ieee80211_open+0x48/0x4c [mac80211] + [<812dbed8>] __dev_open+0x82/0xab + [<812dc0c9>] __dev_change_flags+0x9c/0x113 + [<812dc1ae>] dev_change_flags+0x18/0x44 + [<8132144f>] devinet_ioctl+0x243/0x51a + [<81321ba9>] inet_ioctl+0x93/0xac + [<812cc951>] sock_ioctl+0x1c6/0x1ea + [<812cc78b>] ? might_fault+0x20/0x20 + [<810b1ebb>] do_vfs_ioctl+0x46e/0x4a2 + [<810a6ebb>] ? fget_light+0x2f/0x70 + [<812ce549>] ? sys_recvmsg+0x3e/0x48 + [<810b1f35>] sys_ioctl+0x46/0x69 + [<8137fa77>] sysenter_do_call+0x12/0x2 + +Cc: +Cc: Gary Morain +Cc: Paul Stewart +Cc: Abhijit Pradhan +Cc: Vasanthakumar Thiagarajan +Cc: Rajkumar Manoharan +Acked-by: Johannes Berg +Tested-by: Mohammed Shafi Shajakhan +Signed-off-by: Mohammed Shafi Shajakhan +Signed-off-by: John W. Linville +--- + net/mac80211/main.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/main.c b/net/mac80211/main.c +index 0a0d94a..b142bd4 100644 +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -910,6 +910,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) + wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n", + result); + ++ ieee80211_led_init(local); ++ + rtnl_lock(); + + result = ieee80211_init_rate_ctrl_alg(local, +@@ -931,8 +933,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) + + rtnl_unlock(); + +- ieee80211_led_init(local); +- + local->network_latency_notifier.notifier_call = + ieee80211_max_network_latency; + result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, +-- +1.7.4.4 + diff --git a/mwifiex-add-NULL-checks-in-driver-unload-path.patch b/mwifiex-add-NULL-checks-in-driver-unload-path.patch new file mode 100644 index 000000000..0b7be1fb7 --- /dev/null +++ b/mwifiex-add-NULL-checks-in-driver-unload-path.patch @@ -0,0 +1,66 @@ +From 2da8cbf8a6b454296c9db7b57cac72d5a39e3aa7 Mon Sep 17 00:00:00 2001 +From: Amitkumar Karwar +Date: Fri, 3 Feb 2012 20:34:02 -0800 +Subject: [PATCH] mwifiex: add NULL checks in driver unload path + +If driver load is failed, sometimes few pointers may remain +uninitialized ex. priv->wdev, priv->netdev, adapter->sleep_cfm +This will cause NULL pointer dereferance while unloading the +driver. + +Signed-off-by: Amitkumar Karwar +Signed-off-by: Kiran Divekar +Signed-off-by: Bing Zhao +Signed-off-by: John W. Linville +--- + drivers/net/wireless/mwifiex/init.c | 3 ++- + drivers/net/wireless/mwifiex/main.c | 12 ++++++++---- + 2 files changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c +index e05b417..1d0ec57 100644 +--- a/drivers/net/wireless/mwifiex/init.c ++++ b/drivers/net/wireless/mwifiex/init.c +@@ -382,7 +382,8 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter) + + adapter->if_ops.cleanup_if(adapter); + +- dev_kfree_skb_any(adapter->sleep_cfm); ++ if (adapter->sleep_cfm) ++ dev_kfree_skb_any(adapter->sleep_cfm); + } + + /* +diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c +index 84be196..b728f54 100644 +--- a/drivers/net/wireless/mwifiex/main.c ++++ b/drivers/net/wireless/mwifiex/main.c +@@ -822,7 +822,9 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) + continue; + + rtnl_lock(); +- mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev); ++ if (priv->wdev && priv->netdev) ++ mwifiex_del_virtual_intf(priv->wdev->wiphy, ++ priv->netdev); + rtnl_unlock(); + } + +@@ -830,9 +832,11 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) + if (!priv) + goto exit_remove; + +- wiphy_unregister(priv->wdev->wiphy); +- wiphy_free(priv->wdev->wiphy); +- kfree(priv->wdev); ++ if (priv->wdev) { ++ wiphy_unregister(priv->wdev->wiphy); ++ wiphy_free(priv->wdev->wiphy); ++ kfree(priv->wdev); ++ } + + mwifiex_terminate_workqueue(adapter); + +-- +1.7.4.4 + diff --git a/mwifiex-handle-association-failure-case-correctly.patch b/mwifiex-handle-association-failure-case-correctly.patch new file mode 100644 index 000000000..48c757083 --- /dev/null +++ b/mwifiex-handle-association-failure-case-correctly.patch @@ -0,0 +1,67 @@ +From b7097eb75fa11c302dcdec83f1dbfa874e0af0d1 Mon Sep 17 00:00:00 2001 +From: Amitkumar Karwar +Date: Wed, 1 Feb 2012 20:41:43 -0800 +Subject: [PATCH] mwifiex: handle association failure case correctly + +Currently even if association is failed "iw link" shows some +information about connected BSS and "Tx timeout" error is seen in +dmesg log. + +This patch fixes below issues in the code to handle assoc failure +case correctly. +1) "status" variable in mwifiex_wait_queue_complete() is not +correctly updated. Hence driver doesn't inform cfg80211 stack +about association failure. +2) During association network queues are stopped but carrier is +not cleared, which gives Tx timeout error in failure case + +Signed-off-by: Amitkumar Karwar +Signed-off-by: Bing Zhao +Signed-off-by: John W. Linville +--- + drivers/net/wireless/mwifiex/sta_ioctl.c | 8 +++++++- + 1 files changed, 7 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c +index 470ca75..b0fbf5d 100644 +--- a/drivers/net/wireless/mwifiex/sta_ioctl.c ++++ b/drivers/net/wireless/mwifiex/sta_ioctl.c +@@ -54,7 +54,7 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, + int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) + { + bool cancel_flag = false; +- int status = adapter->cmd_wait_q.status; ++ int status; + struct cmd_ctrl_node *cmd_queued; + + if (!adapter->cmd_queued) +@@ -79,6 +79,8 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) + mwifiex_cancel_pending_ioctl(adapter); + dev_dbg(adapter->dev, "cmd cancel\n"); + } ++ ++ status = adapter->cmd_wait_q.status; + adapter->cmd_wait_q.status = 0; + + return status; +@@ -240,6 +242,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, + + if (!netif_queue_stopped(priv->netdev)) + mwifiex_stop_net_dev_queue(priv->netdev, adapter); ++ if (netif_carrier_ok(priv->netdev)) ++ netif_carrier_off(priv->netdev); + + /* Clear any past association response stored for + * application retrieval */ +@@ -271,6 +275,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, + + if (!netif_queue_stopped(priv->netdev)) + mwifiex_stop_net_dev_queue(priv->netdev, adapter); ++ if (netif_carrier_ok(priv->netdev)) ++ netif_carrier_off(priv->netdev); + + if (!ret) { + dev_dbg(adapter->dev, "info: network found in scan" +-- +1.7.4.4 + diff --git a/rtlwifi-Modify-rtl_pci_init-to-return-0-on-success.patch b/rtlwifi-Modify-rtl_pci_init-to-return-0-on-success.patch new file mode 100644 index 000000000..849c449c4 --- /dev/null +++ b/rtlwifi-Modify-rtl_pci_init-to-return-0-on-success.patch @@ -0,0 +1,40 @@ +From c27111e5b8d6b1e9296f7075cdc35872f672b524 Mon Sep 17 00:00:00 2001 +From: Simon Graham +Date: Thu, 9 Feb 2012 09:55:13 -0500 +Subject: [PATCH] rtlwifi: Modify rtl_pci_init to return 0 on success + +Fixes problem where caller would think routine succeeded when it failed +leading to divide by zero panic. + +Signed-off-by: Simon Graham +Acked-by: Larry Finger +Signed-off-by: John W. Linville +--- + drivers/net/wireless/rtlwifi/pci.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c +index 39e0907..9245d88 100644 +--- a/drivers/net/wireless/rtlwifi/pci.c ++++ b/drivers/net/wireless/rtlwifi/pci.c +@@ -1501,7 +1501,7 @@ static int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev) + return err; + } + +- return 1; ++ return 0; + } + + static int rtl_pci_start(struct ieee80211_hw *hw) +@@ -1870,7 +1870,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, + } + + /* Init PCI sw */ +- err = !rtl_pci_init(hw, pdev); ++ err = rtl_pci_init(hw, pdev); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Failed to init PCI.\n")); +-- +1.7.4.4 + diff --git a/zd1211rw-firmware-needs-duration_id-set-to-zero-for-.patch b/zd1211rw-firmware-needs-duration_id-set-to-zero-for-.patch new file mode 100644 index 000000000..cc9a16def --- /dev/null +++ b/zd1211rw-firmware-needs-duration_id-set-to-zero-for-.patch @@ -0,0 +1,51 @@ +From e81a7bd55531a77d8c16d44766db4089c2983f1b Mon Sep 17 00:00:00 2001 +From: Tomas Vanek +Date: Sun, 5 Feb 2012 15:51:53 +0200 +Subject: [PATCH] zd1211rw: firmware needs duration_id set to zero for + non-pspoll frames + +Some devices (iwl5100) cannot connect to zd1211rw based AP. It appears that +zd1211 firmware messes up duration_id field if it is not set to zero by driver. + +Sniffing traffic shows that zd1211 is transmitting frames with duration_id bits +14 and 15 set and other bits appearing random. Setting duration_id at driver to +zero results zd1211 outputting sane duration_id. This means that firmware is +setting correct values itself and expects duration_id to be zero in first +place. + +Looking at vendor driver shows that only PSPoll frames have duration_id set by +driver, for other frames duration_id left zero. + +Original bug-report and attached patch at: + http://sourceforge.net/mailarchive/message.php?msg_id=28759111 + +Reported-by: Tomas Vanek +[modified original patch from bug-report, added check for pspoll frame] +Signed-off-by: Jussi Kivilinna +Signed-off-by: John W. Linville +--- + drivers/net/wireless/zd1211rw/zd_mac.c | 8 ++++++++ + 1 files changed, 8 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c +index 0a70149..98a574a 100644 +--- a/drivers/net/wireless/zd1211rw/zd_mac.c ++++ b/drivers/net/wireless/zd1211rw/zd_mac.c +@@ -866,6 +866,14 @@ static int fill_ctrlset(struct zd_mac *mac, + + ZD_ASSERT(frag_len <= 0xffff); + ++ /* ++ * Firmware computes the duration itself (for all frames except PSPoll) ++ * and needs the field set to 0 at input, otherwise firmware messes up ++ * duration_id and sets bits 14 and 15 on. ++ */ ++ if (!ieee80211_is_pspoll(hdr->frame_control)) ++ hdr->duration_id = 0; ++ + txrate = ieee80211_get_tx_rate(mac->hw, info); + + cs->modulation = txrate->hw_value; +-- +1.7.4.4 + From 05f7286fe57f78e3bf3d2da3256f2eda2ee1c4bc Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 13 Feb 2012 15:19:16 -0500 Subject: [PATCH 274/487] Linux 3.2.6 --- block-readahead-block-plug.patch | 92 -------------------------------- kernel.spec | 8 +-- sources | 2 +- 3 files changed, 5 insertions(+), 97 deletions(-) delete mode 100644 block-readahead-block-plug.patch diff --git a/block-readahead-block-plug.patch b/block-readahead-block-plug.patch deleted file mode 100644 index 0b7bca650..000000000 --- a/block-readahead-block-plug.patch +++ /dev/null @@ -1,92 +0,0 @@ -commit 3deaa7190a8da38453c4fabd9dec7f66d17fff67 -Author: Shaohua Li -Date: Fri Feb 3 15:37:17 2012 -0800 - - readahead: fix pipeline break caused by block plug - - Herbert Poetzl reported a performance regression since 2.6.39. The test - is a simple dd read, but with big block size. The reason is: - - T1: ra (A, A+128k), (A+128k, A+256k) - T2: lock_page for page A, submit the 256k - T3: hit page A+128K, ra (A+256k, A+384). the range isn't submitted - because of plug and there isn't any lock_page till we hit page A+256k - because all pages from A to A+256k is in memory - T4: hit page A+256k, ra (A+384, A+ 512). Because of plug, the range isn't - submitted again. - T5: lock_page A+256k, so (A+256k, A+512k) will be submitted. The task is - waitting for (A+256k, A+512k) finish. - - There is no request to disk in T3 and T4, so readahead pipeline breaks. - - We really don't need block plug for generic_file_aio_read() for buffered - I/O. The readahead already has plug and has fine grained control when I/O - should be submitted. Deleting plug for buffered I/O fixes the regression. - - One side effect is plug makes the request size 256k, the size is 128k - without it. This is because default ra size is 128k and not a reason we - need plug here. - - Vivek said: - - : We submit some readahead IO to device request queue but because of nested - : plug, queue never gets unplugged. When read logic reaches a page which is - : not in page cache, it waits for page to be read from the disk - : (lock_page_killable()) and that time we flush the plug list. - : - : So effectively read ahead logic is kind of broken in parts because of - : nested plugging. Removing top level plug (generic_file_aio_read()) for - : buffered reads, will allow unplugging queue earlier for readahead. - - Signed-off-by: Shaohua Li - Signed-off-by: Wu Fengguang - Reported-by: Herbert Poetzl - Tested-by: Eric Dumazet - Cc: Christoph Hellwig - Cc: Jens Axboe - Cc: Vivek Goyal - Cc: - Signed-off-by: Andrew Morton - Signed-off-by: Linus Torvalds - -diff --git a/mm/filemap.c b/mm/filemap.c -index 97f49ed..b662757 100644 ---- a/mm/filemap.c -+++ b/mm/filemap.c -@@ -1400,15 +1400,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, - unsigned long seg = 0; - size_t count; - loff_t *ppos = &iocb->ki_pos; -- struct blk_plug plug; - - count = 0; - retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE); - if (retval) - return retval; - -- blk_start_plug(&plug); -- - /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ - if (filp->f_flags & O_DIRECT) { - loff_t size; -@@ -1424,8 +1421,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, - retval = filemap_write_and_wait_range(mapping, pos, - pos + iov_length(iov, nr_segs) - 1); - if (!retval) { -+ struct blk_plug plug; -+ -+ blk_start_plug(&plug); - retval = mapping->a_ops->direct_IO(READ, iocb, - iov, pos, nr_segs); -+ blk_finish_plug(&plug); - } - if (retval > 0) { - *ppos = pos + retval; -@@ -1481,7 +1482,6 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, - break; - } - out: -- blk_finish_plug(&plug); - return retval; - } - EXPORT_SYMBOL(generic_file_aio_read); diff --git a/kernel.spec b/kernel.spec index 8e9ca0a09..d59e5927d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 5 +%define stable_update 6 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -743,8 +743,6 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch Patch12016: disable-i8042-check-on-apple-mac.patch -Patch12025: block-readahead-block-plug.patch - Patch12026: bsg-fix-sysfs-link-remove-warning.patch Patch12030: epoll-limit-paths.patch @@ -1466,7 +1464,6 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch ApplyPatch disable-i8042-check-on-apple-mac.patch ApplyPatch epoll-limit-paths.patch -ApplyPatch block-readahead-block-plug.patch ApplyPatch bsg-fix-sysfs-link-remove-warning.patch @@ -2329,6 +2326,9 @@ fi # and build. %changelog +* Mon Feb 13 2012 Dave Jones 3.2.6-3 +- Linux 3.2.6 + * Mon Feb 13 2012 John W. Linville - mwifiex: handle association failure case correctly - ath9k: Fix kernel panic during driver initilization diff --git a/sources b/sources index 06e37eb44..bf9947c74 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz 8cfe037a7a7a356278ec3638e25ad506 compat-wireless-3.3-rc1-2.tar.bz2 -89cb9fb7ed01dccb15510435fb1e5024 patch-3.2.5.xz +0aea8fc5e705c5b1ef68697de9379cef patch-3.2.6.xz From 9a37463424b2977cb0fe503e4c11275960b1fa0c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 14 Feb 2012 10:22:26 -0500 Subject: [PATCH 275/487] Patch to enable CONFIG_KEYS_COMPAT on s390 from David Howells (rhbz 790367) --- kernel.spec | 11 ++++++++++- s390x-enable-keys-compat.patch | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 s390x-enable-keys-compat.patch diff --git a/kernel.spec b/kernel.spec index d59e5927d..435da91d9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -805,6 +805,9 @@ Patch21234: e1000e-Avoid-wrong-check-on-TX-hang.patch #rhbz 754518 Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch +#rhbz 790367 +Patch21239: s390x-enable-keys-compat.patch + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-pr_fmt-warning-avoidance.patch @@ -1521,6 +1524,9 @@ ApplyPatch e1000e-Avoid-wrong-check-on-TX-hang.patch #rhbz 754518 ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch +#rhbz 790367 +ApplyPatch s390x-enable-keys-compat.patch + # END OF PATCH APPLICATIONS %endif @@ -2326,6 +2332,9 @@ fi # and build. %changelog +* Tue Feb 14 2012 Josh Boyer +- Patch to enable CONFIG_KEYS_COMPAT on s390 from David Howells (rhbz 790367) + * Mon Feb 13 2012 Dave Jones 3.2.6-3 - Linux 3.2.6 diff --git a/s390x-enable-keys-compat.patch b/s390x-enable-keys-compat.patch new file mode 100644 index 000000000..43d203ca5 --- /dev/null +++ b/s390x-enable-keys-compat.patch @@ -0,0 +1,15 @@ +@@ -, +, @@ + arch/s390/Kconfig | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) +--- a/arch/s390/Kconfig ++++ a/arch/s390/Kconfig +@@ -227,6 +227,9 @@ config COMPAT + config SYSVIPC_COMPAT + def_bool y if COMPAT && SYSVIPC + ++config KEYS_COMPAT ++ def_bool y if COMPAT && KEYS ++ + config AUDIT_ARCH + def_bool y + From 973c2685b25481f0b7a5c3b23de58384762941ec Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 15 Feb 2012 19:10:32 -0500 Subject: [PATCH 276/487] Require newer linux-firmware for updated bnx2/bnx2x drivers --- kernel.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 435da91d9..10b0946c5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -524,7 +524,7 @@ Requires(pre): %{initrd_prereq}\ %if %{with_firmware}\ Requires(pre): kernel-firmware >= %{rpmversion}-%{pkg_release}\ %else\ -Requires(pre): linux-firmware >= 20100806-2\ +Requires(pre): linux-firmware >= 20120206-0.1.git06c8f81\ %endif\ Requires(post): /sbin/new-kernel-pkg\ Requires(preun): /sbin/new-kernel-pkg\ @@ -2332,6 +2332,9 @@ fi # and build. %changelog +* Wed Feb 15 2012 Josh Boyer +- Require newer linux-firmware for updated bnx2/bnx2x drivers + * Tue Feb 14 2012 Josh Boyer - Patch to enable CONFIG_KEYS_COMPAT on s390 from David Howells (rhbz 790367) From 90fada335077559f0718dc99486ab2ff8047b99c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 16 Feb 2012 23:20:05 -0500 Subject: [PATCH 277/487] Freeze all filesystems during system suspend/hibernate. --- hibernate-freeze-filesystems.patch | 257 +++++++++++++++++++++++++++++ kernel.spec | 7 + 2 files changed, 264 insertions(+) create mode 100644 hibernate-freeze-filesystems.patch diff --git a/hibernate-freeze-filesystems.patch b/hibernate-freeze-filesystems.patch new file mode 100644 index 000000000..dfb2f0478 --- /dev/null +++ b/hibernate-freeze-filesystems.patch @@ -0,0 +1,257 @@ +From: Rafael J. Wysocki + +Freeze all filesystems during system suspend and (kernel-driven) +hibernation by calling freeze_supers() for all superblocks and thaw +them during the subsequent resume with the help of thaw_supers(). + +This makes filesystems stay in a consistent state in case something +goes wrong between system suspend (or hibernation) and the subsequent +resume (e.g. journal replays won't be necessary in those cases). In +particular, this should help to solve a long-standing issue that, in +some cases, during resume from hibernation the boot loader causes the +journal to be replied for the filesystem containing the kernel image +and/or initrd causing it to become inconsistent with the information +stored in the hibernation image. + +The user-space-driven hibernation (s2disk) is not covered by this +change, because the freezing of filesystems prevents s2disk from +accessing device special files it needs to do its job. + +This change is based on earlier work by Nigel Cunningham. + +Signed-off-by: Rafael J. Wysocki +--- + fs/super.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/fs.h | 3 + + kernel/power/hibernate.c | 11 +++++-- + kernel/power/power.h | 23 -------------- + kernel/power/suspend.c | 42 +++++++++++++++++++++++++++ + 5 files changed, 128 insertions(+), 24 deletions(-) + +Index: linux/include/linux/fs.h +=================================================================== +--- linux.orig/include/linux/fs.h ++++ linux/include/linux/fs.h +@@ -210,6 +210,7 @@ struct inodes_stat_t { + #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */ + #define MS_I_VERSION (1<<23) /* Update inode I_version field */ + #define MS_STRICTATIME (1<<24) /* Always perform atime updates */ ++#define MS_FROZEN (1<<25) /* Frozen filesystem */ + #define MS_NOSEC (1<<28) + #define MS_BORN (1<<29) + #define MS_ACTIVE (1<<30) +@@ -2501,6 +2502,8 @@ extern void drop_super(struct super_bloc + extern void iterate_supers(void (*)(struct super_block *, void *), void *); + extern void iterate_supers_type(struct file_system_type *, + void (*)(struct super_block *, void *), void *); ++extern int freeze_supers(void); ++extern void thaw_supers(void); + + extern int dcache_dir_open(struct inode *, struct file *); + extern int dcache_dir_close(struct inode *, struct file *); +Index: linux/fs/super.c +=================================================================== +--- linux.orig/fs/super.c ++++ linux/fs/super.c +@@ -594,6 +594,79 @@ void iterate_supers_type(struct file_sys + EXPORT_SYMBOL(iterate_supers_type); + + /** ++ * thaw_supers - call thaw_super() for all superblocks ++ */ ++void thaw_supers(void) ++{ ++ struct super_block *sb, *p = NULL; ++ ++ spin_lock(&sb_lock); ++ list_for_each_entry(sb, &super_blocks, s_list) { ++ if (list_empty(&sb->s_instances)) ++ continue; ++ sb->s_count++; ++ spin_unlock(&sb_lock); ++ ++ if (sb->s_flags & MS_FROZEN) { ++ thaw_super(sb); ++ sb->s_flags &= ~MS_FROZEN; ++ } ++ ++ spin_lock(&sb_lock); ++ if (p) ++ __put_super(p); ++ p = sb; ++ } ++ if (p) ++ __put_super(p); ++ spin_unlock(&sb_lock); ++} ++ ++/** ++ * freeze_supers - call freeze_super() for all superblocks ++ */ ++int freeze_supers(void) ++{ ++ struct super_block *sb, *p = NULL; ++ int error = 0; ++ ++ spin_lock(&sb_lock); ++ /* ++ * Freeze in reverse order so filesystems depending on others are ++ * frozen in the right order (eg. loopback on ext3). ++ */ ++ list_for_each_entry_reverse(sb, &super_blocks, s_list) { ++ if (list_empty(&sb->s_instances)) ++ continue; ++ sb->s_count++; ++ spin_unlock(&sb_lock); ++ ++ if (sb->s_root && sb->s_frozen != SB_FREEZE_TRANS ++ && !(sb->s_flags & MS_RDONLY)) { ++ error = freeze_super(sb); ++ if (!error) ++ sb->s_flags |= MS_FROZEN; ++ } ++ ++ spin_lock(&sb_lock); ++ if (error) ++ break; ++ if (p) ++ __put_super(p); ++ p = sb; ++ } ++ if (p) ++ __put_super(p); ++ spin_unlock(&sb_lock); ++ ++ if (error) ++ thaw_supers(); ++ ++ return error; ++} ++ ++ ++/** + * get_super - get the superblock of a device + * @bdev: device to get the superblock for + * +Index: linux/kernel/power/power.h +=================================================================== +--- linux.orig/kernel/power/power.h ++++ linux/kernel/power/power.h +@@ -1,3 +1,4 @@ ++#include + #include + #include + #include +@@ -227,25 +228,3 @@ enum { + #define TEST_MAX (__TEST_AFTER_LAST - 1) + + extern int pm_test_level; +- +-#ifdef CONFIG_SUSPEND_FREEZER +-static inline int suspend_freeze_processes(void) +-{ +- int error = freeze_processes(); +- return error ? : freeze_kernel_threads(); +-} +- +-static inline void suspend_thaw_processes(void) +-{ +- thaw_processes(); +-} +-#else +-static inline int suspend_freeze_processes(void) +-{ +- return 0; +-} +- +-static inline void suspend_thaw_processes(void) +-{ +-} +-#endif +Index: linux/kernel/power/suspend.c +=================================================================== +--- linux.orig/kernel/power/suspend.c ++++ linux/kernel/power/suspend.c +@@ -29,6 +29,48 @@ + + #include "power.h" + ++#ifdef CONFIG_SUSPEND_FREEZER ++ ++static inline int suspend_freeze_processes(void) ++{ ++ int error; ++ ++ error = freeze_processes(); ++ if (error) ++ return error; ++ ++ error = freeze_supers(); ++ if (error) { ++ thaw_processes(); ++ return error; ++ } ++ ++ error = freeze_kernel_threads(); ++ if (error) ++ thaw_supers(); ++ ++ return error; ++} ++ ++static inline void suspend_thaw_processes(void) ++{ ++ thaw_supers(); ++ thaw_processes(); ++} ++ ++#else /* !CONFIG_SUSPEND_FREEZER */ ++ ++static inline int suspend_freeze_processes(void) ++{ ++ return 0; ++} ++ ++static inline void suspend_thaw_processes(void) ++{ ++} ++ ++#endif /* !CONFIG_SUSPEND_FREEZER */ ++ + const char *const pm_states[PM_SUSPEND_MAX] = { + [PM_SUSPEND_STANDBY] = "standby", + [PM_SUSPEND_MEM] = "mem", +Index: linux/kernel/power/hibernate.c +=================================================================== +--- linux.orig/kernel/power/hibernate.c ++++ linux/kernel/power/hibernate.c +@@ -626,12 +626,17 @@ int hibernate(void) + if (error) + goto Finish; + +- error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); ++ error = freeze_supers(); + if (error) + goto Thaw; ++ ++ error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); ++ if (error) ++ goto Thaw_fs; ++ + if (freezer_test_done) { + freezer_test_done = false; +- goto Thaw; ++ goto Thaw_fs; + } + + if (in_suspend) { +@@ -655,6 +660,8 @@ int hibernate(void) + pr_debug("PM: Image restored successfully.\n"); + } + ++ Thaw_fs: ++ thaw_supers(); + Thaw: + thaw_processes(); + Finish: + diff --git a/kernel.spec b/kernel.spec index 10b0946c5..69040dadf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -752,6 +752,8 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13002: revert-efi-rtclock.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch +Patch14000: hibernate-freeze-filesystems.patch + Patch20000: utrace.patch # Flattened devicetree support @@ -1476,6 +1478,8 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch revert-efi-rtclock.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch +ApplyPatch hibernate-freeze-filesystems.patch + # utrace. ApplyPatch utrace.patch @@ -2332,6 +2336,9 @@ fi # and build. %changelog +* Thu Feb 16 2012 Dave Jones +- Freeze all filesystems during system suspend/hibernate. + * Wed Feb 15 2012 Josh Boyer - Require newer linux-firmware for updated bnx2/bnx2x drivers From 98a4640c2dedcd14b3eefd69ebbef14cfc6a606f Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 16 Feb 2012 23:22:53 -0500 Subject: [PATCH 278/487] add version --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 69040dadf..da9a4e6ce 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2336,7 +2336,7 @@ fi # and build. %changelog -* Thu Feb 16 2012 Dave Jones +* Thu Feb 16 2012 Dave Jones 3.2.6-4 - Freeze all filesystems during system suspend/hibernate. * Wed Feb 15 2012 Josh Boyer From f1ec5c04e8d2f946b667473cb0338251632b9750 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 17 Feb 2012 14:56:29 -0500 Subject: [PATCH 279/487] Reenable radio drivers. (rhbz 784824) --- config-generic | 15 ++++++++++++++- kernel.spec | 3 +++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 025b58cde..a6a821b23 100644 --- a/config-generic +++ b/config-generic @@ -4161,7 +4161,20 @@ CONFIG_NE2000=m # CONFIG_SERIAL_8250_HUB6 is not set # CONFIG_SERIAL_8250_EXAR_ST16C554 is not set -# CONFIG_RADIO_ADAPTERS is not set +CONFIG_RADIO_ADAPTERS=y +CONFIG_RADIO_TEA5764=m +CONFIG_RADIO_SAA7706H=m +CONFIG_RADIO_CADET=m +CONFIG_RADIO_RTRACK=m +CONFIG_RADIO_RTRACK2=m +CONFIG_RADIO_AZTECH=m +CONFIG_RADIO_GEMTEK=m +CONFIG_RADIO_SF16FMI=m +CONFIG_RADIO_SF16FMR2=m +CONFIG_RADIO_TERRATEC=m +CONFIG_RADIO_TRUST=m +CONFIG_RADIO_TYPHOON=m +CONFIG_RADIO_ZOLTRIX=m # CONFIG_SND_OPL4_LIB is not set # CONFIG_SND_AD1816A is not set diff --git a/kernel.spec b/kernel.spec index da9a4e6ce..503c4f19f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2336,6 +2336,9 @@ fi # and build. %changelog +* Fri Feb 17 2012 Dave Jones +- Reenable radio drivers. (rhbz 784824) + * Thu Feb 16 2012 Dave Jones 3.2.6-4 - Freeze all filesystems during system suspend/hibernate. From b995bdd158bb5e2461261f7116a6a0d1e0788517 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 17 Feb 2012 16:00:02 -0500 Subject: [PATCH 280/487] improve handling of null rate in LIS3LV02Dx accelerometer driver. (rhbz 785814) --- kernel.spec | 7 +++ lis3-improve-handling-of-null-rate.patch | 79 ++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 lis3-improve-handling-of-null-rate.patch diff --git a/kernel.spec b/kernel.spec index 503c4f19f..556a7f1e6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -754,6 +754,8 @@ Patch13003: efi-dont-map-boot-services-on-32bit.patch Patch14000: hibernate-freeze-filesystems.patch +Patch14010: lis3-improve-handling-of-null-rate.patch + Patch20000: utrace.patch # Flattened devicetree support @@ -1480,6 +1482,8 @@ ApplyPatch efi-dont-map-boot-services-on-32bit.patch ApplyPatch hibernate-freeze-filesystems.patch +ApplyPatch lis3-improve-handling-of-null-rate.patch + # utrace. ApplyPatch utrace.patch @@ -2336,6 +2340,9 @@ fi # and build. %changelog +* Fri Feb 17 2012 Dave Jones +- improve handling of null rate in LIS3LV02Dx accelerometer driver. (rhbz 785814) + * Fri Feb 17 2012 Dave Jones - Reenable radio drivers. (rhbz 784824) diff --git a/lis3-improve-handling-of-null-rate.patch b/lis3-improve-handling-of-null-rate.patch new file mode 100644 index 000000000..98512564a --- /dev/null +++ b/lis3-improve-handling-of-null-rate.patch @@ -0,0 +1,79 @@ +>From 56fb161a9ca0129f8e266e4dbe79346552ff8089 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=89ric=20Piel?= +Date: Thu, 3 Nov 2011 16:22:40 +0100 +Subject: [PATCH] lis3: Improve handling of null rate +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When obtaining a rate of 0, we would disable the device supposely +because it seems to behave incorectly. It actually only comes from the +fact that the device is off and on lis3dc it's reflected in the rate. +So handle this nicely by just waiting a safe time, and then using the +device as normally. + +Signed-off-by: ??ric Piel +--- + drivers/misc/lis3lv02d/lis3lv02d.c | 16 ++++++++-------- + 1 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c +index 35c67e0..42dce2a 100644 +--- a/drivers/misc/lis3lv02d/lis3lv02d.c ++++ b/drivers/misc/lis3lv02d/lis3lv02d.c +@@ -188,7 +188,8 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z) + /* conversion btw sampling rate and the register values */ + static int lis3_12_rates[4] = {40, 160, 640, 2560}; + static int lis3_8_rates[2] = {100, 400}; +-static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000}; ++/* LIS3DC: 0 = power off, above 9 = undefined */ ++static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000, -1, -1, -1, -1, -1, -1}; + + /* ODR is Output Data Rate */ + static int lis3lv02d_get_odr(struct lis3lv02d *lis3) +@@ -202,12 +203,11 @@ static int lis3lv02d_get_odr(struct lis3lv02d *lis3) + return lis3->odrs[(ctrl >> shift)]; + } + +-static int lis3lv02d_get_pwron_wait(struct lis3lv02d *lis3) ++static int lis3lv02d_wait_pwron(struct lis3lv02d *lis3) + { + int div = lis3lv02d_get_odr(lis3); +- +- if (WARN_ONCE(div == 0, "device returned spurious data")) +- return -ENXIO; ++ if (div <= 0) ++ div = 1; /* maximum delay */ + + /* LIS3 power on delay is quite long */ + msleep(lis3->pwron_delay / div); +@@ -274,7 +274,7 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3]) + + lis3->read(lis3, ctlreg, ®); + lis3->write(lis3, ctlreg, (reg | selftest)); +- ret = lis3lv02d_get_pwron_wait(lis3); ++ ret = lis3lv02d_wait_pwron(lis3); + if (ret) + goto fail; + +@@ -285,7 +285,7 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3]) + + /* back to normal settings */ + lis3->write(lis3, ctlreg, reg); +- ret = lis3lv02d_get_pwron_wait(lis3); ++ ret = lis3lv02d_wait_pwron(lis3); + if (ret) + goto fail; + +@@ -397,7 +397,7 @@ int lis3lv02d_poweron(struct lis3lv02d *lis3) + lis3->write(lis3, CTRL_REG2, reg); + } + +- err = lis3lv02d_get_pwron_wait(lis3); ++ err = lis3lv02d_wait_pwron(lis3); + if (err) + return err; + +-- +1.7.7.1 + From b0afc0c7f3eea660f57959332ac78f0d4d640035 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 20 Feb 2012 13:22:56 -0500 Subject: [PATCH 281/487] NFSv4: Fix an Oops in the NFSv4 getacl code --- kernel.spec | 11 ++++- nfs-oops-getacl.patch | 96 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 nfs-oops-getacl.patch diff --git a/kernel.spec b/kernel.spec index 556a7f1e6..41431538e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 6 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -765,8 +765,10 @@ Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch #rhbz 717735 Patch21045: nfs-client-freezer.patch +Patch21046: nfs-oops-getacl.patch + #rhbz 590880 -Patch21046: alps.patch +Patch21050: alps.patch Patch21070: ext4-Support-check-none-nocheck-mount-options.patch Patch21071: ext4-Fix-error-handling-on-inode-bitmap-corruption.patch @@ -1498,6 +1500,8 @@ ApplyPatch hpsa-add-irqf-shared.patch #rhbz 717735 ApplyPatch nfs-client-freezer.patch +ApplyPatch nfs-oops-getacl.patch + #rhbz 590880 ApplyPatch alps.patch @@ -2340,6 +2344,9 @@ fi # and build. %changelog +* Mon Feb 20 2012 Dave Jones +- NFSv4: Fix an Oops in the NFSv4 getacl code + * Fri Feb 17 2012 Dave Jones - improve handling of null rate in LIS3LV02Dx accelerometer driver. (rhbz 785814) diff --git a/nfs-oops-getacl.patch b/nfs-oops-getacl.patch new file mode 100644 index 000000000..53e599dd4 --- /dev/null +++ b/nfs-oops-getacl.patch @@ -0,0 +1,96 @@ +From 331818f1c468a24e581aedcbe52af799366a9dfe Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Fri, 3 Feb 2012 18:30:53 -0500 +Subject: [PATCH] NFSv4: Fix an Oops in the NFSv4 getacl code + +Commit bf118a342f10dafe44b14451a1392c3254629a1f (NFSv4: include bitmap +in nfsv4 get acl data) introduces the 'acl_scratch' page for the case +where we may need to decode multi-page data. However it fails to take +into account the fact that the variable may be NULL (for the case where +we're not doing multi-page decode), and it also attaches it to the +encoding xdr_stream rather than the decoding one. + +The immediate result is an Oops in nfs4_xdr_enc_getacl due to the +call to page_address() with a NULL page pointer. + +Signed-off-by: Trond Myklebust +Cc: Andy Adamson +Cc: stable@vger.kernel.org +--- + fs/nfs/nfs4proc.c | 8 ++++---- + fs/nfs/nfs4xdr.c | 5 ++++- + include/linux/nfs_xdr.h | 2 +- + 3 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index f0c849c..d202e04 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -3575,8 +3575,8 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu + } + if (npages > 1) { + /* for decoding across pages */ +- args.acl_scratch = alloc_page(GFP_KERNEL); +- if (!args.acl_scratch) ++ res.acl_scratch = alloc_page(GFP_KERNEL); ++ if (!res.acl_scratch) + goto out_free; + } + args.acl_len = npages * PAGE_SIZE; +@@ -3612,8 +3612,8 @@ out_free: + for (i = 0; i < npages; i++) + if (pages[i]) + __free_page(pages[i]); +- if (args.acl_scratch) +- __free_page(args.acl_scratch); ++ if (res.acl_scratch) ++ __free_page(res.acl_scratch); + return ret; + } + +diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c +index 95e92e4..33bd8d0 100644 +--- a/fs/nfs/nfs4xdr.c ++++ b/fs/nfs/nfs4xdr.c +@@ -2522,7 +2522,6 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, + + xdr_inline_pages(&req->rq_rcv_buf, replen << 2, + args->acl_pages, args->acl_pgbase, args->acl_len); +- xdr_set_scratch_buffer(xdr, page_address(args->acl_scratch), PAGE_SIZE); + + encode_nops(&hdr); + } +@@ -6032,6 +6031,10 @@ nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr, + struct compound_hdr hdr; + int status; + ++ if (res->acl_scratch != NULL) { ++ void *p = page_address(res->acl_scratch); ++ xdr_set_scratch_buffer(xdr, p, PAGE_SIZE); ++ } + status = decode_compound_hdr(xdr, &hdr); + if (status) + goto out; +diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h +index a764cef..d6ba9a1 100644 +--- a/include/linux/nfs_xdr.h ++++ b/include/linux/nfs_xdr.h +@@ -614,7 +614,6 @@ struct nfs_getaclargs { + size_t acl_len; + unsigned int acl_pgbase; + struct page ** acl_pages; +- struct page * acl_scratch; + struct nfs4_sequence_args seq_args; + }; + +@@ -624,6 +623,7 @@ struct nfs_getaclres { + size_t acl_len; + size_t acl_data_offset; + int acl_flags; ++ struct page * acl_scratch; + struct nfs4_sequence_res seq_res; + }; + +-- +1.7.4.1 + From 2919d1eb00a60b55d81a8c793cfa878d9e3c5ad5 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 20 Feb 2012 18:27:59 -0500 Subject: [PATCH 282/487] 3.2.7 --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 41431538e..262d3f254 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 6 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 6 +%define stable_update 7 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2344,6 +2344,9 @@ fi # and build. %changelog +* Mon Feb 20 2012 Dave Jones +- Linux 3.2.7 + * Mon Feb 20 2012 Dave Jones - NFSv4: Fix an Oops in the NFSv4 getacl code diff --git a/sources b/sources index bf9947c74..6a79988da 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz 8cfe037a7a7a356278ec3638e25ad506 compat-wireless-3.3-rc1-2.tar.bz2 -0aea8fc5e705c5b1ef68697de9379cef patch-3.2.6.xz +e507fce2c266549df9565172196c912d patch-3.2.7.xz From 15609ef4c4488afd6f62cff8c105045ea832bc9b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 20 Feb 2012 20:06:42 -0500 Subject: [PATCH 283/487] Do not call drivers when invalidating partitions for -ENOMEDIUM --- kernel.spec | 9 +- scsi-fix-sd_revalidate_disk-oops.patch | 116 +++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 scsi-fix-sd_revalidate_disk-oops.patch diff --git a/kernel.spec b/kernel.spec index 262d3f254..ecc5c2ad8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -809,7 +809,8 @@ Patch21233: jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch Patch21234: e1000e-Avoid-wrong-check-on-TX-hang.patch #rhbz 754518 -Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch +#Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch +Patch21235: scsi-fix-sd_revalidate_disk-oops.patch #rhbz 790367 Patch21239: s390x-enable-keys-compat.patch @@ -1534,7 +1535,8 @@ ApplyPatch jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch ApplyPatch e1000e-Avoid-wrong-check-on-TX-hang.patch #rhbz 754518 -ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch +#ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch +ApplyPatch scsi-fix-sd_revalidate_disk-oops.patch #rhbz 790367 ApplyPatch s390x-enable-keys-compat.patch @@ -2344,6 +2346,9 @@ fi # and build. %changelog +* Mon Feb 20 2012 Dave Jones 3.2.7-1 +- Do not call drivers when invalidating partitions for -ENOMEDIUM + * Mon Feb 20 2012 Dave Jones - Linux 3.2.7 diff --git a/scsi-fix-sd_revalidate_disk-oops.patch b/scsi-fix-sd_revalidate_disk-oops.patch new file mode 100644 index 000000000..defa240a2 --- /dev/null +++ b/scsi-fix-sd_revalidate_disk-oops.patch @@ -0,0 +1,116 @@ +--- linux-2.6.42.noarch/fs/partitions/check.c~ 2012-02-20 18:32:55.314253719 -0500 ++++ linux-2.6.42.noarch/fs/partitions/check.c 2012-02-20 18:34:46.509859745 -0500 +@@ -539,17 +539,11 @@ static bool disk_unlock_native_capacity( + } + } + +-int rescan_partitions(struct gendisk *disk, struct block_device *bdev) ++static int drop_partitions(struct gendisk *disk, struct block_device *bdev) + { +- struct parsed_partitions *state = NULL; + struct disk_part_iter piter; + struct hd_struct *part; +- int p, highest, res; +-rescan: +- if (state && !IS_ERR(state)) { +- kfree(state); +- state = NULL; +- } ++ int res; + + if (bdev->bd_part_count) + return -EBUSY; +@@ -562,6 +556,24 @@ rescan: + delete_partition(disk, part->partno); + disk_part_iter_exit(&piter); + ++ return 0; ++} ++ ++int rescan_partitions(struct gendisk *disk, struct block_device *bdev) ++{ ++ struct parsed_partitions *state = NULL; ++ struct hd_struct *part; ++ int p, highest, res; ++rescan: ++ if (state && !IS_ERR(state)) { ++ kfree(state); ++ state = NULL; ++ } ++ ++ res = drop_partitions(disk, bdev); ++ if (res) ++ return res; ++ + if (disk->fops->revalidate_disk) + disk->fops->revalidate_disk(disk); + check_disk_size_change(disk, bdev); +@@ -665,6 +677,26 @@ rescan: + return 0; + } + ++int invalidate_partitions(struct gendisk *disk, struct block_device *bdev) ++{ ++ int res; ++ ++ if (!bdev->bd_invalidated) ++ return 0; ++ ++ res = drop_partitions(disk, bdev); ++ if (res) ++ return res; ++ ++ set_capacity(disk, 0); ++ check_disk_size_change(disk, bdev); ++ bdev->bd_invalidated = 0; ++ /* tell userspace that the media / partition table may have changed */ ++ kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE); ++ ++ return 0; ++} ++ + unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p) + { + struct address_space *mapping = bdev->bd_inode->i_mapping; +--- linux-2.6.42.noarch/include/linux/genhd.h~ 2012-02-20 18:35:02.777802107 -0500 ++++ linux-2.6.42.noarch/include/linux/genhd.h 2012-02-20 18:35:13.873762792 -0500 +@@ -596,6 +596,7 @@ extern char *disk_name (struct gendisk * + + extern int disk_expand_part_tbl(struct gendisk *disk, int target); + extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); ++extern int invalidate_partitions(struct gendisk *disk, struct block_device *bdev); + extern struct hd_struct * __must_check add_partition(struct gendisk *disk, + int partno, sector_t start, + sector_t len, int flags, +--- linux-2.6.42.noarch/fs/block_dev.c~ 2012-02-20 18:35:24.890723757 -0500 ++++ linux-2.6.42.noarch/fs/block_dev.c 2012-02-20 18:36:25.166510197 -0500 +@@ -1159,8 +1159,12 @@ static int __blkdev_get(struct block_dev + * The latter is necessary to prevent ghost + * partitions on a removed medium. + */ +- if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM)) +- rescan_partitions(disk, bdev); ++ if (bdev->bd_invalidated) { ++ if (!ret) ++ rescan_partitions(disk, bdev); ++ else if (ret == -ENOMEDIUM) ++ invalidate_partitions(disk, bdev); ++ } + if (ret) + goto out_clear; + } else { +@@ -1190,8 +1194,12 @@ static int __blkdev_get(struct block_dev + if (bdev->bd_disk->fops->open) + ret = bdev->bd_disk->fops->open(bdev, mode); + /* the same as first opener case, read comment there */ +- if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM)) +- rescan_partitions(bdev->bd_disk, bdev); ++ if (bdev->bd_invalidated) { ++ if (!ret) ++ rescan_partitions(bdev->bd_disk, bdev); ++ else if (ret == -ENOMEDIUM) ++ invalidate_partitions(bdev->bd_disk, bdev); ++ } + if (ret) + goto out_unlock_bdev; + } From 88b9de105c155ec301c662cb96a0a1609167d067 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 24 Feb 2012 10:04:27 -0500 Subject: [PATCH 284/487] mac80211: call rate control only after init mac80211: do not call rate control .tx_status before .rate_init mwifiex: clear previous security setting during association ath9k: stop on rates with idx -1 in ath9k rate control's .tx_status ath9k_hw: prevent writes to const data on AR9160 rt2x00: fix a possible NULL pointer dereference iwlwifi: fix key removal mac80211: zero initialize count field in ieee80211_tx_rate mac80211: Fix a warning on changing to monitor mode from STA brcm80211: smac: fix endless retry of A-MPDU transmissions brcm80211: smac: only print block-ack timeout message at trace level --- ...tes-with-idx-1-in-ath9k-rate-control.patch | 39 ++++++ ...event-writes-to-const-data-on-AR9160.patch | 117 ++++++++++++++++++ ...ix-endless-retry-of-A-MPDU-transmiss.patch | 56 +++++++++ ...nly-print-block-ack-timeout-message-.patch | 37 ++++++ iwlwifi-fix-key-removal.patch | 56 +++++++++ kernel.spec | 35 ++++++ ...arning-on-changing-to-monitor-mode-f.patch | 72 +++++++++++ ...11-call-rate-control-only-after-init.patch | 91 ++++++++++++++ ...call-rate-control-.tx_status-before-.patch | 33 +++++ ...itialize-count-field-in-ieee80211_tx.patch | 39 ++++++ ...evious-security-setting-during-assoc.patch | 55 ++++++++ ...-a-possible-NULL-pointer-dereference.patch | 37 ++++++ 12 files changed, 667 insertions(+) create mode 100644 ath9k-stop-on-rates-with-idx-1-in-ath9k-rate-control.patch create mode 100644 ath9k_hw-prevent-writes-to-const-data-on-AR9160.patch create mode 100644 brcm80211-smac-fix-endless-retry-of-A-MPDU-transmiss.patch create mode 100644 brcm80211-smac-only-print-block-ack-timeout-message-.patch create mode 100644 iwlwifi-fix-key-removal.patch create mode 100644 mac80211-Fix-a-warning-on-changing-to-monitor-mode-f.patch create mode 100644 mac80211-call-rate-control-only-after-init.patch create mode 100644 mac80211-do-not-call-rate-control-.tx_status-before-.patch create mode 100644 mac80211-zero-initialize-count-field-in-ieee80211_tx.patch create mode 100644 mwifiex-clear-previous-security-setting-during-assoc.patch create mode 100644 rt2x00-fix-a-possible-NULL-pointer-dereference.patch diff --git a/ath9k-stop-on-rates-with-idx-1-in-ath9k-rate-control.patch b/ath9k-stop-on-rates-with-idx-1-in-ath9k-rate-control.patch new file mode 100644 index 000000000..f118bd5c2 --- /dev/null +++ b/ath9k-stop-on-rates-with-idx-1-in-ath9k-rate-control.patch @@ -0,0 +1,39 @@ +From 2504a6423b9ab4c36df78227055995644de19edb Mon Sep 17 00:00:00 2001 +From: Pavel Roskin +Date: Sat, 11 Feb 2012 10:01:53 -0500 +Subject: [PATCH] ath9k: stop on rates with idx -1 in ath9k rate control's + .tx_status + +Rate control algorithms are supposed to stop processing when they +encounter a rate with the index -1. Checking for rate->count not being +zero is not enough. + +Allowing a rate with negative index leads to memory corruption in +ath_debug_stat_rc(). + +One consequence of the bug is discussed at +https://bugzilla.redhat.com/show_bug.cgi?id=768639 + +Signed-off-by: Pavel Roskin +Cc: stable@vger.kernel.org +Signed-off-by: John W. Linville +--- + drivers/net/wireless/ath/ath9k/rc.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c +index 635b592..a427a16 100644 +--- a/drivers/net/wireless/ath/ath9k/rc.c ++++ b/drivers/net/wireless/ath/ath9k/rc.c +@@ -1346,7 +1346,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, + fc = hdr->frame_control; + for (i = 0; i < sc->hw->max_rates; i++) { + struct ieee80211_tx_rate *rate = &tx_info->status.rates[i]; +- if (!rate->count) ++ if (rate->idx < 0 || !rate->count) + break; + + final_ts_idx = i; +-- +1.7.4.4 + diff --git a/ath9k_hw-prevent-writes-to-const-data-on-AR9160.patch b/ath9k_hw-prevent-writes-to-const-data-on-AR9160.patch new file mode 100644 index 000000000..f034020d9 --- /dev/null +++ b/ath9k_hw-prevent-writes-to-const-data-on-AR9160.patch @@ -0,0 +1,117 @@ +From 9bbb8168ed3d8b946f9c1901a63a675012de88f2 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Wed, 15 Feb 2012 19:31:20 +0100 +Subject: [PATCH] ath9k_hw: prevent writes to const data on AR9160 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Duplicate the data for iniAddac early on, to avoid having to do redundant +memcpy calls later. While we're at it, make AR5416 < v2.2 use the same +codepath. Fixes a reported crash on x86. + +Signed-off-by: Felix Fietkau +Reported-by: Magnus Määttä +Cc: stable@vger.kernel.org +Signed-off-by: John W. Linville +--- + drivers/net/wireless/ath/ath9k/ar5008_phy.c | 25 +------------------------ + drivers/net/wireless/ath/ath9k/ar9002_hw.c | 19 +++++++++++++++++++ + drivers/net/wireless/ath/ath9k/hw.h | 1 - + 3 files changed, 20 insertions(+), 25 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +index f901a17..86a891f 100644 +--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +@@ -489,8 +489,6 @@ static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah) + ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows); + ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows); + ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows); +- ATH_ALLOC_BANK(ah->addac5416_21, +- ah->iniAddac.ia_rows * ah->iniAddac.ia_columns); + ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows); + + return 0; +@@ -519,7 +517,6 @@ static void ar5008_hw_rf_free_ext_banks(struct ath_hw *ah) + ATH_FREE_BANK(ah->analogBank6Data); + ATH_FREE_BANK(ah->analogBank6TPCData); + ATH_FREE_BANK(ah->analogBank7Data); +- ATH_FREE_BANK(ah->addac5416_21); + ATH_FREE_BANK(ah->bank6Temp); + + #undef ATH_FREE_BANK +@@ -805,27 +802,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, + if (ah->eep_ops->set_addac) + ah->eep_ops->set_addac(ah, chan); + +- if (AR_SREV_5416_22_OR_LATER(ah)) { +- REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites); +- } else { +- struct ar5416IniArray temp; +- u32 addacSize = +- sizeof(u32) * ah->iniAddac.ia_rows * +- ah->iniAddac.ia_columns; +- +- /* For AR5416 2.0/2.1 */ +- memcpy(ah->addac5416_21, +- ah->iniAddac.ia_array, addacSize); +- +- /* override CLKDRV value at [row, column] = [31, 1] */ +- (ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0; +- +- temp.ia_array = ah->addac5416_21; +- temp.ia_columns = ah->iniAddac.ia_columns; +- temp.ia_rows = ah->iniAddac.ia_rows; +- REG_WRITE_ARRAY(&temp, 1, regWrites); +- } +- ++ REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites); + REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); + + ENABLE_REGWRITE_BUFFER(ah); +diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c +index 11f192a..d190411 100644 +--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c ++++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c +@@ -180,6 +180,25 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) + INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac, + ARRAY_SIZE(ar5416Addac), 2); + } ++ ++ /* iniAddac needs to be modified for these chips */ ++ if (AR_SREV_9160(ah) || !AR_SREV_5416_22_OR_LATER(ah)) { ++ struct ar5416IniArray *addac = &ah->iniAddac; ++ u32 size = sizeof(u32) * addac->ia_rows * addac->ia_columns; ++ u32 *data; ++ ++ data = kmalloc(size, GFP_KERNEL); ++ if (!data) ++ return; ++ ++ memcpy(data, addac->ia_array, size); ++ addac->ia_array = data; ++ ++ if (!AR_SREV_5416_22_OR_LATER(ah)) { ++ /* override CLKDRV value */ ++ INI_RA(addac, 31,1) = 0; ++ } ++ } + } + + /* Support for Japan ch.14 (2484) spread */ +diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h +index 6a29004..c8261d4 100644 +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -940,7 +940,6 @@ struct ath_hw { + u32 *analogBank6Data; + u32 *analogBank6TPCData; + u32 *analogBank7Data; +- u32 *addac5416_21; + u32 *bank6Temp; + + u8 txpower_limit; +-- +1.7.4.4 + diff --git a/brcm80211-smac-fix-endless-retry-of-A-MPDU-transmiss.patch b/brcm80211-smac-fix-endless-retry-of-A-MPDU-transmiss.patch new file mode 100644 index 000000000..c50c64248 --- /dev/null +++ b/brcm80211-smac-fix-endless-retry-of-A-MPDU-transmiss.patch @@ -0,0 +1,56 @@ +From 85091fc0a75653e239dc8379658515e577544927 Mon Sep 17 00:00:00 2001 +From: Arend van Spriel +Date: Thu, 23 Feb 2012 18:38:22 +0100 +Subject: [PATCH] brcm80211: smac: fix endless retry of A-MPDU transmissions + +The A-MPDU code checked against a retry limit, but it was using +the wrong variable to do so. This patch fixes this to assure +proper retry mechanism. + +This problem had a side-effect causing the mac80211 flush callback +to remain waiting forever as well. That side effect has been fixed +by commit by Stanislaw Gruszka: + +commit f96b08a7e6f69c0f0a576554df3df5b1b519c479 +Date: Tue Jan 17 12:38:50 2012 +0100 + + brcmsmac: fix tx queue flush infinite loop + + Reference: + https://bugzilla.kernel.org/show_bug.cgi?id=42576 + +Cc: Stanislaw Gruszka +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Alwin Beukers +Signed-off-by: Arend van Spriel +Signed-off-by: John W. Linville +--- + drivers/net/wireless/brcm80211/brcmsmac/ampdu.c | 6 +----- + 1 files changed, 1 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c +index 90911ee..9265226 100644 +--- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c +@@ -1051,17 +1051,13 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, + } + /* either retransmit or send bar if ack not recd */ + if (!ack_recd) { +- struct ieee80211_tx_rate *txrate = +- tx_info->status.rates; +- if (retry && (txrate[0].count < (int)retry_limit)) { ++ if (retry && (ini->txretry[index] < (int)retry_limit)) { + ini->txretry[index]++; + ini->tx_in_transit--; + /* + * Use high prededence for retransmit to + * give some punch + */ +- /* brcms_c_txq_enq(wlc, scb, p, +- * BRCMS_PRIO_TO_PREC(tid)); */ + brcms_c_txq_enq(wlc, scb, p, + BRCMS_PRIO_TO_HI_PREC(tid)); + } else { +-- +1.7.4.4 + diff --git a/brcm80211-smac-only-print-block-ack-timeout-message-.patch b/brcm80211-smac-only-print-block-ack-timeout-message-.patch new file mode 100644 index 000000000..b0e9d6974 --- /dev/null +++ b/brcm80211-smac-only-print-block-ack-timeout-message-.patch @@ -0,0 +1,37 @@ +From 2b0a53d51b5f263bb581bbdb40ebb9f7e09609b1 Mon Sep 17 00:00:00 2001 +From: Arend van Spriel +Date: Thu, 23 Feb 2012 18:38:23 +0100 +Subject: [PATCH] brcm80211: smac: only print block-ack timeout message at + trace level + +In regular use block-ack timeouts can happen so it does not make +sense to fill the log with these messages. + +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Alwin Beukers +Signed-off-by: Arend van Spriel +Signed-off-by: John W. Linville +--- + drivers/net/wireless/brcm80211/brcmsmac/ampdu.c | 6 +++--- + 1 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c +index 9265226..30b5887 100644 +--- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c +@@ -1070,9 +1070,9 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, + IEEE80211_TX_STAT_AMPDU_NO_BACK; + skb_pull(p, D11_PHY_HDR_LEN); + skb_pull(p, D11_TXH_LEN); +- wiphy_err(wiphy, "%s: BA Timeout, seq %d, in_" +- "transit %d\n", "AMPDU status", seq, +- ini->tx_in_transit); ++ BCMMSG(wiphy, ++ "BA Timeout, seq %d, in_transit %d\n", ++ seq, ini->tx_in_transit); + ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, + p); + } +-- +1.7.4.4 + diff --git a/iwlwifi-fix-key-removal.patch b/iwlwifi-fix-key-removal.patch new file mode 100644 index 000000000..9a90160aa --- /dev/null +++ b/iwlwifi-fix-key-removal.patch @@ -0,0 +1,56 @@ +From 5dcbf480473f6c3f06ad2426b7517038a2a18911 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 17 Feb 2012 09:47:14 -0800 +Subject: [PATCH] iwlwifi: fix key removal + +When trying to remove a key, we always send key +flags just setting the key type, not including +the multicast flag and the key ID. As a result, +whenever any key was removed, the unicast key 0 +would be removed, causing a complete connection +loss after the second rekey (the first doesn't +cause a key removal). Fix the key removal code +to include the key ID and multicast flag, thus +removing the correct key. + +Cc: stable@vger.kernel.org +Reported-by: Alexander Schnaidt +Tested-by: Alexander Schnaidt +Signed-off-by: Johannes Berg +Signed-off-by: Wey-Yi Guy +Signed-off-by: John W. Linville +--- + drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 10 +++++++++- + 1 files changed, 9 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +index 7353826..e483cfa 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +@@ -1187,6 +1187,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, + unsigned long flags; + struct iwl_addsta_cmd sta_cmd; + u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta); ++ __le16 key_flags; + + /* if station isn't there, neither is the key */ + if (sta_id == IWL_INVALID_STATION) +@@ -1212,7 +1213,14 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, + IWL_ERR(priv, "offset %d not used in uCode key table.\n", + keyconf->hw_key_idx); + +- sta_cmd.key.key_flags = STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID; ++ key_flags = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); ++ key_flags |= STA_KEY_FLG_MAP_KEY_MSK | STA_KEY_FLG_NO_ENC | ++ STA_KEY_FLG_INVALID; ++ ++ if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) ++ key_flags |= STA_KEY_MULTICAST_MSK; ++ ++ sta_cmd.key.key_flags = key_flags; + sta_cmd.key.key_offset = WEP_INVALID_OFFSET; + sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK; + sta_cmd.mode = STA_CONTROL_MODIFY_MSK; +-- +1.7.4.4 + diff --git a/kernel.spec b/kernel.spec index ecc5c2ad8..15fded651 100644 --- a/kernel.spec +++ b/kernel.spec @@ -845,6 +845,17 @@ Patch50121: bcma-don-t-fail-for-bad-SPROM-CRC.patch Patch50122: zd1211rw-firmware-needs-duration_id-set-to-zero-for-.patch Patch50123: mac80211-Fix-a-rwlock-bad-magic-bug.patch Patch50124: rtlwifi-Modify-rtl_pci_init-to-return-0-on-success.patch +Patch50125: mac80211-call-rate-control-only-after-init.patch +Patch50126: mac80211-do-not-call-rate-control-.tx_status-before-.patch +Patch50127: mwifiex-clear-previous-security-setting-during-assoc.patch +Patch50128: ath9k-stop-on-rates-with-idx-1-in-ath9k-rate-control.patch +Patch50129: ath9k_hw-prevent-writes-to-const-data-on-AR9160.patch +Patch50130: rt2x00-fix-a-possible-NULL-pointer-dereference.patch +Patch50131: iwlwifi-fix-key-removal.patch +Patch50132: mac80211-zero-initialize-count-field-in-ieee80211_tx.patch +Patch50133: mac80211-Fix-a-warning-on-changing-to-monitor-mode-f.patch +Patch50134: brcm80211-smac-fix-endless-retry-of-A-MPDU-transmiss.patch +Patch50135: brcm80211-smac-only-print-block-ack-timeout-message-.patch %endif @@ -1633,6 +1644,17 @@ ApplyPatch bcma-don-t-fail-for-bad-SPROM-CRC.patch ApplyPatch zd1211rw-firmware-needs-duration_id-set-to-zero-for-.patch ApplyPatch mac80211-Fix-a-rwlock-bad-magic-bug.patch ApplyPatch rtlwifi-Modify-rtl_pci_init-to-return-0-on-success.patch +ApplyPatch mac80211-call-rate-control-only-after-init.patch +ApplyPatch mac80211-do-not-call-rate-control-.tx_status-before-.patch +ApplyPatch mwifiex-clear-previous-security-setting-during-assoc.patch +ApplyPatch ath9k-stop-on-rates-with-idx-1-in-ath9k-rate-control.patch +ApplyPatch ath9k_hw-prevent-writes-to-const-data-on-AR9160.patch +ApplyPatch rt2x00-fix-a-possible-NULL-pointer-dereference.patch +ApplyPatch iwlwifi-fix-key-removal.patch +ApplyPatch mac80211-zero-initialize-count-field-in-ieee80211_tx.patch +ApplyPatch mac80211-Fix-a-warning-on-changing-to-monitor-mode-f.patch +ApplyPatch brcm80211-smac-fix-endless-retry-of-A-MPDU-transmiss.patch +ApplyPatch brcm80211-smac-only-print-block-ack-timeout-message-.patch ApplyPatch rt2x00_fix_MCU_request_failures.patch @@ -2346,6 +2368,19 @@ fi # and build. %changelog +* Fri Feb 24 2012 John W. Linville +- mac80211: call rate control only after init +- mac80211: do not call rate control .tx_status before .rate_init +- mwifiex: clear previous security setting during association +- ath9k: stop on rates with idx -1 in ath9k rate control's .tx_status +- ath9k_hw: prevent writes to const data on AR9160 +- rt2x00: fix a possible NULL pointer dereference +- iwlwifi: fix key removal +- mac80211: zero initialize count field in ieee80211_tx_rate +- mac80211: Fix a warning on changing to monitor mode from STA +- brcm80211: smac: fix endless retry of A-MPDU transmissions +- brcm80211: smac: only print block-ack timeout message at trace level + * Mon Feb 20 2012 Dave Jones 3.2.7-1 - Do not call drivers when invalidating partitions for -ENOMEDIUM diff --git a/mac80211-Fix-a-warning-on-changing-to-monitor-mode-f.patch b/mac80211-Fix-a-warning-on-changing-to-monitor-mode-f.patch new file mode 100644 index 000000000..421bd9323 --- /dev/null +++ b/mac80211-Fix-a-warning-on-changing-to-monitor-mode-f.patch @@ -0,0 +1,72 @@ +From 0dee00686da88cc32753e02e4e8efdd9e326e4d2 Mon Sep 17 00:00:00 2001 +From: Mohammed Shafi Shajakhan +Date: Mon, 20 Feb 2012 14:44:01 +0530 +Subject: [PATCH] mac80211: Fix a warning on changing to monitor mode from STA + +nothing needs to be done for monitor/AP_VLAN mode on calling +ieee80211_bss_info_change_notify -> drv_bss_info_changed with the change +flag 'BSS_CHANGED_IDLE'. 'wl1271' seems to use BSS_CHANGED_IDLE only for +STA and IBSS mode. further the non-idle state of the monitor mode is +taken care by the 'count' variable which counts non-idle interfaces. +ieee80211_idle_off(local, "in use") will be called. +this fixes the following WARNING when we have initially STA mode +(network manager running) and not associated, and change it to monitor +mode with network manager disabled and bringing up the monitor mode. +this changes the idle state from 'true' (STA unassociated) to 'false' +(MONITOR mode) +exposed by the commit 405385f8ce7a2ed8f82e216d88b5282142e1288b +"mac80211: set bss_conf.idle when vif is connected" + + WARNING: net/mac80211/main.c:212 + ieee80211_bss_info_change_notify+0x1cf/0x330 [mac80211]() + Hardware name: 64756D6 + Pid: 3835, comm: ifconfig Tainted: G O + 3.3.0-rc3-wl #9 + Call Trace: + [] warn_slowpath_common+0x72/0xa0 + [] ? + ieee80211_bss_info_change_notify+0x1cf/0x330 [mac80211] + [] ? + ieee80211_bss_info_change_notify+0x1cf/0x330 [mac80211] + [] warn_slowpath_null+0x22/0x30 + [] + ieee80211_bss_info_change_notify+0x1cf/0x330 [mac80211] + [] __ieee80211_recalc_idle+0x113/0x430 + [mac80211] + [] ieee80211_do_open+0x156/0x7e0 [mac80211] + [] ? + ieee80211_check_concurrent_iface+0x25/0x180 [mac80211] + [] ? raw_notifier_call_chain+0x1f/0x30 + [] ieee80211_open+0x40/0x80 [mac80211] + [] __dev_open+0x96/0xe0 + [] ? _raw_spin_unlock_bh+0x35/0x40 + [] __dev_change_flags+0x109/0x170 + [] dev_change_flags+0x23/0x60 + [] devinet_ioctl+0x6a0/0x770 + + ieee80211 phy0: device no longer idle - in use + +Cc: Eliad Peller +Signed-off-by: Mohammed Shafi Shajakhan +Signed-off-by: John W. Linville +--- + net/mac80211/iface.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 01a21c2..8e2137b 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -1332,6 +1332,9 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) + hw_roc = true; + + list_for_each_entry(sdata, &local->interfaces, list) { ++ if (sdata->vif.type == NL80211_IFTYPE_MONITOR || ++ sdata->vif.type == NL80211_IFTYPE_AP_VLAN) ++ continue; + if (sdata->old_idle == sdata->vif.bss_conf.idle) + continue; + if (!ieee80211_sdata_running(sdata)) +-- +1.7.4.4 + diff --git a/mac80211-call-rate-control-only-after-init.patch b/mac80211-call-rate-control-only-after-init.patch new file mode 100644 index 000000000..16fdda166 --- /dev/null +++ b/mac80211-call-rate-control-only-after-init.patch @@ -0,0 +1,91 @@ +From 4b5a433ae5348c23caa0b5f0a2fca7c342acb200 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 20 Jan 2012 13:55:23 +0100 +Subject: [PATCH] mac80211: call rate control only after init + +There are situations where we don't have the +necessary rate control information yet for +station entries, e.g. when associating. This +currently doesn't really happen due to the +dummy station handling; explicitly disabling +rate control when it's not initialised will +allow us to remove dummy stations. + +Signed-off-by: Johannes Berg +Signed-off-by: John W. Linville +--- + net/mac80211/debugfs_sta.c | 4 ++-- + net/mac80211/rate.c | 2 +- + net/mac80211/rate.h | 1 + + net/mac80211/sta_info.h | 2 ++ + 4 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c +index 2406b3e..d86217d 100644 +--- a/net/mac80211/debugfs_sta.c ++++ b/net/mac80211/debugfs_sta.c +@@ -63,14 +63,14 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, + test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" + + int res = scnprintf(buf, sizeof(buf), +- "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", ++ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + TEST(AUTH), TEST(ASSOC), TEST(PS_STA), + TEST(PS_DRIVER), TEST(AUTHORIZED), + TEST(SHORT_PREAMBLE), + TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT), + TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), + TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), +- TEST(TDLS_PEER_AUTH)); ++ TEST(TDLS_PEER_AUTH), TEST(RATE_CONTROL)); + #undef TEST + return simple_read_from_buffer(userbuf, count, ppos, buf, res); + } +diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c +index 5a5a776..ad64f4d 100644 +--- a/net/mac80211/rate.c ++++ b/net/mac80211/rate.c +@@ -336,7 +336,7 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, + int i; + u32 mask; + +- if (sta) { ++ if (sta && test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) { + ista = &sta->sta; + priv_sta = sta->rate_ctrl_priv; + } +diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h +index 168427b..2b83f32 100644 +--- a/net/mac80211/rate.h ++++ b/net/mac80211/rate.h +@@ -62,6 +62,7 @@ static inline void rate_control_rate_init(struct sta_info *sta) + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + + ref->ops->rate_init(ref->priv, sband, ista, priv_sta); ++ set_sta_flag(sta, WLAN_STA_RATE_CONTROL); + } + + static inline void rate_control_rate_update(struct ieee80211_local *local, +diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h +index 6f77f12..bfed851 100644 +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -52,6 +52,7 @@ + * @WLAN_STA_SP: Station is in a service period, so don't try to + * reply to other uAPSD trigger frames or PS-Poll. + * @WLAN_STA_4ADDR_EVENT: 4-addr event was already sent for this frame. ++ * @WLAN_STA_RATE_CONTROL: rate control was initialized for this station. + */ + enum ieee80211_sta_info_flags { + WLAN_STA_AUTH, +@@ -71,6 +72,7 @@ enum ieee80211_sta_info_flags { + WLAN_STA_UAPSD, + WLAN_STA_SP, + WLAN_STA_4ADDR_EVENT, ++ WLAN_STA_RATE_CONTROL, + }; + + enum ieee80211_sta_state { +-- +1.7.4.4 + diff --git a/mac80211-do-not-call-rate-control-.tx_status-before-.patch b/mac80211-do-not-call-rate-control-.tx_status-before-.patch new file mode 100644 index 000000000..28343b342 --- /dev/null +++ b/mac80211-do-not-call-rate-control-.tx_status-before-.patch @@ -0,0 +1,33 @@ +From 216c57b214bd621335ff698b475f6db2802502dc Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Wed, 8 Feb 2012 19:17:11 +0100 +Subject: [PATCH] mac80211: do not call rate control .tx_status before + .rate_init + +Most rate control implementations assume .get_rate and .tx_status are only +called once the per-station data has been fully initialized. +minstrel_ht crashes if this assumption is violated. + +Signed-off-by: Felix Fietkau +Tested-by: Arend van Spriel +Signed-off-by: John W. Linville +--- + net/mac80211/rate.h | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h +index 2b83f32..80cfc00 100644 +--- a/net/mac80211/rate.h ++++ b/net/mac80211/rate.h +@@ -41,7 +41,7 @@ static inline void rate_control_tx_status(struct ieee80211_local *local, + struct ieee80211_sta *ista = &sta->sta; + void *priv_sta = sta->rate_ctrl_priv; + +- if (!ref) ++ if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) + return; + + ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); +-- +1.7.4.4 + diff --git a/mac80211-zero-initialize-count-field-in-ieee80211_tx.patch b/mac80211-zero-initialize-count-field-in-ieee80211_tx.patch new file mode 100644 index 000000000..4b0ec167c --- /dev/null +++ b/mac80211-zero-initialize-count-field-in-ieee80211_tx.patch @@ -0,0 +1,39 @@ +From 8617b093d0031837a7be9b32bc674580cfb5f6b5 Mon Sep 17 00:00:00 2001 +From: Mohammed Shafi Shajakhan +Date: Mon, 20 Feb 2012 10:05:31 +0530 +Subject: [PATCH] mac80211: zero initialize count field in ieee80211_tx_rate + +rate control algorithms concludes the rate as invalid +with rate[i].idx < -1 , while they do also check for rate[i].count is +non-zero. it would be safer to zero initialize the 'count' field. +recently we had a ath9k rate control crash where the ath9k rate control +in ath_tx_status assumed to check only for rate[i].count being non-zero +in one instance and ended up in using invalid rate index for +'connection monitoring NULL func frames' which eventually lead to the crash. +thanks to Pavel Roskin for fixing it and finding the root cause. +https://bugzilla.redhat.com/show_bug.cgi?id=768639 + +Cc: stable@vger.kernel.org +Cc: Pavel Roskin +Signed-off-by: Mohammed Shafi Shajakhan +Signed-off-by: John W. Linville +--- + net/mac80211/rate.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c +index ad64f4d..f9b8e81 100644 +--- a/net/mac80211/rate.c ++++ b/net/mac80211/rate.c +@@ -344,7 +344,7 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { + info->control.rates[i].idx = -1; + info->control.rates[i].flags = 0; +- info->control.rates[i].count = 1; ++ info->control.rates[i].count = 0; + } + + if (sdata->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) +-- +1.7.4.4 + diff --git a/mwifiex-clear-previous-security-setting-during-assoc.patch b/mwifiex-clear-previous-security-setting-during-assoc.patch new file mode 100644 index 000000000..f3fa7cb2b --- /dev/null +++ b/mwifiex-clear-previous-security-setting-during-assoc.patch @@ -0,0 +1,55 @@ +From 6670f15b1f6858a43b292d8ab64464e9f085a6aa Mon Sep 17 00:00:00 2001 +From: Amitkumar Karwar +Date: Thu, 9 Feb 2012 18:32:22 -0800 +Subject: [PATCH] mwifiex: clear previous security setting during association + +Driver maintains different flags for WEP, WPA, WPA2 security modes. +Appropriate flag is set using security information provided in +connect request. mwifiex_is_network_compatible() routine uses them +to check if driver's setting is compatible with AP. Association is +aborted if the routine fails. + +For some corner cases, it is observed that association is failed +even for valid security information based on association history. +This patch fixes the problem by clearing previous security setting +during each association. + +We should set WEP key provided in connect request as default tx key. +This missing change is also added here. + +Signed-off-by: Amitkumar Karwar +Signed-off-by: Bing Zhao +Signed-off-by: John W. Linville +--- + drivers/net/wireless/mwifiex/cfg80211.c | 8 +++++++- + 1 files changed, 7 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c +index c3b6c46..5b2972b 100644 +--- a/drivers/net/wireless/mwifiex/cfg80211.c ++++ b/drivers/net/wireless/mwifiex/cfg80211.c +@@ -841,7 +841,12 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, + ret = mwifiex_set_rf_channel(priv, channel, + priv->adapter->channel_type); + +- ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); /* Disable keys */ ++ /* As this is new association, clear locally stored ++ * keys and security related flags */ ++ priv->sec_info.wpa_enabled = false; ++ priv->sec_info.wpa2_enabled = false; ++ priv->wep_key_curr_index = 0; ++ ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); + + if (mode == NL80211_IFTYPE_ADHOC) { + /* "privacy" is set only for ad-hoc mode */ +@@ -886,6 +891,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, + dev_dbg(priv->adapter->dev, + "info: setting wep encryption" + " with key len %d\n", sme->key_len); ++ priv->wep_key_curr_index = sme->key_idx; + ret = mwifiex_set_encode(priv, sme->key, sme->key_len, + sme->key_idx, 0); + } +-- +1.7.4.4 + diff --git a/rt2x00-fix-a-possible-NULL-pointer-dereference.patch b/rt2x00-fix-a-possible-NULL-pointer-dereference.patch new file mode 100644 index 000000000..8158bcb89 --- /dev/null +++ b/rt2x00-fix-a-possible-NULL-pointer-dereference.patch @@ -0,0 +1,37 @@ +From 7be081539e540517d5e1fcbf96b8080074afbf08 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Thu, 16 Feb 2012 20:44:59 +0100 +Subject: [PATCH] rt2x00: fix a possible NULL pointer dereference + +The 'rt2x00lib_probe_dev' function tries to +allocate the workqueue. If the allocation +fails, 'rt2x00_lib_remove_dev' is called on +the error path. Because 'rt2x00dev->workqueue' +is NULL in this case, the 'destroy_workqueue' +call will cause a NULL pointer dereference. + +Signed-off-by: Gabor Juhos +Acked-by: Gertjan van Wingerde +Acked-by: Ivo van Doorn +Signed-off-by: John W. Linville +--- + drivers/net/wireless/rt2x00/rt2x00dev.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c +index c3e1aa7..d2a1ea9 100644 +--- a/drivers/net/wireless/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c +@@ -1220,7 +1220,8 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) + cancel_work_sync(&rt2x00dev->rxdone_work); + cancel_work_sync(&rt2x00dev->txdone_work); + } +- destroy_workqueue(rt2x00dev->workqueue); ++ if (rt2x00dev->workqueue) ++ destroy_workqueue(rt2x00dev->workqueue); + + /* + * Free the tx status fifo. +-- +1.7.4.4 + From 9fbab193124cbc8fe814548eb8bd1b4a544d63e3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 27 Feb 2012 13:57:05 -0500 Subject: [PATCH 285/487] Add patch to fix regression in FADT revision checks (rhbz 730007 727865) --- ...x-regression-in-FADT-revision-checks.patch | 58 +++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 ACPICA-Fix-regression-in-FADT-revision-checks.patch diff --git a/ACPICA-Fix-regression-in-FADT-revision-checks.patch b/ACPICA-Fix-regression-in-FADT-revision-checks.patch new file mode 100644 index 000000000..d6b590389 --- /dev/null +++ b/ACPICA-Fix-regression-in-FADT-revision-checks.patch @@ -0,0 +1,58 @@ + commit 64b3db22c04586997ab4be46dd5a5b99f8a2d390 (2.6.39), +"Remove use of unreliable FADT revision field" causes regression +for old P4 systems because now cst_control and other fields are +not reset to 0. + + The effect is that acpi_processor_power_init will notice +cst_control != 0 and a write to CST_CNT register is performed +that should not happen. As result, the system oopses after the +"No _CST, giving up" message, sometimes in acpi_ns_internalize_name, +sometimes in acpi_ns_get_type, usually at random places. May be +during migration to CPU 1 in acpi_processor_get_throttling. + + Every one of these settings help to avoid this problem: + - acpi=off + - processor.nocst=1 + - maxcpus=1 + + The fix is to update acpi_gbl_FADT.header.length after +the original value is used to check for old revisions. + +Signed-off-by: Julian Anastasov +--- + drivers/acpi/acpica/tbfadt.c | 8 ++++---- + 1 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c +index c5d8704..4c9c760 100644 +--- a/drivers/acpi/acpica/tbfadt.c ++++ b/drivers/acpi/acpica/tbfadt.c +@@ -363,10 +363,6 @@ static void acpi_tb_convert_fadt(void) + u32 address32; + u32 i; + +- /* Update the local FADT table header length */ +- +- acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); +- + /* + * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary. + * Later code will always use the X 64-bit field. Also, check for an +@@ -408,6 +404,10 @@ static void acpi_tb_convert_fadt(void) + acpi_gbl_FADT.boot_flags = 0; + } + ++ /* Update the local FADT table header length */ ++ ++ acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); ++ + /* + * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" + * generic address structures as necessary. Later code will always use +-- +1.7.3.4 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-acpi" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index 15fded651..39bb0935f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -857,6 +857,9 @@ Patch50133: mac80211-Fix-a-warning-on-changing-to-monitor-mode-f.patch Patch50134: brcm80211-smac-fix-endless-retry-of-A-MPDU-transmiss.patch Patch50135: brcm80211-smac-only-print-block-ack-timeout-message-.patch +#rhbz 727865 730007 +Patch21102: ACPICA-Fix-regression-in-FADT-revision-checks.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1552,6 +1555,9 @@ ApplyPatch scsi-fix-sd_revalidate_disk-oops.patch #rhbz 790367 ApplyPatch s390x-enable-keys-compat.patch +#rhbz 727865 730007 +ApplyPatch ACPICA-Fix-regression-in-FADT-revision-checks.patch + # END OF PATCH APPLICATIONS %endif @@ -2368,6 +2374,9 @@ fi # and build. %changelog +* Mon Feb 27 2012 Josh Boyer +- Add patch to fix regression in FADT revision checks (rhbz 730007 727865) + * Fri Feb 24 2012 John W. Linville - mac80211: call rate control only after init - mac80211: do not call rate control .tx_status before .rate_init From e14b40bbbddffe789b3dbff0c6912c8ff0e629ab Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 27 Feb 2012 16:18:04 -0500 Subject: [PATCH 286/487] Linux 3.2.8 --- kernel.spec | 7 ++- linux-2.6-i386-nx-emulation.patch | 98 ++++++++++++++++++++----------- sources | 2 +- 3 files changed, 70 insertions(+), 37 deletions(-) diff --git a/kernel.spec b/kernel.spec index 39bb0935f..26fc66ce4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 7 +%define stable_update 8 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2374,6 +2374,9 @@ fi # and build. %changelog +* Mon Feb 27 2012 Josh Boyer 3.2.8-1 +- Linux 3.2.8 + * Mon Feb 27 2012 Josh Boyer - Add patch to fix regression in FADT revision checks (rhbz 730007 727865) diff --git a/linux-2.6-i386-nx-emulation.patch b/linux-2.6-i386-nx-emulation.patch index 07a0faec8..d97d52999 100644 --- a/linux-2.6-i386-nx-emulation.patch +++ b/linux-2.6-i386-nx-emulation.patch @@ -1,3 +1,5 @@ +diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h +index 41935fa..6e9259b 100644 --- a/arch/x86/include/asm/desc.h +++ b/arch/x86/include/asm/desc.h @@ -5,6 +5,7 @@ @@ -44,6 +46,8 @@ +#endif /* CONFIG_X86_32 */ + #endif /* _ASM_X86_DESC_H */ +diff --git a/arch/x86/include/asm/mmu.h b/arch/x86/include/asm/mmu.h +index 5f55e69..aba94f0 100644 --- a/arch/x86/include/asm/mmu.h +++ b/arch/x86/include/asm/mmu.h @@ -7,6 +7,9 @@ @@ -68,9 +72,11 @@ } mm_context_t; #ifdef CONFIG_SMP +diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h +index a7d2db9..cc4ad60 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h -@@ -289,6 +289,12 @@ static inline void set_ldt(const void *addr, unsigned entries) +@@ -298,6 +298,12 @@ static inline void set_ldt(const void *addr, unsigned entries) { PVOP_VCALL2(pv_cpu_ops.set_ldt, addr, entries); } @@ -83,9 +89,11 @@ static inline void store_gdt(struct desc_ptr *dtr) { PVOP_VCALL1(pv_cpu_ops.store_gdt, dtr); +diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h +index 8e8b9a4..cca421e 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h -@@ -118,6 +118,9 @@ struct pv_cpu_ops { +@@ -125,6 +125,9 @@ struct pv_cpu_ops { void (*store_gdt)(struct desc_ptr *); void (*store_idt)(struct desc_ptr *); void (*set_ldt)(const void *desc, unsigned entries); @@ -95,9 +103,11 @@ unsigned long (*store_tr)(void); void (*load_tls)(struct thread_struct *t, unsigned int cpu); #ifdef CONFIG_X86_64 +diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c +index aa003b1..c094152 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c -@@ -802,6 +802,22 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) +@@ -844,6 +844,22 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) /* Filter out anything that depends on CPUID levels we don't have */ filter_cpuid_features(c, true); @@ -120,9 +130,11 @@ /* If the model name is still unset, do table lookup. */ if (!c->x86_model_id[0]) { const char *p; +diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c +index d90272e..cc594fc 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c -@@ -345,6 +345,9 @@ struct pv_cpu_ops pv_cpu_ops = { +@@ -358,6 +358,9 @@ struct pv_cpu_ops pv_cpu_ops = { .read_tscp = native_read_tscp, .load_tr_desc = native_load_tr_desc, .set_ldt = native_set_ldt, @@ -132,9 +144,11 @@ .load_gdt = native_load_gdt, .load_idt = native_load_idt, .store_gdt = native_store_gdt, +diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c +index 8598296..641ae48 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c -@@ -243,7 +243,10 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, +@@ -247,7 +247,10 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, void start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) { @@ -145,7 +159,7 @@ regs->fs = 0; regs->ds = __USER_DS; regs->es = __USER_DS; -@@ -252,6 +255,11 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) +@@ -255,6 +258,11 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) regs->cs = __USER_CS; regs->ip = new_ip; regs->sp = new_sp; @@ -157,17 +171,17 @@ /* * Free the old FP and other extended state */ -@@ -311,6 +319,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) - if (preload_fpu) - prefetch(next->fpu.state); +@@ -320,6 +328,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) + */ + lazy_save_gs(prev->gs); + if (next_p->mm) + load_user_cs_desc(cpu, next_p->mm); + /* - * Reload esp0. + * Load the per-thread Thread-Local Storage descriptor. */ -@@ -404,3 +415,40 @@ unsigned long get_wchan(struct task_struct *p) +@@ -390,3 +401,40 @@ unsigned long get_wchan(struct task_struct *p) return 0; } @@ -208,9 +222,11 @@ + mm->context.exec_limit = 0; + set_user_cs(&mm->context.user_cs, 0); +} +diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c +index 31d9d0f..f7c210d 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c -@@ -109,6 +109,78 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) +@@ -107,6 +107,78 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) dec_preempt_count(); } @@ -289,7 +305,7 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, long error_code, siginfo_t *info) -@@ -265,6 +337,29 @@ do_general_protection(struct pt_regs *regs, long error_code) +@@ -263,6 +335,29 @@ do_general_protection(struct pt_regs *regs, long error_code) if (!user_mode(regs)) goto gp_in_kernel; @@ -319,7 +335,7 @@ tsk->thread.error_code = error_code; tsk->thread.trap_no = 13; -@@ -792,19 +887,37 @@ do_device_not_available(struct pt_regs *regs, long error_code) +@@ -649,19 +744,37 @@ do_device_not_available(struct pt_regs *regs, long error_code) } #ifdef CONFIG_X86_32 @@ -366,6 +382,8 @@ } #endif +diff --git a/arch/x86/mm/setup_nx.c b/arch/x86/mm/setup_nx.c +index 410531d..eb040ad 100644 --- a/arch/x86/mm/setup_nx.c +++ b/arch/x86/mm/setup_nx.c @@ -1,3 +1,4 @@ @@ -373,16 +391,16 @@ #include #include #include -@@ -6,7 +6,7 @@ +@@ -5,7 +6,7 @@ #include #include - + -static int disable_nx __cpuinitdata; +int disable_nx __cpuinitdata; - + /* * noexec = on|off -@@ -40,6 +42,10 @@ void __cpuinit x86_configure_nx(void) +@@ -40,6 +41,10 @@ void __cpuinit x86_configure_nx(void) void __init x86_report_nx(void) { if (!cpu_has_nx) { @@ -393,9 +411,11 @@ printk(KERN_NOTICE "Notice: NX (Execute Disable) protection " "missing in CPU!\n"); } else { +diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c +index d6c0418..c15b765 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c -@@ -6,6 +6,7 @@ +@@ -7,6 +7,7 @@ #include #include @@ -403,7 +423,7 @@ #include #include #include -@@ -131,6 +132,12 @@ void smp_invalidate_interrupt(struct pt_regs *regs) +@@ -134,6 +135,12 @@ void smp_invalidate_interrupt(struct pt_regs *regs) union smp_flush_state *f; cpu = smp_processor_id(); @@ -416,9 +436,11 @@ /* * orig_rax contains the negated interrupt vector. * Use that to determine where the sender put the data. +diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c +index 1f92865..b8f4319 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c -@@ -335,6 +335,24 @@ static void xen_set_ldt(const void *addr, unsigned entries) +@@ -354,6 +354,24 @@ static void xen_set_ldt(const void *addr, unsigned entries) xen_mc_issue(PARAVIRT_LAZY_CPU); } @@ -443,7 +465,7 @@ static void xen_load_gdt(const struct desc_ptr *dtr) { unsigned long va = dtr->address; -@@ -961,6 +979,9 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = { +@@ -994,6 +1012,9 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { .load_tr_desc = paravirt_nop, .set_ldt = xen_set_ldt, @@ -453,9 +475,11 @@ .load_gdt = xen_load_gdt, .load_idt = xen_load_idt, .load_tls = xen_load_tls, +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index 21ac5ee..3f26963 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c -@@ -717,6 +722,15 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) +@@ -711,6 +711,15 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) if (retval) goto out_free_dentry; @@ -471,9 +495,11 @@ /* OK, This is the point of no return */ current->flags &= ~PF_FORKNOEXEC; current->mm->def_flags = def_flags; +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 1c4f3e9..52011a7 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h -@@ -101,6 +101,9 @@ struct bio_list; +@@ -102,6 +102,9 @@ struct fs_struct; struct perf_event_context; struct blk_plug; @@ -483,9 +509,11 @@ /* * List of flags we want to share for kernel threads, * if only because they are not used by them anyway. ---- b/mm/mmap.c +diff --git a/mm/mmap.c b/mm/mmap.c +index eae90af..f4de6c0 100644 +--- a/mm/mmap.c +++ b/mm/mmap.c -@@ -44,6 +45,18 @@ +@@ -46,6 +46,18 @@ #define arch_rebalance_pgtables(addr, len) (addr) #endif @@ -504,7 +532,7 @@ static void unmap_region(struct mm_struct *mm, struct vm_area_struct *vma, struct vm_area_struct *prev, unsigned long start, unsigned long end); -@@ -432,6 +432,8 @@ __vma_link(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -424,6 +436,8 @@ __vma_link(struct mm_struct *mm, struct vm_area_struct *vma, struct vm_area_struct *prev, struct rb_node **rb_link, struct rb_node *rb_parent) { @@ -513,7 +541,7 @@ __vma_link_list(mm, vma, prev, rb_parent); __vma_link_rb(mm, vma, rb_link, rb_parent); } -@@ -489,6 +504,8 @@ +@@ -478,6 +492,8 @@ __vma_unlink(struct mm_struct *mm, struct vm_area_struct *vma, rb_erase(&vma->vm_rb, &mm->mm_rb); if (mm->mmap_cache == vma) mm->mmap_cache = prev; @@ -522,7 +550,7 @@ } /* -@@ -790,6 +807,8 @@ +@@ -794,6 +810,8 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm, } else /* cases 2, 5, 7 */ err = vma_adjust(prev, prev->vm_start, end, prev->vm_pgoff, NULL); @@ -530,8 +558,8 @@ + arch_add_exec_range(mm, prev->vm_end); if (err) return NULL; - return prev; -@@ -1966,10 +2075,14 @@ + khugepaged_enter_vma_merge(prev); +@@ -1972,10 +1990,14 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, if (new->vm_ops && new->vm_ops->open) new->vm_ops->open(new); @@ -548,7 +576,7 @@ err = vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new); /* Success. */ -@@ -2254,6 +2367,7 @@ +@@ -2263,6 +2285,7 @@ void exit_mmap(struct mm_struct *mm) free_pgtables(&tlb, vma, FIRST_USER_ADDRESS, 0); tlb_finish_mmu(&tlb, 0, end); @@ -556,6 +584,8 @@ /* * Walk the list again, actually closing and freeing it, +diff --git a/mm/mprotect.c b/mm/mprotect.c +index 5a688a2..128d996 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -25,9 +25,14 @@ @@ -573,7 +603,7 @@ #ifndef pgprot_modify static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot) { -@@ -138,7 +143,7 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, +@@ -148,7 +153,7 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, struct mm_struct *mm = vma->vm_mm; unsigned long oldflags = vma->vm_flags; long nrpages = (end - start) >> PAGE_SHIFT; @@ -582,7 +612,7 @@ pgoff_t pgoff; int error; int dirty_accountable = 0; -@@ -203,6 +208,9 @@ success: +@@ -213,6 +218,9 @@ success: dirty_accountable = 1; } diff --git a/sources b/sources index 6a79988da..6a9fe0d7e 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz 8cfe037a7a7a356278ec3638e25ad506 compat-wireless-3.3-rc1-2.tar.bz2 -e507fce2c266549df9565172196c912d patch-3.2.7.xz +417b97cdd9e8b2664eb31260dbbcdc72 patch-3.2.8.xz From 8a8688b23133d69b86dc259c212a90786eee4a15 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 28 Feb 2012 11:34:10 -0600 Subject: [PATCH 287/487] CVE-2012-1090 CIFS: fix dentry refcount leak when opening a FIFO on lookup (rhbz 798296) --- ...ry-refcount-leak-when-opening-a-FIFO.patch | 61 +++++++++++++++++++ kernel.spec | 9 ++- 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch diff --git a/cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch b/cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch new file mode 100644 index 000000000..9fd87acac --- /dev/null +++ b/cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch @@ -0,0 +1,61 @@ +From 5bccda0ebc7c0331b81ac47d39e4b920b198b2cd Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Thu, 23 Feb 2012 09:37:45 -0500 +Subject: [PATCH] cifs: fix dentry refcount leak when opening a FIFO on lookup + +The cifs code will attempt to open files on lookup under certain +circumstances. What happens though if we find that the file we opened +was actually a FIFO or other special file? + +Currently, the open filehandle just ends up being leaked leading to +a dentry refcount mismatch and oops on umount. Fix this by having the +code close the filehandle on the server if it turns out not to be a +regular file. While we're at it, change this spaghetti if statement +into a switch too. + +Cc: stable@vger.kernel.org +Reported-by: CAI Qian +Tested-by: CAI Qian +Reviewed-by: Shirish Pargaonkar +Signed-off-by: Jeff Layton +Signed-off-by: Steve French +--- + fs/cifs/dir.c | 20 ++++++++++++++++++-- + 1 files changed, 18 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c +index 63a196b..bc7e244 100644 +--- a/fs/cifs/dir.c ++++ b/fs/cifs/dir.c +@@ -584,10 +584,26 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, + * If either that or op not supported returned, follow + * the normal lookup. + */ +- if ((rc == 0) || (rc == -ENOENT)) ++ switch (rc) { ++ case 0: ++ /* ++ * The server may allow us to open things like ++ * FIFOs, but the client isn't set up to deal ++ * with that. If it's not a regular file, just ++ * close it and proceed as if it were a normal ++ * lookup. ++ */ ++ if (newInode && !S_ISREG(newInode->i_mode)) { ++ CIFSSMBClose(xid, pTcon, fileHandle); ++ break; ++ } ++ case -ENOENT: + posix_open = true; +- else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP)) ++ case -EOPNOTSUPP: ++ break; ++ default: + pTcon->broken_posix_open = true; ++ } + } + if (!posix_open) + rc = cifs_get_inode_info_unix(&newInode, full_path, +-- +1.7.0.4 + diff --git a/kernel.spec b/kernel.spec index 26fc66ce4..9b604263e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -856,6 +856,7 @@ Patch50132: mac80211-zero-initialize-count-field-in-ieee80211_tx.patch Patch50133: mac80211-Fix-a-warning-on-changing-to-monitor-mode-f.patch Patch50134: brcm80211-smac-fix-endless-retry-of-A-MPDU-transmiss.patch Patch50135: brcm80211-smac-only-print-block-ack-timeout-message-.patch +Patch50136: cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch #rhbz 727865 730007 Patch21102: ACPICA-Fix-regression-in-FADT-revision-checks.patch @@ -1558,6 +1559,9 @@ ApplyPatch s390x-enable-keys-compat.patch #rhbz 727865 730007 ApplyPatch ACPICA-Fix-regression-in-FADT-revision-checks.patch +#rhbz 798296 +ApplyPatch cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch + # END OF PATCH APPLICATIONS %endif @@ -2374,6 +2378,9 @@ fi # and build. %changelog +* Tue Feb 28 2012 Justin M. Forbes 3.2.8-2 +- CVE-2012-1090 CIFS: fix dentry refcount leak when opening a FIFO on lookup (rhbz 798296) + * Mon Feb 27 2012 Josh Boyer 3.2.8-1 - Linux 3.2.8 From f9a06c1afbda06fc5205aa338d5af0a2a5646d68 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 28 Feb 2012 15:31:26 -0500 Subject: [PATCH 288/487] Add patch to enable keyboard backlight on Sony laptops (rhbz 728478) --- kernel.spec | 19 ++++++-- ...Enable-keyboard-backlight-by-default.patch | 44 +++++++++++++++++++ 2 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 sony-laptop-Enable-keyboard-backlight-by-default.patch diff --git a/kernel.spec b/kernel.spec index 9b604263e..2b0a9d81c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -815,6 +815,14 @@ Patch21235: scsi-fix-sd_revalidate_disk-oops.patch #rhbz 790367 Patch21239: s390x-enable-keys-compat.patch +#rhbz 727865 730007 +Patch21240: ACPICA-Fix-regression-in-FADT-revision-checks.patch + +Patch21241: cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch + +#rhbz 728478 +Patch21242: sony-laptop-Enable-keyboard-backlight-by-default.patch + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-pr_fmt-warning-avoidance.patch @@ -856,10 +864,7 @@ Patch50132: mac80211-zero-initialize-count-field-in-ieee80211_tx.patch Patch50133: mac80211-Fix-a-warning-on-changing-to-monitor-mode-f.patch Patch50134: brcm80211-smac-fix-endless-retry-of-A-MPDU-transmiss.patch Patch50135: brcm80211-smac-only-print-block-ack-timeout-message-.patch -Patch50136: cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch -#rhbz 727865 730007 -Patch21102: ACPICA-Fix-regression-in-FADT-revision-checks.patch %endif @@ -1562,6 +1567,9 @@ ApplyPatch ACPICA-Fix-regression-in-FADT-revision-checks.patch #rhbz 798296 ApplyPatch cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch +#rhbz 728478 +ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch + # END OF PATCH APPLICATIONS %endif @@ -2378,6 +2386,9 @@ fi # and build. %changelog +* Tue Feb 28 2012 Josh Boyer 3.2.8-3 +- Add patch to enable keyboard backlight on Sony laptops (rhbz 728478) + * Tue Feb 28 2012 Justin M. Forbes 3.2.8-2 - CVE-2012-1090 CIFS: fix dentry refcount leak when opening a FIFO on lookup (rhbz 798296) diff --git a/sony-laptop-Enable-keyboard-backlight-by-default.patch b/sony-laptop-Enable-keyboard-backlight-by-default.patch new file mode 100644 index 000000000..c993fd86d --- /dev/null +++ b/sony-laptop-Enable-keyboard-backlight-by-default.patch @@ -0,0 +1,44 @@ +From 0dbc2bc96b1ec741bdd43451c286ccd45da3310b Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Wed, 2 Nov 2011 14:31:59 -0400 +Subject: [PATCH] sony-laptop: Enable keyboard backlight by default + +When the keyboard backlight support was originally added, the commit said +to default it to on with a 10 second timeout. That actually wasn't the +case, as the default value is commented out for the kbd_backlight parameter. +Because it is a static variable, it gets set to 0 by default without some +other form of initialization. + +However, it seems the function to set the value wasn't actually called +immediately, so whatever state the keyboard was in initially would remain. +Then commit df410d522410e67660 was introduced during the 2.6.39 timeframe to +immediately set whatever value was present (as well as attempt to +restore/reset the state on module removal or resume). That seems to have +now forced the light off immediately when the module is loaded unless +the option kbd_backlight=1 is specified. + +Let's enable it by default again (for the first time). This should solve +https://bugzilla.redhat.com/show_bug.cgi?id=728478 + +Acked-by: Mattia Dongili +Signed-off-by: Josh Boyer +--- + drivers/platform/x86/sony-laptop.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c +index c006dee..40c4705 100644 +--- a/drivers/platform/x86/sony-laptop.c ++++ b/drivers/platform/x86/sony-laptop.c +@@ -127,7 +127,7 @@ MODULE_PARM_DESC(minor, + "default is -1 (automatic)"); + #endif + +-static int kbd_backlight; /* = 1 */ ++static int kbd_backlight = 1; + module_param(kbd_backlight, int, 0444); + MODULE_PARM_DESC(kbd_backlight, + "set this to 0 to disable keyboard backlight, " +-- +1.7.7.6 + From bb1d90cb35db20403f6c6533b57a57f58f87db01 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 29 Feb 2012 20:24:52 -0500 Subject: [PATCH 289/487] Linux 3.2.9 --- epoll-limit-paths.patch | 465 ---------------------------------------- kernel.spec | 15 +- nfs-oops-getacl.patch | 96 --------- sources | 2 +- utrace.patch | 4 +- 5 files changed, 8 insertions(+), 574 deletions(-) delete mode 100644 epoll-limit-paths.patch delete mode 100644 nfs-oops-getacl.patch diff --git a/epoll-limit-paths.patch b/epoll-limit-paths.patch deleted file mode 100644 index 4ed306af4..000000000 --- a/epoll-limit-paths.patch +++ /dev/null @@ -1,465 +0,0 @@ -From 0a6cc45426fe3baaf231efd7efe4300fd879efc8 Mon Sep 17 00:00:00 2001 -From: Jason Baron -Date: Mon, 24 Oct 2011 14:59:02 +1100 -Subject: [PATCH] epoll: limit paths - -epoll: limit paths - -The current epoll code can be tickled to run basically indefinitely in -both loop detection path check (on ep_insert()), and in the wakeup paths. -The programs that tickle this behavior set up deeply linked networks of -epoll file descriptors that cause the epoll algorithms to traverse them -indefinitely. A couple of these sample programs have been previously -posted in this thread: https://lkml.org/lkml/2011/2/25/297. - -To fix the loop detection path check algorithms, I simply keep track of -the epoll nodes that have been already visited. Thus, the loop detection -becomes proportional to the number of epoll file descriptor and links. -This dramatically decreases the run-time of the loop check algorithm. In -one diabolical case I tried it reduced the run-time from 15 mintues (all -in kernel time) to .3 seconds. - -Fixing the wakeup paths could be done at wakeup time in a similar manner -by keeping track of nodes that have already been visited, but the -complexity is harder, since there can be multiple wakeups on different -cpus...Thus, I've opted to limit the number of possible wakeup paths when -the paths are created. - -This is accomplished, by noting that the end file descriptor points that -are found during the loop detection pass (from the newly added link), are -actually the sources for wakeup events. I keep a list of these file -descriptors and limit the number and length of these paths that emanate -from these 'source file descriptors'. In the current implemetation I -allow 1000 paths of length 1, 500 of length 2, 100 of length 3, 50 of -length 4 and 10 of length 5. Note that it is sufficient to check the -'source file descriptors' reachable from the newly added link, since no -other 'source file descriptors' will have newly added links. This allows -us to check only the wakeup paths that may have gotten too long, and not -re-check all possible wakeup paths on the system. - -In terms of the path limit selection, I think its first worth noting that -the most common case for epoll, is probably the model where you have 1 -epoll file descriptor that is monitoring n number of 'source file -descriptors'. In this case, each 'source file descriptor' has a 1 path of -length 1. Thus, I believe that the limits I'm proposing are quite -reasonable and in fact may be too generous. Thus, I'm hoping that the -proposed limits will not prevent any workloads that currently work to -fail. - -In terms of locking, I have extended the use of the 'epmutex' to all -epoll_ctl add and remove operations. Currently its only used in a subset -of the add paths. I need to hold the epmutex, so that we can correctly -traverse a coherent graph, to check the number of paths. I believe that -this additional locking is probably ok, since its in the setup/teardown -paths, and doesn't affect the running paths, but it certainly is going to -add some extra overhead. Also, worth noting is that the epmuex was -recently added to the ep_ctl add operations in the initial path loop -detection code using the argument that it was not on a critical path. - -Another thing to note here, is the length of epoll chains that is allowed. -Currently, eventpoll.c defines: - -/* Maximum number of nesting allowed inside epoll sets */ -#define EP_MAX_NESTS 4 - -This basically means that I am limited to a graph depth of 5 (EP_MAX_NESTS -+ 1). However, this limit is currently only enforced during the loop -check detection code, and only when the epoll file descriptors are added -in a certain order. Thus, this limit is currently easily bypassed. The -newly added check for wakeup paths, stricly limits the wakeup paths to a -length of 5, regardless of the order in which ep's are linked together. -Thus, a side-effect of the new code is a more consistent enforcement of -the graph depth. - -Thus far, I've tested this, using the sample programs previously -mentioned, which now either return quickly or return -EINVAL. I've also -testing using the piptest.c epoll tester, which showed no difference in -performance. I've also created a number of different epoll networks and -tested that they behave as expectded. - -I believe this solves the original diabolical test cases, while still -preserving the sane epoll nesting. - -Signed-off-by: Jason Baron -Cc: Nelson Elhage -Cc: Davide Libenzi -Signed-off-by: Andrew Morton ---- - fs/eventpoll.c | 226 ++++++++++++++++++++++++++++++++++++++++----- - include/linux/eventpoll.h | 1 + - include/linux/fs.h | 1 + - 3 files changed, 203 insertions(+), 25 deletions(-) - -diff --git a/fs/eventpoll.c b/fs/eventpoll.c -index b84fad9..414ac74 100644 ---- a/fs/eventpoll.c -+++ b/fs/eventpoll.c -@@ -197,6 +197,12 @@ struct eventpoll { - - /* The user that created the eventpoll descriptor */ - struct user_struct *user; -+ -+ struct file *file; -+ -+ /* used to optimize loop detection check */ -+ int visited; -+ struct list_head visitedllink; - }; - - /* Wait structure used by the poll hooks */ -@@ -255,6 +261,12 @@ static struct kmem_cache *epi_cache __read_mostly; - /* Slab cache used to allocate "struct eppoll_entry" */ - static struct kmem_cache *pwq_cache __read_mostly; - -+/* Visited nodes during ep_loop_check(), so we can unset them when we finish */ -+LIST_HEAD(visited_list); -+ -+/* Files with newly added links, which need a limit on emanating paths */ -+LIST_HEAD(tfile_check_list); -+ - #ifdef CONFIG_SYSCTL - - #include -@@ -276,6 +288,12 @@ ctl_table epoll_table[] = { - }; - #endif /* CONFIG_SYSCTL */ - -+static const struct file_operations eventpoll_fops; -+ -+static inline int is_file_epoll(struct file *f) -+{ -+ return f->f_op == &eventpoll_fops; -+} - - /* Setup the structure that is used as key for the RB tree */ - static inline void ep_set_ffd(struct epoll_filefd *ffd, -@@ -711,12 +729,6 @@ static const struct file_operations eventpoll_fops = { - .llseek = noop_llseek, - }; - --/* Fast test to see if the file is an eventpoll file */ --static inline int is_file_epoll(struct file *f) --{ -- return f->f_op == &eventpoll_fops; --} -- - /* - * This is called from eventpoll_release() to unlink files from the eventpoll - * interface. We need to have this facility to cleanup correctly files that are -@@ -926,6 +938,96 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi) - rb_insert_color(&epi->rbn, &ep->rbr); - } - -+ -+ -+#define PATH_ARR_SIZE 5 -+/* These are the number paths of length 1 to 5, that we are allowing to emanate -+ * from a single file of interest. For example, we allow 1000 paths of length -+ * 1, to emanate from each file of interest. This essentially represents the -+ * potential wakeup paths, which need to be limited in order to avoid massive -+ * uncontrolled wakeup storms. The common use case should be a single ep which -+ * is connected to n file sources. In this case each file source has 1 path -+ * of length 1. Thus, the numbers below should be more than sufficient. -+ */ -+int path_limits[PATH_ARR_SIZE] = { 1000, 500, 100, 50, 10 }; -+int path_count[PATH_ARR_SIZE]; -+ -+static int path_count_inc(int nests) -+{ -+ if (++path_count[nests] > path_limits[nests]) -+ return -1; -+ return 0; -+} -+ -+static void path_count_init(void) -+{ -+ int i; -+ -+ for (i = 0; i < PATH_ARR_SIZE; i++) -+ path_count[i] = 0; -+} -+ -+static int reverse_path_check_proc(void *priv, void *cookie, int call_nests) -+{ -+ int error = 0; -+ struct file *file = priv; -+ struct file *child_file; -+ struct epitem *epi; -+ -+ list_for_each_entry(epi, &file->f_ep_links, fllink) { -+ child_file = epi->ep->file; -+ if (is_file_epoll(child_file)) { -+ if (list_empty(&child_file->f_ep_links)) { -+ if (path_count_inc(call_nests)) { -+ error = -1; -+ break; -+ } -+ } else { -+ error = ep_call_nested(&poll_loop_ncalls, -+ EP_MAX_NESTS, -+ reverse_path_check_proc, -+ child_file, child_file, -+ current); -+ } -+ if (error != 0) -+ break; -+ } else { -+ printk(KERN_ERR "reverse_path_check_proc: " -+ "file is not an ep!\n"); -+ } -+ } -+ return error; -+} -+ -+/** -+ * reverse_path_check - The tfile_check_list is list of file *, which have -+ * links that are proposed to be newly added. We need to -+ * make sure that those added links don't add too many -+ * paths such that we will spend all our time waking up -+ * eventpoll objects. -+ * -+ * Returns: Returns zero if the proposed links don't create too many paths, -+ * -1 otherwise. -+ */ -+static int reverse_path_check(void) -+{ -+ int length = 0; -+ int error = 0; -+ struct file *current_file; -+ -+ /* let's call this for all tfiles */ -+ list_for_each_entry(current_file, &tfile_check_list, f_tfile_llink) { -+ length++; -+ path_count_init(); -+ error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, -+ reverse_path_check_proc, current_file, -+ current_file, current); -+ if (error) -+ break; -+ } -+ return error; -+} -+ - /* - * Must be called with "mtx" held. - */ -@@ -987,6 +1089,11 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, - */ - ep_rbtree_insert(ep, epi); - -+ /* now check if we've created too many backpaths */ -+ error = -EINVAL; -+ if (reverse_path_check()) -+ goto error_remove_epi; -+ - /* We have to drop the new item inside our item list to keep track of it */ - spin_lock_irqsave(&ep->lock, flags); - -@@ -1011,6 +1118,14 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, - - return 0; - -+error_remove_epi: -+ spin_lock(&tfile->f_lock); -+ if (ep_is_linked(&epi->fllink)) -+ list_del_init(&epi->fllink); -+ spin_unlock(&tfile->f_lock); -+ -+ rb_erase(&epi->rbn, &ep->rbr); -+ - error_unregister: - ep_unregister_pollwait(ep, epi); - -@@ -1275,18 +1390,35 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests) - int error = 0; - struct file *file = priv; - struct eventpoll *ep = file->private_data; -+ struct eventpoll *ep_tovisit; - struct rb_node *rbp; - struct epitem *epi; - - mutex_lock_nested(&ep->mtx, call_nests + 1); -+ ep->visited = 1; -+ list_add(&ep->visitedllink, &visited_list); - for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) { - epi = rb_entry(rbp, struct epitem, rbn); - if (unlikely(is_file_epoll(epi->ffd.file))) { -+ ep_tovisit = epi->ffd.file->private_data; -+ if (ep_tovisit->visited) -+ continue; - error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, -- ep_loop_check_proc, epi->ffd.file, -- epi->ffd.file->private_data, current); -+ ep_loop_check_proc, epi->ffd.file, -+ ep_tovisit, current); - if (error != 0) - break; -+ } else { -+ /* if we've reached a file that is not associated with -+ * an ep, then then we need to check if the newly added -+ * links are going to add too many wakeup paths. We do -+ * this by adding it to the tfile_check_list, if it's -+ * not already there, and calling reverse_path_check() -+ * during ep_insert() -+ */ -+ if (list_empty(&epi->ffd.file->f_tfile_llink)) -+ list_add(&epi->ffd.file->f_tfile_llink, -+ &tfile_check_list); - } - } - mutex_unlock(&ep->mtx); -@@ -1307,8 +1439,30 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests) - */ - static int ep_loop_check(struct eventpoll *ep, struct file *file) - { -- return ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, -+ int ret; -+ struct eventpoll *ep_cur, *ep_next; -+ -+ ret = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, - ep_loop_check_proc, file, ep, current); -+ /* clear visited list */ -+ list_for_each_entry_safe(ep_cur, ep_next, &visited_list, visitedllink) { -+ ep_cur->visited = 0; -+ list_del(&ep_cur->visitedllink); -+ } -+ return ret; -+} -+ -+static void clear_tfile_check_list(void) -+{ -+ struct file *file; -+ -+ /* first clear the tfile_check_list */ -+ while (!list_empty(&tfile_check_list)) { -+ file = list_first_entry(&tfile_check_list, struct file, -+ f_tfile_llink); -+ list_del_init(&file->f_tfile_llink); -+ } -+ INIT_LIST_HEAD(&tfile_check_list); - } - - /* -@@ -1316,8 +1470,9 @@ static int ep_loop_check(struct eventpoll *ep, struct file *file) - */ - SYSCALL_DEFINE1(epoll_create1, int, flags) - { -- int error; -+ int error, fd; - struct eventpoll *ep = NULL; -+ struct file *file; - - /* Check the EPOLL_* constant for consistency. */ - BUILD_BUG_ON(EPOLL_CLOEXEC != O_CLOEXEC); -@@ -1334,11 +1489,25 @@ SYSCALL_DEFINE1(epoll_create1, int, flags) - * Creates all the items needed to setup an eventpoll file. That is, - * a file structure and a free file descriptor. - */ -- error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep, -+ fd = get_unused_fd_flags(O_RDWR | (flags & O_CLOEXEC)); -+ if (fd < 0) { -+ error = fd; -+ goto out_free_ep; -+ } -+ file = anon_inode_getfile("[eventpoll]", &eventpoll_fops, ep, - O_RDWR | (flags & O_CLOEXEC)); -- if (error < 0) -- ep_free(ep); -- -+ if (IS_ERR(file)) { -+ error = PTR_ERR(file); -+ goto out_free_fd; -+ } -+ fd_install(fd, file); -+ ep->file = file; -+ return fd; -+ -+out_free_fd: -+ put_unused_fd(fd); -+out_free_ep: -+ ep_free(ep); - return error; - } - -@@ -1404,21 +1573,27 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, - /* - * When we insert an epoll file descriptor, inside another epoll file - * descriptor, there is the change of creating closed loops, which are -- * better be handled here, than in more critical paths. -+ * better be handled here, than in more critical paths. While we are -+ * checking for loops we also determine the list of files reachable -+ * and hang them on the tfile_check_list, so we can check that we -+ * haven't created too many possible wakeup paths. - * -- * We hold epmutex across the loop check and the insert in this case, in -- * order to prevent two separate inserts from racing and each doing the -- * insert "at the same time" such that ep_loop_check passes on both -- * before either one does the insert, thereby creating a cycle. -+ * We need to hold the epmutex across both ep_insert and ep_remove -+ * b/c we want to make sure we are looking at a coherent view of -+ * epoll network. - */ -- if (unlikely(is_file_epoll(tfile) && op == EPOLL_CTL_ADD)) { -+ if (op == EPOLL_CTL_ADD || op == EPOLL_CTL_DEL) { - mutex_lock(&epmutex); - did_lock_epmutex = 1; -- error = -ELOOP; -- if (ep_loop_check(ep, tfile) != 0) -- goto error_tgt_fput; - } -- -+ if (op == EPOLL_CTL_ADD) { -+ if (is_file_epoll(tfile)) { -+ error = -ELOOP; -+ if (ep_loop_check(ep, tfile) != 0) -+ goto error_tgt_fput; -+ } else -+ list_add(&tfile->f_tfile_llink, &tfile_check_list); -+ } - - mutex_lock_nested(&ep->mtx, 0); - -@@ -1437,6 +1612,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, - error = ep_insert(ep, &epds, tfile, fd); - } else - error = -EEXIST; -+ clear_tfile_check_list(); - break; - case EPOLL_CTL_DEL: - if (epi) -@@ -1455,7 +1631,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, - mutex_unlock(&ep->mtx); - - error_tgt_fput: -- if (unlikely(did_lock_epmutex)) -+ if (did_lock_epmutex) - mutex_unlock(&epmutex); - - fput(tfile); -diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h -index f362733..657ab55 100644 ---- a/include/linux/eventpoll.h -+++ b/include/linux/eventpoll.h -@@ -61,6 +61,7 @@ struct file; - static inline void eventpoll_init_file(struct file *file) - { - INIT_LIST_HEAD(&file->f_ep_links); -+ INIT_LIST_HEAD(&file->f_tfile_llink); - } - - -diff --git a/include/linux/fs.h b/include/linux/fs.h -index ba98668..d393a68 100644 ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -985,6 +985,7 @@ struct file { - #ifdef CONFIG_EPOLL - /* Used by fs/eventpoll.c to link all the hooks to this file */ - struct list_head f_ep_links; -+ struct list_head f_tfile_llink; - #endif /* #ifdef CONFIG_EPOLL */ - struct address_space *f_mapping; - #ifdef CONFIG_DEBUG_WRITECOUNT --- -1.7.6.4 - diff --git a/kernel.spec b/kernel.spec index 2b0a9d81c..7319fa202 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 8 +%define stable_update 9 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -745,8 +745,6 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12026: bsg-fix-sysfs-link-remove-warning.patch -Patch12030: epoll-limit-paths.patch - Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13002: revert-efi-rtclock.patch @@ -765,8 +763,6 @@ Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch #rhbz 717735 Patch21045: nfs-client-freezer.patch -Patch21046: nfs-oops-getacl.patch - #rhbz 590880 Patch21050: alps.patch @@ -1493,8 +1489,6 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch ApplyPatch disable-i8042-check-on-apple-mac.patch -ApplyPatch epoll-limit-paths.patch - ApplyPatch bsg-fix-sysfs-link-remove-warning.patch # rhbz#605888 @@ -1521,8 +1515,6 @@ ApplyPatch hpsa-add-irqf-shared.patch #rhbz 717735 ApplyPatch nfs-client-freezer.patch -ApplyPatch nfs-oops-getacl.patch - #rhbz 590880 ApplyPatch alps.patch @@ -2386,6 +2378,9 @@ fi # and build. %changelog +* Wed Feb 29 2012 Josh Boyer 3.2.9-1 +- Linux 3.2.9 + * Tue Feb 28 2012 Josh Boyer 3.2.8-3 - Add patch to enable keyboard backlight on Sony laptops (rhbz 728478) diff --git a/nfs-oops-getacl.patch b/nfs-oops-getacl.patch deleted file mode 100644 index 53e599dd4..000000000 --- a/nfs-oops-getacl.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 331818f1c468a24e581aedcbe52af799366a9dfe Mon Sep 17 00:00:00 2001 -From: Trond Myklebust -Date: Fri, 3 Feb 2012 18:30:53 -0500 -Subject: [PATCH] NFSv4: Fix an Oops in the NFSv4 getacl code - -Commit bf118a342f10dafe44b14451a1392c3254629a1f (NFSv4: include bitmap -in nfsv4 get acl data) introduces the 'acl_scratch' page for the case -where we may need to decode multi-page data. However it fails to take -into account the fact that the variable may be NULL (for the case where -we're not doing multi-page decode), and it also attaches it to the -encoding xdr_stream rather than the decoding one. - -The immediate result is an Oops in nfs4_xdr_enc_getacl due to the -call to page_address() with a NULL page pointer. - -Signed-off-by: Trond Myklebust -Cc: Andy Adamson -Cc: stable@vger.kernel.org ---- - fs/nfs/nfs4proc.c | 8 ++++---- - fs/nfs/nfs4xdr.c | 5 ++++- - include/linux/nfs_xdr.h | 2 +- - 3 files changed, 9 insertions(+), 6 deletions(-) - -diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c -index f0c849c..d202e04 100644 ---- a/fs/nfs/nfs4proc.c -+++ b/fs/nfs/nfs4proc.c -@@ -3575,8 +3575,8 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu - } - if (npages > 1) { - /* for decoding across pages */ -- args.acl_scratch = alloc_page(GFP_KERNEL); -- if (!args.acl_scratch) -+ res.acl_scratch = alloc_page(GFP_KERNEL); -+ if (!res.acl_scratch) - goto out_free; - } - args.acl_len = npages * PAGE_SIZE; -@@ -3612,8 +3612,8 @@ out_free: - for (i = 0; i < npages; i++) - if (pages[i]) - __free_page(pages[i]); -- if (args.acl_scratch) -- __free_page(args.acl_scratch); -+ if (res.acl_scratch) -+ __free_page(res.acl_scratch); - return ret; - } - -diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c -index 95e92e4..33bd8d0 100644 ---- a/fs/nfs/nfs4xdr.c -+++ b/fs/nfs/nfs4xdr.c -@@ -2522,7 +2522,6 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, - - xdr_inline_pages(&req->rq_rcv_buf, replen << 2, - args->acl_pages, args->acl_pgbase, args->acl_len); -- xdr_set_scratch_buffer(xdr, page_address(args->acl_scratch), PAGE_SIZE); - - encode_nops(&hdr); - } -@@ -6032,6 +6031,10 @@ nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr, - struct compound_hdr hdr; - int status; - -+ if (res->acl_scratch != NULL) { -+ void *p = page_address(res->acl_scratch); -+ xdr_set_scratch_buffer(xdr, p, PAGE_SIZE); -+ } - status = decode_compound_hdr(xdr, &hdr); - if (status) - goto out; -diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h -index a764cef..d6ba9a1 100644 ---- a/include/linux/nfs_xdr.h -+++ b/include/linux/nfs_xdr.h -@@ -614,7 +614,6 @@ struct nfs_getaclargs { - size_t acl_len; - unsigned int acl_pgbase; - struct page ** acl_pages; -- struct page * acl_scratch; - struct nfs4_sequence_args seq_args; - }; - -@@ -624,6 +623,7 @@ struct nfs_getaclres { - size_t acl_len; - size_t acl_data_offset; - int acl_flags; -+ struct page * acl_scratch; - struct nfs4_sequence_res seq_res; - }; - --- -1.7.4.1 - diff --git a/sources b/sources index 6a9fe0d7e..9741e0ff5 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz 8cfe037a7a7a356278ec3638e25ad506 compat-wireless-3.3-rc1-2.tar.bz2 -417b97cdd9e8b2664eb31260dbbcdc72 patch-3.2.8.xz +3916159a999ee49cd6bd002556c629ad patch-3.2.9.xz diff --git a/utrace.patch b/utrace.patch index 060d351e5..333c669f5 100644 --- a/utrace.patch +++ b/utrace.patch @@ -3961,10 +3961,10 @@ diff --git a/kernel/fork.c b/kernel/fork.c index ba0d172..b8719c2 100644 --- a/kernel/fork.c +++ b/kernel/fork.c -@@ -66,6 +66,7 @@ - #include +@@ -67,6 +67,7 @@ #include #include + #include +#include #include From 77583d026d47e3ffaadaf1b5c374f7769d1023e4 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 1 Mar 2012 13:00:13 -0500 Subject: [PATCH 290/487] temporarily switch to low-performance polling IRQ mode when unexpected IRQs occur. --- kernel.spec | 8 + unhandled-irqs-switch-to-polling.patch | 269 +++++++++++++++++++++++++ 2 files changed, 277 insertions(+) create mode 100644 unhandled-irqs-switch-to-polling.patch diff --git a/kernel.spec b/kernel.spec index 7319fa202..8de7f49a6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -819,6 +819,8 @@ Patch21241: cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch #rhbz 728478 Patch21242: sony-laptop-Enable-keyboard-backlight-by-default.patch +Patch21300: unhandled-irqs-switch-to-polling.patch + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-pr_fmt-warning-avoidance.patch @@ -1562,6 +1564,8 @@ ApplyPatch cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch #rhbz 728478 ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch +ApplyPatch unhandled-irqs-switch-to-polling.patch + # END OF PATCH APPLICATIONS %endif @@ -2378,6 +2382,10 @@ fi # and build. %changelog +* Thu Mar 01 2012 Dave Jones +- temporarily switch to low-performance polling IRQ mode when + unexpected IRQs occur. + * Wed Feb 29 2012 Josh Boyer 3.2.9-1 - Linux 3.2.9 diff --git a/unhandled-irqs-switch-to-polling.patch b/unhandled-irqs-switch-to-polling.patch new file mode 100644 index 000000000..8eb09052b --- /dev/null +++ b/unhandled-irqs-switch-to-polling.patch @@ -0,0 +1,269 @@ +From davej Mon Jan 30 16:40:11 2012 +Return-Path: linux-kernel-owner@vger.kernel.org +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-4.9 required=5.0 tests=DKIM_ADSP_CUSTOM_MED, + DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_HI,T_DKIM_INVALID,T_RP_MATCHES_RCVD, + T_TO_NO_BRKTS_FREEMAIL,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.2 +Received: from mail.corp.redhat.com [10.5.5.52] + by gelk.kernelslacker.org with IMAP (fetchmail-6.3.20) + for (single-drop); Mon, 30 Jan 2012 16:40:11 -0500 (EST) +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + zmail11.collab.prod.int.phx2.redhat.com with LMTP; Mon, 30 Jan 2012 + 16:37:45 -0500 (EST) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4BAD0114054; + Mon, 30 Jan 2012 16:37:45 -0500 (EST) +X-Quarantine-ID: <1529X45BXJfc> +Authentication-Results: zmta01.collab.prod.int.phx2.redhat.com (amavisd-new); + dkim=softfail (fail, body has been altered) header.i=@gmail.com +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 1529X45BXJfc; Mon, 30 Jan 2012 16:37:45 -0500 (EST) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 717AC11404F; + Mon, 30 Jan 2012 16:37:44 -0500 (EST) +Received: from mx1.redhat.com (ext-mx14.extmail.prod.ext.phx2.redhat.com [10.5.110.19]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q0ULbhea005095; + Mon, 30 Jan 2012 16:37:43 -0500 +Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q0ULQIU9002068; + Mon, 30 Jan 2012 16:37:42 -0500 +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1753551Ab2A3Vha (ORCPT + + 52 others); Mon, 30 Jan 2012 16:37:30 -0500 +Received: from mail-pz0-f46.google.com ([209.85.210.46]:44901 "EHLO + mail-pz0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1751932Ab2A3Vh2 (ORCPT + ); + Mon, 30 Jan 2012 16:37:28 -0500 +Received: by dadi2 with SMTP id i2so3911730dad.19 + for ; Mon, 30 Jan 2012 13:37:28 -0800 (PST) +Received-SPF: pass (google.com: domain of jeroen.vandenkeybus@gmail.com designates 10.68.218.68 as permitted sender) client-ip=10.68.218.68; +Authentication-Results: mr.google.com; spf=pass (google.com: domain of jeroen.vandenkeybus@gmail.com designates 10.68.218.68 as permitted sender) smtp.mail=jeroen.vandenkeybus@gmail.com; dkim=pass header.i=jeroen.vandenkeybus@gmail.com +Received: from mr.google.com ([10.68.218.68]) + by 10.68.218.68 with SMTP id pe4mr25063612pbc.97.1327959448228 (num_hops = 1); + Mon, 30 Jan 2012 13:37:28 -0800 (PST) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=gamma; + h=mime-version:date:message-id:subject:from:to:cc:content-type; + bh=acUEKJRLazlNr7PWqoJIHm/MPkfhI5SUq1Z0ntfqXSE=; + b=J1hmytKDfluL7NI73mVH+flbQ2+36FPRRx+DFhrPs8hiOebxJHysZZH+etW1ppCJG0 + ORowrKZYuyXb1CVYkSAYSnZ60r0edu8VycE4wsVItKQV8f0ZFyFZi5HteL1KiBRHqTYI + soeRaI/zW4cJv3AbTTc1Aj/4/HXKyuPtj0Ayc= +MIME-Version: 1.0 +Received: by 10.68.218.68 with SMTP id pe4mr20868027pbc.97.1327959448085; Mon, + 30 Jan 2012 13:37:28 -0800 (PST) +Received: by 10.143.38.11 with HTTP; Mon, 30 Jan 2012 13:37:28 -0800 (PST) +Date: Mon, 30 Jan 2012 22:37:28 +0100 +Message-ID: +Subject: [PATCH] Unhandled IRQs on AMD E-450: temporarily switch to + low-performance polling IRQ mode +From: Jeroen Van den Keybus +To: linux-kernel@vger.kernel.org +Cc: Clemens Ladisch , "Huang, Shane" , + Borislav Petkov , "Nguyen, Dong" , + jesse.brandeburg@gmail.com +Content-Type: text/plain; charset=ISO-8859-1 +Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org +X-RedHat-Spam-Score: -4.898 (DKIM_ADSP_CUSTOM_MED,DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_HI,T_DKIM_INVALID,T_RP_MATCHES_RCVD) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.110.19 +Status: RO +Content-Length: 7029 +Lines: 189 + +It seems that some motherboard designs using the ASM1083 PCI/PCIe +bridge (PCI device ID 1b21:1080, Rev. 01) suffer from stuck IRQ lines +on the PCI bus (causing the kernel to emit 'IRQxx: nobody cared' and +disable the IRQ). The following patch is an attempt to mitigate the +serious impact of permanently disabling an IRQ in that case and +actually make PCI devices better usable on this platform. + +It seems that the bridge fails to issue a IRQ deassertion message on +the PCIe bus, when the relevant driver causes the interrupting PCI +device to deassert its IRQ line. To solve this issue, it was tried to +re-issue an IRQ on a PCI device being able to do so (e1000 in this +case), but we suspect that the attempt to re-assert/deassert may have +occurred too soon after the initial IRQ for the ASM1083. Anyway, it +didn't work but if, after some delay, a new IRQ occurred, the related +IRQ deassertion message eventually did clear the IOAPIC IRQ. It would +be useful to re-enable the IRQ here. + +Therefore the patch below to poll_spurious_irqs() in spurious.c is +proposed, It does the following: + +1. lets the kernel decide that an IRQ is unhandled after only 10 +positives (instead of 100,000); +2. briefly (a few seconds or so, currently 1 s) switches to polling +IRQ at a higher rate than usual (100..1,000Hz instead of 10Hz, +currently 100Hz), but not too high to avoid excessive CPU load. Any +device drivers 'see' their interrupts handled with a higher latency +than usual, but they will still operate properly; +3. afterwards, simply reenable the IRQ. + +If proper operation of the PCIe legacy IRQ line emulation is restored +after 3, the system operates again at normal performance. If the IRQ +is still stuck after this procedure, the sequence repeats. + +If a genuinely stuck IRQ is used with this solution, the system would +simply sustain short bursts of 10 unhandled IRQs per second, and use +polling mode indefinitely at a moderate 100Hz rate. It seemed a good +alternative to the default irqpoll behaviour to me, which is why I +left it in poll_spurious_irqs() (instead of creating a new kernel +option). Additionally, if any device happens to share an IRQ with a +faulty one, that device is no longer banned forever. + +Debugging output is still present and may be removed. Bad IRQ +reporting is also commented out now. + +I have now tried it for about 2 months and I can conclude the following: + +1. The patch works and, judging from my Firewire card interrupt on +IRQ16, which repeats every 64 secs, I can confirm that the IRQ usually +gets reset when a new IRQ arrives (polling mode runs for 64 seconds +every time). +2. When testing a SiL-3114 SATA PCI card behind the ASM1083, I could +keep this running at fairly high speeds (50..70MB/s) for an hour or +so, but eventually the SiL driver crashed. In such conditions the PCI +system had to deal with a few hundred IRQs per second / polling mode +kicking in every 5..10 seconds). + +I would like to thank Clemens Ladisch for his invaluable help in +finding a solution (and providing a patch to avoid my SATA going down +every time during debugging). + + +Signed-off-by: Jeroen Van den Keybus +====== + +diff -up linux-3.2-rc4.orig/kernel/irq/spurious.c +linux-3.2-rc4/kernel/irq/spurious.c +--- linux-3.2-rc4.orig/kernel/irq/spurious.c 2011-12-01 23:56:01.000000000 +0100 ++++ linux-3.2-rc4/kernel/irq/spurious.c 2011-12-11 16:14:48.188377387 +0100 +@@ -18,7 +18,7 @@ + + static int irqfixup __read_mostly; + +-#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10) ++#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/100) + static void poll_spurious_irqs(unsigned long dummy); + static DEFINE_TIMER(poll_spurious_irq_timer, poll_spurious_irqs, 0, 0); + static int irq_poll_cpu; +@@ -141,14 +141,15 @@ out: + static void poll_spurious_irqs(unsigned long dummy) + { + struct irq_desc *desc; +- int i; ++ int i, poll_again; + + if (atomic_inc_return(&irq_poll_active) != 1) + goto out; + irq_poll_cpu = smp_processor_id(); + ++ poll_again = 0; /* Will stay false as long as no polling candidate is found */ + for_each_irq_desc(i, desc) { +- unsigned int state; ++ unsigned int state, irq; + + if (!i) + continue; +@@ -158,15 +159,33 @@ static void poll_spurious_irqs(unsigned + barrier(); + if (!(state & IRQS_SPURIOUS_DISABLED)) + continue; +- +- local_irq_disable(); +- try_one_irq(i, desc, true); +- local_irq_enable(); ++ ++ /* We end up here with a disabled spurious interrupt. ++ desc->irqs_unhandled now tracks the number of times ++ the interrupt has been polled */ ++ ++ irq = desc->irq_data.irq; ++ if (desc->irqs_unhandled < 100) { /* 1 second delay with poll frequency 100 Hz */ ++ if (desc->irqs_unhandled == 0) ++ printk("Polling IRQ %d\n", irq); ++ local_irq_disable(); ++ try_one_irq(i, desc, true); ++ local_irq_enable(); ++ desc->irqs_unhandled++; ++ poll_again = 1; ++ } else { ++ printk("Reenabling IRQ %d\n", irq); ++ irq_enable(desc); /* Reenable the interrupt line */ ++ desc->depth--; ++ desc->istate &= (~IRQS_SPURIOUS_DISABLED); ++ desc->irqs_unhandled = 0; ++ } + } ++ if (poll_again) ++ mod_timer(&poll_spurious_irq_timer, ++ jiffies + POLL_SPURIOUS_IRQ_INTERVAL); + out: + atomic_dec(&irq_poll_active); +- mod_timer(&poll_spurious_irq_timer, +- jiffies + POLL_SPURIOUS_IRQ_INTERVAL); + } + + static inline int bad_action_ret(irqreturn_t action_ret) +@@ -177,11 +196,19 @@ static inline int bad_action_ret(irqretu + } + + /* +- * If 99,900 of the previous 100,000 interrupts have not been handled ++ * If 9 of the previous 10 interrupts have not been handled + * then assume that the IRQ is stuck in some manner. Drop a diagnostic + * and try to turn the IRQ off. + * +- * (The other 100-of-100,000 interrupts may have been a correctly ++ * Although this may cause early deactivation of a sporadically ++ * malfunctioning IRQ line, the poll system will: ++ * a) Poll it for 100 cycles at a 100 Hz rate ++ * b) Reenable it afterwards ++ * ++ * In worst case, with current settings, this will cause short bursts ++ * of 10 interrupts every second. ++ * ++ * (The other single interrupt may have been a correctly + * functioning device sharing an IRQ with the failing one) + */ + static void +@@ -302,19 +329,19 @@ void note_interrupt(unsigned int irq, st + } + + desc->irq_count++; +- if (likely(desc->irq_count < 100000)) ++ if (likely(desc->irq_count < 10)) + return; + + desc->irq_count = 0; +- if (unlikely(desc->irqs_unhandled > 99900)) { ++ if (unlikely(desc->irqs_unhandled >= 9)) { + /* + * The interrupt is stuck + */ +- __report_bad_irq(irq, desc, action_ret); ++ /* __report_bad_irq(irq, desc, action_ret); */ + /* + * Now kill the IRQ + */ +- printk(KERN_EMERG "Disabling IRQ #%d\n", irq); ++ printk(KERN_EMERG "Disabling IRQ %d\n", irq); + desc->istate |= IRQS_SPURIOUS_DISABLED; + desc->depth++; + irq_disable(desc); + +====== +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ + From 9b8bd9b67b18a41feccdc59ff2465c8a29e21950 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 1 Mar 2012 14:16:31 -0500 Subject: [PATCH 291/487] Temporarily enable CONFIG_DEBUG_PAGEALLOC in -debug builds to help track down some long-standing bugs. --- config-debug | 3 +++ kernel.spec | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/config-debug b/config-debug index e3c1e6e44..ad5f5352c 100644 --- a/config-debug +++ b/config-debug @@ -109,3 +109,6 @@ CONFIG_DEBUG_KMEMLEAK=y CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 # CONFIG_DEBUG_KMEMLEAK_TEST is not set CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y + +# Temporary +CONFIG_DEBUG_PAGEALLOC=y diff --git a/kernel.spec b/kernel.spec index 8de7f49a6..6f8a5f24e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2382,6 +2382,11 @@ fi # and build. %changelog +* Thu Mar 01 2012 Dave Jones +- Temporarily enable CONFIG_DEBUG_PAGEALLOC in -debug builds to help track + down some long-standing bugs. + Note: This will make -debug builds even slower than normal. + * Thu Mar 01 2012 Dave Jones - temporarily switch to low-performance polling IRQ mode when unexpected IRQs occur. From 3525238463efdfd261de8eb92ce1ef791c2be7be Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Fri, 2 Mar 2012 12:27:28 -0500 Subject: [PATCH 292/487] drm-intel-crtc-dpms-fix.patch: Fix system hang on gen2 kit on DPMS (#730853) --- drm-intel-crtc-dpms-fix.patch | 40 +++++++++++++++++++++++++++++++++++ kernel.spec | 5 +++++ 2 files changed, 45 insertions(+) create mode 100644 drm-intel-crtc-dpms-fix.patch diff --git a/drm-intel-crtc-dpms-fix.patch b/drm-intel-crtc-dpms-fix.patch new file mode 100644 index 000000000..eb582cbec --- /dev/null +++ b/drm-intel-crtc-dpms-fix.patch @@ -0,0 +1,40 @@ +From aed3f09db39596e539f90b11a5016aea4d8442e1 Mon Sep 17 00:00:00 2001 +From: Alban Browaeys +Date: Fri, 24 Feb 2012 17:12:45 +0000 +Subject: [PATCH] drm/i915: Prevent a machine hang by checking crtc->active + before loading lut + +Before loading the lut (gamma), check the active state of intel_crtc, +otherwise at least on gen2 hang ensue. + +This is reproducible in Xorg via: + xset dpms force off +then + xgamma -rgamma 2.0 # freeze. + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=44505 +Signed-off-by: Alban Browaeys +Signed-off-by: Chris Wilson +Reviewed-by: Jesse Barnes +Cc: stable@kernel.org +Signed-off-by: Jesse Barnes +--- + drivers/gpu/drm/i915/intel_display.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index 4871ba0..f851db7 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -6184,7 +6184,7 @@ void intel_crtc_load_lut(struct drm_crtc *crtc) + int i; + + /* The clocks have to be on to load the palette. */ +- if (!crtc->enabled) ++ if (!crtc->enabled || !intel_crtc->active) + return; + + /* use legacy palette for Ironlake */ +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index 6f8a5f24e..4bb646811 100644 --- a/kernel.spec +++ b/kernel.spec @@ -717,6 +717,7 @@ Patch1500: fix_xen_guest_on_old_EC2.patch # intel drm is all merged upstream Patch1824: drm-intel-next.patch +Patch1825: drm-intel-crtc-dpms-fix.patch # hush the i915 fbc noise Patch1826: drm-i915-fbc-stfu.patch @@ -1473,6 +1474,7 @@ ApplyPatch fix_xen_guest_on_old_EC2.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch +ApplyPatch drm-intel-crtc-dpms-fix.patch ApplyPatch drm-i915-fbc-stfu.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch @@ -2382,6 +2384,9 @@ fi # and build. %changelog +* Fri Mar 02 2012 Adam Jackson +- drm-intel-crtc-dpms-fix.patch: Fix system hang on gen2 kit on DPMS (#730853) + * Thu Mar 01 2012 Dave Jones - Temporarily enable CONFIG_DEBUG_PAGEALLOC in -debug builds to help track down some long-standing bugs. From 6611af355f8c5fca5a0f81a625a9c8b0fa7be420 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 2 Mar 2012 14:32:18 -0600 Subject: [PATCH 293/487] Disable threading on compression/decompression for hibernate --- ...threading-in-compression-for-hibernate.patch | 17 +++++++++++++++++ kernel.spec | 10 ++++++++++ 2 files changed, 27 insertions(+) create mode 100644 disable-threading-in-compression-for-hibernate.patch diff --git a/disable-threading-in-compression-for-hibernate.patch b/disable-threading-in-compression-for-hibernate.patch new file mode 100644 index 000000000..685c294ef --- /dev/null +++ b/disable-threading-in-compression-for-hibernate.patch @@ -0,0 +1,17 @@ +In attempt to find the cause of some of the hibernate issues we are seeing, +turn off threading for compression. + +Signed-off-by: Justin M. Forbes + +diff -ruNp a/kernel/power/swap.c b/kernel/power/swap.c +--- a/kernel/power/swap.c 2012-03-02 13:52:27.777485028 -0600 ++++ b/kernel/power/swap.c 2012-03-02 14:05:20.168115129 -0600 +@@ -401,7 +401,7 @@ static int swap_writer_finish(struct swa + #define LZO_CMP_SIZE (LZO_CMP_PAGES * PAGE_SIZE) + + /* Maximum number of threads for compression/decompression. */ +-#define LZO_THREADS 3 ++#define LZO_THREADS 1 + + /* Maximum number of pages for read buffering. */ + #define LZO_READ_PAGES (MAP_PAGE_ENTRIES * 8) diff --git a/kernel.spec b/kernel.spec index 4bb646811..2946096da 100644 --- a/kernel.spec +++ b/kernel.spec @@ -820,6 +820,9 @@ Patch21241: cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch #rhbz 728478 Patch21242: sony-laptop-Enable-keyboard-backlight-by-default.patch +# Disable threading in hibernate compression +Patch21243: disable-threading-in-compression-for-hibernate.patch + Patch21300: unhandled-irqs-switch-to-polling.patch # compat-wireless patches @@ -1566,6 +1569,10 @@ ApplyPatch cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch #rhbz 728478 ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch +#Disable threading in hibernate compression +ApplyPatch disable-threading-in-compression-for-hibernate.patch + + ApplyPatch unhandled-irqs-switch-to-polling.patch # END OF PATCH APPLICATIONS @@ -2384,6 +2391,9 @@ fi # and build. %changelog +* Fri Mar 02 2012 Justin M. Forbes +- Disable threading in hibernate compression/decompression + * Fri Mar 02 2012 Adam Jackson - drm-intel-crtc-dpms-fix.patch: Fix system hang on gen2 kit on DPMS (#730853) From 903b4ae829e5741b441e9b0ed372f38f1e926e5c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 2 Mar 2012 16:03:36 -0500 Subject: [PATCH 294/487] Enable VM debugging in non-debug kernels too. --- config-nodebug | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-nodebug b/config-nodebug index 0f70aa0ae..43b70d774 100644 --- a/config-nodebug +++ b/config-nodebug @@ -8,7 +8,7 @@ CONFIG_SND_PCM_XRUN_DEBUG=y # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_DEBUG_LOCK_ALLOC is not set # CONFIG_PROVE_LOCKING is not set -# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_VM=y # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_PROVE_RCU is not set # CONFIG_PROVE_RCU_REPEATEDLY is not set diff --git a/kernel.spec b/kernel.spec index 2946096da..b13475e64 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2391,6 +2391,9 @@ fi # and build. %changelog +* Fri Mar 02 2012 Dave Jones +- Enable VM debugging in non-debug kernels too. + * Fri Mar 02 2012 Justin M. Forbes - Disable threading in hibernate compression/decompression From 51a4affbb914b8057533c39ce321f6a98c603406 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 5 Mar 2012 09:40:00 -0500 Subject: [PATCH 295/487] CVE-2012-1097 regset: Prevent null pointer reference on readonly regsets --- kernel.spec | 12 +++- ...ull-pointer-reference-on-readonly-re.patch | 63 +++++++++++++++++++ ...AULT-not-EIO-on-host-side-memory-fau.patch | 46 ++++++++++++++ 3 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 regset-Prevent-null-pointer-reference-on-readonly-re.patch create mode 100644 regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch diff --git a/kernel.spec b/kernel.spec index b13475e64..a917a86ce 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -823,6 +823,10 @@ Patch21242: sony-laptop-Enable-keyboard-backlight-by-default.patch # Disable threading in hibernate compression Patch21243: disable-threading-in-compression-for-hibernate.patch +#rhbz 799782 CVE-2012-1097 +Patch21244: regset-Prevent-null-pointer-reference-on-readonly-re.patch +Patch21245: regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch + Patch21300: unhandled-irqs-switch-to-polling.patch # compat-wireless patches @@ -1572,6 +1576,9 @@ ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch #Disable threading in hibernate compression ApplyPatch disable-threading-in-compression-for-hibernate.patch +#rhbz 799782 CVE-2012-1097 +ApplyPatch regset-Prevent-null-pointer-reference-on-readonly-re.patch +ApplyPatch regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch ApplyPatch unhandled-irqs-switch-to-polling.patch @@ -2391,6 +2398,9 @@ fi # and build. %changelog +* Mon Mar 05 2012 Josh Boyer +- CVE-2012-1097 regset: Prevent null pointer reference on readonly regsets + * Fri Mar 02 2012 Dave Jones - Enable VM debugging in non-debug kernels too. diff --git a/regset-Prevent-null-pointer-reference-on-readonly-re.patch b/regset-Prevent-null-pointer-reference-on-readonly-re.patch new file mode 100644 index 000000000..6e2462ee1 --- /dev/null +++ b/regset-Prevent-null-pointer-reference-on-readonly-re.patch @@ -0,0 +1,63 @@ +From c8e252586f8d5de906385d8cf6385fee289a825e Mon Sep 17 00:00:00 2001 +From: "H. Peter Anvin" +Date: Fri, 2 Mar 2012 10:43:48 -0800 +Subject: [PATCH 1/2] regset: Prevent null pointer reference on readonly + regsets + +The regset common infrastructure assumed that regsets would always +have .get and .set methods, but not necessarily .active methods. +Unfortunately people have since written regsets without .set methods. + +Rather than putting in stub functions everywhere, handle regsets with +null .get or .set methods explicitly. + +Signed-off-by: H. Peter Anvin +Reviewed-by: Oleg Nesterov +Acked-by: Roland McGrath +Cc: +Signed-off-by: Linus Torvalds +--- + fs/binfmt_elf.c | 2 +- + include/linux/regset.h | 6 ++++++ + 2 files changed, 7 insertions(+), 1 deletions(-) + +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index bcb884e..07d096c 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -1421,7 +1421,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t, + for (i = 1; i < view->n; ++i) { + const struct user_regset *regset = &view->regsets[i]; + do_thread_regset_writeback(t->task, regset); +- if (regset->core_note_type && ++ if (regset->core_note_type && regset->get && + (!regset->active || regset->active(t->task, regset))) { + int ret; + size_t size = regset->n * regset->size; +diff --git a/include/linux/regset.h b/include/linux/regset.h +index 8abee65..5150fd1 100644 +--- a/include/linux/regset.h ++++ b/include/linux/regset.h +@@ -335,6 +335,9 @@ static inline int copy_regset_to_user(struct task_struct *target, + { + const struct user_regset *regset = &view->regsets[setno]; + ++ if (!regset->get) ++ return -EOPNOTSUPP; ++ + if (!access_ok(VERIFY_WRITE, data, size)) + return -EIO; + +@@ -358,6 +361,9 @@ static inline int copy_regset_from_user(struct task_struct *target, + { + const struct user_regset *regset = &view->regsets[setno]; + ++ if (!regset->set) ++ return -EOPNOTSUPP; ++ + if (!access_ok(VERIFY_READ, data, size)) + return -EIO; + +-- +1.7.7.6 + diff --git a/regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch b/regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch new file mode 100644 index 000000000..21b8ae1ce --- /dev/null +++ b/regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch @@ -0,0 +1,46 @@ +From 5189fa19a4b2b4c3bec37c3a019d446148827717 Mon Sep 17 00:00:00 2001 +From: "H. Peter Anvin" +Date: Fri, 2 Mar 2012 10:43:49 -0800 +Subject: [PATCH 2/2] regset: Return -EFAULT, not -EIO, on host-side memory + fault + +There is only one error code to return for a bad user-space buffer +pointer passed to a system call in the same address space as the +system call is executed, and that is EFAULT. Furthermore, the +low-level access routines, which catch most of the faults, return +EFAULT already. + +Signed-off-by: H. Peter Anvin +Reviewed-by: Oleg Nesterov +Acked-by: Roland McGrath +Cc: +Signed-off-by: Linus Torvalds +--- + include/linux/regset.h | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/regset.h b/include/linux/regset.h +index 5150fd1..686f373 100644 +--- a/include/linux/regset.h ++++ b/include/linux/regset.h +@@ -339,7 +339,7 @@ static inline int copy_regset_to_user(struct task_struct *target, + return -EOPNOTSUPP; + + if (!access_ok(VERIFY_WRITE, data, size)) +- return -EIO; ++ return -EFAULT; + + return regset->get(target, regset, offset, size, NULL, data); + } +@@ -365,7 +365,7 @@ static inline int copy_regset_from_user(struct task_struct *target, + return -EOPNOTSUPP; + + if (!access_ok(VERIFY_READ, data, size)) +- return -EIO; ++ return -EFAULT; + + return regset->set(target, regset, offset, size, NULL, data); + } +-- +1.7.7.6 + From c07883e8e825714cc1dab4d6252902840ab23f24 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 5 Mar 2012 15:39:03 -0500 Subject: [PATCH 296/487] Add patch to fix BUG_ON mm->nr_ptes (rhbz 786632) --- kernel.spec | 7 ++ mm-thp-fix-BUG-on-mm-nr_ptes.patch | 121 +++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 mm-thp-fix-BUG-on-mm-nr_ptes.patch diff --git a/kernel.spec b/kernel.spec index a917a86ce..e1f8ddeeb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -827,6 +827,9 @@ Patch21243: disable-threading-in-compression-for-hibernate.patch Patch21244: regset-Prevent-null-pointer-reference-on-readonly-re.patch Patch21245: regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch +#rhbz 786632 +Patch21246: mm-thp-fix-BUG-on-mm-nr_ptes.patch + Patch21300: unhandled-irqs-switch-to-polling.patch # compat-wireless patches @@ -1580,6 +1583,9 @@ ApplyPatch disable-threading-in-compression-for-hibernate.patch ApplyPatch regset-Prevent-null-pointer-reference-on-readonly-re.patch ApplyPatch regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch +#rhbz 786632 +ApplyPatch mm-thp-fix-BUG-on-mm-nr_ptes.patch + ApplyPatch unhandled-irqs-switch-to-polling.patch # END OF PATCH APPLICATIONS @@ -2400,6 +2406,7 @@ fi %changelog * Mon Mar 05 2012 Josh Boyer - CVE-2012-1097 regset: Prevent null pointer reference on readonly regsets +- Add patch to fix BUG_ON mm->nr_ptes (rhbz 786632) * Fri Mar 02 2012 Dave Jones - Enable VM debugging in non-debug kernels too. diff --git a/mm-thp-fix-BUG-on-mm-nr_ptes.patch b/mm-thp-fix-BUG-on-mm-nr_ptes.patch new file mode 100644 index 000000000..44be5d5a9 --- /dev/null +++ b/mm-thp-fix-BUG-on-mm-nr_ptes.patch @@ -0,0 +1,121 @@ +On Thu, 16 Feb 2012, Andrea Arcangeli wrote: +> On Thu, Feb 16, 2012 at 01:53:04AM -0800, Hugh Dickins wrote: +> > Yes (and I think less troublesome than most BUGs, coming at exit +> > while not holding locks; though we could well make it a WARN_ON, +> > I don't think that existed back in the day). +> +> A WARN_ON would be fine with me, go ahead if you prefer it... only +> risk would be to go unnoticed or be underestimated. I am ok with the +> BUG_ON too (even if this time it triggered false positives... sigh). +> +> > Acked-by: Hugh Dickins +> +> Thanks for the quick review! +> +> > In looking into the bug, it had actually bothered me a little that you +> > were setting aside those pages, yet not counting them into nr_ptes; +> > though the only thing that cares is oom_kill.c, and the count of pages +> > in each hugepage can only dwarf the count in nr_ptes (whereas, without +> > hugepages, it's possible to populate very sparsely and nr_ptes become +> > significant). +> +> Agreed, it's not significant either ways. +> +> Running my two primary systems with this applied for half a day and no +> problem so far so it should be good foro -mm at least. + +And I've had no trouble running your patch since then (but I never hit +the bug it fixes either). But we've all forgottent about it, so let me +bring your patch back inline (I've added one introductory sentence) and +address to akpm... + + +From: Andrea Arcangeli +Subject: [PATCH] mm: thp: fix BUG on mm->nr_ptes + +Dave Jones reports a few Fedora users hitting the BUG_ON(mm->nr_ptes...) +in exit_mmap() recently. + +Quoting Hugh's discovery and explanation of the SMP race condition: + +=== +mm->nr_ptes had unusual locking: down_read mmap_sem plus +page_table_lock when incrementing, down_write mmap_sem (or mm_users 0) +when decrementing; whereas THP is careful to increment and decrement +it under page_table_lock. + +Now most of those paths in THP also hold mmap_sem for read or write +(with appropriate checks on mm_users), but two do not: when +split_huge_page() is called by hwpoison_user_mappings(), and when +called by add_to_swap(). + +It's conceivable that the latter case is responsible for the +exit_mmap() BUG_ON mm->nr_ptes that has been reported on Fedora. +=== + +The simplest way to fix it without having to alter the locking is to +make split_huge_page() a noop in nr_ptes terms, so by counting the +preallocated pagetables that exists for every mapped hugepage. It was +an arbitrary choice not to count them and either way is not wrong or +right, because they are not used but they're still allocated. + +Reported-by: Dave Jones +Reported-by: Hugh Dickins +Signed-off-by: Andrea Arcangeli +Acked-by: Hugh Dickins +--- + mm/huge_memory.c | 6 +++--- + 1 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index 91d3efb..8f7fc39 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -671,6 +671,7 @@ static int __do_huge_pmd_anonymous_page(struct mm_struct *mm, + set_pmd_at(mm, haddr, pmd, entry); + prepare_pmd_huge_pte(pgtable, mm); + add_mm_counter(mm, MM_ANONPAGES, HPAGE_PMD_NR); ++ mm->nr_ptes++; + spin_unlock(&mm->page_table_lock); + } + +@@ -789,6 +790,7 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm, + pmd = pmd_mkold(pmd_wrprotect(pmd)); + set_pmd_at(dst_mm, addr, dst_pmd, pmd); + prepare_pmd_huge_pte(pgtable, dst_mm); ++ dst_mm->nr_ptes++; + + ret = 0; + out_unlock: +@@ -887,7 +889,6 @@ static int do_huge_pmd_wp_page_fallback(struct mm_struct *mm, + } + kfree(pages); + +- mm->nr_ptes++; + smp_wmb(); /* make pte visible before pmd */ + pmd_populate(mm, pmd, pgtable); + page_remove_rmap(page); +@@ -1047,6 +1048,7 @@ int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma, + VM_BUG_ON(page_mapcount(page) < 0); + add_mm_counter(tlb->mm, MM_ANONPAGES, -HPAGE_PMD_NR); + VM_BUG_ON(!PageHead(page)); ++ tlb->mm->nr_ptes--; + spin_unlock(&tlb->mm->page_table_lock); + tlb_remove_page(tlb, page); + pte_free(tlb->mm, pgtable); +@@ -1375,7 +1377,6 @@ static int __split_huge_page_map(struct page *page, + pte_unmap(pte); + } + +- mm->nr_ptes++; + smp_wmb(); /* make pte visible before pmd */ + /* + * Up to this point the pmd is present and huge and +@@ -1988,7 +1989,6 @@ static void collapse_huge_page(struct mm_struct *mm, + set_pmd_at(mm, address, pmd, _pmd); + update_mmu_cache(vma, address, _pmd); + prepare_pmd_huge_pte(pgtable, mm); +- mm->nr_ptes--; + spin_unlock(&mm->page_table_lock); + + #ifndef CONFIG_NUMA From 0d90f6ff37ecc3a0581c1f0473ae4cdf97348d18 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 6 Mar 2012 22:33:53 -0500 Subject: [PATCH 297/487] Some things to remember when rebasing to 3.3 --- rebase-notes.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 rebase-notes.txt diff --git a/rebase-notes.txt b/rebase-notes.txt new file mode 100644 index 000000000..41c4f1a4d --- /dev/null +++ b/rebase-notes.txt @@ -0,0 +1,5 @@ +* disable CONFIG_B43_BCMA_EXTRA (799657) + +* Check if nfs-utinough for CONFIG_NFS_USE_NEW_IDMAPPER + + From 58338b4b822583a672618d9df9b36f64d19e2c79 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 7 Mar 2012 07:55:38 -0500 Subject: [PATCH 298/487] memcg: unregister events attached to the same eventfd can oops (rhbz 800817) --- kernel.spec | 11 ++- ...-unregistring-of-events-attached-to-.patch | 69 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 mm-memcg-Correct-unregistring-of-events-attached-to-.patch diff --git a/kernel.spec b/kernel.spec index e1f8ddeeb..16b8e729a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -830,6 +830,9 @@ Patch21245: regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch #rhbz 786632 Patch21246: mm-thp-fix-BUG-on-mm-nr_ptes.patch +#rhbz 800817 +Patch21247: mm-memcg-Correct-unregistring-of-events-attached-to-.patch + Patch21300: unhandled-irqs-switch-to-polling.patch # compat-wireless patches @@ -1586,6 +1589,9 @@ ApplyPatch regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch #rhbz 786632 ApplyPatch mm-thp-fix-BUG-on-mm-nr_ptes.patch +#rhbz 800817 +ApplyPatch mm-memcg-Correct-unregistring-of-events-attached-to-.patch + ApplyPatch unhandled-irqs-switch-to-polling.patch # END OF PATCH APPLICATIONS @@ -2404,6 +2410,9 @@ fi # and build. %changelog +* Wed Mar 07 2012 Josh Boye +- memcg: unregister events attached to the same eventfd can oops (rhbz 800817) + * Mon Mar 05 2012 Josh Boyer - CVE-2012-1097 regset: Prevent null pointer reference on readonly regsets - Add patch to fix BUG_ON mm->nr_ptes (rhbz 786632) diff --git a/mm-memcg-Correct-unregistring-of-events-attached-to-.patch b/mm-memcg-Correct-unregistring-of-events-attached-to-.patch new file mode 100644 index 000000000..5da0f02b2 --- /dev/null +++ b/mm-memcg-Correct-unregistring-of-events-attached-to-.patch @@ -0,0 +1,69 @@ +From 371528caec553785c37f73fa3926ea0de84f986f Mon Sep 17 00:00:00 2001 +From: Anton Vorontsov +Date: Fri, 24 Feb 2012 05:14:46 +0400 +Subject: [PATCH] mm: memcg: Correct unregistring of events attached to the + same eventfd + +There is an issue when memcg unregisters events that were attached to +the same eventfd: + +- On the first call mem_cgroup_usage_unregister_event() removes all + events attached to a given eventfd, and if there were no events left, + thresholds->primary would become NULL; + +- Since there were several events registered, cgroups core will call + mem_cgroup_usage_unregister_event() again, but now kernel will oops, + as the function doesn't expect that threshold->primary may be NULL. + +That's a good question whether mem_cgroup_usage_unregister_event() +should actually remove all events in one go, but nowadays it can't +do any better as cftype->unregister_event callback doesn't pass +any private event-associated cookie. So, let's fix the issue by +simply checking for threshold->primary. + +FWIW, w/o the patch the following oops may be observed: + + BUG: unable to handle kernel NULL pointer dereference at 0000000000000004 + IP: [] mem_cgroup_usage_unregister_event+0x9c/0x1f0 + Pid: 574, comm: kworker/0:2 Not tainted 3.3.0-rc4+ #9 Bochs Bochs + RIP: 0010:[] [] mem_cgroup_usage_unregister_event+0x9c/0x1f0 + RSP: 0018:ffff88001d0b9d60 EFLAGS: 00010246 + Process kworker/0:2 (pid: 574, threadinfo ffff88001d0b8000, task ffff88001de91cc0) + Call Trace: + [] cgroup_event_remove+0x2b/0x60 + [] process_one_work+0x174/0x450 + [] worker_thread+0x123/0x2d0 + +Cc: stable +Signed-off-by: Anton Vorontsov +Acked-by: KAMEZAWA Hiroyuki +Cc: Kirill A. Shutemov +Cc: Michal Hocko +Signed-off-by: Linus Torvalds + +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index 6728a7a..228d646 100644 +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -4414,6 +4414,9 @@ static void mem_cgroup_usage_unregister_event(struct cgroup *cgrp, + */ + BUG_ON(!thresholds); + ++ if (!thresholds->primary) ++ goto unlock; ++ + usage = mem_cgroup_usage(memcg, type == _MEMSWAP); + + /* Check if a threshold crossed before removing */ +@@ -4462,7 +4465,7 @@ swap_buffers: + + /* To be sure that nobody uses thresholds */ + synchronize_rcu(); +- ++unlock: + mutex_unlock(&memcg->thresholds_lock); + } + +-- +1.7.7.6 + From b93bd5005516f6c84391f44376340828c2a8a03b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 7 Mar 2012 11:58:37 -0500 Subject: [PATCH 299/487] Add CVE number --- kernel.spec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 16b8e729a..4180be05f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2411,7 +2411,8 @@ fi %changelog * Wed Mar 07 2012 Josh Boye -- memcg: unregister events attached to the same eventfd can oops (rhbz 800817) +- CVE-2012-1146: memcg: unregister events attached to the same eventfd can + oops (rhbz 800817) * Mon Mar 05 2012 Josh Boyer - CVE-2012-1097 regset: Prevent null pointer reference on readonly regsets From d08db1bba421c6e70979d5d3a7f908bbb49f799a Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 7 Mar 2012 17:10:29 -0500 Subject: [PATCH 300/487] Add debug patch for bugs 787171/766277 --- kernel.spec | 7 +++++++ weird-root-dentry-name-debug.patch | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 weird-root-dentry-name-debug.patch diff --git a/kernel.spec b/kernel.spec index 4180be05f..47078c853 100644 --- a/kernel.spec +++ b/kernel.spec @@ -835,6 +835,8 @@ Patch21247: mm-memcg-Correct-unregistring-of-events-attached-to-.patch Patch21300: unhandled-irqs-switch-to-polling.patch +Patch22000: weird-root-dentry-name-debug.patch + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-pr_fmt-warning-avoidance.patch @@ -1594,6 +1596,8 @@ ApplyPatch mm-memcg-Correct-unregistring-of-events-attached-to-.patch ApplyPatch unhandled-irqs-switch-to-polling.patch +ApplyPatch weird-root-dentry-name-debug.patch + # END OF PATCH APPLICATIONS %endif @@ -2410,6 +2414,9 @@ fi # and build. %changelog +* Wed Mar 07 2012 Dave Jones +- Add debug patch for bugs 787171/766277 + * Wed Mar 07 2012 Josh Boye - CVE-2012-1146: memcg: unregister events attached to the same eventfd can oops (rhbz 800817) diff --git a/weird-root-dentry-name-debug.patch b/weird-root-dentry-name-debug.patch new file mode 100644 index 000000000..e2fb2e116 --- /dev/null +++ b/weird-root-dentry-name-debug.patch @@ -0,0 +1,19 @@ +debug patch for bz 787171/766277 + +diff --git a/fs/dcache.c b/fs/dcache.c +index bcbdb33..a6a5fdb 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -2530,8 +2530,10 @@ global_root: + */ + if (IS_ROOT(dentry) && + (dentry->d_name.len != 1 || dentry->d_name.name[0] != '/')) { +- WARN(1, "Root dentry has weird name <%.*s>\n", +- (int) dentry->d_name.len, dentry->d_name.name); ++ WARN(1, "Root dentry has weird name <%.*s> vfsmnt:%s fs:%s\n", ++ (int) dentry->d_name.len, dentry->d_name.name, ++ vfsmnt->mnt_root->d_name.name, ++ vfsmnt->mnt_sb->s_type->name); + } + if (!slash) + error = prepend(buffer, buflen, "/", 1); From e4894874e4753f6cd36b80e49db3b7a3ba26106d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 12 Mar 2012 09:19:54 -0400 Subject: [PATCH 301/487] Add patch to ignore bogus io-apic entries (rhbz 801501) --- kernel.spec | 9 +- ...ter-checks-for-bogus-io-apic-entries.patch | 93 +++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch diff --git a/kernel.spec b/kernel.spec index 47078c853..b3c5b4f55 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -835,6 +835,8 @@ Patch21247: mm-memcg-Correct-unregistring-of-events-attached-to-.patch Patch21300: unhandled-irqs-switch-to-polling.patch +Patch21350: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch + Patch22000: weird-root-dentry-name-debug.patch # compat-wireless patches @@ -1598,6 +1600,8 @@ ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch +ApplyPatch x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch + # END OF PATCH APPLICATIONS %endif @@ -2414,6 +2418,9 @@ fi # and build. %changelog +* Mon Mar 12 2012 Josh Boyer +- Add patch to ignore bogus io-apic entries (rhbz 801501) + * Wed Mar 07 2012 Dave Jones - Add debug patch for bugs 787171/766277 diff --git a/x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch b/x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch new file mode 100644 index 000000000..9928829e0 --- /dev/null +++ b/x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch @@ -0,0 +1,93 @@ +On Tue, 2012-01-31 at 09:26 -0500, Josh Boyer wrote: +> On Wed, Jan 25, 2012 at 06:15:35PM -0500, Josh Boyer wrote: +> > On Wed, Jan 25, 2012 at 02:04:08PM -0800, Suresh Siddha wrote: +> > > On Wed, 2012-01-25 at 08:49 -0500, Josh Boyer wrote: +> > > > [ 0.000000] IOAPIC[1]: apic_id 2, version 255, address 0xfec28000, GSI 24-279 +> > > +> > > This looks indeed like a bogus entry probably returning all 1's for +> > > RTE's etc. Can you please send me a dmesg with "apic=verbose" boot +> > > parameter? +> > +> > Here you go: +> > +> > https://bugzilla.redhat.com/attachment.cgi?id=557552 +> +> Was this helpful at all? I've been watching lkml for a related patch +> in case I was missed on CC but haven't seen anything as of yet. + +Yes, it was helpful. Something like the appended patch should ignore the +bogus io-apic entry all together. As I can't test this, can you or the +reporter give the appended patch a try and ack please? + +thanks, +suresh +--- + +From: Suresh Siddha +Subject: x86, ioapic: add register checks for bogus io-apic entries + +With the recent changes to clear_IO_APIC_pin() which tries to clear +remoteIRR bit explicitly, some of the users started to see +"Unable to reset IRR for apic .." messages. + +Close look shows that these are related to bogus IO-APIC entries which +return's all 1's for their io-apic registers. And the above mentioned error +messages are benign. But kernel should have ignored such io-apic's in the +first place. + +Check if register 0, 1, 2 of the listed io-apic are all 1's and ignore +such io-apic. + +Reported-by: Álvaro Castillo +Signed-off-by: Suresh Siddha +--- + arch/x86/kernel/apic/io_apic.c | 26 ++++++++++++++++++++++++++ + 1 files changed, 26 insertions(+), 0 deletions(-) + +diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c +index fb07275..953e54d 100644 +--- a/arch/x86/kernel/apic/io_apic.c ++++ b/arch/x86/kernel/apic/io_apic.c +@@ -3979,6 +3979,26 @@ static __init int bad_ioapic(unsigned long address) + return 0; + } + ++static __init int bad_ioapic_regs(int idx) ++{ ++ union IO_APIC_reg_00 reg_00; ++ union IO_APIC_reg_01 reg_01; ++ union IO_APIC_reg_02 reg_02; ++ ++ reg_00.raw = io_apic_read(idx, 0); ++ reg_01.raw = io_apic_read(idx, 1); ++ reg_02.raw = io_apic_read(idx, 2); ++ ++ if (reg_00.raw == -1 && reg_01.raw == -1 && reg_02.raw == -1) { ++ printk(KERN_WARNING ++ "I/O APIC 0x%x regs return all ones, skipping!\n", ++ mpc_ioapic_addr(idx)); ++ return 1; ++ } ++ ++ return 0; ++} ++ + void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) + { + int idx = 0; +@@ -3995,6 +4015,12 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) + ioapics[idx].mp_config.apicaddr = address; + + set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); ++ ++ if (bad_ioapic_regs(idx)) { ++ clear_fixmap(FIX_IO_APIC_BASE_0 + idx); ++ return; ++ } ++ + ioapics[idx].mp_config.apicid = io_apic_unique_id(id); + ioapics[idx].mp_config.apicver = io_apic_get_version(idx); + + + + From ef4cf365c1d839c800542beadfc06992fbc69905 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 12 Mar 2012 14:58:06 -0400 Subject: [PATCH 302/487] Make the irqpoll patch less chatty (rhbz 800520) Should look at making the frequency of checking dynamic, but this will help the immediate problem. --- unhandled-irqs-switch-to-polling.patch | 47 ++++++++++---------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/unhandled-irqs-switch-to-polling.patch b/unhandled-irqs-switch-to-polling.patch index 8eb09052b..6eeaf0bec 100644 --- a/unhandled-irqs-switch-to-polling.patch +++ b/unhandled-irqs-switch-to-polling.patch @@ -140,16 +140,16 @@ every time during debugging). Signed-off-by: Jeroen Van den Keybus + +Make it less chatty. Josh Boyer ====== -diff -up linux-3.2-rc4.orig/kernel/irq/spurious.c -linux-3.2-rc4/kernel/irq/spurious.c ---- linux-3.2-rc4.orig/kernel/irq/spurious.c 2011-12-01 23:56:01.000000000 +0100 -+++ linux-3.2-rc4/kernel/irq/spurious.c 2011-12-11 16:14:48.188377387 +0100 +--- linux-2.6.orig/kernel/irq/spurious.c ++++ linux-2.6/kernel/irq/spurious.c @@ -18,7 +18,7 @@ - + static int irqfixup __read_mostly; - + -#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10) +#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/100) static void poll_spurious_irqs(unsigned long dummy); @@ -161,42 +161,37 @@ linux-3.2-rc4/kernel/irq/spurious.c struct irq_desc *desc; - int i; + int i, poll_again; - + if (atomic_inc_return(&irq_poll_active) != 1) goto out; irq_poll_cpu = smp_processor_id(); - + + poll_again = 0; /* Will stay false as long as no polling candidate is found */ for_each_irq_desc(i, desc) { - unsigned int state; + unsigned int state, irq; - + if (!i) continue; -@@ -158,15 +159,33 @@ static void poll_spurious_irqs(unsigned - barrier(); +@@ -159,14 +160,29 @@ static void poll_spurious_irqs(unsigned if (!(state & IRQS_SPURIOUS_DISABLED)) continue; -- + - local_irq_disable(); - try_one_irq(i, desc, true); - local_irq_enable(); -+ + /* We end up here with a disabled spurious interrupt. + desc->irqs_unhandled now tracks the number of times + the interrupt has been polled */ + + irq = desc->irq_data.irq; + if (desc->irqs_unhandled < 100) { /* 1 second delay with poll frequency 100 Hz */ -+ if (desc->irqs_unhandled == 0) -+ printk("Polling IRQ %d\n", irq); + local_irq_disable(); + try_one_irq(i, desc, true); + local_irq_enable(); + desc->irqs_unhandled++; + poll_again = 1; + } else { -+ printk("Reenabling IRQ %d\n", irq); + irq_enable(desc); /* Reenable the interrupt line */ + desc->depth--; + desc->istate &= (~IRQS_SPURIOUS_DISABLED); @@ -211,11 +206,11 @@ linux-3.2-rc4/kernel/irq/spurious.c - mod_timer(&poll_spurious_irq_timer, - jiffies + POLL_SPURIOUS_IRQ_INTERVAL); } - + static inline int bad_action_ret(irqreturn_t action_ret) -@@ -177,11 +196,19 @@ static inline int bad_action_ret(irqretu +@@ -177,11 +193,19 @@ static inline int bad_action_ret(irqretu } - + /* - * If 99,900 of the previous 100,000 interrupts have not been handled + * If 9 of the previous 10 interrupts have not been handled @@ -235,14 +230,14 @@ linux-3.2-rc4/kernel/irq/spurious.c * functioning device sharing an IRQ with the failing one) */ static void -@@ -302,19 +329,19 @@ void note_interrupt(unsigned int irq, st +@@ -302,19 +326,19 @@ void note_interrupt(unsigned int irq, st } - + desc->irq_count++; - if (likely(desc->irq_count < 100000)) + if (likely(desc->irq_count < 10)) return; - + desc->irq_count = 0; - if (unlikely(desc->irqs_unhandled > 99900)) { + if (unlikely(desc->irqs_unhandled >= 9)) { @@ -259,11 +254,3 @@ linux-3.2-rc4/kernel/irq/spurious.c desc->istate |= IRQS_SPURIOUS_DISABLED; desc->depth++; irq_disable(desc); - -====== --- -To unsubscribe from this list: send the line "unsubscribe linux-kernel" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html -Please read the FAQ at http://www.tux.org/lkml/ - From e323d4f8297f962d3cff78147711f9cee7cbe86f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 12 Mar 2012 16:04:12 -0400 Subject: [PATCH 303/487] Add version number to changelog --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index b3c5b4f55..d15582414 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2418,7 +2418,7 @@ fi # and build. %changelog -* Mon Mar 12 2012 Josh Boyer +* Mon Mar 12 2012 Josh Boyer - 3.2.9-4 - Add patch to ignore bogus io-apic entries (rhbz 801501) * Wed Mar 07 2012 Dave Jones From 3bdc12b849e3e682e736b29600f86517a60d0c00 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 12 Mar 2012 16:43:41 -0400 Subject: [PATCH 304/487] Linux 3.2.10 --- bsg-fix-sysfs-link-remove-warning.patch | 16 --- ...ry-refcount-leak-when-opening-a-FIFO.patch | 61 --------- drm-intel-crtc-dpms-fix.patch | 40 ------ kernel.spec | 45 +------ ...-unregistring-of-events-attached-to-.patch | 69 ---------- mm-thp-fix-BUG-on-mm-nr_ptes.patch | 121 ------------------ ...ull-pointer-reference-on-readonly-re.patch | 63 --------- ...AULT-not-EIO-on-host-side-memory-fau.patch | 46 ------- s390x-enable-keys-compat.patch | 15 --- sources | 2 +- 10 files changed, 7 insertions(+), 471 deletions(-) delete mode 100644 bsg-fix-sysfs-link-remove-warning.patch delete mode 100644 cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch delete mode 100644 drm-intel-crtc-dpms-fix.patch delete mode 100644 mm-memcg-Correct-unregistring-of-events-attached-to-.patch delete mode 100644 mm-thp-fix-BUG-on-mm-nr_ptes.patch delete mode 100644 regset-Prevent-null-pointer-reference-on-readonly-re.patch delete mode 100644 regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch delete mode 100644 s390x-enable-keys-compat.patch diff --git a/bsg-fix-sysfs-link-remove-warning.patch b/bsg-fix-sysfs-link-remove-warning.patch deleted file mode 100644 index 6e7625327..000000000 --- a/bsg-fix-sysfs-link-remove-warning.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/block/bsg.c b/block/bsg.c -index 4cf703f..ff64ae3 100644 ---- a/block/bsg.c -+++ b/block/bsg.c -@@ -983,7 +983,8 @@ void bsg_unregister_queue(struct request_queue *q) - - mutex_lock(&bsg_mutex); - idr_remove(&bsg_minor_idr, bcd->minor); -- sysfs_remove_link(&q->kobj, "bsg"); -+ if (q->kobj.sd) -+ sysfs_remove_link(&q->kobj, "bsg"); - device_unregister(bcd->class_dev); - bcd->class_dev = NULL; - kref_put(&bcd->ref, bsg_kref_release_function); --- -1.7.4.4 diff --git a/cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch b/cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch deleted file mode 100644 index 9fd87acac..000000000 --- a/cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 5bccda0ebc7c0331b81ac47d39e4b920b198b2cd Mon Sep 17 00:00:00 2001 -From: Jeff Layton -Date: Thu, 23 Feb 2012 09:37:45 -0500 -Subject: [PATCH] cifs: fix dentry refcount leak when opening a FIFO on lookup - -The cifs code will attempt to open files on lookup under certain -circumstances. What happens though if we find that the file we opened -was actually a FIFO or other special file? - -Currently, the open filehandle just ends up being leaked leading to -a dentry refcount mismatch and oops on umount. Fix this by having the -code close the filehandle on the server if it turns out not to be a -regular file. While we're at it, change this spaghetti if statement -into a switch too. - -Cc: stable@vger.kernel.org -Reported-by: CAI Qian -Tested-by: CAI Qian -Reviewed-by: Shirish Pargaonkar -Signed-off-by: Jeff Layton -Signed-off-by: Steve French ---- - fs/cifs/dir.c | 20 ++++++++++++++++++-- - 1 files changed, 18 insertions(+), 2 deletions(-) - -diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c -index 63a196b..bc7e244 100644 ---- a/fs/cifs/dir.c -+++ b/fs/cifs/dir.c -@@ -584,10 +584,26 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, - * If either that or op not supported returned, follow - * the normal lookup. - */ -- if ((rc == 0) || (rc == -ENOENT)) -+ switch (rc) { -+ case 0: -+ /* -+ * The server may allow us to open things like -+ * FIFOs, but the client isn't set up to deal -+ * with that. If it's not a regular file, just -+ * close it and proceed as if it were a normal -+ * lookup. -+ */ -+ if (newInode && !S_ISREG(newInode->i_mode)) { -+ CIFSSMBClose(xid, pTcon, fileHandle); -+ break; -+ } -+ case -ENOENT: - posix_open = true; -- else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP)) -+ case -EOPNOTSUPP: -+ break; -+ default: - pTcon->broken_posix_open = true; -+ } - } - if (!posix_open) - rc = cifs_get_inode_info_unix(&newInode, full_path, --- -1.7.0.4 - diff --git a/drm-intel-crtc-dpms-fix.patch b/drm-intel-crtc-dpms-fix.patch deleted file mode 100644 index eb582cbec..000000000 --- a/drm-intel-crtc-dpms-fix.patch +++ /dev/null @@ -1,40 +0,0 @@ -From aed3f09db39596e539f90b11a5016aea4d8442e1 Mon Sep 17 00:00:00 2001 -From: Alban Browaeys -Date: Fri, 24 Feb 2012 17:12:45 +0000 -Subject: [PATCH] drm/i915: Prevent a machine hang by checking crtc->active - before loading lut - -Before loading the lut (gamma), check the active state of intel_crtc, -otherwise at least on gen2 hang ensue. - -This is reproducible in Xorg via: - xset dpms force off -then - xgamma -rgamma 2.0 # freeze. - -Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=44505 -Signed-off-by: Alban Browaeys -Signed-off-by: Chris Wilson -Reviewed-by: Jesse Barnes -Cc: stable@kernel.org -Signed-off-by: Jesse Barnes ---- - drivers/gpu/drm/i915/intel_display.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c -index 4871ba0..f851db7 100644 ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -6184,7 +6184,7 @@ void intel_crtc_load_lut(struct drm_crtc *crtc) - int i; - - /* The clocks have to be on to load the palette. */ -- if (!crtc->enabled) -+ if (!crtc->enabled || !intel_crtc->active) - return; - - /* use legacy palette for Ironlake */ --- -1.7.7.6 - diff --git a/kernel.spec b/kernel.spec index d15582414..83a268323 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 9 +%define stable_update 10 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -717,7 +717,7 @@ Patch1500: fix_xen_guest_on_old_EC2.patch # intel drm is all merged upstream Patch1824: drm-intel-next.patch -Patch1825: drm-intel-crtc-dpms-fix.patch + # hush the i915 fbc noise Patch1826: drm-i915-fbc-stfu.patch @@ -744,8 +744,6 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch Patch12016: disable-i8042-check-on-apple-mac.patch -Patch12026: bsg-fix-sysfs-link-remove-warning.patch - Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13002: revert-efi-rtclock.patch @@ -809,30 +807,15 @@ Patch21234: e1000e-Avoid-wrong-check-on-TX-hang.patch #Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch Patch21235: scsi-fix-sd_revalidate_disk-oops.patch -#rhbz 790367 -Patch21239: s390x-enable-keys-compat.patch - #rhbz 727865 730007 Patch21240: ACPICA-Fix-regression-in-FADT-revision-checks.patch -Patch21241: cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch - #rhbz 728478 Patch21242: sony-laptop-Enable-keyboard-backlight-by-default.patch # Disable threading in hibernate compression Patch21243: disable-threading-in-compression-for-hibernate.patch -#rhbz 799782 CVE-2012-1097 -Patch21244: regset-Prevent-null-pointer-reference-on-readonly-re.patch -Patch21245: regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch - -#rhbz 786632 -Patch21246: mm-thp-fix-BUG-on-mm-nr_ptes.patch - -#rhbz 800817 -Patch21247: mm-memcg-Correct-unregistring-of-events-attached-to-.patch - Patch21300: unhandled-irqs-switch-to-polling.patch Patch21350: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch @@ -1491,7 +1474,6 @@ ApplyPatch fix_xen_guest_on_old_EC2.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch -ApplyPatch drm-intel-crtc-dpms-fix.patch ApplyPatch drm-i915-fbc-stfu.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch @@ -1510,8 +1492,6 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch ApplyPatch disable-i8042-check-on-apple-mac.patch -ApplyPatch bsg-fix-sysfs-link-remove-warning.patch - # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -1571,31 +1551,15 @@ ApplyPatch e1000e-Avoid-wrong-check-on-TX-hang.patch #ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch ApplyPatch scsi-fix-sd_revalidate_disk-oops.patch -#rhbz 790367 -ApplyPatch s390x-enable-keys-compat.patch - #rhbz 727865 730007 ApplyPatch ACPICA-Fix-regression-in-FADT-revision-checks.patch -#rhbz 798296 -ApplyPatch cifs-fix-dentry-refcount-leak-when-opening-a-FIFO.patch - #rhbz 728478 ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch #Disable threading in hibernate compression ApplyPatch disable-threading-in-compression-for-hibernate.patch -#rhbz 799782 CVE-2012-1097 -ApplyPatch regset-Prevent-null-pointer-reference-on-readonly-re.patch -ApplyPatch regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch - -#rhbz 786632 -ApplyPatch mm-thp-fix-BUG-on-mm-nr_ptes.patch - -#rhbz 800817 -ApplyPatch mm-memcg-Correct-unregistring-of-events-attached-to-.patch - ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch @@ -2418,6 +2382,9 @@ fi # and build. %changelog +* Mon Mar 12 2012 Josh Boyer - 3.2.10-1 +- Linux 3.2.10 + * Mon Mar 12 2012 Josh Boyer - 3.2.9-4 - Add patch to ignore bogus io-apic entries (rhbz 801501) diff --git a/mm-memcg-Correct-unregistring-of-events-attached-to-.patch b/mm-memcg-Correct-unregistring-of-events-attached-to-.patch deleted file mode 100644 index 5da0f02b2..000000000 --- a/mm-memcg-Correct-unregistring-of-events-attached-to-.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 371528caec553785c37f73fa3926ea0de84f986f Mon Sep 17 00:00:00 2001 -From: Anton Vorontsov -Date: Fri, 24 Feb 2012 05:14:46 +0400 -Subject: [PATCH] mm: memcg: Correct unregistring of events attached to the - same eventfd - -There is an issue when memcg unregisters events that were attached to -the same eventfd: - -- On the first call mem_cgroup_usage_unregister_event() removes all - events attached to a given eventfd, and if there were no events left, - thresholds->primary would become NULL; - -- Since there were several events registered, cgroups core will call - mem_cgroup_usage_unregister_event() again, but now kernel will oops, - as the function doesn't expect that threshold->primary may be NULL. - -That's a good question whether mem_cgroup_usage_unregister_event() -should actually remove all events in one go, but nowadays it can't -do any better as cftype->unregister_event callback doesn't pass -any private event-associated cookie. So, let's fix the issue by -simply checking for threshold->primary. - -FWIW, w/o the patch the following oops may be observed: - - BUG: unable to handle kernel NULL pointer dereference at 0000000000000004 - IP: [] mem_cgroup_usage_unregister_event+0x9c/0x1f0 - Pid: 574, comm: kworker/0:2 Not tainted 3.3.0-rc4+ #9 Bochs Bochs - RIP: 0010:[] [] mem_cgroup_usage_unregister_event+0x9c/0x1f0 - RSP: 0018:ffff88001d0b9d60 EFLAGS: 00010246 - Process kworker/0:2 (pid: 574, threadinfo ffff88001d0b8000, task ffff88001de91cc0) - Call Trace: - [] cgroup_event_remove+0x2b/0x60 - [] process_one_work+0x174/0x450 - [] worker_thread+0x123/0x2d0 - -Cc: stable -Signed-off-by: Anton Vorontsov -Acked-by: KAMEZAWA Hiroyuki -Cc: Kirill A. Shutemov -Cc: Michal Hocko -Signed-off-by: Linus Torvalds - -diff --git a/mm/memcontrol.c b/mm/memcontrol.c -index 6728a7a..228d646 100644 ---- a/mm/memcontrol.c -+++ b/mm/memcontrol.c -@@ -4414,6 +4414,9 @@ static void mem_cgroup_usage_unregister_event(struct cgroup *cgrp, - */ - BUG_ON(!thresholds); - -+ if (!thresholds->primary) -+ goto unlock; -+ - usage = mem_cgroup_usage(memcg, type == _MEMSWAP); - - /* Check if a threshold crossed before removing */ -@@ -4462,7 +4465,7 @@ swap_buffers: - - /* To be sure that nobody uses thresholds */ - synchronize_rcu(); -- -+unlock: - mutex_unlock(&memcg->thresholds_lock); - } - --- -1.7.7.6 - diff --git a/mm-thp-fix-BUG-on-mm-nr_ptes.patch b/mm-thp-fix-BUG-on-mm-nr_ptes.patch deleted file mode 100644 index 44be5d5a9..000000000 --- a/mm-thp-fix-BUG-on-mm-nr_ptes.patch +++ /dev/null @@ -1,121 +0,0 @@ -On Thu, 16 Feb 2012, Andrea Arcangeli wrote: -> On Thu, Feb 16, 2012 at 01:53:04AM -0800, Hugh Dickins wrote: -> > Yes (and I think less troublesome than most BUGs, coming at exit -> > while not holding locks; though we could well make it a WARN_ON, -> > I don't think that existed back in the day). -> -> A WARN_ON would be fine with me, go ahead if you prefer it... only -> risk would be to go unnoticed or be underestimated. I am ok with the -> BUG_ON too (even if this time it triggered false positives... sigh). -> -> > Acked-by: Hugh Dickins -> -> Thanks for the quick review! -> -> > In looking into the bug, it had actually bothered me a little that you -> > were setting aside those pages, yet not counting them into nr_ptes; -> > though the only thing that cares is oom_kill.c, and the count of pages -> > in each hugepage can only dwarf the count in nr_ptes (whereas, without -> > hugepages, it's possible to populate very sparsely and nr_ptes become -> > significant). -> -> Agreed, it's not significant either ways. -> -> Running my two primary systems with this applied for half a day and no -> problem so far so it should be good foro -mm at least. - -And I've had no trouble running your patch since then (but I never hit -the bug it fixes either). But we've all forgottent about it, so let me -bring your patch back inline (I've added one introductory sentence) and -address to akpm... - - -From: Andrea Arcangeli -Subject: [PATCH] mm: thp: fix BUG on mm->nr_ptes - -Dave Jones reports a few Fedora users hitting the BUG_ON(mm->nr_ptes...) -in exit_mmap() recently. - -Quoting Hugh's discovery and explanation of the SMP race condition: - -=== -mm->nr_ptes had unusual locking: down_read mmap_sem plus -page_table_lock when incrementing, down_write mmap_sem (or mm_users 0) -when decrementing; whereas THP is careful to increment and decrement -it under page_table_lock. - -Now most of those paths in THP also hold mmap_sem for read or write -(with appropriate checks on mm_users), but two do not: when -split_huge_page() is called by hwpoison_user_mappings(), and when -called by add_to_swap(). - -It's conceivable that the latter case is responsible for the -exit_mmap() BUG_ON mm->nr_ptes that has been reported on Fedora. -=== - -The simplest way to fix it without having to alter the locking is to -make split_huge_page() a noop in nr_ptes terms, so by counting the -preallocated pagetables that exists for every mapped hugepage. It was -an arbitrary choice not to count them and either way is not wrong or -right, because they are not used but they're still allocated. - -Reported-by: Dave Jones -Reported-by: Hugh Dickins -Signed-off-by: Andrea Arcangeli -Acked-by: Hugh Dickins ---- - mm/huge_memory.c | 6 +++--- - 1 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/mm/huge_memory.c b/mm/huge_memory.c -index 91d3efb..8f7fc39 100644 ---- a/mm/huge_memory.c -+++ b/mm/huge_memory.c -@@ -671,6 +671,7 @@ static int __do_huge_pmd_anonymous_page(struct mm_struct *mm, - set_pmd_at(mm, haddr, pmd, entry); - prepare_pmd_huge_pte(pgtable, mm); - add_mm_counter(mm, MM_ANONPAGES, HPAGE_PMD_NR); -+ mm->nr_ptes++; - spin_unlock(&mm->page_table_lock); - } - -@@ -789,6 +790,7 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm, - pmd = pmd_mkold(pmd_wrprotect(pmd)); - set_pmd_at(dst_mm, addr, dst_pmd, pmd); - prepare_pmd_huge_pte(pgtable, dst_mm); -+ dst_mm->nr_ptes++; - - ret = 0; - out_unlock: -@@ -887,7 +889,6 @@ static int do_huge_pmd_wp_page_fallback(struct mm_struct *mm, - } - kfree(pages); - -- mm->nr_ptes++; - smp_wmb(); /* make pte visible before pmd */ - pmd_populate(mm, pmd, pgtable); - page_remove_rmap(page); -@@ -1047,6 +1048,7 @@ int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma, - VM_BUG_ON(page_mapcount(page) < 0); - add_mm_counter(tlb->mm, MM_ANONPAGES, -HPAGE_PMD_NR); - VM_BUG_ON(!PageHead(page)); -+ tlb->mm->nr_ptes--; - spin_unlock(&tlb->mm->page_table_lock); - tlb_remove_page(tlb, page); - pte_free(tlb->mm, pgtable); -@@ -1375,7 +1377,6 @@ static int __split_huge_page_map(struct page *page, - pte_unmap(pte); - } - -- mm->nr_ptes++; - smp_wmb(); /* make pte visible before pmd */ - /* - * Up to this point the pmd is present and huge and -@@ -1988,7 +1989,6 @@ static void collapse_huge_page(struct mm_struct *mm, - set_pmd_at(mm, address, pmd, _pmd); - update_mmu_cache(vma, address, _pmd); - prepare_pmd_huge_pte(pgtable, mm); -- mm->nr_ptes--; - spin_unlock(&mm->page_table_lock); - - #ifndef CONFIG_NUMA diff --git a/regset-Prevent-null-pointer-reference-on-readonly-re.patch b/regset-Prevent-null-pointer-reference-on-readonly-re.patch deleted file mode 100644 index 6e2462ee1..000000000 --- a/regset-Prevent-null-pointer-reference-on-readonly-re.patch +++ /dev/null @@ -1,63 +0,0 @@ -From c8e252586f8d5de906385d8cf6385fee289a825e Mon Sep 17 00:00:00 2001 -From: "H. Peter Anvin" -Date: Fri, 2 Mar 2012 10:43:48 -0800 -Subject: [PATCH 1/2] regset: Prevent null pointer reference on readonly - regsets - -The regset common infrastructure assumed that regsets would always -have .get and .set methods, but not necessarily .active methods. -Unfortunately people have since written regsets without .set methods. - -Rather than putting in stub functions everywhere, handle regsets with -null .get or .set methods explicitly. - -Signed-off-by: H. Peter Anvin -Reviewed-by: Oleg Nesterov -Acked-by: Roland McGrath -Cc: -Signed-off-by: Linus Torvalds ---- - fs/binfmt_elf.c | 2 +- - include/linux/regset.h | 6 ++++++ - 2 files changed, 7 insertions(+), 1 deletions(-) - -diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c -index bcb884e..07d096c 100644 ---- a/fs/binfmt_elf.c -+++ b/fs/binfmt_elf.c -@@ -1421,7 +1421,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t, - for (i = 1; i < view->n; ++i) { - const struct user_regset *regset = &view->regsets[i]; - do_thread_regset_writeback(t->task, regset); -- if (regset->core_note_type && -+ if (regset->core_note_type && regset->get && - (!regset->active || regset->active(t->task, regset))) { - int ret; - size_t size = regset->n * regset->size; -diff --git a/include/linux/regset.h b/include/linux/regset.h -index 8abee65..5150fd1 100644 ---- a/include/linux/regset.h -+++ b/include/linux/regset.h -@@ -335,6 +335,9 @@ static inline int copy_regset_to_user(struct task_struct *target, - { - const struct user_regset *regset = &view->regsets[setno]; - -+ if (!regset->get) -+ return -EOPNOTSUPP; -+ - if (!access_ok(VERIFY_WRITE, data, size)) - return -EIO; - -@@ -358,6 +361,9 @@ static inline int copy_regset_from_user(struct task_struct *target, - { - const struct user_regset *regset = &view->regsets[setno]; - -+ if (!regset->set) -+ return -EOPNOTSUPP; -+ - if (!access_ok(VERIFY_READ, data, size)) - return -EIO; - --- -1.7.7.6 - diff --git a/regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch b/regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch deleted file mode 100644 index 21b8ae1ce..000000000 --- a/regset-Return-EFAULT-not-EIO-on-host-side-memory-fau.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 5189fa19a4b2b4c3bec37c3a019d446148827717 Mon Sep 17 00:00:00 2001 -From: "H. Peter Anvin" -Date: Fri, 2 Mar 2012 10:43:49 -0800 -Subject: [PATCH 2/2] regset: Return -EFAULT, not -EIO, on host-side memory - fault - -There is only one error code to return for a bad user-space buffer -pointer passed to a system call in the same address space as the -system call is executed, and that is EFAULT. Furthermore, the -low-level access routines, which catch most of the faults, return -EFAULT already. - -Signed-off-by: H. Peter Anvin -Reviewed-by: Oleg Nesterov -Acked-by: Roland McGrath -Cc: -Signed-off-by: Linus Torvalds ---- - include/linux/regset.h | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/include/linux/regset.h b/include/linux/regset.h -index 5150fd1..686f373 100644 ---- a/include/linux/regset.h -+++ b/include/linux/regset.h -@@ -339,7 +339,7 @@ static inline int copy_regset_to_user(struct task_struct *target, - return -EOPNOTSUPP; - - if (!access_ok(VERIFY_WRITE, data, size)) -- return -EIO; -+ return -EFAULT; - - return regset->get(target, regset, offset, size, NULL, data); - } -@@ -365,7 +365,7 @@ static inline int copy_regset_from_user(struct task_struct *target, - return -EOPNOTSUPP; - - if (!access_ok(VERIFY_READ, data, size)) -- return -EIO; -+ return -EFAULT; - - return regset->set(target, regset, offset, size, NULL, data); - } --- -1.7.7.6 - diff --git a/s390x-enable-keys-compat.patch b/s390x-enable-keys-compat.patch deleted file mode 100644 index 43d203ca5..000000000 --- a/s390x-enable-keys-compat.patch +++ /dev/null @@ -1,15 +0,0 @@ -@@ -, +, @@ - arch/s390/Kconfig | 3 +++ - 1 files changed, 3 insertions(+), 0 deletions(-) ---- a/arch/s390/Kconfig -+++ a/arch/s390/Kconfig -@@ -227,6 +227,9 @@ config COMPAT - config SYSVIPC_COMPAT - def_bool y if COMPAT && SYSVIPC - -+config KEYS_COMPAT -+ def_bool y if COMPAT && KEYS -+ - config AUDIT_ARCH - def_bool y - diff --git a/sources b/sources index 9741e0ff5..ea05b23c7 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz 8cfe037a7a7a356278ec3638e25ad506 compat-wireless-3.3-rc1-2.tar.bz2 -3916159a999ee49cd6bd002556c629ad patch-3.2.9.xz +7481fa09f2efda915ed19a9da33a2e59 patch-3.2.10.xz From db01769147ba6609a2fbe995977afdc5e14c5499 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 13 Mar 2012 13:43:43 -0400 Subject: [PATCH 305/487] Add some more things to do on rebase to 3.3 --- rebase-notes.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rebase-notes.txt b/rebase-notes.txt index 41c4f1a4d..7824940c6 100644 --- a/rebase-notes.txt +++ b/rebase-notes.txt @@ -2,4 +2,8 @@ * Check if nfs-utinough for CONFIG_NFS_USE_NEW_IDMAPPER +* Turn on the amilo-rfkill driver + +* Remove the with_backports/compat-wireless stuff + From 6924a689b521b59c713101476cf7a229ebd4aa17 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 13 Mar 2012 13:57:10 -0400 Subject: [PATCH 306/487] fix weird typo --- rebase-notes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebase-notes.txt b/rebase-notes.txt index 7824940c6..c5c369858 100644 --- a/rebase-notes.txt +++ b/rebase-notes.txt @@ -1,6 +1,6 @@ * disable CONFIG_B43_BCMA_EXTRA (799657) -* Check if nfs-utinough for CONFIG_NFS_USE_NEW_IDMAPPER +* Check if nfs-utils is new enough for CONFIG_NFS_USE_NEW_IDMAPPER * Turn on the amilo-rfkill driver From 13fb067e9182b2a76c00b0a9733a8ddd631a082f Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 14 Mar 2012 18:17:57 -0400 Subject: [PATCH 307/487] Reduce the foot print of the NFSv4 idmapping coda (bz 593035) --- ...reduce-the-footprint-of-the-idmapper.patch | 109 ++++++++++++++++++ ...Reduce-the-footprint-of-the-idmapper.patch | 46 ++++++++ kernel.spec | 7 ++ 3 files changed, 162 insertions(+) create mode 100644 NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch create mode 100644 NFSv4-Reduce-the-footprint-of-the-idmapper.patch diff --git a/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch b/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch new file mode 100644 index 000000000..42d1052e2 --- /dev/null +++ b/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch @@ -0,0 +1,109 @@ +diff -up linux-3.2.noarch/fs/nfs/idmap.c.orig linux-3.2.noarch/fs/nfs/idmap.c +--- linux-3.2.noarch/fs/nfs/idmap.c.orig 2012-03-14 13:08:37.462928792 -0400 ++++ linux-3.2.noarch/fs/nfs/idmap.c 2012-03-14 13:10:17.076030982 -0400 +@@ -365,7 +365,7 @@ struct idmap_hashent { + + struct idmap_hashtable { + __u8 h_type; +- struct idmap_hashent h_entries[IDMAP_HASH_SZ]; ++ struct idmap_hashent *h_entries; + }; + + struct idmap { +@@ -420,20 +420,39 @@ nfs_idmap_new(struct nfs_client *clp) + return 0; + } + ++static void ++idmap_alloc_hashtable(struct idmap_hashtable *h) ++{ ++ if (h->h_entries != NULL) ++ return; ++ h->h_entries = kcalloc(IDMAP_HASH_SZ, ++ sizeof(*h->h_entries), ++ GFP_KERNEL); ++} ++ ++static void ++idmap_free_hashtable(struct idmap_hashtable *h) ++{ ++ int i; ++ ++ if (h->h_entries == NULL) ++ return; ++ for (i = 0; i < IDMAP_HASH_SZ; i++) ++ kfree(h->h_entries[i].ih_name); ++ kfree(h->h_entries); ++} ++ + void + nfs_idmap_delete(struct nfs_client *clp) + { + struct idmap *idmap = clp->cl_idmap; +- int i; + + if (!idmap) + return; + rpc_unlink(idmap->idmap_dentry); + clp->cl_idmap = NULL; +- for (i = 0; i < ARRAY_SIZE(idmap->idmap_user_hash.h_entries); i++) +- kfree(idmap->idmap_user_hash.h_entries[i].ih_name); +- for (i = 0; i < ARRAY_SIZE(idmap->idmap_group_hash.h_entries); i++) +- kfree(idmap->idmap_group_hash.h_entries[i].ih_name); ++ idmap_free_hashtable(&idmap->idmap_user_hash); ++ idmap_free_hashtable(&idmap->idmap_group_hash); + kfree(idmap); + } + +@@ -443,6 +462,8 @@ nfs_idmap_delete(struct nfs_client *clp) + static inline struct idmap_hashent * + idmap_name_hash(struct idmap_hashtable* h, const char *name, size_t len) + { ++ if (h->h_entries == NULL) ++ return NULL; + return &h->h_entries[fnvhash32(name, len) % IDMAP_HASH_SZ]; + } + +@@ -451,6 +472,8 @@ idmap_lookup_name(struct idmap_hashtable + { + struct idmap_hashent *he = idmap_name_hash(h, name, len); + ++ if (he == NULL) ++ return NULL; + if (he->ih_namelen != len || memcmp(he->ih_name, name, len) != 0) + return NULL; + if (time_after(jiffies, he->ih_expires)) +@@ -461,6 +484,8 @@ idmap_lookup_name(struct idmap_hashtable + static inline struct idmap_hashent * + idmap_id_hash(struct idmap_hashtable* h, __u32 id) + { ++ if (h->h_entries == NULL) ++ return NULL; + return &h->h_entries[fnvhash32(&id, sizeof(id)) % IDMAP_HASH_SZ]; + } + +@@ -468,6 +493,9 @@ static struct idmap_hashent * + idmap_lookup_id(struct idmap_hashtable *h, __u32 id) + { + struct idmap_hashent *he = idmap_id_hash(h, id); ++ ++ if (he == NULL) ++ return NULL; + if (he->ih_id != id || he->ih_namelen == 0) + return NULL; + if (time_after(jiffies, he->ih_expires)) +@@ -483,12 +511,14 @@ idmap_lookup_id(struct idmap_hashtable * + static inline struct idmap_hashent * + idmap_alloc_name(struct idmap_hashtable *h, char *name, size_t len) + { ++ idmap_alloc_hashtable(h); + return idmap_name_hash(h, name, len); + } + + static inline struct idmap_hashent * + idmap_alloc_id(struct idmap_hashtable *h, __u32 id) + { ++ idmap_alloc_hashtable(h); + return idmap_id_hash(h, id); + } + diff --git a/NFSv4-Reduce-the-footprint-of-the-idmapper.patch b/NFSv4-Reduce-the-footprint-of-the-idmapper.patch new file mode 100644 index 000000000..4110ef904 --- /dev/null +++ b/NFSv4-Reduce-the-footprint-of-the-idmapper.patch @@ -0,0 +1,46 @@ +diff -up linux-3.2.noarch/fs/nfs/idmap.c.orig linux-3.2.noarch/fs/nfs/idmap.c +--- linux-3.2.noarch/fs/nfs/idmap.c.orig 2012-02-07 07:12:52.585471833 -0500 ++++ linux-3.2.noarch/fs/nfs/idmap.c 2012-03-14 13:08:37.462928792 -0400 +@@ -360,7 +360,7 @@ struct idmap_hashent { + unsigned long ih_expires; + __u32 ih_id; + size_t ih_namelen; +- char ih_name[IDMAP_NAMESZ]; ++ const char *ih_name; + }; + + struct idmap_hashtable { +@@ -424,11 +424,16 @@ void + nfs_idmap_delete(struct nfs_client *clp) + { + struct idmap *idmap = clp->cl_idmap; ++ int i; + + if (!idmap) + return; + rpc_unlink(idmap->idmap_dentry); + clp->cl_idmap = NULL; ++ for (i = 0; i < ARRAY_SIZE(idmap->idmap_user_hash.h_entries); i++) ++ kfree(idmap->idmap_user_hash.h_entries[i].ih_name); ++ for (i = 0; i < ARRAY_SIZE(idmap->idmap_group_hash.h_entries); i++) ++ kfree(idmap->idmap_group_hash.h_entries[i].ih_name); + kfree(idmap); + } + +@@ -491,9 +496,14 @@ static void + idmap_update_entry(struct idmap_hashent *he, const char *name, + size_t namelen, __u32 id) + { ++ char *str = kmalloc(namelen + 1, GFP_KERNEL); ++ if (str == NULL) ++ return; ++ kfree(he->ih_name); + he->ih_id = id; +- memcpy(he->ih_name, name, namelen); +- he->ih_name[namelen] = '\0'; ++ memcpy(str, name, namelen); ++ str[namelen] = '\0'; ++ he->ih_name = str; + he->ih_namelen = namelen; + he->ih_expires = jiffies + nfs_idmap_cache_timeout; + } diff --git a/kernel.spec b/kernel.spec index 83a268323..a6cb6c740 100644 --- a/kernel.spec +++ b/kernel.spec @@ -739,6 +739,8 @@ Patch2902: linux-2.6-v4l-dvb-uvcvideo-update.patch Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # NFSv4 +Patch4000: NFSv4-Reduce-the-footprint-of-the-idmapper.patch +Patch4001: NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch # patches headed upstream @@ -1402,6 +1404,8 @@ ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # eCryptfs # NFSv4 +ApplyPatch NFSv4-Reduce-the-footprint-of-the-idmapper.patch +ApplyPatch NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch # USB @@ -2382,6 +2386,9 @@ fi # and build. %changelog +* Wed Mar 14 2012 Steve Dickson +- Reduce the foot print of the NFSv4 idmapping coda (bz 593035) + * Mon Mar 12 2012 Josh Boyer - 3.2.10-1 - Linux 3.2.10 From 953a16a7c01f215ba54cfa7f3ce15ea1be928e4f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 14 Mar 2012 20:29:41 -0400 Subject: [PATCH 308/487] Fixup irqpoll patch to only activate on machines with ASM108x PCI bridge --- kernel.spec | 7 +- unhandled-irqs-switch-to-polling.patch | 145 ++++++++++--------------- 2 files changed, 65 insertions(+), 87 deletions(-) diff --git a/kernel.spec b/kernel.spec index a6cb6c740..56e0cdd15 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2386,6 +2386,9 @@ fi # and build. %changelog +* Wed Mar 14 2012 Josh Boyer +- Fixup irqpoll patch to only activate on machines with ASM108x PCI bridge + * Wed Mar 14 2012 Steve Dickson - Reduce the foot print of the NFSv4 idmapping coda (bz 593035) @@ -2398,7 +2401,7 @@ fi * Wed Mar 07 2012 Dave Jones - Add debug patch for bugs 787171/766277 -* Wed Mar 07 2012 Josh Boye +* Wed Mar 07 2012 Josh Boyer - CVE-2012-1146: memcg: unregister events attached to the same eventfd can oops (rhbz 800817) diff --git a/unhandled-irqs-switch-to-polling.patch b/unhandled-irqs-switch-to-polling.patch index 6eeaf0bec..39169ba96 100644 --- a/unhandled-irqs-switch-to-polling.patch +++ b/unhandled-irqs-switch-to-polling.patch @@ -1,62 +1,3 @@ -From davej Mon Jan 30 16:40:11 2012 -Return-Path: linux-kernel-owner@vger.kernel.org -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-4.9 required=5.0 tests=DKIM_ADSP_CUSTOM_MED, - DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_HI,T_DKIM_INVALID,T_RP_MATCHES_RCVD, - T_TO_NO_BRKTS_FREEMAIL,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.2 -Received: from mail.corp.redhat.com [10.5.5.52] - by gelk.kernelslacker.org with IMAP (fetchmail-6.3.20) - for (single-drop); Mon, 30 Jan 2012 16:40:11 -0500 (EST) -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail11.collab.prod.int.phx2.redhat.com with LMTP; Mon, 30 Jan 2012 - 16:37:45 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4BAD0114054; - Mon, 30 Jan 2012 16:37:45 -0500 (EST) -X-Quarantine-ID: <1529X45BXJfc> -Authentication-Results: zmta01.collab.prod.int.phx2.redhat.com (amavisd-new); - dkim=softfail (fail, body has been altered) header.i=@gmail.com -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 1529X45BXJfc; Mon, 30 Jan 2012 16:37:45 -0500 (EST) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 717AC11404F; - Mon, 30 Jan 2012 16:37:44 -0500 (EST) -Received: from mx1.redhat.com (ext-mx14.extmail.prod.ext.phx2.redhat.com [10.5.110.19]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q0ULbhea005095; - Mon, 30 Jan 2012 16:37:43 -0500 -Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q0ULQIU9002068; - Mon, 30 Jan 2012 16:37:42 -0500 -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1753551Ab2A3Vha (ORCPT - + 52 others); Mon, 30 Jan 2012 16:37:30 -0500 -Received: from mail-pz0-f46.google.com ([209.85.210.46]:44901 "EHLO - mail-pz0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1751932Ab2A3Vh2 (ORCPT - ); - Mon, 30 Jan 2012 16:37:28 -0500 -Received: by dadi2 with SMTP id i2so3911730dad.19 - for ; Mon, 30 Jan 2012 13:37:28 -0800 (PST) -Received-SPF: pass (google.com: domain of jeroen.vandenkeybus@gmail.com designates 10.68.218.68 as permitted sender) client-ip=10.68.218.68; -Authentication-Results: mr.google.com; spf=pass (google.com: domain of jeroen.vandenkeybus@gmail.com designates 10.68.218.68 as permitted sender) smtp.mail=jeroen.vandenkeybus@gmail.com; dkim=pass header.i=jeroen.vandenkeybus@gmail.com -Received: from mr.google.com ([10.68.218.68]) - by 10.68.218.68 with SMTP id pe4mr25063612pbc.97.1327959448228 (num_hops = 1); - Mon, 30 Jan 2012 13:37:28 -0800 (PST) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=gamma; - h=mime-version:date:message-id:subject:from:to:cc:content-type; - bh=acUEKJRLazlNr7PWqoJIHm/MPkfhI5SUq1Z0ntfqXSE=; - b=J1hmytKDfluL7NI73mVH+flbQ2+36FPRRx+DFhrPs8hiOebxJHysZZH+etW1ppCJG0 - ORowrKZYuyXb1CVYkSAYSnZ60r0edu8VycE4wsVItKQV8f0ZFyFZi5HteL1KiBRHqTYI - soeRaI/zW4cJv3AbTTc1Aj/4/HXKyuPtj0Ayc= -MIME-Version: 1.0 -Received: by 10.68.218.68 with SMTP id pe4mr20868027pbc.97.1327959448085; Mon, - 30 Jan 2012 13:37:28 -0800 (PST) -Received: by 10.143.38.11 with HTTP; Mon, 30 Jan 2012 13:37:28 -0800 (PST) Date: Mon, 30 Jan 2012 22:37:28 +0100 Message-ID: Subject: [PATCH] Unhandled IRQs on AMD E-450: temporarily switch to @@ -141,21 +82,23 @@ every time during debugging). Signed-off-by: Jeroen Van den Keybus -Make it less chatty. Josh Boyer +Make it less chatty. Only kick it in if we detect an ASM1083 PCI bridge. + +Josh Boyer ====== --- linux-2.6.orig/kernel/irq/spurious.c +++ linux-2.6/kernel/irq/spurious.c -@@ -18,7 +18,7 @@ +@@ -18,6 +18,8 @@ static int irqfixup __read_mostly; --#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10) -+#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/100) ++int irq_poll_and_retry = 0; ++ + #define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10) static void poll_spurious_irqs(unsigned long dummy); static DEFINE_TIMER(poll_spurious_irq_timer, poll_spurious_irqs, 0, 0); - static int irq_poll_cpu; -@@ -141,14 +141,15 @@ out: +@@ -141,12 +143,13 @@ out: static void poll_spurious_irqs(unsigned long dummy) { struct irq_desc *desc; @@ -168,12 +111,9 @@ Make it less chatty. Josh Boyer + poll_again = 0; /* Will stay false as long as no polling candidate is found */ for_each_irq_desc(i, desc) { -- unsigned int state; -+ unsigned int state, irq; + unsigned int state; - if (!i) - continue; -@@ -159,14 +160,29 @@ static void poll_spurious_irqs(unsigned +@@ -159,14 +162,33 @@ static void poll_spurious_irqs(unsigned if (!(state & IRQS_SPURIOUS_DISABLED)) continue; @@ -183,19 +123,23 @@ Make it less chatty. Josh Boyer + /* We end up here with a disabled spurious interrupt. + desc->irqs_unhandled now tracks the number of times + the interrupt has been polled */ -+ -+ irq = desc->irq_data.irq; -+ if (desc->irqs_unhandled < 100) { /* 1 second delay with poll frequency 100 Hz */ ++ if (irq_poll_and_retry) { ++ if (desc->irqs_unhandled < 100) { /* 1 second delay with poll frequency 100 Hz */ ++ local_irq_disable(); ++ try_one_irq(i, desc, true); ++ local_irq_enable(); ++ desc->irqs_unhandled++; ++ poll_again = 1; ++ } else { ++ irq_enable(desc); /* Reenable the interrupt line */ ++ desc->depth--; ++ desc->istate &= (~IRQS_SPURIOUS_DISABLED); ++ desc->irqs_unhandled = 0; ++ } ++ } else { + local_irq_disable(); + try_one_irq(i, desc, true); + local_irq_enable(); -+ desc->irqs_unhandled++; -+ poll_again = 1; -+ } else { -+ irq_enable(desc); /* Reenable the interrupt line */ -+ desc->depth--; -+ desc->istate &= (~IRQS_SPURIOUS_DISABLED); -+ desc->irqs_unhandled = 0; + } } + if (poll_again) @@ -208,7 +152,7 @@ Make it less chatty. Josh Boyer } static inline int bad_action_ret(irqreturn_t action_ret) -@@ -177,11 +193,19 @@ static inline int bad_action_ret(irqretu +@@ -177,11 +199,19 @@ static inline int bad_action_ret(irqretu } /* @@ -230,7 +174,7 @@ Make it less chatty. Josh Boyer * functioning device sharing an IRQ with the failing one) */ static void -@@ -302,19 +326,19 @@ void note_interrupt(unsigned int irq, st +@@ -302,19 +332,24 @@ void note_interrupt(unsigned int irq, st } desc->irq_count++; @@ -242,15 +186,46 @@ Make it less chatty. Josh Boyer - if (unlikely(desc->irqs_unhandled > 99900)) { + if (unlikely(desc->irqs_unhandled >= 9)) { /* - * The interrupt is stuck +- * The interrupt is stuck ++ * The interrupt might be stuck */ - __report_bad_irq(irq, desc, action_ret); -+ /* __report_bad_irq(irq, desc, action_ret); */ ++ if (!irq_poll_and_retry) { ++ __report_bad_irq(irq, desc, action_ret); ++ printk(KERN_EMERG "Disabling IRQ %d\n", irq); ++ } else { ++ printk(KERN_INFO "IRQ %d might be stuck. Polling\n", ++ irq); ++ } /* * Now kill the IRQ */ - printk(KERN_EMERG "Disabling IRQ #%d\n", irq); -+ printk(KERN_EMERG "Disabling IRQ %d\n", irq); desc->istate |= IRQS_SPURIOUS_DISABLED; desc->depth++; irq_disable(desc); +--- linux-2.6.orig/drivers/pci/quirks.c ++++ linux-2.6/drivers/pci/quirks.c +@@ -1677,6 +1677,22 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm); + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm); + ++/* ASM108x transparent PCI bridges apparently have broken IRQ deassert ++ * handling. This causes interrupts to get "stuck" and eventually disabled. ++ * However, the interrupts are often shared and disabling them is fairly bad. ++ * It's been somewhat successful to switch to polling mode and retry after ++ * a bit, so let's do that. ++ */ ++extern int irq_poll_and_retry; ++static void quirk_asm108x_poll_interrupts(struct pci_dev *dev) ++{ ++ dev_info(&dev->dev, "Buggy bridge found [%04x:%04x]\n", ++ dev->vendor, dev->device); ++ dev_info(&dev->dev, "Stuck interrupts will be polled and retried\n"); ++ irq_poll_and_retry = 1; ++} ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_asm108x_poll_interrupts); ++ + #ifdef CONFIG_X86_IO_APIC + /* + * Boot interrupts on some chipsets cannot be turned off. For these chipsets, From 6adca049b27e15410ed6690a2bb6ad9b27fe337d Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 15 Mar 2012 14:22:53 -0500 Subject: [PATCH 309/487] CVE-2012-1179 fix pmd_bad() triggering in code paths holding mmap_sem read mode --- kernel.spec | 13 +- mm-thp-fix-pmd_bad-triggering.patch | 447 ++++++++++++++++++++++++++++ 2 files changed, 458 insertions(+), 2 deletions(-) create mode 100644 mm-thp-fix-pmd_bad-triggering.patch diff --git a/kernel.spec b/kernel.spec index 56e0cdd15..f8e5ee4e4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -818,6 +818,9 @@ Patch21242: sony-laptop-Enable-keyboard-backlight-by-default.patch # Disable threading in hibernate compression Patch21243: disable-threading-in-compression-for-hibernate.patch +#rhbz 803809 CVE-2012-1179 +Patch21244: mm-thp-fix-pmd_bad-triggering.patch + Patch21300: unhandled-irqs-switch-to-polling.patch Patch21350: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch @@ -1564,12 +1567,15 @@ ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch #Disable threading in hibernate compression ApplyPatch disable-threading-in-compression-for-hibernate.patch -ApplyPatch unhandled-irqs-switch-to-polling.patch +# ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch ApplyPatch x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch +#rhbz 803809 CVE-2012-1179 +ApplyPatch mm-thp-fix-pmd_bad-triggering.patch + # END OF PATCH APPLICATIONS %endif @@ -2386,6 +2392,9 @@ fi # and build. %changelog +* Thu Mar 15 2012 Justin M. Forbes - 3.2.10-3 +- CVE-2012-1179 fix pmd_bad() triggering in code paths holding mmap_sem read mode (rhbz 803809) + * Wed Mar 14 2012 Josh Boyer - Fixup irqpoll patch to only activate on machines with ASM108x PCI bridge diff --git a/mm-thp-fix-pmd_bad-triggering.patch b/mm-thp-fix-pmd_bad-triggering.patch new file mode 100644 index 000000000..3af9d2e2d --- /dev/null +++ b/mm-thp-fix-pmd_bad-triggering.patch @@ -0,0 +1,447 @@ +In some cases it may happen that pmd_none_or_clear_bad() is called +with the mmap_sem hold in read mode. In those cases the huge page +faults can allocate hugepmds under pmd_none_or_clear_bad() and that +can trigger a false positive from pmd_bad() that will not like to see +a pmd materializing as trans huge. + +It's not khugepaged the problem, khugepaged holds the mmap_sem in +write mode (and all those sites must hold the mmap_sem in read mode to +prevent pagetables to go away from under them, during code review it +seems vm86 mode on 32bit kernels requires that too unless it's +restricted to 1 thread per process or UP builds). The race is only +with the huge pagefaults that can convert a pmd_none() into a +pmd_trans_huge(). + +Effectively all these pmd_none_or_clear_bad() sites running with +mmap_sem in read mode are somewhat speculative with the page faults, +and the result is always undefined when they run simultaneously. This +is probably why it wasn't common to run into this. For example if the +madvise(MADV_DONTNEED) runs zap_page_range() shortly before the page +fault, the hugepage will not be zapped, if the page fault runs first +it will be zapped. + +Altering pmd_bad() not to error out if it finds hugepmds won't be +enough to fix this, because zap_pmd_range would then proceed to call +zap_pte_range (which would be incorrect if the pmd become a +pmd_trans_huge()). + +The simplest way to fix this is to read the pmd in the local stack +(regardless of what we read, no need of actual CPU barriers, only +compiler barrier needed), and be sure it is not changing under the +code that computes its value. Even if the real pmd is changing under +the value we hold on the stack, we don't care. If we actually end up +in zap_pte_range it means the pmd was not none already and it was not +huge, and it can't become huge from under us (khugepaged locking +explained above). + +All we need is to enforce that there is no way anymore that in a code +path like below, pmd_trans_huge can be false, but +pmd_none_or_clear_bad can run into a hugepmd. The overhead of a +barrier() is just a compiler tweak and should not be measurable (I +only added it for THP builds). I don't exclude different compiler +versions may have prevented the race too by caching the value of *pmd +on the stack (that hasn't been verified, but it wouldn't be impossible +considering pmd_none_or_clear_bad, pmd_bad, pmd_trans_huge, pmd_none +are all inlines and there's no external function called in between +pmd_trans_huge and pmd_none_or_clear_bad). + + if (pmd_trans_huge(*pmd)) { + if (next-addr != HPAGE_PMD_SIZE) { + VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem)); + split_huge_page_pmd(vma->vm_mm, pmd); + } else if (zap_huge_pmd(tlb, vma, pmd, addr)) + continue; + /* fall through */ + } + if (pmd_none_or_clear_bad(pmd)) + +Because this race condition could be exercised without special +privileges this was reported in CVE-2012-1179. + +The race was identified and fully explained by Ulrich who debugged it. +I'm quoting his accurate explanation below, for reference. + +====== start quote ======= + mapcount 0 page_mapcount 1 + kernel BUG at mm/huge_memory.c:1384! + +At some point prior to the panic, a "bad pmd ..." message similar to the +following is logged on the console: + + mm/memory.c:145: bad pmd ffff8800376e1f98(80000000314000e7). + +The "bad pmd ..." message is logged by pmd_clear_bad() before it clears +the page's PMD table entry. + + 143 void pmd_clear_bad(pmd_t *pmd) + 144 { +-> 145 pmd_ERROR(*pmd); + 146 pmd_clear(pmd); + 147 } + +After the PMD table entry has been cleared, there is an inconsistency +between the actual number of PMD table entries that are mapping the page +and the page's map count (_mapcount field in struct page). When the page +is subsequently reclaimed, __split_huge_page() detects this inconsistency. + + 1381 if (mapcount != page_mapcount(page)) + 1382 printk(KERN_ERR "mapcount %d page_mapcount %d\n", + 1383 mapcount, page_mapcount(page)); +-> 1384 BUG_ON(mapcount != page_mapcount(page)); + +The root cause of the problem is a race of two threads in a multithreaded +process. Thread B incurs a page fault on a virtual address that has never +been accessed (PMD entry is zero) while Thread A is executing an madvise() +system call on a virtual address within the same 2 MB (huge page) range. + + virtual address space + .---------------------. + | | + | | + .-|---------------------| + | | | + | | |<-- B(fault) + | | | + 2 MB | |/////////////////////|-. + huge < |/////////////////////| > A(range) + page | |/////////////////////|-' + | | | + | | | + '-|---------------------| + | | + | | + '---------------------' + +- Thread A is executing an madvise(..., MADV_DONTNEED) system call + on the virtual address range "A(range)" shown in the picture. + +sys_madvise + // Acquire the semaphore in shared mode. + down_read(¤t->mm->mmap_sem) + ... + madvise_vma + switch (behavior) + case MADV_DONTNEED: + madvise_dontneed + zap_page_range + unmap_vmas + unmap_page_range + zap_pud_range + zap_pmd_range + // + // Assume that this huge page has never been accessed. + // I.e. content of the PMD entry is zero (not mapped). + // + if (pmd_trans_huge(*pmd)) { + // We don't get here due to the above assumption. + } + // + // Assume that Thread B incurred a page fault and + .---------> // sneaks in here as shown below. + | // + | if (pmd_none_or_clear_bad(pmd)) + | { + | if (unlikely(pmd_bad(*pmd))) + | pmd_clear_bad + | { + | pmd_ERROR + | // Log "bad pmd ..." message here. + | pmd_clear + | // Clear the page's PMD entry. + | // Thread B incremented the map count + | // in page_add_new_anon_rmap(), but + | // now the page is no longer mapped + | // by a PMD entry (-> inconsistency). + | } + | } + | + v +- Thread B is handling a page fault on virtual address "B(fault)" shown + in the picture. + +... +do_page_fault + __do_page_fault + // Acquire the semaphore in shared mode. + down_read_trylock(&mm->mmap_sem) + ... + handle_mm_fault + if (pmd_none(*pmd) && transparent_hugepage_enabled(vma)) + // We get here due to the above assumption (PMD entry is zero). + do_huge_pmd_anonymous_page + alloc_hugepage_vma + // Allocate a new transparent huge page here. + ... + __do_huge_pmd_anonymous_page + ... + spin_lock(&mm->page_table_lock) + ... + page_add_new_anon_rmap + // Here we increment the page's map count (starts at -1). + atomic_set(&page->_mapcount, 0) + set_pmd_at + // Here we set the page's PMD entry which will be cleared + // when Thread A calls pmd_clear_bad(). + ... + spin_unlock(&mm->page_table_lock) + +The mmap_sem does not prevent the race because both threads are acquiring +it in shared mode (down_read). Thread B holds the page_table_lock while +the page's map count and PMD table entry are updated. However, Thread A +does not synchronize on that lock. +====== end quote ======= + +Reported-by: Ulrich Obergfell +Signed-off-by: Andrea Arcangeli +--- + arch/x86/kernel/vm86_32.c | 2 + + fs/proc/task_mmu.c | 9 ++++++ + include/asm-generic/pgtable.h | 57 +++++++++++++++++++++++++++++++++++++++++ + mm/memcontrol.c | 4 +++ + mm/memory.c | 14 ++++++++-- + mm/mempolicy.c | 2 +- + mm/mincore.c | 2 +- + mm/pagewalk.c | 2 +- + mm/swapfile.c | 4 +-- + 9 files changed, 87 insertions(+), 9 deletions(-) + +diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c +index b466cab..328cb37 100644 +--- a/arch/x86/kernel/vm86_32.c ++++ b/arch/x86/kernel/vm86_32.c +@@ -172,6 +172,7 @@ static void mark_screen_rdonly(struct mm_struct *mm) + spinlock_t *ptl; + int i; + ++ down_write(&mm->mmap_sem); + pgd = pgd_offset(mm, 0xA0000); + if (pgd_none_or_clear_bad(pgd)) + goto out; +@@ -190,6 +191,7 @@ static void mark_screen_rdonly(struct mm_struct *mm) + } + pte_unmap_unlock(pte, ptl); + out: ++ up_write(&mm->mmap_sem); + flush_tlb(); + } + +diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c +index 7dcd2a2..3efa725 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -409,6 +409,9 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, + } else { + spin_unlock(&walk->mm->page_table_lock); + } ++ ++ if (pmd_trans_unstable(pmd)) ++ return 0; + /* + * The mmap_sem held all the way back in m_start() is what + * keeps khugepaged out of here and from collapsing things +@@ -507,6 +510,8 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr, + struct page *page; + + split_huge_page_pmd(walk->mm, pmd); ++ if (pmd_trans_unstable(pmd)) ++ return 0; + + pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); + for (; addr != end; pte++, addr += PAGE_SIZE) { +@@ -670,6 +675,8 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, + int err = 0; + + split_huge_page_pmd(walk->mm, pmd); ++ if (pmd_trans_unstable(pmd)) ++ return 0; + + /* find the first VMA at or above 'addr' */ + vma = find_vma(walk->mm, addr); +@@ -961,6 +968,8 @@ static int gather_pte_stats(pmd_t *pmd, unsigned long addr, + spin_unlock(&walk->mm->page_table_lock); + } + ++ if (pmd_trans_unstable(pmd)) ++ return 0; + orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); + do { + struct page *page = can_gather_numa_stats(*pte, md->vma, addr); +diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h +index 76bff2b..10f8291 100644 +--- a/include/asm-generic/pgtable.h ++++ b/include/asm-generic/pgtable.h +@@ -443,6 +443,63 @@ static inline int pmd_write(pmd_t pmd) + #endif /* __HAVE_ARCH_PMD_WRITE */ + #endif + ++/* ++ * This function is meant to be used by sites walking pagetables with ++ * the mmap_sem hold in read mode to protect against MADV_DONTNEED and ++ * transhuge page faults. MADV_DONTNEED can convert a transhuge pmd ++ * into a null pmd and the transhuge page fault can convert a null pmd ++ * into an hugepmd or into a regular pmd (if the hugepage allocation ++ * fails). While holding the mmap_sem in read mode the pmd becomes ++ * stable and stops changing under us only if it's not null and not a ++ * transhuge pmd. When those races occurs and this function makes a ++ * difference vs the standard pmd_none_or_clear_bad, the result is ++ * undefined so behaving like if the pmd was none is safe (because it ++ * can return none anyway). The compiler level barrier() is critically ++ * important to compute the two checks atomically on the same pmdval. ++ */ ++static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd) ++{ ++ /* depend on compiler for an atomic pmd read */ ++ pmd_t pmdval = *pmd; ++ /* ++ * The barrier will stabilize the pmdval in a register or on ++ * the stack so that it will stop changing under the code. ++ */ ++#ifdef CONFIG_TRANSPARENT_HUGEPAGE ++ barrier(); ++#endif ++ if (pmd_none(pmdval)) ++ return 1; ++ if (unlikely(pmd_bad(pmdval))) { ++ if (!pmd_trans_huge(pmdval)) ++ pmd_clear_bad(pmd); ++ return 1; ++ } ++ return 0; ++} ++ ++/* ++ * This is a noop if Transparent Hugepage Support is not built into ++ * the kernel. Otherwise it is equivalent to ++ * pmd_none_or_trans_huge_or_clear_bad(), and shall only be called in ++ * places that already verified the pmd is not none and they want to ++ * walk ptes while holding the mmap sem in read mode (write mode don't ++ * need this). If THP is not enabled, the pmd can't go away under the ++ * code even if MADV_DONTNEED runs, but if THP is enabled we need to ++ * run a pmd_trans_unstable before walking the ptes after ++ * split_huge_page_pmd returns (because it may have run when the pmd ++ * become null, but then a page fault can map in a THP and not a ++ * regular page). ++ */ ++static inline int pmd_trans_unstable(pmd_t *pmd) ++{ ++#ifdef CONFIG_TRANSPARENT_HUGEPAGE ++ return pmd_none_or_trans_huge_or_clear_bad(pmd); ++#else ++ return 0; ++#endif ++} ++ + #endif /* !__ASSEMBLY__ */ + + #endif /* _ASM_GENERIC_PGTABLE_H */ +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index d0e57a3..67b0578 100644 +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -5193,6 +5193,8 @@ static int mem_cgroup_count_precharge_pte_range(pmd_t *pmd, + spinlock_t *ptl; + + split_huge_page_pmd(walk->mm, pmd); ++ if (pmd_trans_unstable(pmd)) ++ return 0; + + pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); + for (; addr != end; pte++, addr += PAGE_SIZE) +@@ -5355,6 +5357,8 @@ static int mem_cgroup_move_charge_pte_range(pmd_t *pmd, + spinlock_t *ptl; + + split_huge_page_pmd(walk->mm, pmd); ++ if (pmd_trans_unstable(pmd)) ++ return 0; + retry: + pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); + for (; addr != end; addr += PAGE_SIZE) { +diff --git a/mm/memory.c b/mm/memory.c +index fa2f04e..e3090fc 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -1251,12 +1251,20 @@ static inline unsigned long zap_pmd_range(struct mmu_gather *tlb, + VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem)); + split_huge_page_pmd(vma->vm_mm, pmd); + } else if (zap_huge_pmd(tlb, vma, pmd)) +- continue; ++ goto next; + /* fall through */ + } +- if (pmd_none_or_clear_bad(pmd)) +- continue; ++ /* ++ * Here there can be other concurrent MADV_DONTNEED or ++ * trans huge page faults running, and if the pmd is ++ * none or trans huge it can change under us. This is ++ * because MADV_DONTNEED holds the mmap_sem in read ++ * mode. ++ */ ++ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) ++ goto next; + next = zap_pte_range(tlb, vma, pmd, addr, next, details); ++ next: + cond_resched(); + } while (pmd++, addr = next, addr != end); + +diff --git a/mm/mempolicy.c b/mm/mempolicy.c +index 47296fe..0a37570 100644 +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -512,7 +512,7 @@ static inline int check_pmd_range(struct vm_area_struct *vma, pud_t *pud, + do { + next = pmd_addr_end(addr, end); + split_huge_page_pmd(vma->vm_mm, pmd); +- if (pmd_none_or_clear_bad(pmd)) ++ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) + continue; + if (check_pte_range(vma, pmd, addr, next, nodes, + flags, private)) +diff --git a/mm/mincore.c b/mm/mincore.c +index 636a868..936b4ce 100644 +--- a/mm/mincore.c ++++ b/mm/mincore.c +@@ -164,7 +164,7 @@ static void mincore_pmd_range(struct vm_area_struct *vma, pud_t *pud, + } + /* fall through */ + } +- if (pmd_none_or_clear_bad(pmd)) ++ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) + mincore_unmapped_range(vma, addr, next, vec); + else + mincore_pte_range(vma, pmd, addr, next, vec); +diff --git a/mm/pagewalk.c b/mm/pagewalk.c +index 2f5cf10..aa9701e 100644 +--- a/mm/pagewalk.c ++++ b/mm/pagewalk.c +@@ -59,7 +59,7 @@ again: + continue; + + split_huge_page_pmd(walk->mm, pmd); +- if (pmd_none_or_clear_bad(pmd)) ++ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) + goto again; + err = walk_pte_range(pmd, addr, next, walk); + if (err) +diff --git a/mm/swapfile.c b/mm/swapfile.c +index d999f09..f31b29d 100644 +--- a/mm/swapfile.c ++++ b/mm/swapfile.c +@@ -932,9 +932,7 @@ static inline int unuse_pmd_range(struct vm_area_struct *vma, pud_t *pud, + pmd = pmd_offset(pud, addr); + do { + next = pmd_addr_end(addr, end); +- if (unlikely(pmd_trans_huge(*pmd))) +- continue; +- if (pmd_none_or_clear_bad(pmd)) ++ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) + continue; + ret = unuse_pte_range(vma, pmd, addr, next, entry, page); + if (ret) + +-- +To unsubscribe, send a message with 'unsubscribe linux-mm' in +the body to majordomo@kvack.org. For more info on Linux MM, +see: http://www.linux-mm.org/ . +Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ +Don't email: email@kvack.org From 12b6d38c8a84f1b51bd4fb1cf8f8ee57b6618fcf Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 16 Mar 2012 07:55:35 -0400 Subject: [PATCH 310/487] Avoid the rage of steved --- rebase-notes.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rebase-notes.txt b/rebase-notes.txt index c5c369858..cf9ab9d1f 100644 --- a/rebase-notes.txt +++ b/rebase-notes.txt @@ -1,6 +1,7 @@ * disable CONFIG_B43_BCMA_EXTRA (799657) -* Check if nfs-utils is new enough for CONFIG_NFS_USE_NEW_IDMAPPER +* Do not turn on CONFIG_NFS_USE_NEW_IDMAPPER in f15/f16. Steved will hunt you + down. * Turn on the amilo-rfkill driver From c91e32221e2a35960845b4054f6037c2b5dfe1a9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 16 Mar 2012 07:58:36 -0400 Subject: [PATCH 311/487] Fixup irqpoll patch to really not impact machines without ASM108x bridges (rhbz 800520) WITH FEELING THIS TIME --- kernel.spec | 7 +++++-- unhandled-irqs-switch-to-polling.patch | 25 +++++++++++++++++++++---- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/kernel.spec b/kernel.spec index f8e5ee4e4..adad4266a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -1567,7 +1567,7 @@ ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch #Disable threading in hibernate compression ApplyPatch disable-threading-in-compression-for-hibernate.patch -# ApplyPatch unhandled-irqs-switch-to-polling.patch +ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch @@ -2392,6 +2392,9 @@ fi # and build. %changelog +* Fri Mar 16 2012 Josh Boyer +- Fix irqpoll patch to really only apply for ASM108x machines (rhbz 800520) + * Thu Mar 15 2012 Justin M. Forbes - 3.2.10-3 - CVE-2012-1179 fix pmd_bad() triggering in code paths holding mmap_sem read mode (rhbz 803809) diff --git a/unhandled-irqs-switch-to-polling.patch b/unhandled-irqs-switch-to-polling.patch index 39169ba96..2f25cda6f 100644 --- a/unhandled-irqs-switch-to-polling.patch +++ b/unhandled-irqs-switch-to-polling.patch @@ -174,17 +174,34 @@ Josh Boyer * functioning device sharing an IRQ with the failing one) */ static void -@@ -302,19 +332,24 @@ void note_interrupt(unsigned int irq, st +@@ -269,6 +299,8 @@ try_misrouted_irq(unsigned int irq, stru + void note_interrupt(unsigned int irq, struct irq_desc *desc, + irqreturn_t action_ret) + { ++ int unhandled_thresh = 999000; ++ + if (desc->istate & IRQS_POLL_INPROGRESS) + return; + +@@ -302,19 +334,31 @@ void note_interrupt(unsigned int irq, st } desc->irq_count++; - if (likely(desc->irq_count < 100000)) -+ if (likely(desc->irq_count < 10)) - return; +- return; ++ if (!irq_poll_and_retry) ++ if (likely(desc->irq_count < 100000)) ++ return; ++ else ++ if (likely(desc->irq_count < 10)) ++ return; desc->irq_count = 0; - if (unlikely(desc->irqs_unhandled > 99900)) { -+ if (unlikely(desc->irqs_unhandled >= 9)) { ++ if (irq_poll_and_retry) ++ unhandled_thresh = 9; ++ ++ if (unlikely(desc->irqs_unhandled >= unhandled_thresh)) { /* - * The interrupt is stuck + * The interrupt might be stuck From ea76f538e8a282c9d2057cb480a8615c1689a4b8 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 16 Mar 2012 13:16:36 -0500 Subject: [PATCH 312/487] re-enable threading on hibernate compression/decompressio --- ...threading-in-compression-for-hibernate.patch | 17 ----------------- kernel.spec | 9 +++------ 2 files changed, 3 insertions(+), 23 deletions(-) delete mode 100644 disable-threading-in-compression-for-hibernate.patch diff --git a/disable-threading-in-compression-for-hibernate.patch b/disable-threading-in-compression-for-hibernate.patch deleted file mode 100644 index 685c294ef..000000000 --- a/disable-threading-in-compression-for-hibernate.patch +++ /dev/null @@ -1,17 +0,0 @@ -In attempt to find the cause of some of the hibernate issues we are seeing, -turn off threading for compression. - -Signed-off-by: Justin M. Forbes - -diff -ruNp a/kernel/power/swap.c b/kernel/power/swap.c ---- a/kernel/power/swap.c 2012-03-02 13:52:27.777485028 -0600 -+++ b/kernel/power/swap.c 2012-03-02 14:05:20.168115129 -0600 -@@ -401,7 +401,7 @@ static int swap_writer_finish(struct swa - #define LZO_CMP_SIZE (LZO_CMP_PAGES * PAGE_SIZE) - - /* Maximum number of threads for compression/decompression. */ --#define LZO_THREADS 3 -+#define LZO_THREADS 1 - - /* Maximum number of pages for read buffering. */ - #define LZO_READ_PAGES (MAP_PAGE_ENTRIES * 8) diff --git a/kernel.spec b/kernel.spec index adad4266a..95f32d00d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -815,9 +815,6 @@ Patch21240: ACPICA-Fix-regression-in-FADT-revision-checks.patch #rhbz 728478 Patch21242: sony-laptop-Enable-keyboard-backlight-by-default.patch -# Disable threading in hibernate compression -Patch21243: disable-threading-in-compression-for-hibernate.patch - #rhbz 803809 CVE-2012-1179 Patch21244: mm-thp-fix-pmd_bad-triggering.patch @@ -1564,9 +1561,6 @@ ApplyPatch ACPICA-Fix-regression-in-FADT-revision-checks.patch #rhbz 728478 ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch -#Disable threading in hibernate compression -ApplyPatch disable-threading-in-compression-for-hibernate.patch - ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch @@ -2392,6 +2386,9 @@ fi # and build. %changelog +* Fri Mar 16 2012 Justin M. Forbes +- re-enable threading on hibernate compression/decompression + * Fri Mar 16 2012 Josh Boyer - Fix irqpoll patch to really only apply for ASM108x machines (rhbz 800520) From d8b686023e84924ae01d8e0b733c63d38f08ea4c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 19 Mar 2012 13:39:58 -0400 Subject: [PATCH 313/487] Drop compat-wireless infrastructure in preparation for 3.3 rebase --- ...el-panic-during-driver-initilization.patch | 94 --- ...-fix-a-WEP-crypto-related-regression.patch | 43 -- ...tes-with-idx-1-in-ath9k-rate-control.patch | 39 - ...RN_ON_ONCE-in-ath_rc_get_highest_rix.patch | 29 - ..._hw-fix-a-RTS-CTS-timeout-regression.patch | 50 -- ...event-writes-to-const-data-on-AR9160.patch | 117 --- ...o-avoid-duplicating-device-support-w.patch | 47 -- bcma-Fix-mem-leak-in-bcma_bus_scan.patch | 51 -- bcma-don-t-fail-for-bad-SPROM-CRC.patch | 36 - ...ix-endless-retry-of-A-MPDU-transmiss.patch | 56 -- ...nly-print-block-ack-timeout-message-.patch | 37 - ...mac-fix-tx-queue-flush-infinite-loop.patch | 51 -- compat-wireless-config-fixups.patch | 67 -- compat-wireless-integrated-build.patch | 12 - ...at-wireless-pr_fmt-warning-avoidance.patch | 710 ------------------ ...8192cu-Fix-WARNING-on-suspend-resume.patch | 131 ---- config-backports | 29 - ...ss-up-QoS-counters-with-non-QoS-fram.patch | 89 --- iwlwifi-fix-PCI-E-transport-inta-race.patch | 51 -- iwlwifi-fix-key-removal.patch | 56 -- ...aggregation-enabled-on-ra-be-at-DEBU.patch | 30 - kernel.spec | 190 +---- mac80211-Fix-a-rwlock-bad-magic-bug.patch | 89 --- ...arning-on-changing-to-monitor-mode-f.patch | 72 -- ...-right-headroom-size-for-mesh-mgmt-f.patch | 83 -- ...11-call-rate-control-only-after-init.patch | 91 --- ...call-rate-control-.tx_status-before-.patch | 33 - ...0211-fix-debugfs-key-station-symlink.patch | 43 -- ...-bss_conf.idle-when-vif-is-connected.patch | 37 - ...-a-single-frame-in-the-rx-reorder-bu.patch | 33 - ...211-update-oper_channel-on-ibss-join.patch | 31 - ...itialize-count-field-in-ieee80211_tx.patch | 39 - ...on-to-allow-external-modules-to-avoi.patch | 80 -- ...dd-NULL-checks-in-driver-unload-path.patch | 66 -- ...evious-security-setting-during-assoc.patch | 55 -- ...e-association-failure-case-correctly.patch | 67 -- ...ong-128dBm-when-signal-is-stronger-t.patch | 55 -- ...-a-possible-NULL-pointer-dereference.patch | 37 - ...-rtl_pci_init-to-return-0-on-success.patch | 40 - sources | 1 - ssb-fix-cardbus-slot-in-hostmode.patch | 34 - ...e-needs-duration_id-set-to-zero-for-.patch | 51 -- 42 files changed, 14 insertions(+), 3038 deletions(-) delete mode 100644 ath9k-Fix-kernel-panic-during-driver-initilization.patch delete mode 100644 ath9k-fix-a-WEP-crypto-related-regression.patch delete mode 100644 ath9k-stop-on-rates-with-idx-1-in-ath9k-rate-control.patch delete mode 100644 ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch delete mode 100644 ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch delete mode 100644 ath9k_hw-prevent-writes-to-const-data-on-AR9160.patch delete mode 100644 b43-add-option-to-avoid-duplicating-device-support-w.patch delete mode 100644 bcma-Fix-mem-leak-in-bcma_bus_scan.patch delete mode 100644 bcma-don-t-fail-for-bad-SPROM-CRC.patch delete mode 100644 brcm80211-smac-fix-endless-retry-of-A-MPDU-transmiss.patch delete mode 100644 brcm80211-smac-only-print-block-ack-timeout-message-.patch delete mode 100644 brcmsmac-fix-tx-queue-flush-infinite-loop.patch delete mode 100644 compat-wireless-config-fixups.patch delete mode 100644 compat-wireless-integrated-build.patch delete mode 100644 compat-wireless-pr_fmt-warning-avoidance.patch delete mode 100644 compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch delete mode 100644 config-backports delete mode 100644 iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch delete mode 100644 iwlwifi-fix-PCI-E-transport-inta-race.patch delete mode 100644 iwlwifi-fix-key-removal.patch delete mode 100644 iwlwifi-make-Tx-aggregation-enabled-on-ra-be-at-DEBU.patch delete mode 100644 mac80211-Fix-a-rwlock-bad-magic-bug.patch delete mode 100644 mac80211-Fix-a-warning-on-changing-to-monitor-mode-f.patch delete mode 100644 mac80211-Use-the-right-headroom-size-for-mesh-mgmt-f.patch delete mode 100644 mac80211-call-rate-control-only-after-init.patch delete mode 100644 mac80211-do-not-call-rate-control-.tx_status-before-.patch delete mode 100644 mac80211-fix-debugfs-key-station-symlink.patch delete mode 100644 mac80211-set-bss_conf.idle-when-vif-is-connected.patch delete mode 100644 mac80211-timeout-a-single-frame-in-the-rx-reorder-bu.patch delete mode 100644 mac80211-update-oper_channel-on-ibss-join.patch delete mode 100644 mac80211-zero-initialize-count-field-in-ieee80211_tx.patch delete mode 100644 modpost-add-option-to-allow-external-modules-to-avoi.patch delete mode 100644 mwifiex-add-NULL-checks-in-driver-unload-path.patch delete mode 100644 mwifiex-clear-previous-security-setting-during-assoc.patch delete mode 100644 mwifiex-handle-association-failure-case-correctly.patch delete mode 100644 rt2800lib-fix-wrong-128dBm-when-signal-is-stronger-t.patch delete mode 100644 rt2x00-fix-a-possible-NULL-pointer-dereference.patch delete mode 100644 rtlwifi-Modify-rtl_pci_init-to-return-0-on-success.patch delete mode 100644 ssb-fix-cardbus-slot-in-hostmode.patch delete mode 100644 zd1211rw-firmware-needs-duration_id-set-to-zero-for-.patch diff --git a/ath9k-Fix-kernel-panic-during-driver-initilization.patch b/ath9k-Fix-kernel-panic-during-driver-initilization.patch deleted file mode 100644 index 385f39cd9..000000000 --- a/ath9k-Fix-kernel-panic-during-driver-initilization.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 07445f688218a48bde72316aed9de4fdcc173131 Mon Sep 17 00:00:00 2001 -From: Mohammed Shafi Shajakhan -Date: Thu, 2 Feb 2012 16:29:05 +0530 -Subject: [PATCH] ath9k: Fix kernel panic during driver initilization - -all works need to be initialized before ieee80211_register_hw -to prevent mac80211 call backs such as drv_start, drv_config -getting started. otherwise we would queue/cancel works before -initializing them and it leads to kernel panic. -this issue can be recreated with the following script -in Chrome laptops with AR928X cards, with background scan -running (or) Network manager is running - -while true -do -sudo modprobe -v ath9k -sleep 3 -sudo modprobe -r ath9k -sleep 3 -done - - EIP: [<81040a47>] __cancel_work_timer+0xb8/0xe1 SS:ESP 0068:f6be9d70 - ---[ end trace 4f86d6139a9900ef ]--- - Registered led device: ath9k-phy0 - ieee80211 phy0: Atheros AR9280 Rev:2 mem=0xf88a0000, - irq=16 - Kernel panic - not syncing: Fatal exception - Pid: 456, comm: wpa_supplicant Tainted: G D - 3.0.13 #1 - Call Trace: - [<81379e21>] panic+0x53/0x14a - [<81004a30>] oops_end+0x73/0x81 - [<81004b53>] die+0x4c/0x55 - [<81002710>] do_trap+0x7c/0x83 - [<81002855>] ? do_bounds+0x58/0x58 - [<810028cc>] do_invalid_op+0x77/0x81 - [<81040a47>] ? __cancel_work_timer+0xb8/0xe1 - [<810489ec>] ? sched_clock_cpu+0x81/0x11f - [<8103f809>] ? wait_on_work+0xe2/0xf7 - [<8137f807>] error_code+0x67/0x6c - [<810300d8>] ? wait_consider_task+0x4ba/0x84c - [<81040a47>] ? __cancel_work_timer+0xb8/0xe1 - [<810380c9>] ? try_to_del_timer_sync+0x5f/0x67 - [<81040a91>] cancel_work_sync+0xf/0x11 - [] ath_set_channel+0x62/0x25c [ath9k] - [] ? ath9k_tx_last_beacon+0x26a/0x85c [ath9k] - [] ath_radio_disable+0x3f1/0x68e [ath9k] - [] ieee80211_hw_config+0x111/0x116 [mac80211] - [] __ieee80211_recalc_idle+0x919/0xa37 [mac80211] - [] __ieee80211_recalc_idle+0xa33/0xa37 [mac80211] - [<812dbed8>] __dev_open+0x82/0xab - -Cc: -Cc: Gary Morain -Cc: Paul Stewart -Cc: Vasanthakumar Thiagarajan -Tested-by: Mohammed Shafi Shajakhan -Signed-off-by: Rajkumar Manoharan -Signed-off-by: Mohammed Shafi Shajakhan -Signed-off-by: John W. Linville ---- - drivers/net/wireless/ath/ath9k/init.c | 9 +++++---- - 1 files changed, 5 insertions(+), 4 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c -index abf9435..53a005d 100644 ---- a/drivers/net/wireless/ath/ath9k/init.c -+++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -822,6 +822,11 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, - ARRAY_SIZE(ath9k_tpt_blink)); - #endif - -+ INIT_WORK(&sc->hw_reset_work, ath_reset_work); -+ INIT_WORK(&sc->hw_check_work, ath_hw_check); -+ INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); -+ INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); -+ - /* Register with mac80211 */ - error = ieee80211_register_hw(hw); - if (error) -@@ -840,10 +845,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, - goto error_world; - } - -- INIT_WORK(&sc->hw_reset_work, ath_reset_work); -- INIT_WORK(&sc->hw_check_work, ath_hw_check); -- INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); -- INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); - sc->last_rssi = ATH_RSSI_DUMMY_MARKER; - - ath_init_leds(sc); --- -1.7.4.4 - diff --git a/ath9k-fix-a-WEP-crypto-related-regression.patch b/ath9k-fix-a-WEP-crypto-related-regression.patch deleted file mode 100644 index 54f603980..000000000 --- a/ath9k-fix-a-WEP-crypto-related-regression.patch +++ /dev/null @@ -1,43 +0,0 @@ -From f88373fa47f3ce6590fdfaa742d0ddacc2ae017f Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Sun, 5 Feb 2012 21:15:17 +0100 -Subject: [PATCH] ath9k: fix a WEP crypto related regression - -commit b4a82a0 "ath9k_hw: fix interpretation of the rx KeyMiss flag" -fixed the interpretation of the KeyMiss flag for keycache based lookups, -however WEP encryption uses a static index, so KeyMiss is always asserted -for it, even though frames are decrypted properly. -Fix this by clearing the ATH9K_RXERR_KEYMISS flag if no keycache based -lookup was performed. - -Signed-off-by: Felix Fietkau -Cc: stable@vger.kernel.org -Reported-by: Laurent Bonnans -Reported-by: Jurica Vukadin -Signed-off-by: John W. Linville ---- - drivers/net/wireless/ath/ath9k/recv.c | 8 ++++++++ - 1 files changed, 8 insertions(+), 0 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c -index 0e666fb..7e1a91a 100644 ---- a/drivers/net/wireless/ath/ath9k/recv.c -+++ b/drivers/net/wireless/ath/ath9k/recv.c -@@ -822,6 +822,14 @@ static bool ath9k_rx_accept(struct ath_common *common, - (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC | - ATH9K_RXERR_KEYMISS)); - -+ /* -+ * Key miss events are only relevant for pairwise keys where the -+ * descriptor does contain a valid key index. This has been observed -+ * mostly with CCMP encryption. -+ */ -+ if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID) -+ rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS; -+ - if (!rx_stats->rs_datalen) - return false; - /* --- -1.7.4.4 - diff --git a/ath9k-stop-on-rates-with-idx-1-in-ath9k-rate-control.patch b/ath9k-stop-on-rates-with-idx-1-in-ath9k-rate-control.patch deleted file mode 100644 index f118bd5c2..000000000 --- a/ath9k-stop-on-rates-with-idx-1-in-ath9k-rate-control.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 2504a6423b9ab4c36df78227055995644de19edb Mon Sep 17 00:00:00 2001 -From: Pavel Roskin -Date: Sat, 11 Feb 2012 10:01:53 -0500 -Subject: [PATCH] ath9k: stop on rates with idx -1 in ath9k rate control's - .tx_status - -Rate control algorithms are supposed to stop processing when they -encounter a rate with the index -1. Checking for rate->count not being -zero is not enough. - -Allowing a rate with negative index leads to memory corruption in -ath_debug_stat_rc(). - -One consequence of the bug is discussed at -https://bugzilla.redhat.com/show_bug.cgi?id=768639 - -Signed-off-by: Pavel Roskin -Cc: stable@vger.kernel.org -Signed-off-by: John W. Linville ---- - drivers/net/wireless/ath/ath9k/rc.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c -index 635b592..a427a16 100644 ---- a/drivers/net/wireless/ath/ath9k/rc.c -+++ b/drivers/net/wireless/ath/ath9k/rc.c -@@ -1346,7 +1346,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, - fc = hdr->frame_control; - for (i = 0; i < sc->hw->max_rates; i++) { - struct ieee80211_tx_rate *rate = &tx_info->status.rates[i]; -- if (!rate->count) -+ if (rate->idx < 0 || !rate->count) - break; - - final_ts_idx = i; --- -1.7.4.4 - diff --git a/ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch b/ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch deleted file mode 100644 index 7d5c9a5c8..000000000 --- a/ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 41b2d62702730b0c6bc5a40722e423bb0338311a Mon Sep 17 00:00:00 2001 -From: John W. Linville -Date: Mon, 30 Jan 2012 10:53:55 -0500 -Subject: [PATCH] ath9k: use WARN_ON_ONCE in ath_rc_get_highest_rix - -The device seems to survive the issue, so no need to flood the logs -about it... - -Signed-off-by: John W. Linville ---- - drivers/net/wireless/ath/ath9k/rc.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c -index b3c3798..635b592 100644 ---- a/drivers/net/wireless/ath/ath9k/rc.c -+++ b/drivers/net/wireless/ath/ath9k/rc.c -@@ -694,7 +694,7 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc, - return rate; - - /* This should not happen */ -- WARN_ON(1); -+ WARN_ON_ONCE(1); - - rate = ath_rc_priv->valid_rate_index[0]; - --- -1.7.4.4 - diff --git a/ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch b/ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch deleted file mode 100644 index 8aa5b2fc1..000000000 --- a/ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 55a2bb4a6d5e8c7b324d003e130fd9aaf33be4e6 Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Sun, 5 Feb 2012 21:15:18 +0100 -Subject: [PATCH] ath9k_hw: fix a RTS/CTS timeout regression - -commit adb5066 "ath9k_hw: do not apply the 2.4 ghz ack timeout -workaround to cts" reduced the hardware CTS timeout to the normal -values specified by the standard, but it turns out while it doesn't -need the same extra time that it needs for the ACK timeout, it -does need more than the value specified in the standard, but only -for 2.4 GHz. - -This patch brings the CTS timeout value in sync with the initialization -values, while still allowing adjustment for bigger distances. - -Signed-off-by: Felix Fietkau -Cc: stable@vger.kernel.org -Reported-by: Seth Forshee -Reported-by: Marek Lindner -Signed-off-by: John W. Linville ---- - drivers/net/wireless/ath/ath9k/hw.c | 7 +++++-- - 1 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c -index ee77595..87db1ee 100644 ---- a/drivers/net/wireless/ath/ath9k/hw.c -+++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -1037,13 +1037,16 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) - - /* - * Workaround for early ACK timeouts, add an offset to match the -- * initval's 64us ack timeout value. -+ * initval's 64us ack timeout value. Use 48us for the CTS timeout. - * This was initially only meant to work around an issue with delayed - * BA frames in some implementations, but it has been found to fix ACK - * timeout issues in other cases as well. - */ -- if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) -+ if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) { - acktimeout += 64 - sifstime - ah->slottime; -+ ctstimeout += 48 - sifstime - ah->slottime; -+ } -+ - - ath9k_hw_set_sifs_time(ah, sifstime); - ath9k_hw_setslottime(ah, slottime); --- -1.7.4.4 - diff --git a/ath9k_hw-prevent-writes-to-const-data-on-AR9160.patch b/ath9k_hw-prevent-writes-to-const-data-on-AR9160.patch deleted file mode 100644 index f034020d9..000000000 --- a/ath9k_hw-prevent-writes-to-const-data-on-AR9160.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 9bbb8168ed3d8b946f9c1901a63a675012de88f2 Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Wed, 15 Feb 2012 19:31:20 +0100 -Subject: [PATCH] ath9k_hw: prevent writes to const data on AR9160 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Duplicate the data for iniAddac early on, to avoid having to do redundant -memcpy calls later. While we're at it, make AR5416 < v2.2 use the same -codepath. Fixes a reported crash on x86. - -Signed-off-by: Felix Fietkau -Reported-by: Magnus Määttä -Cc: stable@vger.kernel.org -Signed-off-by: John W. Linville ---- - drivers/net/wireless/ath/ath9k/ar5008_phy.c | 25 +------------------------ - drivers/net/wireless/ath/ath9k/ar9002_hw.c | 19 +++++++++++++++++++ - drivers/net/wireless/ath/ath9k/hw.h | 1 - - 3 files changed, 20 insertions(+), 25 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c -index f901a17..86a891f 100644 ---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c -+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c -@@ -489,8 +489,6 @@ static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah) - ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows); - ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows); - ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows); -- ATH_ALLOC_BANK(ah->addac5416_21, -- ah->iniAddac.ia_rows * ah->iniAddac.ia_columns); - ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows); - - return 0; -@@ -519,7 +517,6 @@ static void ar5008_hw_rf_free_ext_banks(struct ath_hw *ah) - ATH_FREE_BANK(ah->analogBank6Data); - ATH_FREE_BANK(ah->analogBank6TPCData); - ATH_FREE_BANK(ah->analogBank7Data); -- ATH_FREE_BANK(ah->addac5416_21); - ATH_FREE_BANK(ah->bank6Temp); - - #undef ATH_FREE_BANK -@@ -805,27 +802,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, - if (ah->eep_ops->set_addac) - ah->eep_ops->set_addac(ah, chan); - -- if (AR_SREV_5416_22_OR_LATER(ah)) { -- REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites); -- } else { -- struct ar5416IniArray temp; -- u32 addacSize = -- sizeof(u32) * ah->iniAddac.ia_rows * -- ah->iniAddac.ia_columns; -- -- /* For AR5416 2.0/2.1 */ -- memcpy(ah->addac5416_21, -- ah->iniAddac.ia_array, addacSize); -- -- /* override CLKDRV value at [row, column] = [31, 1] */ -- (ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0; -- -- temp.ia_array = ah->addac5416_21; -- temp.ia_columns = ah->iniAddac.ia_columns; -- temp.ia_rows = ah->iniAddac.ia_rows; -- REG_WRITE_ARRAY(&temp, 1, regWrites); -- } -- -+ REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites); - REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); - - ENABLE_REGWRITE_BUFFER(ah); -diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c -index 11f192a..d190411 100644 ---- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c -+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c -@@ -180,6 +180,25 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) - INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac, - ARRAY_SIZE(ar5416Addac), 2); - } -+ -+ /* iniAddac needs to be modified for these chips */ -+ if (AR_SREV_9160(ah) || !AR_SREV_5416_22_OR_LATER(ah)) { -+ struct ar5416IniArray *addac = &ah->iniAddac; -+ u32 size = sizeof(u32) * addac->ia_rows * addac->ia_columns; -+ u32 *data; -+ -+ data = kmalloc(size, GFP_KERNEL); -+ if (!data) -+ return; -+ -+ memcpy(data, addac->ia_array, size); -+ addac->ia_array = data; -+ -+ if (!AR_SREV_5416_22_OR_LATER(ah)) { -+ /* override CLKDRV value */ -+ INI_RA(addac, 31,1) = 0; -+ } -+ } - } - - /* Support for Japan ch.14 (2484) spread */ -diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h -index 6a29004..c8261d4 100644 ---- a/drivers/net/wireless/ath/ath9k/hw.h -+++ b/drivers/net/wireless/ath/ath9k/hw.h -@@ -940,7 +940,6 @@ struct ath_hw { - u32 *analogBank6Data; - u32 *analogBank6TPCData; - u32 *analogBank7Data; -- u32 *addac5416_21; - u32 *bank6Temp; - - u8 txpower_limit; --- -1.7.4.4 - diff --git a/b43-add-option-to-avoid-duplicating-device-support-w.patch b/b43-add-option-to-avoid-duplicating-device-support-w.patch deleted file mode 100644 index ca820dfe0..000000000 --- a/b43-add-option-to-avoid-duplicating-device-support-w.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 4f3d09de38d234ce7ffba5ec5a7e6704f983d375 Mon Sep 17 00:00:00 2001 -From: John W. Linville -Date: Wed, 11 Jan 2012 15:50:15 -0500 -Subject: [PATCH 5/8] b43: add option to avoid duplicating device support with - brcmsmac - -Signed-off-by: John W. Linville ---- - drivers/net/wireless/b43/Kconfig | 6 ++++++ - drivers/net/wireless/b43/main.c | 2 ++ - 2 files changed, 8 insertions(+), 0 deletions(-) - -diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig -index b97a40e..3876c7e 100644 ---- a/drivers/net/wireless/b43/Kconfig -+++ b/drivers/net/wireless/b43/Kconfig -@@ -31,6 +31,12 @@ config B43_BCMA - depends on B43 && BCMA - default y - -+config B43_BCMA_EXTRA -+ bool "Hardware support that overlaps with the brcmsmac driver" -+ depends on B43_BCMA -+ default n if BRCMSMAC || BRCMSMAC_MODULE -+ default y -+ - config B43_SSB - bool - depends on B43 && SSB -diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c -index b91f28e..23ffb1b 100644 ---- a/drivers/net/wireless/b43/main.c -+++ b/drivers/net/wireless/b43/main.c -@@ -116,8 +116,10 @@ MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO"); - #ifdef CONFIG_B43_BCMA - static const struct bcma_device_id b43_bcma_tbl[] = { - BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS), -+#ifdef CONFIG_B43_BCMA_EXTRA - BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS), - BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS), -+#endif - BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS), - BCMA_CORETABLE_END - }; --- -1.7.4.4 - diff --git a/bcma-Fix-mem-leak-in-bcma_bus_scan.patch b/bcma-Fix-mem-leak-in-bcma_bus_scan.patch deleted file mode 100644 index d888e8c8b..000000000 --- a/bcma-Fix-mem-leak-in-bcma_bus_scan.patch +++ /dev/null @@ -1,51 +0,0 @@ -From f9721ed2707661af75a414d09cdcd71f99a13f62 Mon Sep 17 00:00:00 2001 -From: Jesper Juhl -Date: Sun, 29 Jan 2012 21:34:04 +0100 -Subject: [PATCH] bcma: Fix mem leak in bcma_bus_scan() - -bcma_bus_scan() leaks 'struct bcma_device' bytes if -bcma_get_next_core() returns error. - -Restructure the code so we always kfree() the memory we allocate to -the variable 'core' before it goes out of scope. - -Signed-off-by: Jesper Juhl -Signed-off-by: John W. Linville ---- - drivers/bcma/scan.c | 19 +++++++++++-------- - 1 files changed, 11 insertions(+), 8 deletions(-) - -diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c -index cad9948..3a2f672 100644 ---- a/drivers/bcma/scan.c -+++ b/drivers/bcma/scan.c -@@ -399,15 +399,18 @@ int bcma_bus_scan(struct bcma_bus *bus) - core->bus = bus; - - err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core); -- if (err == -ENODEV) { -- core_num++; -- continue; -- } else if (err == -ENXIO) -- continue; -- else if (err == -ESPIPE) -- break; -- else if (err < 0) -+ if (err < 0) { -+ kfree(core); -+ if (err == -ENODEV) { -+ core_num++; -+ continue; -+ } else if (err == -ENXIO) { -+ continue; -+ } else if (err == -ESPIPE) { -+ break; -+ } - return err; -+ } - - core->core_index = core_num++; - bus->nr_cores++; --- -1.7.4.4 - diff --git a/bcma-don-t-fail-for-bad-SPROM-CRC.patch b/bcma-don-t-fail-for-bad-SPROM-CRC.patch deleted file mode 100644 index 6769c2b34..000000000 --- a/bcma-don-t-fail-for-bad-SPROM-CRC.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 2e6b411971de727a5bcea4323331fdaa70a81b11 Mon Sep 17 00:00:00 2001 -From: Henrik Rydberg -Date: Tue, 31 Jan 2012 14:22:15 -0500 -Subject: [PATCH] bcma: don't fail for bad SPROM CRC - -The brcmsmac driver is now using the bcma SPROM CRC check, which does -not recognize all chipsets that were functional prior to the switch. In -particular, the current code bails out on odd CRC errors in recent -Macbooks. This patch ignores those errors, with the argument that an -unrecognized SPROM should be treated similarly to a non-existing one. - -Signed-off-by: Henrik Rydberg -Signed-off-by: John W. Linville ---- - drivers/bcma/main.c | 4 +--- - 1 files changed, 1 insertions(+), 3 deletions(-) - -diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c -index febbc0a..ec31f7d 100644 ---- a/drivers/bcma/main.c -+++ b/drivers/bcma/main.c -@@ -169,10 +169,8 @@ int bcma_bus_register(struct bcma_bus *bus) - err = bcma_sprom_get(bus); - if (err == -ENOENT) { - pr_err("No SPROM available\n"); -- } else if (err) { -+ } else if (err) - pr_err("Failed to get SPROM: %d\n", err); -- return -ENOENT; -- } - - /* Register found cores */ - bcma_register_cores(bus); --- -1.7.4.4 - diff --git a/brcm80211-smac-fix-endless-retry-of-A-MPDU-transmiss.patch b/brcm80211-smac-fix-endless-retry-of-A-MPDU-transmiss.patch deleted file mode 100644 index c50c64248..000000000 --- a/brcm80211-smac-fix-endless-retry-of-A-MPDU-transmiss.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 85091fc0a75653e239dc8379658515e577544927 Mon Sep 17 00:00:00 2001 -From: Arend van Spriel -Date: Thu, 23 Feb 2012 18:38:22 +0100 -Subject: [PATCH] brcm80211: smac: fix endless retry of A-MPDU transmissions - -The A-MPDU code checked against a retry limit, but it was using -the wrong variable to do so. This patch fixes this to assure -proper retry mechanism. - -This problem had a side-effect causing the mac80211 flush callback -to remain waiting forever as well. That side effect has been fixed -by commit by Stanislaw Gruszka: - -commit f96b08a7e6f69c0f0a576554df3df5b1b519c479 -Date: Tue Jan 17 12:38:50 2012 +0100 - - brcmsmac: fix tx queue flush infinite loop - - Reference: - https://bugzilla.kernel.org/show_bug.cgi?id=42576 - -Cc: Stanislaw Gruszka -Reviewed-by: Pieter-Paul Giesberts -Reviewed-by: Alwin Beukers -Signed-off-by: Arend van Spriel -Signed-off-by: John W. Linville ---- - drivers/net/wireless/brcm80211/brcmsmac/ampdu.c | 6 +----- - 1 files changed, 1 insertions(+), 5 deletions(-) - -diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c -index 90911ee..9265226 100644 ---- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c -+++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c -@@ -1051,17 +1051,13 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, - } - /* either retransmit or send bar if ack not recd */ - if (!ack_recd) { -- struct ieee80211_tx_rate *txrate = -- tx_info->status.rates; -- if (retry && (txrate[0].count < (int)retry_limit)) { -+ if (retry && (ini->txretry[index] < (int)retry_limit)) { - ini->txretry[index]++; - ini->tx_in_transit--; - /* - * Use high prededence for retransmit to - * give some punch - */ -- /* brcms_c_txq_enq(wlc, scb, p, -- * BRCMS_PRIO_TO_PREC(tid)); */ - brcms_c_txq_enq(wlc, scb, p, - BRCMS_PRIO_TO_HI_PREC(tid)); - } else { --- -1.7.4.4 - diff --git a/brcm80211-smac-only-print-block-ack-timeout-message-.patch b/brcm80211-smac-only-print-block-ack-timeout-message-.patch deleted file mode 100644 index b0e9d6974..000000000 --- a/brcm80211-smac-only-print-block-ack-timeout-message-.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 2b0a53d51b5f263bb581bbdb40ebb9f7e09609b1 Mon Sep 17 00:00:00 2001 -From: Arend van Spriel -Date: Thu, 23 Feb 2012 18:38:23 +0100 -Subject: [PATCH] brcm80211: smac: only print block-ack timeout message at - trace level - -In regular use block-ack timeouts can happen so it does not make -sense to fill the log with these messages. - -Reviewed-by: Pieter-Paul Giesberts -Reviewed-by: Alwin Beukers -Signed-off-by: Arend van Spriel -Signed-off-by: John W. Linville ---- - drivers/net/wireless/brcm80211/brcmsmac/ampdu.c | 6 +++--- - 1 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c -index 9265226..30b5887 100644 ---- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c -+++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c -@@ -1070,9 +1070,9 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, - IEEE80211_TX_STAT_AMPDU_NO_BACK; - skb_pull(p, D11_PHY_HDR_LEN); - skb_pull(p, D11_TXH_LEN); -- wiphy_err(wiphy, "%s: BA Timeout, seq %d, in_" -- "transit %d\n", "AMPDU status", seq, -- ini->tx_in_transit); -+ BCMMSG(wiphy, -+ "BA Timeout, seq %d, in_transit %d\n", -+ seq, ini->tx_in_transit); - ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, - p); - } --- -1.7.4.4 - diff --git a/brcmsmac-fix-tx-queue-flush-infinite-loop.patch b/brcmsmac-fix-tx-queue-flush-infinite-loop.patch deleted file mode 100644 index c5d69d467..000000000 --- a/brcmsmac-fix-tx-queue-flush-infinite-loop.patch +++ /dev/null @@ -1,51 +0,0 @@ -From f96b08a7e6f69c0f0a576554df3df5b1b519c479 Mon Sep 17 00:00:00 2001 -From: Stanislaw Gruszka -Date: Tue, 17 Jan 2012 12:38:50 +0100 -Subject: [PATCH 2/8] brcmsmac: fix tx queue flush infinite loop - -This patch workaround live deadlock problem caused by infinite loop -in brcms_c_wait_for_tx_completion(). I do not consider the patch as -the proper fix, which should fix the real reason of tx queue flush -failure, but patch helps with system lockup. - -Reference: -https://bugzilla.kernel.org/show_bug.cgi?id=42576 - -Reported-and-tested-by: Patrick -Cc: stable@vger.kernel.org # 3.2+ -Signed-off-by: Stanislaw Gruszka -Signed-off-by: John W. Linville ---- - drivers/net/wireless/brcm80211/brcmsmac/main.c | 10 +++++++++- - 1 files changed, 9 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c -index f7ed340..f6affc6 100644 ---- a/drivers/net/wireless/brcm80211/brcmsmac/main.c -+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c -@@ -7981,13 +7981,21 @@ int brcms_c_get_curband(struct brcms_c_info *wlc) - - void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop) - { -+ int timeout = 20; -+ - /* flush packet queue when requested */ - if (drop) - brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL); - - /* wait for queue and DMA fifos to run dry */ -- while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0) -+ while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0) { - brcms_msleep(wlc->wl, 1); -+ -+ if (--timeout == 0) -+ break; -+ } -+ -+ WARN_ON_ONCE(timeout == 0); - } - - void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval) --- -1.7.4.4 - diff --git a/compat-wireless-config-fixups.patch b/compat-wireless-config-fixups.patch deleted file mode 100644 index 7bb19bcdc..000000000 --- a/compat-wireless-config-fixups.patch +++ /dev/null @@ -1,67 +0,0 @@ -diff -up compat-wireless-3.3-rc1-2/config.mk.orig compat-wireless-3.3-rc1-2/config.mk ---- compat-wireless-3.3-rc1-2/config.mk.orig 2012-01-21 02:00:21.000000000 -0500 -+++ compat-wireless-3.3-rc1-2/config.mk 2012-01-24 15:16:38.204409844 -0500 -@@ -14,6 +14,9 @@ else - include $(KLIB_BUILD)/.config - endif - -+# Enable SSB module (needs to be visible in compat_autoconf.h) -+CONFIG_SSB=m -+ - ifneq ($(wildcard $(KLIB_BUILD)/Makefile),) - - COMPAT_LATEST_VERSION = 3 -diff -up compat-wireless-3.3-rc1-2/drivers/net/ethernet/atheros/Makefile.orig compat-wireless-3.3-rc1-2/drivers/net/ethernet/atheros/Makefile ---- compat-wireless-3.3-rc1-2/drivers/net/ethernet/atheros/Makefile.orig 2012-01-21 02:08:39.000000000 -0500 -+++ compat-wireless-3.3-rc1-2/drivers/net/ethernet/atheros/Makefile 2012-01-24 15:16:38.204409844 -0500 -@@ -2,7 +2,7 @@ - # Makefile for the Atheros network device drivers. - # - --obj-$(CONFIG_ATL1) += atlx/ --obj-$(CONFIG_ATL2) += atlx/ --obj-$(CONFIG_ATL1E) += atl1e/ --obj-$(CONFIG_ATL1C) += atl1c/ -+#obj-$(CONFIG_ATL1) += atlx/ -+#obj-$(CONFIG_ATL2) += atlx/ -+#obj-$(CONFIG_ATL1E) += atl1e/ -+#obj-$(CONFIG_ATL1C) += atl1c/ -diff -up compat-wireless-3.3-rc1-2/drivers/net/usb/Makefile.orig compat-wireless-3.3-rc1-2/drivers/net/usb/Makefile ---- compat-wireless-3.3-rc1-2/drivers/net/usb/Makefile.orig 2012-01-21 02:08:39.000000000 -0500 -+++ compat-wireless-3.3-rc1-2/drivers/net/usb/Makefile 2012-01-24 15:16:38.205409832 -0500 -@@ -2,7 +2,7 @@ - # Makefile for USB Network drivers - # - --obj-$(CONFIG_USB_NET_COMPAT_CDCETHER) += cdc_ether.o --obj-$(CONFIG_USB_NET_COMPAT_RNDIS_HOST) += rndis_host.o --obj-$(CONFIG_USB_COMPAT_USBNET) += usbnet.o -+#obj-$(CONFIG_USB_NET_COMPAT_CDCETHER) += cdc_ether.o -+#obj-$(CONFIG_USB_NET_COMPAT_RNDIS_HOST) += rndis_host.o -+#obj-$(CONFIG_USB_COMPAT_USBNET) += usbnet.o - -diff -up compat-wireless-3.3-rc1-2/Makefile.orig compat-wireless-3.3-rc1-2/Makefile ---- compat-wireless-3.3-rc1-2/Makefile.orig 2012-01-21 02:00:21.000000000 -0500 -+++ compat-wireless-3.3-rc1-2/Makefile 2012-01-24 15:17:34.524705743 -0500 -@@ -10,8 +10,8 @@ export KLIB_BUILD ?= $(KLIB)/build - MODPROBE := /sbin/modprobe - - ifneq ($(wildcard $(MODPROBE)),) --MADWIFI=$(shell $(MODPROBE) -l ath_pci) --OLD_IWL=$(shell $(MODPROBE) -l iwl4965) -+MADWIFI="" -+OLD_IWL="" - endif - - DESTDIR?= -@@ -44,8 +44,8 @@ endif - - endif - --obj-$(CONFIG_COMPAT_BLUETOOTH) += net/bluetooth/ --obj-$(CONFIG_COMPAT_BLUETOOTH_MODULES) += drivers/bluetooth/ -+#obj-$(CONFIG_COMPAT_BLUETOOTH) += net/bluetooth/ -+#obj-$(CONFIG_COMPAT_BLUETOOTH_MODULES) += drivers/bluetooth/ - - else - diff --git a/compat-wireless-integrated-build.patch b/compat-wireless-integrated-build.patch deleted file mode 100644 index 1d08e4b58..000000000 --- a/compat-wireless-integrated-build.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up compat-wireless-2011-12-01/Makefile.orig compat-wireless-2011-12-01/Makefile ---- compat-wireless-2011-12-01/Makefile.orig 2011-12-14 09:10:01.377297637 -0500 -+++ compat-wireless-2011-12-01/Makefile 2011-12-14 09:47:36.834100534 -0500 -@@ -68,7 +68,7 @@ all: modules - - modules: $(CREL_CHECK) - @./scripts/check_config.sh -- $(MAKE) -C $(KLIB_BUILD) M=$(PWD) modules -+ $(MAKE) -C $(KLIB_BUILD) M=$(PWD) INTEGRATED_BUILD=1 modules - @touch $@ - - bt: $(CREL_CHECK) diff --git a/compat-wireless-pr_fmt-warning-avoidance.patch b/compat-wireless-pr_fmt-warning-avoidance.patch deleted file mode 100644 index 7ca8f02fc..000000000 --- a/compat-wireless-pr_fmt-warning-avoidance.patch +++ /dev/null @@ -1,710 +0,0 @@ -diff -up compat-wireless-2011-12-18/compat/crc8.c.orig compat-wireless-2011-12-18/compat/crc8.c ---- compat-wireless-2011-12-18/compat/crc8.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/compat/crc8.c 2012-01-05 13:40:29.271996550 -0500 -@@ -14,6 +14,7 @@ - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/bcma/bcma_private.h.orig compat-wireless-2011-12-18/drivers/bcma/bcma_private.h ---- compat-wireless-2011-12-18/drivers/bcma/bcma_private.h.orig 2011-12-18 16:10:34.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/bcma/bcma_private.h 2012-01-05 13:40:29.271996550 -0500 -@@ -1,6 +1,7 @@ - #ifndef LINUX_BCMA_PRIVATE_H_ - #define LINUX_BCMA_PRIVATE_H_ - -+#undef pr_fmt - #ifndef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #endif -diff -up compat-wireless-2011-12-18/drivers/net/ethernet/broadcom/b44.c.orig compat-wireless-2011-12-18/drivers/net/ethernet/broadcom/b44.c ---- compat-wireless-2011-12-18/drivers/net/ethernet/broadcom/b44.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/ethernet/broadcom/b44.c 2012-01-05 13:40:29.273996525 -0500 -@@ -10,6 +10,7 @@ - * Distribute under GPL. - */ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c.orig compat-wireless-2011-12-18/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c ---- compat-wireless-2011-12-18/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c.orig 2012-01-05 13:44:54.137685272 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c 2012-01-05 13:44:56.589654617 -0500 -@@ -16,6 +16,7 @@ - * File contents: support functions for PCI/PCIe - */ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/brcm80211/brcmsmac/dma.c.orig compat-wireless-2011-12-18/drivers/net/wireless/brcm80211/brcmsmac/dma.c ---- compat-wireless-2011-12-18/drivers/net/wireless/brcm80211/brcmsmac/dma.c.orig 2012-01-05 13:44:23.579067307 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/brcm80211/brcmsmac/dma.c 2012-01-05 13:44:43.324820451 -0500 -@@ -14,6 +14,7 @@ - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/iwlegacy/3945-mac.c.orig compat-wireless-2011-12-18/drivers/net/wireless/iwlegacy/3945-mac.c ---- compat-wireless-2011-12-18/drivers/net/wireless/iwlegacy/3945-mac.c.orig 2012-01-05 13:41:22.852326703 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/iwlegacy/3945-mac.c 2012-01-05 13:41:31.209222227 -0500 -@@ -27,6 +27,7 @@ - * - *****************************************************************************/ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/iwlegacy/4965-mac.c.orig compat-wireless-2011-12-18/drivers/net/wireless/iwlegacy/4965-mac.c ---- compat-wireless-2011-12-18/drivers/net/wireless/iwlegacy/4965-mac.c.orig 2012-01-05 13:41:47.962012787 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/iwlegacy/4965-mac.c 2012-01-05 13:41:41.547092984 -0500 -@@ -27,6 +27,7 @@ - * - *****************************************************************************/ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas/cfg.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas/cfg.c ---- compat-wireless-2011-12-18/drivers/net/wireless/libertas/cfg.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/libertas/cfg.c 2012-01-05 13:40:44.681803897 -0500 -@@ -6,6 +6,7 @@ - * - */ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_cs.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_cs.c ---- compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_cs.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_cs.c 2012-01-05 13:40:44.682803885 -0500 -@@ -21,6 +21,7 @@ - - */ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_sdio.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_sdio.c ---- compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_sdio.c.orig 2011-12-18 16:10:36.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_sdio.c 2012-01-05 13:40:44.683803873 -0500 -@@ -26,6 +26,7 @@ - * if_sdio_card_to_host() to pad the data. - */ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_spi.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_spi.c ---- compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_spi.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_spi.c 2012-01-05 13:40:44.685803849 -0500 -@@ -17,6 +17,7 @@ - * (at your option) any later version. - */ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_usb.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_usb.c ---- compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_usb.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/libertas/if_usb.c 2012-01-05 13:40:44.686803837 -0500 -@@ -2,6 +2,7 @@ - * This file contains functions used in USB interface module. - */ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas/main.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas/main.c ---- compat-wireless-2011-12-18/drivers/net/wireless/libertas/main.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/libertas/main.c 2012-01-05 13:40:44.687803825 -0500 -@@ -4,6 +4,7 @@ - * thread etc.. - */ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas/mesh.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas/mesh.c ---- compat-wireless-2011-12-18/drivers/net/wireless/libertas/mesh.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/libertas/mesh.c 2012-01-05 13:40:44.688803813 -0500 -@@ -1,3 +1,4 @@ -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas/rx.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas/rx.c ---- compat-wireless-2011-12-18/drivers/net/wireless/libertas/rx.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/libertas/rx.c 2012-01-05 13:40:44.689803801 -0500 -@@ -2,6 +2,7 @@ - * This file contains the handling of RX in wlan driver. - */ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/cmd.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/cmd.c ---- compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/cmd.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/cmd.c 2012-01-05 13:40:44.690803789 -0500 -@@ -7,6 +7,7 @@ - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - */ -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/if_usb.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/if_usb.c ---- compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/if_usb.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/if_usb.c 2012-01-05 13:40:44.691803776 -0500 -@@ -9,6 +9,7 @@ - */ - #define DRV_NAME "lbtf_usb" - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include "libertas_tf.h" -diff -up compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/main.c.orig compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/main.c ---- compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/main.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/libertas_tf/main.c 2012-01-05 13:40:44.692803763 -0500 -@@ -7,6 +7,7 @@ - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - */ -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/base.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/base.c ---- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/base.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/base.c 2012-01-05 13:40:44.693803750 -0500 -@@ -27,6 +27,7 @@ - * - *****************************************************************************/ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/cam.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/cam.c ---- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/cam.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/cam.c 2012-01-05 13:40:44.694803737 -0500 -@@ -27,6 +27,7 @@ - * - *****************************************************************************/ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c ---- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-05 13:40:44.694803737 -0500 -@@ -27,6 +27,7 @@ - * - *****************************************************************************/ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c ---- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c 2012-01-05 13:40:44.695803725 -0500 -@@ -27,6 +27,7 @@ - * - *****************************************************************************/ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include "../wifi.h" -diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c ---- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c 2012-01-05 13:40:44.695803725 -0500 -@@ -27,6 +27,7 @@ - * - ****************************************************************************/ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192de/sw.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192de/sw.c ---- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192de/sw.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192de/sw.c 2012-01-05 13:40:44.695803725 -0500 -@@ -27,6 +27,7 @@ - * - *****************************************************************************/ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/hw.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/hw.c ---- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/hw.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/hw.c 2012-01-05 13:40:44.696803713 -0500 -@@ -27,6 +27,7 @@ - * - *****************************************************************************/ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include "../wifi.h" -diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/phy.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/phy.c ---- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/phy.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/phy.c 2012-01-05 13:40:44.696803713 -0500 -@@ -27,6 +27,7 @@ - * - *****************************************************************************/ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include "../wifi.h" -diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/rf.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/rf.c ---- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/rf.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/rf.c 2012-01-05 13:40:44.697803701 -0500 -@@ -27,6 +27,7 @@ - * - *****************************************************************************/ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include "../wifi.h" -diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/sw.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/sw.c ---- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/sw.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/rtl8192se/sw.c 2012-01-05 13:40:44.697803701 -0500 -@@ -27,6 +27,7 @@ - * - *****************************************************************************/ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/usb.c.orig compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/usb.c ---- compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/usb.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/drivers/net/wireless/rtlwifi/usb.c 2012-01-05 13:40:44.697803701 -0500 -@@ -25,6 +25,7 @@ - * - *****************************************************************************/ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/net/wireless/core.c.orig compat-wireless-2011-12-18/net/wireless/core.c ---- compat-wireless-2011-12-18/net/wireless/core.c.orig 2011-12-18 16:10:35.000000000 -0500 -+++ compat-wireless-2011-12-18/net/wireless/core.c 2012-01-05 13:40:44.698803689 -0500 -@@ -4,6 +4,7 @@ - * Copyright 2006-2010 Johannes Berg - */ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/net/wireless/lib80211.c.orig compat-wireless-2011-12-18/net/wireless/lib80211.c ---- compat-wireless-2011-12-18/net/wireless/lib80211.c.orig 2011-12-18 16:10:34.000000000 -0500 -+++ compat-wireless-2011-12-18/net/wireless/lib80211.c 2012-01-05 13:40:44.698803689 -0500 -@@ -13,6 +13,7 @@ - * - */ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/net/wireless/lib80211_crypt_tkip.c.orig compat-wireless-2011-12-18/net/wireless/lib80211_crypt_tkip.c ---- compat-wireless-2011-12-18/net/wireless/lib80211_crypt_tkip.c.orig 2011-12-18 16:10:34.000000000 -0500 -+++ compat-wireless-2011-12-18/net/wireless/lib80211_crypt_tkip.c 2012-01-05 13:40:44.698803689 -0500 -@@ -10,6 +10,7 @@ - * more details. - */ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/net/wireless/reg.c.orig compat-wireless-2011-12-18/net/wireless/reg.c ---- compat-wireless-2011-12-18/net/wireless/reg.c.orig 2011-12-18 16:10:34.000000000 -0500 -+++ compat-wireless-2011-12-18/net/wireless/reg.c 2012-01-05 13:40:44.699803676 -0500 -@@ -33,6 +33,7 @@ - * - */ - -+#undef pr_fmt - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff -up compat-wireless-2011-12-18/patches/98-pr_fmt.patch.orig compat-wireless-2011-12-18/patches/98-pr_fmt.patch ---- compat-wireless-2011-12-18/patches/98-pr_fmt.patch.orig 2012-01-05 13:39:36.552655633 -0500 -+++ compat-wireless-2011-12-18/patches/98-pr_fmt.patch 2012-01-05 13:39:36.553655620 -0500 -@@ -0,0 +1,346 @@ -+The way the compat-* header files are included causes the default -+pr_fmt definition from to be evaluated for every file. -+Files that define pr_fmt then generate a lot of build SPAM about -+pr_fmt being redefined. -+ -+Eliminate the build noise by preemptively undefining pr_fmt in those -+files that define it. -+ -+diff -up compat-wireless-3.2-rc1-1/compat/crc8.c.pr_fmt compat-wireless-3.2-rc1-1/compat/crc8.c -+--- compat-wireless-3.2-rc1-1/compat/crc8.c.pr_fmt 2011-11-18 15:08:04.497812086 -0500 -++++ compat-wireless-3.2-rc1-1/compat/crc8.c 2011-11-18 15:20:09.450522691 -0500 -+@@ -14,6 +14,7 @@ -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/bcma/bcma_private.h.pr_fmt compat-wireless-3.2-rc1-1/drivers/bcma/bcma_private.h -+--- compat-wireless-3.2-rc1-1/drivers/bcma/bcma_private.h.pr_fmt 2011-11-18 15:08:04.522323679 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/bcma/bcma_private.h 2011-11-18 15:20:09.451522757 -0500 -+@@ -1,6 +1,7 @@ -+ #ifndef LINUX_BCMA_PRIVATE_H_ -+ #define LINUX_BCMA_PRIVATE_H_ -+ -++#undef pr_fmt -+ #ifndef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ #endif -+diff -up compat-wireless-3.2-rc1-1/drivers/net/ethernet/broadcom/b44.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/ethernet/broadcom/b44.c -+--- compat-wireless-3.2-rc1-1/drivers/net/ethernet/broadcom/b44.c.pr_fmt 2011-11-18 15:08:04.529757401 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/ethernet/broadcom/b44.c 2011-11-18 15:20:09.453522618 -0500 -+@@ -10,6 +10,7 @@ -+ * Distribute under GPL. -+ */ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/iwlegacy/iwl3945-base.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/iwlegacy/iwl3945-base.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/iwlegacy/iwl3945-base.c.pr_fmt 2011-11-18 15:08:04.531811389 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/iwlegacy/iwl3945-base.c 2011-11-18 15:20:09.455522411 -0500 -+@@ -27,6 +27,7 @@ -+ * -+ *****************************************************************************/ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/iwlegacy/iwl4965-base.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/iwlegacy/iwl4965-base.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/iwlegacy/iwl4965-base.c.pr_fmt 2011-11-18 15:08:04.533811528 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/iwlegacy/iwl4965-base.c 2011-11-18 15:20:09.456520247 -0500 -+@@ -27,6 +27,7 @@ -+ * -+ *****************************************************************************/ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/cfg.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/cfg.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/cfg.c.pr_fmt 2011-11-18 15:08:04.534811319 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/cfg.c 2011-11-18 15:20:09.456520247 -0500 -+@@ -6,6 +6,7 @@ -+ * -+ */ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_cs.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_cs.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_cs.c.pr_fmt 2011-11-18 15:08:04.534811319 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_cs.c 2011-11-18 15:20:09.457520945 -0500 -+@@ -21,6 +21,7 @@ -+ -+ */ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_sdio.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_sdio.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_sdio.c.pr_fmt 2011-11-18 15:08:04.535829198 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_sdio.c 2011-11-18 15:20:09.457520945 -0500 -+@@ -26,6 +26,7 @@ -+ * if_sdio_card_to_host() to pad the data. -+ */ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_spi.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_spi.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_spi.c.pr_fmt 2011-11-18 15:08:04.536811878 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_spi.c 2011-11-18 15:20:09.457520945 -0500 -+@@ -17,6 +17,7 @@ -+ * (at your option) any later version. -+ */ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_usb.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_usb.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_usb.c.pr_fmt 2011-11-18 15:08:04.536811878 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/if_usb.c 2011-11-18 15:20:09.458521084 -0500 -+@@ -2,6 +2,7 @@ -+ * This file contains functions used in USB interface module. -+ */ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/main.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/main.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/main.c.pr_fmt 2011-11-18 15:08:04.537812436 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/main.c 2011-11-18 15:20:09.458521084 -0500 -+@@ -4,6 +4,7 @@ -+ * thread etc.. -+ */ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/mesh.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/mesh.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/mesh.c.pr_fmt 2011-11-18 15:08:04.537812436 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/mesh.c 2011-11-18 15:20:09.458521084 -0500 -+@@ -1,3 +1,4 @@ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/rx.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/rx.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/rx.c.pr_fmt 2011-11-18 15:08:04.538812017 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas/rx.c 2011-11-18 15:20:09.459520455 -0500 -+@@ -2,6 +2,7 @@ -+ * This file contains the handling of RX in wlan driver. -+ */ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/cmd.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/cmd.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/cmd.c.pr_fmt 2011-11-18 15:08:04.544819700 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/cmd.c 2011-11-18 15:20:09.459520455 -0500 -+@@ -7,6 +7,7 @@ -+ * the Free Software Foundation; either version 2 of the License, or (at -+ * your option) any later version. -+ */ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/if_usb.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/if_usb.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/if_usb.c.pr_fmt 2011-11-18 15:08:04.545747064 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/if_usb.c 2011-11-18 15:20:09.459520455 -0500 -+@@ -9,6 +9,7 @@ -+ */ -+ #define DRV_NAME "lbtf_usb" -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include "libertas_tf.h" -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/main.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/main.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/main.c.pr_fmt 2011-11-18 15:08:04.545747064 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/libertas_tf/main.c 2011-11-18 15:20:09.459520455 -0500 -+@@ -7,6 +7,7 @@ -+ * the Free Software Foundation; either version 2 of the License, or (at -+ * your option) any later version. -+ */ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/base.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/base.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/base.c.pr_fmt 2011-11-18 15:08:04.565011903 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/base.c 2011-11-18 15:20:55.315644844 -0500 -+@@ -27,6 +27,7 @@ -+ * -+ *****************************************************************************/ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/cam.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/cam.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/cam.c.pr_fmt 2011-11-18 15:08:04.565812364 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/cam.c 2011-11-18 15:20:55.322652946 -0500 -+@@ -27,6 +27,7 @@ -+ * -+ *****************************************************************************/ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c.pr_fmt 2011-11-18 15:08:04.565812364 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2011-11-18 15:20:55.334647078 -0500 -+@@ -27,6 +27,7 @@ -+ * -+ *****************************************************************************/ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c.pr_fmt 2011-11-18 15:08:04.567811877 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c 2011-11-18 15:20:55.341625637 -0500 -+@@ -27,6 +27,7 @@ -+ * -+ *****************************************************************************/ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include "../wifi.h" -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c.pr_fmt 2011-11-18 15:08:04.567811877 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c 2011-11-18 15:20:55.342644635 -0500 -+@@ -27,6 +27,7 @@ -+ * -+ ****************************************************************************/ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192de/sw.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192de/sw.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192de/sw.c.pr_fmt 2011-11-18 15:08:04.568814042 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192de/sw.c 2011-11-18 15:20:55.350617325 -0500 -+@@ -27,6 +27,7 @@ -+ * -+ *****************************************************************************/ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/hw.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/hw.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/hw.c.pr_fmt 2011-11-18 15:08:04.569828848 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/hw.c 2011-11-18 15:20:55.358645682 -0500 -+@@ -27,6 +27,7 @@ -+ * -+ *****************************************************************************/ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include "../wifi.h" -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/phy.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/phy.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/phy.c.pr_fmt 2011-11-18 15:08:04.570818023 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/phy.c 2011-11-18 15:20:55.365635904 -0500 -+@@ -27,6 +27,7 @@ -+ * -+ *****************************************************************************/ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include "../wifi.h" -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/rf.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/rf.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/rf.c.pr_fmt 2011-11-18 15:08:04.571812156 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/rf.c 2011-11-18 15:20:55.371549230 -0500 -+@@ -27,6 +27,7 @@ -+ * -+ *****************************************************************************/ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include "../wifi.h" -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/sw.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/sw.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/sw.c.pr_fmt 2011-11-18 15:08:04.571812156 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/rtl8192se/sw.c 2011-11-18 15:20:55.379720621 -0500 -+@@ -27,6 +27,7 @@ -+ * -+ *****************************************************************************/ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/usb.c.pr_fmt compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/usb.c -+--- compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/usb.c.pr_fmt 2011-11-18 15:08:04.572718638 -0500 -++++ compat-wireless-3.2-rc1-1/drivers/net/wireless/rtlwifi/usb.c 2011-11-18 15:20:55.389173129 -0500 -+@@ -25,6 +25,7 @@ -+ * -+ *****************************************************************************/ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/net/wireless/core.c.pr_fmt compat-wireless-3.2-rc1-1/net/wireless/core.c -+--- compat-wireless-3.2-rc1-1/net/wireless/core.c.pr_fmt 2011-11-18 15:08:04.573774302 -0500 -++++ compat-wireless-3.2-rc1-1/net/wireless/core.c 2011-11-18 15:20:55.395647078 -0500 -+@@ -4,6 +4,7 @@ -+ * Copyright 2006-2010 Johannes Berg -+ */ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/net/wireless/lib80211.c.pr_fmt compat-wireless-3.2-rc1-1/net/wireless/lib80211.c -+--- compat-wireless-3.2-rc1-1/net/wireless/lib80211.c.pr_fmt 2011-11-18 15:08:04.573774302 -0500 -++++ compat-wireless-3.2-rc1-1/net/wireless/lib80211.c 2011-11-18 15:20:55.405646450 -0500 -+@@ -13,6 +13,7 @@ -+ * -+ */ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/net/wireless/lib80211_crypt_tkip.c.pr_fmt compat-wireless-3.2-rc1-1/net/wireless/lib80211_crypt_tkip.c -+--- compat-wireless-3.2-rc1-1/net/wireless/lib80211_crypt_tkip.c.pr_fmt 2011-11-18 15:08:04.574811667 -0500 -++++ compat-wireless-3.2-rc1-1/net/wireless/lib80211_crypt_tkip.c 2011-11-18 15:20:55.406648475 -0500 -+@@ -10,6 +10,7 @@ -+ * more details. -+ */ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include -+diff -up compat-wireless-3.2-rc1-1/net/wireless/reg.c.pr_fmt compat-wireless-3.2-rc1-1/net/wireless/reg.c -+--- compat-wireless-3.2-rc1-1/net/wireless/reg.c.pr_fmt 2011-11-18 15:08:04.575716473 -0500 -++++ compat-wireless-3.2-rc1-1/net/wireless/reg.c 2011-11-18 15:20:55.408647986 -0500 -+@@ -33,6 +33,7 @@ -+ * -+ */ -+ -++#undef pr_fmt -+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+ #include diff --git a/compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch b/compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch deleted file mode 100644 index 7a3792c25..000000000 --- a/compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch +++ /dev/null @@ -1,131 +0,0 @@ ---- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c -+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c -@@ -265,7 +265,6 @@ int rtl92c_download_fw(struct ieee80211_ - if (!rtlhal->pfirmware) - return 1; - -- pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); - pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; - pfwdata = (u8 *) rtlhal->pfirmware; - fwsize = rtlhal->fwsize; ---- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c -+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c -@@ -186,6 +186,7 @@ int rtl92c_init_sw_vars(struct ieee80211 - memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); - rtlpriv->rtlhal.fwsize = firmware->size; - release_firmware(firmware); -+ pr_info("rtl8192ce: Loaded firmware file %s\n", rtlpriv->cfg->fw_name); - - return 0; - } ---- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c -+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c -@@ -43,6 +43,8 @@ - #include "hw.h" - #include - #include -+#include -+#include - - MODULE_AUTHOR("Georgia "); - MODULE_AUTHOR("Ziv Huang "); -@@ -51,6 +53,10 @@ MODULE_LICENSE("GPL"); - MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless"); - MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); - -+static char *rtl8192cu_firmware; /* pointer to firmware */ -+static int firmware_size; -+static atomic_t usage_count; -+ - static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -@@ -62,12 +68,21 @@ static int rtl92cu_init_sw_vars(struct i - rtlpriv->dm.disable_framebursting = false; - rtlpriv->dm.thermalvalue = 0; - rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; -- rtlpriv->rtlhal.pfirmware = vmalloc(0x4000); -- if (!rtlpriv->rtlhal.pfirmware) { -+ -+ if (rtl8192cu_firmware) { -+ /* firmware already loaded - true for suspend/resume -+ * and multiple instances of the device */ -+ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware; -+ rtlpriv->rtlhal.fwsize = firmware_size; -+ return 0; -+ } -+ rtl8192cu_firmware = vzalloc(0x4000); -+ if (!rtl8192cu_firmware) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Can't alloc buffer for fw.\n")); - return 1; - } -+ - /* request fw */ - err = request_firmware(&firmware, rtlpriv->cfg->fw_name, - rtlpriv->io.dev); -@@ -82,9 +97,14 @@ static int rtl92cu_init_sw_vars(struct i - release_firmware(firmware); - return 1; - } -- memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); -+ pr_info("rtl8192cu: Loaded firmware from file %s\n", -+ rtlpriv->cfg->fw_name); -+ memcpy(rtl8192cu_firmware, firmware->data, firmware->size); -+ firmware_size = firmware->size; - rtlpriv->rtlhal.fwsize = firmware->size; -+ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware; - release_firmware(firmware); -+ atomic_inc(&usage_count); - - return 0; - } -@@ -93,12 +113,30 @@ static void rtl92cu_deinit_sw_vars(struc - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - -- if (rtlpriv->rtlhal.pfirmware) { -- vfree(rtlpriv->rtlhal.pfirmware); -+ atomic_dec(&usage_count); -+ if (!atomic_read(&usage_count) && rtlpriv->rtlhal.pfirmware) { -+ vfree(rtl8192cu_firmware); -+ rtl8192cu_firmware = NULL; - rtlpriv->rtlhal.pfirmware = NULL; - } - } - -+#ifdef CONFIG_PM_SLEEP -+static int rtl8192cu_usb_suspend(struct usb_interface *pusb_intf, -+ pm_message_t message) -+{ -+ /* Increase usage_count to Save loaded fw across suspend/resume */ -+ atomic_inc(&usage_count); -+ return 0; -+} -+ -+static int rtl8192cu_usb_resume(struct usb_interface *pusb_intf) -+{ -+ atomic_dec(&usage_count); /* after resume, decrease usage count */ -+ return 0; -+} -+#endif -+ - static struct rtl_hal_ops rtl8192cu_hal_ops = { - .init_sw_vars = rtl92cu_init_sw_vars, - .deinit_sw_vars = rtl92cu_deinit_sw_vars, -@@ -374,11 +412,10 @@ static struct usb_driver rtl8192cu_drive - .disconnect = rtl_usb_disconnect, - .id_table = rtl8192c_usb_ids, - --#ifdef CONFIG_PM -- /* .suspend = rtl_usb_suspend, */ -- /* .resume = rtl_usb_resume, */ -- /* .reset_resume = rtl8192c_resume, */ --#endif /* CONFIG_PM */ -+#ifdef CONFIG_PM_SLEEP -+ .suspend = rtl8192cu_usb_suspend, -+ .resume = rtl8192cu_usb_resume, -+#endif /* CONFIG_PM_SLEEP */ - #ifdef CONFIG_AUTOSUSPEND - .supports_autosuspend = 1, - #endif diff --git a/config-backports b/config-backports deleted file mode 100644 index c9ccf2033..000000000 --- a/config-backports +++ /dev/null @@ -1,29 +0,0 @@ -# CONFIG_CFG80211 is not set -# CONFIG_LIB80211 is not set - -# CONFIG_MAC80211 is not set - -# CONFIG_BCMA is not set - -# -# ssb and b44 share infrastructure with b43 -# -# CONFIG_SSB is not set -# CONFIG_B44 is not set - -# -# Prevent b43 and brcmsmac from competing -# -# CONFIG_B43_BCMA is not set - -# -# Several wireless drivers have this chip, use the backported driver version -# -# CONFIG_EEPROM_93CX6 is not set - -# -# These have to be turned-on again since compat-wireless does not -# provide them... -# -CONFIG_CRC7=m -CONFIG_AVERAGE=y diff --git a/iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch b/iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch deleted file mode 100644 index 5be686b84..000000000 --- a/iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 3d29dd9b5b160ba4542a9b8f869a220559e633a0 Mon Sep 17 00:00:00 2001 -From: Emmanuel Grumbach -Date: Wed, 1 Feb 2012 07:01:32 -0800 -Subject: [PATCH] iwlwifi: don't mess up QoS counters with non-QoS frames - -In my AMPDU rework, I rely on the sequence numbers of frames. But -I didn't check that the frame has a valid tid before updating the -tracking counters. As a result, the Tx queues were stalled. People -who hit this bug saw that we simply didn't let any data out. - -This bug was introduced in 3.3. - -This patch fixes that and checks that the frame is a QoS frame before -looking at its tid and changing the counters. - -Signed-off-by: Emmanuel Grumbach -Signed-off-by: Wey-Yi Guy -Signed-off-by: John W. Linville ---- - drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 12 +++++++++--- - drivers/net/wireless/iwlwifi/iwl-commands.h | 1 + - drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 1 + - 3 files changed, 11 insertions(+), 3 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c -index 339e8d9..63bbc60 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c -@@ -91,6 +91,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, - tx_cmd->tid_tspec = qc[0] & 0xf; - tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; - } else { -+ tx_cmd->tid_tspec = IWL_TID_NON_QOS; - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) - tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; - else -@@ -808,6 +809,8 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, - u32 status = le16_to_cpu(tx_resp->status.status); - int i; - -+ WARN_ON(tid == IWL_TID_NON_QOS); -+ - if (agg->wait_for_ba) - IWL_DEBUG_TX_REPLY(priv, - "got tx response w/o block-ack\n"); -@@ -1035,10 +1038,13 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, - } - - __skb_queue_head_init(&skbs); -- priv->tid_data[sta_id][tid].next_reclaimed = next_reclaimed; - -- IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d", -- next_reclaimed); -+ if (tid != IWL_TID_NON_QOS) { -+ priv->tid_data[sta_id][tid].next_reclaimed = -+ next_reclaimed; -+ IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d", -+ next_reclaimed); -+ } - - /*we can free until ssn % q.n_bd not inclusive */ - WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id, -diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h -index 265de39..f822ac4 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-commands.h -+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h -@@ -815,6 +815,7 @@ struct iwl_qosparam_cmd { - - #define IWL_INVALID_STATION 255 - #define IWL_MAX_TID_COUNT 8 -+#define IWL_TID_NON_QOS IWL_MAX_TID_COUNT - - #define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) - #define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8) -diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c -index 67d6e32..324d06d 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c -+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c -@@ -1262,6 +1262,7 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, - txq->time_stamp = jiffies; - - if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE && -+ tid != IWL_TID_NON_QOS && - txq_id != trans_pcie->agg_txq[sta_id][tid])) { - /* - * FIXME: this is a uCode bug which need to be addressed, --- -1.7.4.4 - diff --git a/iwlwifi-fix-PCI-E-transport-inta-race.patch b/iwlwifi-fix-PCI-E-transport-inta-race.patch deleted file mode 100644 index b17e5ec7b..000000000 --- a/iwlwifi-fix-PCI-E-transport-inta-race.patch +++ /dev/null @@ -1,51 +0,0 @@ -From b49ba04a3a0382e7314d990707c21094c410425a Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Thu, 19 Jan 2012 08:20:57 -0800 -Subject: [PATCH 8/8] iwlwifi: fix PCI-E transport "inta" race - -When an interrupt comes in, we read the reason -bits and collect them into "trans_pcie->inta". -This happens with the spinlock held. However, -there's a bug resetting this variable -- that -happens after the spinlock has been released. -This means that it is possible for interrupts -to be missed if the reset happens after some -other interrupt reasons were already added to -the variable. - -I found this by code inspection, looking for a -reason that we sometimes see random commands -time out. It seems possible that this causes -such behaviour, but I can't say for sure right -now since it happens extremely infrequently on -my test systems. - -Cc: stable@vger.kernel.org [3.2] -Signed-off-by: Johannes Berg -Signed-off-by: Wey-Yi Guy -Signed-off-by: John W. Linville ---- - drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c -index 752493f..65d1f05 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c -+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c -@@ -972,11 +972,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans) - } - #endif - -- spin_unlock_irqrestore(&trans->shrd->lock, flags); -- - /* saved interrupt in inta variable now we can reset trans_pcie->inta */ - trans_pcie->inta = 0; - -+ spin_unlock_irqrestore(&trans->shrd->lock, flags); -+ - /* Now service all interrupt bits discovered above. */ - if (inta & CSR_INT_BIT_HW_ERR) { - IWL_ERR(trans, "Hardware error detected. Restarting.\n"); --- -1.7.4.4 - diff --git a/iwlwifi-fix-key-removal.patch b/iwlwifi-fix-key-removal.patch deleted file mode 100644 index 9a90160aa..000000000 --- a/iwlwifi-fix-key-removal.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 5dcbf480473f6c3f06ad2426b7517038a2a18911 Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Fri, 17 Feb 2012 09:47:14 -0800 -Subject: [PATCH] iwlwifi: fix key removal - -When trying to remove a key, we always send key -flags just setting the key type, not including -the multicast flag and the key ID. As a result, -whenever any key was removed, the unicast key 0 -would be removed, causing a complete connection -loss after the second rekey (the first doesn't -cause a key removal). Fix the key removal code -to include the key ID and multicast flag, thus -removing the correct key. - -Cc: stable@vger.kernel.org -Reported-by: Alexander Schnaidt -Tested-by: Alexander Schnaidt -Signed-off-by: Johannes Berg -Signed-off-by: Wey-Yi Guy -Signed-off-by: John W. Linville ---- - drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 10 +++++++++- - 1 files changed, 9 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c -index 7353826..e483cfa 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c -@@ -1187,6 +1187,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, - unsigned long flags; - struct iwl_addsta_cmd sta_cmd; - u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta); -+ __le16 key_flags; - - /* if station isn't there, neither is the key */ - if (sta_id == IWL_INVALID_STATION) -@@ -1212,7 +1213,14 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, - IWL_ERR(priv, "offset %d not used in uCode key table.\n", - keyconf->hw_key_idx); - -- sta_cmd.key.key_flags = STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID; -+ key_flags = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); -+ key_flags |= STA_KEY_FLG_MAP_KEY_MSK | STA_KEY_FLG_NO_ENC | -+ STA_KEY_FLG_INVALID; -+ -+ if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) -+ key_flags |= STA_KEY_MULTICAST_MSK; -+ -+ sta_cmd.key.key_flags = key_flags; - sta_cmd.key.key_offset = WEP_INVALID_OFFSET; - sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK; - sta_cmd.mode = STA_CONTROL_MODIFY_MSK; --- -1.7.4.4 - diff --git a/iwlwifi-make-Tx-aggregation-enabled-on-ra-be-at-DEBU.patch b/iwlwifi-make-Tx-aggregation-enabled-on-ra-be-at-DEBU.patch deleted file mode 100644 index 0537e8133..000000000 --- a/iwlwifi-make-Tx-aggregation-enabled-on-ra-be-at-DEBU.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 5fb8c182d26472ea24cbbadb6a3e355d7621cca4 Mon Sep 17 00:00:00 2001 -From: John W. Linville -Date: Tue, 31 Jan 2012 14:40:49 -0500 -Subject: [PATCH] iwlwifi: make "Tx aggregation enabled on ra =" be at DEBUG - level - -Average users either don't care or they think that message indicates a -problem... - -Signed-off-by: John W. Linville ---- - drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c -index c664c27..339e8d9 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c -@@ -620,7 +620,7 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, - sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit = - sta_priv->max_agg_bufsize; - -- IWL_INFO(priv, "Tx aggregation enabled on ra = %pM tid = %d\n", -+ IWL_DEBUG_HT(priv, "Tx aggregation enabled on ra = %pM tid = %d\n", - sta->addr, tid); - - return iwl_send_lq_cmd(priv, ctx, --- -1.7.4.4 - diff --git a/kernel.spec b/kernel.spec index 95f32d00d..e4b43f71f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -163,9 +163,6 @@ Summary: The Linux kernel # should we do C=1 builds with sparse %define with_sparse %{?_with_sparse: 1} %{?!_with_sparse: 0} -# Include driver backports (e.g. compat-wireless) in the kernel build. -%define with_backports %{?_without_backports: 0} %{?!_without_backports: 1} - # Set debugbuildsenabled to 1 for production (build separate debug kernels) # and 0 for rawhide (all kernels are debug kernels). # See also 'make debug' and 'make release'. @@ -204,20 +201,6 @@ Summary: The Linux kernel # The kernel tarball/base version %define kversion 3.%{base_sublevel} -# The compat-wireless version -%define cwversion 3.3-rc1-2 - -####################################################################### -# If cwversion is less than kversion, make sure with_backports is -# turned-off. -# -# For rawhide, disable with_backports immediately after a rebase... -# -# (Uncomment the '#' and both spaces below to disable with_backports.) -# -# % define with_backports 0 -####################################################################### - %define make_target bzImage %define KVERREL %{version}-%{release}.%{_target_cpu} @@ -384,7 +367,6 @@ Summary: The Linux kernel %define make_target image %define kernel_image arch/s390/boot/image %define with_tools 0 -%define with_backports 0 %endif %ifarch sparc64 @@ -464,7 +446,6 @@ Summary: The Linux kernel %define with_pae 0 %define with_debuginfo 0 %define with_tools 0 -%define with_backports 0 %define _enable_debug_packages 0 %endif @@ -583,7 +564,6 @@ BuildRequires: rpm-build >= 4.4.2.1-4 %endif Source0: ftp://ftp.kernel.org/pub/linux/kernel/v3.0/linux-%{kversion}.tar.xz -Source1: compat-wireless-%{cwversion}.tar.bz2 Source11: genkey Source14: find-provides @@ -617,8 +597,6 @@ Source112: config-arm-kirkwood Source113: config-arm-imx Source114: config-arm-highbank -Source200: config-backports - # This file is intentionally left empty in the stock kernel. Its a nicety # added for those wanting to do custom rebuilds with altered config opts. Source1000: config-local @@ -701,7 +679,6 @@ Patch471: floppy-drop-disable_hlt-warning.patch Patch510: linux-2.6-silence-noise.patch Patch520: quite-apm.patch Patch530: linux-2.6-silence-fbcon-logo.patch -Patch540: modpost-add-option-to-allow-external-modules-to-avoi.patch Patch700: linux-2.6-e1000-ich9-montevina.patch @@ -824,49 +801,6 @@ Patch21350: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch Patch22000: weird-root-dentry-name-debug.patch -# compat-wireless patches -Patch50000: compat-wireless-config-fixups.patch -Patch50001: compat-wireless-pr_fmt-warning-avoidance.patch -Patch50002: compat-wireless-integrated-build.patch -Patch50100: compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch - -# Pending upstream fixes -Patch50101: mac80211-fix-debugfs-key-station-symlink.patch -Patch50102: brcmsmac-fix-tx-queue-flush-infinite-loop.patch -Patch50103: mac80211-Use-the-right-headroom-size-for-mesh-mgmt-f.patch -Patch50105: b43-add-option-to-avoid-duplicating-device-support-w.patch -Patch50106: mac80211-update-oper_channel-on-ibss-join.patch -Patch50107: mac80211-set-bss_conf.idle-when-vif-is-connected.patch -Patch50108: iwlwifi-fix-PCI-E-transport-inta-race.patch -Patch50109: bcma-Fix-mem-leak-in-bcma_bus_scan.patch -Patch50110: rt2800lib-fix-wrong-128dBm-when-signal-is-stronger-t.patch -Patch50111: iwlwifi-make-Tx-aggregation-enabled-on-ra-be-at-DEBU.patch -Patch50112: ssb-fix-cardbus-slot-in-hostmode.patch -Patch50113: iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch -Patch50114: mac80211-timeout-a-single-frame-in-the-rx-reorder-bu.patch -Patch50115: ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch -Patch50116: mwifiex-handle-association-failure-case-correctly.patch -Patch50117: ath9k-Fix-kernel-panic-during-driver-initilization.patch -Patch50118: mwifiex-add-NULL-checks-in-driver-unload-path.patch -Patch50119: ath9k-fix-a-WEP-crypto-related-regression.patch -Patch50120: ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch -Patch50121: bcma-don-t-fail-for-bad-SPROM-CRC.patch -Patch50122: zd1211rw-firmware-needs-duration_id-set-to-zero-for-.patch -Patch50123: mac80211-Fix-a-rwlock-bad-magic-bug.patch -Patch50124: rtlwifi-Modify-rtl_pci_init-to-return-0-on-success.patch -Patch50125: mac80211-call-rate-control-only-after-init.patch -Patch50126: mac80211-do-not-call-rate-control-.tx_status-before-.patch -Patch50127: mwifiex-clear-previous-security-setting-during-assoc.patch -Patch50128: ath9k-stop-on-rates-with-idx-1-in-ath9k-rate-control.patch -Patch50129: ath9k_hw-prevent-writes-to-const-data-on-AR9160.patch -Patch50130: rt2x00-fix-a-possible-NULL-pointer-dereference.patch -Patch50131: iwlwifi-fix-key-removal.patch -Patch50132: mac80211-zero-initialize-count-field-in-ieee80211_tx.patch -Patch50133: mac80211-Fix-a-warning-on-changing-to-monitor-mode-f.patch -Patch50134: brcm80211-smac-fix-endless-retry-of-A-MPDU-transmiss.patch -Patch50135: brcm80211-smac-only-print-block-ack-timeout-message-.patch - - %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1327,16 +1261,6 @@ cp %{SOURCE15} . # Dynamically generate kernel .config files from config-* files make -f %{SOURCE20} VERSION=%{version} configs -%if %{with_backports} -# Turn-off bits provided by compat-wireless -for i in %{all_arch_configs} -do - mv $i $i.tmp - ./merge.pl %{SOURCE200} $i.tmp > $i - rm $i.tmp -done -%endif - %if %{?all_arch_configs:1}%{!?all_arch_configs:0} #if a rhel kernel, apply the rhel config options %if 0%{?rhel} @@ -1454,11 +1378,6 @@ ApplyPatch linux-2.6-silence-noise.patch # Make fbcon not show the penguins with 'quiet' ApplyPatch linux-2.6-silence-fbcon-logo.patch -%if %{with_backports} -# modpost: add option to allow external modules to avoid taint -ApplyPatch modpost-add-option-to-allow-external-modules-to-avoi.patch -%endif - # Changes to upstream defaults. @@ -1617,72 +1536,14 @@ done # end of kernel config %endif +# get rid of unwanted files resulting from patch fuzz +find . \( -name "*.orig" -o -name "*~" \) -exec rm -f {} \; >/dev/null + # remove unnecessary SCM files find . -name .gitignore -exec rm -f {} \; >/dev/null cd .. -%if %{with_backports} - -# Always start fresh -rm -rf compat-wireless-%{cwversion} - -# Extract the compat-wireless bits -%setup -q -n kernel-%{kversion}%{?dist} -T -D -a 1 - -cd compat-wireless-%{cwversion} - -ApplyPatch compat-wireless-config-fixups.patch -ApplyPatch compat-wireless-pr_fmt-warning-avoidance.patch -ApplyPatch compat-wireless-integrated-build.patch - -ApplyPatch compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch - -# Pending upstream fixes -ApplyPatch mac80211-fix-debugfs-key-station-symlink.patch -ApplyPatch brcmsmac-fix-tx-queue-flush-infinite-loop.patch -ApplyPatch mac80211-Use-the-right-headroom-size-for-mesh-mgmt-f.patch -ApplyPatch b43-add-option-to-avoid-duplicating-device-support-w.patch -ApplyPatch mac80211-update-oper_channel-on-ibss-join.patch -ApplyPatch mac80211-set-bss_conf.idle-when-vif-is-connected.patch -ApplyPatch iwlwifi-fix-PCI-E-transport-inta-race.patch -ApplyPatch bcma-Fix-mem-leak-in-bcma_bus_scan.patch -ApplyPatch rt2800lib-fix-wrong-128dBm-when-signal-is-stronger-t.patch -ApplyPatch iwlwifi-make-Tx-aggregation-enabled-on-ra-be-at-DEBU.patch -ApplyPatch ssb-fix-cardbus-slot-in-hostmode.patch -ApplyPatch iwlwifi-don-t-mess-up-QoS-counters-with-non-QoS-fram.patch -ApplyPatch mac80211-timeout-a-single-frame-in-the-rx-reorder-bu.patch -ApplyPatch ath9k-use-WARN_ON_ONCE-in-ath_rc_get_highest_rix.patch -ApplyPatch mwifiex-handle-association-failure-case-correctly.patch -ApplyPatch ath9k-Fix-kernel-panic-during-driver-initilization.patch -ApplyPatch mwifiex-add-NULL-checks-in-driver-unload-path.patch -ApplyPatch ath9k-fix-a-WEP-crypto-related-regression.patch -ApplyPatch ath9k_hw-fix-a-RTS-CTS-timeout-regression.patch -ApplyPatch bcma-don-t-fail-for-bad-SPROM-CRC.patch -ApplyPatch zd1211rw-firmware-needs-duration_id-set-to-zero-for-.patch -ApplyPatch mac80211-Fix-a-rwlock-bad-magic-bug.patch -ApplyPatch rtlwifi-Modify-rtl_pci_init-to-return-0-on-success.patch -ApplyPatch mac80211-call-rate-control-only-after-init.patch -ApplyPatch mac80211-do-not-call-rate-control-.tx_status-before-.patch -ApplyPatch mwifiex-clear-previous-security-setting-during-assoc.patch -ApplyPatch ath9k-stop-on-rates-with-idx-1-in-ath9k-rate-control.patch -ApplyPatch ath9k_hw-prevent-writes-to-const-data-on-AR9160.patch -ApplyPatch rt2x00-fix-a-possible-NULL-pointer-dereference.patch -ApplyPatch iwlwifi-fix-key-removal.patch -ApplyPatch mac80211-zero-initialize-count-field-in-ieee80211_tx.patch -ApplyPatch mac80211-Fix-a-warning-on-changing-to-monitor-mode-f.patch -ApplyPatch brcm80211-smac-fix-endless-retry-of-A-MPDU-transmiss.patch -ApplyPatch brcm80211-smac-only-print-block-ack-timeout-message-.patch - -ApplyPatch rt2x00_fix_MCU_request_failures.patch - -cd .. - -%endif - -# get rid of unwanted files resulting from patch fuzz -find . \( -name "*.orig" -o -name "*~" \) -exec rm -f {} \; >/dev/null - ### ### build ### @@ -1805,9 +1666,7 @@ BuildKernel() { # dirs for additional modules per module-init-tools, kbuild/modules.txt mkdir -p $RPM_BUILD_ROOT/lib/modules/$KernelVer/extra mkdir -p $RPM_BUILD_ROOT/lib/modules/$KernelVer/updates -%if %{with_backports} - mkdir -p $RPM_BUILD_ROOT/lib/modules/$KernelVer/backports -%endif + # first copy everything cp --parents `find -type f -name "Makefile*" -o -name "Kconfig*"` $RPM_BUILD_ROOT/lib/modules/$KernelVer/build cp Module.symvers $RPM_BUILD_ROOT/lib/modules/$KernelVer/build @@ -1900,6 +1759,12 @@ BuildKernel() { rm -f modinfo modnames + # remove files that will be auto generated by depmod at rpm -i time + for i in alias alias.bin builtin.bin ccwmap dep dep.bin ieee1394map inputmap isapnpmap ofmap pcimap seriomap symbols symbols.bin usbmap + do + rm -f $RPM_BUILD_ROOT/lib/modules/$KernelVer/modules.$i + done + # Move the devel headers out of the root file system mkdir -p $RPM_BUILD_ROOT/usr/src/kernels mv $RPM_BUILD_ROOT/lib/modules/$KernelVer/build $RPM_BUILD_ROOT/$DevelDir @@ -1913,32 +1778,6 @@ BuildKernel() { # prune junk from kernel-devel find $RPM_BUILD_ROOT/usr/src/kernels -name ".*.cmd" -exec rm -f {} \; -%if %{with_backports} - - cd ../compat-wireless-%{cwversion}/ - - install -m 644 config.mk \ - $RPM_BUILD_ROOT/boot/config.mk-compat-wireless-%{cwversion}-$KernelVer - - make -s ARCH=$Arch V=1 %{?_smp_mflags} \ - KLIB_BUILD=../linux-%{kversion}.%{_target_cpu} \ - KMODPATH_ARG="INSTALL_MOD_PATH=$RPM_BUILD_ROOT" \ - KMODDIR="backports" install-modules %{?sparse_mflags} - - # mark modules executable so that strip-to-file can strip them - find $RPM_BUILD_ROOT/lib/modules/$KernelVer/backports -name "*.ko" \ - -type f | xargs --no-run-if-empty chmod u+x - - cd - - -%endif - - # remove files that will be auto generated by depmod at rpm -i time - for i in alias alias.bin builtin.bin ccwmap dep dep.bin ieee1394map inputmap isapnpmap ofmap pcimap seriomap symbols symbols.bin usbmap - do - rm -f $RPM_BUILD_ROOT/lib/modules/$KernelVer/modules.$i - done - } ### @@ -2337,10 +2176,6 @@ fi /lib/modules/%{KVERREL}%{?2:.%{2}}/source\ /lib/modules/%{KVERREL}%{?2:.%{2}}/extra\ /lib/modules/%{KVERREL}%{?2:.%{2}}/updates\ -%if %{with_backports}\ -/boot/config.mk-compat-wireless-%{cwversion}-%{KVERREL}%{?2:.%{2}}\ -/lib/modules/%{KVERREL}%{?2:.%{2}}/backports\ -%endif\ %ifarch %{vdso_arches}\ /lib/modules/%{KVERREL}%{?2:.%{2}}/vdso\ /etc/ld.so.conf.d/kernel-%{KVERREL}%{?2:.%{2}}.conf\ @@ -2386,6 +2221,9 @@ fi # and build. %changelog +* Mon Mar 19 2012 Josh Boyer +- Drop compat-wireless infrastructure in preparation for 3.3 rebase + * Fri Mar 16 2012 Justin M. Forbes - re-enable threading on hibernate compression/decompression diff --git a/mac80211-Fix-a-rwlock-bad-magic-bug.patch b/mac80211-Fix-a-rwlock-bad-magic-bug.patch deleted file mode 100644 index 822b0dd54..000000000 --- a/mac80211-Fix-a-rwlock-bad-magic-bug.patch +++ /dev/null @@ -1,89 +0,0 @@ -From b57e6b560fc2a2742910ac5ca0eb2c46e45aeac2 Mon Sep 17 00:00:00 2001 -From: Mohammed Shafi Shajakhan -Date: Thu, 9 Feb 2012 19:59:43 +0530 -Subject: [PATCH] mac80211: Fix a rwlock bad magic bug - -read_lock(&tpt_trig->trig.leddev_list_lock) is accessed via the path -ieee80211_open (->) ieee80211_do_open (->) ieee80211_mod_tpt_led_trig -(->) ieee80211_start_tpt_led_trig (->) tpt_trig_timer before initializing -it. -the intilization of this read/write lock happens via the path -ieee80211_led_init (->) led_trigger_register, but we are doing -'ieee80211_led_init' after 'ieeee80211_if_add' where we -register netdev_ops. -so we access leddev_list_lock before initializing it and causes the -following bug in chrome laptops with AR928X cards with the following -script - -while true -do -sudo modprobe -v ath9k -sleep 3 -sudo modprobe -r ath9k -sleep 3 -done - - BUG: rwlock bad magic on CPU#1, wpa_supplicant/358, f5b9eccc - Pid: 358, comm: wpa_supplicant Not tainted 3.0.13 #1 - Call Trace: - - [<8137b9df>] rwlock_bug+0x3d/0x47 - [<81179830>] do_raw_read_lock+0x19/0x29 - [<8137f063>] _raw_read_lock+0xd/0xf - [] tpt_trig_timer+0xc3/0x145 [mac80211] - [] ieee80211_mod_tpt_led_trig+0x152/0x174 [mac80211] - [] ieee80211_do_open+0x11e/0x42e [mac80211] - [] ? ieee80211_check_concurrent_iface+0x26/0x13c [mac80211] - [] ieee80211_open+0x48/0x4c [mac80211] - [<812dbed8>] __dev_open+0x82/0xab - [<812dc0c9>] __dev_change_flags+0x9c/0x113 - [<812dc1ae>] dev_change_flags+0x18/0x44 - [<8132144f>] devinet_ioctl+0x243/0x51a - [<81321ba9>] inet_ioctl+0x93/0xac - [<812cc951>] sock_ioctl+0x1c6/0x1ea - [<812cc78b>] ? might_fault+0x20/0x20 - [<810b1ebb>] do_vfs_ioctl+0x46e/0x4a2 - [<810a6ebb>] ? fget_light+0x2f/0x70 - [<812ce549>] ? sys_recvmsg+0x3e/0x48 - [<810b1f35>] sys_ioctl+0x46/0x69 - [<8137fa77>] sysenter_do_call+0x12/0x2 - -Cc: -Cc: Gary Morain -Cc: Paul Stewart -Cc: Abhijit Pradhan -Cc: Vasanthakumar Thiagarajan -Cc: Rajkumar Manoharan -Acked-by: Johannes Berg -Tested-by: Mohammed Shafi Shajakhan -Signed-off-by: Mohammed Shafi Shajakhan -Signed-off-by: John W. Linville ---- - net/mac80211/main.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/net/mac80211/main.c b/net/mac80211/main.c -index 0a0d94a..b142bd4 100644 ---- a/net/mac80211/main.c -+++ b/net/mac80211/main.c -@@ -910,6 +910,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) - wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n", - result); - -+ ieee80211_led_init(local); -+ - rtnl_lock(); - - result = ieee80211_init_rate_ctrl_alg(local, -@@ -931,8 +933,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) - - rtnl_unlock(); - -- ieee80211_led_init(local); -- - local->network_latency_notifier.notifier_call = - ieee80211_max_network_latency; - result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, --- -1.7.4.4 - diff --git a/mac80211-Fix-a-warning-on-changing-to-monitor-mode-f.patch b/mac80211-Fix-a-warning-on-changing-to-monitor-mode-f.patch deleted file mode 100644 index 421bd9323..000000000 --- a/mac80211-Fix-a-warning-on-changing-to-monitor-mode-f.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0dee00686da88cc32753e02e4e8efdd9e326e4d2 Mon Sep 17 00:00:00 2001 -From: Mohammed Shafi Shajakhan -Date: Mon, 20 Feb 2012 14:44:01 +0530 -Subject: [PATCH] mac80211: Fix a warning on changing to monitor mode from STA - -nothing needs to be done for monitor/AP_VLAN mode on calling -ieee80211_bss_info_change_notify -> drv_bss_info_changed with the change -flag 'BSS_CHANGED_IDLE'. 'wl1271' seems to use BSS_CHANGED_IDLE only for -STA and IBSS mode. further the non-idle state of the monitor mode is -taken care by the 'count' variable which counts non-idle interfaces. -ieee80211_idle_off(local, "in use") will be called. -this fixes the following WARNING when we have initially STA mode -(network manager running) and not associated, and change it to monitor -mode with network manager disabled and bringing up the monitor mode. -this changes the idle state from 'true' (STA unassociated) to 'false' -(MONITOR mode) -exposed by the commit 405385f8ce7a2ed8f82e216d88b5282142e1288b -"mac80211: set bss_conf.idle when vif is connected" - - WARNING: net/mac80211/main.c:212 - ieee80211_bss_info_change_notify+0x1cf/0x330 [mac80211]() - Hardware name: 64756D6 - Pid: 3835, comm: ifconfig Tainted: G O - 3.3.0-rc3-wl #9 - Call Trace: - [] warn_slowpath_common+0x72/0xa0 - [] ? - ieee80211_bss_info_change_notify+0x1cf/0x330 [mac80211] - [] ? - ieee80211_bss_info_change_notify+0x1cf/0x330 [mac80211] - [] warn_slowpath_null+0x22/0x30 - [] - ieee80211_bss_info_change_notify+0x1cf/0x330 [mac80211] - [] __ieee80211_recalc_idle+0x113/0x430 - [mac80211] - [] ieee80211_do_open+0x156/0x7e0 [mac80211] - [] ? - ieee80211_check_concurrent_iface+0x25/0x180 [mac80211] - [] ? raw_notifier_call_chain+0x1f/0x30 - [] ieee80211_open+0x40/0x80 [mac80211] - [] __dev_open+0x96/0xe0 - [] ? _raw_spin_unlock_bh+0x35/0x40 - [] __dev_change_flags+0x109/0x170 - [] dev_change_flags+0x23/0x60 - [] devinet_ioctl+0x6a0/0x770 - - ieee80211 phy0: device no longer idle - in use - -Cc: Eliad Peller -Signed-off-by: Mohammed Shafi Shajakhan -Signed-off-by: John W. Linville ---- - net/mac80211/iface.c | 3 +++ - 1 files changed, 3 insertions(+), 0 deletions(-) - -diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c -index 01a21c2..8e2137b 100644 ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -1332,6 +1332,9 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) - hw_roc = true; - - list_for_each_entry(sdata, &local->interfaces, list) { -+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR || -+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN) -+ continue; - if (sdata->old_idle == sdata->vif.bss_conf.idle) - continue; - if (!ieee80211_sdata_running(sdata)) --- -1.7.4.4 - diff --git a/mac80211-Use-the-right-headroom-size-for-mesh-mgmt-f.patch b/mac80211-Use-the-right-headroom-size-for-mesh-mgmt-f.patch deleted file mode 100644 index 9096effdd..000000000 --- a/mac80211-Use-the-right-headroom-size-for-mesh-mgmt-f.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 65e8b0ccb6cf176f8eddb1b05534be46580da9dd Mon Sep 17 00:00:00 2001 -From: Javier Cardona -Date: Tue, 17 Jan 2012 18:17:46 -0800 -Subject: [PATCH 3/8] mac80211: Use the right headroom size for mesh mgmt - frames - -Use local->tx_headroom instad of local->hw.extra_tx_headroom. -local->tx_headroom is the max of hw.extra_tx_headroom required by the -driver and the headroom required by mac80211 for status reporting. On -drivers where hw.extra_tx_headroom is smaller than what mac80211 -requires (e.g. ath5k), we would not reserve sufficient buffer space to -report tx status. - -Also, don't reserve local->tx_headroom + local->hw.extra_tx_headroom. - -Reported-by: Simon Morgenthaler -Reported-by: Kai Scharwies -Signed-off-by: Javier Cardona -Signed-off-by: John W. Linville ---- - net/mac80211/mesh_hwmp.c | 8 ++++---- - net/mac80211/mesh_plink.c | 4 ++-- - 2 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c -index 73abb75..54df1b2 100644 ---- a/net/mac80211/mesh_hwmp.c -+++ b/net/mac80211/mesh_hwmp.c -@@ -119,12 +119,12 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, - int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) + - sizeof(mgmt->u.action.u.mesh_action); - -- skb = dev_alloc_skb(local->hw.extra_tx_headroom + -+ skb = dev_alloc_skb(local->tx_headroom + - hdr_len + - 2 + 37); /* max HWMP IE */ - if (!skb) - return -1; -- skb_reserve(skb, local->hw.extra_tx_headroom); -+ skb_reserve(skb, local->tx_headroom); - mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); - memset(mgmt, 0, hdr_len); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | -@@ -250,12 +250,12 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, - if (time_before(jiffies, ifmsh->next_perr)) - return -EAGAIN; - -- skb = dev_alloc_skb(local->hw.extra_tx_headroom + -+ skb = dev_alloc_skb(local->tx_headroom + - hdr_len + - 2 + 15 /* PERR IE */); - if (!skb) - return -1; -- skb_reserve(skb, local->tx_headroom + local->hw.extra_tx_headroom); -+ skb_reserve(skb, local->tx_headroom); - mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); - memset(mgmt, 0, hdr_len); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | -diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c -index 41ef1b4..a172517 100644 ---- a/net/mac80211/mesh_plink.c -+++ b/net/mac80211/mesh_plink.c -@@ -172,7 +172,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, - int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) + - sizeof(mgmt->u.action.u.self_prot); - -- skb = dev_alloc_skb(local->hw.extra_tx_headroom + -+ skb = dev_alloc_skb(local->tx_headroom + - hdr_len + - 2 + /* capability info */ - 2 + /* AID */ -@@ -186,7 +186,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, - sdata->u.mesh.ie_len); - if (!skb) - return -1; -- skb_reserve(skb, local->hw.extra_tx_headroom); -+ skb_reserve(skb, local->tx_headroom); - mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); - memset(mgmt, 0, hdr_len); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | --- -1.7.4.4 - diff --git a/mac80211-call-rate-control-only-after-init.patch b/mac80211-call-rate-control-only-after-init.patch deleted file mode 100644 index 16fdda166..000000000 --- a/mac80211-call-rate-control-only-after-init.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 4b5a433ae5348c23caa0b5f0a2fca7c342acb200 Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Fri, 20 Jan 2012 13:55:23 +0100 -Subject: [PATCH] mac80211: call rate control only after init - -There are situations where we don't have the -necessary rate control information yet for -station entries, e.g. when associating. This -currently doesn't really happen due to the -dummy station handling; explicitly disabling -rate control when it's not initialised will -allow us to remove dummy stations. - -Signed-off-by: Johannes Berg -Signed-off-by: John W. Linville ---- - net/mac80211/debugfs_sta.c | 4 ++-- - net/mac80211/rate.c | 2 +- - net/mac80211/rate.h | 1 + - net/mac80211/sta_info.h | 2 ++ - 4 files changed, 6 insertions(+), 3 deletions(-) - -diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c -index 2406b3e..d86217d 100644 ---- a/net/mac80211/debugfs_sta.c -+++ b/net/mac80211/debugfs_sta.c -@@ -63,14 +63,14 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, - test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" - - int res = scnprintf(buf, sizeof(buf), -- "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", -+ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", - TEST(AUTH), TEST(ASSOC), TEST(PS_STA), - TEST(PS_DRIVER), TEST(AUTHORIZED), - TEST(SHORT_PREAMBLE), - TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT), - TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), - TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), -- TEST(TDLS_PEER_AUTH)); -+ TEST(TDLS_PEER_AUTH), TEST(RATE_CONTROL)); - #undef TEST - return simple_read_from_buffer(userbuf, count, ppos, buf, res); - } -diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c -index 5a5a776..ad64f4d 100644 ---- a/net/mac80211/rate.c -+++ b/net/mac80211/rate.c -@@ -336,7 +336,7 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, - int i; - u32 mask; - -- if (sta) { -+ if (sta && test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) { - ista = &sta->sta; - priv_sta = sta->rate_ctrl_priv; - } -diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h -index 168427b..2b83f32 100644 ---- a/net/mac80211/rate.h -+++ b/net/mac80211/rate.h -@@ -62,6 +62,7 @@ static inline void rate_control_rate_init(struct sta_info *sta) - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - ref->ops->rate_init(ref->priv, sband, ista, priv_sta); -+ set_sta_flag(sta, WLAN_STA_RATE_CONTROL); - } - - static inline void rate_control_rate_update(struct ieee80211_local *local, -diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h -index 6f77f12..bfed851 100644 ---- a/net/mac80211/sta_info.h -+++ b/net/mac80211/sta_info.h -@@ -52,6 +52,7 @@ - * @WLAN_STA_SP: Station is in a service period, so don't try to - * reply to other uAPSD trigger frames or PS-Poll. - * @WLAN_STA_4ADDR_EVENT: 4-addr event was already sent for this frame. -+ * @WLAN_STA_RATE_CONTROL: rate control was initialized for this station. - */ - enum ieee80211_sta_info_flags { - WLAN_STA_AUTH, -@@ -71,6 +72,7 @@ enum ieee80211_sta_info_flags { - WLAN_STA_UAPSD, - WLAN_STA_SP, - WLAN_STA_4ADDR_EVENT, -+ WLAN_STA_RATE_CONTROL, - }; - - enum ieee80211_sta_state { --- -1.7.4.4 - diff --git a/mac80211-do-not-call-rate-control-.tx_status-before-.patch b/mac80211-do-not-call-rate-control-.tx_status-before-.patch deleted file mode 100644 index 28343b342..000000000 --- a/mac80211-do-not-call-rate-control-.tx_status-before-.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 216c57b214bd621335ff698b475f6db2802502dc Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -Date: Wed, 8 Feb 2012 19:17:11 +0100 -Subject: [PATCH] mac80211: do not call rate control .tx_status before - .rate_init - -Most rate control implementations assume .get_rate and .tx_status are only -called once the per-station data has been fully initialized. -minstrel_ht crashes if this assumption is violated. - -Signed-off-by: Felix Fietkau -Tested-by: Arend van Spriel -Signed-off-by: John W. Linville ---- - net/mac80211/rate.h | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h -index 2b83f32..80cfc00 100644 ---- a/net/mac80211/rate.h -+++ b/net/mac80211/rate.h -@@ -41,7 +41,7 @@ static inline void rate_control_tx_status(struct ieee80211_local *local, - struct ieee80211_sta *ista = &sta->sta; - void *priv_sta = sta->rate_ctrl_priv; - -- if (!ref) -+ if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) - return; - - ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); --- -1.7.4.4 - diff --git a/mac80211-fix-debugfs-key-station-symlink.patch b/mac80211-fix-debugfs-key-station-symlink.patch deleted file mode 100644 index d98f2c99b..000000000 --- a/mac80211-fix-debugfs-key-station-symlink.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 9446f3efc53512e5ad9e0966539021a2a41fe5a0 Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Tue, 17 Jan 2012 10:32:01 +0100 -Subject: [PATCH 1/8] mac80211: fix debugfs key->station symlink - -Since stations moved into a virtual interface -subdirectory, this link has been broken. Fix it. - -Signed-off-by: Johannes Berg -Signed-off-by: John W. Linville ---- - net/mac80211/debugfs_key.c | 7 ++++--- - 1 files changed, 4 insertions(+), 3 deletions(-) - -diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c -index 38e6101..59edcd9 100644 ---- a/net/mac80211/debugfs_key.c -+++ b/net/mac80211/debugfs_key.c -@@ -225,9 +225,9 @@ KEY_OPS(key); - key, &key_##name##_ops); - - void ieee80211_debugfs_key_add(struct ieee80211_key *key) -- { -+{ - static int keycount; -- char buf[50]; -+ char buf[100]; - struct sta_info *sta; - - if (!key->local->debugfs.keys) -@@ -244,7 +244,8 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key) - - sta = key->sta; - if (sta) { -- sprintf(buf, "../../stations/%pM", sta->sta.addr); -+ sprintf(buf, "../../netdev:%s/stations/%pM", -+ sta->sdata->name, sta->sta.addr); - key->debugfs.stalink = - debugfs_create_symlink("station", key->debugfs.dir, buf); - } --- -1.7.4.4 - diff --git a/mac80211-set-bss_conf.idle-when-vif-is-connected.patch b/mac80211-set-bss_conf.idle-when-vif-is-connected.patch deleted file mode 100644 index 42720d075..000000000 --- a/mac80211-set-bss_conf.idle-when-vif-is-connected.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 405385f8ce7a2ed8f82e216d88b5282142e1288b Mon Sep 17 00:00:00 2001 -From: Eliad Peller -Date: Wed, 11 Jan 2012 13:11:50 +0200 -Subject: [PATCH 7/8] mac80211: set bss_conf.idle when vif is connected - -__ieee80211_recalc_idle() iterates through the vifs, -sets bss_conf.idle = true if they are disconnected, -and increases "count" if they are not (which later -gets evaluated in order to determine whether the -device is idle). - -However, the loop doesn't set bss_conf.idle = false -(along with increasing "count"), causing the device -idle state and the vif idle state to get out of sync -in some cases. - -Signed-off-by: Eliad Peller -Signed-off-by: John W. Linville ---- - net/mac80211/iface.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c -index e47768c..01a21c2 100644 ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -1314,6 +1314,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) - continue; - } - /* count everything else */ -+ sdata->vif.bss_conf.idle = false; - count++; - } - --- -1.7.4.4 - diff --git a/mac80211-timeout-a-single-frame-in-the-rx-reorder-bu.patch b/mac80211-timeout-a-single-frame-in-the-rx-reorder-bu.patch deleted file mode 100644 index 8d836d2bb..000000000 --- a/mac80211-timeout-a-single-frame-in-the-rx-reorder-bu.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 07ae2dfcf4f7143ce191c6436da1c33f179af0d6 Mon Sep 17 00:00:00 2001 -From: Eliad Peller -Date: Wed, 1 Feb 2012 18:48:09 +0200 -Subject: [PATCH] mac80211: timeout a single frame in the rx reorder buffer - -The current code checks for stored_mpdu_num > 1, causing -the reorder_timer to be triggered indefinitely, but the -frame is never timed-out (until the next packet is received) - -Signed-off-by: Eliad Peller -Cc: -Acked-by: Johannes Berg -Signed-off-by: John W. Linville ---- - net/mac80211/rx.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c -index 7514091..5a5e504 100644 ---- a/net/mac80211/rx.c -+++ b/net/mac80211/rx.c -@@ -611,7 +611,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, - index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % - tid_agg_rx->buf_size; - if (!tid_agg_rx->reorder_buf[index] && -- tid_agg_rx->stored_mpdu_num > 1) { -+ tid_agg_rx->stored_mpdu_num) { - /* - * No buffers ready to be released, but check whether any - * frames in the reorder buffer have timed out. --- -1.7.4.4 - diff --git a/mac80211-update-oper_channel-on-ibss-join.patch b/mac80211-update-oper_channel-on-ibss-join.patch deleted file mode 100644 index 1a0d93249..000000000 --- a/mac80211-update-oper_channel-on-ibss-join.patch +++ /dev/null @@ -1,31 +0,0 @@ -From ba1960257c5980f9b58057995ce3394bd8e48ca3 Mon Sep 17 00:00:00 2001 -From: Eliad Peller -Date: Tue, 10 Jan 2012 15:19:54 +0200 -Subject: [PATCH 6/8] mac80211: update oper_channel on ibss join - -Commit 13c40c5 ("mac80211: Add HT operation modes for IBSS") broke -ibss operation by mistakenly removing the local->oper_channel -update (causing ibss to start on the wrong channel). fix it. - -Signed-off-by: Eliad Peller -Acked-by: Simon Wunderlich -Signed-off-by: John W. Linville ---- - net/mac80211/ibss.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c -index b3d76b7..a464396 100644 ---- a/net/mac80211/ibss.c -+++ b/net/mac80211/ibss.c -@@ -106,6 +106,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, - - sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; - -+ local->oper_channel = chan; - channel_type = ifibss->channel_type; - if (channel_type > NL80211_CHAN_HT20 && - !cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) --- -1.7.4.4 - diff --git a/mac80211-zero-initialize-count-field-in-ieee80211_tx.patch b/mac80211-zero-initialize-count-field-in-ieee80211_tx.patch deleted file mode 100644 index 4b0ec167c..000000000 --- a/mac80211-zero-initialize-count-field-in-ieee80211_tx.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 8617b093d0031837a7be9b32bc674580cfb5f6b5 Mon Sep 17 00:00:00 2001 -From: Mohammed Shafi Shajakhan -Date: Mon, 20 Feb 2012 10:05:31 +0530 -Subject: [PATCH] mac80211: zero initialize count field in ieee80211_tx_rate - -rate control algorithms concludes the rate as invalid -with rate[i].idx < -1 , while they do also check for rate[i].count is -non-zero. it would be safer to zero initialize the 'count' field. -recently we had a ath9k rate control crash where the ath9k rate control -in ath_tx_status assumed to check only for rate[i].count being non-zero -in one instance and ended up in using invalid rate index for -'connection monitoring NULL func frames' which eventually lead to the crash. -thanks to Pavel Roskin for fixing it and finding the root cause. -https://bugzilla.redhat.com/show_bug.cgi?id=768639 - -Cc: stable@vger.kernel.org -Cc: Pavel Roskin -Signed-off-by: Mohammed Shafi Shajakhan -Signed-off-by: John W. Linville ---- - net/mac80211/rate.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c -index ad64f4d..f9b8e81 100644 ---- a/net/mac80211/rate.c -+++ b/net/mac80211/rate.c -@@ -344,7 +344,7 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, - for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { - info->control.rates[i].idx = -1; - info->control.rates[i].flags = 0; -- info->control.rates[i].count = 1; -+ info->control.rates[i].count = 0; - } - - if (sdata->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) --- -1.7.4.4 - diff --git a/modpost-add-option-to-allow-external-modules-to-avoi.patch b/modpost-add-option-to-allow-external-modules-to-avoi.patch deleted file mode 100644 index d20385457..000000000 --- a/modpost-add-option-to-allow-external-modules-to-avoi.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 69f63a67165da5e9f08c1132521598701d914573 Mon Sep 17 00:00:00 2001 -From: John W. Linville -Date: Wed, 14 Dec 2011 11:09:04 -0500 -Subject: [PATCH] modpost: add option to allow external modules to avoid taint - -In some cases, it might be desirable to package a module from an -external source tree alongside the base kernel. In those cases, it -might also be desirable to not have those modules tainting the kernel. - -This patch provides a mechanism for an external module build to declare -itself as an "integrated build". Such a module is then treated the same -as an intree module. - -Signed-off-by: John W. Linville ---- -Any thoughts on this? I'm thinking of adding this to Fedora kernels, -where I have been working to integrate the compat-wireless package as -part of the base kernel RPM. - - scripts/Makefile.modpost | 1 + - scripts/mod/modpost.c | 10 ++++++++-- - 2 files changed, 9 insertions(+), 2 deletions(-) - -diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost -index 08dce14..160c6fb 100644 ---- a/scripts/Makefile.modpost -+++ b/scripts/Makefile.modpost -@@ -81,6 +81,7 @@ modpost = scripts/mod/modpost \ - $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ - $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \ - $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \ -+ $(if $(INTEGRATED_BUILD),-B) \ - $(if $(cross_build),-c) - - quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules -diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c -index 2bd594e..5d077f9 100644 ---- a/scripts/mod/modpost.c -+++ b/scripts/mod/modpost.c -@@ -43,6 +43,9 @@ static int warn_unresolved = 0; - static int sec_mismatch_count = 0; - static int sec_mismatch_verbose = 1; - -+/* Is this a module being built as part of an integrated package? */ -+static int integrated_build = 0; -+ - enum export { - export_plain, export_unused, export_gpl, - export_unused_gpl, export_gpl_future, export_unknown -@@ -1851,7 +1854,7 @@ static void add_header(struct buffer *b, struct module *mod) - - static void add_intree_flag(struct buffer *b, int is_intree) - { -- if (is_intree) -+ if (is_intree || integrated_build) - buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n"); - } - -@@ -2101,7 +2104,7 @@ int main(int argc, char **argv) - struct ext_sym_list *extsym_iter; - struct ext_sym_list *extsym_start = NULL; - -- while ((opt = getopt(argc, argv, "i:I:e:cmsSo:awM:K:")) != -1) { -+ while ((opt = getopt(argc, argv, "i:I:e:cmsSo:awM:K:B")) != -1) { - switch (opt) { - case 'i': - kernel_read = optarg; -@@ -2139,6 +2142,9 @@ int main(int argc, char **argv) - case 'w': - warn_unresolved = 1; - break; -+ case 'B': -+ integrated_build = 1; -+ break; - default: - exit(1); - } --- -1.7.4.4 - diff --git a/mwifiex-add-NULL-checks-in-driver-unload-path.patch b/mwifiex-add-NULL-checks-in-driver-unload-path.patch deleted file mode 100644 index 0b7be1fb7..000000000 --- a/mwifiex-add-NULL-checks-in-driver-unload-path.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 2da8cbf8a6b454296c9db7b57cac72d5a39e3aa7 Mon Sep 17 00:00:00 2001 -From: Amitkumar Karwar -Date: Fri, 3 Feb 2012 20:34:02 -0800 -Subject: [PATCH] mwifiex: add NULL checks in driver unload path - -If driver load is failed, sometimes few pointers may remain -uninitialized ex. priv->wdev, priv->netdev, adapter->sleep_cfm -This will cause NULL pointer dereferance while unloading the -driver. - -Signed-off-by: Amitkumar Karwar -Signed-off-by: Kiran Divekar -Signed-off-by: Bing Zhao -Signed-off-by: John W. Linville ---- - drivers/net/wireless/mwifiex/init.c | 3 ++- - drivers/net/wireless/mwifiex/main.c | 12 ++++++++---- - 2 files changed, 10 insertions(+), 5 deletions(-) - -diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c -index e05b417..1d0ec57 100644 ---- a/drivers/net/wireless/mwifiex/init.c -+++ b/drivers/net/wireless/mwifiex/init.c -@@ -382,7 +382,8 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter) - - adapter->if_ops.cleanup_if(adapter); - -- dev_kfree_skb_any(adapter->sleep_cfm); -+ if (adapter->sleep_cfm) -+ dev_kfree_skb_any(adapter->sleep_cfm); - } - - /* -diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c -index 84be196..b728f54 100644 ---- a/drivers/net/wireless/mwifiex/main.c -+++ b/drivers/net/wireless/mwifiex/main.c -@@ -822,7 +822,9 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) - continue; - - rtnl_lock(); -- mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev); -+ if (priv->wdev && priv->netdev) -+ mwifiex_del_virtual_intf(priv->wdev->wiphy, -+ priv->netdev); - rtnl_unlock(); - } - -@@ -830,9 +832,11 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) - if (!priv) - goto exit_remove; - -- wiphy_unregister(priv->wdev->wiphy); -- wiphy_free(priv->wdev->wiphy); -- kfree(priv->wdev); -+ if (priv->wdev) { -+ wiphy_unregister(priv->wdev->wiphy); -+ wiphy_free(priv->wdev->wiphy); -+ kfree(priv->wdev); -+ } - - mwifiex_terminate_workqueue(adapter); - --- -1.7.4.4 - diff --git a/mwifiex-clear-previous-security-setting-during-assoc.patch b/mwifiex-clear-previous-security-setting-during-assoc.patch deleted file mode 100644 index f3fa7cb2b..000000000 --- a/mwifiex-clear-previous-security-setting-during-assoc.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 6670f15b1f6858a43b292d8ab64464e9f085a6aa Mon Sep 17 00:00:00 2001 -From: Amitkumar Karwar -Date: Thu, 9 Feb 2012 18:32:22 -0800 -Subject: [PATCH] mwifiex: clear previous security setting during association - -Driver maintains different flags for WEP, WPA, WPA2 security modes. -Appropriate flag is set using security information provided in -connect request. mwifiex_is_network_compatible() routine uses them -to check if driver's setting is compatible with AP. Association is -aborted if the routine fails. - -For some corner cases, it is observed that association is failed -even for valid security information based on association history. -This patch fixes the problem by clearing previous security setting -during each association. - -We should set WEP key provided in connect request as default tx key. -This missing change is also added here. - -Signed-off-by: Amitkumar Karwar -Signed-off-by: Bing Zhao -Signed-off-by: John W. Linville ---- - drivers/net/wireless/mwifiex/cfg80211.c | 8 +++++++- - 1 files changed, 7 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c -index c3b6c46..5b2972b 100644 ---- a/drivers/net/wireless/mwifiex/cfg80211.c -+++ b/drivers/net/wireless/mwifiex/cfg80211.c -@@ -841,7 +841,12 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, - ret = mwifiex_set_rf_channel(priv, channel, - priv->adapter->channel_type); - -- ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); /* Disable keys */ -+ /* As this is new association, clear locally stored -+ * keys and security related flags */ -+ priv->sec_info.wpa_enabled = false; -+ priv->sec_info.wpa2_enabled = false; -+ priv->wep_key_curr_index = 0; -+ ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); - - if (mode == NL80211_IFTYPE_ADHOC) { - /* "privacy" is set only for ad-hoc mode */ -@@ -886,6 +891,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, - dev_dbg(priv->adapter->dev, - "info: setting wep encryption" - " with key len %d\n", sme->key_len); -+ priv->wep_key_curr_index = sme->key_idx; - ret = mwifiex_set_encode(priv, sme->key, sme->key_len, - sme->key_idx, 0); - } --- -1.7.4.4 - diff --git a/mwifiex-handle-association-failure-case-correctly.patch b/mwifiex-handle-association-failure-case-correctly.patch deleted file mode 100644 index 48c757083..000000000 --- a/mwifiex-handle-association-failure-case-correctly.patch +++ /dev/null @@ -1,67 +0,0 @@ -From b7097eb75fa11c302dcdec83f1dbfa874e0af0d1 Mon Sep 17 00:00:00 2001 -From: Amitkumar Karwar -Date: Wed, 1 Feb 2012 20:41:43 -0800 -Subject: [PATCH] mwifiex: handle association failure case correctly - -Currently even if association is failed "iw link" shows some -information about connected BSS and "Tx timeout" error is seen in -dmesg log. - -This patch fixes below issues in the code to handle assoc failure -case correctly. -1) "status" variable in mwifiex_wait_queue_complete() is not -correctly updated. Hence driver doesn't inform cfg80211 stack -about association failure. -2) During association network queues are stopped but carrier is -not cleared, which gives Tx timeout error in failure case - -Signed-off-by: Amitkumar Karwar -Signed-off-by: Bing Zhao -Signed-off-by: John W. Linville ---- - drivers/net/wireless/mwifiex/sta_ioctl.c | 8 +++++++- - 1 files changed, 7 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c -index 470ca75..b0fbf5d 100644 ---- a/drivers/net/wireless/mwifiex/sta_ioctl.c -+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c -@@ -54,7 +54,7 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, - int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) - { - bool cancel_flag = false; -- int status = adapter->cmd_wait_q.status; -+ int status; - struct cmd_ctrl_node *cmd_queued; - - if (!adapter->cmd_queued) -@@ -79,6 +79,8 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) - mwifiex_cancel_pending_ioctl(adapter); - dev_dbg(adapter->dev, "cmd cancel\n"); - } -+ -+ status = adapter->cmd_wait_q.status; - adapter->cmd_wait_q.status = 0; - - return status; -@@ -240,6 +242,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, - - if (!netif_queue_stopped(priv->netdev)) - mwifiex_stop_net_dev_queue(priv->netdev, adapter); -+ if (netif_carrier_ok(priv->netdev)) -+ netif_carrier_off(priv->netdev); - - /* Clear any past association response stored for - * application retrieval */ -@@ -271,6 +275,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, - - if (!netif_queue_stopped(priv->netdev)) - mwifiex_stop_net_dev_queue(priv->netdev, adapter); -+ if (netif_carrier_ok(priv->netdev)) -+ netif_carrier_off(priv->netdev); - - if (!ret) { - dev_dbg(adapter->dev, "info: network found in scan" --- -1.7.4.4 - diff --git a/rt2800lib-fix-wrong-128dBm-when-signal-is-stronger-t.patch b/rt2800lib-fix-wrong-128dBm-when-signal-is-stronger-t.patch deleted file mode 100644 index 7fc6c20d0..000000000 --- a/rt2800lib-fix-wrong-128dBm-when-signal-is-stronger-t.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 7fc417556473f15efac269523c17eb92103c6484 Mon Sep 17 00:00:00 2001 -From: Luigi Tarenga -Date: Tue, 31 Jan 2012 18:51:23 +0100 -Subject: [PATCH] rt2800lib: fix wrong -128dBm when signal is stronger than - -12dBm - -This patch correct the type of variables containing the rssi -values read from the rxwi. - -In function rt2800_agc_to_rssi() 3 variables (rssi0, rssi1, rss2) -defined as int was assigned a 16bit signed values as unsigned. -From a test with a hi-gain antenna I verified that the rxwi -contains signed rssi values in the range -13/+81 (inclusive) -with 0 as an error condition. In case of negative values a -condition is triggered and the function return -128dBm while -the signal is at its maximum. This patch correct the cast so -negative values are not treated as very high positive values -(ex. -13 does not become 243). - -Signed-off-by: Luigi Tarenga -Reviewed-by: Stanislaw Gruszka -Signed-off-by: John W. Linville ---- - drivers/net/wireless/rt2x00/rt2800lib.c | 8 ++++---- - 1 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c -index 22a1a8f..7bef66d 100644 ---- a/drivers/net/wireless/rt2x00/rt2800lib.c -+++ b/drivers/net/wireless/rt2x00/rt2800lib.c -@@ -514,9 +514,9 @@ EXPORT_SYMBOL_GPL(rt2800_write_tx_data); - - static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2) - { -- int rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0); -- int rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1); -- int rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2); -+ s8 rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0); -+ s8 rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1); -+ s8 rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2); - u16 eeprom; - u8 offset0; - u8 offset1; -@@ -552,7 +552,7 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2) - * which gives less energy... - */ - rssi0 = max(rssi0, rssi1); -- return max(rssi0, rssi2); -+ return (int)max(rssi0, rssi2); - } - - void rt2800_process_rxwi(struct queue_entry *entry, --- -1.7.4.4 - diff --git a/rt2x00-fix-a-possible-NULL-pointer-dereference.patch b/rt2x00-fix-a-possible-NULL-pointer-dereference.patch deleted file mode 100644 index 8158bcb89..000000000 --- a/rt2x00-fix-a-possible-NULL-pointer-dereference.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 7be081539e540517d5e1fcbf96b8080074afbf08 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Thu, 16 Feb 2012 20:44:59 +0100 -Subject: [PATCH] rt2x00: fix a possible NULL pointer dereference - -The 'rt2x00lib_probe_dev' function tries to -allocate the workqueue. If the allocation -fails, 'rt2x00_lib_remove_dev' is called on -the error path. Because 'rt2x00dev->workqueue' -is NULL in this case, the 'destroy_workqueue' -call will cause a NULL pointer dereference. - -Signed-off-by: Gabor Juhos -Acked-by: Gertjan van Wingerde -Acked-by: Ivo van Doorn -Signed-off-by: John W. Linville ---- - drivers/net/wireless/rt2x00/rt2x00dev.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c -index c3e1aa7..d2a1ea9 100644 ---- a/drivers/net/wireless/rt2x00/rt2x00dev.c -+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c -@@ -1220,7 +1220,8 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) - cancel_work_sync(&rt2x00dev->rxdone_work); - cancel_work_sync(&rt2x00dev->txdone_work); - } -- destroy_workqueue(rt2x00dev->workqueue); -+ if (rt2x00dev->workqueue) -+ destroy_workqueue(rt2x00dev->workqueue); - - /* - * Free the tx status fifo. --- -1.7.4.4 - diff --git a/rtlwifi-Modify-rtl_pci_init-to-return-0-on-success.patch b/rtlwifi-Modify-rtl_pci_init-to-return-0-on-success.patch deleted file mode 100644 index 849c449c4..000000000 --- a/rtlwifi-Modify-rtl_pci_init-to-return-0-on-success.patch +++ /dev/null @@ -1,40 +0,0 @@ -From c27111e5b8d6b1e9296f7075cdc35872f672b524 Mon Sep 17 00:00:00 2001 -From: Simon Graham -Date: Thu, 9 Feb 2012 09:55:13 -0500 -Subject: [PATCH] rtlwifi: Modify rtl_pci_init to return 0 on success - -Fixes problem where caller would think routine succeeded when it failed -leading to divide by zero panic. - -Signed-off-by: Simon Graham -Acked-by: Larry Finger -Signed-off-by: John W. Linville ---- - drivers/net/wireless/rtlwifi/pci.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c -index 39e0907..9245d88 100644 ---- a/drivers/net/wireless/rtlwifi/pci.c -+++ b/drivers/net/wireless/rtlwifi/pci.c -@@ -1501,7 +1501,7 @@ static int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev) - return err; - } - -- return 1; -+ return 0; - } - - static int rtl_pci_start(struct ieee80211_hw *hw) -@@ -1870,7 +1870,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, - } - - /* Init PCI sw */ -- err = !rtl_pci_init(hw, pdev); -+ err = rtl_pci_init(hw, pdev); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Failed to init PCI.\n")); --- -1.7.4.4 - diff --git a/sources b/sources index ea05b23c7..a003ef5f5 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz -8cfe037a7a7a356278ec3638e25ad506 compat-wireless-3.3-rc1-2.tar.bz2 7481fa09f2efda915ed19a9da33a2e59 patch-3.2.10.xz diff --git a/ssb-fix-cardbus-slot-in-hostmode.patch b/ssb-fix-cardbus-slot-in-hostmode.patch deleted file mode 100644 index ed5de4da2..000000000 --- a/ssb-fix-cardbus-slot-in-hostmode.patch +++ /dev/null @@ -1,34 +0,0 @@ -From a6c84622b7fa3ea5417a9d1d0ce0bc3e7fbe3be1 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens -Date: Wed, 1 Feb 2012 00:13:53 +0100 -Subject: [PATCH] ssb: fix cardbus slot in hostmode - -ssb supports one extra device on the cardbus. This results in two -devices in total, one beeing the host controller itself and the other -the external device connected to the hostcontroller over cardbus. - -This makes the cardbus slot work on the Linksys WRT150N. - -Reported-by: Aaron Z -Signed-off-by: Hauke Mehrtens -Signed-off-by: John W. Linville ---- - drivers/ssb/driver_pcicore.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c -index 520e828..49d2091 100644 ---- a/drivers/ssb/driver_pcicore.c -+++ b/drivers/ssb/driver_pcicore.c -@@ -75,7 +75,7 @@ static u32 get_cfgspace_addr(struct ssb_pcicore *pc, - u32 tmp; - - /* We do only have one cardbus device behind the bridge. */ -- if (pc->cardbusmode && (dev >= 1)) -+ if (pc->cardbusmode && (dev > 1)) - goto out; - - if (bus == 0) { --- -1.7.4.4 - diff --git a/zd1211rw-firmware-needs-duration_id-set-to-zero-for-.patch b/zd1211rw-firmware-needs-duration_id-set-to-zero-for-.patch deleted file mode 100644 index cc9a16def..000000000 --- a/zd1211rw-firmware-needs-duration_id-set-to-zero-for-.patch +++ /dev/null @@ -1,51 +0,0 @@ -From e81a7bd55531a77d8c16d44766db4089c2983f1b Mon Sep 17 00:00:00 2001 -From: Tomas Vanek -Date: Sun, 5 Feb 2012 15:51:53 +0200 -Subject: [PATCH] zd1211rw: firmware needs duration_id set to zero for - non-pspoll frames - -Some devices (iwl5100) cannot connect to zd1211rw based AP. It appears that -zd1211 firmware messes up duration_id field if it is not set to zero by driver. - -Sniffing traffic shows that zd1211 is transmitting frames with duration_id bits -14 and 15 set and other bits appearing random. Setting duration_id at driver to -zero results zd1211 outputting sane duration_id. This means that firmware is -setting correct values itself and expects duration_id to be zero in first -place. - -Looking at vendor driver shows that only PSPoll frames have duration_id set by -driver, for other frames duration_id left zero. - -Original bug-report and attached patch at: - http://sourceforge.net/mailarchive/message.php?msg_id=28759111 - -Reported-by: Tomas Vanek -[modified original patch from bug-report, added check for pspoll frame] -Signed-off-by: Jussi Kivilinna -Signed-off-by: John W. Linville ---- - drivers/net/wireless/zd1211rw/zd_mac.c | 8 ++++++++ - 1 files changed, 8 insertions(+), 0 deletions(-) - -diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c -index 0a70149..98a574a 100644 ---- a/drivers/net/wireless/zd1211rw/zd_mac.c -+++ b/drivers/net/wireless/zd1211rw/zd_mac.c -@@ -866,6 +866,14 @@ static int fill_ctrlset(struct zd_mac *mac, - - ZD_ASSERT(frag_len <= 0xffff); - -+ /* -+ * Firmware computes the duration itself (for all frames except PSPoll) -+ * and needs the field set to 0 at input, otherwise firmware messes up -+ * duration_id and sets bits 14 and 15 on. -+ */ -+ if (!ieee80211_is_pspoll(hdr->frame_control)) -+ hdr->duration_id = 0; -+ - txrate = ieee80211_get_tx_rate(mac->hw, info); - - cs->modulation = txrate->hw_value; --- -1.7.4.4 - From bfafc479d5453b4ac25cb0b29a70ae7114656177 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 19 Mar 2012 19:13:43 -0400 Subject: [PATCH 314/487] Linux 3.3 Rebase to the 3.3 release --- ...truct-x86_emulate_ops-with-get_cpuid.patch | 78 - ...-missing-checks-in-syscall-emulation.patch | 144 - alps.patch | 1861 ------- config-arm-generic | 12 + config-arm-highbank | 1 + config-arm-omap-generic | 11 + config-arm-tegra | 9 + config-generic | 61 +- config-powerpc-generic | 7 + config-powerpc64 | 4 + config-sparc64-generic | 1 + config-x86-32-generic | 4 + config-x86-generic | 18 +- config-x86_64-generic | 4 + e1000e-Avoid-wrong-check-on-TX-hang.patch | 95 - ...-handling-on-inode-bitmap-corruption.patch | 19 - hibernate-freeze-filesystems.patch | 326 +- hpsa-add-irqf-shared.patch | 34 - kernel.spec | 76 +- linux-2.6-defaults-acpi-video.patch | 10 +- linux-2.6-serial-460800.patch | 4 +- mm-thp-fix-pmd_bad-triggering.patch | 4 +- msi-irq-sysfs-warning.patch | 87 - nfs-client-freezer.patch | 197 - ...pointer-deref-in-proc_pid_permission.patch | 44 - ...fs-add-hidepid-and-gid-mount-options.patch | 342 -- procfs-parse-mount-options.patch | 173 - rebase-notes.txt | 10 - revert-efi-rtclock.patch | 76 - rtl8192cu-Fix-WARNING-on-suspend-resume.patch | 163 - scsi-fix-sd_revalidate_disk-oops.patch | 116 - sources | 3 +- sysfs-msi-irq-per-device.patch | 239 - utrace.patch | 4300 ++++------------- 34 files changed, 1226 insertions(+), 7307 deletions(-) delete mode 100644 KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch delete mode 100644 KVM-x86-fix-missing-checks-in-syscall-emulation.patch delete mode 100644 alps.patch delete mode 100644 e1000e-Avoid-wrong-check-on-TX-hang.patch delete mode 100644 ext4-Fix-error-handling-on-inode-bitmap-corruption.patch delete mode 100644 hpsa-add-irqf-shared.patch delete mode 100644 msi-irq-sysfs-warning.patch delete mode 100644 nfs-client-freezer.patch delete mode 100644 proc-fix-null-pointer-deref-in-proc_pid_permission.patch delete mode 100644 procfs-add-hidepid-and-gid-mount-options.patch delete mode 100644 procfs-parse-mount-options.patch delete mode 100644 rebase-notes.txt delete mode 100644 revert-efi-rtclock.patch delete mode 100644 rtl8192cu-Fix-WARNING-on-suspend-resume.patch delete mode 100644 scsi-fix-sd_revalidate_disk-oops.patch delete mode 100644 sysfs-msi-irq-per-device.patch diff --git a/KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch b/KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch deleted file mode 100644 index f9dbaa014..000000000 --- a/KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 0769c5de24621141c953fbe1f943582d37cb4244 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Stephan=20B=C3=A4rwolf?= -Date: Thu, 12 Jan 2012 16:43:03 +0100 -Subject: [PATCH 1/2] KVM: x86: extend "struct x86_emulate_ops" with - "get_cpuid" - -In order to be able to proceed checks on CPU-specific properties -within the emulator, function "get_cpuid" is introduced. -With "get_cpuid" it is possible to virtually call the guests -"cpuid"-opcode without changing the VM's context. - -[mtosatti: cleanup/beautify code] - -Signed-off-by: Stephan Baerwolf -Signed-off-by: Marcelo Tosatti ---- - arch/x86/include/asm/kvm_emulate.h | 3 +++ - arch/x86/kvm/x86.c | 23 +++++++++++++++++++++++ - 2 files changed, 26 insertions(+), 0 deletions(-) - -diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h -index ab4092e..c8b2868 100644 ---- a/arch/x86/include/asm/kvm_emulate.h -+++ b/arch/x86/include/asm/kvm_emulate.h -@@ -190,6 +190,9 @@ struct x86_emulate_ops { - int (*intercept)(struct x86_emulate_ctxt *ctxt, - struct x86_instruction_info *info, - enum x86_intercept_stage stage); -+ -+ bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt, -+ u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); - }; - - typedef u32 __attribute__((vector_size(16))) sse128_t; -diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c -index f0fa3fb..c95ca2d 100644 ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -4205,6 +4205,28 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt, - return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage); - } - -+static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt, -+ u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) -+{ -+ struct kvm_cpuid_entry2 *cpuid = NULL; -+ -+ if (eax && ecx) -+ cpuid = kvm_find_cpuid_entry(emul_to_vcpu(ctxt), -+ *eax, *ecx); -+ -+ if (cpuid) { -+ *eax = cpuid->eax; -+ *ecx = cpuid->ecx; -+ if (ebx) -+ *ebx = cpuid->ebx; -+ if (edx) -+ *edx = cpuid->edx; -+ return true; -+ } -+ -+ return false; -+} -+ - static struct x86_emulate_ops emulate_ops = { - .read_std = kvm_read_guest_virt_system, - .write_std = kvm_write_guest_virt_system, -@@ -4236,6 +4258,7 @@ static struct x86_emulate_ops emulate_ops = { - .get_fpu = emulator_get_fpu, - .put_fpu = emulator_put_fpu, - .intercept = emulator_intercept, -+ .get_cpuid = emulator_get_cpuid, - }; - - static void cache_all_regs(struct kvm_vcpu *vcpu) --- -1.7.7.5 - diff --git a/KVM-x86-fix-missing-checks-in-syscall-emulation.patch b/KVM-x86-fix-missing-checks-in-syscall-emulation.patch deleted file mode 100644 index 933a13431..000000000 --- a/KVM-x86-fix-missing-checks-in-syscall-emulation.patch +++ /dev/null @@ -1,144 +0,0 @@ -From e28ba7bb020f07193bc000453c8775e9d2c0dda7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Stephan=20B=C3=A4rwolf?= -Date: Thu, 12 Jan 2012 16:43:04 +0100 -Subject: [PATCH 2/2] KVM: x86: fix missing checks in syscall emulation - -On hosts without this patch, 32bit guests will crash (and 64bit guests -may behave in a wrong way) for example by simply executing following -nasm-demo-application: - - [bits 32] - global _start - SECTION .text - _start: syscall - -(I tested it with winxp and linux - both always crashed) - - Disassembly of section .text: - - 00000000 <_start>: - 0: 0f 05 syscall - -The reason seems a missing "invalid opcode"-trap (int6) for the -syscall opcode "0f05", which is not available on Intel CPUs -within non-longmodes, as also on some AMD CPUs within legacy-mode. -(depending on CPU vendor, MSR_EFER and cpuid) - -Because previous mentioned OSs may not engage corresponding -syscall target-registers (STAR, LSTAR, CSTAR), they remain -NULL and (non trapping) syscalls are leading to multiple -faults and finally crashs. - -Depending on the architecture (AMD or Intel) pretended by -guests, various checks according to vendor's documentation -are implemented to overcome the current issue and behave -like the CPUs physical counterparts. - -[mtosatti: cleanup/beautify code] - -Signed-off-by: Stephan Baerwolf -Signed-off-by: Marcelo Tosatti ---- - arch/x86/include/asm/kvm_emulate.h | 13 +++++++++ - arch/x86/kvm/emulate.c | 51 ++++++++++++++++++++++++++++++++++++ - 2 files changed, 64 insertions(+), 0 deletions(-) - -diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h -index c8b2868..7b9cfc4 100644 ---- a/arch/x86/include/asm/kvm_emulate.h -+++ b/arch/x86/include/asm/kvm_emulate.h -@@ -301,6 +301,19 @@ struct x86_emulate_ctxt { - #define X86EMUL_MODE_PROT (X86EMUL_MODE_PROT16|X86EMUL_MODE_PROT32| \ - X86EMUL_MODE_PROT64) - -+/* CPUID vendors */ -+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx 0x68747541 -+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx 0x444d4163 -+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_edx 0x69746e65 -+ -+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx 0x69444d41 -+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx 0x21726574 -+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_edx 0x74656273 -+ -+#define X86EMUL_CPUID_VENDOR_GenuineIntel_ebx 0x756e6547 -+#define X86EMUL_CPUID_VENDOR_GenuineIntel_ecx 0x6c65746e -+#define X86EMUL_CPUID_VENDOR_GenuineIntel_edx 0x49656e69 -+ - enum x86_intercept_stage { - X86_ICTP_NONE = 0, /* Allow zero-init to not match anything */ - X86_ICPT_PRE_EXCEPT, -diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c -index 05a562b..0982507 100644 ---- a/arch/x86/kvm/emulate.c -+++ b/arch/x86/kvm/emulate.c -@@ -1891,6 +1891,51 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt, - ss->p = 1; - } - -+static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt) -+{ -+ struct x86_emulate_ops *ops = ctxt->ops; -+ u32 eax, ebx, ecx, edx; -+ -+ /* -+ * syscall should always be enabled in longmode - so only become -+ * vendor specific (cpuid) if other modes are active... -+ */ -+ if (ctxt->mode == X86EMUL_MODE_PROT64) -+ return true; -+ -+ eax = 0x00000000; -+ ecx = 0x00000000; -+ if (ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)) { -+ /* -+ * Intel ("GenuineIntel") -+ * remark: Intel CPUs only support "syscall" in 64bit -+ * longmode. Also an 64bit guest with a -+ * 32bit compat-app running will #UD !! While this -+ * behaviour can be fixed (by emulating) into AMD -+ * response - CPUs of AMD can't behave like Intel. -+ */ -+ if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx && -+ ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx && -+ edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx) -+ return false; -+ -+ /* AMD ("AuthenticAMD") */ -+ if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx && -+ ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx && -+ edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx) -+ return true; -+ -+ /* AMD ("AMDisbetter!") */ -+ if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx && -+ ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx && -+ edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx) -+ return true; -+ } -+ -+ /* default: (not Intel, not AMD), apply Intel's stricter rules... */ -+ return false; -+} -+ - static int em_syscall(struct x86_emulate_ctxt *ctxt) - { - struct x86_emulate_ops *ops = ctxt->ops; -@@ -1904,9 +1949,15 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt) - ctxt->mode == X86EMUL_MODE_VM86) - return emulate_ud(ctxt); - -+ if (!(em_syscall_is_enabled(ctxt))) -+ return emulate_ud(ctxt); -+ - ops->get_msr(ctxt, MSR_EFER, &efer); - setup_syscalls_segments(ctxt, &cs, &ss); - -+ if (!(efer & EFER_SCE)) -+ return emulate_ud(ctxt); -+ - ops->get_msr(ctxt, MSR_STAR, &msr_data); - msr_data >>= 32; - cs_sel = (u16)(msr_data & 0xfffc); --- -1.7.7.5 - diff --git a/alps.patch b/alps.patch deleted file mode 100644 index 331716d3b..000000000 --- a/alps.patch +++ /dev/null @@ -1,1861 +0,0 @@ -From d4b347b29b4d14647c7394f7167bf6785dc98e50 Mon Sep 17 00:00:00 2001 -From: Seth Forshee -Date: Mon, 7 Nov 2011 19:53:15 -0800 -Subject: [PATCH 1/6] Input: ALPS - move protocol information to Documentation - -In preparation for new protocol support, move the protocol -information currently documented in alps.c to -Documentation/input/alps.txt, where it can be expanded without -cluttering up the driver. - -Signed-off-by: Seth Forshee -Acked-by: Chase Douglas -Signed-off-by: Dmitry Torokhov ---- - Documentation/input/alps.txt | 75 ++++++++++++++++++++++++++++++++++++++++++ - drivers/input/mouse/alps.c | 37 +-------------------- - 2 files changed, 76 insertions(+), 36 deletions(-) - create mode 100644 Documentation/input/alps.txt - -diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt -new file mode 100644 -index 0000000..ab5478f ---- /dev/null -+++ b/Documentation/input/alps.txt -@@ -0,0 +1,75 @@ -+ALPS Touchpad Protocol -+---------------------- -+ -+Introduction -+------------ -+ -+Currently the ALPS touchpad driver supports two protocol versions in use by -+ALPS touchpads, the "old" and "new" protocol versions. Fundamentally these -+differ only in the format of their event packets (in reality many features may -+be found on new protocol devices that aren't found on the old protocol -+devices, but these are handled transparently as feature differences rather -+than protocol differences). -+ -+Detection -+--------- -+ -+All ALPS touchpads should respond to the "E6 report" command sequence: -+E8-E6-E6-E6-E9. An ALPS touchpad should respond with either 00-00-0A or -+00-00-64. -+ -+If the E6 report is successful, the touchpad model is identified using the "E7 -+report" sequence: E8-E7-E7-E7-E9. The response is the model signature and is -+matched against known models in the alps_model_data_array. -+ -+Packet Format -+------------- -+ -+In the following tables, the following notation us used. -+ -+ CAPITALS = stick, miniscules = touchpad -+ -+?'s can have different meanings on different models, such as wheel rotation, -+extra buttons, stick buttons on a dualpoint, etc. -+ -+PS/2 packet format -+------------------ -+ -+ byte 0: 0 0 YSGN XSGN 1 M R L -+ byte 1: X7 X6 X5 X4 X3 X2 X1 X0 -+ byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 -+ -+Note that the device never signals overflow condition. -+ -+ALPS Absolute Mode - Old Format -+------------------------------- -+ -+ byte 0: 1 0 0 0 1 x9 x8 x7 -+ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -+ byte 2: 0 ? ? l r ? fin ges -+ byte 3: 0 ? ? ? ? y9 y8 y7 -+ byte 4: 0 y6 y5 y4 y3 y2 y1 y0 -+ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 -+ -+ALPS Absolute Mode - New Format -+------------------------------- -+ -+ byte 0: 1 ? ? ? 1 ? ? ? -+ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -+ byte 2: 0 x10 x9 x8 x7 ? fin ges -+ byte 3: 0 y9 y8 y7 1 M R L -+ byte 4: 0 y6 y5 y4 y3 y2 y1 y0 -+ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 -+ -+Dualpoint device -- interleaved packet format -+--------------------------------------------- -+ -+ byte 0: 1 1 0 0 1 1 1 1 -+ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -+ byte 2: 0 x10 x9 x8 x7 0 fin ges -+ byte 3: 0 0 YSGN XSGN 1 1 1 1 -+ byte 4: X7 X6 X5 X4 X3 X2 X1 X0 -+ byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 -+ byte 6: 0 y9 y8 y7 1 m r l -+ byte 7: 0 y6 y5 y4 y3 y2 y1 y0 -+ byte 8: 0 z6 z5 z4 z3 z2 z1 z0 -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 003587c..19d0943 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -67,42 +67,7 @@ static const struct alps_model_info alps_model_data[] = { - * isn't valid per PS/2 spec. - */ - --/* -- * PS/2 packet format -- * -- * byte 0: 0 0 YSGN XSGN 1 M R L -- * byte 1: X7 X6 X5 X4 X3 X2 X1 X0 -- * byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 -- * -- * Note that the device never signals overflow condition. -- * -- * ALPS absolute Mode - new format -- * -- * byte 0: 1 ? ? ? 1 ? ? ? -- * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -- * byte 2: 0 x10 x9 x8 x7 ? fin ges -- * byte 3: 0 y9 y8 y7 1 M R L -- * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 -- * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 -- * -- * Dualpoint device -- interleaved packet format -- * -- * byte 0: 1 1 0 0 1 1 1 1 -- * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -- * byte 2: 0 x10 x9 x8 x7 0 fin ges -- * byte 3: 0 0 YSGN XSGN 1 1 1 1 -- * byte 4: X7 X6 X5 X4 X3 X2 X1 X0 -- * byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 -- * byte 6: 0 y9 y8 y7 1 m r l -- * byte 7: 0 y6 y5 y4 y3 y2 y1 y0 -- * byte 8: 0 z6 z5 z4 z3 z2 z1 z0 -- * -- * CAPITALS = stick, miniscules = touchpad -- * -- * ?'s can have different meanings on different models, -- * such as wheel rotation, extra buttons, stick buttons -- * on a dualpoint, etc. -- */ -+/* Packet formats are described in Documentation/input/alps.txt */ - - static bool alps_is_valid_first_byte(const struct alps_model_info *model, - unsigned char data) --- -1.7.7.3 - - -From fa629ef5222193214da9a2b3c94369f79353bec9 Mon Sep 17 00:00:00 2001 -From: Seth Forshee -Date: Mon, 7 Nov 2011 19:53:24 -0800 -Subject: [PATCH 2/6] Input: ALPS - add protocol version field in - alps_model_info - -In preparation for adding support for more ALPS protocol versions, -add a field for the protocol version to the model info instead of -using a field in the flags. OLDPROTO and !OLDPROTO are now called -version 1 and version 2, repsectively. - -Signed-off-by: Seth Forshee -Acked-by: Chase Douglas -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 47 +++++++++++++++++++++---------------------- - drivers/input/mouse/alps.h | 4 +++ - 2 files changed, 27 insertions(+), 24 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 19d0943..77b776d 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -23,7 +23,6 @@ - #include "psmouse.h" - #include "alps.h" - --#define ALPS_OLDPROTO 0x01 /* old style input */ - #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ - #define ALPS_PASS 0x04 /* device has a pass-through port */ - -@@ -35,30 +34,30 @@ - 6-byte ALPS packet */ - - static const struct alps_model_info alps_model_data[] = { -- { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ -- { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ -- { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, -- { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, -- { { 0x60, 0x03, 0xc8 }, 0xf8, 0xf8, 0 }, /* HP ze1115 */ -- { { 0x63, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ -- { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ -- { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ -- { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ -- { { 0x73, 0x00, 0x0a }, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ -- { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, -- { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ -- { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ -- { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, -- { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ -+ { { 0x32, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ -+ { { 0x33, 0x02, 0x0a }, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ -+ { { 0x53, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x53, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x60, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ -+ { { 0x63, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x02, 0x28 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ -+ { { 0x63, 0x02, 0x3c }, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ -+ { { 0x63, 0x02, 0x50 }, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ -+ { { 0x63, 0x02, 0x64 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ -+ { { 0x73, 0x00, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ -+ { { 0x73, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x73, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ -+ { { 0x20, 0x02, 0x0e }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ -+ { { 0x22, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, -+ { { 0x22, 0x02, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ - /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ -- { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, -+ { { 0x62, 0x02, 0x14 }, ALPS_PROTO_V2, 0xcf, 0xcf, - ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, -- { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ -- { { 0x52, 0x01, 0x14 }, 0xff, 0xff, -- ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ -+ { { 0x73, 0x02, 0x50 }, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ -+ { { 0x52, 0x01, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, -+ ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ - }; - - /* -@@ -112,7 +111,7 @@ static void alps_process_packet(struct psmouse *psmouse) - int x, y, z, ges, fin, left, right, middle; - int back = 0, forward = 0; - -- if (model->flags & ALPS_OLDPROTO) { -+ if (model->proto_version == ALPS_PROTO_V1) { - left = packet[2] & 0x10; - right = packet[2] & 0x08; - middle = 0; -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index 904ed8b..4ce9bba 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -12,8 +12,12 @@ - #ifndef _ALPS_H - #define _ALPS_H - -+#define ALPS_PROTO_V1 0 -+#define ALPS_PROTO_V2 1 -+ - struct alps_model_info { - unsigned char signature[3]; -+ unsigned char proto_version; - unsigned char byte0, mask0; - unsigned char flags; - }; --- -1.7.7.3 - - -From b46615fe9215214ac00e26d35fc54dbe1c510803 Mon Sep 17 00:00:00 2001 -From: Seth Forshee -Date: Mon, 7 Nov 2011 19:53:30 -0800 -Subject: [PATCH 3/6] Input: ALPS - remove assumptions about packet size - -In preparation for version 4 protocol support, which has 8-byte -data packets, remove all hard-coded assumptions about packet size -and use psmouse->pktsize instead. - -Signed-off-by: Seth Forshee -Acked-by: Chase Douglas -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 10 +++++----- - 1 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 77b776d..44a0a71 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -308,7 +308,7 @@ static void alps_flush_packet(unsigned long data) - - serio_pause_rx(psmouse->ps2dev.serio); - -- if (psmouse->pktcnt == 6) { -+ if (psmouse->pktcnt == psmouse->pktsize) { - - /* - * We did not any more data in reasonable amount of time. -@@ -359,8 +359,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) - return PSMOUSE_BAD_DATA; - } - -- /* Bytes 2 - 6 should have 0 in the highest bit */ -- if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && -+ /* Bytes 2 - pktsize should have 0 in the highest bit */ -+ if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && - (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { - psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", - psmouse->pktcnt - 1, -@@ -368,7 +368,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) - return PSMOUSE_BAD_DATA; - } - -- if (psmouse->pktcnt == 6) { -+ if (psmouse->pktcnt == psmouse->pktsize) { - alps_process_packet(psmouse); - return PSMOUSE_FULL_PACKET; - } -@@ -529,7 +529,7 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable) - static int alps_poll(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; -- unsigned char buf[6]; -+ unsigned char buf[sizeof(psmouse->packet)]; - bool poll_failed; - - if (priv->i->flags & ALPS_PASS) --- -1.7.7.3 - - -From 25bded7cd60fa460e520e9f819bd06f4c5cb53f0 Mon Sep 17 00:00:00 2001 -From: Seth Forshee -Date: Mon, 7 Nov 2011 19:53:36 -0800 -Subject: [PATCH 4/6] Input: ALPS - add support for protocol versions 3 and 4 - -This patch adds support for two ALPS touchpad protocols not -supported currently by the driver, which I am arbitrarily naming -version 3 and version 4. Support is single-touch only at this time, -although both protocols are capable of limited multitouch support. - -Thanks to Andrew Skalski, who did the initial reverse-engineering -of the v3 protocol. - -Signed-off-by: Seth Forshee -Acked-by: Chase Douglas -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 791 +++++++++++++++++++++++++++++++++++++++-- - drivers/input/mouse/alps.h | 14 + - drivers/input/mouse/psmouse.h | 1 + - 3 files changed, 768 insertions(+), 38 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index 44a0a71..a0248fd 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -23,6 +23,50 @@ - #include "psmouse.h" - #include "alps.h" - -+/* -+ * Definitions for ALPS version 3 and 4 command mode protocol -+ */ -+#define ALPS_CMD_NIBBLE_10 0x01f2 -+ -+static const struct alps_nibble_commands alps_v3_nibble_commands[] = { -+ { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */ -+ { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ -+ { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ -+ { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ -+ { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ -+ { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ -+ { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ -+ { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ -+ { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ -+ { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ -+ { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ -+ { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ -+ { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ -+ { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ -+ { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ -+ { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ -+}; -+ -+static const struct alps_nibble_commands alps_v4_nibble_commands[] = { -+ { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */ -+ { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ -+ { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ -+ { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ -+ { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ -+ { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ -+ { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ -+ { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ -+ { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ -+ { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ -+ { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ -+ { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ -+ { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ -+ { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ -+ { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ -+ { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ -+}; -+ -+ - #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ - #define ALPS_PASS 0x04 /* device has a pass-through port */ - -@@ -34,30 +78,33 @@ - 6-byte ALPS packet */ - - static const struct alps_model_info alps_model_data[] = { -- { { 0x32, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ -- { { 0x33, 0x02, 0x0a }, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ -- { { 0x53, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x53, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x60, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ -- { { 0x63, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x02, 0x28 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ -- { { 0x63, 0x02, 0x3c }, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ -- { { 0x63, 0x02, 0x50 }, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ -- { { 0x63, 0x02, 0x64 }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x63, 0x03, 0xc8 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ -- { { 0x73, 0x00, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ -- { { 0x73, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -- { { 0x73, 0x02, 0x14 }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ -- { { 0x20, 0x02, 0x0e }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ -- { { 0x22, 0x02, 0x0a }, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, -- { { 0x22, 0x02, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ -+ { { 0x32, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ -+ { { 0x33, 0x02, 0x0a }, 0x00, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ -+ { { 0x53, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x53, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x60, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ -+ { { 0x63, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x02, 0x28 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ -+ { { 0x63, 0x02, 0x3c }, 0x00, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ -+ { { 0x63, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ -+ { { 0x63, 0x02, 0x64 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x63, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ -+ { { 0x73, 0x00, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ -+ { { 0x73, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, -+ { { 0x73, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ -+ { { 0x20, 0x02, 0x0e }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ -+ { { 0x22, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, -+ { { 0x22, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ - /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ -- { { 0x62, 0x02, 0x14 }, ALPS_PROTO_V2, 0xcf, 0xcf, -+ { { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, - ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, -- { { 0x73, 0x02, 0x50 }, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ -- { { 0x52, 0x01, 0x14 }, ALPS_PROTO_V2, 0xff, 0xff, -- ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ -+ { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ -+ { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, -+ ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ -+ { { 0x73, 0x02, 0x64 }, 0x9b, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, -+ { { 0x73, 0x02, 0x64 }, 0x9d, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, -+ { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, - }; - - /* -@@ -101,7 +148,7 @@ static void alps_report_buttons(struct psmouse *psmouse, - input_sync(dev2); - } - --static void alps_process_packet(struct psmouse *psmouse) -+static void alps_process_packet_v1_v2(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; -@@ -203,6 +250,224 @@ static void alps_process_packet(struct psmouse *psmouse) - input_sync(dev); - } - -+static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ unsigned char *packet = psmouse->packet; -+ struct input_dev *dev = priv->dev2; -+ int x, y, z, left, right, middle; -+ -+ /* Sanity check packet */ -+ if (!(packet[0] & 0x40)) { -+ psmouse_dbg(psmouse, "Bad trackstick packet, discarding\n"); -+ return; -+ } -+ -+ /* -+ * There's a special packet that seems to indicate the end -+ * of a stream of trackstick data. Filter these out. -+ */ -+ if (packet[1] == 0x7f && packet[2] == 0x7f && packet[4] == 0x7f) -+ return; -+ -+ x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f)); -+ y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f)); -+ z = (packet[4] & 0x7c) >> 2; -+ -+ /* -+ * The x and y values tend to be quite large, and when used -+ * alone the trackstick is difficult to use. Scale them down -+ * to compensate. -+ */ -+ x /= 8; -+ y /= 8; -+ -+ input_report_rel(dev, REL_X, x); -+ input_report_rel(dev, REL_Y, -y); -+ -+ /* -+ * Most ALPS models report the trackstick buttons in the touchpad -+ * packets, but a few report them here. No reliable way has been -+ * found to differentiate between the models upfront, so we enable -+ * the quirk in response to seeing a button press in the trackstick -+ * packet. -+ */ -+ left = packet[3] & 0x01; -+ right = packet[3] & 0x02; -+ middle = packet[3] & 0x04; -+ -+ if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) && -+ (left || right || middle)) -+ priv->quirks |= ALPS_QUIRK_TRACKSTICK_BUTTONS; -+ -+ if (priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) { -+ input_report_key(dev, BTN_LEFT, left); -+ input_report_key(dev, BTN_RIGHT, right); -+ input_report_key(dev, BTN_MIDDLE, middle); -+ } -+ -+ input_sync(dev); -+ return; -+} -+ -+static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ unsigned char *packet = psmouse->packet; -+ struct input_dev *dev = psmouse->dev; -+ struct input_dev *dev2 = priv->dev2; -+ int x, y, z; -+ int left, right, middle; -+ -+ /* -+ * There's no single feature of touchpad position and bitmap -+ * packets that can be used to distinguish between them. We -+ * rely on the fact that a bitmap packet should always follow -+ * a position packet with bit 6 of packet[4] set. -+ */ -+ if (priv->multi_packet) { -+ priv->multi_packet = 0; -+ -+ /* -+ * Sometimes a position packet will indicate a multi-packet -+ * sequence, but then what follows is another position -+ * packet. Check for this, and when it happens process the -+ * position packet as usual. -+ */ -+ if (packet[0] & 0x40) { -+ /* -+ * Bitmap packets are not yet supported, so for now -+ * just ignore them. -+ */ -+ return; -+ } -+ } -+ -+ if (!priv->multi_packet && (packet[4] & 0x40)) -+ priv->multi_packet = 1; -+ else -+ priv->multi_packet = 0; -+ -+ left = packet[3] & 0x01; -+ right = packet[3] & 0x02; -+ middle = packet[3] & 0x04; -+ -+ x = ((packet[1] & 0x7f) << 4) | ((packet[4] & 0x30) >> 2) | -+ ((packet[0] & 0x30) >> 4); -+ y = ((packet[2] & 0x7f) << 4) | (packet[4] & 0x0f); -+ z = packet[5] & 0x7f; -+ -+ /* -+ * Sometimes the hardware sends a single packet with z = 0 -+ * in the middle of a stream. Real releases generate packets -+ * with x, y, and z all zero, so these seem to be flukes. -+ * Ignore them. -+ */ -+ if (x && y && !z) -+ return; -+ -+ if (z >= 64) -+ input_report_key(dev, BTN_TOUCH, 1); -+ else -+ input_report_key(dev, BTN_TOUCH, 0); -+ -+ if (z > 0) { -+ input_report_abs(dev, ABS_X, x); -+ input_report_abs(dev, ABS_Y, y); -+ } -+ input_report_abs(dev, ABS_PRESSURE, z); -+ -+ input_report_key(dev, BTN_TOOL_FINGER, z > 0); -+ input_report_key(dev, BTN_LEFT, left); -+ input_report_key(dev, BTN_RIGHT, right); -+ input_report_key(dev, BTN_MIDDLE, middle); -+ -+ input_sync(dev); -+ -+ if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { -+ left = packet[3] & 0x10; -+ right = packet[3] & 0x20; -+ middle = packet[3] & 0x40; -+ -+ input_report_key(dev2, BTN_LEFT, left); -+ input_report_key(dev2, BTN_RIGHT, right); -+ input_report_key(dev2, BTN_MIDDLE, middle); -+ input_sync(dev2); -+ } -+} -+ -+static void alps_process_packet_v3(struct psmouse *psmouse) -+{ -+ unsigned char *packet = psmouse->packet; -+ -+ /* -+ * v3 protocol packets come in three types, two representing -+ * touchpad data and one representing trackstick data. -+ * Trackstick packets seem to be distinguished by always -+ * having 0x3f in the last byte. This value has never been -+ * observed in the last byte of either of the other types -+ * of packets. -+ */ -+ if (packet[5] == 0x3f) { -+ alps_process_trackstick_packet_v3(psmouse); -+ return; -+ } -+ -+ alps_process_touchpad_packet_v3(psmouse); -+} -+ -+static void alps_process_packet_v4(struct psmouse *psmouse) -+{ -+ unsigned char *packet = psmouse->packet; -+ struct input_dev *dev = psmouse->dev; -+ int x, y, z; -+ int left, right; -+ -+ left = packet[4] & 0x01; -+ right = packet[4] & 0x02; -+ -+ x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) | -+ ((packet[0] & 0x30) >> 4); -+ y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f); -+ z = packet[5] & 0x7f; -+ -+ if (z >= 64) -+ input_report_key(dev, BTN_TOUCH, 1); -+ else -+ input_report_key(dev, BTN_TOUCH, 0); -+ -+ if (z > 0) { -+ input_report_abs(dev, ABS_X, x); -+ input_report_abs(dev, ABS_Y, y); -+ } -+ input_report_abs(dev, ABS_PRESSURE, z); -+ -+ input_report_key(dev, BTN_TOOL_FINGER, z > 0); -+ input_report_key(dev, BTN_LEFT, left); -+ input_report_key(dev, BTN_RIGHT, right); -+ -+ input_sync(dev); -+} -+ -+static void alps_process_packet(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ const struct alps_model_info *model = priv->i; -+ -+ switch (model->proto_version) { -+ case ALPS_PROTO_V1: -+ case ALPS_PROTO_V2: -+ alps_process_packet_v1_v2(psmouse); -+ break; -+ case ALPS_PROTO_V3: -+ alps_process_packet_v3(psmouse); -+ break; -+ case ALPS_PROTO_V4: -+ alps_process_packet_v4(psmouse); -+ break; -+ } -+} -+ - static void alps_report_bare_ps2_packet(struct psmouse *psmouse, - unsigned char packet[], - bool report_buttons) -@@ -376,11 +641,127 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) - return PSMOUSE_GOOD_DATA; - } - -+static int alps_command_mode_send_nibble(struct psmouse *psmouse, int nibble) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ struct alps_data *priv = psmouse->private; -+ int command; -+ unsigned char *param; -+ unsigned char dummy[4]; -+ -+ BUG_ON(nibble > 0xf); -+ -+ command = priv->nibble_commands[nibble].command; -+ param = (command & 0x0f00) ? -+ dummy : (unsigned char *)&priv->nibble_commands[nibble].data; -+ -+ if (ps2_command(ps2dev, param, command)) -+ return -1; -+ -+ return 0; -+} -+ -+static int alps_command_mode_set_addr(struct psmouse *psmouse, int addr) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ struct alps_data *priv = psmouse->private; -+ int i, nibble; -+ -+ if (ps2_command(ps2dev, NULL, priv->addr_command)) -+ return -1; -+ -+ for (i = 12; i >= 0; i -= 4) { -+ nibble = (addr >> i) & 0xf; -+ if (alps_command_mode_send_nibble(psmouse, nibble)) -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static int __alps_command_mode_read_reg(struct psmouse *psmouse, int addr) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ unsigned char param[4]; -+ -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) -+ return -1; -+ -+ /* -+ * The address being read is returned in the first two bytes -+ * of the result. Check that this address matches the expected -+ * address. -+ */ -+ if (addr != ((param[0] << 8) | param[1])) -+ return -1; -+ -+ return param[2]; -+} -+ -+static int alps_command_mode_read_reg(struct psmouse *psmouse, int addr) -+{ -+ if (alps_command_mode_set_addr(psmouse, addr)) -+ return -1; -+ return __alps_command_mode_read_reg(psmouse, addr); -+} -+ -+static int __alps_command_mode_write_reg(struct psmouse *psmouse, u8 value) -+{ -+ if (alps_command_mode_send_nibble(psmouse, (value >> 4) & 0xf)) -+ return -1; -+ if (alps_command_mode_send_nibble(psmouse, value & 0xf)) -+ return -1; -+ return 0; -+} -+ -+static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr, -+ u8 value) -+{ -+ if (alps_command_mode_set_addr(psmouse, addr)) -+ return -1; -+ return __alps_command_mode_write_reg(psmouse, value); -+} -+ -+static int alps_enter_command_mode(struct psmouse *psmouse, -+ unsigned char *resp) -+{ -+ unsigned char param[4]; -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ -+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || -+ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { -+ psmouse_err(psmouse, "failed to enter command mode\n"); -+ return -1; -+ } -+ -+ if (param[0] != 0x88 && param[1] != 0x07) { -+ psmouse_dbg(psmouse, -+ "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", -+ param[0], param[1], param[2]); -+ return -1; -+ } -+ -+ if (resp) -+ *resp = param[2]; -+ return 0; -+} -+ -+static inline int alps_exit_command_mode(struct psmouse *psmouse) -+{ -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) -+ return -1; -+ return 0; -+} -+ - static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) - { - struct ps2dev *ps2dev = &psmouse->ps2dev; - static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; - unsigned char param[4]; -+ const struct alps_model_info *model = NULL; - int i; - - /* -@@ -428,12 +809,41 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int - *version = (param[0] << 8) | (param[1] << 4) | i; - } - -- for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) -+ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { - if (!memcmp(param, alps_model_data[i].signature, -- sizeof(alps_model_data[i].signature))) -- return alps_model_data + i; -+ sizeof(alps_model_data[i].signature))) { -+ model = alps_model_data + i; -+ break; -+ } -+ } - -- return NULL; -+ if (model && model->proto_version > ALPS_PROTO_V2) { -+ /* -+ * Need to check command mode response to identify -+ * model -+ */ -+ model = NULL; -+ if (alps_enter_command_mode(psmouse, param)) { -+ psmouse_warn(psmouse, -+ "touchpad failed to enter command mode\n"); -+ } else { -+ for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { -+ if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && -+ alps_model_data[i].command_mode_resp == param[0]) { -+ model = alps_model_data + i; -+ break; -+ } -+ } -+ alps_exit_command_mode(psmouse); -+ -+ if (!model) -+ psmouse_dbg(psmouse, -+ "Unknown command mode response %2.2x\n", -+ param[0]); -+ } -+ } -+ -+ return model; - } - - /* -@@ -441,7 +851,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int - * subsequent commands. It looks like glidepad is behind stickpointer, - * I'd thought it would be other way around... - */ --static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) -+static int alps_passthrough_mode_v2(struct psmouse *psmouse, bool enable) - { - struct ps2dev *ps2dev = &psmouse->ps2dev; - int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; -@@ -458,7 +868,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) - return 0; - } - --static int alps_absolute_mode(struct psmouse *psmouse) -+static int alps_absolute_mode_v1_v2(struct psmouse *psmouse) - { - struct ps2dev *ps2dev = &psmouse->ps2dev; - -@@ -533,13 +943,13 @@ static int alps_poll(struct psmouse *psmouse) - bool poll_failed; - - if (priv->i->flags & ALPS_PASS) -- alps_passthrough_mode(psmouse, true); -+ alps_passthrough_mode_v2(psmouse, true); - - poll_failed = ps2_command(&psmouse->ps2dev, buf, - PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; - - if (priv->i->flags & ALPS_PASS) -- alps_passthrough_mode(psmouse, false); -+ alps_passthrough_mode_v2(psmouse, false); - - if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) - return -1; -@@ -556,13 +966,13 @@ static int alps_poll(struct psmouse *psmouse) - return 0; - } - --static int alps_hw_init(struct psmouse *psmouse) -+static int alps_hw_init_v1_v2(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; - - if ((model->flags & ALPS_PASS) && -- alps_passthrough_mode(psmouse, true)) { -+ alps_passthrough_mode_v2(psmouse, true)) { - return -1; - } - -@@ -571,13 +981,13 @@ static int alps_hw_init(struct psmouse *psmouse) - return -1; - } - -- if (alps_absolute_mode(psmouse)) { -+ if (alps_absolute_mode_v1_v2(psmouse)) { - psmouse_err(psmouse, "Failed to enable absolute mode\n"); - return -1; - } - - if ((model->flags & ALPS_PASS) && -- alps_passthrough_mode(psmouse, false)) { -+ alps_passthrough_mode_v2(psmouse, false)) { - return -1; - } - -@@ -590,6 +1000,297 @@ static int alps_hw_init(struct psmouse *psmouse) - return 0; - } - -+/* -+ * Enable or disable passthrough mode to the trackstick. Must be in -+ * command mode when calling this function. -+ */ -+static int alps_passthrough_mode_v3(struct psmouse *psmouse, bool enable) -+{ -+ int reg_val; -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0008); -+ if (reg_val == -1) -+ return -1; -+ -+ if (enable) -+ reg_val |= 0x01; -+ else -+ reg_val &= ~0x01; -+ -+ if (__alps_command_mode_write_reg(psmouse, reg_val)) -+ return -1; -+ -+ return 0; -+} -+ -+/* Must be in command mode when calling this function */ -+static int alps_absolute_mode_v3(struct psmouse *psmouse) -+{ -+ int reg_val; -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0004); -+ if (reg_val == -1) -+ return -1; -+ -+ reg_val |= 0x06; -+ if (__alps_command_mode_write_reg(psmouse, reg_val)) -+ return -1; -+ -+ return 0; -+} -+ -+static int alps_hw_init_v3(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ int reg_val; -+ unsigned char param[4]; -+ -+ priv->nibble_commands = alps_v3_nibble_commands; -+ priv->addr_command = PSMOUSE_CMD_RESET_WRAP; -+ -+ if (alps_enter_command_mode(psmouse, NULL)) -+ goto error; -+ -+ /* Check for trackstick */ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0008); -+ if (reg_val == -1) -+ goto error; -+ if (reg_val & 0x80) { -+ if (alps_passthrough_mode_v3(psmouse, true)) -+ goto error; -+ if (alps_exit_command_mode(psmouse)) -+ goto error; -+ -+ /* -+ * E7 report for the trackstick -+ * -+ * There have been reports of failures to seem to trace back -+ * to the above trackstick check failing. When these occur -+ * this E7 report fails, so when that happens we continue -+ * with the assumption that there isn't a trackstick after -+ * all. -+ */ -+ param[0] = 0x64; -+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || -+ ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { -+ psmouse_warn(psmouse, "trackstick E7 report failed\n"); -+ } else { -+ psmouse_dbg(psmouse, -+ "trackstick E7 report: %2.2x %2.2x %2.2x\n", -+ param[0], param[1], param[2]); -+ -+ /* -+ * Not sure what this does, but it is absolutely -+ * essential. Without it, the touchpad does not -+ * work at all and the trackstick just emits normal -+ * PS/2 packets. -+ */ -+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || -+ alps_command_mode_send_nibble(psmouse, 0x9) || -+ alps_command_mode_send_nibble(psmouse, 0x4)) { -+ psmouse_err(psmouse, -+ "Error sending magic E6 sequence\n"); -+ goto error_passthrough; -+ } -+ } -+ -+ if (alps_enter_command_mode(psmouse, NULL)) -+ goto error_passthrough; -+ if (alps_passthrough_mode_v3(psmouse, false)) -+ goto error; -+ } -+ -+ if (alps_absolute_mode_v3(psmouse)) { -+ psmouse_err(psmouse, "Failed to enter absolute mode\n"); -+ goto error; -+ } -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0006); -+ if (reg_val == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) -+ goto error; -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0007); -+ if (reg_val == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) -+ goto error; -+ -+ if (alps_command_mode_read_reg(psmouse, 0x0144) == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, 0x04)) -+ goto error; -+ -+ if (alps_command_mode_read_reg(psmouse, 0x0159) == -1) -+ goto error; -+ if (__alps_command_mode_write_reg(psmouse, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_read_reg(psmouse, 0x0163) == -1) -+ goto error; -+ if (alps_command_mode_write_reg(psmouse, 0x0163, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_read_reg(psmouse, 0x0162) == -1) -+ goto error; -+ if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04)) -+ goto error; -+ -+ /* -+ * This ensures the trackstick packets are in the format -+ * supported by this driver. If bit 1 isn't set the packet -+ * format is different. -+ */ -+ if (alps_command_mode_write_reg(psmouse, 0x0008, 0x82)) -+ goto error; -+ -+ alps_exit_command_mode(psmouse); -+ -+ /* Set rate and enable data reporting */ -+ param[0] = 0x64; -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { -+ psmouse_err(psmouse, "Failed to enable data reporting\n"); -+ return -1; -+ } -+ -+ return 0; -+ -+error_passthrough: -+ /* Something failed while in passthrough mode, so try to get out */ -+ if (!alps_enter_command_mode(psmouse, NULL)) -+ alps_passthrough_mode_v3(psmouse, false); -+error: -+ /* -+ * Leaving the touchpad in command mode will essentially render -+ * it unusable until the machine reboots, so exit it here just -+ * to be safe -+ */ -+ alps_exit_command_mode(psmouse); -+ return -1; -+} -+ -+/* Must be in command mode when calling this function */ -+static int alps_absolute_mode_v4(struct psmouse *psmouse) -+{ -+ int reg_val; -+ -+ reg_val = alps_command_mode_read_reg(psmouse, 0x0004); -+ if (reg_val == -1) -+ return -1; -+ -+ reg_val |= 0x02; -+ if (__alps_command_mode_write_reg(psmouse, reg_val)) -+ return -1; -+ -+ return 0; -+} -+ -+static int alps_hw_init_v4(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ struct ps2dev *ps2dev = &psmouse->ps2dev; -+ unsigned char param[4]; -+ -+ priv->nibble_commands = alps_v4_nibble_commands; -+ priv->addr_command = PSMOUSE_CMD_DISABLE; -+ -+ if (alps_enter_command_mode(psmouse, NULL)) -+ goto error; -+ -+ if (alps_absolute_mode_v4(psmouse)) { -+ psmouse_err(psmouse, "Failed to enter absolute mode\n"); -+ goto error; -+ } -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0007, 0x8c)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0149, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0160, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x017f, 0x15)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0151, 0x01)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0168, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x014a, 0x03)) -+ goto error; -+ -+ if (alps_command_mode_write_reg(psmouse, 0x0161, 0x03)) -+ goto error; -+ -+ alps_exit_command_mode(psmouse); -+ -+ /* -+ * This sequence changes the output from a 9-byte to an -+ * 8-byte format. All the same data seems to be present, -+ * just in a more compact format. -+ */ -+ param[0] = 0xc8; -+ param[1] = 0x64; -+ param[2] = 0x50; -+ if (ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || -+ ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE) || -+ ps2_command(ps2dev, ¶m[2], PSMOUSE_CMD_SETRATE) || -+ ps2_command(ps2dev, param, PSMOUSE_CMD_GETID)) -+ return -1; -+ -+ /* Set rate and enable data reporting */ -+ param[0] = 0x64; -+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || -+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { -+ psmouse_err(psmouse, "Failed to enable data reporting\n"); -+ return -1; -+ } -+ -+ return 0; -+ -+error: -+ /* -+ * Leaving the touchpad in command mode will essentially render -+ * it unusable until the machine reboots, so exit it here just -+ * to be safe -+ */ -+ alps_exit_command_mode(psmouse); -+ return -1; -+} -+ -+static int alps_hw_init(struct psmouse *psmouse) -+{ -+ struct alps_data *priv = psmouse->private; -+ const struct alps_model_info *model = priv->i; -+ int ret = -1; -+ -+ switch (model->proto_version) { -+ case ALPS_PROTO_V1: -+ case ALPS_PROTO_V2: -+ ret = alps_hw_init_v1_v2(psmouse); -+ break; -+ case ALPS_PROTO_V3: -+ ret = alps_hw_init_v3(psmouse); -+ break; -+ case ALPS_PROTO_V4: -+ ret = alps_hw_init_v4(psmouse); -+ break; -+ } -+ -+ return ret; -+} -+ - static int alps_reconnect(struct psmouse *psmouse) - { - const struct alps_model_info *model; -@@ -630,6 +1331,8 @@ int alps_init(struct psmouse *psmouse) - - psmouse->private = priv; - -+ psmouse_reset(psmouse); -+ - model = alps_get_model(psmouse, &version); - if (!model) - goto init_fail; -@@ -657,8 +1360,20 @@ int alps_init(struct psmouse *psmouse) - BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); - - dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); -- input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); -- input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); -+ -+ switch (model->proto_version) { -+ case ALPS_PROTO_V1: -+ case ALPS_PROTO_V2: -+ input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); -+ input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); -+ break; -+ case ALPS_PROTO_V3: -+ case ALPS_PROTO_V4: -+ input_set_abs_params(dev1, ABS_X, 0, 2000, 0, 0); -+ input_set_abs_params(dev1, ABS_Y, 0, 1400, 0, 0); -+ break; -+ } -+ - input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); - - if (model->flags & ALPS_WHEEL) { -@@ -701,7 +1416,7 @@ int alps_init(struct psmouse *psmouse) - psmouse->poll = alps_poll; - psmouse->disconnect = alps_disconnect; - psmouse->reconnect = alps_reconnect; -- psmouse->pktsize = 6; -+ psmouse->pktsize = model->proto_version == ALPS_PROTO_V4 ? 8 : 6; - - /* We are having trouble resyncing ALPS touchpads so disable it for now */ - psmouse->resync_time = 0; -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index 4ce9bba..62db7f4 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -14,22 +14,36 @@ - - #define ALPS_PROTO_V1 0 - #define ALPS_PROTO_V2 1 -+#define ALPS_PROTO_V3 2 -+#define ALPS_PROTO_V4 3 - - struct alps_model_info { - unsigned char signature[3]; -+ unsigned char command_mode_resp; /* v3/v4 only */ - unsigned char proto_version; - unsigned char byte0, mask0; - unsigned char flags; - }; - -+struct alps_nibble_commands { -+ int command; -+ unsigned char data; -+}; -+ - struct alps_data { - struct input_dev *dev2; /* Relative device */ - char phys[32]; /* Phys */ - const struct alps_model_info *i;/* Info */ -+ const struct alps_nibble_commands *nibble_commands; -+ int addr_command; /* Command to set register address */ - int prev_fin; /* Finger bit from previous packet */ -+ int multi_packet; /* Multi-packet data in progress */ -+ u8 quirks; - struct timer_list timer; - }; - -+#define ALPS_QUIRK_TRACKSTICK_BUTTONS 1 /* trakcstick buttons in trackstick packet */ -+ - #ifdef CONFIG_MOUSE_PS2_ALPS - int alps_detect(struct psmouse *psmouse, bool set_properties); - int alps_init(struct psmouse *psmouse); -diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h -index 9b84b0c..11a9c6c 100644 ---- a/drivers/input/mouse/psmouse.h -+++ b/drivers/input/mouse/psmouse.h -@@ -8,6 +8,7 @@ - #define PSMOUSE_CMD_SETSTREAM 0x00ea - #define PSMOUSE_CMD_SETPOLL 0x00f0 - #define PSMOUSE_CMD_POLL 0x00eb /* caller sets number of bytes to receive */ -+#define PSMOUSE_CMD_RESET_WRAP 0x00ec - #define PSMOUSE_CMD_GETID 0x02f2 - #define PSMOUSE_CMD_SETRATE 0x10f3 - #define PSMOUSE_CMD_ENABLE 0x00f4 --- -1.7.7.3 - - -From 01ce661fc83005947dc958a5739c153843af8a73 Mon Sep 17 00:00:00 2001 -From: Seth Forshee -Date: Mon, 7 Nov 2011 19:54:13 -0800 -Subject: [PATCH 5/6] Input: ALPS - add semi-MT support for v3 protocol - -Signed-off-by: Seth Forshee -Acked-by: Chase Douglas -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/alps.c | 233 ++++++++++++++++++++++++++++++++++++++++---- - drivers/input/mouse/alps.h | 1 + - 2 files changed, 215 insertions(+), 19 deletions(-) - -diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c -index a0248fd..bd87380 100644 ---- a/drivers/input/mouse/alps.c -+++ b/drivers/input/mouse/alps.c -@@ -17,6 +17,7 @@ - - #include - #include -+#include - #include - #include - -@@ -26,6 +27,12 @@ - /* - * Definitions for ALPS version 3 and 4 command mode protocol - */ -+#define ALPS_V3_X_MAX 2000 -+#define ALPS_V3_Y_MAX 1400 -+ -+#define ALPS_BITMAP_X_BITS 15 -+#define ALPS_BITMAP_Y_BITS 11 -+ - #define ALPS_CMD_NIBBLE_10 0x01f2 - - static const struct alps_nibble_commands alps_v3_nibble_commands[] = { -@@ -250,6 +257,137 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) - input_sync(dev); - } - -+/* -+ * Process bitmap data from v3 and v4 protocols. Returns the number of -+ * fingers detected. A return value of 0 means at least one of the -+ * bitmaps was empty. -+ * -+ * The bitmaps don't have enough data to track fingers, so this function -+ * only generates points representing a bounding box of all contacts. -+ * These points are returned in x1, y1, x2, and y2 when the return value -+ * is greater than 0. -+ */ -+static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, -+ int *x1, int *y1, int *x2, int *y2) -+{ -+ struct alps_bitmap_point { -+ int start_bit; -+ int num_bits; -+ }; -+ -+ int fingers_x = 0, fingers_y = 0, fingers; -+ int i, bit, prev_bit; -+ struct alps_bitmap_point x_low = {0,}, x_high = {0,}; -+ struct alps_bitmap_point y_low = {0,}, y_high = {0,}; -+ struct alps_bitmap_point *point; -+ -+ if (!x_map || !y_map) -+ return 0; -+ -+ *x1 = *y1 = *x2 = *y2 = 0; -+ -+ prev_bit = 0; -+ point = &x_low; -+ for (i = 0; x_map != 0; i++, x_map >>= 1) { -+ bit = x_map & 1; -+ if (bit) { -+ if (!prev_bit) { -+ point->start_bit = i; -+ fingers_x++; -+ } -+ point->num_bits++; -+ } else { -+ if (prev_bit) -+ point = &x_high; -+ else -+ point->num_bits = 0; -+ } -+ prev_bit = bit; -+ } -+ -+ /* -+ * y bitmap is reversed for what we need (lower positions are in -+ * higher bits), so we process from the top end. -+ */ -+ y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - ALPS_BITMAP_Y_BITS); -+ prev_bit = 0; -+ point = &y_low; -+ for (i = 0; y_map != 0; i++, y_map <<= 1) { -+ bit = y_map & (1 << (sizeof(y_map) * BITS_PER_BYTE - 1)); -+ if (bit) { -+ if (!prev_bit) { -+ point->start_bit = i; -+ fingers_y++; -+ } -+ point->num_bits++; -+ } else { -+ if (prev_bit) -+ point = &y_high; -+ else -+ point->num_bits = 0; -+ } -+ prev_bit = bit; -+ } -+ -+ /* -+ * Fingers can overlap, so we use the maximum count of fingers -+ * on either axis as the finger count. -+ */ -+ fingers = max(fingers_x, fingers_y); -+ -+ /* -+ * If total fingers is > 1 but either axis reports only a single -+ * contact, we have overlapping or adjacent fingers. For the -+ * purposes of creating a bounding box, divide the single contact -+ * (roughly) equally between the two points. -+ */ -+ if (fingers > 1) { -+ if (fingers_x == 1) { -+ i = x_low.num_bits / 2; -+ x_low.num_bits = x_low.num_bits - i; -+ x_high.start_bit = x_low.start_bit + i; -+ x_high.num_bits = max(i, 1); -+ } else if (fingers_y == 1) { -+ i = y_low.num_bits / 2; -+ y_low.num_bits = y_low.num_bits - i; -+ y_high.start_bit = y_low.start_bit + i; -+ y_high.num_bits = max(i, 1); -+ } -+ } -+ -+ *x1 = (ALPS_V3_X_MAX * (2 * x_low.start_bit + x_low.num_bits - 1)) / -+ (2 * (ALPS_BITMAP_X_BITS - 1)); -+ *y1 = (ALPS_V3_Y_MAX * (2 * y_low.start_bit + y_low.num_bits - 1)) / -+ (2 * (ALPS_BITMAP_Y_BITS - 1)); -+ -+ if (fingers > 1) { -+ *x2 = (ALPS_V3_X_MAX * (2 * x_high.start_bit + x_high.num_bits - 1)) / -+ (2 * (ALPS_BITMAP_X_BITS - 1)); -+ *y2 = (ALPS_V3_Y_MAX * (2 * y_high.start_bit + y_high.num_bits - 1)) / -+ (2 * (ALPS_BITMAP_Y_BITS - 1)); -+ } -+ -+ return fingers; -+} -+ -+static void alps_set_slot(struct input_dev *dev, int slot, bool active, -+ int x, int y) -+{ -+ input_mt_slot(dev, slot); -+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); -+ if (active) { -+ input_report_abs(dev, ABS_MT_POSITION_X, x); -+ input_report_abs(dev, ABS_MT_POSITION_Y, y); -+ } -+} -+ -+static void alps_report_semi_mt_data(struct input_dev *dev, int num_fingers, -+ int x1, int y1, int x2, int y2) -+{ -+ alps_set_slot(dev, 0, num_fingers != 0, x1, y1); -+ alps_set_slot(dev, 1, num_fingers == 2, x2, y2); -+} -+ - static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) - { - struct alps_data *priv = psmouse->private; -@@ -318,16 +456,17 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - struct input_dev *dev2 = priv->dev2; - int x, y, z; - int left, right, middle; -+ int x1 = 0, y1 = 0, x2 = 0, y2 = 0; -+ int fingers = 0, bmap_fingers; -+ unsigned int x_bitmap, y_bitmap; - - /* -- * There's no single feature of touchpad position and bitmap -- * packets that can be used to distinguish between them. We -- * rely on the fact that a bitmap packet should always follow -- * a position packet with bit 6 of packet[4] set. -+ * There's no single feature of touchpad position and bitmap packets -+ * that can be used to distinguish between them. We rely on the fact -+ * that a bitmap packet should always follow a position packet with -+ * bit 6 of packet[4] set. - */ - if (priv->multi_packet) { -- priv->multi_packet = 0; -- - /* - * Sometimes a position packet will indicate a multi-packet - * sequence, but then what follows is another position -@@ -335,18 +474,49 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - * position packet as usual. - */ - if (packet[0] & 0x40) { -+ fingers = (packet[5] & 0x3) + 1; -+ x_bitmap = ((packet[4] & 0x7e) << 8) | -+ ((packet[1] & 0x7f) << 2) | -+ ((packet[0] & 0x30) >> 4); -+ y_bitmap = ((packet[3] & 0x70) << 4) | -+ ((packet[2] & 0x7f) << 1) | -+ (packet[4] & 0x01); -+ -+ bmap_fingers = alps_process_bitmap(x_bitmap, y_bitmap, -+ &x1, &y1, &x2, &y2); -+ - /* -- * Bitmap packets are not yet supported, so for now -- * just ignore them. -+ * We shouldn't report more than one finger if -+ * we don't have two coordinates. - */ -- return; -+ if (fingers > 1 && bmap_fingers < 2) -+ fingers = bmap_fingers; -+ -+ /* Now process position packet */ -+ packet = priv->multi_data; -+ } else { -+ priv->multi_packet = 0; - } - } - -- if (!priv->multi_packet && (packet[4] & 0x40)) -+ /* -+ * Bit 6 of byte 0 is not usually set in position packets. The only -+ * times it seems to be set is in situations where the data is -+ * suspect anyway, e.g. a palm resting flat on the touchpad. Given -+ * this combined with the fact that this bit is useful for filtering -+ * out misidentified bitmap packets, we reject anything with this -+ * bit set. -+ */ -+ if (packet[0] & 0x40) -+ return; -+ -+ if (!priv->multi_packet && (packet[4] & 0x40)) { - priv->multi_packet = 1; -- else -- priv->multi_packet = 0; -+ memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); -+ return; -+ } -+ -+ priv->multi_packet = 0; - - left = packet[3] & 0x01; - right = packet[3] & 0x02; -@@ -366,22 +536,38 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) - if (x && y && !z) - return; - -+ /* -+ * If we don't have MT data or the bitmaps were empty, we have -+ * to rely on ST data. -+ */ -+ if (!fingers) { -+ x1 = x; -+ y1 = y; -+ fingers = z > 0 ? 1 : 0; -+ } -+ - if (z >= 64) - input_report_key(dev, BTN_TOUCH, 1); - else - input_report_key(dev, BTN_TOUCH, 0); - -+ alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); -+ -+ input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); -+ input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); -+ input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); -+ input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4); -+ -+ input_report_key(dev, BTN_LEFT, left); -+ input_report_key(dev, BTN_RIGHT, right); -+ input_report_key(dev, BTN_MIDDLE, middle); -+ - if (z > 0) { - input_report_abs(dev, ABS_X, x); - input_report_abs(dev, ABS_Y, y); - } - input_report_abs(dev, ABS_PRESSURE, z); - -- input_report_key(dev, BTN_TOOL_FINGER, z > 0); -- input_report_key(dev, BTN_LEFT, left); -- input_report_key(dev, BTN_RIGHT, right); -- input_report_key(dev, BTN_MIDDLE, middle); -- - input_sync(dev); - - if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { -@@ -1368,9 +1554,18 @@ int alps_init(struct psmouse *psmouse) - input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); - break; - case ALPS_PROTO_V3: -+ set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); -+ input_mt_init_slots(dev1, 2); -+ input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); -+ input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); -+ -+ set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); -+ set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); -+ set_bit(BTN_TOOL_QUADTAP, dev1->keybit); -+ /* fall through */ - case ALPS_PROTO_V4: -- input_set_abs_params(dev1, ABS_X, 0, 2000, 0, 0); -- input_set_abs_params(dev1, ABS_Y, 0, 1400, 0, 0); -+ input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); -+ input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); - break; - } - -diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h -index 62db7f4..a00a4ab 100644 ---- a/drivers/input/mouse/alps.h -+++ b/drivers/input/mouse/alps.h -@@ -38,6 +38,7 @@ struct alps_data { - int addr_command; /* Command to set register address */ - int prev_fin; /* Finger bit from previous packet */ - int multi_packet; /* Multi-packet data in progress */ -+ unsigned char multi_data[6]; /* Saved multi-packet data */ - u8 quirks; - struct timer_list timer; - }; --- -1.7.7.3 - - -From 7cf801cfc0774b777aa6861cf4a43a90b112b1ed Mon Sep 17 00:00:00 2001 -From: Seth Forshee -Date: Mon, 7 Nov 2011 19:54:35 -0800 -Subject: [PATCH 6/6] Input: ALPS - add documentation for protocol versions 3 - and 4 - -Also converts from using "old" and "new" to describe the already-known -protocols to using "version 1" and "version 2" to match the code. - -Signed-off-by: Seth Forshee -Acked-by: Chase Douglas -Signed-off-by: Dmitry Torokhov ---- - Documentation/input/alps.txt | 135 ++++++++++++++++++++++++++++++++++++++---- - 1 files changed, 124 insertions(+), 11 deletions(-) - -diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt -index ab5478f..f274c28 100644 ---- a/Documentation/input/alps.txt -+++ b/Documentation/input/alps.txt -@@ -4,12 +4,9 @@ ALPS Touchpad Protocol - Introduction - ------------ - --Currently the ALPS touchpad driver supports two protocol versions in use by --ALPS touchpads, the "old" and "new" protocol versions. Fundamentally these --differ only in the format of their event packets (in reality many features may --be found on new protocol devices that aren't found on the old protocol --devices, but these are handled transparently as feature differences rather --than protocol differences). -+Currently the ALPS touchpad driver supports four protocol versions in use by -+ALPS touchpads, called versions 1, 2, 3, and 4. Information about the various -+protocol versions is contained in the following sections. - - Detection - --------- -@@ -22,10 +19,37 @@ If the E6 report is successful, the touchpad model is identified using the "E7 - report" sequence: E8-E7-E7-E7-E9. The response is the model signature and is - matched against known models in the alps_model_data_array. - -+With protocol versions 3 and 4, the E7 report model signature is always -+73-02-64. To differentiate between these versions, the response from the -+"Enter Command Mode" sequence must be inspected as described below. -+ -+Command Mode -+------------ -+ -+Protocol versions 3 and 4 have a command mode that is used to read and write -+one-byte device registers in a 16-bit address space. The command sequence -+EC-EC-EC-E9 places the device in command mode, and the device will respond -+with 88-07 followed by a third byte. This third byte can be used to determine -+whether the devices uses the version 3 or 4 protocol. -+ -+To exit command mode, PSMOUSE_CMD_SETSTREAM (EA) is sent to the touchpad. -+ -+While in command mode, register addresses can be set by first sending a -+specific command, either EC for v3 devices or F5 for v4 devices. Then the -+address is sent one nibble at a time, where each nibble is encoded as a -+command with optional data. This enoding differs slightly between the v3 and -+v4 protocols. -+ -+Once an address has been set, the addressed register can be read by sending -+PSMOUSE_CMD_GETINFO (E9). The first two bytes of the response contains the -+address of the register being read, and the third contains the value of the -+register. Registers are written by writing the value one nibble at a time -+using the same encoding used for addresses. -+ - Packet Format - ------------- - --In the following tables, the following notation us used. -+In the following tables, the following notation is used. - - CAPITALS = stick, miniscules = touchpad - -@@ -41,8 +65,8 @@ PS/2 packet format - - Note that the device never signals overflow condition. - --ALPS Absolute Mode - Old Format --------------------------------- -+ALPS Absolute Mode - Protocol Verion 1 -+-------------------------------------- - - byte 0: 1 0 0 0 1 x9 x8 x7 - byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -@@ -51,8 +75,8 @@ ALPS Absolute Mode - Old Format - byte 4: 0 y6 y5 y4 y3 y2 y1 y0 - byte 5: 0 z6 z5 z4 z3 z2 z1 z0 - --ALPS Absolute Mode - New Format --------------------------------- -+ALPS Absolute Mode - Protocol Version 2 -+--------------------------------------- - - byte 0: 1 ? ? ? 1 ? ? ? - byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -@@ -73,3 +97,92 @@ Dualpoint device -- interleaved packet format - byte 6: 0 y9 y8 y7 1 m r l - byte 7: 0 y6 y5 y4 y3 y2 y1 y0 - byte 8: 0 z6 z5 z4 z3 z2 z1 z0 -+ -+ALPS Absolute Mode - Protocol Version 3 -+--------------------------------------- -+ -+ALPS protocol version 3 has three different packet formats. The first two are -+associated with touchpad events, and the third is associatd with trackstick -+events. -+ -+The first type is the touchpad position packet. -+ -+ byte 0: 1 ? x1 x0 1 1 1 1 -+ byte 1: 0 x10 x9 x8 x7 x6 x5 x4 -+ byte 2: 0 y10 y9 y8 y7 y6 y5 y4 -+ byte 3: 0 M R L 1 m r l -+ byte 4: 0 mt x3 x2 y3 y2 y1 y0 -+ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 -+ -+Note that for some devices the trackstick buttons are reported in this packet, -+and on others it is reported in the trackstick packets. -+ -+The second packet type contains bitmaps representing the x and y axes. In the -+bitmaps a given bit is set if there is a finger covering that position on the -+given axis. Thus the bitmap packet can be used for low-resolution multi-touch -+data, although finger tracking is not possible. This packet also encodes the -+number of contacts (f1 and f0 in the table below). -+ -+ byte 0: 1 1 x1 x0 1 1 1 1 -+ byte 1: 0 x8 x7 x6 x5 x4 x3 x2 -+ byte 2: 0 y7 y6 y5 y4 y3 y2 y1 -+ byte 3: 0 y10 y9 y8 1 1 1 1 -+ byte 4: 0 x14 x13 x12 x11 x10 x9 y0 -+ byte 5: 0 1 ? ? ? ? f1 f0 -+ -+This packet only appears after a position packet with the mt bit set, and -+ususally only appears when there are two or more contacts (although -+ocassionally it's seen with only a single contact). -+ -+The final v3 packet type is the trackstick packet. -+ -+ byte 0: 1 1 x7 y7 1 1 1 1 -+ byte 1: 0 x6 x5 x4 x3 x2 x1 x0 -+ byte 2: 0 y6 y5 y4 y3 y2 y1 y0 -+ byte 3: 0 1 0 0 1 0 0 0 -+ byte 4: 0 z4 z3 z2 z1 z0 ? ? -+ byte 5: 0 0 1 1 1 1 1 1 -+ -+ALPS Absolute Mode - Protocol Version 4 -+--------------------------------------- -+ -+Protocol version 4 has an 8-byte packet format. -+ -+ byte 0: 1 ? x1 x0 1 1 1 1 -+ byte 1: 0 x10 x9 x8 x7 x6 x5 x4 -+ byte 2: 0 y10 y9 y8 y7 y6 y5 y4 -+ byte 3: 0 1 x3 x2 y3 y2 y1 y0 -+ byte 4: 0 ? ? ? 1 ? r l -+ byte 5: 0 z6 z5 z4 z3 z2 z1 z0 -+ byte 6: bitmap data (described below) -+ byte 7: bitmap data (described below) -+ -+The last two bytes represent a partial bitmap packet, with 3 full packets -+required to construct a complete bitmap packet. Once assembled, the 6-byte -+bitmap packet has the following format: -+ -+ byte 0: 0 1 x7 x6 x5 x4 x3 x2 -+ byte 1: 0 x1 x0 y4 y3 y2 y1 y0 -+ byte 2: 0 0 ? x14 x13 x12 x11 x10 -+ byte 3: 0 x9 x8 y9 y8 y7 y6 y5 -+ byte 4: 0 0 0 0 0 0 0 0 -+ byte 5: 0 0 0 0 0 0 0 y10 -+ -+There are several things worth noting here. -+ -+ 1) In the bitmap data, bit 6 of byte 0 serves as a sync byte to -+ identify the first fragment of a bitmap packet. -+ -+ 2) The bitmaps represent the same data as in the v3 bitmap packets, although -+ the packet layout is different. -+ -+ 3) There doesn't seem to be a count of the contact points anywhere in the v4 -+ protocol packets. Deriving a count of contact points must be done by -+ analyzing the bitmaps. -+ -+ 4) There is a 3 to 1 ratio of position packets to bitmap packets. Therefore -+ MT position can only be updated for every third ST position update, and -+ the count of contact points can only be updated every third packet as -+ well. -+ -+So far no v4 devices with tracksticks have been encountered. --- -1.7.7.3 - diff --git a/config-arm-generic b/config-arm-generic index 558c7c4d0..2ad9ca63c 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -194,3 +194,15 @@ CONFIG_ARM_ERRATA_751472=y # CONFIG_MX3_IPU is not set # CONFIG_MX3_IPU_IRQS is not set +# CONFIG_OF_SELFTEST is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set + +# CONFIG_MACH_IMX51_DT is not set +# CONFIG_MACH_IMX53_DT is not set +# CONFIG_MACH_MX53_EVK is not set +# CONFIG_MACH_MX53_SMD is not set +# CONFIG_MACH_MX53_LOCO is not set +# CONFIG_MACH_MX53_ARD is not set +# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set diff --git a/config-arm-highbank b/config-arm-highbank index d4aca8222..8cd7fc3b5 100644 --- a/config-arm-highbank +++ b/config-arm-highbank @@ -14,3 +14,4 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m CONFIG_CPU_FREQ_TABLE=y CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_NET_CALXEDA_XGMAC=y diff --git a/config-arm-omap-generic b/config-arm-omap-generic index d623e1817..de17513e4 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -1083,3 +1083,14 @@ CONFIG_LEDS_RENESAS_TPU=y # CONFIG_OMAP_IOMMU is not set CONFIG_USB_RENESAS_USBHS_HCD=m +# CONFIG_SOC_OMAPTI81XX is not set +# CONFIG_SOC_OMAPAM33XX is not set +# CONFIG_MACH_TI8148EVM is not set +# CONFIG_OMAP4_ERRATA_I688 is not set +# CONFIG_ARM_LPAE is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_S5M_CORE is not set +# CONFIG_VIDEO_AS3645A is not set diff --git a/config-arm-tegra b/config-arm-tegra index 495e91e65..9658d4989 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -90,3 +90,12 @@ CONFIG_ARM_CPU_TOPOLOGY=y CONFIG_SCHED_MC=y CONFIG_SCHED_SMT=y CONFIG_LEDS_RENESAS_TPU=y + +# CONFIG_ARCH_TEGRA_2x_SOC is not set +# CONFIG_ARCH_TEGRA_3x_SOC is not set +# CONFIG_ETHERNET is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_DVB_TDA1004X is not set +# CONFIG_DVB_PLL is not set +# CONFIG_SND_SOC_TEGRA_ALC5632 is not set + diff --git a/config-generic b/config-generic index a6a821b23..b25c4dc46 100644 --- a/config-generic +++ b/config-generic @@ -152,6 +152,7 @@ CONFIG_INFINIBAND_IPOIB_DEBUG=y CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y CONFIG_INFINIBAND_IPOIB_CM=y CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_SRPT=m CONFIG_INFINIBAND_USER_MAD=m CONFIG_INFINIBAND_USER_ACCESS=m CONFIG_INFINIBAND_IPATH=m @@ -362,6 +363,7 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_NVME is not set CONFIG_BLK_DEV_OSD=m CONFIG_BLK_DEV_RAM=m CONFIG_BLK_DEV_RAM_COUNT=16 @@ -783,12 +785,14 @@ CONFIG_TCP_MD5SIG=y # CONFIG_PACKET=y CONFIG_UNIX=y +CONFIG_UNIX_DIAG=m CONFIG_NET_KEY=m CONFIG_NET_KEY_MIGRATE=y CONFIG_INET=y CONFIG_INET_LRO=y CONFIG_INET_TUNNEL=m CONFIG_INET_DIAG=m +CONFIG_INET_UDP_DIAG=m CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y CONFIG_IP_FIB_TRIE_STATS=y @@ -837,6 +841,13 @@ CONFIG_IP_VS_DH=m CONFIG_IP_VS_SH=m CONFIG_IP_VS_SED=m CONFIG_IP_VS_NQ=m + +# +# IPVS SH scheduler +# +# +CONFIG_IP_VS_SH_TAB_BITS=8 + CONFIG_IP_VS_FTP=m CONFIG_IP_VS_PE_SIP=m @@ -879,6 +890,7 @@ CONFIG_NETFILTER=y CONFIG_NETFILTER_ADVANCED=y CONFIG_NF_CONNTRACK=m CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_ACCT=m CONFIG_NETFILTER_NETLINK_QUEUE=m CONFIG_NETFILTER_NETLINK_LOG=m CONFIG_NETFILTER_TPROXY=m @@ -919,6 +931,7 @@ CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y CONFIG_NETFILTER_XT_MATCH_DCCP=m CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ECN=m CONFIG_NETFILTER_XT_MATCH_ESP=m CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m CONFIG_NETFILTER_XT_MATCH_HELPER=m @@ -930,6 +943,7 @@ CONFIG_NETFILTER_XT_MATCH_LIMIT=m CONFIG_NETFILTER_XT_MATCH_MAC=m CONFIG_NETFILTER_XT_MATCH_MARK=m CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m CONFIG_NETFILTER_XT_MATCH_OSF=m CONFIG_NETFILTER_XT_MATCH_OWNER=m CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m @@ -959,6 +973,7 @@ CONFIG_NF_CONNTRACK_MARK=y CONFIG_NF_CONNTRACK_SECMARK=y CONFIG_NF_CONNTRACK_EVENTS=y CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_PROCFS=y # CONFIG_NF_CONNTRACK_PROC_COMPAT is not set CONFIG_NF_CONNTRACK_AMANDA=m CONFIG_NF_CONNTRACK_FTP=m @@ -982,6 +997,7 @@ CONFIG_NF_CT_PROTO_UDPLITE=m CONFIG_IP_NF_MATCH_AH=m CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m CONFIG_IP_NF_MATCH_TTL=m CONFIG_IP_NF_TARGET_CLUSTERIP=m CONFIG_IP_NF_TARGET_MASQUERADE=m @@ -1014,6 +1030,7 @@ CONFIG_IP6_NF_MATCH_FRAG=m CONFIG_IP6_NF_MATCH_HL=m CONFIG_IP6_NF_MATCH_IPV6HEADER=m CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RPFILTER=m CONFIG_IP6_NF_MATCH_OPTS=m CONFIG_IP6_NF_MATCH_RT=m CONFIG_IP6_NF_QUEUE=m @@ -1175,6 +1192,8 @@ CONFIG_NET_ACT_SIMP=m CONFIG_NET_ACT_SKBEDIT=m CONFIG_DCB=y +CONFIG_OPENVSWITCH=m +CONFIG_NETPRIO_CGROUP=m # # Network testing @@ -1191,6 +1210,9 @@ CONFIG_NETDEVICES=y # # CONFIG_ARCNET is not set CONFIG_IFB=m +CONFIG_NET_TEAM=m +CONFIG_NET_TEAM_MODE_ROUNDROBIN=m +CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m CONFIG_DUMMY=m CONFIG_BONDING=m CONFIG_MACVLAN=m @@ -1280,6 +1302,7 @@ CONFIG_ATL1E=m CONFIG_NET_VENDOR_BROCADE=y CONFIG_BNA=m +CONFIG_NET_CALXEDA_XGMAC=m CONFIG_NET_VENDOR_CHELSIO=y CONFIG_CHELSIO_T1=m @@ -1417,6 +1440,8 @@ CONFIG_SMSC9420=m CONFIG_NET_VENDOR_STMICRO=y CONFIG_STMMAC_ETH=m +# CONFIG_STMMAC_PLATFORM is not set +# CONFIG_STMMAC_PCI is not set # CONFIG_STMMAC_DA is not set # CONFIG_STMMAC_DUAL_MAC is not set # CONFIG_STMMAC_TIMER is not set @@ -1566,6 +1591,7 @@ CONFIG_ATH9K_AHB=y # CONFIG_ATH9K_DEBUG is not set CONFIG_ATH9K_DEBUGFS=y CONFIG_ATH9K_HTC=m +CONFIG_ATH9K_BTCOEX_SUPPORT=y # CONFIG_ATH9K_HTC_DEBUGFS is not set CONFIG_ATH9K_RATE_CONTROL=y CONFIG_CARL9170=m @@ -1579,6 +1605,7 @@ CONFIG_B43=m CONFIG_B43_PCMCIA=y CONFIG_B43_SDIO=y CONFIG_B43_BCMA=y +# CONFIG_B43_BCMA_EXTRA is not set CONFIG_B43_BCMA_PIO=y # CONFIG_B43_DEBUG is not set CONFIG_B43_PHY_LP=y @@ -1594,6 +1621,7 @@ CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y # CONFIG_B43LEGACY_PIO_MODE is not set CONFIG_BRCMSMAC=m CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_SDIO=y # CONFIG_BRCMDBG is not set CONFIG_HERMES=m CONFIG_HERMES_CACHE_FW_ON_INIT=y @@ -1627,11 +1655,10 @@ CONFIG_IWLWIFI=m CONFIG_IWLWIFI_DEBUG=y CONFIG_IWLWIFI_DEBUGFS=y CONFIG_IWLWIFI_DEVICE_SVTOOL=y -# CONFIG_IWL_P2P is not set -CONFIG_IWLAGN=m -CONFIG_IWLWIFI_LEGACY=m -CONFIG_IWLWIFI_LEGACY_DEBUG=y -CONFIG_IWLWIFI_LEGACY_DEBUGFS=y +# CONFIG_IWLWIFI_P2P is not set +CONFIG_IWLEGACY=m +CONFIG_IWLEGACY_DEBUG=y +CONFIG_IWLEGACY_DEBUGFS=y # CONFIG_IWLWIFI_LEGACY_DEVICE_TRACING is not set CONFIG_IWL4965=y CONFIG_IWL3945=m @@ -2015,8 +2042,10 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_QT1070 is not set # CONFIG_KEYBOARD_MCS is not set # CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set # CONFIG_KEYBOARD_QT2160 is not set # CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y # CONFIG_MOUSE_PS2_TOUCHKIT is not set @@ -2065,6 +2094,7 @@ CONFIG_TOUCHSCREEN_AD7879_I2C=m # CONFIG_TOUCHSCREEN_CY8CTMG110 is not set CONFIG_TOUCHSCREEN_DYNAPRO=m CONFIG_TOUCHSCREEN_EETI=m +CONFIG_TOUCHSCREEN_EGALAX=m CONFIG_TOUCHSCREEN_ELO=m CONFIG_TOUCHSCREEN_FUJITSU=m CONFIG_TOUCHSCREEN_GUNZE=m @@ -2081,6 +2111,7 @@ CONFIG_TOUCHSCREEN_TSC2007=m CONFIG_TOUCHSCREEN_TOUCHIT213=m CONFIG_TOUCHSCREEN_TOUCHRIGHT=m CONFIG_TOUCHSCREEN_TOUCHWIN=m +CONFIG_TOUCHSCREEN_PIXCIR=m CONFIG_TOUCHSCREEN_UCB1400=m CONFIG_TOUCHSCREEN_WACOM_W8001=m CONFIG_TOUCHSCREEN_USB_E2I=y @@ -2568,6 +2599,7 @@ CONFIG_VIDEO_V4L2_SUBDEV_API=y # CONFIG_V4L_USB_DRIVERS=y CONFIG_VIDEO_CAPTURE_DRIVERS=y +CONFIG_V4L_PCI_DRIVERS=y CONFIG_VIDEO_AU0828=m CONFIG_VIDEO_BT848=m CONFIG_VIDEO_BT848_DVB=y @@ -2618,6 +2650,8 @@ CONFIG_VIDEO_ZORAN_DC30=m CONFIG_VIDEO_ZORAN_LML33=m CONFIG_VIDEO_ZORAN_LML33R10=m CONFIG_VIDEO_ZORAN_ZR36060=m +# CONFIG_V4L_ISA_PARPORT_DRIVERS is not set +# CONFIG_V4L_PLATFORM_DRIVERS is not set CONFIG_VIDEO_FB_IVTV=m CONFIG_VIDEO_SAA7164=m CONFIG_VIDEO_TM6000=m @@ -2645,6 +2679,7 @@ CONFIG_MEDIA_TUNER_TEA5761=m CONFIG_MEDIA_TUNER_TEA5767=m CONFIG_MEDIA_TUNER_MT20XX=m CONFIG_MEDIA_TUNER_MT2060=m +CONFIG_MEDIA_TUNER_MT2063=m CONFIG_MEDIA_TUNER_MT2266=m CONFIG_MEDIA_TUNER_MT2131=m CONFIG_MEDIA_TUNER_QT1010=m @@ -2768,6 +2803,7 @@ CONFIG_DVB_DDBRIDGE=m CONFIG_DVB_MB86A20S=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_DIB9000=m +CONFIG_DVB_HD29L2=m CONFIG_DVB_STV0367=m # @@ -2843,6 +2879,7 @@ CONFIG_IR_RC6_DECODER=m CONFIG_IR_JVC_DECODER=m CONFIG_IR_SONY_DECODER=m CONFIG_IR_RC5_SZ_DECODER=m +CONFIG_IR_SANYO_DECODER=m CONFIG_IR_MCE_KBD_DECODER=m CONFIG_IR_LIRC_CODEC=m CONFIG_IR_IMON=m @@ -3152,6 +3189,7 @@ CONFIG_USB_SUSPEND=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_EHCI_MV is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_HCD_SSB is not set CONFIG_USB_UHCI_HCD=y @@ -3236,6 +3274,7 @@ CONFIG_HID_PANTHERLORD=m CONFIG_HID_PETALYNX=m CONFIG_HID_PICOLCD=m CONFIG_HID_ROCCAT=m +CONFIG_HID_ROCCAT_ISKU=m CONFIG_HID_ROCCAT_KONE=m CONFIG_HID_SAMSUNG=m CONFIG_HID_SONY=m @@ -3262,6 +3301,7 @@ CONFIG_HID_HOLTEK=m CONFIG_HOLTEK_FF=y CONFIG_HID_SPEEDLINK=m CONFIG_HID_WIIMOTE=m +CONFIG_HID_WIIMOTE_EXT=y # # USB Imaging devices @@ -3313,6 +3353,7 @@ CONFIG_USB_GSPCA_PAC7302=m CONFIG_USB_GSPCA_STV0680=m CONFIG_USB_GL860=m CONFIG_USB_GSPCA_JEILINJ=m +CONFIG_USB_GSPCA_JL2005BCD=m CONFIG_USB_GSPCA_KONICA=m CONFIG_USB_GSPCA_XIRLINK_CIT=m CONFIG_USB_GSPCA_SPCA1528=m @@ -3703,6 +3744,7 @@ CONFIG_NFSD=m CONFIG_NFSD_V3=y CONFIG_NFSD_V3_ACL=y CONFIG_NFSD_V4=y +# CONFIG_NFSD_FAULT_INJECTION is not set CONFIG_NFS_FSCACHE=y # CONFIG_NFS_USE_LEGACY_DNS is not set # CONFIG_NFS_USE_NEW_IDMAPPER is not set @@ -3749,6 +3791,7 @@ CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m CONFIG_BTRFS_FS=m CONFIG_BTRFS_FS_POSIX_ACL=y +# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set CONFIG_CONFIGFS_FS=y @@ -3923,6 +3966,7 @@ CONFIG_SECURITY_SELINUX_AVC_STATS=y # CONFIG_SECURITY_APPARMOR is not set CONFIG_AUDIT=y CONFIG_AUDITSYSCALL=y +# CONFIG_AUDIT_LOGINUID_IMMUTABLE is not set # # Cryptographic options @@ -4061,6 +4105,7 @@ CONFIG_CGROUP_SCHED=y CONFIG_CGROUP_MEM_RES_CTLR=y CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y # XXX disabled by default, pass 'swapaccount' # CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED is not set +CONFIG_CGROUP_MEM_RES_CTLR_KMEM=y CONFIG_CGROUP_PERF=y CONFIG_BLK_CGROUP=y @@ -4232,6 +4277,8 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_BD2802 is not set # CONFIG_LEDS_S3C24XX is not set CONFIG_LEDS_DELL_NETBOOKS=m +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_OT200 is not set CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=m CONFIG_LEDS_TRIGGER_IDE_DISK=y @@ -4305,6 +4352,7 @@ CONFIG_APM_POWER=m # CONFIG_BATTERY_DS2760 is not set # CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set # CONFIG_BATTERY_BQ20Z75 is not set # CONFIG_BATTERY_DS2780 is not set # CONFIG_BATTERY_BQ27x00 is not set @@ -4313,6 +4361,7 @@ CONFIG_APM_POWER=m # CONFIG_CHARGER_ISP1704 is not set # CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set # CONFIG_CHARGER_GPIO is not set # CONFIG_CHARGER_PCF50633 is not set @@ -4415,6 +4464,8 @@ CONFIG_UWB_WHCI=m CONFIG_UWB_I1480U=m CONFIG_STAGING=y +# CONFIG_RTLLIB is not set +# CONFIG_ANDROID is not set CONFIG_STAGING_MEDIA=y # CONFIG_DVB_AS102 is not set # CONFIG_ET131X is not set diff --git a/config-powerpc-generic b/config-powerpc-generic index 2ca0c3e83..6b5498542 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -353,3 +353,10 @@ CONFIG_RFKILL_GPIO=m # Disable btrfs until it is shown to work with 64k pages (rhbz 747079) # CONFIG_BTRFS_FS is not set +# CONFIG_OF_SELFTEST is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_CPU_IDLE is not set +CONFIG_STRICT_DEVMEM=y +# CONFIG_V4L_RADIO_ISA_DRIVERS is not set diff --git a/config-powerpc64 b/config-powerpc64 index 548bf468a..30571917d 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -159,3 +159,7 @@ CONFIG_IO_EVENT_IRQ=y CONFIG_HW_RANDOM_AMD=m CONFIG_BPF_JIT=y + +# CONFIG_PPC_ICSWX_PID is not set +# CONFIG_PPC_ICSWX_USE_SIGILL is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set diff --git a/config-sparc64-generic b/config-sparc64-generic index e9b66f6d6..2b29f9b7e 100644 --- a/config-sparc64-generic +++ b/config-sparc64-generic @@ -195,3 +195,4 @@ CONFIG_CRYPTO_DEV_NIAGARA2=y # CONFIG_MTD_OF_PARTS is not set # CONFIG_MTD_PHYSMAP_OF is not set # CONFIG_MMC_SDHCI_OF is not set +# CONFIG_OF_SELFTEST is not set diff --git a/config-x86-32-generic b/config-x86-32-generic index 3b55ae521..3f4fc346f 100644 --- a/config-x86-32-generic +++ b/config-x86-32-generic @@ -203,3 +203,7 @@ CONFIG_I2O_BUS=m # CONFIG_EDAC_SBRIDGE is not set # CONFIG_X86_WANT_INTEL_MID is not set +# CONFIG_OF_SELFTEST is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set diff --git a/config-x86-generic b/config-x86-generic index fec30ea87..8654c4613 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -29,6 +29,7 @@ CONFIG_X86_PAT=y CONFIG_X86_PM_TIMER=y CONFIG_EFI=y +CONFIG_EFI_STUB=y CONFIG_EFI_VARS=y CONFIG_EFI_PCDP=y CONFIG_FB_EFI=y @@ -108,6 +109,7 @@ CONFIG_PM_STD_PARTITION="" CONFIG_PCI_MMCONFIG=y CONFIG_PCI_BIOS=y +CONFIG_PCI_IOAPIC=y CONFIG_HOTPLUG_PCI=y CONFIG_HOTPLUG_PCI_COMPAQ=m @@ -192,6 +194,9 @@ CONFIG_PANASONIC_LAPTOP=m CONFIG_SAMSUNG_LAPTOP=m CONFIG_SONY_LAPTOP=m CONFIG_TOPSTAR_LAPTOP=m +CONFIG_FUJITSU_TABLET=m +CONFIG_AMILO_RFKILL=m + CONFIG_ACPI_WMI=m CONFIG_ACER_WMI=m @@ -211,6 +216,7 @@ CONFIG_XO15_EBOOK=m # CONFIG_SMSC37B787_WDT is not set CONFIG_W83697HF_WDT=m +CONFIG_VIA_WDT=m CONFIG_CRASH_DUMP=y CONFIG_PROC_VMCORE=y @@ -360,7 +366,7 @@ CONFIG_INTEL_IPS=m # CONFIG_IBM_RTL is not set CONFIG_VIDEO_VIA_CAMERA=m - +# CONFIG_V4L_RADIO_ISA_DRIVERS is not set CONFIG_IRQ_TIME_ACCOUNTING=y CONFIG_X86_RESERVE_LOW=64 @@ -370,6 +376,7 @@ CONFIG_PCH_PHUB=m CONFIG_TRANSPARENT_HUGEPAGE=y CONFIG_CRYPTO_AES_NI_INTEL=y +CONFIG_CRYPTO_SERPENT_SSE2_586=m CONFIG_HP_ACCEL=m @@ -384,3 +391,12 @@ CONFIG_RELOCATABLE=y # CONFIG_HYPERV is not set +# Depends on HOTPLUG_PCI_PCIE +CONFIG_BLK_DEV_PCIESSD_MTIP32XX=m + +CONFIG_DRM_GMA500=m +# CONFIG_DRM_GMA600 is not set +# CONFIG_DRM_GMA3600 is not set + +# Maybe enable in debug kernels? +# CONFIG_DEBUG_NMI_SELFTEST is not set diff --git a/config-x86_64-generic b/config-x86_64-generic index f5b440a73..a334a3736 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -11,6 +11,8 @@ CONFIG_K8_NUMA=y CONFIG_AMD_NUMA=y CONFIG_X86_64_ACPI_NUMA=y # CONFIG_NUMA_EMU is not set +# CONFIG_X86_NUMACHIP is not set + CONFIG_NR_CPUS=256 CONFIG_PHYSICAL_START=0x1000000 @@ -20,6 +22,7 @@ CONFIG_IA32_EMULATION=y CONFIG_AMD_IOMMU=y CONFIG_AMD_IOMMU_STATS=y +CONFIG_AMD_IOMMU_V2=m # CONFIG_IOMMU_DEBUG is not set CONFIG_SWIOTLB=y # CONFIG_CALGARY_IOMMU is not set @@ -40,6 +43,7 @@ CONFIG_PNP=y CONFIG_BLK_DEV_AMD74XX=y CONFIG_CRYPTO_AES_X86_64=y +CONFIG_CRYPTO_SERPENT_SSE2_X86_64=m CONFIG_CRYPTO_TWOFISH_X86_64=m CONFIG_CRYPTO_SALSA20_X86_64=m CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m diff --git a/e1000e-Avoid-wrong-check-on-TX-hang.patch b/e1000e-Avoid-wrong-check-on-TX-hang.patch deleted file mode 100644 index 6064ddde8..000000000 --- a/e1000e-Avoid-wrong-check-on-TX-hang.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 09357b00255c233705b1cf6d76a8d147340545b8 Mon Sep 17 00:00:00 2001 -From: Jeff Kirsher -Date: Fri, 18 Nov 2011 14:25:00 +0000 -Subject: [PATCH] e1000e: Avoid wrong check on TX hang - -Based on the original patch submitted my Michael Wang -. -Descriptors may not be write-back while checking TX hang with flag -FLAG2_DMA_BURST on. -So when we detect hang, we just flush the descriptor and detect -again for once. - --v2 change 1 to true and 0 to false and remove extra () - -CC: Michael Wang -CC: Flavio Leitner -Acked-by: Jesse Brandeburg -Tested-by: Aaron Brown -Signed-off-by: Jeff Kirsher ---- - drivers/net/ethernet/intel/e1000e/e1000.h | 1 + - drivers/net/ethernet/intel/e1000e/netdev.c | 23 ++++++++++++++++++++--- - 2 files changed, 21 insertions(+), 3 deletions(-) - -diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h -index 9fe18d1..f478a22 100644 ---- a/drivers/net/ethernet/intel/e1000e/e1000.h -+++ b/drivers/net/ethernet/intel/e1000e/e1000.h -@@ -309,6 +309,7 @@ struct e1000_adapter { - u32 txd_cmd; - - bool detect_tx_hung; -+ bool tx_hang_recheck; - u8 tx_timeout_factor; - - u32 tx_int_delay; -diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c -index c6e9763..c12df69 100644 ---- a/drivers/net/ethernet/intel/e1000e/netdev.c -+++ b/drivers/net/ethernet/intel/e1000e/netdev.c -@@ -1014,6 +1014,7 @@ static void e1000_print_hw_hang(struct work_struct *work) - struct e1000_adapter *adapter = container_of(work, - struct e1000_adapter, - print_hang_task); -+ struct net_device *netdev = adapter->netdev; - struct e1000_ring *tx_ring = adapter->tx_ring; - unsigned int i = tx_ring->next_to_clean; - unsigned int eop = tx_ring->buffer_info[i].next_to_watch; -@@ -1025,6 +1026,21 @@ static void e1000_print_hw_hang(struct work_struct *work) - if (test_bit(__E1000_DOWN, &adapter->state)) - return; - -+ if (!adapter->tx_hang_recheck && -+ (adapter->flags2 & FLAG2_DMA_BURST)) { -+ /* May be block on write-back, flush and detect again -+ * flush pending descriptor writebacks to memory -+ */ -+ ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); -+ /* execute the writes immediately */ -+ e1e_flush(); -+ adapter->tx_hang_recheck = true; -+ return; -+ } -+ /* Real hang detected */ -+ adapter->tx_hang_recheck = false; -+ netif_stop_queue(netdev); -+ - e1e_rphy(hw, PHY_STATUS, &phy_status); - e1e_rphy(hw, PHY_1000T_STATUS, &phy_1000t_status); - e1e_rphy(hw, PHY_EXT_STATUS, &phy_ext_status); -@@ -1145,10 +1161,10 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) - if (tx_ring->buffer_info[i].time_stamp && - time_after(jiffies, tx_ring->buffer_info[i].time_stamp - + (adapter->tx_timeout_factor * HZ)) && -- !(er32(STATUS) & E1000_STATUS_TXOFF)) { -+ !(er32(STATUS) & E1000_STATUS_TXOFF)) - schedule_work(&adapter->print_hang_task); -- netif_stop_queue(netdev); -- } -+ else -+ adapter->tx_hang_recheck = false; - } - adapter->total_tx_bytes += total_tx_bytes; - adapter->total_tx_packets += total_tx_packets; -@@ -3838,6 +3854,7 @@ static int e1000_open(struct net_device *netdev) - - e1000_irq_enable(adapter); - -+ adapter->tx_hang_recheck = false; - netif_start_queue(netdev); - - adapter->idle_check = true; --- -1.7.9 - diff --git a/ext4-Fix-error-handling-on-inode-bitmap-corruption.patch b/ext4-Fix-error-handling-on-inode-bitmap-corruption.patch deleted file mode 100644 index e22a2b4ff..000000000 --- a/ext4-Fix-error-handling-on-inode-bitmap-corruption.patch +++ /dev/null @@ -1,19 +0,0 @@ -diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c -index 00beb4f..8fb6844 100644 ---- a/fs/ext4/ialloc.c -+++ b/fs/ext4/ialloc.c -@@ -885,8 +885,12 @@ got: - if (IS_DIRSYNC(inode)) - ext4_handle_sync(handle); - if (insert_inode_locked(inode) < 0) { -- err = -EINVAL; -- goto fail_drop; -+ /* -+ * Likely a bitmap corruption causing inode to be allocated -+ * twice. -+ */ -+ err = -EIO; -+ goto fail; - } - spin_lock(&sbi->s_next_gen_lock); - inode->i_generation = sbi->s_next_generation++; diff --git a/hibernate-freeze-filesystems.patch b/hibernate-freeze-filesystems.patch index dfb2f0478..841cab643 100644 --- a/hibernate-freeze-filesystems.patch +++ b/hibernate-freeze-filesystems.patch @@ -1,59 +1,35 @@ -From: Rafael J. Wysocki +commit b94887bbc0621e1e8402e7f0ec4bc3adf46c9a6e +Author: Rafael J. Wysocki +Date: Fri Feb 17 12:42:08 2012 -0500 -Freeze all filesystems during system suspend and (kernel-driven) -hibernation by calling freeze_supers() for all superblocks and thaw -them during the subsequent resume with the help of thaw_supers(). + Freeze all filesystems during system suspend and (kernel-driven) + hibernation by calling freeze_supers() for all superblocks and thaw + them during the subsequent resume with the help of thaw_supers(). + + This makes filesystems stay in a consistent state in case something + goes wrong between system suspend (or hibernation) and the subsequent + resume (e.g. journal replays won't be necessary in those cases). In + particular, this should help to solve a long-standing issue that, in + some cases, during resume from hibernation the boot loader causes the + journal to be replied for the filesystem containing the kernel image + and/or initrd causing it to become inconsistent with the information + stored in the hibernation image. + + The user-space-driven hibernation (s2disk) is not covered by this + change, because the freezing of filesystems prevents s2disk from + accessing device special files it needs to do its job. + + This change is based on earlier work by Nigel Cunningham. + + Signed-off-by: Rafael J. Wysocki + + Rebased to 3.3-rc3 by Josh Boyer -This makes filesystems stay in a consistent state in case something -goes wrong between system suspend (or hibernation) and the subsequent -resume (e.g. journal replays won't be necessary in those cases). In -particular, this should help to solve a long-standing issue that, in -some cases, during resume from hibernation the boot loader causes the -journal to be replied for the filesystem containing the kernel image -and/or initrd causing it to become inconsistent with the information -stored in the hibernation image. - -The user-space-driven hibernation (s2disk) is not covered by this -change, because the freezing of filesystems prevents s2disk from -accessing device special files it needs to do its job. - -This change is based on earlier work by Nigel Cunningham. - -Signed-off-by: Rafael J. Wysocki ---- - fs/super.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++ - include/linux/fs.h | 3 + - kernel/power/hibernate.c | 11 +++++-- - kernel/power/power.h | 23 -------------- - kernel/power/suspend.c | 42 +++++++++++++++++++++++++++ - 5 files changed, 128 insertions(+), 24 deletions(-) - -Index: linux/include/linux/fs.h -=================================================================== ---- linux.orig/include/linux/fs.h -+++ linux/include/linux/fs.h -@@ -210,6 +210,7 @@ struct inodes_stat_t { - #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */ - #define MS_I_VERSION (1<<23) /* Update inode I_version field */ - #define MS_STRICTATIME (1<<24) /* Always perform atime updates */ -+#define MS_FROZEN (1<<25) /* Frozen filesystem */ - #define MS_NOSEC (1<<28) - #define MS_BORN (1<<29) - #define MS_ACTIVE (1<<30) -@@ -2501,6 +2502,8 @@ extern void drop_super(struct super_bloc - extern void iterate_supers(void (*)(struct super_block *, void *), void *); - extern void iterate_supers_type(struct file_system_type *, - void (*)(struct super_block *, void *), void *); -+extern int freeze_supers(void); -+extern void thaw_supers(void); - - extern int dcache_dir_open(struct inode *, struct file *); - extern int dcache_dir_close(struct inode *, struct file *); -Index: linux/fs/super.c -=================================================================== ---- linux.orig/fs/super.c -+++ linux/fs/super.c -@@ -594,6 +594,79 @@ void iterate_supers_type(struct file_sys +diff --git a/fs/super.c b/fs/super.c +index 6015c02..c8057fa 100644 +--- a/fs/super.c ++++ b/fs/super.c +@@ -594,6 +594,79 @@ void iterate_supers_type(struct file_system_type *type, EXPORT_SYMBOL(iterate_supers_type); /** @@ -65,7 +41,7 @@ Index: linux/fs/super.c + + spin_lock(&sb_lock); + list_for_each_entry(sb, &super_blocks, s_list) { -+ if (list_empty(&sb->s_instances)) ++ if (hlist_unhashed(&sb->s_instances)) + continue; + sb->s_count++; + spin_unlock(&sb_lock); @@ -99,7 +75,7 @@ Index: linux/fs/super.c + * frozen in the right order (eg. loopback on ext3). + */ + list_for_each_entry_reverse(sb, &super_blocks, s_list) { -+ if (list_empty(&sb->s_instances)) ++ if (hlist_unhashed(&sb->s_instances)) + continue; + sb->s_count++; + spin_unlock(&sb_lock); @@ -133,98 +109,31 @@ Index: linux/fs/super.c * get_super - get the superblock of a device * @bdev: device to get the superblock for * -Index: linux/kernel/power/power.h -=================================================================== ---- linux.orig/kernel/power/power.h -+++ linux/kernel/power/power.h -@@ -1,3 +1,4 @@ -+#include - #include - #include - #include -@@ -227,25 +228,3 @@ enum { - #define TEST_MAX (__TEST_AFTER_LAST - 1) +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 386da09..a164f4a 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -210,6 +210,7 @@ struct inodes_stat_t { + #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */ + #define MS_I_VERSION (1<<23) /* Update inode I_version field */ + #define MS_STRICTATIME (1<<24) /* Always perform atime updates */ ++#define MS_FROZEN (1<<25) /* Frozen filesystem */ + #define MS_NOSEC (1<<28) + #define MS_BORN (1<<29) + #define MS_ACTIVE (1<<30) +@@ -2501,6 +2502,8 @@ extern void drop_super(struct super_block *sb); + extern void iterate_supers(void (*)(struct super_block *, void *), void *); + extern void iterate_supers_type(struct file_system_type *, + void (*)(struct super_block *, void *), void *); ++extern int freeze_supers(void); ++extern void thaw_supers(void); - extern int pm_test_level; -- --#ifdef CONFIG_SUSPEND_FREEZER --static inline int suspend_freeze_processes(void) --{ -- int error = freeze_processes(); -- return error ? : freeze_kernel_threads(); --} -- --static inline void suspend_thaw_processes(void) --{ -- thaw_processes(); --} --#else --static inline int suspend_freeze_processes(void) --{ -- return 0; --} -- --static inline void suspend_thaw_processes(void) --{ --} --#endif -Index: linux/kernel/power/suspend.c -=================================================================== ---- linux.orig/kernel/power/suspend.c -+++ linux/kernel/power/suspend.c -@@ -29,6 +29,48 @@ - - #include "power.h" - -+#ifdef CONFIG_SUSPEND_FREEZER -+ -+static inline int suspend_freeze_processes(void) -+{ -+ int error; -+ -+ error = freeze_processes(); -+ if (error) -+ return error; -+ -+ error = freeze_supers(); -+ if (error) { -+ thaw_processes(); -+ return error; -+ } -+ -+ error = freeze_kernel_threads(); -+ if (error) -+ thaw_supers(); -+ -+ return error; -+} -+ -+static inline void suspend_thaw_processes(void) -+{ -+ thaw_supers(); -+ thaw_processes(); -+} -+ -+#else /* !CONFIG_SUSPEND_FREEZER */ -+ -+static inline int suspend_freeze_processes(void) -+{ -+ return 0; -+} -+ -+static inline void suspend_thaw_processes(void) -+{ -+} -+ -+#endif /* !CONFIG_SUSPEND_FREEZER */ -+ - const char *const pm_states[PM_SUSPEND_MAX] = { - [PM_SUSPEND_STANDBY] = "standby", - [PM_SUSPEND_MEM] = "mem", -Index: linux/kernel/power/hibernate.c -=================================================================== ---- linux.orig/kernel/power/hibernate.c -+++ linux/kernel/power/hibernate.c + extern int dcache_dir_open(struct inode *, struct file *); + extern int dcache_dir_close(struct inode *, struct file *); +diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c +index 6d6d288..492fc62 100644 +--- a/kernel/power/hibernate.c ++++ b/kernel/power/hibernate.c @@ -626,12 +626,17 @@ int hibernate(void) if (error) goto Finish; @@ -254,4 +163,125 @@ Index: linux/kernel/power/hibernate.c Thaw: thaw_processes(); Finish: - +diff --git a/kernel/power/power.h b/kernel/power/power.h +index 21724ee..40d6f64 100644 +--- a/kernel/power/power.h ++++ b/kernel/power/power.h +@@ -1,3 +1,4 @@ ++#include + #include + #include + #include +@@ -227,45 +228,3 @@ enum { + #define TEST_MAX (__TEST_AFTER_LAST - 1) + + extern int pm_test_level; +- +-#ifdef CONFIG_SUSPEND_FREEZER +-static inline int suspend_freeze_processes(void) +-{ +- int error; +- +- error = freeze_processes(); +- +- /* +- * freeze_processes() automatically thaws every task if freezing +- * fails. So we need not do anything extra upon error. +- */ +- if (error) +- goto Finish; +- +- error = freeze_kernel_threads(); +- +- /* +- * freeze_kernel_threads() thaws only kernel threads upon freezing +- * failure. So we have to thaw the userspace tasks ourselves. +- */ +- if (error) +- thaw_processes(); +- +- Finish: +- return error; +-} +- +-static inline void suspend_thaw_processes(void) +-{ +- thaw_processes(); +-} +-#else +-static inline int suspend_freeze_processes(void) +-{ +- return 0; +-} +- +-static inline void suspend_thaw_processes(void) +-{ +-} +-#endif +diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c +index 4fd51be..5f51fc7 100644 +--- a/kernel/power/suspend.c ++++ b/kernel/power/suspend.c +@@ -29,6 +29,62 @@ + + #include "power.h" + ++#ifdef CONFIG_SUSPEND_FREEZER ++ ++static inline int suspend_freeze_processes(void) ++{ ++ int error; ++ ++ error = freeze_processes(); ++ ++ /* ++ * freeze_processes() automatically thaws every task if freezing ++ * fails. So we need not do anything extra upon error. ++ */ ++ ++ if (error) ++ goto Finish; ++ ++ error = freeze_supers(); ++ if (error) { ++ thaw_processes(); ++ goto Finish; ++ } ++ ++ error = freeze_kernel_threads(); ++ ++ /* ++ * freeze_kernel_threads() thaws only kernel threads upon freezing ++ * failure. So we have to thaw the userspace tasks ourselves. ++ */ ++ if (error) { ++ thaw_supers(); ++ thaw_processes(); ++ } ++ ++Finish: ++ return error; ++} ++ ++static inline void suspend_thaw_processes(void) ++{ ++ thaw_supers(); ++ thaw_processes(); ++} ++ ++#else /* !CONFIG_SUSPEND_FREEZER */ ++ ++static inline int suspend_freeze_processes(void) ++{ ++ return 0; ++} ++ ++static inline void suspend_thaw_processes(void) ++{ ++} ++ ++#endif /* !CONFIG_SUSPEND_FREEZER */ ++ + const char *const pm_states[PM_SUSPEND_MAX] = { + [PM_SUSPEND_STANDBY] = "standby", + [PM_SUSPEND_MEM] = "mem", diff --git a/hpsa-add-irqf-shared.patch b/hpsa-add-irqf-shared.patch deleted file mode 100644 index d29e2353e..000000000 --- a/hpsa-add-irqf-shared.patch +++ /dev/null @@ -1,34 +0,0 @@ -hpsa: Add IRQF_SHARED back in for the non-MSI(X) interrupt handler - -From: Stephen M. Cameron - -IRQF_SHARED is required for older controllers that don't support MSI(X) -and which may end up sharing an interrupt. All the controllers hpsa -normally supports have MSI(X) capability, but older controllers may be -encountered via the hpsa_allow_any=1 module parameter. - -Also remove deprecated IRQF_DISABLED. - -Signed-off-by: Stephen M. Cameron ---- - drivers/scsi/hpsa.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -RHBZ 754907 -diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c -index 865d452..594ce83 100644 ---- a/drivers/scsi/hpsa.c -+++ b/drivers/scsi/hpsa.c -@@ -4072,10 +4072,10 @@ static int hpsa_request_irq(struct ctlr_info *h, - - if (h->msix_vector || h->msi_vector) - rc = request_irq(h->intr[h->intr_mode], msixhandler, -- IRQF_DISABLED, h->devname, h); -+ 0, h->devname, h); - else - rc = request_irq(h->intr[h->intr_mode], intxhandler, -- IRQF_DISABLED, h->devname, h); -+ IRQF_SHARED, h->devname, h); - if (rc) { - dev_err(&h->pdev->dev, "unable to get irq %d for %s\n", - h->intr[h->intr_mode], h->devname); diff --git a/kernel.spec b/kernel.spec index e4b43f71f..7cc92177d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,19 +54,19 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 5 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching # on top of -- for example, 2.6.22-rc7-git1 starts with a 2.6.21 base, # which yields a base_sublevel of 21. -%define base_sublevel 2 +%define base_sublevel 3 ## If this is a released kernel ## %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 10 +%define stable_update 0 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -725,7 +725,6 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch -Patch13002: revert-efi-rtclock.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch Patch14000: hibernate-freeze-filesystems.patch @@ -738,39 +737,11 @@ Patch20000: utrace.patch Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch -#rhbz 717735 -Patch21045: nfs-client-freezer.patch - -#rhbz 590880 -Patch21050: alps.patch - Patch21070: ext4-Support-check-none-nocheck-mount-options.patch -Patch21071: ext4-Fix-error-handling-on-inode-bitmap-corruption.patch #rhbz 769766 Patch21072: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch -#rhbz 773392 -Patch21073: KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch -Patch21074: KVM-x86-fix-missing-checks-in-syscall-emulation.patch - -#rhbz 728740 -Patch21076: rtl8192cu-Fix-WARNING-on-suspend-resume.patch - -#rhbz752176 -Patch21080: sysfs-msi-irq-per-device.patch - -#rhbz 782686 -Patch21082: procfs-parse-mount-options.patch -Patch21083: procfs-add-hidepid-and-gid-mount-options.patch -Patch21084: proc-fix-null-pointer-deref-in-proc_pid_permission.patch - -#rhbz 771058 -Patch22100: msi-irq-sysfs-warning.patch - -# rhbz 754907 -Patch21101: hpsa-add-irqf-shared.patch - Patch21226: pci-crs-blacklist.patch #rhbz 772772 @@ -779,12 +750,8 @@ Patch21232: rt2x00_fix_MCU_request_failures.patch #rhbz 788260 Patch21233: jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch -#rhbz 785806 -Patch21234: e1000e-Avoid-wrong-check-on-TX-hang.patch - #rhbz 754518 #Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch -Patch21235: scsi-fix-sd_revalidate_disk-oops.patch #rhbz 727865 730007 Patch21240: ACPICA-Fix-regression-in-FADT-revision-checks.patch @@ -1302,7 +1269,7 @@ ApplyOptionalPatch linux-2.6-upstream-reverts.patch -R # # ARM # -ApplyPatch arm-omap-dt-compat.patch +# ApplyPatch arm-omap-dt-compat.patch ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch ApplyPatch taint-vbox.patch @@ -1418,7 +1385,6 @@ ApplyPatch disable-i8042-check-on-apple-mac.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch -ApplyPatch revert-efi-rtclock.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch ApplyPatch hibernate-freeze-filesystems.patch @@ -1428,51 +1394,18 @@ ApplyPatch lis3-improve-handling-of-null-rate.patch # utrace. ApplyPatch utrace.patch -#rhbz 752176 -ApplyPatch sysfs-msi-irq-per-device.patch - -# rhbz 754907 -ApplyPatch hpsa-add-irqf-shared.patch - #ApplyPatch pci-crs-blacklist.patch -#rhbz 717735 -ApplyPatch nfs-client-freezer.patch - -#rhbz 590880 -ApplyPatch alps.patch - -#rhbz 771058 -ApplyPatch msi-irq-sysfs-warning.patch - ApplyPatch ext4-Support-check-none-nocheck-mount-options.patch -ApplyPatch ext4-Fix-error-handling-on-inode-bitmap-corruption.patch - -#rhbz 773392 -ApplyPatch KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch -ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch - -#rhbz 728740 -ApplyPatch rtl8192cu-Fix-WARNING-on-suspend-resume.patch - -#rhbz 782686 -ApplyPatch procfs-parse-mount-options.patch -ApplyPatch procfs-add-hidepid-and-gid-mount-options.patch -ApplyPatch proc-fix-null-pointer-deref-in-proc_pid_permission.patch - #rhbz 772772 ApplyPatch rt2x00_fix_MCU_request_failures.patch #rhbz 788269 ApplyPatch jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch -#rhbz 785806 -ApplyPatch e1000e-Avoid-wrong-check-on-TX-hang.patch - #rhbz 754518 #ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch -ApplyPatch scsi-fix-sd_revalidate_disk-oops.patch #rhbz 727865 730007 ApplyPatch ACPICA-Fix-regression-in-FADT-revision-checks.patch @@ -2222,6 +2155,7 @@ fi %changelog * Mon Mar 19 2012 Josh Boyer +- Linux 3.3 - Drop compat-wireless infrastructure in preparation for 3.3 rebase * Fri Mar 16 2012 Justin M. Forbes diff --git a/linux-2.6-defaults-acpi-video.patch b/linux-2.6-defaults-acpi-video.patch index af883b0d3..b83f4b614 100644 --- a/linux-2.6-defaults-acpi-video.patch +++ b/linux-2.6-defaults-acpi-video.patch @@ -1,13 +1,13 @@ diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c -index d8d7596..a1b7117 100644 +index eaef02a..2029819 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c -@@ -71,7 +71,7 @@ MODULE_AUTHOR("Bruno Ducrot"); +@@ -69,7 +69,7 @@ MODULE_AUTHOR("Bruno Ducrot"); MODULE_DESCRIPTION("ACPI Video Driver"); MODULE_LICENSE("GPL"); --static int brightness_switch_enabled = 1; -+static int brightness_switch_enabled = 0; +-static bool brightness_switch_enabled = 1; ++static bool brightness_switch_enabled = 0; module_param(brightness_switch_enabled, bool, 0644); - static int acpi_video_bus_add(struct acpi_device *device); + /* diff --git a/linux-2.6-serial-460800.patch b/linux-2.6-serial-460800.patch index 9aa392c9e..979b248d5 100644 --- a/linux-2.6-serial-460800.patch +++ b/linux-2.6-serial-460800.patch @@ -1,7 +1,7 @@ diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 2209620..659c1bb 100644 ---- a/drivers/tty/serial/8250.c -+++ b/drivers/tty/serial/8250.c +--- a/drivers/tty/serial/8250/8250.c ++++ b/drivers/tty/serial/8250/8250.c @@ -7,6 +7,9 @@ * * Copyright (C) 2001 Russell King. diff --git a/mm-thp-fix-pmd_bad-triggering.patch b/mm-thp-fix-pmd_bad-triggering.patch index 3af9d2e2d..8e1a77cd7 100644 --- a/mm-thp-fix-pmd_bad-triggering.patch +++ b/mm-thp-fix-pmd_bad-triggering.patch @@ -363,7 +363,7 @@ index fa2f04e..e3090fc 100644 @@ -1251,12 +1251,20 @@ static inline unsigned long zap_pmd_range(struct mmu_gather *tlb, VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem)); split_huge_page_pmd(vma->vm_mm, pmd); - } else if (zap_huge_pmd(tlb, vma, pmd)) + } else if (zap_huge_pmd(tlb, vma, pmd, addr)) - continue; + goto next; /* fall through */ @@ -444,4 +444,4 @@ To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ -Don't email: email@kvack.org +Don't email: email@kvack.org \ No newline at end of file diff --git a/msi-irq-sysfs-warning.patch b/msi-irq-sysfs-warning.patch deleted file mode 100644 index dce440e4a..000000000 --- a/msi-irq-sysfs-warning.patch +++ /dev/null @@ -1,87 +0,0 @@ -commit 3ff0e97a1bc3059bfbcc1d864c5d4ff5f8d3c2b9 -Author: Neil Horman -Date: Tue Jan 3 10:17:21 2012 -0500 - - msi: fix imbalanced refcount of msi irq sysfs objects - - This warning was recently reported to me: - - ------------[ cut here ]------------ - WARNING: at lib/kobject.c:595 kobject_put+0x50/0x60() - Hardware name: VMware Virtual Platform - kobject: '(null)' (ffff880027b0df40): is not initialized, yet kobject_put() is - being called. - Modules linked in: vmxnet3(+) vmw_balloon i2c_piix4 i2c_core shpchp raid10 - vmw_pvscsi - Pid: 630, comm: modprobe Tainted: G W 3.1.6-1.fc16.x86_64 #1 - Call Trace: - [] warn_slowpath_common+0x7f/0xc0 - [] warn_slowpath_fmt+0x46/0x50 - [] ? free_desc+0x63/0x70 - [] kobject_put+0x50/0x60 - [] free_msi_irqs+0xd5/0x120 - [] pci_enable_msi_block+0x24c/0x2c0 - [] vmxnet3_alloc_intr_resources+0x173/0x240 [vmxnet3] - [] vmxnet3_probe_device+0x615/0x834 [vmxnet3] - [] local_pci_probe+0x5c/0xd0 - [] pci_device_probe+0x109/0x130 - [] driver_probe_device+0x9c/0x2b0 - [] __driver_attach+0xab/0xb0 - [] ? driver_probe_device+0x2b0/0x2b0 - [] ? driver_probe_device+0x2b0/0x2b0 - [] bus_for_each_dev+0x5c/0x90 - [] driver_attach+0x1e/0x20 - [] bus_add_driver+0x1b0/0x2a0 - [] ? 0xffffffffa0187fff - [] driver_register+0x76/0x140 - [] ? printk+0x51/0x53 - [] ? 0xffffffffa0187fff - [] __pci_register_driver+0x56/0xd0 - [] vmxnet3_init_module+0x3a/0x3c [vmxnet3] - [] do_one_initcall+0x42/0x180 - [] sys_init_module+0x91/0x200 - [] system_call_fastpath+0x16/0x1b - ---[ end trace 44593438a59a9558 ]--- - Using INTx interrupt, #Rx queues: 1. - - It occurs when populate_msi_sysfs fails, which in turn causes free_msi_irqs to - be called. Because populate_msi_sysfs fails, we never registered any of the - msi irq sysfs objects, but free_msi_irqs still calls kobject_del and kobject_put - on each of them, which gets flagged in the above stack trace. - - The fix is pretty straightforward. We can key of the parent pointer in the - kobject. It is only set if the kobject_init_and_add succededs in - populate_msi_sysfs. If anything fails there, each kobject has its parent reset - to NULL - - Signed-off-by: Neil Horman - CC: Jesse Barnes - CC: Bjorn Helgaas - CC: Greg Kroah-Hartman - CC: linux-pci@vger.kernel.org - -diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c -index 337e16a..82de95e 100644 ---- a/drivers/pci/msi.c -+++ b/drivers/pci/msi.c -@@ -323,8 +323,18 @@ static void free_msi_irqs(struct pci_dev *dev) - if (list_is_last(&entry->list, &dev->msi_list)) - iounmap(entry->mask_base); - } -- kobject_del(&entry->kobj); -- kobject_put(&entry->kobj); -+ -+ /* -+ * Its possible that we get into this path -+ * When populate_msi_sysfs fails, which means the entries -+ * were not registered with sysfs. In that case don't -+ * unregister them. -+ */ -+ if (entry->kobj.parent) { -+ kobject_del(&entry->kobj); -+ kobject_put(&entry->kobj); -+ } -+ - list_del(&entry->list); - kfree(entry); - } diff --git a/nfs-client-freezer.patch b/nfs-client-freezer.patch deleted file mode 100644 index 5f5b0836e..000000000 --- a/nfs-client-freezer.patch +++ /dev/null @@ -1,197 +0,0 @@ -@@ -, +, @@ - fs/nfs/inode.c | 3 ++- - fs/nfs/nfs3proc.c | 3 ++- - fs/nfs/nfs4proc.c | 5 +++-- - fs/nfs/proc.c | 3 ++- - include/linux/freezer.h | 28 ++++++++++++++++++++++++++++ - net/sunrpc/sched.c | 3 ++- - 6 files changed, 39 insertions(+), 6 deletions(-) ---- a/fs/nfs/inode.c -+++ a/fs/nfs/inode.c -@@ -38,6 +38,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -77,7 +78,7 @@ int nfs_wait_bit_killable(void *word) - { - if (fatal_signal_pending(current)) - return -ERESTARTSYS; -- schedule(); -+ freezable_schedule(); - return 0; - } - ---- a/fs/nfs/nfs3proc.c -+++ a/fs/nfs/nfs3proc.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - #include "iostat.h" - #include "internal.h" -@@ -32,7 +33,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) - res = rpc_call_sync(clnt, msg, flags); - if (res != -EJUKEBOX && res != -EKEYEXPIRED) - break; -- schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); -+ freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); - res = -ERESTARTSYS; - } while (!fatal_signal_pending(current)); - return res; ---- a/fs/nfs/nfs4proc.c -+++ a/fs/nfs/nfs4proc.c -@@ -53,6 +53,7 @@ - #include - #include - #include -+#include - - #include "nfs4_fs.h" - #include "delegation.h" -@@ -241,7 +242,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) - *timeout = NFS4_POLL_RETRY_MIN; - if (*timeout > NFS4_POLL_RETRY_MAX) - *timeout = NFS4_POLL_RETRY_MAX; -- schedule_timeout_killable(*timeout); -+ freezable_schedule_timeout_killable(*timeout); - if (fatal_signal_pending(current)) - res = -ERESTARTSYS; - *timeout <<= 1; -@@ -3950,7 +3951,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 - static unsigned long - nfs4_set_lock_task_retry(unsigned long timeout) - { -- schedule_timeout_killable(timeout); -+ freezable_schedule_timeout_killable(timeout); - timeout <<= 1; - if (timeout > NFS4_LOCK_MAXTIMEOUT) - return NFS4_LOCK_MAXTIMEOUT; ---- a/fs/nfs/proc.c -+++ a/fs/nfs/proc.c -@@ -41,6 +41,7 @@ - #include - #include - #include -+#include - #include "internal.h" - - #define NFSDBG_FACILITY NFSDBG_PROC -@@ -59,7 +60,7 @@ nfs_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) - res = rpc_call_sync(clnt, msg, flags); - if (res != -EKEYEXPIRED) - break; -- schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); -+ freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); - res = -ERESTARTSYS; - } while (!fatal_signal_pending(current)); - return res; ---- a/include/linux/freezer.h -+++ a/include/linux/freezer.h -@@ -135,6 +135,29 @@ static inline void set_freezable_with_signal(void) - } - - /* -+ * These macros are intended to be used whenever you want allow a task that's -+ * sleeping in TASK_UNINTERRUPTIBLE or TASK_KILLABLE state to be frozen. Note -+ * that neither return any clear indication of whether a freeze event happened -+ * while in this function. -+ */ -+ -+/* Like schedule(), but should not block the freezer. */ -+#define freezable_schedule() \ -+({ \ -+ freezer_do_not_count(); \ -+ schedule(); \ -+ freezer_count(); \ -+}) -+ -+/* Like schedule_timeout_killable(), but should not block the freezer. */ -+#define freezable_schedule_timeout_killable(timeout) \ -+({ \ -+ freezer_do_not_count(); \ -+ schedule_timeout_killable(timeout); \ -+ freezer_count(); \ -+}) -+ -+/* - * Freezer-friendly wrappers around wait_event_interruptible(), - * wait_event_killable() and wait_event_interruptible_timeout(), originally - * defined in -@@ -194,6 +217,11 @@ static inline int freezer_should_skip(struct task_struct *p) { return 0; } - static inline void set_freezable(void) {} - static inline void set_freezable_with_signal(void) {} - -+#define freezable_schedule() schedule() -+ -+#define freezable_schedule_timeout_killable(timeout) \ -+ schedule_timeout_killable(timeout) -+ - #define wait_event_freezable(wq, condition) \ - wait_event_interruptible(wq, condition) - ---- a/net/sunrpc/sched.c -+++ a/net/sunrpc/sched.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - - #include - -@@ -231,7 +232,7 @@ static int rpc_wait_bit_killable(void *word) - { - if (fatal_signal_pending(current)) - return -ERESTARTSYS; -- schedule(); -+ freezable_schedule(); - return 0; - } - - include/linux/freezer.h | 21 ++++++++++++++++++--- - 1 files changed, 18 insertions(+), 3 deletions(-) ---- a/include/linux/freezer.h -+++ a/include/linux/freezer.h -@@ -141,18 +141,33 @@ static inline void set_freezable_with_signal(void) - * while in this function. - */ - --/* Like schedule(), but should not block the freezer. */ -+/* -+ * Like schedule(), but should not block the freezer. It may return immediately -+ * if it ends up racing with the freezer. Callers must be able to deal with -+ * spurious wakeups. -+ */ - #define freezable_schedule() \ - ({ \ - freezer_do_not_count(); \ -- schedule(); \ -+ if (!try_to_freeze()) \ -+ schedule(); \ - freezer_count(); \ - }) - --/* Like schedule_timeout_killable(), but should not block the freezer. */ -+/* -+ * Like schedule_timeout_killable(), but should not block the freezer. It may -+ * end up returning immediately if it ends up racing with the freezer. Callers -+ * must be able to deal with the loose wakeup timing that can occur when the -+ * freezer races in. When that occurs, this function will return the timeout -+ * value instead of 0. -+ */ - #define freezable_schedule_timeout_killable(timeout) \ - ({ \ - freezer_do_not_count(); \ -+ if (try_to_freeze()) { \ -+ freezer_count(); \ -+ return timeout; \ -+ } \ - schedule_timeout_killable(timeout); \ - freezer_count(); \ - }) diff --git a/proc-fix-null-pointer-deref-in-proc_pid_permission.patch b/proc-fix-null-pointer-deref-in-proc_pid_permission.patch deleted file mode 100644 index 62d2fb21a..000000000 --- a/proc-fix-null-pointer-deref-in-proc_pid_permission.patch +++ /dev/null @@ -1,44 +0,0 @@ -From a2ef990ab5a6705a356d146dd773a3b359787497 Mon Sep 17 00:00:00 2001 -From: Xiaotian Feng -Date: Thu, 12 Jan 2012 17:17:08 -0800 -Subject: [PATCH] proc: fix null pointer deref in proc_pid_permission() - -get_proc_task() can fail to search the task and return NULL, -put_task_struct() will then bomb the kernel with following oops: - - BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 - IP: [] proc_pid_permission+0x64/0xe0 - PGD 112075067 PUD 112814067 PMD 0 - Oops: 0002 [#1] PREEMPT SMP - -This is a regression introduced by commit 0499680a ("procfs: add hidepid= -and gid= mount options"). The kernel should return -ESRCH if -get_proc_task() failed. - -Signed-off-by: Xiaotian Feng -Cc: Al Viro -Cc: Vasiliy Kulikov -Cc: Stephen Wilson -Acked-by: David Rientjes -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds ---- - fs/proc/base.c | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) - -diff --git a/fs/proc/base.c b/fs/proc/base.c -index 8173dfd..5485a53 100644 ---- a/fs/proc/base.c -+++ b/fs/proc/base.c -@@ -654,6 +654,8 @@ static int proc_pid_permission(struct inode *inode, int mask) - bool has_perms; - - task = get_proc_task(inode); -+ if (!task) -+ return -ESRCH; - has_perms = has_pid_permissions(pid, task, 1); - put_task_struct(task); - --- -1.7.7.5 - diff --git a/procfs-add-hidepid-and-gid-mount-options.patch b/procfs-add-hidepid-and-gid-mount-options.patch deleted file mode 100644 index 803f77d4c..000000000 --- a/procfs-add-hidepid-and-gid-mount-options.patch +++ /dev/null @@ -1,342 +0,0 @@ -From 0499680a42141d86417a8fbaa8c8db806bea1201 Mon Sep 17 00:00:00 2001 -From: Vasiliy Kulikov -Date: Tue, 10 Jan 2012 15:11:31 -0800 -Subject: [PATCH] procfs: add hidepid= and gid= mount options - -Add support for mount options to restrict access to /proc/PID/ -directories. The default backward-compatible "relaxed" behaviour is left -untouched. - -The first mount option is called "hidepid" and its value defines how much -info about processes we want to be available for non-owners: - -hidepid=0 (default) means the old behavior - anybody may read all -world-readable /proc/PID/* files. - -hidepid=1 means users may not access any /proc// directories, but -their own. Sensitive files like cmdline, sched*, status are now protected -against other users. As permission checking done in proc_pid_permission() -and files' permissions are left untouched, programs expecting specific -files' modes are not confused. - -hidepid=2 means hidepid=1 plus all /proc/PID/ will be invisible to other -users. It doesn't mean that it hides whether a process exists (it can be -learned by other means, e.g. by kill -0 $PID), but it hides process' euid -and egid. It compicates intruder's task of gathering info about running -processes, whether some daemon runs with elevated privileges, whether -another user runs some sensitive program, whether other users run any -program at all, etc. - -gid=XXX defines a group that will be able to gather all processes' info -(as in hidepid=0 mode). This group should be used instead of putting -nonroot user in sudoers file or something. However, untrusted users (like -daemons, etc.) which are not supposed to monitor the tasks in the whole -system should not be added to the group. - -hidepid=1 or higher is designed to restrict access to procfs files, which -might reveal some sensitive private information like precise keystrokes -timings: - -http://www.openwall.com/lists/oss-security/2011/11/05/3 - -hidepid=1/2 doesn't break monitoring userspace tools. ps, top, pgrep, and -conky gracefully handle EPERM/ENOENT and behave as if the current user is -the only user running processes. pstree shows the process subtree which -contains "pstree" process. - -Note: the patch doesn't deal with setuid/setgid issues of keeping -preopened descriptors of procfs files (like -https://lkml.org/lkml/2011/2/7/368). We rely on that the leaked -information like the scheduling counters of setuid apps doesn't threaten -anybody's privacy - only the user started the setuid program may read the -counters. - -Signed-off-by: Vasiliy Kulikov -Cc: Alexey Dobriyan -Cc: Al Viro -Cc: Randy Dunlap -Cc: "H. Peter Anvin" -Cc: Greg KH -Cc: Theodore Tso -Cc: Alan Cox -Cc: James Morris -Cc: Oleg Nesterov -Cc: Hugh Dickins -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds ---- - Documentation/filesystems/proc.txt | 39 ++++++++++++++++++++ - fs/proc/base.c | 69 +++++++++++++++++++++++++++++++++++- - fs/proc/inode.c | 8 ++++ - fs/proc/root.c | 21 +++++++++-- - include/linux/pid_namespace.h | 2 + - 5 files changed, 135 insertions(+), 4 deletions(-) - -diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt -index 0ec91f0..12fee13 100644 ---- a/Documentation/filesystems/proc.txt -+++ b/Documentation/filesystems/proc.txt -@@ -41,6 +41,8 @@ Table of Contents - 3.5 /proc//mountinfo - Information about mounts - 3.6 /proc//comm & /proc//task//comm - -+ 4 Configuring procfs -+ 4.1 Mount options - - ------------------------------------------------------------------------------ - Preface -@@ -1542,3 +1544,40 @@ a task to set its own or one of its thread siblings comm value. The comm value - is limited in size compared to the cmdline value, so writing anything longer - then the kernel's TASK_COMM_LEN (currently 16 chars) will result in a truncated - comm value. -+ -+ -+------------------------------------------------------------------------------ -+Configuring procfs -+------------------------------------------------------------------------------ -+ -+4.1 Mount options -+--------------------- -+ -+The following mount options are supported: -+ -+ hidepid= Set /proc// access mode. -+ gid= Set the group authorized to learn processes information. -+ -+hidepid=0 means classic mode - everybody may access all /proc// directories -+(default). -+ -+hidepid=1 means users may not access any /proc// directories but their -+own. Sensitive files like cmdline, sched*, status are now protected against -+other users. This makes it impossible to learn whether any user runs -+specific program (given the program doesn't reveal itself by its behaviour). -+As an additional bonus, as /proc//cmdline is unaccessible for other users, -+poorly written programs passing sensitive information via program arguments are -+now protected against local eavesdroppers. -+ -+hidepid=2 means hidepid=1 plus all /proc// will be fully invisible to other -+users. It doesn't mean that it hides a fact whether a process with a specific -+pid value exists (it can be learned by other means, e.g. by "kill -0 $PID"), -+but it hides process' uid and gid, which may be learned by stat()'ing -+/proc// otherwise. It greatly complicates an intruder's task of gathering -+information about running processes, whether some daemon runs with elevated -+privileges, whether other user runs some sensitive program, whether other users -+run any program at all, etc. -+ -+gid= defines a group authorized to learn processes information otherwise -+prohibited by hidepid=. If you use some daemon like identd which needs to learn -+information about processes information, just add identd to this group. -diff --git a/fs/proc/base.c b/fs/proc/base.c -index 4d755fe..8173dfd 100644 ---- a/fs/proc/base.c -+++ b/fs/proc/base.c -@@ -631,6 +631,50 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr) - return 0; - } - -+/* -+ * May current process learn task's sched/cmdline info (for hide_pid_min=1) -+ * or euid/egid (for hide_pid_min=2)? -+ */ -+static bool has_pid_permissions(struct pid_namespace *pid, -+ struct task_struct *task, -+ int hide_pid_min) -+{ -+ if (pid->hide_pid < hide_pid_min) -+ return true; -+ if (in_group_p(pid->pid_gid)) -+ return true; -+ return ptrace_may_access(task, PTRACE_MODE_READ); -+} -+ -+ -+static int proc_pid_permission(struct inode *inode, int mask) -+{ -+ struct pid_namespace *pid = inode->i_sb->s_fs_info; -+ struct task_struct *task; -+ bool has_perms; -+ -+ task = get_proc_task(inode); -+ has_perms = has_pid_permissions(pid, task, 1); -+ put_task_struct(task); -+ -+ if (!has_perms) { -+ if (pid->hide_pid == 2) { -+ /* -+ * Let's make getdents(), stat(), and open() -+ * consistent with each other. If a process -+ * may not stat() a file, it shouldn't be seen -+ * in procfs at all. -+ */ -+ return -ENOENT; -+ } -+ -+ return -EPERM; -+ } -+ return generic_permission(inode, mask); -+} -+ -+ -+ - static const struct inode_operations proc_def_inode_operations = { - .setattr = proc_setattr, - }; -@@ -1615,6 +1659,7 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) - struct inode *inode = dentry->d_inode; - struct task_struct *task; - const struct cred *cred; -+ struct pid_namespace *pid = dentry->d_sb->s_fs_info; - - generic_fillattr(inode, stat); - -@@ -1623,6 +1668,14 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) - stat->gid = 0; - task = pid_task(proc_pid(inode), PIDTYPE_PID); - if (task) { -+ if (!has_pid_permissions(pid, task, 2)) { -+ rcu_read_unlock(); -+ /* -+ * This doesn't prevent learning whether PID exists, -+ * it only makes getattr() consistent with readdir(). -+ */ -+ return -ENOENT; -+ } - if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || - task_dumpable(task)) { - cred = __task_cred(task); -@@ -3119,6 +3172,7 @@ static const struct inode_operations proc_tgid_base_inode_operations = { - .lookup = proc_tgid_base_lookup, - .getattr = pid_getattr, - .setattr = proc_setattr, -+ .permission = proc_pid_permission, - }; - - static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid) -@@ -3322,6 +3376,12 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi - proc_pid_instantiate, iter.task, NULL); - } - -+static int fake_filldir(void *buf, const char *name, int namelen, -+ loff_t offset, u64 ino, unsigned d_type) -+{ -+ return 0; -+} -+ - /* for the /proc/ directory itself, after non-process stuff has been done */ - int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) - { -@@ -3329,6 +3389,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) - struct task_struct *reaper; - struct tgid_iter iter; - struct pid_namespace *ns; -+ filldir_t __filldir; - - if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET) - goto out_no_task; -@@ -3350,8 +3411,13 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) - for (iter = next_tgid(ns, iter); - iter.task; - iter.tgid += 1, iter = next_tgid(ns, iter)) { -+ if (has_pid_permissions(ns, iter.task, 2)) -+ __filldir = filldir; -+ else -+ __filldir = fake_filldir; -+ - filp->f_pos = iter.tgid + TGID_OFFSET; -- if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) { -+ if (proc_pid_fill_cache(filp, dirent, __filldir, iter) < 0) { - put_task_struct(iter.task); - goto out; - } -@@ -3686,6 +3752,7 @@ static const struct inode_operations proc_task_inode_operations = { - .lookup = proc_task_lookup, - .getattr = proc_task_getattr, - .setattr = proc_setattr, -+ .permission = proc_pid_permission, - }; - - static const struct file_operations proc_task_operations = { -diff --git a/fs/proc/inode.c b/fs/proc/inode.c -index 27c762f..84fd323 100644 ---- a/fs/proc/inode.c -+++ b/fs/proc/inode.c -@@ -106,6 +106,14 @@ void __init proc_init_inodecache(void) - - static int proc_show_options(struct seq_file *seq, struct vfsmount *vfs) - { -+ struct super_block *sb = vfs->mnt_sb; -+ struct pid_namespace *pid = sb->s_fs_info; -+ -+ if (pid->pid_gid) -+ seq_printf(seq, ",gid=%lu", (unsigned long)pid->pid_gid); -+ if (pid->hide_pid != 0) -+ seq_printf(seq, ",hidepid=%u", pid->hide_pid); -+ - return 0; - } - -diff --git a/fs/proc/root.c b/fs/proc/root.c -index 6a8ac1d..46a15d8 100644 ---- a/fs/proc/root.c -+++ b/fs/proc/root.c -@@ -38,10 +38,12 @@ static int proc_set_super(struct super_block *sb, void *data) - } - - enum { -- Opt_err, -+ Opt_gid, Opt_hidepid, Opt_err, - }; - - static const match_table_t tokens = { -+ {Opt_hidepid, "hidepid=%u"}, -+ {Opt_gid, "gid=%u"}, - {Opt_err, NULL}, - }; - -@@ -49,8 +51,7 @@ static int proc_parse_options(char *options, struct pid_namespace *pid) - { - char *p; - substring_t args[MAX_OPT_ARGS]; -- -- pr_debug("proc: options = %s\n", options); -+ int option; - - if (!options) - return 1; -@@ -63,6 +64,20 @@ static int proc_parse_options(char *options, struct pid_namespace *pid) - args[0].to = args[0].from = 0; - token = match_token(p, tokens, args); - switch (token) { -+ case Opt_gid: -+ if (match_int(&args[0], &option)) -+ return 0; -+ pid->pid_gid = option; -+ break; -+ case Opt_hidepid: -+ if (match_int(&args[0], &option)) -+ return 0; -+ if (option < 0 || option > 2) { -+ pr_err("proc: hidepid value must be between 0 and 2.\n"); -+ return 0; -+ } -+ pid->hide_pid = option; -+ break; - default: - pr_err("proc: unrecognized mount option \"%s\" " - "or missing value\n", p); -diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h -index 38d1032..e7cf666 100644 ---- a/include/linux/pid_namespace.h -+++ b/include/linux/pid_namespace.h -@@ -30,6 +30,8 @@ struct pid_namespace { - #ifdef CONFIG_BSD_PROCESS_ACCT - struct bsd_acct_struct *bacct; - #endif -+ gid_t pid_gid; -+ int hide_pid; - }; - - extern struct pid_namespace init_pid_ns; --- -1.7.7.5 - diff --git a/procfs-parse-mount-options.patch b/procfs-parse-mount-options.patch deleted file mode 100644 index 0187a1d44..000000000 --- a/procfs-parse-mount-options.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 97412950b10e64f347aec4a9b759395c2465adf6 Mon Sep 17 00:00:00 2001 -From: Vasiliy Kulikov -Date: Tue, 10 Jan 2012 15:11:27 -0800 -Subject: [PATCH] procfs: parse mount options - -Add support for procfs mount options. Actual mount options are coming in -the next patches. - -Signed-off-by: Vasiliy Kulikov -Cc: Alexey Dobriyan -Cc: Al Viro -Cc: Randy Dunlap -Cc: "H. Peter Anvin" -Cc: Greg KH -Cc: Theodore Tso -Cc: Alan Cox -Cc: James Morris -Cc: Oleg Nesterov -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds ---- - fs/proc/inode.c | 10 +++++++++ - fs/proc/internal.h | 1 + - fs/proc/root.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++- - 3 files changed, 64 insertions(+), 2 deletions(-) - -diff --git a/fs/proc/inode.c b/fs/proc/inode.c -index 51a1766..27c762f 100644 ---- a/fs/proc/inode.c -+++ b/fs/proc/inode.c -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -17,7 +18,9 @@ - #include - #include - #include -+#include - #include -+#include - - #include - #include -@@ -101,12 +104,19 @@ void __init proc_init_inodecache(void) - init_once); - } - -+static int proc_show_options(struct seq_file *seq, struct vfsmount *vfs) -+{ -+ return 0; -+} -+ - static const struct super_operations proc_sops = { - .alloc_inode = proc_alloc_inode, - .destroy_inode = proc_destroy_inode, - .drop_inode = generic_delete_inode, - .evict_inode = proc_evict_inode, - .statfs = simple_statfs, -+ .remount_fs = proc_remount, -+ .show_options = proc_show_options, - }; - - static void __pde_users_dec(struct proc_dir_entry *pde) -diff --git a/fs/proc/internal.h b/fs/proc/internal.h -index 7838e5c..2925775 100644 ---- a/fs/proc/internal.h -+++ b/fs/proc/internal.h -@@ -117,6 +117,7 @@ void pde_put(struct proc_dir_entry *pde); - - int proc_fill_super(struct super_block *); - struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *); -+int proc_remount(struct super_block *sb, int *flags, char *data); - - /* - * These are generic /proc routines that use the internal -diff --git a/fs/proc/root.c b/fs/proc/root.c -index 03102d9..6a8ac1d 100644 ---- a/fs/proc/root.c -+++ b/fs/proc/root.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - - #include "internal.h" - -@@ -36,6 +37,48 @@ static int proc_set_super(struct super_block *sb, void *data) - return err; - } - -+enum { -+ Opt_err, -+}; -+ -+static const match_table_t tokens = { -+ {Opt_err, NULL}, -+}; -+ -+static int proc_parse_options(char *options, struct pid_namespace *pid) -+{ -+ char *p; -+ substring_t args[MAX_OPT_ARGS]; -+ -+ pr_debug("proc: options = %s\n", options); -+ -+ if (!options) -+ return 1; -+ -+ while ((p = strsep(&options, ",")) != NULL) { -+ int token; -+ if (!*p) -+ continue; -+ -+ args[0].to = args[0].from = 0; -+ token = match_token(p, tokens, args); -+ switch (token) { -+ default: -+ pr_err("proc: unrecognized mount option \"%s\" " -+ "or missing value\n", p); -+ return 0; -+ } -+ } -+ -+ return 1; -+} -+ -+int proc_remount(struct super_block *sb, int *flags, char *data) -+{ -+ struct pid_namespace *pid = sb->s_fs_info; -+ return !proc_parse_options(data, pid); -+} -+ - static struct dentry *proc_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) - { -@@ -43,11 +86,15 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, - struct super_block *sb; - struct pid_namespace *ns; - struct proc_inode *ei; -+ char *options; - -- if (flags & MS_KERNMOUNT) -+ if (flags & MS_KERNMOUNT) { - ns = (struct pid_namespace *)data; -- else -+ options = NULL; -+ } else { - ns = current->nsproxy->pid_ns; -+ options = data; -+ } - - sb = sget(fs_type, proc_test_super, proc_set_super, ns); - if (IS_ERR(sb)) -@@ -55,6 +102,10 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, - - if (!sb->s_root) { - sb->s_flags = flags; -+ if (!proc_parse_options(options, ns)) { -+ deactivate_locked_super(sb); -+ return ERR_PTR(-EINVAL); -+ } - err = proc_fill_super(sb); - if (err) { - deactivate_locked_super(sb); --- -1.7.7.5 - diff --git a/rebase-notes.txt b/rebase-notes.txt deleted file mode 100644 index cf9ab9d1f..000000000 --- a/rebase-notes.txt +++ /dev/null @@ -1,10 +0,0 @@ -* disable CONFIG_B43_BCMA_EXTRA (799657) - -* Do not turn on CONFIG_NFS_USE_NEW_IDMAPPER in f15/f16. Steved will hunt you - down. - -* Turn on the amilo-rfkill driver - -* Remove the with_backports/compat-wireless stuff - - diff --git a/revert-efi-rtclock.patch b/revert-efi-rtclock.patch deleted file mode 100644 index 87ecaa11a..000000000 --- a/revert-efi-rtclock.patch +++ /dev/null @@ -1,76 +0,0 @@ -diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c -index 3ae4128..e17c6d2 100644 ---- a/arch/x86/platform/efi/efi.c -+++ b/arch/x86/platform/efi/efi.c -@@ -89,50 +89,26 @@ early_param("add_efi_memmap", setup_add_efi_memmap); - - static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) - { -- unsigned long flags; -- efi_status_t status; -- -- spin_lock_irqsave(&rtc_lock, flags); -- status = efi_call_virt2(get_time, tm, tc); -- spin_unlock_irqrestore(&rtc_lock, flags); -- return status; -+ return efi_call_virt2(get_time, tm, tc); - } - - static efi_status_t virt_efi_set_time(efi_time_t *tm) - { -- unsigned long flags; -- efi_status_t status; -- -- spin_lock_irqsave(&rtc_lock, flags); -- status = efi_call_virt1(set_time, tm); -- spin_unlock_irqrestore(&rtc_lock, flags); -- return status; -+ return efi_call_virt1(set_time, tm); - } - - static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled, - efi_bool_t *pending, - efi_time_t *tm) - { -- unsigned long flags; -- efi_status_t status; -- -- spin_lock_irqsave(&rtc_lock, flags); -- status = efi_call_virt3(get_wakeup_time, -- enabled, pending, tm); -- spin_unlock_irqrestore(&rtc_lock, flags); -- return status; -+ return efi_call_virt3(get_wakeup_time, -+ enabled, pending, tm); - } - - static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) - { -- unsigned long flags; -- efi_status_t status; -- -- spin_lock_irqsave(&rtc_lock, flags); -- status = efi_call_virt2(set_wakeup_time, -- enabled, tm); -- spin_unlock_irqrestore(&rtc_lock, flags); -- return status; -+ return efi_call_virt2(set_wakeup_time, -+ enabled, tm); - } - - static efi_status_t virt_efi_get_variable(efi_char16_t *name, -@@ -232,14 +208,11 @@ static efi_status_t __init phys_efi_set_virtual_address_map( - static efi_status_t __init phys_efi_get_time(efi_time_t *tm, - efi_time_cap_t *tc) - { -- unsigned long flags; - efi_status_t status; - -- spin_lock_irqsave(&rtc_lock, flags); - efi_call_phys_prelog(); - status = efi_call_phys2(efi_phys.get_time, tm, tc); - efi_call_phys_epilog(); -- spin_unlock_irqrestore(&rtc_lock, flags); - return status; - } - diff --git a/rtl8192cu-Fix-WARNING-on-suspend-resume.patch b/rtl8192cu-Fix-WARNING-on-suspend-resume.patch deleted file mode 100644 index bdc8a5492..000000000 --- a/rtl8192cu-Fix-WARNING-on-suspend-resume.patch +++ /dev/null @@ -1,163 +0,0 @@ -A recent LKML thread (http://lkml.indiana.edu/hypermail/linux/kernel/1112.3/00965.html) -discusses warnings that occur during a suspend/resume cycle. The driver -attempts to read the firmware file before userspace is ready, leading to the -following warning: - -WARNING: at drivers/base/firmware_class.c:537 _request_firmware+0x3f6/0x420() - -For rtl8192cu, the problem is fixed by storing the firmware in a global buffer -rather than one allocated per device. The usage count is increased when -suspending and decreased when resuming. This way, the firmware is retained -through a suspend/resume cycle, and does not have to be reread. - -This patch should fix the bug reported in -https://bugzilla.redhat.com/show_bug.cgi?id=771002. - -Note: This patch also touches rtl8192ce as the "firmware" loaded message -is now printed in the wrong place. -Note: This patch also touches rtl8192ce as the "firmware" loaded message -is now printed in the wrong place. - -Reported-by: Mohammed Arafa -Reported-by: Dave Jones -Signed-off-by: Larry Finger -Cc: Linus Torvalds -Cc: Stable - ---- - drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 1 - - drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 1 + - drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 58 +++++++++++++++++---- - 3 files changed, 49 insertions(+), 11 deletions(-) - ---- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:07:58.830625006 -0500 -+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:08:06.825439927 -0500 -@@ -227,7 +227,6 @@ int rtl92c_download_fw(struct ieee80211_ - u32 fwsize; - enum version_8192c version = rtlhal->version; - -- pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); - if (!rtlhal->pfirmware) - return 1; - ---- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c -+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c -@@ -186,6 +186,7 @@ int rtl92c_init_sw_vars(struct ieee80211 - memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); - rtlpriv->rtlhal.fwsize = firmware->size; - release_firmware(firmware); -+ pr_info("rtl8192ce: Loaded firmware file %s\n", rtlpriv->cfg->fw_name); - - return 0; - } ---- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c -+++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c -@@ -43,6 +43,8 @@ - #include "hw.h" - #include - #include -+#include -+#include - - MODULE_AUTHOR("Georgia "); - MODULE_AUTHOR("Ziv Huang "); -@@ -51,6 +53,10 @@ MODULE_LICENSE("GPL"); - MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless"); - MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); - -+static char *rtl8192cu_firmware; /* pointer to firmware */ -+static int firmware_size; -+static atomic_t usage_count; -+ - static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -@@ -62,12 +68,21 @@ static int rtl92cu_init_sw_vars(struct i - rtlpriv->dm.disable_framebursting = false; - rtlpriv->dm.thermalvalue = 0; - rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; -- rtlpriv->rtlhal.pfirmware = vmalloc(0x4000); -- if (!rtlpriv->rtlhal.pfirmware) { -+ -+ if (rtl8192cu_firmware) { -+ /* firmware already loaded - true for suspend/resume -+ * and multiple instances of the device */ -+ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware; -+ rtlpriv->rtlhal.fwsize = firmware_size; -+ return 0; -+ } -+ rtl8192cu_firmware = vzalloc(0x4000); -+ if (!rtl8192cu_firmware) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Can't alloc buffer for fw.\n")); - return 1; - } -+ - /* request fw */ - err = request_firmware(&firmware, rtlpriv->cfg->fw_name, - rtlpriv->io.dev); -@@ -82,9 +97,14 @@ static int rtl92cu_init_sw_vars(struct i - release_firmware(firmware); - return 1; - } -- memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); -+ pr_info("rtl8192cu: Loaded firmware from file %s\n", -+ rtlpriv->cfg->fw_name); -+ memcpy(rtl8192cu_firmware, firmware->data, firmware->size); -+ firmware_size = firmware->size; - rtlpriv->rtlhal.fwsize = firmware->size; -+ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware; - release_firmware(firmware); -+ atomic_inc(&usage_count); - - return 0; - } -@@ -93,12 +113,30 @@ static void rtl92cu_deinit_sw_vars(struc - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - -- if (rtlpriv->rtlhal.pfirmware) { -- vfree(rtlpriv->rtlhal.pfirmware); -+ atomic_dec(&usage_count); -+ if (!atomic_read(&usage_count) && rtlpriv->rtlhal.pfirmware) { -+ vfree(rtl8192cu_firmware); -+ rtl8192cu_firmware = NULL; - rtlpriv->rtlhal.pfirmware = NULL; - } - } - -+#ifdef CONFIG_PM_SLEEP -+static int rtl8192cu_usb_suspend(struct usb_interface *pusb_intf, -+ pm_message_t message) -+{ -+ /* Increase usage_count to Save loaded fw across suspend/resume */ -+ atomic_inc(&usage_count); -+ return 0; -+} -+ -+static int rtl8192cu_usb_resume(struct usb_interface *pusb_intf) -+{ -+ atomic_dec(&usage_count); /* after resume, decrease usage count */ -+ return 0; -+} -+#endif -+ - static struct rtl_hal_ops rtl8192cu_hal_ops = { - .init_sw_vars = rtl92cu_init_sw_vars, - .deinit_sw_vars = rtl92cu_deinit_sw_vars, -@@ -374,11 +412,10 @@ static struct usb_driver rtl8192cu_drive - .disconnect = rtl_usb_disconnect, - .id_table = rtl8192c_usb_ids, - --#ifdef CONFIG_PM -- /* .suspend = rtl_usb_suspend, */ -- /* .resume = rtl_usb_resume, */ -- /* .reset_resume = rtl8192c_resume, */ --#endif /* CONFIG_PM */ -+#ifdef CONFIG_PM_SLEEP -+ .suspend = rtl8192cu_usb_suspend, -+ .resume = rtl8192cu_usb_resume, -+#endif /* CONFIG_PM_SLEEP */ - #ifdef CONFIG_AUTOSUSPEND - .supports_autosuspend = 1, - #endif diff --git a/scsi-fix-sd_revalidate_disk-oops.patch b/scsi-fix-sd_revalidate_disk-oops.patch deleted file mode 100644 index defa240a2..000000000 --- a/scsi-fix-sd_revalidate_disk-oops.patch +++ /dev/null @@ -1,116 +0,0 @@ ---- linux-2.6.42.noarch/fs/partitions/check.c~ 2012-02-20 18:32:55.314253719 -0500 -+++ linux-2.6.42.noarch/fs/partitions/check.c 2012-02-20 18:34:46.509859745 -0500 -@@ -539,17 +539,11 @@ static bool disk_unlock_native_capacity( - } - } - --int rescan_partitions(struct gendisk *disk, struct block_device *bdev) -+static int drop_partitions(struct gendisk *disk, struct block_device *bdev) - { -- struct parsed_partitions *state = NULL; - struct disk_part_iter piter; - struct hd_struct *part; -- int p, highest, res; --rescan: -- if (state && !IS_ERR(state)) { -- kfree(state); -- state = NULL; -- } -+ int res; - - if (bdev->bd_part_count) - return -EBUSY; -@@ -562,6 +556,24 @@ rescan: - delete_partition(disk, part->partno); - disk_part_iter_exit(&piter); - -+ return 0; -+} -+ -+int rescan_partitions(struct gendisk *disk, struct block_device *bdev) -+{ -+ struct parsed_partitions *state = NULL; -+ struct hd_struct *part; -+ int p, highest, res; -+rescan: -+ if (state && !IS_ERR(state)) { -+ kfree(state); -+ state = NULL; -+ } -+ -+ res = drop_partitions(disk, bdev); -+ if (res) -+ return res; -+ - if (disk->fops->revalidate_disk) - disk->fops->revalidate_disk(disk); - check_disk_size_change(disk, bdev); -@@ -665,6 +677,26 @@ rescan: - return 0; - } - -+int invalidate_partitions(struct gendisk *disk, struct block_device *bdev) -+{ -+ int res; -+ -+ if (!bdev->bd_invalidated) -+ return 0; -+ -+ res = drop_partitions(disk, bdev); -+ if (res) -+ return res; -+ -+ set_capacity(disk, 0); -+ check_disk_size_change(disk, bdev); -+ bdev->bd_invalidated = 0; -+ /* tell userspace that the media / partition table may have changed */ -+ kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE); -+ -+ return 0; -+} -+ - unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p) - { - struct address_space *mapping = bdev->bd_inode->i_mapping; ---- linux-2.6.42.noarch/include/linux/genhd.h~ 2012-02-20 18:35:02.777802107 -0500 -+++ linux-2.6.42.noarch/include/linux/genhd.h 2012-02-20 18:35:13.873762792 -0500 -@@ -596,6 +596,7 @@ extern char *disk_name (struct gendisk * - - extern int disk_expand_part_tbl(struct gendisk *disk, int target); - extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); -+extern int invalidate_partitions(struct gendisk *disk, struct block_device *bdev); - extern struct hd_struct * __must_check add_partition(struct gendisk *disk, - int partno, sector_t start, - sector_t len, int flags, ---- linux-2.6.42.noarch/fs/block_dev.c~ 2012-02-20 18:35:24.890723757 -0500 -+++ linux-2.6.42.noarch/fs/block_dev.c 2012-02-20 18:36:25.166510197 -0500 -@@ -1159,8 +1159,12 @@ static int __blkdev_get(struct block_dev - * The latter is necessary to prevent ghost - * partitions on a removed medium. - */ -- if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM)) -- rescan_partitions(disk, bdev); -+ if (bdev->bd_invalidated) { -+ if (!ret) -+ rescan_partitions(disk, bdev); -+ else if (ret == -ENOMEDIUM) -+ invalidate_partitions(disk, bdev); -+ } - if (ret) - goto out_clear; - } else { -@@ -1190,8 +1194,12 @@ static int __blkdev_get(struct block_dev - if (bdev->bd_disk->fops->open) - ret = bdev->bd_disk->fops->open(bdev, mode); - /* the same as first opener case, read comment there */ -- if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM)) -- rescan_partitions(bdev->bd_disk, bdev); -+ if (bdev->bd_invalidated) { -+ if (!ret) -+ rescan_partitions(bdev->bd_disk, bdev); -+ else if (ret == -ENOMEDIUM) -+ invalidate_partitions(bdev->bd_disk, bdev); -+ } - if (ret) - goto out_unlock_bdev; - } diff --git a/sources b/sources index a003ef5f5..2fad201c9 100644 --- a/sources +++ b/sources @@ -1,2 +1 @@ -364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz -7481fa09f2efda915ed19a9da33a2e59 patch-3.2.10.xz +7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz diff --git a/sysfs-msi-irq-per-device.patch b/sysfs-msi-irq-per-device.patch deleted file mode 100644 index a2bf57c92..000000000 --- a/sysfs-msi-irq-per-device.patch +++ /dev/null @@ -1,239 +0,0 @@ -From: Neil Horman -Date: Thu, 6 Oct 2011 18:08:18 +0000 (-0400) -Subject: PCI/sysfs: add per pci device msi[x] irq listing (v5) -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fjbarnes%2Fpci.git;a=commitdiff_plain;h=933aa5c1f69aa650f59ba783307fc7ed7cc5fafa - -PCI/sysfs: add per pci device msi[x] irq listing (v5) - -This patch adds a per-pci-device subdirectory in sysfs called: -/sys/bus/pci/devices//msi_irqs - -This sub-directory exports the set of msi vectors allocated by a given -pci device, by creating a numbered sub-directory for each vector beneath -msi_irqs. For each vector various attributes can be exported. -Currently the only attribute is called mode, which tracks the -operational mode of that vector (msi vs. msix) - -Acked-by: Greg Kroah-Hartman -Signed-off-by: Jesse Barnes ---- - -diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci -index 349ecf2..34f5110 100644 ---- a/Documentation/ABI/testing/sysfs-bus-pci -+++ b/Documentation/ABI/testing/sysfs-bus-pci -@@ -66,6 +66,24 @@ Description: - re-discover previously removed devices. - Depends on CONFIG_HOTPLUG. - -+What: /sys/bus/pci/devices/.../msi_irqs/ -+Date: September, 2011 -+Contact: Neil Horman -+Description: -+ The /sys/devices/.../msi_irqs directory contains a variable set -+ of sub-directories, with each sub-directory being named after a -+ corresponding msi irq vector allocated to that device. Each -+ numbered sub-directory N contains attributes of that irq. -+ Note that this directory is not created for device drivers which -+ do not support msi irqs -+ -+What: /sys/bus/pci/devices/.../msi_irqs//mode -+Date: September 2011 -+Contact: Neil Horman -+Description: -+ This attribute indicates the mode that the irq vector named by -+ the parent directory is in (msi vs. msix) -+ - What: /sys/bus/pci/devices/.../remove - Date: January 2009 - Contact: Linux PCI developers -diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c -index 2f10328..73613e2 100644 ---- a/drivers/pci/msi.c -+++ b/drivers/pci/msi.c -@@ -322,6 +322,8 @@ static void free_msi_irqs(struct pci_dev *dev) - if (list_is_last(&entry->list, &dev->msi_list)) - iounmap(entry->mask_base); - } -+ kobject_del(&entry->kobj); -+ kobject_put(&entry->kobj); - list_del(&entry->list); - kfree(entry); - } -@@ -402,6 +404,98 @@ void pci_restore_msi_state(struct pci_dev *dev) - } - EXPORT_SYMBOL_GPL(pci_restore_msi_state); - -+ -+#define to_msi_attr(obj) container_of(obj, struct msi_attribute, attr) -+#define to_msi_desc(obj) container_of(obj, struct msi_desc, kobj) -+ -+struct msi_attribute { -+ struct attribute attr; -+ ssize_t (*show)(struct msi_desc *entry, struct msi_attribute *attr, -+ char *buf); -+ ssize_t (*store)(struct msi_desc *entry, struct msi_attribute *attr, -+ const char *buf, size_t count); -+}; -+ -+static ssize_t show_msi_mode(struct msi_desc *entry, struct msi_attribute *atr, -+ char *buf) -+{ -+ return sprintf(buf, "%s\n", entry->msi_attrib.is_msix ? "msix" : "msi"); -+} -+ -+static ssize_t msi_irq_attr_show(struct kobject *kobj, -+ struct attribute *attr, char *buf) -+{ -+ struct msi_attribute *attribute = to_msi_attr(attr); -+ struct msi_desc *entry = to_msi_desc(kobj); -+ -+ if (!attribute->show) -+ return -EIO; -+ -+ return attribute->show(entry, attribute, buf); -+} -+ -+static const struct sysfs_ops msi_irq_sysfs_ops = { -+ .show = msi_irq_attr_show, -+}; -+ -+static struct msi_attribute mode_attribute = -+ __ATTR(mode, S_IRUGO, show_msi_mode, NULL); -+ -+ -+struct attribute *msi_irq_default_attrs[] = { -+ &mode_attribute.attr, -+ NULL -+}; -+ -+void msi_kobj_release(struct kobject *kobj) -+{ -+ struct msi_desc *entry = to_msi_desc(kobj); -+ -+ pci_dev_put(entry->dev); -+} -+ -+static struct kobj_type msi_irq_ktype = { -+ .release = msi_kobj_release, -+ .sysfs_ops = &msi_irq_sysfs_ops, -+ .default_attrs = msi_irq_default_attrs, -+}; -+ -+static int populate_msi_sysfs(struct pci_dev *pdev) -+{ -+ struct msi_desc *entry; -+ struct kobject *kobj; -+ int ret; -+ int count = 0; -+ -+ pdev->msi_kset = kset_create_and_add("msi_irqs", NULL, &pdev->dev.kobj); -+ if (!pdev->msi_kset) -+ return -ENOMEM; -+ -+ list_for_each_entry(entry, &pdev->msi_list, list) { -+ kobj = &entry->kobj; -+ kobj->kset = pdev->msi_kset; -+ pci_dev_get(pdev); -+ ret = kobject_init_and_add(kobj, &msi_irq_ktype, NULL, -+ "%u", entry->irq); -+ if (ret) -+ goto out_unroll; -+ -+ count++; -+ } -+ -+ return 0; -+ -+out_unroll: -+ list_for_each_entry(entry, &pdev->msi_list, list) { -+ if (!count) -+ break; -+ kobject_del(&entry->kobj); -+ kobject_put(&entry->kobj); -+ count--; -+ } -+ return ret; -+} -+ - /** - * msi_capability_init - configure device's MSI capability structure - * @dev: pointer to the pci_dev data structure of MSI device function -@@ -453,6 +547,13 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) - return ret; - } - -+ ret = populate_msi_sysfs(dev); -+ if (ret) { -+ msi_mask_irq(entry, mask, ~mask); -+ free_msi_irqs(dev); -+ return ret; -+ } -+ - /* Set MSI enabled bits */ - pci_intx_for_msi(dev, 0); - msi_set_enable(dev, pos, 1); -@@ -573,6 +674,12 @@ static int msix_capability_init(struct pci_dev *dev, - - msix_program_entries(dev, entries); - -+ ret = populate_msi_sysfs(dev); -+ if (ret) { -+ ret = 0; -+ goto error; -+ } -+ - /* Set MSI-X enabled bits and unmask the function */ - pci_intx_for_msi(dev, 0); - dev->msix_enabled = 1; -@@ -731,6 +838,8 @@ void pci_disable_msi(struct pci_dev *dev) - - pci_msi_shutdown(dev); - free_msi_irqs(dev); -+ kset_unregister(dev->msi_kset); -+ dev->msi_kset = NULL; - } - EXPORT_SYMBOL(pci_disable_msi); - -@@ -829,6 +938,8 @@ void pci_disable_msix(struct pci_dev *dev) - - pci_msix_shutdown(dev); - free_msi_irqs(dev); -+ kset_unregister(dev->msi_kset); -+ dev->msi_kset = NULL; - } - EXPORT_SYMBOL(pci_disable_msix); - -diff --git a/include/linux/msi.h b/include/linux/msi.h -index 05acced..ce93a34 100644 ---- a/include/linux/msi.h -+++ b/include/linux/msi.h -@@ -1,6 +1,7 @@ - #ifndef LINUX_MSI_H - #define LINUX_MSI_H - -+#include - #include - - struct msi_msg { -@@ -44,6 +45,8 @@ struct msi_desc { - - /* Last set MSI message */ - struct msi_msg msg; -+ -+ struct kobject kobj; - }; - - /* -diff --git a/include/linux/pci.h b/include/linux/pci.h -index 7cda65b..84225c7 100644 ---- a/include/linux/pci.h -+++ b/include/linux/pci.h -@@ -336,6 +336,7 @@ struct pci_dev { - struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */ - #ifdef CONFIG_PCI_MSI - struct list_head msi_list; -+ struct kset *msi_kset; - #endif - struct pci_vpd *vpd; - #ifdef CONFIG_PCI_ATS diff --git a/utrace.patch b/utrace.patch index 333c669f5..fdf24a472 100644 --- a/utrace.patch +++ b/utrace.patch @@ -1,81 +1,74 @@ -From davej Wed Aug 3 15:16:11 2011 -From oleg@redhat.com Mon Nov 21 15:06:14 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:14 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9A1F8D50F1; - Mon, 21 Nov 2011 15:06:14 -0500 (EST) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id gJzpul4rDNnA; Mon, 21 Nov 2011 15:06:14 -0500 (EST) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7DD4BD50EA; - Mon, 21 Nov 2011 15:06:14 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6BJJ022074; - Mon, 21 Nov 2011 15:06:12 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:32 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:30 +0100 +From d007ce2c3f1f67624fde5e6b7ccc00566b7df9c3 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 01/33] utrace core -Message-ID: <20111121200130.GA27756@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Status: RO -Content-Length: 139951 -Lines: 3867 +Date: Sat, 25 Feb 2012 07:29:40 -0500 +Subject: [PATCH] utrace for 3.3-rc4 kernel, on top of + b52b80023f262ce8a0ffdcb490acb23e8678377a. -From: Roland McGrath +The split-out series is available in the git repository at: -This adds the utrace facility, a new modular interface in the kernel for -implementing user thread tracing and debugging. This fits on top of the -tracehook_* layer, so the new code is well-isolated. + git@github.com:utrace/linux.git utrace-3.3 -The new interface is in and the DocBook utrace book -describes it. It allows for multiple separate tracing engines to work in -parallel without interfering with each other. Higher-level tracing -facilities can be implemented as loadable kernel modules using this layer. +Oleg Nesterov (31): + utrace: add utrace_init_task/utrace_free_task calls + tracehooks: add utrace hooks + tracehooks: reintroduce tracehook_consider_fatal_signal() + add utrace hooks into sig_ignored() and recalc_sigpending() + restore the EXEC/EXIT/CLONE utrace hooks + utrace: utrace_report_death() can use task_utrace_struct() + restore the DEATH/REAP utrace hooks + utrace: remove jobctl bits + ptrace: take ->siglock around s/TRACED/RUNNING/ + introduce wake_up_quiescent() + introduce ptrace_signal_wake_up() + wait_task_inactive: treat task->state and match_state as bitmasks + introduce TASK_UTRACED state + utrace: use TASK_UTRACED instead of TASK_TRACED + reintroduce tracehook_finish_jctl() as utrace_end_stop() + teach wake_up_quiescent() to do "selective" wake_up + ptrace_stop: do not assume the task is running after wake_up_quiescent() + get_signal_to_deliver: restore/restructure utrace/ptrace signal reporting + utrace_get_signal: s/JOBCTL_STOP_PENDING/JOBCTL_PENDING_MASK/ + introduce ptrace_set_syscall_trace() + introduce PT_SYSCALL_TRACE flag + utrace: don't clear TIF_SYSCALL_TRACE if it is needed by ptrace + introduce task_utrace_lock/task_utrace_unlock + teach ptrace_set_syscall_trace() to play well with utrace + introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK + utrace: finish_resume_report: don't do user_xxx_step() if ptrace_wants_step() + ptrace: shift user_*_step() from ptrace_resume() to ptrace_stop() + ptrace_disable: no need to disable stepping + ptrace_report_syscall: check TIF_SYSCALL_EMU + utrace_resume: check irqs_disabled() to shut up lockdep + utrace: s390: fix the compile problem with traps.c -The new facility is made optional under CONFIG_UTRACE. -When this is not enabled, no new code is added. -It can only be enabled on machines that have all the -prerequisites and select CONFIG_HAVE_ARCH_TRACEHOOK. +Roland McGrath (1): + utrace core -In this initial version, utrace and ptrace do not play together at all, -the next patches try to fix this. +Tony Breeds (1): + ptrace_report_syscall: check if TIF_SYSCALL_EMU is defined -This is is same/old utrace-core patch except: - - - use task->jobctl/JOBCTL_STOP_DEQUEUED instead of removed - signal->flags/SIGNAL_STOP_DEQUEUED in utrace_get_signal() - - - do not include the tracehook changes, this comes with the - next patches - -Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov --- Documentation/DocBook/Makefile | 2 +- Documentation/DocBook/utrace.tmpl | 589 +++++++++ - fs/proc/array.c | 3 + - include/linux/sched.h | 5 + - include/linux/utrace.h | 692 +++++++++++ + arch/s390/kernel/traps.c | 6 +- + arch/x86/kernel/ptrace.c | 1 - + fs/exec.c | 5 +- + fs/proc/array.c | 14 +- + include/linux/ptrace.h | 7 + + include/linux/sched.h | 25 +- + include/linux/signal.h | 2 + + include/linux/tracehook.h | 59 +- + include/linux/utrace.h | 774 ++++++++++++ init/Kconfig | 9 + kernel/Makefile | 1 + - kernel/utrace.c | 2440 +++++++++++++++++++++++++++++++++++++ - 8 files changed, 3740 insertions(+), 1 deletions(-) + kernel/exit.c | 5 + + kernel/fork.c | 9 + + kernel/ptrace.c | 57 +- + kernel/sched/core.c | 2 +- + kernel/signal.c | 97 ++- + kernel/utrace.c | 2466 +++++++++++++++++++++++++++++++++++++ + 19 files changed, 4074 insertions(+), 56 deletions(-) create mode 100644 Documentation/DocBook/utrace.tmpl create mode 100644 include/linux/utrace.h create mode 100644 kernel/utrace.c @@ -688,8 +681,69 @@ index 0000000..0c40add + + + +diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c +index 5ce3750..4f0b32f 100644 +--- a/arch/s390/kernel/traps.c ++++ b/arch/s390/kernel/traps.c +@@ -18,7 +18,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +@@ -330,7 +330,7 @@ void __kprobes do_per_trap(struct pt_regs *regs) + + if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP) + return; +- if (!current->ptrace) ++ if (!tracehook_consider_fatal_signal(current, SIGTRAP)) + return; + info.si_signo = SIGTRAP; + info.si_errno = 0; +@@ -415,7 +415,7 @@ static void __kprobes illegal_op(struct pt_regs *regs) + if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) + return; + if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) { +- if (current->ptrace) { ++ if (tracehook_consider_fatal_signal(current, SIGTRAP)) { + info.si_signo = SIGTRAP; + info.si_errno = 0; + info.si_code = TRAP_BRKPT; +diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c +index 5026738..97687f3 100644 +--- a/arch/x86/kernel/ptrace.c ++++ b/arch/x86/kernel/ptrace.c +@@ -809,7 +809,6 @@ static int ioperm_get(struct task_struct *target, + */ + void ptrace_disable(struct task_struct *child) + { +- user_disable_single_step(child); + #ifdef TIF_SYSCALL_EMU + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); + #endif +diff --git a/fs/exec.c b/fs/exec.c +index 92ce83a..87ff31f 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1402,9 +1402,12 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) + */ + bprm->recursion_depth = depth; + if (retval >= 0) { +- if (depth == 0) ++ if (depth == 0) { ++ UTRACE_HOOK(current, EXEC, ++ report_exec(fmt, bprm, regs)); + ptrace_event(PTRACE_EVENT_EXEC, + old_pid); ++ } + put_binfmt(fmt); + allow_write_access(bprm->file); + if (bprm->file) diff --git a/fs/proc/array.c b/fs/proc/array.c -index 3a1dafd..f0c0ea2 100644 +index c602b8d..a700b78 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -81,6 +81,7 @@ @@ -700,7 +754,25 @@ index 3a1dafd..f0c0ea2 100644 #include #include -@@ -192,6 +193,8 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, +@@ -137,11 +138,12 @@ static const char * const task_state_array[] = { + "D (disk sleep)", /* 2 */ + "T (stopped)", /* 4 */ + "t (tracing stop)", /* 8 */ +- "Z (zombie)", /* 16 */ +- "X (dead)", /* 32 */ +- "x (dead)", /* 64 */ +- "K (wakekill)", /* 128 */ +- "W (waking)", /* 256 */ ++ "t (tracing stop)", /* 16 (stopped by utrace) */ ++ "Z (zombie)", /* 32 */ ++ "X (dead)", /* 64 */ ++ "x (dead)", /* 128 */ ++ "K (wakekill)", /* 256 */ ++ "W (waking)", /* 512 */ + }; + + static inline const char *get_task_state(struct task_struct *tsk) +@@ -192,6 +194,8 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, cred->uid, cred->euid, cred->suid, cred->fsuid, cred->gid, cred->egid, cred->sgid, cred->fsgid); @@ -709,11 +781,87 @@ index 3a1dafd..f0c0ea2 100644 task_lock(p); if (p->files) fdt = files_fdtable(p->files); +diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h +index c2f1f6a..236b920 100644 +--- a/include/linux/ptrace.h ++++ b/include/linux/ptrace.h +@@ -104,6 +104,10 @@ + + #define PT_TRACE_MASK 0x000003f4 + ++#define PT_SYSCALL_TRACE 0x00020000 ++#define PT_SINGLE_STEP 0x00040000 ++#define PT_SINGLE_BLOCK 0x00080000 ++ + /* single stepping state bits (used on ARM and PA-RISC) */ + #define PT_SINGLESTEP_BIT 31 + #define PT_SINGLESTEP (1< /* For struct task_struct. */ + #include /* for IS_ERR_VALUE */ + ++extern void ptrace_signal_wake_up(struct task_struct *p, int quiescent); + + extern long arch_ptrace(struct task_struct *child, long request, + unsigned long addr, unsigned long data); +@@ -228,6 +233,8 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) + + if (unlikely(ptrace) && current->ptrace) { + child->ptrace = current->ptrace; ++ child->ptrace &= ++ ~(PT_SYSCALL_TRACE | PT_SINGLE_STEP | PT_SINGLE_BLOCK); + __ptrace_link(child, current->parent); + + if (child->ptrace & PT_SEIZED) diff --git a/include/linux/sched.h b/include/linux/sched.h -index 68daf4f..4d45f93 100644 +index 7d379a6..a3c4599 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h -@@ -1403,6 +1403,11 @@ struct task_struct { +@@ -185,16 +185,17 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) + #define TASK_UNINTERRUPTIBLE 2 + #define __TASK_STOPPED 4 + #define __TASK_TRACED 8 ++#define __TASK_UTRACED 16 + /* in tsk->exit_state */ +-#define EXIT_ZOMBIE 16 +-#define EXIT_DEAD 32 ++#define EXIT_ZOMBIE 32 ++#define EXIT_DEAD 64 + /* in tsk->state again */ +-#define TASK_DEAD 64 +-#define TASK_WAKEKILL 128 +-#define TASK_WAKING 256 +-#define TASK_STATE_MAX 512 ++#define TASK_DEAD 128 ++#define TASK_WAKEKILL 256 ++#define TASK_WAKING 512 ++#define TASK_STATE_MAX 1024 + +-#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKW" ++#define TASK_STATE_TO_CHAR_STR "RSDTtUZXxKW" + + extern char ___assert_task_state[1 - 2*!!( + sizeof(TASK_STATE_TO_CHAR_STR)-1 != ilog2(TASK_STATE_MAX)+1)]; +@@ -203,15 +204,16 @@ extern char ___assert_task_state[1 - 2*!!( + #define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE) + #define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED) + #define TASK_TRACED (TASK_WAKEKILL | __TASK_TRACED) ++#define TASK_UTRACED (TASK_WAKEKILL | __TASK_UTRACED) + + /* Convenience macros for the sake of wake_up */ + #define TASK_NORMAL (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE) +-#define TASK_ALL (TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED) ++#define TASK_ALL (TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED | __TASK_UTRACED) + + /* get_task_state() */ + #define TASK_REPORT (TASK_RUNNING | TASK_INTERRUPTIBLE | \ + TASK_UNINTERRUPTIBLE | __TASK_STOPPED | \ +- __TASK_TRACED) ++ __TASK_TRACED | __TASK_UTRACED) + + #define task_is_traced(task) ((task->state & __TASK_TRACED) != 0) + #define task_is_stopped(task) ((task->state & __TASK_STOPPED) != 0) +@@ -1420,6 +1422,11 @@ struct task_struct { #endif seccomp_t seccomp; @@ -725,12 +873,140 @@ index 68daf4f..4d45f93 100644 /* Thread group tracking */ u32 parent_exec_id; u32 self_exec_id; +diff --git a/include/linux/signal.h b/include/linux/signal.h +index 7987ce74..c320549 100644 +--- a/include/linux/signal.h ++++ b/include/linux/signal.h +@@ -239,6 +239,8 @@ static inline int valid_signal(unsigned long sig) + struct timespec; + struct pt_regs; + ++extern int wake_up_quiescent(struct task_struct *p, unsigned int state); ++ + extern int next_signal(struct sigpending *pending, sigset_t *mask); + extern int do_send_sig_info(int sig, struct siginfo *info, + struct task_struct *p, bool group); +diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h +index a71a292..a1bac95 100644 +--- a/include/linux/tracehook.h ++++ b/include/linux/tracehook.h +@@ -49,6 +49,7 @@ + #include + #include + #include ++#include + struct linux_binprm; + + /* +@@ -58,8 +59,12 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) + { + int ptrace = current->ptrace; + +- if (!(ptrace & PT_PTRACED)) +- return; ++ if (!(ptrace & PT_SYSCALL_TRACE)) { ++#ifdef TIF_SYSCALL_EMU ++ if (!test_thread_flag(TIF_SYSCALL_EMU)) ++#endif ++ return; ++ } + + ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); + +@@ -96,10 +101,16 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) + static inline __must_check int tracehook_report_syscall_entry( + struct pt_regs *regs) + { ++ if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && ++ utrace_report_syscall_entry(regs)) ++ return 1; + ptrace_report_syscall(regs); + return 0; + } + ++#define ptrace_wants_step(task) \ ++ ((task)->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK)) ++ + /** + * tracehook_report_syscall_exit - task has just finished a system call + * @regs: user register state of current task +@@ -119,7 +130,10 @@ static inline __must_check int tracehook_report_syscall_entry( + */ + static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) + { +- if (step) { ++ if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) ++ utrace_report_syscall_exit(regs); ++ ++ if (step && ptrace_wants_step(current)) { + siginfo_t info; + user_single_step_siginfo(current, regs, &info); + force_sig_info(SIGTRAP, &info, current); +@@ -148,10 +162,34 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, + const struct k_sigaction *ka, + struct pt_regs *regs, int stepping) + { +- if (stepping) ++ if (task_utrace_flags(current)) ++ utrace_signal_handler(current, stepping); ++ if (stepping && ptrace_wants_step(current)) + ptrace_notify(SIGTRAP); + } + ++/** ++ * tracehook_consider_fatal_signal - suppress special handling of fatal signal ++ * @task: task receiving the signal ++ * @sig: signal number being sent ++ * ++ * Return nonzero to prevent special handling of this termination signal. ++ * Normally handler for signal is %SIG_DFL. It can be %SIG_IGN if @sig is ++ * ignored, in which case force_sig() is about to reset it to %SIG_DFL. ++ * When this returns zero, this signal might cause a quick termination ++ * that does not give the debugger a chance to intercept the signal. ++ * ++ * Called with or without @task->sighand->siglock held. ++ */ ++static inline int tracehook_consider_fatal_signal(struct task_struct *task, ++ int sig) ++{ ++ if (unlikely(task_utrace_flags(task) & (UTRACE_EVENT(SIGNAL_TERM) | ++ UTRACE_EVENT(SIGNAL_CORE)))) ++ return 1; ++ return task->ptrace != 0; ++} ++ + #ifdef TIF_NOTIFY_RESUME + /** + * set_notify_resume - cause tracehook_notify_resume() to be called +@@ -179,10 +217,21 @@ static inline void set_notify_resume(struct task_struct *task) + * asynchronously, this will be called again before we return to + * user mode. + * +- * Called without locks. ++ * Called without locks. However, on some machines this may be ++ * called with interrupts disabled. + */ + static inline void tracehook_notify_resume(struct pt_regs *regs) + { ++ struct task_struct *task = current; ++ /* ++ * Prevent the following store/load from getting ahead of the ++ * caller which clears TIF_NOTIFY_RESUME. This pairs with the ++ * implicit mb() before setting TIF_NOTIFY_RESUME in ++ * set_notify_resume(). ++ */ ++ smp_mb(); ++ if (task_utrace_flags(task)) ++ utrace_resume(task, regs); + } + #endif /* TIF_NOTIFY_RESUME */ + diff --git a/include/linux/utrace.h b/include/linux/utrace.h new file mode 100644 -index 0000000..f251efe +index 0000000..46959af --- /dev/null +++ b/include/linux/utrace.h -@@ -0,0 +1,692 @@ +@@ -0,0 +1,774 @@ +/* + * utrace infrastructure interface for debugging user processes + * @@ -832,7 +1108,7 @@ index 0000000..f251efe +void utrace_report_clone(unsigned long, struct task_struct *); +void utrace_finish_vfork(struct task_struct *); +void utrace_report_exit(long *exit_code); -+void utrace_report_death(struct task_struct *, struct utrace *, bool, int); ++void utrace_report_death(struct task_struct *, bool, int); +void utrace_report_jctl(int notify, int type); +void utrace_report_exec(struct linux_binfmt *, struct linux_binprm *, + struct pt_regs *regs); @@ -840,8 +1116,22 @@ index 0000000..f251efe +void utrace_report_syscall_exit(struct pt_regs *); +void utrace_signal_handler(struct task_struct *, int); + ++#define UTRACE_FLAG(task, ev) (task_utrace_flags(task) & UTRACE_EVENT(ev)) ++ ++#define UTRACE_HOOK(task, ev, callback) \ ++ do { \ ++ if (UTRACE_FLAG(task, ev)) \ ++ utrace_ ## callback; \ ++ } while (0) ++ +#ifndef CONFIG_UTRACE + ++static inline void task_utrace_lock(struct task_struct *task) ++{ ++} ++static inline void task_utrace_unlock(struct task_struct *task) ++{ ++} +/* + * uses these accessors to avoid #ifdef CONFIG_UTRACE. + */ @@ -864,6 +1154,9 @@ index 0000000..f251efe + +#else /* CONFIG_UTRACE */ + ++extern void task_utrace_lock(struct task_struct *task); ++extern void task_utrace_unlock(struct task_struct *task); ++ +static inline unsigned long task_utrace_flags(struct task_struct *task) +{ + return task->utrace_flags; @@ -1033,6 +1326,7 @@ index 0000000..f251efe +#define UTRACE_ATTACH_MATCH_MASK 0x000f +#define UTRACE_ATTACH_CREATE 0x0010 /* Attach a new engine. */ +#define UTRACE_ATTACH_EXCLUSIVE 0x0020 /* Refuse if existing match. */ ++#define UTRACE_ATTACH_ATOMIC 0x0040 /* For _CREATE, don't sleep */ + +/** + * struct utrace_engine - per-engine structure @@ -1422,14 +1716,78 @@ index 0000000..f251efe + +#endif /* CONFIG_UTRACE */ + ++static inline void utrace_release_task(struct task_struct *task) ++{ ++ /* see utrace_add_engine() about this barrier */ ++ smp_mb(); ++ if (task_utrace_flags(task)) ++ utrace_maybe_reap(task, task_utrace_struct(task), true); ++} ++ ++static inline void utrace_exit_notify(struct task_struct *task, ++ int signal, int group_dead) ++{ ++ /* ++ * If utrace_set_events() was just called to enable ++ * UTRACE_EVENT(DEATH), then we are obliged to call ++ * utrace_report_death() and not miss it. utrace_set_events() ++ * checks @task->exit_state under tasklist_lock to synchronize ++ * with exit_notify(), the caller. ++ */ ++ if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) ++ utrace_report_death(task, group_dead, signal); ++} ++ ++/** ++ * utrace_end_stop - report about return from STOPPED/TRACED ++ * ++ * This is called by do_signal_stop() and ptrace_stop after wakeup. ++ */ ++static inline void utrace_end_stop(void) ++{ ++ if (task_utrace_flags(current)) ++ utrace_finish_stop(); ++} ++ ++/** ++ * utrace_hook_signal - deliver synthetic signal to traced task ++ * @task: @current ++ * @regs: task_pt_regs(@current) ++ * @info: details of synthetic signal ++ * @return_ka: sigaction for synthetic signal ++ * ++ * Return zero to check for a real pending signal normally. ++ * Return -1 after releasing the siglock to repeat the check. ++ * Return a signal number to induce an artificial signal delivery, ++ * setting *@info and *@return_ka to specify its details and behavior. ++ * ++ * The @return_ka->sa_handler value controls the disposition of the ++ * signal, no matter the signal number. For %SIG_DFL, the return value ++ * is a representative signal to indicate the behavior (e.g. %SIGTERM ++ * for death, %SIGQUIT for core dump, %SIGSTOP for job control stop, ++ * %SIGTSTP for stop unless in an orphaned pgrp), but the signal number ++ * reported will be @info->si_signo instead. ++ * ++ * Called with @task->sighand->siglock held, before dequeuing pending signals. ++ */ ++static inline int utrace_hook_signal(struct task_struct *task, ++ struct pt_regs *regs, ++ siginfo_t *info, ++ struct k_sigaction *return_ka) ++{ ++ if (unlikely(task_utrace_flags(task))) ++ return utrace_get_signal(task, regs, info, return_ka); ++ return 0; ++} ++ +#endif /* linux/utrace.h */ diff --git a/init/Kconfig b/init/Kconfig -index 43298f9..3f670e5 100644 +index 3f42cd6..5f4f92e 100644 --- a/init/Kconfig +++ b/init/Kconfig -@@ -372,6 +372,15 @@ config AUDIT_TREE - depends on AUDITSYSCALL - select FSNOTIFY +@@ -386,6 +386,15 @@ config AUDIT_LOGINUID_IMMUTABLE + one to drop potentially dangerous capabilites from the login tasks, + but may not be backwards compatible with older init systems. +config UTRACE + bool "Infrastructure for tracing and debugging user processes" @@ -1444,10 +1802,10 @@ index 43298f9..3f670e5 100644 menu "RCU Subsystem" diff --git a/kernel/Makefile b/kernel/Makefile -index e898c5b..e43bbfb 100644 +index 2d9de86..6c6749d 100644 --- a/kernel/Makefile +++ b/kernel/Makefile -@@ -68,6 +68,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o +@@ -67,6 +67,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o obj-$(CONFIG_SMP) += stop_machine.o obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o @@ -1455,12 +1813,418 @@ index e898c5b..e43bbfb 100644 obj-$(CONFIG_AUDIT) += audit.o auditfilter.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o obj-$(CONFIG_AUDIT_WATCH) += audit_watch.o +diff --git a/kernel/exit.c b/kernel/exit.c +index 4b4042f..b1e0518 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -169,6 +169,8 @@ void release_task(struct task_struct * p) + struct task_struct *leader; + int zap_leader; + repeat: ++ utrace_release_task(p); ++ + /* don't need to get the RCU readlock here - the process is dead and + * can't be modifying its own credentials. But shut RCU-lockdep up */ + rcu_read_lock(); +@@ -857,6 +859,8 @@ static void exit_notify(struct task_struct *tsk, int group_dead) + wake_up_process(tsk->signal->group_exit_task); + write_unlock_irq(&tasklist_lock); + ++ utrace_exit_notify(tsk, autoreap ? -1 : SIGCHLD, group_dead); ++ + /* If the process is dead, release it - nobody will wait for it */ + if (autoreap) + release_task(tsk); +@@ -910,6 +914,7 @@ void do_exit(long code) + */ + set_fs(USER_DS); + ++ UTRACE_HOOK(current, EXIT, report_exit(&code)); + ptrace_event(PTRACE_EVENT_EXIT, code); + + validate_creds_for_do_exit(tsk); +diff --git a/kernel/fork.c b/kernel/fork.c +index e2cd3e2..fa40928 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -67,6 +67,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -170,6 +171,8 @@ void free_task(struct task_struct *tsk) + free_thread_info(tsk->stack); + rt_mutex_debug_task_free(tsk); + ftrace_graph_exit_task(tsk); ++ if (task_utrace_struct(tsk)) ++ utrace_free_task(tsk); + free_task_struct(tsk); + } + EXPORT_SYMBOL(free_task); +@@ -1115,6 +1118,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, + if (!p) + goto fork_out; + ++ utrace_init_task(p); ++ + ftrace_graph_init_task(p); + + rt_mutex_init_task(p); +@@ -1583,6 +1583,8 @@ long do_fork(unsigned long clone_flags, + get_task_struct(p); + } + ++ UTRACE_HOOK(current, CLONE, report_clone(clone_flags, p)); ++ + wake_up_new_task(p); + + /* forking complete and child started to run, tell ptracer */ +@@ -1561,6 +1568,8 @@ long do_fork(unsigned long clone_flags, + wake_up_new_task(p); + + /* forking complete and child started to run, tell ptracer */ ++ if (clone_flags & CLONE_VFORK) ++ UTRACE_HOOK(current, CLONE, finish_vfork(current)); + if (unlikely(trace)) + ptrace_event(trace, nr); + +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index 00ab2ca..a7024b8 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -24,7 +24,34 @@ + #include + #include + #include ++#include + ++void ptrace_signal_wake_up(struct task_struct *p, int quiescent) ++{ ++ unsigned int state; ++ ++ set_tsk_thread_flag(p, TIF_SIGPENDING); ++ ++ state = TASK_INTERRUPTIBLE; ++ if (quiescent) ++ state |= (__TASK_STOPPED | __TASK_TRACED); ++ if (!wake_up_quiescent(p, state)) ++ kick_process(p); ++} ++ ++static void ptrace_set_syscall_trace(struct task_struct *p, bool on) ++{ ++ task_utrace_lock(p); ++ if (on) { ++ p->ptrace |= PT_SYSCALL_TRACE; ++ set_tsk_thread_flag(p, TIF_SYSCALL_TRACE); ++ } else { ++ p->ptrace &= ~PT_SYSCALL_TRACE; ++ if (!(task_utrace_flags(p) & UTRACE_EVENT_SYSCALL)) ++ clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); ++ } ++ task_utrace_unlock(p); ++} + + static int ptrace_trapping_sleep_fn(void *flags) + { +@@ -117,7 +144,7 @@ void __ptrace_unlink(struct task_struct *child) + * TASK_KILLABLE sleeps. + */ + if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child)) +- signal_wake_up(child, task_is_traced(child)); ++ ptrace_signal_wake_up(child, task_is_traced(child)); + + spin_unlock(&child->sighand->siglock); + } +@@ -315,7 +342,7 @@ static int ptrace_attach(struct task_struct *task, long request, + */ + if (task_is_stopped(task) && + task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING)) +- signal_wake_up(task, 1); ++ ptrace_signal_wake_up(task, 1); + + spin_unlock(&task->sighand->siglock); + +@@ -425,7 +452,7 @@ static int ptrace_detach(struct task_struct *child, unsigned int data) + + /* Architecture-specific hardware disable .. */ + ptrace_disable(child); +- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); ++ ptrace_set_syscall_trace(child, false); + + write_lock_irq(&tasklist_lock); + /* +@@ -608,13 +635,12 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info) + static int ptrace_resume(struct task_struct *child, long request, + unsigned long data) + { ++ unsigned long flags; ++ + if (!valid_signal(data)) + return -EIO; + +- if (request == PTRACE_SYSCALL) +- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); +- else +- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); ++ ptrace_set_syscall_trace(child, request == PTRACE_SYSCALL); + + #ifdef TIF_SYSCALL_EMU + if (request == PTRACE_SYSEMU || request == PTRACE_SYSEMU_SINGLESTEP) +@@ -623,20 +649,23 @@ static int ptrace_resume(struct task_struct *child, long request, + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); + #endif + ++ child->ptrace &= ~(PT_SINGLE_STEP | PT_SINGLE_BLOCK); + if (is_singleblock(request)) { + if (unlikely(!arch_has_block_step())) + return -EIO; +- user_enable_block_step(child); ++ child->ptrace |= PT_SINGLE_BLOCK; + } else if (is_singlestep(request) || is_sysemu_singlestep(request)) { + if (unlikely(!arch_has_single_step())) + return -EIO; +- user_enable_single_step(child); +- } else { +- user_disable_single_step(child); ++ child->ptrace |= PT_SINGLE_STEP; + } + + child->exit_code = data; +- wake_up_state(child, __TASK_TRACED); ++ ++ if (lock_task_sighand(child, &flags)) { ++ wake_up_quiescent(child, __TASK_TRACED); ++ unlock_task_sighand(child, &flags); ++ } + + return 0; + } +@@ -744,7 +773,7 @@ int ptrace_request(struct task_struct *child, long request, + * tracee into STOP. + */ + if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP))) +- signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); ++ ptrace_signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); + + unlock_task_sighand(child, &flags); + ret = 0; +@@ -770,7 +799,7 @@ int ptrace_request(struct task_struct *child, long request, + * start of this trap and now. Trigger re-trap. + */ + if (child->jobctl & JOBCTL_TRAP_NOTIFY) +- signal_wake_up(child, true); ++ ptrace_signal_wake_up(child, true); + ret = 0; + } + unlock_task_sighand(child, &flags); +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 5255c9d..f1719b8 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -1167,7 +1167,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) + * is actually now running somewhere else! + */ + while (task_running(rq, p)) { +- if (match_state && unlikely(p->state != match_state)) ++ if (match_state && !likely(p->state & match_state)) + return 0; + cpu_relax(); + } +diff --git a/kernel/signal.c b/kernel/signal.c +index c73c428..0508d93 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -88,7 +88,7 @@ static int sig_ignored(struct task_struct *t, int sig, int from_ancestor_ns) + /* + * Tracers may want to know about even ignored signals. + */ +- return !t->ptrace; ++ return !t->ptrace && !UTRACE_FLAG(t, SIGNAL_IGN); + } + + /* +@@ -151,6 +151,11 @@ void recalc_sigpending_and_wake(struct task_struct *t) + + void recalc_sigpending(void) + { ++ if (task_utrace_flags(current) && utrace_interrupt_pending()) { ++ set_thread_flag(TIF_SIGPENDING); ++ return; ++ } ++ + if (!recalc_sigpending_tsk(current) && !freezing(current)) + clear_thread_flag(TIF_SIGPENDING); + +@@ -495,7 +500,7 @@ int unhandled_signal(struct task_struct *tsk, int sig) + if (handler != SIG_IGN && handler != SIG_DFL) + return 0; + /* if ptraced, let the tracer determine */ +- return !tsk->ptrace; ++ return !tracehook_consider_fatal_signal(tsk, sig); + } + + /* +@@ -697,6 +702,29 @@ void signal_wake_up(struct task_struct *t, int resume) + kick_process(t); + } + ++#define STATE_QUIESCENT (__TASK_STOPPED | __TASK_TRACED | __TASK_UTRACED) ++/* ++ * wakes up the STOPPED/TRACED task, must be called with ->siglock held. ++ */ ++int wake_up_quiescent(struct task_struct *p, unsigned int state) ++{ ++ unsigned int quiescent = (p->state & STATE_QUIESCENT); ++ ++ WARN_ON(state & ~(STATE_QUIESCENT | TASK_INTERRUPTIBLE)); ++ ++ if (quiescent) { ++ state &= ~TASK_INTERRUPTIBLE; ++ if ((quiescent & ~state) != 0) { ++ p->state &= ~state; ++ WARN_ON(!(p->state & STATE_QUIESCENT)); ++ WARN_ON(!(p->state & TASK_WAKEKILL)); ++ return 0; ++ } ++ } ++ ++ return wake_up_state(p, state); ++} ++ + /* + * Remove signals in mask from the pending set and queue. + * Returns 1 if any signals were found. +@@ -842,7 +870,7 @@ static void ptrace_trap_notify(struct task_struct *t) + assert_spin_locked(&t->sighand->siglock); + + task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY); +- signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); ++ ptrace_signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); + } + + /* +@@ -884,7 +912,7 @@ static int prepare_signal(int sig, struct task_struct *p, int from_ancestor_ns) + task_clear_jobctl_pending(t, JOBCTL_STOP_PENDING); + rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending); + if (likely(!(t->ptrace & PT_SEIZED))) +- wake_up_state(t, __TASK_STOPPED); ++ wake_up_quiescent(t, __TASK_STOPPED); + else + ptrace_trap_notify(t); + } while_each_thread(p, t); +@@ -983,7 +1011,7 @@ static void complete_signal(int sig, struct task_struct *p, int group) + if (sig_fatal(p, sig) && + !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) && + !sigismember(&t->real_blocked, sig) && +- (sig == SIGKILL || !t->ptrace)) { ++ (sig == SIGKILL || !tracehook_consider_fatal_signal(t, sig))) { + /* + * This signal will be fatal to the whole group. + */ +@@ -1913,10 +1941,34 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) + if (gstop_done) + do_notify_parent_cldstop(current, false, why); + +- __set_current_state(TASK_RUNNING); ++ spin_lock_irq(¤t->sighand->siglock); ++ wake_up_quiescent(current, __TASK_TRACED); ++ spin_unlock_irq(¤t->sighand->siglock); ++ + if (clear_code) + current->exit_code = 0; + read_unlock(&tasklist_lock); ++ ++ /* ++ * It is possible that __TASK_UTRACED was added by utrace ++ * while we were __TASK_TRACED and before we take ->siglock ++ * for wake_up_quiescent(), we need to block in this case. ++ * Otherwise this is unnecessary but absolutely harmless. ++ */ ++ schedule(); ++ } ++ ++ utrace_end_stop(); ++ ++ if (current->ptrace & PT_SINGLE_BLOCK) ++ user_enable_block_step(current); ++ else if (current->ptrace & PT_SINGLE_STEP) ++ user_enable_single_step(current); ++ else { ++ user_disable_single_step(current); ++ /* if utrace needs the stepping it should reassert */ ++ if (task_utrace_flags(current)) ++ set_thread_flag(TIF_NOTIFY_RESUME); + } + + /* +@@ -2081,6 +2133,9 @@ static bool do_signal_stop(int signr) + + /* Now we don't run again until woken by SIGCONT or SIGKILL */ + schedule(); ++ ++ utrace_end_stop(); ++ + return true; + } else { + /* +@@ -2231,17 +2286,27 @@ relock: + for (;;) { + struct k_sigaction *ka; + +- if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) && +- do_signal_stop(0)) ++ signr = utrace_hook_signal(current, regs, info, return_ka); ++ if (unlikely(signr < 0)) + goto relock; + +- if (unlikely(current->jobctl & JOBCTL_TRAP_MASK)) { +- do_jobctl_trap(); +- spin_unlock_irq(&sighand->siglock); +- goto relock; +- } ++ if (unlikely(signr != 0)) ++ ka = return_ka; ++ else { ++ if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) && ++ do_signal_stop(0)) ++ goto relock; ++ ++ if (unlikely(current->jobctl & JOBCTL_TRAP_MASK)) { ++ do_jobctl_trap(); ++ spin_unlock_irq(&sighand->siglock); ++ goto relock; ++ } + +- signr = dequeue_signal(current, ¤t->blocked, info); ++ signr = dequeue_signal(current, ¤t->blocked, info); ++ ++ ka = &sighand->action[signr-1]; ++ } + + if (!signr) + break; /* will return 0 */ +@@ -2251,9 +2316,9 @@ relock: + regs, cookie); + if (!signr) + continue; +- } + +- ka = &sighand->action[signr-1]; ++ ka = &sighand->action[signr-1]; ++ } + + /* Trace actually delivered signals. */ + trace_signal_deliver(signr, info, ka); diff --git a/kernel/utrace.c b/kernel/utrace.c new file mode 100644 -index 0000000..ef856c9 +index 0000000..a169e1b --- /dev/null +++ b/kernel/utrace.c -@@ -0,0 +1,2440 @@ +@@ -0,0 +1,2466 @@ +/* + * utrace infrastructure interface for debugging user processes + * @@ -1542,6 +2306,32 @@ index 0000000..ef856c9 +} +module_init(utrace_init); + ++void task_utrace_lock(struct task_struct *task) ++{ ++ struct utrace *utrace = task_utrace_struct(task); ++ ++ if (!utrace) { ++ task_lock(task); ++ utrace = task_utrace_struct(task); ++ if (!utrace) ++ return; ++ ++ task_unlock(task); ++ } ++ ++ spin_lock(&utrace->lock); ++} ++ ++void task_utrace_unlock(struct task_struct *task) ++{ ++ struct utrace *utrace = task_utrace_struct(task); ++ ++ if (utrace) ++ spin_unlock(&utrace->lock); ++ else ++ task_unlock(task); ++} ++ +/* + * Set up @task.utrace for the first time. We can have races + * between two utrace_attach_task() calls here. The task_lock() @@ -1550,9 +2340,9 @@ index 0000000..ef856c9 + * + * This returns false only in case of a memory allocation failure. + */ -+static bool utrace_task_alloc(struct task_struct *task) ++static bool utrace_task_alloc(struct task_struct *task, gfp_t gfp_flags) +{ -+ struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, GFP_KERNEL); ++ struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, gfp_flags); + if (unlikely(!utrace)) + return false; + spin_lock_init(&utrace->lock); @@ -1732,6 +2522,7 @@ index 0000000..ef856c9 +{ + struct utrace *utrace = task_utrace_struct(target); + struct utrace_engine *engine; ++ gfp_t gfp_flags; + int ret; + + if (!(flags & UTRACE_ATTACH_CREATE)) { @@ -1754,13 +2545,16 @@ index 0000000..ef856c9 + */ + return ERR_PTR(-EPERM); + ++ gfp_flags = (flags & UTRACE_ATTACH_ATOMIC) ++ ? GFP_ATOMIC : GFP_KERNEL; ++ + if (!utrace) { -+ if (unlikely(!utrace_task_alloc(target))) ++ if (unlikely(!utrace_task_alloc(target, gfp_flags))) + return ERR_PTR(-ENOMEM); + utrace = task_utrace_struct(target); + } + -+ engine = kmem_cache_alloc(utrace_engine_cachep, GFP_KERNEL); ++ engine = kmem_cache_alloc(utrace_engine_cachep, gfp_flags); + if (unlikely(!engine)) + return ERR_PTR(-ENOMEM); + @@ -1925,6 +2719,8 @@ index 0000000..ef856c9 + */ +#define ENGINE_STOP (1UL << _UTRACE_NEVENTS) + ++#define task_is_utraced(task) ((task->state & __TASK_UTRACED) != 0) ++ +static void mark_engine_wants_stop(struct task_struct *task, + struct utrace_engine *engine) +{ @@ -2039,7 +2835,7 @@ index 0000000..ef856c9 + + ret = 0; + if ((old_flags & ~events) && target != current && -+ !task_is_stopped_or_traced(target) && !target->exit_state) { ++ !task_is_utraced(target) && !target->exit_state) { + /* + * This barrier ensures that our engine->flags changes + * have hit before we examine utrace->reporting, @@ -2086,21 +2882,21 @@ index 0000000..ef856c9 + */ +static bool utrace_do_stop(struct task_struct *target, struct utrace *utrace) +{ -+ if (task_is_stopped(target)) { ++ if (task_is_stopped_or_traced(target)) { + /* + * Stopped is considered quiescent; when it wakes up, it will + * go through utrace_finish_stop() before doing anything else. + */ + spin_lock_irq(&target->sighand->siglock); -+ if (likely(task_is_stopped(target))) -+ __set_task_state(target, TASK_TRACED); ++ if (likely(task_is_stopped_or_traced(target))) ++ target->state |= TASK_UTRACED; + spin_unlock_irq(&target->sighand->siglock); + } else if (utrace->resume > UTRACE_REPORT) { + utrace->resume = UTRACE_REPORT; + set_notify_resume(target); + } + -+ return task_is_traced(target); ++ return task_is_utraced(target); +} + +/* @@ -2111,11 +2907,7 @@ index 0000000..ef856c9 +{ + lockdep_assert_held(&utrace->lock); + spin_lock_irq(&target->sighand->siglock); -+ if (target->signal->flags & SIGNAL_STOP_STOPPED || -+ target->signal->group_stop_count) -+ target->state = TASK_STOPPED; -+ else -+ wake_up_state(target, __TASK_TRACED); ++ wake_up_quiescent(target, __TASK_UTRACED); + spin_unlock_irq(&target->sighand->siglock); +} + @@ -2162,6 +2954,7 @@ index 0000000..ef856c9 + BUG_ON(utrace->death); + flags &= UTRACE_EVENT(REAP); + } else if (!(flags & UTRACE_EVENT_SYSCALL) && ++ !(task->ptrace & PT_SYSCALL_TRACE) && + test_tsk_thread_flag(task, TIF_SYSCALL_TRACE)) { + clear_tsk_thread_flag(task, TIF_SYSCALL_TRACE); + } @@ -2177,7 +2970,7 @@ index 0000000..ef856c9 + /* + * If no more engines want it stopped, wake it up. + */ -+ if (task_is_traced(task) && !(flags & ENGINE_STOP)) { ++ if (task_is_utraced(task) && !(flags & ENGINE_STOP)) { + /* + * It just resumes, so make sure single-step + * is not left set. @@ -2206,7 +2999,7 @@ index 0000000..ef856c9 +void utrace_finish_stop(void) +{ + /* -+ * If we were task_is_traced() and then SIGKILL'ed, make ++ * If we were task_is_utraced() and then SIGKILL'ed, make + * sure we do nothing until the tracer drops utrace->lock. + */ + if (unlikely(__fatal_signal_pending(current))) { @@ -2216,7 +3009,7 @@ index 0000000..ef856c9 +} + +/* -+ * Perform %UTRACE_STOP, i.e. block in TASK_TRACED until woken up. ++ * Perform %UTRACE_STOP, i.e. block in TASK_UTRACED until woken up. + * @task == current, @utrace == current->utrace, which is not locked. + * Return true if we were woken up by SIGKILL even though some utrace + * engine may still want us to stay stopped. @@ -2266,15 +3059,7 @@ index 0000000..ef856c9 + return; + } + -+ __set_current_state(TASK_TRACED); -+ -+ /* -+ * If there is a group stop in progress, -+ * we must participate in the bookkeeping. -+ */ -+ if (unlikely(task->signal->group_stop_count) && -+ !--task->signal->group_stop_count) -+ task->signal->flags = SIGNAL_STOP_STOPPED; ++ __set_current_state(TASK_UTRACED); + + spin_unlock_irq(&task->sighand->siglock); + spin_unlock(&utrace->lock); @@ -2284,14 +3069,14 @@ index 0000000..ef856c9 + utrace_finish_stop(); + + /* -+ * While in TASK_TRACED, we were considered "frozen enough". ++ * While in TASK_UTRACED, we were considered "frozen enough". + * Now that we woke up, it's crucial if we're supposed to be + * frozen that we freeze now before running anything substantial. + */ + try_to_freeze(); + + /* -+ * While we were in TASK_TRACED, complete_signal() considered ++ * While we were in TASK_UTRACED, complete_signal() considered + * us "uninterested" in signal wakeups. Now make sure our + * TIF_SIGPENDING state is correct for normal running. + */ @@ -2562,7 +3347,7 @@ index 0000000..ef856c9 + if (unlikely(IS_ERR(utrace))) + return PTR_ERR(utrace); + -+ reset = task_is_traced(target); ++ reset = task_is_utraced(target); + ret = 0; + + /* @@ -3222,9 +4007,10 @@ index 0000000..ef856c9 + * For this reason, utrace_release_task checks for the event bits that get + * us here, and delays its cleanup for us to do. + */ -+void utrace_report_death(struct task_struct *task, struct utrace *utrace, -+ bool group_dead, int signal) ++void utrace_report_death(struct task_struct *task, bool group_dead, int signal) +{ ++ struct utrace *utrace = task_utrace_struct(task); ++ + INIT_REPORT(report); + + BUG_ON(!task->exit_state); @@ -3274,7 +4060,8 @@ index 0000000..ef856c9 + + case UTRACE_BLOCKSTEP: + if (likely(arch_has_block_step())) { -+ user_enable_block_step(task); ++ if (!ptrace_wants_step(task)) ++ user_enable_block_step(task); + break; + } + @@ -3287,7 +4074,8 @@ index 0000000..ef856c9 + + case UTRACE_SINGLESTEP: + if (likely(arch_has_single_step())) { -+ user_enable_single_step(task); ++ if (!ptrace_wants_step(task)) ++ user_enable_single_step(task); + } else { + /* + * This means some callback is to blame for failing @@ -3302,7 +4090,8 @@ index 0000000..ef856c9 + case UTRACE_REPORT: + case UTRACE_RESUME: + default: -+ user_disable_single_step(task); ++ if (!ptrace_wants_step(task)) ++ user_disable_single_step(task); + break; + } +} @@ -3323,7 +4112,8 @@ index 0000000..ef856c9 + * code path leads to calling into get_signal_to_deliver(), which + * implicitly reenables them by virtue of spin_unlock_irq. + */ -+ local_irq_enable(); ++ if (irqs_disabled()) /* make trace_hardirqs_on() happy */ ++ local_irq_enable(); + + /* + * If this flag is still set it's because there was a signal @@ -3499,7 +4289,7 @@ index 0000000..ef856c9 + ka = NULL; + memset(return_ka, 0, sizeof *return_ka); + } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || -+ unlikely(task->signal->group_stop_count)) { ++ unlikely(task->jobctl & JOBCTL_PENDING_MASK)) { + /* + * If no engine is interested in intercepting signals or + * we must stop, let the caller just dequeue them normally @@ -3902,3281 +4692,5 @@ index 0000000..ef856c9 + seq_printf(m, "Utrace:\t%lx\n", p->utrace_flags); +} -- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:17 2011 -Return-Path: oleg@redhat.com -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:17 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1CCED128D6B; - Mon, 21 Nov 2011 15:06:17 -0500 (EST) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id FWdJDV74o-ay; Mon, 21 Nov 2011 15:06:17 -0500 (EST) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 082081285E4; - Mon, 21 Nov 2011 15:06:17 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6E7d015251; - Mon, 21 Nov 2011 15:06:15 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:35 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:33 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 02/33] utrace: add utrace_init_task/utrace_free_task calls -Message-ID: <20111121200133.GA27759@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 -Status: RO -Content-Length: 1295 -Lines: 47 - -Add the necessary copy_process()->utrace_init_task() and -free_task()->utrace_free_task() calls. - -Originally this was the part of "utrace core" patch, but since -tracehooks are dying it doesn't make sense to reintroduce them. -Instead, just call the utrace_ helpers directly. This is fine -even without CONFIG_UTRACE, gcc is smart enough to optimize out -the code in free_task(). - -Signed-off-by: Oleg Nesterov ---- - kernel/fork.c | 5 +++++ - 1 files changed, 5 insertions(+), 0 deletions(-) - -diff --git a/kernel/fork.c b/kernel/fork.c -index ba0d172..b8719c2 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -67,6 +67,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -167,6 +168,8 @@ void free_task(struct task_struct *tsk) - free_thread_info(tsk->stack); - rt_mutex_debug_task_free(tsk); - ftrace_graph_exit_task(tsk); -+ if (task_utrace_struct(tsk)) -+ utrace_free_task(tsk); - free_task_struct(tsk); - } - EXPORT_SYMBOL(free_task); -@@ -1093,6 +1096,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, - if (!p) - goto fork_out; - -+ utrace_init_task(p); -+ - ftrace_graph_init_task(p); - - rt_mutex_init_task(p); --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:20 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:20 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8779AD87BC; - Mon, 21 Nov 2011 15:06:20 -0500 (EST) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id umzAMwRd7rMt; Mon, 21 Nov 2011 15:06:20 -0500 (EST) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 72C98D8707; - Mon, 21 Nov 2011 15:06:20 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6HAj015261; - Mon, 21 Nov 2011 15:06:18 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:39 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:36 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 03/33] tracehooks: add utrace hooks -Message-ID: <20111121200136.GA27766@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 -Status: RO -Content-Length: 2310 -Lines: 75 - -Add the necessary utrace hooks in the tracehooks which were not -removed yet. - -Signed-off-by: Oleg Nesterov ---- - include/linux/tracehook.h | 22 +++++++++++++++++++++- - 1 files changed, 21 insertions(+), 1 deletions(-) - -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index a71a292..8cc28bc 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -49,6 +49,7 @@ - #include - #include - #include -+#include - struct linux_binprm; - - /* -@@ -96,6 +97,9 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) - static inline __must_check int tracehook_report_syscall_entry( - struct pt_regs *regs) - { -+ if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && -+ utrace_report_syscall_entry(regs)) -+ return 1; - ptrace_report_syscall(regs); - return 0; - } -@@ -119,6 +123,9 @@ static inline __must_check int tracehook_report_syscall_entry( - */ - static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) - { -+ if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) -+ utrace_report_syscall_exit(regs); -+ - if (step) { - siginfo_t info; - user_single_step_siginfo(current, regs, &info); -@@ -148,6 +155,8 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, - const struct k_sigaction *ka, - struct pt_regs *regs, int stepping) - { -+ if (task_utrace_flags(current)) -+ utrace_signal_handler(current, stepping); - if (stepping) - ptrace_notify(SIGTRAP); - } -@@ -179,10 +188,21 @@ static inline void set_notify_resume(struct task_struct *task) - * asynchronously, this will be called again before we return to - * user mode. - * -- * Called without locks. -+ * Called without locks. However, on some machines this may be -+ * called with interrupts disabled. - */ - static inline void tracehook_notify_resume(struct pt_regs *regs) - { -+ struct task_struct *task = current; -+ /* -+ * Prevent the following store/load from getting ahead of the -+ * caller which clears TIF_NOTIFY_RESUME. This pairs with the -+ * implicit mb() before setting TIF_NOTIFY_RESUME in -+ * set_notify_resume(). -+ */ -+ smp_mb(); -+ if (task_utrace_flags(task)) -+ utrace_resume(task, regs); - } - #endif /* TIF_NOTIFY_RESUME */ - --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:23 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:23 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6559BD4FDE; - Mon, 21 Nov 2011 15:06:23 -0500 (EST) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 6BjISiO+cS1U; Mon, 21 Nov 2011 15:06:23 -0500 (EST) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 50366D4C39; - Mon, 21 Nov 2011 15:06:23 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6KT9017533; - Mon, 21 Nov 2011 15:06:21 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:42 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:39 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 04/33] tracehooks: reintroduce - tracehook_consider_fatal_signal() -Message-ID: <20111121200139.GA27769@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Status: RO -Content-Length: 3257 -Lines: 90 - -Add the killed tracehook_consider_fatal_signal() back. It has multiple -callers and it is not easy add the necessary checks inline. - -Signed-off-by: Oleg Nesterov ---- - arch/s390/kernel/traps.c | 4 ++-- - include/linux/tracehook.h | 22 ++++++++++++++++++++++ - kernel/signal.c | 4 ++-- - 3 files changed, 26 insertions(+), 4 deletions(-) - -diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c -index a9807dd..f506e1b 100644 ---- a/arch/s390/kernel/traps.c -+++ b/arch/s390/kernel/traps.c -@@ -329,7 +329,7 @@ void __kprobes do_per_trap(struct pt_regs *regs) - - if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP) - return; -- if (!current->ptrace) -+ if (!tracehook_consider_fatal_signal(current, SIGTRAP)) - return; - info.si_signo = SIGTRAP; - info.si_errno = 0; -@@ -429,7 +429,7 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code, - if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) - return; - if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) { -- if (current->ptrace) { -+ if (tracehook_consider_fatal_signal(current, SIGTRAP)) { - info.si_signo = SIGTRAP; - info.si_errno = 0; - info.si_code = TRAP_BRKPT; -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 8cc28bc..ec2af67 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -161,6 +161,28 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, - ptrace_notify(SIGTRAP); - } - -+/** -+ * tracehook_consider_fatal_signal - suppress special handling of fatal signal -+ * @task: task receiving the signal -+ * @sig: signal number being sent -+ * -+ * Return nonzero to prevent special handling of this termination signal. -+ * Normally handler for signal is %SIG_DFL. It can be %SIG_IGN if @sig is -+ * ignored, in which case force_sig() is about to reset it to %SIG_DFL. -+ * When this returns zero, this signal might cause a quick termination -+ * that does not give the debugger a chance to intercept the signal. -+ * -+ * Called with or without @task->sighand->siglock held. -+ */ -+static inline int tracehook_consider_fatal_signal(struct task_struct *task, -+ int sig) -+{ -+ if (unlikely(task_utrace_flags(task) & (UTRACE_EVENT(SIGNAL_TERM) | -+ UTRACE_EVENT(SIGNAL_CORE)))) -+ return 1; -+ return task->ptrace != 0; -+} -+ - #ifdef TIF_NOTIFY_RESUME - /** - * set_notify_resume - cause tracehook_notify_resume() to be called -diff --git a/kernel/signal.c b/kernel/signal.c -index b3f78d0..d7b90cd 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -494,7 +494,7 @@ int unhandled_signal(struct task_struct *tsk, int sig) - if (handler != SIG_IGN && handler != SIG_DFL) - return 0; - /* if ptraced, let the tracer determine */ -- return !tsk->ptrace; -+ return !tracehook_consider_fatal_signal(tsk, sig); - } - - /* -@@ -982,7 +982,7 @@ static void complete_signal(int sig, struct task_struct *p, int group) - if (sig_fatal(p, sig) && - !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) && - !sigismember(&t->real_blocked, sig) && -- (sig == SIGKILL || !t->ptrace)) { -+ (sig == SIGKILL || !tracehook_consider_fatal_signal(t, sig))) { - /* - * This signal will be fatal to the whole group. - */ --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:26 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:25 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E7A2DD498A; - Mon, 21 Nov 2011 15:06:25 -0500 (EST) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 4L9zskFVsr4I; Mon, 21 Nov 2011 15:06:25 -0500 (EST) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D3487D4C39; - Mon, 21 Nov 2011 15:06:25 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6Nnp017552; - Mon, 21 Nov 2011 15:06:24 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:44 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:42 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 05/33] add utrace hooks into sig_ignored() and - recalc_sigpending() -Message-ID: <20111121200142.GA27777@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Status: RO -Content-Length: 1508 -Lines: 51 - -Add the necessary and somewhat "special" hooks into sig_ignored() and -recalc_sigpending(). Basically this restores _force_sigpending() and -_consider_ignored_signal() tracehook logic. - -Signed-off-by: Oleg Nesterov ---- - include/linux/utrace.h | 2 ++ - kernel/signal.c | 7 ++++++- - 2 files changed, 8 insertions(+), 1 deletions(-) - -diff --git a/include/linux/utrace.h b/include/linux/utrace.h -index f251efe..1b8da1c 100644 ---- a/include/linux/utrace.h -+++ b/include/linux/utrace.h -@@ -107,6 +107,8 @@ bool utrace_report_syscall_entry(struct pt_regs *); - void utrace_report_syscall_exit(struct pt_regs *); - void utrace_signal_handler(struct task_struct *, int); - -+#define UTRACE_FLAG(task, ev) (task_utrace_flags(task) & UTRACE_EVENT(ev)) -+ - #ifndef CONFIG_UTRACE - - /* -diff --git a/kernel/signal.c b/kernel/signal.c -index d7b90cd..8594cb2 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -87,7 +87,7 @@ static int sig_ignored(struct task_struct *t, int sig, int from_ancestor_ns) - /* - * Tracers may want to know about even ignored signals. - */ -- return !t->ptrace; -+ return !t->ptrace && !UTRACE_FLAG(t, SIGNAL_IGN); - } - - /* -@@ -150,6 +150,11 @@ void recalc_sigpending_and_wake(struct task_struct *t) - - void recalc_sigpending(void) - { -+ if (task_utrace_flags(current) && utrace_interrupt_pending()) { -+ set_thread_flag(TIF_SIGPENDING); -+ return; -+ } -+ - if (!recalc_sigpending_tsk(current) && !freezing(current)) - clear_thread_flag(TIF_SIGPENDING); - --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:28 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:28 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6E4A6D4F4A; - Mon, 21 Nov 2011 15:06:28 -0500 (EST) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id vEeGLyK1+rX9; Mon, 21 Nov 2011 15:06:28 -0500 (EST) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5AD50D4C39; - Mon, 21 Nov 2011 15:06:28 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6QOB029543; - Mon, 21 Nov 2011 15:06:26 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:47 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:45 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 06/33] restore the EXEC/EXIT/CLONE utrace hooks -Message-ID: <20111121200145.GA27780@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -Status: RO -Content-Length: 2383 -Lines: 83 - -Restore the "trivial" EXEC/EXIT/CLONE utrace hooks. Add the -simple helper, UTRACE_HOOK(), to minimize the changes. - -Signed-off-by: Oleg Nesterov ---- - fs/exec.c | 5 ++++- - include/linux/utrace.h | 6 ++++++ - kernel/exit.c | 1 + - kernel/fork.c | 4 ++++ - 4 files changed, 15 insertions(+), 1 deletions(-) - -diff --git a/fs/exec.c b/fs/exec.c -index 3625464..7d8f8bd 100644 ---- a/fs/exec.c -+++ b/fs/exec.c -@@ -1397,9 +1397,12 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) - */ - bprm->recursion_depth = depth; - if (retval >= 0) { -- if (depth == 0) -+ if (depth == 0) { -+ UTRACE_HOOK(current, EXEC, -+ report_exec(fmt, bprm, regs)); - ptrace_event(PTRACE_EVENT_EXEC, - old_pid); -+ } - put_binfmt(fmt); - allow_write_access(bprm->file); - if (bprm->file) -diff --git a/include/linux/utrace.h b/include/linux/utrace.h -index 1b8da1c..9ac0b1b 100644 ---- a/include/linux/utrace.h -+++ b/include/linux/utrace.h -@@ -109,6 +109,12 @@ void utrace_signal_handler(struct task_struct *, int); - - #define UTRACE_FLAG(task, ev) (task_utrace_flags(task) & UTRACE_EVENT(ev)) - -+#define UTRACE_HOOK(task, ev, callback) \ -+ do { \ -+ if (UTRACE_FLAG(task, ev)) \ -+ utrace_ ## callback; \ -+ } while (0) -+ - #ifndef CONFIG_UTRACE - - /* -diff --git a/kernel/exit.c b/kernel/exit.c -index d0b7d98..f5eba3b 100644 ---- a/kernel/exit.c -+++ b/kernel/exit.c -@@ -911,6 +911,7 @@ NORET_TYPE void do_exit(long code) - */ - set_fs(USER_DS); - -+ UTRACE_HOOK(current, EXIT, report_exit(&code)); - ptrace_event(PTRACE_EVENT_EXIT, code); - - validate_creds_for_do_exit(tsk); -diff --git a/kernel/fork.c b/kernel/fork.c -index b8719c2..09d5049 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -1535,6 +1535,8 @@ long do_fork(unsigned long clone_flags, - - audit_finish_fork(p); - -+ UTRACE_HOOK(current, CLONE, report_clone(clone_flags, p)); -+ - /* - * We set PF_STARTING at creation in case tracing wants to - * use this to distinguish a fully live task from one that -@@ -1546,6 +1548,8 @@ long do_fork(unsigned long clone_flags, - wake_up_new_task(p); - - /* forking complete and child started to run, tell ptracer */ -+ if (clone_flags & CLONE_VFORK) -+ UTRACE_HOOK(current, CLONE, finish_vfork(current)); - if (unlikely(trace)) - ptrace_event(trace, nr); - --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:30 2011 -Return-Path: oleg@redhat.com -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:30 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D248D1284E0; - Mon, 21 Nov 2011 15:06:30 -0500 (EST) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id divvekTmLScS; Mon, 21 Nov 2011 15:06:30 -0500 (EST) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BDC9412800E; - Mon, 21 Nov 2011 15:06:30 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6Shj029546; - Mon, 21 Nov 2011 15:06:29 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:49 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:47 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 07/33] utrace: utrace_report_death() can use - task_utrace_struct() -Message-ID: <20111121200147.GA27787@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -Status: RO -Content-Length: 1692 -Lines: 44 - -utrace_report_death() assumes that the caller (exit_notify) should -pass task->utrace as an argument. This is no longer needed, it can -safely do task_utrace_struct(). This way we avoid the nasty changes -in exit_notify(). - -Signed-off-by: Oleg Nesterov ---- - include/linux/utrace.h | 2 +- - kernel/utrace.c | 5 +++-- - 2 files changed, 4 insertions(+), 3 deletions(-) - -diff --git a/include/linux/utrace.h b/include/linux/utrace.h -index 9ac0b1b..9a2e2f4 100644 ---- a/include/linux/utrace.h -+++ b/include/linux/utrace.h -@@ -99,7 +99,7 @@ int utrace_get_signal(struct task_struct *, struct pt_regs *, - void utrace_report_clone(unsigned long, struct task_struct *); - void utrace_finish_vfork(struct task_struct *); - void utrace_report_exit(long *exit_code); --void utrace_report_death(struct task_struct *, struct utrace *, bool, int); -+void utrace_report_death(struct task_struct *, bool, int); - void utrace_report_jctl(int notify, int type); - void utrace_report_exec(struct linux_binfmt *, struct linux_binprm *, - struct pt_regs *regs); -diff --git a/kernel/utrace.c b/kernel/utrace.c -index ef856c9..1e750ad 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -1759,9 +1759,10 @@ void utrace_report_exit(long *exit_code) - * For this reason, utrace_release_task checks for the event bits that get - * us here, and delays its cleanup for us to do. - */ --void utrace_report_death(struct task_struct *task, struct utrace *utrace, -- bool group_dead, int signal) -+void utrace_report_death(struct task_struct *task, bool group_dead, int signal) - { -+ struct utrace *utrace = task_utrace_struct(task); -+ - INIT_REPORT(report); - - BUG_ON(!task->exit_state); --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:33 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:33 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 62E1BD50A3; - Mon, 21 Nov 2011 15:06:33 -0500 (EST) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id FB36YkOAHDc5; Mon, 21 Nov 2011 15:06:33 -0500 (EST) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4D161D4C39; - Mon, 21 Nov 2011 15:06:33 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6VBW022130; - Mon, 21 Nov 2011 15:06:31 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:52 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:50 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 08/33] restore the DEATH/REAP utrace hooks -Message-ID: <20111121200150.GA27790@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Status: RO -Content-Length: 2346 -Lines: 70 - -Restore the necessary hooks in release_task() and exit_notify(), -add the corresponding helpers into utrace.h. - -Note: the @signal argument passed to ->report_death() does not -match the previous behaviour. I think this shouldn't affect the -current users, and I bet nobody can really understand what this -magic argument should actually mean anyway. - -Signed-off-by: Oleg Nesterov ---- - include/linux/utrace.h | 22 ++++++++++++++++++++++ - kernel/exit.c | 4 ++++ - 2 files changed, 26 insertions(+), 0 deletions(-) - -diff --git a/include/linux/utrace.h b/include/linux/utrace.h -index 9a2e2f4..cf13839 100644 ---- a/include/linux/utrace.h -+++ b/include/linux/utrace.h -@@ -697,4 +697,26 @@ static inline __must_check int utrace_barrier_pid(struct pid *pid, - - #endif /* CONFIG_UTRACE */ - -+static inline void utrace_release_task(struct task_struct *task) -+{ -+ /* see utrace_add_engine() about this barrier */ -+ smp_mb(); -+ if (task_utrace_flags(task)) -+ utrace_maybe_reap(task, task_utrace_struct(task), true); -+} -+ -+static inline void utrace_exit_notify(struct task_struct *task, -+ int signal, int group_dead) -+{ -+ /* -+ * If utrace_set_events() was just called to enable -+ * UTRACE_EVENT(DEATH), then we are obliged to call -+ * utrace_report_death() and not miss it. utrace_set_events() -+ * checks @task->exit_state under tasklist_lock to synchronize -+ * with exit_notify(), the caller. -+ */ -+ if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) -+ utrace_report_death(task, group_dead, signal); -+} -+ - #endif /* linux/utrace.h */ -diff --git a/kernel/exit.c b/kernel/exit.c -index f5eba3b..746c5df 100644 ---- a/kernel/exit.c -+++ b/kernel/exit.c -@@ -168,6 +168,8 @@ void release_task(struct task_struct * p) - struct task_struct *leader; - int zap_leader; - repeat: -+ utrace_release_task(p); -+ - /* don't need to get the RCU readlock here - the process is dead and - * can't be modifying its own credentials. But shut RCU-lockdep up */ - rcu_read_lock(); -@@ -858,6 +860,8 @@ static void exit_notify(struct task_struct *tsk, int group_dead) - wake_up_process(tsk->signal->group_exit_task); - write_unlock_irq(&tasklist_lock); - -+ utrace_exit_notify(tsk, autoreap ? -1 : SIGCHLD, group_dead); -+ - /* If the process is dead, release it - nobody will wait for it */ - if (autoreap) - release_task(tsk); --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:35 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:35 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D4AB3D8761; - Mon, 21 Nov 2011 15:06:35 -0500 (EST) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id TiShkH1f6rnj; Mon, 21 Nov 2011 15:06:35 -0500 (EST) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id BCB85D877F; - Mon, 21 Nov 2011 15:06:35 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6XNu015312; - Mon, 21 Nov 2011 15:06:34 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:54 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:52 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 09/33] utrace: remove jobctl bits -Message-ID: <20111121200152.GA27793@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 -Status: RO -Content-Length: 1888 -Lines: 56 - -- change utrace_get_signal() to check JOBCTL_STOP_PENDING instead of - signal->group_stop_count. With the recent changes group_stop_count - doesn't necessarily mean this task should participate in group stop. - -- remove the "participate in group stop" code from utrace_wakeup() and - utrace_stop(), this is no longer needed and wrong. - -Signed-off-by: Oleg Nesterov ---- - kernel/utrace.c | 16 ++-------------- - 1 files changed, 2 insertions(+), 14 deletions(-) - -diff --git a/kernel/utrace.c b/kernel/utrace.c -index 1e750ad..5d3974e 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -648,11 +648,7 @@ static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) - { - lockdep_assert_held(&utrace->lock); - spin_lock_irq(&target->sighand->siglock); -- if (target->signal->flags & SIGNAL_STOP_STOPPED || -- target->signal->group_stop_count) -- target->state = TASK_STOPPED; -- else -- wake_up_state(target, __TASK_TRACED); -+ wake_up_state(target, __TASK_TRACED); - spin_unlock_irq(&target->sighand->siglock); - } - -@@ -805,14 +801,6 @@ relock: - - __set_current_state(TASK_TRACED); - -- /* -- * If there is a group stop in progress, -- * we must participate in the bookkeeping. -- */ -- if (unlikely(task->signal->group_stop_count) && -- !--task->signal->group_stop_count) -- task->signal->flags = SIGNAL_STOP_STOPPED; -- - spin_unlock_irq(&task->sighand->siglock); - spin_unlock(&utrace->lock); - -@@ -2037,7 +2025,7 @@ int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, - ka = NULL; - memset(return_ka, 0, sizeof *return_ka); - } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || -- unlikely(task->signal->group_stop_count)) { -+ unlikely(task->jobctl & JOBCTL_STOP_PENDING)) { - /* - * If no engine is interested in intercepting signals or - * we must stop, let the caller just dequeue them normally --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:38 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:38 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 425CED8707; - Mon, 21 Nov 2011 15:06:38 -0500 (EST) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 9paRC+dwSflh; Mon, 21 Nov 2011 15:06:38 -0500 (EST) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2DDBCD8410; - Mon, 21 Nov 2011 15:06:38 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6a31031355; - Mon, 21 Nov 2011 15:06:36 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:56 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:55 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 10/33] ptrace: take ->siglock around s/TRACED/RUNNING/ -Message-ID: <20111121200155.GA27801@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 -Status: RO -Content-Length: 1624 -Lines: 56 - -change ptrace_resume() and ptrace_stop() to take ->siglock around changing -task->state from TRACED to RUNNING. - -With this patch __TASK_TRACED/STOPPED bits are fully protected by ->siglock, -nobody can set or clear these bits without ->siglock held. - -Signed-off-by: Oleg Nesterov ---- - kernel/ptrace.c | 8 +++++++- - kernel/signal.c | 3 +++ - 2 files changed, 10 insertions(+), 1 deletions(-) - -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 24d0447..daf47bc 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -589,6 +589,8 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info) - static int ptrace_resume(struct task_struct *child, long request, - unsigned long data) - { -+ unsigned long flags; -+ - if (!valid_signal(data)) - return -EIO; - -@@ -617,7 +619,11 @@ static int ptrace_resume(struct task_struct *child, long request, - } - - child->exit_code = data; -- wake_up_state(child, __TASK_TRACED); -+ -+ if (lock_task_sighand(child, &flags)) { -+ wake_up_state(child, __TASK_TRACED); -+ unlock_task_sighand(child, &flags); -+ } - - return 0; - } -diff --git a/kernel/signal.c b/kernel/signal.c -index 8594cb2..4512bb4 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -1886,7 +1886,10 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) - if (gstop_done) - do_notify_parent_cldstop(current, false, why); - -+ spin_lock_irq(¤t->sighand->siglock); - __set_current_state(TASK_RUNNING); -+ spin_unlock_irq(¤t->sighand->siglock); -+ - if (clear_code) - current->exit_code = 0; - read_unlock(&tasklist_lock); --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:40 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:40 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B0D19D877F; - Mon, 21 Nov 2011 15:06:40 -0500 (EST) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 3jv-cDBpMP5B; Mon, 21 Nov 2011 15:06:40 -0500 (EST) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9C98DD8410; - Mon, 21 Nov 2011 15:06:40 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6cHF029573; - Mon, 21 Nov 2011 15:06:39 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:01:59 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:57 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 11/33] introduce wake_up_quiescent() -Message-ID: <20111121200157.GA27805@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -Status: RO -Content-Length: 3186 -Lines: 93 - -No functional changes. Add the new helper, wake_up_quiescent(task, state), -which simply returns wake_up_state(task, state). Change all callers which -do wake_up_state(STOPPED/TRACED) to use the new helper. ptrace_stop() is -a bit special, it does __set_current_state(RUNNING) in the very unlikely -case, change it as well. - -Signed-off-by: Oleg Nesterov ---- - include/linux/signal.h | 2 ++ - kernel/ptrace.c | 2 +- - kernel/signal.c | 12 ++++++++++-- - kernel/utrace.c | 2 +- - 4 files changed, 14 insertions(+), 4 deletions(-) - -diff --git a/include/linux/signal.h b/include/linux/signal.h -index a822300..2be3712 100644 ---- a/include/linux/signal.h -+++ b/include/linux/signal.h -@@ -239,6 +239,8 @@ static inline int valid_signal(unsigned long sig) - struct timespec; - struct pt_regs; - -+extern int wake_up_quiescent(struct task_struct *p, unsigned int state); -+ - extern int next_signal(struct sigpending *pending, sigset_t *mask); - extern int do_send_sig_info(int sig, struct siginfo *info, - struct task_struct *p, bool group); -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index daf47bc..8439ef1 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -621,7 +621,7 @@ static int ptrace_resume(struct task_struct *child, long request, - child->exit_code = data; - - if (lock_task_sighand(child, &flags)) { -- wake_up_state(child, __TASK_TRACED); -+ wake_up_quiescent(child, __TASK_TRACED); - unlock_task_sighand(child, &flags); - } - -diff --git a/kernel/signal.c b/kernel/signal.c -index 4512bb4..99a6008 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -702,6 +702,14 @@ void signal_wake_up(struct task_struct *t, int resume) - } - - /* -+ * wakes up the STOPPED/TRACED task, must be called with ->siglock held. -+ */ -+int wake_up_quiescent(struct task_struct *p, unsigned int state) -+{ -+ return wake_up_state(p, state); -+} -+ -+/* - * Remove signals in mask from the pending set and queue. - * Returns 1 if any signals were found. - * -@@ -888,7 +896,7 @@ static int prepare_signal(int sig, struct task_struct *p, int from_ancestor_ns) - task_clear_jobctl_pending(t, JOBCTL_STOP_PENDING); - rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending); - if (likely(!(t->ptrace & PT_SEIZED))) -- wake_up_state(t, __TASK_STOPPED); -+ wake_up_quiescent(t, __TASK_STOPPED); - else - ptrace_trap_notify(t); - } while_each_thread(p, t); -@@ -1887,7 +1895,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) - do_notify_parent_cldstop(current, false, why); - - spin_lock_irq(¤t->sighand->siglock); -- __set_current_state(TASK_RUNNING); -+ wake_up_quiescent(current, __TASK_TRACED); - spin_unlock_irq(¤t->sighand->siglock); - - if (clear_code) -diff --git a/kernel/utrace.c b/kernel/utrace.c -index 5d3974e..cebc390 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -648,7 +648,7 @@ static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) - { - lockdep_assert_held(&utrace->lock); - spin_lock_irq(&target->sighand->siglock); -- wake_up_state(target, __TASK_TRACED); -+ wake_up_quiescent(target, __TASK_TRACED); - spin_unlock_irq(&target->sighand->siglock); - } - --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:43 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:43 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6488BD514C; - Mon, 21 Nov 2011 15:06:43 -0500 (EST) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id TKQUj5mU4NYM; Mon, 21 Nov 2011 15:06:43 -0500 (EST) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4EC82D5000; - Mon, 21 Nov 2011 15:06:43 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6fp6015343; - Mon, 21 Nov 2011 15:06:41 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:02 +0100 (CET) -Date: Mon, 21 Nov 2011 21:01:59 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 12/33] introduce ptrace_signal_wake_up() -Message-ID: <20111121200159.GA27812@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 -Status: RO -Content-Length: 3670 -Lines: 113 - -Add the new helper, ptrace_signal_wake_up(), change ptrace.c/signal.c -to use it instead of signal_wake_up() to wake up a STOPPED/TRACED task. - -The new helper does almost the same, except: - - - it doesn't use the TASK_WAKEKILL bit to wake up the TRACED - or STOPPED task, it uses __TASK_STOPPED | __TASK_TRACED - explicitly. This is what ptrace actually wants, it should - never wake up a TASK_KILLABLE task. - - This should be cleanuped upatream, signal_wake_up() should - take the state as an argument, not a boolean. Until then - we add a new static helper. - - - it uses wake_up_quiescent() instead of wake_up_state(). - -Thereafter every change from STOPPED/TRACED to RUNNING is done via -wake_up_quiescent(). - -Signed-off-by: Oleg Nesterov ---- - include/linux/ptrace.h | 1 + - kernel/ptrace.c | 20 ++++++++++++++++---- - kernel/signal.c | 2 +- - 3 files changed, 18 insertions(+), 5 deletions(-) - -diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h -index 800f113..6d9282a 100644 ---- a/include/linux/ptrace.h -+++ b/include/linux/ptrace.h -@@ -113,6 +113,7 @@ - #include /* For unlikely. */ - #include /* For struct task_struct. */ - -+extern void ptrace_signal_wake_up(struct task_struct *p, int quiescent); - - extern long arch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data); -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 8439ef1..a464ab5 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -25,6 +25,18 @@ - #include - #include - -+void ptrace_signal_wake_up(struct task_struct *p, int quiescent) -+{ -+ unsigned int state; -+ -+ set_tsk_thread_flag(p, TIF_SIGPENDING); -+ -+ state = TASK_INTERRUPTIBLE; -+ if (quiescent) -+ state |= (__TASK_STOPPED | __TASK_TRACED); -+ if (!wake_up_quiescent(p, state)) -+ kick_process(p); -+} - - static int ptrace_trapping_sleep_fn(void *flags) - { -@@ -106,7 +118,7 @@ void __ptrace_unlink(struct task_struct *child) - * TASK_KILLABLE sleeps. - */ - if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child)) -- signal_wake_up(child, task_is_traced(child)); -+ ptrace_signal_wake_up(child, task_is_traced(child)); - - spin_unlock(&child->sighand->siglock); - } -@@ -296,7 +308,7 @@ static int ptrace_attach(struct task_struct *task, long request, - */ - if (task_is_stopped(task) && - task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING)) -- signal_wake_up(task, 1); -+ ptrace_signal_wake_up(task, 1); - - spin_unlock(&task->sighand->siglock); - -@@ -731,7 +743,7 @@ int ptrace_request(struct task_struct *child, long request, - * tracee into STOP. - */ - if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP))) -- signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); -+ ptrace_signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); - - unlock_task_sighand(child, &flags); - ret = 0; -@@ -757,7 +769,7 @@ int ptrace_request(struct task_struct *child, long request, - * start of this trap and now. Trigger re-trap. - */ - if (child->jobctl & JOBCTL_TRAP_NOTIFY) -- signal_wake_up(child, true); -+ ptrace_signal_wake_up(child, true); - ret = 0; - } - unlock_task_sighand(child, &flags); -diff --git a/kernel/signal.c b/kernel/signal.c -index 99a6008..7a47a93 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -854,7 +854,7 @@ static void ptrace_trap_notify(struct task_struct *t) - assert_spin_locked(&t->sighand->siglock); - - task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY); -- signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); -+ ptrace_signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); - } - - /* --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:46 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:46 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 3A7AED8410; - Mon, 21 Nov 2011 15:06:46 -0500 (EST) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id jhYAwDyYmdhg; Mon, 21 Nov 2011 15:06:46 -0500 (EST) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 25D5FD889A; - Mon, 21 Nov 2011 15:06:46 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6h29029619; - Mon, 21 Nov 2011 15:06:44 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:04 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:02 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 13/33] wait_task_inactive: treat task->state and - match_state as bitmasks -Message-ID: <20111121200202.GA27816@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -Status: RO -Content-Length: 1558 -Lines: 39 - -Change wait_task_inactive() to check "state & match_state" instead of -"state == match_state". This should not make any difference, but this -allows us to add more "stopped" bits which can be set or cleared -independently. - -IOW. wait_task_inactive() assumes that if task->state != 0, it can -only be changed to TASK_RUNNING. Currently this is true, and in this -case "state & match_state" continues to work. But, unlike the current -check, it also works if task->state has other bits set while the caller -is only interested in, say, __TASK_TRACED. - -Note: I think wait_task_inactive() should be cleanuped upstrean anyway, -nowadays we have TASK_WAKING and task->state != 0 doesn't necessarily -mean it is TASK_RUNNING. It also makes sense to exclude the !TASK_REPORT -bits during the check. Finally, probably this patch makes sense anyway -even without utrace. For example, a stopped _and_ traced thread could -have task->state = TASK_STOPPED | TASK_TRACED, this can be useful. - -Signed-off-by: Oleg Nesterov ---- - kernel/sched.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/kernel/sched.c b/kernel/sched.c -index 0e9344a..84ecc0a 100644 ---- a/kernel/sched.c -+++ b/kernel/sched.c -@@ -2443,7 +2443,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) - * is actually now running somewhere else! - */ - while (task_running(rq, p)) { -- if (match_state && unlikely(p->state != match_state)) -+ if (match_state && !likely(p->state & match_state)) - return 0; - cpu_relax(); - } --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:48 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:48 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C2934D5000; - Mon, 21 Nov 2011 15:06:48 -0500 (EST) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id ThT2PyhztDpQ; Mon, 21 Nov 2011 15:06:48 -0500 (EST) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id ACE02D4F84; - Mon, 21 Nov 2011 15:06:48 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6kdb022201; - Mon, 21 Nov 2011 15:06:47 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:07 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:05 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 14/33] introduce TASK_UTRACED state -Message-ID: <20111121200205.GA27823@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Status: RO -Content-Length: 2913 -Lines: 84 - -Introduce TASK_UTRACED state, will be used by utrace instead of TASK_TRACED. - -Note: this state is reported as "t (tracing stop)" to the user-space to -avoid the confusion. IOW, it looks like TASK_TRACED in /proc/pid/status. - -Signed-off-by: Oleg Nesterov ---- - fs/proc/array.c | 11 ++++++----- - include/linux/sched.h | 20 +++++++++++--------- - 2 files changed, 17 insertions(+), 14 deletions(-) - -diff --git a/fs/proc/array.c b/fs/proc/array.c -index f0c0ea2..e0daec4 100644 ---- a/fs/proc/array.c -+++ b/fs/proc/array.c -@@ -138,11 +138,12 @@ static const char * const task_state_array[] = { - "D (disk sleep)", /* 2 */ - "T (stopped)", /* 4 */ - "t (tracing stop)", /* 8 */ -- "Z (zombie)", /* 16 */ -- "X (dead)", /* 32 */ -- "x (dead)", /* 64 */ -- "K (wakekill)", /* 128 */ -- "W (waking)", /* 256 */ -+ "t (tracing stop)", /* 16 (stopped by utrace) */ -+ "Z (zombie)", /* 32 */ -+ "X (dead)", /* 64 */ -+ "x (dead)", /* 128 */ -+ "K (wakekill)", /* 256 */ -+ "W (waking)", /* 512 */ - }; - - static inline const char *get_task_state(struct task_struct *tsk) -diff --git a/include/linux/sched.h b/include/linux/sched.h -index 4d45f93..746b4d3 100644 ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -185,16 +185,17 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) - #define TASK_UNINTERRUPTIBLE 2 - #define __TASK_STOPPED 4 - #define __TASK_TRACED 8 -+#define __TASK_UTRACED 16 - /* in tsk->exit_state */ --#define EXIT_ZOMBIE 16 --#define EXIT_DEAD 32 -+#define EXIT_ZOMBIE 32 -+#define EXIT_DEAD 64 - /* in tsk->state again */ --#define TASK_DEAD 64 --#define TASK_WAKEKILL 128 --#define TASK_WAKING 256 --#define TASK_STATE_MAX 512 -+#define TASK_DEAD 128 -+#define TASK_WAKEKILL 256 -+#define TASK_WAKING 512 -+#define TASK_STATE_MAX 1024 - --#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKW" -+#define TASK_STATE_TO_CHAR_STR "RSDTtUZXxKW" - - extern char ___assert_task_state[1 - 2*!!( - sizeof(TASK_STATE_TO_CHAR_STR)-1 != ilog2(TASK_STATE_MAX)+1)]; -@@ -203,15 +204,16 @@ extern char ___assert_task_state[1 - 2*!!( - #define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE) - #define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED) - #define TASK_TRACED (TASK_WAKEKILL | __TASK_TRACED) -+#define TASK_UTRACED (TASK_WAKEKILL | __TASK_UTRACED) - - /* Convenience macros for the sake of wake_up */ - #define TASK_NORMAL (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE) --#define TASK_ALL (TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED) -+#define TASK_ALL (TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED | __TASK_UTRACED) - - /* get_task_state() */ - #define TASK_REPORT (TASK_RUNNING | TASK_INTERRUPTIBLE | \ - TASK_UNINTERRUPTIBLE | __TASK_STOPPED | \ -- __TASK_TRACED) -+ __TASK_TRACED | __TASK_UTRACED) - - #define task_is_traced(task) ((task->state & __TASK_TRACED) != 0) - #define task_is_stopped(task) ((task->state & __TASK_STOPPED) != 0) --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:51 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:51 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 48F35D889C; - Mon, 21 Nov 2011 15:06:51 -0500 (EST) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id ZXkDvXaDg0cN; Mon, 21 Nov 2011 15:06:51 -0500 (EST) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 34485D889A; - Mon, 21 Nov 2011 15:06:51 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6nlT022211; - Mon, 21 Nov 2011 15:06:49 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:09 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:08 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 15/33] utrace: use TASK_UTRACED instead of TASK_TRACED -Message-ID: <20111121200208.GA27826@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Status: RO -Content-Length: 4316 -Lines: 130 - -Change utrace.c to use TASK_UTRACED instead of TASK_TRACED. - -- utrace_stop/utrace_wakeup: simply use the new state - -- utrace_do_stop: do not clear STOPPED/TRACED, but add the new - __TASK_UTRACED bit to state the fact that both ptrace and utrace - want this task to be stopped - -- naturally, do not use task_is_traced() to check if this task was - stopped by utrace, use the new task_is_utraced() helper which - checks __TASK_UTRACED. - -Signed-off-by: Oleg Nesterov ---- - kernel/utrace.c | 26 ++++++++++++++------------ - 1 files changed, 14 insertions(+), 12 deletions(-) - -diff --git a/kernel/utrace.c b/kernel/utrace.c -index cebc390..2097103 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -462,6 +462,8 @@ static void put_detached_list(struct list_head *list) - */ - #define ENGINE_STOP (1UL << _UTRACE_NEVENTS) - -+#define task_is_utraced(task) ((task->state & __TASK_UTRACED) != 0) -+ - static void mark_engine_wants_stop(struct task_struct *task, - struct utrace_engine *engine) - { -@@ -576,7 +578,7 @@ int utrace_set_events(struct task_struct *target, - - ret = 0; - if ((old_flags & ~events) && target != current && -- !task_is_stopped_or_traced(target) && !target->exit_state) { -+ !task_is_utraced(target) && !target->exit_state) { - /* - * This barrier ensures that our engine->flags changes - * have hit before we examine utrace->reporting, -@@ -623,21 +625,21 @@ static void mark_engine_detached(struct utrace_engine *engine) - */ - static bool utrace_do_stop(struct task_struct *target, struct utrace *utrace) - { -- if (task_is_stopped(target)) { -+ if (task_is_stopped_or_traced(target)) { - /* - * Stopped is considered quiescent; when it wakes up, it will - * go through utrace_finish_stop() before doing anything else. - */ - spin_lock_irq(&target->sighand->siglock); -- if (likely(task_is_stopped(target))) -- __set_task_state(target, TASK_TRACED); -+ if (likely(task_is_stopped_or_traced(target))) -+ target->state |= TASK_UTRACED; - spin_unlock_irq(&target->sighand->siglock); - } else if (utrace->resume > UTRACE_REPORT) { - utrace->resume = UTRACE_REPORT; - set_notify_resume(target); - } - -- return task_is_traced(target); -+ return task_is_utraced(target); - } - - /* -@@ -648,7 +650,7 @@ static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) - { - lockdep_assert_held(&utrace->lock); - spin_lock_irq(&target->sighand->siglock); -- wake_up_quiescent(target, __TASK_TRACED); -+ wake_up_quiescent(target, __TASK_UTRACED); - spin_unlock_irq(&target->sighand->siglock); - } - -@@ -710,7 +712,7 @@ static bool utrace_reset(struct task_struct *task, struct utrace *utrace) - /* - * If no more engines want it stopped, wake it up. - */ -- if (task_is_traced(task) && !(flags & ENGINE_STOP)) { -+ if (task_is_utraced(task) && !(flags & ENGINE_STOP)) { - /* - * It just resumes, so make sure single-step - * is not left set. -@@ -749,7 +751,7 @@ void utrace_finish_stop(void) - } - - /* -- * Perform %UTRACE_STOP, i.e. block in TASK_TRACED until woken up. -+ * Perform %UTRACE_STOP, i.e. block in TASK_UTRACED until woken up. - * @task == current, @utrace == current->utrace, which is not locked. - * Return true if we were woken up by SIGKILL even though some utrace - * engine may still want us to stay stopped. -@@ -799,7 +801,7 @@ relock: - return; - } - -- __set_current_state(TASK_TRACED); -+ __set_current_state(TASK_UTRACED); - - spin_unlock_irq(&task->sighand->siglock); - spin_unlock(&utrace->lock); -@@ -809,14 +811,14 @@ relock: - utrace_finish_stop(); - - /* -- * While in TASK_TRACED, we were considered "frozen enough". -+ * While in TASK_UTRACED, we were considered "frozen enough". - * Now that we woke up, it's crucial if we're supposed to be - * frozen that we freeze now before running anything substantial. - */ - try_to_freeze(); - - /* -- * While we were in TASK_TRACED, complete_signal() considered -+ * While we were in TASK_UTRACED, complete_signal() considered - * us "uninterested" in signal wakeups. Now make sure our - * TIF_SIGPENDING state is correct for normal running. - */ -@@ -1087,7 +1089,7 @@ int utrace_control(struct task_struct *target, - if (unlikely(IS_ERR(utrace))) - return PTR_ERR(utrace); - -- reset = task_is_traced(target); -+ reset = task_is_utraced(target); - ret = 0; - - /* --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:53 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:53 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B8F54D5296; - Mon, 21 Nov 2011 15:06:53 -0500 (EST) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id PX4Y3H1mw0hD; Mon, 21 Nov 2011 15:06:53 -0500 (EST) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A4B5CD528E; - Mon, 21 Nov 2011 15:06:53 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6pXd029643; - Mon, 21 Nov 2011 15:06:52 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:12 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:10 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 16/33] reintroduce tracehook_finish_jctl() as - utrace_end_stop() -Message-ID: <20111121200210.GA27829@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -Status: RO -Content-Length: 2401 -Lines: 77 - -utrace_finish_stop() is needed to avoid the races with SIGKILL which -wakes up UTRACED task, and thus it should be called every time after -the STOPPED/TRACED/UTRACED returns from schedule(), remember that -TASK_UTRACED can be added while the task is STOPPED/UTRACED. - -- change do_signal_state() to call this helper right after schedule(), - otherwise this logic is broken by the upstream changes - -- now that utrace doesn't control TASK_TRACED bit, ptrace_stop() must - call this helper too. - -Signed-off-by: Oleg Nesterov ---- - include/linux/utrace.h | 11 +++++++++++ - kernel/signal.c | 5 +++++ - kernel/utrace.c | 2 +- - 3 files changed, 17 insertions(+), 1 deletions(-) - -diff --git a/include/linux/utrace.h b/include/linux/utrace.h -index cf13839..0279c74 100644 ---- a/include/linux/utrace.h -+++ b/include/linux/utrace.h -@@ -719,4 +719,15 @@ static inline void utrace_exit_notify(struct task_struct *task, - utrace_report_death(task, group_dead, signal); - } - -+/** -+ * utrace_end_stop - report about return from STOPPED/TRACED -+ * -+ * This is called by do_signal_stop() and ptrace_stop after wakeup. -+ */ -+static inline void utrace_end_stop(void) -+{ -+ if (task_utrace_flags(current)) -+ utrace_finish_stop(); -+} -+ - #endif /* linux/utrace.h */ -diff --git a/kernel/signal.c b/kernel/signal.c -index 7a47a93..ba46eab 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -1903,6 +1903,8 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) - read_unlock(&tasklist_lock); - } - -+ utrace_end_stop(); -+ - /* - * While in TASK_TRACED, we were considered "frozen enough". - * Now that we woke up, it's crucial if we're supposed to be -@@ -2067,6 +2069,9 @@ static bool do_signal_stop(int signr) - - /* Now we don't run again until woken by SIGCONT or SIGKILL */ - schedule(); -+ -+ utrace_end_stop(); -+ - return true; - } else { - /* -diff --git a/kernel/utrace.c b/kernel/utrace.c -index 2097103..d41b982 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -741,7 +741,7 @@ static bool utrace_reset(struct task_struct *task, struct utrace *utrace) - void utrace_finish_stop(void) - { - /* -- * If we were task_is_traced() and then SIGKILL'ed, make -+ * If we were task_is_utraced() and then SIGKILL'ed, make - * sure we do nothing until the tracer drops utrace->lock. - */ - if (unlikely(__fatal_signal_pending(current))) { --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:56 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:56 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4A487D83A1; - Mon, 21 Nov 2011 15:06:56 -0500 (EST) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 3vHogPyhojlJ; Mon, 21 Nov 2011 15:06:56 -0500 (EST) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 358A0D88B0; - Mon, 21 Nov 2011 15:06:56 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK6sHk017679; - Mon, 21 Nov 2011 15:06:54 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:14 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:12 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 17/33] teach wake_up_quiescent() to do "selective" wake_up -Message-ID: <20111121200212.GA27836@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Status: RO -Content-Length: 1335 -Lines: 46 - -Both utrace and ptrace can want the same thread to be quiescent, in this -case its state is TASK_TRACED | TASK_UTRACED. And this also means that -this task must not run unless both utrace and ptrace resume it. - -Change wake_up_quiescent(p, state) to do "p->state &= ~state" and return -false unless there is no more "quiescent" bits in task->state. - -Signed-off-by: Oleg Nesterov ---- - kernel/signal.c | 15 +++++++++++++++ - 1 files changed, 15 insertions(+), 0 deletions(-) - -diff --git a/kernel/signal.c b/kernel/signal.c -index ba46eab..e06f795 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -701,11 +701,26 @@ void signal_wake_up(struct task_struct *t, int resume) - kick_process(t); - } - -+#define STATE_QUIESCENT (__TASK_STOPPED | __TASK_TRACED | __TASK_UTRACED) - /* - * wakes up the STOPPED/TRACED task, must be called with ->siglock held. - */ - int wake_up_quiescent(struct task_struct *p, unsigned int state) - { -+ unsigned int quiescent = (p->state & STATE_QUIESCENT); -+ -+ WARN_ON(state & ~(STATE_QUIESCENT | TASK_INTERRUPTIBLE)); -+ -+ if (quiescent) { -+ state &= ~TASK_INTERRUPTIBLE; -+ if ((quiescent & ~state) != 0) { -+ p->state &= ~state; -+ WARN_ON(!(p->state & STATE_QUIESCENT)); -+ WARN_ON(!(p->state & TASK_WAKEKILL)); -+ return 0; -+ } -+ } -+ - return wake_up_state(p, state); - } - --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:06:59 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:06:58 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C88E2D528B; - Mon, 21 Nov 2011 15:06:58 -0500 (EST) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id nNrAxBD5KOME; Mon, 21 Nov 2011 15:06:58 -0500 (EST) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B2114D51C1; - Mon, 21 Nov 2011 15:06:58 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6uQQ031440; - Mon, 21 Nov 2011 15:06:57 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:17 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:15 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 18/33] ptrace_stop: do not assume the task is running after - wake_up_quiescent() -Message-ID: <20111121200215.GA27839@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 -Status: RO -Content-Length: 956 -Lines: 31 - -If ptrace_stop() sets TASK_TRACED and then detects we should not stop, -it can race with utrace_do_stop() which can see TASK_TRACED and add -TASK_UTRACED. In this case we should stop for utrace needs. - -Signed-off-by: Oleg Nesterov ---- - kernel/signal.c | 8 ++++++++ - 1 files changed, 8 insertions(+), 0 deletions(-) - -diff --git a/kernel/signal.c b/kernel/signal.c -index e06f795..9348da6 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -1916,6 +1916,14 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) - if (clear_code) - current->exit_code = 0; - read_unlock(&tasklist_lock); -+ -+ /* -+ * It is possible that __TASK_UTRACED was added by utrace -+ * while we were __TASK_TRACED and before we take ->siglock -+ * for wake_up_quiescent(), we need to block in this case. -+ * Otherwise this is unnecessary but absolutely harmless. -+ */ -+ schedule(); - } - - utrace_end_stop(); --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:01 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:01 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4BF37D889A; - Mon, 21 Nov 2011 15:07:01 -0500 (EST) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 5p8tvlXAqUHr; Mon, 21 Nov 2011 15:07:01 -0500 (EST) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 37C22D8757; - Mon, 21 Nov 2011 15:07:01 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK6xFJ031449; - Mon, 21 Nov 2011 15:06:59 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:19 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:18 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 19/33] get_signal_to_deliver: restore/restructure - utrace/ptrace signal reporting -Message-ID: <20111121200218.GA27846@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 -Status: RO -Content-Length: 3556 -Lines: 115 - -- Reintroduce tracehook_get_signal() as utrace_hook_signal(). - -- Change get_signal_to_deliver() to call utrace_hook_signal() first, - before dequeue_signal() - -- Always call ptrace_signal() if signal != SIGKILL, no matter whether - this signal comes from utrace or not. - - Since this can change signr again, update "struct k_sigaction *ka" - in this case. - -IOW, roughly, ptrace acts as if it is the last attached engine, it -takes the final decision about the signal. - -Signed-off-by: Oleg Nesterov ---- - include/linux/utrace.h | 31 +++++++++++++++++++++++++++++++ - kernel/signal.c | 30 ++++++++++++++++++++---------- - 2 files changed, 51 insertions(+), 10 deletions(-) - -diff --git a/include/linux/utrace.h b/include/linux/utrace.h -index 0279c74..63103e2 100644 ---- a/include/linux/utrace.h -+++ b/include/linux/utrace.h -@@ -730,4 +730,35 @@ static inline void utrace_end_stop(void) - utrace_finish_stop(); - } - -+/** -+ * utrace_hook_signal - deliver synthetic signal to traced task -+ * @task: @current -+ * @regs: task_pt_regs(@current) -+ * @info: details of synthetic signal -+ * @return_ka: sigaction for synthetic signal -+ * -+ * Return zero to check for a real pending signal normally. -+ * Return -1 after releasing the siglock to repeat the check. -+ * Return a signal number to induce an artificial signal delivery, -+ * setting *@info and *@return_ka to specify its details and behavior. -+ * -+ * The @return_ka->sa_handler value controls the disposition of the -+ * signal, no matter the signal number. For %SIG_DFL, the return value -+ * is a representative signal to indicate the behavior (e.g. %SIGTERM -+ * for death, %SIGQUIT for core dump, %SIGSTOP for job control stop, -+ * %SIGTSTP for stop unless in an orphaned pgrp), but the signal number -+ * reported will be @info->si_signo instead. -+ * -+ * Called with @task->sighand->siglock held, before dequeuing pending signals. -+ */ -+static inline int utrace_hook_signal(struct task_struct *task, -+ struct pt_regs *regs, -+ siginfo_t *info, -+ struct k_sigaction *return_ka) -+{ -+ if (unlikely(task_utrace_flags(task))) -+ return utrace_get_signal(task, regs, info, return_ka); -+ return 0; -+} -+ - #endif /* linux/utrace.h */ -diff --git a/kernel/signal.c b/kernel/signal.c -index 9348da6..38ea4e6 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -2242,17 +2242,27 @@ relock: - for (;;) { - struct k_sigaction *ka; - -- if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) && -- do_signal_stop(0)) -+ signr = utrace_hook_signal(current, regs, info, return_ka); -+ if (unlikely(signr < 0)) - goto relock; - -- if (unlikely(current->jobctl & JOBCTL_TRAP_MASK)) { -- do_jobctl_trap(); -- spin_unlock_irq(&sighand->siglock); -- goto relock; -- } -+ if (unlikely(signr != 0)) -+ ka = return_ka; -+ else { -+ if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) && -+ do_signal_stop(0)) -+ goto relock; - -- signr = dequeue_signal(current, ¤t->blocked, info); -+ if (unlikely(current->jobctl & JOBCTL_TRAP_MASK)) { -+ do_jobctl_trap(); -+ spin_unlock_irq(&sighand->siglock); -+ goto relock; -+ } -+ -+ signr = dequeue_signal(current, ¤t->blocked, info); -+ -+ ka = &sighand->action[signr-1]; -+ } - - if (!signr) - break; /* will return 0 */ -@@ -2262,9 +2272,9 @@ relock: - regs, cookie); - if (!signr) - continue; -- } - -- ka = &sighand->action[signr-1]; -+ ka = &sighand->action[signr-1]; -+ } - - /* Trace actually delivered signals. */ - trace_signal_deliver(signr, info, ka); --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:03 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:03 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id CB362D89E9; - Mon, 21 Nov 2011 15:07:03 -0500 (EST) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id wm2JqccPnhsV; Mon, 21 Nov 2011 15:07:03 -0500 (EST) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B6D25D89DE; - Mon, 21 Nov 2011 15:07:03 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK715f031455; - Mon, 21 Nov 2011 15:07:02 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:22 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:20 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 20/33] utrace_get_signal: - s/JOBCTL_STOP_PENDING/JOBCTL_PENDING_MASK/ -Message-ID: <20111121200220.GA27849@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 -Status: RO -Content-Length: 1204 -Lines: 33 - -utrace_get_signal() checks JOBCTL_STOP_PENDING to detect the -case when we should not try to dequeue the signal but should -try to participate in the group-stop. - -With the recent changes this is not enough, everything which -contrbutes to recalc_sigpending_tsk() should be respected. - -Check JOBCTL_PENDING_MASK instead. This matches the -JOBCTL_STOP_PENDING | JOBCTL_TRAP_MASK code in the caller, -get_signal_to_deliver(). Note that this code won't run if -utrace_get_signal() returns signr > 0. - -Signed-off-by: Oleg Nesterov ---- - kernel/utrace.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/kernel/utrace.c b/kernel/utrace.c -index d41b982..0bb0a06 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -2027,7 +2027,7 @@ int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, - ka = NULL; - memset(return_ka, 0, sizeof *return_ka); - } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || -- unlikely(task->jobctl & JOBCTL_STOP_PENDING)) { -+ unlikely(task->jobctl & JOBCTL_PENDING_MASK)) { - /* - * If no engine is interested in intercepting signals or - * we must stop, let the caller just dequeue them normally --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:07 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:06 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8C14BD4F84; - Mon, 21 Nov 2011 15:07:06 -0500 (EST) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 39eM-KKZxrZ3; Mon, 21 Nov 2011 15:07:06 -0500 (EST) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7628FD4FF4; - Mon, 21 Nov 2011 15:07:06 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK74dN022253; - Mon, 21 Nov 2011 15:07:04 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:25 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:23 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 21/33] introduce ptrace_set_syscall_trace() -Message-ID: <20111121200223.GA27856@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Status: RO -Content-Length: 1549 -Lines: 52 - -No functional changes. Add the new helper, ptrace_set_syscall_trace(), -which should be used to set/clear TIF_SYSCALL_TRACE in ptrace code. -Currently it does nothing more. - -Signed-off-by: Oleg Nesterov ---- - kernel/ptrace.c | 15 ++++++++++----- - 1 files changed, 10 insertions(+), 5 deletions(-) - -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index a464ab5..43357e5 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -38,6 +38,14 @@ void ptrace_signal_wake_up(struct task_struct *p, int quiescent) - kick_process(p); - } - -+static void ptrace_set_syscall_trace(struct task_struct *p, bool on) -+{ -+ if (on) -+ set_tsk_thread_flag(p, TIF_SYSCALL_TRACE); -+ else -+ clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); -+} -+ - static int ptrace_trapping_sleep_fn(void *flags) - { - schedule(); -@@ -418,7 +426,7 @@ static int ptrace_detach(struct task_struct *child, unsigned int data) - - /* Architecture-specific hardware disable .. */ - ptrace_disable(child); -- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); -+ ptrace_set_syscall_trace(child, false); - - write_lock_irq(&tasklist_lock); - /* -@@ -606,10 +614,7 @@ static int ptrace_resume(struct task_struct *child, long request, - if (!valid_signal(data)) - return -EIO; - -- if (request == PTRACE_SYSCALL) -- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); -- else -- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); -+ ptrace_set_syscall_trace(child, request == PTRACE_SYSCALL); - - #ifdef TIF_SYSCALL_EMU - if (request == PTRACE_SYSEMU || request == PTRACE_SYSEMU_SINGLESTEP) --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:09 2011 -Return-Path: oleg@redhat.com -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:09 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1ADF01285E4; - Mon, 21 Nov 2011 15:07:09 -0500 (EST) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id rF+XegsxVXnL; Mon, 21 Nov 2011 15:07:09 -0500 (EST) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 067E41287D0; - Mon, 21 Nov 2011 15:07:09 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK76tD022270; - Mon, 21 Nov 2011 15:07:07 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:27 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:25 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 22/33] introduce PT_SYSCALL_TRACE flag -Message-ID: <20111121200225.GA27860@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Status: RO -Content-Length: 2268 -Lines: 73 - -Currently tracehooks assume that if the ptraced task has -TIF_SYSCALL_TRACE set, the tracee should report the syscall. -This is not true, this thread flag can be set by utrace. - -Add the new internal ptrace flag, PT_SYSCALL_TRACE. Change -ptrace_set_syscall_trace() to set/clear this bit along with -TIF_SYSCALL_TRACE, change ptrace_report_syscall() to check -this flag instead of PT_PTRACED. - -Signed-off-by: Oleg Nesterov ---- - include/linux/ptrace.h | 3 +++ - include/linux/tracehook.h | 2 +- - kernel/ptrace.c | 7 +++++-- - 3 files changed, 9 insertions(+), 3 deletions(-) - -diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h -index 6d9282a..c10f610 100644 ---- a/include/linux/ptrace.h -+++ b/include/linux/ptrace.h -@@ -104,6 +104,8 @@ - - #define PT_TRACE_MASK 0x000003f4 - -+#define PT_SYSCALL_TRACE 0x00020000 -+ - /* single stepping state bits (used on ARM and PA-RISC) */ - #define PT_SINGLESTEP_BIT 31 - #define PT_SINGLESTEP (1<ptrace) { - child->ptrace = current->ptrace; -+ child->ptrace &= ~PT_SYSCALL_TRACE; - __ptrace_link(child, current->parent); - - if (child->ptrace & PT_SEIZED) -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index ec2af67..eb9fe30 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -59,7 +59,7 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) - { - int ptrace = current->ptrace; - -- if (!(ptrace & PT_PTRACED)) -+ if (!(ptrace & PT_SYSCALL_TRACE)) - return; - - ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 43357e5..1ac03eb 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -40,10 +40,13 @@ void ptrace_signal_wake_up(struct task_struct *p, int quiescent) - - static void ptrace_set_syscall_trace(struct task_struct *p, bool on) - { -- if (on) -+ if (on) { -+ p->ptrace |= PT_SYSCALL_TRACE; - set_tsk_thread_flag(p, TIF_SYSCALL_TRACE); -- else -+ } else { -+ p->ptrace &= ~PT_SYSCALL_TRACE; - clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); -+ } - } - - static int ptrace_trapping_sleep_fn(void *flags) --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:11 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:11 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id B7D62D4DCC; - Mon, 21 Nov 2011 15:07:11 -0500 (EST) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 1ENpGO166I-W; Mon, 21 Nov 2011 15:07:11 -0500 (EST) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id A3A55D498A; - Mon, 21 Nov 2011 15:07:11 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK79AS017728; - Mon, 21 Nov 2011 15:07:10 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:30 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:28 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 23/33] utrace: don't clear TIF_SYSCALL_TRACE if it is - needed by ptrace -Message-ID: <20111121200228.GA27863@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Status: RO -Content-Length: 797 -Lines: 24 - -TIF_SYSCALL_TRACE should be cleared only if both ptrace and utrace do -not want it, change utrace_reset() to check PT_SYSCALL_TRACE before -clear_tsk_thread_flag(TIF_SYSCALL_TRACE). - -Signed-off-by: Oleg Nesterov ---- - kernel/utrace.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/kernel/utrace.c b/kernel/utrace.c -index 0bb0a06..bebf6de 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -697,6 +697,7 @@ static bool utrace_reset(struct task_struct *task, struct utrace *utrace) - BUG_ON(utrace->death); - flags &= UTRACE_EVENT(REAP); - } else if (!(flags & UTRACE_EVENT_SYSCALL) && -+ !(task->ptrace & PT_SYSCALL_TRACE) && - test_tsk_thread_flag(task, TIF_SYSCALL_TRACE)) { - clear_tsk_thread_flag(task, TIF_SYSCALL_TRACE); - } --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:14 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:14 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5376AD8774; - Mon, 21 Nov 2011 15:07:14 -0500 (EST) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 5Oc8ErfFfJSs; Mon, 21 Nov 2011 15:07:14 -0500 (EST) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 3F2CFD81E9; - Mon, 21 Nov 2011 15:07:14 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7Cw3015467; - Mon, 21 Nov 2011 15:07:12 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:32 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:30 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 24/33] introduce task_utrace_lock/task_utrace_unlock -Message-ID: <20111121200230.GA27870@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 -Status: RO -Content-Length: 2190 -Lines: 81 - -- Add task_utrace_lock(task). It simply takes task->utrace->lock if - this task was ever utraced. Otherwise it takes task_lock(), this - serializes with utrace_attach_task()->utrace_task_alloc(). In both - case the caller can be sure it can't race with anything which needs - utrace->lock. - -- Add task_utrace_unlock(task), it releases the corresponding lock. - -Signed-off-by: Oleg Nesterov ---- - include/linux/utrace.h | 9 +++++++++ - kernel/utrace.c | 26 ++++++++++++++++++++++++++ - 2 files changed, 35 insertions(+), 0 deletions(-) - -diff --git a/include/linux/utrace.h b/include/linux/utrace.h -index 63103e2..f37373b 100644 ---- a/include/linux/utrace.h -+++ b/include/linux/utrace.h -@@ -117,6 +117,12 @@ void utrace_signal_handler(struct task_struct *, int); - - #ifndef CONFIG_UTRACE - -+static inline void task_utrace_lock(struct task_struct *task) -+{ -+} -+static inline void task_utrace_unlock(struct task_struct *task) -+{ -+} - /* - * uses these accessors to avoid #ifdef CONFIG_UTRACE. - */ -@@ -139,6 +145,9 @@ static inline void task_utrace_proc_status(struct seq_file *m, - - #else /* CONFIG_UTRACE */ - -+extern void task_utrace_lock(struct task_struct *task); -+extern void task_utrace_unlock(struct task_struct *task); -+ - static inline unsigned long task_utrace_flags(struct task_struct *task) - { - return task->utrace_flags; -diff --git a/kernel/utrace.c b/kernel/utrace.c -index bebf6de..960dd9e 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -79,6 +79,32 @@ static int __init utrace_init(void) - } - module_init(utrace_init); - -+void task_utrace_lock(struct task_struct *task) -+{ -+ struct utrace *utrace = task_utrace_struct(task); -+ -+ if (!utrace) { -+ task_lock(task); -+ utrace = task_utrace_struct(task); -+ if (!utrace) -+ return; -+ -+ task_unlock(task); -+ } -+ -+ spin_lock(&utrace->lock); -+} -+ -+void task_utrace_unlock(struct task_struct *task) -+{ -+ struct utrace *utrace = task_utrace_struct(task); -+ -+ if (utrace) -+ spin_unlock(&utrace->lock); -+ else -+ task_unlock(task); -+} -+ - /* - * Set up @task.utrace for the first time. We can have races - * between two utrace_attach_task() calls here. The task_lock() --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:17 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:17 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 01034D498A; - Mon, 21 Nov 2011 15:07:17 -0500 (EST) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id BglmrU3H2hJr; Mon, 21 Nov 2011 15:07:16 -0500 (EST) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E0D31D4FF4; - Mon, 21 Nov 2011 15:07:16 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7Egx015474; - Mon, 21 Nov 2011 15:07:15 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:35 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:33 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 25/33] teach ptrace_set_syscall_trace() to play well with - utrace -Message-ID: <20111121200233.GA27873@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 -Status: RO -Content-Length: 1545 -Lines: 49 - -1. ptrace_set_syscall_trace(true)->set_tsk_thread_flag(TIF_SYSCALL_TRACE) - can race with utrace_control()->utrace_reset() path which can miss - PT_SYSCALL_TRACE and clear TIF_SYSCALL_TRACE after it was already set. - -2. ptrace_set_syscall_trace(false) clears TIF_SYSCALL_TRACE and this is - not utrace-friendly, it can need this flag. - -Change ptrace_set_syscall_trace() to take task_utrace_lock(), this is -enough to fix the 1st problem. Check task_utrace_flags() before clearing -TIF_SYSCALL_TRACE, this fixes 2. - -Signed-off-by: Oleg Nesterov ---- - kernel/ptrace.c | 6 +++++- - 1 files changed, 5 insertions(+), 1 deletions(-) - -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 1ac03eb..739183a 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - - void ptrace_signal_wake_up(struct task_struct *p, int quiescent) - { -@@ -40,13 +41,16 @@ void ptrace_signal_wake_up(struct task_struct *p, int quiescent) - - static void ptrace_set_syscall_trace(struct task_struct *p, bool on) - { -+ task_utrace_lock(p); - if (on) { - p->ptrace |= PT_SYSCALL_TRACE; - set_tsk_thread_flag(p, TIF_SYSCALL_TRACE); - } else { - p->ptrace &= ~PT_SYSCALL_TRACE; -- clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); -+ if (!(task_utrace_flags(p) & UTRACE_EVENT_SYSCALL)) -+ clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); - } -+ task_utrace_unlock(p); - } - - static int ptrace_trapping_sleep_fn(void *flags) --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:19 2011 -Return-Path: oleg@redhat.com -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:19 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8F87F128EAA; - Mon, 21 Nov 2011 15:07:19 -0500 (EST) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id yittEjCd+X4F; Mon, 21 Nov 2011 15:07:19 -0500 (EST) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7BC701287D0; - Mon, 21 Nov 2011 15:07:19 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK7HbH031553; - Mon, 21 Nov 2011 15:07:18 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:38 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:36 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 26/33] introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK -Message-ID: <20111121200236.GA27880@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 -Status: RO -Content-Length: 3723 -Lines: 108 - -Add the new internal ptrace flags, PT_SINGLE_STEP and PT_SINGLE_BLOCK. - -Like PT_SYSCALL_TRACE, this is needed to avoid the unnecessary ptrace -reports when TIF_SINGLESTEP was set by another engine, not by ptrace. -Also, we need these bits to coordinate the user_*_single_step() calls -from ptrace and utrace. - -TODO: update the !x86 ptrace code which does user_disable_single_step(). - -Signed-off-by: Oleg Nesterov ---- - arch/x86/kernel/ptrace.c | 1 + - include/linux/ptrace.h | 5 ++++- - include/linux/tracehook.h | 7 +++++-- - kernel/ptrace.c | 3 +++ - 4 files changed, 13 insertions(+), 3 deletions(-) - -diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c -index 8252879..d1557dc 100644 ---- a/arch/x86/kernel/ptrace.c -+++ b/arch/x86/kernel/ptrace.c -@@ -808,6 +808,7 @@ static int ioperm_get(struct task_struct *target, - */ - void ptrace_disable(struct task_struct *child) - { -+ child->ptrace &= ~(PT_SINGLE_STEP | PT_SINGLE_BLOCK); - user_disable_single_step(child); - #ifdef TIF_SYSCALL_EMU - clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); -diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h -index c10f610..2743315 100644 ---- a/include/linux/ptrace.h -+++ b/include/linux/ptrace.h -@@ -105,6 +105,8 @@ - #define PT_TRACE_MASK 0x000003f4 - - #define PT_SYSCALL_TRACE 0x00020000 -+#define PT_SINGLE_STEP 0x00040000 -+#define PT_SINGLE_BLOCK 0x00080000 - - /* single stepping state bits (used on ARM and PA-RISC) */ - #define PT_SINGLESTEP_BIT 31 -@@ -229,7 +231,8 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) - - if (unlikely(ptrace) && current->ptrace) { - child->ptrace = current->ptrace; -- child->ptrace &= ~PT_SYSCALL_TRACE; -+ child->ptrace &= -+ ~(PT_SYSCALL_TRACE | PT_SINGLE_STEP | PT_SINGLE_BLOCK); - __ptrace_link(child, current->parent); - - if (child->ptrace & PT_SEIZED) -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index eb9fe30..21c8ca2 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -104,6 +104,9 @@ static inline __must_check int tracehook_report_syscall_entry( - return 0; - } - -+#define ptrace_wants_step() \ -+ (current->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK)) -+ - /** - * tracehook_report_syscall_exit - task has just finished a system call - * @regs: user register state of current task -@@ -126,7 +129,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) - if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) - utrace_report_syscall_exit(regs); - -- if (step) { -+ if (step && ptrace_wants_step()) { - siginfo_t info; - user_single_step_siginfo(current, regs, &info); - force_sig_info(SIGTRAP, &info, current); -@@ -157,7 +160,7 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, - { - if (task_utrace_flags(current)) - utrace_signal_handler(current, stepping); -- if (stepping) -+ if (stepping && ptrace_wants_step()) - ptrace_notify(SIGTRAP); - } - -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 739183a..792080d 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -630,13 +630,16 @@ static int ptrace_resume(struct task_struct *child, long request, - clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); - #endif - -+ child->ptrace &= ~(PT_SINGLE_STEP | PT_SINGLE_BLOCK); - if (is_singleblock(request)) { - if (unlikely(!arch_has_block_step())) - return -EIO; -+ child->ptrace |= PT_SINGLE_BLOCK; - user_enable_block_step(child); - } else if (is_singlestep(request) || is_sysemu_singlestep(request)) { - if (unlikely(!arch_has_single_step())) - return -EIO; -+ child->ptrace |= PT_SINGLE_STEP; - user_enable_single_step(child); - } else { - user_disable_single_step(child); --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:22 2011 -Return-Path: oleg@redhat.com -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:22 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 0C136128FB0; - Mon, 21 Nov 2011 15:07:22 -0500 (EST) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id GNbS20gY5Jq9; Mon, 21 Nov 2011 15:07:21 -0500 (EST) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id EB5821287D0; - Mon, 21 Nov 2011 15:07:21 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK7Kn1029766; - Mon, 21 Nov 2011 15:07:20 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:40 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:38 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 27/33] utrace: finish_resume_report: don't do - user_xxx_step() if ptrace_wants_step() -Message-ID: <20111121200238.GA27883@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -Status: RO -Content-Length: 2741 -Lines: 84 - -finish_resume_report() should not enable/disable the stepping if -ptrace_wants_step() == T. If ptrace wants block_step while utrace -wants single_step we could "promote" the stepping, but I do not -think this really makes sense. - -Unless the tracee is killed this can't race with ptrace, this is -called by the tracee itself. If it is killed we do not care. - -Signed-off-by: Oleg Nesterov ---- - include/linux/tracehook.h | 8 ++++---- - kernel/utrace.c | 9 ++++++--- - 2 files changed, 10 insertions(+), 7 deletions(-) - -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 21c8ca2..b6812d4 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -104,8 +104,8 @@ static inline __must_check int tracehook_report_syscall_entry( - return 0; - } - --#define ptrace_wants_step() \ -- (current->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK)) -+#define ptrace_wants_step(task) \ -+ ((task)->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK)) - - /** - * tracehook_report_syscall_exit - task has just finished a system call -@@ -129,7 +129,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) - if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) - utrace_report_syscall_exit(regs); - -- if (step && ptrace_wants_step()) { -+ if (step && ptrace_wants_step(current)) { - siginfo_t info; - user_single_step_siginfo(current, regs, &info); - force_sig_info(SIGTRAP, &info, current); -@@ -160,7 +160,7 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, - { - if (task_utrace_flags(current)) - utrace_signal_handler(current, stepping); -- if (stepping && ptrace_wants_step()) -+ if (stepping && ptrace_wants_step(current)) - ptrace_notify(SIGTRAP); - } - -diff --git a/kernel/utrace.c b/kernel/utrace.c -index 960dd9e..05e8532 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -1829,7 +1829,8 @@ static void finish_resume_report(struct task_struct *task, - - case UTRACE_BLOCKSTEP: - if (likely(arch_has_block_step())) { -- user_enable_block_step(task); -+ if (!ptrace_wants_step(task)) -+ user_enable_block_step(task); - break; - } - -@@ -1842,7 +1843,8 @@ static void finish_resume_report(struct task_struct *task, - - case UTRACE_SINGLESTEP: - if (likely(arch_has_single_step())) { -- user_enable_single_step(task); -+ if (!ptrace_wants_step(task)) -+ user_enable_single_step(task); - } else { - /* - * This means some callback is to blame for failing -@@ -1857,7 +1859,8 @@ static void finish_resume_report(struct task_struct *task, - case UTRACE_REPORT: - case UTRACE_RESUME: - default: -- user_disable_single_step(task); -+ if (!ptrace_wants_step(task)) -+ user_disable_single_step(task); - break; - } - } --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:24 2011 -Return-Path: oleg@redhat.com -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:24 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8954F12914D; - Mon, 21 Nov 2011 15:07:24 -0500 (EST) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 0lU8wXKC78yu; Mon, 21 Nov 2011 15:07:24 -0500 (EST) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 759B61287D0; - Mon, 21 Nov 2011 15:07:24 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7Mi7022329; - Mon, 21 Nov 2011 15:07:23 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:43 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:41 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 28/33] ptrace: shift user_*_step() from ptrace_resume() to - ptrace_stop() -Message-ID: <20111121200241.GA27890@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Status: RO -Content-Length: 2374 -Lines: 70 - -1. ptrace_resume() plays with the stopped task which can be also - task_is_utraced(). In this case user_enable_xxx_step() can race - with utrace_reset()->user_disable_single_step(). - - We could change utrace_reset() to check ptrace_wants_step() and - add the task_utrace_lock + unlock barrier after ptrace_resume() - sets PT_SINGLE_STEP. - - But it is better to reassign enable/desable from the tracer to - the tracee, it can check its PT_SINGLE_ bits after wakeup. This - also makes sense because enable_step(task) can be faster if - task == current. - -2. ptrace can do user_disable_single_step() while utrace needs the - stepping. - - Set TIF_NOTIFY_RESUME after user_disable_single_step() to ensure - the tracee can't return to the user-space without utrace_resume(). - Any correct engine which wants the stepping should reassert it. - -Signed-off-by: Oleg Nesterov ---- - kernel/ptrace.c | 4 ---- - kernel/signal.c | 11 +++++++++++ - 2 files changed, 11 insertions(+), 4 deletions(-) - -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 792080d..eba9a22 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -635,14 +635,10 @@ static int ptrace_resume(struct task_struct *child, long request, - if (unlikely(!arch_has_block_step())) - return -EIO; - child->ptrace |= PT_SINGLE_BLOCK; -- user_enable_block_step(child); - } else if (is_singlestep(request) || is_sysemu_singlestep(request)) { - if (unlikely(!arch_has_single_step())) - return -EIO; - child->ptrace |= PT_SINGLE_STEP; -- user_enable_single_step(child); -- } else { -- user_disable_single_step(child); - } - - child->exit_code = data; -diff --git a/kernel/signal.c b/kernel/signal.c -index 38ea4e6..b13d2bc 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -1928,6 +1928,17 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) - - utrace_end_stop(); - -+ if (current->ptrace & PT_SINGLE_BLOCK) -+ user_enable_block_step(current); -+ else if (current->ptrace & PT_SINGLE_STEP) -+ user_enable_single_step(current); -+ else { -+ user_disable_single_step(current); -+ /* if utrace needs the stepping it should reassert */ -+ if (task_utrace_flags(current)) -+ set_thread_flag(TIF_NOTIFY_RESUME); -+ } -+ - /* - * While in TASK_TRACED, we were considered "frozen enough". - * Now that we woke up, it's crucial if we're supposed to be --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:27 2011 -Return-Path: oleg@redhat.com -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:27 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 043581287D0; - Mon, 21 Nov 2011 15:07:27 -0500 (EST) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 4WO1El1jiIrJ; Mon, 21 Nov 2011 15:07:26 -0500 (EST) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id E3FCA129045; - Mon, 21 Nov 2011 15:07:26 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7OdV017836; - Mon, 21 Nov 2011 15:07:25 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:45 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:43 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 29/33] ptrace_disable: no need to disable stepping -Message-ID: <20111121200243.GA27893@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Status: RO -Content-Length: 945 -Lines: 29 - -ptrace_disable() is called when the tracee is quiescent and we -are going to untrace. This means we are going to clear ->ptrace -and wake up the tracee. Now that ptrace_stop() checks PT_ bits -and does user_disable_single_step() we can remove this code from -ptrace_disable(), it is unneeded and not utrace-friendly. - -TODO: change !x86 code. - -Signed-off-by: Oleg Nesterov ---- - arch/x86/kernel/ptrace.c | 2 -- - 1 files changed, 0 insertions(+), 2 deletions(-) - -diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c -index d1557dc..96d315a 100644 ---- a/arch/x86/kernel/ptrace.c -+++ b/arch/x86/kernel/ptrace.c -@@ -808,8 +808,6 @@ static int ioperm_get(struct task_struct *target, - */ - void ptrace_disable(struct task_struct *child) - { -- child->ptrace &= ~(PT_SINGLE_STEP | PT_SINGLE_BLOCK); -- user_disable_single_step(child); - #ifdef TIF_SYSCALL_EMU - clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); - #endif --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:29 2011 -Return-Path: oleg@redhat.com -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:29 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 8A6E8D4C39; - Mon, 21 Nov 2011 15:07:29 -0500 (EST) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id NLURBx2yQes5; Mon, 21 Nov 2011 15:07:29 -0500 (EST) -Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7660DD498A; - Mon, 21 Nov 2011 15:07:29 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7RnP015578; - Mon, 21 Nov 2011 15:07:27 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:48 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:46 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 30/33] ptrace_report_syscall: check TIF_SYSCALL_EMU -Message-ID: <20111121200246.GA27896@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 -Status: RO -Content-Length: 858 -Lines: 28 - -4d16a64 "introduce PT_SYSCALL_TRACE flag" breaks PTRACE_SYSEMU -which doesn't set PT_SYSCALL_TRACE. - -Change ptrace_report_syscall() to check TIF_SYSCALL_EMU as well. -This can't conflict with utrace, this flag can only be set by -ptrace. - -Signed-off-by: Oleg Nesterov ---- - include/linux/tracehook.h | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index b6812d4..90ca578 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -59,7 +59,7 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) - { - int ptrace = current->ptrace; - -- if (!(ptrace & PT_SYSCALL_TRACE)) -+ if (!(ptrace & PT_SYSCALL_TRACE) && !test_thread_flag(TIF_SYSCALL_EMU)) - return; - - ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:32 2011 -Return-Path: oleg@redhat.com -Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO - zmta02.collab.prod.int.phx2.redhat.com) (10.5.5.32) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:32 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 10D1312916C; - Mon, 21 Nov 2011 15:07:32 -0500 (EST) -Received: from zmta02.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta02.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id Z14plX1oxaYL; Mon, 21 Nov 2011 15:07:32 -0500 (EST) -Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id F12FF128E1D; - Mon, 21 Nov 2011 15:07:31 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7T0q022460; - Mon, 21 Nov 2011 15:07:30 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:50 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:48 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 31/33] utrace_resume: check irqs_disabled() to shut up - lockdep -Message-ID: <20111121200248.GA27903@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -Status: RO -Content-Length: 823 -Lines: 26 - -utrace_resume() enables irqs unconditionally. With the recent changes -in lockdep.c this triggers the warning. Check irqs_disabled() before -local_irq_enable(). - -Signed-off-by: Oleg Nesterov ---- - kernel/utrace.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/kernel/utrace.c b/kernel/utrace.c -index 05e8532..c817a46 100644 ---- a/kernel/utrace.c -+++ b/kernel/utrace.c -@@ -1881,7 +1881,8 @@ void utrace_resume(struct task_struct *task, struct pt_regs *regs) - * code path leads to calling into get_signal_to_deliver(), which - * implicitly reenables them by virtue of spin_unlock_irq. - */ -- local_irq_enable(); -+ if (irqs_disabled()) /* make trace_hardirqs_on() happy */ -+ local_irq_enable(); - - /* - * If this flag is still set it's because there was a signal --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:34 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:34 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 860BCD8A3E; - Mon, 21 Nov 2011 15:07:34 -0500 (EST) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id pVTbN1oF62dg; Mon, 21 Nov 2011 15:07:34 -0500 (EST) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6FBFFD87A3; - Mon, 21 Nov 2011 15:07:34 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id pALK7W0B029871; - Mon, 21 Nov 2011 15:07:32 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:53 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:51 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 32/33] ptrace_report_syscall: check if TIF_SYSCALL_EMU is - defined -Message-ID: <20111121200251.GA27906@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -Status: RO -Content-Length: 839 -Lines: 31 - -From: Tony Breeds - -TIF_SYSCALL_EMU is x86 only, add ifdef into ptrace_report_syscall(). - -Signed-off-by: Oleg Nesterov ---- - include/linux/tracehook.h | 8 ++++++-- - 1 files changed, 6 insertions(+), 2 deletions(-) - -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index 90ca578..a1bac95 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -59,8 +59,12 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) - { - int ptrace = current->ptrace; - -- if (!(ptrace & PT_SYSCALL_TRACE) && !test_thread_flag(TIF_SYSCALL_EMU)) -- return; -+ if (!(ptrace & PT_SYSCALL_TRACE)) { -+#ifdef TIF_SYSCALL_EMU -+ if (!test_thread_flag(TIF_SYSCALL_EMU)) -+#endif -+ return; -+ } - - ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); - --- -1.5.5.1 - - -From oleg@redhat.com Mon Nov 21 15:07:37 2011 -Return-Path: oleg@redhat.com -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - zmail13.collab.prod.int.phx2.redhat.com with LMTP; Mon, 21 Nov 2011 - 15:07:37 -0500 (EST) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 33405D8A50; - Mon, 21 Nov 2011 15:07:37 -0500 (EST) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id 3WH8FhvizjEA; Mon, 21 Nov 2011 15:07:37 -0500 (EST) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1274FD89BB; - Mon, 21 Nov 2011 15:07:37 -0500 (EST) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id pALK7YHr017898; - Mon, 21 Nov 2011 15:07:35 -0500 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Mon, 21 Nov 2011 21:02:55 +0100 (CET) -Date: Mon, 21 Nov 2011 21:02:53 +0100 -From: Oleg Nesterov -To: Dave Jones , "Frank Ch. Eigler" , - Josh Boyer , Josh Stone , - Kyle McMartin -Cc: kernel@lists.fedoraproject.org -Subject: [PATCH 33/33] utrace: s390: fix the compile problem with traps.c -Message-ID: <20111121200253.GA27913@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20111121200039.GA27699@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Status: RO -Content-Length: 725 -Lines: 25 - -d99e60e5 "tracehooks: reintroduce tracehook_consider_fatal_signal()" -breaks the compilation of arch/s390/kernel/traps.c. Restore the -necessary include removed by upstream 73b7d40f commit. - -Signed-off-by: Oleg Nesterov ---- - arch/s390/kernel/traps.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c -index f506e1b..3132498 100644 ---- a/arch/s390/kernel/traps.c -+++ b/arch/s390/kernel/traps.c -@@ -18,7 +18,7 @@ - #include - #include - #include --#include -+#include - #include - #include - #include --- -1.5.5.1 - +1.7.9.1 From 70a06342d81b58b605384085d2bd86bb1499cbc2 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 19 Mar 2012 19:23:04 -0400 Subject: [PATCH 315/487] drm-i915-dp-stfu.patch: Muzzle a bunch of DP WARN()s. They're not wrong, but they're not helpful at this point. --- drm-i915-dp-stfu.patch | 69 ++++++++++++++++++++++++++++++++++++++++++ kernel.spec | 10 ++++-- 2 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 drm-i915-dp-stfu.patch diff --git a/drm-i915-dp-stfu.patch b/drm-i915-dp-stfu.patch new file mode 100644 index 000000000..8948229dc --- /dev/null +++ b/drm-i915-dp-stfu.patch @@ -0,0 +1,69 @@ +From 04a43e2598db35b3d0ec25925bb8475b5c0a3809 Mon Sep 17 00:00:00 2001 +From: Adam Jackson +Date: Fri, 16 Mar 2012 16:39:11 -0400 +Subject: [PATCH] drm/i915/dp: Use DRM_ERROR not WARN for sanity checks + +These are noisy as shit and creating a ton of abrt reports. I don't +need more, thanks. Proper fix upstream eventually. + +Signed-off-by: Adam Jackson +--- + drivers/gpu/drm/i915/intel_dp.c | 14 ++++++++------ + 1 files changed, 8 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c +index 94f860c..6bf27c9 100644 +--- a/drivers/gpu/drm/i915/intel_dp.c ++++ b/drivers/gpu/drm/i915/intel_dp.c +@@ -331,7 +331,7 @@ intel_dp_check_edp(struct intel_dp *intel_dp) + if (!is_edp(intel_dp)) + return; + if (!ironlake_edp_have_panel_power(intel_dp) && !ironlake_edp_have_panel_vdd(intel_dp)) { +- WARN(1, "eDP powered off while attempting aux channel communication.\n"); ++ DRM_ERROR("eDP powered off while attempting aux channel communication.\n"); + DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n", + I915_READ(PCH_PP_STATUS), + I915_READ(PCH_PP_CONTROL)); +@@ -386,7 +386,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, + } + + if (try == 3) { +- WARN(1, "dp_aux_ch not started status 0x%08x\n", ++ DRM_ERROR("dp_aux_ch not started status 0x%08x\n", + I915_READ(ch_ctl)); + return -EBUSY; + } +@@ -992,8 +992,8 @@ static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) + return; + DRM_DEBUG_KMS("Turn eDP VDD on\n"); + +- WARN(intel_dp->want_panel_vdd, +- "eDP VDD already requested on\n"); ++ if (intel_dp->want_panel_vdd) ++ DRM_ERROR("eDP VDD already requested on\n"); + + intel_dp->want_panel_vdd = true; + +@@ -1058,7 +1058,8 @@ static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) + return; + + DRM_DEBUG_KMS("Turn eDP VDD off %d\n", intel_dp->want_panel_vdd); +- WARN(!intel_dp->want_panel_vdd, "eDP VDD not forced on"); ++ if (!intel_dp->want_panel_vdd) ++ DRM_ERROR("eDP VDD not forced on"); + + intel_dp->want_panel_vdd = false; + +@@ -1128,7 +1129,8 @@ static void ironlake_edp_panel_off(struct intel_dp *intel_dp) + + DRM_DEBUG_KMS("Turn eDP power off\n"); + +- WARN(intel_dp->want_panel_vdd, "Cannot turn power off while VDD is on\n"); ++ if (intel_dp->want_panel_vdd) ++ DRM_ERROR("Cannot turn power off while VDD is on\n"); + + pp = ironlake_get_pp_control(dev_priv); + pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE); +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index 7cc92177d..823c367af 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -694,6 +694,7 @@ Patch1500: fix_xen_guest_on_old_EC2.patch # intel drm is all merged upstream Patch1824: drm-intel-next.patch +Patch1825: drm-i915-dp-stfu.patch # hush the i915 fbc noise Patch1826: drm-i915-fbc-stfu.patch @@ -1364,6 +1365,7 @@ ApplyPatch fix_xen_guest_on_old_EC2.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch +ApplyPatch drm-i915-dp-stfu.patch ApplyPatch drm-i915-fbc-stfu.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch @@ -2154,7 +2156,11 @@ fi # and build. %changelog -* Mon Mar 19 2012 Josh Boyer +* Mon Mar 19 2012 Adam Jackson - 3.3.0-2 +- drm-i915-dp-stfu.patch: Muzzle a bunch of DP WARN()s. They're not wrong, + but they're not helpful at this point. + +* Mon Mar 19 2012 Josh Boyer - 3.3.0-1 - Linux 3.3 - Drop compat-wireless infrastructure in preparation for 3.3 rebase From 85be624b7a7483af54e1be852f0e39c0a3f98ecb Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 20 Mar 2012 08:44:32 -0400 Subject: [PATCH 316/487] mac80211: fix possible tid_rx->reorder_timer use after free from Stanislaw Gruska (rhbz 804007) --- kernel.spec | 12 +++++- ...-tid_rx-reorder_timer-use-after-free.patch | 42 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch diff --git a/kernel.spec b/kernel.spec index 823c367af..7b7cde5a9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -765,6 +765,9 @@ Patch21244: mm-thp-fix-pmd_bad-triggering.patch Patch21300: unhandled-irqs-switch-to-polling.patch +#rhbz 804007 +Patch21305: mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch + Patch21350: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch Patch22000: weird-root-dentry-name-debug.patch @@ -1415,6 +1418,9 @@ ApplyPatch ACPICA-Fix-regression-in-FADT-revision-checks.patch #rhbz 728478 ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch +#rhbz 804007 +ApplyPatch mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch + ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch @@ -2156,6 +2162,10 @@ fi # and build. %changelog +* Tue Mar 20 2012 Josh Boyer +- mac80211: fix possible tid_rx->reorder_timer use after free + from Stanislaw Gruska (rhbz 804007) + * Mon Mar 19 2012 Adam Jackson - 3.3.0-2 - drm-i915-dp-stfu.patch: Muzzle a bunch of DP WARN()s. They're not wrong, but they're not helpful at this point. diff --git a/mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch b/mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch new file mode 100644 index 000000000..accda8afc --- /dev/null +++ b/mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch @@ -0,0 +1,42 @@ +Is possible that we will arm the tid_rx->reorder_timer after +del_timer_sync() in ___ieee80211_stop_rx_ba_session(). We need to stop +timer after RCU grace period finish, so move it to +ieee80211_free_tid_rx(). Timer will not be armed again, as +rcu_dereference(sta->ampdu_mlme.tid_rx[tid]) will return NULL. + +Debug object detected problem with the following warning: +ODEBUG: free active (active state 0) object type: timer_list hint: sta_rx_agg_reorder_timer_expired+0x0/0xf0 [mac80211] + +Bug report (with all warning messages): +https://bugzilla.redhat.com/show_bug.cgi?id=804007 + +Reported-by: "jan p. springer" +Cc: stable@vger.kernel.org +Signed-off-by: Stanislaw Gruszka +--- + net/mac80211/agg-rx.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c +index 1068f66..64d3ce5 100644 +--- a/net/mac80211/agg-rx.c ++++ b/net/mac80211/agg-rx.c +@@ -49,6 +49,8 @@ static void ieee80211_free_tid_rx(struct rcu_head *h) + container_of(h, struct tid_ampdu_rx, rcu_head); + int i; + ++ del_timer_sync(&tid_rx->reorder_timer); ++ + for (i = 0; i < tid_rx->buf_size; i++) + dev_kfree_skb(tid_rx->reorder_buf[i]); + kfree(tid_rx->reorder_buf); +@@ -91,7 +93,6 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, + tid, WLAN_BACK_RECIPIENT, reason); + + del_timer_sync(&tid_rx->session_timer); +- del_timer_sync(&tid_rx->reorder_timer); + + call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); + } +-- +1.7.1 From 8bc44875e2d854da4a48e4c1d1392e484c9cc31f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 20 Mar 2012 10:31:52 -0400 Subject: [PATCH 317/487] CVE-2012-1568: execshield: predictable ascii armour base address (rhbz 804957) --- kernel.spec | 9 ++++- shlib_base_randomize.patch | 69 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 shlib_base_randomize.patch diff --git a/kernel.spec b/kernel.spec index 7b7cde5a9..d4ca66f74 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -768,6 +768,9 @@ Patch21300: unhandled-irqs-switch-to-polling.patch #rhbz 804007 Patch21305: mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch +#rhbz 804957 CVE-2012-1568 +Patch21306: shlib_base_randomize.patch + Patch21350: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch Patch22000: weird-root-dentry-name-debug.patch @@ -1421,6 +1424,9 @@ ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch #rhbz 804007 ApplyPatch mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch +#rhbz 804957 CVE-2012-1568 +ApplyPatch shlib_base_randomize.patch + ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch @@ -2163,6 +2169,7 @@ fi %changelog * Tue Mar 20 2012 Josh Boyer +- CVE-2012-1568: execshield: predictable ascii armour base address (rhbz 804957) - mac80211: fix possible tid_rx->reorder_timer use after free from Stanislaw Gruska (rhbz 804007) diff --git a/shlib_base_randomize.patch b/shlib_base_randomize.patch new file mode 100644 index 000000000..80e4d644b --- /dev/null +++ b/shlib_base_randomize.patch @@ -0,0 +1,69 @@ +diff -uNrp kernel-3.2.fc16.orig/arch/x86/mm/mmap.c kernel-3.2.fc16.new/arch/x86/mm/mmap.c +--- kernel-3.2.fc16.orig/arch/x86/mm/mmap.c 2012-03-19 16:47:03.495169091 -0400 ++++ kernel-3.2.fc16.new/arch/x86/mm/mmap.c 2012-03-19 16:50:03.574168052 -0400 +@@ -106,6 +106,10 @@ static unsigned long mmap_legacy_base(vo + return TASK_UNMAPPED_BASE + mmap_rnd(); + } + ++#ifdef CONFIG_X86_32 ++ #define SHLIB_BASE 0x00111000 ++#endif ++ + /* + * This function, called very early during the creation of a new + * process VM image, sets up which VM layout function to use: +@@ -126,8 +126,10 @@ void arch_pick_mmap_layout(struct mm_str + #ifdef CONFIG_X86_32 + if (!(current->personality & READ_IMPLIES_EXEC) + && !(__supported_pte_mask & _PAGE_NX) +- && mmap_is_ia32()) ++ && mmap_is_ia32()) { ++ mm->shlib_base = SHLIB_BASE + mmap_rnd(); + mm->get_unmapped_exec_area = arch_get_unmapped_exec_area; ++ } + #endif + mm->unmap_area = arch_unmap_area_topdown; + } +diff -uNrp kernel-3.2.fc16.orig/include/linux/mm_types.h kernel-3.2.fc16.new/include/linux/mm_types.h +--- kernel-3.2.fc16.orig/include/linux/mm_types.h 2012-03-19 16:46:47.382169153 -0400 ++++ kernel-3.2.fc16.new/include/linux/mm_types.h 2012-03-19 16:50:40.738168219 -0400 +@@ -300,6 +300,7 @@ struct mm_struct { + void (*unmap_area) (struct mm_struct *mm, unsigned long addr); + #endif + unsigned long mmap_base; /* base of mmap area */ ++ unsigned long shlib_base; /* base of lib map area (ASCII armour)*/ + unsigned long task_size; /* size of task vm space */ + unsigned long cached_hole_size; /* if non-zero, the largest hole below free_area_cache */ + unsigned long free_area_cache; /* first hole of size cached_hole_size or larger */ +diff -uNrp kernel-3.2.fc16.orig/mm/mmap.c kernel-3.2.fc16.new/mm/mmap.c +--- kernel-3.2.fc16.orig/mm/mmap.c 2012-03-19 16:46:15.791169274 -0400 ++++ kernel-3.2.fc16.new/mm/mmap.c 2012-03-19 16:51:37.351166875 -0400 +@@ -1594,8 +1594,6 @@ static bool should_randomize(void) + !(current->personality & ADDR_NO_RANDOMIZE); + } + +-#define SHLIB_BASE 0x00110000 +- + unsigned long + arch_get_unmapped_exec_area(struct file *filp, unsigned long addr0, + unsigned long len0, unsigned long pgoff, unsigned long flags) +@@ -1612,8 +1610,8 @@ arch_get_unmapped_exec_area(struct file + return addr; + + if (!addr) +- addr = !should_randomize() ? SHLIB_BASE : +- randomize_range(SHLIB_BASE, 0x01000000, len); ++ addr = !should_randomize() ? mm->shlib_base : ++ randomize_range(mm->shlib_base, 0x01000000, len); + + if (addr) { + addr = PAGE_ALIGN(addr); +@@ -1623,7 +1621,7 @@ arch_get_unmapped_exec_area(struct file + return addr; + } + +- addr = SHLIB_BASE; ++ addr = mm->shlib_base; + for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { + /* At this point: (!vma || addr < vma->vm_end). */ + if (TASK_SIZE - len < addr) From e9dfffad72b17357732beb17953e1dc91edc082f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 21 Mar 2012 15:09:49 -0400 Subject: [PATCH 318/487] Ship hmac file for vmlinuz for FIPS-140 (rhbz 805538) --- kernel.spec | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index d4ca66f74..670abb6e1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -539,7 +539,7 @@ ExclusiveOS: Linux # BuildRequires: module-init-tools, patch >= 2.5.4, bash >= 2.03, sh-utils, tar BuildRequires: bzip2, xz, findutils, gzip, m4, perl, make >= 3.78, diffutils, gawk -BuildRequires: gcc >= 3.4.2, binutils >= 2.12, redhat-rpm-config +BuildRequires: gcc >= 3.4.2, binutils >= 2.12, redhat-rpm-config, hmaccalc BuildRequires: net-tools BuildRequires: xmlto, asciidoc %if %{with_sparse} @@ -1585,6 +1585,11 @@ BuildKernel() { $RPM_BUILD_ROOT/%{image_install_path}/$InstallName-$KernelVer chmod 755 $RPM_BUILD_ROOT/%{image_install_path}/$InstallName-$KernelVer + # hmac sign the kernel for FIPS + echo "Creating hmac file: $RPM_BUILD_ROOT/%{image_install_path}/.vmlinuz-$KernelVer.hmac" + ls -l $RPM_BUILD_ROOT/%{image_install_path}/$InstallName-$KernelVer + sha512hmac $RPM_BUILD_ROOT/%{image_install_path}/$InstallName-$KernelVer | sed -e "s,$RPM_BUILD_ROOT,," > $RPM_BUILD_ROOT/%{image_install_path}/.vmlinuz-$KernelVer.hmac; + mkdir -p $RPM_BUILD_ROOT/lib/modules/$KernelVer # Override $(mod-fw) because we don't want it to install any firmware # We'll do that ourselves with 'make firmware_install' @@ -2115,6 +2120,7 @@ fi %{expand:%%files %{?2}}\ %defattr(-,root,root)\ /%{image_install_path}/%{?-k:%{-k*}}%{!?-k:vmlinuz}-%{KVERREL}%{?2:.%{2}}\ +/%{image_install_path}/.vmlinuz-%{KVERREL}%{?2:.%{2}}.hmac \ %attr(600,root,root) /boot/System.map-%{KVERREL}%{?2:.%{2}}\ /boot/config-%{KVERREL}%{?2:.%{2}}\ %dir /lib/modules/%{KVERREL}%{?2:.%{2}}\ @@ -2168,6 +2174,9 @@ fi # and build. %changelog +* Wed Mar 21 2012 Josh Boyer +- Ship hmac file for vmlinuz for FIPS-140 (rhbz 805538) + * Tue Mar 20 2012 Josh Boyer - CVE-2012-1568: execshield: predictable ascii armour base address (rhbz 804957) - mac80211: fix possible tid_rx->reorder_timer use after free From 4721953b8b31d8031170f4ddd8f87549e592bac2 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 23 Mar 2012 12:15:34 -0400 Subject: [PATCH 319/487] Apply patches that should solve the bluetooth use-after-free oopses. (rhbz 806033) --- bluetooth-use-after-free.patch | 105 +++++++++++++++++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 112 insertions(+) create mode 100644 bluetooth-use-after-free.patch diff --git a/bluetooth-use-after-free.patch b/bluetooth-use-after-free.patch new file mode 100644 index 000000000..0d21cad9a --- /dev/null +++ b/bluetooth-use-after-free.patch @@ -0,0 +1,105 @@ +From 2a5a5ec620a29d4ba07743c3151cdf0a417c8f8c Mon Sep 17 00:00:00 2001 +From: Andrei Emeltchenko +Date: Thu, 2 Feb 2012 10:32:18 +0200 +Subject: [PATCH] Bluetooth: Use list _safe deleting from conn chan_list + +Fixes possible bug when deleting element from the list in +function hci_chan_list_flush. list_for_each_entry_rcu is used +and after deleting element from the list we also free pointer +and then list_entry_rcu is taken from freed pointer. + +Signed-off-by: Andrei Emeltchenko +Acked-by: Marcel Holtmann +Signed-off-by: Johan Hedberg +--- + net/bluetooth/hci_conn.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index b074bd6..b4ecdde 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -975,10 +975,10 @@ int hci_chan_del(struct hci_chan *chan) + + void hci_chan_list_flush(struct hci_conn *conn) + { +- struct hci_chan *chan; ++ struct hci_chan *chan, *n; + + BT_DBG("conn %p", conn); + +- list_for_each_entry_rcu(chan, &conn->chan_list, list) ++ list_for_each_entry_safe(chan, n, &conn->chan_list, list) + hci_chan_del(chan); + } +-- +1.7.6.5 + +From 3c4e0df028935618d052235ba85bc7079be13394 Mon Sep 17 00:00:00 2001 +From: Andrei Emeltchenko +Date: Thu, 2 Feb 2012 10:32:17 +0200 +Subject: [PATCH] Bluetooth: Use list _safe deleting from conn_hash_list + +Use list_for_each_entry_safe which is safe version against removal +of list entry. Otherwise we remove hci_conn element and reference +next element which result in accessing LIST_POISON. + +[ 95.571834] Bluetooth: unknown link type 127 +[ 95.578349] BUG: unable to handle kernel paging request at 20002000 +[ 95.580236] IP: [<20002000>] 0x20001fff +[ 95.580763] *pde = 00000000 +[ 95.581196] Oops: 0000 [#1] SMP +... +[ 95.582298] Pid: 3355, comm: hciconfig Tainted: G O 3.2.0-VirttualBox +[ 95.582298] EIP: 0060:[<20002000>] EFLAGS: 00210206 CPU: 0 +[ 95.582298] EIP is at 0x20002000 +... +[ 95.582298] Call Trace: +[ 95.582298] [] ? hci_conn_hash_flush+0x76/0xf0 [bluetooth] +[ 95.582298] [] hci_dev_do_close+0xc1/0x2e0 [bluetooth] +[ 95.582298] [] ? hci_dev_get+0x69/0xb0 [bluetooth] +[ 95.582298] [] hci_dev_close+0x2a/0x50 [bluetooth] +[ 95.582298] [] hci_sock_ioctl+0x1af/0x3f0 [bluetooth] +[ 95.582298] [] ? handle_pte_fault+0x8a/0x8f0 +[ 95.582298] [] sock_ioctl+0x5f/0x260 +[ 95.582298] [] ? sock_fasync+0x90/0x90 +[ 95.582298] [] do_vfs_ioctl+0x83/0x5b0 +[ 95.582298] [] ? do_page_fault+0x297/0x500 +[ 95.582298] [] ? spurious_fault+0xd0/0xd0 +[ 95.582298] [] ? up_read+0x1b/0x30 +[ 95.582298] [] ? do_page_fault+0x297/0x500 +[ 95.582298] [] ? init_fpu+0xef/0x160 +[ 95.582298] [] ? do_debug+0x180/0x180 +[ 95.582298] [] ? fpu_finit+0x28/0x80 +[ 95.582298] [] sys_ioctl+0x87/0x90 +[ 95.582298] [] sysenter_do_call+0x12/0x38 +... + +Signed-off-by: Andrei Emeltchenko +Acked-by: Marcel Holtmann +Signed-off-by: Johan Hedberg +--- + net/bluetooth/hci_conn.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index aca71c0..b074bd6 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -795,11 +795,11 @@ timer: + void hci_conn_hash_flush(struct hci_dev *hdev) + { + struct hci_conn_hash *h = &hdev->conn_hash; +- struct hci_conn *c; ++ struct hci_conn *c, *n; + + BT_DBG("hdev %s", hdev->name); + +- list_for_each_entry_rcu(c, &h->list, list) { ++ list_for_each_entry_safe(c, n, &h->list, list) { + c->state = BT_CLOSED; + + hci_proto_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM); +-- +1.7.6.5 + diff --git a/kernel.spec b/kernel.spec index 670abb6e1..8284e1838 100644 --- a/kernel.spec +++ b/kernel.spec @@ -732,6 +732,8 @@ Patch14000: hibernate-freeze-filesystems.patch Patch14010: lis3-improve-handling-of-null-rate.patch +Patch15000: bluetooth-use-after-free.patch + Patch20000: utrace.patch # Flattened devicetree support @@ -1399,6 +1401,8 @@ ApplyPatch hibernate-freeze-filesystems.patch ApplyPatch lis3-improve-handling-of-null-rate.patch +ApplyPatch bluetooth-use-after-free.patch + # utrace. ApplyPatch utrace.patch @@ -2174,6 +2178,9 @@ fi # and build. %changelog +* Fri Mar 23 2012 Dave Jones +- Apply patches that should solve the bluetooth use-after-free oopses. (rhbz 806033) + * Wed Mar 21 2012 Josh Boyer - Ship hmac file for vmlinuz for FIPS-140 (rhbz 805538) From 5d30d9525ad3f184e2bf3790ab5de573dc82e558 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 27 Mar 2012 09:02:02 -0400 Subject: [PATCH 320/487] Apply patch to fix MCE rcu splat (rhbz 789644) --- kernel.spec | 11 ++++++++++- mcelog-rcu-splat.patch | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 mcelog-rcu-splat.patch diff --git a/kernel.spec b/kernel.spec index 8284e1838..b3e584d51 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 5 +%global baserelease 6 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -756,6 +756,9 @@ Patch21233: jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch #rhbz 754518 #Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch +#rhbz 789644 +Patch21237: mcelog-rcu-splat.patch + #rhbz 727865 730007 Patch21240: ACPICA-Fix-regression-in-FADT-revision-checks.patch @@ -1419,6 +1422,9 @@ ApplyPatch jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch #rhbz 754518 #ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch +#rhbz 789644 +ApplyPatch mcelog-rcu-splat.patch + #rhbz 727865 730007 ApplyPatch ACPICA-Fix-regression-in-FADT-revision-checks.patch @@ -2178,6 +2184,9 @@ fi # and build. %changelog +* Tue Mar 27 2012 Josh Boyer +- Apply patch to fix MCE rcu splat (rhbz 789644) + * Fri Mar 23 2012 Dave Jones - Apply patches that should solve the bluetooth use-after-free oopses. (rhbz 806033) diff --git a/mcelog-rcu-splat.patch b/mcelog-rcu-splat.patch new file mode 100644 index 000000000..12c1fe3ea --- /dev/null +++ b/mcelog-rcu-splat.patch @@ -0,0 +1,15 @@ +diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c +index f22a9f7..f525f99 100644 +--- a/arch/x86/kernel/cpu/mcheck/mce.c ++++ b/arch/x86/kernel/cpu/mcheck/mce.c +@@ -191,7 +191,7 @@ static void drain_mcelog_buffer(void) + { + unsigned int next, i, prev = 0; + +- next = rcu_dereference_check_mce(mcelog.next); ++ next = ACCESS_ONCE(mcelog.next); + + do { + struct mce *m; + + \ No newline at end of file From 890cdcf1b4360d6bbc8910ca93f5a23431cd3194 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 27 Mar 2012 12:13:33 -0400 Subject: [PATCH 321/487] Implement xen apic_ops to fix early crash in Xen Dom0 (rhbz 804347) --- kernel.spec | 13 +- ...dd-io_apic_ops-to-allow-interception.patch | 135 +++++++++ ...s-Replace-apic_ops-with-x86_apic_ops.patch | 258 ++++++++++++++++++ xen-x86-Implement-x86_apic_ops.patch | 85 ++++++ 4 files changed, 490 insertions(+), 1 deletion(-) create mode 100644 x86-add-io_apic_ops-to-allow-interception.patch create mode 100644 x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch create mode 100644 xen-x86-Implement-x86_apic_ops.patch diff --git a/kernel.spec b/kernel.spec index b3e584d51..5c971979d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 6 +%global baserelease 7 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -778,6 +778,11 @@ Patch21306: shlib_base_randomize.patch Patch21350: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch +#rhbz 804347 +Patch21351: x86-add-io_apic_ops-to-allow-interception.patch +Patch21352: x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch +Patch21353: xen-x86-Implement-x86_apic_ops.patch + Patch22000: weird-root-dentry-name-debug.patch %endif @@ -1443,6 +1448,11 @@ ApplyPatch weird-root-dentry-name-debug.patch ApplyPatch x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch +#rhbz 804347 +ApplyPatch x86-add-io_apic_ops-to-allow-interception.patch +ApplyPatch x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch +ApplyPatch xen-x86-Implement-x86_apic_ops.patch + #rhbz 803809 CVE-2012-1179 ApplyPatch mm-thp-fix-pmd_bad-triggering.patch @@ -2185,6 +2195,7 @@ fi %changelog * Tue Mar 27 2012 Josh Boyer +- Implement xen apic_ops to fix early crash in Xen Dom0 (rhbz 804347) - Apply patch to fix MCE rcu splat (rhbz 789644) * Fri Mar 23 2012 Dave Jones diff --git a/x86-add-io_apic_ops-to-allow-interception.patch b/x86-add-io_apic_ops-to-allow-interception.patch new file mode 100644 index 000000000..c82d21fff --- /dev/null +++ b/x86-add-io_apic_ops-to-allow-interception.patch @@ -0,0 +1,135 @@ +From: Jeremy Fitzhardinge + +Xen dom0 needs to paravirtualize IO operations to the IO APIC, so add +a io_apic_ops for it to intercept. Do this as ops structure because +there's at least some chance that another paravirtualized environment +may want to intercept these. + +[ Impact: indirect IO APIC access via io_apic_ops ] + +Signed-off-by: Jeremy Fitzhardinge +Signed-off-by: Konrad Rzeszutek Wilk +Acked-by: Suresh Siddha +--- + arch/x86/include/asm/io_apic.h | 9 +++++++ + arch/x86/kernel/apic/io_apic.c | 50 +++++++++++++++++++++++++++++++++++++-- + 2 files changed, 56 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h +index 690d1cc..190d8c2 100644 +--- a/arch/x86/include/asm/io_apic.h ++++ b/arch/x86/include/asm/io_apic.h +@@ -21,6 +21,15 @@ + #define IO_APIC_REDIR_LEVEL_TRIGGER (1 << 15) + #define IO_APIC_REDIR_MASKED (1 << 16) + ++struct io_apic_ops { ++ void (*init)(void); ++ unsigned int (*read)(unsigned int apic, unsigned int reg); ++ void (*write)(unsigned int apic, unsigned int reg, unsigned int value); ++ void (*modify)(unsigned int apic, unsigned int reg, unsigned int value); ++}; ++ ++void __init set_io_apic_ops(const struct io_apic_ops *); ++ + /* + * The structure of the IO-APIC: + */ +diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c +index fb07275..bf120234 100644 +--- a/arch/x86/kernel/apic/io_apic.c ++++ b/arch/x86/kernel/apic/io_apic.c +@@ -67,6 +67,25 @@ + #define for_each_irq_pin(entry, head) \ + for (entry = head; entry; entry = entry->next) + ++static void __init __ioapic_init_mappings(void); ++static unsigned int __io_apic_read(unsigned int apic, unsigned int reg); ++static void __io_apic_write(unsigned int apic, unsigned int reg, ++ unsigned int val); ++static void __io_apic_modify(unsigned int apic, unsigned int reg, ++ unsigned int val); ++ ++static struct io_apic_ops io_apic_ops = { ++ .init = __ioapic_init_mappings, ++ .read = __io_apic_read, ++ .write = __io_apic_write, ++ .modify = __io_apic_modify, ++}; ++ ++void __init set_io_apic_ops(const struct io_apic_ops *ops) ++{ ++ io_apic_ops = *ops; ++} ++ + /* + * Is the SiS APIC rmw bug present ? + * -1 = don't know, 0 = no, 1 = yes +@@ -294,6 +313,24 @@ static void free_irq_at(unsigned int at, struct irq_cfg *cfg) + irq_free_desc(at); + } + ++static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) ++{ ++ return io_apic_ops.read(apic, reg); ++} ++ ++static inline void io_apic_write(unsigned int apic, unsigned int reg, ++ unsigned int value) ++{ ++ io_apic_ops.write(apic, reg, value); ++} ++ ++static inline void io_apic_modify(unsigned int apic, unsigned int reg, ++ unsigned int value) ++{ ++ io_apic_ops.modify(apic, reg, value); ++} ++ ++ + struct io_apic { + unsigned int index; + unsigned int unused[3]; +@@ -314,14 +351,15 @@ static inline void io_apic_eoi(unsigned int apic, unsigned int vector) + writel(vector, &io_apic->eoi); + } + +-static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) ++static unsigned int __io_apic_read(unsigned int apic, unsigned int reg) + { + struct io_apic __iomem *io_apic = io_apic_base(apic); + writel(reg, &io_apic->index); + return readl(&io_apic->data); + } + +-static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) ++static void __io_apic_write(unsigned int apic, unsigned int reg, ++ unsigned int value) + { + struct io_apic __iomem *io_apic = io_apic_base(apic); + writel(reg, &io_apic->index); +@@ -334,7 +372,8 @@ static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned i + * + * Older SiS APIC requires we rewrite the index register + */ +-static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) ++static void __io_apic_modify(unsigned int apic, unsigned int reg, ++ unsigned int value) + { + struct io_apic __iomem *io_apic = io_apic_base(apic); + +@@ -3873,6 +3912,11 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics) + + void __init ioapic_and_gsi_init(void) + { ++ io_apic_ops.init(); ++} ++ ++static void __init __ioapic_init_mappings(void) ++{ + unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; + struct resource *ioapic_res; + int i; +-- +1.7.7.5 + diff --git a/x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch b/x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch new file mode 100644 index 000000000..ddbb92412 --- /dev/null +++ b/x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch @@ -0,0 +1,258 @@ +. which makes the code fit within the rest of the x86_ops functions. + +Signed-off-by: Konrad Rzeszutek Wilk +[v1: Changed x86_apic -> x86_ioapic per Yinghai Lu suggestion] +Acked-by: Suresh Siddha +--- + arch/x86/include/asm/io_apic.h | 40 +++++++++++++++++++++-------- + arch/x86/include/asm/x86_init.h | 8 ++++++ + arch/x86/kernel/apic/io_apic.c | 54 ++++---------------------------------- + arch/x86/kernel/setup.c | 2 +- + arch/x86/kernel/x86_init.c | 8 ++++++ + 5 files changed, 52 insertions(+), 60 deletions(-) + +diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h +index 190d8c2..ba1b11a 100644 +--- a/arch/x86/include/asm/io_apic.h ++++ b/arch/x86/include/asm/io_apic.h +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + + /* + * Intel IO-APIC support for SMP and UP systems. +@@ -21,15 +22,6 @@ + #define IO_APIC_REDIR_LEVEL_TRIGGER (1 << 15) + #define IO_APIC_REDIR_MASKED (1 << 16) + +-struct io_apic_ops { +- void (*init)(void); +- unsigned int (*read)(unsigned int apic, unsigned int reg); +- void (*write)(unsigned int apic, unsigned int reg, unsigned int value); +- void (*modify)(unsigned int apic, unsigned int reg, unsigned int value); +-}; +- +-void __init set_io_apic_ops(const struct io_apic_ops *); +- + /* + * The structure of the IO-APIC: + */ +@@ -156,7 +148,6 @@ struct io_apic_irq_attr; + extern int io_apic_set_pci_routing(struct device *dev, int irq, + struct io_apic_irq_attr *irq_attr); + void setup_IO_APIC_irq_extra(u32 gsi); +-extern void ioapic_and_gsi_init(void); + extern void ioapic_insert_resources(void); + + int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr); +@@ -185,12 +176,35 @@ extern void mp_save_irq(struct mpc_intsrc *m); + + extern void disable_ioapic_support(void); + ++ ++void __init native_ioapic_init_mappings(void); ++unsigned int native_ioapic_read(unsigned int apic, unsigned int reg); ++void native_ioapic_write(unsigned int apic, unsigned int reg, ++ unsigned int val); ++void native_ioapic_modify(unsigned int apic, unsigned int reg, ++ unsigned int val); ++ ++static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) ++{ ++ return x86_ioapic.read(apic, reg); ++} ++ ++static inline void io_apic_write(unsigned int apic, unsigned int reg, ++ unsigned int value) ++{ ++ x86_ioapic.write(apic, reg, value); ++} ++ ++static inline void io_apic_modify(unsigned int apic, unsigned int reg, ++ unsigned int value) ++{ ++ x86_ioapic.modify(apic, reg, value); ++} + #else /* !CONFIG_X86_IO_APIC */ + + #define io_apic_assign_pci_irqs 0 + #define setup_ioapic_ids_from_mpc x86_init_noop + static const int timer_through_8259 = 0; +-static inline void ioapic_and_gsi_init(void) { } + static inline void ioapic_insert_resources(void) { } + #define gsi_top (NR_IRQS_LEGACY) + static inline int mp_find_ioapic(u32 gsi) { return 0; } +@@ -212,6 +226,10 @@ static inline int restore_ioapic_entries(void) + + static inline void mp_save_irq(struct mpc_intsrc *m) { }; + static inline void disable_ioapic_support(void) { } ++#define native_ioapic_init_mappings NULL ++#define native_ioapic_read NULL ++#define native_ioapic_write NULL ++#define native_ioapic_modify NULL + #endif + + #endif /* _ASM_X86_IO_APIC_H */ +diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h +index 517d476..a3730cc 100644 +--- a/arch/x86/include/asm/x86_init.h ++++ b/arch/x86/include/asm/x86_init.h +@@ -182,10 +182,18 @@ struct x86_msi_ops { + void (*restore_msi_irqs)(struct pci_dev *dev, int irq); + }; + ++struct x86_ioapic_ops { ++ void (*init)(void); ++ unsigned int (*read)(unsigned int apic, unsigned int reg); ++ void (*write)(unsigned int apic, unsigned int reg, unsigned int value); ++ void (*modify)(unsigned int apic, unsigned int reg, unsigned int value); ++}; ++ + extern struct x86_init_ops x86_init; + extern struct x86_cpuinit_ops x86_cpuinit; + extern struct x86_platform_ops x86_platform; + extern struct x86_msi_ops x86_msi; ++extern struct x86_ioapic_ops x86_ioapic; + + extern void x86_init_noop(void); + extern void x86_init_uint_noop(unsigned int unused); +diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c +index bf120234..9a15d4b 100644 +--- a/arch/x86/kernel/apic/io_apic.c ++++ b/arch/x86/kernel/apic/io_apic.c +@@ -67,25 +67,6 @@ + #define for_each_irq_pin(entry, head) \ + for (entry = head; entry; entry = entry->next) + +-static void __init __ioapic_init_mappings(void); +-static unsigned int __io_apic_read(unsigned int apic, unsigned int reg); +-static void __io_apic_write(unsigned int apic, unsigned int reg, +- unsigned int val); +-static void __io_apic_modify(unsigned int apic, unsigned int reg, +- unsigned int val); +- +-static struct io_apic_ops io_apic_ops = { +- .init = __ioapic_init_mappings, +- .read = __io_apic_read, +- .write = __io_apic_write, +- .modify = __io_apic_modify, +-}; +- +-void __init set_io_apic_ops(const struct io_apic_ops *ops) +-{ +- io_apic_ops = *ops; +-} +- + /* + * Is the SiS APIC rmw bug present ? + * -1 = don't know, 0 = no, 1 = yes +@@ -313,24 +294,6 @@ static void free_irq_at(unsigned int at, struct irq_cfg *cfg) + irq_free_desc(at); + } + +-static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) +-{ +- return io_apic_ops.read(apic, reg); +-} +- +-static inline void io_apic_write(unsigned int apic, unsigned int reg, +- unsigned int value) +-{ +- io_apic_ops.write(apic, reg, value); +-} +- +-static inline void io_apic_modify(unsigned int apic, unsigned int reg, +- unsigned int value) +-{ +- io_apic_ops.modify(apic, reg, value); +-} +- +- + struct io_apic { + unsigned int index; + unsigned int unused[3]; +@@ -351,15 +314,15 @@ static inline void io_apic_eoi(unsigned int apic, unsigned int vector) + writel(vector, &io_apic->eoi); + } + +-static unsigned int __io_apic_read(unsigned int apic, unsigned int reg) ++unsigned int native_ioapic_read(unsigned int apic, unsigned int reg) + { + struct io_apic __iomem *io_apic = io_apic_base(apic); + writel(reg, &io_apic->index); + return readl(&io_apic->data); + } + +-static void __io_apic_write(unsigned int apic, unsigned int reg, +- unsigned int value) ++void native_ioapic_write(unsigned int apic, unsigned int reg, ++ unsigned int value) + { + struct io_apic __iomem *io_apic = io_apic_base(apic); + writel(reg, &io_apic->index); +@@ -372,8 +335,8 @@ static void __io_apic_write(unsigned int apic, unsigned int reg, + * + * Older SiS APIC requires we rewrite the index register + */ +-static void __io_apic_modify(unsigned int apic, unsigned int reg, +- unsigned int value) ++void native_ioapic_modify(unsigned int apic, unsigned int reg, ++ unsigned int value) + { + struct io_apic __iomem *io_apic = io_apic_base(apic); + +@@ -3910,12 +3873,7 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics) + return res; + } + +-void __init ioapic_and_gsi_init(void) +-{ +- io_apic_ops.init(); +-} +- +-static void __init __ioapic_init_mappings(void) ++void __init native_ioapic_init_mappings(void) + { + unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; + struct resource *ioapic_res; +diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c +index d7d5099..7eaef1a 100644 +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -1016,7 +1016,7 @@ void __init setup_arch(char **cmdline_p) + init_cpu_to_node(); + + init_apic_mappings(); +- ioapic_and_gsi_init(); ++ x86_ioapic.init(); + + kvm_guest_init(); + +diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c +index 947a06c..df870d3 100644 +--- a/arch/x86/kernel/x86_init.c ++++ b/arch/x86/kernel/x86_init.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -117,3 +118,10 @@ struct x86_msi_ops x86_msi = { + .teardown_msi_irqs = default_teardown_msi_irqs, + .restore_msi_irqs = default_restore_msi_irqs, + }; ++ ++struct x86_ioapic_ops x86_ioapic = { ++ .init = native_ioapic_init_mappings, ++ .read = native_ioapic_read, ++ .write = native_ioapic_write, ++ .modify = native_ioapic_modify, ++}; +-- +1.7.7.5 + diff --git a/xen-x86-Implement-x86_apic_ops.patch b/xen-x86-Implement-x86_apic_ops.patch new file mode 100644 index 000000000..0963ecb25 --- /dev/null +++ b/xen-x86-Implement-x86_apic_ops.patch @@ -0,0 +1,85 @@ +Or rather just implement one different function as opposed +to the native one : the read function. + +We synthesize the values. + +Acked-by: Suresh Siddha +Signed-off-by: Konrad Rzeszutek Wilk +--- + arch/x86/xen/Makefile | 2 +- + arch/x86/xen/apic.c | 17 +++++++++++++++++ + arch/x86/xen/enlighten.c | 2 ++ + arch/x86/xen/xen-ops.h | 4 ++++ + 4 files changed, 24 insertions(+), 1 deletions(-) + create mode 100644 arch/x86/xen/apic.c + +diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile +index add2c2d..96ab2c0 100644 +--- a/arch/x86/xen/Makefile ++++ b/arch/x86/xen/Makefile +@@ -20,5 +20,5 @@ obj-$(CONFIG_EVENT_TRACING) += trace.o + obj-$(CONFIG_SMP) += smp.o + obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o + obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o +-obj-$(CONFIG_XEN_DOM0) += vga.o ++obj-$(CONFIG_XEN_DOM0) += apic.o vga.o + obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o +diff --git a/arch/x86/xen/apic.c b/arch/x86/xen/apic.c +new file mode 100644 +index 0000000..71ed91c +--- /dev/null ++++ b/arch/x86/xen/apic.c +@@ -0,0 +1,17 @@ ++#include ++#include ++ ++unsigned int xen_io_apic_read(unsigned apic, unsigned reg) ++{ ++ if (reg == 0x1) ++ return 0x00170020; ++ else if (reg == 0x0) ++ return apic << 24; ++ ++ return 0xff; ++} ++ ++void __init xen_init_apic(void) ++{ ++ x86_ioapic.read = xen_io_apic_read; ++} +diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c +index 0732326..93a03195 100644 +--- a/arch/x86/xen/enlighten.c ++++ b/arch/x86/xen/enlighten.c +@@ -1377,6 +1377,8 @@ asmlinkage void __init xen_start_kernel(void) + xen_start_info->console.domU.mfn = 0; + xen_start_info->console.domU.evtchn = 0; + ++ xen_init_apic(); ++ + /* Make sure ACS will be enabled */ + pci_request_acs(); + +diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h +index b095739..45c0c06 100644 +--- a/arch/x86/xen/xen-ops.h ++++ b/arch/x86/xen/xen-ops.h +@@ -92,11 +92,15 @@ struct dom0_vga_console_info; + + #ifdef CONFIG_XEN_DOM0 + void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size); ++void __init xen_init_apic(void); + #else + static inline void __init xen_init_vga(const struct dom0_vga_console_info *info, + size_t size) + { + } ++static inline void __init xen_init_apic(void) ++{ ++} + #endif + + /* Declare an asm function, along with symbols needed to make it +-- +1.7.7.5 + From cb6adeaa2b61399606cc3bbb8ad120e93dd6362b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 20 Mar 2012 16:50:59 -0400 Subject: [PATCH 322/487] Don't bind the IPS driver if no irq is assigned (typically BIOS bug). (rhbz 804353) --- ips-noirq.patch | 15 +++++++++++++++ kernel.spec | 7 +++++++ 2 files changed, 22 insertions(+) create mode 100644 ips-noirq.patch diff --git a/ips-noirq.patch b/ips-noirq.patch new file mode 100644 index 000000000..95837ecf4 --- /dev/null +++ b/ips-noirq.patch @@ -0,0 +1,15 @@ +--- a/drivers/platform/x86/intel_ips.c ++++ a/drivers/platform/x86/intel_ips.c +@@ -1603,6 +1603,12 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) + goto error_unmap; + } + ++ /* No IRQ assigned is a BIOS failure... */ ++ if (dev->irq <= 0) { ++ ret = -ENODEV; ++ goto error_unmap; ++ } ++ + /* + * IRQ handler for ME interaction + * Note: don't use MSI here as the PCH has bugs. diff --git a/kernel.spec b/kernel.spec index 5c971979d..615201d9a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -734,6 +734,8 @@ Patch14010: lis3-improve-handling-of-null-rate.patch Patch15000: bluetooth-use-after-free.patch +Patch19000: ips-noirq.patch + Patch20000: utrace.patch # Flattened devicetree support @@ -1411,6 +1413,8 @@ ApplyPatch lis3-improve-handling-of-null-rate.patch ApplyPatch bluetooth-use-after-free.patch +ApplyPatch ips-noirq.patch + # utrace. ApplyPatch utrace.patch @@ -2194,6 +2198,9 @@ fi # and build. %changelog +* Wed Mar 28 2012 Dave Jones +- Don't bind the IPS driver if no irq is assigned (typically BIOS bug). (rhbz 804353) + * Tue Mar 27 2012 Josh Boyer - Implement xen apic_ops to fix early crash in Xen Dom0 (rhbz 804347) - Apply patch to fix MCE rcu splat (rhbz 789644) From 964eeef941fe5ab32e3f5d8f1d2d80425c37749b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 28 Mar 2012 13:12:02 -0400 Subject: [PATCH 323/487] Fix disabled ASPM regression --- ...Fix-pcie-devs-with-non-pcie-children.patch | 48 +++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 55 insertions(+) create mode 100644 ASPM-Fix-pcie-devs-with-non-pcie-children.patch diff --git a/ASPM-Fix-pcie-devs-with-non-pcie-children.patch b/ASPM-Fix-pcie-devs-with-non-pcie-children.patch new file mode 100644 index 000000000..2f52fa870 --- /dev/null +++ b/ASPM-Fix-pcie-devs-with-non-pcie-children.patch @@ -0,0 +1,48 @@ +Commit 4949be16822e92a18ea0cc1616319926628092ee changed the behaviour of +pcie_aspm_sanity_check() to always return 0 if aspm is disabled, in order +to avoid cases where we changed ASPM state on pre-PCIe 1.1 devices. This +skipped the secondary function of pcie_aspm_sanity_check which was to avoid +us enabling ASPM on devices that had non-PCIe children, causing us to hit +a BUG_ON later on. Move the aspm_disabled check so we continue to honour +that scenario. + +Signed-off-by: Matthew Garrett +Cc: stable@vger.kernel.org +--- + drivers/pci/pcie/aspm.c | 13 ++++++++++--- + 1 files changed, 10 insertions(+), 3 deletions(-) +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index 86111d9..41e367b 100644 +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -521,9 +521,6 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) + int pos; + u32 reg32; + +- if (aspm_disabled) +- return 0; +- + /* + * Some functions in a slot might not all be PCIe functions, + * very strange. Disable ASPM for the whole slot +@@ -532,6 +529,16 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) + pos = pci_pcie_cap(child); + if (!pos) + return -EINVAL; ++ ++ /* ++ * If ASPM is disabled then we're not going to change ++ * the BIOS state. It's safe to continue even if it's a ++ * pre-1.1 device ++ */ ++ ++ if (aspm_disabled) ++ continue; ++ + /* + * Disable ASPM for pre-1.1 PCIe device, we follow MS to use + * RBER bit to determine if a function is 1.1 version device +-- +1.7.7.6 + + diff --git a/kernel.spec b/kernel.spec index 615201d9a..f1f4c2255 100644 --- a/kernel.spec +++ b/kernel.spec @@ -785,6 +785,8 @@ Patch21351: x86-add-io_apic_ops-to-allow-interception.patch Patch21352: x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch Patch21353: xen-x86-Implement-x86_apic_ops.patch +Patch21500: ASPM-Fix-pcie-devs-with-non-pcie-children.patch + Patch22000: weird-root-dentry-name-debug.patch %endif @@ -1460,6 +1462,8 @@ ApplyPatch xen-x86-Implement-x86_apic_ops.patch #rhbz 803809 CVE-2012-1179 ApplyPatch mm-thp-fix-pmd_bad-triggering.patch +ApplyPatch ASPM-Fix-pcie-devs-with-non-pcie-children.patch + # END OF PATCH APPLICATIONS %endif @@ -2198,6 +2202,9 @@ fi # and build. %changelog +* Wed Mar 28 2012 Josh Boyer +- Fix disabled ASPM regression + * Wed Mar 28 2012 Dave Jones - Don't bind the IPS driver if no irq is assigned (typically BIOS bug). (rhbz 804353) From 44e6a69b2a5a7cfb8251561c2bfb2d3057eaded9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 28 Mar 2012 11:56:33 -0400 Subject: [PATCH 324/487] iwl{wifi,legacy}: Fix warnings on remove interface from Stanislaw Gruszka (rhbz 770467) --- iwlegacy-do-not-nulify-il-vif-on-reset.patch | 77 ++++++++++++++++++++ iwlwifi-do-not-nulify-ctx-vif-on-reset.patch | 66 +++++++++++++++++ kernel.spec | 12 +++ 3 files changed, 155 insertions(+) create mode 100644 iwlegacy-do-not-nulify-il-vif-on-reset.patch create mode 100644 iwlwifi-do-not-nulify-ctx-vif-on-reset.patch diff --git a/iwlegacy-do-not-nulify-il-vif-on-reset.patch b/iwlegacy-do-not-nulify-il-vif-on-reset.patch new file mode 100644 index 000000000..d1913d708 --- /dev/null +++ b/iwlegacy-do-not-nulify-il-vif-on-reset.patch @@ -0,0 +1,77 @@ +This il->vif is dereferenced in different part of iwlegacy code, so do +not nullify it. This should fix random crashes observed in companion +with microcode errors i.e. crash in il3945_config_ap(). + +Additionally this should address also +WARNING: at drivers/net/wireless/iwlegacy/common.c:4656 il_mac_remove_interface +at least one of the possible reasons of that warning. + +Cc: stable@vger.kernel.org +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/iwlegacy/3945-mac.c | 2 -- + drivers/net/wireless/iwlegacy/4965-mac.c | 2 -- + drivers/net/wireless/iwlegacy/common.c | 15 ++++++++++++--- + 3 files changed, 12 insertions(+), 7 deletions(-) + +--- linux-3.3.noarch.orig/drivers/net/wireless/iwlegacy/3945-mac.c ++++ linux-3.3.noarch/drivers/net/wireless/iwlegacy/3945-mac.c +@@ -2684,7 +2684,6 @@ il3945_bg_restart(struct work_struct *da + + if (test_and_clear_bit(S_FW_ERROR, &il->status)) { + mutex_lock(&il->mutex); +- il->ctx.vif = NULL; + il->is_open = 0; + mutex_unlock(&il->mutex); + il3945_down(il); +--- linux-3.3.noarch.orig/drivers/net/wireless/iwlegacy/4965-mac.c ++++ linux-3.3.noarch/drivers/net/wireless/iwlegacy/4965-mac.c +@@ -5381,7 +5381,6 @@ il4965_bg_restart(struct work_struct *da + + if (test_and_clear_bit(S_FW_ERROR, &il->status)) { + mutex_lock(&il->mutex); +- il->ctx.vif = NULL; + il->is_open = 0; + + __il4965_down(il); +--- linux-3.3.noarch.orig/drivers/net/wireless/iwlegacy/common.c ++++ linux-3.3.noarch/drivers/net/wireless/iwlegacy/common.c +@@ -4575,6 +4575,7 @@ il_mac_add_interface(struct ieee80211_hw + struct il_priv *il = hw->priv; + struct il_vif_priv *vif_priv = (void *)vif->drv_priv; + int err; ++ bool reset; + u32 modes; + + D_MAC80211("enter: type %d, addr %pM\n", vif->type, vif->addr); +@@ -4594,6 +4595,16 @@ il_mac_add_interface(struct ieee80211_hw + goto out; + } + ++ /* ++ * We do not support multiple virtual interfaces, but on hardware reset ++ * we have to add the same interface again. ++ */ ++ reset = (il->ctx.vif == vif); ++ if (il->ctx.vif && !reset) { ++ err = -EOPNOTSUPP; ++ goto out; ++ } ++ + modes = il->ctx.interface_modes | il->ctx.exclusive_interface_modes; + if (!(modes & BIT(vif->type))) { + err = -EOPNOTSUPP; +@@ -4605,8 +4616,11 @@ il_mac_add_interface(struct ieee80211_hw + + err = il_setup_interface(il, &il->ctx); + if (err) { +- il->ctx.vif = NULL; +- il->iw_mode = NL80211_IFTYPE_STATION; ++ IL_WARN("Fail to set mode %d\n", vif->type); ++ if (!reset) { ++ il->ctx.vif = NULL; ++ il->iw_mode = NL80211_IFTYPE_STATION; ++ } + } + + out: diff --git a/iwlwifi-do-not-nulify-ctx-vif-on-reset.patch b/iwlwifi-do-not-nulify-ctx-vif-on-reset.patch new file mode 100644 index 000000000..e03f2d304 --- /dev/null +++ b/iwlwifi-do-not-nulify-ctx-vif-on-reset.patch @@ -0,0 +1,66 @@ +ctx->vif is dereferenced in different part of iwlwifi code, so do not +nullify it. + +This should address at least one of the possible reasons of WARNING at +iwlagn_mac_remove_interface, and perhaps some random crashes when +firmware reset is performed. + +Cc: stable@vger.kernel.org +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/iwlwifi/iwl-agn.c | 3 --- + drivers/net/wireless/iwlwifi/iwl-mac80211.c | 10 +++++++++- + 2 files changed, 9 insertions(+), 4 deletions(-) + +--- linux-3.3.noarch.orig/drivers/net/wireless/iwlwifi/iwl-agn.c ++++ linux-3.3.noarch/drivers/net/wireless/iwlwifi/iwl-agn.c +@@ -1403,7 +1403,6 @@ static void iwl_bg_run_time_calib_work(s + + void iwlagn_prepare_restart(struct iwl_priv *priv) + { +- struct iwl_rxon_context *ctx; + bool bt_full_concurrent; + u8 bt_ci_compliance; + u8 bt_load; +@@ -1412,8 +1411,6 @@ void iwlagn_prepare_restart(struct iwl_p + + lockdep_assert_held(&priv->shrd->mutex); + +- for_each_context(priv, ctx) +- ctx->vif = NULL; + priv->is_open = 0; + + /* +--- linux-3.3.noarch.orig/drivers/net/wireless/iwlwifi/iwl-mac80211.c ++++ linux-3.3.noarch/drivers/net/wireless/iwlwifi/iwl-mac80211.c +@@ -1226,6 +1226,7 @@ static int iwlagn_mac_add_interface(stru + struct iwl_rxon_context *tmp, *ctx = NULL; + int err; + enum nl80211_iftype viftype = ieee80211_vif_type_p2p(vif); ++ bool reset = false; + + IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", + viftype, vif->addr); +@@ -1247,6 +1248,13 @@ static int iwlagn_mac_add_interface(stru + tmp->interface_modes | tmp->exclusive_interface_modes; + + if (tmp->vif) { ++ /* On reset we need to add the same interface again */ ++ if (tmp->vif == vif) { ++ reset = true; ++ ctx = tmp; ++ break; ++ } ++ + /* check if this busy context is exclusive */ + if (tmp->exclusive_interface_modes & + BIT(tmp->vif->type)) { +@@ -1273,7 +1281,7 @@ static int iwlagn_mac_add_interface(stru + ctx->vif = vif; + + err = iwl_setup_interface(priv, ctx); +- if (!err) ++ if (!err || reset) + goto out; + + ctx->vif = NULL; diff --git a/kernel.spec b/kernel.spec index f1f4c2255..9ea0ec36a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -785,6 +785,10 @@ Patch21351: x86-add-io_apic_ops-to-allow-interception.patch Patch21352: x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch Patch21353: xen-x86-Implement-x86_apic_ops.patch +#rhbz 770476 +Patch21370: iwlegacy-do-not-nulify-il-vif-on-reset.patch +Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch + Patch21500: ASPM-Fix-pcie-devs-with-non-pcie-children.patch Patch22000: weird-root-dentry-name-debug.patch @@ -1459,6 +1463,10 @@ ApplyPatch x86-add-io_apic_ops-to-allow-interception.patch ApplyPatch x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch ApplyPatch xen-x86-Implement-x86_apic_ops.patch +#rhbz 770476 +ApplyPatch iwlegacy-do-not-nulify-il-vif-on-reset.patch +ApplyPatch iwlwifi-do-not-nulify-ctx-vif-on-reset.patch + #rhbz 803809 CVE-2012-1179 ApplyPatch mm-thp-fix-pmd_bad-triggering.patch @@ -2202,6 +2210,10 @@ fi # and build. %changelog +* Thu Mar 29 2012 Josh Boyer +- iwl{wifi,legacy}: Fix warnings on remove interface from Stanislaw Gruszka + (rhbz 770467) + * Wed Mar 28 2012 Josh Boyer - Fix disabled ASPM regression From 381fffb1004041e691ca2dfd082773ea2ec0cda8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 29 Mar 2012 10:58:35 -0400 Subject: [PATCH 325/487] Drop __cpuinitdata on disable_nx for x86_32 (rhbz 808075) --- kernel.spec | 5 +- ...cpuinitdata-for-disable_nx-on-x86_32.patch | 47 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 nx-emu-remove-cpuinitdata-for-disable_nx-on-x86_32.patch diff --git a/kernel.spec b/kernel.spec index 9ea0ec36a..9044a9ba9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 7 +%global baserelease 8 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -659,6 +659,7 @@ Patch09: linux-2.6-upstream-reverts.patch Patch100: taint-vbox.patch Patch160: linux-2.6-32bit-mmap-exec-randomization.patch Patch161: linux-2.6-i386-nx-emulation.patch +Patch162: nx-emu-remove-cpuinitdata-for-disable_nx-on-x86_32.patch Patch383: linux-2.6-defaults-aspm.patch @@ -1303,6 +1304,7 @@ ApplyPatch taint-vbox.patch # ApplyPatch linux-2.6-32bit-mmap-exec-randomization.patch ApplyPatch linux-2.6-i386-nx-emulation.patch +ApplyPatch nx-emu-remove-cpuinitdata-for-disable_nx-on-x86_32.patch # # bugfixes to drivers and filesystems @@ -2211,6 +2213,7 @@ fi %changelog * Thu Mar 29 2012 Josh Boyer +- Drop __cpuinitdata on disable_nx for x86_32 (rhbz 808075) - iwl{wifi,legacy}: Fix warnings on remove interface from Stanislaw Gruszka (rhbz 770467) diff --git a/nx-emu-remove-cpuinitdata-for-disable_nx-on-x86_32.patch b/nx-emu-remove-cpuinitdata-for-disable_nx-on-x86_32.patch new file mode 100644 index 000000000..38c96caed --- /dev/null +++ b/nx-emu-remove-cpuinitdata-for-disable_nx-on-x86_32.patch @@ -0,0 +1,47 @@ +>From e540f21852043a4d8e8cf5e505607909d0ab0f51 Mon Sep 17 00:00:00 2001 +From: Tim Gardner +Date: Thu, 29 Mar 2012 06:21:01 -0600 +Subject: [PATCH] UBUNTU: SAUCE: disable_nx should not be in __cpuinitdata + section for X86_32 + +I noticed a section mismatch warning while building 3.2.0-20.33 for X86_32. + + AR arch/x86/lib/lib.a + LD vmlinux.o + MODPOST vmlinux.o +WARNING: vmlinux.o(.text+0x187833): Section mismatch in reference from the function load_elf_binary() to the variable .cpuinit.data:disable_nx +The function load_elf_binary() references +the variable __cpuinitdata disable_nx. +This is often because load_elf_binary lacks a __cpuinitdata +annotation or the annotation of disable_nx is wrong. + +load_elf_binary() is definitely called after initialization. + +This code was added by 'UBUNTU: ubuntu: nx-emu - i386: NX emulation', so +this is not an upstream problem. + +Reported-by: Tetsuo Handa +Signed-off-by: Tim Gardner +--- + arch/x86/mm/setup_nx.c | 4 ++++ + 1 files changed, 4 insertions(+), 0 deletions(-) + +diff --git a/arch/x86/mm/setup_nx.c b/arch/x86/mm/setup_nx.c +index 90c9eff3..89fd946 100644 +--- a/arch/x86/mm/setup_nx.c ++++ b/arch/x86/mm/setup_nx.c +@@ -6,7 +6,11 @@ + #include + #include + ++#ifdef CONFIG_X86_32 ++int disable_nx; /* referenced by load_elf_binary() */ ++#else + int disable_nx __cpuinitdata; ++#endif + + /* + * noexec = on|off +-- +1.7.9.1 + From e17bbff2005aa3e38fb9e225c4bf74fae722bfcb Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 29 Mar 2012 14:00:04 -0400 Subject: [PATCH 326/487] Add version for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 9044a9ba9..bede763a2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2212,7 +2212,7 @@ fi # and build. %changelog -* Thu Mar 29 2012 Josh Boyer +* Thu Mar 29 2012 Josh Boyer - 3.3.0-8 - Drop __cpuinitdata on disable_nx for x86_32 (rhbz 808075) - iwl{wifi,legacy}: Fix warnings on remove interface from Stanislaw Gruszka (rhbz 770467) From d08bf805ac6c458f3087de5ca04215aeeb4a8b3e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 30 Mar 2012 10:49:57 -0400 Subject: [PATCH 327/487] Add patch to fix incorrect buffer length in __nfs4_get_acl_uncached --- kernel.spec | 8 ++++- ...er-copied-in-__nfs4_get_acl_uncached.patch | 32 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch diff --git a/kernel.spec b/kernel.spec index bede763a2..df180f090 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 8 +%global baserelease 9 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -791,6 +791,7 @@ Patch21370: iwlegacy-do-not-nulify-il-vif-on-reset.patch Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch Patch21500: ASPM-Fix-pcie-devs-with-non-pcie-children.patch +Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch Patch22000: weird-root-dentry-name-debug.patch @@ -1474,6 +1475,8 @@ ApplyPatch mm-thp-fix-pmd_bad-triggering.patch ApplyPatch ASPM-Fix-pcie-devs-with-non-pcie-children.patch +ApplyPatch nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch + # END OF PATCH APPLICATIONS %endif @@ -2212,6 +2215,9 @@ fi # and build. %changelog +* Fri Mar 30 2012 Josh Boyer +- Add patch to fix incorrect buffer length in __nfs4_get_acl_uncached + * Thu Mar 29 2012 Josh Boyer - 3.3.0-8 - Drop __cpuinitdata on disable_nx for x86_32 (rhbz 808075) - iwl{wifi,legacy}: Fix warnings on remove interface from Stanislaw Gruszka diff --git a/nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch b/nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch new file mode 100644 index 000000000..981f1f467 --- /dev/null +++ b/nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch @@ -0,0 +1,32 @@ +From 20e0fa98b751facf9a1101edaefbc19c82616a68 Mon Sep 17 00:00:00 2001 +From: Sachin Prabhu +Date: Thu, 22 Mar 2012 16:46:28 +0000 +Subject: [PATCH] Fix length of buffer copied in __nfs4_get_acl_uncached + +_copy_from_pages() used to copy data from the temporary buffer to the +user passed buffer is passed the wrong size parameter when copying +data. res.acl_len contains both the bitmap and acl lenghts while +acl_len contains the acl length after adjusting for the bitmap size. + +Signed-off-by: Sachin Prabhu +Signed-off-by: Trond Myklebust +--- + fs/nfs/nfs4proc.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index e809d23..45df7d4 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -3712,7 +3712,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu + if (acl_len > buflen) + goto out_free; + _copy_from_pages(buf, pages, res.acl_data_offset, +- res.acl_len); ++ acl_len); + } + ret = acl_len; + out_free: +-- +1.7.7.6 + From 7b5b29761d9fa40f14da30cf6d60761cb896ec1d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 30 Mar 2012 11:08:12 -0400 Subject: [PATCH 328/487] CVE-2012-1601: kvm: NULL dereference from irqchip_in_kernel and vcpu->arch.apic inconsistency (rhbz 808207) --- ...cpus-are-consistent-with-in-kernel-i.patch | 106 ++++++++++++++++++ kernel.spec | 8 ++ 2 files changed, 114 insertions(+) create mode 100644 KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch diff --git a/KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch b/KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch new file mode 100644 index 000000000..7e1664f41 --- /dev/null +++ b/KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch @@ -0,0 +1,106 @@ +From 5b40572ed5f0344b9dbee486a17c589ce1abe1a3 Mon Sep 17 00:00:00 2001 +From: Avi Kivity +Date: Mon, 5 Mar 2012 14:23:29 +0200 +Subject: [PATCH] KVM: Ensure all vcpus are consistent with in-kernel irqchip + settings + +If some vcpus are created before KVM_CREATE_IRQCHIP, then +irqchip_in_kernel() and vcpu->arch.apic will be inconsistent, leading +to potential NULL pointer dereferences. + +Fix by: +- ensuring that no vcpus are installed when KVM_CREATE_IRQCHIP is called +- ensuring that a vcpu has an apic if it is installed after KVM_CREATE_IRQCHIP + +This is somewhat long winded because vcpu->arch.apic is created without +kvm->lock held. + +Based on earlier patch by Michael Ellerman. + +Signed-off-by: Michael Ellerman +Signed-off-by: Avi Kivity +--- + arch/ia64/kvm/kvm-ia64.c | 5 +++++ + arch/x86/kvm/x86.c | 8 ++++++++ + include/linux/kvm_host.h | 7 +++++++ + virt/kvm/kvm_main.c | 4 ++++ + 4 files changed, 24 insertions(+), 0 deletions(-) + +diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c +index d8ddbba..f5104b7 100644 +--- a/arch/ia64/kvm/kvm-ia64.c ++++ b/arch/ia64/kvm/kvm-ia64.c +@@ -1172,6 +1172,11 @@ out: + + #define PALE_RESET_ENTRY 0x80000000ffffffb0UL + ++bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) ++{ ++ return irqchip_in_kernel(vcpu->kcm) == (vcpu->arch.apic != NULL); ++} ++ + int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) + { + struct kvm_vcpu *v; +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 3ee008f..be9594a 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -3199,6 +3199,9 @@ long kvm_arch_vm_ioctl(struct file *filp, + r = -EEXIST; + if (kvm->arch.vpic) + goto create_irqchip_unlock; ++ r = -EINVAL; ++ if (atomic_read(&kvm->online_vcpus)) ++ goto create_irqchip_unlock; + r = -ENOMEM; + vpic = kvm_create_pic(kvm); + if (vpic) { +@@ -6107,6 +6110,11 @@ void kvm_arch_check_processor_compat(void *rtn) + kvm_x86_ops->check_processor_compatibility(rtn); + } + ++bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) ++{ ++ return irqchip_in_kernel(vcpu->kvm) == (vcpu->arch.apic != NULL); ++} ++ + int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) + { + struct page *page; +diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h +index 355e445..759fa26 100644 +--- a/include/linux/kvm_host.h ++++ b/include/linux/kvm_host.h +@@ -805,6 +805,13 @@ static inline bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu) + { + return vcpu->kvm->bsp_vcpu_id == vcpu->vcpu_id; + } ++ ++bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu); ++ ++#else ++ ++static bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) { return true; } ++ + #endif + + #ifdef __KVM_HAVE_DEVICE_ASSIGNMENT +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index e4431ad..94e148e 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -1651,6 +1651,10 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id) + goto vcpu_destroy; + + mutex_lock(&kvm->lock); ++ if (!kvm_vcpu_compatible(vcpu)) { ++ r = -EINVAL; ++ goto unlock_vcpu_destroy; ++ } + if (atomic_read(&kvm->online_vcpus) == KVM_MAX_VCPUS) { + r = -EINVAL; + goto unlock_vcpu_destroy; +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index df180f090..cde36fa6e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -793,6 +793,9 @@ Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch Patch21500: ASPM-Fix-pcie-devs-with-non-pcie-children.patch Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch +#rhbz 808207 CVE-2012-1601 +Patch21520: KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch + Patch22000: weird-root-dentry-name-debug.patch %endif @@ -1477,6 +1480,9 @@ ApplyPatch ASPM-Fix-pcie-devs-with-non-pcie-children.patch ApplyPatch nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch +#rhbz 808207 CVE-2012-1601 +ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch + # END OF PATCH APPLICATIONS %endif @@ -2216,6 +2222,8 @@ fi %changelog * Fri Mar 30 2012 Josh Boyer +- CVE-2012-1601: kvm: NULL dereference from irqchip_in_kernel and + vcpu->arch.apic inconsistency (rhbz 808207) - Add patch to fix incorrect buffer length in __nfs4_get_acl_uncached * Thu Mar 29 2012 Josh Boyer - 3.3.0-8 From 1c2671dad3f2e14e961e6969edb5e3111ae9e440 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 30 Mar 2012 12:54:23 -0400 Subject: [PATCH 329/487] Fix i915 fbdev cursor blink around suspend/hibernate from Dave Airlied --- ...-fbdev-device-around-suspend-hiberna.patch | 92 +++++++++++++++++++ kernel.spec | 4 + 2 files changed, 96 insertions(+) create mode 100644 drm-i915-suspend-fbdev-device-around-suspend-hiberna.patch diff --git a/drm-i915-suspend-fbdev-device-around-suspend-hiberna.patch b/drm-i915-suspend-fbdev-device-around-suspend-hiberna.patch new file mode 100644 index 000000000..826e4c5b4 --- /dev/null +++ b/drm-i915-suspend-fbdev-device-around-suspend-hiberna.patch @@ -0,0 +1,92 @@ +From 3fa016a0b5c5237e9c387fc3249592b2cb5391c6 Mon Sep 17 00:00:00 2001 +From: Dave Airlie +Date: Wed, 28 Mar 2012 10:48:49 +0100 +Subject: [PATCH] drm/i915: suspend fbdev device around suspend/hibernate + +Looking at hibernate overwriting I though it looked like a cursor, +so I tracked down this missing piece to stop the cursor blink +timer. I've no idea if this is sufficient to fix the hibernate +problems people are seeing, but please test it. + +Both radeon and nouveau have done this for a long time. + +I've run this personally all night hib/resume cycles with no fails. + +Reviewed-by: Keith Packard +Reported-by: Petr Tesarik +Reported-by: Stanislaw Gruszka +Reported-by: Lots of misc segfaults after hibernate across the world. +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=37142 +Tested-by: Dave Airlie +Tested-by: Bojan Smojver +Tested-by: Andreas Hartmann +Cc: stable@vger.kernel.org +Signed-off-by: Dave Airlie +--- + drivers/gpu/drm/i915/i915_drv.c | 7 +++++++ + drivers/gpu/drm/i915/intel_drv.h | 2 +- + drivers/gpu/drm/i915/intel_fb.c | 10 ++++++++++ + 3 files changed, 18 insertions(+), 1 deletions(-) + +diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c +index 0694e17..1a7559b 100644 +--- a/drivers/gpu/drm/i915/i915_drv.c ++++ b/drivers/gpu/drm/i915/i915_drv.c +@@ -467,6 +467,10 @@ static int i915_drm_freeze(struct drm_device *dev) + /* Modeset on resume, not lid events */ + dev_priv->modeset_on_lid = 0; + ++ console_lock(); ++ intel_fbdev_set_suspend(dev, 1); ++ console_unlock(); ++ + return 0; + } + +@@ -539,6 +543,9 @@ static int i915_drm_thaw(struct drm_device *dev) + + dev_priv->modeset_on_lid = 0; + ++ console_lock(); ++ intel_fbdev_set_suspend(dev, 0); ++ console_unlock(); + return error; + } + +diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h +index 9cec6c3..5a14149 100644 +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -382,7 +382,7 @@ extern int intel_framebuffer_init(struct drm_device *dev, + struct drm_i915_gem_object *obj); + extern int intel_fbdev_init(struct drm_device *dev); + extern void intel_fbdev_fini(struct drm_device *dev); +- ++extern void intel_fbdev_set_suspend(struct drm_device *dev, int state); + extern void intel_prepare_page_flip(struct drm_device *dev, int plane); + extern void intel_finish_page_flip(struct drm_device *dev, int pipe); + extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane); +diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c +index 2d87669..19ecd78 100644 +--- a/drivers/gpu/drm/i915/intel_fb.c ++++ b/drivers/gpu/drm/i915/intel_fb.c +@@ -254,6 +254,16 @@ void intel_fbdev_fini(struct drm_device *dev) + kfree(dev_priv->fbdev); + dev_priv->fbdev = NULL; + } ++ ++void intel_fbdev_set_suspend(struct drm_device *dev, int state) ++{ ++ drm_i915_private_t *dev_priv = dev->dev_private; ++ if (!dev_priv->fbdev) ++ return; ++ ++ fb_set_suspend(dev_priv->fbdev->helper.fbdev, state); ++} ++ + MODULE_LICENSE("GPL and additional rights"); + + void intel_fb_output_poll_changed(struct drm_device *dev) +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index cde36fa6e..b18610a52 100644 --- a/kernel.spec +++ b/kernel.spec @@ -699,6 +699,7 @@ Patch1825: drm-i915-dp-stfu.patch # hush the i915 fbc noise Patch1826: drm-i915-fbc-stfu.patch +Patch1827: drm-i915-suspend-fbdev-device-around-suspend-hiberna.patch Patch1900: linux-2.6-intel-iommu-igfx.patch @@ -1400,6 +1401,8 @@ ApplyPatch drm-i915-fbc-stfu.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch +ApplyPatch drm-i915-suspend-fbdev-device-around-suspend-hiberna.patch + # silence the ACPI blacklist code ApplyPatch linux-2.6-silence-acpi-blacklist.patch ApplyPatch quite-apm.patch @@ -2222,6 +2225,7 @@ fi %changelog * Fri Mar 30 2012 Josh Boyer +- Fix i915 fbdev cursor blink around suspend/hibernate from Dave Airlied - CVE-2012-1601: kvm: NULL dereference from irqchip_in_kernel and vcpu->arch.apic inconsistency (rhbz 808207) - Add patch to fix incorrect buffer length in __nfs4_get_acl_uncached From d15571e206b48a35979c1e924b8e0d991c98c76c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 30 Mar 2012 14:56:55 -0400 Subject: [PATCH 330/487] Silence the timekeeping "Adjusting tsc more then 11%" spew. (rhbz 798600) --- kernel.spec | 6 ++++++ silence-timekeeping-spew.patch | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 silence-timekeeping-spew.patch diff --git a/kernel.spec b/kernel.spec index b18610a52..cc9f89199 100644 --- a/kernel.spec +++ b/kernel.spec @@ -678,6 +678,7 @@ Patch470: die-floppy-die.patch Patch471: floppy-drop-disable_hlt-warning.patch Patch510: linux-2.6-silence-noise.patch +Patch511: silence-timekeeping-spew.patch Patch520: quite-apm.patch Patch530: linux-2.6-silence-fbcon-logo.patch @@ -1374,6 +1375,8 @@ ApplyPatch linux-2.6-serial-460800.patch # Silence some useless messages that still get printed with 'quiet' ApplyPatch linux-2.6-silence-noise.patch +ApplyPatch silence-timekeeping-spew.patch + # Make fbcon not show the penguins with 'quiet' ApplyPatch linux-2.6-silence-fbcon-logo.patch @@ -2224,6 +2227,9 @@ fi # and build. %changelog +* Fri Mar 30 2012 Dave Jones +- Silence the timekeeping "Adjusting tsc more then 11%" spew. (rhbz 798600) + * Fri Mar 30 2012 Josh Boyer - Fix i915 fbdev cursor blink around suspend/hibernate from Dave Airlied - CVE-2012-1601: kvm: NULL dereference from irqchip_in_kernel and diff --git a/silence-timekeeping-spew.patch b/silence-timekeeping-spew.patch new file mode 100644 index 000000000..19416d433 --- /dev/null +++ b/silence-timekeeping-spew.patch @@ -0,0 +1,16 @@ +--- linux-3.3.0-4.fc17.noarch/kernel/time/timekeeping.c~ 2012-03-30 14:18:15.591162207 -0400 ++++ linux-3.3.0-4.fc17.noarch/kernel/time/timekeeping.c 2012-03-30 14:18:38.959121171 -0400 +@@ -854,13 +854,6 @@ static void timekeeping_adjust(s64 offse + } else /* No adjustment needed */ + return; + +- WARN_ONCE(timekeeper.clock->maxadj && +- (timekeeper.mult + adj > timekeeper.clock->mult + +- timekeeper.clock->maxadj), +- "Adjusting %s more then 11%% (%ld vs %ld)\n", +- timekeeper.clock->name, (long)timekeeper.mult + adj, +- (long)timekeeper.clock->mult + +- timekeeper.clock->maxadj); + /* + * So the following can be confusing. + * From b6cb947f14df1197d538ef868e4781c6a33e1729 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 2 Apr 2012 14:24:22 -0400 Subject: [PATCH 331/487] Linux 3.3.1 --- ...Fix-pcie-devs-with-non-pcie-children.patch | 48 -- ...-fbdev-device-around-suspend-hiberna.patch | 92 ---- ...nd-BH_Unwritten-in-journal_unmap_buf.patch | 91 ---- kernel.spec | 32 +- mm-thp-fix-pmd_bad-triggering.patch | 447 ------------------ sources | 1 + ...ter-checks-for-bogus-io-apic-entries.patch | 93 ---- 7 files changed, 8 insertions(+), 796 deletions(-) delete mode 100644 ASPM-Fix-pcie-devs-with-non-pcie-children.patch delete mode 100644 drm-i915-suspend-fbdev-device-around-suspend-hiberna.patch delete mode 100644 jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch delete mode 100644 mm-thp-fix-pmd_bad-triggering.patch delete mode 100644 x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch diff --git a/ASPM-Fix-pcie-devs-with-non-pcie-children.patch b/ASPM-Fix-pcie-devs-with-non-pcie-children.patch deleted file mode 100644 index 2f52fa870..000000000 --- a/ASPM-Fix-pcie-devs-with-non-pcie-children.patch +++ /dev/null @@ -1,48 +0,0 @@ -Commit 4949be16822e92a18ea0cc1616319926628092ee changed the behaviour of -pcie_aspm_sanity_check() to always return 0 if aspm is disabled, in order -to avoid cases where we changed ASPM state on pre-PCIe 1.1 devices. This -skipped the secondary function of pcie_aspm_sanity_check which was to avoid -us enabling ASPM on devices that had non-PCIe children, causing us to hit -a BUG_ON later on. Move the aspm_disabled check so we continue to honour -that scenario. - -Signed-off-by: Matthew Garrett -Cc: stable@vger.kernel.org ---- - drivers/pci/pcie/aspm.c | 13 ++++++++++--- - 1 files changed, 10 insertions(+), 3 deletions(-) -diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c -index 86111d9..41e367b 100644 ---- a/drivers/pci/pcie/aspm.c -+++ b/drivers/pci/pcie/aspm.c -@@ -521,9 +521,6 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) - int pos; - u32 reg32; - -- if (aspm_disabled) -- return 0; -- - /* - * Some functions in a slot might not all be PCIe functions, - * very strange. Disable ASPM for the whole slot -@@ -532,6 +529,16 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) - pos = pci_pcie_cap(child); - if (!pos) - return -EINVAL; -+ -+ /* -+ * If ASPM is disabled then we're not going to change -+ * the BIOS state. It's safe to continue even if it's a -+ * pre-1.1 device -+ */ -+ -+ if (aspm_disabled) -+ continue; -+ - /* - * Disable ASPM for pre-1.1 PCIe device, we follow MS to use - * RBER bit to determine if a function is 1.1 version device --- -1.7.7.6 - - diff --git a/drm-i915-suspend-fbdev-device-around-suspend-hiberna.patch b/drm-i915-suspend-fbdev-device-around-suspend-hiberna.patch deleted file mode 100644 index 826e4c5b4..000000000 --- a/drm-i915-suspend-fbdev-device-around-suspend-hiberna.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 3fa016a0b5c5237e9c387fc3249592b2cb5391c6 Mon Sep 17 00:00:00 2001 -From: Dave Airlie -Date: Wed, 28 Mar 2012 10:48:49 +0100 -Subject: [PATCH] drm/i915: suspend fbdev device around suspend/hibernate - -Looking at hibernate overwriting I though it looked like a cursor, -so I tracked down this missing piece to stop the cursor blink -timer. I've no idea if this is sufficient to fix the hibernate -problems people are seeing, but please test it. - -Both radeon and nouveau have done this for a long time. - -I've run this personally all night hib/resume cycles with no fails. - -Reviewed-by: Keith Packard -Reported-by: Petr Tesarik -Reported-by: Stanislaw Gruszka -Reported-by: Lots of misc segfaults after hibernate across the world. -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=37142 -Tested-by: Dave Airlie -Tested-by: Bojan Smojver -Tested-by: Andreas Hartmann -Cc: stable@vger.kernel.org -Signed-off-by: Dave Airlie ---- - drivers/gpu/drm/i915/i915_drv.c | 7 +++++++ - drivers/gpu/drm/i915/intel_drv.h | 2 +- - drivers/gpu/drm/i915/intel_fb.c | 10 ++++++++++ - 3 files changed, 18 insertions(+), 1 deletions(-) - -diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c -index 0694e17..1a7559b 100644 ---- a/drivers/gpu/drm/i915/i915_drv.c -+++ b/drivers/gpu/drm/i915/i915_drv.c -@@ -467,6 +467,10 @@ static int i915_drm_freeze(struct drm_device *dev) - /* Modeset on resume, not lid events */ - dev_priv->modeset_on_lid = 0; - -+ console_lock(); -+ intel_fbdev_set_suspend(dev, 1); -+ console_unlock(); -+ - return 0; - } - -@@ -539,6 +543,9 @@ static int i915_drm_thaw(struct drm_device *dev) - - dev_priv->modeset_on_lid = 0; - -+ console_lock(); -+ intel_fbdev_set_suspend(dev, 0); -+ console_unlock(); - return error; - } - -diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h -index 9cec6c3..5a14149 100644 ---- a/drivers/gpu/drm/i915/intel_drv.h -+++ b/drivers/gpu/drm/i915/intel_drv.h -@@ -382,7 +382,7 @@ extern int intel_framebuffer_init(struct drm_device *dev, - struct drm_i915_gem_object *obj); - extern int intel_fbdev_init(struct drm_device *dev); - extern void intel_fbdev_fini(struct drm_device *dev); -- -+extern void intel_fbdev_set_suspend(struct drm_device *dev, int state); - extern void intel_prepare_page_flip(struct drm_device *dev, int plane); - extern void intel_finish_page_flip(struct drm_device *dev, int pipe); - extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane); -diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c -index 2d87669..19ecd78 100644 ---- a/drivers/gpu/drm/i915/intel_fb.c -+++ b/drivers/gpu/drm/i915/intel_fb.c -@@ -254,6 +254,16 @@ void intel_fbdev_fini(struct drm_device *dev) - kfree(dev_priv->fbdev); - dev_priv->fbdev = NULL; - } -+ -+void intel_fbdev_set_suspend(struct drm_device *dev, int state) -+{ -+ drm_i915_private_t *dev_priv = dev->dev_private; -+ if (!dev_priv->fbdev) -+ return; -+ -+ fb_set_suspend(dev_priv->fbdev->helper.fbdev, state); -+} -+ - MODULE_LICENSE("GPL and additional rights"); - - void intel_fb_output_poll_changed(struct drm_device *dev) --- -1.7.7.6 - diff --git a/jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch b/jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch deleted file mode 100644 index 5ea8ccc10..000000000 --- a/jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch +++ /dev/null @@ -1,91 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Eric Sandeen -Newsgroups: gmane.comp.file-systems.ext4 -Subject: [PATCH] jbd2: clear BH_Delay & BH_Unwritten in journal_unmap_buffer -Date: Tue, 07 Feb 2012 16:07:20 -0600 -Lines: 42 -Approved: news@gmane.org -Message-ID: <4F31A098.4050601@redhat.com> -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: 7bit -X-Trace: dough.gmane.org 1328656072 12026 80.91.229.3 (7 Feb 2012 23:07:52 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Tue, 7 Feb 2012 23:07:52 +0000 (UTC) -To: ext4 development -Original-X-From: linux-ext4-owner@vger.kernel.org Wed Feb 08 00:07:52 2012 -Return-path: -Envelope-to: gcfe-linux-ext4@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1Ruu8d-0000lK-5P - for gcfe-linux-ext4@plane.gmane.org; Wed, 08 Feb 2012 00:07:51 +0100 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1756187Ab2BGXHt (ORCPT ); - Tue, 7 Feb 2012 18:07:49 -0500 -Original-Received: from mx1.redhat.com ([209.132.183.28]:19432 "EHLO mx1.redhat.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1753992Ab2BGXHs (ORCPT ); - Tue, 7 Feb 2012 18:07:48 -0500 -Original-Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q17N7dj0027622 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) - for ; Tue, 7 Feb 2012 18:07:48 -0500 -Original-Received: from liberator.sandeen.net (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q17M7Kgt001990 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) - for ; Tue, 7 Feb 2012 17:07:21 -0500 -User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:10.0) Gecko/20120129 Thunderbird/10.0 -X-Enigmail-Version: 1.3.5 -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 -Original-Sender: linux-ext4-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-ext4@vger.kernel.org -Xref: news.gmane.org gmane.comp.file-systems.ext4:30623 -Archived-At: - -journal_unmap_buffer()'s zap_buffer: code clears a lot of buffer head -state ala discard_buffer(), but does not touch _Delay or _Unwritten -as discard_buffer() does. - -This can be problematic in some areas of the ext4 code which assume -that if they have found a buffer marked unwritten or delay, then it's -a live one. Perhaps those spots should check whether it is mapped -as well, but if jbd2 is going to tear down a buffer, let's really -tear it down completely. - -Without this I get some fsx failures on sub-page-block filesystems -up until v3.2, at which point 4e96b2dbbf1d7e81f22047a50f862555a6cb87cb -and 189e868fa8fdca702eb9db9d8afc46b5cb9144c9 make the failures go -away, because buried within that large change is some more flag -clearing. I still think it's worth doing in jbd2, since -->invalidatepage leads here directly, and it's the right place -to clear away these flags. - -Signed-off-by: Eric Sandeen -Cc: stable@vger.kernel.org ---- - -diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c -index 35ae096..52653306 100644 ---- a/fs/jbd2/transaction.c -+++ b/fs/jbd2/transaction.c -@@ -1949,6 +1949,8 @@ zap_buffer_unlocked: - clear_buffer_mapped(bh); - clear_buffer_req(bh); - clear_buffer_new(bh); -+ clear_buffer_delay(bh); -+ clear_buffer_unwritten(bh); - bh->b_bdev = NULL; - return may_free; - } - - --- -To unsubscribe from this list: send the line "unsubscribe linux-ext4" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - diff --git a/kernel.spec b/kernel.spec index cc9f89199..a169ca0d3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 9 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 0 +%define stable_update 1 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -700,7 +700,6 @@ Patch1825: drm-i915-dp-stfu.patch # hush the i915 fbc noise Patch1826: drm-i915-fbc-stfu.patch -Patch1827: drm-i915-suspend-fbdev-device-around-suspend-hiberna.patch Patch1900: linux-2.6-intel-iommu-igfx.patch @@ -755,9 +754,6 @@ Patch21226: pci-crs-blacklist.patch #rhbz 772772 Patch21232: rt2x00_fix_MCU_request_failures.patch -#rhbz 788260 -Patch21233: jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch - #rhbz 754518 #Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -770,9 +766,6 @@ Patch21240: ACPICA-Fix-regression-in-FADT-revision-checks.patch #rhbz 728478 Patch21242: sony-laptop-Enable-keyboard-backlight-by-default.patch -#rhbz 803809 CVE-2012-1179 -Patch21244: mm-thp-fix-pmd_bad-triggering.patch - Patch21300: unhandled-irqs-switch-to-polling.patch #rhbz 804007 @@ -781,8 +774,6 @@ Patch21305: mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch #rhbz 804957 CVE-2012-1568 Patch21306: shlib_base_randomize.patch -Patch21350: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch - #rhbz 804347 Patch21351: x86-add-io_apic_ops-to-allow-interception.patch Patch21352: x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch @@ -792,7 +783,6 @@ Patch21353: xen-x86-Implement-x86_apic_ops.patch Patch21370: iwlegacy-do-not-nulify-il-vif-on-reset.patch Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch -Patch21500: ASPM-Fix-pcie-devs-with-non-pcie-children.patch Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch #rhbz 808207 CVE-2012-1601 @@ -1404,8 +1394,6 @@ ApplyPatch drm-i915-fbc-stfu.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch -ApplyPatch drm-i915-suspend-fbdev-device-around-suspend-hiberna.patch - # silence the ACPI blacklist code ApplyPatch linux-2.6-silence-acpi-blacklist.patch ApplyPatch quite-apm.patch @@ -1425,7 +1413,8 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch -ApplyPatch hibernate-freeze-filesystems.patch +# FIXME +#ApplyPatch hibernate-freeze-filesystems.patch ApplyPatch lis3-improve-handling-of-null-rate.patch @@ -1443,9 +1432,6 @@ ApplyPatch ext4-Support-check-none-nocheck-mount-options.patch #rhbz 772772 ApplyPatch rt2x00_fix_MCU_request_failures.patch -#rhbz 788269 -ApplyPatch jbd2-clear-BH_Delay-and-BH_Unwritten-in-journal_unmap_buf.patch - #rhbz 754518 #ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -1468,8 +1454,6 @@ ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch -ApplyPatch x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch - #rhbz 804347 ApplyPatch x86-add-io_apic_ops-to-allow-interception.patch ApplyPatch x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch @@ -1479,11 +1463,6 @@ ApplyPatch xen-x86-Implement-x86_apic_ops.patch ApplyPatch iwlegacy-do-not-nulify-il-vif-on-reset.patch ApplyPatch iwlwifi-do-not-nulify-ctx-vif-on-reset.patch -#rhbz 803809 CVE-2012-1179 -ApplyPatch mm-thp-fix-pmd_bad-triggering.patch - -ApplyPatch ASPM-Fix-pcie-devs-with-non-pcie-children.patch - ApplyPatch nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch #rhbz 808207 CVE-2012-1601 @@ -2227,6 +2206,9 @@ fi # and build. %changelog +* Mon Apr 02 2012 Dave Jones 3.3.1-1 +- Linux 3.3.1 + * Fri Mar 30 2012 Dave Jones - Silence the timekeeping "Adjusting tsc more then 11%" spew. (rhbz 798600) diff --git a/mm-thp-fix-pmd_bad-triggering.patch b/mm-thp-fix-pmd_bad-triggering.patch deleted file mode 100644 index 8e1a77cd7..000000000 --- a/mm-thp-fix-pmd_bad-triggering.patch +++ /dev/null @@ -1,447 +0,0 @@ -In some cases it may happen that pmd_none_or_clear_bad() is called -with the mmap_sem hold in read mode. In those cases the huge page -faults can allocate hugepmds under pmd_none_or_clear_bad() and that -can trigger a false positive from pmd_bad() that will not like to see -a pmd materializing as trans huge. - -It's not khugepaged the problem, khugepaged holds the mmap_sem in -write mode (and all those sites must hold the mmap_sem in read mode to -prevent pagetables to go away from under them, during code review it -seems vm86 mode on 32bit kernels requires that too unless it's -restricted to 1 thread per process or UP builds). The race is only -with the huge pagefaults that can convert a pmd_none() into a -pmd_trans_huge(). - -Effectively all these pmd_none_or_clear_bad() sites running with -mmap_sem in read mode are somewhat speculative with the page faults, -and the result is always undefined when they run simultaneously. This -is probably why it wasn't common to run into this. For example if the -madvise(MADV_DONTNEED) runs zap_page_range() shortly before the page -fault, the hugepage will not be zapped, if the page fault runs first -it will be zapped. - -Altering pmd_bad() not to error out if it finds hugepmds won't be -enough to fix this, because zap_pmd_range would then proceed to call -zap_pte_range (which would be incorrect if the pmd become a -pmd_trans_huge()). - -The simplest way to fix this is to read the pmd in the local stack -(regardless of what we read, no need of actual CPU barriers, only -compiler barrier needed), and be sure it is not changing under the -code that computes its value. Even if the real pmd is changing under -the value we hold on the stack, we don't care. If we actually end up -in zap_pte_range it means the pmd was not none already and it was not -huge, and it can't become huge from under us (khugepaged locking -explained above). - -All we need is to enforce that there is no way anymore that in a code -path like below, pmd_trans_huge can be false, but -pmd_none_or_clear_bad can run into a hugepmd. The overhead of a -barrier() is just a compiler tweak and should not be measurable (I -only added it for THP builds). I don't exclude different compiler -versions may have prevented the race too by caching the value of *pmd -on the stack (that hasn't been verified, but it wouldn't be impossible -considering pmd_none_or_clear_bad, pmd_bad, pmd_trans_huge, pmd_none -are all inlines and there's no external function called in between -pmd_trans_huge and pmd_none_or_clear_bad). - - if (pmd_trans_huge(*pmd)) { - if (next-addr != HPAGE_PMD_SIZE) { - VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem)); - split_huge_page_pmd(vma->vm_mm, pmd); - } else if (zap_huge_pmd(tlb, vma, pmd, addr)) - continue; - /* fall through */ - } - if (pmd_none_or_clear_bad(pmd)) - -Because this race condition could be exercised without special -privileges this was reported in CVE-2012-1179. - -The race was identified and fully explained by Ulrich who debugged it. -I'm quoting his accurate explanation below, for reference. - -====== start quote ======= - mapcount 0 page_mapcount 1 - kernel BUG at mm/huge_memory.c:1384! - -At some point prior to the panic, a "bad pmd ..." message similar to the -following is logged on the console: - - mm/memory.c:145: bad pmd ffff8800376e1f98(80000000314000e7). - -The "bad pmd ..." message is logged by pmd_clear_bad() before it clears -the page's PMD table entry. - - 143 void pmd_clear_bad(pmd_t *pmd) - 144 { --> 145 pmd_ERROR(*pmd); - 146 pmd_clear(pmd); - 147 } - -After the PMD table entry has been cleared, there is an inconsistency -between the actual number of PMD table entries that are mapping the page -and the page's map count (_mapcount field in struct page). When the page -is subsequently reclaimed, __split_huge_page() detects this inconsistency. - - 1381 if (mapcount != page_mapcount(page)) - 1382 printk(KERN_ERR "mapcount %d page_mapcount %d\n", - 1383 mapcount, page_mapcount(page)); --> 1384 BUG_ON(mapcount != page_mapcount(page)); - -The root cause of the problem is a race of two threads in a multithreaded -process. Thread B incurs a page fault on a virtual address that has never -been accessed (PMD entry is zero) while Thread A is executing an madvise() -system call on a virtual address within the same 2 MB (huge page) range. - - virtual address space - .---------------------. - | | - | | - .-|---------------------| - | | | - | | |<-- B(fault) - | | | - 2 MB | |/////////////////////|-. - huge < |/////////////////////| > A(range) - page | |/////////////////////|-' - | | | - | | | - '-|---------------------| - | | - | | - '---------------------' - -- Thread A is executing an madvise(..., MADV_DONTNEED) system call - on the virtual address range "A(range)" shown in the picture. - -sys_madvise - // Acquire the semaphore in shared mode. - down_read(¤t->mm->mmap_sem) - ... - madvise_vma - switch (behavior) - case MADV_DONTNEED: - madvise_dontneed - zap_page_range - unmap_vmas - unmap_page_range - zap_pud_range - zap_pmd_range - // - // Assume that this huge page has never been accessed. - // I.e. content of the PMD entry is zero (not mapped). - // - if (pmd_trans_huge(*pmd)) { - // We don't get here due to the above assumption. - } - // - // Assume that Thread B incurred a page fault and - .---------> // sneaks in here as shown below. - | // - | if (pmd_none_or_clear_bad(pmd)) - | { - | if (unlikely(pmd_bad(*pmd))) - | pmd_clear_bad - | { - | pmd_ERROR - | // Log "bad pmd ..." message here. - | pmd_clear - | // Clear the page's PMD entry. - | // Thread B incremented the map count - | // in page_add_new_anon_rmap(), but - | // now the page is no longer mapped - | // by a PMD entry (-> inconsistency). - | } - | } - | - v -- Thread B is handling a page fault on virtual address "B(fault)" shown - in the picture. - -... -do_page_fault - __do_page_fault - // Acquire the semaphore in shared mode. - down_read_trylock(&mm->mmap_sem) - ... - handle_mm_fault - if (pmd_none(*pmd) && transparent_hugepage_enabled(vma)) - // We get here due to the above assumption (PMD entry is zero). - do_huge_pmd_anonymous_page - alloc_hugepage_vma - // Allocate a new transparent huge page here. - ... - __do_huge_pmd_anonymous_page - ... - spin_lock(&mm->page_table_lock) - ... - page_add_new_anon_rmap - // Here we increment the page's map count (starts at -1). - atomic_set(&page->_mapcount, 0) - set_pmd_at - // Here we set the page's PMD entry which will be cleared - // when Thread A calls pmd_clear_bad(). - ... - spin_unlock(&mm->page_table_lock) - -The mmap_sem does not prevent the race because both threads are acquiring -it in shared mode (down_read). Thread B holds the page_table_lock while -the page's map count and PMD table entry are updated. However, Thread A -does not synchronize on that lock. -====== end quote ======= - -Reported-by: Ulrich Obergfell -Signed-off-by: Andrea Arcangeli ---- - arch/x86/kernel/vm86_32.c | 2 + - fs/proc/task_mmu.c | 9 ++++++ - include/asm-generic/pgtable.h | 57 +++++++++++++++++++++++++++++++++++++++++ - mm/memcontrol.c | 4 +++ - mm/memory.c | 14 ++++++++-- - mm/mempolicy.c | 2 +- - mm/mincore.c | 2 +- - mm/pagewalk.c | 2 +- - mm/swapfile.c | 4 +-- - 9 files changed, 87 insertions(+), 9 deletions(-) - -diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c -index b466cab..328cb37 100644 ---- a/arch/x86/kernel/vm86_32.c -+++ b/arch/x86/kernel/vm86_32.c -@@ -172,6 +172,7 @@ static void mark_screen_rdonly(struct mm_struct *mm) - spinlock_t *ptl; - int i; - -+ down_write(&mm->mmap_sem); - pgd = pgd_offset(mm, 0xA0000); - if (pgd_none_or_clear_bad(pgd)) - goto out; -@@ -190,6 +191,7 @@ static void mark_screen_rdonly(struct mm_struct *mm) - } - pte_unmap_unlock(pte, ptl); - out: -+ up_write(&mm->mmap_sem); - flush_tlb(); - } - -diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c -index 7dcd2a2..3efa725 100644 ---- a/fs/proc/task_mmu.c -+++ b/fs/proc/task_mmu.c -@@ -409,6 +409,9 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, - } else { - spin_unlock(&walk->mm->page_table_lock); - } -+ -+ if (pmd_trans_unstable(pmd)) -+ return 0; - /* - * The mmap_sem held all the way back in m_start() is what - * keeps khugepaged out of here and from collapsing things -@@ -507,6 +510,8 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr, - struct page *page; - - split_huge_page_pmd(walk->mm, pmd); -+ if (pmd_trans_unstable(pmd)) -+ return 0; - - pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); - for (; addr != end; pte++, addr += PAGE_SIZE) { -@@ -670,6 +675,8 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, - int err = 0; - - split_huge_page_pmd(walk->mm, pmd); -+ if (pmd_trans_unstable(pmd)) -+ return 0; - - /* find the first VMA at or above 'addr' */ - vma = find_vma(walk->mm, addr); -@@ -961,6 +968,8 @@ static int gather_pte_stats(pmd_t *pmd, unsigned long addr, - spin_unlock(&walk->mm->page_table_lock); - } - -+ if (pmd_trans_unstable(pmd)) -+ return 0; - orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); - do { - struct page *page = can_gather_numa_stats(*pte, md->vma, addr); -diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h -index 76bff2b..10f8291 100644 ---- a/include/asm-generic/pgtable.h -+++ b/include/asm-generic/pgtable.h -@@ -443,6 +443,63 @@ static inline int pmd_write(pmd_t pmd) - #endif /* __HAVE_ARCH_PMD_WRITE */ - #endif - -+/* -+ * This function is meant to be used by sites walking pagetables with -+ * the mmap_sem hold in read mode to protect against MADV_DONTNEED and -+ * transhuge page faults. MADV_DONTNEED can convert a transhuge pmd -+ * into a null pmd and the transhuge page fault can convert a null pmd -+ * into an hugepmd or into a regular pmd (if the hugepage allocation -+ * fails). While holding the mmap_sem in read mode the pmd becomes -+ * stable and stops changing under us only if it's not null and not a -+ * transhuge pmd. When those races occurs and this function makes a -+ * difference vs the standard pmd_none_or_clear_bad, the result is -+ * undefined so behaving like if the pmd was none is safe (because it -+ * can return none anyway). The compiler level barrier() is critically -+ * important to compute the two checks atomically on the same pmdval. -+ */ -+static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd) -+{ -+ /* depend on compiler for an atomic pmd read */ -+ pmd_t pmdval = *pmd; -+ /* -+ * The barrier will stabilize the pmdval in a register or on -+ * the stack so that it will stop changing under the code. -+ */ -+#ifdef CONFIG_TRANSPARENT_HUGEPAGE -+ barrier(); -+#endif -+ if (pmd_none(pmdval)) -+ return 1; -+ if (unlikely(pmd_bad(pmdval))) { -+ if (!pmd_trans_huge(pmdval)) -+ pmd_clear_bad(pmd); -+ return 1; -+ } -+ return 0; -+} -+ -+/* -+ * This is a noop if Transparent Hugepage Support is not built into -+ * the kernel. Otherwise it is equivalent to -+ * pmd_none_or_trans_huge_or_clear_bad(), and shall only be called in -+ * places that already verified the pmd is not none and they want to -+ * walk ptes while holding the mmap sem in read mode (write mode don't -+ * need this). If THP is not enabled, the pmd can't go away under the -+ * code even if MADV_DONTNEED runs, but if THP is enabled we need to -+ * run a pmd_trans_unstable before walking the ptes after -+ * split_huge_page_pmd returns (because it may have run when the pmd -+ * become null, but then a page fault can map in a THP and not a -+ * regular page). -+ */ -+static inline int pmd_trans_unstable(pmd_t *pmd) -+{ -+#ifdef CONFIG_TRANSPARENT_HUGEPAGE -+ return pmd_none_or_trans_huge_or_clear_bad(pmd); -+#else -+ return 0; -+#endif -+} -+ - #endif /* !__ASSEMBLY__ */ - - #endif /* _ASM_GENERIC_PGTABLE_H */ -diff --git a/mm/memcontrol.c b/mm/memcontrol.c -index d0e57a3..67b0578 100644 ---- a/mm/memcontrol.c -+++ b/mm/memcontrol.c -@@ -5193,6 +5193,8 @@ static int mem_cgroup_count_precharge_pte_range(pmd_t *pmd, - spinlock_t *ptl; - - split_huge_page_pmd(walk->mm, pmd); -+ if (pmd_trans_unstable(pmd)) -+ return 0; - - pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); - for (; addr != end; pte++, addr += PAGE_SIZE) -@@ -5355,6 +5357,8 @@ static int mem_cgroup_move_charge_pte_range(pmd_t *pmd, - spinlock_t *ptl; - - split_huge_page_pmd(walk->mm, pmd); -+ if (pmd_trans_unstable(pmd)) -+ return 0; - retry: - pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); - for (; addr != end; addr += PAGE_SIZE) { -diff --git a/mm/memory.c b/mm/memory.c -index fa2f04e..e3090fc 100644 ---- a/mm/memory.c -+++ b/mm/memory.c -@@ -1251,12 +1251,20 @@ static inline unsigned long zap_pmd_range(struct mmu_gather *tlb, - VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem)); - split_huge_page_pmd(vma->vm_mm, pmd); - } else if (zap_huge_pmd(tlb, vma, pmd, addr)) -- continue; -+ goto next; - /* fall through */ - } -- if (pmd_none_or_clear_bad(pmd)) -- continue; -+ /* -+ * Here there can be other concurrent MADV_DONTNEED or -+ * trans huge page faults running, and if the pmd is -+ * none or trans huge it can change under us. This is -+ * because MADV_DONTNEED holds the mmap_sem in read -+ * mode. -+ */ -+ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) -+ goto next; - next = zap_pte_range(tlb, vma, pmd, addr, next, details); -+ next: - cond_resched(); - } while (pmd++, addr = next, addr != end); - -diff --git a/mm/mempolicy.c b/mm/mempolicy.c -index 47296fe..0a37570 100644 ---- a/mm/mempolicy.c -+++ b/mm/mempolicy.c -@@ -512,7 +512,7 @@ static inline int check_pmd_range(struct vm_area_struct *vma, pud_t *pud, - do { - next = pmd_addr_end(addr, end); - split_huge_page_pmd(vma->vm_mm, pmd); -- if (pmd_none_or_clear_bad(pmd)) -+ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) - continue; - if (check_pte_range(vma, pmd, addr, next, nodes, - flags, private)) -diff --git a/mm/mincore.c b/mm/mincore.c -index 636a868..936b4ce 100644 ---- a/mm/mincore.c -+++ b/mm/mincore.c -@@ -164,7 +164,7 @@ static void mincore_pmd_range(struct vm_area_struct *vma, pud_t *pud, - } - /* fall through */ - } -- if (pmd_none_or_clear_bad(pmd)) -+ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) - mincore_unmapped_range(vma, addr, next, vec); - else - mincore_pte_range(vma, pmd, addr, next, vec); -diff --git a/mm/pagewalk.c b/mm/pagewalk.c -index 2f5cf10..aa9701e 100644 ---- a/mm/pagewalk.c -+++ b/mm/pagewalk.c -@@ -59,7 +59,7 @@ again: - continue; - - split_huge_page_pmd(walk->mm, pmd); -- if (pmd_none_or_clear_bad(pmd)) -+ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) - goto again; - err = walk_pte_range(pmd, addr, next, walk); - if (err) -diff --git a/mm/swapfile.c b/mm/swapfile.c -index d999f09..f31b29d 100644 ---- a/mm/swapfile.c -+++ b/mm/swapfile.c -@@ -932,9 +932,7 @@ static inline int unuse_pmd_range(struct vm_area_struct *vma, pud_t *pud, - pmd = pmd_offset(pud, addr); - do { - next = pmd_addr_end(addr, end); -- if (unlikely(pmd_trans_huge(*pmd))) -- continue; -- if (pmd_none_or_clear_bad(pmd)) -+ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) - continue; - ret = unuse_pte_range(vma, pmd, addr, next, entry, page); - if (ret) - --- -To unsubscribe, send a message with 'unsubscribe linux-mm' in -the body to majordomo@kvack.org. For more info on Linux MM, -see: http://www.linux-mm.org/ . -Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ -Don't email: email@kvack.org \ No newline at end of file diff --git a/sources b/sources index 2fad201c9..e8c9e05f6 100644 --- a/sources +++ b/sources @@ -1 +1,2 @@ 7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz +10771d657c5bf342bcfe66ed06653ecb patch-3.3.1.xz diff --git a/x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch b/x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch deleted file mode 100644 index 9928829e0..000000000 --- a/x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch +++ /dev/null @@ -1,93 +0,0 @@ -On Tue, 2012-01-31 at 09:26 -0500, Josh Boyer wrote: -> On Wed, Jan 25, 2012 at 06:15:35PM -0500, Josh Boyer wrote: -> > On Wed, Jan 25, 2012 at 02:04:08PM -0800, Suresh Siddha wrote: -> > > On Wed, 2012-01-25 at 08:49 -0500, Josh Boyer wrote: -> > > > [ 0.000000] IOAPIC[1]: apic_id 2, version 255, address 0xfec28000, GSI 24-279 -> > > -> > > This looks indeed like a bogus entry probably returning all 1's for -> > > RTE's etc. Can you please send me a dmesg with "apic=verbose" boot -> > > parameter? -> > -> > Here you go: -> > -> > https://bugzilla.redhat.com/attachment.cgi?id=557552 -> -> Was this helpful at all? I've been watching lkml for a related patch -> in case I was missed on CC but haven't seen anything as of yet. - -Yes, it was helpful. Something like the appended patch should ignore the -bogus io-apic entry all together. As I can't test this, can you or the -reporter give the appended patch a try and ack please? - -thanks, -suresh ---- - -From: Suresh Siddha -Subject: x86, ioapic: add register checks for bogus io-apic entries - -With the recent changes to clear_IO_APIC_pin() which tries to clear -remoteIRR bit explicitly, some of the users started to see -"Unable to reset IRR for apic .." messages. - -Close look shows that these are related to bogus IO-APIC entries which -return's all 1's for their io-apic registers. And the above mentioned error -messages are benign. But kernel should have ignored such io-apic's in the -first place. - -Check if register 0, 1, 2 of the listed io-apic are all 1's and ignore -such io-apic. - -Reported-by: Álvaro Castillo -Signed-off-by: Suresh Siddha ---- - arch/x86/kernel/apic/io_apic.c | 26 ++++++++++++++++++++++++++ - 1 files changed, 26 insertions(+), 0 deletions(-) - -diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c -index fb07275..953e54d 100644 ---- a/arch/x86/kernel/apic/io_apic.c -+++ b/arch/x86/kernel/apic/io_apic.c -@@ -3979,6 +3979,26 @@ static __init int bad_ioapic(unsigned long address) - return 0; - } - -+static __init int bad_ioapic_regs(int idx) -+{ -+ union IO_APIC_reg_00 reg_00; -+ union IO_APIC_reg_01 reg_01; -+ union IO_APIC_reg_02 reg_02; -+ -+ reg_00.raw = io_apic_read(idx, 0); -+ reg_01.raw = io_apic_read(idx, 1); -+ reg_02.raw = io_apic_read(idx, 2); -+ -+ if (reg_00.raw == -1 && reg_01.raw == -1 && reg_02.raw == -1) { -+ printk(KERN_WARNING -+ "I/O APIC 0x%x regs return all ones, skipping!\n", -+ mpc_ioapic_addr(idx)); -+ return 1; -+ } -+ -+ return 0; -+} -+ - void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) - { - int idx = 0; -@@ -3995,6 +4015,12 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) - ioapics[idx].mp_config.apicaddr = address; - - set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); -+ -+ if (bad_ioapic_regs(idx)) { -+ clear_fixmap(FIX_IO_APIC_BASE_0 + idx); -+ return; -+ } -+ - ioapics[idx].mp_config.apicid = io_apic_unique_id(id); - ioapics[idx].mp_config.apicver = io_apic_get_version(idx); - - - - From 0dc1678dba3e0e9c94a56f1fcc5b18470acd6f7b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 2 Apr 2012 20:28:24 -0400 Subject: [PATCH 332/487] Add patch to display more debug info for bug 808990. --- debug-808990.patch | 17 +++++++++++++++++ kernel.spec | 9 ++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 debug-808990.patch diff --git a/debug-808990.patch b/debug-808990.patch new file mode 100644 index 000000000..571bef729 --- /dev/null +++ b/debug-808990.patch @@ -0,0 +1,17 @@ +--- linux-3.3.noarch/net/ipv4/route.c~ 2012-04-02 20:24:44.162789023 -0400 ++++ linux-3.3.noarch/net/ipv4/route.c 2012-04-02 20:25:20.610784137 -0400 +@@ -2794,6 +2794,14 @@ static struct rtable *ip_route_output_sl + fl4->saddr = FIB_RES_PREFSRC(net, res); + + dev_out = FIB_RES_DEV(res); ++ ++ if (!dev_out) { ++ pr_crit("ipv4: FIB_RES_DEV() is NULL, nh_sel=%d\n", ++ res.nh_sel); ++ rth = ERR_PTR(-EINVAL); ++ goto out; ++ } ++ + fl4->flowi4_oif = dev_out->ifindex; + + diff --git a/kernel.spec b/kernel.spec index a169ca0d3..17c96392d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -788,7 +788,9 @@ Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch #rhbz 808207 CVE-2012-1601 Patch21520: KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch -Patch22000: weird-root-dentry-name-debug.patch +# Debug patches +Patch30000: weird-root-dentry-name-debug.patch +Patch30010: debug-808990.patch %endif @@ -1452,7 +1454,9 @@ ApplyPatch shlib_base_randomize.patch ApplyPatch unhandled-irqs-switch-to-polling.patch +# debug patches ApplyPatch weird-root-dentry-name-debug.patch +ApplyPatch debug-808990.patch #rhbz 804347 ApplyPatch x86-add-io_apic_ops-to-allow-interception.patch @@ -2206,6 +2210,9 @@ fi # and build. %changelog +* Mon Apr 02 2012 Dave Jones +- Add patch to display more debug info for bug 808990. + * Mon Apr 02 2012 Dave Jones 3.3.1-1 - Linux 3.3.1 From 57711b475d99eb5473c18eeb4154c63341225a6b Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 2 Apr 2012 20:29:56 -0400 Subject: [PATCH 333/487] Disable CONFIG_DEBUG_PAGEALLOC in -debug builds again. --- config-debug | 2 -- kernel.spec | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/config-debug b/config-debug index ad5f5352c..ca1ba2b59 100644 --- a/config-debug +++ b/config-debug @@ -110,5 +110,3 @@ CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 # CONFIG_DEBUG_KMEMLEAK_TEST is not set CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y -# Temporary -CONFIG_DEBUG_PAGEALLOC=y diff --git a/kernel.spec b/kernel.spec index 17c96392d..cb10cec15 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2210,6 +2210,9 @@ fi # and build. %changelog +* Mon Apr 02 2012 Dave Jones +- Disable CONFIG_DEBUG_PAGEALLOC in -debug builds again. + * Mon Apr 02 2012 Dave Jones - Add patch to display more debug info for bug 808990. From 72ef31e7d8012dba2cb29204cd7c2b8b4b48d8bc Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 2 Apr 2012 20:30:23 -0400 Subject: [PATCH 334/487] bump for build --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index cb10cec15..84440e807 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2210,7 +2210,7 @@ fi # and build. %changelog -* Mon Apr 02 2012 Dave Jones +* Mon Apr 02 2012 Dave Jones 3.3.1-2 - Disable CONFIG_DEBUG_PAGEALLOC in -debug builds again. * Mon Apr 02 2012 Dave Jones From 0b6221081620b9c5f1ddaeb29dfe6ca1311049cd Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 3 Apr 2012 12:55:28 -0400 Subject: [PATCH 335/487] Fix crash in uvc_video_clock_update from Laurent Pinchart (rhbz 806433) --- kernel.spec | 11 +- ...uced-crash-in-uvc_video_clock_update.patch | 113 ++++++++++++++++++ 2 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch diff --git a/kernel.spec b/kernel.spec index 84440e807..905deda33 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -779,6 +779,9 @@ Patch21351: x86-add-io_apic_ops-to-allow-interception.patch Patch21352: x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch Patch21353: xen-x86-Implement-x86_apic_ops.patch +#rhbz 806433 +Patch21360: uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch + #rhbz 770476 Patch21370: iwlegacy-do-not-nulify-il-vif-on-reset.patch Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch @@ -1472,6 +1475,9 @@ ApplyPatch nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch #rhbz 808207 CVE-2012-1601 ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch +#rhbz 806433 +ApplyPatch uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch + # END OF PATCH APPLICATIONS %endif @@ -2210,6 +2216,9 @@ fi # and build. %changelog +* Tue Apr 03 2012 Josh Boyer +- Fix crash in uvc_video_clock_update from Laurent Pinchart (rhbz 806433) + * Mon Apr 02 2012 Dave Jones 3.3.1-2 - Disable CONFIG_DEBUG_PAGEALLOC in -debug builds again. diff --git a/uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch b/uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch new file mode 100644 index 000000000..5f2a1c006 --- /dev/null +++ b/uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch @@ -0,0 +1,113 @@ +@@ -, +, @@ + drivers/media/video/uvc/uvc_video.c | 50 ++++++++++++++++++++++------------ + 1 files changed, 32 insertions(+), 18 deletions(-) +--- a/drivers/media/video/uvc/uvc_video.c ++++ a/drivers/media/video/uvc/uvc_video.c +@@ -468,22 +468,30 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf, + spin_unlock_irqrestore(&stream->clock.lock, flags); + } + +-static int uvc_video_clock_init(struct uvc_streaming *stream) ++static void uvc_video_clock_reset(struct uvc_streaming *stream) + { + struct uvc_clock *clock = &stream->clock; + +- spin_lock_init(&clock->lock); + clock->head = 0; + clock->count = 0; +- clock->size = 32; + clock->last_sof = -1; + clock->sof_offset = -1; ++} ++ ++static int uvc_video_clock_init(struct uvc_streaming *stream) ++{ ++ struct uvc_clock *clock = &stream->clock; ++ ++ spin_lock_init(&clock->lock); ++ clock->size = 32; + + clock->samples = kmalloc(clock->size * sizeof(*clock->samples), + GFP_KERNEL); + if (clock->samples == NULL) + return -ENOMEM; + ++ uvc_video_clock_reset(stream); ++ + return 0; + } + +@@ -1424,8 +1432,6 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) + + if (free_buffers) + uvc_free_urb_buffers(stream); +- +- uvc_video_clock_cleanup(stream); + } + + /* +@@ -1555,10 +1561,6 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) + + uvc_video_stats_start(stream); + +- ret = uvc_video_clock_init(stream); +- if (ret < 0) +- return ret; +- + if (intf->num_altsetting > 1) { + struct usb_host_endpoint *best_ep = NULL; + unsigned int best_psize = 3 * 1024; +@@ -1683,6 +1685,8 @@ int uvc_video_resume(struct uvc_streaming *stream, int reset) + + stream->frozen = 0; + ++ uvc_video_clock_reset(stream); ++ + ret = uvc_commit_video(stream, &stream->ctrl); + if (ret < 0) { + uvc_queue_enable(&stream->queue, 0); +@@ -1819,25 +1823,35 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable) + uvc_uninit_video(stream, 1); + usb_set_interface(stream->dev->udev, stream->intfnum, 0); + uvc_queue_enable(&stream->queue, 0); ++ uvc_video_clock_cleanup(stream); + return 0; + } + +- ret = uvc_queue_enable(&stream->queue, 1); ++ ret = uvc_video_clock_init(stream); + if (ret < 0) + return ret; + ++ ret = uvc_queue_enable(&stream->queue, 1); ++ if (ret < 0) ++ goto error_queue; ++ + /* Commit the streaming parameters. */ + ret = uvc_commit_video(stream, &stream->ctrl); +- if (ret < 0) { +- uvc_queue_enable(&stream->queue, 0); +- return ret; +- } ++ if (ret < 0) ++ goto error_commit; + + ret = uvc_init_video(stream, GFP_KERNEL); +- if (ret < 0) { +- usb_set_interface(stream->dev->udev, stream->intfnum, 0); +- uvc_queue_enable(&stream->queue, 0); +- } ++ if (ret < 0) ++ goto error_video; ++ ++ return 0; ++ ++error_video: ++ usb_set_interface(stream->dev->udev, stream->intfnum, 0); ++error_commit: ++ uvc_queue_enable(&stream->queue, 0); ++error_queue: ++ uvc_video_clock_cleanup(stream); + + return ret; + } From d12aed4d96376cc47ac596492f124dd041d4a902 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 4 Apr 2012 08:19:48 -0400 Subject: [PATCH 336/487] Fix NULL pointer dereference in i2400m (rhbz 808603) --- kernel.spec | 9 +++++ ...vent-a-possible-kernel-bug-due-to-mi.patch | 34 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch diff --git a/kernel.spec b/kernel.spec index 905deda33..3ee0b3b62 100644 --- a/kernel.spec +++ b/kernel.spec @@ -786,6 +786,9 @@ Patch21360: uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch Patch21370: iwlegacy-do-not-nulify-il-vif-on-reset.patch Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch +#rhbz 808603 +Patch21380: wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch + Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch #rhbz 808207 CVE-2012-1601 @@ -1478,6 +1481,9 @@ ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch #rhbz 806433 ApplyPatch uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch +#rhbz 808603 +ApplyPatch wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch + # END OF PATCH APPLICATIONS %endif @@ -2216,6 +2222,9 @@ fi # and build. %changelog +* Wed Apr 04 2012 Josh Boyer +- Fix NULL pointer dereference in i2400m (rhbz 808603) + * Tue Apr 03 2012 Josh Boyer - Fix crash in uvc_video_clock_update from Laurent Pinchart (rhbz 806433) diff --git a/wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch b/wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch new file mode 100644 index 000000000..92b2e9970 --- /dev/null +++ b/wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch @@ -0,0 +1,34 @@ +From 4eee6a3a04e8bb53fbe7de0f64d0524d3fbe3f80 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 26 Mar 2012 09:01:30 +0000 +Subject: [PATCH] wimax: i2400m - prevent a possible kernel bug due to missing + fw_name string + +This happened on a machine with a custom hotplug script calling nameif, +probably due to slow firmware loading. At the time nameif uses ethtool +to gather interface information, i2400m->fw_name is zero and so a null +pointer dereference occurs from within i2400m_get_drvinfo(). + +Signed-off-by: Phil Sutter +Signed-off-by: David S. Miller +--- + drivers/net/wimax/i2400m/netdev.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c +index 63e4b70..1d76ae8 100644 +--- a/drivers/net/wimax/i2400m/netdev.c ++++ b/drivers/net/wimax/i2400m/netdev.c +@@ -597,7 +597,8 @@ static void i2400m_get_drvinfo(struct net_device *net_dev, + struct i2400m *i2400m = net_dev_to_i2400m(net_dev); + + strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver) - 1); +- strncpy(info->fw_version, i2400m->fw_name, sizeof(info->fw_version) - 1); ++ strncpy(info->fw_version, ++ i2400m->fw_name ? : "", sizeof(info->fw_version) - 1); + if (net_dev->dev.parent) + strncpy(info->bus_info, dev_name(net_dev->dev.parent), + sizeof(info->bus_info) - 1); +-- +1.7.7.6 + From 85f4f40f5c4190c81eaa005ed0ca4086dc5581cc Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 4 Apr 2012 08:25:03 -0400 Subject: [PATCH 337/487] Disable MID_PTI driver (rhbz 783561) --- config-generic | 2 +- kernel.spec | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index b25c4dc46..5054b5b4b 100644 --- a/config-generic +++ b/config-generic @@ -4342,6 +4342,7 @@ CONFIG_CFAG12864B=y CONFIG_CFAG12864B_RATE=20 # CONFIG_PHANTOM is not set +# CONFIG_INTEL_MID_PTI is not set CONFIG_POWER_SUPPLY=m # CONFIG_POWER_SUPPLY_DEBUG is not set @@ -4638,7 +4639,6 @@ CONFIG_BCMA_HOST_PCI=y # CONFIG_BCMA_DEBUG is not set # CONFIG_GOOGLE_FIRMWARE is not set -CONFIG_INTEL_MID_PTI=m CONFIG_IOMMU_SUPPORT=y # CONFIG_PM_DEVFREQ is not set diff --git a/kernel.spec b/kernel.spec index 3ee0b3b62..b742cad08 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2223,6 +2223,7 @@ fi %changelog * Wed Apr 04 2012 Josh Boyer +- Disable MID_PTI driver (rhbz 783561) - Fix NULL pointer dereference in i2400m (rhbz 808603) * Tue Apr 03 2012 Josh Boyer From 75c0de8eed7479cfc96a16848b3dc44a237a7208 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 4 Apr 2012 10:42:03 -0400 Subject: [PATCH 338/487] Disable runtime PM for hotpluggable ATA ports (rhbz 806676) --- kernel.spec | 7 + ...ble-runtime-pm-for-hotpluggable-port.patch | 180 ++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 libata-disable-runtime-pm-for-hotpluggable-port.patch diff --git a/kernel.spec b/kernel.spec index b742cad08..ef5d9e2f8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -789,6 +789,9 @@ Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch #rhbz 808603 Patch21380: wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch +#rhbz 806676 +Patch21385: libata-disable-runtime-pm-for-hotpluggable-port.patch + Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch #rhbz 808207 CVE-2012-1601 @@ -1484,6 +1487,9 @@ ApplyPatch uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch #rhbz 808603 ApplyPatch wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch +#rhbz 806676 +ApplyPatch libata-disable-runtime-pm-for-hotpluggable-port.patch + # END OF PATCH APPLICATIONS %endif @@ -2223,6 +2229,7 @@ fi %changelog * Wed Apr 04 2012 Josh Boyer +- Disable runtime PM for hotpluggable ATA ports (rhbz 806676) - Disable MID_PTI driver (rhbz 783561) - Fix NULL pointer dereference in i2400m (rhbz 808603) diff --git a/libata-disable-runtime-pm-for-hotpluggable-port.patch b/libata-disable-runtime-pm-for-hotpluggable-port.patch new file mode 100644 index 000000000..06020fdde --- /dev/null +++ b/libata-disable-runtime-pm-for-hotpluggable-port.patch @@ -0,0 +1,180 @@ +Path: news.gmane.org!not-for-mail +From: Lin Ming +Newsgroups: gmane.linux.ide,gmane.linux.kernel +Subject: [PATCH v2] libata: disable runtime pm for hotpluggable port +Date: Tue, 13 Mar 2012 09:57:37 +0800 +Lines: 131 +Approved: news@gmane.org +Message-ID: <1331603857.3436.24.camel@minggr> +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 7bit +X-Trace: dough.gmane.org 1331603865 12388 80.91.229.3 (13 Mar 2012 01:57:45 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Tue, 13 Mar 2012 01:57:45 +0000 (UTC) +Cc: linux-ide@vger.kernel.org, lkml , + jslaby@suse.cz, cwillu@cwillu.com, jackdachef@gmail.com, + Sergei Shtylyov +To: Jeff Garzik +Original-X-From: linux-ide-owner@vger.kernel.org Tue Mar 13 02:57:43 2012 +Return-path: +Envelope-to: lnx-linux-ide@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1S7Gze-0005pE-Sg + for lnx-linux-ide@plane.gmane.org; Tue, 13 Mar 2012 02:57:43 +0100 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1754650Ab2CMB5l (ORCPT ); + Mon, 12 Mar 2012 21:57:41 -0400 +Original-Received: from mga14.intel.com ([143.182.124.37]:15186 "EHLO mga14.intel.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1754582Ab2CMB5k (ORCPT ); + Mon, 12 Mar 2012 21:57:40 -0400 +Original-Received: from azsmga002.ch.intel.com ([10.2.17.35]) + by azsmga102.ch.intel.com with ESMTP; 12 Mar 2012 18:57:39 -0700 +X-ExtLoop1: 1 +X-IronPort-AV: E=Sophos;i="4.71,315,1320652800"; + d="scan'208";a="76719701" +Original-Received: from minggr.sh.intel.com (HELO [10.239.36.45]) ([10.239.36.45]) + by AZSMGA002.ch.intel.com with ESMTP; 12 Mar 2012 18:57:38 -0700 +X-Mailer: Evolution 2.30.3 +Original-Sender: linux-ide-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-ide@vger.kernel.org +Xref: news.gmane.org gmane.linux.ide:51560 gmane.linux.kernel:1266262 +Archived-At: + +Currently, hotplug doesn't work if port is already runtime suspended. +For now, we simply disable runtime pm for hotpluggable port. +Later, we should add runtime pm support for hotpluggable port too. + +Bug report: +https://lkml.org/lkml/2012/2/19/70 + +v2: +- Use bit 2 and 3 for flags ATA_FLAG_EXTERNAL and ATA_FLAG_PLUGGABLE. + +TODO: add similar hotpluggable port check for controllers other than +AHCI. + +Reported-and-tested-by: Jiri Slaby +Reported-and-tested-by: cwillu@cwillu.com +Reported-and-tested-by: jackdachef@gmail.com +Signed-off-by: Lin Ming +--- + drivers/ata/ahci.c | 3 +++ + drivers/ata/ahci.h | 3 +++ + drivers/ata/libahci.c | 20 ++++++++++++++++++++ + drivers/ata/libata-transport.c | 6 ++++-- + include/linux/libata.h | 2 ++ + 5 files changed, 32 insertions(+), 2 deletions(-) + +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index d07bf03..02e93ff 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -1145,6 +1145,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + if (hpriv->cap & HOST_CAP_PMP) + pi.flags |= ATA_FLAG_PMP; + ++ if (hpriv->cap & HOST_CAP_SXS) ++ pi.flags |= ATA_FLAG_EXTERNAL; ++ + ahci_set_em_messages(hpriv, &pi); + + if (ahci_broken_system_poweroff(pdev)) { +diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h +index b175000..92f7172 100644 +--- a/drivers/ata/ahci.h ++++ b/drivers/ata/ahci.h +@@ -172,6 +172,9 @@ enum { + PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */ + PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ + PORT_CMD_FBSCP = (1 << 22), /* FBS Capable Port */ ++ PORT_CMD_ESP = (1 << 21), /* External SATA Port */ ++ PORT_CMD_MPSP = (1 << 19), /* Mechanical Presence Switch Attached to Port */ ++ PORT_CMD_HPCP = (1 << 18), /* Hot Plug Capable Port */ + PORT_CMD_PMP = (1 << 17), /* PMP attached */ + PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ + PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */ +diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c +index a72bfd0..7d72d3c 100644 +--- a/drivers/ata/libahci.c ++++ b/drivers/ata/libahci.c +@@ -1097,6 +1097,23 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap, + writel(1 << port_no, mmio + HOST_IRQ_STAT); + } + ++static bool ahci_port_pluggable(struct ata_port *ap) ++{ ++ void __iomem *port_mmio = ahci_port_base(ap); ++ u32 cmd; ++ ++ cmd = readl(port_mmio + PORT_CMD); ++ ++ if ((ap->flags & ATA_FLAG_EXTERNAL) && ++ (cmd & PORT_CMD_ESP)) ++ return true; ++ ++ if (cmd & (PORT_CMD_MPSP | PORT_CMD_HPCP)) ++ return true; ++ ++ return false; ++} ++ + void ahci_init_controller(struct ata_host *host) + { + struct ahci_host_priv *hpriv = host->private_data; +@@ -1112,6 +1129,9 @@ void ahci_init_controller(struct ata_host *host) + if (ata_port_is_dummy(ap)) + continue; + ++ if (ahci_port_pluggable(ap)) ++ ap->flags |= ATA_FLAG_PLUGGABLE; ++ + ahci_port_init(host->dev, ap, i, mmio, port_mmio); + } + +diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c +index 74aaee3..a7166b9 100644 +--- a/drivers/ata/libata-transport.c ++++ b/drivers/ata/libata-transport.c +@@ -292,8 +292,10 @@ int ata_tport_add(struct device *parent, + } + + device_enable_async_suspend(dev); +- pm_runtime_set_active(dev); +- pm_runtime_enable(dev); ++ if (!(ap->flags & ATA_FLAG_PLUGGABLE)) { ++ pm_runtime_set_active(dev); ++ pm_runtime_enable(dev); ++ } + + transport_add_device(dev); + transport_configure_device(dev); +diff --git a/include/linux/libata.h b/include/linux/libata.h +index cafc09a..f46961d 100644 +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -187,6 +187,8 @@ enum { + ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */ + /* (doesn't imply presence) */ + ATA_FLAG_SATA = (1 << 1), ++ ATA_FLAG_EXTERNAL = (1 << 2), /* Controller supports external SATA */ ++ ATA_FLAG_PLUGGABLE = (1 << 3), /* Port is hotpluggable */ + ATA_FLAG_NO_ATAPI = (1 << 6), /* No ATAPI support */ + ATA_FLAG_PIO_DMA = (1 << 7), /* PIO cmds via DMA */ + ATA_FLAG_PIO_LBA48 = (1 << 8), /* Host DMA engine is LBA28 only */ +-- +1.7.2.5 + + + +-- +To unsubscribe from this list: send the line "unsubscribe linux-ide" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + From 06a33d04e68df771837ac54f830876fbd8dea5c8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 4 Apr 2012 10:50:46 -0400 Subject: [PATCH 339/487] Add additional bug number for libata hotplug fix (rhbz 807632) --- kernel.spec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index ef5d9e2f8..b5ce43872 100644 --- a/kernel.spec +++ b/kernel.spec @@ -789,7 +789,7 @@ Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch #rhbz 808603 Patch21380: wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch -#rhbz 806676 +#rhbz 806676 807632 Patch21385: libata-disable-runtime-pm-for-hotpluggable-port.patch Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch @@ -1487,7 +1487,7 @@ ApplyPatch uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch #rhbz 808603 ApplyPatch wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch -#rhbz 806676 +#rhbz 806676 807632 ApplyPatch libata-disable-runtime-pm-for-hotpluggable-port.patch # END OF PATCH APPLICATIONS @@ -2229,7 +2229,7 @@ fi %changelog * Wed Apr 04 2012 Josh Boyer -- Disable runtime PM for hotpluggable ATA ports (rhbz 806676) +- Disable runtime PM for hotpluggable ATA ports (rhbz 806676 807632) - Disable MID_PTI driver (rhbz 783561) - Fix NULL pointer dereference in i2400m (rhbz 808603) From a3556f93fb55bf50f2ecab122aaf5c33309e123d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 4 Apr 2012 13:53:25 -0400 Subject: [PATCH 340/487] Add version to changelog for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index b5ce43872..a636cb9fa 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2228,7 +2228,7 @@ fi # and build. %changelog -* Wed Apr 04 2012 Josh Boyer +* Wed Apr 04 2012 Josh Boyer - 3.3.1-3 - Disable runtime PM for hotpluggable ATA ports (rhbz 806676 807632) - Disable MID_PTI driver (rhbz 783561) - Fix NULL pointer dereference in i2400m (rhbz 808603) From 0273af1816dba4b42737b857c26052828fa640b3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 4 Apr 2012 14:43:32 -0400 Subject: [PATCH 341/487] Increase the size of the dmesg buffer Bump it to 256K, as discussed in the community kernel meeting on Mar 30, 2012 --- config-generic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 5054b5b4b..2e78de439 100644 --- a/config-generic +++ b/config-generic @@ -39,7 +39,7 @@ CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=17 +CONFIG_LOG_BUF_SHIFT=18 # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set # CONFIG_EXPERT is not set From 489a5d6586eb887cd65d44f45784fe8d1f480c7e Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 5 Apr 2012 11:46:57 -0400 Subject: [PATCH 342/487] Better watermark the number of pages used by hibernation I/O (Bojan Smojver) (rhbz 785384) --- hibernate-watermark.patch | 99 +++++++++++++++++++++++++++++++++++++++ kernel.spec | 5 ++ 2 files changed, 104 insertions(+) create mode 100644 hibernate-watermark.patch diff --git a/hibernate-watermark.patch b/hibernate-watermark.patch new file mode 100644 index 000000000..2cb75e6ef --- /dev/null +++ b/hibernate-watermark.patch @@ -0,0 +1,99 @@ + +--- a/kernel/power/swap.c ++++ a/kernel/power/swap.c +@@ -6,7 +6,7 @@ + * + * Copyright (C) 1998,2001-2005 Pavel Machek + * Copyright (C) 2006 Rafael J. Wysocki +- * Copyright (C) 2010 Bojan Smojver ++ * Copyright (C) 2010-2012 Bojan Smojver + * + * This file is released under the GPLv2. + * +@@ -51,6 +51,15 @@ + + #define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(sector_t) - 1) + ++/* ++ * Number of pages required to be kept free while writing the image. Always ++ * three quarters of all available pages before the writing starts. ++ */ ++static inline unsigned long reqd_free_pages(void) ++{ ++ return (nr_free_pages() / 4) * 3; ++} ++ + struct swap_map_page { + sector_t entries[MAP_PAGE_ENTRIES]; + sector_t next_swap; +@@ -72,7 +81,7 @@ struct swap_map_handle { + sector_t cur_swap; + sector_t first_sector; + unsigned int k; +- unsigned long nr_free_pages, written; ++ unsigned long reqd_free_pages; + u32 crc32; + }; + +@@ -316,8 +325,7 @@ static int get_swap_writer(struct swap_map_handle *handle) + goto err_rel; + } + handle->k = 0; +- handle->nr_free_pages = nr_free_pages() >> 1; +- handle->written = 0; ++ handle->reqd_free_pages = reqd_free_pages(); + handle->first_sector = handle->cur_swap; + return 0; + err_rel: +@@ -352,11 +360,15 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, + handle->cur_swap = offset; + handle->k = 0; + } +- if (bio_chain && ++handle->written > handle->nr_free_pages) { ++ if (bio_chain && nr_free_pages() <= handle->reqd_free_pages) { + error = hib_wait_on_bio_chain(bio_chain); + if (error) + goto out; +- handle->written = 0; ++ /* ++ * Recalculate the number of required free pages, to make sure ++ * we never take more than a quarter. ++ */ ++ handle->reqd_free_pages = reqd_free_pages(); + } + out: + return error; +@@ -404,7 +416,7 @@ static int swap_writer_finish(struct swap_map_handle *handle, + #define LZO_THREADS 3 + + /* Maximum number of pages for read buffering. */ +-#define LZO_READ_PAGES (MAP_PAGE_ENTRIES * 8) ++#define LZO_READ_PAGES 8192 + + + /** +@@ -615,10 +627,10 @@ static int save_image_lzo(struct swap_map_handle *handle, + } + + /* +- * Adjust number of free pages after all allocations have been done. +- * We don't want to run out of pages when writing. ++ * Adjust the number of required free pages after all allocations have ++ * been done. We don't want to run out of pages when writing. + */ +- handle->nr_free_pages = nr_free_pages() >> 1; ++ handle->reqd_free_pages = reqd_free_pages(); + + /* + * Start the CRC32 thread. +@@ -1129,8 +1141,9 @@ static int load_image_lzo(struct swap_map_handle *handle, + + /* + * Adjust number of pages for read buffering, in case we are short. ++ * Never take more than a quarter of all available pages. + */ +- read_pages = (nr_free_pages() - snapshot_get_image_size()) >> 1; ++ read_pages = (nr_free_pages() - snapshot_get_image_size()) / 4; + read_pages = clamp_val(read_pages, LZO_CMP_PAGES, LZO_READ_PAGES); + + for (i = 0; i < read_pages; i++) { diff --git a/kernel.spec b/kernel.spec index a636cb9fa..220bafc57 100644 --- a/kernel.spec +++ b/kernel.spec @@ -731,6 +731,7 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch Patch14000: hibernate-freeze-filesystems.patch +Patch14001: hibernate-watermark.patch Patch14010: lis3-improve-handling-of-null-rate.patch @@ -1426,6 +1427,7 @@ ApplyPatch efi-dont-map-boot-services-on-32bit.patch # FIXME #ApplyPatch hibernate-freeze-filesystems.patch +ApplyPatch hibernate-watermark.patch ApplyPatch lis3-improve-handling-of-null-rate.patch @@ -2228,6 +2230,9 @@ fi # and build. %changelog +* Thu Apr 05 2012 Dave Jones +- Better watermark the number of pages used by hibernation I/O (Bojan Smojver) (rhbz 785384) + * Wed Apr 04 2012 Josh Boyer - 3.3.1-3 - Disable runtime PM for hotpluggable ATA ports (rhbz 806676 807632) - Disable MID_PTI driver (rhbz 783561) From 5876403f19a1044053f31f88489fa75e7a42e240 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Apr 2012 09:30:13 -0300 Subject: [PATCH 343/487] Update media with the fixes and patches for 3.4 There are also a few new drivers for 3.5. Some fixes here are needed for DVB to work with xine and Kaffeine. Signed-off-by: Mauro Carvalho Chehab --- config-generic | 12 + drivers-media-update.patch | 38124 +++++++++++++++++++++++++ kernel.spec | 12 +- linux-2.6-v4l-dvb-experimental.patch | 0 linux-2.6-v4l-dvb-fixes.patch | 0 linux-2.6-v4l-dvb-update.patch | 0 6 files changed, 38141 insertions(+), 7 deletions(-) create mode 100644 drivers-media-update.patch delete mode 100644 linux-2.6-v4l-dvb-experimental.patch delete mode 100644 linux-2.6-v4l-dvb-fixes.patch delete mode 100644 linux-2.6-v4l-dvb-update.patch diff --git a/config-generic b/config-generic index 2e78de439..3766af795 100644 --- a/config-generic +++ b/config-generic @@ -2658,6 +2658,12 @@ CONFIG_VIDEO_TM6000=m CONFIG_VIDEO_TM6000_ALSA=m CONFIG_VIDEO_TM6000_DVB=m CONFIG_VIDEO_TLG2300=m + +CONFIG_IR_GPIO_CIR=m +CONFIG_MEDIA_TUNER_FC0011=m +CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_USB_KEENE=n + # CONFIG_VIDEO_TIMBERDALE is not set # CONFIG_VIDEO_M5MOLS is not set @@ -2768,6 +2774,12 @@ CONFIG_DVB_STV0299=m CONFIG_DVB_MB86A16=m CONFIG_DVB_DRXD=m CONFIG_DVB_CXD2820R=m +CONFIG_DVB_USB_AZ6007=m +CONFIG_DVB_USB_RTL28XXU=m +CONFIG_DVB_USB_AF9035=m +CONFIG_DVB_RTL2830=m +CONFIG_DVB_M88RS2000=m +CONFIG_DVB_AF9033=m # # Supported Frontend Modules diff --git a/drivers-media-update.patch b/drivers-media-update.patch new file mode 100644 index 000000000..b2ffad5c5 --- /dev/null +++ b/drivers-media-update.patch @@ -0,0 +1,38124 @@ +Driver updates with all media stuff + +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/az6007.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/az6007.c +@@ -0,0 +1,957 @@ ++/* ++ * Driver for AzureWave 6007 DVB-C/T USB2.0 and clones ++ * ++ * Copyright (c) Henry Wang ++ * ++ * This driver was made publicly available by Terratec, at: ++ * http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz ++ * The original driver's license is GPL, as declared with MODULE_LICENSE() ++ * ++ * Copyright (c) 2010-2011 Mauro Carvalho Chehab ++ * Driver modified by in order to work with upstream drxk driver, and ++ * tons of bugs got fixed. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation under version 2 of the License. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include "drxk.h" ++#include "mt2063.h" ++#include "dvb_ca_en50221.h" ++ ++#define DVB_USB_LOG_PREFIX "az6007" ++#include "dvb-usb.h" ++ ++/* debug */ ++int dvb_usb_az6007_debug; ++module_param_named(debug, dvb_usb_az6007_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." ++ DVB_USB_DEBUG_STATUS); ++ ++#define deb_info(args...) dprintk(dvb_usb_az6007_debug, 0x01, args) ++#define deb_xfer(args...) dprintk(dvb_usb_az6007_debug, 0x02, args) ++#define deb_rc(args...) dprintk(dvb_usb_az6007_debug, 0x04, args) ++#define deb_fe(args...) dprintk(dvb_usb_az6007_debug, 0x08, args) ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++/* Known requests (Cypress FX2 firmware + az6007 "private" ones*/ ++ ++#define FX2_OED 0xb5 ++#define AZ6007_READ_DATA 0xb7 ++#define AZ6007_I2C_RD 0xb9 ++#define AZ6007_POWER 0xbc ++#define AZ6007_I2C_WR 0xbd ++#define FX2_SCON1 0xc0 ++#define AZ6007_TS_THROUGH 0xc7 ++#define AZ6007_READ_IR 0xb4 ++ ++struct az6007_device_state { ++ struct mutex mutex; ++ struct mutex ca_mutex; ++ struct dvb_ca_en50221 ca; ++ unsigned warm:1; ++ int (*gate_ctrl) (struct dvb_frontend *, int); ++ unsigned char data[4096]; ++}; ++ ++static struct drxk_config terratec_h7_drxk = { ++ .adr = 0x29, ++ .parallel_ts = true, ++ .dynamic_clk = true, ++ .single_master = true, ++ .enable_merr_cfg = true, ++ .no_i2c_bridge = false, ++ .chunk_size = 64, ++ .mpeg_out_clk_strength = 0x02, ++ .microcode_name = "dvb-usb-terratec-h7-drxk.fw", ++}; ++ ++static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) ++{ ++ struct dvb_usb_adapter *adap = fe->sec_priv; ++ struct az6007_device_state *st; ++ int status = 0; ++ ++ deb_info("%s: %s\n", __func__, enable ? "enable" : "disable"); ++ ++ if (!adap) ++ return -EINVAL; ++ ++ st = adap->dev->priv; ++ ++ if (!st) ++ return -EINVAL; ++ ++ if (enable) ++ status = st->gate_ctrl(fe, 1); ++ else ++ status = st->gate_ctrl(fe, 0); ++ ++ return status; ++} ++ ++static struct mt2063_config az6007_mt2063_config = { ++ .tuner_address = 0x60, ++ .refclock = 36125000, ++}; ++ ++static int __az6007_read(struct usb_device *udev, u8 req, u16 value, ++ u16 index, u8 *b, int blen) ++{ ++ int ret; ++ ++ ret = usb_control_msg(udev, ++ usb_rcvctrlpipe(udev, 0), ++ req, ++ USB_TYPE_VENDOR | USB_DIR_IN, ++ value, index, b, blen, 5000); ++ if (ret < 0) { ++ warn("usb read operation failed. (%d)", ret); ++ return -EIO; ++ } ++ ++ deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, ++ index); ++ debug_dump(b, blen, deb_xfer); ++ ++ return ret; ++} ++ ++static int az6007_read(struct dvb_usb_device *d, u8 req, u16 value, ++ u16 index, u8 *b, int blen) ++{ ++ struct az6007_device_state *st = d->priv; ++ int ret; ++ ++ if (mutex_lock_interruptible(&st->mutex) < 0) ++ return -EAGAIN; ++ ++ ret = __az6007_read(d->udev, req, value, index, b, blen); ++ ++ mutex_unlock(&st->mutex); ++ ++ return ret; ++} ++ ++static int __az6007_write(struct usb_device *udev, u8 req, u16 value, ++ u16 index, u8 *b, int blen) ++{ ++ int ret; ++ ++ deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, ++ index); ++ debug_dump(b, blen, deb_xfer); ++ ++ if (blen > 64) { ++ err("az6007: tried to write %d bytes, but I2C max size is 64 bytes\n", ++ blen); ++ return -EOPNOTSUPP; ++ } ++ ++ ret = usb_control_msg(udev, ++ usb_sndctrlpipe(udev, 0), ++ req, ++ USB_TYPE_VENDOR | USB_DIR_OUT, ++ value, index, b, blen, 5000); ++ if (ret != blen) { ++ err("usb write operation failed. (%d)", ret); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int az6007_write(struct dvb_usb_device *d, u8 req, u16 value, ++ u16 index, u8 *b, int blen) ++{ ++ struct az6007_device_state *st = d->priv; ++ int ret; ++ ++ if (mutex_lock_interruptible(&st->mutex) < 0) ++ return -EAGAIN; ++ ++ ret = __az6007_write(d->udev, req, value, index, b, blen); ++ ++ mutex_unlock(&st->mutex); ++ ++ return ret; ++} ++ ++static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) ++{ ++ struct dvb_usb_device *d = adap->dev; ++ ++ deb_info("%s: %s", __func__, onoff ? "enable" : "disable"); ++ ++ return az6007_write(d, 0xbc, onoff, 0, NULL, 0); ++} ++ ++/* remote control stuff (does not work with my box) */ ++static int az6007_rc_query(struct dvb_usb_device *d) ++{ ++ struct az6007_device_state *st = d->priv; ++ unsigned code = 0; ++ ++ az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10); ++ ++ if (st->data[1] == 0x44) ++ return 0; ++ ++ if ((st->data[1] ^ st->data[2]) == 0xff) ++ code = st->data[1]; ++ else ++ code = st->data[1] << 8 | st->data[2]; ++ ++ if ((st->data[3] ^ st->data[4]) == 0xff) ++ code = code << 8 | st->data[3]; ++ else ++ code = code << 16 | st->data[3] << 8 | st->data[4]; ++ ++ rc_keydown(d->rc_dev, code, st->data[5]); ++ ++ return 0; ++} ++ ++static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, ++ int slot, ++ int address) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; ++ ++ int ret; ++ u8 req; ++ u16 value; ++ u16 index; ++ int blen; ++ u8 *b; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ b = kmalloc(12, GFP_KERNEL); ++ if (!b) ++ return -ENOMEM; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ req = 0xC1; ++ value = address; ++ index = 0; ++ blen = 1; ++ ++ ret = az6007_read(d, req, value, index, b, blen); ++ if (ret < 0) { ++ warn("usb in operation failed. (%d)", ret); ++ ret = -EINVAL; ++ } else { ++ ret = b[0]; ++ } ++ ++ mutex_unlock(&state->ca_mutex); ++ kfree(b); ++ return ret; ++} ++ ++static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, ++ int slot, ++ int address, ++ u8 value) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; ++ ++ int ret; ++ u8 req; ++ u16 value1; ++ u16 index; ++ int blen; ++ ++ deb_info("%s %d", __func__, slot); ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ req = 0xC2; ++ value1 = address; ++ index = value; ++ blen = 0; ++ ++ ret = az6007_write(d, req, value1, index, NULL, blen); ++ if (ret != 0) ++ warn("usb out operation failed. (%d)", ret); ++ ++ mutex_unlock(&state->ca_mutex); ++ return ret; ++} ++ ++static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca, ++ int slot, ++ u8 address) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; ++ ++ int ret; ++ u8 req; ++ u16 value; ++ u16 index; ++ int blen; ++ u8 *b; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ b = kmalloc(12, GFP_KERNEL); ++ if (!b) ++ return -ENOMEM; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ req = 0xC3; ++ value = address; ++ index = 0; ++ blen = 2; ++ ++ ret = az6007_read(d, req, value, index, b, blen); ++ if (ret < 0) { ++ warn("usb in operation failed. (%d)", ret); ++ ret = -EINVAL; ++ } else { ++ if (b[0] == 0) ++ warn("Read CI IO error"); ++ ++ ret = b[1]; ++ deb_info("read cam data = %x from 0x%x", b[1], value); ++ } ++ ++ mutex_unlock(&state->ca_mutex); ++ kfree(b); ++ return ret; ++} ++ ++static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca, ++ int slot, ++ u8 address, ++ u8 value) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; ++ ++ int ret; ++ u8 req; ++ u16 value1; ++ u16 index; ++ int blen; ++ ++ if (slot != 0) ++ return -EINVAL; ++ ++ mutex_lock(&state->ca_mutex); ++ req = 0xC4; ++ value1 = address; ++ index = value; ++ blen = 0; ++ ++ ret = az6007_write(d, req, value1, index, NULL, blen); ++ if (ret != 0) { ++ warn("usb out operation failed. (%d)", ret); ++ goto failed; ++ } ++ ++failed: ++ mutex_unlock(&state->ca_mutex); ++ return ret; ++} ++ ++static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ ++ int ret; ++ u8 req; ++ u16 value; ++ u16 index; ++ int blen; ++ u8 *b; ++ ++ b = kmalloc(12, GFP_KERNEL); ++ if (!b) ++ return -ENOMEM; ++ ++ req = 0xC8; ++ value = 0; ++ index = 0; ++ blen = 1; ++ ++ ret = az6007_read(d, req, value, index, b, blen); ++ if (ret < 0) { ++ warn("usb in operation failed. (%d)", ret); ++ ret = -EIO; ++ } else{ ++ ret = b[0]; ++ } ++ kfree(b); ++ return ret; ++} ++ ++static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; ++ ++ int ret, i; ++ u8 req; ++ u16 value; ++ u16 index; ++ int blen; ++ ++ mutex_lock(&state->ca_mutex); ++ ++ req = 0xC6; ++ value = 1; ++ index = 0; ++ blen = 0; ++ ++ ret = az6007_write(d, req, value, index, NULL, blen); ++ if (ret != 0) { ++ warn("usb out operation failed. (%d)", ret); ++ goto failed; ++ } ++ ++ msleep(500); ++ req = 0xC6; ++ value = 0; ++ index = 0; ++ blen = 0; ++ ++ ret = az6007_write(d, req, value, index, NULL, blen); ++ if (ret != 0) { ++ warn("usb out operation failed. (%d)", ret); ++ goto failed; ++ } ++ ++ for (i = 0; i < 15; i++) { ++ msleep(100); ++ ++ if (CI_CamReady(ca, slot)) { ++ deb_info("CAM Ready"); ++ break; ++ } ++ } ++ msleep(5000); ++ ++failed: ++ mutex_unlock(&state->ca_mutex); ++ return ret; ++} ++ ++static int az6007_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) ++{ ++ return 0; ++} ++ ++static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; ++ ++ int ret; ++ u8 req; ++ u16 value; ++ u16 index; ++ int blen; ++ ++ deb_info("%s", __func__); ++ mutex_lock(&state->ca_mutex); ++ req = 0xC7; ++ value = 1; ++ index = 0; ++ blen = 0; ++ ++ ret = az6007_write(d, req, value, index, NULL, blen); ++ if (ret != 0) { ++ warn("usb out operation failed. (%d)", ret); ++ goto failed; ++ } ++ ++failed: ++ mutex_unlock(&state->ca_mutex); ++ return ret; ++} ++ ++static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) ++{ ++ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; ++ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; ++ int ret; ++ u8 req; ++ u16 value; ++ u16 index; ++ int blen; ++ u8 *b; ++ ++ b = kmalloc(12, GFP_KERNEL); ++ if (!b) ++ return -ENOMEM; ++ mutex_lock(&state->ca_mutex); ++ ++ req = 0xC5; ++ value = 0; ++ index = 0; ++ blen = 1; ++ ++ ret = az6007_read(d, req, value, index, b, blen); ++ if (ret < 0) { ++ warn("usb in operation failed. (%d)", ret); ++ ret = -EIO; ++ } else ++ ret = 0; ++ ++ if (!ret && b[0] == 1) { ++ ret = DVB_CA_EN50221_POLL_CAM_PRESENT | ++ DVB_CA_EN50221_POLL_CAM_READY; ++ } ++ ++ mutex_unlock(&state->ca_mutex); ++ kfree(b); ++ return ret; ++} ++ ++ ++static void az6007_ci_uninit(struct dvb_usb_device *d) ++{ ++ struct az6007_device_state *state; ++ ++ deb_info("%s", __func__); ++ ++ if (NULL == d) ++ return; ++ ++ state = (struct az6007_device_state *)d->priv; ++ if (NULL == state) ++ return; ++ ++ if (NULL == state->ca.data) ++ return; ++ ++ dvb_ca_en50221_release(&state->ca); ++ ++ memset(&state->ca, 0, sizeof(state->ca)); ++} ++ ++ ++static int az6007_ci_init(struct dvb_usb_adapter *a) ++{ ++ struct dvb_usb_device *d = a->dev; ++ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; ++ int ret; ++ ++ deb_info("%s", __func__); ++ ++ mutex_init(&state->ca_mutex); ++ ++ state->ca.owner = THIS_MODULE; ++ state->ca.read_attribute_mem = az6007_ci_read_attribute_mem; ++ state->ca.write_attribute_mem = az6007_ci_write_attribute_mem; ++ state->ca.read_cam_control = az6007_ci_read_cam_control; ++ state->ca.write_cam_control = az6007_ci_write_cam_control; ++ state->ca.slot_reset = az6007_ci_slot_reset; ++ state->ca.slot_shutdown = az6007_ci_slot_shutdown; ++ state->ca.slot_ts_enable = az6007_ci_slot_ts_enable; ++ state->ca.poll_slot_status = az6007_ci_poll_slot_status; ++ state->ca.data = d; ++ ++ ret = dvb_ca_en50221_init(&a->dvb_adap, ++ &state->ca, ++ 0, /* flags */ ++ 1);/* n_slots */ ++ if (ret != 0) { ++ err("Cannot initialize CI: Error %d.", ret); ++ memset(&state->ca, 0, sizeof(state->ca)); ++ return ret; ++ } ++ ++ deb_info("CI initialized."); ++ ++ return 0; ++} ++ ++static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ struct az6007_device_state *st = d->priv; ++ int ret; ++ ++ ret = az6007_read(d, AZ6007_READ_DATA, 6, 0, st->data, 6); ++ memcpy(mac, st->data, sizeof(mac)); ++ ++ if (ret > 0) ++ deb_info("%s: mac is %02x:%02x:%02x:%02x:%02x:%02x\n", ++ __func__, mac[0], mac[1], mac[2], ++ mac[3], mac[4], mac[5]); ++ ++ return ret; ++} ++ ++static int az6007_frontend_attach(struct dvb_usb_adapter *adap) ++{ ++ struct az6007_device_state *st = adap->dev->priv; ++ ++ deb_info("attaching demod drxk"); ++ ++ adap->fe_adap[0].fe = dvb_attach(drxk_attach, &terratec_h7_drxk, ++ &adap->dev->i2c_adap); ++ if (!adap->fe_adap[0].fe) ++ return -EINVAL; ++ ++ adap->fe_adap[0].fe->sec_priv = adap; ++ st->gate_ctrl = adap->fe_adap[0].fe->ops.i2c_gate_ctrl; ++ adap->fe_adap[0].fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; ++ ++ az6007_ci_init(adap); ++ ++ return 0; ++} ++ ++static int az6007_tuner_attach(struct dvb_usb_adapter *adap) ++{ ++ deb_info("attaching tuner mt2063"); ++ ++ /* Attach mt2063 to DVB-C frontend */ ++ if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) ++ adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1); ++ if (!dvb_attach(mt2063_attach, adap->fe_adap[0].fe, ++ &az6007_mt2063_config, ++ &adap->dev->i2c_adap)) ++ return -EINVAL; ++ ++ if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) ++ adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0); ++ ++ return 0; ++} ++ ++int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) ++{ ++ struct az6007_device_state *st = d->priv; ++ int ret; ++ ++ deb_info("%s()\n", __func__); ++ ++ if (!st->warm) { ++ mutex_init(&st->mutex); ++ ++ ret = az6007_write(d, AZ6007_POWER, 0, 2, NULL, 0); ++ if (ret < 0) ++ return ret; ++ msleep(60); ++ ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0); ++ if (ret < 0) ++ return ret; ++ msleep(100); ++ ret = az6007_write(d, AZ6007_POWER, 1, 3, NULL, 0); ++ if (ret < 0) ++ return ret; ++ msleep(20); ++ ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0); ++ if (ret < 0) ++ return ret; ++ ++ msleep(400); ++ ret = az6007_write(d, FX2_SCON1, 0, 3, NULL, 0); ++ if (ret < 0) ++ return ret; ++ msleep(150); ++ ret = az6007_write(d, FX2_SCON1, 1, 3, NULL, 0); ++ if (ret < 0) ++ return ret; ++ msleep(430); ++ ret = az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0); ++ if (ret < 0) ++ return ret; ++ ++ st->warm = true; ++ ++ return 0; ++ } ++ ++ if (!onoff) ++ return 0; ++ ++ az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0); ++ az6007_write(d, AZ6007_TS_THROUGH, 0, 0, NULL, 0); ++ ++ return 0; ++} ++ ++/* I2C */ ++static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], ++ int num) ++{ ++ struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ struct az6007_device_state *st = d->priv; ++ int i, j, len; ++ int ret = 0; ++ u16 index; ++ u16 value; ++ int length; ++ u8 req, addr; ++ ++ if (mutex_lock_interruptible(&st->mutex) < 0) ++ return -EAGAIN; ++ ++ for (i = 0; i < num; i++) { ++ addr = msgs[i].addr << 1; ++ if (((i + 1) < num) ++ && (msgs[i].len == 1) ++ && (!msgs[i].flags & I2C_M_RD) ++ && (msgs[i + 1].flags & I2C_M_RD) ++ && (msgs[i].addr == msgs[i + 1].addr)) { ++ /* ++ * A write + read xfer for the same address, where ++ * the first xfer has just 1 byte length. ++ * Need to join both into one operation ++ */ ++ if (dvb_usb_az6007_debug & 2) ++ printk(KERN_DEBUG ++ "az6007 I2C xfer write+read addr=0x%x len=%d/%d: ", ++ addr, msgs[i].len, msgs[i + 1].len); ++ req = AZ6007_I2C_RD; ++ index = msgs[i].buf[0]; ++ value = addr | (1 << 8); ++ length = 6 + msgs[i + 1].len; ++ len = msgs[i + 1].len; ++ ret = __az6007_read(d->udev, req, value, index, ++ st->data, length); ++ if (ret >= len) { ++ for (j = 0; j < len; j++) { ++ msgs[i + 1].buf[j] = st->data[j + 5]; ++ if (dvb_usb_az6007_debug & 2) ++ printk(KERN_CONT ++ "0x%02x ", ++ msgs[i + 1].buf[j]); ++ } ++ } else ++ ret = -EIO; ++ i++; ++ } else if (!(msgs[i].flags & I2C_M_RD)) { ++ /* write bytes */ ++ if (dvb_usb_az6007_debug & 2) ++ printk(KERN_DEBUG ++ "az6007 I2C xfer write addr=0x%x len=%d: ", ++ addr, msgs[i].len); ++ req = AZ6007_I2C_WR; ++ index = msgs[i].buf[0]; ++ value = addr | (1 << 8); ++ length = msgs[i].len - 1; ++ len = msgs[i].len - 1; ++ if (dvb_usb_az6007_debug & 2) ++ printk(KERN_CONT "(0x%02x) ", msgs[i].buf[0]); ++ for (j = 0; j < len; j++) { ++ st->data[j] = msgs[i].buf[j + 1]; ++ if (dvb_usb_az6007_debug & 2) ++ printk(KERN_CONT "0x%02x ", ++ st->data[j]); ++ } ++ ret = __az6007_write(d->udev, req, value, index, ++ st->data, length); ++ } else { ++ /* read bytes */ ++ if (dvb_usb_az6007_debug & 2) ++ printk(KERN_DEBUG ++ "az6007 I2C xfer read addr=0x%x len=%d: ", ++ addr, msgs[i].len); ++ req = AZ6007_I2C_RD; ++ index = msgs[i].buf[0]; ++ value = addr; ++ length = msgs[i].len + 6; ++ len = msgs[i].len; ++ ret = __az6007_read(d->udev, req, value, index, ++ st->data, length); ++ for (j = 0; j < len; j++) { ++ msgs[i].buf[j] = st->data[j + 5]; ++ if (dvb_usb_az6007_debug & 2) ++ printk(KERN_CONT ++ "0x%02x ", st->data[j + 5]); ++ } ++ } ++ if (dvb_usb_az6007_debug & 2) ++ printk(KERN_CONT "\n"); ++ if (ret < 0) ++ goto err; ++ } ++err: ++ mutex_unlock(&st->mutex); ++ ++ if (ret < 0) { ++ info("%s ERROR: %i", __func__, ret); ++ return ret; ++ } ++ return num; ++} ++ ++static u32 az6007_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static struct i2c_algorithm az6007_i2c_algo = { ++ .master_xfer = az6007_i2c_xfer, ++ .functionality = az6007_i2c_func, ++}; ++ ++int az6007_identify_state(struct usb_device *udev, ++ struct dvb_usb_device_properties *props, ++ struct dvb_usb_device_description **desc, int *cold) ++{ ++ int ret; ++ u8 *mac; ++ ++ mac = kmalloc(6, GFP_ATOMIC); ++ if (!mac) ++ return -ENOMEM; ++ ++ /* Try to read the mac address */ ++ ret = __az6007_read(udev, AZ6007_READ_DATA, 6, 0, mac, 6); ++ if (ret == 6) ++ *cold = 0; ++ else ++ *cold = 1; ++ ++ kfree(mac); ++ ++ if (*cold) { ++ __az6007_write(udev, 0x09, 1, 0, NULL, 0); ++ __az6007_write(udev, 0x00, 0, 0, NULL, 0); ++ __az6007_write(udev, 0x00, 0, 0, NULL, 0); ++ } ++ ++ deb_info("Device is on %s state\n", *cold ? "warm" : "cold"); ++ return 0; ++} ++ ++static struct dvb_usb_device_properties az6007_properties; ++ ++static void az6007_usb_disconnect(struct usb_interface *intf) ++{ ++ struct dvb_usb_device *d = usb_get_intfdata(intf); ++ az6007_ci_uninit(d); ++ dvb_usb_device_exit(intf); ++} ++ ++static int az6007_usb_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ return dvb_usb_device_init(intf, &az6007_properties, ++ THIS_MODULE, NULL, adapter_nr); ++} ++ ++static struct usb_device_id az6007_usb_table[] = { ++ {USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007)}, ++ {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7)}, ++ {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2)}, ++ {0}, ++}; ++ ++MODULE_DEVICE_TABLE(usb, az6007_usb_table); ++ ++static struct dvb_usb_device_properties az6007_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = CYPRESS_FX2, ++ .firmware = "dvb-usb-terratec-h7-az6007.fw", ++ .no_reconnect = 1, ++ .size_of_priv = sizeof(struct az6007_device_state), ++ .identify_state = az6007_identify_state, ++ .num_adapters = 1, ++ .adapter = { ++ { ++ .num_frontends = 1, ++ .fe = {{ ++ .streaming_ctrl = az6007_streaming_ctrl, ++ .tuner_attach = az6007_tuner_attach, ++ .frontend_attach = az6007_frontend_attach, ++ ++ /* parameter for the MPEG2-data transfer */ ++ .stream = { ++ .type = USB_BULK, ++ .count = 10, ++ .endpoint = 0x02, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ }, ++ } } ++ } }, ++ .power_ctrl = az6007_power_ctrl, ++ .read_mac_address = az6007_read_mac_addr, ++ ++ .rc.core = { ++ .rc_interval = 400, ++ .rc_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS, ++ .module_name = "az6007", ++ .rc_query = az6007_rc_query, ++ .allowed_protos = RC_TYPE_NEC, ++ }, ++ .i2c_algo = &az6007_i2c_algo, ++ ++ .num_device_descs = 2, ++ .devices = { ++ { .name = "AzureWave DTV StarBox DVB-T/C USB2.0 (az6007)", ++ .cold_ids = { &az6007_usb_table[0], NULL }, ++ .warm_ids = { NULL }, ++ }, ++ { .name = "TerraTec DTV StarBox DVB-T/C USB2.0 (az6007)", ++ .cold_ids = { &az6007_usb_table[1], &az6007_usb_table[2], NULL }, ++ .warm_ids = { NULL }, ++ }, ++ { NULL }, ++ } ++}; ++ ++/* usb specific object needed to register this driver with the usb subsystem */ ++static struct usb_driver az6007_usb_driver = { ++ .name = "dvb_usb_az6007", ++ .probe = az6007_usb_probe, ++ .disconnect = az6007_usb_disconnect, ++ .id_table = az6007_usb_table, ++}; ++ ++/* module stuff */ ++static int __init az6007_usb_module_init(void) ++{ ++ int result; ++ deb_info("az6007 usb module init\n"); ++ ++ result = usb_register(&az6007_usb_driver); ++ if (result) { ++ err("usb_register failed. (%d)", result); ++ return result; ++ } ++ ++ return 0; ++} ++ ++static void __exit az6007_usb_module_exit(void) ++{ ++ /* deregister this driver from the USB subsystem */ ++ deb_info("az6007 usb module exit\n"); ++ usb_deregister(&az6007_usb_driver); ++} ++ ++module_init(az6007_usb_module_init); ++module_exit(az6007_usb_module_exit); ++ ++MODULE_AUTHOR("Henry Wang "); ++MODULE_AUTHOR("Mauro Carvalho Chehab "); ++MODULE_DESCRIPTION("Driver for AzureWave 6007 DVB-C/T USB2.0 and clones"); ++MODULE_VERSION("1.1"); ++MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/az6007.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/az6007.h +@@ -0,0 +1,18 @@ ++#ifndef _DVB_USB_AZ6007_H_ ++#define _DVB_USB_AZ6007_H_ ++ ++#define DVB_USB_LOG_PREFIX "az6007" ++#include "dvb-usb.h" ++ ++ ++extern int dvb_usb_az6007_debug; ++#define deb_info(args...) dprintk(dvb_usb_az6007_debug,0x01,args) ++#define deb_xfer(args...) dprintk(dvb_usb_az6007_debug,0x02,args) ++#define deb_rc(args...) dprintk(dvb_usb_az6007_debug,0x04,args) ++#define deb_fe(args...) dprintk(dvb_usb_az6007_debug,0x08,args) ++ ++ ++extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec); ++extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); ++ ++#endif +Index: linux-3.3.x86_64/drivers/media/common/tuners/mt2063.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/common/tuners/mt2063.c ++++ linux-3.3.x86_64/drivers/media/common/tuners/mt2063.c +@@ -350,7 +350,7 @@ static int MT2063_Sleep(struct dvb_front + /* + * ToDo: Add code here to implement a OS blocking + */ +- msleep(10); ++ msleep(100); + + return 0; + } +@@ -2226,7 +2226,7 @@ static struct dvb_tuner_ops mt2063_ops = + .info = { + .name = "MT2063 Silicon Tuner", + .frequency_min = 45000000, +- .frequency_max = 850000000, ++ .frequency_max = 865000000, + .frequency_step = 0, + }, + +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/dvb-usb-ids.h ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +@@ -51,6 +51,7 @@ + #define USB_VID_PINNACLE 0x2304 + #define USB_VID_PCTV 0x2013 + #define USB_VID_PIXELVIEW 0x1554 ++#define USB_VID_REALTEK 0x0bda + #define USB_VID_TECHNOTREND 0x0b48 + #define USB_VID_TERRATEC 0x0ccd + #define USB_VID_TELESTAR 0x10b9 +@@ -75,11 +76,14 @@ + #define USB_PID_AFATECH_AF9005 0x9020 + #define USB_PID_AFATECH_AF9015_9015 0x9015 + #define USB_PID_AFATECH_AF9015_9016 0x9016 ++#define USB_PID_AFATECH_AF9035 0x9035 ++#define USB_PID_AFATECH_AF9035_2 0x1001 + #define USB_PID_TREKSTOR_DVBT 0x901b + #define USB_VID_ALINK_DTU 0xf170 + #define USB_PID_ANSONIC_DVBT_USB 0x6000 + #define USB_PID_ANYSEE 0x861f + #define USB_PID_AZUREWAVE_AD_TU700 0x3237 ++#define USB_PID_AZUREWAVE_6007 0x0ccd + #define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 + #define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 + #define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 +@@ -125,6 +129,8 @@ + #define USB_PID_E3C_EC168_3 0xfffb + #define USB_PID_E3C_EC168_4 0x1001 + #define USB_PID_E3C_EC168_5 0x1002 ++#define USB_PID_FREECOM_DVBT 0x0160 ++#define USB_PID_FREECOM_DVBT_2 0x0161 + #define USB_PID_UNIWILL_STK7700P 0x6003 + #define USB_PID_GENIUS_TVGO_DVB_T03 0x4012 + #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 +@@ -148,6 +154,7 @@ + #define USB_PID_KWORLD_VSTREAM_WARM 0x17df + #define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055 + #define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2 0x0069 ++#define USB_PID_TERRATEC_CINERGY_T_STICK 0x0093 + #define USB_PID_TERRATEC_CINERGY_T_STICK_RC 0x0097 + #define USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC 0x0099 + #define USB_PID_TWINHAN_VP7041_COLD 0x3201 +@@ -217,6 +224,11 @@ + #define USB_PID_AVERMEDIA_A850T 0x850b + #define USB_PID_AVERMEDIA_A805 0xa805 + #define USB_PID_AVERMEDIA_A815M 0x815a ++#define USB_PID_AVERMEDIA_A835 0xa835 ++#define USB_PID_AVERMEDIA_B835 0xb835 ++#define USB_PID_AVERMEDIA_1867 0x1867 ++#define USB_PID_AVERMEDIA_A867 0xa867 ++#define USB_PID_AVERMEDIA_TWINSTAR 0x0825 + #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 + #define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d + #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a +@@ -226,6 +238,8 @@ + #define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062 + #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 + #define USB_PID_TERRATEC_CINERGY_T_XXS_2 0x00ab ++#define USB_PID_TERRATEC_H7 0x10b4 ++#define USB_PID_TERRATEC_H7_2 0x10a3 + #define USB_PID_TERRATEC_T3 0x10a0 + #define USB_PID_TERRATEC_T5 0x10a1 + #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e +@@ -249,6 +263,8 @@ + #define USB_PID_PCTV_400E 0x020f + #define USB_PID_PCTV_450E 0x0222 + #define USB_PID_PCTV_452E 0x021f ++#define USB_PID_REALTEK_RTL2831U 0x2831 ++#define USB_PID_REALTEK_RTL2832U 0x2832 + #define USB_PID_TECHNOTREND_CONNECT_S2_3600 0x3007 + #define USB_PID_TECHNOTREND_CONNECT_S2_3650_CI 0x300a + #define USB_PID_NEBULA_DIGITV 0x0201 +Index: linux-3.3.x86_64/drivers/media/dvb/ddbridge/ddbridge-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/ddbridge/ddbridge-core.c ++++ linux-3.3.x86_64/drivers/media/dvb/ddbridge/ddbridge-core.c +@@ -578,6 +578,7 @@ static int demod_attach_drxk(struct ddb_ + struct drxk_config config; + + memset(&config, 0, sizeof(config)); ++ config.microcode_name = "drxk_a3.mc"; + config.adr = 0x29 + (input->nr & 1); + + fe = input->fe = dvb_attach(drxk_attach, &config, i2c); +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/drxk_hard.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/drxk_hard.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/drxk_hard.c +@@ -28,7 +28,6 @@ + #include + #include + #include +-#include + #include + + #include "dvb_frontend.h" +@@ -91,10 +90,6 @@ bool IsA1WithRomCode(struct drxk_state * + #define DRXK_MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH (0x03) + #endif + +-#ifndef DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH +-#define DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH (0x06) +-#endif +- + #define DEFAULT_DRXK_MPEG_LOCK_TIMEOUT 700 + #define DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT 500 + +@@ -650,9 +645,6 @@ static int init_state(struct drxk_state + u32 ulQual83 = DEFAULT_MER_83; + u32 ulQual93 = DEFAULT_MER_93; + +- u32 ulDVBTStaticTSClock = 1; +- u32 ulDVBCStaticTSClock = 1; +- + u32 ulMpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; + u32 ulDemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; + +@@ -662,7 +654,6 @@ static int init_state(struct drxk_state + u32 ulGPIOCfg = 0x0113; + u32 ulInvertTSClock = 0; + u32 ulTSDataStrength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH; +- u32 ulTSClockkStrength = DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH; + u32 ulDVBTBitrate = 50000000; + u32 ulDVBCBitrate = DRXK_QAM_SYMBOLRATE_MAX * 8; + +@@ -815,8 +806,7 @@ static int init_state(struct drxk_state + state->m_invertSTR = false; /* If TRUE; invert STR signals */ + state->m_invertVAL = false; /* If TRUE; invert VAL signals */ + state->m_invertCLK = (ulInvertTSClock != 0); /* If TRUE; invert CLK signals */ +- state->m_DVBTStaticCLK = (ulDVBTStaticTSClock != 0); +- state->m_DVBCStaticCLK = (ulDVBCStaticTSClock != 0); ++ + /* If TRUE; static MPEG clockrate will be used; + otherwise clockrate will adapt to the bitrate of the TS */ + +@@ -824,7 +814,6 @@ static int init_state(struct drxk_state + state->m_DVBCBitrate = ulDVBCBitrate; + + state->m_TSDataStrength = (ulTSDataStrength & 0x07); +- state->m_TSClockkStrength = (ulTSClockkStrength & 0x07); + + /* Maximum bitrate in b/s in case static clockrate is selected */ + state->m_mpegTsStaticBitrate = 19392658; +@@ -1189,6 +1178,7 @@ static int MPEGTSConfigurePins(struct dr + int status = -1; + u16 sioPdrMclkCfg = 0; + u16 sioPdrMdxCfg = 0; ++ u16 err_cfg = 0; + + dprintk(1, ": mpeg %s, %s mode\n", + mpegEnable ? "enable" : "disable", +@@ -1254,12 +1244,17 @@ static int MPEGTSConfigurePins(struct dr + status = write16(state, SIO_PDR_MSTRT_CFG__A, sioPdrMdxCfg); + if (status < 0) + goto error; +- status = write16(state, SIO_PDR_MERR_CFG__A, 0x0000); /* Disable */ ++ ++ if (state->enable_merr_cfg) ++ err_cfg = sioPdrMdxCfg; ++ ++ status = write16(state, SIO_PDR_MERR_CFG__A, err_cfg); + if (status < 0) + goto error; +- status = write16(state, SIO_PDR_MVAL_CFG__A, 0x0000); /* Disable */ ++ status = write16(state, SIO_PDR_MVAL_CFG__A, err_cfg); + if (status < 0) + goto error; ++ + if (state->m_enableParallel == true) { + /* paralel -> enable MD1 to MD7 */ + status = write16(state, SIO_PDR_MD1_CFG__A, sioPdrMdxCfg); +@@ -6070,9 +6065,7 @@ static int init_drxk(struct drxk_state * + if (status < 0) + goto error; + +- if (!state->microcode_name) +- load_microcode(state, "drxk_a3.mc"); +- else ++ if (state->microcode_name) + load_microcode(state, state->microcode_name); + + /* disable token-ring bus through OFDM block for possible ucode upload */ +@@ -6323,15 +6316,12 @@ static int drxk_get_tune_settings(struct + switch (p->delivery_system) { + case SYS_DVBC_ANNEX_A: + case SYS_DVBC_ANNEX_C: ++ case SYS_DVBT: + sets->min_delay_ms = 3000; + sets->max_drift = 0; + sets->step_size = 0; + return 0; + default: +- /* +- * For DVB-T, let it use the default DVB core way, that is: +- * fepriv->step_size = fe->ops.info.frequency_stepsize * 2 +- */ + return -EINVAL; + } + } +@@ -6391,6 +6381,21 @@ struct dvb_frontend *drxk_attach(const s + state->antenna_gpio = config->antenna_gpio; + state->antenna_dvbt = config->antenna_dvbt; + state->m_ChunkSize = config->chunk_size; ++ state->enable_merr_cfg = config->enable_merr_cfg; ++ ++ if (config->dynamic_clk) { ++ state->m_DVBTStaticCLK = 0; ++ state->m_DVBCStaticCLK = 0; ++ } else { ++ state->m_DVBTStaticCLK = 1; ++ state->m_DVBCStaticCLK = 1; ++ } ++ ++ ++ if (config->mpeg_out_clk_strength) ++ state->m_TSClockkStrength = config->mpeg_out_clk_strength & 0x07; ++ else ++ state->m_TSClockkStrength = 0x06; + + if (config->parallel_ts) + state->m_enableParallel = true; +Index: linux-3.3.x86_64/drivers/media/dvb/ngene/ngene-cards.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/ngene/ngene-cards.c ++++ linux-3.3.x86_64/drivers/media/dvb/ngene/ngene-cards.c +@@ -216,6 +216,7 @@ static int demod_attach_drxk(struct ngen + struct drxk_config config; + + memset(&config, 0, sizeof(config)); ++ config.microcode_name = "drxk_a3.mc"; + config.adr = 0x29 + (chan->number ^ 2); + + chan->fe = dvb_attach(drxk_attach, &config, i2c); +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/drxk.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/drxk.h ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/drxk.h +@@ -7,15 +7,19 @@ + /** + * struct drxk_config - Configure the initial parameters for DRX-K + * +- * adr: I2C Address of the DRX-K +- * parallel_ts: true means that the device uses parallel TS, ++ * @adr: I2C Address of the DRX-K ++ * @parallel_ts: True means that the device uses parallel TS, + * Serial otherwise. +- * single_master: Device is on the single master mode +- * no_i2c_bridge: Don't switch the I2C bridge to talk with tuner +- * antenna_gpio: GPIO bit used to control the antenna +- * antenna_dvbt: GPIO bit for changing antenna to DVB-C. A value of 1 ++ * @dynamic_clk: True means that the clock will be dynamically ++ * adjusted. Static clock otherwise. ++ * @enable_merr_cfg: Enable SIO_PDR_PERR_CFG/SIO_PDR_MVAL_CFG. ++ * @single_master: Device is on the single master mode ++ * @no_i2c_bridge: Don't switch the I2C bridge to talk with tuner ++ * @antenna_gpio: GPIO bit used to control the antenna ++ * @antenna_dvbt: GPIO bit for changing antenna to DVB-C. A value of 1 + * means that 1=DVBC, 0 = DVBT. Zero means the opposite. +- * microcode_name: Name of the firmware file with the microcode ++ * @mpeg_out_clk_strength: DRXK Mpeg output clock drive strength. ++ * @microcode_name: Name of the firmware file with the microcode + * + * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is + * UIO-3. +@@ -25,11 +29,14 @@ struct drxk_config { + bool single_master; + bool no_i2c_bridge; + bool parallel_ts; ++ bool dynamic_clk; ++ bool enable_merr_cfg; + + bool antenna_dvbt; + u16 antenna_gpio; + +- int chunk_size; ++ u8 mpeg_out_clk_strength; ++ int chunk_size; + + const char *microcode_name; + }; +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/drxk_hard.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/drxk_hard.h ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/drxk_hard.h +@@ -332,6 +332,7 @@ struct drxk_state { + + u16 UIO_mask; /* Bits used by UIO */ + ++ bool enable_merr_cfg; + bool single_master; + bool no_i2c_bridge; + bool antenna_dvbt; +Index: linux-3.3.x86_64/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c ++++ linux-3.3.x86_64/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c +@@ -18,6 +18,8 @@ + */ + + static struct rc_map_table nec_terratec_cinergy_xs[] = { ++ ++ /* Terratec Grey IR, with most keys in orange */ + { 0x1441, KEY_HOME}, + { 0x1401, KEY_POWER2}, + +@@ -78,6 +80,56 @@ static struct rc_map_table nec_terratec_ + { 0x144e, KEY_REWIND}, + { 0x144f, KEY_FASTFORWARD}, + { 0x145c, KEY_NEXT}, ++ ++ /* Terratec Black IR, with most keys in black */ ++ { 0x04eb01, KEY_POWER2}, ++ ++ { 0x04eb02, KEY_1}, ++ { 0x04eb03, KEY_2}, ++ { 0x04eb04, KEY_3}, ++ { 0x04eb05, KEY_4}, ++ { 0x04eb06, KEY_5}, ++ { 0x04eb07, KEY_6}, ++ { 0x04eb08, KEY_7}, ++ { 0x04eb09, KEY_8}, ++ { 0x04eb0a, KEY_9}, ++ { 0x04eb0c, KEY_0}, ++ ++ { 0x04eb0b, KEY_TEXT}, /* TXT */ ++ { 0x04eb0d, KEY_REFRESH}, /* Refresh */ ++ ++ { 0x04eb0e, KEY_HOME}, ++ { 0x04eb0f, KEY_EPG}, ++ ++ { 0x04eb10, KEY_UP}, ++ { 0x04eb11, KEY_LEFT}, ++ { 0x04eb12, KEY_OK}, ++ { 0x04eb13, KEY_RIGHT}, ++ { 0x04eb14, KEY_DOWN}, ++ ++ { 0x04eb15, KEY_BACKSPACE}, ++ { 0x04eb16, KEY_INFO}, ++ ++ { 0x04eb17, KEY_RED}, ++ { 0x04eb18, KEY_GREEN}, ++ { 0x04eb19, KEY_YELLOW}, ++ { 0x04eb1a, KEY_BLUE}, ++ ++ { 0x04eb1c, KEY_VOLUMEUP}, ++ { 0x04eb1e, KEY_VOLUMEDOWN}, ++ ++ { 0x04eb1d, KEY_MUTE}, ++ ++ { 0x04eb1b, KEY_CHANNELUP}, ++ { 0x04eb1f, KEY_CHANNELDOWN}, ++ ++ { 0x04eb40, KEY_RECORD}, ++ { 0x04eb4c, KEY_PLAY}, ++ { 0x04eb58, KEY_PAUSE}, ++ ++ { 0x04eb54, KEY_REWIND}, ++ { 0x04eb48, KEY_STOP}, ++ { 0x04eb5c, KEY_NEXT}, + }; + + static struct rc_map_list nec_terratec_cinergy_xs_map = { +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/Kconfig +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/Kconfig ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/Kconfig +@@ -361,6 +361,14 @@ config DVB_USB_EC168 + help + Say Y here to support the E3C EC168 DVB-T USB2.0 receiver. + ++config DVB_USB_AZ6007 ++ tristate "AzureWave 6007 and clones DVB-T/C USB2.0 support" ++ depends on DVB_USB ++ select DVB_DRXK if !DVB_FE_CUSTOMISE ++ select MEDIA_TUNER_MT2063 if !DVB_FE_CUSTOMISE ++ help ++ Say Y here to support theAfatech AF9005 based DVB-T/DVB-C receivers. ++ + config DVB_USB_AZ6027 + tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support" + depends on DVB_USB +@@ -378,6 +386,7 @@ config DVB_USB_LME2510 + select DVB_IX2505V if !DVB_FE_CUSTOMISE + select DVB_STV0299 if !DVB_FE_CUSTOMISE + select DVB_PLL if !DVB_FE_CUSTOMISE ++ select DVB_M88RS2000 if !DVB_FE_CUSTOMISE + help + Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 . + +@@ -403,3 +412,25 @@ config DVB_USB_MXL111SF + select VIDEO_TVEEPROM + help + Say Y here to support the MxL111SF USB2.0 DTV receiver. ++ ++config DVB_USB_RTL28XXU ++ tristate "Realtek RTL28xxU DVB USB support" ++ depends on DVB_USB && EXPERIMENTAL ++ select DVB_RTL2830 ++ select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE ++ select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE ++ select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE ++ help ++ Say Y here to support the Realtek RTL28xxU DVB USB receiver. ++ ++config DVB_USB_AF9035 ++ tristate "Afatech AF9035 DVB-T USB2.0 support" ++ depends on DVB_USB ++ select DVB_AF9033 ++ select MEDIA_TUNER_TUA9001 if !MEDIA_TUNER_CUSTOMISE ++ select MEDIA_TUNER_FC0011 if !MEDIA_TUNER_CUSTOMISE ++ select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE ++ select MEDIA_TUNER_TDA18218 if !MEDIA_TUNER_CUSTOMISE ++ help ++ Say Y here to support the Afatech AF9035 based DVB USB receiver. ++ +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/Makefile ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/Makefile +@@ -54,7 +54,6 @@ obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb + dvb-usb-opera-objs = opera1.o + obj-$(CONFIG_DVB_USB_OPERA1) += dvb-usb-opera.o + +- + dvb-usb-af9005-objs = af9005.o af9005-fe.o + obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o + +@@ -88,6 +87,9 @@ obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-f + dvb-usb-ec168-objs = ec168.o + obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o + ++dvb-usb-az6007-objs = az6007.o ++obj-$(CONFIG_DVB_USB_AZ6007) += dvb-usb-az6007.o ++ + dvb-usb-az6027-objs = az6027.o + obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o + +@@ -105,8 +107,15 @@ obj-$(CONFIG_DVB_USB_MXL111SF) += dvb-us + obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-demod.o + obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o + +-ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ ++dvb-usb-rtl28xxu-objs = rtl28xxu.o ++obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o ++ ++dvb-usb-af9035-objs = af9035.o ++obj-$(CONFIG_DVB_USB_AF9035) += dvb-usb-af9035.o ++ ++ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core ++ccflags-y += -I$(srctree)/drivers/media/dvb/frontends/ + # due to tuner-xc3028 +-ccflags-y += -Idrivers/media/common/tuners +-EXTRA_CFLAGS += -Idrivers/media/dvb/ttpci ++ccflags-y += -I$(srctree)/drivers/media/common/tuners ++ccflags-y += -I$(srctree)/drivers/media/dvb/ttpci + +Index: linux-3.3.x86_64/drivers/media/video/omap/omap_vout.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/omap/omap_vout.c ++++ linux-3.3.x86_64/drivers/media/video/omap/omap_vout.c +@@ -2268,13 +2268,12 @@ static struct platform_driver omap_vout_ + .driver = { + .name = VOUT_NAME, + }, +- .probe = omap_vout_probe, + .remove = omap_vout_remove, + }; + + static int __init omap_vout_init(void) + { +- if (platform_driver_register(&omap_vout_driver) != 0) { ++ if (platform_driver_probe(&omap_vout_driver, omap_vout_probe) != 0) { + printk(KERN_ERR VOUT_NAME ":Could not register Video driver\n"); + return -EINVAL; + } +Index: linux-3.3.x86_64/Documentation/DocBook/media/v4l/compat.xml +=================================================================== +--- linux-3.3.x86_64.orig/Documentation/DocBook/media/v4l/compat.xml ++++ linux-3.3.x86_64/Documentation/DocBook/media/v4l/compat.xml +@@ -2393,6 +2393,10 @@ details. + to the User controls class. + + ++ ++ Added the device_caps field to struct v4l2_capabilities and added the new ++ V4L2_CAP_DEVICE_CAPS capability. ++ + + + +Index: linux-3.3.x86_64/Documentation/DocBook/media/v4l/v4l2.xml +=================================================================== +--- linux-3.3.x86_64.orig/Documentation/DocBook/media/v4l/v4l2.xml ++++ linux-3.3.x86_64/Documentation/DocBook/media/v4l/v4l2.xml +@@ -128,6 +128,13 @@ structs, ioctls) must be noted in more d + applications. --> + + ++ 3.3 ++ 2012-01-11 ++ hv ++ Added device_caps field to struct v4l2_capabilities. ++ ++ ++ + 3.2 + 2011-08-26 + hv +@@ -417,7 +424,7 @@ and discussions on the V4L mailing list. + + + Video for Linux Two API Specification +- Revision 3.2 ++ Revision 3.3 + + + &sub-common; +Index: linux-3.3.x86_64/Documentation/DocBook/media/v4l/vidioc-querycap.xml +=================================================================== +--- linux-3.3.x86_64.orig/Documentation/DocBook/media/v4l/vidioc-querycap.xml ++++ linux-3.3.x86_64/Documentation/DocBook/media/v4l/vidioc-querycap.xml +@@ -124,12 +124,35 @@ printf ("Version: %u.%u.%u\n", + + __u32 + capabilities +- Device capabilities, see . ++ Available capabilities of the physical device as a whole, see . The same physical device can export ++ multiple devices in /dev (e.g. /dev/videoX, /dev/vbiY and /dev/radioZ). ++ The capabilities field should contain a union ++ of all capabilities available around the several V4L2 devices exported ++ to userspace. ++ For all those devices the capabilities field ++ returns the same set of capabilities. This allows applications to open ++ just one of the devices (typically the video device) and discover whether ++ video, vbi and/or radio are also supported. ++ + + + __u32 +- reserved[4] ++ device_caps ++ Device capabilities of the opened device, see . Should contain the available capabilities ++ of that specific device node. So, for example, device_caps ++ of a radio device will only contain radio related capabilities and ++ no video or vbi capabilities. This field is only set if the capabilities ++ field contains the V4L2_CAP_DEVICE_CAPS capability. ++ Only the capabilities field can have the ++ V4L2_CAP_DEVICE_CAPS capability, device_caps ++ will never set V4L2_CAP_DEVICE_CAPS. ++ ++ ++ ++ __u32 ++ reserved[3] + Reserved for future extensions. Drivers must set + this array to zero. + +@@ -276,6 +299,13 @@ linkend="async">asynchronous I/O + The device supports the streaming I/O method. + ++ ++ V4L2_CAP_DEVICE_CAPS ++ 0x80000000 ++ The driver fills the device_caps ++ field. This capability can only appear in the capabilities ++ field and never in the device_caps field. ++ + + + +Index: linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-417.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx231xx/cx231xx-417.c ++++ linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-417.c +@@ -1686,7 +1686,6 @@ static struct v4l2_capability pvr_capabi + .capabilities = (V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | + V4L2_CAP_STREAMING | V4L2_CAP_READWRITE), +- .reserved = {0, 0, 0, 0} + }; + static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +Index: linux-3.3.x86_64/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/pvrusb2/pvrusb2-v4l2.c ++++ linux-3.3.x86_64/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +@@ -96,7 +96,6 @@ static struct v4l2_capability pvr_capabi + .capabilities = (V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | + V4L2_CAP_READWRITE), +- .reserved = {0,0,0,0} + }; + + static struct v4l2_fmtdesc pvr_fmtdesc [] = { +Index: linux-3.3.x86_64/drivers/media/video/v4l2-ioctl.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/v4l2-ioctl.c ++++ linux-3.3.x86_64/drivers/media/video/v4l2-ioctl.c +@@ -260,6 +260,8 @@ static const char *v4l2_ioctls[] = { + [_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD", + [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD", + ++ [_IOC_NR(VIDIOC_DECODER_CMD)] = "VIDIOC_DECODER_CMD", ++ [_IOC_NR(VIDIOC_TRY_DECODER_CMD)] = "VIDIOC_TRY_DECODER_CMD", + [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", + [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", + +@@ -540,10 +542,12 @@ static long __video_do_ioctl(struct file + if (!ret) + dbgarg(cmd, "driver=%s, card=%s, bus=%s, " + "version=0x%08x, " +- "capabilities=0x%08x\n", ++ "capabilities=0x%08x, " ++ "device_caps=0x%08x\n", + cap->driver, cap->card, cap->bus_info, + cap->version, +- cap->capabilities); ++ cap->capabilities, ++ cap->device_caps); + break; + } + +@@ -1762,6 +1766,32 @@ static long __video_do_ioctl(struct file + dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); + break; + } ++ case VIDIOC_DECODER_CMD: ++ { ++ struct v4l2_decoder_cmd *p = arg; ++ ++ if (!ops->vidioc_decoder_cmd) ++ break; ++ if (ret_prio) { ++ ret = ret_prio; ++ break; ++ } ++ ret = ops->vidioc_decoder_cmd(file, fh, p); ++ if (!ret) ++ dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); ++ break; ++ } ++ case VIDIOC_TRY_DECODER_CMD: ++ { ++ struct v4l2_decoder_cmd *p = arg; ++ ++ if (!ops->vidioc_try_decoder_cmd) ++ break; ++ ret = ops->vidioc_try_decoder_cmd(file, fh, p); ++ if (!ret) ++ dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); ++ break; ++ } + case VIDIOC_G_PARM: + { + struct v4l2_streamparm *p = arg; +@@ -1909,7 +1939,13 @@ static long __video_do_ioctl(struct file + { + if (!ops->vidioc_log_status) + break; ++ if (vfd->v4l2_dev) ++ pr_info("%s: ================= START STATUS =================\n", ++ vfd->v4l2_dev->name); + ret = ops->vidioc_log_status(file, fh); ++ if (vfd->v4l2_dev) ++ pr_info("%s: ================== END STATUS ==================\n", ++ vfd->v4l2_dev->name); + break; + } + #ifdef CONFIG_VIDEO_ADV_DEBUG +@@ -2419,7 +2455,7 @@ video_usercopy(struct file *file, unsign + /* Handles IOCTL */ + err = func(file, cmd, parg); + if (err == -ENOIOCTLCMD) +- err = -EINVAL; ++ err = -ENOTTY; + + if (has_array_args) { + *kernel_ptr = user_ptr; +Index: linux-3.3.x86_64/include/linux/videodev2.h +=================================================================== +--- linux-3.3.x86_64.orig/include/linux/videodev2.h ++++ linux-3.3.x86_64/include/linux/videodev2.h +@@ -235,16 +235,25 @@ struct v4l2_fract { + __u32 denominator; + }; + +-/* +- * D R I V E R C A P A B I L I T I E S +- */ ++/** ++ * struct v4l2_capability - Describes V4L2 device caps returned by VIDIOC_QUERYCAP ++ * ++ * @driver: name of the driver module (e.g. "bttv") ++ * @card: name of the card (e.g. "Hauppauge WinTV") ++ * @bus_info: name of the bus (e.g. "PCI:" + pci_name(pci_dev) ) ++ * @version: KERNEL_VERSION ++ * @capabilities: capabilities of the physical device as a whole ++ * @device_caps: capabilities accessed via this particular device (node) ++ * @reserved: reserved fields for future extensions ++ */ + struct v4l2_capability { +- __u8 driver[16]; /* i.e. "bttv" */ +- __u8 card[32]; /* i.e. "Hauppauge WinTV" */ +- __u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */ +- __u32 version; /* should use KERNEL_VERSION() */ +- __u32 capabilities; /* Device capabilities */ +- __u32 reserved[4]; ++ __u8 driver[16]; ++ __u8 card[32]; ++ __u8 bus_info[32]; ++ __u32 version; ++ __u32 capabilities; ++ __u32 device_caps; ++ __u32 reserved[3]; + }; + + /* Values for 'capabilities' field */ +@@ -274,6 +283,8 @@ struct v4l2_capability { + #define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */ + #define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */ + ++#define V4L2_CAP_DEVICE_CAPS 0x80000000 /* sets device capabilities field */ ++ + /* + * V I D E O I M A G E F O R M A T + */ +@@ -751,20 +762,20 @@ struct v4l2_crop { + + /* Selection targets */ + +-/* current cropping area */ +-#define V4L2_SEL_TGT_CROP_ACTIVE 0 +-/* default cropping area */ +-#define V4L2_SEL_TGT_CROP_DEFAULT 1 +-/* cropping bounds */ +-#define V4L2_SEL_TGT_CROP_BOUNDS 2 +-/* current composing area */ +-#define V4L2_SEL_TGT_COMPOSE_ACTIVE 256 +-/* default composing area */ +-#define V4L2_SEL_TGT_COMPOSE_DEFAULT 257 +-/* composing bounds */ +-#define V4L2_SEL_TGT_COMPOSE_BOUNDS 258 +-/* current composing area plus all padding pixels */ +-#define V4L2_SEL_TGT_COMPOSE_PADDED 259 ++/* Current cropping area */ ++#define V4L2_SEL_TGT_CROP_ACTIVE 0x0000 ++/* Default cropping area */ ++#define V4L2_SEL_TGT_CROP_DEFAULT 0x0001 ++/* Cropping bounds */ ++#define V4L2_SEL_TGT_CROP_BOUNDS 0x0002 ++/* Current composing area */ ++#define V4L2_SEL_TGT_COMPOSE_ACTIVE 0x0100 ++/* Default composing area */ ++#define V4L2_SEL_TGT_COMPOSE_DEFAULT 0x0101 ++/* Composing bounds */ ++#define V4L2_SEL_TGT_COMPOSE_BOUNDS 0x0102 ++/* Current composing area plus all padding pixels */ ++#define V4L2_SEL_TGT_COMPOSE_PADDED 0x0103 + + /** + * struct v4l2_selection - selection info +@@ -774,7 +785,7 @@ struct v4l2_crop { + * @r: coordinates of selection window + * @reserved: for future use, rounds structure size to 64 bytes, set to zero + * +- * Hardware may use multiple helper window to process a video stream. ++ * Hardware may use multiple helper windows to process a video stream. + * The structure is used to exchange this selection areas between + * an application and a driver. + */ +@@ -1125,6 +1136,7 @@ struct v4l2_ext_controls { + #define V4L2_CTRL_CLASS_CAMERA 0x009a0000 /* Camera class controls */ + #define V4L2_CTRL_CLASS_FM_TX 0x009b0000 /* FM Modulator control class */ + #define V4L2_CTRL_CLASS_FLASH 0x009c0000 /* Camera flash controls */ ++#define V4L2_CTRL_CLASS_JPEG 0x009d0000 /* JPEG-compression controls */ + + #define V4L2_CTRL_ID_MASK (0x0fffffff) + #define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) +@@ -1396,6 +1408,16 @@ enum v4l2_mpeg_audio_ac3_bitrate { + V4L2_MPEG_AUDIO_AC3_BITRATE_576K = 17, + V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18, + }; ++#define V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK (V4L2_CID_MPEG_BASE+112) ++enum v4l2_mpeg_audio_dec_playback { ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO = 0, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO = 1, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT = 2, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_RIGHT = 3, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_MONO = 4, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO = 5, ++}; ++#define V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK (V4L2_CID_MPEG_BASE+113) + + /* MPEG video controls specific to multiplexed streams */ + #define V4L2_CID_MPEG_VIDEO_ENCODING (V4L2_CID_MPEG_BASE+200) +@@ -1446,6 +1468,9 @@ enum v4l2_mpeg_video_multi_slice_mode { + V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES = 2, + }; + #define V4L2_CID_MPEG_VIDEO_VBV_SIZE (V4L2_CID_MPEG_BASE+222) ++#define V4L2_CID_MPEG_VIDEO_DEC_PTS (V4L2_CID_MPEG_BASE+223) ++#define V4L2_CID_MPEG_VIDEO_DEC_FRAME (V4L2_CID_MPEG_BASE+224) ++ + #define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP (V4L2_CID_MPEG_BASE+300) + #define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP (V4L2_CID_MPEG_BASE+301) + #define V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP (V4L2_CID_MPEG_BASE+302) +@@ -1734,6 +1759,29 @@ enum v4l2_flash_strobe_source { + #define V4L2_CID_FLASH_CHARGE (V4L2_CID_FLASH_CLASS_BASE + 11) + #define V4L2_CID_FLASH_READY (V4L2_CID_FLASH_CLASS_BASE + 12) + ++/* JPEG-class control IDs defined by V4L2 */ ++#define V4L2_CID_JPEG_CLASS_BASE (V4L2_CTRL_CLASS_JPEG | 0x900) ++#define V4L2_CID_JPEG_CLASS (V4L2_CTRL_CLASS_JPEG | 1) ++ ++#define V4L2_CID_JPEG_CHROMA_SUBSAMPLING (V4L2_CID_JPEG_CLASS_BASE + 1) ++enum v4l2_jpeg_chroma_subsampling { ++ V4L2_JPEG_CHROMA_SUBSAMPLING_444 = 0, ++ V4L2_JPEG_CHROMA_SUBSAMPLING_422 = 1, ++ V4L2_JPEG_CHROMA_SUBSAMPLING_420 = 2, ++ V4L2_JPEG_CHROMA_SUBSAMPLING_411 = 3, ++ V4L2_JPEG_CHROMA_SUBSAMPLING_410 = 4, ++ V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY = 5, ++}; ++#define V4L2_CID_JPEG_RESTART_INTERVAL (V4L2_CID_JPEG_CLASS_BASE + 2) ++#define V4L2_CID_JPEG_COMPRESSION_QUALITY (V4L2_CID_JPEG_CLASS_BASE + 3) ++ ++#define V4L2_CID_JPEG_ACTIVE_MARKER (V4L2_CID_JPEG_CLASS_BASE + 4) ++#define V4L2_JPEG_ACTIVE_MARKER_APP0 (1 << 0) ++#define V4L2_JPEG_ACTIVE_MARKER_APP1 (1 << 1) ++#define V4L2_JPEG_ACTIVE_MARKER_COM (1 << 16) ++#define V4L2_JPEG_ACTIVE_MARKER_DQT (1 << 17) ++#define V4L2_JPEG_ACTIVE_MARKER_DHT (1 << 18) ++ + /* + * T U N I N G + */ +@@ -1897,6 +1945,54 @@ struct v4l2_encoder_cmd { + }; + }; + ++/* Decoder commands */ ++#define V4L2_DEC_CMD_START (0) ++#define V4L2_DEC_CMD_STOP (1) ++#define V4L2_DEC_CMD_PAUSE (2) ++#define V4L2_DEC_CMD_RESUME (3) ++ ++/* Flags for V4L2_DEC_CMD_START */ ++#define V4L2_DEC_CMD_START_MUTE_AUDIO (1 << 0) ++ ++/* Flags for V4L2_DEC_CMD_PAUSE */ ++#define V4L2_DEC_CMD_PAUSE_TO_BLACK (1 << 0) ++ ++/* Flags for V4L2_DEC_CMD_STOP */ ++#define V4L2_DEC_CMD_STOP_TO_BLACK (1 << 0) ++#define V4L2_DEC_CMD_STOP_IMMEDIATELY (1 << 1) ++ ++/* Play format requirements (returned by the driver): */ ++ ++/* The decoder has no special format requirements */ ++#define V4L2_DEC_START_FMT_NONE (0) ++/* The decoder requires full GOPs */ ++#define V4L2_DEC_START_FMT_GOP (1) ++ ++/* The structure must be zeroed before use by the application ++ This ensures it can be extended safely in the future. */ ++struct v4l2_decoder_cmd { ++ __u32 cmd; ++ __u32 flags; ++ union { ++ struct { ++ __u64 pts; ++ } stop; ++ ++ struct { ++ /* 0 or 1000 specifies normal speed, ++ 1 specifies forward single stepping, ++ -1 specifies backward single stepping, ++ >1: playback at speed/1000 of the normal speed, ++ <-1: reverse playback at (-speed/1000) of the normal speed. */ ++ __s32 speed; ++ __u32 format; ++ } start; ++ ++ struct { ++ __u32 data[16]; ++ } raw; ++ }; ++}; + #endif + + +@@ -2307,6 +2403,11 @@ struct v4l2_create_buffers { + #define VIDIOC_G_SELECTION _IOWR('V', 94, struct v4l2_selection) + #define VIDIOC_S_SELECTION _IOWR('V', 95, struct v4l2_selection) + ++/* Experimental, these two ioctls may change over the next couple of kernel ++ versions. */ ++#define VIDIOC_DECODER_CMD _IOWR('V', 96, struct v4l2_decoder_cmd) ++#define VIDIOC_TRY_DECODER_CMD _IOWR('V', 97, struct v4l2_decoder_cmd) ++ + /* Reminder: when adding new ioctls please add support for them to + drivers/media/video/v4l2-compat-ioctl32.c as well! */ + +Index: linux-3.3.x86_64/drivers/media/video/vivi.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/vivi.c ++++ linux-3.3.x86_64/drivers/media/video/vivi.c +@@ -819,8 +819,9 @@ static int vidioc_querycap(struct file * + strcpy(cap->driver, "vivi"); + strcpy(cap->card, "vivi"); + strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); +- cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \ ++ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; ++ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + return 0; + } + +@@ -958,14 +959,6 @@ static int vidioc_streamoff(struct file + return vb2_streamoff(&dev->vb_vidq, i); + } + +-static int vidioc_log_status(struct file *file, void *priv) +-{ +- struct vivi_dev *dev = video_drvdata(file); +- +- v4l2_ctrl_handler_log_status(&dev->ctrl_handler, dev->v4l2_dev.name); +- return 0; +-} +- + static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) + { + return 0; +@@ -1008,17 +1001,6 @@ static int vidioc_s_input(struct file *f + return 0; + } + +-static int vidioc_subscribe_event(struct v4l2_fh *fh, +- struct v4l2_event_subscription *sub) +-{ +- switch (sub->type) { +- case V4L2_EVENT_CTRL: +- return v4l2_event_subscribe(fh, sub, 0); +- default: +- return -EINVAL; +- } +-} +- + /* --- controls ---------------------------------------------- */ + + static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl) +@@ -1057,17 +1039,10 @@ static unsigned int + vivi_poll(struct file *file, struct poll_table_struct *wait) + { + struct vivi_dev *dev = video_drvdata(file); +- struct v4l2_fh *fh = file->private_data; + struct vb2_queue *q = &dev->vb_vidq; +- unsigned int res; + + dprintk(dev, 1, "%s\n", __func__); +- res = vb2_poll(q, file, wait); +- if (v4l2_event_pending(fh)) +- res |= POLLPRI; +- else +- poll_wait(file, &fh->wait, wait); +- return res; ++ return vb2_poll(q, file, wait); + } + + static int vivi_close(struct file *file) +@@ -1209,8 +1184,8 @@ static const struct v4l2_ioctl_ops vivi_ + .vidioc_s_input = vidioc_s_input, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, +- .vidioc_log_status = vidioc_log_status, +- .vidioc_subscribe_event = vidioc_subscribe_event, ++ .vidioc_log_status = v4l2_ctrl_log_status, ++ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + }; + +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-driver.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-driver.h ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-driver.h +@@ -331,6 +331,7 @@ struct ivtv_stream { + struct ivtv *itv; /* for ease of use */ + const char *name; /* name of the stream */ + int type; /* stream type */ ++ u32 caps; /* V4L2 capabilities */ + + struct v4l2_fh *fh; /* pointer to the streaming filehandle */ + spinlock_t qlock; /* locks access to the queues */ +@@ -630,6 +631,16 @@ struct ivtv { + + struct v4l2_device v4l2_dev; + struct cx2341x_handler cxhdl; ++ struct { ++ /* PTS/Frame count control cluster */ ++ struct v4l2_ctrl *ctrl_pts; ++ struct v4l2_ctrl *ctrl_frame; ++ }; ++ struct { ++ /* Audio Playback control cluster */ ++ struct v4l2_ctrl *ctrl_audio_playback; ++ struct v4l2_ctrl *ctrl_audio_multilingual_playback; ++ }; + struct v4l2_ctrl_handler hdl_gpio; + struct v4l2_subdev sd_gpio; /* GPIO sub-device */ + u16 instance; +@@ -649,7 +660,6 @@ struct ivtv { + u8 audio_stereo_mode; /* decoder setting how to handle stereo MPEG audio */ + u8 audio_bilingual_mode; /* decoder setting how to handle bilingual MPEG audio */ + +- + /* Locking */ + spinlock_t lock; /* lock access to this struct */ + struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */ +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-ioctl.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-ioctl.c ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-ioctl.c +@@ -246,34 +246,40 @@ static int ivtv_validate_speed(int cur_s + } + + static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, +- struct video_command *vc, int try) ++ struct v4l2_decoder_cmd *dc, int try) + { + struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; + + if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) + return -EINVAL; + +- switch (vc->cmd) { +- case VIDEO_CMD_PLAY: { +- vc->flags = 0; +- vc->play.speed = ivtv_validate_speed(itv->speed, vc->play.speed); +- if (vc->play.speed < 0) +- vc->play.format = VIDEO_PLAY_FMT_GOP; ++ switch (dc->cmd) { ++ case V4L2_DEC_CMD_START: { ++ dc->flags &= V4L2_DEC_CMD_START_MUTE_AUDIO; ++ dc->start.speed = ivtv_validate_speed(itv->speed, dc->start.speed); ++ if (dc->start.speed < 0) ++ dc->start.format = V4L2_DEC_START_FMT_GOP; ++ else ++ dc->start.format = V4L2_DEC_START_FMT_NONE; ++ if (dc->start.speed != 500 && dc->start.speed != 1500) ++ dc->flags = dc->start.speed == 1000 ? 0 : ++ V4L2_DEC_CMD_START_MUTE_AUDIO; + if (try) break; + ++ itv->speed_mute_audio = dc->flags & V4L2_DEC_CMD_START_MUTE_AUDIO; + if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG) + return -EBUSY; + if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) { + /* forces ivtv_set_speed to be called */ + itv->speed = 0; + } +- return ivtv_start_decoding(id, vc->play.speed); ++ return ivtv_start_decoding(id, dc->start.speed); + } + +- case VIDEO_CMD_STOP: +- vc->flags &= VIDEO_CMD_STOP_IMMEDIATELY|VIDEO_CMD_STOP_TO_BLACK; +- if (vc->flags & VIDEO_CMD_STOP_IMMEDIATELY) +- vc->stop.pts = 0; ++ case V4L2_DEC_CMD_STOP: ++ dc->flags &= V4L2_DEC_CMD_STOP_IMMEDIATELY | V4L2_DEC_CMD_STOP_TO_BLACK; ++ if (dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) ++ dc->stop.pts = 0; + if (try) break; + if (atomic_read(&itv->decoding) == 0) + return 0; +@@ -281,22 +287,22 @@ static int ivtv_video_command(struct ivt + return -EBUSY; + + itv->output_mode = OUT_NONE; +- return ivtv_stop_v4l2_decode_stream(s, vc->flags, vc->stop.pts); ++ return ivtv_stop_v4l2_decode_stream(s, dc->flags, dc->stop.pts); + +- case VIDEO_CMD_FREEZE: +- vc->flags &= VIDEO_CMD_FREEZE_TO_BLACK; ++ case V4L2_DEC_CMD_PAUSE: ++ dc->flags &= V4L2_DEC_CMD_PAUSE_TO_BLACK; + if (try) break; + if (itv->output_mode != OUT_MPG) + return -EBUSY; + if (atomic_read(&itv->decoding) > 0) { + ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, +- (vc->flags & VIDEO_CMD_FREEZE_TO_BLACK) ? 1 : 0); ++ (dc->flags & V4L2_DEC_CMD_PAUSE_TO_BLACK) ? 1 : 0); + set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); + } + break; + +- case VIDEO_CMD_CONTINUE: +- vc->flags = 0; ++ case V4L2_DEC_CMD_RESUME: ++ dc->flags = 0; + if (try) break; + if (itv->output_mode != OUT_MPG) + return -EBUSY; +@@ -754,12 +760,15 @@ static int ivtv_s_register(struct file * + + static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap) + { +- struct ivtv *itv = fh2id(fh)->itv; ++ struct ivtv_open_id *id = fh2id(file->private_data); ++ struct ivtv *itv = id->itv; ++ struct ivtv_stream *s = &itv->streams[id->type]; + + strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); + strlcpy(vcap->card, itv->card_name, sizeof(vcap->card)); + snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev)); +- vcap->capabilities = itv->v4l2_cap; /* capabilities */ ++ vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS; ++ vcap->device_caps = s->caps; + return 0; + } + +@@ -1476,8 +1485,6 @@ static int ivtv_log_status(struct file * + struct v4l2_audio audin; + int i; + +- IVTV_INFO("================= START STATUS CARD #%d =================\n", +- itv->instance); + IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name); + if (itv->hw_flags & IVTV_HW_TVEEPROM) { + struct tveeprom tv; +@@ -1501,13 +1508,6 @@ static int ivtv_log_status(struct file * + "YUV Frames", + "Passthrough", + }; +- static const char * const audio_modes[5] = { +- "Stereo", +- "Left", +- "Right", +- "Mono", +- "Swapped" +- }; + static const char * const alpha_mode[4] = { + "None", + "Global", +@@ -1536,9 +1536,6 @@ static int ivtv_log_status(struct file * + ivtv_get_output(itv, itv->active_output, &vidout); + ivtv_get_audio_output(itv, 0, &audout); + IVTV_INFO("Video Output: %s\n", vidout.name); +- IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name, +- audio_modes[itv->audio_stereo_mode], +- audio_modes[itv->audio_bilingual_mode]); + if (mode < 0 || mode > OUT_PASSTHROUGH) + mode = OUT_NONE; + IVTV_INFO("Output Mode: %s\n", output_modes[mode]); +@@ -1566,12 +1563,27 @@ static int ivtv_log_status(struct file * + IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", + (long long)itv->mpg_data_received, + (long long)itv->vbi_data_inserted); +- IVTV_INFO("================== END STATUS CARD #%d ==================\n", +- itv->instance); +- + return 0; + } + ++static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) ++{ ++ struct ivtv_open_id *id = fh2id(file->private_data); ++ struct ivtv *itv = id->itv; ++ ++ IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n", dec->cmd); ++ return ivtv_video_command(itv, id, dec, false); ++} ++ ++static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) ++{ ++ struct ivtv_open_id *id = fh2id(file->private_data); ++ struct ivtv *itv = id->itv; ++ ++ IVTV_DEBUG_IOCTL("VIDIOC_TRY_DECODER_CMD %d\n", dec->cmd); ++ return ivtv_video_command(itv, id, dec, true); ++} ++ + static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) + { + struct ivtv_open_id *id = fh2id(filp->private_data); +@@ -1605,9 +1617,15 @@ static int ivtv_decoder_ioctls(struct fi + return ivtv_yuv_prep_frame(itv, args); + } + ++ case IVTV_IOC_PASSTHROUGH_MODE: ++ IVTV_DEBUG_IOCTL("IVTV_IOC_PASSTHROUGH_MODE\n"); ++ if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) ++ return -EINVAL; ++ return ivtv_passthrough_mode(itv, *(int *)arg != 0); ++ + case VIDEO_GET_PTS: { +- u32 data[CX2341X_MBOX_MAX_DATA]; +- u64 *pts = arg; ++ s64 *pts = arg; ++ s64 frame; + + IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n"); + if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { +@@ -1616,29 +1634,12 @@ static int ivtv_decoder_ioctls(struct fi + } + if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) + return -EINVAL; +- +- if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { +- *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) | +- (u64)itv->last_dec_timing[1]; +- break; +- } +- *pts = 0; +- if (atomic_read(&itv->decoding)) { +- if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { +- IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); +- return -EIO; +- } +- memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); +- set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); +- *pts = (u64) ((u64) data[2] << 32) | (u64) data[1]; +- /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/ +- } +- break; ++ return ivtv_g_pts_frame(itv, pts, &frame); + } + + case VIDEO_GET_FRAME_COUNT: { +- u32 data[CX2341X_MBOX_MAX_DATA]; +- u64 *frame = arg; ++ s64 *frame = arg; ++ s64 pts; + + IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n"); + if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { +@@ -1647,71 +1648,58 @@ static int ivtv_decoder_ioctls(struct fi + } + if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) + return -EINVAL; +- +- if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { +- *frame = itv->last_dec_timing[0]; +- break; +- } +- *frame = 0; +- if (atomic_read(&itv->decoding)) { +- if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { +- IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); +- return -EIO; +- } +- memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); +- set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); +- *frame = data[0]; +- } +- break; ++ return ivtv_g_pts_frame(itv, &pts, frame); + } + + case VIDEO_PLAY: { +- struct video_command vc; ++ struct v4l2_decoder_cmd dc; + + IVTV_DEBUG_IOCTL("VIDEO_PLAY\n"); +- memset(&vc, 0, sizeof(vc)); +- vc.cmd = VIDEO_CMD_PLAY; +- return ivtv_video_command(itv, id, &vc, 0); ++ memset(&dc, 0, sizeof(dc)); ++ dc.cmd = V4L2_DEC_CMD_START; ++ return ivtv_video_command(itv, id, &dc, 0); + } + + case VIDEO_STOP: { +- struct video_command vc; ++ struct v4l2_decoder_cmd dc; + + IVTV_DEBUG_IOCTL("VIDEO_STOP\n"); +- memset(&vc, 0, sizeof(vc)); +- vc.cmd = VIDEO_CMD_STOP; +- vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY; +- return ivtv_video_command(itv, id, &vc, 0); ++ memset(&dc, 0, sizeof(dc)); ++ dc.cmd = V4L2_DEC_CMD_STOP; ++ dc.flags = V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY; ++ return ivtv_video_command(itv, id, &dc, 0); + } + + case VIDEO_FREEZE: { +- struct video_command vc; ++ struct v4l2_decoder_cmd dc; + + IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n"); +- memset(&vc, 0, sizeof(vc)); +- vc.cmd = VIDEO_CMD_FREEZE; +- return ivtv_video_command(itv, id, &vc, 0); ++ memset(&dc, 0, sizeof(dc)); ++ dc.cmd = V4L2_DEC_CMD_PAUSE; ++ return ivtv_video_command(itv, id, &dc, 0); + } + + case VIDEO_CONTINUE: { +- struct video_command vc; ++ struct v4l2_decoder_cmd dc; + + IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n"); +- memset(&vc, 0, sizeof(vc)); +- vc.cmd = VIDEO_CMD_CONTINUE; +- return ivtv_video_command(itv, id, &vc, 0); ++ memset(&dc, 0, sizeof(dc)); ++ dc.cmd = V4L2_DEC_CMD_RESUME; ++ return ivtv_video_command(itv, id, &dc, 0); + } + + case VIDEO_COMMAND: + case VIDEO_TRY_COMMAND: { +- struct video_command *vc = arg; ++ /* Note: struct v4l2_decoder_cmd has the same layout as ++ struct video_command */ ++ struct v4l2_decoder_cmd *dc = arg; + int try = (cmd == VIDEO_TRY_COMMAND); + + if (try) +- IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd); ++ IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", dc->cmd); + else +- IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd); +- return ivtv_video_command(itv, id, vc, try); ++ IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", dc->cmd); ++ return ivtv_video_command(itv, id, dc, try); + } + + case VIDEO_GET_EVENT: { +@@ -1775,17 +1763,13 @@ static int ivtv_decoder_ioctls(struct fi + IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n"); + if (iarg > AUDIO_STEREO_SWAPPED) + return -EINVAL; +- itv->audio_stereo_mode = iarg; +- ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); +- return 0; ++ return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg); + + case AUDIO_BILINGUAL_CHANNEL_SELECT: + IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); + if (iarg > AUDIO_STEREO_SWAPPED) + return -EINVAL; +- itv->audio_bilingual_mode = iarg; +- ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); +- return 0; ++ return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg); + + default: + return -EINVAL; +@@ -1800,6 +1784,7 @@ static long ivtv_default(struct file *fi + + if (!valid_prio) { + switch (cmd) { ++ case IVTV_IOC_PASSTHROUGH_MODE: + case VIDEO_PLAY: + case VIDEO_STOP: + case VIDEO_FREEZE: +@@ -1825,6 +1810,7 @@ static long ivtv_default(struct file *fi + } + + case IVTV_IOC_DMA_FRAME: ++ case IVTV_IOC_PASSTHROUGH_MODE: + case VIDEO_GET_PTS: + case VIDEO_GET_FRAME_COUNT: + case VIDEO_GET_EVENT: +@@ -1889,6 +1875,8 @@ static const struct v4l2_ioctl_ops ivtv_ + .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap, + .vidioc_encoder_cmd = ivtv_encoder_cmd, + .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd, ++ .vidioc_decoder_cmd = ivtv_decoder_cmd, ++ .vidioc_try_decoder_cmd = ivtv_try_decoder_cmd, + .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out, + .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap, + .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap, +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-streams.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-streams.c ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-streams.c +@@ -78,60 +78,73 @@ static struct { + int num_offset; + int dma, pio; + enum v4l2_buf_type buf_type; ++ u32 v4l2_caps; + const struct v4l2_file_operations *fops; + } ivtv_stream_info[] = { + { /* IVTV_ENC_STREAM_TYPE_MPG */ + "encoder MPG", + VFL_TYPE_GRABBER, 0, + PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, ++ V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | ++ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, + &ivtv_v4l2_enc_fops + }, + { /* IVTV_ENC_STREAM_TYPE_YUV */ + "encoder YUV", + VFL_TYPE_GRABBER, IVTV_V4L2_ENC_YUV_OFFSET, + PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, ++ V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | ++ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, + &ivtv_v4l2_enc_fops + }, + { /* IVTV_ENC_STREAM_TYPE_VBI */ + "encoder VBI", + VFL_TYPE_VBI, 0, + PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VBI_CAPTURE, ++ V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_TUNER | ++ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, + &ivtv_v4l2_enc_fops + }, + { /* IVTV_ENC_STREAM_TYPE_PCM */ + "encoder PCM", + VFL_TYPE_GRABBER, IVTV_V4L2_ENC_PCM_OFFSET, + PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_PRIVATE, ++ V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, + &ivtv_v4l2_enc_fops + }, + { /* IVTV_ENC_STREAM_TYPE_RAD */ + "encoder radio", + VFL_TYPE_RADIO, 0, + PCI_DMA_NONE, 1, V4L2_BUF_TYPE_PRIVATE, ++ V4L2_CAP_RADIO | V4L2_CAP_TUNER, + &ivtv_v4l2_enc_fops + }, + { /* IVTV_DEC_STREAM_TYPE_MPG */ + "decoder MPG", + VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET, + PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, ++ V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, + &ivtv_v4l2_dec_fops + }, + { /* IVTV_DEC_STREAM_TYPE_VBI */ + "decoder VBI", + VFL_TYPE_VBI, IVTV_V4L2_DEC_VBI_OFFSET, + PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_CAPTURE, ++ V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_READWRITE, + &ivtv_v4l2_enc_fops + }, + { /* IVTV_DEC_STREAM_TYPE_VOUT */ + "decoder VOUT", + VFL_TYPE_VBI, IVTV_V4L2_DEC_VOUT_OFFSET, + PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_OUTPUT, ++ V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, + &ivtv_v4l2_dec_fops + }, + { /* IVTV_DEC_STREAM_TYPE_YUV */ + "decoder YUV", + VFL_TYPE_GRABBER, IVTV_V4L2_DEC_YUV_OFFSET, + PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, ++ V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, + &ivtv_v4l2_dec_fops + } + }; +@@ -149,6 +162,7 @@ static void ivtv_stream_init(struct ivtv + s->itv = itv; + s->type = type; + s->name = ivtv_stream_info[type].name; ++ s->caps = ivtv_stream_info[type].v4l2_caps; + + if (ivtv_stream_info[type].pio) + s->dma = PCI_DMA_NONE; +@@ -209,8 +223,8 @@ static int ivtv_prep_dev(struct ivtv *it + + s->vdev->num = num; + s->vdev->v4l2_dev = &itv->v4l2_dev; +- s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler; + s->vdev->fops = ivtv_stream_info[type].fops; ++ s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler; + s->vdev->release = video_device_release; + s->vdev->tvnorms = V4L2_STD_ALL; + s->vdev->lock = &itv->serialize_lock; +@@ -891,7 +905,7 @@ int ivtv_stop_v4l2_decode_stream(struct + IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags); + + /* Stop Decoder */ +- if (!(flags & VIDEO_CMD_STOP_IMMEDIATELY) || pts) { ++ if (!(flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) || pts) { + u32 tmp = 0; + + /* Wait until the decoder is no longer running */ +@@ -911,7 +925,7 @@ int ivtv_stop_v4l2_decode_stream(struct + break; + } + } +- ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & VIDEO_CMD_STOP_TO_BLACK, 0, 0); ++ ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & V4L2_DEC_CMD_STOP_TO_BLACK, 0, 0); + + /* turn off notification of dual/stereo mode change */ + ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_DEC_AUD_MODE_CHG, -1); +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/it913x.c ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c +@@ -64,6 +64,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr + struct it913x_state { + u8 id; + struct ite_config it913x_config; ++ u8 pid_filter_onoff; + }; + + struct ite_config it913x_config; +@@ -259,15 +260,16 @@ static u32 it913x_query(struct usb_devic + + static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) + { ++ struct it913x_state *st = adap->dev->priv; + struct usb_device *udev = adap->dev->udev; + int ret; + u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; + +- if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) +- return -EAGAIN; ++ mutex_lock(&adap->dev->i2c_mutex); ++ + deb_info(1, "PID_C (%02x)", onoff); + +- ret = it913x_wr_reg(udev, pro, PID_EN, onoff); ++ ret = it913x_wr_reg(udev, pro, PID_EN, st->pid_filter_onoff); + + mutex_unlock(&adap->dev->i2c_mutex); + return ret; +@@ -276,12 +278,13 @@ static int it913x_pid_filter_ctrl(struct + static int it913x_pid_filter(struct dvb_usb_adapter *adap, + int index, u16 pid, int onoff) + { ++ struct it913x_state *st = adap->dev->priv; + struct usb_device *udev = adap->dev->udev; + int ret; + u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; + +- if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) +- return -EAGAIN; ++ mutex_lock(&adap->dev->i2c_mutex); ++ + deb_info(1, "PID_F (%02x)", onoff); + + ret = it913x_wr_reg(udev, pro, PID_LSB, (u8)(pid & 0xff)); +@@ -292,6 +295,13 @@ static int it913x_pid_filter(struct dvb_ + + ret |= it913x_wr_reg(udev, pro, PID_INX, (u8)(index & 0x1f)); + ++ if (udev->speed == USB_SPEED_HIGH && pid == 0x2000) { ++ ret |= it913x_wr_reg(udev, pro, PID_EN, !onoff); ++ st->pid_filter_onoff = !onoff; ++ } else ++ st->pid_filter_onoff = ++ adap->fe_adap[adap->active_fe].pid_filtering; ++ + mutex_unlock(&adap->dev->i2c_mutex); + return 0; + } +@@ -316,8 +326,8 @@ static int it913x_i2c_xfer(struct i2c_ad + int ret; + u32 reg; + u8 pro; +- if (mutex_lock_interruptible(&d->i2c_mutex) < 0) +- return -EAGAIN; ++ ++ mutex_lock(&d->i2c_mutex); + + debug_data_snipet(1, "Message out", msg[0].buf); + deb_info(2, "num of messages %d address %02x", num, msg[0].addr); +@@ -358,8 +368,7 @@ static int it913x_rc_query(struct dvb_us + int ret; + u32 key; + /* Avoid conflict with frontends*/ +- if (mutex_lock_interruptible(&d->i2c_mutex) < 0) +- return -EAGAIN; ++ mutex_lock(&d->i2c_mutex); + + ret = it913x_io(d->udev, READ_LONG, PRO_LINK, CMD_IR_GET, + 0, 0, &ibuf[0], sizeof(ibuf)); +@@ -388,19 +397,12 @@ static int ite_firmware_select(struct us + { + int sw; + /* auto switch */ +- if (le16_to_cpu(udev->descriptor.idProduct) == +- USB_PID_ITETECH_IT9135) +- sw = IT9135_V1_FW; +- else if (le16_to_cpu(udev->descriptor.idProduct) == +- USB_PID_ITETECH_IT9135_9005) ++ if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_KWORLD_2) ++ sw = IT9137_FW; ++ else if (it913x_config.chip_ver == 1) + sw = IT9135_V1_FW; +- else if (le16_to_cpu(udev->descriptor.idProduct) == +- USB_PID_ITETECH_IT9135_9006) { ++ else + sw = IT9135_V2_FW; +- if (it913x_config.tuner_id_0 == 0) +- it913x_config.tuner_id_0 = IT9135_60; +- } else +- sw = IT9137_FW; + + /* force switch */ + if (dvb_usb_it913x_firmware != IT9135_AUTO) +@@ -410,41 +412,103 @@ static int ite_firmware_select(struct us + case IT9135_V1_FW: + it913x_config.firmware_ver = 1; + it913x_config.adc_x2 = 1; ++ it913x_config.read_slevel = false; + props->firmware = fw_it9135_v1; + break; + case IT9135_V2_FW: + it913x_config.firmware_ver = 1; + it913x_config.adc_x2 = 1; ++ it913x_config.read_slevel = false; + props->firmware = fw_it9135_v2; ++ switch (it913x_config.tuner_id_0) { ++ case IT9135_61: ++ case IT9135_62: ++ break; ++ default: ++ info("Unknown tuner ID applying default 0x60"); ++ case IT9135_60: ++ it913x_config.tuner_id_0 = IT9135_60; ++ } + break; + case IT9137_FW: + default: + it913x_config.firmware_ver = 0; + it913x_config.adc_x2 = 0; ++ it913x_config.read_slevel = true; + props->firmware = fw_it9137; + } + + return 0; + } + ++static void it913x_select_remote(struct usb_device *udev, ++ struct dvb_usb_device_properties *props) ++{ ++ switch (le16_to_cpu(udev->descriptor.idProduct)) { ++ case USB_PID_ITETECH_IT9135_9005: ++ props->rc.core.rc_codes = RC_MAP_IT913X_V2; ++ return; ++ default: ++ props->rc.core.rc_codes = RC_MAP_IT913X_V1; ++ } ++ return; ++} ++ + #define TS_MPEG_PKT_SIZE 188 + #define EP_LOW 21 + #define TS_BUFFER_SIZE_PID (EP_LOW*TS_MPEG_PKT_SIZE) + #define EP_HIGH 348 + #define TS_BUFFER_SIZE_MAX (EP_HIGH*TS_MPEG_PKT_SIZE) + +-static int it913x_identify_state(struct usb_device *udev, +- struct dvb_usb_device_properties *props, +- struct dvb_usb_device_description **desc, +- int *cold) ++static int it913x_select_config(struct usb_device *udev, ++ struct dvb_usb_device_properties *props) + { +- int ret = 0, firm_no; +- u8 reg, remote; ++ int ret = 0, reg; ++ bool proprietary_ir = false; + +- firm_no = it913x_return_status(udev); ++ if (it913x_config.chip_ver == 0x02 ++ && it913x_config.chip_type == 0x9135) ++ reg = it913x_read_reg(udev, 0x461d); ++ else ++ reg = it913x_read_reg(udev, 0x461b); + +- /* checnk for dual mode */ +- it913x_config.dual_mode = it913x_read_reg(udev, 0x49c5); ++ if (reg < 0) ++ return reg; ++ ++ if (reg == 0) { ++ it913x_config.dual_mode = 0; ++ it913x_config.tuner_id_0 = IT9135_38; ++ proprietary_ir = true; ++ } else { ++ /* TS mode */ ++ reg = it913x_read_reg(udev, 0x49c5); ++ if (reg < 0) ++ return reg; ++ it913x_config.dual_mode = reg; ++ ++ /* IR mode type */ ++ reg = it913x_read_reg(udev, 0x49ac); ++ if (reg < 0) ++ return reg; ++ if (reg == 5) { ++ info("Remote propriety (raw) mode"); ++ proprietary_ir = true; ++ } else if (reg == 1) { ++ info("Remote HID mode NOT SUPPORTED"); ++ proprietary_ir = false; ++ props->rc.core.rc_codes = NULL; ++ } else ++ props->rc.core.rc_codes = NULL; ++ ++ /* Tuner_id */ ++ reg = it913x_read_reg(udev, 0x49d0); ++ if (reg < 0) ++ return reg; ++ it913x_config.tuner_id_0 = reg; ++ } ++ ++ if (proprietary_ir) ++ it913x_select_remote(udev, props); + + if (udev->speed != USB_SPEED_HIGH) { + props->adapter[0].fe[0].pid_filter_count = 5; +@@ -459,17 +523,6 @@ static int it913x_identify_state(struct + if(props->adapter[0].fe[0].pid_filter_count == 5) + props->adapter[0].fe[0].pid_filter_count = 31; + +- /* TODO different remotes */ +- remote = it913x_read_reg(udev, 0x49ac); /* Remote */ +- if (remote == 0) +- props->rc.core.rc_codes = NULL; +- +- /* TODO at the moment tuner_id is always assigned to 0x38 */ +- it913x_config.tuner_id_0 = it913x_read_reg(udev, 0x49d0); +- +- info("Dual mode=%x Remote=%x Tuner Type=%x", it913x_config.dual_mode +- , remote, it913x_config.tuner_id_0); +- + /* Select Stream Buffer Size and pid filter option*/ + if (pid_filter) { + props->adapter[0].fe[0].stream.u.bulk.buffersize = +@@ -490,8 +543,29 @@ static int it913x_identify_state(struct + } else + props->num_adapters = 1; + ++ info("Dual mode=%x Tuner Type=%x", it913x_config.dual_mode, ++ it913x_config.tuner_id_0); ++ + ret = ite_firmware_select(udev, props); + ++ return ret; ++} ++ ++static int it913x_identify_state(struct usb_device *udev, ++ struct dvb_usb_device_properties *props, ++ struct dvb_usb_device_description **desc, ++ int *cold) ++{ ++ int ret = 0, firm_no; ++ u8 reg; ++ ++ firm_no = it913x_return_status(udev); ++ ++ /* Read and select config */ ++ ret = it913x_select_config(udev, props); ++ if (ret < 0) ++ return ret; ++ + if (firm_no > 0) { + *cold = 0; + return 0; +@@ -538,18 +612,22 @@ static int it913x_identify_state(struct + + static int it913x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) + { ++ struct it913x_state *st = adap->dev->priv; + int ret = 0; + u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; + +- if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) +- return -EAGAIN; + deb_info(1, "STM (%02x)", onoff); + +- if (!onoff) ++ if (!onoff) { ++ mutex_lock(&adap->dev->i2c_mutex); ++ + ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1); + ++ mutex_unlock(&adap->dev->i2c_mutex); ++ st->pid_filter_onoff = ++ adap->fe_adap[adap->active_fe].pid_filtering; + +- mutex_unlock(&adap->dev->i2c_mutex); ++ } + + return ret; + } +@@ -789,7 +867,7 @@ static struct dvb_usb_device_properties + .rc_query = it913x_rc_query, + .rc_interval = IT913X_POLL, + .allowed_protos = RC_TYPE_NEC, +- .rc_codes = RC_MAP_MSI_DIGIVOX_III, ++ .rc_codes = RC_MAP_IT913X_V1, + }, + .i2c_algo = &it913x_i2c_algo, + .num_device_descs = 5, +@@ -823,5 +901,5 @@ module_usb_driver(it913x_driver); + + MODULE_AUTHOR("Malcolm Priestley "); + MODULE_DESCRIPTION("it913x USB 2 Driver"); +-MODULE_VERSION("1.22"); ++MODULE_VERSION("1.27"); + MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/base/driver.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/base/driver.c ++++ linux-3.3.x86_64/drivers/base/driver.c +@@ -234,7 +234,6 @@ int driver_register(struct device_driver + + other = driver_find(drv->name, drv->bus); + if (other) { +- put_driver(other); + printk(KERN_ERR "Error: Driver '%s' is already registered, " + "aborting...\n", drv->name); + return -EBUSY; +@@ -275,7 +274,9 @@ EXPORT_SYMBOL_GPL(driver_unregister); + * Call kset_find_obj() to iterate over list of drivers on + * a bus to find driver by name. Return driver if found. + * +- * Note that kset_find_obj increments driver's reference count. ++ * This routine provides no locking to prevent the driver it returns ++ * from being unregistered or unloaded while the caller is using it. ++ * The caller is responsible for preventing this. + */ + struct device_driver *driver_find(const char *name, struct bus_type *bus) + { +@@ -283,6 +284,8 @@ struct device_driver *driver_find(const + struct driver_private *priv; + + if (k) { ++ /* Drop reference added by kset_find_obj() */ ++ kobject_put(k); + priv = to_driver(k); + return priv->driver; + } +Index: linux-3.3.x86_64/drivers/input/gameport/gameport.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/input/gameport/gameport.c ++++ linux-3.3.x86_64/drivers/input/gameport/gameport.c +@@ -449,7 +449,6 @@ static ssize_t gameport_rebind_driver(st + } else if ((drv = driver_find(buf, &gameport_bus)) != NULL) { + gameport_disconnect_port(gameport); + error = gameport_bind_driver(gameport, to_gameport_driver(drv)); +- put_driver(drv); + } else { + error = -EINVAL; + } +Index: linux-3.3.x86_64/drivers/input/serio/serio.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/input/serio/serio.c ++++ linux-3.3.x86_64/drivers/input/serio/serio.c +@@ -441,7 +441,6 @@ static ssize_t serio_rebind_driver(struc + } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { + serio_disconnect_port(serio); + error = serio_bind_driver(serio, to_serio_driver(drv)); +- put_driver(drv); + serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); + } else { + error = -EINVAL; +Index: linux-3.3.x86_64/drivers/media/video/cx18/cx18-alsa-main.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx18/cx18-alsa-main.c ++++ linux-3.3.x86_64/drivers/media/video/cx18/cx18-alsa-main.c +@@ -285,7 +285,6 @@ static void __exit cx18_alsa_exit(void) + + drv = driver_find("cx18", &pci_bus_type); + ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback); +- put_driver(drv); + + cx18_ext_init = NULL; + printk(KERN_INFO "cx18-alsa: module unload complete\n"); +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtvfb.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtvfb.c ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtvfb.c +@@ -1293,7 +1293,6 @@ static int __init ivtvfb_init(void) + + drv = driver_find("ivtv", &pci_bus_type); + err = driver_for_each_device(drv, NULL, ®istered, ivtvfb_callback_init); +- put_driver(drv); + if (!registered) { + printk(KERN_ERR "ivtvfb: no cards found\n"); + return -ENODEV; +@@ -1310,7 +1309,6 @@ static void ivtvfb_cleanup(void) + + drv = driver_find("ivtv", &pci_bus_type); + err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup); +- put_driver(drv); + } + + module_init(ivtvfb_init); +Index: linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-mdevice.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-fimc/fimc-mdevice.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-mdevice.c +@@ -344,16 +344,13 @@ static int fimc_md_register_platform_ent + return -ENODEV; + ret = driver_for_each_device(driver, NULL, fmd, + fimc_register_callback); +- put_driver(driver); + if (ret) + return ret; + + driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type); +- if (driver) { ++ if (driver) + ret = driver_for_each_device(driver, NULL, fmd, + csis_register_callback); +- put_driver(driver); +- } + return ret; + } + +@@ -753,7 +750,7 @@ static int __devinit fimc_md_probe(struc + struct fimc_md *fmd; + int ret; + +- fmd = kzalloc(sizeof(struct fimc_md), GFP_KERNEL); ++ fmd = devm_kzalloc(&pdev->dev, sizeof(*fmd), GFP_KERNEL); + if (!fmd) + return -ENOMEM; + +@@ -774,7 +771,7 @@ static int __devinit fimc_md_probe(struc + ret = v4l2_device_register(&pdev->dev, &fmd->v4l2_dev); + if (ret < 0) { + v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret); +- goto err1; ++ return ret; + } + ret = media_device_register(&fmd->media_dev); + if (ret < 0) { +@@ -816,8 +813,6 @@ err3: + fimc_md_unregister_entities(fmd); + err2: + v4l2_device_unregister(&fmd->v4l2_dev); +-err1: +- kfree(fmd); + return ret; + } + +@@ -831,7 +826,6 @@ static int __devexit fimc_md_remove(stru + fimc_md_unregister_entities(fmd); + media_device_unregister(&fmd->media_dev); + fimc_md_put_clocks(fmd); +- kfree(fmd); + return 0; + } + +Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/mixer_video.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/mixer_video.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-tv/mixer_video.c +@@ -58,7 +58,6 @@ static struct v4l2_subdev *find_and_regi + } + + done: +- put_driver(drv); + return sd; + } + +Index: linux-3.3.x86_64/drivers/s390/net/smsgiucv_app.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/s390/net/smsgiucv_app.c ++++ linux-3.3.x86_64/drivers/s390/net/smsgiucv_app.c +@@ -168,7 +168,7 @@ static int __init smsgiucv_app_init(void + rc = dev_set_name(smsg_app_dev, KMSG_COMPONENT); + if (rc) { + kfree(smsg_app_dev); +- goto fail_put_driver; ++ goto fail; + } + smsg_app_dev->bus = &iucv_bus; + smsg_app_dev->parent = iucv_root; +@@ -177,7 +177,7 @@ static int __init smsgiucv_app_init(void + rc = device_register(smsg_app_dev); + if (rc) { + put_device(smsg_app_dev); +- goto fail_put_driver; ++ goto fail; + } + + /* convert sender to uppercase characters */ +@@ -191,12 +191,11 @@ static int __init smsgiucv_app_init(void + rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback); + if (rc) { + device_unregister(smsg_app_dev); +- goto fail_put_driver; ++ goto fail; + } + + rc = 0; +-fail_put_driver: +- put_driver(smsgiucv_drv); ++fail: + return rc; + } + module_init(smsgiucv_app_init); +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/anysee.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/anysee.c ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/anysee.c +@@ -58,7 +58,7 @@ static int anysee_ctrl_msg(struct dvb_us + u8 *rbuf, u8 rlen) + { + struct anysee_state *state = d->priv; +- int act_len, ret; ++ int act_len, ret, i; + u8 buf[64]; + + memcpy(&buf[0], sbuf, slen); +@@ -73,26 +73,52 @@ static int anysee_ctrl_msg(struct dvb_us + /* We need receive one message more after dvb_usb_generic_rw due + to weird transaction flow, which is 1 x send + 2 x receive. */ + ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0); +- if (!ret) { ++ if (ret) ++ goto error_unlock; ++ ++ /* TODO FIXME: dvb_usb_generic_rw() fails rarely with error code -32 ++ * (EPIPE, Broken pipe). Function supports currently msleep() as a ++ * parameter but I would not like to use it, since according to ++ * Documentation/timers/timers-howto.txt it should not be used such ++ * short, under < 20ms, sleeps. Repeating failed message would be ++ * better choice as not to add unwanted delays... ++ * Fixing that correctly is one of those or both; ++ * 1) use repeat if possible ++ * 2) add suitable delay ++ */ ++ ++ /* get answer, retry few times if error returned */ ++ for (i = 0; i < 3; i++) { + /* receive 2nd answer */ + ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, + d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf), + &act_len, 2000); +- if (ret) +- err("%s: recv bulk message failed: %d", __func__, ret); +- else { ++ ++ if (ret) { ++ deb_info("%s: recv bulk message failed: %d", ++ __func__, ret); ++ } else { + deb_xfer("<<< "); + debug_dump(buf, rlen, deb_xfer); + + if (buf[63] != 0x4f) + deb_info("%s: cmd failed\n", __func__); ++ ++ break; + } + } + ++ if (ret) { ++ /* all retries failed, it is fatal */ ++ err("%s: recv bulk message failed: %d", __func__, ret); ++ goto error_unlock; ++ } ++ + /* read request, copy returned data to return buf */ +- if (!ret && rbuf && rlen) ++ if (rbuf && rlen) + memcpy(rbuf, buf, rlen); + ++error_unlock: + mutex_unlock(&anysee_usb_mutex); + + return ret; +Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/hdmi_drv.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/hdmi_drv.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-tv/hdmi_drv.c +@@ -30,6 +30,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -66,6 +67,8 @@ struct hdmi_device { + struct v4l2_device v4l2_dev; + /** subdev of HDMIPHY interface */ + struct v4l2_subdev *phy_sd; ++ /** subdev of MHL interface */ ++ struct v4l2_subdev *mhl_sd; + /** configuration of current graphic mode */ + const struct hdmi_preset_conf *cur_conf; + /** current preset */ +@@ -74,10 +77,6 @@ struct hdmi_device { + struct hdmi_resources res; + }; + +-struct hdmi_driver_data { +- int hdmiphy_bus; +-}; +- + struct hdmi_tg_regs { + u8 cmd; + u8 h_fsz_l; +@@ -129,23 +128,11 @@ struct hdmi_preset_conf { + struct v4l2_mbus_framefmt mbus_fmt; + }; + +-/* I2C module and id for HDMIPHY */ +-static struct i2c_board_info hdmiphy_info = { +- I2C_BOARD_INFO("hdmiphy", 0x38), +-}; +- +-static struct hdmi_driver_data hdmi_driver_data[] = { +- { .hdmiphy_bus = 3 }, +- { .hdmiphy_bus = 8 }, +-}; +- + static struct platform_device_id hdmi_driver_types[] = { + { + .name = "s5pv210-hdmi", +- .driver_data = (unsigned long)&hdmi_driver_data[0], + }, { + .name = "exynos4-hdmi", +- .driver_data = (unsigned long)&hdmi_driver_data[1], + }, { + /* end node */ + } +@@ -587,7 +574,15 @@ static int hdmi_streamon(struct hdmi_dev + if (tries == 0) { + dev_err(dev, "hdmiphy's pll could not reach steady state.\n"); + v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); +- hdmi_dumpregs(hdev, "s_stream"); ++ hdmi_dumpregs(hdev, "hdmiphy - s_stream"); ++ return -EIO; ++ } ++ ++ /* starting MHL */ ++ ret = v4l2_subdev_call(hdev->mhl_sd, video, s_stream, 1); ++ if (hdev->mhl_sd && ret) { ++ v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); ++ hdmi_dumpregs(hdev, "mhl - s_stream"); + return -EIO; + } + +@@ -618,6 +613,7 @@ static int hdmi_streamoff(struct hdmi_de + clk_set_parent(res->sclk_hdmi, res->sclk_pixel); + clk_enable(res->sclk_hdmi); + ++ v4l2_subdev_call(hdev->mhl_sd, video, s_stream, 0); + v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); + + hdmi_dumpregs(hdev, "streamoff"); +@@ -739,6 +735,7 @@ static int hdmi_runtime_suspend(struct d + struct hdmi_device *hdev = sd_to_hdmi_dev(sd); + + dev_dbg(dev, "%s\n", __func__); ++ v4l2_subdev_call(hdev->mhl_sd, core, s_power, 0); + hdmi_resource_poweroff(&hdev->res); + return 0; + } +@@ -757,6 +754,11 @@ static int hdmi_runtime_resume(struct de + if (ret) + goto fail; + ++ /* starting MHL */ ++ ret = v4l2_subdev_call(hdev->mhl_sd, core, s_power, 1); ++ if (hdev->mhl_sd && ret) ++ goto fail; ++ + dev_dbg(dev, "poweron succeed\n"); + + return 0; +@@ -867,15 +869,21 @@ static int __devinit hdmi_probe(struct p + { + struct device *dev = &pdev->dev; + struct resource *res; +- struct i2c_adapter *phy_adapter; ++ struct i2c_adapter *adapter; + struct v4l2_subdev *sd; + struct hdmi_device *hdmi_dev = NULL; +- struct hdmi_driver_data *drv_data; ++ struct s5p_hdmi_platform_data *pdata = dev->platform_data; + int ret; + + dev_dbg(dev, "probe start\n"); + +- hdmi_dev = kzalloc(sizeof(*hdmi_dev), GFP_KERNEL); ++ if (!pdata) { ++ dev_err(dev, "platform data is missing\n"); ++ ret = -ENODEV; ++ goto fail; ++ } ++ ++ hdmi_dev = devm_kzalloc(&pdev->dev, sizeof(*hdmi_dev), GFP_KERNEL); + if (!hdmi_dev) { + dev_err(dev, "out of memory\n"); + ret = -ENOMEM; +@@ -886,7 +894,7 @@ static int __devinit hdmi_probe(struct p + + ret = hdmi_resources_init(hdmi_dev); + if (ret) +- goto fail_hdev; ++ goto fail; + + /* mapping HDMI registers */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +@@ -896,24 +904,26 @@ static int __devinit hdmi_probe(struct p + goto fail_init; + } + +- hdmi_dev->regs = ioremap(res->start, resource_size(res)); ++ hdmi_dev->regs = devm_ioremap(&pdev->dev, res->start, ++ resource_size(res)); + if (hdmi_dev->regs == NULL) { + dev_err(dev, "register mapping failed.\n"); + ret = -ENXIO; +- goto fail_hdev; ++ goto fail_init; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res == NULL) { + dev_err(dev, "get interrupt resource failed.\n"); + ret = -ENXIO; +- goto fail_regs; ++ goto fail_init; + } + +- ret = request_irq(res->start, hdmi_irq_handler, 0, "hdmi", hdmi_dev); ++ ret = devm_request_irq(&pdev->dev, res->start, hdmi_irq_handler, 0, ++ "hdmi", hdmi_dev); + if (ret) { + dev_err(dev, "request interrupt failed.\n"); +- goto fail_regs; ++ goto fail_init; + } + hdmi_dev->irq = res->start; + +@@ -924,28 +934,54 @@ static int __devinit hdmi_probe(struct p + ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev); + if (ret) { + dev_err(dev, "could not register v4l2 device.\n"); +- goto fail_irq; ++ goto fail_init; + } + +- drv_data = (struct hdmi_driver_data *) +- platform_get_device_id(pdev)->driver_data; +- phy_adapter = i2c_get_adapter(drv_data->hdmiphy_bus); +- if (phy_adapter == NULL) { +- dev_err(dev, "adapter request failed\n"); ++ /* testing if hdmiphy info is present */ ++ if (!pdata->hdmiphy_info) { ++ dev_err(dev, "hdmiphy info is missing in platform data\n"); ++ ret = -ENXIO; ++ goto fail_vdev; ++ } ++ ++ adapter = i2c_get_adapter(pdata->hdmiphy_bus); ++ if (adapter == NULL) { ++ dev_err(dev, "hdmiphy adapter request failed\n"); + ret = -ENXIO; + goto fail_vdev; + } + + hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev, +- phy_adapter, &hdmiphy_info, NULL); ++ adapter, pdata->hdmiphy_info, NULL); + /* on failure or not adapter is no longer useful */ +- i2c_put_adapter(phy_adapter); ++ i2c_put_adapter(adapter); + if (hdmi_dev->phy_sd == NULL) { + dev_err(dev, "missing subdev for hdmiphy\n"); + ret = -ENODEV; + goto fail_vdev; + } + ++ /* initialization of MHL interface if present */ ++ if (pdata->mhl_info) { ++ adapter = i2c_get_adapter(pdata->mhl_bus); ++ if (adapter == NULL) { ++ dev_err(dev, "MHL adapter request failed\n"); ++ ret = -ENXIO; ++ goto fail_vdev; ++ } ++ ++ hdmi_dev->mhl_sd = v4l2_i2c_new_subdev_board( ++ &hdmi_dev->v4l2_dev, adapter, ++ pdata->mhl_info, NULL); ++ /* on failure or not adapter is no longer useful */ ++ i2c_put_adapter(adapter); ++ if (hdmi_dev->mhl_sd == NULL) { ++ dev_err(dev, "missing subdev for MHL\n"); ++ ret = -ENODEV; ++ goto fail_vdev; ++ } ++ } ++ + clk_enable(hdmi_dev->res.hdmi); + + pm_runtime_enable(dev); +@@ -969,18 +1005,9 @@ static int __devinit hdmi_probe(struct p + fail_vdev: + v4l2_device_unregister(&hdmi_dev->v4l2_dev); + +-fail_irq: +- free_irq(hdmi_dev->irq, hdmi_dev); +- +-fail_regs: +- iounmap(hdmi_dev->regs); +- + fail_init: + hdmi_resources_cleanup(hdmi_dev); + +-fail_hdev: +- kfree(hdmi_dev); +- + fail: + dev_err(dev, "probe failed\n"); + return ret; +@@ -996,8 +1023,6 @@ static int __devexit hdmi_remove(struct + clk_disable(hdmi_dev->res.hdmi); + v4l2_device_unregister(&hdmi_dev->v4l2_dev); + disable_irq(hdmi_dev->irq); +- free_irq(hdmi_dev->irq, hdmi_dev); +- iounmap(hdmi_dev->regs); + hdmi_resources_cleanup(hdmi_dev); + kfree(hdmi_dev); + dev_info(dev, "remove sucessful\n"); +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/lmedm04.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/lmedm04.c ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/lmedm04.c +@@ -77,6 +77,7 @@ + #include "stv0299.h" + #include "dvb-pll.h" + #include "z0194a.h" ++#include "m88rs2000.h" + + + +@@ -104,7 +105,7 @@ MODULE_PARM_DESC(firmware, "set default + + static int pid_filter; + module_param_named(pid, pid_filter, int, 0644); +-MODULE_PARM_DESC(pid, "set default 0=on 1=off"); ++MODULE_PARM_DESC(pid, "set default 0=default 1=off 2=on"); + + + DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); +@@ -113,6 +114,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr + #define TUNER_LG 0x1 + #define TUNER_S7395 0x2 + #define TUNER_S0194 0x3 ++#define TUNER_RS2000 0x4 + + struct lme2510_state { + u8 id; +@@ -121,6 +123,8 @@ struct lme2510_state { + u8 signal_level; + u8 signal_sn; + u8 time_key; ++ u8 last_key; ++ u8 key_timeout; + u8 i2c_talk_onoff; + u8 i2c_gate; + u8 i2c_tuner_gate_w; +@@ -128,6 +132,7 @@ struct lme2510_state { + u8 i2c_tuner_addr; + u8 stream_on; + u8 pid_size; ++ u8 pid_off; + void *buffer; + struct urb *lme_urb; + void *usb_buffer; +@@ -178,14 +183,8 @@ static int lme2510_usb_talk(struct dvb_u + /* the read/write capped at 64 */ + memcpy(buff, wbuf, (wlen < 64) ? wlen : 64); + +- ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01)); +- + ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01); + +- msleep(10); +- +- ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01)); +- + ret |= lme2510_bulk_read(d->udev, buff, (rlen < 64) ? + rlen : 64 , 0x01); + +@@ -199,9 +198,14 @@ static int lme2510_usb_talk(struct dvb_u + + static int lme2510_stream_restart(struct dvb_usb_device *d) + { +- static u8 stream_on[] = LME_ST_ON_W; ++ struct lme2510_state *st = d->priv; ++ u8 all_pids[] = LME_ALL_PIDS; ++ u8 stream_on[] = LME_ST_ON_W; + int ret; +- u8 rbuff[10]; ++ u8 rbuff[1]; ++ if (st->pid_off) ++ ret = lme2510_usb_talk(d, all_pids, sizeof(all_pids), ++ rbuff, sizeof(rbuff)); + /*Restart Stream Command*/ + ret = lme2510_usb_talk(d, stream_on, sizeof(stream_on), + rbuff, sizeof(rbuff)); +@@ -308,6 +312,14 @@ static void lme2510_int_response(struct + ((ibuf[2] & 0x01) << 0x03); + } + break; ++ case TUNER_RS2000: ++ if (ibuf[2] > 0) ++ st->signal_lock = 0xff; ++ else ++ st->signal_lock = 0xf0; ++ st->signal_level = ibuf[4]; ++ st->signal_sn = ibuf[5]; ++ st->time_key = ibuf[7]; + default: + break; + } +@@ -359,19 +371,20 @@ static int lme2510_int_read(struct dvb_u + static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) + { + struct lme2510_state *st = adap->dev->priv; +- static u8 clear_pid_reg[] = LME_CLEAR_PID; ++ static u8 clear_pid_reg[] = LME_ALL_PIDS; + static u8 rbuf[1]; + int ret; + + deb_info(1, "PID Clearing Filter"); + +- ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); +- if (ret < 0) +- return -EAGAIN; ++ mutex_lock(&adap->dev->i2c_mutex); + +- if (!onoff) ++ if (!onoff) { + ret |= lme2510_usb_talk(adap->dev, clear_pid_reg, + sizeof(clear_pid_reg), rbuf, sizeof(rbuf)); ++ st->pid_off = true; ++ } else ++ st->pid_off = false; + + st->pid_size = 0; + +@@ -389,11 +402,9 @@ static int lme2510_pid_filter(struct dvb + pid, index, onoff); + + if (onoff) { +- ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); +- if (ret < 0) +- return -EAGAIN; +- ret |= lme2510_enable_pid(adap->dev, index, pid); +- mutex_unlock(&adap->dev->i2c_mutex); ++ mutex_lock(&adap->dev->i2c_mutex); ++ ret |= lme2510_enable_pid(adap->dev, index, pid); ++ mutex_unlock(&adap->dev->i2c_mutex); + } + + +@@ -425,9 +436,6 @@ static int lme2510_msg(struct dvb_usb_de + int ret = 0; + struct lme2510_state *st = d->priv; + +- if (mutex_lock_interruptible(&d->i2c_mutex) < 0) +- return -EAGAIN; +- + if (st->i2c_talk_onoff == 1) { + + ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); +@@ -456,8 +464,6 @@ static int lme2510_msg(struct dvb_usb_de + st->i2c_talk_onoff = 0; + } + } +- if ((wbuf[3] != 0x6) & (wbuf[3] != 0x5)) +- msleep(5); + } + break; + case TUNER_S0194: +@@ -472,10 +478,12 @@ static int lme2510_msg(struct dvb_usb_de + } + } + break; ++ case TUNER_RS2000: + default: + break; + } + } else { ++ /* TODO rewrite this section */ + switch (st->tuner_config) { + case TUNER_LG: + switch (wbuf[3]) { +@@ -559,6 +567,24 @@ static int lme2510_msg(struct dvb_usb_de + break; + } + break; ++ case TUNER_RS2000: ++ switch (wbuf[3]) { ++ case 0x8c: ++ rbuf[0] = 0x55; ++ rbuf[1] = 0xff; ++ if (st->last_key == st->time_key) { ++ st->key_timeout++; ++ if (st->key_timeout > 5) ++ rbuf[1] = 0; ++ } else ++ st->key_timeout = 0; ++ st->last_key = st->time_key; ++ break; ++ default: ++ lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); ++ st->i2c_talk_onoff = 1; ++ break; ++ } + default: + break; + } +@@ -568,8 +594,6 @@ static int lme2510_msg(struct dvb_usb_de + + } + +- mutex_unlock(&d->i2c_mutex); +- + return ret; + } + +@@ -584,6 +608,8 @@ static int lme2510_i2c_xfer(struct i2c_a + u16 len; + u8 gate = st->i2c_gate; + ++ mutex_lock(&d->i2c_mutex); ++ + if (gate == 0) + gate = 5; + +@@ -622,6 +648,7 @@ static int lme2510_i2c_xfer(struct i2c_a + + if (lme2510_msg(d, obuf, len, ibuf, 64) < 0) { + deb_info(1, "i2c transfer failed."); ++ mutex_unlock(&d->i2c_mutex); + return -EAGAIN; + } + +@@ -634,6 +661,8 @@ static int lme2510_i2c_xfer(struct i2c_a + } + } + } ++ ++ mutex_unlock(&d->i2c_mutex); + return i; + } + +@@ -653,7 +682,7 @@ static int lme2510_identify_state(struct + struct dvb_usb_device_description **desc, + int *cold) + { +- if (pid_filter > 0) ++ if (pid_filter != 2) + props->adapter[0].fe[0].caps &= + ~DVB_USB_ADAP_NEED_PID_FILTERING; + *cold = 0; +@@ -663,7 +692,7 @@ static int lme2510_identify_state(struct + static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) + { + struct lme2510_state *st = adap->dev->priv; +- static u8 clear_reg_3[] = LME_CLEAR_PID; ++ static u8 clear_reg_3[] = LME_ALL_PIDS; + static u8 rbuf[1]; + int ret = 0, rlen = sizeof(rbuf); + +@@ -675,8 +704,7 @@ static int lme2510_streaming_ctrl(struct + else { + deb_info(1, "STM Steam Off"); + /* mutex is here only to avoid collision with I2C */ +- if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) +- return -EAGAIN; ++ mutex_lock(&adap->dev->i2c_mutex); + + ret = lme2510_usb_talk(adap->dev, clear_reg_3, + sizeof(clear_reg_3), rbuf, rlen); +@@ -781,16 +809,18 @@ static int lme_firmware_switch(struct us + const char fw_c_s7395[] = "dvb-usb-lme2510c-s7395.fw"; + const char fw_c_lg[] = "dvb-usb-lme2510c-lg.fw"; + const char fw_c_s0194[] = "dvb-usb-lme2510c-s0194.fw"; ++ const char fw_c_rs2000[] = "dvb-usb-lme2510c-rs2000.fw"; + const char fw_lg[] = "dvb-usb-lme2510-lg.fw"; + const char fw_s0194[] = "dvb-usb-lme2510-s0194.fw"; + const char *fw_lme; +- int ret, cold_fw; ++ int ret = 0, cold_fw; + + cold = (cold > 0) ? (cold & 1) : 0; + + cold_fw = !cold; + +- if (le16_to_cpu(udev->descriptor.idProduct) == 0x1122) { ++ switch (le16_to_cpu(udev->descriptor.idProduct)) { ++ case 0x1122: + switch (dvb_usb_lme2510_firmware) { + default: + dvb_usb_lme2510_firmware = TUNER_S0194; +@@ -813,7 +843,8 @@ static int lme_firmware_switch(struct us + cold_fw = 0; + break; + } +- } else { ++ break; ++ case 0x1120: + switch (dvb_usb_lme2510_firmware) { + default: + dvb_usb_lme2510_firmware = TUNER_S7395; +@@ -842,8 +873,17 @@ static int lme_firmware_switch(struct us + cold_fw = 0; + break; + } ++ break; ++ case 0x22f0: ++ fw_lme = fw_c_rs2000; ++ ret = request_firmware(&fw, fw_lme, &udev->dev); ++ dvb_usb_lme2510_firmware = TUNER_RS2000; ++ break; ++ default: ++ fw_lme = fw_c_s7395; + } + ++ + if (cold_fw) { + info("FRM Loading %s file", fw_lme); + ret = lme2510_download_firmware(udev, fw); +@@ -906,6 +946,29 @@ static struct stv0299_config sharp_z0194 + .set_symbol_rate = sharp_z0194a_set_symbol_rate, + }; + ++static int dm04_rs2000_set_ts_param(struct dvb_frontend *fe, ++ int caller) ++{ ++ struct dvb_usb_adapter *adap = fe->dvb->priv; ++ struct dvb_usb_device *d = adap->dev; ++ struct lme2510_state *st = d->priv; ++ ++ mutex_lock(&d->i2c_mutex); ++ if ((st->i2c_talk_onoff == 1) && (st->stream_on & 1)) { ++ st->i2c_talk_onoff = 0; ++ lme2510_stream_restart(d); ++ } ++ mutex_unlock(&d->i2c_mutex); ++ ++ return 0; ++} ++ ++static struct m88rs2000_config m88rs2000_config = { ++ .demod_addr = 0xd0, ++ .tuner_addr = 0xc0, ++ .set_ts_params = dm04_rs2000_set_ts_param, ++}; ++ + static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, + fe_sec_voltage_t voltage) + { +@@ -915,8 +978,7 @@ static int dm04_lme2510_set_voltage(stru + static u8 rbuf[1]; + int ret = 0, len = 3, rlen = 1; + +- if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) +- return -EAGAIN; ++ mutex_lock(&adap->dev->i2c_mutex); + + switch (voltage) { + case SEC_VOLTAGE_18: +@@ -937,12 +999,31 @@ static int dm04_lme2510_set_voltage(stru + return (ret < 0) ? -ENODEV : 0; + } + ++static int dm04_rs2000_read_signal_strength(struct dvb_frontend *fe, ++ u16 *strength) ++{ ++ struct dvb_usb_adapter *adap = fe->dvb->priv; ++ struct lme2510_state *st = adap->dev->priv; ++ ++ *strength = (u16)((u32)st->signal_level * 0xffff / 0x7f); ++ return 0; ++} ++ ++static int dm04_rs2000_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct dvb_usb_adapter *adap = fe->dvb->priv; ++ struct lme2510_state *st = adap->dev->priv; ++ ++ *snr = (u16)((u32)st->signal_sn * 0xffff / 0xff); ++ return 0; ++} ++ + static int lme_name(struct dvb_usb_adapter *adap) + { + struct lme2510_state *st = adap->dev->priv; + const char *desc = adap->dev->desc->name; + char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395", +- " SHARP:BS2F7HZ0194"}; ++ " SHARP:BS2F7HZ0194", " RS2000"}; + char *name = adap->fe_adap[0].fe->ops.info.name; + + strlcpy(name, desc, 128); +@@ -958,60 +1039,82 @@ static int dm04_lme2510_frontend_attach( + int ret = 0; + + st->i2c_talk_onoff = 1; ++ switch (le16_to_cpu(adap->dev->udev->descriptor.idProduct)) { ++ case 0x1122: ++ case 0x1120: ++ st->i2c_gate = 4; ++ adap->fe_adap[0].fe = dvb_attach(tda10086_attach, ++ &tda10086_config, &adap->dev->i2c_adap); ++ if (adap->fe_adap[0].fe) { ++ info("TUN Found Frontend TDA10086"); ++ st->i2c_tuner_gate_w = 4; ++ st->i2c_tuner_gate_r = 4; ++ st->i2c_tuner_addr = 0xc0; ++ st->tuner_config = TUNER_LG; ++ if (dvb_usb_lme2510_firmware != TUNER_LG) { ++ dvb_usb_lme2510_firmware = TUNER_LG; ++ ret = lme_firmware_switch(adap->dev->udev, 1); ++ } ++ break; ++ } + +- st->i2c_gate = 4; +- adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config, +- &adap->dev->i2c_adap); +- +- if (adap->fe_adap[0].fe) { +- info("TUN Found Frontend TDA10086"); +- st->i2c_tuner_gate_w = 4; +- st->i2c_tuner_gate_r = 4; +- st->i2c_tuner_addr = 0xc0; +- st->tuner_config = TUNER_LG; +- if (dvb_usb_lme2510_firmware != TUNER_LG) { +- dvb_usb_lme2510_firmware = TUNER_LG; +- ret = lme_firmware_switch(adap->dev->udev, 1); ++ st->i2c_gate = 4; ++ adap->fe_adap[0].fe = dvb_attach(stv0299_attach, ++ &sharp_z0194_config, &adap->dev->i2c_adap); ++ if (adap->fe_adap[0].fe) { ++ info("FE Found Stv0299"); ++ st->i2c_tuner_gate_w = 4; ++ st->i2c_tuner_gate_r = 5; ++ st->i2c_tuner_addr = 0xc0; ++ st->tuner_config = TUNER_S0194; ++ if (dvb_usb_lme2510_firmware != TUNER_S0194) { ++ dvb_usb_lme2510_firmware = TUNER_S0194; ++ ret = lme_firmware_switch(adap->dev->udev, 1); ++ } ++ break; + } +- goto end; +- } + +- st->i2c_gate = 4; +- adap->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194_config, ++ st->i2c_gate = 5; ++ adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config, + &adap->dev->i2c_adap); +- if (adap->fe_adap[0].fe) { +- info("FE Found Stv0299"); +- st->i2c_tuner_gate_w = 4; +- st->i2c_tuner_gate_r = 5; +- st->i2c_tuner_addr = 0xc0; +- st->tuner_config = TUNER_S0194; +- if (dvb_usb_lme2510_firmware != TUNER_S0194) { +- dvb_usb_lme2510_firmware = TUNER_S0194; +- ret = lme_firmware_switch(adap->dev->udev, 1); ++ ++ if (adap->fe_adap[0].fe) { ++ info("FE Found Stv0288"); ++ st->i2c_tuner_gate_w = 4; ++ st->i2c_tuner_gate_r = 5; ++ st->i2c_tuner_addr = 0xc0; ++ st->tuner_config = TUNER_S7395; ++ if (dvb_usb_lme2510_firmware != TUNER_S7395) { ++ dvb_usb_lme2510_firmware = TUNER_S7395; ++ ret = lme_firmware_switch(adap->dev->udev, 1); ++ } ++ break; + } +- goto end; +- } ++ case 0x22f0: ++ st->i2c_gate = 5; ++ adap->fe_adap[0].fe = dvb_attach(m88rs2000_attach, ++ &m88rs2000_config, &adap->dev->i2c_adap); + +- st->i2c_gate = 5; +- adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config, +- &adap->dev->i2c_adap); +- if (adap->fe_adap[0].fe) { +- info("FE Found Stv0288"); +- st->i2c_tuner_gate_w = 4; +- st->i2c_tuner_gate_r = 5; +- st->i2c_tuner_addr = 0xc0; +- st->tuner_config = TUNER_S7395; +- if (dvb_usb_lme2510_firmware != TUNER_S7395) { +- dvb_usb_lme2510_firmware = TUNER_S7395; +- ret = lme_firmware_switch(adap->dev->udev, 1); ++ if (adap->fe_adap[0].fe) { ++ info("FE Found M88RS2000"); ++ st->i2c_tuner_gate_w = 5; ++ st->i2c_tuner_gate_r = 5; ++ st->i2c_tuner_addr = 0xc0; ++ st->tuner_config = TUNER_RS2000; ++ adap->fe_adap[0].fe->ops.read_signal_strength = ++ dm04_rs2000_read_signal_strength; ++ adap->fe_adap[0].fe->ops.read_snr = ++ dm04_rs2000_read_snr; + } +- } else { +- info("DM04 Not Supported"); +- return -ENODEV; ++ break; + } + ++ if (adap->fe_adap[0].fe == NULL) { ++ info("DM04/QQBOX Not Powered up or not Supported"); ++ return -ENODEV; ++ } + +-end: if (ret) { ++ if (ret) { + if (adap->fe_adap[0].fe) { + dvb_frontend_detach(adap->fe_adap[0].fe); + adap->fe_adap[0].fe = NULL; +@@ -1028,7 +1131,7 @@ end: if (ret) { + static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) + { + struct lme2510_state *st = adap->dev->priv; +- char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA"}; ++ char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA", "RS2000"}; + int ret = 0; + + switch (st->tuner_config) { +@@ -1047,6 +1150,9 @@ static int dm04_lme2510_tuner(struct dvb + &adap->dev->i2c_adap, DVB_PLL_OPERA1)) + ret = st->tuner_config; + break; ++ case TUNER_RS2000: ++ ret = st->tuner_config; ++ break; + default: + break; + } +@@ -1054,7 +1160,7 @@ static int dm04_lme2510_tuner(struct dvb + if (ret) + info("TUN Found %s tuner", tun_msg[ret]); + else { +- info("TUN No tuner found --- reseting device"); ++ info("TUN No tuner found --- resetting device"); + lme_coldreset(adap->dev->udev); + return -ENODEV; + } +@@ -1075,10 +1181,9 @@ static int lme2510_powerup(struct dvb_us + static u8 lnb_on[] = LNB_ON; + static u8 lnb_off[] = LNB_OFF; + static u8 rbuf[1]; +- int ret, len = 3, rlen = 1; ++ int ret = 0, len = 3, rlen = 1; + +- if (mutex_lock_interruptible(&d->i2c_mutex) < 0) +- return -EAGAIN; ++ mutex_lock(&d->i2c_mutex); + + if (onoff) + ret = lme2510_usb_talk(d, lnb_on, len, rbuf, rlen); +@@ -1136,6 +1241,7 @@ static int lme2510_probe(struct usb_inte + static struct usb_device_id lme2510_table[] = { + { USB_DEVICE(0x3344, 0x1122) }, /* LME2510 */ + { USB_DEVICE(0x3344, 0x1120) }, /* LME2510C */ ++ { USB_DEVICE(0x3344, 0x22f0) }, /* LME2510C RS2000 */ + {} /* Terminating entry */ + }; + +@@ -1153,7 +1259,7 @@ static struct dvb_usb_device_properties + DVB_USB_ADAP_NEED_PID_FILTERING| + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .streaming_ctrl = lme2510_streaming_ctrl, +- .pid_filter_count = 15, ++ .pid_filter_count = 32, + .pid_filter = lme2510_pid_filter, + .pid_filter_ctrl = lme2510_pid_filter_ctrl, + .frontend_attach = dm04_lme2510_frontend_attach, +@@ -1204,7 +1310,7 @@ static struct dvb_usb_device_properties + DVB_USB_ADAP_NEED_PID_FILTERING| + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .streaming_ctrl = lme2510_streaming_ctrl, +- .pid_filter_count = 15, ++ .pid_filter_count = 32, + .pid_filter = lme2510_pid_filter, + .pid_filter_ctrl = lme2510_pid_filter_ctrl, + .frontend_attach = dm04_lme2510_frontend_attach, +@@ -1234,11 +1340,14 @@ static struct dvb_usb_device_properties + .identify_state = lme2510_identify_state, + .i2c_algo = &lme2510_i2c_algo, + .generic_bulk_ctrl_endpoint = 0, +- .num_device_descs = 1, ++ .num_device_descs = 2, + .devices = { + { "DM04_LME2510C_DVB-S", + { &lme2510_table[1], NULL }, + }, ++ { "DM04_LME2510C_DVB-S RS2000", ++ { &lme2510_table[2], NULL }, ++ }, + } + }; + +@@ -1295,5 +1404,5 @@ module_usb_driver(lme2510_driver); + + MODULE_AUTHOR("Malcolm Priestley "); + MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); +-MODULE_VERSION("1.91"); ++MODULE_VERSION("1.99"); + MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/video/ov6650.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ov6650.c ++++ linux-3.3.x86_64/drivers/media/video/ov6650.c +@@ -649,7 +649,7 @@ static int ov6650_s_fmt(struct v4l2_subd + clkrc = CLKRC_24MHz; + } else { + dev_err(&client->dev, +- "unspported input clock, check platform data\n"); ++ "unsupported input clock, check platform data\n"); + return -EINVAL; + } + mclk = sense->master_clock; +@@ -1046,18 +1046,7 @@ static struct i2c_driver ov6650_i2c_driv + .id_table = ov6650_id, + }; + +-static int __init ov6650_module_init(void) +-{ +- return i2c_add_driver(&ov6650_i2c_driver); +-} +- +-static void __exit ov6650_module_exit(void) +-{ +- i2c_del_driver(&ov6650_i2c_driver); +-} +- +-module_init(ov6650_module_init); +-module_exit(ov6650_module_exit); ++module_i2c_driver(ov6650_i2c_driver); + + MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV6650"); + MODULE_AUTHOR("Janusz Krzysztofik "); +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/tda1004x.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/tda1004x.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/tda1004x.c +@@ -1272,7 +1272,7 @@ struct dvb_frontend* tda10045_attach(con + /* allocate memory for the internal state */ + state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL); + if (!state) { +- printk(KERN_ERR "Can't alocate memory for tda10045 state\n"); ++ printk(KERN_ERR "Can't allocate memory for tda10045 state\n"); + return NULL; + } + +@@ -1342,7 +1342,7 @@ struct dvb_frontend* tda10046_attach(con + /* allocate memory for the internal state */ + state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL); + if (!state) { +- printk(KERN_ERR "Can't alocate memory for tda10046 state\n"); ++ printk(KERN_ERR "Can't allocate memory for tda10046 state\n"); + return NULL; + } + +Index: linux-3.3.x86_64/drivers/media/video/davinci/vpif.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/davinci/vpif.h ++++ linux-3.3.x86_64/drivers/media/video/davinci/vpif.h +@@ -18,8 +18,6 @@ + + #include + #include +-#include +-#include + #include + + /* Maximum channel allowed */ +Index: linux-3.3.x86_64/drivers/media/video/davinci/vpif_display.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/davinci/vpif_display.c ++++ linux-3.3.x86_64/drivers/media/video/davinci/vpif_display.c +@@ -39,8 +39,6 @@ + #include + #include + +-#include +- + #include "vpif_display.h" + #include "vpif.h" + +Index: linux-3.3.x86_64/include/media/davinci/vpif_types.h +=================================================================== +--- linux-3.3.x86_64.orig/include/media/davinci/vpif_types.h ++++ linux-3.3.x86_64/include/media/davinci/vpif_types.h +@@ -17,6 +17,8 @@ + #ifndef _VPIF_TYPES_H + #define _VPIF_TYPES_H + ++#include ++ + #define VPIF_CAPTURE_MAX_CHANNELS 2 + + enum vpif_if_type { +Index: linux-3.3.x86_64/drivers/media/video/tm6000/tm6000-input.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tm6000/tm6000-input.c ++++ linux-3.3.x86_64/drivers/media/video/tm6000/tm6000-input.c +@@ -481,8 +481,6 @@ int tm6000_ir_fini(struct tm6000_core *d + + dprintk(2, "%s\n",__func__); + +- rc_unregister_device(ir->rc); +- + if (!ir->polling) + __tm6000_ir_int_stop(ir->rc); + +@@ -492,6 +490,7 @@ int tm6000_ir_fini(struct tm6000_core *d + tm6000_flash_led(dev, 0); + ir->pwled = 0; + ++ rc_unregister_device(ir->rc); + + kfree(ir); + dev->ir = NULL; +Index: linux-3.3.x86_64/drivers/media/dvb/mantis/mantis_hif.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/mantis/mantis_hif.c ++++ linux-3.3.x86_64/drivers/media/dvb/mantis/mantis_hif.c +@@ -76,7 +76,7 @@ static int mantis_hif_write_wait(struct + udelay(500); + timeout++; + if (timeout > 100) { +- dprintk(MANTIS_ERROR, 1, "Adater(%d) Slot(0): Write operation timed out!", mantis->num); ++ dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write operation timed out!", mantis->num); + rc = -ETIMEDOUT; + break; + } +Index: linux-3.3.x86_64/drivers/media/common/tuners/max2165.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/common/tuners/max2165.c ++++ linux-3.3.x86_64/drivers/media/common/tuners/max2165.c +@@ -168,7 +168,7 @@ int fixpt_div32(u32 dividend, u32 diviso + int i; + + if (0 == divisor) +- return -1; ++ return -EINVAL; + + q = dividend / divisor; + remainder = dividend - q * divisor; +@@ -194,10 +194,13 @@ static int max2165_set_rf(struct max2165 + u8 tf_ntch; + u32 t; + u32 quotient, fraction; ++ int ret; + + /* Set PLL divider according to RF frequency */ +- fixpt_div32(freq / 1000, priv->config->osc_clk * 1000, +- "ient, &fraction); ++ ret = fixpt_div32(freq / 1000, priv->config->osc_clk * 1000, ++ "ient, &fraction); ++ if (ret != 0) ++ return ret; + + /* 20-bit fraction */ + fraction >>= 12; +Index: linux-3.3.x86_64/drivers/media/video/v4l2-compat-ioctl32.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/v4l2-compat-ioctl32.c ++++ linux-3.3.x86_64/drivers/media/video/v4l2-compat-ioctl32.c +@@ -14,12 +14,11 @@ + */ + + #include +-#include + #include ++#include ++#include + #include + +-#ifdef CONFIG_COMPAT +- + static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + { + long ret = -ENOIOCTLCMD; +@@ -937,6 +936,7 @@ static long do_video_ioctl(struct file * + + long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) + { ++ struct video_device *vdev = video_devdata(file); + long ret = -ENOIOCTLCMD; + + if (!file->f_op->unlocked_ioctl) +@@ -1005,6 +1005,8 @@ long v4l2_compat_ioctl32(struct file *fi + case VIDIOC_G_ENC_INDEX: + case VIDIOC_ENCODER_CMD: + case VIDIOC_TRY_ENCODER_CMD: ++ case VIDIOC_DECODER_CMD: ++ case VIDIOC_TRY_DECODER_CMD: + case VIDIOC_DBG_S_REGISTER: + case VIDIOC_DBG_G_REGISTER: + case VIDIOC_DBG_G_CHIP_IDENT: +@@ -1025,14 +1027,16 @@ long v4l2_compat_ioctl32(struct file *fi + break; + + default: +- printk(KERN_WARNING "compat_ioctl32: " +- "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", +- _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd); ++ if (vdev->fops->compat_ioctl32) ++ ret = vdev->fops->compat_ioctl32(file, cmd, arg); ++ ++ if (ret == -ENOIOCTLCMD) ++ printk(KERN_WARNING "compat_ioctl32: " ++ "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", ++ _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), ++ cmd); + break; + } + return ret; + } + EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32); +-#endif +- +-MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/include/media/v4l2-ioctl.h +=================================================================== +--- linux-3.3.x86_64.orig/include/media/v4l2-ioctl.h ++++ linux-3.3.x86_64/include/media/v4l2-ioctl.h +@@ -211,6 +211,10 @@ struct v4l2_ioctl_ops { + struct v4l2_encoder_cmd *a); + int (*vidioc_try_encoder_cmd) (struct file *file, void *fh, + struct v4l2_encoder_cmd *a); ++ int (*vidioc_decoder_cmd) (struct file *file, void *fh, ++ struct v4l2_decoder_cmd *a); ++ int (*vidioc_try_decoder_cmd) (struct file *file, void *fh, ++ struct v4l2_decoder_cmd *a); + + /* Stream type-dependent parameter ioctls */ + int (*vidioc_g_parm) (struct file *file, void *fh, +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-driver.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-driver.c ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-driver.c +@@ -55,7 +55,7 @@ + #include "ivtv-routing.h" + #include "ivtv-controls.h" + #include "ivtv-gpio.h" +- ++#include + #include + #include + #include +@@ -99,7 +99,7 @@ static int i2c_clock_period[IVTV_MAX_CAR + + static unsigned int cardtype_c = 1; + static unsigned int tuner_c = 1; +-static bool radio_c = 1; ++static int radio_c = 1; + static unsigned int i2c_clock_period_c = 1; + static char pal[] = "---"; + static char secam[] = "--"; +@@ -139,7 +139,7 @@ static int tunertype = -1; + static int newi2c = -1; + + module_param_array(tuner, int, &tuner_c, 0644); +-module_param_array(radio, bool, &radio_c, 0644); ++module_param_array(radio, int, &radio_c, 0644); + module_param_array(cardtype, int, &cardtype_c, 0644); + module_param_string(pal, pal, sizeof(pal), 0644); + module_param_string(secam, secam, sizeof(secam), 0644); +@@ -744,8 +744,6 @@ static int __devinit ivtv_init_struct1(s + + itv->cur_dma_stream = -1; + itv->cur_pio_stream = -1; +- itv->audio_stereo_mode = AUDIO_STEREO; +- itv->audio_bilingual_mode = AUDIO_MONO_LEFT; + + /* Ctrls */ + itv->speed = 1000; +@@ -815,7 +813,7 @@ static int ivtv_setup_pci(struct ivtv *i + IVTV_ERR("Can't enable device!\n"); + return -EIO; + } +- if (pci_set_dma_mask(pdev, 0xffffffff)) { ++ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { + IVTV_ERR("No suitable DMA available.\n"); + return -EIO; + } +@@ -1200,6 +1198,32 @@ static int __devinit ivtv_probe(struct p + itv->tuner_std = itv->std; + + if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { ++ struct v4l2_ctrl_handler *hdl = itv->v4l2_dev.ctrl_handler; ++ ++ itv->ctrl_pts = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops, ++ V4L2_CID_MPEG_VIDEO_DEC_PTS, 0, 0, 1, 0); ++ itv->ctrl_frame = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops, ++ V4L2_CID_MPEG_VIDEO_DEC_FRAME, 0, 0x7fffffff, 1, 0); ++ /* Note: V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO is not supported, ++ mask that menu item. */ ++ itv->ctrl_audio_playback = ++ v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops, ++ V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO, ++ 1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO); ++ itv->ctrl_audio_multilingual_playback = ++ v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops, ++ V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO, ++ 1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO, ++ V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT); ++ if (hdl->error) { ++ retval = hdl->error; ++ goto free_i2c; ++ } ++ v4l2_ctrl_cluster(2, &itv->ctrl_pts); ++ v4l2_ctrl_cluster(2, &itv->ctrl_audio_playback); + ivtv_call_all(itv, video, s_std_output, itv->std); + /* Turn off the output signal. The mpeg decoder is not yet + active so without this you would get a green image until the +@@ -1236,6 +1260,7 @@ free_streams: + free_irq: + free_irq(itv->pdev->irq, (void *)itv); + free_i2c: ++ v4l2_ctrl_handler_free(&itv->cxhdl.hdl); + exit_ivtv_i2c(itv); + free_io: + ivtv_iounmap(itv); +@@ -1375,7 +1400,7 @@ static void ivtv_remove(struct pci_dev * + else + type = IVTV_DEC_STREAM_TYPE_MPG; + ivtv_stop_v4l2_decode_stream(&itv->streams[type], +- VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); ++ V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0); + } + ivtv_halt_firmware(itv); + } +@@ -1391,6 +1416,8 @@ static void ivtv_remove(struct pci_dev * + ivtv_streams_cleanup(itv, 1); + ivtv_udma_free(itv); + ++ v4l2_ctrl_handler_free(&itv->cxhdl.hdl); ++ + exit_ivtv_i2c(itv); + + free_irq(itv->pdev->irq, (void *)itv); +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-fileops.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-fileops.c ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-fileops.c +@@ -746,8 +746,9 @@ unsigned int ivtv_v4l2_dec_poll(struct f + return res; + } + +-unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait) ++unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table *wait) + { ++ unsigned long req_events = poll_requested_events(wait); + struct ivtv_open_id *id = fh2id(filp->private_data); + struct ivtv *itv = id->itv; + struct ivtv_stream *s = &itv->streams[id->type]; +@@ -755,7 +756,8 @@ unsigned int ivtv_v4l2_enc_poll(struct f + unsigned res = 0; + + /* Start a capture if there is none */ +- if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { ++ if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags) && ++ (req_events & (POLLIN | POLLRDNORM))) { + int rc; + + rc = ivtv_start_capture(id); +@@ -900,7 +902,7 @@ int ivtv_v4l2_close(struct file *filp) + if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { + struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT]; + +- ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); ++ ivtv_stop_decoding(id, V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0); + + /* If all output streams are closed, and if the user doesn't have + IVTV_DEC_STREAM_TYPE_VOUT open, then disable CC on TV-out. */ +Index: linux-3.3.x86_64/drivers/media/video/v4l2-ctrls.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/v4l2-ctrls.c ++++ linux-3.3.x86_64/drivers/media/video/v4l2-ctrls.c +@@ -175,6 +175,15 @@ const char * const *v4l2_ctrl_get_menu(u + "16-bit CRC", + NULL + }; ++ static const char * const mpeg_audio_dec_playback[] = { ++ "Auto", ++ "Stereo", ++ "Left", ++ "Right", ++ "Mono", ++ "Swapped Stereo", ++ NULL ++ }; + static const char * const mpeg_video_encoding[] = { + "MPEG-1", + "MPEG-2", +@@ -236,8 +245,8 @@ const char * const *v4l2_ctrl_get_menu(u + }; + static const char * const tune_preemphasis[] = { + "No Preemphasis", +- "50 useconds", +- "75 useconds", ++ "50 Microseconds", ++ "75 Microseconds", + NULL, + }; + static const char * const header_mode[] = { +@@ -334,7 +343,7 @@ const char * const *v4l2_ctrl_get_menu(u + }; + static const char * const mpeg4_profile[] = { + "Simple", +- "Adcanved Simple", ++ "Advanced Simple", + "Core", + "Simple Scalable", + "Advanced Coding Efficency", +@@ -353,6 +362,16 @@ const char * const *v4l2_ctrl_get_menu(u + NULL, + }; + ++ static const char * const jpeg_chroma_subsampling[] = { ++ "4:4:4", ++ "4:2:2", ++ "4:2:0", ++ "4:1:1", ++ "4:1:0", ++ "Gray", ++ NULL, ++ }; ++ + switch (id) { + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + return mpeg_audio_sampling_freq; +@@ -374,6 +393,9 @@ const char * const *v4l2_ctrl_get_menu(u + return mpeg_audio_emphasis; + case V4L2_CID_MPEG_AUDIO_CRC: + return mpeg_audio_crc; ++ case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: ++ case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: ++ return mpeg_audio_dec_playback; + case V4L2_CID_MPEG_VIDEO_ENCODING: + return mpeg_video_encoding; + case V4L2_CID_MPEG_VIDEO_ASPECT: +@@ -414,6 +436,9 @@ const char * const *v4l2_ctrl_get_menu(u + return mpeg_mpeg4_level; + case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: + return mpeg4_profile; ++ case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: ++ return jpeg_chroma_subsampling; ++ + default: + return NULL; + } +@@ -492,6 +517,8 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_MPEG_AUDIO_MUTE: return "Audio Mute"; + case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: return "Audio AAC Bitrate"; + case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: return "Audio AC-3 Bitrate"; ++ case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: return "Audio Playback"; ++ case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: return "Audio Multilingual Playback"; + case V4L2_CID_MPEG_VIDEO_ENCODING: return "Video Encoding"; + case V4L2_CID_MPEG_VIDEO_ASPECT: return "Video Aspect"; + case V4L2_CID_MPEG_VIDEO_B_FRAMES: return "Video B Frames"; +@@ -546,6 +573,8 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: return "Number of MBs in a Slice"; + case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: return "Slice Partitioning Method"; + case V4L2_CID_MPEG_VIDEO_VBV_SIZE: return "VBV Buffer Size"; ++ case V4L2_CID_MPEG_VIDEO_DEC_PTS: return "Video Decoder PTS"; ++ case V4L2_CID_MPEG_VIDEO_DEC_FRAME: return "Video Decoder Frame Count"; + + /* CAMERA controls */ + /* Keep the order of the 'case's the same as in videodev2.h! */ +@@ -607,6 +636,14 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_FLASH_CHARGE: return "Charge"; + case V4L2_CID_FLASH_READY: return "Ready to Strobe"; + ++ /* JPEG encoder controls */ ++ /* Keep the order of the 'case's the same as in videodev2.h! */ ++ case V4L2_CID_JPEG_CLASS: return "JPEG Compression Controls"; ++ case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: return "Chroma Subsampling"; ++ case V4L2_CID_JPEG_RESTART_INTERVAL: return "Restart Interval"; ++ case V4L2_CID_JPEG_COMPRESSION_QUALITY: return "Compression Quality"; ++ case V4L2_CID_JPEG_ACTIVE_MARKER: return "Active Markers"; ++ + default: + return NULL; + } +@@ -674,6 +711,8 @@ void v4l2_ctrl_fill(u32 id, const char * + case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: + case V4L2_CID_MPEG_AUDIO_EMPHASIS: + case V4L2_CID_MPEG_AUDIO_CRC: ++ case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: ++ case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: + case V4L2_CID_MPEG_VIDEO_ENCODING: + case V4L2_CID_MPEG_VIDEO_ASPECT: + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: +@@ -693,6 +732,7 @@ void v4l2_ctrl_fill(u32 id, const char * + case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: + case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: + case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: ++ case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: + *type = V4L2_CTRL_TYPE_MENU; + break; + case V4L2_CID_RDS_TX_PS_NAME: +@@ -704,6 +744,7 @@ void v4l2_ctrl_fill(u32 id, const char * + case V4L2_CID_MPEG_CLASS: + case V4L2_CID_FM_TX_CLASS: + case V4L2_CID_FLASH_CLASS: ++ case V4L2_CID_JPEG_CLASS: + *type = V4L2_CTRL_TYPE_CTRL_CLASS; + /* You can neither read not write these */ + *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY; +@@ -717,6 +758,7 @@ void v4l2_ctrl_fill(u32 id, const char * + *max = 0xFFFFFF; + break; + case V4L2_CID_FLASH_FAULT: ++ case V4L2_CID_JPEG_ACTIVE_MARKER: + *type = V4L2_CTRL_TYPE_BITMASK; + break; + case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: +@@ -724,6 +766,11 @@ void v4l2_ctrl_fill(u32 id, const char * + *type = V4L2_CTRL_TYPE_INTEGER; + *flags |= V4L2_CTRL_FLAG_READ_ONLY; + break; ++ case V4L2_CID_MPEG_VIDEO_DEC_FRAME: ++ case V4L2_CID_MPEG_VIDEO_DEC_PTS: ++ *type = V4L2_CTRL_TYPE_INTEGER64; ++ *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_VOLATILE; ++ break; + default: + *type = V4L2_CTRL_TYPE_INTEGER; + break; +@@ -1470,7 +1517,7 @@ EXPORT_SYMBOL(v4l2_ctrl_add_ctrl); + int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl, + struct v4l2_ctrl_handler *add) + { +- struct v4l2_ctrl *ctrl; ++ struct v4l2_ctrl_ref *ref; + int ret = 0; + + /* Do nothing if either handler is NULL or if they are the same */ +@@ -1479,7 +1526,9 @@ int v4l2_ctrl_add_handler(struct v4l2_ct + if (hdl->error) + return hdl->error; + mutex_lock(&add->lock); +- list_for_each_entry(ctrl, &add->ctrls, node) { ++ list_for_each_entry(ref, &add->ctrl_refs, node) { ++ struct v4l2_ctrl *ctrl = ref->ctrl; ++ + /* Skip handler-private controls. */ + if (ctrl->is_private) + continue; +@@ -2359,3 +2408,35 @@ void v4l2_ctrl_del_event(struct v4l2_ctr + v4l2_ctrl_unlock(ctrl); + } + EXPORT_SYMBOL(v4l2_ctrl_del_event); ++ ++int v4l2_ctrl_log_status(struct file *file, void *fh) ++{ ++ struct video_device *vfd = video_devdata(file); ++ struct v4l2_fh *vfh = file->private_data; ++ ++ if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) && vfd->v4l2_dev) ++ v4l2_ctrl_handler_log_status(vfh->ctrl_handler, ++ vfd->v4l2_dev->name); ++ return 0; ++} ++EXPORT_SYMBOL(v4l2_ctrl_log_status); ++ ++int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh, ++ struct v4l2_event_subscription *sub) ++{ ++ if (sub->type == V4L2_EVENT_CTRL) ++ return v4l2_event_subscribe(fh, sub, 0); ++ return -EINVAL; ++} ++EXPORT_SYMBOL(v4l2_ctrl_subscribe_event); ++ ++unsigned int v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait) ++{ ++ struct v4l2_fh *fh = file->private_data; ++ ++ if (v4l2_event_pending(fh)) ++ return POLLPRI; ++ poll_wait(file, &fh->wait, wait); ++ return 0; ++} ++EXPORT_SYMBOL(v4l2_ctrl_poll); +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-controls.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-controls.c ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-controls.c +@@ -21,6 +21,7 @@ + #include "ivtv-driver.h" + #include "ivtv-ioctl.h" + #include "ivtv-controls.h" ++#include "ivtv-mailbox.h" + + static int ivtv_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt) + { +@@ -99,3 +100,64 @@ struct cx2341x_handler_ops ivtv_cxhdl_op + .s_video_encoding = ivtv_s_video_encoding, + .s_stream_vbi_fmt = ivtv_s_stream_vbi_fmt, + }; ++ ++int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame) ++{ ++ u32 data[CX2341X_MBOX_MAX_DATA]; ++ ++ if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { ++ *pts = (s64)((u64)itv->last_dec_timing[2] << 32) | ++ (u64)itv->last_dec_timing[1]; ++ *frame = itv->last_dec_timing[0]; ++ return 0; ++ } ++ *pts = 0; ++ *frame = 0; ++ if (atomic_read(&itv->decoding)) { ++ if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { ++ IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); ++ return -EIO; ++ } ++ memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); ++ set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); ++ *pts = (s64)((u64) data[2] << 32) | (u64) data[1]; ++ *frame = data[0]; ++ /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/ ++ } ++ return 0; ++} ++ ++static int ivtv_g_volatile_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl); ++ ++ switch (ctrl->id) { ++ /* V4L2_CID_MPEG_VIDEO_DEC_PTS and V4L2_CID_MPEG_VIDEO_DEC_FRAME ++ control cluster */ ++ case V4L2_CID_MPEG_VIDEO_DEC_PTS: ++ return ivtv_g_pts_frame(itv, &itv->ctrl_pts->val64, ++ &itv->ctrl_frame->val64); ++ } ++ return 0; ++} ++ ++static int ivtv_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl); ++ ++ switch (ctrl->id) { ++ /* V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK and MULTILINGUAL_PLAYBACK ++ control cluster */ ++ case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: ++ itv->audio_stereo_mode = itv->ctrl_audio_playback->val - 1; ++ itv->audio_bilingual_mode = itv->ctrl_audio_multilingual_playback->val - 1; ++ ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); ++ break; ++ } ++ return 0; ++} ++ ++const struct v4l2_ctrl_ops ivtv_hdl_out_ops = { ++ .s_ctrl = ivtv_s_ctrl, ++ .g_volatile_ctrl = ivtv_g_volatile_ctrl, ++}; +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-controls.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-controls.h ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-controls.h +@@ -22,5 +22,7 @@ + #define IVTV_CONTROLS_H + + extern struct cx2341x_handler_ops ivtv_cxhdl_ops; ++extern const struct v4l2_ctrl_ops ivtv_hdl_out_ops; ++int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame); + + #endif +Index: linux-3.3.x86_64/drivers/media/dvb/ddbridge/ddbridge.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/ddbridge/ddbridge.h ++++ linux-3.3.x86_64/drivers/media/dvb/ddbridge/ddbridge.h +@@ -32,8 +32,6 @@ + #include + #include + #include +-#include +-#include + #include + + #include "dmxdev.h" +Index: linux-3.3.x86_64/drivers/media/video/cx18/cx18-driver.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx18/cx18-driver.h ++++ linux-3.3.x86_64/drivers/media/video/cx18/cx18-driver.h +@@ -44,8 +44,6 @@ + #include + #include + +-#include +-#include + #include + #include + #include +Index: linux-3.3.x86_64/include/linux/ivtv.h +=================================================================== +--- linux-3.3.x86_64.orig/include/linux/ivtv.h ++++ linux-3.3.x86_64/include/linux/ivtv.h +@@ -58,7 +58,11 @@ struct ivtv_dma_frame { + __u32 src_height; + }; + +-#define IVTV_IOC_DMA_FRAME _IOW ('V', BASE_VIDIOC_PRIVATE+0, struct ivtv_dma_frame) ++#define IVTV_IOC_DMA_FRAME _IOW ('V', BASE_VIDIOC_PRIVATE+0, struct ivtv_dma_frame) ++ ++/* Select the passthrough mode (if the argument is non-zero). In the passthrough ++ mode the output of the encoder is passed immediately into the decoder. */ ++#define IVTV_IOC_PASSTHROUGH_MODE _IOW ('V', BASE_VIDIOC_PRIVATE+1, int) + + /* Deprecated defines: applications should use the defines from videodev2.h */ + #define IVTV_SLICED_TYPE_TELETEXT_B V4L2_MPEG_VBI_IVTV_TELETEXT_B +Index: linux-3.3.x86_64/drivers/media/rc/keymaps/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/keymaps/Makefile ++++ linux-3.3.x86_64/drivers/media/rc/keymaps/Makefile +@@ -41,8 +41,11 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t + rc-imon-mce.o \ + rc-imon-pad.o \ + rc-iodata-bctv7e.o \ ++ rc-it913x-v1.o \ ++ rc-it913x-v2.o \ + rc-kaiomy.o \ + rc-kworld-315u.o \ ++ rc-kworld-pc150u.o \ + rc-kworld-plus-tv-analog.o \ + rc-leadtek-y04g0051.o \ + rc-lirc.o \ +Index: linux-3.3.x86_64/drivers/media/rc/keymaps/rc-it913x-v1.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/rc/keymaps/rc-it913x-v1.c +@@ -0,0 +1,95 @@ ++/* ITE Generic remotes Version 1 ++ * ++ * Copyright (C) 2012 Malcolm Priestley (tvboxspy@gmail.com) ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include ++#include ++ ++ ++static struct rc_map_table it913x_v1_rc[] = { ++ /* Type 1 */ ++ { 0x61d601, KEY_VIDEO }, /* Source */ ++ { 0x61d602, KEY_3 }, ++ { 0x61d603, KEY_POWER }, /* ShutDown */ ++ { 0x61d604, KEY_1 }, ++ { 0x61d605, KEY_5 }, ++ { 0x61d606, KEY_6 }, ++ { 0x61d607, KEY_CHANNELDOWN }, /* CH- */ ++ { 0x61d608, KEY_2 }, ++ { 0x61d609, KEY_CHANNELUP }, /* CH+ */ ++ { 0x61d60a, KEY_9 }, ++ { 0x61d60b, KEY_ZOOM }, /* Zoom */ ++ { 0x61d60c, KEY_7 }, ++ { 0x61d60d, KEY_8 }, ++ { 0x61d60e, KEY_VOLUMEUP }, /* Vol+ */ ++ { 0x61d60f, KEY_4 }, ++ { 0x61d610, KEY_ESC }, /* [back up arrow] */ ++ { 0x61d611, KEY_0 }, ++ { 0x61d612, KEY_OK }, /* [enter arrow] */ ++ { 0x61d613, KEY_VOLUMEDOWN }, /* Vol- */ ++ { 0x61d614, KEY_RECORD }, /* Rec */ ++ { 0x61d615, KEY_STOP }, /* Stop */ ++ { 0x61d616, KEY_PLAY }, /* Play */ ++ { 0x61d617, KEY_MUTE }, /* Mute */ ++ { 0x61d618, KEY_UP }, ++ { 0x61d619, KEY_DOWN }, ++ { 0x61d61a, KEY_LEFT }, ++ { 0x61d61b, KEY_RIGHT }, ++ { 0x61d61c, KEY_RED }, ++ { 0x61d61d, KEY_GREEN }, ++ { 0x61d61e, KEY_YELLOW }, ++ { 0x61d61f, KEY_BLUE }, ++ { 0x61d643, KEY_POWER2 }, /* [red power button] */ ++ /* Type 2 - 20 buttons */ ++ { 0x807f0d, KEY_0 }, ++ { 0x807f04, KEY_1 }, ++ { 0x807f05, KEY_2 }, ++ { 0x807f06, KEY_3 }, ++ { 0x807f07, KEY_4 }, ++ { 0x807f08, KEY_5 }, ++ { 0x807f09, KEY_6 }, ++ { 0x807f0a, KEY_7 }, ++ { 0x807f1b, KEY_8 }, ++ { 0x807f1f, KEY_9 }, ++ { 0x807f12, KEY_POWER }, ++ { 0x807f01, KEY_MEDIA_REPEAT}, /* Recall */ ++ { 0x807f19, KEY_PAUSE }, /* Timeshift */ ++ { 0x807f1e, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ ++ { 0x807f03, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ ++ { 0x807f1a, KEY_CHANNELUP }, ++ { 0x807f02, KEY_CHANNELDOWN }, ++ { 0x807f0c, KEY_ZOOM }, ++ { 0x807f00, KEY_RECORD }, ++ { 0x807f0e, KEY_STOP }, ++}; ++ ++static struct rc_map_list it913x_v1_map = { ++ .map = { ++ .scan = it913x_v1_rc, ++ .size = ARRAY_SIZE(it913x_v1_rc), ++ .rc_type = RC_TYPE_NEC, ++ .name = RC_MAP_IT913X_V1, ++ } ++}; ++ ++static int __init init_rc_it913x_v1_map(void) ++{ ++ return rc_map_register(&it913x_v1_map); ++} ++ ++static void __exit exit_rc_it913x_v1_map(void) ++{ ++ rc_map_unregister(&it913x_v1_map); ++} ++ ++module_init(init_rc_it913x_v1_map) ++module_exit(exit_rc_it913x_v1_map) ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); +Index: linux-3.3.x86_64/drivers/media/rc/keymaps/rc-it913x-v2.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/rc/keymaps/rc-it913x-v2.c +@@ -0,0 +1,94 @@ ++/* ITE Generic remotes Version 2 ++ * ++ * Copyright (C) 2012 Malcolm Priestley (tvboxspy@gmail.com) ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include ++#include ++ ++ ++static struct rc_map_table it913x_v2_rc[] = { ++ /* Type 1 */ ++ /* 9005 remote */ ++ { 0x807f12, KEY_POWER2 }, /* Power (RED POWER BUTTON)*/ ++ { 0x807f1a, KEY_VIDEO }, /* Source */ ++ { 0x807f1e, KEY_MUTE }, /* Mute */ ++ { 0x807f01, KEY_RECORD }, /* Record */ ++ { 0x807f02, KEY_CHANNELUP }, /* Channel+ */ ++ { 0x807f03, KEY_TIME }, /* TimeShift */ ++ { 0x807f04, KEY_VOLUMEUP }, /* Volume- */ ++ { 0x807f05, KEY_SCREEN }, /* FullScreen */ ++ { 0x807f06, KEY_VOLUMEDOWN }, /* Volume- */ ++ { 0x807f07, KEY_0 }, /* 0 */ ++ { 0x807f08, KEY_CHANNELDOWN }, /* Channel- */ ++ { 0x807f09, KEY_PREVIOUS }, /* Recall */ ++ { 0x807f0a, KEY_1 }, /* 1 */ ++ { 0x807f1b, KEY_2 }, /* 2 */ ++ { 0x807f1f, KEY_3 }, /* 3 */ ++ { 0x807f0c, KEY_4 }, /* 4 */ ++ { 0x807f0d, KEY_5 }, /* 5 */ ++ { 0x807f0e, KEY_6 }, /* 6 */ ++ { 0x807f00, KEY_7 }, /* 7 */ ++ { 0x807f0f, KEY_8 }, /* 8 */ ++ { 0x807f19, KEY_9 }, /* 9 */ ++ ++ /* Type 2 */ ++ /* keys stereo, snapshot unassigned */ ++ { 0x866b00, KEY_0 }, ++ { 0x866b1b, KEY_1 }, ++ { 0x866b02, KEY_2 }, ++ { 0x866b03, KEY_3 }, ++ { 0x866b04, KEY_4 }, ++ { 0x866b05, KEY_5 }, ++ { 0x866b06, KEY_6 }, ++ { 0x866b07, KEY_7 }, ++ { 0x866b08, KEY_8 }, ++ { 0x866b09, KEY_9 }, ++ { 0x866b12, KEY_POWER }, ++ { 0x866b13, KEY_MUTE }, ++ { 0x866b0a, KEY_PREVIOUS }, /* Recall */ ++ { 0x866b1e, KEY_PAUSE }, ++ { 0x866b0c, KEY_VOLUMEUP }, ++ { 0x866b18, KEY_VOLUMEDOWN }, ++ { 0x866b0b, KEY_CHANNELUP }, ++ { 0x866b18, KEY_CHANNELDOWN }, ++ { 0x866b10, KEY_ZOOM }, ++ { 0x866b1d, KEY_RECORD }, ++ { 0x866b0e, KEY_STOP }, ++ { 0x866b11, KEY_EPG}, ++ { 0x866b1a, KEY_FASTFORWARD }, ++ { 0x866b0f, KEY_REWIND }, ++ { 0x866b1c, KEY_TV }, ++ { 0x866b1b, KEY_TEXT }, ++ ++}; ++ ++static struct rc_map_list it913x_v2_map = { ++ .map = { ++ .scan = it913x_v2_rc, ++ .size = ARRAY_SIZE(it913x_v2_rc), ++ .rc_type = RC_TYPE_NEC, ++ .name = RC_MAP_IT913X_V2, ++ } ++}; ++ ++static int __init init_rc_it913x_v2_map(void) ++{ ++ return rc_map_register(&it913x_v2_map); ++} ++ ++static void __exit exit_rc_it913x_v2_map(void) ++{ ++ rc_map_unregister(&it913x_v2_map); ++} ++ ++module_init(init_rc_it913x_v2_map) ++module_exit(exit_rc_it913x_v2_map) ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); +Index: linux-3.3.x86_64/include/media/rc-map.h +=================================================================== +--- linux-3.3.x86_64.orig/include/media/rc-map.h ++++ linux-3.3.x86_64/include/media/rc-map.h +@@ -102,8 +102,11 @@ void rc_map_init(void); + #define RC_MAP_IMON_MCE "rc-imon-mce" + #define RC_MAP_IMON_PAD "rc-imon-pad" + #define RC_MAP_IODATA_BCTV7E "rc-iodata-bctv7e" ++#define RC_MAP_IT913X_V1 "rc-it913x-v1" ++#define RC_MAP_IT913X_V2 "rc-it913x-v2" + #define RC_MAP_KAIOMY "rc-kaiomy" + #define RC_MAP_KWORLD_315U "rc-kworld-315u" ++#define RC_MAP_KWORLD_PC150U "rc-kworld-pc150u" + #define RC_MAP_KWORLD_PLUS_TV_ANALOG "rc-kworld-plus-tv-analog" + #define RC_MAP_LEADTEK_Y04G0051 "rc-leadtek-y04g0051" + #define RC_MAP_LIRC "rc-lirc" +Index: linux-3.3.x86_64/drivers/media/video/bt8xx/bttv-driver.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/bt8xx/bttv-driver.c ++++ linux-3.3.x86_64/drivers/media/video/bt8xx/bttv-driver.c +@@ -2035,11 +2035,7 @@ static int bttv_log_status(struct file * + struct bttv_fh *fh = f; + struct bttv *btv = fh->btv; + +- pr_info("%d: ======== START STATUS CARD #%d ========\n", +- btv->c.nr, btv->c.nr); + bttv_call_all(btv, core, log_status); +- pr_info("%d: ======== END STATUS CARD #%d ========\n", +- btv->c.nr, btv->c.nr); + return 0; + } + +Index: linux-3.3.x86_64/drivers/media/video/cx18/cx18-ioctl.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx18/cx18-ioctl.c ++++ linux-3.3.x86_64/drivers/media/video/cx18/cx18-ioctl.c +@@ -1085,8 +1085,6 @@ static int cx18_log_status(struct file * + struct v4l2_audio audin; + int i; + +- CX18_INFO("================= START STATUS CARD #%d " +- "=================\n", cx->instance); + CX18_INFO("Version: %s Card: %s\n", CX18_VERSION, cx->card_name); + if (cx->hw_flags & CX18_HW_TVEEPROM) { + struct tveeprom tv; +@@ -1120,8 +1118,6 @@ static int cx18_log_status(struct file * + CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", + (long long)cx->mpg_data_received, + (long long)cx->vbi_data_inserted); +- CX18_INFO("================== END STATUS CARD #%d " +- "==================\n", cx->instance); + return 0; + } + +Index: linux-3.3.x86_64/drivers/media/video/pwc/pwc-v4l.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/pwc/pwc-v4l.c ++++ linux-3.3.x86_64/drivers/media/video/pwc/pwc-v4l.c +@@ -1146,14 +1146,6 @@ leave: + return ret; + } + +-static int pwc_log_status(struct file *file, void *priv) +-{ +- struct pwc_device *pdev = video_drvdata(file); +- +- v4l2_ctrl_handler_log_status(&pdev->ctrl_handler, PWC_NAME); +- return 0; +-} +- + const struct v4l2_ioctl_ops pwc_ioctl_ops = { + .vidioc_querycap = pwc_querycap, + .vidioc_enum_input = pwc_enum_input, +@@ -1169,9 +1161,11 @@ const struct v4l2_ioctl_ops pwc_ioctl_op + .vidioc_dqbuf = pwc_dqbuf, + .vidioc_streamon = pwc_streamon, + .vidioc_streamoff = pwc_streamoff, +- .vidioc_log_status = pwc_log_status, ++ .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_enum_framesizes = pwc_enum_framesizes, + .vidioc_enum_frameintervals = pwc_enum_frameintervals, + .vidioc_g_parm = pwc_g_parm, + .vidioc_s_parm = pwc_s_parm, ++ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + }; +Index: linux-3.3.x86_64/drivers/media/video/saa7164/saa7164-encoder.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7164/saa7164-encoder.c ++++ linux-3.3.x86_64/drivers/media/video/saa7164/saa7164-encoder.c +@@ -791,11 +791,6 @@ static int vidioc_s_fmt_vid_cap(struct f + return 0; + } + +-static int vidioc_log_status(struct file *file, void *priv) +-{ +- return 0; +-} +- + static int fill_queryctrl(struct saa7164_encoder_params *params, + struct v4l2_queryctrl *c) + { +@@ -1347,7 +1342,6 @@ static const struct v4l2_ioctl_ops mpeg_ + .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, + .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, + .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, +- .vidioc_log_status = vidioc_log_status, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_chip_ident = saa7164_g_chip_ident, + #ifdef CONFIG_VIDEO_ADV_DEBUG +Index: linux-3.3.x86_64/drivers/media/video/saa7164/saa7164-vbi.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7164/saa7164-vbi.c ++++ linux-3.3.x86_64/drivers/media/video/saa7164/saa7164-vbi.c +@@ -730,11 +730,6 @@ static int vidioc_s_fmt_vid_cap(struct f + return 0; + } + +-static int vidioc_log_status(struct file *file, void *priv) +-{ +- return 0; +-} +- + static int fill_queryctrl(struct saa7164_vbi_params *params, + struct v4l2_queryctrl *c) + { +@@ -1256,7 +1251,6 @@ static const struct v4l2_ioctl_ops vbi_i + .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, + .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, + .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, +- .vidioc_log_status = vidioc_log_status, + .vidioc_queryctrl = vidioc_queryctrl, + #if 0 + .vidioc_g_chip_ident = saa7164_g_chip_ident, +Index: linux-3.3.x86_64/include/media/v4l2-ctrls.h +=================================================================== +--- linux-3.3.x86_64.orig/include/media/v4l2-ctrls.h ++++ linux-3.3.x86_64/include/media/v4l2-ctrls.h +@@ -33,6 +33,7 @@ struct video_device; + struct v4l2_subdev; + struct v4l2_subscribed_event; + struct v4l2_fh; ++struct poll_table_struct; + + /** struct v4l2_ctrl_ops - The control operations that the driver has to provide. + * @g_volatile_ctrl: Get a new value for this control. Generally only relevant +@@ -492,6 +493,18 @@ void v4l2_ctrl_add_event(struct v4l2_ctr + void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl, + struct v4l2_subscribed_event *sev); + ++/* Can be used as a vidioc_log_status function that just dumps all controls ++ associated with the filehandle. */ ++int v4l2_ctrl_log_status(struct file *file, void *fh); ++ ++/* Can be used as a vidioc_subscribe_event function that just subscribes ++ control events. */ ++int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh, ++ struct v4l2_event_subscription *sub); ++ ++/* Can be used as a poll function that just polls for control events. */ ++unsigned int v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait); ++ + /* Helpers for ioctl_ops. If hdl == NULL then they will all return -EINVAL. */ + int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc); + int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm); +Index: linux-3.3.x86_64/drivers/media/video/v4l2-subdev.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/v4l2-subdev.c ++++ linux-3.3.x86_64/drivers/media/video/v4l2-subdev.c +@@ -194,8 +194,16 @@ static long subdev_do_ioctl(struct file + } + #endif + +- case VIDIOC_LOG_STATUS: +- return v4l2_subdev_call(sd, core, log_status); ++ case VIDIOC_LOG_STATUS: { ++ int ret; ++ ++ pr_info("%s: ================= START STATUS =================\n", ++ sd->name); ++ ret = v4l2_subdev_call(sd, core, log_status); ++ pr_info("%s: ================== END STATUS ==================\n", ++ sd->name); ++ return ret; ++ } + + #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) + case VIDIOC_SUBDEV_G_FMT: { +Index: linux-3.3.x86_64/drivers/media/radio/Kconfig +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/Kconfig ++++ linux-3.3.x86_64/drivers/media/radio/Kconfig +@@ -43,7 +43,7 @@ config USB_DSBR + + config RADIO_MAXIRADIO + tristate "Guillemot MAXI Radio FM 2000 radio" +- depends on VIDEO_V4L2 && PCI ++ depends on VIDEO_V4L2 && PCI && SND + ---help--- + Choose Y here if you have this radio card. This card may also be + found as Gemtek PCI FM. +@@ -80,6 +80,16 @@ config RADIO_SI4713 + To compile this driver as a module, choose M here: the + module will be called radio-si4713. + ++config USB_KEENE ++ tristate "Keene FM Transmitter USB support" ++ depends on USB && VIDEO_V4L2 ++ ---help--- ++ Say Y here if you want to connect this type of FM transmitter ++ to your computer's USB port. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called radio-keene. ++ + config RADIO_TEA5764 + tristate "TEA5764 I2C FM radio support" + depends on I2C && VIDEO_V4L2 +@@ -167,6 +177,10 @@ menuconfig V4L_RADIO_ISA_DRIVERS + + if V4L_RADIO_ISA_DRIVERS + ++config RADIO_ISA ++ depends on ISA ++ tristate ++ + config RADIO_CADET + tristate "ADS Cadet AM/FM Tuner" + depends on ISA && VIDEO_V4L2 +@@ -174,20 +188,13 @@ config RADIO_CADET + Choose Y here if you have one of these AM/FM radio cards, and then + fill in the port address below. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . +- +- Further documentation on this driver can be found on the WWW at +- . +- + To compile this driver as a module, choose M here: the + module will be called radio-cadet. + + config RADIO_RTRACK + tristate "AIMSlab RadioTrack (aka RadioReveal) support" + depends on ISA && VIDEO_V4L2 ++ select RADIO_ISA + ---help--- + Choose Y here if you have one of these FM radio cards, and then fill + in the port address below. +@@ -201,11 +208,7 @@ config RADIO_RTRACK + You must also pass the module a suitable io parameter, 0x248 has + been reported to be used by these cards. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . More information is +- contained in the file ++ More information is contained in the file + . + + To compile this driver as a module, choose M here: the +@@ -214,7 +217,7 @@ config RADIO_RTRACK + config RADIO_RTRACK_PORT + hex "RadioTrack i/o port (0x20f or 0x30f)" + depends on RADIO_RTRACK=y +- default "20f" ++ default "30f" + help + Enter either 0x30f or 0x20f here. The card default is 0x30f, if you + haven't changed the jumper setting on the card. +@@ -222,14 +225,14 @@ config RADIO_RTRACK_PORT + config RADIO_RTRACK2 + tristate "AIMSlab RadioTrack II support" + depends on ISA && VIDEO_V4L2 ++ select RADIO_ISA + ---help--- + Choose Y here if you have this FM radio card, and then fill in the + port address below. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . ++ Note: this driver hasn't been tested since a long time due to lack ++ of hardware. If you have this hardware, then please contact the ++ linux-media mailinglist. + + To compile this driver as a module, choose M here: the + module will be called radio-rtrack2. +@@ -245,15 +248,11 @@ config RADIO_RTRACK2_PORT + config RADIO_AZTECH + tristate "Aztech/Packard Bell Radio" + depends on ISA && VIDEO_V4L2 ++ select RADIO_ISA + ---help--- + Choose Y here if you have one of these FM radio cards, and then fill + in the port address below. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . +- + To compile this driver as a module, choose M here: the + module will be called radio-aztech. + +@@ -269,6 +268,7 @@ config RADIO_AZTECH_PORT + config RADIO_GEMTEK + tristate "GemTek Radio card (or compatible) support" + depends on ISA && VIDEO_V4L2 ++ select RADIO_ISA + ---help--- + Choose Y here if you have this FM radio card, and then fill in the + I/O port address and settings below. The following cards either have +@@ -278,23 +278,21 @@ config RADIO_GEMTEK + - Typhoon Radio card (some models) + - Hama Radio card + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . +- + To compile this driver as a module, choose M here: the + module will be called radio-gemtek. + + config RADIO_GEMTEK_PORT +- hex "Fixed I/O port (0x20c, 0x30c, 0x24c, 0x34c, 0c24c or 0x28c)" ++ hex "Fixed I/O port (0x20c, 0x30c, 0x24c, 0x34c, 0x248 or 0x28c)" + depends on RADIO_GEMTEK=y + default "34c" + help +- Enter either 0x20c, 0x30c, 0x24c or 0x34c here. The card default is +- 0x34c, if you haven't changed the jumper setting on the card. On +- Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the I/O ++ Enter either 0x20c, 0x30c, 0x24c, 0x34c, 0x248 or 0x28c here. The ++ card default is 0x34c, if you haven't changed the jumper setting ++ on the card. ++ ++ On Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the I/O + port is 0x20c, 0x248 or 0x28c. ++ + If automatic I/O port probing is enabled this port will be used only + in case of automatic probing failure, ie. as a fallback. + +@@ -318,11 +316,6 @@ config RADIO_MIROPCM20 + sound card driver "Miro miroSOUND PCM1pro/PCM12/PCM20radio" as this + is required for the radio-miropcm20. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . +- + To compile this driver as a module, choose M here: the + module will be called radio-miropcm20. + +@@ -332,11 +325,6 @@ config RADIO_SF16FMI + ---help--- + Choose Y here if you have one of these FM radio cards. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . +- + To compile this driver as a module, choose M here: the + module will be called radio-sf16fmi. + +@@ -346,50 +334,35 @@ config RADIO_SF16FMR2 + ---help--- + Choose Y here if you have one of these FM radio cards. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found on the WWW at +- . +- + To compile this driver as a module, choose M here: the + module will be called radio-sf16fmr2. + + config RADIO_TERRATEC + tristate "TerraTec ActiveRadio ISA Standalone" + depends on ISA && VIDEO_V4L2 ++ select RADIO_ISA + ---help--- +- Choose Y here if you have this FM radio card, and then fill in the +- port address below. (TODO) +- +- Note: This driver is in its early stages. Right now volume and +- frequency control and muting works at least for me, but +- unfortunately I have not found anybody who wants to use this card +- with Linux. So if it is this what YOU are trying to do right now, +- PLEASE DROP ME A NOTE!! Rolf Offermanns . ++ Choose Y here if you have this FM radio card. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . ++ Note: this driver hasn't been tested since a long time due to lack ++ of hardware. If you have this hardware, then please contact the ++ linux-media mailinglist. + + To compile this driver as a module, choose M here: the + module will be called radio-terratec. + +-config RADIO_TERRATEC_PORT +- hex "Terratec i/o port (normally 0x590)" +- depends on RADIO_TERRATEC=y +- default "590" +- help +- Fill in the I/O port of your TerraTec FM radio card. If unsure, go +- with the default. +- + config RADIO_TRUST + tristate "Trust FM radio card" + depends on ISA && VIDEO_V4L2 ++ select RADIO_ISA + help + This is a driver for the Trust FM radio cards. Say Y if you have + such a card and want to use it under Linux. + ++ Note: this driver hasn't been tested since a long time due to lack ++ of hardware. If you have this hardware, then please contact the ++ linux-media mailinglist. ++ + To compile this driver as a module, choose M here: the + module will be called radio-trust. + +@@ -404,14 +377,14 @@ config RADIO_TRUST_PORT + config RADIO_TYPHOON + tristate "Typhoon Radio (a.k.a. EcoRadio)" + depends on ISA && VIDEO_V4L2 ++ select RADIO_ISA + ---help--- + Choose Y here if you have one of these FM radio cards, and then fill + in the port address and the frequency used for muting below. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . ++ Note: this driver hasn't been tested since a long time due to lack ++ of hardware. If you have this hardware, then please contact the ++ linux-media mailinglist. + + To compile this driver as a module, choose M here: the + module will be called radio-typhoon. +@@ -438,14 +411,14 @@ config RADIO_TYPHOON_MUTEFREQ + config RADIO_ZOLTRIX + tristate "Zoltrix Radio" + depends on ISA && VIDEO_V4L2 ++ select RADIO_ISA + ---help--- + Choose Y here if you have one of these FM radio cards, and then fill + in the port address below. + +- In order to control your radio card, you will need to use programs +- that are compatible with the Video For Linux API. Information on +- this API and pointers to "v4l" programs may be found at +- . ++ Note: this driver hasn't been tested since a long time due to lack ++ of hardware. If you have this hardware, then please contact the ++ linux-media mailinglist. + + To compile this driver as a module, choose M here: the + module will be called radio-zoltrix. +Index: linux-3.3.x86_64/drivers/media/radio/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/Makefile ++++ linux-3.3.x86_64/drivers/media/radio/Makefile +@@ -2,6 +2,7 @@ + # Makefile for the kernel character device drivers. + # + ++obj-$(CONFIG_RADIO_ISA) += radio-isa.o + obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o + obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o + obj-$(CONFIG_RADIO_SF16FMI) += radio-sf16fmi.o +@@ -20,6 +21,7 @@ obj-$(CONFIG_RADIO_MIROPCM20) += radio-m + obj-$(CONFIG_USB_DSBR) += dsbr100.o + obj-$(CONFIG_RADIO_SI470X) += si470x/ + obj-$(CONFIG_USB_MR800) += radio-mr800.o ++obj-$(CONFIG_USB_KEENE) += radio-keene.o + obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o + obj-$(CONFIG_RADIO_SAA7706H) += saa7706h.o + obj-$(CONFIG_RADIO_TEF6862) += tef6862.o +Index: linux-3.3.x86_64/drivers/media/radio/radio-keene.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/radio/radio-keene.c +@@ -0,0 +1,427 @@ ++/* ++ * Copyright (c) 2012 Hans Verkuil ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++/* kernel includes */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* driver and module definitions */ ++MODULE_AUTHOR("Hans Verkuil "); ++MODULE_DESCRIPTION("Keene FM Transmitter driver"); ++MODULE_LICENSE("GPL"); ++ ++/* Actually, it advertises itself as a Logitech */ ++#define USB_KEENE_VENDOR 0x046d ++#define USB_KEENE_PRODUCT 0x0a0e ++ ++/* Probably USB_TIMEOUT should be modified in module parameter */ ++#define BUFFER_LENGTH 8 ++#define USB_TIMEOUT 500 ++ ++/* Frequency limits in MHz */ ++#define FREQ_MIN 76U ++#define FREQ_MAX 108U ++#define FREQ_MUL 16000U ++ ++/* USB Device ID List */ ++static struct usb_device_id usb_keene_device_table[] = { ++ {USB_DEVICE_AND_INTERFACE_INFO(USB_KEENE_VENDOR, USB_KEENE_PRODUCT, ++ USB_CLASS_HID, 0, 0) }, ++ { } /* Terminating entry */ ++}; ++ ++MODULE_DEVICE_TABLE(usb, usb_keene_device_table); ++ ++struct keene_device { ++ struct usb_device *usbdev; ++ struct usb_interface *intf; ++ struct video_device vdev; ++ struct v4l2_device v4l2_dev; ++ struct v4l2_ctrl_handler hdl; ++ struct mutex lock; ++ ++ u8 *buffer; ++ unsigned curfreq; ++ u8 tx; ++ u8 pa; ++ bool stereo; ++ bool muted; ++ bool preemph_75_us; ++}; ++ ++static inline struct keene_device *to_keene_dev(struct v4l2_device *v4l2_dev) ++{ ++ return container_of(v4l2_dev, struct keene_device, v4l2_dev); ++} ++ ++/* Set frequency (if non-0), PA, mute and turn on/off the FM transmitter. */ ++static int keene_cmd_main(struct keene_device *radio, unsigned freq, bool play) ++{ ++ unsigned short freq_send = freq ? (freq - 76 * 16000) / 800 : 0; ++ int ret; ++ ++ radio->buffer[0] = 0x00; ++ radio->buffer[1] = 0x50; ++ radio->buffer[2] = (freq_send >> 8) & 0xff; ++ radio->buffer[3] = freq_send & 0xff; ++ radio->buffer[4] = radio->pa; ++ /* If bit 4 is set, then tune to the frequency. ++ If bit 3 is set, then unmute; if bit 2 is set, then mute. ++ If bit 1 is set, then enter idle mode; if bit 0 is set, ++ then enter transit mode. ++ */ ++ radio->buffer[5] = (radio->muted ? 4 : 8) | (play ? 1 : 2) | ++ (freq ? 0x10 : 0); ++ radio->buffer[6] = 0x00; ++ radio->buffer[7] = 0x00; ++ ++ ret = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0), ++ 9, 0x21, 0x200, 2, radio->buffer, BUFFER_LENGTH, USB_TIMEOUT); ++ ++ if (ret < 0) { ++ dev_warn(&radio->vdev.dev, "%s failed (%d)\n", __func__, ret); ++ return ret; ++ } ++ if (freq) ++ radio->curfreq = freq; ++ return 0; ++} ++ ++/* Set TX, stereo and preemphasis mode (50 us vs 75 us). */ ++static int keene_cmd_set(struct keene_device *radio) ++{ ++ int ret; ++ ++ radio->buffer[0] = 0x00; ++ radio->buffer[1] = 0x51; ++ radio->buffer[2] = radio->tx; ++ /* If bit 0 is set, then transmit mono, otherwise stereo. ++ If bit 2 is set, then enable 75 us preemphasis, otherwise ++ it is 50 us. */ ++ radio->buffer[3] = (!radio->stereo) | (radio->preemph_75_us ? 4 : 0); ++ radio->buffer[4] = 0x00; ++ radio->buffer[5] = 0x00; ++ radio->buffer[6] = 0x00; ++ radio->buffer[7] = 0x00; ++ ++ ret = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0), ++ 9, 0x21, 0x200, 2, radio->buffer, BUFFER_LENGTH, USB_TIMEOUT); ++ ++ if (ret < 0) { ++ dev_warn(&radio->vdev.dev, "%s failed (%d)\n", __func__, ret); ++ return ret; ++ } ++ return 0; ++} ++ ++/* Handle unplugging the device. ++ * We call video_unregister_device in any case. ++ * The last function called in this procedure is ++ * usb_keene_device_release. ++ */ ++static void usb_keene_disconnect(struct usb_interface *intf) ++{ ++ struct keene_device *radio = to_keene_dev(usb_get_intfdata(intf)); ++ ++ v4l2_device_get(&radio->v4l2_dev); ++ mutex_lock(&radio->lock); ++ usb_set_intfdata(intf, NULL); ++ video_unregister_device(&radio->vdev); ++ v4l2_device_disconnect(&radio->v4l2_dev); ++ mutex_unlock(&radio->lock); ++ v4l2_device_put(&radio->v4l2_dev); ++} ++ ++static int vidioc_querycap(struct file *file, void *priv, ++ struct v4l2_capability *v) ++{ ++ struct keene_device *radio = video_drvdata(file); ++ ++ strlcpy(v->driver, "radio-keene", sizeof(v->driver)); ++ strlcpy(v->card, "Keene FM Transmitter", sizeof(v->card)); ++ usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info)); ++ v->device_caps = V4L2_CAP_RADIO | V4L2_CAP_MODULATOR; ++ v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; ++ return 0; ++} ++ ++static int vidioc_g_modulator(struct file *file, void *priv, ++ struct v4l2_modulator *v) ++{ ++ struct keene_device *radio = video_drvdata(file); ++ ++ if (v->index > 0) ++ return -EINVAL; ++ ++ strlcpy(v->name, "FM", sizeof(v->name)); ++ v->rangelow = FREQ_MIN * FREQ_MUL; ++ v->rangehigh = FREQ_MAX * FREQ_MUL; ++ v->txsubchans = radio->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; ++ v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; ++ return 0; ++} ++ ++static int vidioc_s_modulator(struct file *file, void *priv, ++ struct v4l2_modulator *v) ++{ ++ struct keene_device *radio = video_drvdata(file); ++ ++ if (v->index > 0) ++ return -EINVAL; ++ ++ radio->stereo = (v->txsubchans == V4L2_TUNER_SUB_STEREO); ++ return keene_cmd_set(radio); ++} ++ ++static int vidioc_s_frequency(struct file *file, void *priv, ++ struct v4l2_frequency *f) ++{ ++ struct keene_device *radio = video_drvdata(file); ++ ++ if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) ++ return -EINVAL; ++ f->frequency = clamp(f->frequency, ++ FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL); ++ return keene_cmd_main(radio, f->frequency, true); ++} ++ ++static int vidioc_g_frequency(struct file *file, void *priv, ++ struct v4l2_frequency *f) ++{ ++ struct keene_device *radio = video_drvdata(file); ++ ++ if (f->tuner != 0) ++ return -EINVAL; ++ f->type = V4L2_TUNER_RADIO; ++ f->frequency = radio->curfreq; ++ return 0; ++} ++ ++static int keene_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ static const u8 db2tx[] = { ++ /* -15, -12, -9, -6, -3, 0 dB */ ++ 0x03, 0x13, 0x02, 0x12, 0x22, 0x32, ++ /* 3, 6, 9, 12, 15, 18 dB */ ++ 0x21, 0x31, 0x20, 0x30, 0x40, 0x50 ++ }; ++ struct keene_device *radio = ++ container_of(ctrl->handler, struct keene_device, hdl); ++ ++ switch (ctrl->id) { ++ case V4L2_CID_AUDIO_MUTE: ++ radio->muted = ctrl->val; ++ return keene_cmd_main(radio, 0, true); ++ ++ case V4L2_CID_TUNE_POWER_LEVEL: ++ /* To go from dBuV to the register value we apply the ++ following formula: */ ++ radio->pa = (ctrl->val - 71) * 100 / 62; ++ return keene_cmd_main(radio, 0, true); ++ ++ case V4L2_CID_TUNE_PREEMPHASIS: ++ radio->preemph_75_us = ctrl->val == V4L2_PREEMPHASIS_75_uS; ++ return keene_cmd_set(radio); ++ ++ case V4L2_CID_AUDIO_COMPRESSION_GAIN: ++ radio->tx = db2tx[(ctrl->val - ctrl->minimum) / ctrl->step]; ++ return keene_cmd_set(radio); ++ } ++ return -EINVAL; ++} ++ ++static int vidioc_subscribe_event(struct v4l2_fh *fh, ++ struct v4l2_event_subscription *sub) ++{ ++ switch (sub->type) { ++ case V4L2_EVENT_CTRL: ++ return v4l2_event_subscribe(fh, sub, 0); ++ default: ++ return -EINVAL; ++ } ++} ++ ++ ++/* File system interface */ ++static const struct v4l2_file_operations usb_keene_fops = { ++ .owner = THIS_MODULE, ++ .open = v4l2_fh_open, ++ .release = v4l2_fh_release, ++ .poll = v4l2_ctrl_poll, ++ .unlocked_ioctl = video_ioctl2, ++}; ++ ++static const struct v4l2_ctrl_ops keene_ctrl_ops = { ++ .s_ctrl = keene_s_ctrl, ++}; ++ ++static const struct v4l2_ioctl_ops usb_keene_ioctl_ops = { ++ .vidioc_querycap = vidioc_querycap, ++ .vidioc_g_modulator = vidioc_g_modulator, ++ .vidioc_s_modulator = vidioc_s_modulator, ++ .vidioc_g_frequency = vidioc_g_frequency, ++ .vidioc_s_frequency = vidioc_s_frequency, ++ .vidioc_log_status = v4l2_ctrl_log_status, ++ .vidioc_subscribe_event = vidioc_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, ++}; ++ ++static void usb_keene_video_device_release(struct v4l2_device *v4l2_dev) ++{ ++ struct keene_device *radio = to_keene_dev(v4l2_dev); ++ ++ /* free rest memory */ ++ v4l2_ctrl_handler_free(&radio->hdl); ++ kfree(radio->buffer); ++ kfree(radio); ++} ++ ++/* check if the device is present and register with v4l and usb if it is */ ++static int usb_keene_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ struct usb_device *dev = interface_to_usbdev(intf); ++ struct keene_device *radio; ++ struct v4l2_ctrl_handler *hdl; ++ int retval = 0; ++ ++ /* ++ * The Keene FM transmitter USB device has the same USB ID as ++ * the Logitech AudioHub Speaker, but it should ignore the hid. ++ * Check if the name is that of the Keene device. ++ * If not, then someone connected the AudioHub and we shouldn't ++ * attempt to handle this driver. ++ * For reference: the product name of the AudioHub is ++ * "AudioHub Speaker". ++ */ ++ if (dev->product && strcmp(dev->product, "B-LINK USB Audio ")) ++ return -ENODEV; ++ ++ radio = kzalloc(sizeof(struct keene_device), GFP_KERNEL); ++ if (radio) ++ radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL); ++ ++ if (!radio || !radio->buffer) { ++ dev_err(&intf->dev, "kmalloc for keene_device failed\n"); ++ kfree(radio); ++ retval = -ENOMEM; ++ goto err; ++ } ++ ++ hdl = &radio->hdl; ++ v4l2_ctrl_handler_init(hdl, 4); ++ v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_AUDIO_MUTE, ++ 0, 1, 1, 0); ++ v4l2_ctrl_new_std_menu(hdl, &keene_ctrl_ops, V4L2_CID_TUNE_PREEMPHASIS, ++ V4L2_PREEMPHASIS_75_uS, 1, V4L2_PREEMPHASIS_50_uS); ++ v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_TUNE_POWER_LEVEL, ++ 84, 118, 1, 118); ++ v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_AUDIO_COMPRESSION_GAIN, ++ -15, 18, 3, 0); ++ radio->pa = 118; ++ radio->tx = 0x32; ++ radio->stereo = true; ++ radio->curfreq = 95.16 * FREQ_MUL; ++ if (hdl->error) { ++ retval = hdl->error; ++ ++ v4l2_ctrl_handler_free(hdl); ++ goto err_v4l2; ++ } ++ retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev); ++ if (retval < 0) { ++ dev_err(&intf->dev, "couldn't register v4l2_device\n"); ++ goto err_v4l2; ++ } ++ ++ mutex_init(&radio->lock); ++ ++ radio->v4l2_dev.ctrl_handler = hdl; ++ radio->v4l2_dev.release = usb_keene_video_device_release; ++ strlcpy(radio->vdev.name, radio->v4l2_dev.name, ++ sizeof(radio->vdev.name)); ++ radio->vdev.v4l2_dev = &radio->v4l2_dev; ++ radio->vdev.fops = &usb_keene_fops; ++ radio->vdev.ioctl_ops = &usb_keene_ioctl_ops; ++ radio->vdev.lock = &radio->lock; ++ radio->vdev.release = video_device_release_empty; ++ ++ radio->usbdev = interface_to_usbdev(intf); ++ radio->intf = intf; ++ usb_set_intfdata(intf, &radio->v4l2_dev); ++ ++ video_set_drvdata(&radio->vdev, radio); ++ set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags); ++ ++ retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO, -1); ++ if (retval < 0) { ++ dev_err(&intf->dev, "could not register video device\n"); ++ goto err_vdev; ++ } ++ v4l2_ctrl_handler_setup(hdl); ++ dev_info(&intf->dev, "V4L2 device registered as %s\n", ++ video_device_node_name(&radio->vdev)); ++ return 0; ++ ++err_vdev: ++ v4l2_device_unregister(&radio->v4l2_dev); ++err_v4l2: ++ kfree(radio->buffer); ++ kfree(radio); ++err: ++ return retval; ++} ++ ++/* USB subsystem interface */ ++static struct usb_driver usb_keene_driver = { ++ .name = "radio-keene", ++ .probe = usb_keene_probe, ++ .disconnect = usb_keene_disconnect, ++ .id_table = usb_keene_device_table, ++}; ++ ++static int __init keene_init(void) ++{ ++ int retval = usb_register(&usb_keene_driver); ++ ++ if (retval) ++ pr_err(KBUILD_MODNAME ++ ": usb_register failed. Error number %d\n", retval); ++ ++ return retval; ++} ++ ++static void __exit keene_exit(void) ++{ ++ usb_deregister(&usb_keene_driver); ++} ++ ++module_init(keene_init); ++module_exit(keene_exit); ++ +Index: linux-3.3.x86_64/drivers/media/rc/fintek-cir.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/fintek-cir.c ++++ linux-3.3.x86_64/drivers/media/rc/fintek-cir.c +@@ -117,7 +117,7 @@ static u8 fintek_cir_reg_read(struct fin + static void cir_dump_regs(struct fintek_dev *fintek) + { + fintek_config_mode_enable(fintek); +- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); ++ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); + + pr_reg("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME); + pr_reg(" * CR CIR BASE ADDR: 0x%x\n", +@@ -143,7 +143,7 @@ static int fintek_hw_detect(struct finte + u8 chip_major, chip_minor; + u8 vendor_major, vendor_minor; + u8 portsel, ir_class; +- u16 vendor; ++ u16 vendor, chip; + int ret = 0; + + fintek_config_mode_enable(fintek); +@@ -176,6 +176,7 @@ static int fintek_hw_detect(struct finte + + chip_major = fintek_cr_read(fintek, GCR_CHIP_ID_HI); + chip_minor = fintek_cr_read(fintek, GCR_CHIP_ID_LO); ++ chip = chip_major << 8 | chip_minor; + + vendor_major = fintek_cr_read(fintek, GCR_VENDOR_ID_HI); + vendor_minor = fintek_cr_read(fintek, GCR_VENDOR_ID_LO); +@@ -192,6 +193,15 @@ static int fintek_hw_detect(struct finte + fintek->chip_major = chip_major; + fintek->chip_minor = chip_minor; + fintek->chip_vendor = vendor; ++ ++ /* ++ * Newer reviews of this chipset uses port 8 instead of 5 ++ */ ++ if ((chip != 0x0408) || (chip != 0x0804)) ++ fintek->logical_dev_cir = LOGICAL_DEV_CIR_REV2; ++ else ++ fintek->logical_dev_cir = LOGICAL_DEV_CIR_REV1; ++ + spin_unlock_irqrestore(&fintek->fintek_lock, flags); + + return ret; +@@ -200,7 +210,7 @@ static int fintek_hw_detect(struct finte + static void fintek_cir_ldev_init(struct fintek_dev *fintek) + { + /* Select CIR logical device and enable */ +- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); ++ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); + fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); + + /* Write allocated CIR address and IRQ information to hardware */ +@@ -381,7 +391,7 @@ static irqreturn_t fintek_cir_isr(int ir + fit_dbg_verbose("%s firing", __func__); + + fintek_config_mode_enable(fintek); +- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); ++ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); + fintek_config_mode_disable(fintek); + + /* +@@ -422,7 +432,7 @@ static void fintek_enable_cir(struct fin + fintek_config_mode_enable(fintek); + + /* enable the CIR logical device */ +- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); ++ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); + fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); + + fintek_config_mode_disable(fintek); +@@ -439,7 +449,7 @@ static void fintek_disable_cir(struct fi + fintek_config_mode_enable(fintek); + + /* disable the CIR logical device */ +- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); ++ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); + fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN); + + fintek_config_mode_disable(fintek); +@@ -611,7 +621,7 @@ static int fintek_suspend(struct pnp_dev + fintek_config_mode_enable(fintek); + + /* disable cir logical dev */ +- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); ++ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); + fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN); + + fintek_config_mode_disable(fintek); +@@ -634,7 +644,7 @@ static int fintek_resume(struct pnp_dev + + /* Enable CIR logical device */ + fintek_config_mode_enable(fintek); +- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); ++ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); + fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); + + fintek_config_mode_disable(fintek); +Index: linux-3.3.x86_64/drivers/media/rc/fintek-cir.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/fintek-cir.h ++++ linux-3.3.x86_64/drivers/media/rc/fintek-cir.h +@@ -88,6 +88,7 @@ struct fintek_dev { + u8 chip_major; + u8 chip_minor; + u16 chip_vendor; ++ u8 logical_dev_cir; + + /* hardware features */ + bool hw_learning_capable; +@@ -172,7 +173,8 @@ struct fintek_dev { + #define LOGICAL_DEV_ENABLE 0x01 + + /* Logical device number of the CIR function */ +-#define LOGICAL_DEV_CIR 0x05 ++#define LOGICAL_DEV_CIR_REV1 0x05 ++#define LOGICAL_DEV_CIR_REV2 0x08 + + /* CIR Logical Device (LDN 0x08) config registers */ + #define CIR_CR_COMMAND_INDEX 0x04 +Index: linux-3.3.x86_64/drivers/media/radio/radio-isa.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/radio/radio-isa.c +@@ -0,0 +1,340 @@ ++/* ++ * Framework for ISA radio drivers. ++ * This takes care of all the V4L2 scaffolding, allowing the ISA drivers ++ * to concentrate on the actual hardware operation. ++ * ++ * Copyright (C) 2012 Hans Verkuil ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "radio-isa.h" ++ ++MODULE_AUTHOR("Hans Verkuil"); ++MODULE_DESCRIPTION("A framework for ISA radio drivers."); ++MODULE_LICENSE("GPL"); ++ ++#define FREQ_LOW (87U * 16000U) ++#define FREQ_HIGH (108U * 16000U) ++ ++static int radio_isa_querycap(struct file *file, void *priv, ++ struct v4l2_capability *v) ++{ ++ struct radio_isa_card *isa = video_drvdata(file); ++ ++ strlcpy(v->driver, isa->drv->driver.driver.name, sizeof(v->driver)); ++ strlcpy(v->card, isa->drv->card, sizeof(v->card)); ++ snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name); ++ ++ v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; ++ v->device_caps = v->capabilities | V4L2_CAP_DEVICE_CAPS; ++ return 0; ++} ++ ++static int radio_isa_g_tuner(struct file *file, void *priv, ++ struct v4l2_tuner *v) ++{ ++ struct radio_isa_card *isa = video_drvdata(file); ++ const struct radio_isa_ops *ops = isa->drv->ops; ++ ++ if (v->index > 0) ++ return -EINVAL; ++ ++ strlcpy(v->name, "FM", sizeof(v->name)); ++ v->type = V4L2_TUNER_RADIO; ++ v->rangelow = FREQ_LOW; ++ v->rangehigh = FREQ_HIGH; ++ v->capability = V4L2_TUNER_CAP_LOW; ++ if (isa->drv->has_stereo) ++ v->capability |= V4L2_TUNER_CAP_STEREO; ++ ++ if (ops->g_rxsubchans) ++ v->rxsubchans = ops->g_rxsubchans(isa); ++ else ++ v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; ++ v->audmode = isa->stereo ? V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO; ++ if (ops->g_signal) ++ v->signal = ops->g_signal(isa); ++ else ++ v->signal = (v->rxsubchans & V4L2_TUNER_SUB_STEREO) ? ++ 0xffff : 0; ++ return 0; ++} ++ ++static int radio_isa_s_tuner(struct file *file, void *priv, ++ struct v4l2_tuner *v) ++{ ++ struct radio_isa_card *isa = video_drvdata(file); ++ const struct radio_isa_ops *ops = isa->drv->ops; ++ ++ if (v->index) ++ return -EINVAL; ++ if (ops->s_stereo) { ++ isa->stereo = (v->audmode == V4L2_TUNER_MODE_STEREO); ++ return ops->s_stereo(isa, isa->stereo); ++ } ++ return 0; ++} ++ ++static int radio_isa_s_frequency(struct file *file, void *priv, ++ struct v4l2_frequency *f) ++{ ++ struct radio_isa_card *isa = video_drvdata(file); ++ int res; ++ ++ if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) ++ return -EINVAL; ++ f->frequency = clamp(f->frequency, FREQ_LOW, FREQ_HIGH); ++ res = isa->drv->ops->s_frequency(isa, f->frequency); ++ if (res == 0) ++ isa->freq = f->frequency; ++ return res; ++} ++ ++static int radio_isa_g_frequency(struct file *file, void *priv, ++ struct v4l2_frequency *f) ++{ ++ struct radio_isa_card *isa = video_drvdata(file); ++ ++ if (f->tuner != 0) ++ return -EINVAL; ++ f->type = V4L2_TUNER_RADIO; ++ f->frequency = isa->freq; ++ return 0; ++} ++ ++static int radio_isa_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct radio_isa_card *isa = ++ container_of(ctrl->handler, struct radio_isa_card, hdl); ++ ++ switch (ctrl->id) { ++ case V4L2_CID_AUDIO_MUTE: ++ return isa->drv->ops->s_mute_volume(isa, ctrl->val, ++ isa->volume ? isa->volume->val : 0); ++ } ++ return -EINVAL; ++} ++ ++static int radio_isa_log_status(struct file *file, void *priv) ++{ ++ struct radio_isa_card *isa = video_drvdata(file); ++ ++ v4l2_info(&isa->v4l2_dev, "I/O Port = 0x%03x\n", isa->io); ++ v4l2_ctrl_handler_log_status(&isa->hdl, isa->v4l2_dev.name); ++ return 0; ++} ++ ++static int radio_isa_subscribe_event(struct v4l2_fh *fh, ++ struct v4l2_event_subscription *sub) ++{ ++ if (sub->type == V4L2_EVENT_CTRL) ++ return v4l2_event_subscribe(fh, sub, 0); ++ return -EINVAL; ++} ++ ++static const struct v4l2_ctrl_ops radio_isa_ctrl_ops = { ++ .s_ctrl = radio_isa_s_ctrl, ++}; ++ ++static const struct v4l2_file_operations radio_isa_fops = { ++ .owner = THIS_MODULE, ++ .open = v4l2_fh_open, ++ .release = v4l2_fh_release, ++ .poll = v4l2_ctrl_poll, ++ .unlocked_ioctl = video_ioctl2, ++}; ++ ++static const struct v4l2_ioctl_ops radio_isa_ioctl_ops = { ++ .vidioc_querycap = radio_isa_querycap, ++ .vidioc_g_tuner = radio_isa_g_tuner, ++ .vidioc_s_tuner = radio_isa_s_tuner, ++ .vidioc_g_frequency = radio_isa_g_frequency, ++ .vidioc_s_frequency = radio_isa_s_frequency, ++ .vidioc_log_status = radio_isa_log_status, ++ .vidioc_subscribe_event = radio_isa_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, ++}; ++ ++int radio_isa_match(struct device *pdev, unsigned int dev) ++{ ++ struct radio_isa_driver *drv = pdev->platform_data; ++ ++ return drv->probe || drv->io_params[dev] >= 0; ++} ++EXPORT_SYMBOL_GPL(radio_isa_match); ++ ++static bool radio_isa_valid_io(const struct radio_isa_driver *drv, int io) ++{ ++ int i; ++ ++ for (i = 0; i < drv->num_of_io_ports; i++) ++ if (drv->io_ports[i] == io) ++ return true; ++ return false; ++} ++ ++int radio_isa_probe(struct device *pdev, unsigned int dev) ++{ ++ struct radio_isa_driver *drv = pdev->platform_data; ++ const struct radio_isa_ops *ops = drv->ops; ++ struct v4l2_device *v4l2_dev; ++ struct radio_isa_card *isa; ++ int res; ++ ++ isa = drv->ops->alloc(); ++ if (isa == NULL) ++ return -ENOMEM; ++ dev_set_drvdata(pdev, isa); ++ isa->drv = drv; ++ isa->io = drv->io_params[dev]; ++ v4l2_dev = &isa->v4l2_dev; ++ strlcpy(v4l2_dev->name, dev_name(pdev), sizeof(v4l2_dev->name)); ++ ++ if (drv->probe && ops->probe) { ++ int i; ++ ++ for (i = 0; i < drv->num_of_io_ports; ++i) { ++ int io = drv->io_ports[i]; ++ ++ if (request_region(io, drv->region_size, v4l2_dev->name)) { ++ bool found = ops->probe(isa, io); ++ ++ release_region(io, drv->region_size); ++ if (found) { ++ isa->io = io; ++ break; ++ } ++ } ++ } ++ } ++ ++ if (!radio_isa_valid_io(drv, isa->io)) { ++ int i; ++ ++ if (isa->io < 0) ++ return -ENODEV; ++ v4l2_err(v4l2_dev, "you must set an I/O address with io=0x%03x", ++ drv->io_ports[0]); ++ for (i = 1; i < drv->num_of_io_ports; i++) ++ printk(KERN_CONT "/0x%03x", drv->io_ports[i]); ++ printk(KERN_CONT ".\n"); ++ kfree(isa); ++ return -EINVAL; ++ } ++ ++ if (!request_region(isa->io, drv->region_size, v4l2_dev->name)) { ++ v4l2_err(v4l2_dev, "port 0x%x already in use\n", isa->io); ++ kfree(isa); ++ return -EBUSY; ++ } ++ ++ res = v4l2_device_register(pdev, v4l2_dev); ++ if (res < 0) { ++ v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); ++ goto err_dev_reg; ++ } ++ ++ v4l2_ctrl_handler_init(&isa->hdl, 1); ++ isa->mute = v4l2_ctrl_new_std(&isa->hdl, &radio_isa_ctrl_ops, ++ V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); ++ if (drv->max_volume) ++ isa->volume = v4l2_ctrl_new_std(&isa->hdl, &radio_isa_ctrl_ops, ++ V4L2_CID_AUDIO_VOLUME, 0, drv->max_volume, 1, ++ drv->max_volume); ++ v4l2_dev->ctrl_handler = &isa->hdl; ++ if (isa->hdl.error) { ++ res = isa->hdl.error; ++ v4l2_err(v4l2_dev, "Could not register controls\n"); ++ goto err_hdl; ++ } ++ if (drv->max_volume) ++ v4l2_ctrl_cluster(2, &isa->mute); ++ v4l2_dev->ctrl_handler = &isa->hdl; ++ ++ mutex_init(&isa->lock); ++ isa->vdev.lock = &isa->lock; ++ strlcpy(isa->vdev.name, v4l2_dev->name, sizeof(isa->vdev.name)); ++ isa->vdev.v4l2_dev = v4l2_dev; ++ isa->vdev.fops = &radio_isa_fops; ++ isa->vdev.ioctl_ops = &radio_isa_ioctl_ops; ++ isa->vdev.release = video_device_release_empty; ++ set_bit(V4L2_FL_USE_FH_PRIO, &isa->vdev.flags); ++ video_set_drvdata(&isa->vdev, isa); ++ isa->freq = FREQ_LOW; ++ isa->stereo = drv->has_stereo; ++ ++ if (ops->init) ++ res = ops->init(isa); ++ if (!res) ++ res = v4l2_ctrl_handler_setup(&isa->hdl); ++ if (!res) ++ res = ops->s_frequency(isa, isa->freq); ++ if (!res && ops->s_stereo) ++ res = ops->s_stereo(isa, isa->stereo); ++ if (res < 0) { ++ v4l2_err(v4l2_dev, "Could not setup card\n"); ++ goto err_node_reg; ++ } ++ res = video_register_device(&isa->vdev, VFL_TYPE_RADIO, ++ drv->radio_nr_params[dev]); ++ if (res < 0) { ++ v4l2_err(v4l2_dev, "Could not register device node\n"); ++ goto err_node_reg; ++ } ++ ++ v4l2_info(v4l2_dev, "Initialized radio card %s on port 0x%03x\n", ++ drv->card, isa->io); ++ return 0; ++ ++err_node_reg: ++ v4l2_ctrl_handler_free(&isa->hdl); ++err_hdl: ++ v4l2_device_unregister(&isa->v4l2_dev); ++err_dev_reg: ++ release_region(isa->io, drv->region_size); ++ kfree(isa); ++ return res; ++} ++EXPORT_SYMBOL_GPL(radio_isa_probe); ++ ++int radio_isa_remove(struct device *pdev, unsigned int dev) ++{ ++ struct radio_isa_card *isa = dev_get_drvdata(pdev); ++ const struct radio_isa_ops *ops = isa->drv->ops; ++ ++ ops->s_mute_volume(isa, true, isa->volume ? isa->volume->cur.val : 0); ++ video_unregister_device(&isa->vdev); ++ v4l2_ctrl_handler_free(&isa->hdl); ++ v4l2_device_unregister(&isa->v4l2_dev); ++ release_region(isa->io, isa->drv->region_size); ++ v4l2_info(&isa->v4l2_dev, "Removed radio card %s\n", isa->drv->card); ++ kfree(isa); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(radio_isa_remove); +Index: linux-3.3.x86_64/drivers/media/radio/radio-isa.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/radio/radio-isa.h +@@ -0,0 +1,105 @@ ++/* ++ * Framework for ISA radio drivers. ++ * This takes care of all the V4L2 scaffolding, allowing the ISA drivers ++ * to concentrate on the actual hardware operation. ++ * ++ * Copyright (C) 2012 Hans Verkuil ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#ifndef _RADIO_ISA_H_ ++#define _RADIO_ISA_H_ ++ ++#include ++#include ++#include ++#include ++ ++struct radio_isa_driver; ++struct radio_isa_ops; ++ ++/* Core structure for radio ISA cards */ ++struct radio_isa_card { ++ const struct radio_isa_driver *drv; ++ struct v4l2_device v4l2_dev; ++ struct v4l2_ctrl_handler hdl; ++ struct video_device vdev; ++ struct mutex lock; ++ const struct radio_isa_ops *ops; ++ struct { /* mute/volume cluster */ ++ struct v4l2_ctrl *mute; ++ struct v4l2_ctrl *volume; ++ }; ++ /* I/O port */ ++ int io; ++ ++ /* Card is in stereo audio mode */ ++ bool stereo; ++ /* Current frequency */ ++ u32 freq; ++}; ++ ++struct radio_isa_ops { ++ /* Allocate and initialize a radio_isa_card struct */ ++ struct radio_isa_card *(*alloc)(void); ++ /* Probe whether a card is present at the given port */ ++ bool (*probe)(struct radio_isa_card *isa, int io); ++ /* Special card initialization can be done here, this is called after ++ * the standard controls are registered, but before they are setup, ++ * thus allowing drivers to add their own controls here. */ ++ int (*init)(struct radio_isa_card *isa); ++ /* Set mute and volume. */ ++ int (*s_mute_volume)(struct radio_isa_card *isa, bool mute, int volume); ++ /* Set frequency */ ++ int (*s_frequency)(struct radio_isa_card *isa, u32 freq); ++ /* Set stereo/mono audio mode */ ++ int (*s_stereo)(struct radio_isa_card *isa, bool stereo); ++ /* Get rxsubchans value for VIDIOC_G_TUNER */ ++ u32 (*g_rxsubchans)(struct radio_isa_card *isa); ++ /* Get the signal strength for VIDIOC_G_TUNER */ ++ u32 (*g_signal)(struct radio_isa_card *isa); ++}; ++ ++/* Top level structure needed to instantiate the cards */ ++struct radio_isa_driver { ++ struct isa_driver driver; ++ const struct radio_isa_ops *ops; ++ /* The module_param_array with the specified I/O ports */ ++ int *io_params; ++ /* The module_param_array with the radio_nr values */ ++ int *radio_nr_params; ++ /* Whether we should probe for possible cards */ ++ bool probe; ++ /* The list of possible I/O ports */ ++ const int *io_ports; ++ /* The size of that list */ ++ int num_of_io_ports; ++ /* The region size to request */ ++ unsigned region_size; ++ /* The name of the card */ ++ const char *card; ++ /* Card can capture stereo audio */ ++ bool has_stereo; ++ /* The maximum volume for the volume control. If 0, then there ++ is no volume control possible. */ ++ int max_volume; ++}; ++ ++int radio_isa_match(struct device *pdev, unsigned int dev); ++int radio_isa_probe(struct device *pdev, unsigned int dev); ++int radio_isa_remove(struct device *pdev, unsigned int dev); ++ ++#endif +Index: linux-3.3.x86_64/drivers/media/radio/radio-aimslab.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-aimslab.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-aimslab.c +@@ -1,16 +1,13 @@ +-/* radiotrack (radioreveal) driver for Linux radio support +- * (c) 1997 M. Kirkwood ++/* ++ * AimsLab RadioTrack (aka RadioVeveal) driver ++ * ++ * Copyright 1997 M. Kirkwood ++ * ++ * Converted to the radio-isa framework by Hans Verkuil + * Converted to V4L2 API by Mauro Carvalho Chehab + * Converted to new API by Alan Cox + * Various bugfixes and enhancements by Russell Kroll + * +- * History: +- * 1999-02-24 Russell Kroll +- * Fine tuning/VIDEO_TUNER_LOW +- * Frequency range expanded to start at 87 MHz +- * +- * TODO: Allow for more than one of these foolish entities :-) +- * + * Notes on the hardware (reverse engineered from other peoples' + * reverse engineering of AIMS' code :-) + * +@@ -26,6 +23,7 @@ + * wait(a_wee_while); + * out(port, stop_changing_the_volume); + * ++ * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool. + */ + + #include /* Modules */ +@@ -34,401 +32,179 @@ + #include /* msleep */ + #include /* kernel radio structs */ + #include /* outb, outb_p */ ++#include + #include + #include ++#include ++#include "radio-isa.h" + +-MODULE_AUTHOR("M.Kirkwood"); ++MODULE_AUTHOR("M. Kirkwood"); + MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION("0.0.3"); ++MODULE_VERSION("1.0.0"); + + #ifndef CONFIG_RADIO_RTRACK_PORT + #define CONFIG_RADIO_RTRACK_PORT -1 + #endif + +-static int io = CONFIG_RADIO_RTRACK_PORT; +-static int radio_nr = -1; ++#define RTRACK_MAX 2 + +-module_param(io, int, 0); +-MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20f or 0x30f)"); +-module_param(radio_nr, int, 0); ++static int io[RTRACK_MAX] = { [0] = CONFIG_RADIO_RTRACK_PORT, ++ [1 ... (RTRACK_MAX - 1)] = -1 }; ++static int radio_nr[RTRACK_MAX] = { [0 ... (RTRACK_MAX - 1)] = -1 }; ++ ++module_param_array(io, int, NULL, 0444); ++MODULE_PARM_DESC(io, "I/O addresses of the RadioTrack card (0x20f or 0x30f)"); ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); + +-struct rtrack +-{ +- struct v4l2_device v4l2_dev; +- struct video_device vdev; +- int port; ++struct rtrack { ++ struct radio_isa_card isa; + int curvol; +- unsigned long curfreq; +- int muted; +- int io; +- struct mutex lock; + }; + +-static struct rtrack rtrack_card; +- +-/* local things */ +- +-static void rt_decvol(struct rtrack *rt) +-{ +- outb(0x58, rt->io); /* volume down + sigstr + on */ +- msleep(100); +- outb(0xd8, rt->io); /* volume steady + sigstr + on */ +-} +- +-static void rt_incvol(struct rtrack *rt) +-{ +- outb(0x98, rt->io); /* volume up + sigstr + on */ +- msleep(100); +- outb(0xd8, rt->io); /* volume steady + sigstr + on */ +-} +- +-static void rt_mute(struct rtrack *rt) +-{ +- rt->muted = 1; +- mutex_lock(&rt->lock); +- outb(0xd0, rt->io); /* volume steady, off */ +- mutex_unlock(&rt->lock); +-} +- +-static int rt_setvol(struct rtrack *rt, int vol) ++static struct radio_isa_card *rtrack_alloc(void) + { +- int i; +- +- mutex_lock(&rt->lock); +- +- if (vol == rt->curvol) { /* requested volume = current */ +- if (rt->muted) { /* user is unmuting the card */ +- rt->muted = 0; +- outb(0xd8, rt->io); /* enable card */ +- } +- mutex_unlock(&rt->lock); +- return 0; +- } +- +- if (vol == 0) { /* volume = 0 means mute the card */ +- outb(0x48, rt->io); /* volume down but still "on" */ +- msleep(2000); /* make sure it's totally down */ +- outb(0xd0, rt->io); /* volume steady, off */ +- rt->curvol = 0; /* track the volume state! */ +- mutex_unlock(&rt->lock); +- return 0; +- } +- +- rt->muted = 0; +- if (vol > rt->curvol) +- for (i = rt->curvol; i < vol; i++) +- rt_incvol(rt); +- else +- for (i = rt->curvol; i > vol; i--) +- rt_decvol(rt); ++ struct rtrack *rt = kzalloc(sizeof(struct rtrack), GFP_KERNEL); + +- rt->curvol = vol; +- mutex_unlock(&rt->lock); +- return 0; ++ if (rt) ++ rt->curvol = 0xff; ++ return rt ? &rt->isa : NULL; + } + +-/* the 128+64 on these outb's is to keep the volume stable while tuning +- * without them, the volume _will_ creep up with each frequency change +- * and bit 4 (+16) is to keep the signal strength meter enabled ++/* The 128+64 on these outb's is to keep the volume stable while tuning. ++ * Without them, the volume _will_ creep up with each frequency change ++ * and bit 4 (+16) is to keep the signal strength meter enabled. + */ + +-static void send_0_byte(struct rtrack *rt) ++static void send_0_byte(struct radio_isa_card *isa, int on) + { +- if (rt->curvol == 0 || rt->muted) { +- outb_p(128+64+16+ 1, rt->io); /* wr-enable + data low */ +- outb_p(128+64+16+2+1, rt->io); /* clock */ +- } +- else { +- outb_p(128+64+16+8+ 1, rt->io); /* on + wr-enable + data low */ +- outb_p(128+64+16+8+2+1, rt->io); /* clock */ +- } ++ outb_p(128+64+16+on+1, isa->io); /* wr-enable + data low */ ++ outb_p(128+64+16+on+2+1, isa->io); /* clock */ + msleep(1); + } + +-static void send_1_byte(struct rtrack *rt) ++static void send_1_byte(struct radio_isa_card *isa, int on) + { +- if (rt->curvol == 0 || rt->muted) { +- outb_p(128+64+16+4 +1, rt->io); /* wr-enable+data high */ +- outb_p(128+64+16+4+2+1, rt->io); /* clock */ +- } +- else { +- outb_p(128+64+16+8+4 +1, rt->io); /* on+wr-enable+data high */ +- outb_p(128+64+16+8+4+2+1, rt->io); /* clock */ +- } +- ++ outb_p(128+64+16+on+4+1, isa->io); /* wr-enable+data high */ ++ outb_p(128+64+16+on+4+2+1, isa->io); /* clock */ + msleep(1); + } + +-static int rt_setfreq(struct rtrack *rt, unsigned long freq) ++static int rtrack_s_frequency(struct radio_isa_card *isa, u32 freq) + { ++ int on = v4l2_ctrl_g_ctrl(isa->mute) ? 0 : 8; + int i; + +- mutex_lock(&rt->lock); /* Stop other ops interfering */ +- +- rt->curfreq = freq; +- +- /* now uses VIDEO_TUNER_LOW for fine tuning */ +- + freq += 171200; /* Add 10.7 MHz IF */ + freq /= 800; /* Convert to 50 kHz units */ + +- send_0_byte(rt); /* 0: LSB of frequency */ ++ send_0_byte(isa, on); /* 0: LSB of frequency */ + + for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ + if (freq & (1 << i)) +- send_1_byte(rt); ++ send_1_byte(isa, on); + else +- send_0_byte(rt); ++ send_0_byte(isa, on); + +- send_0_byte(rt); /* 14: test bit - always 0 */ +- send_0_byte(rt); /* 15: test bit - always 0 */ ++ send_0_byte(isa, on); /* 14: test bit - always 0 */ ++ send_0_byte(isa, on); /* 15: test bit - always 0 */ + +- send_0_byte(rt); /* 16: band data 0 - always 0 */ +- send_0_byte(rt); /* 17: band data 1 - always 0 */ +- send_0_byte(rt); /* 18: band data 2 - always 0 */ +- send_0_byte(rt); /* 19: time base - always 0 */ +- +- send_0_byte(rt); /* 20: spacing (0 = 25 kHz) */ +- send_1_byte(rt); /* 21: spacing (1 = 25 kHz) */ +- send_0_byte(rt); /* 22: spacing (0 = 25 kHz) */ +- send_1_byte(rt); /* 23: AM/FM (FM = 1, always) */ +- +- if (rt->curvol == 0 || rt->muted) +- outb(0xd0, rt->io); /* volume steady + sigstr */ +- else +- outb(0xd8, rt->io); /* volume steady + sigstr + on */ ++ send_0_byte(isa, on); /* 16: band data 0 - always 0 */ ++ send_0_byte(isa, on); /* 17: band data 1 - always 0 */ ++ send_0_byte(isa, on); /* 18: band data 2 - always 0 */ ++ send_0_byte(isa, on); /* 19: time base - always 0 */ + +- mutex_unlock(&rt->lock); ++ send_0_byte(isa, on); /* 20: spacing (0 = 25 kHz) */ ++ send_1_byte(isa, on); /* 21: spacing (1 = 25 kHz) */ ++ send_0_byte(isa, on); /* 22: spacing (0 = 25 kHz) */ ++ send_1_byte(isa, on); /* 23: AM/FM (FM = 1, always) */ + ++ outb(0xd0 + on, isa->io); /* volume steady + sigstr */ + return 0; + } + +-static int rt_getsigstr(struct rtrack *rt) ++static u32 rtrack_g_signal(struct radio_isa_card *isa) + { +- int sig = 1; +- +- mutex_lock(&rt->lock); +- if (inb(rt->io) & 2) /* bit set = no signal present */ +- sig = 0; +- mutex_unlock(&rt->lock); +- return sig; +-} +- +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- strlcpy(v->driver, "radio-aimslab", sizeof(v->driver)); +- strlcpy(v->card, "RadioTrack", sizeof(v->card)); +- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; +- return 0; +-} +- +-static int vidioc_g_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- struct rtrack *rt = video_drvdata(file); +- +- if (v->index > 0) +- return -EINVAL; +- +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- v->rangelow = 87 * 16000; +- v->rangehigh = 108 * 16000; +- v->rxsubchans = V4L2_TUNER_SUB_MONO; +- v->capability = V4L2_TUNER_CAP_LOW; +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->signal = 0xffff * rt_getsigstr(rt); +- return 0; ++ /* bit set = no signal present */ ++ return 0xffff * !(inb(isa->io) & 2); + } + +-static int vidioc_s_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) ++static int rtrack_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) + { +- return v->index ? -EINVAL : 0; +-} ++ struct rtrack *rt = container_of(isa, struct rtrack, isa); ++ int curvol = rt->curvol; + +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct rtrack *rt = video_drvdata(file); +- +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- rt_setfreq(rt, f->frequency); +- return 0; +-} +- +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct rtrack *rt = video_drvdata(file); +- +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = rt->curfreq; +- return 0; +-} +- +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- switch (qc->id) { +- case V4L2_CID_AUDIO_MUTE: +- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); +- case V4L2_CID_AUDIO_VOLUME: +- return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff); +- } +- return -EINVAL; +-} +- +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct rtrack *rt = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- ctrl->value = rt->muted; +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- ctrl->value = rt->curvol; ++ if (mute) { ++ outb(0xd0, isa->io); /* volume steady + sigstr + off */ + return 0; + } +- return -EINVAL; +-} +- +-static int vidioc_s_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct rtrack *rt = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (ctrl->value) +- rt_mute(rt); +- else +- rt_setvol(rt, rt->curvol); +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- rt_setvol(rt, ctrl->value); +- return 0; ++ if (vol == 0) { /* volume = 0 means mute the card */ ++ outb(0x48, isa->io); /* volume down but still "on" */ ++ msleep(curvol * 3); /* make sure it's totally down */ ++ } else if (curvol < vol) { ++ outb(0x98, isa->io); /* volume up + sigstr + on */ ++ for (; curvol < vol; curvol++) ++ udelay(3000); ++ } else if (curvol > vol) { ++ outb(0x58, isa->io); /* volume down + sigstr + on */ ++ for (; curvol > vol; curvol--) ++ udelay(3000); + } +- return -EINVAL; +-} +- +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; ++ outb(0xd8, isa->io); /* volume steady + sigstr + on */ ++ rt->curvol = vol; + return 0; + } + +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +-{ +- return i ? -EINVAL : 0; +-} +- +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) ++/* Mute card - prevents noisy bootups */ ++static int rtrack_initialize(struct radio_isa_card *isa) + { +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; ++ /* this ensures that the volume is all the way up */ ++ outb(0x90, isa->io); /* volume up but still "on" */ ++ msleep(3000); /* make sure it's totally up */ ++ outb(0xc0, isa->io); /* steady volume, mute card */ + return 0; + } + +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- return a->index ? -EINVAL : 0; +-} +- +-static const struct v4l2_file_operations rtrack_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, ++static const struct radio_isa_ops rtrack_ops = { ++ .alloc = rtrack_alloc, ++ .init = rtrack_initialize, ++ .s_mute_volume = rtrack_s_mute_volume, ++ .s_frequency = rtrack_s_frequency, ++ .g_signal = rtrack_g_signal, + }; + +-static const struct v4l2_ioctl_ops rtrack_ioctl_ops = { +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl, ++static const int rtrack_ioports[] = { 0x20f, 0x30f }; ++ ++static struct radio_isa_driver rtrack_driver = { ++ .driver = { ++ .match = radio_isa_match, ++ .probe = radio_isa_probe, ++ .remove = radio_isa_remove, ++ .driver = { ++ .name = "radio-aimslab", ++ }, ++ }, ++ .io_params = io, ++ .radio_nr_params = radio_nr, ++ .io_ports = rtrack_ioports, ++ .num_of_io_ports = ARRAY_SIZE(rtrack_ioports), ++ .region_size = 2, ++ .card = "AIMSlab RadioTrack/RadioReveal", ++ .ops = &rtrack_ops, ++ .has_stereo = true, ++ .max_volume = 0xff, + }; + + static int __init rtrack_init(void) + { +- struct rtrack *rt = &rtrack_card; +- struct v4l2_device *v4l2_dev = &rt->v4l2_dev; +- int res; +- +- strlcpy(v4l2_dev->name, "rtrack", sizeof(v4l2_dev->name)); +- rt->io = io; +- +- if (rt->io == -1) { +- v4l2_err(v4l2_dev, "you must set an I/O address with io=0x20f or 0x30f\n"); +- return -EINVAL; +- } +- +- if (!request_region(rt->io, 2, "rtrack")) { +- v4l2_err(v4l2_dev, "port 0x%x already in use\n", rt->io); +- return -EBUSY; +- } +- +- res = v4l2_device_register(NULL, v4l2_dev); +- if (res < 0) { +- release_region(rt->io, 2); +- v4l2_err(v4l2_dev, "could not register v4l2_device\n"); +- return res; +- } +- +- strlcpy(rt->vdev.name, v4l2_dev->name, sizeof(rt->vdev.name)); +- rt->vdev.v4l2_dev = v4l2_dev; +- rt->vdev.fops = &rtrack_fops; +- rt->vdev.ioctl_ops = &rtrack_ioctl_ops; +- rt->vdev.release = video_device_release_empty; +- video_set_drvdata(&rt->vdev, rt); +- +- /* Set up the I/O locking */ +- +- mutex_init(&rt->lock); +- +- /* mute card - prevents noisy bootups */ +- +- /* this ensures that the volume is all the way down */ +- outb(0x48, rt->io); /* volume down but still "on" */ +- msleep(2000); /* make sure it's totally down */ +- outb(0xc0, rt->io); /* steady volume, mute card */ +- +- if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_device_unregister(&rt->v4l2_dev); +- release_region(rt->io, 2); +- return -EINVAL; +- } +- v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n"); +- +- return 0; ++ return isa_register_driver(&rtrack_driver.driver, RTRACK_MAX); + } + + static void __exit rtrack_exit(void) + { +- struct rtrack *rt = &rtrack_card; +- +- video_unregister_device(&rt->vdev); +- v4l2_device_unregister(&rt->v4l2_dev); +- release_region(rt->io, 2); ++ isa_unregister_driver(&rtrack_driver.driver); + } + + module_init(rtrack_init); + module_exit(rtrack_exit); +- +Index: linux-3.3.x86_64/drivers/media/radio/radio-aztech.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-aztech.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-aztech.c +@@ -1,5 +1,7 @@ +-/* radio-aztech.c - Aztech radio card driver for Linux 2.2 ++/* ++ * radio-aztech.c - Aztech radio card driver + * ++ * Converted to the radio-isa framework by Hans Verkuil + * Converted to V4L2 API by Mauro Carvalho Chehab + * Adapted to support the Video for Linux API by + * Russell Kroll . Based on original tuner code by: +@@ -10,19 +12,7 @@ + * Scott McGrath (smcgrath@twilight.vtc.vsc.edu) + * William McGrath (wmcgrath@twilight.vtc.vsc.edu) + * +- * The basis for this code may be found at http://bigbang.vtc.vsc.edu/fmradio/ +- * along with more information on the card itself. +- * +- * History: +- * 1999-02-24 Russell Kroll +- * Fine tuning/VIDEO_TUNER_LOW +- * Range expanded to 87-108 MHz (from 87.9-107.8) +- * +- * Notable changes from the original source: +- * - includes stripped down to the essentials +- * - for loops used as delays replaced with udelay() +- * - #defines removed, changed to static values +- * - tuning structure changed - no more character arrays, other changes ++ * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool. + */ + + #include /* Modules */ +@@ -31,126 +21,72 @@ + #include /* udelay */ + #include /* kernel radio structs */ + #include /* outb, outb_p */ ++#include + #include + #include ++#include ++#include "radio-isa.h" + + MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); + MODULE_DESCRIPTION("A driver for the Aztech radio card."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION("0.0.3"); ++MODULE_VERSION("1.0.0"); + + /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ +- + #ifndef CONFIG_RADIO_AZTECH_PORT + #define CONFIG_RADIO_AZTECH_PORT -1 + #endif + +-static int io = CONFIG_RADIO_AZTECH_PORT; +-static int radio_nr = -1; +-static int radio_wait_time = 1000; +- +-module_param(io, int, 0); +-module_param(radio_nr, int, 0); +-MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)"); ++#define AZTECH_MAX 2 + +-struct aztech +-{ +- struct v4l2_device v4l2_dev; +- struct video_device vdev; +- int io; ++static int io[AZTECH_MAX] = { [0] = CONFIG_RADIO_AZTECH_PORT, ++ [1 ... (AZTECH_MAX - 1)] = -1 }; ++static int radio_nr[AZTECH_MAX] = { [0 ... (AZTECH_MAX - 1)] = -1 }; ++static const int radio_wait_time = 1000; ++ ++module_param_array(io, int, NULL, 0444); ++MODULE_PARM_DESC(io, "I/O addresses of the Aztech card (0x350 or 0x358)"); ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); ++ ++struct aztech { ++ struct radio_isa_card isa; + int curvol; +- unsigned long curfreq; +- int stereo; +- struct mutex lock; + }; + +-static struct aztech aztech_card; +- +-static int volconvert(int level) +-{ +- level >>= 14; /* Map 16bits down to 2 bit */ +- level &= 3; +- +- /* convert to card-friendly values */ +- switch (level) { +- case 0: +- return 0; +- case 1: +- return 1; +- case 2: +- return 4; +- case 3: +- return 5; +- } +- return 0; /* Quieten gcc */ +-} +- + static void send_0_byte(struct aztech *az) + { + udelay(radio_wait_time); +- outb_p(2 + volconvert(az->curvol), az->io); +- outb_p(64 + 2 + volconvert(az->curvol), az->io); ++ outb_p(2 + az->curvol, az->isa.io); ++ outb_p(64 + 2 + az->curvol, az->isa.io); + } + + static void send_1_byte(struct aztech *az) + { +- udelay (radio_wait_time); +- outb_p(128 + 2 + volconvert(az->curvol), az->io); +- outb_p(128 + 64 + 2 + volconvert(az->curvol), az->io); +-} +- +-static int az_setvol(struct aztech *az, int vol) +-{ +- mutex_lock(&az->lock); +- outb(volconvert(vol), az->io); +- mutex_unlock(&az->lock); +- return 0; +-} +- +-/* thanks to Michael Dwyer for giving me a dose of clues in +- * the signal strength department.. +- * +- * This card has a stereo bit - bit 0 set = mono, not set = stereo +- * It also has a "signal" bit - bit 1 set = bad signal, not set = good +- * +- */ +- +-static int az_getsigstr(struct aztech *az) +-{ +- int sig = 1; +- +- mutex_lock(&az->lock); +- if (inb(az->io) & 2) /* bit set = no signal present */ +- sig = 0; +- mutex_unlock(&az->lock); +- return sig; ++ udelay(radio_wait_time); ++ outb_p(128 + 2 + az->curvol, az->isa.io); ++ outb_p(128 + 64 + 2 + az->curvol, az->isa.io); + } + +-static int az_getstereo(struct aztech *az) ++static struct radio_isa_card *aztech_alloc(void) + { +- int stereo = 1; ++ struct aztech *az = kzalloc(sizeof(*az), GFP_KERNEL); + +- mutex_lock(&az->lock); +- if (inb(az->io) & 1) /* bit set = mono */ +- stereo = 0; +- mutex_unlock(&az->lock); +- return stereo; ++ return az ? &az->isa : NULL; + } + +-static int az_setfreq(struct aztech *az, unsigned long frequency) ++static int aztech_s_frequency(struct radio_isa_card *isa, u32 freq) + { ++ struct aztech *az = container_of(isa, struct aztech, isa); + int i; + +- mutex_lock(&az->lock); +- +- az->curfreq = frequency; +- frequency += 171200; /* Add 10.7 MHz IF */ +- frequency /= 800; /* Convert to 50 kHz units */ ++ freq += 171200; /* Add 10.7 MHz IF */ ++ freq /= 800; /* Convert to 50 kHz units */ + + send_0_byte(az); /* 0: LSB of frequency */ + + for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ +- if (frequency & (1 << i)) ++ if (freq & (1 << i)) + send_1_byte(az); + else + send_0_byte(az); +@@ -158,7 +94,7 @@ static int az_setfreq(struct aztech *az, + send_0_byte(az); /* 14: test bit - always 0 */ + send_0_byte(az); /* 15: test bit - always 0 */ + send_0_byte(az); /* 16: band data 0 - always 0 */ +- if (az->stereo) /* 17: stereo (1 to enable) */ ++ if (isa->stereo) /* 17: stereo (1 to enable) */ + send_1_byte(az); + else + send_0_byte(az); +@@ -173,225 +109,77 @@ static int az_setfreq(struct aztech *az, + /* latch frequency */ + + udelay(radio_wait_time); +- outb_p(128 + 64 + volconvert(az->curvol), az->io); +- +- mutex_unlock(&az->lock); +- +- return 0; +-} ++ outb_p(128 + 64 + az->curvol, az->isa.io); + +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- strlcpy(v->driver, "radio-aztech", sizeof(v->driver)); +- strlcpy(v->card, "Aztech Radio", sizeof(v->card)); +- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; + return 0; + } + +-static int vidioc_g_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- struct aztech *az = video_drvdata(file); +- +- if (v->index > 0) +- return -EINVAL; +- +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- +- v->rangelow = 87 * 16000; +- v->rangehigh = 108 * 16000; +- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; +- v->capability = V4L2_TUNER_CAP_LOW; +- if (az_getstereo(az)) +- v->audmode = V4L2_TUNER_MODE_STEREO; +- else +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->signal = 0xFFFF * az_getsigstr(az); +- +- return 0; +-} +- +-static int vidioc_s_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- return v->index ? -EINVAL : 0; +-} +- +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; +- return 0; +-} +- +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +-{ +- return i ? -EINVAL : 0; +-} +- +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) ++/* thanks to Michael Dwyer for giving me a dose of clues in ++ * the signal strength department.. ++ * ++ * This card has a stereo bit - bit 0 set = mono, not set = stereo ++ */ ++static u32 aztech_g_rxsubchans(struct radio_isa_card *isa) + { +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; ++ if (inb(isa->io) & 1) ++ return V4L2_TUNER_SUB_MONO; ++ return V4L2_TUNER_SUB_STEREO; + } + +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) ++static int aztech_s_stereo(struct radio_isa_card *isa, bool stereo) + { +- return a->index ? -EINVAL : 0; ++ return aztech_s_frequency(isa, isa->freq); + } + +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) ++static int aztech_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) + { +- struct aztech *az = video_drvdata(file); ++ struct aztech *az = container_of(isa, struct aztech, isa); + +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- az_setfreq(az, f->frequency); ++ if (mute) ++ vol = 0; ++ az->curvol = (vol & 1) + ((vol & 2) << 1); ++ outb(az->curvol, isa->io); + return 0; + } + +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct aztech *az = video_drvdata(file); +- +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = az->curfreq; +- return 0; +-} +- +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- switch (qc->id) { +- case V4L2_CID_AUDIO_MUTE: +- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); +- case V4L2_CID_AUDIO_VOLUME: +- return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff); +- } +- return -EINVAL; +-} +- +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct aztech *az = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (az->curvol == 0) +- ctrl->value = 1; +- else +- ctrl->value = 0; +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- ctrl->value = az->curvol * 6554; +- return 0; +- } +- return -EINVAL; +-} +- +-static int vidioc_s_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct aztech *az = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (ctrl->value) +- az_setvol(az, 0); +- else +- az_setvol(az, az->curvol); +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- az_setvol(az, ctrl->value); +- return 0; +- } +- return -EINVAL; +-} +- +-static const struct v4l2_file_operations aztech_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, ++static const struct radio_isa_ops aztech_ops = { ++ .alloc = aztech_alloc, ++ .s_mute_volume = aztech_s_mute_volume, ++ .s_frequency = aztech_s_frequency, ++ .s_stereo = aztech_s_stereo, ++ .g_rxsubchans = aztech_g_rxsubchans, + }; + +-static const struct v4l2_ioctl_ops aztech_ioctl_ops = { +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl, ++static const int aztech_ioports[] = { 0x350, 0x358 }; ++ ++static struct radio_isa_driver aztech_driver = { ++ .driver = { ++ .match = radio_isa_match, ++ .probe = radio_isa_probe, ++ .remove = radio_isa_remove, ++ .driver = { ++ .name = "radio-aztech", ++ }, ++ }, ++ .io_params = io, ++ .radio_nr_params = radio_nr, ++ .io_ports = aztech_ioports, ++ .num_of_io_ports = ARRAY_SIZE(aztech_ioports), ++ .region_size = 2, ++ .card = "Aztech Radio", ++ .ops = &aztech_ops, ++ .has_stereo = true, ++ .max_volume = 3, + }; + + static int __init aztech_init(void) + { +- struct aztech *az = &aztech_card; +- struct v4l2_device *v4l2_dev = &az->v4l2_dev; +- int res; +- +- strlcpy(v4l2_dev->name, "aztech", sizeof(v4l2_dev->name)); +- az->io = io; +- +- if (az->io == -1) { +- v4l2_err(v4l2_dev, "you must set an I/O address with io=0x350 or 0x358\n"); +- return -EINVAL; +- } +- +- if (!request_region(az->io, 2, "aztech")) { +- v4l2_err(v4l2_dev, "port 0x%x already in use\n", az->io); +- return -EBUSY; +- } +- +- res = v4l2_device_register(NULL, v4l2_dev); +- if (res < 0) { +- release_region(az->io, 2); +- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); +- return res; +- } +- +- mutex_init(&az->lock); +- strlcpy(az->vdev.name, v4l2_dev->name, sizeof(az->vdev.name)); +- az->vdev.v4l2_dev = v4l2_dev; +- az->vdev.fops = &aztech_fops; +- az->vdev.ioctl_ops = &aztech_ioctl_ops; +- az->vdev.release = video_device_release_empty; +- video_set_drvdata(&az->vdev, az); +- /* mute card - prevents noisy bootups */ +- outb(0, az->io); +- +- if (video_register_device(&az->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_device_unregister(v4l2_dev); +- release_region(az->io, 2); +- return -EINVAL; +- } +- +- v4l2_info(v4l2_dev, "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n"); +- return 0; ++ return isa_register_driver(&aztech_driver.driver, AZTECH_MAX); + } + + static void __exit aztech_exit(void) + { +- struct aztech *az = &aztech_card; +- +- video_unregister_device(&az->vdev); +- v4l2_device_unregister(&az->v4l2_dev); +- release_region(az->io, 2); ++ isa_unregister_driver(&aztech_driver.driver); + } + + module_init(aztech_init); +Index: linux-3.3.x86_64/drivers/media/radio/radio-gemtek.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-gemtek.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-gemtek.c +@@ -1,4 +1,7 @@ +-/* GemTek radio card driver for Linux (C) 1998 Jonas Munsin ++/* ++ * GemTek radio card driver ++ * ++ * Copyright 1998 Jonas Munsin + * + * GemTek hasn't released any specs on the card, so the protocol had to + * be reverse engineered with dosemu. +@@ -11,9 +14,12 @@ + * Converted to new API by Alan Cox + * Various bugfixes and enhancements by Russell Kroll + * +- * TODO: Allow for more than one of these foolish entities :-) +- * ++ * Converted to the radio-isa framework by Hans Verkuil + * Converted to V4L2 API by Mauro Carvalho Chehab ++ * ++ * Note: this card seems to swap the left and right audio channels! ++ * ++ * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool. + */ + + #include /* Modules */ +@@ -23,8 +29,10 @@ + #include /* kernel radio structs */ + #include + #include /* outb, outb_p */ ++#include + #include + #include ++#include "radio-isa.h" + + /* + * Module info. +@@ -33,7 +41,7 @@ + MODULE_AUTHOR("Jonas Munsin, Pekka Seppänen "); + MODULE_DESCRIPTION("A driver for the GemTek Radio card."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION("0.0.4"); ++MODULE_VERSION("1.0.0"); + + /* + * Module params. +@@ -46,45 +54,29 @@ MODULE_VERSION("0.0.4"); + #define CONFIG_RADIO_GEMTEK_PROBE 1 + #endif + +-static int io = CONFIG_RADIO_GEMTEK_PORT; +-static bool probe = CONFIG_RADIO_GEMTEK_PROBE; +-static bool hardmute; +-static bool shutdown = 1; +-static bool keepmuted = 1; +-static bool initmute = 1; +-static int radio_nr = -1; ++#define GEMTEK_MAX 4 + +-module_param(io, int, 0444); +-MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic " +- "probing is disabled or fails. The most common I/O ports are: 0x20c " +- "0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to " +- "work for the combined sound/radiocard)."); ++static bool probe = CONFIG_RADIO_GEMTEK_PROBE; ++static bool hardmute; ++static int io[GEMTEK_MAX] = { [0] = CONFIG_RADIO_GEMTEK_PORT, ++ [1 ... (GEMTEK_MAX - 1)] = -1 }; ++static int radio_nr[GEMTEK_MAX] = { [0 ... (GEMTEK_MAX - 1)] = -1 }; + + module_param(probe, bool, 0444); +-MODULE_PARM_DESC(probe, "Enable automatic device probing. Note: only the most " +- "common I/O ports used by the card are probed."); ++MODULE_PARM_DESC(probe, "Enable automatic device probing."); + + module_param(hardmute, bool, 0644); +-MODULE_PARM_DESC(hardmute, "Enable `hard muting' by shutting down PLL, may " ++MODULE_PARM_DESC(hardmute, "Enable 'hard muting' by shutting down PLL, may " + "reduce static noise."); + +-module_param(shutdown, bool, 0644); +-MODULE_PARM_DESC(shutdown, "Enable shutting down PLL and muting line when " +- "module is unloaded."); +- +-module_param(keepmuted, bool, 0644); +-MODULE_PARM_DESC(keepmuted, "Keep card muted even when frequency is changed."); +- +-module_param(initmute, bool, 0444); +-MODULE_PARM_DESC(initmute, "Mute card when module is loaded."); +- +-module_param(radio_nr, int, 0444); ++module_param_array(io, int, NULL, 0444); ++MODULE_PARM_DESC(io, "Force I/O ports for the GemTek Radio card if automatic " ++ "probing is disabled or fails. The most common I/O ports are: 0x20c " ++ "0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to " ++ "work for the combined sound/radiocard)."); + +-/* +- * Functions for controlling the card. +- */ +-#define GEMTEK_LOWFREQ (87*16000) +-#define GEMTEK_HIGHFREQ (108*16000) ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); + + /* + * Frequency calculation constants. Intermediate frequency 10.52 MHz (nominal +@@ -108,18 +100,11 @@ module_param(radio_nr, int, 0444); + #define LONG_DELAY 75 /* usec */ + + struct gemtek { +- struct v4l2_device v4l2_dev; +- struct video_device vdev; +- struct mutex lock; +- unsigned long lastfreq; +- int muted; +- int verified; +- int io; ++ struct radio_isa_card isa; ++ bool muted; + u32 bu2614data; + }; + +-static struct gemtek gemtek_card; +- + #define BU2614_FREQ_BITS 16 /* D0..D15, Frequency data */ + #define BU2614_PORT_BITS 3 /* P0..P2, Output port control data */ + #define BU2614_VOID_BITS 4 /* unused */ +@@ -166,31 +151,24 @@ static struct gemtek gemtek_card; + */ + static void gemtek_bu2614_transmit(struct gemtek *gt) + { ++ struct radio_isa_card *isa = >->isa; + int i, bit, q, mute; + +- mutex_lock(>->lock); +- + mute = gt->muted ? GEMTEK_MT : 0x00; + +- outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io); +- udelay(SHORT_DELAY); +- outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io); ++ outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, isa->io); + udelay(LONG_DELAY); + + for (i = 0, q = gt->bu2614data; i < 32; i++, q >>= 1) { + bit = (q & 1) ? GEMTEK_DA : 0; +- outb_p(mute | GEMTEK_CE | bit, gt->io); ++ outb_p(mute | GEMTEK_CE | bit, isa->io); + udelay(SHORT_DELAY); +- outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, gt->io); ++ outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, isa->io); + udelay(SHORT_DELAY); + } + +- outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io); ++ outb_p(mute | GEMTEK_DA | GEMTEK_CK, isa->io); + udelay(SHORT_DELAY); +- outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io); +- udelay(LONG_DELAY); +- +- mutex_unlock(>->lock); + } + + /* +@@ -198,21 +176,27 @@ static void gemtek_bu2614_transmit(struc + */ + static unsigned long gemtek_convfreq(unsigned long freq) + { +- return ((freq<muted = true; ++ return gt ? >->isa : NULL; + } + + /* + * Set FM-frequency. + */ +-static void gemtek_setfreq(struct gemtek *gt, unsigned long freq) ++static int gemtek_s_frequency(struct radio_isa_card *isa, u32 freq) + { +- if (keepmuted && hardmute && gt->muted) +- return; ++ struct gemtek *gt = container_of(isa, struct gemtek, isa); + +- freq = clamp_val(freq, GEMTEK_LOWFREQ, GEMTEK_HIGHFREQ); +- +- gt->lastfreq = freq; +- gt->muted = 0; ++ if (hardmute && gt->muted) ++ return 0; + + gemtek_bu2614_set(gt, BU2614_PORT, 0); + gemtek_bu2614_set(gt, BU2614_FMES, 0); +@@ -220,23 +204,25 @@ static void gemtek_setfreq(struct gemtek + gemtek_bu2614_set(gt, BU2614_SWAL, 0); + gemtek_bu2614_set(gt, BU2614_FMUN, 1); /* GT bit set */ + gemtek_bu2614_set(gt, BU2614_TEST, 0); +- + gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_STDF_3_125_KHZ); + gemtek_bu2614_set(gt, BU2614_FREQ, gemtek_convfreq(freq)); +- + gemtek_bu2614_transmit(gt); ++ return 0; + } + + /* + * Set mute flag. + */ +-static void gemtek_mute(struct gemtek *gt) ++static int gemtek_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) + { ++ struct gemtek *gt = container_of(isa, struct gemtek, isa); + int i; + +- gt->muted = 1; +- ++ gt->muted = mute; + if (hardmute) { ++ if (!mute) ++ return gemtek_s_frequency(isa, isa->freq); ++ + /* Turn off PLL, disable data output */ + gemtek_bu2614_set(gt, BU2614_PORT, 0); + gemtek_bu2614_set(gt, BU2614_FMES, 0); /* CT bit off */ +@@ -247,367 +233,85 @@ static void gemtek_mute(struct gemtek *g + gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_PLL_OFF); + gemtek_bu2614_set(gt, BU2614_FREQ, 0); + gemtek_bu2614_transmit(gt); +- return; ++ return 0; + } + +- mutex_lock(>->lock); +- + /* Read bus contents (CE, CK and DA). */ +- i = inb_p(gt->io); ++ i = inb_p(isa->io); + /* Write it back with mute flag set. */ +- outb_p((i >> 5) | GEMTEK_MT, gt->io); ++ outb_p((i >> 5) | (mute ? GEMTEK_MT : 0), isa->io); + udelay(SHORT_DELAY); +- +- mutex_unlock(>->lock); +-} +- +-/* +- * Unset mute flag. +- */ +-static void gemtek_unmute(struct gemtek *gt) +-{ +- int i; +- +- gt->muted = 0; +- if (hardmute) { +- /* Turn PLL back on. */ +- gemtek_setfreq(gt, gt->lastfreq); +- return; +- } +- mutex_lock(>->lock); +- +- i = inb_p(gt->io); +- outb_p(i >> 5, gt->io); +- udelay(SHORT_DELAY); +- +- mutex_unlock(>->lock); ++ return 0; + } + +-/* +- * Get signal strength (= stereo status). +- */ +-static inline int gemtek_getsigstr(struct gemtek *gt) ++static u32 gemtek_g_rxsubchans(struct radio_isa_card *isa) + { +- int sig; +- +- mutex_lock(>->lock); +- sig = inb_p(gt->io) & GEMTEK_NS ? 0 : 1; +- mutex_unlock(>->lock); +- return sig; ++ if (inb_p(isa->io) & GEMTEK_NS) ++ return V4L2_TUNER_SUB_MONO; ++ return V4L2_TUNER_SUB_STEREO; + } + + /* + * Check if requested card acts like GemTek Radio card. + */ +-static int gemtek_verify(struct gemtek *gt, int port) ++static bool gemtek_probe(struct radio_isa_card *isa, int io) + { + int i, q; + +- if (gt->verified == port) +- return 1; +- +- mutex_lock(>->lock); +- +- q = inb_p(port); /* Read bus contents before probing. */ ++ q = inb_p(io); /* Read bus contents before probing. */ + /* Try to turn on CE, CK and DA respectively and check if card responds + properly. */ + for (i = 0; i < 3; ++i) { +- outb_p(1 << i, port); ++ outb_p(1 << i, io); + udelay(SHORT_DELAY); + +- if ((inb_p(port) & (~GEMTEK_NS)) != (0x17 | (1 << (i + 5)))) { +- mutex_unlock(>->lock); +- return 0; +- } ++ if ((inb_p(io) & ~GEMTEK_NS) != (0x17 | (1 << (i + 5)))) ++ return false; + } +- outb_p(q >> 5, port); /* Write bus contents back. */ ++ outb_p(q >> 5, io); /* Write bus contents back. */ + udelay(SHORT_DELAY); +- +- mutex_unlock(>->lock); +- gt->verified = port; +- +- return 1; +-} +- +-/* +- * Automatic probing for card. +- */ +-static int gemtek_probe(struct gemtek *gt) +-{ +- struct v4l2_device *v4l2_dev = >->v4l2_dev; +- int ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c }; +- int i; +- +- if (!probe) { +- v4l2_info(v4l2_dev, "Automatic device probing disabled.\n"); +- return -1; +- } +- +- v4l2_info(v4l2_dev, "Automatic device probing enabled.\n"); +- +- for (i = 0; i < ARRAY_SIZE(ioports); ++i) { +- v4l2_info(v4l2_dev, "Trying I/O port 0x%x...\n", ioports[i]); +- +- if (!request_region(ioports[i], 1, "gemtek-probe")) { +- v4l2_warn(v4l2_dev, "I/O port 0x%x busy!\n", +- ioports[i]); +- continue; +- } +- +- if (gemtek_verify(gt, ioports[i])) { +- v4l2_info(v4l2_dev, "Card found from I/O port " +- "0x%x!\n", ioports[i]); +- +- release_region(ioports[i], 1); +- gt->io = ioports[i]; +- return gt->io; +- } +- +- release_region(ioports[i], 1); +- } +- +- v4l2_err(v4l2_dev, "Automatic probing failed!\n"); +- return -1; ++ return true; + } + +-/* +- * Video 4 Linux stuff. +- */ +- +-static const struct v4l2_file_operations gemtek_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, ++static const struct radio_isa_ops gemtek_ops = { ++ .alloc = gemtek_alloc, ++ .probe = gemtek_probe, ++ .s_mute_volume = gemtek_s_mute_volume, ++ .s_frequency = gemtek_s_frequency, ++ .g_rxsubchans = gemtek_g_rxsubchans, + }; + +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- strlcpy(v->driver, "radio-gemtek", sizeof(v->driver)); +- strlcpy(v->card, "GemTek", sizeof(v->card)); +- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; +- return 0; +-} +- +-static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) +-{ +- struct gemtek *gt = video_drvdata(file); +- +- if (v->index > 0) +- return -EINVAL; +- +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- v->rangelow = GEMTEK_LOWFREQ; +- v->rangehigh = GEMTEK_HIGHFREQ; +- v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; +- v->signal = 0xffff * gemtek_getsigstr(gt); +- if (v->signal) { +- v->audmode = V4L2_TUNER_MODE_STEREO; +- v->rxsubchans = V4L2_TUNER_SUB_STEREO; +- } else { +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->rxsubchans = V4L2_TUNER_SUB_MONO; +- } +- return 0; +-} +- +-static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) +-{ +- return (v->index != 0) ? -EINVAL : 0; +-} +- +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct gemtek *gt = video_drvdata(file); +- +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = gt->lastfreq; +- return 0; +-} +- +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct gemtek *gt = video_drvdata(file); +- +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- gemtek_setfreq(gt, f->frequency); +- return 0; +-} +- +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- switch (qc->id) { +- case V4L2_CID_AUDIO_MUTE: +- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); +- default: +- return -EINVAL; +- } +-} +- +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct gemtek *gt = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- ctrl->value = gt->muted; +- return 0; +- } +- return -EINVAL; +-} ++static const int gemtek_ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c }; + +-static int vidioc_s_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct gemtek *gt = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (ctrl->value) +- gemtek_mute(gt); +- else +- gemtek_unmute(gt); +- return 0; +- } +- return -EINVAL; +-} +- +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; +- return 0; +-} +- +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +-{ +- return (i != 0) ? -EINVAL : 0; +-} +- +-static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) +-{ +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; +-} +- +-static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) +-{ +- return (a->index != 0) ? -EINVAL : 0; +-} +- +-static const struct v4l2_ioctl_ops gemtek_ioctl_ops = { +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl ++static struct radio_isa_driver gemtek_driver = { ++ .driver = { ++ .match = radio_isa_match, ++ .probe = radio_isa_probe, ++ .remove = radio_isa_remove, ++ .driver = { ++ .name = "radio-gemtek", ++ }, ++ }, ++ .io_params = io, ++ .radio_nr_params = radio_nr, ++ .io_ports = gemtek_ioports, ++ .num_of_io_ports = ARRAY_SIZE(gemtek_ioports), ++ .region_size = 1, ++ .card = "GemTek Radio", ++ .ops = &gemtek_ops, ++ .has_stereo = true, + }; + +-/* +- * Initialization / cleanup related stuff. +- */ +- + static int __init gemtek_init(void) + { +- struct gemtek *gt = &gemtek_card; +- struct v4l2_device *v4l2_dev = >->v4l2_dev; +- int res; +- +- strlcpy(v4l2_dev->name, "gemtek", sizeof(v4l2_dev->name)); +- +- v4l2_info(v4l2_dev, "GemTek Radio card driver: v0.0.3\n"); +- +- mutex_init(>->lock); +- +- gt->verified = -1; +- gt->io = io; +- gemtek_probe(gt); +- if (gt->io) { +- if (!request_region(gt->io, 1, "gemtek")) { +- v4l2_err(v4l2_dev, "I/O port 0x%x already in use.\n", gt->io); +- return -EBUSY; +- } +- +- if (!gemtek_verify(gt, gt->io)) +- v4l2_warn(v4l2_dev, "Card at I/O port 0x%x does not " +- "respond properly, check your " +- "configuration.\n", gt->io); +- else +- v4l2_info(v4l2_dev, "Using I/O port 0x%x.\n", gt->io); +- } else if (probe) { +- v4l2_err(v4l2_dev, "Automatic probing failed and no " +- "fixed I/O port defined.\n"); +- return -ENODEV; +- } else { +- v4l2_err(v4l2_dev, "Automatic probing disabled but no fixed " +- "I/O port defined."); +- return -EINVAL; +- } +- +- res = v4l2_device_register(NULL, v4l2_dev); +- if (res < 0) { +- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); +- release_region(gt->io, 1); +- return res; +- } +- +- strlcpy(gt->vdev.name, v4l2_dev->name, sizeof(gt->vdev.name)); +- gt->vdev.v4l2_dev = v4l2_dev; +- gt->vdev.fops = &gemtek_fops; +- gt->vdev.ioctl_ops = &gemtek_ioctl_ops; +- gt->vdev.release = video_device_release_empty; +- video_set_drvdata(>->vdev, gt); +- +- /* Set defaults */ +- gt->lastfreq = GEMTEK_LOWFREQ; +- gt->bu2614data = 0; +- +- if (initmute) +- gemtek_mute(gt); +- +- if (video_register_device(>->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_device_unregister(v4l2_dev); +- release_region(gt->io, 1); +- return -EBUSY; +- } +- +- return 0; ++ gemtek_driver.probe = probe; ++ return isa_register_driver(&gemtek_driver.driver, GEMTEK_MAX); + } + +-/* +- * Module cleanup +- */ + static void __exit gemtek_exit(void) + { +- struct gemtek *gt = &gemtek_card; +- struct v4l2_device *v4l2_dev = >->v4l2_dev; +- +- if (shutdown) { +- hardmute = 1; /* Turn off PLL */ +- gemtek_mute(gt); +- } else { +- v4l2_info(v4l2_dev, "Module unloaded but card not muted!\n"); +- } +- +- video_unregister_device(>->vdev); +- v4l2_device_unregister(>->v4l2_dev); +- release_region(gt->io, 1); ++ hardmute = 1; /* Turn off PLL */ ++ isa_unregister_driver(&gemtek_driver.driver); + } + + module_init(gemtek_init); +Index: linux-3.3.x86_64/drivers/media/radio/radio-rtrack2.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-rtrack2.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-rtrack2.c +@@ -1,11 +1,12 @@ +-/* RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff ++/* ++ * RadioTrack II driver ++ * Copyright 1998 Ben Pfaff + * + * Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood + * Converted to new API by Alan Cox + * Various bugfixes and enhancements by Russell Kroll + * +- * TODO: Allow for more than one of these foolish entities :-) +- * ++ * Converted to the radio-isa framework by Hans Verkuil + * Converted to V4L2 API by Mauro Carvalho Chehab + */ + +@@ -16,325 +17,123 @@ + #include /* kernel radio structs */ + #include + #include /* outb, outb_p */ ++#include + #include + #include ++#include "radio-isa.h" + + MODULE_AUTHOR("Ben Pfaff"); + MODULE_DESCRIPTION("A driver for the RadioTrack II radio card."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION("0.0.3"); ++MODULE_VERSION("0.1.99"); + + #ifndef CONFIG_RADIO_RTRACK2_PORT + #define CONFIG_RADIO_RTRACK2_PORT -1 + #endif + +-static int io = CONFIG_RADIO_RTRACK2_PORT; +-static int radio_nr = -1; +- +-module_param(io, int, 0); +-MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)"); +-module_param(radio_nr, int, 0); +- +-struct rtrack2 +-{ +- struct v4l2_device v4l2_dev; +- struct video_device vdev; +- int io; +- unsigned long curfreq; +- int muted; +- struct mutex lock; +-}; +- +-static struct rtrack2 rtrack2_card; ++#define RTRACK2_MAX 2 + ++static int io[RTRACK2_MAX] = { [0] = CONFIG_RADIO_RTRACK2_PORT, ++ [1 ... (RTRACK2_MAX - 1)] = -1 }; ++static int radio_nr[RTRACK2_MAX] = { [0 ... (RTRACK2_MAX - 1)] = -1 }; + +-/* local things */ +- +-static void rt_mute(struct rtrack2 *dev) +-{ +- if (dev->muted) +- return; +- mutex_lock(&dev->lock); +- outb(1, dev->io); +- mutex_unlock(&dev->lock); +- dev->muted = 1; +-} ++module_param_array(io, int, NULL, 0444); ++MODULE_PARM_DESC(io, "I/O addresses of the RadioTrack card (0x20f or 0x30f)"); ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); + +-static void rt_unmute(struct rtrack2 *dev) ++static struct radio_isa_card *rtrack2_alloc(void) + { +- if(dev->muted == 0) +- return; +- mutex_lock(&dev->lock); +- outb(0, dev->io); +- mutex_unlock(&dev->lock); +- dev->muted = 0; ++ return kzalloc(sizeof(struct radio_isa_card), GFP_KERNEL); + } + +-static void zero(struct rtrack2 *dev) ++static void zero(struct radio_isa_card *isa) + { +- outb_p(1, dev->io); +- outb_p(3, dev->io); +- outb_p(1, dev->io); ++ outb_p(1, isa->io); ++ outb_p(3, isa->io); ++ outb_p(1, isa->io); + } + +-static void one(struct rtrack2 *dev) ++static void one(struct radio_isa_card *isa) + { +- outb_p(5, dev->io); +- outb_p(7, dev->io); +- outb_p(5, dev->io); ++ outb_p(5, isa->io); ++ outb_p(7, isa->io); ++ outb_p(5, isa->io); + } + +-static int rt_setfreq(struct rtrack2 *dev, unsigned long freq) ++static int rtrack2_s_frequency(struct radio_isa_card *isa, u32 freq) + { + int i; + +- mutex_lock(&dev->lock); +- dev->curfreq = freq; + freq = freq / 200 + 856; + +- outb_p(0xc8, dev->io); +- outb_p(0xc9, dev->io); +- outb_p(0xc9, dev->io); ++ outb_p(0xc8, isa->io); ++ outb_p(0xc9, isa->io); ++ outb_p(0xc9, isa->io); + + for (i = 0; i < 10; i++) +- zero(dev); ++ zero(isa); + + for (i = 14; i >= 0; i--) + if (freq & (1 << i)) +- one(dev); ++ one(isa); + else +- zero(dev); +- +- outb_p(0xc8, dev->io); +- if (!dev->muted) +- outb_p(0, dev->io); +- +- mutex_unlock(&dev->lock); +- return 0; +-} +- +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- strlcpy(v->driver, "radio-rtrack2", sizeof(v->driver)); +- strlcpy(v->card, "RadioTrack II", sizeof(v->card)); +- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; +- return 0; +-} +- +-static int vidioc_s_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- return v->index ? -EINVAL : 0; +-} +- +-static int rt_getsigstr(struct rtrack2 *dev) +-{ +- int sig = 1; +- +- mutex_lock(&dev->lock); +- if (inb(dev->io) & 2) /* bit set = no signal present */ +- sig = 0; +- mutex_unlock(&dev->lock); +- return sig; +-} ++ zero(isa); + +-static int vidioc_g_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- struct rtrack2 *rt = video_drvdata(file); +- +- if (v->index > 0) +- return -EINVAL; +- +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- v->rangelow = 88 * 16000; +- v->rangehigh = 108 * 16000; +- v->rxsubchans = V4L2_TUNER_SUB_MONO; +- v->capability = V4L2_TUNER_CAP_LOW; +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->signal = 0xFFFF * rt_getsigstr(rt); ++ outb_p(0xc8, isa->io); ++ if (!v4l2_ctrl_g_ctrl(isa->mute)) ++ outb_p(0, isa->io); + return 0; + } + +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) ++static u32 rtrack2_g_signal(struct radio_isa_card *isa) + { +- struct rtrack2 *rt = video_drvdata(file); +- +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- rt_setfreq(rt, f->frequency); +- return 0; ++ /* bit set = no signal present */ ++ return (inb(isa->io) & 2) ? 0 : 0xffff; + } + +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) ++static int rtrack2_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) + { +- struct rtrack2 *rt = video_drvdata(file); +- +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = rt->curfreq; ++ outb(mute, isa->io); + return 0; + } + +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- switch (qc->id) { +- case V4L2_CID_AUDIO_MUTE: +- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); +- case V4L2_CID_AUDIO_VOLUME: +- return v4l2_ctrl_query_fill(qc, 0, 65535, 65535, 65535); +- } +- return -EINVAL; +-} +- +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct rtrack2 *rt = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- ctrl->value = rt->muted; +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- if (rt->muted) +- ctrl->value = 0; +- else +- ctrl->value = 65535; +- return 0; +- } +- return -EINVAL; +-} +- +-static int vidioc_s_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct rtrack2 *rt = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (ctrl->value) +- rt_mute(rt); +- else +- rt_unmute(rt); +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- if (ctrl->value) +- rt_unmute(rt); +- else +- rt_mute(rt); +- return 0; +- } +- return -EINVAL; +-} +- +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; +- return 0; +-} +- +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +-{ +- return i ? -EINVAL : 0; +-} +- +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; +-} +- +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- return a->index ? -EINVAL : 0; +-} +- +-static const struct v4l2_file_operations rtrack2_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, ++static const struct radio_isa_ops rtrack2_ops = { ++ .alloc = rtrack2_alloc, ++ .s_mute_volume = rtrack2_s_mute_volume, ++ .s_frequency = rtrack2_s_frequency, ++ .g_signal = rtrack2_g_signal, + }; + +-static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = { +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, ++static const int rtrack2_ioports[] = { 0x20f, 0x30f }; ++ ++static struct radio_isa_driver rtrack2_driver = { ++ .driver = { ++ .match = radio_isa_match, ++ .probe = radio_isa_probe, ++ .remove = radio_isa_remove, ++ .driver = { ++ .name = "radio-rtrack2", ++ }, ++ }, ++ .io_params = io, ++ .radio_nr_params = radio_nr, ++ .io_ports = rtrack2_ioports, ++ .num_of_io_ports = ARRAY_SIZE(rtrack2_ioports), ++ .region_size = 4, ++ .card = "AIMSlab RadioTrack II", ++ .ops = &rtrack2_ops, ++ .has_stereo = true, + }; + + static int __init rtrack2_init(void) + { +- struct rtrack2 *dev = &rtrack2_card; +- struct v4l2_device *v4l2_dev = &dev->v4l2_dev; +- int res; +- +- strlcpy(v4l2_dev->name, "rtrack2", sizeof(v4l2_dev->name)); +- dev->io = io; +- if (dev->io == -1) { +- v4l2_err(v4l2_dev, "You must set an I/O address with io=0x20c or io=0x30c\n"); +- return -EINVAL; +- } +- if (!request_region(dev->io, 4, "rtrack2")) { +- v4l2_err(v4l2_dev, "port 0x%x already in use\n", dev->io); +- return -EBUSY; +- } +- +- res = v4l2_device_register(NULL, v4l2_dev); +- if (res < 0) { +- release_region(dev->io, 4); +- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); +- return res; +- } +- +- strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); +- dev->vdev.v4l2_dev = v4l2_dev; +- dev->vdev.fops = &rtrack2_fops; +- dev->vdev.ioctl_ops = &rtrack2_ioctl_ops; +- dev->vdev.release = video_device_release_empty; +- video_set_drvdata(&dev->vdev, dev); +- +- /* mute card - prevents noisy bootups */ +- outb(1, dev->io); +- dev->muted = 1; +- +- mutex_init(&dev->lock); +- if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_device_unregister(v4l2_dev); +- release_region(dev->io, 4); +- return -EINVAL; +- } +- +- v4l2_info(v4l2_dev, "AIMSlab Radiotrack II card driver.\n"); +- +- return 0; ++ return isa_register_driver(&rtrack2_driver.driver, RTRACK2_MAX); + } + + static void __exit rtrack2_exit(void) + { +- struct rtrack2 *dev = &rtrack2_card; +- +- video_unregister_device(&dev->vdev); +- v4l2_device_unregister(&dev->v4l2_dev); +- release_region(dev->io, 4); ++ isa_unregister_driver(&rtrack2_driver.driver); + } + + module_init(rtrack2_init); +Index: linux-3.3.x86_64/drivers/media/radio/radio-terratec.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-terratec.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-terratec.c +@@ -16,11 +16,7 @@ + * Frequency control is done digitally -- ie out(port,encodefreq(95.8)); + * Volume Control is done digitally + * +- * there is a I2C controlled RDS decoder (SAA6588) onboard, which i would like to support someday +- * (as soon i have understand how to get started :) +- * If you can help me out with that, please contact me!! +- * +- * ++ * Converted to the radio-isa framework by Hans Verkuil + * Converted to V4L2 API by Mauro Carvalho Chehab + */ + +@@ -30,43 +26,24 @@ + #include /* kernel radio structs */ + #include + #include /* outb, outb_p */ ++#include + #include + #include ++#include "radio-isa.h" + +-MODULE_AUTHOR("R.OFFERMANNS & others"); ++MODULE_AUTHOR("R. Offermans & others"); + MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio card."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION("0.0.3"); +- +-#ifndef CONFIG_RADIO_TERRATEC_PORT +-#define CONFIG_RADIO_TERRATEC_PORT 0x590 +-#endif ++MODULE_VERSION("0.1.99"); + +-static int io = CONFIG_RADIO_TERRATEC_PORT; ++/* Note: there seems to be only one possible port (0x590), but without ++ hardware this is hard to verify. For now, this is the only one we will ++ support. */ ++static int io = 0x590; + static int radio_nr = -1; + +-module_param(io, int, 0); +-MODULE_PARM_DESC(io, "I/O address of the TerraTec ActiveRadio card (0x590 or 0x591)"); +-module_param(radio_nr, int, 0); +- +-static struct v4l2_queryctrl radio_qctrl[] = { +- { +- .id = V4L2_CID_AUDIO_MUTE, +- .name = "Mute", +- .minimum = 0, +- .maximum = 1, +- .default_value = 1, +- .type = V4L2_CTRL_TYPE_BOOLEAN, +- },{ +- .id = V4L2_CID_AUDIO_VOLUME, +- .name = "Volume", +- .minimum = 0, +- .maximum = 0xff, +- .step = 1, +- .default_value = 0xff, +- .type = V4L2_CTRL_TYPE_INTEGER, +- } +-}; ++module_param(radio_nr, int, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device number"); + + #define WRT_DIS 0x00 + #define CLK_OFF 0x00 +@@ -76,63 +53,24 @@ static struct v4l2_queryctrl radio_qctrl + #define CLK_ON 0x08 + #define WRT_EN 0x10 + +-struct terratec ++static struct radio_isa_card *terratec_alloc(void) + { +- struct v4l2_device v4l2_dev; +- struct video_device vdev; +- int io; +- int curvol; +- unsigned long curfreq; +- int muted; +- struct mutex lock; +-}; +- +-static struct terratec terratec_card; +- +-/* local things */ ++ return kzalloc(sizeof(struct radio_isa_card), GFP_KERNEL); ++} + +-static void tt_write_vol(struct terratec *tt, int volume) ++static int terratec_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) + { + int i; + +- volume = volume + (volume * 32); /* change both channels */ +- mutex_lock(&tt->lock); ++ if (mute) ++ vol = 0; ++ vol = vol + (vol * 32); /* change both channels */ + for (i = 0; i < 8; i++) { +- if (volume & (0x80 >> i)) +- outb(0x80, tt->io + 1); ++ if (vol & (0x80 >> i)) ++ outb(0x80, isa->io + 1); + else +- outb(0x00, tt->io + 1); ++ outb(0x00, isa->io + 1); + } +- mutex_unlock(&tt->lock); +-} +- +- +- +-static void tt_mute(struct terratec *tt) +-{ +- tt->muted = 1; +- tt_write_vol(tt, 0); +-} +- +-static int tt_setvol(struct terratec *tt, int vol) +-{ +- if (vol == tt->curvol) { /* requested volume = current */ +- if (tt->muted) { /* user is unmuting the card */ +- tt->muted = 0; +- tt_write_vol(tt, vol); /* enable card */ +- } +- return 0; +- } +- +- if (vol == 0) { /* volume = 0 means mute the card */ +- tt_write_vol(tt, 0); /* "turn off card" by setting vol to 0 */ +- tt->curvol = vol; /* track the volume state! */ +- return 0; +- } +- +- tt->muted = 0; +- tt_write_vol(tt, vol); +- tt->curvol = vol; + return 0; + } + +@@ -140,20 +78,15 @@ static int tt_setvol(struct terratec *tt + /* this is the worst part in this driver */ + /* many more or less strange things are going on here, but hey, it works :) */ + +-static int tt_setfreq(struct terratec *tt, unsigned long freq1) ++static int terratec_s_frequency(struct radio_isa_card *isa, u32 freq) + { +- int freq; + int i; + int p; +- int temp; ++ int temp; + long rest; + unsigned char buffer[25]; /* we have to bit shift 25 registers */ + +- mutex_lock(&tt->lock); +- +- tt->curfreq = freq1; +- +- freq = freq1 / 160; /* convert the freq. to a nice to handle value */ ++ freq = freq / 160; /* convert the freq. to a nice to handle value */ + memset(buffer, 0, sizeof(buffer)); + + rest = freq * 10 + 10700; /* I once had understood what is going on here */ +@@ -175,239 +108,61 @@ static int tt_setfreq(struct terratec *t + + for (i = 24; i > -1; i--) { /* bit shift the values to the radiocard */ + if (buffer[i] == 1) { +- outb(WRT_EN | DATA, tt->io); +- outb(WRT_EN | DATA | CLK_ON, tt->io); +- outb(WRT_EN | DATA, tt->io); ++ outb(WRT_EN | DATA, isa->io); ++ outb(WRT_EN | DATA | CLK_ON, isa->io); ++ outb(WRT_EN | DATA, isa->io); + } else { +- outb(WRT_EN | 0x00, tt->io); +- outb(WRT_EN | 0x00 | CLK_ON, tt->io); +- } +- } +- outb(0x00, tt->io); +- +- mutex_unlock(&tt->lock); +- +- return 0; +-} +- +-static int tt_getsigstr(struct terratec *tt) +-{ +- if (inb(tt->io) & 2) /* bit set = no signal present */ +- return 0; +- return 1; /* signal present */ +-} +- +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- strlcpy(v->driver, "radio-terratec", sizeof(v->driver)); +- strlcpy(v->card, "ActiveRadio", sizeof(v->card)); +- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; +- return 0; +-} +- +-static int vidioc_g_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- struct terratec *tt = video_drvdata(file); +- +- if (v->index > 0) +- return -EINVAL; +- +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- v->rangelow = 87 * 16000; +- v->rangehigh = 108 * 16000; +- v->rxsubchans = V4L2_TUNER_SUB_MONO; +- v->capability = V4L2_TUNER_CAP_LOW; +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->signal = 0xFFFF * tt_getsigstr(tt); +- return 0; +-} +- +-static int vidioc_s_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- return v->index ? -EINVAL : 0; +-} +- +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct terratec *tt = video_drvdata(file); +- +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- tt_setfreq(tt, f->frequency); +- return 0; +-} +- +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct terratec *tt = video_drvdata(file); +- +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = tt->curfreq; +- return 0; +-} +- +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- int i; +- +- for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { +- if (qc->id && qc->id == radio_qctrl[i].id) { +- memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); +- return 0; ++ outb(WRT_EN | 0x00, isa->io); ++ outb(WRT_EN | 0x00 | CLK_ON, isa->io); + } + } +- return -EINVAL; +-} +- +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct terratec *tt = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (tt->muted) +- ctrl->value = 1; +- else +- ctrl->value = 0; +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- ctrl->value = tt->curvol * 6554; +- return 0; +- } +- return -EINVAL; +-} +- +-static int vidioc_s_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct terratec *tt = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (ctrl->value) +- tt_mute(tt); +- else +- tt_setvol(tt,tt->curvol); +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- tt_setvol(tt,ctrl->value); +- return 0; +- } +- return -EINVAL; +-} +- +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; ++ outb(0x00, isa->io); + return 0; + } + +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) ++static u32 terratec_g_signal(struct radio_isa_card *isa) + { +- return i ? -EINVAL : 0; ++ /* bit set = no signal present */ ++ return (inb(isa->io) & 2) ? 0 : 0xffff; + } + +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; +-} +- +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- return a->index ? -EINVAL : 0; +-} +- +-static const struct v4l2_file_operations terratec_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, ++static const struct radio_isa_ops terratec_ops = { ++ .alloc = terratec_alloc, ++ .s_mute_volume = terratec_s_mute_volume, ++ .s_frequency = terratec_s_frequency, ++ .g_signal = terratec_g_signal, + }; + +-static const struct v4l2_ioctl_ops terratec_ioctl_ops = { +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, ++static const int terratec_ioports[] = { 0x590 }; ++ ++static struct radio_isa_driver terratec_driver = { ++ .driver = { ++ .match = radio_isa_match, ++ .probe = radio_isa_probe, ++ .remove = radio_isa_remove, ++ .driver = { ++ .name = "radio-terratec", ++ }, ++ }, ++ .io_params = &io, ++ .radio_nr_params = &radio_nr, ++ .io_ports = terratec_ioports, ++ .num_of_io_ports = ARRAY_SIZE(terratec_ioports), ++ .region_size = 2, ++ .card = "TerraTec ActiveRadio", ++ .ops = &terratec_ops, ++ .has_stereo = true, ++ .max_volume = 10, + }; + + static int __init terratec_init(void) + { +- struct terratec *tt = &terratec_card; +- struct v4l2_device *v4l2_dev = &tt->v4l2_dev; +- int res; +- +- strlcpy(v4l2_dev->name, "terratec", sizeof(v4l2_dev->name)); +- tt->io = io; +- if (tt->io == -1) { +- v4l2_err(v4l2_dev, "you must set an I/O address with io=0x590 or 0x591\n"); +- return -EINVAL; +- } +- if (!request_region(tt->io, 2, "terratec")) { +- v4l2_err(v4l2_dev, "port 0x%x already in use\n", io); +- return -EBUSY; +- } +- +- res = v4l2_device_register(NULL, v4l2_dev); +- if (res < 0) { +- release_region(tt->io, 2); +- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); +- return res; +- } +- +- strlcpy(tt->vdev.name, v4l2_dev->name, sizeof(tt->vdev.name)); +- tt->vdev.v4l2_dev = v4l2_dev; +- tt->vdev.fops = &terratec_fops; +- tt->vdev.ioctl_ops = &terratec_ioctl_ops; +- tt->vdev.release = video_device_release_empty; +- video_set_drvdata(&tt->vdev, tt); +- +- mutex_init(&tt->lock); +- +- /* mute card - prevents noisy bootups */ +- tt_write_vol(tt, 0); +- +- if (video_register_device(&tt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_device_unregister(&tt->v4l2_dev); +- release_region(tt->io, 2); +- return -EINVAL; +- } +- +- v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver.\n"); +- return 0; ++ return isa_register_driver(&terratec_driver.driver, 1); + } + + static void __exit terratec_exit(void) + { +- struct terratec *tt = &terratec_card; +- struct v4l2_device *v4l2_dev = &tt->v4l2_dev; +- +- video_unregister_device(&tt->vdev); +- v4l2_device_unregister(&tt->v4l2_dev); +- release_region(tt->io, 2); +- v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver unloaded.\n"); ++ isa_unregister_driver(&terratec_driver.driver); + } + + module_init(terratec_init); +Index: linux-3.3.x86_64/drivers/media/radio/radio-trust.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-trust.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-trust.c +@@ -21,13 +21,15 @@ + #include + #include + #include ++#include + #include + #include ++#include "radio-isa.h" + + MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); + MODULE_DESCRIPTION("A driver for the Trust FM Radio card."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION("0.0.3"); ++MODULE_VERSION("0.1.99"); + + /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ + +@@ -35,39 +37,38 @@ MODULE_VERSION("0.0.3"); + #define CONFIG_RADIO_TRUST_PORT -1 + #endif + +-static int io = CONFIG_RADIO_TRUST_PORT; +-static int radio_nr = -1; ++#define TRUST_MAX 2 + +-module_param(io, int, 0); +-MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)"); +-module_param(radio_nr, int, 0); ++static int io[TRUST_MAX] = { [0] = CONFIG_RADIO_TRUST_PORT, ++ [1 ... (TRUST_MAX - 1)] = -1 }; ++static int radio_nr[TRUST_MAX] = { [0 ... (TRUST_MAX - 1)] = -1 }; ++ ++module_param_array(io, int, NULL, 0444); ++MODULE_PARM_DESC(io, "I/O addresses of the Trust FM Radio card (0x350 or 0x358)"); ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); + + struct trust { +- struct v4l2_device v4l2_dev; +- struct video_device vdev; +- int io; ++ struct radio_isa_card isa; + int ioval; +- __u16 curvol; +- __u16 curbass; +- __u16 curtreble; +- int muted; +- unsigned long curfreq; +- int curstereo; +- int curmute; +- struct mutex lock; + }; + +-static struct trust trust_card; ++static struct radio_isa_card *trust_alloc(void) ++{ ++ struct trust *tr = kzalloc(sizeof(*tr), GFP_KERNEL); ++ ++ return tr ? &tr->isa : NULL; ++} + + /* i2c addresses */ + #define TDA7318_ADDR 0x88 + #define TSA6060T_ADDR 0xc4 + +-#define TR_DELAY do { inb(tr->io); inb(tr->io); inb(tr->io); } while (0) +-#define TR_SET_SCL outb(tr->ioval |= 2, tr->io) +-#define TR_CLR_SCL outb(tr->ioval &= 0xfd, tr->io) +-#define TR_SET_SDA outb(tr->ioval |= 1, tr->io) +-#define TR_CLR_SDA outb(tr->ioval &= 0xfe, tr->io) ++#define TR_DELAY do { inb(tr->isa.io); inb(tr->isa.io); inb(tr->isa.io); } while (0) ++#define TR_SET_SCL outb(tr->ioval |= 2, tr->isa.io) ++#define TR_CLR_SCL outb(tr->ioval &= 0xfd, tr->isa.io) ++#define TR_SET_SDA outb(tr->ioval |= 1, tr->isa.io) ++#define TR_CLR_SDA outb(tr->ioval &= 0xfe, tr->isa.io) + + static void write_i2c(struct trust *tr, int n, ...) + { +@@ -84,10 +85,10 @@ static void write_i2c(struct trust *tr, + TR_CLR_SCL; + TR_DELAY; + +- for(; n; n--) { ++ for (; n; n--) { + val = va_arg(args, unsigned); +- for(mask = 0x80; mask; mask >>= 1) { +- if(val & mask) ++ for (mask = 0x80; mask; mask >>= 1) { ++ if (val & mask) + TR_SET_SDA; + else + TR_CLR_SDA; +@@ -115,317 +116,128 @@ static void write_i2c(struct trust *tr, + va_end(args); + } + +-static void tr_setvol(struct trust *tr, __u16 vol) ++static int trust_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) + { +- mutex_lock(&tr->lock); +- tr->curvol = vol / 2048; +- write_i2c(tr, 2, TDA7318_ADDR, tr->curvol ^ 0x1f); +- mutex_unlock(&tr->lock); +-} ++ struct trust *tr = container_of(isa, struct trust, isa); + +-static int basstreble2chip[15] = { +- 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8 +-}; +- +-static void tr_setbass(struct trust *tr, __u16 bass) +-{ +- mutex_lock(&tr->lock); +- tr->curbass = bass / 4370; +- write_i2c(tr, 2, TDA7318_ADDR, 0x60 | basstreble2chip[tr->curbass]); +- mutex_unlock(&tr->lock); ++ tr->ioval = (tr->ioval & 0xf7) | (mute << 3); ++ outb(tr->ioval, isa->io); ++ write_i2c(tr, 2, TDA7318_ADDR, vol ^ 0x1f); ++ return 0; + } + +-static void tr_settreble(struct trust *tr, __u16 treble) ++static int trust_s_stereo(struct radio_isa_card *isa, bool stereo) + { +- mutex_lock(&tr->lock); +- tr->curtreble = treble / 4370; +- write_i2c(tr, 2, TDA7318_ADDR, 0x70 | basstreble2chip[tr->curtreble]); +- mutex_unlock(&tr->lock); +-} ++ struct trust *tr = container_of(isa, struct trust, isa); + +-static void tr_setstereo(struct trust *tr, int stereo) +-{ +- mutex_lock(&tr->lock); +- tr->curstereo = !!stereo; +- tr->ioval = (tr->ioval & 0xfb) | (!tr->curstereo << 2); +- outb(tr->ioval, tr->io); +- mutex_unlock(&tr->lock); +-} +- +-static void tr_setmute(struct trust *tr, int mute) +-{ +- mutex_lock(&tr->lock); +- tr->curmute = !!mute; +- tr->ioval = (tr->ioval & 0xf7) | (tr->curmute << 3); +- outb(tr->ioval, tr->io); +- mutex_unlock(&tr->lock); ++ tr->ioval = (tr->ioval & 0xfb) | (!stereo << 2); ++ outb(tr->ioval, isa->io); ++ return 0; + } + +-static int tr_getsigstr(struct trust *tr) ++static u32 trust_g_signal(struct radio_isa_card *isa) + { + int i, v; + +- mutex_lock(&tr->lock); + for (i = 0, v = 0; i < 100; i++) +- v |= inb(tr->io); +- mutex_unlock(&tr->lock); ++ v |= inb(isa->io); + return (v & 1) ? 0 : 0xffff; + } + +-static int tr_getstereo(struct trust *tr) +-{ +- /* don't know how to determine it, just return the setting */ +- return tr->curstereo; +-} +- +-static void tr_setfreq(struct trust *tr, unsigned long f) +-{ +- mutex_lock(&tr->lock); +- tr->curfreq = f; +- f /= 160; /* Convert to 10 kHz units */ +- f += 1070; /* Add 10.7 MHz IF */ +- write_i2c(tr, 5, TSA6060T_ADDR, (f << 1) | 1, f >> 7, 0x60 | ((f >> 15) & 1), 0); +- mutex_unlock(&tr->lock); +-} +- +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- strlcpy(v->driver, "radio-trust", sizeof(v->driver)); +- strlcpy(v->card, "Trust FM Radio", sizeof(v->card)); +- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; +- return 0; +-} +- +-static int vidioc_g_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- struct trust *tr = video_drvdata(file); +- +- if (v->index > 0) +- return -EINVAL; +- +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- v->rangelow = 87.5 * 16000; +- v->rangehigh = 108 * 16000; +- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; +- v->capability = V4L2_TUNER_CAP_LOW; +- if (tr_getstereo(tr)) +- v->audmode = V4L2_TUNER_MODE_STEREO; +- else +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->signal = tr_getsigstr(tr); +- return 0; +-} +- +-static int vidioc_s_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) ++static int trust_s_frequency(struct radio_isa_card *isa, u32 freq) + { +- struct trust *tr = video_drvdata(file); ++ struct trust *tr = container_of(isa, struct trust, isa); + +- if (v->index) +- return -EINVAL; +- tr_setstereo(tr, v->audmode == V4L2_TUNER_MODE_STEREO); ++ freq /= 160; /* Convert to 10 kHz units */ ++ freq += 1070; /* Add 10.7 MHz IF */ ++ write_i2c(tr, 5, TSA6060T_ADDR, (freq << 1) | 1, ++ freq >> 7, 0x60 | ((freq >> 15) & 1), 0); + return 0; + } + +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct trust *tr = video_drvdata(file); +- +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- tr_setfreq(tr, f->frequency); +- return 0; +-} +- +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct trust *tr = video_drvdata(file); +- +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = tr->curfreq; +- return 0; +-} +- +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- switch (qc->id) { +- case V4L2_CID_AUDIO_MUTE: +- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); +- case V4L2_CID_AUDIO_VOLUME: +- return v4l2_ctrl_query_fill(qc, 0, 65535, 2048, 65535); +- case V4L2_CID_AUDIO_BASS: +- case V4L2_CID_AUDIO_TREBLE: +- return v4l2_ctrl_query_fill(qc, 0, 65535, 4370, 32768); +- } +- return -EINVAL; +-} +- +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct trust *tr = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- ctrl->value = tr->curmute; +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- ctrl->value = tr->curvol * 2048; +- return 0; +- case V4L2_CID_AUDIO_BASS: +- ctrl->value = tr->curbass * 4370; +- return 0; +- case V4L2_CID_AUDIO_TREBLE: +- ctrl->value = tr->curtreble * 4370; +- return 0; +- } +- return -EINVAL; +-} ++static int basstreble2chip[15] = { ++ 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8 ++}; + +-static int vidioc_s_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) ++static int trust_s_ctrl(struct v4l2_ctrl *ctrl) + { +- struct trust *tr = video_drvdata(file); ++ struct radio_isa_card *isa = ++ container_of(ctrl->handler, struct radio_isa_card, hdl); ++ struct trust *tr = container_of(isa, struct trust, isa); + + switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- tr_setmute(tr, ctrl->value); +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- tr_setvol(tr, ctrl->value); +- return 0; + case V4L2_CID_AUDIO_BASS: +- tr_setbass(tr, ctrl->value); ++ write_i2c(tr, 2, TDA7318_ADDR, 0x60 | basstreble2chip[ctrl->val]); + return 0; + case V4L2_CID_AUDIO_TREBLE: +- tr_settreble(tr, ctrl->value); ++ write_i2c(tr, 2, TDA7318_ADDR, 0x70 | basstreble2chip[ctrl->val]); + return 0; + } + return -EINVAL; + } + +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; +- return 0; +-} +- +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +-{ +- return i ? -EINVAL : 0; +-} +- +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; +-} +- +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- return a->index ? -EINVAL : 0; +-} +- +-static const struct v4l2_file_operations trust_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, +-}; +- +-static const struct v4l2_ioctl_ops trust_ioctl_ops = { +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, ++static const struct v4l2_ctrl_ops trust_ctrl_ops = { ++ .s_ctrl = trust_s_ctrl, + }; + +-static int __init trust_init(void) ++static int trust_initialize(struct radio_isa_card *isa) + { +- struct trust *tr = &trust_card; +- struct v4l2_device *v4l2_dev = &tr->v4l2_dev; +- int res; ++ struct trust *tr = container_of(isa, struct trust, isa); + +- strlcpy(v4l2_dev->name, "trust", sizeof(v4l2_dev->name)); +- tr->io = io; + tr->ioval = 0xf; +- mutex_init(&tr->lock); +- +- if (tr->io == -1) { +- v4l2_err(v4l2_dev, "You must set an I/O address with io=0x0x350 or 0x358\n"); +- return -EINVAL; +- } +- if (!request_region(tr->io, 2, "Trust FM Radio")) { +- v4l2_err(v4l2_dev, "port 0x%x already in use\n", tr->io); +- return -EBUSY; +- } +- +- res = v4l2_device_register(NULL, v4l2_dev); +- if (res < 0) { +- release_region(tr->io, 2); +- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); +- return res; +- } +- +- strlcpy(tr->vdev.name, v4l2_dev->name, sizeof(tr->vdev.name)); +- tr->vdev.v4l2_dev = v4l2_dev; +- tr->vdev.fops = &trust_fops; +- tr->vdev.ioctl_ops = &trust_ioctl_ops; +- tr->vdev.release = video_device_release_empty; +- video_set_drvdata(&tr->vdev, tr); +- + write_i2c(tr, 2, TDA7318_ADDR, 0x80); /* speaker att. LF = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0xa0); /* speaker att. RF = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0xc0); /* speaker att. LR = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0xe0); /* speaker att. RR = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0x40); /* stereo 1 input, gain = 18.75 dB */ + +- tr_setvol(tr, 0xffff); +- tr_setbass(tr, 0x8000); +- tr_settreble(tr, 0x8000); +- tr_setstereo(tr, 1); +- +- /* mute card - prevents noisy bootups */ +- tr_setmute(tr, 1); +- +- if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_device_unregister(v4l2_dev); +- release_region(tr->io, 2); +- return -EINVAL; +- } ++ v4l2_ctrl_new_std(&isa->hdl, &trust_ctrl_ops, ++ V4L2_CID_AUDIO_BASS, 0, 15, 1, 8); ++ v4l2_ctrl_new_std(&isa->hdl, &trust_ctrl_ops, ++ V4L2_CID_AUDIO_TREBLE, 0, 15, 1, 8); ++ return isa->hdl.error; ++} + +- v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n"); ++static const struct radio_isa_ops trust_ops = { ++ .init = trust_initialize, ++ .alloc = trust_alloc, ++ .s_mute_volume = trust_s_mute_volume, ++ .s_frequency = trust_s_frequency, ++ .s_stereo = trust_s_stereo, ++ .g_signal = trust_g_signal, ++}; + +- return 0; +-} ++static const int trust_ioports[] = { 0x350, 0x358 }; ++ ++static struct radio_isa_driver trust_driver = { ++ .driver = { ++ .match = radio_isa_match, ++ .probe = radio_isa_probe, ++ .remove = radio_isa_remove, ++ .driver = { ++ .name = "radio-trust", ++ }, ++ }, ++ .io_params = io, ++ .radio_nr_params = radio_nr, ++ .io_ports = trust_ioports, ++ .num_of_io_ports = ARRAY_SIZE(trust_ioports), ++ .region_size = 2, ++ .card = "Trust FM Radio", ++ .ops = &trust_ops, ++ .has_stereo = true, ++ .max_volume = 31, ++}; + +-static void __exit cleanup_trust_module(void) ++static int __init trust_init(void) + { +- struct trust *tr = &trust_card; ++ return isa_register_driver(&trust_driver.driver, TRUST_MAX); ++} + +- video_unregister_device(&tr->vdev); +- v4l2_device_unregister(&tr->v4l2_dev); +- release_region(tr->io, 2); ++static void __exit trust_exit(void) ++{ ++ isa_unregister_driver(&trust_driver.driver); + } + + module_init(trust_init); +-module_exit(cleanup_trust_module); ++module_exit(trust_exit); +Index: linux-3.3.x86_64/drivers/media/radio/radio-typhoon.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-typhoon.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-typhoon.c +@@ -33,63 +33,53 @@ + #include /* request_region */ + #include /* kernel radio structs */ + #include /* outb, outb_p */ ++#include + #include + #include ++#include "radio-isa.h" + + #define DRIVER_VERSION "0.1.2" + + MODULE_AUTHOR("Dr. Henrik Seidel"); + MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio)."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION(DRIVER_VERSION); ++MODULE_VERSION("0.1.99"); + + #ifndef CONFIG_RADIO_TYPHOON_PORT + #define CONFIG_RADIO_TYPHOON_PORT -1 + #endif + + #ifndef CONFIG_RADIO_TYPHOON_MUTEFREQ +-#define CONFIG_RADIO_TYPHOON_MUTEFREQ 0 ++#define CONFIG_RADIO_TYPHOON_MUTEFREQ 87000 + #endif + +-static int io = CONFIG_RADIO_TYPHOON_PORT; +-static int radio_nr = -1; +- +-module_param(io, int, 0); +-MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)"); +- +-module_param(radio_nr, int, 0); ++#define TYPHOON_MAX 2 + ++static int io[TYPHOON_MAX] = { [0] = CONFIG_RADIO_TYPHOON_PORT, ++ [1 ... (TYPHOON_MAX - 1)] = -1 }; ++static int radio_nr[TYPHOON_MAX] = { [0 ... (TYPHOON_MAX - 1)] = -1 }; + static unsigned long mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ; ++ ++module_param_array(io, int, NULL, 0444); ++MODULE_PARM_DESC(io, "I/O addresses of the Typhoon card (0x316 or 0x336)"); ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); + module_param(mutefreq, ulong, 0); + MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)"); + +-#define BANNER "Typhoon Radio Card driver v" DRIVER_VERSION "\n" +- + struct typhoon { +- struct v4l2_device v4l2_dev; +- struct video_device vdev; +- int io; +- int curvol; ++ struct radio_isa_card isa; + int muted; +- unsigned long curfreq; +- unsigned long mutefreq; +- struct mutex lock; + }; + +-static struct typhoon typhoon_card; +- +-static void typhoon_setvol_generic(struct typhoon *dev, int vol) ++static struct radio_isa_card *typhoon_alloc(void) + { +- mutex_lock(&dev->lock); +- vol >>= 14; /* Map 16 bit to 2 bit */ +- vol &= 3; +- outb_p(vol / 2, dev->io); /* Set the volume, high bit. */ +- outb_p(vol % 2, dev->io + 2); /* Set the volume, low bit. */ +- mutex_unlock(&dev->lock); ++ struct typhoon *ty = kzalloc(sizeof(*ty), GFP_KERNEL); ++ ++ return ty ? &ty->isa : NULL; + } + +-static int typhoon_setfreq_generic(struct typhoon *dev, +- unsigned long frequency) ++static int typhoon_s_frequency(struct radio_isa_card *isa, u32 freq) + { + unsigned long outval; + unsigned long x; +@@ -105,302 +95,86 @@ static int typhoon_setfreq_generic(struc + * + */ + +- mutex_lock(&dev->lock); +- x = frequency / 160; ++ x = freq / 160; + outval = (x * x + 2500) / 5000; + outval = (outval * x + 5000) / 10000; + outval -= (10 * x * x + 10433) / 20866; + outval += 4 * x - 11505; + +- outb_p((outval >> 8) & 0x01, dev->io + 4); +- outb_p(outval >> 9, dev->io + 6); +- outb_p(outval & 0xff, dev->io + 8); +- mutex_unlock(&dev->lock); +- +- return 0; +-} +- +-static int typhoon_setfreq(struct typhoon *dev, unsigned long frequency) +-{ +- typhoon_setfreq_generic(dev, frequency); +- dev->curfreq = frequency; +- return 0; +-} +- +-static void typhoon_mute(struct typhoon *dev) +-{ +- if (dev->muted == 1) +- return; +- typhoon_setvol_generic(dev, 0); +- typhoon_setfreq_generic(dev, dev->mutefreq); +- dev->muted = 1; +-} +- +-static void typhoon_unmute(struct typhoon *dev) +-{ +- if (dev->muted == 0) +- return; +- typhoon_setfreq_generic(dev, dev->curfreq); +- typhoon_setvol_generic(dev, dev->curvol); +- dev->muted = 0; +-} +- +-static int typhoon_setvol(struct typhoon *dev, int vol) +-{ +- if (dev->muted && vol != 0) { /* user is unmuting the card */ +- dev->curvol = vol; +- typhoon_unmute(dev); +- return 0; +- } +- if (vol == dev->curvol) /* requested volume == current */ +- return 0; +- +- if (vol == 0) { /* volume == 0 means mute the card */ +- typhoon_mute(dev); +- dev->curvol = vol; +- return 0; +- } +- typhoon_setvol_generic(dev, vol); +- dev->curvol = vol; +- return 0; +-} +- +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- strlcpy(v->driver, "radio-typhoon", sizeof(v->driver)); +- strlcpy(v->card, "Typhoon Radio", sizeof(v->card)); +- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; +- return 0; +-} +- +-static int vidioc_g_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- if (v->index > 0) +- return -EINVAL; +- +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- v->rangelow = 87.5 * 16000; +- v->rangehigh = 108 * 16000; +- v->rxsubchans = V4L2_TUNER_SUB_MONO; +- v->capability = V4L2_TUNER_CAP_LOW; +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->signal = 0xFFFF; /* We can't get the signal strength */ ++ outb_p((outval >> 8) & 0x01, isa->io + 4); ++ outb_p(outval >> 9, isa->io + 6); ++ outb_p(outval & 0xff, isa->io + 8); + return 0; + } + +-static int vidioc_s_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- return v->index ? -EINVAL : 0; +-} +- +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) ++static int typhoon_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) + { +- struct typhoon *dev = video_drvdata(file); ++ struct typhoon *ty = container_of(isa, struct typhoon, isa); + +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = dev->curfreq; +- return 0; +-} +- +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct typhoon *dev = video_drvdata(file); +- +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- dev->curfreq = f->frequency; +- typhoon_setfreq(dev, dev->curfreq); +- return 0; +-} +- +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- switch (qc->id) { +- case V4L2_CID_AUDIO_MUTE: +- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); +- case V4L2_CID_AUDIO_VOLUME: +- return v4l2_ctrl_query_fill(qc, 0, 65535, 16384, 65535); +- } +- return -EINVAL; +-} +- +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct typhoon *dev = video_drvdata(file); ++ if (mute) ++ vol = 0; ++ vol >>= 14; /* Map 16 bit to 2 bit */ ++ vol &= 3; ++ outb_p(vol / 2, isa->io); /* Set the volume, high bit. */ ++ outb_p(vol % 2, isa->io + 2); /* Set the volume, low bit. */ + +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- ctrl->value = dev->muted; +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- ctrl->value = dev->curvol; +- return 0; ++ if (vol == 0 && !ty->muted) { ++ ty->muted = true; ++ return typhoon_s_frequency(isa, mutefreq << 4); + } +- return -EINVAL; +-} +- +-static int vidioc_s_ctrl (struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct typhoon *dev = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (ctrl->value) +- typhoon_mute(dev); +- else +- typhoon_unmute(dev); +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- typhoon_setvol(dev, ctrl->value); +- return 0; ++ if (vol && ty->muted) { ++ ty->muted = false; ++ return typhoon_s_frequency(isa, isa->freq); + } +- return -EINVAL; +-} +- +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; + return 0; + } + +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +-{ +- return i ? -EINVAL : 0; +-} +- +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; +-} +- +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- return a->index ? -EINVAL : 0; +-} +- +-static int vidioc_log_status(struct file *file, void *priv) +-{ +- struct typhoon *dev = video_drvdata(file); +- struct v4l2_device *v4l2_dev = &dev->v4l2_dev; +- +- v4l2_info(v4l2_dev, BANNER); +-#ifdef MODULE +- v4l2_info(v4l2_dev, "Load type: Driver loaded as a module\n\n"); +-#else +- v4l2_info(v4l2_dev, "Load type: Driver compiled into kernel\n\n"); +-#endif +- v4l2_info(v4l2_dev, "frequency = %lu kHz\n", dev->curfreq >> 4); +- v4l2_info(v4l2_dev, "volume = %d\n", dev->curvol); +- v4l2_info(v4l2_dev, "mute = %s\n", dev->muted ? "on" : "off"); +- v4l2_info(v4l2_dev, "io = 0x%x\n", dev->io); +- v4l2_info(v4l2_dev, "mute frequency = %lu kHz\n", dev->mutefreq >> 4); +- return 0; +-} +- +-static const struct v4l2_file_operations typhoon_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, ++static const struct radio_isa_ops typhoon_ops = { ++ .alloc = typhoon_alloc, ++ .s_mute_volume = typhoon_s_mute_volume, ++ .s_frequency = typhoon_s_frequency, + }; + +-static const struct v4l2_ioctl_ops typhoon_ioctl_ops = { +- .vidioc_log_status = vidioc_log_status, +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl, ++static const int typhoon_ioports[] = { 0x316, 0x336 }; ++ ++static struct radio_isa_driver typhoon_driver = { ++ .driver = { ++ .match = radio_isa_match, ++ .probe = radio_isa_probe, ++ .remove = radio_isa_remove, ++ .driver = { ++ .name = "radio-typhoon", ++ }, ++ }, ++ .io_params = io, ++ .radio_nr_params = radio_nr, ++ .io_ports = typhoon_ioports, ++ .num_of_io_ports = ARRAY_SIZE(typhoon_ioports), ++ .region_size = 8, ++ .card = "Typhoon Radio", ++ .ops = &typhoon_ops, ++ .has_stereo = true, ++ .max_volume = 3, + }; + + static int __init typhoon_init(void) + { +- struct typhoon *dev = &typhoon_card; +- struct v4l2_device *v4l2_dev = &dev->v4l2_dev; +- int res; +- +- strlcpy(v4l2_dev->name, "typhoon", sizeof(v4l2_dev->name)); +- dev->io = io; +- +- if (dev->io == -1) { +- v4l2_err(v4l2_dev, "You must set an I/O address with io=0x316 or io=0x336\n"); +- return -EINVAL; +- } +- +- if (mutefreq < 87000 || mutefreq > 108500) { +- v4l2_err(v4l2_dev, "You must set a frequency (in kHz) used when muting the card,\n"); +- v4l2_err(v4l2_dev, "e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n"); +- return -EINVAL; ++ if (mutefreq < 87000 || mutefreq > 108000) { ++ printk(KERN_ERR "%s: You must set a frequency (in kHz) used when muting the card,\n", ++ typhoon_driver.driver.driver.name); ++ printk(KERN_ERR "%s: e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108000)\n", ++ typhoon_driver.driver.driver.name); ++ return -ENODEV; + } +- dev->curfreq = dev->mutefreq = mutefreq << 4; +- +- mutex_init(&dev->lock); +- if (!request_region(dev->io, 8, "typhoon")) { +- v4l2_err(v4l2_dev, "port 0x%x already in use\n", +- dev->io); +- return -EBUSY; +- } +- +- res = v4l2_device_register(NULL, v4l2_dev); +- if (res < 0) { +- release_region(dev->io, 8); +- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); +- return res; +- } +- v4l2_info(v4l2_dev, BANNER); +- +- strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); +- dev->vdev.v4l2_dev = v4l2_dev; +- dev->vdev.fops = &typhoon_fops; +- dev->vdev.ioctl_ops = &typhoon_ioctl_ops; +- dev->vdev.release = video_device_release_empty; +- video_set_drvdata(&dev->vdev, dev); +- +- /* mute card - prevents noisy bootups */ +- typhoon_mute(dev); +- +- if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_device_unregister(&dev->v4l2_dev); +- release_region(dev->io, 8); +- return -EINVAL; +- } +- v4l2_info(v4l2_dev, "port 0x%x.\n", dev->io); +- v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", mutefreq); +- +- return 0; ++ return isa_register_driver(&typhoon_driver.driver, TYPHOON_MAX); + } + + static void __exit typhoon_exit(void) + { +- struct typhoon *dev = &typhoon_card; +- +- video_unregister_device(&dev->vdev); +- v4l2_device_unregister(&dev->v4l2_dev); +- release_region(dev->io, 8); ++ isa_unregister_driver(&typhoon_driver.driver); + } + ++ + module_init(typhoon_init); + module_exit(typhoon_exit); + +Index: linux-3.3.x86_64/drivers/media/radio/radio-zoltrix.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-zoltrix.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-zoltrix.c +@@ -1,5 +1,6 @@ +-/* zoltrix radio plus driver for Linux radio support +- * (c) 1998 C. van Schaik ++/* ++ * Zoltrix Radio Plus driver ++ * Copyright 1998 C. van Schaik + * + * BUGS + * Due to the inconsistency in reading from the signal flags +@@ -27,6 +28,14 @@ + * + * 2006-07-24 - Converted to V4L2 API + * by Mauro Carvalho Chehab ++ * ++ * Converted to the radio-isa framework by Hans Verkuil ++ * ++ * Note that this is the driver for the Zoltrix Radio Plus. ++ * This driver does not work for the Zoltrix Radio Plus 108 or the ++ * Zoltrix Radio Plus for Windows. ++ * ++ * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool. + */ + + #include /* Modules */ +@@ -36,82 +45,70 @@ + #include /* kernel radio structs */ + #include + #include /* outb, outb_p */ ++#include + #include + #include ++#include "radio-isa.h" + +-MODULE_AUTHOR("C.van Schaik"); ++MODULE_AUTHOR("C. van Schaik"); + MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION("0.0.3"); ++MODULE_VERSION("0.1.99"); + + #ifndef CONFIG_RADIO_ZOLTRIX_PORT + #define CONFIG_RADIO_ZOLTRIX_PORT -1 + #endif + +-static int io = CONFIG_RADIO_ZOLTRIX_PORT; +-static int radio_nr = -1; ++#define ZOLTRIX_MAX 2 + +-module_param(io, int, 0); +-MODULE_PARM_DESC(io, "I/O address of the Zoltrix Radio Plus (0x20c or 0x30c)"); +-module_param(radio_nr, int, 0); ++static int io[ZOLTRIX_MAX] = { [0] = CONFIG_RADIO_ZOLTRIX_PORT, ++ [1 ... (ZOLTRIX_MAX - 1)] = -1 }; ++static int radio_nr[ZOLTRIX_MAX] = { [0 ... (ZOLTRIX_MAX - 1)] = -1 }; ++ ++module_param_array(io, int, NULL, 0444); ++MODULE_PARM_DESC(io, "I/O addresses of the Zoltrix Radio Plus card (0x20c or 0x30c)"); ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); + + struct zoltrix { +- struct v4l2_device v4l2_dev; +- struct video_device vdev; +- int io; ++ struct radio_isa_card isa; + int curvol; +- unsigned long curfreq; +- int muted; +- unsigned int stereo; +- struct mutex lock; ++ bool muted; + }; + +-static struct zoltrix zoltrix_card; ++static struct radio_isa_card *zoltrix_alloc(void) ++{ ++ struct zoltrix *zol = kzalloc(sizeof(*zol), GFP_KERNEL); + +-static int zol_setvol(struct zoltrix *zol, int vol) ++ return zol ? &zol->isa : NULL; ++} ++ ++static int zoltrix_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) + { +- zol->curvol = vol; +- if (zol->muted) +- return 0; ++ struct zoltrix *zol = container_of(isa, struct zoltrix, isa); + +- mutex_lock(&zol->lock); +- if (vol == 0) { +- outb(0, zol->io); +- outb(0, zol->io); +- inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ +- mutex_unlock(&zol->lock); ++ zol->curvol = vol; ++ zol->muted = mute; ++ if (mute || vol == 0) { ++ outb(0, isa->io); ++ outb(0, isa->io); ++ inb(isa->io + 3); /* Zoltrix needs to be read to confirm */ + return 0; + } + +- outb(zol->curvol-1, zol->io); ++ outb(vol - 1, isa->io); + msleep(10); +- inb(zol->io + 2); +- mutex_unlock(&zol->lock); ++ inb(isa->io + 2); + return 0; + } + +-static void zol_mute(struct zoltrix *zol) +-{ +- zol->muted = 1; +- mutex_lock(&zol->lock); +- outb(0, zol->io); +- outb(0, zol->io); +- inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ +- mutex_unlock(&zol->lock); +-} +- +-static void zol_unmute(struct zoltrix *zol) +-{ +- zol->muted = 0; +- zol_setvol(zol, zol->curvol); +-} +- +-static int zol_setfreq(struct zoltrix *zol, unsigned long freq) ++/* tunes the radio to the desired frequency */ ++static int zoltrix_s_frequency(struct radio_isa_card *isa, u32 freq) + { +- /* tunes the radio to the desired frequency */ +- struct v4l2_device *v4l2_dev = &zol->v4l2_dev; ++ struct zoltrix *zol = container_of(isa, struct zoltrix, isa); ++ struct v4l2_device *v4l2_dev = &isa->v4l2_dev; + unsigned long long bitmask, f, m; +- unsigned int stereo = zol->stereo; ++ bool stereo = isa->stereo; + int i; + + if (freq == 0) { +@@ -125,340 +122,125 @@ static int zol_setfreq(struct zoltrix *z + bitmask = 0xc480402c10080000ull; + i = 45; + +- mutex_lock(&zol->lock); +- +- zol->curfreq = freq; ++ outb(0, isa->io); ++ outb(0, isa->io); ++ inb(isa->io + 3); /* Zoltrix needs to be read to confirm */ + +- outb(0, zol->io); +- outb(0, zol->io); +- inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ +- +- outb(0x40, zol->io); +- outb(0xc0, zol->io); ++ outb(0x40, isa->io); ++ outb(0xc0, isa->io); + + bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ (stereo << 31)); + while (i--) { + if ((bitmask & 0x8000000000000000ull) != 0) { +- outb(0x80, zol->io); ++ outb(0x80, isa->io); + udelay(50); +- outb(0x00, zol->io); ++ outb(0x00, isa->io); + udelay(50); +- outb(0x80, zol->io); ++ outb(0x80, isa->io); + udelay(50); + } else { +- outb(0xc0, zol->io); ++ outb(0xc0, isa->io); + udelay(50); +- outb(0x40, zol->io); ++ outb(0x40, isa->io); + udelay(50); +- outb(0xc0, zol->io); ++ outb(0xc0, isa->io); + udelay(50); + } + bitmask *= 2; + } + /* termination sequence */ +- outb(0x80, zol->io); +- outb(0xc0, zol->io); +- outb(0x40, zol->io); ++ outb(0x80, isa->io); ++ outb(0xc0, isa->io); ++ outb(0x40, isa->io); + udelay(1000); +- inb(zol->io + 2); +- ++ inb(isa->io + 2); + udelay(1000); + +- if (zol->muted) { +- outb(0, zol->io); +- outb(0, zol->io); +- inb(zol->io + 3); +- udelay(1000); +- } +- +- mutex_unlock(&zol->lock); +- +- if (!zol->muted) +- zol_setvol(zol, zol->curvol); +- return 0; ++ return zoltrix_s_mute_volume(isa, zol->muted, zol->curvol); + } + + /* Get signal strength */ +-static int zol_getsigstr(struct zoltrix *zol) ++static u32 zoltrix_g_rxsubchans(struct radio_isa_card *isa) + { ++ struct zoltrix *zol = container_of(isa, struct zoltrix, isa); + int a, b; + +- mutex_lock(&zol->lock); +- outb(0x00, zol->io); /* This stuff I found to do nothing */ +- outb(zol->curvol, zol->io); ++ outb(0x00, isa->io); /* This stuff I found to do nothing */ ++ outb(zol->curvol, isa->io); + msleep(20); + +- a = inb(zol->io); ++ a = inb(isa->io); + msleep(10); +- b = inb(zol->io); +- +- mutex_unlock(&zol->lock); ++ b = inb(isa->io); + +- if (a != b) +- return 0; +- +- /* I found this out by playing with a binary scanner on the card io */ +- return a == 0xcf || a == 0xdf || a == 0xef; ++ return (a == b && a == 0xcf) ? ++ V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; + } + +-static int zol_is_stereo(struct zoltrix *zol) ++static u32 zoltrix_g_signal(struct radio_isa_card *isa) + { +- int x1, x2; +- +- mutex_lock(&zol->lock); ++ struct zoltrix *zol = container_of(isa, struct zoltrix, isa); ++ int a, b; + +- outb(0x00, zol->io); +- outb(zol->curvol, zol->io); ++ outb(0x00, isa->io); /* This stuff I found to do nothing */ ++ outb(zol->curvol, isa->io); + msleep(20); + +- x1 = inb(zol->io); ++ a = inb(isa->io); + msleep(10); +- x2 = inb(zol->io); +- +- mutex_unlock(&zol->lock); +- +- return x1 == x2 && x1 == 0xcf; +-} +- +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- strlcpy(v->driver, "radio-zoltrix", sizeof(v->driver)); +- strlcpy(v->card, "Zoltrix Radio", sizeof(v->card)); +- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; +- return 0; +-} +- +-static int vidioc_g_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- struct zoltrix *zol = video_drvdata(file); +- +- if (v->index > 0) +- return -EINVAL; +- +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- v->rangelow = 88 * 16000; +- v->rangehigh = 108 * 16000; +- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; +- v->capability = V4L2_TUNER_CAP_LOW; +- if (zol_is_stereo(zol)) +- v->audmode = V4L2_TUNER_MODE_STEREO; +- else +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->signal = 0xFFFF * zol_getsigstr(zol); +- return 0; +-} +- +-static int vidioc_s_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- return v->index ? -EINVAL : 0; +-} +- +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct zoltrix *zol = video_drvdata(file); +- +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- if (zol_setfreq(zol, f->frequency) != 0) +- return -EINVAL; +- return 0; +-} +- +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct zoltrix *zol = video_drvdata(file); +- +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = zol->curfreq; +- return 0; +-} +- +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- switch (qc->id) { +- case V4L2_CID_AUDIO_MUTE: +- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); +- case V4L2_CID_AUDIO_VOLUME: +- return v4l2_ctrl_query_fill(qc, 0, 65535, 4096, 65535); +- } +- return -EINVAL; +-} +- +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct zoltrix *zol = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- ctrl->value = zol->muted; +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- ctrl->value = zol->curvol * 4096; +- return 0; +- } +- return -EINVAL; +-} ++ b = inb(isa->io); + +-static int vidioc_s_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) +-{ +- struct zoltrix *zol = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- if (ctrl->value) +- zol_mute(zol); +- else { +- zol_unmute(zol); +- zol_setvol(zol, zol->curvol); +- } +- return 0; +- case V4L2_CID_AUDIO_VOLUME: +- zol_setvol(zol, ctrl->value / 4096); ++ if (a != b) + return 0; +- } +- zol->stereo = 1; +- if (zol_setfreq(zol, zol->curfreq) != 0) +- return -EINVAL; +-#if 0 +-/* FIXME: Implement stereo/mono switch on V4L2 */ +- if (v->mode & VIDEO_SOUND_STEREO) { +- zol->stereo = 1; +- zol_setfreq(zol, zol->curfreq); +- } +- if (v->mode & VIDEO_SOUND_MONO) { +- zol->stereo = 0; +- zol_setfreq(zol, zol->curfreq); +- } +-#endif +- return -EINVAL; +-} +- +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; +- return 0; +-} +- +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +-{ +- return i ? -EINVAL : 0; +-} + +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; ++ /* I found this out by playing with a binary scanner on the card io */ ++ return (a == 0xcf || a == 0xdf || a == 0xef) ? 0xffff : 0; + } + +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) ++static int zoltrix_s_stereo(struct radio_isa_card *isa, bool stereo) + { +- return a->index ? -EINVAL : 0; ++ return zoltrix_s_frequency(isa, isa->freq); + } + +-static const struct v4l2_file_operations zoltrix_fops = +-{ +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, ++static const struct radio_isa_ops zoltrix_ops = { ++ .alloc = zoltrix_alloc, ++ .s_mute_volume = zoltrix_s_mute_volume, ++ .s_frequency = zoltrix_s_frequency, ++ .s_stereo = zoltrix_s_stereo, ++ .g_rxsubchans = zoltrix_g_rxsubchans, ++ .g_signal = zoltrix_g_signal, + }; + +-static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = { +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl, ++static const int zoltrix_ioports[] = { 0x20c, 0x30c }; ++ ++static struct radio_isa_driver zoltrix_driver = { ++ .driver = { ++ .match = radio_isa_match, ++ .probe = radio_isa_probe, ++ .remove = radio_isa_remove, ++ .driver = { ++ .name = "radio-zoltrix", ++ }, ++ }, ++ .io_params = io, ++ .radio_nr_params = radio_nr, ++ .io_ports = zoltrix_ioports, ++ .num_of_io_ports = ARRAY_SIZE(zoltrix_ioports), ++ .region_size = 2, ++ .card = "Zoltrix Radio Plus", ++ .ops = &zoltrix_ops, ++ .has_stereo = true, ++ .max_volume = 15, + }; + + static int __init zoltrix_init(void) + { +- struct zoltrix *zol = &zoltrix_card; +- struct v4l2_device *v4l2_dev = &zol->v4l2_dev; +- int res; +- +- strlcpy(v4l2_dev->name, "zoltrix", sizeof(v4l2_dev->name)); +- zol->io = io; +- if (zol->io == -1) { +- v4l2_err(v4l2_dev, "You must set an I/O address with io=0x20c or 0x30c\n"); +- return -EINVAL; +- } +- if (zol->io != 0x20c && zol->io != 0x30c) { +- v4l2_err(v4l2_dev, "invalid port, try 0x20c or 0x30c\n"); +- return -ENXIO; +- } +- +- if (!request_region(zol->io, 2, "zoltrix")) { +- v4l2_err(v4l2_dev, "port 0x%x already in use\n", zol->io); +- return -EBUSY; +- } +- +- res = v4l2_device_register(NULL, v4l2_dev); +- if (res < 0) { +- release_region(zol->io, 2); +- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); +- return res; +- } +- +- mutex_init(&zol->lock); +- +- /* mute card - prevents noisy bootups */ +- +- /* this ensures that the volume is all the way down */ +- +- outb(0, zol->io); +- outb(0, zol->io); +- msleep(20); +- inb(zol->io + 3); +- +- zol->curvol = 0; +- zol->stereo = 1; +- +- strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name)); +- zol->vdev.v4l2_dev = v4l2_dev; +- zol->vdev.fops = &zoltrix_fops; +- zol->vdev.ioctl_ops = &zoltrix_ioctl_ops; +- zol->vdev.release = video_device_release_empty; +- video_set_drvdata(&zol->vdev, zol); +- +- if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_device_unregister(v4l2_dev); +- release_region(zol->io, 2); +- return -EINVAL; +- } +- v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n"); +- +- return 0; ++ return isa_register_driver(&zoltrix_driver.driver, ZOLTRIX_MAX); + } + + static void __exit zoltrix_exit(void) + { +- struct zoltrix *zol = &zoltrix_card; +- +- video_unregister_device(&zol->vdev); +- v4l2_device_unregister(&zol->v4l2_dev); +- release_region(zol->io, 2); ++ isa_unregister_driver(&zoltrix_driver.driver); + } + + module_init(zoltrix_init); +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-core/dvb_frontend.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-core/dvb_frontend.c ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-core/dvb_frontend.c +@@ -655,6 +655,8 @@ restart: + dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__); + re_tune = true; + fepriv->state = FESTATE_TUNED; ++ } else { ++ re_tune = false; + } + + if (fe->ops.tune) +Index: linux-3.3.x86_64/drivers/media/common/tuners/xc5000.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/common/tuners/xc5000.c ++++ linux-3.3.x86_64/drivers/media/common/tuners/xc5000.c +@@ -49,9 +49,6 @@ static LIST_HEAD(hybrid_tuner_instance_l + #define dprintk(level, fmt, arg...) if (debug >= level) \ + printk(KERN_INFO "%s: " fmt, "xc5000", ## arg) + +-#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.6.114.fw" +-#define XC5000_DEFAULT_FIRMWARE_SIZE 12401 +- + struct xc5000_priv { + struct tuner_i2c_props i2c_props; + struct list_head hybrid_tuner_instance_list; +@@ -62,6 +59,8 @@ struct xc5000_priv { + u8 video_standard; + u8 rf_mode; + u8 radio_input; ++ ++ int chip_id; + }; + + /* Misc Defines */ +@@ -204,6 +203,33 @@ static struct XC_TV_STANDARD XC5000_Stan + {"FM Radio-INPUT1_MONO", 0x0278, 0x9002} + }; + ++ ++struct xc5000_fw_cfg { ++ char *name; ++ u16 size; ++}; ++ ++static const struct xc5000_fw_cfg xc5000a_1_6_114 = { ++ .name = "dvb-fe-xc5000-1.6.114.fw", ++ .size = 12401, ++}; ++ ++static const struct xc5000_fw_cfg xc5000c_41_024_5_31875 = { ++ .name = "dvb-fe-xc5000c-41.024.5-31875.fw", ++ .size = 16503, ++}; ++ ++static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id) ++{ ++ switch (chip_id) { ++ default: ++ case XC5000A: ++ return &xc5000a_1_6_114; ++ case XC5000C: ++ return &xc5000c_41_024_5_31875; ++ } ++} ++ + static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe); + static int xc5000_is_firmware_loaded(struct dvb_frontend *fe); + static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val); +@@ -552,12 +578,14 @@ static int xc5000_fwupload(struct dvb_fr + struct xc5000_priv *priv = fe->tuner_priv; + const struct firmware *fw; + int ret; ++ const struct xc5000_fw_cfg *desired_fw = ++ xc5000_assign_firmware(priv->chip_id); + + /* request the firmware, this will block and timeout */ + printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", +- XC5000_DEFAULT_FIRMWARE); ++ desired_fw->name); + +- ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, ++ ret = request_firmware(&fw, desired_fw->name, + priv->i2c_props.adap->dev.parent); + if (ret) { + printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n"); +@@ -569,7 +597,7 @@ static int xc5000_fwupload(struct dvb_fr + ret = XC_RESULT_SUCCESS; + } + +- if (fw->size != XC5000_DEFAULT_FIRMWARE_SIZE) { ++ if (fw->size != desired_fw->size) { + printk(KERN_ERR "xc5000: firmware incorrect size\n"); + ret = XC_RESULT_RESET_FAILURE; + } else { +@@ -1139,6 +1167,13 @@ struct dvb_frontend *xc5000_attach(struc + if (priv->radio_input == 0) + priv->radio_input = cfg->radio_input; + ++ /* don't override chip id if it's already been set ++ unless explicitly specified */ ++ if ((priv->chip_id == 0) || (cfg->chip_id)) ++ /* use default chip id if none specified, set to 0 so ++ it can be overridden if this is a hybrid driver */ ++ priv->chip_id = (cfg->chip_id) ? cfg->chip_id : 0; ++ + /* Check if firmware has been loaded. It is possible that another + instance of the driver has loaded the firmware. + */ +Index: linux-3.3.x86_64/drivers/media/common/tuners/xc5000.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/common/tuners/xc5000.h ++++ linux-3.3.x86_64/drivers/media/common/tuners/xc5000.h +@@ -27,10 +27,15 @@ + struct dvb_frontend; + struct i2c_adapter; + ++#define XC5000A 1 ++#define XC5000C 2 ++ + struct xc5000_config { + u8 i2c_address; + u32 if_khz; + u8 radio_input; ++ ++ int chip_id; + }; + + /* xc5000 callback command */ +Index: linux-3.3.x86_64/drivers/media/common/tuners/tuner-types.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/common/tuners/tuner-types.c ++++ linux-3.3.x86_64/drivers/media/common/tuners/tuner-types.c +@@ -1868,6 +1868,10 @@ struct tunertype tuners[] = { + .params = tuner_tena_tnf_5337_params, + .count = ARRAY_SIZE(tuner_tena_tnf_5337_params), + }, ++ [TUNER_XC5000C] = { /* Xceive 5000C */ ++ .name = "Xceive 5000C tuner", ++ /* see xc5000.c for details */ ++ }, + }; + EXPORT_SYMBOL(tuners); + +Index: linux-3.3.x86_64/drivers/media/video/tuner-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tuner-core.c ++++ linux-3.3.x86_64/drivers/media/video/tuner-core.c +@@ -380,6 +380,21 @@ static void set_type(struct i2c_client * + tune_now = 0; + break; + } ++ case TUNER_XC5000C: ++ { ++ struct xc5000_config xc5000c_cfg = { ++ .i2c_address = t->i2c->addr, ++ /* if_khz will be set at dvb_attach() */ ++ .if_khz = 0, ++ .chip_id = XC5000C, ++ }; ++ ++ if (!dvb_attach(xc5000_attach, ++ &t->fe, t->i2c->adapter, &xc5000c_cfg)) ++ goto attach_failed; ++ tune_now = 0; ++ break; ++ } + case TUNER_NXP_TDA18271: + { + struct tda18271_config cfg = { +@@ -1314,18 +1329,7 @@ static struct i2c_driver tuner_driver = + .id_table = tuner_id, + }; + +-static __init int init_tuner(void) +-{ +- return i2c_add_driver(&tuner_driver); +-} +- +-static __exit void exit_tuner(void) +-{ +- i2c_del_driver(&tuner_driver); +-} +- +-module_init(init_tuner); +-module_exit(exit_tuner); ++module_i2c_driver(tuner_driver); + + MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners"); + MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); +Index: linux-3.3.x86_64/include/media/tuner.h +=================================================================== +--- linux-3.3.x86_64.orig/include/media/tuner.h ++++ linux-3.3.x86_64/include/media/tuner.h +@@ -136,6 +136,7 @@ + #define TUNER_TENA_TNF_5337 86 + + #define TUNER_XC4000 87 /* Xceive Silicon Tuner */ ++#define TUNER_XC5000C 88 /* Xceive Silicon Tuner */ + + /* tv card specific */ + #define TDA9887_PRESENT (1<<0) +Index: linux-3.3.x86_64/drivers/media/video/tveeprom.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tveeprom.c ++++ linux-3.3.x86_64/drivers/media/video/tveeprom.c +@@ -286,8 +286,16 @@ hauppauge_tuner[] = + { TUNER_ABSENT, "MaxLinear 301"}, + { TUNER_ABSENT, "Mirics MSi001"}, + { TUNER_ABSENT, "MaxLinear MxL241SF"}, +- { TUNER_ABSENT, "Xceive XC5000C"}, ++ { TUNER_XC5000C, "Xceive XC5000C"}, + { TUNER_ABSENT, "Montage M68TS2020"}, ++ { TUNER_ABSENT, "Siano SMS1530"}, ++ { TUNER_ABSENT, "Dibcom 7090"}, ++ { TUNER_ABSENT, "Xceive XC5200C"}, ++ { TUNER_ABSENT, "NXP 18273"}, ++ { TUNER_ABSENT, "Montage M88TS2022"}, ++ /* 180-189 */ ++ { TUNER_ABSENT, "NXP 18272M"}, ++ { TUNER_ABSENT, "NXP 18272S"}, + }; + + /* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are +Index: linux-3.3.x86_64/drivers/media/radio/radio-sf16fmr2.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-sf16fmr2.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-sf16fmr2.c +@@ -9,16 +9,23 @@ + #include + #include /* Modules */ + #include /* Initdata */ ++#include + #include /* request_region */ + #include /* outb, outb_p */ ++#include + #include + + MODULE_AUTHOR("Ondrej Zary"); + MODULE_DESCRIPTION("MediaForte SF16-FMR2 FM radio card driver"); + MODULE_LICENSE("GPL"); + ++static int radio_nr = -1; ++module_param(radio_nr, int, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device number"); ++ + struct fmr2 { + int io; ++ struct v4l2_device v4l2_dev; + struct snd_tea575x tea; + struct v4l2_ctrl *volume; + struct v4l2_ctrl *balance; +@@ -26,7 +33,6 @@ struct fmr2 { + + /* the port is hardwired so no need to support multiple cards */ + #define FMR2_PORT 0x384 +-static struct fmr2 fmr2_card; + + /* TEA575x tuner pins */ + #define STR_DATA (1 << 0) +@@ -172,7 +178,7 @@ static int fmr2_tea_ext_init(struct snd_ + fmr2->volume = v4l2_ctrl_new_std(&tea->ctrl_handler, &fmr2_ctrl_ops, V4L2_CID_AUDIO_VOLUME, 0, 68, 2, 56); + fmr2->balance = v4l2_ctrl_new_std(&tea->ctrl_handler, &fmr2_ctrl_ops, V4L2_CID_AUDIO_BALANCE, -68, 68, 2, 0); + if (tea->ctrl_handler.error) { +- printk(KERN_ERR "radio-sf16fmr2: can't initialize contrls\n"); ++ printk(KERN_ERR "radio-sf16fmr2: can't initialize controls\n"); + return tea->ctrl_handler.error; + } + } +@@ -180,26 +186,46 @@ static int fmr2_tea_ext_init(struct snd_ + return 0; + } + +-static int __init fmr2_init(void) ++static int __devinit fmr2_probe(struct device *pdev, unsigned int dev) + { +- struct fmr2 *fmr2 = &fmr2_card; ++ struct fmr2 *fmr2; ++ int err; ++ ++ fmr2 = kzalloc(sizeof(*fmr2), GFP_KERNEL); ++ if (fmr2 == NULL) ++ return -ENOMEM; + ++ strlcpy(fmr2->v4l2_dev.name, dev_name(pdev), ++ sizeof(fmr2->v4l2_dev.name)); + fmr2->io = FMR2_PORT; + +- if (!request_region(fmr2->io, 2, "SF16-FMR2")) { ++ if (!request_region(fmr2->io, 2, fmr2->v4l2_dev.name)) { + printk(KERN_ERR "radio-sf16fmr2: I/O port 0x%x already in use\n", fmr2->io); ++ kfree(fmr2); + return -EBUSY; + } + ++ dev_set_drvdata(pdev, fmr2); ++ err = v4l2_device_register(pdev, &fmr2->v4l2_dev); ++ if (err < 0) { ++ v4l2_err(&fmr2->v4l2_dev, "Could not register v4l2_device\n"); ++ release_region(fmr2->io, 2); ++ kfree(fmr2); ++ return err; ++ } ++ fmr2->tea.v4l2_dev = &fmr2->v4l2_dev; + fmr2->tea.private_data = fmr2; ++ fmr2->tea.radio_nr = radio_nr; + fmr2->tea.ops = &fmr2_tea_ops; + fmr2->tea.ext_init = fmr2_tea_ext_init; + strlcpy(fmr2->tea.card, "SF16-FMR2", sizeof(fmr2->tea.card)); +- strcpy(fmr2->tea.bus_info, "ISA"); ++ snprintf(fmr2->tea.bus_info, sizeof(fmr2->tea.bus_info), "ISA:%s", ++ fmr2->v4l2_dev.name); + + if (snd_tea575x_init(&fmr2->tea)) { + printk(KERN_ERR "radio-sf16fmr2: Unable to detect TEA575x tuner\n"); + release_region(fmr2->io, 2); ++ kfree(fmr2); + return -ENODEV; + } + +@@ -207,12 +233,33 @@ static int __init fmr2_init(void) + return 0; + } + +-static void __exit fmr2_exit(void) ++static int __exit fmr2_remove(struct device *pdev, unsigned int dev) + { +- struct fmr2 *fmr2 = &fmr2_card; ++ struct fmr2 *fmr2 = dev_get_drvdata(pdev); + + snd_tea575x_exit(&fmr2->tea); + release_region(fmr2->io, 2); ++ v4l2_device_unregister(&fmr2->v4l2_dev); ++ kfree(fmr2); ++ return 0; ++} ++ ++struct isa_driver fmr2_driver = { ++ .probe = fmr2_probe, ++ .remove = fmr2_remove, ++ .driver = { ++ .name = "radio-sf16fmr2", ++ }, ++}; ++ ++static int __init fmr2_init(void) ++{ ++ return isa_register_driver(&fmr2_driver, 1); ++} ++ ++static void __exit fmr2_exit(void) ++{ ++ isa_unregister_driver(&fmr2_driver); + } + + module_init(fmr2_init); +Index: linux-3.3.x86_64/drivers/media/video/davinci/dm355_ccdc.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/davinci/dm355_ccdc.c ++++ linux-3.3.x86_64/drivers/media/video/davinci/dm355_ccdc.c +@@ -292,7 +292,7 @@ static int validate_ccdc_param(struct cc + if ((ccdcparam->med_filt_thres < 0) || + (ccdcparam->med_filt_thres > CCDC_MED_FILT_THRESH)) { + dev_dbg(ccdc_cfg.dev, +- "Invalid value of median filter thresold\n"); ++ "Invalid value of median filter threshold\n"); + return -EINVAL; + } + +Index: linux-3.3.x86_64/drivers/media/video/Kconfig +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/Kconfig ++++ linux-3.3.x86_64/drivers/media/video/Kconfig +@@ -273,6 +273,16 @@ config VIDEO_ADV7180 + To compile this driver as a module, choose M here: the + module will be called adv7180. + ++config VIDEO_ADV7183 ++ tristate "Analog Devices ADV7183 decoder" ++ depends on VIDEO_V4L2 && I2C ++ ---help--- ++ V4l2 subdevice driver for the Analog Devices ++ ADV7183 video decoder. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called adv7183. ++ + config VIDEO_BT819 + tristate "BT819A VideoStream decoder" + depends on VIDEO_V4L2 && I2C +@@ -459,6 +469,9 @@ config VIDEO_AK881X + + comment "Camera sensor devices" + ++config VIDEO_APTINA_PLL ++ tristate ++ + config VIDEO_OV7670 + tristate "OmniVision OV7670 sensor support" + depends on I2C && VIDEO_V4L2 +@@ -467,9 +480,28 @@ config VIDEO_OV7670 + OV7670 VGA camera. It currently only works with the M88ALP01 + controller. + ++config VIDEO_VS6624 ++ tristate "ST VS6624 sensor support" ++ depends on VIDEO_V4L2 && I2C ++ ---help--- ++ This is a Video4Linux2 sensor-level driver for the ST VS6624 ++ camera. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called vs6624. ++ ++config VIDEO_MT9M032 ++ tristate "MT9M032 camera sensor support" ++ depends on I2C && VIDEO_V4L2 ++ select VIDEO_APTINA_PLL ++ ---help--- ++ This driver supports MT9M032 camera sensors from Aptina, monochrome ++ models only. ++ + config VIDEO_MT9P031 + tristate "Aptina MT9P031 support" + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API ++ select VIDEO_APTINA_PLL + ---help--- + This is a Video4Linux2 sensor-level driver for the Aptina + (Micron) mt9p031 5 Mpixel camera. +@@ -851,6 +883,8 @@ source "drivers/media/video/davinci/Kcon + + source "drivers/media/video/omap/Kconfig" + ++source "drivers/media/video/blackfin/Kconfig" ++ + config VIDEO_SH_VOU + tristate "SuperH VOU video output driver" + depends on VIDEO_DEV && ARCH_SHMOBILE +@@ -1087,7 +1121,7 @@ config VIDEO_MX2_HOSTSUPPORT + config VIDEO_MX2 + tristate "i.MX27/i.MX25 Camera Sensor Interface driver" + depends on VIDEO_DEV && SOC_CAMERA && (MACH_MX27 || ARCH_MX25) +- select VIDEOBUF_DMA_CONTIG ++ select VIDEOBUF2_DMA_CONTIG + select VIDEO_MX2_HOSTSUPPORT + ---help--- + This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor +@@ -1116,7 +1150,8 @@ config VIDEO_ATMEL_ISI + + config VIDEO_S5P_MIPI_CSIS + tristate "Samsung S5P and EXYNOS4 MIPI CSI receiver driver" +- depends on VIDEO_V4L2 && PM_RUNTIME && PLAT_S5P && VIDEO_V4L2_SUBDEV_API ++ depends on VIDEO_V4L2 && PM_RUNTIME && PLAT_S5P ++ depends on VIDEO_V4L2_SUBDEV_API && REGULATOR + ---help--- + This is a v4l2 driver for Samsung S5P/EXYNOS4 MIPI-CSI receiver. + +@@ -1176,4 +1211,14 @@ config VIDEO_SAMSUNG_S5P_MFC + help + MFC 5.1 driver for V4L2. + ++config VIDEO_MX2_EMMAPRP ++ tristate "MX2 eMMa-PrP support" ++ depends on VIDEO_DEV && VIDEO_V4L2 && SOC_IMX27 ++ select VIDEOBUF2_DMA_CONTIG ++ select V4L2_MEM2MEM_DEV ++ help ++ MX2X chips have a PrP that can be used to process buffers from ++ memory to memory. Operations include resizing and format ++ conversion. ++ + endif # V4L_MEM2MEM_DRIVERS +Index: linux-3.3.x86_64/drivers/media/video/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/Makefile ++++ linux-3.3.x86_64/drivers/media/video/Makefile +@@ -12,16 +12,19 @@ omap2cam-objs := omap24xxcam.o omap24xxc + + videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ + v4l2-event.o v4l2-ctrls.o v4l2-subdev.o ++ifeq ($(CONFIG_COMPAT),y) ++ videodev-objs += v4l2-compat-ioctl32.o ++endif + + # V4L2 core modules + + obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o +-ifeq ($(CONFIG_COMPAT),y) +- obj-$(CONFIG_VIDEO_DEV) += v4l2-compat-ioctl32.o +-endif +- + obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o + ++# Helper modules ++ ++obj-$(CONFIG_VIDEO_APTINA_PLL) += aptina-pll.o ++ + # All i2c modules must come first: + + obj-$(CONFIG_VIDEO_TUNER) += tuner.o +@@ -40,8 +43,10 @@ obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o + obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o + obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o + obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o ++obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o + obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o + obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o ++obj-$(CONFIG_VIDEO_VS6624) += vs6624.o + obj-$(CONFIG_VIDEO_BT819) += bt819.o + obj-$(CONFIG_VIDEO_BT856) += bt856.o + obj-$(CONFIG_VIDEO_BT866) += bt866.o +@@ -65,6 +70,7 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083 + obj-$(CONFIG_VIDEO_OV7670) += ov7670.o + obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o + obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o ++obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o + obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o + obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o + obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o +@@ -177,6 +183,8 @@ obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_ + obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o + obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o + ++obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o ++ + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/ + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg/ + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) += s5p-mfc/ +@@ -184,6 +192,8 @@ obj-$(CONFIG_VIDEO_SAMSUNG_S5P_TV) += s5 + + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D) += s5p-g2d/ + ++obj-$(CONFIG_BLACKFIN) += blackfin/ ++ + obj-$(CONFIG_ARCH_DAVINCI) += davinci/ + + obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o +@@ -199,6 +209,6 @@ obj-y += davinci/ + + obj-$(CONFIG_ARCH_OMAP) += omap/ + +-ccflags-y += -Idrivers/media/dvb/dvb-core +-ccflags-y += -Idrivers/media/dvb/frontends +-ccflags-y += -Idrivers/media/common/tuners ++ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core ++ccflags-y += -I$(srctree)/drivers/media/dvb/frontends ++ccflags-y += -I$(srctree)/drivers/media/common/tuners +Index: linux-3.3.x86_64/drivers/media/video/mx2_emmaprp.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/mx2_emmaprp.c +@@ -0,0 +1,1008 @@ ++/* ++ * Support eMMa-PrP through mem2mem framework. ++ * ++ * eMMa-PrP is a piece of HW that allows fetching buffers ++ * from one memory location and do several operations on ++ * them such as scaling or format conversion giving, as a result ++ * a new processed buffer in another memory location. ++ * ++ * Based on mem2mem_testdev.c by Pawel Osciak. ++ * ++ * Copyright (c) 2011 Vista Silicon S.L. ++ * Javier Martin ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version ++ */ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define EMMAPRP_MODULE_NAME "mem2mem-emmaprp" ++ ++MODULE_DESCRIPTION("Mem-to-mem device which supports eMMa-PrP present in mx2 SoCs"); ++MODULE_AUTHOR("Javier Martin v4l2_dev, "%s: " fmt, __func__, ## arg) ++ ++/* EMMA PrP */ ++#define PRP_CNTL 0x00 ++#define PRP_INTR_CNTL 0x04 ++#define PRP_INTRSTATUS 0x08 ++#define PRP_SOURCE_Y_PTR 0x0c ++#define PRP_SOURCE_CB_PTR 0x10 ++#define PRP_SOURCE_CR_PTR 0x14 ++#define PRP_DEST_RGB1_PTR 0x18 ++#define PRP_DEST_RGB2_PTR 0x1c ++#define PRP_DEST_Y_PTR 0x20 ++#define PRP_DEST_CB_PTR 0x24 ++#define PRP_DEST_CR_PTR 0x28 ++#define PRP_SRC_FRAME_SIZE 0x2c ++#define PRP_DEST_CH1_LINE_STRIDE 0x30 ++#define PRP_SRC_PIXEL_FORMAT_CNTL 0x34 ++#define PRP_CH1_PIXEL_FORMAT_CNTL 0x38 ++#define PRP_CH1_OUT_IMAGE_SIZE 0x3c ++#define PRP_CH2_OUT_IMAGE_SIZE 0x40 ++#define PRP_SRC_LINE_STRIDE 0x44 ++#define PRP_CSC_COEF_012 0x48 ++#define PRP_CSC_COEF_345 0x4c ++#define PRP_CSC_COEF_678 0x50 ++#define PRP_CH1_RZ_HORI_COEF1 0x54 ++#define PRP_CH1_RZ_HORI_COEF2 0x58 ++#define PRP_CH1_RZ_HORI_VALID 0x5c ++#define PRP_CH1_RZ_VERT_COEF1 0x60 ++#define PRP_CH1_RZ_VERT_COEF2 0x64 ++#define PRP_CH1_RZ_VERT_VALID 0x68 ++#define PRP_CH2_RZ_HORI_COEF1 0x6c ++#define PRP_CH2_RZ_HORI_COEF2 0x70 ++#define PRP_CH2_RZ_HORI_VALID 0x74 ++#define PRP_CH2_RZ_VERT_COEF1 0x78 ++#define PRP_CH2_RZ_VERT_COEF2 0x7c ++#define PRP_CH2_RZ_VERT_VALID 0x80 ++ ++#define PRP_CNTL_CH1EN (1 << 0) ++#define PRP_CNTL_CH2EN (1 << 1) ++#define PRP_CNTL_CSIEN (1 << 2) ++#define PRP_CNTL_DATA_IN_YUV420 (0 << 3) ++#define PRP_CNTL_DATA_IN_YUV422 (1 << 3) ++#define PRP_CNTL_DATA_IN_RGB16 (2 << 3) ++#define PRP_CNTL_DATA_IN_RGB32 (3 << 3) ++#define PRP_CNTL_CH1_OUT_RGB8 (0 << 5) ++#define PRP_CNTL_CH1_OUT_RGB16 (1 << 5) ++#define PRP_CNTL_CH1_OUT_RGB32 (2 << 5) ++#define PRP_CNTL_CH1_OUT_YUV422 (3 << 5) ++#define PRP_CNTL_CH2_OUT_YUV420 (0 << 7) ++#define PRP_CNTL_CH2_OUT_YUV422 (1 << 7) ++#define PRP_CNTL_CH2_OUT_YUV444 (2 << 7) ++#define PRP_CNTL_CH1_LEN (1 << 9) ++#define PRP_CNTL_CH2_LEN (1 << 10) ++#define PRP_CNTL_SKIP_FRAME (1 << 11) ++#define PRP_CNTL_SWRST (1 << 12) ++#define PRP_CNTL_CLKEN (1 << 13) ++#define PRP_CNTL_WEN (1 << 14) ++#define PRP_CNTL_CH1BYP (1 << 15) ++#define PRP_CNTL_IN_TSKIP(x) ((x) << 16) ++#define PRP_CNTL_CH1_TSKIP(x) ((x) << 19) ++#define PRP_CNTL_CH2_TSKIP(x) ((x) << 22) ++#define PRP_CNTL_INPUT_FIFO_LEVEL(x) ((x) << 25) ++#define PRP_CNTL_RZ_FIFO_LEVEL(x) ((x) << 27) ++#define PRP_CNTL_CH2B1EN (1 << 29) ++#define PRP_CNTL_CH2B2EN (1 << 30) ++#define PRP_CNTL_CH2FEN (1 << 31) ++ ++#define PRP_SIZE_HEIGHT(x) (x) ++#define PRP_SIZE_WIDTH(x) ((x) << 16) ++ ++/* IRQ Enable and status register */ ++#define PRP_INTR_RDERR (1 << 0) ++#define PRP_INTR_CH1WERR (1 << 1) ++#define PRP_INTR_CH2WERR (1 << 2) ++#define PRP_INTR_CH1FC (1 << 3) ++#define PRP_INTR_CH2FC (1 << 5) ++#define PRP_INTR_LBOVF (1 << 7) ++#define PRP_INTR_CH2OVF (1 << 8) ++ ++#define PRP_INTR_ST_RDERR (1 << 0) ++#define PRP_INTR_ST_CH1WERR (1 << 1) ++#define PRP_INTR_ST_CH2WERR (1 << 2) ++#define PRP_INTR_ST_CH2B2CI (1 << 3) ++#define PRP_INTR_ST_CH2B1CI (1 << 4) ++#define PRP_INTR_ST_CH1B2CI (1 << 5) ++#define PRP_INTR_ST_CH1B1CI (1 << 6) ++#define PRP_INTR_ST_LBOVF (1 << 7) ++#define PRP_INTR_ST_CH2OVF (1 << 8) ++ ++struct emmaprp_fmt { ++ char *name; ++ u32 fourcc; ++ /* Types the format can be used for */ ++ u32 types; ++}; ++ ++static struct emmaprp_fmt formats[] = { ++ { ++ .name = "YUV 4:2:0 Planar", ++ .fourcc = V4L2_PIX_FMT_YUV420, ++ .types = MEM2MEM_CAPTURE, ++ }, ++ { ++ .name = "4:2:2, packed, YUYV", ++ .fourcc = V4L2_PIX_FMT_YUYV, ++ .types = MEM2MEM_OUTPUT, ++ }, ++}; ++ ++/* Per-queue, driver-specific private data */ ++struct emmaprp_q_data { ++ unsigned int width; ++ unsigned int height; ++ unsigned int sizeimage; ++ struct emmaprp_fmt *fmt; ++}; ++ ++enum { ++ V4L2_M2M_SRC = 0, ++ V4L2_M2M_DST = 1, ++}; ++ ++#define NUM_FORMATS ARRAY_SIZE(formats) ++ ++static struct emmaprp_fmt *find_format(struct v4l2_format *f) ++{ ++ struct emmaprp_fmt *fmt; ++ unsigned int k; ++ ++ for (k = 0; k < NUM_FORMATS; k++) { ++ fmt = &formats[k]; ++ if (fmt->fourcc == f->fmt.pix.pixelformat) ++ break; ++ } ++ ++ if (k == NUM_FORMATS) ++ return NULL; ++ ++ return &formats[k]; ++} ++ ++struct emmaprp_dev { ++ struct v4l2_device v4l2_dev; ++ struct video_device *vfd; ++ ++ struct mutex dev_mutex; ++ spinlock_t irqlock; ++ ++ int irq_emma; ++ void __iomem *base_emma; ++ struct clk *clk_emma; ++ struct resource *res_emma; ++ ++ struct v4l2_m2m_dev *m2m_dev; ++ struct vb2_alloc_ctx *alloc_ctx; ++}; ++ ++struct emmaprp_ctx { ++ struct emmaprp_dev *dev; ++ /* Abort requested by m2m */ ++ int aborting; ++ struct emmaprp_q_data q_data[2]; ++ struct v4l2_m2m_ctx *m2m_ctx; ++}; ++ ++static struct emmaprp_q_data *get_q_data(struct emmaprp_ctx *ctx, ++ enum v4l2_buf_type type) ++{ ++ switch (type) { ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT: ++ return &(ctx->q_data[V4L2_M2M_SRC]); ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ return &(ctx->q_data[V4L2_M2M_DST]); ++ default: ++ BUG(); ++ } ++ return NULL; ++} ++ ++/* ++ * mem2mem callbacks ++ */ ++static void emmaprp_job_abort(void *priv) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ struct emmaprp_dev *pcdev = ctx->dev; ++ ++ ctx->aborting = 1; ++ ++ dprintk(pcdev, "Aborting task\n"); ++ ++ v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->m2m_ctx); ++} ++ ++static void emmaprp_lock(void *priv) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ struct emmaprp_dev *pcdev = ctx->dev; ++ mutex_lock(&pcdev->dev_mutex); ++} ++ ++static void emmaprp_unlock(void *priv) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ struct emmaprp_dev *pcdev = ctx->dev; ++ mutex_unlock(&pcdev->dev_mutex); ++} ++ ++static inline void emmaprp_dump_regs(struct emmaprp_dev *pcdev) ++{ ++ dprintk(pcdev, ++ "eMMa-PrP Registers:\n" ++ " SOURCE_Y_PTR = 0x%08X\n" ++ " SRC_FRAME_SIZE = 0x%08X\n" ++ " DEST_Y_PTR = 0x%08X\n" ++ " DEST_CR_PTR = 0x%08X\n" ++ " DEST_CB_PTR = 0x%08X\n" ++ " CH2_OUT_IMAGE_SIZE = 0x%08X\n" ++ " CNTL = 0x%08X\n", ++ readl(pcdev->base_emma + PRP_SOURCE_Y_PTR), ++ readl(pcdev->base_emma + PRP_SRC_FRAME_SIZE), ++ readl(pcdev->base_emma + PRP_DEST_Y_PTR), ++ readl(pcdev->base_emma + PRP_DEST_CR_PTR), ++ readl(pcdev->base_emma + PRP_DEST_CB_PTR), ++ readl(pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE), ++ readl(pcdev->base_emma + PRP_CNTL)); ++} ++ ++static void emmaprp_device_run(void *priv) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ struct emmaprp_q_data *s_q_data, *d_q_data; ++ struct vb2_buffer *src_buf, *dst_buf; ++ struct emmaprp_dev *pcdev = ctx->dev; ++ unsigned int s_width, s_height; ++ unsigned int d_width, d_height; ++ unsigned int d_size; ++ dma_addr_t p_in, p_out; ++ u32 tmp; ++ ++ src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); ++ dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); ++ ++ s_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ s_width = s_q_data->width; ++ s_height = s_q_data->height; ++ ++ d_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ d_width = d_q_data->width; ++ d_height = d_q_data->height; ++ d_size = d_width * d_height; ++ ++ p_in = vb2_dma_contig_plane_dma_addr(src_buf, 0); ++ p_out = vb2_dma_contig_plane_dma_addr(dst_buf, 0); ++ if (!p_in || !p_out) { ++ v4l2_err(&pcdev->v4l2_dev, ++ "Acquiring kernel pointers to buffers failed\n"); ++ return; ++ } ++ ++ /* Input frame parameters */ ++ writel(p_in, pcdev->base_emma + PRP_SOURCE_Y_PTR); ++ writel(PRP_SIZE_WIDTH(s_width) | PRP_SIZE_HEIGHT(s_height), ++ pcdev->base_emma + PRP_SRC_FRAME_SIZE); ++ ++ /* Output frame parameters */ ++ writel(p_out, pcdev->base_emma + PRP_DEST_Y_PTR); ++ writel(p_out + d_size, pcdev->base_emma + PRP_DEST_CB_PTR); ++ writel(p_out + d_size + (d_size >> 2), ++ pcdev->base_emma + PRP_DEST_CR_PTR); ++ writel(PRP_SIZE_WIDTH(d_width) | PRP_SIZE_HEIGHT(d_height), ++ pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); ++ ++ /* IRQ configuration */ ++ tmp = readl(pcdev->base_emma + PRP_INTR_CNTL); ++ writel(tmp | PRP_INTR_RDERR | ++ PRP_INTR_CH2WERR | ++ PRP_INTR_CH2FC, ++ pcdev->base_emma + PRP_INTR_CNTL); ++ ++ emmaprp_dump_regs(pcdev); ++ ++ /* Enable transfer */ ++ tmp = readl(pcdev->base_emma + PRP_CNTL); ++ writel(tmp | PRP_CNTL_CH2_OUT_YUV420 | ++ PRP_CNTL_DATA_IN_YUV422 | ++ PRP_CNTL_CH2EN, ++ pcdev->base_emma + PRP_CNTL); ++} ++ ++static irqreturn_t emmaprp_irq(int irq_emma, void *data) ++{ ++ struct emmaprp_dev *pcdev = data; ++ struct emmaprp_ctx *curr_ctx; ++ struct vb2_buffer *src_vb, *dst_vb; ++ unsigned long flags; ++ u32 irqst; ++ ++ /* Check irq flags and clear irq */ ++ irqst = readl(pcdev->base_emma + PRP_INTRSTATUS); ++ writel(irqst, pcdev->base_emma + PRP_INTRSTATUS); ++ dprintk(pcdev, "irqst = 0x%08x\n", irqst); ++ ++ curr_ctx = v4l2_m2m_get_curr_priv(pcdev->m2m_dev); ++ if (curr_ctx == NULL) { ++ pr_err("Instance released before the end of transaction\n"); ++ return IRQ_HANDLED; ++ } ++ ++ if (!curr_ctx->aborting) { ++ if ((irqst & PRP_INTR_ST_RDERR) || ++ (irqst & PRP_INTR_ST_CH2WERR)) { ++ pr_err("PrP bus error ocurred, this transfer is probably corrupted\n"); ++ writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL); ++ } else if (irqst & PRP_INTR_ST_CH2B1CI) { /* buffer ready */ ++ src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); ++ dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx); ++ ++ spin_lock_irqsave(&pcdev->irqlock, flags); ++ v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE); ++ v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE); ++ spin_unlock_irqrestore(&pcdev->irqlock, flags); ++ } ++ } ++ ++ v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->m2m_ctx); ++ return IRQ_HANDLED; ++} ++ ++/* ++ * video ioctls ++ */ ++static int vidioc_querycap(struct file *file, void *priv, ++ struct v4l2_capability *cap) ++{ ++ strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1); ++ strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1); ++ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT ++ | V4L2_CAP_STREAMING; ++ ++ return 0; ++} ++ ++static int enum_fmt(struct v4l2_fmtdesc *f, u32 type) ++{ ++ int i, num; ++ struct emmaprp_fmt *fmt; ++ ++ num = 0; ++ ++ for (i = 0; i < NUM_FORMATS; ++i) { ++ if (formats[i].types & type) { ++ /* index-th format of type type found ? */ ++ if (num == f->index) ++ break; ++ /* Correct type but haven't reached our index yet, ++ * just increment per-type index */ ++ ++num; ++ } ++ } ++ ++ if (i < NUM_FORMATS) { ++ /* Format found */ ++ fmt = &formats[i]; ++ strlcpy(f->description, fmt->name, sizeof(f->description) - 1); ++ f->pixelformat = fmt->fourcc; ++ return 0; ++ } ++ ++ /* Format not found */ ++ return -EINVAL; ++} ++ ++static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_fmtdesc *f) ++{ ++ return enum_fmt(f, MEM2MEM_CAPTURE); ++} ++ ++static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, ++ struct v4l2_fmtdesc *f) ++{ ++ return enum_fmt(f, MEM2MEM_OUTPUT); ++} ++ ++static int vidioc_g_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f) ++{ ++ struct vb2_queue *vq; ++ struct emmaprp_q_data *q_data; ++ ++ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); ++ if (!vq) ++ return -EINVAL; ++ ++ q_data = get_q_data(ctx, f->type); ++ ++ f->fmt.pix.width = q_data->width; ++ f->fmt.pix.height = q_data->height; ++ f->fmt.pix.field = V4L2_FIELD_NONE; ++ f->fmt.pix.pixelformat = q_data->fmt->fourcc; ++ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) ++ f->fmt.pix.bytesperline = q_data->width * 3 / 2; ++ else /* YUYV */ ++ f->fmt.pix.bytesperline = q_data->width * 2; ++ f->fmt.pix.sizeimage = q_data->sizeimage; ++ ++ return 0; ++} ++ ++static int vidioc_g_fmt_vid_out(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ return vidioc_g_fmt(priv, f); ++} ++ ++static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ return vidioc_g_fmt(priv, f); ++} ++ ++static int vidioc_try_fmt(struct v4l2_format *f) ++{ ++ enum v4l2_field field; ++ ++ ++ if (!find_format(f)) ++ return -EINVAL; ++ ++ field = f->fmt.pix.field; ++ if (field == V4L2_FIELD_ANY) ++ field = V4L2_FIELD_NONE; ++ else if (V4L2_FIELD_NONE != field) ++ return -EINVAL; ++ ++ /* V4L2 specification suggests the driver corrects the format struct ++ * if any of the dimensions is unsupported */ ++ f->fmt.pix.field = field; ++ ++ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) { ++ v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, ++ W_ALIGN_YUV420, &f->fmt.pix.height, ++ MIN_H, MAX_H, H_ALIGN, S_ALIGN); ++ f->fmt.pix.bytesperline = f->fmt.pix.width * 3 / 2; ++ } else { ++ v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, ++ W_ALIGN_OTHERS, &f->fmt.pix.height, ++ MIN_H, MAX_H, H_ALIGN, S_ALIGN); ++ f->fmt.pix.bytesperline = f->fmt.pix.width * 2; ++ } ++ f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; ++ ++ return 0; ++} ++ ++static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct emmaprp_fmt *fmt; ++ struct emmaprp_ctx *ctx = priv; ++ ++ fmt = find_format(f); ++ if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) { ++ v4l2_err(&ctx->dev->v4l2_dev, ++ "Fourcc format (0x%08x) invalid.\n", ++ f->fmt.pix.pixelformat); ++ return -EINVAL; ++ } ++ ++ return vidioc_try_fmt(f); ++} ++ ++static int vidioc_try_fmt_vid_out(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct emmaprp_fmt *fmt; ++ struct emmaprp_ctx *ctx = priv; ++ ++ fmt = find_format(f); ++ if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) { ++ v4l2_err(&ctx->dev->v4l2_dev, ++ "Fourcc format (0x%08x) invalid.\n", ++ f->fmt.pix.pixelformat); ++ return -EINVAL; ++ } ++ ++ return vidioc_try_fmt(f); ++} ++ ++static int vidioc_s_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f) ++{ ++ struct emmaprp_q_data *q_data; ++ struct vb2_queue *vq; ++ int ret; ++ ++ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); ++ if (!vq) ++ return -EINVAL; ++ ++ q_data = get_q_data(ctx, f->type); ++ if (!q_data) ++ return -EINVAL; ++ ++ if (vb2_is_busy(vq)) { ++ v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__); ++ return -EBUSY; ++ } ++ ++ ret = vidioc_try_fmt(f); ++ if (ret) ++ return ret; ++ ++ q_data->fmt = find_format(f); ++ q_data->width = f->fmt.pix.width; ++ q_data->height = f->fmt.pix.height; ++ if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420) ++ q_data->sizeimage = q_data->width * q_data->height * 3 / 2; ++ else /* YUYV */ ++ q_data->sizeimage = q_data->width * q_data->height * 2; ++ ++ dprintk(ctx->dev, ++ "Setting format for type %d, wxh: %dx%d, fmt: %d\n", ++ f->type, q_data->width, q_data->height, q_data->fmt->fourcc); ++ ++ return 0; ++} ++ ++static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ int ret; ++ ++ ret = vidioc_try_fmt_vid_cap(file, priv, f); ++ if (ret) ++ return ret; ++ ++ return vidioc_s_fmt(priv, f); ++} ++ ++static int vidioc_s_fmt_vid_out(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ int ret; ++ ++ ret = vidioc_try_fmt_vid_out(file, priv, f); ++ if (ret) ++ return ret; ++ ++ return vidioc_s_fmt(priv, f); ++} ++ ++static int vidioc_reqbufs(struct file *file, void *priv, ++ struct v4l2_requestbuffers *reqbufs) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ ++ return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); ++} ++ ++static int vidioc_querybuf(struct file *file, void *priv, ++ struct v4l2_buffer *buf) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ ++ return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); ++} ++ ++static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ ++ return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); ++} ++ ++static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ ++ return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); ++} ++ ++static int vidioc_streamon(struct file *file, void *priv, ++ enum v4l2_buf_type type) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ ++ return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); ++} ++ ++static int vidioc_streamoff(struct file *file, void *priv, ++ enum v4l2_buf_type type) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ ++ return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); ++} ++ ++static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = { ++ .vidioc_querycap = vidioc_querycap, ++ ++ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, ++ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, ++ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, ++ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, ++ ++ .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, ++ .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out, ++ .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, ++ .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, ++ ++ .vidioc_reqbufs = vidioc_reqbufs, ++ .vidioc_querybuf = vidioc_querybuf, ++ ++ .vidioc_qbuf = vidioc_qbuf, ++ .vidioc_dqbuf = vidioc_dqbuf, ++ ++ .vidioc_streamon = vidioc_streamon, ++ .vidioc_streamoff = vidioc_streamoff, ++}; ++ ++ ++/* ++ * Queue operations ++ */ ++static int emmaprp_queue_setup(struct vb2_queue *vq, ++ const struct v4l2_format *fmt, ++ unsigned int *nbuffers, unsigned int *nplanes, ++ unsigned int sizes[], void *alloc_ctxs[]) ++{ ++ struct emmaprp_ctx *ctx = vb2_get_drv_priv(vq); ++ struct emmaprp_q_data *q_data; ++ unsigned int size, count = *nbuffers; ++ ++ q_data = get_q_data(ctx, vq->type); ++ ++ if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420) ++ size = q_data->width * q_data->height * 3 / 2; ++ else ++ size = q_data->width * q_data->height * 2; ++ ++ while (size * count > MEM2MEM_VID_MEM_LIMIT) ++ (count)--; ++ ++ *nplanes = 1; ++ *nbuffers = count; ++ sizes[0] = size; ++ ++ alloc_ctxs[0] = ctx->dev->alloc_ctx; ++ ++ dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size); ++ ++ return 0; ++} ++ ++static int emmaprp_buf_prepare(struct vb2_buffer *vb) ++{ ++ struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); ++ struct emmaprp_q_data *q_data; ++ ++ dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type); ++ ++ q_data = get_q_data(ctx, vb->vb2_queue->type); ++ ++ if (vb2_plane_size(vb, 0) < q_data->sizeimage) { ++ dprintk(ctx->dev, "%s data will not fit into plane" ++ "(%lu < %lu)\n", __func__, ++ vb2_plane_size(vb, 0), ++ (long)q_data->sizeimage); ++ return -EINVAL; ++ } ++ ++ vb2_set_plane_payload(vb, 0, q_data->sizeimage); ++ ++ return 0; ++} ++ ++static void emmaprp_buf_queue(struct vb2_buffer *vb) ++{ ++ struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); ++ v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); ++} ++ ++static struct vb2_ops emmaprp_qops = { ++ .queue_setup = emmaprp_queue_setup, ++ .buf_prepare = emmaprp_buf_prepare, ++ .buf_queue = emmaprp_buf_queue, ++}; ++ ++static int queue_init(void *priv, struct vb2_queue *src_vq, ++ struct vb2_queue *dst_vq) ++{ ++ struct emmaprp_ctx *ctx = priv; ++ int ret; ++ ++ memset(src_vq, 0, sizeof(*src_vq)); ++ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ src_vq->io_modes = VB2_MMAP; ++ src_vq->drv_priv = ctx; ++ src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); ++ src_vq->ops = &emmaprp_qops; ++ src_vq->mem_ops = &vb2_dma_contig_memops; ++ ++ ret = vb2_queue_init(src_vq); ++ if (ret) ++ return ret; ++ ++ memset(dst_vq, 0, sizeof(*dst_vq)); ++ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ dst_vq->io_modes = VB2_MMAP; ++ dst_vq->drv_priv = ctx; ++ dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); ++ dst_vq->ops = &emmaprp_qops; ++ dst_vq->mem_ops = &vb2_dma_contig_memops; ++ ++ return vb2_queue_init(dst_vq); ++} ++ ++/* ++ * File operations ++ */ ++static int emmaprp_open(struct file *file) ++{ ++ struct emmaprp_dev *pcdev = video_drvdata(file); ++ struct emmaprp_ctx *ctx; ++ ++ ctx = kzalloc(sizeof *ctx, GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ ++ file->private_data = ctx; ++ ctx->dev = pcdev; ++ ++ ctx->m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init); ++ ++ if (IS_ERR(ctx->m2m_ctx)) { ++ int ret = PTR_ERR(ctx->m2m_ctx); ++ ++ kfree(ctx); ++ return ret; ++ } ++ ++ clk_enable(pcdev->clk_emma); ++ ctx->q_data[V4L2_M2M_SRC].fmt = &formats[1]; ++ ctx->q_data[V4L2_M2M_DST].fmt = &formats[0]; ++ ++ dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx); ++ ++ return 0; ++} ++ ++static int emmaprp_release(struct file *file) ++{ ++ struct emmaprp_dev *pcdev = video_drvdata(file); ++ struct emmaprp_ctx *ctx = file->private_data; ++ ++ dprintk(pcdev, "Releasing instance %p\n", ctx); ++ ++ clk_disable(pcdev->clk_emma); ++ v4l2_m2m_ctx_release(ctx->m2m_ctx); ++ kfree(ctx); ++ ++ return 0; ++} ++ ++static unsigned int emmaprp_poll(struct file *file, ++ struct poll_table_struct *wait) ++{ ++ struct emmaprp_ctx *ctx = file->private_data; ++ ++ return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); ++} ++ ++static int emmaprp_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ struct emmaprp_ctx *ctx = file->private_data; ++ ++ return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); ++} ++ ++static const struct v4l2_file_operations emmaprp_fops = { ++ .owner = THIS_MODULE, ++ .open = emmaprp_open, ++ .release = emmaprp_release, ++ .poll = emmaprp_poll, ++ .unlocked_ioctl = video_ioctl2, ++ .mmap = emmaprp_mmap, ++}; ++ ++static struct video_device emmaprp_videodev = { ++ .name = MEM2MEM_NAME, ++ .fops = &emmaprp_fops, ++ .ioctl_ops = &emmaprp_ioctl_ops, ++ .minor = -1, ++ .release = video_device_release, ++}; ++ ++static struct v4l2_m2m_ops m2m_ops = { ++ .device_run = emmaprp_device_run, ++ .job_abort = emmaprp_job_abort, ++ .lock = emmaprp_lock, ++ .unlock = emmaprp_unlock, ++}; ++ ++static int emmaprp_probe(struct platform_device *pdev) ++{ ++ struct emmaprp_dev *pcdev; ++ struct video_device *vfd; ++ struct resource *res_emma; ++ int irq_emma; ++ int ret; ++ ++ pcdev = kzalloc(sizeof *pcdev, GFP_KERNEL); ++ if (!pcdev) ++ return -ENOMEM; ++ ++ spin_lock_init(&pcdev->irqlock); ++ ++ pcdev->clk_emma = clk_get(&pdev->dev, NULL); ++ if (IS_ERR(pcdev->clk_emma)) { ++ ret = PTR_ERR(pcdev->clk_emma); ++ goto free_dev; ++ } ++ ++ irq_emma = platform_get_irq(pdev, 0); ++ res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (irq_emma < 0 || res_emma == NULL) { ++ dev_err(&pdev->dev, "Missing platform resources data\n"); ++ ret = -ENODEV; ++ goto free_clk; ++ } ++ ++ ret = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev); ++ if (ret) ++ goto free_clk; ++ ++ mutex_init(&pcdev->dev_mutex); ++ ++ vfd = video_device_alloc(); ++ if (!vfd) { ++ v4l2_err(&pcdev->v4l2_dev, "Failed to allocate video device\n"); ++ ret = -ENOMEM; ++ goto unreg_dev; ++ } ++ ++ *vfd = emmaprp_videodev; ++ vfd->lock = &pcdev->dev_mutex; ++ ++ video_set_drvdata(vfd, pcdev); ++ snprintf(vfd->name, sizeof(vfd->name), "%s", emmaprp_videodev.name); ++ pcdev->vfd = vfd; ++ v4l2_info(&pcdev->v4l2_dev, EMMAPRP_MODULE_NAME ++ " Device registered as /dev/video%d\n", vfd->num); ++ ++ platform_set_drvdata(pdev, pcdev); ++ ++ if (devm_request_mem_region(&pdev->dev, res_emma->start, ++ resource_size(res_emma), MEM2MEM_NAME) == NULL) ++ goto rel_vdev; ++ ++ pcdev->base_emma = devm_ioremap(&pdev->dev, res_emma->start, ++ resource_size(res_emma)); ++ if (!pcdev->base_emma) ++ goto rel_vdev; ++ ++ pcdev->irq_emma = irq_emma; ++ pcdev->res_emma = res_emma; ++ ++ if (devm_request_irq(&pdev->dev, pcdev->irq_emma, emmaprp_irq, ++ 0, MEM2MEM_NAME, pcdev) < 0) ++ goto rel_vdev; ++ ++ pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); ++ if (IS_ERR(pcdev->alloc_ctx)) { ++ v4l2_err(&pcdev->v4l2_dev, "Failed to alloc vb2 context\n"); ++ ret = PTR_ERR(pcdev->alloc_ctx); ++ goto rel_vdev; ++ } ++ ++ pcdev->m2m_dev = v4l2_m2m_init(&m2m_ops); ++ if (IS_ERR(pcdev->m2m_dev)) { ++ v4l2_err(&pcdev->v4l2_dev, "Failed to init mem2mem device\n"); ++ ret = PTR_ERR(pcdev->m2m_dev); ++ goto rel_ctx; ++ } ++ ++ ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); ++ if (ret) { ++ v4l2_err(&pcdev->v4l2_dev, "Failed to register video device\n"); ++ goto rel_m2m; ++ } ++ ++ return 0; ++ ++ ++rel_m2m: ++ v4l2_m2m_release(pcdev->m2m_dev); ++rel_ctx: ++ vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); ++rel_vdev: ++ video_device_release(vfd); ++unreg_dev: ++ v4l2_device_unregister(&pcdev->v4l2_dev); ++free_clk: ++ clk_put(pcdev->clk_emma); ++free_dev: ++ kfree(pcdev); ++ ++ return ret; ++} ++ ++static int emmaprp_remove(struct platform_device *pdev) ++{ ++ struct emmaprp_dev *pcdev = platform_get_drvdata(pdev); ++ ++ v4l2_info(&pcdev->v4l2_dev, "Removing " EMMAPRP_MODULE_NAME); ++ ++ video_unregister_device(pcdev->vfd); ++ v4l2_m2m_release(pcdev->m2m_dev); ++ vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); ++ v4l2_device_unregister(&pcdev->v4l2_dev); ++ clk_put(pcdev->clk_emma); ++ kfree(pcdev); ++ ++ return 0; ++} ++ ++static struct platform_driver emmaprp_pdrv = { ++ .probe = emmaprp_probe, ++ .remove = emmaprp_remove, ++ .driver = { ++ .name = MEM2MEM_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static void __exit emmaprp_exit(void) ++{ ++ platform_driver_unregister(&emmaprp_pdrv); ++} ++ ++static int __init emmaprp_init(void) ++{ ++ return platform_driver_register(&emmaprp_pdrv); ++} ++ ++module_init(emmaprp_init); ++module_exit(emmaprp_exit); +Index: linux-3.3.x86_64/drivers/media/common/tuners/mt2063.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/common/tuners/mt2063.h ++++ linux-3.3.x86_64/drivers/media/common/tuners/mt2063.h +@@ -23,10 +23,6 @@ static inline struct dvb_frontend *mt206 + return NULL; + } + +-int mt2063_setTune(struct dvb_frontend *fe, u32 f_in, +- u32 bw_in, +- enum MTTune_atv_standard tv_type); +- + /* FIXME: Should use the standard DVB attachment interfaces */ + unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe); + unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe); +Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/sdo_drv.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/sdo_drv.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-tv/sdo_drv.c +@@ -301,7 +301,7 @@ static int __devinit sdo_probe(struct pl + struct clk *sclk_vpll; + + dev_info(dev, "probe start\n"); +- sdev = kzalloc(sizeof *sdev, GFP_KERNEL); ++ sdev = devm_kzalloc(&pdev->dev, sizeof *sdev, GFP_KERNEL); + if (!sdev) { + dev_err(dev, "not enough memory.\n"); + ret = -ENOMEM; +@@ -314,14 +314,14 @@ static int __devinit sdo_probe(struct pl + if (res == NULL) { + dev_err(dev, "get memory resource failed.\n"); + ret = -ENXIO; +- goto fail_sdev; ++ goto fail; + } + +- sdev->regs = ioremap(res->start, resource_size(res)); ++ sdev->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (sdev->regs == NULL) { + dev_err(dev, "register mapping failed.\n"); + ret = -ENXIO; +- goto fail_sdev; ++ goto fail; + } + + /* acquiring interrupt */ +@@ -329,12 +329,13 @@ static int __devinit sdo_probe(struct pl + if (res == NULL) { + dev_err(dev, "get interrupt resource failed.\n"); + ret = -ENXIO; +- goto fail_regs; ++ goto fail; + } +- ret = request_irq(res->start, sdo_irq_handler, 0, "s5p-sdo", sdev); ++ ret = devm_request_irq(&pdev->dev, res->start, sdo_irq_handler, 0, ++ "s5p-sdo", sdev); + if (ret) { + dev_err(dev, "request interrupt failed.\n"); +- goto fail_regs; ++ goto fail; + } + sdev->irq = res->start; + +@@ -343,7 +344,7 @@ static int __devinit sdo_probe(struct pl + if (IS_ERR_OR_NULL(sdev->sclk_dac)) { + dev_err(dev, "failed to get clock 'sclk_dac'\n"); + ret = -ENXIO; +- goto fail_irq; ++ goto fail; + } + sdev->dac = clk_get(dev, "dac"); + if (IS_ERR_OR_NULL(sdev->dac)) { +@@ -415,12 +416,6 @@ fail_dac: + clk_put(sdev->dac); + fail_sclk_dac: + clk_put(sdev->sclk_dac); +-fail_irq: +- free_irq(sdev->irq, sdev); +-fail_regs: +- iounmap(sdev->regs); +-fail_sdev: +- kfree(sdev); + fail: + dev_info(dev, "probe failed\n"); + return ret; +@@ -439,9 +434,6 @@ static int __devexit sdo_remove(struct p + clk_put(sdev->dacphy); + clk_put(sdev->dac); + clk_put(sdev->sclk_dac); +- free_irq(sdev->irq, sdev); +- iounmap(sdev->regs); +- kfree(sdev); + + dev_info(&pdev->dev, "remove successful\n"); + return 0; +Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/Kconfig +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/Kconfig ++++ linux-3.3.x86_64/drivers/media/video/s5p-tv/Kconfig +@@ -46,6 +46,16 @@ config VIDEO_SAMSUNG_S5P_HDMIPHY + as module. It is an I2C driver, that exposes a V4L2 + subdev for use by other drivers. + ++config VIDEO_SAMSUNG_S5P_SII9234 ++ tristate "Samsung SII9234 Driver" ++ depends on VIDEO_DEV && VIDEO_V4L2 && I2C ++ depends on VIDEO_SAMSUNG_S5P_TV ++ help ++ Say Y here if you want support for the MHL interface ++ in S5P Samsung SoC. The driver can be compiled ++ as module. It is an I2C driver, that exposes a V4L2 ++ subdev for use by other drivers. ++ + config VIDEO_SAMSUNG_S5P_SDO + tristate "Samsung Analog TV Driver" + depends on VIDEO_DEV && VIDEO_V4L2 +Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/Makefile ++++ linux-3.3.x86_64/drivers/media/video/s5p-tv/Makefile +@@ -8,6 +8,8 @@ + + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMIPHY) += s5p-hdmiphy.o + s5p-hdmiphy-y += hdmiphy_drv.o ++obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SII9234) += s5p-sii9234.o ++s5p-sii9234-y += sii9234_drv.o + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMI) += s5p-hdmi.o + s5p-hdmi-y += hdmi_drv.o + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SDO) += s5p-sdo.o +Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/sii9234_drv.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/s5p-tv/sii9234_drv.c +@@ -0,0 +1,432 @@ ++/* ++ * Samsung MHL interface driver ++ * ++ * Copyright (C) 2011 Samsung Electronics Co.Ltd ++ * Author: Tomasz Stanislawski ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++MODULE_AUTHOR("Tomasz Stanislawski "); ++MODULE_DESCRIPTION("Samsung MHL interface driver"); ++MODULE_LICENSE("GPL"); ++ ++struct sii9234_context { ++ struct i2c_client *client; ++ struct regulator *power; ++ int gpio_n_reset; ++ struct v4l2_subdev sd; ++}; ++ ++static inline struct sii9234_context *sd_to_context(struct v4l2_subdev *sd) ++{ ++ return container_of(sd, struct sii9234_context, sd); ++} ++ ++static inline int sii9234_readb(struct i2c_client *client, int addr) ++{ ++ return i2c_smbus_read_byte_data(client, addr); ++} ++ ++static inline int sii9234_writeb(struct i2c_client *client, int addr, int value) ++{ ++ return i2c_smbus_write_byte_data(client, addr, value); ++} ++ ++static inline int sii9234_writeb_mask(struct i2c_client *client, int addr, ++ int value, int mask) ++{ ++ int ret; ++ ++ ret = i2c_smbus_read_byte_data(client, addr); ++ if (ret < 0) ++ return ret; ++ ret = (ret & ~mask) | (value & mask); ++ return i2c_smbus_write_byte_data(client, addr, ret); ++} ++ ++static inline int sii9234_readb_idx(struct i2c_client *client, int addr) ++{ ++ int ret; ++ ret = i2c_smbus_write_byte_data(client, 0xbc, addr >> 8); ++ if (ret < 0) ++ return ret; ++ ret = i2c_smbus_write_byte_data(client, 0xbd, addr & 0xff); ++ if (ret < 0) ++ return ret; ++ return i2c_smbus_read_byte_data(client, 0xbe); ++} ++ ++static inline int sii9234_writeb_idx(struct i2c_client *client, int addr, ++ int value) ++{ ++ int ret; ++ ret = i2c_smbus_write_byte_data(client, 0xbc, addr >> 8); ++ if (ret < 0) ++ return ret; ++ ret = i2c_smbus_write_byte_data(client, 0xbd, addr & 0xff); ++ if (ret < 0) ++ return ret; ++ ret = i2c_smbus_write_byte_data(client, 0xbe, value); ++ return ret; ++} ++ ++static inline int sii9234_writeb_idx_mask(struct i2c_client *client, int addr, ++ int value, int mask) ++{ ++ int ret; ++ ++ ret = sii9234_readb_idx(client, addr); ++ if (ret < 0) ++ return ret; ++ ret = (ret & ~mask) | (value & mask); ++ return sii9234_writeb_idx(client, addr, ret); ++} ++ ++static int sii9234_reset(struct sii9234_context *ctx) ++{ ++ struct i2c_client *client = ctx->client; ++ struct device *dev = &client->dev; ++ int ret, tries; ++ ++ gpio_direction_output(ctx->gpio_n_reset, 1); ++ mdelay(1); ++ gpio_direction_output(ctx->gpio_n_reset, 0); ++ mdelay(1); ++ gpio_direction_output(ctx->gpio_n_reset, 1); ++ mdelay(1); ++ ++ /* going to TTPI mode */ ++ ret = sii9234_writeb(client, 0xc7, 0); ++ if (ret < 0) { ++ dev_err(dev, "failed to set TTPI mode\n"); ++ return ret; ++ } ++ for (tries = 0; tries < 100 ; ++tries) { ++ ret = sii9234_readb(client, 0x1b); ++ if (ret > 0) ++ break; ++ if (ret < 0) { ++ dev_err(dev, "failed to reset device\n"); ++ return -EIO; ++ } ++ mdelay(1); ++ } ++ if (tries == 100) { ++ dev_err(dev, "maximal number of tries reached\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int sii9234_verify_version(struct i2c_client *client) ++{ ++ struct device *dev = &client->dev; ++ int family, rev, tpi_rev, dev_id, sub_id, hdcp, id; ++ ++ family = sii9234_readb(client, 0x1b); ++ rev = sii9234_readb(client, 0x1c) & 0x0f; ++ tpi_rev = sii9234_readb(client, 0x1d) & 0x7f; ++ dev_id = sii9234_readb_idx(client, 0x0103); ++ sub_id = sii9234_readb_idx(client, 0x0102); ++ hdcp = sii9234_readb(client, 0x30); ++ ++ if (family < 0 || rev < 0 || tpi_rev < 0 || dev_id < 0 || ++ sub_id < 0 || hdcp < 0) { ++ dev_err(dev, "failed to read chip's version\n"); ++ return -EIO; ++ } ++ ++ id = (dev_id << 8) | sub_id; ++ ++ dev_info(dev, "chip: SiL%02x family: %02x, rev: %02x\n", ++ id, family, rev); ++ dev_info(dev, "tpi_rev:%02x, hdcp: %02x\n", tpi_rev, hdcp); ++ if (id != 0x9234) { ++ dev_err(dev, "not supported chip\n"); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static u8 data[][3] = { ++/* setup from driver created by doonsoo45.kim */ ++ { 0x01, 0x05, 0x04 }, /* Enable Auto soft reset on SCDT = 0 */ ++ { 0x01, 0x08, 0x35 }, /* Power Up TMDS Tx Core */ ++ { 0x01, 0x0d, 0x1c }, /* HDMI Transcode mode enable */ ++ { 0x01, 0x2b, 0x01 }, /* Enable HDCP Compliance workaround */ ++ { 0x01, 0x79, 0x40 }, /* daniel test...MHL_INT */ ++ { 0x01, 0x80, 0x34 }, /* Enable Rx PLL Clock Value */ ++ { 0x01, 0x90, 0x27 }, /* Enable CBUS discovery */ ++ { 0x01, 0x91, 0xe5 }, /* Skip RGND detection */ ++ { 0x01, 0x92, 0x46 }, /* Force MHD mode */ ++ { 0x01, 0x93, 0xdc }, /* Disable CBUS pull-up during RGND measurement */ ++ { 0x01, 0x94, 0x66 }, /* 1.8V CBUS VTH & GND threshold */ ++ { 0x01, 0x95, 0x31 }, /* RGND block & single discovery attempt */ ++ { 0x01, 0x96, 0x22 }, /* use 1K and 2K setting */ ++ { 0x01, 0xa0, 0x10 }, /* SIMG: Term mode */ ++ { 0x01, 0xa1, 0xfc }, /* Disable internal Mobile HD driver */ ++ { 0x01, 0xa3, 0xfa }, /* SIMG: Output Swing default EB, 3x Clk Mult */ ++ { 0x01, 0xa5, 0x80 }, /* SIMG: RGND Hysterisis, 3x mode for Beast */ ++ { 0x01, 0xa6, 0x0c }, /* SIMG: Swing Offset */ ++ { 0x02, 0x3d, 0x3f }, /* Power up CVCC 1.2V core */ ++ { 0x03, 0x00, 0x00 }, /* SIMG: correcting HW default */ ++ { 0x03, 0x11, 0x01 }, /* Enable TxPLL Clock */ ++ { 0x03, 0x12, 0x15 }, /* Enable Tx Clock Path & Equalizer */ ++ { 0x03, 0x13, 0x60 }, /* SIMG: Set termination value */ ++ { 0x03, 0x14, 0xf0 }, /* SIMG: Change CKDT level */ ++ { 0x03, 0x17, 0x07 }, /* SIMG: PLL Calrefsel */ ++ { 0x03, 0x1a, 0x20 }, /* VCO Cal */ ++ { 0x03, 0x22, 0xe0 }, /* SIMG: Auto EQ */ ++ { 0x03, 0x23, 0xc0 }, /* SIMG: Auto EQ */ ++ { 0x03, 0x24, 0xa0 }, /* SIMG: Auto EQ */ ++ { 0x03, 0x25, 0x80 }, /* SIMG: Auto EQ */ ++ { 0x03, 0x26, 0x60 }, /* SIMG: Auto EQ */ ++ { 0x03, 0x27, 0x40 }, /* SIMG: Auto EQ */ ++ { 0x03, 0x28, 0x20 }, /* SIMG: Auto EQ */ ++ { 0x03, 0x29, 0x00 }, /* SIMG: Auto EQ */ ++ { 0x03, 0x31, 0x0b }, /* SIMG: Rx PLL BW value from I2C BW ~ 4MHz */ ++ { 0x03, 0x45, 0x06 }, /* SIMG: DPLL Mode */ ++ { 0x03, 0x4b, 0x06 }, /* SIMG: Correcting HW default */ ++ { 0x03, 0x4c, 0xa0 }, /* Manual zone control */ ++ { 0x03, 0x4d, 0x02 }, /* SIMG: PLL Mode Value (order is important) */ ++}; ++ ++static int sii9234_set_internal(struct sii9234_context *ctx) ++{ ++ struct i2c_client *client = ctx->client; ++ int i, ret; ++ ++ for (i = 0; i < ARRAY_SIZE(data); ++i) { ++ int addr = (data[i][0] << 8) | data[i][1]; ++ ret = sii9234_writeb_idx(client, addr, data[i][2]); ++ if (ret < 0) ++ return ret; ++ } ++ return 0; ++} ++ ++static int sii9234_runtime_suspend(struct device *dev) ++{ ++ struct v4l2_subdev *sd = dev_get_drvdata(dev); ++ struct sii9234_context *ctx = sd_to_context(sd); ++ struct i2c_client *client = ctx->client; ++ ++ dev_info(dev, "suspend start\n"); ++ ++ sii9234_writeb_mask(client, 0x1e, 3, 3); ++ regulator_disable(ctx->power); ++ ++ return 0; ++} ++ ++static int sii9234_runtime_resume(struct device *dev) ++{ ++ struct v4l2_subdev *sd = dev_get_drvdata(dev); ++ struct sii9234_context *ctx = sd_to_context(sd); ++ struct i2c_client *client = ctx->client; ++ int ret; ++ ++ dev_info(dev, "resume start\n"); ++ regulator_enable(ctx->power); ++ ++ ret = sii9234_reset(ctx); ++ if (ret) ++ goto fail; ++ ++ /* enable tpi */ ++ ret = sii9234_writeb_mask(client, 0x1e, 1, 0); ++ if (ret < 0) ++ goto fail; ++ ret = sii9234_set_internal(ctx); ++ if (ret < 0) ++ goto fail; ++ ++ return 0; ++ ++fail: ++ dev_err(dev, "failed to resume\n"); ++ regulator_disable(ctx->power); ++ ++ return ret; ++} ++ ++static const struct dev_pm_ops sii9234_pm_ops = { ++ .runtime_suspend = sii9234_runtime_suspend, ++ .runtime_resume = sii9234_runtime_resume, ++}; ++ ++static int sii9234_s_power(struct v4l2_subdev *sd, int on) ++{ ++ struct sii9234_context *ctx = sd_to_context(sd); ++ int ret; ++ ++ if (on) ++ ret = pm_runtime_get_sync(&ctx->client->dev); ++ else ++ ret = pm_runtime_put(&ctx->client->dev); ++ /* only values < 0 indicate errors */ ++ return IS_ERR_VALUE(ret) ? ret : 0; ++} ++ ++static int sii9234_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ struct sii9234_context *ctx = sd_to_context(sd); ++ ++ /* (dis/en)able TDMS output */ ++ sii9234_writeb_mask(ctx->client, 0x1a, enable ? 0 : ~0 , 1 << 4); ++ return 0; ++} ++ ++static const struct v4l2_subdev_core_ops sii9234_core_ops = { ++ .s_power = sii9234_s_power, ++}; ++ ++static const struct v4l2_subdev_video_ops sii9234_video_ops = { ++ .s_stream = sii9234_s_stream, ++}; ++ ++static const struct v4l2_subdev_ops sii9234_ops = { ++ .core = &sii9234_core_ops, ++ .video = &sii9234_video_ops, ++}; ++ ++static int __devinit sii9234_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct device *dev = &client->dev; ++ struct sii9234_platform_data *pdata = dev->platform_data; ++ struct sii9234_context *ctx; ++ int ret; ++ ++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) { ++ dev_err(dev, "out of memory\n"); ++ ret = -ENOMEM; ++ goto fail; ++ } ++ ctx->client = client; ++ ++ ctx->power = regulator_get(dev, "hdmi-en"); ++ if (IS_ERR(ctx->power)) { ++ dev_err(dev, "failed to acquire regulator hdmi-en\n"); ++ ret = PTR_ERR(ctx->power); ++ goto fail_ctx; ++ } ++ ++ ctx->gpio_n_reset = pdata->gpio_n_reset; ++ ret = gpio_request(ctx->gpio_n_reset, "MHL_RST"); ++ if (ret) { ++ dev_err(dev, "failed to acquire MHL_RST gpio\n"); ++ goto fail_power; ++ } ++ ++ v4l2_i2c_subdev_init(&ctx->sd, client, &sii9234_ops); ++ ++ pm_runtime_enable(dev); ++ ++ /* enable device */ ++ ret = pm_runtime_get_sync(dev); ++ if (ret) ++ goto fail_pm; ++ ++ /* verify chip version */ ++ ret = sii9234_verify_version(client); ++ if (ret) ++ goto fail_pm_get; ++ ++ /* stop processing */ ++ pm_runtime_put(dev); ++ ++ dev_info(dev, "probe successful\n"); ++ ++ return 0; ++ ++fail_pm_get: ++ pm_runtime_put_sync(dev); ++ ++fail_pm: ++ pm_runtime_disable(dev); ++ gpio_free(ctx->gpio_n_reset); ++ ++fail_power: ++ regulator_put(ctx->power); ++ ++fail_ctx: ++ kfree(ctx); ++ ++fail: ++ dev_err(dev, "probe failed\n"); ++ ++ return ret; ++} ++ ++static int __devexit sii9234_remove(struct i2c_client *client) ++{ ++ struct device *dev = &client->dev; ++ struct v4l2_subdev *sd = i2c_get_clientdata(client); ++ struct sii9234_context *ctx = sd_to_context(sd); ++ ++ pm_runtime_disable(dev); ++ gpio_free(ctx->gpio_n_reset); ++ regulator_put(ctx->power); ++ kfree(ctx); ++ ++ dev_info(dev, "remove successful\n"); ++ ++ return 0; ++} ++ ++ ++static const struct i2c_device_id sii9234_id[] = { ++ { "SII9234", 0 }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(i2c, sii9234_id); ++static struct i2c_driver sii9234_driver = { ++ .driver = { ++ .name = "sii9234", ++ .owner = THIS_MODULE, ++ .pm = &sii9234_pm_ops, ++ }, ++ .probe = sii9234_probe, ++ .remove = __devexit_p(sii9234_remove), ++ .id_table = sii9234_id, ++}; ++ ++static int __init sii9234_init(void) ++{ ++ return i2c_add_driver(&sii9234_driver); ++} ++module_init(sii9234_init); ++ ++static void __exit sii9234_exit(void) ++{ ++ i2c_del_driver(&sii9234_driver); ++} ++module_exit(sii9234_exit); +Index: linux-3.3.x86_64/include/media/sii9234.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/include/media/sii9234.h +@@ -0,0 +1,24 @@ ++/* ++ * Driver header for SII9234 MHL converter chip. ++ * ++ * Copyright (c) 2011 Samsung Electronics, Co. Ltd ++ * Contact: Tomasz Stanislawski ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#ifndef SII9234_H ++#define SII9234_H ++ ++/** ++ * @gpio_n_reset: GPIO driving nRESET pin ++ */ ++ ++struct sii9234_platform_data { ++ int gpio_n_reset; ++}; ++ ++#endif /* SII9234_H */ +Index: linux-3.3.x86_64/include/media/s5p_hdmi.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/include/media/s5p_hdmi.h +@@ -0,0 +1,35 @@ ++/* ++ * Driver header for S5P HDMI chip. ++ * ++ * Copyright (c) 2011 Samsung Electronics, Co. Ltd ++ * Contact: Tomasz Stanislawski ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#ifndef S5P_HDMI_H ++#define S5P_HDMI_H ++ ++struct i2c_board_info; ++ ++/** ++ * @hdmiphy_bus: controller id for HDMIPHY bus ++ * @hdmiphy_info: template for HDMIPHY I2C device ++ * @mhl_bus: controller id for MHL control bus ++ * @mhl_info: template for MHL I2C device ++ * ++ * NULL pointer for *_info fields indicates that ++ * the corresponding chip is not present ++ */ ++struct s5p_hdmi_platform_data { ++ int hdmiphy_bus; ++ struct i2c_board_info *hdmiphy_info; ++ int mhl_bus; ++ struct i2c_board_info *mhl_info; ++}; ++ ++#endif /* S5P_HDMI_H */ ++ +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/Kconfig +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/Kconfig ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/Kconfig +@@ -425,6 +425,13 @@ config DVB_CXD2820R + help + Say Y when you want to support this frontend. + ++config DVB_RTL2830 ++ tristate "Realtek RTL2830 DVB-T" ++ depends on DVB_CORE && I2C ++ default m if DVB_FE_CUSTOMISE ++ help ++ Say Y when you want to support this frontend. ++ + comment "DVB-C (cable) frontends" + depends on DVB_CORE + +@@ -698,6 +705,19 @@ config DVB_IT913X_FE + A DVB-T tuner module. + Say Y when you want to support this frontend. + ++config DVB_M88RS2000 ++ tristate "M88RS2000 DVB-S demodulator and tuner" ++ depends on DVB_CORE && I2C ++ default m if DVB_FE_CUSTOMISE ++ help ++ A DVB-S tuner module. ++ Say Y when you want to support this frontend. ++ ++config DVB_AF9033 ++ tristate "Afatech AF9033 DVB-T demodulator" ++ depends on DVB_CORE && I2C ++ default m if DVB_FE_CUSTOMISE ++ + comment "Tools to develop new frontends" + + config DVB_DUMMY_FE +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/Makefile ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/Makefile +@@ -2,8 +2,8 @@ + # Makefile for the kernel DVB frontend device drivers. + # + +-ccflags-y += -Idrivers/media/dvb/dvb-core/ +-ccflags-y += -Idrivers/media/common/tuners/ ++ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core/ ++ccflags-y += -I$(srctree)/drivers/media/common/tuners/ + + stb0899-objs = stb0899_drv.o stb0899_algo.o + stv0900-objs = stv0900_core.o stv0900_sw.o +@@ -96,4 +96,7 @@ obj-$(CONFIG_DVB_TDA18271C2DD) += tda182 + obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o + obj-$(CONFIG_DVB_A8293) += a8293.o + obj-$(CONFIG_DVB_TDA10071) += tda10071.o ++obj-$(CONFIG_DVB_RTL2830) += rtl2830.o ++obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o ++obj-$(CONFIG_DVB_AF9033) += af9033.o + +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830.c +@@ -0,0 +1,562 @@ ++/* ++ * Realtek RTL2830 DVB-T demodulator driver ++ * ++ * Copyright (C) 2011 Antti Palosaari ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++ ++/* ++ * Driver implements own I2C-adapter for tuner I2C access. That's since chip ++ * have unusual I2C-gate control which closes gate automatically after each ++ * I2C transfer. Using own I2C adapter we can workaround that. ++ */ ++ ++#include "rtl2830_priv.h" ++ ++int rtl2830_debug; ++module_param_named(debug, rtl2830_debug, int, 0644); ++MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); ++ ++/* write multiple hardware registers */ ++static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, u8 *val, int len) ++{ ++ int ret; ++ u8 buf[1+len]; ++ struct i2c_msg msg[1] = { ++ { ++ .addr = priv->cfg.i2c_addr, ++ .flags = 0, ++ .len = 1+len, ++ .buf = buf, ++ } ++ }; ++ ++ buf[0] = reg; ++ memcpy(&buf[1], val, len); ++ ++ ret = i2c_transfer(priv->i2c, msg, 1); ++ if (ret == 1) { ++ ret = 0; ++ } else { ++ warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len); ++ ret = -EREMOTEIO; ++ } ++ return ret; ++} ++ ++/* read multiple hardware registers */ ++static int rtl2830_rd(struct rtl2830_priv *priv, u8 reg, u8 *val, int len) ++{ ++ int ret; ++ struct i2c_msg msg[2] = { ++ { ++ .addr = priv->cfg.i2c_addr, ++ .flags = 0, ++ .len = 1, ++ .buf = ®, ++ }, { ++ .addr = priv->cfg.i2c_addr, ++ .flags = I2C_M_RD, ++ .len = len, ++ .buf = val, ++ } ++ }; ++ ++ ret = i2c_transfer(priv->i2c, msg, 2); ++ if (ret == 2) { ++ ret = 0; ++ } else { ++ warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len); ++ ret = -EREMOTEIO; ++ } ++ return ret; ++} ++ ++/* write multiple registers */ ++static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) ++{ ++ int ret; ++ u8 reg2 = (reg >> 0) & 0xff; ++ u8 page = (reg >> 8) & 0xff; ++ ++ /* switch bank if needed */ ++ if (page != priv->page) { ++ ret = rtl2830_wr(priv, 0x00, &page, 1); ++ if (ret) ++ return ret; ++ ++ priv->page = page; ++ } ++ ++ return rtl2830_wr(priv, reg2, val, len); ++} ++ ++/* read multiple registers */ ++static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) ++{ ++ int ret; ++ u8 reg2 = (reg >> 0) & 0xff; ++ u8 page = (reg >> 8) & 0xff; ++ ++ /* switch bank if needed */ ++ if (page != priv->page) { ++ ret = rtl2830_wr(priv, 0x00, &page, 1); ++ if (ret) ++ return ret; ++ ++ priv->page = page; ++ } ++ ++ return rtl2830_rd(priv, reg2, val, len); ++} ++ ++#if 0 /* currently not used */ ++/* write single register */ ++static int rtl2830_wr_reg(struct rtl2830_priv *priv, u16 reg, u8 val) ++{ ++ return rtl2830_wr_regs(priv, reg, &val, 1); ++} ++#endif ++ ++/* read single register */ ++static int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val) ++{ ++ return rtl2830_rd_regs(priv, reg, val, 1); ++} ++ ++/* write single register with mask */ ++int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask) ++{ ++ int ret; ++ u8 tmp; ++ ++ /* no need for read if whole reg is written */ ++ if (mask != 0xff) { ++ ret = rtl2830_rd_regs(priv, reg, &tmp, 1); ++ if (ret) ++ return ret; ++ ++ val &= mask; ++ tmp &= ~mask; ++ val |= tmp; ++ } ++ ++ return rtl2830_wr_regs(priv, reg, &val, 1); ++} ++ ++/* read single register with mask */ ++int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask) ++{ ++ int ret, i; ++ u8 tmp; ++ ++ ret = rtl2830_rd_regs(priv, reg, &tmp, 1); ++ if (ret) ++ return ret; ++ ++ tmp &= mask; ++ ++ /* find position of the first bit */ ++ for (i = 0; i < 8; i++) { ++ if ((mask >> i) & 0x01) ++ break; ++ } ++ *val = tmp >> i; ++ ++ return 0; ++} ++ ++static int rtl2830_init(struct dvb_frontend *fe) ++{ ++ struct rtl2830_priv *priv = fe->demodulator_priv; ++ int ret, i; ++ u64 num; ++ u8 buf[3], tmp; ++ u32 if_ctl; ++ struct rtl2830_reg_val_mask tab[] = { ++ { 0x00d, 0x01, 0x03 }, ++ { 0x00d, 0x10, 0x10 }, ++ { 0x104, 0x00, 0x1e }, ++ { 0x105, 0x80, 0x80 }, ++ { 0x110, 0x02, 0x03 }, ++ { 0x110, 0x08, 0x0c }, ++ { 0x17b, 0x00, 0x40 }, ++ { 0x17d, 0x05, 0x0f }, ++ { 0x17d, 0x50, 0xf0 }, ++ { 0x18c, 0x08, 0x0f }, ++ { 0x18d, 0x00, 0xc0 }, ++ { 0x188, 0x05, 0x0f }, ++ { 0x189, 0x00, 0xfc }, ++ { 0x2d5, 0x02, 0x02 }, ++ { 0x2f1, 0x02, 0x06 }, ++ { 0x2f1, 0x20, 0xf8 }, ++ { 0x16d, 0x00, 0x01 }, ++ { 0x1a6, 0x00, 0x80 }, ++ { 0x106, priv->cfg.vtop, 0x3f }, ++ { 0x107, priv->cfg.krf, 0x3f }, ++ { 0x112, 0x28, 0xff }, ++ { 0x103, priv->cfg.agc_targ_val, 0xff }, ++ { 0x00a, 0x02, 0x07 }, ++ { 0x140, 0x0c, 0x3c }, ++ { 0x140, 0x40, 0xc0 }, ++ { 0x15b, 0x05, 0x07 }, ++ { 0x15b, 0x28, 0x38 }, ++ { 0x15c, 0x05, 0x07 }, ++ { 0x15c, 0x28, 0x38 }, ++ { 0x115, priv->cfg.spec_inv, 0x01 }, ++ { 0x16f, 0x01, 0x07 }, ++ { 0x170, 0x18, 0x38 }, ++ { 0x172, 0x0f, 0x0f }, ++ { 0x173, 0x08, 0x38 }, ++ { 0x175, 0x01, 0x07 }, ++ { 0x176, 0x00, 0xc0 }, ++ }; ++ ++ for (i = 0; i < ARRAY_SIZE(tab); i++) { ++ ret = rtl2830_wr_reg_mask(priv, tab[i].reg, tab[i].val, ++ tab[i].mask); ++ if (ret) ++ goto err; ++ } ++ ++ ret = rtl2830_wr_regs(priv, 0x18f, "\x28\x00", 2); ++ if (ret) ++ goto err; ++ ++ ret = rtl2830_wr_regs(priv, 0x195, ++ "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8); ++ if (ret) ++ goto err; ++ ++ num = priv->cfg.if_dvbt % priv->cfg.xtal; ++ num *= 0x400000; ++ num = div_u64(num, priv->cfg.xtal); ++ num = -num; ++ if_ctl = num & 0x3fffff; ++ dbg("%s: if_ctl=%08x", __func__, if_ctl); ++ ++ ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */ ++ if (ret) ++ goto err; ++ ++ buf[0] = tmp << 6; ++ buf[0] = (if_ctl >> 16) & 0x3f; ++ buf[1] = (if_ctl >> 8) & 0xff; ++ buf[2] = (if_ctl >> 0) & 0xff; ++ ++ ret = rtl2830_wr_regs(priv, 0x119, buf, 3); ++ if (ret) ++ goto err; ++ ++ /* TODO: spec init */ ++ ++ /* soft reset */ ++ ret = rtl2830_wr_reg_mask(priv, 0x101, 0x04, 0x04); ++ if (ret) ++ goto err; ++ ++ ret = rtl2830_wr_reg_mask(priv, 0x101, 0x00, 0x04); ++ if (ret) ++ goto err; ++ ++ priv->sleeping = false; ++ ++ return ret; ++err: ++ dbg("%s: failed=%d", __func__, ret); ++ return ret; ++} ++ ++static int rtl2830_sleep(struct dvb_frontend *fe) ++{ ++ struct rtl2830_priv *priv = fe->demodulator_priv; ++ priv->sleeping = true; ++ return 0; ++} ++ ++int rtl2830_get_tune_settings(struct dvb_frontend *fe, ++ struct dvb_frontend_tune_settings *s) ++{ ++ s->min_delay_ms = 500; ++ s->step_size = fe->ops.info.frequency_stepsize * 2; ++ s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; ++ ++ return 0; ++} ++ ++static int rtl2830_set_frontend(struct dvb_frontend *fe) ++{ ++ struct rtl2830_priv *priv = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret, i; ++ static u8 bw_params1[3][34] = { ++ { ++ 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41, ++ 0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a, ++ 0x1f, 0x47, 0x1f, 0x7c, 0x00, 0x30, 0x01, 0x4b, 0x02, 0x82, ++ 0x03, 0x73, 0x03, 0xcf, /* 6 MHz */ ++ }, { ++ 0x1f, 0xfa, 0x1f, 0xda, 0x1f, 0xc1, 0x1f, 0xb3, 0x1f, 0xca, ++ 0x00, 0x07, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x40, 0x1f, 0xca, ++ 0x1f, 0x4d, 0x1f, 0x2a, 0x1f, 0xb2, 0x00, 0xec, 0x02, 0x7e, ++ 0x03, 0xd0, 0x04, 0x53, /* 7 MHz */ ++ }, { ++ 0x00, 0x10, 0x00, 0x0e, 0x1f, 0xf7, 0x1f, 0xc9, 0x1f, 0xa0, ++ 0x1f, 0xa6, 0x1f, 0xec, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x3a, ++ 0x1f, 0x98, 0x1f, 0x10, 0x1f, 0x40, 0x00, 0x75, 0x02, 0x5f, ++ 0x04, 0x24, 0x04, 0xdb, /* 8 MHz */ ++ }, ++ }; ++ static u8 bw_params2[3][6] = { ++ {0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30,}, /* 6 MHz */ ++ {0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98,}, /* 7 MHz */ ++ {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64,}, /* 8 MHz */ ++ }; ++ ++ ++ dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__, ++ c->frequency, c->bandwidth_hz, c->inversion); ++ ++ /* program tuner */ ++ if (fe->ops.tuner_ops.set_params) ++ fe->ops.tuner_ops.set_params(fe); ++ ++ switch (c->bandwidth_hz) { ++ case 6000000: ++ i = 0; ++ break; ++ case 7000000: ++ i = 1; ++ break; ++ case 8000000: ++ i = 2; ++ break; ++ default: ++ dbg("invalid bandwidth"); ++ return -EINVAL; ++ } ++ ++ ret = rtl2830_wr_reg_mask(priv, 0x008, i << 1, 0x06); ++ if (ret) ++ goto err; ++ ++ /* 1/2 split I2C write */ ++ ret = rtl2830_wr_regs(priv, 0x11c, &bw_params1[i][0], 17); ++ if (ret) ++ goto err; ++ ++ /* 2/2 split I2C write */ ++ ret = rtl2830_wr_regs(priv, 0x12d, &bw_params1[i][17], 17); ++ if (ret) ++ goto err; ++ ++ ret = rtl2830_wr_regs(priv, 0x19d, bw_params2[i], 6); ++ if (ret) ++ goto err; ++ ++ return ret; ++err: ++ dbg("%s: failed=%d", __func__, ret); ++ return ret; ++} ++ ++static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status) ++{ ++ struct rtl2830_priv *priv = fe->demodulator_priv; ++ int ret; ++ u8 tmp; ++ *status = 0; ++ ++ if (priv->sleeping) ++ return 0; ++ ++ ret = rtl2830_rd_reg_mask(priv, 0x351, &tmp, 0x78); /* [6:3] */ ++ if (ret) ++ goto err; ++ ++ if (tmp == 11) { ++ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | ++ FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; ++ } else if (tmp == 10) { ++ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | ++ FE_HAS_VITERBI; ++ } ++ ++ return ret; ++err: ++ dbg("%s: failed=%d", __func__, ret); ++ return ret; ++} ++ ++static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ *snr = 0; ++ return 0; ++} ++ ++static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ *ber = 0; ++ return 0; ++} ++ ++static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ *ucblocks = 0; ++ return 0; ++} ++ ++static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength) ++{ ++ *strength = 0; ++ return 0; ++} ++ ++static struct dvb_frontend_ops rtl2830_ops; ++ ++static u32 rtl2830_tuner_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static int rtl2830_tuner_i2c_xfer(struct i2c_adapter *i2c_adap, ++ struct i2c_msg msg[], int num) ++{ ++ struct rtl2830_priv *priv = i2c_get_adapdata(i2c_adap); ++ int ret; ++ ++ /* open i2c-gate */ ++ ret = rtl2830_wr_reg_mask(priv, 0x101, 0x08, 0x08); ++ if (ret) ++ goto err; ++ ++ ret = i2c_transfer(priv->i2c, msg, num); ++ if (ret < 0) ++ warn("tuner i2c failed=%d", ret); ++ ++ return ret; ++err: ++ dbg("%s: failed=%d", __func__, ret); ++ return ret; ++} ++ ++static struct i2c_algorithm rtl2830_tuner_i2c_algo = { ++ .master_xfer = rtl2830_tuner_i2c_xfer, ++ .functionality = rtl2830_tuner_i2c_func, ++}; ++ ++struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(struct dvb_frontend *fe) ++{ ++ struct rtl2830_priv *priv = fe->demodulator_priv; ++ return &priv->tuner_i2c_adapter; ++} ++EXPORT_SYMBOL(rtl2830_get_tuner_i2c_adapter); ++ ++static void rtl2830_release(struct dvb_frontend *fe) ++{ ++ struct rtl2830_priv *priv = fe->demodulator_priv; ++ ++ i2c_del_adapter(&priv->tuner_i2c_adapter); ++ kfree(priv); ++} ++ ++struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg, ++ struct i2c_adapter *i2c) ++{ ++ struct rtl2830_priv *priv = NULL; ++ int ret = 0; ++ u8 tmp; ++ ++ /* allocate memory for the internal state */ ++ priv = kzalloc(sizeof(struct rtl2830_priv), GFP_KERNEL); ++ if (priv == NULL) ++ goto err; ++ ++ /* setup the priv */ ++ priv->i2c = i2c; ++ memcpy(&priv->cfg, cfg, sizeof(struct rtl2830_config)); ++ ++ /* check if the demod is there */ ++ ret = rtl2830_rd_reg(priv, 0x000, &tmp); ++ if (ret) ++ goto err; ++ ++ /* create dvb_frontend */ ++ memcpy(&priv->fe.ops, &rtl2830_ops, sizeof(struct dvb_frontend_ops)); ++ priv->fe.demodulator_priv = priv; ++ ++ /* create tuner i2c adapter */ ++ strlcpy(priv->tuner_i2c_adapter.name, "RTL2830 tuner I2C adapter", ++ sizeof(priv->tuner_i2c_adapter.name)); ++ priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo; ++ priv->tuner_i2c_adapter.algo_data = NULL; ++ i2c_set_adapdata(&priv->tuner_i2c_adapter, priv); ++ if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) { ++ err("tuner I2C bus could not be initialized"); ++ goto err; ++ } ++ ++ priv->sleeping = true; ++ ++ return &priv->fe; ++err: ++ dbg("%s: failed=%d", __func__, ret); ++ kfree(priv); ++ return NULL; ++} ++EXPORT_SYMBOL(rtl2830_attach); ++ ++static struct dvb_frontend_ops rtl2830_ops = { ++ .delsys = { SYS_DVBT }, ++ .info = { ++ .name = "Realtek RTL2830 (DVB-T)", ++ .caps = FE_CAN_FEC_1_2 | ++ FE_CAN_FEC_2_3 | ++ FE_CAN_FEC_3_4 | ++ FE_CAN_FEC_5_6 | ++ FE_CAN_FEC_7_8 | ++ FE_CAN_FEC_AUTO | ++ FE_CAN_QPSK | ++ FE_CAN_QAM_16 | ++ FE_CAN_QAM_64 | ++ FE_CAN_QAM_AUTO | ++ FE_CAN_TRANSMISSION_MODE_AUTO | ++ FE_CAN_GUARD_INTERVAL_AUTO | ++ FE_CAN_HIERARCHY_AUTO | ++ FE_CAN_RECOVER | ++ FE_CAN_MUTE_TS ++ }, ++ ++ .release = rtl2830_release, ++ ++ .init = rtl2830_init, ++ .sleep = rtl2830_sleep, ++ ++ .get_tune_settings = rtl2830_get_tune_settings, ++ ++ .set_frontend = rtl2830_set_frontend, ++ ++ .read_status = rtl2830_read_status, ++ .read_snr = rtl2830_read_snr, ++ .read_ber = rtl2830_read_ber, ++ .read_ucblocks = rtl2830_read_ucblocks, ++ .read_signal_strength = rtl2830_read_signal_strength, ++}; ++ ++MODULE_AUTHOR("Antti Palosaari "); ++MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver"); ++MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830.h +@@ -0,0 +1,97 @@ ++/* ++ * Realtek RTL2830 DVB-T demodulator driver ++ * ++ * Copyright (C) 2011 Antti Palosaari ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef RTL2830_H ++#define RTL2830_H ++ ++#include ++ ++struct rtl2830_config { ++ /* ++ * Demodulator I2C address. ++ */ ++ u8 i2c_addr; ++ ++ /* ++ * Xtal frequency. ++ * Hz ++ * 4000000, 16000000, 25000000, 28800000 ++ */ ++ u32 xtal; ++ ++ /* ++ * TS output mode. ++ */ ++ u8 ts_mode; ++ ++ /* ++ * Spectrum inversion. ++ */ ++ bool spec_inv; ++ ++ /* ++ * IFs for all used modes. ++ * Hz ++ * 4570000, 4571429, 36000000, 36125000, 36166667, 44000000 ++ */ ++ u32 if_dvbt; ++ ++ /* ++ */ ++ u8 vtop; ++ ++ /* ++ */ ++ u8 krf; ++ ++ /* ++ */ ++ u8 agc_targ_val; ++}; ++ ++#if defined(CONFIG_DVB_RTL2830) || \ ++ (defined(CONFIG_DVB_RTL2830_MODULE) && defined(MODULE)) ++extern struct dvb_frontend *rtl2830_attach( ++ const struct rtl2830_config *config, ++ struct i2c_adapter *i2c ++); ++ ++extern struct i2c_adapter *rtl2830_get_tuner_i2c_adapter( ++ struct dvb_frontend *fe ++); ++#else ++static inline struct dvb_frontend *rtl2830_attach( ++ const struct rtl2830_config *config, ++ struct i2c_adapter *i2c ++) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++ ++static inline struct i2c_adapter *rtl2830_get_tuner_i2c_adapter( ++ struct dvb_frontend *fe ++) ++{ ++ return NULL; ++} ++#endif ++ ++#endif /* RTL2830_H */ +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830_priv.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830_priv.h +@@ -0,0 +1,57 @@ ++/* ++ * Realtek RTL2830 DVB-T demodulator driver ++ * ++ * Copyright (C) 2011 Antti Palosaari ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef RTL2830_PRIV_H ++#define RTL2830_PRIV_H ++ ++#include "dvb_frontend.h" ++#include "rtl2830.h" ++ ++#define LOG_PREFIX "rtl2830" ++ ++#undef dbg ++#define dbg(f, arg...) \ ++ if (rtl2830_debug) \ ++ printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) ++#undef err ++#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) ++#undef info ++#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) ++#undef warn ++#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) ++ ++struct rtl2830_priv { ++ struct i2c_adapter *i2c; ++ struct dvb_frontend fe; ++ struct rtl2830_config cfg; ++ struct i2c_adapter tuner_i2c_adapter; ++ ++ bool sleeping; ++ ++ u8 page; /* active register page */ ++}; ++ ++struct rtl2830_reg_val_mask { ++ u16 reg; ++ u8 val; ++ u8 mask; ++}; ++ ++#endif /* RTL2830_PRIV_H */ +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/rtl28xxu.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/rtl28xxu.c +@@ -0,0 +1,982 @@ ++/* ++ * Realtek RTL28xxU DVB USB driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * Copyright (C) 2011 Antti Palosaari ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include "rtl28xxu.h" ++ ++#include "rtl2830.h" ++ ++#include "qt1010.h" ++#include "mt2060.h" ++#include "mxl5005s.h" ++ ++/* debug */ ++static int dvb_usb_rtl28xxu_debug; ++module_param_named(debug, dvb_usb_rtl28xxu_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) ++{ ++ int ret; ++ unsigned int pipe; ++ u8 requesttype; ++ u8 *buf; ++ ++ buf = kmalloc(req->size, GFP_KERNEL); ++ if (!buf) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ if (req->index & CMD_WR_FLAG) { ++ /* write */ ++ memcpy(buf, req->data, req->size); ++ requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); ++ pipe = usb_sndctrlpipe(d->udev, 0); ++ } else { ++ /* read */ ++ requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); ++ pipe = usb_rcvctrlpipe(d->udev, 0); ++ } ++ ++ ret = usb_control_msg(d->udev, pipe, 0, requesttype, req->value, ++ req->index, buf, req->size, 1000); ++ if (ret > 0) ++ ret = 0; ++ ++ deb_dump(0, requesttype, req->value, req->index, buf, req->size, ++ deb_xfer); ++ ++ /* read request, copy returned data to return buf */ ++ if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) ++ memcpy(req->data, buf, req->size); ++ ++ kfree(buf); ++ ++ if (ret) ++ goto err; ++ ++ return ret; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static int rtl2831_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) ++{ ++ struct rtl28xxu_req req; ++ ++ if (reg < 0x3000) ++ req.index = CMD_USB_WR; ++ else if (reg < 0x4000) ++ req.index = CMD_SYS_WR; ++ else ++ req.index = CMD_IR_WR; ++ ++ req.value = reg; ++ req.size = len; ++ req.data = val; ++ ++ return rtl28xxu_ctrl_msg(d, &req); ++} ++ ++static int rtl2831_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) ++{ ++ struct rtl28xxu_req req; ++ ++ if (reg < 0x3000) ++ req.index = CMD_USB_RD; ++ else if (reg < 0x4000) ++ req.index = CMD_SYS_RD; ++ else ++ req.index = CMD_IR_RD; ++ ++ req.value = reg; ++ req.size = len; ++ req.data = val; ++ ++ return rtl28xxu_ctrl_msg(d, &req); ++} ++ ++static int rtl2831_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val) ++{ ++ return rtl2831_wr_regs(d, reg, &val, 1); ++} ++ ++static int rtl2831_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val) ++{ ++ return rtl2831_rd_regs(d, reg, val, 1); ++} ++ ++/* I2C */ ++static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], ++ int num) ++{ ++ int ret; ++ struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ struct rtl28xxu_priv *priv = d->priv; ++ struct rtl28xxu_req req; ++ ++ /* ++ * It is not known which are real I2C bus xfer limits, but testing ++ * with RTL2831U + MT2060 gives max RD 24 and max WR 22 bytes. ++ * TODO: find out RTL2832U lens ++ */ ++ ++ /* ++ * I2C adapter logic looks rather complicated due to fact it handles ++ * three different access methods. Those methods are; ++ * 1) integrated demod access ++ * 2) old I2C access ++ * 3) new I2C access ++ * ++ * Used method is selected in order 1, 2, 3. Method 3 can handle all ++ * requests but there is two reasons why not use it always; ++ * 1) It is most expensive, usually two USB messages are needed ++ * 2) At least RTL2831U does not support it ++ * ++ * Method 3 is needed in case of I2C write+read (typical register read) ++ * where write is more than one byte. ++ */ ++ ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ if (num == 2 && !(msg[0].flags & I2C_M_RD) && ++ (msg[1].flags & I2C_M_RD)) { ++ if (msg[0].len > 24 || msg[1].len > 24) { ++ /* TODO: check msg[0].len max */ ++ ret = -EOPNOTSUPP; ++ goto err_mutex_unlock; ++ } else if (msg[0].addr == 0x10) { ++ /* method 1 - integrated demod */ ++ req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); ++ req.index = CMD_DEMOD_RD | priv->page; ++ req.size = msg[1].len; ++ req.data = &msg[1].buf[0]; ++ ret = rtl28xxu_ctrl_msg(d, &req); ++ } else if (msg[0].len < 2) { ++ /* method 2 - old I2C */ ++ req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); ++ req.index = CMD_I2C_RD; ++ req.size = msg[1].len; ++ req.data = &msg[1].buf[0]; ++ ret = rtl28xxu_ctrl_msg(d, &req); ++ } else { ++ /* method 3 - new I2C */ ++ req.value = (msg[0].addr << 1); ++ req.index = CMD_I2C_DA_WR; ++ req.size = msg[0].len; ++ req.data = msg[0].buf; ++ ret = rtl28xxu_ctrl_msg(d, &req); ++ if (ret) ++ goto err_mutex_unlock; ++ ++ req.value = (msg[0].addr << 1); ++ req.index = CMD_I2C_DA_RD; ++ req.size = msg[1].len; ++ req.data = msg[1].buf; ++ ret = rtl28xxu_ctrl_msg(d, &req); ++ } ++ } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { ++ if (msg[0].len > 22) { ++ /* TODO: check msg[0].len max */ ++ ret = -EOPNOTSUPP; ++ goto err_mutex_unlock; ++ } else if (msg[0].addr == 0x10) { ++ /* method 1 - integrated demod */ ++ if (msg[0].buf[0] == 0x00) { ++ /* save demod page for later demod access */ ++ priv->page = msg[0].buf[1]; ++ ret = 0; ++ } else { ++ req.value = (msg[0].buf[0] << 8) | ++ (msg[0].addr << 1); ++ req.index = CMD_DEMOD_WR | priv->page; ++ req.size = msg[0].len-1; ++ req.data = &msg[0].buf[1]; ++ ret = rtl28xxu_ctrl_msg(d, &req); ++ } ++ } else if (msg[0].len < 23) { ++ /* method 2 - old I2C */ ++ req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); ++ req.index = CMD_I2C_WR; ++ req.size = msg[0].len-1; ++ req.data = &msg[0].buf[1]; ++ ret = rtl28xxu_ctrl_msg(d, &req); ++ } else { ++ /* method 3 - new I2C */ ++ req.value = (msg[0].addr << 1); ++ req.index = CMD_I2C_DA_WR; ++ req.size = msg[0].len; ++ req.data = msg[0].buf; ++ ret = rtl28xxu_ctrl_msg(d, &req); ++ } ++ } else { ++ ret = -EINVAL; ++ } ++ ++err_mutex_unlock: ++ mutex_unlock(&d->i2c_mutex); ++ ++ return ret ? ret : num; ++} ++ ++static u32 rtl28xxu_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static struct i2c_algorithm rtl28xxu_i2c_algo = { ++ .master_xfer = rtl28xxu_i2c_xfer, ++ .functionality = rtl28xxu_i2c_func, ++}; ++ ++static struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = { ++ .i2c_addr = 0x10, /* 0x20 */ ++ .xtal = 28800000, ++ .ts_mode = 0, ++ .spec_inv = 1, ++ .if_dvbt = 36150000, ++ .vtop = 0x20, ++ .krf = 0x04, ++ .agc_targ_val = 0x2d, ++ ++}; ++ ++static struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = { ++ .i2c_addr = 0x10, /* 0x20 */ ++ .xtal = 28800000, ++ .ts_mode = 0, ++ .spec_inv = 1, ++ .if_dvbt = 36125000, ++ .vtop = 0x20, ++ .krf = 0x04, ++ .agc_targ_val = 0x2d, ++}; ++ ++static struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = { ++ .i2c_addr = 0x10, /* 0x20 */ ++ .xtal = 28800000, ++ .ts_mode = 0, ++ .spec_inv = 0, ++ .if_dvbt = 4570000, ++ .vtop = 0x3f, ++ .krf = 0x04, ++ .agc_targ_val = 0x3e, ++}; ++ ++static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) ++{ ++ int ret; ++ struct rtl28xxu_priv *priv = adap->dev->priv; ++ u8 buf[1]; ++ struct rtl2830_config *rtl2830_config; ++ /* open RTL2831U/RTL2830 I2C gate */ ++ struct rtl28xxu_req req_gate = { 0x0120, 0x0011, 0x0001, "\x08" }; ++ /* for MT2060 tuner probe */ ++ struct rtl28xxu_req req_mt2060 = { 0x00c0, CMD_I2C_RD, 1, buf }; ++ /* for QT1010 tuner probe */ ++ struct rtl28xxu_req req_qt1010 = { 0x0fc4, CMD_I2C_RD, 1, buf }; ++ ++ deb_info("%s:\n", __func__); ++ ++ /* ++ * RTL2831U GPIOs ++ * ========================================================= ++ * GPIO0 | tuner#0 | 0 off | 1 on | MXL5005S (?) ++ * GPIO2 | LED | 0 off | 1 on | ++ * GPIO4 | tuner#1 | 0 on | 1 off | MT2060 ++ */ ++ ++ /* GPIO direction */ ++ ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a); ++ if (ret) ++ goto err; ++ ++ /* enable as output GPIO0, GPIO2, GPIO4 */ ++ ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15); ++ if (ret) ++ goto err; ++ ++ /* ++ * Probe used tuner. We need to know used tuner before demod attach ++ * since there is some demod params needed to set according to tuner. ++ */ ++ ++ /* open demod I2C gate */ ++ ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate); ++ if (ret) ++ goto err; ++ ++ /* check QT1010 ID(?) register; reg=0f val=2c */ ++ ret = rtl28xxu_ctrl_msg(adap->dev, &req_qt1010); ++ if (ret == 0 && buf[0] == 0x2c) { ++ priv->tuner = TUNER_RTL2830_QT1010; ++ rtl2830_config = &rtl28xxu_rtl2830_qt1010_config; ++ deb_info("%s: QT1010\n", __func__); ++ goto found; ++ } else { ++ deb_info("%s: QT1010 probe failed=%d - %02x\n", ++ __func__, ret, buf[0]); ++ } ++ ++ /* open demod I2C gate */ ++ ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate); ++ if (ret) ++ goto err; ++ ++ /* check MT2060 ID register; reg=00 val=63 */ ++ ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2060); ++ if (ret == 0 && buf[0] == 0x63) { ++ priv->tuner = TUNER_RTL2830_MT2060; ++ rtl2830_config = &rtl28xxu_rtl2830_mt2060_config; ++ deb_info("%s: MT2060\n", __func__); ++ goto found; ++ } else { ++ deb_info("%s: MT2060 probe failed=%d - %02x\n", ++ __func__, ret, buf[0]); ++ } ++ ++ /* assume MXL5005S */ ++ ret = 0; ++ priv->tuner = TUNER_RTL2830_MXL5005S; ++ rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config; ++ deb_info("%s: MXL5005S\n", __func__); ++ goto found; ++ ++found: ++ /* attach demodulator */ ++ adap->fe_adap[0].fe = dvb_attach(rtl2830_attach, rtl2830_config, ++ &adap->dev->i2c_adap); ++ if (adap->fe_adap[0].fe == NULL) { ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ return ret; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) ++{ ++ int ret; ++ struct rtl28xxu_priv *priv = adap->dev->priv; ++ u8 buf[1]; ++ /* open RTL2832U/RTL2832 I2C gate */ ++ struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"}; ++ /* close RTL2832U/RTL2832 I2C gate */ ++ struct rtl28xxu_req req_gate_close = {0x0120, 0x0011, 0x0001, "\x10"}; ++ /* for FC2580 tuner probe */ ++ struct rtl28xxu_req req_fc2580 = {0x01ac, CMD_I2C_RD, 1, buf}; ++ ++ deb_info("%s:\n", __func__); ++ ++ /* GPIO direction */ ++ ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a); ++ if (ret) ++ goto err; ++ ++ /* enable as output GPIO0, GPIO2, GPIO4 */ ++ ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15); ++ if (ret) ++ goto err; ++ ++ ret = rtl2831_wr_reg(adap->dev, SYS_DEMOD_CTL, 0xe8); ++ if (ret) ++ goto err; ++ ++ /* ++ * Probe used tuner. We need to know used tuner before demod attach ++ * since there is some demod params needed to set according to tuner. ++ */ ++ ++ /* open demod I2C gate */ ++ ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_open); ++ if (ret) ++ goto err; ++ ++ /* check FC2580 ID register; reg=01 val=56 */ ++ ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc2580); ++ if (ret == 0 && buf[0] == 0x56) { ++ priv->tuner = TUNER_RTL2832_FC2580; ++ deb_info("%s: FC2580\n", __func__); ++ goto found; ++ } else { ++ deb_info("%s: FC2580 probe failed=%d - %02x\n", ++ __func__, ret, buf[0]); ++ } ++ ++ /* close demod I2C gate */ ++ ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close); ++ if (ret) ++ goto err; ++ ++ /* tuner not found */ ++ ret = -ENODEV; ++ goto err; ++ ++found: ++ /* close demod I2C gate */ ++ ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close); ++ if (ret) ++ goto err; ++ ++ /* attach demodulator */ ++ /* TODO: */ ++ ++ return ret; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static struct qt1010_config rtl28xxu_qt1010_config = { ++ .i2c_address = 0x62, /* 0xc4 */ ++}; ++ ++static struct mt2060_config rtl28xxu_mt2060_config = { ++ .i2c_address = 0x60, /* 0xc0 */ ++ .clock_out = 0, ++}; ++ ++static struct mxl5005s_config rtl28xxu_mxl5005s_config = { ++ .i2c_address = 0x63, /* 0xc6 */ ++ .if_freq = IF_FREQ_4570000HZ, ++ .xtal_freq = CRYSTAL_FREQ_16000000HZ, ++ .agc_mode = MXL_SINGLE_AGC, ++ .tracking_filter = MXL_TF_C_H, ++ .rssi_enable = MXL_RSSI_ENABLE, ++ .cap_select = MXL_CAP_SEL_ENABLE, ++ .div_out = MXL_DIV_OUT_4, ++ .clock_out = MXL_CLOCK_OUT_DISABLE, ++ .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, ++ .top = MXL5005S_TOP_25P2, ++ .mod_mode = MXL_DIGITAL_MODE, ++ .if_mode = MXL_ZERO_IF, ++ .AgcMasterByte = 0x00, ++}; ++ ++static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap) ++{ ++ int ret; ++ struct rtl28xxu_priv *priv = adap->dev->priv; ++ struct i2c_adapter *rtl2830_tuner_i2c; ++ struct dvb_frontend *fe; ++ ++ deb_info("%s:\n", __func__); ++ ++ /* use rtl2830 driver I2C adapter, for more info see rtl2830 driver */ ++ rtl2830_tuner_i2c = rtl2830_get_tuner_i2c_adapter(adap->fe_adap[0].fe); ++ ++ switch (priv->tuner) { ++ case TUNER_RTL2830_QT1010: ++ fe = dvb_attach(qt1010_attach, adap->fe_adap[0].fe, ++ rtl2830_tuner_i2c, &rtl28xxu_qt1010_config); ++ break; ++ case TUNER_RTL2830_MT2060: ++ fe = dvb_attach(mt2060_attach, adap->fe_adap[0].fe, ++ rtl2830_tuner_i2c, &rtl28xxu_mt2060_config, ++ 1220); ++ break; ++ case TUNER_RTL2830_MXL5005S: ++ fe = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, ++ rtl2830_tuner_i2c, &rtl28xxu_mxl5005s_config); ++ break; ++ default: ++ fe = NULL; ++ err("unknown tuner=%d", priv->tuner); ++ } ++ ++ if (fe == NULL) { ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ return 0; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) ++{ ++ int ret; ++ struct rtl28xxu_priv *priv = adap->dev->priv; ++ struct dvb_frontend *fe; ++ ++ deb_info("%s:\n", __func__); ++ ++ switch (priv->tuner) { ++ case TUNER_RTL2832_FC2580: ++ /* TODO: */ ++ fe = NULL; ++ break; ++ default: ++ fe = NULL; ++ err("unknown tuner=%d", priv->tuner); ++ } ++ ++ if (fe == NULL) { ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ return 0; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static int rtl28xxu_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff) ++{ ++ int ret; ++ u8 buf[2], gpio; ++ ++ deb_info("%s: onoff=%d\n", __func__, onoff); ++ ++ ret = rtl2831_rd_reg(adap->dev, SYS_GPIO_OUT_VAL, &gpio); ++ if (ret) ++ goto err; ++ ++ if (onoff) { ++ buf[0] = 0x00; ++ buf[1] = 0x00; ++ gpio |= 0x04; /* LED on */ ++ } else { ++ buf[0] = 0x10; /* stall EPA */ ++ buf[1] = 0x02; /* reset EPA */ ++ gpio &= (~0x04); /* LED off */ ++ } ++ ++ ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_VAL, gpio); ++ if (ret) ++ goto err; ++ ++ ret = rtl2831_wr_regs(adap->dev, USB_EPA_CTL, buf, 2); ++ if (ret) ++ goto err; ++ ++ return ret; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static int rtl28xxu_power_ctrl(struct dvb_usb_device *d, int onoff) ++{ ++ int ret; ++ u8 gpio, sys0; ++ ++ deb_info("%s: onoff=%d\n", __func__, onoff); ++ ++ /* demod adc */ ++ ret = rtl2831_rd_reg(d, SYS_SYS0, &sys0); ++ if (ret) ++ goto err; ++ ++ /* tuner power, read GPIOs */ ++ ret = rtl2831_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio); ++ if (ret) ++ goto err; ++ ++ deb_info("%s: RD SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio); ++ ++ if (onoff) { ++ gpio |= 0x01; /* GPIO0 = 1 */ ++ gpio &= (~0x10); /* GPIO4 = 0 */ ++ sys0 = sys0 & 0x0f; ++ sys0 |= 0xe0; ++ } else { ++ gpio &= (~0x01); /* GPIO0 = 0 */ ++ gpio |= 0x10; /* GPIO4 = 1 */ ++ sys0 = sys0 & (~0xc0); ++ } ++ ++ deb_info("%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio); ++ ++ /* demod adc */ ++ ret = rtl2831_wr_reg(d, SYS_SYS0, sys0); ++ if (ret) ++ goto err; ++ ++ /* tuner power, write GPIOs */ ++ ret = rtl2831_wr_reg(d, SYS_GPIO_OUT_VAL, gpio); ++ if (ret) ++ goto err; ++ ++ return ret; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static int rtl2831u_rc_query(struct dvb_usb_device *d) ++{ ++ int ret, i; ++ struct rtl28xxu_priv *priv = d->priv; ++ u8 buf[5]; ++ u32 rc_code; ++ struct rtl28xxu_reg_val rc_nec_tab[] = { ++ { 0x3033, 0x80 }, ++ { 0x3020, 0x43 }, ++ { 0x3021, 0x16 }, ++ { 0x3022, 0x16 }, ++ { 0x3023, 0x5a }, ++ { 0x3024, 0x2d }, ++ { 0x3025, 0x16 }, ++ { 0x3026, 0x01 }, ++ { 0x3028, 0xb0 }, ++ { 0x3029, 0x04 }, ++ { 0x302c, 0x88 }, ++ { 0x302e, 0x13 }, ++ { 0x3030, 0xdf }, ++ { 0x3031, 0x05 }, ++ }; ++ ++ /* init remote controller */ ++ if (!priv->rc_active) { ++ for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { ++ ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg, ++ rc_nec_tab[i].val); ++ if (ret) ++ goto err; ++ } ++ priv->rc_active = true; ++ } ++ ++ ret = rtl2831_rd_regs(d, SYS_IRRC_RP, buf, 5); ++ if (ret) ++ goto err; ++ ++ if (buf[4] & 0x01) { ++ if (buf[2] == (u8) ~buf[3]) { ++ if (buf[0] == (u8) ~buf[1]) { ++ /* NEC standard (16 bit) */ ++ rc_code = buf[0] << 8 | buf[2]; ++ } else { ++ /* NEC extended (24 bit) */ ++ rc_code = buf[0] << 16 | ++ buf[1] << 8 | buf[2]; ++ } ++ } else { ++ /* NEC full (32 bit) */ ++ rc_code = buf[0] << 24 | buf[1] << 16 | ++ buf[2] << 8 | buf[3]; ++ } ++ ++ rc_keydown(d->rc_dev, rc_code, 0); ++ ++ ret = rtl2831_wr_reg(d, SYS_IRRC_SR, 1); ++ if (ret) ++ goto err; ++ ++ /* repeated intentionally to avoid extra keypress */ ++ ret = rtl2831_wr_reg(d, SYS_IRRC_SR, 1); ++ if (ret) ++ goto err; ++ } ++ ++ return ret; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static int rtl2832u_rc_query(struct dvb_usb_device *d) ++{ ++ int ret, i; ++ struct rtl28xxu_priv *priv = d->priv; ++ u8 buf[128]; ++ int len; ++ struct rtl28xxu_reg_val rc_nec_tab[] = { ++ { IR_RX_CTRL, 0x20 }, ++ { IR_RX_BUF_CTRL, 0x80 }, ++ { IR_RX_IF, 0xff }, ++ { IR_RX_IE, 0xff }, ++ { IR_MAX_DURATION0, 0xd0 }, ++ { IR_MAX_DURATION1, 0x07 }, ++ { IR_IDLE_LEN0, 0xc0 }, ++ { IR_IDLE_LEN1, 0x00 }, ++ { IR_GLITCH_LEN, 0x03 }, ++ { IR_RX_CLK, 0x09 }, ++ { IR_RX_CFG, 0x1c }, ++ { IR_MAX_H_TOL_LEN, 0x1e }, ++ { IR_MAX_L_TOL_LEN, 0x1e }, ++ { IR_RX_CTRL, 0x80 }, ++ }; ++ ++ /* init remote controller */ ++ if (!priv->rc_active) { ++ for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { ++ ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg, ++ rc_nec_tab[i].val); ++ if (ret) ++ goto err; ++ } ++ priv->rc_active = true; ++ } ++ ++ ret = rtl2831_rd_reg(d, IR_RX_IF, &buf[0]); ++ if (ret) ++ goto err; ++ ++ if (buf[0] != 0x83) ++ goto exit; ++ ++ ret = rtl2831_rd_reg(d, IR_RX_BC, &buf[0]); ++ if (ret) ++ goto err; ++ ++ len = buf[0]; ++ ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len); ++ ++ /* TODO: pass raw IR to Kernel IR decoder */ ++ ++ ret = rtl2831_wr_reg(d, IR_RX_IF, 0x03); ++ ret = rtl2831_wr_reg(d, IR_RX_BUF_CTRL, 0x80); ++ ret = rtl2831_wr_reg(d, IR_RX_CTRL, 0x80); ++ ++exit: ++ return ret; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++enum rtl28xxu_usb_table_entry { ++ RTL2831U_0BDA_2831, ++ RTL2831U_14AA_0160, ++ RTL2831U_14AA_0161, ++}; ++ ++static struct usb_device_id rtl28xxu_table[] = { ++ /* RTL2831U */ ++ [RTL2831U_0BDA_2831] = { ++ USB_DEVICE(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U)}, ++ [RTL2831U_14AA_0160] = { ++ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT)}, ++ [RTL2831U_14AA_0161] = { ++ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2)}, ++ ++ /* RTL2832U */ ++ {} /* terminating entry */ ++}; ++ ++MODULE_DEVICE_TABLE(usb, rtl28xxu_table); ++ ++static struct dvb_usb_device_properties rtl28xxu_properties[] = { ++ { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .no_reconnect = 1, ++ ++ .size_of_priv = sizeof(struct rtl28xxu_priv), ++ ++ .num_adapters = 1, ++ .adapter = { ++ { ++ .num_frontends = 1, ++ .fe = { ++ { ++ .frontend_attach = rtl2831u_frontend_attach, ++ .tuner_attach = rtl2831u_tuner_attach, ++ .streaming_ctrl = rtl28xxu_streaming_ctrl, ++ .stream = { ++ .type = USB_BULK, ++ .count = 6, ++ .endpoint = 0x81, ++ .u = { ++ .bulk = { ++ .buffersize = 8*512, ++ } ++ } ++ } ++ } ++ } ++ } ++ }, ++ ++ .power_ctrl = rtl28xxu_power_ctrl, ++ ++ .rc.core = { ++ .protocol = RC_TYPE_NEC, ++ .module_name = "rtl28xxu", ++ .rc_query = rtl2831u_rc_query, ++ .rc_interval = 400, ++ .allowed_protos = RC_TYPE_NEC, ++ .rc_codes = RC_MAP_EMPTY, ++ }, ++ ++ .i2c_algo = &rtl28xxu_i2c_algo, ++ ++ .num_device_descs = 2, ++ .devices = { ++ { ++ .name = "Realtek RTL2831U reference design", ++ .warm_ids = { ++ &rtl28xxu_table[RTL2831U_0BDA_2831], ++ }, ++ }, ++ { ++ .name = "Freecom USB2.0 DVB-T", ++ .warm_ids = { ++ &rtl28xxu_table[RTL2831U_14AA_0160], ++ &rtl28xxu_table[RTL2831U_14AA_0161], ++ }, ++ }, ++ } ++ }, ++ { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .no_reconnect = 1, ++ ++ .size_of_priv = sizeof(struct rtl28xxu_priv), ++ ++ .num_adapters = 1, ++ .adapter = { ++ { ++ .num_frontends = 1, ++ .fe = { ++ { ++ .frontend_attach = rtl2832u_frontend_attach, ++ .tuner_attach = rtl2832u_tuner_attach, ++ .streaming_ctrl = rtl28xxu_streaming_ctrl, ++ .stream = { ++ .type = USB_BULK, ++ .count = 6, ++ .endpoint = 0x81, ++ .u = { ++ .bulk = { ++ .buffersize = 8*512, ++ } ++ } ++ } ++ } ++ } ++ } ++ }, ++ ++ .power_ctrl = rtl28xxu_power_ctrl, ++ ++ .rc.core = { ++ .protocol = RC_TYPE_NEC, ++ .module_name = "rtl28xxu", ++ .rc_query = rtl2832u_rc_query, ++ .rc_interval = 400, ++ .allowed_protos = RC_TYPE_NEC, ++ .rc_codes = RC_MAP_EMPTY, ++ }, ++ ++ .i2c_algo = &rtl28xxu_i2c_algo, ++ ++ .num_device_descs = 0, /* disabled as no support for RTL2832 */ ++ .devices = { ++ { ++ .name = "Realtek RTL2832U reference design", ++ }, ++ } ++ }, ++ ++}; ++ ++static int rtl28xxu_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ int ret, i; ++ int properties_count = ARRAY_SIZE(rtl28xxu_properties); ++ struct dvb_usb_device *d; ++ ++ deb_info("%s: interface=%d\n", __func__, ++ intf->cur_altsetting->desc.bInterfaceNumber); ++ ++ if (intf->cur_altsetting->desc.bInterfaceNumber != 0) ++ return 0; ++ ++ for (i = 0; i < properties_count; i++) { ++ ret = dvb_usb_device_init(intf, &rtl28xxu_properties[i], ++ THIS_MODULE, &d, adapter_nr); ++ if (ret == 0 || ret != -ENODEV) ++ break; ++ } ++ ++ if (ret) ++ goto err; ++ ++ /* init USB endpoints */ ++ ret = rtl2831_wr_reg(d, USB_SYSCTL_0, 0x09); ++ if (ret) ++ goto err; ++ ++ ret = rtl2831_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4); ++ if (ret) ++ goto err; ++ ++ ret = rtl2831_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4); ++ if (ret) ++ goto err; ++ ++ return ret; ++err: ++ deb_info("%s: failed=%d\n", __func__, ret); ++ return ret; ++} ++ ++static struct usb_driver rtl28xxu_driver = { ++ .name = "dvb_usb_rtl28xxu", ++ .probe = rtl28xxu_probe, ++ .disconnect = dvb_usb_device_exit, ++ .id_table = rtl28xxu_table, ++}; ++ ++/* module stuff */ ++static int __init rtl28xxu_module_init(void) ++{ ++ int ret; ++ ++ deb_info("%s:\n", __func__); ++ ++ ret = usb_register(&rtl28xxu_driver); ++ if (ret) ++ err("usb_register failed=%d", ret); ++ ++ return ret; ++} ++ ++static void __exit rtl28xxu_module_exit(void) ++{ ++ deb_info("%s:\n", __func__); ++ ++ /* deregister this driver from the USB subsystem */ ++ usb_deregister(&rtl28xxu_driver); ++} ++ ++module_init(rtl28xxu_module_init); ++module_exit(rtl28xxu_module_exit); ++ ++MODULE_DESCRIPTION("Realtek RTL28xxU DVB USB driver"); ++MODULE_AUTHOR("Antti Palosaari "); ++MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/rtl28xxu.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/rtl28xxu.h +@@ -0,0 +1,264 @@ ++/* ++ * Realtek RTL28xxU DVB USB driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * Copyright (C) 2011 Antti Palosaari ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef RTL28XXU_H ++#define RTL28XXU_H ++ ++#define DVB_USB_LOG_PREFIX "rtl28xxu" ++#include "dvb-usb.h" ++ ++#define deb_info(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x01, args) ++#define deb_rc(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x02, args) ++#define deb_xfer(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x04, args) ++#define deb_reg(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x08, args) ++#define deb_i2c(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x10, args) ++#define deb_fw(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x20, args) ++ ++#define deb_dump(r, t, v, i, b, l, func) { \ ++ int loop_; \ ++ func("%02x %02x %02x %02x %02x %02x %02x %02x", \ ++ t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \ ++ if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \ ++ func(" >>> "); \ ++ else \ ++ func(" <<< "); \ ++ for (loop_ = 0; loop_ < l; loop_++) \ ++ func("%02x ", b[loop_]); \ ++ func("\n");\ ++} ++ ++/* ++ * USB commands ++ * (usb_control_msg() index parameter) ++ */ ++ ++#define DEMOD 0x0000 ++#define USB 0x0100 ++#define SYS 0x0200 ++#define I2C 0x0300 ++#define I2C_DA 0x0600 ++ ++#define CMD_WR_FLAG 0x0010 ++#define CMD_DEMOD_RD 0x0000 ++#define CMD_DEMOD_WR 0x0010 ++#define CMD_USB_RD 0x0100 ++#define CMD_USB_WR 0x0110 ++#define CMD_SYS_RD 0x0200 ++#define CMD_IR_RD 0x0201 ++#define CMD_IR_WR 0x0211 ++#define CMD_SYS_WR 0x0210 ++#define CMD_I2C_RD 0x0300 ++#define CMD_I2C_WR 0x0310 ++#define CMD_I2C_DA_RD 0x0600 ++#define CMD_I2C_DA_WR 0x0610 ++ ++ ++struct rtl28xxu_priv { ++ u8 chip_id; ++ u8 tuner; ++ u8 page; /* integrated demod active register page */ ++ bool rc_active; ++}; ++ ++enum rtl28xxu_chip_id { ++ CHIP_ID_NONE, ++ CHIP_ID_RTL2831U, ++ CHIP_ID_RTL2832U, ++}; ++ ++enum rtl28xxu_tuner { ++ TUNER_NONE, ++ ++ TUNER_RTL2830_QT1010, ++ TUNER_RTL2830_MT2060, ++ TUNER_RTL2830_MXL5005S, ++ ++ TUNER_RTL2832_MT2266, ++ TUNER_RTL2832_FC2580, ++ TUNER_RTL2832_MT2063, ++ TUNER_RTL2832_MAX3543, ++ TUNER_RTL2832_TUA9001, ++ TUNER_RTL2832_MXL5007T, ++ TUNER_RTL2832_FC0012, ++ TUNER_RTL2832_E4000, ++ TUNER_RTL2832_TDA18272, ++ TUNER_RTL2832_FC0013, ++}; ++ ++struct rtl28xxu_req { ++ u16 value; ++ u16 index; ++ u16 size; ++ u8 *data; ++}; ++ ++struct rtl28xxu_reg_val { ++ u16 reg; ++ u8 val; ++}; ++ ++/* ++ * memory map ++ * ++ * 0x0000 DEMOD : demodulator ++ * 0x2000 USB : SIE, USB endpoint, debug, DMA ++ * 0x3000 SYS : system ++ * 0xfc00 RC : remote controller (not RTL2831U) ++ */ ++ ++/* ++ * USB registers ++ */ ++/* SIE Control Registers */ ++#define USB_SYSCTL 0x2000 /* USB system control */ ++#define USB_SYSCTL_0 0x2000 /* USB system control */ ++#define USB_SYSCTL_1 0x2001 /* USB system control */ ++#define USB_SYSCTL_2 0x2002 /* USB system control */ ++#define USB_SYSCTL_3 0x2003 /* USB system control */ ++#define USB_IRQSTAT 0x2008 /* SIE interrupt status */ ++#define USB_IRQEN 0x200C /* SIE interrupt enable */ ++#define USB_CTRL 0x2010 /* USB control */ ++#define USB_STAT 0x2014 /* USB status */ ++#define USB_DEVADDR 0x2018 /* USB device address */ ++#define USB_TEST 0x201C /* USB test mode */ ++#define USB_FRAME_NUMBER 0x2020 /* frame number */ ++#define USB_FIFO_ADDR 0x2028 /* address of SIE FIFO RAM */ ++#define USB_FIFO_CMD 0x202A /* SIE FIFO RAM access command */ ++#define USB_FIFO_DATA 0x2030 /* SIE FIFO RAM data */ ++/* Endpoint Registers */ ++#define EP0_SETUPA 0x20F8 /* EP 0 setup packet lower byte */ ++#define EP0_SETUPB 0x20FC /* EP 0 setup packet higher byte */ ++#define USB_EP0_CFG 0x2104 /* EP 0 configure */ ++#define USB_EP0_CTL 0x2108 /* EP 0 control */ ++#define USB_EP0_STAT 0x210C /* EP 0 status */ ++#define USB_EP0_IRQSTAT 0x2110 /* EP 0 interrupt status */ ++#define USB_EP0_IRQEN 0x2114 /* EP 0 interrupt enable */ ++#define USB_EP0_MAXPKT 0x2118 /* EP 0 max packet size */ ++#define USB_EP0_BC 0x2120 /* EP 0 FIFO byte counter */ ++#define USB_EPA_CFG 0x2144 /* EP A configure */ ++#define USB_EPA_CFG_0 0x2144 /* EP A configure */ ++#define USB_EPA_CFG_1 0x2145 /* EP A configure */ ++#define USB_EPA_CFG_2 0x2146 /* EP A configure */ ++#define USB_EPA_CFG_3 0x2147 /* EP A configure */ ++#define USB_EPA_CTL 0x2148 /* EP A control */ ++#define USB_EPA_CTL_0 0x2148 /* EP A control */ ++#define USB_EPA_CTL_1 0x2149 /* EP A control */ ++#define USB_EPA_CTL_2 0x214A /* EP A control */ ++#define USB_EPA_CTL_3 0x214B /* EP A control */ ++#define USB_EPA_STAT 0x214C /* EP A status */ ++#define USB_EPA_IRQSTAT 0x2150 /* EP A interrupt status */ ++#define USB_EPA_IRQEN 0x2154 /* EP A interrupt enable */ ++#define USB_EPA_MAXPKT 0x2158 /* EP A max packet size */ ++#define USB_EPA_MAXPKT_0 0x2158 /* EP A max packet size */ ++#define USB_EPA_MAXPKT_1 0x2159 /* EP A max packet size */ ++#define USB_EPA_MAXPKT_2 0x215A /* EP A max packet size */ ++#define USB_EPA_MAXPKT_3 0x215B /* EP A max packet size */ ++#define USB_EPA_FIFO_CFG 0x2160 /* EP A FIFO configure */ ++#define USB_EPA_FIFO_CFG_0 0x2160 /* EP A FIFO configure */ ++#define USB_EPA_FIFO_CFG_1 0x2161 /* EP A FIFO configure */ ++#define USB_EPA_FIFO_CFG_2 0x2162 /* EP A FIFO configure */ ++#define USB_EPA_FIFO_CFG_3 0x2163 /* EP A FIFO configure */ ++/* Debug Registers */ ++#define USB_PHYTSTDIS 0x2F04 /* PHY test disable */ ++#define USB_TOUT_VAL 0x2F08 /* USB time-out time */ ++#define USB_VDRCTRL 0x2F10 /* UTMI vendor signal control */ ++#define USB_VSTAIN 0x2F14 /* UTMI vendor signal status in */ ++#define USB_VLOADM 0x2F18 /* UTMI load vendor signal status in */ ++#define USB_VSTAOUT 0x2F1C /* UTMI vendor signal status out */ ++#define USB_UTMI_TST 0x2F80 /* UTMI test */ ++#define USB_UTMI_STATUS 0x2F84 /* UTMI status */ ++#define USB_TSTCTL 0x2F88 /* test control */ ++#define USB_TSTCTL2 0x2F8C /* test control 2 */ ++#define USB_PID_FORCE 0x2F90 /* force PID */ ++#define USB_PKTERR_CNT 0x2F94 /* packet error counter */ ++#define USB_RXERR_CNT 0x2F98 /* RX error counter */ ++#define USB_MEM_BIST 0x2F9C /* MEM BIST test */ ++#define USB_SLBBIST 0x2FA0 /* self-loop-back BIST */ ++#define USB_CNTTEST 0x2FA4 /* counter test */ ++#define USB_PHYTST 0x2FC0 /* USB PHY test */ ++#define USB_DBGIDX 0x2FF0 /* select individual block debug signal */ ++#define USB_DBGMUX 0x2FF4 /* debug signal module mux */ ++ ++/* ++ * SYS registers ++ */ ++/* demod control registers */ ++#define SYS_SYS0 0x3000 /* include DEMOD_CTL, GPO, GPI, GPOE */ ++#define SYS_DEMOD_CTL 0x3000 /* control register for DVB-T demodulator */ ++/* GPIO registers */ ++#define SYS_GPIO_OUT_VAL 0x3001 /* output value of GPIO */ ++#define SYS_GPIO_IN_VAL 0x3002 /* input value of GPIO */ ++#define SYS_GPIO_OUT_EN 0x3003 /* output enable of GPIO */ ++#define SYS_SYS1 0x3004 /* include GPD, SYSINTE, SYSINTS, GP_CFG0 */ ++#define SYS_GPIO_DIR 0x3004 /* direction control for GPIO */ ++#define SYS_SYSINTE 0x3005 /* system interrupt enable */ ++#define SYS_SYSINTS 0x3006 /* system interrupt status */ ++#define SYS_GPIO_CFG0 0x3007 /* PAD configuration for GPIO0-GPIO3 */ ++#define SYS_SYS2 0x3008 /* include GP_CFG1 and 3 reserved bytes */ ++#define SYS_GPIO_CFG1 0x3008 /* PAD configuration for GPIO4 */ ++#define SYS_DEMOD_CTL1 0x300B ++ ++/* IrDA registers */ ++#define SYS_IRRC_PSR 0x3020 /* IR protocol selection */ ++#define SYS_IRRC_PER 0x3024 /* IR protocol extension */ ++#define SYS_IRRC_SF 0x3028 /* IR sampling frequency */ ++#define SYS_IRRC_DPIR 0x302C /* IR data package interval */ ++#define SYS_IRRC_CR 0x3030 /* IR control */ ++#define SYS_IRRC_RP 0x3034 /* IR read port */ ++#define SYS_IRRC_SR 0x3038 /* IR status */ ++/* I2C master registers */ ++#define SYS_I2CCR 0x3040 /* I2C clock */ ++#define SYS_I2CMCR 0x3044 /* I2C master control */ ++#define SYS_I2CMSTR 0x3048 /* I2C master SCL timing */ ++#define SYS_I2CMSR 0x304C /* I2C master status */ ++#define SYS_I2CMFR 0x3050 /* I2C master FIFO */ ++ ++/* ++ * IR registers ++ */ ++#define IR_RX_BUF 0xFC00 ++#define IR_RX_IE 0xFD00 ++#define IR_RX_IF 0xFD01 ++#define IR_RX_CTRL 0xFD02 ++#define IR_RX_CFG 0xFD03 ++#define IR_MAX_DURATION0 0xFD04 ++#define IR_MAX_DURATION1 0xFD05 ++#define IR_IDLE_LEN0 0xFD06 ++#define IR_IDLE_LEN1 0xFD07 ++#define IR_GLITCH_LEN 0xFD08 ++#define IR_RX_BUF_CTRL 0xFD09 ++#define IR_RX_BUF_DATA 0xFD0A ++#define IR_RX_BC 0xFD0B ++#define IR_RX_CLK 0xFD0C ++#define IR_RX_C_COUNT_L 0xFD0D ++#define IR_RX_C_COUNT_H 0xFD0E ++#define IR_SUSPEND_CTRL 0xFD10 ++#define IR_ERR_TOL_CTRL 0xFD11 ++#define IR_UNIT_LEN 0xFD12 ++#define IR_ERR_TOL_LEN 0xFD13 ++#define IR_MAX_H_TOL_LEN 0xFD14 ++#define IR_MAX_L_TOL_LEN 0xFD15 ++#define IR_MASK_CTRL 0xFD16 ++#define IR_MASK_DATA 0xFD17 ++#define IR_RES_MASK_ADDR 0xFD18 ++#define IR_RES_MASK_T_LEN 0xFD19 ++ ++#endif +Index: linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-jpeg/jpeg-core.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-core.c +@@ -32,10 +32,9 @@ + + static struct s5p_jpeg_fmt formats_enc[] = { + { +- .name = "YUV 4:2:0 planar, YCbCr", +- .fourcc = V4L2_PIX_FMT_YUV420, +- .depth = 12, +- .colplanes = 3, ++ .name = "JPEG JFIF", ++ .fourcc = V4L2_PIX_FMT_JPEG, ++ .colplanes = 1, + .types = MEM2MEM_CAPTURE, + }, + { +@@ -43,7 +42,7 @@ static struct s5p_jpeg_fmt formats_enc[] + .fourcc = V4L2_PIX_FMT_YUYV, + .depth = 16, + .colplanes = 1, +- .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, ++ .types = MEM2MEM_OUTPUT, + }, + { + .name = "RGB565", +@@ -203,6 +202,16 @@ static const unsigned char hactblg0[162] + 0xf9, 0xfa + }; + ++static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c) ++{ ++ return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler); ++} ++ ++static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh) ++{ ++ return container_of(fh, struct s5p_jpeg_ctx, fh); ++} ++ + static inline void jpeg_set_qtbl(void __iomem *regs, const unsigned char *qtbl, + unsigned long tab, int len) + { +@@ -269,6 +278,7 @@ static int queue_init(void *priv, struct + struct vb2_queue *dst_vq); + static struct s5p_jpeg_fmt *s5p_jpeg_find_format(unsigned int mode, + __u32 pixelformat); ++static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx); + + static int s5p_jpeg_open(struct file *file) + { +@@ -276,12 +286,18 @@ static int s5p_jpeg_open(struct file *fi + struct video_device *vfd = video_devdata(file); + struct s5p_jpeg_ctx *ctx; + struct s5p_jpeg_fmt *out_fmt; ++ int ret = 0; + + ctx = kzalloc(sizeof *ctx, GFP_KERNEL); + if (!ctx) + return -ENOMEM; + +- file->private_data = ctx; ++ v4l2_fh_init(&ctx->fh, vfd); ++ /* Use separate control handler per file handle */ ++ ctx->fh.ctrl_handler = &ctx->ctrl_handler; ++ file->private_data = &ctx->fh; ++ v4l2_fh_add(&ctx->fh); ++ + ctx->jpeg = jpeg; + if (vfd == jpeg->vfd_encoder) { + ctx->mode = S5P_JPEG_ENCODE; +@@ -291,24 +307,35 @@ static int s5p_jpeg_open(struct file *fi + out_fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_JPEG); + } + ++ ret = s5p_jpeg_controls_create(ctx); ++ if (ret < 0) ++ goto error; ++ + ctx->m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init); + if (IS_ERR(ctx->m2m_ctx)) { +- int err = PTR_ERR(ctx->m2m_ctx); +- kfree(ctx); +- return err; ++ ret = PTR_ERR(ctx->m2m_ctx); ++ goto error; + } + + ctx->out_q.fmt = out_fmt; + ctx->cap_q.fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_YUYV); +- + return 0; ++ ++error: ++ v4l2_fh_del(&ctx->fh); ++ v4l2_fh_exit(&ctx->fh); ++ kfree(ctx); ++ return ret; + } + + static int s5p_jpeg_release(struct file *file) + { +- struct s5p_jpeg_ctx *ctx = file->private_data; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); + + v4l2_m2m_ctx_release(ctx->m2m_ctx); ++ v4l2_ctrl_handler_free(&ctx->ctrl_handler); ++ v4l2_fh_del(&ctx->fh); ++ v4l2_fh_exit(&ctx->fh); + kfree(ctx); + + return 0; +@@ -317,14 +344,14 @@ static int s5p_jpeg_release(struct file + static unsigned int s5p_jpeg_poll(struct file *file, + struct poll_table_struct *wait) + { +- struct s5p_jpeg_ctx *ctx = file->private_data; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); + + return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); + } + + static int s5p_jpeg_mmap(struct file *file, struct vm_area_struct *vma) + { +- struct s5p_jpeg_ctx *ctx = file->private_data; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); + + return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); + } +@@ -448,7 +475,7 @@ static bool s5p_jpeg_parse_hdr(struct s5 + static int s5p_jpeg_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + if (ctx->mode == S5P_JPEG_ENCODE) { + strlcpy(cap->driver, S5P_JPEG_M2M_NAME " encoder", +@@ -497,9 +524,7 @@ static int enum_fmt(struct s5p_jpeg_fmt + static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) + { +- struct s5p_jpeg_ctx *ctx; +- +- ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + if (ctx->mode == S5P_JPEG_ENCODE) + return enum_fmt(formats_enc, NUM_FORMATS_ENC, f, +@@ -511,9 +536,7 @@ static int s5p_jpeg_enum_fmt_vid_cap(str + static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv, + struct v4l2_fmtdesc *f) + { +- struct s5p_jpeg_ctx *ctx; +- +- ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + if (ctx->mode == S5P_JPEG_ENCODE) + return enum_fmt(formats_enc, NUM_FORMATS_ENC, f, +@@ -538,7 +561,7 @@ static int s5p_jpeg_g_fmt(struct file *f + struct vb2_queue *vq; + struct s5p_jpeg_q_data *q_data = NULL; + struct v4l2_pix_format *pix = &f->fmt.pix; +- struct s5p_jpeg_ctx *ct = priv; ++ struct s5p_jpeg_ctx *ct = fh_to_ctx(priv); + + vq = v4l2_m2m_get_vq(ct->m2m_ctx, f->type); + if (!vq) +@@ -659,8 +682,8 @@ static int vidioc_try_fmt(struct v4l2_fo + static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) + { ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + struct s5p_jpeg_fmt *fmt; +- struct s5p_jpeg_ctx *ctx = priv; + + fmt = s5p_jpeg_find_format(ctx->mode, f->fmt.pix.pixelformat); + if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) { +@@ -676,8 +699,8 @@ static int s5p_jpeg_try_fmt_vid_cap(stru + static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *f) + { ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + struct s5p_jpeg_fmt *fmt; +- struct s5p_jpeg_ctx *ctx = priv; + + fmt = s5p_jpeg_find_format(ctx->mode, f->fmt.pix.pixelformat); + if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) { +@@ -728,7 +751,7 @@ static int s5p_jpeg_s_fmt_vid_cap(struct + if (ret) + return ret; + +- return s5p_jpeg_s_fmt(priv, f); ++ return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); + } + + static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv, +@@ -740,13 +763,13 @@ static int s5p_jpeg_s_fmt_vid_out(struct + if (ret) + return ret; + +- return s5p_jpeg_s_fmt(priv, f); ++ return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); + } + + static int s5p_jpeg_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *reqbufs) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); + } +@@ -754,14 +777,14 @@ static int s5p_jpeg_reqbufs(struct file + static int s5p_jpeg_querybuf(struct file *file, void *priv, + struct v4l2_buffer *buf) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); + } + + static int s5p_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); + } +@@ -769,7 +792,7 @@ static int s5p_jpeg_qbuf(struct file *fi + static int s5p_jpeg_dqbuf(struct file *file, void *priv, + struct v4l2_buffer *buf) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); + } +@@ -777,7 +800,7 @@ static int s5p_jpeg_dqbuf(struct file *f + static int s5p_jpeg_streamon(struct file *file, void *priv, + enum v4l2_buf_type type) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); + } +@@ -785,7 +808,7 @@ static int s5p_jpeg_streamon(struct file + static int s5p_jpeg_streamoff(struct file *file, void *priv, + enum v4l2_buf_type type) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); + } +@@ -793,7 +816,7 @@ static int s5p_jpeg_streamoff(struct fil + int s5p_jpeg_g_selection(struct file *file, void *priv, + struct v4l2_selection *s) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); + + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && + s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) +@@ -822,33 +845,89 @@ int s5p_jpeg_g_selection(struct file *fi + return 0; + } + +-static int s5p_jpeg_g_jpegcomp(struct file *file, void *priv, +- struct v4l2_jpegcompression *compr) ++/* ++ * V4L2 controls ++ */ ++ ++static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl); ++ struct s5p_jpeg *jpeg = ctx->jpeg; ++ unsigned long flags; + +- if (ctx->mode == S5P_JPEG_DECODE) +- return -ENOTTY; ++ switch (ctrl->id) { ++ case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: ++ spin_lock_irqsave(&jpeg->slock, flags); ++ ++ WARN_ON(ctx->subsampling > S5P_SUBSAMPLING_MODE_GRAY); ++ if (ctx->subsampling > 2) ++ ctrl->val = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; ++ else ++ ctrl->val = ctx->subsampling; ++ spin_unlock_irqrestore(&jpeg->slock, flags); ++ break; ++ } + +- memset(compr, 0, sizeof(*compr)); +- compr->quality = ctx->compr_quality; ++ return 0; ++} ++ ++static int s5p_jpeg_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ctx->jpeg->slock, flags); ++ ++ switch (ctrl->id) { ++ case V4L2_CID_JPEG_COMPRESSION_QUALITY: ++ ctx->compr_quality = S5P_JPEG_COMPR_QUAL_WORST - ctrl->val; ++ break; ++ case V4L2_CID_JPEG_RESTART_INTERVAL: ++ ctx->restart_interval = ctrl->val; ++ break; ++ case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: ++ ctx->subsampling = ctrl->val; ++ break; ++ } + ++ spin_unlock_irqrestore(&ctx->jpeg->slock, flags); + return 0; + } + +-static int s5p_jpeg_s_jpegcomp(struct file *file, void *priv, +- struct v4l2_jpegcompression *compr) ++static const struct v4l2_ctrl_ops s5p_jpeg_ctrl_ops = { ++ .g_volatile_ctrl = s5p_jpeg_g_volatile_ctrl, ++ .s_ctrl = s5p_jpeg_s_ctrl, ++}; ++ ++static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx) + { +- struct s5p_jpeg_ctx *ctx = priv; ++ unsigned int mask = ~0x27; /* 444, 422, 420, GRAY */ ++ struct v4l2_ctrl *ctrl; + +- if (ctx->mode == S5P_JPEG_DECODE) +- return -ENOTTY; ++ v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3); + +- compr->quality = clamp(compr->quality, S5P_JPEG_COMPR_QUAL_BEST, +- S5P_JPEG_COMPR_QUAL_WORST); ++ if (ctx->mode == S5P_JPEG_ENCODE) { ++ v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops, ++ V4L2_CID_JPEG_COMPRESSION_QUALITY, ++ 0, 3, 1, 3); ++ ++ v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops, ++ V4L2_CID_JPEG_RESTART_INTERVAL, ++ 0, 3, 0xffff, 0); ++ mask = ~0x06; /* 422, 420 */ ++ } ++ ++ ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops, ++ V4L2_CID_JPEG_CHROMA_SUBSAMPLING, ++ V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY, mask, ++ V4L2_JPEG_CHROMA_SUBSAMPLING_422); + +- ctx->compr_quality = S5P_JPEG_COMPR_QUAL_WORST - compr->quality; ++ if (ctx->ctrl_handler.error) ++ return ctx->ctrl_handler.error; + ++ if (ctx->mode == S5P_JPEG_DECODE) ++ ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE | ++ V4L2_CTRL_FLAG_READ_ONLY; + return 0; + } + +@@ -877,9 +956,6 @@ static const struct v4l2_ioctl_ops s5p_j + .vidioc_streamoff = s5p_jpeg_streamoff, + + .vidioc_g_selection = s5p_jpeg_g_selection, +- +- .vidioc_g_jpegcomp = s5p_jpeg_g_jpegcomp, +- .vidioc_s_jpegcomp = s5p_jpeg_s_jpegcomp, + }; + + /* +@@ -908,13 +984,8 @@ static void s5p_jpeg_device_run(void *pr + jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_565); + else + jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_422); +- if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV) +- jpeg_subsampling_mode(jpeg->regs, +- S5P_JPEG_SUBSAMPLING_422); +- else +- jpeg_subsampling_mode(jpeg->regs, +- S5P_JPEG_SUBSAMPLING_420); +- jpeg_dri(jpeg->regs, 0); ++ jpeg_subsampling_mode(jpeg->regs, ctx->subsampling); ++ jpeg_dri(jpeg->regs, ctx->restart_interval); + jpeg_x(jpeg->regs, ctx->out_q.w); + jpeg_y(jpeg->regs, ctx->out_q.h); + jpeg_imgadr(jpeg->regs, src_addr); +@@ -953,14 +1024,18 @@ static void s5p_jpeg_device_run(void *pr + jpeg_htbl_dc(jpeg->regs, 2); + jpeg_htbl_ac(jpeg->regs, 3); + jpeg_htbl_dc(jpeg->regs, 3); +- } else { ++ } else { /* S5P_JPEG_DECODE */ + jpeg_rst_int_enable(jpeg->regs, true); + jpeg_data_num_int_enable(jpeg->regs, true); + jpeg_final_mcu_num_int_enable(jpeg->regs, true); +- jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422); ++ if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV) ++ jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422); ++ else ++ jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_420); + jpeg_jpgadr(jpeg->regs, src_addr); + jpeg_imgadr(jpeg->regs, dst_addr); + } ++ + jpeg_start(jpeg->regs); + } + +@@ -1162,6 +1237,8 @@ static irqreturn_t s5p_jpeg_irq(int irq, + bool timer_elapsed = false; + bool op_completed = false; + ++ spin_lock(&jpeg->slock); ++ + curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); + + src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); +@@ -1192,6 +1269,9 @@ static irqreturn_t s5p_jpeg_irq(int irq, + v4l2_m2m_buf_done(dst_buf, state); + v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->m2m_ctx); + ++ curr_ctx->subsampling = jpeg_get_subsampling_mode(jpeg->regs); ++ spin_unlock(&jpeg->slock); ++ + jpeg_clear_int(jpeg->regs); + + return IRQ_HANDLED; +@@ -1215,6 +1295,7 @@ static int s5p_jpeg_probe(struct platfor + return -ENOMEM; + + mutex_init(&jpeg->lock); ++ spin_lock_init(&jpeg->slock); + jpeg->dev = &pdev->dev; + + /* memory-mapped registers */ +Index: linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-core.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-jpeg/jpeg-core.h ++++ linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-core.h +@@ -14,6 +14,8 @@ + #define JPEG_CORE_H_ + + #include ++#include ++#include + + #define S5P_JPEG_M2M_NAME "s5p-jpeg" + +@@ -47,6 +49,7 @@ + /** + * struct s5p_jpeg - JPEG IP abstraction + * @lock: the mutex protecting this structure ++ * @slock: spinlock protecting the device contexts + * @v4l2_dev: v4l2 device for mem2mem mode + * @vfd_encoder: video device node for encoder mem2mem mode + * @vfd_decoder: video device node for decoder mem2mem mode +@@ -60,6 +63,7 @@ + */ + struct s5p_jpeg { + struct mutex lock; ++ struct spinlock slock; + + struct v4l2_device v4l2_dev; + struct video_device *vfd_encoder; +@@ -117,15 +121,20 @@ struct s5p_jpeg_q_data { + * @out_q: source (output) queue information + * @cap_fmt: destination (capture) queue queue information + * @hdr_parsed: set if header has been parsed during decompression ++ * @ctrl_handler: controls handler + */ + struct s5p_jpeg_ctx { + struct s5p_jpeg *jpeg; + unsigned int mode; +- unsigned int compr_quality; ++ unsigned short compr_quality; ++ unsigned short restart_interval; ++ unsigned short subsampling; + struct v4l2_m2m_ctx *m2m_ctx; + struct s5p_jpeg_q_data out_q; + struct s5p_jpeg_q_data cap_q; ++ struct v4l2_fh fh; + bool hdr_parsed; ++ struct v4l2_ctrl_handler ctrl_handler; + }; + + /** +Index: linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-hw.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-jpeg/jpeg-hw.h ++++ linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-hw.h +@@ -13,6 +13,7 @@ + #define JPEG_HW_H_ + + #include ++#include + + #include "jpeg-hw.h" + #include "jpeg-regs.h" +@@ -25,8 +26,6 @@ + #define S5P_JPEG_DECODE 1 + #define S5P_JPEG_RAW_IN_565 0 + #define S5P_JPEG_RAW_IN_422 1 +-#define S5P_JPEG_SUBSAMPLING_422 0 +-#define S5P_JPEG_SUBSAMPLING_420 1 + #define S5P_JPEG_RAW_OUT_422 0 + #define S5P_JPEG_RAW_OUT_420 1 + +@@ -91,21 +90,26 @@ static inline void jpeg_proc_mode(void _ + writel(reg, regs + S5P_JPGMOD); + } + +-static inline void jpeg_subsampling_mode(void __iomem *regs, unsigned long mode) ++static inline void jpeg_subsampling_mode(void __iomem *regs, unsigned int mode) + { + unsigned long reg, m; + +- m = S5P_SUBSAMPLING_MODE_422; +- if (mode == S5P_JPEG_SUBSAMPLING_422) +- m = S5P_SUBSAMPLING_MODE_422; +- else if (mode == S5P_JPEG_SUBSAMPLING_420) ++ if (mode == V4L2_JPEG_CHROMA_SUBSAMPLING_420) + m = S5P_SUBSAMPLING_MODE_420; ++ else ++ m = S5P_SUBSAMPLING_MODE_422; ++ + reg = readl(regs + S5P_JPGMOD); + reg &= ~S5P_SUBSAMPLING_MODE_MASK; + reg |= m; + writel(reg, regs + S5P_JPGMOD); + } + ++static inline unsigned int jpeg_get_subsampling_mode(void __iomem *regs) ++{ ++ return readl(regs + S5P_JPGMOD) & S5P_SUBSAMPLING_MODE_MASK; ++} ++ + static inline void jpeg_dri(void __iomem *regs, unsigned int dri) + { + unsigned long reg; +Index: linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-fimc/fimc-core.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-core.c +@@ -1602,24 +1602,35 @@ static void fimc_clk_put(struct fimc_dev + { + int i; + for (i = 0; i < fimc->num_clocks; i++) { +- if (fimc->clock[i]) +- clk_put(fimc->clock[i]); ++ if (IS_ERR_OR_NULL(fimc->clock[i])) ++ continue; ++ clk_unprepare(fimc->clock[i]); ++ clk_put(fimc->clock[i]); ++ fimc->clock[i] = NULL; + } + } + + static int fimc_clk_get(struct fimc_dev *fimc) + { +- int i; ++ int i, ret; ++ + for (i = 0; i < fimc->num_clocks; i++) { + fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]); +- if (!IS_ERR_OR_NULL(fimc->clock[i])) +- continue; +- dev_err(&fimc->pdev->dev, "failed to get fimc clock: %s\n", +- fimc_clocks[i]); +- return -ENXIO; ++ if (IS_ERR(fimc->clock[i])) ++ goto err; ++ ret = clk_prepare(fimc->clock[i]); ++ if (ret < 0) { ++ clk_put(fimc->clock[i]); ++ fimc->clock[i] = NULL; ++ goto err; ++ } + } +- + return 0; ++err: ++ fimc_clk_put(fimc); ++ dev_err(&fimc->pdev->dev, "failed to get clock: %s\n", ++ fimc_clocks[i]); ++ return -ENXIO; + } + + static int fimc_m2m_suspend(struct fimc_dev *fimc) +@@ -1667,8 +1678,6 @@ static int fimc_probe(struct platform_de + struct s5p_platform_fimc *pdata; + int ret = 0; + +- dev_dbg(&pdev->dev, "%s():\n", __func__); +- + drv_data = (struct samsung_fimc_driverdata *) + platform_get_device_id(pdev)->driver_data; + +@@ -1678,7 +1687,7 @@ static int fimc_probe(struct platform_de + return -EINVAL; + } + +- fimc = kzalloc(sizeof(struct fimc_dev), GFP_KERNEL); ++ fimc = devm_kzalloc(&pdev->dev, sizeof(*fimc), GFP_KERNEL); + if (!fimc) + return -ENOMEM; + +@@ -1689,51 +1698,35 @@ static int fimc_probe(struct platform_de + pdata = pdev->dev.platform_data; + fimc->pdata = pdata; + +- + init_waitqueue_head(&fimc->irq_queue); + spin_lock_init(&fimc->slock); + mutex_init(&fimc->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!res) { +- dev_err(&pdev->dev, "failed to find the registers\n"); +- ret = -ENOENT; +- goto err_info; +- } +- +- fimc->regs_res = request_mem_region(res->start, resource_size(res), +- dev_name(&pdev->dev)); +- if (!fimc->regs_res) { +- dev_err(&pdev->dev, "failed to obtain register region\n"); +- ret = -ENOENT; +- goto err_info; +- } +- +- fimc->regs = ioremap(res->start, resource_size(res)); +- if (!fimc->regs) { +- dev_err(&pdev->dev, "failed to map registers\n"); +- ret = -ENXIO; +- goto err_req_region; ++ fimc->regs = devm_request_and_ioremap(&pdev->dev, res); ++ if (fimc->regs == NULL) { ++ dev_err(&pdev->dev, "Failed to obtain io memory\n"); ++ return -ENOENT; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); +- if (!res) { +- dev_err(&pdev->dev, "failed to get IRQ resource\n"); +- ret = -ENXIO; +- goto err_regs_unmap; ++ if (res == NULL) { ++ dev_err(&pdev->dev, "Failed to get IRQ resource\n"); ++ return -ENXIO; + } + fimc->irq = res->start; + + fimc->num_clocks = MAX_FIMC_CLOCKS; + ret = fimc_clk_get(fimc); + if (ret) +- goto err_regs_unmap; ++ return ret; + clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency); + clk_enable(fimc->clock[CLK_BUS]); + + platform_set_drvdata(pdev, fimc); + +- ret = request_irq(fimc->irq, fimc_irq_handler, 0, pdev->name, fimc); ++ ret = devm_request_irq(&pdev->dev, fimc->irq, fimc_irq_handler, ++ 0, pdev->name, fimc); + if (ret) { + dev_err(&pdev->dev, "failed to install irq (%d)\n", ret); + goto err_clk; +@@ -1742,7 +1735,7 @@ static int fimc_probe(struct platform_de + pm_runtime_enable(&pdev->dev); + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) +- goto err_irq; ++ goto err_clk; + /* Initialize contiguous memory allocator */ + fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); + if (IS_ERR(fimc->alloc_ctx)) { +@@ -1757,17 +1750,8 @@ static int fimc_probe(struct platform_de + + err_pm: + pm_runtime_put(&pdev->dev); +-err_irq: +- free_irq(fimc->irq, fimc); + err_clk: + fimc_clk_put(fimc); +-err_regs_unmap: +- iounmap(fimc->regs); +-err_req_region: +- release_resource(fimc->regs_res); +- kfree(fimc->regs_res); +-err_info: +- kfree(fimc); + return ret; + } + +@@ -1854,11 +1838,6 @@ static int __devexit fimc_remove(struct + + clk_disable(fimc->clock[CLK_BUS]); + fimc_clk_put(fimc); +- free_irq(fimc->irq, fimc); +- iounmap(fimc->regs); +- release_resource(fimc->regs_res); +- kfree(fimc->regs_res); +- kfree(fimc); + + dev_info(&pdev->dev, "driver unloaded\n"); + return 0; +Index: linux-3.3.x86_64/drivers/media/video/s5p-fimc/mipi-csis.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-fimc/mipi-csis.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-fimc/mipi-csis.c +@@ -1,8 +1,8 @@ + /* + * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver + * +- * Copyright (C) 2011 Samsung Electronics Co., Ltd. +- * Contact: Sylwester Nawrocki, ++ * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. ++ * Sylwester Nawrocki, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as +@@ -100,7 +100,6 @@ enum { + * @pads: CSIS pads array + * @sd: v4l2_subdev associated with CSIS device instance + * @pdev: CSIS platform device +- * @regs_res: requested I/O register memory resource + * @regs: mmaped I/O registers memory + * @clock: CSIS clocks + * @irq: requested s5p-mipi-csis irq number +@@ -113,7 +112,6 @@ struct csis_state { + struct media_pad pads[CSIS_PADS_NUM]; + struct v4l2_subdev sd; + struct platform_device *pdev; +- struct resource *regs_res; + void __iomem *regs; + struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES]; + struct clk *clock[NUM_CSIS_CLOCKS]; +@@ -258,26 +256,36 @@ static void s5pcsis_clk_put(struct csis_ + { + int i; + +- for (i = 0; i < NUM_CSIS_CLOCKS; i++) +- if (!IS_ERR_OR_NULL(state->clock[i])) +- clk_put(state->clock[i]); ++ for (i = 0; i < NUM_CSIS_CLOCKS; i++) { ++ if (IS_ERR_OR_NULL(state->clock[i])) ++ continue; ++ clk_unprepare(state->clock[i]); ++ clk_put(state->clock[i]); ++ state->clock[i] = NULL; ++ } + } + + static int s5pcsis_clk_get(struct csis_state *state) + { + struct device *dev = &state->pdev->dev; +- int i; ++ int i, ret; + + for (i = 0; i < NUM_CSIS_CLOCKS; i++) { + state->clock[i] = clk_get(dev, csi_clock_name[i]); +- if (IS_ERR(state->clock[i])) { +- s5pcsis_clk_put(state); +- dev_err(dev, "failed to get clock: %s\n", +- csi_clock_name[i]); +- return -ENXIO; ++ if (IS_ERR(state->clock[i])) ++ goto err; ++ ret = clk_prepare(state->clock[i]); ++ if (ret < 0) { ++ clk_put(state->clock[i]); ++ state->clock[i] = NULL; ++ goto err; + } + } + return 0; ++err: ++ s5pcsis_clk_put(state); ++ dev_err(dev, "failed to get clock: %s\n", csi_clock_name[i]); ++ return -ENXIO; + } + + static int s5pcsis_s_power(struct v4l2_subdev *sd, int on) +@@ -480,12 +488,11 @@ static int __devinit s5pcsis_probe(struc + { + struct s5p_platform_mipi_csis *pdata; + struct resource *mem_res; +- struct resource *regs_res; + struct csis_state *state; + int ret = -ENOMEM; + int i; + +- state = kzalloc(sizeof(*state), GFP_KERNEL); ++ state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + +@@ -495,52 +502,27 @@ static int __devinit s5pcsis_probe(struc + pdata = pdev->dev.platform_data; + if (pdata == NULL || pdata->phy_enable == NULL) { + dev_err(&pdev->dev, "Platform data not fully specified\n"); +- goto e_free; ++ return -EINVAL; + } + + if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) || + pdata->lanes > CSIS0_MAX_LANES) { +- ret = -EINVAL; + dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n", + pdata->lanes); +- goto e_free; ++ return -EINVAL; + } + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!mem_res) { +- dev_err(&pdev->dev, "Failed to get IO memory region\n"); +- goto e_free; +- } +- +- regs_res = request_mem_region(mem_res->start, resource_size(mem_res), +- pdev->name); +- if (!regs_res) { +- dev_err(&pdev->dev, "Failed to request IO memory region\n"); +- goto e_free; +- } +- state->regs_res = regs_res; +- +- state->regs = ioremap(mem_res->start, resource_size(mem_res)); +- if (!state->regs) { +- dev_err(&pdev->dev, "Failed to remap IO region\n"); +- goto e_reqmem; ++ state->regs = devm_request_and_ioremap(&pdev->dev, mem_res); ++ if (state->regs == NULL) { ++ dev_err(&pdev->dev, "Failed to request and remap io memory\n"); ++ return -ENXIO; + } + +- ret = s5pcsis_clk_get(state); +- if (ret) +- goto e_unmap; +- +- clk_enable(state->clock[CSIS_CLK_MUX]); +- if (pdata->clk_rate) +- clk_set_rate(state->clock[CSIS_CLK_MUX], pdata->clk_rate); +- else +- dev_WARN(&pdev->dev, "No clock frequency specified!\n"); +- + state->irq = platform_get_irq(pdev, 0); + if (state->irq < 0) { +- ret = state->irq; + dev_err(&pdev->dev, "Failed to get irq\n"); +- goto e_clkput; ++ return state->irq; + } + + for (i = 0; i < CSIS_NUM_SUPPLIES; i++) +@@ -549,12 +531,22 @@ static int __devinit s5pcsis_probe(struc + ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES, + state->supplies); + if (ret) ++ return ret; ++ ++ ret = s5pcsis_clk_get(state); ++ if (ret) + goto e_clkput; + +- ret = request_irq(state->irq, s5pcsis_irq_handler, 0, +- dev_name(&pdev->dev), state); ++ clk_enable(state->clock[CSIS_CLK_MUX]); ++ if (pdata->clk_rate) ++ clk_set_rate(state->clock[CSIS_CLK_MUX], pdata->clk_rate); ++ else ++ dev_WARN(&pdev->dev, "No clock frequency specified!\n"); ++ ++ ret = devm_request_irq(&pdev->dev, state->irq, s5pcsis_irq_handler, ++ 0, dev_name(&pdev->dev), state); + if (ret) { +- dev_err(&pdev->dev, "request_irq failed\n"); ++ dev_err(&pdev->dev, "Interrupt request failed\n"); + goto e_regput; + } + +@@ -573,7 +565,7 @@ static int __devinit s5pcsis_probe(struc + ret = media_entity_init(&state->sd.entity, + CSIS_PADS_NUM, state->pads, 0); + if (ret < 0) +- goto e_irqfree; ++ goto e_clkput; + + /* This allows to retrieve the platform device id by the host driver */ + v4l2_set_subdevdata(&state->sd, pdev); +@@ -582,22 +574,13 @@ static int __devinit s5pcsis_probe(struc + platform_set_drvdata(pdev, &state->sd); + + pm_runtime_enable(&pdev->dev); +- + return 0; + +-e_irqfree: +- free_irq(state->irq, state); + e_regput: + regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); + e_clkput: + clk_disable(state->clock[CSIS_CLK_MUX]); + s5pcsis_clk_put(state); +-e_unmap: +- iounmap(state->regs); +-e_reqmem: +- release_mem_region(regs_res->start, resource_size(regs_res)); +-e_free: +- kfree(state); + return ret; + } + +@@ -699,21 +682,15 @@ static int __devexit s5pcsis_remove(stru + { + struct v4l2_subdev *sd = platform_get_drvdata(pdev); + struct csis_state *state = sd_to_csis_state(sd); +- struct resource *res = state->regs_res; + + pm_runtime_disable(&pdev->dev); +- s5pcsis_suspend(&pdev->dev); ++ s5pcsis_pm_suspend(&pdev->dev, false); + clk_disable(state->clock[CSIS_CLK_MUX]); + pm_runtime_set_suspended(&pdev->dev); +- + s5pcsis_clk_put(state); + regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); + + media_entity_cleanup(&state->sd.entity); +- free_irq(state->irq, state); +- iounmap(state->regs); +- release_mem_region(res->start, resource_size(res)); +- kfree(state); + + return 0; + } +Index: linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-core.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-fimc/fimc-core.h ++++ linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-core.h +@@ -434,7 +434,6 @@ struct fimc_ctx; + * @num_clocks: the number of clocks managed by this device instance + * @clock: clocks required for FIMC operation + * @regs: the mapped hardware registers +- * @regs_res: the resource claimed for IO registers + * @irq: FIMC interrupt number + * @irq_queue: interrupt handler waitqueue + * @v4l2_dev: root v4l2_device +@@ -454,7 +453,6 @@ struct fimc_dev { + u16 num_clocks; + struct clk *clock[MAX_FIMC_CLOCKS]; + void __iomem *regs; +- struct resource *regs_res; + int irq; + wait_queue_head_t irq_queue; + struct v4l2_device *v4l2_dev; +Index: linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-capture.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-fimc/fimc-capture.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-capture.c +@@ -1019,52 +1019,117 @@ static int fimc_cap_dqbuf(struct file *f + return vb2_dqbuf(&fimc->vid_cap.vbq, buf, file->f_flags & O_NONBLOCK); + } + +-static int fimc_cap_cropcap(struct file *file, void *fh, +- struct v4l2_cropcap *cr) ++static int fimc_cap_create_bufs(struct file *file, void *priv, ++ struct v4l2_create_buffers *create) + { + struct fimc_dev *fimc = video_drvdata(file); +- struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame; + +- if (cr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) +- return -EINVAL; ++ return vb2_create_bufs(&fimc->vid_cap.vbq, create); ++} + +- cr->bounds.left = 0; +- cr->bounds.top = 0; +- cr->bounds.width = f->o_width; +- cr->bounds.height = f->o_height; +- cr->defrect = cr->bounds; ++static int fimc_cap_prepare_buf(struct file *file, void *priv, ++ struct v4l2_buffer *b) ++{ ++ struct fimc_dev *fimc = video_drvdata(file); + +- return 0; ++ return vb2_prepare_buf(&fimc->vid_cap.vbq, b); + } + +-static int fimc_cap_g_crop(struct file *file, void *fh, struct v4l2_crop *cr) ++static int fimc_cap_g_selection(struct file *file, void *fh, ++ struct v4l2_selection *s) + { + struct fimc_dev *fimc = video_drvdata(file); +- struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame; ++ struct fimc_ctx *ctx = fimc->vid_cap.ctx; ++ struct fimc_frame *f = &ctx->s_frame; + +- cr->c.left = f->offs_h; +- cr->c.top = f->offs_v; +- cr->c.width = f->width; +- cr->c.height = f->height; ++ if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) ++ return -EINVAL; + +- return 0; ++ switch (s->target) { ++ case V4L2_SEL_TGT_COMPOSE_DEFAULT: ++ case V4L2_SEL_TGT_COMPOSE_BOUNDS: ++ f = &ctx->d_frame; ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ s->r.left = 0; ++ s->r.top = 0; ++ s->r.width = f->o_width; ++ s->r.height = f->o_height; ++ return 0; ++ ++ case V4L2_SEL_TGT_COMPOSE_ACTIVE: ++ f = &ctx->d_frame; ++ case V4L2_SEL_TGT_CROP_ACTIVE: ++ s->r.left = f->offs_h; ++ s->r.top = f->offs_v; ++ s->r.width = f->width; ++ s->r.height = f->height; ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++/* Return 1 if rectangle a is enclosed in rectangle b, or 0 otherwise. */ ++int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b) ++{ ++ if (a->left < b->left || a->top < b->top) ++ return 0; ++ if (a->left + a->width > b->left + b->width) ++ return 0; ++ if (a->top + a->height > b->top + b->height) ++ return 0; ++ ++ return 1; + } + +-static int fimc_cap_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) ++static int fimc_cap_s_selection(struct file *file, void *fh, ++ struct v4l2_selection *s) + { + struct fimc_dev *fimc = video_drvdata(file); + struct fimc_ctx *ctx = fimc->vid_cap.ctx; +- struct fimc_frame *ff; ++ struct v4l2_rect rect = s->r; ++ struct fimc_frame *f; + unsigned long flags; ++ unsigned int pad; ++ ++ if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) ++ return -EINVAL; ++ ++ switch (s->target) { ++ case V4L2_SEL_TGT_COMPOSE_DEFAULT: ++ case V4L2_SEL_TGT_COMPOSE_BOUNDS: ++ case V4L2_SEL_TGT_COMPOSE_ACTIVE: ++ f = &ctx->d_frame; ++ pad = FIMC_SD_PAD_SOURCE; ++ break; ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ case V4L2_SEL_TGT_CROP_ACTIVE: ++ f = &ctx->s_frame; ++ pad = FIMC_SD_PAD_SINK; ++ break; ++ default: ++ return -EINVAL; ++ } + +- fimc_capture_try_crop(ctx, &cr->c, FIMC_SD_PAD_SINK); +- ff = &ctx->s_frame; ++ fimc_capture_try_crop(ctx, &rect, pad); + ++ if (s->flags & V4L2_SEL_FLAG_LE && ++ !enclosed_rectangle(&rect, &s->r)) ++ return -ERANGE; ++ ++ if (s->flags & V4L2_SEL_FLAG_GE && ++ !enclosed_rectangle(&s->r, &rect)) ++ return -ERANGE; ++ ++ s->r = rect; + spin_lock_irqsave(&fimc->slock, flags); +- set_frame_crop(ff, cr->c.left, cr->c.top, cr->c.width, cr->c.height); +- set_bit(ST_CAPT_APPLY_CFG, &fimc->state); ++ set_frame_crop(f, s->r.left, s->r.top, s->r.width, ++ s->r.height); + spin_unlock_irqrestore(&fimc->slock, flags); + ++ set_bit(ST_CAPT_APPLY_CFG, &fimc->state); + return 0; + } + +@@ -1082,12 +1147,14 @@ static const struct v4l2_ioctl_ops fimc_ + .vidioc_qbuf = fimc_cap_qbuf, + .vidioc_dqbuf = fimc_cap_dqbuf, + ++ .vidioc_prepare_buf = fimc_cap_prepare_buf, ++ .vidioc_create_bufs = fimc_cap_create_bufs, ++ + .vidioc_streamon = fimc_cap_streamon, + .vidioc_streamoff = fimc_cap_streamoff, + +- .vidioc_g_crop = fimc_cap_g_crop, +- .vidioc_s_crop = fimc_cap_s_crop, +- .vidioc_cropcap = fimc_cap_cropcap, ++ .vidioc_g_selection = fimc_cap_g_selection, ++ .vidioc_s_selection = fimc_cap_s_selection, + + .vidioc_enum_input = fimc_cap_enum_input, + .vidioc_s_input = fimc_cap_s_input, +Index: linux-3.3.x86_64/drivers/media/video/videobuf2-vmalloc.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/videobuf2-vmalloc.c ++++ linux-3.3.x86_64/drivers/media/video/videobuf2-vmalloc.c +@@ -10,6 +10,7 @@ + * the Free Software Foundation. + */ + ++#include + #include + #include + #include +@@ -22,6 +23,7 @@ + struct vb2_vmalloc_buf { + void *vaddr; + struct page **pages; ++ struct vm_area_struct *vma; + int write; + unsigned long size; + unsigned int n_pages; +@@ -71,6 +73,8 @@ static void *vb2_vmalloc_get_userptr(voi + struct vb2_vmalloc_buf *buf; + unsigned long first, last; + int n_pages, offset; ++ struct vm_area_struct *vma; ++ dma_addr_t physp; + + buf = kzalloc(sizeof(*buf), GFP_KERNEL); + if (!buf) +@@ -80,23 +84,37 @@ static void *vb2_vmalloc_get_userptr(voi + offset = vaddr & ~PAGE_MASK; + buf->size = size; + +- first = vaddr >> PAGE_SHIFT; +- last = (vaddr + size - 1) >> PAGE_SHIFT; +- buf->n_pages = last - first + 1; +- buf->pages = kzalloc(buf->n_pages * sizeof(struct page *), GFP_KERNEL); +- if (!buf->pages) +- goto fail_pages_array_alloc; +- +- /* current->mm->mmap_sem is taken by videobuf2 core */ +- n_pages = get_user_pages(current, current->mm, vaddr & PAGE_MASK, +- buf->n_pages, write, 1, /* force */ +- buf->pages, NULL); +- if (n_pages != buf->n_pages) +- goto fail_get_user_pages; +- +- buf->vaddr = vm_map_ram(buf->pages, buf->n_pages, -1, PAGE_KERNEL); +- if (!buf->vaddr) +- goto fail_get_user_pages; ++ ++ vma = find_vma(current->mm, vaddr); ++ if (vma && (vma->vm_flags & VM_PFNMAP) && (vma->vm_pgoff)) { ++ if (vb2_get_contig_userptr(vaddr, size, &vma, &physp)) ++ goto fail_pages_array_alloc; ++ buf->vma = vma; ++ buf->vaddr = ioremap_nocache(physp, size); ++ if (!buf->vaddr) ++ goto fail_pages_array_alloc; ++ } else { ++ first = vaddr >> PAGE_SHIFT; ++ last = (vaddr + size - 1) >> PAGE_SHIFT; ++ buf->n_pages = last - first + 1; ++ buf->pages = kzalloc(buf->n_pages * sizeof(struct page *), ++ GFP_KERNEL); ++ if (!buf->pages) ++ goto fail_pages_array_alloc; ++ ++ /* current->mm->mmap_sem is taken by videobuf2 core */ ++ n_pages = get_user_pages(current, current->mm, ++ vaddr & PAGE_MASK, buf->n_pages, ++ write, 1, /* force */ ++ buf->pages, NULL); ++ if (n_pages != buf->n_pages) ++ goto fail_get_user_pages; ++ ++ buf->vaddr = vm_map_ram(buf->pages, buf->n_pages, -1, ++ PAGE_KERNEL); ++ if (!buf->vaddr) ++ goto fail_get_user_pages; ++ } + + buf->vaddr += offset; + return buf; +@@ -120,14 +138,20 @@ static void vb2_vmalloc_put_userptr(void + unsigned long vaddr = (unsigned long)buf->vaddr & PAGE_MASK; + unsigned int i; + +- if (vaddr) +- vm_unmap_ram((void *)vaddr, buf->n_pages); +- for (i = 0; i < buf->n_pages; ++i) { +- if (buf->write) +- set_page_dirty_lock(buf->pages[i]); +- put_page(buf->pages[i]); ++ if (buf->pages) { ++ if (vaddr) ++ vm_unmap_ram((void *)vaddr, buf->n_pages); ++ for (i = 0; i < buf->n_pages; ++i) { ++ if (buf->write) ++ set_page_dirty_lock(buf->pages[i]); ++ put_page(buf->pages[i]); ++ } ++ kfree(buf->pages); ++ } else { ++ if (buf->vma) ++ vb2_put_vma(buf->vma); ++ iounmap(buf->vaddr); + } +- kfree(buf->pages); + kfree(buf); + } + +Index: linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-g2d/g2d.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d.c +@@ -178,6 +178,9 @@ static int g2d_s_ctrl(struct v4l2_ctrl * + { + struct g2d_ctx *ctx = container_of(ctrl->handler, struct g2d_ctx, + ctrl_handler); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ctx->dev->ctrl_lock, flags); + switch (ctrl->id) { + case V4L2_CID_COLORFX: + if (ctrl->val == V4L2_COLORFX_NEGATIVE) +@@ -185,10 +188,13 @@ static int g2d_s_ctrl(struct v4l2_ctrl * + else + ctx->rop = ROP4_COPY; + break; +- default: +- v4l2_err(&ctx->dev->v4l2_dev, "unknown control\n"); +- return -EINVAL; ++ ++ case V4L2_CID_HFLIP: ++ ctx->flip = ctx->ctrl_hflip->val | (ctx->ctrl_vflip->val << 1); ++ break; ++ + } ++ spin_unlock_irqrestore(&ctx->dev->ctrl_lock, flags); + return 0; + } + +@@ -200,11 +206,13 @@ int g2d_setup_ctrls(struct g2d_ctx *ctx) + { + struct g2d_dev *dev = ctx->dev; + +- v4l2_ctrl_handler_init(&ctx->ctrl_handler, 1); +- if (ctx->ctrl_handler.error) { +- v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n"); +- return ctx->ctrl_handler.error; +- } ++ v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3); ++ ++ ctx->ctrl_hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &g2d_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ ++ ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &g2d_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); + + v4l2_ctrl_new_std_menu( + &ctx->ctrl_handler, +@@ -215,10 +223,14 @@ int g2d_setup_ctrls(struct g2d_ctx *ctx) + V4L2_COLORFX_NONE); + + if (ctx->ctrl_handler.error) { +- v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n"); +- return ctx->ctrl_handler.error; ++ int err = ctx->ctrl_handler.error; ++ v4l2_err(&dev->v4l2_dev, "g2d_setup_ctrls failed\n"); ++ v4l2_ctrl_handler_free(&ctx->ctrl_handler); ++ return err; + } + ++ v4l2_ctrl_cluster(2, &ctx->ctrl_hflip); ++ + return 0; + } + +@@ -547,6 +559,7 @@ static void device_run(void *prv) + struct g2d_ctx *ctx = prv; + struct g2d_dev *dev = ctx->dev; + struct vb2_buffer *src, *dst; ++ unsigned long flags; + u32 cmd = 0; + + dev->curr = ctx; +@@ -557,6 +570,8 @@ static void device_run(void *prv) + clk_enable(dev->gate); + g2d_reset(dev); + ++ spin_lock_irqsave(&dev->ctrl_lock, flags); ++ + g2d_set_src_size(dev, &ctx->in); + g2d_set_src_addr(dev, vb2_dma_contig_plane_dma_addr(src, 0)); + +@@ -564,11 +579,15 @@ static void device_run(void *prv) + g2d_set_dst_addr(dev, vb2_dma_contig_plane_dma_addr(dst, 0)); + + g2d_set_rop4(dev, ctx->rop); ++ g2d_set_flip(dev, ctx->flip); ++ + if (ctx->in.c_width != ctx->out.c_width || + ctx->in.c_height != ctx->out.c_height) + cmd |= g2d_cmd_stretch(1); + g2d_set_cmd(dev, cmd); + g2d_start(dev); ++ ++ spin_unlock_irqrestore(&dev->ctrl_lock, flags); + } + + static irqreturn_t g2d_isr(int irq, void *prv) +@@ -658,7 +677,7 @@ static int g2d_probe(struct platform_dev + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; +- spin_lock_init(&dev->irqlock); ++ spin_lock_init(&dev->ctrl_lock); + mutex_init(&dev->mutex); + atomic_set(&dev->num_inst, 0); + init_waitqueue_head(&dev->irq_queue); +@@ -693,18 +712,30 @@ static int g2d_probe(struct platform_dev + goto unmap_regs; + } + ++ ret = clk_prepare(dev->clk); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to prepare g2d clock\n"); ++ goto put_clk; ++ } ++ + dev->gate = clk_get(&pdev->dev, "fimg2d"); + if (IS_ERR_OR_NULL(dev->gate)) { + dev_err(&pdev->dev, "failed to get g2d clock gate\n"); + ret = -ENXIO; +- goto put_clk; ++ goto unprep_clk; ++ } ++ ++ ret = clk_prepare(dev->gate); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to prepare g2d clock gate\n"); ++ goto put_clk_gate; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(&pdev->dev, "failed to find IRQ\n"); + ret = -ENXIO; +- goto put_clk_gate; ++ goto unprep_clk_gate; + } + + dev->irq = res->start; +@@ -764,8 +795,12 @@ alloc_ctx_cleanup: + vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); + rel_irq: + free_irq(dev->irq, dev); ++unprep_clk_gate: ++ clk_unprepare(dev->gate); + put_clk_gate: + clk_put(dev->gate); ++unprep_clk: ++ clk_unprepare(dev->clk); + put_clk: + clk_put(dev->clk); + unmap_regs: +@@ -787,7 +822,9 @@ static int g2d_remove(struct platform_de + v4l2_device_unregister(&dev->v4l2_dev); + vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); + free_irq(dev->irq, dev); ++ clk_unprepare(dev->gate); + clk_put(dev->gate); ++ clk_unprepare(dev->clk); + clk_put(dev->clk); + iounmap(dev->regs); + release_resource(dev->res_regs); +Index: linux-3.3.x86_64/drivers/media/video/s5p-mfc/s5p_mfc_pm.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-mfc/s5p_mfc_pm.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-mfc/s5p_mfc_pm.c +@@ -41,15 +41,29 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev * + pm->clock_gate = clk_get(&dev->plat_dev->dev, MFC_GATE_CLK_NAME); + if (IS_ERR(pm->clock_gate)) { + mfc_err("Failed to get clock-gating control\n"); +- ret = -ENOENT; ++ ret = PTR_ERR(pm->clock_gate); + goto err_g_ip_clk; + } ++ ++ ret = clk_prepare(pm->clock_gate); ++ if (ret) { ++ mfc_err("Failed to preapre clock-gating control\n"); ++ goto err_p_ip_clk; ++ } ++ + pm->clock = clk_get(&dev->plat_dev->dev, MFC_CLKNAME); + if (IS_ERR(pm->clock)) { + mfc_err("Failed to get MFC clock\n"); +- ret = -ENOENT; ++ ret = PTR_ERR(pm->clock); + goto err_g_ip_clk_2; + } ++ ++ ret = clk_prepare(pm->clock); ++ if (ret) { ++ mfc_err("Failed to prepare MFC clock\n"); ++ goto err_p_ip_clk_2; ++ } ++ + atomic_set(&pm->power, 0); + #ifdef CONFIG_PM_RUNTIME + pm->device = &dev->plat_dev->dev; +@@ -59,7 +73,11 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev * + atomic_set(&clk_ref, 0); + #endif + return 0; ++err_p_ip_clk_2: ++ clk_put(pm->clock); + err_g_ip_clk_2: ++ clk_unprepare(pm->clock_gate); ++err_p_ip_clk: + clk_put(pm->clock_gate); + err_g_ip_clk: + return ret; +@@ -67,7 +85,9 @@ err_g_ip_clk: + + void s5p_mfc_final_pm(struct s5p_mfc_dev *dev) + { ++ clk_unprepare(pm->clock_gate); + clk_put(pm->clock_gate); ++ clk_unprepare(pm->clock); + clk_put(pm->clock); + #ifdef CONFIG_PM_RUNTIME + pm_runtime_disable(pm->device); +Index: linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d-hw.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-g2d/g2d-hw.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d-hw.c +@@ -77,6 +77,11 @@ void g2d_set_rop4(struct g2d_dev *d, u32 + w(r, ROP4_REG); + } + ++void g2d_set_flip(struct g2d_dev *d, u32 r) ++{ ++ w(r, SRC_MSK_DIRECT_REG); ++} ++ + u32 g2d_cmd_stretch(u32 e) + { + e &= 1; +Index: linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-g2d/g2d.h ++++ linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d.h +@@ -20,7 +20,7 @@ struct g2d_dev { + struct v4l2_m2m_dev *m2m_dev; + struct video_device *vfd; + struct mutex mutex; +- spinlock_t irqlock; ++ spinlock_t ctrl_lock; + atomic_t num_inst; + struct vb2_alloc_ctx *alloc_ctx; + struct resource *res_regs; +@@ -57,8 +57,11 @@ struct g2d_ctx { + struct v4l2_m2m_ctx *m2m_ctx; + struct g2d_frame in; + struct g2d_frame out; ++ struct v4l2_ctrl *ctrl_hflip; ++ struct v4l2_ctrl *ctrl_vflip; + struct v4l2_ctrl_handler ctrl_handler; + u32 rop; ++ u32 flip; + }; + + struct g2d_fmt { +@@ -77,6 +80,7 @@ void g2d_set_dst_addr(struct g2d_dev *d, + void g2d_start(struct g2d_dev *d); + void g2d_clear_int(struct g2d_dev *d); + void g2d_set_rop4(struct g2d_dev *d, u32 r); ++void g2d_set_flip(struct g2d_dev *d, u32 r); + u32 g2d_cmd_stretch(u32 e); + void g2d_set_cmd(struct g2d_dev *d, u32 c); + +Index: linux-3.3.x86_64/drivers/media/video/s5k6aa.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5k6aa.c ++++ linux-3.3.x86_64/drivers/media/video/s5k6aa.c +@@ -1582,8 +1582,8 @@ static int s5k6aa_probe(struct i2c_clien + s5k6aa->inv_vflip = pdata->vert_flip; + + sd = &s5k6aa->sd; +- strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name)); + v4l2_i2c_subdev_init(sd, client, &s5k6aa_subdev_ops); ++ strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name)); + + sd->internal_ops = &s5k6aa_subdev_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; +@@ -1663,18 +1663,7 @@ static struct i2c_driver s5k6aa_i2c_driv + .id_table = s5k6aa_id, + }; + +-static int __init s5k6aa_init(void) +-{ +- return i2c_add_driver(&s5k6aa_i2c_driver); +-} +- +-static void __exit s5k6aa_exit(void) +-{ +- i2c_del_driver(&s5k6aa_i2c_driver); +-} +- +-module_init(s5k6aa_init); +-module_exit(s5k6aa_exit); ++module_i2c_driver(s5k6aa_i2c_driver); + + MODULE_DESCRIPTION("Samsung S5K6AA(FX) SXGA camera driver"); + MODULE_AUTHOR("Sylwester Nawrocki "); +Index: linux-3.3.x86_64/drivers/media/video/noon010pc30.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/noon010pc30.c ++++ linux-3.3.x86_64/drivers/media/video/noon010pc30.c +@@ -725,8 +725,8 @@ static int noon010_probe(struct i2c_clie + + mutex_init(&info->lock); + sd = &info->sd; +- strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); + v4l2_i2c_subdev_init(sd, client, &noon010_ops); ++ strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); + + sd->internal_ops = &noon010_subdev_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; +@@ -844,18 +844,7 @@ static struct i2c_driver noon010_i2c_dri + .id_table = noon010_id, + }; + +-static int __init noon010_init(void) +-{ +- return i2c_add_driver(&noon010_i2c_driver); +-} +- +-static void __exit noon010_exit(void) +-{ +- i2c_del_driver(&noon010_i2c_driver); +-} +- +-module_init(noon010_init); +-module_exit(noon010_exit); ++module_i2c_driver(noon010_i2c_driver); + + MODULE_DESCRIPTION("Siliconfile NOON010PC30 camera driver"); + MODULE_AUTHOR("Sylwester Nawrocki "); +Index: linux-3.3.x86_64/drivers/media/video/m5mols/m5mols_core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/m5mols/m5mols_core.c ++++ linux-3.3.x86_64/drivers/media/video/m5mols/m5mols_core.c +@@ -982,8 +982,8 @@ static int __devinit m5mols_probe(struct + } + + sd = &info->sd; +- strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); + v4l2_i2c_subdev_init(sd, client, &m5mols_ops); ++ strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + sd->internal_ops = &m5mols_subdev_internal_ops; +@@ -1057,18 +1057,7 @@ static struct i2c_driver m5mols_i2c_driv + .id_table = m5mols_id, + }; + +-static int __init m5mols_mod_init(void) +-{ +- return i2c_add_driver(&m5mols_i2c_driver); +-} +- +-static void __exit m5mols_mod_exit(void) +-{ +- i2c_del_driver(&m5mols_i2c_driver); +-} +- +-module_init(m5mols_mod_init); +-module_exit(m5mols_mod_exit); ++module_i2c_driver(m5mols_i2c_driver); + + MODULE_AUTHOR("HeungJun Kim "); + MODULE_AUTHOR("Dongsoo Kim "); +Index: linux-3.3.x86_64/Documentation/video4linux/gspca.txt +=================================================================== +--- linux-3.3.x86_64.orig/Documentation/video4linux/gspca.txt ++++ linux-3.3.x86_64/Documentation/video4linux/gspca.txt +@@ -217,6 +217,7 @@ ov534_9 06f8:3003 Hercules Dualpix HD W + sonixj 06f8:3004 Hercules Classic Silver + sonixj 06f8:3008 Hercules Deluxe Optical Glass + pac7302 06f8:3009 Hercules Classic Link ++pac7302 06f8:301b Hercules Link + nw80x 0728:d001 AVerMedia Camguard + spca508 0733:0110 ViewQuest VQ110 + spca501 0733:0401 Intel Create and Share +Index: linux-3.3.x86_64/drivers/media/video/gspca/pac7302.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/gspca/pac7302.c ++++ linux-3.3.x86_64/drivers/media/video/gspca/pac7302.c +@@ -1,8 +1,8 @@ + /* +- * Pixart PAC7302 library +- * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li ++ * Pixart PAC7302 driver + * +- * V4L2 by Jean-Francois Moine ++ * Copyright (C) 2008-2012 Jean-Francois Moine ++ * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li + * + * Separated from Pixart PAC7311 library by Márton Németh + * Camera button input handling by Márton Németh +@@ -63,67 +63,61 @@ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +-#define MODULE_NAME "pac7302" +- + #include + #include + #include "gspca.h" ++/* Include pac common sof detection functions */ ++#include "pac_common.h" + +-MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); ++MODULE_AUTHOR("Jean-Francois Moine , " ++ "Thomas Kaiser thomas@kaiser-linux.li"); + MODULE_DESCRIPTION("Pixart PAC7302"); + MODULE_LICENSE("GPL"); + ++enum e_ctrl { ++ BRIGHTNESS, ++ CONTRAST, ++ COLORS, ++ WHITE_BALANCE, ++ RED_BALANCE, ++ BLUE_BALANCE, ++ GAIN, ++ AUTOGAIN, ++ EXPOSURE, ++ VFLIP, ++ HFLIP, ++ NCTRLS /* number of controls */ ++}; ++ + /* specific webcam descriptor for pac7302 */ + struct sd { + struct gspca_dev gspca_dev; /* !! must be the first item */ + +- unsigned char brightness; +- unsigned char contrast; +- unsigned char colors; +- unsigned char white_balance; +- unsigned char red_balance; +- unsigned char blue_balance; +- unsigned char gain; +- unsigned char autogain; +- unsigned short exposure; +- __u8 hflip; +- __u8 vflip; ++ struct gspca_ctrl ctrls[NCTRLS]; ++ + u8 flags; + #define FL_HFLIP 0x01 /* mirrored by default */ + #define FL_VFLIP 0x02 /* vertical flipped by default */ + + u8 sof_read; +- u8 autogain_ignore_frames; ++ s8 autogain_ignore_frames; + + atomic_t avg_lum; + }; + + /* V4L2 controls supported by the driver */ +-static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); +-static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); +-static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); ++static void setbrightcont(struct gspca_dev *gspca_dev); ++static void setcolors(struct gspca_dev *gspca_dev); ++static void setwhitebalance(struct gspca_dev *gspca_dev); ++static void setredbalance(struct gspca_dev *gspca_dev); ++static void setbluebalance(struct gspca_dev *gspca_dev); ++static void setgain(struct gspca_dev *gspca_dev); ++static void setexposure(struct gspca_dev *gspca_dev); ++static void setautogain(struct gspca_dev *gspca_dev); ++static void sethvflip(struct gspca_dev *gspca_dev); + + static const struct ctrl sd_ctrls[] = { +- { ++[BRIGHTNESS] = { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, +@@ -132,13 +126,11 @@ static const struct ctrl sd_ctrls[] = { + #define BRIGHTNESS_MAX 0x20 + .maximum = BRIGHTNESS_MAX, + .step = 1, +-#define BRIGHTNESS_DEF 0x10 +- .default_value = BRIGHTNESS_DEF, ++ .default_value = 0x10, + }, +- .set = sd_setbrightness, +- .get = sd_getbrightness, ++ .set_control = setbrightcont + }, +- { ++[CONTRAST] = { + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, +@@ -147,13 +139,11 @@ static const struct ctrl sd_ctrls[] = { + #define CONTRAST_MAX 255 + .maximum = CONTRAST_MAX, + .step = 1, +-#define CONTRAST_DEF 127 +- .default_value = CONTRAST_DEF, ++ .default_value = 127, + }, +- .set = sd_setcontrast, +- .get = sd_getcontrast, ++ .set_control = setbrightcont + }, +- { ++[COLORS] = { + { + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, +@@ -162,13 +152,11 @@ static const struct ctrl sd_ctrls[] = { + #define COLOR_MAX 255 + .maximum = COLOR_MAX, + .step = 1, +-#define COLOR_DEF 127 +- .default_value = COLOR_DEF, ++ .default_value = 127 + }, +- .set = sd_setcolors, +- .get = sd_getcolors, ++ .set_control = setcolors + }, +- { ++[WHITE_BALANCE] = { + { + .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE, + .type = V4L2_CTRL_TYPE_INTEGER, +@@ -176,13 +164,11 @@ static const struct ctrl sd_ctrls[] = { + .minimum = 0, + .maximum = 255, + .step = 1, +-#define WHITEBALANCE_DEF 4 +- .default_value = WHITEBALANCE_DEF, ++ .default_value = 4, + }, +- .set = sd_setwhitebalance, +- .get = sd_getwhitebalance, ++ .set_control = setwhitebalance + }, +- { ++[RED_BALANCE] = { + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, +@@ -190,13 +176,11 @@ static const struct ctrl sd_ctrls[] = { + .minimum = 0, + .maximum = 3, + .step = 1, +-#define REDBALANCE_DEF 1 +- .default_value = REDBALANCE_DEF, ++ .default_value = 1, + }, +- .set = sd_setredbalance, +- .get = sd_getredbalance, ++ .set_control = setredbalance + }, +- { ++[BLUE_BALANCE] = { + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, +@@ -204,29 +188,25 @@ static const struct ctrl sd_ctrls[] = { + .minimum = 0, + .maximum = 3, + .step = 1, +-#define BLUEBALANCE_DEF 1 +- .default_value = BLUEBALANCE_DEF, ++ .default_value = 1, + }, +- .set = sd_setbluebalance, +- .get = sd_getbluebalance, ++ .set_control = setbluebalance + }, +- { ++[GAIN] = { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, +-#define GAIN_MAX 255 +- .maximum = GAIN_MAX, ++ .maximum = 255, + .step = 1, + #define GAIN_DEF 127 + #define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */ + .default_value = GAIN_DEF, + }, +- .set = sd_setgain, +- .get = sd_getgain, ++ .set_control = setgain + }, +- { ++[EXPOSURE] = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, +@@ -238,10 +218,9 @@ static const struct ctrl sd_ctrls[] = { + #define EXPOSURE_KNEE 133 /* 66 ms / 15 fps */ + .default_value = EXPOSURE_DEF, + }, +- .set = sd_setexposure, +- .get = sd_getexposure, ++ .set_control = setexposure + }, +- { ++[AUTOGAIN] = { + { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, +@@ -252,10 +231,9 @@ static const struct ctrl sd_ctrls[] = { + #define AUTOGAIN_DEF 1 + .default_value = AUTOGAIN_DEF, + }, +- .set = sd_setautogain, +- .get = sd_getautogain, ++ .set_control = setautogain, + }, +- { ++[HFLIP] = { + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, +@@ -263,13 +241,11 @@ static const struct ctrl sd_ctrls[] = { + .minimum = 0, + .maximum = 1, + .step = 1, +-#define HFLIP_DEF 0 +- .default_value = HFLIP_DEF, ++ .default_value = 0, + }, +- .set = sd_sethflip, +- .get = sd_gethflip, ++ .set_control = sethvflip, + }, +- { ++[VFLIP] = { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, +@@ -277,11 +253,9 @@ static const struct ctrl sd_ctrls[] = { + .minimum = 0, + .maximum = 1, + .step = 1, +-#define VFLIP_DEF 0 +- .default_value = VFLIP_DEF, ++ .default_value = 0, + }, +- .set = sd_setvflip, +- .get = sd_getvflip, ++ .set_control = sethvflip + }, + }; + +@@ -290,21 +264,21 @@ static const struct v4l2_pix_format vga_ + .bytesperline = 640, + .sizeimage = 640 * 480 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, +- .priv = 0}, ++ }, + }; + + #define LOAD_PAGE3 255 + #define END_OF_SEQUENCE 0 + + /* pac 7302 */ +-static const __u8 init_7302[] = { ++static const u8 init_7302[] = { + /* index,value */ + 0xff, 0x01, /* page 1 */ + 0x78, 0x00, /* deactivate */ + 0xff, 0x01, + 0x78, 0x40, /* led off */ + }; +-static const __u8 start_7302[] = { ++static const u8 start_7302[] = { + /* index, len, [value]* */ + 0xff, 1, 0x00, /* page 0 */ + 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80, +@@ -319,7 +293,7 @@ static const __u8 start_7302[] = { + 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11, + 0x00, 0x54, 0x11, + 0x55, 1, 0x00, +- 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, ++ 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, + 0x6b, 1, 0x00, + 0x6e, 3, 0x08, 0x06, 0x00, + 0x72, 3, 0x00, 0xff, 0x00, +@@ -370,7 +344,7 @@ static const __u8 start_7302[] = { + + #define SKIP 0xaa + /* page 3 - the value SKIP says skip the index - see reg_w_page() */ +-static const __u8 page3_7302[] = { ++static const u8 page3_7302[] = { + 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16, + 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, + 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +@@ -394,7 +368,7 @@ static const __u8 page3_7302[] = { + }; + + static void reg_w_buf(struct gspca_dev *gspca_dev, +- __u8 index, ++ u8 index, + const u8 *buffer, int len) + { + int ret; +@@ -410,7 +384,7 @@ static void reg_w_buf(struct gspca_dev * + index, gspca_dev->usb_buf, len, + 500); + if (ret < 0) { +- pr_err("reg_w_buf failed index 0x%02x, error %d\n", ++ pr_err("reg_w_buf failed i: %02x error %d\n", + index, ret); + gspca_dev->usb_err = ret; + } +@@ -418,8 +392,8 @@ static void reg_w_buf(struct gspca_dev * + + + static void reg_w(struct gspca_dev *gspca_dev, +- __u8 index, +- __u8 value) ++ u8 index, ++ u8 value) + { + int ret; + +@@ -433,14 +407,14 @@ static void reg_w(struct gspca_dev *gspc + 0, index, gspca_dev->usb_buf, 1, + 500); + if (ret < 0) { +- pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n", ++ pr_err("reg_w() failed i: %02x v: %02x error %d\n", + index, value, ret); + gspca_dev->usb_err = ret; + } + } + + static void reg_w_seq(struct gspca_dev *gspca_dev, +- const __u8 *seq, int len) ++ const u8 *seq, int len) + { + while (--len >= 0) { + reg_w(gspca_dev, seq[0], seq[1]); +@@ -450,7 +424,7 @@ static void reg_w_seq(struct gspca_dev * + + /* load the beginning of a page */ + static void reg_w_page(struct gspca_dev *gspca_dev, +- const __u8 *page, int len) ++ const u8 *page, int len) + { + int index; + int ret = 0; +@@ -468,7 +442,7 @@ static void reg_w_page(struct gspca_dev + 0, index, gspca_dev->usb_buf, 1, + 500); + if (ret < 0) { +- pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n", ++ pr_err("reg_w_page() failed i: %02x v: %02x error %d\n", + index, page[index], ret); + gspca_dev->usb_err = ret; + break; +@@ -478,8 +452,8 @@ static void reg_w_page(struct gspca_dev + + /* output a variable sequence */ + static void reg_w_var(struct gspca_dev *gspca_dev, +- const __u8 *seq, +- const __u8 *page3, unsigned int page3_len) ++ const u8 *seq, ++ const u8 *page3, unsigned int page3_len) + { + int index, len; + +@@ -493,11 +467,13 @@ static void reg_w_var(struct gspca_dev * + reg_w_page(gspca_dev, page3, page3_len); + break; + default: ++#ifdef GSPCA_DEBUG + if (len > USB_BUF_SZ) { + PDEBUG(D_ERR|D_STREAM, + "Incorrect variable sequence"); + return; + } ++#endif + while (len > 0) { + if (len < 8) { + reg_w_buf(gspca_dev, +@@ -524,21 +500,11 @@ static int sd_config(struct gspca_dev *g + + cam = &gspca_dev->cam; + +- PDEBUG(D_CONF, "Find Sensor PAC7302"); + cam->cam_mode = vga_mode; /* only 640x480 */ + cam->nmodes = ARRAY_SIZE(vga_mode); + +- sd->brightness = BRIGHTNESS_DEF; +- sd->contrast = CONTRAST_DEF; +- sd->colors = COLOR_DEF; +- sd->white_balance = WHITEBALANCE_DEF; +- sd->red_balance = REDBALANCE_DEF; +- sd->blue_balance = BLUEBALANCE_DEF; +- sd->gain = GAIN_DEF; +- sd->exposure = EXPOSURE_DEF; +- sd->autogain = AUTOGAIN_DEF; +- sd->hflip = HFLIP_DEF; +- sd->vflip = VFLIP_DEF; ++ gspca_dev->cam.ctrls = sd->ctrls; ++ + sd->flags = id->driver_info; + return 0; + } +@@ -548,19 +514,19 @@ static void setbrightcont(struct gspca_d + { + struct sd *sd = (struct sd *) gspca_dev; + int i, v; +- static const __u8 max[10] = ++ static const u8 max[10] = + {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, + 0xd4, 0xec}; +- static const __u8 delta[10] = ++ static const u8 delta[10] = + {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, + 0x11, 0x0b}; + + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + for (i = 0; i < 10; i++) { + v = max[i]; +- v += (sd->brightness - BRIGHTNESS_MAX) ++ v += (sd->ctrls[BRIGHTNESS].val - BRIGHTNESS_MAX) + * 150 / BRIGHTNESS_MAX; /* 200 ? */ +- v -= delta[i] * sd->contrast / CONTRAST_MAX; ++ v -= delta[i] * sd->ctrls[CONTRAST].val / CONTRAST_MAX; + if (v < 0) + v = 0; + else if (v > 0xff) +@@ -584,12 +550,11 @@ static void setcolors(struct gspca_dev * + reg_w(gspca_dev, 0x11, 0x01); + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + for (i = 0; i < 9; i++) { +- v = a[i] * sd->colors / COLOR_MAX + b[i]; ++ v = a[i] * sd->ctrls[COLORS].val / COLOR_MAX + b[i]; + reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); + reg_w(gspca_dev, 0x0f + 2 * i + 1, v); + } + reg_w(gspca_dev, 0xdc, 0x01); +- PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); + } + + static void setwhitebalance(struct gspca_dev *gspca_dev) +@@ -597,10 +562,9 @@ static void setwhitebalance(struct gspca + struct sd *sd = (struct sd *) gspca_dev; + + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ +- reg_w(gspca_dev, 0xc6, sd->white_balance); ++ reg_w(gspca_dev, 0xc6, sd->ctrls[WHITE_BALANCE].val); + + reg_w(gspca_dev, 0xdc, 0x01); +- PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance); + } + + static void setredbalance(struct gspca_dev *gspca_dev) +@@ -608,10 +572,9 @@ static void setredbalance(struct gspca_d + struct sd *sd = (struct sd *) gspca_dev; + + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ +- reg_w(gspca_dev, 0xc5, sd->red_balance); ++ reg_w(gspca_dev, 0xc5, sd->ctrls[RED_BALANCE].val); + + reg_w(gspca_dev, 0xdc, 0x01); +- PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance); + } + + static void setbluebalance(struct gspca_dev *gspca_dev) +@@ -619,10 +582,9 @@ static void setbluebalance(struct gspca_ + struct sd *sd = (struct sd *) gspca_dev; + + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ +- reg_w(gspca_dev, 0xc7, sd->blue_balance); ++ reg_w(gspca_dev, 0xc7, sd->ctrls[BLUE_BALANCE].val); + + reg_w(gspca_dev, 0xdc, 0x01); +- PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance); + } + + static void setgain(struct gspca_dev *gspca_dev) +@@ -630,7 +592,7 @@ static void setgain(struct gspca_dev *gs + struct sd *sd = (struct sd *) gspca_dev; + + reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ +- reg_w(gspca_dev, 0x10, sd->gain >> 3); ++ reg_w(gspca_dev, 0x10, sd->ctrls[GAIN].val >> 3); + + /* load registers to sensor (Bit 0, auto clear) */ + reg_w(gspca_dev, 0x11, 0x01); +@@ -639,13 +601,13 @@ static void setgain(struct gspca_dev *gs + static void setexposure(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- __u8 clockdiv; +- __u16 exposure; ++ u8 clockdiv; ++ u16 exposure; + + /* register 2 of frame 3 contains the clock divider configuring the + no fps according to the formula: 90 / reg. sd->exposure is the + desired exposure time in 0.5 ms. */ +- clockdiv = (90 * sd->exposure + 1999) / 2000; ++ clockdiv = (90 * sd->ctrls[EXPOSURE].val + 1999) / 2000; + + /* Note clockdiv = 3 also works, but when running at 30 fps, depending + on the scene being recorded, the camera switches to another +@@ -664,7 +626,7 @@ static void setexposure(struct gspca_dev + + /* frame exposure time in ms = 1000 * clockdiv / 90 -> + exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */ +- exposure = (sd->exposure * 45 * 448) / (1000 * clockdiv); ++ exposure = (sd->ctrls[EXPOSURE].val * 45 * 448) / (1000 * clockdiv); + /* 0 = use full frametime, 448 = no exposure, reverse it */ + exposure = 448 - exposure; + +@@ -677,15 +639,35 @@ static void setexposure(struct gspca_dev + reg_w(gspca_dev, 0x11, 0x01); + } + ++static void setautogain(struct gspca_dev *gspca_dev) ++{ ++ struct sd *sd = (struct sd *) gspca_dev; ++ ++ /* when switching to autogain set defaults to make sure ++ we are on a valid point of the autogain gain / ++ exposure knee graph, and give this change time to ++ take effect before doing autogain. */ ++ if (sd->ctrls[AUTOGAIN].val) { ++ sd->ctrls[EXPOSURE].val = EXPOSURE_DEF; ++ sd->ctrls[GAIN].val = GAIN_DEF; ++ sd->autogain_ignore_frames = ++ PAC_AUTOGAIN_IGNORE_FRAMES; ++ } else { ++ sd->autogain_ignore_frames = -1; ++ } ++ setexposure(gspca_dev); ++ setgain(gspca_dev); ++} ++ + static void sethvflip(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; + u8 data, hflip, vflip; + +- hflip = sd->hflip; ++ hflip = sd->ctrls[HFLIP].val; + if (sd->flags & FL_HFLIP) + hflip = !hflip; +- vflip = sd->vflip; ++ vflip = sd->ctrls[VFLIP].val; + if (sd->flags & FL_VFLIP) + vflip = !vflip; + +@@ -708,8 +690,6 @@ static int sd_start(struct gspca_dev *gs + { + struct sd *sd = (struct sd *) gspca_dev; + +- sd->sof_read = 0; +- + reg_w_var(gspca_dev, start_7302, + page3_7302, sizeof(page3_7302)); + setbrightcont(gspca_dev); +@@ -717,15 +697,13 @@ static int sd_start(struct gspca_dev *gs + setwhitebalance(gspca_dev); + setredbalance(gspca_dev); + setbluebalance(gspca_dev); +- setgain(gspca_dev); +- setexposure(gspca_dev); ++ setautogain(gspca_dev); + sethvflip(gspca_dev); + + /* only resolution 640x480 is supported for pac7302 */ + + sd->sof_read = 0; +- sd->autogain_ignore_frames = 0; +- atomic_set(&sd->avg_lum, -1); ++ atomic_set(&sd->avg_lum, 270 + sd->ctrls[BRIGHTNESS].val); + + /* start stream */ + reg_w(gspca_dev, 0xff, 0x01); +@@ -751,8 +729,10 @@ static void sd_stop0(struct gspca_dev *g + reg_w(gspca_dev, 0x78, 0x40); + } + +-/* Include pac common sof detection functions */ +-#include "pac_common.h" ++/* !! coarse_grained_expo_autogain is not used !! */ ++#define exp_too_low_cnt flags ++#define exp_too_high_cnt sof_read ++#include "autogain_functions.h" + + static void do_autogain(struct gspca_dev *gspca_dev) + { +@@ -761,65 +741,44 @@ static void do_autogain(struct gspca_dev + int desired_lum; + const int deadzone = 30; + +- if (avg_lum == -1) ++ if (sd->autogain_ignore_frames < 0) + return; + +- desired_lum = 270 + sd->brightness; +- +- if (sd->autogain_ignore_frames > 0) ++ if (sd->autogain_ignore_frames > 0) { + sd->autogain_ignore_frames--; +- else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum, +- deadzone, GAIN_KNEE, EXPOSURE_KNEE)) ++ } else { ++ desired_lum = 270 + sd->ctrls[BRIGHTNESS].val; ++ ++ auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum, ++ deadzone, GAIN_KNEE, EXPOSURE_KNEE); + sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; ++ } + } + +-/* JPEG header, part 1 */ +-static const unsigned char pac_jpeg_header1[] = { +- 0xff, 0xd8, /* SOI: Start of Image */ +- +- 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ +- 0x00, 0x11, /* length = 17 bytes (including this length field) */ +- 0x08 /* Precision: 8 */ +- /* 2 bytes is placed here: number of image lines */ +- /* 2 bytes is placed here: samples per line */ +-}; +- +-/* JPEG header, continued */ +-static const unsigned char pac_jpeg_header2[] = { +- 0x03, /* Number of image components: 3 */ +- 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ +- 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ +- 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ +- +- 0xff, 0xda, /* SOS: Start Of Scan */ +- 0x00, 0x0c, /* length = 12 bytes (including this length field) */ +- 0x03, /* number of components: 3 */ +- 0x01, 0x00, /* selector 1, table 0x00 */ +- 0x02, 0x11, /* selector 2, table 0x11 */ +- 0x03, 0x11, /* selector 3, table 0x11 */ +- 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ +- 0x00 /* Successive approximation: 0 */ ++/* JPEG header */ ++static const u8 jpeg_header[] = { ++ 0xff, 0xd8, /* SOI: Start of Image */ ++ ++ 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ ++ 0x00, 0x11, /* length = 17 bytes (including this length field) */ ++ 0x08, /* Precision: 8 */ ++ 0x02, 0x80, /* height = 640 (image rotated) */ ++ 0x01, 0xe0, /* width = 480 */ ++ 0x03, /* Number of image components: 3 */ ++ 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ ++ 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ ++ 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ ++ ++ 0xff, 0xda, /* SOS: Start Of Scan */ ++ 0x00, 0x0c, /* length = 12 bytes (including this length field) */ ++ 0x03, /* number of components: 3 */ ++ 0x01, 0x00, /* selector 1, table 0x00 */ ++ 0x02, 0x11, /* selector 2, table 0x11 */ ++ 0x03, 0x11, /* selector 3, table 0x11 */ ++ 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ ++ 0x00 /* Successive approximation: 0 */ + }; + +-static void pac_start_frame(struct gspca_dev *gspca_dev, +- __u16 lines, __u16 samples_per_line) +-{ +- unsigned char tmpbuf[4]; +- +- gspca_frame_add(gspca_dev, FIRST_PACKET, +- pac_jpeg_header1, sizeof(pac_jpeg_header1)); +- +- tmpbuf[0] = lines >> 8; +- tmpbuf[1] = lines & 0xff; +- tmpbuf[2] = samples_per_line >> 8; +- tmpbuf[3] = samples_per_line & 0xff; +- +- gspca_frame_add(gspca_dev, INTER_PACKET, +- tmpbuf, sizeof(tmpbuf)); +- gspca_frame_add(gspca_dev, INTER_PACKET, +- pac_jpeg_header2, sizeof(pac_jpeg_header2)); +-} +- + /* this function is run at interrupt level */ + static void sd_pkt_scan(struct gspca_dev *gspca_dev, + u8 *data, /* isoc packet */ +@@ -827,7 +786,7 @@ static void sd_pkt_scan(struct gspca_dev + { + struct sd *sd = (struct sd *) gspca_dev; + u8 *image; +- unsigned char *sof; ++ u8 *sof; + + sof = pac_find_sof(&sd->sof_read, data, len); + if (sof) { +@@ -864,234 +823,21 @@ static void sd_pkt_scan(struct gspca_dev + n >= lum_offset) + atomic_set(&sd->avg_lum, data[-lum_offset] + + data[-lum_offset + 1]); +- else +- atomic_set(&sd->avg_lum, -1); + + /* Start the new frame with the jpeg header */ + /* The PAC7302 has the image rotated 90 degrees */ +- pac_start_frame(gspca_dev, +- gspca_dev->width, gspca_dev->height); ++ gspca_frame_add(gspca_dev, FIRST_PACKET, ++ jpeg_header, sizeof jpeg_header); + } + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); + } + +-static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->brightness = val; +- if (gspca_dev->streaming) +- setbrightcont(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->brightness; +- return 0; +-} +- +-static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->contrast = val; +- if (gspca_dev->streaming) +- setbrightcont(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->contrast; +- return 0; +-} +- +-static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->colors = val; +- if (gspca_dev->streaming) +- setcolors(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->colors; +- return 0; +-} +- +-static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->white_balance = val; +- if (gspca_dev->streaming) +- setwhitebalance(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->white_balance; +- return 0; +-} +- +-static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->red_balance = val; +- if (gspca_dev->streaming) +- setredbalance(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->red_balance; +- return 0; +-} +- +-static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->blue_balance = val; +- if (gspca_dev->streaming) +- setbluebalance(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->blue_balance; +- return 0; +-} +- +-static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->gain = val; +- if (gspca_dev->streaming) +- setgain(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->gain; +- return 0; +-} +- +-static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->exposure = val; +- if (gspca_dev->streaming) +- setexposure(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->exposure; +- return 0; +-} +- +-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->autogain = val; +- /* when switching to autogain set defaults to make sure +- we are on a valid point of the autogain gain / +- exposure knee graph, and give this change time to +- take effect before doing autogain. */ +- if (sd->autogain) { +- sd->exposure = EXPOSURE_DEF; +- sd->gain = GAIN_DEF; +- if (gspca_dev->streaming) { +- sd->autogain_ignore_frames = +- PAC_AUTOGAIN_IGNORE_FRAMES; +- setexposure(gspca_dev); +- setgain(gspca_dev); +- } +- } +- +- return gspca_dev->usb_err; +-} +- +-static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->autogain; +- return 0; +-} +- +-static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->hflip = val; +- if (gspca_dev->streaming) +- sethvflip(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->hflip; +- return 0; +-} +- +-static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->vflip = val; +- if (gspca_dev->streaming) +- sethvflip(gspca_dev); +- return gspca_dev->usb_err; +-} +- +-static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- *val = sd->vflip; +- return 0; +-} +- + #ifdef CONFIG_VIDEO_ADV_DEBUG + static int sd_dbg_s_register(struct gspca_dev *gspca_dev, + struct v4l2_dbg_register *reg) + { +- __u8 index; +- __u8 value; ++ u8 index; ++ u8 value; + + /* reg->reg: bit0..15: reserved for register index (wIndex is 16bit + long on the USB bus) +@@ -1103,8 +849,8 @@ static int sd_dbg_s_register(struct gspc + ) { + /* Currently writing to page 0 is only supported. */ + /* reg_w() only supports 8bit index */ +- index = reg->reg & 0x000000ff; +- value = reg->val & 0x000000ff; ++ index = reg->reg; ++ value = reg->val; + + /* Note that there shall be no access to other page + by any other function between the page swith and +@@ -1165,7 +911,7 @@ static int sd_int_pkt_scan(struct gspca_ + + /* sub-driver description for pac7302 */ + static const struct sd_desc sd_desc = { +- .name = MODULE_NAME, ++ .name = KBUILD_MODNAME, + .ctrls = sd_ctrls, + .nctrls = ARRAY_SIZE(sd_ctrls), + .config = sd_config, +@@ -1187,6 +933,7 @@ static const struct sd_desc sd_desc = { + /* -- module initialisation -- */ + static const struct usb_device_id device_table[] = { + {USB_DEVICE(0x06f8, 0x3009)}, ++ {USB_DEVICE(0x06f8, 0x301b)}, + {USB_DEVICE(0x093a, 0x2620)}, + {USB_DEVICE(0x093a, 0x2621)}, + {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP}, +@@ -1211,7 +958,7 @@ static int sd_probe(struct usb_interface + } + + static struct usb_driver sd_driver = { +- .name = MODULE_NAME, ++ .name = KBUILD_MODNAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +Index: linux-3.3.x86_64/drivers/media/video/gspca/sonixj.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/gspca/sonixj.c ++++ linux-3.3.x86_64/drivers/media/video/gspca/sonixj.c +@@ -39,7 +39,9 @@ enum e_ctrl { + BLUE, + RED, + GAMMA, ++ EXPOSURE, + AUTOGAIN, ++ GAIN, + HFLIP, + VFLIP, + SHARPNESS, +@@ -131,7 +133,9 @@ static void setcontrast(struct gspca_dev + static void setcolors(struct gspca_dev *gspca_dev); + static void setredblue(struct gspca_dev *gspca_dev); + static void setgamma(struct gspca_dev *gspca_dev); +-static void setautogain(struct gspca_dev *gspca_dev); ++static void setexposure(struct gspca_dev *gspca_dev); ++static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); ++static void setgain(struct gspca_dev *gspca_dev); + static void sethvflip(struct gspca_dev *gspca_dev); + static void setsharpness(struct gspca_dev *gspca_dev); + static void setillum(struct gspca_dev *gspca_dev); +@@ -213,6 +217,18 @@ static const struct ctrl sd_ctrls[NCTRLS + }, + .set_control = setgamma + }, ++[EXPOSURE] = { ++ { ++ .id = V4L2_CID_EXPOSURE, ++ .type = V4L2_CTRL_TYPE_INTEGER, ++ .name = "Exposure", ++ .minimum = 500, ++ .maximum = 1500, ++ .step = 1, ++ .default_value = 1024 ++ }, ++ .set_control = setexposure ++ }, + [AUTOGAIN] = { + { + .id = V4L2_CID_AUTOGAIN, +@@ -223,7 +239,19 @@ static const struct ctrl sd_ctrls[NCTRLS + .step = 1, + .default_value = 1 + }, +- .set_control = setautogain ++ .set = sd_setautogain, ++ }, ++[GAIN] = { ++ { ++ .id = V4L2_CID_GAIN, ++ .type = V4L2_CTRL_TYPE_INTEGER, ++ .name = "Gain", ++ .minimum = 4, ++ .maximum = 49, ++ .step = 1, ++ .default_value = 15 ++ }, ++ .set_control = setgain + }, + [HFLIP] = { + { +@@ -290,60 +318,87 @@ static const struct ctrl sd_ctrls[NCTRLS + + /* table of the disabled controls */ + static const __u32 ctrl_dis[] = { +-[SENSOR_ADCM1700] = (1 << AUTOGAIN) | ++[SENSOR_ADCM1700] = (1 << EXPOSURE) | ++ (1 << AUTOGAIN) | ++ (1 << GAIN) | + (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_GC0307] = (1 << HFLIP) | ++[SENSOR_GC0307] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_HV7131R] = (1 << HFLIP) | ++[SENSOR_HV7131R] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP) | + (1 << FREQ), + +-[SENSOR_MI0360] = (1 << HFLIP) | ++[SENSOR_MI0360] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_MI0360B] = (1 << HFLIP) | ++[SENSOR_MI0360B] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_MO4000] = (1 << HFLIP) | ++[SENSOR_MO4000] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_MT9V111] = (1 << HFLIP) | ++[SENSOR_MT9V111] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_OM6802] = (1 << HFLIP) | ++[SENSOR_OM6802] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_OV7630] = (1 << HFLIP), +- +-[SENSOR_OV7648] = (1 << HFLIP), +- +-[SENSOR_OV7660] = (1 << AUTOGAIN) | ++[SENSOR_OV7630] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP), ++ ++[SENSOR_OV7648] = (1 << EXPOSURE) | ++ (1 << GAIN) | ++ (1 << HFLIP), ++ ++[SENSOR_OV7660] = (1 << EXPOSURE) | ++ (1 << AUTOGAIN) | ++ (1 << GAIN) | + (1 << HFLIP) | + (1 << VFLIP), + +-[SENSOR_PO1030] = (1 << AUTOGAIN) | ++[SENSOR_PO1030] = (1 << EXPOSURE) | ++ (1 << AUTOGAIN) | ++ (1 << GAIN) | + (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_PO2030N] = (1 << AUTOGAIN) | +- (1 << FREQ), ++[SENSOR_PO2030N] = (1 << FREQ), + +-[SENSOR_SOI768] = (1 << AUTOGAIN) | ++[SENSOR_SOI768] = (1 << EXPOSURE) | ++ (1 << AUTOGAIN) | ++ (1 << GAIN) | + (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), + +-[SENSOR_SP80708] = (1 << AUTOGAIN) | ++[SENSOR_SP80708] = (1 << EXPOSURE) | ++ (1 << AUTOGAIN) | ++ (1 << GAIN) | + (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), +@@ -1242,14 +1297,6 @@ static const u8 po2030n_sensor_param1[][ + {0xa1, 0x6e, 0x05, 0x6f, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10}, +- {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, +- {0xc1, 0x6e, 0x16, 0x52, 0x40, 0x48, 0x00, 0x10}, +-/*after start*/ +- {0xa1, 0x6e, 0x15, 0x0f, 0x00, 0x00, 0x00, 0x10}, +- {DELAY, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */ +- {0xa1, 0x6e, 0x1a, 0x05, 0x00, 0x00, 0x00, 0x10}, +- {DELAY, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */ +- {0xa1, 0x6e, 0x1b, 0x53, 0x00, 0x00, 0x00, 0x10}, + {} + }; + +@@ -1858,7 +1905,7 @@ static int sd_init(struct gspca_dev *gsp + return gspca_dev->usb_err; + } + +-static u32 setexposure(struct gspca_dev *gspca_dev, ++static u32 expo_adjust(struct gspca_dev *gspca_dev, + u32 expo) + { + struct sd *sd = (struct sd *) gspca_dev; +@@ -1982,28 +2029,28 @@ static void setbrightness(struct gspca_d + expo = 0x002dc6c0; + else if (expo < 0x02a0) + expo = 0x02a0; +- sd->exposure = setexposure(gspca_dev, expo); ++ sd->exposure = expo_adjust(gspca_dev, expo); + break; + case SENSOR_MI0360: + case SENSOR_MO4000: + expo = brightness << 4; +- sd->exposure = setexposure(gspca_dev, expo); ++ sd->exposure = expo_adjust(gspca_dev, expo); + break; + case SENSOR_MI0360B: + expo = brightness << 2; +- sd->exposure = setexposure(gspca_dev, expo); ++ sd->exposure = expo_adjust(gspca_dev, expo); + break; + case SENSOR_GC0307: + expo = brightness; +- sd->exposure = setexposure(gspca_dev, expo); ++ sd->exposure = expo_adjust(gspca_dev, expo); + return; /* don't set the Y offset */ + case SENSOR_MT9V111: + expo = brightness << 2; +- sd->exposure = setexposure(gspca_dev, expo); ++ sd->exposure = expo_adjust(gspca_dev, expo); + return; /* don't set the Y offset */ + case SENSOR_OM6802: + expo = brightness << 2; +- sd->exposure = setexposure(gspca_dev, expo); ++ sd->exposure = expo_adjust(gspca_dev, expo); + return; /* Y offset already set */ + } + +@@ -2112,6 +2159,23 @@ static void setgamma(struct gspca_dev *g + reg_w(gspca_dev, 0x20, gamma, sizeof gamma); + } + ++static void setexposure(struct gspca_dev *gspca_dev) ++{ ++ struct sd *sd = (struct sd *) gspca_dev; ++ ++ if (sd->sensor == SENSOR_PO2030N) { ++ u8 rexpo[] = /* 1a: expo H, 1b: expo M */ ++ {0xa1, 0x6e, 0x1a, 0x00, 0x40, 0x00, 0x00, 0x10}; ++ ++ rexpo[3] = sd->ctrls[EXPOSURE].val >> 8; ++ i2c_w8(gspca_dev, rexpo); ++ msleep(6); ++ rexpo[2] = 0x1b; ++ rexpo[3] = sd->ctrls[EXPOSURE].val; ++ i2c_w8(gspca_dev, rexpo); ++ } ++} ++ + static void setautogain(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +@@ -2139,6 +2203,19 @@ static void setautogain(struct gspca_dev + sd->ag_cnt = -1; + } + ++static void setgain(struct gspca_dev *gspca_dev) ++{ ++ struct sd *sd = (struct sd *) gspca_dev; ++ ++ if (sd->sensor == SENSOR_PO2030N) { ++ u8 rgain[] = /* 15: gain */ ++ {0xa1, 0x6e, 0x15, 0x00, 0x40, 0x00, 0x00, 0x15}; ++ ++ rgain[3] = sd->ctrls[GAIN].val; ++ i2c_w8(gspca_dev, rgain); ++ } ++} ++ + static void sethvflip(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +@@ -2623,6 +2700,10 @@ static int sd_start(struct gspca_dev *gs + setcontrast(gspca_dev); + setcolors(gspca_dev); + setautogain(gspca_dev); ++ if (!(gspca_dev->ctrl_inac & ((1 << EXPOSURE) | (1 << GAIN)))) { ++ setexposure(gspca_dev); ++ setgain(gspca_dev); ++ } + setfreq(gspca_dev); + + sd->pktsz = sd->npkt = 0; +@@ -2719,6 +2800,12 @@ static void sd_stop0(struct gspca_dev *g + } + } + ++/* !! coarse_grained_expo_autogain is not used !! */ ++#define exp_too_low_cnt bridge ++#define exp_too_high_cnt sensor ++ ++#include "autogain_functions.h" ++ + static void do_autogain(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +@@ -2736,6 +2823,13 @@ static void do_autogain(struct gspca_dev + + delta = atomic_read(&sd->avg_lum); + PDEBUG(D_FRAM, "mean lum %d", delta); ++ ++ if (sd->sensor == SENSOR_PO2030N) { ++ auto_gain_n_exposure(gspca_dev, delta, luma_mean, luma_delta, ++ 15, 1024); ++ return; ++ } ++ + if (delta < luma_mean - luma_delta || + delta > luma_mean + luma_delta) { + switch (sd->sensor) { +@@ -2744,7 +2838,7 @@ static void do_autogain(struct gspca_dev + expotimes += (luma_mean - delta) >> 6; + if (expotimes < 0) + expotimes = 0; +- sd->exposure = setexposure(gspca_dev, ++ sd->exposure = expo_adjust(gspca_dev, + (unsigned int) expotimes); + break; + case SENSOR_HV7131R: +@@ -2752,7 +2846,7 @@ static void do_autogain(struct gspca_dev + expotimes += (luma_mean - delta) >> 4; + if (expotimes < 0) + expotimes = 0; +- sd->exposure = setexposure(gspca_dev, ++ sd->exposure = expo_adjust(gspca_dev, + (unsigned int) (expotimes << 8)); + break; + case SENSOR_OM6802: +@@ -2761,7 +2855,7 @@ static void do_autogain(struct gspca_dev + expotimes += (luma_mean - delta) >> 2; + if (expotimes < 0) + expotimes = 0; +- sd->exposure = setexposure(gspca_dev, ++ sd->exposure = expo_adjust(gspca_dev, + (unsigned int) expotimes); + setredblue(gspca_dev); + break; +@@ -2773,7 +2867,7 @@ static void do_autogain(struct gspca_dev + expotimes += (luma_mean - delta) >> 6; + if (expotimes < 0) + expotimes = 0; +- sd->exposure = setexposure(gspca_dev, ++ sd->exposure = expo_adjust(gspca_dev, + (unsigned int) expotimes); + setredblue(gspca_dev); + break; +@@ -2948,16 +3042,18 @@ marker_found: + } + } + +-static int sd_get_jcomp(struct gspca_dev *gspca_dev, +- struct v4l2_jpegcompression *jcomp) ++static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) + { + struct sd *sd = (struct sd *) gspca_dev; + +- memset(jcomp, 0, sizeof *jcomp); +- jcomp->quality = sd->quality; +- jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT +- | V4L2_JPEG_MARKER_DQT; +- return 0; ++ sd->ctrls[AUTOGAIN].val = val; ++ if (val) ++ gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN); ++ else ++ gspca_dev->ctrl_inac &= ~(1 << EXPOSURE) & ~(1 << GAIN); ++ if (gspca_dev->streaming) ++ setautogain(gspca_dev); ++ return gspca_dev->usb_err; + } + + static int sd_querymenu(struct gspca_dev *gspca_dev, +@@ -3012,7 +3108,6 @@ static const struct sd_desc sd_desc = { + .stop0 = sd_stop0, + .pkt_scan = sd_pkt_scan, + .dq_callback = do_autogain, +- .get_jcomp = sd_get_jcomp, + .querymenu = sd_querymenu, + #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + .int_pkt_scan = sd_int_pkt_scan, +Index: linux-3.3.x86_64/drivers/media/video/gspca/zc3xx.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/gspca/zc3xx.c ++++ linux-3.3.x86_64/drivers/media/video/gspca/zc3xx.c +@@ -1,7 +1,7 @@ + /* +- * Z-Star/Vimicro zc301/zc302p/vc30x library ++ * Z-Star/Vimicro zc301/zc302p/vc30x driver + * +- * Copyright (C) 2009-2011 Jean-Francois Moine ++ * Copyright (C) 2009-2012 Jean-Francois Moine + * Copyright (C) 2004 2005 2006 Michel Xhaard mxhaard@magic.fr + * + * This program is free software; you can redistribute it and/or modify +@@ -21,8 +21,6 @@ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +-#define MODULE_NAME "zc3xx" +- + #include + #include "gspca.h" + #include "jpeg.h" +@@ -34,7 +32,7 @@ MODULE_LICENSE("GPL"); + + static int force_sensor = -1; + +-#define QUANT_VAL 1 /* quantization table */ ++#define REG08_DEF 3 /* default JPEG compression (70%) */ + #include "zc3xx-reg.h" + + /* controls */ +@@ -46,6 +44,7 @@ enum e_ctrl { + AUTOGAIN, + LIGHTFREQ, + SHARPNESS, ++ QUALITY, + NCTRLS /* number of controls */ + }; + +@@ -57,10 +56,10 @@ struct sd { + + struct gspca_ctrl ctrls[NCTRLS]; + +- u8 quality; /* image quality */ +-#define QUALITY_MIN 50 +-#define QUALITY_MAX 80 +-#define QUALITY_DEF 70 ++ struct work_struct work; ++ struct workqueue_struct *work_thread; ++ ++ u8 reg08; /* webcam compression quality */ + + u8 bridge; + u8 sensor; /* Type of image sensor chip */ +@@ -101,6 +100,7 @@ static void setexposure(struct gspca_dev + static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); + static void setlightfreq(struct gspca_dev *gspca_dev); + static void setsharpness(struct gspca_dev *gspca_dev); ++static int sd_setquality(struct gspca_dev *gspca_dev, __s32 val); + + static const struct ctrl sd_ctrls[NCTRLS] = { + [BRIGHTNESS] = { +@@ -188,6 +188,18 @@ static const struct ctrl sd_ctrls[NCTRLS + }, + .set_control = setsharpness + }, ++[QUALITY] = { ++ { ++ .id = V4L2_CID_JPEG_COMPRESSION_QUALITY, ++ .type = V4L2_CTRL_TYPE_INTEGER, ++ .name = "Compression Quality", ++ .minimum = 40, ++ .maximum = 70, ++ .step = 1, ++ .default_value = 70 /* updated in sd_init() */ ++ }, ++ .set = sd_setquality ++ }, + }; + + static const struct v4l2_pix_format vga_mode[] = { +@@ -229,6 +241,9 @@ static const struct v4l2_pix_format sif_ + .priv = 0}, + }; + ++/* bridge reg08 -> JPEG quality conversion table */ ++static u8 jpeg_qual[] = {40, 50, 60, 70, /*80*/}; ++ + /* usb exchanges */ + struct usb_action { + u8 req; +@@ -3894,7 +3909,6 @@ static const struct usb_action pas106b_I + /* Gains */ + {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF}, + {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, +- {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN}, + {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, + /* Auto correction */ + {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, +@@ -5640,7 +5654,7 @@ static const struct usb_action gc0303_No + {} + }; + +-static u8 reg_r_i(struct gspca_dev *gspca_dev, ++static u8 reg_r(struct gspca_dev *gspca_dev, + u16 index) + { + int ret; +@@ -5655,24 +5669,14 @@ static u8 reg_r_i(struct gspca_dev *gspc + index, gspca_dev->usb_buf, 1, + 500); + if (ret < 0) { +- pr_err("reg_r_i err %d\n", ret); ++ pr_err("reg_r err %d\n", ret); + gspca_dev->usb_err = ret; + return 0; + } + return gspca_dev->usb_buf[0]; + } + +-static u8 reg_r(struct gspca_dev *gspca_dev, +- u16 index) +-{ +- u8 ret; +- +- ret = reg_r_i(gspca_dev, index); +- PDEBUG(D_USBI, "reg r [%04x] -> %02x", index, ret); +- return ret; +-} +- +-static void reg_w_i(struct gspca_dev *gspca_dev, ++static void reg_w(struct gspca_dev *gspca_dev, + u8 value, + u16 index) + { +@@ -5692,14 +5696,6 @@ static void reg_w_i(struct gspca_dev *gs + } + } + +-static void reg_w(struct gspca_dev *gspca_dev, +- u8 value, +- u16 index) +-{ +- PDEBUG(D_USBO, "reg w [%04x] = %02x", index, value); +- reg_w_i(gspca_dev, value, index); +-} +- + static u16 i2c_read(struct gspca_dev *gspca_dev, + u8 reg) + { +@@ -5708,16 +5704,14 @@ static u16 i2c_read(struct gspca_dev *gs + + if (gspca_dev->usb_err < 0) + return 0; +- reg_w_i(gspca_dev, reg, 0x0092); +- reg_w_i(gspca_dev, 0x02, 0x0090); /* <- read command */ ++ reg_w(gspca_dev, reg, 0x0092); ++ reg_w(gspca_dev, 0x02, 0x0090); /* <- read command */ + msleep(20); +- retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ ++ retbyte = reg_r(gspca_dev, 0x0091); /* read status */ + if (retbyte != 0x00) + pr_err("i2c_r status error %02x\n", retbyte); +- retval = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */ +- retval |= reg_r_i(gspca_dev, 0x0096) << 8; /* read Hightbyte */ +- PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)", +- reg, retval, retbyte); ++ retval = reg_r(gspca_dev, 0x0095); /* read Lowbyte */ ++ retval |= reg_r(gspca_dev, 0x0096) << 8; /* read Hightbyte */ + return retval; + } + +@@ -5730,16 +5724,14 @@ static u8 i2c_write(struct gspca_dev *gs + + if (gspca_dev->usb_err < 0) + return 0; +- reg_w_i(gspca_dev, reg, 0x92); +- reg_w_i(gspca_dev, valL, 0x93); +- reg_w_i(gspca_dev, valH, 0x94); +- reg_w_i(gspca_dev, 0x01, 0x90); /* <- write command */ ++ reg_w(gspca_dev, reg, 0x92); ++ reg_w(gspca_dev, valL, 0x93); ++ reg_w(gspca_dev, valH, 0x94); ++ reg_w(gspca_dev, 0x01, 0x90); /* <- write command */ + msleep(1); +- retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ ++ retbyte = reg_r(gspca_dev, 0x0091); /* read status */ + if (retbyte != 0x00) + pr_err("i2c_w status error %02x\n", retbyte); +- PDEBUG(D_USBO, "i2c w [%02x] = %02x%02x (%02x)", +- reg, valH, valL, retbyte); + return retbyte; + } + +@@ -5906,6 +5898,8 @@ static void getexposure(struct gspca_dev + { + struct sd *sd = (struct sd *) gspca_dev; + ++ if (sd->sensor != SENSOR_HV7131R) ++ return; + sd->ctrls[EXPOSURE].val = (i2c_read(gspca_dev, 0x25) << 9) + | (i2c_read(gspca_dev, 0x26) << 1) + | (i2c_read(gspca_dev, 0x27) >> 7); +@@ -5916,6 +5910,8 @@ static void setexposure(struct gspca_dev + struct sd *sd = (struct sd *) gspca_dev; + int val; + ++ if (sd->sensor != SENSOR_HV7131R) ++ return; + val = sd->ctrls[EXPOSURE].val; + i2c_write(gspca_dev, 0x25, val >> 9, 0x00); + i2c_write(gspca_dev, 0x26, val >> 1, 0x00); +@@ -5925,32 +5921,20 @@ static void setexposure(struct gspca_dev + static void setquality(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- u8 frxt; ++ s8 reg07; + ++ reg07 = 0; + switch (sd->sensor) { +- case SENSOR_ADCM2700: +- case SENSOR_GC0305: +- case SENSOR_HV7131B: +- case SENSOR_HV7131R: + case SENSOR_OV7620: ++ reg07 = 0x30; ++ break; ++ case SENSOR_HV7131R: + case SENSOR_PAS202B: +- case SENSOR_PO2030: +- return; ++ return; /* done by work queue */ + } +-/*fixme: is it really 0008 0007 0018 for all other sensors? */ +- reg_w(gspca_dev, QUANT_VAL, 0x0008); +- frxt = 0x30; +- reg_w(gspca_dev, frxt, 0x0007); +-#if QUANT_VAL == 0 || QUANT_VAL == 1 || QUANT_VAL == 2 +- frxt = 0xff; +-#elif QUANT_VAL == 3 +- frxt = 0xf0; +-#elif QUANT_VAL == 4 +- frxt = 0xe0; +-#else +- frxt = 0x20; +-#endif +- reg_w(gspca_dev, frxt, 0x0018); ++ reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING); ++ if (reg07 != 0) ++ reg_w(gspca_dev, reg07, 0x0007); + } + + /* Matches the sensor's internal frame rate to the lighting frequency. +@@ -6084,6 +6068,115 @@ static void setautogain(struct gspca_dev + reg_w(gspca_dev, autoval, 0x0180); + } + ++/* update the transfer parameters */ ++/* This function is executed from a work queue. */ ++/* The exact use of the bridge registers 07 and 08 is not known. ++ * The following algorithm has been adapted from ms-win traces */ ++static void transfer_update(struct work_struct *work) ++{ ++ struct sd *sd = container_of(work, struct sd, work); ++ struct gspca_dev *gspca_dev = &sd->gspca_dev; ++ int change, good; ++ u8 reg07, reg11; ++ ++ /* synchronize with the main driver and initialize the registers */ ++ mutex_lock(&gspca_dev->usb_lock); ++ reg07 = 0; /* max */ ++ reg_w(gspca_dev, reg07, 0x0007); ++ reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING); ++ mutex_unlock(&gspca_dev->usb_lock); ++ ++ good = 0; ++ for (;;) { ++ msleep(100); ++ ++ /* get the transfer status */ ++ /* the bit 0 of the bridge register 11 indicates overflow */ ++ mutex_lock(&gspca_dev->usb_lock); ++ if (!gspca_dev->present || !gspca_dev->streaming) ++ goto err; ++ reg11 = reg_r(gspca_dev, 0x0011); ++ if (gspca_dev->usb_err < 0 ++ || !gspca_dev->present || !gspca_dev->streaming) ++ goto err; ++ ++ change = reg11 & 0x01; ++ if (change) { /* overflow */ ++ switch (reg07) { ++ case 0: /* max */ ++ reg07 = sd->sensor == SENSOR_HV7131R ++ ? 0x30 : 0x32; ++ if (sd->reg08 != 0) { ++ change = 3; ++ sd->reg08--; ++ } ++ break; ++ case 0x32: ++ reg07 -= 4; ++ break; ++ default: ++ reg07 -= 2; ++ break; ++ case 2: ++ change = 0; /* already min */ ++ break; ++ } ++ good = 0; ++ } else { /* no overflow */ ++ if (reg07 != 0) { /* if not max */ ++ good++; ++ if (good >= 10) { ++ good = 0; ++ change = 1; ++ reg07 += 2; ++ switch (reg07) { ++ case 0x30: ++ if (sd->sensor == SENSOR_PAS202B) ++ reg07 += 2; ++ break; ++ case 0x32: ++ case 0x34: ++ reg07 = 0; ++ break; ++ } ++ } ++ } else { /* reg07 max */ ++ if (sd->reg08 < sizeof jpeg_qual - 1) { ++ good++; ++ if (good > 10) { ++ sd->reg08++; ++ change = 2; ++ } ++ } ++ } ++ } ++ if (change) { ++ if (change & 1) { ++ reg_w(gspca_dev, reg07, 0x0007); ++ if (gspca_dev->usb_err < 0 ++ || !gspca_dev->present ++ || !gspca_dev->streaming) ++ goto err; ++ } ++ if (change & 2) { ++ reg_w(gspca_dev, sd->reg08, ++ ZC3XX_R008_CLOCKSETTING); ++ if (gspca_dev->usb_err < 0 ++ || !gspca_dev->present ++ || !gspca_dev->streaming) ++ goto err; ++ sd->ctrls[QUALITY].val = jpeg_qual[sd->reg08]; ++ jpeg_set_qual(sd->jpeg_hdr, ++ jpeg_qual[sd->reg08]); ++ } ++ } ++ mutex_unlock(&gspca_dev->usb_lock); ++ } ++ return; ++err: ++ mutex_unlock(&gspca_dev->usb_lock); ++} ++ + static void send_unknown(struct gspca_dev *gspca_dev, int sensor) + { + reg_w(gspca_dev, 0x01, 0x0000); /* bridge reset */ +@@ -6411,7 +6504,9 @@ static int sd_config(struct gspca_dev *g + sd->sensor = id->driver_info; + + gspca_dev->cam.ctrls = sd->ctrls; +- sd->quality = QUALITY_DEF; ++ sd->reg08 = REG08_DEF; ++ ++ INIT_WORK(&sd->work, transfer_update); + + return 0; + } +@@ -6464,6 +6559,27 @@ static int sd_init(struct gspca_dev *gsp + [SENSOR_PO2030] = 1, + [SENSOR_TAS5130C] = 1, + }; ++ static const u8 reg08_tb[SENSOR_MAX] = { ++ [SENSOR_ADCM2700] = 1, ++ [SENSOR_CS2102] = 3, ++ [SENSOR_CS2102K] = 3, ++ [SENSOR_GC0303] = 2, ++ [SENSOR_GC0305] = 3, ++ [SENSOR_HDCS2020] = 1, ++ [SENSOR_HV7131B] = 3, ++ [SENSOR_HV7131R] = 3, ++ [SENSOR_ICM105A] = 3, ++ [SENSOR_MC501CB] = 3, ++ [SENSOR_MT9V111_1] = 3, ++ [SENSOR_MT9V111_3] = 3, ++ [SENSOR_OV7620] = 1, ++ [SENSOR_OV7630C] = 3, ++ [SENSOR_PAS106] = 3, ++ [SENSOR_PAS202B] = 3, ++ [SENSOR_PB0330] = 3, ++ [SENSOR_PO2030] = 2, ++ [SENSOR_TAS5130C] = 3, ++ }; + + sensor = zcxx_probeSensor(gspca_dev); + if (sensor >= 0) +@@ -6528,7 +6644,6 @@ static int sd_init(struct gspca_dev *gsp + case 0x0e: + PDEBUG(D_PROBE, "Find Sensor PAS202B"); + sd->sensor = SENSOR_PAS202B; +-/* sd->sharpness = 1; */ + break; + case 0x0f: + PDEBUG(D_PROBE, "Find Sensor PAS106"); +@@ -6616,13 +6731,21 @@ static int sd_init(struct gspca_dev *gsp + } + + sd->ctrls[GAMMA].def = gamma[sd->sensor]; ++ sd->reg08 = reg08_tb[sd->sensor]; ++ sd->ctrls[QUALITY].def = jpeg_qual[sd->reg08]; ++ sd->ctrls[QUALITY].min = jpeg_qual[0]; ++ sd->ctrls[QUALITY].max = jpeg_qual[ARRAY_SIZE(jpeg_qual) - 1]; + + switch (sd->sensor) { + case SENSOR_HV7131R: ++ gspca_dev->ctrl_dis = (1 << QUALITY); + break; + case SENSOR_OV7630C: + gspca_dev->ctrl_dis = (1 << LIGHTFREQ) | (1 << EXPOSURE); + break; ++ case SENSOR_PAS202B: ++ gspca_dev->ctrl_dis = (1 << QUALITY) | (1 << EXPOSURE); ++ break; + default: + gspca_dev->ctrl_dis = (1 << EXPOSURE); + break; +@@ -6685,7 +6808,6 @@ static int sd_start(struct gspca_dev *gs + /* create the JPEG header */ + jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x21); /* JPEG 422 */ +- jpeg_set_qual(sd->jpeg_hdr, sd->quality); + + mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; + switch (sd->sensor) { +@@ -6761,10 +6883,9 @@ static int sd_start(struct gspca_dev *gs + reg_r(gspca_dev, 0x0180); /* from win */ + reg_w(gspca_dev, 0x00, 0x0180); + break; +- default: +- setquality(gspca_dev); +- break; + } ++ setquality(gspca_dev); ++ jpeg_set_qual(sd->jpeg_hdr, jpeg_qual[sd->reg08]); + setlightfreq(gspca_dev); + + switch (sd->sensor) { +@@ -6776,8 +6897,7 @@ static int sd_start(struct gspca_dev *gs + reg_w(gspca_dev, 0x40, 0x0117); + break; + case SENSOR_HV7131R: +- if (!sd->ctrls[AUTOGAIN].val) +- setexposure(gspca_dev); ++ setexposure(gspca_dev); + reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN); + break; + case SENSOR_GC0305: +@@ -6802,13 +6922,19 @@ static int sd_start(struct gspca_dev *gs + } + + setautogain(gspca_dev); +- switch (sd->sensor) { +- case SENSOR_PO2030: +- msleep(50); +- reg_w(gspca_dev, 0x00, 0x0007); /* (from win traces) */ +- reg_w(gspca_dev, 0x02, ZC3XX_R008_CLOCKSETTING); +- break; ++ ++ /* start the transfer update thread if needed */ ++ if (gspca_dev->usb_err >= 0) { ++ switch (sd->sensor) { ++ case SENSOR_HV7131R: ++ case SENSOR_PAS202B: ++ sd->work_thread = ++ create_singlethread_workqueue(KBUILD_MODNAME); ++ queue_work(sd->work_thread, &sd->work); ++ break; ++ } + } ++ + return gspca_dev->usb_err; + } + +@@ -6817,6 +6943,12 @@ static void sd_stop0(struct gspca_dev *g + { + struct sd *sd = (struct sd *) gspca_dev; + ++ if (sd->work_thread != NULL) { ++ mutex_unlock(&gspca_dev->usb_lock); ++ destroy_workqueue(sd->work_thread); ++ mutex_lock(&gspca_dev->usb_lock); ++ sd->work_thread = NULL; ++ } + if (!gspca_dev->present) + return; + send_unknown(gspca_dev, sd->sensor); +@@ -6893,19 +7025,33 @@ static int sd_querymenu(struct gspca_dev + return -EINVAL; + } + ++static int sd_setquality(struct gspca_dev *gspca_dev, __s32 val) ++{ ++ struct sd *sd = (struct sd *) gspca_dev; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(jpeg_qual) - 1; i++) { ++ if (val <= jpeg_qual[i]) ++ break; ++ } ++ if (i > 0 ++ && i == sd->reg08 ++ && val < jpeg_qual[sd->reg08]) ++ i--; ++ sd->reg08 = i; ++ sd->ctrls[QUALITY].val = jpeg_qual[i]; ++ if (gspca_dev->streaming) ++ jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); ++ return gspca_dev->usb_err; ++} ++ + static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) + { + struct sd *sd = (struct sd *) gspca_dev; + +- if (jcomp->quality < QUALITY_MIN) +- sd->quality = QUALITY_MIN; +- else if (jcomp->quality > QUALITY_MAX) +- sd->quality = QUALITY_MAX; +- else +- sd->quality = jcomp->quality; +- if (gspca_dev->streaming) +- jpeg_set_qual(sd->jpeg_hdr, sd->quality); ++ sd_setquality(gspca_dev, jcomp->quality); ++ jcomp->quality = sd->ctrls[QUALITY].val; + return gspca_dev->usb_err; + } + +@@ -6915,7 +7061,7 @@ static int sd_get_jcomp(struct gspca_dev + struct sd *sd = (struct sd *) gspca_dev; + + memset(jcomp, 0, sizeof *jcomp); +- jcomp->quality = sd->quality; ++ jcomp->quality = sd->ctrls[QUALITY].val; + jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT + | V4L2_JPEG_MARKER_DQT; + return 0; +@@ -6938,7 +7084,7 @@ static int sd_int_pkt_scan(struct gspca_ + #endif + + static const struct sd_desc sd_desc = { +- .name = MODULE_NAME, ++ .name = KBUILD_MODNAME, + .ctrls = sd_ctrls, + .nctrls = ARRAY_SIZE(sd_ctrls), + .config = sd_config, +@@ -7023,7 +7169,7 @@ static int sd_probe(struct usb_interface + + /* USB driver */ + static struct usb_driver sd_driver = { +- .name = MODULE_NAME, ++ .name = KBUILD_MODNAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/au8522_decoder.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/au8522_decoder.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/au8522_decoder.c +@@ -839,15 +839,4 @@ static struct i2c_driver au8522_driver = + .id_table = au8522_id, + }; + +-static __init int init_au8522(void) +-{ +- return i2c_add_driver(&au8522_driver); +-} +- +-static __exit void exit_au8522(void) +-{ +- i2c_del_driver(&au8522_driver); +-} +- +-module_init(init_au8522); +-module_exit(exit_au8522); ++module_i2c_driver(au8522_driver); +Index: linux-3.3.x86_64/drivers/media/radio/radio-tea5764.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-tea5764.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-tea5764.c +@@ -575,21 +575,7 @@ static struct i2c_driver tea5764_i2c_dri + .id_table = tea5764_id, + }; + +-/* init the driver */ +-static int __init tea5764_init(void) +-{ +- int ret = i2c_add_driver(&tea5764_i2c_driver); +- +- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ": " +- DRIVER_DESC "\n"); +- return ret; +-} +- +-/* cleanup the driver */ +-static void __exit tea5764_exit(void) +-{ +- i2c_del_driver(&tea5764_i2c_driver); +-} ++module_i2c_driver(tea5764_i2c_driver); + + MODULE_AUTHOR(DRIVER_AUTHOR); + MODULE_DESCRIPTION(DRIVER_DESC); +@@ -600,6 +586,3 @@ module_param(use_xtal, int, 0); + MODULE_PARM_DESC(use_xtal, "Chip have a xtal connected in board"); + module_param(radio_nr, int, 0); + MODULE_PARM_DESC(radio_nr, "video4linux device number to use"); +- +-module_init(tea5764_init); +-module_exit(tea5764_exit); +Index: linux-3.3.x86_64/drivers/media/radio/saa7706h.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/saa7706h.c ++++ linux-3.3.x86_64/drivers/media/radio/saa7706h.c +@@ -434,18 +434,7 @@ static struct i2c_driver saa7706h_driver + .id_table = saa7706h_id, + }; + +-static __init int saa7706h_init(void) +-{ +- return i2c_add_driver(&saa7706h_driver); +-} +- +-static __exit void saa7706h_exit(void) +-{ +- i2c_del_driver(&saa7706h_driver); +-} +- +-module_init(saa7706h_init); +-module_exit(saa7706h_exit); ++module_i2c_driver(saa7706h_driver); + + MODULE_DESCRIPTION("SAA7706H Car Radio DSP driver"); + MODULE_AUTHOR("Mocean Laboratories"); +Index: linux-3.3.x86_64/drivers/media/radio/si470x/radio-si470x-i2c.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/si470x/radio-si470x-i2c.c ++++ linux-3.3.x86_64/drivers/media/radio/si470x/radio-si470x-i2c.c +@@ -539,33 +539,7 @@ static struct i2c_driver si470x_i2c_driv + .id_table = si470x_i2c_id, + }; + +- +- +-/************************************************************************** +- * Module Interface +- **************************************************************************/ +- +-/* +- * si470x_i2c_init - module init +- */ +-static int __init si470x_i2c_init(void) +-{ +- printk(KERN_INFO DRIVER_DESC ", Version " DRIVER_VERSION "\n"); +- return i2c_add_driver(&si470x_i2c_driver); +-} +- +- +-/* +- * si470x_i2c_exit - module exit +- */ +-static void __exit si470x_i2c_exit(void) +-{ +- i2c_del_driver(&si470x_i2c_driver); +-} +- +- +-module_init(si470x_i2c_init); +-module_exit(si470x_i2c_exit); ++module_i2c_driver(si470x_i2c_driver); + + MODULE_LICENSE("GPL"); + MODULE_AUTHOR(DRIVER_AUTHOR); +Index: linux-3.3.x86_64/drivers/media/radio/si4713-i2c.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/si4713-i2c.c ++++ linux-3.3.x86_64/drivers/media/radio/si4713-i2c.c +@@ -2106,17 +2106,4 @@ static struct i2c_driver si4713_i2c_driv + .id_table = si4713_id, + }; + +-/* Module Interface */ +-static int __init si4713_module_init(void) +-{ +- return i2c_add_driver(&si4713_i2c_driver); +-} +- +-static void __exit si4713_module_exit(void) +-{ +- i2c_del_driver(&si4713_i2c_driver); +-} +- +-module_init(si4713_module_init); +-module_exit(si4713_module_exit); +- ++module_i2c_driver(si4713_i2c_driver); +Index: linux-3.3.x86_64/drivers/media/radio/tef6862.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/tef6862.c ++++ linux-3.3.x86_64/drivers/media/radio/tef6862.c +@@ -215,20 +215,8 @@ static struct i2c_driver tef6862_driver + .id_table = tef6862_id, + }; + +-static __init int tef6862_init(void) +-{ +- return i2c_add_driver(&tef6862_driver); +-} +- +-static __exit void tef6862_exit(void) +-{ +- i2c_del_driver(&tef6862_driver); +-} +- +-module_init(tef6862_init); +-module_exit(tef6862_exit); ++module_i2c_driver(tef6862_driver); + + MODULE_DESCRIPTION("TEF6862 Car Radio Enhanced Selectivity Tuner"); + MODULE_AUTHOR("Mocean Laboratories"); + MODULE_LICENSE("GPL v2"); +- +Index: linux-3.3.x86_64/drivers/media/video/adp1653.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/adp1653.c ++++ linux-3.3.x86_64/drivers/media/video/adp1653.c +@@ -33,7 +33,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -482,24 +481,7 @@ static struct i2c_driver adp1653_i2c_dri + .id_table = adp1653_id_table, + }; + +-static int __init adp1653_init(void) +-{ +- int rval; +- +- rval = i2c_add_driver(&adp1653_i2c_driver); +- if (rval) +- printk(KERN_ALERT "%s: failed at i2c_add_driver\n", __func__); +- +- return rval; +-} +- +-static void __exit adp1653_exit(void) +-{ +- i2c_del_driver(&adp1653_i2c_driver); +-} +- +-module_init(adp1653_init); +-module_exit(adp1653_exit); ++module_i2c_driver(adp1653_i2c_driver); + + MODULE_AUTHOR("Sakari Ailus "); + MODULE_DESCRIPTION("Analog Devices ADP1653 LED flash driver"); +Index: linux-3.3.x86_64/drivers/media/video/adv7170.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/adv7170.c ++++ linux-3.3.x86_64/drivers/media/video/adv7170.c +@@ -407,15 +407,4 @@ static struct i2c_driver adv7170_driver + .id_table = adv7170_id, + }; + +-static __init int init_adv7170(void) +-{ +- return i2c_add_driver(&adv7170_driver); +-} +- +-static __exit void exit_adv7170(void) +-{ +- i2c_del_driver(&adv7170_driver); +-} +- +-module_init(init_adv7170); +-module_exit(exit_adv7170); ++module_i2c_driver(adv7170_driver); +Index: linux-3.3.x86_64/drivers/media/video/adv7175.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/adv7175.c ++++ linux-3.3.x86_64/drivers/media/video/adv7175.c +@@ -457,15 +457,4 @@ static struct i2c_driver adv7175_driver + .id_table = adv7175_id, + }; + +-static __init int init_adv7175(void) +-{ +- return i2c_add_driver(&adv7175_driver); +-} +- +-static __exit void exit_adv7175(void) +-{ +- i2c_del_driver(&adv7175_driver); +-} +- +-module_init(init_adv7175); +-module_exit(exit_adv7175); ++module_i2c_driver(adv7175_driver); +Index: linux-3.3.x86_64/drivers/media/video/adv7180.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/adv7180.c ++++ linux-3.3.x86_64/drivers/media/video/adv7180.c +@@ -444,20 +444,8 @@ static struct i2c_driver adv7180_driver + .id_table = adv7180_id, + }; + +-static __init int adv7180_init(void) +-{ +- return i2c_add_driver(&adv7180_driver); +-} +- +-static __exit void adv7180_exit(void) +-{ +- i2c_del_driver(&adv7180_driver); +-} +- +-module_init(adv7180_init); +-module_exit(adv7180_exit); ++module_i2c_driver(adv7180_driver); + + MODULE_DESCRIPTION("Analog Devices ADV7180 video decoder driver"); + MODULE_AUTHOR("Mocean Laboratories"); + MODULE_LICENSE("GPL v2"); +- +Index: linux-3.3.x86_64/drivers/media/video/adv7343.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/adv7343.c ++++ linux-3.3.x86_64/drivers/media/video/adv7343.c +@@ -475,15 +475,4 @@ static struct i2c_driver adv7343_driver + .id_table = adv7343_id, + }; + +-static __init int init_adv7343(void) +-{ +- return i2c_add_driver(&adv7343_driver); +-} +- +-static __exit void exit_adv7343(void) +-{ +- i2c_del_driver(&adv7343_driver); +-} +- +-module_init(init_adv7343); +-module_exit(exit_adv7343); ++module_i2c_driver(adv7343_driver); +Index: linux-3.3.x86_64/drivers/media/video/ak881x.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ak881x.c ++++ linux-3.3.x86_64/drivers/media/video/ak881x.c +@@ -352,18 +352,7 @@ static struct i2c_driver ak881x_i2c_driv + .id_table = ak881x_id, + }; + +-static int __init ak881x_module_init(void) +-{ +- return i2c_add_driver(&ak881x_i2c_driver); +-} +- +-static void __exit ak881x_module_exit(void) +-{ +- i2c_del_driver(&ak881x_i2c_driver); +-} +- +-module_init(ak881x_module_init); +-module_exit(ak881x_module_exit); ++module_i2c_driver(ak881x_i2c_driver); + + MODULE_DESCRIPTION("TV-output driver for ak8813/ak8814"); + MODULE_AUTHOR("Guennadi Liakhovetski "); +Index: linux-3.3.x86_64/drivers/media/video/as3645a.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/as3645a.c ++++ linux-3.3.x86_64/drivers/media/video/as3645a.c +@@ -881,24 +881,7 @@ static struct i2c_driver as3645a_i2c_dri + .id_table = as3645a_id_table, + }; + +-static int __init as3645a_init(void) +-{ +- int rval; +- +- rval = i2c_add_driver(&as3645a_i2c_driver); +- if (rval) +- pr_err("%s: Failed to register the driver\n", AS3645A_NAME); +- +- return rval; +-} +- +-static void __exit as3645a_exit(void) +-{ +- i2c_del_driver(&as3645a_i2c_driver); +-} +- +-module_init(as3645a_init); +-module_exit(as3645a_exit); ++module_i2c_driver(as3645a_i2c_driver); + + MODULE_AUTHOR("Laurent Pinchart "); + MODULE_DESCRIPTION("LED flash driver for AS3645A, LM3555 and their clones"); +Index: linux-3.3.x86_64/drivers/media/video/bt819.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/bt819.c ++++ linux-3.3.x86_64/drivers/media/video/bt819.c +@@ -514,15 +514,4 @@ static struct i2c_driver bt819_driver = + .id_table = bt819_id, + }; + +-static __init int init_bt819(void) +-{ +- return i2c_add_driver(&bt819_driver); +-} +- +-static __exit void exit_bt819(void) +-{ +- i2c_del_driver(&bt819_driver); +-} +- +-module_init(init_bt819); +-module_exit(exit_bt819); ++module_i2c_driver(bt819_driver); +Index: linux-3.3.x86_64/drivers/media/video/bt856.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/bt856.c ++++ linux-3.3.x86_64/drivers/media/video/bt856.c +@@ -270,15 +270,4 @@ static struct i2c_driver bt856_driver = + .id_table = bt856_id, + }; + +-static __init int init_bt856(void) +-{ +- return i2c_add_driver(&bt856_driver); +-} +- +-static __exit void exit_bt856(void) +-{ +- i2c_del_driver(&bt856_driver); +-} +- +-module_init(init_bt856); +-module_exit(exit_bt856); ++module_i2c_driver(bt856_driver); +Index: linux-3.3.x86_64/drivers/media/video/bt866.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/bt866.c ++++ linux-3.3.x86_64/drivers/media/video/bt866.c +@@ -240,15 +240,4 @@ static struct i2c_driver bt866_driver = + .id_table = bt866_id, + }; + +-static __init int init_bt866(void) +-{ +- return i2c_add_driver(&bt866_driver); +-} +- +-static __exit void exit_bt866(void) +-{ +- i2c_del_driver(&bt866_driver); +-} +- +-module_init(init_bt866); +-module_exit(exit_bt866); ++module_i2c_driver(bt866_driver); +Index: linux-3.3.x86_64/drivers/media/video/cs5345.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cs5345.c ++++ linux-3.3.x86_64/drivers/media/video/cs5345.c +@@ -249,15 +249,4 @@ static struct i2c_driver cs5345_driver = + .id_table = cs5345_id, + }; + +-static __init int init_cs5345(void) +-{ +- return i2c_add_driver(&cs5345_driver); +-} +- +-static __exit void exit_cs5345(void) +-{ +- i2c_del_driver(&cs5345_driver); +-} +- +-module_init(init_cs5345); +-module_exit(exit_cs5345); ++module_i2c_driver(cs5345_driver); +Index: linux-3.3.x86_64/drivers/media/video/cs53l32a.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cs53l32a.c ++++ linux-3.3.x86_64/drivers/media/video/cs53l32a.c +@@ -248,15 +248,4 @@ static struct i2c_driver cs53l32a_driver + .id_table = cs53l32a_id, + }; + +-static __init int init_cs53l32a(void) +-{ +- return i2c_add_driver(&cs53l32a_driver); +-} +- +-static __exit void exit_cs53l32a(void) +-{ +- i2c_del_driver(&cs53l32a_driver); +-} +- +-module_init(init_cs53l32a); +-module_exit(exit_cs53l32a); ++module_i2c_driver(cs53l32a_driver); +Index: linux-3.3.x86_64/drivers/media/video/cx25840/cx25840-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx25840/cx25840-core.c ++++ linux-3.3.x86_64/drivers/media/video/cx25840/cx25840-core.c +@@ -5301,15 +5301,4 @@ static struct i2c_driver cx25840_driver + .id_table = cx25840_id, + }; + +-static __init int init_cx25840(void) +-{ +- return i2c_add_driver(&cx25840_driver); +-} +- +-static __exit void exit_cx25840(void) +-{ +- i2c_del_driver(&cx25840_driver); +-} +- +-module_init(init_cx25840); +-module_exit(exit_cx25840); ++module_i2c_driver(cx25840_driver); +Index: linux-3.3.x86_64/drivers/media/video/imx074.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/imx074.c ++++ linux-3.3.x86_64/drivers/media/video/imx074.c +@@ -468,18 +468,7 @@ static struct i2c_driver imx074_i2c_driv + .id_table = imx074_id, + }; + +-static int __init imx074_mod_init(void) +-{ +- return i2c_add_driver(&imx074_i2c_driver); +-} +- +-static void __exit imx074_mod_exit(void) +-{ +- i2c_del_driver(&imx074_i2c_driver); +-} +- +-module_init(imx074_mod_init); +-module_exit(imx074_mod_exit); ++module_i2c_driver(imx074_i2c_driver); + + MODULE_DESCRIPTION("Sony IMX074 Camera driver"); + MODULE_AUTHOR("Guennadi Liakhovetski "); +Index: linux-3.3.x86_64/drivers/media/video/indycam.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/indycam.c ++++ linux-3.3.x86_64/drivers/media/video/indycam.c +@@ -387,15 +387,4 @@ static struct i2c_driver indycam_driver + .id_table = indycam_id, + }; + +-static __init int init_indycam(void) +-{ +- return i2c_add_driver(&indycam_driver); +-} +- +-static __exit void exit_indycam(void) +-{ +- i2c_del_driver(&indycam_driver); +-} +- +-module_init(init_indycam); +-module_exit(exit_indycam); ++module_i2c_driver(indycam_driver); +Index: linux-3.3.x86_64/drivers/media/video/ir-kbd-i2c.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ir-kbd-i2c.c ++++ linux-3.3.x86_64/drivers/media/video/ir-kbd-i2c.c +@@ -471,7 +471,7 @@ static const struct i2c_device_id ir_kbd + { } + }; + +-static struct i2c_driver driver = { ++static struct i2c_driver ir_kbd_driver = { + .driver = { + .name = "ir-kbd-i2c", + }, +@@ -480,21 +480,10 @@ static struct i2c_driver driver = { + .id_table = ir_kbd_id, + }; + ++module_i2c_driver(ir_kbd_driver); ++ + /* ----------------------------------------------------------------------- */ + + MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Mueller"); + MODULE_DESCRIPTION("input driver for i2c IR remote controls"); + MODULE_LICENSE("GPL"); +- +-static int __init ir_init(void) +-{ +- return i2c_add_driver(&driver); +-} +- +-static void __exit ir_fini(void) +-{ +- i2c_del_driver(&driver); +-} +- +-module_init(ir_init); +-module_exit(ir_fini); +Index: linux-3.3.x86_64/drivers/media/video/ks0127.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ks0127.c ++++ linux-3.3.x86_64/drivers/media/video/ks0127.c +@@ -721,15 +721,4 @@ static struct i2c_driver ks0127_driver = + .id_table = ks0127_id, + }; + +-static __init int init_ks0127(void) +-{ +- return i2c_add_driver(&ks0127_driver); +-} +- +-static __exit void exit_ks0127(void) +-{ +- i2c_del_driver(&ks0127_driver); +-} +- +-module_init(init_ks0127); +-module_exit(exit_ks0127); ++module_i2c_driver(ks0127_driver); +Index: linux-3.3.x86_64/drivers/media/video/m52790.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/m52790.c ++++ linux-3.3.x86_64/drivers/media/video/m52790.c +@@ -213,15 +213,4 @@ static struct i2c_driver m52790_driver = + .id_table = m52790_id, + }; + +-static __init int init_m52790(void) +-{ +- return i2c_add_driver(&m52790_driver); +-} +- +-static __exit void exit_m52790(void) +-{ +- i2c_del_driver(&m52790_driver); +-} +- +-module_init(init_m52790); +-module_exit(exit_m52790); ++module_i2c_driver(m52790_driver); +Index: linux-3.3.x86_64/drivers/media/video/msp3400-driver.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/msp3400-driver.c ++++ linux-3.3.x86_64/drivers/media/video/msp3400-driver.c +@@ -881,18 +881,7 @@ static struct i2c_driver msp_driver = { + .id_table = msp_id, + }; + +-static __init int init_msp(void) +-{ +- return i2c_add_driver(&msp_driver); +-} +- +-static __exit void exit_msp(void) +-{ +- i2c_del_driver(&msp_driver); +-} +- +-module_init(init_msp); +-module_exit(exit_msp); ++module_i2c_driver(msp_driver); + + /* + * Overrides for Emacs so that we follow Linus's tabbing style. +Index: linux-3.3.x86_64/drivers/media/video/mt9m001.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9m001.c ++++ linux-3.3.x86_64/drivers/media/video/mt9m001.c +@@ -730,18 +730,7 @@ static struct i2c_driver mt9m001_i2c_dri + .id_table = mt9m001_id, + }; + +-static int __init mt9m001_mod_init(void) +-{ +- return i2c_add_driver(&mt9m001_i2c_driver); +-} +- +-static void __exit mt9m001_mod_exit(void) +-{ +- i2c_del_driver(&mt9m001_i2c_driver); +-} +- +-module_init(mt9m001_mod_init); +-module_exit(mt9m001_mod_exit); ++module_i2c_driver(mt9m001_i2c_driver); + + MODULE_DESCRIPTION("Micron MT9M001 Camera driver"); + MODULE_AUTHOR("Guennadi Liakhovetski "); +Index: linux-3.3.x86_64/drivers/media/video/mt9m111.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9m111.c ++++ linux-3.3.x86_64/drivers/media/video/mt9m111.c +@@ -1008,18 +1008,7 @@ static struct i2c_driver mt9m111_i2c_dri + .id_table = mt9m111_id, + }; + +-static int __init mt9m111_mod_init(void) +-{ +- return i2c_add_driver(&mt9m111_i2c_driver); +-} +- +-static void __exit mt9m111_mod_exit(void) +-{ +- i2c_del_driver(&mt9m111_i2c_driver); +-} +- +-module_init(mt9m111_mod_init); +-module_exit(mt9m111_mod_exit); ++module_i2c_driver(mt9m111_i2c_driver); + + MODULE_DESCRIPTION("Micron/Aptina MT9M111/MT9M112/MT9M131 Camera driver"); + MODULE_AUTHOR("Robert Jarzmik"); +Index: linux-3.3.x86_64/drivers/media/video/mt9p031.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9p031.c ++++ linux-3.3.x86_64/drivers/media/video/mt9p031.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + + #include +@@ -28,6 +27,8 @@ + #include + #include + ++#include "aptina-pll.h" ++ + #define MT9P031_PIXEL_ARRAY_WIDTH 2752 + #define MT9P031_PIXEL_ARRAY_HEIGHT 2004 + +@@ -98,14 +99,6 @@ + #define MT9P031_TEST_PATTERN_RED 0xa2 + #define MT9P031_TEST_PATTERN_BLUE 0xa3 + +-struct mt9p031_pll_divs { +- u32 ext_freq; +- u32 target_freq; +- u8 m; +- u8 n; +- u8 p1; +-}; +- + struct mt9p031 { + struct v4l2_subdev subdev; + struct media_pad pad; +@@ -115,10 +108,8 @@ struct mt9p031 { + struct mt9p031_platform_data *pdata; + struct mutex power_lock; /* lock to protect power_count */ + int power_count; +- u16 xskip; +- u16 yskip; + +- const struct mt9p031_pll_divs *pll; ++ struct aptina_pll pll; + + /* Registers cache */ + u16 output_control; +@@ -186,33 +177,31 @@ static int mt9p031_reset(struct mt9p031 + 0); + } + +-/* +- * This static table uses ext_freq and vdd_io values to select suitable +- * PLL dividers m, n and p1 which have been calculated as specifiec in p36 +- * of Aptina's mt9p031 datasheet. New values should be added here. +- */ +-static const struct mt9p031_pll_divs mt9p031_divs[] = { +- /* ext_freq target_freq m n p1 */ +- {21000000, 48000000, 26, 2, 6} +-}; +- +-static int mt9p031_pll_get_divs(struct mt9p031 *mt9p031) ++static int mt9p031_pll_setup(struct mt9p031 *mt9p031) + { ++ static const struct aptina_pll_limits limits = { ++ .ext_clock_min = 6000000, ++ .ext_clock_max = 27000000, ++ .int_clock_min = 2000000, ++ .int_clock_max = 13500000, ++ .out_clock_min = 180000000, ++ .out_clock_max = 360000000, ++ .pix_clock_max = 96000000, ++ .n_min = 1, ++ .n_max = 64, ++ .m_min = 16, ++ .m_max = 255, ++ .p1_min = 1, ++ .p1_max = 128, ++ }; ++ + struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); +- int i; ++ struct mt9p031_platform_data *pdata = mt9p031->pdata; + +- for (i = 0; i < ARRAY_SIZE(mt9p031_divs); i++) { +- if (mt9p031_divs[i].ext_freq == mt9p031->pdata->ext_freq && +- mt9p031_divs[i].target_freq == mt9p031->pdata->target_freq) { +- mt9p031->pll = &mt9p031_divs[i]; +- return 0; +- } +- } ++ mt9p031->pll.ext_clock = pdata->ext_freq; ++ mt9p031->pll.pix_clock = pdata->target_freq; + +- dev_err(&client->dev, "Couldn't find PLL dividers for ext_freq = %d, " +- "target_freq = %d\n", mt9p031->pdata->ext_freq, +- mt9p031->pdata->target_freq); +- return -EINVAL; ++ return aptina_pll_calculate(&client->dev, &limits, &mt9p031->pll); + } + + static int mt9p031_pll_enable(struct mt9p031 *mt9p031) +@@ -226,11 +215,11 @@ static int mt9p031_pll_enable(struct mt9 + return ret; + + ret = mt9p031_write(client, MT9P031_PLL_CONFIG_1, +- (mt9p031->pll->m << 8) | (mt9p031->pll->n - 1)); ++ (mt9p031->pll.m << 8) | (mt9p031->pll.n - 1)); + if (ret < 0) + return ret; + +- ret = mt9p031_write(client, MT9P031_PLL_CONFIG_2, mt9p031->pll->p1 - 1); ++ ret = mt9p031_write(client, MT9P031_PLL_CONFIG_2, mt9p031->pll.p1 - 1); + if (ret < 0) + return ret; + +@@ -785,8 +774,6 @@ static int mt9p031_open(struct v4l2_subd + format->field = V4L2_FIELD_NONE; + format->colorspace = V4L2_COLORSPACE_SRGB; + +- mt9p031->xskip = 1; +- mt9p031->yskip = 1; + return mt9p031_set_power(subdev, 1); + } + +@@ -905,7 +892,7 @@ static int mt9p031_probe(struct i2c_clie + mt9p031->format.field = V4L2_FIELD_NONE; + mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB; + +- ret = mt9p031_pll_get_divs(mt9p031); ++ ret = mt9p031_pll_setup(mt9p031); + + done: + if (ret < 0) { +@@ -945,18 +932,7 @@ static struct i2c_driver mt9p031_i2c_dri + .id_table = mt9p031_id, + }; + +-static int __init mt9p031_mod_init(void) +-{ +- return i2c_add_driver(&mt9p031_i2c_driver); +-} +- +-static void __exit mt9p031_mod_exit(void) +-{ +- i2c_del_driver(&mt9p031_i2c_driver); +-} +- +-module_init(mt9p031_mod_init); +-module_exit(mt9p031_mod_exit); ++module_i2c_driver(mt9p031_i2c_driver); + + MODULE_DESCRIPTION("Aptina MT9P031 Camera driver"); + MODULE_AUTHOR("Bastian Hecht "); +Index: linux-3.3.x86_64/drivers/media/video/mt9t001.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9t001.c ++++ linux-3.3.x86_64/drivers/media/video/mt9t001.c +@@ -817,18 +817,7 @@ static struct i2c_driver mt9t001_driver + .id_table = mt9t001_id, + }; + +-static int __init mt9t001_init(void) +-{ +- return i2c_add_driver(&mt9t001_driver); +-} +- +-static void __exit mt9t001_exit(void) +-{ +- i2c_del_driver(&mt9t001_driver); +-} +- +-module_init(mt9t001_init); +-module_exit(mt9t001_exit); ++module_i2c_driver(mt9t001_driver); + + MODULE_DESCRIPTION("Aptina (Micron) MT9T001 Camera driver"); + MODULE_AUTHOR("Laurent Pinchart "); +Index: linux-3.3.x86_64/drivers/media/video/mt9t031.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9t031.c ++++ linux-3.3.x86_64/drivers/media/video/mt9t031.c +@@ -850,18 +850,7 @@ static struct i2c_driver mt9t031_i2c_dri + .id_table = mt9t031_id, + }; + +-static int __init mt9t031_mod_init(void) +-{ +- return i2c_add_driver(&mt9t031_i2c_driver); +-} +- +-static void __exit mt9t031_mod_exit(void) +-{ +- i2c_del_driver(&mt9t031_i2c_driver); +-} +- +-module_init(mt9t031_mod_init); +-module_exit(mt9t031_mod_exit); ++module_i2c_driver(mt9t031_i2c_driver); + + MODULE_DESCRIPTION("Micron MT9T031 Camera driver"); + MODULE_AUTHOR("Guennadi Liakhovetski "); +Index: linux-3.3.x86_64/drivers/media/video/mt9t112.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9t112.c ++++ linux-3.3.x86_64/drivers/media/video/mt9t112.c +@@ -1117,21 +1117,7 @@ static struct i2c_driver mt9t112_i2c_dri + .id_table = mt9t112_id, + }; + +-/************************************************************************ +- module function +-************************************************************************/ +-static int __init mt9t112_module_init(void) +-{ +- return i2c_add_driver(&mt9t112_i2c_driver); +-} +- +-static void __exit mt9t112_module_exit(void) +-{ +- i2c_del_driver(&mt9t112_i2c_driver); +-} +- +-module_init(mt9t112_module_init); +-module_exit(mt9t112_module_exit); ++module_i2c_driver(mt9t112_i2c_driver); + + MODULE_DESCRIPTION("SoC Camera driver for mt9t112"); + MODULE_AUTHOR("Kuninori Morimoto"); +Index: linux-3.3.x86_64/drivers/media/video/mt9v011.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9v011.c ++++ linux-3.3.x86_64/drivers/media/video/mt9v011.c +@@ -709,15 +709,4 @@ static struct i2c_driver mt9v011_driver + .id_table = mt9v011_id, + }; + +-static __init int init_mt9v011(void) +-{ +- return i2c_add_driver(&mt9v011_driver); +-} +- +-static __exit void exit_mt9v011(void) +-{ +- i2c_del_driver(&mt9v011_driver); +-} +- +-module_init(init_mt9v011); +-module_exit(exit_mt9v011); ++module_i2c_driver(mt9v011_driver); +Index: linux-3.3.x86_64/drivers/media/video/mt9v022.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9v022.c ++++ linux-3.3.x86_64/drivers/media/video/mt9v022.c +@@ -872,18 +872,7 @@ static struct i2c_driver mt9v022_i2c_dri + .id_table = mt9v022_id, + }; + +-static int __init mt9v022_mod_init(void) +-{ +- return i2c_add_driver(&mt9v022_i2c_driver); +-} +- +-static void __exit mt9v022_mod_exit(void) +-{ +- i2c_del_driver(&mt9v022_i2c_driver); +-} +- +-module_init(mt9v022_mod_init); +-module_exit(mt9v022_mod_exit); ++module_i2c_driver(mt9v022_i2c_driver); + + MODULE_DESCRIPTION("Micron MT9V022 Camera driver"); + MODULE_AUTHOR("Guennadi Liakhovetski "); +Index: linux-3.3.x86_64/drivers/media/video/mt9v032.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mt9v032.c ++++ linux-3.3.x86_64/drivers/media/video/mt9v032.c +@@ -756,18 +756,7 @@ static struct i2c_driver mt9v032_driver + .id_table = mt9v032_id, + }; + +-static int __init mt9v032_init(void) +-{ +- return i2c_add_driver(&mt9v032_driver); +-} +- +-static void __exit mt9v032_exit(void) +-{ +- i2c_del_driver(&mt9v032_driver); +-} +- +-module_init(mt9v032_init); +-module_exit(mt9v032_exit); ++module_i2c_driver(mt9v032_driver); + + MODULE_DESCRIPTION("Aptina MT9V032 Camera driver"); + MODULE_AUTHOR("Laurent Pinchart "); +Index: linux-3.3.x86_64/drivers/media/video/ov2640.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ov2640.c ++++ linux-3.3.x86_64/drivers/media/video/ov2640.c +@@ -1103,21 +1103,7 @@ static struct i2c_driver ov2640_i2c_driv + .id_table = ov2640_id, + }; + +-/* +- * Module functions +- */ +-static int __init ov2640_module_init(void) +-{ +- return i2c_add_driver(&ov2640_i2c_driver); +-} +- +-static void __exit ov2640_module_exit(void) +-{ +- i2c_del_driver(&ov2640_i2c_driver); +-} +- +-module_init(ov2640_module_init); +-module_exit(ov2640_module_exit); ++module_i2c_driver(ov2640_i2c_driver); + + MODULE_DESCRIPTION("SoC Camera driver for Omni Vision 2640 sensor"); + MODULE_AUTHOR("Alberto Panizzo"); +Index: linux-3.3.x86_64/drivers/media/video/ov5642.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ov5642.c ++++ linux-3.3.x86_64/drivers/media/video/ov5642.c +@@ -1068,18 +1068,7 @@ static struct i2c_driver ov5642_i2c_driv + .id_table = ov5642_id, + }; + +-static int __init ov5642_mod_init(void) +-{ +- return i2c_add_driver(&ov5642_i2c_driver); +-} +- +-static void __exit ov5642_mod_exit(void) +-{ +- i2c_del_driver(&ov5642_i2c_driver); +-} +- +-module_init(ov5642_mod_init); +-module_exit(ov5642_mod_exit); ++module_i2c_driver(ov5642_i2c_driver); + + MODULE_DESCRIPTION("Omnivision OV5642 Camera driver"); + MODULE_AUTHOR("Bastian Hecht "); +Index: linux-3.3.x86_64/drivers/media/video/ov7670.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ov7670.c ++++ linux-3.3.x86_64/drivers/media/video/ov7670.c +@@ -1583,15 +1583,4 @@ static struct i2c_driver ov7670_driver = + .id_table = ov7670_id, + }; + +-static __init int init_ov7670(void) +-{ +- return i2c_add_driver(&ov7670_driver); +-} +- +-static __exit void exit_ov7670(void) +-{ +- i2c_del_driver(&ov7670_driver); +-} +- +-module_init(init_ov7670); +-module_exit(exit_ov7670); ++module_i2c_driver(ov7670_driver); +Index: linux-3.3.x86_64/drivers/media/video/ov772x.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ov772x.c ++++ linux-3.3.x86_64/drivers/media/video/ov772x.c +@@ -1123,22 +1123,7 @@ static struct i2c_driver ov772x_i2c_driv + .id_table = ov772x_id, + }; + +-/* +- * module function +- */ +- +-static int __init ov772x_module_init(void) +-{ +- return i2c_add_driver(&ov772x_i2c_driver); +-} +- +-static void __exit ov772x_module_exit(void) +-{ +- i2c_del_driver(&ov772x_i2c_driver); +-} +- +-module_init(ov772x_module_init); +-module_exit(ov772x_module_exit); ++module_i2c_driver(ov772x_i2c_driver); + + MODULE_DESCRIPTION("SoC Camera driver for ov772x"); + MODULE_AUTHOR("Kuninori Morimoto"); +Index: linux-3.3.x86_64/drivers/media/video/ov9640.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ov9640.c ++++ linux-3.3.x86_64/drivers/media/video/ov9640.c +@@ -738,18 +738,7 @@ static struct i2c_driver ov9640_i2c_driv + .id_table = ov9640_id, + }; + +-static int __init ov9640_module_init(void) +-{ +- return i2c_add_driver(&ov9640_i2c_driver); +-} +- +-static void __exit ov9640_module_exit(void) +-{ +- i2c_del_driver(&ov9640_i2c_driver); +-} +- +-module_init(ov9640_module_init); +-module_exit(ov9640_module_exit); ++module_i2c_driver(ov9640_i2c_driver); + + MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV96xx"); + MODULE_AUTHOR("Marek Vasut "); +Index: linux-3.3.x86_64/drivers/media/video/ov9740.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ov9740.c ++++ linux-3.3.x86_64/drivers/media/video/ov9740.c +@@ -998,18 +998,7 @@ static struct i2c_driver ov9740_i2c_driv + .id_table = ov9740_id, + }; + +-static int __init ov9740_module_init(void) +-{ +- return i2c_add_driver(&ov9740_i2c_driver); +-} +- +-static void __exit ov9740_module_exit(void) +-{ +- i2c_del_driver(&ov9740_i2c_driver); +-} +- +-module_init(ov9740_module_init); +-module_exit(ov9740_module_exit); ++module_i2c_driver(ov9740_i2c_driver); + + MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV9740"); + MODULE_AUTHOR("Andrew Chew "); +Index: linux-3.3.x86_64/drivers/media/video/rj54n1cb0c.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/rj54n1cb0c.c ++++ linux-3.3.x86_64/drivers/media/video/rj54n1cb0c.c +@@ -1407,18 +1407,7 @@ static struct i2c_driver rj54n1_i2c_driv + .id_table = rj54n1_id, + }; + +-static int __init rj54n1_mod_init(void) +-{ +- return i2c_add_driver(&rj54n1_i2c_driver); +-} +- +-static void __exit rj54n1_mod_exit(void) +-{ +- i2c_del_driver(&rj54n1_i2c_driver); +-} +- +-module_init(rj54n1_mod_init); +-module_exit(rj54n1_mod_exit); ++module_i2c_driver(rj54n1_i2c_driver); + + MODULE_DESCRIPTION("Sharp RJ54N1CB0C Camera driver"); + MODULE_AUTHOR("Guennadi Liakhovetski "); +Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/hdmiphy_drv.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/hdmiphy_drv.c ++++ linux-3.3.x86_64/drivers/media/video/s5p-tv/hdmiphy_drv.c +@@ -175,14 +175,4 @@ static struct i2c_driver hdmiphy_driver + .id_table = hdmiphy_id, + }; + +-static int __init hdmiphy_init(void) +-{ +- return i2c_add_driver(&hdmiphy_driver); +-} +-module_init(hdmiphy_init); +- +-static void __exit hdmiphy_exit(void) +-{ +- i2c_del_driver(&hdmiphy_driver); +-} +-module_exit(hdmiphy_exit); ++module_i2c_driver(hdmiphy_driver); +Index: linux-3.3.x86_64/drivers/media/video/saa6588.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa6588.c ++++ linux-3.3.x86_64/drivers/media/video/saa6588.c +@@ -539,15 +539,4 @@ static struct i2c_driver saa6588_driver + .id_table = saa6588_id, + }; + +-static __init int init_saa6588(void) +-{ +- return i2c_add_driver(&saa6588_driver); +-} +- +-static __exit void exit_saa6588(void) +-{ +- i2c_del_driver(&saa6588_driver); +-} +- +-module_init(init_saa6588); +-module_exit(exit_saa6588); ++module_i2c_driver(saa6588_driver); +Index: linux-3.3.x86_64/drivers/media/video/saa7110.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7110.c ++++ linux-3.3.x86_64/drivers/media/video/saa7110.c +@@ -491,15 +491,4 @@ static struct i2c_driver saa7110_driver + .id_table = saa7110_id, + }; + +-static __init int init_saa7110(void) +-{ +- return i2c_add_driver(&saa7110_driver); +-} +- +-static __exit void exit_saa7110(void) +-{ +- i2c_del_driver(&saa7110_driver); +-} +- +-module_init(init_saa7110); +-module_exit(exit_saa7110); ++module_i2c_driver(saa7110_driver); +Index: linux-3.3.x86_64/drivers/media/video/saa7115.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7115.c ++++ linux-3.3.x86_64/drivers/media/video/saa7115.c +@@ -1724,15 +1724,4 @@ static struct i2c_driver saa711x_driver + .id_table = saa711x_id, + }; + +-static __init int init_saa711x(void) +-{ +- return i2c_add_driver(&saa711x_driver); +-} +- +-static __exit void exit_saa711x(void) +-{ +- i2c_del_driver(&saa711x_driver); +-} +- +-module_init(init_saa711x); +-module_exit(exit_saa711x); ++module_i2c_driver(saa711x_driver); +Index: linux-3.3.x86_64/drivers/media/video/saa7127.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7127.c ++++ linux-3.3.x86_64/drivers/media/video/saa7127.c +@@ -852,15 +852,4 @@ static struct i2c_driver saa7127_driver + .id_table = saa7127_id, + }; + +-static __init int init_saa7127(void) +-{ +- return i2c_add_driver(&saa7127_driver); +-} +- +-static __exit void exit_saa7127(void) +-{ +- i2c_del_driver(&saa7127_driver); +-} +- +-module_init(init_saa7127); +-module_exit(exit_saa7127); ++module_i2c_driver(saa7127_driver); +Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa6752hs.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa6752hs.c ++++ linux-3.3.x86_64/drivers/media/video/saa7134/saa6752hs.c +@@ -1001,18 +1001,7 @@ static struct i2c_driver saa6752hs_drive + .id_table = saa6752hs_id, + }; + +-static __init int init_saa6752hs(void) +-{ +- return i2c_add_driver(&saa6752hs_driver); +-} +- +-static __exit void exit_saa6752hs(void) +-{ +- i2c_del_driver(&saa6752hs_driver); +-} +- +-module_init(init_saa6752hs); +-module_exit(exit_saa6752hs); ++module_i2c_driver(saa6752hs_driver); + + /* + * Overrides for Emacs so that we follow Linus's tabbing style. +Index: linux-3.3.x86_64/drivers/media/video/saa717x.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa717x.c ++++ linux-3.3.x86_64/drivers/media/video/saa717x.c +@@ -1375,15 +1375,4 @@ static struct i2c_driver saa717x_driver + .id_table = saa717x_id, + }; + +-static __init int init_saa717x(void) +-{ +- return i2c_add_driver(&saa717x_driver); +-} +- +-static __exit void exit_saa717x(void) +-{ +- i2c_del_driver(&saa717x_driver); +-} +- +-module_init(init_saa717x); +-module_exit(exit_saa717x); ++module_i2c_driver(saa717x_driver); +Index: linux-3.3.x86_64/drivers/media/video/saa7185.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7185.c ++++ linux-3.3.x86_64/drivers/media/video/saa7185.c +@@ -374,15 +374,4 @@ static struct i2c_driver saa7185_driver + .id_table = saa7185_id, + }; + +-static __init int init_saa7185(void) +-{ +- return i2c_add_driver(&saa7185_driver); +-} +- +-static __exit void exit_saa7185(void) +-{ +- i2c_del_driver(&saa7185_driver); +-} +- +-module_init(init_saa7185); +-module_exit(exit_saa7185); ++module_i2c_driver(saa7185_driver); +Index: linux-3.3.x86_64/drivers/media/video/saa7191.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7191.c ++++ linux-3.3.x86_64/drivers/media/video/saa7191.c +@@ -656,15 +656,4 @@ static struct i2c_driver saa7191_driver + .id_table = saa7191_id, + }; + +-static __init int init_saa7191(void) +-{ +- return i2c_add_driver(&saa7191_driver); +-} +- +-static __exit void exit_saa7191(void) +-{ +- i2c_del_driver(&saa7191_driver); +-} +- +-module_init(init_saa7191); +-module_exit(exit_saa7191); ++module_i2c_driver(saa7191_driver); +Index: linux-3.3.x86_64/drivers/media/video/sr030pc30.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/sr030pc30.c ++++ linux-3.3.x86_64/drivers/media/video/sr030pc30.c +@@ -864,18 +864,7 @@ static struct i2c_driver sr030pc30_i2c_d + .id_table = sr030pc30_id, + }; + +-static int __init sr030pc30_init(void) +-{ +- return i2c_add_driver(&sr030pc30_i2c_driver); +-} +- +-static void __exit sr030pc30_exit(void) +-{ +- i2c_del_driver(&sr030pc30_i2c_driver); +-} +- +-module_init(sr030pc30_init); +-module_exit(sr030pc30_exit); ++module_i2c_driver(sr030pc30_i2c_driver); + + MODULE_DESCRIPTION("Siliconfile SR030PC30 camera driver"); + MODULE_AUTHOR("Sylwester Nawrocki "); +Index: linux-3.3.x86_64/drivers/media/video/tda7432.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tda7432.c ++++ linux-3.3.x86_64/drivers/media/video/tda7432.c +@@ -482,15 +482,4 @@ static struct i2c_driver tda7432_driver + .id_table = tda7432_id, + }; + +-static __init int init_tda7432(void) +-{ +- return i2c_add_driver(&tda7432_driver); +-} +- +-static __exit void exit_tda7432(void) +-{ +- i2c_del_driver(&tda7432_driver); +-} +- +-module_init(init_tda7432); +-module_exit(exit_tda7432); ++module_i2c_driver(tda7432_driver); +Index: linux-3.3.x86_64/drivers/media/video/tda9840.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tda9840.c ++++ linux-3.3.x86_64/drivers/media/video/tda9840.c +@@ -208,15 +208,4 @@ static struct i2c_driver tda9840_driver + .id_table = tda9840_id, + }; + +-static __init int init_tda9840(void) +-{ +- return i2c_add_driver(&tda9840_driver); +-} +- +-static __exit void exit_tda9840(void) +-{ +- i2c_del_driver(&tda9840_driver); +-} +- +-module_init(init_tda9840); +-module_exit(exit_tda9840); ++module_i2c_driver(tda9840_driver); +Index: linux-3.3.x86_64/drivers/media/video/tea6415c.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tea6415c.c ++++ linux-3.3.x86_64/drivers/media/video/tea6415c.c +@@ -184,15 +184,4 @@ static struct i2c_driver tea6415c_driver + .id_table = tea6415c_id, + }; + +-static __init int init_tea6415c(void) +-{ +- return i2c_add_driver(&tea6415c_driver); +-} +- +-static __exit void exit_tea6415c(void) +-{ +- i2c_del_driver(&tea6415c_driver); +-} +- +-module_init(init_tea6415c); +-module_exit(exit_tea6415c); ++module_i2c_driver(tea6415c_driver); +Index: linux-3.3.x86_64/drivers/media/video/tea6420.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tea6420.c ++++ linux-3.3.x86_64/drivers/media/video/tea6420.c +@@ -166,15 +166,4 @@ static struct i2c_driver tea6420_driver + .id_table = tea6420_id, + }; + +-static __init int init_tea6420(void) +-{ +- return i2c_add_driver(&tea6420_driver); +-} +- +-static __exit void exit_tea6420(void) +-{ +- i2c_del_driver(&tea6420_driver); +-} +- +-module_init(init_tea6420); +-module_exit(exit_tea6420); ++module_i2c_driver(tea6420_driver); +Index: linux-3.3.x86_64/drivers/media/video/ths7303.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ths7303.c ++++ linux-3.3.x86_64/drivers/media/video/ths7303.c +@@ -137,16 +137,4 @@ static struct i2c_driver ths7303_driver + .id_table = ths7303_id, + }; + +-static int __init ths7303_init(void) +-{ +- return i2c_add_driver(&ths7303_driver); +-} +- +-static void __exit ths7303_exit(void) +-{ +- i2c_del_driver(&ths7303_driver); +-} +- +-module_init(ths7303_init); +-module_exit(ths7303_exit); +- ++module_i2c_driver(ths7303_driver); +Index: linux-3.3.x86_64/drivers/media/video/tlv320aic23b.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tlv320aic23b.c ++++ linux-3.3.x86_64/drivers/media/video/tlv320aic23b.c +@@ -227,15 +227,4 @@ static struct i2c_driver tlv320aic23b_dr + .id_table = tlv320aic23b_id, + }; + +-static __init int init_tlv320aic23b(void) +-{ +- return i2c_add_driver(&tlv320aic23b_driver); +-} +- +-static __exit void exit_tlv320aic23b(void) +-{ +- i2c_del_driver(&tlv320aic23b_driver); +-} +- +-module_init(init_tlv320aic23b); +-module_exit(exit_tlv320aic23b); ++module_i2c_driver(tlv320aic23b_driver); +Index: linux-3.3.x86_64/drivers/media/video/tvaudio.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tvaudio.c ++++ linux-3.3.x86_64/drivers/media/video/tvaudio.c +@@ -2078,15 +2078,4 @@ static struct i2c_driver tvaudio_driver + .id_table = tvaudio_id, + }; + +-static __init int init_tvaudio(void) +-{ +- return i2c_add_driver(&tvaudio_driver); +-} +- +-static __exit void exit_tvaudio(void) +-{ +- i2c_del_driver(&tvaudio_driver); +-} +- +-module_init(init_tvaudio); +-module_exit(exit_tvaudio); ++module_i2c_driver(tvaudio_driver); +Index: linux-3.3.x86_64/drivers/media/video/tvp514x.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tvp514x.c ++++ linux-3.3.x86_64/drivers/media/video/tvp514x.c +@@ -1163,15 +1163,4 @@ static struct i2c_driver tvp514x_driver + .id_table = tvp514x_id, + }; + +-static int __init tvp514x_init(void) +-{ +- return i2c_add_driver(&tvp514x_driver); +-} +- +-static void __exit tvp514x_exit(void) +-{ +- i2c_del_driver(&tvp514x_driver); +-} +- +-module_init(tvp514x_init); +-module_exit(tvp514x_exit); ++module_i2c_driver(tvp514x_driver); +Index: linux-3.3.x86_64/drivers/media/video/tvp5150.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tvp5150.c ++++ linux-3.3.x86_64/drivers/media/video/tvp5150.c +@@ -17,6 +17,13 @@ + + #include "tvp5150_reg.h" + ++#define TVP5150_H_MAX 720 ++#define TVP5150_V_MAX_525_60 480 ++#define TVP5150_V_MAX_OTHERS 576 ++#define TVP5150_MAX_CROP_LEFT 511 ++#define TVP5150_MAX_CROP_TOP 127 ++#define TVP5150_CROP_SHIFT 2 ++ + MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); + MODULE_AUTHOR("Mauro Carvalho Chehab"); + MODULE_LICENSE("GPL"); +@@ -29,6 +36,7 @@ MODULE_PARM_DESC(debug, "Debug level (0- + struct tvp5150 { + struct v4l2_subdev sd; + struct v4l2_ctrl_handler hdl; ++ struct v4l2_rect rect; + + v4l2_std_id norm; /* Current set standard */ + u32 input; +@@ -732,6 +740,13 @@ static int tvp5150_s_std(struct v4l2_sub + if (decoder->norm == std) + return 0; + ++ /* Change cropping height limits */ ++ if (std & V4L2_STD_525_60) ++ decoder->rect.height = TVP5150_V_MAX_525_60; ++ else ++ decoder->rect.height = TVP5150_V_MAX_OTHERS; ++ ++ + return tvp5150_set_std(sd, std); + } + +@@ -828,11 +843,8 @@ static int tvp5150_mbus_fmt(struct v4l2_ + else + std = decoder->norm; + +- f->width = 720; +- if (std & V4L2_STD_525_60) +- f->height = 480; +- else +- f->height = 576; ++ f->width = decoder->rect.width; ++ f->height = decoder->rect.height; + + f->code = V4L2_MBUS_FMT_YUYV8_2X8; + f->field = V4L2_FIELD_SEQ_TB; +@@ -843,6 +855,99 @@ static int tvp5150_mbus_fmt(struct v4l2_ + return 0; + } + ++static int tvp5150_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) ++{ ++ struct v4l2_rect rect = a->c; ++ struct tvp5150 *decoder = to_tvp5150(sd); ++ v4l2_std_id std; ++ int hmax; ++ ++ v4l2_dbg(1, debug, sd, "%s left=%d, top=%d, width=%d, height=%d\n", ++ __func__, rect.left, rect.top, rect.width, rect.height); ++ ++ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ /* tvp5150 has some special limits */ ++ rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT); ++ rect.width = clamp(rect.width, ++ TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect.left, ++ TVP5150_H_MAX - rect.left); ++ rect.top = clamp(rect.top, 0, TVP5150_MAX_CROP_TOP); ++ ++ /* Calculate height based on current standard */ ++ if (decoder->norm == V4L2_STD_ALL) ++ std = tvp5150_read_std(sd); ++ else ++ std = decoder->norm; ++ ++ if (std & V4L2_STD_525_60) ++ hmax = TVP5150_V_MAX_525_60; ++ else ++ hmax = TVP5150_V_MAX_OTHERS; ++ ++ rect.height = clamp(rect.height, ++ hmax - TVP5150_MAX_CROP_TOP - rect.top, ++ hmax - rect.top); ++ ++ tvp5150_write(sd, TVP5150_VERT_BLANKING_START, rect.top); ++ tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP, ++ rect.top + rect.height - hmax); ++ tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_MSB, ++ rect.left >> TVP5150_CROP_SHIFT); ++ tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_LSB, ++ rect.left | (1 << TVP5150_CROP_SHIFT)); ++ tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_MSB, ++ (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >> ++ TVP5150_CROP_SHIFT); ++ tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_LSB, ++ rect.left + rect.width - TVP5150_MAX_CROP_LEFT); ++ ++ decoder->rect = rect; ++ ++ return 0; ++} ++ ++static int tvp5150_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) ++{ ++ struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd); ++ ++ a->c = decoder->rect; ++ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ ++ return 0; ++} ++ ++static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) ++{ ++ struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd); ++ v4l2_std_id std; ++ ++ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ a->bounds.left = 0; ++ a->bounds.top = 0; ++ a->bounds.width = TVP5150_H_MAX; ++ ++ /* Calculate height based on current standard */ ++ if (decoder->norm == V4L2_STD_ALL) ++ std = tvp5150_read_std(sd); ++ else ++ std = decoder->norm; ++ ++ if (std & V4L2_STD_525_60) ++ a->bounds.height = TVP5150_V_MAX_525_60; ++ else ++ a->bounds.height = TVP5150_V_MAX_OTHERS; ++ ++ a->defrect = a->bounds; ++ a->pixelaspect.numerator = 1; ++ a->pixelaspect.denominator = 1; ++ ++ return 0; ++} ++ + /**************************************************************************** + I2C Command + ****************************************************************************/ +@@ -998,6 +1103,10 @@ static const struct v4l2_subdev_video_op + .enum_mbus_fmt = tvp5150_enum_mbus_fmt, + .s_mbus_fmt = tvp5150_mbus_fmt, + .try_mbus_fmt = tvp5150_mbus_fmt, ++ .g_mbus_fmt = tvp5150_mbus_fmt, ++ .s_crop = tvp5150_s_crop, ++ .g_crop = tvp5150_g_crop, ++ .cropcap = tvp5150_cropcap, + }; + + static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { +@@ -1083,6 +1192,15 @@ static int tvp5150_probe(struct i2c_clie + } + v4l2_ctrl_handler_setup(&core->hdl); + ++ /* Default is no cropping */ ++ core->rect.top = 0; ++ if (tvp5150_read_std(sd) & V4L2_STD_525_60) ++ core->rect.height = TVP5150_V_MAX_525_60; ++ else ++ core->rect.height = TVP5150_V_MAX_OTHERS; ++ core->rect.left = 0; ++ core->rect.width = TVP5150_H_MAX; ++ + if (debug > 1) + tvp5150_log_status(sd); + return 0; +@@ -1121,15 +1239,4 @@ static struct i2c_driver tvp5150_driver + .id_table = tvp5150_id, + }; + +-static __init int init_tvp5150(void) +-{ +- return i2c_add_driver(&tvp5150_driver); +-} +- +-static __exit void exit_tvp5150(void) +-{ +- i2c_del_driver(&tvp5150_driver); +-} +- +-module_init(init_tvp5150); +-module_exit(exit_tvp5150); ++module_i2c_driver(tvp5150_driver); +Index: linux-3.3.x86_64/drivers/media/video/tvp7002.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tvp7002.c ++++ linux-3.3.x86_64/drivers/media/video/tvp7002.c +@@ -1069,27 +1069,4 @@ static struct i2c_driver tvp7002_driver + .id_table = tvp7002_id, + }; + +-/* +- * tvp7002_init - Initialize driver via I2C interface +- * +- * Register the TVP7002 driver. +- * Return 0 on success or error code on failure. +- */ +-static int __init tvp7002_init(void) +-{ +- return i2c_add_driver(&tvp7002_driver); +-} +- +-/* +- * tvp7002_exit - Remove driver via I2C interface +- * +- * Unregister the TVP7002 driver. +- * Returns nothing. +- */ +-static void __exit tvp7002_exit(void) +-{ +- i2c_del_driver(&tvp7002_driver); +-} +- +-module_init(tvp7002_init); +-module_exit(tvp7002_exit); ++module_i2c_driver(tvp7002_driver); +Index: linux-3.3.x86_64/drivers/media/video/tw9910.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/tw9910.c ++++ linux-3.3.x86_64/drivers/media/video/tw9910.c +@@ -951,21 +951,7 @@ static struct i2c_driver tw9910_i2c_driv + .id_table = tw9910_id, + }; + +-/* +- * module function +- */ +-static int __init tw9910_module_init(void) +-{ +- return i2c_add_driver(&tw9910_i2c_driver); +-} +- +-static void __exit tw9910_module_exit(void) +-{ +- i2c_del_driver(&tw9910_i2c_driver); +-} +- +-module_init(tw9910_module_init); +-module_exit(tw9910_module_exit); ++module_i2c_driver(tw9910_i2c_driver); + + MODULE_DESCRIPTION("SoC Camera driver for tw9910"); + MODULE_AUTHOR("Kuninori Morimoto"); +Index: linux-3.3.x86_64/drivers/media/video/upd64031a.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/upd64031a.c ++++ linux-3.3.x86_64/drivers/media/video/upd64031a.c +@@ -271,15 +271,4 @@ static struct i2c_driver upd64031a_drive + .id_table = upd64031a_id, + }; + +-static __init int init_upd64031a(void) +-{ +- return i2c_add_driver(&upd64031a_driver); +-} +- +-static __exit void exit_upd64031a(void) +-{ +- i2c_del_driver(&upd64031a_driver); +-} +- +-module_init(init_upd64031a); +-module_exit(exit_upd64031a); ++module_i2c_driver(upd64031a_driver); +Index: linux-3.3.x86_64/drivers/media/video/upd64083.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/upd64083.c ++++ linux-3.3.x86_64/drivers/media/video/upd64083.c +@@ -243,15 +243,4 @@ static struct i2c_driver upd64083_driver + .id_table = upd64083_id, + }; + +-static __init int init_upd64083(void) +-{ +- return i2c_add_driver(&upd64083_driver); +-} +- +-static __exit void exit_upd64083(void) +-{ +- i2c_del_driver(&upd64083_driver); +-} +- +-module_init(init_upd64083); +-module_exit(exit_upd64083); ++module_i2c_driver(upd64083_driver); +Index: linux-3.3.x86_64/drivers/media/video/vp27smpx.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/vp27smpx.c ++++ linux-3.3.x86_64/drivers/media/video/vp27smpx.c +@@ -208,15 +208,4 @@ static struct i2c_driver vp27smpx_driver + .id_table = vp27smpx_id, + }; + +-static __init int init_vp27smpx(void) +-{ +- return i2c_add_driver(&vp27smpx_driver); +-} +- +-static __exit void exit_vp27smpx(void) +-{ +- i2c_del_driver(&vp27smpx_driver); +-} +- +-module_init(init_vp27smpx); +-module_exit(exit_vp27smpx); ++module_i2c_driver(vp27smpx_driver); +Index: linux-3.3.x86_64/drivers/media/video/vpx3220.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/vpx3220.c ++++ linux-3.3.x86_64/drivers/media/video/vpx3220.c +@@ -588,15 +588,4 @@ static struct i2c_driver vpx3220_driver + .id_table = vpx3220_id, + }; + +-static __init int init_vpx3220(void) +-{ +- return i2c_add_driver(&vpx3220_driver); +-} +- +-static __exit void exit_vpx3220(void) +-{ +- i2c_del_driver(&vpx3220_driver); +-} +- +-module_init(init_vpx3220); +-module_exit(exit_vpx3220); ++module_i2c_driver(vpx3220_driver); +Index: linux-3.3.x86_64/drivers/media/video/wm8739.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/wm8739.c ++++ linux-3.3.x86_64/drivers/media/video/wm8739.c +@@ -291,15 +291,4 @@ static struct i2c_driver wm8739_driver = + .id_table = wm8739_id, + }; + +-static __init int init_wm8739(void) +-{ +- return i2c_add_driver(&wm8739_driver); +-} +- +-static __exit void exit_wm8739(void) +-{ +- i2c_del_driver(&wm8739_driver); +-} +- +-module_init(init_wm8739); +-module_exit(exit_wm8739); ++module_i2c_driver(wm8739_driver); +Index: linux-3.3.x86_64/drivers/media/video/wm8775.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/wm8775.c ++++ linux-3.3.x86_64/drivers/media/video/wm8775.c +@@ -339,15 +339,4 @@ static struct i2c_driver wm8775_driver = + .id_table = wm8775_id, + }; + +-static __init int init_wm8775(void) +-{ +- return i2c_add_driver(&wm8775_driver); +-} +- +-static __exit void exit_wm8775(void) +-{ +- i2c_del_driver(&wm8775_driver); +-} +- +-module_init(init_wm8775); +-module_exit(exit_wm8775); ++module_i2c_driver(wm8775_driver); +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe-priv.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/it913x-fe-priv.h ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe-priv.h +@@ -201,6 +201,11 @@ fe_modulation_t fe_con[] = { + QAM_64, + }; + ++enum { ++ PRIORITY_HIGH = 0, /* High-priority stream */ ++ PRIORITY_LOW, /* Low-priority stream */ ++}; ++ + /* Standard demodulator functions */ + static struct it913xset set_solo_fe[] = { + {PRO_LINK, GPIOH5_EN, {0x01}, 0x01}, +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/it913x-fe.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe.c +@@ -57,6 +57,7 @@ struct it913x_fe_state { + u32 frequency; + fe_modulation_t constellation; + fe_transmit_mode_t transmission_mode; ++ u8 priority; + u32 crystalFrequency; + u32 adcFrequency; + u8 tuner_type; +@@ -500,19 +501,87 @@ static int it913x_fe_read_status(struct + return 0; + } + ++/* FEC values based on fe_code_rate_t non supported values 0*/ ++int it913x_qpsk_pval[] = {0, -93, -91, -90, 0, -89, -88}; ++int it913x_16qam_pval[] = {0, -87, -85, -84, 0, -83, -82}; ++int it913x_64qam_pval[] = {0, -82, -80, -78, 0, -77, -76}; ++ ++static int it913x_get_signal_strength(struct dvb_frontend *fe) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ struct it913x_fe_state *state = fe->demodulator_priv; ++ u8 code_rate; ++ int ret, temp; ++ u8 lna_gain_os; ++ ++ ret = it913x_read_reg_u8(state, VAR_P_INBAND); ++ if (ret < 0) ++ return ret; ++ ++ /* VHF/UHF gain offset */ ++ if (state->frequency < 300000000) ++ lna_gain_os = 7; ++ else ++ lna_gain_os = 14; ++ ++ temp = (ret - 100) - lna_gain_os; ++ ++ if (state->priority == PRIORITY_HIGH) ++ code_rate = p->code_rate_HP; ++ else ++ code_rate = p->code_rate_LP; ++ ++ if (code_rate >= ARRAY_SIZE(it913x_qpsk_pval)) ++ return -EINVAL; ++ ++ deb_info("Reg VAR_P_INBAND:%d Calc Offset Value:%d", ret, temp); ++ ++ /* Apply FEC offset values*/ ++ switch (p->modulation) { ++ case QPSK: ++ temp -= it913x_qpsk_pval[code_rate]; ++ break; ++ case QAM_16: ++ temp -= it913x_16qam_pval[code_rate]; ++ break; ++ case QAM_64: ++ temp -= it913x_64qam_pval[code_rate]; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (temp < -15) ++ ret = 0; ++ else if ((-15 <= temp) && (temp < 0)) ++ ret = (2 * (temp + 15)) / 3; ++ else if ((0 <= temp) && (temp < 20)) ++ ret = 4 * temp + 10; ++ else if ((20 <= temp) && (temp < 35)) ++ ret = (2 * (temp - 20)) / 3 + 90; ++ else if (temp >= 35) ++ ret = 100; ++ ++ deb_info("Signal Strength :%d", ret); ++ ++ return ret; ++} ++ + static int it913x_fe_read_signal_strength(struct dvb_frontend *fe, + u16 *strength) + { + struct it913x_fe_state *state = fe->demodulator_priv; +- int ret = it913x_read_reg_u8(state, SIGNAL_LEVEL); +- /*SIGNAL_LEVEL always returns 100%! so using FE_HAS_SIGNAL as switch*/ +- if (state->it913x_status & FE_HAS_SIGNAL) +- ret = (ret * 0xff) / 0x64; +- else +- ret = 0x0; +- ret |= ret << 0x8; +- *strength = ret; +- return 0; ++ int ret = 0; ++ if (state->config->read_slevel) { ++ if (state->it913x_status & FE_HAS_SIGNAL) ++ ret = it913x_read_reg_u8(state, SIGNAL_LEVEL); ++ } else ++ ret = it913x_get_signal_strength(fe); ++ ++ if (ret >= 0) ++ *strength = (u16)((u32)ret * 0xffff / 0x64); ++ ++ return (ret < 0) ? -ENODEV : 0; + } + + static int it913x_fe_read_snr(struct dvb_frontend *fe, u16 *snr) +@@ -606,6 +675,8 @@ static int it913x_fe_get_frontend(struct + if (reg[2] < 4) + p->hierarchy = fe_hi[reg[2]]; + ++ state->priority = reg[5]; ++ + p->code_rate_HP = (reg[6] < 6) ? fe_code[reg[6]] : FEC_NONE; + p->code_rate_LP = (reg[7] < 6) ? fe_code[reg[7]] : FEC_NONE; + +@@ -972,5 +1043,5 @@ static struct dvb_frontend_ops it913x_fe + + MODULE_DESCRIPTION("it913x Frontend and it9137 tuner"); + MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); +-MODULE_VERSION("1.13"); ++MODULE_VERSION("1.15"); + MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/it913x-fe.h ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe.h +@@ -34,6 +34,8 @@ struct ite_config { + u8 tuner_id_1; + u8 dual_mode; + u8 adf; ++ /* option to read SIGNAL_LEVEL */ ++ u8 read_slevel; + }; + + #if defined(CONFIG_DVB_IT913X_FE) || (defined(CONFIG_DVB_IT913X_FE_MODULE) && \ +@@ -168,6 +170,8 @@ static inline struct dvb_frontend *it913 + #define EST_SIGNAL_LEVEL 0x004a + #define FREE_BAND 0x004b + #define SUSPEND_FLAG 0x004c ++#define VAR_P_INBAND 0x00f7 ++ + /* Build in tuner types */ + #define IT9137 0x38 + #define IT9135_38 0x38 +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/cx22702.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/cx22702.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/cx22702.c +@@ -502,10 +502,26 @@ static int cx22702_read_signal_strength( + u16 *signal_strength) + { + struct cx22702_state *state = fe->demodulator_priv; ++ u8 reg23; + +- u16 rs_ber; +- rs_ber = cx22702_readreg(state, 0x23); +- *signal_strength = (rs_ber << 8) | rs_ber; ++ /* ++ * Experience suggests that the strength signal register works as ++ * follows: ++ * - In the absence of signal, value is 0xff. ++ * - In the presence of a weak signal, bit 7 is set, not sure what ++ * the lower 7 bits mean. ++ * - In the presence of a strong signal, the register holds a 7-bit ++ * value (bit 7 is cleared), with greater values standing for ++ * weaker signals. ++ */ ++ reg23 = cx22702_readreg(state, 0x23); ++ if (reg23 & 0x80) { ++ *signal_strength = 0; ++ } else { ++ reg23 = ~reg23 & 0x7f; ++ /* Scale to 16 bit */ ++ *signal_strength = (reg23 << 9) | (reg23 << 2) | (reg23 >> 5); ++ } + + return 0; + } +Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-cards.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx-cards.c ++++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-cards.c +@@ -353,6 +353,44 @@ static struct em28xx_reg_seq hauppauge_9 + }; + #endif + ++/* 1b80:e425 MaxMedia UB425-TC ++ * GPIO_6 - demod reset, 0=active ++ * GPIO_7 - LED, 0=active ++ */ ++static struct em28xx_reg_seq maxmedia_ub425_tc[] = { ++ {EM2874_R80_GPIO, 0x83, 0xff, 100}, ++ {EM2874_R80_GPIO, 0xc3, 0xff, 100}, /* GPIO_6 = 1 */ ++ {EM2874_R80_GPIO, 0x43, 0xff, 000}, /* GPIO_7 = 0 */ ++ {-1, -1, -1, -1}, ++}; ++ ++/* 2304:0242 PCTV QuatroStick (510e) ++ * GPIO_2: decoder reset, 0=active ++ * GPIO_4: decoder suspend, 0=active ++ * GPIO_6: demod reset, 0=active ++ * GPIO_7: LED, 1=active ++ */ ++static struct em28xx_reg_seq pctv_510e[] = { ++ {EM2874_R80_GPIO, 0x10, 0xff, 100}, ++ {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ ++ {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ ++ { -1, -1, -1, -1}, ++}; ++ ++/* 2013:0251 PCTV QuatroStick nano (520e) ++ * GPIO_2: decoder reset, 0=active ++ * GPIO_4: decoder suspend, 0=active ++ * GPIO_6: demod reset, 0=active ++ * GPIO_7: LED, 1=active ++ */ ++static struct em28xx_reg_seq pctv_520e[] = { ++ {EM2874_R80_GPIO, 0x10, 0xff, 100}, ++ {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ ++ {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ ++ {EM2874_R80_GPIO, 0xd4, 0xff, 000}, /* GPIO_7 = 1 */ ++ { -1, -1, -1, -1}, ++}; ++ + /* + * Board definitions + */ +@@ -1908,6 +1946,41 @@ struct em28xx_board em28xx_boards[] = { + .amux = EM28XX_AMUX_LINE_IN, + } }, + }, ++ /* 1b80:e425 MaxMedia UB425-TC ++ * Empia EM2874B + Micronas DRX 3913KA2 + NXP TDA18271HDC2 */ ++ [EM2874_BOARD_MAXMEDIA_UB425_TC] = { ++ .name = "MaxMedia UB425-TC", ++ .tuner_type = TUNER_ABSENT, ++ .tuner_gpio = maxmedia_ub425_tc, ++ .has_dvb = 1, ++ .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | ++ EM28XX_I2C_CLK_WAIT_ENABLE | ++ EM28XX_I2C_FREQ_400_KHZ, ++ }, ++ /* 2304:0242 PCTV QuatroStick (510e) ++ * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */ ++ [EM2884_BOARD_PCTV_510E] = { ++ .name = "PCTV QuatroStick (510e)", ++ .tuner_type = TUNER_ABSENT, ++ .tuner_gpio = pctv_510e, ++ .has_dvb = 1, ++ .ir_codes = RC_MAP_PINNACLE_PCTV_HD, ++ .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | ++ EM28XX_I2C_CLK_WAIT_ENABLE | ++ EM28XX_I2C_FREQ_400_KHZ, ++ }, ++ /* 2013:0251 PCTV QuatroStick nano (520e) ++ * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */ ++ [EM2884_BOARD_PCTV_520E] = { ++ .name = "PCTV QuatroStick nano (520e)", ++ .tuner_type = TUNER_ABSENT, ++ .tuner_gpio = pctv_520e, ++ .has_dvb = 1, ++ .ir_codes = RC_MAP_PINNACLE_PCTV_HD, ++ .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | ++ EM28XX_I2C_CLK_WAIT_ENABLE | ++ EM28XX_I2C_FREQ_400_KHZ, ++ }, + }; + const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); + +@@ -2059,6 +2132,12 @@ struct usb_device_id em28xx_id_table[] = + .driver_info = EM2860_BOARD_HT_VIDBOX_NW03 }, + { USB_DEVICE(0x1b80, 0xe309), /* Sveon STV40 */ + .driver_info = EM2860_BOARD_EASYCAP }, ++ { USB_DEVICE(0x1b80, 0xe425), ++ .driver_info = EM2874_BOARD_MAXMEDIA_UB425_TC }, ++ { USB_DEVICE(0x2304, 0x0242), ++ .driver_info = EM2884_BOARD_PCTV_510E }, ++ { USB_DEVICE(0x2013, 0x0251), ++ .driver_info = EM2884_BOARD_PCTV_520E }, + { }, + }; + MODULE_DEVICE_TABLE(usb, em28xx_id_table); +@@ -3122,7 +3201,6 @@ static int em28xx_usb_probe(struct usb_i + int i, nr; + const int ifnum = interface->altsetting[0].desc.bInterfaceNumber; + char *speed; +- char descr[255] = ""; + + udev = usb_get_dev(interface_to_usbdev(interface)); + +@@ -3227,21 +3305,11 @@ static int em28xx_usb_probe(struct usb_i + speed = "unknown"; + } + +- if (udev->manufacturer) +- strlcpy(descr, udev->manufacturer, sizeof(descr)); +- +- if (udev->product) { +- if (*descr) +- strlcat(descr, " ", sizeof(descr)); +- strlcat(descr, udev->product, sizeof(descr)); +- } +- +- if (*descr) +- strlcat(descr, " ", sizeof(descr)); +- + printk(KERN_INFO DRIVER_NAME +- ": New device %s@ %s Mbps (%04x:%04x, interface %d, class %d)\n", +- descr, ++ ": New device %s %s @ %s Mbps " ++ "(%04x:%04x, interface %d, class %d)\n", ++ udev->manufacturer ? udev->manufacturer : "", ++ udev->product ? udev->product : "", + speed, + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), +@@ -3307,6 +3375,17 @@ static int em28xx_usb_probe(struct usb_i + goto unlock_and_free; + } + ++ if (has_dvb) { ++ /* pre-allocate DVB isoc transfer buffers */ ++ retval = em28xx_alloc_isoc(dev, EM28XX_DIGITAL_MODE, ++ EM28XX_DVB_MAX_PACKETS, ++ EM28XX_DVB_NUM_BUFS, ++ dev->dvb_max_pkt_size); ++ if (retval) { ++ goto unlock_and_free; ++ } ++ } ++ + request_modules(dev); + + /* Should be the last thing to do, to avoid newer udev's to +@@ -3379,7 +3458,7 @@ static void em28xx_usb_disconnect(struct + video_device_node_name(dev->vdev)); + + dev->state |= DEV_MISCONFIGURED; +- em28xx_uninit_isoc(dev); ++ em28xx_uninit_isoc(dev, dev->mode); + dev->state |= DEV_DISCONNECTED; + wake_up_interruptible(&dev->wait_frame); + wake_up_interruptible(&dev->wait_stream); +@@ -3388,6 +3467,9 @@ static void em28xx_usb_disconnect(struct + em28xx_release_resources(dev); + } + ++ /* free DVB isoc buffers */ ++ em28xx_uninit_isoc(dev, EM28XX_DIGITAL_MODE); ++ + mutex_unlock(&dev->lock); + + em28xx_close_extension(dev); +Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx-core.c ++++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-core.c +@@ -666,6 +666,7 @@ int em28xx_capture_start(struct em28xx * + + return rc; + } ++EXPORT_SYMBOL_GPL(em28xx_capture_start); + + int em28xx_vbi_supported(struct em28xx *dev) + { +@@ -961,146 +962,192 @@ static void em28xx_irq_callback(struct u + /* + * Stop and Deallocate URBs + */ +-void em28xx_uninit_isoc(struct em28xx *dev) ++void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode) + { + struct urb *urb; ++ struct em28xx_usb_isoc_bufs *isoc_bufs; + int i; + +- em28xx_isocdbg("em28xx: called em28xx_uninit_isoc\n"); ++ em28xx_isocdbg("em28xx: called em28xx_uninit_isoc in mode %d\n", mode); ++ ++ if (mode == EM28XX_DIGITAL_MODE) ++ isoc_bufs = &dev->isoc_ctl.digital_bufs; ++ else ++ isoc_bufs = &dev->isoc_ctl.analog_bufs; + + dev->isoc_ctl.nfields = -1; +- for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { +- urb = dev->isoc_ctl.urb[i]; ++ for (i = 0; i < isoc_bufs->num_bufs; i++) { ++ urb = isoc_bufs->urb[i]; + if (urb) { + if (!irqs_disabled()) + usb_kill_urb(urb); + else + usb_unlink_urb(urb); + +- if (dev->isoc_ctl.transfer_buffer[i]) { ++ if (isoc_bufs->transfer_buffer[i]) { + usb_free_coherent(dev->udev, + urb->transfer_buffer_length, +- dev->isoc_ctl.transfer_buffer[i], ++ isoc_bufs->transfer_buffer[i], + urb->transfer_dma); + } + usb_free_urb(urb); +- dev->isoc_ctl.urb[i] = NULL; ++ isoc_bufs->urb[i] = NULL; + } +- dev->isoc_ctl.transfer_buffer[i] = NULL; ++ isoc_bufs->transfer_buffer[i] = NULL; + } + +- kfree(dev->isoc_ctl.urb); +- kfree(dev->isoc_ctl.transfer_buffer); ++ kfree(isoc_bufs->urb); ++ kfree(isoc_bufs->transfer_buffer); + +- dev->isoc_ctl.urb = NULL; +- dev->isoc_ctl.transfer_buffer = NULL; +- dev->isoc_ctl.num_bufs = 0; ++ isoc_bufs->urb = NULL; ++ isoc_bufs->transfer_buffer = NULL; ++ isoc_bufs->num_bufs = 0; + + em28xx_capture_start(dev, 0); + } + EXPORT_SYMBOL_GPL(em28xx_uninit_isoc); + + /* +- * Allocate URBs and start IRQ ++ * Allocate URBs + */ +-int em28xx_init_isoc(struct em28xx *dev, int max_packets, +- int num_bufs, int max_pkt_size, +- int (*isoc_copy) (struct em28xx *dev, struct urb *urb)) ++int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode, ++ int max_packets, int num_bufs, int max_pkt_size) + { +- struct em28xx_dmaqueue *dma_q = &dev->vidq; +- struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; ++ struct em28xx_usb_isoc_bufs *isoc_bufs; + int i; + int sb_size, pipe; + struct urb *urb; + int j, k; +- int rc; + +- em28xx_isocdbg("em28xx: called em28xx_prepare_isoc\n"); ++ em28xx_isocdbg("em28xx: called em28xx_alloc_isoc in mode %d\n", mode); ++ ++ if (mode == EM28XX_DIGITAL_MODE) ++ isoc_bufs = &dev->isoc_ctl.digital_bufs; ++ else ++ isoc_bufs = &dev->isoc_ctl.analog_bufs; + + /* De-allocates all pending stuff */ +- em28xx_uninit_isoc(dev); ++ em28xx_uninit_isoc(dev, mode); + +- dev->isoc_ctl.isoc_copy = isoc_copy; +- dev->isoc_ctl.num_bufs = num_bufs; ++ isoc_bufs->num_bufs = num_bufs; + +- dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); +- if (!dev->isoc_ctl.urb) { ++ isoc_bufs->urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); ++ if (!isoc_bufs->urb) { + em28xx_errdev("cannot alloc memory for usb buffers\n"); + return -ENOMEM; + } + +- dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, +- GFP_KERNEL); +- if (!dev->isoc_ctl.transfer_buffer) { ++ isoc_bufs->transfer_buffer = kzalloc(sizeof(void *)*num_bufs, ++ GFP_KERNEL); ++ if (!isoc_bufs->transfer_buffer) { + em28xx_errdev("cannot allocate memory for usb transfer\n"); +- kfree(dev->isoc_ctl.urb); ++ kfree(isoc_bufs->urb); + return -ENOMEM; + } + +- dev->isoc_ctl.max_pkt_size = max_pkt_size; ++ isoc_bufs->max_pkt_size = max_pkt_size; ++ isoc_bufs->num_packets = max_packets; + dev->isoc_ctl.vid_buf = NULL; + dev->isoc_ctl.vbi_buf = NULL; + +- sb_size = max_packets * dev->isoc_ctl.max_pkt_size; ++ sb_size = isoc_bufs->num_packets * isoc_bufs->max_pkt_size; + + /* allocate urbs and transfer buffers */ +- for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { +- urb = usb_alloc_urb(max_packets, GFP_KERNEL); ++ for (i = 0; i < isoc_bufs->num_bufs; i++) { ++ urb = usb_alloc_urb(isoc_bufs->num_packets, GFP_KERNEL); + if (!urb) { + em28xx_err("cannot alloc isoc_ctl.urb %i\n", i); +- em28xx_uninit_isoc(dev); ++ em28xx_uninit_isoc(dev, mode); + return -ENOMEM; + } +- dev->isoc_ctl.urb[i] = urb; ++ isoc_bufs->urb[i] = urb; + +- dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev, ++ isoc_bufs->transfer_buffer[i] = usb_alloc_coherent(dev->udev, + sb_size, GFP_KERNEL, &urb->transfer_dma); +- if (!dev->isoc_ctl.transfer_buffer[i]) { ++ if (!isoc_bufs->transfer_buffer[i]) { + em28xx_err("unable to allocate %i bytes for transfer" + " buffer %i%s\n", + sb_size, i, + in_interrupt() ? " while in int" : ""); +- em28xx_uninit_isoc(dev); ++ em28xx_uninit_isoc(dev, mode); + return -ENOMEM; + } +- memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); ++ memset(isoc_bufs->transfer_buffer[i], 0, sb_size); + + /* FIXME: this is a hack - should be + 'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK' + should also be using 'desc.bInterval' + */ + pipe = usb_rcvisocpipe(dev->udev, +- dev->mode == EM28XX_ANALOG_MODE ? ++ mode == EM28XX_ANALOG_MODE ? + EM28XX_EP_ANALOG : EM28XX_EP_DIGITAL); + + usb_fill_int_urb(urb, dev->udev, pipe, +- dev->isoc_ctl.transfer_buffer[i], sb_size, ++ isoc_bufs->transfer_buffer[i], sb_size, + em28xx_irq_callback, dev, 1); + +- urb->number_of_packets = max_packets; ++ urb->number_of_packets = isoc_bufs->num_packets; + urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; + + k = 0; +- for (j = 0; j < max_packets; j++) { ++ for (j = 0; j < isoc_bufs->num_packets; j++) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = +- dev->isoc_ctl.max_pkt_size; +- k += dev->isoc_ctl.max_pkt_size; ++ isoc_bufs->max_pkt_size; ++ k += isoc_bufs->max_pkt_size; + } + } + ++ return 0; ++} ++EXPORT_SYMBOL_GPL(em28xx_alloc_isoc); ++ ++/* ++ * Allocate URBs and start IRQ ++ */ ++int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode, ++ int max_packets, int num_bufs, int max_pkt_size, ++ int (*isoc_copy) (struct em28xx *dev, struct urb *urb)) ++{ ++ struct em28xx_dmaqueue *dma_q = &dev->vidq; ++ struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; ++ struct em28xx_usb_isoc_bufs *isoc_bufs; ++ int i; ++ int rc; ++ int alloc; ++ ++ em28xx_isocdbg("em28xx: called em28xx_init_isoc in mode %d\n", mode); ++ ++ dev->isoc_ctl.isoc_copy = isoc_copy; ++ ++ if (mode == EM28XX_DIGITAL_MODE) { ++ isoc_bufs = &dev->isoc_ctl.digital_bufs; ++ /* no need to free/alloc isoc buffers in digital mode */ ++ alloc = 0; ++ } else { ++ isoc_bufs = &dev->isoc_ctl.analog_bufs; ++ alloc = 1; ++ } ++ ++ if (alloc) { ++ rc = em28xx_alloc_isoc(dev, mode, max_packets, ++ num_bufs, max_pkt_size); ++ if (rc) ++ return rc; ++ } ++ + init_waitqueue_head(&dma_q->wq); + init_waitqueue_head(&vbi_dma_q->wq); + + em28xx_capture_start(dev, 1); + + /* submit urbs and enables IRQ */ +- for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { +- rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); ++ for (i = 0; i < isoc_bufs->num_bufs; i++) { ++ rc = usb_submit_urb(isoc_bufs->urb[i], GFP_ATOMIC); + if (rc) { + em28xx_err("submit of urb %i failed (error=%i)\n", i, + rc); +- em28xx_uninit_isoc(dev); ++ em28xx_uninit_isoc(dev, mode); + return rc; + } + } +Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-dvb.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx-dvb.c ++++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-dvb.c +@@ -61,9 +61,6 @@ if (debug >= level) \ + printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \ + } while (0) + +-#define EM28XX_DVB_NUM_BUFS 5 +-#define EM28XX_DVB_MAX_PACKETS 64 +- + struct em28xx_dvb { + struct dvb_frontend *fe[2]; + +@@ -172,20 +169,21 @@ static int em28xx_start_streaming(struct + max_dvb_packet_size = dev->dvb_max_pkt_size; + if (max_dvb_packet_size < 0) + return max_dvb_packet_size; +- dprintk(1, "Using %d buffers each with %d bytes\n", ++ dprintk(1, "Using %d buffers each with %d x %d bytes\n", + EM28XX_DVB_NUM_BUFS, ++ EM28XX_DVB_MAX_PACKETS, + max_dvb_packet_size); + +- return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS, +- EM28XX_DVB_NUM_BUFS, max_dvb_packet_size, +- em28xx_dvb_isoc_copy); ++ return em28xx_init_isoc(dev, EM28XX_DIGITAL_MODE, ++ EM28XX_DVB_MAX_PACKETS, EM28XX_DVB_NUM_BUFS, ++ max_dvb_packet_size, em28xx_dvb_isoc_copy); + } + + static int em28xx_stop_streaming(struct em28xx_dvb *dvb) + { + struct em28xx *dev = dvb->adapter.priv; + +- em28xx_uninit_isoc(dev); ++ em28xx_capture_start(dev, 0); + + em28xx_set_mode(dev, EM28XX_SUSPEND); + +@@ -327,6 +325,19 @@ struct drxk_config hauppauge_930c_drxk = + .chunk_size = 56, + }; + ++struct drxk_config maxmedia_ub425_tc_drxk = { ++ .adr = 0x29, ++ .single_master = 1, ++ .no_i2c_bridge = 1, ++}; ++ ++struct drxk_config pctv_520e_drxk = { ++ .adr = 0x29, ++ .single_master = 1, ++ .microcode_name = "dvb-demod-drxk-pctv.fw", ++ .chunk_size = 58, ++}; ++ + static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) + { + struct em28xx_dvb *dvb = fe->sec_priv; +@@ -460,6 +471,33 @@ static void terratec_h5_init(struct em28 + em28xx_gpio_set(dev, terratec_h5_end); + }; + ++static void pctv_520e_init(struct em28xx *dev) ++{ ++ /* ++ * Init TDA8295(?) analog demodulator. Looks like I2C traffic to ++ * digital demodulator and tuner are routed via TDA8295. ++ */ ++ int i; ++ struct { ++ unsigned char r[4]; ++ int len; ++ } regs[] = { ++ {{ 0x06, 0x02, 0x00, 0x31 }, 4}, ++ {{ 0x01, 0x02 }, 2}, ++ {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, ++ {{ 0x01, 0x00 }, 2}, ++ {{ 0x01, 0x00, 0xff, 0xaf }, 4}, ++ {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, ++ {{ 0x01, 0x00 }, 2}, ++ {{ 0x01, 0x00, 0x73, 0xaf }, 4}, ++ }; ++ ++ dev->i2c_client.addr = 0x82 >> 1; /* 0x41 */ ++ ++ for (i = 0; i < ARRAY_SIZE(regs); i++) ++ i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); ++}; ++ + static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe) + { + /* Values extracted from a USB trace of the Terratec Windows driver */ +@@ -938,6 +976,48 @@ static int em28xx_dvb_init(struct em28xx + dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap, + &em28xx_a8293_config); + break; ++ case EM2874_BOARD_MAXMEDIA_UB425_TC: ++ /* attach demodulator */ ++ dvb->fe[0] = dvb_attach(drxk_attach, &maxmedia_ub425_tc_drxk, ++ &dev->i2c_adap); ++ ++ if (dvb->fe[0]) { ++ /* disable I2C-gate */ ++ dvb->fe[0]->ops.i2c_gate_ctrl = NULL; ++ ++ /* attach tuner */ ++ if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], ++ &dev->i2c_adap, 0x60)) { ++ dvb_frontend_detach(dvb->fe[0]); ++ result = -EINVAL; ++ goto out_free; ++ } ++ } ++ ++ /* TODO: we need drx-3913k firmware in order to support DVB-T */ ++ em28xx_info("MaxMedia UB425-TC: only DVB-C supported by that " \ ++ "driver version\n"); ++ ++ break; ++ case EM2884_BOARD_PCTV_510E: ++ case EM2884_BOARD_PCTV_520E: ++ pctv_520e_init(dev); ++ ++ /* attach demodulator */ ++ dvb->fe[0] = dvb_attach(drxk_attach, &pctv_520e_drxk, ++ &dev->i2c_adap); ++ ++ if (dvb->fe[0]) { ++ /* attach tuner */ ++ if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, ++ &dev->i2c_adap, ++ &em28xx_cxd2820r_tda18271_config)) { ++ dvb_frontend_detach(dvb->fe[0]); ++ result = -EINVAL; ++ goto out_free; ++ } ++ } ++ break; + default: + em28xx_errdev("/2: The frontend of your DVB/ATSC card" + " isn't supported yet\n"); +Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-video.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx-video.c ++++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-video.c +@@ -760,17 +760,19 @@ buffer_prepare(struct videobuf_queue *vq + goto fail; + } + +- if (!dev->isoc_ctl.num_bufs) ++ if (!dev->isoc_ctl.analog_bufs.num_bufs) + urb_init = 1; + + if (urb_init) { + if (em28xx_vbi_supported(dev) == 1) +- rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS, ++ rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE, ++ EM28XX_NUM_PACKETS, + EM28XX_NUM_BUFS, + dev->max_pkt_size, + em28xx_isoc_copy_vbi); + else +- rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS, ++ rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE, ++ EM28XX_NUM_PACKETS, + EM28XX_NUM_BUFS, + dev->max_pkt_size, + em28xx_isoc_copy); +@@ -2267,7 +2269,7 @@ static int em28xx_v4l2_close(struct file + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); + + /* do this before setting alternate! */ +- em28xx_uninit_isoc(dev); ++ em28xx_uninit_isoc(dev, EM28XX_ANALOG_MODE); + em28xx_set_mode(dev, EM28XX_SUSPEND); + + /* set alternate 0 */ +Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx.h ++++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx.h +@@ -125,6 +125,9 @@ + #define EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C 81 + #define EM2884_BOARD_CINERGY_HTC_STICK 82 + #define EM2860_BOARD_HT_VIDBOX_NW03 83 ++#define EM2874_BOARD_MAXMEDIA_UB425_TC 84 ++#define EM2884_BOARD_PCTV_510E 85 ++#define EM2884_BOARD_PCTV_520E 86 + + /* Limits minimum and default number of buffers */ + #define EM28XX_MIN_BUF 4 +@@ -151,12 +154,14 @@ + + /* number of buffers for isoc transfers */ + #define EM28XX_NUM_BUFS 5 ++#define EM28XX_DVB_NUM_BUFS 5 + + /* number of packets for each buffer + windows requests only 64 packets .. so we better do the same + this is what I found out for all alternate numbers there! + */ + #define EM28XX_NUM_PACKETS 64 ++#define EM28XX_DVB_MAX_PACKETS 64 + + #define EM28XX_INTERLACED_DEFAULT 1 + +@@ -197,10 +202,13 @@ enum em28xx_mode { + + struct em28xx; + +-struct em28xx_usb_isoc_ctl { ++struct em28xx_usb_isoc_bufs { + /* max packet size of isoc transaction */ + int max_pkt_size; + ++ /* number of packets in each buffer */ ++ int num_packets; ++ + /* number of allocated urbs */ + int num_bufs; + +@@ -209,6 +217,14 @@ struct em28xx_usb_isoc_ctl { + + /* transfer buffers for isoc transfer */ + char **transfer_buffer; ++}; ++ ++struct em28xx_usb_isoc_ctl { ++ /* isoc transfer buffers for analog mode */ ++ struct em28xx_usb_isoc_bufs analog_bufs; ++ ++ /* isoc transfer buffers for digital mode */ ++ struct em28xx_usb_isoc_bufs digital_bufs; + + /* Last buffer command and region */ + u8 cmd; +@@ -600,9 +616,6 @@ struct em28xx { + unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ + int dvb_alt; /* alternate for DVB */ + unsigned int dvb_max_pkt_size; /* wMaxPacketSize for DVB */ +- struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ +- char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc +- transfer */ + char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ + + /* helper funcs that call usb_control_msg */ +@@ -676,10 +689,12 @@ int em28xx_vbi_supported(struct em28xx * + int em28xx_set_outfmt(struct em28xx *dev); + int em28xx_resolution_set(struct em28xx *dev); + int em28xx_set_alternate(struct em28xx *dev); +-int em28xx_init_isoc(struct em28xx *dev, int max_packets, +- int num_bufs, int max_pkt_size, ++int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode, ++ int max_packets, int num_bufs, int max_pkt_size); ++int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode, ++ int max_packets, int num_bufs, int max_pkt_size, + int (*isoc_copy) (struct em28xx *dev, struct urb *urb)); +-void em28xx_uninit_isoc(struct em28xx *dev); ++void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode); + int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev); + int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode); + int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); +Index: linux-3.3.x86_64/drivers/media/video/mx2_camera.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/mx2_camera.c ++++ linux-3.3.x86_64/drivers/media/video/mx2_camera.c +@@ -3,6 +3,7 @@ + * + * Copyright (C) 2008, Sascha Hauer, Pengutronix + * Copyright (C) 2010, Baruch Siach, Orex Computed Radiography ++ * Copyright (C) 2012, Javier Martin, Vista Silicon S.L. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -18,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -30,17 +32,14 @@ + + #include + #include +-#include +-#include ++#include ++#include + #include + #include + + #include + + #include +-#ifdef CONFIG_MACH_MX27 +-#include +-#endif + #include + + #include +@@ -206,10 +205,23 @@ + #define PRP_INTR_LBOVF (1 << 7) + #define PRP_INTR_CH2OVF (1 << 8) + +-#define mx27_camera_emma(pcdev) (cpu_is_mx27() && pcdev->use_emma) ++/* Resizing registers */ ++#define PRP_RZ_VALID_TBL_LEN(x) ((x) << 24) ++#define PRP_RZ_VALID_BILINEAR (1 << 31) + + #define MAX_VIDEO_MEM 16 + ++#define RESIZE_NUM_MIN 1 ++#define RESIZE_NUM_MAX 20 ++#define BC_COEF 3 ++#define SZ_COEF (1 << BC_COEF) ++ ++#define RESIZE_DIR_H 0 ++#define RESIZE_DIR_V 1 ++ ++#define RESIZE_ALGO_BILINEAR 0 ++#define RESIZE_ALGO_AVERAGING 1 ++ + struct mx2_prp_cfg { + int channel; + u32 in_fmt; +@@ -219,6 +231,13 @@ struct mx2_prp_cfg { + u32 irq_flags; + }; + ++/* prp resizing parameters */ ++struct emma_prp_resize { ++ int algo; /* type of algorithm used */ ++ int len; /* number of coefficients */ ++ unsigned char s[RESIZE_NUM_MAX]; /* table of coefficients */ ++}; ++ + /* prp configuration for a client-host fmt pair */ + struct mx2_fmt_cfg { + enum v4l2_mbus_pixelcode in_fmt; +@@ -226,6 +245,26 @@ struct mx2_fmt_cfg { + struct mx2_prp_cfg cfg; + }; + ++enum mx2_buffer_state { ++ MX2_STATE_QUEUED, ++ MX2_STATE_ACTIVE, ++ MX2_STATE_DONE, ++}; ++ ++struct mx2_buf_internal { ++ struct list_head queue; ++ int bufnum; ++ bool discard; ++}; ++ ++/* buffer for one video frame */ ++struct mx2_buffer { ++ /* common v4l buffer stuff -- must be first */ ++ struct vb2_buffer vb; ++ enum mx2_buffer_state state; ++ struct mx2_buf_internal internal; ++}; ++ + struct mx2_camera_dev { + struct device *dev; + struct soc_camera_host soc_host; +@@ -242,6 +281,7 @@ struct mx2_camera_dev { + + struct list_head capture; + struct list_head active_bufs; ++ struct list_head discard; + + spinlock_t lock; + +@@ -250,26 +290,23 @@ struct mx2_camera_dev { + struct mx2_buffer *fb1_active; + struct mx2_buffer *fb2_active; + +- int use_emma; +- + u32 csicr1; + ++ struct mx2_buf_internal buf_discard[2]; + void *discard_buffer; + dma_addr_t discard_buffer_dma; + size_t discard_size; + struct mx2_fmt_cfg *emma_prp; ++ struct emma_prp_resize resizing[2]; ++ unsigned int s_width, s_height; + u32 frame_count; ++ struct vb2_alloc_ctx *alloc_ctx; + }; + +-/* buffer for one video frame */ +-struct mx2_buffer { +- /* common v4l buffer stuff -- must be first */ +- struct videobuf_buffer vb; +- +- enum v4l2_mbus_pixelcode code; +- +- int bufnum; +-}; ++static struct mx2_buffer *mx2_ibuf_to_buf(struct mx2_buf_internal *int_buf) ++{ ++ return container_of(int_buf, struct mx2_buffer, internal); ++} + + static struct mx2_fmt_cfg mx27_emma_prp_table[] = { + /* +@@ -324,13 +361,36 @@ static struct mx2_fmt_cfg *mx27_emma_prp + return &mx27_emma_prp_table[0]; + }; + ++static void mx27_update_emma_buf(struct mx2_camera_dev *pcdev, ++ unsigned long phys, int bufnum) ++{ ++ struct mx2_fmt_cfg *prp = pcdev->emma_prp; ++ ++ if (prp->cfg.channel == 1) { ++ writel(phys, pcdev->base_emma + ++ PRP_DEST_RGB1_PTR + 4 * bufnum); ++ } else { ++ writel(phys, pcdev->base_emma + ++ PRP_DEST_Y_PTR - 0x14 * bufnum); ++ if (prp->out_fmt == V4L2_PIX_FMT_YUV420) { ++ u32 imgsize = pcdev->icd->user_height * ++ pcdev->icd->user_width; ++ ++ writel(phys + imgsize, pcdev->base_emma + ++ PRP_DEST_CB_PTR - 0x14 * bufnum); ++ writel(phys + ((5 * imgsize) / 4), pcdev->base_emma + ++ PRP_DEST_CR_PTR - 0x14 * bufnum); ++ } ++ } ++} ++ + static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) + { + unsigned long flags; + + clk_disable(pcdev->clk_csi); + writel(0, pcdev->base_csi + CSICR1); +- if (mx27_camera_emma(pcdev)) { ++ if (cpu_is_mx27()) { + writel(0, pcdev->base_emma + PRP_CNTL); + } else if (cpu_is_mx25()) { + spin_lock_irqsave(&pcdev->lock, flags); +@@ -362,7 +422,7 @@ static int mx2_camera_add_device(struct + + csicr1 = CSICR1_MCLKEN; + +- if (mx27_camera_emma(pcdev)) { ++ if (cpu_is_mx27()) { + csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC | + CSICR1_RXFF_LEVEL(0); + } else if (cpu_is_mx27()) +@@ -392,56 +452,13 @@ static void mx2_camera_remove_device(str + + mx2_camera_deactivate(pcdev); + +- if (pcdev->discard_buffer) { +- dma_free_coherent(ici->v4l2_dev.dev, pcdev->discard_size, +- pcdev->discard_buffer, +- pcdev->discard_buffer_dma); +- pcdev->discard_buffer = NULL; +- } +- + pcdev->icd = NULL; + } + +-#ifdef CONFIG_MACH_MX27 +-static void mx27_camera_dma_enable(struct mx2_camera_dev *pcdev) +-{ +- u32 tmp; +- +- imx_dma_enable(pcdev->dma); +- +- tmp = readl(pcdev->base_csi + CSICR1); +- tmp |= CSICR1_RF_OR_INTEN; +- writel(tmp, pcdev->base_csi + CSICR1); +-} +- +-static irqreturn_t mx27_camera_irq(int irq_csi, void *data) +-{ +- struct mx2_camera_dev *pcdev = data; +- u32 status = readl(pcdev->base_csi + CSISR); +- +- if (status & CSISR_SOF_INT && pcdev->active) { +- u32 tmp; +- +- tmp = readl(pcdev->base_csi + CSICR1); +- writel(tmp | CSICR1_CLR_RXFIFO, pcdev->base_csi + CSICR1); +- mx27_camera_dma_enable(pcdev); +- } +- +- writel(CSISR_SOF_INT | CSISR_RFF_OR_INT, pcdev->base_csi + CSISR); +- +- return IRQ_HANDLED; +-} +-#else +-static irqreturn_t mx27_camera_irq(int irq_csi, void *data) +-{ +- return IRQ_NONE; +-} +-#endif /* CONFIG_MACH_MX27 */ +- + static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb, + int state) + { +- struct videobuf_buffer *vb; ++ struct vb2_buffer *vb; + struct mx2_buffer *buf; + struct mx2_buffer **fb_active = fb == 1 ? &pcdev->fb1_active : + &pcdev->fb2_active; +@@ -454,25 +471,24 @@ static void mx25_camera_frame_done(struc + goto out; + + vb = &(*fb_active)->vb; +- dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +- vb, vb->baddr, vb->bsize); +- +- vb->state = state; +- do_gettimeofday(&vb->ts); +- vb->field_count++; ++ dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, ++ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); + +- wake_up(&vb->done); ++ do_gettimeofday(&vb->v4l2_buf.timestamp); ++ vb->v4l2_buf.sequence++; ++ vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + + if (list_empty(&pcdev->capture)) { + buf = NULL; + writel(0, pcdev->base_csi + fb_reg); + } else { +- buf = list_entry(pcdev->capture.next, struct mx2_buffer, +- vb.queue); ++ buf = list_first_entry(&pcdev->capture, struct mx2_buffer, ++ internal.queue); + vb = &buf->vb; +- list_del(&vb->queue); +- vb->state = VIDEOBUF_ACTIVE; +- writel(videobuf_to_dma_contig(vb), pcdev->base_csi + fb_reg); ++ list_del(&buf->internal.queue); ++ buf->state = MX2_STATE_ACTIVE; ++ writel(vb2_dma_contig_plane_dma_addr(vb, 0), ++ pcdev->base_csi + fb_reg); + } + + *fb_active = buf; +@@ -487,9 +503,9 @@ static irqreturn_t mx25_camera_irq(int i + u32 status = readl(pcdev->base_csi + CSISR); + + if (status & CSISR_DMA_TSF_FB1_INT) +- mx25_camera_frame_done(pcdev, 1, VIDEOBUF_DONE); ++ mx25_camera_frame_done(pcdev, 1, MX2_STATE_DONE); + else if (status & CSISR_DMA_TSF_FB2_INT) +- mx25_camera_frame_done(pcdev, 2, VIDEOBUF_DONE); ++ mx25_camera_frame_done(pcdev, 2, MX2_STATE_DONE); + + /* FIXME: handle CSISR_RFF_OR_INT */ + +@@ -501,59 +517,50 @@ static irqreturn_t mx25_camera_irq(int i + /* + * Videobuf operations + */ +-static int mx2_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, +- unsigned int *size) ++static int mx2_videobuf_setup(struct vb2_queue *vq, ++ const struct v4l2_format *fmt, ++ unsigned int *count, unsigned int *num_planes, ++ unsigned int sizes[], void *alloc_ctxs[]) + { +- struct soc_camera_device *icd = vq->priv_data; ++ struct soc_camera_device *icd = soc_camera_from_vb2q(vq); ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct mx2_camera_dev *pcdev = ici->priv; + int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, + icd->current_fmt->host_fmt); + +- dev_dbg(icd->parent, "count=%d, size=%d\n", *count, *size); ++ dev_dbg(icd->parent, "count=%d, size=%d\n", *count, sizes[0]); ++ ++ /* TODO: support for VIDIOC_CREATE_BUFS not ready */ ++ if (fmt != NULL) ++ return -ENOTTY; + + if (bytes_per_line < 0) + return bytes_per_line; + +- *size = bytes_per_line * icd->user_height; ++ alloc_ctxs[0] = pcdev->alloc_ctx; ++ ++ sizes[0] = bytes_per_line * icd->user_height; + + if (0 == *count) + *count = 32; +- if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) +- *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size; ++ if (!*num_planes && ++ sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024) ++ *count = (MAX_VIDEO_MEM * 1024 * 1024) / sizes[0]; + +- return 0; +-} +- +-static void free_buffer(struct videobuf_queue *vq, struct mx2_buffer *buf) +-{ +- struct soc_camera_device *icd = vq->priv_data; +- struct videobuf_buffer *vb = &buf->vb; ++ *num_planes = 1; + +- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +- vb, vb->baddr, vb->bsize); +- +- /* +- * This waits until this buffer is out of danger, i.e., until it is no +- * longer in state VIDEOBUF_QUEUED or VIDEOBUF_ACTIVE +- */ +- videobuf_waiton(vq, vb, 0, 0); +- +- videobuf_dma_contig_free(vq, vb); +- dev_dbg(icd->parent, "%s freed\n", __func__); +- +- vb->state = VIDEOBUF_NEEDS_INIT; ++ return 0; + } + +-static int mx2_videobuf_prepare(struct videobuf_queue *vq, +- struct videobuf_buffer *vb, enum v4l2_field field) ++static int mx2_videobuf_prepare(struct vb2_buffer *vb) + { +- struct soc_camera_device *icd = vq->priv_data; +- struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); ++ struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); + int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, + icd->current_fmt->host_fmt); + int ret = 0; + +- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +- vb, vb->baddr, vb->bsize); ++ dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, ++ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); + + if (bytes_per_line < 0) + return bytes_per_line; +@@ -563,99 +570,58 @@ static int mx2_videobuf_prepare(struct v + * This can be useful if you want to see if we actually fill + * the buffer with something + */ +- memset((void *)vb->baddr, 0xaa, vb->bsize); ++ memset((void *)vb2_plane_vaddr(vb, 0), ++ 0xaa, vb2_get_plane_payload(vb, 0)); + #endif + +- if (buf->code != icd->current_fmt->code || +- vb->width != icd->user_width || +- vb->height != icd->user_height || +- vb->field != field) { +- buf->code = icd->current_fmt->code; +- vb->width = icd->user_width; +- vb->height = icd->user_height; +- vb->field = field; +- vb->state = VIDEOBUF_NEEDS_INIT; +- } +- +- vb->size = bytes_per_line * vb->height; +- if (vb->baddr && vb->bsize < vb->size) { ++ vb2_set_plane_payload(vb, 0, bytes_per_line * icd->user_height); ++ if (vb2_plane_vaddr(vb, 0) && ++ vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) { + ret = -EINVAL; + goto out; + } + +- if (vb->state == VIDEOBUF_NEEDS_INIT) { +- ret = videobuf_iolock(vq, vb, NULL); +- if (ret) +- goto fail; +- +- vb->state = VIDEOBUF_PREPARED; +- } +- + return 0; + +-fail: +- free_buffer(vq, buf); + out: + return ret; + } + +-static void mx2_videobuf_queue(struct videobuf_queue *vq, +- struct videobuf_buffer *vb) ++static void mx2_videobuf_queue(struct vb2_buffer *vb) + { +- struct soc_camera_device *icd = vq->priv_data; ++ struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); + struct soc_camera_host *ici = + to_soc_camera_host(icd->parent); + struct mx2_camera_dev *pcdev = ici->priv; + struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); + unsigned long flags; + +- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +- vb, vb->baddr, vb->bsize); ++ dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, ++ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); + + spin_lock_irqsave(&pcdev->lock, flags); + +- vb->state = VIDEOBUF_QUEUED; +- list_add_tail(&vb->queue, &pcdev->capture); +- +- if (mx27_camera_emma(pcdev)) { +- goto out; +-#ifdef CONFIG_MACH_MX27 +- } else if (cpu_is_mx27()) { +- int ret; +- +- if (pcdev->active == NULL) { +- ret = imx_dma_setup_single(pcdev->dma, +- videobuf_to_dma_contig(vb), vb->size, +- (u32)pcdev->base_dma + 0x10, +- DMA_MODE_READ); +- if (ret) { +- vb->state = VIDEOBUF_ERROR; +- wake_up(&vb->done); +- goto out; +- } ++ buf->state = MX2_STATE_QUEUED; ++ list_add_tail(&buf->internal.queue, &pcdev->capture); + +- vb->state = VIDEOBUF_ACTIVE; +- pcdev->active = buf; +- } +-#endif +- } else { /* cpu_is_mx25() */ ++ if (cpu_is_mx25()) { + u32 csicr3, dma_inten = 0; + + if (pcdev->fb1_active == NULL) { +- writel(videobuf_to_dma_contig(vb), ++ writel(vb2_dma_contig_plane_dma_addr(vb, 0), + pcdev->base_csi + CSIDMASA_FB1); + pcdev->fb1_active = buf; + dma_inten = CSICR1_FB1_DMA_INTEN; + } else if (pcdev->fb2_active == NULL) { +- writel(videobuf_to_dma_contig(vb), ++ writel(vb2_dma_contig_plane_dma_addr(vb, 0), + pcdev->base_csi + CSIDMASA_FB2); + pcdev->fb2_active = buf; + dma_inten = CSICR1_FB2_DMA_INTEN; + } + + if (dma_inten) { +- list_del(&vb->queue); +- vb->state = VIDEOBUF_ACTIVE; ++ list_del(&buf->internal.queue); ++ buf->state = MX2_STATE_ACTIVE; + + csicr3 = readl(pcdev->base_csi + CSICR3); + +@@ -674,36 +640,31 @@ static void mx2_videobuf_queue(struct vi + } + } + +-out: + spin_unlock_irqrestore(&pcdev->lock, flags); + } + +-static void mx2_videobuf_release(struct videobuf_queue *vq, +- struct videobuf_buffer *vb) ++static void mx2_videobuf_release(struct vb2_buffer *vb) + { +- struct soc_camera_device *icd = vq->priv_data; ++ struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct mx2_camera_dev *pcdev = ici->priv; + struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); + unsigned long flags; + + #ifdef DEBUG +- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +- vb, vb->baddr, vb->bsize); ++ dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, ++ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); + +- switch (vb->state) { +- case VIDEOBUF_ACTIVE: ++ switch (buf->state) { ++ case MX2_STATE_ACTIVE: + dev_info(icd->parent, "%s (active)\n", __func__); + break; +- case VIDEOBUF_QUEUED: ++ case MX2_STATE_QUEUED: + dev_info(icd->parent, "%s (queued)\n", __func__); + break; +- case VIDEOBUF_PREPARED: +- dev_info(icd->parent, "%s (prepared)\n", __func__); +- break; + default: + dev_info(icd->parent, "%s (unknown) %d\n", __func__, +- vb->state); ++ buf->state); + break; + } + #endif +@@ -717,11 +678,9 @@ static void mx2_videobuf_release(struct + * state. This requires a specific handling for each of the these DMA + * types. + */ ++ + spin_lock_irqsave(&pcdev->lock, flags); +- if (vb->state == VIDEOBUF_QUEUED) { +- list_del(&vb->queue); +- vb->state = VIDEOBUF_ERROR; +- } else if (cpu_is_mx25() && vb->state == VIDEOBUF_ACTIVE) { ++ if (cpu_is_mx25() && buf->state == MX2_STATE_ACTIVE) { + if (pcdev->fb1_active == buf) { + pcdev->csicr1 &= ~CSICR1_FB1_DMA_INTEN; + writel(0, pcdev->base_csi + CSIDMASA_FB1); +@@ -732,30 +691,260 @@ static void mx2_videobuf_release(struct + pcdev->fb2_active = NULL; + } + writel(pcdev->csicr1, pcdev->base_csi + CSICR1); +- vb->state = VIDEOBUF_ERROR; + } + spin_unlock_irqrestore(&pcdev->lock, flags); ++} ++ ++static void mx27_camera_emma_buf_init(struct soc_camera_device *icd, ++ int bytesperline) ++{ ++ struct soc_camera_host *ici = ++ to_soc_camera_host(icd->parent); ++ struct mx2_camera_dev *pcdev = ici->priv; ++ struct mx2_fmt_cfg *prp = pcdev->emma_prp; ++ ++ writel((pcdev->s_width << 16) | pcdev->s_height, ++ pcdev->base_emma + PRP_SRC_FRAME_SIZE); ++ writel(prp->cfg.src_pixel, ++ pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); ++ if (prp->cfg.channel == 1) { ++ writel((icd->user_width << 16) | icd->user_height, ++ pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE); ++ writel(bytesperline, ++ pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE); ++ writel(prp->cfg.ch1_pixel, ++ pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL); ++ } else { /* channel 2 */ ++ writel((icd->user_width << 16) | icd->user_height, ++ pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); ++ } ++ ++ /* Enable interrupts */ ++ writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL); ++} ++ ++static void mx2_prp_resize_commit(struct mx2_camera_dev *pcdev) ++{ ++ int dir; ++ ++ for (dir = RESIZE_DIR_H; dir <= RESIZE_DIR_V; dir++) { ++ unsigned char *s = pcdev->resizing[dir].s; ++ int len = pcdev->resizing[dir].len; ++ unsigned int coeff[2] = {0, 0}; ++ unsigned int valid = 0; ++ int i; ++ ++ if (len == 0) ++ continue; ++ ++ for (i = RESIZE_NUM_MAX - 1; i >= 0; i--) { ++ int j; ++ ++ j = i > 9 ? 1 : 0; ++ coeff[j] = (coeff[j] << BC_COEF) | ++ (s[i] & (SZ_COEF - 1)); ++ ++ if (i == 5 || i == 15) ++ coeff[j] <<= 1; ++ ++ valid = (valid << 1) | (s[i] >> BC_COEF); ++ } ++ ++ valid |= PRP_RZ_VALID_TBL_LEN(len); ++ ++ if (pcdev->resizing[dir].algo == RESIZE_ALGO_BILINEAR) ++ valid |= PRP_RZ_VALID_BILINEAR; ++ ++ if (pcdev->emma_prp->cfg.channel == 1) { ++ if (dir == RESIZE_DIR_H) { ++ writel(coeff[0], pcdev->base_emma + ++ PRP_CH1_RZ_HORI_COEF1); ++ writel(coeff[1], pcdev->base_emma + ++ PRP_CH1_RZ_HORI_COEF2); ++ writel(valid, pcdev->base_emma + ++ PRP_CH1_RZ_HORI_VALID); ++ } else { ++ writel(coeff[0], pcdev->base_emma + ++ PRP_CH1_RZ_VERT_COEF1); ++ writel(coeff[1], pcdev->base_emma + ++ PRP_CH1_RZ_VERT_COEF2); ++ writel(valid, pcdev->base_emma + ++ PRP_CH1_RZ_VERT_VALID); ++ } ++ } else { ++ if (dir == RESIZE_DIR_H) { ++ writel(coeff[0], pcdev->base_emma + ++ PRP_CH2_RZ_HORI_COEF1); ++ writel(coeff[1], pcdev->base_emma + ++ PRP_CH2_RZ_HORI_COEF2); ++ writel(valid, pcdev->base_emma + ++ PRP_CH2_RZ_HORI_VALID); ++ } else { ++ writel(coeff[0], pcdev->base_emma + ++ PRP_CH2_RZ_VERT_COEF1); ++ writel(coeff[1], pcdev->base_emma + ++ PRP_CH2_RZ_VERT_COEF2); ++ writel(valid, pcdev->base_emma + ++ PRP_CH2_RZ_VERT_VALID); ++ } ++ } ++ } ++} ++ ++static int mx2_start_streaming(struct vb2_queue *q, unsigned int count) ++{ ++ struct soc_camera_device *icd = soc_camera_from_vb2q(q); ++ struct soc_camera_host *ici = ++ to_soc_camera_host(icd->parent); ++ struct mx2_camera_dev *pcdev = ici->priv; ++ struct mx2_fmt_cfg *prp = pcdev->emma_prp; ++ struct vb2_buffer *vb; ++ struct mx2_buffer *buf; ++ unsigned long phys; ++ int bytesperline; ++ ++ if (cpu_is_mx27()) { ++ unsigned long flags; ++ if (count < 2) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&pcdev->lock, flags); ++ ++ buf = list_first_entry(&pcdev->capture, struct mx2_buffer, ++ internal.queue); ++ buf->internal.bufnum = 0; ++ vb = &buf->vb; ++ buf->state = MX2_STATE_ACTIVE; ++ ++ phys = vb2_dma_contig_plane_dma_addr(vb, 0); ++ mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); ++ list_move_tail(pcdev->capture.next, &pcdev->active_bufs); ++ ++ buf = list_first_entry(&pcdev->capture, struct mx2_buffer, ++ internal.queue); ++ buf->internal.bufnum = 1; ++ vb = &buf->vb; ++ buf->state = MX2_STATE_ACTIVE; ++ ++ phys = vb2_dma_contig_plane_dma_addr(vb, 0); ++ mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); ++ list_move_tail(pcdev->capture.next, &pcdev->active_bufs); ++ ++ bytesperline = soc_mbus_bytes_per_line(icd->user_width, ++ icd->current_fmt->host_fmt); ++ if (bytesperline < 0) ++ return bytesperline; ++ ++ /* ++ * I didn't manage to properly enable/disable the prp ++ * on a per frame basis during running transfers, ++ * thus we allocate a buffer here and use it to ++ * discard frames when no buffer is available. ++ * Feel free to work on this ;) ++ */ ++ pcdev->discard_size = icd->user_height * bytesperline; ++ pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, ++ pcdev->discard_size, &pcdev->discard_buffer_dma, ++ GFP_KERNEL); ++ if (!pcdev->discard_buffer) ++ return -ENOMEM; ++ ++ pcdev->buf_discard[0].discard = true; ++ list_add_tail(&pcdev->buf_discard[0].queue, ++ &pcdev->discard); ++ ++ pcdev->buf_discard[1].discard = true; ++ list_add_tail(&pcdev->buf_discard[1].queue, ++ &pcdev->discard); ++ ++ mx2_prp_resize_commit(pcdev); ++ ++ mx27_camera_emma_buf_init(icd, bytesperline); ++ ++ if (prp->cfg.channel == 1) { ++ writel(PRP_CNTL_CH1EN | ++ PRP_CNTL_CSIEN | ++ prp->cfg.in_fmt | ++ prp->cfg.out_fmt | ++ PRP_CNTL_CH1_LEN | ++ PRP_CNTL_CH1BYP | ++ PRP_CNTL_CH1_TSKIP(0) | ++ PRP_CNTL_IN_TSKIP(0), ++ pcdev->base_emma + PRP_CNTL); ++ } else { ++ writel(PRP_CNTL_CH2EN | ++ PRP_CNTL_CSIEN | ++ prp->cfg.in_fmt | ++ prp->cfg.out_fmt | ++ PRP_CNTL_CH2_LEN | ++ PRP_CNTL_CH2_TSKIP(0) | ++ PRP_CNTL_IN_TSKIP(0), ++ pcdev->base_emma + PRP_CNTL); ++ } ++ spin_unlock_irqrestore(&pcdev->lock, flags); ++ } ++ ++ return 0; ++} ++ ++static int mx2_stop_streaming(struct vb2_queue *q) ++{ ++ struct soc_camera_device *icd = soc_camera_from_vb2q(q); ++ struct soc_camera_host *ici = ++ to_soc_camera_host(icd->parent); ++ struct mx2_camera_dev *pcdev = ici->priv; ++ struct mx2_fmt_cfg *prp = pcdev->emma_prp; ++ unsigned long flags; ++ void *b; ++ u32 cntl; ++ ++ if (cpu_is_mx27()) { ++ spin_lock_irqsave(&pcdev->lock, flags); ++ ++ cntl = readl(pcdev->base_emma + PRP_CNTL); ++ if (prp->cfg.channel == 1) { ++ writel(cntl & ~PRP_CNTL_CH1EN, ++ pcdev->base_emma + PRP_CNTL); ++ } else { ++ writel(cntl & ~PRP_CNTL_CH2EN, ++ pcdev->base_emma + PRP_CNTL); ++ } ++ INIT_LIST_HEAD(&pcdev->capture); ++ INIT_LIST_HEAD(&pcdev->active_bufs); ++ INIT_LIST_HEAD(&pcdev->discard); ++ ++ b = pcdev->discard_buffer; ++ pcdev->discard_buffer = NULL; ++ ++ spin_unlock_irqrestore(&pcdev->lock, flags); ++ ++ dma_free_coherent(ici->v4l2_dev.dev, ++ pcdev->discard_size, b, pcdev->discard_buffer_dma); ++ } + +- free_buffer(vq, buf); ++ return 0; + } + +-static struct videobuf_queue_ops mx2_videobuf_ops = { +- .buf_setup = mx2_videobuf_setup, +- .buf_prepare = mx2_videobuf_prepare, +- .buf_queue = mx2_videobuf_queue, +- .buf_release = mx2_videobuf_release, ++static struct vb2_ops mx2_videobuf_ops = { ++ .queue_setup = mx2_videobuf_setup, ++ .buf_prepare = mx2_videobuf_prepare, ++ .buf_queue = mx2_videobuf_queue, ++ .buf_cleanup = mx2_videobuf_release, ++ .start_streaming = mx2_start_streaming, ++ .stop_streaming = mx2_stop_streaming, + }; + +-static void mx2_camera_init_videobuf(struct videobuf_queue *q, ++static int mx2_camera_init_videobuf(struct vb2_queue *q, + struct soc_camera_device *icd) + { +- struct soc_camera_host *ici = to_soc_camera_host(icd->parent); +- struct mx2_camera_dev *pcdev = ici->priv; ++ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ q->io_modes = VB2_MMAP | VB2_USERPTR; ++ q->drv_priv = icd; ++ q->ops = &mx2_videobuf_ops; ++ q->mem_ops = &vb2_dma_contig_memops; ++ q->buf_struct_size = sizeof(struct mx2_buffer); + +- videobuf_queue_dma_contig_init(q, &mx2_videobuf_ops, pcdev->dev, +- &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, +- V4L2_FIELD_NONE, sizeof(struct mx2_buffer), +- icd, &icd->video_lock); ++ return vb2_queue_init(q); + } + + #define MX2_BUS_FLAGS (V4L2_MBUS_MASTER | \ +@@ -785,82 +974,6 @@ static int mx27_camera_emma_prp_reset(st + return -ETIMEDOUT; + } + +-static void mx27_camera_emma_buf_init(struct soc_camera_device *icd, +- int bytesperline) +-{ +- struct soc_camera_host *ici = +- to_soc_camera_host(icd->parent); +- struct mx2_camera_dev *pcdev = ici->priv; +- struct mx2_fmt_cfg *prp = pcdev->emma_prp; +- u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width; +- +- if (prp->cfg.channel == 1) { +- writel(pcdev->discard_buffer_dma, +- pcdev->base_emma + PRP_DEST_RGB1_PTR); +- writel(pcdev->discard_buffer_dma, +- pcdev->base_emma + PRP_DEST_RGB2_PTR); +- +- writel(PRP_CNTL_CH1EN | +- PRP_CNTL_CSIEN | +- prp->cfg.in_fmt | +- prp->cfg.out_fmt | +- PRP_CNTL_CH1_LEN | +- PRP_CNTL_CH1BYP | +- PRP_CNTL_CH1_TSKIP(0) | +- PRP_CNTL_IN_TSKIP(0), +- pcdev->base_emma + PRP_CNTL); +- +- writel((icd->user_width << 16) | icd->user_height, +- pcdev->base_emma + PRP_SRC_FRAME_SIZE); +- writel((icd->user_width << 16) | icd->user_height, +- pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE); +- writel(bytesperline, +- pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE); +- writel(prp->cfg.src_pixel, +- pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); +- writel(prp->cfg.ch1_pixel, +- pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL); +- } else { /* channel 2 */ +- writel(pcdev->discard_buffer_dma, +- pcdev->base_emma + PRP_DEST_Y_PTR); +- writel(pcdev->discard_buffer_dma, +- pcdev->base_emma + PRP_SOURCE_Y_PTR); +- +- if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) { +- writel(pcdev->discard_buffer_dma + imgsize, +- pcdev->base_emma + PRP_DEST_CB_PTR); +- writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4), +- pcdev->base_emma + PRP_DEST_CR_PTR); +- writel(pcdev->discard_buffer_dma + imgsize, +- pcdev->base_emma + PRP_SOURCE_CB_PTR); +- writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4), +- pcdev->base_emma + PRP_SOURCE_CR_PTR); +- } +- +- writel(PRP_CNTL_CH2EN | +- PRP_CNTL_CSIEN | +- prp->cfg.in_fmt | +- prp->cfg.out_fmt | +- PRP_CNTL_CH2_LEN | +- PRP_CNTL_CH2_TSKIP(0) | +- PRP_CNTL_IN_TSKIP(0), +- pcdev->base_emma + PRP_CNTL); +- +- writel((icd->user_width << 16) | icd->user_height, +- pcdev->base_emma + PRP_SRC_FRAME_SIZE); +- +- writel((icd->user_width << 16) | icd->user_height, +- pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); +- +- writel(prp->cfg.src_pixel, +- pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); +- +- } +- +- /* Enable interrupts */ +- writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL); +-} +- + static int mx2_camera_set_bus_param(struct soc_camera_device *icd) + { + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); +@@ -939,31 +1052,10 @@ static int mx2_camera_set_bus_param(stru + if (bytesperline < 0) + return bytesperline; + +- if (mx27_camera_emma(pcdev)) { ++ if (cpu_is_mx27()) { + ret = mx27_camera_emma_prp_reset(pcdev); + if (ret) + return ret; +- +- if (pcdev->discard_buffer) +- dma_free_coherent(ici->v4l2_dev.dev, +- pcdev->discard_size, pcdev->discard_buffer, +- pcdev->discard_buffer_dma); +- +- /* +- * I didn't manage to properly enable/disable the prp +- * on a per frame basis during running transfers, +- * thus we allocate a buffer here and use it to +- * discard frames when no buffer is available. +- * Feel free to work on this ;) +- */ +- pcdev->discard_size = icd->user_height * bytesperline; +- pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, +- pcdev->discard_size, &pcdev->discard_buffer_dma, +- GFP_KERNEL); +- if (!pcdev->discard_buffer) +- return -ENOMEM; +- +- mx27_camera_emma_buf_init(icd, bytesperline); + } else if (cpu_is_mx25()) { + writel((bytesperline * icd->user_height) >> 2, + pcdev->base_csi + CSIRXCNT); +@@ -1052,6 +1144,123 @@ static int mx2_camera_get_formats(struct + return formats; + } + ++static int mx2_emmaprp_resize(struct mx2_camera_dev *pcdev, ++ struct v4l2_mbus_framefmt *mf_in, ++ struct v4l2_pix_format *pix_out, bool apply) ++{ ++ int num, den; ++ unsigned long m; ++ int i, dir; ++ ++ for (dir = RESIZE_DIR_H; dir <= RESIZE_DIR_V; dir++) { ++ struct emma_prp_resize tmprsz; ++ unsigned char *s = tmprsz.s; ++ int len = 0; ++ int in, out; ++ ++ if (dir == RESIZE_DIR_H) { ++ in = mf_in->width; ++ out = pix_out->width; ++ } else { ++ in = mf_in->height; ++ out = pix_out->height; ++ } ++ ++ if (in < out) ++ return -EINVAL; ++ else if (in == out) ++ continue; ++ ++ /* Calculate ratio */ ++ m = gcd(in, out); ++ num = in / m; ++ den = out / m; ++ if (num > RESIZE_NUM_MAX) ++ return -EINVAL; ++ ++ if ((num >= 2 * den) && (den == 1) && ++ (num < 9) && (!(num & 0x01))) { ++ int sum = 0; ++ int j; ++ ++ /* Average scaling for >= 2:1 ratios */ ++ /* Support can be added for num >=9 and odd values */ ++ ++ tmprsz.algo = RESIZE_ALGO_AVERAGING; ++ len = num; ++ ++ for (i = 0; i < (len / 2); i++) ++ s[i] = 8; ++ ++ do { ++ for (i = 0; i < (len / 2); i++) { ++ s[i] = s[i] >> 1; ++ sum = 0; ++ for (j = 0; j < (len / 2); j++) ++ sum += s[j]; ++ if (sum == 4) ++ break; ++ } ++ } while (sum != 4); ++ ++ for (i = (len / 2); i < len; i++) ++ s[i] = s[len - i - 1]; ++ ++ s[len - 1] |= SZ_COEF; ++ } else { ++ /* bilinear scaling for < 2:1 ratios */ ++ int v; /* overflow counter */ ++ int coeff, nxt; /* table output */ ++ int in_pos_inc = 2 * den; ++ int out_pos = num; ++ int out_pos_inc = 2 * num; ++ int init_carry = num - den; ++ int carry = init_carry; ++ ++ tmprsz.algo = RESIZE_ALGO_BILINEAR; ++ v = den + in_pos_inc; ++ do { ++ coeff = v - out_pos; ++ out_pos += out_pos_inc; ++ carry += out_pos_inc; ++ for (nxt = 0; v < out_pos; nxt++) { ++ v += in_pos_inc; ++ carry -= in_pos_inc; ++ } ++ ++ if (len > RESIZE_NUM_MAX) ++ return -EINVAL; ++ ++ coeff = ((coeff << BC_COEF) + ++ (in_pos_inc >> 1)) / in_pos_inc; ++ ++ if (coeff >= (SZ_COEF - 1)) ++ coeff--; ++ ++ coeff |= SZ_COEF; ++ s[len] = (unsigned char)coeff; ++ len++; ++ ++ for (i = 1; i < nxt; i++) { ++ if (len >= RESIZE_NUM_MAX) ++ return -EINVAL; ++ s[len] = 0; ++ len++; ++ } ++ } while (carry != init_carry); ++ } ++ tmprsz.len = len; ++ if (dir == RESIZE_DIR_H) ++ mf_in->width = pix_out->width; ++ else ++ mf_in->height = pix_out->height; ++ ++ if (apply) ++ memcpy(&pcdev->resizing[dir], &tmprsz, sizeof(tmprsz)); ++ } ++ return 0; ++} ++ + static int mx2_camera_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) + { +@@ -1063,6 +1272,9 @@ static int mx2_camera_set_fmt(struct soc + struct v4l2_mbus_framefmt mf; + int ret; + ++ dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n", ++ __func__, pix->width, pix->height); ++ + xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); + if (!xlate) { + dev_warn(icd->parent, "Format %x not found\n", +@@ -1080,6 +1292,22 @@ static int mx2_camera_set_fmt(struct soc + if (ret < 0 && ret != -ENOIOCTLCMD) + return ret; + ++ /* Store width and height returned by the sensor for resizing */ ++ pcdev->s_width = mf.width; ++ pcdev->s_height = mf.height; ++ dev_dbg(icd->parent, "%s: sensor params: width = %d, height = %d\n", ++ __func__, pcdev->s_width, pcdev->s_height); ++ ++ pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, ++ xlate->host_fmt->fourcc); ++ ++ memset(pcdev->resizing, 0, sizeof(pcdev->resizing)); ++ if ((mf.width != pix->width || mf.height != pix->height) && ++ pcdev->emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { ++ if (mx2_emmaprp_resize(pcdev, &mf, pix, true) < 0) ++ dev_dbg(icd->parent, "%s: can't resize\n", __func__); ++ } ++ + if (mf.code != xlate->code) + return -EINVAL; + +@@ -1089,9 +1317,8 @@ static int mx2_camera_set_fmt(struct soc + pix->colorspace = mf.colorspace; + icd->current_fmt = xlate; + +- if (mx27_camera_emma(pcdev)) +- pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, +- xlate->host_fmt->fourcc); ++ dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n", ++ __func__, pix->width, pix->height); + + return 0; + } +@@ -1104,9 +1331,14 @@ static int mx2_camera_try_fmt(struct soc + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_mbus_framefmt mf; + __u32 pixfmt = pix->pixelformat; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct mx2_camera_dev *pcdev = ici->priv; + unsigned int width_limit; + int ret; + ++ dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n", ++ __func__, pix->width, pix->height); ++ + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + if (pixfmt && !xlate) { + dev_warn(icd->parent, "Format %x not found\n", pixfmt); +@@ -1156,6 +1388,20 @@ static int mx2_camera_try_fmt(struct soc + if (ret < 0) + return ret; + ++ dev_dbg(icd->parent, "%s: sensor params: width = %d, height = %d\n", ++ __func__, pcdev->s_width, pcdev->s_height); ++ ++ /* If the sensor does not support image size try PrP resizing */ ++ pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, ++ xlate->host_fmt->fourcc); ++ ++ memset(pcdev->resizing, 0, sizeof(pcdev->resizing)); ++ if ((mf.width != pix->width || mf.height != pix->height) && ++ pcdev->emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { ++ if (mx2_emmaprp_resize(pcdev, &mf, pix, false) < 0) ++ dev_dbg(icd->parent, "%s: can't resize\n", __func__); ++ } ++ + if (mf.field == V4L2_FIELD_ANY) + mf.field = V4L2_FIELD_NONE; + /* +@@ -1174,6 +1420,9 @@ static int mx2_camera_try_fmt(struct soc + pix->field = mf.field; + pix->colorspace = mf.colorspace; + ++ dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n", ++ __func__, pix->width, pix->height); ++ + return 0; + } + +@@ -1187,136 +1436,11 @@ static int mx2_camera_querycap(struct so + return 0; + } + +-static int mx2_camera_reqbufs(struct soc_camera_device *icd, +- struct v4l2_requestbuffers *p) +-{ +- int i; +- +- for (i = 0; i < p->count; i++) { +- struct mx2_buffer *buf = container_of(icd->vb_vidq.bufs[i], +- struct mx2_buffer, vb); +- INIT_LIST_HEAD(&buf->vb.queue); +- } +- +- return 0; +-} +- +-#ifdef CONFIG_MACH_MX27 +-static void mx27_camera_frame_done(struct mx2_camera_dev *pcdev, int state) +-{ +- struct videobuf_buffer *vb; +- struct mx2_buffer *buf; +- unsigned long flags; +- int ret; +- +- spin_lock_irqsave(&pcdev->lock, flags); +- +- if (!pcdev->active) { +- dev_err(pcdev->dev, "%s called with no active buffer!\n", +- __func__); +- goto out; +- } +- +- vb = &pcdev->active->vb; +- buf = container_of(vb, struct mx2_buffer, vb); +- WARN_ON(list_empty(&vb->queue)); +- dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +- vb, vb->baddr, vb->bsize); +- +- /* _init is used to debug races, see comment in pxa_camera_reqbufs() */ +- list_del_init(&vb->queue); +- vb->state = state; +- do_gettimeofday(&vb->ts); +- vb->field_count++; +- +- wake_up(&vb->done); +- +- if (list_empty(&pcdev->capture)) { +- pcdev->active = NULL; +- goto out; +- } +- +- pcdev->active = list_entry(pcdev->capture.next, +- struct mx2_buffer, vb.queue); +- +- vb = &pcdev->active->vb; +- vb->state = VIDEOBUF_ACTIVE; +- +- ret = imx_dma_setup_single(pcdev->dma, videobuf_to_dma_contig(vb), +- vb->size, (u32)pcdev->base_dma + 0x10, DMA_MODE_READ); +- +- if (ret) { +- vb->state = VIDEOBUF_ERROR; +- pcdev->active = NULL; +- wake_up(&vb->done); +- } +- +-out: +- spin_unlock_irqrestore(&pcdev->lock, flags); +-} +- +-static void mx27_camera_dma_err_callback(int channel, void *data, int err) +-{ +- struct mx2_camera_dev *pcdev = data; +- +- mx27_camera_frame_done(pcdev, VIDEOBUF_ERROR); +-} +- +-static void mx27_camera_dma_callback(int channel, void *data) +-{ +- struct mx2_camera_dev *pcdev = data; +- +- mx27_camera_frame_done(pcdev, VIDEOBUF_DONE); +-} +- +-#define DMA_REQ_CSI_RX 31 /* FIXME: Add this to a resource */ +- +-static int __devinit mx27_camera_dma_init(struct platform_device *pdev, +- struct mx2_camera_dev *pcdev) +-{ +- int err; +- +- pcdev->dma = imx_dma_request_by_prio("CSI RX DMA", DMA_PRIO_HIGH); +- if (pcdev->dma < 0) { +- dev_err(&pdev->dev, "%s failed to request DMA channel\n", +- __func__); +- return pcdev->dma; +- } +- +- err = imx_dma_setup_handlers(pcdev->dma, mx27_camera_dma_callback, +- mx27_camera_dma_err_callback, pcdev); +- if (err) { +- dev_err(&pdev->dev, "%s failed to set DMA callback\n", +- __func__); +- goto err_out; +- } +- +- err = imx_dma_config_channel(pcdev->dma, +- IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_FIFO, +- IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, +- DMA_REQ_CSI_RX, 1); +- if (err) { +- dev_err(&pdev->dev, "%s failed to config DMA channel\n", +- __func__); +- goto err_out; +- } +- +- imx_dma_config_burstlen(pcdev->dma, 64); +- +- return 0; +- +-err_out: +- imx_dma_free(pcdev->dma); +- +- return err; +-} +-#endif /* CONFIG_MACH_MX27 */ +- + static unsigned int mx2_camera_poll(struct file *file, poll_table *pt) + { + struct soc_camera_device *icd = file->private_data; + +- return videobuf_poll_stream(file, &icd->vb_vidq, pt); ++ return vb2_poll(&icd->vb2_vidq, file, pt); + } + + static struct soc_camera_host_ops mx2_soc_camera_host_ops = { +@@ -1327,144 +1451,148 @@ static struct soc_camera_host_ops mx2_so + .set_crop = mx2_camera_set_crop, + .get_formats = mx2_camera_get_formats, + .try_fmt = mx2_camera_try_fmt, +- .init_videobuf = mx2_camera_init_videobuf, +- .reqbufs = mx2_camera_reqbufs, ++ .init_videobuf2 = mx2_camera_init_videobuf, + .poll = mx2_camera_poll, + .querycap = mx2_camera_querycap, + .set_bus_param = mx2_camera_set_bus_param, + }; + + static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, +- int bufnum, int state) ++ int bufnum, bool err) + { +- u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width; ++#ifdef DEBUG + struct mx2_fmt_cfg *prp = pcdev->emma_prp; ++#endif ++ struct mx2_buf_internal *ibuf; + struct mx2_buffer *buf; +- struct videobuf_buffer *vb; ++ struct vb2_buffer *vb; + unsigned long phys; + +- if (!list_empty(&pcdev->active_bufs)) { +- buf = list_entry(pcdev->active_bufs.next, +- struct mx2_buffer, vb.queue); ++ ibuf = list_first_entry(&pcdev->active_bufs, struct mx2_buf_internal, ++ queue); + +- BUG_ON(buf->bufnum != bufnum); ++ BUG_ON(ibuf->bufnum != bufnum); ++ ++ if (ibuf->discard) { ++ /* ++ * Discard buffer must not be returned to user space. ++ * Just return it to the discard queue. ++ */ ++ list_move_tail(pcdev->active_bufs.next, &pcdev->discard); ++ } else { ++ buf = mx2_ibuf_to_buf(ibuf); + + vb = &buf->vb; + #ifdef DEBUG +- phys = videobuf_to_dma_contig(vb); ++ phys = vb2_dma_contig_plane_dma_addr(vb, 0); + if (prp->cfg.channel == 1) { + if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + + 4 * bufnum) != phys) { +- dev_err(pcdev->dev, "%p != %p\n", phys, +- readl(pcdev->base_emma + +- PRP_DEST_RGB1_PTR + +- 4 * bufnum)); ++ dev_err(pcdev->dev, "%lx != %x\n", phys, ++ readl(pcdev->base_emma + ++ PRP_DEST_RGB1_PTR + 4 * bufnum)); + } + } else { + if (readl(pcdev->base_emma + PRP_DEST_Y_PTR - + 0x14 * bufnum) != phys) { +- dev_err(pcdev->dev, "%p != %p\n", phys, +- readl(pcdev->base_emma + +- PRP_DEST_Y_PTR - +- 0x14 * bufnum)); ++ dev_err(pcdev->dev, "%lx != %x\n", phys, ++ readl(pcdev->base_emma + ++ PRP_DEST_Y_PTR - 0x14 * bufnum)); + } + } + #endif +- dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, +- vb->baddr, vb->bsize); +- +- list_del(&vb->queue); +- vb->state = state; +- do_gettimeofday(&vb->ts); +- vb->field_count = pcdev->frame_count * 2; +- pcdev->frame_count++; +- +- wake_up(&vb->done); ++ dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, vb, ++ vb2_plane_vaddr(vb, 0), ++ vb2_get_plane_payload(vb, 0)); ++ ++ list_del_init(&buf->internal.queue); ++ do_gettimeofday(&vb->v4l2_buf.timestamp); ++ vb->v4l2_buf.sequence = pcdev->frame_count; ++ if (err) ++ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); ++ else ++ vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + } + ++ pcdev->frame_count++; ++ + if (list_empty(&pcdev->capture)) { +- if (prp->cfg.channel == 1) { +- writel(pcdev->discard_buffer_dma, pcdev->base_emma + +- PRP_DEST_RGB1_PTR + 4 * bufnum); +- } else { +- writel(pcdev->discard_buffer_dma, pcdev->base_emma + +- PRP_DEST_Y_PTR - +- 0x14 * bufnum); +- if (prp->out_fmt == V4L2_PIX_FMT_YUV420) { +- writel(pcdev->discard_buffer_dma + imgsize, +- pcdev->base_emma + PRP_DEST_CB_PTR - +- 0x14 * bufnum); +- writel(pcdev->discard_buffer_dma + +- ((5 * imgsize) / 4), pcdev->base_emma + +- PRP_DEST_CR_PTR - 0x14 * bufnum); +- } ++ if (list_empty(&pcdev->discard)) { ++ dev_warn(pcdev->dev, "%s: trying to access empty discard list\n", ++ __func__); ++ return; + } ++ ++ ibuf = list_first_entry(&pcdev->discard, ++ struct mx2_buf_internal, queue); ++ ibuf->bufnum = bufnum; ++ ++ list_move_tail(pcdev->discard.next, &pcdev->active_bufs); ++ mx27_update_emma_buf(pcdev, pcdev->discard_buffer_dma, bufnum); + return; + } + +- buf = list_entry(pcdev->capture.next, +- struct mx2_buffer, vb.queue); ++ buf = list_first_entry(&pcdev->capture, struct mx2_buffer, ++ internal.queue); + +- buf->bufnum = !bufnum; ++ buf->internal.bufnum = bufnum; + + list_move_tail(pcdev->capture.next, &pcdev->active_bufs); + + vb = &buf->vb; +- vb->state = VIDEOBUF_ACTIVE; ++ buf->state = MX2_STATE_ACTIVE; + +- phys = videobuf_to_dma_contig(vb); +- if (prp->cfg.channel == 1) { +- writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum); +- } else { +- writel(phys, pcdev->base_emma + +- PRP_DEST_Y_PTR - 0x14 * bufnum); +- if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) { +- writel(phys + imgsize, pcdev->base_emma + +- PRP_DEST_CB_PTR - 0x14 * bufnum); +- writel(phys + ((5 * imgsize) / 4), pcdev->base_emma + +- PRP_DEST_CR_PTR - 0x14 * bufnum); +- } +- } ++ phys = vb2_dma_contig_plane_dma_addr(vb, 0); ++ mx27_update_emma_buf(pcdev, phys, bufnum); + } + + static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) + { + struct mx2_camera_dev *pcdev = data; + unsigned int status = readl(pcdev->base_emma + PRP_INTRSTATUS); +- struct mx2_buffer *buf; ++ struct mx2_buf_internal *ibuf; ++ ++ spin_lock(&pcdev->lock); ++ ++ if (list_empty(&pcdev->active_bufs)) { ++ dev_warn(pcdev->dev, "%s: called while active list is empty\n", ++ __func__); ++ ++ if (!status) { ++ spin_unlock(&pcdev->lock); ++ return IRQ_NONE; ++ } ++ } + + if (status & (1 << 7)) { /* overflow */ +- u32 cntl; +- /* +- * We only disable channel 1 here since this is the only +- * enabled channel +- * +- * FIXME: the correct DMA overflow handling should be resetting +- * the buffer, returning an error frame, and continuing with +- * the next one. +- */ +- cntl = readl(pcdev->base_emma + PRP_CNTL); ++ u32 cntl = readl(pcdev->base_emma + PRP_CNTL); + writel(cntl & ~(PRP_CNTL_CH1EN | PRP_CNTL_CH2EN), + pcdev->base_emma + PRP_CNTL); + writel(cntl, pcdev->base_emma + PRP_CNTL); +- } +- if ((((status & (3 << 5)) == (3 << 5)) || +- ((status & (3 << 3)) == (3 << 3))) +- && !list_empty(&pcdev->active_bufs)) { ++ ++ ibuf = list_first_entry(&pcdev->active_bufs, ++ struct mx2_buf_internal, queue); ++ mx27_camera_frame_done_emma(pcdev, ++ ibuf->bufnum, true); ++ ++ status &= ~(1 << 7); ++ } else if (((status & (3 << 5)) == (3 << 5)) || ++ ((status & (3 << 3)) == (3 << 3))) { + /* + * Both buffers have triggered, process the one we're expecting + * to first + */ +- buf = list_entry(pcdev->active_bufs.next, +- struct mx2_buffer, vb.queue); +- mx27_camera_frame_done_emma(pcdev, buf->bufnum, VIDEOBUF_DONE); +- status &= ~(1 << (6 - buf->bufnum)); /* mark processed */ +- } +- if ((status & (1 << 6)) || (status & (1 << 4))) +- mx27_camera_frame_done_emma(pcdev, 0, VIDEOBUF_DONE); +- if ((status & (1 << 5)) || (status & (1 << 3))) +- mx27_camera_frame_done_emma(pcdev, 1, VIDEOBUF_DONE); ++ ibuf = list_first_entry(&pcdev->active_bufs, ++ struct mx2_buf_internal, queue); ++ mx27_camera_frame_done_emma(pcdev, ibuf->bufnum, false); ++ status &= ~(1 << (6 - ibuf->bufnum)); /* mark processed */ ++ } else if ((status & (1 << 6)) || (status & (1 << 4))) { ++ mx27_camera_frame_done_emma(pcdev, 0, false); ++ } else if ((status & (1 << 5)) || (status & (1 << 3))) { ++ mx27_camera_frame_done_emma(pcdev, 1, false); ++ } + ++ spin_unlock(&pcdev->lock); + writel(status, pcdev->base_emma + PRP_INTRSTATUS); + + return IRQ_HANDLED; +@@ -1527,8 +1655,6 @@ static int __devinit mx2_camera_probe(st + struct resource *res_csi, *res_emma; + void __iomem *base_csi; + int irq_csi, irq_emma; +- irq_handler_t mx2_cam_irq_handler = cpu_is_mx25() ? mx25_camera_irq +- : mx27_camera_irq; + int err = 0; + + dev_dbg(&pdev->dev, "initialising\n"); +@@ -1550,22 +1676,11 @@ static int __devinit mx2_camera_probe(st + + pcdev->clk_csi = clk_get(&pdev->dev, NULL); + if (IS_ERR(pcdev->clk_csi)) { ++ dev_err(&pdev->dev, "Could not get csi clock\n"); + err = PTR_ERR(pcdev->clk_csi); + goto exit_kfree; + } + +- dev_dbg(&pdev->dev, "Camera clock frequency: %ld\n", +- clk_get_rate(pcdev->clk_csi)); +- +- /* Initialize DMA */ +-#ifdef CONFIG_MACH_MX27 +- if (cpu_is_mx27()) { +- err = mx27_camera_dma_init(pdev, pcdev); +- if (err) +- goto exit_clk_put; +- } +-#endif /* CONFIG_MACH_MX27 */ +- + pcdev->res_csi = res_csi; + pcdev->pdata = pdev->dev.platform_data; + if (pcdev->pdata) { +@@ -1585,6 +1700,7 @@ static int __devinit mx2_camera_probe(st + + INIT_LIST_HEAD(&pcdev->capture); + INIT_LIST_HEAD(&pcdev->active_bufs); ++ INIT_LIST_HEAD(&pcdev->discard); + spin_lock_init(&pcdev->lock); + + /* +@@ -1606,11 +1722,13 @@ static int __devinit mx2_camera_probe(st + pcdev->base_dma = res_csi->start; + pcdev->dev = &pdev->dev; + +- err = request_irq(pcdev->irq_csi, mx2_cam_irq_handler, 0, +- MX2_CAM_DRV_NAME, pcdev); +- if (err) { +- dev_err(pcdev->dev, "Camera interrupt register failed \n"); +- goto exit_iounmap; ++ if (cpu_is_mx25()) { ++ err = request_irq(pcdev->irq_csi, mx25_camera_irq, 0, ++ MX2_CAM_DRV_NAME, pcdev); ++ if (err) { ++ dev_err(pcdev->dev, "Camera interrupt register failed \n"); ++ goto exit_iounmap; ++ } + } + + if (cpu_is_mx27()) { +@@ -1618,14 +1736,15 @@ static int __devinit mx2_camera_probe(st + res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 1); + irq_emma = platform_get_irq(pdev, 1); + +- if (res_emma && irq_emma >= 0) { +- dev_info(&pdev->dev, "Using EMMA\n"); +- pcdev->use_emma = 1; +- pcdev->res_emma = res_emma; +- pcdev->irq_emma = irq_emma; +- if (mx27_camera_emma_init(pcdev)) +- goto exit_free_irq; ++ if (!res_emma || !irq_emma) { ++ dev_err(&pdev->dev, "no EMMA resources\n"); ++ goto exit_free_irq; + } ++ ++ pcdev->res_emma = res_emma; ++ pcdev->irq_emma = irq_emma; ++ if (mx27_camera_emma_init(pcdev)) ++ goto exit_free_irq; + } + + pcdev->soc_host.drv_name = MX2_CAM_DRV_NAME, +@@ -1633,6 +1752,12 @@ static int __devinit mx2_camera_probe(st + pcdev->soc_host.priv = pcdev; + pcdev->soc_host.v4l2_dev.dev = &pdev->dev; + pcdev->soc_host.nr = pdev->id; ++ ++ pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); ++ if (IS_ERR(pcdev->alloc_ctx)) { ++ err = PTR_ERR(pcdev->alloc_ctx); ++ goto eallocctx; ++ } + err = soc_camera_host_register(&pcdev->soc_host); + if (err) + goto exit_free_emma; +@@ -1643,26 +1768,24 @@ static int __devinit mx2_camera_probe(st + return 0; + + exit_free_emma: +- if (mx27_camera_emma(pcdev)) { ++ vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); ++eallocctx: ++ if (cpu_is_mx27()) { + free_irq(pcdev->irq_emma, pcdev); + clk_disable(pcdev->clk_emma); + clk_put(pcdev->clk_emma); + iounmap(pcdev->base_emma); +- release_mem_region(res_emma->start, resource_size(res_emma)); ++ release_mem_region(pcdev->res_emma->start, resource_size(pcdev->res_emma)); + } + exit_free_irq: +- free_irq(pcdev->irq_csi, pcdev); ++ if (cpu_is_mx25()) ++ free_irq(pcdev->irq_csi, pcdev); + exit_iounmap: + iounmap(base_csi); + exit_release: + release_mem_region(res_csi->start, resource_size(res_csi)); + exit_dma_free: +-#ifdef CONFIG_MACH_MX27 +- if (cpu_is_mx27()) +- imx_dma_free(pcdev->dma); +-exit_clk_put: + clk_put(pcdev->clk_csi); +-#endif /* CONFIG_MACH_MX27 */ + exit_kfree: + kfree(pcdev); + exit: +@@ -1677,19 +1800,18 @@ static int __devexit mx2_camera_remove(s + struct resource *res; + + clk_put(pcdev->clk_csi); +-#ifdef CONFIG_MACH_MX27 ++ if (cpu_is_mx25()) ++ free_irq(pcdev->irq_csi, pcdev); + if (cpu_is_mx27()) +- imx_dma_free(pcdev->dma); +-#endif /* CONFIG_MACH_MX27 */ +- free_irq(pcdev->irq_csi, pcdev); +- if (mx27_camera_emma(pcdev)) + free_irq(pcdev->irq_emma, pcdev); + + soc_camera_host_unregister(&pcdev->soc_host); + ++ vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); ++ + iounmap(pcdev->base_csi); + +- if (mx27_camera_emma(pcdev)) { ++ if (cpu_is_mx27()) { + clk_disable(pcdev->clk_emma); + clk_put(pcdev->clk_emma); + iounmap(pcdev->base_emma); +Index: linux-3.3.x86_64/drivers/media/rc/rc-core-priv.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/rc-core-priv.h ++++ linux-3.3.x86_64/drivers/media/rc/rc-core-priv.h +@@ -35,7 +35,7 @@ struct ir_raw_event_ctrl { + struct list_head list; /* to keep track of raw clients */ + struct task_struct *thread; + spinlock_t lock; +- struct kfifo kfifo; /* fifo for the pulse/space durations */ ++ struct kfifo_rec_ptr_1 kfifo; /* fifo for the pulse/space durations */ + ktime_t last_event; /* when last event occurred */ + enum raw_event_type last_type; /* last event type */ + struct rc_dev *dev; /* pointer to the parent rc_dev */ +Index: linux-3.3.x86_64/drivers/media/video/s2255drv.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/s2255drv.c ++++ linux-3.3.x86_64/drivers/media/video/s2255drv.c +@@ -134,7 +134,7 @@ + + /* usb config commands */ + #define IN_DATA_TOKEN cpu_to_le32(0x2255c0de) +-#define CMD_2255 cpu_to_le32(0xc2255000) ++#define CMD_2255 0xc2255000 + #define CMD_SET_MODE cpu_to_le32((CMD_2255 | 0x10)) + #define CMD_START cpu_to_le32((CMD_2255 | 0x20)) + #define CMD_STOP cpu_to_le32((CMD_2255 | 0x30)) +@@ -852,15 +852,13 @@ static int vidioc_querycap(struct file * + static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) + { +- int index = 0; +- if (f) +- index = f->index; ++ int index = f->index; + + if (index >= ARRAY_SIZE(formats)) + return -EINVAL; +- if (!jpeg_enable && ((formats[index].fourcc == V4L2_PIX_FMT_JPEG) || +- (formats[index].fourcc == V4L2_PIX_FMT_MJPEG))) +- return -EINVAL; ++ if (!jpeg_enable && ((formats[index].fourcc == V4L2_PIX_FMT_JPEG) || ++ (formats[index].fourcc == V4L2_PIX_FMT_MJPEG))) ++ return -EINVAL; + dprintk(4, "name %s\n", formats[index].name); + strlcpy(f->description, formats[index].name, sizeof(f->description)); + f->pixelformat = formats[index].fourcc; +@@ -2027,7 +2025,7 @@ static int save_frame(struct s2255_dev * + pdata[1]); + offset = jj + PREFIX_SIZE; + bframe = 1; +- cc = pdword[1]; ++ cc = le32_to_cpu(pdword[1]); + if (cc >= MAX_CHANNELS) { + printk(KERN_ERR + "bad channel\n"); +@@ -2036,22 +2034,22 @@ static int save_frame(struct s2255_dev * + /* reverse it */ + dev->cc = G_chnmap[cc]; + channel = &dev->channel[dev->cc]; +- payload = pdword[3]; ++ payload = le32_to_cpu(pdword[3]); + if (payload > channel->req_image_size) { + channel->bad_payload++; + /* discard the bad frame */ + return -EINVAL; + } + channel->pkt_size = payload; +- channel->jpg_size = pdword[4]; ++ channel->jpg_size = le32_to_cpu(pdword[4]); + break; + case S2255_MARKER_RESPONSE: + + pdata += DEF_USB_BLOCK; + jj += DEF_USB_BLOCK; +- if (pdword[1] >= MAX_CHANNELS) ++ if (le32_to_cpu(pdword[1]) >= MAX_CHANNELS) + break; +- cc = G_chnmap[pdword[1]]; ++ cc = G_chnmap[le32_to_cpu(pdword[1])]; + if (cc >= MAX_CHANNELS) + break; + channel = &dev->channel[cc]; +@@ -2074,11 +2072,11 @@ static int save_frame(struct s2255_dev * + wake_up(&dev->fw_data->wait_fw); + break; + case S2255_RESPONSE_STATUS: +- channel->vidstatus = pdword[3]; ++ channel->vidstatus = le32_to_cpu(pdword[3]); + channel->vidstatus_ready = 1; + wake_up(&channel->wait_vidstatus); + dprintk(5, "got vidstatus %x chan %d\n", +- pdword[3], cc); ++ le32_to_cpu(pdword[3]), cc); + break; + default: + printk(KERN_INFO "s2255 unknown resp\n"); +@@ -2605,10 +2603,11 @@ static int s2255_probe(struct usb_interf + __le32 *pRel; + pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4]; + printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel); +- dev->dsp_fw_ver = *pRel; +- if (*pRel < S2255_CUR_DSP_FWVER) ++ dev->dsp_fw_ver = le32_to_cpu(*pRel); ++ if (dev->dsp_fw_ver < S2255_CUR_DSP_FWVER) + printk(KERN_INFO "s2255: f2255usb.bin out of date.\n"); +- if (dev->pid == 0x2257 && *pRel < S2255_MIN_DSP_COLORFILTER) ++ if (dev->pid == 0x2257 && ++ dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER) + printk(KERN_WARNING "s2255: 2257 requires firmware %d" + " or above.\n", S2255_MIN_DSP_COLORFILTER); + } +Index: linux-3.3.x86_64/drivers/media/common/tuners/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/common/tuners/Makefile ++++ linux-3.3.x86_64/drivers/media/common/tuners/Makefile +@@ -28,6 +28,8 @@ obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc + obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o + obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o + obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o ++obj-$(CONFIG_MEDIA_TUNER_TUA9001) += tua9001.o ++obj-$(CONFIG_MEDIA_TUNER_FC0011) += fc0011.o + +-ccflags-y += -Idrivers/media/dvb/dvb-core +-ccflags-y += -Idrivers/media/dvb/frontends ++ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core ++ccflags-y += -I$(srctree)/drivers/media/dvb/frontends +Index: linux-3.3.x86_64/drivers/media/video/saa7134/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7134/Makefile ++++ linux-3.3.x86_64/drivers/media/video/saa7134/Makefile +@@ -10,7 +10,7 @@ obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7 + + obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o + +-ccflags-y += -Idrivers/media/video +-ccflags-y += -Idrivers/media/common/tuners +-ccflags-y += -Idrivers/media/dvb/dvb-core +-ccflags-y += -Idrivers/media/dvb/frontends ++ccflags-y += -I$(srctree)/drivers/media/video ++ccflags-y += -I$(srctree)/drivers/media/common/tuners ++ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core ++ccflags-y += -I$(srctree)/drivers/media/dvb/frontends +Index: linux-3.3.x86_64/drivers/media/video/saa7164/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7164/Makefile ++++ linux-3.3.x86_64/drivers/media/video/saa7164/Makefile +@@ -4,9 +4,9 @@ saa7164-objs := saa7164-cards.o saa7164- + + obj-$(CONFIG_VIDEO_SAA7164) += saa7164.o + +-ccflags-y += -Idrivers/media/video +-ccflags-y += -Idrivers/media/common/tuners +-ccflags-y += -Idrivers/media/dvb/dvb-core +-ccflags-y += -Idrivers/media/dvb/frontends ++ccflags-y += -I$(srctree)/drivers/media/video ++ccflags-y += -I$(srctree)/drivers/media/common/tuners ++ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core ++ccflags-y += -I$(srctree)/drivers/media/dvb/frontends + + ccflags-y += $(extra-cflags-y) $(extra-cflags-m) +Index: linux-3.3.x86_64/drivers/media/video/ivtv/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/Makefile ++++ linux-3.3.x86_64/drivers/media/video/ivtv/Makefile +@@ -7,8 +7,8 @@ ivtv-objs := ivtv-routing.o ivtv-cards.o + obj-$(CONFIG_VIDEO_IVTV) += ivtv.o + obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o + +-ccflags-y += -Idrivers/media/video +-ccflags-y += -Idrivers/media/common/tuners +-ccflags-y += -Idrivers/media/dvb/dvb-core +-ccflags-y += -Idrivers/media/dvb/frontends ++ccflags-y += -I$(srctree)/drivers/media/video ++ccflags-y += -I$(srctree)/drivers/media/common/tuners ++ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core ++ccflags-y += -I$(srctree)/drivers/media/dvb/frontends + +Index: linux-3.3.x86_64/drivers/media/video/gspca/gl860/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/gspca/gl860/Makefile ++++ linux-3.3.x86_64/drivers/media/video/gspca/gl860/Makefile +@@ -6,5 +6,5 @@ gspca_gl860-objs := gl860.o \ + gl860-ov9655.o \ + gl860-mi2020.o + +-ccflags-y += -Idrivers/media/video/gspca ++ccflags-y += -I$(srctree)/drivers/media/video/gspca + +Index: linux-3.3.x86_64/drivers/media/video/gspca/m5602/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/gspca/m5602/Makefile ++++ linux-3.3.x86_64/drivers/media/video/gspca/m5602/Makefile +@@ -8,4 +8,4 @@ gspca_m5602-objs := m5602_core.o \ + m5602_s5k83a.o \ + m5602_s5k4aa.o + +-ccflags-y += -Idrivers/media/video/gspca ++ccflags-y += -I$(srctree)/drivers/media/video/gspca +Index: linux-3.3.x86_64/drivers/media/video/gspca/stv06xx/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/gspca/stv06xx/Makefile ++++ linux-3.3.x86_64/drivers/media/video/gspca/stv06xx/Makefile +@@ -6,5 +6,5 @@ gspca_stv06xx-objs := stv06xx.o \ + stv06xx_pb0100.o \ + stv06xx_st6422.o + +-ccflags-y += -Idrivers/media/video/gspca ++ccflags-y += -I$(srctree)/drivers/media/video/gspca + +Index: linux-3.3.x86_64/Documentation/dvb/cards.txt +=================================================================== +--- linux-3.3.x86_64.orig/Documentation/dvb/cards.txt ++++ linux-3.3.x86_64/Documentation/dvb/cards.txt +@@ -119,4 +119,5 @@ o Cards based on the Phillips saa7134 PC + - Compro Videomate DVB-T300 + - Compro Videomate DVB-T200 + - AVerMedia AVerTVHD MCE A180 ++ - KWorld PC150-U ATSC Hybrid + +Index: linux-3.3.x86_64/drivers/media/rc/keymaps/rc-kworld-pc150u.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/rc/keymaps/rc-kworld-pc150u.c +@@ -0,0 +1,102 @@ ++/* kworld-pc150u.c - Keytable for kworld_pc150u Remote Controller ++ * ++ * keymap imported from ir-keymaps.c ++ * ++ * Copyright (c) 2010 by Kyle Strickland ++ * (based on kworld-plus-tv-analog.c by ++ * Mauro Carvalho Chehab ) ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include ++#include ++ ++/* Kworld PC150-U ++ Kyle Strickland ++ */ ++ ++static struct rc_map_table kworld_pc150u[] = { ++ { 0x0c, KEY_MEDIA }, /* Kworld key */ ++ { 0x16, KEY_EJECTCLOSECD }, /* -> ) */ ++ { 0x1d, KEY_POWER2 }, ++ ++ { 0x00, KEY_1 }, ++ { 0x01, KEY_2 }, ++ { 0x02, KEY_3 }, ++ { 0x03, KEY_4 }, ++ { 0x04, KEY_5 }, ++ { 0x05, KEY_6 }, ++ { 0x06, KEY_7 }, ++ { 0x07, KEY_8 }, ++ { 0x08, KEY_9 }, ++ { 0x0a, KEY_0 }, ++ ++ { 0x09, KEY_AGAIN }, ++ { 0x14, KEY_MUTE }, ++ ++ { 0x1e, KEY_LAST }, ++ { 0x17, KEY_ZOOM }, ++ { 0x1f, KEY_HOMEPAGE }, ++ { 0x0e, KEY_ESC }, ++ ++ { 0x20, KEY_UP }, ++ { 0x21, KEY_DOWN }, ++ { 0x42, KEY_LEFT }, ++ { 0x43, KEY_RIGHT }, ++ { 0x0b, KEY_ENTER }, ++ ++ { 0x10, KEY_CHANNELUP }, ++ { 0x11, KEY_CHANNELDOWN }, ++ ++ { 0x13, KEY_VOLUMEUP }, ++ { 0x12, KEY_VOLUMEDOWN }, ++ ++ { 0x19, KEY_TIME}, /* Timeshift */ ++ { 0x1a, KEY_STOP}, ++ { 0x1b, KEY_RECORD}, ++ { 0x4b, KEY_EMAIL}, ++ ++ { 0x40, KEY_REWIND}, ++ { 0x44, KEY_PLAYPAUSE}, ++ { 0x41, KEY_FORWARD}, ++ { 0x22, KEY_TEXT}, ++ ++ { 0x15, KEY_AUDIO}, /* ((*)) */ ++ { 0x0f, KEY_MODE}, /* display ratio */ ++ { 0x1c, KEY_SYSRQ}, /* snapshot */ ++ { 0x4a, KEY_SLEEP}, /* sleep timer */ ++ ++ { 0x48, KEY_SOUND}, /* switch theater mode */ ++ { 0x49, KEY_BLUE}, /* A */ ++ { 0x18, KEY_RED}, /* B */ ++ { 0x23, KEY_GREEN}, /* C */ ++}; ++ ++static struct rc_map_list kworld_pc150u_map = { ++ .map = { ++ .scan = kworld_pc150u, ++ .size = ARRAY_SIZE(kworld_pc150u), ++ .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ ++ .name = RC_MAP_KWORLD_PC150U, ++ } ++}; ++ ++static int __init init_rc_map_kworld_pc150u(void) ++{ ++ return rc_map_register(&kworld_pc150u_map); ++} ++ ++static void __exit exit_rc_map_kworld_pc150u(void) ++{ ++ rc_map_unregister(&kworld_pc150u_map); ++} ++ ++module_init(init_rc_map_kworld_pc150u) ++module_exit(exit_rc_map_kworld_pc150u) ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Kyle Strickland "); +Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-cards.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa7134-cards.c ++++ linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-cards.c +@@ -33,6 +33,7 @@ + #include "tea5767.h" + #include "tda18271.h" + #include "xc5000.h" ++#include "s5h1411.h" + + /* commly used strings */ + static char name_mute[] = "mute"; +@@ -5712,6 +5713,36 @@ struct saa7134_board saa7134_boards[] = + .amux = LINE1, + } }, + }, ++ [SAA7134_BOARD_KWORLD_PC150U] = { ++ .name = "Kworld PC150-U", ++ .audio_clock = 0x00187de7, ++ .tuner_type = TUNER_PHILIPS_TDA8290, ++ .radio_type = UNSET, ++ .tuner_addr = ADDR_UNSET, ++ .radio_addr = ADDR_UNSET, ++ .mpeg = SAA7134_MPEG_DVB, ++ .gpiomask = 1 << 21, ++ .ts_type = SAA7134_MPEG_TS_PARALLEL, ++ .inputs = { { ++ .name = name_tv, ++ .vmux = 1, ++ .amux = TV, ++ .tv = 1, ++ }, { ++ .name = name_comp, ++ .vmux = 3, ++ .amux = LINE1, ++ }, { ++ .name = name_svideo, ++ .vmux = 8, ++ .amux = LINE2, ++ } }, ++ .radio = { ++ .name = name_radio, ++ .amux = TV, ++ .gpio = 0x0000000, ++ }, ++ }, + + }; + +@@ -6306,6 +6337,12 @@ struct pci_device_id saa7134_pci_tbl[] = + .driver_data = SAA7134_BOARD_KWORLD_ATSC110, /* ATSC 115 */ + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, ++ .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ ++ .subvendor = 0x17de, ++ .subdevice = 0xa134, ++ .driver_data = SAA7134_BOARD_KWORLD_PC150U, ++ }, { ++ .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x1461, + .subdevice = 0x7360, +@@ -7134,6 +7171,23 @@ static inline int saa7134_kworld_sbtvd_t + return 0; + } + ++static int saa7134_kworld_pc150u_toggle_agc(struct saa7134_dev *dev, ++ enum tda18271_mode mode) ++{ ++ switch (mode) { ++ case TDA18271_ANALOG: ++ saa7134_set_gpio(dev, 18, 0); ++ break; ++ case TDA18271_DIGITAL: ++ saa7134_set_gpio(dev, 18, 1); ++ msleep(30); ++ break; ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} ++ + static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, + int command, int arg) + { +@@ -7150,6 +7204,9 @@ static int saa7134_tda8290_18271_callbac + case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: + ret = saa7134_kworld_sbtvd_toggle_agc(dev, arg); + break; ++ case SAA7134_BOARD_KWORLD_PC150U: ++ ret = saa7134_kworld_pc150u_toggle_agc(dev, arg); ++ break; + default: + break; + } +@@ -7171,6 +7228,7 @@ static int saa7134_tda8290_callback(stru + case SAA7134_BOARD_HAUPPAUGE_HVR1120: + case SAA7134_BOARD_AVERMEDIA_M733A: + case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: ++ case SAA7134_BOARD_KWORLD_PC150U: + case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2: + /* tda8290 + tda18271 */ + ret = saa7134_tda8290_18271_callback(dev, command, arg); +@@ -7452,6 +7510,7 @@ int saa7134_board_init1(struct saa7134_d + case SAA7134_BOARD_BEHOLD_X7: + case SAA7134_BOARD_BEHOLD_H7: + case SAA7134_BOARD_BEHOLD_A7: ++ case SAA7134_BOARD_KWORLD_PC150U: + dev->has_remote = SAA7134_REMOTE_I2C; + break; + case SAA7134_BOARD_AVERMEDIA_A169_B: +Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-dvb.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa7134-dvb.c ++++ linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-dvb.c +@@ -61,6 +61,7 @@ + #include "zl10036.h" + #include "zl10039.h" + #include "mt312.h" ++#include "s5h1411.h" + + MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); + MODULE_LICENSE("GPL"); +@@ -1158,6 +1159,33 @@ static struct tda18271_config prohdtv_pr + .output_opt = TDA18271_OUTPUT_LT_OFF, + }; + ++static struct tda18271_std_map kworld_tda18271_std_map = { ++ .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 3, ++ .if_lvl = 6, .rfagc_top = 0x37 }, ++ .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 0, ++ .if_lvl = 6, .rfagc_top = 0x37 }, ++}; ++ ++static struct tda18271_config kworld_pc150u_tda18271_config = { ++ .std_map = &kworld_tda18271_std_map, ++ .gate = TDA18271_GATE_ANALOG, ++ .output_opt = TDA18271_OUTPUT_LT_OFF, ++ .config = 3, /* Use tuner callback for AGC */ ++ .rf_cal_on_startup = 1 ++}; ++ ++static struct s5h1411_config kworld_s5h1411_config = { ++ .output_mode = S5H1411_PARALLEL_OUTPUT, ++ .gpio = S5H1411_GPIO_OFF, ++ .qam_if = S5H1411_IF_4000, ++ .vsb_if = S5H1411_IF_3250, ++ .inversion = S5H1411_INVERSION_ON, ++ .status_mode = S5H1411_DEMODLOCKING, ++ .mpeg_timing = ++ S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, ++}; ++ ++ + /* ================================================================== + * Core code + */ +@@ -1438,6 +1466,22 @@ static int dvb_init(struct saa7134_dev * + &dev->i2c_adap, 0x61, + TUNER_PHILIPS_TUV1236D); + break; ++ case SAA7134_BOARD_KWORLD_PC150U: ++ saa7134_set_gpio(dev, 18, 1); /* Switch to digital mode */ ++ saa7134_tuner_callback(dev, 0, ++ TDA18271_CALLBACK_CMD_AGC_ENABLE, 1); ++ fe0->dvb.frontend = dvb_attach(s5h1411_attach, ++ &kworld_s5h1411_config, ++ &dev->i2c_adap); ++ if (fe0->dvb.frontend != NULL) { ++ dvb_attach(tda829x_attach, fe0->dvb.frontend, ++ &dev->i2c_adap, 0x4b, ++ &tda829x_no_probe); ++ dvb_attach(tda18271_attach, fe0->dvb.frontend, ++ 0x60, &dev->i2c_adap, ++ &kworld_pc150u_tda18271_config); ++ } ++ break; + case SAA7134_BOARD_FLYDVBS_LR300: + fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, + &dev->i2c_adap); +Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-i2c.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa7134-i2c.c ++++ linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-i2c.c +@@ -254,7 +254,9 @@ static int saa7134_i2c_xfer(struct i2c_a + addr = msgs[i].addr << 1; + if (msgs[i].flags & I2C_M_RD) + addr |= 1; +- if (i > 0 && msgs[i].flags & I2C_M_RD && msgs[i].addr != 0x40) { ++ if (i > 0 && msgs[i].flags & ++ I2C_M_RD && msgs[i].addr != 0x40 && ++ msgs[i].addr != 0x19) { + /* workaround for a saa7134 i2c bug + * needed to talk to the mt352 demux + * thanks to pinnacle for the hint */ +@@ -279,6 +281,16 @@ static int saa7134_i2c_xfer(struct i2c_a + d1printk("%02x", rc); + msgs[i].buf[byte] = rc; + } ++ /* discard mysterious extra byte when reading ++ from Samsung S5H1411. i2c bus gets error ++ if we do not. */ ++ if (0x19 == msgs[i].addr) { ++ d1printk(" ?"); ++ rc = i2c_recv_byte(dev); ++ if (rc < 0) ++ goto err; ++ d1printk("%02x", rc); ++ } + } else { + /* write bytes */ + d2printk("write bytes\n"); +Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-input.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa7134-input.c ++++ linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-input.c +@@ -210,6 +210,54 @@ static int get_key_msi_tvanywhere_plus(s + return 1; + } + ++/* copied and modified from get_key_msi_tvanywhere_plus() */ ++static int get_key_kworld_pc150u(struct IR_i2c *ir, u32 *ir_key, ++ u32 *ir_raw) ++{ ++ unsigned char b; ++ unsigned int gpio; ++ ++ /* is needed to access GPIO. Used by the saa_readl macro. */ ++ struct saa7134_dev *dev = ir->c->adapter->algo_data; ++ if (dev == NULL) { ++ i2cdprintk("get_key_kworld_pc150u: " ++ "ir->c->adapter->algo_data is NULL!\n"); ++ return -EIO; ++ } ++ ++ /* rising SAA7134_GPIO_GPRESCAN reads the status */ ++ ++ saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); ++ saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); ++ ++ gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); ++ ++ /* GPIO&0x100 is pulsed low when a button is pressed. Don't do ++ I2C receive if gpio&0x100 is not low. */ ++ ++ if (gpio & 0x100) ++ return 0; /* No button press */ ++ ++ /* GPIO says there is a button press. Get it. */ ++ ++ if (1 != i2c_master_recv(ir->c, &b, 1)) { ++ i2cdprintk("read error\n"); ++ return -EIO; ++ } ++ ++ /* No button press */ ++ ++ if (b == 0xff) ++ return 0; ++ ++ /* Button pressed */ ++ ++ dprintk("get_key_kworld_pc150u: Key = 0x%02X\n", b); ++ *ir_key = b; ++ *ir_raw = b; ++ return 1; ++} ++ + static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) + { + unsigned char b; +@@ -894,6 +942,21 @@ void saa7134_probe_i2c_ir(struct saa7134 + info.addr = 0x30; + /* MSI TV@nywhere Plus controller doesn't seem to + respond to probes unless we read something from ++ an existing device. Weird... ++ REVISIT: might no longer be needed */ ++ rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); ++ dprintk("probe 0x%02x @ %s: %s\n", ++ msg_msi.addr, dev->i2c_adap.name, ++ (1 == rc) ? "yes" : "no"); ++ break; ++ case SAA7134_BOARD_KWORLD_PC150U: ++ /* copied and modified from MSI TV@nywhere Plus */ ++ dev->init_data.name = "Kworld PC150-U"; ++ dev->init_data.get_key = get_key_kworld_pc150u; ++ dev->init_data.ir_codes = RC_MAP_KWORLD_PC150U; ++ info.addr = 0x30; ++ /* MSI TV@nywhere Plus controller doesn't seem to ++ respond to probes unless we read something from + an existing device. Weird... + REVISIT: might no longer be needed */ + rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); +Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa7134.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa7134.h ++++ linux-3.3.x86_64/drivers/media/video/saa7134/saa7134.h +@@ -126,8 +126,8 @@ struct saa7134_card_ir { + unsigned users; + + u32 polling; +- u32 last_gpio; +- u32 mask_keycode, mask_keydown, mask_keyup; ++ u32 last_gpio; ++ u32 mask_keycode, mask_keydown, mask_keyup; + + bool running; + bool active; +@@ -331,6 +331,7 @@ struct saa7134_card_ir { + #define SAA7134_BOARD_BEHOLD_501 186 + #define SAA7134_BOARD_BEHOLD_503FM 187 + #define SAA7134_BOARD_SENSORAY811_911 188 ++#define SAA7134_BOARD_KWORLD_PC150U 189 + + #define SAA7134_MAXBOARDS 32 + #define SAA7134_INPUT_MAX 8 +Index: linux-3.3.x86_64/drivers/media/video/cx18/cx18-driver.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx18/cx18-driver.c ++++ linux-3.3.x86_64/drivers/media/video/cx18/cx18-driver.c +@@ -38,7 +38,7 @@ + #include "cx18-ioctl.h" + #include "cx18-controls.h" + #include "tuner-xc2028.h" +- ++#include + #include + + /* If you have already X v4l cards, then set this to X. This way +@@ -75,7 +75,7 @@ static int radio[CX18_MAX_CARDS] = { -1, + -1, -1, -1, -1, -1, -1, -1, -1 }; + static unsigned cardtype_c = 1; + static unsigned tuner_c = 1; +-static bool radio_c = 1; ++static unsigned radio_c = 1; + static char pal[] = "--"; + static char secam[] = "--"; + static char ntsc[] = "-"; +@@ -110,7 +110,7 @@ static int retry_mmio = 1; + int cx18_debug; + + module_param_array(tuner, int, &tuner_c, 0644); +-module_param_array(radio, bool, &radio_c, 0644); ++module_param_array(radio, int, &radio_c, 0644); + module_param_array(cardtype, int, &cardtype_c, 0644); + module_param_string(pal, pal, sizeof(pal), 0644); + module_param_string(secam, secam, sizeof(secam), 0644); +@@ -812,7 +812,7 @@ static int cx18_setup_pci(struct cx18 *c + CX18_ERR("Can't enable device %d!\n", cx->instance); + return -EIO; + } +- if (pci_set_dma_mask(pci_dev, 0xffffffff)) { ++ if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32))) { + CX18_ERR("No suitable DMA available, card %d\n", cx->instance); + return -EIO; + } +Index: linux-3.3.x86_64/drivers/media/rc/Kconfig +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/Kconfig ++++ linux-3.3.x86_64/drivers/media/rc/Kconfig +@@ -266,4 +266,13 @@ config RC_LOOPBACK + To compile this driver as a module, choose M here: the module will + be called rc_loopback. + ++config IR_GPIO_CIR ++ tristate "GPIO IR remote control" ++ depends on RC_CORE ++ ---help--- ++ Say Y if you want to use GPIO based IR Receiver. ++ ++ To compile this driver as a module, choose M here: the module will ++ be called gpio-ir-recv. ++ + endif #RC_CORE +Index: linux-3.3.x86_64/drivers/media/rc/Makefile +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/Makefile ++++ linux-3.3.x86_64/drivers/media/rc/Makefile +@@ -26,3 +26,4 @@ obj-$(CONFIG_IR_REDRAT3) += redrat3.o + obj-$(CONFIG_IR_STREAMZAP) += streamzap.o + obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o + obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o ++obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.o +Index: linux-3.3.x86_64/drivers/media/rc/gpio-ir-recv.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/rc/gpio-ir-recv.c +@@ -0,0 +1,205 @@ ++/* Copyright (c) 2012, Code Aurora Forum. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define GPIO_IR_DRIVER_NAME "gpio-rc-recv" ++#define GPIO_IR_DEVICE_NAME "gpio_ir_recv" ++ ++struct gpio_rc_dev { ++ struct rc_dev *rcdev; ++ int gpio_nr; ++ bool active_low; ++}; ++ ++static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id) ++{ ++ struct gpio_rc_dev *gpio_dev = dev_id; ++ int gval; ++ int rc = 0; ++ enum raw_event_type type = IR_SPACE; ++ ++ gval = gpio_get_value_cansleep(gpio_dev->gpio_nr); ++ ++ if (gval < 0) ++ goto err_get_value; ++ ++ if (gpio_dev->active_low) ++ gval = !gval; ++ ++ if (gval == 1) ++ type = IR_PULSE; ++ ++ rc = ir_raw_event_store_edge(gpio_dev->rcdev, type); ++ if (rc < 0) ++ goto err_get_value; ++ ++ ir_raw_event_handle(gpio_dev->rcdev); ++ ++err_get_value: ++ return IRQ_HANDLED; ++} ++ ++static int __devinit gpio_ir_recv_probe(struct platform_device *pdev) ++{ ++ struct gpio_rc_dev *gpio_dev; ++ struct rc_dev *rcdev; ++ const struct gpio_ir_recv_platform_data *pdata = ++ pdev->dev.platform_data; ++ int rc; ++ ++ if (!pdata) ++ return -EINVAL; ++ ++ if (pdata->gpio_nr < 0) ++ return -EINVAL; ++ ++ gpio_dev = kzalloc(sizeof(struct gpio_rc_dev), GFP_KERNEL); ++ if (!gpio_dev) ++ return -ENOMEM; ++ ++ rcdev = rc_allocate_device(); ++ if (!rcdev) { ++ rc = -ENOMEM; ++ goto err_allocate_device; ++ } ++ ++ rcdev->driver_type = RC_DRIVER_IR_RAW; ++ rcdev->allowed_protos = RC_TYPE_ALL; ++ rcdev->input_name = GPIO_IR_DEVICE_NAME; ++ rcdev->input_id.bustype = BUS_HOST; ++ rcdev->driver_name = GPIO_IR_DRIVER_NAME; ++ rcdev->map_name = RC_MAP_EMPTY; ++ ++ gpio_dev->rcdev = rcdev; ++ gpio_dev->gpio_nr = pdata->gpio_nr; ++ gpio_dev->active_low = pdata->active_low; ++ ++ rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv"); ++ if (rc < 0) ++ goto err_gpio_request; ++ rc = gpio_direction_input(pdata->gpio_nr); ++ if (rc < 0) ++ goto err_gpio_direction_input; ++ ++ rc = rc_register_device(rcdev); ++ if (rc < 0) { ++ dev_err(&pdev->dev, "failed to register rc device\n"); ++ goto err_register_rc_device; ++ } ++ ++ platform_set_drvdata(pdev, gpio_dev); ++ ++ rc = request_any_context_irq(gpio_to_irq(pdata->gpio_nr), ++ gpio_ir_recv_irq, ++ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, ++ "gpio-ir-recv-irq", gpio_dev); ++ if (rc < 0) ++ goto err_request_irq; ++ ++ return 0; ++ ++err_request_irq: ++ platform_set_drvdata(pdev, NULL); ++ rc_unregister_device(rcdev); ++err_register_rc_device: ++err_gpio_direction_input: ++ gpio_free(pdata->gpio_nr); ++err_gpio_request: ++ rc_free_device(rcdev); ++ rcdev = NULL; ++err_allocate_device: ++ kfree(gpio_dev); ++ return rc; ++} ++ ++static int __devexit gpio_ir_recv_remove(struct platform_device *pdev) ++{ ++ struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); ++ ++ free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev); ++ platform_set_drvdata(pdev, NULL); ++ rc_unregister_device(gpio_dev->rcdev); ++ gpio_free(gpio_dev->gpio_nr); ++ rc_free_device(gpio_dev->rcdev); ++ kfree(gpio_dev); ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++static int gpio_ir_recv_suspend(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); ++ ++ if (device_may_wakeup(dev)) ++ enable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr)); ++ else ++ disable_irq(gpio_to_irq(gpio_dev->gpio_nr)); ++ ++ return 0; ++} ++ ++static int gpio_ir_recv_resume(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); ++ ++ if (device_may_wakeup(dev)) ++ disable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr)); ++ else ++ enable_irq(gpio_to_irq(gpio_dev->gpio_nr)); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops gpio_ir_recv_pm_ops = { ++ .suspend = gpio_ir_recv_suspend, ++ .resume = gpio_ir_recv_resume, ++}; ++#endif ++ ++static struct platform_driver gpio_ir_recv_driver = { ++ .probe = gpio_ir_recv_probe, ++ .remove = __devexit_p(gpio_ir_recv_remove), ++ .driver = { ++ .name = GPIO_IR_DRIVER_NAME, ++ .owner = THIS_MODULE, ++#ifdef CONFIG_PM ++ .pm = &gpio_ir_recv_pm_ops, ++#endif ++ }, ++}; ++ ++static int __init gpio_ir_recv_init(void) ++{ ++ return platform_driver_register(&gpio_ir_recv_driver); ++} ++module_init(gpio_ir_recv_init); ++ ++static void __exit gpio_ir_recv_exit(void) ++{ ++ platform_driver_unregister(&gpio_ir_recv_driver); ++} ++module_exit(gpio_ir_recv_exit); ++ ++MODULE_DESCRIPTION("GPIO IR Receiver driver"); ++MODULE_LICENSE("GPL v2"); +Index: linux-3.3.x86_64/include/media/gpio-ir-recv.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/include/media/gpio-ir-recv.h +@@ -0,0 +1,22 @@ ++/* Copyright (c) 2012, Code Aurora Forum. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __GPIO_IR_RECV_H__ ++#define __GPIO_IR_RECV_H__ ++ ++struct gpio_ir_recv_platform_data { ++ int gpio_nr; ++ bool active_low; ++}; ++ ++#endif /* __GPIO_IR_RECV_H__ */ ++ +Index: linux-3.3.x86_64/drivers/media/rc/ir-sony-decoder.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/ir-sony-decoder.c ++++ linux-3.3.x86_64/drivers/media/rc/ir-sony-decoder.c +@@ -130,7 +130,7 @@ static int ir_sony_decode(struct rc_dev + case 15: + device = bitrev8((data->bits >> 0) & 0xFF); + subdevice = 0; +- function = bitrev8((data->bits >> 7) & 0xFD); ++ function = bitrev8((data->bits >> 7) & 0xFE); + break; + case 20: + device = bitrev8((data->bits >> 5) & 0xF8); +Index: linux-3.3.x86_64/drivers/media/video/cx25821/cx25821-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx25821/cx25821-core.c ++++ linux-3.3.x86_64/drivers/media/video/cx25821/cx25821-core.c +@@ -1474,8 +1474,13 @@ static DEFINE_PCI_DEVICE_TABLE(cx25821_p + .device = 0x8210, + .subvendor = 0x14f1, + .subdevice = 0x0920, +- }, +- { ++ }, { ++ /* CX25821 No Brand */ ++ .vendor = 0x14f1, ++ .device = 0x8210, ++ .subvendor = 0x0000, ++ .subdevice = 0x0000, ++ }, { + /* --- end of list --- */ + } + }; +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/dib0090.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/dib0090.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/dib0090.c +@@ -519,7 +519,7 @@ static int dib0090_fw_identify(struct dv + return 0; + + identification_error: +- return -EIO;; ++ return -EIO; + } + + static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg) +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/stb0899_drv.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/stb0899_drv.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/stb0899_drv.c +@@ -67,7 +67,7 @@ static const struct stb0899_tab stb0899_ + * Crude linear extrapolation below -84.8dBm and above -8.0dBm. + */ + static const struct stb0899_tab stb0899_dvbsrf_tab[] = { +- { -950, -128 }, ++ { -750, -128 }, + { -748, -94 }, + { -745, -92 }, + { -735, -90 }, +@@ -131,7 +131,7 @@ static const struct stb0899_tab stb0899_ + { -730, 13645 }, + { -750, 13909 }, + { -766, 14153 }, +- { -999, 16383 } ++ { -950, 16383 } + }; + + /* DVB-S2 Es/N0 quant in dB/100 vs read value * 100*/ +@@ -964,6 +964,7 @@ static int stb0899_read_signal_strength( + + int val; + u32 reg; ++ *strength = 0; + switch (state->delsys) { + case SYS_DVBS: + case SYS_DSS: +@@ -983,11 +984,11 @@ static int stb0899_read_signal_strength( + break; + case SYS_DVBS2: + if (internal->lock) { +- reg = STB0899_READ_S2REG(STB0899_DEMOD, IF_AGC_GAIN); ++ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_GAIN); + val = STB0899_GETFIELD(IF_AGC_GAIN, reg); + + *strength = stb0899_table_lookup(stb0899_dvbs2rf_tab, ARRAY_SIZE(stb0899_dvbs2rf_tab) - 1, val); +- *strength += 750; ++ *strength += 950; + dprintk(state->verbose, FE_DEBUG, 1, "IF_AGC_GAIN = 0x%04x, C = %d * 0.1 dBm", + val & 0x3fff, *strength); + } +@@ -1009,6 +1010,7 @@ static int stb0899_read_snr(struct dvb_f + u8 buf[2]; + u32 reg; + ++ *snr = 0; + reg = stb0899_read_reg(state, STB0899_VSTATUS); + switch (state->delsys) { + case SYS_DVBS: +@@ -1071,7 +1073,7 @@ static int stb0899_read_status(struct dv + reg = stb0899_read_reg(state, STB0899_VSTATUS); + if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) { + dprintk(state->verbose, FE_DEBUG, 1, "--------> FE_HAS_CARRIER | FE_HAS_LOCK"); +- *status |= FE_HAS_CARRIER | FE_HAS_LOCK; ++ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK; + + reg = stb0899_read_reg(state, STB0899_PLPARM); + if (STB0899_GETFIELD(VITCURPUN, reg)) { +Index: linux-3.3.x86_64/include/sound/tea575x-tuner.h +=================================================================== +--- linux-3.3.x86_64.orig/include/sound/tea575x-tuner.h ++++ linux-3.3.x86_64/include/sound/tea575x-tuner.h +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #define TEA575X_FMIF 10700 + +@@ -42,13 +43,16 @@ struct snd_tea575x_ops { + }; + + struct snd_tea575x { ++ struct v4l2_device *v4l2_dev; + struct video_device vd; /* video device */ ++ int radio_nr; /* radio_nr */ + bool tea5759; /* 5759 chip is present */ ++ bool cannot_read_data; /* Device cannot read the data pin */ + bool mute; /* Device is muted? */ + bool stereo; /* receiving stereo */ + bool tuned; /* tuned to a station */ + unsigned int val; /* hw value */ +- unsigned long freq; /* frequency */ ++ u32 freq; /* frequency */ + struct mutex mutex; + struct snd_tea575x_ops *ops; + void *private_data; +Index: linux-3.3.x86_64/sound/i2c/other/tea575x-tuner.c +=================================================================== +--- linux-3.3.x86_64.orig/sound/i2c/other/tea575x-tuner.c ++++ linux-3.3.x86_64/sound/i2c/other/tea575x-tuner.c +@@ -25,21 +25,20 @@ + #include + #include + #include +-#include ++#include ++#include + #include ++#include + #include ++#include + #include + + MODULE_AUTHOR("Jaroslav Kysela "); + MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); + MODULE_LICENSE("GPL"); + +-static int radio_nr = -1; +-module_param(radio_nr, int, 0); +- +-#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) +-#define FREQ_LO (50UL * 16000) +-#define FREQ_HI (150UL * 16000) ++#define FREQ_LO (76U * 16000) ++#define FREQ_HI (108U * 16000) + + /* + * definitions +@@ -121,28 +120,10 @@ static unsigned int snd_tea575x_read(str + return data; + } + +-static void snd_tea575x_get_freq(struct snd_tea575x *tea) +-{ +- unsigned long freq; +- +- freq = snd_tea575x_read(tea) & TEA575X_BIT_FREQ_MASK; +- /* freq *= 12.5 */ +- freq *= 125; +- freq /= 10; +- /* crystal fixup */ +- if (tea->tea5759) +- freq += TEA575X_FMIF; +- else +- freq -= TEA575X_FMIF; +- +- tea->freq = freq * 16; /* from kHz */ +-} +- + static void snd_tea575x_set_freq(struct snd_tea575x *tea) + { +- unsigned long freq; ++ u32 freq = tea->freq; + +- freq = clamp(tea->freq, FREQ_LO, FREQ_HI); + freq /= 16; /* to kHz */ + /* crystal fixup */ + if (tea->tea5759) +@@ -167,12 +148,14 @@ static int vidioc_querycap(struct file * + { + struct snd_tea575x *tea = video_drvdata(file); + +- strlcpy(v->driver, "tea575x-tuner", sizeof(v->driver)); ++ strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); + strlcpy(v->card, tea->card, sizeof(v->card)); + strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); + strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); +- v->version = RADIO_VERSION; +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; ++ v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; ++ if (!tea->cannot_read_data) ++ v->device_caps |= V4L2_CAP_HW_FREQ_SEEK; ++ v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; + return 0; + } + +@@ -191,18 +174,24 @@ static int vidioc_g_tuner(struct file *f + v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; + v->rangelow = FREQ_LO; + v->rangehigh = FREQ_HI; +- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; +- v->audmode = tea->stereo ? V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO; ++ v->rxsubchans = tea->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; ++ v->audmode = (tea->val & TEA575X_BIT_MONO) ? ++ V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO; + v->signal = tea->tuned ? 0xffff : 0; +- + return 0; + } + + static int vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) + { +- if (v->index > 0) ++ struct snd_tea575x *tea = video_drvdata(file); ++ ++ if (v->index) + return -EINVAL; ++ tea->val &= ~TEA575X_BIT_MONO; ++ if (v->audmode == V4L2_TUNER_MODE_MONO) ++ tea->val |= TEA575X_BIT_MONO; ++ snd_tea575x_write(tea, tea->val); + return 0; + } + +@@ -214,7 +203,6 @@ static int vidioc_g_frequency(struct fil + if (f->tuner != 0) + return -EINVAL; + f->type = V4L2_TUNER_RADIO; +- snd_tea575x_get_freq(tea); + f->frequency = tea->freq; + return 0; + } +@@ -227,32 +215,47 @@ static int vidioc_s_frequency(struct fil + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; + +- if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) +- return -EINVAL; +- +- tea->freq = f->frequency; +- ++ tea->val &= ~TEA575X_BIT_SEARCH; ++ tea->freq = clamp(f->frequency, FREQ_LO, FREQ_HI); + snd_tea575x_set_freq(tea); +- + return 0; + } + +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) ++static int vidioc_s_hw_freq_seek(struct file *file, void *fh, ++ struct v4l2_hw_freq_seek *a) + { +- if (a->index > 1) +- return -EINVAL; +- +- strcpy(a->name, "Radio"); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; +-} ++ struct snd_tea575x *tea = video_drvdata(file); + +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- if (a->index != 0) ++ if (tea->cannot_read_data) ++ return -ENOTTY; ++ if (a->tuner || a->wrap_around) + return -EINVAL; ++ tea->val |= TEA575X_BIT_SEARCH; ++ tea->val &= ~TEA575X_BIT_UPDOWN; ++ if (a->seek_upward) ++ tea->val |= TEA575X_BIT_UPDOWN; ++ snd_tea575x_write(tea, tea->val); ++ for (;;) { ++ unsigned val = snd_tea575x_read(tea); ++ ++ if (!(val & TEA575X_BIT_SEARCH)) { ++ /* Found a frequency */ ++ val &= TEA575X_BIT_FREQ_MASK; ++ val = (val * 10) / 125; ++ if (tea->tea5759) ++ val += TEA575X_FMIF; ++ else ++ val -= TEA575X_FMIF; ++ tea->freq = clamp(val * 16, FREQ_LO, FREQ_HI); ++ return 0; ++ } ++ if (schedule_timeout_interruptible(msecs_to_jiffies(10))) { ++ /* some signal arrived, stop search */ ++ tea->val &= ~TEA575X_BIT_SEARCH; ++ snd_tea575x_write(tea, tea->val); ++ return -ERESTARTSYS; ++ } ++ } + return 0; + } + +@@ -273,23 +276,27 @@ static int tea575x_s_ctrl(struct v4l2_ct + static const struct v4l2_file_operations tea575x_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = video_ioctl2, ++ .open = v4l2_fh_open, ++ .release = v4l2_fh_release, ++ .poll = v4l2_ctrl_poll, + }; + + static const struct v4l2_ioctl_ops tea575x_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, ++ .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek, ++ .vidioc_log_status = v4l2_ctrl_log_status, ++ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + }; + +-static struct video_device tea575x_radio = { +- .name = "tea575x-tuner", ++static const struct video_device tea575x_radio = { + .fops = &tea575x_fops, + .ioctl_ops = &tea575x_ioctl_ops, +- .release = video_device_release_empty, ++ .release = video_device_release_empty, + }; + + static const struct v4l2_ctrl_ops tea575x_ctrl_ops = { +@@ -303,11 +310,15 @@ int snd_tea575x_init(struct snd_tea575x + { + int retval; + +- tea->mute = 1; ++ tea->mute = true; + +- snd_tea575x_write(tea, 0x55AA); +- if (snd_tea575x_read(tea) != 0x55AA) +- return -ENODEV; ++ /* Not all devices can or know how to read the data back. ++ Such devices can set cannot_read_data to true. */ ++ if (!tea->cannot_read_data) { ++ snd_tea575x_write(tea, 0x55AA); ++ if (snd_tea575x_read(tea) != 0x55AA) ++ return -ENODEV; ++ } + + tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40; + tea->freq = 90500 * 16; /* 90.5Mhz default */ +@@ -316,14 +327,17 @@ int snd_tea575x_init(struct snd_tea575x + tea->vd = tea575x_radio; + video_set_drvdata(&tea->vd, tea); + mutex_init(&tea->mutex); ++ strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name)); + tea->vd.lock = &tea->mutex; ++ tea->vd.v4l2_dev = tea->v4l2_dev; ++ tea->vd.ctrl_handler = &tea->ctrl_handler; ++ set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags); + + v4l2_ctrl_handler_init(&tea->ctrl_handler, 1); +- tea->vd.ctrl_handler = &tea->ctrl_handler; + v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops, V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); + retval = tea->ctrl_handler.error; + if (retval) { +- printk(KERN_ERR "tea575x-tuner: can't initialize controls\n"); ++ v4l2_err(tea->v4l2_dev, "can't initialize controls\n"); + v4l2_ctrl_handler_free(&tea->ctrl_handler); + return retval; + } +@@ -338,9 +352,9 @@ int snd_tea575x_init(struct snd_tea575x + + v4l2_ctrl_handler_setup(&tea->ctrl_handler); + +- retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, radio_nr); ++ retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->radio_nr); + if (retval) { +- printk(KERN_ERR "tea575x-tuner: can't register video device!\n"); ++ v4l2_err(tea->v4l2_dev, "can't register video device!\n"); + v4l2_ctrl_handler_free(&tea->ctrl_handler); + return retval; + } +Index: linux-3.3.x86_64/sound/pci/es1968.c +=================================================================== +--- linux-3.3.x86_64.orig/sound/pci/es1968.c ++++ linux-3.3.x86_64/sound/pci/es1968.c +@@ -142,6 +142,7 @@ static int enable_mpu[SNDRV_CARDS] = {[0 + #ifdef SUPPORT_JOYSTICK + static bool joystick[SNDRV_CARDS]; + #endif ++static int radio_nr[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; + + module_param_array(index, int, NULL, 0444); + MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); +@@ -165,6 +166,9 @@ MODULE_PARM_DESC(enable_mpu, "Enable MPU + module_param_array(joystick, bool, NULL, 0444); + MODULE_PARM_DESC(joystick, "Enable joystick."); + #endif ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); ++ + + + #define NR_APUS 64 +@@ -558,6 +562,7 @@ struct es1968 { + struct work_struct hwvol_work; + + #ifdef CONFIG_SND_ES1968_RADIO ++ struct v4l2_device v4l2_dev; + struct snd_tea575x tea; + #endif + }; +@@ -2613,6 +2618,7 @@ static int snd_es1968_free(struct es1968 + + #ifdef CONFIG_SND_ES1968_RADIO + snd_tea575x_exit(&chip->tea); ++ v4l2_device_unregister(&chip->v4l2_dev); + #endif + + if (chip->irq >= 0) +@@ -2655,6 +2661,7 @@ static int __devinit snd_es1968_create(s + int capt_streams, + int chip_type, + int do_pm, ++ int radio_nr, + struct es1968 **chip_ret) + { + static struct snd_device_ops ops = { +@@ -2751,7 +2758,14 @@ static int __devinit snd_es1968_create(s + snd_card_set_dev(card, &pci->dev); + + #ifdef CONFIG_SND_ES1968_RADIO ++ err = v4l2_device_register(&pci->dev, &chip->v4l2_dev); ++ if (err < 0) { ++ snd_es1968_free(chip); ++ return err; ++ } ++ chip->tea.v4l2_dev = &chip->v4l2_dev; + chip->tea.private_data = chip; ++ chip->tea.radio_nr = radio_nr; + chip->tea.ops = &snd_es1968_tea_ops; + strlcpy(chip->tea.card, "SF64-PCE2", sizeof(chip->tea.card)); + sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); +@@ -2797,6 +2811,7 @@ static int __devinit snd_es1968_probe(st + pcm_substreams_c[dev], + pci_id->driver_data, + use_pm[dev], ++ radio_nr[dev], + &chip)) < 0) { + snd_card_free(card); + return err; +Index: linux-3.3.x86_64/sound/pci/fm801.c +=================================================================== +--- linux-3.3.x86_64.orig/sound/pci/fm801.c ++++ linux-3.3.x86_64/sound/pci/fm801.c +@@ -58,6 +58,7 @@ static bool enable[SNDRV_CARDS] = SNDRV_ + * High 16-bits are video (radio) device number + 1 + */ + static int tea575x_tuner[SNDRV_CARDS]; ++static int radio_nr[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; + + module_param_array(index, int, NULL, 0444); + MODULE_PARM_DESC(index, "Index value for the FM801 soundcard."); +@@ -67,6 +68,9 @@ module_param_array(enable, bool, NULL, 0 + MODULE_PARM_DESC(enable, "Enable FM801 soundcard."); + module_param_array(tea575x_tuner, int, NULL, 0444); + MODULE_PARM_DESC(tea575x_tuner, "TEA575x tuner access method (0 = auto, 1 = SF256-PCS, 2=SF256-PCP, 3=SF64-PCR, 8=disable, +16=tuner-only)."); ++module_param_array(radio_nr, int, NULL, 0444); ++MODULE_PARM_DESC(radio_nr, "Radio device numbers"); ++ + + #define TUNER_DISABLED (1<<3) + #define TUNER_ONLY (1<<4) +@@ -197,6 +201,7 @@ struct fm801 { + struct snd_info_entry *proc_entry; + + #ifdef CONFIG_SND_FM801_TEA575X_BOOL ++ struct v4l2_device v4l2_dev; + struct snd_tea575x tea; + #endif + +@@ -1154,8 +1159,10 @@ static int snd_fm801_free(struct fm801 * + + __end_hw: + #ifdef CONFIG_SND_FM801_TEA575X_BOOL +- if (!(chip->tea575x_tuner & TUNER_DISABLED)) ++ if (!(chip->tea575x_tuner & TUNER_DISABLED)) { + snd_tea575x_exit(&chip->tea); ++ v4l2_device_unregister(&chip->v4l2_dev); ++ } + #endif + if (chip->irq >= 0) + free_irq(chip->irq, chip); +@@ -1175,6 +1182,7 @@ static int snd_fm801_dev_free(struct snd + static int __devinit snd_fm801_create(struct snd_card *card, + struct pci_dev * pci, + int tea575x_tuner, ++ int radio_nr, + struct fm801 ** rchip) + { + struct fm801 *chip; +@@ -1234,6 +1242,13 @@ static int __devinit snd_fm801_create(st + snd_card_set_dev(card, &pci->dev); + + #ifdef CONFIG_SND_FM801_TEA575X_BOOL ++ err = v4l2_device_register(&pci->dev, &chip->v4l2_dev); ++ if (err < 0) { ++ snd_fm801_free(chip); ++ return err; ++ } ++ chip->tea.v4l2_dev = &chip->v4l2_dev; ++ chip->tea.radio_nr = radio_nr; + chip->tea.private_data = chip; + chip->tea.ops = &snd_fm801_tea_ops; + sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); +@@ -1241,6 +1256,7 @@ static int __devinit snd_fm801_create(st + (tea575x_tuner & TUNER_TYPE_MASK) < 4) { + if (snd_tea575x_init(&chip->tea)) { + snd_printk(KERN_ERR "TEA575x radio not found\n"); ++ snd_fm801_free(chip); + return -ENODEV; + } + } else if ((tea575x_tuner & TUNER_TYPE_MASK) == 0) { +@@ -1287,7 +1303,7 @@ static int __devinit snd_card_fm801_prob + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; +- if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], &chip)) < 0) { ++ if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], radio_nr[dev], &chip)) < 0) { + snd_card_free(card); + return err; + } +Index: linux-3.3.x86_64/drivers/media/radio/radio-maxiradio.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/radio/radio-maxiradio.c ++++ linux-3.3.x86_64/drivers/media/radio/radio-maxiradio.c +@@ -42,67 +42,37 @@ + #include + #include + #include ++#include + #include + #include +- +-#define DRIVER_VERSION "0.7.8" +- ++#include ++#include ++#include + + MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net"); +-MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio."); ++MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000."); + MODULE_LICENSE("GPL"); +-MODULE_VERSION(DRIVER_VERSION); ++MODULE_VERSION("1.0.0"); + + static int radio_nr = -1; +-module_param(radio_nr, int, 0); +- +-static int debug; +- +-module_param(debug, int, 0644); +-MODULE_PARM_DESC(debug, "activates debug info"); +- +-#define dprintk(dev, num, fmt, arg...) \ +- v4l2_dbg(num, debug, &dev->v4l2_dev, fmt, ## arg) +- +-#ifndef PCI_VENDOR_ID_GUILLEMOT +-#define PCI_VENDOR_ID_GUILLEMOT 0x5046 +-#endif +- +-#ifndef PCI_DEVICE_ID_GUILLEMOT +-#define PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO 0x1001 +-#endif +- ++module_param(radio_nr, int, 0644); ++MODULE_PARM_DESC(radio_nr, "Radio device number"); + + /* TEA5757 pin mappings */ + static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16; + +-#define FREQ_LO (87 * 16000) +-#define FREQ_HI (108 * 16000) +- +-#define FREQ_IF 171200 /* 10.7*16000 */ +-#define FREQ_STEP 200 /* 12.5*16 */ +- +-/* (x==fmhz*16*1000) -> bits */ +-#define FREQ2BITS(x) \ +- ((((unsigned int)(x) + FREQ_IF + (FREQ_STEP << 1)) / (FREQ_STEP << 2)) << 2) +- +-#define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF) ++static atomic_t maxiradio_instance = ATOMIC_INIT(0); + ++#define PCI_VENDOR_ID_GUILLEMOT 0x5046 ++#define PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO 0x1001 + + struct maxiradio + { ++ struct snd_tea575x tea; + struct v4l2_device v4l2_dev; +- struct video_device vdev; + struct pci_dev *pdev; + + u16 io; /* base of radio io */ +- u16 muted; /* VIDEO_AUDIO_MUTE */ +- u16 stereo; /* VIDEO_TUNER_STEREO_ON */ +- u16 tuned; /* signal strength (0 or 0xffff) */ +- +- unsigned long freq; +- +- struct mutex lock; + }; + + static inline struct maxiradio *to_maxiradio(struct v4l2_device *v4l2_dev) +@@ -110,259 +80,41 @@ static inline struct maxiradio *to_maxir + return container_of(v4l2_dev, struct maxiradio, v4l2_dev); + } + +-static void outbit(unsigned long bit, u16 io) +-{ +- int val = power | wren | (bit ? data : 0); +- +- outb(val, io); +- udelay(4); +- outb(val | clk, io); +- udelay(4); +- outb(val, io); +- udelay(4); +-} +- +-static void turn_power(struct maxiradio *dev, int p) +-{ +- if (p != 0) { +- dprintk(dev, 1, "Radio powered on\n"); +- outb(power, dev->io); +- } else { +- dprintk(dev, 1, "Radio powered off\n"); +- outb(0, dev->io); +- } +-} +- +-static void set_freq(struct maxiradio *dev, u32 freq) +-{ +- unsigned long int si; +- int bl; +- int io = dev->io; +- int val = FREQ2BITS(freq); +- +- /* TEA5757 shift register bits (see pdf) */ +- +- outbit(0, io); /* 24 search */ +- outbit(1, io); /* 23 search up/down */ +- +- outbit(0, io); /* 22 stereo/mono */ +- +- outbit(0, io); /* 21 band */ +- outbit(0, io); /* 20 band (only 00=FM works I think) */ +- +- outbit(0, io); /* 19 port ? */ +- outbit(0, io); /* 18 port ? */ +- +- outbit(0, io); /* 17 search level */ +- outbit(0, io); /* 16 search level */ +- +- si = 0x8000; +- for (bl = 1; bl <= 16; bl++) { +- outbit(val & si, io); +- si >>= 1; +- } +- +- dprintk(dev, 1, "Radio freq set to %d.%02d MHz\n", +- freq / 16000, +- freq % 16000 * 100 / 16000); +- +- turn_power(dev, 1); +-} +- +-static int get_stereo(u16 io) +-{ +- outb(power,io); +- udelay(4); +- +- return !(inb(io) & mo_st); +-} +- +-static int get_tune(u16 io) +-{ +- outb(power+clk,io); +- udelay(4); +- +- return !(inb(io) & mo_st); +-} +- +- +-static int vidioc_querycap(struct file *file, void *priv, +- struct v4l2_capability *v) +-{ +- struct maxiradio *dev = video_drvdata(file); +- +- strlcpy(v->driver, "radio-maxiradio", sizeof(v->driver)); +- strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof(v->card)); +- snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(dev->pdev)); +- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; +- return 0; +-} +- +-static int vidioc_g_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) ++static void maxiradio_tea575x_set_pins(struct snd_tea575x *tea, u8 pins) + { +- struct maxiradio *dev = video_drvdata(file); ++ struct maxiradio *dev = tea->private_data; ++ u8 bits = 0; + +- if (v->index > 0) +- return -EINVAL; ++ bits |= (pins & TEA575X_DATA) ? data : 0; ++ bits |= (pins & TEA575X_CLK) ? clk : 0; ++ bits |= (pins & TEA575X_WREN) ? wren : 0; ++ bits |= power; + +- mutex_lock(&dev->lock); +- strlcpy(v->name, "FM", sizeof(v->name)); +- v->type = V4L2_TUNER_RADIO; +- v->rangelow = FREQ_LO; +- v->rangehigh = FREQ_HI; +- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; +- v->capability = V4L2_TUNER_CAP_LOW; +- if (get_stereo(dev->io)) +- v->audmode = V4L2_TUNER_MODE_STEREO; +- else +- v->audmode = V4L2_TUNER_MODE_MONO; +- v->signal = 0xffff * get_tune(dev->io); +- mutex_unlock(&dev->lock); +- +- return 0; +-} +- +-static int vidioc_s_tuner(struct file *file, void *priv, +- struct v4l2_tuner *v) +-{ +- return v->index ? -EINVAL : 0; +-} +- +-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +-{ +- *i = 0; +- return 0; +-} +- +-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +-{ +- return i ? -EINVAL : 0; +-} +- +-static int vidioc_g_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- a->index = 0; +- strlcpy(a->name, "Radio", sizeof(a->name)); +- a->capability = V4L2_AUDCAP_STEREO; +- return 0; +-} +- +- +-static int vidioc_s_audio(struct file *file, void *priv, +- struct v4l2_audio *a) +-{ +- return a->index ? -EINVAL : 0; +-} +- +-static int vidioc_s_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct maxiradio *dev = video_drvdata(file); +- +- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) +- return -EINVAL; +- if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) { +- dprintk(dev, 1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n", +- f->frequency / 16000, +- f->frequency % 16000 * 100 / 16000, +- FREQ_LO / 16000, FREQ_HI / 16000); +- +- return -EINVAL; +- } +- +- mutex_lock(&dev->lock); +- dev->freq = f->frequency; +- set_freq(dev, dev->freq); +- msleep(125); +- mutex_unlock(&dev->lock); +- +- return 0; +-} +- +-static int vidioc_g_frequency(struct file *file, void *priv, +- struct v4l2_frequency *f) +-{ +- struct maxiradio *dev = video_drvdata(file); +- +- if (f->tuner != 0) +- return -EINVAL; +- f->type = V4L2_TUNER_RADIO; +- f->frequency = dev->freq; +- +- dprintk(dev, 4, "radio freq is %d.%02d MHz", +- f->frequency / 16000, +- f->frequency % 16000 * 100 / 16000); +- +- return 0; +-} +- +-static int vidioc_queryctrl(struct file *file, void *priv, +- struct v4l2_queryctrl *qc) +-{ +- switch (qc->id) { +- case V4L2_CID_AUDIO_MUTE: +- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); +- } +- return -EINVAL; ++ outb(bits, dev->io); + } + +-static int vidioc_g_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) ++/* Note: this card cannot read out the data of the shift registers, ++ only the mono/stereo pin works. */ ++static u8 maxiradio_tea575x_get_pins(struct snd_tea575x *tea) + { +- struct maxiradio *dev = video_drvdata(file); ++ struct maxiradio *dev = tea->private_data; ++ u8 bits = inb(dev->io); + +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- ctrl->value = dev->muted; +- return 0; +- } +- +- return -EINVAL; ++ return ((bits & data) ? TEA575X_DATA : 0) | ++ ((bits & mo_st) ? TEA575X_MOST : 0); + } + +-static int vidioc_s_ctrl(struct file *file, void *priv, +- struct v4l2_control *ctrl) ++static void maxiradio_tea575x_set_direction(struct snd_tea575x *tea, bool output) + { +- struct maxiradio *dev = video_drvdata(file); +- +- switch (ctrl->id) { +- case V4L2_CID_AUDIO_MUTE: +- mutex_lock(&dev->lock); +- dev->muted = ctrl->value; +- if (dev->muted) +- turn_power(dev, 0); +- else +- set_freq(dev, dev->freq); +- mutex_unlock(&dev->lock); +- return 0; +- } +- +- return -EINVAL; + } + +-static const struct v4l2_file_operations maxiradio_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = video_ioctl2, +-}; +- +-static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = { +- .vidioc_querycap = vidioc_querycap, +- .vidioc_g_tuner = vidioc_g_tuner, +- .vidioc_s_tuner = vidioc_s_tuner, +- .vidioc_g_audio = vidioc_g_audio, +- .vidioc_s_audio = vidioc_s_audio, +- .vidioc_g_input = vidioc_g_input, +- .vidioc_s_input = vidioc_s_input, +- .vidioc_g_frequency = vidioc_g_frequency, +- .vidioc_s_frequency = vidioc_s_frequency, +- .vidioc_queryctrl = vidioc_queryctrl, +- .vidioc_g_ctrl = vidioc_g_ctrl, +- .vidioc_s_ctrl = vidioc_s_ctrl, ++static struct snd_tea575x_ops maxiradio_tea_ops = { ++ .set_pins = maxiradio_tea575x_set_pins, ++ .get_pins = maxiradio_tea575x_get_pins, ++ .set_direction = maxiradio_tea575x_set_direction, + }; + +-static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ++static int __devinit maxiradio_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + { + struct maxiradio *dev; + struct v4l2_device *v4l2_dev; +@@ -375,63 +127,60 @@ static int __devinit maxiradio_init_one( + } + + v4l2_dev = &dev->v4l2_dev; +- mutex_init(&dev->lock); +- dev->pdev = pdev; +- dev->muted = 1; +- dev->freq = FREQ_LO; +- +- strlcpy(v4l2_dev->name, "maxiradio", sizeof(v4l2_dev->name)); ++ v4l2_device_set_name(v4l2_dev, "maxiradio", &maxiradio_instance); + + retval = v4l2_device_register(&pdev->dev, v4l2_dev); + if (retval < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + goto errfr; + } ++ dev->tea.private_data = dev; ++ dev->tea.ops = &maxiradio_tea_ops; ++ /* The data pin cannot be read. This may be a hardware limitation, or ++ we just don't know how to read it. */ ++ dev->tea.cannot_read_data = true; ++ dev->tea.v4l2_dev = v4l2_dev; ++ dev->tea.radio_nr = radio_nr; ++ strlcpy(dev->tea.card, "Maxi Radio FM2000", sizeof(dev->tea.card)); ++ snprintf(dev->tea.bus_info, sizeof(dev->tea.bus_info), ++ "PCI:%s", pci_name(pdev)); ++ ++ retval = -ENODEV; + + if (!request_region(pci_resource_start(pdev, 0), +- pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) { +- v4l2_err(v4l2_dev, "can't reserve I/O ports\n"); +- goto err_out; ++ pci_resource_len(pdev, 0), v4l2_dev->name)) { ++ dev_err(&pdev->dev, "can't reserve I/O ports\n"); ++ goto err_hdl; + } + + if (pci_enable_device(pdev)) + goto err_out_free_region; + + dev->io = pci_resource_start(pdev, 0); +- strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); +- dev->vdev.v4l2_dev = v4l2_dev; +- dev->vdev.fops = &maxiradio_fops; +- dev->vdev.ioctl_ops = &maxiradio_ioctl_ops; +- dev->vdev.release = video_device_release_empty; +- video_set_drvdata(&dev->vdev, dev); +- +- if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +- v4l2_err(v4l2_dev, "can't register device!"); ++ if (snd_tea575x_init(&dev->tea)) { ++ printk(KERN_ERR "radio-maxiradio: Unable to detect TEA575x tuner\n"); + goto err_out_free_region; + } +- +- v4l2_info(v4l2_dev, "version " DRIVER_VERSION "\n"); +- +- v4l2_info(v4l2_dev, "found Guillemot MAXI Radio device (io = 0x%x)\n", +- dev->io); + return 0; + + err_out_free_region: + release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); +-err_out: ++err_hdl: + v4l2_device_unregister(v4l2_dev); + errfr: + kfree(dev); +- return -ENODEV; ++ return retval; + } + +-static void __devexit maxiradio_remove_one(struct pci_dev *pdev) ++static void __devexit maxiradio_remove(struct pci_dev *pdev) + { + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct maxiradio *dev = to_maxiradio(v4l2_dev); + +- video_unregister_device(&dev->vdev); +- v4l2_device_unregister(&dev->v4l2_dev); ++ snd_tea575x_exit(&dev->tea); ++ /* Turn off power */ ++ outb(0, dev->io); ++ v4l2_device_unregister(v4l2_dev); + release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + } + +@@ -446,19 +195,19 @@ MODULE_DEVICE_TABLE(pci, maxiradio_pci_t + static struct pci_driver maxiradio_driver = { + .name = "radio-maxiradio", + .id_table = maxiradio_pci_tbl, +- .probe = maxiradio_init_one, +- .remove = __devexit_p(maxiradio_remove_one), ++ .probe = maxiradio_probe, ++ .remove = __devexit_p(maxiradio_remove), + }; + +-static int __init maxiradio_radio_init(void) ++static int __init maxiradio_init(void) + { + return pci_register_driver(&maxiradio_driver); + } + +-static void __exit maxiradio_radio_exit(void) ++static void __exit maxiradio_exit(void) + { + pci_unregister_driver(&maxiradio_driver); + } + +-module_init(maxiradio_radio_init); +-module_exit(maxiradio_radio_exit); ++module_init(maxiradio_init); ++module_exit(maxiradio_exit); +Index: linux-3.3.x86_64/include/media/v4l2-dev.h +=================================================================== +--- linux-3.3.x86_64.orig/include/media/v4l2-dev.h ++++ linux-3.3.x86_64/include/media/v4l2-dev.h +@@ -62,6 +62,9 @@ struct v4l2_file_operations { + unsigned int (*poll) (struct file *, struct poll_table_struct *); + long (*ioctl) (struct file *, unsigned int, unsigned long); + long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); ++#ifdef CONFIG_COMPAT ++ long (*compat_ioctl32) (struct file *, unsigned int, unsigned long); ++#endif + unsigned long (*get_unmapped_area) (struct file *, unsigned long, + unsigned long, unsigned long, unsigned long); + int (*mmap) (struct file *, struct vm_area_struct *); +Index: linux-3.3.x86_64/drivers/media/video/uvc/uvc_v4l2.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/uvc/uvc_v4l2.c ++++ linux-3.3.x86_64/drivers/media/video/uvc/uvc_v4l2.c +@@ -11,6 +11,7 @@ + * + */ + ++#include + #include + #include + #include +@@ -1012,7 +1013,7 @@ static long uvc_v4l2_do_ioctl(struct fil + + default: + uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd); +- return -EINVAL; ++ return -ENOTTY; + } + + return ret; +@@ -1030,6 +1031,207 @@ static long uvc_v4l2_ioctl(struct file * + return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl); + } + ++#ifdef CONFIG_COMPAT ++struct uvc_xu_control_mapping32 { ++ __u32 id; ++ __u8 name[32]; ++ __u8 entity[16]; ++ __u8 selector; ++ ++ __u8 size; ++ __u8 offset; ++ __u32 v4l2_type; ++ __u32 data_type; ++ ++ compat_caddr_t menu_info; ++ __u32 menu_count; ++ ++ __u32 reserved[4]; ++}; ++ ++static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp, ++ const struct uvc_xu_control_mapping32 __user *up) ++{ ++ struct uvc_menu_info __user *umenus; ++ struct uvc_menu_info __user *kmenus; ++ compat_caddr_t p; ++ ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ __copy_from_user(kp, up, offsetof(typeof(*up), menu_info)) || ++ __get_user(kp->menu_count, &up->menu_count)) ++ return -EFAULT; ++ ++ memset(kp->reserved, 0, sizeof(kp->reserved)); ++ ++ if (kp->menu_count == 0) { ++ kp->menu_info = NULL; ++ return 0; ++ } ++ ++ if (__get_user(p, &up->menu_info)) ++ return -EFAULT; ++ umenus = compat_ptr(p); ++ if (!access_ok(VERIFY_READ, umenus, kp->menu_count * sizeof(*umenus))) ++ return -EFAULT; ++ ++ kmenus = compat_alloc_user_space(kp->menu_count * sizeof(*kmenus)); ++ if (kmenus == NULL) ++ return -EFAULT; ++ kp->menu_info = kmenus; ++ ++ if (copy_in_user(kmenus, umenus, kp->menu_count * sizeof(*umenus))) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp, ++ struct uvc_xu_control_mapping32 __user *up) ++{ ++ struct uvc_menu_info __user *umenus; ++ struct uvc_menu_info __user *kmenus = kp->menu_info; ++ compat_caddr_t p; ++ ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ __copy_to_user(up, kp, offsetof(typeof(*up), menu_info)) || ++ __put_user(kp->menu_count, &up->menu_count)) ++ return -EFAULT; ++ ++ __clear_user(up->reserved, sizeof(up->reserved)); ++ ++ if (kp->menu_count == 0) ++ return 0; ++ ++ if (get_user(p, &up->menu_info)) ++ return -EFAULT; ++ umenus = compat_ptr(p); ++ if (!access_ok(VERIFY_WRITE, umenus, kp->menu_count * sizeof(*umenus))) ++ return -EFAULT; ++ ++ if (copy_in_user(umenus, kmenus, kp->menu_count * sizeof(*umenus))) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++struct uvc_xu_control_query32 { ++ __u8 unit; ++ __u8 selector; ++ __u8 query; ++ __u16 size; ++ compat_caddr_t data; ++}; ++ ++static int uvc_v4l2_get_xu_query(struct uvc_xu_control_query *kp, ++ const struct uvc_xu_control_query32 __user *up) ++{ ++ u8 __user *udata; ++ u8 __user *kdata; ++ compat_caddr_t p; ++ ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ __copy_from_user(kp, up, offsetof(typeof(*up), data))) ++ return -EFAULT; ++ ++ if (kp->size == 0) { ++ kp->data = NULL; ++ return 0; ++ } ++ ++ if (__get_user(p, &up->data)) ++ return -EFAULT; ++ udata = compat_ptr(p); ++ if (!access_ok(VERIFY_READ, udata, kp->size)) ++ return -EFAULT; ++ ++ kdata = compat_alloc_user_space(kp->size); ++ if (kdata == NULL) ++ return -EFAULT; ++ kp->data = kdata; ++ ++ if (copy_in_user(kdata, udata, kp->size)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++static int uvc_v4l2_put_xu_query(const struct uvc_xu_control_query *kp, ++ struct uvc_xu_control_query32 __user *up) ++{ ++ u8 __user *udata; ++ u8 __user *kdata = kp->data; ++ compat_caddr_t p; ++ ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ __copy_to_user(up, kp, offsetof(typeof(*up), data))) ++ return -EFAULT; ++ ++ if (kp->size == 0) ++ return 0; ++ ++ if (get_user(p, &up->data)) ++ return -EFAULT; ++ udata = compat_ptr(p); ++ if (!access_ok(VERIFY_READ, udata, kp->size)) ++ return -EFAULT; ++ ++ if (copy_in_user(udata, kdata, kp->size)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++#define UVCIOC_CTRL_MAP32 _IOWR('u', 0x20, struct uvc_xu_control_mapping32) ++#define UVCIOC_CTRL_QUERY32 _IOWR('u', 0x21, struct uvc_xu_control_query32) ++ ++static long uvc_v4l2_compat_ioctl32(struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ union { ++ struct uvc_xu_control_mapping xmap; ++ struct uvc_xu_control_query xqry; ++ } karg; ++ void __user *up = compat_ptr(arg); ++ mm_segment_t old_fs; ++ long ret; ++ ++ switch (cmd) { ++ case UVCIOC_CTRL_MAP32: ++ cmd = UVCIOC_CTRL_MAP; ++ ret = uvc_v4l2_get_xu_mapping(&karg.xmap, up); ++ break; ++ ++ case UVCIOC_CTRL_QUERY32: ++ cmd = UVCIOC_CTRL_QUERY; ++ ret = uvc_v4l2_get_xu_query(&karg.xqry, up); ++ break; ++ ++ default: ++ return -ENOIOCTLCMD; ++ } ++ ++ old_fs = get_fs(); ++ set_fs(KERNEL_DS); ++ ret = uvc_v4l2_ioctl(file, cmd, (unsigned long)&karg); ++ set_fs(old_fs); ++ ++ if (ret < 0) ++ return ret; ++ ++ switch (cmd) { ++ case UVCIOC_CTRL_MAP: ++ ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up); ++ break; ++ ++ case UVCIOC_CTRL_QUERY: ++ ret = uvc_v4l2_put_xu_query(&karg.xqry, up); ++ break; ++ } ++ ++ return ret; ++} ++#endif ++ + static ssize_t uvc_v4l2_read(struct file *file, char __user *data, + size_t count, loff_t *ppos) + { +@@ -1076,6 +1278,9 @@ const struct v4l2_file_operations uvc_fo + .open = uvc_v4l2_open, + .release = uvc_v4l2_release, + .unlocked_ioctl = uvc_v4l2_ioctl, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl32 = uvc_v4l2_compat_ioctl32, ++#endif + .read = uvc_v4l2_read, + .mmap = uvc_v4l2_mmap, + .poll = uvc_v4l2_poll, +Index: linux-3.3.x86_64/drivers/media/video/uvc/uvc_queue.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/uvc/uvc_queue.c ++++ linux-3.3.x86_64/drivers/media/video/uvc/uvc_queue.c +@@ -126,7 +126,7 @@ void uvc_queue_init(struct uvc_video_que + int drop_corrupted) + { + queue->queue.type = type; +- queue->queue.io_modes = VB2_MMAP; ++ queue->queue.io_modes = VB2_MMAP | VB2_USERPTR; + queue->queue.drv_priv = queue; + queue->queue.buf_struct_size = sizeof(struct uvc_buffer); + queue->queue.ops = &uvc_queue_qops; +Index: linux-3.3.x86_64/drivers/media/video/uvc/uvc_driver.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/uvc/uvc_driver.c ++++ linux-3.3.x86_64/drivers/media/video/uvc/uvc_driver.c +@@ -23,6 +23,7 @@ + * codec can't handle MJPEG data. + */ + ++#include + #include + #include + #include +@@ -32,7 +33,6 @@ + #include + #include + #include +-#include + #include + + #include +@@ -2139,6 +2139,15 @@ static struct usb_device_id uvc_ids[] = + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_MINMAX }, ++ /* Dell XPS m1530 */ ++ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE ++ | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x05a9, ++ .idProduct = 0x2640, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = 1, ++ .bInterfaceProtocol = 0, ++ .driver_info = UVC_QUIRK_PROBE_DEF }, + /* Apple Built-In iSight */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/stv0288.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/stv0288.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/stv0288.c +@@ -506,7 +506,7 @@ static int stv0288_set_frontend(struct d + tda[1] = (unsigned char)tm; + stv0288_writeregI(state, 0x2b, tda[1]); + stv0288_writeregI(state, 0x2c, tda[2]); +- udelay(30); ++ msleep(30); + } + state->tuner_frequency = c->frequency; + state->fec_inner = FEC_AUTO; +Index: linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-cards.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx231xx/cx231xx-cards.c ++++ linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-cards.c +@@ -861,7 +861,6 @@ void cx231xx_release_resources(struct cx + kfree(dev->sliced_cc_mode.alt_max_pkt_size); + kfree(dev->ts1_mode.alt_max_pkt_size); + kfree(dev); +- dev = NULL; + } + + /* +Index: linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-video.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/cx231xx/cx231xx-video.c ++++ linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-video.c +@@ -2319,8 +2319,7 @@ static int cx231xx_v4l2_close(struct fil + if (dev->state & DEV_DISCONNECTED) { + if (atomic_read(&dev->devlist_count) > 0) { + cx231xx_release_resources(dev); +- kfree(dev); +- dev = NULL; ++ fh->dev = NULL; + return 0; + } + return 0; +@@ -2350,8 +2349,7 @@ static int cx231xx_v4l2_close(struct fil + free the remaining resources */ + if (dev->state & DEV_DISCONNECTED) { + cx231xx_release_resources(dev); +- kfree(dev); +- dev = NULL; ++ fh->dev = NULL; + return 0; + } + +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/dib9000.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/dib9000.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/dib9000.c +@@ -33,7 +33,7 @@ struct i2c_device { + + /* lock */ + #define DIB_LOCK struct mutex +-#define DibAcquireLock(lock) do { if (mutex_lock_interruptible(lock) < 0) dprintk("could not get the lock"); } while (0) ++#define DibAcquireLock(lock) mutex_lock_interruptible(lock) + #define DibReleaseLock(lock) mutex_unlock(lock) + #define DibInitLock(lock) mutex_init(lock) + #define DibFreeLock(lock) +@@ -446,7 +446,10 @@ static int dib9000_risc_mem_read(struct + if (!state->platform.risc.fw_is_running) + return -EIO; + +- DibAcquireLock(&state->platform.risc.mem_lock); ++ if (DibAcquireLock(&state->platform.risc.mem_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + dib9000_risc_mem_setup(state, cmd | 0x80); + dib9000_risc_mem_read_chunks(state, b, len); + DibReleaseLock(&state->platform.risc.mem_lock); +@@ -459,7 +462,10 @@ static int dib9000_risc_mem_write(struct + if (!state->platform.risc.fw_is_running) + return -EIO; + +- DibAcquireLock(&state->platform.risc.mem_lock); ++ if (DibAcquireLock(&state->platform.risc.mem_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + dib9000_risc_mem_setup(state, cmd); + dib9000_risc_mem_write_chunks(state, b, m->size); + DibReleaseLock(&state->platform.risc.mem_lock); +@@ -531,7 +537,10 @@ static int dib9000_mbx_send_attr(struct + if (!state->platform.risc.fw_is_running) + return -EINVAL; + +- DibAcquireLock(&state->platform.risc.mbx_if_lock); ++ if (DibAcquireLock(&state->platform.risc.mbx_if_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + tmp = MAX_MAILBOX_TRY; + do { + size = dib9000_read_word_attr(state, 1043, attr) & 0xff; +@@ -593,7 +602,10 @@ static u8 dib9000_mbx_read(struct dib900 + if (!state->platform.risc.fw_is_running) + return 0; + +- DibAcquireLock(&state->platform.risc.mbx_if_lock); ++ if (DibAcquireLock(&state->platform.risc.mbx_if_lock) < 0) { ++ dprintk("could not get the lock"); ++ return 0; ++ } + if (risc_id == 1) + mc_base = 16; + else +@@ -701,7 +713,10 @@ static int dib9000_mbx_process(struct di + if (!state->platform.risc.fw_is_running) + return -1; + +- DibAcquireLock(&state->platform.risc.mbx_lock); ++ if (DibAcquireLock(&state->platform.risc.mbx_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -1; ++ } + + if (dib9000_mbx_count(state, 1, attr)) /* 1=RiscB */ + ret = dib9000_mbx_fetch_to_cache(state, attr); +@@ -1178,7 +1193,10 @@ static int dib9000_fw_get_channel(struct + struct dibDVBTChannel *ch; + int ret = 0; + +- DibAcquireLock(&state->platform.risc.mem_mbx_lock); ++ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { + ret = -EIO; + goto error; +@@ -1660,7 +1678,10 @@ static int dib9000_fw_component_bus_xfer + p[12] = 0; + } + +- DibAcquireLock(&state->platform.risc.mem_mbx_lock); ++ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { ++ dprintk("could not get the lock"); ++ return 0; ++ } + + dib9000_risc_mem_write(state, FE_MM_W_COMPONENT_ACCESS, p); + +@@ -1768,7 +1789,10 @@ int dib9000_fw_pid_filter_ctrl(struct dv + return 0; + } + +- DibAcquireLock(&state->demod_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + + val = dib9000_read_word(state, 294 + 1) & 0xffef; + val |= (onoff & 0x1) << 4; +@@ -1800,7 +1824,10 @@ int dib9000_fw_pid_filter(struct dvb_fro + return 0; + } + +- DibAcquireLock(&state->demod_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff); + ret = dib9000_write_word(state, 300 + 1 + id, + onoff ? (1 << 13) | pid : 0); +@@ -1848,7 +1875,10 @@ static int dib9000_sleep(struct dvb_fron + u8 index_frontend; + int ret = 0; + +- DibAcquireLock(&state->demod_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { + ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]); + if (ret < 0) +@@ -1874,8 +1904,12 @@ static int dib9000_get_frontend(struct d + fe_status_t stat; + int ret = 0; + +- if (state->get_frontend_internal == 0) +- DibAcquireLock(&state->demod_lock); ++ if (state->get_frontend_internal == 0) { ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } ++ } + + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { + state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat); +@@ -1978,7 +2012,10 @@ static int dib9000_set_frontend(struct d + } + + state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */ +- DibAcquireLock(&state->demod_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return 0; ++ } + + fe->dtv_property_cache.delivery_system = SYS_DVBT; + +@@ -2138,7 +2175,10 @@ static int dib9000_read_status(struct dv + u8 index_frontend; + u16 lock = 0, lock_slave = 0; + +- DibAcquireLock(&state->demod_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) + lock_slave |= dib9000_read_lock(state->fe[index_frontend]); + +@@ -2168,8 +2208,15 @@ static int dib9000_read_ber(struct dvb_f + u16 *c; + int ret = 0; + +- DibAcquireLock(&state->demod_lock); +- DibAcquireLock(&state->platform.risc.mem_mbx_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } ++ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { ++ dprintk("could not get the lock"); ++ ret = -EINTR; ++ goto error; ++ } + if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { + DibReleaseLock(&state->platform.risc.mem_mbx_lock); + ret = -EIO; +@@ -2196,7 +2243,10 @@ static int dib9000_read_signal_strength( + u16 val; + int ret = 0; + +- DibAcquireLock(&state->demod_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + *strength = 0; + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { + state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val); +@@ -2206,8 +2256,13 @@ static int dib9000_read_signal_strength( + *strength += val; + } + +- DibAcquireLock(&state->platform.risc.mem_mbx_lock); ++ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { ++ dprintk("could not get the lock"); ++ ret = -EINTR; ++ goto error; ++ } + if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { ++ DibReleaseLock(&state->platform.risc.mem_mbx_lock); + ret = -EIO; + goto error; + } +@@ -2232,9 +2287,14 @@ static u32 dib9000_get_snr(struct dvb_fr + u32 n, s, exp; + u16 val; + +- DibAcquireLock(&state->platform.risc.mem_mbx_lock); +- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) +- return -EIO; ++ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { ++ dprintk("could not get the lock"); ++ return 0; ++ } ++ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { ++ DibReleaseLock(&state->platform.risc.mem_mbx_lock); ++ return 0; ++ } + dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); + DibReleaseLock(&state->platform.risc.mem_mbx_lock); + +@@ -2266,7 +2326,10 @@ static int dib9000_read_snr(struct dvb_f + u8 index_frontend; + u32 snr_master; + +- DibAcquireLock(&state->demod_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } + snr_master = dib9000_get_snr(fe); + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) + snr_master += dib9000_get_snr(state->fe[index_frontend]); +@@ -2288,9 +2351,17 @@ static int dib9000_read_unc_blocks(struc + u16 *c = (u16 *)state->i2c_read_buffer; + int ret = 0; + +- DibAcquireLock(&state->demod_lock); +- DibAcquireLock(&state->platform.risc.mem_mbx_lock); ++ if (DibAcquireLock(&state->demod_lock) < 0) { ++ dprintk("could not get the lock"); ++ return -EINTR; ++ } ++ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { ++ dprintk("could not get the lock"); ++ ret = -EINTR; ++ goto error; ++ } + if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { ++ DibReleaseLock(&state->platform.risc.mem_mbx_lock); + ret = -EIO; + goto error; + } +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/drxd_hard.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/drxd_hard.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/drxd_hard.c +@@ -101,9 +101,9 @@ struct SCfgAgc { + + struct SNoiseCal { + int cpOpt; +- u16 cpNexpOfs; +- u16 tdCal2k; +- u16 tdCal8k; ++ short cpNexpOfs; ++ short tdCal2k; ++ short tdCal8k; + }; + + enum app_env { +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/m88rs2000.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/m88rs2000.c +@@ -0,0 +1,904 @@ ++/* ++ Driver for M88RS2000 demodulator and tuner ++ ++ Copyright (C) 2012 Malcolm Priestley (tvboxspy@gmail.com) ++ Beta Driver ++ ++ Include various calculation code from DS3000 driver. ++ Copyright (C) 2009 Konstantin Dimitrov. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ ++*/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#include "dvb_frontend.h" ++#include "m88rs2000.h" ++ ++struct m88rs2000_state { ++ struct i2c_adapter *i2c; ++ const struct m88rs2000_config *config; ++ struct dvb_frontend frontend; ++ u8 no_lock_count; ++ u32 tuner_frequency; ++ u32 symbol_rate; ++ fe_code_rate_t fec_inner; ++ u8 tuner_level; ++ int errmode; ++}; ++ ++static int m88rs2000_debug; ++ ++module_param_named(debug, m88rs2000_debug, int, 0644); ++MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); ++ ++#define dprintk(level, args...) do { \ ++ if (level & m88rs2000_debug) \ ++ printk(KERN_DEBUG "m88rs2000-fe: " args); \ ++} while (0) ++ ++#define deb_info(args...) dprintk(0x01, args) ++#define info(format, arg...) \ ++ printk(KERN_INFO "m88rs2000-fe: " format "\n" , ## arg) ++ ++static int m88rs2000_writereg(struct m88rs2000_state *state, u8 tuner, ++ u8 reg, u8 data) ++{ ++ int ret; ++ u8 addr = (tuner == 0) ? state->config->tuner_addr : ++ state->config->demod_addr; ++ u8 buf[] = { reg, data }; ++ struct i2c_msg msg = { ++ .addr = addr, ++ .flags = 0, ++ .buf = buf, ++ .len = 2 ++ }; ++ ++ ret = i2c_transfer(state->i2c, &msg, 1); ++ ++ if (ret != 1) ++ deb_info("%s: writereg error (reg == 0x%02x, val == 0x%02x, " ++ "ret == %i)\n", __func__, reg, data, ret); ++ ++ return (ret != 1) ? -EREMOTEIO : 0; ++} ++ ++static int m88rs2000_demod_write(struct m88rs2000_state *state, u8 reg, u8 data) ++{ ++ return m88rs2000_writereg(state, 1, reg, data); ++} ++ ++static int m88rs2000_tuner_write(struct m88rs2000_state *state, u8 reg, u8 data) ++{ ++ m88rs2000_demod_write(state, 0x81, 0x84); ++ udelay(10); ++ return m88rs2000_writereg(state, 0, reg, data); ++ ++} ++ ++static int m88rs2000_write(struct dvb_frontend *fe, const u8 buf[], int len) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ ++ if (len != 2) ++ return -EINVAL; ++ ++ return m88rs2000_writereg(state, 1, buf[0], buf[1]); ++} ++ ++static u8 m88rs2000_readreg(struct m88rs2000_state *state, u8 tuner, u8 reg) ++{ ++ int ret; ++ u8 b0[] = { reg }; ++ u8 b1[] = { 0 }; ++ u8 addr = (tuner == 0) ? state->config->tuner_addr : ++ state->config->demod_addr; ++ struct i2c_msg msg[] = { ++ { ++ .addr = addr, ++ .flags = 0, ++ .buf = b0, ++ .len = 1 ++ }, { ++ .addr = addr, ++ .flags = I2C_M_RD, ++ .buf = b1, ++ .len = 1 ++ } ++ }; ++ ++ ret = i2c_transfer(state->i2c, msg, 2); ++ ++ if (ret != 2) ++ deb_info("%s: readreg error (reg == 0x%02x, ret == %i)\n", ++ __func__, reg, ret); ++ ++ return b1[0]; ++} ++ ++static u8 m88rs2000_demod_read(struct m88rs2000_state *state, u8 reg) ++{ ++ return m88rs2000_readreg(state, 1, reg); ++} ++ ++static u8 m88rs2000_tuner_read(struct m88rs2000_state *state, u8 reg) ++{ ++ m88rs2000_demod_write(state, 0x81, 0x85); ++ udelay(10); ++ return m88rs2000_readreg(state, 0, reg); ++} ++ ++static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ int ret; ++ u32 temp; ++ u8 b[3]; ++ ++ if ((srate < 1000000) || (srate > 45000000)) ++ return -EINVAL; ++ ++ temp = srate / 1000; ++ temp *= 11831; ++ temp /= 68; ++ temp -= 3; ++ ++ b[0] = (u8) (temp >> 16) & 0xff; ++ b[1] = (u8) (temp >> 8) & 0xff; ++ b[2] = (u8) temp & 0xff; ++ ret = m88rs2000_demod_write(state, 0x93, b[2]); ++ ret |= m88rs2000_demod_write(state, 0x94, b[1]); ++ ret |= m88rs2000_demod_write(state, 0x95, b[0]); ++ ++ deb_info("m88rs2000: m88rs2000_set_symbolrate\n"); ++ return ret; ++} ++ ++static int m88rs2000_send_diseqc_msg(struct dvb_frontend *fe, ++ struct dvb_diseqc_master_cmd *m) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ ++ int i; ++ u8 reg; ++ deb_info("%s\n", __func__); ++ m88rs2000_demod_write(state, 0x9a, 0x30); ++ reg = m88rs2000_demod_read(state, 0xb2); ++ reg &= 0x3f; ++ m88rs2000_demod_write(state, 0xb2, reg); ++ for (i = 0; i < m->msg_len; i++) ++ m88rs2000_demod_write(state, 0xb3 + i, m->msg[i]); ++ ++ reg = m88rs2000_demod_read(state, 0xb1); ++ reg &= 0x87; ++ reg |= ((m->msg_len - 1) << 3) | 0x07; ++ reg &= 0x7f; ++ m88rs2000_demod_write(state, 0xb1, reg); ++ ++ for (i = 0; i < 15; i++) { ++ if ((m88rs2000_demod_read(state, 0xb1) & 0x40) == 0x0) ++ break; ++ msleep(20); ++ } ++ ++ reg = m88rs2000_demod_read(state, 0xb1); ++ if ((reg & 0x40) > 0x0) { ++ reg &= 0x7f; ++ reg |= 0x40; ++ m88rs2000_demod_write(state, 0xb1, reg); ++ } ++ ++ reg = m88rs2000_demod_read(state, 0xb2); ++ reg &= 0x3f; ++ reg |= 0x80; ++ m88rs2000_demod_write(state, 0xb2, reg); ++ m88rs2000_demod_write(state, 0x9a, 0xb0); ++ ++ ++ return 0; ++} ++ ++static int m88rs2000_send_diseqc_burst(struct dvb_frontend *fe, ++ fe_sec_mini_cmd_t burst) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ u8 reg0, reg1; ++ deb_info("%s\n", __func__); ++ m88rs2000_demod_write(state, 0x9a, 0x30); ++ msleep(50); ++ reg0 = m88rs2000_demod_read(state, 0xb1); ++ reg1 = m88rs2000_demod_read(state, 0xb2); ++ /* TODO complete this section */ ++ m88rs2000_demod_write(state, 0xb2, reg1); ++ m88rs2000_demod_write(state, 0xb1, reg0); ++ m88rs2000_demod_write(state, 0x9a, 0xb0); ++ ++ return 0; ++} ++ ++static int m88rs2000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ u8 reg0, reg1; ++ m88rs2000_demod_write(state, 0x9a, 0x30); ++ reg0 = m88rs2000_demod_read(state, 0xb1); ++ reg1 = m88rs2000_demod_read(state, 0xb2); ++ ++ reg1 &= 0x3f; ++ ++ switch (tone) { ++ case SEC_TONE_ON: ++ reg0 |= 0x4; ++ reg0 &= 0xbc; ++ break; ++ case SEC_TONE_OFF: ++ reg1 |= 0x80; ++ break; ++ default: ++ break; ++ } ++ m88rs2000_demod_write(state, 0xb2, reg1); ++ m88rs2000_demod_write(state, 0xb1, reg0); ++ m88rs2000_demod_write(state, 0x9a, 0xb0); ++ return 0; ++} ++ ++struct inittab { ++ u8 cmd; ++ u8 reg; ++ u8 val; ++}; ++ ++struct inittab m88rs2000_setup[] = { ++ {DEMOD_WRITE, 0x9a, 0x30}, ++ {DEMOD_WRITE, 0x00, 0x01}, ++ {WRITE_DELAY, 0x19, 0x00}, ++ {DEMOD_WRITE, 0x00, 0x00}, ++ {DEMOD_WRITE, 0x9a, 0xb0}, ++ {DEMOD_WRITE, 0x81, 0xc1}, ++ {TUNER_WRITE, 0x42, 0x73}, ++ {TUNER_WRITE, 0x05, 0x07}, ++ {TUNER_WRITE, 0x20, 0x27}, ++ {TUNER_WRITE, 0x07, 0x02}, ++ {TUNER_WRITE, 0x11, 0xff}, ++ {TUNER_WRITE, 0x60, 0xf9}, ++ {TUNER_WRITE, 0x08, 0x01}, ++ {TUNER_WRITE, 0x00, 0x41}, ++ {DEMOD_WRITE, 0x81, 0x81}, ++ {DEMOD_WRITE, 0x86, 0xc6}, ++ {DEMOD_WRITE, 0x9a, 0x30}, ++ {DEMOD_WRITE, 0xf0, 0x22}, ++ {DEMOD_WRITE, 0xf1, 0xbf}, ++ {DEMOD_WRITE, 0xb0, 0x45}, ++ {DEMOD_WRITE, 0xb2, 0x01}, /* set voltage pin always set 1*/ ++ {DEMOD_WRITE, 0x9a, 0xb0}, ++ {0xff, 0xaa, 0xff} ++}; ++ ++struct inittab m88rs2000_shutdown[] = { ++ {DEMOD_WRITE, 0x9a, 0x30}, ++ {DEMOD_WRITE, 0xb0, 0x00}, ++ {DEMOD_WRITE, 0xf1, 0x89}, ++ {DEMOD_WRITE, 0x00, 0x01}, ++ {DEMOD_WRITE, 0x9a, 0xb0}, ++ {TUNER_WRITE, 0x00, 0x40}, ++ {DEMOD_WRITE, 0x81, 0x81}, ++ {0xff, 0xaa, 0xff} ++}; ++ ++struct inittab tuner_reset[] = { ++ {TUNER_WRITE, 0x42, 0x73}, ++ {TUNER_WRITE, 0x05, 0x07}, ++ {TUNER_WRITE, 0x20, 0x27}, ++ {TUNER_WRITE, 0x07, 0x02}, ++ {TUNER_WRITE, 0x11, 0xff}, ++ {TUNER_WRITE, 0x60, 0xf9}, ++ {TUNER_WRITE, 0x08, 0x01}, ++ {TUNER_WRITE, 0x00, 0x41}, ++ {0xff, 0xaa, 0xff} ++}; ++ ++struct inittab fe_reset[] = { ++ {DEMOD_WRITE, 0x00, 0x01}, ++ {DEMOD_WRITE, 0xf1, 0xbf}, ++ {DEMOD_WRITE, 0x00, 0x01}, ++ {DEMOD_WRITE, 0x20, 0x81}, ++ {DEMOD_WRITE, 0x21, 0x80}, ++ {DEMOD_WRITE, 0x10, 0x33}, ++ {DEMOD_WRITE, 0x11, 0x44}, ++ {DEMOD_WRITE, 0x12, 0x07}, ++ {DEMOD_WRITE, 0x18, 0x20}, ++ {DEMOD_WRITE, 0x28, 0x04}, ++ {DEMOD_WRITE, 0x29, 0x8e}, ++ {DEMOD_WRITE, 0x3b, 0xff}, ++ {DEMOD_WRITE, 0x32, 0x10}, ++ {DEMOD_WRITE, 0x33, 0x02}, ++ {DEMOD_WRITE, 0x34, 0x30}, ++ {DEMOD_WRITE, 0x35, 0xff}, ++ {DEMOD_WRITE, 0x38, 0x50}, ++ {DEMOD_WRITE, 0x39, 0x68}, ++ {DEMOD_WRITE, 0x3c, 0x7f}, ++ {DEMOD_WRITE, 0x3d, 0x0f}, ++ {DEMOD_WRITE, 0x45, 0x20}, ++ {DEMOD_WRITE, 0x46, 0x24}, ++ {DEMOD_WRITE, 0x47, 0x7c}, ++ {DEMOD_WRITE, 0x48, 0x16}, ++ {DEMOD_WRITE, 0x49, 0x04}, ++ {DEMOD_WRITE, 0x4a, 0x01}, ++ {DEMOD_WRITE, 0x4b, 0x78}, ++ {DEMOD_WRITE, 0X4d, 0xd2}, ++ {DEMOD_WRITE, 0x4e, 0x6d}, ++ {DEMOD_WRITE, 0x50, 0x30}, ++ {DEMOD_WRITE, 0x51, 0x30}, ++ {DEMOD_WRITE, 0x54, 0x7b}, ++ {DEMOD_WRITE, 0x56, 0x09}, ++ {DEMOD_WRITE, 0x58, 0x59}, ++ {DEMOD_WRITE, 0x59, 0x37}, ++ {DEMOD_WRITE, 0x63, 0xfa}, ++ {0xff, 0xaa, 0xff} ++}; ++ ++struct inittab fe_trigger[] = { ++ {DEMOD_WRITE, 0x97, 0x04}, ++ {DEMOD_WRITE, 0x99, 0x77}, ++ {DEMOD_WRITE, 0x9b, 0x64}, ++ {DEMOD_WRITE, 0x9e, 0x00}, ++ {DEMOD_WRITE, 0x9f, 0xf8}, ++ {DEMOD_WRITE, 0xa0, 0x20}, ++ {DEMOD_WRITE, 0xa1, 0xe0}, ++ {DEMOD_WRITE, 0xa3, 0x38}, ++ {DEMOD_WRITE, 0x98, 0xff}, ++ {DEMOD_WRITE, 0xc0, 0x0f}, ++ {DEMOD_WRITE, 0x89, 0x01}, ++ {DEMOD_WRITE, 0x00, 0x00}, ++ {WRITE_DELAY, 0x0a, 0x00}, ++ {DEMOD_WRITE, 0x00, 0x01}, ++ {DEMOD_WRITE, 0x00, 0x00}, ++ {DEMOD_WRITE, 0x9a, 0xb0}, ++ {0xff, 0xaa, 0xff} ++}; ++ ++static int m88rs2000_tab_set(struct m88rs2000_state *state, ++ struct inittab *tab) ++{ ++ int ret = 0; ++ u8 i; ++ if (tab == NULL) ++ return -EINVAL; ++ ++ for (i = 0; i < 255; i++) { ++ switch (tab[i].cmd) { ++ case 0x01: ++ ret = m88rs2000_demod_write(state, tab[i].reg, ++ tab[i].val); ++ break; ++ case 0x02: ++ ret = m88rs2000_tuner_write(state, tab[i].reg, ++ tab[i].val); ++ break; ++ case 0x10: ++ if (tab[i].reg > 0) ++ mdelay(tab[i].reg); ++ break; ++ case 0xff: ++ if (tab[i].reg == 0xaa && tab[i].val == 0xff) ++ return 0; ++ case 0x00: ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (ret < 0) ++ return -ENODEV; ++ } ++ return 0; ++} ++ ++static int m88rs2000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt) ++{ ++ deb_info("%s: %s\n", __func__, ++ volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" : ++ volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??"); ++ ++ return 0; ++} ++ ++static int m88rs2000_startup(struct m88rs2000_state *state) ++{ ++ int ret = 0; ++ u8 reg; ++ ++ reg = m88rs2000_tuner_read(state, 0x00); ++ if ((reg & 0x40) == 0) ++ ret = -ENODEV; ++ ++ return ret; ++} ++ ++static int m88rs2000_init(struct dvb_frontend *fe) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ int ret; ++ ++ deb_info("m88rs2000: init chip\n"); ++ /* Setup frontend from shutdown/cold */ ++ ret = m88rs2000_tab_set(state, m88rs2000_setup); ++ ++ return ret; ++} ++ ++static int m88rs2000_sleep(struct dvb_frontend *fe) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ int ret; ++ /* Shutdown the frondend */ ++ ret = m88rs2000_tab_set(state, m88rs2000_shutdown); ++ return ret; ++} ++ ++static int m88rs2000_read_status(struct dvb_frontend *fe, fe_status_t *status) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ u8 reg = m88rs2000_demod_read(state, 0x8c); ++ ++ *status = 0; ++ ++ if ((reg & 0x7) == 0x7) { ++ *status = FE_HAS_CARRIER | FE_HAS_SIGNAL | FE_HAS_VITERBI ++ | FE_HAS_LOCK; ++ if (state->config->set_ts_params) ++ state->config->set_ts_params(fe, CALL_IS_READ); ++ } ++ return 0; ++} ++ ++/* Extact code for these unknown but lmedm04 driver uses interupt callbacks */ ++ ++static int m88rs2000_read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ deb_info("m88rs2000_read_ber %d\n", *ber); ++ *ber = 0; ++ return 0; ++} ++ ++static int m88rs2000_read_signal_strength(struct dvb_frontend *fe, ++ u16 *strength) ++{ ++ *strength = 0; ++ return 0; ++} ++ ++static int m88rs2000_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ deb_info("m88rs2000_read_snr %d\n", *snr); ++ *snr = 0; ++ return 0; ++} ++ ++static int m88rs2000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ deb_info("m88rs2000_read_ber %d\n", *ucblocks); ++ *ucblocks = 0; ++ return 0; ++} ++ ++static int m88rs2000_tuner_gate_ctrl(struct m88rs2000_state *state, u8 offset) ++{ ++ int ret; ++ ret = m88rs2000_tuner_write(state, 0x51, 0x1f - offset); ++ ret |= m88rs2000_tuner_write(state, 0x51, 0x1f); ++ ret |= m88rs2000_tuner_write(state, 0x50, offset); ++ ret |= m88rs2000_tuner_write(state, 0x50, 0x00); ++ msleep(20); ++ return ret; ++} ++ ++static int m88rs2000_set_tuner_rf(struct dvb_frontend *fe) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ int reg; ++ reg = m88rs2000_tuner_read(state, 0x3d); ++ reg &= 0x7f; ++ if (reg < 0x16) ++ reg = 0xa1; ++ else if (reg == 0x16) ++ reg = 0x99; ++ else ++ reg = 0xf9; ++ ++ m88rs2000_tuner_write(state, 0x60, reg); ++ reg = m88rs2000_tuner_gate_ctrl(state, 0x08); ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ return reg; ++} ++ ++static int m88rs2000_set_tuner(struct dvb_frontend *fe, u16 *offset) ++{ ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ int ret; ++ u32 frequency = c->frequency; ++ s32 offset_khz; ++ s32 tmp; ++ u32 symbol_rate = (c->symbol_rate / 1000); ++ u32 f3db, gdiv28; ++ u16 value, ndiv, lpf_coeff; ++ u8 lpf_mxdiv, mlpf_max, mlpf_min, nlpf; ++ u8 lo = 0x01, div4 = 0x0; ++ ++ /* Reset Tuner */ ++ ret = m88rs2000_tab_set(state, tuner_reset); ++ ++ /* Calculate frequency divider */ ++ if (frequency < 1060000) { ++ lo |= 0x10; ++ div4 = 0x1; ++ ndiv = (frequency * 14 * 4) / FE_CRYSTAL_KHZ; ++ } else ++ ndiv = (frequency * 14 * 2) / FE_CRYSTAL_KHZ; ++ ndiv = ndiv + ndiv % 2; ++ ndiv = ndiv - 1024; ++ ++ ret = m88rs2000_tuner_write(state, 0x10, 0x80 | lo); ++ ++ /* Set frequency divider */ ++ ret |= m88rs2000_tuner_write(state, 0x01, (ndiv >> 8) & 0xf); ++ ret |= m88rs2000_tuner_write(state, 0x02, ndiv & 0xff); ++ ++ ret |= m88rs2000_tuner_write(state, 0x03, 0x06); ++ ret |= m88rs2000_tuner_gate_ctrl(state, 0x10); ++ if (ret < 0) ++ return -ENODEV; ++ ++ /* Tuner Frequency Range */ ++ ret = m88rs2000_tuner_write(state, 0x10, lo); ++ ++ ret |= m88rs2000_tuner_gate_ctrl(state, 0x08); ++ ++ /* Tuner RF */ ++ ret |= m88rs2000_set_tuner_rf(fe); ++ ++ gdiv28 = (FE_CRYSTAL_KHZ / 1000 * 1694 + 500) / 1000; ++ ret |= m88rs2000_tuner_write(state, 0x04, gdiv28 & 0xff); ++ ret |= m88rs2000_tuner_gate_ctrl(state, 0x04); ++ if (ret < 0) ++ return -ENODEV; ++ ++ value = m88rs2000_tuner_read(state, 0x26); ++ ++ f3db = (symbol_rate * 135) / 200 + 2000; ++ f3db += FREQ_OFFSET_LOW_SYM_RATE; ++ if (f3db < 7000) ++ f3db = 7000; ++ if (f3db > 40000) ++ f3db = 40000; ++ ++ gdiv28 = gdiv28 * 207 / (value * 2 + 151); ++ mlpf_max = gdiv28 * 135 / 100; ++ mlpf_min = gdiv28 * 78 / 100; ++ if (mlpf_max > 63) ++ mlpf_max = 63; ++ ++ lpf_coeff = 2766; ++ ++ nlpf = (f3db * gdiv28 * 2 / lpf_coeff / ++ (FE_CRYSTAL_KHZ / 1000) + 1) / 2; ++ if (nlpf > 23) ++ nlpf = 23; ++ if (nlpf < 1) ++ nlpf = 1; ++ ++ lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000) ++ * lpf_coeff * 2 / f3db + 1) / 2; ++ ++ if (lpf_mxdiv < mlpf_min) { ++ nlpf++; ++ lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000) ++ * lpf_coeff * 2 / f3db + 1) / 2; ++ } ++ ++ if (lpf_mxdiv > mlpf_max) ++ lpf_mxdiv = mlpf_max; ++ ++ ret = m88rs2000_tuner_write(state, 0x04, lpf_mxdiv); ++ ret |= m88rs2000_tuner_write(state, 0x06, nlpf); ++ ++ ret |= m88rs2000_tuner_gate_ctrl(state, 0x04); ++ ++ ret |= m88rs2000_tuner_gate_ctrl(state, 0x01); ++ ++ msleep(80); ++ /* calculate offset assuming 96000kHz*/ ++ offset_khz = (ndiv - ndiv % 2 + 1024) * FE_CRYSTAL_KHZ ++ / 14 / (div4 + 1) / 2; ++ ++ offset_khz -= frequency; ++ ++ tmp = offset_khz; ++ tmp *= 65536; ++ ++ tmp = (2 * tmp + 96000) / (2 * 96000); ++ if (tmp < 0) ++ tmp += 65536; ++ ++ *offset = tmp & 0xffff; ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ ++ return (ret < 0) ? -EINVAL : 0; ++} ++ ++static int m88rs2000_set_fec(struct m88rs2000_state *state, ++ fe_code_rate_t fec) ++{ ++ int ret; ++ u16 fec_set; ++ switch (fec) { ++ /* This is not confirmed kept for reference */ ++/* case FEC_1_2: ++ fec_set = 0x88; ++ break; ++ case FEC_2_3: ++ fec_set = 0x68; ++ break; ++ case FEC_3_4: ++ fec_set = 0x48; ++ break; ++ case FEC_5_6: ++ fec_set = 0x28; ++ break; ++ case FEC_7_8: ++ fec_set = 0x18; ++ break; */ ++ case FEC_AUTO: ++ default: ++ fec_set = 0x08; ++ } ++ ret = m88rs2000_demod_write(state, 0x76, fec_set); ++ ++ return 0; ++} ++ ++ ++static fe_code_rate_t m88rs2000_get_fec(struct m88rs2000_state *state) ++{ ++ u8 reg; ++ m88rs2000_demod_write(state, 0x9a, 0x30); ++ reg = m88rs2000_demod_read(state, 0x76); ++ m88rs2000_demod_write(state, 0x9a, 0xb0); ++ ++ switch (reg) { ++ case 0x88: ++ return FEC_1_2; ++ case 0x68: ++ return FEC_2_3; ++ case 0x48: ++ return FEC_3_4; ++ case 0x28: ++ return FEC_5_6; ++ case 0x18: ++ return FEC_7_8; ++ case 0x08: ++ default: ++ break; ++ } ++ ++ return FEC_AUTO; ++} ++ ++static int m88rs2000_set_frontend(struct dvb_frontend *fe) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ fe_status_t status; ++ int i, ret; ++ u16 offset = 0; ++ u8 reg; ++ ++ state->no_lock_count = 0; ++ ++ if (c->delivery_system != SYS_DVBS) { ++ deb_info("%s: unsupported delivery " ++ "system selected (%d)\n", ++ __func__, c->delivery_system); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Set Tuner */ ++ ret = m88rs2000_set_tuner(fe, &offset); ++ if (ret < 0) ++ return -ENODEV; ++ ++ ret = m88rs2000_demod_write(state, 0x9a, 0x30); ++ /* Unknown usually 0xc6 sometimes 0xc1 */ ++ reg = m88rs2000_demod_read(state, 0x86); ++ ret |= m88rs2000_demod_write(state, 0x86, reg); ++ /* Offset lower nibble always 0 */ ++ ret |= m88rs2000_demod_write(state, 0x9c, (offset >> 8)); ++ ret |= m88rs2000_demod_write(state, 0x9d, offset & 0xf0); ++ ++ ++ /* Reset Demod */ ++ ret = m88rs2000_tab_set(state, fe_reset); ++ if (ret < 0) ++ return -ENODEV; ++ ++ /* Unknown */ ++ reg = m88rs2000_demod_read(state, 0x70); ++ ret = m88rs2000_demod_write(state, 0x70, reg); ++ ++ /* Set FEC */ ++ ret |= m88rs2000_set_fec(state, c->fec_inner); ++ ret |= m88rs2000_demod_write(state, 0x85, 0x1); ++ ret |= m88rs2000_demod_write(state, 0x8a, 0xbf); ++ ret |= m88rs2000_demod_write(state, 0x8d, 0x1e); ++ ret |= m88rs2000_demod_write(state, 0x90, 0xf1); ++ ret |= m88rs2000_demod_write(state, 0x91, 0x08); ++ ++ if (ret < 0) ++ return -ENODEV; ++ ++ /* Set Symbol Rate */ ++ ret = m88rs2000_set_symbolrate(fe, c->symbol_rate); ++ if (ret < 0) ++ return -ENODEV; ++ ++ /* Set up Demod */ ++ ret = m88rs2000_tab_set(state, fe_trigger); ++ if (ret < 0) ++ return -ENODEV; ++ ++ for (i = 0; i < 25; i++) { ++ u8 reg = m88rs2000_demod_read(state, 0x8c); ++ if ((reg & 0x7) == 0x7) { ++ status = FE_HAS_LOCK; ++ break; ++ } ++ state->no_lock_count++; ++ if (state->no_lock_count > 15) { ++ reg = m88rs2000_demod_read(state, 0x70); ++ reg ^= 0x4; ++ m88rs2000_demod_write(state, 0x70, reg); ++ state->no_lock_count = 0; ++ } ++ if (state->no_lock_count == 20) ++ m88rs2000_set_tuner_rf(fe); ++ msleep(20); ++ } ++ ++ if (status & FE_HAS_LOCK) { ++ state->fec_inner = m88rs2000_get_fec(state); ++ /* Uknown suspect SNR level */ ++ reg = m88rs2000_demod_read(state, 0x65); ++ } ++ ++ state->tuner_frequency = c->frequency; ++ state->symbol_rate = c->symbol_rate; ++ return 0; ++} ++ ++static int m88rs2000_get_frontend(struct dvb_frontend *fe) ++{ ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ c->fec_inner = state->fec_inner; ++ c->frequency = state->tuner_frequency; ++ c->symbol_rate = state->symbol_rate; ++ return 0; ++} ++ ++static int m88rs2000_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ ++ if (enable) ++ m88rs2000_demod_write(state, 0x81, 0x84); ++ else ++ m88rs2000_demod_write(state, 0x81, 0x81); ++ udelay(10); ++ return 0; ++} ++ ++static void m88rs2000_release(struct dvb_frontend *fe) ++{ ++ struct m88rs2000_state *state = fe->demodulator_priv; ++ kfree(state); ++} ++ ++static struct dvb_frontend_ops m88rs2000_ops = { ++ .delsys = { SYS_DVBS }, ++ .info = { ++ .name = "M88RS2000 DVB-S", ++ .frequency_min = 950000, ++ .frequency_max = 2150000, ++ .frequency_stepsize = 1000, /* kHz for QPSK frontends */ ++ .frequency_tolerance = 5000, ++ .symbol_rate_min = 1000000, ++ .symbol_rate_max = 45000000, ++ .symbol_rate_tolerance = 500, /* ppm */ ++ .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | ++ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | ++ FE_CAN_QPSK | ++ FE_CAN_FEC_AUTO ++ }, ++ ++ .release = m88rs2000_release, ++ .init = m88rs2000_init, ++ .sleep = m88rs2000_sleep, ++ .write = m88rs2000_write, ++ .i2c_gate_ctrl = m88rs2000_i2c_gate_ctrl, ++ .read_status = m88rs2000_read_status, ++ .read_ber = m88rs2000_read_ber, ++ .read_signal_strength = m88rs2000_read_signal_strength, ++ .read_snr = m88rs2000_read_snr, ++ .read_ucblocks = m88rs2000_read_ucblocks, ++ .diseqc_send_master_cmd = m88rs2000_send_diseqc_msg, ++ .diseqc_send_burst = m88rs2000_send_diseqc_burst, ++ .set_tone = m88rs2000_set_tone, ++ .set_voltage = m88rs2000_set_voltage, ++ ++ .set_frontend = m88rs2000_set_frontend, ++ .get_frontend = m88rs2000_get_frontend, ++}; ++ ++struct dvb_frontend *m88rs2000_attach(const struct m88rs2000_config *config, ++ struct i2c_adapter *i2c) ++{ ++ struct m88rs2000_state *state = NULL; ++ ++ /* allocate memory for the internal state */ ++ state = kzalloc(sizeof(struct m88rs2000_state), GFP_KERNEL); ++ if (state == NULL) ++ goto error; ++ ++ /* setup the state */ ++ state->config = config; ++ state->i2c = i2c; ++ state->tuner_frequency = 0; ++ state->symbol_rate = 0; ++ state->fec_inner = 0; ++ ++ if (m88rs2000_startup(state) < 0) ++ goto error; ++ ++ /* create dvb_frontend */ ++ memcpy(&state->frontend.ops, &m88rs2000_ops, ++ sizeof(struct dvb_frontend_ops)); ++ state->frontend.demodulator_priv = state; ++ return &state->frontend; ++ ++error: ++ kfree(state); ++ ++ return NULL; ++} ++EXPORT_SYMBOL(m88rs2000_attach); ++ ++MODULE_DESCRIPTION("M88RS2000 DVB-S Demodulator driver"); ++MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION("1.13"); ++ +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/m88rs2000.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/m88rs2000.h +@@ -0,0 +1,66 @@ ++/* ++ Driver for M88RS2000 demodulator ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ ++*/ ++ ++#ifndef M88RS2000_H ++#define M88RS2000_H ++ ++#include ++#include "dvb_frontend.h" ++ ++struct m88rs2000_config { ++ /* Demodulator i2c address */ ++ u8 demod_addr; ++ /* Tuner address */ ++ u8 tuner_addr; ++ ++ u8 *inittab; ++ ++ /* minimum delay before retuning */ ++ int min_delay_ms; ++ ++ int (*set_ts_params)(struct dvb_frontend *, int); ++}; ++ ++enum { ++ CALL_IS_SET_FRONTEND = 0x0, ++ CALL_IS_READ, ++}; ++ ++#if defined(CONFIG_DVB_M88RS2000) || (defined(CONFIG_DVB_M88RS2000_MODULE) && \ ++ defined(MODULE)) ++extern struct dvb_frontend *m88rs2000_attach( ++ const struct m88rs2000_config *config, struct i2c_adapter *i2c); ++#else ++static inline struct dvb_frontend *m88rs2000_attach( ++ const struct m88rs2000_config *config, struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif /* CONFIG_DVB_M88RS2000 */ ++ ++#define FE_CRYSTAL_KHZ 27000 ++#define FREQ_OFFSET_LOW_SYM_RATE 3000 ++ ++enum { ++ DEMOD_WRITE = 0x1, ++ TUNER_WRITE, ++ WRITE_DELAY = 0x10, ++}; ++#endif /* M88RS2000_H */ +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/lmedm04.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/lmedm04.h ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/lmedm04.h +@@ -41,6 +41,7 @@ + #define LME_ST_ON_W {0x06, 0x00} + #define LME_CLEAR_PID {0x03, 0x02, 0x20, 0xa0} + #define LME_ZERO_PID {0x03, 0x06, 0x00, 0x00, 0x01, 0x00, 0x20, 0x9c} ++#define LME_ALL_PIDS {0x03, 0x06, 0x00, 0xff, 0x01, 0x1f, 0x20, 0x81} + + /* LNB Voltage + * 07 XX XX +Index: linux-3.3.x86_64/drivers/media/video/adv7183.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/adv7183.c +@@ -0,0 +1,699 @@ ++/* ++ * adv7183.c Analog Devices ADV7183 video decoder driver ++ * ++ * Copyright (c) 2011 Analog Devices Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "adv7183_regs.h" ++ ++struct adv7183 { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ ++ v4l2_std_id std; /* Current set standard */ ++ u32 input; ++ u32 output; ++ unsigned reset_pin; ++ unsigned oe_pin; ++ struct v4l2_mbus_framefmt fmt; ++}; ++ ++/* EXAMPLES USING 27 MHz CLOCK ++ * Mode 1 CVBS Input (Composite Video on AIN5) ++ * All standards are supported through autodetect, 8-bit, 4:2:2, ITU-R BT.656 output on P15 to P8. ++ */ ++static const unsigned char adv7183_init_regs[] = { ++ ADV7183_IN_CTRL, 0x04, /* CVBS input on AIN5 */ ++ ADV7183_DIGI_CLAMP_CTRL_1, 0x00, /* Slow down digital clamps */ ++ ADV7183_SHAP_FILT_CTRL, 0x41, /* Set CSFM to SH1 */ ++ ADV7183_ADC_CTRL, 0x16, /* Power down ADC 1 and ADC 2 */ ++ ADV7183_CTI_DNR_CTRL_4, 0x04, /* Set DNR threshold to 4 for flat response */ ++ /* ADI recommended programming sequence */ ++ ADV7183_ADI_CTRL, 0x80, ++ ADV7183_CTI_DNR_CTRL_4, 0x20, ++ 0x52, 0x18, ++ 0x58, 0xED, ++ 0x77, 0xC5, ++ 0x7C, 0x93, ++ 0x7D, 0x00, ++ 0xD0, 0x48, ++ 0xD5, 0xA0, ++ 0xD7, 0xEA, ++ ADV7183_SD_SATURATION_CR, 0x3E, ++ ADV7183_PAL_V_END, 0x3E, ++ ADV7183_PAL_F_TOGGLE, 0x0F, ++ ADV7183_ADI_CTRL, 0x00, ++}; ++ ++static inline struct adv7183 *to_adv7183(struct v4l2_subdev *sd) ++{ ++ return container_of(sd, struct adv7183, sd); ++} ++static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) ++{ ++ return &container_of(ctrl->handler, struct adv7183, hdl)->sd; ++} ++ ++static inline int adv7183_read(struct v4l2_subdev *sd, unsigned char reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return i2c_smbus_read_byte_data(client, reg); ++} ++ ++static inline int adv7183_write(struct v4l2_subdev *sd, unsigned char reg, ++ unsigned char value) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return i2c_smbus_write_byte_data(client, reg, value); ++} ++ ++static int adv7183_writeregs(struct v4l2_subdev *sd, ++ const unsigned char *regs, unsigned int num) ++{ ++ unsigned char reg, data; ++ unsigned int cnt = 0; ++ ++ if (num & 0x1) { ++ v4l2_err(sd, "invalid regs array\n"); ++ return -1; ++ } ++ ++ while (cnt < num) { ++ reg = *regs++; ++ data = *regs++; ++ cnt += 2; ++ ++ adv7183_write(sd, reg, data); ++ } ++ return 0; ++} ++ ++static int adv7183_log_status(struct v4l2_subdev *sd) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ ++ v4l2_info(sd, "adv7183: Input control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_IN_CTRL)); ++ v4l2_info(sd, "adv7183: Video selection = 0x%02x\n", ++ adv7183_read(sd, ADV7183_VD_SEL)); ++ v4l2_info(sd, "adv7183: Output control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_OUT_CTRL)); ++ v4l2_info(sd, "adv7183: Extended output control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_EXT_OUT_CTRL)); ++ v4l2_info(sd, "adv7183: Autodetect enable = 0x%02x\n", ++ adv7183_read(sd, ADV7183_AUTO_DET_EN)); ++ v4l2_info(sd, "adv7183: Contrast = 0x%02x\n", ++ adv7183_read(sd, ADV7183_CONTRAST)); ++ v4l2_info(sd, "adv7183: Brightness = 0x%02x\n", ++ adv7183_read(sd, ADV7183_BRIGHTNESS)); ++ v4l2_info(sd, "adv7183: Hue = 0x%02x\n", ++ adv7183_read(sd, ADV7183_HUE)); ++ v4l2_info(sd, "adv7183: Default value Y = 0x%02x\n", ++ adv7183_read(sd, ADV7183_DEF_Y)); ++ v4l2_info(sd, "adv7183: Default value C = 0x%02x\n", ++ adv7183_read(sd, ADV7183_DEF_C)); ++ v4l2_info(sd, "adv7183: ADI control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_ADI_CTRL)); ++ v4l2_info(sd, "adv7183: Power Management = 0x%02x\n", ++ adv7183_read(sd, ADV7183_POW_MANAGE)); ++ v4l2_info(sd, "adv7183: Status 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n", ++ adv7183_read(sd, ADV7183_STATUS_1), ++ adv7183_read(sd, ADV7183_STATUS_2), ++ adv7183_read(sd, ADV7183_STATUS_3)); ++ v4l2_info(sd, "adv7183: Ident = 0x%02x\n", ++ adv7183_read(sd, ADV7183_IDENT)); ++ v4l2_info(sd, "adv7183: Analog clamp control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_ANAL_CLAMP_CTRL)); ++ v4l2_info(sd, "adv7183: Digital clamp control 1 = 0x%02x\n", ++ adv7183_read(sd, ADV7183_DIGI_CLAMP_CTRL_1)); ++ v4l2_info(sd, "adv7183: Shaping filter control 1 and 2 = 0x%02x 0x%02x\n", ++ adv7183_read(sd, ADV7183_SHAP_FILT_CTRL), ++ adv7183_read(sd, ADV7183_SHAP_FILT_CTRL_2)); ++ v4l2_info(sd, "adv7183: Comb filter control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_COMB_FILT_CTRL)); ++ v4l2_info(sd, "adv7183: ADI control 2 = 0x%02x\n", ++ adv7183_read(sd, ADV7183_ADI_CTRL_2)); ++ v4l2_info(sd, "adv7183: Pixel delay control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_PIX_DELAY_CTRL)); ++ v4l2_info(sd, "adv7183: Misc gain control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_MISC_GAIN_CTRL)); ++ v4l2_info(sd, "adv7183: AGC mode control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_AGC_MODE_CTRL)); ++ v4l2_info(sd, "adv7183: Chroma gain control 1 and 2 = 0x%02x 0x%02x\n", ++ adv7183_read(sd, ADV7183_CHRO_GAIN_CTRL_1), ++ adv7183_read(sd, ADV7183_CHRO_GAIN_CTRL_2)); ++ v4l2_info(sd, "adv7183: Luma gain control 1 and 2 = 0x%02x 0x%02x\n", ++ adv7183_read(sd, ADV7183_LUMA_GAIN_CTRL_1), ++ adv7183_read(sd, ADV7183_LUMA_GAIN_CTRL_2)); ++ v4l2_info(sd, "adv7183: Vsync field control 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n", ++ adv7183_read(sd, ADV7183_VS_FIELD_CTRL_1), ++ adv7183_read(sd, ADV7183_VS_FIELD_CTRL_2), ++ adv7183_read(sd, ADV7183_VS_FIELD_CTRL_3)); ++ v4l2_info(sd, "adv7183: Hsync positon control 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n", ++ adv7183_read(sd, ADV7183_HS_POS_CTRL_1), ++ adv7183_read(sd, ADV7183_HS_POS_CTRL_2), ++ adv7183_read(sd, ADV7183_HS_POS_CTRL_3)); ++ v4l2_info(sd, "adv7183: Polarity = 0x%02x\n", ++ adv7183_read(sd, ADV7183_POLARITY)); ++ v4l2_info(sd, "adv7183: ADC control = 0x%02x\n", ++ adv7183_read(sd, ADV7183_ADC_CTRL)); ++ v4l2_info(sd, "adv7183: SD offset Cb and Cr = 0x%02x 0x%02x\n", ++ adv7183_read(sd, ADV7183_SD_OFFSET_CB), ++ adv7183_read(sd, ADV7183_SD_OFFSET_CR)); ++ v4l2_info(sd, "adv7183: SD saturation Cb and Cr = 0x%02x 0x%02x\n", ++ adv7183_read(sd, ADV7183_SD_SATURATION_CB), ++ adv7183_read(sd, ADV7183_SD_SATURATION_CR)); ++ v4l2_info(sd, "adv7183: Drive strength = 0x%02x\n", ++ adv7183_read(sd, ADV7183_DRIVE_STR)); ++ v4l2_ctrl_handler_log_status(&decoder->hdl, sd->name); ++ return 0; ++} ++ ++static int adv7183_g_std(struct v4l2_subdev *sd, v4l2_std_id *std) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ ++ *std = decoder->std; ++ return 0; ++} ++ ++static int adv7183_s_std(struct v4l2_subdev *sd, v4l2_std_id std) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ int reg; ++ ++ reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF; ++ if (std == V4L2_STD_PAL_60) ++ reg |= 0x60; ++ else if (std == V4L2_STD_NTSC_443) ++ reg |= 0x70; ++ else if (std == V4L2_STD_PAL_N) ++ reg |= 0x90; ++ else if (std == V4L2_STD_PAL_M) ++ reg |= 0xA0; ++ else if (std == V4L2_STD_PAL_Nc) ++ reg |= 0xC0; ++ else if (std & V4L2_STD_PAL) ++ reg |= 0x80; ++ else if (std & V4L2_STD_NTSC) ++ reg |= 0x50; ++ else if (std & V4L2_STD_SECAM) ++ reg |= 0xE0; ++ else ++ return -EINVAL; ++ adv7183_write(sd, ADV7183_IN_CTRL, reg); ++ ++ decoder->std = std; ++ ++ return 0; ++} ++ ++static int adv7183_reset(struct v4l2_subdev *sd, u32 val) ++{ ++ int reg; ++ ++ reg = adv7183_read(sd, ADV7183_POW_MANAGE) | 0x80; ++ adv7183_write(sd, ADV7183_POW_MANAGE, reg); ++ /* wait 5ms before any further i2c writes are performed */ ++ usleep_range(5000, 10000); ++ return 0; ++} ++ ++static int adv7183_s_routing(struct v4l2_subdev *sd, ++ u32 input, u32 output, u32 config) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ int reg; ++ ++ if ((input > ADV7183_COMPONENT1) || (output > ADV7183_16BIT_OUT)) ++ return -EINVAL; ++ ++ if (input != decoder->input) { ++ decoder->input = input; ++ reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF0; ++ switch (input) { ++ case ADV7183_COMPOSITE1: ++ reg |= 0x1; ++ break; ++ case ADV7183_COMPOSITE2: ++ reg |= 0x2; ++ break; ++ case ADV7183_COMPOSITE3: ++ reg |= 0x3; ++ break; ++ case ADV7183_COMPOSITE4: ++ reg |= 0x4; ++ break; ++ case ADV7183_COMPOSITE5: ++ reg |= 0x5; ++ break; ++ case ADV7183_COMPOSITE6: ++ reg |= 0xB; ++ break; ++ case ADV7183_COMPOSITE7: ++ reg |= 0xC; ++ break; ++ case ADV7183_COMPOSITE8: ++ reg |= 0xD; ++ break; ++ case ADV7183_COMPOSITE9: ++ reg |= 0xE; ++ break; ++ case ADV7183_COMPOSITE10: ++ reg |= 0xF; ++ break; ++ case ADV7183_SVIDEO0: ++ reg |= 0x6; ++ break; ++ case ADV7183_SVIDEO1: ++ reg |= 0x7; ++ break; ++ case ADV7183_SVIDEO2: ++ reg |= 0x8; ++ break; ++ case ADV7183_COMPONENT0: ++ reg |= 0x9; ++ break; ++ case ADV7183_COMPONENT1: ++ reg |= 0xA; ++ break; ++ default: ++ break; ++ } ++ adv7183_write(sd, ADV7183_IN_CTRL, reg); ++ } ++ ++ if (output != decoder->output) { ++ decoder->output = output; ++ reg = adv7183_read(sd, ADV7183_OUT_CTRL) & 0xC0; ++ switch (output) { ++ case ADV7183_16BIT_OUT: ++ reg |= 0x9; ++ break; ++ default: ++ reg |= 0xC; ++ break; ++ } ++ adv7183_write(sd, ADV7183_OUT_CTRL, reg); ++ } ++ ++ return 0; ++} ++ ++static int adv7183_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ int val = ctrl->val; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ if (val < 0) ++ val = 127 - val; ++ adv7183_write(sd, ADV7183_BRIGHTNESS, val); ++ break; ++ case V4L2_CID_CONTRAST: ++ adv7183_write(sd, ADV7183_CONTRAST, val); ++ break; ++ case V4L2_CID_SATURATION: ++ adv7183_write(sd, ADV7183_SD_SATURATION_CB, val >> 8); ++ adv7183_write(sd, ADV7183_SD_SATURATION_CR, (val & 0xFF)); ++ break; ++ case V4L2_CID_HUE: ++ adv7183_write(sd, ADV7183_SD_OFFSET_CB, val >> 8); ++ adv7183_write(sd, ADV7183_SD_OFFSET_CR, (val & 0xFF)); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int adv7183_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ int reg; ++ ++ /* enable autodetection block */ ++ reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF; ++ adv7183_write(sd, ADV7183_IN_CTRL, reg); ++ ++ /* wait autodetection switch */ ++ mdelay(10); ++ ++ /* get autodetection result */ ++ reg = adv7183_read(sd, ADV7183_STATUS_1); ++ switch ((reg >> 0x4) & 0x7) { ++ case 0: ++ *std = V4L2_STD_NTSC; ++ break; ++ case 1: ++ *std = V4L2_STD_NTSC_443; ++ break; ++ case 2: ++ *std = V4L2_STD_PAL_M; ++ break; ++ case 3: ++ *std = V4L2_STD_PAL_60; ++ break; ++ case 4: ++ *std = V4L2_STD_PAL; ++ break; ++ case 5: ++ *std = V4L2_STD_SECAM; ++ break; ++ case 6: ++ *std = V4L2_STD_PAL_Nc; ++ break; ++ case 7: ++ *std = V4L2_STD_SECAM; ++ break; ++ default: ++ *std = V4L2_STD_UNKNOWN; ++ break; ++ } ++ ++ /* after std detection, write back user set std */ ++ adv7183_s_std(sd, decoder->std); ++ return 0; ++} ++ ++static int adv7183_g_input_status(struct v4l2_subdev *sd, u32 *status) ++{ ++ int reg; ++ ++ *status = V4L2_IN_ST_NO_SIGNAL; ++ reg = adv7183_read(sd, ADV7183_STATUS_1); ++ if (reg < 0) ++ return reg; ++ if (reg & 0x1) ++ *status = 0; ++ return 0; ++} ++ ++static int adv7183_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, ++ enum v4l2_mbus_pixelcode *code) ++{ ++ if (index > 0) ++ return -EINVAL; ++ ++ *code = V4L2_MBUS_FMT_UYVY8_2X8; ++ return 0; ++} ++ ++static int adv7183_try_mbus_fmt(struct v4l2_subdev *sd, ++ struct v4l2_mbus_framefmt *fmt) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ ++ fmt->code = V4L2_MBUS_FMT_UYVY8_2X8; ++ fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ if (decoder->std & V4L2_STD_525_60) { ++ fmt->field = V4L2_FIELD_SEQ_TB; ++ fmt->width = 720; ++ fmt->height = 480; ++ } else { ++ fmt->field = V4L2_FIELD_SEQ_BT; ++ fmt->width = 720; ++ fmt->height = 576; ++ } ++ return 0; ++} ++ ++static int adv7183_s_mbus_fmt(struct v4l2_subdev *sd, ++ struct v4l2_mbus_framefmt *fmt) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ ++ adv7183_try_mbus_fmt(sd, fmt); ++ decoder->fmt = *fmt; ++ return 0; ++} ++ ++static int adv7183_g_mbus_fmt(struct v4l2_subdev *sd, ++ struct v4l2_mbus_framefmt *fmt) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ ++ *fmt = decoder->fmt; ++ return 0; ++} ++ ++static int adv7183_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ struct adv7183 *decoder = to_adv7183(sd); ++ ++ if (enable) ++ gpio_direction_output(decoder->oe_pin, 0); ++ else ++ gpio_direction_output(decoder->oe_pin, 1); ++ udelay(1); ++ return 0; ++} ++ ++static int adv7183_g_chip_ident(struct v4l2_subdev *sd, ++ struct v4l2_dbg_chip_ident *chip) ++{ ++ int rev; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ /* 0x11 for adv7183, 0x13 for adv7183b */ ++ rev = adv7183_read(sd, ADV7183_IDENT); ++ ++ return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7183, rev); ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int adv7183_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ if (!v4l2_chip_match_i2c_client(client, ®->match)) ++ return -EINVAL; ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ reg->val = adv7183_read(sd, reg->reg & 0xff); ++ reg->size = 1; ++ return 0; ++} ++ ++static int adv7183_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ if (!v4l2_chip_match_i2c_client(client, ®->match)) ++ return -EINVAL; ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ adv7183_write(sd, reg->reg & 0xff, reg->val & 0xff); ++ return 0; ++} ++#endif ++ ++static const struct v4l2_ctrl_ops adv7183_ctrl_ops = { ++ .s_ctrl = adv7183_s_ctrl, ++}; ++ ++static const struct v4l2_subdev_core_ops adv7183_core_ops = { ++ .log_status = adv7183_log_status, ++ .g_std = adv7183_g_std, ++ .s_std = adv7183_s_std, ++ .reset = adv7183_reset, ++ .g_chip_ident = adv7183_g_chip_ident, ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = adv7183_g_register, ++ .s_register = adv7183_s_register, ++#endif ++}; ++ ++static const struct v4l2_subdev_video_ops adv7183_video_ops = { ++ .s_routing = adv7183_s_routing, ++ .querystd = adv7183_querystd, ++ .g_input_status = adv7183_g_input_status, ++ .enum_mbus_fmt = adv7183_enum_mbus_fmt, ++ .try_mbus_fmt = adv7183_try_mbus_fmt, ++ .s_mbus_fmt = adv7183_s_mbus_fmt, ++ .g_mbus_fmt = adv7183_g_mbus_fmt, ++ .s_stream = adv7183_s_stream, ++}; ++ ++static const struct v4l2_subdev_ops adv7183_ops = { ++ .core = &adv7183_core_ops, ++ .video = &adv7183_video_ops, ++}; ++ ++static int adv7183_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct adv7183 *decoder; ++ struct v4l2_subdev *sd; ++ struct v4l2_ctrl_handler *hdl; ++ int ret; ++ struct v4l2_mbus_framefmt fmt; ++ const unsigned *pin_array; ++ ++ /* Check if the adapter supports the needed features */ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) ++ return -EIO; ++ ++ v4l_info(client, "chip found @ 0x%02x (%s)\n", ++ client->addr << 1, client->adapter->name); ++ ++ pin_array = client->dev.platform_data; ++ if (pin_array == NULL) ++ return -EINVAL; ++ ++ decoder = kzalloc(sizeof(struct adv7183), GFP_KERNEL); ++ if (decoder == NULL) ++ return -ENOMEM; ++ ++ decoder->reset_pin = pin_array[0]; ++ decoder->oe_pin = pin_array[1]; ++ ++ if (gpio_request(decoder->reset_pin, "ADV7183 Reset")) { ++ v4l_err(client, "failed to request GPIO %d\n", decoder->reset_pin); ++ ret = -EBUSY; ++ goto err_free_decoder; ++ } ++ ++ if (gpio_request(decoder->oe_pin, "ADV7183 Output Enable")) { ++ v4l_err(client, "failed to request GPIO %d\n", decoder->oe_pin); ++ ret = -EBUSY; ++ goto err_free_reset; ++ } ++ ++ sd = &decoder->sd; ++ v4l2_i2c_subdev_init(sd, client, &adv7183_ops); ++ ++ hdl = &decoder->hdl; ++ v4l2_ctrl_handler_init(hdl, 4); ++ v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); ++ v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 0xFF, 1, 0x80); ++ v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 0xFFFF, 1, 0x8080); ++ v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops, ++ V4L2_CID_HUE, 0, 0xFFFF, 1, 0x8080); ++ /* hook the control handler into the driver */ ++ sd->ctrl_handler = hdl; ++ if (hdl->error) { ++ ret = hdl->error; ++ ++ v4l2_ctrl_handler_free(hdl); ++ goto err_free_oe; ++ } ++ ++ /* v4l2 doesn't support an autodetect standard, pick PAL as default */ ++ decoder->std = V4L2_STD_PAL; ++ decoder->input = ADV7183_COMPOSITE4; ++ decoder->output = ADV7183_8BIT_OUT; ++ ++ gpio_direction_output(decoder->oe_pin, 1); ++ /* reset chip */ ++ gpio_direction_output(decoder->reset_pin, 0); ++ /* reset pulse width at least 5ms */ ++ mdelay(10); ++ gpio_direction_output(decoder->reset_pin, 1); ++ /* wait 5ms before any further i2c writes are performed */ ++ mdelay(5); ++ ++ adv7183_writeregs(sd, adv7183_init_regs, ARRAY_SIZE(adv7183_init_regs)); ++ adv7183_s_std(sd, decoder->std); ++ fmt.width = 720; ++ fmt.height = 576; ++ adv7183_s_mbus_fmt(sd, &fmt); ++ ++ /* initialize the hardware to the default control values */ ++ ret = v4l2_ctrl_handler_setup(hdl); ++ if (ret) { ++ v4l2_ctrl_handler_free(hdl); ++ goto err_free_oe; ++ } ++ ++ return 0; ++err_free_oe: ++ gpio_free(decoder->oe_pin); ++err_free_reset: ++ gpio_free(decoder->reset_pin); ++err_free_decoder: ++ kfree(decoder); ++ return ret; ++} ++ ++static int adv7183_remove(struct i2c_client *client) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(client); ++ struct adv7183 *decoder = to_adv7183(sd); ++ ++ v4l2_device_unregister_subdev(sd); ++ v4l2_ctrl_handler_free(sd->ctrl_handler); ++ gpio_free(decoder->oe_pin); ++ gpio_free(decoder->reset_pin); ++ kfree(decoder); ++ return 0; ++} ++ ++static const struct i2c_device_id adv7183_id[] = { ++ {"adv7183", 0}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(i2c, adv7183_id); ++ ++static struct i2c_driver adv7183_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "adv7183", ++ }, ++ .probe = adv7183_probe, ++ .remove = __devexit_p(adv7183_remove), ++ .id_table = adv7183_id, ++}; ++ ++static __init int adv7183_init(void) ++{ ++ return i2c_add_driver(&adv7183_driver); ++} ++ ++static __exit void adv7183_exit(void) ++{ ++ i2c_del_driver(&adv7183_driver); ++} ++ ++module_init(adv7183_init); ++module_exit(adv7183_exit); ++ ++MODULE_DESCRIPTION("Analog Devices ADV7183 video decoder driver"); ++MODULE_AUTHOR("Scott Jiang "); ++MODULE_LICENSE("GPL v2"); +Index: linux-3.3.x86_64/drivers/media/video/adv7183_regs.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/adv7183_regs.h +@@ -0,0 +1,107 @@ ++/* ++ * adv7183 - Analog Devices ADV7183 video decoder registers ++ * ++ * Copyright (c) 2011 Analog Devices Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef _ADV7183_REGS_H_ ++#define _ADV7183_REGS_H_ ++ ++#define ADV7183_IN_CTRL 0x00 /* Input control */ ++#define ADV7183_VD_SEL 0x01 /* Video selection */ ++#define ADV7183_OUT_CTRL 0x03 /* Output control */ ++#define ADV7183_EXT_OUT_CTRL 0x04 /* Extended output control */ ++#define ADV7183_AUTO_DET_EN 0x07 /* Autodetect enable */ ++#define ADV7183_CONTRAST 0x08 /* Contrast */ ++#define ADV7183_BRIGHTNESS 0x0A /* Brightness */ ++#define ADV7183_HUE 0x0B /* Hue */ ++#define ADV7183_DEF_Y 0x0C /* Default value Y */ ++#define ADV7183_DEF_C 0x0D /* Default value C */ ++#define ADV7183_ADI_CTRL 0x0E /* ADI control */ ++#define ADV7183_POW_MANAGE 0x0F /* Power Management */ ++#define ADV7183_STATUS_1 0x10 /* Status 1 */ ++#define ADV7183_IDENT 0x11 /* Ident */ ++#define ADV7183_STATUS_2 0x12 /* Status 2 */ ++#define ADV7183_STATUS_3 0x13 /* Status 3 */ ++#define ADV7183_ANAL_CLAMP_CTRL 0x14 /* Analog clamp control */ ++#define ADV7183_DIGI_CLAMP_CTRL_1 0x15 /* Digital clamp control 1 */ ++#define ADV7183_SHAP_FILT_CTRL 0x17 /* Shaping filter control */ ++#define ADV7183_SHAP_FILT_CTRL_2 0x18 /* Shaping filter control 2 */ ++#define ADV7183_COMB_FILT_CTRL 0x19 /* Comb filter control */ ++#define ADV7183_ADI_CTRL_2 0x1D /* ADI control 2 */ ++#define ADV7183_PIX_DELAY_CTRL 0x27 /* Pixel delay control */ ++#define ADV7183_MISC_GAIN_CTRL 0x2B /* Misc gain control */ ++#define ADV7183_AGC_MODE_CTRL 0x2C /* AGC mode control */ ++#define ADV7183_CHRO_GAIN_CTRL_1 0x2D /* Chroma gain control 1 */ ++#define ADV7183_CHRO_GAIN_CTRL_2 0x2E /* Chroma gain control 2 */ ++#define ADV7183_LUMA_GAIN_CTRL_1 0x2F /* Luma gain control 1 */ ++#define ADV7183_LUMA_GAIN_CTRL_2 0x30 /* Luma gain control 2 */ ++#define ADV7183_VS_FIELD_CTRL_1 0x31 /* Vsync field control 1 */ ++#define ADV7183_VS_FIELD_CTRL_2 0x32 /* Vsync field control 2 */ ++#define ADV7183_VS_FIELD_CTRL_3 0x33 /* Vsync field control 3 */ ++#define ADV7183_HS_POS_CTRL_1 0x34 /* Hsync positon control 1 */ ++#define ADV7183_HS_POS_CTRL_2 0x35 /* Hsync positon control 2 */ ++#define ADV7183_HS_POS_CTRL_3 0x36 /* Hsync positon control 3 */ ++#define ADV7183_POLARITY 0x37 /* Polarity */ ++#define ADV7183_NTSC_COMB_CTRL 0x38 /* NTSC comb control */ ++#define ADV7183_PAL_COMB_CTRL 0x39 /* PAL comb control */ ++#define ADV7183_ADC_CTRL 0x3A /* ADC control */ ++#define ADV7183_MAN_WIN_CTRL 0x3D /* Manual window control */ ++#define ADV7183_RESAMPLE_CTRL 0x41 /* Resample control */ ++#define ADV7183_GEMSTAR_CTRL_1 0x48 /* Gemstar ctrl 1 */ ++#define ADV7183_GEMSTAR_CTRL_2 0x49 /* Gemstar ctrl 2 */ ++#define ADV7183_GEMSTAR_CTRL_3 0x4A /* Gemstar ctrl 3 */ ++#define ADV7183_GEMSTAR_CTRL_4 0x4B /* Gemstar ctrl 4 */ ++#define ADV7183_GEMSTAR_CTRL_5 0x4C /* Gemstar ctrl 5 */ ++#define ADV7183_CTI_DNR_CTRL_1 0x4D /* CTI DNR ctrl 1 */ ++#define ADV7183_CTI_DNR_CTRL_2 0x4E /* CTI DNR ctrl 2 */ ++#define ADV7183_CTI_DNR_CTRL_4 0x50 /* CTI DNR ctrl 4 */ ++#define ADV7183_LOCK_CNT 0x51 /* Lock count */ ++#define ADV7183_FREE_LINE_LEN 0x8F /* Free-Run line length 1 */ ++#define ADV7183_VBI_INFO 0x90 /* VBI info */ ++#define ADV7183_WSS_1 0x91 /* WSS 1 */ ++#define ADV7183_WSS_2 0x92 /* WSS 2 */ ++#define ADV7183_EDTV_1 0x93 /* EDTV 1 */ ++#define ADV7183_EDTV_2 0x94 /* EDTV 2 */ ++#define ADV7183_EDTV_3 0x95 /* EDTV 3 */ ++#define ADV7183_CGMS_1 0x96 /* CGMS 1 */ ++#define ADV7183_CGMS_2 0x97 /* CGMS 2 */ ++#define ADV7183_CGMS_3 0x98 /* CGMS 3 */ ++#define ADV7183_CCAP_1 0x99 /* CCAP 1 */ ++#define ADV7183_CCAP_2 0x9A /* CCAP 2 */ ++#define ADV7183_LETTERBOX_1 0x9B /* Letterbox 1 */ ++#define ADV7183_LETTERBOX_2 0x9C /* Letterbox 2 */ ++#define ADV7183_LETTERBOX_3 0x9D /* Letterbox 3 */ ++#define ADV7183_CRC_EN 0xB2 /* CRC enable */ ++#define ADV7183_ADC_SWITCH_1 0xC3 /* ADC switch 1 */ ++#define ADV7183_ADC_SWITCH_2 0xC4 /* ADC swithc 2 */ ++#define ADV7183_LETTERBOX_CTRL_1 0xDC /* Letterbox control 1 */ ++#define ADV7183_LETTERBOX_CTRL_2 0xDD /* Letterbox control 2 */ ++#define ADV7183_SD_OFFSET_CB 0xE1 /* SD offset Cb */ ++#define ADV7183_SD_OFFSET_CR 0xE2 /* SD offset Cr */ ++#define ADV7183_SD_SATURATION_CB 0xE3 /* SD saturation Cb */ ++#define ADV7183_SD_SATURATION_CR 0xE4 /* SD saturation Cr */ ++#define ADV7183_NTSC_V_BEGIN 0xE5 /* NTSC V bit begin */ ++#define ADV7183_NTSC_V_END 0xE6 /* NTSC V bit end */ ++#define ADV7183_NTSC_F_TOGGLE 0xE7 /* NTSC F bit toggle */ ++#define ADV7183_PAL_V_BEGIN 0xE8 /* PAL V bit begin */ ++#define ADV7183_PAL_V_END 0xE9 /* PAL V bit end */ ++#define ADV7183_PAL_F_TOGGLE 0xEA /* PAL F bit toggle */ ++#define ADV7183_DRIVE_STR 0xF4 /* Drive strength */ ++#define ADV7183_IF_COMP_CTRL 0xF8 /* IF comp control */ ++#define ADV7183_VS_MODE_CTRL 0xF9 /* VS mode control */ ++ ++#endif +Index: linux-3.3.x86_64/include/media/adv7183.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/include/media/adv7183.h +@@ -0,0 +1,47 @@ ++/* ++ * adv7183.h - definition for adv7183 inputs and outputs ++ * ++ * Copyright (c) 2011 Analog Devices Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef _ADV7183_H_ ++#define _ADV7183_H_ ++ ++/* ADV7183 HW inputs */ ++#define ADV7183_COMPOSITE0 0 /* CVBS in on AIN1 */ ++#define ADV7183_COMPOSITE1 1 /* CVBS in on AIN2 */ ++#define ADV7183_COMPOSITE2 2 /* CVBS in on AIN3 */ ++#define ADV7183_COMPOSITE3 3 /* CVBS in on AIN4 */ ++#define ADV7183_COMPOSITE4 4 /* CVBS in on AIN5 */ ++#define ADV7183_COMPOSITE5 5 /* CVBS in on AIN6 */ ++#define ADV7183_COMPOSITE6 6 /* CVBS in on AIN7 */ ++#define ADV7183_COMPOSITE7 7 /* CVBS in on AIN8 */ ++#define ADV7183_COMPOSITE8 8 /* CVBS in on AIN9 */ ++#define ADV7183_COMPOSITE9 9 /* CVBS in on AIN10 */ ++#define ADV7183_COMPOSITE10 10 /* CVBS in on AIN11 */ ++ ++#define ADV7183_SVIDEO0 11 /* Y on AIN1, C on AIN4 */ ++#define ADV7183_SVIDEO1 12 /* Y on AIN2, C on AIN5 */ ++#define ADV7183_SVIDEO2 13 /* Y on AIN3, C on AIN6 */ ++ ++#define ADV7183_COMPONENT0 14 /* Y on AIN1, Pr on AIN4, Pb on AIN5 */ ++#define ADV7183_COMPONENT1 15 /* Y on AIN2, Pr on AIN3, Pb on AIN6 */ ++ ++/* ADV7183 HW outputs */ ++#define ADV7183_8BIT_OUT 0 ++#define ADV7183_16BIT_OUT 1 ++ ++#endif +Index: linux-3.3.x86_64/include/media/v4l2-chip-ident.h +=================================================================== +--- linux-3.3.x86_64.orig/include/media/v4l2-chip-ident.h ++++ linux-3.3.x86_64/include/media/v4l2-chip-ident.h +@@ -143,6 +143,9 @@ enum { + /* module saa6588: just ident 6588 */ + V4L2_IDENT_SAA6588 = 6588, + ++ /* module vs6624: just ident 6624 */ ++ V4L2_IDENT_VS6624 = 6624, ++ + /* module saa6752hs: reserved range 6750-6759 */ + V4L2_IDENT_SAA6752HS = 6752, + V4L2_IDENT_SAA6752HS_AC3 = 6753, +@@ -162,6 +165,9 @@ enum { + /* module adv7180: just ident 7180 */ + V4L2_IDENT_ADV7180 = 7180, + ++ /* module adv7183: just ident 7183 */ ++ V4L2_IDENT_ADV7183 = 7183, ++ + /* module saa7185: just ident 7185 */ + V4L2_IDENT_SAA7185 = 7185, + +Index: linux-3.3.x86_64/drivers/media/video/vs6624.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/vs6624.c +@@ -0,0 +1,928 @@ ++/* ++ * vs6624.c ST VS6624 CMOS image sensor driver ++ * ++ * Copyright (c) 2011 Analog Devices Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "vs6624_regs.h" ++ ++#define VGA_WIDTH 640 ++#define VGA_HEIGHT 480 ++#define QVGA_WIDTH 320 ++#define QVGA_HEIGHT 240 ++#define QQVGA_WIDTH 160 ++#define QQVGA_HEIGHT 120 ++#define CIF_WIDTH 352 ++#define CIF_HEIGHT 288 ++#define QCIF_WIDTH 176 ++#define QCIF_HEIGHT 144 ++#define QQCIF_WIDTH 88 ++#define QQCIF_HEIGHT 72 ++ ++#define MAX_FRAME_RATE 30 ++ ++struct vs6624 { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct v4l2_fract frame_rate; ++ struct v4l2_mbus_framefmt fmt; ++ unsigned ce_pin; ++}; ++ ++static const struct vs6624_format { ++ enum v4l2_mbus_pixelcode mbus_code; ++ enum v4l2_colorspace colorspace; ++} vs6624_formats[] = { ++ { ++ .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, ++ .colorspace = V4L2_COLORSPACE_JPEG, ++ }, ++ { ++ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, ++ .colorspace = V4L2_COLORSPACE_JPEG, ++ }, ++ { ++ .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, ++ .colorspace = V4L2_COLORSPACE_SRGB, ++ }, ++}; ++ ++static struct v4l2_mbus_framefmt vs6624_default_fmt = { ++ .width = VGA_WIDTH, ++ .height = VGA_HEIGHT, ++ .code = V4L2_MBUS_FMT_UYVY8_2X8, ++ .field = V4L2_FIELD_NONE, ++ .colorspace = V4L2_COLORSPACE_JPEG, ++}; ++ ++static const u16 vs6624_p1[] = { ++ 0x8104, 0x03, ++ 0x8105, 0x01, ++ 0xc900, 0x03, ++ 0xc904, 0x47, ++ 0xc905, 0x10, ++ 0xc906, 0x80, ++ 0xc907, 0x3a, ++ 0x903a, 0x02, ++ 0x903b, 0x47, ++ 0x903c, 0x15, ++ 0xc908, 0x31, ++ 0xc909, 0xdc, ++ 0xc90a, 0x80, ++ 0xc90b, 0x44, ++ 0x9044, 0x02, ++ 0x9045, 0x31, ++ 0x9046, 0xe2, ++ 0xc90c, 0x07, ++ 0xc90d, 0xe0, ++ 0xc90e, 0x80, ++ 0xc90f, 0x47, ++ 0x9047, 0x90, ++ 0x9048, 0x83, ++ 0x9049, 0x81, ++ 0x904a, 0xe0, ++ 0x904b, 0x60, ++ 0x904c, 0x08, ++ 0x904d, 0x90, ++ 0x904e, 0xc0, ++ 0x904f, 0x43, ++ 0x9050, 0x74, ++ 0x9051, 0x01, ++ 0x9052, 0xf0, ++ 0x9053, 0x80, ++ 0x9054, 0x05, ++ 0x9055, 0xE4, ++ 0x9056, 0x90, ++ 0x9057, 0xc0, ++ 0x9058, 0x43, ++ 0x9059, 0xf0, ++ 0x905a, 0x02, ++ 0x905b, 0x07, ++ 0x905c, 0xec, ++ 0xc910, 0x5d, ++ 0xc911, 0xca, ++ 0xc912, 0x80, ++ 0xc913, 0x5d, ++ 0x905d, 0xa3, ++ 0x905e, 0x04, ++ 0x905f, 0xf0, ++ 0x9060, 0xa3, ++ 0x9061, 0x04, ++ 0x9062, 0xf0, ++ 0x9063, 0x22, ++ 0xc914, 0x72, ++ 0xc915, 0x92, ++ 0xc916, 0x80, ++ 0xc917, 0x64, ++ 0x9064, 0x74, ++ 0x9065, 0x01, ++ 0x9066, 0x02, ++ 0x9067, 0x72, ++ 0x9068, 0x95, ++ 0xc918, 0x47, ++ 0xc919, 0xf2, ++ 0xc91a, 0x81, ++ 0xc91b, 0x69, ++ 0x9169, 0x74, ++ 0x916a, 0x02, ++ 0x916b, 0xf0, ++ 0x916c, 0xec, ++ 0x916d, 0xb4, ++ 0x916e, 0x10, ++ 0x916f, 0x0a, ++ 0x9170, 0x90, ++ 0x9171, 0x80, ++ 0x9172, 0x16, ++ 0x9173, 0xe0, ++ 0x9174, 0x70, ++ 0x9175, 0x04, ++ 0x9176, 0x90, ++ 0x9177, 0xd3, ++ 0x9178, 0xc4, ++ 0x9179, 0xf0, ++ 0x917a, 0x22, ++ 0xc91c, 0x0a, ++ 0xc91d, 0xbe, ++ 0xc91e, 0x80, ++ 0xc91f, 0x73, ++ 0x9073, 0xfc, ++ 0x9074, 0xa3, ++ 0x9075, 0xe0, ++ 0x9076, 0xf5, ++ 0x9077, 0x82, ++ 0x9078, 0x8c, ++ 0x9079, 0x83, ++ 0x907a, 0xa3, ++ 0x907b, 0xa3, ++ 0x907c, 0xe0, ++ 0x907d, 0xfc, ++ 0x907e, 0xa3, ++ 0x907f, 0xe0, ++ 0x9080, 0xc3, ++ 0x9081, 0x9f, ++ 0x9082, 0xff, ++ 0x9083, 0xec, ++ 0x9084, 0x9e, ++ 0x9085, 0xfe, ++ 0x9086, 0x02, ++ 0x9087, 0x0a, ++ 0x9088, 0xea, ++ 0xc920, 0x47, ++ 0xc921, 0x38, ++ 0xc922, 0x80, ++ 0xc923, 0x89, ++ 0x9089, 0xec, ++ 0x908a, 0xd3, ++ 0x908b, 0x94, ++ 0x908c, 0x20, ++ 0x908d, 0x40, ++ 0x908e, 0x01, ++ 0x908f, 0x1c, ++ 0x9090, 0x90, ++ 0x9091, 0xd3, ++ 0x9092, 0xd4, ++ 0x9093, 0xec, ++ 0x9094, 0xf0, ++ 0x9095, 0x02, ++ 0x9096, 0x47, ++ 0x9097, 0x3d, ++ 0xc924, 0x45, ++ 0xc925, 0xca, ++ 0xc926, 0x80, ++ 0xc927, 0x98, ++ 0x9098, 0x12, ++ 0x9099, 0x77, ++ 0x909a, 0xd6, ++ 0x909b, 0x02, ++ 0x909c, 0x45, ++ 0x909d, 0xcd, ++ 0xc928, 0x20, ++ 0xc929, 0xd5, ++ 0xc92a, 0x80, ++ 0xc92b, 0x9e, ++ 0x909e, 0x90, ++ 0x909f, 0x82, ++ 0x90a0, 0x18, ++ 0x90a1, 0xe0, ++ 0x90a2, 0xb4, ++ 0x90a3, 0x03, ++ 0x90a4, 0x0e, ++ 0x90a5, 0x90, ++ 0x90a6, 0x83, ++ 0x90a7, 0xbf, ++ 0x90a8, 0xe0, ++ 0x90a9, 0x60, ++ 0x90aa, 0x08, ++ 0x90ab, 0x90, ++ 0x90ac, 0x81, ++ 0x90ad, 0xfc, ++ 0x90ae, 0xe0, ++ 0x90af, 0xff, ++ 0x90b0, 0xc3, ++ 0x90b1, 0x13, ++ 0x90b2, 0xf0, ++ 0x90b3, 0x90, ++ 0x90b4, 0x81, ++ 0x90b5, 0xfc, ++ 0x90b6, 0xe0, ++ 0x90b7, 0xff, ++ 0x90b8, 0x02, ++ 0x90b9, 0x20, ++ 0x90ba, 0xda, ++ 0xc92c, 0x70, ++ 0xc92d, 0xbc, ++ 0xc92e, 0x80, ++ 0xc92f, 0xbb, ++ 0x90bb, 0x90, ++ 0x90bc, 0x82, ++ 0x90bd, 0x18, ++ 0x90be, 0xe0, ++ 0x90bf, 0xb4, ++ 0x90c0, 0x03, ++ 0x90c1, 0x06, ++ 0x90c2, 0x90, ++ 0x90c3, 0xc1, ++ 0x90c4, 0x06, ++ 0x90c5, 0x74, ++ 0x90c6, 0x05, ++ 0x90c7, 0xf0, ++ 0x90c8, 0x90, ++ 0x90c9, 0xd3, ++ 0x90ca, 0xa0, ++ 0x90cb, 0x02, ++ 0x90cc, 0x70, ++ 0x90cd, 0xbf, ++ 0xc930, 0x72, ++ 0xc931, 0x21, ++ 0xc932, 0x81, ++ 0xc933, 0x3b, ++ 0x913b, 0x7d, ++ 0x913c, 0x02, ++ 0x913d, 0x7f, ++ 0x913e, 0x7b, ++ 0x913f, 0x02, ++ 0x9140, 0x72, ++ 0x9141, 0x25, ++ 0xc934, 0x28, ++ 0xc935, 0xae, ++ 0xc936, 0x80, ++ 0xc937, 0xd2, ++ 0x90d2, 0xf0, ++ 0x90d3, 0x90, ++ 0x90d4, 0xd2, ++ 0x90d5, 0x0a, ++ 0x90d6, 0x02, ++ 0x90d7, 0x28, ++ 0x90d8, 0xb4, ++ 0xc938, 0x28, ++ 0xc939, 0xb1, ++ 0xc93a, 0x80, ++ 0xc93b, 0xd9, ++ 0x90d9, 0x90, ++ 0x90da, 0x83, ++ 0x90db, 0xba, ++ 0x90dc, 0xe0, ++ 0x90dd, 0xff, ++ 0x90de, 0x90, ++ 0x90df, 0xd2, ++ 0x90e0, 0x08, ++ 0x90e1, 0xe0, ++ 0x90e2, 0xe4, ++ 0x90e3, 0xef, ++ 0x90e4, 0xf0, ++ 0x90e5, 0xa3, ++ 0x90e6, 0xe0, ++ 0x90e7, 0x74, ++ 0x90e8, 0xff, ++ 0x90e9, 0xf0, ++ 0x90ea, 0x90, ++ 0x90eb, 0xd2, ++ 0x90ec, 0x0a, ++ 0x90ed, 0x02, ++ 0x90ee, 0x28, ++ 0x90ef, 0xb4, ++ 0xc93c, 0x29, ++ 0xc93d, 0x79, ++ 0xc93e, 0x80, ++ 0xc93f, 0xf0, ++ 0x90f0, 0xf0, ++ 0x90f1, 0x90, ++ 0x90f2, 0xd2, ++ 0x90f3, 0x0e, ++ 0x90f4, 0x02, ++ 0x90f5, 0x29, ++ 0x90f6, 0x7f, ++ 0xc940, 0x29, ++ 0xc941, 0x7c, ++ 0xc942, 0x80, ++ 0xc943, 0xf7, ++ 0x90f7, 0x90, ++ 0x90f8, 0x83, ++ 0x90f9, 0xba, ++ 0x90fa, 0xe0, ++ 0x90fb, 0xff, ++ 0x90fc, 0x90, ++ 0x90fd, 0xd2, ++ 0x90fe, 0x0c, ++ 0x90ff, 0xe0, ++ 0x9100, 0xe4, ++ 0x9101, 0xef, ++ 0x9102, 0xf0, ++ 0x9103, 0xa3, ++ 0x9104, 0xe0, ++ 0x9105, 0x74, ++ 0x9106, 0xff, ++ 0x9107, 0xf0, ++ 0x9108, 0x90, ++ 0x9109, 0xd2, ++ 0x910a, 0x0e, ++ 0x910b, 0x02, ++ 0x910c, 0x29, ++ 0x910d, 0x7f, ++ 0xc944, 0x2a, ++ 0xc945, 0x42, ++ 0xc946, 0x81, ++ 0xc947, 0x0e, ++ 0x910e, 0xf0, ++ 0x910f, 0x90, ++ 0x9110, 0xd2, ++ 0x9111, 0x12, ++ 0x9112, 0x02, ++ 0x9113, 0x2a, ++ 0x9114, 0x48, ++ 0xc948, 0x2a, ++ 0xc949, 0x45, ++ 0xc94a, 0x81, ++ 0xc94b, 0x15, ++ 0x9115, 0x90, ++ 0x9116, 0x83, ++ 0x9117, 0xba, ++ 0x9118, 0xe0, ++ 0x9119, 0xff, ++ 0x911a, 0x90, ++ 0x911b, 0xd2, ++ 0x911c, 0x10, ++ 0x911d, 0xe0, ++ 0x911e, 0xe4, ++ 0x911f, 0xef, ++ 0x9120, 0xf0, ++ 0x9121, 0xa3, ++ 0x9122, 0xe0, ++ 0x9123, 0x74, ++ 0x9124, 0xff, ++ 0x9125, 0xf0, ++ 0x9126, 0x90, ++ 0x9127, 0xd2, ++ 0x9128, 0x12, ++ 0x9129, 0x02, ++ 0x912a, 0x2a, ++ 0x912b, 0x48, ++ 0xc900, 0x01, ++ 0x0000, 0x00, ++}; ++ ++static const u16 vs6624_p2[] = { ++ 0x806f, 0x01, ++ 0x058c, 0x01, ++ 0x0000, 0x00, ++}; ++ ++static const u16 vs6624_run_setup[] = { ++ 0x1d18, 0x00, /* Enableconstrainedwhitebalance */ ++ VS6624_PEAK_MIN_OUT_G_MSB, 0x3c, /* Damper PeakGain Output MSB */ ++ VS6624_PEAK_MIN_OUT_G_LSB, 0x66, /* Damper PeakGain Output LSB */ ++ VS6624_CM_LOW_THR_MSB, 0x65, /* Damper Low MSB */ ++ VS6624_CM_LOW_THR_LSB, 0xd1, /* Damper Low LSB */ ++ VS6624_CM_HIGH_THR_MSB, 0x66, /* Damper High MSB */ ++ VS6624_CM_HIGH_THR_LSB, 0x62, /* Damper High LSB */ ++ VS6624_CM_MIN_OUT_MSB, 0x00, /* Damper Min output MSB */ ++ VS6624_CM_MIN_OUT_LSB, 0x00, /* Damper Min output LSB */ ++ VS6624_NORA_DISABLE, 0x00, /* Nora fDisable */ ++ VS6624_NORA_USAGE, 0x04, /* Nora usage */ ++ VS6624_NORA_LOW_THR_MSB, 0x63, /* Damper Low MSB Changed 0x63 to 0x65 */ ++ VS6624_NORA_LOW_THR_LSB, 0xd1, /* Damper Low LSB */ ++ VS6624_NORA_HIGH_THR_MSB, 0x68, /* Damper High MSB */ ++ VS6624_NORA_HIGH_THR_LSB, 0xdd, /* Damper High LSB */ ++ VS6624_NORA_MIN_OUT_MSB, 0x3a, /* Damper Min output MSB */ ++ VS6624_NORA_MIN_OUT_LSB, 0x00, /* Damper Min output LSB */ ++ VS6624_F2B_DISABLE, 0x00, /* Disable */ ++ 0x1d8a, 0x30, /* MAXWeightHigh */ ++ 0x1d91, 0x62, /* fpDamperLowThresholdHigh MSB */ ++ 0x1d92, 0x4a, /* fpDamperLowThresholdHigh LSB */ ++ 0x1d95, 0x65, /* fpDamperHighThresholdHigh MSB */ ++ 0x1d96, 0x0e, /* fpDamperHighThresholdHigh LSB */ ++ 0x1da1, 0x3a, /* fpMinimumDamperOutputLow MSB */ ++ 0x1da2, 0xb8, /* fpMinimumDamperOutputLow LSB */ ++ 0x1e08, 0x06, /* MAXWeightLow */ ++ 0x1e0a, 0x0a, /* MAXWeightHigh */ ++ 0x1601, 0x3a, /* Red A MSB */ ++ 0x1602, 0x14, /* Red A LSB */ ++ 0x1605, 0x3b, /* Blue A MSB */ ++ 0x1606, 0x85, /* BLue A LSB */ ++ 0x1609, 0x3b, /* RED B MSB */ ++ 0x160a, 0x85, /* RED B LSB */ ++ 0x160d, 0x3a, /* Blue B MSB */ ++ 0x160e, 0x14, /* Blue B LSB */ ++ 0x1611, 0x30, /* Max Distance from Locus MSB */ ++ 0x1612, 0x8f, /* Max Distance from Locus MSB */ ++ 0x1614, 0x01, /* Enable constrainer */ ++ 0x0000, 0x00, ++}; ++ ++static const u16 vs6624_default[] = { ++ VS6624_CONTRAST0, 0x84, ++ VS6624_SATURATION0, 0x75, ++ VS6624_GAMMA0, 0x11, ++ VS6624_CONTRAST1, 0x84, ++ VS6624_SATURATION1, 0x75, ++ VS6624_GAMMA1, 0x11, ++ VS6624_MAN_RG, 0x80, ++ VS6624_MAN_GG, 0x80, ++ VS6624_MAN_BG, 0x80, ++ VS6624_WB_MODE, 0x1, ++ VS6624_EXPO_COMPENSATION, 0xfe, ++ VS6624_EXPO_METER, 0x0, ++ VS6624_LIGHT_FREQ, 0x64, ++ VS6624_PEAK_GAIN, 0xe, ++ VS6624_PEAK_LOW_THR, 0x28, ++ VS6624_HMIRROR0, 0x0, ++ VS6624_VFLIP0, 0x0, ++ VS6624_ZOOM_HSTEP0_MSB, 0x0, ++ VS6624_ZOOM_HSTEP0_LSB, 0x1, ++ VS6624_ZOOM_VSTEP0_MSB, 0x0, ++ VS6624_ZOOM_VSTEP0_LSB, 0x1, ++ VS6624_PAN_HSTEP0_MSB, 0x0, ++ VS6624_PAN_HSTEP0_LSB, 0xf, ++ VS6624_PAN_VSTEP0_MSB, 0x0, ++ VS6624_PAN_VSTEP0_LSB, 0xf, ++ VS6624_SENSOR_MODE, 0x1, ++ VS6624_SYNC_CODE_SETUP, 0x21, ++ VS6624_DISABLE_FR_DAMPER, 0x0, ++ VS6624_FR_DEN, 0x1, ++ VS6624_FR_NUM_LSB, 0xf, ++ VS6624_INIT_PIPE_SETUP, 0x0, ++ VS6624_IMG_FMT0, 0x0, ++ VS6624_YUV_SETUP, 0x1, ++ VS6624_IMAGE_SIZE0, 0x2, ++ 0x0000, 0x00, ++}; ++ ++static inline struct vs6624 *to_vs6624(struct v4l2_subdev *sd) ++{ ++ return container_of(sd, struct vs6624, sd); ++} ++static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) ++{ ++ return &container_of(ctrl->handler, struct vs6624, hdl)->sd; ++} ++ ++static int vs6624_read(struct v4l2_subdev *sd, u16 index) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ u8 buf[2]; ++ ++ buf[0] = index >> 8; ++ buf[1] = index; ++ i2c_master_send(client, buf, 2); ++ i2c_master_recv(client, buf, 1); ++ ++ return buf[0]; ++} ++ ++static int vs6624_write(struct v4l2_subdev *sd, u16 index, ++ u8 value) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ u8 buf[3]; ++ ++ buf[0] = index >> 8; ++ buf[1] = index; ++ buf[2] = value; ++ ++ return i2c_master_send(client, buf, 3); ++} ++ ++static int vs6624_writeregs(struct v4l2_subdev *sd, const u16 *regs) ++{ ++ u16 reg; ++ u8 data; ++ ++ while (*regs != 0x00) { ++ reg = *regs++; ++ data = *regs++; ++ ++ vs6624_write(sd, reg, data); ++ } ++ return 0; ++} ++ ++static int vs6624_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ ++ switch (ctrl->id) { ++ case V4L2_CID_CONTRAST: ++ vs6624_write(sd, VS6624_CONTRAST0, ctrl->val); ++ break; ++ case V4L2_CID_SATURATION: ++ vs6624_write(sd, VS6624_SATURATION0, ctrl->val); ++ break; ++ case V4L2_CID_HFLIP: ++ vs6624_write(sd, VS6624_HMIRROR0, ctrl->val); ++ break; ++ case V4L2_CID_VFLIP: ++ vs6624_write(sd, VS6624_VFLIP0, ctrl->val); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int vs6624_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, ++ enum v4l2_mbus_pixelcode *code) ++{ ++ if (index >= ARRAY_SIZE(vs6624_formats)) ++ return -EINVAL; ++ ++ *code = vs6624_formats[index].mbus_code; ++ return 0; ++} ++ ++static int vs6624_try_mbus_fmt(struct v4l2_subdev *sd, ++ struct v4l2_mbus_framefmt *fmt) ++{ ++ int index; ++ ++ for (index = 0; index < ARRAY_SIZE(vs6624_formats); index++) ++ if (vs6624_formats[index].mbus_code == fmt->code) ++ break; ++ if (index >= ARRAY_SIZE(vs6624_formats)) { ++ /* default to first format */ ++ index = 0; ++ fmt->code = vs6624_formats[0].mbus_code; ++ } ++ ++ /* sensor mode is VGA */ ++ if (fmt->width > VGA_WIDTH) ++ fmt->width = VGA_WIDTH; ++ if (fmt->height > VGA_HEIGHT) ++ fmt->height = VGA_HEIGHT; ++ fmt->width = fmt->width & (~3); ++ fmt->height = fmt->height & (~3); ++ fmt->field = V4L2_FIELD_NONE; ++ fmt->colorspace = vs6624_formats[index].colorspace; ++ return 0; ++} ++ ++static int vs6624_s_mbus_fmt(struct v4l2_subdev *sd, ++ struct v4l2_mbus_framefmt *fmt) ++{ ++ struct vs6624 *sensor = to_vs6624(sd); ++ int ret; ++ ++ ret = vs6624_try_mbus_fmt(sd, fmt); ++ if (ret) ++ return ret; ++ ++ /* set image format */ ++ switch (fmt->code) { ++ case V4L2_MBUS_FMT_UYVY8_2X8: ++ vs6624_write(sd, VS6624_IMG_FMT0, 0x0); ++ vs6624_write(sd, VS6624_YUV_SETUP, 0x1); ++ break; ++ case V4L2_MBUS_FMT_YUYV8_2X8: ++ vs6624_write(sd, VS6624_IMG_FMT0, 0x0); ++ vs6624_write(sd, VS6624_YUV_SETUP, 0x3); ++ break; ++ case V4L2_MBUS_FMT_RGB565_2X8_LE: ++ vs6624_write(sd, VS6624_IMG_FMT0, 0x4); ++ vs6624_write(sd, VS6624_RGB_SETUP, 0x0); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* set image size */ ++ if ((fmt->width == VGA_WIDTH) && (fmt->height == VGA_HEIGHT)) ++ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x2); ++ else if ((fmt->width == QVGA_WIDTH) && (fmt->height == QVGA_HEIGHT)) ++ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x4); ++ else if ((fmt->width == QQVGA_WIDTH) && (fmt->height == QQVGA_HEIGHT)) ++ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x6); ++ else if ((fmt->width == CIF_WIDTH) && (fmt->height == CIF_HEIGHT)) ++ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x3); ++ else if ((fmt->width == QCIF_WIDTH) && (fmt->height == QCIF_HEIGHT)) ++ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x5); ++ else if ((fmt->width == QQCIF_WIDTH) && (fmt->height == QQCIF_HEIGHT)) ++ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x7); ++ else { ++ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x8); ++ vs6624_write(sd, VS6624_MAN_HSIZE0_MSB, fmt->width >> 8); ++ vs6624_write(sd, VS6624_MAN_HSIZE0_LSB, fmt->width & 0xFF); ++ vs6624_write(sd, VS6624_MAN_VSIZE0_MSB, fmt->height >> 8); ++ vs6624_write(sd, VS6624_MAN_VSIZE0_LSB, fmt->height & 0xFF); ++ vs6624_write(sd, VS6624_CROP_CTRL0, 0x1); ++ } ++ ++ sensor->fmt = *fmt; ++ ++ return 0; ++} ++ ++static int vs6624_g_mbus_fmt(struct v4l2_subdev *sd, ++ struct v4l2_mbus_framefmt *fmt) ++{ ++ struct vs6624 *sensor = to_vs6624(sd); ++ ++ *fmt = sensor->fmt; ++ return 0; ++} ++ ++static int vs6624_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct vs6624 *sensor = to_vs6624(sd); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ memset(cp, 0, sizeof(*cp)); ++ cp->capability = V4L2_CAP_TIMEPERFRAME; ++ cp->timeperframe.numerator = sensor->frame_rate.denominator; ++ cp->timeperframe.denominator = sensor->frame_rate.numerator; ++ return 0; ++} ++ ++static int vs6624_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct vs6624 *sensor = to_vs6624(sd); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ struct v4l2_fract *tpf = &cp->timeperframe; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ if (cp->extendedmode != 0) ++ return -EINVAL; ++ ++ if (tpf->numerator == 0 || tpf->denominator == 0 ++ || (tpf->denominator > tpf->numerator * MAX_FRAME_RATE)) { ++ /* reset to max frame rate */ ++ tpf->numerator = 1; ++ tpf->denominator = MAX_FRAME_RATE; ++ } ++ sensor->frame_rate.numerator = tpf->denominator; ++ sensor->frame_rate.denominator = tpf->numerator; ++ vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0); ++ vs6624_write(sd, VS6624_FR_NUM_MSB, ++ sensor->frame_rate.numerator >> 8); ++ vs6624_write(sd, VS6624_FR_NUM_LSB, ++ sensor->frame_rate.numerator & 0xFF); ++ vs6624_write(sd, VS6624_FR_DEN, ++ sensor->frame_rate.denominator & 0xFF); ++ return 0; ++} ++ ++static int vs6624_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ if (enable) ++ vs6624_write(sd, VS6624_USER_CMD, 0x2); ++ else ++ vs6624_write(sd, VS6624_USER_CMD, 0x4); ++ udelay(100); ++ return 0; ++} ++ ++static int vs6624_g_chip_ident(struct v4l2_subdev *sd, ++ struct v4l2_dbg_chip_ident *chip) ++{ ++ int rev; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ rev = (vs6624_read(sd, VS6624_FW_VSN_MAJOR) << 8) ++ | vs6624_read(sd, VS6624_FW_VSN_MINOR); ++ ++ return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_VS6624, rev); ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int vs6624_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ if (!v4l2_chip_match_i2c_client(client, ®->match)) ++ return -EINVAL; ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ reg->val = vs6624_read(sd, reg->reg & 0xffff); ++ reg->size = 1; ++ return 0; ++} ++ ++static int vs6624_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ if (!v4l2_chip_match_i2c_client(client, ®->match)) ++ return -EINVAL; ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ vs6624_write(sd, reg->reg & 0xffff, reg->val & 0xff); ++ return 0; ++} ++#endif ++ ++static const struct v4l2_ctrl_ops vs6624_ctrl_ops = { ++ .s_ctrl = vs6624_s_ctrl, ++}; ++ ++static const struct v4l2_subdev_core_ops vs6624_core_ops = { ++ .g_chip_ident = vs6624_g_chip_ident, ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = vs6624_g_register, ++ .s_register = vs6624_s_register, ++#endif ++}; ++ ++static const struct v4l2_subdev_video_ops vs6624_video_ops = { ++ .enum_mbus_fmt = vs6624_enum_mbus_fmt, ++ .try_mbus_fmt = vs6624_try_mbus_fmt, ++ .s_mbus_fmt = vs6624_s_mbus_fmt, ++ .g_mbus_fmt = vs6624_g_mbus_fmt, ++ .s_parm = vs6624_s_parm, ++ .g_parm = vs6624_g_parm, ++ .s_stream = vs6624_s_stream, ++}; ++ ++static const struct v4l2_subdev_ops vs6624_ops = { ++ .core = &vs6624_core_ops, ++ .video = &vs6624_video_ops, ++}; ++ ++static int __devinit vs6624_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct vs6624 *sensor; ++ struct v4l2_subdev *sd; ++ struct v4l2_ctrl_handler *hdl; ++ const unsigned *ce; ++ int ret; ++ ++ /* Check if the adapter supports the needed features */ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) ++ return -EIO; ++ ++ ce = client->dev.platform_data; ++ if (ce == NULL) ++ return -EINVAL; ++ ++ ret = gpio_request(*ce, "VS6624 Chip Enable"); ++ if (ret) { ++ v4l_err(client, "failed to request GPIO %d\n", *ce); ++ return ret; ++ } ++ gpio_direction_output(*ce, 1); ++ /* wait 100ms before any further i2c writes are performed */ ++ mdelay(100); ++ ++ sensor = kzalloc(sizeof(*sensor), GFP_KERNEL); ++ if (sensor == NULL) { ++ gpio_free(*ce); ++ return -ENOMEM; ++ } ++ ++ sd = &sensor->sd; ++ v4l2_i2c_subdev_init(sd, client, &vs6624_ops); ++ ++ vs6624_writeregs(sd, vs6624_p1); ++ vs6624_write(sd, VS6624_MICRO_EN, 0x2); ++ vs6624_write(sd, VS6624_DIO_EN, 0x1); ++ mdelay(10); ++ vs6624_writeregs(sd, vs6624_p2); ++ ++ vs6624_writeregs(sd, vs6624_default); ++ vs6624_write(sd, VS6624_HSYNC_SETUP, 0xF); ++ vs6624_writeregs(sd, vs6624_run_setup); ++ ++ /* set frame rate */ ++ sensor->frame_rate.numerator = MAX_FRAME_RATE; ++ sensor->frame_rate.denominator = 1; ++ vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0); ++ vs6624_write(sd, VS6624_FR_NUM_MSB, ++ sensor->frame_rate.numerator >> 8); ++ vs6624_write(sd, VS6624_FR_NUM_LSB, ++ sensor->frame_rate.numerator & 0xFF); ++ vs6624_write(sd, VS6624_FR_DEN, ++ sensor->frame_rate.denominator & 0xFF); ++ ++ sensor->fmt = vs6624_default_fmt; ++ sensor->ce_pin = *ce; ++ ++ v4l_info(client, "chip found @ 0x%02x (%s)\n", ++ client->addr << 1, client->adapter->name); ++ ++ hdl = &sensor->hdl; ++ v4l2_ctrl_handler_init(hdl, 4); ++ v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 0xFF, 1, 0x87); ++ v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 0xFF, 1, 0x78); ++ v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ /* hook the control handler into the driver */ ++ sd->ctrl_handler = hdl; ++ if (hdl->error) { ++ int err = hdl->error; ++ ++ v4l2_ctrl_handler_free(hdl); ++ kfree(sensor); ++ gpio_free(*ce); ++ return err; ++ } ++ ++ /* initialize the hardware to the default control values */ ++ ret = v4l2_ctrl_handler_setup(hdl); ++ if (ret) { ++ v4l2_ctrl_handler_free(hdl); ++ kfree(sensor); ++ gpio_free(*ce); ++ } ++ return ret; ++} ++ ++static int __devexit vs6624_remove(struct i2c_client *client) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(client); ++ struct vs6624 *sensor = to_vs6624(sd); ++ ++ v4l2_device_unregister_subdev(sd); ++ v4l2_ctrl_handler_free(sd->ctrl_handler); ++ gpio_free(sensor->ce_pin); ++ kfree(sensor); ++ return 0; ++} ++ ++static const struct i2c_device_id vs6624_id[] = { ++ {"vs6624", 0}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(i2c, vs6624_id); ++ ++static struct i2c_driver vs6624_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "vs6624", ++ }, ++ .probe = vs6624_probe, ++ .remove = __devexit_p(vs6624_remove), ++ .id_table = vs6624_id, ++}; ++ ++static __init int vs6624_init(void) ++{ ++ return i2c_add_driver(&vs6624_driver); ++} ++ ++static __exit void vs6624_exit(void) ++{ ++ i2c_del_driver(&vs6624_driver); ++} ++ ++module_init(vs6624_init); ++module_exit(vs6624_exit); ++ ++MODULE_DESCRIPTION("VS6624 sensor driver"); ++MODULE_AUTHOR("Scott Jiang "); ++MODULE_LICENSE("GPL v2"); +Index: linux-3.3.x86_64/drivers/media/video/vs6624_regs.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/vs6624_regs.h +@@ -0,0 +1,337 @@ ++/* ++ * vs6624 - ST VS6624 CMOS image sensor registers ++ * ++ * Copyright (c) 2011 Analog Devices Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef _VS6624_REGS_H_ ++#define _VS6624_REGS_H_ ++ ++/* low level control registers */ ++#define VS6624_MICRO_EN 0xC003 /* power enable for all MCU clock */ ++#define VS6624_DIO_EN 0xC044 /* enable digital I/O */ ++/* device parameters */ ++#define VS6624_DEV_ID_MSB 0x0001 /* device id MSB */ ++#define VS6624_DEV_ID_LSB 0x0002 /* device id LSB */ ++#define VS6624_FW_VSN_MAJOR 0x0004 /* firmware version major */ ++#define VS6624_FW_VSN_MINOR 0x0006 /* firmware version minor */ ++#define VS6624_PATCH_VSN_MAJOR 0x0008 /* patch version major */ ++#define VS6624_PATCH_VSN_MINOR 0x000A /* patch version minor */ ++/* host interface manager control */ ++#define VS6624_USER_CMD 0x0180 /* user level control of operating states */ ++/* host interface manager status */ ++#define VS6624_STATE 0x0202 /* current state of the mode manager */ ++/* run mode control */ ++#define VS6624_METER_ON 0x0280 /* if false AE and AWB are disabled */ ++/* mode setup */ ++#define VS6624_ACTIVE_PIPE_SETUP 0x0302 /* select the active bank for non view live mode */ ++#define VS6624_SENSOR_MODE 0x0308 /* select the different sensor mode */ ++/* pipe setup bank0 */ ++#define VS6624_IMAGE_SIZE0 0x0380 /* required output dimension */ ++#define VS6624_MAN_HSIZE0_MSB 0x0383 /* input required manual H size MSB */ ++#define VS6624_MAN_HSIZE0_LSB 0x0384 /* input required manual H size LSB */ ++#define VS6624_MAN_VSIZE0_MSB 0x0387 /* input required manual V size MSB */ ++#define VS6624_MAN_VSIZE0_LSB 0x0388 /* input required manual V size LSB */ ++#define VS6624_ZOOM_HSTEP0_MSB 0x038B /* set the zoom H step MSB */ ++#define VS6624_ZOOM_HSTEP0_LSB 0x038C /* set the zoom H step LSB */ ++#define VS6624_ZOOM_VSTEP0_MSB 0x038F /* set the zoom V step MSB */ ++#define VS6624_ZOOM_VSTEP0_LSB 0x0390 /* set the zoom V step LSB */ ++#define VS6624_ZOOM_CTRL0 0x0392 /* control zoon in, out and stop */ ++#define VS6624_PAN_HSTEP0_MSB 0x0395 /* set the pan H step MSB */ ++#define VS6624_PAN_HSTEP0_LSB 0x0396 /* set the pan H step LSB */ ++#define VS6624_PAN_VSTEP0_MSB 0x0399 /* set the pan V step MSB */ ++#define VS6624_PAN_VSTEP0_LSB 0x039A /* set the pan V step LSB */ ++#define VS6624_PAN_CTRL0 0x039C /* control pan operation */ ++#define VS6624_CROP_CTRL0 0x039E /* select cropping mode */ ++#define VS6624_CROP_HSTART0_MSB 0x03A1 /* set the cropping H start address MSB */ ++#define VS6624_CROP_HSTART0_LSB 0x03A2 /* set the cropping H start address LSB */ ++#define VS6624_CROP_HSIZE0_MSB 0x03A5 /* set the cropping H size MSB */ ++#define VS6624_CROP_HSIZE0_LSB 0x03A6 /* set the cropping H size LSB */ ++#define VS6624_CROP_VSTART0_MSB 0x03A9 /* set the cropping V start address MSB */ ++#define VS6624_CROP_VSTART0_LSB 0x03AA /* set the cropping V start address LSB */ ++#define VS6624_CROP_VSIZE0_MSB 0x03AD /* set the cropping V size MSB */ ++#define VS6624_CROP_VSIZE0_LSB 0x03AE /* set the cropping V size LSB */ ++#define VS6624_IMG_FMT0 0x03B0 /* select required output image format */ ++#define VS6624_BAYER_OUT_ALIGN0 0x03B2 /* set bayer output alignment */ ++#define VS6624_CONTRAST0 0x03B4 /* contrast control for output */ ++#define VS6624_SATURATION0 0x03B6 /* saturation control for output */ ++#define VS6624_GAMMA0 0x03B8 /* gamma settings */ ++#define VS6624_HMIRROR0 0x03BA /* horizontal image orientation flip */ ++#define VS6624_VFLIP0 0x03BC /* vertical image orientation flip */ ++#define VS6624_CHANNEL_ID0 0x03BE /* logical DMA channel number */ ++/* pipe setup bank1 */ ++#define VS6624_IMAGE_SIZE1 0x0400 /* required output dimension */ ++#define VS6624_MAN_HSIZE1_MSB 0x0403 /* input required manual H size MSB */ ++#define VS6624_MAN_HSIZE1_LSB 0x0404 /* input required manual H size LSB */ ++#define VS6624_MAN_VSIZE1_MSB 0x0407 /* input required manual V size MSB */ ++#define VS6624_MAN_VSIZE1_LSB 0x0408 /* input required manual V size LSB */ ++#define VS6624_ZOOM_HSTEP1_MSB 0x040B /* set the zoom H step MSB */ ++#define VS6624_ZOOM_HSTEP1_LSB 0x040C /* set the zoom H step LSB */ ++#define VS6624_ZOOM_VSTEP1_MSB 0x040F /* set the zoom V step MSB */ ++#define VS6624_ZOOM_VSTEP1_LSB 0x0410 /* set the zoom V step LSB */ ++#define VS6624_ZOOM_CTRL1 0x0412 /* control zoon in, out and stop */ ++#define VS6624_PAN_HSTEP1_MSB 0x0415 /* set the pan H step MSB */ ++#define VS6624_PAN_HSTEP1_LSB 0x0416 /* set the pan H step LSB */ ++#define VS6624_PAN_VSTEP1_MSB 0x0419 /* set the pan V step MSB */ ++#define VS6624_PAN_VSTEP1_LSB 0x041A /* set the pan V step LSB */ ++#define VS6624_PAN_CTRL1 0x041C /* control pan operation */ ++#define VS6624_CROP_CTRL1 0x041E /* select cropping mode */ ++#define VS6624_CROP_HSTART1_MSB 0x0421 /* set the cropping H start address MSB */ ++#define VS6624_CROP_HSTART1_LSB 0x0422 /* set the cropping H start address LSB */ ++#define VS6624_CROP_HSIZE1_MSB 0x0425 /* set the cropping H size MSB */ ++#define VS6624_CROP_HSIZE1_LSB 0x0426 /* set the cropping H size LSB */ ++#define VS6624_CROP_VSTART1_MSB 0x0429 /* set the cropping V start address MSB */ ++#define VS6624_CROP_VSTART1_LSB 0x042A /* set the cropping V start address LSB */ ++#define VS6624_CROP_VSIZE1_MSB 0x042D /* set the cropping V size MSB */ ++#define VS6624_CROP_VSIZE1_LSB 0x042E /* set the cropping V size LSB */ ++#define VS6624_IMG_FMT1 0x0430 /* select required output image format */ ++#define VS6624_BAYER_OUT_ALIGN1 0x0432 /* set bayer output alignment */ ++#define VS6624_CONTRAST1 0x0434 /* contrast control for output */ ++#define VS6624_SATURATION1 0x0436 /* saturation control for output */ ++#define VS6624_GAMMA1 0x0438 /* gamma settings */ ++#define VS6624_HMIRROR1 0x043A /* horizontal image orientation flip */ ++#define VS6624_VFLIP1 0x043C /* vertical image orientation flip */ ++#define VS6624_CHANNEL_ID1 0x043E /* logical DMA channel number */ ++/* view live control */ ++#define VS6624_VIEW_LIVE_EN 0x0480 /* enable view live mode */ ++#define VS6624_INIT_PIPE_SETUP 0x0482 /* select initial pipe setup bank */ ++/* view live status */ ++#define VS6624_CUR_PIPE_SETUP 0x0500 /* indicates most recently applied setup bank */ ++/* power management */ ++#define VS6624_TIME_TO_POWER_DOWN 0x0580 /* automatically transition time to stop mode */ ++/* video timing parameter host inputs */ ++#define VS6624_EXT_CLK_FREQ_NUM_MSB 0x0605 /* external clock frequency numerator MSB */ ++#define VS6624_EXT_CLK_FREQ_NUM_LSB 0x0606 /* external clock frequency numerator LSB */ ++#define VS6624_EXT_CLK_FREQ_DEN 0x0608 /* external clock frequency denominator */ ++/* video timing control */ ++#define VS6624_SYS_CLK_MODE 0x0880 /* decides system clock frequency */ ++/* frame dimension parameter host inputs */ ++#define VS6624_LIGHT_FREQ 0x0C80 /* AC frequency used for flicker free time */ ++#define VS6624_FLICKER_COMPAT 0x0C82 /* flicker compatible frame length */ ++/* static frame rate control */ ++#define VS6624_FR_NUM_MSB 0x0D81 /* desired frame rate numerator MSB */ ++#define VS6624_FR_NUM_LSB 0x0D82 /* desired frame rate numerator LSB */ ++#define VS6624_FR_DEN 0x0D84 /* desired frame rate denominator */ ++/* automatic frame rate control */ ++#define VS6624_DISABLE_FR_DAMPER 0x0E80 /* defines frame rate mode */ ++#define VS6624_MIN_DAMPER_OUT_MSB 0x0E8C /* minimum frame rate MSB */ ++#define VS6624_MIN_DAMPER_OUT_LSB 0x0E8A /* minimum frame rate LSB */ ++/* exposure controls */ ++#define VS6624_EXPO_MODE 0x1180 /* exposure mode */ ++#define VS6624_EXPO_METER 0x1182 /* weights to be associated with the zones */ ++#define VS6624_EXPO_TIME_NUM 0x1184 /* exposure time numerator */ ++#define VS6624_EXPO_TIME_DEN 0x1186 /* exposure time denominator */ ++#define VS6624_EXPO_TIME_MSB 0x1189 /* exposure time for the Manual Mode MSB */ ++#define VS6624_EXPO_TIME_LSB 0x118A /* exposure time for the Manual Mode LSB */ ++#define VS6624_EXPO_COMPENSATION 0x1190 /* exposure compensation */ ++#define VS6624_DIRECT_COARSE_MSB 0x1195 /* coarse integration lines for Direct Mode MSB */ ++#define VS6624_DIRECT_COARSE_LSB 0x1196 /* coarse integration lines for Direct Mode LSB */ ++#define VS6624_DIRECT_FINE_MSB 0x1199 /* fine integration pixels for Direct Mode MSB */ ++#define VS6624_DIRECT_FINE_LSB 0x119A /* fine integration pixels for Direct Mode LSB */ ++#define VS6624_DIRECT_ANAL_GAIN_MSB 0x119D /* analog gain for Direct Mode MSB */ ++#define VS6624_DIRECT_ANAL_GAIN_LSB 0x119E /* analog gain for Direct Mode LSB */ ++#define VS6624_DIRECT_DIGI_GAIN_MSB 0x11A1 /* digital gain for Direct Mode MSB */ ++#define VS6624_DIRECT_DIGI_GAIN_LSB 0x11A2 /* digital gain for Direct Mode LSB */ ++#define VS6624_FLASH_COARSE_MSB 0x11A5 /* coarse integration lines for Flash Gun Mode MSB */ ++#define VS6624_FLASH_COARSE_LSB 0x11A6 /* coarse integration lines for Flash Gun Mode LSB */ ++#define VS6624_FLASH_FINE_MSB 0x11A9 /* fine integration pixels for Flash Gun Mode MSB */ ++#define VS6624_FLASH_FINE_LSB 0x11AA /* fine integration pixels for Flash Gun Mode LSB */ ++#define VS6624_FLASH_ANAL_GAIN_MSB 0x11AD /* analog gain for Flash Gun Mode MSB */ ++#define VS6624_FLASH_ANAL_GAIN_LSB 0x11AE /* analog gain for Flash Gun Mode LSB */ ++#define VS6624_FLASH_DIGI_GAIN_MSB 0x11B1 /* digital gain for Flash Gun Mode MSB */ ++#define VS6624_FLASH_DIGI_GAIN_LSB 0x11B2 /* digital gain for Flash Gun Mode LSB */ ++#define VS6624_FREEZE_AE 0x11B4 /* freeze auto exposure */ ++#define VS6624_MAX_INT_TIME_MSB 0x11B7 /* user maximum integration time MSB */ ++#define VS6624_MAX_INT_TIME_LSB 0x11B8 /* user maximum integration time LSB */ ++#define VS6624_FLASH_AG_THR_MSB 0x11BB /* recommend flash gun analog gain threshold MSB */ ++#define VS6624_FLASH_AG_THR_LSB 0x11BC /* recommend flash gun analog gain threshold LSB */ ++#define VS6624_ANTI_FLICKER_MODE 0x11C0 /* anti flicker mode */ ++/* white balance control */ ++#define VS6624_WB_MODE 0x1480 /* set white balance mode */ ++#define VS6624_MAN_RG 0x1482 /* user setting for red channel gain */ ++#define VS6624_MAN_GG 0x1484 /* user setting for green channel gain */ ++#define VS6624_MAN_BG 0x1486 /* user setting for blue channel gain */ ++#define VS6624_FLASH_RG_MSB 0x148B /* red gain for Flash Gun MSB */ ++#define VS6624_FLASH_RG_LSB 0x148C /* red gain for Flash Gun LSB */ ++#define VS6624_FLASH_GG_MSB 0x148F /* green gain for Flash Gun MSB */ ++#define VS6624_FLASH_GG_LSB 0x1490 /* green gain for Flash Gun LSB */ ++#define VS6624_FLASH_BG_MSB 0x1493 /* blue gain for Flash Gun MSB */ ++#define VS6624_FLASH_BG_LSB 0x1494 /* blue gain for Flash Gun LSB */ ++/* sensor setup */ ++#define VS6624_BC_OFFSET 0x1990 /* Black Correction Offset */ ++/* image stability */ ++#define VS6624_STABLE_WB 0x1900 /* white balance stable */ ++#define VS6624_STABLE_EXPO 0x1902 /* exposure stable */ ++#define VS6624_STABLE 0x1906 /* system stable */ ++/* flash control */ ++#define VS6624_FLASH_MODE 0x1A80 /* flash mode */ ++#define VS6624_FLASH_OFF_LINE_MSB 0x1A83 /* off line at flash pulse mode MSB */ ++#define VS6624_FLASH_OFF_LINE_LSB 0x1A84 /* off line at flash pulse mode LSB */ ++/* flash status */ ++#define VS6624_FLASH_RECOM 0x1B00 /* flash gun is recommended */ ++#define VS6624_FLASH_GRAB_COMPLETE 0x1B02 /* flash gun image has been grabbed */ ++/* scythe filter controls */ ++#define VS6624_SCYTHE_FILTER 0x1D80 /* disable scythe defect correction */ ++/* jack filter controls */ ++#define VS6624_JACK_FILTER 0x1E00 /* disable jack defect correction */ ++/* demosaic control */ ++#define VS6624_ANTI_ALIAS_FILTER 0x1E80 /* anti alias filter suppress */ ++/* color matrix dampers */ ++#define VS6624_CM_DISABLE 0x1F00 /* disable color matrix damper */ ++#define VS6624_CM_LOW_THR_MSB 0x1F03 /* low threshold for exposure MSB */ ++#define VS6624_CM_LOW_THR_LSB 0x1F04 /* low threshold for exposure LSB */ ++#define VS6624_CM_HIGH_THR_MSB 0x1F07 /* high threshold for exposure MSB */ ++#define VS6624_CM_HIGH_THR_LSB 0x1F08 /* high threshold for exposure LSB */ ++#define VS6624_CM_MIN_OUT_MSB 0x1F0B /* minimum possible damper output MSB */ ++#define VS6624_CM_MIN_OUT_LSB 0x1F0C /* minimum possible damper output LSB */ ++/* peaking control */ ++#define VS6624_PEAK_GAIN 0x2000 /* controls peaking gain */ ++#define VS6624_PEAK_G_DISABLE 0x2002 /* disable peak gain damping */ ++#define VS6624_PEAK_LOW_THR_G_MSB 0x2005 /* low threshold for exposure for gain MSB */ ++#define VS6624_PEAK_LOW_THR_G_LSB 0x2006 /* low threshold for exposure for gain LSB */ ++#define VS6624_PEAK_HIGH_THR_G_MSB 0x2009 /* high threshold for exposure for gain MSB */ ++#define VS6624_PEAK_HIGH_THR_G_LSB 0x200A /* high threshold for exposure for gain LSB */ ++#define VS6624_PEAK_MIN_OUT_G_MSB 0x200D /* minimum damper output for gain MSB */ ++#define VS6624_PEAK_MIN_OUT_G_LSB 0x200E /* minimum damper output for gain LSB */ ++#define VS6624_PEAK_LOW_THR 0x2010 /* adjust degree of coring */ ++#define VS6624_PEAK_C_DISABLE 0x2012 /* disable coring damping */ ++#define VS6624_PEAK_HIGH_THR 0x2014 /* adjust maximum gain */ ++#define VS6624_PEAK_LOW_THR_C_MSB 0x2017 /* low threshold for exposure for coring MSB */ ++#define VS6624_PEAK_LOW_THR_C_LSB 0x2018 /* low threshold for exposure for coring LSB */ ++#define VS6624_PEAK_HIGH_THR_C_MSB 0x201B /* high threshold for exposure for coring MSB */ ++#define VS6624_PEAK_HIGH_THR_C_LSB 0x201C /* high threshold for exposure for coring LSB */ ++#define VS6624_PEAK_MIN_OUT_C_MSB 0x201F /* minimum damper output for coring MSB */ ++#define VS6624_PEAK_MIN_OUT_C_LSB 0x2020 /* minimum damper output for coring LSB */ ++/* pipe 0 RGB to YUV matrix manual control */ ++#define VS6624_RYM0_MAN_CTRL 0x2180 /* enable manual RGB to YUV matrix */ ++#define VS6624_RYM0_W00_MSB 0x2183 /* row 0 column 0 of YUV matrix MSB */ ++#define VS6624_RYM0_W00_LSB 0x2184 /* row 0 column 0 of YUV matrix LSB */ ++#define VS6624_RYM0_W01_MSB 0x2187 /* row 0 column 1 of YUV matrix MSB */ ++#define VS6624_RYM0_W01_LSB 0x2188 /* row 0 column 1 of YUV matrix LSB */ ++#define VS6624_RYM0_W02_MSB 0x218C /* row 0 column 2 of YUV matrix MSB */ ++#define VS6624_RYM0_W02_LSB 0x218D /* row 0 column 2 of YUV matrix LSB */ ++#define VS6624_RYM0_W10_MSB 0x2190 /* row 1 column 0 of YUV matrix MSB */ ++#define VS6624_RYM0_W10_LSB 0x218F /* row 1 column 0 of YUV matrix LSB */ ++#define VS6624_RYM0_W11_MSB 0x2193 /* row 1 column 1 of YUV matrix MSB */ ++#define VS6624_RYM0_W11_LSB 0x2194 /* row 1 column 1 of YUV matrix LSB */ ++#define VS6624_RYM0_W12_MSB 0x2197 /* row 1 column 2 of YUV matrix MSB */ ++#define VS6624_RYM0_W12_LSB 0x2198 /* row 1 column 2 of YUV matrix LSB */ ++#define VS6624_RYM0_W20_MSB 0x219B /* row 2 column 0 of YUV matrix MSB */ ++#define VS6624_RYM0_W20_LSB 0x219C /* row 2 column 0 of YUV matrix LSB */ ++#define VS6624_RYM0_W21_MSB 0x21A0 /* row 2 column 1 of YUV matrix MSB */ ++#define VS6624_RYM0_W21_LSB 0x219F /* row 2 column 1 of YUV matrix LSB */ ++#define VS6624_RYM0_W22_MSB 0x21A3 /* row 2 column 2 of YUV matrix MSB */ ++#define VS6624_RYM0_W22_LSB 0x21A4 /* row 2 column 2 of YUV matrix LSB */ ++#define VS6624_RYM0_YINY_MSB 0x21A7 /* Y in Y MSB */ ++#define VS6624_RYM0_YINY_LSB 0x21A8 /* Y in Y LSB */ ++#define VS6624_RYM0_YINCB_MSB 0x21AB /* Y in Cb MSB */ ++#define VS6624_RYM0_YINCB_LSB 0x21AC /* Y in Cb LSB */ ++#define VS6624_RYM0_YINCR_MSB 0x21B0 /* Y in Cr MSB */ ++#define VS6624_RYM0_YINCR_LSB 0x21AF /* Y in Cr LSB */ ++/* pipe 1 RGB to YUV matrix manual control */ ++#define VS6624_RYM1_MAN_CTRL 0x2200 /* enable manual RGB to YUV matrix */ ++#define VS6624_RYM1_W00_MSB 0x2203 /* row 0 column 0 of YUV matrix MSB */ ++#define VS6624_RYM1_W00_LSB 0x2204 /* row 0 column 0 of YUV matrix LSB */ ++#define VS6624_RYM1_W01_MSB 0x2207 /* row 0 column 1 of YUV matrix MSB */ ++#define VS6624_RYM1_W01_LSB 0x2208 /* row 0 column 1 of YUV matrix LSB */ ++#define VS6624_RYM1_W02_MSB 0x220C /* row 0 column 2 of YUV matrix MSB */ ++#define VS6624_RYM1_W02_LSB 0x220D /* row 0 column 2 of YUV matrix LSB */ ++#define VS6624_RYM1_W10_MSB 0x2210 /* row 1 column 0 of YUV matrix MSB */ ++#define VS6624_RYM1_W10_LSB 0x220F /* row 1 column 0 of YUV matrix LSB */ ++#define VS6624_RYM1_W11_MSB 0x2213 /* row 1 column 1 of YUV matrix MSB */ ++#define VS6624_RYM1_W11_LSB 0x2214 /* row 1 column 1 of YUV matrix LSB */ ++#define VS6624_RYM1_W12_MSB 0x2217 /* row 1 column 2 of YUV matrix MSB */ ++#define VS6624_RYM1_W12_LSB 0x2218 /* row 1 column 2 of YUV matrix LSB */ ++#define VS6624_RYM1_W20_MSB 0x221B /* row 2 column 0 of YUV matrix MSB */ ++#define VS6624_RYM1_W20_LSB 0x221C /* row 2 column 0 of YUV matrix LSB */ ++#define VS6624_RYM1_W21_MSB 0x2220 /* row 2 column 1 of YUV matrix MSB */ ++#define VS6624_RYM1_W21_LSB 0x221F /* row 2 column 1 of YUV matrix LSB */ ++#define VS6624_RYM1_W22_MSB 0x2223 /* row 2 column 2 of YUV matrix MSB */ ++#define VS6624_RYM1_W22_LSB 0x2224 /* row 2 column 2 of YUV matrix LSB */ ++#define VS6624_RYM1_YINY_MSB 0x2227 /* Y in Y MSB */ ++#define VS6624_RYM1_YINY_LSB 0x2228 /* Y in Y LSB */ ++#define VS6624_RYM1_YINCB_MSB 0x222B /* Y in Cb MSB */ ++#define VS6624_RYM1_YINCB_LSB 0x222C /* Y in Cb LSB */ ++#define VS6624_RYM1_YINCR_MSB 0x2220 /* Y in Cr MSB */ ++#define VS6624_RYM1_YINCR_LSB 0x222F /* Y in Cr LSB */ ++/* pipe 0 gamma manual control */ ++#define VS6624_GAMMA_MAN_CTRL0 0x2280 /* enable manual gamma setup */ ++#define VS6624_GAMMA_PEAK_R0 0x2282 /* peaked red channel gamma value */ ++#define VS6624_GAMMA_PEAK_G0 0x2284 /* peaked green channel gamma value */ ++#define VS6624_GAMMA_PEAK_B0 0x2286 /* peaked blue channel gamma value */ ++#define VS6624_GAMMA_UNPEAK_R0 0x2288 /* unpeaked red channel gamma value */ ++#define VS6624_GAMMA_UNPEAK_G0 0x228A /* unpeaked green channel gamma value */ ++#define VS6624_GAMMA_UNPEAK_B0 0x228C /* unpeaked blue channel gamma value */ ++/* pipe 1 gamma manual control */ ++#define VS6624_GAMMA_MAN_CTRL1 0x2300 /* enable manual gamma setup */ ++#define VS6624_GAMMA_PEAK_R1 0x2302 /* peaked red channel gamma value */ ++#define VS6624_GAMMA_PEAK_G1 0x2304 /* peaked green channel gamma value */ ++#define VS6624_GAMMA_PEAK_B1 0x2306 /* peaked blue channel gamma value */ ++#define VS6624_GAMMA_UNPEAK_R1 0x2308 /* unpeaked red channel gamma value */ ++#define VS6624_GAMMA_UNPEAK_G1 0x230A /* unpeaked green channel gamma value */ ++#define VS6624_GAMMA_UNPEAK_B1 0x230C /* unpeaked blue channel gamma value */ ++/* fade to black */ ++#define VS6624_F2B_DISABLE 0x2480 /* disable fade to black */ ++#define VS6624_F2B_BLACK_VAL_MSB 0x2483 /* black value MSB */ ++#define VS6624_F2B_BLACK_VAL_LSB 0x2484 /* black value LSB */ ++#define VS6624_F2B_LOW_THR_MSB 0x2487 /* low threshold for exposure MSB */ ++#define VS6624_F2B_LOW_THR_LSB 0x2488 /* low threshold for exposure LSB */ ++#define VS6624_F2B_HIGH_THR_MSB 0x248B /* high threshold for exposure MSB */ ++#define VS6624_F2B_HIGH_THR_LSB 0x248C /* high threshold for exposure LSB */ ++#define VS6624_F2B_MIN_OUT_MSB 0x248F /* minimum damper output MSB */ ++#define VS6624_F2B_MIN_OUT_LSB 0x2490 /* minimum damper output LSB */ ++/* output formatter control */ ++#define VS6624_CODE_CK_EN 0x2580 /* code check enable */ ++#define VS6624_BLANK_FMT 0x2582 /* blank format */ ++#define VS6624_SYNC_CODE_SETUP 0x2584 /* sync code setup */ ++#define VS6624_HSYNC_SETUP 0x2586 /* H sync setup */ ++#define VS6624_VSYNC_SETUP 0x2588 /* V sync setup */ ++#define VS6624_PCLK_SETUP 0x258A /* PCLK setup */ ++#define VS6624_PCLK_EN 0x258C /* PCLK enable */ ++#define VS6624_OPF_SP_SETUP 0x258E /* output formatter sp setup */ ++#define VS6624_BLANK_DATA_MSB 0x2590 /* blank data MSB */ ++#define VS6624_BLANK_DATA_LSB 0x2592 /* blank data LSB */ ++#define VS6624_RGB_SETUP 0x2594 /* RGB setup */ ++#define VS6624_YUV_SETUP 0x2596 /* YUV setup */ ++#define VS6624_VSYNC_RIS_COARSE_H 0x2598 /* V sync rising coarse high */ ++#define VS6624_VSYNC_RIS_COARSE_L 0x259A /* V sync rising coarse low */ ++#define VS6624_VSYNC_RIS_FINE_H 0x259C /* V sync rising fine high */ ++#define VS6624_VSYNC_RIS_FINE_L 0x259E /* V sync rising fine low */ ++#define VS6624_VSYNC_FALL_COARSE_H 0x25A0 /* V sync falling coarse high */ ++#define VS6624_VSYNC_FALL_COARSE_L 0x25A2 /* V sync falling coarse low */ ++#define VS6624_VSYNC_FALL_FINE_H 0x25A4 /* V sync falling fine high */ ++#define VS6624_VSYNC_FALL_FINE_L 0x25A6 /* V sync falling fine low */ ++#define VS6624_HSYNC_RIS_H 0x25A8 /* H sync rising high */ ++#define VS6624_HSYNC_RIS_L 0x25AA /* H sync rising low */ ++#define VS6624_HSYNC_FALL_H 0x25AC /* H sync falling high */ ++#define VS6624_HSYNC_FALL_L 0x25AE /* H sync falling low */ ++#define VS6624_OUT_IF 0x25B0 /* output interface */ ++#define VS6624_CCP_EXT_DATA 0x25B2 /* CCP extra data */ ++/* NoRA controls */ ++#define VS6624_NORA_DISABLE 0x2600 /* NoRA control mode */ ++#define VS6624_NORA_USAGE 0x2602 /* usage */ ++#define VS6624_NORA_SPLIT_KN 0x2604 /* split kn */ ++#define VS6624_NORA_SPLIT_NI 0x2606 /* split ni */ ++#define VS6624_NORA_TIGHT_G 0x2608 /* tight green */ ++#define VS6624_NORA_DISABLE_NP 0x260A /* disable noro promoting */ ++#define VS6624_NORA_LOW_THR_MSB 0x260D /* low threshold for exposure MSB */ ++#define VS6624_NORA_LOW_THR_LSB 0x260E /* low threshold for exposure LSB */ ++#define VS6624_NORA_HIGH_THR_MSB 0x2611 /* high threshold for exposure MSB */ ++#define VS6624_NORA_HIGH_THR_LSB 0x2612 /* high threshold for exposure LSB */ ++#define VS6624_NORA_MIN_OUT_MSB 0x2615 /* minimum damper output MSB */ ++#define VS6624_NORA_MIN_OUT_LSB 0x2616 /* minimum damper output LSB */ ++ ++#endif +Index: linux-3.3.x86_64/drivers/media/video/blackfin/Kconfig +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/blackfin/Kconfig +@@ -0,0 +1,10 @@ ++config VIDEO_BLACKFIN_CAPTURE ++ tristate "Blackfin Video Capture Driver" ++ depends on VIDEO_V4L2 && BLACKFIN && I2C ++ select VIDEOBUF2_DMA_CONTIG ++ help ++ V4L2 bridge driver for Blackfin video capture device. ++ Choose PPI or EPPI as its interface. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called bfin_video_capture. +Index: linux-3.3.x86_64/drivers/media/video/blackfin/Makefile +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/blackfin/Makefile +@@ -0,0 +1,2 @@ ++bfin_video_capture-objs := bfin_capture.o ppi.o ++obj-$(CONFIG_VIDEO_BLACKFIN_CAPTURE) += bfin_video_capture.o +Index: linux-3.3.x86_64/drivers/media/video/blackfin/bfin_capture.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/blackfin/bfin_capture.c +@@ -0,0 +1,1059 @@ ++/* ++ * Analog Devices video capture driver ++ * ++ * Copyright (c) 2011 Analog Devices Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++ ++#define CAPTURE_DRV_NAME "bfin_capture" ++#define BCAP_MIN_NUM_BUF 2 ++ ++struct bcap_format { ++ char *desc; ++ u32 pixelformat; ++ enum v4l2_mbus_pixelcode mbus_code; ++ int bpp; /* bits per pixel */ ++}; ++ ++struct bcap_buffer { ++ struct vb2_buffer vb; ++ struct list_head list; ++}; ++ ++struct bcap_device { ++ /* capture device instance */ ++ struct v4l2_device v4l2_dev; ++ /* v4l2 control handler */ ++ struct v4l2_ctrl_handler ctrl_handler; ++ /* device node data */ ++ struct video_device *video_dev; ++ /* sub device instance */ ++ struct v4l2_subdev *sd; ++ /* capture config */ ++ struct bfin_capture_config *cfg; ++ /* ppi interface */ ++ struct ppi_if *ppi; ++ /* current input */ ++ unsigned int cur_input; ++ /* current selected standard */ ++ v4l2_std_id std; ++ /* used to store pixel format */ ++ struct v4l2_pix_format fmt; ++ /* bits per pixel*/ ++ int bpp; ++ /* used to store sensor supported format */ ++ struct bcap_format *sensor_formats; ++ /* number of sensor formats array */ ++ int num_sensor_formats; ++ /* pointing to current video buffer */ ++ struct bcap_buffer *cur_frm; ++ /* pointing to next video buffer */ ++ struct bcap_buffer *next_frm; ++ /* buffer queue used in videobuf2 */ ++ struct vb2_queue buffer_queue; ++ /* allocator-specific contexts for each plane */ ++ struct vb2_alloc_ctx *alloc_ctx; ++ /* queue of filled frames */ ++ struct list_head dma_queue; ++ /* used in videobuf2 callback */ ++ spinlock_t lock; ++ /* used to access capture device */ ++ struct mutex mutex; ++ /* used to wait ppi to complete one transfer */ ++ struct completion comp; ++ /* prepare to stop */ ++ bool stop; ++}; ++ ++struct bcap_fh { ++ struct v4l2_fh fh; ++ /* indicates whether this file handle is doing IO */ ++ bool io_allowed; ++}; ++ ++static const struct bcap_format bcap_formats[] = { ++ { ++ .desc = "YCbCr 4:2:2 Interleaved UYVY", ++ .pixelformat = V4L2_PIX_FMT_UYVY, ++ .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, ++ .bpp = 16, ++ }, ++ { ++ .desc = "YCbCr 4:2:2 Interleaved YUYV", ++ .pixelformat = V4L2_PIX_FMT_YUYV, ++ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, ++ .bpp = 16, ++ }, ++ { ++ .desc = "RGB 565", ++ .pixelformat = V4L2_PIX_FMT_RGB565, ++ .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, ++ .bpp = 16, ++ }, ++ { ++ .desc = "RGB 444", ++ .pixelformat = V4L2_PIX_FMT_RGB444, ++ .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, ++ .bpp = 16, ++ }, ++ ++}; ++#define BCAP_MAX_FMTS ARRAY_SIZE(bcap_formats) ++ ++static irqreturn_t bcap_isr(int irq, void *dev_id); ++ ++static struct bcap_buffer *to_bcap_vb(struct vb2_buffer *vb) ++{ ++ return container_of(vb, struct bcap_buffer, vb); ++} ++ ++static int bcap_init_sensor_formats(struct bcap_device *bcap_dev) ++{ ++ enum v4l2_mbus_pixelcode code; ++ struct bcap_format *sf; ++ unsigned int num_formats = 0; ++ int i, j; ++ ++ while (!v4l2_subdev_call(bcap_dev->sd, video, ++ enum_mbus_fmt, num_formats, &code)) ++ num_formats++; ++ if (!num_formats) ++ return -ENXIO; ++ ++ sf = kzalloc(num_formats * sizeof(*sf), GFP_KERNEL); ++ if (!sf) ++ return -ENOMEM; ++ ++ for (i = 0; i < num_formats; i++) { ++ v4l2_subdev_call(bcap_dev->sd, video, ++ enum_mbus_fmt, i, &code); ++ for (j = 0; j < BCAP_MAX_FMTS; j++) ++ if (code == bcap_formats[j].mbus_code) ++ break; ++ if (j == BCAP_MAX_FMTS) { ++ /* we don't allow this sensor working with our bridge */ ++ kfree(sf); ++ return -EINVAL; ++ } ++ sf[i] = bcap_formats[j]; ++ } ++ bcap_dev->sensor_formats = sf; ++ bcap_dev->num_sensor_formats = num_formats; ++ return 0; ++} ++ ++static void bcap_free_sensor_formats(struct bcap_device *bcap_dev) ++{ ++ bcap_dev->num_sensor_formats = 0; ++ kfree(bcap_dev->sensor_formats); ++ bcap_dev->sensor_formats = NULL; ++} ++ ++static int bcap_open(struct file *file) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct video_device *vfd = bcap_dev->video_dev; ++ struct bcap_fh *bcap_fh; ++ ++ if (!bcap_dev->sd) { ++ v4l2_err(&bcap_dev->v4l2_dev, "No sub device registered\n"); ++ return -ENODEV; ++ } ++ ++ bcap_fh = kzalloc(sizeof(*bcap_fh), GFP_KERNEL); ++ if (!bcap_fh) { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "unable to allocate memory for file handle object\n"); ++ return -ENOMEM; ++ } ++ ++ v4l2_fh_init(&bcap_fh->fh, vfd); ++ ++ /* store pointer to v4l2_fh in private_data member of file */ ++ file->private_data = &bcap_fh->fh; ++ v4l2_fh_add(&bcap_fh->fh); ++ bcap_fh->io_allowed = false; ++ return 0; ++} ++ ++static int bcap_release(struct file *file) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct v4l2_fh *fh = file->private_data; ++ struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); ++ ++ /* if this instance is doing IO */ ++ if (bcap_fh->io_allowed) ++ vb2_queue_release(&bcap_dev->buffer_queue); ++ ++ file->private_data = NULL; ++ v4l2_fh_del(&bcap_fh->fh); ++ v4l2_fh_exit(&bcap_fh->fh); ++ kfree(bcap_fh); ++ return 0; ++} ++ ++static int bcap_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ return vb2_mmap(&bcap_dev->buffer_queue, vma); ++} ++ ++#ifndef CONFIG_MMU ++static unsigned long bcap_get_unmapped_area(struct file *file, ++ unsigned long addr, ++ unsigned long len, ++ unsigned long pgoff, ++ unsigned long flags) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ return vb2_get_unmapped_area(&bcap_dev->buffer_queue, ++ addr, ++ len, ++ pgoff, ++ flags); ++} ++#endif ++ ++static unsigned int bcap_poll(struct file *file, poll_table *wait) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ return vb2_poll(&bcap_dev->buffer_queue, file, wait); ++} ++ ++static int bcap_queue_setup(struct vb2_queue *vq, ++ const struct v4l2_format *fmt, ++ unsigned int *nbuffers, unsigned int *nplanes, ++ unsigned int sizes[], void *alloc_ctxs[]) ++{ ++ struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); ++ ++ if (*nbuffers < BCAP_MIN_NUM_BUF) ++ *nbuffers = BCAP_MIN_NUM_BUF; ++ ++ *nplanes = 1; ++ sizes[0] = bcap_dev->fmt.sizeimage; ++ alloc_ctxs[0] = bcap_dev->alloc_ctx; ++ ++ return 0; ++} ++ ++static int bcap_buffer_init(struct vb2_buffer *vb) ++{ ++ struct bcap_buffer *buf = to_bcap_vb(vb); ++ ++ INIT_LIST_HEAD(&buf->list); ++ return 0; ++} ++ ++static int bcap_buffer_prepare(struct vb2_buffer *vb) ++{ ++ struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); ++ struct bcap_buffer *buf = to_bcap_vb(vb); ++ unsigned long size; ++ ++ size = bcap_dev->fmt.sizeimage; ++ if (vb2_plane_size(vb, 0) < size) { ++ v4l2_err(&bcap_dev->v4l2_dev, "buffer too small (%lu < %lu)\n", ++ vb2_plane_size(vb, 0), size); ++ return -EINVAL; ++ } ++ vb2_set_plane_payload(&buf->vb, 0, size); ++ ++ return 0; ++} ++ ++static void bcap_buffer_queue(struct vb2_buffer *vb) ++{ ++ struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); ++ struct bcap_buffer *buf = to_bcap_vb(vb); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&bcap_dev->lock, flags); ++ list_add_tail(&buf->list, &bcap_dev->dma_queue); ++ spin_unlock_irqrestore(&bcap_dev->lock, flags); ++} ++ ++static void bcap_buffer_cleanup(struct vb2_buffer *vb) ++{ ++ struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); ++ struct bcap_buffer *buf = to_bcap_vb(vb); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&bcap_dev->lock, flags); ++ list_del_init(&buf->list); ++ spin_unlock_irqrestore(&bcap_dev->lock, flags); ++} ++ ++static void bcap_lock(struct vb2_queue *vq) ++{ ++ struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); ++ mutex_lock(&bcap_dev->mutex); ++} ++ ++static void bcap_unlock(struct vb2_queue *vq) ++{ ++ struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); ++ mutex_unlock(&bcap_dev->mutex); ++} ++ ++static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count) ++{ ++ struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); ++ struct ppi_if *ppi = bcap_dev->ppi; ++ struct ppi_params params; ++ int ret; ++ ++ /* enable streamon on the sub device */ ++ ret = v4l2_subdev_call(bcap_dev->sd, video, s_stream, 1); ++ if (ret && (ret != -ENOIOCTLCMD)) { ++ v4l2_err(&bcap_dev->v4l2_dev, "stream on failed in subdev\n"); ++ return ret; ++ } ++ ++ /* set ppi params */ ++ params.width = bcap_dev->fmt.width; ++ params.height = bcap_dev->fmt.height; ++ params.bpp = bcap_dev->bpp; ++ params.ppi_control = bcap_dev->cfg->ppi_control; ++ params.int_mask = bcap_dev->cfg->int_mask; ++ params.blank_clocks = bcap_dev->cfg->blank_clocks; ++ ret = ppi->ops->set_params(ppi, ¶ms); ++ if (ret < 0) { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "Error in setting ppi params\n"); ++ return ret; ++ } ++ ++ /* attach ppi DMA irq handler */ ++ ret = ppi->ops->attach_irq(ppi, bcap_isr); ++ if (ret < 0) { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "Error in attaching interrupt handler\n"); ++ return ret; ++ } ++ ++ INIT_COMPLETION(bcap_dev->comp); ++ bcap_dev->stop = false; ++ return 0; ++} ++ ++static int bcap_stop_streaming(struct vb2_queue *vq) ++{ ++ struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); ++ struct ppi_if *ppi = bcap_dev->ppi; ++ int ret; ++ ++ if (!vb2_is_streaming(vq)) ++ return 0; ++ ++ bcap_dev->stop = true; ++ wait_for_completion(&bcap_dev->comp); ++ ppi->ops->stop(ppi); ++ ppi->ops->detach_irq(ppi); ++ ret = v4l2_subdev_call(bcap_dev->sd, video, s_stream, 0); ++ if (ret && (ret != -ENOIOCTLCMD)) ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "stream off failed in subdev\n"); ++ ++ /* release all active buffers */ ++ while (!list_empty(&bcap_dev->dma_queue)) { ++ bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, ++ struct bcap_buffer, list); ++ list_del(&bcap_dev->next_frm->list); ++ vb2_buffer_done(&bcap_dev->next_frm->vb, VB2_BUF_STATE_ERROR); ++ } ++ return 0; ++} ++ ++static struct vb2_ops bcap_video_qops = { ++ .queue_setup = bcap_queue_setup, ++ .buf_init = bcap_buffer_init, ++ .buf_prepare = bcap_buffer_prepare, ++ .buf_cleanup = bcap_buffer_cleanup, ++ .buf_queue = bcap_buffer_queue, ++ .wait_prepare = bcap_unlock, ++ .wait_finish = bcap_lock, ++ .start_streaming = bcap_start_streaming, ++ .stop_streaming = bcap_stop_streaming, ++}; ++ ++static int bcap_reqbufs(struct file *file, void *priv, ++ struct v4l2_requestbuffers *req_buf) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct vb2_queue *vq = &bcap_dev->buffer_queue; ++ struct v4l2_fh *fh = file->private_data; ++ struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); ++ ++ if (vb2_is_busy(vq)) ++ return -EBUSY; ++ ++ bcap_fh->io_allowed = true; ++ ++ return vb2_reqbufs(vq, req_buf); ++} ++ ++static int bcap_querybuf(struct file *file, void *priv, ++ struct v4l2_buffer *buf) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ return vb2_querybuf(&bcap_dev->buffer_queue, buf); ++} ++ ++static int bcap_qbuf(struct file *file, void *priv, ++ struct v4l2_buffer *buf) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct v4l2_fh *fh = file->private_data; ++ struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); ++ ++ if (!bcap_fh->io_allowed) ++ return -EBUSY; ++ ++ return vb2_qbuf(&bcap_dev->buffer_queue, buf); ++} ++ ++static int bcap_dqbuf(struct file *file, void *priv, ++ struct v4l2_buffer *buf) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct v4l2_fh *fh = file->private_data; ++ struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); ++ ++ if (!bcap_fh->io_allowed) ++ return -EBUSY; ++ ++ return vb2_dqbuf(&bcap_dev->buffer_queue, ++ buf, file->f_flags & O_NONBLOCK); ++} ++ ++static irqreturn_t bcap_isr(int irq, void *dev_id) ++{ ++ struct ppi_if *ppi = dev_id; ++ struct bcap_device *bcap_dev = ppi->priv; ++ struct timeval timevalue; ++ struct vb2_buffer *vb = &bcap_dev->cur_frm->vb; ++ dma_addr_t addr; ++ ++ spin_lock(&bcap_dev->lock); ++ ++ if (bcap_dev->cur_frm != bcap_dev->next_frm) { ++ do_gettimeofday(&timevalue); ++ vb->v4l2_buf.timestamp = timevalue; ++ vb2_buffer_done(vb, VB2_BUF_STATE_DONE); ++ bcap_dev->cur_frm = bcap_dev->next_frm; ++ } ++ ++ ppi->ops->stop(ppi); ++ ++ if (bcap_dev->stop) { ++ complete(&bcap_dev->comp); ++ } else { ++ if (!list_empty(&bcap_dev->dma_queue)) { ++ bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, ++ struct bcap_buffer, list); ++ list_del(&bcap_dev->next_frm->list); ++ addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->next_frm->vb, 0); ++ ppi->ops->update_addr(ppi, (unsigned long)addr); ++ } ++ ppi->ops->start(ppi); ++ } ++ ++ spin_unlock(&bcap_dev->lock); ++ ++ return IRQ_HANDLED; ++} ++ ++static int bcap_streamon(struct file *file, void *priv, ++ enum v4l2_buf_type buf_type) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct bcap_fh *fh = file->private_data; ++ struct ppi_if *ppi = bcap_dev->ppi; ++ dma_addr_t addr; ++ int ret; ++ ++ if (!fh->io_allowed) ++ return -EBUSY; ++ ++ /* call streamon to start streaming in videobuf */ ++ ret = vb2_streamon(&bcap_dev->buffer_queue, buf_type); ++ if (ret) ++ return ret; ++ ++ /* if dma queue is empty, return error */ ++ if (list_empty(&bcap_dev->dma_queue)) { ++ v4l2_err(&bcap_dev->v4l2_dev, "dma queue is empty\n"); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ /* get the next frame from the dma queue */ ++ bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, ++ struct bcap_buffer, list); ++ bcap_dev->cur_frm = bcap_dev->next_frm; ++ /* remove buffer from the dma queue */ ++ list_del(&bcap_dev->cur_frm->list); ++ addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0); ++ /* update DMA address */ ++ ppi->ops->update_addr(ppi, (unsigned long)addr); ++ /* enable ppi */ ++ ppi->ops->start(ppi); ++ ++ return 0; ++err: ++ vb2_streamoff(&bcap_dev->buffer_queue, buf_type); ++ return ret; ++} ++ ++static int bcap_streamoff(struct file *file, void *priv, ++ enum v4l2_buf_type buf_type) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct bcap_fh *fh = file->private_data; ++ ++ if (!fh->io_allowed) ++ return -EBUSY; ++ ++ return vb2_streamoff(&bcap_dev->buffer_queue, buf_type); ++} ++ ++static int bcap_querystd(struct file *file, void *priv, v4l2_std_id *std) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ return v4l2_subdev_call(bcap_dev->sd, video, querystd, std); ++} ++ ++static int bcap_g_std(struct file *file, void *priv, v4l2_std_id *std) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ *std = bcap_dev->std; ++ return 0; ++} ++ ++static int bcap_s_std(struct file *file, void *priv, v4l2_std_id *std) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ int ret; ++ ++ if (vb2_is_busy(&bcap_dev->buffer_queue)) ++ return -EBUSY; ++ ++ ret = v4l2_subdev_call(bcap_dev->sd, core, s_std, *std); ++ if (ret < 0) ++ return ret; ++ ++ bcap_dev->std = *std; ++ return 0; ++} ++ ++static int bcap_enum_input(struct file *file, void *priv, ++ struct v4l2_input *input) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct bfin_capture_config *config = bcap_dev->cfg; ++ int ret; ++ u32 status; ++ ++ if (input->index >= config->num_inputs) ++ return -EINVAL; ++ ++ *input = config->inputs[input->index]; ++ /* get input status */ ++ ret = v4l2_subdev_call(bcap_dev->sd, video, g_input_status, &status); ++ if (!ret) ++ input->status = status; ++ return 0; ++} ++ ++static int bcap_g_input(struct file *file, void *priv, unsigned int *index) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ *index = bcap_dev->cur_input; ++ return 0; ++} ++ ++static int bcap_s_input(struct file *file, void *priv, unsigned int index) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct bfin_capture_config *config = bcap_dev->cfg; ++ struct bcap_route *route; ++ int ret; ++ ++ if (vb2_is_busy(&bcap_dev->buffer_queue)) ++ return -EBUSY; ++ ++ if (index >= config->num_inputs) ++ return -EINVAL; ++ ++ route = &config->routes[index]; ++ ret = v4l2_subdev_call(bcap_dev->sd, video, s_routing, ++ route->input, route->output, 0); ++ if ((ret < 0) && (ret != -ENOIOCTLCMD)) { ++ v4l2_err(&bcap_dev->v4l2_dev, "Failed to set input\n"); ++ return ret; ++ } ++ bcap_dev->cur_input = index; ++ return 0; ++} ++ ++static int bcap_try_format(struct bcap_device *bcap, ++ struct v4l2_pix_format *pixfmt, ++ enum v4l2_mbus_pixelcode *mbus_code, ++ int *bpp) ++{ ++ struct bcap_format *sf = bcap->sensor_formats; ++ struct bcap_format *fmt = NULL; ++ struct v4l2_mbus_framefmt mbus_fmt; ++ int ret, i; ++ ++ for (i = 0; i < bcap->num_sensor_formats; i++) { ++ fmt = &sf[i]; ++ if (pixfmt->pixelformat == fmt->pixelformat) ++ break; ++ } ++ if (i == bcap->num_sensor_formats) ++ fmt = &sf[0]; ++ ++ if (mbus_code) ++ *mbus_code = fmt->mbus_code; ++ if (bpp) ++ *bpp = fmt->bpp; ++ v4l2_fill_mbus_format(&mbus_fmt, pixfmt, fmt->mbus_code); ++ ret = v4l2_subdev_call(bcap->sd, video, ++ try_mbus_fmt, &mbus_fmt); ++ if (ret < 0) ++ return ret; ++ v4l2_fill_pix_format(pixfmt, &mbus_fmt); ++ pixfmt->bytesperline = pixfmt->width * fmt->bpp / 8; ++ pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; ++ return 0; ++} ++ ++static int bcap_enum_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_fmtdesc *fmt) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct bcap_format *sf = bcap_dev->sensor_formats; ++ ++ if (fmt->index >= bcap_dev->num_sensor_formats) ++ return -EINVAL; ++ ++ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ strlcpy(fmt->description, ++ sf[fmt->index].desc, ++ sizeof(fmt->description)); ++ fmt->pixelformat = sf[fmt->index].pixelformat; ++ return 0; ++} ++ ++static int bcap_try_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *fmt) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; ++ ++ return bcap_try_format(bcap_dev, pixfmt, NULL, NULL); ++} ++ ++static int bcap_g_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *fmt) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ fmt->fmt.pix = bcap_dev->fmt; ++ return 0; ++} ++ ++static int bcap_s_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *fmt) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ struct v4l2_mbus_framefmt mbus_fmt; ++ enum v4l2_mbus_pixelcode mbus_code; ++ struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; ++ int ret, bpp; ++ ++ if (vb2_is_busy(&bcap_dev->buffer_queue)) ++ return -EBUSY; ++ ++ /* see if format works */ ++ ret = bcap_try_format(bcap_dev, pixfmt, &mbus_code, &bpp); ++ if (ret < 0) ++ return ret; ++ ++ v4l2_fill_mbus_format(&mbus_fmt, pixfmt, mbus_code); ++ ret = v4l2_subdev_call(bcap_dev->sd, video, s_mbus_fmt, &mbus_fmt); ++ if (ret < 0) ++ return ret; ++ bcap_dev->fmt = *pixfmt; ++ bcap_dev->bpp = bpp; ++ return 0; ++} ++ ++static int bcap_querycap(struct file *file, void *priv, ++ struct v4l2_capability *cap) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; ++ strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver)); ++ strlcpy(cap->bus_info, "Blackfin Platform", sizeof(cap->bus_info)); ++ strlcpy(cap->card, bcap_dev->cfg->card_name, sizeof(cap->card)); ++ return 0; ++} ++ ++static int bcap_g_parm(struct file *file, void *fh, ++ struct v4l2_streamparm *a) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ return v4l2_subdev_call(bcap_dev->sd, video, g_parm, a); ++} ++ ++static int bcap_s_parm(struct file *file, void *fh, ++ struct v4l2_streamparm *a) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ return v4l2_subdev_call(bcap_dev->sd, video, s_parm, a); ++} ++ ++static int bcap_g_chip_ident(struct file *file, void *priv, ++ struct v4l2_dbg_chip_ident *chip) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ chip->ident = V4L2_IDENT_NONE; ++ chip->revision = 0; ++ if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && ++ chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) ++ return -EINVAL; ++ ++ return v4l2_subdev_call(bcap_dev->sd, core, ++ g_chip_ident, chip); ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int bcap_dbg_g_register(struct file *file, void *priv, ++ struct v4l2_dbg_register *reg) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ return v4l2_subdev_call(bcap_dev->sd, core, ++ g_register, reg); ++} ++ ++static int bcap_dbg_s_register(struct file *file, void *priv, ++ struct v4l2_dbg_register *reg) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ ++ return v4l2_subdev_call(bcap_dev->sd, core, ++ s_register, reg); ++} ++#endif ++ ++static int bcap_log_status(struct file *file, void *priv) ++{ ++ struct bcap_device *bcap_dev = video_drvdata(file); ++ /* status for sub devices */ ++ v4l2_device_call_all(&bcap_dev->v4l2_dev, 0, core, log_status); ++ return 0; ++} ++ ++static const struct v4l2_ioctl_ops bcap_ioctl_ops = { ++ .vidioc_querycap = bcap_querycap, ++ .vidioc_g_fmt_vid_cap = bcap_g_fmt_vid_cap, ++ .vidioc_enum_fmt_vid_cap = bcap_enum_fmt_vid_cap, ++ .vidioc_s_fmt_vid_cap = bcap_s_fmt_vid_cap, ++ .vidioc_try_fmt_vid_cap = bcap_try_fmt_vid_cap, ++ .vidioc_enum_input = bcap_enum_input, ++ .vidioc_g_input = bcap_g_input, ++ .vidioc_s_input = bcap_s_input, ++ .vidioc_querystd = bcap_querystd, ++ .vidioc_s_std = bcap_s_std, ++ .vidioc_g_std = bcap_g_std, ++ .vidioc_reqbufs = bcap_reqbufs, ++ .vidioc_querybuf = bcap_querybuf, ++ .vidioc_qbuf = bcap_qbuf, ++ .vidioc_dqbuf = bcap_dqbuf, ++ .vidioc_streamon = bcap_streamon, ++ .vidioc_streamoff = bcap_streamoff, ++ .vidioc_g_parm = bcap_g_parm, ++ .vidioc_s_parm = bcap_s_parm, ++ .vidioc_g_chip_ident = bcap_g_chip_ident, ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .vidioc_g_register = bcap_dbg_g_register, ++ .vidioc_s_register = bcap_dbg_s_register, ++#endif ++ .vidioc_log_status = bcap_log_status, ++}; ++ ++static struct v4l2_file_operations bcap_fops = { ++ .owner = THIS_MODULE, ++ .open = bcap_open, ++ .release = bcap_release, ++ .unlocked_ioctl = video_ioctl2, ++ .mmap = bcap_mmap, ++#ifndef CONFIG_MMU ++ .get_unmapped_area = bcap_get_unmapped_area, ++#endif ++ .poll = bcap_poll ++}; ++ ++static int __devinit bcap_probe(struct platform_device *pdev) ++{ ++ struct bcap_device *bcap_dev; ++ struct video_device *vfd; ++ struct i2c_adapter *i2c_adap; ++ struct bfin_capture_config *config; ++ struct vb2_queue *q; ++ int ret; ++ ++ config = pdev->dev.platform_data; ++ if (!config) { ++ v4l2_err(pdev->dev.driver, "Unable to get board config\n"); ++ return -ENODEV; ++ } ++ ++ bcap_dev = kzalloc(sizeof(*bcap_dev), GFP_KERNEL); ++ if (!bcap_dev) { ++ v4l2_err(pdev->dev.driver, "Unable to alloc bcap_dev\n"); ++ return -ENOMEM; ++ } ++ ++ bcap_dev->cfg = config; ++ ++ bcap_dev->ppi = ppi_create_instance(config->ppi_info); ++ if (!bcap_dev->ppi) { ++ v4l2_err(pdev->dev.driver, "Unable to create ppi\n"); ++ ret = -ENODEV; ++ goto err_free_dev; ++ } ++ bcap_dev->ppi->priv = bcap_dev; ++ ++ bcap_dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); ++ if (IS_ERR(bcap_dev->alloc_ctx)) { ++ ret = PTR_ERR(bcap_dev->alloc_ctx); ++ goto err_free_ppi; ++ } ++ ++ vfd = video_device_alloc(); ++ if (!vfd) { ++ ret = -ENOMEM; ++ v4l2_err(pdev->dev.driver, "Unable to alloc video device\n"); ++ goto err_cleanup_ctx; ++ } ++ ++ /* initialize field of video device */ ++ vfd->release = video_device_release; ++ vfd->fops = &bcap_fops; ++ vfd->ioctl_ops = &bcap_ioctl_ops; ++ vfd->tvnorms = 0; ++ vfd->v4l2_dev = &bcap_dev->v4l2_dev; ++ set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); ++ strncpy(vfd->name, CAPTURE_DRV_NAME, sizeof(vfd->name)); ++ bcap_dev->video_dev = vfd; ++ ++ ret = v4l2_device_register(&pdev->dev, &bcap_dev->v4l2_dev); ++ if (ret) { ++ v4l2_err(pdev->dev.driver, ++ "Unable to register v4l2 device\n"); ++ goto err_release_vdev; ++ } ++ v4l2_info(&bcap_dev->v4l2_dev, "v4l2 device registered\n"); ++ ++ bcap_dev->v4l2_dev.ctrl_handler = &bcap_dev->ctrl_handler; ++ ret = v4l2_ctrl_handler_init(&bcap_dev->ctrl_handler, 0); ++ if (ret) { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "Unable to init control handler\n"); ++ goto err_unreg_v4l2; ++ } ++ ++ spin_lock_init(&bcap_dev->lock); ++ /* initialize queue */ ++ q = &bcap_dev->buffer_queue; ++ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ q->io_modes = VB2_MMAP; ++ q->drv_priv = bcap_dev; ++ q->buf_struct_size = sizeof(struct bcap_buffer); ++ q->ops = &bcap_video_qops; ++ q->mem_ops = &vb2_dma_contig_memops; ++ ++ vb2_queue_init(q); ++ ++ mutex_init(&bcap_dev->mutex); ++ init_completion(&bcap_dev->comp); ++ ++ /* init video dma queues */ ++ INIT_LIST_HEAD(&bcap_dev->dma_queue); ++ ++ vfd->lock = &bcap_dev->mutex; ++ ++ /* register video device */ ++ ret = video_register_device(bcap_dev->video_dev, VFL_TYPE_GRABBER, -1); ++ if (ret) { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "Unable to register video device\n"); ++ goto err_free_handler; ++ } ++ video_set_drvdata(bcap_dev->video_dev, bcap_dev); ++ v4l2_info(&bcap_dev->v4l2_dev, "video device registered as: %s\n", ++ video_device_node_name(vfd)); ++ ++ /* load up the subdevice */ ++ i2c_adap = i2c_get_adapter(config->i2c_adapter_id); ++ if (!i2c_adap) { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "Unable to find i2c adapter\n"); ++ goto err_unreg_vdev; ++ ++ } ++ bcap_dev->sd = v4l2_i2c_new_subdev_board(&bcap_dev->v4l2_dev, ++ i2c_adap, ++ &config->board_info, ++ NULL); ++ if (bcap_dev->sd) { ++ int i; ++ /* update tvnorms from the sub devices */ ++ for (i = 0; i < config->num_inputs; i++) ++ vfd->tvnorms |= config->inputs[i].std; ++ } else { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "Unable to register sub device\n"); ++ goto err_unreg_vdev; ++ } ++ ++ v4l2_info(&bcap_dev->v4l2_dev, "v4l2 sub device registered\n"); ++ ++ /* now we can probe the default state */ ++ if (vfd->tvnorms) { ++ v4l2_std_id std; ++ ret = v4l2_subdev_call(bcap_dev->sd, core, g_std, &std); ++ if (ret) { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "Unable to get std\n"); ++ goto err_unreg_vdev; ++ } ++ bcap_dev->std = std; ++ } ++ ret = bcap_init_sensor_formats(bcap_dev); ++ if (ret) { ++ v4l2_err(&bcap_dev->v4l2_dev, ++ "Unable to create sensor formats table\n"); ++ goto err_unreg_vdev; ++ } ++ return 0; ++err_unreg_vdev: ++ video_unregister_device(bcap_dev->video_dev); ++ bcap_dev->video_dev = NULL; ++err_free_handler: ++ v4l2_ctrl_handler_free(&bcap_dev->ctrl_handler); ++err_unreg_v4l2: ++ v4l2_device_unregister(&bcap_dev->v4l2_dev); ++err_release_vdev: ++ if (bcap_dev->video_dev) ++ video_device_release(bcap_dev->video_dev); ++err_cleanup_ctx: ++ vb2_dma_contig_cleanup_ctx(bcap_dev->alloc_ctx); ++err_free_ppi: ++ ppi_delete_instance(bcap_dev->ppi); ++err_free_dev: ++ kfree(bcap_dev); ++ return ret; ++} ++ ++static int __devexit bcap_remove(struct platform_device *pdev) ++{ ++ struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); ++ struct bcap_device *bcap_dev = container_of(v4l2_dev, ++ struct bcap_device, v4l2_dev); ++ ++ bcap_free_sensor_formats(bcap_dev); ++ video_unregister_device(bcap_dev->video_dev); ++ v4l2_ctrl_handler_free(&bcap_dev->ctrl_handler); ++ v4l2_device_unregister(v4l2_dev); ++ vb2_dma_contig_cleanup_ctx(bcap_dev->alloc_ctx); ++ ppi_delete_instance(bcap_dev->ppi); ++ kfree(bcap_dev); ++ return 0; ++} ++ ++static struct platform_driver bcap_driver = { ++ .driver = { ++ .name = CAPTURE_DRV_NAME, ++ .owner = THIS_MODULE, ++ }, ++ .probe = bcap_probe, ++ .remove = __devexit_p(bcap_remove), ++}; ++ ++static __init int bcap_init(void) ++{ ++ return platform_driver_register(&bcap_driver); ++} ++ ++static __exit void bcap_exit(void) ++{ ++ platform_driver_unregister(&bcap_driver); ++} ++ ++module_init(bcap_init); ++module_exit(bcap_exit); ++ ++MODULE_DESCRIPTION("Analog Devices blackfin video capture driver"); ++MODULE_AUTHOR("Scott Jiang "); ++MODULE_LICENSE("GPL v2"); +Index: linux-3.3.x86_64/drivers/media/video/blackfin/ppi.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/blackfin/ppi.c +@@ -0,0 +1,271 @@ ++/* ++ * ppi.c Analog Devices Parallel Peripheral Interface driver ++ * ++ * Copyright (c) 2011 Analog Devices Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++static int ppi_attach_irq(struct ppi_if *ppi, irq_handler_t handler); ++static void ppi_detach_irq(struct ppi_if *ppi); ++static int ppi_start(struct ppi_if *ppi); ++static int ppi_stop(struct ppi_if *ppi); ++static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params); ++static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr); ++ ++static const struct ppi_ops ppi_ops = { ++ .attach_irq = ppi_attach_irq, ++ .detach_irq = ppi_detach_irq, ++ .start = ppi_start, ++ .stop = ppi_stop, ++ .set_params = ppi_set_params, ++ .update_addr = ppi_update_addr, ++}; ++ ++static irqreturn_t ppi_irq_err(int irq, void *dev_id) ++{ ++ struct ppi_if *ppi = dev_id; ++ const struct ppi_info *info = ppi->info; ++ ++ switch (info->type) { ++ case PPI_TYPE_PPI: ++ { ++ struct bfin_ppi_regs *reg = info->base; ++ unsigned short status; ++ ++ /* register on bf561 is cleared when read ++ * others are W1C ++ */ ++ status = bfin_read16(®->status); ++ bfin_write16(®->status, 0xff00); ++ break; ++ } ++ case PPI_TYPE_EPPI: ++ { ++ struct bfin_eppi_regs *reg = info->base; ++ bfin_write16(®->status, 0xffff); ++ break; ++ } ++ default: ++ break; ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static int ppi_attach_irq(struct ppi_if *ppi, irq_handler_t handler) ++{ ++ const struct ppi_info *info = ppi->info; ++ int ret; ++ ++ ret = request_dma(info->dma_ch, "PPI_DMA"); ++ ++ if (ret) { ++ pr_err("Unable to allocate DMA channel for PPI\n"); ++ return ret; ++ } ++ set_dma_callback(info->dma_ch, handler, ppi); ++ ++ if (ppi->err_int) { ++ ret = request_irq(info->irq_err, ppi_irq_err, 0, "PPI ERROR", ppi); ++ if (ret) { ++ pr_err("Unable to allocate IRQ for PPI\n"); ++ free_dma(info->dma_ch); ++ } ++ } ++ return ret; ++} ++ ++static void ppi_detach_irq(struct ppi_if *ppi) ++{ ++ const struct ppi_info *info = ppi->info; ++ ++ if (ppi->err_int) ++ free_irq(info->irq_err, ppi); ++ free_dma(info->dma_ch); ++} ++ ++static int ppi_start(struct ppi_if *ppi) ++{ ++ const struct ppi_info *info = ppi->info; ++ ++ /* enable DMA */ ++ enable_dma(info->dma_ch); ++ ++ /* enable PPI */ ++ ppi->ppi_control |= PORT_EN; ++ switch (info->type) { ++ case PPI_TYPE_PPI: ++ { ++ struct bfin_ppi_regs *reg = info->base; ++ bfin_write16(®->control, ppi->ppi_control); ++ break; ++ } ++ case PPI_TYPE_EPPI: ++ { ++ struct bfin_eppi_regs *reg = info->base; ++ bfin_write32(®->control, ppi->ppi_control); ++ break; ++ } ++ default: ++ return -EINVAL; ++ } ++ ++ SSYNC(); ++ return 0; ++} ++ ++static int ppi_stop(struct ppi_if *ppi) ++{ ++ const struct ppi_info *info = ppi->info; ++ ++ /* disable PPI */ ++ ppi->ppi_control &= ~PORT_EN; ++ switch (info->type) { ++ case PPI_TYPE_PPI: ++ { ++ struct bfin_ppi_regs *reg = info->base; ++ bfin_write16(®->control, ppi->ppi_control); ++ break; ++ } ++ case PPI_TYPE_EPPI: ++ { ++ struct bfin_eppi_regs *reg = info->base; ++ bfin_write32(®->control, ppi->ppi_control); ++ break; ++ } ++ default: ++ return -EINVAL; ++ } ++ ++ /* disable DMA */ ++ clear_dma_irqstat(info->dma_ch); ++ disable_dma(info->dma_ch); ++ ++ SSYNC(); ++ return 0; ++} ++ ++static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) ++{ ++ const struct ppi_info *info = ppi->info; ++ int dma32 = 0; ++ int dma_config, bytes_per_line, lines_per_frame; ++ ++ bytes_per_line = params->width * params->bpp / 8; ++ lines_per_frame = params->height; ++ if (params->int_mask == 0xFFFFFFFF) ++ ppi->err_int = false; ++ else ++ ppi->err_int = true; ++ ++ dma_config = (DMA_FLOW_STOP | WNR | RESTART | DMA2D | DI_EN); ++ ppi->ppi_control = params->ppi_control & ~PORT_EN; ++ switch (info->type) { ++ case PPI_TYPE_PPI: ++ { ++ struct bfin_ppi_regs *reg = info->base; ++ ++ if (params->ppi_control & DMA32) ++ dma32 = 1; ++ ++ bfin_write16(®->control, ppi->ppi_control); ++ bfin_write16(®->count, bytes_per_line - 1); ++ bfin_write16(®->frame, lines_per_frame); ++ break; ++ } ++ case PPI_TYPE_EPPI: ++ { ++ struct bfin_eppi_regs *reg = info->base; ++ ++ if ((params->ppi_control & PACK_EN) ++ || (params->ppi_control & 0x38000) > DLEN_16) ++ dma32 = 1; ++ ++ bfin_write32(®->control, ppi->ppi_control); ++ bfin_write16(®->line, bytes_per_line + params->blank_clocks); ++ bfin_write16(®->frame, lines_per_frame); ++ bfin_write16(®->hdelay, 0); ++ bfin_write16(®->vdelay, 0); ++ bfin_write16(®->hcount, bytes_per_line); ++ bfin_write16(®->vcount, lines_per_frame); ++ break; ++ } ++ default: ++ return -EINVAL; ++ } ++ ++ if (dma32) { ++ dma_config |= WDSIZE_32; ++ set_dma_x_count(info->dma_ch, bytes_per_line >> 2); ++ set_dma_x_modify(info->dma_ch, 4); ++ set_dma_y_modify(info->dma_ch, 4); ++ } else { ++ dma_config |= WDSIZE_16; ++ set_dma_x_count(info->dma_ch, bytes_per_line >> 1); ++ set_dma_x_modify(info->dma_ch, 2); ++ set_dma_y_modify(info->dma_ch, 2); ++ } ++ set_dma_y_count(info->dma_ch, lines_per_frame); ++ set_dma_config(info->dma_ch, dma_config); ++ ++ SSYNC(); ++ return 0; ++} ++ ++static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr) ++{ ++ set_dma_start_addr(ppi->info->dma_ch, addr); ++} ++ ++struct ppi_if *ppi_create_instance(const struct ppi_info *info) ++{ ++ struct ppi_if *ppi; ++ ++ if (!info || !info->pin_req) ++ return NULL; ++ ++ if (peripheral_request_list(info->pin_req, KBUILD_MODNAME)) { ++ pr_err("request peripheral failed\n"); ++ return NULL; ++ } ++ ++ ppi = kzalloc(sizeof(*ppi), GFP_KERNEL); ++ if (!ppi) { ++ peripheral_free_list(info->pin_req); ++ pr_err("unable to allocate memory for ppi handle\n"); ++ return NULL; ++ } ++ ppi->ops = &ppi_ops; ++ ppi->info = info; ++ ++ pr_info("ppi probe success\n"); ++ return ppi; ++} ++ ++void ppi_delete_instance(struct ppi_if *ppi) ++{ ++ peripheral_free_list(ppi->info->pin_req); ++ kfree(ppi); ++} +Index: linux-3.3.x86_64/include/media/blackfin/bfin_capture.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/include/media/blackfin/bfin_capture.h +@@ -0,0 +1,37 @@ ++#ifndef _BFIN_CAPTURE_H_ ++#define _BFIN_CAPTURE_H_ ++ ++#include ++ ++struct v4l2_input; ++struct ppi_info; ++ ++struct bcap_route { ++ u32 input; ++ u32 output; ++}; ++ ++struct bfin_capture_config { ++ /* card name */ ++ char *card_name; ++ /* inputs available at the sub device */ ++ struct v4l2_input *inputs; ++ /* number of inputs supported */ ++ int num_inputs; ++ /* routing information for each input */ ++ struct bcap_route *routes; ++ /* i2c bus adapter no */ ++ int i2c_adapter_id; ++ /* i2c subdevice board info */ ++ struct i2c_board_info board_info; ++ /* ppi board info */ ++ const struct ppi_info *ppi_info; ++ /* ppi control */ ++ unsigned long ppi_control; ++ /* ppi interrupt mask */ ++ u32 int_mask; ++ /* horizontal blanking clocks */ ++ int blank_clocks; ++}; ++ ++#endif +Index: linux-3.3.x86_64/include/media/blackfin/ppi.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/include/media/blackfin/ppi.h +@@ -0,0 +1,74 @@ ++/* ++ * Analog Devices PPI header file ++ * ++ * Copyright (c) 2011 Analog Devices Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef _PPI_H_ ++#define _PPI_H_ ++ ++#include ++ ++#ifdef EPPI_EN ++#define PORT_EN EPPI_EN ++#define DMA32 0 ++#define PACK_EN PACKEN ++#endif ++ ++struct ppi_if; ++ ++struct ppi_params { ++ int width; ++ int height; ++ int bpp; ++ unsigned long ppi_control; ++ u32 int_mask; ++ int blank_clocks; ++}; ++ ++struct ppi_ops { ++ int (*attach_irq)(struct ppi_if *ppi, irq_handler_t handler); ++ void (*detach_irq)(struct ppi_if *ppi); ++ int (*start)(struct ppi_if *ppi); ++ int (*stop)(struct ppi_if *ppi); ++ int (*set_params)(struct ppi_if *ppi, struct ppi_params *params); ++ void (*update_addr)(struct ppi_if *ppi, unsigned long addr); ++}; ++ ++enum ppi_type { ++ PPI_TYPE_PPI, ++ PPI_TYPE_EPPI, ++}; ++ ++struct ppi_info { ++ enum ppi_type type; ++ int dma_ch; ++ int irq_err; ++ void __iomem *base; ++ const unsigned short *pin_req; ++}; ++ ++struct ppi_if { ++ unsigned long ppi_control; ++ const struct ppi_ops *ops; ++ const struct ppi_info *info; ++ bool err_int; ++ void *priv; ++}; ++ ++struct ppi_if *ppi_create_instance(const struct ppi_info *info); ++void ppi_delete_instance(struct ppi_if *ppi); ++#endif +Index: linux-3.3.x86_64/Documentation/DocBook/media/v4l/selection-api.xml +=================================================================== +--- linux-3.3.x86_64.orig/Documentation/DocBook/media/v4l/selection-api.xml ++++ linux-3.3.x86_64/Documentation/DocBook/media/v4l/selection-api.xml +@@ -52,6 +52,10 @@ cropping and composing rectangles have t + + + ++ ++For complete list of the available selection targets see table ++ + + +
+@@ -186,7 +190,7 @@ V4L2_SEL_TGT_COMPOSE_ACTIVE + +
+ +- Scaling control. ++ Scaling control + + An application can detect if scaling is performed by comparing the width + and the height of rectangles obtained using V4L2_SEL_TGT_CROP_ACTIVE +@@ -200,7 +204,7 @@ the scaling ratios using these values. + +- Comparison with old cropping API. ++ Comparison with old cropping API + + The selection API was introduced to cope with deficiencies of previous + API , that was designed to control simple capture +Index: linux-3.3.x86_64/Documentation/DocBook/media/v4l/vidioc-g-selection.xml +=================================================================== +--- linux-3.3.x86_64.orig/Documentation/DocBook/media/v4l/vidioc-g-selection.xml ++++ linux-3.3.x86_64/Documentation/DocBook/media/v4l/vidioc-g-selection.xml +@@ -58,43 +58,43 @@ + + The ioctls are used to query and configure selection rectangles. + +- To query the cropping (composing) rectangle set +-&v4l2-selection;::type to the respective buffer type. Do not +-use multiplanar buffers. Use V4L2_BUF_TYPE_VIDEO_CAPTURE ++ To query the cropping (composing) rectangle set &v4l2-selection; ++ type field to the respective buffer type. ++Do not use multiplanar buffers. Use V4L2_BUF_TYPE_VIDEO_CAPTURE + instead of V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE + . Use V4L2_BUF_TYPE_VIDEO_OUTPUT instead of + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE . The next step is +-setting &v4l2-selection;::target to value +- V4L2_SEL_TGT_CROP_ACTIVE ( ++setting the value of &v4l2-selection; target field ++to V4L2_SEL_TGT_CROP_ACTIVE ( + V4L2_SEL_TGT_COMPOSE_ACTIVE ). Please refer to table or for additional +-targets. Fields &v4l2-selection;::flags and +- &v4l2-selection;::reserved are ignored and they +-must be filled with zeros. The driver fills the rest of the structure or ++targets. The flags and reserved ++ fields of &v4l2-selection; are ignored and they must be filled ++with zeros. The driver fills the rest of the structure or + returns &EINVAL; if incorrect buffer type or target was used. If cropping + (composing) is not supported then the active rectangle is not mutable and it is +-always equal to the bounds rectangle. Finally, structure +-&v4l2-selection;::r is filled with the current cropping ++always equal to the bounds rectangle. Finally, the &v4l2-rect; ++r rectangle is filled with the current cropping + (composing) coordinates. The coordinates are expressed in driver-dependent + units. The only exception are rectangles for images in raw formats, whose + coordinates are always expressed in pixels. + +- To change the cropping (composing) rectangle set +-&v4l2-selection;::type to the respective buffer type. Do not ++ To change the cropping (composing) rectangle set the &v4l2-selection; ++type field to the respective buffer type. Do not + use multiplanar buffers. Use V4L2_BUF_TYPE_VIDEO_CAPTURE + instead of V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE + . Use V4L2_BUF_TYPE_VIDEO_OUTPUT instead of + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE . The next step is +-setting &v4l2-selection;::target to value +- V4L2_SEL_TGT_CROP_ACTIVE ( ++setting the value of &v4l2-selection; target to ++V4L2_SEL_TGT_CROP_ACTIVE ( + V4L2_SEL_TGT_COMPOSE_ACTIVE ). Please refer to table or for additional +-targets. Set desired active area into the field +-&v4l2-selection;::r . Field +-&v4l2-selection;::reserved is ignored and must be filled with +-zeros. The driver may adjust the rectangle coordinates. An application may +-introduce constraints to control rounding behaviour. Set the field +- &v4l2-selection;::flags to one of values: ++targets. The &v4l2-rect; r rectangle need to be ++set to the desired active area. Field &v4l2-selection; reserved ++ is ignored and must be filled with zeros. The driver may adjust ++coordinates of the requested rectangle. An application may ++introduce constraints to control rounding behaviour. The &v4l2-selection; ++flags field must be set to one of the following: + + + +@@ -129,7 +129,7 @@ and vertical offset and sizes are chosen + + + +- Satisfy constraints from &v4l2-selection;::flags. ++ Satisfy constraints from &v4l2-selection; flags. + + + Adjust width, height, left, and top to hardware limits and alignments. +@@ -145,7 +145,7 @@ and vertical offset and sizes are chosen + + + +-On success the field &v4l2-selection;::r contains ++On success the &v4l2-rect; r field contains + the adjusted rectangle. When the parameters are unsuitable the application may + modify the cropping (composing) or image parameters and repeat the cycle until + satisfactory parameters have been negotiated. If constraints flags have to be +@@ -162,38 +162,38 @@ exist no rectangle that sati + + + V4L2_SEL_TGT_CROP_ACTIVE +- 0 +- area that is currently cropped by hardware ++ 0x0000 ++ The area that is currently cropped by hardware. + + + V4L2_SEL_TGT_CROP_DEFAULT +- 1 +- suggested cropping rectangle that covers the "whole picture" ++ 0x0001 ++ Suggested cropping rectangle that covers the "whole picture". + + + V4L2_SEL_TGT_CROP_BOUNDS +- 2 +- limits for the cropping rectangle ++ 0x0002 ++ Limits for the cropping rectangle. + + + V4L2_SEL_TGT_COMPOSE_ACTIVE +- 256 +- area to which data are composed by hardware ++ 0x0100 ++ The area to which data is composed by hardware. + + + V4L2_SEL_TGT_COMPOSE_DEFAULT +- 257 +- suggested composing rectangle that covers the "whole picture" ++ 0x0101 ++ Suggested composing rectangle that covers the "whole picture". + + + V4L2_SEL_TGT_COMPOSE_BOUNDS +- 258 +- limits for the composing rectangle ++ 0x0102 ++ Limits for the composing rectangle. + + + V4L2_SEL_TGT_COMPOSE_PADDED +- 259 +- the active area and all padding pixels that are inserted or modified by the hardware ++ 0x0103 ++ The active area and all padding pixels that are inserted or modified by hardware. + + + +@@ -209,12 +209,14 @@ exist no rectangle that sati + + V4L2_SEL_FLAG_GE + 0x00000001 +- indicate that adjusted rectangle must contain a rectangle from &v4l2-selection;::r ++ Indicates that the adjusted rectangle must contain the original ++ &v4l2-selection; r rectangle. + + + V4L2_SEL_FLAG_LE + 0x00000002 +- indicate that adjusted rectangle must be inside a rectangle from &v4l2-selection;::r ++ Indicates that the adjusted rectangle must be inside the original ++ &v4l2-rect; r rectangle. + + + +@@ -245,27 +247,29 @@ exist no rectangle that sati + + __u32 + type +- Type of the buffer (from &v4l2-buf-type;) ++ Type of the buffer (from &v4l2-buf-type;). + + + __u32 + target +- used to select between cropping and composing rectangles ++ Used to select between cropping ++ and composing rectangles. + + + __u32 + flags +- control over coordinates adjustments, refer to selection flags ++ Flags controlling the selection rectangle adjustments, refer to ++ selection flags. + + + &v4l2-rect; + r +- selection rectangle ++ The selection rectangle. + + + __u32 + reserved[9] +- Reserved fields for future use ++ Reserved fields for future use. + + + +@@ -278,24 +282,24 @@ exist no rectangle that sati + + EINVAL + +- The buffer &v4l2-selection;::type +-or &v4l2-selection;::target is not supported, or +-the &v4l2-selection;::flags are invalid. ++ Given buffer type type or ++the selection target target is not supported, ++or the flags argument is not valid. + + + + ERANGE + +- it is not possible to adjust a rectangle +-&v4l2-selection;::r that satisfies all contraints from +- &v4l2-selection;::flags . ++ It is not possible to adjust &v4l2-rect; ++r rectangle to satisfy all contraints given in the ++flags argument. + + + + EBUSY + +- it is not possible to apply change of selection rectangle at the moment. +-Usually because streaming is in progress. ++ It is not possible to apply change of the selection rectangle ++at the moment. Usually because streaming is in progress. + + + +Index: linux-3.3.x86_64/drivers/media/video/w9966.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/w9966.c ++++ linux-3.3.x86_64/drivers/media/video/w9966.c +@@ -129,9 +129,9 @@ MODULE_LICENSE("GPL"); + MODULE_VERSION("0.33.1"); + + #ifdef MODULE +-static const char *pardev[] = {[0 ... W9966_MAXCAMS] = ""}; ++static char *pardev[] = {[0 ... W9966_MAXCAMS] = ""}; + #else +-static const char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"}; ++static char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"}; + #endif + module_param_array(pardev, charp, NULL, 0); + MODULE_PARM_DESC(pardev, "pardev: where to search for\n" +Index: linux-3.3.x86_64/drivers/media/dvb/pt1/pt1.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/pt1/pt1.c ++++ linux-3.3.x86_64/drivers/media/dvb/pt1/pt1.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include "dvbdev.h" + #include "dvb_demux.h" +@@ -77,6 +78,8 @@ struct pt1 { + struct pt1_adapter *adaps[PT1_NR_ADAPS]; + struct pt1_table *tables; + struct task_struct *kthread; ++ int table_index; ++ int buf_index; + + struct mutex lock; + int power; +@@ -90,12 +93,12 @@ struct pt1_adapter { + u8 *buf; + int upacket_count; + int packet_count; ++ int st_count; + + struct dvb_adapter adap; + struct dvb_demux demux; + int users; + struct dmxdev dmxdev; +- struct dvb_net net; + struct dvb_frontend *fe; + int (*orig_set_voltage)(struct dvb_frontend *fe, + fe_sec_voltage_t voltage); +@@ -119,7 +122,7 @@ static u32 pt1_read_reg(struct pt1 *pt1, + return readl(pt1->regs + reg * 4); + } + +-static int pt1_nr_tables = 64; ++static int pt1_nr_tables = 8; + module_param_named(nr_tables, pt1_nr_tables, int, 0); + + static void pt1_increment_table_count(struct pt1 *pt1) +@@ -264,6 +267,7 @@ static int pt1_filter(struct pt1 *pt1, s + struct pt1_adapter *adap; + int offset; + u8 *buf; ++ int sc; + + if (!page->upackets[PT1_NR_UPACKETS - 1]) + return 0; +@@ -280,6 +284,16 @@ static int pt1_filter(struct pt1 *pt1, s + else if (!adap->upacket_count) + continue; + ++ if (upacket >> 24 & 1) ++ printk_ratelimited(KERN_INFO "earth-pt1: device " ++ "buffer overflowing. table[%d] buf[%d]\n", ++ pt1->table_index, pt1->buf_index); ++ sc = upacket >> 26 & 0x7; ++ if (adap->st_count != -1 && sc != ((adap->st_count + 1) & 0x7)) ++ printk_ratelimited(KERN_INFO "earth-pt1: data loss" ++ " in streamID(adapter)[%d]\n", index); ++ adap->st_count = sc; ++ + buf = adap->buf; + offset = adap->packet_count * 188 + adap->upacket_count * 3; + buf[offset] = upacket >> 16; +@@ -303,30 +317,25 @@ static int pt1_filter(struct pt1 *pt1, s + static int pt1_thread(void *data) + { + struct pt1 *pt1; +- int table_index; +- int buf_index; + struct pt1_buffer_page *page; + + pt1 = data; + set_freezable(); + +- table_index = 0; +- buf_index = 0; +- + while (!kthread_should_stop()) { + try_to_freeze(); + +- page = pt1->tables[table_index].bufs[buf_index].page; ++ page = pt1->tables[pt1->table_index].bufs[pt1->buf_index].page; + if (!pt1_filter(pt1, page)) { + schedule_timeout_interruptible((HZ + 999) / 1000); + continue; + } + +- if (++buf_index >= PT1_NR_BUFS) { ++ if (++pt1->buf_index >= PT1_NR_BUFS) { + pt1_increment_table_count(pt1); +- buf_index = 0; +- if (++table_index >= pt1_nr_tables) +- table_index = 0; ++ pt1->buf_index = 0; ++ if (++pt1->table_index >= pt1_nr_tables) ++ pt1->table_index = 0; + } + } + +@@ -477,21 +486,60 @@ err: + return ret; + } + ++static int pt1_start_polling(struct pt1 *pt1) ++{ ++ int ret = 0; ++ ++ mutex_lock(&pt1->lock); ++ if (!pt1->kthread) { ++ pt1->kthread = kthread_run(pt1_thread, pt1, "earth-pt1"); ++ if (IS_ERR(pt1->kthread)) { ++ ret = PTR_ERR(pt1->kthread); ++ pt1->kthread = NULL; ++ } ++ } ++ mutex_unlock(&pt1->lock); ++ return ret; ++} ++ + static int pt1_start_feed(struct dvb_demux_feed *feed) + { + struct pt1_adapter *adap; + adap = container_of(feed->demux, struct pt1_adapter, demux); +- if (!adap->users++) ++ if (!adap->users++) { ++ int ret; ++ ++ ret = pt1_start_polling(adap->pt1); ++ if (ret) ++ return ret; + pt1_set_stream(adap->pt1, adap->index, 1); ++ } + return 0; + } + ++static void pt1_stop_polling(struct pt1 *pt1) ++{ ++ int i, count; ++ ++ mutex_lock(&pt1->lock); ++ for (i = 0, count = 0; i < PT1_NR_ADAPS; i++) ++ count += pt1->adaps[i]->users; ++ ++ if (count == 0 && pt1->kthread) { ++ kthread_stop(pt1->kthread); ++ pt1->kthread = NULL; ++ } ++ mutex_unlock(&pt1->lock); ++} ++ + static int pt1_stop_feed(struct dvb_demux_feed *feed) + { + struct pt1_adapter *adap; + adap = container_of(feed->demux, struct pt1_adapter, demux); +- if (!--adap->users) ++ if (!--adap->users) { + pt1_set_stream(adap->pt1, adap->index, 0); ++ pt1_stop_polling(adap->pt1); ++ } + return 0; + } + +@@ -575,7 +623,6 @@ static int pt1_wakeup(struct dvb_fronten + + static void pt1_free_adapter(struct pt1_adapter *adap) + { +- dvb_net_release(&adap->net); + adap->demux.dmx.close(&adap->demux.dmx); + dvb_dmxdev_release(&adap->dmxdev); + dvb_dmx_release(&adap->demux); +@@ -616,6 +663,7 @@ pt1_alloc_adapter(struct pt1 *pt1) + adap->buf = buf; + adap->upacket_count = 0; + adap->packet_count = 0; ++ adap->st_count = -1; + + dvb_adap = &adap->adap; + dvb_adap->priv = adap; +@@ -644,8 +692,6 @@ pt1_alloc_adapter(struct pt1 *pt1) + if (ret < 0) + goto err_dmx_release; + +- dvb_net_init(dvb_adap, &adap->net, &demux->dmx); +- + return adap; + + err_dmx_release: +@@ -1020,7 +1066,8 @@ static void __devexit pt1_remove(struct + pt1 = pci_get_drvdata(pdev); + regs = pt1->regs; + +- kthread_stop(pt1->kthread); ++ if (pt1->kthread) ++ kthread_stop(pt1->kthread); + pt1_cleanup_tables(pt1); + pt1_cleanup_frontends(pt1); + pt1_disable_ram(pt1); +@@ -1043,7 +1090,6 @@ pt1_probe(struct pci_dev *pdev, const st + void __iomem *regs; + struct pt1 *pt1; + struct i2c_adapter *i2c_adap; +- struct task_struct *kthread; + + ret = pci_enable_device(pdev); + if (ret < 0) +@@ -1139,17 +1185,8 @@ pt1_probe(struct pci_dev *pdev, const st + if (ret < 0) + goto err_pt1_cleanup_frontends; + +- kthread = kthread_run(pt1_thread, pt1, "pt1"); +- if (IS_ERR(kthread)) { +- ret = PTR_ERR(kthread); +- goto err_pt1_cleanup_tables; +- } +- +- pt1->kthread = kthread; + return 0; + +-err_pt1_cleanup_tables: +- pt1_cleanup_tables(pt1); + err_pt1_cleanup_frontends: + pt1_cleanup_frontends(pt1); + err_pt1_disable_ram: +Index: linux-3.3.x86_64/drivers/media/video/aptina-pll.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/aptina-pll.c +@@ -0,0 +1,174 @@ ++/* ++ * Aptina Sensor PLL Configuration ++ * ++ * Copyright (C) 2012 Laurent Pinchart ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "aptina-pll.h" ++ ++int aptina_pll_calculate(struct device *dev, ++ const struct aptina_pll_limits *limits, ++ struct aptina_pll *pll) ++{ ++ unsigned int mf_min; ++ unsigned int mf_max; ++ unsigned int p1_min; ++ unsigned int p1_max; ++ unsigned int p1; ++ unsigned int div; ++ ++ dev_dbg(dev, "PLL: ext clock %u pix clock %u\n", ++ pll->ext_clock, pll->pix_clock); ++ ++ if (pll->ext_clock < limits->ext_clock_min || ++ pll->ext_clock > limits->ext_clock_max) { ++ dev_err(dev, "pll: invalid external clock frequency.\n"); ++ return -EINVAL; ++ } ++ ++ if (pll->pix_clock == 0 || pll->pix_clock > limits->pix_clock_max) { ++ dev_err(dev, "pll: invalid pixel clock frequency.\n"); ++ return -EINVAL; ++ } ++ ++ /* Compute the multiplier M and combined N*P1 divisor. */ ++ div = gcd(pll->pix_clock, pll->ext_clock); ++ pll->m = pll->pix_clock / div; ++ div = pll->ext_clock / div; ++ ++ /* We now have the smallest M and N*P1 values that will result in the ++ * desired pixel clock frequency, but they might be out of the valid ++ * range. Compute the factor by which we should multiply them given the ++ * following constraints: ++ * ++ * - minimum/maximum multiplier ++ * - minimum/maximum multiplier output clock frequency assuming the ++ * minimum/maximum N value ++ * - minimum/maximum combined N*P1 divisor ++ */ ++ mf_min = DIV_ROUND_UP(limits->m_min, pll->m); ++ mf_min = max(mf_min, limits->out_clock_min / ++ (pll->ext_clock / limits->n_min * pll->m)); ++ mf_min = max(mf_min, limits->n_min * limits->p1_min / div); ++ mf_max = limits->m_max / pll->m; ++ mf_max = min(mf_max, limits->out_clock_max / ++ (pll->ext_clock / limits->n_max * pll->m)); ++ mf_max = min(mf_max, DIV_ROUND_UP(limits->n_max * limits->p1_max, div)); ++ ++ dev_dbg(dev, "pll: mf min %u max %u\n", mf_min, mf_max); ++ if (mf_min > mf_max) { ++ dev_err(dev, "pll: no valid combined N*P1 divisor.\n"); ++ return -EINVAL; ++ } ++ ++ /* ++ * We're looking for the highest acceptable P1 value for which a ++ * multiplier factor MF exists that fulfills the following conditions: ++ * ++ * 1. p1 is in the [p1_min, p1_max] range given by the limits and is ++ * even ++ * 2. mf is in the [mf_min, mf_max] range computed above ++ * 3. div * mf is a multiple of p1, in order to compute ++ * n = div * mf / p1 ++ * m = pll->m * mf ++ * 4. the internal clock frequency, given by ext_clock / n, is in the ++ * [int_clock_min, int_clock_max] range given by the limits ++ * 5. the output clock frequency, given by ext_clock / n * m, is in the ++ * [out_clock_min, out_clock_max] range given by the limits ++ * ++ * The first naive approach is to iterate over all p1 values acceptable ++ * according to (1) and all mf values acceptable according to (2), and ++ * stop at the first combination that fulfills (3), (4) and (5). This ++ * has a O(n^2) complexity. ++ * ++ * Instead of iterating over all mf values in the [mf_min, mf_max] range ++ * we can compute the mf increment between two acceptable values ++ * according to (3) with ++ * ++ * mf_inc = p1 / gcd(div, p1) (6) ++ * ++ * and round the minimum up to the nearest multiple of mf_inc. This will ++ * restrict the number of mf values to be checked. ++ * ++ * Furthermore, conditions (4) and (5) only restrict the range of ++ * acceptable p1 and mf values by modifying the minimum and maximum ++ * limits. (5) can be expressed as ++ * ++ * ext_clock / (div * mf / p1) * m * mf >= out_clock_min ++ * ext_clock / (div * mf / p1) * m * mf <= out_clock_max ++ * ++ * or ++ * ++ * p1 >= out_clock_min * div / (ext_clock * m) (7) ++ * p1 <= out_clock_max * div / (ext_clock * m) ++ * ++ * Similarly, (4) can be expressed as ++ * ++ * mf >= ext_clock * p1 / (int_clock_max * div) (8) ++ * mf <= ext_clock * p1 / (int_clock_min * div) ++ * ++ * We can thus iterate over the restricted p1 range defined by the ++ * combination of (1) and (7), and then compute the restricted mf range ++ * defined by the combination of (2), (6) and (8). If the resulting mf ++ * range is not empty, any value in the mf range is acceptable. We thus ++ * select the mf lwoer bound and the corresponding p1 value. ++ */ ++ if (limits->p1_min == 0) { ++ dev_err(dev, "pll: P1 minimum value must be >0.\n"); ++ return -EINVAL; ++ } ++ ++ p1_min = max(limits->p1_min, DIV_ROUND_UP(limits->out_clock_min * div, ++ pll->ext_clock * pll->m)); ++ p1_max = min(limits->p1_max, limits->out_clock_max * div / ++ (pll->ext_clock * pll->m)); ++ ++ for (p1 = p1_max & ~1; p1 >= p1_min; p1 -= 2) { ++ unsigned int mf_inc = p1 / gcd(div, p1); ++ unsigned int mf_high; ++ unsigned int mf_low; ++ ++ mf_low = max(roundup(mf_min, mf_inc), ++ DIV_ROUND_UP(pll->ext_clock * p1, ++ limits->int_clock_max * div)); ++ mf_high = min(mf_max, pll->ext_clock * p1 / ++ (limits->int_clock_min * div)); ++ ++ if (mf_low > mf_high) ++ continue; ++ ++ pll->n = div * mf_low / p1; ++ pll->m *= mf_low; ++ pll->p1 = p1; ++ dev_dbg(dev, "PLL: N %u M %u P1 %u\n", pll->n, pll->m, pll->p1); ++ return 0; ++ } ++ ++ dev_err(dev, "pll: no valid N and P1 divisors found.\n"); ++ return -EINVAL; ++} ++EXPORT_SYMBOL_GPL(aptina_pll_calculate); ++ ++MODULE_DESCRIPTION("Aptina PLL Helpers"); ++MODULE_AUTHOR("Laurent Pinchart "); ++MODULE_LICENSE("GPL v2"); +Index: linux-3.3.x86_64/drivers/media/video/aptina-pll.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/aptina-pll.h +@@ -0,0 +1,56 @@ ++/* ++ * Aptina Sensor PLL Configuration ++ * ++ * Copyright (C) 2012 Laurent Pinchart ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#ifndef __APTINA_PLL_H ++#define __APTINA_PLL_H ++ ++struct aptina_pll { ++ unsigned int ext_clock; ++ unsigned int pix_clock; ++ ++ unsigned int n; ++ unsigned int m; ++ unsigned int p1; ++}; ++ ++struct aptina_pll_limits { ++ unsigned int ext_clock_min; ++ unsigned int ext_clock_max; ++ unsigned int int_clock_min; ++ unsigned int int_clock_max; ++ unsigned int out_clock_min; ++ unsigned int out_clock_max; ++ unsigned int pix_clock_max; ++ ++ unsigned int n_min; ++ unsigned int n_max; ++ unsigned int m_min; ++ unsigned int m_max; ++ unsigned int p1_min; ++ unsigned int p1_max; ++}; ++ ++struct device; ++ ++int aptina_pll_calculate(struct device *dev, ++ const struct aptina_pll_limits *limits, ++ struct aptina_pll *pll); ++ ++#endif /* __APTINA_PLL_H */ +Index: linux-3.3.x86_64/drivers/media/video/mt9m032.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/video/mt9m032.c +@@ -0,0 +1,868 @@ ++/* ++ * Driver for MT9M032 CMOS Image Sensor from Micron ++ * ++ * Copyright (C) 2010-2011 Lund Engineering ++ * Contact: Gil Lund ++ * Author: Martin Hostettler ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "aptina-pll.h" ++ ++/* ++ * width and height include active boundary and black parts ++ * ++ * column 0- 15 active boundary ++ * column 16-1455 image ++ * column 1456-1471 active boundary ++ * column 1472-1599 black ++ * ++ * row 0- 51 black ++ * row 53- 59 active boundary ++ * row 60-1139 image ++ * row 1140-1147 active boundary ++ * row 1148-1151 black ++ */ ++ ++#define MT9M032_PIXEL_ARRAY_WIDTH 1600 ++#define MT9M032_PIXEL_ARRAY_HEIGHT 1152 ++ ++#define MT9M032_CHIP_VERSION 0x00 ++#define MT9M032_CHIP_VERSION_VALUE 0x1402 ++#define MT9M032_ROW_START 0x01 ++#define MT9M032_ROW_START_MIN 0 ++#define MT9M032_ROW_START_MAX 1152 ++#define MT9M032_ROW_START_DEF 60 ++#define MT9M032_COLUMN_START 0x02 ++#define MT9M032_COLUMN_START_MIN 0 ++#define MT9M032_COLUMN_START_MAX 1600 ++#define MT9M032_COLUMN_START_DEF 16 ++#define MT9M032_ROW_SIZE 0x03 ++#define MT9M032_ROW_SIZE_MIN 32 ++#define MT9M032_ROW_SIZE_MAX 1152 ++#define MT9M032_ROW_SIZE_DEF 1080 ++#define MT9M032_COLUMN_SIZE 0x04 ++#define MT9M032_COLUMN_SIZE_MIN 32 ++#define MT9M032_COLUMN_SIZE_MAX 1600 ++#define MT9M032_COLUMN_SIZE_DEF 1440 ++#define MT9M032_HBLANK 0x05 ++#define MT9M032_VBLANK 0x06 ++#define MT9M032_VBLANK_MAX 0x7ff ++#define MT9M032_SHUTTER_WIDTH_HIGH 0x08 ++#define MT9M032_SHUTTER_WIDTH_LOW 0x09 ++#define MT9M032_SHUTTER_WIDTH_MIN 1 ++#define MT9M032_SHUTTER_WIDTH_MAX 1048575 ++#define MT9M032_SHUTTER_WIDTH_DEF 1943 ++#define MT9M032_PIX_CLK_CTRL 0x0a ++#define MT9M032_PIX_CLK_CTRL_INV_PIXCLK 0x8000 ++#define MT9M032_RESTART 0x0b ++#define MT9M032_RESET 0x0d ++#define MT9M032_PLL_CONFIG1 0x11 ++#define MT9M032_PLL_CONFIG1_OUTDIV_MASK 0x3f ++#define MT9M032_PLL_CONFIG1_MUL_SHIFT 8 ++#define MT9M032_READ_MODE1 0x1e ++#define MT9M032_READ_MODE2 0x20 ++#define MT9M032_READ_MODE2_VFLIP_SHIFT 15 ++#define MT9M032_READ_MODE2_HFLIP_SHIFT 14 ++#define MT9M032_READ_MODE2_ROW_BLC 0x40 ++#define MT9M032_GAIN_GREEN1 0x2b ++#define MT9M032_GAIN_BLUE 0x2c ++#define MT9M032_GAIN_RED 0x2d ++#define MT9M032_GAIN_GREEN2 0x2e ++ ++/* write only */ ++#define MT9M032_GAIN_ALL 0x35 ++#define MT9M032_GAIN_DIGITAL_MASK 0x7f ++#define MT9M032_GAIN_DIGITAL_SHIFT 8 ++#define MT9M032_GAIN_AMUL_SHIFT 6 ++#define MT9M032_GAIN_ANALOG_MASK 0x3f ++#define MT9M032_FORMATTER1 0x9e ++#define MT9M032_FORMATTER2 0x9f ++#define MT9M032_FORMATTER2_DOUT_EN 0x1000 ++#define MT9M032_FORMATTER2_PIXCLK_EN 0x2000 ++ ++/* ++ * The available MT9M032 datasheet is missing documentation for register 0x10 ++ * MT9P031 seems to be close enough, so use constants from that datasheet for ++ * now. ++ * But keep the name MT9P031 to remind us, that this isn't really confirmed ++ * for this sensor. ++ */ ++#define MT9P031_PLL_CONTROL 0x10 ++#define MT9P031_PLL_CONTROL_PWROFF 0x0050 ++#define MT9P031_PLL_CONTROL_PWRON 0x0051 ++#define MT9P031_PLL_CONTROL_USEPLL 0x0052 ++#define MT9P031_PLL_CONFIG2 0x11 ++#define MT9P031_PLL_CONFIG2_P1_DIV_MASK 0x1f ++ ++struct mt9m032 { ++ struct v4l2_subdev subdev; ++ struct media_pad pad; ++ struct mt9m032_platform_data *pdata; ++ ++ unsigned int pix_clock; ++ ++ struct v4l2_ctrl_handler ctrls; ++ struct { ++ struct v4l2_ctrl *hflip; ++ struct v4l2_ctrl *vflip; ++ }; ++ ++ struct mutex lock; /* Protects streaming, format, interval and crop */ ++ ++ bool streaming; ++ ++ struct v4l2_mbus_framefmt format; ++ struct v4l2_rect crop; ++ struct v4l2_fract frame_interval; ++}; ++ ++#define to_mt9m032(sd) container_of(sd, struct mt9m032, subdev) ++#define to_dev(sensor) \ ++ (&((struct i2c_client *)v4l2_get_subdevdata(&(sensor)->subdev))->dev) ++ ++static int mt9m032_read(struct i2c_client *client, u8 reg) ++{ ++ return i2c_smbus_read_word_swapped(client, reg); ++} ++ ++static int mt9m032_write(struct i2c_client *client, u8 reg, const u16 data) ++{ ++ return i2c_smbus_write_word_swapped(client, reg, data); ++} ++ ++static u32 mt9m032_row_time(struct mt9m032 *sensor, unsigned int width) ++{ ++ unsigned int effective_width; ++ u32 ns; ++ ++ effective_width = width + 716; /* empirical value */ ++ ns = div_u64(1000000000ULL * effective_width, sensor->pix_clock); ++ dev_dbg(to_dev(sensor), "MT9M032 line time: %u ns\n", ns); ++ return ns; ++} ++ ++static int mt9m032_update_timing(struct mt9m032 *sensor, ++ struct v4l2_fract *interval) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ struct v4l2_rect *crop = &sensor->crop; ++ unsigned int min_vblank; ++ unsigned int vblank; ++ u32 row_time; ++ ++ if (!interval) ++ interval = &sensor->frame_interval; ++ ++ row_time = mt9m032_row_time(sensor, crop->width); ++ ++ vblank = div_u64(1000000000ULL * interval->numerator, ++ (u64)row_time * interval->denominator) ++ - crop->height; ++ ++ if (vblank > MT9M032_VBLANK_MAX) { ++ /* hardware limits to 11 bit values */ ++ interval->denominator = 1000; ++ interval->numerator = ++ div_u64((crop->height + MT9M032_VBLANK_MAX) * ++ (u64)row_time * interval->denominator, ++ 1000000000ULL); ++ vblank = div_u64(1000000000ULL * interval->numerator, ++ (u64)row_time * interval->denominator) ++ - crop->height; ++ } ++ /* enforce minimal 1.6ms blanking time. */ ++ min_vblank = 1600000 / row_time; ++ vblank = clamp_t(unsigned int, vblank, min_vblank, MT9M032_VBLANK_MAX); ++ ++ return mt9m032_write(client, MT9M032_VBLANK, vblank); ++} ++ ++static int mt9m032_update_geom_timing(struct mt9m032 *sensor) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ int ret; ++ ++ ret = mt9m032_write(client, MT9M032_COLUMN_SIZE, ++ sensor->crop.width - 1); ++ if (!ret) ++ ret = mt9m032_write(client, MT9M032_ROW_SIZE, ++ sensor->crop.height - 1); ++ if (!ret) ++ ret = mt9m032_write(client, MT9M032_COLUMN_START, ++ sensor->crop.left); ++ if (!ret) ++ ret = mt9m032_write(client, MT9M032_ROW_START, ++ sensor->crop.top); ++ if (!ret) ++ ret = mt9m032_update_timing(sensor, NULL); ++ return ret; ++} ++ ++static int update_formatter2(struct mt9m032 *sensor, bool streaming) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ u16 reg_val = MT9M032_FORMATTER2_DOUT_EN ++ | 0x0070; /* parts reserved! */ ++ /* possibly for changing to 14-bit mode */ ++ ++ if (streaming) ++ reg_val |= MT9M032_FORMATTER2_PIXCLK_EN; /* pixclock enable */ ++ ++ return mt9m032_write(client, MT9M032_FORMATTER2, reg_val); ++} ++ ++static int mt9m032_setup_pll(struct mt9m032 *sensor) ++{ ++ static const struct aptina_pll_limits limits = { ++ .ext_clock_min = 8000000, ++ .ext_clock_max = 16500000, ++ .int_clock_min = 2000000, ++ .int_clock_max = 24000000, ++ .out_clock_min = 322000000, ++ .out_clock_max = 693000000, ++ .pix_clock_max = 99000000, ++ .n_min = 1, ++ .n_max = 64, ++ .m_min = 16, ++ .m_max = 255, ++ .p1_min = 1, ++ .p1_max = 128, ++ }; ++ ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ struct mt9m032_platform_data *pdata = sensor->pdata; ++ struct aptina_pll pll; ++ int ret; ++ ++ pll.ext_clock = pdata->ext_clock; ++ pll.pix_clock = pdata->pix_clock; ++ ++ ret = aptina_pll_calculate(&client->dev, &limits, &pll); ++ if (ret < 0) ++ return ret; ++ ++ sensor->pix_clock = pdata->pix_clock; ++ ++ ret = mt9m032_write(client, MT9M032_PLL_CONFIG1, ++ (pll.m << MT9M032_PLL_CONFIG1_MUL_SHIFT) ++ | (pll.p1 - 1)); ++ if (!ret) ++ ret = mt9m032_write(client, MT9P031_PLL_CONFIG2, pll.n - 1); ++ if (!ret) ++ ret = mt9m032_write(client, MT9P031_PLL_CONTROL, ++ MT9P031_PLL_CONTROL_PWRON | ++ MT9P031_PLL_CONTROL_USEPLL); ++ if (!ret) /* more reserved, Continuous, Master Mode */ ++ ret = mt9m032_write(client, MT9M032_READ_MODE1, 0x8006); ++ if (!ret) /* Set 14-bit mode, select 7 divider */ ++ ret = mt9m032_write(client, MT9M032_FORMATTER1, 0x111e); ++ ++ return ret; ++} ++ ++/* ----------------------------------------------------------------------------- ++ * Subdev pad operations ++ */ ++ ++static int mt9m032_enum_mbus_code(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_fh *fh, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->index != 0) ++ return -EINVAL; ++ ++ code->code = V4L2_MBUS_FMT_Y8_1X8; ++ return 0; ++} ++ ++static int mt9m032_enum_frame_size(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_fh *fh, ++ struct v4l2_subdev_frame_size_enum *fse) ++{ ++ if (fse->index != 0 || fse->code != V4L2_MBUS_FMT_Y8_1X8) ++ return -EINVAL; ++ ++ fse->min_width = MT9M032_COLUMN_SIZE_DEF; ++ fse->max_width = MT9M032_COLUMN_SIZE_DEF; ++ fse->min_height = MT9M032_ROW_SIZE_DEF; ++ fse->max_height = MT9M032_ROW_SIZE_DEF; ++ ++ return 0; ++} ++ ++/** ++ * __mt9m032_get_pad_crop() - get crop rect ++ * @sensor: pointer to the sensor struct ++ * @fh: file handle for getting the try crop rect from ++ * @which: select try or active crop rect ++ * ++ * Returns a pointer the current active or fh relative try crop rect ++ */ ++static struct v4l2_rect * ++__mt9m032_get_pad_crop(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh, ++ enum v4l2_subdev_format_whence which) ++{ ++ switch (which) { ++ case V4L2_SUBDEV_FORMAT_TRY: ++ return v4l2_subdev_get_try_crop(fh, 0); ++ case V4L2_SUBDEV_FORMAT_ACTIVE: ++ return &sensor->crop; ++ default: ++ return NULL; ++ } ++} ++ ++/** ++ * __mt9m032_get_pad_format() - get format ++ * @sensor: pointer to the sensor struct ++ * @fh: file handle for getting the try format from ++ * @which: select try or active format ++ * ++ * Returns a pointer the current active or fh relative try format ++ */ ++static struct v4l2_mbus_framefmt * ++__mt9m032_get_pad_format(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh, ++ enum v4l2_subdev_format_whence which) ++{ ++ switch (which) { ++ case V4L2_SUBDEV_FORMAT_TRY: ++ return v4l2_subdev_get_try_format(fh, 0); ++ case V4L2_SUBDEV_FORMAT_ACTIVE: ++ return &sensor->format; ++ default: ++ return NULL; ++ } ++} ++ ++static int mt9m032_get_pad_format(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_fh *fh, ++ struct v4l2_subdev_format *fmt) ++{ ++ struct mt9m032 *sensor = to_mt9m032(subdev); ++ ++ mutex_lock(&sensor->lock); ++ fmt->format = *__mt9m032_get_pad_format(sensor, fh, fmt->which); ++ mutex_unlock(&sensor->lock); ++ ++ return 0; ++} ++ ++static int mt9m032_set_pad_format(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_fh *fh, ++ struct v4l2_subdev_format *fmt) ++{ ++ struct mt9m032 *sensor = to_mt9m032(subdev); ++ int ret; ++ ++ mutex_lock(&sensor->lock); ++ ++ if (sensor->streaming && fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { ++ ret = -EBUSY; ++ goto done; ++ } ++ ++ /* Scaling is not supported, the format is thus fixed. */ ++ ret = mt9m032_get_pad_format(subdev, fh, fmt); ++ ++done: ++ mutex_lock(&sensor->lock); ++ return ret; ++} ++ ++static int mt9m032_get_pad_crop(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_fh *fh, ++ struct v4l2_subdev_crop *crop) ++{ ++ struct mt9m032 *sensor = to_mt9m032(subdev); ++ ++ mutex_lock(&sensor->lock); ++ crop->rect = *__mt9m032_get_pad_crop(sensor, fh, crop->which); ++ mutex_unlock(&sensor->lock); ++ ++ return 0; ++} ++ ++static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_fh *fh, ++ struct v4l2_subdev_crop *crop) ++{ ++ struct mt9m032 *sensor = to_mt9m032(subdev); ++ struct v4l2_mbus_framefmt *format; ++ struct v4l2_rect *__crop; ++ struct v4l2_rect rect; ++ int ret = 0; ++ ++ mutex_lock(&sensor->lock); ++ ++ if (sensor->streaming && crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) { ++ ret = -EBUSY; ++ goto done; ++ } ++ ++ /* Clamp the crop rectangle boundaries and align them to a multiple of 2 ++ * pixels to ensure a GRBG Bayer pattern. ++ */ ++ rect.left = clamp(ALIGN(crop->rect.left, 2), MT9M032_COLUMN_START_MIN, ++ MT9M032_COLUMN_START_MAX); ++ rect.top = clamp(ALIGN(crop->rect.top, 2), MT9M032_ROW_START_MIN, ++ MT9M032_ROW_START_MAX); ++ rect.width = clamp(ALIGN(crop->rect.width, 2), MT9M032_COLUMN_SIZE_MIN, ++ MT9M032_COLUMN_SIZE_MAX); ++ rect.height = clamp(ALIGN(crop->rect.height, 2), MT9M032_ROW_SIZE_MIN, ++ MT9M032_ROW_SIZE_MAX); ++ ++ rect.width = min(rect.width, MT9M032_PIXEL_ARRAY_WIDTH - rect.left); ++ rect.height = min(rect.height, MT9M032_PIXEL_ARRAY_HEIGHT - rect.top); ++ ++ __crop = __mt9m032_get_pad_crop(sensor, fh, crop->which); ++ ++ if (rect.width != __crop->width || rect.height != __crop->height) { ++ /* Reset the output image size if the crop rectangle size has ++ * been modified. ++ */ ++ format = __mt9m032_get_pad_format(sensor, fh, crop->which); ++ format->width = rect.width; ++ format->height = rect.height; ++ } ++ ++ *__crop = rect; ++ crop->rect = rect; ++ ++ if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) ++ ret = mt9m032_update_geom_timing(sensor); ++ ++done: ++ mutex_unlock(&sensor->lock); ++ return ret; ++} ++ ++static int mt9m032_get_frame_interval(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_frame_interval *fi) ++{ ++ struct mt9m032 *sensor = to_mt9m032(subdev); ++ ++ mutex_lock(&sensor->lock); ++ memset(fi, 0, sizeof(*fi)); ++ fi->interval = sensor->frame_interval; ++ mutex_unlock(&sensor->lock); ++ ++ return 0; ++} ++ ++static int mt9m032_set_frame_interval(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_frame_interval *fi) ++{ ++ struct mt9m032 *sensor = to_mt9m032(subdev); ++ int ret; ++ ++ mutex_lock(&sensor->lock); ++ ++ if (sensor->streaming) { ++ ret = -EBUSY; ++ goto done; ++ } ++ ++ /* Avoid divisions by 0. */ ++ if (fi->interval.denominator == 0) ++ fi->interval.denominator = 1; ++ ++ ret = mt9m032_update_timing(sensor, &fi->interval); ++ if (!ret) ++ sensor->frame_interval = fi->interval; ++ ++done: ++ mutex_unlock(&sensor->lock); ++ return ret; ++} ++ ++static int mt9m032_s_stream(struct v4l2_subdev *subdev, int streaming) ++{ ++ struct mt9m032 *sensor = to_mt9m032(subdev); ++ int ret; ++ ++ mutex_lock(&sensor->lock); ++ ret = update_formatter2(sensor, streaming); ++ if (!ret) ++ sensor->streaming = streaming; ++ mutex_unlock(&sensor->lock); ++ ++ return ret; ++} ++ ++/* ----------------------------------------------------------------------------- ++ * V4L2 subdev core operations ++ */ ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int mt9m032_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct mt9m032 *sensor = to_mt9m032(sd); ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ int val; ++ ++ if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) ++ return -EINVAL; ++ if (reg->match.addr != client->addr) ++ return -ENODEV; ++ ++ val = mt9m032_read(client, reg->reg); ++ if (val < 0) ++ return -EIO; ++ ++ reg->size = 2; ++ reg->val = val; ++ ++ return 0; ++} ++ ++static int mt9m032_s_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct mt9m032 *sensor = to_mt9m032(sd); ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ ++ if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) ++ return -EINVAL; ++ ++ if (reg->match.addr != client->addr) ++ return -ENODEV; ++ ++ return mt9m032_write(client, reg->reg, reg->val); ++} ++#endif ++ ++/* ----------------------------------------------------------------------------- ++ * V4L2 subdev control operations ++ */ ++ ++static int update_read_mode2(struct mt9m032 *sensor, bool vflip, bool hflip) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ int reg_val = (vflip << MT9M032_READ_MODE2_VFLIP_SHIFT) ++ | (hflip << MT9M032_READ_MODE2_HFLIP_SHIFT) ++ | MT9M032_READ_MODE2_ROW_BLC ++ | 0x0007; ++ ++ return mt9m032_write(client, MT9M032_READ_MODE2, reg_val); ++} ++ ++static int mt9m032_set_gain(struct mt9m032 *sensor, s32 val) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ int digital_gain_val; /* in 1/8th (0..127) */ ++ int analog_mul; /* 0 or 1 */ ++ int analog_gain_val; /* in 1/16th. (0..63) */ ++ u16 reg_val; ++ ++ digital_gain_val = 51; /* from setup example */ ++ ++ if (val < 63) { ++ analog_mul = 0; ++ analog_gain_val = val; ++ } else { ++ analog_mul = 1; ++ analog_gain_val = val / 2; ++ } ++ ++ /* a_gain = (1 + analog_mul) + (analog_gain_val + 1) / 16 */ ++ /* overall_gain = a_gain * (1 + digital_gain_val / 8) */ ++ ++ reg_val = ((digital_gain_val & MT9M032_GAIN_DIGITAL_MASK) ++ << MT9M032_GAIN_DIGITAL_SHIFT) ++ | ((analog_mul & 1) << MT9M032_GAIN_AMUL_SHIFT) ++ | (analog_gain_val & MT9M032_GAIN_ANALOG_MASK); ++ ++ return mt9m032_write(client, MT9M032_GAIN_ALL, reg_val); ++} ++ ++static int mt9m032_try_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ if (ctrl->id == V4L2_CID_GAIN && ctrl->val >= 63) { ++ /* round because of multiplier used for values >= 63 */ ++ ctrl->val &= ~1; ++ } ++ ++ return 0; ++} ++ ++static int mt9m032_set_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct mt9m032 *sensor = ++ container_of(ctrl->handler, struct mt9m032, ctrls); ++ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); ++ int ret; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_GAIN: ++ return mt9m032_set_gain(sensor, ctrl->val); ++ ++ case V4L2_CID_HFLIP: ++ /* case V4L2_CID_VFLIP: -- In the same cluster */ ++ return update_read_mode2(sensor, sensor->vflip->val, ++ sensor->hflip->val); ++ ++ case V4L2_CID_EXPOSURE: ++ ret = mt9m032_write(client, MT9M032_SHUTTER_WIDTH_HIGH, ++ (ctrl->val >> 16) & 0xffff); ++ if (ret < 0) ++ return ret; ++ ++ return mt9m032_write(client, MT9M032_SHUTTER_WIDTH_LOW, ++ ctrl->val & 0xffff); ++ } ++ ++ return 0; ++} ++ ++static struct v4l2_ctrl_ops mt9m032_ctrl_ops = { ++ .s_ctrl = mt9m032_set_ctrl, ++ .try_ctrl = mt9m032_try_ctrl, ++}; ++ ++/* -------------------------------------------------------------------------- */ ++ ++static const struct v4l2_subdev_core_ops mt9m032_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = mt9m032_g_register, ++ .s_register = mt9m032_s_register, ++#endif ++}; ++ ++static const struct v4l2_subdev_video_ops mt9m032_video_ops = { ++ .s_stream = mt9m032_s_stream, ++ .g_frame_interval = mt9m032_get_frame_interval, ++ .s_frame_interval = mt9m032_set_frame_interval, ++}; ++ ++static const struct v4l2_subdev_pad_ops mt9m032_pad_ops = { ++ .enum_mbus_code = mt9m032_enum_mbus_code, ++ .enum_frame_size = mt9m032_enum_frame_size, ++ .get_fmt = mt9m032_get_pad_format, ++ .set_fmt = mt9m032_set_pad_format, ++ .set_crop = mt9m032_set_pad_crop, ++ .get_crop = mt9m032_get_pad_crop, ++}; ++ ++static const struct v4l2_subdev_ops mt9m032_ops = { ++ .core = &mt9m032_core_ops, ++ .video = &mt9m032_video_ops, ++ .pad = &mt9m032_pad_ops, ++}; ++ ++/* ----------------------------------------------------------------------------- ++ * Driver initialization and probing ++ */ ++ ++static int mt9m032_probe(struct i2c_client *client, ++ const struct i2c_device_id *devid) ++{ ++ struct i2c_adapter *adapter = client->adapter; ++ struct mt9m032 *sensor; ++ int chip_version; ++ int ret; ++ ++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { ++ dev_warn(&client->dev, ++ "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); ++ return -EIO; ++ } ++ ++ if (!client->dev.platform_data) ++ return -ENODEV; ++ ++ sensor = kzalloc(sizeof(*sensor), GFP_KERNEL); ++ if (sensor == NULL) ++ return -ENOMEM; ++ ++ mutex_init(&sensor->lock); ++ ++ sensor->pdata = client->dev.platform_data; ++ ++ v4l2_i2c_subdev_init(&sensor->subdev, client, &mt9m032_ops); ++ sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ chip_version = mt9m032_read(client, MT9M032_CHIP_VERSION); ++ if (chip_version != MT9M032_CHIP_VERSION_VALUE) { ++ dev_err(&client->dev, "MT9M032 not detected, wrong version " ++ "0x%04x\n", chip_version); ++ ret = -ENODEV; ++ goto error_sensor; ++ } ++ ++ dev_info(&client->dev, "MT9M032 detected at address 0x%02x\n", ++ client->addr); ++ ++ sensor->frame_interval.numerator = 1; ++ sensor->frame_interval.denominator = 30; ++ ++ sensor->crop.left = MT9M032_COLUMN_START_DEF; ++ sensor->crop.top = MT9M032_ROW_START_DEF; ++ sensor->crop.width = MT9M032_COLUMN_SIZE_DEF; ++ sensor->crop.height = MT9M032_ROW_SIZE_DEF; ++ ++ sensor->format.width = sensor->crop.width; ++ sensor->format.height = sensor->crop.height; ++ sensor->format.code = V4L2_MBUS_FMT_Y8_1X8; ++ sensor->format.field = V4L2_FIELD_NONE; ++ sensor->format.colorspace = V4L2_COLORSPACE_SRGB; ++ ++ v4l2_ctrl_handler_init(&sensor->ctrls, 4); ++ ++ v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops, ++ V4L2_CID_GAIN, 0, 127, 1, 64); ++ ++ sensor->hflip = v4l2_ctrl_new_std(&sensor->ctrls, ++ &mt9m032_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ sensor->vflip = v4l2_ctrl_new_std(&sensor->ctrls, ++ &mt9m032_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ ++ v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops, ++ V4L2_CID_EXPOSURE, MT9M032_SHUTTER_WIDTH_MIN, ++ MT9M032_SHUTTER_WIDTH_MAX, 1, ++ MT9M032_SHUTTER_WIDTH_DEF); ++ ++ if (sensor->ctrls.error) { ++ ret = sensor->ctrls.error; ++ dev_err(&client->dev, "control initialization error %d\n", ret); ++ goto error_ctrl; ++ } ++ ++ v4l2_ctrl_cluster(2, &sensor->hflip); ++ ++ sensor->subdev.ctrl_handler = &sensor->ctrls; ++ sensor->pad.flags = MEDIA_PAD_FL_SOURCE; ++ ret = media_entity_init(&sensor->subdev.entity, 1, &sensor->pad, 0); ++ if (ret < 0) ++ goto error_ctrl; ++ ++ ret = mt9m032_write(client, MT9M032_RESET, 1); /* reset on */ ++ if (ret < 0) ++ goto error_entity; ++ mt9m032_write(client, MT9M032_RESET, 0); /* reset off */ ++ if (ret < 0) ++ goto error_entity; ++ ++ ret = mt9m032_setup_pll(sensor); ++ if (ret < 0) ++ goto error_entity; ++ usleep_range(10000, 11000); ++ ++ ret = v4l2_ctrl_handler_setup(&sensor->ctrls); ++ if (ret < 0) ++ goto error_entity; ++ ++ /* SIZE */ ++ ret = mt9m032_update_geom_timing(sensor); ++ if (ret < 0) ++ goto error_entity; ++ ++ ret = mt9m032_write(client, 0x41, 0x0000); /* reserved !!! */ ++ if (ret < 0) ++ goto error_entity; ++ ret = mt9m032_write(client, 0x42, 0x0003); /* reserved !!! */ ++ if (ret < 0) ++ goto error_entity; ++ ret = mt9m032_write(client, 0x43, 0x0003); /* reserved !!! */ ++ if (ret < 0) ++ goto error_entity; ++ ret = mt9m032_write(client, 0x7f, 0x0000); /* reserved !!! */ ++ if (ret < 0) ++ goto error_entity; ++ if (sensor->pdata->invert_pixclock) { ++ ret = mt9m032_write(client, MT9M032_PIX_CLK_CTRL, ++ MT9M032_PIX_CLK_CTRL_INV_PIXCLK); ++ if (ret < 0) ++ goto error_entity; ++ } ++ ++ ret = mt9m032_write(client, MT9M032_RESTART, 1); /* Restart on */ ++ if (ret < 0) ++ goto error_entity; ++ msleep(100); ++ ret = mt9m032_write(client, MT9M032_RESTART, 0); /* Restart off */ ++ if (ret < 0) ++ goto error_entity; ++ msleep(100); ++ ret = update_formatter2(sensor, false); ++ if (ret < 0) ++ goto error_entity; ++ ++ return ret; ++ ++error_entity: ++ media_entity_cleanup(&sensor->subdev.entity); ++error_ctrl: ++ v4l2_ctrl_handler_free(&sensor->ctrls); ++error_sensor: ++ mutex_destroy(&sensor->lock); ++ kfree(sensor); ++ return ret; ++} ++ ++static int mt9m032_remove(struct i2c_client *client) ++{ ++ struct v4l2_subdev *subdev = i2c_get_clientdata(client); ++ struct mt9m032 *sensor = to_mt9m032(subdev); ++ ++ v4l2_device_unregister_subdev(&sensor->subdev); ++ v4l2_ctrl_handler_free(&sensor->ctrls); ++ media_entity_cleanup(&sensor->subdev.entity); ++ mutex_destroy(&sensor->lock); ++ kfree(sensor); ++ return 0; ++} ++ ++static const struct i2c_device_id mt9m032_id_table[] = { ++ { MT9M032_NAME, 0 }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(i2c, mt9m032_id_table); ++ ++static struct i2c_driver mt9m032_i2c_driver = { ++ .driver = { ++ .name = MT9M032_NAME, ++ }, ++ .probe = mt9m032_probe, ++ .remove = mt9m032_remove, ++ .id_table = mt9m032_id_table, ++}; ++ ++module_i2c_driver(mt9m032_i2c_driver); ++ ++MODULE_AUTHOR("Martin Hostettler "); ++MODULE_DESCRIPTION("MT9M032 camera sensor driver"); ++MODULE_LICENSE("GPL v2"); +Index: linux-3.3.x86_64/include/media/mt9m032.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/include/media/mt9m032.h +@@ -0,0 +1,36 @@ ++/* ++ * Driver for MT9M032 CMOS Image Sensor from Micron ++ * ++ * Copyright (C) 2010-2011 Lund Engineering ++ * Contact: Gil Lund ++ * Author: Martin Hostettler ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ * ++ */ ++ ++#ifndef MT9M032_H ++#define MT9M032_H ++ ++#define MT9M032_NAME "mt9m032" ++#define MT9M032_I2C_ADDR (0xb8 >> 1) ++ ++struct mt9m032_platform_data { ++ u32 ext_clock; ++ u32 pix_clock; ++ bool invert_pixclock; ++ ++}; ++#endif /* MT9M032_H */ +Index: linux-3.3.x86_64/drivers/media/video/v4l2-dev.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/v4l2-dev.c ++++ linux-3.3.x86_64/drivers/media/video/v4l2-dev.c +@@ -788,7 +788,7 @@ static void __exit videodev_exit(void) + unregister_chrdev_region(dev, VIDEO_NUM_DEVICES); + } + +-module_init(videodev_init) ++subsys_initcall(videodev_init); + module_exit(videodev_exit) + + MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab "); +Index: linux-3.3.x86_64/drivers/media/media-devnode.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/media-devnode.c ++++ linux-3.3.x86_64/drivers/media/media-devnode.c +@@ -312,7 +312,7 @@ static void __exit media_devnode_exit(vo + unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES); + } + +-module_init(media_devnode_init) ++subsys_initcall(media_devnode_init); + module_exit(media_devnode_exit) + + MODULE_AUTHOR("Laurent Pinchart "); +Index: linux-3.3.x86_64/drivers/media/rc/mceusb.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/mceusb.c ++++ linux-3.3.x86_64/drivers/media/rc/mceusb.c +@@ -361,6 +361,8 @@ static struct usb_device_id mceusb_dev_t + { USB_DEVICE(VENDOR_FORMOSA, 0xe03c) }, + /* Formosa Industrial Computing */ + { USB_DEVICE(VENDOR_FORMOSA, 0xe03e) }, ++ /* Formosa Industrial Computing */ ++ { USB_DEVICE(VENDOR_FORMOSA, 0xe042) }, + /* Fintek eHome Infrared Transceiver (HP branded) */ + { USB_DEVICE(VENDOR_FINTEK, 0x5168) }, + /* Fintek eHome Infrared Transceiver */ +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/au8522_dig.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/au8522_dig.c ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/au8522_dig.c +@@ -604,6 +604,11 @@ static int au8522_set_frontend(struct dv + + au8522_enable_modulation(fe, c->modulation); + ++ /* Allow the tuner to settle */ ++ msleep(100); ++ ++ au8522_enable_modulation(fe, c->modulation); ++ + state->current_frequency = c->frequency; + + return 0; +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/dib0700_core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/dib0700_core.c ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/dib0700_core.c +@@ -677,11 +677,9 @@ static void dib0700_rc_urb_completion(st + u8 toggle; + + deb_info("%s()\n", __func__); +- if (d == NULL) +- return; +- + if (d->rc_dev == NULL) { + /* This will occur if disable_rc_polling=1 */ ++ kfree(purb->transfer_buffer); + usb_free_urb(purb); + return; + } +@@ -690,6 +688,7 @@ static void dib0700_rc_urb_completion(st + + if (purb->status < 0) { + deb_info("discontinuing polling\n"); ++ kfree(purb->transfer_buffer); + usb_free_urb(purb); + return; + } +@@ -784,8 +783,11 @@ int dib0700_rc_setup(struct dvb_usb_devi + dib0700_rc_urb_completion, d); + + ret = usb_submit_urb(purb, GFP_ATOMIC); +- if (ret) ++ if (ret) { + err("rc submit urb failed\n"); ++ kfree(purb->transfer_buffer); ++ usb_free_urb(purb); ++ } + + return ret; + } +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9015.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/af9015.c ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9015.c +@@ -1164,6 +1164,41 @@ static int af9015_af9013_sleep(struct dv + return ret; + } + ++/* override tuner callbacks for resource locking */ ++static int af9015_tuner_init(struct dvb_frontend *fe) ++{ ++ int ret; ++ struct dvb_usb_adapter *adap = fe->dvb->priv; ++ struct af9015_state *priv = adap->dev->priv; ++ ++ if (mutex_lock_interruptible(&adap->dev->usb_mutex)) ++ return -EAGAIN; ++ ++ ret = priv->tuner_init[adap->id](fe); ++ ++ mutex_unlock(&adap->dev->usb_mutex); ++ ++ return ret; ++} ++ ++/* override tuner callbacks for resource locking */ ++static int af9015_tuner_sleep(struct dvb_frontend *fe) ++{ ++ int ret; ++ struct dvb_usb_adapter *adap = fe->dvb->priv; ++ struct af9015_state *priv = adap->dev->priv; ++ ++ if (mutex_lock_interruptible(&adap->dev->usb_mutex)) ++ return -EAGAIN; ++ ++ ret = priv->tuner_sleep[adap->id](fe); ++ ++ mutex_unlock(&adap->dev->usb_mutex); ++ ++ return ret; ++} ++ ++ + static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) + { + int ret; +@@ -1283,6 +1318,7 @@ static struct mxl5007t_config af9015_mxl + static int af9015_tuner_attach(struct dvb_usb_adapter *adap) + { + int ret; ++ struct af9015_state *state = adap->dev->priv; + deb_info("%s:\n", __func__); + + switch (af9015_af9013_config[adap->id].tuner) { +@@ -1340,6 +1376,19 @@ static int af9015_tuner_attach(struct dv + err("Unknown tuner id:%d", + af9015_af9013_config[adap->id].tuner); + } ++ ++ if (adap->fe_adap[0].fe->ops.tuner_ops.init) { ++ state->tuner_init[adap->id] = ++ adap->fe_adap[0].fe->ops.tuner_ops.init; ++ adap->fe_adap[0].fe->ops.tuner_ops.init = af9015_tuner_init; ++ } ++ ++ if (adap->fe_adap[0].fe->ops.tuner_ops.sleep) { ++ state->tuner_sleep[adap->id] = ++ adap->fe_adap[0].fe->ops.tuner_ops.sleep; ++ adap->fe_adap[0].fe->ops.tuner_ops.sleep = af9015_tuner_sleep; ++ } ++ + return ret; + } + +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9015.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/af9015.h ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9015.h +@@ -108,6 +108,8 @@ struct af9015_state { + int (*read_status[2]) (struct dvb_frontend *fe, fe_status_t *status); + int (*init[2]) (struct dvb_frontend *fe); + int (*sleep[2]) (struct dvb_frontend *fe); ++ int (*tuner_init[2]) (struct dvb_frontend *fe); ++ int (*tuner_sleep[2]) (struct dvb_frontend *fe); + }; + + struct af9015_config { +Index: linux-3.3.x86_64/drivers/media/rc/rc-main.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/rc/rc-main.c ++++ linux-3.3.x86_64/drivers/media/rc/rc-main.c +@@ -1029,6 +1029,7 @@ EXPORT_SYMBOL_GPL(rc_free_device); + + int rc_register_device(struct rc_dev *dev) + { ++ static bool raw_init = false; /* raw decoders loaded? */ + static atomic_t devno = ATOMIC_INIT(0); + struct rc_map *rc_map; + const char *path; +@@ -1103,6 +1104,12 @@ int rc_register_device(struct rc_dev *de + kfree(path); + + if (dev->driver_type == RC_DRIVER_IR_RAW) { ++ /* Load raw decoders, if they aren't already */ ++ if (!raw_init) { ++ IR_dprintk(1, "Loading raw decoders\n"); ++ ir_raw_init(); ++ raw_init = true; ++ } + rc = ir_raw_event_register(dev); + if (rc < 0) + goto out_input; +@@ -1176,8 +1183,6 @@ static int __init rc_core_init(void) + return rc; + } + +- /* Initialize/load the decoders/keymap code that will be used */ +- ir_raw_init(); + rc_map_register(&empty_map); + + return 0; +Index: linux-3.3.x86_64/drivers/media/video/soc_camera.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/soc_camera.c ++++ linux-3.3.x86_64/drivers/media/video/soc_camera.c +@@ -526,10 +526,6 @@ static int soc_camera_open(struct file * + }, + }; + +- ret = soc_camera_power_on(icd, icl); +- if (ret < 0) +- goto epower; +- + /* The camera could have been already on, try to reset */ + if (icl->reset) + icl->reset(icd->pdev); +@@ -540,6 +536,10 @@ static int soc_camera_open(struct file * + goto eiciadd; + } + ++ ret = soc_camera_power_on(icd, icl); ++ if (ret < 0) ++ goto epower; ++ + pm_runtime_enable(&icd->vdev->dev); + ret = pm_runtime_resume(&icd->vdev->dev); + if (ret < 0 && ret != -ENOSYS) +@@ -578,10 +578,10 @@ einitvb: + esfmt: + pm_runtime_disable(&icd->vdev->dev); + eresume: +- ici->ops->remove(icd); +-eiciadd: + soc_camera_power_off(icd, icl); + epower: ++ ici->ops->remove(icd); ++eiciadd: + icd->use_count--; + module_put(ici->ops->owner); + +@@ -1050,6 +1050,14 @@ static int soc_camera_probe(struct soc_c + if (ret < 0) + goto ereg; + ++ /* The camera could have been already on, try to reset */ ++ if (icl->reset) ++ icl->reset(icd->pdev); ++ ++ ret = ici->ops->add(icd); ++ if (ret < 0) ++ goto eadd; ++ + /* + * This will not yet call v4l2_subdev_core_ops::s_power(1), because the + * subdevice has not been initialised yet. We'll have to call it once +@@ -1060,14 +1068,6 @@ static int soc_camera_probe(struct soc_c + if (ret < 0) + goto epower; + +- /* The camera could have been already on, try to reset */ +- if (icl->reset) +- icl->reset(icd->pdev); +- +- ret = ici->ops->add(icd); +- if (ret < 0) +- goto eadd; +- + /* Must have icd->vdev before registering the device */ + ret = video_dev_create(icd); + if (ret < 0) +@@ -1165,10 +1165,10 @@ eadddev: + video_device_release(icd->vdev); + icd->vdev = NULL; + evdc: +- ici->ops->remove(icd); +-eadd: + soc_camera_power_off(icd, icl); + epower: ++ ici->ops->remove(icd); ++eadd: + regulator_bulk_free(icl->num_regulators, icl->regulators); + ereg: + v4l2_ctrl_handler_free(&icd->ctrl_handler); +Index: linux-3.3.x86_64/drivers/media/video/sh_mobile_ceu_camera.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/sh_mobile_ceu_camera.c ++++ linux-3.3.x86_64/drivers/media/video/sh_mobile_ceu_camera.c +@@ -112,6 +112,10 @@ struct sh_mobile_ceu_dev { + + u32 cflcr; + ++ /* static max sizes either from platform data or default */ ++ int max_width; ++ int max_height; ++ + enum v4l2_field field; + int sequence; + +@@ -1081,7 +1085,15 @@ static int sh_mobile_ceu_get_formats(str + if (ret < 0) + return ret; + +- while ((mf.width > 2560 || mf.height > 1920) && shift < 4) { ++ /* ++ * All currently existing CEU implementations support 2560x1920 ++ * or larger frames. If the sensor is proposing too big a frame, ++ * don't bother with possibly supportred by the CEU larger ++ * sizes, just try VGA multiples. If needed, this can be ++ * adjusted in the future. ++ */ ++ while ((mf.width > pcdev->max_width || ++ mf.height > pcdev->max_height) && shift < 4) { + /* Try 2560x1920, 1280x960, 640x480, 320x240 */ + mf.width = 2560 >> shift; + mf.height = 1920 >> shift; +@@ -1377,6 +1389,8 @@ static int client_s_crop(struct soc_came + static int client_s_fmt(struct soc_camera_device *icd, + struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) + { ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct sh_mobile_ceu_dev *pcdev = ici->priv; + struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct device *dev = icd->parent; +@@ -1410,8 +1424,8 @@ static int client_s_fmt(struct soc_camer + if (ret < 0) + return ret; + +- max_width = min(cap.bounds.width, 2560); +- max_height = min(cap.bounds.height, 1920); ++ max_width = min(cap.bounds.width, pcdev->max_width); ++ max_height = min(cap.bounds.height, pcdev->max_height); + + /* Camera set a format, but geometry is not precise, try to improve */ + tmp_w = mf->width; +@@ -1551,7 +1565,7 @@ static int sh_mobile_ceu_set_crop(struct + if (ret < 0) + return ret; + +- if (mf.width > 2560 || mf.height > 1920) ++ if (mf.width > pcdev->max_width || mf.height > pcdev->max_height) + return -EINVAL; + + /* 4. Calculate camera scales */ +@@ -1834,6 +1848,8 @@ static int sh_mobile_ceu_set_fmt(struct + static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) + { ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct sh_mobile_ceu_dev *pcdev = ici->priv; + const struct soc_camera_format_xlate *xlate; + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); +@@ -1854,8 +1870,8 @@ static int sh_mobile_ceu_try_fmt(struct + /* FIXME: calculate using depth and bus width */ + + /* CFSZR requires height and width to be 4-pixel aligned */ +- v4l_bound_align_image(&pix->width, 2, 2560, 2, +- &pix->height, 4, 1920, 2, 0); ++ v4l_bound_align_image(&pix->width, 2, pcdev->max_width, 2, ++ &pix->height, 4, pcdev->max_height, 2, 0); + + width = pix->width; + height = pix->height; +@@ -1890,8 +1906,8 @@ static int sh_mobile_ceu_try_fmt(struct + * requested a bigger rectangle, it will not return a + * smaller one. + */ +- mf.width = 2560; +- mf.height = 1920; ++ mf.width = pcdev->max_width; ++ mf.height = pcdev->max_height; + ret = v4l2_device_call_until_err(sd->v4l2_dev, + soc_camera_grp_id(icd), video, + try_mbus_fmt, &mf); +@@ -2082,6 +2098,9 @@ static int __devinit sh_mobile_ceu_probe + goto exit_kfree; + } + ++ pcdev->max_width = pcdev->pdata->max_width ? : 2560; ++ pcdev->max_height = pcdev->pdata->max_height ? : 1920; ++ + base = ioremap_nocache(res->start, resource_size(res)); + if (!base) { + err = -ENXIO; +Index: linux-3.3.x86_64/include/media/sh_mobile_ceu.h +=================================================================== +--- linux-3.3.x86_64.orig/include/media/sh_mobile_ceu.h ++++ linux-3.3.x86_64/include/media/sh_mobile_ceu.h +@@ -18,6 +18,8 @@ struct sh_mobile_ceu_companion { + + struct sh_mobile_ceu_info { + unsigned long flags; ++ int max_width; ++ int max_height; + struct sh_mobile_ceu_companion *csi2; + }; + +Index: linux-3.3.x86_64/drivers/media/video/pxa_camera.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/pxa_camera.c ++++ linux-3.3.x86_64/drivers/media/video/pxa_camera.c +@@ -921,12 +921,12 @@ static void pxa_camera_activate(struct p + /* "Safe default" - 13MHz */ + recalculate_fifo_timeout(pcdev, 13000000); + +- clk_enable(pcdev->clk); ++ clk_prepare_enable(pcdev->clk); + } + + static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) + { +- clk_disable(pcdev->clk); ++ clk_disable_unprepare(pcdev->clk); + } + + static irqreturn_t pxa_camera_irq(int irq, void *data) +Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-i2c.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx-i2c.c ++++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-i2c.c +@@ -41,14 +41,6 @@ static unsigned int i2c_debug; + module_param(i2c_debug, int, 0644); + MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); + +- +-#define dprintk1(lvl, fmt, args...) \ +-do { \ +- if (i2c_debug >= lvl) { \ +- printk(fmt, ##args); \ +- } \ +-} while (0) +- + #define dprintk2(lvl, fmt, args...) \ + do { \ + if (i2c_debug >= lvl) { \ +Index: linux-3.3.x86_64/drivers/media/video/marvell-ccic/mcam-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/marvell-ccic/mcam-core.c ++++ linux-3.3.x86_64/drivers/media/video/marvell-ccic/mcam-core.c +@@ -509,11 +509,17 @@ static void mcam_sg_next_buffer(struct m + + buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue); + list_del_init(&buf->queue); ++ /* ++ * Very Bad Not Good Things happen if you don't clear ++ * C1_DESC_ENA before making any descriptor changes. ++ */ ++ mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_ENA); + mcam_reg_write(cam, REG_DMA_DESC_Y, buf->dma_desc_pa); + mcam_reg_write(cam, REG_DESC_LEN_Y, + buf->dma_desc_nent*sizeof(struct mcam_dma_desc)); + mcam_reg_write(cam, REG_DESC_LEN_U, 0); + mcam_reg_write(cam, REG_DESC_LEN_V, 0); ++ mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA); + cam->vb_bufs[0] = buf; + } + +@@ -533,7 +539,6 @@ static void mcam_ctlr_dma_sg(struct mcam + + mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_3WORD); + mcam_sg_next_buffer(cam); +- mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA); + cam->nbufs = 3; + } + +@@ -556,17 +561,16 @@ static void mcam_dma_sg_done(struct mcam + struct mcam_vb_buffer *buf = cam->vb_bufs[0]; + + /* +- * Very Bad Not Good Things happen if you don't clear +- * C1_DESC_ENA before making any descriptor changes. ++ * If we're no longer supposed to be streaming, don't do anything. + */ +- mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_ENA); ++ if (cam->state != S_STREAMING) ++ return; + /* + * If we have another buffer available, put it in and + * restart the engine. + */ + if (!list_empty(&cam->buffers)) { + mcam_sg_next_buffer(cam); +- mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA); + mcam_ctlr_start(cam); + /* + * Otherwise set CF_SG_RESTART and the controller will +@@ -737,7 +741,14 @@ static void mcam_ctlr_stop_dma(struct mc + mcam_ctlr_stop(cam); + cam->state = S_IDLE; + spin_unlock_irqrestore(&cam->dev_lock, flags); +- msleep(40); ++ /* ++ * This is a brutally long sleep, but experience shows that ++ * it can take the controller a while to get the message that ++ * it needs to stop grabbing frames. In particular, we can ++ * sometimes (on mmp) get a frame at the end WITHOUT the ++ * start-of-frame indication. ++ */ ++ msleep(150); + if (test_bit(CF_DMA_ACTIVE, &cam->flags)) + cam_err(cam, "Timeout waiting for DMA to end\n"); + /* This would be bad news - what now? */ +@@ -880,6 +891,7 @@ static int mcam_read_setup(struct mcam_c + * Turn it loose. + */ + spin_lock_irqsave(&cam->dev_lock, flags); ++ clear_bit(CF_DMA_ACTIVE, &cam->flags); + mcam_reset_buffers(cam); + mcam_ctlr_irq_enable(cam); + cam->state = S_STREAMING; +@@ -922,7 +934,7 @@ static void mcam_vb_buf_queue(struct vb2 + spin_lock_irqsave(&cam->dev_lock, flags); + start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers); + list_add(&mvb->queue, &cam->buffers); +- if (test_bit(CF_SG_RESTART, &cam->flags)) ++ if (cam->state == S_STREAMING && test_bit(CF_SG_RESTART, &cam->flags)) + mcam_sg_restart(cam); + spin_unlock_irqrestore(&cam->dev_lock, flags); + if (start) +@@ -1555,15 +1567,12 @@ static int mcam_v4l_release(struct file + { + struct mcam_camera *cam = filp->private_data; + +- cam_err(cam, "Release, %d frames, %d singles, %d delivered\n", frames, ++ cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n", frames, + singles, delivered); + mutex_lock(&cam->s_mutex); + (cam->users)--; +- if (filp == cam->owner) { +- mcam_ctlr_stop_dma(cam); +- cam->owner = NULL; +- } + if (cam->users == 0) { ++ mcam_ctlr_stop_dma(cam); + mcam_cleanup_vb2(cam); + mcam_ctlr_power_down(cam); + if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read) +@@ -1688,6 +1697,8 @@ int mccic_irq(struct mcam_camera *cam, u + if (irqs & (IRQ_EOF0 << frame)) { + mcam_frame_complete(cam, frame); + handled = 1; ++ if (cam->buffer_mode == B_DMA_sg) ++ break; + } + /* + * If a frame starts, note that we have DMA active. This +Index: linux-3.3.x86_64/drivers/media/video/marvell-ccic/mcam-core.h +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/marvell-ccic/mcam-core.h ++++ linux-3.3.x86_64/drivers/media/video/marvell-ccic/mcam-core.h +@@ -107,7 +107,6 @@ struct mcam_camera { + enum mcam_state state; + unsigned long flags; /* Buffer status, mainly (dev_lock) */ + int users; /* How many open FDs */ +- struct file *owner; /* Who has data access (v4l2) */ + + /* + * Subsystem structures. +Index: linux-3.3.x86_64/drivers/media/video/marvell-ccic/mmp-driver.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/marvell-ccic/mmp-driver.c ++++ linux-3.3.x86_64/drivers/media/video/marvell-ccic/mmp-driver.c +@@ -106,6 +106,13 @@ static struct mmp_camera *mmpcam_find_de + /* + * Power control. + */ ++static void mmpcam_power_up_ctlr(struct mmp_camera *cam) ++{ ++ iowrite32(0x3f, cam->power_regs + REG_CCIC_DCGCR); ++ iowrite32(0x3805b, cam->power_regs + REG_CCIC_CRCR); ++ mdelay(1); ++} ++ + static void mmpcam_power_up(struct mcam_camera *mcam) + { + struct mmp_camera *cam = mcam_to_cam(mcam); +@@ -113,9 +120,7 @@ static void mmpcam_power_up(struct mcam_ + /* + * Turn on power and clocks to the controller. + */ +- iowrite32(0x3f, cam->power_regs + REG_CCIC_DCGCR); +- iowrite32(0x3805b, cam->power_regs + REG_CCIC_CRCR); +- mdelay(1); ++ mmpcam_power_up_ctlr(cam); + /* + * Provide power to the sensor. + */ +@@ -335,7 +340,7 @@ static int mmpcam_resume(struct platform + * touch a register even if nothing was active before; trust + * me, it's better this way. + */ +- mmpcam_power_up(&cam->mcam); ++ mmpcam_power_up_ctlr(cam); + return mccic_resume(&cam->mcam); + } + +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/mxl111sf.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/mxl111sf.c ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/mxl111sf.c +@@ -340,7 +340,6 @@ static int mxl111sf_ep6_streaming_ctrl(s + struct mxl111sf_state *state = d->priv; + struct mxl111sf_adap_state *adap_state = adap->fe_adap[adap->active_fe].priv; + int ret = 0; +- u8 tmp; + + deb_info("%s(%d)\n", __func__, onoff); + +Index: linux-3.3.x86_64/drivers/media/video/pvrusb2/pvrusb2-devattr.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/pvrusb2/pvrusb2-devattr.c ++++ linux-3.3.x86_64/drivers/media/video/pvrusb2/pvrusb2-devattr.c +@@ -329,6 +329,15 @@ static struct tda18271_std_map hauppauge + .if_lvl = 1, .rfagc_top = 0x37, }, + }; + ++static struct tda18271_std_map hauppauge_tda18271_dvbt_std_map = { ++ .dvbt_6 = { .if_freq = 3300, .agc_mode = 3, .std = 4, ++ .if_lvl = 1, .rfagc_top = 0x37, }, ++ .dvbt_7 = { .if_freq = 3800, .agc_mode = 3, .std = 5, ++ .if_lvl = 1, .rfagc_top = 0x37, }, ++ .dvbt_8 = { .if_freq = 4300, .agc_mode = 3, .std = 6, ++ .if_lvl = 1, .rfagc_top = 0x37, }, ++}; ++ + static struct tda18271_config hauppauge_tda18271_dvb_config = { + .std_map = &hauppauge_tda18271_dvbt_std_map, + .gate = TDA18271_GATE_ANALOG, +Index: linux-3.3.x86_64/drivers/media/video/gspca/ov534_9.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/gspca/ov534_9.c ++++ linux-3.3.x86_64/drivers/media/video/gspca/ov534_9.c +@@ -1107,16 +1107,34 @@ static void setbrightness(struct gspca_d + { + struct sd *sd = (struct sd *) gspca_dev; + u8 val; ++ s8 sval; + + if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS)) + return; +- val = sd->ctrls[BRIGHTNESS].val; +- if (val < 8) +- val = 15 - val; /* f .. 8 */ +- else +- val = val - 8; /* 0 .. 7 */ +- sccb_write(gspca_dev, 0x55, /* brtn - brightness adjustment */ +- 0x0f | (val << 4)); ++ if (sd->sensor == SENSOR_OV562x) { ++ sval = sd->ctrls[BRIGHTNESS].val; ++ val = 0x76; ++ val += sval; ++ sccb_write(gspca_dev, 0x24, val); ++ val = 0x6a; ++ val += sval; ++ sccb_write(gspca_dev, 0x25, val); ++ if (sval < -40) ++ val = 0x71; ++ else if (sval < 20) ++ val = 0x94; ++ else ++ val = 0xe6; ++ sccb_write(gspca_dev, 0x26, val); ++ } else { ++ val = sd->ctrls[BRIGHTNESS].val; ++ if (val < 8) ++ val = 15 - val; /* f .. 8 */ ++ else ++ val = val - 8; /* 0 .. 7 */ ++ sccb_write(gspca_dev, 0x55, /* brtn - brightness adjustment */ ++ 0x0f | (val << 4)); ++ } + } + + static void setcontrast(struct gspca_dev *gspca_dev) +@@ -1339,7 +1357,16 @@ static int sd_init(struct gspca_dev *gsp + reg_w(gspca_dev, 0x56, 0x17); + } else if ((sensor_id & 0xfff0) == 0x5620) { + sd->sensor = SENSOR_OV562x; +- ++ gspca_dev->ctrl_dis = (1 << CONTRAST) | ++ (1 << AUTOGAIN) | ++ (1 << EXPOSURE) | ++ (1 << SHARPNESS) | ++ (1 << SATUR) | ++ (1 << LIGHTFREQ); ++ ++ sd->ctrls[BRIGHTNESS].min = -90; ++ sd->ctrls[BRIGHTNESS].max = 90; ++ sd->ctrls[BRIGHTNESS].def = 0; + gspca_dev->cam.cam_mode = ov562x_mode; + gspca_dev->cam.nmodes = ARRAY_SIZE(ov562x_mode); + +@@ -1360,8 +1387,12 @@ static int sd_start(struct gspca_dev *gs + { + struct sd *sd = (struct sd *) gspca_dev; + +- if (sd->sensor == SENSOR_OV971x || sd->sensor == SENSOR_OV562x) ++ if (sd->sensor == SENSOR_OV971x) + return gspca_dev->usb_err; ++ else if (sd->sensor == SENSOR_OV562x) { ++ setbrightness(gspca_dev); ++ return gspca_dev->usb_err; ++ } + switch (gspca_dev->curr_mode) { + case QVGA_MODE: /* 320x240 */ + sccb_w_array(gspca_dev, ov965x_start_1_vga, +Index: linux-3.3.x86_64/drivers/media/video/gspca/sn9c20x.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/gspca/sn9c20x.c ++++ linux-3.3.x86_64/drivers/media/video/gspca/sn9c20x.c +@@ -1,5 +1,7 @@ + /* + * Sonix sn9c201 sn9c202 library ++ * ++ * Copyright (C) 2012 Jean-Francois Moine + * Copyright (C) 2008-2009 microdia project + * Copyright (C) 2009 Brian Johnson + * +@@ -33,8 +35,6 @@ MODULE_AUTHOR("Brian Johnson dev; + int result; ++ ++ if (gspca_dev->usb_err < 0) ++ return; + result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + 0x00, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, +@@ -1125,17 +1103,19 @@ static int reg_r(struct gspca_dev *gspca + length, + 500); + if (unlikely(result < 0 || result != length)) { +- pr_err("Read register failed 0x%02X\n", reg); +- return -EIO; ++ pr_err("Read register %02x failed %d\n", reg, result); ++ gspca_dev->usb_err = result; + } +- return 0; + } + +-static int reg_w(struct gspca_dev *gspca_dev, u16 reg, ++static void reg_w(struct gspca_dev *gspca_dev, u16 reg, + const u8 *buffer, int length) + { + struct usb_device *dev = gspca_dev->dev; + int result; ++ ++ if (gspca_dev->usb_err < 0) ++ return; + memcpy(gspca_dev->usb_buf, buffer, length); + result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + 0x08, +@@ -1146,38 +1126,41 @@ static int reg_w(struct gspca_dev *gspca + length, + 500); + if (unlikely(result < 0 || result != length)) { +- pr_err("Write register failed index 0x%02X\n", reg); +- return -EIO; ++ pr_err("Write register %02x failed %d\n", reg, result); ++ gspca_dev->usb_err = result; + } +- return 0; + } + +-static int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value) ++static void reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value) + { +- u8 data[1] = {value}; +- return reg_w(gspca_dev, reg, data, 1); ++ reg_w(gspca_dev, reg, &value, 1); + } + +-static int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer) ++static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer) + { + int i; ++ + reg_w(gspca_dev, 0x10c0, buffer, 8); + for (i = 0; i < 5; i++) { + reg_r(gspca_dev, 0x10c0, 1); ++ if (gspca_dev->usb_err < 0) ++ return; + if (gspca_dev->usb_buf[0] & 0x04) { +- if (gspca_dev->usb_buf[0] & 0x08) +- return -EIO; +- return 0; ++ if (gspca_dev->usb_buf[0] & 0x08) { ++ pr_err("i2c_w error\n"); ++ gspca_dev->usb_err = -EIO; ++ } ++ return; + } +- msleep(1); ++ msleep(10); + } +- return -EIO; ++ pr_err("i2c_w reg %02x no response\n", buffer[2]); ++/* gspca_dev->usb_err = -EIO; fixme: may occur */ + } + +-static int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) ++static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) + { + struct sd *sd = (struct sd *) gspca_dev; +- + u8 row[8]; + + /* +@@ -1193,10 +1176,19 @@ static int i2c_w1(struct gspca_dev *gspc + row[6] = 0x00; + row[7] = 0x10; + +- return i2c_w(gspca_dev, row); ++ i2c_w(gspca_dev, row); ++} ++ ++static void i2c_w1_buf(struct gspca_dev *gspca_dev, ++ struct i2c_reg_u8 *buf, int sz) ++{ ++ while (--sz >= 0) { ++ i2c_w1(gspca_dev, buf->reg, buf->val); ++ buf++; ++ } + } + +-static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val) ++static void i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val) + { + struct sd *sd = (struct sd *) gspca_dev; + u8 row[8]; +@@ -1208,16 +1200,25 @@ static int i2c_w2(struct gspca_dev *gspc + row[0] = 0x81 | (3 << 4); + row[1] = sd->i2c_addr; + row[2] = reg; +- row[3] = (val >> 8) & 0xff; +- row[4] = val & 0xff; ++ row[3] = val >> 8; ++ row[4] = val; + row[5] = 0x00; + row[6] = 0x00; + row[7] = 0x10; + +- return i2c_w(gspca_dev, row); ++ i2c_w(gspca_dev, row); + } + +-static int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) ++static void i2c_w2_buf(struct gspca_dev *gspca_dev, ++ struct i2c_reg_u16 *buf, int sz) ++{ ++ while (--sz >= 0) { ++ i2c_w2(gspca_dev, buf->reg, buf->val); ++ buf++; ++ } ++} ++ ++static void i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) + { + struct sd *sd = (struct sd *) gspca_dev; + u8 row[8]; +@@ -1230,19 +1231,15 @@ static int i2c_r1(struct gspca_dev *gspc + row[5] = 0; + row[6] = 0; + row[7] = 0x10; +- if (i2c_w(gspca_dev, row) < 0) +- return -EIO; ++ i2c_w(gspca_dev, row); + row[0] = 0x81 | (1 << 4) | 0x02; + row[2] = 0; +- if (i2c_w(gspca_dev, row) < 0) +- return -EIO; +- if (reg_r(gspca_dev, 0x10c2, 5) < 0) +- return -EIO; ++ i2c_w(gspca_dev, row); ++ reg_r(gspca_dev, 0x10c2, 5); + *val = gspca_dev->usb_buf[4]; +- return 0; + } + +-static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) ++static void i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) + { + struct sd *sd = (struct sd *) gspca_dev; + u8 row[8]; +@@ -1255,233 +1252,204 @@ static int i2c_r2(struct gspca_dev *gspc + row[5] = 0; + row[6] = 0; + row[7] = 0x10; +- if (i2c_w(gspca_dev, row) < 0) +- return -EIO; ++ i2c_w(gspca_dev, row); + row[0] = 0x81 | (2 << 4) | 0x02; + row[2] = 0; +- if (i2c_w(gspca_dev, row) < 0) +- return -EIO; +- if (reg_r(gspca_dev, 0x10c2, 5) < 0) +- return -EIO; ++ i2c_w(gspca_dev, row); ++ reg_r(gspca_dev, 0x10c2, 5); + *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; +- return 0; + } + +-static int ov9650_init_sensor(struct gspca_dev *gspca_dev) ++static void ov9650_init_sensor(struct gspca_dev *gspca_dev) + { +- int i; + u16 id; + struct sd *sd = (struct sd *) gspca_dev; + +- if (i2c_r2(gspca_dev, 0x1c, &id) < 0) +- return -EINVAL; ++ i2c_r2(gspca_dev, 0x1c, &id); ++ if (gspca_dev->usb_err < 0) ++ return; + + if (id != 0x7fa2) { + pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id); +- return -ENODEV; ++ gspca_dev->usb_err = -ENODEV; ++ return; + } + +- for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) { +- if (i2c_w1(gspca_dev, ov9650_init[i].reg, +- ov9650_init[i].val) < 0) { +- pr_err("OV9650 sensor initialization failed\n"); +- return -ENODEV; +- } +- } ++ i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ ++ msleep(200); ++ i2c_w1_buf(gspca_dev, ov9650_init, ARRAY_SIZE(ov9650_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("OV9650 sensor initialization failed\n"); + sd->hstart = 1; + sd->vstart = 7; +- return 0; + } + +-static int ov9655_init_sensor(struct gspca_dev *gspca_dev) ++static void ov9655_init_sensor(struct gspca_dev *gspca_dev) + { +- int i; + struct sd *sd = (struct sd *) gspca_dev; + +- for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) { +- if (i2c_w1(gspca_dev, ov9655_init[i].reg, +- ov9655_init[i].val) < 0) { +- pr_err("OV9655 sensor initialization failed\n"); +- return -ENODEV; +- } +- } ++ i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ ++ msleep(200); ++ i2c_w1_buf(gspca_dev, ov9655_init, ARRAY_SIZE(ov9655_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("OV9655 sensor initialization failed\n"); ++ + /* disable hflip and vflip */ +- gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); ++ gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP); + sd->hstart = 1; + sd->vstart = 2; +- return 0; + } + +-static int soi968_init_sensor(struct gspca_dev *gspca_dev) ++static void soi968_init_sensor(struct gspca_dev *gspca_dev) + { +- int i; + struct sd *sd = (struct sd *) gspca_dev; + +- for (i = 0; i < ARRAY_SIZE(soi968_init); i++) { +- if (i2c_w1(gspca_dev, soi968_init[i].reg, +- soi968_init[i].val) < 0) { +- pr_err("SOI968 sensor initialization failed\n"); +- return -ENODEV; +- } +- } ++ i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ ++ msleep(200); ++ i2c_w1_buf(gspca_dev, soi968_init, ARRAY_SIZE(soi968_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("SOI968 sensor initialization failed\n"); ++ + /* disable hflip and vflip */ +- gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) +- | (1 << EXPOSURE_IDX); ++ gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP) ++ | (1 << EXPOSURE); + sd->hstart = 60; + sd->vstart = 11; +- return 0; + } + +-static int ov7660_init_sensor(struct gspca_dev *gspca_dev) ++static void ov7660_init_sensor(struct gspca_dev *gspca_dev) + { +- int i; + struct sd *sd = (struct sd *) gspca_dev; + +- for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) { +- if (i2c_w1(gspca_dev, ov7660_init[i].reg, +- ov7660_init[i].val) < 0) { +- pr_err("OV7660 sensor initialization failed\n"); +- return -ENODEV; +- } +- } ++ i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ ++ msleep(200); ++ i2c_w1_buf(gspca_dev, ov7660_init, ARRAY_SIZE(ov7660_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("OV7660 sensor initialization failed\n"); + sd->hstart = 3; + sd->vstart = 3; +- return 0; + } + +-static int ov7670_init_sensor(struct gspca_dev *gspca_dev) ++static void ov7670_init_sensor(struct gspca_dev *gspca_dev) + { +- int i; + struct sd *sd = (struct sd *) gspca_dev; + +- for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) { +- if (i2c_w1(gspca_dev, ov7670_init[i].reg, +- ov7670_init[i].val) < 0) { +- pr_err("OV7670 sensor initialization failed\n"); +- return -ENODEV; +- } +- } ++ i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ ++ msleep(200); ++ i2c_w1_buf(gspca_dev, ov7670_init, ARRAY_SIZE(ov7670_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("OV7670 sensor initialization failed\n"); ++ + /* disable hflip and vflip */ +- gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); ++ gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP); + sd->hstart = 0; + sd->vstart = 1; +- return 0; + } + +-static int mt9v_init_sensor(struct gspca_dev *gspca_dev) ++static void mt9v_init_sensor(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- int i; + u16 value; +- int ret; + + sd->i2c_addr = 0x5d; +- ret = i2c_r2(gspca_dev, 0xff, &value); +- if ((ret == 0) && (value == 0x8243)) { +- for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) { +- if (i2c_w2(gspca_dev, mt9v011_init[i].reg, +- mt9v011_init[i].val) < 0) { +- pr_err("MT9V011 sensor initialization failed\n"); +- return -ENODEV; +- } ++ i2c_r2(gspca_dev, 0xff, &value); ++ if (gspca_dev->usb_err >= 0 ++ && value == 0x8243) { ++ i2c_w2_buf(gspca_dev, mt9v011_init, ARRAY_SIZE(mt9v011_init)); ++ if (gspca_dev->usb_err < 0) { ++ pr_err("MT9V011 sensor initialization failed\n"); ++ return; + } + sd->hstart = 2; + sd->vstart = 2; + sd->sensor = SENSOR_MT9V011; + pr_info("MT9V011 sensor detected\n"); +- return 0; ++ return; + } + ++ gspca_dev->usb_err = 0; + sd->i2c_addr = 0x5c; + i2c_w2(gspca_dev, 0x01, 0x0004); +- ret = i2c_r2(gspca_dev, 0xff, &value); +- if ((ret == 0) && (value == 0x823a)) { +- for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) { +- if (i2c_w2(gspca_dev, mt9v111_init[i].reg, +- mt9v111_init[i].val) < 0) { +- pr_err("MT9V111 sensor initialization failed\n"); +- return -ENODEV; +- } ++ i2c_r2(gspca_dev, 0xff, &value); ++ if (gspca_dev->usb_err >= 0 ++ && value == 0x823a) { ++ i2c_w2_buf(gspca_dev, mt9v111_init, ARRAY_SIZE(mt9v111_init)); ++ if (gspca_dev->usb_err < 0) { ++ pr_err("MT9V111 sensor initialization failed\n"); ++ return; + } +- gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) +- | (1 << AUTOGAIN_IDX) +- | (1 << GAIN_IDX); ++ gspca_dev->ctrl_dis = (1 << EXPOSURE) ++ | (1 << AUTOGAIN) ++ | (1 << GAIN); + sd->hstart = 2; + sd->vstart = 2; + sd->sensor = SENSOR_MT9V111; + pr_info("MT9V111 sensor detected\n"); +- return 0; ++ return; + } + ++ gspca_dev->usb_err = 0; + sd->i2c_addr = 0x5d; +- ret = i2c_w2(gspca_dev, 0xf0, 0x0000); +- if (ret < 0) { ++ i2c_w2(gspca_dev, 0xf0, 0x0000); ++ if (gspca_dev->usb_err < 0) { ++ gspca_dev->usb_err = 0; + sd->i2c_addr = 0x48; + i2c_w2(gspca_dev, 0xf0, 0x0000); + } +- ret = i2c_r2(gspca_dev, 0x00, &value); +- if ((ret == 0) && (value == 0x1229)) { +- for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) { +- if (i2c_w2(gspca_dev, mt9v112_init[i].reg, +- mt9v112_init[i].val) < 0) { +- pr_err("MT9V112 sensor initialization failed\n"); +- return -ENODEV; +- } ++ i2c_r2(gspca_dev, 0x00, &value); ++ if (gspca_dev->usb_err >= 0 ++ && value == 0x1229) { ++ i2c_w2_buf(gspca_dev, mt9v112_init, ARRAY_SIZE(mt9v112_init)); ++ if (gspca_dev->usb_err < 0) { ++ pr_err("MT9V112 sensor initialization failed\n"); ++ return; + } + sd->hstart = 6; + sd->vstart = 2; + sd->sensor = SENSOR_MT9V112; + pr_info("MT9V112 sensor detected\n"); +- return 0; ++ return; + } + +- return -ENODEV; ++ gspca_dev->usb_err = -ENODEV; + } + +-static int mt9m112_init_sensor(struct gspca_dev *gspca_dev) ++static void mt9m112_init_sensor(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- int i; +- for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) { +- if (i2c_w2(gspca_dev, mt9m112_init[i].reg, +- mt9m112_init[i].val) < 0) { +- pr_err("MT9M112 sensor initialization failed\n"); +- return -ENODEV; +- } +- } +- gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) +- | (1 << GAIN_IDX); ++ ++ i2c_w2_buf(gspca_dev, mt9m112_init, ARRAY_SIZE(mt9m112_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("MT9M112 sensor initialization failed\n"); ++ ++ gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN) ++ | (1 << GAIN); + sd->hstart = 0; + sd->vstart = 2; +- return 0; + } + +-static int mt9m111_init_sensor(struct gspca_dev *gspca_dev) ++static void mt9m111_init_sensor(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- int i; +- for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) { +- if (i2c_w2(gspca_dev, mt9m111_init[i].reg, +- mt9m111_init[i].val) < 0) { +- pr_err("MT9M111 sensor initialization failed\n"); +- return -ENODEV; +- } +- } +- gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) +- | (1 << GAIN_IDX); ++ ++ i2c_w2_buf(gspca_dev, mt9m111_init, ARRAY_SIZE(mt9m111_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("MT9M111 sensor initialization failed\n"); ++ ++ gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN) ++ | (1 << GAIN); + sd->hstart = 0; + sd->vstart = 2; +- return 0; + } + +-static int mt9m001_init_sensor(struct gspca_dev *gspca_dev) ++static void mt9m001_init_sensor(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- int i; + u16 id; + +- if (i2c_r2(gspca_dev, 0x00, &id) < 0) +- return -EINVAL; ++ i2c_r2(gspca_dev, 0x00, &id); ++ if (gspca_dev->usb_err < 0) ++ return; + + /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ + switch (id) { +@@ -1494,85 +1462,78 @@ static int mt9m001_init_sensor(struct gs + break; + default: + pr_err("No MT9M001 chip detected, ID = %x\n\n", id); +- return -ENODEV; ++ gspca_dev->usb_err = -ENODEV; ++ return; + } + +- for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) { +- if (i2c_w2(gspca_dev, mt9m001_init[i].reg, +- mt9m001_init[i].val) < 0) { +- pr_err("MT9M001 sensor initialization failed\n"); +- return -ENODEV; +- } +- } ++ i2c_w2_buf(gspca_dev, mt9m001_init, ARRAY_SIZE(mt9m001_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("MT9M001 sensor initialization failed\n"); ++ + /* disable hflip and vflip */ +- gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); ++ gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP); + sd->hstart = 1; + sd->vstart = 1; +- return 0; + } + +-static int hv7131r_init_sensor(struct gspca_dev *gspca_dev) ++static void hv7131r_init_sensor(struct gspca_dev *gspca_dev) + { +- int i; + struct sd *sd = (struct sd *) gspca_dev; + +- for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) { +- if (i2c_w1(gspca_dev, hv7131r_init[i].reg, +- hv7131r_init[i].val) < 0) { +- pr_err("HV7131R Sensor initialization failed\n"); +- return -ENODEV; +- } +- } ++ i2c_w1_buf(gspca_dev, hv7131r_init, ARRAY_SIZE(hv7131r_init)); ++ if (gspca_dev->usb_err < 0) ++ pr_err("HV7131R Sensor initialization failed\n"); ++ + sd->hstart = 0; + sd->vstart = 1; +- return 0; + } + +-static int set_cmatrix(struct gspca_dev *gspca_dev) ++static void set_cmatrix(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- s32 hue_coord, hue_index = 180 + sd->hue; ++ int satur; ++ s32 hue_coord, hue_index = 180 + sd->ctrls[HUE].val; + u8 cmatrix[21]; + + memset(cmatrix, 0, sizeof cmatrix); +- cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26; ++ cmatrix[2] = (sd->ctrls[CONTRAST].val * 0x25 / 0x100) + 0x26; + cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25; + cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25; +- cmatrix[18] = sd->brightness - 0x80; ++ cmatrix[18] = sd->ctrls[BRIGHTNESS].val - 0x80; + +- hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8; ++ satur = sd->ctrls[SATURATION].val; ++ hue_coord = (hsv_red_x[hue_index] * satur) >> 8; + cmatrix[6] = hue_coord; + cmatrix[7] = (hue_coord >> 8) & 0x0f; + +- hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8; ++ hue_coord = (hsv_red_y[hue_index] * satur) >> 8; + cmatrix[8] = hue_coord; + cmatrix[9] = (hue_coord >> 8) & 0x0f; + +- hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8; ++ hue_coord = (hsv_green_x[hue_index] * satur) >> 8; + cmatrix[10] = hue_coord; + cmatrix[11] = (hue_coord >> 8) & 0x0f; + +- hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8; ++ hue_coord = (hsv_green_y[hue_index] * satur) >> 8; + cmatrix[12] = hue_coord; + cmatrix[13] = (hue_coord >> 8) & 0x0f; + +- hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8; ++ hue_coord = (hsv_blue_x[hue_index] * satur) >> 8; + cmatrix[14] = hue_coord; + cmatrix[15] = (hue_coord >> 8) & 0x0f; + +- hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8; ++ hue_coord = (hsv_blue_y[hue_index] * satur) >> 8; + cmatrix[16] = hue_coord; + cmatrix[17] = (hue_coord >> 8) & 0x0f; + +- return reg_w(gspca_dev, 0x10e1, cmatrix, 21); ++ reg_w(gspca_dev, 0x10e1, cmatrix, 21); + } + +-static int set_gamma(struct gspca_dev *gspca_dev) ++static void set_gamma(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; + u8 gamma[17]; +- u8 gval = sd->gamma * 0xb8 / 0x100; +- ++ u8 gval = sd->ctrls[GAMMA].val * 0xb8 / 0x100; + + gamma[0] = 0x0a; + gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8); +@@ -1592,29 +1553,29 @@ static int set_gamma(struct gspca_dev *g + gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8); + gamma[16] = 0xf5; + +- return reg_w(gspca_dev, 0x1190, gamma, 17); ++ reg_w(gspca_dev, 0x1190, gamma, 17); + } + +-static int set_redblue(struct gspca_dev *gspca_dev) ++static void set_redblue(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- reg_w1(gspca_dev, 0x118c, sd->red); +- reg_w1(gspca_dev, 0x118f, sd->blue); +- return 0; ++ ++ reg_w1(gspca_dev, 0x118c, sd->ctrls[RED].val); ++ reg_w1(gspca_dev, 0x118f, sd->ctrls[BLUE].val); + } + +-static int set_hvflip(struct gspca_dev *gspca_dev) ++static void set_hvflip(struct gspca_dev *gspca_dev) + { + u8 value, tslb, hflip, vflip; + u16 value2; + struct sd *sd = (struct sd *) gspca_dev; + + if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) { +- hflip = !sd->hflip; +- vflip = !sd->vflip; ++ hflip = !sd->ctrls[HFLIP].val; ++ vflip = !sd->ctrls[VFLIP].val; + } else { +- hflip = sd->hflip; +- vflip = sd->vflip; ++ hflip = sd->ctrls[HFLIP].val; ++ vflip = sd->ctrls[VFLIP].val; + } + + switch (sd->sensor) { +@@ -1625,8 +1586,9 @@ static int set_hvflip(struct gspca_dev * + if (vflip) { + value |= 0x10; + sd->vstart = 2; +- } else ++ } else { + sd->vstart = 3; ++ } + reg_w1(gspca_dev, 0x1182, sd->vstart); + i2c_w1(gspca_dev, 0x1e, value); + break; +@@ -1674,13 +1636,15 @@ static int set_hvflip(struct gspca_dev * + i2c_w1(gspca_dev, 0x01, value); + break; + } +- return 0; + } + +-static int set_exposure(struct gspca_dev *gspca_dev) ++static void set_exposure(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; + u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e}; ++ int expo; ++ ++ expo = sd->ctrls[EXPOSURE].val; + switch (sd->sensor) { + case SENSOR_OV7660: + case SENSOR_OV7670: +@@ -1688,35 +1652,37 @@ static int set_exposure(struct gspca_dev + case SENSOR_OV9650: + exp[0] |= (3 << 4); + exp[2] = 0x2d; +- exp[3] = sd->exposure & 0xff; +- exp[4] = sd->exposure >> 8; ++ exp[3] = expo; ++ exp[4] = expo >> 8; + break; + case SENSOR_MT9M001: + case SENSOR_MT9V112: + case SENSOR_MT9V011: + exp[0] |= (3 << 4); + exp[2] = 0x09; +- exp[3] = sd->exposure >> 8; +- exp[4] = sd->exposure & 0xff; ++ exp[3] = expo >> 8; ++ exp[4] = expo; + break; + case SENSOR_HV7131R: + exp[0] |= (4 << 4); + exp[2] = 0x25; +- exp[3] = (sd->exposure >> 5) & 0xff; +- exp[4] = (sd->exposure << 3) & 0xff; ++ exp[3] = expo >> 5; ++ exp[4] = expo << 3; + exp[5] = 0; + break; + default: +- return 0; ++ return; + } + i2c_w(gspca_dev, exp); +- return 0; + } + +-static int set_gain(struct gspca_dev *gspca_dev) ++static void set_gain(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; + u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d}; ++ int g; ++ ++ g = sd->ctrls[GAIN].val; + switch (sd->sensor) { + case SENSOR_OV7660: + case SENSOR_OV7670: +@@ -1724,238 +1690,50 @@ static int set_gain(struct gspca_dev *gs + case SENSOR_OV9655: + case SENSOR_OV9650: + gain[0] |= (2 << 4); +- gain[3] = ov_gain[sd->gain]; ++ gain[3] = ov_gain[g]; + break; + case SENSOR_MT9V011: + gain[0] |= (3 << 4); + gain[2] = 0x35; +- gain[3] = micron1_gain[sd->gain] >> 8; +- gain[4] = micron1_gain[sd->gain] & 0xff; ++ gain[3] = micron1_gain[g] >> 8; ++ gain[4] = micron1_gain[g]; + break; + case SENSOR_MT9V112: + gain[0] |= (3 << 4); + gain[2] = 0x2f; +- gain[3] = micron1_gain[sd->gain] >> 8; +- gain[4] = micron1_gain[sd->gain] & 0xff; ++ gain[3] = micron1_gain[g] >> 8; ++ gain[4] = micron1_gain[g]; + break; + case SENSOR_MT9M001: + gain[0] |= (3 << 4); + gain[2] = 0x2f; +- gain[3] = micron2_gain[sd->gain] >> 8; +- gain[4] = micron2_gain[sd->gain] & 0xff; ++ gain[3] = micron2_gain[g] >> 8; ++ gain[4] = micron2_gain[g]; + break; + case SENSOR_HV7131R: + gain[0] |= (2 << 4); + gain[2] = 0x30; +- gain[3] = hv7131r_gain[sd->gain]; ++ gain[3] = hv7131r_gain[g]; + break; + default: +- return 0; ++ return; + } + i2c_w(gspca_dev, gain); +- return 0; +-} +- +-static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->brightness = val; +- if (gspca_dev->streaming) +- return set_cmatrix(gspca_dev); +- return 0; +-} +- +-static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->brightness; +- return 0; +-} +- +- +-static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->contrast = val; +- if (gspca_dev->streaming) +- return set_cmatrix(gspca_dev); +- return 0; +-} +- +-static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->contrast; +- return 0; +-} +- +-static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->saturation = val; +- if (gspca_dev->streaming) +- return set_cmatrix(gspca_dev); +- return 0; +-} +- +-static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->saturation; +- return 0; +-} +- +-static int sd_sethue(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->hue = val; +- if (gspca_dev->streaming) +- return set_cmatrix(gspca_dev); +- return 0; +-} +- +-static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->hue; +- return 0; +-} +- +-static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->gamma = val; +- if (gspca_dev->streaming) +- return set_gamma(gspca_dev); +- return 0; +-} +- +-static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->gamma; +- return 0; +-} +- +-static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->red = val; +- if (gspca_dev->streaming) +- return set_redblue(gspca_dev); +- return 0; +-} +- +-static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->red; +- return 0; +-} +- +-static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->blue = val; +- if (gspca_dev->streaming) +- return set_redblue(gspca_dev); +- return 0; +-} +- +-static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->blue; +- return 0; +-} +- +-static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->hflip = val; +- if (gspca_dev->streaming) +- return set_hvflip(gspca_dev); +- return 0; +-} +- +-static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->hflip; +- return 0; +-} +- +-static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->vflip = val; +- if (gspca_dev->streaming) +- return set_hvflip(gspca_dev); +- return 0; +-} +- +-static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->vflip; +- return 0; +-} +- +-static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->exposure = val; +- if (gspca_dev->streaming) +- return set_exposure(gspca_dev); +- return 0; +-} +- +-static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->exposure; +- return 0; +-} +- +-static int sd_setgain(struct gspca_dev *gspca_dev, s32 val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- +- sd->gain = val; +- if (gspca_dev->streaming) +- return set_gain(gspca_dev); +- return 0; +-} +- +-static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->gain; +- return 0; + } + +-static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val) ++static void set_quality(struct gspca_dev *gspca_dev) + { + struct sd *sd = (struct sd *) gspca_dev; +- sd->auto_exposure = val; +- return 0; +-} + +-static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val) +-{ +- struct sd *sd = (struct sd *) gspca_dev; +- *val = sd->auto_exposure; +- return 0; ++ jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); ++ reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */ ++ reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */ ++ reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64); ++ reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64); ++ reg_w1(gspca_dev, 0x1061, 0x03); /* restart transfer */ ++ reg_w1(gspca_dev, 0x10e0, sd->fmt); ++ sd->fmt ^= 0x0c; /* invert QTAB use + write */ ++ reg_w1(gspca_dev, 0x10e0, sd->fmt); + } + + #ifdef CONFIG_VIDEO_ADV_DEBUG +@@ -1963,28 +1741,26 @@ static int sd_dbg_g_register(struct gspc + struct v4l2_dbg_register *reg) + { + struct sd *sd = (struct sd *) gspca_dev; ++ + switch (reg->match.type) { + case V4L2_CHIP_MATCH_HOST: + if (reg->match.addr != 0) + return -EINVAL; + if (reg->reg < 0x1000 || reg->reg > 0x11ff) + return -EINVAL; +- if (reg_r(gspca_dev, reg->reg, 1) < 0) +- return -EINVAL; ++ reg_r(gspca_dev, reg->reg, 1); + reg->val = gspca_dev->usb_buf[0]; +- return 0; ++ return gspca_dev->usb_err; + case V4L2_CHIP_MATCH_I2C_ADDR: + if (reg->match.addr != sd->i2c_addr) + return -EINVAL; + if (sd->sensor >= SENSOR_MT9V011 && + sd->sensor <= SENSOR_MT9M112) { +- if (i2c_r2(gspca_dev, reg->reg, (u16 *)®->val) < 0) +- return -EINVAL; ++ i2c_r2(gspca_dev, reg->reg, (u16 *) ®->val); + } else { +- if (i2c_r1(gspca_dev, reg->reg, (u8 *)®->val) < 0) +- return -EINVAL; ++ i2c_r1(gspca_dev, reg->reg, (u8 *) ®->val); + } +- return 0; ++ return gspca_dev->usb_err; + } + return -EINVAL; + } +@@ -1993,27 +1769,25 @@ static int sd_dbg_s_register(struct gspc + struct v4l2_dbg_register *reg) + { + struct sd *sd = (struct sd *) gspca_dev; ++ + switch (reg->match.type) { + case V4L2_CHIP_MATCH_HOST: + if (reg->match.addr != 0) + return -EINVAL; + if (reg->reg < 0x1000 || reg->reg > 0x11ff) + return -EINVAL; +- if (reg_w1(gspca_dev, reg->reg, reg->val) < 0) +- return -EINVAL; +- return 0; ++ reg_w1(gspca_dev, reg->reg, reg->val); ++ return gspca_dev->usb_err; + case V4L2_CHIP_MATCH_I2C_ADDR: + if (reg->match.addr != sd->i2c_addr) + return -EINVAL; + if (sd->sensor >= SENSOR_MT9V011 && + sd->sensor <= SENSOR_MT9M112) { +- if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0) +- return -EINVAL; ++ i2c_w2(gspca_dev, reg->reg, reg->val); + } else { +- if (i2c_w1(gspca_dev, reg->reg, reg->val) < 0) +- return -EINVAL; ++ i2c_w1(gspca_dev, reg->reg, reg->val); + } +- return 0; ++ return gspca_dev->usb_err; + } + return -EINVAL; + } +@@ -2050,9 +1824,9 @@ static int sd_config(struct gspca_dev *g + cam = &gspca_dev->cam; + cam->needs_full_bandwidth = 1; + +- sd->sensor = (id->driver_info >> 8) & 0xff; +- sd->i2c_addr = id->driver_info & 0xff; +- sd->flags = (id->driver_info >> 16) & 0xff; ++ sd->sensor = id->driver_info >> 8; ++ sd->i2c_addr = id->driver_info; ++ sd->flags = id->driver_info >> 16; + + switch (sd->sensor) { + case SENSOR_MT9M112: +@@ -2076,21 +1850,9 @@ static int sd_config(struct gspca_dev *g + sd->older_step = 0; + sd->exposure_step = 16; + +- sd->brightness = BRIGHTNESS_DEFAULT; +- sd->contrast = CONTRAST_DEFAULT; +- sd->saturation = SATURATION_DEFAULT; +- sd->hue = HUE_DEFAULT; +- sd->gamma = GAMMA_DEFAULT; +- sd->red = RED_DEFAULT; +- sd->blue = BLUE_DEFAULT; +- +- sd->hflip = HFLIP_DEFAULT; +- sd->vflip = VFLIP_DEFAULT; +- sd->exposure = EXPOSURE_DEFAULT; +- sd->gain = GAIN_DEFAULT; +- sd->auto_exposure = AUTO_EXPOSURE_DEFAULT; ++ gspca_dev->cam.ctrls = sd->ctrls; + +- sd->quality = 95; ++ INIT_WORK(&sd->work, qual_upd); + + return 0; + } +@@ -2105,9 +1867,10 @@ static int sd_init(struct gspca_dev *gsp + + for (i = 0; i < ARRAY_SIZE(bridge_init); i++) { + value = bridge_init[i][1]; +- if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) { ++ reg_w(gspca_dev, bridge_init[i][0], &value, 1); ++ if (gspca_dev->usb_err < 0) { + pr_err("Device initialization failed\n"); +- return -ENODEV; ++ return gspca_dev->usb_err; + } + } + +@@ -2116,72 +1879,85 @@ static int sd_init(struct gspca_dev *gsp + else + reg_w1(gspca_dev, 0x1006, 0x20); + +- if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) { ++ reg_w(gspca_dev, 0x10c0, i2c_init, 9); ++ if (gspca_dev->usb_err < 0) { + pr_err("Device initialization failed\n"); +- return -ENODEV; ++ return gspca_dev->usb_err; + } + + switch (sd->sensor) { + case SENSOR_OV9650: +- if (ov9650_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ ov9650_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + pr_info("OV9650 sensor detected\n"); + break; + case SENSOR_OV9655: +- if (ov9655_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ ov9655_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + pr_info("OV9655 sensor detected\n"); + break; + case SENSOR_SOI968: +- if (soi968_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ soi968_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + pr_info("SOI968 sensor detected\n"); + break; + case SENSOR_OV7660: +- if (ov7660_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ ov7660_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + pr_info("OV7660 sensor detected\n"); + break; + case SENSOR_OV7670: +- if (ov7670_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ ov7670_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + pr_info("OV7670 sensor detected\n"); + break; + case SENSOR_MT9VPRB: +- if (mt9v_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ mt9v_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; ++ pr_info("MT9VPRB sensor detected\n"); + break; + case SENSOR_MT9M111: +- if (mt9m111_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ mt9m111_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + pr_info("MT9M111 sensor detected\n"); + break; + case SENSOR_MT9M112: +- if (mt9m112_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ mt9m112_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + pr_info("MT9M112 sensor detected\n"); + break; + case SENSOR_MT9M001: +- if (mt9m001_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ mt9m001_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + break; + case SENSOR_HV7131R: +- if (hv7131r_init_sensor(gspca_dev) < 0) +- return -ENODEV; ++ hv7131r_init_sensor(gspca_dev); ++ if (gspca_dev->usb_err < 0) ++ break; + pr_info("HV7131R sensor detected\n"); + break; + default: +- pr_info("Unsupported Sensor\n"); +- return -ENODEV; ++ pr_err("Unsupported sensor\n"); ++ gspca_dev->usb_err = -ENODEV; + } + +- return 0; ++ return gspca_dev->usb_err; + } + + static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode) + { + struct sd *sd = (struct sd *) gspca_dev; + u8 value; ++ + switch (sd->sensor) { + case SENSOR_SOI968: + if (mode & MODE_SXGA) { +@@ -2264,6 +2040,7 @@ static int sd_isoc_init(struct gspca_dev + break; + default: /* >= 640x480 */ + gspca_dev->alt = 9; ++ break; + } + } + +@@ -2290,14 +2067,15 @@ static int sd_start(struct gspca_dev *gs + + jpeg_define(sd->jpeg_hdr, height, width, + 0x21); +- jpeg_set_qual(sd->jpeg_hdr, sd->quality); ++ jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); + + if (mode & MODE_RAW) + fmt = 0x2d; + else if (mode & MODE_JPEG) +- fmt = 0x2c; ++ fmt = 0x24; + else + fmt = 0x2f; /* YUV 420 */ ++ sd->fmt = fmt; + + switch (mode & SCALE_MASK) { + case SCALE_1280x1024: +@@ -2334,18 +2112,37 @@ static int sd_start(struct gspca_dev *gs + set_hvflip(gspca_dev); + + reg_w1(gspca_dev, 0x1007, 0x20); ++ reg_w1(gspca_dev, 0x1061, 0x03); + +- reg_r(gspca_dev, 0x1061, 1); +- reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02); +- return 0; ++ /* if JPEG, prepare the compression quality update */ ++ if (mode & MODE_JPEG) { ++ sd->pktsz = sd->npkt = 0; ++ sd->nchg = 0; ++ sd->work_thread = ++ create_singlethread_workqueue(KBUILD_MODNAME); ++ } ++ ++ return gspca_dev->usb_err; + } + + static void sd_stopN(struct gspca_dev *gspca_dev) + { + reg_w1(gspca_dev, 0x1007, 0x00); ++ reg_w1(gspca_dev, 0x1061, 0x01); ++} + +- reg_r(gspca_dev, 0x1061, 1); +- reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02); ++/* called on streamoff with alt==0 and on disconnect */ ++/* the usb_lock is held at entry - restore on exit */ ++static void sd_stop0(struct gspca_dev *gspca_dev) ++{ ++ struct sd *sd = (struct sd *) gspca_dev; ++ ++ if (sd->work_thread != NULL) { ++ mutex_unlock(&gspca_dev->usb_lock); ++ destroy_workqueue(sd->work_thread); ++ mutex_lock(&gspca_dev->usb_lock); ++ sd->work_thread = NULL; ++ } + } + + static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum) +@@ -2359,15 +2156,15 @@ static void do_autoexposure(struct gspca + * and exposure steps + */ + if (avg_lum < MIN_AVG_LUM) { +- if (sd->exposure > 0x1770) ++ if (sd->ctrls[EXPOSURE].val > 0x1770) + return; + +- new_exp = sd->exposure + sd->exposure_step; ++ new_exp = sd->ctrls[EXPOSURE].val + sd->exposure_step; + if (new_exp > 0x1770) + new_exp = 0x1770; + if (new_exp < 0x10) + new_exp = 0x10; +- sd->exposure = new_exp; ++ sd->ctrls[EXPOSURE].val = new_exp; + set_exposure(gspca_dev); + + sd->older_step = sd->old_step; +@@ -2379,14 +2176,14 @@ static void do_autoexposure(struct gspca + sd->exposure_step += 2; + } + if (avg_lum > MAX_AVG_LUM) { +- if (sd->exposure < 0x10) ++ if (sd->ctrls[EXPOSURE].val < 0x10) + return; +- new_exp = sd->exposure - sd->exposure_step; ++ new_exp = sd->ctrls[EXPOSURE].val - sd->exposure_step; + if (new_exp > 0x1700) + new_exp = 0x1770; + if (new_exp < 0x10) + new_exp = 0x10; +- sd->exposure = new_exp; ++ sd->ctrls[EXPOSURE].val = new_exp; + set_exposure(gspca_dev); + sd->older_step = sd->old_step; + sd->old_step = 0; +@@ -2403,14 +2200,14 @@ static void do_autogain(struct gspca_dev + struct sd *sd = (struct sd *) gspca_dev; + + if (avg_lum < MIN_AVG_LUM) { +- if (sd->gain + 1 <= 28) { +- sd->gain++; ++ if (sd->ctrls[GAIN].val + 1 <= 28) { ++ sd->ctrls[GAIN].val++; + set_gain(gspca_dev); + } + } + if (avg_lum > MAX_AVG_LUM) { +- if (sd->gain > 0) { +- sd->gain--; ++ if (sd->ctrls[GAIN].val > 0) { ++ sd->ctrls[GAIN].val--; + set_gain(gspca_dev); + } + } +@@ -2421,7 +2218,7 @@ static void sd_dqcallback(struct gspca_d + struct sd *sd = (struct sd *) gspca_dev; + int avg_lum; + +- if (!sd->auto_exposure) ++ if (!sd->ctrls[AUTOGAIN].val) + return; + + avg_lum = atomic_read(&sd->avg_lum); +@@ -2431,33 +2228,92 @@ static void sd_dqcallback(struct gspca_d + do_autoexposure(gspca_dev, avg_lum); + } + ++/* JPEG quality update */ ++/* This function is executed from a work queue. */ ++static void qual_upd(struct work_struct *work) ++{ ++ struct sd *sd = container_of(work, struct sd, work); ++ struct gspca_dev *gspca_dev = &sd->gspca_dev; ++ ++ mutex_lock(&gspca_dev->usb_lock); ++ PDEBUG(D_STREAM, "qual_upd %d%%", sd->ctrls[QUALITY].val); ++ set_quality(gspca_dev); ++ mutex_unlock(&gspca_dev->usb_lock); ++} ++ + #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, + u8 *data, /* interrupt packet */ + int len) /* interrupt packet length */ + { + struct sd *sd = (struct sd *) gspca_dev; +- int ret = -EINVAL; ++ + if (!(sd->flags & HAS_NO_BUTTON) && len == 1) { +- input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); +- input_sync(gspca_dev->input_dev); +- input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); +- input_sync(gspca_dev->input_dev); +- ret = 0; ++ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); ++ input_sync(gspca_dev->input_dev); ++ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); ++ input_sync(gspca_dev->input_dev); ++ return 0; + } +- return ret; ++ return -EINVAL; + } + #endif + ++/* check the JPEG compression */ ++static void transfer_check(struct gspca_dev *gspca_dev, ++ u8 *data) ++{ ++ struct sd *sd = (struct sd *) gspca_dev; ++ int new_qual, r; ++ ++ new_qual = 0; ++ ++ /* if USB error, discard the frame and decrease the quality */ ++ if (data[6] & 0x08) { /* USB FIFO full */ ++ gspca_dev->last_packet_type = DISCARD_PACKET; ++ new_qual = -5; ++ } else { ++ ++ /* else, compute the filling rate and a new JPEG quality */ ++ r = (sd->pktsz * 100) / ++ (sd->npkt * ++ gspca_dev->urb[0]->iso_frame_desc[0].length); ++ if (r >= 85) ++ new_qual = -3; ++ else if (r < 75) ++ new_qual = 2; ++ } ++ if (new_qual != 0) { ++ sd->nchg += new_qual; ++ if (sd->nchg < -6 || sd->nchg >= 12) { ++ sd->nchg = 0; ++ new_qual += sd->ctrls[QUALITY].val; ++ if (new_qual < QUALITY_MIN) ++ new_qual = QUALITY_MIN; ++ else if (new_qual > QUALITY_MAX) ++ new_qual = QUALITY_MAX; ++ if (new_qual != sd->ctrls[QUALITY].val) { ++ sd->ctrls[QUALITY].val = new_qual; ++ queue_work(sd->work_thread, &sd->work); ++ } ++ } ++ } else { ++ sd->nchg = 0; ++ } ++ sd->pktsz = sd->npkt = 0; ++} ++ + static void sd_pkt_scan(struct gspca_dev *gspca_dev, + u8 *data, /* isoc packet */ + int len) /* iso packet length */ + { + struct sd *sd = (struct sd *) gspca_dev; +- int avg_lum; ++ int avg_lum, is_jpeg; + static u8 frame_header[] = + {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; +- if (len == 64 && memcmp(data, frame_header, 6) == 0) { ++ ++ is_jpeg = (sd->fmt & 0x03) == 0; ++ if (len >= 64 && memcmp(data, frame_header, 6) == 0) { + avg_lum = ((data[35] >> 2) & 3) | + (data[20] << 2) | + (data[19] << 10); +@@ -2484,12 +2340,18 @@ static void sd_pkt_scan(struct gspca_dev + (data[33] << 10); + avg_lum >>= 9; + atomic_set(&sd->avg_lum, avg_lum); ++ ++ if (is_jpeg) ++ transfer_check(gspca_dev, data); ++ + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); +- return; ++ len -= 64; ++ if (len == 0) ++ return; ++ data += 64; + } + if (gspca_dev->last_packet_type == LAST_PACKET) { +- if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv +- & MODE_JPEG) { ++ if (is_jpeg) { + gspca_frame_add(gspca_dev, FIRST_PACKET, + sd->jpeg_hdr, JPEG_HDR_SZ); + gspca_frame_add(gspca_dev, INTER_PACKET, +@@ -2499,13 +2361,18 @@ static void sd_pkt_scan(struct gspca_dev + data, len); + } + } else { ++ /* if JPEG, count the packets and their size */ ++ if (is_jpeg) { ++ sd->npkt++; ++ sd->pktsz += len; ++ } + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); + } + } + + /* sub-driver description */ + static const struct sd_desc sd_desc = { +- .name = MODULE_NAME, ++ .name = KBUILD_MODNAME, + .ctrls = sd_ctrls, + .nctrls = ARRAY_SIZE(sd_ctrls), + .config = sd_config, +@@ -2513,6 +2380,7 @@ static const struct sd_desc sd_desc = { + .isoc_init = sd_isoc_init, + .start = sd_start, + .stopN = sd_stopN, ++ .stop0 = sd_stop0, + .pkt_scan = sd_pkt_scan, + #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + .int_pkt_scan = sd_int_pkt_scan, +@@ -2581,7 +2449,7 @@ static int sd_probe(struct usb_interface + } + + static struct usb_driver sd_driver = { +- .name = MODULE_NAME, ++ .name = KBUILD_MODNAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-udma.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-udma.c ++++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-udma.c +@@ -57,9 +57,9 @@ int ivtv_udma_fill_sg_list (struct ivtv_ + if (dma->bouncemap[map_offset] == NULL) + return -1; + local_irq_save(flags); +- src = kmap_atomic(dma->map[map_offset], KM_BOUNCE_READ) + offset; ++ src = kmap_atomic(dma->map[map_offset]) + offset; + memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len); +- kunmap_atomic(src, KM_BOUNCE_READ); ++ kunmap_atomic(src); + local_irq_restore(flags); + sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset], len, offset); + } +Index: linux-3.3.x86_64/drivers/media/video/videobuf2-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/videobuf2-core.c ++++ linux-3.3.x86_64/drivers/media/video/videobuf2-core.c +@@ -19,6 +19,9 @@ + #include + #include + ++#include ++#include ++#include + #include + + static int debug; +@@ -1642,32 +1645,46 @@ static int __vb2_cleanup_fileio(struct v + * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor + * will be reported as available for writing. + * ++ * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any ++ * pending events. ++ * + * The return values from this function are intended to be directly returned + * from poll handler in driver. + */ + unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) + { +- unsigned long flags; +- unsigned int ret; ++ struct video_device *vfd = video_devdata(file); ++ unsigned long req_events = poll_requested_events(wait); + struct vb2_buffer *vb = NULL; ++ unsigned int res = 0; ++ unsigned long flags; ++ ++ if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { ++ struct v4l2_fh *fh = file->private_data; ++ ++ if (v4l2_event_pending(fh)) ++ res = POLLPRI; ++ else if (req_events & POLLPRI) ++ poll_wait(file, &fh->wait, wait); ++ } + + /* + * Start file I/O emulator only if streaming API has not been used yet. + */ + if (q->num_buffers == 0 && q->fileio == NULL) { +- if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ)) { +- ret = __vb2_init_fileio(q, 1); +- if (ret) +- return POLLERR; ++ if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) && ++ (req_events & (POLLIN | POLLRDNORM))) { ++ if (__vb2_init_fileio(q, 1)) ++ return res | POLLERR; + } +- if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE)) { +- ret = __vb2_init_fileio(q, 0); +- if (ret) +- return POLLERR; ++ if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE) && ++ (req_events & (POLLOUT | POLLWRNORM))) { ++ if (__vb2_init_fileio(q, 0)) ++ return res | POLLERR; + /* + * Write to OUTPUT queue can be done immediately. + */ +- return POLLOUT | POLLWRNORM; ++ return res | POLLOUT | POLLWRNORM; + } + } + +@@ -1675,7 +1692,7 @@ unsigned int vb2_poll(struct vb2_queue * + * There is nothing to wait for if no buffers have already been queued. + */ + if (list_empty(&q->queued_list)) +- return POLLERR; ++ return res | POLLERR; + + poll_wait(file, &q->done_wq, wait); + +@@ -1690,10 +1707,11 @@ unsigned int vb2_poll(struct vb2_queue * + + if (vb && (vb->state == VB2_BUF_STATE_DONE + || vb->state == VB2_BUF_STATE_ERROR)) { +- return (V4L2_TYPE_IS_OUTPUT(q->type)) ? POLLOUT | POLLWRNORM : +- POLLIN | POLLRDNORM; ++ return (V4L2_TYPE_IS_OUTPUT(q->type)) ? ++ res | POLLOUT | POLLWRNORM : ++ res | POLLIN | POLLRDNORM; + } +- return 0; ++ return res; + } + EXPORT_SYMBOL_GPL(vb2_poll); + +Index: linux-3.3.x86_64/drivers/media/video/videobuf-core.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/videobuf-core.c ++++ linux-3.3.x86_64/drivers/media/video/videobuf-core.c +@@ -1129,6 +1129,7 @@ unsigned int videobuf_poll_stream(struct + struct videobuf_queue *q, + poll_table *wait) + { ++ unsigned long req_events = poll_requested_events(wait); + struct videobuf_buffer *buf = NULL; + unsigned int rc = 0; + +@@ -1137,7 +1138,7 @@ unsigned int videobuf_poll_stream(struct + if (!list_empty(&q->stream)) + buf = list_entry(q->stream.next, + struct videobuf_buffer, stream); +- } else { ++ } else if (req_events & (POLLIN | POLLRDNORM)) { + if (!q->reading) + __videobuf_read_start(q); + if (!q->reading) { +Index: linux-3.3.x86_64/drivers/media/video/pwc/pwc-if.c +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/video/pwc/pwc-if.c ++++ linux-3.3.x86_64/drivers/media/video/pwc/pwc-if.c +@@ -625,10 +625,19 @@ static ssize_t pwc_video_read(struct fil + static unsigned int pwc_video_poll(struct file *file, poll_table *wait) + { + struct pwc_device *pdev = video_drvdata(file); ++ unsigned long req_events = poll_requested_events(wait); + + if (!pdev->udev) + return POLL_ERR; + ++ if ((req_events & (POLLIN | POLLRDNORM)) && ++ pdev->vb_queue.num_buffers == 0 && ++ !pdev->iso_init) { ++ /* This poll will start a read stream, check capt_file */ ++ if (pwc_test_n_set_capt_file(pdev, file)) ++ return POLL_ERR; ++ } ++ + return vb2_poll(&pdev->vb_queue, file, wait); + } + +Index: linux-3.3.x86_64/drivers/media/common/tuners/Kconfig +=================================================================== +--- linux-3.3.x86_64.orig/drivers/media/common/tuners/Kconfig ++++ linux-3.3.x86_64/drivers/media/common/tuners/Kconfig +@@ -204,6 +204,13 @@ config MEDIA_TUNER_TDA18218 + help + NXP TDA18218 silicon tuner driver. + ++config MEDIA_TUNER_FC0011 ++ tristate "Fitipower FC0011 silicon tuner" ++ depends on VIDEO_MEDIA && I2C ++ default m if MEDIA_TUNER_CUSTOMISE ++ help ++ Fitipower FC0011 silicon tuner driver. ++ + config MEDIA_TUNER_TDA18212 + tristate "NXP TDA18212 silicon tuner" + depends on VIDEO_MEDIA && I2C +@@ -211,4 +218,10 @@ config MEDIA_TUNER_TDA18212 + help + NXP TDA18212 silicon tuner driver. + ++config MEDIA_TUNER_TUA9001 ++ tristate "Infineon TUA 9001 silicon tuner" ++ depends on VIDEO_MEDIA && I2C ++ default m if MEDIA_TUNER_CUSTOMISE ++ help ++ Infineon TUA 9001 silicon tuner driver. + endmenu +Index: linux-3.3.x86_64/drivers/media/common/tuners/tua9001.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/common/tuners/tua9001.c +@@ -0,0 +1,215 @@ ++/* ++ * Infineon TUA 9001 silicon tuner driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include "tua9001.h" ++#include "tua9001_priv.h" ++ ++/* write register */ ++static int tua9001_wr_reg(struct tua9001_priv *priv, u8 reg, u16 val) ++{ ++ int ret; ++ u8 buf[3] = { reg, (val >> 8) & 0xff, (val >> 0) & 0xff }; ++ struct i2c_msg msg[1] = { ++ { ++ .addr = priv->cfg->i2c_addr, ++ .flags = 0, ++ .len = sizeof(buf), ++ .buf = buf, ++ } ++ }; ++ ++ ret = i2c_transfer(priv->i2c, msg, 1); ++ if (ret == 1) { ++ ret = 0; ++ } else { ++ printk(KERN_WARNING "%s: I2C wr failed=%d reg=%02x\n", ++ __func__, ret, reg); ++ ret = -EREMOTEIO; ++ } ++ ++ return ret; ++} ++ ++static int tua9001_release(struct dvb_frontend *fe) ++{ ++ kfree(fe->tuner_priv); ++ fe->tuner_priv = NULL; ++ ++ return 0; ++} ++ ++static int tua9001_init(struct dvb_frontend *fe) ++{ ++ struct tua9001_priv *priv = fe->tuner_priv; ++ int ret = 0; ++ u8 i; ++ struct reg_val data[] = { ++ { 0x1e, 0x6512 }, ++ { 0x25, 0xb888 }, ++ { 0x39, 0x5460 }, ++ { 0x3b, 0x00c0 }, ++ { 0x3a, 0xf000 }, ++ { 0x08, 0x0000 }, ++ { 0x32, 0x0030 }, ++ { 0x41, 0x703a }, ++ { 0x40, 0x1c78 }, ++ { 0x2c, 0x1c00 }, ++ { 0x36, 0xc013 }, ++ { 0x37, 0x6f18 }, ++ { 0x27, 0x0008 }, ++ { 0x2a, 0x0001 }, ++ { 0x34, 0x0a40 }, ++ }; ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */ ++ ++ for (i = 0; i < ARRAY_SIZE(data); i++) { ++ ret = tua9001_wr_reg(priv, data[i].reg, data[i].val); ++ if (ret) ++ break; ++ } ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */ ++ ++ if (ret < 0) ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int tua9001_set_params(struct dvb_frontend *fe) ++{ ++ struct tua9001_priv *priv = fe->tuner_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret, i; ++ u16 val; ++ u32 frequency; ++ struct reg_val data[2]; ++ ++ pr_debug("%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n", ++ __func__, c->delivery_system, c->frequency, ++ c->bandwidth_hz); ++ ++ switch (c->delivery_system) { ++ case SYS_DVBT: ++ switch (c->bandwidth_hz) { ++ case 8000000: ++ val = 0x0000; ++ break; ++ case 7000000: ++ val = 0x1000; ++ break; ++ case 6000000: ++ val = 0x2000; ++ break; ++ case 5000000: ++ val = 0x3000; ++ break; ++ default: ++ ret = -EINVAL; ++ goto err; ++ } ++ break; ++ default: ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ data[0].reg = 0x04; ++ data[0].val = val; ++ ++ frequency = (c->frequency - 150000000); ++ frequency /= 100; ++ frequency *= 48; ++ frequency /= 10000; ++ ++ data[1].reg = 0x1f; ++ data[1].val = frequency; ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */ ++ ++ for (i = 0; i < ARRAY_SIZE(data); i++) { ++ ret = tua9001_wr_reg(priv, data[i].reg, data[i].val); ++ if (ret < 0) ++ break; ++ } ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */ ++ ++err: ++ if (ret < 0) ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int tua9001_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) ++{ ++ *frequency = 0; /* Zero-IF */ ++ ++ return 0; ++} ++ ++static const struct dvb_tuner_ops tua9001_tuner_ops = { ++ .info = { ++ .name = "Infineon TUA 9001", ++ ++ .frequency_min = 170000000, ++ .frequency_max = 862000000, ++ .frequency_step = 0, ++ }, ++ ++ .release = tua9001_release, ++ ++ .init = tua9001_init, ++ .set_params = tua9001_set_params, ++ ++ .get_if_frequency = tua9001_get_if_frequency, ++}; ++ ++struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, struct tua9001_config *cfg) ++{ ++ struct tua9001_priv *priv = NULL; ++ ++ priv = kzalloc(sizeof(struct tua9001_priv), GFP_KERNEL); ++ if (priv == NULL) ++ return NULL; ++ ++ priv->cfg = cfg; ++ priv->i2c = i2c; ++ ++ printk(KERN_INFO "Infineon TUA 9001 successfully attached."); ++ ++ memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops, ++ sizeof(struct dvb_tuner_ops)); ++ ++ fe->tuner_priv = priv; ++ return fe; ++} ++EXPORT_SYMBOL(tua9001_attach); ++ ++MODULE_DESCRIPTION("Infineon TUA 9001 silicon tuner driver"); ++MODULE_AUTHOR("Antti Palosaari "); ++MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/common/tuners/tua9001.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/common/tuners/tua9001.h +@@ -0,0 +1,46 @@ ++/* ++ * Infineon TUA 9001 silicon tuner driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef TUA9001_H ++#define TUA9001_H ++ ++#include "dvb_frontend.h" ++ ++struct tua9001_config { ++ /* ++ * I2C address ++ */ ++ u8 i2c_addr; ++}; ++ ++#if defined(CONFIG_MEDIA_TUNER_TUA9001) || \ ++ (defined(CONFIG_MEDIA_TUNER_TUA9001_MODULE) && defined(MODULE)) ++extern struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, struct tua9001_config *cfg); ++#else ++static inline struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, struct tua9001_config *cfg) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif ++ ++#endif +Index: linux-3.3.x86_64/drivers/media/common/tuners/tua9001_priv.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/common/tuners/tua9001_priv.h +@@ -0,0 +1,34 @@ ++/* ++ * Infineon TUA 9001 silicon tuner driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef TUA9001_PRIV_H ++#define TUA9001_PRIV_H ++ ++struct reg_val { ++ u8 reg; ++ u16 val; ++}; ++ ++struct tua9001_priv { ++ struct tua9001_config *cfg; ++ struct i2c_adapter *i2c; ++}; ++ ++#endif +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/af9033.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/af9033.c +@@ -0,0 +1,919 @@ ++/* ++ * Afatech AF9033 demodulator driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * Copyright (C) 2012 Antti Palosaari ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include "af9033_priv.h" ++ ++struct af9033_state { ++ struct i2c_adapter *i2c; ++ struct dvb_frontend fe; ++ struct af9033_config cfg; ++ ++ u32 bandwidth_hz; ++ bool ts_mode_parallel; ++ bool ts_mode_serial; ++}; ++ ++/* write multiple registers */ ++static int af9033_wr_regs(struct af9033_state *state, u32 reg, const u8 *val, ++ int len) ++{ ++ int ret; ++ u8 buf[3 + len]; ++ struct i2c_msg msg[1] = { ++ { ++ .addr = state->cfg.i2c_addr, ++ .flags = 0, ++ .len = sizeof(buf), ++ .buf = buf, ++ } ++ }; ++ ++ buf[0] = (reg >> 16) & 0xff; ++ buf[1] = (reg >> 8) & 0xff; ++ buf[2] = (reg >> 0) & 0xff; ++ memcpy(&buf[3], val, len); ++ ++ ret = i2c_transfer(state->i2c, msg, 1); ++ if (ret == 1) { ++ ret = 0; ++ } else { ++ printk(KERN_WARNING "%s: i2c wr failed=%d reg=%06x len=%d\n", ++ __func__, ret, reg, len); ++ ret = -EREMOTEIO; ++ } ++ ++ return ret; ++} ++ ++/* read multiple registers */ ++static int af9033_rd_regs(struct af9033_state *state, u32 reg, u8 *val, int len) ++{ ++ int ret; ++ u8 buf[3] = { (reg >> 16) & 0xff, (reg >> 8) & 0xff, ++ (reg >> 0) & 0xff }; ++ struct i2c_msg msg[2] = { ++ { ++ .addr = state->cfg.i2c_addr, ++ .flags = 0, ++ .len = sizeof(buf), ++ .buf = buf ++ }, { ++ .addr = state->cfg.i2c_addr, ++ .flags = I2C_M_RD, ++ .len = len, ++ .buf = val ++ } ++ }; ++ ++ ret = i2c_transfer(state->i2c, msg, 2); ++ if (ret == 2) { ++ ret = 0; ++ } else { ++ printk(KERN_WARNING "%s: i2c rd failed=%d reg=%06x len=%d\n", ++ __func__, ret, reg, len); ++ ret = -EREMOTEIO; ++ } ++ ++ return ret; ++} ++ ++ ++/* write single register */ ++static int af9033_wr_reg(struct af9033_state *state, u32 reg, u8 val) ++{ ++ return af9033_wr_regs(state, reg, &val, 1); ++} ++ ++/* read single register */ ++static int af9033_rd_reg(struct af9033_state *state, u32 reg, u8 *val) ++{ ++ return af9033_rd_regs(state, reg, val, 1); ++} ++ ++/* write single register with mask */ ++static int af9033_wr_reg_mask(struct af9033_state *state, u32 reg, u8 val, ++ u8 mask) ++{ ++ int ret; ++ u8 tmp; ++ ++ /* no need for read if whole reg is written */ ++ if (mask != 0xff) { ++ ret = af9033_rd_regs(state, reg, &tmp, 1); ++ if (ret) ++ return ret; ++ ++ val &= mask; ++ tmp &= ~mask; ++ val |= tmp; ++ } ++ ++ return af9033_wr_regs(state, reg, &val, 1); ++} ++ ++/* read single register with mask */ ++static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val, ++ u8 mask) ++{ ++ int ret, i; ++ u8 tmp; ++ ++ ret = af9033_rd_regs(state, reg, &tmp, 1); ++ if (ret) ++ return ret; ++ ++ tmp &= mask; ++ ++ /* find position of the first bit */ ++ for (i = 0; i < 8; i++) { ++ if ((mask >> i) & 0x01) ++ break; ++ } ++ *val = tmp >> i; ++ ++ return 0; ++} ++ ++static u32 af9033_div(u32 a, u32 b, u32 x) ++{ ++ u32 r = 0, c = 0, i; ++ ++ pr_debug("%s: a=%d b=%d x=%d\n", __func__, a, b, x); ++ ++ if (a > b) { ++ c = a / b; ++ a = a - c * b; ++ } ++ ++ for (i = 0; i < x; i++) { ++ if (a >= b) { ++ r += 1; ++ a -= b; ++ } ++ a <<= 1; ++ r <<= 1; ++ } ++ r = (c << (u32)x) + r; ++ ++ pr_debug("%s: a=%d b=%d x=%d r=%d r=%x\n", __func__, a, b, x, r, r); ++ ++ return r; ++} ++ ++static void af9033_release(struct dvb_frontend *fe) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ ++ kfree(state); ++} ++ ++static int af9033_init(struct dvb_frontend *fe) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ int ret, i, len; ++ const struct reg_val *init; ++ u8 buf[4]; ++ u32 adc_cw, clock_cw; ++ struct reg_val_mask tab[] = { ++ { 0x80fb24, 0x00, 0x08 }, ++ { 0x80004c, 0x00, 0xff }, ++ { 0x00f641, state->cfg.tuner, 0xff }, ++ { 0x80f5ca, 0x01, 0x01 }, ++ { 0x80f715, 0x01, 0x01 }, ++ { 0x00f41f, 0x04, 0x04 }, ++ { 0x00f41a, 0x01, 0x01 }, ++ { 0x80f731, 0x00, 0x01 }, ++ { 0x00d91e, 0x00, 0x01 }, ++ { 0x00d919, 0x00, 0x01 }, ++ { 0x80f732, 0x00, 0x01 }, ++ { 0x00d91f, 0x00, 0x01 }, ++ { 0x00d91a, 0x00, 0x01 }, ++ { 0x80f730, 0x00, 0x01 }, ++ { 0x80f778, 0x00, 0xff }, ++ { 0x80f73c, 0x01, 0x01 }, ++ { 0x80f776, 0x00, 0x01 }, ++ { 0x00d8fd, 0x01, 0xff }, ++ { 0x00d830, 0x01, 0xff }, ++ { 0x00d831, 0x00, 0xff }, ++ { 0x00d832, 0x00, 0xff }, ++ { 0x80f985, state->ts_mode_serial, 0x01 }, ++ { 0x80f986, state->ts_mode_parallel, 0x01 }, ++ { 0x00d827, 0x00, 0xff }, ++ { 0x00d829, 0x00, 0xff }, ++ }; ++ ++ /* program clock control */ ++ clock_cw = af9033_div(state->cfg.clock, 1000000ul, 19ul); ++ buf[0] = (clock_cw >> 0) & 0xff; ++ buf[1] = (clock_cw >> 8) & 0xff; ++ buf[2] = (clock_cw >> 16) & 0xff; ++ buf[3] = (clock_cw >> 24) & 0xff; ++ ++ pr_debug("%s: clock=%d clock_cw=%08x\n", __func__, state->cfg.clock, ++ clock_cw); ++ ++ ret = af9033_wr_regs(state, 0x800025, buf, 4); ++ if (ret < 0) ++ goto err; ++ ++ /* program ADC control */ ++ for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { ++ if (clock_adc_lut[i].clock == state->cfg.clock) ++ break; ++ } ++ ++ adc_cw = af9033_div(clock_adc_lut[i].adc, 1000000ul, 19ul); ++ buf[0] = (adc_cw >> 0) & 0xff; ++ buf[1] = (adc_cw >> 8) & 0xff; ++ buf[2] = (adc_cw >> 16) & 0xff; ++ ++ pr_debug("%s: adc=%d adc_cw=%06x\n", __func__, clock_adc_lut[i].adc, ++ adc_cw); ++ ++ ret = af9033_wr_regs(state, 0x80f1cd, buf, 3); ++ if (ret < 0) ++ goto err; ++ ++ /* program register table */ ++ for (i = 0; i < ARRAY_SIZE(tab); i++) { ++ ret = af9033_wr_reg_mask(state, tab[i].reg, tab[i].val, ++ tab[i].mask); ++ if (ret < 0) ++ goto err; ++ } ++ ++ /* settings for TS interface */ ++ if (state->cfg.ts_mode == AF9033_TS_MODE_USB) { ++ ret = af9033_wr_reg_mask(state, 0x80f9a5, 0x00, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x01, 0x01); ++ if (ret < 0) ++ goto err; ++ } else { ++ ret = af9033_wr_reg_mask(state, 0x80f990, 0x00, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x00, 0x01); ++ if (ret < 0) ++ goto err; ++ } ++ ++ /* load OFSM settings */ ++ pr_debug("%s: load ofsm settings\n", __func__); ++ len = ARRAY_SIZE(ofsm_init); ++ init = ofsm_init; ++ for (i = 0; i < len; i++) { ++ ret = af9033_wr_reg(state, init[i].reg, init[i].val); ++ if (ret < 0) ++ goto err; ++ } ++ ++ /* load tuner specific settings */ ++ pr_debug("%s: load tuner specific settings\n", ++ __func__); ++ switch (state->cfg.tuner) { ++ case AF9033_TUNER_TUA9001: ++ len = ARRAY_SIZE(tuner_init_tua9001); ++ init = tuner_init_tua9001; ++ break; ++ case AF9033_TUNER_FC0011: ++ len = ARRAY_SIZE(tuner_init_fc0011); ++ init = tuner_init_fc0011; ++ break; ++ case AF9033_TUNER_MXL5007T: ++ len = ARRAY_SIZE(tuner_init_mxl5007t); ++ init = tuner_init_mxl5007t; ++ break; ++ case AF9033_TUNER_TDA18218: ++ len = ARRAY_SIZE(tuner_init_tda18218); ++ init = tuner_init_tda18218; ++ break; ++ default: ++ pr_debug("%s: unsupported tuner ID=%d\n", __func__, ++ state->cfg.tuner); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ for (i = 0; i < len; i++) { ++ ret = af9033_wr_reg(state, init[i].reg, init[i].val); ++ if (ret < 0) ++ goto err; ++ } ++ ++ state->bandwidth_hz = 0; /* force to program all parameters */ ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9033_sleep(struct dvb_frontend *fe) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ int ret, i; ++ u8 tmp; ++ ++ ret = af9033_wr_reg(state, 0x80004c, 1); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_wr_reg(state, 0x800000, 0); ++ if (ret < 0) ++ goto err; ++ ++ for (i = 100, tmp = 1; i && tmp; i--) { ++ ret = af9033_rd_reg(state, 0x80004c, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ usleep_range(200, 10000); ++ } ++ ++ pr_debug("%s: loop=%d\n", __func__, i); ++ ++ if (i == 0) { ++ ret = -ETIMEDOUT; ++ goto err; ++ } ++ ++ ret = af9033_wr_reg_mask(state, 0x80fb24, 0x08, 0x08); ++ if (ret < 0) ++ goto err; ++ ++ /* prevent current leak (?) */ ++ if (state->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { ++ /* enable parallel TS */ ++ ret = af9033_wr_reg_mask(state, 0x00d917, 0x00, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_wr_reg_mask(state, 0x00d916, 0x01, 0x01); ++ if (ret < 0) ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9033_get_tune_settings(struct dvb_frontend *fe, ++ struct dvb_frontend_tune_settings *fesettings) ++{ ++ fesettings->min_delay_ms = 800; ++ fesettings->step_size = 0; ++ fesettings->max_drift = 0; ++ ++ return 0; ++} ++ ++static int af9033_set_frontend(struct dvb_frontend *fe) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret, i, spec_inv; ++ u8 tmp, buf[3], bandwidth_reg_val; ++ u32 if_frequency, freq_cw, adc_freq; ++ ++ pr_debug("%s: frequency=%d bandwidth_hz=%d\n", __func__, c->frequency, ++ c->bandwidth_hz); ++ ++ /* check bandwidth */ ++ switch (c->bandwidth_hz) { ++ case 6000000: ++ bandwidth_reg_val = 0x00; ++ break; ++ case 7000000: ++ bandwidth_reg_val = 0x01; ++ break; ++ case 8000000: ++ bandwidth_reg_val = 0x02; ++ break; ++ default: ++ pr_debug("%s: invalid bandwidth_hz\n", __func__); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ /* program tuner */ ++ if (fe->ops.tuner_ops.set_params) ++ fe->ops.tuner_ops.set_params(fe); ++ ++ /* program CFOE coefficients */ ++ if (c->bandwidth_hz != state->bandwidth_hz) { ++ for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) { ++ if (coeff_lut[i].clock == state->cfg.clock && ++ coeff_lut[i].bandwidth_hz == c->bandwidth_hz) { ++ break; ++ } ++ } ++ ret = af9033_wr_regs(state, 0x800001, ++ coeff_lut[i].val, sizeof(coeff_lut[i].val)); ++ } ++ ++ /* program frequency control */ ++ if (c->bandwidth_hz != state->bandwidth_hz) { ++ spec_inv = state->cfg.spec_inv ? -1 : 1; ++ ++ for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { ++ if (clock_adc_lut[i].clock == state->cfg.clock) ++ break; ++ } ++ adc_freq = clock_adc_lut[i].adc; ++ ++ /* get used IF frequency */ ++ if (fe->ops.tuner_ops.get_if_frequency) ++ fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency); ++ else ++ if_frequency = 0; ++ ++ while (if_frequency > (adc_freq / 2)) ++ if_frequency -= adc_freq; ++ ++ if (if_frequency >= 0) ++ spec_inv *= -1; ++ else ++ if_frequency *= -1; ++ ++ freq_cw = af9033_div(if_frequency, adc_freq, 23ul); ++ ++ if (spec_inv == -1) ++ freq_cw *= -1; ++ ++ /* get adc multiplies */ ++ ret = af9033_rd_reg(state, 0x800045, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ if (tmp == 1) ++ freq_cw /= 2; ++ ++ buf[0] = (freq_cw >> 0) & 0xff; ++ buf[1] = (freq_cw >> 8) & 0xff; ++ buf[2] = (freq_cw >> 16) & 0x7f; ++ ret = af9033_wr_regs(state, 0x800029, buf, 3); ++ if (ret < 0) ++ goto err; ++ ++ state->bandwidth_hz = c->bandwidth_hz; ++ } ++ ++ ret = af9033_wr_reg_mask(state, 0x80f904, bandwidth_reg_val, 0x03); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_wr_reg(state, 0x800040, 0x00); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_wr_reg(state, 0x800047, 0x00); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_wr_reg_mask(state, 0x80f999, 0x00, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ if (c->frequency <= 230000000) ++ tmp = 0x00; /* VHF */ ++ else ++ tmp = 0x01; /* UHF */ ++ ++ ret = af9033_wr_reg(state, 0x80004b, tmp); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_wr_reg(state, 0x800000, 0x00); ++ if (ret < 0) ++ goto err; ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9033_get_frontend(struct dvb_frontend *fe) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ int ret; ++ u8 buf[8]; ++ ++ pr_debug("%s\n", __func__); ++ ++ /* read all needed registers */ ++ ret = af9033_rd_regs(state, 0x80f900, buf, sizeof(buf)); ++ if (ret < 0) ++ goto err; ++ ++ switch ((buf[0] >> 0) & 3) { ++ case 0: ++ c->transmission_mode = TRANSMISSION_MODE_2K; ++ break; ++ case 1: ++ c->transmission_mode = TRANSMISSION_MODE_8K; ++ break; ++ } ++ ++ switch ((buf[1] >> 0) & 3) { ++ case 0: ++ c->guard_interval = GUARD_INTERVAL_1_32; ++ break; ++ case 1: ++ c->guard_interval = GUARD_INTERVAL_1_16; ++ break; ++ case 2: ++ c->guard_interval = GUARD_INTERVAL_1_8; ++ break; ++ case 3: ++ c->guard_interval = GUARD_INTERVAL_1_4; ++ break; ++ } ++ ++ switch ((buf[2] >> 0) & 7) { ++ case 0: ++ c->hierarchy = HIERARCHY_NONE; ++ break; ++ case 1: ++ c->hierarchy = HIERARCHY_1; ++ break; ++ case 2: ++ c->hierarchy = HIERARCHY_2; ++ break; ++ case 3: ++ c->hierarchy = HIERARCHY_4; ++ break; ++ } ++ ++ switch ((buf[3] >> 0) & 3) { ++ case 0: ++ c->modulation = QPSK; ++ break; ++ case 1: ++ c->modulation = QAM_16; ++ break; ++ case 2: ++ c->modulation = QAM_64; ++ break; ++ } ++ ++ switch ((buf[4] >> 0) & 3) { ++ case 0: ++ c->bandwidth_hz = 6000000; ++ break; ++ case 1: ++ c->bandwidth_hz = 7000000; ++ break; ++ case 2: ++ c->bandwidth_hz = 8000000; ++ break; ++ } ++ ++ switch ((buf[6] >> 0) & 7) { ++ case 0: ++ c->code_rate_HP = FEC_1_2; ++ break; ++ case 1: ++ c->code_rate_HP = FEC_2_3; ++ break; ++ case 2: ++ c->code_rate_HP = FEC_3_4; ++ break; ++ case 3: ++ c->code_rate_HP = FEC_5_6; ++ break; ++ case 4: ++ c->code_rate_HP = FEC_7_8; ++ break; ++ case 5: ++ c->code_rate_HP = FEC_NONE; ++ break; ++ } ++ ++ switch ((buf[7] >> 0) & 7) { ++ case 0: ++ c->code_rate_LP = FEC_1_2; ++ break; ++ case 1: ++ c->code_rate_LP = FEC_2_3; ++ break; ++ case 2: ++ c->code_rate_LP = FEC_3_4; ++ break; ++ case 3: ++ c->code_rate_LP = FEC_5_6; ++ break; ++ case 4: ++ c->code_rate_LP = FEC_7_8; ++ break; ++ case 5: ++ c->code_rate_LP = FEC_NONE; ++ break; ++ } ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9033_read_status(struct dvb_frontend *fe, fe_status_t *status) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ int ret; ++ u8 tmp; ++ ++ *status = 0; ++ ++ /* radio channel status, 0=no result, 1=has signal, 2=no signal */ ++ ret = af9033_rd_reg(state, 0x800047, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ /* has signal */ ++ if (tmp == 0x01) ++ *status |= FE_HAS_SIGNAL; ++ ++ if (tmp != 0x02) { ++ /* TPS lock */ ++ ret = af9033_rd_reg_mask(state, 0x80f5a9, &tmp, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ if (tmp) ++ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | ++ FE_HAS_VITERBI; ++ ++ /* full lock */ ++ ret = af9033_rd_reg_mask(state, 0x80f999, &tmp, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ if (tmp) ++ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | ++ FE_HAS_VITERBI | FE_HAS_SYNC | ++ FE_HAS_LOCK; ++ } ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9033_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ int ret, i, len; ++ u8 buf[3], tmp; ++ u32 snr_val; ++ const struct val_snr *uninitialized_var(snr_lut); ++ ++ /* read value */ ++ ret = af9033_rd_regs(state, 0x80002c, buf, 3); ++ if (ret < 0) ++ goto err; ++ ++ snr_val = (buf[2] << 16) | (buf[1] << 8) | buf[0]; ++ ++ /* read current modulation */ ++ ret = af9033_rd_reg(state, 0x80f903, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ switch ((tmp >> 0) & 3) { ++ case 0: ++ len = ARRAY_SIZE(qpsk_snr_lut); ++ snr_lut = qpsk_snr_lut; ++ break; ++ case 1: ++ len = ARRAY_SIZE(qam16_snr_lut); ++ snr_lut = qam16_snr_lut; ++ break; ++ case 2: ++ len = ARRAY_SIZE(qam64_snr_lut); ++ snr_lut = qam64_snr_lut; ++ break; ++ default: ++ goto err; ++ } ++ ++ for (i = 0; i < len; i++) { ++ tmp = snr_lut[i].snr; ++ ++ if (snr_val < snr_lut[i].val) ++ break; ++ } ++ ++ *snr = tmp * 10; /* dB/10 */ ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ int ret; ++ u8 strength2; ++ ++ /* read signal strength of 0-100 scale */ ++ ret = af9033_rd_reg(state, 0x800048, &strength2); ++ if (ret < 0) ++ goto err; ++ ++ /* scale value to 0x0000-0xffff */ ++ *strength = strength2 * 0xffff / 100; ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9033_read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ *ber = 0; ++ ++ return 0; ++} ++ ++static int af9033_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ *ucblocks = 0; ++ ++ return 0; ++} ++ ++static int af9033_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) ++{ ++ struct af9033_state *state = fe->demodulator_priv; ++ int ret; ++ ++ pr_debug("%s: enable=%d\n", __func__, enable); ++ ++ ret = af9033_wr_reg_mask(state, 0x00fa04, enable, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static struct dvb_frontend_ops af9033_ops; ++ ++struct dvb_frontend *af9033_attach(const struct af9033_config *config, ++ struct i2c_adapter *i2c) ++{ ++ int ret; ++ struct af9033_state *state; ++ u8 buf[8]; ++ ++ pr_debug("%s:\n", __func__); ++ ++ /* allocate memory for the internal state */ ++ state = kzalloc(sizeof(struct af9033_state), GFP_KERNEL); ++ if (state == NULL) ++ goto err; ++ ++ /* setup the state */ ++ state->i2c = i2c; ++ memcpy(&state->cfg, config, sizeof(struct af9033_config)); ++ ++ if (state->cfg.clock != 12000000) { ++ printk(KERN_INFO "af9033: unsupported clock=%d, only " \ ++ "12000000 Hz is supported currently\n", ++ state->cfg.clock); ++ goto err; ++ } ++ ++ /* firmware version */ ++ ret = af9033_rd_regs(state, 0x0083e9, &buf[0], 4); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9033_rd_regs(state, 0x804191, &buf[4], 4); ++ if (ret < 0) ++ goto err; ++ ++ printk(KERN_INFO "af9033: firmware version: LINK=%d.%d.%d.%d " \ ++ "OFDM=%d.%d.%d.%d\n", buf[0], buf[1], buf[2], buf[3], ++ buf[4], buf[5], buf[6], buf[7]); ++ ++ /* configure internal TS mode */ ++ switch (state->cfg.ts_mode) { ++ case AF9033_TS_MODE_PARALLEL: ++ state->ts_mode_parallel = true; ++ break; ++ case AF9033_TS_MODE_SERIAL: ++ state->ts_mode_serial = true; ++ break; ++ case AF9033_TS_MODE_USB: ++ /* usb mode for AF9035 */ ++ default: ++ break; ++ } ++ ++ /* create dvb_frontend */ ++ memcpy(&state->fe.ops, &af9033_ops, sizeof(struct dvb_frontend_ops)); ++ state->fe.demodulator_priv = state; ++ ++ return &state->fe; ++ ++err: ++ kfree(state); ++ return NULL; ++} ++EXPORT_SYMBOL(af9033_attach); ++ ++static struct dvb_frontend_ops af9033_ops = { ++ .delsys = { SYS_DVBT }, ++ .info = { ++ .name = "Afatech AF9033 (DVB-T)", ++ .frequency_min = 174000000, ++ .frequency_max = 862000000, ++ .frequency_stepsize = 250000, ++ .frequency_tolerance = 0, ++ .caps = FE_CAN_FEC_1_2 | ++ FE_CAN_FEC_2_3 | ++ FE_CAN_FEC_3_4 | ++ FE_CAN_FEC_5_6 | ++ FE_CAN_FEC_7_8 | ++ FE_CAN_FEC_AUTO | ++ FE_CAN_QPSK | ++ FE_CAN_QAM_16 | ++ FE_CAN_QAM_64 | ++ FE_CAN_QAM_AUTO | ++ FE_CAN_TRANSMISSION_MODE_AUTO | ++ FE_CAN_GUARD_INTERVAL_AUTO | ++ FE_CAN_HIERARCHY_AUTO | ++ FE_CAN_RECOVER | ++ FE_CAN_MUTE_TS ++ }, ++ ++ .release = af9033_release, ++ ++ .init = af9033_init, ++ .sleep = af9033_sleep, ++ ++ .get_tune_settings = af9033_get_tune_settings, ++ .set_frontend = af9033_set_frontend, ++ .get_frontend = af9033_get_frontend, ++ ++ .read_status = af9033_read_status, ++ .read_snr = af9033_read_snr, ++ .read_signal_strength = af9033_read_signal_strength, ++ .read_ber = af9033_read_ber, ++ .read_ucblocks = af9033_read_ucblocks, ++ ++ .i2c_gate_ctrl = af9033_i2c_gate_ctrl, ++}; ++ ++MODULE_AUTHOR("Antti Palosaari "); ++MODULE_DESCRIPTION("Afatech AF9033 DVB-T demodulator driver"); ++MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/af9033.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/af9033.h +@@ -0,0 +1,75 @@ ++/* ++ * Afatech AF9033 demodulator driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * Copyright (C) 2012 Antti Palosaari ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef AF9033_H ++#define AF9033_H ++ ++struct af9033_config { ++ /* ++ * I2C address ++ */ ++ u8 i2c_addr; ++ ++ /* ++ * clock Hz ++ * 12000000, 22000000, 24000000, 34000000, 32000000, 28000000, 26000000, ++ * 30000000, 36000000, 20480000, 16384000 ++ */ ++ u32 clock; ++ ++ /* ++ * tuner ++ */ ++#define AF9033_TUNER_TUA9001 0x27 /* Infineon TUA 9001 */ ++#define AF9033_TUNER_FC0011 0x28 /* Fitipower FC0011 */ ++#define AF9033_TUNER_MXL5007T 0xa0 /* MaxLinear MxL5007T */ ++#define AF9033_TUNER_TDA18218 0xa1 /* NXP TDA 18218HN */ ++ u8 tuner; ++ ++ /* ++ * TS settings ++ */ ++#define AF9033_TS_MODE_USB 0 ++#define AF9033_TS_MODE_PARALLEL 1 ++#define AF9033_TS_MODE_SERIAL 2 ++ u8 ts_mode:2; ++ ++ /* ++ * input spectrum inversion ++ */ ++ bool spec_inv; ++}; ++ ++ ++#if defined(CONFIG_DVB_AF9033) || \ ++ (defined(CONFIG_DVB_AF9033_MODULE) && defined(MODULE)) ++extern struct dvb_frontend *af9033_attach(const struct af9033_config *config, ++ struct i2c_adapter *i2c); ++#else ++static inline struct dvb_frontend *af9033_attach( ++ const struct af9033_config *config, struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif ++ ++#endif /* AF9033_H */ +Index: linux-3.3.x86_64/drivers/media/dvb/frontends/af9033_priv.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/frontends/af9033_priv.h +@@ -0,0 +1,470 @@ ++/* ++ * Afatech AF9033 demodulator driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * Copyright (C) 2012 Antti Palosaari ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef AF9033_PRIV_H ++#define AF9033_PRIV_H ++ ++#include "dvb_frontend.h" ++#include "af9033.h" ++ ++struct reg_val { ++ u32 reg; ++ u8 val; ++}; ++ ++struct reg_val_mask { ++ u32 reg; ++ u8 val; ++ u8 mask; ++}; ++ ++struct coeff { ++ u32 clock; ++ u32 bandwidth_hz; ++ u8 val[36]; ++}; ++ ++struct clock_adc { ++ u32 clock; ++ u32 adc; ++}; ++ ++struct val_snr { ++ u32 val; ++ u8 snr; ++}; ++ ++/* Xtal clock vs. ADC clock lookup table */ ++static const struct clock_adc clock_adc_lut[] = { ++ { 16384000, 20480000 }, ++ { 20480000, 20480000 }, ++ { 36000000, 20250000 }, ++ { 30000000, 20156250 }, ++ { 26000000, 20583333 }, ++ { 28000000, 20416667 }, ++ { 32000000, 20500000 }, ++ { 34000000, 20187500 }, ++ { 24000000, 20500000 }, ++ { 22000000, 20625000 }, ++ { 12000000, 20250000 }, ++}; ++ ++/* pre-calculated coeff lookup table */ ++static const struct coeff coeff_lut[] = { ++ /* 12.000 MHz */ ++ { 12000000, 8000000, { ++ 0x01, 0xce, 0x55, 0xc9, 0x00, 0xe7, 0x2a, 0xe4, 0x00, 0x73, ++ 0x99, 0x0f, 0x00, 0x73, 0x95, 0x72, 0x00, 0x73, 0x91, 0xd5, ++ 0x00, 0x39, 0xca, 0xb9, 0x00, 0xe7, 0x2a, 0xe4, 0x00, 0x73, ++ 0x95, 0x72, 0x37, 0x02, 0xce, 0x01 } ++ }, ++ { 12000000, 7000000, { ++ 0x01, 0x94, 0x8b, 0x10, 0x00, 0xca, 0x45, 0x88, 0x00, 0x65, ++ 0x25, 0xed, 0x00, 0x65, 0x22, 0xc4, 0x00, 0x65, 0x1f, 0x9b, ++ 0x00, 0x32, 0x91, 0x62, 0x00, 0xca, 0x45, 0x88, 0x00, 0x65, ++ 0x22, 0xc4, 0x88, 0x02, 0x95, 0x01 } ++ }, ++ { 12000000, 6000000, { ++ 0x01, 0x5a, 0xc0, 0x56, 0x00, 0xad, 0x60, 0x2b, 0x00, 0x56, ++ 0xb2, 0xcb, 0x00, 0x56, 0xb0, 0x15, 0x00, 0x56, 0xad, 0x60, ++ 0x00, 0x2b, 0x58, 0x0b, 0x00, 0xad, 0x60, 0x2b, 0x00, 0x56, ++ 0xb0, 0x15, 0xf4, 0x02, 0x5b, 0x01 } ++ }, ++}; ++ ++/* QPSK SNR lookup table */ ++static const struct val_snr qpsk_snr_lut[] = { ++ { 0x0b4771, 0 }, ++ { 0x0c1aed, 1 }, ++ { 0x0d0d27, 2 }, ++ { 0x0e4d19, 3 }, ++ { 0x0e5da8, 4 }, ++ { 0x107097, 5 }, ++ { 0x116975, 6 }, ++ { 0x1252d9, 7 }, ++ { 0x131fa4, 8 }, ++ { 0x13d5e1, 9 }, ++ { 0x148e53, 10 }, ++ { 0x15358b, 11 }, ++ { 0x15dd29, 12 }, ++ { 0x168112, 13 }, ++ { 0x170b61, 14 }, ++ { 0x17a532, 15 }, ++ { 0x180f94, 16 }, ++ { 0x186ed2, 17 }, ++ { 0x18b271, 18 }, ++ { 0x18e118, 19 }, ++ { 0x18ff4b, 20 }, ++ { 0x190af1, 21 }, ++ { 0x191451, 22 }, ++ { 0xffffff, 23 }, ++}; ++ ++/* QAM16 SNR lookup table */ ++static const struct val_snr qam16_snr_lut[] = { ++ { 0x04f0d5, 0 }, ++ { 0x05387a, 1 }, ++ { 0x0573a4, 2 }, ++ { 0x05a99e, 3 }, ++ { 0x05cc80, 4 }, ++ { 0x05eb62, 5 }, ++ { 0x05fecf, 6 }, ++ { 0x060b80, 7 }, ++ { 0x062501, 8 }, ++ { 0x064865, 9 }, ++ { 0x069604, 10 }, ++ { 0x06f356, 11 }, ++ { 0x07706a, 12 }, ++ { 0x0804d3, 13 }, ++ { 0x089d1a, 14 }, ++ { 0x093e3d, 15 }, ++ { 0x09e35d, 16 }, ++ { 0x0a7c3c, 17 }, ++ { 0x0afaf8, 18 }, ++ { 0x0b719d, 19 }, ++ { 0x0bda6a, 20 }, ++ { 0x0c0c75, 21 }, ++ { 0x0c3f7d, 22 }, ++ { 0x0c5e62, 23 }, ++ { 0x0c6c31, 24 }, ++ { 0x0c7925, 25 }, ++ { 0xffffff, 26 }, ++}; ++ ++/* QAM64 SNR lookup table */ ++static const struct val_snr qam64_snr_lut[] = { ++ { 0x0256d0, 0 }, ++ { 0x027a65, 1 }, ++ { 0x029873, 2 }, ++ { 0x02b7fe, 3 }, ++ { 0x02cf1e, 4 }, ++ { 0x02e234, 5 }, ++ { 0x02f409, 6 }, ++ { 0x030046, 7 }, ++ { 0x030844, 8 }, ++ { 0x030a02, 9 }, ++ { 0x030cde, 10 }, ++ { 0x031031, 11 }, ++ { 0x03144c, 12 }, ++ { 0x0315dd, 13 }, ++ { 0x031920, 14 }, ++ { 0x0322d0, 15 }, ++ { 0x0339fc, 16 }, ++ { 0x0364a1, 17 }, ++ { 0x038bcc, 18 }, ++ { 0x03c7d3, 19 }, ++ { 0x0408cc, 20 }, ++ { 0x043bed, 21 }, ++ { 0x048061, 22 }, ++ { 0x04be95, 23 }, ++ { 0x04fa7d, 24 }, ++ { 0x052405, 25 }, ++ { 0x05570d, 26 }, ++ { 0x059feb, 27 }, ++ { 0x05bf38, 28 }, ++ { 0xffffff, 29 }, ++}; ++ ++static const struct reg_val ofsm_init[] = { ++ { 0x800051, 0x01 }, ++ { 0x800070, 0x0a }, ++ { 0x80007e, 0x04 }, ++ { 0x800081, 0x0a }, ++ { 0x80008a, 0x01 }, ++ { 0x80008e, 0x01 }, ++ { 0x800092, 0x06 }, ++ { 0x800099, 0x01 }, ++ { 0x80009f, 0xe1 }, ++ { 0x8000a0, 0xcf }, ++ { 0x8000a3, 0x01 }, ++ { 0x8000a5, 0x01 }, ++ { 0x8000a6, 0x01 }, ++ { 0x8000a9, 0x00 }, ++ { 0x8000aa, 0x01 }, ++ { 0x8000ab, 0x01 }, ++ { 0x8000b0, 0x01 }, ++ { 0x8000c0, 0x05 }, ++ { 0x8000c4, 0x19 }, ++ { 0x80f000, 0x0f }, ++ { 0x80f016, 0x10 }, ++ { 0x80f017, 0x04 }, ++ { 0x80f018, 0x05 }, ++ { 0x80f019, 0x04 }, ++ { 0x80f01a, 0x05 }, ++ { 0x80f021, 0x03 }, ++ { 0x80f022, 0x0a }, ++ { 0x80f023, 0x0a }, ++ { 0x80f02b, 0x00 }, ++ { 0x80f02c, 0x01 }, ++ { 0x80f064, 0x03 }, ++ { 0x80f065, 0xf9 }, ++ { 0x80f066, 0x03 }, ++ { 0x80f067, 0x01 }, ++ { 0x80f06f, 0xe0 }, ++ { 0x80f070, 0x03 }, ++ { 0x80f072, 0x0f }, ++ { 0x80f073, 0x03 }, ++ { 0x80f078, 0x00 }, ++ { 0x80f087, 0x00 }, ++ { 0x80f09b, 0x3f }, ++ { 0x80f09c, 0x00 }, ++ { 0x80f09d, 0x20 }, ++ { 0x80f09e, 0x00 }, ++ { 0x80f09f, 0x0c }, ++ { 0x80f0a0, 0x00 }, ++ { 0x80f130, 0x04 }, ++ { 0x80f132, 0x04 }, ++ { 0x80f144, 0x1a }, ++ { 0x80f146, 0x00 }, ++ { 0x80f14a, 0x01 }, ++ { 0x80f14c, 0x00 }, ++ { 0x80f14d, 0x00 }, ++ { 0x80f14f, 0x04 }, ++ { 0x80f158, 0x7f }, ++ { 0x80f15a, 0x00 }, ++ { 0x80f15b, 0x08 }, ++ { 0x80f15d, 0x03 }, ++ { 0x80f15e, 0x05 }, ++ { 0x80f163, 0x05 }, ++ { 0x80f166, 0x01 }, ++ { 0x80f167, 0x40 }, ++ { 0x80f168, 0x0f }, ++ { 0x80f17a, 0x00 }, ++ { 0x80f17b, 0x00 }, ++ { 0x80f183, 0x01 }, ++ { 0x80f19d, 0x40 }, ++ { 0x80f1bc, 0x36 }, ++ { 0x80f1bd, 0x00 }, ++ { 0x80f1cb, 0xa0 }, ++ { 0x80f1cc, 0x01 }, ++ { 0x80f204, 0x10 }, ++ { 0x80f214, 0x00 }, ++ { 0x80f40e, 0x0a }, ++ { 0x80f40f, 0x40 }, ++ { 0x80f410, 0x08 }, ++ { 0x80f55f, 0x0a }, ++ { 0x80f561, 0x15 }, ++ { 0x80f562, 0x20 }, ++ { 0x80f5df, 0xfb }, ++ { 0x80f5e0, 0x00 }, ++ { 0x80f5e3, 0x09 }, ++ { 0x80f5e4, 0x01 }, ++ { 0x80f5e5, 0x01 }, ++ { 0x80f5f8, 0x01 }, ++ { 0x80f5fd, 0x01 }, ++ { 0x80f600, 0x05 }, ++ { 0x80f601, 0x08 }, ++ { 0x80f602, 0x0b }, ++ { 0x80f603, 0x0e }, ++ { 0x80f604, 0x11 }, ++ { 0x80f605, 0x14 }, ++ { 0x80f606, 0x17 }, ++ { 0x80f607, 0x1f }, ++ { 0x80f60e, 0x00 }, ++ { 0x80f60f, 0x04 }, ++ { 0x80f610, 0x32 }, ++ { 0x80f611, 0x10 }, ++ { 0x80f707, 0xfc }, ++ { 0x80f708, 0x00 }, ++ { 0x80f709, 0x37 }, ++ { 0x80f70a, 0x00 }, ++ { 0x80f78b, 0x01 }, ++ { 0x80f80f, 0x40 }, ++ { 0x80f810, 0x54 }, ++ { 0x80f811, 0x5a }, ++ { 0x80f905, 0x01 }, ++ { 0x80fb06, 0x03 }, ++ { 0x80fd8b, 0x00 }, ++}; ++ ++/* Infineon TUA 9001 tuner init ++ AF9033_TUNER_TUA9001 = 0x27 */ ++static const struct reg_val tuner_init_tua9001[] = { ++ { 0x800046, 0x27 }, ++ { 0x800057, 0x00 }, ++ { 0x800058, 0x01 }, ++ { 0x80005f, 0x00 }, ++ { 0x800060, 0x00 }, ++ { 0x80006d, 0x00 }, ++ { 0x800071, 0x05 }, ++ { 0x800072, 0x02 }, ++ { 0x800074, 0x01 }, ++ { 0x800075, 0x03 }, ++ { 0x800076, 0x02 }, ++ { 0x800077, 0x00 }, ++ { 0x800078, 0x01 }, ++ { 0x800079, 0x00 }, ++ { 0x80007a, 0x7e }, ++ { 0x80007b, 0x3e }, ++ { 0x800093, 0x00 }, ++ { 0x800094, 0x01 }, ++ { 0x800095, 0x02 }, ++ { 0x800096, 0x01 }, ++ { 0x800098, 0x0a }, ++ { 0x80009b, 0x05 }, ++ { 0x80009c, 0x80 }, ++ { 0x8000b3, 0x00 }, ++ { 0x8000c1, 0x01 }, ++ { 0x8000c2, 0x00 }, ++ { 0x80f007, 0x00 }, ++ { 0x80f01f, 0x82 }, ++ { 0x80f020, 0x00 }, ++ { 0x80f029, 0x82 }, ++ { 0x80f02a, 0x00 }, ++ { 0x80f047, 0x00 }, ++ { 0x80f054, 0x00 }, ++ { 0x80f055, 0x00 }, ++ { 0x80f077, 0x01 }, ++ { 0x80f1e6, 0x00 }, ++}; ++ ++/* Fitipower fc0011 tuner init ++ AF9033_TUNER_FC0011 = 0x28 */ ++static const struct reg_val tuner_init_fc0011[] = { ++ { 0x800046, AF9033_TUNER_FC0011 }, ++ { 0x800057, 0x00 }, ++ { 0x800058, 0x01 }, ++ { 0x80005f, 0x00 }, ++ { 0x800060, 0x00 }, ++ { 0x800068, 0xa5 }, ++ { 0x80006e, 0x01 }, ++ { 0x800071, 0x0A }, ++ { 0x800072, 0x02 }, ++ { 0x800074, 0x01 }, ++ { 0x800079, 0x01 }, ++ { 0x800093, 0x00 }, ++ { 0x800094, 0x00 }, ++ { 0x800095, 0x00 }, ++ { 0x800096, 0x00 }, ++ { 0x80009b, 0x2D }, ++ { 0x80009c, 0x60 }, ++ { 0x80009d, 0x23 }, ++ { 0x8000a4, 0x50 }, ++ { 0x8000ad, 0x50 }, ++ { 0x8000b3, 0x01 }, ++ { 0x8000b7, 0x88 }, ++ { 0x8000b8, 0xa6 }, ++ { 0x8000c3, 0x01 }, ++ { 0x8000c4, 0x01 }, ++ { 0x8000c7, 0x69 }, ++ { 0x80F007, 0x00 }, ++ { 0x80F00A, 0x1B }, ++ { 0x80F00B, 0x1B }, ++ { 0x80F00C, 0x1B }, ++ { 0x80F00D, 0x1B }, ++ { 0x80F00E, 0xFF }, ++ { 0x80F00F, 0x01 }, ++ { 0x80F010, 0x00 }, ++ { 0x80F011, 0x02 }, ++ { 0x80F012, 0xFF }, ++ { 0x80F013, 0x01 }, ++ { 0x80F014, 0x00 }, ++ { 0x80F015, 0x02 }, ++ { 0x80F01B, 0xEF }, ++ { 0x80F01C, 0x01 }, ++ { 0x80F01D, 0x0f }, ++ { 0x80F01E, 0x02 }, ++ { 0x80F01F, 0x6E }, ++ { 0x80F020, 0x00 }, ++ { 0x80F025, 0xDE }, ++ { 0x80F026, 0x00 }, ++ { 0x80F027, 0x0A }, ++ { 0x80F028, 0x03 }, ++ { 0x80F029, 0x6E }, ++ { 0x80F02A, 0x00 }, ++ { 0x80F047, 0x00 }, ++ { 0x80F054, 0x00 }, ++ { 0x80F055, 0x00 }, ++ { 0x80F077, 0x01 }, ++ { 0x80F1E6, 0x00 }, ++}; ++ ++/* MaxLinear MxL5007T tuner init ++ AF9033_TUNER_MXL5007T = 0xa0 */ ++static const struct reg_val tuner_init_mxl5007t[] = { ++ { 0x800046, 0x1b }, ++ { 0x800057, 0x01 }, ++ { 0x800058, 0x01 }, ++ { 0x80005f, 0x00 }, ++ { 0x800060, 0x00 }, ++ { 0x800068, 0x96 }, ++ { 0x800071, 0x05 }, ++ { 0x800072, 0x02 }, ++ { 0x800074, 0x01 }, ++ { 0x800079, 0x01 }, ++ { 0x800093, 0x00 }, ++ { 0x800094, 0x00 }, ++ { 0x800095, 0x00 }, ++ { 0x800096, 0x00 }, ++ { 0x8000b3, 0x01 }, ++ { 0x8000c1, 0x01 }, ++ { 0x8000c2, 0x00 }, ++ { 0x80f007, 0x00 }, ++ { 0x80f00c, 0x19 }, ++ { 0x80f00d, 0x1a }, ++ { 0x80f012, 0xda }, ++ { 0x80f013, 0x00 }, ++ { 0x80f014, 0x00 }, ++ { 0x80f015, 0x02 }, ++ { 0x80f01f, 0x82 }, ++ { 0x80f020, 0x00 }, ++ { 0x80f029, 0x82 }, ++ { 0x80f02a, 0x00 }, ++ { 0x80f077, 0x02 }, ++ { 0x80f1e6, 0x00 }, ++}; ++ ++/* NXP TDA 18218HN tuner init ++ AF9033_TUNER_TDA18218 = 0xa1 */ ++static const struct reg_val tuner_init_tda18218[] = { ++ {0x800046, 0xa1}, ++ {0x800057, 0x01}, ++ {0x800058, 0x01}, ++ {0x80005f, 0x00}, ++ {0x800060, 0x00}, ++ {0x800071, 0x05}, ++ {0x800072, 0x02}, ++ {0x800074, 0x01}, ++ {0x800079, 0x01}, ++ {0x800093, 0x00}, ++ {0x800094, 0x00}, ++ {0x800095, 0x00}, ++ {0x800096, 0x00}, ++ {0x8000b3, 0x01}, ++ {0x8000c3, 0x01}, ++ {0x8000c4, 0x00}, ++ {0x80f007, 0x00}, ++ {0x80f00c, 0x19}, ++ {0x80f00d, 0x1a}, ++ {0x80f012, 0xda}, ++ {0x80f013, 0x00}, ++ {0x80f014, 0x00}, ++ {0x80f015, 0x02}, ++ {0x80f01f, 0x82}, ++ {0x80f020, 0x00}, ++ {0x80f029, 0x82}, ++ {0x80f02a, 0x00}, ++ {0x80f077, 0x02}, ++ {0x80f1e6, 0x00}, ++}; ++ ++#endif /* AF9033_PRIV_H */ ++ +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9035.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9035.c +@@ -0,0 +1,1164 @@ ++/* ++ * Afatech AF9035 DVB USB driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * Copyright (C) 2012 Antti Palosaari ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include "af9035.h" ++#include "af9033.h" ++#include "tua9001.h" ++#include "fc0011.h" ++#include "mxl5007t.h" ++#include "tda18218.h" ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++static DEFINE_MUTEX(af9035_usb_mutex); ++static struct config af9035_config; ++static struct dvb_usb_device_properties af9035_properties[2]; ++static int af9035_properties_count = ARRAY_SIZE(af9035_properties); ++static struct af9033_config af9035_af9033_config[] = { ++ { ++ .ts_mode = AF9033_TS_MODE_USB, ++ }, { ++ .ts_mode = AF9033_TS_MODE_SERIAL, ++ } ++}; ++ ++static u16 af9035_checksum(const u8 *buf, size_t len) ++{ ++ size_t i; ++ u16 checksum = 0; ++ ++ for (i = 1; i < len; i++) { ++ if (i % 2) ++ checksum += buf[i] << 8; ++ else ++ checksum += buf[i]; ++ } ++ checksum = ~checksum; ++ ++ return checksum; ++} ++ ++static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req) ++{ ++#define BUF_LEN 63 ++#define REQ_HDR_LEN 4 /* send header size */ ++#define ACK_HDR_LEN 3 /* rece header size */ ++#define CHECKSUM_LEN 2 ++#define USB_TIMEOUT 2000 ++ ++ int ret, act_len; ++ u8 buf[BUF_LEN]; ++ u32 msg_len; ++ static u8 seq; /* packet sequence number */ ++ u16 checksum, tmpsum; ++ ++ /* buffer overflow check */ ++ if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) || ++ req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) { ++ pr_debug("%s: too much data wlen=%d rlen=%d\n", __func__, ++ req->wlen, req->rlen); ++ return -EINVAL; ++ } ++ ++ if (mutex_lock_interruptible(&af9035_usb_mutex) < 0) ++ return -EAGAIN; ++ ++ buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1; ++ buf[1] = req->mbox; ++ buf[2] = req->cmd; ++ buf[3] = seq++; ++ if (req->wlen) ++ memcpy(&buf[4], req->wbuf, req->wlen); ++ ++ /* calc and add checksum */ ++ checksum = af9035_checksum(buf, buf[0] - 1); ++ buf[buf[0]-1] = (checksum >> 8); ++ buf[buf[0]-0] = (checksum & 0xff); ++ ++ msg_len = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN ; ++ ++ /* send req */ ++ ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len, ++ &act_len, USB_TIMEOUT); ++ if (ret < 0) ++ err("bulk message failed=%d (%d/%d)", ret, msg_len, act_len); ++ else ++ if (act_len != msg_len) ++ ret = -EIO; /* all data is not send */ ++ if (ret < 0) ++ goto err_mutex_unlock; ++ ++ /* no ack for those packets */ ++ if (req->cmd == CMD_FW_DL) ++ goto exit_mutex_unlock; ++ ++ /* receive ack and data if read req */ ++ msg_len = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN; ++ ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len, ++ &act_len, USB_TIMEOUT); ++ if (ret < 0) { ++ err("recv bulk message failed=%d", ret); ++ ret = -EIO; ++ goto err_mutex_unlock; ++ } ++ if (act_len != msg_len) { ++ err("recv bulk message truncated (%d != %u)\n", ++ act_len, (unsigned int)msg_len); ++ ret = -EIO; ++ goto err_mutex_unlock; ++ } ++ ++ /* verify checksum */ ++ checksum = af9035_checksum(buf, act_len - 2); ++ tmpsum = (buf[act_len - 2] << 8) | buf[act_len - 1]; ++ if (tmpsum != checksum) { ++ err("%s: command=%02X checksum mismatch (%04X != %04X)\n", ++ __func__, req->cmd, ++ (unsigned int)tmpsum, (unsigned int)checksum); ++ ret = -EIO; ++ goto err_mutex_unlock; ++ } ++ /* check status */ ++ if (buf[2]) { ++ pr_debug("%s: command=%02x failed fw error=%d\n", __func__, ++ req->cmd, buf[2]); ++ ret = -EIO; ++ goto err_mutex_unlock; ++ } ++ ++ /* read request, copy returned data to return buf */ ++ if (req->rlen) ++ memcpy(req->rbuf, &buf[ACK_HDR_LEN], req->rlen); ++ ++err_mutex_unlock: ++exit_mutex_unlock: ++ mutex_unlock(&af9035_usb_mutex); ++ ++ return ret; ++} ++ ++/* write multiple registers */ ++static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) ++{ ++ u8 wbuf[6 + len]; ++ u8 mbox = (reg >> 16) & 0xff; ++ struct usb_req req = { CMD_MEM_WR, mbox, sizeof(wbuf), wbuf, 0, NULL }; ++ ++ wbuf[0] = len; ++ wbuf[1] = 2; ++ wbuf[2] = 0; ++ wbuf[3] = 0; ++ wbuf[4] = (reg >> 8) & 0xff; ++ wbuf[5] = (reg >> 0) & 0xff; ++ memcpy(&wbuf[6], val, len); ++ ++ return af9035_ctrl_msg(d->udev, &req); ++} ++ ++/* read multiple registers */ ++static int af9035_rd_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) ++{ ++ u8 wbuf[] = { len, 2, 0, 0, (reg >> 8) & 0xff, reg & 0xff }; ++ u8 mbox = (reg >> 16) & 0xff; ++ struct usb_req req = { CMD_MEM_RD, mbox, sizeof(wbuf), wbuf, len, val }; ++ ++ return af9035_ctrl_msg(d->udev, &req); ++} ++ ++/* write single register */ ++static int af9035_wr_reg(struct dvb_usb_device *d, u32 reg, u8 val) ++{ ++ return af9035_wr_regs(d, reg, &val, 1); ++} ++ ++/* read single register */ ++static int af9035_rd_reg(struct dvb_usb_device *d, u32 reg, u8 *val) ++{ ++ return af9035_rd_regs(d, reg, val, 1); ++} ++ ++/* write single register with mask */ ++static int af9035_wr_reg_mask(struct dvb_usb_device *d, u32 reg, u8 val, ++ u8 mask) ++{ ++ int ret; ++ u8 tmp; ++ ++ /* no need for read if whole reg is written */ ++ if (mask != 0xff) { ++ ret = af9035_rd_regs(d, reg, &tmp, 1); ++ if (ret) ++ return ret; ++ ++ val &= mask; ++ tmp &= ~mask; ++ val |= tmp; ++ } ++ ++ return af9035_wr_regs(d, reg, &val, 1); ++} ++ ++static int af9035_i2c_master_xfer(struct i2c_adapter *adap, ++ struct i2c_msg msg[], int num) ++{ ++ struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ int ret; ++ ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ /* ++ * I2C sub header is 5 bytes long. Meaning of those bytes are: ++ * 0: data len ++ * 1: I2C addr << 1 ++ * 2: reg addr len ++ * byte 3 and 4 can be used as reg addr ++ * 3: reg addr MSB ++ * used when reg addr len is set to 2 ++ * 4: reg addr LSB ++ * used when reg addr len is set to 1 or 2 ++ * ++ * For the simplify we do not use register addr at all. ++ * NOTE: As a firmware knows tuner type there is very small possibility ++ * there could be some tuner I2C hacks done by firmware and this may ++ * lead problems if firmware expects those bytes are used. ++ */ ++ if (num == 2 && !(msg[0].flags & I2C_M_RD) && ++ (msg[1].flags & I2C_M_RD)) { ++ if (msg[0].len > 40 || msg[1].len > 40) { ++ /* TODO: correct limits > 40 */ ++ ret = -EOPNOTSUPP; ++ } else if (msg[0].addr == af9035_af9033_config[0].i2c_addr) { ++ /* integrated demod */ ++ u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | ++ msg[0].buf[2]; ++ ret = af9035_rd_regs(d, reg, &msg[1].buf[0], ++ msg[1].len); ++ } else { ++ /* I2C */ ++ u8 buf[5 + msg[0].len]; ++ struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf), ++ buf, msg[1].len, msg[1].buf }; ++ buf[0] = msg[1].len; ++ buf[1] = msg[0].addr << 1; ++ buf[2] = 0x00; /* reg addr len */ ++ buf[3] = 0x00; /* reg addr MSB */ ++ buf[4] = 0x00; /* reg addr LSB */ ++ memcpy(&buf[5], msg[0].buf, msg[0].len); ++ ret = af9035_ctrl_msg(d->udev, &req); ++ } ++ } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { ++ if (msg[0].len > 40) { ++ /* TODO: correct limits > 40 */ ++ ret = -EOPNOTSUPP; ++ } else if (msg[0].addr == af9035_af9033_config[0].i2c_addr) { ++ /* integrated demod */ ++ u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | ++ msg[0].buf[2]; ++ ret = af9035_wr_regs(d, reg, &msg[0].buf[3], ++ msg[0].len - 3); ++ } else { ++ /* I2C */ ++ u8 buf[5 + msg[0].len]; ++ struct usb_req req = { CMD_I2C_WR, 0, sizeof(buf), buf, ++ 0, NULL }; ++ buf[0] = msg[0].len; ++ buf[1] = msg[0].addr << 1; ++ buf[2] = 0x00; /* reg addr len */ ++ buf[3] = 0x00; /* reg addr MSB */ ++ buf[4] = 0x00; /* reg addr LSB */ ++ memcpy(&buf[5], msg[0].buf, msg[0].len); ++ ret = af9035_ctrl_msg(d->udev, &req); ++ } ++ } else { ++ /* ++ * We support only two kind of I2C transactions: ++ * 1) 1 x read + 1 x write ++ * 2) 1 x write ++ */ ++ ret = -EOPNOTSUPP; ++ } ++ ++ mutex_unlock(&d->i2c_mutex); ++ ++ if (ret < 0) ++ return ret; ++ else ++ return num; ++} ++ ++static u32 af9035_i2c_functionality(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static struct i2c_algorithm af9035_i2c_algo = { ++ .master_xfer = af9035_i2c_master_xfer, ++ .functionality = af9035_i2c_functionality, ++}; ++ ++static int af9035_init(struct dvb_usb_device *d) ++{ ++ int ret, i; ++ u16 frame_size = 87 * 188 / 4; ++ u8 packet_size = 512 / 4; ++ struct reg_val_mask tab[] = { ++ { 0x80f99d, 0x01, 0x01 }, ++ { 0x80f9a4, 0x01, 0x01 }, ++ { 0x00dd11, 0x00, 0x20 }, ++ { 0x00dd11, 0x00, 0x40 }, ++ { 0x00dd13, 0x00, 0x20 }, ++ { 0x00dd13, 0x00, 0x40 }, ++ { 0x00dd11, 0x20, 0x20 }, ++ { 0x00dd88, (frame_size >> 0) & 0xff, 0xff}, ++ { 0x00dd89, (frame_size >> 8) & 0xff, 0xff}, ++ { 0x00dd0c, packet_size, 0xff}, ++ { 0x00dd11, af9035_config.dual_mode << 6, 0x40 }, ++ { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff}, ++ { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff}, ++ { 0x00dd0d, packet_size, 0xff }, ++ { 0x80f9a3, 0x00, 0x01 }, ++ { 0x80f9cd, 0x00, 0x01 }, ++ { 0x80f99d, 0x00, 0x01 }, ++ { 0x80f9a4, 0x00, 0x01 }, ++ }; ++ ++ pr_debug("%s: USB speed=%d frame_size=%04x packet_size=%02x\n", ++ __func__, d->udev->speed, frame_size, packet_size); ++ ++ /* init endpoints */ ++ for (i = 0; i < ARRAY_SIZE(tab); i++) { ++ ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val, ++ tab[i].mask); ++ if (ret < 0) ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9035_identify_state(struct usb_device *udev, ++ struct dvb_usb_device_properties *props, ++ struct dvb_usb_device_description **desc, ++ int *cold) ++{ ++ int ret; ++ u8 wbuf[1] = { 1 }; ++ u8 rbuf[4]; ++ struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf, ++ sizeof(rbuf), rbuf }; ++ ++ ret = af9035_ctrl_msg(udev, &req); ++ if (ret < 0) ++ goto err; ++ ++ pr_debug("%s: reply=%02x %02x %02x %02x\n", __func__, ++ rbuf[0], rbuf[1], rbuf[2], rbuf[3]); ++ if (rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3]) ++ *cold = 0; ++ else ++ *cold = 1; ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9035_download_firmware(struct usb_device *udev, ++ const struct firmware *fw) ++{ ++ int ret, i, j, len; ++ u8 wbuf[1]; ++ u8 rbuf[4]; ++ struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; ++ struct usb_req req_fw_dl = { CMD_FW_DL, 0, 0, wbuf, 0, NULL }; ++ struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; ++ u8 hdr_core; ++ u16 hdr_addr, hdr_data_len, hdr_checksum; ++ #define MAX_DATA 57 ++ #define HDR_SIZE 7 ++ ++ /* ++ * Thanks to Daniel Glöckner about that info! ++ * ++ * byte 0: MCS 51 core ++ * There are two inside the AF9035 (1=Link and 2=OFDM) with separate ++ * address spaces ++ * byte 1-2: Big endian destination address ++ * byte 3-4: Big endian number of data bytes following the header ++ * byte 5-6: Big endian header checksum, apparently ignored by the chip ++ * Calculated as ~(h[0]*256+h[1]+h[2]*256+h[3]+h[4]*256) ++ */ ++ ++ for (i = fw->size; i > HDR_SIZE;) { ++ hdr_core = fw->data[fw->size - i + 0]; ++ hdr_addr = fw->data[fw->size - i + 1] << 8; ++ hdr_addr |= fw->data[fw->size - i + 2] << 0; ++ hdr_data_len = fw->data[fw->size - i + 3] << 8; ++ hdr_data_len |= fw->data[fw->size - i + 4] << 0; ++ hdr_checksum = fw->data[fw->size - i + 5] << 8; ++ hdr_checksum |= fw->data[fw->size - i + 6] << 0; ++ ++ pr_debug("%s: core=%d addr=%04x data_len=%d checksum=%04x\n", ++ __func__, hdr_core, hdr_addr, hdr_data_len, ++ hdr_checksum); ++ ++ if (((hdr_core != 1) && (hdr_core != 2)) || ++ (hdr_data_len > i)) { ++ pr_debug("%s: bad firmware\n", __func__); ++ break; ++ } ++ ++ /* download begin packet */ ++ req.cmd = CMD_FW_DL_BEGIN; ++ ret = af9035_ctrl_msg(udev, &req); ++ if (ret < 0) ++ goto err; ++ ++ /* download firmware packet(s) */ ++ for (j = HDR_SIZE + hdr_data_len; j > 0; j -= MAX_DATA) { ++ len = j; ++ if (len > MAX_DATA) ++ len = MAX_DATA; ++ req_fw_dl.wlen = len; ++ req_fw_dl.wbuf = (u8 *) &fw->data[fw->size - i + ++ HDR_SIZE + hdr_data_len - j]; ++ ret = af9035_ctrl_msg(udev, &req_fw_dl); ++ if (ret < 0) ++ goto err; ++ } ++ ++ /* download end packet */ ++ req.cmd = CMD_FW_DL_END; ++ ret = af9035_ctrl_msg(udev, &req); ++ if (ret < 0) ++ goto err; ++ ++ i -= hdr_data_len + HDR_SIZE; ++ ++ pr_debug("%s: data uploaded=%zu\n", __func__, fw->size - i); ++ } ++ ++ /* firmware loaded, request boot */ ++ req.cmd = CMD_FW_BOOT; ++ ret = af9035_ctrl_msg(udev, &req); ++ if (ret < 0) ++ goto err; ++ ++ /* ensure firmware starts */ ++ wbuf[0] = 1; ++ ret = af9035_ctrl_msg(udev, &req_fw_ver); ++ if (ret < 0) ++ goto err; ++ ++ if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { ++ info("firmware did not run"); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ info("firmware version=%d.%d.%d.%d", rbuf[0], rbuf[1], rbuf[2], ++ rbuf[3]); ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9035_download_firmware_it9135(struct usb_device *udev, ++ const struct firmware *fw) ++{ ++ int ret, i, i_prev; ++ u8 wbuf[1]; ++ u8 rbuf[4]; ++ struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; ++ struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR, 0, 0, NULL, 0, NULL }; ++ struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; ++ #define HDR_SIZE 7 ++ ++ /* ++ * There seems to be following firmware header. Meaning of bytes 0-3 ++ * is unknown. ++ * ++ * 0: 3 ++ * 1: 0, 1 ++ * 2: 0 ++ * 3: 1, 2, 3 ++ * 4: addr MSB ++ * 5: addr LSB ++ * 6: count of data bytes ? ++ */ ++ ++ for (i = HDR_SIZE, i_prev = 0; i <= fw->size; i++) { ++ if (i == fw->size || ++ (fw->data[i + 0] == 0x03 && ++ (fw->data[i + 1] == 0x00 || ++ fw->data[i + 1] == 0x01) && ++ fw->data[i + 2] == 0x00)) { ++ req_fw_dl.wlen = i - i_prev; ++ req_fw_dl.wbuf = (u8 *) &fw->data[i_prev]; ++ i_prev = i; ++ ret = af9035_ctrl_msg(udev, &req_fw_dl); ++ if (ret < 0) ++ goto err; ++ ++ pr_debug("%s: data uploaded=%d\n", __func__, i); ++ } ++ } ++ ++ /* firmware loaded, request boot */ ++ req.cmd = CMD_FW_BOOT; ++ ret = af9035_ctrl_msg(udev, &req); ++ if (ret < 0) ++ goto err; ++ ++ /* ensure firmware starts */ ++ wbuf[0] = 1; ++ ret = af9035_ctrl_msg(udev, &req_fw_ver); ++ if (ret < 0) ++ goto err; ++ ++ if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { ++ info("firmware did not run"); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ info("firmware version=%d.%d.%d.%d", rbuf[0], rbuf[1], rbuf[2], ++ rbuf[3]); ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++/* abuse that callback as there is no better one for reading eeprom */ ++static int af9035_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ int ret, i, eeprom_shift = 0; ++ u8 tmp; ++ u16 tmp16; ++ ++ /* check if there is dual tuners */ ++ ret = af9035_rd_reg(d, EEPROM_DUAL_MODE, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ af9035_config.dual_mode = tmp; ++ pr_debug("%s: dual mode=%d\n", __func__, af9035_config.dual_mode); ++ ++ for (i = 0; i < af9035_properties[0].num_adapters; i++) { ++ /* tuner */ ++ ret = af9035_rd_reg(d, EEPROM_1_TUNER_ID + eeprom_shift, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ af9035_af9033_config[i].tuner = tmp; ++ pr_debug("%s: [%d]tuner=%02x\n", __func__, i, tmp); ++ ++ switch (tmp) { ++ case AF9033_TUNER_TUA9001: ++ case AF9033_TUNER_FC0011: ++ case AF9033_TUNER_MXL5007T: ++ case AF9033_TUNER_TDA18218: ++ af9035_af9033_config[i].spec_inv = 1; ++ break; ++ default: ++ af9035_config.hw_not_supported = true; ++ warn("tuner ID=%02x not supported, please report!", ++ tmp); ++ }; ++ ++ /* tuner IF frequency */ ++ ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_L + eeprom_shift, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ tmp16 = tmp; ++ ++ ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_H + eeprom_shift, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ tmp16 |= tmp << 8; ++ ++ pr_debug("%s: [%d]IF=%d\n", __func__, i, tmp16); ++ ++ eeprom_shift = 0x10; /* shift for the 2nd tuner params */ ++ } ++ ++ /* get demod clock */ ++ ret = af9035_rd_reg(d, 0x00d800, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ tmp = (tmp >> 0) & 0x0f; ++ ++ for (i = 0; i < af9035_properties[0].num_adapters; i++) ++ af9035_af9033_config[i].clock = clock_lut[tmp]; ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++/* abuse that callback as there is no better one for reading eeprom */ ++static int af9035_read_mac_address_it9135(struct dvb_usb_device *d, u8 mac[6]) ++{ ++ int ret, i; ++ u8 tmp; ++ ++ af9035_config.dual_mode = 0; ++ ++ /* get demod clock */ ++ ret = af9035_rd_reg(d, 0x00d800, &tmp); ++ if (ret < 0) ++ goto err; ++ ++ tmp = (tmp >> 0) & 0x0f; ++ ++ for (i = 0; i < af9035_properties[0].num_adapters; i++) ++ af9035_af9033_config[i].clock = clock_lut_it9135[tmp]; ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d, ++ int cmd, int arg) ++{ ++ int ret; ++ ++ switch (cmd) { ++ case FC0011_FE_CALLBACK_POWER: ++ /* Tuner enable */ ++ ret = af9035_wr_reg_mask(d, 0xd8eb, 1, 1); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg_mask(d, 0xd8ec, 1, 1); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg_mask(d, 0xd8ed, 1, 1); ++ if (ret < 0) ++ goto err; ++ ++ /* LED */ ++ ret = af9035_wr_reg_mask(d, 0xd8d0, 1, 1); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg_mask(d, 0xd8d1, 1, 1); ++ if (ret < 0) ++ goto err; ++ ++ usleep_range(10000, 50000); ++ break; ++ case FC0011_FE_CALLBACK_RESET: ++ ret = af9035_wr_reg(d, 0xd8e9, 1); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg(d, 0xd8e8, 1); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg(d, 0xd8e7, 1); ++ if (ret < 0) ++ goto err; ++ ++ usleep_range(10000, 20000); ++ ++ ret = af9035_wr_reg(d, 0xd8e7, 0); ++ if (ret < 0) ++ goto err; ++ ++ usleep_range(10000, 20000); ++ break; ++ default: ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static int af9035_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) ++{ ++ switch (af9035_af9033_config[0].tuner) { ++ case AF9033_TUNER_FC0011: ++ return af9035_fc0011_tuner_callback(d, cmd, arg); ++ default: ++ break; ++ } ++ ++ return -ENODEV; ++} ++ ++static int af9035_frontend_callback(void *adapter_priv, int component, ++ int cmd, int arg) ++{ ++ struct i2c_adapter *adap = adapter_priv; ++ struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ ++ switch (component) { ++ case DVB_FRONTEND_COMPONENT_TUNER: ++ return af9035_tuner_callback(d, cmd, arg); ++ default: ++ break; ++ } ++ ++ return -EINVAL; ++} ++ ++static int af9035_frontend_attach(struct dvb_usb_adapter *adap) ++{ ++ int ret; ++ ++ if (af9035_config.hw_not_supported) { ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ if (adap->id == 0) { ++ ret = af9035_wr_reg(adap->dev, 0x00417f, ++ af9035_af9033_config[1].i2c_addr); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg(adap->dev, 0x00d81a, ++ af9035_config.dual_mode); ++ if (ret < 0) ++ goto err; ++ } ++ ++ /* attach demodulator */ ++ adap->fe_adap[0].fe = dvb_attach(af9033_attach, ++ &af9035_af9033_config[adap->id], &adap->dev->i2c_adap); ++ if (adap->fe_adap[0].fe == NULL) { ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ /* disable I2C-gate */ ++ adap->fe_adap[0].fe->ops.i2c_gate_ctrl = NULL; ++ adap->fe_adap[0].fe->callback = af9035_frontend_callback; ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static struct tua9001_config af9035_tua9001_config = { ++ .i2c_addr = 0x60, ++}; ++ ++static const struct fc0011_config af9035_fc0011_config = { ++ .i2c_address = 0x60, ++}; ++ ++static struct mxl5007t_config af9035_mxl5007t_config = { ++ .xtal_freq_hz = MxL_XTAL_24_MHZ, ++ .if_freq_hz = MxL_IF_4_57_MHZ, ++ .invert_if = 0, ++ .loop_thru_enable = 0, ++ .clk_out_enable = 0, ++ .clk_out_amp = MxL_CLKOUT_AMP_0_94V, ++}; ++ ++static struct tda18218_config af9035_tda18218_config = { ++ .i2c_address = 0x60, ++ .i2c_wr_max = 21, ++}; ++ ++static int af9035_tuner_attach(struct dvb_usb_adapter *adap) ++{ ++ int ret; ++ struct dvb_frontend *fe; ++ ++ switch (af9035_af9033_config[adap->id].tuner) { ++ case AF9033_TUNER_TUA9001: ++ /* AF9035 gpiot3 = TUA9001 RESETN ++ AF9035 gpiot2 = TUA9001 RXEN */ ++ ++ /* configure gpiot2 and gpiot2 as output */ ++ ret = af9035_wr_reg_mask(adap->dev, 0x00d8ec, 0x01, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg_mask(adap->dev, 0x00d8ed, 0x01, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg_mask(adap->dev, 0x00d8e8, 0x01, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ ret = af9035_wr_reg_mask(adap->dev, 0x00d8e9, 0x01, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ /* reset tuner */ ++ ret = af9035_wr_reg_mask(adap->dev, 0x00d8e7, 0x00, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ usleep_range(2000, 20000); ++ ++ ret = af9035_wr_reg_mask(adap->dev, 0x00d8e7, 0x01, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ /* activate tuner RX */ ++ /* TODO: use callback for TUA9001 RXEN */ ++ ret = af9035_wr_reg_mask(adap->dev, 0x00d8eb, 0x01, 0x01); ++ if (ret < 0) ++ goto err; ++ ++ /* attach tuner */ ++ fe = dvb_attach(tua9001_attach, adap->fe_adap[0].fe, ++ &adap->dev->i2c_adap, &af9035_tua9001_config); ++ break; ++ case AF9033_TUNER_FC0011: ++ fe = dvb_attach(fc0011_attach, adap->fe_adap[0].fe, ++ &adap->dev->i2c_adap, &af9035_fc0011_config); ++ break; ++ case AF9033_TUNER_MXL5007T: ++ ret = af9035_wr_reg(adap->dev, 0x00d8e0, 1); ++ if (ret < 0) ++ goto err; ++ ret = af9035_wr_reg(adap->dev, 0x00d8e1, 1); ++ if (ret < 0) ++ goto err; ++ ret = af9035_wr_reg(adap->dev, 0x00d8df, 0); ++ if (ret < 0) ++ goto err; ++ ++ msleep(30); ++ ++ ret = af9035_wr_reg(adap->dev, 0x00d8df, 1); ++ if (ret < 0) ++ goto err; ++ ++ msleep(300); ++ ++ ret = af9035_wr_reg(adap->dev, 0x00d8c0, 1); ++ if (ret < 0) ++ goto err; ++ ret = af9035_wr_reg(adap->dev, 0x00d8c1, 1); ++ if (ret < 0) ++ goto err; ++ ret = af9035_wr_reg(adap->dev, 0x00d8bf, 0); ++ if (ret < 0) ++ goto err; ++ ret = af9035_wr_reg(adap->dev, 0x00d8b4, 1); ++ if (ret < 0) ++ goto err; ++ ret = af9035_wr_reg(adap->dev, 0x00d8b5, 1); ++ if (ret < 0) ++ goto err; ++ ret = af9035_wr_reg(adap->dev, 0x00d8b3, 1); ++ if (ret < 0) ++ goto err; ++ ++ /* attach tuner */ ++ fe = dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe, ++ &adap->dev->i2c_adap, 0x60, &af9035_mxl5007t_config); ++ break; ++ case AF9033_TUNER_TDA18218: ++ /* attach tuner */ ++ fe = dvb_attach(tda18218_attach, adap->fe_adap[0].fe, ++ &adap->dev->i2c_adap, &af9035_tda18218_config); ++ break; ++ default: ++ fe = NULL; ++ } ++ ++ if (fe == NULL) { ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++enum af9035_id_entry { ++ AF9035_15A4_9035, ++ AF9035_15A4_1001, ++ AF9035_0CCD_0093, ++ AF9035_07CA_A835, ++ AF9035_07CA_B835, ++ AF9035_07CA_1867, ++ AF9035_07CA_A867, ++ AF9035_07CA_0825, ++}; ++ ++static struct usb_device_id af9035_id[] = { ++ [AF9035_15A4_9035] = { ++ USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035)}, ++ [AF9035_15A4_1001] = { ++ USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_2)}, ++ [AF9035_0CCD_0093] = { ++ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK)}, ++ [AF9035_07CA_A835] = { ++ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835)}, ++ [AF9035_07CA_B835] = { ++ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835)}, ++ [AF9035_07CA_1867] = { ++ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867)}, ++ [AF9035_07CA_A867] = { ++ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867)}, ++ [AF9035_07CA_0825] = { ++ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR)}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(usb, af9035_id); ++ ++static struct dvb_usb_device_properties af9035_properties[] = { ++ { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .download_firmware = af9035_download_firmware, ++ .firmware = "dvb-usb-af9035-02.fw", ++ .no_reconnect = 1, ++ ++ .num_adapters = 1, ++ .adapter = { ++ { ++ .num_frontends = 1, ++ .fe = { ++ { ++ .frontend_attach = af9035_frontend_attach, ++ .tuner_attach = af9035_tuner_attach, ++ .stream = { ++ .type = USB_BULK, ++ .count = 6, ++ .endpoint = 0x84, ++ .u = { ++ .bulk = { ++ .buffersize = (87 * 188), ++ } ++ } ++ } ++ } ++ } ++ } ++ }, ++ ++ .identify_state = af9035_identify_state, ++ .read_mac_address = af9035_read_mac_address, ++ ++ .i2c_algo = &af9035_i2c_algo, ++ ++ .num_device_descs = 5, ++ .devices = { ++ { ++ .name = "Afatech AF9035 reference design", ++ .cold_ids = { ++ &af9035_id[AF9035_15A4_9035], ++ &af9035_id[AF9035_15A4_1001], ++ }, ++ }, { ++ .name = "TerraTec Cinergy T Stick", ++ .cold_ids = { ++ &af9035_id[AF9035_0CCD_0093], ++ }, ++ }, { ++ .name = "AVerMedia AVerTV Volar HD/PRO (A835)", ++ .cold_ids = { ++ &af9035_id[AF9035_07CA_A835], ++ &af9035_id[AF9035_07CA_B835], ++ }, ++ }, { ++ .name = "AVerMedia HD Volar (A867)", ++ .cold_ids = { ++ &af9035_id[AF9035_07CA_1867], ++ &af9035_id[AF9035_07CA_A867], ++ }, ++ }, { ++ .name = "AVerMedia Twinstar (A825)", ++ .cold_ids = { ++ &af9035_id[AF9035_07CA_0825], ++ }, ++ }, ++ } ++ }, ++ { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .download_firmware = af9035_download_firmware_it9135, ++ .firmware = "dvb-usb-it9135-01.fw", ++ .no_reconnect = 1, ++ ++ .num_adapters = 1, ++ .adapter = { ++ { ++ .num_frontends = 1, ++ .fe = { ++ { ++ .frontend_attach = af9035_frontend_attach, ++ .tuner_attach = af9035_tuner_attach, ++ .stream = { ++ .type = USB_BULK, ++ .count = 6, ++ .endpoint = 0x84, ++ .u = { ++ .bulk = { ++ .buffersize = (87 * 188), ++ } ++ } ++ } ++ } ++ } ++ } ++ }, ++ ++ .identify_state = af9035_identify_state, ++ .read_mac_address = af9035_read_mac_address_it9135, ++ ++ .i2c_algo = &af9035_i2c_algo, ++ ++ .num_device_descs = 0, /* disabled as no support for IT9135 */ ++ .devices = { ++ { ++ .name = "ITE Tech. IT9135 reference design", ++ }, ++ } ++ }, ++}; ++ ++static int af9035_usb_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ int ret, i; ++ struct dvb_usb_device *d = NULL; ++ struct usb_device *udev; ++ bool found; ++ ++ pr_debug("%s: interface=%d\n", __func__, ++ intf->cur_altsetting->desc.bInterfaceNumber); ++ ++ /* interface 0 is used by DVB-T receiver and ++ interface 1 is for remote controller (HID) */ ++ if (intf->cur_altsetting->desc.bInterfaceNumber != 0) ++ return 0; ++ ++ /* Dynamic USB ID support. Replaces first device ID with current one. */ ++ udev = interface_to_usbdev(intf); ++ ++ for (i = 0, found = false; i < ARRAY_SIZE(af9035_id) - 1; i++) { ++ if (af9035_id[i].idVendor == ++ le16_to_cpu(udev->descriptor.idVendor) && ++ af9035_id[i].idProduct == ++ le16_to_cpu(udev->descriptor.idProduct)) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) { ++ pr_debug("%s: using dynamic ID %04x:%04x\n", __func__, ++ le16_to_cpu(udev->descriptor.idVendor), ++ le16_to_cpu(udev->descriptor.idProduct)); ++ af9035_properties[0].devices[0].cold_ids[0]->idVendor = ++ le16_to_cpu(udev->descriptor.idVendor); ++ af9035_properties[0].devices[0].cold_ids[0]->idProduct = ++ le16_to_cpu(udev->descriptor.idProduct); ++ } ++ ++ ++ for (i = 0; i < af9035_properties_count; i++) { ++ ret = dvb_usb_device_init(intf, &af9035_properties[i], ++ THIS_MODULE, &d, adapter_nr); ++ ++ if (ret == -ENODEV) ++ continue; ++ else ++ break; ++ } ++ ++ if (ret < 0) ++ goto err; ++ ++ if (d) { ++ ret = af9035_init(d); ++ if (ret < 0) ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ pr_debug("%s: failed=%d\n", __func__, ret); ++ ++ return ret; ++} ++ ++/* usb specific object needed to register this driver with the usb subsystem */ ++static struct usb_driver af9035_usb_driver = { ++ .name = "dvb_usb_af9035", ++ .probe = af9035_usb_probe, ++ .disconnect = dvb_usb_device_exit, ++ .id_table = af9035_id, ++}; ++ ++module_usb_driver(af9035_usb_driver); ++ ++MODULE_AUTHOR("Antti Palosaari "); ++MODULE_DESCRIPTION("Afatech AF9035 driver"); ++MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9035.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9035.h +@@ -0,0 +1,120 @@ ++/* ++ * Afatech AF9035 DVB USB driver ++ * ++ * Copyright (C) 2009 Antti Palosaari ++ * Copyright (C) 2012 Antti Palosaari ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef AF9035_H ++#define AF9035_H ++ ++/* prefix for dvb-usb log writings */ ++#define DVB_USB_LOG_PREFIX "af9035" ++ ++#include "dvb-usb.h" ++ ++struct reg_val { ++ u32 reg; ++ u8 val; ++}; ++ ++struct reg_val_mask { ++ u32 reg; ++ u8 val; ++ u8 mask; ++}; ++ ++struct usb_req { ++ u8 cmd; ++ u8 mbox; ++ u8 wlen; ++ u8 *wbuf; ++ u8 rlen; ++ u8 *rbuf; ++}; ++ ++struct config { ++ bool dual_mode; ++ bool hw_not_supported; ++}; ++ ++struct fw_segment { ++#define SEGMENT_FW_DL 0 ++#define SEGMENT_ROM_COPY 1 ++#define SEGMENT_DIRECT_CMD 2 ++ u8 type; ++ u32 len; ++}; ++ ++struct fw_header { ++#define SEGMENT_MAX_COUNT 6 ++ u8 segment_count; ++ struct fw_segment segment[SEGMENT_MAX_COUNT]; ++}; ++ ++u32 clock_lut[] = { ++ 20480000, /* FPGA */ ++ 16384000, /* 16.38 MHz */ ++ 20480000, /* 20.48 MHz */ ++ 36000000, /* 36.00 MHz */ ++ 30000000, /* 30.00 MHz */ ++ 26000000, /* 26.00 MHz */ ++ 28000000, /* 28.00 MHz */ ++ 32000000, /* 32.00 MHz */ ++ 34000000, /* 34.00 MHz */ ++ 24000000, /* 24.00 MHz */ ++ 22000000, /* 22.00 MHz */ ++ 12000000, /* 12.00 MHz */ ++}; ++ ++u32 clock_lut_it9135[] = { ++ 12000000, /* 12.00 MHz */ ++ 20480000, /* 20.48 MHz */ ++ 36000000, /* 36.00 MHz */ ++ 30000000, /* 30.00 MHz */ ++ 26000000, /* 26.00 MHz */ ++ 28000000, /* 28.00 MHz */ ++ 32000000, /* 32.00 MHz */ ++ 34000000, /* 34.00 MHz */ ++ 24000000, /* 24.00 MHz */ ++ 22000000, /* 22.00 MHz */ ++}; ++ ++/* EEPROM locations */ ++#define EEPROM_IR_MODE 0x430d ++#define EEPROM_DUAL_MODE 0x4326 ++#define EEPROM_IR_TYPE 0x4329 ++#define EEPROM_1_IFFREQ_L 0x432d ++#define EEPROM_1_IFFREQ_H 0x432e ++#define EEPROM_1_TUNER_ID 0x4331 ++#define EEPROM_2_IFFREQ_L 0x433d ++#define EEPROM_2_IFFREQ_H 0x433e ++#define EEPROM_2_TUNER_ID 0x4341 ++ ++/* USB commands */ ++#define CMD_MEM_RD 0x00 ++#define CMD_MEM_WR 0x01 ++#define CMD_I2C_RD 0x02 ++#define CMD_I2C_WR 0x03 ++#define CMD_FW_DL 0x21 ++#define CMD_FW_QUERYINFO 0x22 ++#define CMD_FW_BOOT 0x23 ++#define CMD_FW_DL_BEGIN 0x24 ++#define CMD_FW_DL_END 0x25 ++#define CMD_FW_SCATTER_WR 0x29 ++ ++#endif +Index: linux-3.3.x86_64/MAINTAINERS +=================================================================== +--- linux-3.3.x86_64.orig/MAINTAINERS ++++ linux-3.3.x86_64/MAINTAINERS +@@ -2659,6 +2659,13 @@ S: Maintained + F: Documentation/hwmon/f71805f + F: drivers/hwmon/f71805f.c + ++FC0011 TUNER DRIVER ++M: Michael Buesch ++L: linux-media@vger.kernel.org ++S: Maintained ++F: drivers/media/common/tuners/fc0011.h ++F: drivers/media/common/tuners/fc0011.c ++ + FANOTIFY + M: Eric Paris + S: Maintained +Index: linux-3.3.x86_64/drivers/media/common/tuners/fc0011.c +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/common/tuners/fc0011.c +@@ -0,0 +1,524 @@ ++/* ++ * Fitipower FC0011 tuner driver ++ * ++ * Copyright (C) 2012 Michael Buesch ++ * ++ * Derived from FC0012 tuner driver: ++ * Copyright (C) 2012 Hans-Frieder Vogt ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include "fc0011.h" ++ ++ ++/* Tuner registers */ ++enum { ++ FC11_REG_0, ++ FC11_REG_FA, /* FA */ ++ FC11_REG_FP, /* FP */ ++ FC11_REG_XINHI, /* XIN high 8 bit */ ++ FC11_REG_XINLO, /* XIN low 8 bit */ ++ FC11_REG_VCO, /* VCO */ ++ FC11_REG_VCOSEL, /* VCO select */ ++ FC11_REG_7, /* Unknown tuner reg 7 */ ++ FC11_REG_8, /* Unknown tuner reg 8 */ ++ FC11_REG_9, ++ FC11_REG_10, /* Unknown tuner reg 10 */ ++ FC11_REG_11, /* Unknown tuner reg 11 */ ++ FC11_REG_12, ++ FC11_REG_RCCAL, /* RC calibrate */ ++ FC11_REG_VCOCAL, /* VCO calibrate */ ++ FC11_REG_15, ++ FC11_REG_16, /* Unknown tuner reg 16 */ ++ FC11_REG_17, ++ ++ FC11_NR_REGS, /* Number of registers */ ++}; ++ ++enum FC11_REG_VCOSEL_bits { ++ FC11_VCOSEL_2 = 0x08, /* VCO select 2 */ ++ FC11_VCOSEL_1 = 0x10, /* VCO select 1 */ ++ FC11_VCOSEL_CLKOUT = 0x20, /* Fix clock out */ ++ FC11_VCOSEL_BW7M = 0x40, /* 7MHz bw */ ++ FC11_VCOSEL_BW6M = 0x80, /* 6MHz bw */ ++}; ++ ++enum FC11_REG_RCCAL_bits { ++ FC11_RCCAL_FORCE = 0x10, /* force */ ++}; ++ ++enum FC11_REG_VCOCAL_bits { ++ FC11_VCOCAL_RUN = 0, /* VCO calibration run */ ++ FC11_VCOCAL_VALUEMASK = 0x3F, /* VCO calibration value mask */ ++ FC11_VCOCAL_OK = 0x40, /* VCO calibration Ok */ ++ FC11_VCOCAL_RESET = 0x80, /* VCO calibration reset */ ++}; ++ ++ ++struct fc0011_priv { ++ struct i2c_adapter *i2c; ++ u8 addr; ++ ++ u32 frequency; ++ u32 bandwidth; ++}; ++ ++ ++static int fc0011_writereg(struct fc0011_priv *priv, u8 reg, u8 val) ++{ ++ u8 buf[2] = { reg, val }; ++ struct i2c_msg msg = { .addr = priv->addr, ++ .flags = 0, .buf = buf, .len = 2 }; ++ ++ if (i2c_transfer(priv->i2c, &msg, 1) != 1) { ++ dev_err(&priv->i2c->dev, ++ "I2C write reg failed, reg: %02x, val: %02x\n", ++ reg, val); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int fc0011_readreg(struct fc0011_priv *priv, u8 reg, u8 *val) ++{ ++ u8 dummy; ++ struct i2c_msg msg[2] = { ++ { .addr = priv->addr, ++ .flags = 0, .buf = ®, .len = 1 }, ++ { .addr = priv->addr, ++ .flags = I2C_M_RD, .buf = val ? : &dummy, .len = 1 }, ++ }; ++ ++ if (i2c_transfer(priv->i2c, msg, 2) != 2) { ++ dev_err(&priv->i2c->dev, ++ "I2C read failed, reg: %02x\n", reg); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int fc0011_release(struct dvb_frontend *fe) ++{ ++ kfree(fe->tuner_priv); ++ fe->tuner_priv = NULL; ++ ++ return 0; ++} ++ ++static int fc0011_init(struct dvb_frontend *fe) ++{ ++ struct fc0011_priv *priv = fe->tuner_priv; ++ int err; ++ ++ if (WARN_ON(!fe->callback)) ++ return -EINVAL; ++ ++ err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, ++ FC0011_FE_CALLBACK_POWER, priv->addr); ++ if (err) { ++ dev_err(&priv->i2c->dev, "Power-on callback failed\n"); ++ return err; ++ } ++ err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, ++ FC0011_FE_CALLBACK_RESET, priv->addr); ++ if (err) { ++ dev_err(&priv->i2c->dev, "Reset callback failed\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++/* Initiate VCO calibration */ ++static int fc0011_vcocal_trigger(struct fc0011_priv *priv) ++{ ++ int err; ++ ++ err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RESET); ++ if (err) ++ return err; ++ err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN); ++ if (err) ++ return err; ++ ++ return 0; ++} ++ ++/* Read VCO calibration value */ ++static int fc0011_vcocal_read(struct fc0011_priv *priv, u8 *value) ++{ ++ int err; ++ ++ err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN); ++ if (err) ++ return err; ++ usleep_range(10000, 20000); ++ err = fc0011_readreg(priv, FC11_REG_VCOCAL, value); ++ if (err) ++ return err; ++ ++ return 0; ++} ++ ++static int fc0011_set_params(struct dvb_frontend *fe) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ struct fc0011_priv *priv = fe->tuner_priv; ++ int err; ++ unsigned int i, vco_retries; ++ u32 freq = p->frequency / 1000; ++ u32 bandwidth = p->bandwidth_hz / 1000; ++ u32 fvco, xin, xdiv, xdivr; ++ u16 frac; ++ u8 fa, fp, vco_sel, vco_cal; ++ u8 regs[FC11_NR_REGS] = { }; ++ ++ regs[FC11_REG_7] = 0x0F; ++ regs[FC11_REG_8] = 0x3E; ++ regs[FC11_REG_10] = 0xB8; ++ regs[FC11_REG_11] = 0x80; ++ regs[FC11_REG_RCCAL] = 0x04; ++ err = fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]); ++ err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]); ++ err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]); ++ err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]); ++ err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]); ++ if (err) ++ return -EIO; ++ ++ /* Set VCO freq and VCO div */ ++ if (freq < 54000) { ++ fvco = freq * 64; ++ regs[FC11_REG_VCO] = 0x82; ++ } else if (freq < 108000) { ++ fvco = freq * 32; ++ regs[FC11_REG_VCO] = 0x42; ++ } else if (freq < 216000) { ++ fvco = freq * 16; ++ regs[FC11_REG_VCO] = 0x22; ++ } else if (freq < 432000) { ++ fvco = freq * 8; ++ regs[FC11_REG_VCO] = 0x12; ++ } else { ++ fvco = freq * 4; ++ regs[FC11_REG_VCO] = 0x0A; ++ } ++ ++ /* Calc XIN. The PLL reference frequency is 18 MHz. */ ++ xdiv = fvco / 18000; ++ frac = fvco - xdiv * 18000; ++ frac = (frac << 15) / 18000; ++ if (frac >= 16384) ++ frac += 32786; ++ if (!frac) ++ xin = 0; ++ else if (frac < 511) ++ xin = 512; ++ else if (frac < 65026) ++ xin = frac; ++ else ++ xin = 65024; ++ regs[FC11_REG_XINHI] = xin >> 8; ++ regs[FC11_REG_XINLO] = xin; ++ ++ /* Calc FP and FA */ ++ xdivr = xdiv; ++ if (fvco - xdiv * 18000 >= 9000) ++ xdivr += 1; /* round */ ++ fp = xdivr / 8; ++ fa = xdivr - fp * 8; ++ if (fa < 2) { ++ fp -= 1; ++ fa += 8; ++ } ++ if (fp > 0x1F) { ++ fp &= 0x1F; ++ fa &= 0xF; ++ } ++ if (fa >= fp) { ++ dev_warn(&priv->i2c->dev, ++ "fa %02X >= fp %02X, but trying to continue\n", ++ (unsigned int)(u8)fa, (unsigned int)(u8)fp); ++ } ++ regs[FC11_REG_FA] = fa; ++ regs[FC11_REG_FP] = fp; ++ ++ /* Select bandwidth */ ++ switch (bandwidth) { ++ case 8000: ++ break; ++ case 7000: ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW7M; ++ break; ++ default: ++ dev_warn(&priv->i2c->dev, "Unsupported bandwidth %u kHz. " ++ "Using 6000 kHz.\n", ++ bandwidth); ++ bandwidth = 6000; ++ /* fallthrough */ ++ case 6000: ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW6M; ++ break; ++ } ++ ++ /* Pre VCO select */ ++ if (fvco < 2320000) { ++ vco_sel = 0; ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ } else if (fvco < 3080000) { ++ vco_sel = 1; ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1; ++ } else { ++ vco_sel = 2; ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2; ++ } ++ ++ /* Fix for low freqs */ ++ if (freq < 45000) { ++ regs[FC11_REG_FA] = 0x6; ++ regs[FC11_REG_FP] = 0x11; ++ } ++ ++ /* Clock out fix */ ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_CLKOUT; ++ ++ /* Write the cached registers */ ++ for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++) { ++ err = fc0011_writereg(priv, i, regs[i]); ++ if (err) ++ return err; ++ } ++ ++ /* VCO calibration */ ++ err = fc0011_vcocal_trigger(priv); ++ if (err) ++ return err; ++ err = fc0011_vcocal_read(priv, &vco_cal); ++ if (err) ++ return err; ++ vco_retries = 0; ++ while (!(vco_cal & FC11_VCOCAL_OK) && vco_retries < 3) { ++ /* Reset the tuner and try again */ ++ err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, ++ FC0011_FE_CALLBACK_RESET, priv->addr); ++ if (err) { ++ dev_err(&priv->i2c->dev, "Failed to reset tuner\n"); ++ return err; ++ } ++ /* Reinit tuner config */ ++ err = 0; ++ for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++) ++ err |= fc0011_writereg(priv, i, regs[i]); ++ err |= fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]); ++ err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]); ++ err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]); ++ err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]); ++ err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]); ++ if (err) ++ return -EIO; ++ /* VCO calibration */ ++ err = fc0011_vcocal_trigger(priv); ++ if (err) ++ return err; ++ err = fc0011_vcocal_read(priv, &vco_cal); ++ if (err) ++ return err; ++ vco_retries++; ++ } ++ if (!(vco_cal & FC11_VCOCAL_OK)) { ++ dev_err(&priv->i2c->dev, ++ "Failed to read VCO calibration value (got %02X)\n", ++ (unsigned int)vco_cal); ++ return -EIO; ++ } ++ vco_cal &= FC11_VCOCAL_VALUEMASK; ++ ++ switch (vco_sel) { ++ case 0: ++ if (vco_cal < 8) { ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1; ++ err = fc0011_writereg(priv, FC11_REG_VCOSEL, ++ regs[FC11_REG_VCOSEL]); ++ if (err) ++ return err; ++ err = fc0011_vcocal_trigger(priv); ++ if (err) ++ return err; ++ } else { ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ err = fc0011_writereg(priv, FC11_REG_VCOSEL, ++ regs[FC11_REG_VCOSEL]); ++ if (err) ++ return err; ++ } ++ break; ++ case 1: ++ if (vco_cal < 5) { ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2; ++ err = fc0011_writereg(priv, FC11_REG_VCOSEL, ++ regs[FC11_REG_VCOSEL]); ++ if (err) ++ return err; ++ err = fc0011_vcocal_trigger(priv); ++ if (err) ++ return err; ++ } else if (vco_cal <= 48) { ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1; ++ err = fc0011_writereg(priv, FC11_REG_VCOSEL, ++ regs[FC11_REG_VCOSEL]); ++ if (err) ++ return err; ++ } else { ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ err = fc0011_writereg(priv, FC11_REG_VCOSEL, ++ regs[FC11_REG_VCOSEL]); ++ if (err) ++ return err; ++ err = fc0011_vcocal_trigger(priv); ++ if (err) ++ return err; ++ } ++ break; ++ case 2: ++ if (vco_cal > 53) { ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1; ++ err = fc0011_writereg(priv, FC11_REG_VCOSEL, ++ regs[FC11_REG_VCOSEL]); ++ if (err) ++ return err; ++ err = fc0011_vcocal_trigger(priv); ++ if (err) ++ return err; ++ } else { ++ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); ++ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2; ++ err = fc0011_writereg(priv, FC11_REG_VCOSEL, ++ regs[FC11_REG_VCOSEL]); ++ if (err) ++ return err; ++ } ++ break; ++ } ++ err = fc0011_vcocal_read(priv, NULL); ++ if (err) ++ return err; ++ usleep_range(10000, 50000); ++ ++ err = fc0011_readreg(priv, FC11_REG_RCCAL, ®s[FC11_REG_RCCAL]); ++ if (err) ++ return err; ++ regs[FC11_REG_RCCAL] |= FC11_RCCAL_FORCE; ++ err = fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]); ++ if (err) ++ return err; ++ err = fc0011_writereg(priv, FC11_REG_16, 0xB); ++ if (err) ++ return err; ++ ++ dev_dbg(&priv->i2c->dev, "Tuned to " ++ "fa=%02X fp=%02X xin=%02X%02X vco=%02X vcosel=%02X " ++ "vcocal=%02X(%u) bw=%u\n", ++ (unsigned int)regs[FC11_REG_FA], ++ (unsigned int)regs[FC11_REG_FP], ++ (unsigned int)regs[FC11_REG_XINHI], ++ (unsigned int)regs[FC11_REG_XINLO], ++ (unsigned int)regs[FC11_REG_VCO], ++ (unsigned int)regs[FC11_REG_VCOSEL], ++ (unsigned int)vco_cal, vco_retries, ++ (unsigned int)bandwidth); ++ ++ priv->frequency = p->frequency; ++ priv->bandwidth = p->bandwidth_hz; ++ ++ return 0; ++} ++ ++static int fc0011_get_frequency(struct dvb_frontend *fe, u32 *frequency) ++{ ++ struct fc0011_priv *priv = fe->tuner_priv; ++ ++ *frequency = priv->frequency; ++ ++ return 0; ++} ++ ++static int fc0011_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) ++{ ++ *frequency = 0; ++ ++ return 0; ++} ++ ++static int fc0011_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) ++{ ++ struct fc0011_priv *priv = fe->tuner_priv; ++ ++ *bandwidth = priv->bandwidth; ++ ++ return 0; ++} ++ ++static const struct dvb_tuner_ops fc0011_tuner_ops = { ++ .info = { ++ .name = "Fitipower FC0011", ++ ++ .frequency_min = 45000000, ++ .frequency_max = 1000000000, ++ }, ++ ++ .release = fc0011_release, ++ .init = fc0011_init, ++ ++ .set_params = fc0011_set_params, ++ ++ .get_frequency = fc0011_get_frequency, ++ .get_if_frequency = fc0011_get_if_frequency, ++ .get_bandwidth = fc0011_get_bandwidth, ++}; ++ ++struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, ++ const struct fc0011_config *config) ++{ ++ struct fc0011_priv *priv; ++ ++ priv = kzalloc(sizeof(struct fc0011_priv), GFP_KERNEL); ++ if (!priv) ++ return NULL; ++ ++ priv->i2c = i2c; ++ priv->addr = config->i2c_address; ++ ++ fe->tuner_priv = priv; ++ fe->ops.tuner_ops = fc0011_tuner_ops; ++ ++ dev_info(&priv->i2c->dev, "Fitipower FC0011 tuner attached\n"); ++ ++ return fe; ++} ++EXPORT_SYMBOL(fc0011_attach); ++ ++MODULE_DESCRIPTION("Fitipower FC0011 silicon tuner driver"); ++MODULE_AUTHOR("Michael Buesch "); ++MODULE_LICENSE("GPL"); +Index: linux-3.3.x86_64/drivers/media/common/tuners/fc0011.h +=================================================================== +--- /dev/null ++++ linux-3.3.x86_64/drivers/media/common/tuners/fc0011.h +@@ -0,0 +1,41 @@ ++#ifndef LINUX_FC0011_H_ ++#define LINUX_FC0011_H_ ++ ++#include "dvb_frontend.h" ++ ++ ++/** struct fc0011_config - fc0011 hardware config ++ * ++ * @i2c_address: I2C bus address. ++ */ ++struct fc0011_config { ++ u8 i2c_address; ++}; ++ ++/** enum fc0011_fe_callback_commands - Frontend callbacks ++ * ++ * @FC0011_FE_CALLBACK_POWER: Power on tuner hardware. ++ * @FC0011_FE_CALLBACK_RESET: Request a tuner reset. ++ */ ++enum fc0011_fe_callback_commands { ++ FC0011_FE_CALLBACK_POWER, ++ FC0011_FE_CALLBACK_RESET, ++}; ++ ++#if defined(CONFIG_MEDIA_TUNER_FC0011) ||\ ++ defined(CONFIG_MEDIA_TUNER_FC0011_MODULE) ++struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, ++ const struct fc0011_config *config); ++#else ++static inline ++struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, ++ const struct fc0011_config *config) ++{ ++ dev_err(&i2c->dev, "fc0011 driver disabled in Kconfig\n"); ++ return NULL; ++} ++#endif ++ ++#endif /* LINUX_FC0011_H_ */ diff --git a/kernel.spec b/kernel.spec index 220bafc57..f23624fe1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -708,10 +708,7 @@ Patch1900: linux-2.6-intel-iommu-igfx.patch Patch2802: linux-2.6-silence-acpi-blacklist.patch # media patches -Patch2899: linux-2.6-v4l-dvb-fixes.patch -Patch2900: linux-2.6-v4l-dvb-update.patch -Patch2901: linux-2.6-v4l-dvb-experimental.patch -Patch2902: linux-2.6-v4l-dvb-uvcvideo-update.patch +Patch2903: drivers-media-update.patch # fs fixes @@ -1412,9 +1409,7 @@ ApplyPatch quite-apm.patch # V4L/DVB updates/fixes/experimental drivers # apply if non-empty -ApplyOptionalPatch linux-2.6-v4l-dvb-fixes.patch -ApplyOptionalPatch linux-2.6-v4l-dvb-update.patch -ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch +ApplyOptionalPatch drivers-media-update.patch # Patches headed upstream @@ -2230,6 +2225,9 @@ fi # and build. %changelog +* Tue Apr 10 2012 Mauro Carvalho Chehab +- Update media tree to what's there at Kernel 3.4-rc2 + fixes for -rc3 + * Thu Apr 05 2012 Dave Jones - Better watermark the number of pages used by hibernation I/O (Bojan Smojver) (rhbz 785384) diff --git a/linux-2.6-v4l-dvb-experimental.patch b/linux-2.6-v4l-dvb-experimental.patch deleted file mode 100644 index e69de29bb..000000000 diff --git a/linux-2.6-v4l-dvb-fixes.patch b/linux-2.6-v4l-dvb-fixes.patch deleted file mode 100644 index e69de29bb..000000000 diff --git a/linux-2.6-v4l-dvb-update.patch b/linux-2.6-v4l-dvb-update.patch deleted file mode 100644 index e69de29bb..000000000 From d925593ef23336f24f556d2614a1a618fb6bcd65 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Apr 2012 09:57:59 -0300 Subject: [PATCH 344/487] Add a few missing new options + cat .newoptions CONFIG_VIDEO_ADV7183 CONFIG_VIDEO_VS6624 CONFIG_VIDEO_MT9M032 RPM build errors: Those three options are used by embedded device drivers. Not needed elsewhere. Signed-off-by: Mauro Carvalho Chehab --- config-generic | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config-generic b/config-generic index 3766af795..681fc3056 100644 --- a/config-generic +++ b/config-generic @@ -2658,6 +2658,9 @@ CONFIG_VIDEO_TM6000=m CONFIG_VIDEO_TM6000_ALSA=m CONFIG_VIDEO_TM6000_DVB=m CONFIG_VIDEO_TLG2300=m +# CONFIG_VIDEO_ADV7183 is not set +# CONFIG_VIDEO_VS6624 is not set +# CONFIG_VIDEO_MT9M032 is not set CONFIG_IR_GPIO_CIR=m CONFIG_MEDIA_TUNER_FC0011=m From 727bb89cc2516ef3378de463f9124a4186cafbc4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 10 Apr 2012 09:11:21 -0400 Subject: [PATCH 345/487] Backport fixes for correct register constraints in cmpxchg.h (rhbz 809014) --- kernel.spec | 13 ++++++- ...e-sized-register-constraint-in-__add.patch | 35 +++++++++++++++++++ ...zed-register-constraint-in-__xchg_op.patch | 32 +++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 x86-Use-correct-byte-sized-register-constraint-in-__add.patch create mode 100644 x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch diff --git a/kernel.spec b/kernel.spec index f23624fe1..2494ae37a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -790,6 +790,10 @@ Patch21380: wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch #rhbz 806676 807632 Patch21385: libata-disable-runtime-pm-for-hotpluggable-port.patch +#rhbz 809014 +Patch21390: x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch +Patch21391: x86-Use-correct-byte-sized-register-constraint-in-__add.patch + Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch #rhbz 808207 CVE-2012-1601 @@ -1487,6 +1491,10 @@ ApplyPatch wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch #rhbz 806676 807632 ApplyPatch libata-disable-runtime-pm-for-hotpluggable-port.patch +#rhbz 809014 +ApplyPatch x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch +ApplyPatch x86-Use-correct-byte-sized-register-constraint-in-__add.patch + # END OF PATCH APPLICATIONS %endif @@ -2225,6 +2233,9 @@ fi # and build. %changelog +* Tue Apr 10 2012 Josh Boyer +- Backport fixes for correct register constraints in cmpxchg.h (rhbz 809014) + * Tue Apr 10 2012 Mauro Carvalho Chehab - Update media tree to what's there at Kernel 3.4-rc2 + fixes for -rc3 diff --git a/x86-Use-correct-byte-sized-register-constraint-in-__add.patch b/x86-Use-correct-byte-sized-register-constraint-in-__add.patch new file mode 100644 index 000000000..3ec765691 --- /dev/null +++ b/x86-Use-correct-byte-sized-register-constraint-in-__add.patch @@ -0,0 +1,35 @@ +From: H. Peter Anvin +Date: Fri, 6 Apr 2012 16:30:57 +0000 (-0700) +Subject: x86: Use correct byte-sized register constraint in __add() +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftip%2Ftip.git;a=commitdiff_plain;h=8c91c5325e107ec17e40a59a47c6517387d64eb7 + +x86: Use correct byte-sized register constraint in __add() + +Similar to: + + 2ca052a x86: Use correct byte-sized register constraint in __xchg_op() + +... the __add() macro also needs to use a "q" constraint in the +byte-sized case, lest we try to generate an illegal register. + +Link: http://lkml.kernel.org/r/4F7A3315.501@goop.org +Signed-off-by: H. Peter Anvin +Cc: Jeremy Fitzhardinge +Cc: Leigh Scott +Cc: Thomas Reitmayr +Cc: v3.3 +--- + +diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h +index bc18d0e..99480e5 100644 +--- a/arch/x86/include/asm/cmpxchg.h ++++ b/arch/x86/include/asm/cmpxchg.h +@@ -173,7 +173,7 @@ extern void __add_wrong_size(void) + switch (sizeof(*(ptr))) { \ + case __X86_CASE_B: \ + asm volatile (lock "addb %b1, %0\n" \ +- : "+m" (*(ptr)) : "ri" (inc) \ ++ : "+m" (*(ptr)) : "qi" (inc) \ + : "memory", "cc"); \ + break; \ + case __X86_CASE_W: \ diff --git a/x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch b/x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch new file mode 100644 index 000000000..a33602f9f --- /dev/null +++ b/x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch @@ -0,0 +1,32 @@ +From: Jeremy Fitzhardinge +Date: Mon, 2 Apr 2012 23:15:33 +0000 (-0700) +Subject: x86: Use correct byte-sized register constraint in __xchg_op() +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftip%2Ftip.git;a=commitdiff_plain;h=2ca052a3710fac208eee690faefdeb8bbd4586a1 + +x86: Use correct byte-sized register constraint in __xchg_op() + +x86-64 can access the low half of any register, but i386 can only do +it with a subset of registers. 'r' causes compilation failures on i386, +but 'q' expresses the constraint properly. + +Signed-off-by: Jeremy Fitzhardinge +Link: http://lkml.kernel.org/r/4F7A3315.501@goop.org +Reported-by: Leigh Scott +Tested-by: Thomas Reitmayr +Signed-off-by: H. Peter Anvin +Cc: v3.3 +--- + +diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h +index b3b7332..bc18d0e 100644 +--- a/arch/x86/include/asm/cmpxchg.h ++++ b/arch/x86/include/asm/cmpxchg.h +@@ -43,7 +43,7 @@ extern void __add_wrong_size(void) + switch (sizeof(*(ptr))) { \ + case __X86_CASE_B: \ + asm volatile (lock #op "b %b0, %1\n" \ +- : "+r" (__ret), "+m" (*(ptr)) \ ++ : "+q" (__ret), "+m" (*(ptr)) \ + : : "memory", "cc"); \ + break; \ + case __X86_CASE_W: \ From 15d159a8875ac4063340ee4debfb89eeda70116f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Apr 2012 10:27:45 -0300 Subject: [PATCH 346/487] Add poll_requested_events The new events interface requires this function in order to work. Signed-off-by: Mauro Carvalho Chehab --- add-poll-requested-events.patch | 393 ++++++++++++++++++++++++++++++++ kernel.spec | 7 +- 2 files changed, 398 insertions(+), 2 deletions(-) create mode 100644 add-poll-requested-events.patch diff --git a/add-poll-requested-events.patch b/add-poll-requested-events.patch new file mode 100644 index 000000000..dafd359e1 --- /dev/null +++ b/add-poll-requested-events.patch @@ -0,0 +1,393 @@ +commit 626cf236608505d376e4799adb4f7eb00a8594af +Author: Hans Verkuil +Date: Fri Mar 23 15:02:27 2012 -0700 + + poll: add poll_requested_events() and poll_does_not_wait() functions + + In some cases the poll() implementation in a driver has to do different + things depending on the events the caller wants to poll for. An example + is when a driver needs to start a DMA engine if the caller polls for + POLLIN, but doesn't want to do that if POLLIN is not requested but instead + only POLLOUT or POLLPRI is requested. This is something that can happen + in the video4linux subsystem among others. + + Unfortunately, the current epoll/poll/select implementation doesn't + provide that information reliably. The poll_table_struct does have it: it + has a key field with the event mask. But once a poll() call matches one + or more bits of that mask any following poll() calls are passed a NULL + poll_table pointer. + + Also, the eventpoll implementation always left the key field at ~0 instead + of using the requested events mask. + + This was changed in eventpoll.c so the key field now contains the actual + events that should be polled for as set by the caller. + + The solution to the NULL poll_table pointer is to set the qproc field to + NULL in poll_table once poll() matches the events, not the poll_table + pointer itself. That way drivers can obtain the mask through a new + poll_requested_events inline. + + The poll_table_struct can still be NULL since some kernel code calls it + internally (netfs_state_poll() in ./drivers/staging/pohmelfs/netfs.h). In + that case poll_requested_events() returns ~0 (i.e. all events). + + Very rarely drivers might want to know whether poll_wait will actually + wait. If another earlier file descriptor in the set already matched the + events the caller wanted to wait for, then the kernel will return from the + select() call without waiting. This might be useful information in order + to avoid doing expensive work. + + A new helper function poll_does_not_wait() is added that drivers can use + to detect this situation. This is now used in sock_poll_wait() in + include/net/sock.h. This was the only place in the kernel that needed + this information. + + Drivers should no longer access any of the poll_table internals, but use + the poll_requested_events() and poll_does_not_wait() access functions + instead. In order to enforce that the poll_table fields are now prepended + with an underscore and a comment was added warning against using them + directly. + + This required a change in unix_dgram_poll() in unix/af_unix.c which used + the key field to get the requested events. It's been replaced by a call + to poll_requested_events(). + + For qproc it was especially important to change its name since the + behavior of that field changes with this patch since this function pointer + can now be NULL when that wasn't possible in the past. + + Any driver accessing the qproc or key fields directly will now fail to compile. + + Some notes regarding the correctness of this patch: the driver's poll() + function is called with a 'struct poll_table_struct *wait' argument. This + pointer may or may not be NULL, drivers can never rely on it being one or + the other as that depends on whether or not an earlier file descriptor in + the select()'s fdset matched the requested events. + + There are only three things a driver can do with the wait argument: + + 1) obtain the key field: + + events = wait ? wait->key : ~0; + + This will still work although it should be replaced with the new + poll_requested_events() function (which does exactly the same). + This will now even work better, since wait is no longer set to NULL + unnecessarily. + + 2) use the qproc callback. This could be deadly since qproc can now be + NULL. Renaming qproc should prevent this from happening. There are no + kernel drivers that actually access this callback directly, BTW. + + 3) test whether wait == NULL to determine whether poll would return without + waiting. This is no longer sufficient as the correct test is now + wait == NULL || wait->_qproc == NULL. + + However, the worst that can happen here is a slight performance hit in + the case where wait != NULL and wait->_qproc == NULL. In that case the + driver will assume that poll_wait() will actually add the fd to the set + of waiting file descriptors. Of course, poll_wait() will not do that + since it tests for wait->_qproc. This will not break anything, though. + + There is only one place in the whole kernel where this happens + (sock_poll_wait() in include/net/sock.h) and that code will be replaced + by a call to poll_does_not_wait() in the next patch. + + Note that even if wait->_qproc != NULL drivers cannot rely on poll_wait() + actually waiting. The next file descriptor from the set might match the + event mask and thus any possible waits will never happen. + + Signed-off-by: Hans Verkuil + Reviewed-by: Jonathan Corbet + Reviewed-by: Al Viro + Cc: Davide Libenzi + Signed-off-by: Hans de Goede + Cc: Mauro Carvalho Chehab + Cc: David Miller + Cc: Eric Dumazet + Signed-off-by: Andrew Morton + Signed-off-by: Linus Torvalds + +diff --git a/fs/eventpoll.c b/fs/eventpoll.c +index 4d9d3a4..ca30007 100644 +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -699,9 +699,12 @@ static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head, + void *priv) + { + struct epitem *epi, *tmp; ++ poll_table pt; + ++ init_poll_funcptr(&pt, NULL); + list_for_each_entry_safe(epi, tmp, head, rdllink) { +- if (epi->ffd.file->f_op->poll(epi->ffd.file, NULL) & ++ pt._key = epi->event.events; ++ if (epi->ffd.file->f_op->poll(epi->ffd.file, &pt) & + epi->event.events) + return POLLIN | POLLRDNORM; + else { +@@ -1097,6 +1100,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, + /* Initialize the poll table using the queue callback */ + epq.epi = epi; + init_poll_funcptr(&epq.pt, ep_ptable_queue_proc); ++ epq.pt._key = event->events; + + /* + * Attach the item to the poll hooks and get current event bits. +@@ -1191,6 +1195,9 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even + { + int pwake = 0; + unsigned int revents; ++ poll_table pt; ++ ++ init_poll_funcptr(&pt, NULL); + + /* + * Set the new event interest mask before calling f_op->poll(); +@@ -1198,13 +1205,14 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even + * f_op->poll() call and the new event set registering. + */ + epi->event.events = event->events; ++ pt._key = event->events; + epi->event.data = event->data; /* protected by mtx */ + + /* + * Get current event bits. We can safely use the file* here because + * its usage count has been increased by the caller of this function. + */ +- revents = epi->ffd.file->f_op->poll(epi->ffd.file, NULL); ++ revents = epi->ffd.file->f_op->poll(epi->ffd.file, &pt); + + /* + * If the item is "hot" and it is not registered inside the ready +@@ -1239,6 +1247,9 @@ static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head, + unsigned int revents; + struct epitem *epi; + struct epoll_event __user *uevent; ++ poll_table pt; ++ ++ init_poll_funcptr(&pt, NULL); + + /* + * We can loop without lock because we are passed a task private list. +@@ -1251,7 +1262,8 @@ static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head, + + list_del_init(&epi->rdllink); + +- revents = epi->ffd.file->f_op->poll(epi->ffd.file, NULL) & ++ pt._key = epi->event.events; ++ revents = epi->ffd.file->f_op->poll(epi->ffd.file, &pt) & + epi->event.events; + + /* +diff --git a/fs/select.c b/fs/select.c +index e782258..ecfd0b1 100644 +--- a/fs/select.c ++++ b/fs/select.c +@@ -223,7 +223,7 @@ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, + get_file(filp); + entry->filp = filp; + entry->wait_address = wait_address; +- entry->key = p->key; ++ entry->key = p->_key; + init_waitqueue_func_entry(&entry->wait, pollwake); + entry->wait.private = pwq; + add_wait_queue(wait_address, &entry->wait); +@@ -386,13 +386,11 @@ get_max: + static inline void wait_key_set(poll_table *wait, unsigned long in, + unsigned long out, unsigned long bit) + { +- if (wait) { +- wait->key = POLLEX_SET; +- if (in & bit) +- wait->key |= POLLIN_SET; +- if (out & bit) +- wait->key |= POLLOUT_SET; +- } ++ wait->_key = POLLEX_SET; ++ if (in & bit) ++ wait->_key |= POLLIN_SET; ++ if (out & bit) ++ wait->_key |= POLLOUT_SET; + } + + int do_select(int n, fd_set_bits *fds, struct timespec *end_time) +@@ -414,7 +412,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) + poll_initwait(&table); + wait = &table.pt; + if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { +- wait = NULL; ++ wait->_qproc = NULL; + timed_out = 1; + } + +@@ -459,17 +457,17 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) + if ((mask & POLLIN_SET) && (in & bit)) { + res_in |= bit; + retval++; +- wait = NULL; ++ wait->_qproc = NULL; + } + if ((mask & POLLOUT_SET) && (out & bit)) { + res_out |= bit; + retval++; +- wait = NULL; ++ wait->_qproc = NULL; + } + if ((mask & POLLEX_SET) && (ex & bit)) { + res_ex |= bit; + retval++; +- wait = NULL; ++ wait->_qproc = NULL; + } + } + } +@@ -481,7 +479,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) + *rexp = res_ex; + cond_resched(); + } +- wait = NULL; ++ wait->_qproc = NULL; + if (retval || timed_out || signal_pending(current)) + break; + if (table.error) { +@@ -720,7 +718,7 @@ struct poll_list { + * interested in events matching the pollfd->events mask, and the result + * matching that mask is both recorded in pollfd->revents and returned. The + * pwait poll_table will be used by the fd-provided poll handler for waiting, +- * if non-NULL. ++ * if pwait->_qproc is non-NULL. + */ + static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait) + { +@@ -738,9 +736,7 @@ static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait) + if (file != NULL) { + mask = DEFAULT_POLLMASK; + if (file->f_op && file->f_op->poll) { +- if (pwait) +- pwait->key = pollfd->events | +- POLLERR | POLLHUP; ++ pwait->_key = pollfd->events|POLLERR|POLLHUP; + mask = file->f_op->poll(file, pwait); + } + /* Mask out unneeded events. */ +@@ -763,7 +759,7 @@ static int do_poll(unsigned int nfds, struct poll_list *list, + + /* Optimise the no-wait case */ + if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { +- pt = NULL; ++ pt->_qproc = NULL; + timed_out = 1; + } + +@@ -781,22 +777,22 @@ static int do_poll(unsigned int nfds, struct poll_list *list, + for (; pfd != pfd_end; pfd++) { + /* + * Fish for events. If we found one, record it +- * and kill the poll_table, so we don't ++ * and kill poll_table->_qproc, so we don't + * needlessly register any other waiters after + * this. They'll get immediately deregistered + * when we break out and return. + */ + if (do_pollfd(pfd, pt)) { + count++; +- pt = NULL; ++ pt->_qproc = NULL; + } + } + } + /* + * All waiters have already been registered, so don't provide +- * a poll_table to them on the next loop iteration. ++ * a poll_table->_qproc to them on the next loop iteration. + */ +- pt = NULL; ++ pt->_qproc = NULL; + if (!count) { + count = wait->error; + if (signal_pending(current)) +diff --git a/include/linux/poll.h b/include/linux/poll.h +index cf40010..48fe8bc 100644 +--- a/include/linux/poll.h ++++ b/include/linux/poll.h +@@ -32,21 +32,46 @@ struct poll_table_struct; + */ + typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *); + ++/* ++ * Do not touch the structure directly, use the access functions ++ * poll_does_not_wait() and poll_requested_events() instead. ++ */ + typedef struct poll_table_struct { +- poll_queue_proc qproc; +- unsigned long key; ++ poll_queue_proc _qproc; ++ unsigned long _key; + } poll_table; + + static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p) + { +- if (p && wait_address) +- p->qproc(filp, wait_address, p); ++ if (p && p->_qproc && wait_address) ++ p->_qproc(filp, wait_address, p); ++} ++ ++/* ++ * Return true if it is guaranteed that poll will not wait. This is the case ++ * if the poll() of another file descriptor in the set got an event, so there ++ * is no need for waiting. ++ */ ++static inline bool poll_does_not_wait(const poll_table *p) ++{ ++ return p == NULL || p->_qproc == NULL; ++} ++ ++/* ++ * Return the set of events that the application wants to poll for. ++ * This is useful for drivers that need to know whether a DMA transfer has ++ * to be started implicitly on poll(). You typically only want to do that ++ * if the application is actually polling for POLLIN and/or POLLOUT. ++ */ ++static inline unsigned long poll_requested_events(const poll_table *p) ++{ ++ return p ? p->_key : ~0UL; + } + + static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc) + { +- pt->qproc = qproc; +- pt->key = ~0UL; /* all events enabled */ ++ pt->_qproc = qproc; ++ pt->_key = ~0UL; /* all events enabled */ + } + + struct poll_table_entry { +diff --git a/include/net/sock.h b/include/net/sock.h +index 04bc0b3..a6ba1f8 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -1854,7 +1854,7 @@ static inline bool wq_has_sleeper(struct socket_wq *wq) + static inline void sock_poll_wait(struct file *filp, + wait_queue_head_t *wait_address, poll_table *p) + { +- if (p && wait_address) { ++ if (!poll_does_not_wait(p) && wait_address) { + poll_wait(filp, wait_address, p); + /* + * We need to be sure we are in sync with the +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index eb4277c..d510353 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -2206,7 +2206,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, + } + + /* No write status requested, avoid expensive OUT tests. */ +- if (wait && !(wait->key & (POLLWRBAND | POLLWRNORM | POLLOUT))) ++ if (!(poll_requested_events(wait) & (POLLWRBAND|POLLWRNORM|POLLOUT))) + return mask; + + writable = unix_writable(sk); diff --git a/kernel.spec b/kernel.spec index 2494ae37a..c21dc3e2b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -708,7 +708,9 @@ Patch1900: linux-2.6-intel-iommu-igfx.patch Patch2802: linux-2.6-silence-acpi-blacklist.patch # media patches -Patch2903: drivers-media-update.patch +# add-poll-requested-events.patch was added for 3.4 +Patch2900: add-poll-requested-events.patch +Patch2901: drivers-media-update.patch # fs fixes @@ -1411,8 +1413,9 @@ ApplyPatch linux-2.6-intel-iommu-igfx.patch ApplyPatch linux-2.6-silence-acpi-blacklist.patch ApplyPatch quite-apm.patch -# V4L/DVB updates/fixes/experimental drivers +# Media (V4L/DVB/IR) updates/fixes/experimental drivers # apply if non-empty +ApplyPatch add-poll-requested-events.patch ApplyOptionalPatch drivers-media-update.patch # Patches headed upstream From d34127e9d60e699a258f139840916904b1980f0a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Apr 2012 11:34:58 -0300 Subject: [PATCH 347/487] Remove a bad merge conflict Signed-off-by: Mauro Carvalho Chehab --- drivers-media-update.patch | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/drivers-media-update.patch b/drivers-media-update.patch index b2ffad5c5..d0f98a2f4 100644 --- a/drivers-media-update.patch +++ b/drivers-media-update.patch @@ -32239,26 +32239,6 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/mxl111sf.c deb_info("%s(%d)\n", __func__, onoff); -Index: linux-3.3.x86_64/drivers/media/video/pvrusb2/pvrusb2-devattr.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/pvrusb2/pvrusb2-devattr.c -+++ linux-3.3.x86_64/drivers/media/video/pvrusb2/pvrusb2-devattr.c -@@ -329,6 +329,15 @@ static struct tda18271_std_map hauppauge - .if_lvl = 1, .rfagc_top = 0x37, }, - }; - -+static struct tda18271_std_map hauppauge_tda18271_dvbt_std_map = { -+ .dvbt_6 = { .if_freq = 3300, .agc_mode = 3, .std = 4, -+ .if_lvl = 1, .rfagc_top = 0x37, }, -+ .dvbt_7 = { .if_freq = 3800, .agc_mode = 3, .std = 5, -+ .if_lvl = 1, .rfagc_top = 0x37, }, -+ .dvbt_8 = { .if_freq = 4300, .agc_mode = 3, .std = 6, -+ .if_lvl = 1, .rfagc_top = 0x37, }, -+}; -+ - static struct tda18271_config hauppauge_tda18271_dvb_config = { - .std_map = &hauppauge_tda18271_dvbt_std_map, - .gate = TDA18271_GATE_ANALOG, Index: linux-3.3.x86_64/drivers/media/video/gspca/ov534_9.c =================================================================== --- linux-3.3.x86_64.orig/drivers/media/video/gspca/ov534_9.c From 69cea03fff38b1092bc280e466c4dafaf9f1b0de Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Apr 2012 14:01:48 -0300 Subject: [PATCH 348/487] Add the Kernel patches that are ready for submission for 3.4 Those patches contain important fixes, expecially the one for BZ#808871 and BZ#807052, at the DVB core. Signed-off-by: Mauro Carvalho Chehab --- drivers-media-update.patch | 151 +++++++++++++++++++++++++++++++++---- kernel.spec | 5 +- 2 files changed, 139 insertions(+), 17 deletions(-) diff --git a/drivers-media-update.patch b/drivers-media-update.patch index d0f98a2f4..b24f2a069 100644 --- a/drivers-media-update.patch +++ b/drivers-media-update.patch @@ -2352,7 +2352,7 @@ Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-ioctl.c - itv->audio_stereo_mode = iarg; - ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); - return 0; -+ return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg); ++ return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg + 1); case AUDIO_BILINGUAL_CHANNEL_SELECT: IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); @@ -2361,7 +2361,7 @@ Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-ioctl.c - itv->audio_bilingual_mode = iarg; - ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); - return 0; -+ return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg); ++ return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg + 1); default: return -EINVAL; @@ -2516,7 +2516,39 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c }; struct ite_config it913x_config; -@@ -259,15 +260,16 @@ static u32 it913x_query(struct usb_devic +@@ -237,12 +238,27 @@ static int it913x_read_reg(struct usb_de + + static u32 it913x_query(struct usb_device *udev, u8 pro) + { +- int ret; ++ int ret, i; + u8 data[4]; +- ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ, +- 0x1222, 0, &data[0], 3); ++ u8 ver; ++ ++ for (i = 0; i < 5; i++) { ++ ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ, ++ 0x1222, 0, &data[0], 3); ++ ver = data[0]; ++ if (ver > 0 && ver < 3) ++ break; ++ msleep(100); ++ } + +- it913x_config.chip_ver = data[0]; ++ if (ver < 1 || ver > 2) { ++ info("Failed to identify chip version applying 1"); ++ it913x_config.chip_ver = 0x1; ++ it913x_config.chip_type = 0x9135; ++ return 0; ++ } ++ ++ it913x_config.chip_ver = ver; + it913x_config.chip_type = (u16)(data[2] << 8) + data[1]; + + info("Chip Version=%02x Chip Type=%04x", it913x_config.chip_ver, +@@ -259,15 +275,16 @@ static u32 it913x_query(struct usb_devic static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) { @@ -2536,7 +2568,7 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c mutex_unlock(&adap->dev->i2c_mutex); return ret; -@@ -276,12 +278,13 @@ static int it913x_pid_filter_ctrl(struct +@@ -276,12 +293,13 @@ static int it913x_pid_filter_ctrl(struct static int it913x_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) { @@ -2552,7 +2584,7 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c deb_info(1, "PID_F (%02x)", onoff); ret = it913x_wr_reg(udev, pro, PID_LSB, (u8)(pid & 0xff)); -@@ -292,6 +295,13 @@ static int it913x_pid_filter(struct dvb_ +@@ -292,6 +310,13 @@ static int it913x_pid_filter(struct dvb_ ret |= it913x_wr_reg(udev, pro, PID_INX, (u8)(index & 0x1f)); @@ -2566,7 +2598,7 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c mutex_unlock(&adap->dev->i2c_mutex); return 0; } -@@ -316,8 +326,8 @@ static int it913x_i2c_xfer(struct i2c_ad +@@ -316,8 +341,8 @@ static int it913x_i2c_xfer(struct i2c_ad int ret; u32 reg; u8 pro; @@ -2577,7 +2609,7 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c debug_data_snipet(1, "Message out", msg[0].buf); deb_info(2, "num of messages %d address %02x", num, msg[0].addr); -@@ -358,8 +368,7 @@ static int it913x_rc_query(struct dvb_us +@@ -358,8 +383,7 @@ static int it913x_rc_query(struct dvb_us int ret; u32 key; /* Avoid conflict with frontends*/ @@ -2587,7 +2619,7 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c ret = it913x_io(d->udev, READ_LONG, PRO_LINK, CMD_IR_GET, 0, 0, &ibuf[0], sizeof(ibuf)); -@@ -388,19 +397,12 @@ static int ite_firmware_select(struct us +@@ -388,19 +412,12 @@ static int ite_firmware_select(struct us { int sw; /* auto switch */ @@ -2611,7 +2643,7 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c /* force switch */ if (dvb_usb_it913x_firmware != IT9135_AUTO) -@@ -410,41 +412,103 @@ static int ite_firmware_select(struct us +@@ -410,41 +427,103 @@ static int ite_firmware_select(struct us case IT9135_V1_FW: it913x_config.firmware_ver = 1; it913x_config.adc_x2 = 1; @@ -2724,7 +2756,7 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c if (udev->speed != USB_SPEED_HIGH) { props->adapter[0].fe[0].pid_filter_count = 5; -@@ -459,17 +523,6 @@ static int it913x_identify_state(struct +@@ -459,17 +538,6 @@ static int it913x_identify_state(struct if(props->adapter[0].fe[0].pid_filter_count == 5) props->adapter[0].fe[0].pid_filter_count = 31; @@ -2742,7 +2774,7 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c /* Select Stream Buffer Size and pid filter option*/ if (pid_filter) { props->adapter[0].fe[0].stream.u.bulk.buffersize = -@@ -490,8 +543,29 @@ static int it913x_identify_state(struct +@@ -490,8 +558,29 @@ static int it913x_identify_state(struct } else props->num_adapters = 1; @@ -2772,7 +2804,7 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c if (firm_no > 0) { *cold = 0; return 0; -@@ -538,18 +612,22 @@ static int it913x_identify_state(struct +@@ -538,18 +627,22 @@ static int it913x_identify_state(struct static int it913x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) { @@ -2799,7 +2831,58 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c return ret; } -@@ -789,7 +867,7 @@ static struct dvb_usb_device_properties +@@ -582,30 +675,41 @@ static int it913x_download_firmware(stru + if ((packet_size > min_pkt) || (i == fw->size)) { + fw_data = (u8 *)(fw->data + pos); + pos += packet_size; +- if (packet_size > 0) +- ret |= it913x_io(udev, WRITE_DATA, ++ if (packet_size > 0) { ++ ret = it913x_io(udev, WRITE_DATA, + DEV_0, CMD_SCATTER_WRITE, 0, + 0, fw_data, packet_size); ++ if (ret < 0) ++ break; ++ } + udelay(1000); + } + } + i++; + } + +- ret |= it913x_io(udev, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0); +- +- msleep(100); +- + if (ret < 0) +- info("FRM Firmware Download Failed (%04x)" , ret); ++ info("FRM Firmware Download Failed (%d)" , ret); + else + info("FRM Firmware Download Completed - Resetting Device"); + +- ret |= it913x_return_status(udev); ++ msleep(30); ++ ++ ret = it913x_io(udev, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0); ++ if (ret < 0) ++ info("FRM Device not responding to reboot"); ++ ++ ret = it913x_return_status(udev); ++ if (ret == 0) { ++ info("FRM Failed to reboot device"); ++ return -ENODEV; ++ } + + msleep(30); + +- ret |= it913x_wr_reg(udev, DEV_0, I2C_CLK, I2C_CLK_400); ++ ret = it913x_wr_reg(udev, DEV_0, I2C_CLK, I2C_CLK_400); ++ ++ msleep(30); + + /* Tuner function */ + if (it913x_config.dual_mode) +@@ -789,7 +893,7 @@ static struct dvb_usb_device_properties .rc_query = it913x_rc_query, .rc_interval = IT913X_POLL, .allowed_protos = RC_TYPE_NEC, @@ -2808,12 +2891,12 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c }, .i2c_algo = &it913x_i2c_algo, .num_device_descs = 5, -@@ -823,5 +901,5 @@ module_usb_driver(it913x_driver); +@@ -823,5 +927,5 @@ module_usb_driver(it913x_driver); MODULE_AUTHOR("Malcolm Priestley "); MODULE_DESCRIPTION("it913x USB 2 Driver"); -MODULE_VERSION("1.22"); -+MODULE_VERSION("1.27"); ++MODULE_VERSION("1.28"); MODULE_LICENSE("GPL"); Index: linux-3.3.x86_64/drivers/base/driver.c =================================================================== @@ -10356,7 +10439,21 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-core/dvb_frontend.c =================================================================== --- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-core/dvb_frontend.c +++ linux-3.3.x86_64/drivers/media/dvb/dvb-core/dvb_frontend.c -@@ -655,6 +655,8 @@ restart: +@@ -143,10 +143,12 @@ struct dvb_frontend_private { + static void dvb_frontend_wakeup(struct dvb_frontend *fe); + static int dtv_get_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p_out); ++static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, ++ struct dvb_frontend_parameters *p); + + static bool has_get_frontend(struct dvb_frontend *fe) + { +- return fe->ops.get_frontend; ++ return fe->ops.get_frontend != NULL; + } + + /* +@@ -655,6 +657,8 @@ restart: dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__); re_tune = true; fepriv->state = FESTATE_TUNED; @@ -10365,6 +10462,28 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-core/dvb_frontend.c } if (fe->ops.tune) +@@ -695,6 +699,7 @@ restart: + fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; + fepriv->delay = HZ / 2; + } ++ dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); + fe->ops.read_status(fe, &s); + if (s != fepriv->status) { + dvb_frontend_add_event(fe, s); /* update event list */ +@@ -1831,6 +1836,13 @@ static int dtv_set_frontend(struct dvb_f + return -EINVAL; + + /* ++ * Initialize output parameters to match the values given by ++ * the user. FE_SET_FRONTEND triggers an initial frontend event ++ * with status = 0, which copies output parameters to userspace. ++ */ ++ dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); ++ ++ /* + * Be sure that the bandwidth will be filled for all + * non-satellite systems, as tuners need to know what + * low pass/Nyquist half filter should be applied, in Index: linux-3.3.x86_64/drivers/media/common/tuners/xc5000.c =================================================================== --- linux-3.3.x86_64.orig/drivers/media/common/tuners/xc5000.c diff --git a/kernel.spec b/kernel.spec index c21dc3e2b..8319ecdb8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2236,6 +2236,9 @@ fi # and build. %changelog +* Tue Apr 10 2012 Mauro Carvalho Chehab +- Backport dvb-core and a few driver fixes from media tree (rhbz808871) + * Tue Apr 10 2012 Josh Boyer - Backport fixes for correct register constraints in cmpxchg.h (rhbz 809014) From 7dbe0a1257ba85cc5f3763b56a37fa5a76802c48 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 10 Apr 2012 15:11:33 -0400 Subject: [PATCH 349/487] Apply upstream patch to add USB device 13d3:3375 (rhbz 811087) --- ...-USB-device-13d3-3375-as-an-Atheros-.patch | 58 +++++++++++++++++++ kernel.spec | 5 ++ 2 files changed, 63 insertions(+) create mode 100644 Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch diff --git a/Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch b/Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch new file mode 100644 index 000000000..f238d50da --- /dev/null +++ b/Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch @@ -0,0 +1,58 @@ +From 9498ba7a1d38d42eef4ef6d906ab1743c9f0fd6f Mon Sep 17 00:00:00 2001 +From: Eran +Date: Mon, 5 Dec 2011 22:15:29 +0000 +Subject: [PATCH] Bluetooth: Adding USB device 13d3:3375 as an Atheros AR3012. + +The bluetooth module in the Asus UX31/UX21 is based on Atheros AR3012 +and requires a firmware to be uploaded before it's usable. + +output of usb-devices for this module: +T: Bus=01 Lev=02 Prnt=02 Port=07 Cnt=03 Dev#= 6 Spd=12 MxCh= 0 +D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 +P: Vendor=13d3 ProdID=3375 Rev=00.02 +S: Manufacturer=Atheros Communications +S: Product=Bluetooth USB Host Controller +S: SerialNumber=Alaska Day 2006 +C: #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA +I: If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +I: If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb + +Signed-off-by: Eran +Tested-by: Michal Labedzki +Signed-off-by: Gustavo F. Padovan + +diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c +index 4eca6e5..4844247 100644 +--- a/drivers/bluetooth/ath3k.c ++++ b/drivers/bluetooth/ath3k.c +@@ -72,6 +72,7 @@ static struct usb_device_id ath3k_table[] = { + + /* Atheros AR3012 with sflash firmware*/ + { USB_DEVICE(0x0CF3, 0x3004) }, ++ { USB_DEVICE(0x13d3, 0x3375) }, + + /* Atheros AR5BBU12 with sflash firmware */ + { USB_DEVICE(0x0489, 0xE02C) }, +@@ -88,6 +89,7 @@ static struct usb_device_id ath3k_blist_tbl[] = { + + /* Atheros AR3012 with sflash firmware*/ + { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, + + { } /* Terminating entry */ + }; +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 22f695e..480cad9 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -129,6 +129,7 @@ static struct usb_device_id blacklist_table[] = { + + /* Atheros 3012 with sflash firmware */ + { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, + + /* Atheros AR5BBU12 with sflash firmware */ + { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index 8319ecdb8..c227df0e2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -735,6 +735,7 @@ Patch14001: hibernate-watermark.patch Patch14010: lis3-improve-handling-of-null-rate.patch Patch15000: bluetooth-use-after-free.patch +Patch15001: Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch Patch19000: ips-noirq.patch @@ -1434,6 +1435,7 @@ ApplyPatch hibernate-watermark.patch ApplyPatch lis3-improve-handling-of-null-rate.patch ApplyPatch bluetooth-use-after-free.patch +ApplyPatch Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch ApplyPatch ips-noirq.patch @@ -2236,6 +2238,9 @@ fi # and build. %changelog +* Tue Apr 10 2012 Josh Boyer +- Apply upstream patch to add USB device 13d3:3375 (rhbz 811087) + * Tue Apr 10 2012 Mauro Carvalho Chehab - Backport dvb-core and a few driver fixes from media tree (rhbz808871) From a253de9cd3e0d70d2ccd0fd892d168a0556b2594 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 10 Apr 2012 20:10:54 -0400 Subject: [PATCH 350/487] Update hibernate watermark patch to latest tested version --- hibernate-watermark.patch | 147 +++++++++++++++++++++++++++++++------- 1 file changed, 123 insertions(+), 24 deletions(-) diff --git a/hibernate-watermark.patch b/hibernate-watermark.patch index 2cb75e6ef..7031e167f 100644 --- a/hibernate-watermark.patch +++ b/hibernate-watermark.patch @@ -1,7 +1,40 @@ +Hi Rafael, ---- a/kernel/power/swap.c -+++ a/kernel/power/swap.c -@@ -6,7 +6,7 @@ +One more version. Heeding Per's suggestion to optimise when +CONFIG_HIGHMEM is not configured. + +--------------------------------------- +Hibernation/thaw fixes/improvements: + +1. Calculate the number of required free pages based on non-high memory +pages only, because that is where the buffers will come from. + +2. Do not allocate memory for buffers from emergency pools, unless +absolutely required. Do not warn about and do not retry non-essential +failed allocations. + +3. Do not check the amount of free pages left on every single page +write, but wait until one map is completely populated and then check. + +4. Set maximum number of pages for read buffering consistently, instead +of inadvertently depending on the size of the sector type. + +5. Fix copyright line, which I missed when I submitted the hibernation +threading patch. + +6. Dispense with bit shifting arithmetic to improve readability. + +Signed-off-by: Bojan Smojver +Signed-off-by: Per Olofsson +--- + kernel/power/swap.c | 76 +++++++++++++++++++++++++++++++++++++++------------ + 1 files changed, 58 insertions(+), 18 deletions(-) + +diff --git a/kernel/power/swap.c b/kernel/power/swap.c +index 8742fd0..8a1c293 100644 +--- a/kernel/power/swap.c ++++ b/kernel/power/swap.c +@@ -6,7 +6,7 @@ * * Copyright (C) 1998,2001-2005 Pavel Machek * Copyright (C) 2006 Rafael J. Wysocki @@ -10,23 +43,44 @@ * * This file is released under the GPLv2. * -@@ -51,6 +51,15 @@ +@@ -51,6 +51,36 @@ #define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(sector_t) - 1) ++/* ++ * Number of free pages that are not high. ++ */ ++#ifdef CONFIG_HIGHMEM ++static unsigned long low_free_pages(void) ++{ ++ struct zone *zone; ++ unsigned long free = 0; ++ ++ for_each_populated_zone(zone) ++ if (!is_highmem(zone)) ++ free += zone_page_state(zone, NR_FREE_PAGES); ++ return free; ++} ++#else ++static inline unsigned long low_free_pages(void) ++{ ++ return nr_free_pages(); ++} ++#endif ++ +/* + * Number of pages required to be kept free while writing the image. Always -+ * three quarters of all available pages before the writing starts. ++ * half of all available low pages before the writing starts. + */ +static inline unsigned long reqd_free_pages(void) +{ -+ return (nr_free_pages() / 4) * 3; ++ return low_free_pages() / 2; +} + struct swap_map_page { sector_t entries[MAP_PAGE_ENTRIES]; sector_t next_swap; -@@ -72,7 +81,7 @@ struct swap_map_handle { +@@ -72,7 +102,7 @@ struct swap_map_handle { sector_t cur_swap; sector_t first_sector; unsigned int k; @@ -35,7 +89,27 @@ u32 crc32; }; -@@ -316,8 +325,7 @@ static int get_swap_writer(struct swap_map_handle *handle) +@@ -265,14 +295,17 @@ static int write_page(void *buf, sector_t offset, struct bio **bio_chain) + return -ENOSPC; + + if (bio_chain) { +- src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); ++ src = (void *)__get_free_page(__GFP_WAIT | __GFP_NOWARN | ++ __GFP_NORETRY); + if (src) { + copy_page(src, buf); + } else { + ret = hib_wait_on_bio_chain(bio_chain); /* Free pages */ + if (ret) + return ret; +- src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); ++ src = (void *)__get_free_page(__GFP_WAIT | ++ __GFP_NOWARN | ++ __GFP_NORETRY); + if (src) { + copy_page(src, buf); + } else { +@@ -316,8 +349,7 @@ static int get_swap_writer(struct swap_map_handle *handle) goto err_rel; } handle->k = 0; @@ -45,25 +119,31 @@ handle->first_sector = handle->cur_swap; return 0; err_rel: -@@ -352,11 +360,15 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, +@@ -351,12 +383,17 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, + clear_page(handle->cur); handle->cur_swap = offset; handle->k = 0; - } +- } - if (bio_chain && ++handle->written > handle->nr_free_pages) { -+ if (bio_chain && nr_free_pages() <= handle->reqd_free_pages) { - error = hib_wait_on_bio_chain(bio_chain); - if (error) - goto out; +- error = hib_wait_on_bio_chain(bio_chain); +- if (error) +- goto out; - handle->written = 0; -+ /* -+ * Recalculate the number of required free pages, to make sure -+ * we never take more than a quarter. -+ */ -+ handle->reqd_free_pages = reqd_free_pages(); ++ ++ if (bio_chain && low_free_pages() <= handle->reqd_free_pages) { ++ error = hib_wait_on_bio_chain(bio_chain); ++ if (error) ++ goto out; ++ /* ++ * Recalculate the number of required free pages, to ++ * make sure we never take more than half. ++ */ ++ handle->reqd_free_pages = reqd_free_pages(); ++ } } out: return error; -@@ -404,7 +416,7 @@ static int swap_writer_finish(struct swap_map_handle *handle, +@@ -404,7 +441,7 @@ static int swap_writer_finish(struct swap_map_handle *handle, #define LZO_THREADS 3 /* Maximum number of pages for read buffering. */ @@ -72,7 +152,7 @@ /** -@@ -615,10 +627,10 @@ static int save_image_lzo(struct swap_map_handle *handle, +@@ -615,10 +652,10 @@ static int save_image_lzo(struct swap_map_handle *handle, } /* @@ -86,14 +166,33 @@ /* * Start the CRC32 thread. -@@ -1129,8 +1141,9 @@ static int load_image_lzo(struct swap_map_handle *handle, +@@ -1129,14 +1166,17 @@ static int load_image_lzo(struct swap_map_handle *handle, /* * Adjust number of pages for read buffering, in case we are short. -+ * Never take more than a quarter of all available pages. ++ * Never take more than half of all available low pages. */ - read_pages = (nr_free_pages() - snapshot_get_image_size()) >> 1; -+ read_pages = (nr_free_pages() - snapshot_get_image_size()) / 4; ++ read_pages = (low_free_pages() - snapshot_get_image_size()) / 2; read_pages = clamp_val(read_pages, LZO_CMP_PAGES, LZO_READ_PAGES); for (i = 0; i < read_pages; i++) { + page[i] = (void *)__get_free_page(i < LZO_CMP_PAGES ? + __GFP_WAIT | __GFP_HIGH : +- __GFP_WAIT); ++ __GFP_WAIT | __GFP_NOWARN | ++ __GFP_NORETRY); ++ + if (!page[i]) { + if (i < LZO_CMP_PAGES) { + ring_size = i; +--------------------------------------- + +-- +Bojan + +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ \ No newline at end of file From 28b13140ec3375d59bac4f2d6bc336f7b8ed6fc7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 13 Apr 2012 13:49:22 -0400 Subject: [PATCH 351/487] Linux 3.3.2 --- ...x-regression-in-FADT-revision-checks.patch | 58 ------- ...ensure-thermal-limits-match-cpu-freq.patch | 146 ------------------ drivers-media-update.patch | 38 +---- iwlegacy-do-not-nulify-il-vif-on-reset.patch | 77 --------- kernel.spec | 33 +--- ...-tid_rx-reorder_timer-use-after-free.patch | 42 ----- ...er-copied-in-__nfs4_get_acl_uncached.patch | 32 ---- sources | 2 +- ...uced-crash-in-uvc_video_clock_update.patch | 113 -------------- 9 files changed, 7 insertions(+), 534 deletions(-) delete mode 100644 ACPICA-Fix-regression-in-FADT-revision-checks.patch delete mode 100644 acpi-ensure-thermal-limits-match-cpu-freq.patch delete mode 100644 iwlegacy-do-not-nulify-il-vif-on-reset.patch delete mode 100644 mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch delete mode 100644 nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch delete mode 100644 uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch diff --git a/ACPICA-Fix-regression-in-FADT-revision-checks.patch b/ACPICA-Fix-regression-in-FADT-revision-checks.patch deleted file mode 100644 index d6b590389..000000000 --- a/ACPICA-Fix-regression-in-FADT-revision-checks.patch +++ /dev/null @@ -1,58 +0,0 @@ - commit 64b3db22c04586997ab4be46dd5a5b99f8a2d390 (2.6.39), -"Remove use of unreliable FADT revision field" causes regression -for old P4 systems because now cst_control and other fields are -not reset to 0. - - The effect is that acpi_processor_power_init will notice -cst_control != 0 and a write to CST_CNT register is performed -that should not happen. As result, the system oopses after the -"No _CST, giving up" message, sometimes in acpi_ns_internalize_name, -sometimes in acpi_ns_get_type, usually at random places. May be -during migration to CPU 1 in acpi_processor_get_throttling. - - Every one of these settings help to avoid this problem: - - acpi=off - - processor.nocst=1 - - maxcpus=1 - - The fix is to update acpi_gbl_FADT.header.length after -the original value is used to check for old revisions. - -Signed-off-by: Julian Anastasov ---- - drivers/acpi/acpica/tbfadt.c | 8 ++++---- - 1 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c -index c5d8704..4c9c760 100644 ---- a/drivers/acpi/acpica/tbfadt.c -+++ b/drivers/acpi/acpica/tbfadt.c -@@ -363,10 +363,6 @@ static void acpi_tb_convert_fadt(void) - u32 address32; - u32 i; - -- /* Update the local FADT table header length */ -- -- acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); -- - /* - * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary. - * Later code will always use the X 64-bit field. Also, check for an -@@ -408,6 +404,10 @@ static void acpi_tb_convert_fadt(void) - acpi_gbl_FADT.boot_flags = 0; - } - -+ /* Update the local FADT table header length */ -+ -+ acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); -+ - /* - * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" - * generic address structures as necessary. Later code will always use --- -1.7.3.4 - --- -To unsubscribe from this list: send the line "unsubscribe linux-acpi" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/acpi-ensure-thermal-limits-match-cpu-freq.patch b/acpi-ensure-thermal-limits-match-cpu-freq.patch deleted file mode 100644 index 9d97b6024..000000000 --- a/acpi-ensure-thermal-limits-match-cpu-freq.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 9a056a5843ff83db987d6e18625f4a2ee64b5450 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Tue, 30 Aug 2011 10:07:24 -0400 -Subject: [PATCH] ACPI: Ensure thermal limits match CPU frequencies - -The ACPI thermal management code supports slowing down a CPU when it's -overheating. Right now that's done by choosing to run it at 100%, 75%, 50% -or 25% of full speed. However, most CPUs do not allow an arbitrary -frequency to be set and so will run at the first frequency below that value. -This doesn't match the intent of the specification, which is to drop the -frequency state by state until the temperature stabalises. Fix this up -so it uses actual frequencies rather than percentages. - -Reported by: Gene Snider -Signed-off-by: Matthew Garrett ---- - drivers/acpi/Kconfig | 1 + - drivers/acpi/processor_thermal.c | 45 +++++++++++++++++++++---------------- - 2 files changed, 26 insertions(+), 20 deletions(-) - -diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig -index de0e3df..7d1bdb5 100644 ---- a/drivers/acpi/Kconfig -+++ b/drivers/acpi/Kconfig -@@ -185,6 +185,7 @@ config ACPI_PROCESSOR - tristate "Processor" - select THERMAL - select CPU_IDLE -+ select CPU_FREQ_TABLE - default y - help - This driver installs ACPI as the idle handler for Linux and uses -diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c -index 870550d..1c4eb60 100644 ---- a/drivers/acpi/processor_thermal.c -+++ b/drivers/acpi/processor_thermal.c -@@ -52,10 +52,8 @@ ACPI_MODULE_NAME("processor_thermal"); - * _any_ cpufreq driver and not only the acpi-cpufreq driver. - */ - --#define CPUFREQ_THERMAL_MIN_STEP 0 --#define CPUFREQ_THERMAL_MAX_STEP 3 - --static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg); -+static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_limit_state); - static unsigned int acpi_thermal_cpufreq_is_init = 0; - - static int cpu_has_cpufreq(unsigned int cpu) -@@ -70,19 +68,19 @@ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, - unsigned long event, void *data) - { - struct cpufreq_policy *policy = data; -- unsigned long max_freq = 0; -+ int state = per_cpu(cpufreq_thermal_limit_state, policy->cpu); -+ struct cpufreq_frequency_table *table; - - if (event != CPUFREQ_ADJUST) -- goto out; -+ return 0; -+ -+ table = cpufreq_frequency_get_table(policy->cpu); - -- max_freq = ( -- policy->cpuinfo.max_freq * -- (100 - per_cpu(cpufreq_thermal_reduction_pctg, policy->cpu) * 20) -- ) / 100; -+ if (!table) -+ return 0; - -- cpufreq_verify_within_limits(policy, 0, max_freq); -+ cpufreq_verify_within_limits(policy, 0, table[state].frequency); - -- out: - return 0; - } - -@@ -92,10 +90,21 @@ static struct notifier_block acpi_thermal_cpufreq_notifier_block = { - - static int cpufreq_get_max_state(unsigned int cpu) - { -+ int count = 0; -+ struct cpufreq_frequency_table *table; -+ - if (!cpu_has_cpufreq(cpu)) - return 0; - -- return CPUFREQ_THERMAL_MAX_STEP; -+ table = cpufreq_frequency_get_table(cpu); -+ -+ if (!table) -+ return 0; -+ -+ while (table[count].frequency != CPUFREQ_TABLE_END) -+ count++; -+ -+ return count; - } - - static int cpufreq_get_cur_state(unsigned int cpu) -@@ -103,7 +112,7 @@ static int cpufreq_get_cur_state(unsigned int cpu) - if (!cpu_has_cpufreq(cpu)) - return 0; - -- return per_cpu(cpufreq_thermal_reduction_pctg, cpu); -+ return per_cpu(cpufreq_thermal_limit_state, cpu); - } - - static int cpufreq_set_cur_state(unsigned int cpu, int state) -@@ -111,7 +120,7 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state) - if (!cpu_has_cpufreq(cpu)) - return 0; - -- per_cpu(cpufreq_thermal_reduction_pctg, cpu) = state; -+ per_cpu(cpufreq_thermal_limit_state, cpu) = state; - cpufreq_update_policy(cpu); - return 0; - } -@@ -122,7 +131,7 @@ void acpi_thermal_cpufreq_init(void) - - for (i = 0; i < nr_cpu_ids; i++) - if (cpu_present(i)) -- per_cpu(cpufreq_thermal_reduction_pctg, i) = 0; -+ per_cpu(cpufreq_thermal_limit_state, i) = 0; - - i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block, - CPUFREQ_POLICY_NOTIFIER); -@@ -170,15 +179,11 @@ int acpi_processor_get_limit_info(struct acpi_processor *pr) - return 0; - } - --/* thermal coolign device callbacks */ -+/* thermal cooling device callbacks */ - static int acpi_processor_max_state(struct acpi_processor *pr) - { - int max_state = 0; - -- /* -- * There exists four states according to -- * cpufreq_thermal_reduction_ptg. 0, 1, 2, 3 -- */ - max_state += cpufreq_get_max_state(pr->id); - if (pr->flags.throttling) - max_state += (pr->throttling.state_count -1); --- -1.7.6 - diff --git a/drivers-media-update.patch b/drivers-media-update.patch index b24f2a069..15eba7350 100644 --- a/drivers-media-update.patch +++ b/drivers-media-update.patch @@ -10439,12 +10439,7 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-core/dvb_frontend.c =================================================================== --- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-core/dvb_frontend.c +++ linux-3.3.x86_64/drivers/media/dvb/dvb-core/dvb_frontend.c -@@ -143,10 +143,12 @@ struct dvb_frontend_private { - static void dvb_frontend_wakeup(struct dvb_frontend *fe); - static int dtv_get_frontend(struct dvb_frontend *fe, - struct dvb_frontend_parameters *p_out); -+static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, -+ struct dvb_frontend_parameters *p); +@@ -148,7 +148,7 @@ static int dtv_property_legacy_params_sy static bool has_get_frontend(struct dvb_frontend *fe) { @@ -10453,37 +10448,6 @@ Index: linux-3.3.x86_64/drivers/media/dvb/dvb-core/dvb_frontend.c } /* -@@ -655,6 +657,8 @@ restart: - dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__); - re_tune = true; - fepriv->state = FESTATE_TUNED; -+ } else { -+ re_tune = false; - } - - if (fe->ops.tune) -@@ -695,6 +699,7 @@ restart: - fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; - fepriv->delay = HZ / 2; - } -+ dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); - fe->ops.read_status(fe, &s); - if (s != fepriv->status) { - dvb_frontend_add_event(fe, s); /* update event list */ -@@ -1831,6 +1836,13 @@ static int dtv_set_frontend(struct dvb_f - return -EINVAL; - - /* -+ * Initialize output parameters to match the values given by -+ * the user. FE_SET_FRONTEND triggers an initial frontend event -+ * with status = 0, which copies output parameters to userspace. -+ */ -+ dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); -+ -+ /* - * Be sure that the bandwidth will be filled for all - * non-satellite systems, as tuners need to know what - * low pass/Nyquist half filter should be applied, in Index: linux-3.3.x86_64/drivers/media/common/tuners/xc5000.c =================================================================== --- linux-3.3.x86_64.orig/drivers/media/common/tuners/xc5000.c diff --git a/iwlegacy-do-not-nulify-il-vif-on-reset.patch b/iwlegacy-do-not-nulify-il-vif-on-reset.patch deleted file mode 100644 index d1913d708..000000000 --- a/iwlegacy-do-not-nulify-il-vif-on-reset.patch +++ /dev/null @@ -1,77 +0,0 @@ -This il->vif is dereferenced in different part of iwlegacy code, so do -not nullify it. This should fix random crashes observed in companion -with microcode errors i.e. crash in il3945_config_ap(). - -Additionally this should address also -WARNING: at drivers/net/wireless/iwlegacy/common.c:4656 il_mac_remove_interface -at least one of the possible reasons of that warning. - -Cc: stable@vger.kernel.org -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/iwlegacy/3945-mac.c | 2 -- - drivers/net/wireless/iwlegacy/4965-mac.c | 2 -- - drivers/net/wireless/iwlegacy/common.c | 15 ++++++++++++--- - 3 files changed, 12 insertions(+), 7 deletions(-) - ---- linux-3.3.noarch.orig/drivers/net/wireless/iwlegacy/3945-mac.c -+++ linux-3.3.noarch/drivers/net/wireless/iwlegacy/3945-mac.c -@@ -2684,7 +2684,6 @@ il3945_bg_restart(struct work_struct *da - - if (test_and_clear_bit(S_FW_ERROR, &il->status)) { - mutex_lock(&il->mutex); -- il->ctx.vif = NULL; - il->is_open = 0; - mutex_unlock(&il->mutex); - il3945_down(il); ---- linux-3.3.noarch.orig/drivers/net/wireless/iwlegacy/4965-mac.c -+++ linux-3.3.noarch/drivers/net/wireless/iwlegacy/4965-mac.c -@@ -5381,7 +5381,6 @@ il4965_bg_restart(struct work_struct *da - - if (test_and_clear_bit(S_FW_ERROR, &il->status)) { - mutex_lock(&il->mutex); -- il->ctx.vif = NULL; - il->is_open = 0; - - __il4965_down(il); ---- linux-3.3.noarch.orig/drivers/net/wireless/iwlegacy/common.c -+++ linux-3.3.noarch/drivers/net/wireless/iwlegacy/common.c -@@ -4575,6 +4575,7 @@ il_mac_add_interface(struct ieee80211_hw - struct il_priv *il = hw->priv; - struct il_vif_priv *vif_priv = (void *)vif->drv_priv; - int err; -+ bool reset; - u32 modes; - - D_MAC80211("enter: type %d, addr %pM\n", vif->type, vif->addr); -@@ -4594,6 +4595,16 @@ il_mac_add_interface(struct ieee80211_hw - goto out; - } - -+ /* -+ * We do not support multiple virtual interfaces, but on hardware reset -+ * we have to add the same interface again. -+ */ -+ reset = (il->ctx.vif == vif); -+ if (il->ctx.vif && !reset) { -+ err = -EOPNOTSUPP; -+ goto out; -+ } -+ - modes = il->ctx.interface_modes | il->ctx.exclusive_interface_modes; - if (!(modes & BIT(vif->type))) { - err = -EOPNOTSUPP; -@@ -4605,8 +4616,11 @@ il_mac_add_interface(struct ieee80211_hw - - err = il_setup_interface(il, &il->ctx); - if (err) { -- il->ctx.vif = NULL; -- il->iw_mode = NL80211_IFTYPE_STATION; -+ IL_WARN("Fail to set mode %d\n", vif->type); -+ if (!reset) { -+ il->ctx.vif = NULL; -+ il->iw_mode = NL80211_IFTYPE_STATION; -+ } - } - - out: diff --git a/kernel.spec b/kernel.spec index c227df0e2..e860a5811 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 5 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 1 +%define stable_update 2 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -666,7 +666,6 @@ Patch383: linux-2.6-defaults-aspm.patch Patch390: linux-2.6-defaults-acpi-video.patch Patch391: linux-2.6-acpi-video-dos.patch Patch394: linux-2.6-acpi-debug-infinite-loop.patch -Patch395: acpi-ensure-thermal-limits-match-cpu-freq.patch Patch396: acpi-sony-nonvs-blacklist.patch Patch450: linux-2.6-input-kill-stupid-messages.patch @@ -761,17 +760,11 @@ Patch21232: rt2x00_fix_MCU_request_failures.patch #rhbz 789644 Patch21237: mcelog-rcu-splat.patch -#rhbz 727865 730007 -Patch21240: ACPICA-Fix-regression-in-FADT-revision-checks.patch - #rhbz 728478 Patch21242: sony-laptop-Enable-keyboard-backlight-by-default.patch Patch21300: unhandled-irqs-switch-to-polling.patch -#rhbz 804007 -Patch21305: mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch - #rhbz 804957 CVE-2012-1568 Patch21306: shlib_base_randomize.patch @@ -780,11 +773,7 @@ Patch21351: x86-add-io_apic_ops-to-allow-interception.patch Patch21352: x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch Patch21353: xen-x86-Implement-x86_apic_ops.patch -#rhbz 806433 -Patch21360: uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch - #rhbz 770476 -Patch21370: iwlegacy-do-not-nulify-il-vif-on-reset.patch Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch #rhbz 808603 @@ -797,8 +786,6 @@ Patch21385: libata-disable-runtime-pm-for-hotpluggable-port.patch Patch21390: x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch Patch21391: x86-Use-correct-byte-sized-register-constraint-in-__add.patch -Patch21501: nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch - #rhbz 808207 CVE-2012-1601 Patch21520: KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch @@ -1345,7 +1332,6 @@ ApplyPatch NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch ApplyPatch linux-2.6-defaults-acpi-video.patch ApplyPatch linux-2.6-acpi-video-dos.patch ApplyPatch linux-2.6-acpi-debug-infinite-loop.patch -ApplyPatch acpi-ensure-thermal-limits-match-cpu-freq.patch ApplyPatch acpi-sony-nonvs-blacklist.patch # @@ -1455,15 +1441,9 @@ ApplyPatch rt2x00_fix_MCU_request_failures.patch #rhbz 789644 ApplyPatch mcelog-rcu-splat.patch -#rhbz 727865 730007 -ApplyPatch ACPICA-Fix-regression-in-FADT-revision-checks.patch - #rhbz 728478 ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch -#rhbz 804007 -ApplyPatch mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch - #rhbz 804957 CVE-2012-1568 ApplyPatch shlib_base_randomize.patch @@ -1479,17 +1459,11 @@ ApplyPatch x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch ApplyPatch xen-x86-Implement-x86_apic_ops.patch #rhbz 770476 -ApplyPatch iwlegacy-do-not-nulify-il-vif-on-reset.patch ApplyPatch iwlwifi-do-not-nulify-ctx-vif-on-reset.patch -ApplyPatch nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch - #rhbz 808207 CVE-2012-1601 ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch -#rhbz 806433 -ApplyPatch uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch - #rhbz 808603 ApplyPatch wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch @@ -2238,6 +2212,9 @@ fi # and build. %changelog +* Fri Apr 13 2012 Josh Boyer - 3.3.2-1 +- Linux 3.3.2 + * Tue Apr 10 2012 Josh Boyer - Apply upstream patch to add USB device 13d3:3375 (rhbz 811087) diff --git a/mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch b/mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch deleted file mode 100644 index accda8afc..000000000 --- a/mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch +++ /dev/null @@ -1,42 +0,0 @@ -Is possible that we will arm the tid_rx->reorder_timer after -del_timer_sync() in ___ieee80211_stop_rx_ba_session(). We need to stop -timer after RCU grace period finish, so move it to -ieee80211_free_tid_rx(). Timer will not be armed again, as -rcu_dereference(sta->ampdu_mlme.tid_rx[tid]) will return NULL. - -Debug object detected problem with the following warning: -ODEBUG: free active (active state 0) object type: timer_list hint: sta_rx_agg_reorder_timer_expired+0x0/0xf0 [mac80211] - -Bug report (with all warning messages): -https://bugzilla.redhat.com/show_bug.cgi?id=804007 - -Reported-by: "jan p. springer" -Cc: stable@vger.kernel.org -Signed-off-by: Stanislaw Gruszka ---- - net/mac80211/agg-rx.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c -index 1068f66..64d3ce5 100644 ---- a/net/mac80211/agg-rx.c -+++ b/net/mac80211/agg-rx.c -@@ -49,6 +49,8 @@ static void ieee80211_free_tid_rx(struct rcu_head *h) - container_of(h, struct tid_ampdu_rx, rcu_head); - int i; - -+ del_timer_sync(&tid_rx->reorder_timer); -+ - for (i = 0; i < tid_rx->buf_size; i++) - dev_kfree_skb(tid_rx->reorder_buf[i]); - kfree(tid_rx->reorder_buf); -@@ -91,7 +93,6 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, - tid, WLAN_BACK_RECIPIENT, reason); - - del_timer_sync(&tid_rx->session_timer); -- del_timer_sync(&tid_rx->reorder_timer); - - call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); - } --- -1.7.1 diff --git a/nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch b/nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch deleted file mode 100644 index 981f1f467..000000000 --- a/nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 20e0fa98b751facf9a1101edaefbc19c82616a68 Mon Sep 17 00:00:00 2001 -From: Sachin Prabhu -Date: Thu, 22 Mar 2012 16:46:28 +0000 -Subject: [PATCH] Fix length of buffer copied in __nfs4_get_acl_uncached - -_copy_from_pages() used to copy data from the temporary buffer to the -user passed buffer is passed the wrong size parameter when copying -data. res.acl_len contains both the bitmap and acl lenghts while -acl_len contains the acl length after adjusting for the bitmap size. - -Signed-off-by: Sachin Prabhu -Signed-off-by: Trond Myklebust ---- - fs/nfs/nfs4proc.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c -index e809d23..45df7d4 100644 ---- a/fs/nfs/nfs4proc.c -+++ b/fs/nfs/nfs4proc.c -@@ -3712,7 +3712,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu - if (acl_len > buflen) - goto out_free; - _copy_from_pages(buf, pages, res.acl_data_offset, -- res.acl_len); -+ acl_len); - } - ret = acl_len; - out_free: --- -1.7.7.6 - diff --git a/sources b/sources index e8c9e05f6..413d6dc42 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz -10771d657c5bf342bcfe66ed06653ecb patch-3.3.1.xz +68907107b0f62a19608588bdb6b29e20 patch-3.3.2.xz diff --git a/uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch b/uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch deleted file mode 100644 index 5f2a1c006..000000000 --- a/uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch +++ /dev/null @@ -1,113 +0,0 @@ -@@ -, +, @@ - drivers/media/video/uvc/uvc_video.c | 50 ++++++++++++++++++++++------------ - 1 files changed, 32 insertions(+), 18 deletions(-) ---- a/drivers/media/video/uvc/uvc_video.c -+++ a/drivers/media/video/uvc/uvc_video.c -@@ -468,22 +468,30 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf, - spin_unlock_irqrestore(&stream->clock.lock, flags); - } - --static int uvc_video_clock_init(struct uvc_streaming *stream) -+static void uvc_video_clock_reset(struct uvc_streaming *stream) - { - struct uvc_clock *clock = &stream->clock; - -- spin_lock_init(&clock->lock); - clock->head = 0; - clock->count = 0; -- clock->size = 32; - clock->last_sof = -1; - clock->sof_offset = -1; -+} -+ -+static int uvc_video_clock_init(struct uvc_streaming *stream) -+{ -+ struct uvc_clock *clock = &stream->clock; -+ -+ spin_lock_init(&clock->lock); -+ clock->size = 32; - - clock->samples = kmalloc(clock->size * sizeof(*clock->samples), - GFP_KERNEL); - if (clock->samples == NULL) - return -ENOMEM; - -+ uvc_video_clock_reset(stream); -+ - return 0; - } - -@@ -1424,8 +1432,6 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) - - if (free_buffers) - uvc_free_urb_buffers(stream); -- -- uvc_video_clock_cleanup(stream); - } - - /* -@@ -1555,10 +1561,6 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) - - uvc_video_stats_start(stream); - -- ret = uvc_video_clock_init(stream); -- if (ret < 0) -- return ret; -- - if (intf->num_altsetting > 1) { - struct usb_host_endpoint *best_ep = NULL; - unsigned int best_psize = 3 * 1024; -@@ -1683,6 +1685,8 @@ int uvc_video_resume(struct uvc_streaming *stream, int reset) - - stream->frozen = 0; - -+ uvc_video_clock_reset(stream); -+ - ret = uvc_commit_video(stream, &stream->ctrl); - if (ret < 0) { - uvc_queue_enable(&stream->queue, 0); -@@ -1819,25 +1823,35 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable) - uvc_uninit_video(stream, 1); - usb_set_interface(stream->dev->udev, stream->intfnum, 0); - uvc_queue_enable(&stream->queue, 0); -+ uvc_video_clock_cleanup(stream); - return 0; - } - -- ret = uvc_queue_enable(&stream->queue, 1); -+ ret = uvc_video_clock_init(stream); - if (ret < 0) - return ret; - -+ ret = uvc_queue_enable(&stream->queue, 1); -+ if (ret < 0) -+ goto error_queue; -+ - /* Commit the streaming parameters. */ - ret = uvc_commit_video(stream, &stream->ctrl); -- if (ret < 0) { -- uvc_queue_enable(&stream->queue, 0); -- return ret; -- } -+ if (ret < 0) -+ goto error_commit; - - ret = uvc_init_video(stream, GFP_KERNEL); -- if (ret < 0) { -- usb_set_interface(stream->dev->udev, stream->intfnum, 0); -- uvc_queue_enable(&stream->queue, 0); -- } -+ if (ret < 0) -+ goto error_video; -+ -+ return 0; -+ -+error_video: -+ usb_set_interface(stream->dev->udev, stream->intfnum, 0); -+error_commit: -+ uvc_queue_enable(&stream->queue, 0); -+error_queue: -+ uvc_video_clock_cleanup(stream); - - return ret; - } From e01885614bdb6a33c97b852ecc491acf6992adb3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sat, 14 Apr 2012 09:23:39 -0400 Subject: [PATCH 352/487] Add ALSA quirk for MacPro 5,1 machines (rhbz 808559) --- ...k-Add-quirk-for-Mac-Pro-5-1-machines.patch | 37 +++++++++++++++++++ kernel.spec | 11 +++++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch diff --git a/ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch b/ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch new file mode 100644 index 000000000..28579d13b --- /dev/null +++ b/ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch @@ -0,0 +1,37 @@ +From a9e1e167d934aa74f48008393ade4f09fc587432 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Thu, 12 Apr 2012 13:55:36 -0400 +Subject: [PATCH] ALSA: hda/realtek - Add quirk for Mac Pro 5,1 machines + +A user reported that setting model=imac24 used to allow sound to work on their +Mac Pro 5,1 machine. Commit 5671087ffa "Move ALC885 macpro and imac24 models +to auto-parser" removed this model option. All Mac machines are now explicitly +handled with a quirk and the auto-parser. This adds a quirk for the device +found on the Mac Pro 5,1 machines. + +This (partially) fixes https://bugzilla.redhat.com/show_bug.cgi?id=808559 + +[sorted the new entry in the ID number order by tiwai] + +Reported-by: Gabriel Somlo +Signed-off-by: Josh Boyer +Signed-off-by: Takashi Iwai +--- + sound/pci/hda/patch_realtek.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 22c73b7..bd34b51 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -4659,6 +4659,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { + SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO), + SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD), + SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO), ++ SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO), + + SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), + SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index e860a5811..5e768de7c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -789,6 +789,9 @@ Patch21391: x86-Use-correct-byte-sized-register-constraint-in-__add.patch #rhbz 808207 CVE-2012-1601 Patch21520: KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch +#rhbz 808559 +Patch21530: ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch + # Debug patches Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch @@ -1348,6 +1351,9 @@ ApplyPatch linux-2.6-defaults-aspm.patch # ALSA +#rhbz 808559 +ApplyPatch ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch + # Networking @@ -2212,6 +2218,9 @@ fi # and build. %changelog +* Sat Apr 14 2012 Josh Boyer +- Add ALSA quirk for MacPro 5,1 machines (rhbz 808559) + * Fri Apr 13 2012 Josh Boyer - 3.3.2-1 - Linux 3.3.2 From 91cd87083437a6ec3c730a95b671f1d0cde83037 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 17 Apr 2012 11:05:33 -0400 Subject: [PATCH 353/487] Fix oops on invalid AMD microcode load (rhbz 797559) --- kernel.spec | 12 +- ...s-only-loaded-for-supported-AMD-CPUs.patch | 163 +++++++++++++++++ ...ng-module-unload-on-unsupported-CPUs.patch | 167 ++++++++++++++++++ 3 files changed, 341 insertions(+), 1 deletion(-) create mode 100644 x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch create mode 100644 x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch diff --git a/kernel.spec b/kernel.spec index 5e768de7c..323cefbd0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -792,6 +792,9 @@ Patch21520: KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch #rhbz 808559 Patch21530: ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch +Patch21700: x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch +Patch21701: x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch + # Debug patches Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch @@ -1480,6 +1483,10 @@ ApplyPatch libata-disable-runtime-pm-for-hotpluggable-port.patch ApplyPatch x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch ApplyPatch x86-Use-correct-byte-sized-register-constraint-in-__add.patch +#rhbz 797559 +ApplyPatch x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch +ApplyPatch x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch + # END OF PATCH APPLICATIONS %endif @@ -2218,6 +2225,9 @@ fi # and build. %changelog +* Tue Apr 17 2012 Josh Boyer +- Fix oops on invalid AMD microcode load (rhbz 797559) + * Sat Apr 14 2012 Josh Boyer - Add ALSA quirk for MacPro 5,1 machines (rhbz 808559) diff --git a/x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch b/x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch new file mode 100644 index 000000000..d69317316 --- /dev/null +++ b/x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch @@ -0,0 +1,163 @@ +Path: news.gmane.org!not-for-mail +From: Borislav Petkov +Newsgroups: gmane.linux.kernel +Subject: [PATCH 2/2] x86, microcode: Ensure that module is only loaded for +Date: Thu, 12 Apr 2012 18:34:22 +0200 +Lines: 80 +Approved: news@gmane.org +Message-ID: <20120412163422.GM24549@aftab> +References: <20120411163849.GE4794@alberich.amd.com> + <20120411200601.GC12288@kroah.com> + <20120411201053.GF18114@aftab> + <20120412162351.GJ24549@aftab> +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" +X-Trace: dough.gmane.org 1334248500 15307 80.91.229.3 (12 Apr 2012 16:35:00 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Thu, 12 Apr 2012 16:35:00 +0000 (UTC) +Cc: Andreas Herrmann , + Kay Sievers , + Dave Jones , +To: Greg Kroah-Hartman +Original-X-From: linux-kernel-owner@vger.kernel.org Thu Apr 12 18:34:59 2012 +Return-path: +Envelope-to: glk-linux-kernel-3@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1SIMz4-0008MV-3g + for glk-linux-kernel-3@plane.gmane.org; Thu, 12 Apr 2012 18:34:58 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S965760Ab2DLQep (ORCPT ); + Thu, 12 Apr 2012 12:34:45 -0400 +Original-Received: from db3ehsobe002.messaging.microsoft.com ([213.199.154.140]:56919 + "EHLO db3outboundpool.messaging.microsoft.com" rhost-flags-OK-OK-OK-OK) + by vger.kernel.org with ESMTP id S965553Ab2DLQen (ORCPT + ); + Thu, 12 Apr 2012 12:34:43 -0400 +Original-Received: from mail2-db3-R.bigfish.com (10.3.81.239) by + DB3EHSOBE005.bigfish.com (10.3.84.25) with Microsoft SMTP Server id + 14.1.225.23; Thu, 12 Apr 2012 16:34:41 +0000 +Original-Received: from mail2-db3 (localhost [127.0.0.1]) by mail2-db3-R.bigfish.com + (Postfix) with ESMTP id E4EF14404B4; Thu, 12 Apr 2012 16:34:41 +0000 (UTC) +X-SpamScore: 0 +X-BigFish: VPS0(zzzz1202hzz8275bh8275dhz2dh668h839h944hd25hd2bh) +X-Forefront-Antispam-Report: CIP:163.181.249.108;KIP:(null);UIP:(null);IPV:NLI;H:ausb3twp01.amd.com;RD:none;EFVD:NLI +Original-Received: from mail2-db3 (localhost.localdomain [127.0.0.1]) by mail2-db3 + (MessageSwitch) id 1334248479906480_3860; Thu, 12 Apr 2012 16:34:39 +0000 + (UTC) +Original-Received: from DB3EHSMHS005.bigfish.com (unknown [10.3.81.241]) by + mail2-db3.bigfish.com (Postfix) with ESMTP id CEB76400A4; Thu, 12 Apr 2012 + 16:34:39 +0000 (UTC) +Original-Received: from ausb3twp01.amd.com (163.181.249.108) by + DB3EHSMHS005.bigfish.com (10.3.87.105) with Microsoft SMTP Server id + 14.1.225.23; Thu, 12 Apr 2012 16:34:38 +0000 +X-WSS-ID: 0M2DKPO-01-CNU-02 +X-M-MSG: +Original-Received: from sausexedgep02.amd.com (sausexedgep02-ext.amd.com + [163.181.249.73]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No + client certificate requested) by ausb3twp01.amd.com (Axway MailGate 3.8.1) + with ESMTP id 2C1D81028100; Thu, 12 Apr 2012 11:34:36 -0500 (CDT) +Original-Received: from SAUSEXDAG02.amd.com (163.181.55.2) by sausexedgep02.amd.com + (163.181.36.59) with Microsoft SMTP Server (TLS) id 8.3.192.1; Thu, 12 Apr + 2012 11:34:51 -0500 +Original-Received: from storexhtp01.amd.com (172.24.4.3) by sausexdag02.amd.com + (163.181.55.2) with Microsoft SMTP Server (TLS) id 14.1.323.3; Thu, 12 Apr + 2012 11:34:36 -0500 +Original-Received: from gwo.osrc.amd.com (165.204.16.204) by storexhtp01.amd.com + (172.24.4.3) with Microsoft SMTP Server id 8.3.213.0; Thu, 12 Apr 2012 + 12:34:35 -0400 +Original-Received: from aftab (aftab.osrc.amd.com [165.204.15.109]) by gwo.osrc.amd.com + (Postfix) with ESMTP id D8E4C49C58B; Thu, 12 Apr 2012 17:34:33 +0100 (BST) +Content-Disposition: inline +In-Reply-To: <20120412162351.GJ24549@aftab> +User-Agent: Mutt/1.5.21 (2010-09-15) +X-OriginatorOrg: amd.com +Original-Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel:1281050 +Archived-At: + +From: Andreas Herrmann +Date: Thu, 12 Apr 2012 16:51:57 +0200 +Subject: [PATCH 2/2] x86, microcode: Ensure that module is only loaded for supported AMD CPUs + +Exit early when there's no support for a particular CPU family. Also, +fixup the "no support for this CPU vendor" to be issued only when the +driver is attempted to be loaded on an unsupported vendor. + +Cc: stable@vger.kernel.org +Cc: Tigran Aivazian +Cc: Borislav Petkov +[Boris: added a commit msg because Andreas is lazy] +Signed-off-by: Andreas Herrmann +--- + arch/x86/kernel/microcode_amd.c | 12 +++++++----- + arch/x86/kernel/microcode_core.c | 6 +++--- + 2 files changed, 10 insertions(+), 8 deletions(-) + +diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c +index 73465aa..8a2ce8f 100644 +--- a/arch/x86/kernel/microcode_amd.c ++++ b/arch/x86/kernel/microcode_amd.c +@@ -82,11 +82,6 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) + { + struct cpuinfo_x86 *c = &cpu_data(cpu); + +- if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { +- pr_warning("CPU%d: family %d not supported\n", cpu, c->x86); +- return -1; +- } +- + csig->rev = c->microcode; + pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev); + +@@ -380,6 +375,13 @@ static struct microcode_ops microcode_amd_ops = { + + struct microcode_ops * __init init_amd_microcode(void) + { ++ struct cpuinfo_x86 *c = &cpu_data(0); ++ ++ if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { ++ pr_warning("AMD CPU family 0x%x not supported\n", c->x86); ++ return NULL; ++ } ++ + patch = (void *)get_zeroed_page(GFP_KERNEL); + if (!patch) + return NULL; +diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c +index d389e74..c9bda6d 100644 +--- a/arch/x86/kernel/microcode_core.c ++++ b/arch/x86/kernel/microcode_core.c +@@ -526,11 +526,11 @@ static int __init microcode_init(void) + microcode_ops = init_intel_microcode(); + else if (c->x86_vendor == X86_VENDOR_AMD) + microcode_ops = init_amd_microcode(); +- +- if (!microcode_ops) { ++ else + pr_err("no support for this CPU vendor\n"); ++ ++ if (!microcode_ops) + return -ENODEV; +- } + + microcode_pdev = platform_device_register_simple("microcode", -1, + NULL, 0); +-- +1.7.8.4 + +-- +Regards/Gruss, +Boris. + +Advanced Micro Devices GmbH +Einsteinring 24, 85609 Dornach +GM: Alberto Bozzo +Reg: Dornach, Landkreis Muenchen +HRB Nr. 43632 WEEE Registernr: 129 19551 + diff --git a/x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch b/x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch new file mode 100644 index 000000000..d1cafc162 --- /dev/null +++ b/x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch @@ -0,0 +1,167 @@ +Path: news.gmane.org!not-for-mail +From: Borislav Petkov +Newsgroups: gmane.linux.kernel +Subject: [PATCH 1/2] x86, microcode: Fix sysfs warning during module unload +Date: Thu, 12 Apr 2012 18:30:38 +0200 +Lines: 83 +Approved: news@gmane.org +Message-ID: <20120412163038.GL24549@aftab> +References: <20120411163849.GE4794@alberich.amd.com> + <20120411200601.GC12288@kroah.com> + <20120411201053.GF18114@aftab> + <20120412162351.GJ24549@aftab> +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" +X-Trace: dough.gmane.org 1334248312 13759 80.91.229.3 (12 Apr 2012 16:31:52 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Thu, 12 Apr 2012 16:31:52 +0000 (UTC) +Cc: Andreas Herrmann , + Kay Sievers , + Dave Jones , +To: Greg Kroah-Hartman +Original-X-From: linux-kernel-owner@vger.kernel.org Thu Apr 12 18:31:50 2012 +Return-path: +Envelope-to: glk-linux-kernel-3@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1SIMw1-0005nm-KE + for glk-linux-kernel-3@plane.gmane.org; Thu, 12 Apr 2012 18:31:49 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S934534Ab2DLQbF (ORCPT ); + Thu, 12 Apr 2012 12:31:05 -0400 +Original-Received: from db3ehsobe004.messaging.microsoft.com ([213.199.154.142]:35401 + "EHLO db3outboundpool.messaging.microsoft.com" rhost-flags-OK-OK-OK-OK) + by vger.kernel.org with ESMTP id S934436Ab2DLQbD (ORCPT + ); + Thu, 12 Apr 2012 12:31:03 -0400 +Original-Received: from mail117-db3-R.bigfish.com (10.3.81.240) by + DB3EHSOBE002.bigfish.com (10.3.84.22) with Microsoft SMTP Server id + 14.1.225.23; Thu, 12 Apr 2012 16:31:00 +0000 +Original-Received: from mail117-db3 (localhost [127.0.0.1]) by + mail117-db3-R.bigfish.com (Postfix) with ESMTP id BAA93180481; Thu, 12 Apr + 2012 16:31:00 +0000 (UTC) +X-SpamScore: 1 +X-BigFish: VPS1(zzzz1202hzz8275eh8275bh8275dha1495iz2dh668h839h944hd25hd2bh) +X-Forefront-Antispam-Report: CIP:163.181.249.109;KIP:(null);UIP:(null);IPV:NLI;H:ausb3twp02.amd.com;RD:none;EFVD:NLI +Original-Received: from mail117-db3 (localhost.localdomain [127.0.0.1]) by mail117-db3 + (MessageSwitch) id 133424825930391_28243; Thu, 12 Apr 2012 16:30:59 +0000 + (UTC) +Original-Received: from DB3EHSMHS006.bigfish.com (unknown [10.3.81.226]) by + mail117-db3.bigfish.com (Postfix) with ESMTP id ED7022E004F; Thu, 12 Apr 2012 + 16:30:58 +0000 (UTC) +Original-Received: from ausb3twp02.amd.com (163.181.249.109) by + DB3EHSMHS006.bigfish.com (10.3.87.106) with Microsoft SMTP Server id + 14.1.225.23; Thu, 12 Apr 2012 16:30:57 +0000 +X-WSS-ID: 0M2DKJG-02-0NU-02 +X-M-MSG: +Original-Received: from sausexedgep01.amd.com (sausexedgep01-ext.amd.com + [163.181.249.72]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No + client certificate requested) by ausb3twp02.amd.com (Axway MailGate 3.8.1) + with ESMTP id 21D3FC814C; Thu, 12 Apr 2012 11:30:50 -0500 (CDT) +Original-Received: from SAUSEXDAG01.amd.com (163.181.55.1) by sausexedgep01.amd.com + (163.181.36.54) with Microsoft SMTP Server (TLS) id 8.3.192.1; Thu, 12 Apr + 2012 11:31:09 -0500 +Original-Received: from storexhtp02.amd.com (172.24.4.4) by sausexdag01.amd.com + (163.181.55.1) with Microsoft SMTP Server (TLS) id 14.1.323.3; Thu, 12 Apr + 2012 11:30:54 -0500 +Original-Received: from gwo.osrc.amd.com (165.204.16.204) by storexhtp02.amd.com + (172.24.4.4) with Microsoft SMTP Server id 8.3.213.0; Thu, 12 Apr 2012 + 12:30:51 -0400 +Original-Received: from aftab (aftab.osrc.amd.com [165.204.15.109]) by gwo.osrc.amd.com + (Postfix) with ESMTP id 0D00D49C58B; Thu, 12 Apr 2012 17:30:50 +0100 (BST) +Content-Disposition: inline +In-Reply-To: <20120412162351.GJ24549@aftab> +User-Agent: Mutt/1.5.21 (2010-09-15) +X-OriginatorOrg: amd.com +Original-Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel:1281049 +Archived-At: + +From: Andreas Herrmann +Date: Thu, 12 Apr 2012 16:48:01 +0200 +Subject: [PATCH 1/2] x86, microcode: Fix sysfs warning during module unload on unsupported CPUs + +Loading microcode driver on an unsupported CPU and subsequently +unloading the driver causes + + WARNING: at fs/sysfs/group.c:138 mc_device_remove+0x5f/0x70 [microcode]() + Hardware name: 01972NG + sysfs group ffffffffa00013d0 not found for kobject 'cpu0' + Modules linked in: snd_hda_codec_hdmi snd_hda_codec_conexant snd_hda_intel btusb snd_hda_codec bluetooth thinkpad_acpi rfkill microcode(-) [last unloaded: cfg80211] + Pid: 4560, comm: modprobe Not tainted 3.4.0-rc2-00002-g258f742 #5 + Call Trace: + [] ? warn_slowpath_common+0x7b/0xc0 + [] ? warn_slowpath_fmt+0x45/0x50 + [] ? sysfs_remove_group+0x34/0x120 + [] ? mc_device_remove+0x5f/0x70 [microcode] + [] ? subsys_interface_unregister+0x69/0xa0 + [] ? mutex_lock+0x16/0x40 + [] ? microcode_exit+0x50/0x92 [microcode] + [] ? sys_delete_module+0x16d/0x260 + [] ? wait_iff_congested+0x45/0x110 + [] ? page_fault+0x1f/0x30 + [] ? system_call_fastpath+0x16/0x1b + +on recent kernels. + +This is due to + + commit 8a25a2fd126c621f44f3aeaef80d51f00fc11639 + (cpu: convert 'cpu' and 'machinecheck' sysdev_class to a regular + subsystem) + +which renders + + commit 6c53cbfced048c421e4f72cb2183465f68fbc5e7 + (x86, microcode: Correct sysdev_add error path) + +useless. + +See http://marc.info/?l=linux-kernel&m=133416246406478 + +Avoid above warning by restoring the old driver behaviour before +commit 6c53cbfced048c421e4f72cb2183465f68fbc5e7 (x86, microcode: +Correct sysdev_add error path) + +Cc: stable@vger.kernel.org +Cc: Tigran Aivazian +Cc: Borislav Petkov +Signed-off-by: Andreas Herrmann +--- + arch/x86/kernel/microcode_core.c | 4 +--- + 1 files changed, 1 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c +index 87a0f86..d389e74 100644 +--- a/arch/x86/kernel/microcode_core.c ++++ b/arch/x86/kernel/microcode_core.c +@@ -419,10 +419,8 @@ static int mc_device_add(struct device *dev, struct subsys_interface *sif) + if (err) + return err; + +- if (microcode_init_cpu(cpu) == UCODE_ERROR) { +- sysfs_remove_group(&dev->kobj, &mc_attr_group); ++ if (microcode_init_cpu(cpu) == UCODE_ERROR) + return -EINVAL; +- } + + return err; + } +-- +1.7.8.4 + +-- +Regards/Gruss, +Boris. + +Advanced Micro Devices GmbH +Einsteinring 24, 85609 Dornach +GM: Alberto Bozzo +Reg: Dornach, Landkreis Muenchen +HRB Nr. 43632 WEEE Registernr: 129 19551 + From 9e205a991d19ce907c3a2a5cb8691195423f6f71 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 17 Apr 2012 11:12:10 -0400 Subject: [PATCH 354/487] Add "# END OF PATCH DEFINITIONS" tag (rhbz 811777) --- kernel.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel.spec b/kernel.spec index 323cefbd0..c30f85ab3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -799,6 +799,8 @@ Patch21701: x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CP Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch +# END OF PATCH DEFINITIONS + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root From 084e405734acd62ea4dc00c5a09f49bac0e8c6ee Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 17 Apr 2012 12:43:28 -0400 Subject: [PATCH 355/487] Fix oops in nfs_have_delegation (rhbz 811138) --- ...nups-for-nfs4_handle_exception-and-n.patch | 51 +++++++++++++++++++ kernel.spec | 3 ++ 2 files changed, 54 insertions(+) create mode 100644 NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch diff --git a/NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch b/NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch new file mode 100644 index 000000000..105235126 --- /dev/null +++ b/NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch @@ -0,0 +1,51 @@ +From 14977489ffdb80d4caf5a184ba41b23b02fbacd9 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Tue, 27 Mar 2012 18:31:25 -0400 +Subject: [PATCH] NFSv4: Minor cleanups for nfs4_handle_exception and + nfs4_async_handle_error + +Signed-off-by: Trond Myklebust +--- + fs/nfs/nfs4proc.c | 10 +++++----- + 1 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index 1933e67..f82bde0 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -270,7 +270,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc + case 0: + return 0; + case -NFS4ERR_OPENMODE: +- if (nfs_have_delegation(inode, FMODE_READ)) { ++ if (inode && nfs_have_delegation(inode, FMODE_READ)) { + nfs_inode_return_delegation(inode); + exception->retry = 1; + return 0; +@@ -282,10 +282,9 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc + case -NFS4ERR_DELEG_REVOKED: + case -NFS4ERR_ADMIN_REVOKED: + case -NFS4ERR_BAD_STATEID: +- if (state != NULL) +- nfs_remove_bad_delegation(state->inode); + if (state == NULL) + break; ++ nfs_remove_bad_delegation(state->inode); + nfs4_schedule_stateid_recovery(server, state); + goto wait_on_recovery; + case -NFS4ERR_EXPIRED: +@@ -3825,8 +3824,9 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, + case -NFS4ERR_DELEG_REVOKED: + case -NFS4ERR_ADMIN_REVOKED: + case -NFS4ERR_BAD_STATEID: +- if (state != NULL) +- nfs_remove_bad_delegation(state->inode); ++ if (state == NULL) ++ break; ++ nfs_remove_bad_delegation(state->inode); + case -NFS4ERR_OPENMODE: + if (state == NULL) + break; +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index c30f85ab3..423f3ba8d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -719,6 +719,7 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # NFSv4 Patch4000: NFSv4-Reduce-the-footprint-of-the-idmapper.patch Patch4001: NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch +Patch4107: NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch # patches headed upstream @@ -1331,6 +1332,7 @@ ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # NFSv4 ApplyPatch NFSv4-Reduce-the-footprint-of-the-idmapper.patch ApplyPatch NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch +ApplyPatch NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch # USB @@ -2228,6 +2230,7 @@ fi %changelog * Tue Apr 17 2012 Josh Boyer +- Fix oops in nfs_have_delegation (rhbz 811138) - Fix oops on invalid AMD microcode load (rhbz 797559) * Sat Apr 14 2012 Josh Boyer From 185d60abac1ba85ca761e3bbfe2f4d8c54f1ddc3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Apr 2012 18:44:38 -0300 Subject: [PATCH 356/487] Fix DVB-S2 to DVB-S switch back on Kaffeine Kaffeine basically tried to switch back to DVB-S using FE_SET_FRONTEND. This ioctl was not designed to allow mode switching. The only ioctl that (explicitly) sets a mode is FE_SET_PROPERTY. Yet, there's a compat code there that should have been converting the call into something different than SYS_UNKNOWN. So, let's fix the code there. It will hopefully do the right thing. Signed-off-by: Mauro Carvalho Chehab --- dvb_frontend_switch_regression_fix.patch | 65 ++++++++++++++++++++++++ kernel.spec | 5 ++ 2 files changed, 70 insertions(+) create mode 100644 dvb_frontend_switch_regression_fix.patch diff --git a/dvb_frontend_switch_regression_fix.patch b/dvb_frontend_switch_regression_fix.patch new file mode 100644 index 000000000..f5c701017 --- /dev/null +++ b/dvb_frontend_switch_regression_fix.patch @@ -0,0 +1,65 @@ +From c6c6fa8dcc27aad6ce3467544be0f57fd82b99a3 Mon Sep 17 00:00:00 2001 +From: Mauro Carvalho Chehab +Date: Tue, 17 Apr 2012 18:32:19 -0300 +Subject: [PATCH] [media] dvb_frontend: Fix a regression when switching back + to DVB-S + +There are some softwares (Kaffeine and likely xine) that uses a +DVBv5 call to switch to DVB-S2, but expects that a DVBv3 call to +switch back to DVB-S. Well, this is not right, as a DVBv3 call +doesn't know anything about delivery systems. + +However, as, by accident, this used to work, we need to restore its +behavior, in order to avoid regressions with those softwares. + +Reported on this Fedora 16 bugzilla: + https://bugzilla.redhat.com/show_bug.cgi?id=812895 + +Reported-by: Dieter Roever +Signed-off-by: Mauro Carvalho Chehab + +diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c +index 4555baa..bb582fd 100644 +--- a/drivers/media/dvb/dvb-core/dvb_frontend.c ++++ b/drivers/media/dvb/dvb-core/dvb_frontend.c +@@ -1443,6 +1443,28 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) + __func__); + return -EINVAL; + } ++ /* ++ * Get a delivery system that is compatible with DVBv3 ++ * NOTE: in order for this to work with softwares like Kaffeine that ++ * uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to ++ * DVB-S, drivers that support both should put the SYS_DVBS entry ++ * before the SYS_DVBS2, otherwise it won't switch back to DVB-S. ++ * The real fix is that userspace applications should not use DVBv3 ++ * and not trust on calling FE_SET_FRONTEND to switch the delivery ++ * system. ++ */ ++ ncaps = 0; ++ while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { ++ if (fe->ops.delsys[ncaps] == desired_system) { ++ delsys = desired_system; ++ break; ++ } ++ ncaps++; ++ } ++ if (delsys == SYS_UNDEFINED) { ++ dprintk("%s() Couldn't find a delivery system that matches %d\n", ++ __func__, desired_system); ++ } + } else { + /* + * This is a DVBv5 call. So, it likely knows the supported +@@ -1491,9 +1513,10 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) + __func__); + return -EINVAL; + } +- c->delivery_system = delsys; + } + ++ c->delivery_system = delsys; ++ + /* + * The DVBv3 or DVBv5 call is requesting a different system. So, + * emulation is needed. diff --git a/kernel.spec b/kernel.spec index 423f3ba8d..2ce9ce042 100644 --- a/kernel.spec +++ b/kernel.spec @@ -710,6 +710,7 @@ Patch2802: linux-2.6-silence-acpi-blacklist.patch # add-poll-requested-events.patch was added for 3.4 Patch2900: add-poll-requested-events.patch Patch2901: drivers-media-update.patch +Patch2902: dvb_frontend_switch_regression_fix.patch # fs fixes @@ -1417,6 +1418,7 @@ ApplyPatch quite-apm.patch # apply if non-empty ApplyPatch add-poll-requested-events.patch ApplyOptionalPatch drivers-media-update.patch +ApplyPatch dvb_frontend_switch_regression_fix.patch # Patches headed upstream @@ -2229,6 +2231,9 @@ fi # and build. %changelog +* Tue Apr 17 2012 Mauro Carvalho Chehab +- Fix DVB-S2->DVB-S switch regression (rhbz 812895) + * Tue Apr 17 2012 Josh Boyer - Fix oops in nfs_have_delegation (rhbz 811138) - Fix oops on invalid AMD microcode load (rhbz 797559) From 65b484ac04a0176790968627fc3f3fa1736378bc Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 18 Apr 2012 09:49:29 -0400 Subject: [PATCH 357/487] Disable CONFIG_HID_BATTERY_STRENGTH (rhbz 806295) --- disable-hid-battery.patch | 11 +++++++++++ kernel.spec | 11 ++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 disable-hid-battery.patch diff --git a/disable-hid-battery.patch b/disable-hid-battery.patch new file mode 100644 index 000000000..98fe2139e --- /dev/null +++ b/disable-hid-battery.patch @@ -0,0 +1,11 @@ +--- linux-2.6.43.noarch.orig/drivers/hid/Kconfig ++++ linux-2.6.43.noarch/drivers/hid/Kconfig +@@ -34,7 +34,7 @@ config HID + config HID_BATTERY_STRENGTH + bool + depends on HID && POWER_SUPPLY && HID = POWER_SUPPLY +- default y ++ default n + + config HIDRAW + bool "/dev/hidraw raw HID device support" diff --git a/kernel.spec b/kernel.spec index 2ce9ce042..81582148f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -797,6 +797,9 @@ Patch21530: ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch Patch21700: x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch Patch21701: x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch +#rhbz 806295 +Patch21710: disable-hid-battery.patch + # Debug patches Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch @@ -1493,6 +1496,9 @@ ApplyPatch x86-Use-correct-byte-sized-register-constraint-in-__add.patch ApplyPatch x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch ApplyPatch x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch +#rhbz 806295 +ApplyPatch disable-hid-battery.patch + # END OF PATCH APPLICATIONS %endif @@ -2231,6 +2237,9 @@ fi # and build. %changelog +* Wed Apr 18 2012 Josh Boyer +- Disable CONFIG_HID_BATTERY_STRENGTH (rhbz 806295) + * Tue Apr 17 2012 Mauro Carvalho Chehab - Fix DVB-S2->DVB-S switch regression (rhbz 812895) From 0ccb487a2bc58806c02d1ab3a2f433e72c8c717a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 18 Apr 2012 13:54:46 -0400 Subject: [PATCH 358/487] Change patch to resolve libata hotplug (rhbz 807632) --- kernel.spec | 9 +- ...ble-runtime-pm-for-hotpluggable-port.patch | 180 ------------------ ...ta-forbid-port-runtime-pm-by-default.patch | 24 +++ 3 files changed, 29 insertions(+), 184 deletions(-) delete mode 100644 libata-disable-runtime-pm-for-hotpluggable-port.patch create mode 100644 libata-forbid-port-runtime-pm-by-default.patch diff --git a/kernel.spec b/kernel.spec index 81582148f..4f9a39110 100644 --- a/kernel.spec +++ b/kernel.spec @@ -781,8 +781,8 @@ Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch #rhbz 808603 Patch21380: wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch -#rhbz 806676 807632 -Patch21385: libata-disable-runtime-pm-for-hotpluggable-port.patch +#rhbz 807632 +Patch21385: libata-forbid-port-runtime-pm-by-default.patch #rhbz 809014 Patch21390: x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch @@ -1485,8 +1485,8 @@ ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch #rhbz 808603 ApplyPatch wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch -#rhbz 806676 807632 -ApplyPatch libata-disable-runtime-pm-for-hotpluggable-port.patch +#rhbz 807632 +ApplyPatch libata-forbid-port-runtime-pm-by-default.patch #rhbz 809014 ApplyPatch x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch @@ -2238,6 +2238,7 @@ fi %changelog * Wed Apr 18 2012 Josh Boyer +- Change patch to resolve libata hotplug (rhbz 807632) - Disable CONFIG_HID_BATTERY_STRENGTH (rhbz 806295) * Tue Apr 17 2012 Mauro Carvalho Chehab diff --git a/libata-disable-runtime-pm-for-hotpluggable-port.patch b/libata-disable-runtime-pm-for-hotpluggable-port.patch deleted file mode 100644 index 06020fdde..000000000 --- a/libata-disable-runtime-pm-for-hotpluggable-port.patch +++ /dev/null @@ -1,180 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Lin Ming -Newsgroups: gmane.linux.ide,gmane.linux.kernel -Subject: [PATCH v2] libata: disable runtime pm for hotpluggable port -Date: Tue, 13 Mar 2012 09:57:37 +0800 -Lines: 131 -Approved: news@gmane.org -Message-ID: <1331603857.3436.24.camel@minggr> -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset="UTF-8" -Content-Transfer-Encoding: 7bit -X-Trace: dough.gmane.org 1331603865 12388 80.91.229.3 (13 Mar 2012 01:57:45 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Tue, 13 Mar 2012 01:57:45 +0000 (UTC) -Cc: linux-ide@vger.kernel.org, lkml , - jslaby@suse.cz, cwillu@cwillu.com, jackdachef@gmail.com, - Sergei Shtylyov -To: Jeff Garzik -Original-X-From: linux-ide-owner@vger.kernel.org Tue Mar 13 02:57:43 2012 -Return-path: -Envelope-to: lnx-linux-ide@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1S7Gze-0005pE-Sg - for lnx-linux-ide@plane.gmane.org; Tue, 13 Mar 2012 02:57:43 +0100 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1754650Ab2CMB5l (ORCPT ); - Mon, 12 Mar 2012 21:57:41 -0400 -Original-Received: from mga14.intel.com ([143.182.124.37]:15186 "EHLO mga14.intel.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1754582Ab2CMB5k (ORCPT ); - Mon, 12 Mar 2012 21:57:40 -0400 -Original-Received: from azsmga002.ch.intel.com ([10.2.17.35]) - by azsmga102.ch.intel.com with ESMTP; 12 Mar 2012 18:57:39 -0700 -X-ExtLoop1: 1 -X-IronPort-AV: E=Sophos;i="4.71,315,1320652800"; - d="scan'208";a="76719701" -Original-Received: from minggr.sh.intel.com (HELO [10.239.36.45]) ([10.239.36.45]) - by AZSMGA002.ch.intel.com with ESMTP; 12 Mar 2012 18:57:38 -0700 -X-Mailer: Evolution 2.30.3 -Original-Sender: linux-ide-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-ide@vger.kernel.org -Xref: news.gmane.org gmane.linux.ide:51560 gmane.linux.kernel:1266262 -Archived-At: - -Currently, hotplug doesn't work if port is already runtime suspended. -For now, we simply disable runtime pm for hotpluggable port. -Later, we should add runtime pm support for hotpluggable port too. - -Bug report: -https://lkml.org/lkml/2012/2/19/70 - -v2: -- Use bit 2 and 3 for flags ATA_FLAG_EXTERNAL and ATA_FLAG_PLUGGABLE. - -TODO: add similar hotpluggable port check for controllers other than -AHCI. - -Reported-and-tested-by: Jiri Slaby -Reported-and-tested-by: cwillu@cwillu.com -Reported-and-tested-by: jackdachef@gmail.com -Signed-off-by: Lin Ming ---- - drivers/ata/ahci.c | 3 +++ - drivers/ata/ahci.h | 3 +++ - drivers/ata/libahci.c | 20 ++++++++++++++++++++ - drivers/ata/libata-transport.c | 6 ++++-- - include/linux/libata.h | 2 ++ - 5 files changed, 32 insertions(+), 2 deletions(-) - -diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c -index d07bf03..02e93ff 100644 ---- a/drivers/ata/ahci.c -+++ b/drivers/ata/ahci.c -@@ -1145,6 +1145,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) - if (hpriv->cap & HOST_CAP_PMP) - pi.flags |= ATA_FLAG_PMP; - -+ if (hpriv->cap & HOST_CAP_SXS) -+ pi.flags |= ATA_FLAG_EXTERNAL; -+ - ahci_set_em_messages(hpriv, &pi); - - if (ahci_broken_system_poweroff(pdev)) { -diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h -index b175000..92f7172 100644 ---- a/drivers/ata/ahci.h -+++ b/drivers/ata/ahci.h -@@ -172,6 +172,9 @@ enum { - PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */ - PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ - PORT_CMD_FBSCP = (1 << 22), /* FBS Capable Port */ -+ PORT_CMD_ESP = (1 << 21), /* External SATA Port */ -+ PORT_CMD_MPSP = (1 << 19), /* Mechanical Presence Switch Attached to Port */ -+ PORT_CMD_HPCP = (1 << 18), /* Hot Plug Capable Port */ - PORT_CMD_PMP = (1 << 17), /* PMP attached */ - PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ - PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */ -diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c -index a72bfd0..7d72d3c 100644 ---- a/drivers/ata/libahci.c -+++ b/drivers/ata/libahci.c -@@ -1097,6 +1097,23 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap, - writel(1 << port_no, mmio + HOST_IRQ_STAT); - } - -+static bool ahci_port_pluggable(struct ata_port *ap) -+{ -+ void __iomem *port_mmio = ahci_port_base(ap); -+ u32 cmd; -+ -+ cmd = readl(port_mmio + PORT_CMD); -+ -+ if ((ap->flags & ATA_FLAG_EXTERNAL) && -+ (cmd & PORT_CMD_ESP)) -+ return true; -+ -+ if (cmd & (PORT_CMD_MPSP | PORT_CMD_HPCP)) -+ return true; -+ -+ return false; -+} -+ - void ahci_init_controller(struct ata_host *host) - { - struct ahci_host_priv *hpriv = host->private_data; -@@ -1112,6 +1129,9 @@ void ahci_init_controller(struct ata_host *host) - if (ata_port_is_dummy(ap)) - continue; - -+ if (ahci_port_pluggable(ap)) -+ ap->flags |= ATA_FLAG_PLUGGABLE; -+ - ahci_port_init(host->dev, ap, i, mmio, port_mmio); - } - -diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c -index 74aaee3..a7166b9 100644 ---- a/drivers/ata/libata-transport.c -+++ b/drivers/ata/libata-transport.c -@@ -292,8 +292,10 @@ int ata_tport_add(struct device *parent, - } - - device_enable_async_suspend(dev); -- pm_runtime_set_active(dev); -- pm_runtime_enable(dev); -+ if (!(ap->flags & ATA_FLAG_PLUGGABLE)) { -+ pm_runtime_set_active(dev); -+ pm_runtime_enable(dev); -+ } - - transport_add_device(dev); - transport_configure_device(dev); -diff --git a/include/linux/libata.h b/include/linux/libata.h -index cafc09a..f46961d 100644 ---- a/include/linux/libata.h -+++ b/include/linux/libata.h -@@ -187,6 +187,8 @@ enum { - ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */ - /* (doesn't imply presence) */ - ATA_FLAG_SATA = (1 << 1), -+ ATA_FLAG_EXTERNAL = (1 << 2), /* Controller supports external SATA */ -+ ATA_FLAG_PLUGGABLE = (1 << 3), /* Port is hotpluggable */ - ATA_FLAG_NO_ATAPI = (1 << 6), /* No ATAPI support */ - ATA_FLAG_PIO_DMA = (1 << 7), /* PIO cmds via DMA */ - ATA_FLAG_PIO_LBA48 = (1 << 8), /* Host DMA engine is LBA28 only */ --- -1.7.2.5 - - - --- -To unsubscribe from this list: send the line "unsubscribe linux-ide" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - diff --git a/libata-forbid-port-runtime-pm-by-default.patch b/libata-forbid-port-runtime-pm-by-default.patch new file mode 100644 index 000000000..0d93a19f5 --- /dev/null +++ b/libata-forbid-port-runtime-pm-by-default.patch @@ -0,0 +1,24 @@ +From: Lin Ming +Date: Wed, 18 Apr 2012 09:13:41 +0800 +Subject: [PATCH] libata: forbid port runtime pm by default + +Forbid port runtime pm by default because it has known hotplug issue. +User can allow it by, for example + +echo auto > /sys/devices/pci0000:00/0000:00:1f.2/ata2/power/control + +Signed-off-by: Lin Ming +--- + drivers/ata/libata-transport.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +--- linux-3.3.noarch.orig/drivers/ata/libata-transport.c ++++ linux-3.3.noarch/drivers/ata/libata-transport.c +@@ -294,6 +294,7 @@ int ata_tport_add(struct device *parent, + device_enable_async_suspend(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); ++ pm_runtime_forbid(dev); + + transport_add_device(dev); + transport_configure_device(dev); From 081d2dbff00ca0f07eb4c213a017b283635ceeef Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 19 Apr 2012 09:54:06 -0500 Subject: [PATCH 359/487] Fix KVM device assignment page leak --- ...rom-the-iommu-when-slots-are-removed.patch | 92 +++++++++++++++++++ kernel.spec | 9 ++ 2 files changed, 101 insertions(+) create mode 100644 KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch diff --git a/KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch b/KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch new file mode 100644 index 000000000..b98e392f7 --- /dev/null +++ b/KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch @@ -0,0 +1,92 @@ +commit 32f6daad4651a748a58a3ab6da0611862175722f +Author: Alex Williamson +Date: Wed Apr 11 09:51:49 2012 -0600 + + KVM: unmap pages from the iommu when slots are removed + + We've been adding new mappings, but not destroying old mappings. + This can lead to a page leak as pages are pinned using + get_user_pages, but only unpinned with put_page if they still + exist in the memslots list on vm shutdown. A memslot that is + destroyed while an iommu domain is enabled for the guest will + therefore result in an elevated page reference count that is + never cleared. + + Additionally, without this fix, the iommu is only programmed + with the first translation for a gpa. This can result in + peer-to-peer errors if a mapping is destroyed and replaced by a + new mapping at the same gpa as the iommu will still be pointing + to the original, pinned memory address. + + Signed-off-by: Alex Williamson + Signed-off-by: Marcelo Tosatti + +diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h +index 665a260..72cbf08 100644 +--- a/include/linux/kvm_host.h ++++ b/include/linux/kvm_host.h +@@ -596,6 +596,7 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id); + + #ifdef CONFIG_IOMMU_API + int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot); ++void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot); + int kvm_iommu_map_guest(struct kvm *kvm); + int kvm_iommu_unmap_guest(struct kvm *kvm); + int kvm_assign_device(struct kvm *kvm, +@@ -609,6 +610,11 @@ static inline int kvm_iommu_map_pages(struct kvm *kvm, + return 0; + } + ++static inline void kvm_iommu_unmap_pages(struct kvm *kvm, ++ struct kvm_memory_slot *slot) ++{ ++} ++ + static inline int kvm_iommu_map_guest(struct kvm *kvm) + { + return -ENODEV; +diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c +index a457d21..fec1723 100644 +--- a/virt/kvm/iommu.c ++++ b/virt/kvm/iommu.c +@@ -310,6 +310,11 @@ static void kvm_iommu_put_pages(struct kvm *kvm, + } + } + ++void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot) ++{ ++ kvm_iommu_put_pages(kvm, slot->base_gfn, slot->npages); ++} ++ + static int kvm_iommu_unmap_memslots(struct kvm *kvm) + { + int idx; +@@ -320,7 +325,7 @@ static int kvm_iommu_unmap_memslots(struct kvm *kvm) + slots = kvm_memslots(kvm); + + kvm_for_each_memslot(memslot, slots) +- kvm_iommu_put_pages(kvm, memslot->base_gfn, memslot->npages); ++ kvm_iommu_unmap_pages(kvm, memslot); + + srcu_read_unlock(&kvm->srcu, idx); + +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index 42b7393..9739b53 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -808,12 +808,13 @@ int __kvm_set_memory_region(struct kvm *kvm, + if (r) + goto out_free; + +- /* map the pages in iommu page table */ ++ /* map/unmap the pages in iommu page table */ + if (npages) { + r = kvm_iommu_map_pages(kvm, &new); + if (r) + goto out_free; +- } ++ } else ++ kvm_iommu_unmap_pages(kvm, &old); + + r = -ENOMEM; + slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots), diff --git a/kernel.spec b/kernel.spec index 4f9a39110..a88113769 100644 --- a/kernel.spec +++ b/kernel.spec @@ -804,6 +804,9 @@ Patch21710: disable-hid-battery.patch Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch +#rhbz 814149 814155 +Patch22006: KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch + # END OF PATCH DEFINITIONS %endif @@ -1499,6 +1502,9 @@ ApplyPatch x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPU #rhbz 806295 ApplyPatch disable-hid-battery.patch +#rhbz 814149 814155 +ApplyPatch KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch + # END OF PATCH APPLICATIONS %endif @@ -2237,6 +2243,9 @@ fi # and build. %changelog +* Thu Apr 19 2012 Justin M. Forbes +- Fix KVM device assignment page leak (rhbz 814149 814155) + * Wed Apr 18 2012 Josh Boyer - Change patch to resolve libata hotplug (rhbz 807632) - Disable CONFIG_HID_BATTERY_STRENGTH (rhbz 806295) From 92b55943d6b20b0f4eb2a86cbc3b6567494f2da9 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 19 Apr 2012 16:23:18 -0500 Subject: [PATCH 360/487] CVE-2012-2119 macvtap: zerocopy: vector length is not validated before pinning user pages (rhbz 814278 814289) --- kernel.spec | 14 +++++++++-- macvtap-zerocopy-validate-vector-length.patch | 25 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 macvtap-zerocopy-validate-vector-length.patch diff --git a/kernel.spec b/kernel.spec index a88113769..433e1cdd0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -804,9 +804,12 @@ Patch21710: disable-hid-battery.patch Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch -#rhbz 814149 814155 +#rhbz 814149 814155 CVE-2012-2121 Patch22006: KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch +#rhbz 814278 814289 CVE-2012-2119 +Patch22007: macvtap-zerocopy-validate-vector-length.patch + # END OF PATCH DEFINITIONS %endif @@ -1502,9 +1505,12 @@ ApplyPatch x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPU #rhbz 806295 ApplyPatch disable-hid-battery.patch -#rhbz 814149 814155 +#rhbz 814149 814155 CVE-2012-2121 ApplyPatch KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch +#rhbz 814278 814289 CVE-2012-2119 +ApplyPatch macvtap-zerocopy-validate-vector-length.patch + # END OF PATCH APPLICATIONS %endif @@ -2243,6 +2249,10 @@ fi # and build. %changelog +* Thu Apr 19 2012 Justin M. Forbes - 3.3.2-4 +- CVE-2012-2119 macvtap: zerocopy: vector length is not validated before + pinning user pages (rhbz 814278 814289) + * Thu Apr 19 2012 Justin M. Forbes - Fix KVM device assignment page leak (rhbz 814149 814155) diff --git a/macvtap-zerocopy-validate-vector-length.patch b/macvtap-zerocopy-validate-vector-length.patch new file mode 100644 index 000000000..3ac31e4b6 --- /dev/null +++ b/macvtap-zerocopy-validate-vector-length.patch @@ -0,0 +1,25 @@ +Currently we do not validate the vector length before calling +get_user_pages_fast(), host stack would be easily overflowed by +malicious guest driver who give us a descriptor with length greater +than MAX_SKB_FRAGS. Solve this problem by checking the free entries +before trying to pin user pages. + +Signed-off-by: Jason Wang +--- + drivers/net/macvtap.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c +index 7cb2684..d197a78 100644 +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -527,6 +527,8 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, + } + base = (unsigned long)from->iov_base + offset1; + size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT; ++ if (i + size >= MAX_SKB_FRAGS) ++ return -EFAULT; + num_pages = get_user_pages_fast(base, size, 0, &page[i]); + if ((num_pages != size) || + (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags)) + From 7439674e98443e92b780108207b829defb64d703 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 20 Apr 2012 08:28:25 -0400 Subject: [PATCH 361/487] CVE-2012-2123 fcaps: clear the same personality flags as suid when fcaps are used (rhbz 814523 806722) --- ...same-personality-flags-as-suid-when-.patch | 38 +++++++++++++++++++ kernel.spec | 14 ++++++- ...ity-fix-compile-error-in-commoncap.c.patch | 28 ++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 fcaps-clear-the-same-personality-flags-as-suid-when-.patch create mode 100644 security-fix-compile-error-in-commoncap.c.patch diff --git a/fcaps-clear-the-same-personality-flags-as-suid-when-.patch b/fcaps-clear-the-same-personality-flags-as-suid-when-.patch new file mode 100644 index 000000000..1cf2ac208 --- /dev/null +++ b/fcaps-clear-the-same-personality-flags-as-suid-when-.patch @@ -0,0 +1,38 @@ +From d52fc5dde171f030170a6cb78034d166b13c9445 Mon Sep 17 00:00:00 2001 +From: Eric Paris +Date: Tue, 17 Apr 2012 16:26:54 -0400 +Subject: [PATCH] fcaps: clear the same personality flags as suid when fcaps + are used + +If a process increases permissions using fcaps all of the dangerous +personality flags which are cleared for suid apps should also be cleared. +Thus programs given priviledge with fcaps will continue to have address space +randomization enabled even if the parent tried to disable it to make it +easier to attack. + +Signed-off-by: Eric Paris +Reviewed-by: Serge Hallyn +Signed-off-by: James Morris +--- + security/commoncap.c | 5 +++++ + 1 files changed, 5 insertions(+), 0 deletions(-) + +diff --git a/security/commoncap.c b/security/commoncap.c +index 0cf4b53..0ecf4ba 100644 +--- a/security/commoncap.c ++++ b/security/commoncap.c +@@ -505,6 +505,11 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) + } + skip: + ++ /* if we have fs caps, clear dangerous personality flags */ ++ if (!cap_issubset(new->cap_permitted, old->cap_permitted)) ++ bprm->per_clear |= PER_CLEAR_ON_SETID; ++ ++ + /* Don't let someone trace a set[ug]id/setpcap binary with the revised + * credentials unless they have the appropriate permit + */ +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index 433e1cdd0..e99c3120c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -810,6 +810,10 @@ Patch22006: KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch #rhbz 814278 814289 CVE-2012-2119 Patch22007: macvtap-zerocopy-validate-vector-length.patch +#rhbz 814523 806722 CVE-2012-2123 +Patch22008: fcaps-clear-the-same-personality-flags-as-suid-when-.patch +Patch22009: security-fix-compile-error-in-commoncap.c.patch + # END OF PATCH DEFINITIONS %endif @@ -1511,6 +1515,10 @@ ApplyPatch KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch #rhbz 814278 814289 CVE-2012-2119 ApplyPatch macvtap-zerocopy-validate-vector-length.patch +#rhbz 814523 806722 CVE-2012-2123 +ApplyPatch fcaps-clear-the-same-personality-flags-as-suid-when-.patch +ApplyPatch security-fix-compile-error-in-commoncap.c.patch + # END OF PATCH APPLICATIONS %endif @@ -2249,6 +2257,10 @@ fi # and build. %changelog +* Fri Apr 20 2012 Josh Boyer +- CVE-2012-2123 fcaps: clear the same personality flags as suid when fcaps + are used (rhbz 814523 806722) + * Thu Apr 19 2012 Justin M. Forbes - 3.3.2-4 - CVE-2012-2119 macvtap: zerocopy: vector length is not validated before pinning user pages (rhbz 814278 814289) diff --git a/security-fix-compile-error-in-commoncap.c.patch b/security-fix-compile-error-in-commoncap.c.patch new file mode 100644 index 000000000..de333e219 --- /dev/null +++ b/security-fix-compile-error-in-commoncap.c.patch @@ -0,0 +1,28 @@ +From 51b79bee627d526199b2f6a6bef8ee0c0739b6d1 Mon Sep 17 00:00:00 2001 +From: Jonghwan Choi +Date: Wed, 18 Apr 2012 17:23:04 -0400 +Subject: [PATCH] security: fix compile error in commoncap.c + +Add missing "personality.h" +security/commoncap.c: In function 'cap_bprm_set_creds': +security/commoncap.c:510: error: 'PER_CLEAR_ON_SETID' undeclared (first use in this function) +security/commoncap.c:510: error: (Each undeclared identifier is reported only once +security/commoncap.c:510: error: for each function it appears in.) + +Signed-off-by: Jonghwan Choi +Acked-by: Serge Hallyn +Signed-off-by: James Morris +--- + security/commoncap.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +--- linux-3.3.2-6.fc17.noarch.orig/security/commoncap.c ++++ linux-3.3.2-6.fc17.noarch/security/commoncap.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + /* + * If a non-root user executes a setuid-root binary in From aa313d9123728ac39be8e390bc9e0a39500d80af Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sat, 21 Apr 2012 08:07:10 -0400 Subject: [PATCH 362/487] Fix error check in memblock that prevented boot on various Dells (rhbz 811225) --- kernel.spec | 11 +++- ...k-should-be-able-to-handle-zero-leng.patch | 63 +++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 memblock-memblock-should-be-able-to-handle-zero-leng.patch diff --git a/kernel.spec b/kernel.spec index e99c3120c..3a8320c2f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 5 +%global baserelease 6 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -814,6 +814,9 @@ Patch22007: macvtap-zerocopy-validate-vector-length.patch Patch22008: fcaps-clear-the-same-personality-flags-as-suid-when-.patch Patch22009: security-fix-compile-error-in-commoncap.c.patch +#rhbz 811225 +Patch22010: memblock-memblock-should-be-able-to-handle-zero-leng.patch + # END OF PATCH DEFINITIONS %endif @@ -1519,6 +1522,9 @@ ApplyPatch macvtap-zerocopy-validate-vector-length.patch ApplyPatch fcaps-clear-the-same-personality-flags-as-suid-when-.patch ApplyPatch security-fix-compile-error-in-commoncap.c.patch +#rhbz 811225 +ApplyPatch memblock-memblock-should-be-able-to-handle-zero-leng.patch + # END OF PATCH APPLICATIONS %endif @@ -2257,6 +2263,9 @@ fi # and build. %changelog +* Sat Apr 21 2012 Josh Boyer - 3.3.2-6 +- Fix error check in memblock that prevented boot on various Dells (rhbz 811225) + * Fri Apr 20 2012 Josh Boyer - CVE-2012-2123 fcaps: clear the same personality flags as suid when fcaps are used (rhbz 814523 806722) diff --git a/memblock-memblock-should-be-able-to-handle-zero-leng.patch b/memblock-memblock-should-be-able-to-handle-zero-leng.patch new file mode 100644 index 000000000..08e364534 --- /dev/null +++ b/memblock-memblock-should-be-able-to-handle-zero-leng.patch @@ -0,0 +1,63 @@ +From b3dc627cabb33fc95f93da78457770c1b2a364d2 Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Fri, 20 Apr 2012 08:31:34 -0700 +Subject: [PATCH] memblock: memblock should be able to handle zero length + operations + +Commit 24aa07882b ("memblock, x86: Replace memblock_x86_reserve/ +free_range() with generic ones") replaced x86 specific memblock +operations with the generic ones; unfortunately, it lost zero length +operation handling in the process making the kernel panic if somebody +tries to reserve zero length area. + +There isn't much to be gained by being cranky to zero length operations +and panicking is almost the worst response. Drop the BUG_ON() in +memblock_reserve() and update memblock_add_region/isolate_range() so +that all zero length operations are handled as noops. + +Signed-off-by: Tejun Heo +Cc: stable@vger.kernel.org +Reported-by: Valere Monseur +Bisected-by: Joseph Freeman +Tested-by: Joseph Freeman +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=43098 +Signed-off-by: Linus Torvalds +--- + mm/memblock.c | 7 ++++++- + 1 files changed, 6 insertions(+), 1 deletions(-) + +diff --git a/mm/memblock.c b/mm/memblock.c +index 99f2855..a44eab3 100644 +--- a/mm/memblock.c ++++ b/mm/memblock.c +@@ -330,6 +330,9 @@ static int __init_memblock memblock_add_region(struct memblock_type *type, + phys_addr_t end = base + memblock_cap_size(base, &size); + int i, nr_new; + ++ if (!size) ++ return 0; ++ + /* special case for empty array */ + if (type->regions[0].size == 0) { + WARN_ON(type->cnt != 1 || type->total_size); +@@ -430,6 +433,9 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, + + *start_rgn = *end_rgn = 0; + ++ if (!size) ++ return 0; ++ + /* we'll create at most two more regions */ + while (type->cnt + 2 > type->max) + if (memblock_double_array(type) < 0) +@@ -514,7 +520,6 @@ int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size) + (unsigned long long)base, + (unsigned long long)base + size, + (void *)_RET_IP_); +- BUG_ON(0 == size); + + return memblock_add_region(_rgn, base, size, MAX_NUMNODES); + } +-- +1.7.7.6 + From d102db46724fd0beb1d52ce4313924b96ff6bab0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 23 Apr 2012 07:45:52 -0400 Subject: [PATCH 363/487] Linux 3.3.3 --- ...-USB-device-13d3-3375-as-an-Atheros-.patch | 58 ------------------- ...same-personality-flags-as-suid-when-.patch | 38 ------------ kernel.spec | 25 ++------ ...ity-fix-compile-error-in-commoncap.c.patch | 28 --------- sources | 2 +- ...e-sized-register-constraint-in-__add.patch | 35 ----------- ...zed-register-constraint-in-__xchg_op.patch | 32 ---------- 7 files changed, 6 insertions(+), 212 deletions(-) delete mode 100644 Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch delete mode 100644 fcaps-clear-the-same-personality-flags-as-suid-when-.patch delete mode 100644 security-fix-compile-error-in-commoncap.c.patch delete mode 100644 x86-Use-correct-byte-sized-register-constraint-in-__add.patch delete mode 100644 x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch diff --git a/Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch b/Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch deleted file mode 100644 index f238d50da..000000000 --- a/Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 9498ba7a1d38d42eef4ef6d906ab1743c9f0fd6f Mon Sep 17 00:00:00 2001 -From: Eran -Date: Mon, 5 Dec 2011 22:15:29 +0000 -Subject: [PATCH] Bluetooth: Adding USB device 13d3:3375 as an Atheros AR3012. - -The bluetooth module in the Asus UX31/UX21 is based on Atheros AR3012 -and requires a firmware to be uploaded before it's usable. - -output of usb-devices for this module: -T: Bus=01 Lev=02 Prnt=02 Port=07 Cnt=03 Dev#= 6 Spd=12 MxCh= 0 -D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 -P: Vendor=13d3 ProdID=3375 Rev=00.02 -S: Manufacturer=Atheros Communications -S: Product=Bluetooth USB Host Controller -S: SerialNumber=Alaska Day 2006 -C: #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA -I: If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb -I: If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb - -Signed-off-by: Eran -Tested-by: Michal Labedzki -Signed-off-by: Gustavo F. Padovan - -diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c -index 4eca6e5..4844247 100644 ---- a/drivers/bluetooth/ath3k.c -+++ b/drivers/bluetooth/ath3k.c -@@ -72,6 +72,7 @@ static struct usb_device_id ath3k_table[] = { - - /* Atheros AR3012 with sflash firmware*/ - { USB_DEVICE(0x0CF3, 0x3004) }, -+ { USB_DEVICE(0x13d3, 0x3375) }, - - /* Atheros AR5BBU12 with sflash firmware */ - { USB_DEVICE(0x0489, 0xE02C) }, -@@ -88,6 +89,7 @@ static struct usb_device_id ath3k_blist_tbl[] = { - - /* Atheros AR3012 with sflash firmware*/ - { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, -+ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, - - { } /* Terminating entry */ - }; -diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c -index 22f695e..480cad9 100644 ---- a/drivers/bluetooth/btusb.c -+++ b/drivers/bluetooth/btusb.c -@@ -129,6 +129,7 @@ static struct usb_device_id blacklist_table[] = { - - /* Atheros 3012 with sflash firmware */ - { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, -+ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, - - /* Atheros AR5BBU12 with sflash firmware */ - { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, --- -1.7.7.6 - diff --git a/fcaps-clear-the-same-personality-flags-as-suid-when-.patch b/fcaps-clear-the-same-personality-flags-as-suid-when-.patch deleted file mode 100644 index 1cf2ac208..000000000 --- a/fcaps-clear-the-same-personality-flags-as-suid-when-.patch +++ /dev/null @@ -1,38 +0,0 @@ -From d52fc5dde171f030170a6cb78034d166b13c9445 Mon Sep 17 00:00:00 2001 -From: Eric Paris -Date: Tue, 17 Apr 2012 16:26:54 -0400 -Subject: [PATCH] fcaps: clear the same personality flags as suid when fcaps - are used - -If a process increases permissions using fcaps all of the dangerous -personality flags which are cleared for suid apps should also be cleared. -Thus programs given priviledge with fcaps will continue to have address space -randomization enabled even if the parent tried to disable it to make it -easier to attack. - -Signed-off-by: Eric Paris -Reviewed-by: Serge Hallyn -Signed-off-by: James Morris ---- - security/commoncap.c | 5 +++++ - 1 files changed, 5 insertions(+), 0 deletions(-) - -diff --git a/security/commoncap.c b/security/commoncap.c -index 0cf4b53..0ecf4ba 100644 ---- a/security/commoncap.c -+++ b/security/commoncap.c -@@ -505,6 +505,11 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) - } - skip: - -+ /* if we have fs caps, clear dangerous personality flags */ -+ if (!cap_issubset(new->cap_permitted, old->cap_permitted)) -+ bprm->per_clear |= PER_CLEAR_ON_SETID; -+ -+ - /* Don't let someone trace a set[ug]id/setpcap binary with the revised - * credentials unless they have the appropriate permit - */ --- -1.7.7.6 - diff --git a/kernel.spec b/kernel.spec index 3a8320c2f..39cc9af02 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 6 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 2 +%define stable_update 3 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -736,7 +736,6 @@ Patch14001: hibernate-watermark.patch Patch14010: lis3-improve-handling-of-null-rate.patch Patch15000: bluetooth-use-after-free.patch -Patch15001: Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch Patch19000: ips-noirq.patch @@ -784,10 +783,6 @@ Patch21380: wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch #rhbz 807632 Patch21385: libata-forbid-port-runtime-pm-by-default.patch -#rhbz 809014 -Patch21390: x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch -Patch21391: x86-Use-correct-byte-sized-register-constraint-in-__add.patch - #rhbz 808207 CVE-2012-1601 Patch21520: KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch @@ -810,10 +805,6 @@ Patch22006: KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch #rhbz 814278 814289 CVE-2012-2119 Patch22007: macvtap-zerocopy-validate-vector-length.patch -#rhbz 814523 806722 CVE-2012-2123 -Patch22008: fcaps-clear-the-same-personality-flags-as-suid-when-.patch -Patch22009: security-fix-compile-error-in-commoncap.c.patch - #rhbz 811225 Patch22010: memblock-memblock-should-be-able-to-handle-zero-leng.patch @@ -1452,7 +1443,6 @@ ApplyPatch hibernate-watermark.patch ApplyPatch lis3-improve-handling-of-null-rate.patch ApplyPatch bluetooth-use-after-free.patch -ApplyPatch Bluetooth-Adding-USB-device-13d3-3375-as-an-Atheros-.patch ApplyPatch ips-noirq.patch @@ -1501,10 +1491,6 @@ ApplyPatch wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch #rhbz 807632 ApplyPatch libata-forbid-port-runtime-pm-by-default.patch -#rhbz 809014 -ApplyPatch x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch -ApplyPatch x86-Use-correct-byte-sized-register-constraint-in-__add.patch - #rhbz 797559 ApplyPatch x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch ApplyPatch x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch @@ -1518,10 +1504,6 @@ ApplyPatch KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch #rhbz 814278 814289 CVE-2012-2119 ApplyPatch macvtap-zerocopy-validate-vector-length.patch -#rhbz 814523 806722 CVE-2012-2123 -ApplyPatch fcaps-clear-the-same-personality-flags-as-suid-when-.patch -ApplyPatch security-fix-compile-error-in-commoncap.c.patch - #rhbz 811225 ApplyPatch memblock-memblock-should-be-able-to-handle-zero-leng.patch @@ -2263,6 +2245,9 @@ fi # and build. %changelog +* Mon Apr 23 2012 Josh Boyer +- Linux 3.3.3 + * Sat Apr 21 2012 Josh Boyer - 3.3.2-6 - Fix error check in memblock that prevented boot on various Dells (rhbz 811225) diff --git a/security-fix-compile-error-in-commoncap.c.patch b/security-fix-compile-error-in-commoncap.c.patch deleted file mode 100644 index de333e219..000000000 --- a/security-fix-compile-error-in-commoncap.c.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 51b79bee627d526199b2f6a6bef8ee0c0739b6d1 Mon Sep 17 00:00:00 2001 -From: Jonghwan Choi -Date: Wed, 18 Apr 2012 17:23:04 -0400 -Subject: [PATCH] security: fix compile error in commoncap.c - -Add missing "personality.h" -security/commoncap.c: In function 'cap_bprm_set_creds': -security/commoncap.c:510: error: 'PER_CLEAR_ON_SETID' undeclared (first use in this function) -security/commoncap.c:510: error: (Each undeclared identifier is reported only once -security/commoncap.c:510: error: for each function it appears in.) - -Signed-off-by: Jonghwan Choi -Acked-by: Serge Hallyn -Signed-off-by: James Morris ---- - security/commoncap.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - ---- linux-3.3.2-6.fc17.noarch.orig/security/commoncap.c -+++ linux-3.3.2-6.fc17.noarch/security/commoncap.c -@@ -28,6 +28,7 @@ - #include - #include - #include -+#include - - /* - * If a non-root user executes a setuid-root binary in diff --git a/sources b/sources index 413d6dc42..d1990b3af 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz -68907107b0f62a19608588bdb6b29e20 patch-3.3.2.xz +634a088d3789870885dc6ee1eb9627d4 patch-3.3.3.xz diff --git a/x86-Use-correct-byte-sized-register-constraint-in-__add.patch b/x86-Use-correct-byte-sized-register-constraint-in-__add.patch deleted file mode 100644 index 3ec765691..000000000 --- a/x86-Use-correct-byte-sized-register-constraint-in-__add.patch +++ /dev/null @@ -1,35 +0,0 @@ -From: H. Peter Anvin -Date: Fri, 6 Apr 2012 16:30:57 +0000 (-0700) -Subject: x86: Use correct byte-sized register constraint in __add() -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftip%2Ftip.git;a=commitdiff_plain;h=8c91c5325e107ec17e40a59a47c6517387d64eb7 - -x86: Use correct byte-sized register constraint in __add() - -Similar to: - - 2ca052a x86: Use correct byte-sized register constraint in __xchg_op() - -... the __add() macro also needs to use a "q" constraint in the -byte-sized case, lest we try to generate an illegal register. - -Link: http://lkml.kernel.org/r/4F7A3315.501@goop.org -Signed-off-by: H. Peter Anvin -Cc: Jeremy Fitzhardinge -Cc: Leigh Scott -Cc: Thomas Reitmayr -Cc: v3.3 ---- - -diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h -index bc18d0e..99480e5 100644 ---- a/arch/x86/include/asm/cmpxchg.h -+++ b/arch/x86/include/asm/cmpxchg.h -@@ -173,7 +173,7 @@ extern void __add_wrong_size(void) - switch (sizeof(*(ptr))) { \ - case __X86_CASE_B: \ - asm volatile (lock "addb %b1, %0\n" \ -- : "+m" (*(ptr)) : "ri" (inc) \ -+ : "+m" (*(ptr)) : "qi" (inc) \ - : "memory", "cc"); \ - break; \ - case __X86_CASE_W: \ diff --git a/x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch b/x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch deleted file mode 100644 index a33602f9f..000000000 --- a/x86-Use-correct-byte-sized-register-constraint-in-__xchg_op.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: Jeremy Fitzhardinge -Date: Mon, 2 Apr 2012 23:15:33 +0000 (-0700) -Subject: x86: Use correct byte-sized register constraint in __xchg_op() -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftip%2Ftip.git;a=commitdiff_plain;h=2ca052a3710fac208eee690faefdeb8bbd4586a1 - -x86: Use correct byte-sized register constraint in __xchg_op() - -x86-64 can access the low half of any register, but i386 can only do -it with a subset of registers. 'r' causes compilation failures on i386, -but 'q' expresses the constraint properly. - -Signed-off-by: Jeremy Fitzhardinge -Link: http://lkml.kernel.org/r/4F7A3315.501@goop.org -Reported-by: Leigh Scott -Tested-by: Thomas Reitmayr -Signed-off-by: H. Peter Anvin -Cc: v3.3 ---- - -diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h -index b3b7332..bc18d0e 100644 ---- a/arch/x86/include/asm/cmpxchg.h -+++ b/arch/x86/include/asm/cmpxchg.h -@@ -43,7 +43,7 @@ extern void __add_wrong_size(void) - switch (sizeof(*(ptr))) { \ - case __X86_CASE_B: \ - asm volatile (lock #op "b %b0, %1\n" \ -- : "+r" (__ret), "+m" (*(ptr)) \ -+ : "+q" (__ret), "+m" (*(ptr)) \ - : : "memory", "cc"); \ - break; \ - case __X86_CASE_W: \ From 5fa38a71388feadfc75df6857dce880b08aa7c8a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 23 Apr 2012 16:50:35 +1000 Subject: [PATCH 364/487] Fix regression on clickpads --- ...gression-with-image-sensor-trackpads.patch | 38 +++++++++++++++++++ kernel.spec | 9 ++++- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 input-synaptics-fix-regression-with-image-sensor-trackpads.patch diff --git a/input-synaptics-fix-regression-with-image-sensor-trackpads.patch b/input-synaptics-fix-regression-with-image-sensor-trackpads.patch new file mode 100644 index 000000000..6c1542b7c --- /dev/null +++ b/input-synaptics-fix-regression-with-image-sensor-trackpads.patch @@ -0,0 +1,38 @@ +From 899c612d74d4a242158a4db20367388d6299c028 Mon Sep 17 00:00:00 2001 +From: Benjamin Herrenschmidt +Date: Fri, 20 Apr 2012 22:34:49 -0700 +Subject: [PATCH] Input: synaptics - fix regression with "image sensor" + trackpads + +commit 7968a5dd492ccc38345013e534ad4c8d6eb60ed1 +Input: synaptics - add support for Relative mode + +Accidentally broke support for advanced gestures (multitouch) +on some trackpads such as the one in my ThinkPad X220 by +incorretly changing the condition for enabling them. This +restores it. + +Signed-off-by: Benjamin Herrenschmidt +CC: stable@kernel.org [3.3] +Signed-off-by: Dmitry Torokhov +--- + drivers/input/mouse/synaptics.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c +index 8081a0a..a4b14a4 100644 +--- a/drivers/input/mouse/synaptics.c ++++ b/drivers/input/mouse/synaptics.c +@@ -274,7 +274,8 @@ static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse) + static unsigned char param = 0xc8; + struct synaptics_data *priv = psmouse->private; + +- if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) ++ if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || ++ SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c))) + return 0; + + if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL)) +-- +1.7.10 + diff --git a/kernel.spec b/kernel.spec index 39cc9af02..5511e671e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -808,6 +808,8 @@ Patch22007: macvtap-zerocopy-validate-vector-length.patch #rhbz 811225 Patch22010: memblock-memblock-should-be-able-to-handle-zero-leng.patch +Patch22011: input-synaptics-fix-regression-with-image-sensor-trackpads.patch + # END OF PATCH DEFINITIONS %endif @@ -1507,6 +1509,8 @@ ApplyPatch macvtap-zerocopy-validate-vector-length.patch #rhbz 811225 ApplyPatch memblock-memblock-should-be-able-to-handle-zero-leng.patch +ApplyPatch input-synaptics-fix-regression-with-image-sensor-trackpads.patch + # END OF PATCH APPLICATIONS %endif @@ -2245,6 +2249,9 @@ fi # and build. %changelog +* Mon Apr 23 2012 Peter Hutterer +- Fix regression on clickpads + * Mon Apr 23 2012 Josh Boyer - Linux 3.3.3 From ebeee9684c467cc35e9be363532e4810ea6e4ba6 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 24 Apr 2012 08:47:28 -0400 Subject: [PATCH 365/487] Add patch to fix ipw2200 (rhbz 783708) --- ...n-the-command-completion-acknowledge.patch | 69 +++++++++++++++++++ kernel.spec | 11 ++- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch diff --git a/ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch b/ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch new file mode 100644 index 000000000..3b7451f9f --- /dev/null +++ b/ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch @@ -0,0 +1,69 @@ +Driver incorrectly validates command completion: instead of waiting +for a command to be acknowledged it continues execution. Most of the +time driver gets acknowledge of the command completion in a tasklet +before it executes the next one. But sometimes it sends the next +command before it gets acknowledge for the previous one. In such a +case one of the following error messages appear in the log: + +Failed to send SYSTEM_CONFIG: Already sending a command. +Failed to send ASSOCIATE: Already sending a command. +Failed to send TX_POWER: Already sending a command. + +After that you need to reload the driver to get it working again. + +This bug occurs during roammaping (reported by Sam Varshavchik) +https://bugzilla.redhat.com/show_bug.cgi?id=738508 +and machine booting (reported by Tom Gundersen and Mads Kiilerich) +https://bugs.archlinux.org/task/28097 +https://bugzilla.redhat.com/show_bug.cgi?id=802106 + +This patch doesn't fix the delay issue during firmware load. +But at least device now works as usual after boot. + +Cc: stable@kernel.org +Signed-off-by: Stanislav Yakovlev +--- + drivers/net/wireless/ipw2x00/ipw2200.c | 13 ++++++++++++- + 1 files changed, 12 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c +index 4130802..8cbafa5 100644 +--- a/drivers/net/wireless/ipw2x00/ipw2200.c ++++ b/drivers/net/wireless/ipw2x00/ipw2200.c +@@ -2192,6 +2192,7 @@ static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) + { + int rc = 0; + unsigned long flags; ++ unsigned long now, end; + + spin_lock_irqsave(&priv->lock, flags); + if (priv->status & STATUS_HCMD_ACTIVE) { +@@ -2233,10 +2234,20 @@ static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) + } + spin_unlock_irqrestore(&priv->lock, flags); + ++ now = jiffies; ++ end = now + HOST_COMPLETE_TIMEOUT; ++again: + rc = wait_event_interruptible_timeout(priv->wait_command_queue, + !(priv-> + status & STATUS_HCMD_ACTIVE), +- HOST_COMPLETE_TIMEOUT); ++ end - now); ++ if (rc < 0) { ++ now = jiffies; ++ if (time_before(now, end)) ++ goto again; ++ rc = 0; ++ } ++ + if (rc == 0) { + spin_lock_irqsave(&priv->lock, flags); + if (priv->status & STATUS_HCMD_ACTIVE) { +-- +1.7.2.5 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index 5511e671e..c61836132 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -810,6 +810,9 @@ Patch22010: memblock-memblock-should-be-able-to-handle-zero-leng.patch Patch22011: input-synaptics-fix-regression-with-image-sensor-trackpads.patch +#rhbz 783708 +Patch22012: ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch + # END OF PATCH DEFINITIONS %endif @@ -1511,6 +1514,9 @@ ApplyPatch memblock-memblock-should-be-able-to-handle-zero-leng.patch ApplyPatch input-synaptics-fix-regression-with-image-sensor-trackpads.patch +#rhbz 783708 +ApplyPatch ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch + # END OF PATCH APPLICATIONS %endif @@ -2249,6 +2255,9 @@ fi # and build. %changelog +* Tue Apr 24 2012 Josh Boyer +- Add patch to fix ipw2200 (rhbz 783708) + * Mon Apr 23 2012 Peter Hutterer - Fix regression on clickpads From 14ad4ec584608e98ee4cab91bc316e0a407ca016 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 24 Apr 2012 09:46:24 -0400 Subject: [PATCH 366/487] Add patch to fix perf build due to incorrect cherry-pick in 3.3.3 --- kernel.spec | 5 ++++ perf-fix-build-breakage.patch | 54 +++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 perf-fix-build-breakage.patch diff --git a/kernel.spec b/kernel.spec index c61836132..822e82fed 100644 --- a/kernel.spec +++ b/kernel.spec @@ -813,6 +813,8 @@ Patch22011: input-synaptics-fix-regression-with-image-sensor-trackpads.patch #rhbz 783708 Patch22012: ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch +Patch22013: perf-fix-build-breakage.patch + # END OF PATCH DEFINITIONS %endif @@ -1517,6 +1519,8 @@ ApplyPatch input-synaptics-fix-regression-with-image-sensor-trackpads.patch #rhbz 783708 ApplyPatch ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch +ApplyPatch perf-fix-build-breakage.patch + # END OF PATCH APPLICATIONS %endif @@ -2256,6 +2260,7 @@ fi %changelog * Tue Apr 24 2012 Josh Boyer +- Add patch to fix perf build due to incorrect cherry-pick in 3.3.3 - Add patch to fix ipw2200 (rhbz 783708) * Mon Apr 23 2012 Peter Hutterer diff --git a/perf-fix-build-breakage.patch b/perf-fix-build-breakage.patch new file mode 100644 index 000000000..d1385ddce --- /dev/null +++ b/perf-fix-build-breakage.patch @@ -0,0 +1,54 @@ +From zeev.tarantov@gmail.com Sun Apr 22 23:38:36 2012 +From: Zeev Tarantov +Date: Mon, 23 Apr 2012 09:37:04 +0300 +Subject: Perf: fix build breakage +To: "David S. Miller" , Arnaldo Carvalho de Melo , Greg Kroah-Hartman , Linux Kernel Mailing List +Message-ID: <20120423063704.GA3465@myhost> +Content-Disposition: inline + + +From: Zeev Tarantov + +[Patch not needed upstream as this is a backport build bugfix - gregkh + +gcc correctly complains: + +util/hist.c: In function ‘__hists__add_entry’: +util/hist.c:240:27: error: invalid type argument of ‘->’ (have ‘struct hist_entry’) +util/hist.c:241:23: error: invalid type argument of ‘->’ (have ‘struct hist_entry’) + +for this new code: + ++ if (he->ms.map != entry->ms.map) { ++ he->ms.map = entry->ms.map; ++ if (he->ms.map) ++ he->ms.map->referenced = true; ++ } + +because "entry" is a "struct hist_entry", not a pointer to a struct. + +In mainline, "entry" is a pointer to struct passed as argument to the function. +So this is broken during backporting. But obviously not compile tested. + +Signed-off-by: Zeev Tarantov +Cc: Signed-off-by: David S. Miller +Cc: Arnaldo Carvalho de Melo +Signed-off-by: Greg Kroah-Hartman + +--- + tools/perf/util/hist.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/tools/perf/util/hist.c ++++ b/tools/perf/util/hist.c +@@ -237,8 +237,8 @@ struct hist_entry *__hists__add_entry(st + * mis-adjust symbol addresses when computing + * the history counter to increment. + */ +- if (he->ms.map != entry->ms.map) { +- he->ms.map = entry->ms.map; ++ if (he->ms.map != entry.ms.map) { ++ he->ms.map = entry.ms.map; + if (he->ms.map) + he->ms.map->referenced = true; + } From 573d368770cc88ccc2d8f5592d3573c4889583e0 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 27 Apr 2012 14:40:30 -0500 Subject: [PATCH 367/487] Linux 3.3.4 --- ...rom-the-iommu-when-slots-are-removed.patch | 92 ------------------- dvb_frontend_switch_regression_fix.patch | 65 ------------- kernel.spec | 31 +------ ...k-should-be-able-to-handle-zero-leng.patch | 63 ------------- perf-fix-build-breakage.patch | 54 ----------- sources | 2 +- ...vent-a-possible-kernel-bug-due-to-mi.patch | 34 ------- 7 files changed, 6 insertions(+), 335 deletions(-) delete mode 100644 KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch delete mode 100644 dvb_frontend_switch_regression_fix.patch delete mode 100644 memblock-memblock-should-be-able-to-handle-zero-leng.patch delete mode 100644 perf-fix-build-breakage.patch delete mode 100644 wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch diff --git a/KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch b/KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch deleted file mode 100644 index b98e392f7..000000000 --- a/KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch +++ /dev/null @@ -1,92 +0,0 @@ -commit 32f6daad4651a748a58a3ab6da0611862175722f -Author: Alex Williamson -Date: Wed Apr 11 09:51:49 2012 -0600 - - KVM: unmap pages from the iommu when slots are removed - - We've been adding new mappings, but not destroying old mappings. - This can lead to a page leak as pages are pinned using - get_user_pages, but only unpinned with put_page if they still - exist in the memslots list on vm shutdown. A memslot that is - destroyed while an iommu domain is enabled for the guest will - therefore result in an elevated page reference count that is - never cleared. - - Additionally, without this fix, the iommu is only programmed - with the first translation for a gpa. This can result in - peer-to-peer errors if a mapping is destroyed and replaced by a - new mapping at the same gpa as the iommu will still be pointing - to the original, pinned memory address. - - Signed-off-by: Alex Williamson - Signed-off-by: Marcelo Tosatti - -diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h -index 665a260..72cbf08 100644 ---- a/include/linux/kvm_host.h -+++ b/include/linux/kvm_host.h -@@ -596,6 +596,7 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id); - - #ifdef CONFIG_IOMMU_API - int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot); -+void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot); - int kvm_iommu_map_guest(struct kvm *kvm); - int kvm_iommu_unmap_guest(struct kvm *kvm); - int kvm_assign_device(struct kvm *kvm, -@@ -609,6 +610,11 @@ static inline int kvm_iommu_map_pages(struct kvm *kvm, - return 0; - } - -+static inline void kvm_iommu_unmap_pages(struct kvm *kvm, -+ struct kvm_memory_slot *slot) -+{ -+} -+ - static inline int kvm_iommu_map_guest(struct kvm *kvm) - { - return -ENODEV; -diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c -index a457d21..fec1723 100644 ---- a/virt/kvm/iommu.c -+++ b/virt/kvm/iommu.c -@@ -310,6 +310,11 @@ static void kvm_iommu_put_pages(struct kvm *kvm, - } - } - -+void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot) -+{ -+ kvm_iommu_put_pages(kvm, slot->base_gfn, slot->npages); -+} -+ - static int kvm_iommu_unmap_memslots(struct kvm *kvm) - { - int idx; -@@ -320,7 +325,7 @@ static int kvm_iommu_unmap_memslots(struct kvm *kvm) - slots = kvm_memslots(kvm); - - kvm_for_each_memslot(memslot, slots) -- kvm_iommu_put_pages(kvm, memslot->base_gfn, memslot->npages); -+ kvm_iommu_unmap_pages(kvm, memslot); - - srcu_read_unlock(&kvm->srcu, idx); - -diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c -index 42b7393..9739b53 100644 ---- a/virt/kvm/kvm_main.c -+++ b/virt/kvm/kvm_main.c -@@ -808,12 +808,13 @@ int __kvm_set_memory_region(struct kvm *kvm, - if (r) - goto out_free; - -- /* map the pages in iommu page table */ -+ /* map/unmap the pages in iommu page table */ - if (npages) { - r = kvm_iommu_map_pages(kvm, &new); - if (r) - goto out_free; -- } -+ } else -+ kvm_iommu_unmap_pages(kvm, &old); - - r = -ENOMEM; - slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots), diff --git a/dvb_frontend_switch_regression_fix.patch b/dvb_frontend_switch_regression_fix.patch deleted file mode 100644 index f5c701017..000000000 --- a/dvb_frontend_switch_regression_fix.patch +++ /dev/null @@ -1,65 +0,0 @@ -From c6c6fa8dcc27aad6ce3467544be0f57fd82b99a3 Mon Sep 17 00:00:00 2001 -From: Mauro Carvalho Chehab -Date: Tue, 17 Apr 2012 18:32:19 -0300 -Subject: [PATCH] [media] dvb_frontend: Fix a regression when switching back - to DVB-S - -There are some softwares (Kaffeine and likely xine) that uses a -DVBv5 call to switch to DVB-S2, but expects that a DVBv3 call to -switch back to DVB-S. Well, this is not right, as a DVBv3 call -doesn't know anything about delivery systems. - -However, as, by accident, this used to work, we need to restore its -behavior, in order to avoid regressions with those softwares. - -Reported on this Fedora 16 bugzilla: - https://bugzilla.redhat.com/show_bug.cgi?id=812895 - -Reported-by: Dieter Roever -Signed-off-by: Mauro Carvalho Chehab - -diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c -index 4555baa..bb582fd 100644 ---- a/drivers/media/dvb/dvb-core/dvb_frontend.c -+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c -@@ -1443,6 +1443,28 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) - __func__); - return -EINVAL; - } -+ /* -+ * Get a delivery system that is compatible with DVBv3 -+ * NOTE: in order for this to work with softwares like Kaffeine that -+ * uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to -+ * DVB-S, drivers that support both should put the SYS_DVBS entry -+ * before the SYS_DVBS2, otherwise it won't switch back to DVB-S. -+ * The real fix is that userspace applications should not use DVBv3 -+ * and not trust on calling FE_SET_FRONTEND to switch the delivery -+ * system. -+ */ -+ ncaps = 0; -+ while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { -+ if (fe->ops.delsys[ncaps] == desired_system) { -+ delsys = desired_system; -+ break; -+ } -+ ncaps++; -+ } -+ if (delsys == SYS_UNDEFINED) { -+ dprintk("%s() Couldn't find a delivery system that matches %d\n", -+ __func__, desired_system); -+ } - } else { - /* - * This is a DVBv5 call. So, it likely knows the supported -@@ -1491,9 +1513,10 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) - __func__); - return -EINVAL; - } -- c->delivery_system = delsys; - } - -+ c->delivery_system = delsys; -+ - /* - * The DVBv3 or DVBv5 call is requesting a different system. So, - * emulation is needed. diff --git a/kernel.spec b/kernel.spec index 822e82fed..18c030aae 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 3 +%define stable_update 4 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -710,7 +710,6 @@ Patch2802: linux-2.6-silence-acpi-blacklist.patch # add-poll-requested-events.patch was added for 3.4 Patch2900: add-poll-requested-events.patch Patch2901: drivers-media-update.patch -Patch2902: dvb_frontend_switch_regression_fix.patch # fs fixes @@ -777,9 +776,6 @@ Patch21353: xen-x86-Implement-x86_apic_ops.patch #rhbz 770476 Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch -#rhbz 808603 -Patch21380: wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch - #rhbz 807632 Patch21385: libata-forbid-port-runtime-pm-by-default.patch @@ -799,22 +795,14 @@ Patch21710: disable-hid-battery.patch Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch -#rhbz 814149 814155 CVE-2012-2121 -Patch22006: KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch - #rhbz 814278 814289 CVE-2012-2119 Patch22007: macvtap-zerocopy-validate-vector-length.patch -#rhbz 811225 -Patch22010: memblock-memblock-should-be-able-to-handle-zero-leng.patch - Patch22011: input-synaptics-fix-regression-with-image-sensor-trackpads.patch #rhbz 783708 Patch22012: ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch -Patch22013: perf-fix-build-breakage.patch - # END OF PATCH DEFINITIONS %endif @@ -1432,7 +1420,6 @@ ApplyPatch quite-apm.patch # apply if non-empty ApplyPatch add-poll-requested-events.patch ApplyOptionalPatch drivers-media-update.patch -ApplyPatch dvb_frontend_switch_regression_fix.patch # Patches headed upstream @@ -1492,9 +1479,6 @@ ApplyPatch iwlwifi-do-not-nulify-ctx-vif-on-reset.patch #rhbz 808207 CVE-2012-1601 ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch -#rhbz 808603 -ApplyPatch wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch - #rhbz 807632 ApplyPatch libata-forbid-port-runtime-pm-by-default.patch @@ -1505,22 +1489,14 @@ ApplyPatch x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPU #rhbz 806295 ApplyPatch disable-hid-battery.patch -#rhbz 814149 814155 CVE-2012-2121 -ApplyPatch KVM-unmap-pages-from-the-iommu-when-slots-are-removed.patch - #rhbz 814278 814289 CVE-2012-2119 ApplyPatch macvtap-zerocopy-validate-vector-length.patch -#rhbz 811225 -ApplyPatch memblock-memblock-should-be-able-to-handle-zero-leng.patch - ApplyPatch input-synaptics-fix-regression-with-image-sensor-trackpads.patch #rhbz 783708 ApplyPatch ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch -ApplyPatch perf-fix-build-breakage.patch - # END OF PATCH APPLICATIONS %endif @@ -2259,6 +2235,9 @@ fi # and build. %changelog +* Fri Apr 27 2012 Justin M. Forbes 3.3.4-1 +- Linux 3.3.4 + * Tue Apr 24 2012 Josh Boyer - Add patch to fix perf build due to incorrect cherry-pick in 3.3.3 - Add patch to fix ipw2200 (rhbz 783708) diff --git a/memblock-memblock-should-be-able-to-handle-zero-leng.patch b/memblock-memblock-should-be-able-to-handle-zero-leng.patch deleted file mode 100644 index 08e364534..000000000 --- a/memblock-memblock-should-be-able-to-handle-zero-leng.patch +++ /dev/null @@ -1,63 +0,0 @@ -From b3dc627cabb33fc95f93da78457770c1b2a364d2 Mon Sep 17 00:00:00 2001 -From: Tejun Heo -Date: Fri, 20 Apr 2012 08:31:34 -0700 -Subject: [PATCH] memblock: memblock should be able to handle zero length - operations - -Commit 24aa07882b ("memblock, x86: Replace memblock_x86_reserve/ -free_range() with generic ones") replaced x86 specific memblock -operations with the generic ones; unfortunately, it lost zero length -operation handling in the process making the kernel panic if somebody -tries to reserve zero length area. - -There isn't much to be gained by being cranky to zero length operations -and panicking is almost the worst response. Drop the BUG_ON() in -memblock_reserve() and update memblock_add_region/isolate_range() so -that all zero length operations are handled as noops. - -Signed-off-by: Tejun Heo -Cc: stable@vger.kernel.org -Reported-by: Valere Monseur -Bisected-by: Joseph Freeman -Tested-by: Joseph Freeman -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=43098 -Signed-off-by: Linus Torvalds ---- - mm/memblock.c | 7 ++++++- - 1 files changed, 6 insertions(+), 1 deletions(-) - -diff --git a/mm/memblock.c b/mm/memblock.c -index 99f2855..a44eab3 100644 ---- a/mm/memblock.c -+++ b/mm/memblock.c -@@ -330,6 +330,9 @@ static int __init_memblock memblock_add_region(struct memblock_type *type, - phys_addr_t end = base + memblock_cap_size(base, &size); - int i, nr_new; - -+ if (!size) -+ return 0; -+ - /* special case for empty array */ - if (type->regions[0].size == 0) { - WARN_ON(type->cnt != 1 || type->total_size); -@@ -430,6 +433,9 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, - - *start_rgn = *end_rgn = 0; - -+ if (!size) -+ return 0; -+ - /* we'll create at most two more regions */ - while (type->cnt + 2 > type->max) - if (memblock_double_array(type) < 0) -@@ -514,7 +520,6 @@ int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size) - (unsigned long long)base, - (unsigned long long)base + size, - (void *)_RET_IP_); -- BUG_ON(0 == size); - - return memblock_add_region(_rgn, base, size, MAX_NUMNODES); - } --- -1.7.7.6 - diff --git a/perf-fix-build-breakage.patch b/perf-fix-build-breakage.patch deleted file mode 100644 index d1385ddce..000000000 --- a/perf-fix-build-breakage.patch +++ /dev/null @@ -1,54 +0,0 @@ -From zeev.tarantov@gmail.com Sun Apr 22 23:38:36 2012 -From: Zeev Tarantov -Date: Mon, 23 Apr 2012 09:37:04 +0300 -Subject: Perf: fix build breakage -To: "David S. Miller" , Arnaldo Carvalho de Melo , Greg Kroah-Hartman , Linux Kernel Mailing List -Message-ID: <20120423063704.GA3465@myhost> -Content-Disposition: inline - - -From: Zeev Tarantov - -[Patch not needed upstream as this is a backport build bugfix - gregkh - -gcc correctly complains: - -util/hist.c: In function ‘__hists__add_entry’: -util/hist.c:240:27: error: invalid type argument of ‘->’ (have ‘struct hist_entry’) -util/hist.c:241:23: error: invalid type argument of ‘->’ (have ‘struct hist_entry’) - -for this new code: - -+ if (he->ms.map != entry->ms.map) { -+ he->ms.map = entry->ms.map; -+ if (he->ms.map) -+ he->ms.map->referenced = true; -+ } - -because "entry" is a "struct hist_entry", not a pointer to a struct. - -In mainline, "entry" is a pointer to struct passed as argument to the function. -So this is broken during backporting. But obviously not compile tested. - -Signed-off-by: Zeev Tarantov -Cc: Signed-off-by: David S. Miller -Cc: Arnaldo Carvalho de Melo -Signed-off-by: Greg Kroah-Hartman - ---- - tools/perf/util/hist.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/tools/perf/util/hist.c -+++ b/tools/perf/util/hist.c -@@ -237,8 +237,8 @@ struct hist_entry *__hists__add_entry(st - * mis-adjust symbol addresses when computing - * the history counter to increment. - */ -- if (he->ms.map != entry->ms.map) { -- he->ms.map = entry->ms.map; -+ if (he->ms.map != entry.ms.map) { -+ he->ms.map = entry.ms.map; - if (he->ms.map) - he->ms.map->referenced = true; - } diff --git a/sources b/sources index d1990b3af..1918a7281 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz -634a088d3789870885dc6ee1eb9627d4 patch-3.3.3.xz +9c4cc16f10b645fbb90f6c05ad388883 patch-3.3.4.xz diff --git a/wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch b/wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch deleted file mode 100644 index 92b2e9970..000000000 --- a/wimax-i2400m-prevent-a-possible-kernel-bug-due-to-mi.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 4eee6a3a04e8bb53fbe7de0f64d0524d3fbe3f80 Mon Sep 17 00:00:00 2001 -From: Phil Sutter -Date: Mon, 26 Mar 2012 09:01:30 +0000 -Subject: [PATCH] wimax: i2400m - prevent a possible kernel bug due to missing - fw_name string - -This happened on a machine with a custom hotplug script calling nameif, -probably due to slow firmware loading. At the time nameif uses ethtool -to gather interface information, i2400m->fw_name is zero and so a null -pointer dereference occurs from within i2400m_get_drvinfo(). - -Signed-off-by: Phil Sutter -Signed-off-by: David S. Miller ---- - drivers/net/wimax/i2400m/netdev.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c -index 63e4b70..1d76ae8 100644 ---- a/drivers/net/wimax/i2400m/netdev.c -+++ b/drivers/net/wimax/i2400m/netdev.c -@@ -597,7 +597,8 @@ static void i2400m_get_drvinfo(struct net_device *net_dev, - struct i2400m *i2400m = net_dev_to_i2400m(net_dev); - - strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver) - 1); -- strncpy(info->fw_version, i2400m->fw_name, sizeof(info->fw_version) - 1); -+ strncpy(info->fw_version, -+ i2400m->fw_name ? : "", sizeof(info->fw_version) - 1); - if (net_dev->dev.parent) - strncpy(info->bus_info, dev_name(net_dev->dev.parent), - sizeof(info->bus_info) - 1); --- -1.7.7.6 - From cebff535ca3de718d841c2b1a807b765021e176c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 30 Apr 2012 12:17:08 -0400 Subject: [PATCH 368/487] Disable CONFIG_RCU_FAST_NO_HZ for now. (rhbz 806548) --- config-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 681fc3056..89c64fff6 100644 --- a/config-generic +++ b/config-generic @@ -4561,7 +4561,7 @@ CONFIG_LSM_MMAP_MIN_ADDR=65536 CONFIG_STRIP_ASM_SYMS=y # CONFIG_RCU_FANOUT_EXACT is not set -CONFIG_RCU_FAST_NO_HZ=y +# CONFIG_RCU_FAST_NO_HZ is not set CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_TRACE is not set diff --git a/kernel.spec b/kernel.spec index 18c030aae..96ed95a40 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2235,6 +2235,9 @@ fi # and build. %changelog +* Mon Apr 30 2012 Dave Jones +- Disable CONFIG_RCU_FAST_NO_HZ for now. (rhbz 806548) + * Fri Apr 27 2012 Justin M. Forbes 3.3.4-1 - Linux 3.3.4 From aef7a0c111bd691ef13240ee6f7285268a6398ef Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 30 Apr 2012 15:23:12 -0400 Subject: [PATCH 369/487] Backport ipw2x00 nl80211 cipher suite reporting (rhbz 817298) --- ...ipher-suites-to-wiphy-initialization.patch | 155 ++++++++++++++++++ kernel.spec | 11 +- 2 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch diff --git a/ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch b/ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch new file mode 100644 index 000000000..705c5eff0 --- /dev/null +++ b/ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch @@ -0,0 +1,155 @@ +Path: news.gmane.org!not-for-mail +From: Stanislav Yakovlev +Newsgroups: gmane.linux.kernel.wireless.general +Subject: [PATCH] net/wireless: ipw2x00: add supported cipher suites to wiphy initialization +Date: Tue, 10 Apr 2012 21:44:47 -0400 +Lines: 97 +Approved: news@gmane.org +Message-ID: <1334108687-12954-1-git-send-email-stas.yakovlev@gmail.com> +NNTP-Posting-Host: plane.gmane.org +X-Trace: dough.gmane.org 1334108469 22291 80.91.229.3 (11 Apr 2012 01:41:09 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Wed, 11 Apr 2012 01:41:09 +0000 (UTC) +Cc: simar-hi6Y0CQ0nG0@public.gmane.org, linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, + Stanislav Yakovlev +To: linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org +Original-X-From: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Wed Apr 11 03:41:07 2012 +Return-path: +Envelope-to: glkwg-linux-wireless-wOFGN7rlS/M9smdsby/KFg@public.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1SHmYV-0004IK-CT + for glkwg-linux-wireless-wOFGN7rlS/M9smdsby/KFg@public.gmane.org; Wed, 11 Apr 2012 03:41:07 +0200 +Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand + id S1759898Ab2DKBlF (ORCPT + ); + Tue, 10 Apr 2012 21:41:05 -0400 +Original-Received: from mail-ob0-f174.google.com ([209.85.214.174]:60108 "EHLO + mail-ob0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1753779Ab2DKBlE (ORCPT + ); + Tue, 10 Apr 2012 21:41:04 -0400 +Original-Received: by obbtb18 with SMTP id tb18so567970obb.19 + for ; Tue, 10 Apr 2012 18:41:02 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20120113; + h=from:to:cc:subject:date:message-id:x-mailer; + bh=8+D+Uuo0bIOG6rz8vxd6TGAxmrbuAw2bjWhd058IjOQ=; + b=beOgy1Y9ZAV1Xw5XqsnPDJ1Oc0qOpOo+gCWlwmWbLdVHxUVG+ZVuRW9eCRQkh+5bZm + 5Ic+xOISztYUJp144Fr4flnbGPRKKp7jP8qQ/HvCOo34J6MCgBlnuWNYKbn4/NUvOYAh + SeHpk2D8yOHbiWAMV+JGTqGG+/N4jVvRL147Yg1IfNDAJd8Ahbl0wARLOVg8WGGTSPvn + MU3HNbmKFFBDhnukYr4keCnjixuDkqPYGMYuDrsmKdiAFHBRDI6qudnvaqi8F8gbtaWg + dfssdTbmNYM/R/PJenInoy7IbRps2iW9ZX+zFzydZWp2EyJ4EZkKrYKmnezQgNJzRVex + KHfg== +Original-Received: by 10.60.24.9 with SMTP id q9mr19071024oef.4.1334108462648; + Tue, 10 Apr 2012 18:41:02 -0700 (PDT) +Original-Received: from localhost.localdomain (50-0-191-227.dsl.static.sonic.net. [50.0.191.227]) + by mx.google.com with ESMTPS id tx2sm1309336obb.8.2012.04.10.18.40.54 + (version=TLSv1/SSLv3 cipher=OTHER); + Tue, 10 Apr 2012 18:41:01 -0700 (PDT) +X-Mailer: git-send-email 1.7.2.5 +Original-Sender: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Xref: news.gmane.org gmane.linux.kernel.wireless.general:88613 +Archived-At: + +Driver doesn't report its supported cipher suites through cfg80211 +interface. It still uses wext interface and probably will not work +through nl80211, but will at least correctly advertise supported +features. + +Bug was reported by Omar Siam. +https://bugzilla.kernel.org/show_bug.cgi?id=43049 + +Signed-off-by: Stanislav Yakovlev +--- + drivers/net/wireless/ipw2x00/ipw.h | 23 +++++++++++++++++++++++ + drivers/net/wireless/ipw2x00/ipw2100.c | 4 ++++ + drivers/net/wireless/ipw2x00/ipw2200.c | 4 ++++ + 3 files changed, 31 insertions(+), 0 deletions(-) + create mode 100644 drivers/net/wireless/ipw2x00/ipw.h + +diff --git a/drivers/net/wireless/ipw2x00/ipw.h b/drivers/net/wireless/ipw2x00/ipw.h +new file mode 100644 +index 0000000..4007bf5 +--- /dev/null ++++ b/drivers/net/wireless/ipw2x00/ipw.h +@@ -0,0 +1,23 @@ ++/* ++ * Intel Pro/Wireless 2100, 2200BG, 2915ABG network connection driver ++ * ++ * Copyright 2012 Stanislav Yakovlev ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef __IPW_H__ ++#define __IPW_H__ ++ ++#include ++ ++static const u32 ipw_cipher_suites[] = { ++ WLAN_CIPHER_SUITE_WEP40, ++ WLAN_CIPHER_SUITE_WEP104, ++ WLAN_CIPHER_SUITE_TKIP, ++ WLAN_CIPHER_SUITE_CCMP, ++}; ++ ++#endif +diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c +index f0551f8..7c8e8b1 100644 +--- a/drivers/net/wireless/ipw2x00/ipw2100.c ++++ b/drivers/net/wireless/ipw2x00/ipw2100.c +@@ -166,6 +166,7 @@ that only one external action is invoked at a time. + #include + + #include "ipw2100.h" ++#include "ipw.h" + + #define IPW2100_VERSION "git-1.2.2" + +@@ -1946,6 +1947,9 @@ static int ipw2100_wdev_init(struct net_device *dev) + wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band; + } + ++ wdev->wiphy->cipher_suites = ipw_cipher_suites; ++ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites); ++ + set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); + if (wiphy_register(wdev->wiphy)) { + ipw2100_down(priv); +diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c +index 2b02257..bb4f42a 100644 +--- a/drivers/net/wireless/ipw2x00/ipw2200.c ++++ b/drivers/net/wireless/ipw2x00/ipw2200.c +@@ -34,6 +34,7 @@ + #include + #include + #include "ipw2200.h" ++#include "ipw.h" + + + #ifndef KBUILD_EXTMOD +@@ -11533,6 +11534,9 @@ static int ipw_wdev_init(struct net_device *dev) + wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = a_band; + } + ++ wdev->wiphy->cipher_suites = ipw_cipher_suites; ++ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites); ++ + set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); + + /* With that information in place, we can now register the wiphy... */ +-- +1.7.2.5 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + diff --git a/kernel.spec b/kernel.spec index 96ed95a40..caece7e57 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -803,6 +803,9 @@ Patch22011: input-synaptics-fix-regression-with-image-sensor-trackpads.patch #rhbz 783708 Patch22012: ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch +#rhbz 817298 +Patch22013: ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch + # END OF PATCH DEFINITIONS %endif @@ -1497,6 +1500,9 @@ ApplyPatch input-synaptics-fix-regression-with-image-sensor-trackpads.patch #rhbz 783708 ApplyPatch ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch +#rhbz 817298 +ApplyPatch ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch + # END OF PATCH APPLICATIONS %endif @@ -2235,6 +2241,9 @@ fi # and build. %changelog +* Mon Apr 30 2012 Josh Boyer +- Backport ipw2x00 nl80211 cipher suite reporting (rhbz 817298) + * Mon Apr 30 2012 Dave Jones - Disable CONFIG_RCU_FAST_NO_HZ for now. (rhbz 806548) From 28303e222e5d093eca6ad4c20966071ac1813d11 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 3 May 2012 08:12:57 -0500 Subject: [PATCH 370/487] Many patches from 3.3.5 stable queue --- ...nnecessary-setattrs-for-open-O_TRUNC.patch | 153 + ...O_TRUNC-and-ftruncate-error-handling.patch | 69 + ...gression-with-image-sensor-trackpads.patch | 38 - kernel.spec | 31 +- stable-queue-3.3.5-0502.patch | 2804 +++++++++++++++++ ...s-only-loaded-for-supported-AMD-CPUs.patch | 163 - ...ng-module-unload-on-unsupported-CPUs.patch | 167 - 7 files changed, 3045 insertions(+), 380 deletions(-) create mode 100644 NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch create mode 100644 NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch delete mode 100644 input-synaptics-fix-regression-with-image-sensor-trackpads.patch create mode 100644 stable-queue-3.3.5-0502.patch delete mode 100644 x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch delete mode 100644 x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch diff --git a/NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch b/NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch new file mode 100644 index 000000000..89b6308cd --- /dev/null +++ b/NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch @@ -0,0 +1,153 @@ +From: Trond Myklebust + +Currently, we will correctly optimise away a truncate that doesn't +change the file size. However, in the case of open(O_TRUNC), we +also want to optimise away the time changes. + +Signed-off-by: Trond Myklebust +--- + fs/nfs/dir.c | 25 +++++++++++++++++++------ + fs/nfs/inode.c | 4 ++-- + fs/nfs/nfs4proc.c | 10 +++++++--- + 3 files changed, 28 insertions(+), 11 deletions(-) + +diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c +index fd9a872..bb132a8 100644 +--- a/fs/nfs/dir.c ++++ b/fs/nfs/dir.c +@@ -1429,6 +1429,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry + } + + open_flags = nd->intent.open.flags; ++ attr.ia_valid = 0; + + ctx = create_nfs_open_context(dentry, open_flags); + res = ERR_CAST(ctx); +@@ -1437,11 +1438,14 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry + + if (nd->flags & LOOKUP_CREATE) { + attr.ia_mode = nd->intent.open.create_mode; +- attr.ia_valid = ATTR_MODE; ++ attr.ia_valid |= ATTR_MODE; + attr.ia_mode &= ~current_umask(); +- } else { ++ } else + open_flags &= ~(O_EXCL | O_CREAT); +- attr.ia_valid = 0; ++ ++ if (open_flags & O_TRUNC) { ++ attr.ia_valid |= ATTR_SIZE; ++ attr.ia_size = 0; + } + + /* Open the file on the server */ +@@ -1495,6 +1499,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) + struct inode *inode; + struct inode *dir; + struct nfs_open_context *ctx; ++ struct iattr attr; + int openflags, ret = 0; + + if (nd->flags & LOOKUP_RCU) +@@ -1523,19 +1528,27 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) + /* We cannot do exclusive creation on a positive dentry */ + if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) + goto no_open_dput; +- /* We can't create new files, or truncate existing ones here */ +- openflags &= ~(O_CREAT|O_EXCL|O_TRUNC); ++ /* We can't create new files here */ ++ openflags &= ~(O_CREAT|O_EXCL); + + ctx = create_nfs_open_context(dentry, openflags); + ret = PTR_ERR(ctx); + if (IS_ERR(ctx)) + goto out; ++ ++ attr.ia_valid = 0; ++ if (openflags & O_TRUNC) { ++ attr.ia_valid |= ATTR_SIZE; ++ attr.ia_size = 0; ++ nfs_wb_all(inode); ++ } ++ + /* + * Note: we're not holding inode->i_mutex and so may be racing with + * operations that change the directory. We therefore save the + * change attribute *before* we do the RPC call. + */ +- inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, NULL); ++ inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr); + if (IS_ERR(inode)) { + ret = PTR_ERR(inode); + switch (ret) { +diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c +index f649fba..57d0abb 100644 +--- a/fs/nfs/inode.c ++++ b/fs/nfs/inode.c +@@ -401,7 +401,7 @@ out_no_inode: + goto out; + } + +-#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE) ++#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE|ATTR_OPEN) + + int + nfs_setattr(struct dentry *dentry, struct iattr *attr) +@@ -423,7 +423,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) + + /* Optimization: if the end result is no change, don't RPC */ + attr->ia_valid &= NFS_VALID_ATTRS; +- if ((attr->ia_valid & ~ATTR_FILE) == 0) ++ if ((attr->ia_valid & ~(ATTR_FILE|ATTR_OPEN)) == 0) + return 0; + + /* Write all dirty data */ +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index 1515e45..c4c6b48 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -833,7 +833,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, + p->o_arg.bitmask = server->attr_bitmask; + p->o_arg.dir_bitmask = server->cache_consistency_bitmask; + p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; +- if (flags & O_CREAT) { ++ if (attrs != NULL && attrs->ia_valid != 0) { + u32 *s; + + p->o_arg.u.attrs = &p->attrs; +@@ -890,7 +890,7 @@ static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode + { + int ret = 0; + +- if (open_mode & O_EXCL) ++ if (open_mode & (O_EXCL|O_TRUNC)) + goto out; + switch (mode & (FMODE_READ|FMODE_WRITE)) { + case FMODE_READ: +@@ -1038,7 +1038,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) + struct nfs4_state *state = opendata->state; + struct nfs_inode *nfsi = NFS_I(state->inode); + struct nfs_delegation *delegation; +- int open_mode = opendata->o_arg.open_flags & O_EXCL; ++ int open_mode = opendata->o_arg.open_flags & (O_EXCL|O_TRUNC); + fmode_t fmode = opendata->o_arg.fmode; + nfs4_stateid stateid; + int ret = -EAGAIN; +@@ -2439,6 +2439,10 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, + } + } + ++ /* Deal with open(O_TRUNC) */ ++ if (sattr->ia_valid & ATTR_OPEN) ++ sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); ++ + status = nfs4_do_setattr(inode, cred, fattr, sattr, state); + if (status == 0) + nfs_setattr_update_inode(inode, sattr); +-- +1.7.7.6 + +_______________________________________________ +kernel mailing list +kernel@lists.fedoraproject.org +https://admin.fedoraproject.org/mailman/listinfo/kernel diff --git a/NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch b/NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch new file mode 100644 index 000000000..134b210fe --- /dev/null +++ b/NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch @@ -0,0 +1,69 @@ +From: Trond Myklebust + +If the file wasn't opened for writing, then truncate and ftruncate +need to report the appropriate errors. + +Reported-by: Miklos Szeredi +Signed-off-by: Trond Myklebust +Cc: stable@vger.kernel.org +--- + fs/nfs/dir.c | 4 ++-- + fs/nfs/nfs4proc.c | 15 ++++++++++++--- + 2 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c +index bb132a8..51a2686 100644 +--- a/fs/nfs/dir.c ++++ b/fs/nfs/dir.c +@@ -1429,7 +1429,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry + } + + open_flags = nd->intent.open.flags; +- attr.ia_valid = 0; ++ attr.ia_valid = ATTR_OPEN; + + ctx = create_nfs_open_context(dentry, open_flags); + res = ERR_CAST(ctx); +@@ -1536,7 +1536,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) + if (IS_ERR(ctx)) + goto out; + +- attr.ia_valid = 0; ++ attr.ia_valid = ATTR_OPEN; + if (openflags & O_TRUNC) { + attr.ia_valid |= ATTR_SIZE; + attr.ia_size = 0; +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index c4c6b48..e2a2893 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -1921,10 +1921,19 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, + }; + int err; + do { +- err = nfs4_handle_exception(server, +- _nfs4_do_setattr(inode, cred, fattr, sattr, state), +- &exception); ++ err = _nfs4_do_setattr(inode, cred, fattr, sattr, state); ++ switch (err) { ++ case -NFS4ERR_OPENMODE: ++ if (state && !(state->state & FMODE_WRITE)) { ++ err = -EBADF; ++ if (sattr->ia_valid & ATTR_OPEN) ++ err = -EACCES; ++ goto out; ++ } ++ } ++ err = nfs4_handle_exception(server, err, &exception); + } while (exception.retry); ++out: + return err; + } + +-- +1.7.7.6 + +_______________________________________________ +kernel mailing list +kernel@lists.fedoraproject.org +https://admin.fedoraproject.org/mailman/listinfo/kernel diff --git a/input-synaptics-fix-regression-with-image-sensor-trackpads.patch b/input-synaptics-fix-regression-with-image-sensor-trackpads.patch deleted file mode 100644 index 6c1542b7c..000000000 --- a/input-synaptics-fix-regression-with-image-sensor-trackpads.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 899c612d74d4a242158a4db20367388d6299c028 Mon Sep 17 00:00:00 2001 -From: Benjamin Herrenschmidt -Date: Fri, 20 Apr 2012 22:34:49 -0700 -Subject: [PATCH] Input: synaptics - fix regression with "image sensor" - trackpads - -commit 7968a5dd492ccc38345013e534ad4c8d6eb60ed1 -Input: synaptics - add support for Relative mode - -Accidentally broke support for advanced gestures (multitouch) -on some trackpads such as the one in my ThinkPad X220 by -incorretly changing the condition for enabling them. This -restores it. - -Signed-off-by: Benjamin Herrenschmidt -CC: stable@kernel.org [3.3] -Signed-off-by: Dmitry Torokhov ---- - drivers/input/mouse/synaptics.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c -index 8081a0a..a4b14a4 100644 ---- a/drivers/input/mouse/synaptics.c -+++ b/drivers/input/mouse/synaptics.c -@@ -274,7 +274,8 @@ static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse) - static unsigned char param = 0xc8; - struct synaptics_data *priv = psmouse->private; - -- if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) -+ if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || -+ SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c))) - return 0; - - if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL)) --- -1.7.10 - diff --git a/kernel.spec b/kernel.spec index caece7e57..969629df6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -721,6 +721,10 @@ Patch4000: NFSv4-Reduce-the-footprint-of-the-idmapper.patch Patch4001: NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch Patch4107: NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch +# NFS Client Patch set from Upstream +Patch4113: NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch +Patch4114: NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch + # patches headed upstream Patch12016: disable-i8042-check-on-apple-mac.patch @@ -785,9 +789,6 @@ Patch21520: KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch #rhbz 808559 Patch21530: ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch -Patch21700: x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch -Patch21701: x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch - #rhbz 806295 Patch21710: disable-hid-battery.patch @@ -798,14 +799,15 @@ Patch30010: debug-808990.patch #rhbz 814278 814289 CVE-2012-2119 Patch22007: macvtap-zerocopy-validate-vector-length.patch -Patch22011: input-synaptics-fix-regression-with-image-sensor-trackpads.patch - #rhbz 783708 Patch22012: ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch #rhbz 817298 Patch22013: ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch +#Lots of fixes from 3.3.5 stable queue +Patch22015: stable-queue-3.3.5-0502.patch + # END OF PATCH DEFINITIONS %endif @@ -1340,6 +1342,10 @@ ApplyPatch NFSv4-Reduce-the-footprint-of-the-idmapper.patch ApplyPatch NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch ApplyPatch NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch +# NFS Client Patch set from Upstream +ApplyPatch NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch +ApplyPatch NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch + # USB # WMI @@ -1485,24 +1491,21 @@ ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch #rhbz 807632 ApplyPatch libata-forbid-port-runtime-pm-by-default.patch -#rhbz 797559 -ApplyPatch x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch -ApplyPatch x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch - #rhbz 806295 ApplyPatch disable-hid-battery.patch #rhbz 814278 814289 CVE-2012-2119 ApplyPatch macvtap-zerocopy-validate-vector-length.patch -ApplyPatch input-synaptics-fix-regression-with-image-sensor-trackpads.patch - #rhbz 783708 ApplyPatch ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch #rhbz 817298 ApplyPatch ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch +#Lots of fixes from 3.3.5 stable queue +ApplyPatch stable-queue-3.3.5-0502.patch + # END OF PATCH APPLICATIONS %endif @@ -2241,6 +2244,10 @@ fi # and build. %changelog +* Thu May 03 2012 Justin M. Forbes 3.3.4-3 +- Many patches from 3.3.5 stable queue +- NFS Bugfixes from upstream + * Mon Apr 30 2012 Josh Boyer - Backport ipw2x00 nl80211 cipher suite reporting (rhbz 817298) diff --git a/stable-queue-3.3.5-0502.patch b/stable-queue-3.3.5-0502.patch new file mode 100644 index 000000000..4f33ba861 --- /dev/null +++ b/stable-queue-3.3.5-0502.patch @@ -0,0 +1,2804 @@ +From 5ac57550f279c3d991ef0b398681bcaca18169f7 Mon Sep 17 00:00:00 2001 +From: David Henningsson +Date: Fri, 20 Apr 2012 10:01:46 +0200 +Subject: ALSA: HDA: Add external mic quirk for Asus Zenbook UX31E + +From: David Henningsson + +commit 5ac57550f279c3d991ef0b398681bcaca18169f7 upstream. + +According to the reporter, external mic starts to work if the +laptop-dmic model is used. According to BIOS pin config, all +pins are consistent with the alc269vb_laptop_dmic fixup, except +for the external mic, which is not present. + +BugLink: https://bugs.launchpad.net/bugs/950490 +Signed-off-by: David Henningsson +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_realtek.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -5402,6 +5402,7 @@ static const struct alc_fixup alc269_fix + }; + + static const struct snd_pci_quirk alc269_fixup_tbl[] = { ++ SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC), + SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), + SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), +From 7e1f7c8a6e517900cd84da1b8ae020f08f286c3b Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Thu, 12 Apr 2012 17:29:36 +0100 +Subject: ASoC: dapm: Ensure power gets managed for line widgets + +From: Mark Brown + +commit 7e1f7c8a6e517900cd84da1b8ae020f08f286c3b upstream. + +Line widgets had not been included in either the power up or power down +sequences so if a widget had an event associated with it that event would +never be run. Fix this minimally by adding them to the sequences, we +should probably be doing away with the specific widget types as they all +have the same priority anyway. + +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/soc-dapm.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/sound/soc/soc-dapm.c ++++ b/sound/soc/soc-dapm.c +@@ -70,6 +70,7 @@ static int dapm_up_seq[] = { + [snd_soc_dapm_out_drv] = 10, + [snd_soc_dapm_hp] = 10, + [snd_soc_dapm_spk] = 10, ++ [snd_soc_dapm_line] = 10, + [snd_soc_dapm_post] = 11, + }; + +@@ -78,6 +79,7 @@ static int dapm_down_seq[] = { + [snd_soc_dapm_adc] = 1, + [snd_soc_dapm_hp] = 2, + [snd_soc_dapm_spk] = 2, ++ [snd_soc_dapm_line] = 2, + [snd_soc_dapm_out_drv] = 2, + [snd_soc_dapm_pga] = 4, + [snd_soc_dapm_mixer_named_ctl] = 5, +From 1a38336b8611a04f0a624330c1f815421f4bf5f4 Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Thu, 12 Apr 2012 19:47:11 +0100 +Subject: ASoC: wm8994: Improve sequencing of AIF channel enables + +From: Mark Brown + +commit 1a38336b8611a04f0a624330c1f815421f4bf5f4 upstream. + +This ensures a clean startup of the channels, without this change some +use cases could result in issues in a small proportion of cases. + +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/wm8994.c | 276 +++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 222 insertions(+), 54 deletions(-) + +--- a/sound/soc/codecs/wm8994.c ++++ b/sound/soc/codecs/wm8994.c +@@ -929,61 +929,170 @@ static void wm8994_update_class_w(struct + } + } + +-static int late_enable_ev(struct snd_soc_dapm_widget *w, +- struct snd_kcontrol *kcontrol, int event) ++static int aif1clk_ev(struct snd_soc_dapm_widget *w, ++ struct snd_kcontrol *kcontrol, int event) + { + struct snd_soc_codec *codec = w->codec; +- struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); ++ struct wm8994 *control = codec->control_data; ++ int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA; ++ int dac; ++ int adc; ++ int val; ++ ++ switch (control->type) { ++ case WM8994: ++ case WM8958: ++ mask |= WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA; ++ break; ++ default: ++ break; ++ } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: +- if (wm8994->aif1clk_enable) { +- snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, +- WM8994_AIF1CLK_ENA_MASK, +- WM8994_AIF1CLK_ENA); +- wm8994->aif1clk_enable = 0; +- } +- if (wm8994->aif2clk_enable) { +- snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, +- WM8994_AIF2CLK_ENA_MASK, +- WM8994_AIF2CLK_ENA); +- wm8994->aif2clk_enable = 0; +- } ++ val = snd_soc_read(codec, WM8994_AIF1_CONTROL_1); ++ if ((val & WM8994_AIF1ADCL_SRC) && ++ (val & WM8994_AIF1ADCR_SRC)) ++ adc = WM8994_AIF1ADC1R_ENA | WM8994_AIF1ADC2R_ENA; ++ else if (!(val & WM8994_AIF1ADCL_SRC) && ++ !(val & WM8994_AIF1ADCR_SRC)) ++ adc = WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC2L_ENA; ++ else ++ adc = WM8994_AIF1ADC1R_ENA | WM8994_AIF1ADC2R_ENA | ++ WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC2L_ENA; ++ ++ val = snd_soc_read(codec, WM8994_AIF1_CONTROL_2); ++ if ((val & WM8994_AIF1DACL_SRC) && ++ (val & WM8994_AIF1DACR_SRC)) ++ dac = WM8994_AIF1DAC1R_ENA | WM8994_AIF1DAC2R_ENA; ++ else if (!(val & WM8994_AIF1DACL_SRC) && ++ !(val & WM8994_AIF1DACR_SRC)) ++ dac = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC2L_ENA; ++ else ++ dac = WM8994_AIF1DAC1R_ENA | WM8994_AIF1DAC2R_ENA | ++ WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC2L_ENA; ++ ++ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_4, ++ mask, adc); ++ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, ++ mask, dac); ++ snd_soc_update_bits(codec, WM8994_CLOCKING_1, ++ WM8994_AIF1DSPCLK_ENA | ++ WM8994_SYSDSPCLK_ENA, ++ WM8994_AIF1DSPCLK_ENA | ++ WM8994_SYSDSPCLK_ENA); ++ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_4, mask, ++ WM8994_AIF1ADC1R_ENA | ++ WM8994_AIF1ADC1L_ENA | ++ WM8994_AIF1ADC2R_ENA | ++ WM8994_AIF1ADC2L_ENA); ++ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, mask, ++ WM8994_AIF1DAC1R_ENA | ++ WM8994_AIF1DAC1L_ENA | ++ WM8994_AIF1DAC2R_ENA | ++ WM8994_AIF1DAC2L_ENA); + break; +- } + +- /* We may also have postponed startup of DSP, handle that. */ +- wm8958_aif_ev(w, kcontrol, event); ++ case SND_SOC_DAPM_PRE_PMD: ++ case SND_SOC_DAPM_POST_PMD: ++ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, ++ mask, 0); ++ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_4, ++ mask, 0); ++ ++ val = snd_soc_read(codec, WM8994_CLOCKING_1); ++ if (val & WM8994_AIF2DSPCLK_ENA) ++ val = WM8994_SYSDSPCLK_ENA; ++ else ++ val = 0; ++ snd_soc_update_bits(codec, WM8994_CLOCKING_1, ++ WM8994_SYSDSPCLK_ENA | ++ WM8994_AIF1DSPCLK_ENA, val); ++ break; ++ } + + return 0; + } + +-static int late_disable_ev(struct snd_soc_dapm_widget *w, +- struct snd_kcontrol *kcontrol, int event) ++static int aif2clk_ev(struct snd_soc_dapm_widget *w, ++ struct snd_kcontrol *kcontrol, int event) + { + struct snd_soc_codec *codec = w->codec; +- struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); ++ int dac; ++ int adc; ++ int val; + + switch (event) { ++ case SND_SOC_DAPM_PRE_PMU: ++ val = snd_soc_read(codec, WM8994_AIF2_CONTROL_1); ++ if ((val & WM8994_AIF2ADCL_SRC) && ++ (val & WM8994_AIF2ADCR_SRC)) ++ adc = WM8994_AIF2ADCR_ENA; ++ else if (!(val & WM8994_AIF2ADCL_SRC) && ++ !(val & WM8994_AIF2ADCR_SRC)) ++ adc = WM8994_AIF2ADCL_ENA; ++ else ++ adc = WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA; ++ ++ ++ val = snd_soc_read(codec, WM8994_AIF2_CONTROL_2); ++ if ((val & WM8994_AIF2DACL_SRC) && ++ (val & WM8994_AIF2DACR_SRC)) ++ dac = WM8994_AIF2DACR_ENA; ++ else if (!(val & WM8994_AIF2DACL_SRC) && ++ !(val & WM8994_AIF2DACR_SRC)) ++ dac = WM8994_AIF2DACL_ENA; ++ else ++ dac = WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA; ++ ++ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_4, ++ WM8994_AIF2ADCL_ENA | ++ WM8994_AIF2ADCR_ENA, adc); ++ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, ++ WM8994_AIF2DACL_ENA | ++ WM8994_AIF2DACR_ENA, dac); ++ snd_soc_update_bits(codec, WM8994_CLOCKING_1, ++ WM8994_AIF2DSPCLK_ENA | ++ WM8994_SYSDSPCLK_ENA, ++ WM8994_AIF2DSPCLK_ENA | ++ WM8994_SYSDSPCLK_ENA); ++ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_4, ++ WM8994_AIF2ADCL_ENA | ++ WM8994_AIF2ADCR_ENA, ++ WM8994_AIF2ADCL_ENA | ++ WM8994_AIF2ADCR_ENA); ++ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, ++ WM8994_AIF2DACL_ENA | ++ WM8994_AIF2DACR_ENA, ++ WM8994_AIF2DACL_ENA | ++ WM8994_AIF2DACR_ENA); ++ break; ++ ++ case SND_SOC_DAPM_PRE_PMD: + case SND_SOC_DAPM_POST_PMD: +- if (wm8994->aif1clk_disable) { +- snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, +- WM8994_AIF1CLK_ENA_MASK, 0); +- wm8994->aif1clk_disable = 0; +- } +- if (wm8994->aif2clk_disable) { +- snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, +- WM8994_AIF2CLK_ENA_MASK, 0); +- wm8994->aif2clk_disable = 0; +- } ++ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, ++ WM8994_AIF2DACL_ENA | ++ WM8994_AIF2DACR_ENA, 0); ++ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, ++ WM8994_AIF2ADCL_ENA | ++ WM8994_AIF2ADCR_ENA, 0); ++ ++ val = snd_soc_read(codec, WM8994_CLOCKING_1); ++ if (val & WM8994_AIF1DSPCLK_ENA) ++ val = WM8994_SYSDSPCLK_ENA; ++ else ++ val = 0; ++ snd_soc_update_bits(codec, WM8994_CLOCKING_1, ++ WM8994_SYSDSPCLK_ENA | ++ WM8994_AIF2DSPCLK_ENA, val); + break; + } + + return 0; + } + +-static int aif1clk_ev(struct snd_soc_dapm_widget *w, +- struct snd_kcontrol *kcontrol, int event) ++static int aif1clk_late_ev(struct snd_soc_dapm_widget *w, ++ struct snd_kcontrol *kcontrol, int event) + { + struct snd_soc_codec *codec = w->codec; + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); +@@ -1000,8 +1109,8 @@ static int aif1clk_ev(struct snd_soc_dap + return 0; + } + +-static int aif2clk_ev(struct snd_soc_dapm_widget *w, +- struct snd_kcontrol *kcontrol, int event) ++static int aif2clk_late_ev(struct snd_soc_dapm_widget *w, ++ struct snd_kcontrol *kcontrol, int event) + { + struct snd_soc_codec *codec = w->codec; + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); +@@ -1018,6 +1127,63 @@ static int aif2clk_ev(struct snd_soc_dap + return 0; + } + ++static int late_enable_ev(struct snd_soc_dapm_widget *w, ++ struct snd_kcontrol *kcontrol, int event) ++{ ++ struct snd_soc_codec *codec = w->codec; ++ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); ++ ++ switch (event) { ++ case SND_SOC_DAPM_PRE_PMU: ++ if (wm8994->aif1clk_enable) { ++ aif1clk_ev(w, kcontrol, event); ++ snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, ++ WM8994_AIF1CLK_ENA_MASK, ++ WM8994_AIF1CLK_ENA); ++ wm8994->aif1clk_enable = 0; ++ } ++ if (wm8994->aif2clk_enable) { ++ aif2clk_ev(w, kcontrol, event); ++ snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, ++ WM8994_AIF2CLK_ENA_MASK, ++ WM8994_AIF2CLK_ENA); ++ wm8994->aif2clk_enable = 0; ++ } ++ break; ++ } ++ ++ /* We may also have postponed startup of DSP, handle that. */ ++ wm8958_aif_ev(w, kcontrol, event); ++ ++ return 0; ++} ++ ++static int late_disable_ev(struct snd_soc_dapm_widget *w, ++ struct snd_kcontrol *kcontrol, int event) ++{ ++ struct snd_soc_codec *codec = w->codec; ++ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); ++ ++ switch (event) { ++ case SND_SOC_DAPM_POST_PMD: ++ if (wm8994->aif1clk_disable) { ++ snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, ++ WM8994_AIF1CLK_ENA_MASK, 0); ++ aif1clk_ev(w, kcontrol, event); ++ wm8994->aif1clk_disable = 0; ++ } ++ if (wm8994->aif2clk_disable) { ++ snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, ++ WM8994_AIF2CLK_ENA_MASK, 0); ++ aif2clk_ev(w, kcontrol, event); ++ wm8994->aif2clk_disable = 0; ++ } ++ break; ++ } ++ ++ return 0; ++} ++ + static int adc_mux_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) + { +@@ -1314,9 +1480,9 @@ static const struct snd_kcontrol_new aif + SOC_DAPM_ENUM("AIF2DACR Mux", aif2dacr_src_enum); + + static const struct snd_soc_dapm_widget wm8994_lateclk_revd_widgets[] = { +-SND_SOC_DAPM_SUPPLY("AIF1CLK", SND_SOC_NOPM, 0, 0, aif1clk_ev, ++SND_SOC_DAPM_SUPPLY("AIF1CLK", SND_SOC_NOPM, 0, 0, aif1clk_late_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +-SND_SOC_DAPM_SUPPLY("AIF2CLK", SND_SOC_NOPM, 0, 0, aif2clk_ev, ++SND_SOC_DAPM_SUPPLY("AIF2CLK", SND_SOC_NOPM, 0, 0, aif2clk_late_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_PGA_E("Late DAC1L Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0, +@@ -1345,8 +1511,10 @@ SND_SOC_DAPM_POST("Late Disable PGA", la + }; + + static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = { +-SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, NULL, 0), +-SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0), ++SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, aif1clk_ev, ++ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), ++SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, aif2clk_ev, ++ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0, + left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), +@@ -1399,30 +1567,30 @@ SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM + SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + +-SND_SOC_DAPM_SUPPLY("DSP1CLK", WM8994_CLOCKING_1, 3, 0, NULL, 0), +-SND_SOC_DAPM_SUPPLY("DSP2CLK", WM8994_CLOCKING_1, 2, 0, NULL, 0), +-SND_SOC_DAPM_SUPPLY("DSPINTCLK", WM8994_CLOCKING_1, 1, 0, NULL, 0), ++SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, 3, 0, NULL, 0), ++SND_SOC_DAPM_SUPPLY("DSP2CLK", SND_SOC_NOPM, 2, 0, NULL, 0), ++SND_SOC_DAPM_SUPPLY("DSPINTCLK", SND_SOC_NOPM, 1, 0, NULL, 0), + + SND_SOC_DAPM_AIF_OUT("AIF1ADC1L", NULL, +- 0, WM8994_POWER_MANAGEMENT_4, 9, 0), ++ 0, SND_SOC_NOPM, 9, 0), + SND_SOC_DAPM_AIF_OUT("AIF1ADC1R", NULL, +- 0, WM8994_POWER_MANAGEMENT_4, 8, 0), ++ 0, SND_SOC_NOPM, 8, 0), + SND_SOC_DAPM_AIF_IN_E("AIF1DAC1L", NULL, 0, +- WM8994_POWER_MANAGEMENT_5, 9, 0, wm8958_aif_ev, ++ SND_SOC_NOPM, 9, 0, wm8958_aif_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_AIF_IN_E("AIF1DAC1R", NULL, 0, +- WM8994_POWER_MANAGEMENT_5, 8, 0, wm8958_aif_ev, ++ SND_SOC_NOPM, 8, 0, wm8958_aif_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_AIF_OUT("AIF1ADC2L", NULL, +- 0, WM8994_POWER_MANAGEMENT_4, 11, 0), ++ 0, SND_SOC_NOPM, 11, 0), + SND_SOC_DAPM_AIF_OUT("AIF1ADC2R", NULL, +- 0, WM8994_POWER_MANAGEMENT_4, 10, 0), ++ 0, SND_SOC_NOPM, 10, 0), + SND_SOC_DAPM_AIF_IN_E("AIF1DAC2L", NULL, 0, +- WM8994_POWER_MANAGEMENT_5, 11, 0, wm8958_aif_ev, ++ SND_SOC_NOPM, 11, 0, wm8958_aif_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_AIF_IN_E("AIF1DAC2R", NULL, 0, +- WM8994_POWER_MANAGEMENT_5, 10, 0, wm8958_aif_ev, ++ SND_SOC_NOPM, 10, 0, wm8958_aif_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER("AIF1ADC1L Mixer", SND_SOC_NOPM, 0, 0, +@@ -1449,14 +1617,14 @@ SND_SOC_DAPM_MIXER("DAC1R Mixer", SND_SO + dac1r_mix, ARRAY_SIZE(dac1r_mix)), + + SND_SOC_DAPM_AIF_OUT("AIF2ADCL", NULL, 0, +- WM8994_POWER_MANAGEMENT_4, 13, 0), ++ SND_SOC_NOPM, 13, 0), + SND_SOC_DAPM_AIF_OUT("AIF2ADCR", NULL, 0, +- WM8994_POWER_MANAGEMENT_4, 12, 0), ++ SND_SOC_NOPM, 12, 0), + SND_SOC_DAPM_AIF_IN_E("AIF2DACL", NULL, 0, +- WM8994_POWER_MANAGEMENT_5, 13, 0, wm8958_aif_ev, ++ SND_SOC_NOPM, 13, 0, wm8958_aif_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_AIF_IN_E("AIF2DACR", NULL, 0, +- WM8994_POWER_MANAGEMENT_5, 12, 0, wm8958_aif_ev, ++ SND_SOC_NOPM, 12, 0, wm8958_aif_ev, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_AIF_IN("AIF1DACDAT", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), +From 64f371bc3107e69efce563a3d0f0e6880de0d537 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Sun, 29 Apr 2012 13:30:08 -0700 +Subject: autofs: make the autofsv5 packet file descriptor use a packetized pipe + +From: Linus Torvalds + +commit 64f371bc3107e69efce563a3d0f0e6880de0d537 upstream. + +The autofs packet size has had a very unfortunate size problem on x86: +because the alignment of 'u64' differs in 32-bit and 64-bit modes, and +because the packet data was not 8-byte aligned, the size of the autofsv5 +packet structure differed between 32-bit and 64-bit modes despite +looking otherwise identical (300 vs 304 bytes respectively). + +We first fixed that up by making the 64-bit compat mode know about this +problem in commit a32744d4abae ("autofs: work around unhappy compat +problem on x86-64"), and that made a 32-bit 'systemd' work happily on a +64-bit kernel because everything then worked the same way as on a 32-bit +kernel. + +But it turned out that 'automount' had actually known and worked around +this problem in user space, so fixing the kernel to do the proper 32-bit +compatibility handling actually *broke* 32-bit automount on a 64-bit +kernel, because it knew that the packet sizes were wrong and expected +those incorrect sizes. + +As a result, we ended up reverting that compatibility mode fix, and +thus breaking systemd again, in commit fcbf94b9dedd. + +With both automount and systemd doing a single read() system call, and +verifying that they get *exactly* the size they expect but using +different sizes, it seemed that fixing one of them inevitably seemed to +break the other. At one point, a patch I seriously considered applying +from Michael Tokarev did a "strcmp()" to see if it was automount that +was doing the operation. Ugly, ugly. + +However, a prettier solution exists now thanks to the packetized pipe +mode. By marking the communication pipe as being packetized (by simply +setting the O_DIRECT flag), we can always just write the bigger packet +size, and if user-space does a smaller read, it will just get that +partial end result and the extra alignment padding will simply be thrown +away. + +This makes both automount and systemd happy, since they now get the size +they asked for, and the kernel side of autofs simply no longer needs to +care - it could pad out the packet arbitrarily. + +Of course, if there is some *other* user of autofs (please, please, +please tell me it ain't so - and we haven't heard of any) that tries to +read the packets with multiple writes, that other user will now be +broken - the whole point of the packetized mode is that one system call +gets exactly one packet, and you cannot read a packet in pieces. + +Tested-by: Michael Tokarev +Cc: Alan Cox +Cc: David Miller +Cc: Ian Kent +Cc: Thomas Meyer +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/autofs4/autofs_i.h | 11 +++++++++++ + fs/autofs4/dev-ioctl.c | 2 +- + fs/autofs4/inode.c | 2 +- + 3 files changed, 13 insertions(+), 2 deletions(-) + +--- a/fs/autofs4/autofs_i.h ++++ b/fs/autofs4/autofs_i.h +@@ -269,6 +269,17 @@ int autofs4_fill_super(struct super_bloc + struct autofs_info *autofs4_new_ino(struct autofs_sb_info *); + void autofs4_clean_ino(struct autofs_info *); + ++static inline int autofs_prepare_pipe(struct file *pipe) ++{ ++ if (!pipe->f_op || !pipe->f_op->write) ++ return -EINVAL; ++ if (!S_ISFIFO(pipe->f_dentry->d_inode->i_mode)) ++ return -EINVAL; ++ /* We want a packet pipe */ ++ pipe->f_flags |= O_DIRECT; ++ return 0; ++} ++ + /* Queue management functions */ + + int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify); +--- a/fs/autofs4/dev-ioctl.c ++++ b/fs/autofs4/dev-ioctl.c +@@ -376,7 +376,7 @@ static int autofs_dev_ioctl_setpipefd(st + err = -EBADF; + goto out; + } +- if (!pipe->f_op || !pipe->f_op->write) { ++ if (autofs_prepare_pipe(pipe) < 0) { + err = -EPIPE; + fput(pipe); + goto out; +--- a/fs/autofs4/inode.c ++++ b/fs/autofs4/inode.c +@@ -293,7 +293,7 @@ int autofs4_fill_super(struct super_bloc + printk("autofs: could not open pipe file descriptor\n"); + goto fail_dput; + } +- if (!pipe->f_op || !pipe->f_op->write) ++ if (autofs_prepare_pipe(pipe) < 0) + goto fail_fput; + sbi->pipe = pipe; + sbi->pipefd = pipefd; +From 511d63cb19329235bc9298b64010ec494b5e1408 Mon Sep 17 00:00:00 2001 +From: Horia Geanta +Date: Fri, 30 Mar 2012 17:49:53 +0300 +Subject: crypto: talitos - properly lock access to global talitos registers + +From: Horia Geanta + +commit 511d63cb19329235bc9298b64010ec494b5e1408 upstream. + +Access to global talitos registers must be protected for the case when +affinities are configured such that primary and secondary talitos irqs +run on different cpus. + +Signed-off-by: Horia Geanta +Signed-off-by: Kim Phillips +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/crypto/talitos.c | 20 +++++++++++++++++--- + 1 file changed, 17 insertions(+), 3 deletions(-) + +--- a/drivers/crypto/talitos.c ++++ b/drivers/crypto/talitos.c +@@ -124,6 +124,9 @@ struct talitos_private { + void __iomem *reg; + int irq[2]; + ++ /* SEC global registers lock */ ++ spinlock_t reg_lock ____cacheline_aligned; ++ + /* SEC version geometry (from device tree node) */ + unsigned int num_channels; + unsigned int chfifo_len; +@@ -412,6 +415,7 @@ static void talitos_done_##name(unsigned + { \ + struct device *dev = (struct device *)data; \ + struct talitos_private *priv = dev_get_drvdata(dev); \ ++ unsigned long flags; \ + \ + if (ch_done_mask & 1) \ + flush_channel(dev, 0, 0, 0); \ +@@ -427,8 +431,10 @@ static void talitos_done_##name(unsigned + out: \ + /* At this point, all completed channels have been processed */ \ + /* Unmask done interrupts for channels completed later on. */ \ ++ spin_lock_irqsave(&priv->reg_lock, flags); \ + setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ + setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT); \ ++ spin_unlock_irqrestore(&priv->reg_lock, flags); \ + } + DEF_TALITOS_DONE(4ch, TALITOS_ISR_4CHDONE) + DEF_TALITOS_DONE(ch0_2, TALITOS_ISR_CH_0_2_DONE) +@@ -619,22 +625,28 @@ static irqreturn_t talitos_interrupt_##n + struct device *dev = data; \ + struct talitos_private *priv = dev_get_drvdata(dev); \ + u32 isr, isr_lo; \ ++ unsigned long flags; \ + \ ++ spin_lock_irqsave(&priv->reg_lock, flags); \ + isr = in_be32(priv->reg + TALITOS_ISR); \ + isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \ + /* Acknowledge interrupt */ \ + out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \ + out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \ + \ +- if (unlikely((isr & ~TALITOS_ISR_4CHDONE) & ch_err_mask || isr_lo)) \ +- talitos_error(dev, isr, isr_lo); \ +- else \ ++ if (unlikely(isr & ch_err_mask || isr_lo)) { \ ++ spin_unlock_irqrestore(&priv->reg_lock, flags); \ ++ talitos_error(dev, isr & ch_err_mask, isr_lo); \ ++ } \ ++ else { \ + if (likely(isr & ch_done_mask)) { \ + /* mask further done interrupts. */ \ + clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ + /* done_task will unmask done interrupts at exit */ \ + tasklet_schedule(&priv->done_task[tlet]); \ + } \ ++ spin_unlock_irqrestore(&priv->reg_lock, flags); \ ++ } \ + \ + return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \ + IRQ_NONE; \ +@@ -2718,6 +2730,8 @@ static int talitos_probe(struct platform + + priv->ofdev = ofdev; + ++ spin_lock_init(&priv->reg_lock); ++ + err = talitos_probe_irq(ofdev); + if (err) + goto err_out; +From d62d421b071b08249361044d8e56c8b5c3ed6aa7 Mon Sep 17 00:00:00 2001 +From: Martin Nyhus +Date: Thu, 15 Mar 2012 18:25:48 +0100 +Subject: dell-laptop: Terminate quirks list properly + +From: Martin Nyhus + +commit d62d421b071b08249361044d8e56c8b5c3ed6aa7 upstream. + +Add missing DMI_NONE entry to end of the quirks list so +dmi_check_system() won't read past the end of the list. + +Signed-off-by: Martin Nyhus +Signed-off-by: Matthew Garrett +Cc: Guenter Roeck +Tested-by: Jens Gustedt +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/dell-laptop.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/platform/x86/dell-laptop.c ++++ b/drivers/platform/x86/dell-laptop.c +@@ -211,6 +211,7 @@ static struct dmi_system_id __devinitdat + }, + .driver_data = &quirk_dell_vostro_v130, + }, ++ { } + }; + + static struct calling_interface_buffer *buffer; +From ed8b0d67f33518a16c6b2450fe5ebebf180c2d04 Mon Sep 17 00:00:00 2001 +From: Nicolas Ferre +Date: Mon, 16 Apr 2012 14:46:30 +0200 +Subject: dmaengine: at_hdmac: remove clear-on-read in atc_dostart() + +From: Nicolas Ferre + +commit ed8b0d67f33518a16c6b2450fe5ebebf180c2d04 upstream. + +This loop on EBCISR register was designed to clear IRQ sources before enabling +a DMA channel. This register is clear-on-read so a race condition can appear if +another channel is already active and has just finished its transfer. +Removing this read on EBCISR is fixing the issue as there is no case where an IRQ +could be pending: we already make sure that this register is drained at probe() +time and during resume. + +Signed-off-by: Nicolas Ferre +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/dma/at_hdmac.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/drivers/dma/at_hdmac.c ++++ b/drivers/dma/at_hdmac.c +@@ -241,10 +241,6 @@ static void atc_dostart(struct at_dma_ch + + vdbg_dump_regs(atchan); + +- /* clear any pending interrupt */ +- while (dma_readl(atdma, EBCISR)) +- cpu_relax(); +- + channel_writel(atchan, SADDR, 0); + channel_writel(atchan, DADDR, 0); + channel_writel(atchan, CTRLA, 0); +From 44afb3a04391a74309d16180d1e4f8386fdfa745 Mon Sep 17 00:00:00 2001 +From: Xi Wang +Date: Mon, 23 Apr 2012 04:06:42 -0400 +Subject: drm/i915: fix integer overflow in i915_gem_do_execbuffer() + +From: Xi Wang + +commit 44afb3a04391a74309d16180d1e4f8386fdfa745 upstream. + +On 32-bit systems, a large args->num_cliprects from userspace via ioctl +may overflow the allocation size, leading to out-of-bounds access. + +This vulnerability was introduced in commit 432e58ed ("drm/i915: Avoid +allocation for execbuffer object list"). + +Signed-off-by: Xi Wang +Reviewed-by: Chris Wilson +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c ++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +@@ -1082,6 +1082,11 @@ i915_gem_do_execbuffer(struct drm_device + return -EINVAL; + } + ++ if (args->num_cliprects > UINT_MAX / sizeof(*cliprects)) { ++ DRM_DEBUG("execbuf with %u cliprects\n", ++ args->num_cliprects); ++ return -EINVAL; ++ } + cliprects = kmalloc(args->num_cliprects * sizeof(*cliprects), + GFP_KERNEL); + if (cliprects == NULL) { +From ed8cd3b2cd61004cab85380c52b1817aca1ca49b Mon Sep 17 00:00:00 2001 +From: Xi Wang +Date: Mon, 23 Apr 2012 04:06:41 -0400 +Subject: drm/i915: fix integer overflow in i915_gem_execbuffer2() + +From: Xi Wang + +commit ed8cd3b2cd61004cab85380c52b1817aca1ca49b upstream. + +On 32-bit systems, a large args->buffer_count from userspace via ioctl +may overflow the allocation size, leading to out-of-bounds access. + +This vulnerability was introduced in commit 8408c282 ("drm/i915: +First try a normal large kmalloc for the temporary exec buffers"). + +Signed-off-by: Xi Wang +Reviewed-by: Chris Wilson +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c ++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +@@ -1353,7 +1353,8 @@ i915_gem_execbuffer2(struct drm_device * + struct drm_i915_gem_exec_object2 *exec2_list = NULL; + int ret; + +- if (args->buffer_count < 1) { ++ if (args->buffer_count < 1 || ++ args->buffer_count > UINT_MAX / sizeof(*exec2_list)) { + DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count); + return -EINVAL; + } +From 6651819b4b4fc3caa6964c5d825eb4bb996f3905 Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Sun, 1 Apr 2012 19:16:18 +0200 +Subject: drm/i915: handle input/output sdvo timings separately in mode_set + +From: Daniel Vetter + +commit 6651819b4b4fc3caa6964c5d825eb4bb996f3905 upstream. + +We seem to have a decent confusion between the output timings and the +input timings of the sdvo encoder. If I understand the code correctly, +we use the original mode unchanged for the output timings, safe for +the lvds case. And we should use the adjusted mode for input timings. + +Clarify the situation by adding an explicit output_dtd to the sdvo +mode_set function and streamline the code-flow by moving the input and +output mode setting in the sdvo encode together. + +Furthermore testing showed that the sdvo input timing needs the +unadjusted dotclock, the sdvo chip will automatically compute the +required pixel multiplier to get a dotclock above 100 MHz. + +Fix this up when converting a drm mode to an sdvo dtd. + +This regression was introduced in + +commit c74696b9c890074c1e1ee3d7496fc71eb3680ced +Author: Pavel Roskin +Date: Thu Sep 2 14:46:34 2010 -0400 + + i915: revert some checks added by commit 32aad86f + +particularly the following hunk: + +# diff --git a/drivers/gpu/drm/i915/intel_sdvo.c +# b/drivers/gpu/drm/i915/intel_sdvo.c +# index 093e914..62d22ae 100644 +# --- a/drivers/gpu/drm/i915/intel_sdvo.c +# +++ b/drivers/gpu/drm/i915/intel_sdvo.c +# @@ -1122,11 +1123,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, +# +# /* We have tried to get input timing in mode_fixup, and filled into +# adjusted_mode */ +# - if (intel_sdvo->is_tv || intel_sdvo->is_lvds) { +# - intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); +# + intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); +# + if (intel_sdvo->is_tv || intel_sdvo->is_lvds) +# input_dtd.part2.sdvo_flags = intel_sdvo->sdvo_flags; +# - } else +# - intel_sdvo_get_dtd_from_mode(&input_dtd, mode); +# +# /* If it's a TV, we already set the output timing in mode_fixup. +# * Otherwise, the output timing is equal to the input timing. + +Due to questions raised in review, below a more elaborate analysis of +the bug at hand: + +Sdvo seems to have two timings, one is the output timing which will be +sent over whatever is connected on the other side of the sdvo chip (panel, +hdmi screen, tv), the other is the input timing which will be generated by +the gmch pipe. It looks like sdvo is expected to scale between the two. + +To make things slightly more complicated, we have a bunch of special +cases: +- For lvds panel we always use a fixed output timing, namely + intel_sdvo->sdvo_lvds_fixed_mode, hence that special case. +- Sdvo has an interface to generate a preferred input timing for a given + output timing. This is the confusing thing that I've tried to clear up + with the follow-on patches. +- A special requirement is that the input pixel clock needs to be between + 100MHz and 200MHz (likely to keep it within the electromechanical design + range of PCIe), 270MHz on later gen4+. Lower pixel clocks are + doubled/quadrupled. + +The thing this patch tries to fix is that the pipe needs to be +explicitly instructed to double/quadruple the pixels and needs the +correspondingly higher pixel clock, whereas the sdvo adaptor seems to +do that itself and needs the unadjusted pixel clock. For the sdvo +encode side we already set the pixel mutliplier with a different +command (0x21). + +This patch tries to fix this mess by: +- Keeping the output mode timing in the unadjusted plain mode, safe + for the lvds case. +- Storing the input timing in the adjusted_mode with the adjusted + pixel clock. This way we don't need to frob around with the core + crtc mode set code. +- Fixing up the pixelclock when constructing the sdvo dtd timing + struct. This is why the first hunk of the patch is an integral part + of the series. +- Dropping the is_tv special case because input_dtd is equivalent to + adjusted_mode after these changes. Follow-up patches clear this up + further (by simply ripping out intel_sdvo->input_dtd because it's + not needed). + +v2: Extend commit message with an in-depth bug analysis. + +Reported-and-Tested-by: Bernard Blackham +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=48157 +Reviewed-by: Jesse Barnes +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_sdvo.c | 34 ++++++++++++++++++---------------- + 1 file changed, 18 insertions(+), 16 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_sdvo.c ++++ b/drivers/gpu/drm/i915/intel_sdvo.c +@@ -731,6 +731,7 @@ static void intel_sdvo_get_dtd_from_mode + uint16_t width, height; + uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len; + uint16_t h_sync_offset, v_sync_offset; ++ int mode_clock; + + width = mode->crtc_hdisplay; + height = mode->crtc_vdisplay; +@@ -745,7 +746,11 @@ static void intel_sdvo_get_dtd_from_mode + h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start; + v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start; + +- dtd->part1.clock = mode->clock / 10; ++ mode_clock = mode->clock; ++ mode_clock /= intel_mode_get_pixel_multiplier(mode) ?: 1; ++ mode_clock /= 10; ++ dtd->part1.clock = mode_clock; ++ + dtd->part1.h_active = width & 0xff; + dtd->part1.h_blank = h_blank_len & 0xff; + dtd->part1.h_high = (((width >> 8) & 0xf) << 4) | +@@ -997,7 +1002,7 @@ static void intel_sdvo_mode_set(struct d + struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder); + u32 sdvox; + struct intel_sdvo_in_out_map in_out; +- struct intel_sdvo_dtd input_dtd; ++ struct intel_sdvo_dtd input_dtd, output_dtd; + int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); + int rate; + +@@ -1022,20 +1027,13 @@ static void intel_sdvo_mode_set(struct d + intel_sdvo->attached_output)) + return; + +- /* We have tried to get input timing in mode_fixup, and filled into +- * adjusted_mode. +- */ +- if (intel_sdvo->is_tv || intel_sdvo->is_lvds) { +- input_dtd = intel_sdvo->input_dtd; +- } else { +- /* Set the output timing to the screen */ +- if (!intel_sdvo_set_target_output(intel_sdvo, +- intel_sdvo->attached_output)) +- return; +- +- intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); +- (void) intel_sdvo_set_output_timing(intel_sdvo, &input_dtd); +- } ++ /* lvds has a special fixed output timing. */ ++ if (intel_sdvo->is_lvds) ++ intel_sdvo_get_dtd_from_mode(&output_dtd, ++ intel_sdvo->sdvo_lvds_fixed_mode); ++ else ++ intel_sdvo_get_dtd_from_mode(&output_dtd, mode); ++ (void) intel_sdvo_set_output_timing(intel_sdvo, &output_dtd); + + /* Set the input timing to the screen. Assume always input 0. */ + if (!intel_sdvo_set_target_input(intel_sdvo)) +@@ -1053,6 +1051,10 @@ static void intel_sdvo_mode_set(struct d + !intel_sdvo_set_tv_format(intel_sdvo)) + return; + ++ /* We have tried to get input timing in mode_fixup, and filled into ++ * adjusted_mode. ++ */ ++ intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); + (void) intel_sdvo_set_input_timing(intel_sdvo, &input_dtd); + + switch (pixel_multiplier) { +From 3a69ddd6f872180b6f61fda87152b37202118fbc Mon Sep 17 00:00:00 2001 +From: Kenneth Graunke +Date: Fri, 27 Apr 2012 12:44:41 -0700 +Subject: drm/i915: Set the Stencil Cache eviction policy to non-LRA mode. + +From: Kenneth Graunke + +commit 3a69ddd6f872180b6f61fda87152b37202118fbc upstream. + +Clearing bit 5 of CACHE_MODE_0 is necessary to prevent GPU hangs in +OpenGL programs such as Google MapsGL, Google Earth, and gzdoom when +using separate stencil buffers. Without it, the GPU tries to use the +LRA eviction policy, which isn't supported. This was supposed to be off +by default, but seems to be on for many machines. + +This cannot be done in gen6_init_clock_gating with most of the other +workaround bits; the render ring needs to exist. Otherwise, the +register write gets dropped on the floor (one printk will show it +changed, but a second printk immediately following shows the value +reverts to the old one). + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=47535 +Cc: Rob Castle +Cc: Eric Appleman +Cc: aaron667@gmx.net +Cc: Keith Packard +Signed-off-by: Kenneth Graunke +Reviewed-by: Daniel Vetter +Acked-by: Daniel Vetter +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_reg.h | 1 + + drivers/gpu/drm/i915/intel_ringbuffer.c | 8 ++++++++ + 2 files changed, 9 insertions(+) + +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -523,6 +523,7 @@ + #define CM0_MASK_SHIFT 16 + #define CM0_IZ_OPT_DISABLE (1<<6) + #define CM0_ZR_OPT_DISABLE (1<<5) ++#define CM0_STC_EVICT_DISABLE_LRA_SNB (1<<5) + #define CM0_DEPTH_EVICT_DISABLE (1<<4) + #define CM0_COLOR_EVICT_DISABLE (1<<3) + #define CM0_DEPTH_WRITE_DISABLE (1<<1) +--- a/drivers/gpu/drm/i915/intel_ringbuffer.c ++++ b/drivers/gpu/drm/i915/intel_ringbuffer.c +@@ -417,6 +417,14 @@ static int init_render_ring(struct intel + if (INTEL_INFO(dev)->gen >= 6) { + I915_WRITE(INSTPM, + INSTPM_FORCE_ORDERING << 16 | INSTPM_FORCE_ORDERING); ++ ++ /* From the Sandybridge PRM, volume 1 part 3, page 24: ++ * "If this bit is set, STCunit will have LRA as replacement ++ * policy. [...] This bit must be reset. LRA replacement ++ * policy is not supported." ++ */ ++ I915_WRITE(CACHE_MODE_0, ++ CM0_STC_EVICT_DISABLE_LRA_SNB << CM0_MASK_SHIFT); + } + + return ret; +From 700698e7c303f5095107c62a81872c2c3dad1702 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Fri, 27 Apr 2012 17:18:59 -0400 +Subject: drm/radeon/kms: need to set up ss on DP bridges as well + +From: Alex Deucher + +commit 700698e7c303f5095107c62a81872c2c3dad1702 upstream. + +Makes Nutmeg DP to VGA bridges work for me. + +Fixes: +https://bugs.freedesktop.org/show_bug.cgi?id=42490 + +Noticed by Jerome Glisse (after weeks of debugging). + +Signed-off-by: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/atombios_crtc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/radeon/atombios_crtc.c ++++ b/drivers/gpu/drm/radeon/atombios_crtc.c +@@ -912,8 +912,8 @@ static void atombios_crtc_set_pll(struct + break; + } + +- if (radeon_encoder->active_device & +- (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) { ++ if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || ++ (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) { + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + struct drm_connector *connector = + radeon_get_connector_for_encoder(encoder); +From 00250ec90963b7ef6678438888f3244985ecde14 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Mon, 9 Apr 2012 18:16:34 -0400 +Subject: hwmon: fam15h_power: fix bogus values with current BIOSes + +From: Andre Przywara + +commit 00250ec90963b7ef6678438888f3244985ecde14 upstream. + +Newer BKDG[1] versions recommend a different initialization value for +the running average range register in the northbridge. This improves +the power reading by avoiding counter saturations resulting in bogus +values for anything below about 80% of TDP power consumption. +Updated BIOSes will have this new value set up from the beginning, +but meanwhile we correct this value ourselves. +This needs to be done on all northbridges, even on those where the +driver itself does not register at. + +This fixes the driver on all current machines to provide proper +values for idle load. + +[1] +http://support.amd.com/us/Processor_TechDocs/42301_15h_Mod_00h-0Fh_BKDG.pdf +Chapter 3.8: D18F5xE0 Processor TDP Running Average (p. 452) + +Signed-off-by: Andre Przywara +Acked-by: Jean Delvare +[guenter.roeck@ericsson.com: Removed unnecessary return statement] +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hwmon/fam15h_power.c | 39 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 39 insertions(+) + +--- a/drivers/hwmon/fam15h_power.c ++++ b/drivers/hwmon/fam15h_power.c +@@ -122,6 +122,38 @@ static bool __devinit fam15h_power_is_in + return true; + } + ++/* ++ * Newer BKDG versions have an updated recommendation on how to properly ++ * initialize the running average range (was: 0xE, now: 0x9). This avoids ++ * counter saturations resulting in bogus power readings. ++ * We correct this value ourselves to cope with older BIOSes. ++ */ ++static void __devinit tweak_runavg_range(struct pci_dev *pdev) ++{ ++ u32 val; ++ const struct pci_device_id affected_device = { ++ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }; ++ ++ /* ++ * let this quirk apply only to the current version of the ++ * northbridge, since future versions may change the behavior ++ */ ++ if (!pci_match_id(&affected_device, pdev)) ++ return; ++ ++ pci_bus_read_config_dword(pdev->bus, ++ PCI_DEVFN(PCI_SLOT(pdev->devfn), 5), ++ REG_TDP_RUNNING_AVERAGE, &val); ++ if ((val & 0xf) != 0xe) ++ return; ++ ++ val &= ~0xf; ++ val |= 0x9; ++ pci_bus_write_config_dword(pdev->bus, ++ PCI_DEVFN(PCI_SLOT(pdev->devfn), 5), ++ REG_TDP_RUNNING_AVERAGE, val); ++} ++ + static void __devinit fam15h_power_init_data(struct pci_dev *f4, + struct fam15h_power_data *data) + { +@@ -155,6 +187,13 @@ static int __devinit fam15h_power_probe( + struct device *dev; + int err; + ++ /* ++ * though we ignore every other northbridge, we still have to ++ * do the tweaking on _each_ node in MCM processors as the counters ++ * are working hand-in-hand ++ */ ++ tweak_runavg_range(pdev); ++ + if (!fam15h_power_is_internal_node0(pdev)) { + err = -ENODEV; + goto exit; +From c3e40a9972428d6e2d8e287ed0233a57a218c30f Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Wed, 25 Apr 2012 13:44:20 -0700 +Subject: hwmon: (fam15h_power) Fix pci_device_id array + +From: Guenter Roeck + +commit c3e40a9972428d6e2d8e287ed0233a57a218c30f upstream. + +pci_match_id() takes an *array* of IDs which must be properly zero- +terminated. + +Reported-by: Ben Hutchings +Signed-off-by: Guenter Roeck +Acked-by: Jean Delvare +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hwmon/fam15h_power.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/hwmon/fam15h_power.c ++++ b/drivers/hwmon/fam15h_power.c +@@ -128,17 +128,20 @@ static bool __devinit fam15h_power_is_in + * counter saturations resulting in bogus power readings. + * We correct this value ourselves to cope with older BIOSes. + */ ++static DEFINE_PCI_DEVICE_TABLE(affected_device) = { ++ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, ++ { 0 } ++}; ++ + static void __devinit tweak_runavg_range(struct pci_dev *pdev) + { + u32 val; +- const struct pci_device_id affected_device = { +- PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }; + + /* + * let this quirk apply only to the current version of the + * northbridge, since future versions may change the behavior + */ +- if (!pci_match_id(&affected_device, pdev)) ++ if (!pci_match_id(affected_device, pdev)) + return; + + pci_bus_read_config_dword(pdev->bus, +From 089f9fba56faf33cc6dd2a6442b7ac92c58b8209 Mon Sep 17 00:00:00 2001 +From: Oleg Nesterov +Date: Mon, 16 Apr 2012 22:48:15 +0200 +Subject: i387: ptrace breaks the lazy-fpu-restore logic + +From: Oleg Nesterov + +commit 089f9fba56faf33cc6dd2a6442b7ac92c58b8209 upstream. + +Starting from 7e16838d "i387: support lazy restore of FPU state" +we assume that fpu_owner_task doesn't need restore_fpu_checking() +on the context switch, its FPU state should match what we already +have in the FPU on this CPU. + +However, debugger can change the tracee's FPU state, in this case +we should reset fpu.last_cpu to ensure fpu_lazy_restore() can't +return true. + +Change init_fpu() to do this, it is called by user_regset->set() +methods. + +Reported-by: Jan Kratochvil +Suggested-by: Linus Torvalds +Signed-off-by: Oleg Nesterov +Link: http://lkml.kernel.org/r/20120416204815.GB24884@redhat.com +Signed-off-by: H. Peter Anvin +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/i387.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/x86/kernel/i387.c ++++ b/arch/x86/kernel/i387.c +@@ -154,6 +154,7 @@ int init_fpu(struct task_struct *tsk) + if (tsk_used_math(tsk)) { + if (HAVE_HWFP && tsk == current) + unlazy_fpu(tsk); ++ tsk->thread.fpu.last_cpu = ~0; + return 0; + } + +From 899c612d74d4a242158a4db20367388d6299c028 Mon Sep 17 00:00:00 2001 +From: Benjamin Herrenschmidt +Date: Fri, 20 Apr 2012 22:34:49 -0700 +Subject: Input: synaptics - fix regression with "image sensor" trackpads + +From: Benjamin Herrenschmidt + +commit 899c612d74d4a242158a4db20367388d6299c028 upstream. + +commit 7968a5dd492ccc38345013e534ad4c8d6eb60ed1 +Input: synaptics - add support for Relative mode + +Accidentally broke support for advanced gestures (multitouch) +on some trackpads such as the one in my ThinkPad X220 by +incorretly changing the condition for enabling them. This +restores it. + +Signed-off-by: Benjamin Herrenschmidt +Signed-off-by: Dmitry Torokhov +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/input/mouse/synaptics.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/input/mouse/synaptics.c ++++ b/drivers/input/mouse/synaptics.c +@@ -274,7 +274,8 @@ static int synaptics_set_advanced_gestur + static unsigned char param = 0xc8; + struct synaptics_data *priv = psmouse->private; + +- if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) ++ if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || ++ SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c))) + return 0; + + if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL)) +From 98a2139f4f4d7b5fcc3a54c7fddbe88612abed20 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Sat, 3 Sep 2011 01:09:43 +0200 +Subject: nfs: Enclose hostname in brackets when needed in + nfs_do_root_mount + +From: Jan Kara + +commit 98a2139f4f4d7b5fcc3a54c7fddbe88612abed20 upstream. + +When hostname contains colon (e.g. when it is an IPv6 address) it needs +to be enclosed in brackets to make parsing of NFS device string possible. +Fix nfs_do_root_mount() to enclose hostname properly when needed. NFS code +actually does not need this as it does not parse the string passed by +nfs_do_root_mount() but the device string is exposed to userspace in +/proc/mounts. + +CC: Josh Boyer +CC: Trond Myklebust +Signed-off-by: Jan Kara +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/super.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/fs/nfs/super.c ++++ b/fs/nfs/super.c +@@ -2707,11 +2707,15 @@ static struct vfsmount *nfs_do_root_moun + char *root_devname; + size_t len; + +- len = strlen(hostname) + 3; ++ len = strlen(hostname) + 5; + root_devname = kmalloc(len, GFP_KERNEL); + if (root_devname == NULL) + return ERR_PTR(-ENOMEM); +- snprintf(root_devname, len, "%s:/", hostname); ++ /* Does hostname needs to be enclosed in brackets? */ ++ if (strchr(hostname, ':')) ++ snprintf(root_devname, len, "[%s]:/", hostname); ++ else ++ snprintf(root_devname, len, "%s:/", hostname); + root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data); + kfree(root_devname); + return root_mnt; +From 8ccd271f7a3a846ce6f85ead0760d9d12994a611 Mon Sep 17 00:00:00 2001 +From: Fred Isaman +Date: Fri, 20 Apr 2012 14:47:35 -0400 +Subject: NFS: put open context on error in nfs_flush_multi + +From: Fred Isaman + +commit 8ccd271f7a3a846ce6f85ead0760d9d12994a611 upstream. + +Signed-off-by: Fred Isaman +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/write.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nfs/write.c ++++ b/fs/nfs/write.c +@@ -974,7 +974,7 @@ out_bad: + while (!list_empty(res)) { + data = list_entry(res->next, struct nfs_write_data, list); + list_del(&data->list); +- nfs_writedata_free(data); ++ nfs_writedata_release(data); + } + nfs_redirty_request(req); + return -ENOMEM; +From 73fb7bc7c57d971b11f2e00536ac2d3e316e0609 Mon Sep 17 00:00:00 2001 +From: Fred Isaman +Date: Fri, 20 Apr 2012 14:47:34 -0400 +Subject: NFS: put open context on error in nfs_pagein_multi + +From: Fred Isaman + +commit 73fb7bc7c57d971b11f2e00536ac2d3e316e0609 upstream. + +Signed-off-by: Fred Isaman +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/read.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nfs/read.c ++++ b/fs/nfs/read.c +@@ -324,7 +324,7 @@ out_bad: + while (!list_empty(res)) { + data = list_entry(res->next, struct nfs_read_data, list); + list_del(&data->list); +- nfs_readdata_free(data); ++ nfs_readdata_release(data); + } + nfs_readpage_release(req); + return -ENOMEM; +From 05ffe24f5290dc095f98fbaf84afe51ef404ccc5 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Wed, 18 Apr 2012 12:20:10 -0400 +Subject: NFSv4: Ensure that the LOCK code sets exception->inode + +From: Trond Myklebust + +commit 05ffe24f5290dc095f98fbaf84afe51ef404ccc5 upstream. + +All callers of nfs4_handle_exception() that need to handle +NFS4ERR_OPENMODE correctly should set exception->inode + +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/nfs4proc.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -4460,7 +4460,9 @@ static int _nfs4_do_setlk(struct nfs4_st + static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request) + { + struct nfs_server *server = NFS_SERVER(state->inode); +- struct nfs4_exception exception = { }; ++ struct nfs4_exception exception = { ++ .inode = state->inode, ++ }; + int err; + + do { +@@ -4478,7 +4480,9 @@ static int nfs4_lock_reclaim(struct nfs4 + static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request) + { + struct nfs_server *server = NFS_SERVER(state->inode); +- struct nfs4_exception exception = { }; ++ struct nfs4_exception exception = { ++ .inode = state->inode, ++ }; + int err; + + err = nfs4_set_lock_state(state, request); +@@ -4558,6 +4562,7 @@ static int nfs4_proc_setlk(struct nfs4_s + { + struct nfs4_exception exception = { + .state = state, ++ .inode = state->inode, + }; + int err; + +From 55725513b5ef9d462aa3e18527658a0362aaae83 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Wed, 18 Apr 2012 12:48:35 -0400 +Subject: NFSv4: Ensure that we check lock exclusive/shared type against open modes + +From: Trond Myklebust + +commit 55725513b5ef9d462aa3e18527658a0362aaae83 upstream. + +Since we may be simulating flock() locks using NFS byte range locks, +we can't rely on the VFS having checked the file open mode for us. + +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/nfs4proc.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -4608,6 +4608,20 @@ nfs4_proc_lock(struct file *filp, int cm + + if (state == NULL) + return -ENOLCK; ++ /* ++ * Don't rely on the VFS having checked the file open mode, ++ * since it won't do this for flock() locks. ++ */ ++ switch (request->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) { ++ case F_RDLCK: ++ if (!(filp->f_mode & FMODE_READ)) ++ return -EBADF; ++ break; ++ case F_WRLCK: ++ if (!(filp->f_mode & FMODE_WRITE)) ++ return -EBADF; ++ } ++ + do { + status = nfs4_proc_setlk(state, cmd, request); + if ((status != -EAGAIN) || IS_SETLK(cmd)) +From 2b5f8b0b44e17e625cfba1e7b88db44f4dcc0441 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Mon, 2 Apr 2012 10:51:55 +0200 +Subject: nl80211: ensure interface is up in various APIs + +From: Johannes Berg + +commit 2b5f8b0b44e17e625cfba1e7b88db44f4dcc0441 upstream. +[backported by Ben Greear] + +The nl80211 handling code should ensure as much as +it can that the interface is in a valid state, it +can certainly ensure the interface is running. + +Not doing so can cause calls through mac80211 into +the driver that result in warnings and unspecified +behaviour in the driver. + +Reported-by: Ben Greear +Signed-off-by: Johannes Berg +Signed-off-by: John W. Linville +Signed-off-by: Ben Greear +Signed-off-by: Greg Kroah-Hartman + +--- + net/wireless/nl80211.c | 29 +++++++++++++++++------------ + 1 file changed, 17 insertions(+), 12 deletions(-) + +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -1293,6 +1293,11 @@ static int nl80211_set_wiphy(struct sk_b + goto bad_res; + } + ++ if (!netif_running(netdev)) { ++ result = -ENETDOWN; ++ goto bad_res; ++ } ++ + nla_for_each_nested(nl_txq_params, + info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], + rem_txq_params) { +@@ -6262,7 +6267,7 @@ static struct genl_ops nl80211_ops[] = { + .doit = nl80211_get_key, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, +- .internal_flags = NL80211_FLAG_NEED_NETDEV | ++ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, + { +@@ -6294,7 +6299,7 @@ static struct genl_ops nl80211_ops[] = { + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + .doit = nl80211_addset_beacon, +- .internal_flags = NL80211_FLAG_NEED_NETDEV | ++ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, + { +@@ -6302,7 +6307,7 @@ static struct genl_ops nl80211_ops[] = { + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + .doit = nl80211_addset_beacon, +- .internal_flags = NL80211_FLAG_NEED_NETDEV | ++ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, + { +@@ -6326,7 +6331,7 @@ static struct genl_ops nl80211_ops[] = { + .doit = nl80211_set_station, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, +- .internal_flags = NL80211_FLAG_NEED_NETDEV | ++ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, + { +@@ -6342,7 +6347,7 @@ static struct genl_ops nl80211_ops[] = { + .doit = nl80211_del_station, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, +- .internal_flags = NL80211_FLAG_NEED_NETDEV | ++ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, + { +@@ -6375,7 +6380,7 @@ static struct genl_ops nl80211_ops[] = { + .doit = nl80211_del_mpath, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, +- .internal_flags = NL80211_FLAG_NEED_NETDEV | ++ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, + { +@@ -6383,7 +6388,7 @@ static struct genl_ops nl80211_ops[] = { + .doit = nl80211_set_bss, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, +- .internal_flags = NL80211_FLAG_NEED_NETDEV | ++ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, + { +@@ -6409,7 +6414,7 @@ static struct genl_ops nl80211_ops[] = { + .doit = nl80211_get_mesh_config, + .policy = nl80211_policy, + /* can be retrieved by unprivileged users */ +- .internal_flags = NL80211_FLAG_NEED_NETDEV | ++ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, + { +@@ -6542,7 +6547,7 @@ static struct genl_ops nl80211_ops[] = { + .doit = nl80211_setdel_pmksa, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, +- .internal_flags = NL80211_FLAG_NEED_NETDEV | ++ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, + { +@@ -6550,7 +6555,7 @@ static struct genl_ops nl80211_ops[] = { + .doit = nl80211_setdel_pmksa, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, +- .internal_flags = NL80211_FLAG_NEED_NETDEV | ++ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, + { +@@ -6558,7 +6563,7 @@ static struct genl_ops nl80211_ops[] = { + .doit = nl80211_flush_pmksa, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, +- .internal_flags = NL80211_FLAG_NEED_NETDEV | ++ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, + { +@@ -6718,7 +6723,7 @@ static struct genl_ops nl80211_ops[] = { + .doit = nl80211_probe_client, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, +- .internal_flags = NL80211_FLAG_NEED_NETDEV | ++ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, + { +From 9883035ae7edef3ec62ad215611cb8e17d6a1a5d Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Sun, 29 Apr 2012 13:12:42 -0700 +Subject: pipes: add a "packetized pipe" mode for writing + +From: Linus Torvalds + +commit 9883035ae7edef3ec62ad215611cb8e17d6a1a5d upstream. + +The actual internal pipe implementation is already really about +individual packets (called "pipe buffers"), and this simply exposes that +as a special packetized mode. + +When we are in the packetized mode (marked by O_DIRECT as suggested by +Alan Cox), a write() on a pipe will not merge the new data with previous +writes, so each write will get a pipe buffer of its own. The pipe +buffer is then marked with the PIPE_BUF_FLAG_PACKET flag, which in turn +will tell the reader side to break the read at that boundary (and throw +away any partial packet contents that do not fit in the read buffer). + +End result: as long as you do writes less than PIPE_BUF in size (so that +the pipe doesn't have to split them up), you can now treat the pipe as a +packet interface, where each read() system call will read one packet at +a time. You can just use a sufficiently big read buffer (PIPE_BUF is +sufficient, since bigger than that doesn't guarantee atomicity anyway), +and the return value of the read() will naturally give you the size of +the packet. + +NOTE! We do not support zero-sized packets, and zero-sized reads and +writes to a pipe continue to be no-ops. Also note that big packets will +currently be split at write time, but that the size at which that +happens is not really specified (except that it's bigger than PIPE_BUF). +Currently that limit is the system page size, but we might want to +explicitly support bigger packets some day. + +The main user for this is going to be the autofs packet interface, +allowing us to stop having to care so deeply about exact packet sizes +(which have had bugs with 32/64-bit compatibility modes). But user +space can create packetized pipes with "pipe2(fd, O_DIRECT)", which will +fail with an EINVAL on kernels that do not support this interface. + +Tested-by: Michael Tokarev +Cc: Alan Cox +Cc: David Miller +Cc: Ian Kent +Cc: Thomas Meyer +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/pipe.c | 31 +++++++++++++++++++++++++++++-- + include/linux/pipe_fs_i.h | 1 + + 2 files changed, 30 insertions(+), 2 deletions(-) + +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -345,6 +345,16 @@ static const struct pipe_buf_operations + .get = generic_pipe_buf_get, + }; + ++static const struct pipe_buf_operations packet_pipe_buf_ops = { ++ .can_merge = 0, ++ .map = generic_pipe_buf_map, ++ .unmap = generic_pipe_buf_unmap, ++ .confirm = generic_pipe_buf_confirm, ++ .release = anon_pipe_buf_release, ++ .steal = generic_pipe_buf_steal, ++ .get = generic_pipe_buf_get, ++}; ++ + static ssize_t + pipe_read(struct kiocb *iocb, const struct iovec *_iov, + unsigned long nr_segs, loff_t pos) +@@ -406,6 +416,13 @@ redo: + ret += chars; + buf->offset += chars; + buf->len -= chars; ++ ++ /* Was it a packet buffer? Clean up and exit */ ++ if (buf->flags & PIPE_BUF_FLAG_PACKET) { ++ total_len = chars; ++ buf->len = 0; ++ } ++ + if (!buf->len) { + buf->ops = NULL; + ops->release(pipe, buf); +@@ -458,6 +475,11 @@ redo: + return ret; + } + ++static inline int is_packetized(struct file *file) ++{ ++ return (file->f_flags & O_DIRECT) != 0; ++} ++ + static ssize_t + pipe_write(struct kiocb *iocb, const struct iovec *_iov, + unsigned long nr_segs, loff_t ppos) +@@ -592,6 +614,11 @@ redo2: + buf->ops = &anon_pipe_buf_ops; + buf->offset = 0; + buf->len = chars; ++ buf->flags = 0; ++ if (is_packetized(filp)) { ++ buf->ops = &packet_pipe_buf_ops; ++ buf->flags = PIPE_BUF_FLAG_PACKET; ++ } + pipe->nrbufs = ++bufs; + pipe->tmp_page = NULL; + +@@ -1012,7 +1039,7 @@ struct file *create_write_pipe(int flags + goto err_dentry; + f->f_mapping = inode->i_mapping; + +- f->f_flags = O_WRONLY | (flags & O_NONBLOCK); ++ f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT)); + f->f_version = 0; + + return f; +@@ -1056,7 +1083,7 @@ int do_pipe_flags(int *fd, int flags) + int error; + int fdw, fdr; + +- if (flags & ~(O_CLOEXEC | O_NONBLOCK)) ++ if (flags & ~(O_CLOEXEC | O_NONBLOCK | O_DIRECT)) + return -EINVAL; + + fw = create_write_pipe(flags); +--- a/include/linux/pipe_fs_i.h ++++ b/include/linux/pipe_fs_i.h +@@ -8,6 +8,7 @@ + #define PIPE_BUF_FLAG_LRU 0x01 /* page is on the LRU */ + #define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */ + #define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */ ++#define PIPE_BUF_FLAG_PACKET 0x08 /* read() as a packet */ + + /** + * struct pipe_buffer - a linux kernel pipe buffer +From fcbf94b9dedd2ce08e798a99aafc94fec8668161 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Sat, 28 Apr 2012 08:29:56 -0700 +Subject: Revert "autofs: work around unhappy compat problem on x86-64" + +From: Linus Torvalds + +commit fcbf94b9dedd2ce08e798a99aafc94fec8668161 upstream. + +This reverts commit a32744d4abae24572eff7269bc17895c41bd0085. + +While that commit was technically the right thing to do, and made the +x86-64 compat mode work identically to native 32-bit mode (and thus +fixing the problem with a 32-bit systemd install on a 64-bit kernel), it +turns out that the automount binaries had workarounds for this compat +problem. + +Now, the workarounds are disgusting: doing an "uname()" to find out the +architecture of the kernel, and then comparing it for the 64-bit cases +and fixing up the size of the read() in automount for those. And they +were confused: it's not actually a generic 64-bit issue at all, it's +very much tied to just x86-64, which has different alignment for an +'u64' in 64-bit mode than in 32-bit mode. + +But the end result is that fixing the compat layer actually breaks the +case of a 32-bit automount on a x86-64 kernel. + +There are various approaches to fix this (including just doing a +"strcmp()" on current->comm and comparing it to "automount"), but I +think that I will do the one that teaches pipes about a special "packet +mode", which will allow user space to not have to care too deeply about +the padding at the end of the autofs packet. + +That change will make the compat workaround unnecessary, so let's revert +it first, and get automount working again in compat mode. The +packetized pipes will then fix autofs for systemd. + +Reported-and-requested-by: Michael Tokarev +Cc: Ian Kent +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/autofs4/autofs_i.h | 1 - + fs/autofs4/dev-ioctl.c | 1 - + fs/autofs4/inode.c | 2 -- + fs/autofs4/waitq.c | 22 +++------------------- + 4 files changed, 3 insertions(+), 23 deletions(-) + +--- a/fs/autofs4/autofs_i.h ++++ b/fs/autofs4/autofs_i.h +@@ -110,7 +110,6 @@ struct autofs_sb_info { + int sub_version; + int min_proto; + int max_proto; +- int compat_daemon; + unsigned long exp_timeout; + unsigned int type; + int reghost_enabled; +--- a/fs/autofs4/dev-ioctl.c ++++ b/fs/autofs4/dev-ioctl.c +@@ -385,7 +385,6 @@ static int autofs_dev_ioctl_setpipefd(st + sbi->pipefd = pipefd; + sbi->pipe = pipe; + sbi->catatonic = 0; +- sbi->compat_daemon = is_compat_task(); + } + out: + mutex_unlock(&sbi->wq_mutex); +--- a/fs/autofs4/inode.c ++++ b/fs/autofs4/inode.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include "autofs_i.h" + #include + +@@ -225,7 +224,6 @@ int autofs4_fill_super(struct super_bloc + set_autofs_type_indirect(&sbi->type); + sbi->min_proto = 0; + sbi->max_proto = 0; +- sbi->compat_daemon = is_compat_task(); + mutex_init(&sbi->wq_mutex); + mutex_init(&sbi->pipe_mutex); + spin_lock_init(&sbi->fs_lock); +--- a/fs/autofs4/waitq.c ++++ b/fs/autofs4/waitq.c +@@ -91,24 +91,7 @@ static int autofs4_write(struct autofs_s + + return (bytes > 0); + } +- +-/* +- * The autofs_v5 packet was misdesigned. +- * +- * The packets are identical on x86-32 and x86-64, but have different +- * alignment. Which means that 'sizeof()' will give different results. +- * Fix it up for the case of running 32-bit user mode on a 64-bit kernel. +- */ +-static noinline size_t autofs_v5_packet_size(struct autofs_sb_info *sbi) +-{ +- size_t pktsz = sizeof(struct autofs_v5_packet); +-#if defined(CONFIG_X86_64) && defined(CONFIG_COMPAT) +- if (sbi->compat_daemon > 0) +- pktsz -= 4; +-#endif +- return pktsz; +-} +- ++ + static void autofs4_notify_daemon(struct autofs_sb_info *sbi, + struct autofs_wait_queue *wq, + int type) +@@ -172,7 +155,8 @@ static void autofs4_notify_daemon(struct + { + struct autofs_v5_packet *packet = &pkt.v5_pkt.v5_packet; + +- pktsz = autofs_v5_packet_size(sbi); ++ pktsz = sizeof(*packet); ++ + packet->wait_queue_token = wq->wait_queue_token; + packet->len = wq->name.len; + memcpy(packet->name, wq->name.name, wq->name.len); +From fb2cf2c660971bea0ad86a9a5c19ad39eab61344 Mon Sep 17 00:00:00 2001 +From: "he, bo" +Date: Wed, 25 Apr 2012 19:59:21 +0800 +Subject: sched: Fix OOPS when build_sched_domains() percpu allocation fails + +From: "he, bo" + +commit fb2cf2c660971bea0ad86a9a5c19ad39eab61344 upstream. + +Under extreme memory used up situations, percpu allocation +might fail. We hit it when system goes to suspend-to-ram, +causing a kworker panic: + + EIP: [] build_sched_domains+0x23a/0xad0 + Kernel panic - not syncing: Fatal exception + Pid: 3026, comm: kworker/u:3 + 3.0.8-137473-gf42fbef #1 + + Call Trace: + [] panic+0x66/0x16c + [...] + [] partition_sched_domains+0x287/0x4b0 + [] cpuset_update_active_cpus+0x1fe/0x210 + [] cpuset_cpu_inactive+0x1d/0x30 + [...] + +With this fix applied build_sched_domains() will return -ENOMEM and +the suspend attempt fails. + +Signed-off-by: he, bo +Reviewed-by: Zhang, Yanmin +Reviewed-by: Srivatsa S. Bhat +Signed-off-by: Peter Zijlstra +Cc: Linus Torvalds +Cc: Andrew Morton +Link: http://lkml.kernel.org/r/1335355161.5892.17.camel@hebo +[ So, we fail to deallocate a CPU because we cannot allocate RAM :-/ + I don't like that kind of sad behavior but nevertheless it should + not crash under high memory load. ] +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/sched/core.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -6334,16 +6334,26 @@ static void __sdt_free(const struct cpum + struct sd_data *sdd = &tl->data; + + for_each_cpu(j, cpu_map) { +- struct sched_domain *sd = *per_cpu_ptr(sdd->sd, j); +- if (sd && (sd->flags & SD_OVERLAP)) +- free_sched_groups(sd->groups, 0); +- kfree(*per_cpu_ptr(sdd->sd, j)); +- kfree(*per_cpu_ptr(sdd->sg, j)); +- kfree(*per_cpu_ptr(sdd->sgp, j)); ++ struct sched_domain *sd; ++ ++ if (sdd->sd) { ++ sd = *per_cpu_ptr(sdd->sd, j); ++ if (sd && (sd->flags & SD_OVERLAP)) ++ free_sched_groups(sd->groups, 0); ++ kfree(*per_cpu_ptr(sdd->sd, j)); ++ } ++ ++ if (sdd->sg) ++ kfree(*per_cpu_ptr(sdd->sg, j)); ++ if (sdd->sgp) ++ kfree(*per_cpu_ptr(sdd->sgp, j)); + } + free_percpu(sdd->sd); ++ sdd->sd = NULL; + free_percpu(sdd->sg); ++ sdd->sg = NULL; + free_percpu(sdd->sgp); ++ sdd->sgp = NULL; + } + } + +From db4c75cbebd7e5910cd3bcb6790272fcc3042857 Mon Sep 17 00:00:00 2001 +From: Steven Rostedt +Date: Thu, 19 Apr 2012 10:31:47 -0400 +Subject: tracing: Fix stacktrace of latency tracers (irqsoff and friends) + +From: Steven Rostedt + +commit db4c75cbebd7e5910cd3bcb6790272fcc3042857 upstream. + +While debugging a latency with someone on IRC (mirage335) on #linux-rt (OFTC), +we discovered that the stacktrace output of the latency tracers +(preemptirqsoff) was empty. + +This bug was caused by the creation of the dynamic length stack trace +again (like commit 12b5da3 "tracing: Fix ent_size in trace output" was). + +This bug is caused by the latency tracers requiring the next event +to determine the time between the current event and the next. But by +grabbing the next event, the iter->ent_size is set to the next event +instead of the current one. As the stacktrace event is the last event, +this makes the ent_size zero and causes nothing to be printed for +the stack trace. The dynamic stacktrace uses the ent_size to determine +how much of the stack can be printed. The ent_size of zero means +no stack. + +The simple fix is to save the iter->ent_size before finding the next event. + +Note, mirage335 asked to remain anonymous from LKML and git, so I will +not add the Reported-by and Tested-by tags, even though he did report +the issue and tested the fix. + +Signed-off-by: Steven Rostedt +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/trace/trace_output.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/kernel/trace/trace_output.c ++++ b/kernel/trace/trace_output.c +@@ -650,6 +650,8 @@ int trace_print_lat_context(struct trace + { + u64 next_ts; + int ret; ++ /* trace_find_next_entry will reset ent_size */ ++ int ent_size = iter->ent_size; + struct trace_seq *s = &iter->seq; + struct trace_entry *entry = iter->ent, + *next_entry = trace_find_next_entry(iter, NULL, +@@ -658,6 +660,9 @@ int trace_print_lat_context(struct trace + unsigned long abs_usecs = ns2usecs(iter->ts - iter->tr->time_start); + unsigned long rel_usecs; + ++ /* Restore the original ent_size */ ++ iter->ent_size = ent_size; ++ + if (!next_entry) + next_ts = iter->ts; + rel_usecs = ns2usecs(next_ts - iter->ts); +From 5c22837adca7c30b66121cf18ad3e160134268d4 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Thu, 26 Apr 2012 21:59:10 +0200 +Subject: USB: cdc-wdm: fix race leading leading to memory corruption +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Oliver Neukum + +commit 5c22837adca7c30b66121cf18ad3e160134268d4 upstream. + +This patch fixes a race whereby a pointer to a buffer +would be overwritten while the buffer was in use leading +to a double free and a memory leak. This causes crashes. +This bug was introduced in 2.6.34 + +Signed-off-by: Oliver Neukum +Tested-by: Bjørn Mork +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/class/cdc-wdm.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/usb/class/cdc-wdm.c ++++ b/drivers/usb/class/cdc-wdm.c +@@ -108,8 +108,9 @@ static void wdm_out_callback(struct urb + spin_lock(&desc->iuspin); + desc->werr = urb->status; + spin_unlock(&desc->iuspin); +- clear_bit(WDM_IN_USE, &desc->flags); + kfree(desc->outbuf); ++ desc->outbuf = NULL; ++ clear_bit(WDM_IN_USE, &desc->flags); + wake_up(&desc->wait); + } + +@@ -312,7 +313,7 @@ static ssize_t wdm_write + if (we < 0) + return -EIO; + +- desc->outbuf = buf = kmalloc(count, GFP_KERNEL); ++ buf = kmalloc(count, GFP_KERNEL); + if (!buf) { + rv = -ENOMEM; + goto outnl; +@@ -376,10 +377,12 @@ static ssize_t wdm_write + req->wIndex = desc->inum; + req->wLength = cpu_to_le16(count); + set_bit(WDM_IN_USE, &desc->flags); ++ desc->outbuf = buf; + + rv = usb_submit_urb(desc->command, GFP_KERNEL); + if (rv < 0) { + kfree(buf); ++ desc->outbuf = NULL; + clear_bit(WDM_IN_USE, &desc->flags); + dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv); + } else { +From 151b61284776be2d6f02d48c23c3625678960b97 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Tue, 24 Apr 2012 14:07:22 -0400 +Subject: USB: EHCI: fix crash during suspend on ASUS computers + +From: Alan Stern + +commit 151b61284776be2d6f02d48c23c3625678960b97 upstream. + +This patch (as1545) fixes a problem affecting several ASUS computers: +The machine crashes or corrupts memory when going into suspend if the +ehci-hcd driver is bound to any controllers. Users have been forced +to unbind or unload ehci-hcd before putting their systems to sleep. + +After extensive testing, it was determined that the machines don't +like going into suspend when any EHCI controllers are in the PCI D3 +power state. Presumably this is a firmware bug, but there's nothing +we can do about it except to avoid putting the controllers in D3 +during system sleep. + +The patch adds a new flag to indicate whether the problem is present, +and avoids changing the controller's power state if the flag is set. +Runtime suspend is unaffected; this matters only for system suspend. +However as a side effect, the controller will not respond to remote +wakeup requests while the system is asleep. Hence USB wakeup is not +functional -- but of course, this is already true in the current state +of affairs. + +This fixes Bugzilla #42728. + +Signed-off-by: Alan Stern +Tested-by: Steven Rostedt +Tested-by: Andrey Rahmatullin +Tested-by: Oleksij Rempel (fishor) +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hcd-pci.c | 9 +++++++++ + drivers/usb/host/ehci-pci.c | 8 ++++++++ + include/linux/usb/hcd.h | 2 ++ + 3 files changed, 19 insertions(+) + +--- a/drivers/usb/core/hcd-pci.c ++++ b/drivers/usb/core/hcd-pci.c +@@ -491,6 +491,15 @@ static int hcd_pci_suspend_noirq(struct + + pci_save_state(pci_dev); + ++ /* ++ * Some systems crash if an EHCI controller is in D3 during ++ * a sleep transition. We have to leave such controllers in D0. ++ */ ++ if (hcd->broken_pci_sleep) { ++ dev_dbg(dev, "Staying in PCI D0\n"); ++ return retval; ++ } ++ + /* If the root hub is dead rather than suspended, disallow remote + * wakeup. usb_hc_died() should ensure that both hosts are marked as + * dying, so we only need to check the primary roothub. +--- a/drivers/usb/host/ehci-pci.c ++++ b/drivers/usb/host/ehci-pci.c +@@ -144,6 +144,14 @@ static int ehci_pci_setup(struct usb_hcd + hcd->has_tt = 1; + tdi_reset(ehci); + } ++ if (pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK) { ++ /* EHCI #1 or #2 on 6 Series/C200 Series chipset */ ++ if (pdev->device == 0x1c26 || pdev->device == 0x1c2d) { ++ ehci_info(ehci, "broken D3 during system sleep on ASUS\n"); ++ hcd->broken_pci_sleep = 1; ++ device_set_wakeup_capable(&pdev->dev, false); ++ } ++ } + break; + case PCI_VENDOR_ID_TDI: + if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { +--- a/include/linux/usb/hcd.h ++++ b/include/linux/usb/hcd.h +@@ -126,6 +126,8 @@ struct usb_hcd { + unsigned wireless:1; /* Wireless USB HCD */ + unsigned authorized_default:1; + unsigned has_tt:1; /* Integrated TT in root hub */ ++ unsigned broken_pci_sleep:1; /* Don't put the ++ controller in PCI-D3 for system sleep */ + + int irq; /* irq allocated */ + void __iomem *regs; /* device memory/io */ +From 15b120d67019d691e4389372967332d74a80522a Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Wed, 18 Apr 2012 13:59:30 +0300 +Subject: usb: gadget: dummy: do not call pullup() on udc_stop() + +From: Felipe Balbi + +commit 15b120d67019d691e4389372967332d74a80522a upstream. + +pullup() is already called properly by udc-core.c and +there's no need to call it from udc_stop(), in fact that +will cause issues. + +Reviewed-by: Alexander Shishkin +Acked-by: Alan Stern +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/dummy_hcd.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/usb/gadget/dummy_hcd.c ++++ b/drivers/usb/gadget/dummy_hcd.c +@@ -924,7 +924,6 @@ static int dummy_udc_stop(struct usb_gad + + dum->driver = NULL; + +- dummy_pullup(&dum->gadget, 0); + return 0; + } + +From c85dcdac5852295cf6822f5c4331a6ddab72581f Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Wed, 11 Apr 2012 16:09:10 -0400 +Subject: USB: gadget: storage gadgets send wrong error code for unknown commands + +From: Alan Stern + +commit c85dcdac5852295cf6822f5c4331a6ddab72581f upstream. + +This patch (as1539) fixes a minor bug in the mass-storage gadget +drivers. When an unknown command is received, the error code sent +back is "Invalid Field in CDB" rather than "Invalid Command". This is +because the bitmask of CDB bytes allowed to be nonzero is incorrect. + +When handling an unknown command, we don't care which command bytes +are nonzero. All the bits in the mask should be set, not just eight +of them. + +Signed-off-by: Alan Stern +CC: +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/f_mass_storage.c | 2 +- + drivers/usb/gadget/file_storage.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/usb/gadget/f_mass_storage.c ++++ b/drivers/usb/gadget/f_mass_storage.c +@@ -2190,7 +2190,7 @@ unknown_cmnd: + common->data_size_from_cmnd = 0; + sprintf(unknown, "Unknown x%02x", common->cmnd[0]); + reply = check_command(common, common->cmnd_size, +- DATA_DIR_UNKNOWN, 0xff, 0, unknown); ++ DATA_DIR_UNKNOWN, ~0, 0, unknown); + if (reply == 0) { + common->curlun->sense_data = SS_INVALID_COMMAND; + reply = -EINVAL; +--- a/drivers/usb/gadget/file_storage.c ++++ b/drivers/usb/gadget/file_storage.c +@@ -2579,7 +2579,7 @@ static int do_scsi_command(struct fsg_de + fsg->data_size_from_cmnd = 0; + sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]); + if ((reply = check_command(fsg, fsg->cmnd_size, +- DATA_DIR_UNKNOWN, 0xff, 0, unknown)) == 0) { ++ DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) { + fsg->curlun->sense_data = SS_INVALID_COMMAND; + reply = -EINVAL; + } +From 6f6543f53f9ce136e01d7114bf6f0818ca54fb41 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Tue, 24 Apr 2012 11:29:42 +0200 +Subject: usb gadget: uvc: uvc_request_data::length field must be signed + +From: Laurent Pinchart + +commit 6f6543f53f9ce136e01d7114bf6f0818ca54fb41 upstream. + +The field is used to pass the UVC request data length, but can also be +used to signal an error when setting it to a negative value. Switch from +unsigned int to __s32. + +Reported-by: Fernandez Gonzalo +Signed-off-by: Laurent Pinchart +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/uvc.h | 2 +- + drivers/usb/gadget/uvc_v4l2.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/usb/gadget/uvc.h ++++ b/drivers/usb/gadget/uvc.h +@@ -28,7 +28,7 @@ + + struct uvc_request_data + { +- unsigned int length; ++ __s32 length; + __u8 data[60]; + }; + +--- a/drivers/usb/gadget/uvc_v4l2.c ++++ b/drivers/usb/gadget/uvc_v4l2.c +@@ -39,7 +39,7 @@ uvc_send_response(struct uvc_device *uvc + if (data->length < 0) + return usb_ep_set_halt(cdev->gadget->ep0); + +- req->length = min(uvc->event_length, data->length); ++ req->length = min_t(unsigned int, uvc->event_length, data->length); + req->zero = data->length < uvc->event_length; + req->dma = DMA_ADDR_INVALID; + +From cbf2829b61c136edcba302a5e1b6b40e97d32c00 Mon Sep 17 00:00:00 2001 +From: Bryan O'Donoghue +Date: Wed, 18 Apr 2012 17:37:39 +0100 +Subject: x86, apic: APIC code touches invalid MSR on P5 class machines + +From: Bryan O'Donoghue + +commit cbf2829b61c136edcba302a5e1b6b40e97d32c00 upstream. + +Current APIC code assumes MSR_IA32_APICBASE is present for all systems. +Pentium Classic P5 and friends didn't have this MSR. MSR_IA32_APICBASE +was introduced as an architectural MSR by Intel @ P6. + +Code paths that can touch this MSR invalidly are when vendor == Intel && +cpu-family == 5 and APIC bit is set in CPUID - or when you simply pass +lapic on the kernel command line, on a P5. + +The below patch stops Linux incorrectly interfering with the +MSR_IA32_APICBASE for P5 class machines. Other code paths exist that +touch the MSR - however those paths are not currently reachable for a +conformant P5. + +Signed-off-by: Bryan O'Donoghue +Link: http://lkml.kernel.org/r/4F8EEDD3.1080404@linux.intel.com +Signed-off-by: H. Peter Anvin +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/apic/apic.c | 34 ++++++++++++++++++++-------------- + 1 file changed, 20 insertions(+), 14 deletions(-) + +--- a/arch/x86/kernel/apic/apic.c ++++ b/arch/x86/kernel/apic/apic.c +@@ -1632,9 +1632,11 @@ static int __init apic_verify(void) + mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; + + /* The BIOS may have set up the APIC at some other address */ +- rdmsr(MSR_IA32_APICBASE, l, h); +- if (l & MSR_IA32_APICBASE_ENABLE) +- mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; ++ if (boot_cpu_data.x86 >= 6) { ++ rdmsr(MSR_IA32_APICBASE, l, h); ++ if (l & MSR_IA32_APICBASE_ENABLE) ++ mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; ++ } + + pr_info("Found and enabled local APIC!\n"); + return 0; +@@ -1652,13 +1654,15 @@ int __init apic_force_enable(unsigned lo + * MSR. This can only be done in software for Intel P6 or later + * and AMD K7 (Model > 1) or later. + */ +- rdmsr(MSR_IA32_APICBASE, l, h); +- if (!(l & MSR_IA32_APICBASE_ENABLE)) { +- pr_info("Local APIC disabled by BIOS -- reenabling.\n"); +- l &= ~MSR_IA32_APICBASE_BASE; +- l |= MSR_IA32_APICBASE_ENABLE | addr; +- wrmsr(MSR_IA32_APICBASE, l, h); +- enabled_via_apicbase = 1; ++ if (boot_cpu_data.x86 >= 6) { ++ rdmsr(MSR_IA32_APICBASE, l, h); ++ if (!(l & MSR_IA32_APICBASE_ENABLE)) { ++ pr_info("Local APIC disabled by BIOS -- reenabling.\n"); ++ l &= ~MSR_IA32_APICBASE_BASE; ++ l |= MSR_IA32_APICBASE_ENABLE | addr; ++ wrmsr(MSR_IA32_APICBASE, l, h); ++ enabled_via_apicbase = 1; ++ } + } + return apic_verify(); + } +@@ -2204,10 +2208,12 @@ static void lapic_resume(void) + * FIXME! This will be wrong if we ever support suspend on + * SMP! We'll need to do this as part of the CPU restore! + */ +- rdmsr(MSR_IA32_APICBASE, l, h); +- l &= ~MSR_IA32_APICBASE_BASE; +- l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; +- wrmsr(MSR_IA32_APICBASE, l, h); ++ if (boot_cpu_data.x86 >= 6) { ++ rdmsr(MSR_IA32_APICBASE, l, h); ++ l &= ~MSR_IA32_APICBASE_BASE; ++ l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; ++ wrmsr(MSR_IA32_APICBASE, l, h); ++ } + } + + maxlvt = lapic_get_maxlvt(); +From 283c1f2558ef4a4411fe908364b15b73b6ab44cf Mon Sep 17 00:00:00 2001 +From: Andreas Herrmann +Date: Thu, 12 Apr 2012 16:51:57 +0200 +Subject: x86, microcode: Ensure that module is only loaded on supported AMD CPUs + +From: Andreas Herrmann + +commit 283c1f2558ef4a4411fe908364b15b73b6ab44cf upstream. + +Exit early when there's no support for a particular CPU family. Also, +fixup the "no support for this CPU vendor" to be issued only when the +driver is attempted to be loaded on an unsupported vendor. + +Cc: Tigran Aivazian +Signed-off-by: Andreas Herrmann +Acked-by: Greg Kroah-Hartman +Link: http://lkml.kernel.org/r/20120411163849.GE4794@alberich.amd.com +[Boris: add a commit msg because Andreas is lazy] +Signed-off-by: Borislav Petkov +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/microcode_amd.c | 12 +++++++----- + arch/x86/kernel/microcode_core.c | 6 +++--- + 2 files changed, 10 insertions(+), 8 deletions(-) + +--- a/arch/x86/kernel/microcode_amd.c ++++ b/arch/x86/kernel/microcode_amd.c +@@ -82,11 +82,6 @@ static int collect_cpu_info_amd(int cpu, + { + struct cpuinfo_x86 *c = &cpu_data(cpu); + +- if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { +- pr_warning("CPU%d: family %d not supported\n", cpu, c->x86); +- return -1; +- } +- + csig->rev = c->microcode; + pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev); + +@@ -380,6 +375,13 @@ static struct microcode_ops microcode_am + + struct microcode_ops * __init init_amd_microcode(void) + { ++ struct cpuinfo_x86 *c = &cpu_data(0); ++ ++ if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { ++ pr_warning("AMD CPU family 0x%x not supported\n", c->x86); ++ return NULL; ++ } ++ + patch = (void *)get_zeroed_page(GFP_KERNEL); + if (!patch) + return NULL; +--- a/arch/x86/kernel/microcode_core.c ++++ b/arch/x86/kernel/microcode_core.c +@@ -511,11 +511,11 @@ static int __init microcode_init(void) + microcode_ops = init_intel_microcode(); + else if (c->x86_vendor == X86_VENDOR_AMD) + microcode_ops = init_amd_microcode(); +- +- if (!microcode_ops) { ++ else + pr_err("no support for this CPU vendor\n"); ++ ++ if (!microcode_ops) + return -ENODEV; +- } + + microcode_pdev = platform_device_register_simple("microcode", -1, + NULL, 0); +From a956bd6f8583326b18348ab1452b4686778f785d Mon Sep 17 00:00:00 2001 +From: Andreas Herrmann +Date: Thu, 12 Apr 2012 16:48:01 +0200 +Subject: x86, microcode: Fix sysfs warning during module unload on unsupported CPUs + +From: Andreas Herrmann + +commit a956bd6f8583326b18348ab1452b4686778f785d upstream. + +Loading the microcode driver on an unsupported CPU and subsequently +unloading the driver causes + + WARNING: at fs/sysfs/group.c:138 mc_device_remove+0x5f/0x70 [microcode]() + Hardware name: 01972NG + sysfs group ffffffffa00013d0 not found for kobject 'cpu0' + Modules linked in: snd_hda_codec_hdmi snd_hda_codec_conexant snd_hda_intel btusb snd_hda_codec bluetooth thinkpad_acpi rfkill microcode(-) [last unloaded: cfg80211] + Pid: 4560, comm: modprobe Not tainted 3.4.0-rc2-00002-g258f742 #5 + Call Trace: + [] ? warn_slowpath_common+0x7b/0xc0 + [] ? warn_slowpath_fmt+0x45/0x50 + [] ? sysfs_remove_group+0x34/0x120 + [] ? mc_device_remove+0x5f/0x70 [microcode] + [] ? subsys_interface_unregister+0x69/0xa0 + [] ? mutex_lock+0x16/0x40 + [] ? microcode_exit+0x50/0x92 [microcode] + [] ? sys_delete_module+0x16d/0x260 + [] ? wait_iff_congested+0x45/0x110 + [] ? page_fault+0x1f/0x30 + [] ? system_call_fastpath+0x16/0x1b + +on recent kernels. + +This is due to commit 8a25a2fd126c ("cpu: convert 'cpu' and +'machinecheck' sysdev_class to a regular subsystem") which renders +commit 6c53cbfced04 ("x86, microcode: Correct sysdev_add error path") +useless. + +See http://marc.info/?l=linux-kernel&m=133416246406478 + +Avoid above warning by restoring the old driver behaviour before +6c53cbfced04 ("x86, microcode: Correct sysdev_add error path"). + +Cc: Tigran Aivazian +Signed-off-by: Andreas Herrmann +Acked-by: Greg Kroah-Hartman +Link: http://lkml.kernel.org/r/20120411163849.GE4794@alberich.amd.com +Signed-off-by: Borislav Petkov +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/microcode_core.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/arch/x86/kernel/microcode_core.c ++++ b/arch/x86/kernel/microcode_core.c +@@ -418,10 +418,8 @@ static int mc_device_add(struct device * + if (err) + return err; + +- if (microcode_init_cpu(cpu) == UCODE_ERROR) { +- sysfs_remove_group(&dev->kobj, &mc_attr_group); ++ if (microcode_init_cpu(cpu) == UCODE_ERROR) + return -EINVAL; +- } + + return err; + } +From 68894632afb2729a1d8785c877840953894c7283 Mon Sep 17 00:00:00 2001 +From: Andreas Herrmann +Date: Mon, 2 Apr 2012 18:06:48 +0200 +Subject: x86/platform: Remove incorrect error message in x86_default_fixup_cpu_id() + +From: Andreas Herrmann + +commit 68894632afb2729a1d8785c877840953894c7283 upstream. + +It's only called from amd.c:srat_detect_node(). The introduced +condition for calling the fixup code is true for all AMD +multi-node processors, e.g. Magny-Cours and Interlagos. There we +have 2 NUMA nodes on one socket. Thus there are cores having +different numa-node-id but with equal phys_proc_id. + +There is no point to print error messages in such a situation. + +The confusing/misleading error message was introduced with +commit 64be4c1c2428e148de6081af235e2418e6a66dda ("x86: Add +x86_init platform override to fix up NUMA core numbering"). + +Remove the default fixup function (especially the error message) +and replace it by a NULL pointer check, move the +Numascale-specific condition for calling the fixup into the +fixup-function itself and slightly adapt the comment. + +Signed-off-by: Andreas Herrmann +Acked-by: Borislav Petkov +Cc: +Cc: +Cc: +Link: http://lkml.kernel.org/r/20120402160648.GR27684@alberich.amd.com +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/include/asm/x86_init.h | 1 - + arch/x86/kernel/apic/apic_numachip.c | 7 +++++-- + arch/x86/kernel/cpu/amd.c | 7 ++++--- + arch/x86/kernel/cpu/common.c | 9 --------- + arch/x86/kernel/x86_init.c | 1 - + 5 files changed, 9 insertions(+), 16 deletions(-) + +--- a/arch/x86/include/asm/x86_init.h ++++ b/arch/x86/include/asm/x86_init.h +@@ -189,6 +189,5 @@ extern struct x86_msi_ops x86_msi; + + extern void x86_init_noop(void); + extern void x86_init_uint_noop(unsigned int unused); +-extern void x86_default_fixup_cpu_id(struct cpuinfo_x86 *c, int node); + + #endif +--- a/arch/x86/kernel/apic/apic_numachip.c ++++ b/arch/x86/kernel/apic/apic_numachip.c +@@ -201,8 +201,11 @@ static void __init map_csrs(void) + + static void fixup_cpu_id(struct cpuinfo_x86 *c, int node) + { +- c->phys_proc_id = node; +- per_cpu(cpu_llc_id, smp_processor_id()) = node; ++ ++ if (c->phys_proc_id != node) { ++ c->phys_proc_id = node; ++ per_cpu(cpu_llc_id, smp_processor_id()) = node; ++ } + } + + static int __init numachip_system_init(void) +--- a/arch/x86/kernel/cpu/amd.c ++++ b/arch/x86/kernel/cpu/amd.c +@@ -352,10 +352,11 @@ static void __cpuinit srat_detect_node(s + node = per_cpu(cpu_llc_id, cpu); + + /* +- * If core numbers are inconsistent, it's likely a multi-fabric platform, +- * so invoke platform-specific handler ++ * On multi-fabric platform (e.g. Numascale NumaChip) a ++ * platform-specific handler needs to be called to fixup some ++ * IDs of the CPU. + */ +- if (c->phys_proc_id != node) ++ if (x86_cpuinit.fixup_cpu_id) + x86_cpuinit.fixup_cpu_id(c, node); + + if (!node_online(node)) { +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -1163,15 +1163,6 @@ static void dbg_restore_debug_regs(void) + #endif /* ! CONFIG_KGDB */ + + /* +- * Prints an error where the NUMA and configured core-number mismatch and the +- * platform didn't override this to fix it up +- */ +-void __cpuinit x86_default_fixup_cpu_id(struct cpuinfo_x86 *c, int node) +-{ +- pr_err("NUMA core number %d differs from configured core number %d\n", node, c->phys_proc_id); +-} +- +-/* + * cpu_init() initializes state that is per-CPU. Some data is already + * initialized (naturally) in the bootstrap process, such as the GDT + * and IDT. We reload them nevertheless, this function acts as a +--- a/arch/x86/kernel/x86_init.c ++++ b/arch/x86/kernel/x86_init.c +@@ -92,7 +92,6 @@ struct x86_init_ops x86_init __initdata + + struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = { + .setup_percpu_clockev = setup_secondary_APIC_clock, +- .fixup_cpu_id = x86_default_fixup_cpu_id, + }; + + static void default_nmi_init(void) { }; +From 7eb7ce4d2e8991aff4ecb71a81949a907ca755ac Mon Sep 17 00:00:00 2001 +From: David Vrabel +Date: Thu, 26 Apr 2012 19:44:06 +0100 +Subject: xen: correctly check for pending events when restoring irq flags + +From: David Vrabel + +commit 7eb7ce4d2e8991aff4ecb71a81949a907ca755ac upstream. + +In xen_restore_fl_direct(), xen_force_evtchn_callback() was being +called even if no events were pending. This resulted in (depending on +workload) about a 100 times as many xen_version hypercalls as +necessary. + +Fix this by correcting the sense of the conditional jump. + +This seems to give a significant performance benefit for some +workloads. + +There is some subtle tricksy "..since the check here is trying to +check both pending and masked in a single cmpw, but I think this is +correct. It will call check_events now only when the combined +mask+pending word is 0x0001 (aka unmasked, pending)." (Ian) + +Acked-by: Ian Campbell +Signed-off-by: David Vrabel +Signed-off-by: Konrad Rzeszutek Wilk +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/xen/xen-asm.S | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/x86/xen/xen-asm.S ++++ b/arch/x86/xen/xen-asm.S +@@ -96,7 +96,7 @@ ENTRY(xen_restore_fl_direct) + + /* check for unmasked and pending */ + cmpw $0x0001, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_pending +- jz 1f ++ jnz 1f + 2: call check_events + 1: + ENDPATCH(xen_restore_fl_direct) +From cf405ae612b0f7e2358db7ff594c0e94846137aa Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Thu, 26 Apr 2012 13:50:03 -0400 +Subject: xen/smp: Fix crash when booting with ACPI hotplug CPUs. + +From: Konrad Rzeszutek Wilk + +commit cf405ae612b0f7e2358db7ff594c0e94846137aa upstream. + +When we boot on a machine that can hotplug CPUs and we +are using 'dom0_max_vcpus=X' on the Xen hypervisor line +to clip the amount of CPUs available to the initial domain, +we get this: + +(XEN) Command line: com1=115200,8n1 dom0_mem=8G noreboot dom0_max_vcpus=8 sync_console mce_verbosity=verbose console=com1,vga loglvl=all guest_loglvl=all +.. snip.. +DMI: Intel Corporation S2600CP/S2600CP, BIOS SE5C600.86B.99.99.x032.072520111118 07/25/2011 +.. snip. +SMP: Allowing 64 CPUs, 32 hotplug CPUs +installing Xen timer for CPU 7 +cpu 7 spinlock event irq 361 +NMI watchdog: disabled (cpu7): hardware events not enabled +Brought up 8 CPUs +.. snip.. + [acpi processor finds the CPUs are not initialized and starts calling + arch_register_cpu, which creates /sys/devices/system/cpu/cpu8/online] +CPU 8 got hotplugged +CPU 9 got hotplugged +CPU 10 got hotplugged +.. snip.. +initcall 1_acpi_battery_init_async+0x0/0x1b returned 0 after 406 usecs +calling erst_init+0x0/0x2bb @ 1 + + [and the scheduler sticks newly started tasks on the new CPUs, but + said CPUs cannot be initialized b/c the hypervisor has limited the + amount of vCPUS to 8 - as per the dom0_max_vcpus=8 flag. + The spinlock tries to kick the other CPU, but the structure for that + is not initialized and we crash.] +BUG: unable to handle kernel paging request at fffffffffffffed8 +IP: [] xen_spin_lock+0x29/0x60 +PGD 180d067 PUD 180e067 PMD 0 +Oops: 0002 [#1] SMP +CPU 7 +Modules linked in: + +Pid: 1, comm: swapper/0 Not tainted 3.4.0-rc2upstream-00001-gf5154e8 #1 Intel Corporation S2600CP/S2600CP +RIP: e030:[] [] xen_spin_lock+0x29/0x60 +RSP: e02b:ffff8801fb9b3a70 EFLAGS: 00010282 + +With this patch, we cap the amount of vCPUS that the initial domain +can run, to exactly what dom0_max_vcpus=X has specified. + +In the future, if there is a hypercall that will allow a running +domain to expand past its initial set of vCPUS, this patch should +be re-evaluated. + +Signed-off-by: Konrad Rzeszutek Wilk +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/xen/smp.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/arch/x86/xen/smp.c ++++ b/arch/x86/xen/smp.c +@@ -172,6 +172,7 @@ static void __init xen_fill_possible_map + static void __init xen_filter_cpu_maps(void) + { + int i, rc; ++ unsigned int subtract = 0; + + if (!xen_initial_domain()) + return; +@@ -186,8 +187,22 @@ static void __init xen_filter_cpu_maps(v + } else { + set_cpu_possible(i, false); + set_cpu_present(i, false); ++ subtract++; + } + } ++#ifdef CONFIG_HOTPLUG_CPU ++ /* This is akin to using 'nr_cpus' on the Linux command line. ++ * Which is OK as when we use 'dom0_max_vcpus=X' we can only ++ * have up to X, while nr_cpu_ids is greater than X. This ++ * normally is not a problem, except when CPU hotplugging ++ * is involved and then there might be more than X CPUs ++ * in the guest - which will not work as there is no ++ * hypercall to expand the max number of VCPUs an already ++ * running guest has. So cap it up to X. */ ++ if (subtract) ++ nr_cpu_ids = nr_cpu_ids - subtract; ++#endif ++ + } + + static void __init xen_smp_prepare_boot_cpu(void) diff --git a/x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch b/x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch deleted file mode 100644 index d69317316..000000000 --- a/x86-microcode-Ensure-that-module-is-only-loaded-for-supported-AMD-CPUs.patch +++ /dev/null @@ -1,163 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Borislav Petkov -Newsgroups: gmane.linux.kernel -Subject: [PATCH 2/2] x86, microcode: Ensure that module is only loaded for -Date: Thu, 12 Apr 2012 18:34:22 +0200 -Lines: 80 -Approved: news@gmane.org -Message-ID: <20120412163422.GM24549@aftab> -References: <20120411163849.GE4794@alberich.amd.com> - <20120411200601.GC12288@kroah.com> - <20120411201053.GF18114@aftab> - <20120412162351.GJ24549@aftab> -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset="us-ascii" -X-Trace: dough.gmane.org 1334248500 15307 80.91.229.3 (12 Apr 2012 16:35:00 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Thu, 12 Apr 2012 16:35:00 +0000 (UTC) -Cc: Andreas Herrmann , - Kay Sievers , - Dave Jones , -To: Greg Kroah-Hartman -Original-X-From: linux-kernel-owner@vger.kernel.org Thu Apr 12 18:34:59 2012 -Return-path: -Envelope-to: glk-linux-kernel-3@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1SIMz4-0008MV-3g - for glk-linux-kernel-3@plane.gmane.org; Thu, 12 Apr 2012 18:34:58 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S965760Ab2DLQep (ORCPT ); - Thu, 12 Apr 2012 12:34:45 -0400 -Original-Received: from db3ehsobe002.messaging.microsoft.com ([213.199.154.140]:56919 - "EHLO db3outboundpool.messaging.microsoft.com" rhost-flags-OK-OK-OK-OK) - by vger.kernel.org with ESMTP id S965553Ab2DLQen (ORCPT - ); - Thu, 12 Apr 2012 12:34:43 -0400 -Original-Received: from mail2-db3-R.bigfish.com (10.3.81.239) by - DB3EHSOBE005.bigfish.com (10.3.84.25) with Microsoft SMTP Server id - 14.1.225.23; Thu, 12 Apr 2012 16:34:41 +0000 -Original-Received: from mail2-db3 (localhost [127.0.0.1]) by mail2-db3-R.bigfish.com - (Postfix) with ESMTP id E4EF14404B4; Thu, 12 Apr 2012 16:34:41 +0000 (UTC) -X-SpamScore: 0 -X-BigFish: VPS0(zzzz1202hzz8275bh8275dhz2dh668h839h944hd25hd2bh) -X-Forefront-Antispam-Report: CIP:163.181.249.108;KIP:(null);UIP:(null);IPV:NLI;H:ausb3twp01.amd.com;RD:none;EFVD:NLI -Original-Received: from mail2-db3 (localhost.localdomain [127.0.0.1]) by mail2-db3 - (MessageSwitch) id 1334248479906480_3860; Thu, 12 Apr 2012 16:34:39 +0000 - (UTC) -Original-Received: from DB3EHSMHS005.bigfish.com (unknown [10.3.81.241]) by - mail2-db3.bigfish.com (Postfix) with ESMTP id CEB76400A4; Thu, 12 Apr 2012 - 16:34:39 +0000 (UTC) -Original-Received: from ausb3twp01.amd.com (163.181.249.108) by - DB3EHSMHS005.bigfish.com (10.3.87.105) with Microsoft SMTP Server id - 14.1.225.23; Thu, 12 Apr 2012 16:34:38 +0000 -X-WSS-ID: 0M2DKPO-01-CNU-02 -X-M-MSG: -Original-Received: from sausexedgep02.amd.com (sausexedgep02-ext.amd.com - [163.181.249.73]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No - client certificate requested) by ausb3twp01.amd.com (Axway MailGate 3.8.1) - with ESMTP id 2C1D81028100; Thu, 12 Apr 2012 11:34:36 -0500 (CDT) -Original-Received: from SAUSEXDAG02.amd.com (163.181.55.2) by sausexedgep02.amd.com - (163.181.36.59) with Microsoft SMTP Server (TLS) id 8.3.192.1; Thu, 12 Apr - 2012 11:34:51 -0500 -Original-Received: from storexhtp01.amd.com (172.24.4.3) by sausexdag02.amd.com - (163.181.55.2) with Microsoft SMTP Server (TLS) id 14.1.323.3; Thu, 12 Apr - 2012 11:34:36 -0500 -Original-Received: from gwo.osrc.amd.com (165.204.16.204) by storexhtp01.amd.com - (172.24.4.3) with Microsoft SMTP Server id 8.3.213.0; Thu, 12 Apr 2012 - 12:34:35 -0400 -Original-Received: from aftab (aftab.osrc.amd.com [165.204.15.109]) by gwo.osrc.amd.com - (Postfix) with ESMTP id D8E4C49C58B; Thu, 12 Apr 2012 17:34:33 +0100 (BST) -Content-Disposition: inline -In-Reply-To: <20120412162351.GJ24549@aftab> -User-Agent: Mutt/1.5.21 (2010-09-15) -X-OriginatorOrg: amd.com -Original-Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel:1281050 -Archived-At: - -From: Andreas Herrmann -Date: Thu, 12 Apr 2012 16:51:57 +0200 -Subject: [PATCH 2/2] x86, microcode: Ensure that module is only loaded for supported AMD CPUs - -Exit early when there's no support for a particular CPU family. Also, -fixup the "no support for this CPU vendor" to be issued only when the -driver is attempted to be loaded on an unsupported vendor. - -Cc: stable@vger.kernel.org -Cc: Tigran Aivazian -Cc: Borislav Petkov -[Boris: added a commit msg because Andreas is lazy] -Signed-off-by: Andreas Herrmann ---- - arch/x86/kernel/microcode_amd.c | 12 +++++++----- - arch/x86/kernel/microcode_core.c | 6 +++--- - 2 files changed, 10 insertions(+), 8 deletions(-) - -diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c -index 73465aa..8a2ce8f 100644 ---- a/arch/x86/kernel/microcode_amd.c -+++ b/arch/x86/kernel/microcode_amd.c -@@ -82,11 +82,6 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) - { - struct cpuinfo_x86 *c = &cpu_data(cpu); - -- if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { -- pr_warning("CPU%d: family %d not supported\n", cpu, c->x86); -- return -1; -- } -- - csig->rev = c->microcode; - pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev); - -@@ -380,6 +375,13 @@ static struct microcode_ops microcode_amd_ops = { - - struct microcode_ops * __init init_amd_microcode(void) - { -+ struct cpuinfo_x86 *c = &cpu_data(0); -+ -+ if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { -+ pr_warning("AMD CPU family 0x%x not supported\n", c->x86); -+ return NULL; -+ } -+ - patch = (void *)get_zeroed_page(GFP_KERNEL); - if (!patch) - return NULL; -diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c -index d389e74..c9bda6d 100644 ---- a/arch/x86/kernel/microcode_core.c -+++ b/arch/x86/kernel/microcode_core.c -@@ -526,11 +526,11 @@ static int __init microcode_init(void) - microcode_ops = init_intel_microcode(); - else if (c->x86_vendor == X86_VENDOR_AMD) - microcode_ops = init_amd_microcode(); -- -- if (!microcode_ops) { -+ else - pr_err("no support for this CPU vendor\n"); -+ -+ if (!microcode_ops) - return -ENODEV; -- } - - microcode_pdev = platform_device_register_simple("microcode", -1, - NULL, 0); --- -1.7.8.4 - --- -Regards/Gruss, -Boris. - -Advanced Micro Devices GmbH -Einsteinring 24, 85609 Dornach -GM: Alberto Bozzo -Reg: Dornach, Landkreis Muenchen -HRB Nr. 43632 WEEE Registernr: 129 19551 - diff --git a/x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch b/x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch deleted file mode 100644 index d1cafc162..000000000 --- a/x86-microcode-Fix-sysfs-warning-during-module-unload-on-unsupported-CPUs.patch +++ /dev/null @@ -1,167 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Borislav Petkov -Newsgroups: gmane.linux.kernel -Subject: [PATCH 1/2] x86, microcode: Fix sysfs warning during module unload -Date: Thu, 12 Apr 2012 18:30:38 +0200 -Lines: 83 -Approved: news@gmane.org -Message-ID: <20120412163038.GL24549@aftab> -References: <20120411163849.GE4794@alberich.amd.com> - <20120411200601.GC12288@kroah.com> - <20120411201053.GF18114@aftab> - <20120412162351.GJ24549@aftab> -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset="us-ascii" -X-Trace: dough.gmane.org 1334248312 13759 80.91.229.3 (12 Apr 2012 16:31:52 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Thu, 12 Apr 2012 16:31:52 +0000 (UTC) -Cc: Andreas Herrmann , - Kay Sievers , - Dave Jones , -To: Greg Kroah-Hartman -Original-X-From: linux-kernel-owner@vger.kernel.org Thu Apr 12 18:31:50 2012 -Return-path: -Envelope-to: glk-linux-kernel-3@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1SIMw1-0005nm-KE - for glk-linux-kernel-3@plane.gmane.org; Thu, 12 Apr 2012 18:31:49 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S934534Ab2DLQbF (ORCPT ); - Thu, 12 Apr 2012 12:31:05 -0400 -Original-Received: from db3ehsobe004.messaging.microsoft.com ([213.199.154.142]:35401 - "EHLO db3outboundpool.messaging.microsoft.com" rhost-flags-OK-OK-OK-OK) - by vger.kernel.org with ESMTP id S934436Ab2DLQbD (ORCPT - ); - Thu, 12 Apr 2012 12:31:03 -0400 -Original-Received: from mail117-db3-R.bigfish.com (10.3.81.240) by - DB3EHSOBE002.bigfish.com (10.3.84.22) with Microsoft SMTP Server id - 14.1.225.23; Thu, 12 Apr 2012 16:31:00 +0000 -Original-Received: from mail117-db3 (localhost [127.0.0.1]) by - mail117-db3-R.bigfish.com (Postfix) with ESMTP id BAA93180481; Thu, 12 Apr - 2012 16:31:00 +0000 (UTC) -X-SpamScore: 1 -X-BigFish: VPS1(zzzz1202hzz8275eh8275bh8275dha1495iz2dh668h839h944hd25hd2bh) -X-Forefront-Antispam-Report: CIP:163.181.249.109;KIP:(null);UIP:(null);IPV:NLI;H:ausb3twp02.amd.com;RD:none;EFVD:NLI -Original-Received: from mail117-db3 (localhost.localdomain [127.0.0.1]) by mail117-db3 - (MessageSwitch) id 133424825930391_28243; Thu, 12 Apr 2012 16:30:59 +0000 - (UTC) -Original-Received: from DB3EHSMHS006.bigfish.com (unknown [10.3.81.226]) by - mail117-db3.bigfish.com (Postfix) with ESMTP id ED7022E004F; Thu, 12 Apr 2012 - 16:30:58 +0000 (UTC) -Original-Received: from ausb3twp02.amd.com (163.181.249.109) by - DB3EHSMHS006.bigfish.com (10.3.87.106) with Microsoft SMTP Server id - 14.1.225.23; Thu, 12 Apr 2012 16:30:57 +0000 -X-WSS-ID: 0M2DKJG-02-0NU-02 -X-M-MSG: -Original-Received: from sausexedgep01.amd.com (sausexedgep01-ext.amd.com - [163.181.249.72]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No - client certificate requested) by ausb3twp02.amd.com (Axway MailGate 3.8.1) - with ESMTP id 21D3FC814C; Thu, 12 Apr 2012 11:30:50 -0500 (CDT) -Original-Received: from SAUSEXDAG01.amd.com (163.181.55.1) by sausexedgep01.amd.com - (163.181.36.54) with Microsoft SMTP Server (TLS) id 8.3.192.1; Thu, 12 Apr - 2012 11:31:09 -0500 -Original-Received: from storexhtp02.amd.com (172.24.4.4) by sausexdag01.amd.com - (163.181.55.1) with Microsoft SMTP Server (TLS) id 14.1.323.3; Thu, 12 Apr - 2012 11:30:54 -0500 -Original-Received: from gwo.osrc.amd.com (165.204.16.204) by storexhtp02.amd.com - (172.24.4.4) with Microsoft SMTP Server id 8.3.213.0; Thu, 12 Apr 2012 - 12:30:51 -0400 -Original-Received: from aftab (aftab.osrc.amd.com [165.204.15.109]) by gwo.osrc.amd.com - (Postfix) with ESMTP id 0D00D49C58B; Thu, 12 Apr 2012 17:30:50 +0100 (BST) -Content-Disposition: inline -In-Reply-To: <20120412162351.GJ24549@aftab> -User-Agent: Mutt/1.5.21 (2010-09-15) -X-OriginatorOrg: amd.com -Original-Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel:1281049 -Archived-At: - -From: Andreas Herrmann -Date: Thu, 12 Apr 2012 16:48:01 +0200 -Subject: [PATCH 1/2] x86, microcode: Fix sysfs warning during module unload on unsupported CPUs - -Loading microcode driver on an unsupported CPU and subsequently -unloading the driver causes - - WARNING: at fs/sysfs/group.c:138 mc_device_remove+0x5f/0x70 [microcode]() - Hardware name: 01972NG - sysfs group ffffffffa00013d0 not found for kobject 'cpu0' - Modules linked in: snd_hda_codec_hdmi snd_hda_codec_conexant snd_hda_intel btusb snd_hda_codec bluetooth thinkpad_acpi rfkill microcode(-) [last unloaded: cfg80211] - Pid: 4560, comm: modprobe Not tainted 3.4.0-rc2-00002-g258f742 #5 - Call Trace: - [] ? warn_slowpath_common+0x7b/0xc0 - [] ? warn_slowpath_fmt+0x45/0x50 - [] ? sysfs_remove_group+0x34/0x120 - [] ? mc_device_remove+0x5f/0x70 [microcode] - [] ? subsys_interface_unregister+0x69/0xa0 - [] ? mutex_lock+0x16/0x40 - [] ? microcode_exit+0x50/0x92 [microcode] - [] ? sys_delete_module+0x16d/0x260 - [] ? wait_iff_congested+0x45/0x110 - [] ? page_fault+0x1f/0x30 - [] ? system_call_fastpath+0x16/0x1b - -on recent kernels. - -This is due to - - commit 8a25a2fd126c621f44f3aeaef80d51f00fc11639 - (cpu: convert 'cpu' and 'machinecheck' sysdev_class to a regular - subsystem) - -which renders - - commit 6c53cbfced048c421e4f72cb2183465f68fbc5e7 - (x86, microcode: Correct sysdev_add error path) - -useless. - -See http://marc.info/?l=linux-kernel&m=133416246406478 - -Avoid above warning by restoring the old driver behaviour before -commit 6c53cbfced048c421e4f72cb2183465f68fbc5e7 (x86, microcode: -Correct sysdev_add error path) - -Cc: stable@vger.kernel.org -Cc: Tigran Aivazian -Cc: Borislav Petkov -Signed-off-by: Andreas Herrmann ---- - arch/x86/kernel/microcode_core.c | 4 +--- - 1 files changed, 1 insertions(+), 3 deletions(-) - -diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c -index 87a0f86..d389e74 100644 ---- a/arch/x86/kernel/microcode_core.c -+++ b/arch/x86/kernel/microcode_core.c -@@ -419,10 +419,8 @@ static int mc_device_add(struct device *dev, struct subsys_interface *sif) - if (err) - return err; - -- if (microcode_init_cpu(cpu) == UCODE_ERROR) { -- sysfs_remove_group(&dev->kobj, &mc_attr_group); -+ if (microcode_init_cpu(cpu) == UCODE_ERROR) - return -EINVAL; -- } - - return err; - } --- -1.7.8.4 - --- -Regards/Gruss, -Boris. - -Advanced Micro Devices GmbH -Einsteinring 24, 85609 Dornach -GM: Alberto Bozzo -Reg: Dornach, Landkreis Muenchen -HRB Nr. 43632 WEEE Registernr: 129 19551 - From f6138cc8638f8380021e44f018d1fbef208a5fa2 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 3 May 2012 08:52:20 -0500 Subject: [PATCH 371/487] Reenable slip for F16 (rhbz 818308) --- config-generic | 4 +++- kernel.spec | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index 89c64fff6..a6a008cfa 100644 --- a/config-generic +++ b/config-generic @@ -1534,7 +1534,9 @@ CONFIG_IPPP_FILTER=y CONFIG_PPP_BSDCOMP=y CONFIG_PPPOE=m CONFIG_PPP_MPPE=m -# CONFIG_SLIP is not set +#Added back for F16 +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y # # Wireless LAN diff --git a/kernel.spec b/kernel.spec index 969629df6..f24fda407 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2244,6 +2244,9 @@ fi # and build. %changelog +* Thu May 03 2012 Justin M. Forbes 3.3.4-3 +- Reenable slip for F16 (rhbz 818308) + * Thu May 03 2012 Justin M. Forbes 3.3.4-3 - Many patches from 3.3.5 stable queue - NFS Bugfixes from upstream From e4ef364737b9e888c952a8f400eaeca7304a78d2 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 3 May 2012 09:29:13 -0500 Subject: [PATCH 372/487] Additional slip options reverted to prior state --- config-generic | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config-generic b/config-generic index a6a008cfa..e991fc0b1 100644 --- a/config-generic +++ b/config-generic @@ -1537,6 +1537,8 @@ CONFIG_PPP_MPPE=m #Added back for F16 CONFIG_SLIP=m CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set # # Wireless LAN From 269237b49fb162d91f70549b0b0c4bc5f1b4ae15 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 4 May 2012 07:16:28 -0400 Subject: [PATCH 373/487] unfiltered netdev rio_ioctl access by users (rhbz 818820) --- dl2k-Clean-up-rio_ioctl.patch | 120 ++++++++++++++++++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 dl2k-Clean-up-rio_ioctl.patch diff --git a/dl2k-Clean-up-rio_ioctl.patch b/dl2k-Clean-up-rio_ioctl.patch new file mode 100644 index 000000000..2ef4eed6d --- /dev/null +++ b/dl2k-Clean-up-rio_ioctl.patch @@ -0,0 +1,120 @@ +From 1bb57e940e1958e40d51f2078f50c3a96a9b2d75 Mon Sep 17 00:00:00 2001 +From: Jeff Mahoney +Date: Wed, 25 Apr 2012 14:32:09 +0000 +Subject: [PATCH] dl2k: Clean up rio_ioctl + +The dl2k driver's rio_ioctl call has a few issues: +- No permissions checking +- Implements SIOCGMIIREG and SIOCGMIIREG using the SIOCDEVPRIVATE numbers +- Has a few ioctls that may have been used for debugging at one point + but have no place in the kernel proper. + +This patch removes all but the MII ioctls, renumbers them to use the +standard ones, and adds the proper permission check for SIOCSMIIREG. + +We can also get rid of the dl2k-specific struct mii_data in favor of +the generic struct mii_ioctl_data. + +Since we have the phyid on hand, we can add the SIOCGMIIPHY ioctl too. + +Most of the MII code for the driver could probably be converted to use +the generic MII library but I don't have a device to test the results. + +Reported-by: Stephan Mueller +Signed-off-by: Jeff Mahoney +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/dlink/dl2k.c | 52 ++++++------------------------------ + drivers/net/ethernet/dlink/dl2k.h | 7 ----- + 2 files changed, 9 insertions(+), 50 deletions(-) + +diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c +index b2dc2c8..2e09edb 100644 +--- a/drivers/net/ethernet/dlink/dl2k.c ++++ b/drivers/net/ethernet/dlink/dl2k.c +@@ -1259,55 +1259,21 @@ rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) + { + int phy_addr; + struct netdev_private *np = netdev_priv(dev); +- struct mii_data *miidata = (struct mii_data *) &rq->ifr_ifru; +- +- struct netdev_desc *desc; +- int i; ++ struct mii_ioctl_data *miidata = if_mii(rq); + + phy_addr = np->phy_addr; + switch (cmd) { +- case SIOCDEVPRIVATE: +- break; +- +- case SIOCDEVPRIVATE + 1: +- miidata->out_value = mii_read (dev, phy_addr, miidata->reg_num); ++ case SIOCGMIIPHY: ++ miidata->phy_id = phy_addr; + break; +- case SIOCDEVPRIVATE + 2: +- mii_write (dev, phy_addr, miidata->reg_num, miidata->in_value); ++ case SIOCGMIIREG: ++ miidata->val_out = mii_read (dev, phy_addr, miidata->reg_num); + break; +- case SIOCDEVPRIVATE + 3: +- break; +- case SIOCDEVPRIVATE + 4: +- break; +- case SIOCDEVPRIVATE + 5: +- netif_stop_queue (dev); ++ case SIOCSMIIREG: ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ mii_write (dev, phy_addr, miidata->reg_num, miidata->val_in); + break; +- case SIOCDEVPRIVATE + 6: +- netif_wake_queue (dev); +- break; +- case SIOCDEVPRIVATE + 7: +- printk +- ("tx_full=%x cur_tx=%lx old_tx=%lx cur_rx=%lx old_rx=%lx\n", +- netif_queue_stopped(dev), np->cur_tx, np->old_tx, np->cur_rx, +- np->old_rx); +- break; +- case SIOCDEVPRIVATE + 8: +- printk("TX ring:\n"); +- for (i = 0; i < TX_RING_SIZE; i++) { +- desc = &np->tx_ring[i]; +- printk +- ("%02x:cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x", +- i, +- (u32) (np->tx_ring_dma + i * sizeof (*desc)), +- (u32)le64_to_cpu(desc->next_desc), +- (u32)le64_to_cpu(desc->status), +- (u32)(le64_to_cpu(desc->fraginfo) >> 32), +- (u32)le64_to_cpu(desc->fraginfo)); +- printk ("\n"); +- } +- printk ("\n"); +- break; +- + default: + return -EOPNOTSUPP; + } +diff --git a/drivers/net/ethernet/dlink/dl2k.h b/drivers/net/ethernet/dlink/dl2k.h +index ba0adca..30c2da3 100644 +--- a/drivers/net/ethernet/dlink/dl2k.h ++++ b/drivers/net/ethernet/dlink/dl2k.h +@@ -365,13 +365,6 @@ struct ioctl_data { + char *data; + }; + +-struct mii_data { +- __u16 reserved; +- __u16 reg_num; +- __u16 in_value; +- __u16 out_value; +-}; +- + /* The Rx and Tx buffer descriptors. */ + struct netdev_desc { + __le64 next_desc; +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index f24fda407..b31dea92e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -808,6 +808,9 @@ Patch22013: ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch #Lots of fixes from 3.3.5 stable queue Patch22015: stable-queue-3.3.5-0502.patch +#rhbz 818820 +Patch22016: dl2k-Clean-up-rio_ioctl.patch + # END OF PATCH DEFINITIONS %endif @@ -1506,6 +1509,9 @@ ApplyPatch ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch #Lots of fixes from 3.3.5 stable queue ApplyPatch stable-queue-3.3.5-0502.patch +#rhbz 818820 +ApplyPatch dl2k-Clean-up-rio_ioctl.patch + # END OF PATCH APPLICATIONS %endif @@ -2244,6 +2250,9 @@ fi # and build. %changelog +* Fri May 04 2012 Josh Boyer +- unfiltered netdev rio_ioctl access by users (rhbz 818820) + * Thu May 03 2012 Justin M. Forbes 3.3.4-3 - Reenable slip for F16 (rhbz 818308) From eee168ca53ac80c52521d3ad685dcc149b05be65 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 7 May 2012 13:27:47 -0400 Subject: [PATCH 374/487] Linux 3.3.5 - Add patch to rate limit NFSv4 message (rhbz 732748) --- ...-the-state-manager-for-lock-reclaim-.patch | 37 + config-arm-generic | 5 + hibernate-watermark.patch | 198 -- ...n-the-command-completion-acknowledge.patch | 69 - iwlwifi-do-not-nulify-ctx-vif-on-reset.patch | 66 - kernel.spec | 35 +- sources | 2 +- stable-queue-3.3.5-0502.patch | 2804 ----------------- 8 files changed, 51 insertions(+), 3165 deletions(-) create mode 100644 NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch delete mode 100644 hibernate-watermark.patch delete mode 100644 ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch delete mode 100644 iwlwifi-do-not-nulify-ctx-vif-on-reset.patch delete mode 100644 stable-queue-3.3.5-0502.patch diff --git a/NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch b/NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch new file mode 100644 index 000000000..5b7f5e51d --- /dev/null +++ b/NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch @@ -0,0 +1,37 @@ +From 34d91cfbc163c6e2a136a27c96918fc35de06341 Mon Sep 17 00:00:00 2001 +From: William Dauchy +Date: Wed, 14 Mar 2012 12:32:04 +0100 +Subject: [PATCH] NFSv4: Rate limit the state manager for lock reclaim warning + messages + +Adding rate limit on `Lock reclaim failed` messages since it could fill +up system logs +Signed-off-by: William Dauchy +Signed-off-by: Trond Myklebust + +Conflicts: + + fs/nfs/nfs4state.c +--- + fs/nfs/nfs4state.c | 5 +++-- + 1 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c +index bacb271..3676b5c 100644 +--- a/fs/nfs/nfs4state.c ++++ b/fs/nfs/nfs4state.c +@@ -1247,8 +1247,9 @@ restart: + spin_lock(&state->state_lock); + list_for_each_entry(lock, &state->lock_states, ls_locks) { + if (!(lock->ls_flags & NFS_LOCK_INITIALIZED)) +- printk("%s: Lock reclaim failed!\n", +- __func__); ++ pr_warn_ratelimited("NFS: " ++ "%s: Lock reclaim " ++ "failed!\n", __func__); + } + spin_unlock(&state->state_lock); + nfs4_put_open_state(state); +-- +1.7.7.6 + diff --git a/config-arm-generic b/config-arm-generic index 2ad9ca63c..6cb515ddb 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -190,6 +190,11 @@ CONFIG_LSM_MMAP_MIN_ADDR=32768 # CONFIG_MACH_EUKREA_CPUIMX35SD is not set CONFIG_ARM_ERRATA_720789=y CONFIG_ARM_ERRATA_751472=y +<<<<<<< HEAD +======= +CONFIG_ARM_ERRATA_326103=y +CONFIG_OMAP4_ERRATA_I688=y +>>>>>>> 99667a9... Linux 3.3.5 # CONFIG_FB_MX3 is not set # CONFIG_MX3_IPU is not set # CONFIG_MX3_IPU_IRQS is not set diff --git a/hibernate-watermark.patch b/hibernate-watermark.patch deleted file mode 100644 index 7031e167f..000000000 --- a/hibernate-watermark.patch +++ /dev/null @@ -1,198 +0,0 @@ -Hi Rafael, - -One more version. Heeding Per's suggestion to optimise when -CONFIG_HIGHMEM is not configured. - ---------------------------------------- -Hibernation/thaw fixes/improvements: - -1. Calculate the number of required free pages based on non-high memory -pages only, because that is where the buffers will come from. - -2. Do not allocate memory for buffers from emergency pools, unless -absolutely required. Do not warn about and do not retry non-essential -failed allocations. - -3. Do not check the amount of free pages left on every single page -write, but wait until one map is completely populated and then check. - -4. Set maximum number of pages for read buffering consistently, instead -of inadvertently depending on the size of the sector type. - -5. Fix copyright line, which I missed when I submitted the hibernation -threading patch. - -6. Dispense with bit shifting arithmetic to improve readability. - -Signed-off-by: Bojan Smojver -Signed-off-by: Per Olofsson ---- - kernel/power/swap.c | 76 +++++++++++++++++++++++++++++++++++++++------------ - 1 files changed, 58 insertions(+), 18 deletions(-) - -diff --git a/kernel/power/swap.c b/kernel/power/swap.c -index 8742fd0..8a1c293 100644 ---- a/kernel/power/swap.c -+++ b/kernel/power/swap.c -@@ -6,7 +6,7 @@ - * - * Copyright (C) 1998,2001-2005 Pavel Machek - * Copyright (C) 2006 Rafael J. Wysocki -- * Copyright (C) 2010 Bojan Smojver -+ * Copyright (C) 2010-2012 Bojan Smojver - * - * This file is released under the GPLv2. - * -@@ -51,6 +51,36 @@ - - #define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(sector_t) - 1) - -+/* -+ * Number of free pages that are not high. -+ */ -+#ifdef CONFIG_HIGHMEM -+static unsigned long low_free_pages(void) -+{ -+ struct zone *zone; -+ unsigned long free = 0; -+ -+ for_each_populated_zone(zone) -+ if (!is_highmem(zone)) -+ free += zone_page_state(zone, NR_FREE_PAGES); -+ return free; -+} -+#else -+static inline unsigned long low_free_pages(void) -+{ -+ return nr_free_pages(); -+} -+#endif -+ -+/* -+ * Number of pages required to be kept free while writing the image. Always -+ * half of all available low pages before the writing starts. -+ */ -+static inline unsigned long reqd_free_pages(void) -+{ -+ return low_free_pages() / 2; -+} -+ - struct swap_map_page { - sector_t entries[MAP_PAGE_ENTRIES]; - sector_t next_swap; -@@ -72,7 +102,7 @@ struct swap_map_handle { - sector_t cur_swap; - sector_t first_sector; - unsigned int k; -- unsigned long nr_free_pages, written; -+ unsigned long reqd_free_pages; - u32 crc32; - }; - -@@ -265,14 +295,17 @@ static int write_page(void *buf, sector_t offset, struct bio **bio_chain) - return -ENOSPC; - - if (bio_chain) { -- src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); -+ src = (void *)__get_free_page(__GFP_WAIT | __GFP_NOWARN | -+ __GFP_NORETRY); - if (src) { - copy_page(src, buf); - } else { - ret = hib_wait_on_bio_chain(bio_chain); /* Free pages */ - if (ret) - return ret; -- src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); -+ src = (void *)__get_free_page(__GFP_WAIT | -+ __GFP_NOWARN | -+ __GFP_NORETRY); - if (src) { - copy_page(src, buf); - } else { -@@ -316,8 +349,7 @@ static int get_swap_writer(struct swap_map_handle *handle) - goto err_rel; - } - handle->k = 0; -- handle->nr_free_pages = nr_free_pages() >> 1; -- handle->written = 0; -+ handle->reqd_free_pages = reqd_free_pages(); - handle->first_sector = handle->cur_swap; - return 0; - err_rel: -@@ -351,12 +383,17 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, - clear_page(handle->cur); - handle->cur_swap = offset; - handle->k = 0; -- } -- if (bio_chain && ++handle->written > handle->nr_free_pages) { -- error = hib_wait_on_bio_chain(bio_chain); -- if (error) -- goto out; -- handle->written = 0; -+ -+ if (bio_chain && low_free_pages() <= handle->reqd_free_pages) { -+ error = hib_wait_on_bio_chain(bio_chain); -+ if (error) -+ goto out; -+ /* -+ * Recalculate the number of required free pages, to -+ * make sure we never take more than half. -+ */ -+ handle->reqd_free_pages = reqd_free_pages(); -+ } - } - out: - return error; -@@ -404,7 +441,7 @@ static int swap_writer_finish(struct swap_map_handle *handle, - #define LZO_THREADS 3 - - /* Maximum number of pages for read buffering. */ --#define LZO_READ_PAGES (MAP_PAGE_ENTRIES * 8) -+#define LZO_READ_PAGES 8192 - - - /** -@@ -615,10 +652,10 @@ static int save_image_lzo(struct swap_map_handle *handle, - } - - /* -- * Adjust number of free pages after all allocations have been done. -- * We don't want to run out of pages when writing. -+ * Adjust the number of required free pages after all allocations have -+ * been done. We don't want to run out of pages when writing. - */ -- handle->nr_free_pages = nr_free_pages() >> 1; -+ handle->reqd_free_pages = reqd_free_pages(); - - /* - * Start the CRC32 thread. -@@ -1129,14 +1166,17 @@ static int load_image_lzo(struct swap_map_handle *handle, - - /* - * Adjust number of pages for read buffering, in case we are short. -+ * Never take more than half of all available low pages. - */ -- read_pages = (nr_free_pages() - snapshot_get_image_size()) >> 1; -+ read_pages = (low_free_pages() - snapshot_get_image_size()) / 2; - read_pages = clamp_val(read_pages, LZO_CMP_PAGES, LZO_READ_PAGES); - - for (i = 0; i < read_pages; i++) { - page[i] = (void *)__get_free_page(i < LZO_CMP_PAGES ? - __GFP_WAIT | __GFP_HIGH : -- __GFP_WAIT); -+ __GFP_WAIT | __GFP_NOWARN | -+ __GFP_NORETRY); -+ - if (!page[i]) { - if (i < LZO_CMP_PAGES) { - ring_size = i; ---------------------------------------- - --- -Bojan - --- -To unsubscribe from this list: send the line "unsubscribe linux-kernel" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html -Please read the FAQ at http://www.tux.org/lkml/ \ No newline at end of file diff --git a/ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch b/ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch deleted file mode 100644 index 3b7451f9f..000000000 --- a/ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch +++ /dev/null @@ -1,69 +0,0 @@ -Driver incorrectly validates command completion: instead of waiting -for a command to be acknowledged it continues execution. Most of the -time driver gets acknowledge of the command completion in a tasklet -before it executes the next one. But sometimes it sends the next -command before it gets acknowledge for the previous one. In such a -case one of the following error messages appear in the log: - -Failed to send SYSTEM_CONFIG: Already sending a command. -Failed to send ASSOCIATE: Already sending a command. -Failed to send TX_POWER: Already sending a command. - -After that you need to reload the driver to get it working again. - -This bug occurs during roammaping (reported by Sam Varshavchik) -https://bugzilla.redhat.com/show_bug.cgi?id=738508 -and machine booting (reported by Tom Gundersen and Mads Kiilerich) -https://bugs.archlinux.org/task/28097 -https://bugzilla.redhat.com/show_bug.cgi?id=802106 - -This patch doesn't fix the delay issue during firmware load. -But at least device now works as usual after boot. - -Cc: stable@kernel.org -Signed-off-by: Stanislav Yakovlev ---- - drivers/net/wireless/ipw2x00/ipw2200.c | 13 ++++++++++++- - 1 files changed, 12 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c -index 4130802..8cbafa5 100644 ---- a/drivers/net/wireless/ipw2x00/ipw2200.c -+++ b/drivers/net/wireless/ipw2x00/ipw2200.c -@@ -2192,6 +2192,7 @@ static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) - { - int rc = 0; - unsigned long flags; -+ unsigned long now, end; - - spin_lock_irqsave(&priv->lock, flags); - if (priv->status & STATUS_HCMD_ACTIVE) { -@@ -2233,10 +2234,20 @@ static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) - } - spin_unlock_irqrestore(&priv->lock, flags); - -+ now = jiffies; -+ end = now + HOST_COMPLETE_TIMEOUT; -+again: - rc = wait_event_interruptible_timeout(priv->wait_command_queue, - !(priv-> - status & STATUS_HCMD_ACTIVE), -- HOST_COMPLETE_TIMEOUT); -+ end - now); -+ if (rc < 0) { -+ now = jiffies; -+ if (time_before(now, end)) -+ goto again; -+ rc = 0; -+ } -+ - if (rc == 0) { - spin_lock_irqsave(&priv->lock, flags); - if (priv->status & STATUS_HCMD_ACTIVE) { --- -1.7.2.5 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/iwlwifi-do-not-nulify-ctx-vif-on-reset.patch b/iwlwifi-do-not-nulify-ctx-vif-on-reset.patch deleted file mode 100644 index e03f2d304..000000000 --- a/iwlwifi-do-not-nulify-ctx-vif-on-reset.patch +++ /dev/null @@ -1,66 +0,0 @@ -ctx->vif is dereferenced in different part of iwlwifi code, so do not -nullify it. - -This should address at least one of the possible reasons of WARNING at -iwlagn_mac_remove_interface, and perhaps some random crashes when -firmware reset is performed. - -Cc: stable@vger.kernel.org -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/iwlwifi/iwl-agn.c | 3 --- - drivers/net/wireless/iwlwifi/iwl-mac80211.c | 10 +++++++++- - 2 files changed, 9 insertions(+), 4 deletions(-) - ---- linux-3.3.noarch.orig/drivers/net/wireless/iwlwifi/iwl-agn.c -+++ linux-3.3.noarch/drivers/net/wireless/iwlwifi/iwl-agn.c -@@ -1403,7 +1403,6 @@ static void iwl_bg_run_time_calib_work(s - - void iwlagn_prepare_restart(struct iwl_priv *priv) - { -- struct iwl_rxon_context *ctx; - bool bt_full_concurrent; - u8 bt_ci_compliance; - u8 bt_load; -@@ -1412,8 +1411,6 @@ void iwlagn_prepare_restart(struct iwl_p - - lockdep_assert_held(&priv->shrd->mutex); - -- for_each_context(priv, ctx) -- ctx->vif = NULL; - priv->is_open = 0; - - /* ---- linux-3.3.noarch.orig/drivers/net/wireless/iwlwifi/iwl-mac80211.c -+++ linux-3.3.noarch/drivers/net/wireless/iwlwifi/iwl-mac80211.c -@@ -1226,6 +1226,7 @@ static int iwlagn_mac_add_interface(stru - struct iwl_rxon_context *tmp, *ctx = NULL; - int err; - enum nl80211_iftype viftype = ieee80211_vif_type_p2p(vif); -+ bool reset = false; - - IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", - viftype, vif->addr); -@@ -1247,6 +1248,13 @@ static int iwlagn_mac_add_interface(stru - tmp->interface_modes | tmp->exclusive_interface_modes; - - if (tmp->vif) { -+ /* On reset we need to add the same interface again */ -+ if (tmp->vif == vif) { -+ reset = true; -+ ctx = tmp; -+ break; -+ } -+ - /* check if this busy context is exclusive */ - if (tmp->exclusive_interface_modes & - BIT(tmp->vif->type)) { -@@ -1273,7 +1281,7 @@ static int iwlagn_mac_add_interface(stru - ctx->vif = vif; - - err = iwl_setup_interface(priv, ctx); -- if (!err) -+ if (!err || reset) - goto out; - - ctx->vif = NULL; diff --git a/kernel.spec b/kernel.spec index b31dea92e..5bbae6b80 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 4 +%define stable_update 5 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -724,6 +724,7 @@ Patch4107: NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch # NFS Client Patch set from Upstream Patch4113: NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch Patch4114: NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch +Patch4115: NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch # patches headed upstream @@ -733,9 +734,6 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch13003: efi-dont-map-boot-services-on-32bit.patch -Patch14000: hibernate-freeze-filesystems.patch -Patch14001: hibernate-watermark.patch - Patch14010: lis3-improve-handling-of-null-rate.patch Patch15000: bluetooth-use-after-free.patch @@ -777,9 +775,6 @@ Patch21351: x86-add-io_apic_ops-to-allow-interception.patch Patch21352: x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch Patch21353: xen-x86-Implement-x86_apic_ops.patch -#rhbz 770476 -Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch - #rhbz 807632 Patch21385: libata-forbid-port-runtime-pm-by-default.patch @@ -799,15 +794,9 @@ Patch30010: debug-808990.patch #rhbz 814278 814289 CVE-2012-2119 Patch22007: macvtap-zerocopy-validate-vector-length.patch -#rhbz 783708 -Patch22012: ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch - #rhbz 817298 Patch22013: ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch -#Lots of fixes from 3.3.5 stable queue -Patch22015: stable-queue-3.3.5-0502.patch - #rhbz 818820 Patch22016: dl2k-Clean-up-rio_ioctl.patch @@ -1348,6 +1337,7 @@ ApplyPatch NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch # NFS Client Patch set from Upstream ApplyPatch NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch ApplyPatch NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch +ApplyPatch NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch # USB @@ -1442,10 +1432,6 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch ApplyPatch efi-dont-map-boot-services-on-32bit.patch -# FIXME -#ApplyPatch hibernate-freeze-filesystems.patch -ApplyPatch hibernate-watermark.patch - ApplyPatch lis3-improve-handling-of-null-rate.patch ApplyPatch bluetooth-use-after-free.patch @@ -1485,9 +1471,6 @@ ApplyPatch x86-add-io_apic_ops-to-allow-interception.patch ApplyPatch x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch ApplyPatch xen-x86-Implement-x86_apic_ops.patch -#rhbz 770476 -ApplyPatch iwlwifi-do-not-nulify-ctx-vif-on-reset.patch - #rhbz 808207 CVE-2012-1601 ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch @@ -1500,15 +1483,9 @@ ApplyPatch disable-hid-battery.patch #rhbz 814278 814289 CVE-2012-2119 ApplyPatch macvtap-zerocopy-validate-vector-length.patch -#rhbz 783708 -ApplyPatch ipw2200-Fix-race-condition-in-the-command-completion-acknowledge.patch - #rhbz 817298 ApplyPatch ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch -#Lots of fixes from 3.3.5 stable queue -ApplyPatch stable-queue-3.3.5-0502.patch - #rhbz 818820 ApplyPatch dl2k-Clean-up-rio_ioctl.patch @@ -2250,6 +2227,10 @@ fi # and build. %changelog +* Mon May 07 2012 Josh Boyer 3.3.5-1 +- Linux 3.3.5 +- Add patch to rate limit NFSv4 message (rhbz 732748) + * Fri May 04 2012 Josh Boyer - unfiltered netdev rio_ioctl access by users (rhbz 818820) diff --git a/sources b/sources index 1918a7281..ae9616785 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz -9c4cc16f10b645fbb90f6c05ad388883 patch-3.3.4.xz +d346edca5d3de7052f49996b01cef401 patch-3.3.5.xz diff --git a/stable-queue-3.3.5-0502.patch b/stable-queue-3.3.5-0502.patch deleted file mode 100644 index 4f33ba861..000000000 --- a/stable-queue-3.3.5-0502.patch +++ /dev/null @@ -1,2804 +0,0 @@ -From 5ac57550f279c3d991ef0b398681bcaca18169f7 Mon Sep 17 00:00:00 2001 -From: David Henningsson -Date: Fri, 20 Apr 2012 10:01:46 +0200 -Subject: ALSA: HDA: Add external mic quirk for Asus Zenbook UX31E - -From: David Henningsson - -commit 5ac57550f279c3d991ef0b398681bcaca18169f7 upstream. - -According to the reporter, external mic starts to work if the -laptop-dmic model is used. According to BIOS pin config, all -pins are consistent with the alc269vb_laptop_dmic fixup, except -for the external mic, which is not present. - -BugLink: https://bugs.launchpad.net/bugs/950490 -Signed-off-by: David Henningsson -Signed-off-by: Takashi Iwai -Signed-off-by: Greg Kroah-Hartman - ---- - sound/pci/hda/patch_realtek.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/sound/pci/hda/patch_realtek.c -+++ b/sound/pci/hda/patch_realtek.c -@@ -5402,6 +5402,7 @@ static const struct alc_fixup alc269_fix - }; - - static const struct snd_pci_quirk alc269_fixup_tbl[] = { -+ SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC), - SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), - SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), - SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), -From 7e1f7c8a6e517900cd84da1b8ae020f08f286c3b Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Thu, 12 Apr 2012 17:29:36 +0100 -Subject: ASoC: dapm: Ensure power gets managed for line widgets - -From: Mark Brown - -commit 7e1f7c8a6e517900cd84da1b8ae020f08f286c3b upstream. - -Line widgets had not been included in either the power up or power down -sequences so if a widget had an event associated with it that event would -never be run. Fix this minimally by adding them to the sequences, we -should probably be doing away with the specific widget types as they all -have the same priority anyway. - -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - sound/soc/soc-dapm.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/sound/soc/soc-dapm.c -+++ b/sound/soc/soc-dapm.c -@@ -70,6 +70,7 @@ static int dapm_up_seq[] = { - [snd_soc_dapm_out_drv] = 10, - [snd_soc_dapm_hp] = 10, - [snd_soc_dapm_spk] = 10, -+ [snd_soc_dapm_line] = 10, - [snd_soc_dapm_post] = 11, - }; - -@@ -78,6 +79,7 @@ static int dapm_down_seq[] = { - [snd_soc_dapm_adc] = 1, - [snd_soc_dapm_hp] = 2, - [snd_soc_dapm_spk] = 2, -+ [snd_soc_dapm_line] = 2, - [snd_soc_dapm_out_drv] = 2, - [snd_soc_dapm_pga] = 4, - [snd_soc_dapm_mixer_named_ctl] = 5, -From 1a38336b8611a04f0a624330c1f815421f4bf5f4 Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Thu, 12 Apr 2012 19:47:11 +0100 -Subject: ASoC: wm8994: Improve sequencing of AIF channel enables - -From: Mark Brown - -commit 1a38336b8611a04f0a624330c1f815421f4bf5f4 upstream. - -This ensures a clean startup of the channels, without this change some -use cases could result in issues in a small proportion of cases. - -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman - ---- - sound/soc/codecs/wm8994.c | 276 +++++++++++++++++++++++++++++++++++++--------- - 1 file changed, 222 insertions(+), 54 deletions(-) - ---- a/sound/soc/codecs/wm8994.c -+++ b/sound/soc/codecs/wm8994.c -@@ -929,61 +929,170 @@ static void wm8994_update_class_w(struct - } - } - --static int late_enable_ev(struct snd_soc_dapm_widget *w, -- struct snd_kcontrol *kcontrol, int event) -+static int aif1clk_ev(struct snd_soc_dapm_widget *w, -+ struct snd_kcontrol *kcontrol, int event) - { - struct snd_soc_codec *codec = w->codec; -- struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); -+ struct wm8994 *control = codec->control_data; -+ int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA; -+ int dac; -+ int adc; -+ int val; -+ -+ switch (control->type) { -+ case WM8994: -+ case WM8958: -+ mask |= WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA; -+ break; -+ default: -+ break; -+ } - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: -- if (wm8994->aif1clk_enable) { -- snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, -- WM8994_AIF1CLK_ENA_MASK, -- WM8994_AIF1CLK_ENA); -- wm8994->aif1clk_enable = 0; -- } -- if (wm8994->aif2clk_enable) { -- snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, -- WM8994_AIF2CLK_ENA_MASK, -- WM8994_AIF2CLK_ENA); -- wm8994->aif2clk_enable = 0; -- } -+ val = snd_soc_read(codec, WM8994_AIF1_CONTROL_1); -+ if ((val & WM8994_AIF1ADCL_SRC) && -+ (val & WM8994_AIF1ADCR_SRC)) -+ adc = WM8994_AIF1ADC1R_ENA | WM8994_AIF1ADC2R_ENA; -+ else if (!(val & WM8994_AIF1ADCL_SRC) && -+ !(val & WM8994_AIF1ADCR_SRC)) -+ adc = WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC2L_ENA; -+ else -+ adc = WM8994_AIF1ADC1R_ENA | WM8994_AIF1ADC2R_ENA | -+ WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC2L_ENA; -+ -+ val = snd_soc_read(codec, WM8994_AIF1_CONTROL_2); -+ if ((val & WM8994_AIF1DACL_SRC) && -+ (val & WM8994_AIF1DACR_SRC)) -+ dac = WM8994_AIF1DAC1R_ENA | WM8994_AIF1DAC2R_ENA; -+ else if (!(val & WM8994_AIF1DACL_SRC) && -+ !(val & WM8994_AIF1DACR_SRC)) -+ dac = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC2L_ENA; -+ else -+ dac = WM8994_AIF1DAC1R_ENA | WM8994_AIF1DAC2R_ENA | -+ WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC2L_ENA; -+ -+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_4, -+ mask, adc); -+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, -+ mask, dac); -+ snd_soc_update_bits(codec, WM8994_CLOCKING_1, -+ WM8994_AIF1DSPCLK_ENA | -+ WM8994_SYSDSPCLK_ENA, -+ WM8994_AIF1DSPCLK_ENA | -+ WM8994_SYSDSPCLK_ENA); -+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_4, mask, -+ WM8994_AIF1ADC1R_ENA | -+ WM8994_AIF1ADC1L_ENA | -+ WM8994_AIF1ADC2R_ENA | -+ WM8994_AIF1ADC2L_ENA); -+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, mask, -+ WM8994_AIF1DAC1R_ENA | -+ WM8994_AIF1DAC1L_ENA | -+ WM8994_AIF1DAC2R_ENA | -+ WM8994_AIF1DAC2L_ENA); - break; -- } - -- /* We may also have postponed startup of DSP, handle that. */ -- wm8958_aif_ev(w, kcontrol, event); -+ case SND_SOC_DAPM_PRE_PMD: -+ case SND_SOC_DAPM_POST_PMD: -+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, -+ mask, 0); -+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_4, -+ mask, 0); -+ -+ val = snd_soc_read(codec, WM8994_CLOCKING_1); -+ if (val & WM8994_AIF2DSPCLK_ENA) -+ val = WM8994_SYSDSPCLK_ENA; -+ else -+ val = 0; -+ snd_soc_update_bits(codec, WM8994_CLOCKING_1, -+ WM8994_SYSDSPCLK_ENA | -+ WM8994_AIF1DSPCLK_ENA, val); -+ break; -+ } - - return 0; - } - --static int late_disable_ev(struct snd_soc_dapm_widget *w, -- struct snd_kcontrol *kcontrol, int event) -+static int aif2clk_ev(struct snd_soc_dapm_widget *w, -+ struct snd_kcontrol *kcontrol, int event) - { - struct snd_soc_codec *codec = w->codec; -- struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); -+ int dac; -+ int adc; -+ int val; - - switch (event) { -+ case SND_SOC_DAPM_PRE_PMU: -+ val = snd_soc_read(codec, WM8994_AIF2_CONTROL_1); -+ if ((val & WM8994_AIF2ADCL_SRC) && -+ (val & WM8994_AIF2ADCR_SRC)) -+ adc = WM8994_AIF2ADCR_ENA; -+ else if (!(val & WM8994_AIF2ADCL_SRC) && -+ !(val & WM8994_AIF2ADCR_SRC)) -+ adc = WM8994_AIF2ADCL_ENA; -+ else -+ adc = WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA; -+ -+ -+ val = snd_soc_read(codec, WM8994_AIF2_CONTROL_2); -+ if ((val & WM8994_AIF2DACL_SRC) && -+ (val & WM8994_AIF2DACR_SRC)) -+ dac = WM8994_AIF2DACR_ENA; -+ else if (!(val & WM8994_AIF2DACL_SRC) && -+ !(val & WM8994_AIF2DACR_SRC)) -+ dac = WM8994_AIF2DACL_ENA; -+ else -+ dac = WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA; -+ -+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_4, -+ WM8994_AIF2ADCL_ENA | -+ WM8994_AIF2ADCR_ENA, adc); -+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, -+ WM8994_AIF2DACL_ENA | -+ WM8994_AIF2DACR_ENA, dac); -+ snd_soc_update_bits(codec, WM8994_CLOCKING_1, -+ WM8994_AIF2DSPCLK_ENA | -+ WM8994_SYSDSPCLK_ENA, -+ WM8994_AIF2DSPCLK_ENA | -+ WM8994_SYSDSPCLK_ENA); -+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_4, -+ WM8994_AIF2ADCL_ENA | -+ WM8994_AIF2ADCR_ENA, -+ WM8994_AIF2ADCL_ENA | -+ WM8994_AIF2ADCR_ENA); -+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, -+ WM8994_AIF2DACL_ENA | -+ WM8994_AIF2DACR_ENA, -+ WM8994_AIF2DACL_ENA | -+ WM8994_AIF2DACR_ENA); -+ break; -+ -+ case SND_SOC_DAPM_PRE_PMD: - case SND_SOC_DAPM_POST_PMD: -- if (wm8994->aif1clk_disable) { -- snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, -- WM8994_AIF1CLK_ENA_MASK, 0); -- wm8994->aif1clk_disable = 0; -- } -- if (wm8994->aif2clk_disable) { -- snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, -- WM8994_AIF2CLK_ENA_MASK, 0); -- wm8994->aif2clk_disable = 0; -- } -+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, -+ WM8994_AIF2DACL_ENA | -+ WM8994_AIF2DACR_ENA, 0); -+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, -+ WM8994_AIF2ADCL_ENA | -+ WM8994_AIF2ADCR_ENA, 0); -+ -+ val = snd_soc_read(codec, WM8994_CLOCKING_1); -+ if (val & WM8994_AIF1DSPCLK_ENA) -+ val = WM8994_SYSDSPCLK_ENA; -+ else -+ val = 0; -+ snd_soc_update_bits(codec, WM8994_CLOCKING_1, -+ WM8994_SYSDSPCLK_ENA | -+ WM8994_AIF2DSPCLK_ENA, val); - break; - } - - return 0; - } - --static int aif1clk_ev(struct snd_soc_dapm_widget *w, -- struct snd_kcontrol *kcontrol, int event) -+static int aif1clk_late_ev(struct snd_soc_dapm_widget *w, -+ struct snd_kcontrol *kcontrol, int event) - { - struct snd_soc_codec *codec = w->codec; - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); -@@ -1000,8 +1109,8 @@ static int aif1clk_ev(struct snd_soc_dap - return 0; - } - --static int aif2clk_ev(struct snd_soc_dapm_widget *w, -- struct snd_kcontrol *kcontrol, int event) -+static int aif2clk_late_ev(struct snd_soc_dapm_widget *w, -+ struct snd_kcontrol *kcontrol, int event) - { - struct snd_soc_codec *codec = w->codec; - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); -@@ -1018,6 +1127,63 @@ static int aif2clk_ev(struct snd_soc_dap - return 0; - } - -+static int late_enable_ev(struct snd_soc_dapm_widget *w, -+ struct snd_kcontrol *kcontrol, int event) -+{ -+ struct snd_soc_codec *codec = w->codec; -+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); -+ -+ switch (event) { -+ case SND_SOC_DAPM_PRE_PMU: -+ if (wm8994->aif1clk_enable) { -+ aif1clk_ev(w, kcontrol, event); -+ snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, -+ WM8994_AIF1CLK_ENA_MASK, -+ WM8994_AIF1CLK_ENA); -+ wm8994->aif1clk_enable = 0; -+ } -+ if (wm8994->aif2clk_enable) { -+ aif2clk_ev(w, kcontrol, event); -+ snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, -+ WM8994_AIF2CLK_ENA_MASK, -+ WM8994_AIF2CLK_ENA); -+ wm8994->aif2clk_enable = 0; -+ } -+ break; -+ } -+ -+ /* We may also have postponed startup of DSP, handle that. */ -+ wm8958_aif_ev(w, kcontrol, event); -+ -+ return 0; -+} -+ -+static int late_disable_ev(struct snd_soc_dapm_widget *w, -+ struct snd_kcontrol *kcontrol, int event) -+{ -+ struct snd_soc_codec *codec = w->codec; -+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); -+ -+ switch (event) { -+ case SND_SOC_DAPM_POST_PMD: -+ if (wm8994->aif1clk_disable) { -+ snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, -+ WM8994_AIF1CLK_ENA_MASK, 0); -+ aif1clk_ev(w, kcontrol, event); -+ wm8994->aif1clk_disable = 0; -+ } -+ if (wm8994->aif2clk_disable) { -+ snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, -+ WM8994_AIF2CLK_ENA_MASK, 0); -+ aif2clk_ev(w, kcontrol, event); -+ wm8994->aif2clk_disable = 0; -+ } -+ break; -+ } -+ -+ return 0; -+} -+ - static int adc_mux_ev(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) - { -@@ -1314,9 +1480,9 @@ static const struct snd_kcontrol_new aif - SOC_DAPM_ENUM("AIF2DACR Mux", aif2dacr_src_enum); - - static const struct snd_soc_dapm_widget wm8994_lateclk_revd_widgets[] = { --SND_SOC_DAPM_SUPPLY("AIF1CLK", SND_SOC_NOPM, 0, 0, aif1clk_ev, -+SND_SOC_DAPM_SUPPLY("AIF1CLK", SND_SOC_NOPM, 0, 0, aif1clk_late_ev, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), --SND_SOC_DAPM_SUPPLY("AIF2CLK", SND_SOC_NOPM, 0, 0, aif2clk_ev, -+SND_SOC_DAPM_SUPPLY("AIF2CLK", SND_SOC_NOPM, 0, 0, aif2clk_late_ev, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_PGA_E("Late DAC1L Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0, -@@ -1345,8 +1511,10 @@ SND_SOC_DAPM_POST("Late Disable PGA", la - }; - - static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = { --SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, NULL, 0), --SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0), -+SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, aif1clk_ev, -+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), -+SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, aif2clk_ev, -+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0, - left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), -@@ -1399,30 +1567,30 @@ SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM - SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - --SND_SOC_DAPM_SUPPLY("DSP1CLK", WM8994_CLOCKING_1, 3, 0, NULL, 0), --SND_SOC_DAPM_SUPPLY("DSP2CLK", WM8994_CLOCKING_1, 2, 0, NULL, 0), --SND_SOC_DAPM_SUPPLY("DSPINTCLK", WM8994_CLOCKING_1, 1, 0, NULL, 0), -+SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, 3, 0, NULL, 0), -+SND_SOC_DAPM_SUPPLY("DSP2CLK", SND_SOC_NOPM, 2, 0, NULL, 0), -+SND_SOC_DAPM_SUPPLY("DSPINTCLK", SND_SOC_NOPM, 1, 0, NULL, 0), - - SND_SOC_DAPM_AIF_OUT("AIF1ADC1L", NULL, -- 0, WM8994_POWER_MANAGEMENT_4, 9, 0), -+ 0, SND_SOC_NOPM, 9, 0), - SND_SOC_DAPM_AIF_OUT("AIF1ADC1R", NULL, -- 0, WM8994_POWER_MANAGEMENT_4, 8, 0), -+ 0, SND_SOC_NOPM, 8, 0), - SND_SOC_DAPM_AIF_IN_E("AIF1DAC1L", NULL, 0, -- WM8994_POWER_MANAGEMENT_5, 9, 0, wm8958_aif_ev, -+ SND_SOC_NOPM, 9, 0, wm8958_aif_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_AIF_IN_E("AIF1DAC1R", NULL, 0, -- WM8994_POWER_MANAGEMENT_5, 8, 0, wm8958_aif_ev, -+ SND_SOC_NOPM, 8, 0, wm8958_aif_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_AIF_OUT("AIF1ADC2L", NULL, -- 0, WM8994_POWER_MANAGEMENT_4, 11, 0), -+ 0, SND_SOC_NOPM, 11, 0), - SND_SOC_DAPM_AIF_OUT("AIF1ADC2R", NULL, -- 0, WM8994_POWER_MANAGEMENT_4, 10, 0), -+ 0, SND_SOC_NOPM, 10, 0), - SND_SOC_DAPM_AIF_IN_E("AIF1DAC2L", NULL, 0, -- WM8994_POWER_MANAGEMENT_5, 11, 0, wm8958_aif_ev, -+ SND_SOC_NOPM, 11, 0, wm8958_aif_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_AIF_IN_E("AIF1DAC2R", NULL, 0, -- WM8994_POWER_MANAGEMENT_5, 10, 0, wm8958_aif_ev, -+ SND_SOC_NOPM, 10, 0, wm8958_aif_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_MIXER("AIF1ADC1L Mixer", SND_SOC_NOPM, 0, 0, -@@ -1449,14 +1617,14 @@ SND_SOC_DAPM_MIXER("DAC1R Mixer", SND_SO - dac1r_mix, ARRAY_SIZE(dac1r_mix)), - - SND_SOC_DAPM_AIF_OUT("AIF2ADCL", NULL, 0, -- WM8994_POWER_MANAGEMENT_4, 13, 0), -+ SND_SOC_NOPM, 13, 0), - SND_SOC_DAPM_AIF_OUT("AIF2ADCR", NULL, 0, -- WM8994_POWER_MANAGEMENT_4, 12, 0), -+ SND_SOC_NOPM, 12, 0), - SND_SOC_DAPM_AIF_IN_E("AIF2DACL", NULL, 0, -- WM8994_POWER_MANAGEMENT_5, 13, 0, wm8958_aif_ev, -+ SND_SOC_NOPM, 13, 0, wm8958_aif_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_AIF_IN_E("AIF2DACR", NULL, 0, -- WM8994_POWER_MANAGEMENT_5, 12, 0, wm8958_aif_ev, -+ SND_SOC_NOPM, 12, 0, wm8958_aif_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - - SND_SOC_DAPM_AIF_IN("AIF1DACDAT", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), -From 64f371bc3107e69efce563a3d0f0e6880de0d537 Mon Sep 17 00:00:00 2001 -From: Linus Torvalds -Date: Sun, 29 Apr 2012 13:30:08 -0700 -Subject: autofs: make the autofsv5 packet file descriptor use a packetized pipe - -From: Linus Torvalds - -commit 64f371bc3107e69efce563a3d0f0e6880de0d537 upstream. - -The autofs packet size has had a very unfortunate size problem on x86: -because the alignment of 'u64' differs in 32-bit and 64-bit modes, and -because the packet data was not 8-byte aligned, the size of the autofsv5 -packet structure differed between 32-bit and 64-bit modes despite -looking otherwise identical (300 vs 304 bytes respectively). - -We first fixed that up by making the 64-bit compat mode know about this -problem in commit a32744d4abae ("autofs: work around unhappy compat -problem on x86-64"), and that made a 32-bit 'systemd' work happily on a -64-bit kernel because everything then worked the same way as on a 32-bit -kernel. - -But it turned out that 'automount' had actually known and worked around -this problem in user space, so fixing the kernel to do the proper 32-bit -compatibility handling actually *broke* 32-bit automount on a 64-bit -kernel, because it knew that the packet sizes were wrong and expected -those incorrect sizes. - -As a result, we ended up reverting that compatibility mode fix, and -thus breaking systemd again, in commit fcbf94b9dedd. - -With both automount and systemd doing a single read() system call, and -verifying that they get *exactly* the size they expect but using -different sizes, it seemed that fixing one of them inevitably seemed to -break the other. At one point, a patch I seriously considered applying -from Michael Tokarev did a "strcmp()" to see if it was automount that -was doing the operation. Ugly, ugly. - -However, a prettier solution exists now thanks to the packetized pipe -mode. By marking the communication pipe as being packetized (by simply -setting the O_DIRECT flag), we can always just write the bigger packet -size, and if user-space does a smaller read, it will just get that -partial end result and the extra alignment padding will simply be thrown -away. - -This makes both automount and systemd happy, since they now get the size -they asked for, and the kernel side of autofs simply no longer needs to -care - it could pad out the packet arbitrarily. - -Of course, if there is some *other* user of autofs (please, please, -please tell me it ain't so - and we haven't heard of any) that tries to -read the packets with multiple writes, that other user will now be -broken - the whole point of the packetized mode is that one system call -gets exactly one packet, and you cannot read a packet in pieces. - -Tested-by: Michael Tokarev -Cc: Alan Cox -Cc: David Miller -Cc: Ian Kent -Cc: Thomas Meyer -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - fs/autofs4/autofs_i.h | 11 +++++++++++ - fs/autofs4/dev-ioctl.c | 2 +- - fs/autofs4/inode.c | 2 +- - 3 files changed, 13 insertions(+), 2 deletions(-) - ---- a/fs/autofs4/autofs_i.h -+++ b/fs/autofs4/autofs_i.h -@@ -269,6 +269,17 @@ int autofs4_fill_super(struct super_bloc - struct autofs_info *autofs4_new_ino(struct autofs_sb_info *); - void autofs4_clean_ino(struct autofs_info *); - -+static inline int autofs_prepare_pipe(struct file *pipe) -+{ -+ if (!pipe->f_op || !pipe->f_op->write) -+ return -EINVAL; -+ if (!S_ISFIFO(pipe->f_dentry->d_inode->i_mode)) -+ return -EINVAL; -+ /* We want a packet pipe */ -+ pipe->f_flags |= O_DIRECT; -+ return 0; -+} -+ - /* Queue management functions */ - - int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify); ---- a/fs/autofs4/dev-ioctl.c -+++ b/fs/autofs4/dev-ioctl.c -@@ -376,7 +376,7 @@ static int autofs_dev_ioctl_setpipefd(st - err = -EBADF; - goto out; - } -- if (!pipe->f_op || !pipe->f_op->write) { -+ if (autofs_prepare_pipe(pipe) < 0) { - err = -EPIPE; - fput(pipe); - goto out; ---- a/fs/autofs4/inode.c -+++ b/fs/autofs4/inode.c -@@ -293,7 +293,7 @@ int autofs4_fill_super(struct super_bloc - printk("autofs: could not open pipe file descriptor\n"); - goto fail_dput; - } -- if (!pipe->f_op || !pipe->f_op->write) -+ if (autofs_prepare_pipe(pipe) < 0) - goto fail_fput; - sbi->pipe = pipe; - sbi->pipefd = pipefd; -From 511d63cb19329235bc9298b64010ec494b5e1408 Mon Sep 17 00:00:00 2001 -From: Horia Geanta -Date: Fri, 30 Mar 2012 17:49:53 +0300 -Subject: crypto: talitos - properly lock access to global talitos registers - -From: Horia Geanta - -commit 511d63cb19329235bc9298b64010ec494b5e1408 upstream. - -Access to global talitos registers must be protected for the case when -affinities are configured such that primary and secondary talitos irqs -run on different cpus. - -Signed-off-by: Horia Geanta -Signed-off-by: Kim Phillips -Signed-off-by: Herbert Xu -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/crypto/talitos.c | 20 +++++++++++++++++--- - 1 file changed, 17 insertions(+), 3 deletions(-) - ---- a/drivers/crypto/talitos.c -+++ b/drivers/crypto/talitos.c -@@ -124,6 +124,9 @@ struct talitos_private { - void __iomem *reg; - int irq[2]; - -+ /* SEC global registers lock */ -+ spinlock_t reg_lock ____cacheline_aligned; -+ - /* SEC version geometry (from device tree node) */ - unsigned int num_channels; - unsigned int chfifo_len; -@@ -412,6 +415,7 @@ static void talitos_done_##name(unsigned - { \ - struct device *dev = (struct device *)data; \ - struct talitos_private *priv = dev_get_drvdata(dev); \ -+ unsigned long flags; \ - \ - if (ch_done_mask & 1) \ - flush_channel(dev, 0, 0, 0); \ -@@ -427,8 +431,10 @@ static void talitos_done_##name(unsigned - out: \ - /* At this point, all completed channels have been processed */ \ - /* Unmask done interrupts for channels completed later on. */ \ -+ spin_lock_irqsave(&priv->reg_lock, flags); \ - setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ - setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT); \ -+ spin_unlock_irqrestore(&priv->reg_lock, flags); \ - } - DEF_TALITOS_DONE(4ch, TALITOS_ISR_4CHDONE) - DEF_TALITOS_DONE(ch0_2, TALITOS_ISR_CH_0_2_DONE) -@@ -619,22 +625,28 @@ static irqreturn_t talitos_interrupt_##n - struct device *dev = data; \ - struct talitos_private *priv = dev_get_drvdata(dev); \ - u32 isr, isr_lo; \ -+ unsigned long flags; \ - \ -+ spin_lock_irqsave(&priv->reg_lock, flags); \ - isr = in_be32(priv->reg + TALITOS_ISR); \ - isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \ - /* Acknowledge interrupt */ \ - out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \ - out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \ - \ -- if (unlikely((isr & ~TALITOS_ISR_4CHDONE) & ch_err_mask || isr_lo)) \ -- talitos_error(dev, isr, isr_lo); \ -- else \ -+ if (unlikely(isr & ch_err_mask || isr_lo)) { \ -+ spin_unlock_irqrestore(&priv->reg_lock, flags); \ -+ talitos_error(dev, isr & ch_err_mask, isr_lo); \ -+ } \ -+ else { \ - if (likely(isr & ch_done_mask)) { \ - /* mask further done interrupts. */ \ - clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \ - /* done_task will unmask done interrupts at exit */ \ - tasklet_schedule(&priv->done_task[tlet]); \ - } \ -+ spin_unlock_irqrestore(&priv->reg_lock, flags); \ -+ } \ - \ - return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \ - IRQ_NONE; \ -@@ -2718,6 +2730,8 @@ static int talitos_probe(struct platform - - priv->ofdev = ofdev; - -+ spin_lock_init(&priv->reg_lock); -+ - err = talitos_probe_irq(ofdev); - if (err) - goto err_out; -From d62d421b071b08249361044d8e56c8b5c3ed6aa7 Mon Sep 17 00:00:00 2001 -From: Martin Nyhus -Date: Thu, 15 Mar 2012 18:25:48 +0100 -Subject: dell-laptop: Terminate quirks list properly - -From: Martin Nyhus - -commit d62d421b071b08249361044d8e56c8b5c3ed6aa7 upstream. - -Add missing DMI_NONE entry to end of the quirks list so -dmi_check_system() won't read past the end of the list. - -Signed-off-by: Martin Nyhus -Signed-off-by: Matthew Garrett -Cc: Guenter Roeck -Tested-by: Jens Gustedt -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/platform/x86/dell-laptop.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/platform/x86/dell-laptop.c -+++ b/drivers/platform/x86/dell-laptop.c -@@ -211,6 +211,7 @@ static struct dmi_system_id __devinitdat - }, - .driver_data = &quirk_dell_vostro_v130, - }, -+ { } - }; - - static struct calling_interface_buffer *buffer; -From ed8b0d67f33518a16c6b2450fe5ebebf180c2d04 Mon Sep 17 00:00:00 2001 -From: Nicolas Ferre -Date: Mon, 16 Apr 2012 14:46:30 +0200 -Subject: dmaengine: at_hdmac: remove clear-on-read in atc_dostart() - -From: Nicolas Ferre - -commit ed8b0d67f33518a16c6b2450fe5ebebf180c2d04 upstream. - -This loop on EBCISR register was designed to clear IRQ sources before enabling -a DMA channel. This register is clear-on-read so a race condition can appear if -another channel is already active and has just finished its transfer. -Removing this read on EBCISR is fixing the issue as there is no case where an IRQ -could be pending: we already make sure that this register is drained at probe() -time and during resume. - -Signed-off-by: Nicolas Ferre -Signed-off-by: Vinod Koul -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/dma/at_hdmac.c | 4 ---- - 1 file changed, 4 deletions(-) - ---- a/drivers/dma/at_hdmac.c -+++ b/drivers/dma/at_hdmac.c -@@ -241,10 +241,6 @@ static void atc_dostart(struct at_dma_ch - - vdbg_dump_regs(atchan); - -- /* clear any pending interrupt */ -- while (dma_readl(atdma, EBCISR)) -- cpu_relax(); -- - channel_writel(atchan, SADDR, 0); - channel_writel(atchan, DADDR, 0); - channel_writel(atchan, CTRLA, 0); -From 44afb3a04391a74309d16180d1e4f8386fdfa745 Mon Sep 17 00:00:00 2001 -From: Xi Wang -Date: Mon, 23 Apr 2012 04:06:42 -0400 -Subject: drm/i915: fix integer overflow in i915_gem_do_execbuffer() - -From: Xi Wang - -commit 44afb3a04391a74309d16180d1e4f8386fdfa745 upstream. - -On 32-bit systems, a large args->num_cliprects from userspace via ioctl -may overflow the allocation size, leading to out-of-bounds access. - -This vulnerability was introduced in commit 432e58ed ("drm/i915: Avoid -allocation for execbuffer object list"). - -Signed-off-by: Xi Wang -Reviewed-by: Chris Wilson -Signed-off-by: Daniel Vetter -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/i915_gem_execbuffer.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c -+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c -@@ -1082,6 +1082,11 @@ i915_gem_do_execbuffer(struct drm_device - return -EINVAL; - } - -+ if (args->num_cliprects > UINT_MAX / sizeof(*cliprects)) { -+ DRM_DEBUG("execbuf with %u cliprects\n", -+ args->num_cliprects); -+ return -EINVAL; -+ } - cliprects = kmalloc(args->num_cliprects * sizeof(*cliprects), - GFP_KERNEL); - if (cliprects == NULL) { -From ed8cd3b2cd61004cab85380c52b1817aca1ca49b Mon Sep 17 00:00:00 2001 -From: Xi Wang -Date: Mon, 23 Apr 2012 04:06:41 -0400 -Subject: drm/i915: fix integer overflow in i915_gem_execbuffer2() - -From: Xi Wang - -commit ed8cd3b2cd61004cab85380c52b1817aca1ca49b upstream. - -On 32-bit systems, a large args->buffer_count from userspace via ioctl -may overflow the allocation size, leading to out-of-bounds access. - -This vulnerability was introduced in commit 8408c282 ("drm/i915: -First try a normal large kmalloc for the temporary exec buffers"). - -Signed-off-by: Xi Wang -Reviewed-by: Chris Wilson -Signed-off-by: Daniel Vetter -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/i915_gem_execbuffer.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c -+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c -@@ -1353,7 +1353,8 @@ i915_gem_execbuffer2(struct drm_device * - struct drm_i915_gem_exec_object2 *exec2_list = NULL; - int ret; - -- if (args->buffer_count < 1) { -+ if (args->buffer_count < 1 || -+ args->buffer_count > UINT_MAX / sizeof(*exec2_list)) { - DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count); - return -EINVAL; - } -From 6651819b4b4fc3caa6964c5d825eb4bb996f3905 Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Sun, 1 Apr 2012 19:16:18 +0200 -Subject: drm/i915: handle input/output sdvo timings separately in mode_set - -From: Daniel Vetter - -commit 6651819b4b4fc3caa6964c5d825eb4bb996f3905 upstream. - -We seem to have a decent confusion between the output timings and the -input timings of the sdvo encoder. If I understand the code correctly, -we use the original mode unchanged for the output timings, safe for -the lvds case. And we should use the adjusted mode for input timings. - -Clarify the situation by adding an explicit output_dtd to the sdvo -mode_set function and streamline the code-flow by moving the input and -output mode setting in the sdvo encode together. - -Furthermore testing showed that the sdvo input timing needs the -unadjusted dotclock, the sdvo chip will automatically compute the -required pixel multiplier to get a dotclock above 100 MHz. - -Fix this up when converting a drm mode to an sdvo dtd. - -This regression was introduced in - -commit c74696b9c890074c1e1ee3d7496fc71eb3680ced -Author: Pavel Roskin -Date: Thu Sep 2 14:46:34 2010 -0400 - - i915: revert some checks added by commit 32aad86f - -particularly the following hunk: - -# diff --git a/drivers/gpu/drm/i915/intel_sdvo.c -# b/drivers/gpu/drm/i915/intel_sdvo.c -# index 093e914..62d22ae 100644 -# --- a/drivers/gpu/drm/i915/intel_sdvo.c -# +++ b/drivers/gpu/drm/i915/intel_sdvo.c -# @@ -1122,11 +1123,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, -# -# /* We have tried to get input timing in mode_fixup, and filled into -# adjusted_mode */ -# - if (intel_sdvo->is_tv || intel_sdvo->is_lvds) { -# - intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); -# + intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); -# + if (intel_sdvo->is_tv || intel_sdvo->is_lvds) -# input_dtd.part2.sdvo_flags = intel_sdvo->sdvo_flags; -# - } else -# - intel_sdvo_get_dtd_from_mode(&input_dtd, mode); -# -# /* If it's a TV, we already set the output timing in mode_fixup. -# * Otherwise, the output timing is equal to the input timing. - -Due to questions raised in review, below a more elaborate analysis of -the bug at hand: - -Sdvo seems to have two timings, one is the output timing which will be -sent over whatever is connected on the other side of the sdvo chip (panel, -hdmi screen, tv), the other is the input timing which will be generated by -the gmch pipe. It looks like sdvo is expected to scale between the two. - -To make things slightly more complicated, we have a bunch of special -cases: -- For lvds panel we always use a fixed output timing, namely - intel_sdvo->sdvo_lvds_fixed_mode, hence that special case. -- Sdvo has an interface to generate a preferred input timing for a given - output timing. This is the confusing thing that I've tried to clear up - with the follow-on patches. -- A special requirement is that the input pixel clock needs to be between - 100MHz and 200MHz (likely to keep it within the electromechanical design - range of PCIe), 270MHz on later gen4+. Lower pixel clocks are - doubled/quadrupled. - -The thing this patch tries to fix is that the pipe needs to be -explicitly instructed to double/quadruple the pixels and needs the -correspondingly higher pixel clock, whereas the sdvo adaptor seems to -do that itself and needs the unadjusted pixel clock. For the sdvo -encode side we already set the pixel mutliplier with a different -command (0x21). - -This patch tries to fix this mess by: -- Keeping the output mode timing in the unadjusted plain mode, safe - for the lvds case. -- Storing the input timing in the adjusted_mode with the adjusted - pixel clock. This way we don't need to frob around with the core - crtc mode set code. -- Fixing up the pixelclock when constructing the sdvo dtd timing - struct. This is why the first hunk of the patch is an integral part - of the series. -- Dropping the is_tv special case because input_dtd is equivalent to - adjusted_mode after these changes. Follow-up patches clear this up - further (by simply ripping out intel_sdvo->input_dtd because it's - not needed). - -v2: Extend commit message with an in-depth bug analysis. - -Reported-and-Tested-by: Bernard Blackham -Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=48157 -Reviewed-by: Jesse Barnes -Signed-off-by: Daniel Vetter -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/intel_sdvo.c | 34 ++++++++++++++++++---------------- - 1 file changed, 18 insertions(+), 16 deletions(-) - ---- a/drivers/gpu/drm/i915/intel_sdvo.c -+++ b/drivers/gpu/drm/i915/intel_sdvo.c -@@ -731,6 +731,7 @@ static void intel_sdvo_get_dtd_from_mode - uint16_t width, height; - uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len; - uint16_t h_sync_offset, v_sync_offset; -+ int mode_clock; - - width = mode->crtc_hdisplay; - height = mode->crtc_vdisplay; -@@ -745,7 +746,11 @@ static void intel_sdvo_get_dtd_from_mode - h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start; - v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start; - -- dtd->part1.clock = mode->clock / 10; -+ mode_clock = mode->clock; -+ mode_clock /= intel_mode_get_pixel_multiplier(mode) ?: 1; -+ mode_clock /= 10; -+ dtd->part1.clock = mode_clock; -+ - dtd->part1.h_active = width & 0xff; - dtd->part1.h_blank = h_blank_len & 0xff; - dtd->part1.h_high = (((width >> 8) & 0xf) << 4) | -@@ -997,7 +1002,7 @@ static void intel_sdvo_mode_set(struct d - struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder); - u32 sdvox; - struct intel_sdvo_in_out_map in_out; -- struct intel_sdvo_dtd input_dtd; -+ struct intel_sdvo_dtd input_dtd, output_dtd; - int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); - int rate; - -@@ -1022,20 +1027,13 @@ static void intel_sdvo_mode_set(struct d - intel_sdvo->attached_output)) - return; - -- /* We have tried to get input timing in mode_fixup, and filled into -- * adjusted_mode. -- */ -- if (intel_sdvo->is_tv || intel_sdvo->is_lvds) { -- input_dtd = intel_sdvo->input_dtd; -- } else { -- /* Set the output timing to the screen */ -- if (!intel_sdvo_set_target_output(intel_sdvo, -- intel_sdvo->attached_output)) -- return; -- -- intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); -- (void) intel_sdvo_set_output_timing(intel_sdvo, &input_dtd); -- } -+ /* lvds has a special fixed output timing. */ -+ if (intel_sdvo->is_lvds) -+ intel_sdvo_get_dtd_from_mode(&output_dtd, -+ intel_sdvo->sdvo_lvds_fixed_mode); -+ else -+ intel_sdvo_get_dtd_from_mode(&output_dtd, mode); -+ (void) intel_sdvo_set_output_timing(intel_sdvo, &output_dtd); - - /* Set the input timing to the screen. Assume always input 0. */ - if (!intel_sdvo_set_target_input(intel_sdvo)) -@@ -1053,6 +1051,10 @@ static void intel_sdvo_mode_set(struct d - !intel_sdvo_set_tv_format(intel_sdvo)) - return; - -+ /* We have tried to get input timing in mode_fixup, and filled into -+ * adjusted_mode. -+ */ -+ intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); - (void) intel_sdvo_set_input_timing(intel_sdvo, &input_dtd); - - switch (pixel_multiplier) { -From 3a69ddd6f872180b6f61fda87152b37202118fbc Mon Sep 17 00:00:00 2001 -From: Kenneth Graunke -Date: Fri, 27 Apr 2012 12:44:41 -0700 -Subject: drm/i915: Set the Stencil Cache eviction policy to non-LRA mode. - -From: Kenneth Graunke - -commit 3a69ddd6f872180b6f61fda87152b37202118fbc upstream. - -Clearing bit 5 of CACHE_MODE_0 is necessary to prevent GPU hangs in -OpenGL programs such as Google MapsGL, Google Earth, and gzdoom when -using separate stencil buffers. Without it, the GPU tries to use the -LRA eviction policy, which isn't supported. This was supposed to be off -by default, but seems to be on for many machines. - -This cannot be done in gen6_init_clock_gating with most of the other -workaround bits; the render ring needs to exist. Otherwise, the -register write gets dropped on the floor (one printk will show it -changed, but a second printk immediately following shows the value -reverts to the old one). - -Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=47535 -Cc: Rob Castle -Cc: Eric Appleman -Cc: aaron667@gmx.net -Cc: Keith Packard -Signed-off-by: Kenneth Graunke -Reviewed-by: Daniel Vetter -Acked-by: Daniel Vetter -Signed-off-by: Dave Airlie -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/i915_reg.h | 1 + - drivers/gpu/drm/i915/intel_ringbuffer.c | 8 ++++++++ - 2 files changed, 9 insertions(+) - ---- a/drivers/gpu/drm/i915/i915_reg.h -+++ b/drivers/gpu/drm/i915/i915_reg.h -@@ -523,6 +523,7 @@ - #define CM0_MASK_SHIFT 16 - #define CM0_IZ_OPT_DISABLE (1<<6) - #define CM0_ZR_OPT_DISABLE (1<<5) -+#define CM0_STC_EVICT_DISABLE_LRA_SNB (1<<5) - #define CM0_DEPTH_EVICT_DISABLE (1<<4) - #define CM0_COLOR_EVICT_DISABLE (1<<3) - #define CM0_DEPTH_WRITE_DISABLE (1<<1) ---- a/drivers/gpu/drm/i915/intel_ringbuffer.c -+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c -@@ -417,6 +417,14 @@ static int init_render_ring(struct intel - if (INTEL_INFO(dev)->gen >= 6) { - I915_WRITE(INSTPM, - INSTPM_FORCE_ORDERING << 16 | INSTPM_FORCE_ORDERING); -+ -+ /* From the Sandybridge PRM, volume 1 part 3, page 24: -+ * "If this bit is set, STCunit will have LRA as replacement -+ * policy. [...] This bit must be reset. LRA replacement -+ * policy is not supported." -+ */ -+ I915_WRITE(CACHE_MODE_0, -+ CM0_STC_EVICT_DISABLE_LRA_SNB << CM0_MASK_SHIFT); - } - - return ret; -From 700698e7c303f5095107c62a81872c2c3dad1702 Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Fri, 27 Apr 2012 17:18:59 -0400 -Subject: drm/radeon/kms: need to set up ss on DP bridges as well - -From: Alex Deucher - -commit 700698e7c303f5095107c62a81872c2c3dad1702 upstream. - -Makes Nutmeg DP to VGA bridges work for me. - -Fixes: -https://bugs.freedesktop.org/show_bug.cgi?id=42490 - -Noticed by Jerome Glisse (after weeks of debugging). - -Signed-off-by: Alex Deucher -Signed-off-by: Dave Airlie -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/atombios_crtc.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/gpu/drm/radeon/atombios_crtc.c -+++ b/drivers/gpu/drm/radeon/atombios_crtc.c -@@ -912,8 +912,8 @@ static void atombios_crtc_set_pll(struct - break; - } - -- if (radeon_encoder->active_device & -- (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) { -+ if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || -+ (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) { - struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - struct drm_connector *connector = - radeon_get_connector_for_encoder(encoder); -From 00250ec90963b7ef6678438888f3244985ecde14 Mon Sep 17 00:00:00 2001 -From: Andre Przywara -Date: Mon, 9 Apr 2012 18:16:34 -0400 -Subject: hwmon: fam15h_power: fix bogus values with current BIOSes - -From: Andre Przywara - -commit 00250ec90963b7ef6678438888f3244985ecde14 upstream. - -Newer BKDG[1] versions recommend a different initialization value for -the running average range register in the northbridge. This improves -the power reading by avoiding counter saturations resulting in bogus -values for anything below about 80% of TDP power consumption. -Updated BIOSes will have this new value set up from the beginning, -but meanwhile we correct this value ourselves. -This needs to be done on all northbridges, even on those where the -driver itself does not register at. - -This fixes the driver on all current machines to provide proper -values for idle load. - -[1] -http://support.amd.com/us/Processor_TechDocs/42301_15h_Mod_00h-0Fh_BKDG.pdf -Chapter 3.8: D18F5xE0 Processor TDP Running Average (p. 452) - -Signed-off-by: Andre Przywara -Acked-by: Jean Delvare -[guenter.roeck@ericsson.com: Removed unnecessary return statement] -Signed-off-by: Guenter Roeck -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/hwmon/fam15h_power.c | 39 +++++++++++++++++++++++++++++++++++++++ - 1 file changed, 39 insertions(+) - ---- a/drivers/hwmon/fam15h_power.c -+++ b/drivers/hwmon/fam15h_power.c -@@ -122,6 +122,38 @@ static bool __devinit fam15h_power_is_in - return true; - } - -+/* -+ * Newer BKDG versions have an updated recommendation on how to properly -+ * initialize the running average range (was: 0xE, now: 0x9). This avoids -+ * counter saturations resulting in bogus power readings. -+ * We correct this value ourselves to cope with older BIOSes. -+ */ -+static void __devinit tweak_runavg_range(struct pci_dev *pdev) -+{ -+ u32 val; -+ const struct pci_device_id affected_device = { -+ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }; -+ -+ /* -+ * let this quirk apply only to the current version of the -+ * northbridge, since future versions may change the behavior -+ */ -+ if (!pci_match_id(&affected_device, pdev)) -+ return; -+ -+ pci_bus_read_config_dword(pdev->bus, -+ PCI_DEVFN(PCI_SLOT(pdev->devfn), 5), -+ REG_TDP_RUNNING_AVERAGE, &val); -+ if ((val & 0xf) != 0xe) -+ return; -+ -+ val &= ~0xf; -+ val |= 0x9; -+ pci_bus_write_config_dword(pdev->bus, -+ PCI_DEVFN(PCI_SLOT(pdev->devfn), 5), -+ REG_TDP_RUNNING_AVERAGE, val); -+} -+ - static void __devinit fam15h_power_init_data(struct pci_dev *f4, - struct fam15h_power_data *data) - { -@@ -155,6 +187,13 @@ static int __devinit fam15h_power_probe( - struct device *dev; - int err; - -+ /* -+ * though we ignore every other northbridge, we still have to -+ * do the tweaking on _each_ node in MCM processors as the counters -+ * are working hand-in-hand -+ */ -+ tweak_runavg_range(pdev); -+ - if (!fam15h_power_is_internal_node0(pdev)) { - err = -ENODEV; - goto exit; -From c3e40a9972428d6e2d8e287ed0233a57a218c30f Mon Sep 17 00:00:00 2001 -From: Guenter Roeck -Date: Wed, 25 Apr 2012 13:44:20 -0700 -Subject: hwmon: (fam15h_power) Fix pci_device_id array - -From: Guenter Roeck - -commit c3e40a9972428d6e2d8e287ed0233a57a218c30f upstream. - -pci_match_id() takes an *array* of IDs which must be properly zero- -terminated. - -Reported-by: Ben Hutchings -Signed-off-by: Guenter Roeck -Acked-by: Jean Delvare -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/hwmon/fam15h_power.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - ---- a/drivers/hwmon/fam15h_power.c -+++ b/drivers/hwmon/fam15h_power.c -@@ -128,17 +128,20 @@ static bool __devinit fam15h_power_is_in - * counter saturations resulting in bogus power readings. - * We correct this value ourselves to cope with older BIOSes. - */ -+static DEFINE_PCI_DEVICE_TABLE(affected_device) = { -+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, -+ { 0 } -+}; -+ - static void __devinit tweak_runavg_range(struct pci_dev *pdev) - { - u32 val; -- const struct pci_device_id affected_device = { -- PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }; - - /* - * let this quirk apply only to the current version of the - * northbridge, since future versions may change the behavior - */ -- if (!pci_match_id(&affected_device, pdev)) -+ if (!pci_match_id(affected_device, pdev)) - return; - - pci_bus_read_config_dword(pdev->bus, -From 089f9fba56faf33cc6dd2a6442b7ac92c58b8209 Mon Sep 17 00:00:00 2001 -From: Oleg Nesterov -Date: Mon, 16 Apr 2012 22:48:15 +0200 -Subject: i387: ptrace breaks the lazy-fpu-restore logic - -From: Oleg Nesterov - -commit 089f9fba56faf33cc6dd2a6442b7ac92c58b8209 upstream. - -Starting from 7e16838d "i387: support lazy restore of FPU state" -we assume that fpu_owner_task doesn't need restore_fpu_checking() -on the context switch, its FPU state should match what we already -have in the FPU on this CPU. - -However, debugger can change the tracee's FPU state, in this case -we should reset fpu.last_cpu to ensure fpu_lazy_restore() can't -return true. - -Change init_fpu() to do this, it is called by user_regset->set() -methods. - -Reported-by: Jan Kratochvil -Suggested-by: Linus Torvalds -Signed-off-by: Oleg Nesterov -Link: http://lkml.kernel.org/r/20120416204815.GB24884@redhat.com -Signed-off-by: H. Peter Anvin -Signed-off-by: Greg Kroah-Hartman - ---- - arch/x86/kernel/i387.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/x86/kernel/i387.c -+++ b/arch/x86/kernel/i387.c -@@ -154,6 +154,7 @@ int init_fpu(struct task_struct *tsk) - if (tsk_used_math(tsk)) { - if (HAVE_HWFP && tsk == current) - unlazy_fpu(tsk); -+ tsk->thread.fpu.last_cpu = ~0; - return 0; - } - -From 899c612d74d4a242158a4db20367388d6299c028 Mon Sep 17 00:00:00 2001 -From: Benjamin Herrenschmidt -Date: Fri, 20 Apr 2012 22:34:49 -0700 -Subject: Input: synaptics - fix regression with "image sensor" trackpads - -From: Benjamin Herrenschmidt - -commit 899c612d74d4a242158a4db20367388d6299c028 upstream. - -commit 7968a5dd492ccc38345013e534ad4c8d6eb60ed1 -Input: synaptics - add support for Relative mode - -Accidentally broke support for advanced gestures (multitouch) -on some trackpads such as the one in my ThinkPad X220 by -incorretly changing the condition for enabling them. This -restores it. - -Signed-off-by: Benjamin Herrenschmidt -Signed-off-by: Dmitry Torokhov -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/input/mouse/synaptics.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/input/mouse/synaptics.c -+++ b/drivers/input/mouse/synaptics.c -@@ -274,7 +274,8 @@ static int synaptics_set_advanced_gestur - static unsigned char param = 0xc8; - struct synaptics_data *priv = psmouse->private; - -- if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) -+ if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || -+ SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c))) - return 0; - - if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL)) -From 98a2139f4f4d7b5fcc3a54c7fddbe88612abed20 Mon Sep 17 00:00:00 2001 -From: Jan Kara -Date: Sat, 3 Sep 2011 01:09:43 +0200 -Subject: nfs: Enclose hostname in brackets when needed in - nfs_do_root_mount - -From: Jan Kara - -commit 98a2139f4f4d7b5fcc3a54c7fddbe88612abed20 upstream. - -When hostname contains colon (e.g. when it is an IPv6 address) it needs -to be enclosed in brackets to make parsing of NFS device string possible. -Fix nfs_do_root_mount() to enclose hostname properly when needed. NFS code -actually does not need this as it does not parse the string passed by -nfs_do_root_mount() but the device string is exposed to userspace in -/proc/mounts. - -CC: Josh Boyer -CC: Trond Myklebust -Signed-off-by: Jan Kara -Signed-off-by: Trond Myklebust -Signed-off-by: Greg Kroah-Hartman - ---- - fs/nfs/super.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - ---- a/fs/nfs/super.c -+++ b/fs/nfs/super.c -@@ -2707,11 +2707,15 @@ static struct vfsmount *nfs_do_root_moun - char *root_devname; - size_t len; - -- len = strlen(hostname) + 3; -+ len = strlen(hostname) + 5; - root_devname = kmalloc(len, GFP_KERNEL); - if (root_devname == NULL) - return ERR_PTR(-ENOMEM); -- snprintf(root_devname, len, "%s:/", hostname); -+ /* Does hostname needs to be enclosed in brackets? */ -+ if (strchr(hostname, ':')) -+ snprintf(root_devname, len, "[%s]:/", hostname); -+ else -+ snprintf(root_devname, len, "%s:/", hostname); - root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data); - kfree(root_devname); - return root_mnt; -From 8ccd271f7a3a846ce6f85ead0760d9d12994a611 Mon Sep 17 00:00:00 2001 -From: Fred Isaman -Date: Fri, 20 Apr 2012 14:47:35 -0400 -Subject: NFS: put open context on error in nfs_flush_multi - -From: Fred Isaman - -commit 8ccd271f7a3a846ce6f85ead0760d9d12994a611 upstream. - -Signed-off-by: Fred Isaman -Signed-off-by: Trond Myklebust -Signed-off-by: Greg Kroah-Hartman - ---- - fs/nfs/write.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/fs/nfs/write.c -+++ b/fs/nfs/write.c -@@ -974,7 +974,7 @@ out_bad: - while (!list_empty(res)) { - data = list_entry(res->next, struct nfs_write_data, list); - list_del(&data->list); -- nfs_writedata_free(data); -+ nfs_writedata_release(data); - } - nfs_redirty_request(req); - return -ENOMEM; -From 73fb7bc7c57d971b11f2e00536ac2d3e316e0609 Mon Sep 17 00:00:00 2001 -From: Fred Isaman -Date: Fri, 20 Apr 2012 14:47:34 -0400 -Subject: NFS: put open context on error in nfs_pagein_multi - -From: Fred Isaman - -commit 73fb7bc7c57d971b11f2e00536ac2d3e316e0609 upstream. - -Signed-off-by: Fred Isaman -Signed-off-by: Trond Myklebust -Signed-off-by: Greg Kroah-Hartman - ---- - fs/nfs/read.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/fs/nfs/read.c -+++ b/fs/nfs/read.c -@@ -324,7 +324,7 @@ out_bad: - while (!list_empty(res)) { - data = list_entry(res->next, struct nfs_read_data, list); - list_del(&data->list); -- nfs_readdata_free(data); -+ nfs_readdata_release(data); - } - nfs_readpage_release(req); - return -ENOMEM; -From 05ffe24f5290dc095f98fbaf84afe51ef404ccc5 Mon Sep 17 00:00:00 2001 -From: Trond Myklebust -Date: Wed, 18 Apr 2012 12:20:10 -0400 -Subject: NFSv4: Ensure that the LOCK code sets exception->inode - -From: Trond Myklebust - -commit 05ffe24f5290dc095f98fbaf84afe51ef404ccc5 upstream. - -All callers of nfs4_handle_exception() that need to handle -NFS4ERR_OPENMODE correctly should set exception->inode - -Signed-off-by: Trond Myklebust -Signed-off-by: Greg Kroah-Hartman - ---- - fs/nfs/nfs4proc.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - ---- a/fs/nfs/nfs4proc.c -+++ b/fs/nfs/nfs4proc.c -@@ -4460,7 +4460,9 @@ static int _nfs4_do_setlk(struct nfs4_st - static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request) - { - struct nfs_server *server = NFS_SERVER(state->inode); -- struct nfs4_exception exception = { }; -+ struct nfs4_exception exception = { -+ .inode = state->inode, -+ }; - int err; - - do { -@@ -4478,7 +4480,9 @@ static int nfs4_lock_reclaim(struct nfs4 - static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request) - { - struct nfs_server *server = NFS_SERVER(state->inode); -- struct nfs4_exception exception = { }; -+ struct nfs4_exception exception = { -+ .inode = state->inode, -+ }; - int err; - - err = nfs4_set_lock_state(state, request); -@@ -4558,6 +4562,7 @@ static int nfs4_proc_setlk(struct nfs4_s - { - struct nfs4_exception exception = { - .state = state, -+ .inode = state->inode, - }; - int err; - -From 55725513b5ef9d462aa3e18527658a0362aaae83 Mon Sep 17 00:00:00 2001 -From: Trond Myklebust -Date: Wed, 18 Apr 2012 12:48:35 -0400 -Subject: NFSv4: Ensure that we check lock exclusive/shared type against open modes - -From: Trond Myklebust - -commit 55725513b5ef9d462aa3e18527658a0362aaae83 upstream. - -Since we may be simulating flock() locks using NFS byte range locks, -we can't rely on the VFS having checked the file open mode for us. - -Signed-off-by: Trond Myklebust -Signed-off-by: Greg Kroah-Hartman - ---- - fs/nfs/nfs4proc.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/fs/nfs/nfs4proc.c -+++ b/fs/nfs/nfs4proc.c -@@ -4608,6 +4608,20 @@ nfs4_proc_lock(struct file *filp, int cm - - if (state == NULL) - return -ENOLCK; -+ /* -+ * Don't rely on the VFS having checked the file open mode, -+ * since it won't do this for flock() locks. -+ */ -+ switch (request->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) { -+ case F_RDLCK: -+ if (!(filp->f_mode & FMODE_READ)) -+ return -EBADF; -+ break; -+ case F_WRLCK: -+ if (!(filp->f_mode & FMODE_WRITE)) -+ return -EBADF; -+ } -+ - do { - status = nfs4_proc_setlk(state, cmd, request); - if ((status != -EAGAIN) || IS_SETLK(cmd)) -From 2b5f8b0b44e17e625cfba1e7b88db44f4dcc0441 Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Mon, 2 Apr 2012 10:51:55 +0200 -Subject: nl80211: ensure interface is up in various APIs - -From: Johannes Berg - -commit 2b5f8b0b44e17e625cfba1e7b88db44f4dcc0441 upstream. -[backported by Ben Greear] - -The nl80211 handling code should ensure as much as -it can that the interface is in a valid state, it -can certainly ensure the interface is running. - -Not doing so can cause calls through mac80211 into -the driver that result in warnings and unspecified -behaviour in the driver. - -Reported-by: Ben Greear -Signed-off-by: Johannes Berg -Signed-off-by: John W. Linville -Signed-off-by: Ben Greear -Signed-off-by: Greg Kroah-Hartman - ---- - net/wireless/nl80211.c | 29 +++++++++++++++++------------ - 1 file changed, 17 insertions(+), 12 deletions(-) - ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -1293,6 +1293,11 @@ static int nl80211_set_wiphy(struct sk_b - goto bad_res; - } - -+ if (!netif_running(netdev)) { -+ result = -ENETDOWN; -+ goto bad_res; -+ } -+ - nla_for_each_nested(nl_txq_params, - info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], - rem_txq_params) { -@@ -6262,7 +6267,7 @@ static struct genl_ops nl80211_ops[] = { - .doit = nl80211_get_key, - .policy = nl80211_policy, - .flags = GENL_ADMIN_PERM, -- .internal_flags = NL80211_FLAG_NEED_NETDEV | -+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_NEED_RTNL, - }, - { -@@ -6294,7 +6299,7 @@ static struct genl_ops nl80211_ops[] = { - .policy = nl80211_policy, - .flags = GENL_ADMIN_PERM, - .doit = nl80211_addset_beacon, -- .internal_flags = NL80211_FLAG_NEED_NETDEV | -+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_NEED_RTNL, - }, - { -@@ -6302,7 +6307,7 @@ static struct genl_ops nl80211_ops[] = { - .policy = nl80211_policy, - .flags = GENL_ADMIN_PERM, - .doit = nl80211_addset_beacon, -- .internal_flags = NL80211_FLAG_NEED_NETDEV | -+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_NEED_RTNL, - }, - { -@@ -6326,7 +6331,7 @@ static struct genl_ops nl80211_ops[] = { - .doit = nl80211_set_station, - .policy = nl80211_policy, - .flags = GENL_ADMIN_PERM, -- .internal_flags = NL80211_FLAG_NEED_NETDEV | -+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_NEED_RTNL, - }, - { -@@ -6342,7 +6347,7 @@ static struct genl_ops nl80211_ops[] = { - .doit = nl80211_del_station, - .policy = nl80211_policy, - .flags = GENL_ADMIN_PERM, -- .internal_flags = NL80211_FLAG_NEED_NETDEV | -+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_NEED_RTNL, - }, - { -@@ -6375,7 +6380,7 @@ static struct genl_ops nl80211_ops[] = { - .doit = nl80211_del_mpath, - .policy = nl80211_policy, - .flags = GENL_ADMIN_PERM, -- .internal_flags = NL80211_FLAG_NEED_NETDEV | -+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_NEED_RTNL, - }, - { -@@ -6383,7 +6388,7 @@ static struct genl_ops nl80211_ops[] = { - .doit = nl80211_set_bss, - .policy = nl80211_policy, - .flags = GENL_ADMIN_PERM, -- .internal_flags = NL80211_FLAG_NEED_NETDEV | -+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_NEED_RTNL, - }, - { -@@ -6409,7 +6414,7 @@ static struct genl_ops nl80211_ops[] = { - .doit = nl80211_get_mesh_config, - .policy = nl80211_policy, - /* can be retrieved by unprivileged users */ -- .internal_flags = NL80211_FLAG_NEED_NETDEV | -+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_NEED_RTNL, - }, - { -@@ -6542,7 +6547,7 @@ static struct genl_ops nl80211_ops[] = { - .doit = nl80211_setdel_pmksa, - .policy = nl80211_policy, - .flags = GENL_ADMIN_PERM, -- .internal_flags = NL80211_FLAG_NEED_NETDEV | -+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_NEED_RTNL, - }, - { -@@ -6550,7 +6555,7 @@ static struct genl_ops nl80211_ops[] = { - .doit = nl80211_setdel_pmksa, - .policy = nl80211_policy, - .flags = GENL_ADMIN_PERM, -- .internal_flags = NL80211_FLAG_NEED_NETDEV | -+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_NEED_RTNL, - }, - { -@@ -6558,7 +6563,7 @@ static struct genl_ops nl80211_ops[] = { - .doit = nl80211_flush_pmksa, - .policy = nl80211_policy, - .flags = GENL_ADMIN_PERM, -- .internal_flags = NL80211_FLAG_NEED_NETDEV | -+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_NEED_RTNL, - }, - { -@@ -6718,7 +6723,7 @@ static struct genl_ops nl80211_ops[] = { - .doit = nl80211_probe_client, - .policy = nl80211_policy, - .flags = GENL_ADMIN_PERM, -- .internal_flags = NL80211_FLAG_NEED_NETDEV | -+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | - NL80211_FLAG_NEED_RTNL, - }, - { -From 9883035ae7edef3ec62ad215611cb8e17d6a1a5d Mon Sep 17 00:00:00 2001 -From: Linus Torvalds -Date: Sun, 29 Apr 2012 13:12:42 -0700 -Subject: pipes: add a "packetized pipe" mode for writing - -From: Linus Torvalds - -commit 9883035ae7edef3ec62ad215611cb8e17d6a1a5d upstream. - -The actual internal pipe implementation is already really about -individual packets (called "pipe buffers"), and this simply exposes that -as a special packetized mode. - -When we are in the packetized mode (marked by O_DIRECT as suggested by -Alan Cox), a write() on a pipe will not merge the new data with previous -writes, so each write will get a pipe buffer of its own. The pipe -buffer is then marked with the PIPE_BUF_FLAG_PACKET flag, which in turn -will tell the reader side to break the read at that boundary (and throw -away any partial packet contents that do not fit in the read buffer). - -End result: as long as you do writes less than PIPE_BUF in size (so that -the pipe doesn't have to split them up), you can now treat the pipe as a -packet interface, where each read() system call will read one packet at -a time. You can just use a sufficiently big read buffer (PIPE_BUF is -sufficient, since bigger than that doesn't guarantee atomicity anyway), -and the return value of the read() will naturally give you the size of -the packet. - -NOTE! We do not support zero-sized packets, and zero-sized reads and -writes to a pipe continue to be no-ops. Also note that big packets will -currently be split at write time, but that the size at which that -happens is not really specified (except that it's bigger than PIPE_BUF). -Currently that limit is the system page size, but we might want to -explicitly support bigger packets some day. - -The main user for this is going to be the autofs packet interface, -allowing us to stop having to care so deeply about exact packet sizes -(which have had bugs with 32/64-bit compatibility modes). But user -space can create packetized pipes with "pipe2(fd, O_DIRECT)", which will -fail with an EINVAL on kernels that do not support this interface. - -Tested-by: Michael Tokarev -Cc: Alan Cox -Cc: David Miller -Cc: Ian Kent -Cc: Thomas Meyer -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - fs/pipe.c | 31 +++++++++++++++++++++++++++++-- - include/linux/pipe_fs_i.h | 1 + - 2 files changed, 30 insertions(+), 2 deletions(-) - ---- a/fs/pipe.c -+++ b/fs/pipe.c -@@ -345,6 +345,16 @@ static const struct pipe_buf_operations - .get = generic_pipe_buf_get, - }; - -+static const struct pipe_buf_operations packet_pipe_buf_ops = { -+ .can_merge = 0, -+ .map = generic_pipe_buf_map, -+ .unmap = generic_pipe_buf_unmap, -+ .confirm = generic_pipe_buf_confirm, -+ .release = anon_pipe_buf_release, -+ .steal = generic_pipe_buf_steal, -+ .get = generic_pipe_buf_get, -+}; -+ - static ssize_t - pipe_read(struct kiocb *iocb, const struct iovec *_iov, - unsigned long nr_segs, loff_t pos) -@@ -406,6 +416,13 @@ redo: - ret += chars; - buf->offset += chars; - buf->len -= chars; -+ -+ /* Was it a packet buffer? Clean up and exit */ -+ if (buf->flags & PIPE_BUF_FLAG_PACKET) { -+ total_len = chars; -+ buf->len = 0; -+ } -+ - if (!buf->len) { - buf->ops = NULL; - ops->release(pipe, buf); -@@ -458,6 +475,11 @@ redo: - return ret; - } - -+static inline int is_packetized(struct file *file) -+{ -+ return (file->f_flags & O_DIRECT) != 0; -+} -+ - static ssize_t - pipe_write(struct kiocb *iocb, const struct iovec *_iov, - unsigned long nr_segs, loff_t ppos) -@@ -592,6 +614,11 @@ redo2: - buf->ops = &anon_pipe_buf_ops; - buf->offset = 0; - buf->len = chars; -+ buf->flags = 0; -+ if (is_packetized(filp)) { -+ buf->ops = &packet_pipe_buf_ops; -+ buf->flags = PIPE_BUF_FLAG_PACKET; -+ } - pipe->nrbufs = ++bufs; - pipe->tmp_page = NULL; - -@@ -1012,7 +1039,7 @@ struct file *create_write_pipe(int flags - goto err_dentry; - f->f_mapping = inode->i_mapping; - -- f->f_flags = O_WRONLY | (flags & O_NONBLOCK); -+ f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT)); - f->f_version = 0; - - return f; -@@ -1056,7 +1083,7 @@ int do_pipe_flags(int *fd, int flags) - int error; - int fdw, fdr; - -- if (flags & ~(O_CLOEXEC | O_NONBLOCK)) -+ if (flags & ~(O_CLOEXEC | O_NONBLOCK | O_DIRECT)) - return -EINVAL; - - fw = create_write_pipe(flags); ---- a/include/linux/pipe_fs_i.h -+++ b/include/linux/pipe_fs_i.h -@@ -8,6 +8,7 @@ - #define PIPE_BUF_FLAG_LRU 0x01 /* page is on the LRU */ - #define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */ - #define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */ -+#define PIPE_BUF_FLAG_PACKET 0x08 /* read() as a packet */ - - /** - * struct pipe_buffer - a linux kernel pipe buffer -From fcbf94b9dedd2ce08e798a99aafc94fec8668161 Mon Sep 17 00:00:00 2001 -From: Linus Torvalds -Date: Sat, 28 Apr 2012 08:29:56 -0700 -Subject: Revert "autofs: work around unhappy compat problem on x86-64" - -From: Linus Torvalds - -commit fcbf94b9dedd2ce08e798a99aafc94fec8668161 upstream. - -This reverts commit a32744d4abae24572eff7269bc17895c41bd0085. - -While that commit was technically the right thing to do, and made the -x86-64 compat mode work identically to native 32-bit mode (and thus -fixing the problem with a 32-bit systemd install on a 64-bit kernel), it -turns out that the automount binaries had workarounds for this compat -problem. - -Now, the workarounds are disgusting: doing an "uname()" to find out the -architecture of the kernel, and then comparing it for the 64-bit cases -and fixing up the size of the read() in automount for those. And they -were confused: it's not actually a generic 64-bit issue at all, it's -very much tied to just x86-64, which has different alignment for an -'u64' in 64-bit mode than in 32-bit mode. - -But the end result is that fixing the compat layer actually breaks the -case of a 32-bit automount on a x86-64 kernel. - -There are various approaches to fix this (including just doing a -"strcmp()" on current->comm and comparing it to "automount"), but I -think that I will do the one that teaches pipes about a special "packet -mode", which will allow user space to not have to care too deeply about -the padding at the end of the autofs packet. - -That change will make the compat workaround unnecessary, so let's revert -it first, and get automount working again in compat mode. The -packetized pipes will then fix autofs for systemd. - -Reported-and-requested-by: Michael Tokarev -Cc: Ian Kent -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - fs/autofs4/autofs_i.h | 1 - - fs/autofs4/dev-ioctl.c | 1 - - fs/autofs4/inode.c | 2 -- - fs/autofs4/waitq.c | 22 +++------------------- - 4 files changed, 3 insertions(+), 23 deletions(-) - ---- a/fs/autofs4/autofs_i.h -+++ b/fs/autofs4/autofs_i.h -@@ -110,7 +110,6 @@ struct autofs_sb_info { - int sub_version; - int min_proto; - int max_proto; -- int compat_daemon; - unsigned long exp_timeout; - unsigned int type; - int reghost_enabled; ---- a/fs/autofs4/dev-ioctl.c -+++ b/fs/autofs4/dev-ioctl.c -@@ -385,7 +385,6 @@ static int autofs_dev_ioctl_setpipefd(st - sbi->pipefd = pipefd; - sbi->pipe = pipe; - sbi->catatonic = 0; -- sbi->compat_daemon = is_compat_task(); - } - out: - mutex_unlock(&sbi->wq_mutex); ---- a/fs/autofs4/inode.c -+++ b/fs/autofs4/inode.c -@@ -19,7 +19,6 @@ - #include - #include - #include --#include - #include "autofs_i.h" - #include - -@@ -225,7 +224,6 @@ int autofs4_fill_super(struct super_bloc - set_autofs_type_indirect(&sbi->type); - sbi->min_proto = 0; - sbi->max_proto = 0; -- sbi->compat_daemon = is_compat_task(); - mutex_init(&sbi->wq_mutex); - mutex_init(&sbi->pipe_mutex); - spin_lock_init(&sbi->fs_lock); ---- a/fs/autofs4/waitq.c -+++ b/fs/autofs4/waitq.c -@@ -91,24 +91,7 @@ static int autofs4_write(struct autofs_s - - return (bytes > 0); - } -- --/* -- * The autofs_v5 packet was misdesigned. -- * -- * The packets are identical on x86-32 and x86-64, but have different -- * alignment. Which means that 'sizeof()' will give different results. -- * Fix it up for the case of running 32-bit user mode on a 64-bit kernel. -- */ --static noinline size_t autofs_v5_packet_size(struct autofs_sb_info *sbi) --{ -- size_t pktsz = sizeof(struct autofs_v5_packet); --#if defined(CONFIG_X86_64) && defined(CONFIG_COMPAT) -- if (sbi->compat_daemon > 0) -- pktsz -= 4; --#endif -- return pktsz; --} -- -+ - static void autofs4_notify_daemon(struct autofs_sb_info *sbi, - struct autofs_wait_queue *wq, - int type) -@@ -172,7 +155,8 @@ static void autofs4_notify_daemon(struct - { - struct autofs_v5_packet *packet = &pkt.v5_pkt.v5_packet; - -- pktsz = autofs_v5_packet_size(sbi); -+ pktsz = sizeof(*packet); -+ - packet->wait_queue_token = wq->wait_queue_token; - packet->len = wq->name.len; - memcpy(packet->name, wq->name.name, wq->name.len); -From fb2cf2c660971bea0ad86a9a5c19ad39eab61344 Mon Sep 17 00:00:00 2001 -From: "he, bo" -Date: Wed, 25 Apr 2012 19:59:21 +0800 -Subject: sched: Fix OOPS when build_sched_domains() percpu allocation fails - -From: "he, bo" - -commit fb2cf2c660971bea0ad86a9a5c19ad39eab61344 upstream. - -Under extreme memory used up situations, percpu allocation -might fail. We hit it when system goes to suspend-to-ram, -causing a kworker panic: - - EIP: [] build_sched_domains+0x23a/0xad0 - Kernel panic - not syncing: Fatal exception - Pid: 3026, comm: kworker/u:3 - 3.0.8-137473-gf42fbef #1 - - Call Trace: - [] panic+0x66/0x16c - [...] - [] partition_sched_domains+0x287/0x4b0 - [] cpuset_update_active_cpus+0x1fe/0x210 - [] cpuset_cpu_inactive+0x1d/0x30 - [...] - -With this fix applied build_sched_domains() will return -ENOMEM and -the suspend attempt fails. - -Signed-off-by: he, bo -Reviewed-by: Zhang, Yanmin -Reviewed-by: Srivatsa S. Bhat -Signed-off-by: Peter Zijlstra -Cc: Linus Torvalds -Cc: Andrew Morton -Link: http://lkml.kernel.org/r/1335355161.5892.17.camel@hebo -[ So, we fail to deallocate a CPU because we cannot allocate RAM :-/ - I don't like that kind of sad behavior but nevertheless it should - not crash under high memory load. ] -Signed-off-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman - ---- - kernel/sched/core.c | 22 ++++++++++++++++------ - 1 file changed, 16 insertions(+), 6 deletions(-) - ---- a/kernel/sched/core.c -+++ b/kernel/sched/core.c -@@ -6334,16 +6334,26 @@ static void __sdt_free(const struct cpum - struct sd_data *sdd = &tl->data; - - for_each_cpu(j, cpu_map) { -- struct sched_domain *sd = *per_cpu_ptr(sdd->sd, j); -- if (sd && (sd->flags & SD_OVERLAP)) -- free_sched_groups(sd->groups, 0); -- kfree(*per_cpu_ptr(sdd->sd, j)); -- kfree(*per_cpu_ptr(sdd->sg, j)); -- kfree(*per_cpu_ptr(sdd->sgp, j)); -+ struct sched_domain *sd; -+ -+ if (sdd->sd) { -+ sd = *per_cpu_ptr(sdd->sd, j); -+ if (sd && (sd->flags & SD_OVERLAP)) -+ free_sched_groups(sd->groups, 0); -+ kfree(*per_cpu_ptr(sdd->sd, j)); -+ } -+ -+ if (sdd->sg) -+ kfree(*per_cpu_ptr(sdd->sg, j)); -+ if (sdd->sgp) -+ kfree(*per_cpu_ptr(sdd->sgp, j)); - } - free_percpu(sdd->sd); -+ sdd->sd = NULL; - free_percpu(sdd->sg); -+ sdd->sg = NULL; - free_percpu(sdd->sgp); -+ sdd->sgp = NULL; - } - } - -From db4c75cbebd7e5910cd3bcb6790272fcc3042857 Mon Sep 17 00:00:00 2001 -From: Steven Rostedt -Date: Thu, 19 Apr 2012 10:31:47 -0400 -Subject: tracing: Fix stacktrace of latency tracers (irqsoff and friends) - -From: Steven Rostedt - -commit db4c75cbebd7e5910cd3bcb6790272fcc3042857 upstream. - -While debugging a latency with someone on IRC (mirage335) on #linux-rt (OFTC), -we discovered that the stacktrace output of the latency tracers -(preemptirqsoff) was empty. - -This bug was caused by the creation of the dynamic length stack trace -again (like commit 12b5da3 "tracing: Fix ent_size in trace output" was). - -This bug is caused by the latency tracers requiring the next event -to determine the time between the current event and the next. But by -grabbing the next event, the iter->ent_size is set to the next event -instead of the current one. As the stacktrace event is the last event, -this makes the ent_size zero and causes nothing to be printed for -the stack trace. The dynamic stacktrace uses the ent_size to determine -how much of the stack can be printed. The ent_size of zero means -no stack. - -The simple fix is to save the iter->ent_size before finding the next event. - -Note, mirage335 asked to remain anonymous from LKML and git, so I will -not add the Reported-by and Tested-by tags, even though he did report -the issue and tested the fix. - -Signed-off-by: Steven Rostedt -Signed-off-by: Greg Kroah-Hartman - ---- - kernel/trace/trace_output.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/kernel/trace/trace_output.c -+++ b/kernel/trace/trace_output.c -@@ -650,6 +650,8 @@ int trace_print_lat_context(struct trace - { - u64 next_ts; - int ret; -+ /* trace_find_next_entry will reset ent_size */ -+ int ent_size = iter->ent_size; - struct trace_seq *s = &iter->seq; - struct trace_entry *entry = iter->ent, - *next_entry = trace_find_next_entry(iter, NULL, -@@ -658,6 +660,9 @@ int trace_print_lat_context(struct trace - unsigned long abs_usecs = ns2usecs(iter->ts - iter->tr->time_start); - unsigned long rel_usecs; - -+ /* Restore the original ent_size */ -+ iter->ent_size = ent_size; -+ - if (!next_entry) - next_ts = iter->ts; - rel_usecs = ns2usecs(next_ts - iter->ts); -From 5c22837adca7c30b66121cf18ad3e160134268d4 Mon Sep 17 00:00:00 2001 -From: Oliver Neukum -Date: Thu, 26 Apr 2012 21:59:10 +0200 -Subject: USB: cdc-wdm: fix race leading leading to memory corruption -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -From: Oliver Neukum - -commit 5c22837adca7c30b66121cf18ad3e160134268d4 upstream. - -This patch fixes a race whereby a pointer to a buffer -would be overwritten while the buffer was in use leading -to a double free and a memory leak. This causes crashes. -This bug was introduced in 2.6.34 - -Signed-off-by: Oliver Neukum -Tested-by: Bjørn Mork -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/class/cdc-wdm.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - ---- a/drivers/usb/class/cdc-wdm.c -+++ b/drivers/usb/class/cdc-wdm.c -@@ -108,8 +108,9 @@ static void wdm_out_callback(struct urb - spin_lock(&desc->iuspin); - desc->werr = urb->status; - spin_unlock(&desc->iuspin); -- clear_bit(WDM_IN_USE, &desc->flags); - kfree(desc->outbuf); -+ desc->outbuf = NULL; -+ clear_bit(WDM_IN_USE, &desc->flags); - wake_up(&desc->wait); - } - -@@ -312,7 +313,7 @@ static ssize_t wdm_write - if (we < 0) - return -EIO; - -- desc->outbuf = buf = kmalloc(count, GFP_KERNEL); -+ buf = kmalloc(count, GFP_KERNEL); - if (!buf) { - rv = -ENOMEM; - goto outnl; -@@ -376,10 +377,12 @@ static ssize_t wdm_write - req->wIndex = desc->inum; - req->wLength = cpu_to_le16(count); - set_bit(WDM_IN_USE, &desc->flags); -+ desc->outbuf = buf; - - rv = usb_submit_urb(desc->command, GFP_KERNEL); - if (rv < 0) { - kfree(buf); -+ desc->outbuf = NULL; - clear_bit(WDM_IN_USE, &desc->flags); - dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv); - } else { -From 151b61284776be2d6f02d48c23c3625678960b97 Mon Sep 17 00:00:00 2001 -From: Alan Stern -Date: Tue, 24 Apr 2012 14:07:22 -0400 -Subject: USB: EHCI: fix crash during suspend on ASUS computers - -From: Alan Stern - -commit 151b61284776be2d6f02d48c23c3625678960b97 upstream. - -This patch (as1545) fixes a problem affecting several ASUS computers: -The machine crashes or corrupts memory when going into suspend if the -ehci-hcd driver is bound to any controllers. Users have been forced -to unbind or unload ehci-hcd before putting their systems to sleep. - -After extensive testing, it was determined that the machines don't -like going into suspend when any EHCI controllers are in the PCI D3 -power state. Presumably this is a firmware bug, but there's nothing -we can do about it except to avoid putting the controllers in D3 -during system sleep. - -The patch adds a new flag to indicate whether the problem is present, -and avoids changing the controller's power state if the flag is set. -Runtime suspend is unaffected; this matters only for system suspend. -However as a side effect, the controller will not respond to remote -wakeup requests while the system is asleep. Hence USB wakeup is not -functional -- but of course, this is already true in the current state -of affairs. - -This fixes Bugzilla #42728. - -Signed-off-by: Alan Stern -Tested-by: Steven Rostedt -Tested-by: Andrey Rahmatullin -Tested-by: Oleksij Rempel (fishor) -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/core/hcd-pci.c | 9 +++++++++ - drivers/usb/host/ehci-pci.c | 8 ++++++++ - include/linux/usb/hcd.h | 2 ++ - 3 files changed, 19 insertions(+) - ---- a/drivers/usb/core/hcd-pci.c -+++ b/drivers/usb/core/hcd-pci.c -@@ -491,6 +491,15 @@ static int hcd_pci_suspend_noirq(struct - - pci_save_state(pci_dev); - -+ /* -+ * Some systems crash if an EHCI controller is in D3 during -+ * a sleep transition. We have to leave such controllers in D0. -+ */ -+ if (hcd->broken_pci_sleep) { -+ dev_dbg(dev, "Staying in PCI D0\n"); -+ return retval; -+ } -+ - /* If the root hub is dead rather than suspended, disallow remote - * wakeup. usb_hc_died() should ensure that both hosts are marked as - * dying, so we only need to check the primary roothub. ---- a/drivers/usb/host/ehci-pci.c -+++ b/drivers/usb/host/ehci-pci.c -@@ -144,6 +144,14 @@ static int ehci_pci_setup(struct usb_hcd - hcd->has_tt = 1; - tdi_reset(ehci); - } -+ if (pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK) { -+ /* EHCI #1 or #2 on 6 Series/C200 Series chipset */ -+ if (pdev->device == 0x1c26 || pdev->device == 0x1c2d) { -+ ehci_info(ehci, "broken D3 during system sleep on ASUS\n"); -+ hcd->broken_pci_sleep = 1; -+ device_set_wakeup_capable(&pdev->dev, false); -+ } -+ } - break; - case PCI_VENDOR_ID_TDI: - if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { ---- a/include/linux/usb/hcd.h -+++ b/include/linux/usb/hcd.h -@@ -126,6 +126,8 @@ struct usb_hcd { - unsigned wireless:1; /* Wireless USB HCD */ - unsigned authorized_default:1; - unsigned has_tt:1; /* Integrated TT in root hub */ -+ unsigned broken_pci_sleep:1; /* Don't put the -+ controller in PCI-D3 for system sleep */ - - int irq; /* irq allocated */ - void __iomem *regs; /* device memory/io */ -From 15b120d67019d691e4389372967332d74a80522a Mon Sep 17 00:00:00 2001 -From: Felipe Balbi -Date: Wed, 18 Apr 2012 13:59:30 +0300 -Subject: usb: gadget: dummy: do not call pullup() on udc_stop() - -From: Felipe Balbi - -commit 15b120d67019d691e4389372967332d74a80522a upstream. - -pullup() is already called properly by udc-core.c and -there's no need to call it from udc_stop(), in fact that -will cause issues. - -Reviewed-by: Alexander Shishkin -Acked-by: Alan Stern -Signed-off-by: Felipe Balbi -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/gadget/dummy_hcd.c | 1 - - 1 file changed, 1 deletion(-) - ---- a/drivers/usb/gadget/dummy_hcd.c -+++ b/drivers/usb/gadget/dummy_hcd.c -@@ -924,7 +924,6 @@ static int dummy_udc_stop(struct usb_gad - - dum->driver = NULL; - -- dummy_pullup(&dum->gadget, 0); - return 0; - } - -From c85dcdac5852295cf6822f5c4331a6ddab72581f Mon Sep 17 00:00:00 2001 -From: Alan Stern -Date: Wed, 11 Apr 2012 16:09:10 -0400 -Subject: USB: gadget: storage gadgets send wrong error code for unknown commands - -From: Alan Stern - -commit c85dcdac5852295cf6822f5c4331a6ddab72581f upstream. - -This patch (as1539) fixes a minor bug in the mass-storage gadget -drivers. When an unknown command is received, the error code sent -back is "Invalid Field in CDB" rather than "Invalid Command". This is -because the bitmask of CDB bytes allowed to be nonzero is incorrect. - -When handling an unknown command, we don't care which command bytes -are nonzero. All the bits in the mask should be set, not just eight -of them. - -Signed-off-by: Alan Stern -CC: -Signed-off-by: Felipe Balbi -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/gadget/f_mass_storage.c | 2 +- - drivers/usb/gadget/file_storage.c | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/usb/gadget/f_mass_storage.c -+++ b/drivers/usb/gadget/f_mass_storage.c -@@ -2190,7 +2190,7 @@ unknown_cmnd: - common->data_size_from_cmnd = 0; - sprintf(unknown, "Unknown x%02x", common->cmnd[0]); - reply = check_command(common, common->cmnd_size, -- DATA_DIR_UNKNOWN, 0xff, 0, unknown); -+ DATA_DIR_UNKNOWN, ~0, 0, unknown); - if (reply == 0) { - common->curlun->sense_data = SS_INVALID_COMMAND; - reply = -EINVAL; ---- a/drivers/usb/gadget/file_storage.c -+++ b/drivers/usb/gadget/file_storage.c -@@ -2579,7 +2579,7 @@ static int do_scsi_command(struct fsg_de - fsg->data_size_from_cmnd = 0; - sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]); - if ((reply = check_command(fsg, fsg->cmnd_size, -- DATA_DIR_UNKNOWN, 0xff, 0, unknown)) == 0) { -+ DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) { - fsg->curlun->sense_data = SS_INVALID_COMMAND; - reply = -EINVAL; - } -From 6f6543f53f9ce136e01d7114bf6f0818ca54fb41 Mon Sep 17 00:00:00 2001 -From: Laurent Pinchart -Date: Tue, 24 Apr 2012 11:29:42 +0200 -Subject: usb gadget: uvc: uvc_request_data::length field must be signed - -From: Laurent Pinchart - -commit 6f6543f53f9ce136e01d7114bf6f0818ca54fb41 upstream. - -The field is used to pass the UVC request data length, but can also be -used to signal an error when setting it to a negative value. Switch from -unsigned int to __s32. - -Reported-by: Fernandez Gonzalo -Signed-off-by: Laurent Pinchart -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/gadget/uvc.h | 2 +- - drivers/usb/gadget/uvc_v4l2.c | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/usb/gadget/uvc.h -+++ b/drivers/usb/gadget/uvc.h -@@ -28,7 +28,7 @@ - - struct uvc_request_data - { -- unsigned int length; -+ __s32 length; - __u8 data[60]; - }; - ---- a/drivers/usb/gadget/uvc_v4l2.c -+++ b/drivers/usb/gadget/uvc_v4l2.c -@@ -39,7 +39,7 @@ uvc_send_response(struct uvc_device *uvc - if (data->length < 0) - return usb_ep_set_halt(cdev->gadget->ep0); - -- req->length = min(uvc->event_length, data->length); -+ req->length = min_t(unsigned int, uvc->event_length, data->length); - req->zero = data->length < uvc->event_length; - req->dma = DMA_ADDR_INVALID; - -From cbf2829b61c136edcba302a5e1b6b40e97d32c00 Mon Sep 17 00:00:00 2001 -From: Bryan O'Donoghue -Date: Wed, 18 Apr 2012 17:37:39 +0100 -Subject: x86, apic: APIC code touches invalid MSR on P5 class machines - -From: Bryan O'Donoghue - -commit cbf2829b61c136edcba302a5e1b6b40e97d32c00 upstream. - -Current APIC code assumes MSR_IA32_APICBASE is present for all systems. -Pentium Classic P5 and friends didn't have this MSR. MSR_IA32_APICBASE -was introduced as an architectural MSR by Intel @ P6. - -Code paths that can touch this MSR invalidly are when vendor == Intel && -cpu-family == 5 and APIC bit is set in CPUID - or when you simply pass -lapic on the kernel command line, on a P5. - -The below patch stops Linux incorrectly interfering with the -MSR_IA32_APICBASE for P5 class machines. Other code paths exist that -touch the MSR - however those paths are not currently reachable for a -conformant P5. - -Signed-off-by: Bryan O'Donoghue -Link: http://lkml.kernel.org/r/4F8EEDD3.1080404@linux.intel.com -Signed-off-by: H. Peter Anvin -Signed-off-by: Greg Kroah-Hartman - ---- - arch/x86/kernel/apic/apic.c | 34 ++++++++++++++++++++-------------- - 1 file changed, 20 insertions(+), 14 deletions(-) - ---- a/arch/x86/kernel/apic/apic.c -+++ b/arch/x86/kernel/apic/apic.c -@@ -1632,9 +1632,11 @@ static int __init apic_verify(void) - mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; - - /* The BIOS may have set up the APIC at some other address */ -- rdmsr(MSR_IA32_APICBASE, l, h); -- if (l & MSR_IA32_APICBASE_ENABLE) -- mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; -+ if (boot_cpu_data.x86 >= 6) { -+ rdmsr(MSR_IA32_APICBASE, l, h); -+ if (l & MSR_IA32_APICBASE_ENABLE) -+ mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; -+ } - - pr_info("Found and enabled local APIC!\n"); - return 0; -@@ -1652,13 +1654,15 @@ int __init apic_force_enable(unsigned lo - * MSR. This can only be done in software for Intel P6 or later - * and AMD K7 (Model > 1) or later. - */ -- rdmsr(MSR_IA32_APICBASE, l, h); -- if (!(l & MSR_IA32_APICBASE_ENABLE)) { -- pr_info("Local APIC disabled by BIOS -- reenabling.\n"); -- l &= ~MSR_IA32_APICBASE_BASE; -- l |= MSR_IA32_APICBASE_ENABLE | addr; -- wrmsr(MSR_IA32_APICBASE, l, h); -- enabled_via_apicbase = 1; -+ if (boot_cpu_data.x86 >= 6) { -+ rdmsr(MSR_IA32_APICBASE, l, h); -+ if (!(l & MSR_IA32_APICBASE_ENABLE)) { -+ pr_info("Local APIC disabled by BIOS -- reenabling.\n"); -+ l &= ~MSR_IA32_APICBASE_BASE; -+ l |= MSR_IA32_APICBASE_ENABLE | addr; -+ wrmsr(MSR_IA32_APICBASE, l, h); -+ enabled_via_apicbase = 1; -+ } - } - return apic_verify(); - } -@@ -2204,10 +2208,12 @@ static void lapic_resume(void) - * FIXME! This will be wrong if we ever support suspend on - * SMP! We'll need to do this as part of the CPU restore! - */ -- rdmsr(MSR_IA32_APICBASE, l, h); -- l &= ~MSR_IA32_APICBASE_BASE; -- l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; -- wrmsr(MSR_IA32_APICBASE, l, h); -+ if (boot_cpu_data.x86 >= 6) { -+ rdmsr(MSR_IA32_APICBASE, l, h); -+ l &= ~MSR_IA32_APICBASE_BASE; -+ l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; -+ wrmsr(MSR_IA32_APICBASE, l, h); -+ } - } - - maxlvt = lapic_get_maxlvt(); -From 283c1f2558ef4a4411fe908364b15b73b6ab44cf Mon Sep 17 00:00:00 2001 -From: Andreas Herrmann -Date: Thu, 12 Apr 2012 16:51:57 +0200 -Subject: x86, microcode: Ensure that module is only loaded on supported AMD CPUs - -From: Andreas Herrmann - -commit 283c1f2558ef4a4411fe908364b15b73b6ab44cf upstream. - -Exit early when there's no support for a particular CPU family. Also, -fixup the "no support for this CPU vendor" to be issued only when the -driver is attempted to be loaded on an unsupported vendor. - -Cc: Tigran Aivazian -Signed-off-by: Andreas Herrmann -Acked-by: Greg Kroah-Hartman -Link: http://lkml.kernel.org/r/20120411163849.GE4794@alberich.amd.com -[Boris: add a commit msg because Andreas is lazy] -Signed-off-by: Borislav Petkov -Signed-off-by: Greg Kroah-Hartman - ---- - arch/x86/kernel/microcode_amd.c | 12 +++++++----- - arch/x86/kernel/microcode_core.c | 6 +++--- - 2 files changed, 10 insertions(+), 8 deletions(-) - ---- a/arch/x86/kernel/microcode_amd.c -+++ b/arch/x86/kernel/microcode_amd.c -@@ -82,11 +82,6 @@ static int collect_cpu_info_amd(int cpu, - { - struct cpuinfo_x86 *c = &cpu_data(cpu); - -- if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { -- pr_warning("CPU%d: family %d not supported\n", cpu, c->x86); -- return -1; -- } -- - csig->rev = c->microcode; - pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev); - -@@ -380,6 +375,13 @@ static struct microcode_ops microcode_am - - struct microcode_ops * __init init_amd_microcode(void) - { -+ struct cpuinfo_x86 *c = &cpu_data(0); -+ -+ if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { -+ pr_warning("AMD CPU family 0x%x not supported\n", c->x86); -+ return NULL; -+ } -+ - patch = (void *)get_zeroed_page(GFP_KERNEL); - if (!patch) - return NULL; ---- a/arch/x86/kernel/microcode_core.c -+++ b/arch/x86/kernel/microcode_core.c -@@ -511,11 +511,11 @@ static int __init microcode_init(void) - microcode_ops = init_intel_microcode(); - else if (c->x86_vendor == X86_VENDOR_AMD) - microcode_ops = init_amd_microcode(); -- -- if (!microcode_ops) { -+ else - pr_err("no support for this CPU vendor\n"); -+ -+ if (!microcode_ops) - return -ENODEV; -- } - - microcode_pdev = platform_device_register_simple("microcode", -1, - NULL, 0); -From a956bd6f8583326b18348ab1452b4686778f785d Mon Sep 17 00:00:00 2001 -From: Andreas Herrmann -Date: Thu, 12 Apr 2012 16:48:01 +0200 -Subject: x86, microcode: Fix sysfs warning during module unload on unsupported CPUs - -From: Andreas Herrmann - -commit a956bd6f8583326b18348ab1452b4686778f785d upstream. - -Loading the microcode driver on an unsupported CPU and subsequently -unloading the driver causes - - WARNING: at fs/sysfs/group.c:138 mc_device_remove+0x5f/0x70 [microcode]() - Hardware name: 01972NG - sysfs group ffffffffa00013d0 not found for kobject 'cpu0' - Modules linked in: snd_hda_codec_hdmi snd_hda_codec_conexant snd_hda_intel btusb snd_hda_codec bluetooth thinkpad_acpi rfkill microcode(-) [last unloaded: cfg80211] - Pid: 4560, comm: modprobe Not tainted 3.4.0-rc2-00002-g258f742 #5 - Call Trace: - [] ? warn_slowpath_common+0x7b/0xc0 - [] ? warn_slowpath_fmt+0x45/0x50 - [] ? sysfs_remove_group+0x34/0x120 - [] ? mc_device_remove+0x5f/0x70 [microcode] - [] ? subsys_interface_unregister+0x69/0xa0 - [] ? mutex_lock+0x16/0x40 - [] ? microcode_exit+0x50/0x92 [microcode] - [] ? sys_delete_module+0x16d/0x260 - [] ? wait_iff_congested+0x45/0x110 - [] ? page_fault+0x1f/0x30 - [] ? system_call_fastpath+0x16/0x1b - -on recent kernels. - -This is due to commit 8a25a2fd126c ("cpu: convert 'cpu' and -'machinecheck' sysdev_class to a regular subsystem") which renders -commit 6c53cbfced04 ("x86, microcode: Correct sysdev_add error path") -useless. - -See http://marc.info/?l=linux-kernel&m=133416246406478 - -Avoid above warning by restoring the old driver behaviour before -6c53cbfced04 ("x86, microcode: Correct sysdev_add error path"). - -Cc: Tigran Aivazian -Signed-off-by: Andreas Herrmann -Acked-by: Greg Kroah-Hartman -Link: http://lkml.kernel.org/r/20120411163849.GE4794@alberich.amd.com -Signed-off-by: Borislav Petkov -Signed-off-by: Greg Kroah-Hartman - ---- - arch/x86/kernel/microcode_core.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/arch/x86/kernel/microcode_core.c -+++ b/arch/x86/kernel/microcode_core.c -@@ -418,10 +418,8 @@ static int mc_device_add(struct device * - if (err) - return err; - -- if (microcode_init_cpu(cpu) == UCODE_ERROR) { -- sysfs_remove_group(&dev->kobj, &mc_attr_group); -+ if (microcode_init_cpu(cpu) == UCODE_ERROR) - return -EINVAL; -- } - - return err; - } -From 68894632afb2729a1d8785c877840953894c7283 Mon Sep 17 00:00:00 2001 -From: Andreas Herrmann -Date: Mon, 2 Apr 2012 18:06:48 +0200 -Subject: x86/platform: Remove incorrect error message in x86_default_fixup_cpu_id() - -From: Andreas Herrmann - -commit 68894632afb2729a1d8785c877840953894c7283 upstream. - -It's only called from amd.c:srat_detect_node(). The introduced -condition for calling the fixup code is true for all AMD -multi-node processors, e.g. Magny-Cours and Interlagos. There we -have 2 NUMA nodes on one socket. Thus there are cores having -different numa-node-id but with equal phys_proc_id. - -There is no point to print error messages in such a situation. - -The confusing/misleading error message was introduced with -commit 64be4c1c2428e148de6081af235e2418e6a66dda ("x86: Add -x86_init platform override to fix up NUMA core numbering"). - -Remove the default fixup function (especially the error message) -and replace it by a NULL pointer check, move the -Numascale-specific condition for calling the fixup into the -fixup-function itself and slightly adapt the comment. - -Signed-off-by: Andreas Herrmann -Acked-by: Borislav Petkov -Cc: -Cc: -Cc: -Link: http://lkml.kernel.org/r/20120402160648.GR27684@alberich.amd.com -Signed-off-by: Ingo Molnar -Signed-off-by: Greg Kroah-Hartman - ---- - arch/x86/include/asm/x86_init.h | 1 - - arch/x86/kernel/apic/apic_numachip.c | 7 +++++-- - arch/x86/kernel/cpu/amd.c | 7 ++++--- - arch/x86/kernel/cpu/common.c | 9 --------- - arch/x86/kernel/x86_init.c | 1 - - 5 files changed, 9 insertions(+), 16 deletions(-) - ---- a/arch/x86/include/asm/x86_init.h -+++ b/arch/x86/include/asm/x86_init.h -@@ -189,6 +189,5 @@ extern struct x86_msi_ops x86_msi; - - extern void x86_init_noop(void); - extern void x86_init_uint_noop(unsigned int unused); --extern void x86_default_fixup_cpu_id(struct cpuinfo_x86 *c, int node); - - #endif ---- a/arch/x86/kernel/apic/apic_numachip.c -+++ b/arch/x86/kernel/apic/apic_numachip.c -@@ -201,8 +201,11 @@ static void __init map_csrs(void) - - static void fixup_cpu_id(struct cpuinfo_x86 *c, int node) - { -- c->phys_proc_id = node; -- per_cpu(cpu_llc_id, smp_processor_id()) = node; -+ -+ if (c->phys_proc_id != node) { -+ c->phys_proc_id = node; -+ per_cpu(cpu_llc_id, smp_processor_id()) = node; -+ } - } - - static int __init numachip_system_init(void) ---- a/arch/x86/kernel/cpu/amd.c -+++ b/arch/x86/kernel/cpu/amd.c -@@ -352,10 +352,11 @@ static void __cpuinit srat_detect_node(s - node = per_cpu(cpu_llc_id, cpu); - - /* -- * If core numbers are inconsistent, it's likely a multi-fabric platform, -- * so invoke platform-specific handler -+ * On multi-fabric platform (e.g. Numascale NumaChip) a -+ * platform-specific handler needs to be called to fixup some -+ * IDs of the CPU. - */ -- if (c->phys_proc_id != node) -+ if (x86_cpuinit.fixup_cpu_id) - x86_cpuinit.fixup_cpu_id(c, node); - - if (!node_online(node)) { ---- a/arch/x86/kernel/cpu/common.c -+++ b/arch/x86/kernel/cpu/common.c -@@ -1163,15 +1163,6 @@ static void dbg_restore_debug_regs(void) - #endif /* ! CONFIG_KGDB */ - - /* -- * Prints an error where the NUMA and configured core-number mismatch and the -- * platform didn't override this to fix it up -- */ --void __cpuinit x86_default_fixup_cpu_id(struct cpuinfo_x86 *c, int node) --{ -- pr_err("NUMA core number %d differs from configured core number %d\n", node, c->phys_proc_id); --} -- --/* - * cpu_init() initializes state that is per-CPU. Some data is already - * initialized (naturally) in the bootstrap process, such as the GDT - * and IDT. We reload them nevertheless, this function acts as a ---- a/arch/x86/kernel/x86_init.c -+++ b/arch/x86/kernel/x86_init.c -@@ -92,7 +92,6 @@ struct x86_init_ops x86_init __initdata - - struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = { - .setup_percpu_clockev = setup_secondary_APIC_clock, -- .fixup_cpu_id = x86_default_fixup_cpu_id, - }; - - static void default_nmi_init(void) { }; -From 7eb7ce4d2e8991aff4ecb71a81949a907ca755ac Mon Sep 17 00:00:00 2001 -From: David Vrabel -Date: Thu, 26 Apr 2012 19:44:06 +0100 -Subject: xen: correctly check for pending events when restoring irq flags - -From: David Vrabel - -commit 7eb7ce4d2e8991aff4ecb71a81949a907ca755ac upstream. - -In xen_restore_fl_direct(), xen_force_evtchn_callback() was being -called even if no events were pending. This resulted in (depending on -workload) about a 100 times as many xen_version hypercalls as -necessary. - -Fix this by correcting the sense of the conditional jump. - -This seems to give a significant performance benefit for some -workloads. - -There is some subtle tricksy "..since the check here is trying to -check both pending and masked in a single cmpw, but I think this is -correct. It will call check_events now only when the combined -mask+pending word is 0x0001 (aka unmasked, pending)." (Ian) - -Acked-by: Ian Campbell -Signed-off-by: David Vrabel -Signed-off-by: Konrad Rzeszutek Wilk -Signed-off-by: Greg Kroah-Hartman - ---- - arch/x86/xen/xen-asm.S | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/x86/xen/xen-asm.S -+++ b/arch/x86/xen/xen-asm.S -@@ -96,7 +96,7 @@ ENTRY(xen_restore_fl_direct) - - /* check for unmasked and pending */ - cmpw $0x0001, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_pending -- jz 1f -+ jnz 1f - 2: call check_events - 1: - ENDPATCH(xen_restore_fl_direct) -From cf405ae612b0f7e2358db7ff594c0e94846137aa Mon Sep 17 00:00:00 2001 -From: Konrad Rzeszutek Wilk -Date: Thu, 26 Apr 2012 13:50:03 -0400 -Subject: xen/smp: Fix crash when booting with ACPI hotplug CPUs. - -From: Konrad Rzeszutek Wilk - -commit cf405ae612b0f7e2358db7ff594c0e94846137aa upstream. - -When we boot on a machine that can hotplug CPUs and we -are using 'dom0_max_vcpus=X' on the Xen hypervisor line -to clip the amount of CPUs available to the initial domain, -we get this: - -(XEN) Command line: com1=115200,8n1 dom0_mem=8G noreboot dom0_max_vcpus=8 sync_console mce_verbosity=verbose console=com1,vga loglvl=all guest_loglvl=all -.. snip.. -DMI: Intel Corporation S2600CP/S2600CP, BIOS SE5C600.86B.99.99.x032.072520111118 07/25/2011 -.. snip. -SMP: Allowing 64 CPUs, 32 hotplug CPUs -installing Xen timer for CPU 7 -cpu 7 spinlock event irq 361 -NMI watchdog: disabled (cpu7): hardware events not enabled -Brought up 8 CPUs -.. snip.. - [acpi processor finds the CPUs are not initialized and starts calling - arch_register_cpu, which creates /sys/devices/system/cpu/cpu8/online] -CPU 8 got hotplugged -CPU 9 got hotplugged -CPU 10 got hotplugged -.. snip.. -initcall 1_acpi_battery_init_async+0x0/0x1b returned 0 after 406 usecs -calling erst_init+0x0/0x2bb @ 1 - - [and the scheduler sticks newly started tasks on the new CPUs, but - said CPUs cannot be initialized b/c the hypervisor has limited the - amount of vCPUS to 8 - as per the dom0_max_vcpus=8 flag. - The spinlock tries to kick the other CPU, but the structure for that - is not initialized and we crash.] -BUG: unable to handle kernel paging request at fffffffffffffed8 -IP: [] xen_spin_lock+0x29/0x60 -PGD 180d067 PUD 180e067 PMD 0 -Oops: 0002 [#1] SMP -CPU 7 -Modules linked in: - -Pid: 1, comm: swapper/0 Not tainted 3.4.0-rc2upstream-00001-gf5154e8 #1 Intel Corporation S2600CP/S2600CP -RIP: e030:[] [] xen_spin_lock+0x29/0x60 -RSP: e02b:ffff8801fb9b3a70 EFLAGS: 00010282 - -With this patch, we cap the amount of vCPUS that the initial domain -can run, to exactly what dom0_max_vcpus=X has specified. - -In the future, if there is a hypercall that will allow a running -domain to expand past its initial set of vCPUS, this patch should -be re-evaluated. - -Signed-off-by: Konrad Rzeszutek Wilk -Signed-off-by: Greg Kroah-Hartman - ---- - arch/x86/xen/smp.c | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - ---- a/arch/x86/xen/smp.c -+++ b/arch/x86/xen/smp.c -@@ -172,6 +172,7 @@ static void __init xen_fill_possible_map - static void __init xen_filter_cpu_maps(void) - { - int i, rc; -+ unsigned int subtract = 0; - - if (!xen_initial_domain()) - return; -@@ -186,8 +187,22 @@ static void __init xen_filter_cpu_maps(v - } else { - set_cpu_possible(i, false); - set_cpu_present(i, false); -+ subtract++; - } - } -+#ifdef CONFIG_HOTPLUG_CPU -+ /* This is akin to using 'nr_cpus' on the Linux command line. -+ * Which is OK as when we use 'dom0_max_vcpus=X' we can only -+ * have up to X, while nr_cpu_ids is greater than X. This -+ * normally is not a problem, except when CPU hotplugging -+ * is involved and then there might be more than X CPUs -+ * in the guest - which will not work as there is no -+ * hypercall to expand the max number of VCPUs an already -+ * running guest has. So cap it up to X. */ -+ if (subtract) -+ nr_cpu_ids = nr_cpu_ids - subtract; -+#endif -+ - } - - static void __init xen_smp_prepare_boot_cpu(void) From 33a9dbb6ec030837c1193f832016d0b9ee4bfff7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 7 May 2012 14:50:48 -0300 Subject: [PATCH 375/487] Fix DVB-S zig-zag logic This logic got broken by the dvb_frontend.c rewrite. Signed-off-by: Mauro Carvalho Chehab --- dvbs-fix-zigzag.patch | 15 +++++++++++++++ kernel.spec | 7 ++++++- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 dvbs-fix-zigzag.patch diff --git a/dvbs-fix-zigzag.patch b/dvbs-fix-zigzag.patch new file mode 100644 index 000000000..4bc9daaf4 --- /dev/null +++ b/dvbs-fix-zigzag.patch @@ -0,0 +1,15 @@ +diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c +index 39696c6..de7dc29 100644 +--- a/drivers/media/dvb/dvb-core/dvb_frontend.c ++++ b/drivers/media/dvb/dvb-core/dvb_frontend.c +@@ -1898,6 +1898,10 @@ static int dtv_set_frontend(struct dvb_frontend *fe) + } else { + /* default values */ + switch (c->delivery_system) { ++ case SYS_DVBS: ++ case SYS_DVBS2: ++ case SYS_ISDBS: ++ case SYS_TURBO: + case SYS_DVBC_ANNEX_A: + case SYS_DVBC_ANNEX_C: + fepriv->min_delay = HZ / 20; diff --git a/kernel.spec b/kernel.spec index 5bbae6b80..b8c6ddbcf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -6,7 +6,7 @@ Summary: The Linux kernel # For a stable, released kernel, released_kernel should be 1. For rawhide # and/or a kernel built from an rc or git snapshot, released_kernel should # be 0. -%global released_kernel 1 +%global released_kernel 2 # Save original buildid for later if it's defined %if 0%{?buildid:1} @@ -710,6 +710,7 @@ Patch2802: linux-2.6-silence-acpi-blacklist.patch # add-poll-requested-events.patch was added for 3.4 Patch2900: add-poll-requested-events.patch Patch2901: drivers-media-update.patch +Patch2902: dvbs-fix-zigzag.patch # fs fixes @@ -1421,6 +1422,7 @@ ApplyPatch quite-apm.patch # Media (V4L/DVB/IR) updates/fixes/experimental drivers # apply if non-empty ApplyPatch add-poll-requested-events.patch +ApplyPatch dvbs-fix-zigzag.patch ApplyOptionalPatch drivers-media-update.patch # Patches headed upstream @@ -2227,6 +2229,9 @@ fi # and build. %changelog +* Mon May 07 2012 Mauro Carvalho Chehab 3.3.5-2 +- Add patch to fix DVB-S zigzag (rhbz 814404) + * Mon May 07 2012 Josh Boyer 3.3.5-1 - Linux 3.3.5 - Add patch to rate limit NFSv4 message (rhbz 732748) From 79b001249abe07d18a410acb3d6cd67aca44e9f3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 May 2012 07:47:41 -0300 Subject: [PATCH 376/487] Update the release tag Previous patch updated the wrong field. Signed-off-by: Mauro Carvalho Chehab --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index b8c6ddbcf..82288ccb6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -6,7 +6,7 @@ Summary: The Linux kernel # For a stable, released kernel, released_kernel should be 1. For rawhide # and/or a kernel built from an rc or git snapshot, released_kernel should # be 0. -%global released_kernel 2 +%global released_kernel 1 # Save original buildid for later if it's defined %if 0%{?buildid:1} @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching From eefa8b0319f5463ba31788e2fc6890ee8137b16d Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 14 May 2012 13:33:04 -0500 Subject: [PATCH 377/487] Linux 3.3.6 --- ...cpus-are-consistent-with-in-kernel-i.patch | 106 ------------------ config-generic | 2 + config-x86-generic | 2 +- kernel.spec | 19 +--- ...Enable-keyboard-backlight-by-default.patch | 44 -------- sources | 2 +- 6 files changed, 9 insertions(+), 166 deletions(-) delete mode 100644 KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch delete mode 100644 sony-laptop-Enable-keyboard-backlight-by-default.patch diff --git a/KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch b/KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch deleted file mode 100644 index 7e1664f41..000000000 --- a/KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 5b40572ed5f0344b9dbee486a17c589ce1abe1a3 Mon Sep 17 00:00:00 2001 -From: Avi Kivity -Date: Mon, 5 Mar 2012 14:23:29 +0200 -Subject: [PATCH] KVM: Ensure all vcpus are consistent with in-kernel irqchip - settings - -If some vcpus are created before KVM_CREATE_IRQCHIP, then -irqchip_in_kernel() and vcpu->arch.apic will be inconsistent, leading -to potential NULL pointer dereferences. - -Fix by: -- ensuring that no vcpus are installed when KVM_CREATE_IRQCHIP is called -- ensuring that a vcpu has an apic if it is installed after KVM_CREATE_IRQCHIP - -This is somewhat long winded because vcpu->arch.apic is created without -kvm->lock held. - -Based on earlier patch by Michael Ellerman. - -Signed-off-by: Michael Ellerman -Signed-off-by: Avi Kivity ---- - arch/ia64/kvm/kvm-ia64.c | 5 +++++ - arch/x86/kvm/x86.c | 8 ++++++++ - include/linux/kvm_host.h | 7 +++++++ - virt/kvm/kvm_main.c | 4 ++++ - 4 files changed, 24 insertions(+), 0 deletions(-) - -diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c -index d8ddbba..f5104b7 100644 ---- a/arch/ia64/kvm/kvm-ia64.c -+++ b/arch/ia64/kvm/kvm-ia64.c -@@ -1172,6 +1172,11 @@ out: - - #define PALE_RESET_ENTRY 0x80000000ffffffb0UL - -+bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) -+{ -+ return irqchip_in_kernel(vcpu->kcm) == (vcpu->arch.apic != NULL); -+} -+ - int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) - { - struct kvm_vcpu *v; -diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c -index 3ee008f..be9594a 100644 ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -3199,6 +3199,9 @@ long kvm_arch_vm_ioctl(struct file *filp, - r = -EEXIST; - if (kvm->arch.vpic) - goto create_irqchip_unlock; -+ r = -EINVAL; -+ if (atomic_read(&kvm->online_vcpus)) -+ goto create_irqchip_unlock; - r = -ENOMEM; - vpic = kvm_create_pic(kvm); - if (vpic) { -@@ -6107,6 +6110,11 @@ void kvm_arch_check_processor_compat(void *rtn) - kvm_x86_ops->check_processor_compatibility(rtn); - } - -+bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) -+{ -+ return irqchip_in_kernel(vcpu->kvm) == (vcpu->arch.apic != NULL); -+} -+ - int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) - { - struct page *page; -diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h -index 355e445..759fa26 100644 ---- a/include/linux/kvm_host.h -+++ b/include/linux/kvm_host.h -@@ -805,6 +805,13 @@ static inline bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu) - { - return vcpu->kvm->bsp_vcpu_id == vcpu->vcpu_id; - } -+ -+bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu); -+ -+#else -+ -+static bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) { return true; } -+ - #endif - - #ifdef __KVM_HAVE_DEVICE_ASSIGNMENT -diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c -index e4431ad..94e148e 100644 ---- a/virt/kvm/kvm_main.c -+++ b/virt/kvm/kvm_main.c -@@ -1651,6 +1651,10 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id) - goto vcpu_destroy; - - mutex_lock(&kvm->lock); -+ if (!kvm_vcpu_compatible(vcpu)) { -+ r = -EINVAL; -+ goto unlock_vcpu_destroy; -+ } - if (atomic_read(&kvm->online_vcpus) == KVM_MAX_VCPUS) { - r = -EINVAL; - goto unlock_vcpu_destroy; --- -1.7.7.6 - diff --git a/config-generic b/config-generic index e991fc0b1..543dc6257 100644 --- a/config-generic +++ b/config-generic @@ -353,6 +353,8 @@ CONFIG_BLK_DEV_FD=m # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set + CONFIG_BLK_CPQ_DA=m CONFIG_BLK_CPQ_CISS_DA=m CONFIG_CISS_SCSI_TAPE=y diff --git a/config-x86-generic b/config-x86-generic index 8654c4613..cf5e3c611 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -391,7 +391,7 @@ CONFIG_RELOCATABLE=y # CONFIG_HYPERV is not set -# Depends on HOTPLUG_PCI_PCIE +# Depends on PCI CONFIG_BLK_DEV_PCIESSD_MTIP32XX=m CONFIG_DRM_GMA500=m diff --git a/kernel.spec b/kernel.spec index 82288ccb6..3ab2bb299 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 5 +%define stable_update 6 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -763,9 +763,6 @@ Patch21232: rt2x00_fix_MCU_request_failures.patch #rhbz 789644 Patch21237: mcelog-rcu-splat.patch -#rhbz 728478 -Patch21242: sony-laptop-Enable-keyboard-backlight-by-default.patch - Patch21300: unhandled-irqs-switch-to-polling.patch #rhbz 804957 CVE-2012-1568 @@ -779,9 +776,6 @@ Patch21353: xen-x86-Implement-x86_apic_ops.patch #rhbz 807632 Patch21385: libata-forbid-port-runtime-pm-by-default.patch -#rhbz 808207 CVE-2012-1601 -Patch21520: KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch - #rhbz 808559 Patch21530: ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch @@ -1456,9 +1450,6 @@ ApplyPatch rt2x00_fix_MCU_request_failures.patch #rhbz 789644 ApplyPatch mcelog-rcu-splat.patch -#rhbz 728478 -ApplyPatch sony-laptop-Enable-keyboard-backlight-by-default.patch - #rhbz 804957 CVE-2012-1568 ApplyPatch shlib_base_randomize.patch @@ -1473,9 +1464,6 @@ ApplyPatch x86-add-io_apic_ops-to-allow-interception.patch ApplyPatch x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch ApplyPatch xen-x86-Implement-x86_apic_ops.patch -#rhbz 808207 CVE-2012-1601 -ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch - #rhbz 807632 ApplyPatch libata-forbid-port-runtime-pm-by-default.patch @@ -2229,6 +2217,9 @@ fi # and build. %changelog +* Mon May 14 2012 Justin M. Forbes 3.3.6-1 +- Linux 3.3.6 + * Mon May 07 2012 Mauro Carvalho Chehab 3.3.5-2 - Add patch to fix DVB-S zigzag (rhbz 814404) diff --git a/sony-laptop-Enable-keyboard-backlight-by-default.patch b/sony-laptop-Enable-keyboard-backlight-by-default.patch deleted file mode 100644 index c993fd86d..000000000 --- a/sony-laptop-Enable-keyboard-backlight-by-default.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0dbc2bc96b1ec741bdd43451c286ccd45da3310b Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Wed, 2 Nov 2011 14:31:59 -0400 -Subject: [PATCH] sony-laptop: Enable keyboard backlight by default - -When the keyboard backlight support was originally added, the commit said -to default it to on with a 10 second timeout. That actually wasn't the -case, as the default value is commented out for the kbd_backlight parameter. -Because it is a static variable, it gets set to 0 by default without some -other form of initialization. - -However, it seems the function to set the value wasn't actually called -immediately, so whatever state the keyboard was in initially would remain. -Then commit df410d522410e67660 was introduced during the 2.6.39 timeframe to -immediately set whatever value was present (as well as attempt to -restore/reset the state on module removal or resume). That seems to have -now forced the light off immediately when the module is loaded unless -the option kbd_backlight=1 is specified. - -Let's enable it by default again (for the first time). This should solve -https://bugzilla.redhat.com/show_bug.cgi?id=728478 - -Acked-by: Mattia Dongili -Signed-off-by: Josh Boyer ---- - drivers/platform/x86/sony-laptop.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c -index c006dee..40c4705 100644 ---- a/drivers/platform/x86/sony-laptop.c -+++ b/drivers/platform/x86/sony-laptop.c -@@ -127,7 +127,7 @@ MODULE_PARM_DESC(minor, - "default is -1 (automatic)"); - #endif - --static int kbd_backlight; /* = 1 */ -+static int kbd_backlight = 1; - module_param(kbd_backlight, int, 0444); - MODULE_PARM_DESC(kbd_backlight, - "set this to 0 to disable keyboard backlight, " --- -1.7.7.6 - diff --git a/sources b/sources index ae9616785..755d90dc6 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz -d346edca5d3de7052f49996b01cef401 patch-3.3.5.xz +a7f67e9c491403906e4bb475de194631 patch-3.3.6.xz From 2db8c9ffc3529fae0c51c69ce681d7ef322c7c0b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 15 May 2012 07:57:12 -0400 Subject: [PATCH 378/487] Fixup atl1c register programming (rhbz 749276) --- atl1c_net_next_update-3.3.patch | 3633 +++++++++++++++++++++++++++++++ kernel.spec | 11 +- 2 files changed, 3643 insertions(+), 1 deletion(-) create mode 100644 atl1c_net_next_update-3.3.patch diff --git a/atl1c_net_next_update-3.3.patch b/atl1c_net_next_update-3.3.patch new file mode 100644 index 000000000..6c53ed607 --- /dev/null +++ b/atl1c_net_next_update-3.3.patch @@ -0,0 +1,3633 @@ +diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c.h b/drivers/net/ethernet/atheros/atl1c/atl1c.h +index ca70e16..b2bf324 100644 +--- a/drivers/net/ethernet/atheros/atl1c/atl1c.h ++++ b/drivers/net/ethernet/atheros/atl1c/atl1c.h +@@ -74,8 +74,6 @@ + + #define AT_RX_BUF_SIZE (ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN) + #define MAX_JUMBO_FRAME_SIZE (6*1024) +-#define MAX_TSO_FRAME_SIZE (7*1024) +-#define MAX_TX_OFFLOAD_THRESH (9*1024) + + #define AT_MAX_RECEIVE_QUEUE 4 + #define AT_DEF_RECEIVE_QUEUE 1 +@@ -100,7 +98,7 @@ + #define ATL1C_ASPM_L0s_ENABLE 0x0001 + #define ATL1C_ASPM_L1_ENABLE 0x0002 + +-#define AT_REGS_LEN (75 * sizeof(u32)) ++#define AT_REGS_LEN (74 * sizeof(u32)) + #define AT_EEPROM_LEN 512 + + #define ATL1C_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i])) +@@ -297,20 +295,6 @@ enum atl1c_dma_req_block { + atl1c_dma_req_4096 = 5 + }; + +-enum atl1c_rss_mode { +- atl1c_rss_mode_disable = 0, +- atl1c_rss_sig_que = 1, +- atl1c_rss_mul_que_sig_int = 2, +- atl1c_rss_mul_que_mul_int = 4, +-}; +- +-enum atl1c_rss_type { +- atl1c_rss_disable = 0, +- atl1c_rss_ipv4 = 1, +- atl1c_rss_ipv4_tcp = 2, +- atl1c_rss_ipv6 = 4, +- atl1c_rss_ipv6_tcp = 8 +-}; + + enum atl1c_nic_type { + athr_l1c = 0, +@@ -388,7 +372,6 @@ struct atl1c_hw { + enum atl1c_dma_order dma_order; + enum atl1c_dma_rcb rcb_value; + enum atl1c_dma_req_block dmar_block; +- enum atl1c_dma_req_block dmaw_block; + + u16 device_id; + u16 vendor_id; +@@ -399,8 +382,6 @@ struct atl1c_hw { + u16 phy_id2; + + u32 intr_mask; +- u8 dmaw_dly_cnt; +- u8 dmar_dly_cnt; + + u8 preamble_len; + u16 max_frame_size; +@@ -440,10 +421,6 @@ struct atl1c_hw { + #define ATL1C_FPGA_VERSION 0x8000 + u16 link_cap_flags; + #define ATL1C_LINK_CAP_1000M 0x0001 +- u16 cmb_tpd; +- u16 cmb_rrd; +- u16 cmb_rx_timer; /* 2us resolution */ +- u16 cmb_tx_timer; + u32 smb_timer; + + u16 rrd_thresh; /* Threshold of number of RRD produced to trigger +@@ -451,9 +428,6 @@ struct atl1c_hw { + u16 tpd_thresh; + u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. */ + u8 rfd_burst; +- enum atl1c_rss_type rss_type; +- enum atl1c_rss_mode rss_mode; +- u8 rss_hash_bits; + u32 base_cpu; + u32 indirect_tab; + u8 mac_addr[ETH_ALEN]; +@@ -462,12 +436,12 @@ struct atl1c_hw { + bool phy_configured; + bool re_autoneg; + bool emi_ca; ++ bool msi_lnkpatch; /* link patch for specific platforms */ + }; + + /* + * atl1c_ring_header represents a single, contiguous block of DMA space +- * mapped for the three descriptor rings (tpd, rfd, rrd) and the two +- * message blocks (cmb, smb) described below ++ * mapped for the three descriptor rings (tpd, rfd, rrd) described below + */ + struct atl1c_ring_header { + void *desc; /* virtual address */ +@@ -541,16 +515,6 @@ struct atl1c_rrd_ring { + u16 next_to_clean; + }; + +-struct atl1c_cmb { +- void *cmb; +- dma_addr_t dma; +-}; +- +-struct atl1c_smb { +- void *smb; +- dma_addr_t dma; +-}; +- + /* board specific private data structure */ + struct atl1c_adapter { + struct net_device *netdev; +@@ -586,11 +550,8 @@ struct atl1c_adapter { + /* All Descriptor memory */ + struct atl1c_ring_header ring_header; + struct atl1c_tpd_ring tpd_ring[AT_MAX_TRANSMIT_QUEUE]; +- struct atl1c_rfd_ring rfd_ring[AT_MAX_RECEIVE_QUEUE]; +- struct atl1c_rrd_ring rrd_ring[AT_MAX_RECEIVE_QUEUE]; +- struct atl1c_cmb cmb; +- struct atl1c_smb smb; +- int num_rx_queues; ++ struct atl1c_rfd_ring rfd_ring; ++ struct atl1c_rrd_ring rrd_ring; + u32 bd_number; /* board number;*/ + }; + +@@ -618,8 +579,14 @@ struct atl1c_adapter { + #define AT_WRITE_REGW(a, reg, value) (\ + writew((value), ((a)->hw_addr + reg))) + +-#define AT_READ_REGW(a, reg) (\ +- readw((a)->hw_addr + reg)) ++#define AT_READ_REGW(a, reg, pdata) do { \ ++ if (unlikely((a)->hibernate)) { \ ++ readw((a)->hw_addr + reg); \ ++ *(u16 *)pdata = readw((a)->hw_addr + reg); \ ++ } else { \ ++ *(u16 *)pdata = readw((a)->hw_addr + reg); \ ++ } \ ++ } while (0) + + #define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \ + writel((value), (((a)->hw_addr + reg) + ((offset) << 2)))) +diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c +index 0a9326a..859ea84 100644 +--- a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c ++++ b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c +@@ -141,8 +141,7 @@ static void atl1c_get_regs(struct net_device *netdev, + + memset(p, 0, AT_REGS_LEN); + +- regs->version = 0; +- AT_READ_REG(hw, REG_VPD_CAP, p++); ++ regs->version = 1; + AT_READ_REG(hw, REG_PM_CTRL, p++); + AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL, p++); + AT_READ_REG(hw, REG_TWSI_CTRL, p++); +@@ -154,7 +153,7 @@ static void atl1c_get_regs(struct net_device *netdev, + AT_READ_REG(hw, REG_LINK_CTRL, p++); + AT_READ_REG(hw, REG_IDLE_STATUS, p++); + AT_READ_REG(hw, REG_MDIO_CTRL, p++); +- AT_READ_REG(hw, REG_SERDES_LOCK, p++); ++ AT_READ_REG(hw, REG_SERDES, p++); + AT_READ_REG(hw, REG_MAC_CTRL, p++); + AT_READ_REG(hw, REG_MAC_IPG_IFG, p++); + AT_READ_REG(hw, REG_MAC_STA_ADDR, p++); +@@ -167,9 +166,9 @@ static void atl1c_get_regs(struct net_device *netdev, + AT_READ_REG(hw, REG_WOL_CTRL, p++); + + atl1c_read_phy_reg(hw, MII_BMCR, &phy_data); +- regs_buff[73] = (u32) phy_data; ++ regs_buff[AT_REGS_LEN/sizeof(u32) - 2] = (u32) phy_data; + atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); +- regs_buff[74] = (u32) phy_data; ++ regs_buff[AT_REGS_LEN/sizeof(u32) - 1] = (u32) phy_data; + } + + static int atl1c_get_eeprom_len(struct net_device *netdev) +diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c +index 23f2ab0..2ea6a21 100644 +--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c ++++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c +@@ -43,7 +43,7 @@ int atl1c_check_eeprom_exist(struct atl1c_hw *hw) + return 0; + } + +-void atl1c_hw_set_mac_addr(struct atl1c_hw *hw) ++void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr) + { + u32 value; + /* +@@ -51,35 +51,48 @@ void atl1c_hw_set_mac_addr(struct atl1c_hw *hw) + * 0: 6AF600DC 1: 000B + * low dword + */ +- value = (((u32)hw->mac_addr[2]) << 24) | +- (((u32)hw->mac_addr[3]) << 16) | +- (((u32)hw->mac_addr[4]) << 8) | +- (((u32)hw->mac_addr[5])) ; ++ value = mac_addr[2] << 24 | ++ mac_addr[3] << 16 | ++ mac_addr[4] << 8 | ++ mac_addr[5]; + AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value); + /* hight dword */ +- value = (((u32)hw->mac_addr[0]) << 8) | +- (((u32)hw->mac_addr[1])) ; ++ value = mac_addr[0] << 8 | ++ mac_addr[1]; + AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value); + } + ++/* read mac address from hardware register */ ++static bool atl1c_read_current_addr(struct atl1c_hw *hw, u8 *eth_addr) ++{ ++ u32 addr[2]; ++ ++ AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]); ++ AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]); ++ ++ *(u32 *) ð_addr[2] = htonl(addr[0]); ++ *(u16 *) ð_addr[0] = htons((u16)addr[1]); ++ ++ return is_valid_ether_addr(eth_addr); ++} ++ + /* + * atl1c_get_permanent_address + * return 0 if get valid mac address, + */ + static int atl1c_get_permanent_address(struct atl1c_hw *hw) + { +- u32 addr[2]; + u32 i; + u32 otp_ctrl_data; + u32 twsi_ctrl_data; +- u32 ltssm_ctrl_data; +- u32 wol_data; +- u8 eth_addr[ETH_ALEN]; + u16 phy_data; + bool raise_vol = false; + ++ /* MAC-address from BIOS is the 1st priority */ ++ if (atl1c_read_current_addr(hw, hw->perm_mac_addr)) ++ return 0; ++ + /* init */ +- addr[0] = addr[1] = 0; + AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data); + if (atl1c_check_eeprom_exist(hw)) { + if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) { +@@ -91,33 +104,17 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw) + msleep(1); + } + } +- +- if (hw->nic_type == athr_l2c_b || +- hw->nic_type == athr_l2c_b2 || +- hw->nic_type == athr_l1d) { +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00); +- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) +- goto out; +- phy_data &= 0xFF7F; +- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); +- +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B); +- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) +- goto out; +- phy_data |= 0x8; +- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); ++ /* raise voltage temporally for l2cb */ ++ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { ++ atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data); ++ phy_data &= ~ANACTRL_HB_EN; ++ atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data); ++ atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); ++ phy_data |= VOLT_CTRL_SWLOWEST; ++ atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); + udelay(20); + raise_vol = true; + } +- /* close open bit of ReadOnly*/ +- AT_READ_REG(hw, REG_LTSSM_ID_CTRL, <ssm_ctrl_data); +- ltssm_ctrl_data &= ~LTSSM_ID_EN_WRO; +- AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, ltssm_ctrl_data); +- +- /* clear any WOL settings */ +- AT_WRITE_REG(hw, REG_WOL_CTRL, 0); +- AT_READ_REG(hw, REG_WOL_CTRL, &wol_data); +- + + AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data); + twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART; +@@ -138,37 +135,18 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw) + msleep(1); + } + if (raise_vol) { +- if (hw->nic_type == athr_l2c_b || +- hw->nic_type == athr_l2c_b2 || +- hw->nic_type == athr_l1d || +- hw->nic_type == athr_l1d_2) { +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00); +- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) +- goto out; +- phy_data |= 0x80; +- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); +- +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B); +- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) +- goto out; +- phy_data &= 0xFFF7; +- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); +- udelay(20); +- } ++ atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data); ++ phy_data |= ANACTRL_HB_EN; ++ atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data); ++ atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); ++ phy_data &= ~VOLT_CTRL_SWLOWEST; ++ atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); ++ udelay(20); + } + +- /* maybe MAC-address is from BIOS */ +- AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]); +- AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]); +- *(u32 *) ð_addr[2] = swab32(addr[0]); +- *(u16 *) ð_addr[0] = swab16(*(u16 *)&addr[1]); +- +- if (is_valid_ether_addr(eth_addr)) { +- memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN); ++ if (atl1c_read_current_addr(hw, hw->perm_mac_addr)) + return 0; +- } + +-out: + return -1; + } + +@@ -278,33 +256,158 @@ void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value) + } + + /* +- * Reads the value from a PHY register +- * hw - Struct containing variables accessed by shared code +- * reg_addr - address of the PHY register to read ++ * wait mdio module be idle ++ * return true: idle ++ * false: still busy + */ +-int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) ++bool atl1c_wait_mdio_idle(struct atl1c_hw *hw) + { + u32 val; + int i; + +- val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT | +- MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | +- MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; ++ for (i = 0; i < MDIO_MAX_AC_TO; i++) { ++ AT_READ_REG(hw, REG_MDIO_CTRL, &val); ++ if (!(val & (MDIO_CTRL_BUSY | MDIO_CTRL_START))) ++ break; ++ udelay(10); ++ } ++ ++ return i != MDIO_MAX_AC_TO; ++} ++ ++void atl1c_stop_phy_polling(struct atl1c_hw *hw) ++{ ++ if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION)) ++ return; ++ ++ AT_WRITE_REG(hw, REG_MDIO_CTRL, 0); ++ atl1c_wait_mdio_idle(hw); ++} + ++void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel) ++{ ++ u32 val; ++ ++ if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION)) ++ return; ++ ++ val = MDIO_CTRL_SPRES_PRMBL | ++ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | ++ FIELDX(MDIO_CTRL_REG, 1) | ++ MDIO_CTRL_START | ++ MDIO_CTRL_OP_READ; ++ AT_WRITE_REG(hw, REG_MDIO_CTRL, val); ++ atl1c_wait_mdio_idle(hw); ++ val |= MDIO_CTRL_AP_EN; ++ val &= ~MDIO_CTRL_START; + AT_WRITE_REG(hw, REG_MDIO_CTRL, val); ++ udelay(30); ++} + +- for (i = 0; i < MDIO_WAIT_TIMES; i++) { +- udelay(2); +- AT_READ_REG(hw, REG_MDIO_CTRL, &val); +- if (!(val & (MDIO_START | MDIO_BUSY))) +- break; ++ ++/* ++ * atl1c_read_phy_core ++ * core funtion to read register in PHY via MDIO control regsiter. ++ * ext: extension register (see IEEE 802.3) ++ * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0) ++ * reg: reg to read ++ */ ++int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, ++ u16 reg, u16 *phy_data) ++{ ++ u32 val; ++ u16 clk_sel = MDIO_CTRL_CLK_25_4; ++ ++ atl1c_stop_phy_polling(hw); ++ ++ *phy_data = 0; ++ ++ /* only l2c_b2 & l1d_2 could use slow clock */ ++ if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) && ++ hw->hibernate) ++ clk_sel = MDIO_CTRL_CLK_25_128; ++ if (ext) { ++ val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg); ++ AT_WRITE_REG(hw, REG_MDIO_EXTN, val); ++ val = MDIO_CTRL_SPRES_PRMBL | ++ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | ++ MDIO_CTRL_START | ++ MDIO_CTRL_MODE_EXT | ++ MDIO_CTRL_OP_READ; ++ } else { ++ val = MDIO_CTRL_SPRES_PRMBL | ++ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | ++ FIELDX(MDIO_CTRL_REG, reg) | ++ MDIO_CTRL_START | ++ MDIO_CTRL_OP_READ; + } +- if (!(val & (MDIO_START | MDIO_BUSY))) { +- *phy_data = (u16)val; +- return 0; ++ AT_WRITE_REG(hw, REG_MDIO_CTRL, val); ++ ++ if (!atl1c_wait_mdio_idle(hw)) ++ return -1; ++ ++ AT_READ_REG(hw, REG_MDIO_CTRL, &val); ++ *phy_data = (u16)FIELD_GETX(val, MDIO_CTRL_DATA); ++ ++ atl1c_start_phy_polling(hw, clk_sel); ++ ++ return 0; ++} ++ ++/* ++ * atl1c_write_phy_core ++ * core funtion to write to register in PHY via MDIO control regsiter. ++ * ext: extension register (see IEEE 802.3) ++ * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0) ++ * reg: reg to write ++ */ ++int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, ++ u16 reg, u16 phy_data) ++{ ++ u32 val; ++ u16 clk_sel = MDIO_CTRL_CLK_25_4; ++ ++ atl1c_stop_phy_polling(hw); ++ ++ ++ /* only l2c_b2 & l1d_2 could use slow clock */ ++ if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) && ++ hw->hibernate) ++ clk_sel = MDIO_CTRL_CLK_25_128; ++ ++ if (ext) { ++ val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg); ++ AT_WRITE_REG(hw, REG_MDIO_EXTN, val); ++ val = MDIO_CTRL_SPRES_PRMBL | ++ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | ++ FIELDX(MDIO_CTRL_DATA, phy_data) | ++ MDIO_CTRL_START | ++ MDIO_CTRL_MODE_EXT; ++ } else { ++ val = MDIO_CTRL_SPRES_PRMBL | ++ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | ++ FIELDX(MDIO_CTRL_DATA, phy_data) | ++ FIELDX(MDIO_CTRL_REG, reg) | ++ MDIO_CTRL_START; + } ++ AT_WRITE_REG(hw, REG_MDIO_CTRL, val); + +- return -1; ++ if (!atl1c_wait_mdio_idle(hw)) ++ return -1; ++ ++ atl1c_start_phy_polling(hw, clk_sel); ++ ++ return 0; ++} ++ ++/* ++ * Reads the value from a PHY register ++ * hw - Struct containing variables accessed by shared code ++ * reg_addr - address of the PHY register to read ++ */ ++int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) ++{ ++ return atl1c_read_phy_core(hw, false, 0, reg_addr, phy_data); + } + + /* +@@ -315,27 +418,47 @@ int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) + */ + int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data) + { +- int i; +- u32 val; ++ return atl1c_write_phy_core(hw, false, 0, reg_addr, phy_data); ++} + +- val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT | +- (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT | +- MDIO_SUP_PREAMBLE | MDIO_START | +- MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; ++/* read from PHY extension register */ ++int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr, ++ u16 reg_addr, u16 *phy_data) ++{ ++ return atl1c_read_phy_core(hw, true, dev_addr, reg_addr, phy_data); ++} + +- AT_WRITE_REG(hw, REG_MDIO_CTRL, val); ++/* write to PHY extension register */ ++int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr, ++ u16 reg_addr, u16 phy_data) ++{ ++ return atl1c_write_phy_core(hw, true, dev_addr, reg_addr, phy_data); ++} + +- for (i = 0; i < MDIO_WAIT_TIMES; i++) { +- udelay(2); +- AT_READ_REG(hw, REG_MDIO_CTRL, &val); +- if (!(val & (MDIO_START | MDIO_BUSY))) +- break; +- } ++int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) ++{ ++ int err; + +- if (!(val & (MDIO_START | MDIO_BUSY))) +- return 0; ++ err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr); ++ if (unlikely(err)) ++ return err; ++ else ++ err = atl1c_read_phy_reg(hw, MII_DBG_DATA, phy_data); + +- return -1; ++ return err; ++} ++ ++int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data) ++{ ++ int err; ++ ++ err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr); ++ if (unlikely(err)) ++ return err; ++ else ++ err = atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); ++ ++ return err; + } + + /* +@@ -380,119 +503,100 @@ static int atl1c_phy_setup_adv(struct atl1c_hw *hw) + + void atl1c_phy_disable(struct atl1c_hw *hw) + { +- AT_WRITE_REGW(hw, REG_GPHY_CTRL, +- GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET); ++ atl1c_power_saving(hw, 0); + } + +-static void atl1c_phy_magic_data(struct atl1c_hw *hw) +-{ +- u16 data; +- +- data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE | +- ((1 & ANA_INTERVAL_SEL_TIMER_MASK) << +- ANA_INTERVAL_SEL_TIMER_SHIFT); +- +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_18); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); +- +- data = (2 & ANA_SERDES_CDR_BW_MASK) | ANA_MS_PAD_DBG | +- ANA_SERDES_EN_DEEM | ANA_SERDES_SEL_HSP | ANA_SERDES_EN_PLL | +- ANA_SERDES_EN_LCKDT; +- +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_5); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); +- +- data = (44 & ANA_LONG_CABLE_TH_100_MASK) | +- ((33 & ANA_SHORT_CABLE_TH_100_MASK) << +- ANA_SHORT_CABLE_TH_100_SHIFT) | ANA_BP_BAD_LINK_ACCUM | +- ANA_BP_SMALL_BW; +- +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_54); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); +- +- data = (11 & ANA_IECHO_ADJ_MASK) | ((11 & ANA_IECHO_ADJ_MASK) << +- ANA_IECHO_ADJ_2_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) << +- ANA_IECHO_ADJ_1_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) << +- ANA_IECHO_ADJ_0_SHIFT); +- +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_4); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); +- +- data = ANA_RESTART_CAL | ((7 & ANA_MANUL_SWICH_ON_MASK) << +- ANA_MANUL_SWICH_ON_SHIFT) | ANA_MAN_ENABLE | +- ANA_SEL_HSP | ANA_EN_HB | ANA_OEN_125M; +- +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_0); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); +- +- if (hw->ctrl_flags & ATL1C_HIB_DISABLE) { +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_41); +- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0) +- return; +- data &= ~ANA_TOP_PS_EN; +- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); +- +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_11); +- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0) +- return; +- data &= ~ANA_PS_HIB_EN; +- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); +- } +-} + + int atl1c_phy_reset(struct atl1c_hw *hw) + { + struct atl1c_adapter *adapter = hw->adapter; + struct pci_dev *pdev = adapter->pdev; + u16 phy_data; +- u32 phy_ctrl_data = GPHY_CTRL_DEFAULT; +- u32 mii_ier_data = IER_LINK_UP | IER_LINK_DOWN; ++ u32 phy_ctrl_data, lpi_ctrl; + int err; + +- if (hw->ctrl_flags & ATL1C_HIB_DISABLE) +- phy_ctrl_data &= ~GPHY_CTRL_HIB_EN; +- ++ /* reset PHY core */ ++ AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl_data); ++ phy_ctrl_data &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_PHY_IDDQ | ++ GPHY_CTRL_GATE_25M_EN | GPHY_CTRL_PWDOWN_HW | GPHY_CTRL_CLS); ++ phy_ctrl_data |= GPHY_CTRL_SEL_ANA_RST; ++ if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE)) ++ phy_ctrl_data |= (GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE); ++ else ++ phy_ctrl_data &= ~(GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE); + AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data); + AT_WRITE_FLUSH(hw); +- msleep(40); +- phy_ctrl_data |= GPHY_CTRL_EXT_RESET; +- AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data); ++ udelay(10); ++ AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data | GPHY_CTRL_EXT_RESET); + AT_WRITE_FLUSH(hw); +- msleep(10); ++ udelay(10 * GPHY_CTRL_EXT_RST_TO); /* delay 800us */ + ++ /* switch clock */ + if (hw->nic_type == athr_l2c_b) { +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x0A); +- atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xDFFF); ++ atl1c_read_phy_dbg(hw, MIIDBG_CFGLPSPD, &phy_data); ++ atl1c_write_phy_dbg(hw, MIIDBG_CFGLPSPD, ++ phy_data & ~CFGLPSPD_RSTCNT_CLK125SW); + } + +- if (hw->nic_type == athr_l2c_b || +- hw->nic_type == athr_l2c_b2 || +- hw->nic_type == athr_l1d || +- hw->nic_type == athr_l1d_2) { +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B); +- atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xFFF7); +- msleep(20); ++ /* tx-half amplitude issue fix */ ++ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { ++ atl1c_read_phy_dbg(hw, MIIDBG_CABLE1TH_DET, &phy_data); ++ phy_data |= CABLE1TH_DET_EN; ++ atl1c_write_phy_dbg(hw, MIIDBG_CABLE1TH_DET, phy_data); + } +- if (hw->nic_type == athr_l1d) { +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x929D); ++ ++ /* clear bit3 of dbgport 3B to lower voltage */ ++ if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE)) { ++ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { ++ atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); ++ phy_data &= ~VOLT_CTRL_SWLOWEST; ++ atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); ++ } ++ /* power saving config */ ++ phy_data = ++ hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 ? ++ L1D_LEGCYPS_DEF : L1C_LEGCYPS_DEF; ++ atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS, phy_data); ++ /* hib */ ++ atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, ++ SYSMODCTRL_IECHOADJ_DEF); ++ } else { ++ /* disable pws */ ++ atl1c_read_phy_dbg(hw, MIIDBG_LEGCYPS, &phy_data); ++ atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS, ++ phy_data & ~LEGCYPS_EN); ++ /* disable hibernate */ ++ atl1c_read_phy_dbg(hw, MIIDBG_HIBNEG, &phy_data); ++ atl1c_write_phy_dbg(hw, MIIDBG_HIBNEG, ++ phy_data & HIBNEG_PSHIB_EN); + } +- if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c_b2 +- || hw->nic_type == athr_l2c) { +- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29); +- atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD); ++ /* disable AZ(EEE) by default */ ++ if (hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 || ++ hw->nic_type == athr_l2c_b2) { ++ AT_READ_REG(hw, REG_LPI_CTRL, &lpi_ctrl); ++ AT_WRITE_REG(hw, REG_LPI_CTRL, lpi_ctrl & ~LPI_CTRL_EN); ++ atl1c_write_phy_ext(hw, MIIEXT_ANEG, MIIEXT_LOCAL_EEEADV, 0); ++ atl1c_write_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL3, ++ L2CB_CLDCTRL3); + } +- err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data); ++ ++ /* other debug port to set */ ++ atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, ANACTRL_DEF); ++ atl1c_write_phy_dbg(hw, MIIDBG_SRDSYSMOD, SRDSYSMOD_DEF); ++ atl1c_write_phy_dbg(hw, MIIDBG_TST10BTCFG, TST10BTCFG_DEF); ++ /* UNH-IOL test issue, set bit7 */ ++ atl1c_write_phy_dbg(hw, MIIDBG_TST100BTCFG, ++ TST100BTCFG_DEF | TST100BTCFG_LITCH_EN); ++ ++ /* set phy interrupt mask */ ++ phy_data = IER_LINK_UP | IER_LINK_DOWN; ++ err = atl1c_write_phy_reg(hw, MII_IER, phy_data); + if (err) { + if (netif_msg_hw(adapter)) + dev_err(&pdev->dev, + "Error enable PHY linkChange Interrupt\n"); + return err; + } +- if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION)) +- atl1c_phy_magic_data(hw); + return 0; + } + +@@ -589,7 +693,8 @@ int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex) + return 0; + } + +-int atl1c_phy_power_saving(struct atl1c_hw *hw) ++/* select one link mode to get lower power consumption */ ++int atl1c_phy_to_ps_link(struct atl1c_hw *hw) + { + struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter; + struct pci_dev *pdev = adapter->pdev; +@@ -660,3 +765,101 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw) + + return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data); + } ++ ++int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc) ++{ ++ struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter; ++ struct pci_dev *pdev = adapter->pdev; ++ u32 master_ctrl, mac_ctrl, phy_ctrl; ++ u32 wol_ctrl, speed; ++ u16 phy_data; ++ ++ wol_ctrl = 0; ++ speed = adapter->link_speed == SPEED_1000 ? ++ MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100; ++ ++ AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl); ++ AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl); ++ AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl); ++ ++ master_ctrl &= ~MASTER_CTRL_CLK_SEL_DIS; ++ mac_ctrl = FIELD_SETX(mac_ctrl, MAC_CTRL_SPEED, speed); ++ mac_ctrl &= ~(MAC_CTRL_DUPLX | MAC_CTRL_RX_EN | MAC_CTRL_TX_EN); ++ if (adapter->link_duplex == FULL_DUPLEX) ++ mac_ctrl |= MAC_CTRL_DUPLX; ++ phy_ctrl &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_CLS); ++ phy_ctrl |= GPHY_CTRL_SEL_ANA_RST | GPHY_CTRL_HIB_PULSE | ++ GPHY_CTRL_HIB_EN; ++ if (!wufc) { /* without WoL */ ++ master_ctrl |= MASTER_CTRL_CLK_SEL_DIS; ++ phy_ctrl |= GPHY_CTRL_PHY_IDDQ | GPHY_CTRL_PWDOWN_HW; ++ AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl); ++ AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl); ++ AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl); ++ AT_WRITE_REG(hw, REG_WOL_CTRL, 0); ++ hw->phy_configured = false; /* re-init PHY when resume */ ++ return 0; ++ } ++ phy_ctrl |= GPHY_CTRL_EXT_RESET; ++ if (wufc & AT_WUFC_MAG) { ++ mac_ctrl |= MAC_CTRL_RX_EN | MAC_CTRL_BC_EN; ++ wol_ctrl |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN; ++ if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V11) ++ wol_ctrl |= WOL_PATTERN_EN | WOL_PATTERN_PME_EN; ++ } ++ if (wufc & AT_WUFC_LNKC) { ++ wol_ctrl |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN; ++ if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) { ++ dev_dbg(&pdev->dev, "%s: write phy MII_IER faild.\n", ++ atl1c_driver_name); ++ } ++ } ++ /* clear PHY interrupt */ ++ atl1c_read_phy_reg(hw, MII_ISR, &phy_data); ++ ++ dev_dbg(&pdev->dev, "%s: suspend MAC=%x,MASTER=%x,PHY=0x%x,WOL=%x\n", ++ atl1c_driver_name, mac_ctrl, master_ctrl, phy_ctrl, wol_ctrl); ++ AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl); ++ AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl); ++ AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl); ++ AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl); ++ ++ return 0; ++} ++ ++ ++/* configure phy after Link change Event */ ++void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed) ++{ ++ u16 phy_val; ++ bool adj_thresh = false; ++ ++ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 || ++ hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2) ++ adj_thresh = true; ++ ++ if (link_speed != SPEED_0) { /* link up */ ++ /* az with brcm, half-amp */ ++ if (hw->nic_type == athr_l1d_2) { ++ atl1c_read_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL6, ++ &phy_val); ++ phy_val = FIELD_GETX(phy_val, CLDCTRL6_CAB_LEN); ++ phy_val = phy_val > CLDCTRL6_CAB_LEN_SHORT ? ++ AZ_ANADECT_LONG : AZ_ANADECT_DEF; ++ atl1c_write_phy_dbg(hw, MIIDBG_AZ_ANADECT, phy_val); ++ } ++ /* threshold adjust */ ++ if (adj_thresh && link_speed == SPEED_100 && hw->msi_lnkpatch) { ++ atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, L1D_MSE16DB_UP); ++ atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, ++ L1D_SYSMODCTRL_IECHOADJ_DEF); ++ } ++ } else { /* link down */ ++ if (adj_thresh && hw->msi_lnkpatch) { ++ atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, ++ SYSMODCTRL_IECHOADJ_DEF); ++ atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, ++ L1D_MSE16DB_DOWN); ++ } ++ } ++} +diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h +index 655fc6c..17d935b 100644 +--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h ++++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h +@@ -25,12 +25,18 @@ + #include + #include + ++#define FIELD_GETX(_x, _name) ((_x) >> (_name##_SHIFT) & (_name##_MASK)) ++#define FIELD_SETX(_x, _name, _v) \ ++(((_x) & ~((_name##_MASK) << (_name##_SHIFT))) |\ ++(((_v) & (_name##_MASK)) << (_name##_SHIFT))) ++#define FIELDX(_name, _v) (((_v) & (_name##_MASK)) << (_name##_SHIFT)) ++ + struct atl1c_adapter; + struct atl1c_hw; + + /* function prototype */ + void atl1c_phy_disable(struct atl1c_hw *hw); +-void atl1c_hw_set_mac_addr(struct atl1c_hw *hw); ++void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr); + int atl1c_phy_reset(struct atl1c_hw *hw); + int atl1c_read_mac_addr(struct atl1c_hw *hw); + int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex); +@@ -42,47 +48,45 @@ bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value); + int atl1c_phy_init(struct atl1c_hw *hw); + int atl1c_check_eeprom_exist(struct atl1c_hw *hw); + int atl1c_restart_autoneg(struct atl1c_hw *hw); +-int atl1c_phy_power_saving(struct atl1c_hw *hw); ++int atl1c_phy_to_ps_link(struct atl1c_hw *hw); ++int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc); ++bool atl1c_wait_mdio_idle(struct atl1c_hw *hw); ++void atl1c_stop_phy_polling(struct atl1c_hw *hw); ++void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel); ++int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, ++ u16 reg, u16 *phy_data); ++int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, ++ u16 reg, u16 phy_data); ++int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr, ++ u16 reg_addr, u16 *phy_data); ++int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr, ++ u16 reg_addr, u16 phy_data); ++int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data); ++int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data); ++void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed); ++ ++/* hw-ids */ ++#define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062 ++#define PCI_DEVICE_ID_ATTANSIC_L1C 0x1063 ++#define PCI_DEVICE_ID_ATHEROS_L2C_B 0x2060 /* AR8152 v1.1 Fast 10/100 */ ++#define PCI_DEVICE_ID_ATHEROS_L2C_B2 0x2062 /* AR8152 v2.0 Fast 10/100 */ ++#define PCI_DEVICE_ID_ATHEROS_L1D 0x1073 /* AR8151 v1.0 Gigabit 1000 */ ++#define PCI_DEVICE_ID_ATHEROS_L1D_2_0 0x1083 /* AR8151 v2.0 Gigabit 1000 */ ++#define L2CB_V10 0xc0 ++#define L2CB_V11 0xc1 ++ + /* register definition */ + #define REG_DEVICE_CAP 0x5C + #define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7 + #define DEVICE_CAP_MAX_PAYLOAD_SHIFT 0 + +-#define REG_DEVICE_CTRL 0x60 +-#define DEVICE_CTRL_MAX_PAYLOAD_MASK 0x7 +-#define DEVICE_CTRL_MAX_PAYLOAD_SHIFT 5 +-#define DEVICE_CTRL_MAX_RREQ_SZ_MASK 0x7 +-#define DEVICE_CTRL_MAX_RREQ_SZ_SHIFT 12 ++#define DEVICE_CTRL_MAXRRS_MIN 2 + + #define REG_LINK_CTRL 0x68 + #define LINK_CTRL_L0S_EN 0x01 + #define LINK_CTRL_L1_EN 0x02 + #define LINK_CTRL_EXT_SYNC 0x80 + +-#define REG_VPD_CAP 0x6C +-#define VPD_CAP_ID_MASK 0xff +-#define VPD_CAP_ID_SHIFT 0 +-#define VPD_CAP_NEXT_PTR_MASK 0xFF +-#define VPD_CAP_NEXT_PTR_SHIFT 8 +-#define VPD_CAP_VPD_ADDR_MASK 0x7FFF +-#define VPD_CAP_VPD_ADDR_SHIFT 16 +-#define VPD_CAP_VPD_FLAG 0x80000000 +- +-#define REG_VPD_DATA 0x70 +- +-#define REG_PCIE_UC_SEVERITY 0x10C +-#define PCIE_UC_SERVRITY_TRN 0x00000001 +-#define PCIE_UC_SERVRITY_DLP 0x00000010 +-#define PCIE_UC_SERVRITY_PSN_TLP 0x00001000 +-#define PCIE_UC_SERVRITY_FCP 0x00002000 +-#define PCIE_UC_SERVRITY_CPL_TO 0x00004000 +-#define PCIE_UC_SERVRITY_CA 0x00008000 +-#define PCIE_UC_SERVRITY_UC 0x00010000 +-#define PCIE_UC_SERVRITY_ROV 0x00020000 +-#define PCIE_UC_SERVRITY_MLFP 0x00040000 +-#define PCIE_UC_SERVRITY_ECRC 0x00080000 +-#define PCIE_UC_SERVRITY_UR 0x00100000 +- + #define REG_DEV_SERIALNUM_CTRL 0x200 + #define REG_DEV_MAC_SEL_MASK 0x0 /* 0:EUI; 1:MAC */ + #define REG_DEV_MAC_SEL_SHIFT 0 +@@ -90,25 +94,17 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define REG_DEV_SERIAL_NUM_EN_SHIFT 1 + + #define REG_TWSI_CTRL 0x218 ++#define TWSI_CTLR_FREQ_MASK 0x3UL ++#define TWSI_CTRL_FREQ_SHIFT 24 ++#define TWSI_CTRL_FREQ_100K 0 ++#define TWSI_CTRL_FREQ_200K 1 ++#define TWSI_CTRL_FREQ_300K 2 ++#define TWSI_CTRL_FREQ_400K 3 ++#define TWSI_CTRL_LD_EXIST BIT(23) ++#define TWSI_CTRL_HW_LDSTAT BIT(12) /* 0:finish,1:in progress */ ++#define TWSI_CTRL_SW_LDSTART BIT(11) + #define TWSI_CTRL_LD_OFFSET_MASK 0xFF + #define TWSI_CTRL_LD_OFFSET_SHIFT 0 +-#define TWSI_CTRL_LD_SLV_ADDR_MASK 0x7 +-#define TWSI_CTRL_LD_SLV_ADDR_SHIFT 8 +-#define TWSI_CTRL_SW_LDSTART 0x800 +-#define TWSI_CTRL_HW_LDSTART 0x1000 +-#define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x7F +-#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT 15 +-#define TWSI_CTRL_LD_EXIST 0x400000 +-#define TWSI_CTRL_READ_FREQ_SEL_MASK 0x3 +-#define TWSI_CTRL_READ_FREQ_SEL_SHIFT 23 +-#define TWSI_CTRL_FREQ_SEL_100K 0 +-#define TWSI_CTRL_FREQ_SEL_200K 1 +-#define TWSI_CTRL_FREQ_SEL_300K 2 +-#define TWSI_CTRL_FREQ_SEL_400K 3 +-#define TWSI_CTRL_SMB_SLV_ADDR +-#define TWSI_CTRL_WRITE_FREQ_SEL_MASK 0x3 +-#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT 24 +- + + #define REG_PCIE_DEV_MISC_CTRL 0x21C + #define PCIE_DEV_MISC_EXT_PIPE 0x2 +@@ -118,16 +114,23 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define PCIE_DEV_MISC_SERDES_SEL_DIN 0x10 + + #define REG_PCIE_PHYMISC 0x1000 +-#define PCIE_PHYMISC_FORCE_RCV_DET 0x4 ++#define PCIE_PHYMISC_FORCE_RCV_DET BIT(2) ++#define PCIE_PHYMISC_NFTS_MASK 0xFFUL ++#define PCIE_PHYMISC_NFTS_SHIFT 16 + + #define REG_PCIE_PHYMISC2 0x1004 +-#define PCIE_PHYMISC2_SERDES_CDR_MASK 0x3 +-#define PCIE_PHYMISC2_SERDES_CDR_SHIFT 16 +-#define PCIE_PHYMISC2_SERDES_TH_MASK 0x3 +-#define PCIE_PHYMISC2_SERDES_TH_SHIFT 18 ++#define PCIE_PHYMISC2_L0S_TH_MASK 0x3UL ++#define PCIE_PHYMISC2_L0S_TH_SHIFT 18 ++#define L2CB1_PCIE_PHYMISC2_L0S_TH 3 ++#define PCIE_PHYMISC2_CDR_BW_MASK 0x3UL ++#define PCIE_PHYMISC2_CDR_BW_SHIFT 16 ++#define L2CB1_PCIE_PHYMISC2_CDR_BW 3 + + #define REG_TWSI_DEBUG 0x1108 +-#define TWSI_DEBUG_DEV_EXIST 0x20000000 ++#define TWSI_DEBUG_DEV_EXIST BIT(29) ++ ++#define REG_DMA_DBG 0x1114 ++#define DMA_DBG_VENDOR_MSG BIT(0) + + #define REG_EEPROM_CTRL 0x12C0 + #define EEPROM_CTRL_DATA_HI_MASK 0xFFFF +@@ -140,56 +143,81 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define REG_EEPROM_DATA_LO 0x12C4 + + #define REG_OTP_CTRL 0x12F0 +-#define OTP_CTRL_CLK_EN 0x0002 ++#define OTP_CTRL_CLK_EN BIT(1) + + #define REG_PM_CTRL 0x12F8 +-#define PM_CTRL_SDES_EN 0x00000001 +-#define PM_CTRL_RBER_EN 0x00000002 +-#define PM_CTRL_CLK_REQ_EN 0x00000004 +-#define PM_CTRL_ASPM_L1_EN 0x00000008 +-#define PM_CTRL_SERDES_L1_EN 0x00000010 +-#define PM_CTRL_SERDES_PLL_L1_EN 0x00000020 +-#define PM_CTRL_SERDES_PD_EX_L1 0x00000040 +-#define PM_CTRL_SERDES_BUDS_RX_L1_EN 0x00000080 +-#define PM_CTRL_L0S_ENTRY_TIMER_MASK 0xF +-#define PM_CTRL_L0S_ENTRY_TIMER_SHIFT 8 +-#define PM_CTRL_ASPM_L0S_EN 0x00001000 +-#define PM_CTRL_CLK_SWH_L1 0x00002000 +-#define PM_CTRL_CLK_PWM_VER1_1 0x00004000 +-#define PM_CTRL_RCVR_WT_TIMER 0x00008000 +-#define PM_CTRL_L1_ENTRY_TIMER_MASK 0xF +-#define PM_CTRL_L1_ENTRY_TIMER_SHIFT 16 +-#define PM_CTRL_PM_REQ_TIMER_MASK 0xF +-#define PM_CTRL_PM_REQ_TIMER_SHIFT 20 +-#define PM_CTRL_LCKDET_TIMER_MASK 0xF ++#define PM_CTRL_HOTRST BIT(31) ++#define PM_CTRL_MAC_ASPM_CHK BIT(30) /* L0s/L1 dis by MAC based on ++ * thrghput(setting in 15A0) */ ++#define PM_CTRL_SA_DLY_EN BIT(29) ++#define PM_CTRL_L0S_BUFSRX_EN BIT(28) ++#define PM_CTRL_LCKDET_TIMER_MASK 0xFUL + #define PM_CTRL_LCKDET_TIMER_SHIFT 24 +-#define PM_CTRL_EN_BUFS_RX_L0S 0x10000000 +-#define PM_CTRL_SA_DLY_EN 0x20000000 +-#define PM_CTRL_MAC_ASPM_CHK 0x40000000 +-#define PM_CTRL_HOTRST 0x80000000 ++#define PM_CTRL_LCKDET_TIMER_DEF 0xC ++#define PM_CTRL_PM_REQ_TIMER_MASK 0xFUL ++#define PM_CTRL_PM_REQ_TIMER_SHIFT 20 /* pm_request_l1 time > @ ++ * ->L0s not L1 */ ++#define PM_CTRL_PM_REQ_TO_DEF 0xF ++#define PMCTRL_TXL1_AFTER_L0S BIT(19) /* l1dv2.0+ */ ++#define L1D_PMCTRL_L1_ENTRY_TM_MASK 7UL /* l1dv2.0+, 3bits */ ++#define L1D_PMCTRL_L1_ENTRY_TM_SHIFT 16 ++#define L1D_PMCTRL_L1_ENTRY_TM_DIS 0 ++#define L1D_PMCTRL_L1_ENTRY_TM_2US 1 ++#define L1D_PMCTRL_L1_ENTRY_TM_4US 2 ++#define L1D_PMCTRL_L1_ENTRY_TM_8US 3 ++#define L1D_PMCTRL_L1_ENTRY_TM_16US 4 ++#define L1D_PMCTRL_L1_ENTRY_TM_24US 5 ++#define L1D_PMCTRL_L1_ENTRY_TM_32US 6 ++#define L1D_PMCTRL_L1_ENTRY_TM_63US 7 ++#define PM_CTRL_L1_ENTRY_TIMER_MASK 0xFUL /* l1C 4bits */ ++#define PM_CTRL_L1_ENTRY_TIMER_SHIFT 16 ++#define L2CB1_PM_CTRL_L1_ENTRY_TM 7 ++#define L1C_PM_CTRL_L1_ENTRY_TM 0xF ++#define PM_CTRL_RCVR_WT_TIMER BIT(15) /* 1:1us, 0:2ms */ ++#define PM_CTRL_CLK_PWM_VER1_1 BIT(14) /* 0:1.0a,1:1.1 */ ++#define PM_CTRL_CLK_SWH_L1 BIT(13) /* en pcie clk sw in L1 */ ++#define PM_CTRL_ASPM_L0S_EN BIT(12) ++#define PM_CTRL_RXL1_AFTER_L0S BIT(11) /* l1dv2.0+ */ ++#define L1D_PMCTRL_L0S_TIMER_MASK 7UL /* l1d2.0+, 3bits*/ ++#define L1D_PMCTRL_L0S_TIMER_SHIFT 8 ++#define PM_CTRL_L0S_ENTRY_TIMER_MASK 0xFUL /* l1c, 4bits */ ++#define PM_CTRL_L0S_ENTRY_TIMER_SHIFT 8 ++#define PM_CTRL_SERDES_BUFS_RX_L1_EN BIT(7) ++#define PM_CTRL_SERDES_PD_EX_L1 BIT(6) /* power down serdes rx */ ++#define PM_CTRL_SERDES_PLL_L1_EN BIT(5) ++#define PM_CTRL_SERDES_L1_EN BIT(4) ++#define PM_CTRL_ASPM_L1_EN BIT(3) ++#define PM_CTRL_CLK_REQ_EN BIT(2) ++#define PM_CTRL_RBER_EN BIT(1) ++#define PM_CTRL_SPRSDWER_EN BIT(0) + + #define REG_LTSSM_ID_CTRL 0x12FC + #define LTSSM_ID_EN_WRO 0x1000 ++ ++ + /* Selene Master Control Register */ + #define REG_MASTER_CTRL 0x1400 +-#define MASTER_CTRL_SOFT_RST 0x1 +-#define MASTER_CTRL_TEST_MODE_MASK 0x3 +-#define MASTER_CTRL_TEST_MODE_SHIFT 2 +-#define MASTER_CTRL_BERT_START 0x10 +-#define MASTER_CTRL_OOB_DIS_OFF 0x40 +-#define MASTER_CTRL_SA_TIMER_EN 0x80 +-#define MASTER_CTRL_MTIMER_EN 0x100 +-#define MASTER_CTRL_MANUAL_INT 0x200 +-#define MASTER_CTRL_TX_ITIMER_EN 0x400 +-#define MASTER_CTRL_RX_ITIMER_EN 0x800 +-#define MASTER_CTRL_CLK_SEL_DIS 0x1000 +-#define MASTER_CTRL_CLK_SWH_MODE 0x2000 +-#define MASTER_CTRL_INT_RDCLR 0x4000 +-#define MASTER_CTRL_REV_NUM_SHIFT 16 +-#define MASTER_CTRL_REV_NUM_MASK 0xff +-#define MASTER_CTRL_DEV_ID_SHIFT 24 +-#define MASTER_CTRL_DEV_ID_MASK 0x7f +-#define MASTER_CTRL_OTP_SEL 0x80000000 ++#define MASTER_CTRL_OTP_SEL BIT(31) ++#define MASTER_DEV_NUM_MASK 0x7FUL ++#define MASTER_DEV_NUM_SHIFT 24 ++#define MASTER_REV_NUM_MASK 0xFFUL ++#define MASTER_REV_NUM_SHIFT 16 ++#define MASTER_CTRL_INT_RDCLR BIT(14) ++#define MASTER_CTRL_CLK_SEL_DIS BIT(12) /* 1:alwys sel pclk from ++ * serdes, not sw to 25M */ ++#define MASTER_CTRL_RX_ITIMER_EN BIT(11) /* IRQ MODURATION FOR RX */ ++#define MASTER_CTRL_TX_ITIMER_EN BIT(10) /* MODURATION FOR TX/RX */ ++#define MASTER_CTRL_MANU_INT BIT(9) /* SOFT MANUAL INT */ ++#define MASTER_CTRL_MANUTIMER_EN BIT(8) ++#define MASTER_CTRL_SA_TIMER_EN BIT(7) /* SYS ALIVE TIMER EN */ ++#define MASTER_CTRL_OOB_DIS BIT(6) /* OUT OF BOX DIS */ ++#define MASTER_CTRL_WAKEN_25M BIT(5) /* WAKE WO. PCIE CLK */ ++#define MASTER_CTRL_BERT_START BIT(4) ++#define MASTER_PCIE_TSTMOD_MASK 3UL ++#define MASTER_PCIE_TSTMOD_SHIFT 2 ++#define MASTER_PCIE_RST BIT(1) ++#define MASTER_CTRL_SOFT_RST BIT(0) /* RST MAC & DMA */ ++#define DMA_MAC_RST_TO 50 + + /* Timer Initial Value Register */ + #define REG_MANUAL_TIMER_INIT 0x1404 +@@ -201,87 +229,85 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define IRQ_MODRT_RX_TIMER_SHIFT 16 + + #define REG_GPHY_CTRL 0x140C +-#define GPHY_CTRL_EXT_RESET 0x1 +-#define GPHY_CTRL_RTL_MODE 0x2 +-#define GPHY_CTRL_LED_MODE 0x4 +-#define GPHY_CTRL_ANEG_NOW 0x8 +-#define GPHY_CTRL_REV_ANEG 0x10 +-#define GPHY_CTRL_GATE_25M_EN 0x20 +-#define GPHY_CTRL_LPW_EXIT 0x40 +-#define GPHY_CTRL_PHY_IDDQ 0x80 +-#define GPHY_CTRL_PHY_IDDQ_DIS 0x100 +-#define GPHY_CTRL_GIGA_DIS 0x200 +-#define GPHY_CTRL_HIB_EN 0x400 +-#define GPHY_CTRL_HIB_PULSE 0x800 +-#define GPHY_CTRL_SEL_ANA_RST 0x1000 +-#define GPHY_CTRL_PHY_PLL_ON 0x2000 +-#define GPHY_CTRL_PWDOWN_HW 0x4000 +-#define GPHY_CTRL_PHY_PLL_BYPASS 0x8000 +- +-#define GPHY_CTRL_DEFAULT ( \ +- GPHY_CTRL_SEL_ANA_RST |\ +- GPHY_CTRL_HIB_PULSE |\ +- GPHY_CTRL_HIB_EN) +- +-#define GPHY_CTRL_PW_WOL_DIS ( \ +- GPHY_CTRL_SEL_ANA_RST |\ +- GPHY_CTRL_HIB_PULSE |\ +- GPHY_CTRL_HIB_EN |\ +- GPHY_CTRL_PWDOWN_HW |\ +- GPHY_CTRL_PHY_IDDQ) +- +-#define GPHY_CTRL_POWER_SAVING ( \ +- GPHY_CTRL_SEL_ANA_RST |\ +- GPHY_CTRL_HIB_EN |\ +- GPHY_CTRL_HIB_PULSE |\ +- GPHY_CTRL_PWDOWN_HW |\ +- GPHY_CTRL_PHY_IDDQ) ++#define GPHY_CTRL_ADDR_MASK 0x1FUL ++#define GPHY_CTRL_ADDR_SHIFT 19 ++#define GPHY_CTRL_BP_VLTGSW BIT(18) ++#define GPHY_CTRL_100AB_EN BIT(17) ++#define GPHY_CTRL_10AB_EN BIT(16) ++#define GPHY_CTRL_PHY_PLL_BYPASS BIT(15) ++#define GPHY_CTRL_PWDOWN_HW BIT(14) /* affect MAC&PHY, to low pw */ ++#define GPHY_CTRL_PHY_PLL_ON BIT(13) /* 1:pll always on, 0:can sw */ ++#define GPHY_CTRL_SEL_ANA_RST BIT(12) ++#define GPHY_CTRL_HIB_PULSE BIT(11) ++#define GPHY_CTRL_HIB_EN BIT(10) ++#define GPHY_CTRL_GIGA_DIS BIT(9) ++#define GPHY_CTRL_PHY_IDDQ_DIS BIT(8) /* pw on RST */ ++#define GPHY_CTRL_PHY_IDDQ BIT(7) /* bit8 affect bit7 while rb */ ++#define GPHY_CTRL_LPW_EXIT BIT(6) ++#define GPHY_CTRL_GATE_25M_EN BIT(5) ++#define GPHY_CTRL_REV_ANEG BIT(4) ++#define GPHY_CTRL_ANEG_NOW BIT(3) ++#define GPHY_CTRL_LED_MODE BIT(2) ++#define GPHY_CTRL_RTL_MODE BIT(1) ++#define GPHY_CTRL_EXT_RESET BIT(0) /* 1:out of DSP RST status */ ++#define GPHY_CTRL_EXT_RST_TO 80 /* 800us atmost */ ++#define GPHY_CTRL_CLS (\ ++ GPHY_CTRL_LED_MODE |\ ++ GPHY_CTRL_100AB_EN |\ ++ GPHY_CTRL_PHY_PLL_ON) ++ + /* Block IDLE Status Register */ +-#define REG_IDLE_STATUS 0x1410 +-#define IDLE_STATUS_MASK 0x00FF +-#define IDLE_STATUS_RXMAC_NO_IDLE 0x1 +-#define IDLE_STATUS_TXMAC_NO_IDLE 0x2 +-#define IDLE_STATUS_RXQ_NO_IDLE 0x4 +-#define IDLE_STATUS_TXQ_NO_IDLE 0x8 +-#define IDLE_STATUS_DMAR_NO_IDLE 0x10 +-#define IDLE_STATUS_DMAW_NO_IDLE 0x20 +-#define IDLE_STATUS_SMB_NO_IDLE 0x40 +-#define IDLE_STATUS_CMB_NO_IDLE 0x80 ++#define REG_IDLE_STATUS 0x1410 ++#define IDLE_STATUS_SFORCE_MASK 0xFUL ++#define IDLE_STATUS_SFORCE_SHIFT 14 ++#define IDLE_STATUS_CALIB_DONE BIT(13) ++#define IDLE_STATUS_CALIB_RES_MASK 0x1FUL ++#define IDLE_STATUS_CALIB_RES_SHIFT 8 ++#define IDLE_STATUS_CALIBERR_MASK 0xFUL ++#define IDLE_STATUS_CALIBERR_SHIFT 4 ++#define IDLE_STATUS_TXQ_BUSY BIT(3) ++#define IDLE_STATUS_RXQ_BUSY BIT(2) ++#define IDLE_STATUS_TXMAC_BUSY BIT(1) ++#define IDLE_STATUS_RXMAC_BUSY BIT(0) ++#define IDLE_STATUS_MASK (\ ++ IDLE_STATUS_TXQ_BUSY |\ ++ IDLE_STATUS_RXQ_BUSY |\ ++ IDLE_STATUS_TXMAC_BUSY |\ ++ IDLE_STATUS_RXMAC_BUSY) + + /* MDIO Control Register */ + #define REG_MDIO_CTRL 0x1414 +-#define MDIO_DATA_MASK 0xffff /* On MDIO write, the 16-bit +- * control data to write to PHY +- * MII management register */ +-#define MDIO_DATA_SHIFT 0 /* On MDIO read, the 16-bit +- * status data that was read +- * from the PHY MII management register */ +-#define MDIO_REG_ADDR_MASK 0x1f /* MDIO register address */ +-#define MDIO_REG_ADDR_SHIFT 16 +-#define MDIO_RW 0x200000 /* 1: read, 0: write */ +-#define MDIO_SUP_PREAMBLE 0x400000 /* Suppress preamble */ +-#define MDIO_START 0x800000 /* Write 1 to initiate the MDIO +- * master. And this bit is self +- * cleared after one cycle */ +-#define MDIO_CLK_SEL_SHIFT 24 +-#define MDIO_CLK_25_4 0 +-#define MDIO_CLK_25_6 2 +-#define MDIO_CLK_25_8 3 +-#define MDIO_CLK_25_10 4 +-#define MDIO_CLK_25_14 5 +-#define MDIO_CLK_25_20 6 +-#define MDIO_CLK_25_28 7 +-#define MDIO_BUSY 0x8000000 +-#define MDIO_AP_EN 0x10000000 +-#define MDIO_WAIT_TIMES 10 +- +-/* MII PHY Status Register */ +-#define REG_PHY_STATUS 0x1418 +-#define PHY_GENERAL_STATUS_MASK 0xFFFF +-#define PHY_STATUS_RECV_ENABLE 0x0001 +-#define PHY_OE_PWSP_STATUS_MASK 0x07FF +-#define PHY_OE_PWSP_STATUS_SHIFT 16 +-#define PHY_STATUS_LPW_STATE 0x80000000 ++#define MDIO_CTRL_MODE_EXT BIT(30) ++#define MDIO_CTRL_POST_READ BIT(29) ++#define MDIO_CTRL_AP_EN BIT(28) ++#define MDIO_CTRL_BUSY BIT(27) ++#define MDIO_CTRL_CLK_SEL_MASK 0x7UL ++#define MDIO_CTRL_CLK_SEL_SHIFT 24 ++#define MDIO_CTRL_CLK_25_4 0 /* 25MHz divide 4 */ ++#define MDIO_CTRL_CLK_25_6 2 ++#define MDIO_CTRL_CLK_25_8 3 ++#define MDIO_CTRL_CLK_25_10 4 ++#define MDIO_CTRL_CLK_25_32 5 ++#define MDIO_CTRL_CLK_25_64 6 ++#define MDIO_CTRL_CLK_25_128 7 ++#define MDIO_CTRL_START BIT(23) ++#define MDIO_CTRL_SPRES_PRMBL BIT(22) ++#define MDIO_CTRL_OP_READ BIT(21) /* 1:read, 0:write */ ++#define MDIO_CTRL_REG_MASK 0x1FUL ++#define MDIO_CTRL_REG_SHIFT 16 ++#define MDIO_CTRL_DATA_MASK 0xFFFFUL ++#define MDIO_CTRL_DATA_SHIFT 0 ++#define MDIO_MAX_AC_TO 120 /* 1.2ms timeout for slow clk */ ++ ++/* for extension reg access */ ++#define REG_MDIO_EXTN 0x1448 ++#define MDIO_EXTN_PORTAD_MASK 0x1FUL ++#define MDIO_EXTN_PORTAD_SHIFT 21 ++#define MDIO_EXTN_DEVAD_MASK 0x1FUL ++#define MDIO_EXTN_DEVAD_SHIFT 16 ++#define MDIO_EXTN_REG_MASK 0xFFFFUL ++#define MDIO_EXTN_REG_SHIFT 0 ++ + /* BIST Control and Status Register0 (for the Packet Memory) */ + #define REG_BIST0_CTRL 0x141c + #define BIST0_NOW 0x1 +@@ -299,50 +325,81 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define BIST1_FUSE_FLAG 0x4 + + /* SerDes Lock Detect Control and Status Register */ +-#define REG_SERDES_LOCK 0x1424 +-#define SERDES_LOCK_DETECT 0x1 /* SerDes lock detected. This signal +- * comes from Analog SerDes */ +-#define SERDES_LOCK_DETECT_EN 0x2 /* 1: Enable SerDes Lock detect function */ +-#define SERDES_LOCK_STS_SELFB_PLL_SHIFT 0xE +-#define SERDES_LOCK_STS_SELFB_PLL_MASK 0x3 +-#define SERDES_OVCLK_18_25 0x0 +-#define SERDES_OVCLK_12_18 0x1 +-#define SERDES_OVCLK_0_4 0x2 +-#define SERDES_OVCLK_4_12 0x3 +-#define SERDES_MAC_CLK_SLOWDOWN 0x20000 +-#define SERDES_PYH_CLK_SLOWDOWN 0x40000 ++#define REG_SERDES 0x1424 ++#define SERDES_PHY_CLK_SLOWDOWN BIT(18) ++#define SERDES_MAC_CLK_SLOWDOWN BIT(17) ++#define SERDES_SELFB_PLL_MASK 0x3UL ++#define SERDES_SELFB_PLL_SHIFT 14 ++#define SERDES_PHYCLK_SEL_GTX BIT(13) /* 1:gtx_clk, 0:25M */ ++#define SERDES_PCIECLK_SEL_SRDS BIT(12) /* 1:serdes,0:25M */ ++#define SERDES_BUFS_RX_EN BIT(11) ++#define SERDES_PD_RX BIT(10) ++#define SERDES_PLL_EN BIT(9) ++#define SERDES_EN BIT(8) ++#define SERDES_SELFB_PLL_SEL_CSR BIT(6) /* 0:state-machine,1:csr */ ++#define SERDES_SELFB_PLL_CSR_MASK 0x3UL ++#define SERDES_SELFB_PLL_CSR_SHIFT 4 ++#define SERDES_SELFB_PLL_CSR_4 3 /* 4-12% OV-CLK */ ++#define SERDES_SELFB_PLL_CSR_0 2 /* 0-4% OV-CLK */ ++#define SERDES_SELFB_PLL_CSR_12 1 /* 12-18% OV-CLK */ ++#define SERDES_SELFB_PLL_CSR_18 0 /* 18-25% OV-CLK */ ++#define SERDES_VCO_SLOW BIT(3) ++#define SERDES_VCO_FAST BIT(2) ++#define SERDES_LOCK_DETECT_EN BIT(1) ++#define SERDES_LOCK_DETECT BIT(0) ++ ++#define REG_LPI_DECISN_TIMER 0x143C ++#define L2CB_LPI_DESISN_TIMER 0x7D00 ++ ++#define REG_LPI_CTRL 0x1440 ++#define LPI_CTRL_CHK_DA BIT(31) ++#define LPI_CTRL_ENH_TO_MASK 0x1FFFUL ++#define LPI_CTRL_ENH_TO_SHIFT 12 ++#define LPI_CTRL_ENH_TH_MASK 0x1FUL ++#define LPI_CTRL_ENH_TH_SHIFT 6 ++#define LPI_CTRL_ENH_EN BIT(5) ++#define LPI_CTRL_CHK_RX BIT(4) ++#define LPI_CTRL_CHK_STATE BIT(3) ++#define LPI_CTRL_GMII BIT(2) ++#define LPI_CTRL_TO_PHY BIT(1) ++#define LPI_CTRL_EN BIT(0) ++ ++#define REG_LPI_WAIT 0x1444 ++#define LPI_WAIT_TIMER_MASK 0xFFFFUL ++#define LPI_WAIT_TIMER_SHIFT 0 + + /* MAC Control Register */ + #define REG_MAC_CTRL 0x1480 +-#define MAC_CTRL_TX_EN 0x1 +-#define MAC_CTRL_RX_EN 0x2 +-#define MAC_CTRL_TX_FLOW 0x4 +-#define MAC_CTRL_RX_FLOW 0x8 +-#define MAC_CTRL_LOOPBACK 0x10 +-#define MAC_CTRL_DUPLX 0x20 +-#define MAC_CTRL_ADD_CRC 0x40 +-#define MAC_CTRL_PAD 0x80 +-#define MAC_CTRL_LENCHK 0x100 +-#define MAC_CTRL_HUGE_EN 0x200 +-#define MAC_CTRL_PRMLEN_SHIFT 10 +-#define MAC_CTRL_PRMLEN_MASK 0xf +-#define MAC_CTRL_RMV_VLAN 0x4000 +-#define MAC_CTRL_PROMIS_EN 0x8000 +-#define MAC_CTRL_TX_PAUSE 0x10000 +-#define MAC_CTRL_SCNT 0x20000 +-#define MAC_CTRL_SRST_TX 0x40000 +-#define MAC_CTRL_TX_SIMURST 0x80000 +-#define MAC_CTRL_SPEED_SHIFT 20 +-#define MAC_CTRL_SPEED_MASK 0x3 +-#define MAC_CTRL_DBG_TX_BKPRESURE 0x400000 +-#define MAC_CTRL_TX_HUGE 0x800000 +-#define MAC_CTRL_RX_CHKSUM_EN 0x1000000 +-#define MAC_CTRL_MC_ALL_EN 0x2000000 +-#define MAC_CTRL_BC_EN 0x4000000 +-#define MAC_CTRL_DBG 0x8000000 +-#define MAC_CTRL_SINGLE_PAUSE_EN 0x10000000 +-#define MAC_CTRL_HASH_ALG_CRC32 0x20000000 +-#define MAC_CTRL_SPEED_MODE_SW 0x40000000 ++#define MAC_CTRL_SPEED_MODE_SW BIT(30) /* 0:phy,1:sw */ ++#define MAC_CTRL_HASH_ALG_CRC32 BIT(29) /* 1:legacy,0:lw_5b */ ++#define MAC_CTRL_SINGLE_PAUSE_EN BIT(28) ++#define MAC_CTRL_DBG BIT(27) ++#define MAC_CTRL_BC_EN BIT(26) ++#define MAC_CTRL_MC_ALL_EN BIT(25) ++#define MAC_CTRL_RX_CHKSUM_EN BIT(24) ++#define MAC_CTRL_TX_HUGE BIT(23) ++#define MAC_CTRL_DBG_TX_BKPRESURE BIT(22) ++#define MAC_CTRL_SPEED_MASK 3UL ++#define MAC_CTRL_SPEED_SHIFT 20 ++#define MAC_CTRL_SPEED_10_100 1 ++#define MAC_CTRL_SPEED_1000 2 ++#define MAC_CTRL_TX_SIMURST BIT(19) ++#define MAC_CTRL_SCNT BIT(17) ++#define MAC_CTRL_TX_PAUSE BIT(16) ++#define MAC_CTRL_PROMIS_EN BIT(15) ++#define MAC_CTRL_RMV_VLAN BIT(14) ++#define MAC_CTRL_PRMLEN_MASK 0xFUL ++#define MAC_CTRL_PRMLEN_SHIFT 10 ++#define MAC_CTRL_HUGE_EN BIT(9) ++#define MAC_CTRL_LENCHK BIT(8) ++#define MAC_CTRL_PAD BIT(7) ++#define MAC_CTRL_ADD_CRC BIT(6) ++#define MAC_CTRL_DUPLX BIT(5) ++#define MAC_CTRL_LOOPBACK BIT(4) ++#define MAC_CTRL_RX_FLOW BIT(3) ++#define MAC_CTRL_TX_FLOW BIT(2) ++#define MAC_CTRL_RX_EN BIT(1) ++#define MAC_CTRL_TX_EN BIT(0) + + /* MAC IPG/IFG Control Register */ + #define REG_MAC_IPG_IFG 0x1484 +@@ -386,34 +443,53 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + + /* Wake-On-Lan control register */ + #define REG_WOL_CTRL 0x14a0 +-#define WOL_PATTERN_EN 0x00000001 +-#define WOL_PATTERN_PME_EN 0x00000002 +-#define WOL_MAGIC_EN 0x00000004 +-#define WOL_MAGIC_PME_EN 0x00000008 +-#define WOL_LINK_CHG_EN 0x00000010 +-#define WOL_LINK_CHG_PME_EN 0x00000020 +-#define WOL_PATTERN_ST 0x00000100 +-#define WOL_MAGIC_ST 0x00000200 +-#define WOL_LINKCHG_ST 0x00000400 +-#define WOL_CLK_SWITCH_EN 0x00008000 +-#define WOL_PT0_EN 0x00010000 +-#define WOL_PT1_EN 0x00020000 +-#define WOL_PT2_EN 0x00040000 +-#define WOL_PT3_EN 0x00080000 +-#define WOL_PT4_EN 0x00100000 +-#define WOL_PT5_EN 0x00200000 +-#define WOL_PT6_EN 0x00400000 ++#define WOL_PT7_MATCH BIT(31) ++#define WOL_PT6_MATCH BIT(30) ++#define WOL_PT5_MATCH BIT(29) ++#define WOL_PT4_MATCH BIT(28) ++#define WOL_PT3_MATCH BIT(27) ++#define WOL_PT2_MATCH BIT(26) ++#define WOL_PT1_MATCH BIT(25) ++#define WOL_PT0_MATCH BIT(24) ++#define WOL_PT7_EN BIT(23) ++#define WOL_PT6_EN BIT(22) ++#define WOL_PT5_EN BIT(21) ++#define WOL_PT4_EN BIT(20) ++#define WOL_PT3_EN BIT(19) ++#define WOL_PT2_EN BIT(18) ++#define WOL_PT1_EN BIT(17) ++#define WOL_PT0_EN BIT(16) ++#define WOL_LNKCHG_ST BIT(10) ++#define WOL_MAGIC_ST BIT(9) ++#define WOL_PATTERN_ST BIT(8) ++#define WOL_OOB_EN BIT(6) ++#define WOL_LINK_CHG_PME_EN BIT(5) ++#define WOL_LINK_CHG_EN BIT(4) ++#define WOL_MAGIC_PME_EN BIT(3) ++#define WOL_MAGIC_EN BIT(2) ++#define WOL_PATTERN_PME_EN BIT(1) ++#define WOL_PATTERN_EN BIT(0) + + /* WOL Length ( 2 DWORD ) */ +-#define REG_WOL_PATTERN_LEN 0x14a4 +-#define WOL_PT_LEN_MASK 0x7f +-#define WOL_PT0_LEN_SHIFT 0 +-#define WOL_PT1_LEN_SHIFT 8 +-#define WOL_PT2_LEN_SHIFT 16 +-#define WOL_PT3_LEN_SHIFT 24 +-#define WOL_PT4_LEN_SHIFT 0 +-#define WOL_PT5_LEN_SHIFT 8 +-#define WOL_PT6_LEN_SHIFT 16 ++#define REG_WOL_PTLEN1 0x14A4 ++#define WOL_PTLEN1_3_MASK 0xFFUL ++#define WOL_PTLEN1_3_SHIFT 24 ++#define WOL_PTLEN1_2_MASK 0xFFUL ++#define WOL_PTLEN1_2_SHIFT 16 ++#define WOL_PTLEN1_1_MASK 0xFFUL ++#define WOL_PTLEN1_1_SHIFT 8 ++#define WOL_PTLEN1_0_MASK 0xFFUL ++#define WOL_PTLEN1_0_SHIFT 0 ++ ++#define REG_WOL_PTLEN2 0x14A8 ++#define WOL_PTLEN2_7_MASK 0xFFUL ++#define WOL_PTLEN2_7_SHIFT 24 ++#define WOL_PTLEN2_6_MASK 0xFFUL ++#define WOL_PTLEN2_6_SHIFT 16 ++#define WOL_PTLEN2_5_MASK 0xFFUL ++#define WOL_PTLEN2_5_SHIFT 8 ++#define WOL_PTLEN2_4_MASK 0xFFUL ++#define WOL_PTLEN2_4_SHIFT 0 + + /* Internal SRAM Partition Register */ + #define RFDX_HEAD_ADDR_MASK 0x03FF +@@ -458,66 +534,50 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + */ + #define REG_RX_BASE_ADDR_HI 0x1540 + #define REG_TX_BASE_ADDR_HI 0x1544 +-#define REG_SMB_BASE_ADDR_HI 0x1548 +-#define REG_SMB_BASE_ADDR_LO 0x154C + #define REG_RFD0_HEAD_ADDR_LO 0x1550 +-#define REG_RFD1_HEAD_ADDR_LO 0x1554 +-#define REG_RFD2_HEAD_ADDR_LO 0x1558 +-#define REG_RFD3_HEAD_ADDR_LO 0x155C + #define REG_RFD_RING_SIZE 0x1560 + #define RFD_RING_SIZE_MASK 0x0FFF + #define REG_RX_BUF_SIZE 0x1564 + #define RX_BUF_SIZE_MASK 0xFFFF + #define REG_RRD0_HEAD_ADDR_LO 0x1568 +-#define REG_RRD1_HEAD_ADDR_LO 0x156C +-#define REG_RRD2_HEAD_ADDR_LO 0x1570 +-#define REG_RRD3_HEAD_ADDR_LO 0x1574 + #define REG_RRD_RING_SIZE 0x1578 + #define RRD_RING_SIZE_MASK 0x0FFF +-#define REG_HTPD_HEAD_ADDR_LO 0x157C +-#define REG_NTPD_HEAD_ADDR_LO 0x1580 ++#define REG_TPD_PRI1_ADDR_LO 0x157C ++#define REG_TPD_PRI0_ADDR_LO 0x1580 + #define REG_TPD_RING_SIZE 0x1584 + #define TPD_RING_SIZE_MASK 0xFFFF +-#define REG_CMB_BASE_ADDR_LO 0x1588 +- +-/* RSS about */ +-#define REG_RSS_KEY0 0x14B0 +-#define REG_RSS_KEY1 0x14B4 +-#define REG_RSS_KEY2 0x14B8 +-#define REG_RSS_KEY3 0x14BC +-#define REG_RSS_KEY4 0x14C0 +-#define REG_RSS_KEY5 0x14C4 +-#define REG_RSS_KEY6 0x14C8 +-#define REG_RSS_KEY7 0x14CC +-#define REG_RSS_KEY8 0x14D0 +-#define REG_RSS_KEY9 0x14D4 +-#define REG_IDT_TABLE0 0x14E0 +-#define REG_IDT_TABLE1 0x14E4 +-#define REG_IDT_TABLE2 0x14E8 +-#define REG_IDT_TABLE3 0x14EC +-#define REG_IDT_TABLE4 0x14F0 +-#define REG_IDT_TABLE5 0x14F4 +-#define REG_IDT_TABLE6 0x14F8 +-#define REG_IDT_TABLE7 0x14FC +-#define REG_IDT_TABLE REG_IDT_TABLE0 +-#define REG_RSS_HASH_VALUE 0x15B0 +-#define REG_RSS_HASH_FLAG 0x15B4 +-#define REG_BASE_CPU_NUMBER 0x15B8 + + /* TXQ Control Register */ +-#define REG_TXQ_CTRL 0x1590 +-#define TXQ_NUM_TPD_BURST_MASK 0xF +-#define TXQ_NUM_TPD_BURST_SHIFT 0 +-#define TXQ_CTRL_IP_OPTION_EN 0x10 +-#define TXQ_CTRL_EN 0x20 +-#define TXQ_CTRL_ENH_MODE 0x40 +-#define TXQ_CTRL_LS_8023_EN 0x80 +-#define TXQ_TXF_BURST_NUM_SHIFT 16 +-#define TXQ_TXF_BURST_NUM_MASK 0xFFFF ++#define REG_TXQ_CTRL 0x1590 ++#define TXQ_TXF_BURST_NUM_MASK 0xFFFFUL ++#define TXQ_TXF_BURST_NUM_SHIFT 16 ++#define L1C_TXQ_TXF_BURST_PREF 0x200 ++#define L2CB_TXQ_TXF_BURST_PREF 0x40 ++#define TXQ_CTRL_PEDING_CLR BIT(8) ++#define TXQ_CTRL_LS_8023_EN BIT(7) ++#define TXQ_CTRL_ENH_MODE BIT(6) ++#define TXQ_CTRL_EN BIT(5) ++#define TXQ_CTRL_IP_OPTION_EN BIT(4) ++#define TXQ_NUM_TPD_BURST_MASK 0xFUL ++#define TXQ_NUM_TPD_BURST_SHIFT 0 ++#define TXQ_NUM_TPD_BURST_DEF 5 ++#define TXQ_CFGV (\ ++ FIELDX(TXQ_NUM_TPD_BURST, TXQ_NUM_TPD_BURST_DEF) |\ ++ TXQ_CTRL_ENH_MODE |\ ++ TXQ_CTRL_LS_8023_EN |\ ++ TXQ_CTRL_IP_OPTION_EN) ++#define L1C_TXQ_CFGV (\ ++ TXQ_CFGV |\ ++ FIELDX(TXQ_TXF_BURST_NUM, L1C_TXQ_TXF_BURST_PREF)) ++#define L2CB_TXQ_CFGV (\ ++ TXQ_CFGV |\ ++ FIELDX(TXQ_TXF_BURST_NUM, L2CB_TXQ_TXF_BURST_PREF)) ++ + + /* Jumbo packet Threshold for task offload */ + #define REG_TX_TSO_OFFLOAD_THRESH 0x1594 /* In 8-bytes */ + #define TX_TSO_OFFLOAD_THRESH_MASK 0x07FF ++#define MAX_TSO_FRAME_SIZE (7*1024) + + #define REG_TXF_WATER_MARK 0x1598 /* In 8-bytes */ + #define TXF_WATER_MARK_MASK 0x0FFF +@@ -537,26 +597,21 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define ASPM_THRUPUT_LIMIT_NO 0x00 + #define ASPM_THRUPUT_LIMIT_1M 0x01 + #define ASPM_THRUPUT_LIMIT_10M 0x02 +-#define ASPM_THRUPUT_LIMIT_100M 0x04 +-#define RXQ1_CTRL_EN 0x10 +-#define RXQ2_CTRL_EN 0x20 +-#define RXQ3_CTRL_EN 0x40 +-#define IPV6_CHKSUM_CTRL_EN 0x80 +-#define RSS_HASH_BITS_MASK 0x00FF +-#define RSS_HASH_BITS_SHIFT 8 +-#define RSS_HASH_IPV4 0x10000 +-#define RSS_HASH_IPV4_TCP 0x20000 +-#define RSS_HASH_IPV6 0x40000 +-#define RSS_HASH_IPV6_TCP 0x80000 ++#define ASPM_THRUPUT_LIMIT_100M 0x03 ++#define IPV6_CHKSUM_CTRL_EN BIT(7) + #define RXQ_RFD_BURST_NUM_MASK 0x003F + #define RXQ_RFD_BURST_NUM_SHIFT 20 +-#define RSS_MODE_MASK 0x0003 ++#define RXQ_NUM_RFD_PREF_DEF 8 ++#define RSS_MODE_MASK 3UL + #define RSS_MODE_SHIFT 26 +-#define RSS_NIP_QUEUE_SEL_MASK 0x1 +-#define RSS_NIP_QUEUE_SEL_SHIFT 28 +-#define RRS_HASH_CTRL_EN 0x20000000 +-#define RX_CUT_THRU_EN 0x40000000 +-#define RXQ_CTRL_EN 0x80000000 ++#define RSS_MODE_DIS 0 ++#define RSS_MODE_SQSI 1 ++#define RSS_MODE_MQSI 2 ++#define RSS_MODE_MQMI 3 ++#define RSS_NIP_QUEUE_SEL BIT(28) /* 0:q0, 1:table */ ++#define RRS_HASH_CTRL_EN BIT(29) ++#define RX_CUT_THRU_EN BIT(30) ++#define RXQ_CTRL_EN BIT(31) + + #define REG_RFD_FREE_THRESH 0x15A4 + #define RFD_FREE_THRESH_MASK 0x003F +@@ -577,57 +632,45 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define RXD_DMA_DOWN_TIMER_SHIFT 16 + + /* DMA Engine Control Register */ +-#define REG_DMA_CTRL 0x15C0 +-#define DMA_CTRL_DMAR_IN_ORDER 0x1 +-#define DMA_CTRL_DMAR_ENH_ORDER 0x2 +-#define DMA_CTRL_DMAR_OUT_ORDER 0x4 +-#define DMA_CTRL_RCB_VALUE 0x8 +-#define DMA_CTRL_DMAR_BURST_LEN_MASK 0x0007 +-#define DMA_CTRL_DMAR_BURST_LEN_SHIFT 4 +-#define DMA_CTRL_DMAW_BURST_LEN_MASK 0x0007 +-#define DMA_CTRL_DMAW_BURST_LEN_SHIFT 7 +-#define DMA_CTRL_DMAR_REQ_PRI 0x400 +-#define DMA_CTRL_DMAR_DLY_CNT_MASK 0x001F +-#define DMA_CTRL_DMAR_DLY_CNT_SHIFT 11 +-#define DMA_CTRL_DMAW_DLY_CNT_MASK 0x000F +-#define DMA_CTRL_DMAW_DLY_CNT_SHIFT 16 +-#define DMA_CTRL_CMB_EN 0x100000 +-#define DMA_CTRL_SMB_EN 0x200000 +-#define DMA_CTRL_CMB_NOW 0x400000 +-#define MAC_CTRL_SMB_DIS 0x1000000 +-#define DMA_CTRL_SMB_NOW 0x80000000 +- +-/* CMB/SMB Control Register */ ++#define REG_DMA_CTRL 0x15C0 ++#define DMA_CTRL_SMB_NOW BIT(31) ++#define DMA_CTRL_WPEND_CLR BIT(30) ++#define DMA_CTRL_RPEND_CLR BIT(29) ++#define DMA_CTRL_WDLY_CNT_MASK 0xFUL ++#define DMA_CTRL_WDLY_CNT_SHIFT 16 ++#define DMA_CTRL_WDLY_CNT_DEF 4 ++#define DMA_CTRL_RDLY_CNT_MASK 0x1FUL ++#define DMA_CTRL_RDLY_CNT_SHIFT 11 ++#define DMA_CTRL_RDLY_CNT_DEF 15 ++#define DMA_CTRL_RREQ_PRI_DATA BIT(10) /* 0:tpd, 1:data */ ++#define DMA_CTRL_WREQ_BLEN_MASK 7UL ++#define DMA_CTRL_WREQ_BLEN_SHIFT 7 ++#define DMA_CTRL_RREQ_BLEN_MASK 7UL ++#define DMA_CTRL_RREQ_BLEN_SHIFT 4 ++#define L1C_CTRL_DMA_RCB_LEN128 BIT(3) /* 0:64bytes,1:128bytes */ ++#define DMA_CTRL_RORDER_MODE_MASK 7UL ++#define DMA_CTRL_RORDER_MODE_SHIFT 0 ++#define DMA_CTRL_RORDER_MODE_OUT 4 ++#define DMA_CTRL_RORDER_MODE_ENHANCE 2 ++#define DMA_CTRL_RORDER_MODE_IN 1 ++ ++/* INT-triggle/SMB Control Register */ + #define REG_SMB_STAT_TIMER 0x15C4 /* 2us resolution */ + #define SMB_STAT_TIMER_MASK 0xFFFFFF +-#define REG_CMB_TPD_THRESH 0x15C8 +-#define CMB_TPD_THRESH_MASK 0xFFFF +-#define REG_CMB_TX_TIMER 0x15CC /* 2us resolution */ +-#define CMB_TX_TIMER_MASK 0xFFFF ++#define REG_TINT_TPD_THRESH 0x15C8 /* tpd th to trig intrrupt */ + + /* Mail box */ + #define MB_RFDX_PROD_IDX_MASK 0xFFFF + #define REG_MB_RFD0_PROD_IDX 0x15E0 +-#define REG_MB_RFD1_PROD_IDX 0x15E4 +-#define REG_MB_RFD2_PROD_IDX 0x15E8 +-#define REG_MB_RFD3_PROD_IDX 0x15EC + +-#define MB_PRIO_PROD_IDX_MASK 0xFFFF +-#define REG_MB_PRIO_PROD_IDX 0x15F0 +-#define MB_HTPD_PROD_IDX_SHIFT 0 +-#define MB_NTPD_PROD_IDX_SHIFT 16 +- +-#define MB_PRIO_CONS_IDX_MASK 0xFFFF +-#define REG_MB_PRIO_CONS_IDX 0x15F4 +-#define MB_HTPD_CONS_IDX_SHIFT 0 +-#define MB_NTPD_CONS_IDX_SHIFT 16 ++#define REG_TPD_PRI1_PIDX 0x15F0 /* 16bit,hi-tpd producer idx */ ++#define REG_TPD_PRI0_PIDX 0x15F2 /* 16bit,lo-tpd producer idx */ ++#define REG_TPD_PRI1_CIDX 0x15F4 /* 16bit,hi-tpd consumer idx */ ++#define REG_TPD_PRI0_CIDX 0x15F6 /* 16bit,lo-tpd consumer idx */ + + #define REG_MB_RFD01_CONS_IDX 0x15F8 + #define MB_RFD0_CONS_IDX_MASK 0x0000FFFF + #define MB_RFD1_CONS_IDX_MASK 0xFFFF0000 +-#define REG_MB_RFD23_CONS_IDX 0x15FC +-#define MB_RFD2_CONS_IDX_MASK 0x0000FFFF +-#define MB_RFD3_CONS_IDX_MASK 0xFFFF0000 + + /* Interrupt Status Register */ + #define REG_ISR 0x1600 +@@ -705,13 +748,6 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define REG_INT_RETRIG_TIMER 0x1608 + #define INT_RETRIG_TIMER_MASK 0xFFFF + +-#define REG_HDS_CTRL 0x160C +-#define HDS_CTRL_EN 0x0001 +-#define HDS_CTRL_BACKFILLSIZE_SHIFT 8 +-#define HDS_CTRL_BACKFILLSIZE_MASK 0x0FFF +-#define HDS_CTRL_MAX_HDRSIZE_SHIFT 20 +-#define HDS_CTRL_MAC_HDRSIZE_MASK 0x0FFF +- + #define REG_MAC_RX_STATUS_BIN 0x1700 + #define REG_MAC_RX_STATUS_END 0x175c + #define REG_MAC_TX_STATUS_BIN 0x1760 +@@ -796,73 +832,188 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); + #define MII_DBG_ADDR 0x1D + #define MII_DBG_DATA 0x1E + +-#define MII_ANA_CTRL_0 0x0 +-#define ANA_RESTART_CAL 0x0001 +-#define ANA_MANUL_SWICH_ON_SHIFT 0x1 +-#define ANA_MANUL_SWICH_ON_MASK 0xF +-#define ANA_MAN_ENABLE 0x0020 +-#define ANA_SEL_HSP 0x0040 +-#define ANA_EN_HB 0x0080 +-#define ANA_EN_HBIAS 0x0100 +-#define ANA_OEN_125M 0x0200 +-#define ANA_EN_LCKDT 0x0400 +-#define ANA_LCKDT_PHY 0x0800 +-#define ANA_AFE_MODE 0x1000 +-#define ANA_VCO_SLOW 0x2000 +-#define ANA_VCO_FAST 0x4000 +-#define ANA_SEL_CLK125M_DSP 0x8000 +- +-#define MII_ANA_CTRL_4 0x4 +-#define ANA_IECHO_ADJ_MASK 0xF +-#define ANA_IECHO_ADJ_3_SHIFT 0 +-#define ANA_IECHO_ADJ_2_SHIFT 4 +-#define ANA_IECHO_ADJ_1_SHIFT 8 +-#define ANA_IECHO_ADJ_0_SHIFT 12 +- +-#define MII_ANA_CTRL_5 0x5 +-#define ANA_SERDES_CDR_BW_SHIFT 0 +-#define ANA_SERDES_CDR_BW_MASK 0x3 +-#define ANA_MS_PAD_DBG 0x0004 +-#define ANA_SPEEDUP_DBG 0x0008 +-#define ANA_SERDES_TH_LOS_SHIFT 4 +-#define ANA_SERDES_TH_LOS_MASK 0x3 +-#define ANA_SERDES_EN_DEEM 0x0040 +-#define ANA_SERDES_TXELECIDLE 0x0080 +-#define ANA_SERDES_BEACON 0x0100 +-#define ANA_SERDES_HALFTXDR 0x0200 +-#define ANA_SERDES_SEL_HSP 0x0400 +-#define ANA_SERDES_EN_PLL 0x0800 +-#define ANA_SERDES_EN 0x1000 +-#define ANA_SERDES_EN_LCKDT 0x2000 +- +-#define MII_ANA_CTRL_11 0xB +-#define ANA_PS_HIB_EN 0x8000 +- +-#define MII_ANA_CTRL_18 0x12 +-#define ANA_TEST_MODE_10BT_01SHIFT 0 +-#define ANA_TEST_MODE_10BT_01MASK 0x3 +-#define ANA_LOOP_SEL_10BT 0x0004 +-#define ANA_RGMII_MODE_SW 0x0008 +-#define ANA_EN_LONGECABLE 0x0010 +-#define ANA_TEST_MODE_10BT_2 0x0020 +-#define ANA_EN_10BT_IDLE 0x0400 +-#define ANA_EN_MASK_TB 0x0800 +-#define ANA_TRIGGER_SEL_TIMER_SHIFT 12 +-#define ANA_TRIGGER_SEL_TIMER_MASK 0x3 +-#define ANA_INTERVAL_SEL_TIMER_SHIFT 14 +-#define ANA_INTERVAL_SEL_TIMER_MASK 0x3 +- +-#define MII_ANA_CTRL_41 0x29 +-#define ANA_TOP_PS_EN 0x8000 +- +-#define MII_ANA_CTRL_54 0x36 +-#define ANA_LONG_CABLE_TH_100_SHIFT 0 +-#define ANA_LONG_CABLE_TH_100_MASK 0x3F +-#define ANA_DESERVED 0x0040 +-#define ANA_EN_LIT_CH 0x0080 +-#define ANA_SHORT_CABLE_TH_100_SHIFT 8 +-#define ANA_SHORT_CABLE_TH_100_MASK 0x3F +-#define ANA_BP_BAD_LINK_ACCUM 0x4000 +-#define ANA_BP_SMALL_BW 0x8000 ++/***************************** debug port *************************************/ ++ ++#define MIIDBG_ANACTRL 0x00 ++#define ANACTRL_CLK125M_DELAY_EN 0x8000 ++#define ANACTRL_VCO_FAST 0x4000 ++#define ANACTRL_VCO_SLOW 0x2000 ++#define ANACTRL_AFE_MODE_EN 0x1000 ++#define ANACTRL_LCKDET_PHY 0x800 ++#define ANACTRL_LCKDET_EN 0x400 ++#define ANACTRL_OEN_125M 0x200 ++#define ANACTRL_HBIAS_EN 0x100 ++#define ANACTRL_HB_EN 0x80 ++#define ANACTRL_SEL_HSP 0x40 ++#define ANACTRL_CLASSA_EN 0x20 ++#define ANACTRL_MANUSWON_SWR_MASK 3U ++#define ANACTRL_MANUSWON_SWR_SHIFT 2 ++#define ANACTRL_MANUSWON_SWR_2V 0 ++#define ANACTRL_MANUSWON_SWR_1P9V 1 ++#define ANACTRL_MANUSWON_SWR_1P8V 2 ++#define ANACTRL_MANUSWON_SWR_1P7V 3 ++#define ANACTRL_MANUSWON_BW3_4M 0x2 ++#define ANACTRL_RESTART_CAL 0x1 ++#define ANACTRL_DEF 0x02EF ++ ++#define MIIDBG_SYSMODCTRL 0x04 ++#define SYSMODCTRL_IECHOADJ_PFMH_PHY 0x8000 ++#define SYSMODCTRL_IECHOADJ_BIASGEN 0x4000 ++#define SYSMODCTRL_IECHOADJ_PFML_PHY 0x2000 ++#define SYSMODCTRL_IECHOADJ_PS_MASK 3U ++#define SYSMODCTRL_IECHOADJ_PS_SHIFT 10 ++#define SYSMODCTRL_IECHOADJ_PS_40 3 ++#define SYSMODCTRL_IECHOADJ_PS_20 2 ++#define SYSMODCTRL_IECHOADJ_PS_0 1 ++#define SYSMODCTRL_IECHOADJ_10BT_100MV 0x40 /* 1:100mv, 0:200mv */ ++#define SYSMODCTRL_IECHOADJ_HLFAP_MASK 3U ++#define SYSMODCTRL_IECHOADJ_HLFAP_SHIFT 4 ++#define SYSMODCTRL_IECHOADJ_VDFULBW 0x8 ++#define SYSMODCTRL_IECHOADJ_VDBIASHLF 0x4 ++#define SYSMODCTRL_IECHOADJ_VDAMPHLF 0x2 ++#define SYSMODCTRL_IECHOADJ_VDLANSW 0x1 ++#define SYSMODCTRL_IECHOADJ_DEF 0x88BB /* ???? */ ++ ++/* for l1d & l2cb */ ++#define SYSMODCTRL_IECHOADJ_CUR_ADD 0x8000 ++#define SYSMODCTRL_IECHOADJ_CUR_MASK 7U ++#define SYSMODCTRL_IECHOADJ_CUR_SHIFT 12 ++#define SYSMODCTRL_IECHOADJ_VOL_MASK 0xFU ++#define SYSMODCTRL_IECHOADJ_VOL_SHIFT 8 ++#define SYSMODCTRL_IECHOADJ_VOL_17ALL 3 ++#define SYSMODCTRL_IECHOADJ_VOL_100M15 1 ++#define SYSMODCTRL_IECHOADJ_VOL_10M17 0 ++#define SYSMODCTRL_IECHOADJ_BIAS1_MASK 0xFU ++#define SYSMODCTRL_IECHOADJ_BIAS1_SHIFT 4 ++#define SYSMODCTRL_IECHOADJ_BIAS2_MASK 0xFU ++#define SYSMODCTRL_IECHOADJ_BIAS2_SHIFT 0 ++#define L1D_SYSMODCTRL_IECHOADJ_DEF 0x4FBB ++ ++#define MIIDBG_SRDSYSMOD 0x05 ++#define SRDSYSMOD_LCKDET_EN 0x2000 ++#define SRDSYSMOD_PLL_EN 0x800 ++#define SRDSYSMOD_SEL_HSP 0x400 ++#define SRDSYSMOD_HLFTXDR 0x200 ++#define SRDSYSMOD_TXCLK_DELAY_EN 0x100 ++#define SRDSYSMOD_TXELECIDLE 0x80 ++#define SRDSYSMOD_DEEMP_EN 0x40 ++#define SRDSYSMOD_MS_PAD 0x4 ++#define SRDSYSMOD_CDR_ADC_VLTG 0x2 ++#define SRDSYSMOD_CDR_DAC_1MA 0x1 ++#define SRDSYSMOD_DEF 0x2C46 ++ ++#define MIIDBG_CFGLPSPD 0x0A ++#define CFGLPSPD_RSTCNT_MASK 3U ++#define CFGLPSPD_RSTCNT_SHIFT 14 ++#define CFGLPSPD_RSTCNT_CLK125SW 0x2000 ++ ++#define MIIDBG_HIBNEG 0x0B ++#define HIBNEG_PSHIB_EN 0x8000 ++#define HIBNEG_WAKE_BOTH 0x4000 ++#define HIBNEG_ONOFF_ANACHG_SUDEN 0x2000 ++#define HIBNEG_HIB_PULSE 0x1000 ++#define HIBNEG_GATE_25M_EN 0x800 ++#define HIBNEG_RST_80U 0x400 ++#define HIBNEG_RST_TIMER_MASK 3U ++#define HIBNEG_RST_TIMER_SHIFT 8 ++#define HIBNEG_GTX_CLK_DELAY_MASK 3U ++#define HIBNEG_GTX_CLK_DELAY_SHIFT 5 ++#define HIBNEG_BYPSS_BRKTIMER 0x10 ++#define HIBNEG_DEF 0xBC40 ++ ++#define MIIDBG_TST10BTCFG 0x12 ++#define TST10BTCFG_INTV_TIMER_MASK 3U ++#define TST10BTCFG_INTV_TIMER_SHIFT 14 ++#define TST10BTCFG_TRIGER_TIMER_MASK 3U ++#define TST10BTCFG_TRIGER_TIMER_SHIFT 12 ++#define TST10BTCFG_DIV_MAN_MLT3_EN 0x800 ++#define TST10BTCFG_OFF_DAC_IDLE 0x400 ++#define TST10BTCFG_LPBK_DEEP 0x4 /* 1:deep,0:shallow */ ++#define TST10BTCFG_DEF 0x4C04 ++ ++#define MIIDBG_AZ_ANADECT 0x15 ++#define AZ_ANADECT_10BTRX_TH 0x8000 ++#define AZ_ANADECT_BOTH_01CHNL 0x4000 ++#define AZ_ANADECT_INTV_MASK 0x3FU ++#define AZ_ANADECT_INTV_SHIFT 8 ++#define AZ_ANADECT_THRESH_MASK 0xFU ++#define AZ_ANADECT_THRESH_SHIFT 4 ++#define AZ_ANADECT_CHNL_MASK 0xFU ++#define AZ_ANADECT_CHNL_SHIFT 0 ++#define AZ_ANADECT_DEF 0x3220 ++#define AZ_ANADECT_LONG 0xb210 ++ ++#define MIIDBG_MSE16DB 0x18 /* l1d */ ++#define L1D_MSE16DB_UP 0x05EA ++#define L1D_MSE16DB_DOWN 0x02EA ++ ++#define MIIDBG_LEGCYPS 0x29 ++#define LEGCYPS_EN 0x8000 ++#define LEGCYPS_DAC_AMP1000_MASK 7U ++#define LEGCYPS_DAC_AMP1000_SHIFT 12 ++#define LEGCYPS_DAC_AMP100_MASK 7U ++#define LEGCYPS_DAC_AMP100_SHIFT 9 ++#define LEGCYPS_DAC_AMP10_MASK 7U ++#define LEGCYPS_DAC_AMP10_SHIFT 6 ++#define LEGCYPS_UNPLUG_TIMER_MASK 7U ++#define LEGCYPS_UNPLUG_TIMER_SHIFT 3 ++#define LEGCYPS_UNPLUG_DECT_EN 0x4 ++#define LEGCYPS_ECNC_PS_EN 0x1 ++#define L1D_LEGCYPS_DEF 0x129D ++#define L1C_LEGCYPS_DEF 0x36DD ++ ++#define MIIDBG_TST100BTCFG 0x36 ++#define TST100BTCFG_NORMAL_BW_EN 0x8000 ++#define TST100BTCFG_BADLNK_BYPASS 0x4000 ++#define TST100BTCFG_SHORTCABL_TH_MASK 0x3FU ++#define TST100BTCFG_SHORTCABL_TH_SHIFT 8 ++#define TST100BTCFG_LITCH_EN 0x80 ++#define TST100BTCFG_VLT_SW 0x40 ++#define TST100BTCFG_LONGCABL_TH_MASK 0x3FU ++#define TST100BTCFG_LONGCABL_TH_SHIFT 0 ++#define TST100BTCFG_DEF 0xE12C ++ ++#define MIIDBG_VOLT_CTRL 0x3B /* only for l2cb 1 & 2 */ ++#define VOLT_CTRL_CABLE1TH_MASK 0x1FFU ++#define VOLT_CTRL_CABLE1TH_SHIFT 7 ++#define VOLT_CTRL_AMPCTRL_MASK 3U ++#define VOLT_CTRL_AMPCTRL_SHIFT 5 ++#define VOLT_CTRL_SW_BYPASS 0x10 ++#define VOLT_CTRL_SWLOWEST 0x8 ++#define VOLT_CTRL_DACAMP10_MASK 7U ++#define VOLT_CTRL_DACAMP10_SHIFT 0 ++ ++#define MIIDBG_CABLE1TH_DET 0x3E ++#define CABLE1TH_DET_EN 0x8000 ++ ++ ++/******* dev 3 *********/ ++#define MIIEXT_PCS 3 ++ ++#define MIIEXT_CLDCTRL3 0x8003 ++#define CLDCTRL3_BP_CABLE1TH_DET_GT 0x8000 ++#define CLDCTRL3_AZ_DISAMP 0x1000 ++#define L2CB_CLDCTRL3 0x4D19 ++#define L1D_CLDCTRL3 0xDD19 ++ ++#define MIIEXT_CLDCTRL6 0x8006 ++#define CLDCTRL6_CAB_LEN_MASK 0x1FFU ++#define CLDCTRL6_CAB_LEN_SHIFT 0 ++#define CLDCTRL6_CAB_LEN_SHORT 0x50 ++ ++/********* dev 7 **********/ ++#define MIIEXT_ANEG 7 ++ ++#define MIIEXT_LOCAL_EEEADV 0x3C ++#define LOCAL_EEEADV_1000BT 0x4 ++#define LOCAL_EEEADV_100BT 0x2 ++ ++#define MIIEXT_REMOTE_EEEADV 0x3D ++#define REMOTE_EEEADV_1000BT 0x4 ++#define REMOTE_EEEADV_100BT 0x2 ++ ++#define MIIEXT_EEE_ANEG 0x8000 ++#define EEE_ANEG_1000M 0x4 ++#define EEE_ANEG_100M 0x2 + + #endif /*_ATL1C_HW_H_*/ +diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +index 47a9bb2..f6f3fe3 100644 +--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c ++++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +@@ -24,14 +24,6 @@ + #define ATL1C_DRV_VERSION "1.0.1.0-NAPI" + char atl1c_driver_name[] = "atl1c"; + char atl1c_driver_version[] = ATL1C_DRV_VERSION; +-#define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062 +-#define PCI_DEVICE_ID_ATTANSIC_L1C 0x1063 +-#define PCI_DEVICE_ID_ATHEROS_L2C_B 0x2060 /* AR8152 v1.1 Fast 10/100 */ +-#define PCI_DEVICE_ID_ATHEROS_L2C_B2 0x2062 /* AR8152 v2.0 Fast 10/100 */ +-#define PCI_DEVICE_ID_ATHEROS_L1D 0x1073 /* AR8151 v1.0 Gigabit 1000 */ +-#define PCI_DEVICE_ID_ATHEROS_L1D_2_0 0x1083 /* AR8151 v2.0 Gigabit 1000 */ +-#define L2CB_V10 0xc0 +-#define L2CB_V11 0xc1 + + /* + * atl1c_pci_tbl - PCI Device ID Table +@@ -54,70 +46,72 @@ static DEFINE_PCI_DEVICE_TABLE(atl1c_pci_tbl) = { + }; + MODULE_DEVICE_TABLE(pci, atl1c_pci_tbl); + +-MODULE_AUTHOR("Jie Yang "); +-MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver"); ++MODULE_AUTHOR("Jie Yang"); ++MODULE_AUTHOR("Qualcomm Atheros Inc., "); ++MODULE_DESCRIPTION("Qualcom Atheros 100/1000M Ethernet Network Driver"); + MODULE_LICENSE("GPL"); + MODULE_VERSION(ATL1C_DRV_VERSION); + + static int atl1c_stop_mac(struct atl1c_hw *hw); +-static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw); +-static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw); + static void atl1c_disable_l0s_l1(struct atl1c_hw *hw); +-static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup); +-static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter); +-static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que, ++static void atl1c_set_aspm(struct atl1c_hw *hw, u16 link_speed); ++static void atl1c_start_mac(struct atl1c_adapter *adapter); ++static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, + int *work_done, int work_to_do); + static int atl1c_up(struct atl1c_adapter *adapter); + static void atl1c_down(struct atl1c_adapter *adapter); ++static int atl1c_reset_mac(struct atl1c_hw *hw); ++static void atl1c_reset_dma_ring(struct atl1c_adapter *adapter); ++static int atl1c_configure(struct atl1c_adapter *adapter); ++static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter); + + static const u16 atl1c_pay_load_size[] = { + 128, 256, 512, 1024, 2048, 4096, + }; + +-static const u16 atl1c_rfd_prod_idx_regs[AT_MAX_RECEIVE_QUEUE] = +-{ +- REG_MB_RFD0_PROD_IDX, +- REG_MB_RFD1_PROD_IDX, +- REG_MB_RFD2_PROD_IDX, +- REG_MB_RFD3_PROD_IDX +-}; +- +-static const u16 atl1c_rfd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] = +-{ +- REG_RFD0_HEAD_ADDR_LO, +- REG_RFD1_HEAD_ADDR_LO, +- REG_RFD2_HEAD_ADDR_LO, +- REG_RFD3_HEAD_ADDR_LO +-}; +- +-static const u16 atl1c_rrd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] = +-{ +- REG_RRD0_HEAD_ADDR_LO, +- REG_RRD1_HEAD_ADDR_LO, +- REG_RRD2_HEAD_ADDR_LO, +- REG_RRD3_HEAD_ADDR_LO +-}; + + static const u32 atl1c_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | + NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP; + static void atl1c_pcie_patch(struct atl1c_hw *hw) + { +- u32 data; ++ u32 mst_data, data; + +- AT_READ_REG(hw, REG_PCIE_PHYMISC, &data); +- data |= PCIE_PHYMISC_FORCE_RCV_DET; +- AT_WRITE_REG(hw, REG_PCIE_PHYMISC, data); ++ /* pclk sel could switch to 25M */ ++ AT_READ_REG(hw, REG_MASTER_CTRL, &mst_data); ++ mst_data &= ~MASTER_CTRL_CLK_SEL_DIS; ++ AT_WRITE_REG(hw, REG_MASTER_CTRL, mst_data); + ++ /* WoL/PCIE related settings */ ++ if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) { ++ AT_READ_REG(hw, REG_PCIE_PHYMISC, &data); ++ data |= PCIE_PHYMISC_FORCE_RCV_DET; ++ AT_WRITE_REG(hw, REG_PCIE_PHYMISC, data); ++ } else { /* new dev set bit5 of MASTER */ ++ if (!(mst_data & MASTER_CTRL_WAKEN_25M)) ++ AT_WRITE_REG(hw, REG_MASTER_CTRL, ++ mst_data | MASTER_CTRL_WAKEN_25M); ++ } ++ /* aspm/PCIE setting only for l2cb 1.0 */ + if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) { + AT_READ_REG(hw, REG_PCIE_PHYMISC2, &data); +- +- data &= ~(PCIE_PHYMISC2_SERDES_CDR_MASK << +- PCIE_PHYMISC2_SERDES_CDR_SHIFT); +- data |= 3 << PCIE_PHYMISC2_SERDES_CDR_SHIFT; +- data &= ~(PCIE_PHYMISC2_SERDES_TH_MASK << +- PCIE_PHYMISC2_SERDES_TH_SHIFT); +- data |= 3 << PCIE_PHYMISC2_SERDES_TH_SHIFT; ++ data = FIELD_SETX(data, PCIE_PHYMISC2_CDR_BW, ++ L2CB1_PCIE_PHYMISC2_CDR_BW); ++ data = FIELD_SETX(data, PCIE_PHYMISC2_L0S_TH, ++ L2CB1_PCIE_PHYMISC2_L0S_TH); + AT_WRITE_REG(hw, REG_PCIE_PHYMISC2, data); ++ /* extend L1 sync timer */ ++ AT_READ_REG(hw, REG_LINK_CTRL, &data); ++ data |= LINK_CTRL_EXT_SYNC; ++ AT_WRITE_REG(hw, REG_LINK_CTRL, data); ++ } ++ /* l2cb 1.x & l1d 1.x */ ++ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d) { ++ AT_READ_REG(hw, REG_PM_CTRL, &data); ++ data |= PM_CTRL_L0S_BUFSRX_EN; ++ AT_WRITE_REG(hw, REG_PM_CTRL, data); ++ /* clear vendor msg */ ++ AT_READ_REG(hw, REG_DMA_DBG, &data); ++ AT_WRITE_REG(hw, REG_DMA_DBG, data & ~DMA_DBG_VENDOR_MSG); + } + } + +@@ -130,6 +124,7 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag) + u32 data; + u32 pci_cmd; + struct pci_dev *pdev = hw->adapter->pdev; ++ int pos; + + AT_READ_REG(hw, PCI_COMMAND, &pci_cmd); + pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; +@@ -142,14 +137,23 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag) + */ + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); ++ /* wol sts read-clear */ ++ AT_READ_REG(hw, REG_WOL_CTRL, &data); ++ AT_WRITE_REG(hw, REG_WOL_CTRL, 0); + + /* + * Mask some pcie error bits + */ +- AT_READ_REG(hw, REG_PCIE_UC_SEVERITY, &data); +- data &= ~PCIE_UC_SERVRITY_DLP; +- data &= ~PCIE_UC_SERVRITY_FCP; +- AT_WRITE_REG(hw, REG_PCIE_UC_SEVERITY, data); ++ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); ++ pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data); ++ data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP); ++ pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data); ++ /* clear error status */ ++ pci_write_config_word(pdev, pci_pcie_cap(pdev) + PCI_EXP_DEVSTA, ++ PCI_EXP_DEVSTA_NFED | ++ PCI_EXP_DEVSTA_FED | ++ PCI_EXP_DEVSTA_CED | ++ PCI_EXP_DEVSTA_URD); + + AT_READ_REG(hw, REG_LTSSM_ID_CTRL, &data); + data &= ~LTSSM_ID_EN_WRO; +@@ -158,11 +162,6 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag) + atl1c_pcie_patch(hw); + if (flag & ATL1C_PCIE_L0S_L1_DISABLE) + atl1c_disable_l0s_l1(hw); +- if (flag & ATL1C_PCIE_PHY_RESET) +- AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT); +- else +- AT_WRITE_REG(hw, REG_GPHY_CTRL, +- GPHY_CTRL_DEFAULT | GPHY_CTRL_EXT_RESET); + + msleep(5); + } +@@ -207,14 +206,14 @@ static inline void atl1c_irq_reset(struct atl1c_adapter *adapter) + * atl1c_wait_until_idle - wait up to AT_HW_MAX_IDLE_DELAY reads + * of the idle status register until the device is actually idle + */ +-static u32 atl1c_wait_until_idle(struct atl1c_hw *hw) ++static u32 atl1c_wait_until_idle(struct atl1c_hw *hw, u32 modu_ctrl) + { + int timeout; + u32 data; + + for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) { + AT_READ_REG(hw, REG_IDLE_STATUS, &data); +- if ((data & IDLE_STATUS_MASK) == 0) ++ if ((data & modu_ctrl) == 0) + return 0; + msleep(1); + } +@@ -261,15 +260,16 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) + + if ((phy_data & BMSR_LSTATUS) == 0) { + /* link down */ +- hw->hibernate = true; +- if (atl1c_stop_mac(hw) != 0) +- if (netif_msg_hw(adapter)) +- dev_warn(&pdev->dev, "stop mac failed\n"); +- atl1c_set_aspm(hw, false); + netif_carrier_off(netdev); + netif_stop_queue(netdev); +- atl1c_phy_reset(hw); +- atl1c_phy_init(&adapter->hw); ++ hw->hibernate = true; ++ if (atl1c_reset_mac(hw) != 0) ++ if (netif_msg_hw(adapter)) ++ dev_warn(&pdev->dev, "reset mac failed\n"); ++ atl1c_set_aspm(hw, SPEED_0); ++ atl1c_post_phy_linkchg(hw, SPEED_0); ++ atl1c_reset_dma_ring(adapter); ++ atl1c_configure(adapter); + } else { + /* Link Up */ + hw->hibernate = false; +@@ -283,10 +283,9 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) + adapter->link_duplex != duplex) { + adapter->link_speed = speed; + adapter->link_duplex = duplex; +- atl1c_set_aspm(hw, true); +- atl1c_enable_tx_ctrl(hw); +- atl1c_enable_rx_ctrl(hw); +- atl1c_setup_mac_ctrl(adapter); ++ atl1c_set_aspm(hw, speed); ++ atl1c_post_phy_linkchg(hw, speed); ++ atl1c_start_mac(adapter); + if (netif_msg_link(adapter)) + dev_info(&pdev->dev, + "%s: %s NIC Link is Up<%d Mbps %s>\n", +@@ -337,6 +336,9 @@ static void atl1c_common_task(struct work_struct *work) + adapter = container_of(work, struct atl1c_adapter, common_task); + netdev = adapter->netdev; + ++ if (test_bit(__AT_DOWN, &adapter->flags)) ++ return; ++ + if (test_and_clear_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event)) { + netif_device_detach(netdev); + atl1c_down(adapter); +@@ -345,8 +347,11 @@ static void atl1c_common_task(struct work_struct *work) + } + + if (test_and_clear_bit(ATL1C_WORK_EVENT_LINK_CHANGE, +- &adapter->work_event)) ++ &adapter->work_event)) { ++ atl1c_irq_disable(adapter); + atl1c_check_link_status(adapter); ++ atl1c_irq_enable(adapter); ++ } + } + + +@@ -469,7 +474,7 @@ static int atl1c_set_mac_addr(struct net_device *netdev, void *p) + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); + +- atl1c_hw_set_mac_addr(&adapter->hw); ++ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr); + + return 0; + } +@@ -522,11 +527,16 @@ static int atl1c_set_features(struct net_device *netdev, + static int atl1c_change_mtu(struct net_device *netdev, int new_mtu) + { + struct atl1c_adapter *adapter = netdev_priv(netdev); ++ struct atl1c_hw *hw = &adapter->hw; + int old_mtu = netdev->mtu; + int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; + +- if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || +- (max_frame > MAX_JUMBO_FRAME_SIZE)) { ++ /* Fast Ethernet controller doesn't support jumbo packet */ ++ if (((hw->nic_type == athr_l2c || ++ hw->nic_type == athr_l2c_b || ++ hw->nic_type == athr_l2c_b2) && new_mtu > ETH_DATA_LEN) || ++ max_frame < ETH_ZLEN + ETH_FCS_LEN || ++ max_frame > MAX_JUMBO_FRAME_SIZE) { + if (netif_msg_link(adapter)) + dev_warn(&adapter->pdev->dev, "invalid MTU setting\n"); + return -EINVAL; +@@ -542,14 +552,6 @@ static int atl1c_change_mtu(struct net_device *netdev, int new_mtu) + netdev_update_features(netdev); + atl1c_up(adapter); + clear_bit(__AT_RESETTING, &adapter->flags); +- if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) { +- u32 phy_data; +- +- AT_READ_REG(&adapter->hw, 0x1414, &phy_data); +- phy_data |= 0x10000000; +- AT_WRITE_REG(&adapter->hw, 0x1414, phy_data); +- } +- + } + return 0; + } +@@ -562,7 +564,7 @@ static int atl1c_mdio_read(struct net_device *netdev, int phy_id, int reg_num) + struct atl1c_adapter *adapter = netdev_priv(netdev); + u16 result; + +- atl1c_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result); ++ atl1c_read_phy_reg(&adapter->hw, reg_num, &result); + return result; + } + +@@ -571,7 +573,7 @@ static void atl1c_mdio_write(struct net_device *netdev, int phy_id, + { + struct atl1c_adapter *adapter = netdev_priv(netdev); + +- atl1c_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val); ++ atl1c_write_phy_reg(&adapter->hw, reg_num, val); + } + + /* +@@ -686,21 +688,15 @@ static void atl1c_set_mac_type(struct atl1c_hw *hw) + + static int atl1c_setup_mac_funcs(struct atl1c_hw *hw) + { +- u32 phy_status_data; + u32 link_ctrl_data; + + atl1c_set_mac_type(hw); +- AT_READ_REG(hw, REG_PHY_STATUS, &phy_status_data); + AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data); + + hw->ctrl_flags = ATL1C_INTR_MODRT_ENABLE | + ATL1C_TXQ_MODE_ENHANCE; +- if (link_ctrl_data & LINK_CTRL_L0S_EN) +- hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT; +- if (link_ctrl_data & LINK_CTRL_L1_EN) +- hw->ctrl_flags |= ATL1C_ASPM_L1_SUPPORT; +- if (link_ctrl_data & LINK_CTRL_EXT_SYNC) +- hw->ctrl_flags |= ATL1C_LINK_EXT_SYNC; ++ hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT | ++ ATL1C_ASPM_L1_SUPPORT; + hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON; + + if (hw->nic_type == athr_l1c || +@@ -709,6 +705,55 @@ static int atl1c_setup_mac_funcs(struct atl1c_hw *hw) + hw->link_cap_flags |= ATL1C_LINK_CAP_1000M; + return 0; + } ++ ++struct atl1c_platform_patch { ++ u16 pci_did; ++ u8 pci_revid; ++ u16 subsystem_vid; ++ u16 subsystem_did; ++ u32 patch_flag; ++#define ATL1C_LINK_PATCH 0x1 ++}; ++static const struct atl1c_platform_patch plats[] __devinitdata = { ++{0x2060, 0xC1, 0x1019, 0x8152, 0x1}, ++{0x2060, 0xC1, 0x1019, 0x2060, 0x1}, ++{0x2060, 0xC1, 0x1019, 0xE000, 0x1}, ++{0x2062, 0xC0, 0x1019, 0x8152, 0x1}, ++{0x2062, 0xC0, 0x1019, 0x2062, 0x1}, ++{0x2062, 0xC0, 0x1458, 0xE000, 0x1}, ++{0x2062, 0xC1, 0x1019, 0x8152, 0x1}, ++{0x2062, 0xC1, 0x1019, 0x2062, 0x1}, ++{0x2062, 0xC1, 0x1458, 0xE000, 0x1}, ++{0x2062, 0xC1, 0x1565, 0x2802, 0x1}, ++{0x2062, 0xC1, 0x1565, 0x2801, 0x1}, ++{0x1073, 0xC0, 0x1019, 0x8151, 0x1}, ++{0x1073, 0xC0, 0x1019, 0x1073, 0x1}, ++{0x1073, 0xC0, 0x1458, 0xE000, 0x1}, ++{0x1083, 0xC0, 0x1458, 0xE000, 0x1}, ++{0x1083, 0xC0, 0x1019, 0x8151, 0x1}, ++{0x1083, 0xC0, 0x1019, 0x1083, 0x1}, ++{0x1083, 0xC0, 0x1462, 0x7680, 0x1}, ++{0x1083, 0xC0, 0x1565, 0x2803, 0x1}, ++{0}, ++}; ++ ++static void __devinit atl1c_patch_assign(struct atl1c_hw *hw) ++{ ++ int i = 0; ++ ++ hw->msi_lnkpatch = false; ++ ++ while (plats[i].pci_did != 0) { ++ if (plats[i].pci_did == hw->device_id && ++ plats[i].pci_revid == hw->revision_id && ++ plats[i].subsystem_vid == hw->subsystem_vendor_id && ++ plats[i].subsystem_did == hw->subsystem_id) { ++ if (plats[i].patch_flag & ATL1C_LINK_PATCH) ++ hw->msi_lnkpatch = true; ++ } ++ i++; ++ } ++} + /* + * atl1c_sw_init - Initialize general software structures (struct atl1c_adapter) + * @adapter: board private structure to initialize +@@ -728,9 +773,8 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) + device_set_wakeup_enable(&pdev->dev, false); + adapter->link_speed = SPEED_0; + adapter->link_duplex = FULL_DUPLEX; +- adapter->num_rx_queues = AT_DEF_RECEIVE_QUEUE; + adapter->tpd_ring[0].count = 1024; +- adapter->rfd_ring[0].count = 512; ++ adapter->rfd_ring.count = 512; + + hw->vendor_id = pdev->vendor; + hw->device_id = pdev->device; +@@ -745,26 +789,18 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) + dev_err(&pdev->dev, "set mac function pointers failed\n"); + return -1; + } ++ atl1c_patch_assign(hw); ++ + hw->intr_mask = IMR_NORMAL_MASK; + hw->phy_configured = false; + hw->preamble_len = 7; + hw->max_frame_size = adapter->netdev->mtu; +- if (adapter->num_rx_queues < 2) { +- hw->rss_type = atl1c_rss_disable; +- hw->rss_mode = atl1c_rss_mode_disable; +- } else { +- hw->rss_type = atl1c_rss_ipv4; +- hw->rss_mode = atl1c_rss_mul_que_mul_int; +- hw->rss_hash_bits = 16; +- } + hw->autoneg_advertised = ADVERTISED_Autoneg; + hw->indirect_tab = 0xE4E4E4E4; + hw->base_cpu = 0; + + hw->ict = 50000; /* 100ms */ + hw->smb_timer = 200000; /* 400ms */ +- hw->cmb_tpd = 4; +- hw->cmb_tx_timer = 1; /* 2 us */ + hw->rx_imt = 200; + hw->tx_imt = 1000; + +@@ -772,9 +808,6 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) + hw->rfd_burst = 8; + hw->dma_order = atl1c_dma_ord_out; + hw->dmar_block = atl1c_dma_req_1024; +- hw->dmaw_block = atl1c_dma_req_1024; +- hw->dmar_dly_cnt = 15; +- hw->dmaw_dly_cnt = 4; + + if (atl1c_alloc_queues(adapter)) { + dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); +@@ -850,24 +883,22 @@ static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter, + */ + static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter) + { +- struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring; +- struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring; ++ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; ++ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct atl1c_buffer *buffer_info; + struct pci_dev *pdev = adapter->pdev; +- int i, j; ++ int j; + +- for (i = 0; i < adapter->num_rx_queues; i++) { +- for (j = 0; j < rfd_ring[i].count; j++) { +- buffer_info = &rfd_ring[i].buffer_info[j]; +- atl1c_clean_buffer(pdev, buffer_info, 0); +- } +- /* zero out the descriptor ring */ +- memset(rfd_ring[i].desc, 0, rfd_ring[i].size); +- rfd_ring[i].next_to_clean = 0; +- rfd_ring[i].next_to_use = 0; +- rrd_ring[i].next_to_use = 0; +- rrd_ring[i].next_to_clean = 0; ++ for (j = 0; j < rfd_ring->count; j++) { ++ buffer_info = &rfd_ring->buffer_info[j]; ++ atl1c_clean_buffer(pdev, buffer_info, 0); + } ++ /* zero out the descriptor ring */ ++ memset(rfd_ring->desc, 0, rfd_ring->size); ++ rfd_ring->next_to_clean = 0; ++ rfd_ring->next_to_use = 0; ++ rrd_ring->next_to_use = 0; ++ rrd_ring->next_to_clean = 0; + } + + /* +@@ -876,8 +907,8 @@ static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter) + static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter) + { + struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring; +- struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring; +- struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring; ++ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; ++ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct atl1c_buffer *buffer_info; + int i, j; + +@@ -889,15 +920,13 @@ static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter) + ATL1C_SET_BUFFER_STATE(&buffer_info[i], + ATL1C_BUFFER_FREE); + } +- for (i = 0; i < adapter->num_rx_queues; i++) { +- rfd_ring[i].next_to_use = 0; +- rfd_ring[i].next_to_clean = 0; +- rrd_ring[i].next_to_use = 0; +- rrd_ring[i].next_to_clean = 0; +- for (j = 0; j < rfd_ring[i].count; j++) { +- buffer_info = &rfd_ring[i].buffer_info[j]; +- ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); +- } ++ rfd_ring->next_to_use = 0; ++ rfd_ring->next_to_clean = 0; ++ rrd_ring->next_to_use = 0; ++ rrd_ring->next_to_clean = 0; ++ for (j = 0; j < rfd_ring->count; j++) { ++ buffer_info = &rfd_ring->buffer_info[j]; ++ ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); + } + } + +@@ -934,27 +963,23 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) + { + struct pci_dev *pdev = adapter->pdev; + struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring; +- struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring; +- struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring; ++ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; ++ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct atl1c_ring_header *ring_header = &adapter->ring_header; +- int num_rx_queues = adapter->num_rx_queues; + int size; + int i; + int count = 0; + int rx_desc_count = 0; + u32 offset = 0; + +- rrd_ring[0].count = rfd_ring[0].count; ++ rrd_ring->count = rfd_ring->count; + for (i = 1; i < AT_MAX_TRANSMIT_QUEUE; i++) + tpd_ring[i].count = tpd_ring[0].count; + +- for (i = 1; i < adapter->num_rx_queues; i++) +- rfd_ring[i].count = rrd_ring[i].count = rfd_ring[0].count; +- + /* 2 tpd queue, one high priority queue, + * another normal priority queue */ + size = sizeof(struct atl1c_buffer) * (tpd_ring->count * 2 + +- rfd_ring->count * num_rx_queues); ++ rfd_ring->count); + tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL); + if (unlikely(!tpd_ring->buffer_info)) { + dev_err(&pdev->dev, "kzalloc failed, size = %d\n", +@@ -967,12 +992,11 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) + count += tpd_ring[i].count; + } + +- for (i = 0; i < num_rx_queues; i++) { +- rfd_ring[i].buffer_info = +- (struct atl1c_buffer *) (tpd_ring->buffer_info + count); +- count += rfd_ring[i].count; +- rx_desc_count += rfd_ring[i].count; +- } ++ rfd_ring->buffer_info = ++ (struct atl1c_buffer *) (tpd_ring->buffer_info + count); ++ count += rfd_ring->count; ++ rx_desc_count += rfd_ring->count; ++ + /* + * real ring DMA buffer + * each ring/block may need up to 8 bytes for alignment, hence the +@@ -982,8 +1006,7 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) + sizeof(struct atl1c_tpd_desc) * tpd_ring->count * 2 + + sizeof(struct atl1c_rx_free_desc) * rx_desc_count + + sizeof(struct atl1c_recv_ret_status) * rx_desc_count + +- sizeof(struct atl1c_hw_stats) + +- 8 * 4 + 8 * 2 * num_rx_queues; ++ 8 * 4; + + ring_header->desc = pci_alloc_consistent(pdev, ring_header->size, + &ring_header->dma); +@@ -1004,25 +1027,18 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) + offset += roundup(tpd_ring[i].size, 8); + } + /* init RFD ring */ +- for (i = 0; i < num_rx_queues; i++) { +- rfd_ring[i].dma = ring_header->dma + offset; +- rfd_ring[i].desc = (u8 *) ring_header->desc + offset; +- rfd_ring[i].size = sizeof(struct atl1c_rx_free_desc) * +- rfd_ring[i].count; +- offset += roundup(rfd_ring[i].size, 8); +- } ++ rfd_ring->dma = ring_header->dma + offset; ++ rfd_ring->desc = (u8 *) ring_header->desc + offset; ++ rfd_ring->size = sizeof(struct atl1c_rx_free_desc) * rfd_ring->count; ++ offset += roundup(rfd_ring->size, 8); + + /* init RRD ring */ +- for (i = 0; i < num_rx_queues; i++) { +- rrd_ring[i].dma = ring_header->dma + offset; +- rrd_ring[i].desc = (u8 *) ring_header->desc + offset; +- rrd_ring[i].size = sizeof(struct atl1c_recv_ret_status) * +- rrd_ring[i].count; +- offset += roundup(rrd_ring[i].size, 8); +- } ++ rrd_ring->dma = ring_header->dma + offset; ++ rrd_ring->desc = (u8 *) ring_header->desc + offset; ++ rrd_ring->size = sizeof(struct atl1c_recv_ret_status) * ++ rrd_ring->count; ++ offset += roundup(rrd_ring->size, 8); + +- adapter->smb.dma = ring_header->dma + offset; +- adapter->smb.smb = (u8 *)ring_header->desc + offset; + return 0; + + err_nomem: +@@ -1033,26 +1049,20 @@ err_nomem: + static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) + { + struct atl1c_hw *hw = &adapter->hw; +- struct atl1c_rfd_ring *rfd_ring = (struct atl1c_rfd_ring *) +- adapter->rfd_ring; +- struct atl1c_rrd_ring *rrd_ring = (struct atl1c_rrd_ring *) +- adapter->rrd_ring; ++ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; ++ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *) + adapter->tpd_ring; +- struct atl1c_cmb *cmb = (struct atl1c_cmb *) &adapter->cmb; +- struct atl1c_smb *smb = (struct atl1c_smb *) &adapter->smb; +- int i; +- u32 data; + + /* TPD */ + AT_WRITE_REG(hw, REG_TX_BASE_ADDR_HI, + (u32)((tpd_ring[atl1c_trans_normal].dma & + AT_DMA_HI_ADDR_MASK) >> 32)); + /* just enable normal priority TX queue */ +- AT_WRITE_REG(hw, REG_NTPD_HEAD_ADDR_LO, ++ AT_WRITE_REG(hw, REG_TPD_PRI0_ADDR_LO, + (u32)(tpd_ring[atl1c_trans_normal].dma & + AT_DMA_LO_ADDR_MASK)); +- AT_WRITE_REG(hw, REG_HTPD_HEAD_ADDR_LO, ++ AT_WRITE_REG(hw, REG_TPD_PRI1_ADDR_LO, + (u32)(tpd_ring[atl1c_trans_high].dma & + AT_DMA_LO_ADDR_MASK)); + AT_WRITE_REG(hw, REG_TPD_RING_SIZE, +@@ -1061,31 +1071,21 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) + + /* RFD */ + AT_WRITE_REG(hw, REG_RX_BASE_ADDR_HI, +- (u32)((rfd_ring[0].dma & AT_DMA_HI_ADDR_MASK) >> 32)); +- for (i = 0; i < adapter->num_rx_queues; i++) +- AT_WRITE_REG(hw, atl1c_rfd_addr_lo_regs[i], +- (u32)(rfd_ring[i].dma & AT_DMA_LO_ADDR_MASK)); ++ (u32)((rfd_ring->dma & AT_DMA_HI_ADDR_MASK) >> 32)); ++ AT_WRITE_REG(hw, REG_RFD0_HEAD_ADDR_LO, ++ (u32)(rfd_ring->dma & AT_DMA_LO_ADDR_MASK)); + + AT_WRITE_REG(hw, REG_RFD_RING_SIZE, +- rfd_ring[0].count & RFD_RING_SIZE_MASK); ++ rfd_ring->count & RFD_RING_SIZE_MASK); + AT_WRITE_REG(hw, REG_RX_BUF_SIZE, + adapter->rx_buffer_len & RX_BUF_SIZE_MASK); + + /* RRD */ +- for (i = 0; i < adapter->num_rx_queues; i++) +- AT_WRITE_REG(hw, atl1c_rrd_addr_lo_regs[i], +- (u32)(rrd_ring[i].dma & AT_DMA_LO_ADDR_MASK)); ++ AT_WRITE_REG(hw, REG_RRD0_HEAD_ADDR_LO, ++ (u32)(rrd_ring->dma & AT_DMA_LO_ADDR_MASK)); + AT_WRITE_REG(hw, REG_RRD_RING_SIZE, +- (rrd_ring[0].count & RRD_RING_SIZE_MASK)); ++ (rrd_ring->count & RRD_RING_SIZE_MASK)); + +- /* CMB */ +- AT_WRITE_REG(hw, REG_CMB_BASE_ADDR_LO, cmb->dma & AT_DMA_LO_ADDR_MASK); +- +- /* SMB */ +- AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_HI, +- (u32)((smb->dma & AT_DMA_HI_ADDR_MASK) >> 32)); +- AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_LO, +- (u32)(smb->dma & AT_DMA_LO_ADDR_MASK)); + if (hw->nic_type == athr_l2c_b) { + AT_WRITE_REG(hw, REG_SRAM_RXF_LEN, 0x02a0L); + AT_WRITE_REG(hw, REG_SRAM_TXF_LEN, 0x0100L); +@@ -1096,13 +1096,6 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) + AT_WRITE_REG(hw, REG_TXF_WATER_MARK, 0); /* TX watermark, to enter l1 state.*/ + AT_WRITE_REG(hw, REG_RXD_DMA_CTRL, 0); /* RXD threshold.*/ + } +- if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d_2) { +- /* Power Saving for L2c_B */ +- AT_READ_REG(hw, REG_SERDES_LOCK, &data); +- data |= SERDES_MAC_CLK_SLOWDOWN; +- data |= SERDES_PYH_CLK_SLOWDOWN; +- AT_WRITE_REG(hw, REG_SERDES_LOCK, data); +- } + /* Load all of base address above */ + AT_WRITE_REG(hw, REG_LOAD_PTR, 1); + } +@@ -1110,32 +1103,26 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) + static void atl1c_configure_tx(struct atl1c_adapter *adapter) + { + struct atl1c_hw *hw = &adapter->hw; +- u32 dev_ctrl_data; +- u32 max_pay_load; ++ int max_pay_load; + u16 tx_offload_thresh; + u32 txq_ctrl_data; +- u32 max_pay_load_data; + +- tx_offload_thresh = MAX_TX_OFFLOAD_THRESH; ++ tx_offload_thresh = MAX_TSO_FRAME_SIZE; + AT_WRITE_REG(hw, REG_TX_TSO_OFFLOAD_THRESH, + (tx_offload_thresh >> 3) & TX_TSO_OFFLOAD_THRESH_MASK); +- AT_READ_REG(hw, REG_DEVICE_CTRL, &dev_ctrl_data); +- max_pay_load = (dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT) & +- DEVICE_CTRL_MAX_PAYLOAD_MASK; +- hw->dmaw_block = min_t(u32, max_pay_load, hw->dmaw_block); +- max_pay_load = (dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT) & +- DEVICE_CTRL_MAX_RREQ_SZ_MASK; ++ max_pay_load = pcie_get_readrq(adapter->pdev) >> 8; + hw->dmar_block = min_t(u32, max_pay_load, hw->dmar_block); +- +- txq_ctrl_data = (hw->tpd_burst & TXQ_NUM_TPD_BURST_MASK) << +- TXQ_NUM_TPD_BURST_SHIFT; +- if (hw->ctrl_flags & ATL1C_TXQ_MODE_ENHANCE) +- txq_ctrl_data |= TXQ_CTRL_ENH_MODE; +- max_pay_load_data = (atl1c_pay_load_size[hw->dmar_block] & +- TXQ_TXF_BURST_NUM_MASK) << TXQ_TXF_BURST_NUM_SHIFT; +- if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) +- max_pay_load_data >>= 1; +- txq_ctrl_data |= max_pay_load_data; ++ /* ++ * if BIOS had changed the dam-read-max-length to an invalid value, ++ * restore it to default value ++ */ ++ if (hw->dmar_block < DEVICE_CTRL_MAXRRS_MIN) { ++ pcie_set_readrq(adapter->pdev, 128 << DEVICE_CTRL_MAXRRS_MIN); ++ hw->dmar_block = DEVICE_CTRL_MAXRRS_MIN; ++ } ++ txq_ctrl_data = ++ hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 ? ++ L2CB_TXQ_CFGV : L1C_TXQ_CFGV; + + AT_WRITE_REG(hw, REG_TXQ_CTRL, txq_ctrl_data); + } +@@ -1150,34 +1137,13 @@ static void atl1c_configure_rx(struct atl1c_adapter *adapter) + + if (hw->ctrl_flags & ATL1C_RX_IPV6_CHKSUM) + rxq_ctrl_data |= IPV6_CHKSUM_CTRL_EN; +- if (hw->rss_type == atl1c_rss_ipv4) +- rxq_ctrl_data |= RSS_HASH_IPV4; +- if (hw->rss_type == atl1c_rss_ipv4_tcp) +- rxq_ctrl_data |= RSS_HASH_IPV4_TCP; +- if (hw->rss_type == atl1c_rss_ipv6) +- rxq_ctrl_data |= RSS_HASH_IPV6; +- if (hw->rss_type == atl1c_rss_ipv6_tcp) +- rxq_ctrl_data |= RSS_HASH_IPV6_TCP; +- if (hw->rss_type != atl1c_rss_disable) +- rxq_ctrl_data |= RRS_HASH_CTRL_EN; +- +- rxq_ctrl_data |= (hw->rss_mode & RSS_MODE_MASK) << +- RSS_MODE_SHIFT; +- rxq_ctrl_data |= (hw->rss_hash_bits & RSS_HASH_BITS_MASK) << +- RSS_HASH_BITS_SHIFT; +- if (hw->ctrl_flags & ATL1C_ASPM_CTRL_MON) +- rxq_ctrl_data |= (ASPM_THRUPUT_LIMIT_1M & +- ASPM_THRUPUT_LIMIT_MASK) << ASPM_THRUPUT_LIMIT_SHIFT; + +- AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data); +-} +- +-static void atl1c_configure_rss(struct atl1c_adapter *adapter) +-{ +- struct atl1c_hw *hw = &adapter->hw; ++ /* aspm for gigabit */ ++ if (hw->nic_type != athr_l1d_2 && (hw->device_id & 1) != 0) ++ rxq_ctrl_data = FIELD_SETX(rxq_ctrl_data, ASPM_THRUPUT_LIMIT, ++ ASPM_THRUPUT_LIMIT_100M); + +- AT_WRITE_REG(hw, REG_IDT_TABLE, hw->indirect_tab); +- AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, hw->base_cpu); ++ AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data); + } + + static void atl1c_configure_dma(struct atl1c_adapter *adapter) +@@ -1185,36 +1151,11 @@ static void atl1c_configure_dma(struct atl1c_adapter *adapter) + struct atl1c_hw *hw = &adapter->hw; + u32 dma_ctrl_data; + +- dma_ctrl_data = DMA_CTRL_DMAR_REQ_PRI; +- if (hw->ctrl_flags & ATL1C_CMB_ENABLE) +- dma_ctrl_data |= DMA_CTRL_CMB_EN; +- if (hw->ctrl_flags & ATL1C_SMB_ENABLE) +- dma_ctrl_data |= DMA_CTRL_SMB_EN; +- else +- dma_ctrl_data |= MAC_CTRL_SMB_DIS; +- +- switch (hw->dma_order) { +- case atl1c_dma_ord_in: +- dma_ctrl_data |= DMA_CTRL_DMAR_IN_ORDER; +- break; +- case atl1c_dma_ord_enh: +- dma_ctrl_data |= DMA_CTRL_DMAR_ENH_ORDER; +- break; +- case atl1c_dma_ord_out: +- dma_ctrl_data |= DMA_CTRL_DMAR_OUT_ORDER; +- break; +- default: +- break; +- } +- +- dma_ctrl_data |= (((u32)hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK) +- << DMA_CTRL_DMAR_BURST_LEN_SHIFT; +- dma_ctrl_data |= (((u32)hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK) +- << DMA_CTRL_DMAW_BURST_LEN_SHIFT; +- dma_ctrl_data |= (((u32)hw->dmar_dly_cnt) & DMA_CTRL_DMAR_DLY_CNT_MASK) +- << DMA_CTRL_DMAR_DLY_CNT_SHIFT; +- dma_ctrl_data |= (((u32)hw->dmaw_dly_cnt) & DMA_CTRL_DMAW_DLY_CNT_MASK) +- << DMA_CTRL_DMAW_DLY_CNT_SHIFT; ++ dma_ctrl_data = FIELDX(DMA_CTRL_RORDER_MODE, DMA_CTRL_RORDER_MODE_OUT) | ++ DMA_CTRL_RREQ_PRI_DATA | ++ FIELDX(DMA_CTRL_RREQ_BLEN, hw->dmar_block) | ++ FIELDX(DMA_CTRL_WDLY_CNT, DMA_CTRL_WDLY_CNT_DEF) | ++ FIELDX(DMA_CTRL_RDLY_CNT, DMA_CTRL_RDLY_CNT_DEF); + + AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data); + } +@@ -1229,52 +1170,53 @@ static int atl1c_stop_mac(struct atl1c_hw *hw) + u32 data; + + AT_READ_REG(hw, REG_RXQ_CTRL, &data); +- data &= ~(RXQ1_CTRL_EN | RXQ2_CTRL_EN | +- RXQ3_CTRL_EN | RXQ_CTRL_EN); ++ data &= ~RXQ_CTRL_EN; + AT_WRITE_REG(hw, REG_RXQ_CTRL, data); + + AT_READ_REG(hw, REG_TXQ_CTRL, &data); + data &= ~TXQ_CTRL_EN; +- AT_WRITE_REG(hw, REG_TWSI_CTRL, data); ++ AT_WRITE_REG(hw, REG_TXQ_CTRL, data); + +- atl1c_wait_until_idle(hw); ++ atl1c_wait_until_idle(hw, IDLE_STATUS_RXQ_BUSY | IDLE_STATUS_TXQ_BUSY); + + AT_READ_REG(hw, REG_MAC_CTRL, &data); + data &= ~(MAC_CTRL_TX_EN | MAC_CTRL_RX_EN); + AT_WRITE_REG(hw, REG_MAC_CTRL, data); + +- return (int)atl1c_wait_until_idle(hw); ++ return (int)atl1c_wait_until_idle(hw, ++ IDLE_STATUS_TXMAC_BUSY | IDLE_STATUS_RXMAC_BUSY); + } + +-static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw) ++static void atl1c_start_mac(struct atl1c_adapter *adapter) + { +- u32 data; +- +- AT_READ_REG(hw, REG_RXQ_CTRL, &data); +- switch (hw->adapter->num_rx_queues) { +- case 4: +- data |= (RXQ3_CTRL_EN | RXQ2_CTRL_EN | RXQ1_CTRL_EN); +- break; +- case 3: +- data |= (RXQ2_CTRL_EN | RXQ1_CTRL_EN); +- break; +- case 2: +- data |= RXQ1_CTRL_EN; +- break; +- default: +- break; +- } +- data |= RXQ_CTRL_EN; +- AT_WRITE_REG(hw, REG_RXQ_CTRL, data); +-} +- +-static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw) +-{ +- u32 data; ++ struct atl1c_hw *hw = &adapter->hw; ++ u32 mac, txq, rxq; ++ ++ hw->mac_duplex = adapter->link_duplex == FULL_DUPLEX ? true : false; ++ hw->mac_speed = adapter->link_speed == SPEED_1000 ? ++ atl1c_mac_speed_1000 : atl1c_mac_speed_10_100; ++ ++ AT_READ_REG(hw, REG_TXQ_CTRL, &txq); ++ AT_READ_REG(hw, REG_RXQ_CTRL, &rxq); ++ AT_READ_REG(hw, REG_MAC_CTRL, &mac); ++ ++ txq |= TXQ_CTRL_EN; ++ rxq |= RXQ_CTRL_EN; ++ mac |= MAC_CTRL_TX_EN | MAC_CTRL_TX_FLOW | ++ MAC_CTRL_RX_EN | MAC_CTRL_RX_FLOW | ++ MAC_CTRL_ADD_CRC | MAC_CTRL_PAD | ++ MAC_CTRL_BC_EN | MAC_CTRL_SINGLE_PAUSE_EN | ++ MAC_CTRL_HASH_ALG_CRC32; ++ if (hw->mac_duplex) ++ mac |= MAC_CTRL_DUPLX; ++ else ++ mac &= ~MAC_CTRL_DUPLX; ++ mac = FIELD_SETX(mac, MAC_CTRL_SPEED, hw->mac_speed); ++ mac = FIELD_SETX(mac, MAC_CTRL_PRMLEN, hw->preamble_len); + +- AT_READ_REG(hw, REG_TXQ_CTRL, &data); +- data |= TXQ_CTRL_EN; +- AT_WRITE_REG(hw, REG_TXQ_CTRL, data); ++ AT_WRITE_REG(hw, REG_TXQ_CTRL, txq); ++ AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq); ++ AT_WRITE_REG(hw, REG_MAC_CTRL, mac); + } + + /* +@@ -1286,10 +1228,7 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) + { + struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter; + struct pci_dev *pdev = adapter->pdev; +- u32 master_ctrl_data = 0; +- +- AT_WRITE_REG(hw, REG_IMR, 0); +- AT_WRITE_REG(hw, REG_ISR, ISR_DIS_INT); ++ u32 ctrl_data = 0; + + atl1c_stop_mac(hw); + /* +@@ -1298,194 +1237,148 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) + * the current PCI configuration. The global reset bit is self- + * clearing, and should clear within a microsecond. + */ +- AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); +- master_ctrl_data |= MASTER_CTRL_OOB_DIS_OFF; +- AT_WRITE_REGW(hw, REG_MASTER_CTRL, ((master_ctrl_data | MASTER_CTRL_SOFT_RST) +- & 0xFFFF)); ++ AT_READ_REG(hw, REG_MASTER_CTRL, &ctrl_data); ++ ctrl_data |= MASTER_CTRL_OOB_DIS; ++ AT_WRITE_REG(hw, REG_MASTER_CTRL, ctrl_data | MASTER_CTRL_SOFT_RST); + + AT_WRITE_FLUSH(hw); + msleep(10); + /* Wait at least 10ms for All module to be Idle */ + +- if (atl1c_wait_until_idle(hw)) { ++ if (atl1c_wait_until_idle(hw, IDLE_STATUS_MASK)) { + dev_err(&pdev->dev, + "MAC state machine can't be idle since" + " disabled for 10ms second\n"); + return -1; + } ++ AT_WRITE_REG(hw, REG_MASTER_CTRL, ctrl_data); ++ ++ /* driver control speed/duplex */ ++ AT_READ_REG(hw, REG_MAC_CTRL, &ctrl_data); ++ AT_WRITE_REG(hw, REG_MAC_CTRL, ctrl_data | MAC_CTRL_SPEED_MODE_SW); ++ ++ /* clk switch setting */ ++ AT_READ_REG(hw, REG_SERDES, &ctrl_data); ++ switch (hw->nic_type) { ++ case athr_l2c_b: ++ ctrl_data &= ~(SERDES_PHY_CLK_SLOWDOWN | ++ SERDES_MAC_CLK_SLOWDOWN); ++ AT_WRITE_REG(hw, REG_SERDES, ctrl_data); ++ break; ++ case athr_l2c_b2: ++ case athr_l1d_2: ++ ctrl_data |= SERDES_PHY_CLK_SLOWDOWN | SERDES_MAC_CLK_SLOWDOWN; ++ AT_WRITE_REG(hw, REG_SERDES, ctrl_data); ++ break; ++ default: ++ break; ++ } ++ + return 0; + } + + static void atl1c_disable_l0s_l1(struct atl1c_hw *hw) + { +- u32 pm_ctrl_data; ++ u16 ctrl_flags = hw->ctrl_flags; + +- AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data); +- pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << +- PM_CTRL_L1_ENTRY_TIMER_SHIFT); +- pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1; +- pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; +- pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; +- pm_ctrl_data &= ~PM_CTRL_MAC_ASPM_CHK; +- pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1; +- +- pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN; +- pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN; +- pm_ctrl_data |= PM_CTRL_SERDES_L1_EN; +- AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data); ++ hw->ctrl_flags &= ~(ATL1C_ASPM_L0S_SUPPORT | ATL1C_ASPM_L1_SUPPORT); ++ atl1c_set_aspm(hw, SPEED_0); ++ hw->ctrl_flags = ctrl_flags; + } + + /* + * Set ASPM state. + * Enable/disable L0s/L1 depend on link state. + */ +-static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup) ++static void atl1c_set_aspm(struct atl1c_hw *hw, u16 link_speed) + { + u32 pm_ctrl_data; +- u32 link_ctrl_data; +- u32 link_l1_timer = 0xF; ++ u32 link_l1_timer; + + AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data); +- AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data); ++ pm_ctrl_data &= ~(PM_CTRL_ASPM_L1_EN | ++ PM_CTRL_ASPM_L0S_EN | ++ PM_CTRL_MAC_ASPM_CHK); ++ /* L1 timer */ ++ if (hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { ++ pm_ctrl_data &= ~PMCTRL_TXL1_AFTER_L0S; ++ link_l1_timer = ++ link_speed == SPEED_1000 || link_speed == SPEED_100 ? ++ L1D_PMCTRL_L1_ENTRY_TM_16US : 1; ++ pm_ctrl_data = FIELD_SETX(pm_ctrl_data, ++ L1D_PMCTRL_L1_ENTRY_TM, link_l1_timer); ++ } else { ++ link_l1_timer = hw->nic_type == athr_l2c_b ? ++ L2CB1_PM_CTRL_L1_ENTRY_TM : L1C_PM_CTRL_L1_ENTRY_TM; ++ if (link_speed != SPEED_1000 && link_speed != SPEED_100) ++ link_l1_timer = 1; ++ pm_ctrl_data = FIELD_SETX(pm_ctrl_data, ++ PM_CTRL_L1_ENTRY_TIMER, link_l1_timer); ++ } + +- pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1; +- pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << +- PM_CTRL_L1_ENTRY_TIMER_SHIFT); +- pm_ctrl_data &= ~(PM_CTRL_LCKDET_TIMER_MASK << +- PM_CTRL_LCKDET_TIMER_SHIFT); +- pm_ctrl_data |= AT_LCKDET_TIMER << PM_CTRL_LCKDET_TIMER_SHIFT; ++ /* L0S/L1 enable */ ++ if ((hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT) && link_speed != SPEED_0) ++ pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN | PM_CTRL_MAC_ASPM_CHK; ++ if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) ++ pm_ctrl_data |= PM_CTRL_ASPM_L1_EN | PM_CTRL_MAC_ASPM_CHK; + ++ /* l2cb & l1d & l2cb2 & l1d2 */ + if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d || +- hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { +- link_ctrl_data &= ~LINK_CTRL_EXT_SYNC; +- if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE)) { +- if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) +- link_ctrl_data |= LINK_CTRL_EXT_SYNC; +- } +- +- AT_WRITE_REG(hw, REG_LINK_CTRL, link_ctrl_data); +- +- pm_ctrl_data |= PM_CTRL_RCVR_WT_TIMER; +- pm_ctrl_data &= ~(PM_CTRL_PM_REQ_TIMER_MASK << +- PM_CTRL_PM_REQ_TIMER_SHIFT); +- pm_ctrl_data |= AT_ASPM_L1_TIMER << +- PM_CTRL_PM_REQ_TIMER_SHIFT; +- pm_ctrl_data &= ~PM_CTRL_SA_DLY_EN; +- pm_ctrl_data &= ~PM_CTRL_HOTRST; +- pm_ctrl_data |= 1 << PM_CTRL_L1_ENTRY_TIMER_SHIFT; +- pm_ctrl_data |= PM_CTRL_SERDES_PD_EX_L1; +- } +- pm_ctrl_data |= PM_CTRL_MAC_ASPM_CHK; +- if (linkup) { +- pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; +- pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; +- if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) +- pm_ctrl_data |= PM_CTRL_ASPM_L1_EN; +- if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT) +- pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN; +- +- if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d || +- hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { +- if (hw->nic_type == athr_l2c_b) +- if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE)) +- pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; +- pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN; +- pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN; +- pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN; +- pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; +- if (hw->adapter->link_speed == SPEED_100 || +- hw->adapter->link_speed == SPEED_1000) { +- pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << +- PM_CTRL_L1_ENTRY_TIMER_SHIFT); +- if (hw->nic_type == athr_l2c_b) +- link_l1_timer = 7; +- else if (hw->nic_type == athr_l2c_b2 || +- hw->nic_type == athr_l1d_2) +- link_l1_timer = 4; +- pm_ctrl_data |= link_l1_timer << +- PM_CTRL_L1_ENTRY_TIMER_SHIFT; +- } +- } else { +- pm_ctrl_data |= PM_CTRL_SERDES_L1_EN; +- pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN; +- pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN; +- pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1; ++ hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { ++ pm_ctrl_data = FIELD_SETX(pm_ctrl_data, ++ PM_CTRL_PM_REQ_TIMER, PM_CTRL_PM_REQ_TO_DEF); ++ pm_ctrl_data |= PM_CTRL_RCVR_WT_TIMER | ++ PM_CTRL_SERDES_PD_EX_L1 | ++ PM_CTRL_CLK_SWH_L1; ++ pm_ctrl_data &= ~(PM_CTRL_SERDES_L1_EN | ++ PM_CTRL_SERDES_PLL_L1_EN | ++ PM_CTRL_SERDES_BUFS_RX_L1_EN | ++ PM_CTRL_SA_DLY_EN | ++ PM_CTRL_HOTRST); ++ /* disable l0s if link down or l2cb */ ++ if (link_speed == SPEED_0 || hw->nic_type == athr_l2c_b) + pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; +- pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; +- ++ } else { /* l1c */ ++ pm_ctrl_data = ++ FIELD_SETX(pm_ctrl_data, PM_CTRL_L1_ENTRY_TIMER, 0); ++ if (link_speed != SPEED_0) { ++ pm_ctrl_data |= PM_CTRL_SERDES_L1_EN | ++ PM_CTRL_SERDES_PLL_L1_EN | ++ PM_CTRL_SERDES_BUFS_RX_L1_EN; ++ pm_ctrl_data &= ~(PM_CTRL_SERDES_PD_EX_L1 | ++ PM_CTRL_CLK_SWH_L1 | ++ PM_CTRL_ASPM_L0S_EN | ++ PM_CTRL_ASPM_L1_EN); ++ } else { /* link down */ ++ pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; ++ pm_ctrl_data &= ~(PM_CTRL_SERDES_L1_EN | ++ PM_CTRL_SERDES_PLL_L1_EN | ++ PM_CTRL_SERDES_BUFS_RX_L1_EN | ++ PM_CTRL_ASPM_L0S_EN); + } +- } else { +- pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN; +- pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; +- pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN; +- pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; +- +- if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) +- pm_ctrl_data |= PM_CTRL_ASPM_L1_EN; +- else +- pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; + } + AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data); + + return; + } + +-static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter) +-{ +- struct atl1c_hw *hw = &adapter->hw; +- struct net_device *netdev = adapter->netdev; +- u32 mac_ctrl_data; +- +- mac_ctrl_data = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN; +- mac_ctrl_data |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW); +- +- if (adapter->link_duplex == FULL_DUPLEX) { +- hw->mac_duplex = true; +- mac_ctrl_data |= MAC_CTRL_DUPLX; +- } +- +- if (adapter->link_speed == SPEED_1000) +- hw->mac_speed = atl1c_mac_speed_1000; +- else +- hw->mac_speed = atl1c_mac_speed_10_100; +- +- mac_ctrl_data |= (hw->mac_speed & MAC_CTRL_SPEED_MASK) << +- MAC_CTRL_SPEED_SHIFT; +- +- mac_ctrl_data |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD); +- mac_ctrl_data |= ((hw->preamble_len & MAC_CTRL_PRMLEN_MASK) << +- MAC_CTRL_PRMLEN_SHIFT); +- +- __atl1c_vlan_mode(netdev->features, &mac_ctrl_data); +- +- mac_ctrl_data |= MAC_CTRL_BC_EN; +- if (netdev->flags & IFF_PROMISC) +- mac_ctrl_data |= MAC_CTRL_PROMIS_EN; +- if (netdev->flags & IFF_ALLMULTI) +- mac_ctrl_data |= MAC_CTRL_MC_ALL_EN; +- +- mac_ctrl_data |= MAC_CTRL_SINGLE_PAUSE_EN; +- if (hw->nic_type == athr_l1d || hw->nic_type == athr_l2c_b2 || +- hw->nic_type == athr_l1d_2) { +- mac_ctrl_data |= MAC_CTRL_SPEED_MODE_SW; +- mac_ctrl_data |= MAC_CTRL_HASH_ALG_CRC32; +- } +- AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); +-} +- + /* + * atl1c_configure - Configure Transmit&Receive Unit after Reset + * @adapter: board private structure + * + * Configure the Tx /Rx unit of the MAC after a reset. + */ +-static int atl1c_configure(struct atl1c_adapter *adapter) ++static int atl1c_configure_mac(struct atl1c_adapter *adapter) + { + struct atl1c_hw *hw = &adapter->hw; + u32 master_ctrl_data = 0; + u32 intr_modrt_data; + u32 data; + ++ AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); ++ master_ctrl_data &= ~(MASTER_CTRL_TX_ITIMER_EN | ++ MASTER_CTRL_RX_ITIMER_EN | ++ MASTER_CTRL_INT_RDCLR); + /* clear interrupt status */ + AT_WRITE_REG(hw, REG_ISR, 0xFFFFFFFF); + /* Clear any WOL status */ +@@ -1524,30 +1417,39 @@ static int atl1c_configure(struct atl1c_adapter *adapter) + master_ctrl_data |= MASTER_CTRL_SA_TIMER_EN; + AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); + +- if (hw->ctrl_flags & ATL1C_CMB_ENABLE) { +- AT_WRITE_REG(hw, REG_CMB_TPD_THRESH, +- hw->cmb_tpd & CMB_TPD_THRESH_MASK); +- AT_WRITE_REG(hw, REG_CMB_TX_TIMER, +- hw->cmb_tx_timer & CMB_TX_TIMER_MASK); +- } ++ AT_WRITE_REG(hw, REG_SMB_STAT_TIMER, ++ hw->smb_timer & SMB_STAT_TIMER_MASK); + +- if (hw->ctrl_flags & ATL1C_SMB_ENABLE) +- AT_WRITE_REG(hw, REG_SMB_STAT_TIMER, +- hw->smb_timer & SMB_STAT_TIMER_MASK); + /* set MTU */ + AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN + + VLAN_HLEN + ETH_FCS_LEN); +- /* HDS, disable */ +- AT_WRITE_REG(hw, REG_HDS_CTRL, 0); + + atl1c_configure_tx(adapter); + atl1c_configure_rx(adapter); +- atl1c_configure_rss(adapter); + atl1c_configure_dma(adapter); + + return 0; + } + ++static int atl1c_configure(struct atl1c_adapter *adapter) ++{ ++ struct net_device *netdev = adapter->netdev; ++ int num; ++ ++ atl1c_init_ring_ptrs(adapter); ++ atl1c_set_multi(netdev); ++ atl1c_restore_vlan(adapter); ++ ++ num = atl1c_alloc_rx_buffer(adapter); ++ if (unlikely(num == 0)) ++ return -ENOMEM; ++ ++ if (atl1c_configure_mac(adapter)) ++ return -EIO; ++ ++ return 0; ++} ++ + static void atl1c_update_hw_stats(struct atl1c_adapter *adapter) + { + u16 hw_reg_addr = 0; +@@ -1634,16 +1536,11 @@ static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter, + struct pci_dev *pdev = adapter->pdev; + u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean); + u16 hw_next_to_clean; +- u16 shift; +- u32 data; ++ u16 reg; + +- if (type == atl1c_trans_high) +- shift = MB_HTPD_CONS_IDX_SHIFT; +- else +- shift = MB_NTPD_CONS_IDX_SHIFT; ++ reg = type == atl1c_trans_high ? REG_TPD_PRI1_CIDX : REG_TPD_PRI0_CIDX; + +- AT_READ_REG(&adapter->hw, REG_MB_PRIO_CONS_IDX, &data); +- hw_next_to_clean = (data >> shift) & MB_PRIO_PROD_IDX_MASK; ++ AT_READ_REGW(&adapter->hw, reg, &hw_next_to_clean); + + while (next_to_clean != hw_next_to_clean) { + buffer_info = &tpd_ring->buffer_info[next_to_clean]; +@@ -1745,9 +1642,9 @@ static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter, + skb_checksum_none_assert(skb); + } + +-static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid) ++static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter) + { +- struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[ringid]; ++ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; + struct pci_dev *pdev = adapter->pdev; + struct atl1c_buffer *buffer_info, *next_info; + struct sk_buff *skb; +@@ -1799,7 +1696,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid + /* TODO: update mailbox here */ + wmb(); + rfd_ring->next_to_use = rfd_next_to_use; +- AT_WRITE_REG(&adapter->hw, atl1c_rfd_prod_idx_regs[ringid], ++ AT_WRITE_REG(&adapter->hw, REG_MB_RFD0_PROD_IDX, + rfd_ring->next_to_use & MB_RFDX_PROD_IDX_MASK); + } + +@@ -1838,7 +1735,7 @@ static void atl1c_clean_rfd(struct atl1c_rfd_ring *rfd_ring, + rfd_ring->next_to_clean = rfd_index; + } + +-static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que, ++static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, + int *work_done, int work_to_do) + { + u16 rfd_num, rfd_index; +@@ -1846,8 +1743,8 @@ static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que, + u16 length; + struct pci_dev *pdev = adapter->pdev; + struct net_device *netdev = adapter->netdev; +- struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[que]; +- struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring[que]; ++ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; ++ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct sk_buff *skb; + struct atl1c_recv_ret_status *rrs; + struct atl1c_buffer *buffer_info; +@@ -1913,7 +1810,7 @@ rrs_checked: + count++; + } + if (count) +- atl1c_alloc_rx_buffer(adapter, que); ++ atl1c_alloc_rx_buffer(adapter); + } + + /* +@@ -1930,7 +1827,7 @@ static int atl1c_clean(struct napi_struct *napi, int budget) + if (!netif_carrier_ok(adapter->netdev)) + goto quit_polling; + /* just enable one RXQ */ +- atl1c_clean_rx_irq(adapter, 0, &work_done, budget); ++ atl1c_clean_rx_irq(adapter, &work_done, budget); + + if (work_done < budget) { + quit_polling: +@@ -2205,23 +2102,10 @@ static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb, + struct atl1c_tpd_desc *tpd, enum atl1c_trans_queue type) + { + struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; +- u32 prod_data; ++ u16 reg; + +- AT_READ_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, &prod_data); +- switch (type) { +- case atl1c_trans_high: +- prod_data &= 0xFFFF0000; +- prod_data |= tpd_ring->next_to_use & 0xFFFF; +- break; +- case atl1c_trans_normal: +- prod_data &= 0x0000FFFF; +- prod_data |= (tpd_ring->next_to_use & 0xFFFF) << 16; +- break; +- default: +- break; +- } +- wmb(); +- AT_WRITE_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, prod_data); ++ reg = type == atl1c_trans_high ? REG_TPD_PRI1_PIDX : REG_TPD_PRI0_PIDX; ++ AT_WRITE_REGW(&adapter->hw, reg, tpd_ring->next_to_use); + } + + static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb, +@@ -2327,44 +2211,38 @@ static int atl1c_request_irq(struct atl1c_adapter *adapter) + return err; + } + ++ ++static void atl1c_reset_dma_ring(struct atl1c_adapter *adapter) ++{ ++ /* release tx-pending skbs and reset tx/rx ring index */ ++ atl1c_clean_tx_ring(adapter, atl1c_trans_normal); ++ atl1c_clean_tx_ring(adapter, atl1c_trans_high); ++ atl1c_clean_rx_ring(adapter); ++} ++ + static int atl1c_up(struct atl1c_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; +- int num; + int err; +- int i; + + netif_carrier_off(netdev); +- atl1c_init_ring_ptrs(adapter); +- atl1c_set_multi(netdev); +- atl1c_restore_vlan(adapter); +- +- for (i = 0; i < adapter->num_rx_queues; i++) { +- num = atl1c_alloc_rx_buffer(adapter, i); +- if (unlikely(num == 0)) { +- err = -ENOMEM; +- goto err_alloc_rx; +- } +- } + +- if (atl1c_configure(adapter)) { +- err = -EIO; ++ err = atl1c_configure(adapter); ++ if (unlikely(err)) + goto err_up; +- } + + err = atl1c_request_irq(adapter); + if (unlikely(err)) + goto err_up; + ++ atl1c_check_link_status(adapter); + clear_bit(__AT_DOWN, &adapter->flags); + napi_enable(&adapter->napi); + atl1c_irq_enable(adapter); +- atl1c_check_link_status(adapter); + netif_start_queue(netdev); + return err; + + err_up: +-err_alloc_rx: + atl1c_clean_rx_ring(adapter); + return err; + } +@@ -2382,15 +2260,15 @@ static void atl1c_down(struct atl1c_adapter *adapter) + napi_disable(&adapter->napi); + atl1c_irq_disable(adapter); + atl1c_free_irq(adapter); ++ /* disable ASPM if device inactive */ ++ atl1c_disable_l0s_l1(&adapter->hw); + /* reset MAC to disable all RX/TX */ + atl1c_reset_mac(&adapter->hw); + msleep(1); + + adapter->link_speed = SPEED_0; + adapter->link_duplex = -1; +- atl1c_clean_tx_ring(adapter, atl1c_trans_normal); +- atl1c_clean_tx_ring(adapter, atl1c_trans_high); +- atl1c_clean_rx_ring(adapter); ++ atl1c_reset_dma_ring(adapter); + } + + /* +@@ -2423,13 +2301,6 @@ static int atl1c_open(struct net_device *netdev) + if (unlikely(err)) + goto err_up; + +- if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) { +- u32 phy_data; +- +- AT_READ_REG(&adapter->hw, REG_MDIO_CTRL, &phy_data); +- phy_data |= MDIO_AP_EN; +- AT_WRITE_REG(&adapter->hw, REG_MDIO_CTRL, phy_data); +- } + return 0; + + err_up: +@@ -2455,6 +2326,8 @@ static int atl1c_close(struct net_device *netdev) + struct atl1c_adapter *adapter = netdev_priv(netdev); + + WARN_ON(test_bit(__AT_RESETTING, &adapter->flags)); ++ set_bit(__AT_DOWN, &adapter->flags); ++ cancel_work_sync(&adapter->common_task); + atl1c_down(adapter); + atl1c_free_ring_resources(adapter); + return 0; +@@ -2466,10 +2339,6 @@ static int atl1c_suspend(struct device *dev) + struct net_device *netdev = pci_get_drvdata(pdev); + struct atl1c_adapter *adapter = netdev_priv(netdev); + struct atl1c_hw *hw = &adapter->hw; +- u32 mac_ctrl_data = 0; +- u32 master_ctrl_data = 0; +- u32 wol_ctrl_data = 0; +- u16 mii_intr_status_data = 0; + u32 wufc = adapter->wol; + + atl1c_disable_l0s_l1(hw); +@@ -2480,75 +2349,10 @@ static int atl1c_suspend(struct device *dev) + netif_device_detach(netdev); + + if (wufc) +- if (atl1c_phy_power_saving(hw) != 0) ++ if (atl1c_phy_to_ps_link(hw) != 0) + dev_dbg(&pdev->dev, "phy power saving failed"); + +- AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); +- AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data); +- +- master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS; +- mac_ctrl_data &= ~(MAC_CTRL_PRMLEN_MASK << MAC_CTRL_PRMLEN_SHIFT); +- mac_ctrl_data |= (((u32)adapter->hw.preamble_len & +- MAC_CTRL_PRMLEN_MASK) << +- MAC_CTRL_PRMLEN_SHIFT); +- mac_ctrl_data &= ~(MAC_CTRL_SPEED_MASK << MAC_CTRL_SPEED_SHIFT); +- mac_ctrl_data &= ~MAC_CTRL_DUPLX; +- +- if (wufc) { +- mac_ctrl_data |= MAC_CTRL_RX_EN; +- if (adapter->link_speed == SPEED_1000 || +- adapter->link_speed == SPEED_0) { +- mac_ctrl_data |= atl1c_mac_speed_1000 << +- MAC_CTRL_SPEED_SHIFT; +- mac_ctrl_data |= MAC_CTRL_DUPLX; +- } else +- mac_ctrl_data |= atl1c_mac_speed_10_100 << +- MAC_CTRL_SPEED_SHIFT; +- +- if (adapter->link_duplex == DUPLEX_FULL) +- mac_ctrl_data |= MAC_CTRL_DUPLX; +- +- /* turn on magic packet wol */ +- if (wufc & AT_WUFC_MAG) +- wol_ctrl_data |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN; +- +- if (wufc & AT_WUFC_LNKC) { +- wol_ctrl_data |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN; +- /* only link up can wake up */ +- if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) { +- dev_dbg(&pdev->dev, "%s: read write phy " +- "register failed.\n", +- atl1c_driver_name); +- } +- } +- /* clear phy interrupt */ +- atl1c_read_phy_reg(hw, MII_ISR, &mii_intr_status_data); +- /* Config MAC Ctrl register */ +- __atl1c_vlan_mode(netdev->features, &mac_ctrl_data); +- +- /* magic packet maybe Broadcast&multicast&Unicast frame */ +- if (wufc & AT_WUFC_MAG) +- mac_ctrl_data |= MAC_CTRL_BC_EN; +- +- dev_dbg(&pdev->dev, +- "%s: suspend MAC=0x%x\n", +- atl1c_driver_name, mac_ctrl_data); +- AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); +- AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data); +- AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); +- +- AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT | +- GPHY_CTRL_EXT_RESET); +- } else { +- AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_POWER_SAVING); +- master_ctrl_data |= MASTER_CTRL_CLK_SEL_DIS; +- mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT; +- mac_ctrl_data |= MAC_CTRL_DUPLX; +- AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); +- AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); +- AT_WRITE_REG(hw, REG_WOL_CTRL, 0); +- hw->phy_configured = false; /* re-init PHY when resume */ +- } ++ atl1c_power_saving(hw, wufc); + + return 0; + } +@@ -2561,8 +2365,7 @@ static int atl1c_resume(struct device *dev) + struct atl1c_adapter *adapter = netdev_priv(netdev); + + AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0); +- atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE | +- ATL1C_PCIE_PHY_RESET); ++ atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE); + + atl1c_phy_reset(&adapter->hw); + atl1c_reset_mac(&adapter->hw); +@@ -2713,7 +2516,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, + adapter->mii.mdio_read = atl1c_mdio_read; + adapter->mii.mdio_write = atl1c_mdio_write; + adapter->mii.phy_id_mask = 0x1f; +- adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK; ++ adapter->mii.reg_num_mask = MDIO_CTRL_REG_MASK; + netif_napi_add(netdev, &adapter->napi, atl1c_clean, 64); + setup_timer(&adapter->phy_config_timer, atl1c_phy_config, + (unsigned long)adapter); +@@ -2723,8 +2526,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, + dev_err(&pdev->dev, "net device private data init failed\n"); + goto err_sw_init; + } +- atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE | +- ATL1C_PCIE_PHY_RESET); ++ atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE); + + /* Init GPHY as early as possible due to power saving issue */ + atl1c_phy_reset(&adapter->hw); +@@ -2753,7 +2555,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, + dev_dbg(&pdev->dev, "mac address : %pM\n", + adapter->hw.mac_addr); + +- atl1c_hw_set_mac_addr(&adapter->hw); ++ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr); + INIT_WORK(&adapter->common_task, atl1c_common_task); + adapter->work_event = 0; + err = register_netdev(netdev); +@@ -2798,6 +2600,8 @@ static void __devexit atl1c_remove(struct pci_dev *pdev) + struct atl1c_adapter *adapter = netdev_priv(netdev); + + unregister_netdev(netdev); ++ /* restore permanent address */ ++ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.perm_mac_addr); + atl1c_phy_disable(&adapter->hw); + + iounmap(adapter->hw.hw_addr); diff --git a/kernel.spec b/kernel.spec index 3ab2bb299..44dd9dc23 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -795,6 +795,9 @@ Patch22013: ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch #rhbz 818820 Patch22016: dl2k-Clean-up-rio_ioctl.patch +#rhbz 749276 +Patch22018: atl1c_net_next_update-3.3.patch + # END OF PATCH DEFINITIONS %endif @@ -1479,6 +1482,9 @@ ApplyPatch ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch #rhbz 818820 ApplyPatch dl2k-Clean-up-rio_ioctl.patch +#rhbz 749276 +ApplyPatch atl1c_net_next_update-3.3.patch + # END OF PATCH APPLICATIONS %endif @@ -2217,6 +2223,9 @@ fi # and build. %changelog +* Tue May 15 2012 Josh Boyer +- Fixup atl1c register programming (rhbz 749276) + * Mon May 14 2012 Justin M. Forbes 3.3.6-1 - Linux 3.3.6 From 9011ea4427827573904897d53e760563e216c115 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 16 May 2012 16:26:49 -0500 Subject: [PATCH 379/487] rtl818x fix sleeping function called from invalid context (rhbz 795176) --- kernel.spec | 11 ++++- ...function-called-from-invalid-context.patch | 49 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 rtl818x-fix-sleeping-function-called-from-invalid-context.patch diff --git a/kernel.spec b/kernel.spec index 44dd9dc23..329088944 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -798,6 +798,9 @@ Patch22016: dl2k-Clean-up-rio_ioctl.patch #rhbz 749276 Patch22018: atl1c_net_next_update-3.3.patch +#rhbz 795176 +Patch22019: rtl818x-fix-sleeping-function-called-from-invalid-context.patch + # END OF PATCH DEFINITIONS %endif @@ -1485,6 +1488,9 @@ ApplyPatch dl2k-Clean-up-rio_ioctl.patch #rhbz 749276 ApplyPatch atl1c_net_next_update-3.3.patch +#rhbz 795176 +ApplyPatch rtl818x-fix-sleeping-function-called-from-invalid-context.patch + # END OF PATCH APPLICATIONS %endif @@ -2223,6 +2229,9 @@ fi # and build. %changelog +* Wed May 16 2012 Justin M. Forbes 3.3.6-3 +- fix rtl8187: ->brightness_set can not sleep (rhbz 795176) + * Tue May 15 2012 Josh Boyer - Fixup atl1c register programming (rhbz 749276) diff --git a/rtl818x-fix-sleeping-function-called-from-invalid-context.patch b/rtl818x-fix-sleeping-function-called-from-invalid-context.patch new file mode 100644 index 000000000..141fcd201 --- /dev/null +++ b/rtl818x-fix-sleeping-function-called-from-invalid-context.patch @@ -0,0 +1,49 @@ +Fix: + +BUG: sleeping function called from invalid context at kernel/workqueue.c:2547 +in_atomic(): 1, irqs_disabled(): 0, pid: 629, name: wpa_supplicant +2 locks held by wpa_supplicant/629: + #0: (rtnl_mutex){+.+.+.}, at: [] rtnl_lock+0x14/0x20 + #1: (&trigger->leddev_list_lock){.+.?..}, at: [] led_trigger_event+0x21/0x80 +Pid: 629, comm: wpa_supplicant Not tainted 3.3.0-0.rc3.git5.1.fc17.i686 +Call Trace: + [] __might_sleep+0x126/0x1d0 + [] wait_on_work+0x2c/0x1d0 + [] __cancel_work_timer+0x6a/0x120 + [] cancel_delayed_work_sync+0x10/0x20 + [] rtl8187_led_brightness_set+0x82/0xf0 [rtl8187] + [] led_trigger_event+0x5c/0x80 + [] ieee80211_led_radio+0x1d/0x40 [mac80211] + [] ieee80211_stop_device+0x13/0x230 [mac80211] + +Removing _sync is ok, because if led_on work is currently running +it will be finished before led_off work start to perform, since +they are always queued on the same mac80211 local->workqueue. + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=795176 + +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/rtl818x/rtl8187/leds.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wireless/rtl818x/rtl8187/leds.c b/drivers/net/wireless/rtl818x/rtl8187/leds.c +index 2e0de2f..c2d5b49 100644 +--- a/drivers/net/wireless/rtl818x/rtl8187/leds.c ++++ b/drivers/net/wireless/rtl818x/rtl8187/leds.c +@@ -117,7 +117,7 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev, + radio_on = true; + } else if (radio_on) { + radio_on = false; +- cancel_delayed_work_sync(&priv->led_on); ++ cancel_delayed_work(&priv->led_on); + ieee80211_queue_delayed_work(hw, &priv->led_off, 0); + } + } else if (radio_on) { +-- +1.7.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file From 5a132922397c267a1e9692020620c86f6f325561 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 17 May 2012 10:30:44 -0400 Subject: [PATCH 380/487] Fix rtlwifi async firmware load race condition (rhbz 822120) --- kernel.spec | 11 ++- ...race-condition-when-firmware-is-cach.patch | 86 +++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch diff --git a/kernel.spec b/kernel.spec index 329088944..0a9d5add8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -801,6 +801,9 @@ Patch22018: atl1c_net_next_update-3.3.patch #rhbz 795176 Patch22019: rtl818x-fix-sleeping-function-called-from-invalid-context.patch +#rhbz 822120 +Patch22020: rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch + # END OF PATCH DEFINITIONS %endif @@ -1491,6 +1494,9 @@ ApplyPatch atl1c_net_next_update-3.3.patch #rhbz 795176 ApplyPatch rtl818x-fix-sleeping-function-called-from-invalid-context.patch +#rhbz 822120 +ApplyPatch rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch + # END OF PATCH APPLICATIONS %endif @@ -2229,6 +2235,9 @@ fi # and build. %changelog +* Thu May 17 2012 Josh Boyer +- Fix rtlwifi async firmware load race condition (rhbz 822120) + * Wed May 16 2012 Justin M. Forbes 3.3.6-3 - fix rtl8187: ->brightness_set can not sleep (rhbz 795176) diff --git a/rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch b/rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch new file mode 100644 index 000000000..431ec00b6 --- /dev/null +++ b/rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch @@ -0,0 +1,86 @@ +From 574e02abaf816b582685805f0c1150ca9f1f18ee Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Fri, 4 May 2012 08:27:43 -0500 +Subject: [PATCH] rtlwifi: fix for race condition when firmware is cached + +In commit b0302ab, the rtlwifi family of drivers was converted to use +asynchronous firmware loading. Unfortumately, the implementation was +racy, and the ieee80211 routines could be started before rtl_init_core() +was called to setup the data. + +This patch fixes the bug noted in https://bugzilla.kernel.org/show_bug.cgi?id=43187. + +Reported-by: Joshua Roys +Tested-by: Neptune Ning +Signed-off-by: Larry Finger +Cc: Stable [3.3] +Signed-off-by: John W. Linville +--- + drivers/net/wireless/rtlwifi/pci.c | 16 ++++++++-------- + drivers/net/wireless/rtlwifi/usb.c | 10 +++++----- + 2 files changed, 13 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c +index b588ca8..03c400e 100644 +--- a/drivers/net/wireless/rtlwifi/pci.c ++++ b/drivers/net/wireless/rtlwifi/pci.c +@@ -1865,14 +1865,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, + /*like read eeprom and so on */ + rtlpriv->cfg->ops->read_eeprom_info(hw); + +- if (rtlpriv->cfg->ops->init_sw_vars(hw)) { +- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +- ("Can't init_sw_vars.\n")); +- goto fail3; +- } +- +- rtlpriv->cfg->ops->init_sw_leds(hw); +- + /*aspm */ + rtl_pci_init_aspm(hw); + +@@ -1892,6 +1884,14 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, + goto fail3; + } + ++ if (rtlpriv->cfg->ops->init_sw_vars(hw)) { ++ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ++ ("Can't init_sw_vars.\n")); ++ goto fail3; ++ } ++ ++ rtlpriv->cfg->ops->init_sw_leds(hw); ++ + err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c +index 049e207..20b53ae 100644 +--- a/drivers/net/wireless/rtlwifi/usb.c ++++ b/drivers/net/wireless/rtlwifi/usb.c +@@ -970,12 +970,6 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, + rtlpriv->cfg->ops->read_chip_version(hw); + /*like read eeprom and so on */ + rtlpriv->cfg->ops->read_eeprom_info(hw); +- if (rtlpriv->cfg->ops->init_sw_vars(hw)) { +- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +- ("Can't init_sw_vars.\n")); +- goto error_out; +- } +- rtlpriv->cfg->ops->init_sw_leds(hw); + err = _rtl_usb_init(hw); + err = _rtl_usb_init_sw(hw); + /* Init mac80211 sw */ +@@ -985,6 +979,12 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, + ("Can't allocate sw for mac80211.\n")); + goto error_out; + } ++ if (rtlpriv->cfg->ops->init_sw_vars(hw)) { ++ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ++ ("Can't init_sw_vars.\n")); ++ goto error_out; ++ } ++ rtlpriv->cfg->ops->init_sw_leds(hw); + + return 0; + error_out: From d1a2aa668f300c4141af6ae0bd49637e016a45a4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 18 May 2012 09:19:40 -0400 Subject: [PATCH 381/487] Additional fixes for CVE-2011-4131 (rhbz 822874 822869) --- kernel.spec | 12 +- ...beyond-bounds-copy-while-caching-ACL.patch | 85 +++++++++++++ ...ding-past-buffer-when-calling-GETACL.patch | 120 ++++++++++++++++++ 3 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch create mode 100644 nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch diff --git a/kernel.spec b/kernel.spec index 0a9d5add8..0b71fb05c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -727,6 +727,10 @@ Patch4113: NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch Patch4114: NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch Patch4115: NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch +#rhbz 822874 +Patch4116: nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch +Patch4117: nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch + # patches headed upstream Patch12016: disable-i8042-check-on-apple-mac.patch @@ -1343,6 +1347,9 @@ ApplyPatch NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch ApplyPatch NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch ApplyPatch NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch +ApplyPatch nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch +ApplyPatch nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch + # USB # WMI @@ -2235,6 +2242,9 @@ fi # and build. %changelog +* Fri May 18 2012 Josh Boyer +- Additional fixes for CVE-2011-4131 (rhbz 822874 822869) + * Thu May 17 2012 Josh Boyer - Fix rtlwifi async firmware load race condition (rhbz 822120) diff --git a/nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch b/nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch new file mode 100644 index 000000000..2798b0d1d --- /dev/null +++ b/nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch @@ -0,0 +1,85 @@ +From 5794d21ef4639f0e33440927bb903f9598c21e92 Mon Sep 17 00:00:00 2001 +From: Sachin Prabhu +Date: Tue, 17 Apr 2012 14:36:40 +0100 +Subject: [PATCH] Avoid beyond bounds copy while caching ACL + +When attempting to cache ACLs returned from the server, if the bitmap +size + the ACL size is greater than a PAGE_SIZE but the ACL size itself +is smaller than a PAGE_SIZE, we can read past the buffer page boundary. + +Signed-off-by: Sachin Prabhu +Reported-by: Jian Li +Signed-off-by: Trond Myklebust +--- + fs/nfs/nfs4proc.c | 12 +++++------- + fs/nfs/nfs4xdr.c | 2 +- + 2 files changed, 6 insertions(+), 8 deletions(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index f5f125f..2ce0698 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -3628,16 +3628,16 @@ out: + return ret; + } + +-static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t acl_len) ++static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len) + { + struct nfs4_cached_acl *acl; + +- if (buf && acl_len <= PAGE_SIZE) { ++ if (pages && acl_len <= PAGE_SIZE) { + acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL); + if (acl == NULL) + goto out; + acl->cached = 1; +- memcpy(acl->data, buf, acl_len); ++ _copy_from_pages(acl->data, pages, pgbase, acl_len); + } else { + acl = kmalloc(sizeof(*acl), GFP_KERNEL); + if (acl == NULL) +@@ -3670,7 +3670,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu + struct nfs_getaclres res = { + .acl_len = buflen, + }; +- void *resp_buf; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL], + .rpc_argp = &args, +@@ -3705,7 +3704,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu + * the page we send as a guess */ + if (buf == NULL) + res.acl_flags |= NFS4_ACL_LEN_REQUEST; +- resp_buf = page_address(pages[0]); + + dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n", + __func__, buf, buflen, npages, args.acl_len); +@@ -3716,9 +3714,9 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu + + acl_len = res.acl_len - res.acl_data_offset; + if (acl_len > args.acl_len) +- nfs4_write_cached_acl(inode, NULL, acl_len); ++ nfs4_write_cached_acl(inode, NULL, 0, acl_len); + else +- nfs4_write_cached_acl(inode, resp_buf + res.acl_data_offset, ++ nfs4_write_cached_acl(inode, pages, res.acl_data_offset, + acl_len); + if (buf) { + ret = -ERANGE; +diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c +index 9312dd7..203c096 100644 +--- a/fs/nfs/nfs4xdr.c ++++ b/fs/nfs/nfs4xdr.c +@@ -4940,7 +4940,7 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, + res->acl_len = attrlen; + goto out; + } +- dprintk("NFS: acl reply: attrlen %zu > page_len %u\n", ++ dprintk("NFS: acl reply: attrlen %u > page_len %zu\n", + attrlen, page_len); + return -EINVAL; + } +-- +1.7.7.6 + diff --git a/nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch b/nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch new file mode 100644 index 000000000..7122e3b9a --- /dev/null +++ b/nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch @@ -0,0 +1,120 @@ +From 5a00689930ab975fdd1b37b034475017e460cf2a Mon Sep 17 00:00:00 2001 +From: Sachin Prabhu +Date: Tue, 17 Apr 2012 14:35:39 +0100 +Subject: [PATCH] Avoid reading past buffer when calling GETACL + +Bug noticed in commit +bf118a342f10dafe44b14451a1392c3254629a1f + +When calling GETACL, if the size of the bitmap array, the length +attribute and the acl returned by the server is greater than the +allocated buffer(args.acl_len), we can Oops with a General Protection +fault at _copy_from_pages() when we attempt to read past the pages +allocated. + +This patch allocates an extra PAGE for the bitmap and checks to see that +the bitmap + attribute_length + ACLs don't exceed the buffer space +allocated to it. + +Signed-off-by: Sachin Prabhu +Reported-by: Jian Li +[Trond: Fixed a size_t vs unsigned int printk() warning] +Signed-off-by: Trond Myklebust +--- + fs/nfs/nfs4proc.c | 16 ++++++++++------ + fs/nfs/nfs4xdr.c | 18 +++++++++++------- + 2 files changed, 21 insertions(+), 13 deletions(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index 60d5f4c..f5f125f 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -3684,19 +3684,23 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu + if (npages == 0) + npages = 1; + ++ /* Add an extra page to handle the bitmap returned */ ++ npages++; ++ + for (i = 0; i < npages; i++) { + pages[i] = alloc_page(GFP_KERNEL); + if (!pages[i]) + goto out_free; + } +- if (npages > 1) { +- /* for decoding across pages */ +- res.acl_scratch = alloc_page(GFP_KERNEL); +- if (!res.acl_scratch) +- goto out_free; +- } ++ ++ /* for decoding across pages */ ++ res.acl_scratch = alloc_page(GFP_KERNEL); ++ if (!res.acl_scratch) ++ goto out_free; ++ + args.acl_len = npages * PAGE_SIZE; + args.acl_pgbase = 0; ++ + /* Let decode_getfacl know not to fail if the ACL data is larger than + * the page we send as a guess */ + if (buf == NULL) +diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c +index 77fc5f9..9312dd7 100644 +--- a/fs/nfs/nfs4xdr.c ++++ b/fs/nfs/nfs4xdr.c +@@ -4902,11 +4902,19 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, + bitmap[3] = {0}; + struct kvec *iov = req->rq_rcv_buf.head; + int status; ++ size_t page_len = xdr->buf->page_len; + + res->acl_len = 0; + if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) + goto out; ++ + bm_p = xdr->p; ++ res->acl_data_offset = be32_to_cpup(bm_p) + 2; ++ res->acl_data_offset <<= 2; ++ /* Check if the acl data starts beyond the allocated buffer */ ++ if (res->acl_data_offset > page_len) ++ return -ERANGE; ++ + if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) + goto out; + if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) +@@ -4916,28 +4924,24 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, + return -EIO; + if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { + size_t hdrlen; +- u32 recvd; + + /* The bitmap (xdr len + bitmaps) and the attr xdr len words + * are stored with the acl data to handle the problem of + * variable length bitmaps.*/ + xdr->p = bm_p; +- res->acl_data_offset = be32_to_cpup(bm_p) + 2; +- res->acl_data_offset <<= 2; + + /* We ignore &savep and don't do consistency checks on + * the attr length. Let userspace figure it out.... */ + hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; + attrlen += res->acl_data_offset; +- recvd = req->rq_rcv_buf.len - hdrlen; +- if (attrlen > recvd) { ++ if (attrlen > page_len) { + if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { + /* getxattr interface called with a NULL buf */ + res->acl_len = attrlen; + goto out; + } +- dprintk("NFS: acl reply: attrlen %u > recvd %u\n", +- attrlen, recvd); ++ dprintk("NFS: acl reply: attrlen %zu > page_len %u\n", ++ attrlen, page_len); + return -EINVAL; + } + xdr_read_pages(xdr, attrlen); +-- +1.7.7.6 + From 60baf10f8cf63454208297dbe4d10761548c42d5 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 22 May 2012 08:43:51 -0500 Subject: [PATCH 382/487] Linux 3.3.7 --- dl2k-Clean-up-rio_ioctl.patch | 120 ------------------ dvbs-fix-zigzag.patch | 15 --- kernel.spec | 22 +--- ...beyond-bounds-copy-while-caching-ACL.patch | 85 ------------- ...ding-past-buffer-when-calling-GETACL.patch | 120 ------------------ sources | 2 +- 6 files changed, 6 insertions(+), 358 deletions(-) delete mode 100644 dl2k-Clean-up-rio_ioctl.patch delete mode 100644 dvbs-fix-zigzag.patch delete mode 100644 nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch delete mode 100644 nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch diff --git a/dl2k-Clean-up-rio_ioctl.patch b/dl2k-Clean-up-rio_ioctl.patch deleted file mode 100644 index 2ef4eed6d..000000000 --- a/dl2k-Clean-up-rio_ioctl.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 1bb57e940e1958e40d51f2078f50c3a96a9b2d75 Mon Sep 17 00:00:00 2001 -From: Jeff Mahoney -Date: Wed, 25 Apr 2012 14:32:09 +0000 -Subject: [PATCH] dl2k: Clean up rio_ioctl - -The dl2k driver's rio_ioctl call has a few issues: -- No permissions checking -- Implements SIOCGMIIREG and SIOCGMIIREG using the SIOCDEVPRIVATE numbers -- Has a few ioctls that may have been used for debugging at one point - but have no place in the kernel proper. - -This patch removes all but the MII ioctls, renumbers them to use the -standard ones, and adds the proper permission check for SIOCSMIIREG. - -We can also get rid of the dl2k-specific struct mii_data in favor of -the generic struct mii_ioctl_data. - -Since we have the phyid on hand, we can add the SIOCGMIIPHY ioctl too. - -Most of the MII code for the driver could probably be converted to use -the generic MII library but I don't have a device to test the results. - -Reported-by: Stephan Mueller -Signed-off-by: Jeff Mahoney -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/dlink/dl2k.c | 52 ++++++------------------------------ - drivers/net/ethernet/dlink/dl2k.h | 7 ----- - 2 files changed, 9 insertions(+), 50 deletions(-) - -diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c -index b2dc2c8..2e09edb 100644 ---- a/drivers/net/ethernet/dlink/dl2k.c -+++ b/drivers/net/ethernet/dlink/dl2k.c -@@ -1259,55 +1259,21 @@ rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) - { - int phy_addr; - struct netdev_private *np = netdev_priv(dev); -- struct mii_data *miidata = (struct mii_data *) &rq->ifr_ifru; -- -- struct netdev_desc *desc; -- int i; -+ struct mii_ioctl_data *miidata = if_mii(rq); - - phy_addr = np->phy_addr; - switch (cmd) { -- case SIOCDEVPRIVATE: -- break; -- -- case SIOCDEVPRIVATE + 1: -- miidata->out_value = mii_read (dev, phy_addr, miidata->reg_num); -+ case SIOCGMIIPHY: -+ miidata->phy_id = phy_addr; - break; -- case SIOCDEVPRIVATE + 2: -- mii_write (dev, phy_addr, miidata->reg_num, miidata->in_value); -+ case SIOCGMIIREG: -+ miidata->val_out = mii_read (dev, phy_addr, miidata->reg_num); - break; -- case SIOCDEVPRIVATE + 3: -- break; -- case SIOCDEVPRIVATE + 4: -- break; -- case SIOCDEVPRIVATE + 5: -- netif_stop_queue (dev); -+ case SIOCSMIIREG: -+ if (!capable(CAP_NET_ADMIN)) -+ return -EPERM; -+ mii_write (dev, phy_addr, miidata->reg_num, miidata->val_in); - break; -- case SIOCDEVPRIVATE + 6: -- netif_wake_queue (dev); -- break; -- case SIOCDEVPRIVATE + 7: -- printk -- ("tx_full=%x cur_tx=%lx old_tx=%lx cur_rx=%lx old_rx=%lx\n", -- netif_queue_stopped(dev), np->cur_tx, np->old_tx, np->cur_rx, -- np->old_rx); -- break; -- case SIOCDEVPRIVATE + 8: -- printk("TX ring:\n"); -- for (i = 0; i < TX_RING_SIZE; i++) { -- desc = &np->tx_ring[i]; -- printk -- ("%02x:cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x", -- i, -- (u32) (np->tx_ring_dma + i * sizeof (*desc)), -- (u32)le64_to_cpu(desc->next_desc), -- (u32)le64_to_cpu(desc->status), -- (u32)(le64_to_cpu(desc->fraginfo) >> 32), -- (u32)le64_to_cpu(desc->fraginfo)); -- printk ("\n"); -- } -- printk ("\n"); -- break; -- - default: - return -EOPNOTSUPP; - } -diff --git a/drivers/net/ethernet/dlink/dl2k.h b/drivers/net/ethernet/dlink/dl2k.h -index ba0adca..30c2da3 100644 ---- a/drivers/net/ethernet/dlink/dl2k.h -+++ b/drivers/net/ethernet/dlink/dl2k.h -@@ -365,13 +365,6 @@ struct ioctl_data { - char *data; - }; - --struct mii_data { -- __u16 reserved; -- __u16 reg_num; -- __u16 in_value; -- __u16 out_value; --}; -- - /* The Rx and Tx buffer descriptors. */ - struct netdev_desc { - __le64 next_desc; --- -1.7.7.6 - diff --git a/dvbs-fix-zigzag.patch b/dvbs-fix-zigzag.patch deleted file mode 100644 index 4bc9daaf4..000000000 --- a/dvbs-fix-zigzag.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c -index 39696c6..de7dc29 100644 ---- a/drivers/media/dvb/dvb-core/dvb_frontend.c -+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c -@@ -1898,6 +1898,10 @@ static int dtv_set_frontend(struct dvb_frontend *fe) - } else { - /* default values */ - switch (c->delivery_system) { -+ case SYS_DVBS: -+ case SYS_DVBS2: -+ case SYS_ISDBS: -+ case SYS_TURBO: - case SYS_DVBC_ANNEX_A: - case SYS_DVBC_ANNEX_C: - fepriv->min_delay = HZ / 20; diff --git a/kernel.spec b/kernel.spec index 0b71fb05c..f797996e5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 5 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 6 +%define stable_update 7 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -710,7 +710,6 @@ Patch2802: linux-2.6-silence-acpi-blacklist.patch # add-poll-requested-events.patch was added for 3.4 Patch2900: add-poll-requested-events.patch Patch2901: drivers-media-update.patch -Patch2902: dvbs-fix-zigzag.patch # fs fixes @@ -727,10 +726,6 @@ Patch4113: NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch Patch4114: NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch Patch4115: NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch -#rhbz 822874 -Patch4116: nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch -Patch4117: nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch - # patches headed upstream Patch12016: disable-i8042-check-on-apple-mac.patch @@ -796,9 +791,6 @@ Patch22007: macvtap-zerocopy-validate-vector-length.patch #rhbz 817298 Patch22013: ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch -#rhbz 818820 -Patch22016: dl2k-Clean-up-rio_ioctl.patch - #rhbz 749276 Patch22018: atl1c_net_next_update-3.3.patch @@ -1347,9 +1339,6 @@ ApplyPatch NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch ApplyPatch NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch ApplyPatch NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch -ApplyPatch nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch -ApplyPatch nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch - # USB # WMI @@ -1432,7 +1421,6 @@ ApplyPatch quite-apm.patch # Media (V4L/DVB/IR) updates/fixes/experimental drivers # apply if non-empty ApplyPatch add-poll-requested-events.patch -ApplyPatch dvbs-fix-zigzag.patch ApplyOptionalPatch drivers-media-update.patch # Patches headed upstream @@ -1492,9 +1480,6 @@ ApplyPatch macvtap-zerocopy-validate-vector-length.patch #rhbz 817298 ApplyPatch ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch -#rhbz 818820 -ApplyPatch dl2k-Clean-up-rio_ioctl.patch - #rhbz 749276 ApplyPatch atl1c_net_next_update-3.3.patch @@ -2242,6 +2227,9 @@ fi # and build. %changelog +* Mon May 21 2012 Justin M. Forbes 3.3.7-1 +- Linux 3.3.7 + * Fri May 18 2012 Josh Boyer - Additional fixes for CVE-2011-4131 (rhbz 822874 822869) diff --git a/nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch b/nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch deleted file mode 100644 index 2798b0d1d..000000000 --- a/nfs-Avoid-beyond-bounds-copy-while-caching-ACL.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 5794d21ef4639f0e33440927bb903f9598c21e92 Mon Sep 17 00:00:00 2001 -From: Sachin Prabhu -Date: Tue, 17 Apr 2012 14:36:40 +0100 -Subject: [PATCH] Avoid beyond bounds copy while caching ACL - -When attempting to cache ACLs returned from the server, if the bitmap -size + the ACL size is greater than a PAGE_SIZE but the ACL size itself -is smaller than a PAGE_SIZE, we can read past the buffer page boundary. - -Signed-off-by: Sachin Prabhu -Reported-by: Jian Li -Signed-off-by: Trond Myklebust ---- - fs/nfs/nfs4proc.c | 12 +++++------- - fs/nfs/nfs4xdr.c | 2 +- - 2 files changed, 6 insertions(+), 8 deletions(-) - -diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c -index f5f125f..2ce0698 100644 ---- a/fs/nfs/nfs4proc.c -+++ b/fs/nfs/nfs4proc.c -@@ -3628,16 +3628,16 @@ out: - return ret; - } - --static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t acl_len) -+static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len) - { - struct nfs4_cached_acl *acl; - -- if (buf && acl_len <= PAGE_SIZE) { -+ if (pages && acl_len <= PAGE_SIZE) { - acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL); - if (acl == NULL) - goto out; - acl->cached = 1; -- memcpy(acl->data, buf, acl_len); -+ _copy_from_pages(acl->data, pages, pgbase, acl_len); - } else { - acl = kmalloc(sizeof(*acl), GFP_KERNEL); - if (acl == NULL) -@@ -3670,7 +3670,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu - struct nfs_getaclres res = { - .acl_len = buflen, - }; -- void *resp_buf; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL], - .rpc_argp = &args, -@@ -3705,7 +3704,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu - * the page we send as a guess */ - if (buf == NULL) - res.acl_flags |= NFS4_ACL_LEN_REQUEST; -- resp_buf = page_address(pages[0]); - - dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n", - __func__, buf, buflen, npages, args.acl_len); -@@ -3716,9 +3714,9 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu - - acl_len = res.acl_len - res.acl_data_offset; - if (acl_len > args.acl_len) -- nfs4_write_cached_acl(inode, NULL, acl_len); -+ nfs4_write_cached_acl(inode, NULL, 0, acl_len); - else -- nfs4_write_cached_acl(inode, resp_buf + res.acl_data_offset, -+ nfs4_write_cached_acl(inode, pages, res.acl_data_offset, - acl_len); - if (buf) { - ret = -ERANGE; -diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c -index 9312dd7..203c096 100644 ---- a/fs/nfs/nfs4xdr.c -+++ b/fs/nfs/nfs4xdr.c -@@ -4940,7 +4940,7 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, - res->acl_len = attrlen; - goto out; - } -- dprintk("NFS: acl reply: attrlen %zu > page_len %u\n", -+ dprintk("NFS: acl reply: attrlen %u > page_len %zu\n", - attrlen, page_len); - return -EINVAL; - } --- -1.7.7.6 - diff --git a/nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch b/nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch deleted file mode 100644 index 7122e3b9a..000000000 --- a/nfs-Avoid-reading-past-buffer-when-calling-GETACL.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 5a00689930ab975fdd1b37b034475017e460cf2a Mon Sep 17 00:00:00 2001 -From: Sachin Prabhu -Date: Tue, 17 Apr 2012 14:35:39 +0100 -Subject: [PATCH] Avoid reading past buffer when calling GETACL - -Bug noticed in commit -bf118a342f10dafe44b14451a1392c3254629a1f - -When calling GETACL, if the size of the bitmap array, the length -attribute and the acl returned by the server is greater than the -allocated buffer(args.acl_len), we can Oops with a General Protection -fault at _copy_from_pages() when we attempt to read past the pages -allocated. - -This patch allocates an extra PAGE for the bitmap and checks to see that -the bitmap + attribute_length + ACLs don't exceed the buffer space -allocated to it. - -Signed-off-by: Sachin Prabhu -Reported-by: Jian Li -[Trond: Fixed a size_t vs unsigned int printk() warning] -Signed-off-by: Trond Myklebust ---- - fs/nfs/nfs4proc.c | 16 ++++++++++------ - fs/nfs/nfs4xdr.c | 18 +++++++++++------- - 2 files changed, 21 insertions(+), 13 deletions(-) - -diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c -index 60d5f4c..f5f125f 100644 ---- a/fs/nfs/nfs4proc.c -+++ b/fs/nfs/nfs4proc.c -@@ -3684,19 +3684,23 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu - if (npages == 0) - npages = 1; - -+ /* Add an extra page to handle the bitmap returned */ -+ npages++; -+ - for (i = 0; i < npages; i++) { - pages[i] = alloc_page(GFP_KERNEL); - if (!pages[i]) - goto out_free; - } -- if (npages > 1) { -- /* for decoding across pages */ -- res.acl_scratch = alloc_page(GFP_KERNEL); -- if (!res.acl_scratch) -- goto out_free; -- } -+ -+ /* for decoding across pages */ -+ res.acl_scratch = alloc_page(GFP_KERNEL); -+ if (!res.acl_scratch) -+ goto out_free; -+ - args.acl_len = npages * PAGE_SIZE; - args.acl_pgbase = 0; -+ - /* Let decode_getfacl know not to fail if the ACL data is larger than - * the page we send as a guess */ - if (buf == NULL) -diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c -index 77fc5f9..9312dd7 100644 ---- a/fs/nfs/nfs4xdr.c -+++ b/fs/nfs/nfs4xdr.c -@@ -4902,11 +4902,19 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, - bitmap[3] = {0}; - struct kvec *iov = req->rq_rcv_buf.head; - int status; -+ size_t page_len = xdr->buf->page_len; - - res->acl_len = 0; - if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) - goto out; -+ - bm_p = xdr->p; -+ res->acl_data_offset = be32_to_cpup(bm_p) + 2; -+ res->acl_data_offset <<= 2; -+ /* Check if the acl data starts beyond the allocated buffer */ -+ if (res->acl_data_offset > page_len) -+ return -ERANGE; -+ - if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) - goto out; - if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) -@@ -4916,28 +4924,24 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, - return -EIO; - if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { - size_t hdrlen; -- u32 recvd; - - /* The bitmap (xdr len + bitmaps) and the attr xdr len words - * are stored with the acl data to handle the problem of - * variable length bitmaps.*/ - xdr->p = bm_p; -- res->acl_data_offset = be32_to_cpup(bm_p) + 2; -- res->acl_data_offset <<= 2; - - /* We ignore &savep and don't do consistency checks on - * the attr length. Let userspace figure it out.... */ - hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; - attrlen += res->acl_data_offset; -- recvd = req->rq_rcv_buf.len - hdrlen; -- if (attrlen > recvd) { -+ if (attrlen > page_len) { - if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { - /* getxattr interface called with a NULL buf */ - res->acl_len = attrlen; - goto out; - } -- dprintk("NFS: acl reply: attrlen %u > recvd %u\n", -- attrlen, recvd); -+ dprintk("NFS: acl reply: attrlen %zu > page_len %u\n", -+ attrlen, page_len); - return -EINVAL; - } - xdr_read_pages(xdr, attrlen); --- -1.7.7.6 - diff --git a/sources b/sources index 755d90dc6..03cb562cf 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz -a7f67e9c491403906e4bb475de194631 patch-3.3.6.xz +622a3b43238559aeb778279969631260 patch-3.3.7.xz From 11891dbd2445cd144959ee576b0559032f63d2cb Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 24 May 2012 07:43:48 -0400 Subject: [PATCH 383/487] CVE-2012-2372 mm: 32bit PAE pmd walk vs populate SMP race (rhbz 822821 822825) --- kernel.spec | 12 +- ...k-vs-pmd_populate-SMP-race-condition.patch | 272 ++++++++++++++++++ 2 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch diff --git a/kernel.spec b/kernel.spec index f797996e5..584440bce 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -800,6 +800,10 @@ Patch22019: rtl818x-fix-sleeping-function-called-from-invalid-context.patch #rhbz 822120 Patch22020: rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch +#rhbz 822825 822821 CVE-2012-2372 +Patch22021: mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch + + # END OF PATCH DEFINITIONS %endif @@ -1489,6 +1493,9 @@ ApplyPatch rtl818x-fix-sleeping-function-called-from-invalid-context.patch #rhbz 822120 ApplyPatch rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch +#rhbz 822825 822821 CVE-2012-2372 +ApplyPatch mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch + # END OF PATCH APPLICATIONS %endif @@ -2227,6 +2234,9 @@ fi # and build. %changelog +* Thu May 24 2012 Josh Boyer +- CVE-2012-2372 mm: 32bit PAE pmd walk vs populate SMP race (rhbz 822821 822825) + * Mon May 21 2012 Justin M. Forbes 3.3.7-1 - Linux 3.3.7 diff --git a/mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch b/mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch new file mode 100644 index 000000000..49ff98a62 --- /dev/null +++ b/mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch @@ -0,0 +1,272 @@ +Path: news.gmane.org!not-for-mail +From: Andrea Arcangeli +Newsgroups: gmane.linux.kernel.mm +Subject: [PATCH] mm: pmd_read_atomic: fix 32bit PAE pmd walk vs pmd_populate SMP race condition +Date: Thu, 24 May 2012 01:39:01 +0200 +Lines: 208 +Approved: news@gmane.org +Message-ID: <1337816341-30743-1-git-send-email-aarcange@redhat.com> +References: <20120518230028.GF32479@redhat.com> +NNTP-Posting-Host: plane.gmane.org +X-Trace: dough.gmane.org 1337816354 18906 80.91.229.3 (23 May 2012 23:39:14 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Wed, 23 May 2012 23:39:14 +0000 (UTC) +Cc: Andrew Morton , Mel Gorman , + Hugh Dickins , Larry Woodman , + Petr Matousek , + Ulrich Obergfell , Rik van Riel +To: linux-mm@kvack.org +Original-X-From: owner-linux-mm@kvack.org Thu May 24 01:39:12 2012 +Return-path: +Envelope-to: glkm-linux-mm-2@m.gmane.org +Original-Received: from kanga.kvack.org ([205.233.56.17]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1SXL94-0002ub-3P + for glkm-linux-mm-2@m.gmane.org; Thu, 24 May 2012 01:39:10 +0200 +Original-Received: by kanga.kvack.org (Postfix) + id 1684A6B0083; Wed, 23 May 2012 19:39:09 -0400 (EDT) +Delivered-To: linux-mm-outgoing@kvack.org +Original-Received: by kanga.kvack.org (Postfix, from userid 40) + id 080DD6B0092; Wed, 23 May 2012 19:39:08 -0400 (EDT) +X-Original-To: int-list-linux-mm@kvack.org +Delivered-To: int-list-linux-mm@kvack.org +Original-Received: by kanga.kvack.org (Postfix, from userid 63042) + id C84046B00E7; Wed, 23 May 2012 19:39:08 -0400 (EDT) +X-Original-To: linux-mm@kvack.org +Delivered-To: linux-mm@kvack.org +Original-Received: from psmtp.com (na3sys010amx119.postini.com [74.125.245.119]) + by kanga.kvack.org (Postfix) with SMTP id 0B2DC6B0083 + for ; Wed, 23 May 2012 19:39:07 -0400 (EDT) +Original-Received: from mx1.redhat.com ([209.132.183.28]) (using TLSv1) by na3sys010amx119.postini.com ([74.125.244.10]) with SMTP; + Wed, 23 May 2012 18:39:08 CDT +Original-Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q4NNd3dP002492 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Wed, 23 May 2012 19:39:03 -0400 +Original-Received: from random.random (ovpn-113-72.phx2.redhat.com [10.3.113.72]) + by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q4NNd1P7012233; + Wed, 23 May 2012 19:39:02 -0400 +In-Reply-To: <20120518230028.GF32479@redhat.com> +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 +X-pstn-neptune: 0/0/0.00/0 +X-pstn-levels: (S:99.90000/99.90000 CV:99.9000 FC:95.5390 LC:95.5390 R:95.9108 P:95.9108 M:97.0282 C:98.6951 ) +X-pstn-dkim: 0 skipped:not-enabled +X-pstn-settings: 3 (1.0000:1.0000) s cv gt3 gt2 gt1 r p m c +X-pstn-addresses: from [db-null] +X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.2 +Original-Sender: owner-linux-mm@kvack.org +Precedence: bulk +X-Loop: owner-majordomo@kvack.org +List-ID: +Xref: news.gmane.org gmane.linux.kernel.mm:78936 +Archived-At: + +When holding the mmap_sem for reading, pmd_offset_map_lock should only +run on a pmd_t that has been read atomically from the pmdp +pointer, otherwise we may read only half of it leading to this crash. + +PID: 11679 TASK: f06e8000 CPU: 3 COMMAND: "do_race_2_panic" + #0 [f06a9dd8] crash_kexec at c049b5ec + #1 [f06a9e2c] oops_end at c083d1c2 + #2 [f06a9e40] no_context at c0433ded + #3 [f06a9e64] bad_area_nosemaphore at c043401a + #4 [f06a9e6c] __do_page_fault at c0434493 + #5 [f06a9eec] do_page_fault at c083eb45 + #6 [f06a9f04] error_code (via page_fault) at c083c5d5 + EAX: 01fb470c EBX: fff35000 ECX: 00000003 EDX: 00000100 EBP: + 00000000 + DS: 007b ESI: 9e201000 ES: 007b EDI: 01fb4700 GS: 00e0 + CS: 0060 EIP: c083bc14 ERR: ffffffff EFLAGS: 00010246 + #7 [f06a9f38] _spin_lock at c083bc14 + #8 [f06a9f44] sys_mincore at c0507b7d + #9 [f06a9fb0] system_call at c083becd + start len + EAX: ffffffda EBX: 9e200000 ECX: 00001000 EDX: 6228537f + DS: 007b ESI: 00000000 ES: 007b EDI: 003d0f00 + SS: 007b ESP: 62285354 EBP: 62285388 GS: 0033 + CS: 0073 EIP: 00291416 ERR: 000000da EFLAGS: 00000286 + +This should be a longstanding bug affecting x86 32bit PAE without +THP. Only archs with 64bit large pmd_t and 32bit unsigned long should +be affected. + +With THP enabled the barrier() in +pmd_none_or_trans_huge_or_clear_bad() would partly hide the bug when +the pmd transition from none to stable, by forcing a re-read of the +*pmd in pmd_offset_map_lock, but when THP is enabled a new set of +problem arises by the fact could then transition freely in any of the +none, pmd_trans_huge or pmd_trans_stable states. So making the barrier +in pmd_none_or_trans_huge_or_clear_bad() unconditional isn't good idea +and it would be a flakey solution. + +This should be fully fixed by introducing a pmd_read_atomic that reads +the pmd in order with THP disabled, or by reading the pmd atomically +with cmpxchg8b with THP enabled. + +Luckily this new race condition only triggers in the places that must +already be covered by pmd_none_or_trans_huge_or_clear_bad() so the fix +is localized there but this bug is not related to THP. + +NOTE: this can trigger on x86 32bit systems with PAE enabled with more +than 4G of ram, otherwise the high part of the pmd will never risk to +be truncated because it would be zero at all times, in turn so hiding +the SMP race. + +This bug was discovered and fully debugged by Ulrich, quote: + +---- +[..] +pmd_none_or_trans_huge_or_clear_bad() loads the content of edx and +eax. + + 496 static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t + *pmd) + 497 { + 498 /* depend on compiler for an atomic pmd read */ + 499 pmd_t pmdval = *pmd; + + // edi = pmd pointer +0xc0507a74 : mov 0x8(%esp),%edi +... + // edx = PTE page table high address +0xc0507a84 : mov 0x4(%edi),%edx +... + // eax = PTE page table low address +0xc0507a8e : mov (%edi),%eax + +[..] + +Please note that the PMD is not read atomically. These are two "mov" +instructions where the high order bits of the PMD entry are fetched +first. Hence, the above machine code is prone to the following race. + +- The PMD entry {high|low} is 0x0000000000000000. + The "mov" at 0xc0507a84 loads 0x00000000 into edx. + +- A page fault (on another CPU) sneaks in between the two "mov" + instructions and instantiates the PMD. + +- The PMD entry {high|low} is now 0x00000003fda38067. + The "mov" at 0xc0507a8e loads 0xfda38067 into eax. +---- + +Reported-by: Ulrich Obergfell +Signed-off-by: Andrea Arcangeli +--- + arch/x86/include/asm/pgtable-3level.h | 50 +++++++++++++++++++++++++++++++++ + include/asm-generic/pgtable.h | 22 +++++++++++++- + 2 files changed, 70 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h +index effff47..43876f1 100644 +--- a/arch/x86/include/asm/pgtable-3level.h ++++ b/arch/x86/include/asm/pgtable-3level.h +@@ -31,6 +31,56 @@ static inline void native_set_pte(pte_t *ptep, pte_t pte) + ptep->pte_low = pte.pte_low; + } + ++#define pmd_read_atomic pmd_read_atomic ++/* ++ * pte_offset_map_lock on 32bit PAE kernels was reading the pmd_t with ++ * a "*pmdp" dereference done by gcc. Problem is, in certain places ++ * where pte_offset_map_lock is called, concurrent page faults are ++ * allowed, if the mmap_sem is hold for reading. An example is mincore ++ * vs page faults vs MADV_DONTNEED. On the page fault side ++ * pmd_populate rightfully does a set_64bit, but if we're reading the ++ * pmd_t with a "*pmdp" on the mincore side, a SMP race can happen ++ * because gcc will not read the 64bit of the pmd atomically. To fix ++ * this all places running pmd_offset_map_lock() while holding the ++ * mmap_sem in read mode, shall read the pmdp pointer using this ++ * function to know if the pmd is null nor not, and in turn to know if ++ * they can run pmd_offset_map_lock or pmd_trans_huge or other pmd ++ * operations. ++ * ++ * Without THP if the mmap_sem is hold for reading, the ++ * pmd can only transition from null to not null while pmd_read_atomic runs. ++ * So there's no need of literally reading it atomically. ++ * ++ * With THP if the mmap_sem is hold for reading, the pmd can become ++ * THP or null or point to a pte (and in turn become "stable") at any ++ * time under pmd_read_atomic, so it's mandatory to read it atomically ++ * with cmpxchg8b. ++ */ ++#ifndef CONFIG_TRANSPARENT_HUGEPAGE ++static inline pmd_t pmd_read_atomic(pmd_t *pmdp) ++{ ++ pmdval_t ret; ++ u32 *tmp = (u32 *)pmdp; ++ ++ ret = (pmdval_t) (*tmp); ++ if (ret) { ++ /* ++ * If the low part is null, we must not read the high part ++ * or we can end up with a partial pmd. ++ */ ++ smp_rmb(); ++ ret |= ((pmdval_t)*(tmp + 1)) << 32; ++ } ++ ++ return (pmd_t) { ret }; ++} ++#else /* CONFIG_TRANSPARENT_HUGEPAGE */ ++static inline pmd_t pmd_read_atomic(pmd_t *pmdp) ++{ ++ return (pmd_t) { atomic64_read((atomic64_t *)pmdp) }; ++} ++#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ ++ + static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) + { + set_64bit((unsigned long long *)(ptep), native_pte_val(pte)); +diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h +index 125c54e..fa596d9 100644 +--- a/include/asm-generic/pgtable.h ++++ b/include/asm-generic/pgtable.h +@@ -446,6 +446,18 @@ static inline int pmd_write(pmd_t pmd) + #endif /* __HAVE_ARCH_PMD_WRITE */ + #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ + ++#ifndef pmd_read_atomic ++static inline pmd_t pmd_read_atomic(pmd_t *pmdp) ++{ ++ /* ++ * Depend on compiler for an atomic pmd read. NOTE: this is ++ * only going to work, if the pmdval_t isn't larger than ++ * an unsigned long. ++ */ ++ return *pmdp; ++} ++#endif ++ + /* + * This function is meant to be used by sites walking pagetables with + * the mmap_sem hold in read mode to protect against MADV_DONTNEED and +@@ -459,11 +471,17 @@ static inline int pmd_write(pmd_t pmd) + * undefined so behaving like if the pmd was none is safe (because it + * can return none anyway). The compiler level barrier() is critically + * important to compute the two checks atomically on the same pmdval. ++ * ++ * For 32bit kernels with a 64bit large pmd_t this automatically takes ++ * care of reading the pmd atomically to avoid SMP race conditions ++ * against pmd_populate() when the mmap_sem is hold for reading by the ++ * caller (a special atomic read not done by "gcc" as in the generic ++ * version above, is also needed when THP is disabled because the page ++ * fault can populate the pmd from under us). + */ + static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd) + { +- /* depend on compiler for an atomic pmd read */ +- pmd_t pmdval = *pmd; ++ pmd_t pmdval = pmd_read_atomic(pmd); + /* + * The barrier will stabilize the pmdval in a register or on + * the stack so that it will stop changing under the code. + +-- +To unsubscribe, send a message with 'unsubscribe linux-mm' in +the body to majordomo@kvack.org. For more info on Linux MM, +see: http://www.linux-mm.org/ . +Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ +Don't email: email@kvack.org + From 8ae7ce1b01f718971a56dcc677a1c6f7aaa0749b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 25 May 2012 08:13:45 -0300 Subject: [PATCH 384/487] Don't customise tuners or frontends The option to customise tuners/frontends are there to allow embedded systems or advanced users that compile their own kernels to disable I2C modules that aren't used by their specific device. When those options are not selected, the building system will automatically select the modules that are needed by each DVB device. The end result is that dummy frontends used only for testing, like DVB_DUMMY_FE won't be selected. Also, when newer frontends are added (and they're added all the times), the new ones will automatically be selected, if the bridge drivers that support them are selected. This also makes the configuration simpler to understand. Signed-off-by: Mauro Carvalho Chehab --- config-generic | 108 ++----------------------------------------------- kernel.spec | 3 ++ 2 files changed, 6 insertions(+), 105 deletions(-) diff --git a/config-generic b/config-generic index 543dc6257..7474f897f 100644 --- a/config-generic +++ b/config-generic @@ -2687,26 +2687,7 @@ CONFIG_RADIO_WL1273=m CONFIG_RADIO_WL128X=m CONFIG_MEDIA_ATTACH=y -CONFIG_MEDIA_TUNER_CUSTOMISE=y -CONFIG_MEDIA_TUNER_SIMPLE=m -CONFIG_MEDIA_TUNER_TDA8290=m -CONFIG_MEDIA_TUNER_TEA5761=m -CONFIG_MEDIA_TUNER_TEA5767=m -CONFIG_MEDIA_TUNER_MT20XX=m -CONFIG_MEDIA_TUNER_MT2060=m -CONFIG_MEDIA_TUNER_MT2063=m -CONFIG_MEDIA_TUNER_MT2266=m -CONFIG_MEDIA_TUNER_MT2131=m -CONFIG_MEDIA_TUNER_QT1010=m -CONFIG_MEDIA_TUNER_XC2028=m -CONFIG_MEDIA_TUNER_XC5000=m -CONFIG_MEDIA_TUNER_XC4000=m -CONFIG_MEDIA_TUNER_MXL5005S=m -CONFIG_MEDIA_TUNER_MXL5007T=m -CONFIG_MEDIA_TUNER_MC44S803=m -CONFIG_MEDIA_TUNER_MAX2165=m -CONFIG_MEDIA_TUNER_TDA18218=m -CONFIG_MEDIA_TUNER_TDA18212=m +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set # # Digital Video Broadcasting Devices @@ -2717,81 +2698,13 @@ CONFIG_DVB_NET=y CONFIG_DVB_MAX_ADAPTERS=8 CONFIG_DVB_DYNAMIC_MINORS=y -CONFIG_DVB_FE_CUSTOMISE=y -CONFIG_DVB_STB0899=m -CONFIG_DVB_STB6100=m -CONFIG_DVB_STV090x=m -CONFIG_DVB_STV6110x=m -CONFIG_DVB_DRXK=m -CONFIG_DVB_TDA18271C2DD=m -CONFIG_DVB_CX24110=m -CONFIG_DVB_CX24123=m -CONFIG_DVB_MT312=m -CONFIG_DVB_ZL10036=m -CONFIG_DVB_ZL10039=m -CONFIG_DVB_S5H1420=m -CONFIG_DVB_STV0288=m -CONFIG_DVB_STB6000=m -CONFIG_DVB_STV6110=m -CONFIG_DVB_STV0900=m -CONFIG_DVB_TDA8083=m -CONFIG_DVB_TDA10086=m -CONFIG_DVB_TDA8261=m -CONFIG_DVB_VES1X93=m -CONFIG_DVB_TUNER_ITD1000=m -CONFIG_DVB_TUNER_CX24113=m -CONFIG_DVB_TDA826X=m -CONFIG_DVB_TUA6100=m -CONFIG_DVB_CX24116=m -CONFIG_DVB_SI21XX=m -CONFIG_DVB_DS3000=m -CONFIG_DVB_SP8870=m -CONFIG_DVB_SP887X=m -CONFIG_DVB_CX22700=m -CONFIG_DVB_CX22702=m -CONFIG_DVB_S5H1432=m -CONFIG_DVB_IX2505V=m -CONFIG_DVB_L64781=m -CONFIG_DVB_NXT6000=m -CONFIG_DVB_MT352=m -CONFIG_DVB_DIB7000M=m -CONFIG_DVB_DIB7000P=m -CONFIG_DVB_TDA10048=m -CONFIG_DVB_VES1820=m -CONFIG_DVB_TDA10021=m -CONFIG_DVB_TDA10023=m -CONFIG_DVB_STV0297=m -CONFIG_DVB_NXT200X=m -CONFIG_DVB_OR51211=m -CONFIG_DVB_OR51132=m -CONFIG_DVB_BCM3510=m -CONFIG_DVB_LGDT330X=m -CONFIG_DVB_LGDT3305=m -CONFIG_DVB_S5H1409=m -CONFIG_DVB_AU8522=m -CONFIG_DVB_S5H1411=m -CONFIG_DVB_DIB8000=m -CONFIG_DVB_TUNER_DIB0070=m -CONFIG_DVB_TUNER_DIB0090=m -CONFIG_DVB_LNBP21=m -CONFIG_DVB_ISL6421=m -CONFIG_DVB_ISL6423=m -CONFIG_DVB_LGS8GXX=m -CONFIG_DVB_ATBM8830=m -CONFIG_DVB_TDA665x=m -CONFIG_DVB_STV0299=m -CONFIG_DVB_MB86A16=m -CONFIG_DVB_DRXD=m -CONFIG_DVB_CXD2820R=m +# CONFIG_DVB_FE_CUSTOMISE is not set CONFIG_DVB_USB_AZ6007=m CONFIG_DVB_USB_RTL28XXU=m CONFIG_DVB_USB_AF9035=m -CONFIG_DVB_RTL2830=m -CONFIG_DVB_M88RS2000=m -CONFIG_DVB_AF9033=m # -# Supported Frontend Modules +# Supported DVB Modules # CONFIG_DVB_BT8XX=m CONFIG_DVB_BUDGET_CORE=m @@ -2809,23 +2722,11 @@ CONFIG_DVB_USB_EC168=m CONFIG_DVB_USB_PCTV452E=m CONFIG_DVB_USB_IT913X=m CONFIG_DVB_USB_MXL111SF=m -CONFIG_DVB_TDA10071=m -CONFIG_DVB_LNBP22=m -CONFIG_DVB_A8293=m -CONFIG_DVB_IT913X_FE=m CONFIG_DVB_DM1105=m -CONFIG_DVB_S921=m -CONFIG_DVB_ISL6405=m -CONFIG_DVB_LGS8GL5=m -CONFIG_DVB_DUMMY_FE=m CONFIG_DVB_FIREDTV=m CONFIG_DVB_NGENE=m CONFIG_DVB_DDBRIDGE=m -CONFIG_DVB_MB86A20S=m CONFIG_DVB_USB_TECHNISAT_USB2=m -CONFIG_DVB_DIB9000=m -CONFIG_DVB_HD29L2=m -CONFIG_DVB_STV0367=m # # Supported SAA7146 based PCI Adapters @@ -2837,9 +2738,6 @@ CONFIG_DVB_BUDGET_CI=m CONFIG_DVB_BUDGET_AV=m CONFIG_DVB_BUDGET_PATCH=m -# -# Supported USB Adapters -# CONFIG_DVB_TTUSB_BUDGET=m # diff --git a/kernel.spec b/kernel.spec index 584440bce..3f8abbcf5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2234,6 +2234,9 @@ fi # and build. %changelog +* Fri May 25 2012 Mauro Carvalho Chehab +- Don't manually customise tuners/frontends (rhbz 825203) + * Thu May 24 2012 Josh Boyer - CVE-2012-2372 mm: 32bit PAE pmd walk vs populate SMP race (rhbz 822821 822825) From 0cb34a0046c4e6a5b16d8146a8a6e6e50b4e6f2c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 30 May 2012 07:33:55 -0400 Subject: [PATCH 385/487] CVE-2012-2390 huge pages: memory leak on mmap failure (rhbz 824352 824345) --- hugetlb-fix-resv_map-leak-in-error-path.patch | 108 ++++++++++++++++++ kernel.spec | 10 +- 2 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 hugetlb-fix-resv_map-leak-in-error-path.patch diff --git a/hugetlb-fix-resv_map-leak-in-error-path.patch b/hugetlb-fix-resv_map-leak-in-error-path.patch new file mode 100644 index 000000000..0bfd38c22 --- /dev/null +++ b/hugetlb-fix-resv_map-leak-in-error-path.patch @@ -0,0 +1,108 @@ +From c50ac050811d6485616a193eb0f37bfbd191cc89 Mon Sep 17 00:00:00 2001 +From: Dave Hansen +Date: Tue, 29 May 2012 15:06:46 -0700 +Subject: [PATCH] hugetlb: fix resv_map leak in error path + +When called for anonymous (non-shared) mappings, hugetlb_reserve_pages() +does a resv_map_alloc(). It depends on code in hugetlbfs's +vm_ops->close() to release that allocation. + +However, in the mmap() failure path, we do a plain unmap_region() without +the remove_vma() which actually calls vm_ops->close(). + +This is a decent fix. This leak could get reintroduced if new code (say, +after hugetlb_reserve_pages() in hugetlbfs_file_mmap()) decides to return +an error. But, I think it would have to unroll the reservation anyway. + +Christoph's test case: + + http://marc.info/?l=linux-mm&m=133728900729735 + +This patch applies to 3.4 and later. A version for earlier kernels is at +https://lkml.org/lkml/2012/5/22/418. + +Signed-off-by: Dave Hansen +Acked-by: Mel Gorman +Acked-by: KOSAKI Motohiro +Reported-by: Christoph Lameter +Tested-by: Christoph Lameter +Cc: Andrea Arcangeli +Cc: [2.6.32+] +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + mm/hugetlb.c | 28 ++++++++++++++++++++++------ + 1 files changed, 22 insertions(+), 6 deletions(-) + +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 41a647d..285a81e 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -2157,6 +2157,15 @@ static void hugetlb_vm_op_open(struct vm_area_struct *vma) + kref_get(&reservations->refs); + } + ++static void resv_map_put(struct vm_area_struct *vma) ++{ ++ struct resv_map *reservations = vma_resv_map(vma); ++ ++ if (!reservations) ++ return; ++ kref_put(&reservations->refs, resv_map_release); ++} ++ + static void hugetlb_vm_op_close(struct vm_area_struct *vma) + { + struct hstate *h = hstate_vma(vma); +@@ -2173,7 +2182,7 @@ static void hugetlb_vm_op_close(struct vm_area_struct *vma) + reserve = (end - start) - + region_count(&reservations->regions, start, end); + +- kref_put(&reservations->refs, resv_map_release); ++ resv_map_put(vma); + + if (reserve) { + hugetlb_acct_memory(h, -reserve); +@@ -2991,12 +3000,16 @@ int hugetlb_reserve_pages(struct inode *inode, + set_vma_resv_flags(vma, HPAGE_RESV_OWNER); + } + +- if (chg < 0) +- return chg; ++ if (chg < 0) { ++ ret = chg; ++ goto out_err; ++ } + + /* There must be enough pages in the subpool for the mapping */ +- if (hugepage_subpool_get_pages(spool, chg)) +- return -ENOSPC; ++ if (hugepage_subpool_get_pages(spool, chg)) { ++ ret = -ENOSPC; ++ goto out_err; ++ } + + /* + * Check enough hugepages are available for the reservation. +@@ -3005,7 +3018,7 @@ int hugetlb_reserve_pages(struct inode *inode, + ret = hugetlb_acct_memory(h, chg); + if (ret < 0) { + hugepage_subpool_put_pages(spool, chg); +- return ret; ++ goto out_err; + } + + /* +@@ -3022,6 +3035,9 @@ int hugetlb_reserve_pages(struct inode *inode, + if (!vma || vma->vm_flags & VM_MAYSHARE) + region_add(&inode->i_mapping->private_list, from, to); + return 0; ++out_err: ++ resv_map_put(vma); ++ return ret; + } + + void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed) +-- +1.7.7.6 + diff --git a/kernel.spec b/kernel.spec index 3f8abbcf5..216b3fb61 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -803,6 +803,8 @@ Patch22020: rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch #rhbz 822825 822821 CVE-2012-2372 Patch22021: mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch +#rhbz 824352 824345 CVE-2012-2390 +Patch22022: hugetlb-fix-resv_map-leak-in-error-path.patch # END OF PATCH DEFINITIONS @@ -1496,6 +1498,9 @@ ApplyPatch rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch #rhbz 822825 822821 CVE-2012-2372 ApplyPatch mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch +#rhbz 824352 824345 CVE-2012-2390 +ApplyPatch hugetlb-fix-resv_map-leak-in-error-path.patch + # END OF PATCH APPLICATIONS %endif @@ -2234,6 +2239,9 @@ fi # and build. %changelog +* Wed May 30 2012 Josh Boyer +- CVE-2012-2390 huge pages: memory leak on mmap failure (rhbz 824352 824345) + * Fri May 25 2012 Mauro Carvalho Chehab - Don't manually customise tuners/frontends (rhbz 825203) From d0d0771165b4315f4d43e9ea88c182d2f283fa3c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 30 May 2012 12:01:58 -0400 Subject: [PATCH 386/487] Include upstream commit 4523e145 for CVE-2012-2390 This fixes an oops that was trivially triggered after the original commit went in. Props to Dave J. --- hugetlb-fix-resv_map-leak-in-error-path.patch | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/hugetlb-fix-resv_map-leak-in-error-path.patch b/hugetlb-fix-resv_map-leak-in-error-path.patch index 0bfd38c22..888d5ce70 100644 --- a/hugetlb-fix-resv_map-leak-in-error-path.patch +++ b/hugetlb-fix-resv_map-leak-in-error-path.patch @@ -106,3 +106,71 @@ index 41a647d..285a81e 100644 -- 1.7.7.6 +From 4523e1458566a0e8ecfaff90f380dd23acc44d27 Mon Sep 17 00:00:00 2001 +From: Dave Hansen +Date: Wed, 30 May 2012 07:51:07 -0700 +Subject: [PATCH] mm: fix vma_resv_map() NULL pointer + +hugetlb_reserve_pages() can be used for either normal file-backed +hugetlbfs mappings, or MAP_HUGETLB. In the MAP_HUGETLB, semi-anonymous +mode, there is not a VMA around. The new call to resv_map_put() assumed +that there was, and resulted in a NULL pointer dereference: + + BUG: unable to handle kernel NULL pointer dereference at 0000000000000030 + IP: vma_resv_map+0x9/0x30 + PGD 141453067 PUD 1421e1067 PMD 0 + Oops: 0000 [#1] PREEMPT SMP + ... + Pid: 14006, comm: trinity-child6 Not tainted 3.4.0+ #36 + RIP: vma_resv_map+0x9/0x30 + ... + Process trinity-child6 (pid: 14006, threadinfo ffff8801414e0000, task ffff8801414f26b0) + Call Trace: + resv_map_put+0xe/0x40 + hugetlb_reserve_pages+0xa6/0x1d0 + hugetlb_file_setup+0x102/0x2c0 + newseg+0x115/0x360 + ipcget+0x1ce/0x310 + sys_shmget+0x5a/0x60 + system_call_fastpath+0x16/0x1b + +This was reported by Dave Jones, but was reproducible with the +libhugetlbfs test cases, so shame on me for not running them in the +first place. + +With this, the oops is gone, and the output of libhugetlbfs's +run_tests.py is identical to plain 3.4 again. + +[ Marked for stable, since this was introduced by commit c50ac050811d + ("hugetlb: fix resv_map leak in error path") which was also marked for + stable ] + +Reported-by: Dave Jones +Cc: Mel Gorman +Cc: KOSAKI Motohiro +Cc: Christoph Lameter +Cc: Andrea Arcangeli +Cc: Andrew Morton +Cc: [2.6.32+] +Signed-off-by: Linus Torvalds +--- + mm/hugetlb.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 285a81e..e198831 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -3036,7 +3036,8 @@ int hugetlb_reserve_pages(struct inode *inode, + region_add(&inode->i_mapping->private_list, from, to); + return 0; + out_err: +- resv_map_put(vma); ++ if (vma) ++ resv_map_put(vma); + return ret; + } + +-- +1.7.7.6 + From 474849beb10e9d241fc3c07f477bb5bf01967eca Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 4 Jun 2012 11:55:51 -0400 Subject: [PATCH 387/487] disable 32bit nx, it seems to be broken --- kernel.spec | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/kernel.spec b/kernel.spec index 216b3fb61..41b912e3b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1316,9 +1316,12 @@ ApplyPatch taint-vbox.patch # # NX Emulation # -ApplyPatch linux-2.6-32bit-mmap-exec-randomization.patch -ApplyPatch linux-2.6-i386-nx-emulation.patch -ApplyPatch nx-emu-remove-cpuinitdata-for-disable_nx-on-x86_32.patch +#ApplyPatch linux-2.6-32bit-mmap-exec-randomization.patch +#ApplyPatch linux-2.6-i386-nx-emulation.patch +#ApplyPatch nx-emu-remove-cpuinitdata-for-disable_nx-on-x86_32.patch +#rhbz 804957 CVE-2012-1568 +#ApplyPatch shlib_base_randomize.patch + # # bugfixes to drivers and filesystems @@ -1460,9 +1463,6 @@ ApplyPatch rt2x00_fix_MCU_request_failures.patch #rhbz 789644 ApplyPatch mcelog-rcu-splat.patch -#rhbz 804957 CVE-2012-1568 -ApplyPatch shlib_base_randomize.patch - ApplyPatch unhandled-irqs-switch-to-polling.patch # debug patches @@ -2239,6 +2239,9 @@ fi # and build. %changelog +* Mon Jun 04 2012 Dave Jones +- Disable 32bit NX emulation. + * Wed May 30 2012 Josh Boyer - CVE-2012-2390 huge pages: memory leak on mmap failure (rhbz 824352 824345) From c701cb2c67c9c9d1e554bdfb704776d598471b51 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 4 Jun 2012 16:13:28 -0400 Subject: [PATCH 388/487] Linux v3.3.8 --- kernel.spec | 19 ++-- ...ta-forbid-port-runtime-pm-by-default.patch | 24 ------ ...race-condition-when-firmware-is-cach.patch | 86 ------------------- sources | 2 +- 4 files changed, 6 insertions(+), 125 deletions(-) delete mode 100644 libata-forbid-port-runtime-pm-by-default.patch delete mode 100644 rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch diff --git a/kernel.spec b/kernel.spec index 41b912e3b..7a442ed55 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 7 +%define stable_update 8 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -772,9 +772,6 @@ Patch21351: x86-add-io_apic_ops-to-allow-interception.patch Patch21352: x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch Patch21353: xen-x86-Implement-x86_apic_ops.patch -#rhbz 807632 -Patch21385: libata-forbid-port-runtime-pm-by-default.patch - #rhbz 808559 Patch21530: ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch @@ -797,9 +794,6 @@ Patch22018: atl1c_net_next_update-3.3.patch #rhbz 795176 Patch22019: rtl818x-fix-sleeping-function-called-from-invalid-context.patch -#rhbz 822120 -Patch22020: rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch - #rhbz 822825 822821 CVE-2012-2372 Patch22021: mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch @@ -1474,9 +1468,6 @@ ApplyPatch x86-add-io_apic_ops-to-allow-interception.patch ApplyPatch x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch ApplyPatch xen-x86-Implement-x86_apic_ops.patch -#rhbz 807632 -ApplyPatch libata-forbid-port-runtime-pm-by-default.patch - #rhbz 806295 ApplyPatch disable-hid-battery.patch @@ -1492,9 +1483,6 @@ ApplyPatch atl1c_net_next_update-3.3.patch #rhbz 795176 ApplyPatch rtl818x-fix-sleeping-function-called-from-invalid-context.patch -#rhbz 822120 -ApplyPatch rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch - #rhbz 822825 822821 CVE-2012-2372 ApplyPatch mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch @@ -2239,6 +2227,9 @@ fi # and build. %changelog +* Mon Jun 04 2012 Josh Boyer 3.3.8-1 +- Linux v3.3.8 + * Mon Jun 04 2012 Dave Jones - Disable 32bit NX emulation. diff --git a/libata-forbid-port-runtime-pm-by-default.patch b/libata-forbid-port-runtime-pm-by-default.patch deleted file mode 100644 index 0d93a19f5..000000000 --- a/libata-forbid-port-runtime-pm-by-default.patch +++ /dev/null @@ -1,24 +0,0 @@ -From: Lin Ming -Date: Wed, 18 Apr 2012 09:13:41 +0800 -Subject: [PATCH] libata: forbid port runtime pm by default - -Forbid port runtime pm by default because it has known hotplug issue. -User can allow it by, for example - -echo auto > /sys/devices/pci0000:00/0000:00:1f.2/ata2/power/control - -Signed-off-by: Lin Ming ---- - drivers/ata/libata-transport.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - ---- linux-3.3.noarch.orig/drivers/ata/libata-transport.c -+++ linux-3.3.noarch/drivers/ata/libata-transport.c -@@ -294,6 +294,7 @@ int ata_tport_add(struct device *parent, - device_enable_async_suspend(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); -+ pm_runtime_forbid(dev); - - transport_add_device(dev); - transport_configure_device(dev); diff --git a/rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch b/rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch deleted file mode 100644 index 431ec00b6..000000000 --- a/rtlwifi-fix-for-race-condition-when-firmware-is-cach.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 574e02abaf816b582685805f0c1150ca9f1f18ee Mon Sep 17 00:00:00 2001 -From: Larry Finger -Date: Fri, 4 May 2012 08:27:43 -0500 -Subject: [PATCH] rtlwifi: fix for race condition when firmware is cached - -In commit b0302ab, the rtlwifi family of drivers was converted to use -asynchronous firmware loading. Unfortumately, the implementation was -racy, and the ieee80211 routines could be started before rtl_init_core() -was called to setup the data. - -This patch fixes the bug noted in https://bugzilla.kernel.org/show_bug.cgi?id=43187. - -Reported-by: Joshua Roys -Tested-by: Neptune Ning -Signed-off-by: Larry Finger -Cc: Stable [3.3] -Signed-off-by: John W. Linville ---- - drivers/net/wireless/rtlwifi/pci.c | 16 ++++++++-------- - drivers/net/wireless/rtlwifi/usb.c | 10 +++++----- - 2 files changed, 13 insertions(+), 13 deletions(-) - -diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c -index b588ca8..03c400e 100644 ---- a/drivers/net/wireless/rtlwifi/pci.c -+++ b/drivers/net/wireless/rtlwifi/pci.c -@@ -1865,14 +1865,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, - /*like read eeprom and so on */ - rtlpriv->cfg->ops->read_eeprom_info(hw); - -- if (rtlpriv->cfg->ops->init_sw_vars(hw)) { -- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -- ("Can't init_sw_vars.\n")); -- goto fail3; -- } -- -- rtlpriv->cfg->ops->init_sw_leds(hw); -- - /*aspm */ - rtl_pci_init_aspm(hw); - -@@ -1892,6 +1884,14 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, - goto fail3; - } - -+ if (rtlpriv->cfg->ops->init_sw_vars(hw)) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("Can't init_sw_vars.\n")); -+ goto fail3; -+ } -+ -+ rtlpriv->cfg->ops->init_sw_leds(hw); -+ - err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c -index 049e207..20b53ae 100644 ---- a/drivers/net/wireless/rtlwifi/usb.c -+++ b/drivers/net/wireless/rtlwifi/usb.c -@@ -970,12 +970,6 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, - rtlpriv->cfg->ops->read_chip_version(hw); - /*like read eeprom and so on */ - rtlpriv->cfg->ops->read_eeprom_info(hw); -- if (rtlpriv->cfg->ops->init_sw_vars(hw)) { -- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -- ("Can't init_sw_vars.\n")); -- goto error_out; -- } -- rtlpriv->cfg->ops->init_sw_leds(hw); - err = _rtl_usb_init(hw); - err = _rtl_usb_init_sw(hw); - /* Init mac80211 sw */ -@@ -985,6 +979,12 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, - ("Can't allocate sw for mac80211.\n")); - goto error_out; - } -+ if (rtlpriv->cfg->ops->init_sw_vars(hw)) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("Can't init_sw_vars.\n")); -+ goto error_out; -+ } -+ rtlpriv->cfg->ops->init_sw_leds(hw); - - return 0; - error_out: diff --git a/sources b/sources index 03cb562cf..033ae54df 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz -622a3b43238559aeb778279969631260 patch-3.3.7.xz +e1714b5136a7f4dab1b5d2d7f98e2891 patch-3.3.8.xz From 14735d35779c3ba034dda89cb25e81023656ac8b Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 14 Jun 2012 14:03:10 -0500 Subject: [PATCH 389/487] Linux 3.4.2 --- ...k-Add-quirk-for-Mac-Pro-5-1-machines.patch | 37 - ...nnecessary-setattrs-for-open-O_TRUNC.patch | 153 - ...reduce-the-footprint-of-the-idmapper.patch | 109 - ...nups-for-nfs4_handle_exception-and-n.patch | 51 - ...-the-state-manager-for-lock-reclaim-.patch | 37 - ...Reduce-the-footprint-of-the-idmapper.patch | 46 - ...O_TRUNC-and-ftruncate-error-handling.patch | 69 - ...-per-net-operations-from-svc_destroy.patch | 327 + SUNRPC-new-svc_bind-routine-introduced.patch | 249 + add-poll-requested-events.patch | 393 - ...3.patch => atl1c_net_next_update-3.4.patch | 149 +- bluetooth-use-after-free.patch | 105 - config-arm-generic | 192 +- config-arm-highbank | 44 +- config-arm-imx | 33 +- config-arm-kirkwood | 15 +- config-arm-omap-generic | 52 +- config-arm-tegra | 54 +- config-generic | 54 + config-powerpc-generic | 3 + config-s390x | 1 + config-x86-32-generic | 6 + config-x86-generic | 11 +- config-x86_64-generic | 2 + disable-hid-battery.patch | 11 - drivers-media-update.patch | 38187 ---------------- drm-i915-dp-stfu.patch | 36 +- ...ort-check-none-nocheck-mount-options.patch | 51 - floppy-drop-disable_hlt-warning.patch | 13 - hugetlb-fix-resv_map-leak-in-error-path.patch | 176 - ...-buggy-chain-extension-feature-in-HW.patch | 48 + ...-mess-up-the-SCD-when-removing-a-key.patch | 45 + kernel.spec | 114 +- linux-2.6-acpi-debug-infinite-loop.patch | 4 +- linux-2.6-defaults-aspm.patch | 12 - mcelog-rcu-splat.patch | 15 - rt2x00_fix_MCU_request_failures.patch | 136 - silence-timekeeping-spew.patch | 16 - sources | 4 +- ...ead-in-pmd_read_atomic-for-32bit-PAE.patch | 228 + utrace.patch | 4696 -- ...dd-io_apic_ops-to-allow-interception.patch | 135 - ...s-Replace-apic_ops-with-x86_apic_ops.patch | 258 - xen-x86-Implement-x86_apic_ops.patch | 85 - 44 files changed, 1376 insertions(+), 45086 deletions(-) delete mode 100644 ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch delete mode 100644 NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch delete mode 100644 NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch delete mode 100644 NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch delete mode 100644 NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch delete mode 100644 NFSv4-Reduce-the-footprint-of-the-idmapper.patch delete mode 100644 NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch create mode 100644 SUNRPC-move-per-net-operations-from-svc_destroy.patch create mode 100644 SUNRPC-new-svc_bind-routine-introduced.patch delete mode 100644 add-poll-requested-events.patch rename atl1c_net_next_update-3.3.patch => atl1c_net_next_update-3.4.patch (97%) delete mode 100644 bluetooth-use-after-free.patch delete mode 100644 disable-hid-battery.patch delete mode 100644 ext4-Support-check-none-nocheck-mount-options.patch delete mode 100644 floppy-drop-disable_hlt-warning.patch delete mode 100644 hugetlb-fix-resv_map-leak-in-error-path.patch create mode 100644 iwlwifi-disable-the-buggy-chain-extension-feature-in-HW.patch create mode 100644 iwlwifi-dont-mess-up-the-SCD-when-removing-a-key.patch delete mode 100644 linux-2.6-defaults-aspm.patch delete mode 100644 mcelog-rcu-splat.patch delete mode 100644 rt2x00_fix_MCU_request_failures.patch delete mode 100644 silence-timekeeping-spew.patch create mode 100644 thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch delete mode 100644 utrace.patch delete mode 100644 x86-add-io_apic_ops-to-allow-interception.patch delete mode 100644 x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch delete mode 100644 xen-x86-Implement-x86_apic_ops.patch diff --git a/ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch b/ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch deleted file mode 100644 index 28579d13b..000000000 --- a/ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch +++ /dev/null @@ -1,37 +0,0 @@ -From a9e1e167d934aa74f48008393ade4f09fc587432 Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Thu, 12 Apr 2012 13:55:36 -0400 -Subject: [PATCH] ALSA: hda/realtek - Add quirk for Mac Pro 5,1 machines - -A user reported that setting model=imac24 used to allow sound to work on their -Mac Pro 5,1 machine. Commit 5671087ffa "Move ALC885 macpro and imac24 models -to auto-parser" removed this model option. All Mac machines are now explicitly -handled with a quirk and the auto-parser. This adds a quirk for the device -found on the Mac Pro 5,1 machines. - -This (partially) fixes https://bugzilla.redhat.com/show_bug.cgi?id=808559 - -[sorted the new entry in the ID number order by tiwai] - -Reported-by: Gabriel Somlo -Signed-off-by: Josh Boyer -Signed-off-by: Takashi Iwai ---- - sound/pci/hda/patch_realtek.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c -index 22c73b7..bd34b51 100644 ---- a/sound/pci/hda/patch_realtek.c -+++ b/sound/pci/hda/patch_realtek.c -@@ -4659,6 +4659,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { - SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO), - SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD), - SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO), -+ SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO), - - SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), - SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), --- -1.7.7.6 - diff --git a/NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch b/NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch deleted file mode 100644 index 89b6308cd..000000000 --- a/NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch +++ /dev/null @@ -1,153 +0,0 @@ -From: Trond Myklebust - -Currently, we will correctly optimise away a truncate that doesn't -change the file size. However, in the case of open(O_TRUNC), we -also want to optimise away the time changes. - -Signed-off-by: Trond Myklebust ---- - fs/nfs/dir.c | 25 +++++++++++++++++++------ - fs/nfs/inode.c | 4 ++-- - fs/nfs/nfs4proc.c | 10 +++++++--- - 3 files changed, 28 insertions(+), 11 deletions(-) - -diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c -index fd9a872..bb132a8 100644 ---- a/fs/nfs/dir.c -+++ b/fs/nfs/dir.c -@@ -1429,6 +1429,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry - } - - open_flags = nd->intent.open.flags; -+ attr.ia_valid = 0; - - ctx = create_nfs_open_context(dentry, open_flags); - res = ERR_CAST(ctx); -@@ -1437,11 +1438,14 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry - - if (nd->flags & LOOKUP_CREATE) { - attr.ia_mode = nd->intent.open.create_mode; -- attr.ia_valid = ATTR_MODE; -+ attr.ia_valid |= ATTR_MODE; - attr.ia_mode &= ~current_umask(); -- } else { -+ } else - open_flags &= ~(O_EXCL | O_CREAT); -- attr.ia_valid = 0; -+ -+ if (open_flags & O_TRUNC) { -+ attr.ia_valid |= ATTR_SIZE; -+ attr.ia_size = 0; - } - - /* Open the file on the server */ -@@ -1495,6 +1499,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) - struct inode *inode; - struct inode *dir; - struct nfs_open_context *ctx; -+ struct iattr attr; - int openflags, ret = 0; - - if (nd->flags & LOOKUP_RCU) -@@ -1523,19 +1528,27 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) - /* We cannot do exclusive creation on a positive dentry */ - if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) - goto no_open_dput; -- /* We can't create new files, or truncate existing ones here */ -- openflags &= ~(O_CREAT|O_EXCL|O_TRUNC); -+ /* We can't create new files here */ -+ openflags &= ~(O_CREAT|O_EXCL); - - ctx = create_nfs_open_context(dentry, openflags); - ret = PTR_ERR(ctx); - if (IS_ERR(ctx)) - goto out; -+ -+ attr.ia_valid = 0; -+ if (openflags & O_TRUNC) { -+ attr.ia_valid |= ATTR_SIZE; -+ attr.ia_size = 0; -+ nfs_wb_all(inode); -+ } -+ - /* - * Note: we're not holding inode->i_mutex and so may be racing with - * operations that change the directory. We therefore save the - * change attribute *before* we do the RPC call. - */ -- inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, NULL); -+ inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr); - if (IS_ERR(inode)) { - ret = PTR_ERR(inode); - switch (ret) { -diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c -index f649fba..57d0abb 100644 ---- a/fs/nfs/inode.c -+++ b/fs/nfs/inode.c -@@ -401,7 +401,7 @@ out_no_inode: - goto out; - } - --#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE) -+#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE|ATTR_OPEN) - - int - nfs_setattr(struct dentry *dentry, struct iattr *attr) -@@ -423,7 +423,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) - - /* Optimization: if the end result is no change, don't RPC */ - attr->ia_valid &= NFS_VALID_ATTRS; -- if ((attr->ia_valid & ~ATTR_FILE) == 0) -+ if ((attr->ia_valid & ~(ATTR_FILE|ATTR_OPEN)) == 0) - return 0; - - /* Write all dirty data */ -diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c -index 1515e45..c4c6b48 100644 ---- a/fs/nfs/nfs4proc.c -+++ b/fs/nfs/nfs4proc.c -@@ -833,7 +833,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, - p->o_arg.bitmask = server->attr_bitmask; - p->o_arg.dir_bitmask = server->cache_consistency_bitmask; - p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; -- if (flags & O_CREAT) { -+ if (attrs != NULL && attrs->ia_valid != 0) { - u32 *s; - - p->o_arg.u.attrs = &p->attrs; -@@ -890,7 +890,7 @@ static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode - { - int ret = 0; - -- if (open_mode & O_EXCL) -+ if (open_mode & (O_EXCL|O_TRUNC)) - goto out; - switch (mode & (FMODE_READ|FMODE_WRITE)) { - case FMODE_READ: -@@ -1038,7 +1038,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) - struct nfs4_state *state = opendata->state; - struct nfs_inode *nfsi = NFS_I(state->inode); - struct nfs_delegation *delegation; -- int open_mode = opendata->o_arg.open_flags & O_EXCL; -+ int open_mode = opendata->o_arg.open_flags & (O_EXCL|O_TRUNC); - fmode_t fmode = opendata->o_arg.fmode; - nfs4_stateid stateid; - int ret = -EAGAIN; -@@ -2439,6 +2439,10 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, - } - } - -+ /* Deal with open(O_TRUNC) */ -+ if (sattr->ia_valid & ATTR_OPEN) -+ sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); -+ - status = nfs4_do_setattr(inode, cred, fattr, sattr, state); - if (status == 0) - nfs_setattr_update_inode(inode, sattr); --- -1.7.7.6 - -_______________________________________________ -kernel mailing list -kernel@lists.fedoraproject.org -https://admin.fedoraproject.org/mailman/listinfo/kernel diff --git a/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch b/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch deleted file mode 100644 index 42d1052e2..000000000 --- a/NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch +++ /dev/null @@ -1,109 +0,0 @@ -diff -up linux-3.2.noarch/fs/nfs/idmap.c.orig linux-3.2.noarch/fs/nfs/idmap.c ---- linux-3.2.noarch/fs/nfs/idmap.c.orig 2012-03-14 13:08:37.462928792 -0400 -+++ linux-3.2.noarch/fs/nfs/idmap.c 2012-03-14 13:10:17.076030982 -0400 -@@ -365,7 +365,7 @@ struct idmap_hashent { - - struct idmap_hashtable { - __u8 h_type; -- struct idmap_hashent h_entries[IDMAP_HASH_SZ]; -+ struct idmap_hashent *h_entries; - }; - - struct idmap { -@@ -420,20 +420,39 @@ nfs_idmap_new(struct nfs_client *clp) - return 0; - } - -+static void -+idmap_alloc_hashtable(struct idmap_hashtable *h) -+{ -+ if (h->h_entries != NULL) -+ return; -+ h->h_entries = kcalloc(IDMAP_HASH_SZ, -+ sizeof(*h->h_entries), -+ GFP_KERNEL); -+} -+ -+static void -+idmap_free_hashtable(struct idmap_hashtable *h) -+{ -+ int i; -+ -+ if (h->h_entries == NULL) -+ return; -+ for (i = 0; i < IDMAP_HASH_SZ; i++) -+ kfree(h->h_entries[i].ih_name); -+ kfree(h->h_entries); -+} -+ - void - nfs_idmap_delete(struct nfs_client *clp) - { - struct idmap *idmap = clp->cl_idmap; -- int i; - - if (!idmap) - return; - rpc_unlink(idmap->idmap_dentry); - clp->cl_idmap = NULL; -- for (i = 0; i < ARRAY_SIZE(idmap->idmap_user_hash.h_entries); i++) -- kfree(idmap->idmap_user_hash.h_entries[i].ih_name); -- for (i = 0; i < ARRAY_SIZE(idmap->idmap_group_hash.h_entries); i++) -- kfree(idmap->idmap_group_hash.h_entries[i].ih_name); -+ idmap_free_hashtable(&idmap->idmap_user_hash); -+ idmap_free_hashtable(&idmap->idmap_group_hash); - kfree(idmap); - } - -@@ -443,6 +462,8 @@ nfs_idmap_delete(struct nfs_client *clp) - static inline struct idmap_hashent * - idmap_name_hash(struct idmap_hashtable* h, const char *name, size_t len) - { -+ if (h->h_entries == NULL) -+ return NULL; - return &h->h_entries[fnvhash32(name, len) % IDMAP_HASH_SZ]; - } - -@@ -451,6 +472,8 @@ idmap_lookup_name(struct idmap_hashtable - { - struct idmap_hashent *he = idmap_name_hash(h, name, len); - -+ if (he == NULL) -+ return NULL; - if (he->ih_namelen != len || memcmp(he->ih_name, name, len) != 0) - return NULL; - if (time_after(jiffies, he->ih_expires)) -@@ -461,6 +484,8 @@ idmap_lookup_name(struct idmap_hashtable - static inline struct idmap_hashent * - idmap_id_hash(struct idmap_hashtable* h, __u32 id) - { -+ if (h->h_entries == NULL) -+ return NULL; - return &h->h_entries[fnvhash32(&id, sizeof(id)) % IDMAP_HASH_SZ]; - } - -@@ -468,6 +493,9 @@ static struct idmap_hashent * - idmap_lookup_id(struct idmap_hashtable *h, __u32 id) - { - struct idmap_hashent *he = idmap_id_hash(h, id); -+ -+ if (he == NULL) -+ return NULL; - if (he->ih_id != id || he->ih_namelen == 0) - return NULL; - if (time_after(jiffies, he->ih_expires)) -@@ -483,12 +511,14 @@ idmap_lookup_id(struct idmap_hashtable * - static inline struct idmap_hashent * - idmap_alloc_name(struct idmap_hashtable *h, char *name, size_t len) - { -+ idmap_alloc_hashtable(h); - return idmap_name_hash(h, name, len); - } - - static inline struct idmap_hashent * - idmap_alloc_id(struct idmap_hashtable *h, __u32 id) - { -+ idmap_alloc_hashtable(h); - return idmap_id_hash(h, id); - } - diff --git a/NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch b/NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch deleted file mode 100644 index 105235126..000000000 --- a/NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 14977489ffdb80d4caf5a184ba41b23b02fbacd9 Mon Sep 17 00:00:00 2001 -From: Trond Myklebust -Date: Tue, 27 Mar 2012 18:31:25 -0400 -Subject: [PATCH] NFSv4: Minor cleanups for nfs4_handle_exception and - nfs4_async_handle_error - -Signed-off-by: Trond Myklebust ---- - fs/nfs/nfs4proc.c | 10 +++++----- - 1 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c -index 1933e67..f82bde0 100644 ---- a/fs/nfs/nfs4proc.c -+++ b/fs/nfs/nfs4proc.c -@@ -270,7 +270,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc - case 0: - return 0; - case -NFS4ERR_OPENMODE: -- if (nfs_have_delegation(inode, FMODE_READ)) { -+ if (inode && nfs_have_delegation(inode, FMODE_READ)) { - nfs_inode_return_delegation(inode); - exception->retry = 1; - return 0; -@@ -282,10 +282,9 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc - case -NFS4ERR_DELEG_REVOKED: - case -NFS4ERR_ADMIN_REVOKED: - case -NFS4ERR_BAD_STATEID: -- if (state != NULL) -- nfs_remove_bad_delegation(state->inode); - if (state == NULL) - break; -+ nfs_remove_bad_delegation(state->inode); - nfs4_schedule_stateid_recovery(server, state); - goto wait_on_recovery; - case -NFS4ERR_EXPIRED: -@@ -3825,8 +3824,9 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, - case -NFS4ERR_DELEG_REVOKED: - case -NFS4ERR_ADMIN_REVOKED: - case -NFS4ERR_BAD_STATEID: -- if (state != NULL) -- nfs_remove_bad_delegation(state->inode); -+ if (state == NULL) -+ break; -+ nfs_remove_bad_delegation(state->inode); - case -NFS4ERR_OPENMODE: - if (state == NULL) - break; --- -1.7.7.6 - diff --git a/NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch b/NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch deleted file mode 100644 index 5b7f5e51d..000000000 --- a/NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 34d91cfbc163c6e2a136a27c96918fc35de06341 Mon Sep 17 00:00:00 2001 -From: William Dauchy -Date: Wed, 14 Mar 2012 12:32:04 +0100 -Subject: [PATCH] NFSv4: Rate limit the state manager for lock reclaim warning - messages - -Adding rate limit on `Lock reclaim failed` messages since it could fill -up system logs -Signed-off-by: William Dauchy -Signed-off-by: Trond Myklebust - -Conflicts: - - fs/nfs/nfs4state.c ---- - fs/nfs/nfs4state.c | 5 +++-- - 1 files changed, 3 insertions(+), 2 deletions(-) - -diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c -index bacb271..3676b5c 100644 ---- a/fs/nfs/nfs4state.c -+++ b/fs/nfs/nfs4state.c -@@ -1247,8 +1247,9 @@ restart: - spin_lock(&state->state_lock); - list_for_each_entry(lock, &state->lock_states, ls_locks) { - if (!(lock->ls_flags & NFS_LOCK_INITIALIZED)) -- printk("%s: Lock reclaim failed!\n", -- __func__); -+ pr_warn_ratelimited("NFS: " -+ "%s: Lock reclaim " -+ "failed!\n", __func__); - } - spin_unlock(&state->state_lock); - nfs4_put_open_state(state); --- -1.7.7.6 - diff --git a/NFSv4-Reduce-the-footprint-of-the-idmapper.patch b/NFSv4-Reduce-the-footprint-of-the-idmapper.patch deleted file mode 100644 index 4110ef904..000000000 --- a/NFSv4-Reduce-the-footprint-of-the-idmapper.patch +++ /dev/null @@ -1,46 +0,0 @@ -diff -up linux-3.2.noarch/fs/nfs/idmap.c.orig linux-3.2.noarch/fs/nfs/idmap.c ---- linux-3.2.noarch/fs/nfs/idmap.c.orig 2012-02-07 07:12:52.585471833 -0500 -+++ linux-3.2.noarch/fs/nfs/idmap.c 2012-03-14 13:08:37.462928792 -0400 -@@ -360,7 +360,7 @@ struct idmap_hashent { - unsigned long ih_expires; - __u32 ih_id; - size_t ih_namelen; -- char ih_name[IDMAP_NAMESZ]; -+ const char *ih_name; - }; - - struct idmap_hashtable { -@@ -424,11 +424,16 @@ void - nfs_idmap_delete(struct nfs_client *clp) - { - struct idmap *idmap = clp->cl_idmap; -+ int i; - - if (!idmap) - return; - rpc_unlink(idmap->idmap_dentry); - clp->cl_idmap = NULL; -+ for (i = 0; i < ARRAY_SIZE(idmap->idmap_user_hash.h_entries); i++) -+ kfree(idmap->idmap_user_hash.h_entries[i].ih_name); -+ for (i = 0; i < ARRAY_SIZE(idmap->idmap_group_hash.h_entries); i++) -+ kfree(idmap->idmap_group_hash.h_entries[i].ih_name); - kfree(idmap); - } - -@@ -491,9 +496,14 @@ static void - idmap_update_entry(struct idmap_hashent *he, const char *name, - size_t namelen, __u32 id) - { -+ char *str = kmalloc(namelen + 1, GFP_KERNEL); -+ if (str == NULL) -+ return; -+ kfree(he->ih_name); - he->ih_id = id; -- memcpy(he->ih_name, name, namelen); -- he->ih_name[namelen] = '\0'; -+ memcpy(str, name, namelen); -+ str[namelen] = '\0'; -+ he->ih_name = str; - he->ih_namelen = namelen; - he->ih_expires = jiffies + nfs_idmap_cache_timeout; - } diff --git a/NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch b/NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch deleted file mode 100644 index 134b210fe..000000000 --- a/NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch +++ /dev/null @@ -1,69 +0,0 @@ -From: Trond Myklebust - -If the file wasn't opened for writing, then truncate and ftruncate -need to report the appropriate errors. - -Reported-by: Miklos Szeredi -Signed-off-by: Trond Myklebust -Cc: stable@vger.kernel.org ---- - fs/nfs/dir.c | 4 ++-- - fs/nfs/nfs4proc.c | 15 ++++++++++++--- - 2 files changed, 14 insertions(+), 5 deletions(-) - -diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c -index bb132a8..51a2686 100644 ---- a/fs/nfs/dir.c -+++ b/fs/nfs/dir.c -@@ -1429,7 +1429,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry - } - - open_flags = nd->intent.open.flags; -- attr.ia_valid = 0; -+ attr.ia_valid = ATTR_OPEN; - - ctx = create_nfs_open_context(dentry, open_flags); - res = ERR_CAST(ctx); -@@ -1536,7 +1536,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) - if (IS_ERR(ctx)) - goto out; - -- attr.ia_valid = 0; -+ attr.ia_valid = ATTR_OPEN; - if (openflags & O_TRUNC) { - attr.ia_valid |= ATTR_SIZE; - attr.ia_size = 0; -diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c -index c4c6b48..e2a2893 100644 ---- a/fs/nfs/nfs4proc.c -+++ b/fs/nfs/nfs4proc.c -@@ -1921,10 +1921,19 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, - }; - int err; - do { -- err = nfs4_handle_exception(server, -- _nfs4_do_setattr(inode, cred, fattr, sattr, state), -- &exception); -+ err = _nfs4_do_setattr(inode, cred, fattr, sattr, state); -+ switch (err) { -+ case -NFS4ERR_OPENMODE: -+ if (state && !(state->state & FMODE_WRITE)) { -+ err = -EBADF; -+ if (sattr->ia_valid & ATTR_OPEN) -+ err = -EACCES; -+ goto out; -+ } -+ } -+ err = nfs4_handle_exception(server, err, &exception); - } while (exception.retry); -+out: - return err; - } - --- -1.7.7.6 - -_______________________________________________ -kernel mailing list -kernel@lists.fedoraproject.org -https://admin.fedoraproject.org/mailman/listinfo/kernel diff --git a/SUNRPC-move-per-net-operations-from-svc_destroy.patch b/SUNRPC-move-per-net-operations-from-svc_destroy.patch new file mode 100644 index 000000000..1895b5bca --- /dev/null +++ b/SUNRPC-move-per-net-operations-from-svc_destroy.patch @@ -0,0 +1,327 @@ +Path: news.gmane.org!not-for-mail +From: Stanislav Kinsbursky +Newsgroups: gmane.linux.kernel,gmane.linux.nfs,gmane.linux.openvz.devel +Subject: [PATCH 2/2] SUNRPC: move per-net operations from svc_destroy() +Date: Fri, 01 Jun 2012 15:17:50 +0400 +Lines: 281 +Approved: news@gmane.org +Message-ID: <20120601111750.7846.23782.stgit@localhost.localdomain> +References: <20120601111619.7846.95457.stgit@localhost.localdomain> +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: 7bit +X-Trace: dough.gmane.org 1338549639 9108 80.91.229.3 (1 Jun 2012 11:20:39 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Fri, 1 Jun 2012 11:20:39 +0000 (UTC) +Cc: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, + devel@openvz.org +To: bfields@fieldses.org, Trond.Myklebust@netapp.com +Original-X-From: linux-kernel-owner@vger.kernel.org Fri Jun 01 13:20:37 2012 +Return-path: +Envelope-to: glk-linux-kernel-3@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1SaPuE-0002JL-ED + for glk-linux-kernel-3@plane.gmane.org; Fri, 01 Jun 2012 13:20:34 +0200 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1759489Ab2FALUJ (ORCPT ); + Fri, 1 Jun 2012 07:20:09 -0400 +Original-Received: from mailhub.sw.ru ([195.214.232.25]:7947 "EHLO relay.sw.ru" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1759474Ab2FALUE (ORCPT ); + Fri, 1 Jun 2012 07:20:04 -0400 +Original-Received: from localhost.localdomain ([10.30.21.131]) + by relay.sw.ru (8.13.4/8.13.4) with ESMTP id q51BJrkd020556; + Fri, 1 Jun 2012 15:19:54 +0400 (MSK) +In-Reply-To: <20120601111619.7846.95457.stgit@localhost.localdomain> +User-Agent: StGit/0.16 +Original-Sender: linux-kernel-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-kernel@vger.kernel.org +Xref: news.gmane.org gmane.linux.kernel:1306567 gmane.linux.nfs:50236 gmane.linux.openvz.devel:1597 +Archived-At: + +This patch was back-ported from 3.5 kernel. + +The idea is to separate service destruction and per-net operations, because +these are two different things and it's mix looks ugly. + +Notes: +1) For NFS server this patch looks ugly (sorry for that). But these place will +be +rewritten soon during NFSd containerization. +2) LockD per-net counter increase int lockd_up() was moved prior to +make_socks() to make lockd_down_net() call safe in case of error. + +Signed-off-by: Stanislav Kinsbursky +--- + fs/lockd/svc.c | 27 +++++++++++++++------------ + fs/nfs/callback.c | 3 +++ + fs/nfsd/nfsctl.c | 12 +++++++++--- + fs/nfsd/nfssvc.c | 14 ++++++++++++++ + net/sunrpc/svc.c | 4 ---- + 5 files changed, 41 insertions(+), 19 deletions(-) + +diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c +index b1d0708..f1b3cce 100644 +--- a/fs/lockd/svc.c ++++ b/fs/lockd/svc.c +@@ -257,7 +257,7 @@ static int lockd_up_net(struct net *net) + struct svc_serv *serv = nlmsvc_rqst->rq_server; + int error; + +- if (ln->nlmsvc_users) ++ if (ln->nlmsvc_users++) + return 0; + + error = svc_rpcb_setup(serv, net); +@@ -272,6 +272,7 @@ static int lockd_up_net(struct net *net) + err_socks: + svc_rpcb_cleanup(serv, net); + err_rpcb: ++ ln->nlmsvc_users--; + return error; + } + +@@ -300,6 +301,7 @@ int lockd_up(void) + struct svc_serv *serv; + int error = 0; + struct net *net = current->nsproxy->net_ns; ++ struct lockd_net *ln = net_generic(net, lockd_net_id); + + mutex_lock(&nlmsvc_mutex); + /* +@@ -331,9 +333,11 @@ int lockd_up(void) + goto destroy_and_out; + } + ++ ln->nlmsvc_users++; ++ + error = make_socks(serv, net); + if (error < 0) +- goto destroy_and_out; ++ goto err_start; + + /* + * Create the kernel thread and wait for it to start. +@@ -345,7 +349,7 @@ int lockd_up(void) + printk(KERN_WARNING + "lockd_up: svc_rqst allocation failed, error=%d\n", + error); +- goto destroy_and_out; ++ goto err_start; + } + + svc_sock_update_bufs(serv); +@@ -359,7 +363,7 @@ int lockd_up(void) + nlmsvc_rqst = NULL; + printk(KERN_WARNING + "lockd_up: kthread_run failed, error=%d\n", error); +- goto destroy_and_out; ++ goto err_start; + } + + /* +@@ -369,14 +373,14 @@ int lockd_up(void) + destroy_and_out: + svc_destroy(serv); + out: +- if (!error) { +- struct lockd_net *ln = net_generic(net, lockd_net_id); +- +- ln->nlmsvc_users++; ++ if (!error) + nlmsvc_users++; +- } + mutex_unlock(&nlmsvc_mutex); + return error; ++ ++err_start: ++ lockd_down_net(net); ++ goto destroy_and_out; + } + EXPORT_SYMBOL_GPL(lockd_up); + +@@ -387,11 +391,10 @@ void + lockd_down(void) + { + mutex_lock(&nlmsvc_mutex); ++ lockd_down_net(current->nsproxy->net_ns); + if (nlmsvc_users) { +- if (--nlmsvc_users) { +- lockd_down_net(current->nsproxy->net_ns); ++ if (--nlmsvc_users) + goto out; +- } + } else { + printk(KERN_ERR "lockd_down: no users! task=%p\n", + nlmsvc_task); +diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c +index 0563237..38a44c6 100644 +--- a/fs/nfs/callback.c ++++ b/fs/nfs/callback.c +@@ -313,6 +313,8 @@ out_err: + dprintk("NFS: Couldn't create callback socket or server thread; " + "err = %d\n", ret); + cb_info->users--; ++ if (serv) ++ svc_shutdown_net(serv, net); + goto out; + } + +@@ -327,6 +329,7 @@ void nfs_callback_down(int minorversion) + cb_info->users--; + if (cb_info->users == 0 && cb_info->task != NULL) { + kthread_stop(cb_info->task); ++ svc_shutdown_net(cb_info->serv, &init_net); + svc_exit_thread(cb_info->rqst); + cb_info->serv = NULL; + cb_info->rqst = NULL; +diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c +index 2c53be6..3ab12eb 100644 +--- a/fs/nfsd/nfsctl.c ++++ b/fs/nfsd/nfsctl.c +@@ -651,6 +651,7 @@ static ssize_t __write_ports_addfd(char *buf) + { + char *mesg = buf; + int fd, err; ++ struct net *net = &init_net; + + err = get_int(&mesg, &fd); + if (err != 0 || fd < 0) +@@ -662,6 +663,8 @@ static ssize_t __write_ports_addfd(char *buf) + + err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); + if (err < 0) { ++ if (nfsd_serv->sv_nrthreads == 1) ++ svc_shutdown_net(nfsd_serv, net); + svc_destroy(nfsd_serv); + return err; + } +@@ -699,6 +702,7 @@ static ssize_t __write_ports_addxprt(char *buf) + char transport[16]; + struct svc_xprt *xprt; + int port, err; ++ struct net *net = &init_net; + + if (sscanf(buf, "%15s %4u", transport, &port) != 2) + return -EINVAL; +@@ -710,12 +714,12 @@ static ssize_t __write_ports_addxprt(char *buf) + if (err != 0) + return err; + +- err = svc_create_xprt(nfsd_serv, transport, &init_net, ++ err = svc_create_xprt(nfsd_serv, transport, net, + PF_INET, port, SVC_SOCK_ANONYMOUS); + if (err < 0) + goto out_err; + +- err = svc_create_xprt(nfsd_serv, transport, &init_net, ++ err = svc_create_xprt(nfsd_serv, transport, net, + PF_INET6, port, SVC_SOCK_ANONYMOUS); + if (err < 0 && err != -EAFNOSUPPORT) + goto out_close; +@@ -724,12 +728,14 @@ static ssize_t __write_ports_addxprt(char *buf) + nfsd_serv->sv_nrthreads--; + return 0; + out_close: +- xprt = svc_find_xprt(nfsd_serv, transport, &init_net, PF_INET, port); ++ xprt = svc_find_xprt(nfsd_serv, transport, net, PF_INET, port); + if (xprt != NULL) { + svc_close_xprt(xprt); + svc_xprt_put(xprt); + } + out_err: ++ if (nfsd_serv->sv_nrthreads == 1) ++ svc_shutdown_net(nfsd_serv, net); + svc_destroy(nfsd_serv); + return err; + } +diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c +index a6461f3..da50e1c 100644 +--- a/fs/nfsd/nfssvc.c ++++ b/fs/nfsd/nfssvc.c +@@ -382,6 +382,7 @@ int nfsd_set_nrthreads(int n, int *nthreads) + int i = 0; + int tot = 0; + int err = 0; ++ struct net *net = &init_net; + + WARN_ON(!mutex_is_locked(&nfsd_mutex)); + +@@ -426,6 +427,9 @@ int nfsd_set_nrthreads(int n, int *nthreads) + if (err) + break; + } ++ ++ if (nfsd_serv->sv_nrthreads == 1) ++ svc_shutdown_net(nfsd_serv, net); + svc_destroy(nfsd_serv); + + return err; +@@ -441,6 +445,7 @@ nfsd_svc(unsigned short port, int nrservs) + { + int error; + bool nfsd_up_before; ++ struct net *net = &init_net; + + mutex_lock(&nfsd_mutex); + dprintk("nfsd: creating service\n"); +@@ -473,6 +478,8 @@ out_shutdown: + if (error < 0 && !nfsd_up_before) + nfsd_shutdown(); + out_destroy: ++ if (nfsd_serv->sv_nrthreads == 1) ++ svc_shutdown_net(nfsd_serv, net); + svc_destroy(nfsd_serv); /* Release server */ + out: + mutex_unlock(&nfsd_mutex); +@@ -556,6 +563,9 @@ nfsd(void *vrqstp) + nfsdstats.th_cnt --; + + out: ++ if (rqstp->rq_server->sv_nrthreads == 1) ++ svc_shutdown_net(rqstp->rq_server, &init_net); ++ + /* Release the thread */ + svc_exit_thread(rqstp); + +@@ -668,8 +678,12 @@ int nfsd_pool_stats_open(struct inode *inode, struct file *file) + int nfsd_pool_stats_release(struct inode *inode, struct file *file) + { + int ret = seq_release(inode, file); ++ struct net *net = &init_net; ++ + mutex_lock(&nfsd_mutex); + /* this function really, really should have been called svc_put() */ ++ if (nfsd_serv->sv_nrthreads == 1) ++ svc_shutdown_net(nfsd_serv, net); + svc_destroy(nfsd_serv); + mutex_unlock(&nfsd_mutex); + return ret; +diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c +index e6d542c..b7210f5 100644 +--- a/net/sunrpc/svc.c ++++ b/net/sunrpc/svc.c +@@ -537,8 +537,6 @@ EXPORT_SYMBOL_GPL(svc_shutdown_net); + void + svc_destroy(struct svc_serv *serv) + { +- struct net *net = current->nsproxy->net_ns; +- + dprintk("svc: svc_destroy(%s, %d)\n", + serv->sv_program->pg_name, + serv->sv_nrthreads); +@@ -553,8 +551,6 @@ svc_destroy(struct svc_serv *serv) + + del_timer_sync(&serv->sv_temptimer); + +- svc_shutdown_net(serv, net); +- + /* + * The last user is gone and thus all sockets have to be destroyed to + * the point. Check this. + diff --git a/SUNRPC-new-svc_bind-routine-introduced.patch b/SUNRPC-new-svc_bind-routine-introduced.patch new file mode 100644 index 000000000..58127cca0 --- /dev/null +++ b/SUNRPC-new-svc_bind-routine-introduced.patch @@ -0,0 +1,249 @@ +Path: news.gmane.org!not-for-mail +From: Stanislav Kinsbursky +Newsgroups: gmane.linux.nfs,gmane.linux.kernel,gmane.linux.openvz.devel +Subject: [PATCH 1/2] SUNRPC: new svc_bind() routine introduced +Date: Fri, 01 Jun 2012 15:17:42 +0400 +Lines: 203 +Approved: news@gmane.org +Message-ID: <20120601111742.7846.99872.stgit@localhost.localdomain> +References: <20120601111619.7846.95457.stgit@localhost.localdomain> +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: 7bit +X-Trace: dough.gmane.org 1338549604 8815 80.91.229.3 (1 Jun 2012 11:20:04 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Fri, 1 Jun 2012 11:20:04 +0000 (UTC) +Cc: linux-nfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, + devel-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org +To: bfields-uC3wQj2KruNg9hUCZPvPmw@public.gmane.org, Trond.Myklebust-HgOvQuBEEgTQT0dZR+AlfA@public.gmane.org +Original-X-From: linux-nfs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Fri Jun 01 13:20:02 2012 +Return-path: +Envelope-to: glN-linux-nfs-wOFGN7rlS/M9smdsby/KFg@public.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1SaPtg-0001Xs-F8 + for glN-linux-nfs-wOFGN7rlS/M9smdsby/KFg@public.gmane.org; Fri, 01 Jun 2012 13:20:00 +0200 +Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand + id S1759450Ab2FALT7 (ORCPT ); + Fri, 1 Jun 2012 07:19:59 -0400 +Original-Received: from mailhub.sw.ru ([195.214.232.25]:20534 "EHLO relay.sw.ru" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1759448Ab2FALT6 (ORCPT ); + Fri, 1 Jun 2012 07:19:58 -0400 +Original-Received: from localhost.localdomain ([10.30.21.131]) + by relay.sw.ru (8.13.4/8.13.4) with ESMTP id q51BJjDD010948; + Fri, 1 Jun 2012 15:19:46 +0400 (MSK) +In-Reply-To: <20120601111619.7846.95457.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org> +User-Agent: StGit/0.16 +Original-Sender: linux-nfs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-nfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Xref: news.gmane.org gmane.linux.nfs:50234 gmane.linux.kernel:1306565 gmane.linux.openvz.devel:1595 +Archived-At: + +This patch was back-ported from 3.5 kernel. + +New routine is responsible for service registration in specified network +context. +The idea is to separate service creation from per-net operations. +Since registering service with svc_bind() can fail, then service will be +destroyed and during destruction it will try to unregister itself from +rpcbind. In this case unregister have to be skipped. + +Signed-off-by: Stanislav Kinsbursky +--- + fs/lockd/svc.c | 6 ++++++ + fs/nfs/callback.c | 13 ++++++++++--- + fs/nfsd/nfssvc.c | 9 +++++++++ + include/linux/sunrpc/svc.h | 1 + + net/sunrpc/rpcb_clnt.c | 12 +++++++----- + net/sunrpc/svc.c | 19 ++++++++++--------- + 6 files changed, 43 insertions(+), 17 deletions(-) + +diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c +index f49b9af..b1d0708 100644 +--- a/fs/lockd/svc.c ++++ b/fs/lockd/svc.c +@@ -325,6 +325,12 @@ int lockd_up(void) + goto out; + } + ++ error = svc_bind(serv, net); ++ if (error < 0) { ++ printk(KERN_WARNING "lockd_up: bind service failed\n"); ++ goto destroy_and_out; ++ } ++ + error = make_socks(serv, net); + if (error < 0) + goto destroy_and_out; +diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c +index eb95f50..0563237 100644 +--- a/fs/nfs/callback.c ++++ b/fs/nfs/callback.c +@@ -106,7 +106,7 @@ nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) + { + int ret; + +- ret = svc_create_xprt(serv, "tcp", xprt->xprt_net, PF_INET, ++ ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET, + nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); + if (ret <= 0) + goto out_err; +@@ -114,7 +114,7 @@ nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) + dprintk("NFS: Callback listener port = %u (af %u)\n", + nfs_callback_tcpport, PF_INET); + +- ret = svc_create_xprt(serv, "tcp", xprt->xprt_net, PF_INET6, ++ ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET6, + nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); + if (ret > 0) { + nfs_callback_tcpport6 = ret; +@@ -183,7 +183,7 @@ nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) + * fore channel connection. + * Returns the input port (0) and sets the svc_serv bc_xprt on success + */ +- ret = svc_create_xprt(serv, "tcp-bc", xprt->xprt_net, PF_INET, 0, ++ ret = svc_create_xprt(serv, "tcp-bc", &init_net, PF_INET, 0, + SVC_SOCK_ANONYMOUS); + if (ret < 0) { + rqstp = ERR_PTR(ret); +@@ -253,6 +253,7 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) + char svc_name[12]; + int ret = 0; + int minorversion_setup; ++ struct net *net = &init_net; + + mutex_lock(&nfs_callback_mutex); + if (cb_info->users++ || cb_info->task != NULL) { +@@ -265,6 +266,12 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) + goto out_err; + } + ++ ret = svc_bind(serv, net); ++ if (ret < 0) { ++ printk(KERN_WARNING "NFS: bind callback service failed\n"); ++ goto out_err; ++ } ++ + minorversion_setup = nfs_minorversion_callback_svc_setup(minorversion, + serv, xprt, &rqstp, &callback_svc); + if (!minorversion_setup) { +diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c +index 28dfad3..a6461f3 100644 +--- a/fs/nfsd/nfssvc.c ++++ b/fs/nfsd/nfssvc.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -330,6 +331,8 @@ static int nfsd_get_default_max_blksize(void) + + int nfsd_create_serv(void) + { ++ int error; ++ + WARN_ON(!mutex_is_locked(&nfsd_mutex)); + if (nfsd_serv) { + svc_get(nfsd_serv); +@@ -343,6 +346,12 @@ int nfsd_create_serv(void) + if (nfsd_serv == NULL) + return -ENOMEM; + ++ error = svc_bind(nfsd_serv, current->nsproxy->net_ns); ++ if (error < 0) { ++ svc_destroy(nfsd_serv); ++ return error; ++ } ++ + set_max_drc(); + do_gettimeofday(&nfssvc_boot); /* record boot time */ + return 0; +diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h +index 51b29ac..2b43e02 100644 +--- a/include/linux/sunrpc/svc.h ++++ b/include/linux/sunrpc/svc.h +@@ -416,6 +416,7 @@ struct svc_procedure { + */ + int svc_rpcb_setup(struct svc_serv *serv, struct net *net); + void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net); ++int svc_bind(struct svc_serv *serv, struct net *net); + struct svc_serv *svc_create(struct svc_program *, unsigned int, + void (*shutdown)(struct svc_serv *, struct net *net)); + struct svc_rqst *svc_prepare_thread(struct svc_serv *serv, +diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c +index 78ac39f..4c38b33 100644 +--- a/net/sunrpc/rpcb_clnt.c ++++ b/net/sunrpc/rpcb_clnt.c +@@ -180,14 +180,16 @@ void rpcb_put_local(struct net *net) + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); + struct rpc_clnt *clnt = sn->rpcb_local_clnt; + struct rpc_clnt *clnt4 = sn->rpcb_local_clnt4; +- int shutdown; ++ int shutdown = 0; + + spin_lock(&sn->rpcb_clnt_lock); +- if (--sn->rpcb_users == 0) { +- sn->rpcb_local_clnt = NULL; +- sn->rpcb_local_clnt4 = NULL; ++ if (sn->rpcb_users) { ++ if (--sn->rpcb_users == 0) { ++ sn->rpcb_local_clnt = NULL; ++ sn->rpcb_local_clnt4 = NULL; ++ } ++ shutdown = !sn->rpcb_users; + } +- shutdown = !sn->rpcb_users; + spin_unlock(&sn->rpcb_clnt_lock); + + if (shutdown) { +diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c +index 4153846..e6d542c 100644 +--- a/net/sunrpc/svc.c ++++ b/net/sunrpc/svc.c +@@ -407,6 +407,14 @@ static int svc_uses_rpcbind(struct svc_serv *serv) + return 0; + } + ++int svc_bind(struct svc_serv *serv, struct net *net) ++{ ++ if (!svc_uses_rpcbind(serv)) ++ return 0; ++ return svc_rpcb_setup(serv, net); ++} ++EXPORT_SYMBOL_GPL(svc_bind); ++ + /* + * Create an RPC service + */ +@@ -471,15 +479,8 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, + spin_lock_init(&pool->sp_lock); + } + +- if (svc_uses_rpcbind(serv)) { +- if (svc_rpcb_setup(serv, current->nsproxy->net_ns) < 0) { +- kfree(serv->sv_pools); +- kfree(serv); +- return NULL; +- } +- if (!serv->sv_shutdown) +- serv->sv_shutdown = svc_rpcb_cleanup; +- } ++ if (svc_uses_rpcbind(serv) && (!serv->sv_shutdown)) ++ serv->sv_shutdown = svc_rpcb_cleanup; + + return serv; + } + +-- +To unsubscribe from this list: send the line "unsubscribe linux-nfs" in +the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + diff --git a/add-poll-requested-events.patch b/add-poll-requested-events.patch deleted file mode 100644 index dafd359e1..000000000 --- a/add-poll-requested-events.patch +++ /dev/null @@ -1,393 +0,0 @@ -commit 626cf236608505d376e4799adb4f7eb00a8594af -Author: Hans Verkuil -Date: Fri Mar 23 15:02:27 2012 -0700 - - poll: add poll_requested_events() and poll_does_not_wait() functions - - In some cases the poll() implementation in a driver has to do different - things depending on the events the caller wants to poll for. An example - is when a driver needs to start a DMA engine if the caller polls for - POLLIN, but doesn't want to do that if POLLIN is not requested but instead - only POLLOUT or POLLPRI is requested. This is something that can happen - in the video4linux subsystem among others. - - Unfortunately, the current epoll/poll/select implementation doesn't - provide that information reliably. The poll_table_struct does have it: it - has a key field with the event mask. But once a poll() call matches one - or more bits of that mask any following poll() calls are passed a NULL - poll_table pointer. - - Also, the eventpoll implementation always left the key field at ~0 instead - of using the requested events mask. - - This was changed in eventpoll.c so the key field now contains the actual - events that should be polled for as set by the caller. - - The solution to the NULL poll_table pointer is to set the qproc field to - NULL in poll_table once poll() matches the events, not the poll_table - pointer itself. That way drivers can obtain the mask through a new - poll_requested_events inline. - - The poll_table_struct can still be NULL since some kernel code calls it - internally (netfs_state_poll() in ./drivers/staging/pohmelfs/netfs.h). In - that case poll_requested_events() returns ~0 (i.e. all events). - - Very rarely drivers might want to know whether poll_wait will actually - wait. If another earlier file descriptor in the set already matched the - events the caller wanted to wait for, then the kernel will return from the - select() call without waiting. This might be useful information in order - to avoid doing expensive work. - - A new helper function poll_does_not_wait() is added that drivers can use - to detect this situation. This is now used in sock_poll_wait() in - include/net/sock.h. This was the only place in the kernel that needed - this information. - - Drivers should no longer access any of the poll_table internals, but use - the poll_requested_events() and poll_does_not_wait() access functions - instead. In order to enforce that the poll_table fields are now prepended - with an underscore and a comment was added warning against using them - directly. - - This required a change in unix_dgram_poll() in unix/af_unix.c which used - the key field to get the requested events. It's been replaced by a call - to poll_requested_events(). - - For qproc it was especially important to change its name since the - behavior of that field changes with this patch since this function pointer - can now be NULL when that wasn't possible in the past. - - Any driver accessing the qproc or key fields directly will now fail to compile. - - Some notes regarding the correctness of this patch: the driver's poll() - function is called with a 'struct poll_table_struct *wait' argument. This - pointer may or may not be NULL, drivers can never rely on it being one or - the other as that depends on whether or not an earlier file descriptor in - the select()'s fdset matched the requested events. - - There are only three things a driver can do with the wait argument: - - 1) obtain the key field: - - events = wait ? wait->key : ~0; - - This will still work although it should be replaced with the new - poll_requested_events() function (which does exactly the same). - This will now even work better, since wait is no longer set to NULL - unnecessarily. - - 2) use the qproc callback. This could be deadly since qproc can now be - NULL. Renaming qproc should prevent this from happening. There are no - kernel drivers that actually access this callback directly, BTW. - - 3) test whether wait == NULL to determine whether poll would return without - waiting. This is no longer sufficient as the correct test is now - wait == NULL || wait->_qproc == NULL. - - However, the worst that can happen here is a slight performance hit in - the case where wait != NULL and wait->_qproc == NULL. In that case the - driver will assume that poll_wait() will actually add the fd to the set - of waiting file descriptors. Of course, poll_wait() will not do that - since it tests for wait->_qproc. This will not break anything, though. - - There is only one place in the whole kernel where this happens - (sock_poll_wait() in include/net/sock.h) and that code will be replaced - by a call to poll_does_not_wait() in the next patch. - - Note that even if wait->_qproc != NULL drivers cannot rely on poll_wait() - actually waiting. The next file descriptor from the set might match the - event mask and thus any possible waits will never happen. - - Signed-off-by: Hans Verkuil - Reviewed-by: Jonathan Corbet - Reviewed-by: Al Viro - Cc: Davide Libenzi - Signed-off-by: Hans de Goede - Cc: Mauro Carvalho Chehab - Cc: David Miller - Cc: Eric Dumazet - Signed-off-by: Andrew Morton - Signed-off-by: Linus Torvalds - -diff --git a/fs/eventpoll.c b/fs/eventpoll.c -index 4d9d3a4..ca30007 100644 ---- a/fs/eventpoll.c -+++ b/fs/eventpoll.c -@@ -699,9 +699,12 @@ static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head, - void *priv) - { - struct epitem *epi, *tmp; -+ poll_table pt; - -+ init_poll_funcptr(&pt, NULL); - list_for_each_entry_safe(epi, tmp, head, rdllink) { -- if (epi->ffd.file->f_op->poll(epi->ffd.file, NULL) & -+ pt._key = epi->event.events; -+ if (epi->ffd.file->f_op->poll(epi->ffd.file, &pt) & - epi->event.events) - return POLLIN | POLLRDNORM; - else { -@@ -1097,6 +1100,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, - /* Initialize the poll table using the queue callback */ - epq.epi = epi; - init_poll_funcptr(&epq.pt, ep_ptable_queue_proc); -+ epq.pt._key = event->events; - - /* - * Attach the item to the poll hooks and get current event bits. -@@ -1191,6 +1195,9 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even - { - int pwake = 0; - unsigned int revents; -+ poll_table pt; -+ -+ init_poll_funcptr(&pt, NULL); - - /* - * Set the new event interest mask before calling f_op->poll(); -@@ -1198,13 +1205,14 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even - * f_op->poll() call and the new event set registering. - */ - epi->event.events = event->events; -+ pt._key = event->events; - epi->event.data = event->data; /* protected by mtx */ - - /* - * Get current event bits. We can safely use the file* here because - * its usage count has been increased by the caller of this function. - */ -- revents = epi->ffd.file->f_op->poll(epi->ffd.file, NULL); -+ revents = epi->ffd.file->f_op->poll(epi->ffd.file, &pt); - - /* - * If the item is "hot" and it is not registered inside the ready -@@ -1239,6 +1247,9 @@ static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head, - unsigned int revents; - struct epitem *epi; - struct epoll_event __user *uevent; -+ poll_table pt; -+ -+ init_poll_funcptr(&pt, NULL); - - /* - * We can loop without lock because we are passed a task private list. -@@ -1251,7 +1262,8 @@ static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head, - - list_del_init(&epi->rdllink); - -- revents = epi->ffd.file->f_op->poll(epi->ffd.file, NULL) & -+ pt._key = epi->event.events; -+ revents = epi->ffd.file->f_op->poll(epi->ffd.file, &pt) & - epi->event.events; - - /* -diff --git a/fs/select.c b/fs/select.c -index e782258..ecfd0b1 100644 ---- a/fs/select.c -+++ b/fs/select.c -@@ -223,7 +223,7 @@ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, - get_file(filp); - entry->filp = filp; - entry->wait_address = wait_address; -- entry->key = p->key; -+ entry->key = p->_key; - init_waitqueue_func_entry(&entry->wait, pollwake); - entry->wait.private = pwq; - add_wait_queue(wait_address, &entry->wait); -@@ -386,13 +386,11 @@ get_max: - static inline void wait_key_set(poll_table *wait, unsigned long in, - unsigned long out, unsigned long bit) - { -- if (wait) { -- wait->key = POLLEX_SET; -- if (in & bit) -- wait->key |= POLLIN_SET; -- if (out & bit) -- wait->key |= POLLOUT_SET; -- } -+ wait->_key = POLLEX_SET; -+ if (in & bit) -+ wait->_key |= POLLIN_SET; -+ if (out & bit) -+ wait->_key |= POLLOUT_SET; - } - - int do_select(int n, fd_set_bits *fds, struct timespec *end_time) -@@ -414,7 +412,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) - poll_initwait(&table); - wait = &table.pt; - if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { -- wait = NULL; -+ wait->_qproc = NULL; - timed_out = 1; - } - -@@ -459,17 +457,17 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) - if ((mask & POLLIN_SET) && (in & bit)) { - res_in |= bit; - retval++; -- wait = NULL; -+ wait->_qproc = NULL; - } - if ((mask & POLLOUT_SET) && (out & bit)) { - res_out |= bit; - retval++; -- wait = NULL; -+ wait->_qproc = NULL; - } - if ((mask & POLLEX_SET) && (ex & bit)) { - res_ex |= bit; - retval++; -- wait = NULL; -+ wait->_qproc = NULL; - } - } - } -@@ -481,7 +479,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) - *rexp = res_ex; - cond_resched(); - } -- wait = NULL; -+ wait->_qproc = NULL; - if (retval || timed_out || signal_pending(current)) - break; - if (table.error) { -@@ -720,7 +718,7 @@ struct poll_list { - * interested in events matching the pollfd->events mask, and the result - * matching that mask is both recorded in pollfd->revents and returned. The - * pwait poll_table will be used by the fd-provided poll handler for waiting, -- * if non-NULL. -+ * if pwait->_qproc is non-NULL. - */ - static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait) - { -@@ -738,9 +736,7 @@ static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait) - if (file != NULL) { - mask = DEFAULT_POLLMASK; - if (file->f_op && file->f_op->poll) { -- if (pwait) -- pwait->key = pollfd->events | -- POLLERR | POLLHUP; -+ pwait->_key = pollfd->events|POLLERR|POLLHUP; - mask = file->f_op->poll(file, pwait); - } - /* Mask out unneeded events. */ -@@ -763,7 +759,7 @@ static int do_poll(unsigned int nfds, struct poll_list *list, - - /* Optimise the no-wait case */ - if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { -- pt = NULL; -+ pt->_qproc = NULL; - timed_out = 1; - } - -@@ -781,22 +777,22 @@ static int do_poll(unsigned int nfds, struct poll_list *list, - for (; pfd != pfd_end; pfd++) { - /* - * Fish for events. If we found one, record it -- * and kill the poll_table, so we don't -+ * and kill poll_table->_qproc, so we don't - * needlessly register any other waiters after - * this. They'll get immediately deregistered - * when we break out and return. - */ - if (do_pollfd(pfd, pt)) { - count++; -- pt = NULL; -+ pt->_qproc = NULL; - } - } - } - /* - * All waiters have already been registered, so don't provide -- * a poll_table to them on the next loop iteration. -+ * a poll_table->_qproc to them on the next loop iteration. - */ -- pt = NULL; -+ pt->_qproc = NULL; - if (!count) { - count = wait->error; - if (signal_pending(current)) -diff --git a/include/linux/poll.h b/include/linux/poll.h -index cf40010..48fe8bc 100644 ---- a/include/linux/poll.h -+++ b/include/linux/poll.h -@@ -32,21 +32,46 @@ struct poll_table_struct; - */ - typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *); - -+/* -+ * Do not touch the structure directly, use the access functions -+ * poll_does_not_wait() and poll_requested_events() instead. -+ */ - typedef struct poll_table_struct { -- poll_queue_proc qproc; -- unsigned long key; -+ poll_queue_proc _qproc; -+ unsigned long _key; - } poll_table; - - static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p) - { -- if (p && wait_address) -- p->qproc(filp, wait_address, p); -+ if (p && p->_qproc && wait_address) -+ p->_qproc(filp, wait_address, p); -+} -+ -+/* -+ * Return true if it is guaranteed that poll will not wait. This is the case -+ * if the poll() of another file descriptor in the set got an event, so there -+ * is no need for waiting. -+ */ -+static inline bool poll_does_not_wait(const poll_table *p) -+{ -+ return p == NULL || p->_qproc == NULL; -+} -+ -+/* -+ * Return the set of events that the application wants to poll for. -+ * This is useful for drivers that need to know whether a DMA transfer has -+ * to be started implicitly on poll(). You typically only want to do that -+ * if the application is actually polling for POLLIN and/or POLLOUT. -+ */ -+static inline unsigned long poll_requested_events(const poll_table *p) -+{ -+ return p ? p->_key : ~0UL; - } - - static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc) - { -- pt->qproc = qproc; -- pt->key = ~0UL; /* all events enabled */ -+ pt->_qproc = qproc; -+ pt->_key = ~0UL; /* all events enabled */ - } - - struct poll_table_entry { -diff --git a/include/net/sock.h b/include/net/sock.h -index 04bc0b3..a6ba1f8 100644 ---- a/include/net/sock.h -+++ b/include/net/sock.h -@@ -1854,7 +1854,7 @@ static inline bool wq_has_sleeper(struct socket_wq *wq) - static inline void sock_poll_wait(struct file *filp, - wait_queue_head_t *wait_address, poll_table *p) - { -- if (p && wait_address) { -+ if (!poll_does_not_wait(p) && wait_address) { - poll_wait(filp, wait_address, p); - /* - * We need to be sure we are in sync with the -diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c -index eb4277c..d510353 100644 ---- a/net/unix/af_unix.c -+++ b/net/unix/af_unix.c -@@ -2206,7 +2206,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, - } - - /* No write status requested, avoid expensive OUT tests. */ -- if (wait && !(wait->key & (POLLWRBAND | POLLWRNORM | POLLOUT))) -+ if (!(poll_requested_events(wait) & (POLLWRBAND|POLLWRNORM|POLLOUT))) - return mask; - - writable = unix_writable(sk); diff --git a/atl1c_net_next_update-3.3.patch b/atl1c_net_next_update-3.4.patch similarity index 97% rename from atl1c_net_next_update-3.3.patch rename to atl1c_net_next_update-3.4.patch index 6c53ed607..1ec9771bc 100644 --- a/atl1c_net_next_update-3.3.patch +++ b/atl1c_net_next_update-3.4.patch @@ -178,7 +178,7 @@ index 0a9326a..859ea84 100644 static int atl1c_get_eeprom_len(struct net_device *netdev) diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c -index 23f2ab0..2ea6a21 100644 +index bd1667c..ff9c738 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c @@ -43,7 +43,7 @@ int atl1c_check_eeprom_exist(struct atl1c_hw *hw) @@ -376,14 +376,14 @@ index 23f2ab0..2ea6a21 100644 + AT_WRITE_REG(hw, REG_MDIO_CTRL, 0); + atl1c_wait_mdio_idle(hw); +} - ++ +void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel) +{ + u32 val; + + if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION)) + return; -+ + + val = MDIO_CTRL_SPRES_PRMBL | + FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | + FIELDX(MDIO_CTRL_REG, 1) | @@ -2024,7 +2024,7 @@ index 655fc6c..17d935b 100644 #endif /*_ATL1C_HW_H_*/ diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c -index 47a9bb2..f6f3fe3 100644 +index 1ef0c92..9cc1570 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -24,14 +24,6 @@ @@ -2282,16 +2282,16 @@ index 47a9bb2..f6f3fe3 100644 } -@@ -469,7 +474,7 @@ static int atl1c_set_mac_addr(struct net_device *netdev, void *p) - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); +@@ -470,7 +475,7 @@ static int atl1c_set_mac_addr(struct net_device *netdev, void *p) memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); + netdev->addr_assign_type &= ~NET_ADDR_RANDOM; - atl1c_hw_set_mac_addr(&adapter->hw); + atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr); return 0; } -@@ -522,11 +527,16 @@ static int atl1c_set_features(struct net_device *netdev, +@@ -523,11 +528,16 @@ static int atl1c_set_features(struct net_device *netdev, static int atl1c_change_mtu(struct net_device *netdev, int new_mtu) { struct atl1c_adapter *adapter = netdev_priv(netdev); @@ -2310,7 +2310,7 @@ index 47a9bb2..f6f3fe3 100644 if (netif_msg_link(adapter)) dev_warn(&adapter->pdev->dev, "invalid MTU setting\n"); return -EINVAL; -@@ -542,14 +552,6 @@ static int atl1c_change_mtu(struct net_device *netdev, int new_mtu) +@@ -543,14 +553,6 @@ static int atl1c_change_mtu(struct net_device *netdev, int new_mtu) netdev_update_features(netdev); atl1c_up(adapter); clear_bit(__AT_RESETTING, &adapter->flags); @@ -2325,7 +2325,7 @@ index 47a9bb2..f6f3fe3 100644 } return 0; } -@@ -562,7 +564,7 @@ static int atl1c_mdio_read(struct net_device *netdev, int phy_id, int reg_num) +@@ -563,7 +565,7 @@ static int atl1c_mdio_read(struct net_device *netdev, int phy_id, int reg_num) struct atl1c_adapter *adapter = netdev_priv(netdev); u16 result; @@ -2334,7 +2334,7 @@ index 47a9bb2..f6f3fe3 100644 return result; } -@@ -571,7 +573,7 @@ static void atl1c_mdio_write(struct net_device *netdev, int phy_id, +@@ -572,7 +574,7 @@ static void atl1c_mdio_write(struct net_device *netdev, int phy_id, { struct atl1c_adapter *adapter = netdev_priv(netdev); @@ -2343,7 +2343,7 @@ index 47a9bb2..f6f3fe3 100644 } /* -@@ -686,21 +688,15 @@ static void atl1c_set_mac_type(struct atl1c_hw *hw) +@@ -687,21 +689,15 @@ static void atl1c_set_mac_type(struct atl1c_hw *hw) static int atl1c_setup_mac_funcs(struct atl1c_hw *hw) { @@ -2367,7 +2367,7 @@ index 47a9bb2..f6f3fe3 100644 hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON; if (hw->nic_type == athr_l1c || -@@ -709,6 +705,55 @@ static int atl1c_setup_mac_funcs(struct atl1c_hw *hw) +@@ -710,6 +706,55 @@ static int atl1c_setup_mac_funcs(struct atl1c_hw *hw) hw->link_cap_flags |= ATL1C_LINK_CAP_1000M; return 0; } @@ -2423,7 +2423,7 @@ index 47a9bb2..f6f3fe3 100644 /* * atl1c_sw_init - Initialize general software structures (struct atl1c_adapter) * @adapter: board private structure to initialize -@@ -728,9 +773,8 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) +@@ -729,9 +774,8 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) device_set_wakeup_enable(&pdev->dev, false); adapter->link_speed = SPEED_0; adapter->link_duplex = FULL_DUPLEX; @@ -2434,7 +2434,7 @@ index 47a9bb2..f6f3fe3 100644 hw->vendor_id = pdev->vendor; hw->device_id = pdev->device; -@@ -745,26 +789,18 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) +@@ -746,26 +790,18 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) dev_err(&pdev->dev, "set mac function pointers failed\n"); return -1; } @@ -2463,7 +2463,7 @@ index 47a9bb2..f6f3fe3 100644 hw->rx_imt = 200; hw->tx_imt = 1000; -@@ -772,9 +808,6 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) +@@ -773,9 +809,6 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) hw->rfd_burst = 8; hw->dma_order = atl1c_dma_ord_out; hw->dmar_block = atl1c_dma_req_1024; @@ -2473,7 +2473,7 @@ index 47a9bb2..f6f3fe3 100644 if (atl1c_alloc_queues(adapter)) { dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); -@@ -850,24 +883,22 @@ static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter, +@@ -851,24 +884,22 @@ static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter, */ static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter) { @@ -2510,7 +2510,7 @@ index 47a9bb2..f6f3fe3 100644 } /* -@@ -876,8 +907,8 @@ static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter) +@@ -877,8 +908,8 @@ static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter) static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter) { struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring; @@ -2521,7 +2521,7 @@ index 47a9bb2..f6f3fe3 100644 struct atl1c_buffer *buffer_info; int i, j; -@@ -889,15 +920,13 @@ static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter) +@@ -890,15 +921,13 @@ static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter) ATL1C_SET_BUFFER_STATE(&buffer_info[i], ATL1C_BUFFER_FREE); } @@ -2544,7 +2544,7 @@ index 47a9bb2..f6f3fe3 100644 } } -@@ -934,27 +963,23 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) +@@ -935,27 +964,23 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring; @@ -2576,7 +2576,7 @@ index 47a9bb2..f6f3fe3 100644 tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL); if (unlikely(!tpd_ring->buffer_info)) { dev_err(&pdev->dev, "kzalloc failed, size = %d\n", -@@ -967,12 +992,11 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) +@@ -968,12 +993,11 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) count += tpd_ring[i].count; } @@ -2594,7 +2594,7 @@ index 47a9bb2..f6f3fe3 100644 /* * real ring DMA buffer * each ring/block may need up to 8 bytes for alignment, hence the -@@ -982,8 +1006,7 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) +@@ -983,8 +1007,7 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) sizeof(struct atl1c_tpd_desc) * tpd_ring->count * 2 + sizeof(struct atl1c_rx_free_desc) * rx_desc_count + sizeof(struct atl1c_recv_ret_status) * rx_desc_count + @@ -2604,7 +2604,7 @@ index 47a9bb2..f6f3fe3 100644 ring_header->desc = pci_alloc_consistent(pdev, ring_header->size, &ring_header->dma); -@@ -1004,25 +1027,18 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) +@@ -1005,25 +1028,18 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) offset += roundup(tpd_ring[i].size, 8); } /* init RFD ring */ @@ -2639,7 +2639,7 @@ index 47a9bb2..f6f3fe3 100644 return 0; err_nomem: -@@ -1033,26 +1049,20 @@ err_nomem: +@@ -1034,26 +1050,20 @@ err_nomem: static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) { struct atl1c_hw *hw = &adapter->hw; @@ -2670,7 +2670,7 @@ index 47a9bb2..f6f3fe3 100644 (u32)(tpd_ring[atl1c_trans_high].dma & AT_DMA_LO_ADDR_MASK)); AT_WRITE_REG(hw, REG_TPD_RING_SIZE, -@@ -1061,31 +1071,21 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) +@@ -1062,31 +1072,21 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) /* RFD */ AT_WRITE_REG(hw, REG_RX_BASE_ADDR_HI, @@ -2709,7 +2709,7 @@ index 47a9bb2..f6f3fe3 100644 if (hw->nic_type == athr_l2c_b) { AT_WRITE_REG(hw, REG_SRAM_RXF_LEN, 0x02a0L); AT_WRITE_REG(hw, REG_SRAM_TXF_LEN, 0x0100L); -@@ -1096,13 +1096,6 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) +@@ -1097,13 +1097,6 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) AT_WRITE_REG(hw, REG_TXF_WATER_MARK, 0); /* TX watermark, to enter l1 state.*/ AT_WRITE_REG(hw, REG_RXD_DMA_CTRL, 0); /* RXD threshold.*/ } @@ -2723,7 +2723,7 @@ index 47a9bb2..f6f3fe3 100644 /* Load all of base address above */ AT_WRITE_REG(hw, REG_LOAD_PTR, 1); } -@@ -1110,32 +1103,26 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) +@@ -1111,32 +1104,26 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) static void atl1c_configure_tx(struct atl1c_adapter *adapter) { struct atl1c_hw *hw = &adapter->hw; @@ -2770,7 +2770,7 @@ index 47a9bb2..f6f3fe3 100644 AT_WRITE_REG(hw, REG_TXQ_CTRL, txq_ctrl_data); } -@@ -1150,34 +1137,13 @@ static void atl1c_configure_rx(struct atl1c_adapter *adapter) +@@ -1151,34 +1138,13 @@ static void atl1c_configure_rx(struct atl1c_adapter *adapter) if (hw->ctrl_flags & ATL1C_RX_IPV6_CHKSUM) rxq_ctrl_data |= IPV6_CHKSUM_CTRL_EN; @@ -2810,7 +2810,7 @@ index 47a9bb2..f6f3fe3 100644 } static void atl1c_configure_dma(struct atl1c_adapter *adapter) -@@ -1185,36 +1151,11 @@ static void atl1c_configure_dma(struct atl1c_adapter *adapter) +@@ -1186,36 +1152,11 @@ static void atl1c_configure_dma(struct atl1c_adapter *adapter) struct atl1c_hw *hw = &adapter->hw; u32 dma_ctrl_data; @@ -2852,7 +2852,7 @@ index 47a9bb2..f6f3fe3 100644 AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data); } -@@ -1229,52 +1170,53 @@ static int atl1c_stop_mac(struct atl1c_hw *hw) +@@ -1230,52 +1171,53 @@ static int atl1c_stop_mac(struct atl1c_hw *hw) u32 data; AT_READ_REG(hw, REG_RXQ_CTRL, &data); @@ -2874,13 +2874,10 @@ index 47a9bb2..f6f3fe3 100644 AT_WRITE_REG(hw, REG_MAC_CTRL, data); - return (int)atl1c_wait_until_idle(hw); -+ return (int)atl1c_wait_until_idle(hw, -+ IDLE_STATUS_TXMAC_BUSY | IDLE_STATUS_RXMAC_BUSY); - } - +-} +- -static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw) -+static void atl1c_start_mac(struct atl1c_adapter *adapter) - { +-{ - u32 data; - - AT_READ_REG(hw, REG_RXQ_CTRL, &data); @@ -2899,10 +2896,13 @@ index 47a9bb2..f6f3fe3 100644 - } - data |= RXQ_CTRL_EN; - AT_WRITE_REG(hw, REG_RXQ_CTRL, data); --} -- ++ return (int)atl1c_wait_until_idle(hw, ++ IDLE_STATUS_TXMAC_BUSY | IDLE_STATUS_RXMAC_BUSY); + } + -static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw) --{ ++static void atl1c_start_mac(struct atl1c_adapter *adapter) + { - u32 data; + struct atl1c_hw *hw = &adapter->hw; + u32 mac, txq, rxq; @@ -2938,7 +2938,7 @@ index 47a9bb2..f6f3fe3 100644 } /* -@@ -1286,10 +1228,7 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) +@@ -1287,10 +1229,7 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) { struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter; struct pci_dev *pdev = adapter->pdev; @@ -2950,7 +2950,7 @@ index 47a9bb2..f6f3fe3 100644 atl1c_stop_mac(hw); /* -@@ -1298,194 +1237,148 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) +@@ -1299,194 +1238,148 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) * the current PCI configuration. The global reset bit is self- * clearing, and should clear within a microsecond. */ @@ -3238,7 +3238,7 @@ index 47a9bb2..f6f3fe3 100644 /* clear interrupt status */ AT_WRITE_REG(hw, REG_ISR, 0xFFFFFFFF); /* Clear any WOL status */ -@@ -1524,30 +1417,39 @@ static int atl1c_configure(struct atl1c_adapter *adapter) +@@ -1525,30 +1418,39 @@ static int atl1c_configure(struct atl1c_adapter *adapter) master_ctrl_data |= MASTER_CTRL_SA_TIMER_EN; AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); @@ -3290,7 +3290,7 @@ index 47a9bb2..f6f3fe3 100644 static void atl1c_update_hw_stats(struct atl1c_adapter *adapter) { u16 hw_reg_addr = 0; -@@ -1634,16 +1536,11 @@ static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter, +@@ -1635,16 +1537,11 @@ static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter, struct pci_dev *pdev = adapter->pdev; u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean); u16 hw_next_to_clean; @@ -3310,7 +3310,7 @@ index 47a9bb2..f6f3fe3 100644 while (next_to_clean != hw_next_to_clean) { buffer_info = &tpd_ring->buffer_info[next_to_clean]; -@@ -1745,9 +1642,9 @@ static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter, +@@ -1746,9 +1643,9 @@ static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter, skb_checksum_none_assert(skb); } @@ -3322,7 +3322,7 @@ index 47a9bb2..f6f3fe3 100644 struct pci_dev *pdev = adapter->pdev; struct atl1c_buffer *buffer_info, *next_info; struct sk_buff *skb; -@@ -1799,7 +1696,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid +@@ -1800,7 +1697,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid /* TODO: update mailbox here */ wmb(); rfd_ring->next_to_use = rfd_next_to_use; @@ -3331,7 +3331,7 @@ index 47a9bb2..f6f3fe3 100644 rfd_ring->next_to_use & MB_RFDX_PROD_IDX_MASK); } -@@ -1838,7 +1735,7 @@ static void atl1c_clean_rfd(struct atl1c_rfd_ring *rfd_ring, +@@ -1839,7 +1736,7 @@ static void atl1c_clean_rfd(struct atl1c_rfd_ring *rfd_ring, rfd_ring->next_to_clean = rfd_index; } @@ -3340,7 +3340,7 @@ index 47a9bb2..f6f3fe3 100644 int *work_done, int work_to_do) { u16 rfd_num, rfd_index; -@@ -1846,8 +1743,8 @@ static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que, +@@ -1847,8 +1744,8 @@ static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que, u16 length; struct pci_dev *pdev = adapter->pdev; struct net_device *netdev = adapter->netdev; @@ -3351,7 +3351,7 @@ index 47a9bb2..f6f3fe3 100644 struct sk_buff *skb; struct atl1c_recv_ret_status *rrs; struct atl1c_buffer *buffer_info; -@@ -1913,7 +1810,7 @@ rrs_checked: +@@ -1914,7 +1811,7 @@ rrs_checked: count++; } if (count) @@ -3360,7 +3360,7 @@ index 47a9bb2..f6f3fe3 100644 } /* -@@ -1930,7 +1827,7 @@ static int atl1c_clean(struct napi_struct *napi, int budget) +@@ -1931,7 +1828,7 @@ static int atl1c_clean(struct napi_struct *napi, int budget) if (!netif_carrier_ok(adapter->netdev)) goto quit_polling; /* just enable one RXQ */ @@ -3369,7 +3369,7 @@ index 47a9bb2..f6f3fe3 100644 if (work_done < budget) { quit_polling: -@@ -2205,23 +2102,10 @@ static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb, +@@ -2206,23 +2103,10 @@ static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb, struct atl1c_tpd_desc *tpd, enum atl1c_trans_queue type) { struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; @@ -3396,7 +3396,17 @@ index 47a9bb2..f6f3fe3 100644 } static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb, -@@ -2327,44 +2211,38 @@ static int atl1c_request_irq(struct atl1c_adapter *adapter) +@@ -2307,8 +2191,7 @@ static int atl1c_request_irq(struct atl1c_adapter *adapter) + "Unable to allocate MSI interrupt Error: %d\n", + err); + adapter->have_msi = false; +- } else +- netdev->irq = pdev->irq; ++ } + + if (!adapter->have_msi) + flags |= IRQF_SHARED; +@@ -2328,44 +2211,38 @@ static int atl1c_request_irq(struct atl1c_adapter *adapter) return err; } @@ -3420,7 +3430,7 @@ index 47a9bb2..f6f3fe3 100644 - atl1c_init_ring_ptrs(adapter); - atl1c_set_multi(netdev); - atl1c_restore_vlan(adapter); -- + - for (i = 0; i < adapter->num_rx_queues; i++) { - num = atl1c_alloc_rx_buffer(adapter, i); - if (unlikely(num == 0)) { @@ -3428,7 +3438,7 @@ index 47a9bb2..f6f3fe3 100644 - goto err_alloc_rx; - } - } - +- - if (atl1c_configure(adapter)) { - err = -EIO; + err = atl1c_configure(adapter); @@ -3453,7 +3463,7 @@ index 47a9bb2..f6f3fe3 100644 atl1c_clean_rx_ring(adapter); return err; } -@@ -2382,15 +2260,15 @@ static void atl1c_down(struct atl1c_adapter *adapter) +@@ -2383,15 +2260,15 @@ static void atl1c_down(struct atl1c_adapter *adapter) napi_disable(&adapter->napi); atl1c_irq_disable(adapter); atl1c_free_irq(adapter); @@ -3472,7 +3482,7 @@ index 47a9bb2..f6f3fe3 100644 } /* -@@ -2423,13 +2301,6 @@ static int atl1c_open(struct net_device *netdev) +@@ -2424,13 +2301,6 @@ static int atl1c_open(struct net_device *netdev) if (unlikely(err)) goto err_up; @@ -3486,7 +3496,7 @@ index 47a9bb2..f6f3fe3 100644 return 0; err_up: -@@ -2455,6 +2326,8 @@ static int atl1c_close(struct net_device *netdev) +@@ -2456,6 +2326,8 @@ static int atl1c_close(struct net_device *netdev) struct atl1c_adapter *adapter = netdev_priv(netdev); WARN_ON(test_bit(__AT_RESETTING, &adapter->flags)); @@ -3495,7 +3505,7 @@ index 47a9bb2..f6f3fe3 100644 atl1c_down(adapter); atl1c_free_ring_resources(adapter); return 0; -@@ -2466,10 +2339,6 @@ static int atl1c_suspend(struct device *dev) +@@ -2467,10 +2339,6 @@ static int atl1c_suspend(struct device *dev) struct net_device *netdev = pci_get_drvdata(pdev); struct atl1c_adapter *adapter = netdev_priv(netdev); struct atl1c_hw *hw = &adapter->hw; @@ -3506,7 +3516,7 @@ index 47a9bb2..f6f3fe3 100644 u32 wufc = adapter->wol; atl1c_disable_l0s_l1(hw); -@@ -2480,75 +2349,10 @@ static int atl1c_suspend(struct device *dev) +@@ -2481,75 +2349,10 @@ static int atl1c_suspend(struct device *dev) netif_device_detach(netdev); if (wufc) @@ -3584,7 +3594,7 @@ index 47a9bb2..f6f3fe3 100644 return 0; } -@@ -2561,8 +2365,7 @@ static int atl1c_resume(struct device *dev) +@@ -2562,8 +2365,7 @@ static int atl1c_resume(struct device *dev) struct atl1c_adapter *adapter = netdev_priv(netdev); AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0); @@ -3594,7 +3604,22 @@ index 47a9bb2..f6f3fe3 100644 atl1c_phy_reset(&adapter->hw); atl1c_reset_mac(&adapter->hw); -@@ -2713,7 +2516,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, +@@ -2616,7 +2418,6 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev) + SET_NETDEV_DEV(netdev, &pdev->dev); + pci_set_drvdata(pdev, netdev); + +- netdev->irq = pdev->irq; + netdev->netdev_ops = &atl1c_netdev_ops; + netdev->watchdog_timeo = AT_TX_WATCHDOG; + atl1c_set_ethtool_ops(netdev); +@@ -2706,14 +2507,13 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, + dev_err(&pdev->dev, "cannot map device registers\n"); + goto err_ioremap; + } +- netdev->base_addr = (unsigned long)adapter->hw.hw_addr; + + /* init mii data */ + adapter->mii.dev = netdev; adapter->mii.mdio_read = atl1c_mdio_read; adapter->mii.mdio_write = atl1c_mdio_write; adapter->mii.phy_id_mask = 0x1f; @@ -3603,7 +3628,7 @@ index 47a9bb2..f6f3fe3 100644 netif_napi_add(netdev, &adapter->napi, atl1c_clean, 64); setup_timer(&adapter->phy_config_timer, atl1c_phy_config, (unsigned long)adapter); -@@ -2723,8 +2526,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, +@@ -2723,8 +2523,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, dev_err(&pdev->dev, "net device private data init failed\n"); goto err_sw_init; } @@ -3613,7 +3638,7 @@ index 47a9bb2..f6f3fe3 100644 /* Init GPHY as early as possible due to power saving issue */ atl1c_phy_reset(&adapter->hw); -@@ -2753,7 +2555,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, +@@ -2752,7 +2551,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, dev_dbg(&pdev->dev, "mac address : %pM\n", adapter->hw.mac_addr); @@ -3622,7 +3647,7 @@ index 47a9bb2..f6f3fe3 100644 INIT_WORK(&adapter->common_task, atl1c_common_task); adapter->work_event = 0; err = register_netdev(netdev); -@@ -2798,6 +2600,8 @@ static void __devexit atl1c_remove(struct pci_dev *pdev) +@@ -2796,6 +2595,8 @@ static void __devexit atl1c_remove(struct pci_dev *pdev) struct atl1c_adapter *adapter = netdev_priv(netdev); unregister_netdev(netdev); diff --git a/bluetooth-use-after-free.patch b/bluetooth-use-after-free.patch deleted file mode 100644 index 0d21cad9a..000000000 --- a/bluetooth-use-after-free.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 2a5a5ec620a29d4ba07743c3151cdf0a417c8f8c Mon Sep 17 00:00:00 2001 -From: Andrei Emeltchenko -Date: Thu, 2 Feb 2012 10:32:18 +0200 -Subject: [PATCH] Bluetooth: Use list _safe deleting from conn chan_list - -Fixes possible bug when deleting element from the list in -function hci_chan_list_flush. list_for_each_entry_rcu is used -and after deleting element from the list we also free pointer -and then list_entry_rcu is taken from freed pointer. - -Signed-off-by: Andrei Emeltchenko -Acked-by: Marcel Holtmann -Signed-off-by: Johan Hedberg ---- - net/bluetooth/hci_conn.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c -index b074bd6..b4ecdde 100644 ---- a/net/bluetooth/hci_conn.c -+++ b/net/bluetooth/hci_conn.c -@@ -975,10 +975,10 @@ int hci_chan_del(struct hci_chan *chan) - - void hci_chan_list_flush(struct hci_conn *conn) - { -- struct hci_chan *chan; -+ struct hci_chan *chan, *n; - - BT_DBG("conn %p", conn); - -- list_for_each_entry_rcu(chan, &conn->chan_list, list) -+ list_for_each_entry_safe(chan, n, &conn->chan_list, list) - hci_chan_del(chan); - } --- -1.7.6.5 - -From 3c4e0df028935618d052235ba85bc7079be13394 Mon Sep 17 00:00:00 2001 -From: Andrei Emeltchenko -Date: Thu, 2 Feb 2012 10:32:17 +0200 -Subject: [PATCH] Bluetooth: Use list _safe deleting from conn_hash_list - -Use list_for_each_entry_safe which is safe version against removal -of list entry. Otherwise we remove hci_conn element and reference -next element which result in accessing LIST_POISON. - -[ 95.571834] Bluetooth: unknown link type 127 -[ 95.578349] BUG: unable to handle kernel paging request at 20002000 -[ 95.580236] IP: [<20002000>] 0x20001fff -[ 95.580763] *pde = 00000000 -[ 95.581196] Oops: 0000 [#1] SMP -... -[ 95.582298] Pid: 3355, comm: hciconfig Tainted: G O 3.2.0-VirttualBox -[ 95.582298] EIP: 0060:[<20002000>] EFLAGS: 00210206 CPU: 0 -[ 95.582298] EIP is at 0x20002000 -... -[ 95.582298] Call Trace: -[ 95.582298] [] ? hci_conn_hash_flush+0x76/0xf0 [bluetooth] -[ 95.582298] [] hci_dev_do_close+0xc1/0x2e0 [bluetooth] -[ 95.582298] [] ? hci_dev_get+0x69/0xb0 [bluetooth] -[ 95.582298] [] hci_dev_close+0x2a/0x50 [bluetooth] -[ 95.582298] [] hci_sock_ioctl+0x1af/0x3f0 [bluetooth] -[ 95.582298] [] ? handle_pte_fault+0x8a/0x8f0 -[ 95.582298] [] sock_ioctl+0x5f/0x260 -[ 95.582298] [] ? sock_fasync+0x90/0x90 -[ 95.582298] [] do_vfs_ioctl+0x83/0x5b0 -[ 95.582298] [] ? do_page_fault+0x297/0x500 -[ 95.582298] [] ? spurious_fault+0xd0/0xd0 -[ 95.582298] [] ? up_read+0x1b/0x30 -[ 95.582298] [] ? do_page_fault+0x297/0x500 -[ 95.582298] [] ? init_fpu+0xef/0x160 -[ 95.582298] [] ? do_debug+0x180/0x180 -[ 95.582298] [] ? fpu_finit+0x28/0x80 -[ 95.582298] [] sys_ioctl+0x87/0x90 -[ 95.582298] [] sysenter_do_call+0x12/0x38 -... - -Signed-off-by: Andrei Emeltchenko -Acked-by: Marcel Holtmann -Signed-off-by: Johan Hedberg ---- - net/bluetooth/hci_conn.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c -index aca71c0..b074bd6 100644 ---- a/net/bluetooth/hci_conn.c -+++ b/net/bluetooth/hci_conn.c -@@ -795,11 +795,11 @@ timer: - void hci_conn_hash_flush(struct hci_dev *hdev) - { - struct hci_conn_hash *h = &hdev->conn_hash; -- struct hci_conn *c; -+ struct hci_conn *c, *n; - - BT_DBG("hdev %s", hdev->name); - -- list_for_each_entry_rcu(c, &h->list, list) { -+ list_for_each_entry_safe(c, n, &h->list, list) { - c->state = BT_CLOSED; - - hci_proto_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM); --- -1.7.6.5 - diff --git a/config-arm-generic b/config-arm-generic index 6cb515ddb..80a7f2b87 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -1,15 +1,35 @@ CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y -# CONFIG_SMP is not set +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_ARM_CPU_TOPOLOGY=y +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y # CONFIG_CMDLINE_FORCE is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_ARCH_VERSATILE=y -CONFIG_ARCH_VERSATILE_PB=y -CONFIG_MACH_VERSATILE_AB=y -CONFIG_MACH_VERSATILE_DT=y +CONFIG_ARCH_VEXPRESS=y +CONFIG_ARCH_VEXPRESS_CA9X4=y +CONFIG_ARCH_VEXPRESS_DT=y +CONFIG_PLAT_VERSATILE_CLCD=y +CONFIG_PLAT_VERSATILE_SCHED_CLOCK=y +CONFIG_PLAT_VERSATILE=y +CONFIG_ARM_TIMER_SP804=y + +CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y CONFIG_HIGHMEM=y # CONFIG_HIGHPTE is not set @@ -26,9 +46,18 @@ CONFIG_ZBOOT_ROM_BSS=0 CONFIG_ATAGS_PROC=y +CONFIG_CPU_IDLE=y +# CONFIG_CPU_IDLE_GOV_LADDER is not set +ONFIG_CPU_IDLE_GOV_MENU=y + +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + # CONFIG_FPE_NWFPE is not set CONFIG_FPE_FASTFPE=y CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y CONFIG_PM=y # CONFIG_PM_DEBUG is not set @@ -42,15 +71,12 @@ CONFIG_ARM_THUMB=y CONFIG_AEABI=y CONFIG_OABI_COMPAT=y +CONFIG_HW_PERF_EVENTS=y + # CONFIG_UACCESS_WITH_MEMCPY is not set CONFIG_CMDLINE="console=ttyAM0,115200 root=/dev/sda1 rootdelay=20" -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y - -# CONFIG_CPU_IDLE is not set - CONFIG_LEDS=y CONFIG_LEDS_CPU=y @@ -94,16 +120,20 @@ CONFIG_USB_TUSB6010=y CONFIG_MMC_ARMMMCI=m CONFIG_MMC_DW=m +CONFIG_MMC_DW_PLTFM=y +# CONFIG_MMC_DW_PCI is not set # CONFIG_MMC_DW_IDMAC is not set -CONFIG_RTC_DRV_PL030=m -CONFIG_RTC_DRV_PL031=m +CONFIG_RTC_DRV_PL030=y +CONFIG_RTC_DRV_PL031=y # CONFIG_SGI_IOC4 is not set # CONFIG_DEBUG_USER is not set # CONFIG_DEBUG_ERRORS is not set # CONFIG_DEBUG_LL is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_IRQ_DOMAIN_DEBUG is not set CONFIG_ARM_UNWIND=y @@ -164,6 +194,36 @@ CONFIG_PL330_DMA=y CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 CONFIG_LSM_MMAP_MIN_ADDR=32768 +# CONFIG_ARM_LPAE is not set +# CONFIG_ARM_THUMBEE is not set +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_CACHE_L2X0=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_742230 is not set +# CONFIG_ARM_ERRATA_742231 is not set +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_ARM_ERRATA_754327 is not set +# CONFIG_ARM_ERRATA_764369 is not set +# CONFIG_PL310_ERRATA_769419 is not set +CONFIG_SCHED_MC=y +# CONFIG_SCHED_SMT is not set +CONFIG_LOCAL_TIMERS=y +# CONFIG_THUMB2_KERNEL is not set +# CONFIG_PATA_PLATFORM is not set +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_MPCORE_WATCHDOG is not set + +CONFIG_DVB_PLL=m +CONFIG_DVB_TDA1004X=m + # disable TPM on arm at least on the trimslices it causes havoc # CONFIG_TCG_TPM is not set # CONFIG_IMA is not set @@ -179,6 +239,7 @@ CONFIG_LSM_MMAP_MIN_ADDR=32768 # CONFIG_DRM_RADEON is not set # CONFIG_ATM_HE is not set # CONFIG_SCSI_ACARD is not set +# CONFIG_SFC is not set # these all currently fail due to missing symbols __bad_udelay or # error: implicit declaration of function ‘iowrite32be’ @@ -186,24 +247,25 @@ CONFIG_LSM_MMAP_MIN_ADDR=32768 # CONFIG_DRM_NOUVEAU is not set # CONFIG_MLX4_EN is not set +# drivers/input/touchscreen/eeti_ts.c:65:2: error: implicit declaration of function 'irq_to_gpio' [-Werror=implicit-function-declaration] +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# # FIXME: Guesses, need checking # CONFIG_MACH_EUKREA_CPUIMX35SD is not set CONFIG_ARM_ERRATA_720789=y CONFIG_ARM_ERRATA_751472=y -<<<<<<< HEAD -======= CONFIG_ARM_ERRATA_326103=y -CONFIG_OMAP4_ERRATA_I688=y ->>>>>>> 99667a9... Linux 3.3.5 +# CONFIG_OMAP4_ERRATA_I688 is not set # CONFIG_FB_MX3 is not set # CONFIG_MX3_IPU is not set # CONFIG_MX3_IPU_IRQS is not set -# CONFIG_OF_SELFTEST is not set -# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set -# CONFIG_INPUT_GP2A is not set -# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_CS89x0 is not set +# CONFIG_OF_SELFTEST is not set # CONFIG_MACH_IMX51_DT is not set # CONFIG_MACH_IMX53_DT is not set # CONFIG_MACH_MX53_EVK is not set @@ -211,3 +273,93 @@ CONFIG_OMAP4_ERRATA_I688=y # CONFIG_MACH_MX53_LOCO is not set # CONFIG_MACH_MX53_ARD is not set # CONFIG_ARM_EXYNOS4210_CPUFREQ is not set + +CONFIG_OF_GPIO=y +CONFIG_INPUT_GP2A=m +CONFIG_INPUT_GPIO_TILT_POLLED=m + +CONFIG_BPF_JIT=y + +CONFIG_MTD=m +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_AFS_PARTS=y +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLKDEVS=m +CONFIG_MTD_BLOCK=m +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_BLOCK_RO is not set +# CONFIG_MTD_AR7_PARTS is not set +CONFIG_MTD_CFI=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +CONFIG_MTD_CFI_GEOMETRY=y +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_DOC2000=m +CONFIG_MTD_DOC2001=m +CONFIG_MTD_DOC2001PLUS=m +# CONFIG_MTD_DOCPROBE_ADVANCED is not set +CONFIG_MTD_ALAUDA=m +# CONFIG_MTD_ONENAND is not set +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_PHYSMAP=m +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_M25P80=m +CONFIG_M25PXX_USE_FAST_READ=y +CONFIG_MTD_NAND=m +CONFIG_MTD_NAND_ECC=m +CONFIG_MTD_NAND_IDS=m +# CONFIG_MTD_NAND_CAFE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_DENALI is not set +# CONFIG_MTD_NAND_DOCG4 is not set +CONFIG_MTD_NAND_GPIO=m +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_NAND_NANDSIM is not set +CONFIG_MTD_NAND_ORION=m +# CONFIG_MTD_NAND_RICOH is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_OTP is not set +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_SLRAM is not set +CONFIG_MTD_UBI=m +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_RESERVE=1 +# CONFIG_MTD_UBI_GLUEBI is not set +# CONFIG_MTD_UBI_DEBUG is not set + +# CONFIG_SM_FTL is not set + +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set + +CONFIG_UBIFS_FS=m +CONFIG_UBIFS_FS_XATTR=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_FS_DEBUG is not set diff --git a/config-arm-highbank b/config-arm-highbank index 8cd7fc3b5..60178dd1f 100644 --- a/config-arm-highbank +++ b/config-arm-highbank @@ -1,17 +1,31 @@ -ONFIG_ARCH_HIGHBANK=y -CONFIG_VFP=y -CONFIG_NEON=y +CONFIG_ARCH_HIGHBANK=y +# CONFIG_ARM_LPAE is not set +# CONFIG_ARM_THUMBEE is not set +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_BPREDICT_DISABLE is not set +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_PL310_ERRATA_753970 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_PL310_ERRATA_769419 is not set -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_DEBUG=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=m -CONFIG_CPU_FREQ_GOV_USERSPACE=m -CONFIG_CPU_FREQ_GOV_ONDEMAND=m -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m -CONFIG_CPU_FREQ_TABLE=y -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_THUMB2_KERNEL is not set + +CONFIG_ARM_TIMER_SP804=y + +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_ATA_SFF=y + +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_BROADCOM=y CONFIG_NET_CALXEDA_XGMAC=y + +CONFIG_GPIO_PL061=y + +CONFIG_SERIAL_AMBA_PL010=y +CONFIG_SERIAL_AMBA_PL010_CONSOLE=y + diff --git a/config-arm-imx b/config-arm-imx index 2dbe10a1f..493769814 100644 --- a/config-arm-imx +++ b/config-arm-imx @@ -3,8 +3,6 @@ CONFIG_ARCH_MX51=y CONFIG_MACH_MX51_BABBAGE=y CONFIG_MACH_MX51_3DS=y CONFIG_MACH_EUKREA_CPUIMX51=y -CONFIG_VFP=y -CONFIG_NEON=y CONFIG_MACH_EUKREA_CPUIMX51SD=y CONFIG_MACH_MX51_EFIKAMX=y @@ -13,6 +11,7 @@ CONFIG_MACH_MX51_EFIKASB=y # CONFIG_THUMB2_KERNEL is not set CONFIG_CPU_FREQ_IMX=y CONFIG_W1_MASTER_MXC=m +CONFIG_IMX_DMA=m CONFIG_IMX_SDMA=y CONFIG_MACH_MX31ADS=y CONFIG_MACH_MX31LILLY=y @@ -33,13 +32,12 @@ CONFIG_MXC_IRQ_PRIOR=y CONFIG_MXC_PWM=m CONFIG_MXC_DEBUG_BOARD=y # CONFIG_CPU_BPREDICT_DISABLE is not set -# CONFIG_CACHE_L2X0 is not set +CONFIG_CACHE_L2X0=y CONFIG_ARM_DMA_MEM_BUFFERABLE=y CONFIG_ARM_ERRATA_411920=y CONFIG_PL310_ERRATA_588369=y CONFIG_PL310_ERRATA_727915=y CONFIG_ARM_ERRATA_364296=y -CONFIG_HW_PERF_EVENTS=y CONFIG_RFKILL_GPIO=m CONFIG_PATA_IMX=m CONFIG_ETHERNET=y @@ -52,14 +50,13 @@ CONFIG_HW_RANDOM_MXC_RNGA=m CONFIG_I2C_IMX=m CONFIG_GPIO_GENERIC_PLATFORM=y CONFIG_GPIO_MCP23S08=m -CONFIG_DVB_TDA1004X=m -CONFIG_DVB_PLL=m +# CONFIG_GPIO_MC9S08DZ60 is not set CONFIG_SND_IMX_SOC=m CONFIG_USB_EHCI_MXC=y -CONFIG_USB_IMX21_HCD=m +# CONFIG_USB_IMX21_HCD is not set CONFIG_MMC_SDHCI_ESDHC_IMX=m CONFIG_MMC_MXC=m -CONFIG_RTC_MXC=m +CONFIG_RTC_MXC=y CONFIG_BACKLIGHT_PWM=m CONFIG_LEDS_PWM=m @@ -81,18 +78,12 @@ CONFIG_IMX2_WDT=m CONFIG_SND_SOC_PHYCORE_AC97=m CONFIG_SND_SOC_EUKREA_TLV320=m -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_DEBUG=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=m -CONFIG_CPU_FREQ_GOV_USERSPACE=m -CONFIG_CPU_FREQ_GOV_ONDEMAND=m -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m -CONFIG_CPU_FREQ_TABLE=y -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_FREQ_STAT_DETAILS=y - CONFIG_PL310_ERRATA_769419=y CONFIG_LEDS_RENESAS_TPU=y + +# CONFIG_ARM_LPAE is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set + +CONFIG_MFD_ANATOP=y + diff --git a/config-arm-kirkwood b/config-arm-kirkwood index 415e822dc..3d3466bc4 100644 --- a/config-arm-kirkwood +++ b/config-arm-kirkwood @@ -1,4 +1,7 @@ CONFIG_ARCH_KIRKWOOD=y +CONFIG_ARCH_KIRKWOOD_DT=y +# CONFIG_SMP is not set +# CONFIG_VFP is not set CONFIG_MACH_DB88F6281_BP=y CONFIG_MACH_RD88F6192_NAS=y CONFIG_MACH_RD88F6281=y @@ -6,6 +9,7 @@ CONFIG_MACH_MV88F6281GTW_GE=y CONFIG_MACH_SHEEVAPLUG=y CONFIG_MACH_ESATA_SHEEVAPLUG=y CONFIG_MACH_GURUPLUG=y +CONFIG_MACH_DREAMPLUG_DT=y CONFIG_MACH_DOCKSTAR=y CONFIG_MACH_TS219=y CONFIG_MACH_TS41X=y @@ -36,8 +40,15 @@ CONFIG_SND_KIRKWOOD_SOC_T5325=m CONFIG_MMC_MVSDIO=m CONFIG_LEDS_NS2=m CONFIG_LEDS_NETXBIG=m -CONFIG_RTC_DRV_MV=m +CONFIG_RTC_DRV_MV=y CONFIG_MV_XOR=y CONFIG_CRYPTO_DEV_MV_CESA=m -# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set + + +# CONFIG_VFP is not set +# CONFIG_VFPv3 is not set +# CONFIG_NEON is not set +# CONFIG_SMP is not set diff --git a/config-arm-omap-generic b/config-arm-omap-generic index de17513e4..c4f22dc3d 100644 --- a/config-arm-omap-generic +++ b/config-arm-omap-generic @@ -1,3 +1,5 @@ +# CONFIG_OMAP4_ERRATA_I688 is not set + CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y CONFIG_GENERIC_LOCKBREAK=y @@ -10,7 +12,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_RCU_BOOST is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y -# CONFIG_BLK_CGROUP is not set # CONFIG_SCHED_AUTOGROUP is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -143,9 +144,7 @@ CONFIG_LOCAL_TIMERS=y CONFIG_PREEMPT=y CONFIG_HZ=128 # CONFIG_THUMB2_KERNEL is not set -# CONFIG_OABI_COMPAT is not set CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y -CONFIG_HW_PERF_EVENTS=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_KSM is not set # CONFIG_CC_STACKPROTECTOR is not set @@ -153,23 +152,6 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CMDLINE="" # CONFIG_AUTO_ZRELADDR is not set -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_TABLE=y -CONFIG_CPU_FREQ_DEBUG=y -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_FREQ_STAT_DETAILS=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_IDLE=y -CONFIG_CPU_IDLE_GOV_LADDER=y -CONFIG_CPU_IDLE_GOV_MENU=y CONFIG_VFPv3=y CONFIG_NEON=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set @@ -242,6 +224,7 @@ CONFIG_MTD_NAND_ECC=y CONFIG_MTD_NAND=y # CONFIG_MTD_SM_COMMON is not set # CONFIG_MTD_NAND_GPIO is not set +# CONFIG_MTD_NAND_DOCG4 is not set CONFIG_MTD_NAND_OMAP2=y CONFIG_MTD_NAND_OMAP_PREFETCH=y CONFIG_MTD_NAND_OMAP_PREFETCH_DMA=y @@ -377,6 +360,7 @@ CONFIG_TOUCHSCREEN_AD7879_I2C=m CONFIG_TOUCHSCREEN_CY8CTMG110=m CONFIG_TOUCHSCREEN_HAMPSHIRE=m CONFIG_TOUCHSCREEN_QT602240=m +CONFIG_TOUCHSCREEN_TI_TSCADC=m CONFIG_TOUCHSCREEN_TPS6507X=m # CONFIG_TOUCHSCREEN_TSC2005 is not set CONFIG_INPUT_AD714X=m @@ -386,6 +370,7 @@ CONFIG_INPUT_AD714X_SPI=m CONFIG_INPUT_TWL4030_PWRBUTTON=y CONFIG_INPUT_TWL4030_VIBRA=y CONFIG_INPUT_TWL6040_VIBRA=y +CONFIG_KEYBOARD_OMAP4=m CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set CONFIG_INPUT_ADXL34X=m @@ -577,14 +562,17 @@ CONFIG_TWL4030_CORE=y CONFIG_TWL4030_POWER=y CONFIG_TWL4030_CODEC=y # CONFIG_TWL6030_PWM is not set +# CONFIG_TWL6040_CORE is not set # CONFIG_MFD_STMPE is not set # CONFIG_MFD_TC3589X is not set # CONFIG_MFD_TC6393XB is not set +# CONFIG_MFD_TPS65090 is not set/ # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_WM831X_SPI is not set @@ -612,6 +600,7 @@ CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_TWL4030=y # CONFIG_REGULATOR_LP3971 is not set # CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_TPS62360 is not set # CONFIG_REGULATOR_TPS65023 is not set # CONFIG_REGULATOR_TPS6507X is not set # CONFIG_REGULATOR_ISL6271A is not set @@ -679,9 +668,9 @@ CONFIG_RADIO_TEF6862=m # CONFIG_TTPCI_EEPROM is not set # CONFIG_SMS_SDIO_DRV is not set # CONFIG_DVB_DUMMY_FE is not set -CONFIG_DVB_TDA1004X=m -CONFIG_DVB_PLL=m -# CONFIG_DRM is not set +CONFIG_DRM=m +CONFIG_DRM_OMAP=m +CONFIG_DRM_OMAP_NUM_CRTCS=2 # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set # CONFIG_FB_DDC is not set @@ -712,9 +701,7 @@ CONFIG_OMAP4_DSS_HDMI=y CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1 CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET=y CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y -CONFIG_FB_OMAP2=y -CONFIG_FB_OMAP2_DEBUG_SUPPORT=y -CONFIG_FB_OMAP2_NUM_FBS=3 +# CONFIG_FB_OMAP2 is not set # # OMAP2/3 Display Device Drivers @@ -732,6 +719,7 @@ CONFIG_PANEL_TPO_TD043MTEA1=y # CONFIG_LCD_S6E63M0 is not set # CONFIG_LCD_AMS369FG06 is not set CONFIG_BACKLIGHT_GENERIC=m +# CONFIG_BACKLIGHT_PANDORA is not set CONFIG_DISPLAY_SUPPORT=y # CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set CONFIG_LOGO_LINUX_MONO=y @@ -1050,7 +1038,6 @@ CONFIG_LIBCRC32C=y # CONFIG_LCD_LD9040 is not set # CONFIG_RTC_DRV_M41T93 is not set # CONFIG_EXT2_FS_XATTR is not set -# CONFIG_CGROUP_PERF is not set # CONFIG_OPROFILE is not set # CONFIG_OPROFILE is not set # CONFIG_PATA_ARASAN_CF is not set @@ -1058,8 +1045,6 @@ CONFIG_LIBCRC32C=y # CONFIG_BT_WILINK is not set # CONFIG_USB_HSO is not set -CONFIG_CRYSTALHD=m - CONFIG_GPIO_GENERIC_PLATFORM=y CONFIG_MACH_OMAP_GENERIC=y @@ -1083,14 +1068,19 @@ CONFIG_LEDS_RENESAS_TPU=y # CONFIG_OMAP_IOMMU is not set CONFIG_USB_RENESAS_USBHS_HCD=m +# CONFIG_ARM_LPAE is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set # CONFIG_SOC_OMAPTI81XX is not set # CONFIG_SOC_OMAPAM33XX is not set # CONFIG_MACH_TI8148EVM is not set -# CONFIG_OMAP4_ERRATA_I688 is not set -# CONFIG_ARM_LPAE is not set +# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set # CONFIG_MICREL_KS8995MA is not set # CONFIG_CHARGER_MANAGER is not set # CONFIG_MFD_DA9052_SPI is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_S5M_CORE is not set # CONFIG_VIDEO_AS3645A is not set +# CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set +# + diff --git a/config-arm-tegra b/config-arm-tegra index 9658d4989..ef4f53599 100644 --- a/config-arm-tegra +++ b/config-arm-tegra @@ -1,15 +1,22 @@ CONFIG_ARCH_TEGRA=y + +CONFIG_ARCH_TEGRA_2x_SOC=y +# CONFIG_ARCH_TEGRA_3x_SOC is not set +# CONFIG_ARM_LPAE is not set +CONFIG_TEGRA_PCI=y + CONFIG_MACH_HARMONY=y CONFIG_MACH_KAEN=y CONFIG_MACH_PAZ00=y +CONFIG_MACH_SEABOARD=y +CONFIG_MACH_TEGRA_DT=y CONFIG_MACH_TRIMSLICE=y CONFIG_MACH_WARIO=y CONFIG_MACH_TEGRA_DT=y +CONFIG_MACH_VENTANA=y + CONFIG_TEGRA_DEBUG_UARTD=y CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_SMP=y -CONFIG_NR_CPUS=2 CONFIG_PREEMPT=y CONFIG_AEABI=y @@ -46,17 +53,17 @@ CONFIG_ARM_ERRATA_720789=y CONFIG_SMP_ON_UP=y CONFIG_LOCAL_TIMERS=y # CONFIG_THUMB2_KERNEL is not set -CONFIG_HW_PERF_EVENTS=y # CONFIG_NEON is not set # CONFIG_RFKILL_GPIO is not set CONFIG_GPIO_GENERIC_PLATFORM=y # CONFIG_GPIO_MCP23S08 is not set -CONFIG_KEYBOARD_TEGRA=y +# CONFIG_KEYBOARD_TEGRA is not set # CONFIG_MPCORE_WATCHDOG is not set CONFIG_USB_EHCI_TEGRA=y -CONFIG_RTC_DRV_TEGRA=m +CONFIG_RTC_DRV_TEGRA=y CONFIG_SND_SOC_TEGRA=m +CONFIG_SND_SOC_TEGRA_ALC5632=m CONFIG_SND_SOC_TEGRA_WM8903=m CONFIG_SND_SOC_TEGRA_TRIMSLICE=m @@ -64,38 +71,29 @@ CONFIG_MFD_NVEC=y # CONFIG_DEBUG_PREEMPT is not set # CONFIG_RCU_CPU_STALL_VERBOSE is not set # CONFIG_PREEMPT_TRACER is not set +# CONFIG_DEBUG_PINCTRL is not set CONFIG_KEYBOARD_NVEC=y CONFIG_SERIO_NVEC_PS2=y CONFIG_NVEC_POWER=y CONFIG_POWER_SUPPLY=y +CONFIG_NVEC_LEDS=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_DEBUG=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=m -CONFIG_CPU_FREQ_GOV_USERSPACE=m -CONFIG_CPU_FREQ_GOV_ONDEMAND=m -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m -CONFIG_CPU_FREQ_TABLE=y -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_PM=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_CPU_SUSPEND=y -CONFIG_CRYSTALHD=m +CONFIG_CRYPTO_DEV_TEGRA_AES=m -CONFIG_MACH_VENTANA=y CONFIG_PL310_ERRATA_753970=y -CONFIG_ARM_CPU_TOPOLOGY=y CONFIG_SCHED_MC=y CONFIG_SCHED_SMT=y CONFIG_LEDS_RENESAS_TPU=y -# CONFIG_ARCH_TEGRA_2x_SOC is not set -# CONFIG_ARCH_TEGRA_3x_SOC is not set -# CONFIG_ETHERNET is not set -# CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_DVB_TDA1004X is not set -# CONFIG_DVB_PLL is not set -# CONFIG_SND_SOC_TEGRA_ALC5632 is not set +CONFIG_OF_GPIO=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_OF=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_TEGRA_IOMMU_GART=y +CONFIG_TEGRA_IOMMU_SMMU=y diff --git a/config-generic b/config-generic index 7474f897f..a6508a90c 100644 --- a/config-generic +++ b/config-generic @@ -94,6 +94,7 @@ CONFIG_PCI_PRI=y CONFIG_PCI_PASID=y CONFIG_HT_IRQ=y CONFIG_PCI_MSI=y +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set CONFIG_PCIEPORTBUS=y CONFIG_PCIEAER=y CONFIG_PCIEASPM=y @@ -298,6 +299,7 @@ CONFIG_MTD_NAND_CS553X=m CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xFF108018 # CONFIG_MTD_NAND_GPIO is not set CONFIG_MTD_NAND_RICOH=m +# CONFIG_MTD_NAND_DOCG4 is not set CONFIG_MTD_REDBOOT_PARTS=m # CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set @@ -439,6 +441,7 @@ CONFIG_BLK_DEV_VIA82CXXX=y CONFIG_BLK_DEV_IDEDMA=y # CONFIG_BLK_DEV_HD is not set +CONFIG_SCSI_VIRTIO=m CONFIG_VIRTIO_BLK=m CONFIG_VIRTIO_PCI=y CONFIG_VIRTIO_BALLOON=m @@ -539,6 +542,8 @@ CONFIG_SCSI_MPT2SAS=m CONFIG_SCSI_MPT2SAS_MAX_SGE=128 CONFIG_SCSI_MPT2SAS_LOGGING=y +CONFIG_SCSI_UFSHCD=m + CONFIG_SCSI_MVUMI=m CONFIG_SCSI_OSD_INITIATOR=m @@ -721,6 +726,7 @@ CONFIG_DM_MULTIPATH_QL=m CONFIG_DM_MULTIPATH_ST=m CONFIG_DM_RAID=m CONFIG_DM_FLAKEY=m +CONFIG_DM_VERITY=m # # Fusion MPT device support @@ -910,6 +916,7 @@ CONFIG_NETFILTER_XT_TARGET_CT=m CONFIG_NETFILTER_XT_TARGET_DSCP=m CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m CONFIG_NETFILTER_XT_TARGET_MARK=m CONFIG_NETFILTER_XT_TARGET_NFLOG=m CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m @@ -988,6 +995,7 @@ CONFIG_NF_CONNTRACK_SIP=m CONFIG_NF_CONNTRACK_TFTP=m CONFIG_NF_CONNTRACK_IPV4=y CONFIG_NF_CONNTRACK_IPV6=y +# CONFIG_NF_CONNTRACK_TIMEOUT is not set CONFIG_NF_CONNTRACK_TIMESTAMP=y CONFIG_NF_CONNTRACK_SNMP=m CONFIG_NF_NAT=m @@ -995,6 +1003,7 @@ CONFIG_NF_NAT_SNMP_BASIC=m CONFIG_NF_CT_PROTO_DCCP=m CONFIG_NF_CT_PROTO_SCTP=m CONFIG_NF_CT_NETLINK=m +# CONFIG_NF_CT_NETLINK_TIMEOUT is not set CONFIG_NF_CT_PROTO_UDPLITE=m CONFIG_IP_NF_MATCH_AH=m @@ -1159,6 +1168,7 @@ CONFIG_NET_SCH_MQPRIO=m CONFIG_NET_SCH_MULTIQ=m CONFIG_NET_SCH_CHOKE=m CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_PLUG=m CONFIG_NET_CLS=y CONFIG_NET_CLS_ACT=y CONFIG_NET_CLS_BASIC=m @@ -1401,6 +1411,7 @@ CONFIG_FORCEDETH=m CONFIG_NET_VENDOR_OKI=y # CONFIG_PCH_GBE is not set +# CONFIG_PCH_PTP is not set CONFIG_NET_PACKET_ENGINE=y CONFIG_HAMACHI=m @@ -1470,6 +1481,7 @@ CONFIG_NET_VENDOR_XIRCOM=y CONFIG_PCMCIA_XIRC2PS=m CONFIG_PHYLIB=y +CONFIG_AMD_PHY=m CONFIG_BROADCOM_PHY=m CONFIG_CICADA_PHY=m CONFIG_DAVICOM_PHY=m @@ -1519,6 +1531,8 @@ CONFIG_IP1000=m CONFIG_MLX4_EN=m # CONFIG_MLX4_DEBUG is not set CONFIG_SFC=m +CONFIG_SFC_MCDI_MON=y +CONFIG_SFC_SRIOV=y CONFIG_SFC_MTD=y # CONFIG_FDDI is not set @@ -1591,10 +1605,13 @@ CONFIG_ATH5K_DEBUG=y # CONFIG_ATH5K_TRACER is not set CONFIG_ATH6KL=m CONFIG_ATH6KL_DEBUG=y +CONFIG_ATH6KL_SDIO=m +CONFIG_ATH6KL_USB=m CONFIG_ATH9K=m CONFIG_ATH9K_PCI=y CONFIG_ATH9K_AHB=y # CONFIG_ATH9K_DEBUG is not set +# CONFIG_ATH9K_MAC_DEBUG is not set CONFIG_ATH9K_DEBUGFS=y CONFIG_ATH9K_HTC=m CONFIG_ATH9K_BTCOEX_SUPPORT=y @@ -1628,6 +1645,7 @@ CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y CONFIG_BRCMSMAC=m CONFIG_BRCMFMAC=m CONFIG_BRCMFMAC_SDIO=y +CONFIG_BRCMFMAC_USB=y # CONFIG_BRCMDBG is not set CONFIG_HERMES=m CONFIG_HERMES_CACHE_FW_ON_INIT=y @@ -1661,6 +1679,7 @@ CONFIG_IWLWIFI=m CONFIG_IWLWIFI_DEBUG=y CONFIG_IWLWIFI_DEBUGFS=y CONFIG_IWLWIFI_DEVICE_SVTOOL=y +# CONFIG_IWLWIFI_EXPERIMENTAL_MFP is not set # CONFIG_IWLWIFI_P2P is not set CONFIG_IWLEGACY=m CONFIG_IWLEGACY_DEBUG=y @@ -1701,10 +1720,12 @@ CONFIG_RT2800PCI_RT53XX=y CONFIG_RT73USB=m CONFIG_RTL8180=m CONFIG_RTL8187=m +# CONFIG_RTLWIFI_DEBUG is not set CONFIG_TMD_HERMES=m CONFIG_USB_ZD1201=m CONFIG_USB_NET_RNDIS_WLAN=m CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_QMI_WWAN=m CONFIG_USB_NET_SMSC75XX=m CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set @@ -2052,6 +2073,7 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_QT2160 is not set # CONFIG_KEYBOARD_TCA6416 is not set # CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_OMAP4 is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y # CONFIG_MOUSE_PS2_TOUCHKIT is not set @@ -2062,6 +2084,7 @@ CONFIG_MOUSE_VSXXXAA=m CONFIG_MOUSE_APPLETOUCH=m CONFIG_MOUSE_BCM5974=m CONFIG_MOUSE_SYNAPTICS_I2C=m +CONFIG_MOUSE_SYNAPTICS_USB=m CONFIG_INPUT_JOYSTICK=y CONFIG_JOYSTICK_ANALOG=m CONFIG_JOYSTICK_A3D=m @@ -2098,6 +2121,7 @@ CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_AD7879 is not set CONFIG_TOUCHSCREEN_AD7879_I2C=m # CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set CONFIG_TOUCHSCREEN_DYNAPRO=m CONFIG_TOUCHSCREEN_EETI=m CONFIG_TOUCHSCREEN_EGALAX=m @@ -2107,6 +2131,7 @@ CONFIG_TOUCHSCREEN_GUNZE=m # CONFIG_TOUCHSCREEN_HAMPSHIRE is not set CONFIG_TOUCHSCREEN_HTCPEN=m CONFIG_TOUCHSCREEN_INEXIO=m +CONFIG_TOUCHSCREEN_ILI210X=m CONFIG_TOUCHSCREEN_MTOUCH=m CONFIG_TOUCHSCREEN_MCS5000=m CONFIG_TOUCHSCREEN_MK712=m @@ -2337,12 +2362,14 @@ CONFIG_SENSORS_LM93=m CONFIG_SENSORS_LTC4245=m CONFIG_SENSORS_MAX1619=m CONFIG_SENSORS_MAX6650=m +CONFIG_SENSORS_MCP3021=m CONFIG_SENSORS_NTC_THERMISTOR=m CONFIG_SENSORS_PC87360=m CONFIG_SENSORS_PC87427=m CONFIG_SENSORS_PCF8591=m CONFIG_SENSORS_SHT15=m CONFIG_SENSORS_SIS5595=m +CONFIG_CHARGER_SMB347=m CONFIG_SENSORS_SMSC47M1=m CONFIG_SENSORS_SMSC47M192=m CONFIG_SENSORS_SMSC47B397=m @@ -2553,6 +2580,7 @@ CONFIG_VGA_ARB_MAX_GPUS=16 CONFIG_STUB_POULSBO=m # CONFIG_DRM_PSB is not set CONFIG_DRM=m +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set CONFIG_DRM_TDFX=m CONFIG_DRM_R128=m CONFIG_DRM_RADEON=m @@ -2569,6 +2597,7 @@ CONFIG_DRM_NOUVEAU_BACKLIGHT=y CONFIG_DRM_NOUVEAU_DEBUG=y CONFIG_DRM_I2C_CH7006=m CONFIG_DRM_I2C_SIL164=m +CONFIG_DRM_UDL=m CONFIG_DRM_VMWGFX=m # @@ -2675,6 +2704,7 @@ CONFIG_USB_KEENE=n # CONFIG_VIDEO_TIMBERDALE is not set # CONFIG_VIDEO_M5MOLS is not set +# CONFIG_EXYNOS_VIDEO is not set CONFIG_USB_VIDEO_CLASS=m CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y @@ -2842,6 +2872,7 @@ CONFIG_FB=y # CONFIG_FB_GEODE is not set # CONFIG_FB_HECUBA is not set # CONFIG_FB_HGA is not set +# CONFIG_FB_I740 is not set CONFIG_FB_I810=m CONFIG_FB_I810_GTF=y CONFIG_FB_I810_I2C=y @@ -3109,8 +3140,10 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y # CONFIG_USB_EHCI_MV is not set +# CONFIG_USB_EHCI_HCD_PLATFORM is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_HCD_SSB is not set +# CONFIG_USB_OHCI_HCD_PLATFORM is not set CONFIG_USB_UHCI_HCD=y CONFIG_USB_SL811_HCD=m CONFIG_USB_SL811_HCD_ISO=y @@ -3221,6 +3254,9 @@ CONFIG_HOLTEK_FF=y CONFIG_HID_SPEEDLINK=m CONFIG_HID_WIIMOTE=m CONFIG_HID_WIIMOTE_EXT=y +CONFIG_HID_KYE=m +CONFIG_HID_SAITEK=m +CONFIG_HID_TIVO=m # # USB Imaging devices @@ -3356,6 +3392,7 @@ CONFIG_USB_SERIAL_SYMBOL=m CONFIG_USB_SERIAL_EDGEPORT=m CONFIG_USB_SERIAL_EDGEPORT_TI=m CONFIG_USB_SERIAL_EMPEG=m +# CONFIG_USB_SERIAL_F81232 is not set CONFIG_USB_SERIAL_FTDI_SIO=m CONFIG_USB_SERIAL_FUNSOFT=m CONFIG_USB_SERIAL_GARMIN=m @@ -3381,6 +3418,7 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y CONFIG_USB_SERIAL_KLSI=m CONFIG_USB_SERIAL_KOBIL_SCT=m CONFIG_USB_SERIAL_MCT_U232=m +# CONFIG_USB_SERIAL_METRO is not set CONFIG_USB_SERIAL_MOS7720=m CONFIG_USB_SERIAL_MOS7715_PARPORT=y # CONFIG_USB_SERIAL_ZIO is not set @@ -3520,6 +3558,7 @@ CONFIG_MFD_WM8400=m # CONFIG_MFD_TPS6586X is not set # CONFIG_MFD_TC3589X is not set # CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_TPS65217 is not set # # File systems @@ -3639,6 +3678,7 @@ CONFIG_SQUASHFS_ZLIB=y # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set CONFIG_SYSV_FS=m CONFIG_UFS_FS=m # CONFIG_UFS_FS_WRITE is not set @@ -3659,6 +3699,7 @@ CONFIG_NFS_V3=y CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y CONFIG_NFS_V4_1=y +CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org" CONFIG_NFSD=m CONFIG_NFSD_V3=y CONFIG_NFSD_V3_ACL=y @@ -3675,6 +3716,7 @@ CONFIG_EXPORTFS=y CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m CONFIG_SUNRPC_XPRT_RDMA=m +CONFIG_SUNRPC_DEBUG=y CONFIG_RPCSEC_GSS_KRB5=m CONFIG_CIFS=m CONFIG_CIFS_STATS=y @@ -3883,6 +3925,7 @@ CONFIG_SECURITY_SELINUX_AVC_STATS=y # CONFIG_SECURITY_SMACK is not set # CONFIG_SECURITY_TOMOYO is not set # CONFIG_SECURITY_APPARMOR is not set +# CONFIG_SECURITY_YAMA is not set CONFIG_AUDIT=y CONFIG_AUDITSYSCALL=y # CONFIG_AUDIT_LOGINUID_IMMUTABLE is not set @@ -3966,6 +4009,7 @@ CONFIG_CRYPTO_USER=m # CONFIG_CRC16=y CONFIG_CRC32=m +# CONFIG_CRC32_SELFTEST is not set CONFIG_CRC_CCITT=m CONFIG_CRC_ITU_T=m CONFIG_CRC_T10DIF=m @@ -4000,6 +4044,7 @@ CONFIG_FB_ATY128_BACKLIGHT=y CONFIG_FB_ATY_BACKLIGHT=y # CONFIG_BACKLIGHT_SAHARA is not set CONFIG_BACKLIGHT_WM831X=m +CONFIG_BACKLIGHT_LP855X=m CONFIG_LCD_CLASS_DEVICE=m CONFIG_LCD_PLATFORM=m @@ -4195,6 +4240,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_BD2802 is not set # CONFIG_LEDS_S3C24XX is not set +# CONFIG_LEDS_PCA9633 is not set CONFIG_LEDS_DELL_NETBOOKS=m # CONFIG_LEDS_TCA6507 is not set # CONFIG_LEDS_OT200 is not set @@ -4271,6 +4317,7 @@ CONFIG_APM_POWER=m # CONFIG_WM831X_POWER is not set # CONFIG_BATTERY_DS2760 is not set +# CONFIG_BATTERY_DS2781 is not set # CONFIG_BATTERY_DS2782 is not set # CONFIG_BATTERY_SBS is not set # CONFIG_BATTERY_BQ20Z75 is not set @@ -4443,6 +4490,9 @@ CONFIG_ALTERA_STAPL=m # CONFIG_RTS5139 is not set # CONFIG_NVEC_LEDS is not set # CONFIG_VT6655 is not set +# CONFIG_ZSMALLOC is not set +# CONFIG_RAMSTER is not set +# CONFIG_USB_WPAN_HCD is not set # # END OF STAGING @@ -4469,6 +4519,7 @@ CONFIG_STRIP_ASM_SYMS=y CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_TRACE is not set +# CONFIG_RCU_CPU_STALL_INFO is not set CONFIG_SPARSE_RCU_POINTER=y CONFIG_KSM=y @@ -4493,6 +4544,7 @@ CONFIG_PPS_CLIENT_GPIO=m CONFIG_NTP_PPS=y CONFIG_PTP_1588_CLOCK=m +CONFIG_PTP_1588_CLOCK_PCH=m CONFIG_CLEANCACHE=y @@ -4560,4 +4612,6 @@ CONFIG_BCMA_HOST_PCI=y # CONFIG_GOOGLE_FIRMWARE is not set CONFIG_IOMMU_SUPPORT=y +# CONFIG_HSI is not set + # CONFIG_PM_DEVFREQ is not set diff --git a/config-powerpc-generic b/config-powerpc-generic index 6b5498542..59e7d5c9e 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -360,3 +360,6 @@ CONFIG_RFKILL_GPIO=m # CONFIG_CPU_IDLE is not set CONFIG_STRICT_DEVMEM=y # CONFIG_V4L_RADIO_ISA_DRIVERS is not set +# CONFIG_IRQ_DOMAIN_DEBUG is not set +# CONFIG_MPIC_MSGR is not set +# CONFIG_FA_DUMP is not set diff --git a/config-s390x b/config-s390x index f03942191..848709dfb 100644 --- a/config-s390x +++ b/config-s390x @@ -197,6 +197,7 @@ CONFIG_QETH_L3=m CONFIG_CRYPTO_SHA512_S390=m CONFIG_VIRTUALIZATION=y CONFIG_KVM=m +# CONFIG_KVM_S390_UCONTROL is not set CONFIG_S390_GUEST=y diff --git a/config-x86-32-generic b/config-x86-32-generic index 3f4fc346f..b00834482 100644 --- a/config-x86-32-generic +++ b/config-x86-32-generic @@ -154,6 +154,8 @@ CONFIG_OLPC_XO1_SCI=y # staging # CONFIG_FB_OLPC_DCON is not set +# CONFIG_IRQ_DOMAIN_DEBUG is not set + # CONFIG_SPARSE_IRQ is not set CONFIG_RCU_FANOUT=32 @@ -207,3 +209,7 @@ CONFIG_I2O_BUS=m # CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set # CONFIG_INPUT_GP2A is not set # CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_GEOS is not set +# CONFIG_NET5501 is not set +# CONFIG_GPIO_SODAVILLE is not set +# CONFIG_BACKLIGHT_OT200 is not set diff --git a/config-x86-generic b/config-x86-generic index cf5e3c611..181e3e92f 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -86,6 +86,7 @@ CONFIG_ACPI_APEI_MEMORY_FAILURE=y # CONFIG_ACPI_APEI_EINJ is not set CONFIG_ACPI_IPMI=m CONFIG_ACPI_CUSTOM_METHOD=m +CONFIG_ACPI_BGRT=m CONFIG_X86_ACPI_CPUFREQ=y CONFIG_X86_PCC_CPUFREQ=y @@ -247,6 +248,7 @@ CONFIG_XEN_BALLOON=y CONFIG_XEN_SCRUB_PAGES=y CONFIG_XEN_SAVE_RESTORE=y CONFIG_HVC_XEN=y +CONFIG_HVC_XEN_FRONTEND=y CONFIG_XEN_FBDEV_FRONTEND=y CONFIG_XEN_BLKDEV_FRONTEND=m CONFIG_XEN_NETDEV_FRONTEND=m @@ -264,6 +266,7 @@ CONFIG_XEN_GNTDEV=m CONFIG_INPUT_XEN_KBDDEV_FRONTEND=m CONFIG_XEN_SELFBALLOONING=y CONFIG_XEN_PCIDEV_BACKEND=m +CONFIG_XEN_ACPI_PROCESSOR=m CONFIG_MTD_ESB2ROM=m CONFIG_MTD_CK804XROM=m @@ -389,7 +392,11 @@ CONFIG_SCHED_SMT=y CONFIG_CC_STACKPROTECTOR=y CONFIG_RELOCATABLE=y -# CONFIG_HYPERV is not set +CONFIG_HYPERV=m +CONFIG_HYPERV_UTILS=m +CONFIG_HID_HYPERV_MOUSE=m +CONFIG_HYPERV_NET=m +CONFIG_HYPERV_STORAGE=m # Depends on PCI CONFIG_BLK_DEV_PCIESSD_MTIP32XX=m @@ -400,3 +407,5 @@ CONFIG_DRM_GMA500=m # Maybe enable in debug kernels? # CONFIG_DEBUG_NMI_SELFTEST is not set + +CONFIG_APPLE_GMUX=m diff --git a/config-x86_64-generic b/config-x86_64-generic index a334a3736..0b01f9f44 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -1,5 +1,6 @@ CONFIG_64BIT=y +# CONFIG_X86_X32 is not set # CONFIG_MK8 is not set # CONFIG_MPSC is not set CONFIG_GENERIC_CPU=y @@ -50,6 +51,7 @@ CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m CONFIG_CRYPTO_SHA1_SSSE3=m CONFIG_CRYPTO_BLOWFISH_X86_64=m CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=m +CONFIG_CRYPTO_CAMELLIA_X86_64=m # CONFIG_I2C_ALI1535 is not set # CONFIG_I2C_ALI1563 is not set diff --git a/disable-hid-battery.patch b/disable-hid-battery.patch deleted file mode 100644 index 98fe2139e..000000000 --- a/disable-hid-battery.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- linux-2.6.43.noarch.orig/drivers/hid/Kconfig -+++ linux-2.6.43.noarch/drivers/hid/Kconfig -@@ -34,7 +34,7 @@ config HID - config HID_BATTERY_STRENGTH - bool - depends on HID && POWER_SUPPLY && HID = POWER_SUPPLY -- default y -+ default n - - config HIDRAW - bool "/dev/hidraw raw HID device support" diff --git a/drivers-media-update.patch b/drivers-media-update.patch index 15eba7350..e69de29bb 100644 --- a/drivers-media-update.patch +++ b/drivers-media-update.patch @@ -1,38187 +0,0 @@ -Driver updates with all media stuff - -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/az6007.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/az6007.c -@@ -0,0 +1,957 @@ -+/* -+ * Driver for AzureWave 6007 DVB-C/T USB2.0 and clones -+ * -+ * Copyright (c) Henry Wang -+ * -+ * This driver was made publicly available by Terratec, at: -+ * http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz -+ * The original driver's license is GPL, as declared with MODULE_LICENSE() -+ * -+ * Copyright (c) 2010-2011 Mauro Carvalho Chehab -+ * Driver modified by in order to work with upstream drxk driver, and -+ * tons of bugs got fixed. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation under version 2 of the License. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include "drxk.h" -+#include "mt2063.h" -+#include "dvb_ca_en50221.h" -+ -+#define DVB_USB_LOG_PREFIX "az6007" -+#include "dvb-usb.h" -+ -+/* debug */ -+int dvb_usb_az6007_debug; -+module_param_named(debug, dvb_usb_az6007_debug, int, 0644); -+MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." -+ DVB_USB_DEBUG_STATUS); -+ -+#define deb_info(args...) dprintk(dvb_usb_az6007_debug, 0x01, args) -+#define deb_xfer(args...) dprintk(dvb_usb_az6007_debug, 0x02, args) -+#define deb_rc(args...) dprintk(dvb_usb_az6007_debug, 0x04, args) -+#define deb_fe(args...) dprintk(dvb_usb_az6007_debug, 0x08, args) -+ -+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -+ -+/* Known requests (Cypress FX2 firmware + az6007 "private" ones*/ -+ -+#define FX2_OED 0xb5 -+#define AZ6007_READ_DATA 0xb7 -+#define AZ6007_I2C_RD 0xb9 -+#define AZ6007_POWER 0xbc -+#define AZ6007_I2C_WR 0xbd -+#define FX2_SCON1 0xc0 -+#define AZ6007_TS_THROUGH 0xc7 -+#define AZ6007_READ_IR 0xb4 -+ -+struct az6007_device_state { -+ struct mutex mutex; -+ struct mutex ca_mutex; -+ struct dvb_ca_en50221 ca; -+ unsigned warm:1; -+ int (*gate_ctrl) (struct dvb_frontend *, int); -+ unsigned char data[4096]; -+}; -+ -+static struct drxk_config terratec_h7_drxk = { -+ .adr = 0x29, -+ .parallel_ts = true, -+ .dynamic_clk = true, -+ .single_master = true, -+ .enable_merr_cfg = true, -+ .no_i2c_bridge = false, -+ .chunk_size = 64, -+ .mpeg_out_clk_strength = 0x02, -+ .microcode_name = "dvb-usb-terratec-h7-drxk.fw", -+}; -+ -+static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) -+{ -+ struct dvb_usb_adapter *adap = fe->sec_priv; -+ struct az6007_device_state *st; -+ int status = 0; -+ -+ deb_info("%s: %s\n", __func__, enable ? "enable" : "disable"); -+ -+ if (!adap) -+ return -EINVAL; -+ -+ st = adap->dev->priv; -+ -+ if (!st) -+ return -EINVAL; -+ -+ if (enable) -+ status = st->gate_ctrl(fe, 1); -+ else -+ status = st->gate_ctrl(fe, 0); -+ -+ return status; -+} -+ -+static struct mt2063_config az6007_mt2063_config = { -+ .tuner_address = 0x60, -+ .refclock = 36125000, -+}; -+ -+static int __az6007_read(struct usb_device *udev, u8 req, u16 value, -+ u16 index, u8 *b, int blen) -+{ -+ int ret; -+ -+ ret = usb_control_msg(udev, -+ usb_rcvctrlpipe(udev, 0), -+ req, -+ USB_TYPE_VENDOR | USB_DIR_IN, -+ value, index, b, blen, 5000); -+ if (ret < 0) { -+ warn("usb read operation failed. (%d)", ret); -+ return -EIO; -+ } -+ -+ deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, -+ index); -+ debug_dump(b, blen, deb_xfer); -+ -+ return ret; -+} -+ -+static int az6007_read(struct dvb_usb_device *d, u8 req, u16 value, -+ u16 index, u8 *b, int blen) -+{ -+ struct az6007_device_state *st = d->priv; -+ int ret; -+ -+ if (mutex_lock_interruptible(&st->mutex) < 0) -+ return -EAGAIN; -+ -+ ret = __az6007_read(d->udev, req, value, index, b, blen); -+ -+ mutex_unlock(&st->mutex); -+ -+ return ret; -+} -+ -+static int __az6007_write(struct usb_device *udev, u8 req, u16 value, -+ u16 index, u8 *b, int blen) -+{ -+ int ret; -+ -+ deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, -+ index); -+ debug_dump(b, blen, deb_xfer); -+ -+ if (blen > 64) { -+ err("az6007: tried to write %d bytes, but I2C max size is 64 bytes\n", -+ blen); -+ return -EOPNOTSUPP; -+ } -+ -+ ret = usb_control_msg(udev, -+ usb_sndctrlpipe(udev, 0), -+ req, -+ USB_TYPE_VENDOR | USB_DIR_OUT, -+ value, index, b, blen, 5000); -+ if (ret != blen) { -+ err("usb write operation failed. (%d)", ret); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+static int az6007_write(struct dvb_usb_device *d, u8 req, u16 value, -+ u16 index, u8 *b, int blen) -+{ -+ struct az6007_device_state *st = d->priv; -+ int ret; -+ -+ if (mutex_lock_interruptible(&st->mutex) < 0) -+ return -EAGAIN; -+ -+ ret = __az6007_write(d->udev, req, value, index, b, blen); -+ -+ mutex_unlock(&st->mutex); -+ -+ return ret; -+} -+ -+static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) -+{ -+ struct dvb_usb_device *d = adap->dev; -+ -+ deb_info("%s: %s", __func__, onoff ? "enable" : "disable"); -+ -+ return az6007_write(d, 0xbc, onoff, 0, NULL, 0); -+} -+ -+/* remote control stuff (does not work with my box) */ -+static int az6007_rc_query(struct dvb_usb_device *d) -+{ -+ struct az6007_device_state *st = d->priv; -+ unsigned code = 0; -+ -+ az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10); -+ -+ if (st->data[1] == 0x44) -+ return 0; -+ -+ if ((st->data[1] ^ st->data[2]) == 0xff) -+ code = st->data[1]; -+ else -+ code = st->data[1] << 8 | st->data[2]; -+ -+ if ((st->data[3] ^ st->data[4]) == 0xff) -+ code = code << 8 | st->data[3]; -+ else -+ code = code << 16 | st->data[3] << 8 | st->data[4]; -+ -+ rc_keydown(d->rc_dev, code, st->data[5]); -+ -+ return 0; -+} -+ -+static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, -+ int slot, -+ int address) -+{ -+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; -+ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; -+ -+ int ret; -+ u8 req; -+ u16 value; -+ u16 index; -+ int blen; -+ u8 *b; -+ -+ if (slot != 0) -+ return -EINVAL; -+ -+ b = kmalloc(12, GFP_KERNEL); -+ if (!b) -+ return -ENOMEM; -+ -+ mutex_lock(&state->ca_mutex); -+ -+ req = 0xC1; -+ value = address; -+ index = 0; -+ blen = 1; -+ -+ ret = az6007_read(d, req, value, index, b, blen); -+ if (ret < 0) { -+ warn("usb in operation failed. (%d)", ret); -+ ret = -EINVAL; -+ } else { -+ ret = b[0]; -+ } -+ -+ mutex_unlock(&state->ca_mutex); -+ kfree(b); -+ return ret; -+} -+ -+static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, -+ int slot, -+ int address, -+ u8 value) -+{ -+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; -+ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; -+ -+ int ret; -+ u8 req; -+ u16 value1; -+ u16 index; -+ int blen; -+ -+ deb_info("%s %d", __func__, slot); -+ if (slot != 0) -+ return -EINVAL; -+ -+ mutex_lock(&state->ca_mutex); -+ req = 0xC2; -+ value1 = address; -+ index = value; -+ blen = 0; -+ -+ ret = az6007_write(d, req, value1, index, NULL, blen); -+ if (ret != 0) -+ warn("usb out operation failed. (%d)", ret); -+ -+ mutex_unlock(&state->ca_mutex); -+ return ret; -+} -+ -+static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca, -+ int slot, -+ u8 address) -+{ -+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; -+ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; -+ -+ int ret; -+ u8 req; -+ u16 value; -+ u16 index; -+ int blen; -+ u8 *b; -+ -+ if (slot != 0) -+ return -EINVAL; -+ -+ b = kmalloc(12, GFP_KERNEL); -+ if (!b) -+ return -ENOMEM; -+ -+ mutex_lock(&state->ca_mutex); -+ -+ req = 0xC3; -+ value = address; -+ index = 0; -+ blen = 2; -+ -+ ret = az6007_read(d, req, value, index, b, blen); -+ if (ret < 0) { -+ warn("usb in operation failed. (%d)", ret); -+ ret = -EINVAL; -+ } else { -+ if (b[0] == 0) -+ warn("Read CI IO error"); -+ -+ ret = b[1]; -+ deb_info("read cam data = %x from 0x%x", b[1], value); -+ } -+ -+ mutex_unlock(&state->ca_mutex); -+ kfree(b); -+ return ret; -+} -+ -+static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca, -+ int slot, -+ u8 address, -+ u8 value) -+{ -+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; -+ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; -+ -+ int ret; -+ u8 req; -+ u16 value1; -+ u16 index; -+ int blen; -+ -+ if (slot != 0) -+ return -EINVAL; -+ -+ mutex_lock(&state->ca_mutex); -+ req = 0xC4; -+ value1 = address; -+ index = value; -+ blen = 0; -+ -+ ret = az6007_write(d, req, value1, index, NULL, blen); -+ if (ret != 0) { -+ warn("usb out operation failed. (%d)", ret); -+ goto failed; -+ } -+ -+failed: -+ mutex_unlock(&state->ca_mutex); -+ return ret; -+} -+ -+static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) -+{ -+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; -+ -+ int ret; -+ u8 req; -+ u16 value; -+ u16 index; -+ int blen; -+ u8 *b; -+ -+ b = kmalloc(12, GFP_KERNEL); -+ if (!b) -+ return -ENOMEM; -+ -+ req = 0xC8; -+ value = 0; -+ index = 0; -+ blen = 1; -+ -+ ret = az6007_read(d, req, value, index, b, blen); -+ if (ret < 0) { -+ warn("usb in operation failed. (%d)", ret); -+ ret = -EIO; -+ } else{ -+ ret = b[0]; -+ } -+ kfree(b); -+ return ret; -+} -+ -+static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) -+{ -+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; -+ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; -+ -+ int ret, i; -+ u8 req; -+ u16 value; -+ u16 index; -+ int blen; -+ -+ mutex_lock(&state->ca_mutex); -+ -+ req = 0xC6; -+ value = 1; -+ index = 0; -+ blen = 0; -+ -+ ret = az6007_write(d, req, value, index, NULL, blen); -+ if (ret != 0) { -+ warn("usb out operation failed. (%d)", ret); -+ goto failed; -+ } -+ -+ msleep(500); -+ req = 0xC6; -+ value = 0; -+ index = 0; -+ blen = 0; -+ -+ ret = az6007_write(d, req, value, index, NULL, blen); -+ if (ret != 0) { -+ warn("usb out operation failed. (%d)", ret); -+ goto failed; -+ } -+ -+ for (i = 0; i < 15; i++) { -+ msleep(100); -+ -+ if (CI_CamReady(ca, slot)) { -+ deb_info("CAM Ready"); -+ break; -+ } -+ } -+ msleep(5000); -+ -+failed: -+ mutex_unlock(&state->ca_mutex); -+ return ret; -+} -+ -+static int az6007_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) -+{ -+ return 0; -+} -+ -+static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) -+{ -+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; -+ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; -+ -+ int ret; -+ u8 req; -+ u16 value; -+ u16 index; -+ int blen; -+ -+ deb_info("%s", __func__); -+ mutex_lock(&state->ca_mutex); -+ req = 0xC7; -+ value = 1; -+ index = 0; -+ blen = 0; -+ -+ ret = az6007_write(d, req, value, index, NULL, blen); -+ if (ret != 0) { -+ warn("usb out operation failed. (%d)", ret); -+ goto failed; -+ } -+ -+failed: -+ mutex_unlock(&state->ca_mutex); -+ return ret; -+} -+ -+static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) -+{ -+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; -+ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; -+ int ret; -+ u8 req; -+ u16 value; -+ u16 index; -+ int blen; -+ u8 *b; -+ -+ b = kmalloc(12, GFP_KERNEL); -+ if (!b) -+ return -ENOMEM; -+ mutex_lock(&state->ca_mutex); -+ -+ req = 0xC5; -+ value = 0; -+ index = 0; -+ blen = 1; -+ -+ ret = az6007_read(d, req, value, index, b, blen); -+ if (ret < 0) { -+ warn("usb in operation failed. (%d)", ret); -+ ret = -EIO; -+ } else -+ ret = 0; -+ -+ if (!ret && b[0] == 1) { -+ ret = DVB_CA_EN50221_POLL_CAM_PRESENT | -+ DVB_CA_EN50221_POLL_CAM_READY; -+ } -+ -+ mutex_unlock(&state->ca_mutex); -+ kfree(b); -+ return ret; -+} -+ -+ -+static void az6007_ci_uninit(struct dvb_usb_device *d) -+{ -+ struct az6007_device_state *state; -+ -+ deb_info("%s", __func__); -+ -+ if (NULL == d) -+ return; -+ -+ state = (struct az6007_device_state *)d->priv; -+ if (NULL == state) -+ return; -+ -+ if (NULL == state->ca.data) -+ return; -+ -+ dvb_ca_en50221_release(&state->ca); -+ -+ memset(&state->ca, 0, sizeof(state->ca)); -+} -+ -+ -+static int az6007_ci_init(struct dvb_usb_adapter *a) -+{ -+ struct dvb_usb_device *d = a->dev; -+ struct az6007_device_state *state = (struct az6007_device_state *)d->priv; -+ int ret; -+ -+ deb_info("%s", __func__); -+ -+ mutex_init(&state->ca_mutex); -+ -+ state->ca.owner = THIS_MODULE; -+ state->ca.read_attribute_mem = az6007_ci_read_attribute_mem; -+ state->ca.write_attribute_mem = az6007_ci_write_attribute_mem; -+ state->ca.read_cam_control = az6007_ci_read_cam_control; -+ state->ca.write_cam_control = az6007_ci_write_cam_control; -+ state->ca.slot_reset = az6007_ci_slot_reset; -+ state->ca.slot_shutdown = az6007_ci_slot_shutdown; -+ state->ca.slot_ts_enable = az6007_ci_slot_ts_enable; -+ state->ca.poll_slot_status = az6007_ci_poll_slot_status; -+ state->ca.data = d; -+ -+ ret = dvb_ca_en50221_init(&a->dvb_adap, -+ &state->ca, -+ 0, /* flags */ -+ 1);/* n_slots */ -+ if (ret != 0) { -+ err("Cannot initialize CI: Error %d.", ret); -+ memset(&state->ca, 0, sizeof(state->ca)); -+ return ret; -+ } -+ -+ deb_info("CI initialized."); -+ -+ return 0; -+} -+ -+static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) -+{ -+ struct az6007_device_state *st = d->priv; -+ int ret; -+ -+ ret = az6007_read(d, AZ6007_READ_DATA, 6, 0, st->data, 6); -+ memcpy(mac, st->data, sizeof(mac)); -+ -+ if (ret > 0) -+ deb_info("%s: mac is %02x:%02x:%02x:%02x:%02x:%02x\n", -+ __func__, mac[0], mac[1], mac[2], -+ mac[3], mac[4], mac[5]); -+ -+ return ret; -+} -+ -+static int az6007_frontend_attach(struct dvb_usb_adapter *adap) -+{ -+ struct az6007_device_state *st = adap->dev->priv; -+ -+ deb_info("attaching demod drxk"); -+ -+ adap->fe_adap[0].fe = dvb_attach(drxk_attach, &terratec_h7_drxk, -+ &adap->dev->i2c_adap); -+ if (!adap->fe_adap[0].fe) -+ return -EINVAL; -+ -+ adap->fe_adap[0].fe->sec_priv = adap; -+ st->gate_ctrl = adap->fe_adap[0].fe->ops.i2c_gate_ctrl; -+ adap->fe_adap[0].fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; -+ -+ az6007_ci_init(adap); -+ -+ return 0; -+} -+ -+static int az6007_tuner_attach(struct dvb_usb_adapter *adap) -+{ -+ deb_info("attaching tuner mt2063"); -+ -+ /* Attach mt2063 to DVB-C frontend */ -+ if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) -+ adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1); -+ if (!dvb_attach(mt2063_attach, adap->fe_adap[0].fe, -+ &az6007_mt2063_config, -+ &adap->dev->i2c_adap)) -+ return -EINVAL; -+ -+ if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) -+ adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0); -+ -+ return 0; -+} -+ -+int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) -+{ -+ struct az6007_device_state *st = d->priv; -+ int ret; -+ -+ deb_info("%s()\n", __func__); -+ -+ if (!st->warm) { -+ mutex_init(&st->mutex); -+ -+ ret = az6007_write(d, AZ6007_POWER, 0, 2, NULL, 0); -+ if (ret < 0) -+ return ret; -+ msleep(60); -+ ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0); -+ if (ret < 0) -+ return ret; -+ msleep(100); -+ ret = az6007_write(d, AZ6007_POWER, 1, 3, NULL, 0); -+ if (ret < 0) -+ return ret; -+ msleep(20); -+ ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0); -+ if (ret < 0) -+ return ret; -+ -+ msleep(400); -+ ret = az6007_write(d, FX2_SCON1, 0, 3, NULL, 0); -+ if (ret < 0) -+ return ret; -+ msleep(150); -+ ret = az6007_write(d, FX2_SCON1, 1, 3, NULL, 0); -+ if (ret < 0) -+ return ret; -+ msleep(430); -+ ret = az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0); -+ if (ret < 0) -+ return ret; -+ -+ st->warm = true; -+ -+ return 0; -+ } -+ -+ if (!onoff) -+ return 0; -+ -+ az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0); -+ az6007_write(d, AZ6007_TS_THROUGH, 0, 0, NULL, 0); -+ -+ return 0; -+} -+ -+/* I2C */ -+static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], -+ int num) -+{ -+ struct dvb_usb_device *d = i2c_get_adapdata(adap); -+ struct az6007_device_state *st = d->priv; -+ int i, j, len; -+ int ret = 0; -+ u16 index; -+ u16 value; -+ int length; -+ u8 req, addr; -+ -+ if (mutex_lock_interruptible(&st->mutex) < 0) -+ return -EAGAIN; -+ -+ for (i = 0; i < num; i++) { -+ addr = msgs[i].addr << 1; -+ if (((i + 1) < num) -+ && (msgs[i].len == 1) -+ && (!msgs[i].flags & I2C_M_RD) -+ && (msgs[i + 1].flags & I2C_M_RD) -+ && (msgs[i].addr == msgs[i + 1].addr)) { -+ /* -+ * A write + read xfer for the same address, where -+ * the first xfer has just 1 byte length. -+ * Need to join both into one operation -+ */ -+ if (dvb_usb_az6007_debug & 2) -+ printk(KERN_DEBUG -+ "az6007 I2C xfer write+read addr=0x%x len=%d/%d: ", -+ addr, msgs[i].len, msgs[i + 1].len); -+ req = AZ6007_I2C_RD; -+ index = msgs[i].buf[0]; -+ value = addr | (1 << 8); -+ length = 6 + msgs[i + 1].len; -+ len = msgs[i + 1].len; -+ ret = __az6007_read(d->udev, req, value, index, -+ st->data, length); -+ if (ret >= len) { -+ for (j = 0; j < len; j++) { -+ msgs[i + 1].buf[j] = st->data[j + 5]; -+ if (dvb_usb_az6007_debug & 2) -+ printk(KERN_CONT -+ "0x%02x ", -+ msgs[i + 1].buf[j]); -+ } -+ } else -+ ret = -EIO; -+ i++; -+ } else if (!(msgs[i].flags & I2C_M_RD)) { -+ /* write bytes */ -+ if (dvb_usb_az6007_debug & 2) -+ printk(KERN_DEBUG -+ "az6007 I2C xfer write addr=0x%x len=%d: ", -+ addr, msgs[i].len); -+ req = AZ6007_I2C_WR; -+ index = msgs[i].buf[0]; -+ value = addr | (1 << 8); -+ length = msgs[i].len - 1; -+ len = msgs[i].len - 1; -+ if (dvb_usb_az6007_debug & 2) -+ printk(KERN_CONT "(0x%02x) ", msgs[i].buf[0]); -+ for (j = 0; j < len; j++) { -+ st->data[j] = msgs[i].buf[j + 1]; -+ if (dvb_usb_az6007_debug & 2) -+ printk(KERN_CONT "0x%02x ", -+ st->data[j]); -+ } -+ ret = __az6007_write(d->udev, req, value, index, -+ st->data, length); -+ } else { -+ /* read bytes */ -+ if (dvb_usb_az6007_debug & 2) -+ printk(KERN_DEBUG -+ "az6007 I2C xfer read addr=0x%x len=%d: ", -+ addr, msgs[i].len); -+ req = AZ6007_I2C_RD; -+ index = msgs[i].buf[0]; -+ value = addr; -+ length = msgs[i].len + 6; -+ len = msgs[i].len; -+ ret = __az6007_read(d->udev, req, value, index, -+ st->data, length); -+ for (j = 0; j < len; j++) { -+ msgs[i].buf[j] = st->data[j + 5]; -+ if (dvb_usb_az6007_debug & 2) -+ printk(KERN_CONT -+ "0x%02x ", st->data[j + 5]); -+ } -+ } -+ if (dvb_usb_az6007_debug & 2) -+ printk(KERN_CONT "\n"); -+ if (ret < 0) -+ goto err; -+ } -+err: -+ mutex_unlock(&st->mutex); -+ -+ if (ret < 0) { -+ info("%s ERROR: %i", __func__, ret); -+ return ret; -+ } -+ return num; -+} -+ -+static u32 az6007_i2c_func(struct i2c_adapter *adapter) -+{ -+ return I2C_FUNC_I2C; -+} -+ -+static struct i2c_algorithm az6007_i2c_algo = { -+ .master_xfer = az6007_i2c_xfer, -+ .functionality = az6007_i2c_func, -+}; -+ -+int az6007_identify_state(struct usb_device *udev, -+ struct dvb_usb_device_properties *props, -+ struct dvb_usb_device_description **desc, int *cold) -+{ -+ int ret; -+ u8 *mac; -+ -+ mac = kmalloc(6, GFP_ATOMIC); -+ if (!mac) -+ return -ENOMEM; -+ -+ /* Try to read the mac address */ -+ ret = __az6007_read(udev, AZ6007_READ_DATA, 6, 0, mac, 6); -+ if (ret == 6) -+ *cold = 0; -+ else -+ *cold = 1; -+ -+ kfree(mac); -+ -+ if (*cold) { -+ __az6007_write(udev, 0x09, 1, 0, NULL, 0); -+ __az6007_write(udev, 0x00, 0, 0, NULL, 0); -+ __az6007_write(udev, 0x00, 0, 0, NULL, 0); -+ } -+ -+ deb_info("Device is on %s state\n", *cold ? "warm" : "cold"); -+ return 0; -+} -+ -+static struct dvb_usb_device_properties az6007_properties; -+ -+static void az6007_usb_disconnect(struct usb_interface *intf) -+{ -+ struct dvb_usb_device *d = usb_get_intfdata(intf); -+ az6007_ci_uninit(d); -+ dvb_usb_device_exit(intf); -+} -+ -+static int az6007_usb_probe(struct usb_interface *intf, -+ const struct usb_device_id *id) -+{ -+ return dvb_usb_device_init(intf, &az6007_properties, -+ THIS_MODULE, NULL, adapter_nr); -+} -+ -+static struct usb_device_id az6007_usb_table[] = { -+ {USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007)}, -+ {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7)}, -+ {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2)}, -+ {0}, -+}; -+ -+MODULE_DEVICE_TABLE(usb, az6007_usb_table); -+ -+static struct dvb_usb_device_properties az6007_properties = { -+ .caps = DVB_USB_IS_AN_I2C_ADAPTER, -+ .usb_ctrl = CYPRESS_FX2, -+ .firmware = "dvb-usb-terratec-h7-az6007.fw", -+ .no_reconnect = 1, -+ .size_of_priv = sizeof(struct az6007_device_state), -+ .identify_state = az6007_identify_state, -+ .num_adapters = 1, -+ .adapter = { -+ { -+ .num_frontends = 1, -+ .fe = {{ -+ .streaming_ctrl = az6007_streaming_ctrl, -+ .tuner_attach = az6007_tuner_attach, -+ .frontend_attach = az6007_frontend_attach, -+ -+ /* parameter for the MPEG2-data transfer */ -+ .stream = { -+ .type = USB_BULK, -+ .count = 10, -+ .endpoint = 0x02, -+ .u = { -+ .bulk = { -+ .buffersize = 4096, -+ } -+ } -+ }, -+ } } -+ } }, -+ .power_ctrl = az6007_power_ctrl, -+ .read_mac_address = az6007_read_mac_addr, -+ -+ .rc.core = { -+ .rc_interval = 400, -+ .rc_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS, -+ .module_name = "az6007", -+ .rc_query = az6007_rc_query, -+ .allowed_protos = RC_TYPE_NEC, -+ }, -+ .i2c_algo = &az6007_i2c_algo, -+ -+ .num_device_descs = 2, -+ .devices = { -+ { .name = "AzureWave DTV StarBox DVB-T/C USB2.0 (az6007)", -+ .cold_ids = { &az6007_usb_table[0], NULL }, -+ .warm_ids = { NULL }, -+ }, -+ { .name = "TerraTec DTV StarBox DVB-T/C USB2.0 (az6007)", -+ .cold_ids = { &az6007_usb_table[1], &az6007_usb_table[2], NULL }, -+ .warm_ids = { NULL }, -+ }, -+ { NULL }, -+ } -+}; -+ -+/* usb specific object needed to register this driver with the usb subsystem */ -+static struct usb_driver az6007_usb_driver = { -+ .name = "dvb_usb_az6007", -+ .probe = az6007_usb_probe, -+ .disconnect = az6007_usb_disconnect, -+ .id_table = az6007_usb_table, -+}; -+ -+/* module stuff */ -+static int __init az6007_usb_module_init(void) -+{ -+ int result; -+ deb_info("az6007 usb module init\n"); -+ -+ result = usb_register(&az6007_usb_driver); -+ if (result) { -+ err("usb_register failed. (%d)", result); -+ return result; -+ } -+ -+ return 0; -+} -+ -+static void __exit az6007_usb_module_exit(void) -+{ -+ /* deregister this driver from the USB subsystem */ -+ deb_info("az6007 usb module exit\n"); -+ usb_deregister(&az6007_usb_driver); -+} -+ -+module_init(az6007_usb_module_init); -+module_exit(az6007_usb_module_exit); -+ -+MODULE_AUTHOR("Henry Wang "); -+MODULE_AUTHOR("Mauro Carvalho Chehab "); -+MODULE_DESCRIPTION("Driver for AzureWave 6007 DVB-C/T USB2.0 and clones"); -+MODULE_VERSION("1.1"); -+MODULE_LICENSE("GPL"); -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/az6007.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/az6007.h -@@ -0,0 +1,18 @@ -+#ifndef _DVB_USB_AZ6007_H_ -+#define _DVB_USB_AZ6007_H_ -+ -+#define DVB_USB_LOG_PREFIX "az6007" -+#include "dvb-usb.h" -+ -+ -+extern int dvb_usb_az6007_debug; -+#define deb_info(args...) dprintk(dvb_usb_az6007_debug,0x01,args) -+#define deb_xfer(args...) dprintk(dvb_usb_az6007_debug,0x02,args) -+#define deb_rc(args...) dprintk(dvb_usb_az6007_debug,0x04,args) -+#define deb_fe(args...) dprintk(dvb_usb_az6007_debug,0x08,args) -+ -+ -+extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec); -+extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); -+ -+#endif -Index: linux-3.3.x86_64/drivers/media/common/tuners/mt2063.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/common/tuners/mt2063.c -+++ linux-3.3.x86_64/drivers/media/common/tuners/mt2063.c -@@ -350,7 +350,7 @@ static int MT2063_Sleep(struct dvb_front - /* - * ToDo: Add code here to implement a OS blocking - */ -- msleep(10); -+ msleep(100); - - return 0; - } -@@ -2226,7 +2226,7 @@ static struct dvb_tuner_ops mt2063_ops = - .info = { - .name = "MT2063 Silicon Tuner", - .frequency_min = 45000000, -- .frequency_max = 850000000, -+ .frequency_max = 865000000, - .frequency_step = 0, - }, - -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/dvb-usb-ids.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/dvb-usb-ids.h -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/dvb-usb-ids.h -@@ -51,6 +51,7 @@ - #define USB_VID_PINNACLE 0x2304 - #define USB_VID_PCTV 0x2013 - #define USB_VID_PIXELVIEW 0x1554 -+#define USB_VID_REALTEK 0x0bda - #define USB_VID_TECHNOTREND 0x0b48 - #define USB_VID_TERRATEC 0x0ccd - #define USB_VID_TELESTAR 0x10b9 -@@ -75,11 +76,14 @@ - #define USB_PID_AFATECH_AF9005 0x9020 - #define USB_PID_AFATECH_AF9015_9015 0x9015 - #define USB_PID_AFATECH_AF9015_9016 0x9016 -+#define USB_PID_AFATECH_AF9035 0x9035 -+#define USB_PID_AFATECH_AF9035_2 0x1001 - #define USB_PID_TREKSTOR_DVBT 0x901b - #define USB_VID_ALINK_DTU 0xf170 - #define USB_PID_ANSONIC_DVBT_USB 0x6000 - #define USB_PID_ANYSEE 0x861f - #define USB_PID_AZUREWAVE_AD_TU700 0x3237 -+#define USB_PID_AZUREWAVE_6007 0x0ccd - #define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 - #define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 - #define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 -@@ -125,6 +129,8 @@ - #define USB_PID_E3C_EC168_3 0xfffb - #define USB_PID_E3C_EC168_4 0x1001 - #define USB_PID_E3C_EC168_5 0x1002 -+#define USB_PID_FREECOM_DVBT 0x0160 -+#define USB_PID_FREECOM_DVBT_2 0x0161 - #define USB_PID_UNIWILL_STK7700P 0x6003 - #define USB_PID_GENIUS_TVGO_DVB_T03 0x4012 - #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 -@@ -148,6 +154,7 @@ - #define USB_PID_KWORLD_VSTREAM_WARM 0x17df - #define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055 - #define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2 0x0069 -+#define USB_PID_TERRATEC_CINERGY_T_STICK 0x0093 - #define USB_PID_TERRATEC_CINERGY_T_STICK_RC 0x0097 - #define USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC 0x0099 - #define USB_PID_TWINHAN_VP7041_COLD 0x3201 -@@ -217,6 +224,11 @@ - #define USB_PID_AVERMEDIA_A850T 0x850b - #define USB_PID_AVERMEDIA_A805 0xa805 - #define USB_PID_AVERMEDIA_A815M 0x815a -+#define USB_PID_AVERMEDIA_A835 0xa835 -+#define USB_PID_AVERMEDIA_B835 0xb835 -+#define USB_PID_AVERMEDIA_1867 0x1867 -+#define USB_PID_AVERMEDIA_A867 0xa867 -+#define USB_PID_AVERMEDIA_TWINSTAR 0x0825 - #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 - #define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d - #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a -@@ -226,6 +238,8 @@ - #define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062 - #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 - #define USB_PID_TERRATEC_CINERGY_T_XXS_2 0x00ab -+#define USB_PID_TERRATEC_H7 0x10b4 -+#define USB_PID_TERRATEC_H7_2 0x10a3 - #define USB_PID_TERRATEC_T3 0x10a0 - #define USB_PID_TERRATEC_T5 0x10a1 - #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e -@@ -249,6 +263,8 @@ - #define USB_PID_PCTV_400E 0x020f - #define USB_PID_PCTV_450E 0x0222 - #define USB_PID_PCTV_452E 0x021f -+#define USB_PID_REALTEK_RTL2831U 0x2831 -+#define USB_PID_REALTEK_RTL2832U 0x2832 - #define USB_PID_TECHNOTREND_CONNECT_S2_3600 0x3007 - #define USB_PID_TECHNOTREND_CONNECT_S2_3650_CI 0x300a - #define USB_PID_NEBULA_DIGITV 0x0201 -Index: linux-3.3.x86_64/drivers/media/dvb/ddbridge/ddbridge-core.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/ddbridge/ddbridge-core.c -+++ linux-3.3.x86_64/drivers/media/dvb/ddbridge/ddbridge-core.c -@@ -578,6 +578,7 @@ static int demod_attach_drxk(struct ddb_ - struct drxk_config config; - - memset(&config, 0, sizeof(config)); -+ config.microcode_name = "drxk_a3.mc"; - config.adr = 0x29 + (input->nr & 1); - - fe = input->fe = dvb_attach(drxk_attach, &config, i2c); -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/drxk_hard.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/drxk_hard.c -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/drxk_hard.c -@@ -28,7 +28,6 @@ - #include - #include - #include --#include - #include - - #include "dvb_frontend.h" -@@ -91,10 +90,6 @@ bool IsA1WithRomCode(struct drxk_state * - #define DRXK_MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH (0x03) - #endif - --#ifndef DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH --#define DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH (0x06) --#endif -- - #define DEFAULT_DRXK_MPEG_LOCK_TIMEOUT 700 - #define DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT 500 - -@@ -650,9 +645,6 @@ static int init_state(struct drxk_state - u32 ulQual83 = DEFAULT_MER_83; - u32 ulQual93 = DEFAULT_MER_93; - -- u32 ulDVBTStaticTSClock = 1; -- u32 ulDVBCStaticTSClock = 1; -- - u32 ulMpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; - u32 ulDemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; - -@@ -662,7 +654,6 @@ static int init_state(struct drxk_state - u32 ulGPIOCfg = 0x0113; - u32 ulInvertTSClock = 0; - u32 ulTSDataStrength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH; -- u32 ulTSClockkStrength = DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH; - u32 ulDVBTBitrate = 50000000; - u32 ulDVBCBitrate = DRXK_QAM_SYMBOLRATE_MAX * 8; - -@@ -815,8 +806,7 @@ static int init_state(struct drxk_state - state->m_invertSTR = false; /* If TRUE; invert STR signals */ - state->m_invertVAL = false; /* If TRUE; invert VAL signals */ - state->m_invertCLK = (ulInvertTSClock != 0); /* If TRUE; invert CLK signals */ -- state->m_DVBTStaticCLK = (ulDVBTStaticTSClock != 0); -- state->m_DVBCStaticCLK = (ulDVBCStaticTSClock != 0); -+ - /* If TRUE; static MPEG clockrate will be used; - otherwise clockrate will adapt to the bitrate of the TS */ - -@@ -824,7 +814,6 @@ static int init_state(struct drxk_state - state->m_DVBCBitrate = ulDVBCBitrate; - - state->m_TSDataStrength = (ulTSDataStrength & 0x07); -- state->m_TSClockkStrength = (ulTSClockkStrength & 0x07); - - /* Maximum bitrate in b/s in case static clockrate is selected */ - state->m_mpegTsStaticBitrate = 19392658; -@@ -1189,6 +1178,7 @@ static int MPEGTSConfigurePins(struct dr - int status = -1; - u16 sioPdrMclkCfg = 0; - u16 sioPdrMdxCfg = 0; -+ u16 err_cfg = 0; - - dprintk(1, ": mpeg %s, %s mode\n", - mpegEnable ? "enable" : "disable", -@@ -1254,12 +1244,17 @@ static int MPEGTSConfigurePins(struct dr - status = write16(state, SIO_PDR_MSTRT_CFG__A, sioPdrMdxCfg); - if (status < 0) - goto error; -- status = write16(state, SIO_PDR_MERR_CFG__A, 0x0000); /* Disable */ -+ -+ if (state->enable_merr_cfg) -+ err_cfg = sioPdrMdxCfg; -+ -+ status = write16(state, SIO_PDR_MERR_CFG__A, err_cfg); - if (status < 0) - goto error; -- status = write16(state, SIO_PDR_MVAL_CFG__A, 0x0000); /* Disable */ -+ status = write16(state, SIO_PDR_MVAL_CFG__A, err_cfg); - if (status < 0) - goto error; -+ - if (state->m_enableParallel == true) { - /* paralel -> enable MD1 to MD7 */ - status = write16(state, SIO_PDR_MD1_CFG__A, sioPdrMdxCfg); -@@ -6070,9 +6065,7 @@ static int init_drxk(struct drxk_state * - if (status < 0) - goto error; - -- if (!state->microcode_name) -- load_microcode(state, "drxk_a3.mc"); -- else -+ if (state->microcode_name) - load_microcode(state, state->microcode_name); - - /* disable token-ring bus through OFDM block for possible ucode upload */ -@@ -6323,15 +6316,12 @@ static int drxk_get_tune_settings(struct - switch (p->delivery_system) { - case SYS_DVBC_ANNEX_A: - case SYS_DVBC_ANNEX_C: -+ case SYS_DVBT: - sets->min_delay_ms = 3000; - sets->max_drift = 0; - sets->step_size = 0; - return 0; - default: -- /* -- * For DVB-T, let it use the default DVB core way, that is: -- * fepriv->step_size = fe->ops.info.frequency_stepsize * 2 -- */ - return -EINVAL; - } - } -@@ -6391,6 +6381,21 @@ struct dvb_frontend *drxk_attach(const s - state->antenna_gpio = config->antenna_gpio; - state->antenna_dvbt = config->antenna_dvbt; - state->m_ChunkSize = config->chunk_size; -+ state->enable_merr_cfg = config->enable_merr_cfg; -+ -+ if (config->dynamic_clk) { -+ state->m_DVBTStaticCLK = 0; -+ state->m_DVBCStaticCLK = 0; -+ } else { -+ state->m_DVBTStaticCLK = 1; -+ state->m_DVBCStaticCLK = 1; -+ } -+ -+ -+ if (config->mpeg_out_clk_strength) -+ state->m_TSClockkStrength = config->mpeg_out_clk_strength & 0x07; -+ else -+ state->m_TSClockkStrength = 0x06; - - if (config->parallel_ts) - state->m_enableParallel = true; -Index: linux-3.3.x86_64/drivers/media/dvb/ngene/ngene-cards.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/ngene/ngene-cards.c -+++ linux-3.3.x86_64/drivers/media/dvb/ngene/ngene-cards.c -@@ -216,6 +216,7 @@ static int demod_attach_drxk(struct ngen - struct drxk_config config; - - memset(&config, 0, sizeof(config)); -+ config.microcode_name = "drxk_a3.mc"; - config.adr = 0x29 + (chan->number ^ 2); - - chan->fe = dvb_attach(drxk_attach, &config, i2c); -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/drxk.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/drxk.h -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/drxk.h -@@ -7,15 +7,19 @@ - /** - * struct drxk_config - Configure the initial parameters for DRX-K - * -- * adr: I2C Address of the DRX-K -- * parallel_ts: true means that the device uses parallel TS, -+ * @adr: I2C Address of the DRX-K -+ * @parallel_ts: True means that the device uses parallel TS, - * Serial otherwise. -- * single_master: Device is on the single master mode -- * no_i2c_bridge: Don't switch the I2C bridge to talk with tuner -- * antenna_gpio: GPIO bit used to control the antenna -- * antenna_dvbt: GPIO bit for changing antenna to DVB-C. A value of 1 -+ * @dynamic_clk: True means that the clock will be dynamically -+ * adjusted. Static clock otherwise. -+ * @enable_merr_cfg: Enable SIO_PDR_PERR_CFG/SIO_PDR_MVAL_CFG. -+ * @single_master: Device is on the single master mode -+ * @no_i2c_bridge: Don't switch the I2C bridge to talk with tuner -+ * @antenna_gpio: GPIO bit used to control the antenna -+ * @antenna_dvbt: GPIO bit for changing antenna to DVB-C. A value of 1 - * means that 1=DVBC, 0 = DVBT. Zero means the opposite. -- * microcode_name: Name of the firmware file with the microcode -+ * @mpeg_out_clk_strength: DRXK Mpeg output clock drive strength. -+ * @microcode_name: Name of the firmware file with the microcode - * - * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is - * UIO-3. -@@ -25,11 +29,14 @@ struct drxk_config { - bool single_master; - bool no_i2c_bridge; - bool parallel_ts; -+ bool dynamic_clk; -+ bool enable_merr_cfg; - - bool antenna_dvbt; - u16 antenna_gpio; - -- int chunk_size; -+ u8 mpeg_out_clk_strength; -+ int chunk_size; - - const char *microcode_name; - }; -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/drxk_hard.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/drxk_hard.h -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/drxk_hard.h -@@ -332,6 +332,7 @@ struct drxk_state { - - u16 UIO_mask; /* Bits used by UIO */ - -+ bool enable_merr_cfg; - bool single_master; - bool no_i2c_bridge; - bool antenna_dvbt; -Index: linux-3.3.x86_64/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c -+++ linux-3.3.x86_64/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c -@@ -18,6 +18,8 @@ - */ - - static struct rc_map_table nec_terratec_cinergy_xs[] = { -+ -+ /* Terratec Grey IR, with most keys in orange */ - { 0x1441, KEY_HOME}, - { 0x1401, KEY_POWER2}, - -@@ -78,6 +80,56 @@ static struct rc_map_table nec_terratec_ - { 0x144e, KEY_REWIND}, - { 0x144f, KEY_FASTFORWARD}, - { 0x145c, KEY_NEXT}, -+ -+ /* Terratec Black IR, with most keys in black */ -+ { 0x04eb01, KEY_POWER2}, -+ -+ { 0x04eb02, KEY_1}, -+ { 0x04eb03, KEY_2}, -+ { 0x04eb04, KEY_3}, -+ { 0x04eb05, KEY_4}, -+ { 0x04eb06, KEY_5}, -+ { 0x04eb07, KEY_6}, -+ { 0x04eb08, KEY_7}, -+ { 0x04eb09, KEY_8}, -+ { 0x04eb0a, KEY_9}, -+ { 0x04eb0c, KEY_0}, -+ -+ { 0x04eb0b, KEY_TEXT}, /* TXT */ -+ { 0x04eb0d, KEY_REFRESH}, /* Refresh */ -+ -+ { 0x04eb0e, KEY_HOME}, -+ { 0x04eb0f, KEY_EPG}, -+ -+ { 0x04eb10, KEY_UP}, -+ { 0x04eb11, KEY_LEFT}, -+ { 0x04eb12, KEY_OK}, -+ { 0x04eb13, KEY_RIGHT}, -+ { 0x04eb14, KEY_DOWN}, -+ -+ { 0x04eb15, KEY_BACKSPACE}, -+ { 0x04eb16, KEY_INFO}, -+ -+ { 0x04eb17, KEY_RED}, -+ { 0x04eb18, KEY_GREEN}, -+ { 0x04eb19, KEY_YELLOW}, -+ { 0x04eb1a, KEY_BLUE}, -+ -+ { 0x04eb1c, KEY_VOLUMEUP}, -+ { 0x04eb1e, KEY_VOLUMEDOWN}, -+ -+ { 0x04eb1d, KEY_MUTE}, -+ -+ { 0x04eb1b, KEY_CHANNELUP}, -+ { 0x04eb1f, KEY_CHANNELDOWN}, -+ -+ { 0x04eb40, KEY_RECORD}, -+ { 0x04eb4c, KEY_PLAY}, -+ { 0x04eb58, KEY_PAUSE}, -+ -+ { 0x04eb54, KEY_REWIND}, -+ { 0x04eb48, KEY_STOP}, -+ { 0x04eb5c, KEY_NEXT}, - }; - - static struct rc_map_list nec_terratec_cinergy_xs_map = { -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/Kconfig -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/Kconfig -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/Kconfig -@@ -361,6 +361,14 @@ config DVB_USB_EC168 - help - Say Y here to support the E3C EC168 DVB-T USB2.0 receiver. - -+config DVB_USB_AZ6007 -+ tristate "AzureWave 6007 and clones DVB-T/C USB2.0 support" -+ depends on DVB_USB -+ select DVB_DRXK if !DVB_FE_CUSTOMISE -+ select MEDIA_TUNER_MT2063 if !DVB_FE_CUSTOMISE -+ help -+ Say Y here to support theAfatech AF9005 based DVB-T/DVB-C receivers. -+ - config DVB_USB_AZ6027 - tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support" - depends on DVB_USB -@@ -378,6 +386,7 @@ config DVB_USB_LME2510 - select DVB_IX2505V if !DVB_FE_CUSTOMISE - select DVB_STV0299 if !DVB_FE_CUSTOMISE - select DVB_PLL if !DVB_FE_CUSTOMISE -+ select DVB_M88RS2000 if !DVB_FE_CUSTOMISE - help - Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 . - -@@ -403,3 +412,25 @@ config DVB_USB_MXL111SF - select VIDEO_TVEEPROM - help - Say Y here to support the MxL111SF USB2.0 DTV receiver. -+ -+config DVB_USB_RTL28XXU -+ tristate "Realtek RTL28xxU DVB USB support" -+ depends on DVB_USB && EXPERIMENTAL -+ select DVB_RTL2830 -+ select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE -+ select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE -+ select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE -+ help -+ Say Y here to support the Realtek RTL28xxU DVB USB receiver. -+ -+config DVB_USB_AF9035 -+ tristate "Afatech AF9035 DVB-T USB2.0 support" -+ depends on DVB_USB -+ select DVB_AF9033 -+ select MEDIA_TUNER_TUA9001 if !MEDIA_TUNER_CUSTOMISE -+ select MEDIA_TUNER_FC0011 if !MEDIA_TUNER_CUSTOMISE -+ select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE -+ select MEDIA_TUNER_TDA18218 if !MEDIA_TUNER_CUSTOMISE -+ help -+ Say Y here to support the Afatech AF9035 based DVB USB receiver. -+ -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/Makefile -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/Makefile -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/Makefile -@@ -54,7 +54,6 @@ obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb - dvb-usb-opera-objs = opera1.o - obj-$(CONFIG_DVB_USB_OPERA1) += dvb-usb-opera.o - -- - dvb-usb-af9005-objs = af9005.o af9005-fe.o - obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o - -@@ -88,6 +87,9 @@ obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-f - dvb-usb-ec168-objs = ec168.o - obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o - -+dvb-usb-az6007-objs = az6007.o -+obj-$(CONFIG_DVB_USB_AZ6007) += dvb-usb-az6007.o -+ - dvb-usb-az6027-objs = az6027.o - obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o - -@@ -105,8 +107,15 @@ obj-$(CONFIG_DVB_USB_MXL111SF) += dvb-us - obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-demod.o - obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o - --ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ -+dvb-usb-rtl28xxu-objs = rtl28xxu.o -+obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o -+ -+dvb-usb-af9035-objs = af9035.o -+obj-$(CONFIG_DVB_USB_AF9035) += dvb-usb-af9035.o -+ -+ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core -+ccflags-y += -I$(srctree)/drivers/media/dvb/frontends/ - # due to tuner-xc3028 --ccflags-y += -Idrivers/media/common/tuners --EXTRA_CFLAGS += -Idrivers/media/dvb/ttpci -+ccflags-y += -I$(srctree)/drivers/media/common/tuners -+ccflags-y += -I$(srctree)/drivers/media/dvb/ttpci - -Index: linux-3.3.x86_64/drivers/media/video/omap/omap_vout.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/omap/omap_vout.c -+++ linux-3.3.x86_64/drivers/media/video/omap/omap_vout.c -@@ -2268,13 +2268,12 @@ static struct platform_driver omap_vout_ - .driver = { - .name = VOUT_NAME, - }, -- .probe = omap_vout_probe, - .remove = omap_vout_remove, - }; - - static int __init omap_vout_init(void) - { -- if (platform_driver_register(&omap_vout_driver) != 0) { -+ if (platform_driver_probe(&omap_vout_driver, omap_vout_probe) != 0) { - printk(KERN_ERR VOUT_NAME ":Could not register Video driver\n"); - return -EINVAL; - } -Index: linux-3.3.x86_64/Documentation/DocBook/media/v4l/compat.xml -=================================================================== ---- linux-3.3.x86_64.orig/Documentation/DocBook/media/v4l/compat.xml -+++ linux-3.3.x86_64/Documentation/DocBook/media/v4l/compat.xml -@@ -2393,6 +2393,10 @@ details. - to the User controls class. - - -+ -+ Added the device_caps field to struct v4l2_capabilities and added the new -+ V4L2_CAP_DEVICE_CAPS capability. -+ - -
- -Index: linux-3.3.x86_64/Documentation/DocBook/media/v4l/v4l2.xml -=================================================================== ---- linux-3.3.x86_64.orig/Documentation/DocBook/media/v4l/v4l2.xml -+++ linux-3.3.x86_64/Documentation/DocBook/media/v4l/v4l2.xml -@@ -128,6 +128,13 @@ structs, ioctls) must be noted in more d - applications. --> - - -+ 3.3 -+ 2012-01-11 -+ hv -+ Added device_caps field to struct v4l2_capabilities. -+ -+ -+ - 3.2 - 2011-08-26 - hv -@@ -417,7 +424,7 @@ and discussions on the V4L mailing list. - - - Video for Linux Two API Specification -- Revision 3.2 -+ Revision 3.3 - - - &sub-common; -Index: linux-3.3.x86_64/Documentation/DocBook/media/v4l/vidioc-querycap.xml -=================================================================== ---- linux-3.3.x86_64.orig/Documentation/DocBook/media/v4l/vidioc-querycap.xml -+++ linux-3.3.x86_64/Documentation/DocBook/media/v4l/vidioc-querycap.xml -@@ -124,12 +124,35 @@ printf ("Version: %u.%u.%u\n", - - __u32 - capabilities -- Device capabilities, see . -+ Available capabilities of the physical device as a whole, see . The same physical device can export -+ multiple devices in /dev (e.g. /dev/videoX, /dev/vbiY and /dev/radioZ). -+ The capabilities field should contain a union -+ of all capabilities available around the several V4L2 devices exported -+ to userspace. -+ For all those devices the capabilities field -+ returns the same set of capabilities. This allows applications to open -+ just one of the devices (typically the video device) and discover whether -+ video, vbi and/or radio are also supported. -+ - - - __u32 -- reserved[4] -+ device_caps -+ Device capabilities of the opened device, see . Should contain the available capabilities -+ of that specific device node. So, for example, device_caps -+ of a radio device will only contain radio related capabilities and -+ no video or vbi capabilities. This field is only set if the capabilities -+ field contains the V4L2_CAP_DEVICE_CAPS capability. -+ Only the capabilities field can have the -+ V4L2_CAP_DEVICE_CAPS capability, device_caps -+ will never set V4L2_CAP_DEVICE_CAPS. -+ -+ -+ -+ __u32 -+ reserved[3] - Reserved for future extensions. Drivers must set - this array to zero. - -@@ -276,6 +299,13 @@ linkend="async">asynchronous I/O - The device supports the streaming I/O method. - -+ -+ V4L2_CAP_DEVICE_CAPS -+ 0x80000000 -+ The driver fills the device_caps -+ field. This capability can only appear in the capabilities -+ field and never in the device_caps field. -+ - - - -Index: linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-417.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/cx231xx/cx231xx-417.c -+++ linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-417.c -@@ -1686,7 +1686,6 @@ static struct v4l2_capability pvr_capabi - .capabilities = (V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | - V4L2_CAP_STREAMING | V4L2_CAP_READWRITE), -- .reserved = {0, 0, 0, 0} - }; - static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -Index: linux-3.3.x86_64/drivers/media/video/pvrusb2/pvrusb2-v4l2.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/pvrusb2/pvrusb2-v4l2.c -+++ linux-3.3.x86_64/drivers/media/video/pvrusb2/pvrusb2-v4l2.c -@@ -96,7 +96,6 @@ static struct v4l2_capability pvr_capabi - .capabilities = (V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | - V4L2_CAP_READWRITE), -- .reserved = {0,0,0,0} - }; - - static struct v4l2_fmtdesc pvr_fmtdesc [] = { -Index: linux-3.3.x86_64/drivers/media/video/v4l2-ioctl.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/v4l2-ioctl.c -+++ linux-3.3.x86_64/drivers/media/video/v4l2-ioctl.c -@@ -260,6 +260,8 @@ static const char *v4l2_ioctls[] = { - [_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD", - [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD", - -+ [_IOC_NR(VIDIOC_DECODER_CMD)] = "VIDIOC_DECODER_CMD", -+ [_IOC_NR(VIDIOC_TRY_DECODER_CMD)] = "VIDIOC_TRY_DECODER_CMD", - [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", - [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", - -@@ -540,10 +542,12 @@ static long __video_do_ioctl(struct file - if (!ret) - dbgarg(cmd, "driver=%s, card=%s, bus=%s, " - "version=0x%08x, " -- "capabilities=0x%08x\n", -+ "capabilities=0x%08x, " -+ "device_caps=0x%08x\n", - cap->driver, cap->card, cap->bus_info, - cap->version, -- cap->capabilities); -+ cap->capabilities, -+ cap->device_caps); - break; - } - -@@ -1762,6 +1766,32 @@ static long __video_do_ioctl(struct file - dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); - break; - } -+ case VIDIOC_DECODER_CMD: -+ { -+ struct v4l2_decoder_cmd *p = arg; -+ -+ if (!ops->vidioc_decoder_cmd) -+ break; -+ if (ret_prio) { -+ ret = ret_prio; -+ break; -+ } -+ ret = ops->vidioc_decoder_cmd(file, fh, p); -+ if (!ret) -+ dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); -+ break; -+ } -+ case VIDIOC_TRY_DECODER_CMD: -+ { -+ struct v4l2_decoder_cmd *p = arg; -+ -+ if (!ops->vidioc_try_decoder_cmd) -+ break; -+ ret = ops->vidioc_try_decoder_cmd(file, fh, p); -+ if (!ret) -+ dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); -+ break; -+ } - case VIDIOC_G_PARM: - { - struct v4l2_streamparm *p = arg; -@@ -1909,7 +1939,13 @@ static long __video_do_ioctl(struct file - { - if (!ops->vidioc_log_status) - break; -+ if (vfd->v4l2_dev) -+ pr_info("%s: ================= START STATUS =================\n", -+ vfd->v4l2_dev->name); - ret = ops->vidioc_log_status(file, fh); -+ if (vfd->v4l2_dev) -+ pr_info("%s: ================== END STATUS ==================\n", -+ vfd->v4l2_dev->name); - break; - } - #ifdef CONFIG_VIDEO_ADV_DEBUG -@@ -2419,7 +2455,7 @@ video_usercopy(struct file *file, unsign - /* Handles IOCTL */ - err = func(file, cmd, parg); - if (err == -ENOIOCTLCMD) -- err = -EINVAL; -+ err = -ENOTTY; - - if (has_array_args) { - *kernel_ptr = user_ptr; -Index: linux-3.3.x86_64/include/linux/videodev2.h -=================================================================== ---- linux-3.3.x86_64.orig/include/linux/videodev2.h -+++ linux-3.3.x86_64/include/linux/videodev2.h -@@ -235,16 +235,25 @@ struct v4l2_fract { - __u32 denominator; - }; - --/* -- * D R I V E R C A P A B I L I T I E S -- */ -+/** -+ * struct v4l2_capability - Describes V4L2 device caps returned by VIDIOC_QUERYCAP -+ * -+ * @driver: name of the driver module (e.g. "bttv") -+ * @card: name of the card (e.g. "Hauppauge WinTV") -+ * @bus_info: name of the bus (e.g. "PCI:" + pci_name(pci_dev) ) -+ * @version: KERNEL_VERSION -+ * @capabilities: capabilities of the physical device as a whole -+ * @device_caps: capabilities accessed via this particular device (node) -+ * @reserved: reserved fields for future extensions -+ */ - struct v4l2_capability { -- __u8 driver[16]; /* i.e. "bttv" */ -- __u8 card[32]; /* i.e. "Hauppauge WinTV" */ -- __u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */ -- __u32 version; /* should use KERNEL_VERSION() */ -- __u32 capabilities; /* Device capabilities */ -- __u32 reserved[4]; -+ __u8 driver[16]; -+ __u8 card[32]; -+ __u8 bus_info[32]; -+ __u32 version; -+ __u32 capabilities; -+ __u32 device_caps; -+ __u32 reserved[3]; - }; - - /* Values for 'capabilities' field */ -@@ -274,6 +283,8 @@ struct v4l2_capability { - #define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */ - #define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */ - -+#define V4L2_CAP_DEVICE_CAPS 0x80000000 /* sets device capabilities field */ -+ - /* - * V I D E O I M A G E F O R M A T - */ -@@ -751,20 +762,20 @@ struct v4l2_crop { - - /* Selection targets */ - --/* current cropping area */ --#define V4L2_SEL_TGT_CROP_ACTIVE 0 --/* default cropping area */ --#define V4L2_SEL_TGT_CROP_DEFAULT 1 --/* cropping bounds */ --#define V4L2_SEL_TGT_CROP_BOUNDS 2 --/* current composing area */ --#define V4L2_SEL_TGT_COMPOSE_ACTIVE 256 --/* default composing area */ --#define V4L2_SEL_TGT_COMPOSE_DEFAULT 257 --/* composing bounds */ --#define V4L2_SEL_TGT_COMPOSE_BOUNDS 258 --/* current composing area plus all padding pixels */ --#define V4L2_SEL_TGT_COMPOSE_PADDED 259 -+/* Current cropping area */ -+#define V4L2_SEL_TGT_CROP_ACTIVE 0x0000 -+/* Default cropping area */ -+#define V4L2_SEL_TGT_CROP_DEFAULT 0x0001 -+/* Cropping bounds */ -+#define V4L2_SEL_TGT_CROP_BOUNDS 0x0002 -+/* Current composing area */ -+#define V4L2_SEL_TGT_COMPOSE_ACTIVE 0x0100 -+/* Default composing area */ -+#define V4L2_SEL_TGT_COMPOSE_DEFAULT 0x0101 -+/* Composing bounds */ -+#define V4L2_SEL_TGT_COMPOSE_BOUNDS 0x0102 -+/* Current composing area plus all padding pixels */ -+#define V4L2_SEL_TGT_COMPOSE_PADDED 0x0103 - - /** - * struct v4l2_selection - selection info -@@ -774,7 +785,7 @@ struct v4l2_crop { - * @r: coordinates of selection window - * @reserved: for future use, rounds structure size to 64 bytes, set to zero - * -- * Hardware may use multiple helper window to process a video stream. -+ * Hardware may use multiple helper windows to process a video stream. - * The structure is used to exchange this selection areas between - * an application and a driver. - */ -@@ -1125,6 +1136,7 @@ struct v4l2_ext_controls { - #define V4L2_CTRL_CLASS_CAMERA 0x009a0000 /* Camera class controls */ - #define V4L2_CTRL_CLASS_FM_TX 0x009b0000 /* FM Modulator control class */ - #define V4L2_CTRL_CLASS_FLASH 0x009c0000 /* Camera flash controls */ -+#define V4L2_CTRL_CLASS_JPEG 0x009d0000 /* JPEG-compression controls */ - - #define V4L2_CTRL_ID_MASK (0x0fffffff) - #define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) -@@ -1396,6 +1408,16 @@ enum v4l2_mpeg_audio_ac3_bitrate { - V4L2_MPEG_AUDIO_AC3_BITRATE_576K = 17, - V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18, - }; -+#define V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK (V4L2_CID_MPEG_BASE+112) -+enum v4l2_mpeg_audio_dec_playback { -+ V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO = 0, -+ V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO = 1, -+ V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT = 2, -+ V4L2_MPEG_AUDIO_DEC_PLAYBACK_RIGHT = 3, -+ V4L2_MPEG_AUDIO_DEC_PLAYBACK_MONO = 4, -+ V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO = 5, -+}; -+#define V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK (V4L2_CID_MPEG_BASE+113) - - /* MPEG video controls specific to multiplexed streams */ - #define V4L2_CID_MPEG_VIDEO_ENCODING (V4L2_CID_MPEG_BASE+200) -@@ -1446,6 +1468,9 @@ enum v4l2_mpeg_video_multi_slice_mode { - V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES = 2, - }; - #define V4L2_CID_MPEG_VIDEO_VBV_SIZE (V4L2_CID_MPEG_BASE+222) -+#define V4L2_CID_MPEG_VIDEO_DEC_PTS (V4L2_CID_MPEG_BASE+223) -+#define V4L2_CID_MPEG_VIDEO_DEC_FRAME (V4L2_CID_MPEG_BASE+224) -+ - #define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP (V4L2_CID_MPEG_BASE+300) - #define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP (V4L2_CID_MPEG_BASE+301) - #define V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP (V4L2_CID_MPEG_BASE+302) -@@ -1734,6 +1759,29 @@ enum v4l2_flash_strobe_source { - #define V4L2_CID_FLASH_CHARGE (V4L2_CID_FLASH_CLASS_BASE + 11) - #define V4L2_CID_FLASH_READY (V4L2_CID_FLASH_CLASS_BASE + 12) - -+/* JPEG-class control IDs defined by V4L2 */ -+#define V4L2_CID_JPEG_CLASS_BASE (V4L2_CTRL_CLASS_JPEG | 0x900) -+#define V4L2_CID_JPEG_CLASS (V4L2_CTRL_CLASS_JPEG | 1) -+ -+#define V4L2_CID_JPEG_CHROMA_SUBSAMPLING (V4L2_CID_JPEG_CLASS_BASE + 1) -+enum v4l2_jpeg_chroma_subsampling { -+ V4L2_JPEG_CHROMA_SUBSAMPLING_444 = 0, -+ V4L2_JPEG_CHROMA_SUBSAMPLING_422 = 1, -+ V4L2_JPEG_CHROMA_SUBSAMPLING_420 = 2, -+ V4L2_JPEG_CHROMA_SUBSAMPLING_411 = 3, -+ V4L2_JPEG_CHROMA_SUBSAMPLING_410 = 4, -+ V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY = 5, -+}; -+#define V4L2_CID_JPEG_RESTART_INTERVAL (V4L2_CID_JPEG_CLASS_BASE + 2) -+#define V4L2_CID_JPEG_COMPRESSION_QUALITY (V4L2_CID_JPEG_CLASS_BASE + 3) -+ -+#define V4L2_CID_JPEG_ACTIVE_MARKER (V4L2_CID_JPEG_CLASS_BASE + 4) -+#define V4L2_JPEG_ACTIVE_MARKER_APP0 (1 << 0) -+#define V4L2_JPEG_ACTIVE_MARKER_APP1 (1 << 1) -+#define V4L2_JPEG_ACTIVE_MARKER_COM (1 << 16) -+#define V4L2_JPEG_ACTIVE_MARKER_DQT (1 << 17) -+#define V4L2_JPEG_ACTIVE_MARKER_DHT (1 << 18) -+ - /* - * T U N I N G - */ -@@ -1897,6 +1945,54 @@ struct v4l2_encoder_cmd { - }; - }; - -+/* Decoder commands */ -+#define V4L2_DEC_CMD_START (0) -+#define V4L2_DEC_CMD_STOP (1) -+#define V4L2_DEC_CMD_PAUSE (2) -+#define V4L2_DEC_CMD_RESUME (3) -+ -+/* Flags for V4L2_DEC_CMD_START */ -+#define V4L2_DEC_CMD_START_MUTE_AUDIO (1 << 0) -+ -+/* Flags for V4L2_DEC_CMD_PAUSE */ -+#define V4L2_DEC_CMD_PAUSE_TO_BLACK (1 << 0) -+ -+/* Flags for V4L2_DEC_CMD_STOP */ -+#define V4L2_DEC_CMD_STOP_TO_BLACK (1 << 0) -+#define V4L2_DEC_CMD_STOP_IMMEDIATELY (1 << 1) -+ -+/* Play format requirements (returned by the driver): */ -+ -+/* The decoder has no special format requirements */ -+#define V4L2_DEC_START_FMT_NONE (0) -+/* The decoder requires full GOPs */ -+#define V4L2_DEC_START_FMT_GOP (1) -+ -+/* The structure must be zeroed before use by the application -+ This ensures it can be extended safely in the future. */ -+struct v4l2_decoder_cmd { -+ __u32 cmd; -+ __u32 flags; -+ union { -+ struct { -+ __u64 pts; -+ } stop; -+ -+ struct { -+ /* 0 or 1000 specifies normal speed, -+ 1 specifies forward single stepping, -+ -1 specifies backward single stepping, -+ >1: playback at speed/1000 of the normal speed, -+ <-1: reverse playback at (-speed/1000) of the normal speed. */ -+ __s32 speed; -+ __u32 format; -+ } start; -+ -+ struct { -+ __u32 data[16]; -+ } raw; -+ }; -+}; - #endif - - -@@ -2307,6 +2403,11 @@ struct v4l2_create_buffers { - #define VIDIOC_G_SELECTION _IOWR('V', 94, struct v4l2_selection) - #define VIDIOC_S_SELECTION _IOWR('V', 95, struct v4l2_selection) - -+/* Experimental, these two ioctls may change over the next couple of kernel -+ versions. */ -+#define VIDIOC_DECODER_CMD _IOWR('V', 96, struct v4l2_decoder_cmd) -+#define VIDIOC_TRY_DECODER_CMD _IOWR('V', 97, struct v4l2_decoder_cmd) -+ - /* Reminder: when adding new ioctls please add support for them to - drivers/media/video/v4l2-compat-ioctl32.c as well! */ - -Index: linux-3.3.x86_64/drivers/media/video/vivi.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/vivi.c -+++ linux-3.3.x86_64/drivers/media/video/vivi.c -@@ -819,8 +819,9 @@ static int vidioc_querycap(struct file * - strcpy(cap->driver, "vivi"); - strcpy(cap->card, "vivi"); - strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); -- cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \ -+ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | - V4L2_CAP_READWRITE; -+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; - } - -@@ -958,14 +959,6 @@ static int vidioc_streamoff(struct file - return vb2_streamoff(&dev->vb_vidq, i); - } - --static int vidioc_log_status(struct file *file, void *priv) --{ -- struct vivi_dev *dev = video_drvdata(file); -- -- v4l2_ctrl_handler_log_status(&dev->ctrl_handler, dev->v4l2_dev.name); -- return 0; --} -- - static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) - { - return 0; -@@ -1008,17 +1001,6 @@ static int vidioc_s_input(struct file *f - return 0; - } - --static int vidioc_subscribe_event(struct v4l2_fh *fh, -- struct v4l2_event_subscription *sub) --{ -- switch (sub->type) { -- case V4L2_EVENT_CTRL: -- return v4l2_event_subscribe(fh, sub, 0); -- default: -- return -EINVAL; -- } --} -- - /* --- controls ---------------------------------------------- */ - - static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl) -@@ -1057,17 +1039,10 @@ static unsigned int - vivi_poll(struct file *file, struct poll_table_struct *wait) - { - struct vivi_dev *dev = video_drvdata(file); -- struct v4l2_fh *fh = file->private_data; - struct vb2_queue *q = &dev->vb_vidq; -- unsigned int res; - - dprintk(dev, 1, "%s\n", __func__); -- res = vb2_poll(q, file, wait); -- if (v4l2_event_pending(fh)) -- res |= POLLPRI; -- else -- poll_wait(file, &fh->wait, wait); -- return res; -+ return vb2_poll(q, file, wait); - } - - static int vivi_close(struct file *file) -@@ -1209,8 +1184,8 @@ static const struct v4l2_ioctl_ops vivi_ - .vidioc_s_input = vidioc_s_input, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, -- .vidioc_log_status = vidioc_log_status, -- .vidioc_subscribe_event = vidioc_subscribe_event, -+ .vidioc_log_status = v4l2_ctrl_log_status, -+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - }; - -Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-driver.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-driver.h -+++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-driver.h -@@ -331,6 +331,7 @@ struct ivtv_stream { - struct ivtv *itv; /* for ease of use */ - const char *name; /* name of the stream */ - int type; /* stream type */ -+ u32 caps; /* V4L2 capabilities */ - - struct v4l2_fh *fh; /* pointer to the streaming filehandle */ - spinlock_t qlock; /* locks access to the queues */ -@@ -630,6 +631,16 @@ struct ivtv { - - struct v4l2_device v4l2_dev; - struct cx2341x_handler cxhdl; -+ struct { -+ /* PTS/Frame count control cluster */ -+ struct v4l2_ctrl *ctrl_pts; -+ struct v4l2_ctrl *ctrl_frame; -+ }; -+ struct { -+ /* Audio Playback control cluster */ -+ struct v4l2_ctrl *ctrl_audio_playback; -+ struct v4l2_ctrl *ctrl_audio_multilingual_playback; -+ }; - struct v4l2_ctrl_handler hdl_gpio; - struct v4l2_subdev sd_gpio; /* GPIO sub-device */ - u16 instance; -@@ -649,7 +660,6 @@ struct ivtv { - u8 audio_stereo_mode; /* decoder setting how to handle stereo MPEG audio */ - u8 audio_bilingual_mode; /* decoder setting how to handle bilingual MPEG audio */ - -- - /* Locking */ - spinlock_t lock; /* lock access to this struct */ - struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */ -Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-ioctl.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-ioctl.c -+++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-ioctl.c -@@ -246,34 +246,40 @@ static int ivtv_validate_speed(int cur_s - } - - static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, -- struct video_command *vc, int try) -+ struct v4l2_decoder_cmd *dc, int try) - { - struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; - - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return -EINVAL; - -- switch (vc->cmd) { -- case VIDEO_CMD_PLAY: { -- vc->flags = 0; -- vc->play.speed = ivtv_validate_speed(itv->speed, vc->play.speed); -- if (vc->play.speed < 0) -- vc->play.format = VIDEO_PLAY_FMT_GOP; -+ switch (dc->cmd) { -+ case V4L2_DEC_CMD_START: { -+ dc->flags &= V4L2_DEC_CMD_START_MUTE_AUDIO; -+ dc->start.speed = ivtv_validate_speed(itv->speed, dc->start.speed); -+ if (dc->start.speed < 0) -+ dc->start.format = V4L2_DEC_START_FMT_GOP; -+ else -+ dc->start.format = V4L2_DEC_START_FMT_NONE; -+ if (dc->start.speed != 500 && dc->start.speed != 1500) -+ dc->flags = dc->start.speed == 1000 ? 0 : -+ V4L2_DEC_CMD_START_MUTE_AUDIO; - if (try) break; - -+ itv->speed_mute_audio = dc->flags & V4L2_DEC_CMD_START_MUTE_AUDIO; - if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG) - return -EBUSY; - if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) { - /* forces ivtv_set_speed to be called */ - itv->speed = 0; - } -- return ivtv_start_decoding(id, vc->play.speed); -+ return ivtv_start_decoding(id, dc->start.speed); - } - -- case VIDEO_CMD_STOP: -- vc->flags &= VIDEO_CMD_STOP_IMMEDIATELY|VIDEO_CMD_STOP_TO_BLACK; -- if (vc->flags & VIDEO_CMD_STOP_IMMEDIATELY) -- vc->stop.pts = 0; -+ case V4L2_DEC_CMD_STOP: -+ dc->flags &= V4L2_DEC_CMD_STOP_IMMEDIATELY | V4L2_DEC_CMD_STOP_TO_BLACK; -+ if (dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) -+ dc->stop.pts = 0; - if (try) break; - if (atomic_read(&itv->decoding) == 0) - return 0; -@@ -281,22 +287,22 @@ static int ivtv_video_command(struct ivt - return -EBUSY; - - itv->output_mode = OUT_NONE; -- return ivtv_stop_v4l2_decode_stream(s, vc->flags, vc->stop.pts); -+ return ivtv_stop_v4l2_decode_stream(s, dc->flags, dc->stop.pts); - -- case VIDEO_CMD_FREEZE: -- vc->flags &= VIDEO_CMD_FREEZE_TO_BLACK; -+ case V4L2_DEC_CMD_PAUSE: -+ dc->flags &= V4L2_DEC_CMD_PAUSE_TO_BLACK; - if (try) break; - if (itv->output_mode != OUT_MPG) - return -EBUSY; - if (atomic_read(&itv->decoding) > 0) { - ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, -- (vc->flags & VIDEO_CMD_FREEZE_TO_BLACK) ? 1 : 0); -+ (dc->flags & V4L2_DEC_CMD_PAUSE_TO_BLACK) ? 1 : 0); - set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); - } - break; - -- case VIDEO_CMD_CONTINUE: -- vc->flags = 0; -+ case V4L2_DEC_CMD_RESUME: -+ dc->flags = 0; - if (try) break; - if (itv->output_mode != OUT_MPG) - return -EBUSY; -@@ -754,12 +760,15 @@ static int ivtv_s_register(struct file * - - static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap) - { -- struct ivtv *itv = fh2id(fh)->itv; -+ struct ivtv_open_id *id = fh2id(file->private_data); -+ struct ivtv *itv = id->itv; -+ struct ivtv_stream *s = &itv->streams[id->type]; - - strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); - strlcpy(vcap->card, itv->card_name, sizeof(vcap->card)); - snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev)); -- vcap->capabilities = itv->v4l2_cap; /* capabilities */ -+ vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS; -+ vcap->device_caps = s->caps; - return 0; - } - -@@ -1476,8 +1485,6 @@ static int ivtv_log_status(struct file * - struct v4l2_audio audin; - int i; - -- IVTV_INFO("================= START STATUS CARD #%d =================\n", -- itv->instance); - IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name); - if (itv->hw_flags & IVTV_HW_TVEEPROM) { - struct tveeprom tv; -@@ -1501,13 +1508,6 @@ static int ivtv_log_status(struct file * - "YUV Frames", - "Passthrough", - }; -- static const char * const audio_modes[5] = { -- "Stereo", -- "Left", -- "Right", -- "Mono", -- "Swapped" -- }; - static const char * const alpha_mode[4] = { - "None", - "Global", -@@ -1536,9 +1536,6 @@ static int ivtv_log_status(struct file * - ivtv_get_output(itv, itv->active_output, &vidout); - ivtv_get_audio_output(itv, 0, &audout); - IVTV_INFO("Video Output: %s\n", vidout.name); -- IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name, -- audio_modes[itv->audio_stereo_mode], -- audio_modes[itv->audio_bilingual_mode]); - if (mode < 0 || mode > OUT_PASSTHROUGH) - mode = OUT_NONE; - IVTV_INFO("Output Mode: %s\n", output_modes[mode]); -@@ -1566,12 +1563,27 @@ static int ivtv_log_status(struct file * - IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", - (long long)itv->mpg_data_received, - (long long)itv->vbi_data_inserted); -- IVTV_INFO("================== END STATUS CARD #%d ==================\n", -- itv->instance); -- - return 0; - } - -+static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) -+{ -+ struct ivtv_open_id *id = fh2id(file->private_data); -+ struct ivtv *itv = id->itv; -+ -+ IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n", dec->cmd); -+ return ivtv_video_command(itv, id, dec, false); -+} -+ -+static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) -+{ -+ struct ivtv_open_id *id = fh2id(file->private_data); -+ struct ivtv *itv = id->itv; -+ -+ IVTV_DEBUG_IOCTL("VIDIOC_TRY_DECODER_CMD %d\n", dec->cmd); -+ return ivtv_video_command(itv, id, dec, true); -+} -+ - static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) - { - struct ivtv_open_id *id = fh2id(filp->private_data); -@@ -1605,9 +1617,15 @@ static int ivtv_decoder_ioctls(struct fi - return ivtv_yuv_prep_frame(itv, args); - } - -+ case IVTV_IOC_PASSTHROUGH_MODE: -+ IVTV_DEBUG_IOCTL("IVTV_IOC_PASSTHROUGH_MODE\n"); -+ if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) -+ return -EINVAL; -+ return ivtv_passthrough_mode(itv, *(int *)arg != 0); -+ - case VIDEO_GET_PTS: { -- u32 data[CX2341X_MBOX_MAX_DATA]; -- u64 *pts = arg; -+ s64 *pts = arg; -+ s64 frame; - - IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n"); - if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { -@@ -1616,29 +1634,12 @@ static int ivtv_decoder_ioctls(struct fi - } - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return -EINVAL; -- -- if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { -- *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) | -- (u64)itv->last_dec_timing[1]; -- break; -- } -- *pts = 0; -- if (atomic_read(&itv->decoding)) { -- if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { -- IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); -- return -EIO; -- } -- memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); -- set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); -- *pts = (u64) ((u64) data[2] << 32) | (u64) data[1]; -- /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/ -- } -- break; -+ return ivtv_g_pts_frame(itv, pts, &frame); - } - - case VIDEO_GET_FRAME_COUNT: { -- u32 data[CX2341X_MBOX_MAX_DATA]; -- u64 *frame = arg; -+ s64 *frame = arg; -+ s64 pts; - - IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n"); - if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { -@@ -1647,71 +1648,58 @@ static int ivtv_decoder_ioctls(struct fi - } - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return -EINVAL; -- -- if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { -- *frame = itv->last_dec_timing[0]; -- break; -- } -- *frame = 0; -- if (atomic_read(&itv->decoding)) { -- if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { -- IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); -- return -EIO; -- } -- memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); -- set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); -- *frame = data[0]; -- } -- break; -+ return ivtv_g_pts_frame(itv, &pts, frame); - } - - case VIDEO_PLAY: { -- struct video_command vc; -+ struct v4l2_decoder_cmd dc; - - IVTV_DEBUG_IOCTL("VIDEO_PLAY\n"); -- memset(&vc, 0, sizeof(vc)); -- vc.cmd = VIDEO_CMD_PLAY; -- return ivtv_video_command(itv, id, &vc, 0); -+ memset(&dc, 0, sizeof(dc)); -+ dc.cmd = V4L2_DEC_CMD_START; -+ return ivtv_video_command(itv, id, &dc, 0); - } - - case VIDEO_STOP: { -- struct video_command vc; -+ struct v4l2_decoder_cmd dc; - - IVTV_DEBUG_IOCTL("VIDEO_STOP\n"); -- memset(&vc, 0, sizeof(vc)); -- vc.cmd = VIDEO_CMD_STOP; -- vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY; -- return ivtv_video_command(itv, id, &vc, 0); -+ memset(&dc, 0, sizeof(dc)); -+ dc.cmd = V4L2_DEC_CMD_STOP; -+ dc.flags = V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY; -+ return ivtv_video_command(itv, id, &dc, 0); - } - - case VIDEO_FREEZE: { -- struct video_command vc; -+ struct v4l2_decoder_cmd dc; - - IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n"); -- memset(&vc, 0, sizeof(vc)); -- vc.cmd = VIDEO_CMD_FREEZE; -- return ivtv_video_command(itv, id, &vc, 0); -+ memset(&dc, 0, sizeof(dc)); -+ dc.cmd = V4L2_DEC_CMD_PAUSE; -+ return ivtv_video_command(itv, id, &dc, 0); - } - - case VIDEO_CONTINUE: { -- struct video_command vc; -+ struct v4l2_decoder_cmd dc; - - IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n"); -- memset(&vc, 0, sizeof(vc)); -- vc.cmd = VIDEO_CMD_CONTINUE; -- return ivtv_video_command(itv, id, &vc, 0); -+ memset(&dc, 0, sizeof(dc)); -+ dc.cmd = V4L2_DEC_CMD_RESUME; -+ return ivtv_video_command(itv, id, &dc, 0); - } - - case VIDEO_COMMAND: - case VIDEO_TRY_COMMAND: { -- struct video_command *vc = arg; -+ /* Note: struct v4l2_decoder_cmd has the same layout as -+ struct video_command */ -+ struct v4l2_decoder_cmd *dc = arg; - int try = (cmd == VIDEO_TRY_COMMAND); - - if (try) -- IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd); -+ IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", dc->cmd); - else -- IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd); -- return ivtv_video_command(itv, id, vc, try); -+ IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", dc->cmd); -+ return ivtv_video_command(itv, id, dc, try); - } - - case VIDEO_GET_EVENT: { -@@ -1775,17 +1763,13 @@ static int ivtv_decoder_ioctls(struct fi - IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n"); - if (iarg > AUDIO_STEREO_SWAPPED) - return -EINVAL; -- itv->audio_stereo_mode = iarg; -- ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); -- return 0; -+ return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg + 1); - - case AUDIO_BILINGUAL_CHANNEL_SELECT: - IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); - if (iarg > AUDIO_STEREO_SWAPPED) - return -EINVAL; -- itv->audio_bilingual_mode = iarg; -- ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); -- return 0; -+ return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg + 1); - - default: - return -EINVAL; -@@ -1800,6 +1784,7 @@ static long ivtv_default(struct file *fi - - if (!valid_prio) { - switch (cmd) { -+ case IVTV_IOC_PASSTHROUGH_MODE: - case VIDEO_PLAY: - case VIDEO_STOP: - case VIDEO_FREEZE: -@@ -1825,6 +1810,7 @@ static long ivtv_default(struct file *fi - } - - case IVTV_IOC_DMA_FRAME: -+ case IVTV_IOC_PASSTHROUGH_MODE: - case VIDEO_GET_PTS: - case VIDEO_GET_FRAME_COUNT: - case VIDEO_GET_EVENT: -@@ -1889,6 +1875,8 @@ static const struct v4l2_ioctl_ops ivtv_ - .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap, - .vidioc_encoder_cmd = ivtv_encoder_cmd, - .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd, -+ .vidioc_decoder_cmd = ivtv_decoder_cmd, -+ .vidioc_try_decoder_cmd = ivtv_try_decoder_cmd, - .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out, - .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap, - .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap, -Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-streams.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-streams.c -+++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-streams.c -@@ -78,60 +78,73 @@ static struct { - int num_offset; - int dma, pio; - enum v4l2_buf_type buf_type; -+ u32 v4l2_caps; - const struct v4l2_file_operations *fops; - } ivtv_stream_info[] = { - { /* IVTV_ENC_STREAM_TYPE_MPG */ - "encoder MPG", - VFL_TYPE_GRABBER, 0, - PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, -+ V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | -+ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, - &ivtv_v4l2_enc_fops - }, - { /* IVTV_ENC_STREAM_TYPE_YUV */ - "encoder YUV", - VFL_TYPE_GRABBER, IVTV_V4L2_ENC_YUV_OFFSET, - PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, -+ V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | -+ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, - &ivtv_v4l2_enc_fops - }, - { /* IVTV_ENC_STREAM_TYPE_VBI */ - "encoder VBI", - VFL_TYPE_VBI, 0, - PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VBI_CAPTURE, -+ V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_TUNER | -+ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, - &ivtv_v4l2_enc_fops - }, - { /* IVTV_ENC_STREAM_TYPE_PCM */ - "encoder PCM", - VFL_TYPE_GRABBER, IVTV_V4L2_ENC_PCM_OFFSET, - PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_PRIVATE, -+ V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, - &ivtv_v4l2_enc_fops - }, - { /* IVTV_ENC_STREAM_TYPE_RAD */ - "encoder radio", - VFL_TYPE_RADIO, 0, - PCI_DMA_NONE, 1, V4L2_BUF_TYPE_PRIVATE, -+ V4L2_CAP_RADIO | V4L2_CAP_TUNER, - &ivtv_v4l2_enc_fops - }, - { /* IVTV_DEC_STREAM_TYPE_MPG */ - "decoder MPG", - VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET, - PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, -+ V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, - &ivtv_v4l2_dec_fops - }, - { /* IVTV_DEC_STREAM_TYPE_VBI */ - "decoder VBI", - VFL_TYPE_VBI, IVTV_V4L2_DEC_VBI_OFFSET, - PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_CAPTURE, -+ V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_READWRITE, - &ivtv_v4l2_enc_fops - }, - { /* IVTV_DEC_STREAM_TYPE_VOUT */ - "decoder VOUT", - VFL_TYPE_VBI, IVTV_V4L2_DEC_VOUT_OFFSET, - PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_OUTPUT, -+ V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, - &ivtv_v4l2_dec_fops - }, - { /* IVTV_DEC_STREAM_TYPE_YUV */ - "decoder YUV", - VFL_TYPE_GRABBER, IVTV_V4L2_DEC_YUV_OFFSET, - PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, -+ V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, - &ivtv_v4l2_dec_fops - } - }; -@@ -149,6 +162,7 @@ static void ivtv_stream_init(struct ivtv - s->itv = itv; - s->type = type; - s->name = ivtv_stream_info[type].name; -+ s->caps = ivtv_stream_info[type].v4l2_caps; - - if (ivtv_stream_info[type].pio) - s->dma = PCI_DMA_NONE; -@@ -209,8 +223,8 @@ static int ivtv_prep_dev(struct ivtv *it - - s->vdev->num = num; - s->vdev->v4l2_dev = &itv->v4l2_dev; -- s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler; - s->vdev->fops = ivtv_stream_info[type].fops; -+ s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler; - s->vdev->release = video_device_release; - s->vdev->tvnorms = V4L2_STD_ALL; - s->vdev->lock = &itv->serialize_lock; -@@ -891,7 +905,7 @@ int ivtv_stop_v4l2_decode_stream(struct - IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags); - - /* Stop Decoder */ -- if (!(flags & VIDEO_CMD_STOP_IMMEDIATELY) || pts) { -+ if (!(flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) || pts) { - u32 tmp = 0; - - /* Wait until the decoder is no longer running */ -@@ -911,7 +925,7 @@ int ivtv_stop_v4l2_decode_stream(struct - break; - } - } -- ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & VIDEO_CMD_STOP_TO_BLACK, 0, 0); -+ ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & V4L2_DEC_CMD_STOP_TO_BLACK, 0, 0); - - /* turn off notification of dual/stereo mode change */ - ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_DEC_AUD_MODE_CHG, -1); -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/it913x.c -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/it913x.c -@@ -64,6 +64,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr - struct it913x_state { - u8 id; - struct ite_config it913x_config; -+ u8 pid_filter_onoff; - }; - - struct ite_config it913x_config; -@@ -237,12 +238,27 @@ static int it913x_read_reg(struct usb_de - - static u32 it913x_query(struct usb_device *udev, u8 pro) - { -- int ret; -+ int ret, i; - u8 data[4]; -- ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ, -- 0x1222, 0, &data[0], 3); -+ u8 ver; -+ -+ for (i = 0; i < 5; i++) { -+ ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ, -+ 0x1222, 0, &data[0], 3); -+ ver = data[0]; -+ if (ver > 0 && ver < 3) -+ break; -+ msleep(100); -+ } - -- it913x_config.chip_ver = data[0]; -+ if (ver < 1 || ver > 2) { -+ info("Failed to identify chip version applying 1"); -+ it913x_config.chip_ver = 0x1; -+ it913x_config.chip_type = 0x9135; -+ return 0; -+ } -+ -+ it913x_config.chip_ver = ver; - it913x_config.chip_type = (u16)(data[2] << 8) + data[1]; - - info("Chip Version=%02x Chip Type=%04x", it913x_config.chip_ver, -@@ -259,15 +275,16 @@ static u32 it913x_query(struct usb_devic - - static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) - { -+ struct it913x_state *st = adap->dev->priv; - struct usb_device *udev = adap->dev->udev; - int ret; - u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; - -- if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) -- return -EAGAIN; -+ mutex_lock(&adap->dev->i2c_mutex); -+ - deb_info(1, "PID_C (%02x)", onoff); - -- ret = it913x_wr_reg(udev, pro, PID_EN, onoff); -+ ret = it913x_wr_reg(udev, pro, PID_EN, st->pid_filter_onoff); - - mutex_unlock(&adap->dev->i2c_mutex); - return ret; -@@ -276,12 +293,13 @@ static int it913x_pid_filter_ctrl(struct - static int it913x_pid_filter(struct dvb_usb_adapter *adap, - int index, u16 pid, int onoff) - { -+ struct it913x_state *st = adap->dev->priv; - struct usb_device *udev = adap->dev->udev; - int ret; - u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; - -- if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) -- return -EAGAIN; -+ mutex_lock(&adap->dev->i2c_mutex); -+ - deb_info(1, "PID_F (%02x)", onoff); - - ret = it913x_wr_reg(udev, pro, PID_LSB, (u8)(pid & 0xff)); -@@ -292,6 +310,13 @@ static int it913x_pid_filter(struct dvb_ - - ret |= it913x_wr_reg(udev, pro, PID_INX, (u8)(index & 0x1f)); - -+ if (udev->speed == USB_SPEED_HIGH && pid == 0x2000) { -+ ret |= it913x_wr_reg(udev, pro, PID_EN, !onoff); -+ st->pid_filter_onoff = !onoff; -+ } else -+ st->pid_filter_onoff = -+ adap->fe_adap[adap->active_fe].pid_filtering; -+ - mutex_unlock(&adap->dev->i2c_mutex); - return 0; - } -@@ -316,8 +341,8 @@ static int it913x_i2c_xfer(struct i2c_ad - int ret; - u32 reg; - u8 pro; -- if (mutex_lock_interruptible(&d->i2c_mutex) < 0) -- return -EAGAIN; -+ -+ mutex_lock(&d->i2c_mutex); - - debug_data_snipet(1, "Message out", msg[0].buf); - deb_info(2, "num of messages %d address %02x", num, msg[0].addr); -@@ -358,8 +383,7 @@ static int it913x_rc_query(struct dvb_us - int ret; - u32 key; - /* Avoid conflict with frontends*/ -- if (mutex_lock_interruptible(&d->i2c_mutex) < 0) -- return -EAGAIN; -+ mutex_lock(&d->i2c_mutex); - - ret = it913x_io(d->udev, READ_LONG, PRO_LINK, CMD_IR_GET, - 0, 0, &ibuf[0], sizeof(ibuf)); -@@ -388,19 +412,12 @@ static int ite_firmware_select(struct us - { - int sw; - /* auto switch */ -- if (le16_to_cpu(udev->descriptor.idProduct) == -- USB_PID_ITETECH_IT9135) -- sw = IT9135_V1_FW; -- else if (le16_to_cpu(udev->descriptor.idProduct) == -- USB_PID_ITETECH_IT9135_9005) -+ if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_KWORLD_2) -+ sw = IT9137_FW; -+ else if (it913x_config.chip_ver == 1) - sw = IT9135_V1_FW; -- else if (le16_to_cpu(udev->descriptor.idProduct) == -- USB_PID_ITETECH_IT9135_9006) { -+ else - sw = IT9135_V2_FW; -- if (it913x_config.tuner_id_0 == 0) -- it913x_config.tuner_id_0 = IT9135_60; -- } else -- sw = IT9137_FW; - - /* force switch */ - if (dvb_usb_it913x_firmware != IT9135_AUTO) -@@ -410,41 +427,103 @@ static int ite_firmware_select(struct us - case IT9135_V1_FW: - it913x_config.firmware_ver = 1; - it913x_config.adc_x2 = 1; -+ it913x_config.read_slevel = false; - props->firmware = fw_it9135_v1; - break; - case IT9135_V2_FW: - it913x_config.firmware_ver = 1; - it913x_config.adc_x2 = 1; -+ it913x_config.read_slevel = false; - props->firmware = fw_it9135_v2; -+ switch (it913x_config.tuner_id_0) { -+ case IT9135_61: -+ case IT9135_62: -+ break; -+ default: -+ info("Unknown tuner ID applying default 0x60"); -+ case IT9135_60: -+ it913x_config.tuner_id_0 = IT9135_60; -+ } - break; - case IT9137_FW: - default: - it913x_config.firmware_ver = 0; - it913x_config.adc_x2 = 0; -+ it913x_config.read_slevel = true; - props->firmware = fw_it9137; - } - - return 0; - } - -+static void it913x_select_remote(struct usb_device *udev, -+ struct dvb_usb_device_properties *props) -+{ -+ switch (le16_to_cpu(udev->descriptor.idProduct)) { -+ case USB_PID_ITETECH_IT9135_9005: -+ props->rc.core.rc_codes = RC_MAP_IT913X_V2; -+ return; -+ default: -+ props->rc.core.rc_codes = RC_MAP_IT913X_V1; -+ } -+ return; -+} -+ - #define TS_MPEG_PKT_SIZE 188 - #define EP_LOW 21 - #define TS_BUFFER_SIZE_PID (EP_LOW*TS_MPEG_PKT_SIZE) - #define EP_HIGH 348 - #define TS_BUFFER_SIZE_MAX (EP_HIGH*TS_MPEG_PKT_SIZE) - --static int it913x_identify_state(struct usb_device *udev, -- struct dvb_usb_device_properties *props, -- struct dvb_usb_device_description **desc, -- int *cold) -+static int it913x_select_config(struct usb_device *udev, -+ struct dvb_usb_device_properties *props) - { -- int ret = 0, firm_no; -- u8 reg, remote; -+ int ret = 0, reg; -+ bool proprietary_ir = false; - -- firm_no = it913x_return_status(udev); -+ if (it913x_config.chip_ver == 0x02 -+ && it913x_config.chip_type == 0x9135) -+ reg = it913x_read_reg(udev, 0x461d); -+ else -+ reg = it913x_read_reg(udev, 0x461b); - -- /* checnk for dual mode */ -- it913x_config.dual_mode = it913x_read_reg(udev, 0x49c5); -+ if (reg < 0) -+ return reg; -+ -+ if (reg == 0) { -+ it913x_config.dual_mode = 0; -+ it913x_config.tuner_id_0 = IT9135_38; -+ proprietary_ir = true; -+ } else { -+ /* TS mode */ -+ reg = it913x_read_reg(udev, 0x49c5); -+ if (reg < 0) -+ return reg; -+ it913x_config.dual_mode = reg; -+ -+ /* IR mode type */ -+ reg = it913x_read_reg(udev, 0x49ac); -+ if (reg < 0) -+ return reg; -+ if (reg == 5) { -+ info("Remote propriety (raw) mode"); -+ proprietary_ir = true; -+ } else if (reg == 1) { -+ info("Remote HID mode NOT SUPPORTED"); -+ proprietary_ir = false; -+ props->rc.core.rc_codes = NULL; -+ } else -+ props->rc.core.rc_codes = NULL; -+ -+ /* Tuner_id */ -+ reg = it913x_read_reg(udev, 0x49d0); -+ if (reg < 0) -+ return reg; -+ it913x_config.tuner_id_0 = reg; -+ } -+ -+ if (proprietary_ir) -+ it913x_select_remote(udev, props); - - if (udev->speed != USB_SPEED_HIGH) { - props->adapter[0].fe[0].pid_filter_count = 5; -@@ -459,17 +538,6 @@ static int it913x_identify_state(struct - if(props->adapter[0].fe[0].pid_filter_count == 5) - props->adapter[0].fe[0].pid_filter_count = 31; - -- /* TODO different remotes */ -- remote = it913x_read_reg(udev, 0x49ac); /* Remote */ -- if (remote == 0) -- props->rc.core.rc_codes = NULL; -- -- /* TODO at the moment tuner_id is always assigned to 0x38 */ -- it913x_config.tuner_id_0 = it913x_read_reg(udev, 0x49d0); -- -- info("Dual mode=%x Remote=%x Tuner Type=%x", it913x_config.dual_mode -- , remote, it913x_config.tuner_id_0); -- - /* Select Stream Buffer Size and pid filter option*/ - if (pid_filter) { - props->adapter[0].fe[0].stream.u.bulk.buffersize = -@@ -490,8 +558,29 @@ static int it913x_identify_state(struct - } else - props->num_adapters = 1; - -+ info("Dual mode=%x Tuner Type=%x", it913x_config.dual_mode, -+ it913x_config.tuner_id_0); -+ - ret = ite_firmware_select(udev, props); - -+ return ret; -+} -+ -+static int it913x_identify_state(struct usb_device *udev, -+ struct dvb_usb_device_properties *props, -+ struct dvb_usb_device_description **desc, -+ int *cold) -+{ -+ int ret = 0, firm_no; -+ u8 reg; -+ -+ firm_no = it913x_return_status(udev); -+ -+ /* Read and select config */ -+ ret = it913x_select_config(udev, props); -+ if (ret < 0) -+ return ret; -+ - if (firm_no > 0) { - *cold = 0; - return 0; -@@ -538,18 +627,22 @@ static int it913x_identify_state(struct - - static int it913x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) - { -+ struct it913x_state *st = adap->dev->priv; - int ret = 0; - u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; - -- if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) -- return -EAGAIN; - deb_info(1, "STM (%02x)", onoff); - -- if (!onoff) -+ if (!onoff) { -+ mutex_lock(&adap->dev->i2c_mutex); -+ - ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1); - -+ mutex_unlock(&adap->dev->i2c_mutex); -+ st->pid_filter_onoff = -+ adap->fe_adap[adap->active_fe].pid_filtering; - -- mutex_unlock(&adap->dev->i2c_mutex); -+ } - - return ret; - } -@@ -582,30 +675,41 @@ static int it913x_download_firmware(stru - if ((packet_size > min_pkt) || (i == fw->size)) { - fw_data = (u8 *)(fw->data + pos); - pos += packet_size; -- if (packet_size > 0) -- ret |= it913x_io(udev, WRITE_DATA, -+ if (packet_size > 0) { -+ ret = it913x_io(udev, WRITE_DATA, - DEV_0, CMD_SCATTER_WRITE, 0, - 0, fw_data, packet_size); -+ if (ret < 0) -+ break; -+ } - udelay(1000); - } - } - i++; - } - -- ret |= it913x_io(udev, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0); -- -- msleep(100); -- - if (ret < 0) -- info("FRM Firmware Download Failed (%04x)" , ret); -+ info("FRM Firmware Download Failed (%d)" , ret); - else - info("FRM Firmware Download Completed - Resetting Device"); - -- ret |= it913x_return_status(udev); -+ msleep(30); -+ -+ ret = it913x_io(udev, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0); -+ if (ret < 0) -+ info("FRM Device not responding to reboot"); -+ -+ ret = it913x_return_status(udev); -+ if (ret == 0) { -+ info("FRM Failed to reboot device"); -+ return -ENODEV; -+ } - - msleep(30); - -- ret |= it913x_wr_reg(udev, DEV_0, I2C_CLK, I2C_CLK_400); -+ ret = it913x_wr_reg(udev, DEV_0, I2C_CLK, I2C_CLK_400); -+ -+ msleep(30); - - /* Tuner function */ - if (it913x_config.dual_mode) -@@ -789,7 +893,7 @@ static struct dvb_usb_device_properties - .rc_query = it913x_rc_query, - .rc_interval = IT913X_POLL, - .allowed_protos = RC_TYPE_NEC, -- .rc_codes = RC_MAP_MSI_DIGIVOX_III, -+ .rc_codes = RC_MAP_IT913X_V1, - }, - .i2c_algo = &it913x_i2c_algo, - .num_device_descs = 5, -@@ -823,5 +927,5 @@ module_usb_driver(it913x_driver); - - MODULE_AUTHOR("Malcolm Priestley "); - MODULE_DESCRIPTION("it913x USB 2 Driver"); --MODULE_VERSION("1.22"); -+MODULE_VERSION("1.28"); - MODULE_LICENSE("GPL"); -Index: linux-3.3.x86_64/drivers/base/driver.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/base/driver.c -+++ linux-3.3.x86_64/drivers/base/driver.c -@@ -234,7 +234,6 @@ int driver_register(struct device_driver - - other = driver_find(drv->name, drv->bus); - if (other) { -- put_driver(other); - printk(KERN_ERR "Error: Driver '%s' is already registered, " - "aborting...\n", drv->name); - return -EBUSY; -@@ -275,7 +274,9 @@ EXPORT_SYMBOL_GPL(driver_unregister); - * Call kset_find_obj() to iterate over list of drivers on - * a bus to find driver by name. Return driver if found. - * -- * Note that kset_find_obj increments driver's reference count. -+ * This routine provides no locking to prevent the driver it returns -+ * from being unregistered or unloaded while the caller is using it. -+ * The caller is responsible for preventing this. - */ - struct device_driver *driver_find(const char *name, struct bus_type *bus) - { -@@ -283,6 +284,8 @@ struct device_driver *driver_find(const - struct driver_private *priv; - - if (k) { -+ /* Drop reference added by kset_find_obj() */ -+ kobject_put(k); - priv = to_driver(k); - return priv->driver; - } -Index: linux-3.3.x86_64/drivers/input/gameport/gameport.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/input/gameport/gameport.c -+++ linux-3.3.x86_64/drivers/input/gameport/gameport.c -@@ -449,7 +449,6 @@ static ssize_t gameport_rebind_driver(st - } else if ((drv = driver_find(buf, &gameport_bus)) != NULL) { - gameport_disconnect_port(gameport); - error = gameport_bind_driver(gameport, to_gameport_driver(drv)); -- put_driver(drv); - } else { - error = -EINVAL; - } -Index: linux-3.3.x86_64/drivers/input/serio/serio.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/input/serio/serio.c -+++ linux-3.3.x86_64/drivers/input/serio/serio.c -@@ -441,7 +441,6 @@ static ssize_t serio_rebind_driver(struc - } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { - serio_disconnect_port(serio); - error = serio_bind_driver(serio, to_serio_driver(drv)); -- put_driver(drv); - serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); - } else { - error = -EINVAL; -Index: linux-3.3.x86_64/drivers/media/video/cx18/cx18-alsa-main.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/cx18/cx18-alsa-main.c -+++ linux-3.3.x86_64/drivers/media/video/cx18/cx18-alsa-main.c -@@ -285,7 +285,6 @@ static void __exit cx18_alsa_exit(void) - - drv = driver_find("cx18", &pci_bus_type); - ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback); -- put_driver(drv); - - cx18_ext_init = NULL; - printk(KERN_INFO "cx18-alsa: module unload complete\n"); -Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtvfb.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtvfb.c -+++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtvfb.c -@@ -1293,7 +1293,6 @@ static int __init ivtvfb_init(void) - - drv = driver_find("ivtv", &pci_bus_type); - err = driver_for_each_device(drv, NULL, ®istered, ivtvfb_callback_init); -- put_driver(drv); - if (!registered) { - printk(KERN_ERR "ivtvfb: no cards found\n"); - return -ENODEV; -@@ -1310,7 +1309,6 @@ static void ivtvfb_cleanup(void) - - drv = driver_find("ivtv", &pci_bus_type); - err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup); -- put_driver(drv); - } - - module_init(ivtvfb_init); -Index: linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-mdevice.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-fimc/fimc-mdevice.c -+++ linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-mdevice.c -@@ -344,16 +344,13 @@ static int fimc_md_register_platform_ent - return -ENODEV; - ret = driver_for_each_device(driver, NULL, fmd, - fimc_register_callback); -- put_driver(driver); - if (ret) - return ret; - - driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type); -- if (driver) { -+ if (driver) - ret = driver_for_each_device(driver, NULL, fmd, - csis_register_callback); -- put_driver(driver); -- } - return ret; - } - -@@ -753,7 +750,7 @@ static int __devinit fimc_md_probe(struc - struct fimc_md *fmd; - int ret; - -- fmd = kzalloc(sizeof(struct fimc_md), GFP_KERNEL); -+ fmd = devm_kzalloc(&pdev->dev, sizeof(*fmd), GFP_KERNEL); - if (!fmd) - return -ENOMEM; - -@@ -774,7 +771,7 @@ static int __devinit fimc_md_probe(struc - ret = v4l2_device_register(&pdev->dev, &fmd->v4l2_dev); - if (ret < 0) { - v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret); -- goto err1; -+ return ret; - } - ret = media_device_register(&fmd->media_dev); - if (ret < 0) { -@@ -816,8 +813,6 @@ err3: - fimc_md_unregister_entities(fmd); - err2: - v4l2_device_unregister(&fmd->v4l2_dev); --err1: -- kfree(fmd); - return ret; - } - -@@ -831,7 +826,6 @@ static int __devexit fimc_md_remove(stru - fimc_md_unregister_entities(fmd); - media_device_unregister(&fmd->media_dev); - fimc_md_put_clocks(fmd); -- kfree(fmd); - return 0; - } - -Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/mixer_video.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/mixer_video.c -+++ linux-3.3.x86_64/drivers/media/video/s5p-tv/mixer_video.c -@@ -58,7 +58,6 @@ static struct v4l2_subdev *find_and_regi - } - - done: -- put_driver(drv); - return sd; - } - -Index: linux-3.3.x86_64/drivers/s390/net/smsgiucv_app.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/s390/net/smsgiucv_app.c -+++ linux-3.3.x86_64/drivers/s390/net/smsgiucv_app.c -@@ -168,7 +168,7 @@ static int __init smsgiucv_app_init(void - rc = dev_set_name(smsg_app_dev, KMSG_COMPONENT); - if (rc) { - kfree(smsg_app_dev); -- goto fail_put_driver; -+ goto fail; - } - smsg_app_dev->bus = &iucv_bus; - smsg_app_dev->parent = iucv_root; -@@ -177,7 +177,7 @@ static int __init smsgiucv_app_init(void - rc = device_register(smsg_app_dev); - if (rc) { - put_device(smsg_app_dev); -- goto fail_put_driver; -+ goto fail; - } - - /* convert sender to uppercase characters */ -@@ -191,12 +191,11 @@ static int __init smsgiucv_app_init(void - rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback); - if (rc) { - device_unregister(smsg_app_dev); -- goto fail_put_driver; -+ goto fail; - } - - rc = 0; --fail_put_driver: -- put_driver(smsgiucv_drv); -+fail: - return rc; - } - module_init(smsgiucv_app_init); -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/anysee.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/anysee.c -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/anysee.c -@@ -58,7 +58,7 @@ static int anysee_ctrl_msg(struct dvb_us - u8 *rbuf, u8 rlen) - { - struct anysee_state *state = d->priv; -- int act_len, ret; -+ int act_len, ret, i; - u8 buf[64]; - - memcpy(&buf[0], sbuf, slen); -@@ -73,26 +73,52 @@ static int anysee_ctrl_msg(struct dvb_us - /* We need receive one message more after dvb_usb_generic_rw due - to weird transaction flow, which is 1 x send + 2 x receive. */ - ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0); -- if (!ret) { -+ if (ret) -+ goto error_unlock; -+ -+ /* TODO FIXME: dvb_usb_generic_rw() fails rarely with error code -32 -+ * (EPIPE, Broken pipe). Function supports currently msleep() as a -+ * parameter but I would not like to use it, since according to -+ * Documentation/timers/timers-howto.txt it should not be used such -+ * short, under < 20ms, sleeps. Repeating failed message would be -+ * better choice as not to add unwanted delays... -+ * Fixing that correctly is one of those or both; -+ * 1) use repeat if possible -+ * 2) add suitable delay -+ */ -+ -+ /* get answer, retry few times if error returned */ -+ for (i = 0; i < 3; i++) { - /* receive 2nd answer */ - ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, - d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf), - &act_len, 2000); -- if (ret) -- err("%s: recv bulk message failed: %d", __func__, ret); -- else { -+ -+ if (ret) { -+ deb_info("%s: recv bulk message failed: %d", -+ __func__, ret); -+ } else { - deb_xfer("<<< "); - debug_dump(buf, rlen, deb_xfer); - - if (buf[63] != 0x4f) - deb_info("%s: cmd failed\n", __func__); -+ -+ break; - } - } - -+ if (ret) { -+ /* all retries failed, it is fatal */ -+ err("%s: recv bulk message failed: %d", __func__, ret); -+ goto error_unlock; -+ } -+ - /* read request, copy returned data to return buf */ -- if (!ret && rbuf && rlen) -+ if (rbuf && rlen) - memcpy(rbuf, buf, rlen); - -+error_unlock: - mutex_unlock(&anysee_usb_mutex); - - return ret; -Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/hdmi_drv.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/hdmi_drv.c -+++ linux-3.3.x86_64/drivers/media/video/s5p-tv/hdmi_drv.c -@@ -30,6 +30,7 @@ - #include - #include - -+#include - #include - #include - #include -@@ -66,6 +67,8 @@ struct hdmi_device { - struct v4l2_device v4l2_dev; - /** subdev of HDMIPHY interface */ - struct v4l2_subdev *phy_sd; -+ /** subdev of MHL interface */ -+ struct v4l2_subdev *mhl_sd; - /** configuration of current graphic mode */ - const struct hdmi_preset_conf *cur_conf; - /** current preset */ -@@ -74,10 +77,6 @@ struct hdmi_device { - struct hdmi_resources res; - }; - --struct hdmi_driver_data { -- int hdmiphy_bus; --}; -- - struct hdmi_tg_regs { - u8 cmd; - u8 h_fsz_l; -@@ -129,23 +128,11 @@ struct hdmi_preset_conf { - struct v4l2_mbus_framefmt mbus_fmt; - }; - --/* I2C module and id for HDMIPHY */ --static struct i2c_board_info hdmiphy_info = { -- I2C_BOARD_INFO("hdmiphy", 0x38), --}; -- --static struct hdmi_driver_data hdmi_driver_data[] = { -- { .hdmiphy_bus = 3 }, -- { .hdmiphy_bus = 8 }, --}; -- - static struct platform_device_id hdmi_driver_types[] = { - { - .name = "s5pv210-hdmi", -- .driver_data = (unsigned long)&hdmi_driver_data[0], - }, { - .name = "exynos4-hdmi", -- .driver_data = (unsigned long)&hdmi_driver_data[1], - }, { - /* end node */ - } -@@ -587,7 +574,15 @@ static int hdmi_streamon(struct hdmi_dev - if (tries == 0) { - dev_err(dev, "hdmiphy's pll could not reach steady state.\n"); - v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); -- hdmi_dumpregs(hdev, "s_stream"); -+ hdmi_dumpregs(hdev, "hdmiphy - s_stream"); -+ return -EIO; -+ } -+ -+ /* starting MHL */ -+ ret = v4l2_subdev_call(hdev->mhl_sd, video, s_stream, 1); -+ if (hdev->mhl_sd && ret) { -+ v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); -+ hdmi_dumpregs(hdev, "mhl - s_stream"); - return -EIO; - } - -@@ -618,6 +613,7 @@ static int hdmi_streamoff(struct hdmi_de - clk_set_parent(res->sclk_hdmi, res->sclk_pixel); - clk_enable(res->sclk_hdmi); - -+ v4l2_subdev_call(hdev->mhl_sd, video, s_stream, 0); - v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); - - hdmi_dumpregs(hdev, "streamoff"); -@@ -739,6 +735,7 @@ static int hdmi_runtime_suspend(struct d - struct hdmi_device *hdev = sd_to_hdmi_dev(sd); - - dev_dbg(dev, "%s\n", __func__); -+ v4l2_subdev_call(hdev->mhl_sd, core, s_power, 0); - hdmi_resource_poweroff(&hdev->res); - return 0; - } -@@ -757,6 +754,11 @@ static int hdmi_runtime_resume(struct de - if (ret) - goto fail; - -+ /* starting MHL */ -+ ret = v4l2_subdev_call(hdev->mhl_sd, core, s_power, 1); -+ if (hdev->mhl_sd && ret) -+ goto fail; -+ - dev_dbg(dev, "poweron succeed\n"); - - return 0; -@@ -867,15 +869,21 @@ static int __devinit hdmi_probe(struct p - { - struct device *dev = &pdev->dev; - struct resource *res; -- struct i2c_adapter *phy_adapter; -+ struct i2c_adapter *adapter; - struct v4l2_subdev *sd; - struct hdmi_device *hdmi_dev = NULL; -- struct hdmi_driver_data *drv_data; -+ struct s5p_hdmi_platform_data *pdata = dev->platform_data; - int ret; - - dev_dbg(dev, "probe start\n"); - -- hdmi_dev = kzalloc(sizeof(*hdmi_dev), GFP_KERNEL); -+ if (!pdata) { -+ dev_err(dev, "platform data is missing\n"); -+ ret = -ENODEV; -+ goto fail; -+ } -+ -+ hdmi_dev = devm_kzalloc(&pdev->dev, sizeof(*hdmi_dev), GFP_KERNEL); - if (!hdmi_dev) { - dev_err(dev, "out of memory\n"); - ret = -ENOMEM; -@@ -886,7 +894,7 @@ static int __devinit hdmi_probe(struct p - - ret = hdmi_resources_init(hdmi_dev); - if (ret) -- goto fail_hdev; -+ goto fail; - - /* mapping HDMI registers */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -@@ -896,24 +904,26 @@ static int __devinit hdmi_probe(struct p - goto fail_init; - } - -- hdmi_dev->regs = ioremap(res->start, resource_size(res)); -+ hdmi_dev->regs = devm_ioremap(&pdev->dev, res->start, -+ resource_size(res)); - if (hdmi_dev->regs == NULL) { - dev_err(dev, "register mapping failed.\n"); - ret = -ENXIO; -- goto fail_hdev; -+ goto fail_init; - } - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (res == NULL) { - dev_err(dev, "get interrupt resource failed.\n"); - ret = -ENXIO; -- goto fail_regs; -+ goto fail_init; - } - -- ret = request_irq(res->start, hdmi_irq_handler, 0, "hdmi", hdmi_dev); -+ ret = devm_request_irq(&pdev->dev, res->start, hdmi_irq_handler, 0, -+ "hdmi", hdmi_dev); - if (ret) { - dev_err(dev, "request interrupt failed.\n"); -- goto fail_regs; -+ goto fail_init; - } - hdmi_dev->irq = res->start; - -@@ -924,28 +934,54 @@ static int __devinit hdmi_probe(struct p - ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev); - if (ret) { - dev_err(dev, "could not register v4l2 device.\n"); -- goto fail_irq; -+ goto fail_init; - } - -- drv_data = (struct hdmi_driver_data *) -- platform_get_device_id(pdev)->driver_data; -- phy_adapter = i2c_get_adapter(drv_data->hdmiphy_bus); -- if (phy_adapter == NULL) { -- dev_err(dev, "adapter request failed\n"); -+ /* testing if hdmiphy info is present */ -+ if (!pdata->hdmiphy_info) { -+ dev_err(dev, "hdmiphy info is missing in platform data\n"); -+ ret = -ENXIO; -+ goto fail_vdev; -+ } -+ -+ adapter = i2c_get_adapter(pdata->hdmiphy_bus); -+ if (adapter == NULL) { -+ dev_err(dev, "hdmiphy adapter request failed\n"); - ret = -ENXIO; - goto fail_vdev; - } - - hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev, -- phy_adapter, &hdmiphy_info, NULL); -+ adapter, pdata->hdmiphy_info, NULL); - /* on failure or not adapter is no longer useful */ -- i2c_put_adapter(phy_adapter); -+ i2c_put_adapter(adapter); - if (hdmi_dev->phy_sd == NULL) { - dev_err(dev, "missing subdev for hdmiphy\n"); - ret = -ENODEV; - goto fail_vdev; - } - -+ /* initialization of MHL interface if present */ -+ if (pdata->mhl_info) { -+ adapter = i2c_get_adapter(pdata->mhl_bus); -+ if (adapter == NULL) { -+ dev_err(dev, "MHL adapter request failed\n"); -+ ret = -ENXIO; -+ goto fail_vdev; -+ } -+ -+ hdmi_dev->mhl_sd = v4l2_i2c_new_subdev_board( -+ &hdmi_dev->v4l2_dev, adapter, -+ pdata->mhl_info, NULL); -+ /* on failure or not adapter is no longer useful */ -+ i2c_put_adapter(adapter); -+ if (hdmi_dev->mhl_sd == NULL) { -+ dev_err(dev, "missing subdev for MHL\n"); -+ ret = -ENODEV; -+ goto fail_vdev; -+ } -+ } -+ - clk_enable(hdmi_dev->res.hdmi); - - pm_runtime_enable(dev); -@@ -969,18 +1005,9 @@ static int __devinit hdmi_probe(struct p - fail_vdev: - v4l2_device_unregister(&hdmi_dev->v4l2_dev); - --fail_irq: -- free_irq(hdmi_dev->irq, hdmi_dev); -- --fail_regs: -- iounmap(hdmi_dev->regs); -- - fail_init: - hdmi_resources_cleanup(hdmi_dev); - --fail_hdev: -- kfree(hdmi_dev); -- - fail: - dev_err(dev, "probe failed\n"); - return ret; -@@ -996,8 +1023,6 @@ static int __devexit hdmi_remove(struct - clk_disable(hdmi_dev->res.hdmi); - v4l2_device_unregister(&hdmi_dev->v4l2_dev); - disable_irq(hdmi_dev->irq); -- free_irq(hdmi_dev->irq, hdmi_dev); -- iounmap(hdmi_dev->regs); - hdmi_resources_cleanup(hdmi_dev); - kfree(hdmi_dev); - dev_info(dev, "remove sucessful\n"); -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/lmedm04.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/lmedm04.c -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/lmedm04.c -@@ -77,6 +77,7 @@ - #include "stv0299.h" - #include "dvb-pll.h" - #include "z0194a.h" -+#include "m88rs2000.h" - - - -@@ -104,7 +105,7 @@ MODULE_PARM_DESC(firmware, "set default - - static int pid_filter; - module_param_named(pid, pid_filter, int, 0644); --MODULE_PARM_DESC(pid, "set default 0=on 1=off"); -+MODULE_PARM_DESC(pid, "set default 0=default 1=off 2=on"); - - - DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -@@ -113,6 +114,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr - #define TUNER_LG 0x1 - #define TUNER_S7395 0x2 - #define TUNER_S0194 0x3 -+#define TUNER_RS2000 0x4 - - struct lme2510_state { - u8 id; -@@ -121,6 +123,8 @@ struct lme2510_state { - u8 signal_level; - u8 signal_sn; - u8 time_key; -+ u8 last_key; -+ u8 key_timeout; - u8 i2c_talk_onoff; - u8 i2c_gate; - u8 i2c_tuner_gate_w; -@@ -128,6 +132,7 @@ struct lme2510_state { - u8 i2c_tuner_addr; - u8 stream_on; - u8 pid_size; -+ u8 pid_off; - void *buffer; - struct urb *lme_urb; - void *usb_buffer; -@@ -178,14 +183,8 @@ static int lme2510_usb_talk(struct dvb_u - /* the read/write capped at 64 */ - memcpy(buff, wbuf, (wlen < 64) ? wlen : 64); - -- ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01)); -- - ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01); - -- msleep(10); -- -- ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01)); -- - ret |= lme2510_bulk_read(d->udev, buff, (rlen < 64) ? - rlen : 64 , 0x01); - -@@ -199,9 +198,14 @@ static int lme2510_usb_talk(struct dvb_u - - static int lme2510_stream_restart(struct dvb_usb_device *d) - { -- static u8 stream_on[] = LME_ST_ON_W; -+ struct lme2510_state *st = d->priv; -+ u8 all_pids[] = LME_ALL_PIDS; -+ u8 stream_on[] = LME_ST_ON_W; - int ret; -- u8 rbuff[10]; -+ u8 rbuff[1]; -+ if (st->pid_off) -+ ret = lme2510_usb_talk(d, all_pids, sizeof(all_pids), -+ rbuff, sizeof(rbuff)); - /*Restart Stream Command*/ - ret = lme2510_usb_talk(d, stream_on, sizeof(stream_on), - rbuff, sizeof(rbuff)); -@@ -308,6 +312,14 @@ static void lme2510_int_response(struct - ((ibuf[2] & 0x01) << 0x03); - } - break; -+ case TUNER_RS2000: -+ if (ibuf[2] > 0) -+ st->signal_lock = 0xff; -+ else -+ st->signal_lock = 0xf0; -+ st->signal_level = ibuf[4]; -+ st->signal_sn = ibuf[5]; -+ st->time_key = ibuf[7]; - default: - break; - } -@@ -359,19 +371,20 @@ static int lme2510_int_read(struct dvb_u - static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) - { - struct lme2510_state *st = adap->dev->priv; -- static u8 clear_pid_reg[] = LME_CLEAR_PID; -+ static u8 clear_pid_reg[] = LME_ALL_PIDS; - static u8 rbuf[1]; - int ret; - - deb_info(1, "PID Clearing Filter"); - -- ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); -- if (ret < 0) -- return -EAGAIN; -+ mutex_lock(&adap->dev->i2c_mutex); - -- if (!onoff) -+ if (!onoff) { - ret |= lme2510_usb_talk(adap->dev, clear_pid_reg, - sizeof(clear_pid_reg), rbuf, sizeof(rbuf)); -+ st->pid_off = true; -+ } else -+ st->pid_off = false; - - st->pid_size = 0; - -@@ -389,11 +402,9 @@ static int lme2510_pid_filter(struct dvb - pid, index, onoff); - - if (onoff) { -- ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); -- if (ret < 0) -- return -EAGAIN; -- ret |= lme2510_enable_pid(adap->dev, index, pid); -- mutex_unlock(&adap->dev->i2c_mutex); -+ mutex_lock(&adap->dev->i2c_mutex); -+ ret |= lme2510_enable_pid(adap->dev, index, pid); -+ mutex_unlock(&adap->dev->i2c_mutex); - } - - -@@ -425,9 +436,6 @@ static int lme2510_msg(struct dvb_usb_de - int ret = 0; - struct lme2510_state *st = d->priv; - -- if (mutex_lock_interruptible(&d->i2c_mutex) < 0) -- return -EAGAIN; -- - if (st->i2c_talk_onoff == 1) { - - ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); -@@ -456,8 +464,6 @@ static int lme2510_msg(struct dvb_usb_de - st->i2c_talk_onoff = 0; - } - } -- if ((wbuf[3] != 0x6) & (wbuf[3] != 0x5)) -- msleep(5); - } - break; - case TUNER_S0194: -@@ -472,10 +478,12 @@ static int lme2510_msg(struct dvb_usb_de - } - } - break; -+ case TUNER_RS2000: - default: - break; - } - } else { -+ /* TODO rewrite this section */ - switch (st->tuner_config) { - case TUNER_LG: - switch (wbuf[3]) { -@@ -559,6 +567,24 @@ static int lme2510_msg(struct dvb_usb_de - break; - } - break; -+ case TUNER_RS2000: -+ switch (wbuf[3]) { -+ case 0x8c: -+ rbuf[0] = 0x55; -+ rbuf[1] = 0xff; -+ if (st->last_key == st->time_key) { -+ st->key_timeout++; -+ if (st->key_timeout > 5) -+ rbuf[1] = 0; -+ } else -+ st->key_timeout = 0; -+ st->last_key = st->time_key; -+ break; -+ default: -+ lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); -+ st->i2c_talk_onoff = 1; -+ break; -+ } - default: - break; - } -@@ -568,8 +594,6 @@ static int lme2510_msg(struct dvb_usb_de - - } - -- mutex_unlock(&d->i2c_mutex); -- - return ret; - } - -@@ -584,6 +608,8 @@ static int lme2510_i2c_xfer(struct i2c_a - u16 len; - u8 gate = st->i2c_gate; - -+ mutex_lock(&d->i2c_mutex); -+ - if (gate == 0) - gate = 5; - -@@ -622,6 +648,7 @@ static int lme2510_i2c_xfer(struct i2c_a - - if (lme2510_msg(d, obuf, len, ibuf, 64) < 0) { - deb_info(1, "i2c transfer failed."); -+ mutex_unlock(&d->i2c_mutex); - return -EAGAIN; - } - -@@ -634,6 +661,8 @@ static int lme2510_i2c_xfer(struct i2c_a - } - } - } -+ -+ mutex_unlock(&d->i2c_mutex); - return i; - } - -@@ -653,7 +682,7 @@ static int lme2510_identify_state(struct - struct dvb_usb_device_description **desc, - int *cold) - { -- if (pid_filter > 0) -+ if (pid_filter != 2) - props->adapter[0].fe[0].caps &= - ~DVB_USB_ADAP_NEED_PID_FILTERING; - *cold = 0; -@@ -663,7 +692,7 @@ static int lme2510_identify_state(struct - static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) - { - struct lme2510_state *st = adap->dev->priv; -- static u8 clear_reg_3[] = LME_CLEAR_PID; -+ static u8 clear_reg_3[] = LME_ALL_PIDS; - static u8 rbuf[1]; - int ret = 0, rlen = sizeof(rbuf); - -@@ -675,8 +704,7 @@ static int lme2510_streaming_ctrl(struct - else { - deb_info(1, "STM Steam Off"); - /* mutex is here only to avoid collision with I2C */ -- if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) -- return -EAGAIN; -+ mutex_lock(&adap->dev->i2c_mutex); - - ret = lme2510_usb_talk(adap->dev, clear_reg_3, - sizeof(clear_reg_3), rbuf, rlen); -@@ -781,16 +809,18 @@ static int lme_firmware_switch(struct us - const char fw_c_s7395[] = "dvb-usb-lme2510c-s7395.fw"; - const char fw_c_lg[] = "dvb-usb-lme2510c-lg.fw"; - const char fw_c_s0194[] = "dvb-usb-lme2510c-s0194.fw"; -+ const char fw_c_rs2000[] = "dvb-usb-lme2510c-rs2000.fw"; - const char fw_lg[] = "dvb-usb-lme2510-lg.fw"; - const char fw_s0194[] = "dvb-usb-lme2510-s0194.fw"; - const char *fw_lme; -- int ret, cold_fw; -+ int ret = 0, cold_fw; - - cold = (cold > 0) ? (cold & 1) : 0; - - cold_fw = !cold; - -- if (le16_to_cpu(udev->descriptor.idProduct) == 0x1122) { -+ switch (le16_to_cpu(udev->descriptor.idProduct)) { -+ case 0x1122: - switch (dvb_usb_lme2510_firmware) { - default: - dvb_usb_lme2510_firmware = TUNER_S0194; -@@ -813,7 +843,8 @@ static int lme_firmware_switch(struct us - cold_fw = 0; - break; - } -- } else { -+ break; -+ case 0x1120: - switch (dvb_usb_lme2510_firmware) { - default: - dvb_usb_lme2510_firmware = TUNER_S7395; -@@ -842,8 +873,17 @@ static int lme_firmware_switch(struct us - cold_fw = 0; - break; - } -+ break; -+ case 0x22f0: -+ fw_lme = fw_c_rs2000; -+ ret = request_firmware(&fw, fw_lme, &udev->dev); -+ dvb_usb_lme2510_firmware = TUNER_RS2000; -+ break; -+ default: -+ fw_lme = fw_c_s7395; - } - -+ - if (cold_fw) { - info("FRM Loading %s file", fw_lme); - ret = lme2510_download_firmware(udev, fw); -@@ -906,6 +946,29 @@ static struct stv0299_config sharp_z0194 - .set_symbol_rate = sharp_z0194a_set_symbol_rate, - }; - -+static int dm04_rs2000_set_ts_param(struct dvb_frontend *fe, -+ int caller) -+{ -+ struct dvb_usb_adapter *adap = fe->dvb->priv; -+ struct dvb_usb_device *d = adap->dev; -+ struct lme2510_state *st = d->priv; -+ -+ mutex_lock(&d->i2c_mutex); -+ if ((st->i2c_talk_onoff == 1) && (st->stream_on & 1)) { -+ st->i2c_talk_onoff = 0; -+ lme2510_stream_restart(d); -+ } -+ mutex_unlock(&d->i2c_mutex); -+ -+ return 0; -+} -+ -+static struct m88rs2000_config m88rs2000_config = { -+ .demod_addr = 0xd0, -+ .tuner_addr = 0xc0, -+ .set_ts_params = dm04_rs2000_set_ts_param, -+}; -+ - static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, - fe_sec_voltage_t voltage) - { -@@ -915,8 +978,7 @@ static int dm04_lme2510_set_voltage(stru - static u8 rbuf[1]; - int ret = 0, len = 3, rlen = 1; - -- if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) -- return -EAGAIN; -+ mutex_lock(&adap->dev->i2c_mutex); - - switch (voltage) { - case SEC_VOLTAGE_18: -@@ -937,12 +999,31 @@ static int dm04_lme2510_set_voltage(stru - return (ret < 0) ? -ENODEV : 0; - } - -+static int dm04_rs2000_read_signal_strength(struct dvb_frontend *fe, -+ u16 *strength) -+{ -+ struct dvb_usb_adapter *adap = fe->dvb->priv; -+ struct lme2510_state *st = adap->dev->priv; -+ -+ *strength = (u16)((u32)st->signal_level * 0xffff / 0x7f); -+ return 0; -+} -+ -+static int dm04_rs2000_read_snr(struct dvb_frontend *fe, u16 *snr) -+{ -+ struct dvb_usb_adapter *adap = fe->dvb->priv; -+ struct lme2510_state *st = adap->dev->priv; -+ -+ *snr = (u16)((u32)st->signal_sn * 0xffff / 0xff); -+ return 0; -+} -+ - static int lme_name(struct dvb_usb_adapter *adap) - { - struct lme2510_state *st = adap->dev->priv; - const char *desc = adap->dev->desc->name; - char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395", -- " SHARP:BS2F7HZ0194"}; -+ " SHARP:BS2F7HZ0194", " RS2000"}; - char *name = adap->fe_adap[0].fe->ops.info.name; - - strlcpy(name, desc, 128); -@@ -958,60 +1039,82 @@ static int dm04_lme2510_frontend_attach( - int ret = 0; - - st->i2c_talk_onoff = 1; -+ switch (le16_to_cpu(adap->dev->udev->descriptor.idProduct)) { -+ case 0x1122: -+ case 0x1120: -+ st->i2c_gate = 4; -+ adap->fe_adap[0].fe = dvb_attach(tda10086_attach, -+ &tda10086_config, &adap->dev->i2c_adap); -+ if (adap->fe_adap[0].fe) { -+ info("TUN Found Frontend TDA10086"); -+ st->i2c_tuner_gate_w = 4; -+ st->i2c_tuner_gate_r = 4; -+ st->i2c_tuner_addr = 0xc0; -+ st->tuner_config = TUNER_LG; -+ if (dvb_usb_lme2510_firmware != TUNER_LG) { -+ dvb_usb_lme2510_firmware = TUNER_LG; -+ ret = lme_firmware_switch(adap->dev->udev, 1); -+ } -+ break; -+ } - -- st->i2c_gate = 4; -- adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config, -- &adap->dev->i2c_adap); -- -- if (adap->fe_adap[0].fe) { -- info("TUN Found Frontend TDA10086"); -- st->i2c_tuner_gate_w = 4; -- st->i2c_tuner_gate_r = 4; -- st->i2c_tuner_addr = 0xc0; -- st->tuner_config = TUNER_LG; -- if (dvb_usb_lme2510_firmware != TUNER_LG) { -- dvb_usb_lme2510_firmware = TUNER_LG; -- ret = lme_firmware_switch(adap->dev->udev, 1); -+ st->i2c_gate = 4; -+ adap->fe_adap[0].fe = dvb_attach(stv0299_attach, -+ &sharp_z0194_config, &adap->dev->i2c_adap); -+ if (adap->fe_adap[0].fe) { -+ info("FE Found Stv0299"); -+ st->i2c_tuner_gate_w = 4; -+ st->i2c_tuner_gate_r = 5; -+ st->i2c_tuner_addr = 0xc0; -+ st->tuner_config = TUNER_S0194; -+ if (dvb_usb_lme2510_firmware != TUNER_S0194) { -+ dvb_usb_lme2510_firmware = TUNER_S0194; -+ ret = lme_firmware_switch(adap->dev->udev, 1); -+ } -+ break; - } -- goto end; -- } - -- st->i2c_gate = 4; -- adap->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194_config, -+ st->i2c_gate = 5; -+ adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config, - &adap->dev->i2c_adap); -- if (adap->fe_adap[0].fe) { -- info("FE Found Stv0299"); -- st->i2c_tuner_gate_w = 4; -- st->i2c_tuner_gate_r = 5; -- st->i2c_tuner_addr = 0xc0; -- st->tuner_config = TUNER_S0194; -- if (dvb_usb_lme2510_firmware != TUNER_S0194) { -- dvb_usb_lme2510_firmware = TUNER_S0194; -- ret = lme_firmware_switch(adap->dev->udev, 1); -+ -+ if (adap->fe_adap[0].fe) { -+ info("FE Found Stv0288"); -+ st->i2c_tuner_gate_w = 4; -+ st->i2c_tuner_gate_r = 5; -+ st->i2c_tuner_addr = 0xc0; -+ st->tuner_config = TUNER_S7395; -+ if (dvb_usb_lme2510_firmware != TUNER_S7395) { -+ dvb_usb_lme2510_firmware = TUNER_S7395; -+ ret = lme_firmware_switch(adap->dev->udev, 1); -+ } -+ break; - } -- goto end; -- } -+ case 0x22f0: -+ st->i2c_gate = 5; -+ adap->fe_adap[0].fe = dvb_attach(m88rs2000_attach, -+ &m88rs2000_config, &adap->dev->i2c_adap); - -- st->i2c_gate = 5; -- adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config, -- &adap->dev->i2c_adap); -- if (adap->fe_adap[0].fe) { -- info("FE Found Stv0288"); -- st->i2c_tuner_gate_w = 4; -- st->i2c_tuner_gate_r = 5; -- st->i2c_tuner_addr = 0xc0; -- st->tuner_config = TUNER_S7395; -- if (dvb_usb_lme2510_firmware != TUNER_S7395) { -- dvb_usb_lme2510_firmware = TUNER_S7395; -- ret = lme_firmware_switch(adap->dev->udev, 1); -+ if (adap->fe_adap[0].fe) { -+ info("FE Found M88RS2000"); -+ st->i2c_tuner_gate_w = 5; -+ st->i2c_tuner_gate_r = 5; -+ st->i2c_tuner_addr = 0xc0; -+ st->tuner_config = TUNER_RS2000; -+ adap->fe_adap[0].fe->ops.read_signal_strength = -+ dm04_rs2000_read_signal_strength; -+ adap->fe_adap[0].fe->ops.read_snr = -+ dm04_rs2000_read_snr; - } -- } else { -- info("DM04 Not Supported"); -- return -ENODEV; -+ break; - } - -+ if (adap->fe_adap[0].fe == NULL) { -+ info("DM04/QQBOX Not Powered up or not Supported"); -+ return -ENODEV; -+ } - --end: if (ret) { -+ if (ret) { - if (adap->fe_adap[0].fe) { - dvb_frontend_detach(adap->fe_adap[0].fe); - adap->fe_adap[0].fe = NULL; -@@ -1028,7 +1131,7 @@ end: if (ret) { - static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) - { - struct lme2510_state *st = adap->dev->priv; -- char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA"}; -+ char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA", "RS2000"}; - int ret = 0; - - switch (st->tuner_config) { -@@ -1047,6 +1150,9 @@ static int dm04_lme2510_tuner(struct dvb - &adap->dev->i2c_adap, DVB_PLL_OPERA1)) - ret = st->tuner_config; - break; -+ case TUNER_RS2000: -+ ret = st->tuner_config; -+ break; - default: - break; - } -@@ -1054,7 +1160,7 @@ static int dm04_lme2510_tuner(struct dvb - if (ret) - info("TUN Found %s tuner", tun_msg[ret]); - else { -- info("TUN No tuner found --- reseting device"); -+ info("TUN No tuner found --- resetting device"); - lme_coldreset(adap->dev->udev); - return -ENODEV; - } -@@ -1075,10 +1181,9 @@ static int lme2510_powerup(struct dvb_us - static u8 lnb_on[] = LNB_ON; - static u8 lnb_off[] = LNB_OFF; - static u8 rbuf[1]; -- int ret, len = 3, rlen = 1; -+ int ret = 0, len = 3, rlen = 1; - -- if (mutex_lock_interruptible(&d->i2c_mutex) < 0) -- return -EAGAIN; -+ mutex_lock(&d->i2c_mutex); - - if (onoff) - ret = lme2510_usb_talk(d, lnb_on, len, rbuf, rlen); -@@ -1136,6 +1241,7 @@ static int lme2510_probe(struct usb_inte - static struct usb_device_id lme2510_table[] = { - { USB_DEVICE(0x3344, 0x1122) }, /* LME2510 */ - { USB_DEVICE(0x3344, 0x1120) }, /* LME2510C */ -+ { USB_DEVICE(0x3344, 0x22f0) }, /* LME2510C RS2000 */ - {} /* Terminating entry */ - }; - -@@ -1153,7 +1259,7 @@ static struct dvb_usb_device_properties - DVB_USB_ADAP_NEED_PID_FILTERING| - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, - .streaming_ctrl = lme2510_streaming_ctrl, -- .pid_filter_count = 15, -+ .pid_filter_count = 32, - .pid_filter = lme2510_pid_filter, - .pid_filter_ctrl = lme2510_pid_filter_ctrl, - .frontend_attach = dm04_lme2510_frontend_attach, -@@ -1204,7 +1310,7 @@ static struct dvb_usb_device_properties - DVB_USB_ADAP_NEED_PID_FILTERING| - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, - .streaming_ctrl = lme2510_streaming_ctrl, -- .pid_filter_count = 15, -+ .pid_filter_count = 32, - .pid_filter = lme2510_pid_filter, - .pid_filter_ctrl = lme2510_pid_filter_ctrl, - .frontend_attach = dm04_lme2510_frontend_attach, -@@ -1234,11 +1340,14 @@ static struct dvb_usb_device_properties - .identify_state = lme2510_identify_state, - .i2c_algo = &lme2510_i2c_algo, - .generic_bulk_ctrl_endpoint = 0, -- .num_device_descs = 1, -+ .num_device_descs = 2, - .devices = { - { "DM04_LME2510C_DVB-S", - { &lme2510_table[1], NULL }, - }, -+ { "DM04_LME2510C_DVB-S RS2000", -+ { &lme2510_table[2], NULL }, -+ }, - } - }; - -@@ -1295,5 +1404,5 @@ module_usb_driver(lme2510_driver); - - MODULE_AUTHOR("Malcolm Priestley "); - MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); --MODULE_VERSION("1.91"); -+MODULE_VERSION("1.99"); - MODULE_LICENSE("GPL"); -Index: linux-3.3.x86_64/drivers/media/video/ov6650.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ov6650.c -+++ linux-3.3.x86_64/drivers/media/video/ov6650.c -@@ -649,7 +649,7 @@ static int ov6650_s_fmt(struct v4l2_subd - clkrc = CLKRC_24MHz; - } else { - dev_err(&client->dev, -- "unspported input clock, check platform data\n"); -+ "unsupported input clock, check platform data\n"); - return -EINVAL; - } - mclk = sense->master_clock; -@@ -1046,18 +1046,7 @@ static struct i2c_driver ov6650_i2c_driv - .id_table = ov6650_id, - }; - --static int __init ov6650_module_init(void) --{ -- return i2c_add_driver(&ov6650_i2c_driver); --} -- --static void __exit ov6650_module_exit(void) --{ -- i2c_del_driver(&ov6650_i2c_driver); --} -- --module_init(ov6650_module_init); --module_exit(ov6650_module_exit); -+module_i2c_driver(ov6650_i2c_driver); - - MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV6650"); - MODULE_AUTHOR("Janusz Krzysztofik "); -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/tda1004x.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/tda1004x.c -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/tda1004x.c -@@ -1272,7 +1272,7 @@ struct dvb_frontend* tda10045_attach(con - /* allocate memory for the internal state */ - state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL); - if (!state) { -- printk(KERN_ERR "Can't alocate memory for tda10045 state\n"); -+ printk(KERN_ERR "Can't allocate memory for tda10045 state\n"); - return NULL; - } - -@@ -1342,7 +1342,7 @@ struct dvb_frontend* tda10046_attach(con - /* allocate memory for the internal state */ - state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL); - if (!state) { -- printk(KERN_ERR "Can't alocate memory for tda10046 state\n"); -+ printk(KERN_ERR "Can't allocate memory for tda10046 state\n"); - return NULL; - } - -Index: linux-3.3.x86_64/drivers/media/video/davinci/vpif.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/davinci/vpif.h -+++ linux-3.3.x86_64/drivers/media/video/davinci/vpif.h -@@ -18,8 +18,6 @@ - - #include - #include --#include --#include - #include - - /* Maximum channel allowed */ -Index: linux-3.3.x86_64/drivers/media/video/davinci/vpif_display.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/davinci/vpif_display.c -+++ linux-3.3.x86_64/drivers/media/video/davinci/vpif_display.c -@@ -39,8 +39,6 @@ - #include - #include - --#include -- - #include "vpif_display.h" - #include "vpif.h" - -Index: linux-3.3.x86_64/include/media/davinci/vpif_types.h -=================================================================== ---- linux-3.3.x86_64.orig/include/media/davinci/vpif_types.h -+++ linux-3.3.x86_64/include/media/davinci/vpif_types.h -@@ -17,6 +17,8 @@ - #ifndef _VPIF_TYPES_H - #define _VPIF_TYPES_H - -+#include -+ - #define VPIF_CAPTURE_MAX_CHANNELS 2 - - enum vpif_if_type { -Index: linux-3.3.x86_64/drivers/media/video/tm6000/tm6000-input.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/tm6000/tm6000-input.c -+++ linux-3.3.x86_64/drivers/media/video/tm6000/tm6000-input.c -@@ -481,8 +481,6 @@ int tm6000_ir_fini(struct tm6000_core *d - - dprintk(2, "%s\n",__func__); - -- rc_unregister_device(ir->rc); -- - if (!ir->polling) - __tm6000_ir_int_stop(ir->rc); - -@@ -492,6 +490,7 @@ int tm6000_ir_fini(struct tm6000_core *d - tm6000_flash_led(dev, 0); - ir->pwled = 0; - -+ rc_unregister_device(ir->rc); - - kfree(ir); - dev->ir = NULL; -Index: linux-3.3.x86_64/drivers/media/dvb/mantis/mantis_hif.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/mantis/mantis_hif.c -+++ linux-3.3.x86_64/drivers/media/dvb/mantis/mantis_hif.c -@@ -76,7 +76,7 @@ static int mantis_hif_write_wait(struct - udelay(500); - timeout++; - if (timeout > 100) { -- dprintk(MANTIS_ERROR, 1, "Adater(%d) Slot(0): Write operation timed out!", mantis->num); -+ dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write operation timed out!", mantis->num); - rc = -ETIMEDOUT; - break; - } -Index: linux-3.3.x86_64/drivers/media/common/tuners/max2165.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/common/tuners/max2165.c -+++ linux-3.3.x86_64/drivers/media/common/tuners/max2165.c -@@ -168,7 +168,7 @@ int fixpt_div32(u32 dividend, u32 diviso - int i; - - if (0 == divisor) -- return -1; -+ return -EINVAL; - - q = dividend / divisor; - remainder = dividend - q * divisor; -@@ -194,10 +194,13 @@ static int max2165_set_rf(struct max2165 - u8 tf_ntch; - u32 t; - u32 quotient, fraction; -+ int ret; - - /* Set PLL divider according to RF frequency */ -- fixpt_div32(freq / 1000, priv->config->osc_clk * 1000, -- "ient, &fraction); -+ ret = fixpt_div32(freq / 1000, priv->config->osc_clk * 1000, -+ "ient, &fraction); -+ if (ret != 0) -+ return ret; - - /* 20-bit fraction */ - fraction >>= 12; -Index: linux-3.3.x86_64/drivers/media/video/v4l2-compat-ioctl32.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/v4l2-compat-ioctl32.c -+++ linux-3.3.x86_64/drivers/media/video/v4l2-compat-ioctl32.c -@@ -14,12 +14,11 @@ - */ - - #include --#include - #include -+#include -+#include - #include - --#ifdef CONFIG_COMPAT -- - static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) - { - long ret = -ENOIOCTLCMD; -@@ -937,6 +936,7 @@ static long do_video_ioctl(struct file * - - long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) - { -+ struct video_device *vdev = video_devdata(file); - long ret = -ENOIOCTLCMD; - - if (!file->f_op->unlocked_ioctl) -@@ -1005,6 +1005,8 @@ long v4l2_compat_ioctl32(struct file *fi - case VIDIOC_G_ENC_INDEX: - case VIDIOC_ENCODER_CMD: - case VIDIOC_TRY_ENCODER_CMD: -+ case VIDIOC_DECODER_CMD: -+ case VIDIOC_TRY_DECODER_CMD: - case VIDIOC_DBG_S_REGISTER: - case VIDIOC_DBG_G_REGISTER: - case VIDIOC_DBG_G_CHIP_IDENT: -@@ -1025,14 +1027,16 @@ long v4l2_compat_ioctl32(struct file *fi - break; - - default: -- printk(KERN_WARNING "compat_ioctl32: " -- "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", -- _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd); -+ if (vdev->fops->compat_ioctl32) -+ ret = vdev->fops->compat_ioctl32(file, cmd, arg); -+ -+ if (ret == -ENOIOCTLCMD) -+ printk(KERN_WARNING "compat_ioctl32: " -+ "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", -+ _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), -+ cmd); - break; - } - return ret; - } - EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32); --#endif -- --MODULE_LICENSE("GPL"); -Index: linux-3.3.x86_64/include/media/v4l2-ioctl.h -=================================================================== ---- linux-3.3.x86_64.orig/include/media/v4l2-ioctl.h -+++ linux-3.3.x86_64/include/media/v4l2-ioctl.h -@@ -211,6 +211,10 @@ struct v4l2_ioctl_ops { - struct v4l2_encoder_cmd *a); - int (*vidioc_try_encoder_cmd) (struct file *file, void *fh, - struct v4l2_encoder_cmd *a); -+ int (*vidioc_decoder_cmd) (struct file *file, void *fh, -+ struct v4l2_decoder_cmd *a); -+ int (*vidioc_try_decoder_cmd) (struct file *file, void *fh, -+ struct v4l2_decoder_cmd *a); - - /* Stream type-dependent parameter ioctls */ - int (*vidioc_g_parm) (struct file *file, void *fh, -Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-driver.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-driver.c -+++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-driver.c -@@ -55,7 +55,7 @@ - #include "ivtv-routing.h" - #include "ivtv-controls.h" - #include "ivtv-gpio.h" -- -+#include - #include - #include - #include -@@ -99,7 +99,7 @@ static int i2c_clock_period[IVTV_MAX_CAR - - static unsigned int cardtype_c = 1; - static unsigned int tuner_c = 1; --static bool radio_c = 1; -+static int radio_c = 1; - static unsigned int i2c_clock_period_c = 1; - static char pal[] = "---"; - static char secam[] = "--"; -@@ -139,7 +139,7 @@ static int tunertype = -1; - static int newi2c = -1; - - module_param_array(tuner, int, &tuner_c, 0644); --module_param_array(radio, bool, &radio_c, 0644); -+module_param_array(radio, int, &radio_c, 0644); - module_param_array(cardtype, int, &cardtype_c, 0644); - module_param_string(pal, pal, sizeof(pal), 0644); - module_param_string(secam, secam, sizeof(secam), 0644); -@@ -744,8 +744,6 @@ static int __devinit ivtv_init_struct1(s - - itv->cur_dma_stream = -1; - itv->cur_pio_stream = -1; -- itv->audio_stereo_mode = AUDIO_STEREO; -- itv->audio_bilingual_mode = AUDIO_MONO_LEFT; - - /* Ctrls */ - itv->speed = 1000; -@@ -815,7 +813,7 @@ static int ivtv_setup_pci(struct ivtv *i - IVTV_ERR("Can't enable device!\n"); - return -EIO; - } -- if (pci_set_dma_mask(pdev, 0xffffffff)) { -+ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { - IVTV_ERR("No suitable DMA available.\n"); - return -EIO; - } -@@ -1200,6 +1198,32 @@ static int __devinit ivtv_probe(struct p - itv->tuner_std = itv->std; - - if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { -+ struct v4l2_ctrl_handler *hdl = itv->v4l2_dev.ctrl_handler; -+ -+ itv->ctrl_pts = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops, -+ V4L2_CID_MPEG_VIDEO_DEC_PTS, 0, 0, 1, 0); -+ itv->ctrl_frame = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops, -+ V4L2_CID_MPEG_VIDEO_DEC_FRAME, 0, 0x7fffffff, 1, 0); -+ /* Note: V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO is not supported, -+ mask that menu item. */ -+ itv->ctrl_audio_playback = -+ v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops, -+ V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK, -+ V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO, -+ 1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO, -+ V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO); -+ itv->ctrl_audio_multilingual_playback = -+ v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops, -+ V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK, -+ V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO, -+ 1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO, -+ V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT); -+ if (hdl->error) { -+ retval = hdl->error; -+ goto free_i2c; -+ } -+ v4l2_ctrl_cluster(2, &itv->ctrl_pts); -+ v4l2_ctrl_cluster(2, &itv->ctrl_audio_playback); - ivtv_call_all(itv, video, s_std_output, itv->std); - /* Turn off the output signal. The mpeg decoder is not yet - active so without this you would get a green image until the -@@ -1236,6 +1260,7 @@ free_streams: - free_irq: - free_irq(itv->pdev->irq, (void *)itv); - free_i2c: -+ v4l2_ctrl_handler_free(&itv->cxhdl.hdl); - exit_ivtv_i2c(itv); - free_io: - ivtv_iounmap(itv); -@@ -1375,7 +1400,7 @@ static void ivtv_remove(struct pci_dev * - else - type = IVTV_DEC_STREAM_TYPE_MPG; - ivtv_stop_v4l2_decode_stream(&itv->streams[type], -- VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); -+ V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0); - } - ivtv_halt_firmware(itv); - } -@@ -1391,6 +1416,8 @@ static void ivtv_remove(struct pci_dev * - ivtv_streams_cleanup(itv, 1); - ivtv_udma_free(itv); - -+ v4l2_ctrl_handler_free(&itv->cxhdl.hdl); -+ - exit_ivtv_i2c(itv); - - free_irq(itv->pdev->irq, (void *)itv); -Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-fileops.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-fileops.c -+++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-fileops.c -@@ -746,8 +746,9 @@ unsigned int ivtv_v4l2_dec_poll(struct f - return res; - } - --unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait) -+unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table *wait) - { -+ unsigned long req_events = poll_requested_events(wait); - struct ivtv_open_id *id = fh2id(filp->private_data); - struct ivtv *itv = id->itv; - struct ivtv_stream *s = &itv->streams[id->type]; -@@ -755,7 +756,8 @@ unsigned int ivtv_v4l2_enc_poll(struct f - unsigned res = 0; - - /* Start a capture if there is none */ -- if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { -+ if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags) && -+ (req_events & (POLLIN | POLLRDNORM))) { - int rc; - - rc = ivtv_start_capture(id); -@@ -900,7 +902,7 @@ int ivtv_v4l2_close(struct file *filp) - if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { - struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT]; - -- ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); -+ ivtv_stop_decoding(id, V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0); - - /* If all output streams are closed, and if the user doesn't have - IVTV_DEC_STREAM_TYPE_VOUT open, then disable CC on TV-out. */ -Index: linux-3.3.x86_64/drivers/media/video/v4l2-ctrls.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/v4l2-ctrls.c -+++ linux-3.3.x86_64/drivers/media/video/v4l2-ctrls.c -@@ -175,6 +175,15 @@ const char * const *v4l2_ctrl_get_menu(u - "16-bit CRC", - NULL - }; -+ static const char * const mpeg_audio_dec_playback[] = { -+ "Auto", -+ "Stereo", -+ "Left", -+ "Right", -+ "Mono", -+ "Swapped Stereo", -+ NULL -+ }; - static const char * const mpeg_video_encoding[] = { - "MPEG-1", - "MPEG-2", -@@ -236,8 +245,8 @@ const char * const *v4l2_ctrl_get_menu(u - }; - static const char * const tune_preemphasis[] = { - "No Preemphasis", -- "50 useconds", -- "75 useconds", -+ "50 Microseconds", -+ "75 Microseconds", - NULL, - }; - static const char * const header_mode[] = { -@@ -334,7 +343,7 @@ const char * const *v4l2_ctrl_get_menu(u - }; - static const char * const mpeg4_profile[] = { - "Simple", -- "Adcanved Simple", -+ "Advanced Simple", - "Core", - "Simple Scalable", - "Advanced Coding Efficency", -@@ -353,6 +362,16 @@ const char * const *v4l2_ctrl_get_menu(u - NULL, - }; - -+ static const char * const jpeg_chroma_subsampling[] = { -+ "4:4:4", -+ "4:2:2", -+ "4:2:0", -+ "4:1:1", -+ "4:1:0", -+ "Gray", -+ NULL, -+ }; -+ - switch (id) { - case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: - return mpeg_audio_sampling_freq; -@@ -374,6 +393,9 @@ const char * const *v4l2_ctrl_get_menu(u - return mpeg_audio_emphasis; - case V4L2_CID_MPEG_AUDIO_CRC: - return mpeg_audio_crc; -+ case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: -+ case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: -+ return mpeg_audio_dec_playback; - case V4L2_CID_MPEG_VIDEO_ENCODING: - return mpeg_video_encoding; - case V4L2_CID_MPEG_VIDEO_ASPECT: -@@ -414,6 +436,9 @@ const char * const *v4l2_ctrl_get_menu(u - return mpeg_mpeg4_level; - case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: - return mpeg4_profile; -+ case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: -+ return jpeg_chroma_subsampling; -+ - default: - return NULL; - } -@@ -492,6 +517,8 @@ const char *v4l2_ctrl_get_name(u32 id) - case V4L2_CID_MPEG_AUDIO_MUTE: return "Audio Mute"; - case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: return "Audio AAC Bitrate"; - case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: return "Audio AC-3 Bitrate"; -+ case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: return "Audio Playback"; -+ case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: return "Audio Multilingual Playback"; - case V4L2_CID_MPEG_VIDEO_ENCODING: return "Video Encoding"; - case V4L2_CID_MPEG_VIDEO_ASPECT: return "Video Aspect"; - case V4L2_CID_MPEG_VIDEO_B_FRAMES: return "Video B Frames"; -@@ -546,6 +573,8 @@ const char *v4l2_ctrl_get_name(u32 id) - case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: return "Number of MBs in a Slice"; - case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: return "Slice Partitioning Method"; - case V4L2_CID_MPEG_VIDEO_VBV_SIZE: return "VBV Buffer Size"; -+ case V4L2_CID_MPEG_VIDEO_DEC_PTS: return "Video Decoder PTS"; -+ case V4L2_CID_MPEG_VIDEO_DEC_FRAME: return "Video Decoder Frame Count"; - - /* CAMERA controls */ - /* Keep the order of the 'case's the same as in videodev2.h! */ -@@ -607,6 +636,14 @@ const char *v4l2_ctrl_get_name(u32 id) - case V4L2_CID_FLASH_CHARGE: return "Charge"; - case V4L2_CID_FLASH_READY: return "Ready to Strobe"; - -+ /* JPEG encoder controls */ -+ /* Keep the order of the 'case's the same as in videodev2.h! */ -+ case V4L2_CID_JPEG_CLASS: return "JPEG Compression Controls"; -+ case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: return "Chroma Subsampling"; -+ case V4L2_CID_JPEG_RESTART_INTERVAL: return "Restart Interval"; -+ case V4L2_CID_JPEG_COMPRESSION_QUALITY: return "Compression Quality"; -+ case V4L2_CID_JPEG_ACTIVE_MARKER: return "Active Markers"; -+ - default: - return NULL; - } -@@ -674,6 +711,8 @@ void v4l2_ctrl_fill(u32 id, const char * - case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: - case V4L2_CID_MPEG_AUDIO_EMPHASIS: - case V4L2_CID_MPEG_AUDIO_CRC: -+ case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: -+ case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: - case V4L2_CID_MPEG_VIDEO_ENCODING: - case V4L2_CID_MPEG_VIDEO_ASPECT: - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: -@@ -693,6 +732,7 @@ void v4l2_ctrl_fill(u32 id, const char * - case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: - case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: - case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: -+ case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: - *type = V4L2_CTRL_TYPE_MENU; - break; - case V4L2_CID_RDS_TX_PS_NAME: -@@ -704,6 +744,7 @@ void v4l2_ctrl_fill(u32 id, const char * - case V4L2_CID_MPEG_CLASS: - case V4L2_CID_FM_TX_CLASS: - case V4L2_CID_FLASH_CLASS: -+ case V4L2_CID_JPEG_CLASS: - *type = V4L2_CTRL_TYPE_CTRL_CLASS; - /* You can neither read not write these */ - *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY; -@@ -717,6 +758,7 @@ void v4l2_ctrl_fill(u32 id, const char * - *max = 0xFFFFFF; - break; - case V4L2_CID_FLASH_FAULT: -+ case V4L2_CID_JPEG_ACTIVE_MARKER: - *type = V4L2_CTRL_TYPE_BITMASK; - break; - case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: -@@ -724,6 +766,11 @@ void v4l2_ctrl_fill(u32 id, const char * - *type = V4L2_CTRL_TYPE_INTEGER; - *flags |= V4L2_CTRL_FLAG_READ_ONLY; - break; -+ case V4L2_CID_MPEG_VIDEO_DEC_FRAME: -+ case V4L2_CID_MPEG_VIDEO_DEC_PTS: -+ *type = V4L2_CTRL_TYPE_INTEGER64; -+ *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_VOLATILE; -+ break; - default: - *type = V4L2_CTRL_TYPE_INTEGER; - break; -@@ -1470,7 +1517,7 @@ EXPORT_SYMBOL(v4l2_ctrl_add_ctrl); - int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl, - struct v4l2_ctrl_handler *add) - { -- struct v4l2_ctrl *ctrl; -+ struct v4l2_ctrl_ref *ref; - int ret = 0; - - /* Do nothing if either handler is NULL or if they are the same */ -@@ -1479,7 +1526,9 @@ int v4l2_ctrl_add_handler(struct v4l2_ct - if (hdl->error) - return hdl->error; - mutex_lock(&add->lock); -- list_for_each_entry(ctrl, &add->ctrls, node) { -+ list_for_each_entry(ref, &add->ctrl_refs, node) { -+ struct v4l2_ctrl *ctrl = ref->ctrl; -+ - /* Skip handler-private controls. */ - if (ctrl->is_private) - continue; -@@ -2359,3 +2408,35 @@ void v4l2_ctrl_del_event(struct v4l2_ctr - v4l2_ctrl_unlock(ctrl); - } - EXPORT_SYMBOL(v4l2_ctrl_del_event); -+ -+int v4l2_ctrl_log_status(struct file *file, void *fh) -+{ -+ struct video_device *vfd = video_devdata(file); -+ struct v4l2_fh *vfh = file->private_data; -+ -+ if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) && vfd->v4l2_dev) -+ v4l2_ctrl_handler_log_status(vfh->ctrl_handler, -+ vfd->v4l2_dev->name); -+ return 0; -+} -+EXPORT_SYMBOL(v4l2_ctrl_log_status); -+ -+int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh, -+ struct v4l2_event_subscription *sub) -+{ -+ if (sub->type == V4L2_EVENT_CTRL) -+ return v4l2_event_subscribe(fh, sub, 0); -+ return -EINVAL; -+} -+EXPORT_SYMBOL(v4l2_ctrl_subscribe_event); -+ -+unsigned int v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait) -+{ -+ struct v4l2_fh *fh = file->private_data; -+ -+ if (v4l2_event_pending(fh)) -+ return POLLPRI; -+ poll_wait(file, &fh->wait, wait); -+ return 0; -+} -+EXPORT_SYMBOL(v4l2_ctrl_poll); -Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-controls.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-controls.c -+++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-controls.c -@@ -21,6 +21,7 @@ - #include "ivtv-driver.h" - #include "ivtv-ioctl.h" - #include "ivtv-controls.h" -+#include "ivtv-mailbox.h" - - static int ivtv_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt) - { -@@ -99,3 +100,64 @@ struct cx2341x_handler_ops ivtv_cxhdl_op - .s_video_encoding = ivtv_s_video_encoding, - .s_stream_vbi_fmt = ivtv_s_stream_vbi_fmt, - }; -+ -+int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame) -+{ -+ u32 data[CX2341X_MBOX_MAX_DATA]; -+ -+ if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { -+ *pts = (s64)((u64)itv->last_dec_timing[2] << 32) | -+ (u64)itv->last_dec_timing[1]; -+ *frame = itv->last_dec_timing[0]; -+ return 0; -+ } -+ *pts = 0; -+ *frame = 0; -+ if (atomic_read(&itv->decoding)) { -+ if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { -+ IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); -+ return -EIO; -+ } -+ memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); -+ set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); -+ *pts = (s64)((u64) data[2] << 32) | (u64) data[1]; -+ *frame = data[0]; -+ /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/ -+ } -+ return 0; -+} -+ -+static int ivtv_g_volatile_ctrl(struct v4l2_ctrl *ctrl) -+{ -+ struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl); -+ -+ switch (ctrl->id) { -+ /* V4L2_CID_MPEG_VIDEO_DEC_PTS and V4L2_CID_MPEG_VIDEO_DEC_FRAME -+ control cluster */ -+ case V4L2_CID_MPEG_VIDEO_DEC_PTS: -+ return ivtv_g_pts_frame(itv, &itv->ctrl_pts->val64, -+ &itv->ctrl_frame->val64); -+ } -+ return 0; -+} -+ -+static int ivtv_s_ctrl(struct v4l2_ctrl *ctrl) -+{ -+ struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl); -+ -+ switch (ctrl->id) { -+ /* V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK and MULTILINGUAL_PLAYBACK -+ control cluster */ -+ case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: -+ itv->audio_stereo_mode = itv->ctrl_audio_playback->val - 1; -+ itv->audio_bilingual_mode = itv->ctrl_audio_multilingual_playback->val - 1; -+ ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); -+ break; -+ } -+ return 0; -+} -+ -+const struct v4l2_ctrl_ops ivtv_hdl_out_ops = { -+ .s_ctrl = ivtv_s_ctrl, -+ .g_volatile_ctrl = ivtv_g_volatile_ctrl, -+}; -Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-controls.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-controls.h -+++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-controls.h -@@ -22,5 +22,7 @@ - #define IVTV_CONTROLS_H - - extern struct cx2341x_handler_ops ivtv_cxhdl_ops; -+extern const struct v4l2_ctrl_ops ivtv_hdl_out_ops; -+int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame); - - #endif -Index: linux-3.3.x86_64/drivers/media/dvb/ddbridge/ddbridge.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/ddbridge/ddbridge.h -+++ linux-3.3.x86_64/drivers/media/dvb/ddbridge/ddbridge.h -@@ -32,8 +32,6 @@ - #include - #include - #include --#include --#include - #include - - #include "dmxdev.h" -Index: linux-3.3.x86_64/drivers/media/video/cx18/cx18-driver.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/cx18/cx18-driver.h -+++ linux-3.3.x86_64/drivers/media/video/cx18/cx18-driver.h -@@ -44,8 +44,6 @@ - #include - #include - --#include --#include - #include - #include - #include -Index: linux-3.3.x86_64/include/linux/ivtv.h -=================================================================== ---- linux-3.3.x86_64.orig/include/linux/ivtv.h -+++ linux-3.3.x86_64/include/linux/ivtv.h -@@ -58,7 +58,11 @@ struct ivtv_dma_frame { - __u32 src_height; - }; - --#define IVTV_IOC_DMA_FRAME _IOW ('V', BASE_VIDIOC_PRIVATE+0, struct ivtv_dma_frame) -+#define IVTV_IOC_DMA_FRAME _IOW ('V', BASE_VIDIOC_PRIVATE+0, struct ivtv_dma_frame) -+ -+/* Select the passthrough mode (if the argument is non-zero). In the passthrough -+ mode the output of the encoder is passed immediately into the decoder. */ -+#define IVTV_IOC_PASSTHROUGH_MODE _IOW ('V', BASE_VIDIOC_PRIVATE+1, int) - - /* Deprecated defines: applications should use the defines from videodev2.h */ - #define IVTV_SLICED_TYPE_TELETEXT_B V4L2_MPEG_VBI_IVTV_TELETEXT_B -Index: linux-3.3.x86_64/drivers/media/rc/keymaps/Makefile -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/rc/keymaps/Makefile -+++ linux-3.3.x86_64/drivers/media/rc/keymaps/Makefile -@@ -41,8 +41,11 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t - rc-imon-mce.o \ - rc-imon-pad.o \ - rc-iodata-bctv7e.o \ -+ rc-it913x-v1.o \ -+ rc-it913x-v2.o \ - rc-kaiomy.o \ - rc-kworld-315u.o \ -+ rc-kworld-pc150u.o \ - rc-kworld-plus-tv-analog.o \ - rc-leadtek-y04g0051.o \ - rc-lirc.o \ -Index: linux-3.3.x86_64/drivers/media/rc/keymaps/rc-it913x-v1.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/rc/keymaps/rc-it913x-v1.c -@@ -0,0 +1,95 @@ -+/* ITE Generic remotes Version 1 -+ * -+ * Copyright (C) 2012 Malcolm Priestley (tvboxspy@gmail.com) -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include -+#include -+ -+ -+static struct rc_map_table it913x_v1_rc[] = { -+ /* Type 1 */ -+ { 0x61d601, KEY_VIDEO }, /* Source */ -+ { 0x61d602, KEY_3 }, -+ { 0x61d603, KEY_POWER }, /* ShutDown */ -+ { 0x61d604, KEY_1 }, -+ { 0x61d605, KEY_5 }, -+ { 0x61d606, KEY_6 }, -+ { 0x61d607, KEY_CHANNELDOWN }, /* CH- */ -+ { 0x61d608, KEY_2 }, -+ { 0x61d609, KEY_CHANNELUP }, /* CH+ */ -+ { 0x61d60a, KEY_9 }, -+ { 0x61d60b, KEY_ZOOM }, /* Zoom */ -+ { 0x61d60c, KEY_7 }, -+ { 0x61d60d, KEY_8 }, -+ { 0x61d60e, KEY_VOLUMEUP }, /* Vol+ */ -+ { 0x61d60f, KEY_4 }, -+ { 0x61d610, KEY_ESC }, /* [back up arrow] */ -+ { 0x61d611, KEY_0 }, -+ { 0x61d612, KEY_OK }, /* [enter arrow] */ -+ { 0x61d613, KEY_VOLUMEDOWN }, /* Vol- */ -+ { 0x61d614, KEY_RECORD }, /* Rec */ -+ { 0x61d615, KEY_STOP }, /* Stop */ -+ { 0x61d616, KEY_PLAY }, /* Play */ -+ { 0x61d617, KEY_MUTE }, /* Mute */ -+ { 0x61d618, KEY_UP }, -+ { 0x61d619, KEY_DOWN }, -+ { 0x61d61a, KEY_LEFT }, -+ { 0x61d61b, KEY_RIGHT }, -+ { 0x61d61c, KEY_RED }, -+ { 0x61d61d, KEY_GREEN }, -+ { 0x61d61e, KEY_YELLOW }, -+ { 0x61d61f, KEY_BLUE }, -+ { 0x61d643, KEY_POWER2 }, /* [red power button] */ -+ /* Type 2 - 20 buttons */ -+ { 0x807f0d, KEY_0 }, -+ { 0x807f04, KEY_1 }, -+ { 0x807f05, KEY_2 }, -+ { 0x807f06, KEY_3 }, -+ { 0x807f07, KEY_4 }, -+ { 0x807f08, KEY_5 }, -+ { 0x807f09, KEY_6 }, -+ { 0x807f0a, KEY_7 }, -+ { 0x807f1b, KEY_8 }, -+ { 0x807f1f, KEY_9 }, -+ { 0x807f12, KEY_POWER }, -+ { 0x807f01, KEY_MEDIA_REPEAT}, /* Recall */ -+ { 0x807f19, KEY_PAUSE }, /* Timeshift */ -+ { 0x807f1e, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */ -+ { 0x807f03, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/ -+ { 0x807f1a, KEY_CHANNELUP }, -+ { 0x807f02, KEY_CHANNELDOWN }, -+ { 0x807f0c, KEY_ZOOM }, -+ { 0x807f00, KEY_RECORD }, -+ { 0x807f0e, KEY_STOP }, -+}; -+ -+static struct rc_map_list it913x_v1_map = { -+ .map = { -+ .scan = it913x_v1_rc, -+ .size = ARRAY_SIZE(it913x_v1_rc), -+ .rc_type = RC_TYPE_NEC, -+ .name = RC_MAP_IT913X_V1, -+ } -+}; -+ -+static int __init init_rc_it913x_v1_map(void) -+{ -+ return rc_map_register(&it913x_v1_map); -+} -+ -+static void __exit exit_rc_it913x_v1_map(void) -+{ -+ rc_map_unregister(&it913x_v1_map); -+} -+ -+module_init(init_rc_it913x_v1_map) -+module_exit(exit_rc_it913x_v1_map) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); -Index: linux-3.3.x86_64/drivers/media/rc/keymaps/rc-it913x-v2.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/rc/keymaps/rc-it913x-v2.c -@@ -0,0 +1,94 @@ -+/* ITE Generic remotes Version 2 -+ * -+ * Copyright (C) 2012 Malcolm Priestley (tvboxspy@gmail.com) -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include -+#include -+ -+ -+static struct rc_map_table it913x_v2_rc[] = { -+ /* Type 1 */ -+ /* 9005 remote */ -+ { 0x807f12, KEY_POWER2 }, /* Power (RED POWER BUTTON)*/ -+ { 0x807f1a, KEY_VIDEO }, /* Source */ -+ { 0x807f1e, KEY_MUTE }, /* Mute */ -+ { 0x807f01, KEY_RECORD }, /* Record */ -+ { 0x807f02, KEY_CHANNELUP }, /* Channel+ */ -+ { 0x807f03, KEY_TIME }, /* TimeShift */ -+ { 0x807f04, KEY_VOLUMEUP }, /* Volume- */ -+ { 0x807f05, KEY_SCREEN }, /* FullScreen */ -+ { 0x807f06, KEY_VOLUMEDOWN }, /* Volume- */ -+ { 0x807f07, KEY_0 }, /* 0 */ -+ { 0x807f08, KEY_CHANNELDOWN }, /* Channel- */ -+ { 0x807f09, KEY_PREVIOUS }, /* Recall */ -+ { 0x807f0a, KEY_1 }, /* 1 */ -+ { 0x807f1b, KEY_2 }, /* 2 */ -+ { 0x807f1f, KEY_3 }, /* 3 */ -+ { 0x807f0c, KEY_4 }, /* 4 */ -+ { 0x807f0d, KEY_5 }, /* 5 */ -+ { 0x807f0e, KEY_6 }, /* 6 */ -+ { 0x807f00, KEY_7 }, /* 7 */ -+ { 0x807f0f, KEY_8 }, /* 8 */ -+ { 0x807f19, KEY_9 }, /* 9 */ -+ -+ /* Type 2 */ -+ /* keys stereo, snapshot unassigned */ -+ { 0x866b00, KEY_0 }, -+ { 0x866b1b, KEY_1 }, -+ { 0x866b02, KEY_2 }, -+ { 0x866b03, KEY_3 }, -+ { 0x866b04, KEY_4 }, -+ { 0x866b05, KEY_5 }, -+ { 0x866b06, KEY_6 }, -+ { 0x866b07, KEY_7 }, -+ { 0x866b08, KEY_8 }, -+ { 0x866b09, KEY_9 }, -+ { 0x866b12, KEY_POWER }, -+ { 0x866b13, KEY_MUTE }, -+ { 0x866b0a, KEY_PREVIOUS }, /* Recall */ -+ { 0x866b1e, KEY_PAUSE }, -+ { 0x866b0c, KEY_VOLUMEUP }, -+ { 0x866b18, KEY_VOLUMEDOWN }, -+ { 0x866b0b, KEY_CHANNELUP }, -+ { 0x866b18, KEY_CHANNELDOWN }, -+ { 0x866b10, KEY_ZOOM }, -+ { 0x866b1d, KEY_RECORD }, -+ { 0x866b0e, KEY_STOP }, -+ { 0x866b11, KEY_EPG}, -+ { 0x866b1a, KEY_FASTFORWARD }, -+ { 0x866b0f, KEY_REWIND }, -+ { 0x866b1c, KEY_TV }, -+ { 0x866b1b, KEY_TEXT }, -+ -+}; -+ -+static struct rc_map_list it913x_v2_map = { -+ .map = { -+ .scan = it913x_v2_rc, -+ .size = ARRAY_SIZE(it913x_v2_rc), -+ .rc_type = RC_TYPE_NEC, -+ .name = RC_MAP_IT913X_V2, -+ } -+}; -+ -+static int __init init_rc_it913x_v2_map(void) -+{ -+ return rc_map_register(&it913x_v2_map); -+} -+ -+static void __exit exit_rc_it913x_v2_map(void) -+{ -+ rc_map_unregister(&it913x_v2_map); -+} -+ -+module_init(init_rc_it913x_v2_map) -+module_exit(exit_rc_it913x_v2_map) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); -Index: linux-3.3.x86_64/include/media/rc-map.h -=================================================================== ---- linux-3.3.x86_64.orig/include/media/rc-map.h -+++ linux-3.3.x86_64/include/media/rc-map.h -@@ -102,8 +102,11 @@ void rc_map_init(void); - #define RC_MAP_IMON_MCE "rc-imon-mce" - #define RC_MAP_IMON_PAD "rc-imon-pad" - #define RC_MAP_IODATA_BCTV7E "rc-iodata-bctv7e" -+#define RC_MAP_IT913X_V1 "rc-it913x-v1" -+#define RC_MAP_IT913X_V2 "rc-it913x-v2" - #define RC_MAP_KAIOMY "rc-kaiomy" - #define RC_MAP_KWORLD_315U "rc-kworld-315u" -+#define RC_MAP_KWORLD_PC150U "rc-kworld-pc150u" - #define RC_MAP_KWORLD_PLUS_TV_ANALOG "rc-kworld-plus-tv-analog" - #define RC_MAP_LEADTEK_Y04G0051 "rc-leadtek-y04g0051" - #define RC_MAP_LIRC "rc-lirc" -Index: linux-3.3.x86_64/drivers/media/video/bt8xx/bttv-driver.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/bt8xx/bttv-driver.c -+++ linux-3.3.x86_64/drivers/media/video/bt8xx/bttv-driver.c -@@ -2035,11 +2035,7 @@ static int bttv_log_status(struct file * - struct bttv_fh *fh = f; - struct bttv *btv = fh->btv; - -- pr_info("%d: ======== START STATUS CARD #%d ========\n", -- btv->c.nr, btv->c.nr); - bttv_call_all(btv, core, log_status); -- pr_info("%d: ======== END STATUS CARD #%d ========\n", -- btv->c.nr, btv->c.nr); - return 0; - } - -Index: linux-3.3.x86_64/drivers/media/video/cx18/cx18-ioctl.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/cx18/cx18-ioctl.c -+++ linux-3.3.x86_64/drivers/media/video/cx18/cx18-ioctl.c -@@ -1085,8 +1085,6 @@ static int cx18_log_status(struct file * - struct v4l2_audio audin; - int i; - -- CX18_INFO("================= START STATUS CARD #%d " -- "=================\n", cx->instance); - CX18_INFO("Version: %s Card: %s\n", CX18_VERSION, cx->card_name); - if (cx->hw_flags & CX18_HW_TVEEPROM) { - struct tveeprom tv; -@@ -1120,8 +1118,6 @@ static int cx18_log_status(struct file * - CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", - (long long)cx->mpg_data_received, - (long long)cx->vbi_data_inserted); -- CX18_INFO("================== END STATUS CARD #%d " -- "==================\n", cx->instance); - return 0; - } - -Index: linux-3.3.x86_64/drivers/media/video/pwc/pwc-v4l.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/pwc/pwc-v4l.c -+++ linux-3.3.x86_64/drivers/media/video/pwc/pwc-v4l.c -@@ -1146,14 +1146,6 @@ leave: - return ret; - } - --static int pwc_log_status(struct file *file, void *priv) --{ -- struct pwc_device *pdev = video_drvdata(file); -- -- v4l2_ctrl_handler_log_status(&pdev->ctrl_handler, PWC_NAME); -- return 0; --} -- - const struct v4l2_ioctl_ops pwc_ioctl_ops = { - .vidioc_querycap = pwc_querycap, - .vidioc_enum_input = pwc_enum_input, -@@ -1169,9 +1161,11 @@ const struct v4l2_ioctl_ops pwc_ioctl_op - .vidioc_dqbuf = pwc_dqbuf, - .vidioc_streamon = pwc_streamon, - .vidioc_streamoff = pwc_streamoff, -- .vidioc_log_status = pwc_log_status, -+ .vidioc_log_status = v4l2_ctrl_log_status, - .vidioc_enum_framesizes = pwc_enum_framesizes, - .vidioc_enum_frameintervals = pwc_enum_frameintervals, - .vidioc_g_parm = pwc_g_parm, - .vidioc_s_parm = pwc_s_parm, -+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, -+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - }; -Index: linux-3.3.x86_64/drivers/media/video/saa7164/saa7164-encoder.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/saa7164/saa7164-encoder.c -+++ linux-3.3.x86_64/drivers/media/video/saa7164/saa7164-encoder.c -@@ -791,11 +791,6 @@ static int vidioc_s_fmt_vid_cap(struct f - return 0; - } - --static int vidioc_log_status(struct file *file, void *priv) --{ -- return 0; --} -- - static int fill_queryctrl(struct saa7164_encoder_params *params, - struct v4l2_queryctrl *c) - { -@@ -1347,7 +1342,6 @@ static const struct v4l2_ioctl_ops mpeg_ - .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, - .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, - .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, -- .vidioc_log_status = vidioc_log_status, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_chip_ident = saa7164_g_chip_ident, - #ifdef CONFIG_VIDEO_ADV_DEBUG -Index: linux-3.3.x86_64/drivers/media/video/saa7164/saa7164-vbi.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/saa7164/saa7164-vbi.c -+++ linux-3.3.x86_64/drivers/media/video/saa7164/saa7164-vbi.c -@@ -730,11 +730,6 @@ static int vidioc_s_fmt_vid_cap(struct f - return 0; - } - --static int vidioc_log_status(struct file *file, void *priv) --{ -- return 0; --} -- - static int fill_queryctrl(struct saa7164_vbi_params *params, - struct v4l2_queryctrl *c) - { -@@ -1256,7 +1251,6 @@ static const struct v4l2_ioctl_ops vbi_i - .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, - .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, - .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, -- .vidioc_log_status = vidioc_log_status, - .vidioc_queryctrl = vidioc_queryctrl, - #if 0 - .vidioc_g_chip_ident = saa7164_g_chip_ident, -Index: linux-3.3.x86_64/include/media/v4l2-ctrls.h -=================================================================== ---- linux-3.3.x86_64.orig/include/media/v4l2-ctrls.h -+++ linux-3.3.x86_64/include/media/v4l2-ctrls.h -@@ -33,6 +33,7 @@ struct video_device; - struct v4l2_subdev; - struct v4l2_subscribed_event; - struct v4l2_fh; -+struct poll_table_struct; - - /** struct v4l2_ctrl_ops - The control operations that the driver has to provide. - * @g_volatile_ctrl: Get a new value for this control. Generally only relevant -@@ -492,6 +493,18 @@ void v4l2_ctrl_add_event(struct v4l2_ctr - void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl, - struct v4l2_subscribed_event *sev); - -+/* Can be used as a vidioc_log_status function that just dumps all controls -+ associated with the filehandle. */ -+int v4l2_ctrl_log_status(struct file *file, void *fh); -+ -+/* Can be used as a vidioc_subscribe_event function that just subscribes -+ control events. */ -+int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh, -+ struct v4l2_event_subscription *sub); -+ -+/* Can be used as a poll function that just polls for control events. */ -+unsigned int v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait); -+ - /* Helpers for ioctl_ops. If hdl == NULL then they will all return -EINVAL. */ - int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc); - int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm); -Index: linux-3.3.x86_64/drivers/media/video/v4l2-subdev.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/v4l2-subdev.c -+++ linux-3.3.x86_64/drivers/media/video/v4l2-subdev.c -@@ -194,8 +194,16 @@ static long subdev_do_ioctl(struct file - } - #endif - -- case VIDIOC_LOG_STATUS: -- return v4l2_subdev_call(sd, core, log_status); -+ case VIDIOC_LOG_STATUS: { -+ int ret; -+ -+ pr_info("%s: ================= START STATUS =================\n", -+ sd->name); -+ ret = v4l2_subdev_call(sd, core, log_status); -+ pr_info("%s: ================== END STATUS ==================\n", -+ sd->name); -+ return ret; -+ } - - #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) - case VIDIOC_SUBDEV_G_FMT: { -Index: linux-3.3.x86_64/drivers/media/radio/Kconfig -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/radio/Kconfig -+++ linux-3.3.x86_64/drivers/media/radio/Kconfig -@@ -43,7 +43,7 @@ config USB_DSBR - - config RADIO_MAXIRADIO - tristate "Guillemot MAXI Radio FM 2000 radio" -- depends on VIDEO_V4L2 && PCI -+ depends on VIDEO_V4L2 && PCI && SND - ---help--- - Choose Y here if you have this radio card. This card may also be - found as Gemtek PCI FM. -@@ -80,6 +80,16 @@ config RADIO_SI4713 - To compile this driver as a module, choose M here: the - module will be called radio-si4713. - -+config USB_KEENE -+ tristate "Keene FM Transmitter USB support" -+ depends on USB && VIDEO_V4L2 -+ ---help--- -+ Say Y here if you want to connect this type of FM transmitter -+ to your computer's USB port. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called radio-keene. -+ - config RADIO_TEA5764 - tristate "TEA5764 I2C FM radio support" - depends on I2C && VIDEO_V4L2 -@@ -167,6 +177,10 @@ menuconfig V4L_RADIO_ISA_DRIVERS - - if V4L_RADIO_ISA_DRIVERS - -+config RADIO_ISA -+ depends on ISA -+ tristate -+ - config RADIO_CADET - tristate "ADS Cadet AM/FM Tuner" - depends on ISA && VIDEO_V4L2 -@@ -174,20 +188,13 @@ config RADIO_CADET - Choose Y here if you have one of these AM/FM radio cards, and then - fill in the port address below. - -- In order to control your radio card, you will need to use programs -- that are compatible with the Video For Linux API. Information on -- this API and pointers to "v4l" programs may be found at -- . -- -- Further documentation on this driver can be found on the WWW at -- . -- - To compile this driver as a module, choose M here: the - module will be called radio-cadet. - - config RADIO_RTRACK - tristate "AIMSlab RadioTrack (aka RadioReveal) support" - depends on ISA && VIDEO_V4L2 -+ select RADIO_ISA - ---help--- - Choose Y here if you have one of these FM radio cards, and then fill - in the port address below. -@@ -201,11 +208,7 @@ config RADIO_RTRACK - You must also pass the module a suitable io parameter, 0x248 has - been reported to be used by these cards. - -- In order to control your radio card, you will need to use programs -- that are compatible with the Video For Linux API. Information on -- this API and pointers to "v4l" programs may be found at -- . More information is -- contained in the file -+ More information is contained in the file - . - - To compile this driver as a module, choose M here: the -@@ -214,7 +217,7 @@ config RADIO_RTRACK - config RADIO_RTRACK_PORT - hex "RadioTrack i/o port (0x20f or 0x30f)" - depends on RADIO_RTRACK=y -- default "20f" -+ default "30f" - help - Enter either 0x30f or 0x20f here. The card default is 0x30f, if you - haven't changed the jumper setting on the card. -@@ -222,14 +225,14 @@ config RADIO_RTRACK_PORT - config RADIO_RTRACK2 - tristate "AIMSlab RadioTrack II support" - depends on ISA && VIDEO_V4L2 -+ select RADIO_ISA - ---help--- - Choose Y here if you have this FM radio card, and then fill in the - port address below. - -- In order to control your radio card, you will need to use programs -- that are compatible with the Video For Linux API. Information on -- this API and pointers to "v4l" programs may be found at -- . -+ Note: this driver hasn't been tested since a long time due to lack -+ of hardware. If you have this hardware, then please contact the -+ linux-media mailinglist. - - To compile this driver as a module, choose M here: the - module will be called radio-rtrack2. -@@ -245,15 +248,11 @@ config RADIO_RTRACK2_PORT - config RADIO_AZTECH - tristate "Aztech/Packard Bell Radio" - depends on ISA && VIDEO_V4L2 -+ select RADIO_ISA - ---help--- - Choose Y here if you have one of these FM radio cards, and then fill - in the port address below. - -- In order to control your radio card, you will need to use programs -- that are compatible with the Video For Linux API. Information on -- this API and pointers to "v4l" programs may be found at -- . -- - To compile this driver as a module, choose M here: the - module will be called radio-aztech. - -@@ -269,6 +268,7 @@ config RADIO_AZTECH_PORT - config RADIO_GEMTEK - tristate "GemTek Radio card (or compatible) support" - depends on ISA && VIDEO_V4L2 -+ select RADIO_ISA - ---help--- - Choose Y here if you have this FM radio card, and then fill in the - I/O port address and settings below. The following cards either have -@@ -278,23 +278,21 @@ config RADIO_GEMTEK - - Typhoon Radio card (some models) - - Hama Radio card - -- In order to control your radio card, you will need to use programs -- that are compatible with the Video For Linux API. Information on -- this API and pointers to "v4l" programs may be found at -- . -- - To compile this driver as a module, choose M here: the - module will be called radio-gemtek. - - config RADIO_GEMTEK_PORT -- hex "Fixed I/O port (0x20c, 0x30c, 0x24c, 0x34c, 0c24c or 0x28c)" -+ hex "Fixed I/O port (0x20c, 0x30c, 0x24c, 0x34c, 0x248 or 0x28c)" - depends on RADIO_GEMTEK=y - default "34c" - help -- Enter either 0x20c, 0x30c, 0x24c or 0x34c here. The card default is -- 0x34c, if you haven't changed the jumper setting on the card. On -- Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the I/O -+ Enter either 0x20c, 0x30c, 0x24c, 0x34c, 0x248 or 0x28c here. The -+ card default is 0x34c, if you haven't changed the jumper setting -+ on the card. -+ -+ On Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the I/O - port is 0x20c, 0x248 or 0x28c. -+ - If automatic I/O port probing is enabled this port will be used only - in case of automatic probing failure, ie. as a fallback. - -@@ -318,11 +316,6 @@ config RADIO_MIROPCM20 - sound card driver "Miro miroSOUND PCM1pro/PCM12/PCM20radio" as this - is required for the radio-miropcm20. - -- In order to control your radio card, you will need to use programs -- that are compatible with the Video For Linux API. Information on -- this API and pointers to "v4l" programs may be found at -- . -- - To compile this driver as a module, choose M here: the - module will be called radio-miropcm20. - -@@ -332,11 +325,6 @@ config RADIO_SF16FMI - ---help--- - Choose Y here if you have one of these FM radio cards. - -- In order to control your radio card, you will need to use programs -- that are compatible with the Video For Linux API. Information on -- this API and pointers to "v4l" programs may be found at -- . -- - To compile this driver as a module, choose M here: the - module will be called radio-sf16fmi. - -@@ -346,50 +334,35 @@ config RADIO_SF16FMR2 - ---help--- - Choose Y here if you have one of these FM radio cards. - -- In order to control your radio card, you will need to use programs -- that are compatible with the Video For Linux API. Information on -- this API and pointers to "v4l" programs may be found on the WWW at -- . -- - To compile this driver as a module, choose M here: the - module will be called radio-sf16fmr2. - - config RADIO_TERRATEC - tristate "TerraTec ActiveRadio ISA Standalone" - depends on ISA && VIDEO_V4L2 -+ select RADIO_ISA - ---help--- -- Choose Y here if you have this FM radio card, and then fill in the -- port address below. (TODO) -- -- Note: This driver is in its early stages. Right now volume and -- frequency control and muting works at least for me, but -- unfortunately I have not found anybody who wants to use this card -- with Linux. So if it is this what YOU are trying to do right now, -- PLEASE DROP ME A NOTE!! Rolf Offermanns . -+ Choose Y here if you have this FM radio card. - -- In order to control your radio card, you will need to use programs -- that are compatible with the Video For Linux API. Information on -- this API and pointers to "v4l" programs may be found at -- . -+ Note: this driver hasn't been tested since a long time due to lack -+ of hardware. If you have this hardware, then please contact the -+ linux-media mailinglist. - - To compile this driver as a module, choose M here: the - module will be called radio-terratec. - --config RADIO_TERRATEC_PORT -- hex "Terratec i/o port (normally 0x590)" -- depends on RADIO_TERRATEC=y -- default "590" -- help -- Fill in the I/O port of your TerraTec FM radio card. If unsure, go -- with the default. -- - config RADIO_TRUST - tristate "Trust FM radio card" - depends on ISA && VIDEO_V4L2 -+ select RADIO_ISA - help - This is a driver for the Trust FM radio cards. Say Y if you have - such a card and want to use it under Linux. - -+ Note: this driver hasn't been tested since a long time due to lack -+ of hardware. If you have this hardware, then please contact the -+ linux-media mailinglist. -+ - To compile this driver as a module, choose M here: the - module will be called radio-trust. - -@@ -404,14 +377,14 @@ config RADIO_TRUST_PORT - config RADIO_TYPHOON - tristate "Typhoon Radio (a.k.a. EcoRadio)" - depends on ISA && VIDEO_V4L2 -+ select RADIO_ISA - ---help--- - Choose Y here if you have one of these FM radio cards, and then fill - in the port address and the frequency used for muting below. - -- In order to control your radio card, you will need to use programs -- that are compatible with the Video For Linux API. Information on -- this API and pointers to "v4l" programs may be found at -- . -+ Note: this driver hasn't been tested since a long time due to lack -+ of hardware. If you have this hardware, then please contact the -+ linux-media mailinglist. - - To compile this driver as a module, choose M here: the - module will be called radio-typhoon. -@@ -438,14 +411,14 @@ config RADIO_TYPHOON_MUTEFREQ - config RADIO_ZOLTRIX - tristate "Zoltrix Radio" - depends on ISA && VIDEO_V4L2 -+ select RADIO_ISA - ---help--- - Choose Y here if you have one of these FM radio cards, and then fill - in the port address below. - -- In order to control your radio card, you will need to use programs -- that are compatible with the Video For Linux API. Information on -- this API and pointers to "v4l" programs may be found at -- . -+ Note: this driver hasn't been tested since a long time due to lack -+ of hardware. If you have this hardware, then please contact the -+ linux-media mailinglist. - - To compile this driver as a module, choose M here: the - module will be called radio-zoltrix. -Index: linux-3.3.x86_64/drivers/media/radio/Makefile -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/radio/Makefile -+++ linux-3.3.x86_64/drivers/media/radio/Makefile -@@ -2,6 +2,7 @@ - # Makefile for the kernel character device drivers. - # - -+obj-$(CONFIG_RADIO_ISA) += radio-isa.o - obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o - obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o - obj-$(CONFIG_RADIO_SF16FMI) += radio-sf16fmi.o -@@ -20,6 +21,7 @@ obj-$(CONFIG_RADIO_MIROPCM20) += radio-m - obj-$(CONFIG_USB_DSBR) += dsbr100.o - obj-$(CONFIG_RADIO_SI470X) += si470x/ - obj-$(CONFIG_USB_MR800) += radio-mr800.o -+obj-$(CONFIG_USB_KEENE) += radio-keene.o - obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o - obj-$(CONFIG_RADIO_SAA7706H) += saa7706h.o - obj-$(CONFIG_RADIO_TEF6862) += tef6862.o -Index: linux-3.3.x86_64/drivers/media/radio/radio-keene.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/radio/radio-keene.c -@@ -0,0 +1,427 @@ -+/* -+ * Copyright (c) 2012 Hans Verkuil -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+/* kernel includes */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* driver and module definitions */ -+MODULE_AUTHOR("Hans Verkuil "); -+MODULE_DESCRIPTION("Keene FM Transmitter driver"); -+MODULE_LICENSE("GPL"); -+ -+/* Actually, it advertises itself as a Logitech */ -+#define USB_KEENE_VENDOR 0x046d -+#define USB_KEENE_PRODUCT 0x0a0e -+ -+/* Probably USB_TIMEOUT should be modified in module parameter */ -+#define BUFFER_LENGTH 8 -+#define USB_TIMEOUT 500 -+ -+/* Frequency limits in MHz */ -+#define FREQ_MIN 76U -+#define FREQ_MAX 108U -+#define FREQ_MUL 16000U -+ -+/* USB Device ID List */ -+static struct usb_device_id usb_keene_device_table[] = { -+ {USB_DEVICE_AND_INTERFACE_INFO(USB_KEENE_VENDOR, USB_KEENE_PRODUCT, -+ USB_CLASS_HID, 0, 0) }, -+ { } /* Terminating entry */ -+}; -+ -+MODULE_DEVICE_TABLE(usb, usb_keene_device_table); -+ -+struct keene_device { -+ struct usb_device *usbdev; -+ struct usb_interface *intf; -+ struct video_device vdev; -+ struct v4l2_device v4l2_dev; -+ struct v4l2_ctrl_handler hdl; -+ struct mutex lock; -+ -+ u8 *buffer; -+ unsigned curfreq; -+ u8 tx; -+ u8 pa; -+ bool stereo; -+ bool muted; -+ bool preemph_75_us; -+}; -+ -+static inline struct keene_device *to_keene_dev(struct v4l2_device *v4l2_dev) -+{ -+ return container_of(v4l2_dev, struct keene_device, v4l2_dev); -+} -+ -+/* Set frequency (if non-0), PA, mute and turn on/off the FM transmitter. */ -+static int keene_cmd_main(struct keene_device *radio, unsigned freq, bool play) -+{ -+ unsigned short freq_send = freq ? (freq - 76 * 16000) / 800 : 0; -+ int ret; -+ -+ radio->buffer[0] = 0x00; -+ radio->buffer[1] = 0x50; -+ radio->buffer[2] = (freq_send >> 8) & 0xff; -+ radio->buffer[3] = freq_send & 0xff; -+ radio->buffer[4] = radio->pa; -+ /* If bit 4 is set, then tune to the frequency. -+ If bit 3 is set, then unmute; if bit 2 is set, then mute. -+ If bit 1 is set, then enter idle mode; if bit 0 is set, -+ then enter transit mode. -+ */ -+ radio->buffer[5] = (radio->muted ? 4 : 8) | (play ? 1 : 2) | -+ (freq ? 0x10 : 0); -+ radio->buffer[6] = 0x00; -+ radio->buffer[7] = 0x00; -+ -+ ret = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0), -+ 9, 0x21, 0x200, 2, radio->buffer, BUFFER_LENGTH, USB_TIMEOUT); -+ -+ if (ret < 0) { -+ dev_warn(&radio->vdev.dev, "%s failed (%d)\n", __func__, ret); -+ return ret; -+ } -+ if (freq) -+ radio->curfreq = freq; -+ return 0; -+} -+ -+/* Set TX, stereo and preemphasis mode (50 us vs 75 us). */ -+static int keene_cmd_set(struct keene_device *radio) -+{ -+ int ret; -+ -+ radio->buffer[0] = 0x00; -+ radio->buffer[1] = 0x51; -+ radio->buffer[2] = radio->tx; -+ /* If bit 0 is set, then transmit mono, otherwise stereo. -+ If bit 2 is set, then enable 75 us preemphasis, otherwise -+ it is 50 us. */ -+ radio->buffer[3] = (!radio->stereo) | (radio->preemph_75_us ? 4 : 0); -+ radio->buffer[4] = 0x00; -+ radio->buffer[5] = 0x00; -+ radio->buffer[6] = 0x00; -+ radio->buffer[7] = 0x00; -+ -+ ret = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0), -+ 9, 0x21, 0x200, 2, radio->buffer, BUFFER_LENGTH, USB_TIMEOUT); -+ -+ if (ret < 0) { -+ dev_warn(&radio->vdev.dev, "%s failed (%d)\n", __func__, ret); -+ return ret; -+ } -+ return 0; -+} -+ -+/* Handle unplugging the device. -+ * We call video_unregister_device in any case. -+ * The last function called in this procedure is -+ * usb_keene_device_release. -+ */ -+static void usb_keene_disconnect(struct usb_interface *intf) -+{ -+ struct keene_device *radio = to_keene_dev(usb_get_intfdata(intf)); -+ -+ v4l2_device_get(&radio->v4l2_dev); -+ mutex_lock(&radio->lock); -+ usb_set_intfdata(intf, NULL); -+ video_unregister_device(&radio->vdev); -+ v4l2_device_disconnect(&radio->v4l2_dev); -+ mutex_unlock(&radio->lock); -+ v4l2_device_put(&radio->v4l2_dev); -+} -+ -+static int vidioc_querycap(struct file *file, void *priv, -+ struct v4l2_capability *v) -+{ -+ struct keene_device *radio = video_drvdata(file); -+ -+ strlcpy(v->driver, "radio-keene", sizeof(v->driver)); -+ strlcpy(v->card, "Keene FM Transmitter", sizeof(v->card)); -+ usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info)); -+ v->device_caps = V4L2_CAP_RADIO | V4L2_CAP_MODULATOR; -+ v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; -+ return 0; -+} -+ -+static int vidioc_g_modulator(struct file *file, void *priv, -+ struct v4l2_modulator *v) -+{ -+ struct keene_device *radio = video_drvdata(file); -+ -+ if (v->index > 0) -+ return -EINVAL; -+ -+ strlcpy(v->name, "FM", sizeof(v->name)); -+ v->rangelow = FREQ_MIN * FREQ_MUL; -+ v->rangehigh = FREQ_MAX * FREQ_MUL; -+ v->txsubchans = radio->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; -+ v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; -+ return 0; -+} -+ -+static int vidioc_s_modulator(struct file *file, void *priv, -+ struct v4l2_modulator *v) -+{ -+ struct keene_device *radio = video_drvdata(file); -+ -+ if (v->index > 0) -+ return -EINVAL; -+ -+ radio->stereo = (v->txsubchans == V4L2_TUNER_SUB_STEREO); -+ return keene_cmd_set(radio); -+} -+ -+static int vidioc_s_frequency(struct file *file, void *priv, -+ struct v4l2_frequency *f) -+{ -+ struct keene_device *radio = video_drvdata(file); -+ -+ if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) -+ return -EINVAL; -+ f->frequency = clamp(f->frequency, -+ FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL); -+ return keene_cmd_main(radio, f->frequency, true); -+} -+ -+static int vidioc_g_frequency(struct file *file, void *priv, -+ struct v4l2_frequency *f) -+{ -+ struct keene_device *radio = video_drvdata(file); -+ -+ if (f->tuner != 0) -+ return -EINVAL; -+ f->type = V4L2_TUNER_RADIO; -+ f->frequency = radio->curfreq; -+ return 0; -+} -+ -+static int keene_s_ctrl(struct v4l2_ctrl *ctrl) -+{ -+ static const u8 db2tx[] = { -+ /* -15, -12, -9, -6, -3, 0 dB */ -+ 0x03, 0x13, 0x02, 0x12, 0x22, 0x32, -+ /* 3, 6, 9, 12, 15, 18 dB */ -+ 0x21, 0x31, 0x20, 0x30, 0x40, 0x50 -+ }; -+ struct keene_device *radio = -+ container_of(ctrl->handler, struct keene_device, hdl); -+ -+ switch (ctrl->id) { -+ case V4L2_CID_AUDIO_MUTE: -+ radio->muted = ctrl->val; -+ return keene_cmd_main(radio, 0, true); -+ -+ case V4L2_CID_TUNE_POWER_LEVEL: -+ /* To go from dBuV to the register value we apply the -+ following formula: */ -+ radio->pa = (ctrl->val - 71) * 100 / 62; -+ return keene_cmd_main(radio, 0, true); -+ -+ case V4L2_CID_TUNE_PREEMPHASIS: -+ radio->preemph_75_us = ctrl->val == V4L2_PREEMPHASIS_75_uS; -+ return keene_cmd_set(radio); -+ -+ case V4L2_CID_AUDIO_COMPRESSION_GAIN: -+ radio->tx = db2tx[(ctrl->val - ctrl->minimum) / ctrl->step]; -+ return keene_cmd_set(radio); -+ } -+ return -EINVAL; -+} -+ -+static int vidioc_subscribe_event(struct v4l2_fh *fh, -+ struct v4l2_event_subscription *sub) -+{ -+ switch (sub->type) { -+ case V4L2_EVENT_CTRL: -+ return v4l2_event_subscribe(fh, sub, 0); -+ default: -+ return -EINVAL; -+ } -+} -+ -+ -+/* File system interface */ -+static const struct v4l2_file_operations usb_keene_fops = { -+ .owner = THIS_MODULE, -+ .open = v4l2_fh_open, -+ .release = v4l2_fh_release, -+ .poll = v4l2_ctrl_poll, -+ .unlocked_ioctl = video_ioctl2, -+}; -+ -+static const struct v4l2_ctrl_ops keene_ctrl_ops = { -+ .s_ctrl = keene_s_ctrl, -+}; -+ -+static const struct v4l2_ioctl_ops usb_keene_ioctl_ops = { -+ .vidioc_querycap = vidioc_querycap, -+ .vidioc_g_modulator = vidioc_g_modulator, -+ .vidioc_s_modulator = vidioc_s_modulator, -+ .vidioc_g_frequency = vidioc_g_frequency, -+ .vidioc_s_frequency = vidioc_s_frequency, -+ .vidioc_log_status = v4l2_ctrl_log_status, -+ .vidioc_subscribe_event = vidioc_subscribe_event, -+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -+}; -+ -+static void usb_keene_video_device_release(struct v4l2_device *v4l2_dev) -+{ -+ struct keene_device *radio = to_keene_dev(v4l2_dev); -+ -+ /* free rest memory */ -+ v4l2_ctrl_handler_free(&radio->hdl); -+ kfree(radio->buffer); -+ kfree(radio); -+} -+ -+/* check if the device is present and register with v4l and usb if it is */ -+static int usb_keene_probe(struct usb_interface *intf, -+ const struct usb_device_id *id) -+{ -+ struct usb_device *dev = interface_to_usbdev(intf); -+ struct keene_device *radio; -+ struct v4l2_ctrl_handler *hdl; -+ int retval = 0; -+ -+ /* -+ * The Keene FM transmitter USB device has the same USB ID as -+ * the Logitech AudioHub Speaker, but it should ignore the hid. -+ * Check if the name is that of the Keene device. -+ * If not, then someone connected the AudioHub and we shouldn't -+ * attempt to handle this driver. -+ * For reference: the product name of the AudioHub is -+ * "AudioHub Speaker". -+ */ -+ if (dev->product && strcmp(dev->product, "B-LINK USB Audio ")) -+ return -ENODEV; -+ -+ radio = kzalloc(sizeof(struct keene_device), GFP_KERNEL); -+ if (radio) -+ radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL); -+ -+ if (!radio || !radio->buffer) { -+ dev_err(&intf->dev, "kmalloc for keene_device failed\n"); -+ kfree(radio); -+ retval = -ENOMEM; -+ goto err; -+ } -+ -+ hdl = &radio->hdl; -+ v4l2_ctrl_handler_init(hdl, 4); -+ v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_AUDIO_MUTE, -+ 0, 1, 1, 0); -+ v4l2_ctrl_new_std_menu(hdl, &keene_ctrl_ops, V4L2_CID_TUNE_PREEMPHASIS, -+ V4L2_PREEMPHASIS_75_uS, 1, V4L2_PREEMPHASIS_50_uS); -+ v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_TUNE_POWER_LEVEL, -+ 84, 118, 1, 118); -+ v4l2_ctrl_new_std(hdl, &keene_ctrl_ops, V4L2_CID_AUDIO_COMPRESSION_GAIN, -+ -15, 18, 3, 0); -+ radio->pa = 118; -+ radio->tx = 0x32; -+ radio->stereo = true; -+ radio->curfreq = 95.16 * FREQ_MUL; -+ if (hdl->error) { -+ retval = hdl->error; -+ -+ v4l2_ctrl_handler_free(hdl); -+ goto err_v4l2; -+ } -+ retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev); -+ if (retval < 0) { -+ dev_err(&intf->dev, "couldn't register v4l2_device\n"); -+ goto err_v4l2; -+ } -+ -+ mutex_init(&radio->lock); -+ -+ radio->v4l2_dev.ctrl_handler = hdl; -+ radio->v4l2_dev.release = usb_keene_video_device_release; -+ strlcpy(radio->vdev.name, radio->v4l2_dev.name, -+ sizeof(radio->vdev.name)); -+ radio->vdev.v4l2_dev = &radio->v4l2_dev; -+ radio->vdev.fops = &usb_keene_fops; -+ radio->vdev.ioctl_ops = &usb_keene_ioctl_ops; -+ radio->vdev.lock = &radio->lock; -+ radio->vdev.release = video_device_release_empty; -+ -+ radio->usbdev = interface_to_usbdev(intf); -+ radio->intf = intf; -+ usb_set_intfdata(intf, &radio->v4l2_dev); -+ -+ video_set_drvdata(&radio->vdev, radio); -+ set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags); -+ -+ retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO, -1); -+ if (retval < 0) { -+ dev_err(&intf->dev, "could not register video device\n"); -+ goto err_vdev; -+ } -+ v4l2_ctrl_handler_setup(hdl); -+ dev_info(&intf->dev, "V4L2 device registered as %s\n", -+ video_device_node_name(&radio->vdev)); -+ return 0; -+ -+err_vdev: -+ v4l2_device_unregister(&radio->v4l2_dev); -+err_v4l2: -+ kfree(radio->buffer); -+ kfree(radio); -+err: -+ return retval; -+} -+ -+/* USB subsystem interface */ -+static struct usb_driver usb_keene_driver = { -+ .name = "radio-keene", -+ .probe = usb_keene_probe, -+ .disconnect = usb_keene_disconnect, -+ .id_table = usb_keene_device_table, -+}; -+ -+static int __init keene_init(void) -+{ -+ int retval = usb_register(&usb_keene_driver); -+ -+ if (retval) -+ pr_err(KBUILD_MODNAME -+ ": usb_register failed. Error number %d\n", retval); -+ -+ return retval; -+} -+ -+static void __exit keene_exit(void) -+{ -+ usb_deregister(&usb_keene_driver); -+} -+ -+module_init(keene_init); -+module_exit(keene_exit); -+ -Index: linux-3.3.x86_64/drivers/media/rc/fintek-cir.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/rc/fintek-cir.c -+++ linux-3.3.x86_64/drivers/media/rc/fintek-cir.c -@@ -117,7 +117,7 @@ static u8 fintek_cir_reg_read(struct fin - static void cir_dump_regs(struct fintek_dev *fintek) - { - fintek_config_mode_enable(fintek); -- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); -+ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); - - pr_reg("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME); - pr_reg(" * CR CIR BASE ADDR: 0x%x\n", -@@ -143,7 +143,7 @@ static int fintek_hw_detect(struct finte - u8 chip_major, chip_minor; - u8 vendor_major, vendor_minor; - u8 portsel, ir_class; -- u16 vendor; -+ u16 vendor, chip; - int ret = 0; - - fintek_config_mode_enable(fintek); -@@ -176,6 +176,7 @@ static int fintek_hw_detect(struct finte - - chip_major = fintek_cr_read(fintek, GCR_CHIP_ID_HI); - chip_minor = fintek_cr_read(fintek, GCR_CHIP_ID_LO); -+ chip = chip_major << 8 | chip_minor; - - vendor_major = fintek_cr_read(fintek, GCR_VENDOR_ID_HI); - vendor_minor = fintek_cr_read(fintek, GCR_VENDOR_ID_LO); -@@ -192,6 +193,15 @@ static int fintek_hw_detect(struct finte - fintek->chip_major = chip_major; - fintek->chip_minor = chip_minor; - fintek->chip_vendor = vendor; -+ -+ /* -+ * Newer reviews of this chipset uses port 8 instead of 5 -+ */ -+ if ((chip != 0x0408) || (chip != 0x0804)) -+ fintek->logical_dev_cir = LOGICAL_DEV_CIR_REV2; -+ else -+ fintek->logical_dev_cir = LOGICAL_DEV_CIR_REV1; -+ - spin_unlock_irqrestore(&fintek->fintek_lock, flags); - - return ret; -@@ -200,7 +210,7 @@ static int fintek_hw_detect(struct finte - static void fintek_cir_ldev_init(struct fintek_dev *fintek) - { - /* Select CIR logical device and enable */ -- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); -+ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); - fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); - - /* Write allocated CIR address and IRQ information to hardware */ -@@ -381,7 +391,7 @@ static irqreturn_t fintek_cir_isr(int ir - fit_dbg_verbose("%s firing", __func__); - - fintek_config_mode_enable(fintek); -- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); -+ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); - fintek_config_mode_disable(fintek); - - /* -@@ -422,7 +432,7 @@ static void fintek_enable_cir(struct fin - fintek_config_mode_enable(fintek); - - /* enable the CIR logical device */ -- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); -+ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); - fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); - - fintek_config_mode_disable(fintek); -@@ -439,7 +449,7 @@ static void fintek_disable_cir(struct fi - fintek_config_mode_enable(fintek); - - /* disable the CIR logical device */ -- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); -+ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); - fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN); - - fintek_config_mode_disable(fintek); -@@ -611,7 +621,7 @@ static int fintek_suspend(struct pnp_dev - fintek_config_mode_enable(fintek); - - /* disable cir logical dev */ -- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); -+ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); - fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN); - - fintek_config_mode_disable(fintek); -@@ -634,7 +644,7 @@ static int fintek_resume(struct pnp_dev - - /* Enable CIR logical device */ - fintek_config_mode_enable(fintek); -- fintek_select_logical_dev(fintek, LOGICAL_DEV_CIR); -+ fintek_select_logical_dev(fintek, fintek->logical_dev_cir); - fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN); - - fintek_config_mode_disable(fintek); -Index: linux-3.3.x86_64/drivers/media/rc/fintek-cir.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/rc/fintek-cir.h -+++ linux-3.3.x86_64/drivers/media/rc/fintek-cir.h -@@ -88,6 +88,7 @@ struct fintek_dev { - u8 chip_major; - u8 chip_minor; - u16 chip_vendor; -+ u8 logical_dev_cir; - - /* hardware features */ - bool hw_learning_capable; -@@ -172,7 +173,8 @@ struct fintek_dev { - #define LOGICAL_DEV_ENABLE 0x01 - - /* Logical device number of the CIR function */ --#define LOGICAL_DEV_CIR 0x05 -+#define LOGICAL_DEV_CIR_REV1 0x05 -+#define LOGICAL_DEV_CIR_REV2 0x08 - - /* CIR Logical Device (LDN 0x08) config registers */ - #define CIR_CR_COMMAND_INDEX 0x04 -Index: linux-3.3.x86_64/drivers/media/radio/radio-isa.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/radio/radio-isa.c -@@ -0,0 +1,340 @@ -+/* -+ * Framework for ISA radio drivers. -+ * This takes care of all the V4L2 scaffolding, allowing the ISA drivers -+ * to concentrate on the actual hardware operation. -+ * -+ * Copyright (C) 2012 Hans Verkuil -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -+ * 02110-1301 USA -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "radio-isa.h" -+ -+MODULE_AUTHOR("Hans Verkuil"); -+MODULE_DESCRIPTION("A framework for ISA radio drivers."); -+MODULE_LICENSE("GPL"); -+ -+#define FREQ_LOW (87U * 16000U) -+#define FREQ_HIGH (108U * 16000U) -+ -+static int radio_isa_querycap(struct file *file, void *priv, -+ struct v4l2_capability *v) -+{ -+ struct radio_isa_card *isa = video_drvdata(file); -+ -+ strlcpy(v->driver, isa->drv->driver.driver.name, sizeof(v->driver)); -+ strlcpy(v->card, isa->drv->card, sizeof(v->card)); -+ snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name); -+ -+ v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; -+ v->device_caps = v->capabilities | V4L2_CAP_DEVICE_CAPS; -+ return 0; -+} -+ -+static int radio_isa_g_tuner(struct file *file, void *priv, -+ struct v4l2_tuner *v) -+{ -+ struct radio_isa_card *isa = video_drvdata(file); -+ const struct radio_isa_ops *ops = isa->drv->ops; -+ -+ if (v->index > 0) -+ return -EINVAL; -+ -+ strlcpy(v->name, "FM", sizeof(v->name)); -+ v->type = V4L2_TUNER_RADIO; -+ v->rangelow = FREQ_LOW; -+ v->rangehigh = FREQ_HIGH; -+ v->capability = V4L2_TUNER_CAP_LOW; -+ if (isa->drv->has_stereo) -+ v->capability |= V4L2_TUNER_CAP_STEREO; -+ -+ if (ops->g_rxsubchans) -+ v->rxsubchans = ops->g_rxsubchans(isa); -+ else -+ v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; -+ v->audmode = isa->stereo ? V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO; -+ if (ops->g_signal) -+ v->signal = ops->g_signal(isa); -+ else -+ v->signal = (v->rxsubchans & V4L2_TUNER_SUB_STEREO) ? -+ 0xffff : 0; -+ return 0; -+} -+ -+static int radio_isa_s_tuner(struct file *file, void *priv, -+ struct v4l2_tuner *v) -+{ -+ struct radio_isa_card *isa = video_drvdata(file); -+ const struct radio_isa_ops *ops = isa->drv->ops; -+ -+ if (v->index) -+ return -EINVAL; -+ if (ops->s_stereo) { -+ isa->stereo = (v->audmode == V4L2_TUNER_MODE_STEREO); -+ return ops->s_stereo(isa, isa->stereo); -+ } -+ return 0; -+} -+ -+static int radio_isa_s_frequency(struct file *file, void *priv, -+ struct v4l2_frequency *f) -+{ -+ struct radio_isa_card *isa = video_drvdata(file); -+ int res; -+ -+ if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) -+ return -EINVAL; -+ f->frequency = clamp(f->frequency, FREQ_LOW, FREQ_HIGH); -+ res = isa->drv->ops->s_frequency(isa, f->frequency); -+ if (res == 0) -+ isa->freq = f->frequency; -+ return res; -+} -+ -+static int radio_isa_g_frequency(struct file *file, void *priv, -+ struct v4l2_frequency *f) -+{ -+ struct radio_isa_card *isa = video_drvdata(file); -+ -+ if (f->tuner != 0) -+ return -EINVAL; -+ f->type = V4L2_TUNER_RADIO; -+ f->frequency = isa->freq; -+ return 0; -+} -+ -+static int radio_isa_s_ctrl(struct v4l2_ctrl *ctrl) -+{ -+ struct radio_isa_card *isa = -+ container_of(ctrl->handler, struct radio_isa_card, hdl); -+ -+ switch (ctrl->id) { -+ case V4L2_CID_AUDIO_MUTE: -+ return isa->drv->ops->s_mute_volume(isa, ctrl->val, -+ isa->volume ? isa->volume->val : 0); -+ } -+ return -EINVAL; -+} -+ -+static int radio_isa_log_status(struct file *file, void *priv) -+{ -+ struct radio_isa_card *isa = video_drvdata(file); -+ -+ v4l2_info(&isa->v4l2_dev, "I/O Port = 0x%03x\n", isa->io); -+ v4l2_ctrl_handler_log_status(&isa->hdl, isa->v4l2_dev.name); -+ return 0; -+} -+ -+static int radio_isa_subscribe_event(struct v4l2_fh *fh, -+ struct v4l2_event_subscription *sub) -+{ -+ if (sub->type == V4L2_EVENT_CTRL) -+ return v4l2_event_subscribe(fh, sub, 0); -+ return -EINVAL; -+} -+ -+static const struct v4l2_ctrl_ops radio_isa_ctrl_ops = { -+ .s_ctrl = radio_isa_s_ctrl, -+}; -+ -+static const struct v4l2_file_operations radio_isa_fops = { -+ .owner = THIS_MODULE, -+ .open = v4l2_fh_open, -+ .release = v4l2_fh_release, -+ .poll = v4l2_ctrl_poll, -+ .unlocked_ioctl = video_ioctl2, -+}; -+ -+static const struct v4l2_ioctl_ops radio_isa_ioctl_ops = { -+ .vidioc_querycap = radio_isa_querycap, -+ .vidioc_g_tuner = radio_isa_g_tuner, -+ .vidioc_s_tuner = radio_isa_s_tuner, -+ .vidioc_g_frequency = radio_isa_g_frequency, -+ .vidioc_s_frequency = radio_isa_s_frequency, -+ .vidioc_log_status = radio_isa_log_status, -+ .vidioc_subscribe_event = radio_isa_subscribe_event, -+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -+}; -+ -+int radio_isa_match(struct device *pdev, unsigned int dev) -+{ -+ struct radio_isa_driver *drv = pdev->platform_data; -+ -+ return drv->probe || drv->io_params[dev] >= 0; -+} -+EXPORT_SYMBOL_GPL(radio_isa_match); -+ -+static bool radio_isa_valid_io(const struct radio_isa_driver *drv, int io) -+{ -+ int i; -+ -+ for (i = 0; i < drv->num_of_io_ports; i++) -+ if (drv->io_ports[i] == io) -+ return true; -+ return false; -+} -+ -+int radio_isa_probe(struct device *pdev, unsigned int dev) -+{ -+ struct radio_isa_driver *drv = pdev->platform_data; -+ const struct radio_isa_ops *ops = drv->ops; -+ struct v4l2_device *v4l2_dev; -+ struct radio_isa_card *isa; -+ int res; -+ -+ isa = drv->ops->alloc(); -+ if (isa == NULL) -+ return -ENOMEM; -+ dev_set_drvdata(pdev, isa); -+ isa->drv = drv; -+ isa->io = drv->io_params[dev]; -+ v4l2_dev = &isa->v4l2_dev; -+ strlcpy(v4l2_dev->name, dev_name(pdev), sizeof(v4l2_dev->name)); -+ -+ if (drv->probe && ops->probe) { -+ int i; -+ -+ for (i = 0; i < drv->num_of_io_ports; ++i) { -+ int io = drv->io_ports[i]; -+ -+ if (request_region(io, drv->region_size, v4l2_dev->name)) { -+ bool found = ops->probe(isa, io); -+ -+ release_region(io, drv->region_size); -+ if (found) { -+ isa->io = io; -+ break; -+ } -+ } -+ } -+ } -+ -+ if (!radio_isa_valid_io(drv, isa->io)) { -+ int i; -+ -+ if (isa->io < 0) -+ return -ENODEV; -+ v4l2_err(v4l2_dev, "you must set an I/O address with io=0x%03x", -+ drv->io_ports[0]); -+ for (i = 1; i < drv->num_of_io_ports; i++) -+ printk(KERN_CONT "/0x%03x", drv->io_ports[i]); -+ printk(KERN_CONT ".\n"); -+ kfree(isa); -+ return -EINVAL; -+ } -+ -+ if (!request_region(isa->io, drv->region_size, v4l2_dev->name)) { -+ v4l2_err(v4l2_dev, "port 0x%x already in use\n", isa->io); -+ kfree(isa); -+ return -EBUSY; -+ } -+ -+ res = v4l2_device_register(pdev, v4l2_dev); -+ if (res < 0) { -+ v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); -+ goto err_dev_reg; -+ } -+ -+ v4l2_ctrl_handler_init(&isa->hdl, 1); -+ isa->mute = v4l2_ctrl_new_std(&isa->hdl, &radio_isa_ctrl_ops, -+ V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); -+ if (drv->max_volume) -+ isa->volume = v4l2_ctrl_new_std(&isa->hdl, &radio_isa_ctrl_ops, -+ V4L2_CID_AUDIO_VOLUME, 0, drv->max_volume, 1, -+ drv->max_volume); -+ v4l2_dev->ctrl_handler = &isa->hdl; -+ if (isa->hdl.error) { -+ res = isa->hdl.error; -+ v4l2_err(v4l2_dev, "Could not register controls\n"); -+ goto err_hdl; -+ } -+ if (drv->max_volume) -+ v4l2_ctrl_cluster(2, &isa->mute); -+ v4l2_dev->ctrl_handler = &isa->hdl; -+ -+ mutex_init(&isa->lock); -+ isa->vdev.lock = &isa->lock; -+ strlcpy(isa->vdev.name, v4l2_dev->name, sizeof(isa->vdev.name)); -+ isa->vdev.v4l2_dev = v4l2_dev; -+ isa->vdev.fops = &radio_isa_fops; -+ isa->vdev.ioctl_ops = &radio_isa_ioctl_ops; -+ isa->vdev.release = video_device_release_empty; -+ set_bit(V4L2_FL_USE_FH_PRIO, &isa->vdev.flags); -+ video_set_drvdata(&isa->vdev, isa); -+ isa->freq = FREQ_LOW; -+ isa->stereo = drv->has_stereo; -+ -+ if (ops->init) -+ res = ops->init(isa); -+ if (!res) -+ res = v4l2_ctrl_handler_setup(&isa->hdl); -+ if (!res) -+ res = ops->s_frequency(isa, isa->freq); -+ if (!res && ops->s_stereo) -+ res = ops->s_stereo(isa, isa->stereo); -+ if (res < 0) { -+ v4l2_err(v4l2_dev, "Could not setup card\n"); -+ goto err_node_reg; -+ } -+ res = video_register_device(&isa->vdev, VFL_TYPE_RADIO, -+ drv->radio_nr_params[dev]); -+ if (res < 0) { -+ v4l2_err(v4l2_dev, "Could not register device node\n"); -+ goto err_node_reg; -+ } -+ -+ v4l2_info(v4l2_dev, "Initialized radio card %s on port 0x%03x\n", -+ drv->card, isa->io); -+ return 0; -+ -+err_node_reg: -+ v4l2_ctrl_handler_free(&isa->hdl); -+err_hdl: -+ v4l2_device_unregister(&isa->v4l2_dev); -+err_dev_reg: -+ release_region(isa->io, drv->region_size); -+ kfree(isa); -+ return res; -+} -+EXPORT_SYMBOL_GPL(radio_isa_probe); -+ -+int radio_isa_remove(struct device *pdev, unsigned int dev) -+{ -+ struct radio_isa_card *isa = dev_get_drvdata(pdev); -+ const struct radio_isa_ops *ops = isa->drv->ops; -+ -+ ops->s_mute_volume(isa, true, isa->volume ? isa->volume->cur.val : 0); -+ video_unregister_device(&isa->vdev); -+ v4l2_ctrl_handler_free(&isa->hdl); -+ v4l2_device_unregister(&isa->v4l2_dev); -+ release_region(isa->io, isa->drv->region_size); -+ v4l2_info(&isa->v4l2_dev, "Removed radio card %s\n", isa->drv->card); -+ kfree(isa); -+ return 0; -+} -+EXPORT_SYMBOL_GPL(radio_isa_remove); -Index: linux-3.3.x86_64/drivers/media/radio/radio-isa.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/radio/radio-isa.h -@@ -0,0 +1,105 @@ -+/* -+ * Framework for ISA radio drivers. -+ * This takes care of all the V4L2 scaffolding, allowing the ISA drivers -+ * to concentrate on the actual hardware operation. -+ * -+ * Copyright (C) 2012 Hans Verkuil -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -+ * 02110-1301 USA -+ */ -+ -+#ifndef _RADIO_ISA_H_ -+#define _RADIO_ISA_H_ -+ -+#include -+#include -+#include -+#include -+ -+struct radio_isa_driver; -+struct radio_isa_ops; -+ -+/* Core structure for radio ISA cards */ -+struct radio_isa_card { -+ const struct radio_isa_driver *drv; -+ struct v4l2_device v4l2_dev; -+ struct v4l2_ctrl_handler hdl; -+ struct video_device vdev; -+ struct mutex lock; -+ const struct radio_isa_ops *ops; -+ struct { /* mute/volume cluster */ -+ struct v4l2_ctrl *mute; -+ struct v4l2_ctrl *volume; -+ }; -+ /* I/O port */ -+ int io; -+ -+ /* Card is in stereo audio mode */ -+ bool stereo; -+ /* Current frequency */ -+ u32 freq; -+}; -+ -+struct radio_isa_ops { -+ /* Allocate and initialize a radio_isa_card struct */ -+ struct radio_isa_card *(*alloc)(void); -+ /* Probe whether a card is present at the given port */ -+ bool (*probe)(struct radio_isa_card *isa, int io); -+ /* Special card initialization can be done here, this is called after -+ * the standard controls are registered, but before they are setup, -+ * thus allowing drivers to add their own controls here. */ -+ int (*init)(struct radio_isa_card *isa); -+ /* Set mute and volume. */ -+ int (*s_mute_volume)(struct radio_isa_card *isa, bool mute, int volume); -+ /* Set frequency */ -+ int (*s_frequency)(struct radio_isa_card *isa, u32 freq); -+ /* Set stereo/mono audio mode */ -+ int (*s_stereo)(struct radio_isa_card *isa, bool stereo); -+ /* Get rxsubchans value for VIDIOC_G_TUNER */ -+ u32 (*g_rxsubchans)(struct radio_isa_card *isa); -+ /* Get the signal strength for VIDIOC_G_TUNER */ -+ u32 (*g_signal)(struct radio_isa_card *isa); -+}; -+ -+/* Top level structure needed to instantiate the cards */ -+struct radio_isa_driver { -+ struct isa_driver driver; -+ const struct radio_isa_ops *ops; -+ /* The module_param_array with the specified I/O ports */ -+ int *io_params; -+ /* The module_param_array with the radio_nr values */ -+ int *radio_nr_params; -+ /* Whether we should probe for possible cards */ -+ bool probe; -+ /* The list of possible I/O ports */ -+ const int *io_ports; -+ /* The size of that list */ -+ int num_of_io_ports; -+ /* The region size to request */ -+ unsigned region_size; -+ /* The name of the card */ -+ const char *card; -+ /* Card can capture stereo audio */ -+ bool has_stereo; -+ /* The maximum volume for the volume control. If 0, then there -+ is no volume control possible. */ -+ int max_volume; -+}; -+ -+int radio_isa_match(struct device *pdev, unsigned int dev); -+int radio_isa_probe(struct device *pdev, unsigned int dev); -+int radio_isa_remove(struct device *pdev, unsigned int dev); -+ -+#endif -Index: linux-3.3.x86_64/drivers/media/radio/radio-aimslab.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/radio/radio-aimslab.c -+++ linux-3.3.x86_64/drivers/media/radio/radio-aimslab.c -@@ -1,16 +1,13 @@ --/* radiotrack (radioreveal) driver for Linux radio support -- * (c) 1997 M. Kirkwood -+/* -+ * AimsLab RadioTrack (aka RadioVeveal) driver -+ * -+ * Copyright 1997 M. Kirkwood -+ * -+ * Converted to the radio-isa framework by Hans Verkuil - * Converted to V4L2 API by Mauro Carvalho Chehab - * Converted to new API by Alan Cox - * Various bugfixes and enhancements by Russell Kroll - * -- * History: -- * 1999-02-24 Russell Kroll -- * Fine tuning/VIDEO_TUNER_LOW -- * Frequency range expanded to start at 87 MHz -- * -- * TODO: Allow for more than one of these foolish entities :-) -- * - * Notes on the hardware (reverse engineered from other peoples' - * reverse engineering of AIMS' code :-) - * -@@ -26,6 +23,7 @@ - * wait(a_wee_while); - * out(port, stop_changing_the_volume); - * -+ * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool. - */ - - #include /* Modules */ -@@ -34,401 +32,179 @@ - #include /* msleep */ - #include /* kernel radio structs */ - #include /* outb, outb_p */ -+#include - #include - #include -+#include -+#include "radio-isa.h" - --MODULE_AUTHOR("M.Kirkwood"); -+MODULE_AUTHOR("M. Kirkwood"); - MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card."); - MODULE_LICENSE("GPL"); --MODULE_VERSION("0.0.3"); -+MODULE_VERSION("1.0.0"); - - #ifndef CONFIG_RADIO_RTRACK_PORT - #define CONFIG_RADIO_RTRACK_PORT -1 - #endif - --static int io = CONFIG_RADIO_RTRACK_PORT; --static int radio_nr = -1; -+#define RTRACK_MAX 2 - --module_param(io, int, 0); --MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20f or 0x30f)"); --module_param(radio_nr, int, 0); -+static int io[RTRACK_MAX] = { [0] = CONFIG_RADIO_RTRACK_PORT, -+ [1 ... (RTRACK_MAX - 1)] = -1 }; -+static int radio_nr[RTRACK_MAX] = { [0 ... (RTRACK_MAX - 1)] = -1 }; -+ -+module_param_array(io, int, NULL, 0444); -+MODULE_PARM_DESC(io, "I/O addresses of the RadioTrack card (0x20f or 0x30f)"); -+module_param_array(radio_nr, int, NULL, 0444); -+MODULE_PARM_DESC(radio_nr, "Radio device numbers"); - --struct rtrack --{ -- struct v4l2_device v4l2_dev; -- struct video_device vdev; -- int port; -+struct rtrack { -+ struct radio_isa_card isa; - int curvol; -- unsigned long curfreq; -- int muted; -- int io; -- struct mutex lock; - }; - --static struct rtrack rtrack_card; -- --/* local things */ -- --static void rt_decvol(struct rtrack *rt) --{ -- outb(0x58, rt->io); /* volume down + sigstr + on */ -- msleep(100); -- outb(0xd8, rt->io); /* volume steady + sigstr + on */ --} -- --static void rt_incvol(struct rtrack *rt) --{ -- outb(0x98, rt->io); /* volume up + sigstr + on */ -- msleep(100); -- outb(0xd8, rt->io); /* volume steady + sigstr + on */ --} -- --static void rt_mute(struct rtrack *rt) --{ -- rt->muted = 1; -- mutex_lock(&rt->lock); -- outb(0xd0, rt->io); /* volume steady, off */ -- mutex_unlock(&rt->lock); --} -- --static int rt_setvol(struct rtrack *rt, int vol) -+static struct radio_isa_card *rtrack_alloc(void) - { -- int i; -- -- mutex_lock(&rt->lock); -- -- if (vol == rt->curvol) { /* requested volume = current */ -- if (rt->muted) { /* user is unmuting the card */ -- rt->muted = 0; -- outb(0xd8, rt->io); /* enable card */ -- } -- mutex_unlock(&rt->lock); -- return 0; -- } -- -- if (vol == 0) { /* volume = 0 means mute the card */ -- outb(0x48, rt->io); /* volume down but still "on" */ -- msleep(2000); /* make sure it's totally down */ -- outb(0xd0, rt->io); /* volume steady, off */ -- rt->curvol = 0; /* track the volume state! */ -- mutex_unlock(&rt->lock); -- return 0; -- } -- -- rt->muted = 0; -- if (vol > rt->curvol) -- for (i = rt->curvol; i < vol; i++) -- rt_incvol(rt); -- else -- for (i = rt->curvol; i > vol; i--) -- rt_decvol(rt); -+ struct rtrack *rt = kzalloc(sizeof(struct rtrack), GFP_KERNEL); - -- rt->curvol = vol; -- mutex_unlock(&rt->lock); -- return 0; -+ if (rt) -+ rt->curvol = 0xff; -+ return rt ? &rt->isa : NULL; - } - --/* the 128+64 on these outb's is to keep the volume stable while tuning -- * without them, the volume _will_ creep up with each frequency change -- * and bit 4 (+16) is to keep the signal strength meter enabled -+/* The 128+64 on these outb's is to keep the volume stable while tuning. -+ * Without them, the volume _will_ creep up with each frequency change -+ * and bit 4 (+16) is to keep the signal strength meter enabled. - */ - --static void send_0_byte(struct rtrack *rt) -+static void send_0_byte(struct radio_isa_card *isa, int on) - { -- if (rt->curvol == 0 || rt->muted) { -- outb_p(128+64+16+ 1, rt->io); /* wr-enable + data low */ -- outb_p(128+64+16+2+1, rt->io); /* clock */ -- } -- else { -- outb_p(128+64+16+8+ 1, rt->io); /* on + wr-enable + data low */ -- outb_p(128+64+16+8+2+1, rt->io); /* clock */ -- } -+ outb_p(128+64+16+on+1, isa->io); /* wr-enable + data low */ -+ outb_p(128+64+16+on+2+1, isa->io); /* clock */ - msleep(1); - } - --static void send_1_byte(struct rtrack *rt) -+static void send_1_byte(struct radio_isa_card *isa, int on) - { -- if (rt->curvol == 0 || rt->muted) { -- outb_p(128+64+16+4 +1, rt->io); /* wr-enable+data high */ -- outb_p(128+64+16+4+2+1, rt->io); /* clock */ -- } -- else { -- outb_p(128+64+16+8+4 +1, rt->io); /* on+wr-enable+data high */ -- outb_p(128+64+16+8+4+2+1, rt->io); /* clock */ -- } -- -+ outb_p(128+64+16+on+4+1, isa->io); /* wr-enable+data high */ -+ outb_p(128+64+16+on+4+2+1, isa->io); /* clock */ - msleep(1); - } - --static int rt_setfreq(struct rtrack *rt, unsigned long freq) -+static int rtrack_s_frequency(struct radio_isa_card *isa, u32 freq) - { -+ int on = v4l2_ctrl_g_ctrl(isa->mute) ? 0 : 8; - int i; - -- mutex_lock(&rt->lock); /* Stop other ops interfering */ -- -- rt->curfreq = freq; -- -- /* now uses VIDEO_TUNER_LOW for fine tuning */ -- - freq += 171200; /* Add 10.7 MHz IF */ - freq /= 800; /* Convert to 50 kHz units */ - -- send_0_byte(rt); /* 0: LSB of frequency */ -+ send_0_byte(isa, on); /* 0: LSB of frequency */ - - for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ - if (freq & (1 << i)) -- send_1_byte(rt); -+ send_1_byte(isa, on); - else -- send_0_byte(rt); -+ send_0_byte(isa, on); - -- send_0_byte(rt); /* 14: test bit - always 0 */ -- send_0_byte(rt); /* 15: test bit - always 0 */ -+ send_0_byte(isa, on); /* 14: test bit - always 0 */ -+ send_0_byte(isa, on); /* 15: test bit - always 0 */ - -- send_0_byte(rt); /* 16: band data 0 - always 0 */ -- send_0_byte(rt); /* 17: band data 1 - always 0 */ -- send_0_byte(rt); /* 18: band data 2 - always 0 */ -- send_0_byte(rt); /* 19: time base - always 0 */ -- -- send_0_byte(rt); /* 20: spacing (0 = 25 kHz) */ -- send_1_byte(rt); /* 21: spacing (1 = 25 kHz) */ -- send_0_byte(rt); /* 22: spacing (0 = 25 kHz) */ -- send_1_byte(rt); /* 23: AM/FM (FM = 1, always) */ -- -- if (rt->curvol == 0 || rt->muted) -- outb(0xd0, rt->io); /* volume steady + sigstr */ -- else -- outb(0xd8, rt->io); /* volume steady + sigstr + on */ -+ send_0_byte(isa, on); /* 16: band data 0 - always 0 */ -+ send_0_byte(isa, on); /* 17: band data 1 - always 0 */ -+ send_0_byte(isa, on); /* 18: band data 2 - always 0 */ -+ send_0_byte(isa, on); /* 19: time base - always 0 */ - -- mutex_unlock(&rt->lock); -+ send_0_byte(isa, on); /* 20: spacing (0 = 25 kHz) */ -+ send_1_byte(isa, on); /* 21: spacing (1 = 25 kHz) */ -+ send_0_byte(isa, on); /* 22: spacing (0 = 25 kHz) */ -+ send_1_byte(isa, on); /* 23: AM/FM (FM = 1, always) */ - -+ outb(0xd0 + on, isa->io); /* volume steady + sigstr */ - return 0; - } - --static int rt_getsigstr(struct rtrack *rt) -+static u32 rtrack_g_signal(struct radio_isa_card *isa) - { -- int sig = 1; -- -- mutex_lock(&rt->lock); -- if (inb(rt->io) & 2) /* bit set = no signal present */ -- sig = 0; -- mutex_unlock(&rt->lock); -- return sig; --} -- --static int vidioc_querycap(struct file *file, void *priv, -- struct v4l2_capability *v) --{ -- strlcpy(v->driver, "radio-aimslab", sizeof(v->driver)); -- strlcpy(v->card, "RadioTrack", sizeof(v->card)); -- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); -- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; -- return 0; --} -- --static int vidioc_g_tuner(struct file *file, void *priv, -- struct v4l2_tuner *v) --{ -- struct rtrack *rt = video_drvdata(file); -- -- if (v->index > 0) -- return -EINVAL; -- -- strlcpy(v->name, "FM", sizeof(v->name)); -- v->type = V4L2_TUNER_RADIO; -- v->rangelow = 87 * 16000; -- v->rangehigh = 108 * 16000; -- v->rxsubchans = V4L2_TUNER_SUB_MONO; -- v->capability = V4L2_TUNER_CAP_LOW; -- v->audmode = V4L2_TUNER_MODE_MONO; -- v->signal = 0xffff * rt_getsigstr(rt); -- return 0; -+ /* bit set = no signal present */ -+ return 0xffff * !(inb(isa->io) & 2); - } - --static int vidioc_s_tuner(struct file *file, void *priv, -- struct v4l2_tuner *v) -+static int rtrack_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) - { -- return v->index ? -EINVAL : 0; --} -+ struct rtrack *rt = container_of(isa, struct rtrack, isa); -+ int curvol = rt->curvol; - --static int vidioc_s_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) --{ -- struct rtrack *rt = video_drvdata(file); -- -- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) -- return -EINVAL; -- rt_setfreq(rt, f->frequency); -- return 0; --} -- --static int vidioc_g_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) --{ -- struct rtrack *rt = video_drvdata(file); -- -- if (f->tuner != 0) -- return -EINVAL; -- f->type = V4L2_TUNER_RADIO; -- f->frequency = rt->curfreq; -- return 0; --} -- --static int vidioc_queryctrl(struct file *file, void *priv, -- struct v4l2_queryctrl *qc) --{ -- switch (qc->id) { -- case V4L2_CID_AUDIO_MUTE: -- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); -- case V4L2_CID_AUDIO_VOLUME: -- return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff); -- } -- return -EINVAL; --} -- --static int vidioc_g_ctrl(struct file *file, void *priv, -- struct v4l2_control *ctrl) --{ -- struct rtrack *rt = video_drvdata(file); -- -- switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- ctrl->value = rt->muted; -- return 0; -- case V4L2_CID_AUDIO_VOLUME: -- ctrl->value = rt->curvol; -+ if (mute) { -+ outb(0xd0, isa->io); /* volume steady + sigstr + off */ - return 0; - } -- return -EINVAL; --} -- --static int vidioc_s_ctrl(struct file *file, void *priv, -- struct v4l2_control *ctrl) --{ -- struct rtrack *rt = video_drvdata(file); -- -- switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- if (ctrl->value) -- rt_mute(rt); -- else -- rt_setvol(rt, rt->curvol); -- return 0; -- case V4L2_CID_AUDIO_VOLUME: -- rt_setvol(rt, ctrl->value); -- return 0; -+ if (vol == 0) { /* volume = 0 means mute the card */ -+ outb(0x48, isa->io); /* volume down but still "on" */ -+ msleep(curvol * 3); /* make sure it's totally down */ -+ } else if (curvol < vol) { -+ outb(0x98, isa->io); /* volume up + sigstr + on */ -+ for (; curvol < vol; curvol++) -+ udelay(3000); -+ } else if (curvol > vol) { -+ outb(0x58, isa->io); /* volume down + sigstr + on */ -+ for (; curvol > vol; curvol--) -+ udelay(3000); - } -- return -EINVAL; --} -- --static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) --{ -- *i = 0; -+ outb(0xd8, isa->io); /* volume steady + sigstr + on */ -+ rt->curvol = vol; - return 0; - } - --static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) --{ -- return i ? -EINVAL : 0; --} -- --static int vidioc_g_audio(struct file *file, void *priv, -- struct v4l2_audio *a) -+/* Mute card - prevents noisy bootups */ -+static int rtrack_initialize(struct radio_isa_card *isa) - { -- a->index = 0; -- strlcpy(a->name, "Radio", sizeof(a->name)); -- a->capability = V4L2_AUDCAP_STEREO; -+ /* this ensures that the volume is all the way up */ -+ outb(0x90, isa->io); /* volume up but still "on" */ -+ msleep(3000); /* make sure it's totally up */ -+ outb(0xc0, isa->io); /* steady volume, mute card */ - return 0; - } - --static int vidioc_s_audio(struct file *file, void *priv, -- struct v4l2_audio *a) --{ -- return a->index ? -EINVAL : 0; --} -- --static const struct v4l2_file_operations rtrack_fops = { -- .owner = THIS_MODULE, -- .unlocked_ioctl = video_ioctl2, -+static const struct radio_isa_ops rtrack_ops = { -+ .alloc = rtrack_alloc, -+ .init = rtrack_initialize, -+ .s_mute_volume = rtrack_s_mute_volume, -+ .s_frequency = rtrack_s_frequency, -+ .g_signal = rtrack_g_signal, - }; - --static const struct v4l2_ioctl_ops rtrack_ioctl_ops = { -- .vidioc_querycap = vidioc_querycap, -- .vidioc_g_tuner = vidioc_g_tuner, -- .vidioc_s_tuner = vidioc_s_tuner, -- .vidioc_g_audio = vidioc_g_audio, -- .vidioc_s_audio = vidioc_s_audio, -- .vidioc_g_input = vidioc_g_input, -- .vidioc_s_input = vidioc_s_input, -- .vidioc_g_frequency = vidioc_g_frequency, -- .vidioc_s_frequency = vidioc_s_frequency, -- .vidioc_queryctrl = vidioc_queryctrl, -- .vidioc_g_ctrl = vidioc_g_ctrl, -- .vidioc_s_ctrl = vidioc_s_ctrl, -+static const int rtrack_ioports[] = { 0x20f, 0x30f }; -+ -+static struct radio_isa_driver rtrack_driver = { -+ .driver = { -+ .match = radio_isa_match, -+ .probe = radio_isa_probe, -+ .remove = radio_isa_remove, -+ .driver = { -+ .name = "radio-aimslab", -+ }, -+ }, -+ .io_params = io, -+ .radio_nr_params = radio_nr, -+ .io_ports = rtrack_ioports, -+ .num_of_io_ports = ARRAY_SIZE(rtrack_ioports), -+ .region_size = 2, -+ .card = "AIMSlab RadioTrack/RadioReveal", -+ .ops = &rtrack_ops, -+ .has_stereo = true, -+ .max_volume = 0xff, - }; - - static int __init rtrack_init(void) - { -- struct rtrack *rt = &rtrack_card; -- struct v4l2_device *v4l2_dev = &rt->v4l2_dev; -- int res; -- -- strlcpy(v4l2_dev->name, "rtrack", sizeof(v4l2_dev->name)); -- rt->io = io; -- -- if (rt->io == -1) { -- v4l2_err(v4l2_dev, "you must set an I/O address with io=0x20f or 0x30f\n"); -- return -EINVAL; -- } -- -- if (!request_region(rt->io, 2, "rtrack")) { -- v4l2_err(v4l2_dev, "port 0x%x already in use\n", rt->io); -- return -EBUSY; -- } -- -- res = v4l2_device_register(NULL, v4l2_dev); -- if (res < 0) { -- release_region(rt->io, 2); -- v4l2_err(v4l2_dev, "could not register v4l2_device\n"); -- return res; -- } -- -- strlcpy(rt->vdev.name, v4l2_dev->name, sizeof(rt->vdev.name)); -- rt->vdev.v4l2_dev = v4l2_dev; -- rt->vdev.fops = &rtrack_fops; -- rt->vdev.ioctl_ops = &rtrack_ioctl_ops; -- rt->vdev.release = video_device_release_empty; -- video_set_drvdata(&rt->vdev, rt); -- -- /* Set up the I/O locking */ -- -- mutex_init(&rt->lock); -- -- /* mute card - prevents noisy bootups */ -- -- /* this ensures that the volume is all the way down */ -- outb(0x48, rt->io); /* volume down but still "on" */ -- msleep(2000); /* make sure it's totally down */ -- outb(0xc0, rt->io); /* steady volume, mute card */ -- -- if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -- v4l2_device_unregister(&rt->v4l2_dev); -- release_region(rt->io, 2); -- return -EINVAL; -- } -- v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n"); -- -- return 0; -+ return isa_register_driver(&rtrack_driver.driver, RTRACK_MAX); - } - - static void __exit rtrack_exit(void) - { -- struct rtrack *rt = &rtrack_card; -- -- video_unregister_device(&rt->vdev); -- v4l2_device_unregister(&rt->v4l2_dev); -- release_region(rt->io, 2); -+ isa_unregister_driver(&rtrack_driver.driver); - } - - module_init(rtrack_init); - module_exit(rtrack_exit); -- -Index: linux-3.3.x86_64/drivers/media/radio/radio-aztech.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/radio/radio-aztech.c -+++ linux-3.3.x86_64/drivers/media/radio/radio-aztech.c -@@ -1,5 +1,7 @@ --/* radio-aztech.c - Aztech radio card driver for Linux 2.2 -+/* -+ * radio-aztech.c - Aztech radio card driver - * -+ * Converted to the radio-isa framework by Hans Verkuil - * Converted to V4L2 API by Mauro Carvalho Chehab - * Adapted to support the Video for Linux API by - * Russell Kroll . Based on original tuner code by: -@@ -10,19 +12,7 @@ - * Scott McGrath (smcgrath@twilight.vtc.vsc.edu) - * William McGrath (wmcgrath@twilight.vtc.vsc.edu) - * -- * The basis for this code may be found at http://bigbang.vtc.vsc.edu/fmradio/ -- * along with more information on the card itself. -- * -- * History: -- * 1999-02-24 Russell Kroll -- * Fine tuning/VIDEO_TUNER_LOW -- * Range expanded to 87-108 MHz (from 87.9-107.8) -- * -- * Notable changes from the original source: -- * - includes stripped down to the essentials -- * - for loops used as delays replaced with udelay() -- * - #defines removed, changed to static values -- * - tuning structure changed - no more character arrays, other changes -+ * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool. - */ - - #include /* Modules */ -@@ -31,126 +21,72 @@ - #include /* udelay */ - #include /* kernel radio structs */ - #include /* outb, outb_p */ -+#include - #include - #include -+#include -+#include "radio-isa.h" - - MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); - MODULE_DESCRIPTION("A driver for the Aztech radio card."); - MODULE_LICENSE("GPL"); --MODULE_VERSION("0.0.3"); -+MODULE_VERSION("1.0.0"); - - /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ -- - #ifndef CONFIG_RADIO_AZTECH_PORT - #define CONFIG_RADIO_AZTECH_PORT -1 - #endif - --static int io = CONFIG_RADIO_AZTECH_PORT; --static int radio_nr = -1; --static int radio_wait_time = 1000; -- --module_param(io, int, 0); --module_param(radio_nr, int, 0); --MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)"); -+#define AZTECH_MAX 2 - --struct aztech --{ -- struct v4l2_device v4l2_dev; -- struct video_device vdev; -- int io; -+static int io[AZTECH_MAX] = { [0] = CONFIG_RADIO_AZTECH_PORT, -+ [1 ... (AZTECH_MAX - 1)] = -1 }; -+static int radio_nr[AZTECH_MAX] = { [0 ... (AZTECH_MAX - 1)] = -1 }; -+static const int radio_wait_time = 1000; -+ -+module_param_array(io, int, NULL, 0444); -+MODULE_PARM_DESC(io, "I/O addresses of the Aztech card (0x350 or 0x358)"); -+module_param_array(radio_nr, int, NULL, 0444); -+MODULE_PARM_DESC(radio_nr, "Radio device numbers"); -+ -+struct aztech { -+ struct radio_isa_card isa; - int curvol; -- unsigned long curfreq; -- int stereo; -- struct mutex lock; - }; - --static struct aztech aztech_card; -- --static int volconvert(int level) --{ -- level >>= 14; /* Map 16bits down to 2 bit */ -- level &= 3; -- -- /* convert to card-friendly values */ -- switch (level) { -- case 0: -- return 0; -- case 1: -- return 1; -- case 2: -- return 4; -- case 3: -- return 5; -- } -- return 0; /* Quieten gcc */ --} -- - static void send_0_byte(struct aztech *az) - { - udelay(radio_wait_time); -- outb_p(2 + volconvert(az->curvol), az->io); -- outb_p(64 + 2 + volconvert(az->curvol), az->io); -+ outb_p(2 + az->curvol, az->isa.io); -+ outb_p(64 + 2 + az->curvol, az->isa.io); - } - - static void send_1_byte(struct aztech *az) - { -- udelay (radio_wait_time); -- outb_p(128 + 2 + volconvert(az->curvol), az->io); -- outb_p(128 + 64 + 2 + volconvert(az->curvol), az->io); --} -- --static int az_setvol(struct aztech *az, int vol) --{ -- mutex_lock(&az->lock); -- outb(volconvert(vol), az->io); -- mutex_unlock(&az->lock); -- return 0; --} -- --/* thanks to Michael Dwyer for giving me a dose of clues in -- * the signal strength department.. -- * -- * This card has a stereo bit - bit 0 set = mono, not set = stereo -- * It also has a "signal" bit - bit 1 set = bad signal, not set = good -- * -- */ -- --static int az_getsigstr(struct aztech *az) --{ -- int sig = 1; -- -- mutex_lock(&az->lock); -- if (inb(az->io) & 2) /* bit set = no signal present */ -- sig = 0; -- mutex_unlock(&az->lock); -- return sig; -+ udelay(radio_wait_time); -+ outb_p(128 + 2 + az->curvol, az->isa.io); -+ outb_p(128 + 64 + 2 + az->curvol, az->isa.io); - } - --static int az_getstereo(struct aztech *az) -+static struct radio_isa_card *aztech_alloc(void) - { -- int stereo = 1; -+ struct aztech *az = kzalloc(sizeof(*az), GFP_KERNEL); - -- mutex_lock(&az->lock); -- if (inb(az->io) & 1) /* bit set = mono */ -- stereo = 0; -- mutex_unlock(&az->lock); -- return stereo; -+ return az ? &az->isa : NULL; - } - --static int az_setfreq(struct aztech *az, unsigned long frequency) -+static int aztech_s_frequency(struct radio_isa_card *isa, u32 freq) - { -+ struct aztech *az = container_of(isa, struct aztech, isa); - int i; - -- mutex_lock(&az->lock); -- -- az->curfreq = frequency; -- frequency += 171200; /* Add 10.7 MHz IF */ -- frequency /= 800; /* Convert to 50 kHz units */ -+ freq += 171200; /* Add 10.7 MHz IF */ -+ freq /= 800; /* Convert to 50 kHz units */ - - send_0_byte(az); /* 0: LSB of frequency */ - - for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ -- if (frequency & (1 << i)) -+ if (freq & (1 << i)) - send_1_byte(az); - else - send_0_byte(az); -@@ -158,7 +94,7 @@ static int az_setfreq(struct aztech *az, - send_0_byte(az); /* 14: test bit - always 0 */ - send_0_byte(az); /* 15: test bit - always 0 */ - send_0_byte(az); /* 16: band data 0 - always 0 */ -- if (az->stereo) /* 17: stereo (1 to enable) */ -+ if (isa->stereo) /* 17: stereo (1 to enable) */ - send_1_byte(az); - else - send_0_byte(az); -@@ -173,225 +109,77 @@ static int az_setfreq(struct aztech *az, - /* latch frequency */ - - udelay(radio_wait_time); -- outb_p(128 + 64 + volconvert(az->curvol), az->io); -- -- mutex_unlock(&az->lock); -- -- return 0; --} -+ outb_p(128 + 64 + az->curvol, az->isa.io); - --static int vidioc_querycap(struct file *file, void *priv, -- struct v4l2_capability *v) --{ -- strlcpy(v->driver, "radio-aztech", sizeof(v->driver)); -- strlcpy(v->card, "Aztech Radio", sizeof(v->card)); -- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); -- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; - return 0; - } - --static int vidioc_g_tuner(struct file *file, void *priv, -- struct v4l2_tuner *v) --{ -- struct aztech *az = video_drvdata(file); -- -- if (v->index > 0) -- return -EINVAL; -- -- strlcpy(v->name, "FM", sizeof(v->name)); -- v->type = V4L2_TUNER_RADIO; -- -- v->rangelow = 87 * 16000; -- v->rangehigh = 108 * 16000; -- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; -- v->capability = V4L2_TUNER_CAP_LOW; -- if (az_getstereo(az)) -- v->audmode = V4L2_TUNER_MODE_STEREO; -- else -- v->audmode = V4L2_TUNER_MODE_MONO; -- v->signal = 0xFFFF * az_getsigstr(az); -- -- return 0; --} -- --static int vidioc_s_tuner(struct file *file, void *priv, -- struct v4l2_tuner *v) --{ -- return v->index ? -EINVAL : 0; --} -- --static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) --{ -- *i = 0; -- return 0; --} -- --static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) --{ -- return i ? -EINVAL : 0; --} -- --static int vidioc_g_audio(struct file *file, void *priv, -- struct v4l2_audio *a) -+/* thanks to Michael Dwyer for giving me a dose of clues in -+ * the signal strength department.. -+ * -+ * This card has a stereo bit - bit 0 set = mono, not set = stereo -+ */ -+static u32 aztech_g_rxsubchans(struct radio_isa_card *isa) - { -- a->index = 0; -- strlcpy(a->name, "Radio", sizeof(a->name)); -- a->capability = V4L2_AUDCAP_STEREO; -- return 0; -+ if (inb(isa->io) & 1) -+ return V4L2_TUNER_SUB_MONO; -+ return V4L2_TUNER_SUB_STEREO; - } - --static int vidioc_s_audio(struct file *file, void *priv, -- struct v4l2_audio *a) -+static int aztech_s_stereo(struct radio_isa_card *isa, bool stereo) - { -- return a->index ? -EINVAL : 0; -+ return aztech_s_frequency(isa, isa->freq); - } - --static int vidioc_s_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) -+static int aztech_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) - { -- struct aztech *az = video_drvdata(file); -+ struct aztech *az = container_of(isa, struct aztech, isa); - -- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) -- return -EINVAL; -- az_setfreq(az, f->frequency); -+ if (mute) -+ vol = 0; -+ az->curvol = (vol & 1) + ((vol & 2) << 1); -+ outb(az->curvol, isa->io); - return 0; - } - --static int vidioc_g_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) --{ -- struct aztech *az = video_drvdata(file); -- -- if (f->tuner != 0) -- return -EINVAL; -- f->type = V4L2_TUNER_RADIO; -- f->frequency = az->curfreq; -- return 0; --} -- --static int vidioc_queryctrl(struct file *file, void *priv, -- struct v4l2_queryctrl *qc) --{ -- switch (qc->id) { -- case V4L2_CID_AUDIO_MUTE: -- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); -- case V4L2_CID_AUDIO_VOLUME: -- return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff); -- } -- return -EINVAL; --} -- --static int vidioc_g_ctrl(struct file *file, void *priv, -- struct v4l2_control *ctrl) --{ -- struct aztech *az = video_drvdata(file); -- -- switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- if (az->curvol == 0) -- ctrl->value = 1; -- else -- ctrl->value = 0; -- return 0; -- case V4L2_CID_AUDIO_VOLUME: -- ctrl->value = az->curvol * 6554; -- return 0; -- } -- return -EINVAL; --} -- --static int vidioc_s_ctrl(struct file *file, void *priv, -- struct v4l2_control *ctrl) --{ -- struct aztech *az = video_drvdata(file); -- -- switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- if (ctrl->value) -- az_setvol(az, 0); -- else -- az_setvol(az, az->curvol); -- return 0; -- case V4L2_CID_AUDIO_VOLUME: -- az_setvol(az, ctrl->value); -- return 0; -- } -- return -EINVAL; --} -- --static const struct v4l2_file_operations aztech_fops = { -- .owner = THIS_MODULE, -- .unlocked_ioctl = video_ioctl2, -+static const struct radio_isa_ops aztech_ops = { -+ .alloc = aztech_alloc, -+ .s_mute_volume = aztech_s_mute_volume, -+ .s_frequency = aztech_s_frequency, -+ .s_stereo = aztech_s_stereo, -+ .g_rxsubchans = aztech_g_rxsubchans, - }; - --static const struct v4l2_ioctl_ops aztech_ioctl_ops = { -- .vidioc_querycap = vidioc_querycap, -- .vidioc_g_tuner = vidioc_g_tuner, -- .vidioc_s_tuner = vidioc_s_tuner, -- .vidioc_g_audio = vidioc_g_audio, -- .vidioc_s_audio = vidioc_s_audio, -- .vidioc_g_input = vidioc_g_input, -- .vidioc_s_input = vidioc_s_input, -- .vidioc_g_frequency = vidioc_g_frequency, -- .vidioc_s_frequency = vidioc_s_frequency, -- .vidioc_queryctrl = vidioc_queryctrl, -- .vidioc_g_ctrl = vidioc_g_ctrl, -- .vidioc_s_ctrl = vidioc_s_ctrl, -+static const int aztech_ioports[] = { 0x350, 0x358 }; -+ -+static struct radio_isa_driver aztech_driver = { -+ .driver = { -+ .match = radio_isa_match, -+ .probe = radio_isa_probe, -+ .remove = radio_isa_remove, -+ .driver = { -+ .name = "radio-aztech", -+ }, -+ }, -+ .io_params = io, -+ .radio_nr_params = radio_nr, -+ .io_ports = aztech_ioports, -+ .num_of_io_ports = ARRAY_SIZE(aztech_ioports), -+ .region_size = 2, -+ .card = "Aztech Radio", -+ .ops = &aztech_ops, -+ .has_stereo = true, -+ .max_volume = 3, - }; - - static int __init aztech_init(void) - { -- struct aztech *az = &aztech_card; -- struct v4l2_device *v4l2_dev = &az->v4l2_dev; -- int res; -- -- strlcpy(v4l2_dev->name, "aztech", sizeof(v4l2_dev->name)); -- az->io = io; -- -- if (az->io == -1) { -- v4l2_err(v4l2_dev, "you must set an I/O address with io=0x350 or 0x358\n"); -- return -EINVAL; -- } -- -- if (!request_region(az->io, 2, "aztech")) { -- v4l2_err(v4l2_dev, "port 0x%x already in use\n", az->io); -- return -EBUSY; -- } -- -- res = v4l2_device_register(NULL, v4l2_dev); -- if (res < 0) { -- release_region(az->io, 2); -- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); -- return res; -- } -- -- mutex_init(&az->lock); -- strlcpy(az->vdev.name, v4l2_dev->name, sizeof(az->vdev.name)); -- az->vdev.v4l2_dev = v4l2_dev; -- az->vdev.fops = &aztech_fops; -- az->vdev.ioctl_ops = &aztech_ioctl_ops; -- az->vdev.release = video_device_release_empty; -- video_set_drvdata(&az->vdev, az); -- /* mute card - prevents noisy bootups */ -- outb(0, az->io); -- -- if (video_register_device(&az->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -- v4l2_device_unregister(v4l2_dev); -- release_region(az->io, 2); -- return -EINVAL; -- } -- -- v4l2_info(v4l2_dev, "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n"); -- return 0; -+ return isa_register_driver(&aztech_driver.driver, AZTECH_MAX); - } - - static void __exit aztech_exit(void) - { -- struct aztech *az = &aztech_card; -- -- video_unregister_device(&az->vdev); -- v4l2_device_unregister(&az->v4l2_dev); -- release_region(az->io, 2); -+ isa_unregister_driver(&aztech_driver.driver); - } - - module_init(aztech_init); -Index: linux-3.3.x86_64/drivers/media/radio/radio-gemtek.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/radio/radio-gemtek.c -+++ linux-3.3.x86_64/drivers/media/radio/radio-gemtek.c -@@ -1,4 +1,7 @@ --/* GemTek radio card driver for Linux (C) 1998 Jonas Munsin -+/* -+ * GemTek radio card driver -+ * -+ * Copyright 1998 Jonas Munsin - * - * GemTek hasn't released any specs on the card, so the protocol had to - * be reverse engineered with dosemu. -@@ -11,9 +14,12 @@ - * Converted to new API by Alan Cox - * Various bugfixes and enhancements by Russell Kroll - * -- * TODO: Allow for more than one of these foolish entities :-) -- * -+ * Converted to the radio-isa framework by Hans Verkuil - * Converted to V4L2 API by Mauro Carvalho Chehab -+ * -+ * Note: this card seems to swap the left and right audio channels! -+ * -+ * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool. - */ - - #include /* Modules */ -@@ -23,8 +29,10 @@ - #include /* kernel radio structs */ - #include - #include /* outb, outb_p */ -+#include - #include - #include -+#include "radio-isa.h" - - /* - * Module info. -@@ -33,7 +41,7 @@ - MODULE_AUTHOR("Jonas Munsin, Pekka Seppänen "); - MODULE_DESCRIPTION("A driver for the GemTek Radio card."); - MODULE_LICENSE("GPL"); --MODULE_VERSION("0.0.4"); -+MODULE_VERSION("1.0.0"); - - /* - * Module params. -@@ -46,45 +54,29 @@ MODULE_VERSION("0.0.4"); - #define CONFIG_RADIO_GEMTEK_PROBE 1 - #endif - --static int io = CONFIG_RADIO_GEMTEK_PORT; --static bool probe = CONFIG_RADIO_GEMTEK_PROBE; --static bool hardmute; --static bool shutdown = 1; --static bool keepmuted = 1; --static bool initmute = 1; --static int radio_nr = -1; -+#define GEMTEK_MAX 4 - --module_param(io, int, 0444); --MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic " -- "probing is disabled or fails. The most common I/O ports are: 0x20c " -- "0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to " -- "work for the combined sound/radiocard)."); -+static bool probe = CONFIG_RADIO_GEMTEK_PROBE; -+static bool hardmute; -+static int io[GEMTEK_MAX] = { [0] = CONFIG_RADIO_GEMTEK_PORT, -+ [1 ... (GEMTEK_MAX - 1)] = -1 }; -+static int radio_nr[GEMTEK_MAX] = { [0 ... (GEMTEK_MAX - 1)] = -1 }; - - module_param(probe, bool, 0444); --MODULE_PARM_DESC(probe, "Enable automatic device probing. Note: only the most " -- "common I/O ports used by the card are probed."); -+MODULE_PARM_DESC(probe, "Enable automatic device probing."); - - module_param(hardmute, bool, 0644); --MODULE_PARM_DESC(hardmute, "Enable `hard muting' by shutting down PLL, may " -+MODULE_PARM_DESC(hardmute, "Enable 'hard muting' by shutting down PLL, may " - "reduce static noise."); - --module_param(shutdown, bool, 0644); --MODULE_PARM_DESC(shutdown, "Enable shutting down PLL and muting line when " -- "module is unloaded."); -- --module_param(keepmuted, bool, 0644); --MODULE_PARM_DESC(keepmuted, "Keep card muted even when frequency is changed."); -- --module_param(initmute, bool, 0444); --MODULE_PARM_DESC(initmute, "Mute card when module is loaded."); -- --module_param(radio_nr, int, 0444); -+module_param_array(io, int, NULL, 0444); -+MODULE_PARM_DESC(io, "Force I/O ports for the GemTek Radio card if automatic " -+ "probing is disabled or fails. The most common I/O ports are: 0x20c " -+ "0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to " -+ "work for the combined sound/radiocard)."); - --/* -- * Functions for controlling the card. -- */ --#define GEMTEK_LOWFREQ (87*16000) --#define GEMTEK_HIGHFREQ (108*16000) -+module_param_array(radio_nr, int, NULL, 0444); -+MODULE_PARM_DESC(radio_nr, "Radio device numbers"); - - /* - * Frequency calculation constants. Intermediate frequency 10.52 MHz (nominal -@@ -108,18 +100,11 @@ module_param(radio_nr, int, 0444); - #define LONG_DELAY 75 /* usec */ - - struct gemtek { -- struct v4l2_device v4l2_dev; -- struct video_device vdev; -- struct mutex lock; -- unsigned long lastfreq; -- int muted; -- int verified; -- int io; -+ struct radio_isa_card isa; -+ bool muted; - u32 bu2614data; - }; - --static struct gemtek gemtek_card; -- - #define BU2614_FREQ_BITS 16 /* D0..D15, Frequency data */ - #define BU2614_PORT_BITS 3 /* P0..P2, Output port control data */ - #define BU2614_VOID_BITS 4 /* unused */ -@@ -166,31 +151,24 @@ static struct gemtek gemtek_card; - */ - static void gemtek_bu2614_transmit(struct gemtek *gt) - { -+ struct radio_isa_card *isa = >->isa; - int i, bit, q, mute; - -- mutex_lock(>->lock); -- - mute = gt->muted ? GEMTEK_MT : 0x00; - -- outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io); -- udelay(SHORT_DELAY); -- outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io); -+ outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, isa->io); - udelay(LONG_DELAY); - - for (i = 0, q = gt->bu2614data; i < 32; i++, q >>= 1) { - bit = (q & 1) ? GEMTEK_DA : 0; -- outb_p(mute | GEMTEK_CE | bit, gt->io); -+ outb_p(mute | GEMTEK_CE | bit, isa->io); - udelay(SHORT_DELAY); -- outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, gt->io); -+ outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, isa->io); - udelay(SHORT_DELAY); - } - -- outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io); -+ outb_p(mute | GEMTEK_DA | GEMTEK_CK, isa->io); - udelay(SHORT_DELAY); -- outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io); -- udelay(LONG_DELAY); -- -- mutex_unlock(>->lock); - } - - /* -@@ -198,21 +176,27 @@ static void gemtek_bu2614_transmit(struc - */ - static unsigned long gemtek_convfreq(unsigned long freq) - { -- return ((freq<muted = true; -+ return gt ? >->isa : NULL; - } - - /* - * Set FM-frequency. - */ --static void gemtek_setfreq(struct gemtek *gt, unsigned long freq) -+static int gemtek_s_frequency(struct radio_isa_card *isa, u32 freq) - { -- if (keepmuted && hardmute && gt->muted) -- return; -+ struct gemtek *gt = container_of(isa, struct gemtek, isa); - -- freq = clamp_val(freq, GEMTEK_LOWFREQ, GEMTEK_HIGHFREQ); -- -- gt->lastfreq = freq; -- gt->muted = 0; -+ if (hardmute && gt->muted) -+ return 0; - - gemtek_bu2614_set(gt, BU2614_PORT, 0); - gemtek_bu2614_set(gt, BU2614_FMES, 0); -@@ -220,23 +204,25 @@ static void gemtek_setfreq(struct gemtek - gemtek_bu2614_set(gt, BU2614_SWAL, 0); - gemtek_bu2614_set(gt, BU2614_FMUN, 1); /* GT bit set */ - gemtek_bu2614_set(gt, BU2614_TEST, 0); -- - gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_STDF_3_125_KHZ); - gemtek_bu2614_set(gt, BU2614_FREQ, gemtek_convfreq(freq)); -- - gemtek_bu2614_transmit(gt); -+ return 0; - } - - /* - * Set mute flag. - */ --static void gemtek_mute(struct gemtek *gt) -+static int gemtek_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) - { -+ struct gemtek *gt = container_of(isa, struct gemtek, isa); - int i; - -- gt->muted = 1; -- -+ gt->muted = mute; - if (hardmute) { -+ if (!mute) -+ return gemtek_s_frequency(isa, isa->freq); -+ - /* Turn off PLL, disable data output */ - gemtek_bu2614_set(gt, BU2614_PORT, 0); - gemtek_bu2614_set(gt, BU2614_FMES, 0); /* CT bit off */ -@@ -247,367 +233,85 @@ static void gemtek_mute(struct gemtek *g - gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_PLL_OFF); - gemtek_bu2614_set(gt, BU2614_FREQ, 0); - gemtek_bu2614_transmit(gt); -- return; -+ return 0; - } - -- mutex_lock(>->lock); -- - /* Read bus contents (CE, CK and DA). */ -- i = inb_p(gt->io); -+ i = inb_p(isa->io); - /* Write it back with mute flag set. */ -- outb_p((i >> 5) | GEMTEK_MT, gt->io); -+ outb_p((i >> 5) | (mute ? GEMTEK_MT : 0), isa->io); - udelay(SHORT_DELAY); -- -- mutex_unlock(>->lock); --} -- --/* -- * Unset mute flag. -- */ --static void gemtek_unmute(struct gemtek *gt) --{ -- int i; -- -- gt->muted = 0; -- if (hardmute) { -- /* Turn PLL back on. */ -- gemtek_setfreq(gt, gt->lastfreq); -- return; -- } -- mutex_lock(>->lock); -- -- i = inb_p(gt->io); -- outb_p(i >> 5, gt->io); -- udelay(SHORT_DELAY); -- -- mutex_unlock(>->lock); -+ return 0; - } - --/* -- * Get signal strength (= stereo status). -- */ --static inline int gemtek_getsigstr(struct gemtek *gt) -+static u32 gemtek_g_rxsubchans(struct radio_isa_card *isa) - { -- int sig; -- -- mutex_lock(>->lock); -- sig = inb_p(gt->io) & GEMTEK_NS ? 0 : 1; -- mutex_unlock(>->lock); -- return sig; -+ if (inb_p(isa->io) & GEMTEK_NS) -+ return V4L2_TUNER_SUB_MONO; -+ return V4L2_TUNER_SUB_STEREO; - } - - /* - * Check if requested card acts like GemTek Radio card. - */ --static int gemtek_verify(struct gemtek *gt, int port) -+static bool gemtek_probe(struct radio_isa_card *isa, int io) - { - int i, q; - -- if (gt->verified == port) -- return 1; -- -- mutex_lock(>->lock); -- -- q = inb_p(port); /* Read bus contents before probing. */ -+ q = inb_p(io); /* Read bus contents before probing. */ - /* Try to turn on CE, CK and DA respectively and check if card responds - properly. */ - for (i = 0; i < 3; ++i) { -- outb_p(1 << i, port); -+ outb_p(1 << i, io); - udelay(SHORT_DELAY); - -- if ((inb_p(port) & (~GEMTEK_NS)) != (0x17 | (1 << (i + 5)))) { -- mutex_unlock(>->lock); -- return 0; -- } -+ if ((inb_p(io) & ~GEMTEK_NS) != (0x17 | (1 << (i + 5)))) -+ return false; - } -- outb_p(q >> 5, port); /* Write bus contents back. */ -+ outb_p(q >> 5, io); /* Write bus contents back. */ - udelay(SHORT_DELAY); -- -- mutex_unlock(>->lock); -- gt->verified = port; -- -- return 1; --} -- --/* -- * Automatic probing for card. -- */ --static int gemtek_probe(struct gemtek *gt) --{ -- struct v4l2_device *v4l2_dev = >->v4l2_dev; -- int ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c }; -- int i; -- -- if (!probe) { -- v4l2_info(v4l2_dev, "Automatic device probing disabled.\n"); -- return -1; -- } -- -- v4l2_info(v4l2_dev, "Automatic device probing enabled.\n"); -- -- for (i = 0; i < ARRAY_SIZE(ioports); ++i) { -- v4l2_info(v4l2_dev, "Trying I/O port 0x%x...\n", ioports[i]); -- -- if (!request_region(ioports[i], 1, "gemtek-probe")) { -- v4l2_warn(v4l2_dev, "I/O port 0x%x busy!\n", -- ioports[i]); -- continue; -- } -- -- if (gemtek_verify(gt, ioports[i])) { -- v4l2_info(v4l2_dev, "Card found from I/O port " -- "0x%x!\n", ioports[i]); -- -- release_region(ioports[i], 1); -- gt->io = ioports[i]; -- return gt->io; -- } -- -- release_region(ioports[i], 1); -- } -- -- v4l2_err(v4l2_dev, "Automatic probing failed!\n"); -- return -1; -+ return true; - } - --/* -- * Video 4 Linux stuff. -- */ -- --static const struct v4l2_file_operations gemtek_fops = { -- .owner = THIS_MODULE, -- .unlocked_ioctl = video_ioctl2, -+static const struct radio_isa_ops gemtek_ops = { -+ .alloc = gemtek_alloc, -+ .probe = gemtek_probe, -+ .s_mute_volume = gemtek_s_mute_volume, -+ .s_frequency = gemtek_s_frequency, -+ .g_rxsubchans = gemtek_g_rxsubchans, - }; - --static int vidioc_querycap(struct file *file, void *priv, -- struct v4l2_capability *v) --{ -- strlcpy(v->driver, "radio-gemtek", sizeof(v->driver)); -- strlcpy(v->card, "GemTek", sizeof(v->card)); -- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); -- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; -- return 0; --} -- --static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) --{ -- struct gemtek *gt = video_drvdata(file); -- -- if (v->index > 0) -- return -EINVAL; -- -- strlcpy(v->name, "FM", sizeof(v->name)); -- v->type = V4L2_TUNER_RADIO; -- v->rangelow = GEMTEK_LOWFREQ; -- v->rangehigh = GEMTEK_HIGHFREQ; -- v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; -- v->signal = 0xffff * gemtek_getsigstr(gt); -- if (v->signal) { -- v->audmode = V4L2_TUNER_MODE_STEREO; -- v->rxsubchans = V4L2_TUNER_SUB_STEREO; -- } else { -- v->audmode = V4L2_TUNER_MODE_MONO; -- v->rxsubchans = V4L2_TUNER_SUB_MONO; -- } -- return 0; --} -- --static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) --{ -- return (v->index != 0) ? -EINVAL : 0; --} -- --static int vidioc_g_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) --{ -- struct gemtek *gt = video_drvdata(file); -- -- if (f->tuner != 0) -- return -EINVAL; -- f->type = V4L2_TUNER_RADIO; -- f->frequency = gt->lastfreq; -- return 0; --} -- --static int vidioc_s_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) --{ -- struct gemtek *gt = video_drvdata(file); -- -- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) -- return -EINVAL; -- gemtek_setfreq(gt, f->frequency); -- return 0; --} -- --static int vidioc_queryctrl(struct file *file, void *priv, -- struct v4l2_queryctrl *qc) --{ -- switch (qc->id) { -- case V4L2_CID_AUDIO_MUTE: -- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); -- default: -- return -EINVAL; -- } --} -- --static int vidioc_g_ctrl(struct file *file, void *priv, -- struct v4l2_control *ctrl) --{ -- struct gemtek *gt = video_drvdata(file); -- -- switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- ctrl->value = gt->muted; -- return 0; -- } -- return -EINVAL; --} -+static const int gemtek_ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c }; - --static int vidioc_s_ctrl(struct file *file, void *priv, -- struct v4l2_control *ctrl) --{ -- struct gemtek *gt = video_drvdata(file); -- -- switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- if (ctrl->value) -- gemtek_mute(gt); -- else -- gemtek_unmute(gt); -- return 0; -- } -- return -EINVAL; --} -- --static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) --{ -- *i = 0; -- return 0; --} -- --static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) --{ -- return (i != 0) ? -EINVAL : 0; --} -- --static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) --{ -- a->index = 0; -- strlcpy(a->name, "Radio", sizeof(a->name)); -- a->capability = V4L2_AUDCAP_STEREO; -- return 0; --} -- --static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) --{ -- return (a->index != 0) ? -EINVAL : 0; --} -- --static const struct v4l2_ioctl_ops gemtek_ioctl_ops = { -- .vidioc_querycap = vidioc_querycap, -- .vidioc_g_tuner = vidioc_g_tuner, -- .vidioc_s_tuner = vidioc_s_tuner, -- .vidioc_g_audio = vidioc_g_audio, -- .vidioc_s_audio = vidioc_s_audio, -- .vidioc_g_input = vidioc_g_input, -- .vidioc_s_input = vidioc_s_input, -- .vidioc_g_frequency = vidioc_g_frequency, -- .vidioc_s_frequency = vidioc_s_frequency, -- .vidioc_queryctrl = vidioc_queryctrl, -- .vidioc_g_ctrl = vidioc_g_ctrl, -- .vidioc_s_ctrl = vidioc_s_ctrl -+static struct radio_isa_driver gemtek_driver = { -+ .driver = { -+ .match = radio_isa_match, -+ .probe = radio_isa_probe, -+ .remove = radio_isa_remove, -+ .driver = { -+ .name = "radio-gemtek", -+ }, -+ }, -+ .io_params = io, -+ .radio_nr_params = radio_nr, -+ .io_ports = gemtek_ioports, -+ .num_of_io_ports = ARRAY_SIZE(gemtek_ioports), -+ .region_size = 1, -+ .card = "GemTek Radio", -+ .ops = &gemtek_ops, -+ .has_stereo = true, - }; - --/* -- * Initialization / cleanup related stuff. -- */ -- - static int __init gemtek_init(void) - { -- struct gemtek *gt = &gemtek_card; -- struct v4l2_device *v4l2_dev = >->v4l2_dev; -- int res; -- -- strlcpy(v4l2_dev->name, "gemtek", sizeof(v4l2_dev->name)); -- -- v4l2_info(v4l2_dev, "GemTek Radio card driver: v0.0.3\n"); -- -- mutex_init(>->lock); -- -- gt->verified = -1; -- gt->io = io; -- gemtek_probe(gt); -- if (gt->io) { -- if (!request_region(gt->io, 1, "gemtek")) { -- v4l2_err(v4l2_dev, "I/O port 0x%x already in use.\n", gt->io); -- return -EBUSY; -- } -- -- if (!gemtek_verify(gt, gt->io)) -- v4l2_warn(v4l2_dev, "Card at I/O port 0x%x does not " -- "respond properly, check your " -- "configuration.\n", gt->io); -- else -- v4l2_info(v4l2_dev, "Using I/O port 0x%x.\n", gt->io); -- } else if (probe) { -- v4l2_err(v4l2_dev, "Automatic probing failed and no " -- "fixed I/O port defined.\n"); -- return -ENODEV; -- } else { -- v4l2_err(v4l2_dev, "Automatic probing disabled but no fixed " -- "I/O port defined."); -- return -EINVAL; -- } -- -- res = v4l2_device_register(NULL, v4l2_dev); -- if (res < 0) { -- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); -- release_region(gt->io, 1); -- return res; -- } -- -- strlcpy(gt->vdev.name, v4l2_dev->name, sizeof(gt->vdev.name)); -- gt->vdev.v4l2_dev = v4l2_dev; -- gt->vdev.fops = &gemtek_fops; -- gt->vdev.ioctl_ops = &gemtek_ioctl_ops; -- gt->vdev.release = video_device_release_empty; -- video_set_drvdata(>->vdev, gt); -- -- /* Set defaults */ -- gt->lastfreq = GEMTEK_LOWFREQ; -- gt->bu2614data = 0; -- -- if (initmute) -- gemtek_mute(gt); -- -- if (video_register_device(>->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -- v4l2_device_unregister(v4l2_dev); -- release_region(gt->io, 1); -- return -EBUSY; -- } -- -- return 0; -+ gemtek_driver.probe = probe; -+ return isa_register_driver(&gemtek_driver.driver, GEMTEK_MAX); - } - --/* -- * Module cleanup -- */ - static void __exit gemtek_exit(void) - { -- struct gemtek *gt = &gemtek_card; -- struct v4l2_device *v4l2_dev = >->v4l2_dev; -- -- if (shutdown) { -- hardmute = 1; /* Turn off PLL */ -- gemtek_mute(gt); -- } else { -- v4l2_info(v4l2_dev, "Module unloaded but card not muted!\n"); -- } -- -- video_unregister_device(>->vdev); -- v4l2_device_unregister(>->v4l2_dev); -- release_region(gt->io, 1); -+ hardmute = 1; /* Turn off PLL */ -+ isa_unregister_driver(&gemtek_driver.driver); - } - - module_init(gemtek_init); -Index: linux-3.3.x86_64/drivers/media/radio/radio-rtrack2.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/radio/radio-rtrack2.c -+++ linux-3.3.x86_64/drivers/media/radio/radio-rtrack2.c -@@ -1,11 +1,12 @@ --/* RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff -+/* -+ * RadioTrack II driver -+ * Copyright 1998 Ben Pfaff - * - * Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood - * Converted to new API by Alan Cox - * Various bugfixes and enhancements by Russell Kroll - * -- * TODO: Allow for more than one of these foolish entities :-) -- * -+ * Converted to the radio-isa framework by Hans Verkuil - * Converted to V4L2 API by Mauro Carvalho Chehab - */ - -@@ -16,325 +17,123 @@ - #include /* kernel radio structs */ - #include - #include /* outb, outb_p */ -+#include - #include - #include -+#include "radio-isa.h" - - MODULE_AUTHOR("Ben Pfaff"); - MODULE_DESCRIPTION("A driver for the RadioTrack II radio card."); - MODULE_LICENSE("GPL"); --MODULE_VERSION("0.0.3"); -+MODULE_VERSION("0.1.99"); - - #ifndef CONFIG_RADIO_RTRACK2_PORT - #define CONFIG_RADIO_RTRACK2_PORT -1 - #endif - --static int io = CONFIG_RADIO_RTRACK2_PORT; --static int radio_nr = -1; -- --module_param(io, int, 0); --MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)"); --module_param(radio_nr, int, 0); -- --struct rtrack2 --{ -- struct v4l2_device v4l2_dev; -- struct video_device vdev; -- int io; -- unsigned long curfreq; -- int muted; -- struct mutex lock; --}; -- --static struct rtrack2 rtrack2_card; -+#define RTRACK2_MAX 2 - -+static int io[RTRACK2_MAX] = { [0] = CONFIG_RADIO_RTRACK2_PORT, -+ [1 ... (RTRACK2_MAX - 1)] = -1 }; -+static int radio_nr[RTRACK2_MAX] = { [0 ... (RTRACK2_MAX - 1)] = -1 }; - --/* local things */ -- --static void rt_mute(struct rtrack2 *dev) --{ -- if (dev->muted) -- return; -- mutex_lock(&dev->lock); -- outb(1, dev->io); -- mutex_unlock(&dev->lock); -- dev->muted = 1; --} -+module_param_array(io, int, NULL, 0444); -+MODULE_PARM_DESC(io, "I/O addresses of the RadioTrack card (0x20f or 0x30f)"); -+module_param_array(radio_nr, int, NULL, 0444); -+MODULE_PARM_DESC(radio_nr, "Radio device numbers"); - --static void rt_unmute(struct rtrack2 *dev) -+static struct radio_isa_card *rtrack2_alloc(void) - { -- if(dev->muted == 0) -- return; -- mutex_lock(&dev->lock); -- outb(0, dev->io); -- mutex_unlock(&dev->lock); -- dev->muted = 0; -+ return kzalloc(sizeof(struct radio_isa_card), GFP_KERNEL); - } - --static void zero(struct rtrack2 *dev) -+static void zero(struct radio_isa_card *isa) - { -- outb_p(1, dev->io); -- outb_p(3, dev->io); -- outb_p(1, dev->io); -+ outb_p(1, isa->io); -+ outb_p(3, isa->io); -+ outb_p(1, isa->io); - } - --static void one(struct rtrack2 *dev) -+static void one(struct radio_isa_card *isa) - { -- outb_p(5, dev->io); -- outb_p(7, dev->io); -- outb_p(5, dev->io); -+ outb_p(5, isa->io); -+ outb_p(7, isa->io); -+ outb_p(5, isa->io); - } - --static int rt_setfreq(struct rtrack2 *dev, unsigned long freq) -+static int rtrack2_s_frequency(struct radio_isa_card *isa, u32 freq) - { - int i; - -- mutex_lock(&dev->lock); -- dev->curfreq = freq; - freq = freq / 200 + 856; - -- outb_p(0xc8, dev->io); -- outb_p(0xc9, dev->io); -- outb_p(0xc9, dev->io); -+ outb_p(0xc8, isa->io); -+ outb_p(0xc9, isa->io); -+ outb_p(0xc9, isa->io); - - for (i = 0; i < 10; i++) -- zero(dev); -+ zero(isa); - - for (i = 14; i >= 0; i--) - if (freq & (1 << i)) -- one(dev); -+ one(isa); - else -- zero(dev); -- -- outb_p(0xc8, dev->io); -- if (!dev->muted) -- outb_p(0, dev->io); -- -- mutex_unlock(&dev->lock); -- return 0; --} -- --static int vidioc_querycap(struct file *file, void *priv, -- struct v4l2_capability *v) --{ -- strlcpy(v->driver, "radio-rtrack2", sizeof(v->driver)); -- strlcpy(v->card, "RadioTrack II", sizeof(v->card)); -- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); -- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; -- return 0; --} -- --static int vidioc_s_tuner(struct file *file, void *priv, -- struct v4l2_tuner *v) --{ -- return v->index ? -EINVAL : 0; --} -- --static int rt_getsigstr(struct rtrack2 *dev) --{ -- int sig = 1; -- -- mutex_lock(&dev->lock); -- if (inb(dev->io) & 2) /* bit set = no signal present */ -- sig = 0; -- mutex_unlock(&dev->lock); -- return sig; --} -+ zero(isa); - --static int vidioc_g_tuner(struct file *file, void *priv, -- struct v4l2_tuner *v) --{ -- struct rtrack2 *rt = video_drvdata(file); -- -- if (v->index > 0) -- return -EINVAL; -- -- strlcpy(v->name, "FM", sizeof(v->name)); -- v->type = V4L2_TUNER_RADIO; -- v->rangelow = 88 * 16000; -- v->rangehigh = 108 * 16000; -- v->rxsubchans = V4L2_TUNER_SUB_MONO; -- v->capability = V4L2_TUNER_CAP_LOW; -- v->audmode = V4L2_TUNER_MODE_MONO; -- v->signal = 0xFFFF * rt_getsigstr(rt); -+ outb_p(0xc8, isa->io); -+ if (!v4l2_ctrl_g_ctrl(isa->mute)) -+ outb_p(0, isa->io); - return 0; - } - --static int vidioc_s_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) -+static u32 rtrack2_g_signal(struct radio_isa_card *isa) - { -- struct rtrack2 *rt = video_drvdata(file); -- -- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) -- return -EINVAL; -- rt_setfreq(rt, f->frequency); -- return 0; -+ /* bit set = no signal present */ -+ return (inb(isa->io) & 2) ? 0 : 0xffff; - } - --static int vidioc_g_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) -+static int rtrack2_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) - { -- struct rtrack2 *rt = video_drvdata(file); -- -- if (f->tuner != 0) -- return -EINVAL; -- f->type = V4L2_TUNER_RADIO; -- f->frequency = rt->curfreq; -+ outb(mute, isa->io); - return 0; - } - --static int vidioc_queryctrl(struct file *file, void *priv, -- struct v4l2_queryctrl *qc) --{ -- switch (qc->id) { -- case V4L2_CID_AUDIO_MUTE: -- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); -- case V4L2_CID_AUDIO_VOLUME: -- return v4l2_ctrl_query_fill(qc, 0, 65535, 65535, 65535); -- } -- return -EINVAL; --} -- --static int vidioc_g_ctrl(struct file *file, void *priv, -- struct v4l2_control *ctrl) --{ -- struct rtrack2 *rt = video_drvdata(file); -- -- switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- ctrl->value = rt->muted; -- return 0; -- case V4L2_CID_AUDIO_VOLUME: -- if (rt->muted) -- ctrl->value = 0; -- else -- ctrl->value = 65535; -- return 0; -- } -- return -EINVAL; --} -- --static int vidioc_s_ctrl(struct file *file, void *priv, -- struct v4l2_control *ctrl) --{ -- struct rtrack2 *rt = video_drvdata(file); -- -- switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- if (ctrl->value) -- rt_mute(rt); -- else -- rt_unmute(rt); -- return 0; -- case V4L2_CID_AUDIO_VOLUME: -- if (ctrl->value) -- rt_unmute(rt); -- else -- rt_mute(rt); -- return 0; -- } -- return -EINVAL; --} -- --static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) --{ -- *i = 0; -- return 0; --} -- --static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) --{ -- return i ? -EINVAL : 0; --} -- --static int vidioc_g_audio(struct file *file, void *priv, -- struct v4l2_audio *a) --{ -- a->index = 0; -- strlcpy(a->name, "Radio", sizeof(a->name)); -- a->capability = V4L2_AUDCAP_STEREO; -- return 0; --} -- --static int vidioc_s_audio(struct file *file, void *priv, -- struct v4l2_audio *a) --{ -- return a->index ? -EINVAL : 0; --} -- --static const struct v4l2_file_operations rtrack2_fops = { -- .owner = THIS_MODULE, -- .unlocked_ioctl = video_ioctl2, -+static const struct radio_isa_ops rtrack2_ops = { -+ .alloc = rtrack2_alloc, -+ .s_mute_volume = rtrack2_s_mute_volume, -+ .s_frequency = rtrack2_s_frequency, -+ .g_signal = rtrack2_g_signal, - }; - --static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = { -- .vidioc_querycap = vidioc_querycap, -- .vidioc_g_tuner = vidioc_g_tuner, -- .vidioc_s_tuner = vidioc_s_tuner, -- .vidioc_g_frequency = vidioc_g_frequency, -- .vidioc_s_frequency = vidioc_s_frequency, -- .vidioc_queryctrl = vidioc_queryctrl, -- .vidioc_g_ctrl = vidioc_g_ctrl, -- .vidioc_s_ctrl = vidioc_s_ctrl, -- .vidioc_g_audio = vidioc_g_audio, -- .vidioc_s_audio = vidioc_s_audio, -- .vidioc_g_input = vidioc_g_input, -- .vidioc_s_input = vidioc_s_input, -+static const int rtrack2_ioports[] = { 0x20f, 0x30f }; -+ -+static struct radio_isa_driver rtrack2_driver = { -+ .driver = { -+ .match = radio_isa_match, -+ .probe = radio_isa_probe, -+ .remove = radio_isa_remove, -+ .driver = { -+ .name = "radio-rtrack2", -+ }, -+ }, -+ .io_params = io, -+ .radio_nr_params = radio_nr, -+ .io_ports = rtrack2_ioports, -+ .num_of_io_ports = ARRAY_SIZE(rtrack2_ioports), -+ .region_size = 4, -+ .card = "AIMSlab RadioTrack II", -+ .ops = &rtrack2_ops, -+ .has_stereo = true, - }; - - static int __init rtrack2_init(void) - { -- struct rtrack2 *dev = &rtrack2_card; -- struct v4l2_device *v4l2_dev = &dev->v4l2_dev; -- int res; -- -- strlcpy(v4l2_dev->name, "rtrack2", sizeof(v4l2_dev->name)); -- dev->io = io; -- if (dev->io == -1) { -- v4l2_err(v4l2_dev, "You must set an I/O address with io=0x20c or io=0x30c\n"); -- return -EINVAL; -- } -- if (!request_region(dev->io, 4, "rtrack2")) { -- v4l2_err(v4l2_dev, "port 0x%x already in use\n", dev->io); -- return -EBUSY; -- } -- -- res = v4l2_device_register(NULL, v4l2_dev); -- if (res < 0) { -- release_region(dev->io, 4); -- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); -- return res; -- } -- -- strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); -- dev->vdev.v4l2_dev = v4l2_dev; -- dev->vdev.fops = &rtrack2_fops; -- dev->vdev.ioctl_ops = &rtrack2_ioctl_ops; -- dev->vdev.release = video_device_release_empty; -- video_set_drvdata(&dev->vdev, dev); -- -- /* mute card - prevents noisy bootups */ -- outb(1, dev->io); -- dev->muted = 1; -- -- mutex_init(&dev->lock); -- if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -- v4l2_device_unregister(v4l2_dev); -- release_region(dev->io, 4); -- return -EINVAL; -- } -- -- v4l2_info(v4l2_dev, "AIMSlab Radiotrack II card driver.\n"); -- -- return 0; -+ return isa_register_driver(&rtrack2_driver.driver, RTRACK2_MAX); - } - - static void __exit rtrack2_exit(void) - { -- struct rtrack2 *dev = &rtrack2_card; -- -- video_unregister_device(&dev->vdev); -- v4l2_device_unregister(&dev->v4l2_dev); -- release_region(dev->io, 4); -+ isa_unregister_driver(&rtrack2_driver.driver); - } - - module_init(rtrack2_init); -Index: linux-3.3.x86_64/drivers/media/radio/radio-terratec.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/radio/radio-terratec.c -+++ linux-3.3.x86_64/drivers/media/radio/radio-terratec.c -@@ -16,11 +16,7 @@ - * Frequency control is done digitally -- ie out(port,encodefreq(95.8)); - * Volume Control is done digitally - * -- * there is a I2C controlled RDS decoder (SAA6588) onboard, which i would like to support someday -- * (as soon i have understand how to get started :) -- * If you can help me out with that, please contact me!! -- * -- * -+ * Converted to the radio-isa framework by Hans Verkuil - * Converted to V4L2 API by Mauro Carvalho Chehab - */ - -@@ -30,43 +26,24 @@ - #include /* kernel radio structs */ - #include - #include /* outb, outb_p */ -+#include - #include - #include -+#include "radio-isa.h" - --MODULE_AUTHOR("R.OFFERMANNS & others"); -+MODULE_AUTHOR("R. Offermans & others"); - MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio card."); - MODULE_LICENSE("GPL"); --MODULE_VERSION("0.0.3"); -- --#ifndef CONFIG_RADIO_TERRATEC_PORT --#define CONFIG_RADIO_TERRATEC_PORT 0x590 --#endif -+MODULE_VERSION("0.1.99"); - --static int io = CONFIG_RADIO_TERRATEC_PORT; -+/* Note: there seems to be only one possible port (0x590), but without -+ hardware this is hard to verify. For now, this is the only one we will -+ support. */ -+static int io = 0x590; - static int radio_nr = -1; - --module_param(io, int, 0); --MODULE_PARM_DESC(io, "I/O address of the TerraTec ActiveRadio card (0x590 or 0x591)"); --module_param(radio_nr, int, 0); -- --static struct v4l2_queryctrl radio_qctrl[] = { -- { -- .id = V4L2_CID_AUDIO_MUTE, -- .name = "Mute", -- .minimum = 0, -- .maximum = 1, -- .default_value = 1, -- .type = V4L2_CTRL_TYPE_BOOLEAN, -- },{ -- .id = V4L2_CID_AUDIO_VOLUME, -- .name = "Volume", -- .minimum = 0, -- .maximum = 0xff, -- .step = 1, -- .default_value = 0xff, -- .type = V4L2_CTRL_TYPE_INTEGER, -- } --}; -+module_param(radio_nr, int, 0444); -+MODULE_PARM_DESC(radio_nr, "Radio device number"); - - #define WRT_DIS 0x00 - #define CLK_OFF 0x00 -@@ -76,63 +53,24 @@ static struct v4l2_queryctrl radio_qctrl - #define CLK_ON 0x08 - #define WRT_EN 0x10 - --struct terratec -+static struct radio_isa_card *terratec_alloc(void) - { -- struct v4l2_device v4l2_dev; -- struct video_device vdev; -- int io; -- int curvol; -- unsigned long curfreq; -- int muted; -- struct mutex lock; --}; -- --static struct terratec terratec_card; -- --/* local things */ -+ return kzalloc(sizeof(struct radio_isa_card), GFP_KERNEL); -+} - --static void tt_write_vol(struct terratec *tt, int volume) -+static int terratec_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) - { - int i; - -- volume = volume + (volume * 32); /* change both channels */ -- mutex_lock(&tt->lock); -+ if (mute) -+ vol = 0; -+ vol = vol + (vol * 32); /* change both channels */ - for (i = 0; i < 8; i++) { -- if (volume & (0x80 >> i)) -- outb(0x80, tt->io + 1); -+ if (vol & (0x80 >> i)) -+ outb(0x80, isa->io + 1); - else -- outb(0x00, tt->io + 1); -+ outb(0x00, isa->io + 1); - } -- mutex_unlock(&tt->lock); --} -- -- -- --static void tt_mute(struct terratec *tt) --{ -- tt->muted = 1; -- tt_write_vol(tt, 0); --} -- --static int tt_setvol(struct terratec *tt, int vol) --{ -- if (vol == tt->curvol) { /* requested volume = current */ -- if (tt->muted) { /* user is unmuting the card */ -- tt->muted = 0; -- tt_write_vol(tt, vol); /* enable card */ -- } -- return 0; -- } -- -- if (vol == 0) { /* volume = 0 means mute the card */ -- tt_write_vol(tt, 0); /* "turn off card" by setting vol to 0 */ -- tt->curvol = vol; /* track the volume state! */ -- return 0; -- } -- -- tt->muted = 0; -- tt_write_vol(tt, vol); -- tt->curvol = vol; - return 0; - } - -@@ -140,20 +78,15 @@ static int tt_setvol(struct terratec *tt - /* this is the worst part in this driver */ - /* many more or less strange things are going on here, but hey, it works :) */ - --static int tt_setfreq(struct terratec *tt, unsigned long freq1) -+static int terratec_s_frequency(struct radio_isa_card *isa, u32 freq) - { -- int freq; - int i; - int p; -- int temp; -+ int temp; - long rest; - unsigned char buffer[25]; /* we have to bit shift 25 registers */ - -- mutex_lock(&tt->lock); -- -- tt->curfreq = freq1; -- -- freq = freq1 / 160; /* convert the freq. to a nice to handle value */ -+ freq = freq / 160; /* convert the freq. to a nice to handle value */ - memset(buffer, 0, sizeof(buffer)); - - rest = freq * 10 + 10700; /* I once had understood what is going on here */ -@@ -175,239 +108,61 @@ static int tt_setfreq(struct terratec *t - - for (i = 24; i > -1; i--) { /* bit shift the values to the radiocard */ - if (buffer[i] == 1) { -- outb(WRT_EN | DATA, tt->io); -- outb(WRT_EN | DATA | CLK_ON, tt->io); -- outb(WRT_EN | DATA, tt->io); -+ outb(WRT_EN | DATA, isa->io); -+ outb(WRT_EN | DATA | CLK_ON, isa->io); -+ outb(WRT_EN | DATA, isa->io); - } else { -- outb(WRT_EN | 0x00, tt->io); -- outb(WRT_EN | 0x00 | CLK_ON, tt->io); -- } -- } -- outb(0x00, tt->io); -- -- mutex_unlock(&tt->lock); -- -- return 0; --} -- --static int tt_getsigstr(struct terratec *tt) --{ -- if (inb(tt->io) & 2) /* bit set = no signal present */ -- return 0; -- return 1; /* signal present */ --} -- --static int vidioc_querycap(struct file *file, void *priv, -- struct v4l2_capability *v) --{ -- strlcpy(v->driver, "radio-terratec", sizeof(v->driver)); -- strlcpy(v->card, "ActiveRadio", sizeof(v->card)); -- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); -- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; -- return 0; --} -- --static int vidioc_g_tuner(struct file *file, void *priv, -- struct v4l2_tuner *v) --{ -- struct terratec *tt = video_drvdata(file); -- -- if (v->index > 0) -- return -EINVAL; -- -- strlcpy(v->name, "FM", sizeof(v->name)); -- v->type = V4L2_TUNER_RADIO; -- v->rangelow = 87 * 16000; -- v->rangehigh = 108 * 16000; -- v->rxsubchans = V4L2_TUNER_SUB_MONO; -- v->capability = V4L2_TUNER_CAP_LOW; -- v->audmode = V4L2_TUNER_MODE_MONO; -- v->signal = 0xFFFF * tt_getsigstr(tt); -- return 0; --} -- --static int vidioc_s_tuner(struct file *file, void *priv, -- struct v4l2_tuner *v) --{ -- return v->index ? -EINVAL : 0; --} -- --static int vidioc_s_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) --{ -- struct terratec *tt = video_drvdata(file); -- -- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) -- return -EINVAL; -- tt_setfreq(tt, f->frequency); -- return 0; --} -- --static int vidioc_g_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) --{ -- struct terratec *tt = video_drvdata(file); -- -- if (f->tuner != 0) -- return -EINVAL; -- f->type = V4L2_TUNER_RADIO; -- f->frequency = tt->curfreq; -- return 0; --} -- --static int vidioc_queryctrl(struct file *file, void *priv, -- struct v4l2_queryctrl *qc) --{ -- int i; -- -- for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { -- if (qc->id && qc->id == radio_qctrl[i].id) { -- memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); -- return 0; -+ outb(WRT_EN | 0x00, isa->io); -+ outb(WRT_EN | 0x00 | CLK_ON, isa->io); - } - } -- return -EINVAL; --} -- --static int vidioc_g_ctrl(struct file *file, void *priv, -- struct v4l2_control *ctrl) --{ -- struct terratec *tt = video_drvdata(file); -- -- switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- if (tt->muted) -- ctrl->value = 1; -- else -- ctrl->value = 0; -- return 0; -- case V4L2_CID_AUDIO_VOLUME: -- ctrl->value = tt->curvol * 6554; -- return 0; -- } -- return -EINVAL; --} -- --static int vidioc_s_ctrl(struct file *file, void *priv, -- struct v4l2_control *ctrl) --{ -- struct terratec *tt = video_drvdata(file); -- -- switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- if (ctrl->value) -- tt_mute(tt); -- else -- tt_setvol(tt,tt->curvol); -- return 0; -- case V4L2_CID_AUDIO_VOLUME: -- tt_setvol(tt,ctrl->value); -- return 0; -- } -- return -EINVAL; --} -- --static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) --{ -- *i = 0; -+ outb(0x00, isa->io); - return 0; - } - --static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) -+static u32 terratec_g_signal(struct radio_isa_card *isa) - { -- return i ? -EINVAL : 0; -+ /* bit set = no signal present */ -+ return (inb(isa->io) & 2) ? 0 : 0xffff; - } - --static int vidioc_g_audio(struct file *file, void *priv, -- struct v4l2_audio *a) --{ -- a->index = 0; -- strlcpy(a->name, "Radio", sizeof(a->name)); -- a->capability = V4L2_AUDCAP_STEREO; -- return 0; --} -- --static int vidioc_s_audio(struct file *file, void *priv, -- struct v4l2_audio *a) --{ -- return a->index ? -EINVAL : 0; --} -- --static const struct v4l2_file_operations terratec_fops = { -- .owner = THIS_MODULE, -- .unlocked_ioctl = video_ioctl2, -+static const struct radio_isa_ops terratec_ops = { -+ .alloc = terratec_alloc, -+ .s_mute_volume = terratec_s_mute_volume, -+ .s_frequency = terratec_s_frequency, -+ .g_signal = terratec_g_signal, - }; - --static const struct v4l2_ioctl_ops terratec_ioctl_ops = { -- .vidioc_querycap = vidioc_querycap, -- .vidioc_g_tuner = vidioc_g_tuner, -- .vidioc_s_tuner = vidioc_s_tuner, -- .vidioc_g_frequency = vidioc_g_frequency, -- .vidioc_s_frequency = vidioc_s_frequency, -- .vidioc_queryctrl = vidioc_queryctrl, -- .vidioc_g_ctrl = vidioc_g_ctrl, -- .vidioc_s_ctrl = vidioc_s_ctrl, -- .vidioc_g_audio = vidioc_g_audio, -- .vidioc_s_audio = vidioc_s_audio, -- .vidioc_g_input = vidioc_g_input, -- .vidioc_s_input = vidioc_s_input, -+static const int terratec_ioports[] = { 0x590 }; -+ -+static struct radio_isa_driver terratec_driver = { -+ .driver = { -+ .match = radio_isa_match, -+ .probe = radio_isa_probe, -+ .remove = radio_isa_remove, -+ .driver = { -+ .name = "radio-terratec", -+ }, -+ }, -+ .io_params = &io, -+ .radio_nr_params = &radio_nr, -+ .io_ports = terratec_ioports, -+ .num_of_io_ports = ARRAY_SIZE(terratec_ioports), -+ .region_size = 2, -+ .card = "TerraTec ActiveRadio", -+ .ops = &terratec_ops, -+ .has_stereo = true, -+ .max_volume = 10, - }; - - static int __init terratec_init(void) - { -- struct terratec *tt = &terratec_card; -- struct v4l2_device *v4l2_dev = &tt->v4l2_dev; -- int res; -- -- strlcpy(v4l2_dev->name, "terratec", sizeof(v4l2_dev->name)); -- tt->io = io; -- if (tt->io == -1) { -- v4l2_err(v4l2_dev, "you must set an I/O address with io=0x590 or 0x591\n"); -- return -EINVAL; -- } -- if (!request_region(tt->io, 2, "terratec")) { -- v4l2_err(v4l2_dev, "port 0x%x already in use\n", io); -- return -EBUSY; -- } -- -- res = v4l2_device_register(NULL, v4l2_dev); -- if (res < 0) { -- release_region(tt->io, 2); -- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); -- return res; -- } -- -- strlcpy(tt->vdev.name, v4l2_dev->name, sizeof(tt->vdev.name)); -- tt->vdev.v4l2_dev = v4l2_dev; -- tt->vdev.fops = &terratec_fops; -- tt->vdev.ioctl_ops = &terratec_ioctl_ops; -- tt->vdev.release = video_device_release_empty; -- video_set_drvdata(&tt->vdev, tt); -- -- mutex_init(&tt->lock); -- -- /* mute card - prevents noisy bootups */ -- tt_write_vol(tt, 0); -- -- if (video_register_device(&tt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -- v4l2_device_unregister(&tt->v4l2_dev); -- release_region(tt->io, 2); -- return -EINVAL; -- } -- -- v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver.\n"); -- return 0; -+ return isa_register_driver(&terratec_driver.driver, 1); - } - - static void __exit terratec_exit(void) - { -- struct terratec *tt = &terratec_card; -- struct v4l2_device *v4l2_dev = &tt->v4l2_dev; -- -- video_unregister_device(&tt->vdev); -- v4l2_device_unregister(&tt->v4l2_dev); -- release_region(tt->io, 2); -- v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver unloaded.\n"); -+ isa_unregister_driver(&terratec_driver.driver); - } - - module_init(terratec_init); -Index: linux-3.3.x86_64/drivers/media/radio/radio-trust.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/radio/radio-trust.c -+++ linux-3.3.x86_64/drivers/media/radio/radio-trust.c -@@ -21,13 +21,15 @@ - #include - #include - #include -+#include - #include - #include -+#include "radio-isa.h" - - MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); - MODULE_DESCRIPTION("A driver for the Trust FM Radio card."); - MODULE_LICENSE("GPL"); --MODULE_VERSION("0.0.3"); -+MODULE_VERSION("0.1.99"); - - /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ - -@@ -35,39 +37,38 @@ MODULE_VERSION("0.0.3"); - #define CONFIG_RADIO_TRUST_PORT -1 - #endif - --static int io = CONFIG_RADIO_TRUST_PORT; --static int radio_nr = -1; -+#define TRUST_MAX 2 - --module_param(io, int, 0); --MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)"); --module_param(radio_nr, int, 0); -+static int io[TRUST_MAX] = { [0] = CONFIG_RADIO_TRUST_PORT, -+ [1 ... (TRUST_MAX - 1)] = -1 }; -+static int radio_nr[TRUST_MAX] = { [0 ... (TRUST_MAX - 1)] = -1 }; -+ -+module_param_array(io, int, NULL, 0444); -+MODULE_PARM_DESC(io, "I/O addresses of the Trust FM Radio card (0x350 or 0x358)"); -+module_param_array(radio_nr, int, NULL, 0444); -+MODULE_PARM_DESC(radio_nr, "Radio device numbers"); - - struct trust { -- struct v4l2_device v4l2_dev; -- struct video_device vdev; -- int io; -+ struct radio_isa_card isa; - int ioval; -- __u16 curvol; -- __u16 curbass; -- __u16 curtreble; -- int muted; -- unsigned long curfreq; -- int curstereo; -- int curmute; -- struct mutex lock; - }; - --static struct trust trust_card; -+static struct radio_isa_card *trust_alloc(void) -+{ -+ struct trust *tr = kzalloc(sizeof(*tr), GFP_KERNEL); -+ -+ return tr ? &tr->isa : NULL; -+} - - /* i2c addresses */ - #define TDA7318_ADDR 0x88 - #define TSA6060T_ADDR 0xc4 - --#define TR_DELAY do { inb(tr->io); inb(tr->io); inb(tr->io); } while (0) --#define TR_SET_SCL outb(tr->ioval |= 2, tr->io) --#define TR_CLR_SCL outb(tr->ioval &= 0xfd, tr->io) --#define TR_SET_SDA outb(tr->ioval |= 1, tr->io) --#define TR_CLR_SDA outb(tr->ioval &= 0xfe, tr->io) -+#define TR_DELAY do { inb(tr->isa.io); inb(tr->isa.io); inb(tr->isa.io); } while (0) -+#define TR_SET_SCL outb(tr->ioval |= 2, tr->isa.io) -+#define TR_CLR_SCL outb(tr->ioval &= 0xfd, tr->isa.io) -+#define TR_SET_SDA outb(tr->ioval |= 1, tr->isa.io) -+#define TR_CLR_SDA outb(tr->ioval &= 0xfe, tr->isa.io) - - static void write_i2c(struct trust *tr, int n, ...) - { -@@ -84,10 +85,10 @@ static void write_i2c(struct trust *tr, - TR_CLR_SCL; - TR_DELAY; - -- for(; n; n--) { -+ for (; n; n--) { - val = va_arg(args, unsigned); -- for(mask = 0x80; mask; mask >>= 1) { -- if(val & mask) -+ for (mask = 0x80; mask; mask >>= 1) { -+ if (val & mask) - TR_SET_SDA; - else - TR_CLR_SDA; -@@ -115,317 +116,128 @@ static void write_i2c(struct trust *tr, - va_end(args); - } - --static void tr_setvol(struct trust *tr, __u16 vol) -+static int trust_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) - { -- mutex_lock(&tr->lock); -- tr->curvol = vol / 2048; -- write_i2c(tr, 2, TDA7318_ADDR, tr->curvol ^ 0x1f); -- mutex_unlock(&tr->lock); --} -+ struct trust *tr = container_of(isa, struct trust, isa); - --static int basstreble2chip[15] = { -- 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8 --}; -- --static void tr_setbass(struct trust *tr, __u16 bass) --{ -- mutex_lock(&tr->lock); -- tr->curbass = bass / 4370; -- write_i2c(tr, 2, TDA7318_ADDR, 0x60 | basstreble2chip[tr->curbass]); -- mutex_unlock(&tr->lock); -+ tr->ioval = (tr->ioval & 0xf7) | (mute << 3); -+ outb(tr->ioval, isa->io); -+ write_i2c(tr, 2, TDA7318_ADDR, vol ^ 0x1f); -+ return 0; - } - --static void tr_settreble(struct trust *tr, __u16 treble) -+static int trust_s_stereo(struct radio_isa_card *isa, bool stereo) - { -- mutex_lock(&tr->lock); -- tr->curtreble = treble / 4370; -- write_i2c(tr, 2, TDA7318_ADDR, 0x70 | basstreble2chip[tr->curtreble]); -- mutex_unlock(&tr->lock); --} -+ struct trust *tr = container_of(isa, struct trust, isa); - --static void tr_setstereo(struct trust *tr, int stereo) --{ -- mutex_lock(&tr->lock); -- tr->curstereo = !!stereo; -- tr->ioval = (tr->ioval & 0xfb) | (!tr->curstereo << 2); -- outb(tr->ioval, tr->io); -- mutex_unlock(&tr->lock); --} -- --static void tr_setmute(struct trust *tr, int mute) --{ -- mutex_lock(&tr->lock); -- tr->curmute = !!mute; -- tr->ioval = (tr->ioval & 0xf7) | (tr->curmute << 3); -- outb(tr->ioval, tr->io); -- mutex_unlock(&tr->lock); -+ tr->ioval = (tr->ioval & 0xfb) | (!stereo << 2); -+ outb(tr->ioval, isa->io); -+ return 0; - } - --static int tr_getsigstr(struct trust *tr) -+static u32 trust_g_signal(struct radio_isa_card *isa) - { - int i, v; - -- mutex_lock(&tr->lock); - for (i = 0, v = 0; i < 100; i++) -- v |= inb(tr->io); -- mutex_unlock(&tr->lock); -+ v |= inb(isa->io); - return (v & 1) ? 0 : 0xffff; - } - --static int tr_getstereo(struct trust *tr) --{ -- /* don't know how to determine it, just return the setting */ -- return tr->curstereo; --} -- --static void tr_setfreq(struct trust *tr, unsigned long f) --{ -- mutex_lock(&tr->lock); -- tr->curfreq = f; -- f /= 160; /* Convert to 10 kHz units */ -- f += 1070; /* Add 10.7 MHz IF */ -- write_i2c(tr, 5, TSA6060T_ADDR, (f << 1) | 1, f >> 7, 0x60 | ((f >> 15) & 1), 0); -- mutex_unlock(&tr->lock); --} -- --static int vidioc_querycap(struct file *file, void *priv, -- struct v4l2_capability *v) --{ -- strlcpy(v->driver, "radio-trust", sizeof(v->driver)); -- strlcpy(v->card, "Trust FM Radio", sizeof(v->card)); -- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); -- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; -- return 0; --} -- --static int vidioc_g_tuner(struct file *file, void *priv, -- struct v4l2_tuner *v) --{ -- struct trust *tr = video_drvdata(file); -- -- if (v->index > 0) -- return -EINVAL; -- -- strlcpy(v->name, "FM", sizeof(v->name)); -- v->type = V4L2_TUNER_RADIO; -- v->rangelow = 87.5 * 16000; -- v->rangehigh = 108 * 16000; -- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; -- v->capability = V4L2_TUNER_CAP_LOW; -- if (tr_getstereo(tr)) -- v->audmode = V4L2_TUNER_MODE_STEREO; -- else -- v->audmode = V4L2_TUNER_MODE_MONO; -- v->signal = tr_getsigstr(tr); -- return 0; --} -- --static int vidioc_s_tuner(struct file *file, void *priv, -- struct v4l2_tuner *v) -+static int trust_s_frequency(struct radio_isa_card *isa, u32 freq) - { -- struct trust *tr = video_drvdata(file); -+ struct trust *tr = container_of(isa, struct trust, isa); - -- if (v->index) -- return -EINVAL; -- tr_setstereo(tr, v->audmode == V4L2_TUNER_MODE_STEREO); -+ freq /= 160; /* Convert to 10 kHz units */ -+ freq += 1070; /* Add 10.7 MHz IF */ -+ write_i2c(tr, 5, TSA6060T_ADDR, (freq << 1) | 1, -+ freq >> 7, 0x60 | ((freq >> 15) & 1), 0); - return 0; - } - --static int vidioc_s_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) --{ -- struct trust *tr = video_drvdata(file); -- -- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) -- return -EINVAL; -- tr_setfreq(tr, f->frequency); -- return 0; --} -- --static int vidioc_g_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) --{ -- struct trust *tr = video_drvdata(file); -- -- if (f->tuner != 0) -- return -EINVAL; -- f->type = V4L2_TUNER_RADIO; -- f->frequency = tr->curfreq; -- return 0; --} -- --static int vidioc_queryctrl(struct file *file, void *priv, -- struct v4l2_queryctrl *qc) --{ -- switch (qc->id) { -- case V4L2_CID_AUDIO_MUTE: -- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); -- case V4L2_CID_AUDIO_VOLUME: -- return v4l2_ctrl_query_fill(qc, 0, 65535, 2048, 65535); -- case V4L2_CID_AUDIO_BASS: -- case V4L2_CID_AUDIO_TREBLE: -- return v4l2_ctrl_query_fill(qc, 0, 65535, 4370, 32768); -- } -- return -EINVAL; --} -- --static int vidioc_g_ctrl(struct file *file, void *priv, -- struct v4l2_control *ctrl) --{ -- struct trust *tr = video_drvdata(file); -- -- switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- ctrl->value = tr->curmute; -- return 0; -- case V4L2_CID_AUDIO_VOLUME: -- ctrl->value = tr->curvol * 2048; -- return 0; -- case V4L2_CID_AUDIO_BASS: -- ctrl->value = tr->curbass * 4370; -- return 0; -- case V4L2_CID_AUDIO_TREBLE: -- ctrl->value = tr->curtreble * 4370; -- return 0; -- } -- return -EINVAL; --} -+static int basstreble2chip[15] = { -+ 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8 -+}; - --static int vidioc_s_ctrl(struct file *file, void *priv, -- struct v4l2_control *ctrl) -+static int trust_s_ctrl(struct v4l2_ctrl *ctrl) - { -- struct trust *tr = video_drvdata(file); -+ struct radio_isa_card *isa = -+ container_of(ctrl->handler, struct radio_isa_card, hdl); -+ struct trust *tr = container_of(isa, struct trust, isa); - - switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- tr_setmute(tr, ctrl->value); -- return 0; -- case V4L2_CID_AUDIO_VOLUME: -- tr_setvol(tr, ctrl->value); -- return 0; - case V4L2_CID_AUDIO_BASS: -- tr_setbass(tr, ctrl->value); -+ write_i2c(tr, 2, TDA7318_ADDR, 0x60 | basstreble2chip[ctrl->val]); - return 0; - case V4L2_CID_AUDIO_TREBLE: -- tr_settreble(tr, ctrl->value); -+ write_i2c(tr, 2, TDA7318_ADDR, 0x70 | basstreble2chip[ctrl->val]); - return 0; - } - return -EINVAL; - } - --static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) --{ -- *i = 0; -- return 0; --} -- --static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) --{ -- return i ? -EINVAL : 0; --} -- --static int vidioc_g_audio(struct file *file, void *priv, -- struct v4l2_audio *a) --{ -- a->index = 0; -- strlcpy(a->name, "Radio", sizeof(a->name)); -- a->capability = V4L2_AUDCAP_STEREO; -- return 0; --} -- --static int vidioc_s_audio(struct file *file, void *priv, -- struct v4l2_audio *a) --{ -- return a->index ? -EINVAL : 0; --} -- --static const struct v4l2_file_operations trust_fops = { -- .owner = THIS_MODULE, -- .unlocked_ioctl = video_ioctl2, --}; -- --static const struct v4l2_ioctl_ops trust_ioctl_ops = { -- .vidioc_querycap = vidioc_querycap, -- .vidioc_g_tuner = vidioc_g_tuner, -- .vidioc_s_tuner = vidioc_s_tuner, -- .vidioc_g_frequency = vidioc_g_frequency, -- .vidioc_s_frequency = vidioc_s_frequency, -- .vidioc_queryctrl = vidioc_queryctrl, -- .vidioc_g_ctrl = vidioc_g_ctrl, -- .vidioc_s_ctrl = vidioc_s_ctrl, -- .vidioc_g_audio = vidioc_g_audio, -- .vidioc_s_audio = vidioc_s_audio, -- .vidioc_g_input = vidioc_g_input, -- .vidioc_s_input = vidioc_s_input, -+static const struct v4l2_ctrl_ops trust_ctrl_ops = { -+ .s_ctrl = trust_s_ctrl, - }; - --static int __init trust_init(void) -+static int trust_initialize(struct radio_isa_card *isa) - { -- struct trust *tr = &trust_card; -- struct v4l2_device *v4l2_dev = &tr->v4l2_dev; -- int res; -+ struct trust *tr = container_of(isa, struct trust, isa); - -- strlcpy(v4l2_dev->name, "trust", sizeof(v4l2_dev->name)); -- tr->io = io; - tr->ioval = 0xf; -- mutex_init(&tr->lock); -- -- if (tr->io == -1) { -- v4l2_err(v4l2_dev, "You must set an I/O address with io=0x0x350 or 0x358\n"); -- return -EINVAL; -- } -- if (!request_region(tr->io, 2, "Trust FM Radio")) { -- v4l2_err(v4l2_dev, "port 0x%x already in use\n", tr->io); -- return -EBUSY; -- } -- -- res = v4l2_device_register(NULL, v4l2_dev); -- if (res < 0) { -- release_region(tr->io, 2); -- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); -- return res; -- } -- -- strlcpy(tr->vdev.name, v4l2_dev->name, sizeof(tr->vdev.name)); -- tr->vdev.v4l2_dev = v4l2_dev; -- tr->vdev.fops = &trust_fops; -- tr->vdev.ioctl_ops = &trust_ioctl_ops; -- tr->vdev.release = video_device_release_empty; -- video_set_drvdata(&tr->vdev, tr); -- - write_i2c(tr, 2, TDA7318_ADDR, 0x80); /* speaker att. LF = 0 dB */ - write_i2c(tr, 2, TDA7318_ADDR, 0xa0); /* speaker att. RF = 0 dB */ - write_i2c(tr, 2, TDA7318_ADDR, 0xc0); /* speaker att. LR = 0 dB */ - write_i2c(tr, 2, TDA7318_ADDR, 0xe0); /* speaker att. RR = 0 dB */ - write_i2c(tr, 2, TDA7318_ADDR, 0x40); /* stereo 1 input, gain = 18.75 dB */ - -- tr_setvol(tr, 0xffff); -- tr_setbass(tr, 0x8000); -- tr_settreble(tr, 0x8000); -- tr_setstereo(tr, 1); -- -- /* mute card - prevents noisy bootups */ -- tr_setmute(tr, 1); -- -- if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -- v4l2_device_unregister(v4l2_dev); -- release_region(tr->io, 2); -- return -EINVAL; -- } -+ v4l2_ctrl_new_std(&isa->hdl, &trust_ctrl_ops, -+ V4L2_CID_AUDIO_BASS, 0, 15, 1, 8); -+ v4l2_ctrl_new_std(&isa->hdl, &trust_ctrl_ops, -+ V4L2_CID_AUDIO_TREBLE, 0, 15, 1, 8); -+ return isa->hdl.error; -+} - -- v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n"); -+static const struct radio_isa_ops trust_ops = { -+ .init = trust_initialize, -+ .alloc = trust_alloc, -+ .s_mute_volume = trust_s_mute_volume, -+ .s_frequency = trust_s_frequency, -+ .s_stereo = trust_s_stereo, -+ .g_signal = trust_g_signal, -+}; - -- return 0; --} -+static const int trust_ioports[] = { 0x350, 0x358 }; -+ -+static struct radio_isa_driver trust_driver = { -+ .driver = { -+ .match = radio_isa_match, -+ .probe = radio_isa_probe, -+ .remove = radio_isa_remove, -+ .driver = { -+ .name = "radio-trust", -+ }, -+ }, -+ .io_params = io, -+ .radio_nr_params = radio_nr, -+ .io_ports = trust_ioports, -+ .num_of_io_ports = ARRAY_SIZE(trust_ioports), -+ .region_size = 2, -+ .card = "Trust FM Radio", -+ .ops = &trust_ops, -+ .has_stereo = true, -+ .max_volume = 31, -+}; - --static void __exit cleanup_trust_module(void) -+static int __init trust_init(void) - { -- struct trust *tr = &trust_card; -+ return isa_register_driver(&trust_driver.driver, TRUST_MAX); -+} - -- video_unregister_device(&tr->vdev); -- v4l2_device_unregister(&tr->v4l2_dev); -- release_region(tr->io, 2); -+static void __exit trust_exit(void) -+{ -+ isa_unregister_driver(&trust_driver.driver); - } - - module_init(trust_init); --module_exit(cleanup_trust_module); -+module_exit(trust_exit); -Index: linux-3.3.x86_64/drivers/media/radio/radio-typhoon.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/radio/radio-typhoon.c -+++ linux-3.3.x86_64/drivers/media/radio/radio-typhoon.c -@@ -33,63 +33,53 @@ - #include /* request_region */ - #include /* kernel radio structs */ - #include /* outb, outb_p */ -+#include - #include - #include -+#include "radio-isa.h" - - #define DRIVER_VERSION "0.1.2" - - MODULE_AUTHOR("Dr. Henrik Seidel"); - MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio)."); - MODULE_LICENSE("GPL"); --MODULE_VERSION(DRIVER_VERSION); -+MODULE_VERSION("0.1.99"); - - #ifndef CONFIG_RADIO_TYPHOON_PORT - #define CONFIG_RADIO_TYPHOON_PORT -1 - #endif - - #ifndef CONFIG_RADIO_TYPHOON_MUTEFREQ --#define CONFIG_RADIO_TYPHOON_MUTEFREQ 0 -+#define CONFIG_RADIO_TYPHOON_MUTEFREQ 87000 - #endif - --static int io = CONFIG_RADIO_TYPHOON_PORT; --static int radio_nr = -1; -- --module_param(io, int, 0); --MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)"); -- --module_param(radio_nr, int, 0); -+#define TYPHOON_MAX 2 - -+static int io[TYPHOON_MAX] = { [0] = CONFIG_RADIO_TYPHOON_PORT, -+ [1 ... (TYPHOON_MAX - 1)] = -1 }; -+static int radio_nr[TYPHOON_MAX] = { [0 ... (TYPHOON_MAX - 1)] = -1 }; - static unsigned long mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ; -+ -+module_param_array(io, int, NULL, 0444); -+MODULE_PARM_DESC(io, "I/O addresses of the Typhoon card (0x316 or 0x336)"); -+module_param_array(radio_nr, int, NULL, 0444); -+MODULE_PARM_DESC(radio_nr, "Radio device numbers"); - module_param(mutefreq, ulong, 0); - MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)"); - --#define BANNER "Typhoon Radio Card driver v" DRIVER_VERSION "\n" -- - struct typhoon { -- struct v4l2_device v4l2_dev; -- struct video_device vdev; -- int io; -- int curvol; -+ struct radio_isa_card isa; - int muted; -- unsigned long curfreq; -- unsigned long mutefreq; -- struct mutex lock; - }; - --static struct typhoon typhoon_card; -- --static void typhoon_setvol_generic(struct typhoon *dev, int vol) -+static struct radio_isa_card *typhoon_alloc(void) - { -- mutex_lock(&dev->lock); -- vol >>= 14; /* Map 16 bit to 2 bit */ -- vol &= 3; -- outb_p(vol / 2, dev->io); /* Set the volume, high bit. */ -- outb_p(vol % 2, dev->io + 2); /* Set the volume, low bit. */ -- mutex_unlock(&dev->lock); -+ struct typhoon *ty = kzalloc(sizeof(*ty), GFP_KERNEL); -+ -+ return ty ? &ty->isa : NULL; - } - --static int typhoon_setfreq_generic(struct typhoon *dev, -- unsigned long frequency) -+static int typhoon_s_frequency(struct radio_isa_card *isa, u32 freq) - { - unsigned long outval; - unsigned long x; -@@ -105,302 +95,86 @@ static int typhoon_setfreq_generic(struc - * - */ - -- mutex_lock(&dev->lock); -- x = frequency / 160; -+ x = freq / 160; - outval = (x * x + 2500) / 5000; - outval = (outval * x + 5000) / 10000; - outval -= (10 * x * x + 10433) / 20866; - outval += 4 * x - 11505; - -- outb_p((outval >> 8) & 0x01, dev->io + 4); -- outb_p(outval >> 9, dev->io + 6); -- outb_p(outval & 0xff, dev->io + 8); -- mutex_unlock(&dev->lock); -- -- return 0; --} -- --static int typhoon_setfreq(struct typhoon *dev, unsigned long frequency) --{ -- typhoon_setfreq_generic(dev, frequency); -- dev->curfreq = frequency; -- return 0; --} -- --static void typhoon_mute(struct typhoon *dev) --{ -- if (dev->muted == 1) -- return; -- typhoon_setvol_generic(dev, 0); -- typhoon_setfreq_generic(dev, dev->mutefreq); -- dev->muted = 1; --} -- --static void typhoon_unmute(struct typhoon *dev) --{ -- if (dev->muted == 0) -- return; -- typhoon_setfreq_generic(dev, dev->curfreq); -- typhoon_setvol_generic(dev, dev->curvol); -- dev->muted = 0; --} -- --static int typhoon_setvol(struct typhoon *dev, int vol) --{ -- if (dev->muted && vol != 0) { /* user is unmuting the card */ -- dev->curvol = vol; -- typhoon_unmute(dev); -- return 0; -- } -- if (vol == dev->curvol) /* requested volume == current */ -- return 0; -- -- if (vol == 0) { /* volume == 0 means mute the card */ -- typhoon_mute(dev); -- dev->curvol = vol; -- return 0; -- } -- typhoon_setvol_generic(dev, vol); -- dev->curvol = vol; -- return 0; --} -- --static int vidioc_querycap(struct file *file, void *priv, -- struct v4l2_capability *v) --{ -- strlcpy(v->driver, "radio-typhoon", sizeof(v->driver)); -- strlcpy(v->card, "Typhoon Radio", sizeof(v->card)); -- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); -- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; -- return 0; --} -- --static int vidioc_g_tuner(struct file *file, void *priv, -- struct v4l2_tuner *v) --{ -- if (v->index > 0) -- return -EINVAL; -- -- strlcpy(v->name, "FM", sizeof(v->name)); -- v->type = V4L2_TUNER_RADIO; -- v->rangelow = 87.5 * 16000; -- v->rangehigh = 108 * 16000; -- v->rxsubchans = V4L2_TUNER_SUB_MONO; -- v->capability = V4L2_TUNER_CAP_LOW; -- v->audmode = V4L2_TUNER_MODE_MONO; -- v->signal = 0xFFFF; /* We can't get the signal strength */ -+ outb_p((outval >> 8) & 0x01, isa->io + 4); -+ outb_p(outval >> 9, isa->io + 6); -+ outb_p(outval & 0xff, isa->io + 8); - return 0; - } - --static int vidioc_s_tuner(struct file *file, void *priv, -- struct v4l2_tuner *v) --{ -- return v->index ? -EINVAL : 0; --} -- --static int vidioc_g_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) -+static int typhoon_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) - { -- struct typhoon *dev = video_drvdata(file); -+ struct typhoon *ty = container_of(isa, struct typhoon, isa); - -- if (f->tuner != 0) -- return -EINVAL; -- f->type = V4L2_TUNER_RADIO; -- f->frequency = dev->curfreq; -- return 0; --} -- --static int vidioc_s_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) --{ -- struct typhoon *dev = video_drvdata(file); -- -- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) -- return -EINVAL; -- dev->curfreq = f->frequency; -- typhoon_setfreq(dev, dev->curfreq); -- return 0; --} -- --static int vidioc_queryctrl(struct file *file, void *priv, -- struct v4l2_queryctrl *qc) --{ -- switch (qc->id) { -- case V4L2_CID_AUDIO_MUTE: -- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); -- case V4L2_CID_AUDIO_VOLUME: -- return v4l2_ctrl_query_fill(qc, 0, 65535, 16384, 65535); -- } -- return -EINVAL; --} -- --static int vidioc_g_ctrl(struct file *file, void *priv, -- struct v4l2_control *ctrl) --{ -- struct typhoon *dev = video_drvdata(file); -+ if (mute) -+ vol = 0; -+ vol >>= 14; /* Map 16 bit to 2 bit */ -+ vol &= 3; -+ outb_p(vol / 2, isa->io); /* Set the volume, high bit. */ -+ outb_p(vol % 2, isa->io + 2); /* Set the volume, low bit. */ - -- switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- ctrl->value = dev->muted; -- return 0; -- case V4L2_CID_AUDIO_VOLUME: -- ctrl->value = dev->curvol; -- return 0; -+ if (vol == 0 && !ty->muted) { -+ ty->muted = true; -+ return typhoon_s_frequency(isa, mutefreq << 4); - } -- return -EINVAL; --} -- --static int vidioc_s_ctrl (struct file *file, void *priv, -- struct v4l2_control *ctrl) --{ -- struct typhoon *dev = video_drvdata(file); -- -- switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- if (ctrl->value) -- typhoon_mute(dev); -- else -- typhoon_unmute(dev); -- return 0; -- case V4L2_CID_AUDIO_VOLUME: -- typhoon_setvol(dev, ctrl->value); -- return 0; -+ if (vol && ty->muted) { -+ ty->muted = false; -+ return typhoon_s_frequency(isa, isa->freq); - } -- return -EINVAL; --} -- --static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) --{ -- *i = 0; - return 0; - } - --static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) --{ -- return i ? -EINVAL : 0; --} -- --static int vidioc_g_audio(struct file *file, void *priv, -- struct v4l2_audio *a) --{ -- a->index = 0; -- strlcpy(a->name, "Radio", sizeof(a->name)); -- a->capability = V4L2_AUDCAP_STEREO; -- return 0; --} -- --static int vidioc_s_audio(struct file *file, void *priv, -- struct v4l2_audio *a) --{ -- return a->index ? -EINVAL : 0; --} -- --static int vidioc_log_status(struct file *file, void *priv) --{ -- struct typhoon *dev = video_drvdata(file); -- struct v4l2_device *v4l2_dev = &dev->v4l2_dev; -- -- v4l2_info(v4l2_dev, BANNER); --#ifdef MODULE -- v4l2_info(v4l2_dev, "Load type: Driver loaded as a module\n\n"); --#else -- v4l2_info(v4l2_dev, "Load type: Driver compiled into kernel\n\n"); --#endif -- v4l2_info(v4l2_dev, "frequency = %lu kHz\n", dev->curfreq >> 4); -- v4l2_info(v4l2_dev, "volume = %d\n", dev->curvol); -- v4l2_info(v4l2_dev, "mute = %s\n", dev->muted ? "on" : "off"); -- v4l2_info(v4l2_dev, "io = 0x%x\n", dev->io); -- v4l2_info(v4l2_dev, "mute frequency = %lu kHz\n", dev->mutefreq >> 4); -- return 0; --} -- --static const struct v4l2_file_operations typhoon_fops = { -- .owner = THIS_MODULE, -- .unlocked_ioctl = video_ioctl2, -+static const struct radio_isa_ops typhoon_ops = { -+ .alloc = typhoon_alloc, -+ .s_mute_volume = typhoon_s_mute_volume, -+ .s_frequency = typhoon_s_frequency, - }; - --static const struct v4l2_ioctl_ops typhoon_ioctl_ops = { -- .vidioc_log_status = vidioc_log_status, -- .vidioc_querycap = vidioc_querycap, -- .vidioc_g_tuner = vidioc_g_tuner, -- .vidioc_s_tuner = vidioc_s_tuner, -- .vidioc_g_audio = vidioc_g_audio, -- .vidioc_s_audio = vidioc_s_audio, -- .vidioc_g_input = vidioc_g_input, -- .vidioc_s_input = vidioc_s_input, -- .vidioc_g_frequency = vidioc_g_frequency, -- .vidioc_s_frequency = vidioc_s_frequency, -- .vidioc_queryctrl = vidioc_queryctrl, -- .vidioc_g_ctrl = vidioc_g_ctrl, -- .vidioc_s_ctrl = vidioc_s_ctrl, -+static const int typhoon_ioports[] = { 0x316, 0x336 }; -+ -+static struct radio_isa_driver typhoon_driver = { -+ .driver = { -+ .match = radio_isa_match, -+ .probe = radio_isa_probe, -+ .remove = radio_isa_remove, -+ .driver = { -+ .name = "radio-typhoon", -+ }, -+ }, -+ .io_params = io, -+ .radio_nr_params = radio_nr, -+ .io_ports = typhoon_ioports, -+ .num_of_io_ports = ARRAY_SIZE(typhoon_ioports), -+ .region_size = 8, -+ .card = "Typhoon Radio", -+ .ops = &typhoon_ops, -+ .has_stereo = true, -+ .max_volume = 3, - }; - - static int __init typhoon_init(void) - { -- struct typhoon *dev = &typhoon_card; -- struct v4l2_device *v4l2_dev = &dev->v4l2_dev; -- int res; -- -- strlcpy(v4l2_dev->name, "typhoon", sizeof(v4l2_dev->name)); -- dev->io = io; -- -- if (dev->io == -1) { -- v4l2_err(v4l2_dev, "You must set an I/O address with io=0x316 or io=0x336\n"); -- return -EINVAL; -- } -- -- if (mutefreq < 87000 || mutefreq > 108500) { -- v4l2_err(v4l2_dev, "You must set a frequency (in kHz) used when muting the card,\n"); -- v4l2_err(v4l2_dev, "e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n"); -- return -EINVAL; -+ if (mutefreq < 87000 || mutefreq > 108000) { -+ printk(KERN_ERR "%s: You must set a frequency (in kHz) used when muting the card,\n", -+ typhoon_driver.driver.driver.name); -+ printk(KERN_ERR "%s: e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108000)\n", -+ typhoon_driver.driver.driver.name); -+ return -ENODEV; - } -- dev->curfreq = dev->mutefreq = mutefreq << 4; -- -- mutex_init(&dev->lock); -- if (!request_region(dev->io, 8, "typhoon")) { -- v4l2_err(v4l2_dev, "port 0x%x already in use\n", -- dev->io); -- return -EBUSY; -- } -- -- res = v4l2_device_register(NULL, v4l2_dev); -- if (res < 0) { -- release_region(dev->io, 8); -- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); -- return res; -- } -- v4l2_info(v4l2_dev, BANNER); -- -- strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); -- dev->vdev.v4l2_dev = v4l2_dev; -- dev->vdev.fops = &typhoon_fops; -- dev->vdev.ioctl_ops = &typhoon_ioctl_ops; -- dev->vdev.release = video_device_release_empty; -- video_set_drvdata(&dev->vdev, dev); -- -- /* mute card - prevents noisy bootups */ -- typhoon_mute(dev); -- -- if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -- v4l2_device_unregister(&dev->v4l2_dev); -- release_region(dev->io, 8); -- return -EINVAL; -- } -- v4l2_info(v4l2_dev, "port 0x%x.\n", dev->io); -- v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", mutefreq); -- -- return 0; -+ return isa_register_driver(&typhoon_driver.driver, TYPHOON_MAX); - } - - static void __exit typhoon_exit(void) - { -- struct typhoon *dev = &typhoon_card; -- -- video_unregister_device(&dev->vdev); -- v4l2_device_unregister(&dev->v4l2_dev); -- release_region(dev->io, 8); -+ isa_unregister_driver(&typhoon_driver.driver); - } - -+ - module_init(typhoon_init); - module_exit(typhoon_exit); - -Index: linux-3.3.x86_64/drivers/media/radio/radio-zoltrix.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/radio/radio-zoltrix.c -+++ linux-3.3.x86_64/drivers/media/radio/radio-zoltrix.c -@@ -1,5 +1,6 @@ --/* zoltrix radio plus driver for Linux radio support -- * (c) 1998 C. van Schaik -+/* -+ * Zoltrix Radio Plus driver -+ * Copyright 1998 C. van Schaik - * - * BUGS - * Due to the inconsistency in reading from the signal flags -@@ -27,6 +28,14 @@ - * - * 2006-07-24 - Converted to V4L2 API - * by Mauro Carvalho Chehab -+ * -+ * Converted to the radio-isa framework by Hans Verkuil -+ * -+ * Note that this is the driver for the Zoltrix Radio Plus. -+ * This driver does not work for the Zoltrix Radio Plus 108 or the -+ * Zoltrix Radio Plus for Windows. -+ * -+ * Fully tested with the Keene USB FM Transmitter and the v4l2-compliance tool. - */ - - #include /* Modules */ -@@ -36,82 +45,70 @@ - #include /* kernel radio structs */ - #include - #include /* outb, outb_p */ -+#include - #include - #include -+#include "radio-isa.h" - --MODULE_AUTHOR("C.van Schaik"); -+MODULE_AUTHOR("C. van Schaik"); - MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus."); - MODULE_LICENSE("GPL"); --MODULE_VERSION("0.0.3"); -+MODULE_VERSION("0.1.99"); - - #ifndef CONFIG_RADIO_ZOLTRIX_PORT - #define CONFIG_RADIO_ZOLTRIX_PORT -1 - #endif - --static int io = CONFIG_RADIO_ZOLTRIX_PORT; --static int radio_nr = -1; -+#define ZOLTRIX_MAX 2 - --module_param(io, int, 0); --MODULE_PARM_DESC(io, "I/O address of the Zoltrix Radio Plus (0x20c or 0x30c)"); --module_param(radio_nr, int, 0); -+static int io[ZOLTRIX_MAX] = { [0] = CONFIG_RADIO_ZOLTRIX_PORT, -+ [1 ... (ZOLTRIX_MAX - 1)] = -1 }; -+static int radio_nr[ZOLTRIX_MAX] = { [0 ... (ZOLTRIX_MAX - 1)] = -1 }; -+ -+module_param_array(io, int, NULL, 0444); -+MODULE_PARM_DESC(io, "I/O addresses of the Zoltrix Radio Plus card (0x20c or 0x30c)"); -+module_param_array(radio_nr, int, NULL, 0444); -+MODULE_PARM_DESC(radio_nr, "Radio device numbers"); - - struct zoltrix { -- struct v4l2_device v4l2_dev; -- struct video_device vdev; -- int io; -+ struct radio_isa_card isa; - int curvol; -- unsigned long curfreq; -- int muted; -- unsigned int stereo; -- struct mutex lock; -+ bool muted; - }; - --static struct zoltrix zoltrix_card; -+static struct radio_isa_card *zoltrix_alloc(void) -+{ -+ struct zoltrix *zol = kzalloc(sizeof(*zol), GFP_KERNEL); - --static int zol_setvol(struct zoltrix *zol, int vol) -+ return zol ? &zol->isa : NULL; -+} -+ -+static int zoltrix_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol) - { -- zol->curvol = vol; -- if (zol->muted) -- return 0; -+ struct zoltrix *zol = container_of(isa, struct zoltrix, isa); - -- mutex_lock(&zol->lock); -- if (vol == 0) { -- outb(0, zol->io); -- outb(0, zol->io); -- inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ -- mutex_unlock(&zol->lock); -+ zol->curvol = vol; -+ zol->muted = mute; -+ if (mute || vol == 0) { -+ outb(0, isa->io); -+ outb(0, isa->io); -+ inb(isa->io + 3); /* Zoltrix needs to be read to confirm */ - return 0; - } - -- outb(zol->curvol-1, zol->io); -+ outb(vol - 1, isa->io); - msleep(10); -- inb(zol->io + 2); -- mutex_unlock(&zol->lock); -+ inb(isa->io + 2); - return 0; - } - --static void zol_mute(struct zoltrix *zol) --{ -- zol->muted = 1; -- mutex_lock(&zol->lock); -- outb(0, zol->io); -- outb(0, zol->io); -- inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ -- mutex_unlock(&zol->lock); --} -- --static void zol_unmute(struct zoltrix *zol) --{ -- zol->muted = 0; -- zol_setvol(zol, zol->curvol); --} -- --static int zol_setfreq(struct zoltrix *zol, unsigned long freq) -+/* tunes the radio to the desired frequency */ -+static int zoltrix_s_frequency(struct radio_isa_card *isa, u32 freq) - { -- /* tunes the radio to the desired frequency */ -- struct v4l2_device *v4l2_dev = &zol->v4l2_dev; -+ struct zoltrix *zol = container_of(isa, struct zoltrix, isa); -+ struct v4l2_device *v4l2_dev = &isa->v4l2_dev; - unsigned long long bitmask, f, m; -- unsigned int stereo = zol->stereo; -+ bool stereo = isa->stereo; - int i; - - if (freq == 0) { -@@ -125,340 +122,125 @@ static int zol_setfreq(struct zoltrix *z - bitmask = 0xc480402c10080000ull; - i = 45; - -- mutex_lock(&zol->lock); -- -- zol->curfreq = freq; -+ outb(0, isa->io); -+ outb(0, isa->io); -+ inb(isa->io + 3); /* Zoltrix needs to be read to confirm */ - -- outb(0, zol->io); -- outb(0, zol->io); -- inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ -- -- outb(0x40, zol->io); -- outb(0xc0, zol->io); -+ outb(0x40, isa->io); -+ outb(0xc0, isa->io); - - bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ (stereo << 31)); - while (i--) { - if ((bitmask & 0x8000000000000000ull) != 0) { -- outb(0x80, zol->io); -+ outb(0x80, isa->io); - udelay(50); -- outb(0x00, zol->io); -+ outb(0x00, isa->io); - udelay(50); -- outb(0x80, zol->io); -+ outb(0x80, isa->io); - udelay(50); - } else { -- outb(0xc0, zol->io); -+ outb(0xc0, isa->io); - udelay(50); -- outb(0x40, zol->io); -+ outb(0x40, isa->io); - udelay(50); -- outb(0xc0, zol->io); -+ outb(0xc0, isa->io); - udelay(50); - } - bitmask *= 2; - } - /* termination sequence */ -- outb(0x80, zol->io); -- outb(0xc0, zol->io); -- outb(0x40, zol->io); -+ outb(0x80, isa->io); -+ outb(0xc0, isa->io); -+ outb(0x40, isa->io); - udelay(1000); -- inb(zol->io + 2); -- -+ inb(isa->io + 2); - udelay(1000); - -- if (zol->muted) { -- outb(0, zol->io); -- outb(0, zol->io); -- inb(zol->io + 3); -- udelay(1000); -- } -- -- mutex_unlock(&zol->lock); -- -- if (!zol->muted) -- zol_setvol(zol, zol->curvol); -- return 0; -+ return zoltrix_s_mute_volume(isa, zol->muted, zol->curvol); - } - - /* Get signal strength */ --static int zol_getsigstr(struct zoltrix *zol) -+static u32 zoltrix_g_rxsubchans(struct radio_isa_card *isa) - { -+ struct zoltrix *zol = container_of(isa, struct zoltrix, isa); - int a, b; - -- mutex_lock(&zol->lock); -- outb(0x00, zol->io); /* This stuff I found to do nothing */ -- outb(zol->curvol, zol->io); -+ outb(0x00, isa->io); /* This stuff I found to do nothing */ -+ outb(zol->curvol, isa->io); - msleep(20); - -- a = inb(zol->io); -+ a = inb(isa->io); - msleep(10); -- b = inb(zol->io); -- -- mutex_unlock(&zol->lock); -+ b = inb(isa->io); - -- if (a != b) -- return 0; -- -- /* I found this out by playing with a binary scanner on the card io */ -- return a == 0xcf || a == 0xdf || a == 0xef; -+ return (a == b && a == 0xcf) ? -+ V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; - } - --static int zol_is_stereo(struct zoltrix *zol) -+static u32 zoltrix_g_signal(struct radio_isa_card *isa) - { -- int x1, x2; -- -- mutex_lock(&zol->lock); -+ struct zoltrix *zol = container_of(isa, struct zoltrix, isa); -+ int a, b; - -- outb(0x00, zol->io); -- outb(zol->curvol, zol->io); -+ outb(0x00, isa->io); /* This stuff I found to do nothing */ -+ outb(zol->curvol, isa->io); - msleep(20); - -- x1 = inb(zol->io); -+ a = inb(isa->io); - msleep(10); -- x2 = inb(zol->io); -- -- mutex_unlock(&zol->lock); -- -- return x1 == x2 && x1 == 0xcf; --} -- --static int vidioc_querycap(struct file *file, void *priv, -- struct v4l2_capability *v) --{ -- strlcpy(v->driver, "radio-zoltrix", sizeof(v->driver)); -- strlcpy(v->card, "Zoltrix Radio", sizeof(v->card)); -- strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); -- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; -- return 0; --} -- --static int vidioc_g_tuner(struct file *file, void *priv, -- struct v4l2_tuner *v) --{ -- struct zoltrix *zol = video_drvdata(file); -- -- if (v->index > 0) -- return -EINVAL; -- -- strlcpy(v->name, "FM", sizeof(v->name)); -- v->type = V4L2_TUNER_RADIO; -- v->rangelow = 88 * 16000; -- v->rangehigh = 108 * 16000; -- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; -- v->capability = V4L2_TUNER_CAP_LOW; -- if (zol_is_stereo(zol)) -- v->audmode = V4L2_TUNER_MODE_STEREO; -- else -- v->audmode = V4L2_TUNER_MODE_MONO; -- v->signal = 0xFFFF * zol_getsigstr(zol); -- return 0; --} -- --static int vidioc_s_tuner(struct file *file, void *priv, -- struct v4l2_tuner *v) --{ -- return v->index ? -EINVAL : 0; --} -- --static int vidioc_s_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) --{ -- struct zoltrix *zol = video_drvdata(file); -- -- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) -- return -EINVAL; -- if (zol_setfreq(zol, f->frequency) != 0) -- return -EINVAL; -- return 0; --} -- --static int vidioc_g_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) --{ -- struct zoltrix *zol = video_drvdata(file); -- -- if (f->tuner != 0) -- return -EINVAL; -- f->type = V4L2_TUNER_RADIO; -- f->frequency = zol->curfreq; -- return 0; --} -- --static int vidioc_queryctrl(struct file *file, void *priv, -- struct v4l2_queryctrl *qc) --{ -- switch (qc->id) { -- case V4L2_CID_AUDIO_MUTE: -- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); -- case V4L2_CID_AUDIO_VOLUME: -- return v4l2_ctrl_query_fill(qc, 0, 65535, 4096, 65535); -- } -- return -EINVAL; --} -- --static int vidioc_g_ctrl(struct file *file, void *priv, -- struct v4l2_control *ctrl) --{ -- struct zoltrix *zol = video_drvdata(file); -- -- switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- ctrl->value = zol->muted; -- return 0; -- case V4L2_CID_AUDIO_VOLUME: -- ctrl->value = zol->curvol * 4096; -- return 0; -- } -- return -EINVAL; --} -+ b = inb(isa->io); - --static int vidioc_s_ctrl(struct file *file, void *priv, -- struct v4l2_control *ctrl) --{ -- struct zoltrix *zol = video_drvdata(file); -- -- switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- if (ctrl->value) -- zol_mute(zol); -- else { -- zol_unmute(zol); -- zol_setvol(zol, zol->curvol); -- } -- return 0; -- case V4L2_CID_AUDIO_VOLUME: -- zol_setvol(zol, ctrl->value / 4096); -+ if (a != b) - return 0; -- } -- zol->stereo = 1; -- if (zol_setfreq(zol, zol->curfreq) != 0) -- return -EINVAL; --#if 0 --/* FIXME: Implement stereo/mono switch on V4L2 */ -- if (v->mode & VIDEO_SOUND_STEREO) { -- zol->stereo = 1; -- zol_setfreq(zol, zol->curfreq); -- } -- if (v->mode & VIDEO_SOUND_MONO) { -- zol->stereo = 0; -- zol_setfreq(zol, zol->curfreq); -- } --#endif -- return -EINVAL; --} -- --static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) --{ -- *i = 0; -- return 0; --} -- --static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) --{ -- return i ? -EINVAL : 0; --} - --static int vidioc_g_audio(struct file *file, void *priv, -- struct v4l2_audio *a) --{ -- a->index = 0; -- strlcpy(a->name, "Radio", sizeof(a->name)); -- a->capability = V4L2_AUDCAP_STEREO; -- return 0; -+ /* I found this out by playing with a binary scanner on the card io */ -+ return (a == 0xcf || a == 0xdf || a == 0xef) ? 0xffff : 0; - } - --static int vidioc_s_audio(struct file *file, void *priv, -- struct v4l2_audio *a) -+static int zoltrix_s_stereo(struct radio_isa_card *isa, bool stereo) - { -- return a->index ? -EINVAL : 0; -+ return zoltrix_s_frequency(isa, isa->freq); - } - --static const struct v4l2_file_operations zoltrix_fops = --{ -- .owner = THIS_MODULE, -- .unlocked_ioctl = video_ioctl2, -+static const struct radio_isa_ops zoltrix_ops = { -+ .alloc = zoltrix_alloc, -+ .s_mute_volume = zoltrix_s_mute_volume, -+ .s_frequency = zoltrix_s_frequency, -+ .s_stereo = zoltrix_s_stereo, -+ .g_rxsubchans = zoltrix_g_rxsubchans, -+ .g_signal = zoltrix_g_signal, - }; - --static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = { -- .vidioc_querycap = vidioc_querycap, -- .vidioc_g_tuner = vidioc_g_tuner, -- .vidioc_s_tuner = vidioc_s_tuner, -- .vidioc_g_audio = vidioc_g_audio, -- .vidioc_s_audio = vidioc_s_audio, -- .vidioc_g_input = vidioc_g_input, -- .vidioc_s_input = vidioc_s_input, -- .vidioc_g_frequency = vidioc_g_frequency, -- .vidioc_s_frequency = vidioc_s_frequency, -- .vidioc_queryctrl = vidioc_queryctrl, -- .vidioc_g_ctrl = vidioc_g_ctrl, -- .vidioc_s_ctrl = vidioc_s_ctrl, -+static const int zoltrix_ioports[] = { 0x20c, 0x30c }; -+ -+static struct radio_isa_driver zoltrix_driver = { -+ .driver = { -+ .match = radio_isa_match, -+ .probe = radio_isa_probe, -+ .remove = radio_isa_remove, -+ .driver = { -+ .name = "radio-zoltrix", -+ }, -+ }, -+ .io_params = io, -+ .radio_nr_params = radio_nr, -+ .io_ports = zoltrix_ioports, -+ .num_of_io_ports = ARRAY_SIZE(zoltrix_ioports), -+ .region_size = 2, -+ .card = "Zoltrix Radio Plus", -+ .ops = &zoltrix_ops, -+ .has_stereo = true, -+ .max_volume = 15, - }; - - static int __init zoltrix_init(void) - { -- struct zoltrix *zol = &zoltrix_card; -- struct v4l2_device *v4l2_dev = &zol->v4l2_dev; -- int res; -- -- strlcpy(v4l2_dev->name, "zoltrix", sizeof(v4l2_dev->name)); -- zol->io = io; -- if (zol->io == -1) { -- v4l2_err(v4l2_dev, "You must set an I/O address with io=0x20c or 0x30c\n"); -- return -EINVAL; -- } -- if (zol->io != 0x20c && zol->io != 0x30c) { -- v4l2_err(v4l2_dev, "invalid port, try 0x20c or 0x30c\n"); -- return -ENXIO; -- } -- -- if (!request_region(zol->io, 2, "zoltrix")) { -- v4l2_err(v4l2_dev, "port 0x%x already in use\n", zol->io); -- return -EBUSY; -- } -- -- res = v4l2_device_register(NULL, v4l2_dev); -- if (res < 0) { -- release_region(zol->io, 2); -- v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); -- return res; -- } -- -- mutex_init(&zol->lock); -- -- /* mute card - prevents noisy bootups */ -- -- /* this ensures that the volume is all the way down */ -- -- outb(0, zol->io); -- outb(0, zol->io); -- msleep(20); -- inb(zol->io + 3); -- -- zol->curvol = 0; -- zol->stereo = 1; -- -- strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name)); -- zol->vdev.v4l2_dev = v4l2_dev; -- zol->vdev.fops = &zoltrix_fops; -- zol->vdev.ioctl_ops = &zoltrix_ioctl_ops; -- zol->vdev.release = video_device_release_empty; -- video_set_drvdata(&zol->vdev, zol); -- -- if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -- v4l2_device_unregister(v4l2_dev); -- release_region(zol->io, 2); -- return -EINVAL; -- } -- v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n"); -- -- return 0; -+ return isa_register_driver(&zoltrix_driver.driver, ZOLTRIX_MAX); - } - - static void __exit zoltrix_exit(void) - { -- struct zoltrix *zol = &zoltrix_card; -- -- video_unregister_device(&zol->vdev); -- v4l2_device_unregister(&zol->v4l2_dev); -- release_region(zol->io, 2); -+ isa_unregister_driver(&zoltrix_driver.driver); - } - - module_init(zoltrix_init); -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-core/dvb_frontend.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-core/dvb_frontend.c -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-core/dvb_frontend.c -@@ -148,7 +148,7 @@ static int dtv_property_legacy_params_sy - - static bool has_get_frontend(struct dvb_frontend *fe) - { -- return fe->ops.get_frontend; -+ return fe->ops.get_frontend != NULL; - } - - /* -Index: linux-3.3.x86_64/drivers/media/common/tuners/xc5000.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/common/tuners/xc5000.c -+++ linux-3.3.x86_64/drivers/media/common/tuners/xc5000.c -@@ -49,9 +49,6 @@ static LIST_HEAD(hybrid_tuner_instance_l - #define dprintk(level, fmt, arg...) if (debug >= level) \ - printk(KERN_INFO "%s: " fmt, "xc5000", ## arg) - --#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.6.114.fw" --#define XC5000_DEFAULT_FIRMWARE_SIZE 12401 -- - struct xc5000_priv { - struct tuner_i2c_props i2c_props; - struct list_head hybrid_tuner_instance_list; -@@ -62,6 +59,8 @@ struct xc5000_priv { - u8 video_standard; - u8 rf_mode; - u8 radio_input; -+ -+ int chip_id; - }; - - /* Misc Defines */ -@@ -204,6 +203,33 @@ static struct XC_TV_STANDARD XC5000_Stan - {"FM Radio-INPUT1_MONO", 0x0278, 0x9002} - }; - -+ -+struct xc5000_fw_cfg { -+ char *name; -+ u16 size; -+}; -+ -+static const struct xc5000_fw_cfg xc5000a_1_6_114 = { -+ .name = "dvb-fe-xc5000-1.6.114.fw", -+ .size = 12401, -+}; -+ -+static const struct xc5000_fw_cfg xc5000c_41_024_5_31875 = { -+ .name = "dvb-fe-xc5000c-41.024.5-31875.fw", -+ .size = 16503, -+}; -+ -+static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id) -+{ -+ switch (chip_id) { -+ default: -+ case XC5000A: -+ return &xc5000a_1_6_114; -+ case XC5000C: -+ return &xc5000c_41_024_5_31875; -+ } -+} -+ - static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe); - static int xc5000_is_firmware_loaded(struct dvb_frontend *fe); - static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val); -@@ -552,12 +578,14 @@ static int xc5000_fwupload(struct dvb_fr - struct xc5000_priv *priv = fe->tuner_priv; - const struct firmware *fw; - int ret; -+ const struct xc5000_fw_cfg *desired_fw = -+ xc5000_assign_firmware(priv->chip_id); - - /* request the firmware, this will block and timeout */ - printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", -- XC5000_DEFAULT_FIRMWARE); -+ desired_fw->name); - -- ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, -+ ret = request_firmware(&fw, desired_fw->name, - priv->i2c_props.adap->dev.parent); - if (ret) { - printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n"); -@@ -569,7 +597,7 @@ static int xc5000_fwupload(struct dvb_fr - ret = XC_RESULT_SUCCESS; - } - -- if (fw->size != XC5000_DEFAULT_FIRMWARE_SIZE) { -+ if (fw->size != desired_fw->size) { - printk(KERN_ERR "xc5000: firmware incorrect size\n"); - ret = XC_RESULT_RESET_FAILURE; - } else { -@@ -1139,6 +1167,13 @@ struct dvb_frontend *xc5000_attach(struc - if (priv->radio_input == 0) - priv->radio_input = cfg->radio_input; - -+ /* don't override chip id if it's already been set -+ unless explicitly specified */ -+ if ((priv->chip_id == 0) || (cfg->chip_id)) -+ /* use default chip id if none specified, set to 0 so -+ it can be overridden if this is a hybrid driver */ -+ priv->chip_id = (cfg->chip_id) ? cfg->chip_id : 0; -+ - /* Check if firmware has been loaded. It is possible that another - instance of the driver has loaded the firmware. - */ -Index: linux-3.3.x86_64/drivers/media/common/tuners/xc5000.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/common/tuners/xc5000.h -+++ linux-3.3.x86_64/drivers/media/common/tuners/xc5000.h -@@ -27,10 +27,15 @@ - struct dvb_frontend; - struct i2c_adapter; - -+#define XC5000A 1 -+#define XC5000C 2 -+ - struct xc5000_config { - u8 i2c_address; - u32 if_khz; - u8 radio_input; -+ -+ int chip_id; - }; - - /* xc5000 callback command */ -Index: linux-3.3.x86_64/drivers/media/common/tuners/tuner-types.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/common/tuners/tuner-types.c -+++ linux-3.3.x86_64/drivers/media/common/tuners/tuner-types.c -@@ -1868,6 +1868,10 @@ struct tunertype tuners[] = { - .params = tuner_tena_tnf_5337_params, - .count = ARRAY_SIZE(tuner_tena_tnf_5337_params), - }, -+ [TUNER_XC5000C] = { /* Xceive 5000C */ -+ .name = "Xceive 5000C tuner", -+ /* see xc5000.c for details */ -+ }, - }; - EXPORT_SYMBOL(tuners); - -Index: linux-3.3.x86_64/drivers/media/video/tuner-core.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/tuner-core.c -+++ linux-3.3.x86_64/drivers/media/video/tuner-core.c -@@ -380,6 +380,21 @@ static void set_type(struct i2c_client * - tune_now = 0; - break; - } -+ case TUNER_XC5000C: -+ { -+ struct xc5000_config xc5000c_cfg = { -+ .i2c_address = t->i2c->addr, -+ /* if_khz will be set at dvb_attach() */ -+ .if_khz = 0, -+ .chip_id = XC5000C, -+ }; -+ -+ if (!dvb_attach(xc5000_attach, -+ &t->fe, t->i2c->adapter, &xc5000c_cfg)) -+ goto attach_failed; -+ tune_now = 0; -+ break; -+ } - case TUNER_NXP_TDA18271: - { - struct tda18271_config cfg = { -@@ -1314,18 +1329,7 @@ static struct i2c_driver tuner_driver = - .id_table = tuner_id, - }; - --static __init int init_tuner(void) --{ -- return i2c_add_driver(&tuner_driver); --} -- --static __exit void exit_tuner(void) --{ -- i2c_del_driver(&tuner_driver); --} -- --module_init(init_tuner); --module_exit(exit_tuner); -+module_i2c_driver(tuner_driver); - - MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners"); - MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); -Index: linux-3.3.x86_64/include/media/tuner.h -=================================================================== ---- linux-3.3.x86_64.orig/include/media/tuner.h -+++ linux-3.3.x86_64/include/media/tuner.h -@@ -136,6 +136,7 @@ - #define TUNER_TENA_TNF_5337 86 - - #define TUNER_XC4000 87 /* Xceive Silicon Tuner */ -+#define TUNER_XC5000C 88 /* Xceive Silicon Tuner */ - - /* tv card specific */ - #define TDA9887_PRESENT (1<<0) -Index: linux-3.3.x86_64/drivers/media/video/tveeprom.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/tveeprom.c -+++ linux-3.3.x86_64/drivers/media/video/tveeprom.c -@@ -286,8 +286,16 @@ hauppauge_tuner[] = - { TUNER_ABSENT, "MaxLinear 301"}, - { TUNER_ABSENT, "Mirics MSi001"}, - { TUNER_ABSENT, "MaxLinear MxL241SF"}, -- { TUNER_ABSENT, "Xceive XC5000C"}, -+ { TUNER_XC5000C, "Xceive XC5000C"}, - { TUNER_ABSENT, "Montage M68TS2020"}, -+ { TUNER_ABSENT, "Siano SMS1530"}, -+ { TUNER_ABSENT, "Dibcom 7090"}, -+ { TUNER_ABSENT, "Xceive XC5200C"}, -+ { TUNER_ABSENT, "NXP 18273"}, -+ { TUNER_ABSENT, "Montage M88TS2022"}, -+ /* 180-189 */ -+ { TUNER_ABSENT, "NXP 18272M"}, -+ { TUNER_ABSENT, "NXP 18272S"}, - }; - - /* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are -Index: linux-3.3.x86_64/drivers/media/radio/radio-sf16fmr2.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/radio/radio-sf16fmr2.c -+++ linux-3.3.x86_64/drivers/media/radio/radio-sf16fmr2.c -@@ -9,16 +9,23 @@ - #include - #include /* Modules */ - #include /* Initdata */ -+#include - #include /* request_region */ - #include /* outb, outb_p */ -+#include - #include - - MODULE_AUTHOR("Ondrej Zary"); - MODULE_DESCRIPTION("MediaForte SF16-FMR2 FM radio card driver"); - MODULE_LICENSE("GPL"); - -+static int radio_nr = -1; -+module_param(radio_nr, int, 0444); -+MODULE_PARM_DESC(radio_nr, "Radio device number"); -+ - struct fmr2 { - int io; -+ struct v4l2_device v4l2_dev; - struct snd_tea575x tea; - struct v4l2_ctrl *volume; - struct v4l2_ctrl *balance; -@@ -26,7 +33,6 @@ struct fmr2 { - - /* the port is hardwired so no need to support multiple cards */ - #define FMR2_PORT 0x384 --static struct fmr2 fmr2_card; - - /* TEA575x tuner pins */ - #define STR_DATA (1 << 0) -@@ -172,7 +178,7 @@ static int fmr2_tea_ext_init(struct snd_ - fmr2->volume = v4l2_ctrl_new_std(&tea->ctrl_handler, &fmr2_ctrl_ops, V4L2_CID_AUDIO_VOLUME, 0, 68, 2, 56); - fmr2->balance = v4l2_ctrl_new_std(&tea->ctrl_handler, &fmr2_ctrl_ops, V4L2_CID_AUDIO_BALANCE, -68, 68, 2, 0); - if (tea->ctrl_handler.error) { -- printk(KERN_ERR "radio-sf16fmr2: can't initialize contrls\n"); -+ printk(KERN_ERR "radio-sf16fmr2: can't initialize controls\n"); - return tea->ctrl_handler.error; - } - } -@@ -180,26 +186,46 @@ static int fmr2_tea_ext_init(struct snd_ - return 0; - } - --static int __init fmr2_init(void) -+static int __devinit fmr2_probe(struct device *pdev, unsigned int dev) - { -- struct fmr2 *fmr2 = &fmr2_card; -+ struct fmr2 *fmr2; -+ int err; -+ -+ fmr2 = kzalloc(sizeof(*fmr2), GFP_KERNEL); -+ if (fmr2 == NULL) -+ return -ENOMEM; - -+ strlcpy(fmr2->v4l2_dev.name, dev_name(pdev), -+ sizeof(fmr2->v4l2_dev.name)); - fmr2->io = FMR2_PORT; - -- if (!request_region(fmr2->io, 2, "SF16-FMR2")) { -+ if (!request_region(fmr2->io, 2, fmr2->v4l2_dev.name)) { - printk(KERN_ERR "radio-sf16fmr2: I/O port 0x%x already in use\n", fmr2->io); -+ kfree(fmr2); - return -EBUSY; - } - -+ dev_set_drvdata(pdev, fmr2); -+ err = v4l2_device_register(pdev, &fmr2->v4l2_dev); -+ if (err < 0) { -+ v4l2_err(&fmr2->v4l2_dev, "Could not register v4l2_device\n"); -+ release_region(fmr2->io, 2); -+ kfree(fmr2); -+ return err; -+ } -+ fmr2->tea.v4l2_dev = &fmr2->v4l2_dev; - fmr2->tea.private_data = fmr2; -+ fmr2->tea.radio_nr = radio_nr; - fmr2->tea.ops = &fmr2_tea_ops; - fmr2->tea.ext_init = fmr2_tea_ext_init; - strlcpy(fmr2->tea.card, "SF16-FMR2", sizeof(fmr2->tea.card)); -- strcpy(fmr2->tea.bus_info, "ISA"); -+ snprintf(fmr2->tea.bus_info, sizeof(fmr2->tea.bus_info), "ISA:%s", -+ fmr2->v4l2_dev.name); - - if (snd_tea575x_init(&fmr2->tea)) { - printk(KERN_ERR "radio-sf16fmr2: Unable to detect TEA575x tuner\n"); - release_region(fmr2->io, 2); -+ kfree(fmr2); - return -ENODEV; - } - -@@ -207,12 +233,33 @@ static int __init fmr2_init(void) - return 0; - } - --static void __exit fmr2_exit(void) -+static int __exit fmr2_remove(struct device *pdev, unsigned int dev) - { -- struct fmr2 *fmr2 = &fmr2_card; -+ struct fmr2 *fmr2 = dev_get_drvdata(pdev); - - snd_tea575x_exit(&fmr2->tea); - release_region(fmr2->io, 2); -+ v4l2_device_unregister(&fmr2->v4l2_dev); -+ kfree(fmr2); -+ return 0; -+} -+ -+struct isa_driver fmr2_driver = { -+ .probe = fmr2_probe, -+ .remove = fmr2_remove, -+ .driver = { -+ .name = "radio-sf16fmr2", -+ }, -+}; -+ -+static int __init fmr2_init(void) -+{ -+ return isa_register_driver(&fmr2_driver, 1); -+} -+ -+static void __exit fmr2_exit(void) -+{ -+ isa_unregister_driver(&fmr2_driver); - } - - module_init(fmr2_init); -Index: linux-3.3.x86_64/drivers/media/video/davinci/dm355_ccdc.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/davinci/dm355_ccdc.c -+++ linux-3.3.x86_64/drivers/media/video/davinci/dm355_ccdc.c -@@ -292,7 +292,7 @@ static int validate_ccdc_param(struct cc - if ((ccdcparam->med_filt_thres < 0) || - (ccdcparam->med_filt_thres > CCDC_MED_FILT_THRESH)) { - dev_dbg(ccdc_cfg.dev, -- "Invalid value of median filter thresold\n"); -+ "Invalid value of median filter threshold\n"); - return -EINVAL; - } - -Index: linux-3.3.x86_64/drivers/media/video/Kconfig -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/Kconfig -+++ linux-3.3.x86_64/drivers/media/video/Kconfig -@@ -273,6 +273,16 @@ config VIDEO_ADV7180 - To compile this driver as a module, choose M here: the - module will be called adv7180. - -+config VIDEO_ADV7183 -+ tristate "Analog Devices ADV7183 decoder" -+ depends on VIDEO_V4L2 && I2C -+ ---help--- -+ V4l2 subdevice driver for the Analog Devices -+ ADV7183 video decoder. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called adv7183. -+ - config VIDEO_BT819 - tristate "BT819A VideoStream decoder" - depends on VIDEO_V4L2 && I2C -@@ -459,6 +469,9 @@ config VIDEO_AK881X - - comment "Camera sensor devices" - -+config VIDEO_APTINA_PLL -+ tristate -+ - config VIDEO_OV7670 - tristate "OmniVision OV7670 sensor support" - depends on I2C && VIDEO_V4L2 -@@ -467,9 +480,28 @@ config VIDEO_OV7670 - OV7670 VGA camera. It currently only works with the M88ALP01 - controller. - -+config VIDEO_VS6624 -+ tristate "ST VS6624 sensor support" -+ depends on VIDEO_V4L2 && I2C -+ ---help--- -+ This is a Video4Linux2 sensor-level driver for the ST VS6624 -+ camera. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called vs6624. -+ -+config VIDEO_MT9M032 -+ tristate "MT9M032 camera sensor support" -+ depends on I2C && VIDEO_V4L2 -+ select VIDEO_APTINA_PLL -+ ---help--- -+ This driver supports MT9M032 camera sensors from Aptina, monochrome -+ models only. -+ - config VIDEO_MT9P031 - tristate "Aptina MT9P031 support" - depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API -+ select VIDEO_APTINA_PLL - ---help--- - This is a Video4Linux2 sensor-level driver for the Aptina - (Micron) mt9p031 5 Mpixel camera. -@@ -851,6 +883,8 @@ source "drivers/media/video/davinci/Kcon - - source "drivers/media/video/omap/Kconfig" - -+source "drivers/media/video/blackfin/Kconfig" -+ - config VIDEO_SH_VOU - tristate "SuperH VOU video output driver" - depends on VIDEO_DEV && ARCH_SHMOBILE -@@ -1087,7 +1121,7 @@ config VIDEO_MX2_HOSTSUPPORT - config VIDEO_MX2 - tristate "i.MX27/i.MX25 Camera Sensor Interface driver" - depends on VIDEO_DEV && SOC_CAMERA && (MACH_MX27 || ARCH_MX25) -- select VIDEOBUF_DMA_CONTIG -+ select VIDEOBUF2_DMA_CONTIG - select VIDEO_MX2_HOSTSUPPORT - ---help--- - This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor -@@ -1116,7 +1150,8 @@ config VIDEO_ATMEL_ISI - - config VIDEO_S5P_MIPI_CSIS - tristate "Samsung S5P and EXYNOS4 MIPI CSI receiver driver" -- depends on VIDEO_V4L2 && PM_RUNTIME && PLAT_S5P && VIDEO_V4L2_SUBDEV_API -+ depends on VIDEO_V4L2 && PM_RUNTIME && PLAT_S5P -+ depends on VIDEO_V4L2_SUBDEV_API && REGULATOR - ---help--- - This is a v4l2 driver for Samsung S5P/EXYNOS4 MIPI-CSI receiver. - -@@ -1176,4 +1211,14 @@ config VIDEO_SAMSUNG_S5P_MFC - help - MFC 5.1 driver for V4L2. - -+config VIDEO_MX2_EMMAPRP -+ tristate "MX2 eMMa-PrP support" -+ depends on VIDEO_DEV && VIDEO_V4L2 && SOC_IMX27 -+ select VIDEOBUF2_DMA_CONTIG -+ select V4L2_MEM2MEM_DEV -+ help -+ MX2X chips have a PrP that can be used to process buffers from -+ memory to memory. Operations include resizing and format -+ conversion. -+ - endif # V4L_MEM2MEM_DRIVERS -Index: linux-3.3.x86_64/drivers/media/video/Makefile -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/Makefile -+++ linux-3.3.x86_64/drivers/media/video/Makefile -@@ -12,16 +12,19 @@ omap2cam-objs := omap24xxcam.o omap24xxc - - videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ - v4l2-event.o v4l2-ctrls.o v4l2-subdev.o -+ifeq ($(CONFIG_COMPAT),y) -+ videodev-objs += v4l2-compat-ioctl32.o -+endif - - # V4L2 core modules - - obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o --ifeq ($(CONFIG_COMPAT),y) -- obj-$(CONFIG_VIDEO_DEV) += v4l2-compat-ioctl32.o --endif -- - obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o - -+# Helper modules -+ -+obj-$(CONFIG_VIDEO_APTINA_PLL) += aptina-pll.o -+ - # All i2c modules must come first: - - obj-$(CONFIG_VIDEO_TUNER) += tuner.o -@@ -40,8 +43,10 @@ obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o - obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o - obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o - obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o -+obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o - obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o - obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o -+obj-$(CONFIG_VIDEO_VS6624) += vs6624.o - obj-$(CONFIG_VIDEO_BT819) += bt819.o - obj-$(CONFIG_VIDEO_BT856) += bt856.o - obj-$(CONFIG_VIDEO_BT866) += bt866.o -@@ -65,6 +70,7 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083 - obj-$(CONFIG_VIDEO_OV7670) += ov7670.o - obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o - obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o -+obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o - obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o - obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o - obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o -@@ -177,6 +183,8 @@ obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_ - obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o - obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o - -+obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o -+ - obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/ - obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg/ - obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) += s5p-mfc/ -@@ -184,6 +192,8 @@ obj-$(CONFIG_VIDEO_SAMSUNG_S5P_TV) += s5 - - obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D) += s5p-g2d/ - -+obj-$(CONFIG_BLACKFIN) += blackfin/ -+ - obj-$(CONFIG_ARCH_DAVINCI) += davinci/ - - obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o -@@ -199,6 +209,6 @@ obj-y += davinci/ - - obj-$(CONFIG_ARCH_OMAP) += omap/ - --ccflags-y += -Idrivers/media/dvb/dvb-core --ccflags-y += -Idrivers/media/dvb/frontends --ccflags-y += -Idrivers/media/common/tuners -+ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core -+ccflags-y += -I$(srctree)/drivers/media/dvb/frontends -+ccflags-y += -I$(srctree)/drivers/media/common/tuners -Index: linux-3.3.x86_64/drivers/media/video/mx2_emmaprp.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/video/mx2_emmaprp.c -@@ -0,0 +1,1008 @@ -+/* -+ * Support eMMa-PrP through mem2mem framework. -+ * -+ * eMMa-PrP is a piece of HW that allows fetching buffers -+ * from one memory location and do several operations on -+ * them such as scaling or format conversion giving, as a result -+ * a new processed buffer in another memory location. -+ * -+ * Based on mem2mem_testdev.c by Pawel Osciak. -+ * -+ * Copyright (c) 2011 Vista Silicon S.L. -+ * Javier Martin -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the -+ * License, or (at your option) any later version -+ */ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define EMMAPRP_MODULE_NAME "mem2mem-emmaprp" -+ -+MODULE_DESCRIPTION("Mem-to-mem device which supports eMMa-PrP present in mx2 SoCs"); -+MODULE_AUTHOR("Javier Martin v4l2_dev, "%s: " fmt, __func__, ## arg) -+ -+/* EMMA PrP */ -+#define PRP_CNTL 0x00 -+#define PRP_INTR_CNTL 0x04 -+#define PRP_INTRSTATUS 0x08 -+#define PRP_SOURCE_Y_PTR 0x0c -+#define PRP_SOURCE_CB_PTR 0x10 -+#define PRP_SOURCE_CR_PTR 0x14 -+#define PRP_DEST_RGB1_PTR 0x18 -+#define PRP_DEST_RGB2_PTR 0x1c -+#define PRP_DEST_Y_PTR 0x20 -+#define PRP_DEST_CB_PTR 0x24 -+#define PRP_DEST_CR_PTR 0x28 -+#define PRP_SRC_FRAME_SIZE 0x2c -+#define PRP_DEST_CH1_LINE_STRIDE 0x30 -+#define PRP_SRC_PIXEL_FORMAT_CNTL 0x34 -+#define PRP_CH1_PIXEL_FORMAT_CNTL 0x38 -+#define PRP_CH1_OUT_IMAGE_SIZE 0x3c -+#define PRP_CH2_OUT_IMAGE_SIZE 0x40 -+#define PRP_SRC_LINE_STRIDE 0x44 -+#define PRP_CSC_COEF_012 0x48 -+#define PRP_CSC_COEF_345 0x4c -+#define PRP_CSC_COEF_678 0x50 -+#define PRP_CH1_RZ_HORI_COEF1 0x54 -+#define PRP_CH1_RZ_HORI_COEF2 0x58 -+#define PRP_CH1_RZ_HORI_VALID 0x5c -+#define PRP_CH1_RZ_VERT_COEF1 0x60 -+#define PRP_CH1_RZ_VERT_COEF2 0x64 -+#define PRP_CH1_RZ_VERT_VALID 0x68 -+#define PRP_CH2_RZ_HORI_COEF1 0x6c -+#define PRP_CH2_RZ_HORI_COEF2 0x70 -+#define PRP_CH2_RZ_HORI_VALID 0x74 -+#define PRP_CH2_RZ_VERT_COEF1 0x78 -+#define PRP_CH2_RZ_VERT_COEF2 0x7c -+#define PRP_CH2_RZ_VERT_VALID 0x80 -+ -+#define PRP_CNTL_CH1EN (1 << 0) -+#define PRP_CNTL_CH2EN (1 << 1) -+#define PRP_CNTL_CSIEN (1 << 2) -+#define PRP_CNTL_DATA_IN_YUV420 (0 << 3) -+#define PRP_CNTL_DATA_IN_YUV422 (1 << 3) -+#define PRP_CNTL_DATA_IN_RGB16 (2 << 3) -+#define PRP_CNTL_DATA_IN_RGB32 (3 << 3) -+#define PRP_CNTL_CH1_OUT_RGB8 (0 << 5) -+#define PRP_CNTL_CH1_OUT_RGB16 (1 << 5) -+#define PRP_CNTL_CH1_OUT_RGB32 (2 << 5) -+#define PRP_CNTL_CH1_OUT_YUV422 (3 << 5) -+#define PRP_CNTL_CH2_OUT_YUV420 (0 << 7) -+#define PRP_CNTL_CH2_OUT_YUV422 (1 << 7) -+#define PRP_CNTL_CH2_OUT_YUV444 (2 << 7) -+#define PRP_CNTL_CH1_LEN (1 << 9) -+#define PRP_CNTL_CH2_LEN (1 << 10) -+#define PRP_CNTL_SKIP_FRAME (1 << 11) -+#define PRP_CNTL_SWRST (1 << 12) -+#define PRP_CNTL_CLKEN (1 << 13) -+#define PRP_CNTL_WEN (1 << 14) -+#define PRP_CNTL_CH1BYP (1 << 15) -+#define PRP_CNTL_IN_TSKIP(x) ((x) << 16) -+#define PRP_CNTL_CH1_TSKIP(x) ((x) << 19) -+#define PRP_CNTL_CH2_TSKIP(x) ((x) << 22) -+#define PRP_CNTL_INPUT_FIFO_LEVEL(x) ((x) << 25) -+#define PRP_CNTL_RZ_FIFO_LEVEL(x) ((x) << 27) -+#define PRP_CNTL_CH2B1EN (1 << 29) -+#define PRP_CNTL_CH2B2EN (1 << 30) -+#define PRP_CNTL_CH2FEN (1 << 31) -+ -+#define PRP_SIZE_HEIGHT(x) (x) -+#define PRP_SIZE_WIDTH(x) ((x) << 16) -+ -+/* IRQ Enable and status register */ -+#define PRP_INTR_RDERR (1 << 0) -+#define PRP_INTR_CH1WERR (1 << 1) -+#define PRP_INTR_CH2WERR (1 << 2) -+#define PRP_INTR_CH1FC (1 << 3) -+#define PRP_INTR_CH2FC (1 << 5) -+#define PRP_INTR_LBOVF (1 << 7) -+#define PRP_INTR_CH2OVF (1 << 8) -+ -+#define PRP_INTR_ST_RDERR (1 << 0) -+#define PRP_INTR_ST_CH1WERR (1 << 1) -+#define PRP_INTR_ST_CH2WERR (1 << 2) -+#define PRP_INTR_ST_CH2B2CI (1 << 3) -+#define PRP_INTR_ST_CH2B1CI (1 << 4) -+#define PRP_INTR_ST_CH1B2CI (1 << 5) -+#define PRP_INTR_ST_CH1B1CI (1 << 6) -+#define PRP_INTR_ST_LBOVF (1 << 7) -+#define PRP_INTR_ST_CH2OVF (1 << 8) -+ -+struct emmaprp_fmt { -+ char *name; -+ u32 fourcc; -+ /* Types the format can be used for */ -+ u32 types; -+}; -+ -+static struct emmaprp_fmt formats[] = { -+ { -+ .name = "YUV 4:2:0 Planar", -+ .fourcc = V4L2_PIX_FMT_YUV420, -+ .types = MEM2MEM_CAPTURE, -+ }, -+ { -+ .name = "4:2:2, packed, YUYV", -+ .fourcc = V4L2_PIX_FMT_YUYV, -+ .types = MEM2MEM_OUTPUT, -+ }, -+}; -+ -+/* Per-queue, driver-specific private data */ -+struct emmaprp_q_data { -+ unsigned int width; -+ unsigned int height; -+ unsigned int sizeimage; -+ struct emmaprp_fmt *fmt; -+}; -+ -+enum { -+ V4L2_M2M_SRC = 0, -+ V4L2_M2M_DST = 1, -+}; -+ -+#define NUM_FORMATS ARRAY_SIZE(formats) -+ -+static struct emmaprp_fmt *find_format(struct v4l2_format *f) -+{ -+ struct emmaprp_fmt *fmt; -+ unsigned int k; -+ -+ for (k = 0; k < NUM_FORMATS; k++) { -+ fmt = &formats[k]; -+ if (fmt->fourcc == f->fmt.pix.pixelformat) -+ break; -+ } -+ -+ if (k == NUM_FORMATS) -+ return NULL; -+ -+ return &formats[k]; -+} -+ -+struct emmaprp_dev { -+ struct v4l2_device v4l2_dev; -+ struct video_device *vfd; -+ -+ struct mutex dev_mutex; -+ spinlock_t irqlock; -+ -+ int irq_emma; -+ void __iomem *base_emma; -+ struct clk *clk_emma; -+ struct resource *res_emma; -+ -+ struct v4l2_m2m_dev *m2m_dev; -+ struct vb2_alloc_ctx *alloc_ctx; -+}; -+ -+struct emmaprp_ctx { -+ struct emmaprp_dev *dev; -+ /* Abort requested by m2m */ -+ int aborting; -+ struct emmaprp_q_data q_data[2]; -+ struct v4l2_m2m_ctx *m2m_ctx; -+}; -+ -+static struct emmaprp_q_data *get_q_data(struct emmaprp_ctx *ctx, -+ enum v4l2_buf_type type) -+{ -+ switch (type) { -+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: -+ return &(ctx->q_data[V4L2_M2M_SRC]); -+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: -+ return &(ctx->q_data[V4L2_M2M_DST]); -+ default: -+ BUG(); -+ } -+ return NULL; -+} -+ -+/* -+ * mem2mem callbacks -+ */ -+static void emmaprp_job_abort(void *priv) -+{ -+ struct emmaprp_ctx *ctx = priv; -+ struct emmaprp_dev *pcdev = ctx->dev; -+ -+ ctx->aborting = 1; -+ -+ dprintk(pcdev, "Aborting task\n"); -+ -+ v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->m2m_ctx); -+} -+ -+static void emmaprp_lock(void *priv) -+{ -+ struct emmaprp_ctx *ctx = priv; -+ struct emmaprp_dev *pcdev = ctx->dev; -+ mutex_lock(&pcdev->dev_mutex); -+} -+ -+static void emmaprp_unlock(void *priv) -+{ -+ struct emmaprp_ctx *ctx = priv; -+ struct emmaprp_dev *pcdev = ctx->dev; -+ mutex_unlock(&pcdev->dev_mutex); -+} -+ -+static inline void emmaprp_dump_regs(struct emmaprp_dev *pcdev) -+{ -+ dprintk(pcdev, -+ "eMMa-PrP Registers:\n" -+ " SOURCE_Y_PTR = 0x%08X\n" -+ " SRC_FRAME_SIZE = 0x%08X\n" -+ " DEST_Y_PTR = 0x%08X\n" -+ " DEST_CR_PTR = 0x%08X\n" -+ " DEST_CB_PTR = 0x%08X\n" -+ " CH2_OUT_IMAGE_SIZE = 0x%08X\n" -+ " CNTL = 0x%08X\n", -+ readl(pcdev->base_emma + PRP_SOURCE_Y_PTR), -+ readl(pcdev->base_emma + PRP_SRC_FRAME_SIZE), -+ readl(pcdev->base_emma + PRP_DEST_Y_PTR), -+ readl(pcdev->base_emma + PRP_DEST_CR_PTR), -+ readl(pcdev->base_emma + PRP_DEST_CB_PTR), -+ readl(pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE), -+ readl(pcdev->base_emma + PRP_CNTL)); -+} -+ -+static void emmaprp_device_run(void *priv) -+{ -+ struct emmaprp_ctx *ctx = priv; -+ struct emmaprp_q_data *s_q_data, *d_q_data; -+ struct vb2_buffer *src_buf, *dst_buf; -+ struct emmaprp_dev *pcdev = ctx->dev; -+ unsigned int s_width, s_height; -+ unsigned int d_width, d_height; -+ unsigned int d_size; -+ dma_addr_t p_in, p_out; -+ u32 tmp; -+ -+ src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); -+ dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); -+ -+ s_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); -+ s_width = s_q_data->width; -+ s_height = s_q_data->height; -+ -+ d_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); -+ d_width = d_q_data->width; -+ d_height = d_q_data->height; -+ d_size = d_width * d_height; -+ -+ p_in = vb2_dma_contig_plane_dma_addr(src_buf, 0); -+ p_out = vb2_dma_contig_plane_dma_addr(dst_buf, 0); -+ if (!p_in || !p_out) { -+ v4l2_err(&pcdev->v4l2_dev, -+ "Acquiring kernel pointers to buffers failed\n"); -+ return; -+ } -+ -+ /* Input frame parameters */ -+ writel(p_in, pcdev->base_emma + PRP_SOURCE_Y_PTR); -+ writel(PRP_SIZE_WIDTH(s_width) | PRP_SIZE_HEIGHT(s_height), -+ pcdev->base_emma + PRP_SRC_FRAME_SIZE); -+ -+ /* Output frame parameters */ -+ writel(p_out, pcdev->base_emma + PRP_DEST_Y_PTR); -+ writel(p_out + d_size, pcdev->base_emma + PRP_DEST_CB_PTR); -+ writel(p_out + d_size + (d_size >> 2), -+ pcdev->base_emma + PRP_DEST_CR_PTR); -+ writel(PRP_SIZE_WIDTH(d_width) | PRP_SIZE_HEIGHT(d_height), -+ pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); -+ -+ /* IRQ configuration */ -+ tmp = readl(pcdev->base_emma + PRP_INTR_CNTL); -+ writel(tmp | PRP_INTR_RDERR | -+ PRP_INTR_CH2WERR | -+ PRP_INTR_CH2FC, -+ pcdev->base_emma + PRP_INTR_CNTL); -+ -+ emmaprp_dump_regs(pcdev); -+ -+ /* Enable transfer */ -+ tmp = readl(pcdev->base_emma + PRP_CNTL); -+ writel(tmp | PRP_CNTL_CH2_OUT_YUV420 | -+ PRP_CNTL_DATA_IN_YUV422 | -+ PRP_CNTL_CH2EN, -+ pcdev->base_emma + PRP_CNTL); -+} -+ -+static irqreturn_t emmaprp_irq(int irq_emma, void *data) -+{ -+ struct emmaprp_dev *pcdev = data; -+ struct emmaprp_ctx *curr_ctx; -+ struct vb2_buffer *src_vb, *dst_vb; -+ unsigned long flags; -+ u32 irqst; -+ -+ /* Check irq flags and clear irq */ -+ irqst = readl(pcdev->base_emma + PRP_INTRSTATUS); -+ writel(irqst, pcdev->base_emma + PRP_INTRSTATUS); -+ dprintk(pcdev, "irqst = 0x%08x\n", irqst); -+ -+ curr_ctx = v4l2_m2m_get_curr_priv(pcdev->m2m_dev); -+ if (curr_ctx == NULL) { -+ pr_err("Instance released before the end of transaction\n"); -+ return IRQ_HANDLED; -+ } -+ -+ if (!curr_ctx->aborting) { -+ if ((irqst & PRP_INTR_ST_RDERR) || -+ (irqst & PRP_INTR_ST_CH2WERR)) { -+ pr_err("PrP bus error ocurred, this transfer is probably corrupted\n"); -+ writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL); -+ } else if (irqst & PRP_INTR_ST_CH2B1CI) { /* buffer ready */ -+ src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); -+ dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx); -+ -+ spin_lock_irqsave(&pcdev->irqlock, flags); -+ v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE); -+ v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE); -+ spin_unlock_irqrestore(&pcdev->irqlock, flags); -+ } -+ } -+ -+ v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->m2m_ctx); -+ return IRQ_HANDLED; -+} -+ -+/* -+ * video ioctls -+ */ -+static int vidioc_querycap(struct file *file, void *priv, -+ struct v4l2_capability *cap) -+{ -+ strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1); -+ strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1); -+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT -+ | V4L2_CAP_STREAMING; -+ -+ return 0; -+} -+ -+static int enum_fmt(struct v4l2_fmtdesc *f, u32 type) -+{ -+ int i, num; -+ struct emmaprp_fmt *fmt; -+ -+ num = 0; -+ -+ for (i = 0; i < NUM_FORMATS; ++i) { -+ if (formats[i].types & type) { -+ /* index-th format of type type found ? */ -+ if (num == f->index) -+ break; -+ /* Correct type but haven't reached our index yet, -+ * just increment per-type index */ -+ ++num; -+ } -+ } -+ -+ if (i < NUM_FORMATS) { -+ /* Format found */ -+ fmt = &formats[i]; -+ strlcpy(f->description, fmt->name, sizeof(f->description) - 1); -+ f->pixelformat = fmt->fourcc; -+ return 0; -+ } -+ -+ /* Format not found */ -+ return -EINVAL; -+} -+ -+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_fmtdesc *f) -+{ -+ return enum_fmt(f, MEM2MEM_CAPTURE); -+} -+ -+static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, -+ struct v4l2_fmtdesc *f) -+{ -+ return enum_fmt(f, MEM2MEM_OUTPUT); -+} -+ -+static int vidioc_g_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f) -+{ -+ struct vb2_queue *vq; -+ struct emmaprp_q_data *q_data; -+ -+ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); -+ if (!vq) -+ return -EINVAL; -+ -+ q_data = get_q_data(ctx, f->type); -+ -+ f->fmt.pix.width = q_data->width; -+ f->fmt.pix.height = q_data->height; -+ f->fmt.pix.field = V4L2_FIELD_NONE; -+ f->fmt.pix.pixelformat = q_data->fmt->fourcc; -+ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) -+ f->fmt.pix.bytesperline = q_data->width * 3 / 2; -+ else /* YUYV */ -+ f->fmt.pix.bytesperline = q_data->width * 2; -+ f->fmt.pix.sizeimage = q_data->sizeimage; -+ -+ return 0; -+} -+ -+static int vidioc_g_fmt_vid_out(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ return vidioc_g_fmt(priv, f); -+} -+ -+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ return vidioc_g_fmt(priv, f); -+} -+ -+static int vidioc_try_fmt(struct v4l2_format *f) -+{ -+ enum v4l2_field field; -+ -+ -+ if (!find_format(f)) -+ return -EINVAL; -+ -+ field = f->fmt.pix.field; -+ if (field == V4L2_FIELD_ANY) -+ field = V4L2_FIELD_NONE; -+ else if (V4L2_FIELD_NONE != field) -+ return -EINVAL; -+ -+ /* V4L2 specification suggests the driver corrects the format struct -+ * if any of the dimensions is unsupported */ -+ f->fmt.pix.field = field; -+ -+ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) { -+ v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, -+ W_ALIGN_YUV420, &f->fmt.pix.height, -+ MIN_H, MAX_H, H_ALIGN, S_ALIGN); -+ f->fmt.pix.bytesperline = f->fmt.pix.width * 3 / 2; -+ } else { -+ v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, -+ W_ALIGN_OTHERS, &f->fmt.pix.height, -+ MIN_H, MAX_H, H_ALIGN, S_ALIGN); -+ f->fmt.pix.bytesperline = f->fmt.pix.width * 2; -+ } -+ f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; -+ -+ return 0; -+} -+ -+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ struct emmaprp_fmt *fmt; -+ struct emmaprp_ctx *ctx = priv; -+ -+ fmt = find_format(f); -+ if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) { -+ v4l2_err(&ctx->dev->v4l2_dev, -+ "Fourcc format (0x%08x) invalid.\n", -+ f->fmt.pix.pixelformat); -+ return -EINVAL; -+ } -+ -+ return vidioc_try_fmt(f); -+} -+ -+static int vidioc_try_fmt_vid_out(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ struct emmaprp_fmt *fmt; -+ struct emmaprp_ctx *ctx = priv; -+ -+ fmt = find_format(f); -+ if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) { -+ v4l2_err(&ctx->dev->v4l2_dev, -+ "Fourcc format (0x%08x) invalid.\n", -+ f->fmt.pix.pixelformat); -+ return -EINVAL; -+ } -+ -+ return vidioc_try_fmt(f); -+} -+ -+static int vidioc_s_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f) -+{ -+ struct emmaprp_q_data *q_data; -+ struct vb2_queue *vq; -+ int ret; -+ -+ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); -+ if (!vq) -+ return -EINVAL; -+ -+ q_data = get_q_data(ctx, f->type); -+ if (!q_data) -+ return -EINVAL; -+ -+ if (vb2_is_busy(vq)) { -+ v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__); -+ return -EBUSY; -+ } -+ -+ ret = vidioc_try_fmt(f); -+ if (ret) -+ return ret; -+ -+ q_data->fmt = find_format(f); -+ q_data->width = f->fmt.pix.width; -+ q_data->height = f->fmt.pix.height; -+ if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420) -+ q_data->sizeimage = q_data->width * q_data->height * 3 / 2; -+ else /* YUYV */ -+ q_data->sizeimage = q_data->width * q_data->height * 2; -+ -+ dprintk(ctx->dev, -+ "Setting format for type %d, wxh: %dx%d, fmt: %d\n", -+ f->type, q_data->width, q_data->height, q_data->fmt->fourcc); -+ -+ return 0; -+} -+ -+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ int ret; -+ -+ ret = vidioc_try_fmt_vid_cap(file, priv, f); -+ if (ret) -+ return ret; -+ -+ return vidioc_s_fmt(priv, f); -+} -+ -+static int vidioc_s_fmt_vid_out(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ int ret; -+ -+ ret = vidioc_try_fmt_vid_out(file, priv, f); -+ if (ret) -+ return ret; -+ -+ return vidioc_s_fmt(priv, f); -+} -+ -+static int vidioc_reqbufs(struct file *file, void *priv, -+ struct v4l2_requestbuffers *reqbufs) -+{ -+ struct emmaprp_ctx *ctx = priv; -+ -+ return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); -+} -+ -+static int vidioc_querybuf(struct file *file, void *priv, -+ struct v4l2_buffer *buf) -+{ -+ struct emmaprp_ctx *ctx = priv; -+ -+ return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); -+} -+ -+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -+{ -+ struct emmaprp_ctx *ctx = priv; -+ -+ return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); -+} -+ -+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -+{ -+ struct emmaprp_ctx *ctx = priv; -+ -+ return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); -+} -+ -+static int vidioc_streamon(struct file *file, void *priv, -+ enum v4l2_buf_type type) -+{ -+ struct emmaprp_ctx *ctx = priv; -+ -+ return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); -+} -+ -+static int vidioc_streamoff(struct file *file, void *priv, -+ enum v4l2_buf_type type) -+{ -+ struct emmaprp_ctx *ctx = priv; -+ -+ return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); -+} -+ -+static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = { -+ .vidioc_querycap = vidioc_querycap, -+ -+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, -+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, -+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, -+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, -+ -+ .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, -+ .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out, -+ .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, -+ .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, -+ -+ .vidioc_reqbufs = vidioc_reqbufs, -+ .vidioc_querybuf = vidioc_querybuf, -+ -+ .vidioc_qbuf = vidioc_qbuf, -+ .vidioc_dqbuf = vidioc_dqbuf, -+ -+ .vidioc_streamon = vidioc_streamon, -+ .vidioc_streamoff = vidioc_streamoff, -+}; -+ -+ -+/* -+ * Queue operations -+ */ -+static int emmaprp_queue_setup(struct vb2_queue *vq, -+ const struct v4l2_format *fmt, -+ unsigned int *nbuffers, unsigned int *nplanes, -+ unsigned int sizes[], void *alloc_ctxs[]) -+{ -+ struct emmaprp_ctx *ctx = vb2_get_drv_priv(vq); -+ struct emmaprp_q_data *q_data; -+ unsigned int size, count = *nbuffers; -+ -+ q_data = get_q_data(ctx, vq->type); -+ -+ if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420) -+ size = q_data->width * q_data->height * 3 / 2; -+ else -+ size = q_data->width * q_data->height * 2; -+ -+ while (size * count > MEM2MEM_VID_MEM_LIMIT) -+ (count)--; -+ -+ *nplanes = 1; -+ *nbuffers = count; -+ sizes[0] = size; -+ -+ alloc_ctxs[0] = ctx->dev->alloc_ctx; -+ -+ dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size); -+ -+ return 0; -+} -+ -+static int emmaprp_buf_prepare(struct vb2_buffer *vb) -+{ -+ struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); -+ struct emmaprp_q_data *q_data; -+ -+ dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type); -+ -+ q_data = get_q_data(ctx, vb->vb2_queue->type); -+ -+ if (vb2_plane_size(vb, 0) < q_data->sizeimage) { -+ dprintk(ctx->dev, "%s data will not fit into plane" -+ "(%lu < %lu)\n", __func__, -+ vb2_plane_size(vb, 0), -+ (long)q_data->sizeimage); -+ return -EINVAL; -+ } -+ -+ vb2_set_plane_payload(vb, 0, q_data->sizeimage); -+ -+ return 0; -+} -+ -+static void emmaprp_buf_queue(struct vb2_buffer *vb) -+{ -+ struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); -+ v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); -+} -+ -+static struct vb2_ops emmaprp_qops = { -+ .queue_setup = emmaprp_queue_setup, -+ .buf_prepare = emmaprp_buf_prepare, -+ .buf_queue = emmaprp_buf_queue, -+}; -+ -+static int queue_init(void *priv, struct vb2_queue *src_vq, -+ struct vb2_queue *dst_vq) -+{ -+ struct emmaprp_ctx *ctx = priv; -+ int ret; -+ -+ memset(src_vq, 0, sizeof(*src_vq)); -+ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ src_vq->io_modes = VB2_MMAP; -+ src_vq->drv_priv = ctx; -+ src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); -+ src_vq->ops = &emmaprp_qops; -+ src_vq->mem_ops = &vb2_dma_contig_memops; -+ -+ ret = vb2_queue_init(src_vq); -+ if (ret) -+ return ret; -+ -+ memset(dst_vq, 0, sizeof(*dst_vq)); -+ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ dst_vq->io_modes = VB2_MMAP; -+ dst_vq->drv_priv = ctx; -+ dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); -+ dst_vq->ops = &emmaprp_qops; -+ dst_vq->mem_ops = &vb2_dma_contig_memops; -+ -+ return vb2_queue_init(dst_vq); -+} -+ -+/* -+ * File operations -+ */ -+static int emmaprp_open(struct file *file) -+{ -+ struct emmaprp_dev *pcdev = video_drvdata(file); -+ struct emmaprp_ctx *ctx; -+ -+ ctx = kzalloc(sizeof *ctx, GFP_KERNEL); -+ if (!ctx) -+ return -ENOMEM; -+ -+ file->private_data = ctx; -+ ctx->dev = pcdev; -+ -+ ctx->m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init); -+ -+ if (IS_ERR(ctx->m2m_ctx)) { -+ int ret = PTR_ERR(ctx->m2m_ctx); -+ -+ kfree(ctx); -+ return ret; -+ } -+ -+ clk_enable(pcdev->clk_emma); -+ ctx->q_data[V4L2_M2M_SRC].fmt = &formats[1]; -+ ctx->q_data[V4L2_M2M_DST].fmt = &formats[0]; -+ -+ dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx); -+ -+ return 0; -+} -+ -+static int emmaprp_release(struct file *file) -+{ -+ struct emmaprp_dev *pcdev = video_drvdata(file); -+ struct emmaprp_ctx *ctx = file->private_data; -+ -+ dprintk(pcdev, "Releasing instance %p\n", ctx); -+ -+ clk_disable(pcdev->clk_emma); -+ v4l2_m2m_ctx_release(ctx->m2m_ctx); -+ kfree(ctx); -+ -+ return 0; -+} -+ -+static unsigned int emmaprp_poll(struct file *file, -+ struct poll_table_struct *wait) -+{ -+ struct emmaprp_ctx *ctx = file->private_data; -+ -+ return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); -+} -+ -+static int emmaprp_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ struct emmaprp_ctx *ctx = file->private_data; -+ -+ return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); -+} -+ -+static const struct v4l2_file_operations emmaprp_fops = { -+ .owner = THIS_MODULE, -+ .open = emmaprp_open, -+ .release = emmaprp_release, -+ .poll = emmaprp_poll, -+ .unlocked_ioctl = video_ioctl2, -+ .mmap = emmaprp_mmap, -+}; -+ -+static struct video_device emmaprp_videodev = { -+ .name = MEM2MEM_NAME, -+ .fops = &emmaprp_fops, -+ .ioctl_ops = &emmaprp_ioctl_ops, -+ .minor = -1, -+ .release = video_device_release, -+}; -+ -+static struct v4l2_m2m_ops m2m_ops = { -+ .device_run = emmaprp_device_run, -+ .job_abort = emmaprp_job_abort, -+ .lock = emmaprp_lock, -+ .unlock = emmaprp_unlock, -+}; -+ -+static int emmaprp_probe(struct platform_device *pdev) -+{ -+ struct emmaprp_dev *pcdev; -+ struct video_device *vfd; -+ struct resource *res_emma; -+ int irq_emma; -+ int ret; -+ -+ pcdev = kzalloc(sizeof *pcdev, GFP_KERNEL); -+ if (!pcdev) -+ return -ENOMEM; -+ -+ spin_lock_init(&pcdev->irqlock); -+ -+ pcdev->clk_emma = clk_get(&pdev->dev, NULL); -+ if (IS_ERR(pcdev->clk_emma)) { -+ ret = PTR_ERR(pcdev->clk_emma); -+ goto free_dev; -+ } -+ -+ irq_emma = platform_get_irq(pdev, 0); -+ res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (irq_emma < 0 || res_emma == NULL) { -+ dev_err(&pdev->dev, "Missing platform resources data\n"); -+ ret = -ENODEV; -+ goto free_clk; -+ } -+ -+ ret = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev); -+ if (ret) -+ goto free_clk; -+ -+ mutex_init(&pcdev->dev_mutex); -+ -+ vfd = video_device_alloc(); -+ if (!vfd) { -+ v4l2_err(&pcdev->v4l2_dev, "Failed to allocate video device\n"); -+ ret = -ENOMEM; -+ goto unreg_dev; -+ } -+ -+ *vfd = emmaprp_videodev; -+ vfd->lock = &pcdev->dev_mutex; -+ -+ video_set_drvdata(vfd, pcdev); -+ snprintf(vfd->name, sizeof(vfd->name), "%s", emmaprp_videodev.name); -+ pcdev->vfd = vfd; -+ v4l2_info(&pcdev->v4l2_dev, EMMAPRP_MODULE_NAME -+ " Device registered as /dev/video%d\n", vfd->num); -+ -+ platform_set_drvdata(pdev, pcdev); -+ -+ if (devm_request_mem_region(&pdev->dev, res_emma->start, -+ resource_size(res_emma), MEM2MEM_NAME) == NULL) -+ goto rel_vdev; -+ -+ pcdev->base_emma = devm_ioremap(&pdev->dev, res_emma->start, -+ resource_size(res_emma)); -+ if (!pcdev->base_emma) -+ goto rel_vdev; -+ -+ pcdev->irq_emma = irq_emma; -+ pcdev->res_emma = res_emma; -+ -+ if (devm_request_irq(&pdev->dev, pcdev->irq_emma, emmaprp_irq, -+ 0, MEM2MEM_NAME, pcdev) < 0) -+ goto rel_vdev; -+ -+ pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); -+ if (IS_ERR(pcdev->alloc_ctx)) { -+ v4l2_err(&pcdev->v4l2_dev, "Failed to alloc vb2 context\n"); -+ ret = PTR_ERR(pcdev->alloc_ctx); -+ goto rel_vdev; -+ } -+ -+ pcdev->m2m_dev = v4l2_m2m_init(&m2m_ops); -+ if (IS_ERR(pcdev->m2m_dev)) { -+ v4l2_err(&pcdev->v4l2_dev, "Failed to init mem2mem device\n"); -+ ret = PTR_ERR(pcdev->m2m_dev); -+ goto rel_ctx; -+ } -+ -+ ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); -+ if (ret) { -+ v4l2_err(&pcdev->v4l2_dev, "Failed to register video device\n"); -+ goto rel_m2m; -+ } -+ -+ return 0; -+ -+ -+rel_m2m: -+ v4l2_m2m_release(pcdev->m2m_dev); -+rel_ctx: -+ vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); -+rel_vdev: -+ video_device_release(vfd); -+unreg_dev: -+ v4l2_device_unregister(&pcdev->v4l2_dev); -+free_clk: -+ clk_put(pcdev->clk_emma); -+free_dev: -+ kfree(pcdev); -+ -+ return ret; -+} -+ -+static int emmaprp_remove(struct platform_device *pdev) -+{ -+ struct emmaprp_dev *pcdev = platform_get_drvdata(pdev); -+ -+ v4l2_info(&pcdev->v4l2_dev, "Removing " EMMAPRP_MODULE_NAME); -+ -+ video_unregister_device(pcdev->vfd); -+ v4l2_m2m_release(pcdev->m2m_dev); -+ vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); -+ v4l2_device_unregister(&pcdev->v4l2_dev); -+ clk_put(pcdev->clk_emma); -+ kfree(pcdev); -+ -+ return 0; -+} -+ -+static struct platform_driver emmaprp_pdrv = { -+ .probe = emmaprp_probe, -+ .remove = emmaprp_remove, -+ .driver = { -+ .name = MEM2MEM_NAME, -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static void __exit emmaprp_exit(void) -+{ -+ platform_driver_unregister(&emmaprp_pdrv); -+} -+ -+static int __init emmaprp_init(void) -+{ -+ return platform_driver_register(&emmaprp_pdrv); -+} -+ -+module_init(emmaprp_init); -+module_exit(emmaprp_exit); -Index: linux-3.3.x86_64/drivers/media/common/tuners/mt2063.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/common/tuners/mt2063.h -+++ linux-3.3.x86_64/drivers/media/common/tuners/mt2063.h -@@ -23,10 +23,6 @@ static inline struct dvb_frontend *mt206 - return NULL; - } - --int mt2063_setTune(struct dvb_frontend *fe, u32 f_in, -- u32 bw_in, -- enum MTTune_atv_standard tv_type); -- - /* FIXME: Should use the standard DVB attachment interfaces */ - unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe); - unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe); -Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/sdo_drv.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/sdo_drv.c -+++ linux-3.3.x86_64/drivers/media/video/s5p-tv/sdo_drv.c -@@ -301,7 +301,7 @@ static int __devinit sdo_probe(struct pl - struct clk *sclk_vpll; - - dev_info(dev, "probe start\n"); -- sdev = kzalloc(sizeof *sdev, GFP_KERNEL); -+ sdev = devm_kzalloc(&pdev->dev, sizeof *sdev, GFP_KERNEL); - if (!sdev) { - dev_err(dev, "not enough memory.\n"); - ret = -ENOMEM; -@@ -314,14 +314,14 @@ static int __devinit sdo_probe(struct pl - if (res == NULL) { - dev_err(dev, "get memory resource failed.\n"); - ret = -ENXIO; -- goto fail_sdev; -+ goto fail; - } - -- sdev->regs = ioremap(res->start, resource_size(res)); -+ sdev->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (sdev->regs == NULL) { - dev_err(dev, "register mapping failed.\n"); - ret = -ENXIO; -- goto fail_sdev; -+ goto fail; - } - - /* acquiring interrupt */ -@@ -329,12 +329,13 @@ static int __devinit sdo_probe(struct pl - if (res == NULL) { - dev_err(dev, "get interrupt resource failed.\n"); - ret = -ENXIO; -- goto fail_regs; -+ goto fail; - } -- ret = request_irq(res->start, sdo_irq_handler, 0, "s5p-sdo", sdev); -+ ret = devm_request_irq(&pdev->dev, res->start, sdo_irq_handler, 0, -+ "s5p-sdo", sdev); - if (ret) { - dev_err(dev, "request interrupt failed.\n"); -- goto fail_regs; -+ goto fail; - } - sdev->irq = res->start; - -@@ -343,7 +344,7 @@ static int __devinit sdo_probe(struct pl - if (IS_ERR_OR_NULL(sdev->sclk_dac)) { - dev_err(dev, "failed to get clock 'sclk_dac'\n"); - ret = -ENXIO; -- goto fail_irq; -+ goto fail; - } - sdev->dac = clk_get(dev, "dac"); - if (IS_ERR_OR_NULL(sdev->dac)) { -@@ -415,12 +416,6 @@ fail_dac: - clk_put(sdev->dac); - fail_sclk_dac: - clk_put(sdev->sclk_dac); --fail_irq: -- free_irq(sdev->irq, sdev); --fail_regs: -- iounmap(sdev->regs); --fail_sdev: -- kfree(sdev); - fail: - dev_info(dev, "probe failed\n"); - return ret; -@@ -439,9 +434,6 @@ static int __devexit sdo_remove(struct p - clk_put(sdev->dacphy); - clk_put(sdev->dac); - clk_put(sdev->sclk_dac); -- free_irq(sdev->irq, sdev); -- iounmap(sdev->regs); -- kfree(sdev); - - dev_info(&pdev->dev, "remove successful\n"); - return 0; -Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/Kconfig -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/Kconfig -+++ linux-3.3.x86_64/drivers/media/video/s5p-tv/Kconfig -@@ -46,6 +46,16 @@ config VIDEO_SAMSUNG_S5P_HDMIPHY - as module. It is an I2C driver, that exposes a V4L2 - subdev for use by other drivers. - -+config VIDEO_SAMSUNG_S5P_SII9234 -+ tristate "Samsung SII9234 Driver" -+ depends on VIDEO_DEV && VIDEO_V4L2 && I2C -+ depends on VIDEO_SAMSUNG_S5P_TV -+ help -+ Say Y here if you want support for the MHL interface -+ in S5P Samsung SoC. The driver can be compiled -+ as module. It is an I2C driver, that exposes a V4L2 -+ subdev for use by other drivers. -+ - config VIDEO_SAMSUNG_S5P_SDO - tristate "Samsung Analog TV Driver" - depends on VIDEO_DEV && VIDEO_V4L2 -Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/Makefile -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/Makefile -+++ linux-3.3.x86_64/drivers/media/video/s5p-tv/Makefile -@@ -8,6 +8,8 @@ - - obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMIPHY) += s5p-hdmiphy.o - s5p-hdmiphy-y += hdmiphy_drv.o -+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SII9234) += s5p-sii9234.o -+s5p-sii9234-y += sii9234_drv.o - obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMI) += s5p-hdmi.o - s5p-hdmi-y += hdmi_drv.o - obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SDO) += s5p-sdo.o -Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/sii9234_drv.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/video/s5p-tv/sii9234_drv.c -@@ -0,0 +1,432 @@ -+/* -+ * Samsung MHL interface driver -+ * -+ * Copyright (C) 2011 Samsung Electronics Co.Ltd -+ * Author: Tomasz Stanislawski -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+ -+MODULE_AUTHOR("Tomasz Stanislawski "); -+MODULE_DESCRIPTION("Samsung MHL interface driver"); -+MODULE_LICENSE("GPL"); -+ -+struct sii9234_context { -+ struct i2c_client *client; -+ struct regulator *power; -+ int gpio_n_reset; -+ struct v4l2_subdev sd; -+}; -+ -+static inline struct sii9234_context *sd_to_context(struct v4l2_subdev *sd) -+{ -+ return container_of(sd, struct sii9234_context, sd); -+} -+ -+static inline int sii9234_readb(struct i2c_client *client, int addr) -+{ -+ return i2c_smbus_read_byte_data(client, addr); -+} -+ -+static inline int sii9234_writeb(struct i2c_client *client, int addr, int value) -+{ -+ return i2c_smbus_write_byte_data(client, addr, value); -+} -+ -+static inline int sii9234_writeb_mask(struct i2c_client *client, int addr, -+ int value, int mask) -+{ -+ int ret; -+ -+ ret = i2c_smbus_read_byte_data(client, addr); -+ if (ret < 0) -+ return ret; -+ ret = (ret & ~mask) | (value & mask); -+ return i2c_smbus_write_byte_data(client, addr, ret); -+} -+ -+static inline int sii9234_readb_idx(struct i2c_client *client, int addr) -+{ -+ int ret; -+ ret = i2c_smbus_write_byte_data(client, 0xbc, addr >> 8); -+ if (ret < 0) -+ return ret; -+ ret = i2c_smbus_write_byte_data(client, 0xbd, addr & 0xff); -+ if (ret < 0) -+ return ret; -+ return i2c_smbus_read_byte_data(client, 0xbe); -+} -+ -+static inline int sii9234_writeb_idx(struct i2c_client *client, int addr, -+ int value) -+{ -+ int ret; -+ ret = i2c_smbus_write_byte_data(client, 0xbc, addr >> 8); -+ if (ret < 0) -+ return ret; -+ ret = i2c_smbus_write_byte_data(client, 0xbd, addr & 0xff); -+ if (ret < 0) -+ return ret; -+ ret = i2c_smbus_write_byte_data(client, 0xbe, value); -+ return ret; -+} -+ -+static inline int sii9234_writeb_idx_mask(struct i2c_client *client, int addr, -+ int value, int mask) -+{ -+ int ret; -+ -+ ret = sii9234_readb_idx(client, addr); -+ if (ret < 0) -+ return ret; -+ ret = (ret & ~mask) | (value & mask); -+ return sii9234_writeb_idx(client, addr, ret); -+} -+ -+static int sii9234_reset(struct sii9234_context *ctx) -+{ -+ struct i2c_client *client = ctx->client; -+ struct device *dev = &client->dev; -+ int ret, tries; -+ -+ gpio_direction_output(ctx->gpio_n_reset, 1); -+ mdelay(1); -+ gpio_direction_output(ctx->gpio_n_reset, 0); -+ mdelay(1); -+ gpio_direction_output(ctx->gpio_n_reset, 1); -+ mdelay(1); -+ -+ /* going to TTPI mode */ -+ ret = sii9234_writeb(client, 0xc7, 0); -+ if (ret < 0) { -+ dev_err(dev, "failed to set TTPI mode\n"); -+ return ret; -+ } -+ for (tries = 0; tries < 100 ; ++tries) { -+ ret = sii9234_readb(client, 0x1b); -+ if (ret > 0) -+ break; -+ if (ret < 0) { -+ dev_err(dev, "failed to reset device\n"); -+ return -EIO; -+ } -+ mdelay(1); -+ } -+ if (tries == 100) { -+ dev_err(dev, "maximal number of tries reached\n"); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+static int sii9234_verify_version(struct i2c_client *client) -+{ -+ struct device *dev = &client->dev; -+ int family, rev, tpi_rev, dev_id, sub_id, hdcp, id; -+ -+ family = sii9234_readb(client, 0x1b); -+ rev = sii9234_readb(client, 0x1c) & 0x0f; -+ tpi_rev = sii9234_readb(client, 0x1d) & 0x7f; -+ dev_id = sii9234_readb_idx(client, 0x0103); -+ sub_id = sii9234_readb_idx(client, 0x0102); -+ hdcp = sii9234_readb(client, 0x30); -+ -+ if (family < 0 || rev < 0 || tpi_rev < 0 || dev_id < 0 || -+ sub_id < 0 || hdcp < 0) { -+ dev_err(dev, "failed to read chip's version\n"); -+ return -EIO; -+ } -+ -+ id = (dev_id << 8) | sub_id; -+ -+ dev_info(dev, "chip: SiL%02x family: %02x, rev: %02x\n", -+ id, family, rev); -+ dev_info(dev, "tpi_rev:%02x, hdcp: %02x\n", tpi_rev, hdcp); -+ if (id != 0x9234) { -+ dev_err(dev, "not supported chip\n"); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+static u8 data[][3] = { -+/* setup from driver created by doonsoo45.kim */ -+ { 0x01, 0x05, 0x04 }, /* Enable Auto soft reset on SCDT = 0 */ -+ { 0x01, 0x08, 0x35 }, /* Power Up TMDS Tx Core */ -+ { 0x01, 0x0d, 0x1c }, /* HDMI Transcode mode enable */ -+ { 0x01, 0x2b, 0x01 }, /* Enable HDCP Compliance workaround */ -+ { 0x01, 0x79, 0x40 }, /* daniel test...MHL_INT */ -+ { 0x01, 0x80, 0x34 }, /* Enable Rx PLL Clock Value */ -+ { 0x01, 0x90, 0x27 }, /* Enable CBUS discovery */ -+ { 0x01, 0x91, 0xe5 }, /* Skip RGND detection */ -+ { 0x01, 0x92, 0x46 }, /* Force MHD mode */ -+ { 0x01, 0x93, 0xdc }, /* Disable CBUS pull-up during RGND measurement */ -+ { 0x01, 0x94, 0x66 }, /* 1.8V CBUS VTH & GND threshold */ -+ { 0x01, 0x95, 0x31 }, /* RGND block & single discovery attempt */ -+ { 0x01, 0x96, 0x22 }, /* use 1K and 2K setting */ -+ { 0x01, 0xa0, 0x10 }, /* SIMG: Term mode */ -+ { 0x01, 0xa1, 0xfc }, /* Disable internal Mobile HD driver */ -+ { 0x01, 0xa3, 0xfa }, /* SIMG: Output Swing default EB, 3x Clk Mult */ -+ { 0x01, 0xa5, 0x80 }, /* SIMG: RGND Hysterisis, 3x mode for Beast */ -+ { 0x01, 0xa6, 0x0c }, /* SIMG: Swing Offset */ -+ { 0x02, 0x3d, 0x3f }, /* Power up CVCC 1.2V core */ -+ { 0x03, 0x00, 0x00 }, /* SIMG: correcting HW default */ -+ { 0x03, 0x11, 0x01 }, /* Enable TxPLL Clock */ -+ { 0x03, 0x12, 0x15 }, /* Enable Tx Clock Path & Equalizer */ -+ { 0x03, 0x13, 0x60 }, /* SIMG: Set termination value */ -+ { 0x03, 0x14, 0xf0 }, /* SIMG: Change CKDT level */ -+ { 0x03, 0x17, 0x07 }, /* SIMG: PLL Calrefsel */ -+ { 0x03, 0x1a, 0x20 }, /* VCO Cal */ -+ { 0x03, 0x22, 0xe0 }, /* SIMG: Auto EQ */ -+ { 0x03, 0x23, 0xc0 }, /* SIMG: Auto EQ */ -+ { 0x03, 0x24, 0xa0 }, /* SIMG: Auto EQ */ -+ { 0x03, 0x25, 0x80 }, /* SIMG: Auto EQ */ -+ { 0x03, 0x26, 0x60 }, /* SIMG: Auto EQ */ -+ { 0x03, 0x27, 0x40 }, /* SIMG: Auto EQ */ -+ { 0x03, 0x28, 0x20 }, /* SIMG: Auto EQ */ -+ { 0x03, 0x29, 0x00 }, /* SIMG: Auto EQ */ -+ { 0x03, 0x31, 0x0b }, /* SIMG: Rx PLL BW value from I2C BW ~ 4MHz */ -+ { 0x03, 0x45, 0x06 }, /* SIMG: DPLL Mode */ -+ { 0x03, 0x4b, 0x06 }, /* SIMG: Correcting HW default */ -+ { 0x03, 0x4c, 0xa0 }, /* Manual zone control */ -+ { 0x03, 0x4d, 0x02 }, /* SIMG: PLL Mode Value (order is important) */ -+}; -+ -+static int sii9234_set_internal(struct sii9234_context *ctx) -+{ -+ struct i2c_client *client = ctx->client; -+ int i, ret; -+ -+ for (i = 0; i < ARRAY_SIZE(data); ++i) { -+ int addr = (data[i][0] << 8) | data[i][1]; -+ ret = sii9234_writeb_idx(client, addr, data[i][2]); -+ if (ret < 0) -+ return ret; -+ } -+ return 0; -+} -+ -+static int sii9234_runtime_suspend(struct device *dev) -+{ -+ struct v4l2_subdev *sd = dev_get_drvdata(dev); -+ struct sii9234_context *ctx = sd_to_context(sd); -+ struct i2c_client *client = ctx->client; -+ -+ dev_info(dev, "suspend start\n"); -+ -+ sii9234_writeb_mask(client, 0x1e, 3, 3); -+ regulator_disable(ctx->power); -+ -+ return 0; -+} -+ -+static int sii9234_runtime_resume(struct device *dev) -+{ -+ struct v4l2_subdev *sd = dev_get_drvdata(dev); -+ struct sii9234_context *ctx = sd_to_context(sd); -+ struct i2c_client *client = ctx->client; -+ int ret; -+ -+ dev_info(dev, "resume start\n"); -+ regulator_enable(ctx->power); -+ -+ ret = sii9234_reset(ctx); -+ if (ret) -+ goto fail; -+ -+ /* enable tpi */ -+ ret = sii9234_writeb_mask(client, 0x1e, 1, 0); -+ if (ret < 0) -+ goto fail; -+ ret = sii9234_set_internal(ctx); -+ if (ret < 0) -+ goto fail; -+ -+ return 0; -+ -+fail: -+ dev_err(dev, "failed to resume\n"); -+ regulator_disable(ctx->power); -+ -+ return ret; -+} -+ -+static const struct dev_pm_ops sii9234_pm_ops = { -+ .runtime_suspend = sii9234_runtime_suspend, -+ .runtime_resume = sii9234_runtime_resume, -+}; -+ -+static int sii9234_s_power(struct v4l2_subdev *sd, int on) -+{ -+ struct sii9234_context *ctx = sd_to_context(sd); -+ int ret; -+ -+ if (on) -+ ret = pm_runtime_get_sync(&ctx->client->dev); -+ else -+ ret = pm_runtime_put(&ctx->client->dev); -+ /* only values < 0 indicate errors */ -+ return IS_ERR_VALUE(ret) ? ret : 0; -+} -+ -+static int sii9234_s_stream(struct v4l2_subdev *sd, int enable) -+{ -+ struct sii9234_context *ctx = sd_to_context(sd); -+ -+ /* (dis/en)able TDMS output */ -+ sii9234_writeb_mask(ctx->client, 0x1a, enable ? 0 : ~0 , 1 << 4); -+ return 0; -+} -+ -+static const struct v4l2_subdev_core_ops sii9234_core_ops = { -+ .s_power = sii9234_s_power, -+}; -+ -+static const struct v4l2_subdev_video_ops sii9234_video_ops = { -+ .s_stream = sii9234_s_stream, -+}; -+ -+static const struct v4l2_subdev_ops sii9234_ops = { -+ .core = &sii9234_core_ops, -+ .video = &sii9234_video_ops, -+}; -+ -+static int __devinit sii9234_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+{ -+ struct device *dev = &client->dev; -+ struct sii9234_platform_data *pdata = dev->platform_data; -+ struct sii9234_context *ctx; -+ int ret; -+ -+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); -+ if (!ctx) { -+ dev_err(dev, "out of memory\n"); -+ ret = -ENOMEM; -+ goto fail; -+ } -+ ctx->client = client; -+ -+ ctx->power = regulator_get(dev, "hdmi-en"); -+ if (IS_ERR(ctx->power)) { -+ dev_err(dev, "failed to acquire regulator hdmi-en\n"); -+ ret = PTR_ERR(ctx->power); -+ goto fail_ctx; -+ } -+ -+ ctx->gpio_n_reset = pdata->gpio_n_reset; -+ ret = gpio_request(ctx->gpio_n_reset, "MHL_RST"); -+ if (ret) { -+ dev_err(dev, "failed to acquire MHL_RST gpio\n"); -+ goto fail_power; -+ } -+ -+ v4l2_i2c_subdev_init(&ctx->sd, client, &sii9234_ops); -+ -+ pm_runtime_enable(dev); -+ -+ /* enable device */ -+ ret = pm_runtime_get_sync(dev); -+ if (ret) -+ goto fail_pm; -+ -+ /* verify chip version */ -+ ret = sii9234_verify_version(client); -+ if (ret) -+ goto fail_pm_get; -+ -+ /* stop processing */ -+ pm_runtime_put(dev); -+ -+ dev_info(dev, "probe successful\n"); -+ -+ return 0; -+ -+fail_pm_get: -+ pm_runtime_put_sync(dev); -+ -+fail_pm: -+ pm_runtime_disable(dev); -+ gpio_free(ctx->gpio_n_reset); -+ -+fail_power: -+ regulator_put(ctx->power); -+ -+fail_ctx: -+ kfree(ctx); -+ -+fail: -+ dev_err(dev, "probe failed\n"); -+ -+ return ret; -+} -+ -+static int __devexit sii9234_remove(struct i2c_client *client) -+{ -+ struct device *dev = &client->dev; -+ struct v4l2_subdev *sd = i2c_get_clientdata(client); -+ struct sii9234_context *ctx = sd_to_context(sd); -+ -+ pm_runtime_disable(dev); -+ gpio_free(ctx->gpio_n_reset); -+ regulator_put(ctx->power); -+ kfree(ctx); -+ -+ dev_info(dev, "remove successful\n"); -+ -+ return 0; -+} -+ -+ -+static const struct i2c_device_id sii9234_id[] = { -+ { "SII9234", 0 }, -+ { }, -+}; -+ -+MODULE_DEVICE_TABLE(i2c, sii9234_id); -+static struct i2c_driver sii9234_driver = { -+ .driver = { -+ .name = "sii9234", -+ .owner = THIS_MODULE, -+ .pm = &sii9234_pm_ops, -+ }, -+ .probe = sii9234_probe, -+ .remove = __devexit_p(sii9234_remove), -+ .id_table = sii9234_id, -+}; -+ -+static int __init sii9234_init(void) -+{ -+ return i2c_add_driver(&sii9234_driver); -+} -+module_init(sii9234_init); -+ -+static void __exit sii9234_exit(void) -+{ -+ i2c_del_driver(&sii9234_driver); -+} -+module_exit(sii9234_exit); -Index: linux-3.3.x86_64/include/media/sii9234.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/include/media/sii9234.h -@@ -0,0 +1,24 @@ -+/* -+ * Driver header for SII9234 MHL converter chip. -+ * -+ * Copyright (c) 2011 Samsung Electronics, Co. Ltd -+ * Contact: Tomasz Stanislawski -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#ifndef SII9234_H -+#define SII9234_H -+ -+/** -+ * @gpio_n_reset: GPIO driving nRESET pin -+ */ -+ -+struct sii9234_platform_data { -+ int gpio_n_reset; -+}; -+ -+#endif /* SII9234_H */ -Index: linux-3.3.x86_64/include/media/s5p_hdmi.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/include/media/s5p_hdmi.h -@@ -0,0 +1,35 @@ -+/* -+ * Driver header for S5P HDMI chip. -+ * -+ * Copyright (c) 2011 Samsung Electronics, Co. Ltd -+ * Contact: Tomasz Stanislawski -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#ifndef S5P_HDMI_H -+#define S5P_HDMI_H -+ -+struct i2c_board_info; -+ -+/** -+ * @hdmiphy_bus: controller id for HDMIPHY bus -+ * @hdmiphy_info: template for HDMIPHY I2C device -+ * @mhl_bus: controller id for MHL control bus -+ * @mhl_info: template for MHL I2C device -+ * -+ * NULL pointer for *_info fields indicates that -+ * the corresponding chip is not present -+ */ -+struct s5p_hdmi_platform_data { -+ int hdmiphy_bus; -+ struct i2c_board_info *hdmiphy_info; -+ int mhl_bus; -+ struct i2c_board_info *mhl_info; -+}; -+ -+#endif /* S5P_HDMI_H */ -+ -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/Kconfig -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/Kconfig -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/Kconfig -@@ -425,6 +425,13 @@ config DVB_CXD2820R - help - Say Y when you want to support this frontend. - -+config DVB_RTL2830 -+ tristate "Realtek RTL2830 DVB-T" -+ depends on DVB_CORE && I2C -+ default m if DVB_FE_CUSTOMISE -+ help -+ Say Y when you want to support this frontend. -+ - comment "DVB-C (cable) frontends" - depends on DVB_CORE - -@@ -698,6 +705,19 @@ config DVB_IT913X_FE - A DVB-T tuner module. - Say Y when you want to support this frontend. - -+config DVB_M88RS2000 -+ tristate "M88RS2000 DVB-S demodulator and tuner" -+ depends on DVB_CORE && I2C -+ default m if DVB_FE_CUSTOMISE -+ help -+ A DVB-S tuner module. -+ Say Y when you want to support this frontend. -+ -+config DVB_AF9033 -+ tristate "Afatech AF9033 DVB-T demodulator" -+ depends on DVB_CORE && I2C -+ default m if DVB_FE_CUSTOMISE -+ - comment "Tools to develop new frontends" - - config DVB_DUMMY_FE -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/Makefile -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/Makefile -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/Makefile -@@ -2,8 +2,8 @@ - # Makefile for the kernel DVB frontend device drivers. - # - --ccflags-y += -Idrivers/media/dvb/dvb-core/ --ccflags-y += -Idrivers/media/common/tuners/ -+ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core/ -+ccflags-y += -I$(srctree)/drivers/media/common/tuners/ - - stb0899-objs = stb0899_drv.o stb0899_algo.o - stv0900-objs = stv0900_core.o stv0900_sw.o -@@ -96,4 +96,7 @@ obj-$(CONFIG_DVB_TDA18271C2DD) += tda182 - obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o - obj-$(CONFIG_DVB_A8293) += a8293.o - obj-$(CONFIG_DVB_TDA10071) += tda10071.o -+obj-$(CONFIG_DVB_RTL2830) += rtl2830.o -+obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o -+obj-$(CONFIG_DVB_AF9033) += af9033.o - -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830.c -@@ -0,0 +1,562 @@ -+/* -+ * Realtek RTL2830 DVB-T demodulator driver -+ * -+ * Copyright (C) 2011 Antti Palosaari -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+ -+/* -+ * Driver implements own I2C-adapter for tuner I2C access. That's since chip -+ * have unusual I2C-gate control which closes gate automatically after each -+ * I2C transfer. Using own I2C adapter we can workaround that. -+ */ -+ -+#include "rtl2830_priv.h" -+ -+int rtl2830_debug; -+module_param_named(debug, rtl2830_debug, int, 0644); -+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -+ -+/* write multiple hardware registers */ -+static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, u8 *val, int len) -+{ -+ int ret; -+ u8 buf[1+len]; -+ struct i2c_msg msg[1] = { -+ { -+ .addr = priv->cfg.i2c_addr, -+ .flags = 0, -+ .len = 1+len, -+ .buf = buf, -+ } -+ }; -+ -+ buf[0] = reg; -+ memcpy(&buf[1], val, len); -+ -+ ret = i2c_transfer(priv->i2c, msg, 1); -+ if (ret == 1) { -+ ret = 0; -+ } else { -+ warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len); -+ ret = -EREMOTEIO; -+ } -+ return ret; -+} -+ -+/* read multiple hardware registers */ -+static int rtl2830_rd(struct rtl2830_priv *priv, u8 reg, u8 *val, int len) -+{ -+ int ret; -+ struct i2c_msg msg[2] = { -+ { -+ .addr = priv->cfg.i2c_addr, -+ .flags = 0, -+ .len = 1, -+ .buf = ®, -+ }, { -+ .addr = priv->cfg.i2c_addr, -+ .flags = I2C_M_RD, -+ .len = len, -+ .buf = val, -+ } -+ }; -+ -+ ret = i2c_transfer(priv->i2c, msg, 2); -+ if (ret == 2) { -+ ret = 0; -+ } else { -+ warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len); -+ ret = -EREMOTEIO; -+ } -+ return ret; -+} -+ -+/* write multiple registers */ -+static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) -+{ -+ int ret; -+ u8 reg2 = (reg >> 0) & 0xff; -+ u8 page = (reg >> 8) & 0xff; -+ -+ /* switch bank if needed */ -+ if (page != priv->page) { -+ ret = rtl2830_wr(priv, 0x00, &page, 1); -+ if (ret) -+ return ret; -+ -+ priv->page = page; -+ } -+ -+ return rtl2830_wr(priv, reg2, val, len); -+} -+ -+/* read multiple registers */ -+static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len) -+{ -+ int ret; -+ u8 reg2 = (reg >> 0) & 0xff; -+ u8 page = (reg >> 8) & 0xff; -+ -+ /* switch bank if needed */ -+ if (page != priv->page) { -+ ret = rtl2830_wr(priv, 0x00, &page, 1); -+ if (ret) -+ return ret; -+ -+ priv->page = page; -+ } -+ -+ return rtl2830_rd(priv, reg2, val, len); -+} -+ -+#if 0 /* currently not used */ -+/* write single register */ -+static int rtl2830_wr_reg(struct rtl2830_priv *priv, u16 reg, u8 val) -+{ -+ return rtl2830_wr_regs(priv, reg, &val, 1); -+} -+#endif -+ -+/* read single register */ -+static int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val) -+{ -+ return rtl2830_rd_regs(priv, reg, val, 1); -+} -+ -+/* write single register with mask */ -+int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask) -+{ -+ int ret; -+ u8 tmp; -+ -+ /* no need for read if whole reg is written */ -+ if (mask != 0xff) { -+ ret = rtl2830_rd_regs(priv, reg, &tmp, 1); -+ if (ret) -+ return ret; -+ -+ val &= mask; -+ tmp &= ~mask; -+ val |= tmp; -+ } -+ -+ return rtl2830_wr_regs(priv, reg, &val, 1); -+} -+ -+/* read single register with mask */ -+int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask) -+{ -+ int ret, i; -+ u8 tmp; -+ -+ ret = rtl2830_rd_regs(priv, reg, &tmp, 1); -+ if (ret) -+ return ret; -+ -+ tmp &= mask; -+ -+ /* find position of the first bit */ -+ for (i = 0; i < 8; i++) { -+ if ((mask >> i) & 0x01) -+ break; -+ } -+ *val = tmp >> i; -+ -+ return 0; -+} -+ -+static int rtl2830_init(struct dvb_frontend *fe) -+{ -+ struct rtl2830_priv *priv = fe->demodulator_priv; -+ int ret, i; -+ u64 num; -+ u8 buf[3], tmp; -+ u32 if_ctl; -+ struct rtl2830_reg_val_mask tab[] = { -+ { 0x00d, 0x01, 0x03 }, -+ { 0x00d, 0x10, 0x10 }, -+ { 0x104, 0x00, 0x1e }, -+ { 0x105, 0x80, 0x80 }, -+ { 0x110, 0x02, 0x03 }, -+ { 0x110, 0x08, 0x0c }, -+ { 0x17b, 0x00, 0x40 }, -+ { 0x17d, 0x05, 0x0f }, -+ { 0x17d, 0x50, 0xf0 }, -+ { 0x18c, 0x08, 0x0f }, -+ { 0x18d, 0x00, 0xc0 }, -+ { 0x188, 0x05, 0x0f }, -+ { 0x189, 0x00, 0xfc }, -+ { 0x2d5, 0x02, 0x02 }, -+ { 0x2f1, 0x02, 0x06 }, -+ { 0x2f1, 0x20, 0xf8 }, -+ { 0x16d, 0x00, 0x01 }, -+ { 0x1a6, 0x00, 0x80 }, -+ { 0x106, priv->cfg.vtop, 0x3f }, -+ { 0x107, priv->cfg.krf, 0x3f }, -+ { 0x112, 0x28, 0xff }, -+ { 0x103, priv->cfg.agc_targ_val, 0xff }, -+ { 0x00a, 0x02, 0x07 }, -+ { 0x140, 0x0c, 0x3c }, -+ { 0x140, 0x40, 0xc0 }, -+ { 0x15b, 0x05, 0x07 }, -+ { 0x15b, 0x28, 0x38 }, -+ { 0x15c, 0x05, 0x07 }, -+ { 0x15c, 0x28, 0x38 }, -+ { 0x115, priv->cfg.spec_inv, 0x01 }, -+ { 0x16f, 0x01, 0x07 }, -+ { 0x170, 0x18, 0x38 }, -+ { 0x172, 0x0f, 0x0f }, -+ { 0x173, 0x08, 0x38 }, -+ { 0x175, 0x01, 0x07 }, -+ { 0x176, 0x00, 0xc0 }, -+ }; -+ -+ for (i = 0; i < ARRAY_SIZE(tab); i++) { -+ ret = rtl2830_wr_reg_mask(priv, tab[i].reg, tab[i].val, -+ tab[i].mask); -+ if (ret) -+ goto err; -+ } -+ -+ ret = rtl2830_wr_regs(priv, 0x18f, "\x28\x00", 2); -+ if (ret) -+ goto err; -+ -+ ret = rtl2830_wr_regs(priv, 0x195, -+ "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8); -+ if (ret) -+ goto err; -+ -+ num = priv->cfg.if_dvbt % priv->cfg.xtal; -+ num *= 0x400000; -+ num = div_u64(num, priv->cfg.xtal); -+ num = -num; -+ if_ctl = num & 0x3fffff; -+ dbg("%s: if_ctl=%08x", __func__, if_ctl); -+ -+ ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */ -+ if (ret) -+ goto err; -+ -+ buf[0] = tmp << 6; -+ buf[0] = (if_ctl >> 16) & 0x3f; -+ buf[1] = (if_ctl >> 8) & 0xff; -+ buf[2] = (if_ctl >> 0) & 0xff; -+ -+ ret = rtl2830_wr_regs(priv, 0x119, buf, 3); -+ if (ret) -+ goto err; -+ -+ /* TODO: spec init */ -+ -+ /* soft reset */ -+ ret = rtl2830_wr_reg_mask(priv, 0x101, 0x04, 0x04); -+ if (ret) -+ goto err; -+ -+ ret = rtl2830_wr_reg_mask(priv, 0x101, 0x00, 0x04); -+ if (ret) -+ goto err; -+ -+ priv->sleeping = false; -+ -+ return ret; -+err: -+ dbg("%s: failed=%d", __func__, ret); -+ return ret; -+} -+ -+static int rtl2830_sleep(struct dvb_frontend *fe) -+{ -+ struct rtl2830_priv *priv = fe->demodulator_priv; -+ priv->sleeping = true; -+ return 0; -+} -+ -+int rtl2830_get_tune_settings(struct dvb_frontend *fe, -+ struct dvb_frontend_tune_settings *s) -+{ -+ s->min_delay_ms = 500; -+ s->step_size = fe->ops.info.frequency_stepsize * 2; -+ s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; -+ -+ return 0; -+} -+ -+static int rtl2830_set_frontend(struct dvb_frontend *fe) -+{ -+ struct rtl2830_priv *priv = fe->demodulator_priv; -+ struct dtv_frontend_properties *c = &fe->dtv_property_cache; -+ int ret, i; -+ static u8 bw_params1[3][34] = { -+ { -+ 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41, -+ 0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a, -+ 0x1f, 0x47, 0x1f, 0x7c, 0x00, 0x30, 0x01, 0x4b, 0x02, 0x82, -+ 0x03, 0x73, 0x03, 0xcf, /* 6 MHz */ -+ }, { -+ 0x1f, 0xfa, 0x1f, 0xda, 0x1f, 0xc1, 0x1f, 0xb3, 0x1f, 0xca, -+ 0x00, 0x07, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x40, 0x1f, 0xca, -+ 0x1f, 0x4d, 0x1f, 0x2a, 0x1f, 0xb2, 0x00, 0xec, 0x02, 0x7e, -+ 0x03, 0xd0, 0x04, 0x53, /* 7 MHz */ -+ }, { -+ 0x00, 0x10, 0x00, 0x0e, 0x1f, 0xf7, 0x1f, 0xc9, 0x1f, 0xa0, -+ 0x1f, 0xa6, 0x1f, 0xec, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x3a, -+ 0x1f, 0x98, 0x1f, 0x10, 0x1f, 0x40, 0x00, 0x75, 0x02, 0x5f, -+ 0x04, 0x24, 0x04, 0xdb, /* 8 MHz */ -+ }, -+ }; -+ static u8 bw_params2[3][6] = { -+ {0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30,}, /* 6 MHz */ -+ {0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98,}, /* 7 MHz */ -+ {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64,}, /* 8 MHz */ -+ }; -+ -+ -+ dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__, -+ c->frequency, c->bandwidth_hz, c->inversion); -+ -+ /* program tuner */ -+ if (fe->ops.tuner_ops.set_params) -+ fe->ops.tuner_ops.set_params(fe); -+ -+ switch (c->bandwidth_hz) { -+ case 6000000: -+ i = 0; -+ break; -+ case 7000000: -+ i = 1; -+ break; -+ case 8000000: -+ i = 2; -+ break; -+ default: -+ dbg("invalid bandwidth"); -+ return -EINVAL; -+ } -+ -+ ret = rtl2830_wr_reg_mask(priv, 0x008, i << 1, 0x06); -+ if (ret) -+ goto err; -+ -+ /* 1/2 split I2C write */ -+ ret = rtl2830_wr_regs(priv, 0x11c, &bw_params1[i][0], 17); -+ if (ret) -+ goto err; -+ -+ /* 2/2 split I2C write */ -+ ret = rtl2830_wr_regs(priv, 0x12d, &bw_params1[i][17], 17); -+ if (ret) -+ goto err; -+ -+ ret = rtl2830_wr_regs(priv, 0x19d, bw_params2[i], 6); -+ if (ret) -+ goto err; -+ -+ return ret; -+err: -+ dbg("%s: failed=%d", __func__, ret); -+ return ret; -+} -+ -+static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status) -+{ -+ struct rtl2830_priv *priv = fe->demodulator_priv; -+ int ret; -+ u8 tmp; -+ *status = 0; -+ -+ if (priv->sleeping) -+ return 0; -+ -+ ret = rtl2830_rd_reg_mask(priv, 0x351, &tmp, 0x78); /* [6:3] */ -+ if (ret) -+ goto err; -+ -+ if (tmp == 11) { -+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | -+ FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; -+ } else if (tmp == 10) { -+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | -+ FE_HAS_VITERBI; -+ } -+ -+ return ret; -+err: -+ dbg("%s: failed=%d", __func__, ret); -+ return ret; -+} -+ -+static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr) -+{ -+ *snr = 0; -+ return 0; -+} -+ -+static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber) -+{ -+ *ber = 0; -+ return 0; -+} -+ -+static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -+{ -+ *ucblocks = 0; -+ return 0; -+} -+ -+static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength) -+{ -+ *strength = 0; -+ return 0; -+} -+ -+static struct dvb_frontend_ops rtl2830_ops; -+ -+static u32 rtl2830_tuner_i2c_func(struct i2c_adapter *adapter) -+{ -+ return I2C_FUNC_I2C; -+} -+ -+static int rtl2830_tuner_i2c_xfer(struct i2c_adapter *i2c_adap, -+ struct i2c_msg msg[], int num) -+{ -+ struct rtl2830_priv *priv = i2c_get_adapdata(i2c_adap); -+ int ret; -+ -+ /* open i2c-gate */ -+ ret = rtl2830_wr_reg_mask(priv, 0x101, 0x08, 0x08); -+ if (ret) -+ goto err; -+ -+ ret = i2c_transfer(priv->i2c, msg, num); -+ if (ret < 0) -+ warn("tuner i2c failed=%d", ret); -+ -+ return ret; -+err: -+ dbg("%s: failed=%d", __func__, ret); -+ return ret; -+} -+ -+static struct i2c_algorithm rtl2830_tuner_i2c_algo = { -+ .master_xfer = rtl2830_tuner_i2c_xfer, -+ .functionality = rtl2830_tuner_i2c_func, -+}; -+ -+struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(struct dvb_frontend *fe) -+{ -+ struct rtl2830_priv *priv = fe->demodulator_priv; -+ return &priv->tuner_i2c_adapter; -+} -+EXPORT_SYMBOL(rtl2830_get_tuner_i2c_adapter); -+ -+static void rtl2830_release(struct dvb_frontend *fe) -+{ -+ struct rtl2830_priv *priv = fe->demodulator_priv; -+ -+ i2c_del_adapter(&priv->tuner_i2c_adapter); -+ kfree(priv); -+} -+ -+struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg, -+ struct i2c_adapter *i2c) -+{ -+ struct rtl2830_priv *priv = NULL; -+ int ret = 0; -+ u8 tmp; -+ -+ /* allocate memory for the internal state */ -+ priv = kzalloc(sizeof(struct rtl2830_priv), GFP_KERNEL); -+ if (priv == NULL) -+ goto err; -+ -+ /* setup the priv */ -+ priv->i2c = i2c; -+ memcpy(&priv->cfg, cfg, sizeof(struct rtl2830_config)); -+ -+ /* check if the demod is there */ -+ ret = rtl2830_rd_reg(priv, 0x000, &tmp); -+ if (ret) -+ goto err; -+ -+ /* create dvb_frontend */ -+ memcpy(&priv->fe.ops, &rtl2830_ops, sizeof(struct dvb_frontend_ops)); -+ priv->fe.demodulator_priv = priv; -+ -+ /* create tuner i2c adapter */ -+ strlcpy(priv->tuner_i2c_adapter.name, "RTL2830 tuner I2C adapter", -+ sizeof(priv->tuner_i2c_adapter.name)); -+ priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo; -+ priv->tuner_i2c_adapter.algo_data = NULL; -+ i2c_set_adapdata(&priv->tuner_i2c_adapter, priv); -+ if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) { -+ err("tuner I2C bus could not be initialized"); -+ goto err; -+ } -+ -+ priv->sleeping = true; -+ -+ return &priv->fe; -+err: -+ dbg("%s: failed=%d", __func__, ret); -+ kfree(priv); -+ return NULL; -+} -+EXPORT_SYMBOL(rtl2830_attach); -+ -+static struct dvb_frontend_ops rtl2830_ops = { -+ .delsys = { SYS_DVBT }, -+ .info = { -+ .name = "Realtek RTL2830 (DVB-T)", -+ .caps = FE_CAN_FEC_1_2 | -+ FE_CAN_FEC_2_3 | -+ FE_CAN_FEC_3_4 | -+ FE_CAN_FEC_5_6 | -+ FE_CAN_FEC_7_8 | -+ FE_CAN_FEC_AUTO | -+ FE_CAN_QPSK | -+ FE_CAN_QAM_16 | -+ FE_CAN_QAM_64 | -+ FE_CAN_QAM_AUTO | -+ FE_CAN_TRANSMISSION_MODE_AUTO | -+ FE_CAN_GUARD_INTERVAL_AUTO | -+ FE_CAN_HIERARCHY_AUTO | -+ FE_CAN_RECOVER | -+ FE_CAN_MUTE_TS -+ }, -+ -+ .release = rtl2830_release, -+ -+ .init = rtl2830_init, -+ .sleep = rtl2830_sleep, -+ -+ .get_tune_settings = rtl2830_get_tune_settings, -+ -+ .set_frontend = rtl2830_set_frontend, -+ -+ .read_status = rtl2830_read_status, -+ .read_snr = rtl2830_read_snr, -+ .read_ber = rtl2830_read_ber, -+ .read_ucblocks = rtl2830_read_ucblocks, -+ .read_signal_strength = rtl2830_read_signal_strength, -+}; -+ -+MODULE_AUTHOR("Antti Palosaari "); -+MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver"); -+MODULE_LICENSE("GPL"); -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830.h -@@ -0,0 +1,97 @@ -+/* -+ * Realtek RTL2830 DVB-T demodulator driver -+ * -+ * Copyright (C) 2011 Antti Palosaari -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#ifndef RTL2830_H -+#define RTL2830_H -+ -+#include -+ -+struct rtl2830_config { -+ /* -+ * Demodulator I2C address. -+ */ -+ u8 i2c_addr; -+ -+ /* -+ * Xtal frequency. -+ * Hz -+ * 4000000, 16000000, 25000000, 28800000 -+ */ -+ u32 xtal; -+ -+ /* -+ * TS output mode. -+ */ -+ u8 ts_mode; -+ -+ /* -+ * Spectrum inversion. -+ */ -+ bool spec_inv; -+ -+ /* -+ * IFs for all used modes. -+ * Hz -+ * 4570000, 4571429, 36000000, 36125000, 36166667, 44000000 -+ */ -+ u32 if_dvbt; -+ -+ /* -+ */ -+ u8 vtop; -+ -+ /* -+ */ -+ u8 krf; -+ -+ /* -+ */ -+ u8 agc_targ_val; -+}; -+ -+#if defined(CONFIG_DVB_RTL2830) || \ -+ (defined(CONFIG_DVB_RTL2830_MODULE) && defined(MODULE)) -+extern struct dvb_frontend *rtl2830_attach( -+ const struct rtl2830_config *config, -+ struct i2c_adapter *i2c -+); -+ -+extern struct i2c_adapter *rtl2830_get_tuner_i2c_adapter( -+ struct dvb_frontend *fe -+); -+#else -+static inline struct dvb_frontend *rtl2830_attach( -+ const struct rtl2830_config *config, -+ struct i2c_adapter *i2c -+) -+{ -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+ -+static inline struct i2c_adapter *rtl2830_get_tuner_i2c_adapter( -+ struct dvb_frontend *fe -+) -+{ -+ return NULL; -+} -+#endif -+ -+#endif /* RTL2830_H */ -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830_priv.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/rtl2830_priv.h -@@ -0,0 +1,57 @@ -+/* -+ * Realtek RTL2830 DVB-T demodulator driver -+ * -+ * Copyright (C) 2011 Antti Palosaari -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#ifndef RTL2830_PRIV_H -+#define RTL2830_PRIV_H -+ -+#include "dvb_frontend.h" -+#include "rtl2830.h" -+ -+#define LOG_PREFIX "rtl2830" -+ -+#undef dbg -+#define dbg(f, arg...) \ -+ if (rtl2830_debug) \ -+ printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) -+#undef err -+#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) -+#undef info -+#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) -+#undef warn -+#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) -+ -+struct rtl2830_priv { -+ struct i2c_adapter *i2c; -+ struct dvb_frontend fe; -+ struct rtl2830_config cfg; -+ struct i2c_adapter tuner_i2c_adapter; -+ -+ bool sleeping; -+ -+ u8 page; /* active register page */ -+}; -+ -+struct rtl2830_reg_val_mask { -+ u16 reg; -+ u8 val; -+ u8 mask; -+}; -+ -+#endif /* RTL2830_PRIV_H */ -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/rtl28xxu.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/rtl28xxu.c -@@ -0,0 +1,982 @@ -+/* -+ * Realtek RTL28xxU DVB USB driver -+ * -+ * Copyright (C) 2009 Antti Palosaari -+ * Copyright (C) 2011 Antti Palosaari -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#include "rtl28xxu.h" -+ -+#include "rtl2830.h" -+ -+#include "qt1010.h" -+#include "mt2060.h" -+#include "mxl5005s.h" -+ -+/* debug */ -+static int dvb_usb_rtl28xxu_debug; -+module_param_named(debug, dvb_usb_rtl28xxu_debug, int, 0644); -+MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); -+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -+ -+static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) -+{ -+ int ret; -+ unsigned int pipe; -+ u8 requesttype; -+ u8 *buf; -+ -+ buf = kmalloc(req->size, GFP_KERNEL); -+ if (!buf) { -+ ret = -ENOMEM; -+ goto err; -+ } -+ -+ if (req->index & CMD_WR_FLAG) { -+ /* write */ -+ memcpy(buf, req->data, req->size); -+ requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); -+ pipe = usb_sndctrlpipe(d->udev, 0); -+ } else { -+ /* read */ -+ requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); -+ pipe = usb_rcvctrlpipe(d->udev, 0); -+ } -+ -+ ret = usb_control_msg(d->udev, pipe, 0, requesttype, req->value, -+ req->index, buf, req->size, 1000); -+ if (ret > 0) -+ ret = 0; -+ -+ deb_dump(0, requesttype, req->value, req->index, buf, req->size, -+ deb_xfer); -+ -+ /* read request, copy returned data to return buf */ -+ if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) -+ memcpy(req->data, buf, req->size); -+ -+ kfree(buf); -+ -+ if (ret) -+ goto err; -+ -+ return ret; -+err: -+ deb_info("%s: failed=%d\n", __func__, ret); -+ return ret; -+} -+ -+static int rtl2831_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) -+{ -+ struct rtl28xxu_req req; -+ -+ if (reg < 0x3000) -+ req.index = CMD_USB_WR; -+ else if (reg < 0x4000) -+ req.index = CMD_SYS_WR; -+ else -+ req.index = CMD_IR_WR; -+ -+ req.value = reg; -+ req.size = len; -+ req.data = val; -+ -+ return rtl28xxu_ctrl_msg(d, &req); -+} -+ -+static int rtl2831_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) -+{ -+ struct rtl28xxu_req req; -+ -+ if (reg < 0x3000) -+ req.index = CMD_USB_RD; -+ else if (reg < 0x4000) -+ req.index = CMD_SYS_RD; -+ else -+ req.index = CMD_IR_RD; -+ -+ req.value = reg; -+ req.size = len; -+ req.data = val; -+ -+ return rtl28xxu_ctrl_msg(d, &req); -+} -+ -+static int rtl2831_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val) -+{ -+ return rtl2831_wr_regs(d, reg, &val, 1); -+} -+ -+static int rtl2831_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val) -+{ -+ return rtl2831_rd_regs(d, reg, val, 1); -+} -+ -+/* I2C */ -+static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], -+ int num) -+{ -+ int ret; -+ struct dvb_usb_device *d = i2c_get_adapdata(adap); -+ struct rtl28xxu_priv *priv = d->priv; -+ struct rtl28xxu_req req; -+ -+ /* -+ * It is not known which are real I2C bus xfer limits, but testing -+ * with RTL2831U + MT2060 gives max RD 24 and max WR 22 bytes. -+ * TODO: find out RTL2832U lens -+ */ -+ -+ /* -+ * I2C adapter logic looks rather complicated due to fact it handles -+ * three different access methods. Those methods are; -+ * 1) integrated demod access -+ * 2) old I2C access -+ * 3) new I2C access -+ * -+ * Used method is selected in order 1, 2, 3. Method 3 can handle all -+ * requests but there is two reasons why not use it always; -+ * 1) It is most expensive, usually two USB messages are needed -+ * 2) At least RTL2831U does not support it -+ * -+ * Method 3 is needed in case of I2C write+read (typical register read) -+ * where write is more than one byte. -+ */ -+ -+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) -+ return -EAGAIN; -+ -+ if (num == 2 && !(msg[0].flags & I2C_M_RD) && -+ (msg[1].flags & I2C_M_RD)) { -+ if (msg[0].len > 24 || msg[1].len > 24) { -+ /* TODO: check msg[0].len max */ -+ ret = -EOPNOTSUPP; -+ goto err_mutex_unlock; -+ } else if (msg[0].addr == 0x10) { -+ /* method 1 - integrated demod */ -+ req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); -+ req.index = CMD_DEMOD_RD | priv->page; -+ req.size = msg[1].len; -+ req.data = &msg[1].buf[0]; -+ ret = rtl28xxu_ctrl_msg(d, &req); -+ } else if (msg[0].len < 2) { -+ /* method 2 - old I2C */ -+ req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); -+ req.index = CMD_I2C_RD; -+ req.size = msg[1].len; -+ req.data = &msg[1].buf[0]; -+ ret = rtl28xxu_ctrl_msg(d, &req); -+ } else { -+ /* method 3 - new I2C */ -+ req.value = (msg[0].addr << 1); -+ req.index = CMD_I2C_DA_WR; -+ req.size = msg[0].len; -+ req.data = msg[0].buf; -+ ret = rtl28xxu_ctrl_msg(d, &req); -+ if (ret) -+ goto err_mutex_unlock; -+ -+ req.value = (msg[0].addr << 1); -+ req.index = CMD_I2C_DA_RD; -+ req.size = msg[1].len; -+ req.data = msg[1].buf; -+ ret = rtl28xxu_ctrl_msg(d, &req); -+ } -+ } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { -+ if (msg[0].len > 22) { -+ /* TODO: check msg[0].len max */ -+ ret = -EOPNOTSUPP; -+ goto err_mutex_unlock; -+ } else if (msg[0].addr == 0x10) { -+ /* method 1 - integrated demod */ -+ if (msg[0].buf[0] == 0x00) { -+ /* save demod page for later demod access */ -+ priv->page = msg[0].buf[1]; -+ ret = 0; -+ } else { -+ req.value = (msg[0].buf[0] << 8) | -+ (msg[0].addr << 1); -+ req.index = CMD_DEMOD_WR | priv->page; -+ req.size = msg[0].len-1; -+ req.data = &msg[0].buf[1]; -+ ret = rtl28xxu_ctrl_msg(d, &req); -+ } -+ } else if (msg[0].len < 23) { -+ /* method 2 - old I2C */ -+ req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); -+ req.index = CMD_I2C_WR; -+ req.size = msg[0].len-1; -+ req.data = &msg[0].buf[1]; -+ ret = rtl28xxu_ctrl_msg(d, &req); -+ } else { -+ /* method 3 - new I2C */ -+ req.value = (msg[0].addr << 1); -+ req.index = CMD_I2C_DA_WR; -+ req.size = msg[0].len; -+ req.data = msg[0].buf; -+ ret = rtl28xxu_ctrl_msg(d, &req); -+ } -+ } else { -+ ret = -EINVAL; -+ } -+ -+err_mutex_unlock: -+ mutex_unlock(&d->i2c_mutex); -+ -+ return ret ? ret : num; -+} -+ -+static u32 rtl28xxu_i2c_func(struct i2c_adapter *adapter) -+{ -+ return I2C_FUNC_I2C; -+} -+ -+static struct i2c_algorithm rtl28xxu_i2c_algo = { -+ .master_xfer = rtl28xxu_i2c_xfer, -+ .functionality = rtl28xxu_i2c_func, -+}; -+ -+static struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = { -+ .i2c_addr = 0x10, /* 0x20 */ -+ .xtal = 28800000, -+ .ts_mode = 0, -+ .spec_inv = 1, -+ .if_dvbt = 36150000, -+ .vtop = 0x20, -+ .krf = 0x04, -+ .agc_targ_val = 0x2d, -+ -+}; -+ -+static struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = { -+ .i2c_addr = 0x10, /* 0x20 */ -+ .xtal = 28800000, -+ .ts_mode = 0, -+ .spec_inv = 1, -+ .if_dvbt = 36125000, -+ .vtop = 0x20, -+ .krf = 0x04, -+ .agc_targ_val = 0x2d, -+}; -+ -+static struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = { -+ .i2c_addr = 0x10, /* 0x20 */ -+ .xtal = 28800000, -+ .ts_mode = 0, -+ .spec_inv = 0, -+ .if_dvbt = 4570000, -+ .vtop = 0x3f, -+ .krf = 0x04, -+ .agc_targ_val = 0x3e, -+}; -+ -+static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) -+{ -+ int ret; -+ struct rtl28xxu_priv *priv = adap->dev->priv; -+ u8 buf[1]; -+ struct rtl2830_config *rtl2830_config; -+ /* open RTL2831U/RTL2830 I2C gate */ -+ struct rtl28xxu_req req_gate = { 0x0120, 0x0011, 0x0001, "\x08" }; -+ /* for MT2060 tuner probe */ -+ struct rtl28xxu_req req_mt2060 = { 0x00c0, CMD_I2C_RD, 1, buf }; -+ /* for QT1010 tuner probe */ -+ struct rtl28xxu_req req_qt1010 = { 0x0fc4, CMD_I2C_RD, 1, buf }; -+ -+ deb_info("%s:\n", __func__); -+ -+ /* -+ * RTL2831U GPIOs -+ * ========================================================= -+ * GPIO0 | tuner#0 | 0 off | 1 on | MXL5005S (?) -+ * GPIO2 | LED | 0 off | 1 on | -+ * GPIO4 | tuner#1 | 0 on | 1 off | MT2060 -+ */ -+ -+ /* GPIO direction */ -+ ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a); -+ if (ret) -+ goto err; -+ -+ /* enable as output GPIO0, GPIO2, GPIO4 */ -+ ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15); -+ if (ret) -+ goto err; -+ -+ /* -+ * Probe used tuner. We need to know used tuner before demod attach -+ * since there is some demod params needed to set according to tuner. -+ */ -+ -+ /* open demod I2C gate */ -+ ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate); -+ if (ret) -+ goto err; -+ -+ /* check QT1010 ID(?) register; reg=0f val=2c */ -+ ret = rtl28xxu_ctrl_msg(adap->dev, &req_qt1010); -+ if (ret == 0 && buf[0] == 0x2c) { -+ priv->tuner = TUNER_RTL2830_QT1010; -+ rtl2830_config = &rtl28xxu_rtl2830_qt1010_config; -+ deb_info("%s: QT1010\n", __func__); -+ goto found; -+ } else { -+ deb_info("%s: QT1010 probe failed=%d - %02x\n", -+ __func__, ret, buf[0]); -+ } -+ -+ /* open demod I2C gate */ -+ ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate); -+ if (ret) -+ goto err; -+ -+ /* check MT2060 ID register; reg=00 val=63 */ -+ ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2060); -+ if (ret == 0 && buf[0] == 0x63) { -+ priv->tuner = TUNER_RTL2830_MT2060; -+ rtl2830_config = &rtl28xxu_rtl2830_mt2060_config; -+ deb_info("%s: MT2060\n", __func__); -+ goto found; -+ } else { -+ deb_info("%s: MT2060 probe failed=%d - %02x\n", -+ __func__, ret, buf[0]); -+ } -+ -+ /* assume MXL5005S */ -+ ret = 0; -+ priv->tuner = TUNER_RTL2830_MXL5005S; -+ rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config; -+ deb_info("%s: MXL5005S\n", __func__); -+ goto found; -+ -+found: -+ /* attach demodulator */ -+ adap->fe_adap[0].fe = dvb_attach(rtl2830_attach, rtl2830_config, -+ &adap->dev->i2c_adap); -+ if (adap->fe_adap[0].fe == NULL) { -+ ret = -ENODEV; -+ goto err; -+ } -+ -+ return ret; -+err: -+ deb_info("%s: failed=%d\n", __func__, ret); -+ return ret; -+} -+ -+static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) -+{ -+ int ret; -+ struct rtl28xxu_priv *priv = adap->dev->priv; -+ u8 buf[1]; -+ /* open RTL2832U/RTL2832 I2C gate */ -+ struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"}; -+ /* close RTL2832U/RTL2832 I2C gate */ -+ struct rtl28xxu_req req_gate_close = {0x0120, 0x0011, 0x0001, "\x10"}; -+ /* for FC2580 tuner probe */ -+ struct rtl28xxu_req req_fc2580 = {0x01ac, CMD_I2C_RD, 1, buf}; -+ -+ deb_info("%s:\n", __func__); -+ -+ /* GPIO direction */ -+ ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a); -+ if (ret) -+ goto err; -+ -+ /* enable as output GPIO0, GPIO2, GPIO4 */ -+ ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15); -+ if (ret) -+ goto err; -+ -+ ret = rtl2831_wr_reg(adap->dev, SYS_DEMOD_CTL, 0xe8); -+ if (ret) -+ goto err; -+ -+ /* -+ * Probe used tuner. We need to know used tuner before demod attach -+ * since there is some demod params needed to set according to tuner. -+ */ -+ -+ /* open demod I2C gate */ -+ ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_open); -+ if (ret) -+ goto err; -+ -+ /* check FC2580 ID register; reg=01 val=56 */ -+ ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc2580); -+ if (ret == 0 && buf[0] == 0x56) { -+ priv->tuner = TUNER_RTL2832_FC2580; -+ deb_info("%s: FC2580\n", __func__); -+ goto found; -+ } else { -+ deb_info("%s: FC2580 probe failed=%d - %02x\n", -+ __func__, ret, buf[0]); -+ } -+ -+ /* close demod I2C gate */ -+ ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close); -+ if (ret) -+ goto err; -+ -+ /* tuner not found */ -+ ret = -ENODEV; -+ goto err; -+ -+found: -+ /* close demod I2C gate */ -+ ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close); -+ if (ret) -+ goto err; -+ -+ /* attach demodulator */ -+ /* TODO: */ -+ -+ return ret; -+err: -+ deb_info("%s: failed=%d\n", __func__, ret); -+ return ret; -+} -+ -+static struct qt1010_config rtl28xxu_qt1010_config = { -+ .i2c_address = 0x62, /* 0xc4 */ -+}; -+ -+static struct mt2060_config rtl28xxu_mt2060_config = { -+ .i2c_address = 0x60, /* 0xc0 */ -+ .clock_out = 0, -+}; -+ -+static struct mxl5005s_config rtl28xxu_mxl5005s_config = { -+ .i2c_address = 0x63, /* 0xc6 */ -+ .if_freq = IF_FREQ_4570000HZ, -+ .xtal_freq = CRYSTAL_FREQ_16000000HZ, -+ .agc_mode = MXL_SINGLE_AGC, -+ .tracking_filter = MXL_TF_C_H, -+ .rssi_enable = MXL_RSSI_ENABLE, -+ .cap_select = MXL_CAP_SEL_ENABLE, -+ .div_out = MXL_DIV_OUT_4, -+ .clock_out = MXL_CLOCK_OUT_DISABLE, -+ .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, -+ .top = MXL5005S_TOP_25P2, -+ .mod_mode = MXL_DIGITAL_MODE, -+ .if_mode = MXL_ZERO_IF, -+ .AgcMasterByte = 0x00, -+}; -+ -+static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap) -+{ -+ int ret; -+ struct rtl28xxu_priv *priv = adap->dev->priv; -+ struct i2c_adapter *rtl2830_tuner_i2c; -+ struct dvb_frontend *fe; -+ -+ deb_info("%s:\n", __func__); -+ -+ /* use rtl2830 driver I2C adapter, for more info see rtl2830 driver */ -+ rtl2830_tuner_i2c = rtl2830_get_tuner_i2c_adapter(adap->fe_adap[0].fe); -+ -+ switch (priv->tuner) { -+ case TUNER_RTL2830_QT1010: -+ fe = dvb_attach(qt1010_attach, adap->fe_adap[0].fe, -+ rtl2830_tuner_i2c, &rtl28xxu_qt1010_config); -+ break; -+ case TUNER_RTL2830_MT2060: -+ fe = dvb_attach(mt2060_attach, adap->fe_adap[0].fe, -+ rtl2830_tuner_i2c, &rtl28xxu_mt2060_config, -+ 1220); -+ break; -+ case TUNER_RTL2830_MXL5005S: -+ fe = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, -+ rtl2830_tuner_i2c, &rtl28xxu_mxl5005s_config); -+ break; -+ default: -+ fe = NULL; -+ err("unknown tuner=%d", priv->tuner); -+ } -+ -+ if (fe == NULL) { -+ ret = -ENODEV; -+ goto err; -+ } -+ -+ return 0; -+err: -+ deb_info("%s: failed=%d\n", __func__, ret); -+ return ret; -+} -+ -+static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) -+{ -+ int ret; -+ struct rtl28xxu_priv *priv = adap->dev->priv; -+ struct dvb_frontend *fe; -+ -+ deb_info("%s:\n", __func__); -+ -+ switch (priv->tuner) { -+ case TUNER_RTL2832_FC2580: -+ /* TODO: */ -+ fe = NULL; -+ break; -+ default: -+ fe = NULL; -+ err("unknown tuner=%d", priv->tuner); -+ } -+ -+ if (fe == NULL) { -+ ret = -ENODEV; -+ goto err; -+ } -+ -+ return 0; -+err: -+ deb_info("%s: failed=%d\n", __func__, ret); -+ return ret; -+} -+ -+static int rtl28xxu_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff) -+{ -+ int ret; -+ u8 buf[2], gpio; -+ -+ deb_info("%s: onoff=%d\n", __func__, onoff); -+ -+ ret = rtl2831_rd_reg(adap->dev, SYS_GPIO_OUT_VAL, &gpio); -+ if (ret) -+ goto err; -+ -+ if (onoff) { -+ buf[0] = 0x00; -+ buf[1] = 0x00; -+ gpio |= 0x04; /* LED on */ -+ } else { -+ buf[0] = 0x10; /* stall EPA */ -+ buf[1] = 0x02; /* reset EPA */ -+ gpio &= (~0x04); /* LED off */ -+ } -+ -+ ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_VAL, gpio); -+ if (ret) -+ goto err; -+ -+ ret = rtl2831_wr_regs(adap->dev, USB_EPA_CTL, buf, 2); -+ if (ret) -+ goto err; -+ -+ return ret; -+err: -+ deb_info("%s: failed=%d\n", __func__, ret); -+ return ret; -+} -+ -+static int rtl28xxu_power_ctrl(struct dvb_usb_device *d, int onoff) -+{ -+ int ret; -+ u8 gpio, sys0; -+ -+ deb_info("%s: onoff=%d\n", __func__, onoff); -+ -+ /* demod adc */ -+ ret = rtl2831_rd_reg(d, SYS_SYS0, &sys0); -+ if (ret) -+ goto err; -+ -+ /* tuner power, read GPIOs */ -+ ret = rtl2831_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio); -+ if (ret) -+ goto err; -+ -+ deb_info("%s: RD SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio); -+ -+ if (onoff) { -+ gpio |= 0x01; /* GPIO0 = 1 */ -+ gpio &= (~0x10); /* GPIO4 = 0 */ -+ sys0 = sys0 & 0x0f; -+ sys0 |= 0xe0; -+ } else { -+ gpio &= (~0x01); /* GPIO0 = 0 */ -+ gpio |= 0x10; /* GPIO4 = 1 */ -+ sys0 = sys0 & (~0xc0); -+ } -+ -+ deb_info("%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio); -+ -+ /* demod adc */ -+ ret = rtl2831_wr_reg(d, SYS_SYS0, sys0); -+ if (ret) -+ goto err; -+ -+ /* tuner power, write GPIOs */ -+ ret = rtl2831_wr_reg(d, SYS_GPIO_OUT_VAL, gpio); -+ if (ret) -+ goto err; -+ -+ return ret; -+err: -+ deb_info("%s: failed=%d\n", __func__, ret); -+ return ret; -+} -+ -+static int rtl2831u_rc_query(struct dvb_usb_device *d) -+{ -+ int ret, i; -+ struct rtl28xxu_priv *priv = d->priv; -+ u8 buf[5]; -+ u32 rc_code; -+ struct rtl28xxu_reg_val rc_nec_tab[] = { -+ { 0x3033, 0x80 }, -+ { 0x3020, 0x43 }, -+ { 0x3021, 0x16 }, -+ { 0x3022, 0x16 }, -+ { 0x3023, 0x5a }, -+ { 0x3024, 0x2d }, -+ { 0x3025, 0x16 }, -+ { 0x3026, 0x01 }, -+ { 0x3028, 0xb0 }, -+ { 0x3029, 0x04 }, -+ { 0x302c, 0x88 }, -+ { 0x302e, 0x13 }, -+ { 0x3030, 0xdf }, -+ { 0x3031, 0x05 }, -+ }; -+ -+ /* init remote controller */ -+ if (!priv->rc_active) { -+ for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { -+ ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg, -+ rc_nec_tab[i].val); -+ if (ret) -+ goto err; -+ } -+ priv->rc_active = true; -+ } -+ -+ ret = rtl2831_rd_regs(d, SYS_IRRC_RP, buf, 5); -+ if (ret) -+ goto err; -+ -+ if (buf[4] & 0x01) { -+ if (buf[2] == (u8) ~buf[3]) { -+ if (buf[0] == (u8) ~buf[1]) { -+ /* NEC standard (16 bit) */ -+ rc_code = buf[0] << 8 | buf[2]; -+ } else { -+ /* NEC extended (24 bit) */ -+ rc_code = buf[0] << 16 | -+ buf[1] << 8 | buf[2]; -+ } -+ } else { -+ /* NEC full (32 bit) */ -+ rc_code = buf[0] << 24 | buf[1] << 16 | -+ buf[2] << 8 | buf[3]; -+ } -+ -+ rc_keydown(d->rc_dev, rc_code, 0); -+ -+ ret = rtl2831_wr_reg(d, SYS_IRRC_SR, 1); -+ if (ret) -+ goto err; -+ -+ /* repeated intentionally to avoid extra keypress */ -+ ret = rtl2831_wr_reg(d, SYS_IRRC_SR, 1); -+ if (ret) -+ goto err; -+ } -+ -+ return ret; -+err: -+ deb_info("%s: failed=%d\n", __func__, ret); -+ return ret; -+} -+ -+static int rtl2832u_rc_query(struct dvb_usb_device *d) -+{ -+ int ret, i; -+ struct rtl28xxu_priv *priv = d->priv; -+ u8 buf[128]; -+ int len; -+ struct rtl28xxu_reg_val rc_nec_tab[] = { -+ { IR_RX_CTRL, 0x20 }, -+ { IR_RX_BUF_CTRL, 0x80 }, -+ { IR_RX_IF, 0xff }, -+ { IR_RX_IE, 0xff }, -+ { IR_MAX_DURATION0, 0xd0 }, -+ { IR_MAX_DURATION1, 0x07 }, -+ { IR_IDLE_LEN0, 0xc0 }, -+ { IR_IDLE_LEN1, 0x00 }, -+ { IR_GLITCH_LEN, 0x03 }, -+ { IR_RX_CLK, 0x09 }, -+ { IR_RX_CFG, 0x1c }, -+ { IR_MAX_H_TOL_LEN, 0x1e }, -+ { IR_MAX_L_TOL_LEN, 0x1e }, -+ { IR_RX_CTRL, 0x80 }, -+ }; -+ -+ /* init remote controller */ -+ if (!priv->rc_active) { -+ for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { -+ ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg, -+ rc_nec_tab[i].val); -+ if (ret) -+ goto err; -+ } -+ priv->rc_active = true; -+ } -+ -+ ret = rtl2831_rd_reg(d, IR_RX_IF, &buf[0]); -+ if (ret) -+ goto err; -+ -+ if (buf[0] != 0x83) -+ goto exit; -+ -+ ret = rtl2831_rd_reg(d, IR_RX_BC, &buf[0]); -+ if (ret) -+ goto err; -+ -+ len = buf[0]; -+ ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len); -+ -+ /* TODO: pass raw IR to Kernel IR decoder */ -+ -+ ret = rtl2831_wr_reg(d, IR_RX_IF, 0x03); -+ ret = rtl2831_wr_reg(d, IR_RX_BUF_CTRL, 0x80); -+ ret = rtl2831_wr_reg(d, IR_RX_CTRL, 0x80); -+ -+exit: -+ return ret; -+err: -+ deb_info("%s: failed=%d\n", __func__, ret); -+ return ret; -+} -+ -+enum rtl28xxu_usb_table_entry { -+ RTL2831U_0BDA_2831, -+ RTL2831U_14AA_0160, -+ RTL2831U_14AA_0161, -+}; -+ -+static struct usb_device_id rtl28xxu_table[] = { -+ /* RTL2831U */ -+ [RTL2831U_0BDA_2831] = { -+ USB_DEVICE(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U)}, -+ [RTL2831U_14AA_0160] = { -+ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT)}, -+ [RTL2831U_14AA_0161] = { -+ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2)}, -+ -+ /* RTL2832U */ -+ {} /* terminating entry */ -+}; -+ -+MODULE_DEVICE_TABLE(usb, rtl28xxu_table); -+ -+static struct dvb_usb_device_properties rtl28xxu_properties[] = { -+ { -+ .caps = DVB_USB_IS_AN_I2C_ADAPTER, -+ -+ .usb_ctrl = DEVICE_SPECIFIC, -+ .no_reconnect = 1, -+ -+ .size_of_priv = sizeof(struct rtl28xxu_priv), -+ -+ .num_adapters = 1, -+ .adapter = { -+ { -+ .num_frontends = 1, -+ .fe = { -+ { -+ .frontend_attach = rtl2831u_frontend_attach, -+ .tuner_attach = rtl2831u_tuner_attach, -+ .streaming_ctrl = rtl28xxu_streaming_ctrl, -+ .stream = { -+ .type = USB_BULK, -+ .count = 6, -+ .endpoint = 0x81, -+ .u = { -+ .bulk = { -+ .buffersize = 8*512, -+ } -+ } -+ } -+ } -+ } -+ } -+ }, -+ -+ .power_ctrl = rtl28xxu_power_ctrl, -+ -+ .rc.core = { -+ .protocol = RC_TYPE_NEC, -+ .module_name = "rtl28xxu", -+ .rc_query = rtl2831u_rc_query, -+ .rc_interval = 400, -+ .allowed_protos = RC_TYPE_NEC, -+ .rc_codes = RC_MAP_EMPTY, -+ }, -+ -+ .i2c_algo = &rtl28xxu_i2c_algo, -+ -+ .num_device_descs = 2, -+ .devices = { -+ { -+ .name = "Realtek RTL2831U reference design", -+ .warm_ids = { -+ &rtl28xxu_table[RTL2831U_0BDA_2831], -+ }, -+ }, -+ { -+ .name = "Freecom USB2.0 DVB-T", -+ .warm_ids = { -+ &rtl28xxu_table[RTL2831U_14AA_0160], -+ &rtl28xxu_table[RTL2831U_14AA_0161], -+ }, -+ }, -+ } -+ }, -+ { -+ .caps = DVB_USB_IS_AN_I2C_ADAPTER, -+ -+ .usb_ctrl = DEVICE_SPECIFIC, -+ .no_reconnect = 1, -+ -+ .size_of_priv = sizeof(struct rtl28xxu_priv), -+ -+ .num_adapters = 1, -+ .adapter = { -+ { -+ .num_frontends = 1, -+ .fe = { -+ { -+ .frontend_attach = rtl2832u_frontend_attach, -+ .tuner_attach = rtl2832u_tuner_attach, -+ .streaming_ctrl = rtl28xxu_streaming_ctrl, -+ .stream = { -+ .type = USB_BULK, -+ .count = 6, -+ .endpoint = 0x81, -+ .u = { -+ .bulk = { -+ .buffersize = 8*512, -+ } -+ } -+ } -+ } -+ } -+ } -+ }, -+ -+ .power_ctrl = rtl28xxu_power_ctrl, -+ -+ .rc.core = { -+ .protocol = RC_TYPE_NEC, -+ .module_name = "rtl28xxu", -+ .rc_query = rtl2832u_rc_query, -+ .rc_interval = 400, -+ .allowed_protos = RC_TYPE_NEC, -+ .rc_codes = RC_MAP_EMPTY, -+ }, -+ -+ .i2c_algo = &rtl28xxu_i2c_algo, -+ -+ .num_device_descs = 0, /* disabled as no support for RTL2832 */ -+ .devices = { -+ { -+ .name = "Realtek RTL2832U reference design", -+ }, -+ } -+ }, -+ -+}; -+ -+static int rtl28xxu_probe(struct usb_interface *intf, -+ const struct usb_device_id *id) -+{ -+ int ret, i; -+ int properties_count = ARRAY_SIZE(rtl28xxu_properties); -+ struct dvb_usb_device *d; -+ -+ deb_info("%s: interface=%d\n", __func__, -+ intf->cur_altsetting->desc.bInterfaceNumber); -+ -+ if (intf->cur_altsetting->desc.bInterfaceNumber != 0) -+ return 0; -+ -+ for (i = 0; i < properties_count; i++) { -+ ret = dvb_usb_device_init(intf, &rtl28xxu_properties[i], -+ THIS_MODULE, &d, adapter_nr); -+ if (ret == 0 || ret != -ENODEV) -+ break; -+ } -+ -+ if (ret) -+ goto err; -+ -+ /* init USB endpoints */ -+ ret = rtl2831_wr_reg(d, USB_SYSCTL_0, 0x09); -+ if (ret) -+ goto err; -+ -+ ret = rtl2831_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4); -+ if (ret) -+ goto err; -+ -+ ret = rtl2831_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4); -+ if (ret) -+ goto err; -+ -+ return ret; -+err: -+ deb_info("%s: failed=%d\n", __func__, ret); -+ return ret; -+} -+ -+static struct usb_driver rtl28xxu_driver = { -+ .name = "dvb_usb_rtl28xxu", -+ .probe = rtl28xxu_probe, -+ .disconnect = dvb_usb_device_exit, -+ .id_table = rtl28xxu_table, -+}; -+ -+/* module stuff */ -+static int __init rtl28xxu_module_init(void) -+{ -+ int ret; -+ -+ deb_info("%s:\n", __func__); -+ -+ ret = usb_register(&rtl28xxu_driver); -+ if (ret) -+ err("usb_register failed=%d", ret); -+ -+ return ret; -+} -+ -+static void __exit rtl28xxu_module_exit(void) -+{ -+ deb_info("%s:\n", __func__); -+ -+ /* deregister this driver from the USB subsystem */ -+ usb_deregister(&rtl28xxu_driver); -+} -+ -+module_init(rtl28xxu_module_init); -+module_exit(rtl28xxu_module_exit); -+ -+MODULE_DESCRIPTION("Realtek RTL28xxU DVB USB driver"); -+MODULE_AUTHOR("Antti Palosaari "); -+MODULE_LICENSE("GPL"); -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/rtl28xxu.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/rtl28xxu.h -@@ -0,0 +1,264 @@ -+/* -+ * Realtek RTL28xxU DVB USB driver -+ * -+ * Copyright (C) 2009 Antti Palosaari -+ * Copyright (C) 2011 Antti Palosaari -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#ifndef RTL28XXU_H -+#define RTL28XXU_H -+ -+#define DVB_USB_LOG_PREFIX "rtl28xxu" -+#include "dvb-usb.h" -+ -+#define deb_info(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x01, args) -+#define deb_rc(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x02, args) -+#define deb_xfer(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x04, args) -+#define deb_reg(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x08, args) -+#define deb_i2c(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x10, args) -+#define deb_fw(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x20, args) -+ -+#define deb_dump(r, t, v, i, b, l, func) { \ -+ int loop_; \ -+ func("%02x %02x %02x %02x %02x %02x %02x %02x", \ -+ t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \ -+ if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \ -+ func(" >>> "); \ -+ else \ -+ func(" <<< "); \ -+ for (loop_ = 0; loop_ < l; loop_++) \ -+ func("%02x ", b[loop_]); \ -+ func("\n");\ -+} -+ -+/* -+ * USB commands -+ * (usb_control_msg() index parameter) -+ */ -+ -+#define DEMOD 0x0000 -+#define USB 0x0100 -+#define SYS 0x0200 -+#define I2C 0x0300 -+#define I2C_DA 0x0600 -+ -+#define CMD_WR_FLAG 0x0010 -+#define CMD_DEMOD_RD 0x0000 -+#define CMD_DEMOD_WR 0x0010 -+#define CMD_USB_RD 0x0100 -+#define CMD_USB_WR 0x0110 -+#define CMD_SYS_RD 0x0200 -+#define CMD_IR_RD 0x0201 -+#define CMD_IR_WR 0x0211 -+#define CMD_SYS_WR 0x0210 -+#define CMD_I2C_RD 0x0300 -+#define CMD_I2C_WR 0x0310 -+#define CMD_I2C_DA_RD 0x0600 -+#define CMD_I2C_DA_WR 0x0610 -+ -+ -+struct rtl28xxu_priv { -+ u8 chip_id; -+ u8 tuner; -+ u8 page; /* integrated demod active register page */ -+ bool rc_active; -+}; -+ -+enum rtl28xxu_chip_id { -+ CHIP_ID_NONE, -+ CHIP_ID_RTL2831U, -+ CHIP_ID_RTL2832U, -+}; -+ -+enum rtl28xxu_tuner { -+ TUNER_NONE, -+ -+ TUNER_RTL2830_QT1010, -+ TUNER_RTL2830_MT2060, -+ TUNER_RTL2830_MXL5005S, -+ -+ TUNER_RTL2832_MT2266, -+ TUNER_RTL2832_FC2580, -+ TUNER_RTL2832_MT2063, -+ TUNER_RTL2832_MAX3543, -+ TUNER_RTL2832_TUA9001, -+ TUNER_RTL2832_MXL5007T, -+ TUNER_RTL2832_FC0012, -+ TUNER_RTL2832_E4000, -+ TUNER_RTL2832_TDA18272, -+ TUNER_RTL2832_FC0013, -+}; -+ -+struct rtl28xxu_req { -+ u16 value; -+ u16 index; -+ u16 size; -+ u8 *data; -+}; -+ -+struct rtl28xxu_reg_val { -+ u16 reg; -+ u8 val; -+}; -+ -+/* -+ * memory map -+ * -+ * 0x0000 DEMOD : demodulator -+ * 0x2000 USB : SIE, USB endpoint, debug, DMA -+ * 0x3000 SYS : system -+ * 0xfc00 RC : remote controller (not RTL2831U) -+ */ -+ -+/* -+ * USB registers -+ */ -+/* SIE Control Registers */ -+#define USB_SYSCTL 0x2000 /* USB system control */ -+#define USB_SYSCTL_0 0x2000 /* USB system control */ -+#define USB_SYSCTL_1 0x2001 /* USB system control */ -+#define USB_SYSCTL_2 0x2002 /* USB system control */ -+#define USB_SYSCTL_3 0x2003 /* USB system control */ -+#define USB_IRQSTAT 0x2008 /* SIE interrupt status */ -+#define USB_IRQEN 0x200C /* SIE interrupt enable */ -+#define USB_CTRL 0x2010 /* USB control */ -+#define USB_STAT 0x2014 /* USB status */ -+#define USB_DEVADDR 0x2018 /* USB device address */ -+#define USB_TEST 0x201C /* USB test mode */ -+#define USB_FRAME_NUMBER 0x2020 /* frame number */ -+#define USB_FIFO_ADDR 0x2028 /* address of SIE FIFO RAM */ -+#define USB_FIFO_CMD 0x202A /* SIE FIFO RAM access command */ -+#define USB_FIFO_DATA 0x2030 /* SIE FIFO RAM data */ -+/* Endpoint Registers */ -+#define EP0_SETUPA 0x20F8 /* EP 0 setup packet lower byte */ -+#define EP0_SETUPB 0x20FC /* EP 0 setup packet higher byte */ -+#define USB_EP0_CFG 0x2104 /* EP 0 configure */ -+#define USB_EP0_CTL 0x2108 /* EP 0 control */ -+#define USB_EP0_STAT 0x210C /* EP 0 status */ -+#define USB_EP0_IRQSTAT 0x2110 /* EP 0 interrupt status */ -+#define USB_EP0_IRQEN 0x2114 /* EP 0 interrupt enable */ -+#define USB_EP0_MAXPKT 0x2118 /* EP 0 max packet size */ -+#define USB_EP0_BC 0x2120 /* EP 0 FIFO byte counter */ -+#define USB_EPA_CFG 0x2144 /* EP A configure */ -+#define USB_EPA_CFG_0 0x2144 /* EP A configure */ -+#define USB_EPA_CFG_1 0x2145 /* EP A configure */ -+#define USB_EPA_CFG_2 0x2146 /* EP A configure */ -+#define USB_EPA_CFG_3 0x2147 /* EP A configure */ -+#define USB_EPA_CTL 0x2148 /* EP A control */ -+#define USB_EPA_CTL_0 0x2148 /* EP A control */ -+#define USB_EPA_CTL_1 0x2149 /* EP A control */ -+#define USB_EPA_CTL_2 0x214A /* EP A control */ -+#define USB_EPA_CTL_3 0x214B /* EP A control */ -+#define USB_EPA_STAT 0x214C /* EP A status */ -+#define USB_EPA_IRQSTAT 0x2150 /* EP A interrupt status */ -+#define USB_EPA_IRQEN 0x2154 /* EP A interrupt enable */ -+#define USB_EPA_MAXPKT 0x2158 /* EP A max packet size */ -+#define USB_EPA_MAXPKT_0 0x2158 /* EP A max packet size */ -+#define USB_EPA_MAXPKT_1 0x2159 /* EP A max packet size */ -+#define USB_EPA_MAXPKT_2 0x215A /* EP A max packet size */ -+#define USB_EPA_MAXPKT_3 0x215B /* EP A max packet size */ -+#define USB_EPA_FIFO_CFG 0x2160 /* EP A FIFO configure */ -+#define USB_EPA_FIFO_CFG_0 0x2160 /* EP A FIFO configure */ -+#define USB_EPA_FIFO_CFG_1 0x2161 /* EP A FIFO configure */ -+#define USB_EPA_FIFO_CFG_2 0x2162 /* EP A FIFO configure */ -+#define USB_EPA_FIFO_CFG_3 0x2163 /* EP A FIFO configure */ -+/* Debug Registers */ -+#define USB_PHYTSTDIS 0x2F04 /* PHY test disable */ -+#define USB_TOUT_VAL 0x2F08 /* USB time-out time */ -+#define USB_VDRCTRL 0x2F10 /* UTMI vendor signal control */ -+#define USB_VSTAIN 0x2F14 /* UTMI vendor signal status in */ -+#define USB_VLOADM 0x2F18 /* UTMI load vendor signal status in */ -+#define USB_VSTAOUT 0x2F1C /* UTMI vendor signal status out */ -+#define USB_UTMI_TST 0x2F80 /* UTMI test */ -+#define USB_UTMI_STATUS 0x2F84 /* UTMI status */ -+#define USB_TSTCTL 0x2F88 /* test control */ -+#define USB_TSTCTL2 0x2F8C /* test control 2 */ -+#define USB_PID_FORCE 0x2F90 /* force PID */ -+#define USB_PKTERR_CNT 0x2F94 /* packet error counter */ -+#define USB_RXERR_CNT 0x2F98 /* RX error counter */ -+#define USB_MEM_BIST 0x2F9C /* MEM BIST test */ -+#define USB_SLBBIST 0x2FA0 /* self-loop-back BIST */ -+#define USB_CNTTEST 0x2FA4 /* counter test */ -+#define USB_PHYTST 0x2FC0 /* USB PHY test */ -+#define USB_DBGIDX 0x2FF0 /* select individual block debug signal */ -+#define USB_DBGMUX 0x2FF4 /* debug signal module mux */ -+ -+/* -+ * SYS registers -+ */ -+/* demod control registers */ -+#define SYS_SYS0 0x3000 /* include DEMOD_CTL, GPO, GPI, GPOE */ -+#define SYS_DEMOD_CTL 0x3000 /* control register for DVB-T demodulator */ -+/* GPIO registers */ -+#define SYS_GPIO_OUT_VAL 0x3001 /* output value of GPIO */ -+#define SYS_GPIO_IN_VAL 0x3002 /* input value of GPIO */ -+#define SYS_GPIO_OUT_EN 0x3003 /* output enable of GPIO */ -+#define SYS_SYS1 0x3004 /* include GPD, SYSINTE, SYSINTS, GP_CFG0 */ -+#define SYS_GPIO_DIR 0x3004 /* direction control for GPIO */ -+#define SYS_SYSINTE 0x3005 /* system interrupt enable */ -+#define SYS_SYSINTS 0x3006 /* system interrupt status */ -+#define SYS_GPIO_CFG0 0x3007 /* PAD configuration for GPIO0-GPIO3 */ -+#define SYS_SYS2 0x3008 /* include GP_CFG1 and 3 reserved bytes */ -+#define SYS_GPIO_CFG1 0x3008 /* PAD configuration for GPIO4 */ -+#define SYS_DEMOD_CTL1 0x300B -+ -+/* IrDA registers */ -+#define SYS_IRRC_PSR 0x3020 /* IR protocol selection */ -+#define SYS_IRRC_PER 0x3024 /* IR protocol extension */ -+#define SYS_IRRC_SF 0x3028 /* IR sampling frequency */ -+#define SYS_IRRC_DPIR 0x302C /* IR data package interval */ -+#define SYS_IRRC_CR 0x3030 /* IR control */ -+#define SYS_IRRC_RP 0x3034 /* IR read port */ -+#define SYS_IRRC_SR 0x3038 /* IR status */ -+/* I2C master registers */ -+#define SYS_I2CCR 0x3040 /* I2C clock */ -+#define SYS_I2CMCR 0x3044 /* I2C master control */ -+#define SYS_I2CMSTR 0x3048 /* I2C master SCL timing */ -+#define SYS_I2CMSR 0x304C /* I2C master status */ -+#define SYS_I2CMFR 0x3050 /* I2C master FIFO */ -+ -+/* -+ * IR registers -+ */ -+#define IR_RX_BUF 0xFC00 -+#define IR_RX_IE 0xFD00 -+#define IR_RX_IF 0xFD01 -+#define IR_RX_CTRL 0xFD02 -+#define IR_RX_CFG 0xFD03 -+#define IR_MAX_DURATION0 0xFD04 -+#define IR_MAX_DURATION1 0xFD05 -+#define IR_IDLE_LEN0 0xFD06 -+#define IR_IDLE_LEN1 0xFD07 -+#define IR_GLITCH_LEN 0xFD08 -+#define IR_RX_BUF_CTRL 0xFD09 -+#define IR_RX_BUF_DATA 0xFD0A -+#define IR_RX_BC 0xFD0B -+#define IR_RX_CLK 0xFD0C -+#define IR_RX_C_COUNT_L 0xFD0D -+#define IR_RX_C_COUNT_H 0xFD0E -+#define IR_SUSPEND_CTRL 0xFD10 -+#define IR_ERR_TOL_CTRL 0xFD11 -+#define IR_UNIT_LEN 0xFD12 -+#define IR_ERR_TOL_LEN 0xFD13 -+#define IR_MAX_H_TOL_LEN 0xFD14 -+#define IR_MAX_L_TOL_LEN 0xFD15 -+#define IR_MASK_CTRL 0xFD16 -+#define IR_MASK_DATA 0xFD17 -+#define IR_RES_MASK_ADDR 0xFD18 -+#define IR_RES_MASK_T_LEN 0xFD19 -+ -+#endif -Index: linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-core.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-jpeg/jpeg-core.c -+++ linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-core.c -@@ -32,10 +32,9 @@ - - static struct s5p_jpeg_fmt formats_enc[] = { - { -- .name = "YUV 4:2:0 planar, YCbCr", -- .fourcc = V4L2_PIX_FMT_YUV420, -- .depth = 12, -- .colplanes = 3, -+ .name = "JPEG JFIF", -+ .fourcc = V4L2_PIX_FMT_JPEG, -+ .colplanes = 1, - .types = MEM2MEM_CAPTURE, - }, - { -@@ -43,7 +42,7 @@ static struct s5p_jpeg_fmt formats_enc[] - .fourcc = V4L2_PIX_FMT_YUYV, - .depth = 16, - .colplanes = 1, -- .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, -+ .types = MEM2MEM_OUTPUT, - }, - { - .name = "RGB565", -@@ -203,6 +202,16 @@ static const unsigned char hactblg0[162] - 0xf9, 0xfa - }; - -+static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c) -+{ -+ return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler); -+} -+ -+static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh) -+{ -+ return container_of(fh, struct s5p_jpeg_ctx, fh); -+} -+ - static inline void jpeg_set_qtbl(void __iomem *regs, const unsigned char *qtbl, - unsigned long tab, int len) - { -@@ -269,6 +278,7 @@ static int queue_init(void *priv, struct - struct vb2_queue *dst_vq); - static struct s5p_jpeg_fmt *s5p_jpeg_find_format(unsigned int mode, - __u32 pixelformat); -+static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx); - - static int s5p_jpeg_open(struct file *file) - { -@@ -276,12 +286,18 @@ static int s5p_jpeg_open(struct file *fi - struct video_device *vfd = video_devdata(file); - struct s5p_jpeg_ctx *ctx; - struct s5p_jpeg_fmt *out_fmt; -+ int ret = 0; - - ctx = kzalloc(sizeof *ctx, GFP_KERNEL); - if (!ctx) - return -ENOMEM; - -- file->private_data = ctx; -+ v4l2_fh_init(&ctx->fh, vfd); -+ /* Use separate control handler per file handle */ -+ ctx->fh.ctrl_handler = &ctx->ctrl_handler; -+ file->private_data = &ctx->fh; -+ v4l2_fh_add(&ctx->fh); -+ - ctx->jpeg = jpeg; - if (vfd == jpeg->vfd_encoder) { - ctx->mode = S5P_JPEG_ENCODE; -@@ -291,24 +307,35 @@ static int s5p_jpeg_open(struct file *fi - out_fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_JPEG); - } - -+ ret = s5p_jpeg_controls_create(ctx); -+ if (ret < 0) -+ goto error; -+ - ctx->m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init); - if (IS_ERR(ctx->m2m_ctx)) { -- int err = PTR_ERR(ctx->m2m_ctx); -- kfree(ctx); -- return err; -+ ret = PTR_ERR(ctx->m2m_ctx); -+ goto error; - } - - ctx->out_q.fmt = out_fmt; - ctx->cap_q.fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_YUYV); -- - return 0; -+ -+error: -+ v4l2_fh_del(&ctx->fh); -+ v4l2_fh_exit(&ctx->fh); -+ kfree(ctx); -+ return ret; - } - - static int s5p_jpeg_release(struct file *file) - { -- struct s5p_jpeg_ctx *ctx = file->private_data; -+ struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); - - v4l2_m2m_ctx_release(ctx->m2m_ctx); -+ v4l2_ctrl_handler_free(&ctx->ctrl_handler); -+ v4l2_fh_del(&ctx->fh); -+ v4l2_fh_exit(&ctx->fh); - kfree(ctx); - - return 0; -@@ -317,14 +344,14 @@ static int s5p_jpeg_release(struct file - static unsigned int s5p_jpeg_poll(struct file *file, - struct poll_table_struct *wait) - { -- struct s5p_jpeg_ctx *ctx = file->private_data; -+ struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); - - return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); - } - - static int s5p_jpeg_mmap(struct file *file, struct vm_area_struct *vma) - { -- struct s5p_jpeg_ctx *ctx = file->private_data; -+ struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); - - return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); - } -@@ -448,7 +475,7 @@ static bool s5p_jpeg_parse_hdr(struct s5 - static int s5p_jpeg_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) - { -- struct s5p_jpeg_ctx *ctx = priv; -+ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - - if (ctx->mode == S5P_JPEG_ENCODE) { - strlcpy(cap->driver, S5P_JPEG_M2M_NAME " encoder", -@@ -497,9 +524,7 @@ static int enum_fmt(struct s5p_jpeg_fmt - static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) - { -- struct s5p_jpeg_ctx *ctx; -- -- ctx = priv; -+ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - - if (ctx->mode == S5P_JPEG_ENCODE) - return enum_fmt(formats_enc, NUM_FORMATS_ENC, f, -@@ -511,9 +536,7 @@ static int s5p_jpeg_enum_fmt_vid_cap(str - static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv, - struct v4l2_fmtdesc *f) - { -- struct s5p_jpeg_ctx *ctx; -- -- ctx = priv; -+ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - - if (ctx->mode == S5P_JPEG_ENCODE) - return enum_fmt(formats_enc, NUM_FORMATS_ENC, f, -@@ -538,7 +561,7 @@ static int s5p_jpeg_g_fmt(struct file *f - struct vb2_queue *vq; - struct s5p_jpeg_q_data *q_data = NULL; - struct v4l2_pix_format *pix = &f->fmt.pix; -- struct s5p_jpeg_ctx *ct = priv; -+ struct s5p_jpeg_ctx *ct = fh_to_ctx(priv); - - vq = v4l2_m2m_get_vq(ct->m2m_ctx, f->type); - if (!vq) -@@ -659,8 +682,8 @@ static int vidioc_try_fmt(struct v4l2_fo - static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) - { -+ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - struct s5p_jpeg_fmt *fmt; -- struct s5p_jpeg_ctx *ctx = priv; - - fmt = s5p_jpeg_find_format(ctx->mode, f->fmt.pix.pixelformat); - if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) { -@@ -676,8 +699,8 @@ static int s5p_jpeg_try_fmt_vid_cap(stru - static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv, - struct v4l2_format *f) - { -+ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - struct s5p_jpeg_fmt *fmt; -- struct s5p_jpeg_ctx *ctx = priv; - - fmt = s5p_jpeg_find_format(ctx->mode, f->fmt.pix.pixelformat); - if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) { -@@ -728,7 +751,7 @@ static int s5p_jpeg_s_fmt_vid_cap(struct - if (ret) - return ret; - -- return s5p_jpeg_s_fmt(priv, f); -+ return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); - } - - static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv, -@@ -740,13 +763,13 @@ static int s5p_jpeg_s_fmt_vid_out(struct - if (ret) - return ret; - -- return s5p_jpeg_s_fmt(priv, f); -+ return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); - } - - static int s5p_jpeg_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *reqbufs) - { -- struct s5p_jpeg_ctx *ctx = priv; -+ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - - return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); - } -@@ -754,14 +777,14 @@ static int s5p_jpeg_reqbufs(struct file - static int s5p_jpeg_querybuf(struct file *file, void *priv, - struct v4l2_buffer *buf) - { -- struct s5p_jpeg_ctx *ctx = priv; -+ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - - return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); - } - - static int s5p_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) - { -- struct s5p_jpeg_ctx *ctx = priv; -+ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - - return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); - } -@@ -769,7 +792,7 @@ static int s5p_jpeg_qbuf(struct file *fi - static int s5p_jpeg_dqbuf(struct file *file, void *priv, - struct v4l2_buffer *buf) - { -- struct s5p_jpeg_ctx *ctx = priv; -+ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - - return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); - } -@@ -777,7 +800,7 @@ static int s5p_jpeg_dqbuf(struct file *f - static int s5p_jpeg_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) - { -- struct s5p_jpeg_ctx *ctx = priv; -+ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - - return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); - } -@@ -785,7 +808,7 @@ static int s5p_jpeg_streamon(struct file - static int s5p_jpeg_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) - { -- struct s5p_jpeg_ctx *ctx = priv; -+ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - - return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); - } -@@ -793,7 +816,7 @@ static int s5p_jpeg_streamoff(struct fil - int s5p_jpeg_g_selection(struct file *file, void *priv, - struct v4l2_selection *s) - { -- struct s5p_jpeg_ctx *ctx = priv; -+ struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); - - if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && - s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -@@ -822,33 +845,89 @@ int s5p_jpeg_g_selection(struct file *fi - return 0; - } - --static int s5p_jpeg_g_jpegcomp(struct file *file, void *priv, -- struct v4l2_jpegcompression *compr) -+/* -+ * V4L2 controls -+ */ -+ -+static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl) - { -- struct s5p_jpeg_ctx *ctx = priv; -+ struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl); -+ struct s5p_jpeg *jpeg = ctx->jpeg; -+ unsigned long flags; - -- if (ctx->mode == S5P_JPEG_DECODE) -- return -ENOTTY; -+ switch (ctrl->id) { -+ case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: -+ spin_lock_irqsave(&jpeg->slock, flags); -+ -+ WARN_ON(ctx->subsampling > S5P_SUBSAMPLING_MODE_GRAY); -+ if (ctx->subsampling > 2) -+ ctrl->val = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; -+ else -+ ctrl->val = ctx->subsampling; -+ spin_unlock_irqrestore(&jpeg->slock, flags); -+ break; -+ } - -- memset(compr, 0, sizeof(*compr)); -- compr->quality = ctx->compr_quality; -+ return 0; -+} -+ -+static int s5p_jpeg_s_ctrl(struct v4l2_ctrl *ctrl) -+{ -+ struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&ctx->jpeg->slock, flags); -+ -+ switch (ctrl->id) { -+ case V4L2_CID_JPEG_COMPRESSION_QUALITY: -+ ctx->compr_quality = S5P_JPEG_COMPR_QUAL_WORST - ctrl->val; -+ break; -+ case V4L2_CID_JPEG_RESTART_INTERVAL: -+ ctx->restart_interval = ctrl->val; -+ break; -+ case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: -+ ctx->subsampling = ctrl->val; -+ break; -+ } - -+ spin_unlock_irqrestore(&ctx->jpeg->slock, flags); - return 0; - } - --static int s5p_jpeg_s_jpegcomp(struct file *file, void *priv, -- struct v4l2_jpegcompression *compr) -+static const struct v4l2_ctrl_ops s5p_jpeg_ctrl_ops = { -+ .g_volatile_ctrl = s5p_jpeg_g_volatile_ctrl, -+ .s_ctrl = s5p_jpeg_s_ctrl, -+}; -+ -+static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx) - { -- struct s5p_jpeg_ctx *ctx = priv; -+ unsigned int mask = ~0x27; /* 444, 422, 420, GRAY */ -+ struct v4l2_ctrl *ctrl; - -- if (ctx->mode == S5P_JPEG_DECODE) -- return -ENOTTY; -+ v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3); - -- compr->quality = clamp(compr->quality, S5P_JPEG_COMPR_QUAL_BEST, -- S5P_JPEG_COMPR_QUAL_WORST); -+ if (ctx->mode == S5P_JPEG_ENCODE) { -+ v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops, -+ V4L2_CID_JPEG_COMPRESSION_QUALITY, -+ 0, 3, 1, 3); -+ -+ v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops, -+ V4L2_CID_JPEG_RESTART_INTERVAL, -+ 0, 3, 0xffff, 0); -+ mask = ~0x06; /* 422, 420 */ -+ } -+ -+ ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops, -+ V4L2_CID_JPEG_CHROMA_SUBSAMPLING, -+ V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY, mask, -+ V4L2_JPEG_CHROMA_SUBSAMPLING_422); - -- ctx->compr_quality = S5P_JPEG_COMPR_QUAL_WORST - compr->quality; -+ if (ctx->ctrl_handler.error) -+ return ctx->ctrl_handler.error; - -+ if (ctx->mode == S5P_JPEG_DECODE) -+ ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE | -+ V4L2_CTRL_FLAG_READ_ONLY; - return 0; - } - -@@ -877,9 +956,6 @@ static const struct v4l2_ioctl_ops s5p_j - .vidioc_streamoff = s5p_jpeg_streamoff, - - .vidioc_g_selection = s5p_jpeg_g_selection, -- -- .vidioc_g_jpegcomp = s5p_jpeg_g_jpegcomp, -- .vidioc_s_jpegcomp = s5p_jpeg_s_jpegcomp, - }; - - /* -@@ -908,13 +984,8 @@ static void s5p_jpeg_device_run(void *pr - jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_565); - else - jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_422); -- if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV) -- jpeg_subsampling_mode(jpeg->regs, -- S5P_JPEG_SUBSAMPLING_422); -- else -- jpeg_subsampling_mode(jpeg->regs, -- S5P_JPEG_SUBSAMPLING_420); -- jpeg_dri(jpeg->regs, 0); -+ jpeg_subsampling_mode(jpeg->regs, ctx->subsampling); -+ jpeg_dri(jpeg->regs, ctx->restart_interval); - jpeg_x(jpeg->regs, ctx->out_q.w); - jpeg_y(jpeg->regs, ctx->out_q.h); - jpeg_imgadr(jpeg->regs, src_addr); -@@ -953,14 +1024,18 @@ static void s5p_jpeg_device_run(void *pr - jpeg_htbl_dc(jpeg->regs, 2); - jpeg_htbl_ac(jpeg->regs, 3); - jpeg_htbl_dc(jpeg->regs, 3); -- } else { -+ } else { /* S5P_JPEG_DECODE */ - jpeg_rst_int_enable(jpeg->regs, true); - jpeg_data_num_int_enable(jpeg->regs, true); - jpeg_final_mcu_num_int_enable(jpeg->regs, true); -- jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422); -+ if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV) -+ jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422); -+ else -+ jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_420); - jpeg_jpgadr(jpeg->regs, src_addr); - jpeg_imgadr(jpeg->regs, dst_addr); - } -+ - jpeg_start(jpeg->regs); - } - -@@ -1162,6 +1237,8 @@ static irqreturn_t s5p_jpeg_irq(int irq, - bool timer_elapsed = false; - bool op_completed = false; - -+ spin_lock(&jpeg->slock); -+ - curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); - - src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); -@@ -1192,6 +1269,9 @@ static irqreturn_t s5p_jpeg_irq(int irq, - v4l2_m2m_buf_done(dst_buf, state); - v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->m2m_ctx); - -+ curr_ctx->subsampling = jpeg_get_subsampling_mode(jpeg->regs); -+ spin_unlock(&jpeg->slock); -+ - jpeg_clear_int(jpeg->regs); - - return IRQ_HANDLED; -@@ -1215,6 +1295,7 @@ static int s5p_jpeg_probe(struct platfor - return -ENOMEM; - - mutex_init(&jpeg->lock); -+ spin_lock_init(&jpeg->slock); - jpeg->dev = &pdev->dev; - - /* memory-mapped registers */ -Index: linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-core.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-jpeg/jpeg-core.h -+++ linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-core.h -@@ -14,6 +14,8 @@ - #define JPEG_CORE_H_ - - #include -+#include -+#include - - #define S5P_JPEG_M2M_NAME "s5p-jpeg" - -@@ -47,6 +49,7 @@ - /** - * struct s5p_jpeg - JPEG IP abstraction - * @lock: the mutex protecting this structure -+ * @slock: spinlock protecting the device contexts - * @v4l2_dev: v4l2 device for mem2mem mode - * @vfd_encoder: video device node for encoder mem2mem mode - * @vfd_decoder: video device node for decoder mem2mem mode -@@ -60,6 +63,7 @@ - */ - struct s5p_jpeg { - struct mutex lock; -+ struct spinlock slock; - - struct v4l2_device v4l2_dev; - struct video_device *vfd_encoder; -@@ -117,15 +121,20 @@ struct s5p_jpeg_q_data { - * @out_q: source (output) queue information - * @cap_fmt: destination (capture) queue queue information - * @hdr_parsed: set if header has been parsed during decompression -+ * @ctrl_handler: controls handler - */ - struct s5p_jpeg_ctx { - struct s5p_jpeg *jpeg; - unsigned int mode; -- unsigned int compr_quality; -+ unsigned short compr_quality; -+ unsigned short restart_interval; -+ unsigned short subsampling; - struct v4l2_m2m_ctx *m2m_ctx; - struct s5p_jpeg_q_data out_q; - struct s5p_jpeg_q_data cap_q; -+ struct v4l2_fh fh; - bool hdr_parsed; -+ struct v4l2_ctrl_handler ctrl_handler; - }; - - /** -Index: linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-hw.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-jpeg/jpeg-hw.h -+++ linux-3.3.x86_64/drivers/media/video/s5p-jpeg/jpeg-hw.h -@@ -13,6 +13,7 @@ - #define JPEG_HW_H_ - - #include -+#include - - #include "jpeg-hw.h" - #include "jpeg-regs.h" -@@ -25,8 +26,6 @@ - #define S5P_JPEG_DECODE 1 - #define S5P_JPEG_RAW_IN_565 0 - #define S5P_JPEG_RAW_IN_422 1 --#define S5P_JPEG_SUBSAMPLING_422 0 --#define S5P_JPEG_SUBSAMPLING_420 1 - #define S5P_JPEG_RAW_OUT_422 0 - #define S5P_JPEG_RAW_OUT_420 1 - -@@ -91,21 +90,26 @@ static inline void jpeg_proc_mode(void _ - writel(reg, regs + S5P_JPGMOD); - } - --static inline void jpeg_subsampling_mode(void __iomem *regs, unsigned long mode) -+static inline void jpeg_subsampling_mode(void __iomem *regs, unsigned int mode) - { - unsigned long reg, m; - -- m = S5P_SUBSAMPLING_MODE_422; -- if (mode == S5P_JPEG_SUBSAMPLING_422) -- m = S5P_SUBSAMPLING_MODE_422; -- else if (mode == S5P_JPEG_SUBSAMPLING_420) -+ if (mode == V4L2_JPEG_CHROMA_SUBSAMPLING_420) - m = S5P_SUBSAMPLING_MODE_420; -+ else -+ m = S5P_SUBSAMPLING_MODE_422; -+ - reg = readl(regs + S5P_JPGMOD); - reg &= ~S5P_SUBSAMPLING_MODE_MASK; - reg |= m; - writel(reg, regs + S5P_JPGMOD); - } - -+static inline unsigned int jpeg_get_subsampling_mode(void __iomem *regs) -+{ -+ return readl(regs + S5P_JPGMOD) & S5P_SUBSAMPLING_MODE_MASK; -+} -+ - static inline void jpeg_dri(void __iomem *regs, unsigned int dri) - { - unsigned long reg; -Index: linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-core.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-fimc/fimc-core.c -+++ linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-core.c -@@ -1602,24 +1602,35 @@ static void fimc_clk_put(struct fimc_dev - { - int i; - for (i = 0; i < fimc->num_clocks; i++) { -- if (fimc->clock[i]) -- clk_put(fimc->clock[i]); -+ if (IS_ERR_OR_NULL(fimc->clock[i])) -+ continue; -+ clk_unprepare(fimc->clock[i]); -+ clk_put(fimc->clock[i]); -+ fimc->clock[i] = NULL; - } - } - - static int fimc_clk_get(struct fimc_dev *fimc) - { -- int i; -+ int i, ret; -+ - for (i = 0; i < fimc->num_clocks; i++) { - fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]); -- if (!IS_ERR_OR_NULL(fimc->clock[i])) -- continue; -- dev_err(&fimc->pdev->dev, "failed to get fimc clock: %s\n", -- fimc_clocks[i]); -- return -ENXIO; -+ if (IS_ERR(fimc->clock[i])) -+ goto err; -+ ret = clk_prepare(fimc->clock[i]); -+ if (ret < 0) { -+ clk_put(fimc->clock[i]); -+ fimc->clock[i] = NULL; -+ goto err; -+ } - } -- - return 0; -+err: -+ fimc_clk_put(fimc); -+ dev_err(&fimc->pdev->dev, "failed to get clock: %s\n", -+ fimc_clocks[i]); -+ return -ENXIO; - } - - static int fimc_m2m_suspend(struct fimc_dev *fimc) -@@ -1667,8 +1678,6 @@ static int fimc_probe(struct platform_de - struct s5p_platform_fimc *pdata; - int ret = 0; - -- dev_dbg(&pdev->dev, "%s():\n", __func__); -- - drv_data = (struct samsung_fimc_driverdata *) - platform_get_device_id(pdev)->driver_data; - -@@ -1678,7 +1687,7 @@ static int fimc_probe(struct platform_de - return -EINVAL; - } - -- fimc = kzalloc(sizeof(struct fimc_dev), GFP_KERNEL); -+ fimc = devm_kzalloc(&pdev->dev, sizeof(*fimc), GFP_KERNEL); - if (!fimc) - return -ENOMEM; - -@@ -1689,51 +1698,35 @@ static int fimc_probe(struct platform_de - pdata = pdev->dev.platform_data; - fimc->pdata = pdata; - -- - init_waitqueue_head(&fimc->irq_queue); - spin_lock_init(&fimc->slock); - mutex_init(&fimc->lock); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (!res) { -- dev_err(&pdev->dev, "failed to find the registers\n"); -- ret = -ENOENT; -- goto err_info; -- } -- -- fimc->regs_res = request_mem_region(res->start, resource_size(res), -- dev_name(&pdev->dev)); -- if (!fimc->regs_res) { -- dev_err(&pdev->dev, "failed to obtain register region\n"); -- ret = -ENOENT; -- goto err_info; -- } -- -- fimc->regs = ioremap(res->start, resource_size(res)); -- if (!fimc->regs) { -- dev_err(&pdev->dev, "failed to map registers\n"); -- ret = -ENXIO; -- goto err_req_region; -+ fimc->regs = devm_request_and_ioremap(&pdev->dev, res); -+ if (fimc->regs == NULL) { -+ dev_err(&pdev->dev, "Failed to obtain io memory\n"); -+ return -ENOENT; - } - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -- if (!res) { -- dev_err(&pdev->dev, "failed to get IRQ resource\n"); -- ret = -ENXIO; -- goto err_regs_unmap; -+ if (res == NULL) { -+ dev_err(&pdev->dev, "Failed to get IRQ resource\n"); -+ return -ENXIO; - } - fimc->irq = res->start; - - fimc->num_clocks = MAX_FIMC_CLOCKS; - ret = fimc_clk_get(fimc); - if (ret) -- goto err_regs_unmap; -+ return ret; - clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency); - clk_enable(fimc->clock[CLK_BUS]); - - platform_set_drvdata(pdev, fimc); - -- ret = request_irq(fimc->irq, fimc_irq_handler, 0, pdev->name, fimc); -+ ret = devm_request_irq(&pdev->dev, fimc->irq, fimc_irq_handler, -+ 0, pdev->name, fimc); - if (ret) { - dev_err(&pdev->dev, "failed to install irq (%d)\n", ret); - goto err_clk; -@@ -1742,7 +1735,7 @@ static int fimc_probe(struct platform_de - pm_runtime_enable(&pdev->dev); - ret = pm_runtime_get_sync(&pdev->dev); - if (ret < 0) -- goto err_irq; -+ goto err_clk; - /* Initialize contiguous memory allocator */ - fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); - if (IS_ERR(fimc->alloc_ctx)) { -@@ -1757,17 +1750,8 @@ static int fimc_probe(struct platform_de - - err_pm: - pm_runtime_put(&pdev->dev); --err_irq: -- free_irq(fimc->irq, fimc); - err_clk: - fimc_clk_put(fimc); --err_regs_unmap: -- iounmap(fimc->regs); --err_req_region: -- release_resource(fimc->regs_res); -- kfree(fimc->regs_res); --err_info: -- kfree(fimc); - return ret; - } - -@@ -1854,11 +1838,6 @@ static int __devexit fimc_remove(struct - - clk_disable(fimc->clock[CLK_BUS]); - fimc_clk_put(fimc); -- free_irq(fimc->irq, fimc); -- iounmap(fimc->regs); -- release_resource(fimc->regs_res); -- kfree(fimc->regs_res); -- kfree(fimc); - - dev_info(&pdev->dev, "driver unloaded\n"); - return 0; -Index: linux-3.3.x86_64/drivers/media/video/s5p-fimc/mipi-csis.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-fimc/mipi-csis.c -+++ linux-3.3.x86_64/drivers/media/video/s5p-fimc/mipi-csis.c -@@ -1,8 +1,8 @@ - /* - * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver - * -- * Copyright (C) 2011 Samsung Electronics Co., Ltd. -- * Contact: Sylwester Nawrocki, -+ * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. -+ * Sylwester Nawrocki, - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as -@@ -100,7 +100,6 @@ enum { - * @pads: CSIS pads array - * @sd: v4l2_subdev associated with CSIS device instance - * @pdev: CSIS platform device -- * @regs_res: requested I/O register memory resource - * @regs: mmaped I/O registers memory - * @clock: CSIS clocks - * @irq: requested s5p-mipi-csis irq number -@@ -113,7 +112,6 @@ struct csis_state { - struct media_pad pads[CSIS_PADS_NUM]; - struct v4l2_subdev sd; - struct platform_device *pdev; -- struct resource *regs_res; - void __iomem *regs; - struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES]; - struct clk *clock[NUM_CSIS_CLOCKS]; -@@ -258,26 +256,36 @@ static void s5pcsis_clk_put(struct csis_ - { - int i; - -- for (i = 0; i < NUM_CSIS_CLOCKS; i++) -- if (!IS_ERR_OR_NULL(state->clock[i])) -- clk_put(state->clock[i]); -+ for (i = 0; i < NUM_CSIS_CLOCKS; i++) { -+ if (IS_ERR_OR_NULL(state->clock[i])) -+ continue; -+ clk_unprepare(state->clock[i]); -+ clk_put(state->clock[i]); -+ state->clock[i] = NULL; -+ } - } - - static int s5pcsis_clk_get(struct csis_state *state) - { - struct device *dev = &state->pdev->dev; -- int i; -+ int i, ret; - - for (i = 0; i < NUM_CSIS_CLOCKS; i++) { - state->clock[i] = clk_get(dev, csi_clock_name[i]); -- if (IS_ERR(state->clock[i])) { -- s5pcsis_clk_put(state); -- dev_err(dev, "failed to get clock: %s\n", -- csi_clock_name[i]); -- return -ENXIO; -+ if (IS_ERR(state->clock[i])) -+ goto err; -+ ret = clk_prepare(state->clock[i]); -+ if (ret < 0) { -+ clk_put(state->clock[i]); -+ state->clock[i] = NULL; -+ goto err; - } - } - return 0; -+err: -+ s5pcsis_clk_put(state); -+ dev_err(dev, "failed to get clock: %s\n", csi_clock_name[i]); -+ return -ENXIO; - } - - static int s5pcsis_s_power(struct v4l2_subdev *sd, int on) -@@ -480,12 +488,11 @@ static int __devinit s5pcsis_probe(struc - { - struct s5p_platform_mipi_csis *pdata; - struct resource *mem_res; -- struct resource *regs_res; - struct csis_state *state; - int ret = -ENOMEM; - int i; - -- state = kzalloc(sizeof(*state), GFP_KERNEL); -+ state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL); - if (!state) - return -ENOMEM; - -@@ -495,52 +502,27 @@ static int __devinit s5pcsis_probe(struc - pdata = pdev->dev.platform_data; - if (pdata == NULL || pdata->phy_enable == NULL) { - dev_err(&pdev->dev, "Platform data not fully specified\n"); -- goto e_free; -+ return -EINVAL; - } - - if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) || - pdata->lanes > CSIS0_MAX_LANES) { -- ret = -EINVAL; - dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n", - pdata->lanes); -- goto e_free; -+ return -EINVAL; - } - - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (!mem_res) { -- dev_err(&pdev->dev, "Failed to get IO memory region\n"); -- goto e_free; -- } -- -- regs_res = request_mem_region(mem_res->start, resource_size(mem_res), -- pdev->name); -- if (!regs_res) { -- dev_err(&pdev->dev, "Failed to request IO memory region\n"); -- goto e_free; -- } -- state->regs_res = regs_res; -- -- state->regs = ioremap(mem_res->start, resource_size(mem_res)); -- if (!state->regs) { -- dev_err(&pdev->dev, "Failed to remap IO region\n"); -- goto e_reqmem; -+ state->regs = devm_request_and_ioremap(&pdev->dev, mem_res); -+ if (state->regs == NULL) { -+ dev_err(&pdev->dev, "Failed to request and remap io memory\n"); -+ return -ENXIO; - } - -- ret = s5pcsis_clk_get(state); -- if (ret) -- goto e_unmap; -- -- clk_enable(state->clock[CSIS_CLK_MUX]); -- if (pdata->clk_rate) -- clk_set_rate(state->clock[CSIS_CLK_MUX], pdata->clk_rate); -- else -- dev_WARN(&pdev->dev, "No clock frequency specified!\n"); -- - state->irq = platform_get_irq(pdev, 0); - if (state->irq < 0) { -- ret = state->irq; - dev_err(&pdev->dev, "Failed to get irq\n"); -- goto e_clkput; -+ return state->irq; - } - - for (i = 0; i < CSIS_NUM_SUPPLIES; i++) -@@ -549,12 +531,22 @@ static int __devinit s5pcsis_probe(struc - ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES, - state->supplies); - if (ret) -+ return ret; -+ -+ ret = s5pcsis_clk_get(state); -+ if (ret) - goto e_clkput; - -- ret = request_irq(state->irq, s5pcsis_irq_handler, 0, -- dev_name(&pdev->dev), state); -+ clk_enable(state->clock[CSIS_CLK_MUX]); -+ if (pdata->clk_rate) -+ clk_set_rate(state->clock[CSIS_CLK_MUX], pdata->clk_rate); -+ else -+ dev_WARN(&pdev->dev, "No clock frequency specified!\n"); -+ -+ ret = devm_request_irq(&pdev->dev, state->irq, s5pcsis_irq_handler, -+ 0, dev_name(&pdev->dev), state); - if (ret) { -- dev_err(&pdev->dev, "request_irq failed\n"); -+ dev_err(&pdev->dev, "Interrupt request failed\n"); - goto e_regput; - } - -@@ -573,7 +565,7 @@ static int __devinit s5pcsis_probe(struc - ret = media_entity_init(&state->sd.entity, - CSIS_PADS_NUM, state->pads, 0); - if (ret < 0) -- goto e_irqfree; -+ goto e_clkput; - - /* This allows to retrieve the platform device id by the host driver */ - v4l2_set_subdevdata(&state->sd, pdev); -@@ -582,22 +574,13 @@ static int __devinit s5pcsis_probe(struc - platform_set_drvdata(pdev, &state->sd); - - pm_runtime_enable(&pdev->dev); -- - return 0; - --e_irqfree: -- free_irq(state->irq, state); - e_regput: - regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); - e_clkput: - clk_disable(state->clock[CSIS_CLK_MUX]); - s5pcsis_clk_put(state); --e_unmap: -- iounmap(state->regs); --e_reqmem: -- release_mem_region(regs_res->start, resource_size(regs_res)); --e_free: -- kfree(state); - return ret; - } - -@@ -699,21 +682,15 @@ static int __devexit s5pcsis_remove(stru - { - struct v4l2_subdev *sd = platform_get_drvdata(pdev); - struct csis_state *state = sd_to_csis_state(sd); -- struct resource *res = state->regs_res; - - pm_runtime_disable(&pdev->dev); -- s5pcsis_suspend(&pdev->dev); -+ s5pcsis_pm_suspend(&pdev->dev, false); - clk_disable(state->clock[CSIS_CLK_MUX]); - pm_runtime_set_suspended(&pdev->dev); -- - s5pcsis_clk_put(state); - regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); - - media_entity_cleanup(&state->sd.entity); -- free_irq(state->irq, state); -- iounmap(state->regs); -- release_mem_region(res->start, resource_size(res)); -- kfree(state); - - return 0; - } -Index: linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-core.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-fimc/fimc-core.h -+++ linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-core.h -@@ -434,7 +434,6 @@ struct fimc_ctx; - * @num_clocks: the number of clocks managed by this device instance - * @clock: clocks required for FIMC operation - * @regs: the mapped hardware registers -- * @regs_res: the resource claimed for IO registers - * @irq: FIMC interrupt number - * @irq_queue: interrupt handler waitqueue - * @v4l2_dev: root v4l2_device -@@ -454,7 +453,6 @@ struct fimc_dev { - u16 num_clocks; - struct clk *clock[MAX_FIMC_CLOCKS]; - void __iomem *regs; -- struct resource *regs_res; - int irq; - wait_queue_head_t irq_queue; - struct v4l2_device *v4l2_dev; -Index: linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-capture.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-fimc/fimc-capture.c -+++ linux-3.3.x86_64/drivers/media/video/s5p-fimc/fimc-capture.c -@@ -1019,52 +1019,117 @@ static int fimc_cap_dqbuf(struct file *f - return vb2_dqbuf(&fimc->vid_cap.vbq, buf, file->f_flags & O_NONBLOCK); - } - --static int fimc_cap_cropcap(struct file *file, void *fh, -- struct v4l2_cropcap *cr) -+static int fimc_cap_create_bufs(struct file *file, void *priv, -+ struct v4l2_create_buffers *create) - { - struct fimc_dev *fimc = video_drvdata(file); -- struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame; - -- if (cr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) -- return -EINVAL; -+ return vb2_create_bufs(&fimc->vid_cap.vbq, create); -+} - -- cr->bounds.left = 0; -- cr->bounds.top = 0; -- cr->bounds.width = f->o_width; -- cr->bounds.height = f->o_height; -- cr->defrect = cr->bounds; -+static int fimc_cap_prepare_buf(struct file *file, void *priv, -+ struct v4l2_buffer *b) -+{ -+ struct fimc_dev *fimc = video_drvdata(file); - -- return 0; -+ return vb2_prepare_buf(&fimc->vid_cap.vbq, b); - } - --static int fimc_cap_g_crop(struct file *file, void *fh, struct v4l2_crop *cr) -+static int fimc_cap_g_selection(struct file *file, void *fh, -+ struct v4l2_selection *s) - { - struct fimc_dev *fimc = video_drvdata(file); -- struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame; -+ struct fimc_ctx *ctx = fimc->vid_cap.ctx; -+ struct fimc_frame *f = &ctx->s_frame; - -- cr->c.left = f->offs_h; -- cr->c.top = f->offs_v; -- cr->c.width = f->width; -- cr->c.height = f->height; -+ if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) -+ return -EINVAL; - -- return 0; -+ switch (s->target) { -+ case V4L2_SEL_TGT_COMPOSE_DEFAULT: -+ case V4L2_SEL_TGT_COMPOSE_BOUNDS: -+ f = &ctx->d_frame; -+ case V4L2_SEL_TGT_CROP_BOUNDS: -+ case V4L2_SEL_TGT_CROP_DEFAULT: -+ s->r.left = 0; -+ s->r.top = 0; -+ s->r.width = f->o_width; -+ s->r.height = f->o_height; -+ return 0; -+ -+ case V4L2_SEL_TGT_COMPOSE_ACTIVE: -+ f = &ctx->d_frame; -+ case V4L2_SEL_TGT_CROP_ACTIVE: -+ s->r.left = f->offs_h; -+ s->r.top = f->offs_v; -+ s->r.width = f->width; -+ s->r.height = f->height; -+ return 0; -+ } -+ -+ return -EINVAL; -+} -+ -+/* Return 1 if rectangle a is enclosed in rectangle b, or 0 otherwise. */ -+int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b) -+{ -+ if (a->left < b->left || a->top < b->top) -+ return 0; -+ if (a->left + a->width > b->left + b->width) -+ return 0; -+ if (a->top + a->height > b->top + b->height) -+ return 0; -+ -+ return 1; - } - --static int fimc_cap_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) -+static int fimc_cap_s_selection(struct file *file, void *fh, -+ struct v4l2_selection *s) - { - struct fimc_dev *fimc = video_drvdata(file); - struct fimc_ctx *ctx = fimc->vid_cap.ctx; -- struct fimc_frame *ff; -+ struct v4l2_rect rect = s->r; -+ struct fimc_frame *f; - unsigned long flags; -+ unsigned int pad; -+ -+ if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) -+ return -EINVAL; -+ -+ switch (s->target) { -+ case V4L2_SEL_TGT_COMPOSE_DEFAULT: -+ case V4L2_SEL_TGT_COMPOSE_BOUNDS: -+ case V4L2_SEL_TGT_COMPOSE_ACTIVE: -+ f = &ctx->d_frame; -+ pad = FIMC_SD_PAD_SOURCE; -+ break; -+ case V4L2_SEL_TGT_CROP_BOUNDS: -+ case V4L2_SEL_TGT_CROP_DEFAULT: -+ case V4L2_SEL_TGT_CROP_ACTIVE: -+ f = &ctx->s_frame; -+ pad = FIMC_SD_PAD_SINK; -+ break; -+ default: -+ return -EINVAL; -+ } - -- fimc_capture_try_crop(ctx, &cr->c, FIMC_SD_PAD_SINK); -- ff = &ctx->s_frame; -+ fimc_capture_try_crop(ctx, &rect, pad); - -+ if (s->flags & V4L2_SEL_FLAG_LE && -+ !enclosed_rectangle(&rect, &s->r)) -+ return -ERANGE; -+ -+ if (s->flags & V4L2_SEL_FLAG_GE && -+ !enclosed_rectangle(&s->r, &rect)) -+ return -ERANGE; -+ -+ s->r = rect; - spin_lock_irqsave(&fimc->slock, flags); -- set_frame_crop(ff, cr->c.left, cr->c.top, cr->c.width, cr->c.height); -- set_bit(ST_CAPT_APPLY_CFG, &fimc->state); -+ set_frame_crop(f, s->r.left, s->r.top, s->r.width, -+ s->r.height); - spin_unlock_irqrestore(&fimc->slock, flags); - -+ set_bit(ST_CAPT_APPLY_CFG, &fimc->state); - return 0; - } - -@@ -1082,12 +1147,14 @@ static const struct v4l2_ioctl_ops fimc_ - .vidioc_qbuf = fimc_cap_qbuf, - .vidioc_dqbuf = fimc_cap_dqbuf, - -+ .vidioc_prepare_buf = fimc_cap_prepare_buf, -+ .vidioc_create_bufs = fimc_cap_create_bufs, -+ - .vidioc_streamon = fimc_cap_streamon, - .vidioc_streamoff = fimc_cap_streamoff, - -- .vidioc_g_crop = fimc_cap_g_crop, -- .vidioc_s_crop = fimc_cap_s_crop, -- .vidioc_cropcap = fimc_cap_cropcap, -+ .vidioc_g_selection = fimc_cap_g_selection, -+ .vidioc_s_selection = fimc_cap_s_selection, - - .vidioc_enum_input = fimc_cap_enum_input, - .vidioc_s_input = fimc_cap_s_input, -Index: linux-3.3.x86_64/drivers/media/video/videobuf2-vmalloc.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/videobuf2-vmalloc.c -+++ linux-3.3.x86_64/drivers/media/video/videobuf2-vmalloc.c -@@ -10,6 +10,7 @@ - * the Free Software Foundation. - */ - -+#include - #include - #include - #include -@@ -22,6 +23,7 @@ - struct vb2_vmalloc_buf { - void *vaddr; - struct page **pages; -+ struct vm_area_struct *vma; - int write; - unsigned long size; - unsigned int n_pages; -@@ -71,6 +73,8 @@ static void *vb2_vmalloc_get_userptr(voi - struct vb2_vmalloc_buf *buf; - unsigned long first, last; - int n_pages, offset; -+ struct vm_area_struct *vma; -+ dma_addr_t physp; - - buf = kzalloc(sizeof(*buf), GFP_KERNEL); - if (!buf) -@@ -80,23 +84,37 @@ static void *vb2_vmalloc_get_userptr(voi - offset = vaddr & ~PAGE_MASK; - buf->size = size; - -- first = vaddr >> PAGE_SHIFT; -- last = (vaddr + size - 1) >> PAGE_SHIFT; -- buf->n_pages = last - first + 1; -- buf->pages = kzalloc(buf->n_pages * sizeof(struct page *), GFP_KERNEL); -- if (!buf->pages) -- goto fail_pages_array_alloc; -- -- /* current->mm->mmap_sem is taken by videobuf2 core */ -- n_pages = get_user_pages(current, current->mm, vaddr & PAGE_MASK, -- buf->n_pages, write, 1, /* force */ -- buf->pages, NULL); -- if (n_pages != buf->n_pages) -- goto fail_get_user_pages; -- -- buf->vaddr = vm_map_ram(buf->pages, buf->n_pages, -1, PAGE_KERNEL); -- if (!buf->vaddr) -- goto fail_get_user_pages; -+ -+ vma = find_vma(current->mm, vaddr); -+ if (vma && (vma->vm_flags & VM_PFNMAP) && (vma->vm_pgoff)) { -+ if (vb2_get_contig_userptr(vaddr, size, &vma, &physp)) -+ goto fail_pages_array_alloc; -+ buf->vma = vma; -+ buf->vaddr = ioremap_nocache(physp, size); -+ if (!buf->vaddr) -+ goto fail_pages_array_alloc; -+ } else { -+ first = vaddr >> PAGE_SHIFT; -+ last = (vaddr + size - 1) >> PAGE_SHIFT; -+ buf->n_pages = last - first + 1; -+ buf->pages = kzalloc(buf->n_pages * sizeof(struct page *), -+ GFP_KERNEL); -+ if (!buf->pages) -+ goto fail_pages_array_alloc; -+ -+ /* current->mm->mmap_sem is taken by videobuf2 core */ -+ n_pages = get_user_pages(current, current->mm, -+ vaddr & PAGE_MASK, buf->n_pages, -+ write, 1, /* force */ -+ buf->pages, NULL); -+ if (n_pages != buf->n_pages) -+ goto fail_get_user_pages; -+ -+ buf->vaddr = vm_map_ram(buf->pages, buf->n_pages, -1, -+ PAGE_KERNEL); -+ if (!buf->vaddr) -+ goto fail_get_user_pages; -+ } - - buf->vaddr += offset; - return buf; -@@ -120,14 +138,20 @@ static void vb2_vmalloc_put_userptr(void - unsigned long vaddr = (unsigned long)buf->vaddr & PAGE_MASK; - unsigned int i; - -- if (vaddr) -- vm_unmap_ram((void *)vaddr, buf->n_pages); -- for (i = 0; i < buf->n_pages; ++i) { -- if (buf->write) -- set_page_dirty_lock(buf->pages[i]); -- put_page(buf->pages[i]); -+ if (buf->pages) { -+ if (vaddr) -+ vm_unmap_ram((void *)vaddr, buf->n_pages); -+ for (i = 0; i < buf->n_pages; ++i) { -+ if (buf->write) -+ set_page_dirty_lock(buf->pages[i]); -+ put_page(buf->pages[i]); -+ } -+ kfree(buf->pages); -+ } else { -+ if (buf->vma) -+ vb2_put_vma(buf->vma); -+ iounmap(buf->vaddr); - } -- kfree(buf->pages); - kfree(buf); - } - -Index: linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-g2d/g2d.c -+++ linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d.c -@@ -178,6 +178,9 @@ static int g2d_s_ctrl(struct v4l2_ctrl * - { - struct g2d_ctx *ctx = container_of(ctrl->handler, struct g2d_ctx, - ctrl_handler); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&ctx->dev->ctrl_lock, flags); - switch (ctrl->id) { - case V4L2_CID_COLORFX: - if (ctrl->val == V4L2_COLORFX_NEGATIVE) -@@ -185,10 +188,13 @@ static int g2d_s_ctrl(struct v4l2_ctrl * - else - ctx->rop = ROP4_COPY; - break; -- default: -- v4l2_err(&ctx->dev->v4l2_dev, "unknown control\n"); -- return -EINVAL; -+ -+ case V4L2_CID_HFLIP: -+ ctx->flip = ctx->ctrl_hflip->val | (ctx->ctrl_vflip->val << 1); -+ break; -+ - } -+ spin_unlock_irqrestore(&ctx->dev->ctrl_lock, flags); - return 0; - } - -@@ -200,11 +206,13 @@ int g2d_setup_ctrls(struct g2d_ctx *ctx) - { - struct g2d_dev *dev = ctx->dev; - -- v4l2_ctrl_handler_init(&ctx->ctrl_handler, 1); -- if (ctx->ctrl_handler.error) { -- v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n"); -- return ctx->ctrl_handler.error; -- } -+ v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3); -+ -+ ctx->ctrl_hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &g2d_ctrl_ops, -+ V4L2_CID_HFLIP, 0, 1, 1, 0); -+ -+ ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &g2d_ctrl_ops, -+ V4L2_CID_VFLIP, 0, 1, 1, 0); - - v4l2_ctrl_new_std_menu( - &ctx->ctrl_handler, -@@ -215,10 +223,14 @@ int g2d_setup_ctrls(struct g2d_ctx *ctx) - V4L2_COLORFX_NONE); - - if (ctx->ctrl_handler.error) { -- v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n"); -- return ctx->ctrl_handler.error; -+ int err = ctx->ctrl_handler.error; -+ v4l2_err(&dev->v4l2_dev, "g2d_setup_ctrls failed\n"); -+ v4l2_ctrl_handler_free(&ctx->ctrl_handler); -+ return err; - } - -+ v4l2_ctrl_cluster(2, &ctx->ctrl_hflip); -+ - return 0; - } - -@@ -547,6 +559,7 @@ static void device_run(void *prv) - struct g2d_ctx *ctx = prv; - struct g2d_dev *dev = ctx->dev; - struct vb2_buffer *src, *dst; -+ unsigned long flags; - u32 cmd = 0; - - dev->curr = ctx; -@@ -557,6 +570,8 @@ static void device_run(void *prv) - clk_enable(dev->gate); - g2d_reset(dev); - -+ spin_lock_irqsave(&dev->ctrl_lock, flags); -+ - g2d_set_src_size(dev, &ctx->in); - g2d_set_src_addr(dev, vb2_dma_contig_plane_dma_addr(src, 0)); - -@@ -564,11 +579,15 @@ static void device_run(void *prv) - g2d_set_dst_addr(dev, vb2_dma_contig_plane_dma_addr(dst, 0)); - - g2d_set_rop4(dev, ctx->rop); -+ g2d_set_flip(dev, ctx->flip); -+ - if (ctx->in.c_width != ctx->out.c_width || - ctx->in.c_height != ctx->out.c_height) - cmd |= g2d_cmd_stretch(1); - g2d_set_cmd(dev, cmd); - g2d_start(dev); -+ -+ spin_unlock_irqrestore(&dev->ctrl_lock, flags); - } - - static irqreturn_t g2d_isr(int irq, void *prv) -@@ -658,7 +677,7 @@ static int g2d_probe(struct platform_dev - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; -- spin_lock_init(&dev->irqlock); -+ spin_lock_init(&dev->ctrl_lock); - mutex_init(&dev->mutex); - atomic_set(&dev->num_inst, 0); - init_waitqueue_head(&dev->irq_queue); -@@ -693,18 +712,30 @@ static int g2d_probe(struct platform_dev - goto unmap_regs; - } - -+ ret = clk_prepare(dev->clk); -+ if (ret) { -+ dev_err(&pdev->dev, "failed to prepare g2d clock\n"); -+ goto put_clk; -+ } -+ - dev->gate = clk_get(&pdev->dev, "fimg2d"); - if (IS_ERR_OR_NULL(dev->gate)) { - dev_err(&pdev->dev, "failed to get g2d clock gate\n"); - ret = -ENXIO; -- goto put_clk; -+ goto unprep_clk; -+ } -+ -+ ret = clk_prepare(dev->gate); -+ if (ret) { -+ dev_err(&pdev->dev, "failed to prepare g2d clock gate\n"); -+ goto put_clk_gate; - } - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(&pdev->dev, "failed to find IRQ\n"); - ret = -ENXIO; -- goto put_clk_gate; -+ goto unprep_clk_gate; - } - - dev->irq = res->start; -@@ -764,8 +795,12 @@ alloc_ctx_cleanup: - vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); - rel_irq: - free_irq(dev->irq, dev); -+unprep_clk_gate: -+ clk_unprepare(dev->gate); - put_clk_gate: - clk_put(dev->gate); -+unprep_clk: -+ clk_unprepare(dev->clk); - put_clk: - clk_put(dev->clk); - unmap_regs: -@@ -787,7 +822,9 @@ static int g2d_remove(struct platform_de - v4l2_device_unregister(&dev->v4l2_dev); - vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); - free_irq(dev->irq, dev); -+ clk_unprepare(dev->gate); - clk_put(dev->gate); -+ clk_unprepare(dev->clk); - clk_put(dev->clk); - iounmap(dev->regs); - release_resource(dev->res_regs); -Index: linux-3.3.x86_64/drivers/media/video/s5p-mfc/s5p_mfc_pm.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-mfc/s5p_mfc_pm.c -+++ linux-3.3.x86_64/drivers/media/video/s5p-mfc/s5p_mfc_pm.c -@@ -41,15 +41,29 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev * - pm->clock_gate = clk_get(&dev->plat_dev->dev, MFC_GATE_CLK_NAME); - if (IS_ERR(pm->clock_gate)) { - mfc_err("Failed to get clock-gating control\n"); -- ret = -ENOENT; -+ ret = PTR_ERR(pm->clock_gate); - goto err_g_ip_clk; - } -+ -+ ret = clk_prepare(pm->clock_gate); -+ if (ret) { -+ mfc_err("Failed to preapre clock-gating control\n"); -+ goto err_p_ip_clk; -+ } -+ - pm->clock = clk_get(&dev->plat_dev->dev, MFC_CLKNAME); - if (IS_ERR(pm->clock)) { - mfc_err("Failed to get MFC clock\n"); -- ret = -ENOENT; -+ ret = PTR_ERR(pm->clock); - goto err_g_ip_clk_2; - } -+ -+ ret = clk_prepare(pm->clock); -+ if (ret) { -+ mfc_err("Failed to prepare MFC clock\n"); -+ goto err_p_ip_clk_2; -+ } -+ - atomic_set(&pm->power, 0); - #ifdef CONFIG_PM_RUNTIME - pm->device = &dev->plat_dev->dev; -@@ -59,7 +73,11 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev * - atomic_set(&clk_ref, 0); - #endif - return 0; -+err_p_ip_clk_2: -+ clk_put(pm->clock); - err_g_ip_clk_2: -+ clk_unprepare(pm->clock_gate); -+err_p_ip_clk: - clk_put(pm->clock_gate); - err_g_ip_clk: - return ret; -@@ -67,7 +85,9 @@ err_g_ip_clk: - - void s5p_mfc_final_pm(struct s5p_mfc_dev *dev) - { -+ clk_unprepare(pm->clock_gate); - clk_put(pm->clock_gate); -+ clk_unprepare(pm->clock); - clk_put(pm->clock); - #ifdef CONFIG_PM_RUNTIME - pm_runtime_disable(pm->device); -Index: linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d-hw.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-g2d/g2d-hw.c -+++ linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d-hw.c -@@ -77,6 +77,11 @@ void g2d_set_rop4(struct g2d_dev *d, u32 - w(r, ROP4_REG); - } - -+void g2d_set_flip(struct g2d_dev *d, u32 r) -+{ -+ w(r, SRC_MSK_DIRECT_REG); -+} -+ - u32 g2d_cmd_stretch(u32 e) - { - e &= 1; -Index: linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-g2d/g2d.h -+++ linux-3.3.x86_64/drivers/media/video/s5p-g2d/g2d.h -@@ -20,7 +20,7 @@ struct g2d_dev { - struct v4l2_m2m_dev *m2m_dev; - struct video_device *vfd; - struct mutex mutex; -- spinlock_t irqlock; -+ spinlock_t ctrl_lock; - atomic_t num_inst; - struct vb2_alloc_ctx *alloc_ctx; - struct resource *res_regs; -@@ -57,8 +57,11 @@ struct g2d_ctx { - struct v4l2_m2m_ctx *m2m_ctx; - struct g2d_frame in; - struct g2d_frame out; -+ struct v4l2_ctrl *ctrl_hflip; -+ struct v4l2_ctrl *ctrl_vflip; - struct v4l2_ctrl_handler ctrl_handler; - u32 rop; -+ u32 flip; - }; - - struct g2d_fmt { -@@ -77,6 +80,7 @@ void g2d_set_dst_addr(struct g2d_dev *d, - void g2d_start(struct g2d_dev *d); - void g2d_clear_int(struct g2d_dev *d); - void g2d_set_rop4(struct g2d_dev *d, u32 r); -+void g2d_set_flip(struct g2d_dev *d, u32 r); - u32 g2d_cmd_stretch(u32 e); - void g2d_set_cmd(struct g2d_dev *d, u32 c); - -Index: linux-3.3.x86_64/drivers/media/video/s5k6aa.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5k6aa.c -+++ linux-3.3.x86_64/drivers/media/video/s5k6aa.c -@@ -1582,8 +1582,8 @@ static int s5k6aa_probe(struct i2c_clien - s5k6aa->inv_vflip = pdata->vert_flip; - - sd = &s5k6aa->sd; -- strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name)); - v4l2_i2c_subdev_init(sd, client, &s5k6aa_subdev_ops); -+ strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name)); - - sd->internal_ops = &s5k6aa_subdev_internal_ops; - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; -@@ -1663,18 +1663,7 @@ static struct i2c_driver s5k6aa_i2c_driv - .id_table = s5k6aa_id, - }; - --static int __init s5k6aa_init(void) --{ -- return i2c_add_driver(&s5k6aa_i2c_driver); --} -- --static void __exit s5k6aa_exit(void) --{ -- i2c_del_driver(&s5k6aa_i2c_driver); --} -- --module_init(s5k6aa_init); --module_exit(s5k6aa_exit); -+module_i2c_driver(s5k6aa_i2c_driver); - - MODULE_DESCRIPTION("Samsung S5K6AA(FX) SXGA camera driver"); - MODULE_AUTHOR("Sylwester Nawrocki "); -Index: linux-3.3.x86_64/drivers/media/video/noon010pc30.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/noon010pc30.c -+++ linux-3.3.x86_64/drivers/media/video/noon010pc30.c -@@ -725,8 +725,8 @@ static int noon010_probe(struct i2c_clie - - mutex_init(&info->lock); - sd = &info->sd; -- strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); - v4l2_i2c_subdev_init(sd, client, &noon010_ops); -+ strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); - - sd->internal_ops = &noon010_subdev_internal_ops; - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; -@@ -844,18 +844,7 @@ static struct i2c_driver noon010_i2c_dri - .id_table = noon010_id, - }; - --static int __init noon010_init(void) --{ -- return i2c_add_driver(&noon010_i2c_driver); --} -- --static void __exit noon010_exit(void) --{ -- i2c_del_driver(&noon010_i2c_driver); --} -- --module_init(noon010_init); --module_exit(noon010_exit); -+module_i2c_driver(noon010_i2c_driver); - - MODULE_DESCRIPTION("Siliconfile NOON010PC30 camera driver"); - MODULE_AUTHOR("Sylwester Nawrocki "); -Index: linux-3.3.x86_64/drivers/media/video/m5mols/m5mols_core.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/m5mols/m5mols_core.c -+++ linux-3.3.x86_64/drivers/media/video/m5mols/m5mols_core.c -@@ -982,8 +982,8 @@ static int __devinit m5mols_probe(struct - } - - sd = &info->sd; -- strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); - v4l2_i2c_subdev_init(sd, client, &m5mols_ops); -+ strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - sd->internal_ops = &m5mols_subdev_internal_ops; -@@ -1057,18 +1057,7 @@ static struct i2c_driver m5mols_i2c_driv - .id_table = m5mols_id, - }; - --static int __init m5mols_mod_init(void) --{ -- return i2c_add_driver(&m5mols_i2c_driver); --} -- --static void __exit m5mols_mod_exit(void) --{ -- i2c_del_driver(&m5mols_i2c_driver); --} -- --module_init(m5mols_mod_init); --module_exit(m5mols_mod_exit); -+module_i2c_driver(m5mols_i2c_driver); - - MODULE_AUTHOR("HeungJun Kim "); - MODULE_AUTHOR("Dongsoo Kim "); -Index: linux-3.3.x86_64/Documentation/video4linux/gspca.txt -=================================================================== ---- linux-3.3.x86_64.orig/Documentation/video4linux/gspca.txt -+++ linux-3.3.x86_64/Documentation/video4linux/gspca.txt -@@ -217,6 +217,7 @@ ov534_9 06f8:3003 Hercules Dualpix HD W - sonixj 06f8:3004 Hercules Classic Silver - sonixj 06f8:3008 Hercules Deluxe Optical Glass - pac7302 06f8:3009 Hercules Classic Link -+pac7302 06f8:301b Hercules Link - nw80x 0728:d001 AVerMedia Camguard - spca508 0733:0110 ViewQuest VQ110 - spca501 0733:0401 Intel Create and Share -Index: linux-3.3.x86_64/drivers/media/video/gspca/pac7302.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/gspca/pac7302.c -+++ linux-3.3.x86_64/drivers/media/video/gspca/pac7302.c -@@ -1,8 +1,8 @@ - /* -- * Pixart PAC7302 library -- * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li -+ * Pixart PAC7302 driver - * -- * V4L2 by Jean-Francois Moine -+ * Copyright (C) 2008-2012 Jean-Francois Moine -+ * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li - * - * Separated from Pixart PAC7311 library by Márton Németh - * Camera button input handling by Márton Németh -@@ -63,67 +63,61 @@ - - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - --#define MODULE_NAME "pac7302" -- - #include - #include - #include "gspca.h" -+/* Include pac common sof detection functions */ -+#include "pac_common.h" - --MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); -+MODULE_AUTHOR("Jean-Francois Moine , " -+ "Thomas Kaiser thomas@kaiser-linux.li"); - MODULE_DESCRIPTION("Pixart PAC7302"); - MODULE_LICENSE("GPL"); - -+enum e_ctrl { -+ BRIGHTNESS, -+ CONTRAST, -+ COLORS, -+ WHITE_BALANCE, -+ RED_BALANCE, -+ BLUE_BALANCE, -+ GAIN, -+ AUTOGAIN, -+ EXPOSURE, -+ VFLIP, -+ HFLIP, -+ NCTRLS /* number of controls */ -+}; -+ - /* specific webcam descriptor for pac7302 */ - struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - -- unsigned char brightness; -- unsigned char contrast; -- unsigned char colors; -- unsigned char white_balance; -- unsigned char red_balance; -- unsigned char blue_balance; -- unsigned char gain; -- unsigned char autogain; -- unsigned short exposure; -- __u8 hflip; -- __u8 vflip; -+ struct gspca_ctrl ctrls[NCTRLS]; -+ - u8 flags; - #define FL_HFLIP 0x01 /* mirrored by default */ - #define FL_VFLIP 0x02 /* vertical flipped by default */ - - u8 sof_read; -- u8 autogain_ignore_frames; -+ s8 autogain_ignore_frames; - - atomic_t avg_lum; - }; - - /* V4L2 controls supported by the driver */ --static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); --static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); --static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); --static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); --static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); --static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); --static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val); --static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val); --static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val); --static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val); --static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val); --static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val); --static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); --static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); --static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); --static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); --static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); --static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); --static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); --static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); --static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); --static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); -+static void setbrightcont(struct gspca_dev *gspca_dev); -+static void setcolors(struct gspca_dev *gspca_dev); -+static void setwhitebalance(struct gspca_dev *gspca_dev); -+static void setredbalance(struct gspca_dev *gspca_dev); -+static void setbluebalance(struct gspca_dev *gspca_dev); -+static void setgain(struct gspca_dev *gspca_dev); -+static void setexposure(struct gspca_dev *gspca_dev); -+static void setautogain(struct gspca_dev *gspca_dev); -+static void sethvflip(struct gspca_dev *gspca_dev); - - static const struct ctrl sd_ctrls[] = { -- { -+[BRIGHTNESS] = { - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, -@@ -132,13 +126,11 @@ static const struct ctrl sd_ctrls[] = { - #define BRIGHTNESS_MAX 0x20 - .maximum = BRIGHTNESS_MAX, - .step = 1, --#define BRIGHTNESS_DEF 0x10 -- .default_value = BRIGHTNESS_DEF, -+ .default_value = 0x10, - }, -- .set = sd_setbrightness, -- .get = sd_getbrightness, -+ .set_control = setbrightcont - }, -- { -+[CONTRAST] = { - { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, -@@ -147,13 +139,11 @@ static const struct ctrl sd_ctrls[] = { - #define CONTRAST_MAX 255 - .maximum = CONTRAST_MAX, - .step = 1, --#define CONTRAST_DEF 127 -- .default_value = CONTRAST_DEF, -+ .default_value = 127, - }, -- .set = sd_setcontrast, -- .get = sd_getcontrast, -+ .set_control = setbrightcont - }, -- { -+[COLORS] = { - { - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, -@@ -162,13 +152,11 @@ static const struct ctrl sd_ctrls[] = { - #define COLOR_MAX 255 - .maximum = COLOR_MAX, - .step = 1, --#define COLOR_DEF 127 -- .default_value = COLOR_DEF, -+ .default_value = 127 - }, -- .set = sd_setcolors, -- .get = sd_getcolors, -+ .set_control = setcolors - }, -- { -+[WHITE_BALANCE] = { - { - .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE, - .type = V4L2_CTRL_TYPE_INTEGER, -@@ -176,13 +164,11 @@ static const struct ctrl sd_ctrls[] = { - .minimum = 0, - .maximum = 255, - .step = 1, --#define WHITEBALANCE_DEF 4 -- .default_value = WHITEBALANCE_DEF, -+ .default_value = 4, - }, -- .set = sd_setwhitebalance, -- .get = sd_getwhitebalance, -+ .set_control = setwhitebalance - }, -- { -+[RED_BALANCE] = { - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, -@@ -190,13 +176,11 @@ static const struct ctrl sd_ctrls[] = { - .minimum = 0, - .maximum = 3, - .step = 1, --#define REDBALANCE_DEF 1 -- .default_value = REDBALANCE_DEF, -+ .default_value = 1, - }, -- .set = sd_setredbalance, -- .get = sd_getredbalance, -+ .set_control = setredbalance - }, -- { -+[BLUE_BALANCE] = { - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, -@@ -204,29 +188,25 @@ static const struct ctrl sd_ctrls[] = { - .minimum = 0, - .maximum = 3, - .step = 1, --#define BLUEBALANCE_DEF 1 -- .default_value = BLUEBALANCE_DEF, -+ .default_value = 1, - }, -- .set = sd_setbluebalance, -- .get = sd_getbluebalance, -+ .set_control = setbluebalance - }, -- { -+[GAIN] = { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Gain", - .minimum = 0, --#define GAIN_MAX 255 -- .maximum = GAIN_MAX, -+ .maximum = 255, - .step = 1, - #define GAIN_DEF 127 - #define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */ - .default_value = GAIN_DEF, - }, -- .set = sd_setgain, -- .get = sd_getgain, -+ .set_control = setgain - }, -- { -+[EXPOSURE] = { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, -@@ -238,10 +218,9 @@ static const struct ctrl sd_ctrls[] = { - #define EXPOSURE_KNEE 133 /* 66 ms / 15 fps */ - .default_value = EXPOSURE_DEF, - }, -- .set = sd_setexposure, -- .get = sd_getexposure, -+ .set_control = setexposure - }, -- { -+[AUTOGAIN] = { - { - .id = V4L2_CID_AUTOGAIN, - .type = V4L2_CTRL_TYPE_BOOLEAN, -@@ -252,10 +231,9 @@ static const struct ctrl sd_ctrls[] = { - #define AUTOGAIN_DEF 1 - .default_value = AUTOGAIN_DEF, - }, -- .set = sd_setautogain, -- .get = sd_getautogain, -+ .set_control = setautogain, - }, -- { -+[HFLIP] = { - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, -@@ -263,13 +241,11 @@ static const struct ctrl sd_ctrls[] = { - .minimum = 0, - .maximum = 1, - .step = 1, --#define HFLIP_DEF 0 -- .default_value = HFLIP_DEF, -+ .default_value = 0, - }, -- .set = sd_sethflip, -- .get = sd_gethflip, -+ .set_control = sethvflip, - }, -- { -+[VFLIP] = { - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, -@@ -277,11 +253,9 @@ static const struct ctrl sd_ctrls[] = { - .minimum = 0, - .maximum = 1, - .step = 1, --#define VFLIP_DEF 0 -- .default_value = VFLIP_DEF, -+ .default_value = 0, - }, -- .set = sd_setvflip, -- .get = sd_getvflip, -+ .set_control = sethvflip - }, - }; - -@@ -290,21 +264,21 @@ static const struct v4l2_pix_format vga_ - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, -- .priv = 0}, -+ }, - }; - - #define LOAD_PAGE3 255 - #define END_OF_SEQUENCE 0 - - /* pac 7302 */ --static const __u8 init_7302[] = { -+static const u8 init_7302[] = { - /* index,value */ - 0xff, 0x01, /* page 1 */ - 0x78, 0x00, /* deactivate */ - 0xff, 0x01, - 0x78, 0x40, /* led off */ - }; --static const __u8 start_7302[] = { -+static const u8 start_7302[] = { - /* index, len, [value]* */ - 0xff, 1, 0x00, /* page 0 */ - 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80, -@@ -319,7 +293,7 @@ static const __u8 start_7302[] = { - 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11, - 0x00, 0x54, 0x11, - 0x55, 1, 0x00, -- 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, -+ 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, - 0x6b, 1, 0x00, - 0x6e, 3, 0x08, 0x06, 0x00, - 0x72, 3, 0x00, 0xff, 0x00, -@@ -370,7 +344,7 @@ static const __u8 start_7302[] = { - - #define SKIP 0xaa - /* page 3 - the value SKIP says skip the index - see reg_w_page() */ --static const __u8 page3_7302[] = { -+static const u8 page3_7302[] = { - 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16, - 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, - 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -@@ -394,7 +368,7 @@ static const __u8 page3_7302[] = { - }; - - static void reg_w_buf(struct gspca_dev *gspca_dev, -- __u8 index, -+ u8 index, - const u8 *buffer, int len) - { - int ret; -@@ -410,7 +384,7 @@ static void reg_w_buf(struct gspca_dev * - index, gspca_dev->usb_buf, len, - 500); - if (ret < 0) { -- pr_err("reg_w_buf failed index 0x%02x, error %d\n", -+ pr_err("reg_w_buf failed i: %02x error %d\n", - index, ret); - gspca_dev->usb_err = ret; - } -@@ -418,8 +392,8 @@ static void reg_w_buf(struct gspca_dev * - - - static void reg_w(struct gspca_dev *gspca_dev, -- __u8 index, -- __u8 value) -+ u8 index, -+ u8 value) - { - int ret; - -@@ -433,14 +407,14 @@ static void reg_w(struct gspca_dev *gspc - 0, index, gspca_dev->usb_buf, 1, - 500); - if (ret < 0) { -- pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n", -+ pr_err("reg_w() failed i: %02x v: %02x error %d\n", - index, value, ret); - gspca_dev->usb_err = ret; - } - } - - static void reg_w_seq(struct gspca_dev *gspca_dev, -- const __u8 *seq, int len) -+ const u8 *seq, int len) - { - while (--len >= 0) { - reg_w(gspca_dev, seq[0], seq[1]); -@@ -450,7 +424,7 @@ static void reg_w_seq(struct gspca_dev * - - /* load the beginning of a page */ - static void reg_w_page(struct gspca_dev *gspca_dev, -- const __u8 *page, int len) -+ const u8 *page, int len) - { - int index; - int ret = 0; -@@ -468,7 +442,7 @@ static void reg_w_page(struct gspca_dev - 0, index, gspca_dev->usb_buf, 1, - 500); - if (ret < 0) { -- pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n", -+ pr_err("reg_w_page() failed i: %02x v: %02x error %d\n", - index, page[index], ret); - gspca_dev->usb_err = ret; - break; -@@ -478,8 +452,8 @@ static void reg_w_page(struct gspca_dev - - /* output a variable sequence */ - static void reg_w_var(struct gspca_dev *gspca_dev, -- const __u8 *seq, -- const __u8 *page3, unsigned int page3_len) -+ const u8 *seq, -+ const u8 *page3, unsigned int page3_len) - { - int index, len; - -@@ -493,11 +467,13 @@ static void reg_w_var(struct gspca_dev * - reg_w_page(gspca_dev, page3, page3_len); - break; - default: -+#ifdef GSPCA_DEBUG - if (len > USB_BUF_SZ) { - PDEBUG(D_ERR|D_STREAM, - "Incorrect variable sequence"); - return; - } -+#endif - while (len > 0) { - if (len < 8) { - reg_w_buf(gspca_dev, -@@ -524,21 +500,11 @@ static int sd_config(struct gspca_dev *g - - cam = &gspca_dev->cam; - -- PDEBUG(D_CONF, "Find Sensor PAC7302"); - cam->cam_mode = vga_mode; /* only 640x480 */ - cam->nmodes = ARRAY_SIZE(vga_mode); - -- sd->brightness = BRIGHTNESS_DEF; -- sd->contrast = CONTRAST_DEF; -- sd->colors = COLOR_DEF; -- sd->white_balance = WHITEBALANCE_DEF; -- sd->red_balance = REDBALANCE_DEF; -- sd->blue_balance = BLUEBALANCE_DEF; -- sd->gain = GAIN_DEF; -- sd->exposure = EXPOSURE_DEF; -- sd->autogain = AUTOGAIN_DEF; -- sd->hflip = HFLIP_DEF; -- sd->vflip = VFLIP_DEF; -+ gspca_dev->cam.ctrls = sd->ctrls; -+ - sd->flags = id->driver_info; - return 0; - } -@@ -548,19 +514,19 @@ static void setbrightcont(struct gspca_d - { - struct sd *sd = (struct sd *) gspca_dev; - int i, v; -- static const __u8 max[10] = -+ static const u8 max[10] = - {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, - 0xd4, 0xec}; -- static const __u8 delta[10] = -+ static const u8 delta[10] = - {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, - 0x11, 0x0b}; - - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ - for (i = 0; i < 10; i++) { - v = max[i]; -- v += (sd->brightness - BRIGHTNESS_MAX) -+ v += (sd->ctrls[BRIGHTNESS].val - BRIGHTNESS_MAX) - * 150 / BRIGHTNESS_MAX; /* 200 ? */ -- v -= delta[i] * sd->contrast / CONTRAST_MAX; -+ v -= delta[i] * sd->ctrls[CONTRAST].val / CONTRAST_MAX; - if (v < 0) - v = 0; - else if (v > 0xff) -@@ -584,12 +550,11 @@ static void setcolors(struct gspca_dev * - reg_w(gspca_dev, 0x11, 0x01); - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ - for (i = 0; i < 9; i++) { -- v = a[i] * sd->colors / COLOR_MAX + b[i]; -+ v = a[i] * sd->ctrls[COLORS].val / COLOR_MAX + b[i]; - reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); - reg_w(gspca_dev, 0x0f + 2 * i + 1, v); - } - reg_w(gspca_dev, 0xdc, 0x01); -- PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); - } - - static void setwhitebalance(struct gspca_dev *gspca_dev) -@@ -597,10 +562,9 @@ static void setwhitebalance(struct gspca - struct sd *sd = (struct sd *) gspca_dev; - - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ -- reg_w(gspca_dev, 0xc6, sd->white_balance); -+ reg_w(gspca_dev, 0xc6, sd->ctrls[WHITE_BALANCE].val); - - reg_w(gspca_dev, 0xdc, 0x01); -- PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance); - } - - static void setredbalance(struct gspca_dev *gspca_dev) -@@ -608,10 +572,9 @@ static void setredbalance(struct gspca_d - struct sd *sd = (struct sd *) gspca_dev; - - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ -- reg_w(gspca_dev, 0xc5, sd->red_balance); -+ reg_w(gspca_dev, 0xc5, sd->ctrls[RED_BALANCE].val); - - reg_w(gspca_dev, 0xdc, 0x01); -- PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance); - } - - static void setbluebalance(struct gspca_dev *gspca_dev) -@@ -619,10 +582,9 @@ static void setbluebalance(struct gspca_ - struct sd *sd = (struct sd *) gspca_dev; - - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ -- reg_w(gspca_dev, 0xc7, sd->blue_balance); -+ reg_w(gspca_dev, 0xc7, sd->ctrls[BLUE_BALANCE].val); - - reg_w(gspca_dev, 0xdc, 0x01); -- PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance); - } - - static void setgain(struct gspca_dev *gspca_dev) -@@ -630,7 +592,7 @@ static void setgain(struct gspca_dev *gs - struct sd *sd = (struct sd *) gspca_dev; - - reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ -- reg_w(gspca_dev, 0x10, sd->gain >> 3); -+ reg_w(gspca_dev, 0x10, sd->ctrls[GAIN].val >> 3); - - /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); -@@ -639,13 +601,13 @@ static void setgain(struct gspca_dev *gs - static void setexposure(struct gspca_dev *gspca_dev) - { - struct sd *sd = (struct sd *) gspca_dev; -- __u8 clockdiv; -- __u16 exposure; -+ u8 clockdiv; -+ u16 exposure; - - /* register 2 of frame 3 contains the clock divider configuring the - no fps according to the formula: 90 / reg. sd->exposure is the - desired exposure time in 0.5 ms. */ -- clockdiv = (90 * sd->exposure + 1999) / 2000; -+ clockdiv = (90 * sd->ctrls[EXPOSURE].val + 1999) / 2000; - - /* Note clockdiv = 3 also works, but when running at 30 fps, depending - on the scene being recorded, the camera switches to another -@@ -664,7 +626,7 @@ static void setexposure(struct gspca_dev - - /* frame exposure time in ms = 1000 * clockdiv / 90 -> - exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */ -- exposure = (sd->exposure * 45 * 448) / (1000 * clockdiv); -+ exposure = (sd->ctrls[EXPOSURE].val * 45 * 448) / (1000 * clockdiv); - /* 0 = use full frametime, 448 = no exposure, reverse it */ - exposure = 448 - exposure; - -@@ -677,15 +639,35 @@ static void setexposure(struct gspca_dev - reg_w(gspca_dev, 0x11, 0x01); - } - -+static void setautogain(struct gspca_dev *gspca_dev) -+{ -+ struct sd *sd = (struct sd *) gspca_dev; -+ -+ /* when switching to autogain set defaults to make sure -+ we are on a valid point of the autogain gain / -+ exposure knee graph, and give this change time to -+ take effect before doing autogain. */ -+ if (sd->ctrls[AUTOGAIN].val) { -+ sd->ctrls[EXPOSURE].val = EXPOSURE_DEF; -+ sd->ctrls[GAIN].val = GAIN_DEF; -+ sd->autogain_ignore_frames = -+ PAC_AUTOGAIN_IGNORE_FRAMES; -+ } else { -+ sd->autogain_ignore_frames = -1; -+ } -+ setexposure(gspca_dev); -+ setgain(gspca_dev); -+} -+ - static void sethvflip(struct gspca_dev *gspca_dev) - { - struct sd *sd = (struct sd *) gspca_dev; - u8 data, hflip, vflip; - -- hflip = sd->hflip; -+ hflip = sd->ctrls[HFLIP].val; - if (sd->flags & FL_HFLIP) - hflip = !hflip; -- vflip = sd->vflip; -+ vflip = sd->ctrls[VFLIP].val; - if (sd->flags & FL_VFLIP) - vflip = !vflip; - -@@ -708,8 +690,6 @@ static int sd_start(struct gspca_dev *gs - { - struct sd *sd = (struct sd *) gspca_dev; - -- sd->sof_read = 0; -- - reg_w_var(gspca_dev, start_7302, - page3_7302, sizeof(page3_7302)); - setbrightcont(gspca_dev); -@@ -717,15 +697,13 @@ static int sd_start(struct gspca_dev *gs - setwhitebalance(gspca_dev); - setredbalance(gspca_dev); - setbluebalance(gspca_dev); -- setgain(gspca_dev); -- setexposure(gspca_dev); -+ setautogain(gspca_dev); - sethvflip(gspca_dev); - - /* only resolution 640x480 is supported for pac7302 */ - - sd->sof_read = 0; -- sd->autogain_ignore_frames = 0; -- atomic_set(&sd->avg_lum, -1); -+ atomic_set(&sd->avg_lum, 270 + sd->ctrls[BRIGHTNESS].val); - - /* start stream */ - reg_w(gspca_dev, 0xff, 0x01); -@@ -751,8 +729,10 @@ static void sd_stop0(struct gspca_dev *g - reg_w(gspca_dev, 0x78, 0x40); - } - --/* Include pac common sof detection functions */ --#include "pac_common.h" -+/* !! coarse_grained_expo_autogain is not used !! */ -+#define exp_too_low_cnt flags -+#define exp_too_high_cnt sof_read -+#include "autogain_functions.h" - - static void do_autogain(struct gspca_dev *gspca_dev) - { -@@ -761,65 +741,44 @@ static void do_autogain(struct gspca_dev - int desired_lum; - const int deadzone = 30; - -- if (avg_lum == -1) -+ if (sd->autogain_ignore_frames < 0) - return; - -- desired_lum = 270 + sd->brightness; -- -- if (sd->autogain_ignore_frames > 0) -+ if (sd->autogain_ignore_frames > 0) { - sd->autogain_ignore_frames--; -- else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum, -- deadzone, GAIN_KNEE, EXPOSURE_KNEE)) -+ } else { -+ desired_lum = 270 + sd->ctrls[BRIGHTNESS].val; -+ -+ auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum, -+ deadzone, GAIN_KNEE, EXPOSURE_KNEE); - sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; -+ } - } - --/* JPEG header, part 1 */ --static const unsigned char pac_jpeg_header1[] = { -- 0xff, 0xd8, /* SOI: Start of Image */ -- -- 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ -- 0x00, 0x11, /* length = 17 bytes (including this length field) */ -- 0x08 /* Precision: 8 */ -- /* 2 bytes is placed here: number of image lines */ -- /* 2 bytes is placed here: samples per line */ --}; -- --/* JPEG header, continued */ --static const unsigned char pac_jpeg_header2[] = { -- 0x03, /* Number of image components: 3 */ -- 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ -- 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ -- 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ -- -- 0xff, 0xda, /* SOS: Start Of Scan */ -- 0x00, 0x0c, /* length = 12 bytes (including this length field) */ -- 0x03, /* number of components: 3 */ -- 0x01, 0x00, /* selector 1, table 0x00 */ -- 0x02, 0x11, /* selector 2, table 0x11 */ -- 0x03, 0x11, /* selector 3, table 0x11 */ -- 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ -- 0x00 /* Successive approximation: 0 */ -+/* JPEG header */ -+static const u8 jpeg_header[] = { -+ 0xff, 0xd8, /* SOI: Start of Image */ -+ -+ 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ -+ 0x00, 0x11, /* length = 17 bytes (including this length field) */ -+ 0x08, /* Precision: 8 */ -+ 0x02, 0x80, /* height = 640 (image rotated) */ -+ 0x01, 0xe0, /* width = 480 */ -+ 0x03, /* Number of image components: 3 */ -+ 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ -+ 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ -+ 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ -+ -+ 0xff, 0xda, /* SOS: Start Of Scan */ -+ 0x00, 0x0c, /* length = 12 bytes (including this length field) */ -+ 0x03, /* number of components: 3 */ -+ 0x01, 0x00, /* selector 1, table 0x00 */ -+ 0x02, 0x11, /* selector 2, table 0x11 */ -+ 0x03, 0x11, /* selector 3, table 0x11 */ -+ 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ -+ 0x00 /* Successive approximation: 0 */ - }; - --static void pac_start_frame(struct gspca_dev *gspca_dev, -- __u16 lines, __u16 samples_per_line) --{ -- unsigned char tmpbuf[4]; -- -- gspca_frame_add(gspca_dev, FIRST_PACKET, -- pac_jpeg_header1, sizeof(pac_jpeg_header1)); -- -- tmpbuf[0] = lines >> 8; -- tmpbuf[1] = lines & 0xff; -- tmpbuf[2] = samples_per_line >> 8; -- tmpbuf[3] = samples_per_line & 0xff; -- -- gspca_frame_add(gspca_dev, INTER_PACKET, -- tmpbuf, sizeof(tmpbuf)); -- gspca_frame_add(gspca_dev, INTER_PACKET, -- pac_jpeg_header2, sizeof(pac_jpeg_header2)); --} -- - /* this function is run at interrupt level */ - static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ -@@ -827,7 +786,7 @@ static void sd_pkt_scan(struct gspca_dev - { - struct sd *sd = (struct sd *) gspca_dev; - u8 *image; -- unsigned char *sof; -+ u8 *sof; - - sof = pac_find_sof(&sd->sof_read, data, len); - if (sof) { -@@ -864,234 +823,21 @@ static void sd_pkt_scan(struct gspca_dev - n >= lum_offset) - atomic_set(&sd->avg_lum, data[-lum_offset] + - data[-lum_offset + 1]); -- else -- atomic_set(&sd->avg_lum, -1); - - /* Start the new frame with the jpeg header */ - /* The PAC7302 has the image rotated 90 degrees */ -- pac_start_frame(gspca_dev, -- gspca_dev->width, gspca_dev->height); -+ gspca_frame_add(gspca_dev, FIRST_PACKET, -+ jpeg_header, sizeof jpeg_header); - } - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); - } - --static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->brightness = val; -- if (gspca_dev->streaming) -- setbrightcont(gspca_dev); -- return gspca_dev->usb_err; --} -- --static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- *val = sd->brightness; -- return 0; --} -- --static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->contrast = val; -- if (gspca_dev->streaming) -- setbrightcont(gspca_dev); -- return gspca_dev->usb_err; --} -- --static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- *val = sd->contrast; -- return 0; --} -- --static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->colors = val; -- if (gspca_dev->streaming) -- setcolors(gspca_dev); -- return gspca_dev->usb_err; --} -- --static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- *val = sd->colors; -- return 0; --} -- --static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->white_balance = val; -- if (gspca_dev->streaming) -- setwhitebalance(gspca_dev); -- return gspca_dev->usb_err; --} -- --static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- *val = sd->white_balance; -- return 0; --} -- --static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->red_balance = val; -- if (gspca_dev->streaming) -- setredbalance(gspca_dev); -- return gspca_dev->usb_err; --} -- --static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- *val = sd->red_balance; -- return 0; --} -- --static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->blue_balance = val; -- if (gspca_dev->streaming) -- setbluebalance(gspca_dev); -- return gspca_dev->usb_err; --} -- --static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- *val = sd->blue_balance; -- return 0; --} -- --static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->gain = val; -- if (gspca_dev->streaming) -- setgain(gspca_dev); -- return gspca_dev->usb_err; --} -- --static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- *val = sd->gain; -- return 0; --} -- --static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->exposure = val; -- if (gspca_dev->streaming) -- setexposure(gspca_dev); -- return gspca_dev->usb_err; --} -- --static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- *val = sd->exposure; -- return 0; --} -- --static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->autogain = val; -- /* when switching to autogain set defaults to make sure -- we are on a valid point of the autogain gain / -- exposure knee graph, and give this change time to -- take effect before doing autogain. */ -- if (sd->autogain) { -- sd->exposure = EXPOSURE_DEF; -- sd->gain = GAIN_DEF; -- if (gspca_dev->streaming) { -- sd->autogain_ignore_frames = -- PAC_AUTOGAIN_IGNORE_FRAMES; -- setexposure(gspca_dev); -- setgain(gspca_dev); -- } -- } -- -- return gspca_dev->usb_err; --} -- --static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- *val = sd->autogain; -- return 0; --} -- --static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->hflip = val; -- if (gspca_dev->streaming) -- sethvflip(gspca_dev); -- return gspca_dev->usb_err; --} -- --static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- *val = sd->hflip; -- return 0; --} -- --static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->vflip = val; -- if (gspca_dev->streaming) -- sethvflip(gspca_dev); -- return gspca_dev->usb_err; --} -- --static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- *val = sd->vflip; -- return 0; --} -- - #ifdef CONFIG_VIDEO_ADV_DEBUG - static int sd_dbg_s_register(struct gspca_dev *gspca_dev, - struct v4l2_dbg_register *reg) - { -- __u8 index; -- __u8 value; -+ u8 index; -+ u8 value; - - /* reg->reg: bit0..15: reserved for register index (wIndex is 16bit - long on the USB bus) -@@ -1103,8 +849,8 @@ static int sd_dbg_s_register(struct gspc - ) { - /* Currently writing to page 0 is only supported. */ - /* reg_w() only supports 8bit index */ -- index = reg->reg & 0x000000ff; -- value = reg->val & 0x000000ff; -+ index = reg->reg; -+ value = reg->val; - - /* Note that there shall be no access to other page - by any other function between the page swith and -@@ -1165,7 +911,7 @@ static int sd_int_pkt_scan(struct gspca_ - - /* sub-driver description for pac7302 */ - static const struct sd_desc sd_desc = { -- .name = MODULE_NAME, -+ .name = KBUILD_MODNAME, - .ctrls = sd_ctrls, - .nctrls = ARRAY_SIZE(sd_ctrls), - .config = sd_config, -@@ -1187,6 +933,7 @@ static const struct sd_desc sd_desc = { - /* -- module initialisation -- */ - static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x06f8, 0x3009)}, -+ {USB_DEVICE(0x06f8, 0x301b)}, - {USB_DEVICE(0x093a, 0x2620)}, - {USB_DEVICE(0x093a, 0x2621)}, - {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP}, -@@ -1211,7 +958,7 @@ static int sd_probe(struct usb_interface - } - - static struct usb_driver sd_driver = { -- .name = MODULE_NAME, -+ .name = KBUILD_MODNAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -Index: linux-3.3.x86_64/drivers/media/video/gspca/sonixj.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/gspca/sonixj.c -+++ linux-3.3.x86_64/drivers/media/video/gspca/sonixj.c -@@ -39,7 +39,9 @@ enum e_ctrl { - BLUE, - RED, - GAMMA, -+ EXPOSURE, - AUTOGAIN, -+ GAIN, - HFLIP, - VFLIP, - SHARPNESS, -@@ -131,7 +133,9 @@ static void setcontrast(struct gspca_dev - static void setcolors(struct gspca_dev *gspca_dev); - static void setredblue(struct gspca_dev *gspca_dev); - static void setgamma(struct gspca_dev *gspca_dev); --static void setautogain(struct gspca_dev *gspca_dev); -+static void setexposure(struct gspca_dev *gspca_dev); -+static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); -+static void setgain(struct gspca_dev *gspca_dev); - static void sethvflip(struct gspca_dev *gspca_dev); - static void setsharpness(struct gspca_dev *gspca_dev); - static void setillum(struct gspca_dev *gspca_dev); -@@ -213,6 +217,18 @@ static const struct ctrl sd_ctrls[NCTRLS - }, - .set_control = setgamma - }, -+[EXPOSURE] = { -+ { -+ .id = V4L2_CID_EXPOSURE, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "Exposure", -+ .minimum = 500, -+ .maximum = 1500, -+ .step = 1, -+ .default_value = 1024 -+ }, -+ .set_control = setexposure -+ }, - [AUTOGAIN] = { - { - .id = V4L2_CID_AUTOGAIN, -@@ -223,7 +239,19 @@ static const struct ctrl sd_ctrls[NCTRLS - .step = 1, - .default_value = 1 - }, -- .set_control = setautogain -+ .set = sd_setautogain, -+ }, -+[GAIN] = { -+ { -+ .id = V4L2_CID_GAIN, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "Gain", -+ .minimum = 4, -+ .maximum = 49, -+ .step = 1, -+ .default_value = 15 -+ }, -+ .set_control = setgain - }, - [HFLIP] = { - { -@@ -290,60 +318,87 @@ static const struct ctrl sd_ctrls[NCTRLS - - /* table of the disabled controls */ - static const __u32 ctrl_dis[] = { --[SENSOR_ADCM1700] = (1 << AUTOGAIN) | -+[SENSOR_ADCM1700] = (1 << EXPOSURE) | -+ (1 << AUTOGAIN) | -+ (1 << GAIN) | - (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - --[SENSOR_GC0307] = (1 << HFLIP) | -+[SENSOR_GC0307] = (1 << EXPOSURE) | -+ (1 << GAIN) | -+ (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - --[SENSOR_HV7131R] = (1 << HFLIP) | -+[SENSOR_HV7131R] = (1 << EXPOSURE) | -+ (1 << GAIN) | -+ (1 << HFLIP) | - (1 << FREQ), - --[SENSOR_MI0360] = (1 << HFLIP) | -+[SENSOR_MI0360] = (1 << EXPOSURE) | -+ (1 << GAIN) | -+ (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - --[SENSOR_MI0360B] = (1 << HFLIP) | -+[SENSOR_MI0360B] = (1 << EXPOSURE) | -+ (1 << GAIN) | -+ (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - --[SENSOR_MO4000] = (1 << HFLIP) | -+[SENSOR_MO4000] = (1 << EXPOSURE) | -+ (1 << GAIN) | -+ (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - --[SENSOR_MT9V111] = (1 << HFLIP) | -+[SENSOR_MT9V111] = (1 << EXPOSURE) | -+ (1 << GAIN) | -+ (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - --[SENSOR_OM6802] = (1 << HFLIP) | -+[SENSOR_OM6802] = (1 << EXPOSURE) | -+ (1 << GAIN) | -+ (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - --[SENSOR_OV7630] = (1 << HFLIP), -- --[SENSOR_OV7648] = (1 << HFLIP), -- --[SENSOR_OV7660] = (1 << AUTOGAIN) | -+[SENSOR_OV7630] = (1 << EXPOSURE) | -+ (1 << GAIN) | -+ (1 << HFLIP), -+ -+[SENSOR_OV7648] = (1 << EXPOSURE) | -+ (1 << GAIN) | -+ (1 << HFLIP), -+ -+[SENSOR_OV7660] = (1 << EXPOSURE) | -+ (1 << AUTOGAIN) | -+ (1 << GAIN) | - (1 << HFLIP) | - (1 << VFLIP), - --[SENSOR_PO1030] = (1 << AUTOGAIN) | -+[SENSOR_PO1030] = (1 << EXPOSURE) | -+ (1 << AUTOGAIN) | -+ (1 << GAIN) | - (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - --[SENSOR_PO2030N] = (1 << AUTOGAIN) | -- (1 << FREQ), -+[SENSOR_PO2030N] = (1 << FREQ), - --[SENSOR_SOI768] = (1 << AUTOGAIN) | -+[SENSOR_SOI768] = (1 << EXPOSURE) | -+ (1 << AUTOGAIN) | -+ (1 << GAIN) | - (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - --[SENSOR_SP80708] = (1 << AUTOGAIN) | -+[SENSOR_SP80708] = (1 << EXPOSURE) | -+ (1 << AUTOGAIN) | -+ (1 << GAIN) | - (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), -@@ -1242,14 +1297,6 @@ static const u8 po2030n_sensor_param1[][ - {0xa1, 0x6e, 0x05, 0x6f, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10}, -- {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, -- {0xc1, 0x6e, 0x16, 0x52, 0x40, 0x48, 0x00, 0x10}, --/*after start*/ -- {0xa1, 0x6e, 0x15, 0x0f, 0x00, 0x00, 0x00, 0x10}, -- {DELAY, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */ -- {0xa1, 0x6e, 0x1a, 0x05, 0x00, 0x00, 0x00, 0x10}, -- {DELAY, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */ -- {0xa1, 0x6e, 0x1b, 0x53, 0x00, 0x00, 0x00, 0x10}, - {} - }; - -@@ -1858,7 +1905,7 @@ static int sd_init(struct gspca_dev *gsp - return gspca_dev->usb_err; - } - --static u32 setexposure(struct gspca_dev *gspca_dev, -+static u32 expo_adjust(struct gspca_dev *gspca_dev, - u32 expo) - { - struct sd *sd = (struct sd *) gspca_dev; -@@ -1982,28 +2029,28 @@ static void setbrightness(struct gspca_d - expo = 0x002dc6c0; - else if (expo < 0x02a0) - expo = 0x02a0; -- sd->exposure = setexposure(gspca_dev, expo); -+ sd->exposure = expo_adjust(gspca_dev, expo); - break; - case SENSOR_MI0360: - case SENSOR_MO4000: - expo = brightness << 4; -- sd->exposure = setexposure(gspca_dev, expo); -+ sd->exposure = expo_adjust(gspca_dev, expo); - break; - case SENSOR_MI0360B: - expo = brightness << 2; -- sd->exposure = setexposure(gspca_dev, expo); -+ sd->exposure = expo_adjust(gspca_dev, expo); - break; - case SENSOR_GC0307: - expo = brightness; -- sd->exposure = setexposure(gspca_dev, expo); -+ sd->exposure = expo_adjust(gspca_dev, expo); - return; /* don't set the Y offset */ - case SENSOR_MT9V111: - expo = brightness << 2; -- sd->exposure = setexposure(gspca_dev, expo); -+ sd->exposure = expo_adjust(gspca_dev, expo); - return; /* don't set the Y offset */ - case SENSOR_OM6802: - expo = brightness << 2; -- sd->exposure = setexposure(gspca_dev, expo); -+ sd->exposure = expo_adjust(gspca_dev, expo); - return; /* Y offset already set */ - } - -@@ -2112,6 +2159,23 @@ static void setgamma(struct gspca_dev *g - reg_w(gspca_dev, 0x20, gamma, sizeof gamma); - } - -+static void setexposure(struct gspca_dev *gspca_dev) -+{ -+ struct sd *sd = (struct sd *) gspca_dev; -+ -+ if (sd->sensor == SENSOR_PO2030N) { -+ u8 rexpo[] = /* 1a: expo H, 1b: expo M */ -+ {0xa1, 0x6e, 0x1a, 0x00, 0x40, 0x00, 0x00, 0x10}; -+ -+ rexpo[3] = sd->ctrls[EXPOSURE].val >> 8; -+ i2c_w8(gspca_dev, rexpo); -+ msleep(6); -+ rexpo[2] = 0x1b; -+ rexpo[3] = sd->ctrls[EXPOSURE].val; -+ i2c_w8(gspca_dev, rexpo); -+ } -+} -+ - static void setautogain(struct gspca_dev *gspca_dev) - { - struct sd *sd = (struct sd *) gspca_dev; -@@ -2139,6 +2203,19 @@ static void setautogain(struct gspca_dev - sd->ag_cnt = -1; - } - -+static void setgain(struct gspca_dev *gspca_dev) -+{ -+ struct sd *sd = (struct sd *) gspca_dev; -+ -+ if (sd->sensor == SENSOR_PO2030N) { -+ u8 rgain[] = /* 15: gain */ -+ {0xa1, 0x6e, 0x15, 0x00, 0x40, 0x00, 0x00, 0x15}; -+ -+ rgain[3] = sd->ctrls[GAIN].val; -+ i2c_w8(gspca_dev, rgain); -+ } -+} -+ - static void sethvflip(struct gspca_dev *gspca_dev) - { - struct sd *sd = (struct sd *) gspca_dev; -@@ -2623,6 +2700,10 @@ static int sd_start(struct gspca_dev *gs - setcontrast(gspca_dev); - setcolors(gspca_dev); - setautogain(gspca_dev); -+ if (!(gspca_dev->ctrl_inac & ((1 << EXPOSURE) | (1 << GAIN)))) { -+ setexposure(gspca_dev); -+ setgain(gspca_dev); -+ } - setfreq(gspca_dev); - - sd->pktsz = sd->npkt = 0; -@@ -2719,6 +2800,12 @@ static void sd_stop0(struct gspca_dev *g - } - } - -+/* !! coarse_grained_expo_autogain is not used !! */ -+#define exp_too_low_cnt bridge -+#define exp_too_high_cnt sensor -+ -+#include "autogain_functions.h" -+ - static void do_autogain(struct gspca_dev *gspca_dev) - { - struct sd *sd = (struct sd *) gspca_dev; -@@ -2736,6 +2823,13 @@ static void do_autogain(struct gspca_dev - - delta = atomic_read(&sd->avg_lum); - PDEBUG(D_FRAM, "mean lum %d", delta); -+ -+ if (sd->sensor == SENSOR_PO2030N) { -+ auto_gain_n_exposure(gspca_dev, delta, luma_mean, luma_delta, -+ 15, 1024); -+ return; -+ } -+ - if (delta < luma_mean - luma_delta || - delta > luma_mean + luma_delta) { - switch (sd->sensor) { -@@ -2744,7 +2838,7 @@ static void do_autogain(struct gspca_dev - expotimes += (luma_mean - delta) >> 6; - if (expotimes < 0) - expotimes = 0; -- sd->exposure = setexposure(gspca_dev, -+ sd->exposure = expo_adjust(gspca_dev, - (unsigned int) expotimes); - break; - case SENSOR_HV7131R: -@@ -2752,7 +2846,7 @@ static void do_autogain(struct gspca_dev - expotimes += (luma_mean - delta) >> 4; - if (expotimes < 0) - expotimes = 0; -- sd->exposure = setexposure(gspca_dev, -+ sd->exposure = expo_adjust(gspca_dev, - (unsigned int) (expotimes << 8)); - break; - case SENSOR_OM6802: -@@ -2761,7 +2855,7 @@ static void do_autogain(struct gspca_dev - expotimes += (luma_mean - delta) >> 2; - if (expotimes < 0) - expotimes = 0; -- sd->exposure = setexposure(gspca_dev, -+ sd->exposure = expo_adjust(gspca_dev, - (unsigned int) expotimes); - setredblue(gspca_dev); - break; -@@ -2773,7 +2867,7 @@ static void do_autogain(struct gspca_dev - expotimes += (luma_mean - delta) >> 6; - if (expotimes < 0) - expotimes = 0; -- sd->exposure = setexposure(gspca_dev, -+ sd->exposure = expo_adjust(gspca_dev, - (unsigned int) expotimes); - setredblue(gspca_dev); - break; -@@ -2948,16 +3042,18 @@ marker_found: - } - } - --static int sd_get_jcomp(struct gspca_dev *gspca_dev, -- struct v4l2_jpegcompression *jcomp) -+static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) - { - struct sd *sd = (struct sd *) gspca_dev; - -- memset(jcomp, 0, sizeof *jcomp); -- jcomp->quality = sd->quality; -- jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT -- | V4L2_JPEG_MARKER_DQT; -- return 0; -+ sd->ctrls[AUTOGAIN].val = val; -+ if (val) -+ gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN); -+ else -+ gspca_dev->ctrl_inac &= ~(1 << EXPOSURE) & ~(1 << GAIN); -+ if (gspca_dev->streaming) -+ setautogain(gspca_dev); -+ return gspca_dev->usb_err; - } - - static int sd_querymenu(struct gspca_dev *gspca_dev, -@@ -3012,7 +3108,6 @@ static const struct sd_desc sd_desc = { - .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, - .dq_callback = do_autogain, -- .get_jcomp = sd_get_jcomp, - .querymenu = sd_querymenu, - #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .int_pkt_scan = sd_int_pkt_scan, -Index: linux-3.3.x86_64/drivers/media/video/gspca/zc3xx.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/gspca/zc3xx.c -+++ linux-3.3.x86_64/drivers/media/video/gspca/zc3xx.c -@@ -1,7 +1,7 @@ - /* -- * Z-Star/Vimicro zc301/zc302p/vc30x library -+ * Z-Star/Vimicro zc301/zc302p/vc30x driver - * -- * Copyright (C) 2009-2011 Jean-Francois Moine -+ * Copyright (C) 2009-2012 Jean-Francois Moine - * Copyright (C) 2004 2005 2006 Michel Xhaard mxhaard@magic.fr - * - * This program is free software; you can redistribute it and/or modify -@@ -21,8 +21,6 @@ - - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - --#define MODULE_NAME "zc3xx" -- - #include - #include "gspca.h" - #include "jpeg.h" -@@ -34,7 +32,7 @@ MODULE_LICENSE("GPL"); - - static int force_sensor = -1; - --#define QUANT_VAL 1 /* quantization table */ -+#define REG08_DEF 3 /* default JPEG compression (70%) */ - #include "zc3xx-reg.h" - - /* controls */ -@@ -46,6 +44,7 @@ enum e_ctrl { - AUTOGAIN, - LIGHTFREQ, - SHARPNESS, -+ QUALITY, - NCTRLS /* number of controls */ - }; - -@@ -57,10 +56,10 @@ struct sd { - - struct gspca_ctrl ctrls[NCTRLS]; - -- u8 quality; /* image quality */ --#define QUALITY_MIN 50 --#define QUALITY_MAX 80 --#define QUALITY_DEF 70 -+ struct work_struct work; -+ struct workqueue_struct *work_thread; -+ -+ u8 reg08; /* webcam compression quality */ - - u8 bridge; - u8 sensor; /* Type of image sensor chip */ -@@ -101,6 +100,7 @@ static void setexposure(struct gspca_dev - static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); - static void setlightfreq(struct gspca_dev *gspca_dev); - static void setsharpness(struct gspca_dev *gspca_dev); -+static int sd_setquality(struct gspca_dev *gspca_dev, __s32 val); - - static const struct ctrl sd_ctrls[NCTRLS] = { - [BRIGHTNESS] = { -@@ -188,6 +188,18 @@ static const struct ctrl sd_ctrls[NCTRLS - }, - .set_control = setsharpness - }, -+[QUALITY] = { -+ { -+ .id = V4L2_CID_JPEG_COMPRESSION_QUALITY, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "Compression Quality", -+ .minimum = 40, -+ .maximum = 70, -+ .step = 1, -+ .default_value = 70 /* updated in sd_init() */ -+ }, -+ .set = sd_setquality -+ }, - }; - - static const struct v4l2_pix_format vga_mode[] = { -@@ -229,6 +241,9 @@ static const struct v4l2_pix_format sif_ - .priv = 0}, - }; - -+/* bridge reg08 -> JPEG quality conversion table */ -+static u8 jpeg_qual[] = {40, 50, 60, 70, /*80*/}; -+ - /* usb exchanges */ - struct usb_action { - u8 req; -@@ -3894,7 +3909,6 @@ static const struct usb_action pas106b_I - /* Gains */ - {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, -- {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - /* Auto correction */ - {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, -@@ -5640,7 +5654,7 @@ static const struct usb_action gc0303_No - {} - }; - --static u8 reg_r_i(struct gspca_dev *gspca_dev, -+static u8 reg_r(struct gspca_dev *gspca_dev, - u16 index) - { - int ret; -@@ -5655,24 +5669,14 @@ static u8 reg_r_i(struct gspca_dev *gspc - index, gspca_dev->usb_buf, 1, - 500); - if (ret < 0) { -- pr_err("reg_r_i err %d\n", ret); -+ pr_err("reg_r err %d\n", ret); - gspca_dev->usb_err = ret; - return 0; - } - return gspca_dev->usb_buf[0]; - } - --static u8 reg_r(struct gspca_dev *gspca_dev, -- u16 index) --{ -- u8 ret; -- -- ret = reg_r_i(gspca_dev, index); -- PDEBUG(D_USBI, "reg r [%04x] -> %02x", index, ret); -- return ret; --} -- --static void reg_w_i(struct gspca_dev *gspca_dev, -+static void reg_w(struct gspca_dev *gspca_dev, - u8 value, - u16 index) - { -@@ -5692,14 +5696,6 @@ static void reg_w_i(struct gspca_dev *gs - } - } - --static void reg_w(struct gspca_dev *gspca_dev, -- u8 value, -- u16 index) --{ -- PDEBUG(D_USBO, "reg w [%04x] = %02x", index, value); -- reg_w_i(gspca_dev, value, index); --} -- - static u16 i2c_read(struct gspca_dev *gspca_dev, - u8 reg) - { -@@ -5708,16 +5704,14 @@ static u16 i2c_read(struct gspca_dev *gs - - if (gspca_dev->usb_err < 0) - return 0; -- reg_w_i(gspca_dev, reg, 0x0092); -- reg_w_i(gspca_dev, 0x02, 0x0090); /* <- read command */ -+ reg_w(gspca_dev, reg, 0x0092); -+ reg_w(gspca_dev, 0x02, 0x0090); /* <- read command */ - msleep(20); -- retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ -+ retbyte = reg_r(gspca_dev, 0x0091); /* read status */ - if (retbyte != 0x00) - pr_err("i2c_r status error %02x\n", retbyte); -- retval = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */ -- retval |= reg_r_i(gspca_dev, 0x0096) << 8; /* read Hightbyte */ -- PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)", -- reg, retval, retbyte); -+ retval = reg_r(gspca_dev, 0x0095); /* read Lowbyte */ -+ retval |= reg_r(gspca_dev, 0x0096) << 8; /* read Hightbyte */ - return retval; - } - -@@ -5730,16 +5724,14 @@ static u8 i2c_write(struct gspca_dev *gs - - if (gspca_dev->usb_err < 0) - return 0; -- reg_w_i(gspca_dev, reg, 0x92); -- reg_w_i(gspca_dev, valL, 0x93); -- reg_w_i(gspca_dev, valH, 0x94); -- reg_w_i(gspca_dev, 0x01, 0x90); /* <- write command */ -+ reg_w(gspca_dev, reg, 0x92); -+ reg_w(gspca_dev, valL, 0x93); -+ reg_w(gspca_dev, valH, 0x94); -+ reg_w(gspca_dev, 0x01, 0x90); /* <- write command */ - msleep(1); -- retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ -+ retbyte = reg_r(gspca_dev, 0x0091); /* read status */ - if (retbyte != 0x00) - pr_err("i2c_w status error %02x\n", retbyte); -- PDEBUG(D_USBO, "i2c w [%02x] = %02x%02x (%02x)", -- reg, valH, valL, retbyte); - return retbyte; - } - -@@ -5906,6 +5898,8 @@ static void getexposure(struct gspca_dev - { - struct sd *sd = (struct sd *) gspca_dev; - -+ if (sd->sensor != SENSOR_HV7131R) -+ return; - sd->ctrls[EXPOSURE].val = (i2c_read(gspca_dev, 0x25) << 9) - | (i2c_read(gspca_dev, 0x26) << 1) - | (i2c_read(gspca_dev, 0x27) >> 7); -@@ -5916,6 +5910,8 @@ static void setexposure(struct gspca_dev - struct sd *sd = (struct sd *) gspca_dev; - int val; - -+ if (sd->sensor != SENSOR_HV7131R) -+ return; - val = sd->ctrls[EXPOSURE].val; - i2c_write(gspca_dev, 0x25, val >> 9, 0x00); - i2c_write(gspca_dev, 0x26, val >> 1, 0x00); -@@ -5925,32 +5921,20 @@ static void setexposure(struct gspca_dev - static void setquality(struct gspca_dev *gspca_dev) - { - struct sd *sd = (struct sd *) gspca_dev; -- u8 frxt; -+ s8 reg07; - -+ reg07 = 0; - switch (sd->sensor) { -- case SENSOR_ADCM2700: -- case SENSOR_GC0305: -- case SENSOR_HV7131B: -- case SENSOR_HV7131R: - case SENSOR_OV7620: -+ reg07 = 0x30; -+ break; -+ case SENSOR_HV7131R: - case SENSOR_PAS202B: -- case SENSOR_PO2030: -- return; -+ return; /* done by work queue */ - } --/*fixme: is it really 0008 0007 0018 for all other sensors? */ -- reg_w(gspca_dev, QUANT_VAL, 0x0008); -- frxt = 0x30; -- reg_w(gspca_dev, frxt, 0x0007); --#if QUANT_VAL == 0 || QUANT_VAL == 1 || QUANT_VAL == 2 -- frxt = 0xff; --#elif QUANT_VAL == 3 -- frxt = 0xf0; --#elif QUANT_VAL == 4 -- frxt = 0xe0; --#else -- frxt = 0x20; --#endif -- reg_w(gspca_dev, frxt, 0x0018); -+ reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING); -+ if (reg07 != 0) -+ reg_w(gspca_dev, reg07, 0x0007); - } - - /* Matches the sensor's internal frame rate to the lighting frequency. -@@ -6084,6 +6068,115 @@ static void setautogain(struct gspca_dev - reg_w(gspca_dev, autoval, 0x0180); - } - -+/* update the transfer parameters */ -+/* This function is executed from a work queue. */ -+/* The exact use of the bridge registers 07 and 08 is not known. -+ * The following algorithm has been adapted from ms-win traces */ -+static void transfer_update(struct work_struct *work) -+{ -+ struct sd *sd = container_of(work, struct sd, work); -+ struct gspca_dev *gspca_dev = &sd->gspca_dev; -+ int change, good; -+ u8 reg07, reg11; -+ -+ /* synchronize with the main driver and initialize the registers */ -+ mutex_lock(&gspca_dev->usb_lock); -+ reg07 = 0; /* max */ -+ reg_w(gspca_dev, reg07, 0x0007); -+ reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING); -+ mutex_unlock(&gspca_dev->usb_lock); -+ -+ good = 0; -+ for (;;) { -+ msleep(100); -+ -+ /* get the transfer status */ -+ /* the bit 0 of the bridge register 11 indicates overflow */ -+ mutex_lock(&gspca_dev->usb_lock); -+ if (!gspca_dev->present || !gspca_dev->streaming) -+ goto err; -+ reg11 = reg_r(gspca_dev, 0x0011); -+ if (gspca_dev->usb_err < 0 -+ || !gspca_dev->present || !gspca_dev->streaming) -+ goto err; -+ -+ change = reg11 & 0x01; -+ if (change) { /* overflow */ -+ switch (reg07) { -+ case 0: /* max */ -+ reg07 = sd->sensor == SENSOR_HV7131R -+ ? 0x30 : 0x32; -+ if (sd->reg08 != 0) { -+ change = 3; -+ sd->reg08--; -+ } -+ break; -+ case 0x32: -+ reg07 -= 4; -+ break; -+ default: -+ reg07 -= 2; -+ break; -+ case 2: -+ change = 0; /* already min */ -+ break; -+ } -+ good = 0; -+ } else { /* no overflow */ -+ if (reg07 != 0) { /* if not max */ -+ good++; -+ if (good >= 10) { -+ good = 0; -+ change = 1; -+ reg07 += 2; -+ switch (reg07) { -+ case 0x30: -+ if (sd->sensor == SENSOR_PAS202B) -+ reg07 += 2; -+ break; -+ case 0x32: -+ case 0x34: -+ reg07 = 0; -+ break; -+ } -+ } -+ } else { /* reg07 max */ -+ if (sd->reg08 < sizeof jpeg_qual - 1) { -+ good++; -+ if (good > 10) { -+ sd->reg08++; -+ change = 2; -+ } -+ } -+ } -+ } -+ if (change) { -+ if (change & 1) { -+ reg_w(gspca_dev, reg07, 0x0007); -+ if (gspca_dev->usb_err < 0 -+ || !gspca_dev->present -+ || !gspca_dev->streaming) -+ goto err; -+ } -+ if (change & 2) { -+ reg_w(gspca_dev, sd->reg08, -+ ZC3XX_R008_CLOCKSETTING); -+ if (gspca_dev->usb_err < 0 -+ || !gspca_dev->present -+ || !gspca_dev->streaming) -+ goto err; -+ sd->ctrls[QUALITY].val = jpeg_qual[sd->reg08]; -+ jpeg_set_qual(sd->jpeg_hdr, -+ jpeg_qual[sd->reg08]); -+ } -+ } -+ mutex_unlock(&gspca_dev->usb_lock); -+ } -+ return; -+err: -+ mutex_unlock(&gspca_dev->usb_lock); -+} -+ - static void send_unknown(struct gspca_dev *gspca_dev, int sensor) - { - reg_w(gspca_dev, 0x01, 0x0000); /* bridge reset */ -@@ -6411,7 +6504,9 @@ static int sd_config(struct gspca_dev *g - sd->sensor = id->driver_info; - - gspca_dev->cam.ctrls = sd->ctrls; -- sd->quality = QUALITY_DEF; -+ sd->reg08 = REG08_DEF; -+ -+ INIT_WORK(&sd->work, transfer_update); - - return 0; - } -@@ -6464,6 +6559,27 @@ static int sd_init(struct gspca_dev *gsp - [SENSOR_PO2030] = 1, - [SENSOR_TAS5130C] = 1, - }; -+ static const u8 reg08_tb[SENSOR_MAX] = { -+ [SENSOR_ADCM2700] = 1, -+ [SENSOR_CS2102] = 3, -+ [SENSOR_CS2102K] = 3, -+ [SENSOR_GC0303] = 2, -+ [SENSOR_GC0305] = 3, -+ [SENSOR_HDCS2020] = 1, -+ [SENSOR_HV7131B] = 3, -+ [SENSOR_HV7131R] = 3, -+ [SENSOR_ICM105A] = 3, -+ [SENSOR_MC501CB] = 3, -+ [SENSOR_MT9V111_1] = 3, -+ [SENSOR_MT9V111_3] = 3, -+ [SENSOR_OV7620] = 1, -+ [SENSOR_OV7630C] = 3, -+ [SENSOR_PAS106] = 3, -+ [SENSOR_PAS202B] = 3, -+ [SENSOR_PB0330] = 3, -+ [SENSOR_PO2030] = 2, -+ [SENSOR_TAS5130C] = 3, -+ }; - - sensor = zcxx_probeSensor(gspca_dev); - if (sensor >= 0) -@@ -6528,7 +6644,6 @@ static int sd_init(struct gspca_dev *gsp - case 0x0e: - PDEBUG(D_PROBE, "Find Sensor PAS202B"); - sd->sensor = SENSOR_PAS202B; --/* sd->sharpness = 1; */ - break; - case 0x0f: - PDEBUG(D_PROBE, "Find Sensor PAS106"); -@@ -6616,13 +6731,21 @@ static int sd_init(struct gspca_dev *gsp - } - - sd->ctrls[GAMMA].def = gamma[sd->sensor]; -+ sd->reg08 = reg08_tb[sd->sensor]; -+ sd->ctrls[QUALITY].def = jpeg_qual[sd->reg08]; -+ sd->ctrls[QUALITY].min = jpeg_qual[0]; -+ sd->ctrls[QUALITY].max = jpeg_qual[ARRAY_SIZE(jpeg_qual) - 1]; - - switch (sd->sensor) { - case SENSOR_HV7131R: -+ gspca_dev->ctrl_dis = (1 << QUALITY); - break; - case SENSOR_OV7630C: - gspca_dev->ctrl_dis = (1 << LIGHTFREQ) | (1 << EXPOSURE); - break; -+ case SENSOR_PAS202B: -+ gspca_dev->ctrl_dis = (1 << QUALITY) | (1 << EXPOSURE); -+ break; - default: - gspca_dev->ctrl_dis = (1 << EXPOSURE); - break; -@@ -6685,7 +6808,6 @@ static int sd_start(struct gspca_dev *gs - /* create the JPEG header */ - jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, - 0x21); /* JPEG 422 */ -- jpeg_set_qual(sd->jpeg_hdr, sd->quality); - - mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - switch (sd->sensor) { -@@ -6761,10 +6883,9 @@ static int sd_start(struct gspca_dev *gs - reg_r(gspca_dev, 0x0180); /* from win */ - reg_w(gspca_dev, 0x00, 0x0180); - break; -- default: -- setquality(gspca_dev); -- break; - } -+ setquality(gspca_dev); -+ jpeg_set_qual(sd->jpeg_hdr, jpeg_qual[sd->reg08]); - setlightfreq(gspca_dev); - - switch (sd->sensor) { -@@ -6776,8 +6897,7 @@ static int sd_start(struct gspca_dev *gs - reg_w(gspca_dev, 0x40, 0x0117); - break; - case SENSOR_HV7131R: -- if (!sd->ctrls[AUTOGAIN].val) -- setexposure(gspca_dev); -+ setexposure(gspca_dev); - reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN); - break; - case SENSOR_GC0305: -@@ -6802,13 +6922,19 @@ static int sd_start(struct gspca_dev *gs - } - - setautogain(gspca_dev); -- switch (sd->sensor) { -- case SENSOR_PO2030: -- msleep(50); -- reg_w(gspca_dev, 0x00, 0x0007); /* (from win traces) */ -- reg_w(gspca_dev, 0x02, ZC3XX_R008_CLOCKSETTING); -- break; -+ -+ /* start the transfer update thread if needed */ -+ if (gspca_dev->usb_err >= 0) { -+ switch (sd->sensor) { -+ case SENSOR_HV7131R: -+ case SENSOR_PAS202B: -+ sd->work_thread = -+ create_singlethread_workqueue(KBUILD_MODNAME); -+ queue_work(sd->work_thread, &sd->work); -+ break; -+ } - } -+ - return gspca_dev->usb_err; - } - -@@ -6817,6 +6943,12 @@ static void sd_stop0(struct gspca_dev *g - { - struct sd *sd = (struct sd *) gspca_dev; - -+ if (sd->work_thread != NULL) { -+ mutex_unlock(&gspca_dev->usb_lock); -+ destroy_workqueue(sd->work_thread); -+ mutex_lock(&gspca_dev->usb_lock); -+ sd->work_thread = NULL; -+ } - if (!gspca_dev->present) - return; - send_unknown(gspca_dev, sd->sensor); -@@ -6893,19 +7025,33 @@ static int sd_querymenu(struct gspca_dev - return -EINVAL; - } - -+static int sd_setquality(struct gspca_dev *gspca_dev, __s32 val) -+{ -+ struct sd *sd = (struct sd *) gspca_dev; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(jpeg_qual) - 1; i++) { -+ if (val <= jpeg_qual[i]) -+ break; -+ } -+ if (i > 0 -+ && i == sd->reg08 -+ && val < jpeg_qual[sd->reg08]) -+ i--; -+ sd->reg08 = i; -+ sd->ctrls[QUALITY].val = jpeg_qual[i]; -+ if (gspca_dev->streaming) -+ jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); -+ return gspca_dev->usb_err; -+} -+ - static int sd_set_jcomp(struct gspca_dev *gspca_dev, - struct v4l2_jpegcompression *jcomp) - { - struct sd *sd = (struct sd *) gspca_dev; - -- if (jcomp->quality < QUALITY_MIN) -- sd->quality = QUALITY_MIN; -- else if (jcomp->quality > QUALITY_MAX) -- sd->quality = QUALITY_MAX; -- else -- sd->quality = jcomp->quality; -- if (gspca_dev->streaming) -- jpeg_set_qual(sd->jpeg_hdr, sd->quality); -+ sd_setquality(gspca_dev, jcomp->quality); -+ jcomp->quality = sd->ctrls[QUALITY].val; - return gspca_dev->usb_err; - } - -@@ -6915,7 +7061,7 @@ static int sd_get_jcomp(struct gspca_dev - struct sd *sd = (struct sd *) gspca_dev; - - memset(jcomp, 0, sizeof *jcomp); -- jcomp->quality = sd->quality; -+ jcomp->quality = sd->ctrls[QUALITY].val; - jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT - | V4L2_JPEG_MARKER_DQT; - return 0; -@@ -6938,7 +7084,7 @@ static int sd_int_pkt_scan(struct gspca_ - #endif - - static const struct sd_desc sd_desc = { -- .name = MODULE_NAME, -+ .name = KBUILD_MODNAME, - .ctrls = sd_ctrls, - .nctrls = ARRAY_SIZE(sd_ctrls), - .config = sd_config, -@@ -7023,7 +7169,7 @@ static int sd_probe(struct usb_interface - - /* USB driver */ - static struct usb_driver sd_driver = { -- .name = MODULE_NAME, -+ .name = KBUILD_MODNAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/au8522_decoder.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/au8522_decoder.c -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/au8522_decoder.c -@@ -839,15 +839,4 @@ static struct i2c_driver au8522_driver = - .id_table = au8522_id, - }; - --static __init int init_au8522(void) --{ -- return i2c_add_driver(&au8522_driver); --} -- --static __exit void exit_au8522(void) --{ -- i2c_del_driver(&au8522_driver); --} -- --module_init(init_au8522); --module_exit(exit_au8522); -+module_i2c_driver(au8522_driver); -Index: linux-3.3.x86_64/drivers/media/radio/radio-tea5764.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/radio/radio-tea5764.c -+++ linux-3.3.x86_64/drivers/media/radio/radio-tea5764.c -@@ -575,21 +575,7 @@ static struct i2c_driver tea5764_i2c_dri - .id_table = tea5764_id, - }; - --/* init the driver */ --static int __init tea5764_init(void) --{ -- int ret = i2c_add_driver(&tea5764_i2c_driver); -- -- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ": " -- DRIVER_DESC "\n"); -- return ret; --} -- --/* cleanup the driver */ --static void __exit tea5764_exit(void) --{ -- i2c_del_driver(&tea5764_i2c_driver); --} -+module_i2c_driver(tea5764_i2c_driver); - - MODULE_AUTHOR(DRIVER_AUTHOR); - MODULE_DESCRIPTION(DRIVER_DESC); -@@ -600,6 +586,3 @@ module_param(use_xtal, int, 0); - MODULE_PARM_DESC(use_xtal, "Chip have a xtal connected in board"); - module_param(radio_nr, int, 0); - MODULE_PARM_DESC(radio_nr, "video4linux device number to use"); -- --module_init(tea5764_init); --module_exit(tea5764_exit); -Index: linux-3.3.x86_64/drivers/media/radio/saa7706h.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/radio/saa7706h.c -+++ linux-3.3.x86_64/drivers/media/radio/saa7706h.c -@@ -434,18 +434,7 @@ static struct i2c_driver saa7706h_driver - .id_table = saa7706h_id, - }; - --static __init int saa7706h_init(void) --{ -- return i2c_add_driver(&saa7706h_driver); --} -- --static __exit void saa7706h_exit(void) --{ -- i2c_del_driver(&saa7706h_driver); --} -- --module_init(saa7706h_init); --module_exit(saa7706h_exit); -+module_i2c_driver(saa7706h_driver); - - MODULE_DESCRIPTION("SAA7706H Car Radio DSP driver"); - MODULE_AUTHOR("Mocean Laboratories"); -Index: linux-3.3.x86_64/drivers/media/radio/si470x/radio-si470x-i2c.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/radio/si470x/radio-si470x-i2c.c -+++ linux-3.3.x86_64/drivers/media/radio/si470x/radio-si470x-i2c.c -@@ -539,33 +539,7 @@ static struct i2c_driver si470x_i2c_driv - .id_table = si470x_i2c_id, - }; - -- -- --/************************************************************************** -- * Module Interface -- **************************************************************************/ -- --/* -- * si470x_i2c_init - module init -- */ --static int __init si470x_i2c_init(void) --{ -- printk(KERN_INFO DRIVER_DESC ", Version " DRIVER_VERSION "\n"); -- return i2c_add_driver(&si470x_i2c_driver); --} -- -- --/* -- * si470x_i2c_exit - module exit -- */ --static void __exit si470x_i2c_exit(void) --{ -- i2c_del_driver(&si470x_i2c_driver); --} -- -- --module_init(si470x_i2c_init); --module_exit(si470x_i2c_exit); -+module_i2c_driver(si470x_i2c_driver); - - MODULE_LICENSE("GPL"); - MODULE_AUTHOR(DRIVER_AUTHOR); -Index: linux-3.3.x86_64/drivers/media/radio/si4713-i2c.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/radio/si4713-i2c.c -+++ linux-3.3.x86_64/drivers/media/radio/si4713-i2c.c -@@ -2106,17 +2106,4 @@ static struct i2c_driver si4713_i2c_driv - .id_table = si4713_id, - }; - --/* Module Interface */ --static int __init si4713_module_init(void) --{ -- return i2c_add_driver(&si4713_i2c_driver); --} -- --static void __exit si4713_module_exit(void) --{ -- i2c_del_driver(&si4713_i2c_driver); --} -- --module_init(si4713_module_init); --module_exit(si4713_module_exit); -- -+module_i2c_driver(si4713_i2c_driver); -Index: linux-3.3.x86_64/drivers/media/radio/tef6862.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/radio/tef6862.c -+++ linux-3.3.x86_64/drivers/media/radio/tef6862.c -@@ -215,20 +215,8 @@ static struct i2c_driver tef6862_driver - .id_table = tef6862_id, - }; - --static __init int tef6862_init(void) --{ -- return i2c_add_driver(&tef6862_driver); --} -- --static __exit void tef6862_exit(void) --{ -- i2c_del_driver(&tef6862_driver); --} -- --module_init(tef6862_init); --module_exit(tef6862_exit); -+module_i2c_driver(tef6862_driver); - - MODULE_DESCRIPTION("TEF6862 Car Radio Enhanced Selectivity Tuner"); - MODULE_AUTHOR("Mocean Laboratories"); - MODULE_LICENSE("GPL v2"); -- -Index: linux-3.3.x86_64/drivers/media/video/adp1653.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/adp1653.c -+++ linux-3.3.x86_64/drivers/media/video/adp1653.c -@@ -33,7 +33,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -482,24 +481,7 @@ static struct i2c_driver adp1653_i2c_dri - .id_table = adp1653_id_table, - }; - --static int __init adp1653_init(void) --{ -- int rval; -- -- rval = i2c_add_driver(&adp1653_i2c_driver); -- if (rval) -- printk(KERN_ALERT "%s: failed at i2c_add_driver\n", __func__); -- -- return rval; --} -- --static void __exit adp1653_exit(void) --{ -- i2c_del_driver(&adp1653_i2c_driver); --} -- --module_init(adp1653_init); --module_exit(adp1653_exit); -+module_i2c_driver(adp1653_i2c_driver); - - MODULE_AUTHOR("Sakari Ailus "); - MODULE_DESCRIPTION("Analog Devices ADP1653 LED flash driver"); -Index: linux-3.3.x86_64/drivers/media/video/adv7170.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/adv7170.c -+++ linux-3.3.x86_64/drivers/media/video/adv7170.c -@@ -407,15 +407,4 @@ static struct i2c_driver adv7170_driver - .id_table = adv7170_id, - }; - --static __init int init_adv7170(void) --{ -- return i2c_add_driver(&adv7170_driver); --} -- --static __exit void exit_adv7170(void) --{ -- i2c_del_driver(&adv7170_driver); --} -- --module_init(init_adv7170); --module_exit(exit_adv7170); -+module_i2c_driver(adv7170_driver); -Index: linux-3.3.x86_64/drivers/media/video/adv7175.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/adv7175.c -+++ linux-3.3.x86_64/drivers/media/video/adv7175.c -@@ -457,15 +457,4 @@ static struct i2c_driver adv7175_driver - .id_table = adv7175_id, - }; - --static __init int init_adv7175(void) --{ -- return i2c_add_driver(&adv7175_driver); --} -- --static __exit void exit_adv7175(void) --{ -- i2c_del_driver(&adv7175_driver); --} -- --module_init(init_adv7175); --module_exit(exit_adv7175); -+module_i2c_driver(adv7175_driver); -Index: linux-3.3.x86_64/drivers/media/video/adv7180.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/adv7180.c -+++ linux-3.3.x86_64/drivers/media/video/adv7180.c -@@ -444,20 +444,8 @@ static struct i2c_driver adv7180_driver - .id_table = adv7180_id, - }; - --static __init int adv7180_init(void) --{ -- return i2c_add_driver(&adv7180_driver); --} -- --static __exit void adv7180_exit(void) --{ -- i2c_del_driver(&adv7180_driver); --} -- --module_init(adv7180_init); --module_exit(adv7180_exit); -+module_i2c_driver(adv7180_driver); - - MODULE_DESCRIPTION("Analog Devices ADV7180 video decoder driver"); - MODULE_AUTHOR("Mocean Laboratories"); - MODULE_LICENSE("GPL v2"); -- -Index: linux-3.3.x86_64/drivers/media/video/adv7343.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/adv7343.c -+++ linux-3.3.x86_64/drivers/media/video/adv7343.c -@@ -475,15 +475,4 @@ static struct i2c_driver adv7343_driver - .id_table = adv7343_id, - }; - --static __init int init_adv7343(void) --{ -- return i2c_add_driver(&adv7343_driver); --} -- --static __exit void exit_adv7343(void) --{ -- i2c_del_driver(&adv7343_driver); --} -- --module_init(init_adv7343); --module_exit(exit_adv7343); -+module_i2c_driver(adv7343_driver); -Index: linux-3.3.x86_64/drivers/media/video/ak881x.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ak881x.c -+++ linux-3.3.x86_64/drivers/media/video/ak881x.c -@@ -352,18 +352,7 @@ static struct i2c_driver ak881x_i2c_driv - .id_table = ak881x_id, - }; - --static int __init ak881x_module_init(void) --{ -- return i2c_add_driver(&ak881x_i2c_driver); --} -- --static void __exit ak881x_module_exit(void) --{ -- i2c_del_driver(&ak881x_i2c_driver); --} -- --module_init(ak881x_module_init); --module_exit(ak881x_module_exit); -+module_i2c_driver(ak881x_i2c_driver); - - MODULE_DESCRIPTION("TV-output driver for ak8813/ak8814"); - MODULE_AUTHOR("Guennadi Liakhovetski "); -Index: linux-3.3.x86_64/drivers/media/video/as3645a.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/as3645a.c -+++ linux-3.3.x86_64/drivers/media/video/as3645a.c -@@ -881,24 +881,7 @@ static struct i2c_driver as3645a_i2c_dri - .id_table = as3645a_id_table, - }; - --static int __init as3645a_init(void) --{ -- int rval; -- -- rval = i2c_add_driver(&as3645a_i2c_driver); -- if (rval) -- pr_err("%s: Failed to register the driver\n", AS3645A_NAME); -- -- return rval; --} -- --static void __exit as3645a_exit(void) --{ -- i2c_del_driver(&as3645a_i2c_driver); --} -- --module_init(as3645a_init); --module_exit(as3645a_exit); -+module_i2c_driver(as3645a_i2c_driver); - - MODULE_AUTHOR("Laurent Pinchart "); - MODULE_DESCRIPTION("LED flash driver for AS3645A, LM3555 and their clones"); -Index: linux-3.3.x86_64/drivers/media/video/bt819.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/bt819.c -+++ linux-3.3.x86_64/drivers/media/video/bt819.c -@@ -514,15 +514,4 @@ static struct i2c_driver bt819_driver = - .id_table = bt819_id, - }; - --static __init int init_bt819(void) --{ -- return i2c_add_driver(&bt819_driver); --} -- --static __exit void exit_bt819(void) --{ -- i2c_del_driver(&bt819_driver); --} -- --module_init(init_bt819); --module_exit(exit_bt819); -+module_i2c_driver(bt819_driver); -Index: linux-3.3.x86_64/drivers/media/video/bt856.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/bt856.c -+++ linux-3.3.x86_64/drivers/media/video/bt856.c -@@ -270,15 +270,4 @@ static struct i2c_driver bt856_driver = - .id_table = bt856_id, - }; - --static __init int init_bt856(void) --{ -- return i2c_add_driver(&bt856_driver); --} -- --static __exit void exit_bt856(void) --{ -- i2c_del_driver(&bt856_driver); --} -- --module_init(init_bt856); --module_exit(exit_bt856); -+module_i2c_driver(bt856_driver); -Index: linux-3.3.x86_64/drivers/media/video/bt866.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/bt866.c -+++ linux-3.3.x86_64/drivers/media/video/bt866.c -@@ -240,15 +240,4 @@ static struct i2c_driver bt866_driver = - .id_table = bt866_id, - }; - --static __init int init_bt866(void) --{ -- return i2c_add_driver(&bt866_driver); --} -- --static __exit void exit_bt866(void) --{ -- i2c_del_driver(&bt866_driver); --} -- --module_init(init_bt866); --module_exit(exit_bt866); -+module_i2c_driver(bt866_driver); -Index: linux-3.3.x86_64/drivers/media/video/cs5345.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/cs5345.c -+++ linux-3.3.x86_64/drivers/media/video/cs5345.c -@@ -249,15 +249,4 @@ static struct i2c_driver cs5345_driver = - .id_table = cs5345_id, - }; - --static __init int init_cs5345(void) --{ -- return i2c_add_driver(&cs5345_driver); --} -- --static __exit void exit_cs5345(void) --{ -- i2c_del_driver(&cs5345_driver); --} -- --module_init(init_cs5345); --module_exit(exit_cs5345); -+module_i2c_driver(cs5345_driver); -Index: linux-3.3.x86_64/drivers/media/video/cs53l32a.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/cs53l32a.c -+++ linux-3.3.x86_64/drivers/media/video/cs53l32a.c -@@ -248,15 +248,4 @@ static struct i2c_driver cs53l32a_driver - .id_table = cs53l32a_id, - }; - --static __init int init_cs53l32a(void) --{ -- return i2c_add_driver(&cs53l32a_driver); --} -- --static __exit void exit_cs53l32a(void) --{ -- i2c_del_driver(&cs53l32a_driver); --} -- --module_init(init_cs53l32a); --module_exit(exit_cs53l32a); -+module_i2c_driver(cs53l32a_driver); -Index: linux-3.3.x86_64/drivers/media/video/cx25840/cx25840-core.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/cx25840/cx25840-core.c -+++ linux-3.3.x86_64/drivers/media/video/cx25840/cx25840-core.c -@@ -5301,15 +5301,4 @@ static struct i2c_driver cx25840_driver - .id_table = cx25840_id, - }; - --static __init int init_cx25840(void) --{ -- return i2c_add_driver(&cx25840_driver); --} -- --static __exit void exit_cx25840(void) --{ -- i2c_del_driver(&cx25840_driver); --} -- --module_init(init_cx25840); --module_exit(exit_cx25840); -+module_i2c_driver(cx25840_driver); -Index: linux-3.3.x86_64/drivers/media/video/imx074.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/imx074.c -+++ linux-3.3.x86_64/drivers/media/video/imx074.c -@@ -468,18 +468,7 @@ static struct i2c_driver imx074_i2c_driv - .id_table = imx074_id, - }; - --static int __init imx074_mod_init(void) --{ -- return i2c_add_driver(&imx074_i2c_driver); --} -- --static void __exit imx074_mod_exit(void) --{ -- i2c_del_driver(&imx074_i2c_driver); --} -- --module_init(imx074_mod_init); --module_exit(imx074_mod_exit); -+module_i2c_driver(imx074_i2c_driver); - - MODULE_DESCRIPTION("Sony IMX074 Camera driver"); - MODULE_AUTHOR("Guennadi Liakhovetski "); -Index: linux-3.3.x86_64/drivers/media/video/indycam.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/indycam.c -+++ linux-3.3.x86_64/drivers/media/video/indycam.c -@@ -387,15 +387,4 @@ static struct i2c_driver indycam_driver - .id_table = indycam_id, - }; - --static __init int init_indycam(void) --{ -- return i2c_add_driver(&indycam_driver); --} -- --static __exit void exit_indycam(void) --{ -- i2c_del_driver(&indycam_driver); --} -- --module_init(init_indycam); --module_exit(exit_indycam); -+module_i2c_driver(indycam_driver); -Index: linux-3.3.x86_64/drivers/media/video/ir-kbd-i2c.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ir-kbd-i2c.c -+++ linux-3.3.x86_64/drivers/media/video/ir-kbd-i2c.c -@@ -471,7 +471,7 @@ static const struct i2c_device_id ir_kbd - { } - }; - --static struct i2c_driver driver = { -+static struct i2c_driver ir_kbd_driver = { - .driver = { - .name = "ir-kbd-i2c", - }, -@@ -480,21 +480,10 @@ static struct i2c_driver driver = { - .id_table = ir_kbd_id, - }; - -+module_i2c_driver(ir_kbd_driver); -+ - /* ----------------------------------------------------------------------- */ - - MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Mueller"); - MODULE_DESCRIPTION("input driver for i2c IR remote controls"); - MODULE_LICENSE("GPL"); -- --static int __init ir_init(void) --{ -- return i2c_add_driver(&driver); --} -- --static void __exit ir_fini(void) --{ -- i2c_del_driver(&driver); --} -- --module_init(ir_init); --module_exit(ir_fini); -Index: linux-3.3.x86_64/drivers/media/video/ks0127.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ks0127.c -+++ linux-3.3.x86_64/drivers/media/video/ks0127.c -@@ -721,15 +721,4 @@ static struct i2c_driver ks0127_driver = - .id_table = ks0127_id, - }; - --static __init int init_ks0127(void) --{ -- return i2c_add_driver(&ks0127_driver); --} -- --static __exit void exit_ks0127(void) --{ -- i2c_del_driver(&ks0127_driver); --} -- --module_init(init_ks0127); --module_exit(exit_ks0127); -+module_i2c_driver(ks0127_driver); -Index: linux-3.3.x86_64/drivers/media/video/m52790.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/m52790.c -+++ linux-3.3.x86_64/drivers/media/video/m52790.c -@@ -213,15 +213,4 @@ static struct i2c_driver m52790_driver = - .id_table = m52790_id, - }; - --static __init int init_m52790(void) --{ -- return i2c_add_driver(&m52790_driver); --} -- --static __exit void exit_m52790(void) --{ -- i2c_del_driver(&m52790_driver); --} -- --module_init(init_m52790); --module_exit(exit_m52790); -+module_i2c_driver(m52790_driver); -Index: linux-3.3.x86_64/drivers/media/video/msp3400-driver.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/msp3400-driver.c -+++ linux-3.3.x86_64/drivers/media/video/msp3400-driver.c -@@ -881,18 +881,7 @@ static struct i2c_driver msp_driver = { - .id_table = msp_id, - }; - --static __init int init_msp(void) --{ -- return i2c_add_driver(&msp_driver); --} -- --static __exit void exit_msp(void) --{ -- i2c_del_driver(&msp_driver); --} -- --module_init(init_msp); --module_exit(exit_msp); -+module_i2c_driver(msp_driver); - - /* - * Overrides for Emacs so that we follow Linus's tabbing style. -Index: linux-3.3.x86_64/drivers/media/video/mt9m001.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/mt9m001.c -+++ linux-3.3.x86_64/drivers/media/video/mt9m001.c -@@ -730,18 +730,7 @@ static struct i2c_driver mt9m001_i2c_dri - .id_table = mt9m001_id, - }; - --static int __init mt9m001_mod_init(void) --{ -- return i2c_add_driver(&mt9m001_i2c_driver); --} -- --static void __exit mt9m001_mod_exit(void) --{ -- i2c_del_driver(&mt9m001_i2c_driver); --} -- --module_init(mt9m001_mod_init); --module_exit(mt9m001_mod_exit); -+module_i2c_driver(mt9m001_i2c_driver); - - MODULE_DESCRIPTION("Micron MT9M001 Camera driver"); - MODULE_AUTHOR("Guennadi Liakhovetski "); -Index: linux-3.3.x86_64/drivers/media/video/mt9m111.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/mt9m111.c -+++ linux-3.3.x86_64/drivers/media/video/mt9m111.c -@@ -1008,18 +1008,7 @@ static struct i2c_driver mt9m111_i2c_dri - .id_table = mt9m111_id, - }; - --static int __init mt9m111_mod_init(void) --{ -- return i2c_add_driver(&mt9m111_i2c_driver); --} -- --static void __exit mt9m111_mod_exit(void) --{ -- i2c_del_driver(&mt9m111_i2c_driver); --} -- --module_init(mt9m111_mod_init); --module_exit(mt9m111_mod_exit); -+module_i2c_driver(mt9m111_i2c_driver); - - MODULE_DESCRIPTION("Micron/Aptina MT9M111/MT9M112/MT9M131 Camera driver"); - MODULE_AUTHOR("Robert Jarzmik"); -Index: linux-3.3.x86_64/drivers/media/video/mt9p031.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/mt9p031.c -+++ linux-3.3.x86_64/drivers/media/video/mt9p031.c -@@ -19,7 +19,6 @@ - #include - #include - #include --#include - #include - - #include -@@ -28,6 +27,8 @@ - #include - #include - -+#include "aptina-pll.h" -+ - #define MT9P031_PIXEL_ARRAY_WIDTH 2752 - #define MT9P031_PIXEL_ARRAY_HEIGHT 2004 - -@@ -98,14 +99,6 @@ - #define MT9P031_TEST_PATTERN_RED 0xa2 - #define MT9P031_TEST_PATTERN_BLUE 0xa3 - --struct mt9p031_pll_divs { -- u32 ext_freq; -- u32 target_freq; -- u8 m; -- u8 n; -- u8 p1; --}; -- - struct mt9p031 { - struct v4l2_subdev subdev; - struct media_pad pad; -@@ -115,10 +108,8 @@ struct mt9p031 { - struct mt9p031_platform_data *pdata; - struct mutex power_lock; /* lock to protect power_count */ - int power_count; -- u16 xskip; -- u16 yskip; - -- const struct mt9p031_pll_divs *pll; -+ struct aptina_pll pll; - - /* Registers cache */ - u16 output_control; -@@ -186,33 +177,31 @@ static int mt9p031_reset(struct mt9p031 - 0); - } - --/* -- * This static table uses ext_freq and vdd_io values to select suitable -- * PLL dividers m, n and p1 which have been calculated as specifiec in p36 -- * of Aptina's mt9p031 datasheet. New values should be added here. -- */ --static const struct mt9p031_pll_divs mt9p031_divs[] = { -- /* ext_freq target_freq m n p1 */ -- {21000000, 48000000, 26, 2, 6} --}; -- --static int mt9p031_pll_get_divs(struct mt9p031 *mt9p031) -+static int mt9p031_pll_setup(struct mt9p031 *mt9p031) - { -+ static const struct aptina_pll_limits limits = { -+ .ext_clock_min = 6000000, -+ .ext_clock_max = 27000000, -+ .int_clock_min = 2000000, -+ .int_clock_max = 13500000, -+ .out_clock_min = 180000000, -+ .out_clock_max = 360000000, -+ .pix_clock_max = 96000000, -+ .n_min = 1, -+ .n_max = 64, -+ .m_min = 16, -+ .m_max = 255, -+ .p1_min = 1, -+ .p1_max = 128, -+ }; -+ - struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); -- int i; -+ struct mt9p031_platform_data *pdata = mt9p031->pdata; - -- for (i = 0; i < ARRAY_SIZE(mt9p031_divs); i++) { -- if (mt9p031_divs[i].ext_freq == mt9p031->pdata->ext_freq && -- mt9p031_divs[i].target_freq == mt9p031->pdata->target_freq) { -- mt9p031->pll = &mt9p031_divs[i]; -- return 0; -- } -- } -+ mt9p031->pll.ext_clock = pdata->ext_freq; -+ mt9p031->pll.pix_clock = pdata->target_freq; - -- dev_err(&client->dev, "Couldn't find PLL dividers for ext_freq = %d, " -- "target_freq = %d\n", mt9p031->pdata->ext_freq, -- mt9p031->pdata->target_freq); -- return -EINVAL; -+ return aptina_pll_calculate(&client->dev, &limits, &mt9p031->pll); - } - - static int mt9p031_pll_enable(struct mt9p031 *mt9p031) -@@ -226,11 +215,11 @@ static int mt9p031_pll_enable(struct mt9 - return ret; - - ret = mt9p031_write(client, MT9P031_PLL_CONFIG_1, -- (mt9p031->pll->m << 8) | (mt9p031->pll->n - 1)); -+ (mt9p031->pll.m << 8) | (mt9p031->pll.n - 1)); - if (ret < 0) - return ret; - -- ret = mt9p031_write(client, MT9P031_PLL_CONFIG_2, mt9p031->pll->p1 - 1); -+ ret = mt9p031_write(client, MT9P031_PLL_CONFIG_2, mt9p031->pll.p1 - 1); - if (ret < 0) - return ret; - -@@ -785,8 +774,6 @@ static int mt9p031_open(struct v4l2_subd - format->field = V4L2_FIELD_NONE; - format->colorspace = V4L2_COLORSPACE_SRGB; - -- mt9p031->xskip = 1; -- mt9p031->yskip = 1; - return mt9p031_set_power(subdev, 1); - } - -@@ -905,7 +892,7 @@ static int mt9p031_probe(struct i2c_clie - mt9p031->format.field = V4L2_FIELD_NONE; - mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB; - -- ret = mt9p031_pll_get_divs(mt9p031); -+ ret = mt9p031_pll_setup(mt9p031); - - done: - if (ret < 0) { -@@ -945,18 +932,7 @@ static struct i2c_driver mt9p031_i2c_dri - .id_table = mt9p031_id, - }; - --static int __init mt9p031_mod_init(void) --{ -- return i2c_add_driver(&mt9p031_i2c_driver); --} -- --static void __exit mt9p031_mod_exit(void) --{ -- i2c_del_driver(&mt9p031_i2c_driver); --} -- --module_init(mt9p031_mod_init); --module_exit(mt9p031_mod_exit); -+module_i2c_driver(mt9p031_i2c_driver); - - MODULE_DESCRIPTION("Aptina MT9P031 Camera driver"); - MODULE_AUTHOR("Bastian Hecht "); -Index: linux-3.3.x86_64/drivers/media/video/mt9t001.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/mt9t001.c -+++ linux-3.3.x86_64/drivers/media/video/mt9t001.c -@@ -817,18 +817,7 @@ static struct i2c_driver mt9t001_driver - .id_table = mt9t001_id, - }; - --static int __init mt9t001_init(void) --{ -- return i2c_add_driver(&mt9t001_driver); --} -- --static void __exit mt9t001_exit(void) --{ -- i2c_del_driver(&mt9t001_driver); --} -- --module_init(mt9t001_init); --module_exit(mt9t001_exit); -+module_i2c_driver(mt9t001_driver); - - MODULE_DESCRIPTION("Aptina (Micron) MT9T001 Camera driver"); - MODULE_AUTHOR("Laurent Pinchart "); -Index: linux-3.3.x86_64/drivers/media/video/mt9t031.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/mt9t031.c -+++ linux-3.3.x86_64/drivers/media/video/mt9t031.c -@@ -850,18 +850,7 @@ static struct i2c_driver mt9t031_i2c_dri - .id_table = mt9t031_id, - }; - --static int __init mt9t031_mod_init(void) --{ -- return i2c_add_driver(&mt9t031_i2c_driver); --} -- --static void __exit mt9t031_mod_exit(void) --{ -- i2c_del_driver(&mt9t031_i2c_driver); --} -- --module_init(mt9t031_mod_init); --module_exit(mt9t031_mod_exit); -+module_i2c_driver(mt9t031_i2c_driver); - - MODULE_DESCRIPTION("Micron MT9T031 Camera driver"); - MODULE_AUTHOR("Guennadi Liakhovetski "); -Index: linux-3.3.x86_64/drivers/media/video/mt9t112.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/mt9t112.c -+++ linux-3.3.x86_64/drivers/media/video/mt9t112.c -@@ -1117,21 +1117,7 @@ static struct i2c_driver mt9t112_i2c_dri - .id_table = mt9t112_id, - }; - --/************************************************************************ -- module function --************************************************************************/ --static int __init mt9t112_module_init(void) --{ -- return i2c_add_driver(&mt9t112_i2c_driver); --} -- --static void __exit mt9t112_module_exit(void) --{ -- i2c_del_driver(&mt9t112_i2c_driver); --} -- --module_init(mt9t112_module_init); --module_exit(mt9t112_module_exit); -+module_i2c_driver(mt9t112_i2c_driver); - - MODULE_DESCRIPTION("SoC Camera driver for mt9t112"); - MODULE_AUTHOR("Kuninori Morimoto"); -Index: linux-3.3.x86_64/drivers/media/video/mt9v011.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/mt9v011.c -+++ linux-3.3.x86_64/drivers/media/video/mt9v011.c -@@ -709,15 +709,4 @@ static struct i2c_driver mt9v011_driver - .id_table = mt9v011_id, - }; - --static __init int init_mt9v011(void) --{ -- return i2c_add_driver(&mt9v011_driver); --} -- --static __exit void exit_mt9v011(void) --{ -- i2c_del_driver(&mt9v011_driver); --} -- --module_init(init_mt9v011); --module_exit(exit_mt9v011); -+module_i2c_driver(mt9v011_driver); -Index: linux-3.3.x86_64/drivers/media/video/mt9v022.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/mt9v022.c -+++ linux-3.3.x86_64/drivers/media/video/mt9v022.c -@@ -872,18 +872,7 @@ static struct i2c_driver mt9v022_i2c_dri - .id_table = mt9v022_id, - }; - --static int __init mt9v022_mod_init(void) --{ -- return i2c_add_driver(&mt9v022_i2c_driver); --} -- --static void __exit mt9v022_mod_exit(void) --{ -- i2c_del_driver(&mt9v022_i2c_driver); --} -- --module_init(mt9v022_mod_init); --module_exit(mt9v022_mod_exit); -+module_i2c_driver(mt9v022_i2c_driver); - - MODULE_DESCRIPTION("Micron MT9V022 Camera driver"); - MODULE_AUTHOR("Guennadi Liakhovetski "); -Index: linux-3.3.x86_64/drivers/media/video/mt9v032.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/mt9v032.c -+++ linux-3.3.x86_64/drivers/media/video/mt9v032.c -@@ -756,18 +756,7 @@ static struct i2c_driver mt9v032_driver - .id_table = mt9v032_id, - }; - --static int __init mt9v032_init(void) --{ -- return i2c_add_driver(&mt9v032_driver); --} -- --static void __exit mt9v032_exit(void) --{ -- i2c_del_driver(&mt9v032_driver); --} -- --module_init(mt9v032_init); --module_exit(mt9v032_exit); -+module_i2c_driver(mt9v032_driver); - - MODULE_DESCRIPTION("Aptina MT9V032 Camera driver"); - MODULE_AUTHOR("Laurent Pinchart "); -Index: linux-3.3.x86_64/drivers/media/video/ov2640.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ov2640.c -+++ linux-3.3.x86_64/drivers/media/video/ov2640.c -@@ -1103,21 +1103,7 @@ static struct i2c_driver ov2640_i2c_driv - .id_table = ov2640_id, - }; - --/* -- * Module functions -- */ --static int __init ov2640_module_init(void) --{ -- return i2c_add_driver(&ov2640_i2c_driver); --} -- --static void __exit ov2640_module_exit(void) --{ -- i2c_del_driver(&ov2640_i2c_driver); --} -- --module_init(ov2640_module_init); --module_exit(ov2640_module_exit); -+module_i2c_driver(ov2640_i2c_driver); - - MODULE_DESCRIPTION("SoC Camera driver for Omni Vision 2640 sensor"); - MODULE_AUTHOR("Alberto Panizzo"); -Index: linux-3.3.x86_64/drivers/media/video/ov5642.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ov5642.c -+++ linux-3.3.x86_64/drivers/media/video/ov5642.c -@@ -1068,18 +1068,7 @@ static struct i2c_driver ov5642_i2c_driv - .id_table = ov5642_id, - }; - --static int __init ov5642_mod_init(void) --{ -- return i2c_add_driver(&ov5642_i2c_driver); --} -- --static void __exit ov5642_mod_exit(void) --{ -- i2c_del_driver(&ov5642_i2c_driver); --} -- --module_init(ov5642_mod_init); --module_exit(ov5642_mod_exit); -+module_i2c_driver(ov5642_i2c_driver); - - MODULE_DESCRIPTION("Omnivision OV5642 Camera driver"); - MODULE_AUTHOR("Bastian Hecht "); -Index: linux-3.3.x86_64/drivers/media/video/ov7670.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ov7670.c -+++ linux-3.3.x86_64/drivers/media/video/ov7670.c -@@ -1583,15 +1583,4 @@ static struct i2c_driver ov7670_driver = - .id_table = ov7670_id, - }; - --static __init int init_ov7670(void) --{ -- return i2c_add_driver(&ov7670_driver); --} -- --static __exit void exit_ov7670(void) --{ -- i2c_del_driver(&ov7670_driver); --} -- --module_init(init_ov7670); --module_exit(exit_ov7670); -+module_i2c_driver(ov7670_driver); -Index: linux-3.3.x86_64/drivers/media/video/ov772x.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ov772x.c -+++ linux-3.3.x86_64/drivers/media/video/ov772x.c -@@ -1123,22 +1123,7 @@ static struct i2c_driver ov772x_i2c_driv - .id_table = ov772x_id, - }; - --/* -- * module function -- */ -- --static int __init ov772x_module_init(void) --{ -- return i2c_add_driver(&ov772x_i2c_driver); --} -- --static void __exit ov772x_module_exit(void) --{ -- i2c_del_driver(&ov772x_i2c_driver); --} -- --module_init(ov772x_module_init); --module_exit(ov772x_module_exit); -+module_i2c_driver(ov772x_i2c_driver); - - MODULE_DESCRIPTION("SoC Camera driver for ov772x"); - MODULE_AUTHOR("Kuninori Morimoto"); -Index: linux-3.3.x86_64/drivers/media/video/ov9640.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ov9640.c -+++ linux-3.3.x86_64/drivers/media/video/ov9640.c -@@ -738,18 +738,7 @@ static struct i2c_driver ov9640_i2c_driv - .id_table = ov9640_id, - }; - --static int __init ov9640_module_init(void) --{ -- return i2c_add_driver(&ov9640_i2c_driver); --} -- --static void __exit ov9640_module_exit(void) --{ -- i2c_del_driver(&ov9640_i2c_driver); --} -- --module_init(ov9640_module_init); --module_exit(ov9640_module_exit); -+module_i2c_driver(ov9640_i2c_driver); - - MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV96xx"); - MODULE_AUTHOR("Marek Vasut "); -Index: linux-3.3.x86_64/drivers/media/video/ov9740.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ov9740.c -+++ linux-3.3.x86_64/drivers/media/video/ov9740.c -@@ -998,18 +998,7 @@ static struct i2c_driver ov9740_i2c_driv - .id_table = ov9740_id, - }; - --static int __init ov9740_module_init(void) --{ -- return i2c_add_driver(&ov9740_i2c_driver); --} -- --static void __exit ov9740_module_exit(void) --{ -- i2c_del_driver(&ov9740_i2c_driver); --} -- --module_init(ov9740_module_init); --module_exit(ov9740_module_exit); -+module_i2c_driver(ov9740_i2c_driver); - - MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV9740"); - MODULE_AUTHOR("Andrew Chew "); -Index: linux-3.3.x86_64/drivers/media/video/rj54n1cb0c.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/rj54n1cb0c.c -+++ linux-3.3.x86_64/drivers/media/video/rj54n1cb0c.c -@@ -1407,18 +1407,7 @@ static struct i2c_driver rj54n1_i2c_driv - .id_table = rj54n1_id, - }; - --static int __init rj54n1_mod_init(void) --{ -- return i2c_add_driver(&rj54n1_i2c_driver); --} -- --static void __exit rj54n1_mod_exit(void) --{ -- i2c_del_driver(&rj54n1_i2c_driver); --} -- --module_init(rj54n1_mod_init); --module_exit(rj54n1_mod_exit); -+module_i2c_driver(rj54n1_i2c_driver); - - MODULE_DESCRIPTION("Sharp RJ54N1CB0C Camera driver"); - MODULE_AUTHOR("Guennadi Liakhovetski "); -Index: linux-3.3.x86_64/drivers/media/video/s5p-tv/hdmiphy_drv.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s5p-tv/hdmiphy_drv.c -+++ linux-3.3.x86_64/drivers/media/video/s5p-tv/hdmiphy_drv.c -@@ -175,14 +175,4 @@ static struct i2c_driver hdmiphy_driver - .id_table = hdmiphy_id, - }; - --static int __init hdmiphy_init(void) --{ -- return i2c_add_driver(&hdmiphy_driver); --} --module_init(hdmiphy_init); -- --static void __exit hdmiphy_exit(void) --{ -- i2c_del_driver(&hdmiphy_driver); --} --module_exit(hdmiphy_exit); -+module_i2c_driver(hdmiphy_driver); -Index: linux-3.3.x86_64/drivers/media/video/saa6588.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/saa6588.c -+++ linux-3.3.x86_64/drivers/media/video/saa6588.c -@@ -539,15 +539,4 @@ static struct i2c_driver saa6588_driver - .id_table = saa6588_id, - }; - --static __init int init_saa6588(void) --{ -- return i2c_add_driver(&saa6588_driver); --} -- --static __exit void exit_saa6588(void) --{ -- i2c_del_driver(&saa6588_driver); --} -- --module_init(init_saa6588); --module_exit(exit_saa6588); -+module_i2c_driver(saa6588_driver); -Index: linux-3.3.x86_64/drivers/media/video/saa7110.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/saa7110.c -+++ linux-3.3.x86_64/drivers/media/video/saa7110.c -@@ -491,15 +491,4 @@ static struct i2c_driver saa7110_driver - .id_table = saa7110_id, - }; - --static __init int init_saa7110(void) --{ -- return i2c_add_driver(&saa7110_driver); --} -- --static __exit void exit_saa7110(void) --{ -- i2c_del_driver(&saa7110_driver); --} -- --module_init(init_saa7110); --module_exit(exit_saa7110); -+module_i2c_driver(saa7110_driver); -Index: linux-3.3.x86_64/drivers/media/video/saa7115.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/saa7115.c -+++ linux-3.3.x86_64/drivers/media/video/saa7115.c -@@ -1724,15 +1724,4 @@ static struct i2c_driver saa711x_driver - .id_table = saa711x_id, - }; - --static __init int init_saa711x(void) --{ -- return i2c_add_driver(&saa711x_driver); --} -- --static __exit void exit_saa711x(void) --{ -- i2c_del_driver(&saa711x_driver); --} -- --module_init(init_saa711x); --module_exit(exit_saa711x); -+module_i2c_driver(saa711x_driver); -Index: linux-3.3.x86_64/drivers/media/video/saa7127.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/saa7127.c -+++ linux-3.3.x86_64/drivers/media/video/saa7127.c -@@ -852,15 +852,4 @@ static struct i2c_driver saa7127_driver - .id_table = saa7127_id, - }; - --static __init int init_saa7127(void) --{ -- return i2c_add_driver(&saa7127_driver); --} -- --static __exit void exit_saa7127(void) --{ -- i2c_del_driver(&saa7127_driver); --} -- --module_init(init_saa7127); --module_exit(exit_saa7127); -+module_i2c_driver(saa7127_driver); -Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa6752hs.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa6752hs.c -+++ linux-3.3.x86_64/drivers/media/video/saa7134/saa6752hs.c -@@ -1001,18 +1001,7 @@ static struct i2c_driver saa6752hs_drive - .id_table = saa6752hs_id, - }; - --static __init int init_saa6752hs(void) --{ -- return i2c_add_driver(&saa6752hs_driver); --} -- --static __exit void exit_saa6752hs(void) --{ -- i2c_del_driver(&saa6752hs_driver); --} -- --module_init(init_saa6752hs); --module_exit(exit_saa6752hs); -+module_i2c_driver(saa6752hs_driver); - - /* - * Overrides for Emacs so that we follow Linus's tabbing style. -Index: linux-3.3.x86_64/drivers/media/video/saa717x.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/saa717x.c -+++ linux-3.3.x86_64/drivers/media/video/saa717x.c -@@ -1375,15 +1375,4 @@ static struct i2c_driver saa717x_driver - .id_table = saa717x_id, - }; - --static __init int init_saa717x(void) --{ -- return i2c_add_driver(&saa717x_driver); --} -- --static __exit void exit_saa717x(void) --{ -- i2c_del_driver(&saa717x_driver); --} -- --module_init(init_saa717x); --module_exit(exit_saa717x); -+module_i2c_driver(saa717x_driver); -Index: linux-3.3.x86_64/drivers/media/video/saa7185.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/saa7185.c -+++ linux-3.3.x86_64/drivers/media/video/saa7185.c -@@ -374,15 +374,4 @@ static struct i2c_driver saa7185_driver - .id_table = saa7185_id, - }; - --static __init int init_saa7185(void) --{ -- return i2c_add_driver(&saa7185_driver); --} -- --static __exit void exit_saa7185(void) --{ -- i2c_del_driver(&saa7185_driver); --} -- --module_init(init_saa7185); --module_exit(exit_saa7185); -+module_i2c_driver(saa7185_driver); -Index: linux-3.3.x86_64/drivers/media/video/saa7191.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/saa7191.c -+++ linux-3.3.x86_64/drivers/media/video/saa7191.c -@@ -656,15 +656,4 @@ static struct i2c_driver saa7191_driver - .id_table = saa7191_id, - }; - --static __init int init_saa7191(void) --{ -- return i2c_add_driver(&saa7191_driver); --} -- --static __exit void exit_saa7191(void) --{ -- i2c_del_driver(&saa7191_driver); --} -- --module_init(init_saa7191); --module_exit(exit_saa7191); -+module_i2c_driver(saa7191_driver); -Index: linux-3.3.x86_64/drivers/media/video/sr030pc30.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/sr030pc30.c -+++ linux-3.3.x86_64/drivers/media/video/sr030pc30.c -@@ -864,18 +864,7 @@ static struct i2c_driver sr030pc30_i2c_d - .id_table = sr030pc30_id, - }; - --static int __init sr030pc30_init(void) --{ -- return i2c_add_driver(&sr030pc30_i2c_driver); --} -- --static void __exit sr030pc30_exit(void) --{ -- i2c_del_driver(&sr030pc30_i2c_driver); --} -- --module_init(sr030pc30_init); --module_exit(sr030pc30_exit); -+module_i2c_driver(sr030pc30_i2c_driver); - - MODULE_DESCRIPTION("Siliconfile SR030PC30 camera driver"); - MODULE_AUTHOR("Sylwester Nawrocki "); -Index: linux-3.3.x86_64/drivers/media/video/tda7432.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/tda7432.c -+++ linux-3.3.x86_64/drivers/media/video/tda7432.c -@@ -482,15 +482,4 @@ static struct i2c_driver tda7432_driver - .id_table = tda7432_id, - }; - --static __init int init_tda7432(void) --{ -- return i2c_add_driver(&tda7432_driver); --} -- --static __exit void exit_tda7432(void) --{ -- i2c_del_driver(&tda7432_driver); --} -- --module_init(init_tda7432); --module_exit(exit_tda7432); -+module_i2c_driver(tda7432_driver); -Index: linux-3.3.x86_64/drivers/media/video/tda9840.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/tda9840.c -+++ linux-3.3.x86_64/drivers/media/video/tda9840.c -@@ -208,15 +208,4 @@ static struct i2c_driver tda9840_driver - .id_table = tda9840_id, - }; - --static __init int init_tda9840(void) --{ -- return i2c_add_driver(&tda9840_driver); --} -- --static __exit void exit_tda9840(void) --{ -- i2c_del_driver(&tda9840_driver); --} -- --module_init(init_tda9840); --module_exit(exit_tda9840); -+module_i2c_driver(tda9840_driver); -Index: linux-3.3.x86_64/drivers/media/video/tea6415c.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/tea6415c.c -+++ linux-3.3.x86_64/drivers/media/video/tea6415c.c -@@ -184,15 +184,4 @@ static struct i2c_driver tea6415c_driver - .id_table = tea6415c_id, - }; - --static __init int init_tea6415c(void) --{ -- return i2c_add_driver(&tea6415c_driver); --} -- --static __exit void exit_tea6415c(void) --{ -- i2c_del_driver(&tea6415c_driver); --} -- --module_init(init_tea6415c); --module_exit(exit_tea6415c); -+module_i2c_driver(tea6415c_driver); -Index: linux-3.3.x86_64/drivers/media/video/tea6420.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/tea6420.c -+++ linux-3.3.x86_64/drivers/media/video/tea6420.c -@@ -166,15 +166,4 @@ static struct i2c_driver tea6420_driver - .id_table = tea6420_id, - }; - --static __init int init_tea6420(void) --{ -- return i2c_add_driver(&tea6420_driver); --} -- --static __exit void exit_tea6420(void) --{ -- i2c_del_driver(&tea6420_driver); --} -- --module_init(init_tea6420); --module_exit(exit_tea6420); -+module_i2c_driver(tea6420_driver); -Index: linux-3.3.x86_64/drivers/media/video/ths7303.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ths7303.c -+++ linux-3.3.x86_64/drivers/media/video/ths7303.c -@@ -137,16 +137,4 @@ static struct i2c_driver ths7303_driver - .id_table = ths7303_id, - }; - --static int __init ths7303_init(void) --{ -- return i2c_add_driver(&ths7303_driver); --} -- --static void __exit ths7303_exit(void) --{ -- i2c_del_driver(&ths7303_driver); --} -- --module_init(ths7303_init); --module_exit(ths7303_exit); -- -+module_i2c_driver(ths7303_driver); -Index: linux-3.3.x86_64/drivers/media/video/tlv320aic23b.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/tlv320aic23b.c -+++ linux-3.3.x86_64/drivers/media/video/tlv320aic23b.c -@@ -227,15 +227,4 @@ static struct i2c_driver tlv320aic23b_dr - .id_table = tlv320aic23b_id, - }; - --static __init int init_tlv320aic23b(void) --{ -- return i2c_add_driver(&tlv320aic23b_driver); --} -- --static __exit void exit_tlv320aic23b(void) --{ -- i2c_del_driver(&tlv320aic23b_driver); --} -- --module_init(init_tlv320aic23b); --module_exit(exit_tlv320aic23b); -+module_i2c_driver(tlv320aic23b_driver); -Index: linux-3.3.x86_64/drivers/media/video/tvaudio.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/tvaudio.c -+++ linux-3.3.x86_64/drivers/media/video/tvaudio.c -@@ -2078,15 +2078,4 @@ static struct i2c_driver tvaudio_driver - .id_table = tvaudio_id, - }; - --static __init int init_tvaudio(void) --{ -- return i2c_add_driver(&tvaudio_driver); --} -- --static __exit void exit_tvaudio(void) --{ -- i2c_del_driver(&tvaudio_driver); --} -- --module_init(init_tvaudio); --module_exit(exit_tvaudio); -+module_i2c_driver(tvaudio_driver); -Index: linux-3.3.x86_64/drivers/media/video/tvp514x.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/tvp514x.c -+++ linux-3.3.x86_64/drivers/media/video/tvp514x.c -@@ -1163,15 +1163,4 @@ static struct i2c_driver tvp514x_driver - .id_table = tvp514x_id, - }; - --static int __init tvp514x_init(void) --{ -- return i2c_add_driver(&tvp514x_driver); --} -- --static void __exit tvp514x_exit(void) --{ -- i2c_del_driver(&tvp514x_driver); --} -- --module_init(tvp514x_init); --module_exit(tvp514x_exit); -+module_i2c_driver(tvp514x_driver); -Index: linux-3.3.x86_64/drivers/media/video/tvp5150.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/tvp5150.c -+++ linux-3.3.x86_64/drivers/media/video/tvp5150.c -@@ -17,6 +17,13 @@ - - #include "tvp5150_reg.h" - -+#define TVP5150_H_MAX 720 -+#define TVP5150_V_MAX_525_60 480 -+#define TVP5150_V_MAX_OTHERS 576 -+#define TVP5150_MAX_CROP_LEFT 511 -+#define TVP5150_MAX_CROP_TOP 127 -+#define TVP5150_CROP_SHIFT 2 -+ - MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); - MODULE_AUTHOR("Mauro Carvalho Chehab"); - MODULE_LICENSE("GPL"); -@@ -29,6 +36,7 @@ MODULE_PARM_DESC(debug, "Debug level (0- - struct tvp5150 { - struct v4l2_subdev sd; - struct v4l2_ctrl_handler hdl; -+ struct v4l2_rect rect; - - v4l2_std_id norm; /* Current set standard */ - u32 input; -@@ -732,6 +740,13 @@ static int tvp5150_s_std(struct v4l2_sub - if (decoder->norm == std) - return 0; - -+ /* Change cropping height limits */ -+ if (std & V4L2_STD_525_60) -+ decoder->rect.height = TVP5150_V_MAX_525_60; -+ else -+ decoder->rect.height = TVP5150_V_MAX_OTHERS; -+ -+ - return tvp5150_set_std(sd, std); - } - -@@ -828,11 +843,8 @@ static int tvp5150_mbus_fmt(struct v4l2_ - else - std = decoder->norm; - -- f->width = 720; -- if (std & V4L2_STD_525_60) -- f->height = 480; -- else -- f->height = 576; -+ f->width = decoder->rect.width; -+ f->height = decoder->rect.height; - - f->code = V4L2_MBUS_FMT_YUYV8_2X8; - f->field = V4L2_FIELD_SEQ_TB; -@@ -843,6 +855,99 @@ static int tvp5150_mbus_fmt(struct v4l2_ - return 0; - } - -+static int tvp5150_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) -+{ -+ struct v4l2_rect rect = a->c; -+ struct tvp5150 *decoder = to_tvp5150(sd); -+ v4l2_std_id std; -+ int hmax; -+ -+ v4l2_dbg(1, debug, sd, "%s left=%d, top=%d, width=%d, height=%d\n", -+ __func__, rect.left, rect.top, rect.width, rect.height); -+ -+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ -+ /* tvp5150 has some special limits */ -+ rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT); -+ rect.width = clamp(rect.width, -+ TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect.left, -+ TVP5150_H_MAX - rect.left); -+ rect.top = clamp(rect.top, 0, TVP5150_MAX_CROP_TOP); -+ -+ /* Calculate height based on current standard */ -+ if (decoder->norm == V4L2_STD_ALL) -+ std = tvp5150_read_std(sd); -+ else -+ std = decoder->norm; -+ -+ if (std & V4L2_STD_525_60) -+ hmax = TVP5150_V_MAX_525_60; -+ else -+ hmax = TVP5150_V_MAX_OTHERS; -+ -+ rect.height = clamp(rect.height, -+ hmax - TVP5150_MAX_CROP_TOP - rect.top, -+ hmax - rect.top); -+ -+ tvp5150_write(sd, TVP5150_VERT_BLANKING_START, rect.top); -+ tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP, -+ rect.top + rect.height - hmax); -+ tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_MSB, -+ rect.left >> TVP5150_CROP_SHIFT); -+ tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_LSB, -+ rect.left | (1 << TVP5150_CROP_SHIFT)); -+ tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_MSB, -+ (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >> -+ TVP5150_CROP_SHIFT); -+ tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_LSB, -+ rect.left + rect.width - TVP5150_MAX_CROP_LEFT); -+ -+ decoder->rect = rect; -+ -+ return 0; -+} -+ -+static int tvp5150_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) -+{ -+ struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd); -+ -+ a->c = decoder->rect; -+ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ -+ return 0; -+} -+ -+static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) -+{ -+ struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd); -+ v4l2_std_id std; -+ -+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ -+ a->bounds.left = 0; -+ a->bounds.top = 0; -+ a->bounds.width = TVP5150_H_MAX; -+ -+ /* Calculate height based on current standard */ -+ if (decoder->norm == V4L2_STD_ALL) -+ std = tvp5150_read_std(sd); -+ else -+ std = decoder->norm; -+ -+ if (std & V4L2_STD_525_60) -+ a->bounds.height = TVP5150_V_MAX_525_60; -+ else -+ a->bounds.height = TVP5150_V_MAX_OTHERS; -+ -+ a->defrect = a->bounds; -+ a->pixelaspect.numerator = 1; -+ a->pixelaspect.denominator = 1; -+ -+ return 0; -+} -+ - /**************************************************************************** - I2C Command - ****************************************************************************/ -@@ -998,6 +1103,10 @@ static const struct v4l2_subdev_video_op - .enum_mbus_fmt = tvp5150_enum_mbus_fmt, - .s_mbus_fmt = tvp5150_mbus_fmt, - .try_mbus_fmt = tvp5150_mbus_fmt, -+ .g_mbus_fmt = tvp5150_mbus_fmt, -+ .s_crop = tvp5150_s_crop, -+ .g_crop = tvp5150_g_crop, -+ .cropcap = tvp5150_cropcap, - }; - - static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { -@@ -1083,6 +1192,15 @@ static int tvp5150_probe(struct i2c_clie - } - v4l2_ctrl_handler_setup(&core->hdl); - -+ /* Default is no cropping */ -+ core->rect.top = 0; -+ if (tvp5150_read_std(sd) & V4L2_STD_525_60) -+ core->rect.height = TVP5150_V_MAX_525_60; -+ else -+ core->rect.height = TVP5150_V_MAX_OTHERS; -+ core->rect.left = 0; -+ core->rect.width = TVP5150_H_MAX; -+ - if (debug > 1) - tvp5150_log_status(sd); - return 0; -@@ -1121,15 +1239,4 @@ static struct i2c_driver tvp5150_driver - .id_table = tvp5150_id, - }; - --static __init int init_tvp5150(void) --{ -- return i2c_add_driver(&tvp5150_driver); --} -- --static __exit void exit_tvp5150(void) --{ -- i2c_del_driver(&tvp5150_driver); --} -- --module_init(init_tvp5150); --module_exit(exit_tvp5150); -+module_i2c_driver(tvp5150_driver); -Index: linux-3.3.x86_64/drivers/media/video/tvp7002.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/tvp7002.c -+++ linux-3.3.x86_64/drivers/media/video/tvp7002.c -@@ -1069,27 +1069,4 @@ static struct i2c_driver tvp7002_driver - .id_table = tvp7002_id, - }; - --/* -- * tvp7002_init - Initialize driver via I2C interface -- * -- * Register the TVP7002 driver. -- * Return 0 on success or error code on failure. -- */ --static int __init tvp7002_init(void) --{ -- return i2c_add_driver(&tvp7002_driver); --} -- --/* -- * tvp7002_exit - Remove driver via I2C interface -- * -- * Unregister the TVP7002 driver. -- * Returns nothing. -- */ --static void __exit tvp7002_exit(void) --{ -- i2c_del_driver(&tvp7002_driver); --} -- --module_init(tvp7002_init); --module_exit(tvp7002_exit); -+module_i2c_driver(tvp7002_driver); -Index: linux-3.3.x86_64/drivers/media/video/tw9910.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/tw9910.c -+++ linux-3.3.x86_64/drivers/media/video/tw9910.c -@@ -951,21 +951,7 @@ static struct i2c_driver tw9910_i2c_driv - .id_table = tw9910_id, - }; - --/* -- * module function -- */ --static int __init tw9910_module_init(void) --{ -- return i2c_add_driver(&tw9910_i2c_driver); --} -- --static void __exit tw9910_module_exit(void) --{ -- i2c_del_driver(&tw9910_i2c_driver); --} -- --module_init(tw9910_module_init); --module_exit(tw9910_module_exit); -+module_i2c_driver(tw9910_i2c_driver); - - MODULE_DESCRIPTION("SoC Camera driver for tw9910"); - MODULE_AUTHOR("Kuninori Morimoto"); -Index: linux-3.3.x86_64/drivers/media/video/upd64031a.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/upd64031a.c -+++ linux-3.3.x86_64/drivers/media/video/upd64031a.c -@@ -271,15 +271,4 @@ static struct i2c_driver upd64031a_drive - .id_table = upd64031a_id, - }; - --static __init int init_upd64031a(void) --{ -- return i2c_add_driver(&upd64031a_driver); --} -- --static __exit void exit_upd64031a(void) --{ -- i2c_del_driver(&upd64031a_driver); --} -- --module_init(init_upd64031a); --module_exit(exit_upd64031a); -+module_i2c_driver(upd64031a_driver); -Index: linux-3.3.x86_64/drivers/media/video/upd64083.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/upd64083.c -+++ linux-3.3.x86_64/drivers/media/video/upd64083.c -@@ -243,15 +243,4 @@ static struct i2c_driver upd64083_driver - .id_table = upd64083_id, - }; - --static __init int init_upd64083(void) --{ -- return i2c_add_driver(&upd64083_driver); --} -- --static __exit void exit_upd64083(void) --{ -- i2c_del_driver(&upd64083_driver); --} -- --module_init(init_upd64083); --module_exit(exit_upd64083); -+module_i2c_driver(upd64083_driver); -Index: linux-3.3.x86_64/drivers/media/video/vp27smpx.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/vp27smpx.c -+++ linux-3.3.x86_64/drivers/media/video/vp27smpx.c -@@ -208,15 +208,4 @@ static struct i2c_driver vp27smpx_driver - .id_table = vp27smpx_id, - }; - --static __init int init_vp27smpx(void) --{ -- return i2c_add_driver(&vp27smpx_driver); --} -- --static __exit void exit_vp27smpx(void) --{ -- i2c_del_driver(&vp27smpx_driver); --} -- --module_init(init_vp27smpx); --module_exit(exit_vp27smpx); -+module_i2c_driver(vp27smpx_driver); -Index: linux-3.3.x86_64/drivers/media/video/vpx3220.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/vpx3220.c -+++ linux-3.3.x86_64/drivers/media/video/vpx3220.c -@@ -588,15 +588,4 @@ static struct i2c_driver vpx3220_driver - .id_table = vpx3220_id, - }; - --static __init int init_vpx3220(void) --{ -- return i2c_add_driver(&vpx3220_driver); --} -- --static __exit void exit_vpx3220(void) --{ -- i2c_del_driver(&vpx3220_driver); --} -- --module_init(init_vpx3220); --module_exit(exit_vpx3220); -+module_i2c_driver(vpx3220_driver); -Index: linux-3.3.x86_64/drivers/media/video/wm8739.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/wm8739.c -+++ linux-3.3.x86_64/drivers/media/video/wm8739.c -@@ -291,15 +291,4 @@ static struct i2c_driver wm8739_driver = - .id_table = wm8739_id, - }; - --static __init int init_wm8739(void) --{ -- return i2c_add_driver(&wm8739_driver); --} -- --static __exit void exit_wm8739(void) --{ -- i2c_del_driver(&wm8739_driver); --} -- --module_init(init_wm8739); --module_exit(exit_wm8739); -+module_i2c_driver(wm8739_driver); -Index: linux-3.3.x86_64/drivers/media/video/wm8775.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/wm8775.c -+++ linux-3.3.x86_64/drivers/media/video/wm8775.c -@@ -339,15 +339,4 @@ static struct i2c_driver wm8775_driver = - .id_table = wm8775_id, - }; - --static __init int init_wm8775(void) --{ -- return i2c_add_driver(&wm8775_driver); --} -- --static __exit void exit_wm8775(void) --{ -- i2c_del_driver(&wm8775_driver); --} -- --module_init(init_wm8775); --module_exit(exit_wm8775); -+module_i2c_driver(wm8775_driver); -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe-priv.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/it913x-fe-priv.h -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe-priv.h -@@ -201,6 +201,11 @@ fe_modulation_t fe_con[] = { - QAM_64, - }; - -+enum { -+ PRIORITY_HIGH = 0, /* High-priority stream */ -+ PRIORITY_LOW, /* Low-priority stream */ -+}; -+ - /* Standard demodulator functions */ - static struct it913xset set_solo_fe[] = { - {PRO_LINK, GPIOH5_EN, {0x01}, 0x01}, -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/it913x-fe.c -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe.c -@@ -57,6 +57,7 @@ struct it913x_fe_state { - u32 frequency; - fe_modulation_t constellation; - fe_transmit_mode_t transmission_mode; -+ u8 priority; - u32 crystalFrequency; - u32 adcFrequency; - u8 tuner_type; -@@ -500,19 +501,87 @@ static int it913x_fe_read_status(struct - return 0; - } - -+/* FEC values based on fe_code_rate_t non supported values 0*/ -+int it913x_qpsk_pval[] = {0, -93, -91, -90, 0, -89, -88}; -+int it913x_16qam_pval[] = {0, -87, -85, -84, 0, -83, -82}; -+int it913x_64qam_pval[] = {0, -82, -80, -78, 0, -77, -76}; -+ -+static int it913x_get_signal_strength(struct dvb_frontend *fe) -+{ -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ struct it913x_fe_state *state = fe->demodulator_priv; -+ u8 code_rate; -+ int ret, temp; -+ u8 lna_gain_os; -+ -+ ret = it913x_read_reg_u8(state, VAR_P_INBAND); -+ if (ret < 0) -+ return ret; -+ -+ /* VHF/UHF gain offset */ -+ if (state->frequency < 300000000) -+ lna_gain_os = 7; -+ else -+ lna_gain_os = 14; -+ -+ temp = (ret - 100) - lna_gain_os; -+ -+ if (state->priority == PRIORITY_HIGH) -+ code_rate = p->code_rate_HP; -+ else -+ code_rate = p->code_rate_LP; -+ -+ if (code_rate >= ARRAY_SIZE(it913x_qpsk_pval)) -+ return -EINVAL; -+ -+ deb_info("Reg VAR_P_INBAND:%d Calc Offset Value:%d", ret, temp); -+ -+ /* Apply FEC offset values*/ -+ switch (p->modulation) { -+ case QPSK: -+ temp -= it913x_qpsk_pval[code_rate]; -+ break; -+ case QAM_16: -+ temp -= it913x_16qam_pval[code_rate]; -+ break; -+ case QAM_64: -+ temp -= it913x_64qam_pval[code_rate]; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ if (temp < -15) -+ ret = 0; -+ else if ((-15 <= temp) && (temp < 0)) -+ ret = (2 * (temp + 15)) / 3; -+ else if ((0 <= temp) && (temp < 20)) -+ ret = 4 * temp + 10; -+ else if ((20 <= temp) && (temp < 35)) -+ ret = (2 * (temp - 20)) / 3 + 90; -+ else if (temp >= 35) -+ ret = 100; -+ -+ deb_info("Signal Strength :%d", ret); -+ -+ return ret; -+} -+ - static int it913x_fe_read_signal_strength(struct dvb_frontend *fe, - u16 *strength) - { - struct it913x_fe_state *state = fe->demodulator_priv; -- int ret = it913x_read_reg_u8(state, SIGNAL_LEVEL); -- /*SIGNAL_LEVEL always returns 100%! so using FE_HAS_SIGNAL as switch*/ -- if (state->it913x_status & FE_HAS_SIGNAL) -- ret = (ret * 0xff) / 0x64; -- else -- ret = 0x0; -- ret |= ret << 0x8; -- *strength = ret; -- return 0; -+ int ret = 0; -+ if (state->config->read_slevel) { -+ if (state->it913x_status & FE_HAS_SIGNAL) -+ ret = it913x_read_reg_u8(state, SIGNAL_LEVEL); -+ } else -+ ret = it913x_get_signal_strength(fe); -+ -+ if (ret >= 0) -+ *strength = (u16)((u32)ret * 0xffff / 0x64); -+ -+ return (ret < 0) ? -ENODEV : 0; - } - - static int it913x_fe_read_snr(struct dvb_frontend *fe, u16 *snr) -@@ -606,6 +675,8 @@ static int it913x_fe_get_frontend(struct - if (reg[2] < 4) - p->hierarchy = fe_hi[reg[2]]; - -+ state->priority = reg[5]; -+ - p->code_rate_HP = (reg[6] < 6) ? fe_code[reg[6]] : FEC_NONE; - p->code_rate_LP = (reg[7] < 6) ? fe_code[reg[7]] : FEC_NONE; - -@@ -972,5 +1043,5 @@ static struct dvb_frontend_ops it913x_fe - - MODULE_DESCRIPTION("it913x Frontend and it9137 tuner"); - MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); --MODULE_VERSION("1.13"); -+MODULE_VERSION("1.15"); - MODULE_LICENSE("GPL"); -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/it913x-fe.h -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/it913x-fe.h -@@ -34,6 +34,8 @@ struct ite_config { - u8 tuner_id_1; - u8 dual_mode; - u8 adf; -+ /* option to read SIGNAL_LEVEL */ -+ u8 read_slevel; - }; - - #if defined(CONFIG_DVB_IT913X_FE) || (defined(CONFIG_DVB_IT913X_FE_MODULE) && \ -@@ -168,6 +170,8 @@ static inline struct dvb_frontend *it913 - #define EST_SIGNAL_LEVEL 0x004a - #define FREE_BAND 0x004b - #define SUSPEND_FLAG 0x004c -+#define VAR_P_INBAND 0x00f7 -+ - /* Build in tuner types */ - #define IT9137 0x38 - #define IT9135_38 0x38 -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/cx22702.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/cx22702.c -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/cx22702.c -@@ -502,10 +502,26 @@ static int cx22702_read_signal_strength( - u16 *signal_strength) - { - struct cx22702_state *state = fe->demodulator_priv; -+ u8 reg23; - -- u16 rs_ber; -- rs_ber = cx22702_readreg(state, 0x23); -- *signal_strength = (rs_ber << 8) | rs_ber; -+ /* -+ * Experience suggests that the strength signal register works as -+ * follows: -+ * - In the absence of signal, value is 0xff. -+ * - In the presence of a weak signal, bit 7 is set, not sure what -+ * the lower 7 bits mean. -+ * - In the presence of a strong signal, the register holds a 7-bit -+ * value (bit 7 is cleared), with greater values standing for -+ * weaker signals. -+ */ -+ reg23 = cx22702_readreg(state, 0x23); -+ if (reg23 & 0x80) { -+ *signal_strength = 0; -+ } else { -+ reg23 = ~reg23 & 0x7f; -+ /* Scale to 16 bit */ -+ *signal_strength = (reg23 << 9) | (reg23 << 2) | (reg23 >> 5); -+ } - - return 0; - } -Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-cards.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx-cards.c -+++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-cards.c -@@ -353,6 +353,44 @@ static struct em28xx_reg_seq hauppauge_9 - }; - #endif - -+/* 1b80:e425 MaxMedia UB425-TC -+ * GPIO_6 - demod reset, 0=active -+ * GPIO_7 - LED, 0=active -+ */ -+static struct em28xx_reg_seq maxmedia_ub425_tc[] = { -+ {EM2874_R80_GPIO, 0x83, 0xff, 100}, -+ {EM2874_R80_GPIO, 0xc3, 0xff, 100}, /* GPIO_6 = 1 */ -+ {EM2874_R80_GPIO, 0x43, 0xff, 000}, /* GPIO_7 = 0 */ -+ {-1, -1, -1, -1}, -+}; -+ -+/* 2304:0242 PCTV QuatroStick (510e) -+ * GPIO_2: decoder reset, 0=active -+ * GPIO_4: decoder suspend, 0=active -+ * GPIO_6: demod reset, 0=active -+ * GPIO_7: LED, 1=active -+ */ -+static struct em28xx_reg_seq pctv_510e[] = { -+ {EM2874_R80_GPIO, 0x10, 0xff, 100}, -+ {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ -+ {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ -+ { -1, -1, -1, -1}, -+}; -+ -+/* 2013:0251 PCTV QuatroStick nano (520e) -+ * GPIO_2: decoder reset, 0=active -+ * GPIO_4: decoder suspend, 0=active -+ * GPIO_6: demod reset, 0=active -+ * GPIO_7: LED, 1=active -+ */ -+static struct em28xx_reg_seq pctv_520e[] = { -+ {EM2874_R80_GPIO, 0x10, 0xff, 100}, -+ {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ -+ {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ -+ {EM2874_R80_GPIO, 0xd4, 0xff, 000}, /* GPIO_7 = 1 */ -+ { -1, -1, -1, -1}, -+}; -+ - /* - * Board definitions - */ -@@ -1908,6 +1946,41 @@ struct em28xx_board em28xx_boards[] = { - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, -+ /* 1b80:e425 MaxMedia UB425-TC -+ * Empia EM2874B + Micronas DRX 3913KA2 + NXP TDA18271HDC2 */ -+ [EM2874_BOARD_MAXMEDIA_UB425_TC] = { -+ .name = "MaxMedia UB425-TC", -+ .tuner_type = TUNER_ABSENT, -+ .tuner_gpio = maxmedia_ub425_tc, -+ .has_dvb = 1, -+ .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | -+ EM28XX_I2C_CLK_WAIT_ENABLE | -+ EM28XX_I2C_FREQ_400_KHZ, -+ }, -+ /* 2304:0242 PCTV QuatroStick (510e) -+ * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */ -+ [EM2884_BOARD_PCTV_510E] = { -+ .name = "PCTV QuatroStick (510e)", -+ .tuner_type = TUNER_ABSENT, -+ .tuner_gpio = pctv_510e, -+ .has_dvb = 1, -+ .ir_codes = RC_MAP_PINNACLE_PCTV_HD, -+ .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | -+ EM28XX_I2C_CLK_WAIT_ENABLE | -+ EM28XX_I2C_FREQ_400_KHZ, -+ }, -+ /* 2013:0251 PCTV QuatroStick nano (520e) -+ * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */ -+ [EM2884_BOARD_PCTV_520E] = { -+ .name = "PCTV QuatroStick nano (520e)", -+ .tuner_type = TUNER_ABSENT, -+ .tuner_gpio = pctv_520e, -+ .has_dvb = 1, -+ .ir_codes = RC_MAP_PINNACLE_PCTV_HD, -+ .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | -+ EM28XX_I2C_CLK_WAIT_ENABLE | -+ EM28XX_I2C_FREQ_400_KHZ, -+ }, - }; - const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); - -@@ -2059,6 +2132,12 @@ struct usb_device_id em28xx_id_table[] = - .driver_info = EM2860_BOARD_HT_VIDBOX_NW03 }, - { USB_DEVICE(0x1b80, 0xe309), /* Sveon STV40 */ - .driver_info = EM2860_BOARD_EASYCAP }, -+ { USB_DEVICE(0x1b80, 0xe425), -+ .driver_info = EM2874_BOARD_MAXMEDIA_UB425_TC }, -+ { USB_DEVICE(0x2304, 0x0242), -+ .driver_info = EM2884_BOARD_PCTV_510E }, -+ { USB_DEVICE(0x2013, 0x0251), -+ .driver_info = EM2884_BOARD_PCTV_520E }, - { }, - }; - MODULE_DEVICE_TABLE(usb, em28xx_id_table); -@@ -3122,7 +3201,6 @@ static int em28xx_usb_probe(struct usb_i - int i, nr; - const int ifnum = interface->altsetting[0].desc.bInterfaceNumber; - char *speed; -- char descr[255] = ""; - - udev = usb_get_dev(interface_to_usbdev(interface)); - -@@ -3227,21 +3305,11 @@ static int em28xx_usb_probe(struct usb_i - speed = "unknown"; - } - -- if (udev->manufacturer) -- strlcpy(descr, udev->manufacturer, sizeof(descr)); -- -- if (udev->product) { -- if (*descr) -- strlcat(descr, " ", sizeof(descr)); -- strlcat(descr, udev->product, sizeof(descr)); -- } -- -- if (*descr) -- strlcat(descr, " ", sizeof(descr)); -- - printk(KERN_INFO DRIVER_NAME -- ": New device %s@ %s Mbps (%04x:%04x, interface %d, class %d)\n", -- descr, -+ ": New device %s %s @ %s Mbps " -+ "(%04x:%04x, interface %d, class %d)\n", -+ udev->manufacturer ? udev->manufacturer : "", -+ udev->product ? udev->product : "", - speed, - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), -@@ -3307,6 +3375,17 @@ static int em28xx_usb_probe(struct usb_i - goto unlock_and_free; - } - -+ if (has_dvb) { -+ /* pre-allocate DVB isoc transfer buffers */ -+ retval = em28xx_alloc_isoc(dev, EM28XX_DIGITAL_MODE, -+ EM28XX_DVB_MAX_PACKETS, -+ EM28XX_DVB_NUM_BUFS, -+ dev->dvb_max_pkt_size); -+ if (retval) { -+ goto unlock_and_free; -+ } -+ } -+ - request_modules(dev); - - /* Should be the last thing to do, to avoid newer udev's to -@@ -3379,7 +3458,7 @@ static void em28xx_usb_disconnect(struct - video_device_node_name(dev->vdev)); - - dev->state |= DEV_MISCONFIGURED; -- em28xx_uninit_isoc(dev); -+ em28xx_uninit_isoc(dev, dev->mode); - dev->state |= DEV_DISCONNECTED; - wake_up_interruptible(&dev->wait_frame); - wake_up_interruptible(&dev->wait_stream); -@@ -3388,6 +3467,9 @@ static void em28xx_usb_disconnect(struct - em28xx_release_resources(dev); - } - -+ /* free DVB isoc buffers */ -+ em28xx_uninit_isoc(dev, EM28XX_DIGITAL_MODE); -+ - mutex_unlock(&dev->lock); - - em28xx_close_extension(dev); -Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-core.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx-core.c -+++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-core.c -@@ -666,6 +666,7 @@ int em28xx_capture_start(struct em28xx * - - return rc; - } -+EXPORT_SYMBOL_GPL(em28xx_capture_start); - - int em28xx_vbi_supported(struct em28xx *dev) - { -@@ -961,146 +962,192 @@ static void em28xx_irq_callback(struct u - /* - * Stop and Deallocate URBs - */ --void em28xx_uninit_isoc(struct em28xx *dev) -+void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode) - { - struct urb *urb; -+ struct em28xx_usb_isoc_bufs *isoc_bufs; - int i; - -- em28xx_isocdbg("em28xx: called em28xx_uninit_isoc\n"); -+ em28xx_isocdbg("em28xx: called em28xx_uninit_isoc in mode %d\n", mode); -+ -+ if (mode == EM28XX_DIGITAL_MODE) -+ isoc_bufs = &dev->isoc_ctl.digital_bufs; -+ else -+ isoc_bufs = &dev->isoc_ctl.analog_bufs; - - dev->isoc_ctl.nfields = -1; -- for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { -- urb = dev->isoc_ctl.urb[i]; -+ for (i = 0; i < isoc_bufs->num_bufs; i++) { -+ urb = isoc_bufs->urb[i]; - if (urb) { - if (!irqs_disabled()) - usb_kill_urb(urb); - else - usb_unlink_urb(urb); - -- if (dev->isoc_ctl.transfer_buffer[i]) { -+ if (isoc_bufs->transfer_buffer[i]) { - usb_free_coherent(dev->udev, - urb->transfer_buffer_length, -- dev->isoc_ctl.transfer_buffer[i], -+ isoc_bufs->transfer_buffer[i], - urb->transfer_dma); - } - usb_free_urb(urb); -- dev->isoc_ctl.urb[i] = NULL; -+ isoc_bufs->urb[i] = NULL; - } -- dev->isoc_ctl.transfer_buffer[i] = NULL; -+ isoc_bufs->transfer_buffer[i] = NULL; - } - -- kfree(dev->isoc_ctl.urb); -- kfree(dev->isoc_ctl.transfer_buffer); -+ kfree(isoc_bufs->urb); -+ kfree(isoc_bufs->transfer_buffer); - -- dev->isoc_ctl.urb = NULL; -- dev->isoc_ctl.transfer_buffer = NULL; -- dev->isoc_ctl.num_bufs = 0; -+ isoc_bufs->urb = NULL; -+ isoc_bufs->transfer_buffer = NULL; -+ isoc_bufs->num_bufs = 0; - - em28xx_capture_start(dev, 0); - } - EXPORT_SYMBOL_GPL(em28xx_uninit_isoc); - - /* -- * Allocate URBs and start IRQ -+ * Allocate URBs - */ --int em28xx_init_isoc(struct em28xx *dev, int max_packets, -- int num_bufs, int max_pkt_size, -- int (*isoc_copy) (struct em28xx *dev, struct urb *urb)) -+int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode, -+ int max_packets, int num_bufs, int max_pkt_size) - { -- struct em28xx_dmaqueue *dma_q = &dev->vidq; -- struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; -+ struct em28xx_usb_isoc_bufs *isoc_bufs; - int i; - int sb_size, pipe; - struct urb *urb; - int j, k; -- int rc; - -- em28xx_isocdbg("em28xx: called em28xx_prepare_isoc\n"); -+ em28xx_isocdbg("em28xx: called em28xx_alloc_isoc in mode %d\n", mode); -+ -+ if (mode == EM28XX_DIGITAL_MODE) -+ isoc_bufs = &dev->isoc_ctl.digital_bufs; -+ else -+ isoc_bufs = &dev->isoc_ctl.analog_bufs; - - /* De-allocates all pending stuff */ -- em28xx_uninit_isoc(dev); -+ em28xx_uninit_isoc(dev, mode); - -- dev->isoc_ctl.isoc_copy = isoc_copy; -- dev->isoc_ctl.num_bufs = num_bufs; -+ isoc_bufs->num_bufs = num_bufs; - -- dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); -- if (!dev->isoc_ctl.urb) { -+ isoc_bufs->urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); -+ if (!isoc_bufs->urb) { - em28xx_errdev("cannot alloc memory for usb buffers\n"); - return -ENOMEM; - } - -- dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, -- GFP_KERNEL); -- if (!dev->isoc_ctl.transfer_buffer) { -+ isoc_bufs->transfer_buffer = kzalloc(sizeof(void *)*num_bufs, -+ GFP_KERNEL); -+ if (!isoc_bufs->transfer_buffer) { - em28xx_errdev("cannot allocate memory for usb transfer\n"); -- kfree(dev->isoc_ctl.urb); -+ kfree(isoc_bufs->urb); - return -ENOMEM; - } - -- dev->isoc_ctl.max_pkt_size = max_pkt_size; -+ isoc_bufs->max_pkt_size = max_pkt_size; -+ isoc_bufs->num_packets = max_packets; - dev->isoc_ctl.vid_buf = NULL; - dev->isoc_ctl.vbi_buf = NULL; - -- sb_size = max_packets * dev->isoc_ctl.max_pkt_size; -+ sb_size = isoc_bufs->num_packets * isoc_bufs->max_pkt_size; - - /* allocate urbs and transfer buffers */ -- for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { -- urb = usb_alloc_urb(max_packets, GFP_KERNEL); -+ for (i = 0; i < isoc_bufs->num_bufs; i++) { -+ urb = usb_alloc_urb(isoc_bufs->num_packets, GFP_KERNEL); - if (!urb) { - em28xx_err("cannot alloc isoc_ctl.urb %i\n", i); -- em28xx_uninit_isoc(dev); -+ em28xx_uninit_isoc(dev, mode); - return -ENOMEM; - } -- dev->isoc_ctl.urb[i] = urb; -+ isoc_bufs->urb[i] = urb; - -- dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev, -+ isoc_bufs->transfer_buffer[i] = usb_alloc_coherent(dev->udev, - sb_size, GFP_KERNEL, &urb->transfer_dma); -- if (!dev->isoc_ctl.transfer_buffer[i]) { -+ if (!isoc_bufs->transfer_buffer[i]) { - em28xx_err("unable to allocate %i bytes for transfer" - " buffer %i%s\n", - sb_size, i, - in_interrupt() ? " while in int" : ""); -- em28xx_uninit_isoc(dev); -+ em28xx_uninit_isoc(dev, mode); - return -ENOMEM; - } -- memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); -+ memset(isoc_bufs->transfer_buffer[i], 0, sb_size); - - /* FIXME: this is a hack - should be - 'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK' - should also be using 'desc.bInterval' - */ - pipe = usb_rcvisocpipe(dev->udev, -- dev->mode == EM28XX_ANALOG_MODE ? -+ mode == EM28XX_ANALOG_MODE ? - EM28XX_EP_ANALOG : EM28XX_EP_DIGITAL); - - usb_fill_int_urb(urb, dev->udev, pipe, -- dev->isoc_ctl.transfer_buffer[i], sb_size, -+ isoc_bufs->transfer_buffer[i], sb_size, - em28xx_irq_callback, dev, 1); - -- urb->number_of_packets = max_packets; -+ urb->number_of_packets = isoc_bufs->num_packets; - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; - - k = 0; -- for (j = 0; j < max_packets; j++) { -+ for (j = 0; j < isoc_bufs->num_packets; j++) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = -- dev->isoc_ctl.max_pkt_size; -- k += dev->isoc_ctl.max_pkt_size; -+ isoc_bufs->max_pkt_size; -+ k += isoc_bufs->max_pkt_size; - } - } - -+ return 0; -+} -+EXPORT_SYMBOL_GPL(em28xx_alloc_isoc); -+ -+/* -+ * Allocate URBs and start IRQ -+ */ -+int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode, -+ int max_packets, int num_bufs, int max_pkt_size, -+ int (*isoc_copy) (struct em28xx *dev, struct urb *urb)) -+{ -+ struct em28xx_dmaqueue *dma_q = &dev->vidq; -+ struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; -+ struct em28xx_usb_isoc_bufs *isoc_bufs; -+ int i; -+ int rc; -+ int alloc; -+ -+ em28xx_isocdbg("em28xx: called em28xx_init_isoc in mode %d\n", mode); -+ -+ dev->isoc_ctl.isoc_copy = isoc_copy; -+ -+ if (mode == EM28XX_DIGITAL_MODE) { -+ isoc_bufs = &dev->isoc_ctl.digital_bufs; -+ /* no need to free/alloc isoc buffers in digital mode */ -+ alloc = 0; -+ } else { -+ isoc_bufs = &dev->isoc_ctl.analog_bufs; -+ alloc = 1; -+ } -+ -+ if (alloc) { -+ rc = em28xx_alloc_isoc(dev, mode, max_packets, -+ num_bufs, max_pkt_size); -+ if (rc) -+ return rc; -+ } -+ - init_waitqueue_head(&dma_q->wq); - init_waitqueue_head(&vbi_dma_q->wq); - - em28xx_capture_start(dev, 1); - - /* submit urbs and enables IRQ */ -- for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { -- rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); -+ for (i = 0; i < isoc_bufs->num_bufs; i++) { -+ rc = usb_submit_urb(isoc_bufs->urb[i], GFP_ATOMIC); - if (rc) { - em28xx_err("submit of urb %i failed (error=%i)\n", i, - rc); -- em28xx_uninit_isoc(dev); -+ em28xx_uninit_isoc(dev, mode); - return rc; - } - } -Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-dvb.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx-dvb.c -+++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-dvb.c -@@ -61,9 +61,6 @@ if (debug >= level) \ - printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \ - } while (0) - --#define EM28XX_DVB_NUM_BUFS 5 --#define EM28XX_DVB_MAX_PACKETS 64 -- - struct em28xx_dvb { - struct dvb_frontend *fe[2]; - -@@ -172,20 +169,21 @@ static int em28xx_start_streaming(struct - max_dvb_packet_size = dev->dvb_max_pkt_size; - if (max_dvb_packet_size < 0) - return max_dvb_packet_size; -- dprintk(1, "Using %d buffers each with %d bytes\n", -+ dprintk(1, "Using %d buffers each with %d x %d bytes\n", - EM28XX_DVB_NUM_BUFS, -+ EM28XX_DVB_MAX_PACKETS, - max_dvb_packet_size); - -- return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS, -- EM28XX_DVB_NUM_BUFS, max_dvb_packet_size, -- em28xx_dvb_isoc_copy); -+ return em28xx_init_isoc(dev, EM28XX_DIGITAL_MODE, -+ EM28XX_DVB_MAX_PACKETS, EM28XX_DVB_NUM_BUFS, -+ max_dvb_packet_size, em28xx_dvb_isoc_copy); - } - - static int em28xx_stop_streaming(struct em28xx_dvb *dvb) - { - struct em28xx *dev = dvb->adapter.priv; - -- em28xx_uninit_isoc(dev); -+ em28xx_capture_start(dev, 0); - - em28xx_set_mode(dev, EM28XX_SUSPEND); - -@@ -327,6 +325,19 @@ struct drxk_config hauppauge_930c_drxk = - .chunk_size = 56, - }; - -+struct drxk_config maxmedia_ub425_tc_drxk = { -+ .adr = 0x29, -+ .single_master = 1, -+ .no_i2c_bridge = 1, -+}; -+ -+struct drxk_config pctv_520e_drxk = { -+ .adr = 0x29, -+ .single_master = 1, -+ .microcode_name = "dvb-demod-drxk-pctv.fw", -+ .chunk_size = 58, -+}; -+ - static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) - { - struct em28xx_dvb *dvb = fe->sec_priv; -@@ -460,6 +471,33 @@ static void terratec_h5_init(struct em28 - em28xx_gpio_set(dev, terratec_h5_end); - }; - -+static void pctv_520e_init(struct em28xx *dev) -+{ -+ /* -+ * Init TDA8295(?) analog demodulator. Looks like I2C traffic to -+ * digital demodulator and tuner are routed via TDA8295. -+ */ -+ int i; -+ struct { -+ unsigned char r[4]; -+ int len; -+ } regs[] = { -+ {{ 0x06, 0x02, 0x00, 0x31 }, 4}, -+ {{ 0x01, 0x02 }, 2}, -+ {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, -+ {{ 0x01, 0x00 }, 2}, -+ {{ 0x01, 0x00, 0xff, 0xaf }, 4}, -+ {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, -+ {{ 0x01, 0x00 }, 2}, -+ {{ 0x01, 0x00, 0x73, 0xaf }, 4}, -+ }; -+ -+ dev->i2c_client.addr = 0x82 >> 1; /* 0x41 */ -+ -+ for (i = 0; i < ARRAY_SIZE(regs); i++) -+ i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); -+}; -+ - static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe) - { - /* Values extracted from a USB trace of the Terratec Windows driver */ -@@ -938,6 +976,48 @@ static int em28xx_dvb_init(struct em28xx - dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap, - &em28xx_a8293_config); - break; -+ case EM2874_BOARD_MAXMEDIA_UB425_TC: -+ /* attach demodulator */ -+ dvb->fe[0] = dvb_attach(drxk_attach, &maxmedia_ub425_tc_drxk, -+ &dev->i2c_adap); -+ -+ if (dvb->fe[0]) { -+ /* disable I2C-gate */ -+ dvb->fe[0]->ops.i2c_gate_ctrl = NULL; -+ -+ /* attach tuner */ -+ if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], -+ &dev->i2c_adap, 0x60)) { -+ dvb_frontend_detach(dvb->fe[0]); -+ result = -EINVAL; -+ goto out_free; -+ } -+ } -+ -+ /* TODO: we need drx-3913k firmware in order to support DVB-T */ -+ em28xx_info("MaxMedia UB425-TC: only DVB-C supported by that " \ -+ "driver version\n"); -+ -+ break; -+ case EM2884_BOARD_PCTV_510E: -+ case EM2884_BOARD_PCTV_520E: -+ pctv_520e_init(dev); -+ -+ /* attach demodulator */ -+ dvb->fe[0] = dvb_attach(drxk_attach, &pctv_520e_drxk, -+ &dev->i2c_adap); -+ -+ if (dvb->fe[0]) { -+ /* attach tuner */ -+ if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, -+ &dev->i2c_adap, -+ &em28xx_cxd2820r_tda18271_config)) { -+ dvb_frontend_detach(dvb->fe[0]); -+ result = -EINVAL; -+ goto out_free; -+ } -+ } -+ break; - default: - em28xx_errdev("/2: The frontend of your DVB/ATSC card" - " isn't supported yet\n"); -Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-video.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx-video.c -+++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-video.c -@@ -760,17 +760,19 @@ buffer_prepare(struct videobuf_queue *vq - goto fail; - } - -- if (!dev->isoc_ctl.num_bufs) -+ if (!dev->isoc_ctl.analog_bufs.num_bufs) - urb_init = 1; - - if (urb_init) { - if (em28xx_vbi_supported(dev) == 1) -- rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS, -+ rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE, -+ EM28XX_NUM_PACKETS, - EM28XX_NUM_BUFS, - dev->max_pkt_size, - em28xx_isoc_copy_vbi); - else -- rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS, -+ rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE, -+ EM28XX_NUM_PACKETS, - EM28XX_NUM_BUFS, - dev->max_pkt_size, - em28xx_isoc_copy); -@@ -2267,7 +2269,7 @@ static int em28xx_v4l2_close(struct file - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); - - /* do this before setting alternate! */ -- em28xx_uninit_isoc(dev); -+ em28xx_uninit_isoc(dev, EM28XX_ANALOG_MODE); - em28xx_set_mode(dev, EM28XX_SUSPEND); - - /* set alternate 0 */ -Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx.h -+++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx.h -@@ -125,6 +125,9 @@ - #define EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C 81 - #define EM2884_BOARD_CINERGY_HTC_STICK 82 - #define EM2860_BOARD_HT_VIDBOX_NW03 83 -+#define EM2874_BOARD_MAXMEDIA_UB425_TC 84 -+#define EM2884_BOARD_PCTV_510E 85 -+#define EM2884_BOARD_PCTV_520E 86 - - /* Limits minimum and default number of buffers */ - #define EM28XX_MIN_BUF 4 -@@ -151,12 +154,14 @@ - - /* number of buffers for isoc transfers */ - #define EM28XX_NUM_BUFS 5 -+#define EM28XX_DVB_NUM_BUFS 5 - - /* number of packets for each buffer - windows requests only 64 packets .. so we better do the same - this is what I found out for all alternate numbers there! - */ - #define EM28XX_NUM_PACKETS 64 -+#define EM28XX_DVB_MAX_PACKETS 64 - - #define EM28XX_INTERLACED_DEFAULT 1 - -@@ -197,10 +202,13 @@ enum em28xx_mode { - - struct em28xx; - --struct em28xx_usb_isoc_ctl { -+struct em28xx_usb_isoc_bufs { - /* max packet size of isoc transaction */ - int max_pkt_size; - -+ /* number of packets in each buffer */ -+ int num_packets; -+ - /* number of allocated urbs */ - int num_bufs; - -@@ -209,6 +217,14 @@ struct em28xx_usb_isoc_ctl { - - /* transfer buffers for isoc transfer */ - char **transfer_buffer; -+}; -+ -+struct em28xx_usb_isoc_ctl { -+ /* isoc transfer buffers for analog mode */ -+ struct em28xx_usb_isoc_bufs analog_bufs; -+ -+ /* isoc transfer buffers for digital mode */ -+ struct em28xx_usb_isoc_bufs digital_bufs; - - /* Last buffer command and region */ - u8 cmd; -@@ -600,9 +616,6 @@ struct em28xx { - unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ - int dvb_alt; /* alternate for DVB */ - unsigned int dvb_max_pkt_size; /* wMaxPacketSize for DVB */ -- struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ -- char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc -- transfer */ - char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ - - /* helper funcs that call usb_control_msg */ -@@ -676,10 +689,12 @@ int em28xx_vbi_supported(struct em28xx * - int em28xx_set_outfmt(struct em28xx *dev); - int em28xx_resolution_set(struct em28xx *dev); - int em28xx_set_alternate(struct em28xx *dev); --int em28xx_init_isoc(struct em28xx *dev, int max_packets, -- int num_bufs, int max_pkt_size, -+int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode, -+ int max_packets, int num_bufs, int max_pkt_size); -+int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode, -+ int max_packets, int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct em28xx *dev, struct urb *urb)); --void em28xx_uninit_isoc(struct em28xx *dev); -+void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode); - int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev); - int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode); - int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); -Index: linux-3.3.x86_64/drivers/media/video/mx2_camera.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/mx2_camera.c -+++ linux-3.3.x86_64/drivers/media/video/mx2_camera.c -@@ -3,6 +3,7 @@ - * - * Copyright (C) 2008, Sascha Hauer, Pengutronix - * Copyright (C) 2010, Baruch Siach, Orex Computed Radiography -+ * Copyright (C) 2012, Javier Martin, Vista Silicon S.L. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -18,6 +19,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -30,17 +32,14 @@ - - #include - #include --#include --#include -+#include -+#include - #include - #include - - #include - - #include --#ifdef CONFIG_MACH_MX27 --#include --#endif - #include - - #include -@@ -206,10 +205,23 @@ - #define PRP_INTR_LBOVF (1 << 7) - #define PRP_INTR_CH2OVF (1 << 8) - --#define mx27_camera_emma(pcdev) (cpu_is_mx27() && pcdev->use_emma) -+/* Resizing registers */ -+#define PRP_RZ_VALID_TBL_LEN(x) ((x) << 24) -+#define PRP_RZ_VALID_BILINEAR (1 << 31) - - #define MAX_VIDEO_MEM 16 - -+#define RESIZE_NUM_MIN 1 -+#define RESIZE_NUM_MAX 20 -+#define BC_COEF 3 -+#define SZ_COEF (1 << BC_COEF) -+ -+#define RESIZE_DIR_H 0 -+#define RESIZE_DIR_V 1 -+ -+#define RESIZE_ALGO_BILINEAR 0 -+#define RESIZE_ALGO_AVERAGING 1 -+ - struct mx2_prp_cfg { - int channel; - u32 in_fmt; -@@ -219,6 +231,13 @@ struct mx2_prp_cfg { - u32 irq_flags; - }; - -+/* prp resizing parameters */ -+struct emma_prp_resize { -+ int algo; /* type of algorithm used */ -+ int len; /* number of coefficients */ -+ unsigned char s[RESIZE_NUM_MAX]; /* table of coefficients */ -+}; -+ - /* prp configuration for a client-host fmt pair */ - struct mx2_fmt_cfg { - enum v4l2_mbus_pixelcode in_fmt; -@@ -226,6 +245,26 @@ struct mx2_fmt_cfg { - struct mx2_prp_cfg cfg; - }; - -+enum mx2_buffer_state { -+ MX2_STATE_QUEUED, -+ MX2_STATE_ACTIVE, -+ MX2_STATE_DONE, -+}; -+ -+struct mx2_buf_internal { -+ struct list_head queue; -+ int bufnum; -+ bool discard; -+}; -+ -+/* buffer for one video frame */ -+struct mx2_buffer { -+ /* common v4l buffer stuff -- must be first */ -+ struct vb2_buffer vb; -+ enum mx2_buffer_state state; -+ struct mx2_buf_internal internal; -+}; -+ - struct mx2_camera_dev { - struct device *dev; - struct soc_camera_host soc_host; -@@ -242,6 +281,7 @@ struct mx2_camera_dev { - - struct list_head capture; - struct list_head active_bufs; -+ struct list_head discard; - - spinlock_t lock; - -@@ -250,26 +290,23 @@ struct mx2_camera_dev { - struct mx2_buffer *fb1_active; - struct mx2_buffer *fb2_active; - -- int use_emma; -- - u32 csicr1; - -+ struct mx2_buf_internal buf_discard[2]; - void *discard_buffer; - dma_addr_t discard_buffer_dma; - size_t discard_size; - struct mx2_fmt_cfg *emma_prp; -+ struct emma_prp_resize resizing[2]; -+ unsigned int s_width, s_height; - u32 frame_count; -+ struct vb2_alloc_ctx *alloc_ctx; - }; - --/* buffer for one video frame */ --struct mx2_buffer { -- /* common v4l buffer stuff -- must be first */ -- struct videobuf_buffer vb; -- -- enum v4l2_mbus_pixelcode code; -- -- int bufnum; --}; -+static struct mx2_buffer *mx2_ibuf_to_buf(struct mx2_buf_internal *int_buf) -+{ -+ return container_of(int_buf, struct mx2_buffer, internal); -+} - - static struct mx2_fmt_cfg mx27_emma_prp_table[] = { - /* -@@ -324,13 +361,36 @@ static struct mx2_fmt_cfg *mx27_emma_prp - return &mx27_emma_prp_table[0]; - }; - -+static void mx27_update_emma_buf(struct mx2_camera_dev *pcdev, -+ unsigned long phys, int bufnum) -+{ -+ struct mx2_fmt_cfg *prp = pcdev->emma_prp; -+ -+ if (prp->cfg.channel == 1) { -+ writel(phys, pcdev->base_emma + -+ PRP_DEST_RGB1_PTR + 4 * bufnum); -+ } else { -+ writel(phys, pcdev->base_emma + -+ PRP_DEST_Y_PTR - 0x14 * bufnum); -+ if (prp->out_fmt == V4L2_PIX_FMT_YUV420) { -+ u32 imgsize = pcdev->icd->user_height * -+ pcdev->icd->user_width; -+ -+ writel(phys + imgsize, pcdev->base_emma + -+ PRP_DEST_CB_PTR - 0x14 * bufnum); -+ writel(phys + ((5 * imgsize) / 4), pcdev->base_emma + -+ PRP_DEST_CR_PTR - 0x14 * bufnum); -+ } -+ } -+} -+ - static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) - { - unsigned long flags; - - clk_disable(pcdev->clk_csi); - writel(0, pcdev->base_csi + CSICR1); -- if (mx27_camera_emma(pcdev)) { -+ if (cpu_is_mx27()) { - writel(0, pcdev->base_emma + PRP_CNTL); - } else if (cpu_is_mx25()) { - spin_lock_irqsave(&pcdev->lock, flags); -@@ -362,7 +422,7 @@ static int mx2_camera_add_device(struct - - csicr1 = CSICR1_MCLKEN; - -- if (mx27_camera_emma(pcdev)) { -+ if (cpu_is_mx27()) { - csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC | - CSICR1_RXFF_LEVEL(0); - } else if (cpu_is_mx27()) -@@ -392,56 +452,13 @@ static void mx2_camera_remove_device(str - - mx2_camera_deactivate(pcdev); - -- if (pcdev->discard_buffer) { -- dma_free_coherent(ici->v4l2_dev.dev, pcdev->discard_size, -- pcdev->discard_buffer, -- pcdev->discard_buffer_dma); -- pcdev->discard_buffer = NULL; -- } -- - pcdev->icd = NULL; - } - --#ifdef CONFIG_MACH_MX27 --static void mx27_camera_dma_enable(struct mx2_camera_dev *pcdev) --{ -- u32 tmp; -- -- imx_dma_enable(pcdev->dma); -- -- tmp = readl(pcdev->base_csi + CSICR1); -- tmp |= CSICR1_RF_OR_INTEN; -- writel(tmp, pcdev->base_csi + CSICR1); --} -- --static irqreturn_t mx27_camera_irq(int irq_csi, void *data) --{ -- struct mx2_camera_dev *pcdev = data; -- u32 status = readl(pcdev->base_csi + CSISR); -- -- if (status & CSISR_SOF_INT && pcdev->active) { -- u32 tmp; -- -- tmp = readl(pcdev->base_csi + CSICR1); -- writel(tmp | CSICR1_CLR_RXFIFO, pcdev->base_csi + CSICR1); -- mx27_camera_dma_enable(pcdev); -- } -- -- writel(CSISR_SOF_INT | CSISR_RFF_OR_INT, pcdev->base_csi + CSISR); -- -- return IRQ_HANDLED; --} --#else --static irqreturn_t mx27_camera_irq(int irq_csi, void *data) --{ -- return IRQ_NONE; --} --#endif /* CONFIG_MACH_MX27 */ -- - static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb, - int state) - { -- struct videobuf_buffer *vb; -+ struct vb2_buffer *vb; - struct mx2_buffer *buf; - struct mx2_buffer **fb_active = fb == 1 ? &pcdev->fb1_active : - &pcdev->fb2_active; -@@ -454,25 +471,24 @@ static void mx25_camera_frame_done(struc - goto out; - - vb = &(*fb_active)->vb; -- dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, -- vb, vb->baddr, vb->bsize); -- -- vb->state = state; -- do_gettimeofday(&vb->ts); -- vb->field_count++; -+ dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, -+ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); - -- wake_up(&vb->done); -+ do_gettimeofday(&vb->v4l2_buf.timestamp); -+ vb->v4l2_buf.sequence++; -+ vb2_buffer_done(vb, VB2_BUF_STATE_DONE); - - if (list_empty(&pcdev->capture)) { - buf = NULL; - writel(0, pcdev->base_csi + fb_reg); - } else { -- buf = list_entry(pcdev->capture.next, struct mx2_buffer, -- vb.queue); -+ buf = list_first_entry(&pcdev->capture, struct mx2_buffer, -+ internal.queue); - vb = &buf->vb; -- list_del(&vb->queue); -- vb->state = VIDEOBUF_ACTIVE; -- writel(videobuf_to_dma_contig(vb), pcdev->base_csi + fb_reg); -+ list_del(&buf->internal.queue); -+ buf->state = MX2_STATE_ACTIVE; -+ writel(vb2_dma_contig_plane_dma_addr(vb, 0), -+ pcdev->base_csi + fb_reg); - } - - *fb_active = buf; -@@ -487,9 +503,9 @@ static irqreturn_t mx25_camera_irq(int i - u32 status = readl(pcdev->base_csi + CSISR); - - if (status & CSISR_DMA_TSF_FB1_INT) -- mx25_camera_frame_done(pcdev, 1, VIDEOBUF_DONE); -+ mx25_camera_frame_done(pcdev, 1, MX2_STATE_DONE); - else if (status & CSISR_DMA_TSF_FB2_INT) -- mx25_camera_frame_done(pcdev, 2, VIDEOBUF_DONE); -+ mx25_camera_frame_done(pcdev, 2, MX2_STATE_DONE); - - /* FIXME: handle CSISR_RFF_OR_INT */ - -@@ -501,59 +517,50 @@ static irqreturn_t mx25_camera_irq(int i - /* - * Videobuf operations - */ --static int mx2_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, -- unsigned int *size) -+static int mx2_videobuf_setup(struct vb2_queue *vq, -+ const struct v4l2_format *fmt, -+ unsigned int *count, unsigned int *num_planes, -+ unsigned int sizes[], void *alloc_ctxs[]) - { -- struct soc_camera_device *icd = vq->priv_data; -+ struct soc_camera_device *icd = soc_camera_from_vb2q(vq); -+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); -+ struct mx2_camera_dev *pcdev = ici->priv; - int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, - icd->current_fmt->host_fmt); - -- dev_dbg(icd->parent, "count=%d, size=%d\n", *count, *size); -+ dev_dbg(icd->parent, "count=%d, size=%d\n", *count, sizes[0]); -+ -+ /* TODO: support for VIDIOC_CREATE_BUFS not ready */ -+ if (fmt != NULL) -+ return -ENOTTY; - - if (bytes_per_line < 0) - return bytes_per_line; - -- *size = bytes_per_line * icd->user_height; -+ alloc_ctxs[0] = pcdev->alloc_ctx; -+ -+ sizes[0] = bytes_per_line * icd->user_height; - - if (0 == *count) - *count = 32; -- if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) -- *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size; -+ if (!*num_planes && -+ sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024) -+ *count = (MAX_VIDEO_MEM * 1024 * 1024) / sizes[0]; - -- return 0; --} -- --static void free_buffer(struct videobuf_queue *vq, struct mx2_buffer *buf) --{ -- struct soc_camera_device *icd = vq->priv_data; -- struct videobuf_buffer *vb = &buf->vb; -+ *num_planes = 1; - -- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, -- vb, vb->baddr, vb->bsize); -- -- /* -- * This waits until this buffer is out of danger, i.e., until it is no -- * longer in state VIDEOBUF_QUEUED or VIDEOBUF_ACTIVE -- */ -- videobuf_waiton(vq, vb, 0, 0); -- -- videobuf_dma_contig_free(vq, vb); -- dev_dbg(icd->parent, "%s freed\n", __func__); -- -- vb->state = VIDEOBUF_NEEDS_INIT; -+ return 0; - } - --static int mx2_videobuf_prepare(struct videobuf_queue *vq, -- struct videobuf_buffer *vb, enum v4l2_field field) -+static int mx2_videobuf_prepare(struct vb2_buffer *vb) - { -- struct soc_camera_device *icd = vq->priv_data; -- struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); -+ struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); - int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, - icd->current_fmt->host_fmt); - int ret = 0; - -- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, -- vb, vb->baddr, vb->bsize); -+ dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, -+ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); - - if (bytes_per_line < 0) - return bytes_per_line; -@@ -563,99 +570,58 @@ static int mx2_videobuf_prepare(struct v - * This can be useful if you want to see if we actually fill - * the buffer with something - */ -- memset((void *)vb->baddr, 0xaa, vb->bsize); -+ memset((void *)vb2_plane_vaddr(vb, 0), -+ 0xaa, vb2_get_plane_payload(vb, 0)); - #endif - -- if (buf->code != icd->current_fmt->code || -- vb->width != icd->user_width || -- vb->height != icd->user_height || -- vb->field != field) { -- buf->code = icd->current_fmt->code; -- vb->width = icd->user_width; -- vb->height = icd->user_height; -- vb->field = field; -- vb->state = VIDEOBUF_NEEDS_INIT; -- } -- -- vb->size = bytes_per_line * vb->height; -- if (vb->baddr && vb->bsize < vb->size) { -+ vb2_set_plane_payload(vb, 0, bytes_per_line * icd->user_height); -+ if (vb2_plane_vaddr(vb, 0) && -+ vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) { - ret = -EINVAL; - goto out; - } - -- if (vb->state == VIDEOBUF_NEEDS_INIT) { -- ret = videobuf_iolock(vq, vb, NULL); -- if (ret) -- goto fail; -- -- vb->state = VIDEOBUF_PREPARED; -- } -- - return 0; - --fail: -- free_buffer(vq, buf); - out: - return ret; - } - --static void mx2_videobuf_queue(struct videobuf_queue *vq, -- struct videobuf_buffer *vb) -+static void mx2_videobuf_queue(struct vb2_buffer *vb) - { -- struct soc_camera_device *icd = vq->priv_data; -+ struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); - struct soc_camera_host *ici = - to_soc_camera_host(icd->parent); - struct mx2_camera_dev *pcdev = ici->priv; - struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); - unsigned long flags; - -- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, -- vb, vb->baddr, vb->bsize); -+ dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, -+ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); - - spin_lock_irqsave(&pcdev->lock, flags); - -- vb->state = VIDEOBUF_QUEUED; -- list_add_tail(&vb->queue, &pcdev->capture); -- -- if (mx27_camera_emma(pcdev)) { -- goto out; --#ifdef CONFIG_MACH_MX27 -- } else if (cpu_is_mx27()) { -- int ret; -- -- if (pcdev->active == NULL) { -- ret = imx_dma_setup_single(pcdev->dma, -- videobuf_to_dma_contig(vb), vb->size, -- (u32)pcdev->base_dma + 0x10, -- DMA_MODE_READ); -- if (ret) { -- vb->state = VIDEOBUF_ERROR; -- wake_up(&vb->done); -- goto out; -- } -+ buf->state = MX2_STATE_QUEUED; -+ list_add_tail(&buf->internal.queue, &pcdev->capture); - -- vb->state = VIDEOBUF_ACTIVE; -- pcdev->active = buf; -- } --#endif -- } else { /* cpu_is_mx25() */ -+ if (cpu_is_mx25()) { - u32 csicr3, dma_inten = 0; - - if (pcdev->fb1_active == NULL) { -- writel(videobuf_to_dma_contig(vb), -+ writel(vb2_dma_contig_plane_dma_addr(vb, 0), - pcdev->base_csi + CSIDMASA_FB1); - pcdev->fb1_active = buf; - dma_inten = CSICR1_FB1_DMA_INTEN; - } else if (pcdev->fb2_active == NULL) { -- writel(videobuf_to_dma_contig(vb), -+ writel(vb2_dma_contig_plane_dma_addr(vb, 0), - pcdev->base_csi + CSIDMASA_FB2); - pcdev->fb2_active = buf; - dma_inten = CSICR1_FB2_DMA_INTEN; - } - - if (dma_inten) { -- list_del(&vb->queue); -- vb->state = VIDEOBUF_ACTIVE; -+ list_del(&buf->internal.queue); -+ buf->state = MX2_STATE_ACTIVE; - - csicr3 = readl(pcdev->base_csi + CSICR3); - -@@ -674,36 +640,31 @@ static void mx2_videobuf_queue(struct vi - } - } - --out: - spin_unlock_irqrestore(&pcdev->lock, flags); - } - --static void mx2_videobuf_release(struct videobuf_queue *vq, -- struct videobuf_buffer *vb) -+static void mx2_videobuf_release(struct vb2_buffer *vb) - { -- struct soc_camera_device *icd = vq->priv_data; -+ struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct mx2_camera_dev *pcdev = ici->priv; - struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); - unsigned long flags; - - #ifdef DEBUG -- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, -- vb, vb->baddr, vb->bsize); -+ dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, -+ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); - -- switch (vb->state) { -- case VIDEOBUF_ACTIVE: -+ switch (buf->state) { -+ case MX2_STATE_ACTIVE: - dev_info(icd->parent, "%s (active)\n", __func__); - break; -- case VIDEOBUF_QUEUED: -+ case MX2_STATE_QUEUED: - dev_info(icd->parent, "%s (queued)\n", __func__); - break; -- case VIDEOBUF_PREPARED: -- dev_info(icd->parent, "%s (prepared)\n", __func__); -- break; - default: - dev_info(icd->parent, "%s (unknown) %d\n", __func__, -- vb->state); -+ buf->state); - break; - } - #endif -@@ -717,11 +678,9 @@ static void mx2_videobuf_release(struct - * state. This requires a specific handling for each of the these DMA - * types. - */ -+ - spin_lock_irqsave(&pcdev->lock, flags); -- if (vb->state == VIDEOBUF_QUEUED) { -- list_del(&vb->queue); -- vb->state = VIDEOBUF_ERROR; -- } else if (cpu_is_mx25() && vb->state == VIDEOBUF_ACTIVE) { -+ if (cpu_is_mx25() && buf->state == MX2_STATE_ACTIVE) { - if (pcdev->fb1_active == buf) { - pcdev->csicr1 &= ~CSICR1_FB1_DMA_INTEN; - writel(0, pcdev->base_csi + CSIDMASA_FB1); -@@ -732,30 +691,260 @@ static void mx2_videobuf_release(struct - pcdev->fb2_active = NULL; - } - writel(pcdev->csicr1, pcdev->base_csi + CSICR1); -- vb->state = VIDEOBUF_ERROR; - } - spin_unlock_irqrestore(&pcdev->lock, flags); -+} -+ -+static void mx27_camera_emma_buf_init(struct soc_camera_device *icd, -+ int bytesperline) -+{ -+ struct soc_camera_host *ici = -+ to_soc_camera_host(icd->parent); -+ struct mx2_camera_dev *pcdev = ici->priv; -+ struct mx2_fmt_cfg *prp = pcdev->emma_prp; -+ -+ writel((pcdev->s_width << 16) | pcdev->s_height, -+ pcdev->base_emma + PRP_SRC_FRAME_SIZE); -+ writel(prp->cfg.src_pixel, -+ pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); -+ if (prp->cfg.channel == 1) { -+ writel((icd->user_width << 16) | icd->user_height, -+ pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE); -+ writel(bytesperline, -+ pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE); -+ writel(prp->cfg.ch1_pixel, -+ pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL); -+ } else { /* channel 2 */ -+ writel((icd->user_width << 16) | icd->user_height, -+ pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); -+ } -+ -+ /* Enable interrupts */ -+ writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL); -+} -+ -+static void mx2_prp_resize_commit(struct mx2_camera_dev *pcdev) -+{ -+ int dir; -+ -+ for (dir = RESIZE_DIR_H; dir <= RESIZE_DIR_V; dir++) { -+ unsigned char *s = pcdev->resizing[dir].s; -+ int len = pcdev->resizing[dir].len; -+ unsigned int coeff[2] = {0, 0}; -+ unsigned int valid = 0; -+ int i; -+ -+ if (len == 0) -+ continue; -+ -+ for (i = RESIZE_NUM_MAX - 1; i >= 0; i--) { -+ int j; -+ -+ j = i > 9 ? 1 : 0; -+ coeff[j] = (coeff[j] << BC_COEF) | -+ (s[i] & (SZ_COEF - 1)); -+ -+ if (i == 5 || i == 15) -+ coeff[j] <<= 1; -+ -+ valid = (valid << 1) | (s[i] >> BC_COEF); -+ } -+ -+ valid |= PRP_RZ_VALID_TBL_LEN(len); -+ -+ if (pcdev->resizing[dir].algo == RESIZE_ALGO_BILINEAR) -+ valid |= PRP_RZ_VALID_BILINEAR; -+ -+ if (pcdev->emma_prp->cfg.channel == 1) { -+ if (dir == RESIZE_DIR_H) { -+ writel(coeff[0], pcdev->base_emma + -+ PRP_CH1_RZ_HORI_COEF1); -+ writel(coeff[1], pcdev->base_emma + -+ PRP_CH1_RZ_HORI_COEF2); -+ writel(valid, pcdev->base_emma + -+ PRP_CH1_RZ_HORI_VALID); -+ } else { -+ writel(coeff[0], pcdev->base_emma + -+ PRP_CH1_RZ_VERT_COEF1); -+ writel(coeff[1], pcdev->base_emma + -+ PRP_CH1_RZ_VERT_COEF2); -+ writel(valid, pcdev->base_emma + -+ PRP_CH1_RZ_VERT_VALID); -+ } -+ } else { -+ if (dir == RESIZE_DIR_H) { -+ writel(coeff[0], pcdev->base_emma + -+ PRP_CH2_RZ_HORI_COEF1); -+ writel(coeff[1], pcdev->base_emma + -+ PRP_CH2_RZ_HORI_COEF2); -+ writel(valid, pcdev->base_emma + -+ PRP_CH2_RZ_HORI_VALID); -+ } else { -+ writel(coeff[0], pcdev->base_emma + -+ PRP_CH2_RZ_VERT_COEF1); -+ writel(coeff[1], pcdev->base_emma + -+ PRP_CH2_RZ_VERT_COEF2); -+ writel(valid, pcdev->base_emma + -+ PRP_CH2_RZ_VERT_VALID); -+ } -+ } -+ } -+} -+ -+static int mx2_start_streaming(struct vb2_queue *q, unsigned int count) -+{ -+ struct soc_camera_device *icd = soc_camera_from_vb2q(q); -+ struct soc_camera_host *ici = -+ to_soc_camera_host(icd->parent); -+ struct mx2_camera_dev *pcdev = ici->priv; -+ struct mx2_fmt_cfg *prp = pcdev->emma_prp; -+ struct vb2_buffer *vb; -+ struct mx2_buffer *buf; -+ unsigned long phys; -+ int bytesperline; -+ -+ if (cpu_is_mx27()) { -+ unsigned long flags; -+ if (count < 2) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&pcdev->lock, flags); -+ -+ buf = list_first_entry(&pcdev->capture, struct mx2_buffer, -+ internal.queue); -+ buf->internal.bufnum = 0; -+ vb = &buf->vb; -+ buf->state = MX2_STATE_ACTIVE; -+ -+ phys = vb2_dma_contig_plane_dma_addr(vb, 0); -+ mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); -+ list_move_tail(pcdev->capture.next, &pcdev->active_bufs); -+ -+ buf = list_first_entry(&pcdev->capture, struct mx2_buffer, -+ internal.queue); -+ buf->internal.bufnum = 1; -+ vb = &buf->vb; -+ buf->state = MX2_STATE_ACTIVE; -+ -+ phys = vb2_dma_contig_plane_dma_addr(vb, 0); -+ mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); -+ list_move_tail(pcdev->capture.next, &pcdev->active_bufs); -+ -+ bytesperline = soc_mbus_bytes_per_line(icd->user_width, -+ icd->current_fmt->host_fmt); -+ if (bytesperline < 0) -+ return bytesperline; -+ -+ /* -+ * I didn't manage to properly enable/disable the prp -+ * on a per frame basis during running transfers, -+ * thus we allocate a buffer here and use it to -+ * discard frames when no buffer is available. -+ * Feel free to work on this ;) -+ */ -+ pcdev->discard_size = icd->user_height * bytesperline; -+ pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, -+ pcdev->discard_size, &pcdev->discard_buffer_dma, -+ GFP_KERNEL); -+ if (!pcdev->discard_buffer) -+ return -ENOMEM; -+ -+ pcdev->buf_discard[0].discard = true; -+ list_add_tail(&pcdev->buf_discard[0].queue, -+ &pcdev->discard); -+ -+ pcdev->buf_discard[1].discard = true; -+ list_add_tail(&pcdev->buf_discard[1].queue, -+ &pcdev->discard); -+ -+ mx2_prp_resize_commit(pcdev); -+ -+ mx27_camera_emma_buf_init(icd, bytesperline); -+ -+ if (prp->cfg.channel == 1) { -+ writel(PRP_CNTL_CH1EN | -+ PRP_CNTL_CSIEN | -+ prp->cfg.in_fmt | -+ prp->cfg.out_fmt | -+ PRP_CNTL_CH1_LEN | -+ PRP_CNTL_CH1BYP | -+ PRP_CNTL_CH1_TSKIP(0) | -+ PRP_CNTL_IN_TSKIP(0), -+ pcdev->base_emma + PRP_CNTL); -+ } else { -+ writel(PRP_CNTL_CH2EN | -+ PRP_CNTL_CSIEN | -+ prp->cfg.in_fmt | -+ prp->cfg.out_fmt | -+ PRP_CNTL_CH2_LEN | -+ PRP_CNTL_CH2_TSKIP(0) | -+ PRP_CNTL_IN_TSKIP(0), -+ pcdev->base_emma + PRP_CNTL); -+ } -+ spin_unlock_irqrestore(&pcdev->lock, flags); -+ } -+ -+ return 0; -+} -+ -+static int mx2_stop_streaming(struct vb2_queue *q) -+{ -+ struct soc_camera_device *icd = soc_camera_from_vb2q(q); -+ struct soc_camera_host *ici = -+ to_soc_camera_host(icd->parent); -+ struct mx2_camera_dev *pcdev = ici->priv; -+ struct mx2_fmt_cfg *prp = pcdev->emma_prp; -+ unsigned long flags; -+ void *b; -+ u32 cntl; -+ -+ if (cpu_is_mx27()) { -+ spin_lock_irqsave(&pcdev->lock, flags); -+ -+ cntl = readl(pcdev->base_emma + PRP_CNTL); -+ if (prp->cfg.channel == 1) { -+ writel(cntl & ~PRP_CNTL_CH1EN, -+ pcdev->base_emma + PRP_CNTL); -+ } else { -+ writel(cntl & ~PRP_CNTL_CH2EN, -+ pcdev->base_emma + PRP_CNTL); -+ } -+ INIT_LIST_HEAD(&pcdev->capture); -+ INIT_LIST_HEAD(&pcdev->active_bufs); -+ INIT_LIST_HEAD(&pcdev->discard); -+ -+ b = pcdev->discard_buffer; -+ pcdev->discard_buffer = NULL; -+ -+ spin_unlock_irqrestore(&pcdev->lock, flags); -+ -+ dma_free_coherent(ici->v4l2_dev.dev, -+ pcdev->discard_size, b, pcdev->discard_buffer_dma); -+ } - -- free_buffer(vq, buf); -+ return 0; - } - --static struct videobuf_queue_ops mx2_videobuf_ops = { -- .buf_setup = mx2_videobuf_setup, -- .buf_prepare = mx2_videobuf_prepare, -- .buf_queue = mx2_videobuf_queue, -- .buf_release = mx2_videobuf_release, -+static struct vb2_ops mx2_videobuf_ops = { -+ .queue_setup = mx2_videobuf_setup, -+ .buf_prepare = mx2_videobuf_prepare, -+ .buf_queue = mx2_videobuf_queue, -+ .buf_cleanup = mx2_videobuf_release, -+ .start_streaming = mx2_start_streaming, -+ .stop_streaming = mx2_stop_streaming, - }; - --static void mx2_camera_init_videobuf(struct videobuf_queue *q, -+static int mx2_camera_init_videobuf(struct vb2_queue *q, - struct soc_camera_device *icd) - { -- struct soc_camera_host *ici = to_soc_camera_host(icd->parent); -- struct mx2_camera_dev *pcdev = ici->priv; -+ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ q->io_modes = VB2_MMAP | VB2_USERPTR; -+ q->drv_priv = icd; -+ q->ops = &mx2_videobuf_ops; -+ q->mem_ops = &vb2_dma_contig_memops; -+ q->buf_struct_size = sizeof(struct mx2_buffer); - -- videobuf_queue_dma_contig_init(q, &mx2_videobuf_ops, pcdev->dev, -- &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, -- V4L2_FIELD_NONE, sizeof(struct mx2_buffer), -- icd, &icd->video_lock); -+ return vb2_queue_init(q); - } - - #define MX2_BUS_FLAGS (V4L2_MBUS_MASTER | \ -@@ -785,82 +974,6 @@ static int mx27_camera_emma_prp_reset(st - return -ETIMEDOUT; - } - --static void mx27_camera_emma_buf_init(struct soc_camera_device *icd, -- int bytesperline) --{ -- struct soc_camera_host *ici = -- to_soc_camera_host(icd->parent); -- struct mx2_camera_dev *pcdev = ici->priv; -- struct mx2_fmt_cfg *prp = pcdev->emma_prp; -- u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width; -- -- if (prp->cfg.channel == 1) { -- writel(pcdev->discard_buffer_dma, -- pcdev->base_emma + PRP_DEST_RGB1_PTR); -- writel(pcdev->discard_buffer_dma, -- pcdev->base_emma + PRP_DEST_RGB2_PTR); -- -- writel(PRP_CNTL_CH1EN | -- PRP_CNTL_CSIEN | -- prp->cfg.in_fmt | -- prp->cfg.out_fmt | -- PRP_CNTL_CH1_LEN | -- PRP_CNTL_CH1BYP | -- PRP_CNTL_CH1_TSKIP(0) | -- PRP_CNTL_IN_TSKIP(0), -- pcdev->base_emma + PRP_CNTL); -- -- writel((icd->user_width << 16) | icd->user_height, -- pcdev->base_emma + PRP_SRC_FRAME_SIZE); -- writel((icd->user_width << 16) | icd->user_height, -- pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE); -- writel(bytesperline, -- pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE); -- writel(prp->cfg.src_pixel, -- pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); -- writel(prp->cfg.ch1_pixel, -- pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL); -- } else { /* channel 2 */ -- writel(pcdev->discard_buffer_dma, -- pcdev->base_emma + PRP_DEST_Y_PTR); -- writel(pcdev->discard_buffer_dma, -- pcdev->base_emma + PRP_SOURCE_Y_PTR); -- -- if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) { -- writel(pcdev->discard_buffer_dma + imgsize, -- pcdev->base_emma + PRP_DEST_CB_PTR); -- writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4), -- pcdev->base_emma + PRP_DEST_CR_PTR); -- writel(pcdev->discard_buffer_dma + imgsize, -- pcdev->base_emma + PRP_SOURCE_CB_PTR); -- writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4), -- pcdev->base_emma + PRP_SOURCE_CR_PTR); -- } -- -- writel(PRP_CNTL_CH2EN | -- PRP_CNTL_CSIEN | -- prp->cfg.in_fmt | -- prp->cfg.out_fmt | -- PRP_CNTL_CH2_LEN | -- PRP_CNTL_CH2_TSKIP(0) | -- PRP_CNTL_IN_TSKIP(0), -- pcdev->base_emma + PRP_CNTL); -- -- writel((icd->user_width << 16) | icd->user_height, -- pcdev->base_emma + PRP_SRC_FRAME_SIZE); -- -- writel((icd->user_width << 16) | icd->user_height, -- pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); -- -- writel(prp->cfg.src_pixel, -- pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); -- -- } -- -- /* Enable interrupts */ -- writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL); --} -- - static int mx2_camera_set_bus_param(struct soc_camera_device *icd) - { - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); -@@ -939,31 +1052,10 @@ static int mx2_camera_set_bus_param(stru - if (bytesperline < 0) - return bytesperline; - -- if (mx27_camera_emma(pcdev)) { -+ if (cpu_is_mx27()) { - ret = mx27_camera_emma_prp_reset(pcdev); - if (ret) - return ret; -- -- if (pcdev->discard_buffer) -- dma_free_coherent(ici->v4l2_dev.dev, -- pcdev->discard_size, pcdev->discard_buffer, -- pcdev->discard_buffer_dma); -- -- /* -- * I didn't manage to properly enable/disable the prp -- * on a per frame basis during running transfers, -- * thus we allocate a buffer here and use it to -- * discard frames when no buffer is available. -- * Feel free to work on this ;) -- */ -- pcdev->discard_size = icd->user_height * bytesperline; -- pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, -- pcdev->discard_size, &pcdev->discard_buffer_dma, -- GFP_KERNEL); -- if (!pcdev->discard_buffer) -- return -ENOMEM; -- -- mx27_camera_emma_buf_init(icd, bytesperline); - } else if (cpu_is_mx25()) { - writel((bytesperline * icd->user_height) >> 2, - pcdev->base_csi + CSIRXCNT); -@@ -1052,6 +1144,123 @@ static int mx2_camera_get_formats(struct - return formats; - } - -+static int mx2_emmaprp_resize(struct mx2_camera_dev *pcdev, -+ struct v4l2_mbus_framefmt *mf_in, -+ struct v4l2_pix_format *pix_out, bool apply) -+{ -+ int num, den; -+ unsigned long m; -+ int i, dir; -+ -+ for (dir = RESIZE_DIR_H; dir <= RESIZE_DIR_V; dir++) { -+ struct emma_prp_resize tmprsz; -+ unsigned char *s = tmprsz.s; -+ int len = 0; -+ int in, out; -+ -+ if (dir == RESIZE_DIR_H) { -+ in = mf_in->width; -+ out = pix_out->width; -+ } else { -+ in = mf_in->height; -+ out = pix_out->height; -+ } -+ -+ if (in < out) -+ return -EINVAL; -+ else if (in == out) -+ continue; -+ -+ /* Calculate ratio */ -+ m = gcd(in, out); -+ num = in / m; -+ den = out / m; -+ if (num > RESIZE_NUM_MAX) -+ return -EINVAL; -+ -+ if ((num >= 2 * den) && (den == 1) && -+ (num < 9) && (!(num & 0x01))) { -+ int sum = 0; -+ int j; -+ -+ /* Average scaling for >= 2:1 ratios */ -+ /* Support can be added for num >=9 and odd values */ -+ -+ tmprsz.algo = RESIZE_ALGO_AVERAGING; -+ len = num; -+ -+ for (i = 0; i < (len / 2); i++) -+ s[i] = 8; -+ -+ do { -+ for (i = 0; i < (len / 2); i++) { -+ s[i] = s[i] >> 1; -+ sum = 0; -+ for (j = 0; j < (len / 2); j++) -+ sum += s[j]; -+ if (sum == 4) -+ break; -+ } -+ } while (sum != 4); -+ -+ for (i = (len / 2); i < len; i++) -+ s[i] = s[len - i - 1]; -+ -+ s[len - 1] |= SZ_COEF; -+ } else { -+ /* bilinear scaling for < 2:1 ratios */ -+ int v; /* overflow counter */ -+ int coeff, nxt; /* table output */ -+ int in_pos_inc = 2 * den; -+ int out_pos = num; -+ int out_pos_inc = 2 * num; -+ int init_carry = num - den; -+ int carry = init_carry; -+ -+ tmprsz.algo = RESIZE_ALGO_BILINEAR; -+ v = den + in_pos_inc; -+ do { -+ coeff = v - out_pos; -+ out_pos += out_pos_inc; -+ carry += out_pos_inc; -+ for (nxt = 0; v < out_pos; nxt++) { -+ v += in_pos_inc; -+ carry -= in_pos_inc; -+ } -+ -+ if (len > RESIZE_NUM_MAX) -+ return -EINVAL; -+ -+ coeff = ((coeff << BC_COEF) + -+ (in_pos_inc >> 1)) / in_pos_inc; -+ -+ if (coeff >= (SZ_COEF - 1)) -+ coeff--; -+ -+ coeff |= SZ_COEF; -+ s[len] = (unsigned char)coeff; -+ len++; -+ -+ for (i = 1; i < nxt; i++) { -+ if (len >= RESIZE_NUM_MAX) -+ return -EINVAL; -+ s[len] = 0; -+ len++; -+ } -+ } while (carry != init_carry); -+ } -+ tmprsz.len = len; -+ if (dir == RESIZE_DIR_H) -+ mf_in->width = pix_out->width; -+ else -+ mf_in->height = pix_out->height; -+ -+ if (apply) -+ memcpy(&pcdev->resizing[dir], &tmprsz, sizeof(tmprsz)); -+ } -+ return 0; -+} -+ - static int mx2_camera_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) - { -@@ -1063,6 +1272,9 @@ static int mx2_camera_set_fmt(struct soc - struct v4l2_mbus_framefmt mf; - int ret; - -+ dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n", -+ __func__, pix->width, pix->height); -+ - xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); - if (!xlate) { - dev_warn(icd->parent, "Format %x not found\n", -@@ -1080,6 +1292,22 @@ static int mx2_camera_set_fmt(struct soc - if (ret < 0 && ret != -ENOIOCTLCMD) - return ret; - -+ /* Store width and height returned by the sensor for resizing */ -+ pcdev->s_width = mf.width; -+ pcdev->s_height = mf.height; -+ dev_dbg(icd->parent, "%s: sensor params: width = %d, height = %d\n", -+ __func__, pcdev->s_width, pcdev->s_height); -+ -+ pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, -+ xlate->host_fmt->fourcc); -+ -+ memset(pcdev->resizing, 0, sizeof(pcdev->resizing)); -+ if ((mf.width != pix->width || mf.height != pix->height) && -+ pcdev->emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { -+ if (mx2_emmaprp_resize(pcdev, &mf, pix, true) < 0) -+ dev_dbg(icd->parent, "%s: can't resize\n", __func__); -+ } -+ - if (mf.code != xlate->code) - return -EINVAL; - -@@ -1089,9 +1317,8 @@ static int mx2_camera_set_fmt(struct soc - pix->colorspace = mf.colorspace; - icd->current_fmt = xlate; - -- if (mx27_camera_emma(pcdev)) -- pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, -- xlate->host_fmt->fourcc); -+ dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n", -+ __func__, pix->width, pix->height); - - return 0; - } -@@ -1104,9 +1331,14 @@ static int mx2_camera_try_fmt(struct soc - struct v4l2_pix_format *pix = &f->fmt.pix; - struct v4l2_mbus_framefmt mf; - __u32 pixfmt = pix->pixelformat; -+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); -+ struct mx2_camera_dev *pcdev = ici->priv; - unsigned int width_limit; - int ret; - -+ dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n", -+ __func__, pix->width, pix->height); -+ - xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); - if (pixfmt && !xlate) { - dev_warn(icd->parent, "Format %x not found\n", pixfmt); -@@ -1156,6 +1388,20 @@ static int mx2_camera_try_fmt(struct soc - if (ret < 0) - return ret; - -+ dev_dbg(icd->parent, "%s: sensor params: width = %d, height = %d\n", -+ __func__, pcdev->s_width, pcdev->s_height); -+ -+ /* If the sensor does not support image size try PrP resizing */ -+ pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, -+ xlate->host_fmt->fourcc); -+ -+ memset(pcdev->resizing, 0, sizeof(pcdev->resizing)); -+ if ((mf.width != pix->width || mf.height != pix->height) && -+ pcdev->emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { -+ if (mx2_emmaprp_resize(pcdev, &mf, pix, false) < 0) -+ dev_dbg(icd->parent, "%s: can't resize\n", __func__); -+ } -+ - if (mf.field == V4L2_FIELD_ANY) - mf.field = V4L2_FIELD_NONE; - /* -@@ -1174,6 +1420,9 @@ static int mx2_camera_try_fmt(struct soc - pix->field = mf.field; - pix->colorspace = mf.colorspace; - -+ dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n", -+ __func__, pix->width, pix->height); -+ - return 0; - } - -@@ -1187,136 +1436,11 @@ static int mx2_camera_querycap(struct so - return 0; - } - --static int mx2_camera_reqbufs(struct soc_camera_device *icd, -- struct v4l2_requestbuffers *p) --{ -- int i; -- -- for (i = 0; i < p->count; i++) { -- struct mx2_buffer *buf = container_of(icd->vb_vidq.bufs[i], -- struct mx2_buffer, vb); -- INIT_LIST_HEAD(&buf->vb.queue); -- } -- -- return 0; --} -- --#ifdef CONFIG_MACH_MX27 --static void mx27_camera_frame_done(struct mx2_camera_dev *pcdev, int state) --{ -- struct videobuf_buffer *vb; -- struct mx2_buffer *buf; -- unsigned long flags; -- int ret; -- -- spin_lock_irqsave(&pcdev->lock, flags); -- -- if (!pcdev->active) { -- dev_err(pcdev->dev, "%s called with no active buffer!\n", -- __func__); -- goto out; -- } -- -- vb = &pcdev->active->vb; -- buf = container_of(vb, struct mx2_buffer, vb); -- WARN_ON(list_empty(&vb->queue)); -- dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, -- vb, vb->baddr, vb->bsize); -- -- /* _init is used to debug races, see comment in pxa_camera_reqbufs() */ -- list_del_init(&vb->queue); -- vb->state = state; -- do_gettimeofday(&vb->ts); -- vb->field_count++; -- -- wake_up(&vb->done); -- -- if (list_empty(&pcdev->capture)) { -- pcdev->active = NULL; -- goto out; -- } -- -- pcdev->active = list_entry(pcdev->capture.next, -- struct mx2_buffer, vb.queue); -- -- vb = &pcdev->active->vb; -- vb->state = VIDEOBUF_ACTIVE; -- -- ret = imx_dma_setup_single(pcdev->dma, videobuf_to_dma_contig(vb), -- vb->size, (u32)pcdev->base_dma + 0x10, DMA_MODE_READ); -- -- if (ret) { -- vb->state = VIDEOBUF_ERROR; -- pcdev->active = NULL; -- wake_up(&vb->done); -- } -- --out: -- spin_unlock_irqrestore(&pcdev->lock, flags); --} -- --static void mx27_camera_dma_err_callback(int channel, void *data, int err) --{ -- struct mx2_camera_dev *pcdev = data; -- -- mx27_camera_frame_done(pcdev, VIDEOBUF_ERROR); --} -- --static void mx27_camera_dma_callback(int channel, void *data) --{ -- struct mx2_camera_dev *pcdev = data; -- -- mx27_camera_frame_done(pcdev, VIDEOBUF_DONE); --} -- --#define DMA_REQ_CSI_RX 31 /* FIXME: Add this to a resource */ -- --static int __devinit mx27_camera_dma_init(struct platform_device *pdev, -- struct mx2_camera_dev *pcdev) --{ -- int err; -- -- pcdev->dma = imx_dma_request_by_prio("CSI RX DMA", DMA_PRIO_HIGH); -- if (pcdev->dma < 0) { -- dev_err(&pdev->dev, "%s failed to request DMA channel\n", -- __func__); -- return pcdev->dma; -- } -- -- err = imx_dma_setup_handlers(pcdev->dma, mx27_camera_dma_callback, -- mx27_camera_dma_err_callback, pcdev); -- if (err) { -- dev_err(&pdev->dev, "%s failed to set DMA callback\n", -- __func__); -- goto err_out; -- } -- -- err = imx_dma_config_channel(pcdev->dma, -- IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_FIFO, -- IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, -- DMA_REQ_CSI_RX, 1); -- if (err) { -- dev_err(&pdev->dev, "%s failed to config DMA channel\n", -- __func__); -- goto err_out; -- } -- -- imx_dma_config_burstlen(pcdev->dma, 64); -- -- return 0; -- --err_out: -- imx_dma_free(pcdev->dma); -- -- return err; --} --#endif /* CONFIG_MACH_MX27 */ -- - static unsigned int mx2_camera_poll(struct file *file, poll_table *pt) - { - struct soc_camera_device *icd = file->private_data; - -- return videobuf_poll_stream(file, &icd->vb_vidq, pt); -+ return vb2_poll(&icd->vb2_vidq, file, pt); - } - - static struct soc_camera_host_ops mx2_soc_camera_host_ops = { -@@ -1327,144 +1451,148 @@ static struct soc_camera_host_ops mx2_so - .set_crop = mx2_camera_set_crop, - .get_formats = mx2_camera_get_formats, - .try_fmt = mx2_camera_try_fmt, -- .init_videobuf = mx2_camera_init_videobuf, -- .reqbufs = mx2_camera_reqbufs, -+ .init_videobuf2 = mx2_camera_init_videobuf, - .poll = mx2_camera_poll, - .querycap = mx2_camera_querycap, - .set_bus_param = mx2_camera_set_bus_param, - }; - - static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, -- int bufnum, int state) -+ int bufnum, bool err) - { -- u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width; -+#ifdef DEBUG - struct mx2_fmt_cfg *prp = pcdev->emma_prp; -+#endif -+ struct mx2_buf_internal *ibuf; - struct mx2_buffer *buf; -- struct videobuf_buffer *vb; -+ struct vb2_buffer *vb; - unsigned long phys; - -- if (!list_empty(&pcdev->active_bufs)) { -- buf = list_entry(pcdev->active_bufs.next, -- struct mx2_buffer, vb.queue); -+ ibuf = list_first_entry(&pcdev->active_bufs, struct mx2_buf_internal, -+ queue); - -- BUG_ON(buf->bufnum != bufnum); -+ BUG_ON(ibuf->bufnum != bufnum); -+ -+ if (ibuf->discard) { -+ /* -+ * Discard buffer must not be returned to user space. -+ * Just return it to the discard queue. -+ */ -+ list_move_tail(pcdev->active_bufs.next, &pcdev->discard); -+ } else { -+ buf = mx2_ibuf_to_buf(ibuf); - - vb = &buf->vb; - #ifdef DEBUG -- phys = videobuf_to_dma_contig(vb); -+ phys = vb2_dma_contig_plane_dma_addr(vb, 0); - if (prp->cfg.channel == 1) { - if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + - 4 * bufnum) != phys) { -- dev_err(pcdev->dev, "%p != %p\n", phys, -- readl(pcdev->base_emma + -- PRP_DEST_RGB1_PTR + -- 4 * bufnum)); -+ dev_err(pcdev->dev, "%lx != %x\n", phys, -+ readl(pcdev->base_emma + -+ PRP_DEST_RGB1_PTR + 4 * bufnum)); - } - } else { - if (readl(pcdev->base_emma + PRP_DEST_Y_PTR - - 0x14 * bufnum) != phys) { -- dev_err(pcdev->dev, "%p != %p\n", phys, -- readl(pcdev->base_emma + -- PRP_DEST_Y_PTR - -- 0x14 * bufnum)); -+ dev_err(pcdev->dev, "%lx != %x\n", phys, -+ readl(pcdev->base_emma + -+ PRP_DEST_Y_PTR - 0x14 * bufnum)); - } - } - #endif -- dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, -- vb->baddr, vb->bsize); -- -- list_del(&vb->queue); -- vb->state = state; -- do_gettimeofday(&vb->ts); -- vb->field_count = pcdev->frame_count * 2; -- pcdev->frame_count++; -- -- wake_up(&vb->done); -+ dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, vb, -+ vb2_plane_vaddr(vb, 0), -+ vb2_get_plane_payload(vb, 0)); -+ -+ list_del_init(&buf->internal.queue); -+ do_gettimeofday(&vb->v4l2_buf.timestamp); -+ vb->v4l2_buf.sequence = pcdev->frame_count; -+ if (err) -+ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); -+ else -+ vb2_buffer_done(vb, VB2_BUF_STATE_DONE); - } - -+ pcdev->frame_count++; -+ - if (list_empty(&pcdev->capture)) { -- if (prp->cfg.channel == 1) { -- writel(pcdev->discard_buffer_dma, pcdev->base_emma + -- PRP_DEST_RGB1_PTR + 4 * bufnum); -- } else { -- writel(pcdev->discard_buffer_dma, pcdev->base_emma + -- PRP_DEST_Y_PTR - -- 0x14 * bufnum); -- if (prp->out_fmt == V4L2_PIX_FMT_YUV420) { -- writel(pcdev->discard_buffer_dma + imgsize, -- pcdev->base_emma + PRP_DEST_CB_PTR - -- 0x14 * bufnum); -- writel(pcdev->discard_buffer_dma + -- ((5 * imgsize) / 4), pcdev->base_emma + -- PRP_DEST_CR_PTR - 0x14 * bufnum); -- } -+ if (list_empty(&pcdev->discard)) { -+ dev_warn(pcdev->dev, "%s: trying to access empty discard list\n", -+ __func__); -+ return; - } -+ -+ ibuf = list_first_entry(&pcdev->discard, -+ struct mx2_buf_internal, queue); -+ ibuf->bufnum = bufnum; -+ -+ list_move_tail(pcdev->discard.next, &pcdev->active_bufs); -+ mx27_update_emma_buf(pcdev, pcdev->discard_buffer_dma, bufnum); - return; - } - -- buf = list_entry(pcdev->capture.next, -- struct mx2_buffer, vb.queue); -+ buf = list_first_entry(&pcdev->capture, struct mx2_buffer, -+ internal.queue); - -- buf->bufnum = !bufnum; -+ buf->internal.bufnum = bufnum; - - list_move_tail(pcdev->capture.next, &pcdev->active_bufs); - - vb = &buf->vb; -- vb->state = VIDEOBUF_ACTIVE; -+ buf->state = MX2_STATE_ACTIVE; - -- phys = videobuf_to_dma_contig(vb); -- if (prp->cfg.channel == 1) { -- writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum); -- } else { -- writel(phys, pcdev->base_emma + -- PRP_DEST_Y_PTR - 0x14 * bufnum); -- if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) { -- writel(phys + imgsize, pcdev->base_emma + -- PRP_DEST_CB_PTR - 0x14 * bufnum); -- writel(phys + ((5 * imgsize) / 4), pcdev->base_emma + -- PRP_DEST_CR_PTR - 0x14 * bufnum); -- } -- } -+ phys = vb2_dma_contig_plane_dma_addr(vb, 0); -+ mx27_update_emma_buf(pcdev, phys, bufnum); - } - - static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) - { - struct mx2_camera_dev *pcdev = data; - unsigned int status = readl(pcdev->base_emma + PRP_INTRSTATUS); -- struct mx2_buffer *buf; -+ struct mx2_buf_internal *ibuf; -+ -+ spin_lock(&pcdev->lock); -+ -+ if (list_empty(&pcdev->active_bufs)) { -+ dev_warn(pcdev->dev, "%s: called while active list is empty\n", -+ __func__); -+ -+ if (!status) { -+ spin_unlock(&pcdev->lock); -+ return IRQ_NONE; -+ } -+ } - - if (status & (1 << 7)) { /* overflow */ -- u32 cntl; -- /* -- * We only disable channel 1 here since this is the only -- * enabled channel -- * -- * FIXME: the correct DMA overflow handling should be resetting -- * the buffer, returning an error frame, and continuing with -- * the next one. -- */ -- cntl = readl(pcdev->base_emma + PRP_CNTL); -+ u32 cntl = readl(pcdev->base_emma + PRP_CNTL); - writel(cntl & ~(PRP_CNTL_CH1EN | PRP_CNTL_CH2EN), - pcdev->base_emma + PRP_CNTL); - writel(cntl, pcdev->base_emma + PRP_CNTL); -- } -- if ((((status & (3 << 5)) == (3 << 5)) || -- ((status & (3 << 3)) == (3 << 3))) -- && !list_empty(&pcdev->active_bufs)) { -+ -+ ibuf = list_first_entry(&pcdev->active_bufs, -+ struct mx2_buf_internal, queue); -+ mx27_camera_frame_done_emma(pcdev, -+ ibuf->bufnum, true); -+ -+ status &= ~(1 << 7); -+ } else if (((status & (3 << 5)) == (3 << 5)) || -+ ((status & (3 << 3)) == (3 << 3))) { - /* - * Both buffers have triggered, process the one we're expecting - * to first - */ -- buf = list_entry(pcdev->active_bufs.next, -- struct mx2_buffer, vb.queue); -- mx27_camera_frame_done_emma(pcdev, buf->bufnum, VIDEOBUF_DONE); -- status &= ~(1 << (6 - buf->bufnum)); /* mark processed */ -- } -- if ((status & (1 << 6)) || (status & (1 << 4))) -- mx27_camera_frame_done_emma(pcdev, 0, VIDEOBUF_DONE); -- if ((status & (1 << 5)) || (status & (1 << 3))) -- mx27_camera_frame_done_emma(pcdev, 1, VIDEOBUF_DONE); -+ ibuf = list_first_entry(&pcdev->active_bufs, -+ struct mx2_buf_internal, queue); -+ mx27_camera_frame_done_emma(pcdev, ibuf->bufnum, false); -+ status &= ~(1 << (6 - ibuf->bufnum)); /* mark processed */ -+ } else if ((status & (1 << 6)) || (status & (1 << 4))) { -+ mx27_camera_frame_done_emma(pcdev, 0, false); -+ } else if ((status & (1 << 5)) || (status & (1 << 3))) { -+ mx27_camera_frame_done_emma(pcdev, 1, false); -+ } - -+ spin_unlock(&pcdev->lock); - writel(status, pcdev->base_emma + PRP_INTRSTATUS); - - return IRQ_HANDLED; -@@ -1527,8 +1655,6 @@ static int __devinit mx2_camera_probe(st - struct resource *res_csi, *res_emma; - void __iomem *base_csi; - int irq_csi, irq_emma; -- irq_handler_t mx2_cam_irq_handler = cpu_is_mx25() ? mx25_camera_irq -- : mx27_camera_irq; - int err = 0; - - dev_dbg(&pdev->dev, "initialising\n"); -@@ -1550,22 +1676,11 @@ static int __devinit mx2_camera_probe(st - - pcdev->clk_csi = clk_get(&pdev->dev, NULL); - if (IS_ERR(pcdev->clk_csi)) { -+ dev_err(&pdev->dev, "Could not get csi clock\n"); - err = PTR_ERR(pcdev->clk_csi); - goto exit_kfree; - } - -- dev_dbg(&pdev->dev, "Camera clock frequency: %ld\n", -- clk_get_rate(pcdev->clk_csi)); -- -- /* Initialize DMA */ --#ifdef CONFIG_MACH_MX27 -- if (cpu_is_mx27()) { -- err = mx27_camera_dma_init(pdev, pcdev); -- if (err) -- goto exit_clk_put; -- } --#endif /* CONFIG_MACH_MX27 */ -- - pcdev->res_csi = res_csi; - pcdev->pdata = pdev->dev.platform_data; - if (pcdev->pdata) { -@@ -1585,6 +1700,7 @@ static int __devinit mx2_camera_probe(st - - INIT_LIST_HEAD(&pcdev->capture); - INIT_LIST_HEAD(&pcdev->active_bufs); -+ INIT_LIST_HEAD(&pcdev->discard); - spin_lock_init(&pcdev->lock); - - /* -@@ -1606,11 +1722,13 @@ static int __devinit mx2_camera_probe(st - pcdev->base_dma = res_csi->start; - pcdev->dev = &pdev->dev; - -- err = request_irq(pcdev->irq_csi, mx2_cam_irq_handler, 0, -- MX2_CAM_DRV_NAME, pcdev); -- if (err) { -- dev_err(pcdev->dev, "Camera interrupt register failed \n"); -- goto exit_iounmap; -+ if (cpu_is_mx25()) { -+ err = request_irq(pcdev->irq_csi, mx25_camera_irq, 0, -+ MX2_CAM_DRV_NAME, pcdev); -+ if (err) { -+ dev_err(pcdev->dev, "Camera interrupt register failed \n"); -+ goto exit_iounmap; -+ } - } - - if (cpu_is_mx27()) { -@@ -1618,14 +1736,15 @@ static int __devinit mx2_camera_probe(st - res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 1); - irq_emma = platform_get_irq(pdev, 1); - -- if (res_emma && irq_emma >= 0) { -- dev_info(&pdev->dev, "Using EMMA\n"); -- pcdev->use_emma = 1; -- pcdev->res_emma = res_emma; -- pcdev->irq_emma = irq_emma; -- if (mx27_camera_emma_init(pcdev)) -- goto exit_free_irq; -+ if (!res_emma || !irq_emma) { -+ dev_err(&pdev->dev, "no EMMA resources\n"); -+ goto exit_free_irq; - } -+ -+ pcdev->res_emma = res_emma; -+ pcdev->irq_emma = irq_emma; -+ if (mx27_camera_emma_init(pcdev)) -+ goto exit_free_irq; - } - - pcdev->soc_host.drv_name = MX2_CAM_DRV_NAME, -@@ -1633,6 +1752,12 @@ static int __devinit mx2_camera_probe(st - pcdev->soc_host.priv = pcdev; - pcdev->soc_host.v4l2_dev.dev = &pdev->dev; - pcdev->soc_host.nr = pdev->id; -+ -+ pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); -+ if (IS_ERR(pcdev->alloc_ctx)) { -+ err = PTR_ERR(pcdev->alloc_ctx); -+ goto eallocctx; -+ } - err = soc_camera_host_register(&pcdev->soc_host); - if (err) - goto exit_free_emma; -@@ -1643,26 +1768,24 @@ static int __devinit mx2_camera_probe(st - return 0; - - exit_free_emma: -- if (mx27_camera_emma(pcdev)) { -+ vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); -+eallocctx: -+ if (cpu_is_mx27()) { - free_irq(pcdev->irq_emma, pcdev); - clk_disable(pcdev->clk_emma); - clk_put(pcdev->clk_emma); - iounmap(pcdev->base_emma); -- release_mem_region(res_emma->start, resource_size(res_emma)); -+ release_mem_region(pcdev->res_emma->start, resource_size(pcdev->res_emma)); - } - exit_free_irq: -- free_irq(pcdev->irq_csi, pcdev); -+ if (cpu_is_mx25()) -+ free_irq(pcdev->irq_csi, pcdev); - exit_iounmap: - iounmap(base_csi); - exit_release: - release_mem_region(res_csi->start, resource_size(res_csi)); - exit_dma_free: --#ifdef CONFIG_MACH_MX27 -- if (cpu_is_mx27()) -- imx_dma_free(pcdev->dma); --exit_clk_put: - clk_put(pcdev->clk_csi); --#endif /* CONFIG_MACH_MX27 */ - exit_kfree: - kfree(pcdev); - exit: -@@ -1677,19 +1800,18 @@ static int __devexit mx2_camera_remove(s - struct resource *res; - - clk_put(pcdev->clk_csi); --#ifdef CONFIG_MACH_MX27 -+ if (cpu_is_mx25()) -+ free_irq(pcdev->irq_csi, pcdev); - if (cpu_is_mx27()) -- imx_dma_free(pcdev->dma); --#endif /* CONFIG_MACH_MX27 */ -- free_irq(pcdev->irq_csi, pcdev); -- if (mx27_camera_emma(pcdev)) - free_irq(pcdev->irq_emma, pcdev); - - soc_camera_host_unregister(&pcdev->soc_host); - -+ vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); -+ - iounmap(pcdev->base_csi); - -- if (mx27_camera_emma(pcdev)) { -+ if (cpu_is_mx27()) { - clk_disable(pcdev->clk_emma); - clk_put(pcdev->clk_emma); - iounmap(pcdev->base_emma); -Index: linux-3.3.x86_64/drivers/media/rc/rc-core-priv.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/rc/rc-core-priv.h -+++ linux-3.3.x86_64/drivers/media/rc/rc-core-priv.h -@@ -35,7 +35,7 @@ struct ir_raw_event_ctrl { - struct list_head list; /* to keep track of raw clients */ - struct task_struct *thread; - spinlock_t lock; -- struct kfifo kfifo; /* fifo for the pulse/space durations */ -+ struct kfifo_rec_ptr_1 kfifo; /* fifo for the pulse/space durations */ - ktime_t last_event; /* when last event occurred */ - enum raw_event_type last_type; /* last event type */ - struct rc_dev *dev; /* pointer to the parent rc_dev */ -Index: linux-3.3.x86_64/drivers/media/video/s2255drv.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/s2255drv.c -+++ linux-3.3.x86_64/drivers/media/video/s2255drv.c -@@ -134,7 +134,7 @@ - - /* usb config commands */ - #define IN_DATA_TOKEN cpu_to_le32(0x2255c0de) --#define CMD_2255 cpu_to_le32(0xc2255000) -+#define CMD_2255 0xc2255000 - #define CMD_SET_MODE cpu_to_le32((CMD_2255 | 0x10)) - #define CMD_START cpu_to_le32((CMD_2255 | 0x20)) - #define CMD_STOP cpu_to_le32((CMD_2255 | 0x30)) -@@ -852,15 +852,13 @@ static int vidioc_querycap(struct file * - static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) - { -- int index = 0; -- if (f) -- index = f->index; -+ int index = f->index; - - if (index >= ARRAY_SIZE(formats)) - return -EINVAL; -- if (!jpeg_enable && ((formats[index].fourcc == V4L2_PIX_FMT_JPEG) || -- (formats[index].fourcc == V4L2_PIX_FMT_MJPEG))) -- return -EINVAL; -+ if (!jpeg_enable && ((formats[index].fourcc == V4L2_PIX_FMT_JPEG) || -+ (formats[index].fourcc == V4L2_PIX_FMT_MJPEG))) -+ return -EINVAL; - dprintk(4, "name %s\n", formats[index].name); - strlcpy(f->description, formats[index].name, sizeof(f->description)); - f->pixelformat = formats[index].fourcc; -@@ -2027,7 +2025,7 @@ static int save_frame(struct s2255_dev * - pdata[1]); - offset = jj + PREFIX_SIZE; - bframe = 1; -- cc = pdword[1]; -+ cc = le32_to_cpu(pdword[1]); - if (cc >= MAX_CHANNELS) { - printk(KERN_ERR - "bad channel\n"); -@@ -2036,22 +2034,22 @@ static int save_frame(struct s2255_dev * - /* reverse it */ - dev->cc = G_chnmap[cc]; - channel = &dev->channel[dev->cc]; -- payload = pdword[3]; -+ payload = le32_to_cpu(pdword[3]); - if (payload > channel->req_image_size) { - channel->bad_payload++; - /* discard the bad frame */ - return -EINVAL; - } - channel->pkt_size = payload; -- channel->jpg_size = pdword[4]; -+ channel->jpg_size = le32_to_cpu(pdword[4]); - break; - case S2255_MARKER_RESPONSE: - - pdata += DEF_USB_BLOCK; - jj += DEF_USB_BLOCK; -- if (pdword[1] >= MAX_CHANNELS) -+ if (le32_to_cpu(pdword[1]) >= MAX_CHANNELS) - break; -- cc = G_chnmap[pdword[1]]; -+ cc = G_chnmap[le32_to_cpu(pdword[1])]; - if (cc >= MAX_CHANNELS) - break; - channel = &dev->channel[cc]; -@@ -2074,11 +2072,11 @@ static int save_frame(struct s2255_dev * - wake_up(&dev->fw_data->wait_fw); - break; - case S2255_RESPONSE_STATUS: -- channel->vidstatus = pdword[3]; -+ channel->vidstatus = le32_to_cpu(pdword[3]); - channel->vidstatus_ready = 1; - wake_up(&channel->wait_vidstatus); - dprintk(5, "got vidstatus %x chan %d\n", -- pdword[3], cc); -+ le32_to_cpu(pdword[3]), cc); - break; - default: - printk(KERN_INFO "s2255 unknown resp\n"); -@@ -2605,10 +2603,11 @@ static int s2255_probe(struct usb_interf - __le32 *pRel; - pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4]; - printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel); -- dev->dsp_fw_ver = *pRel; -- if (*pRel < S2255_CUR_DSP_FWVER) -+ dev->dsp_fw_ver = le32_to_cpu(*pRel); -+ if (dev->dsp_fw_ver < S2255_CUR_DSP_FWVER) - printk(KERN_INFO "s2255: f2255usb.bin out of date.\n"); -- if (dev->pid == 0x2257 && *pRel < S2255_MIN_DSP_COLORFILTER) -+ if (dev->pid == 0x2257 && -+ dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER) - printk(KERN_WARNING "s2255: 2257 requires firmware %d" - " or above.\n", S2255_MIN_DSP_COLORFILTER); - } -Index: linux-3.3.x86_64/drivers/media/common/tuners/Makefile -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/common/tuners/Makefile -+++ linux-3.3.x86_64/drivers/media/common/tuners/Makefile -@@ -28,6 +28,8 @@ obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc - obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o - obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o - obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o -+obj-$(CONFIG_MEDIA_TUNER_TUA9001) += tua9001.o -+obj-$(CONFIG_MEDIA_TUNER_FC0011) += fc0011.o - --ccflags-y += -Idrivers/media/dvb/dvb-core --ccflags-y += -Idrivers/media/dvb/frontends -+ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core -+ccflags-y += -I$(srctree)/drivers/media/dvb/frontends -Index: linux-3.3.x86_64/drivers/media/video/saa7134/Makefile -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/saa7134/Makefile -+++ linux-3.3.x86_64/drivers/media/video/saa7134/Makefile -@@ -10,7 +10,7 @@ obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7 - - obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o - --ccflags-y += -Idrivers/media/video --ccflags-y += -Idrivers/media/common/tuners --ccflags-y += -Idrivers/media/dvb/dvb-core --ccflags-y += -Idrivers/media/dvb/frontends -+ccflags-y += -I$(srctree)/drivers/media/video -+ccflags-y += -I$(srctree)/drivers/media/common/tuners -+ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core -+ccflags-y += -I$(srctree)/drivers/media/dvb/frontends -Index: linux-3.3.x86_64/drivers/media/video/saa7164/Makefile -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/saa7164/Makefile -+++ linux-3.3.x86_64/drivers/media/video/saa7164/Makefile -@@ -4,9 +4,9 @@ saa7164-objs := saa7164-cards.o saa7164- - - obj-$(CONFIG_VIDEO_SAA7164) += saa7164.o - --ccflags-y += -Idrivers/media/video --ccflags-y += -Idrivers/media/common/tuners --ccflags-y += -Idrivers/media/dvb/dvb-core --ccflags-y += -Idrivers/media/dvb/frontends -+ccflags-y += -I$(srctree)/drivers/media/video -+ccflags-y += -I$(srctree)/drivers/media/common/tuners -+ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core -+ccflags-y += -I$(srctree)/drivers/media/dvb/frontends - - ccflags-y += $(extra-cflags-y) $(extra-cflags-m) -Index: linux-3.3.x86_64/drivers/media/video/ivtv/Makefile -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ivtv/Makefile -+++ linux-3.3.x86_64/drivers/media/video/ivtv/Makefile -@@ -7,8 +7,8 @@ ivtv-objs := ivtv-routing.o ivtv-cards.o - obj-$(CONFIG_VIDEO_IVTV) += ivtv.o - obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o - --ccflags-y += -Idrivers/media/video --ccflags-y += -Idrivers/media/common/tuners --ccflags-y += -Idrivers/media/dvb/dvb-core --ccflags-y += -Idrivers/media/dvb/frontends -+ccflags-y += -I$(srctree)/drivers/media/video -+ccflags-y += -I$(srctree)/drivers/media/common/tuners -+ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core -+ccflags-y += -I$(srctree)/drivers/media/dvb/frontends - -Index: linux-3.3.x86_64/drivers/media/video/gspca/gl860/Makefile -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/gspca/gl860/Makefile -+++ linux-3.3.x86_64/drivers/media/video/gspca/gl860/Makefile -@@ -6,5 +6,5 @@ gspca_gl860-objs := gl860.o \ - gl860-ov9655.o \ - gl860-mi2020.o - --ccflags-y += -Idrivers/media/video/gspca -+ccflags-y += -I$(srctree)/drivers/media/video/gspca - -Index: linux-3.3.x86_64/drivers/media/video/gspca/m5602/Makefile -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/gspca/m5602/Makefile -+++ linux-3.3.x86_64/drivers/media/video/gspca/m5602/Makefile -@@ -8,4 +8,4 @@ gspca_m5602-objs := m5602_core.o \ - m5602_s5k83a.o \ - m5602_s5k4aa.o - --ccflags-y += -Idrivers/media/video/gspca -+ccflags-y += -I$(srctree)/drivers/media/video/gspca -Index: linux-3.3.x86_64/drivers/media/video/gspca/stv06xx/Makefile -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/gspca/stv06xx/Makefile -+++ linux-3.3.x86_64/drivers/media/video/gspca/stv06xx/Makefile -@@ -6,5 +6,5 @@ gspca_stv06xx-objs := stv06xx.o \ - stv06xx_pb0100.o \ - stv06xx_st6422.o - --ccflags-y += -Idrivers/media/video/gspca -+ccflags-y += -I$(srctree)/drivers/media/video/gspca - -Index: linux-3.3.x86_64/Documentation/dvb/cards.txt -=================================================================== ---- linux-3.3.x86_64.orig/Documentation/dvb/cards.txt -+++ linux-3.3.x86_64/Documentation/dvb/cards.txt -@@ -119,4 +119,5 @@ o Cards based on the Phillips saa7134 PC - - Compro Videomate DVB-T300 - - Compro Videomate DVB-T200 - - AVerMedia AVerTVHD MCE A180 -+ - KWorld PC150-U ATSC Hybrid - -Index: linux-3.3.x86_64/drivers/media/rc/keymaps/rc-kworld-pc150u.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/rc/keymaps/rc-kworld-pc150u.c -@@ -0,0 +1,102 @@ -+/* kworld-pc150u.c - Keytable for kworld_pc150u Remote Controller -+ * -+ * keymap imported from ir-keymaps.c -+ * -+ * Copyright (c) 2010 by Kyle Strickland -+ * (based on kworld-plus-tv-analog.c by -+ * Mauro Carvalho Chehab ) -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include -+#include -+ -+/* Kworld PC150-U -+ Kyle Strickland -+ */ -+ -+static struct rc_map_table kworld_pc150u[] = { -+ { 0x0c, KEY_MEDIA }, /* Kworld key */ -+ { 0x16, KEY_EJECTCLOSECD }, /* -> ) */ -+ { 0x1d, KEY_POWER2 }, -+ -+ { 0x00, KEY_1 }, -+ { 0x01, KEY_2 }, -+ { 0x02, KEY_3 }, -+ { 0x03, KEY_4 }, -+ { 0x04, KEY_5 }, -+ { 0x05, KEY_6 }, -+ { 0x06, KEY_7 }, -+ { 0x07, KEY_8 }, -+ { 0x08, KEY_9 }, -+ { 0x0a, KEY_0 }, -+ -+ { 0x09, KEY_AGAIN }, -+ { 0x14, KEY_MUTE }, -+ -+ { 0x1e, KEY_LAST }, -+ { 0x17, KEY_ZOOM }, -+ { 0x1f, KEY_HOMEPAGE }, -+ { 0x0e, KEY_ESC }, -+ -+ { 0x20, KEY_UP }, -+ { 0x21, KEY_DOWN }, -+ { 0x42, KEY_LEFT }, -+ { 0x43, KEY_RIGHT }, -+ { 0x0b, KEY_ENTER }, -+ -+ { 0x10, KEY_CHANNELUP }, -+ { 0x11, KEY_CHANNELDOWN }, -+ -+ { 0x13, KEY_VOLUMEUP }, -+ { 0x12, KEY_VOLUMEDOWN }, -+ -+ { 0x19, KEY_TIME}, /* Timeshift */ -+ { 0x1a, KEY_STOP}, -+ { 0x1b, KEY_RECORD}, -+ { 0x4b, KEY_EMAIL}, -+ -+ { 0x40, KEY_REWIND}, -+ { 0x44, KEY_PLAYPAUSE}, -+ { 0x41, KEY_FORWARD}, -+ { 0x22, KEY_TEXT}, -+ -+ { 0x15, KEY_AUDIO}, /* ((*)) */ -+ { 0x0f, KEY_MODE}, /* display ratio */ -+ { 0x1c, KEY_SYSRQ}, /* snapshot */ -+ { 0x4a, KEY_SLEEP}, /* sleep timer */ -+ -+ { 0x48, KEY_SOUND}, /* switch theater mode */ -+ { 0x49, KEY_BLUE}, /* A */ -+ { 0x18, KEY_RED}, /* B */ -+ { 0x23, KEY_GREEN}, /* C */ -+}; -+ -+static struct rc_map_list kworld_pc150u_map = { -+ .map = { -+ .scan = kworld_pc150u, -+ .size = ARRAY_SIZE(kworld_pc150u), -+ .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ -+ .name = RC_MAP_KWORLD_PC150U, -+ } -+}; -+ -+static int __init init_rc_map_kworld_pc150u(void) -+{ -+ return rc_map_register(&kworld_pc150u_map); -+} -+ -+static void __exit exit_rc_map_kworld_pc150u(void) -+{ -+ rc_map_unregister(&kworld_pc150u_map); -+} -+ -+module_init(init_rc_map_kworld_pc150u) -+module_exit(exit_rc_map_kworld_pc150u) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Kyle Strickland "); -Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-cards.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa7134-cards.c -+++ linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-cards.c -@@ -33,6 +33,7 @@ - #include "tea5767.h" - #include "tda18271.h" - #include "xc5000.h" -+#include "s5h1411.h" - - /* commly used strings */ - static char name_mute[] = "mute"; -@@ -5712,6 +5713,36 @@ struct saa7134_board saa7134_boards[] = - .amux = LINE1, - } }, - }, -+ [SAA7134_BOARD_KWORLD_PC150U] = { -+ .name = "Kworld PC150-U", -+ .audio_clock = 0x00187de7, -+ .tuner_type = TUNER_PHILIPS_TDA8290, -+ .radio_type = UNSET, -+ .tuner_addr = ADDR_UNSET, -+ .radio_addr = ADDR_UNSET, -+ .mpeg = SAA7134_MPEG_DVB, -+ .gpiomask = 1 << 21, -+ .ts_type = SAA7134_MPEG_TS_PARALLEL, -+ .inputs = { { -+ .name = name_tv, -+ .vmux = 1, -+ .amux = TV, -+ .tv = 1, -+ }, { -+ .name = name_comp, -+ .vmux = 3, -+ .amux = LINE1, -+ }, { -+ .name = name_svideo, -+ .vmux = 8, -+ .amux = LINE2, -+ } }, -+ .radio = { -+ .name = name_radio, -+ .amux = TV, -+ .gpio = 0x0000000, -+ }, -+ }, - - }; - -@@ -6306,6 +6337,12 @@ struct pci_device_id saa7134_pci_tbl[] = - .driver_data = SAA7134_BOARD_KWORLD_ATSC110, /* ATSC 115 */ - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, -+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ -+ .subvendor = 0x17de, -+ .subdevice = 0xa134, -+ .driver_data = SAA7134_BOARD_KWORLD_PC150U, -+ }, { -+ .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1461, - .subdevice = 0x7360, -@@ -7134,6 +7171,23 @@ static inline int saa7134_kworld_sbtvd_t - return 0; - } - -+static int saa7134_kworld_pc150u_toggle_agc(struct saa7134_dev *dev, -+ enum tda18271_mode mode) -+{ -+ switch (mode) { -+ case TDA18271_ANALOG: -+ saa7134_set_gpio(dev, 18, 0); -+ break; -+ case TDA18271_DIGITAL: -+ saa7134_set_gpio(dev, 18, 1); -+ msleep(30); -+ break; -+ default: -+ return -EINVAL; -+ } -+ return 0; -+} -+ - static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, - int command, int arg) - { -@@ -7150,6 +7204,9 @@ static int saa7134_tda8290_18271_callbac - case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: - ret = saa7134_kworld_sbtvd_toggle_agc(dev, arg); - break; -+ case SAA7134_BOARD_KWORLD_PC150U: -+ ret = saa7134_kworld_pc150u_toggle_agc(dev, arg); -+ break; - default: - break; - } -@@ -7171,6 +7228,7 @@ static int saa7134_tda8290_callback(stru - case SAA7134_BOARD_HAUPPAUGE_HVR1120: - case SAA7134_BOARD_AVERMEDIA_M733A: - case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: -+ case SAA7134_BOARD_KWORLD_PC150U: - case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2: - /* tda8290 + tda18271 */ - ret = saa7134_tda8290_18271_callback(dev, command, arg); -@@ -7452,6 +7510,7 @@ int saa7134_board_init1(struct saa7134_d - case SAA7134_BOARD_BEHOLD_X7: - case SAA7134_BOARD_BEHOLD_H7: - case SAA7134_BOARD_BEHOLD_A7: -+ case SAA7134_BOARD_KWORLD_PC150U: - dev->has_remote = SAA7134_REMOTE_I2C; - break; - case SAA7134_BOARD_AVERMEDIA_A169_B: -Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-dvb.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa7134-dvb.c -+++ linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-dvb.c -@@ -61,6 +61,7 @@ - #include "zl10036.h" - #include "zl10039.h" - #include "mt312.h" -+#include "s5h1411.h" - - MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); - MODULE_LICENSE("GPL"); -@@ -1158,6 +1159,33 @@ static struct tda18271_config prohdtv_pr - .output_opt = TDA18271_OUTPUT_LT_OFF, - }; - -+static struct tda18271_std_map kworld_tda18271_std_map = { -+ .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 3, -+ .if_lvl = 6, .rfagc_top = 0x37 }, -+ .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 0, -+ .if_lvl = 6, .rfagc_top = 0x37 }, -+}; -+ -+static struct tda18271_config kworld_pc150u_tda18271_config = { -+ .std_map = &kworld_tda18271_std_map, -+ .gate = TDA18271_GATE_ANALOG, -+ .output_opt = TDA18271_OUTPUT_LT_OFF, -+ .config = 3, /* Use tuner callback for AGC */ -+ .rf_cal_on_startup = 1 -+}; -+ -+static struct s5h1411_config kworld_s5h1411_config = { -+ .output_mode = S5H1411_PARALLEL_OUTPUT, -+ .gpio = S5H1411_GPIO_OFF, -+ .qam_if = S5H1411_IF_4000, -+ .vsb_if = S5H1411_IF_3250, -+ .inversion = S5H1411_INVERSION_ON, -+ .status_mode = S5H1411_DEMODLOCKING, -+ .mpeg_timing = -+ S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, -+}; -+ -+ - /* ================================================================== - * Core code - */ -@@ -1438,6 +1466,22 @@ static int dvb_init(struct saa7134_dev * - &dev->i2c_adap, 0x61, - TUNER_PHILIPS_TUV1236D); - break; -+ case SAA7134_BOARD_KWORLD_PC150U: -+ saa7134_set_gpio(dev, 18, 1); /* Switch to digital mode */ -+ saa7134_tuner_callback(dev, 0, -+ TDA18271_CALLBACK_CMD_AGC_ENABLE, 1); -+ fe0->dvb.frontend = dvb_attach(s5h1411_attach, -+ &kworld_s5h1411_config, -+ &dev->i2c_adap); -+ if (fe0->dvb.frontend != NULL) { -+ dvb_attach(tda829x_attach, fe0->dvb.frontend, -+ &dev->i2c_adap, 0x4b, -+ &tda829x_no_probe); -+ dvb_attach(tda18271_attach, fe0->dvb.frontend, -+ 0x60, &dev->i2c_adap, -+ &kworld_pc150u_tda18271_config); -+ } -+ break; - case SAA7134_BOARD_FLYDVBS_LR300: - fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, - &dev->i2c_adap); -Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-i2c.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa7134-i2c.c -+++ linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-i2c.c -@@ -254,7 +254,9 @@ static int saa7134_i2c_xfer(struct i2c_a - addr = msgs[i].addr << 1; - if (msgs[i].flags & I2C_M_RD) - addr |= 1; -- if (i > 0 && msgs[i].flags & I2C_M_RD && msgs[i].addr != 0x40) { -+ if (i > 0 && msgs[i].flags & -+ I2C_M_RD && msgs[i].addr != 0x40 && -+ msgs[i].addr != 0x19) { - /* workaround for a saa7134 i2c bug - * needed to talk to the mt352 demux - * thanks to pinnacle for the hint */ -@@ -279,6 +281,16 @@ static int saa7134_i2c_xfer(struct i2c_a - d1printk("%02x", rc); - msgs[i].buf[byte] = rc; - } -+ /* discard mysterious extra byte when reading -+ from Samsung S5H1411. i2c bus gets error -+ if we do not. */ -+ if (0x19 == msgs[i].addr) { -+ d1printk(" ?"); -+ rc = i2c_recv_byte(dev); -+ if (rc < 0) -+ goto err; -+ d1printk("%02x", rc); -+ } - } else { - /* write bytes */ - d2printk("write bytes\n"); -Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-input.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa7134-input.c -+++ linux-3.3.x86_64/drivers/media/video/saa7134/saa7134-input.c -@@ -210,6 +210,54 @@ static int get_key_msi_tvanywhere_plus(s - return 1; - } - -+/* copied and modified from get_key_msi_tvanywhere_plus() */ -+static int get_key_kworld_pc150u(struct IR_i2c *ir, u32 *ir_key, -+ u32 *ir_raw) -+{ -+ unsigned char b; -+ unsigned int gpio; -+ -+ /* is needed to access GPIO. Used by the saa_readl macro. */ -+ struct saa7134_dev *dev = ir->c->adapter->algo_data; -+ if (dev == NULL) { -+ i2cdprintk("get_key_kworld_pc150u: " -+ "ir->c->adapter->algo_data is NULL!\n"); -+ return -EIO; -+ } -+ -+ /* rising SAA7134_GPIO_GPRESCAN reads the status */ -+ -+ saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); -+ saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); -+ -+ gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); -+ -+ /* GPIO&0x100 is pulsed low when a button is pressed. Don't do -+ I2C receive if gpio&0x100 is not low. */ -+ -+ if (gpio & 0x100) -+ return 0; /* No button press */ -+ -+ /* GPIO says there is a button press. Get it. */ -+ -+ if (1 != i2c_master_recv(ir->c, &b, 1)) { -+ i2cdprintk("read error\n"); -+ return -EIO; -+ } -+ -+ /* No button press */ -+ -+ if (b == 0xff) -+ return 0; -+ -+ /* Button pressed */ -+ -+ dprintk("get_key_kworld_pc150u: Key = 0x%02X\n", b); -+ *ir_key = b; -+ *ir_raw = b; -+ return 1; -+} -+ - static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) - { - unsigned char b; -@@ -894,6 +942,21 @@ void saa7134_probe_i2c_ir(struct saa7134 - info.addr = 0x30; - /* MSI TV@nywhere Plus controller doesn't seem to - respond to probes unless we read something from -+ an existing device. Weird... -+ REVISIT: might no longer be needed */ -+ rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); -+ dprintk("probe 0x%02x @ %s: %s\n", -+ msg_msi.addr, dev->i2c_adap.name, -+ (1 == rc) ? "yes" : "no"); -+ break; -+ case SAA7134_BOARD_KWORLD_PC150U: -+ /* copied and modified from MSI TV@nywhere Plus */ -+ dev->init_data.name = "Kworld PC150-U"; -+ dev->init_data.get_key = get_key_kworld_pc150u; -+ dev->init_data.ir_codes = RC_MAP_KWORLD_PC150U; -+ info.addr = 0x30; -+ /* MSI TV@nywhere Plus controller doesn't seem to -+ respond to probes unless we read something from - an existing device. Weird... - REVISIT: might no longer be needed */ - rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); -Index: linux-3.3.x86_64/drivers/media/video/saa7134/saa7134.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/saa7134/saa7134.h -+++ linux-3.3.x86_64/drivers/media/video/saa7134/saa7134.h -@@ -126,8 +126,8 @@ struct saa7134_card_ir { - unsigned users; - - u32 polling; -- u32 last_gpio; -- u32 mask_keycode, mask_keydown, mask_keyup; -+ u32 last_gpio; -+ u32 mask_keycode, mask_keydown, mask_keyup; - - bool running; - bool active; -@@ -331,6 +331,7 @@ struct saa7134_card_ir { - #define SAA7134_BOARD_BEHOLD_501 186 - #define SAA7134_BOARD_BEHOLD_503FM 187 - #define SAA7134_BOARD_SENSORAY811_911 188 -+#define SAA7134_BOARD_KWORLD_PC150U 189 - - #define SAA7134_MAXBOARDS 32 - #define SAA7134_INPUT_MAX 8 -Index: linux-3.3.x86_64/drivers/media/video/cx18/cx18-driver.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/cx18/cx18-driver.c -+++ linux-3.3.x86_64/drivers/media/video/cx18/cx18-driver.c -@@ -38,7 +38,7 @@ - #include "cx18-ioctl.h" - #include "cx18-controls.h" - #include "tuner-xc2028.h" -- -+#include - #include - - /* If you have already X v4l cards, then set this to X. This way -@@ -75,7 +75,7 @@ static int radio[CX18_MAX_CARDS] = { -1, - -1, -1, -1, -1, -1, -1, -1, -1 }; - static unsigned cardtype_c = 1; - static unsigned tuner_c = 1; --static bool radio_c = 1; -+static unsigned radio_c = 1; - static char pal[] = "--"; - static char secam[] = "--"; - static char ntsc[] = "-"; -@@ -110,7 +110,7 @@ static int retry_mmio = 1; - int cx18_debug; - - module_param_array(tuner, int, &tuner_c, 0644); --module_param_array(radio, bool, &radio_c, 0644); -+module_param_array(radio, int, &radio_c, 0644); - module_param_array(cardtype, int, &cardtype_c, 0644); - module_param_string(pal, pal, sizeof(pal), 0644); - module_param_string(secam, secam, sizeof(secam), 0644); -@@ -812,7 +812,7 @@ static int cx18_setup_pci(struct cx18 *c - CX18_ERR("Can't enable device %d!\n", cx->instance); - return -EIO; - } -- if (pci_set_dma_mask(pci_dev, 0xffffffff)) { -+ if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32))) { - CX18_ERR("No suitable DMA available, card %d\n", cx->instance); - return -EIO; - } -Index: linux-3.3.x86_64/drivers/media/rc/Kconfig -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/rc/Kconfig -+++ linux-3.3.x86_64/drivers/media/rc/Kconfig -@@ -266,4 +266,13 @@ config RC_LOOPBACK - To compile this driver as a module, choose M here: the module will - be called rc_loopback. - -+config IR_GPIO_CIR -+ tristate "GPIO IR remote control" -+ depends on RC_CORE -+ ---help--- -+ Say Y if you want to use GPIO based IR Receiver. -+ -+ To compile this driver as a module, choose M here: the module will -+ be called gpio-ir-recv. -+ - endif #RC_CORE -Index: linux-3.3.x86_64/drivers/media/rc/Makefile -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/rc/Makefile -+++ linux-3.3.x86_64/drivers/media/rc/Makefile -@@ -26,3 +26,4 @@ obj-$(CONFIG_IR_REDRAT3) += redrat3.o - obj-$(CONFIG_IR_STREAMZAP) += streamzap.o - obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o - obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o -+obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.o -Index: linux-3.3.x86_64/drivers/media/rc/gpio-ir-recv.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/rc/gpio-ir-recv.c -@@ -0,0 +1,205 @@ -+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define GPIO_IR_DRIVER_NAME "gpio-rc-recv" -+#define GPIO_IR_DEVICE_NAME "gpio_ir_recv" -+ -+struct gpio_rc_dev { -+ struct rc_dev *rcdev; -+ int gpio_nr; -+ bool active_low; -+}; -+ -+static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id) -+{ -+ struct gpio_rc_dev *gpio_dev = dev_id; -+ int gval; -+ int rc = 0; -+ enum raw_event_type type = IR_SPACE; -+ -+ gval = gpio_get_value_cansleep(gpio_dev->gpio_nr); -+ -+ if (gval < 0) -+ goto err_get_value; -+ -+ if (gpio_dev->active_low) -+ gval = !gval; -+ -+ if (gval == 1) -+ type = IR_PULSE; -+ -+ rc = ir_raw_event_store_edge(gpio_dev->rcdev, type); -+ if (rc < 0) -+ goto err_get_value; -+ -+ ir_raw_event_handle(gpio_dev->rcdev); -+ -+err_get_value: -+ return IRQ_HANDLED; -+} -+ -+static int __devinit gpio_ir_recv_probe(struct platform_device *pdev) -+{ -+ struct gpio_rc_dev *gpio_dev; -+ struct rc_dev *rcdev; -+ const struct gpio_ir_recv_platform_data *pdata = -+ pdev->dev.platform_data; -+ int rc; -+ -+ if (!pdata) -+ return -EINVAL; -+ -+ if (pdata->gpio_nr < 0) -+ return -EINVAL; -+ -+ gpio_dev = kzalloc(sizeof(struct gpio_rc_dev), GFP_KERNEL); -+ if (!gpio_dev) -+ return -ENOMEM; -+ -+ rcdev = rc_allocate_device(); -+ if (!rcdev) { -+ rc = -ENOMEM; -+ goto err_allocate_device; -+ } -+ -+ rcdev->driver_type = RC_DRIVER_IR_RAW; -+ rcdev->allowed_protos = RC_TYPE_ALL; -+ rcdev->input_name = GPIO_IR_DEVICE_NAME; -+ rcdev->input_id.bustype = BUS_HOST; -+ rcdev->driver_name = GPIO_IR_DRIVER_NAME; -+ rcdev->map_name = RC_MAP_EMPTY; -+ -+ gpio_dev->rcdev = rcdev; -+ gpio_dev->gpio_nr = pdata->gpio_nr; -+ gpio_dev->active_low = pdata->active_low; -+ -+ rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv"); -+ if (rc < 0) -+ goto err_gpio_request; -+ rc = gpio_direction_input(pdata->gpio_nr); -+ if (rc < 0) -+ goto err_gpio_direction_input; -+ -+ rc = rc_register_device(rcdev); -+ if (rc < 0) { -+ dev_err(&pdev->dev, "failed to register rc device\n"); -+ goto err_register_rc_device; -+ } -+ -+ platform_set_drvdata(pdev, gpio_dev); -+ -+ rc = request_any_context_irq(gpio_to_irq(pdata->gpio_nr), -+ gpio_ir_recv_irq, -+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, -+ "gpio-ir-recv-irq", gpio_dev); -+ if (rc < 0) -+ goto err_request_irq; -+ -+ return 0; -+ -+err_request_irq: -+ platform_set_drvdata(pdev, NULL); -+ rc_unregister_device(rcdev); -+err_register_rc_device: -+err_gpio_direction_input: -+ gpio_free(pdata->gpio_nr); -+err_gpio_request: -+ rc_free_device(rcdev); -+ rcdev = NULL; -+err_allocate_device: -+ kfree(gpio_dev); -+ return rc; -+} -+ -+static int __devexit gpio_ir_recv_remove(struct platform_device *pdev) -+{ -+ struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); -+ -+ free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev); -+ platform_set_drvdata(pdev, NULL); -+ rc_unregister_device(gpio_dev->rcdev); -+ gpio_free(gpio_dev->gpio_nr); -+ rc_free_device(gpio_dev->rcdev); -+ kfree(gpio_dev); -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int gpio_ir_recv_suspend(struct device *dev) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); -+ -+ if (device_may_wakeup(dev)) -+ enable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr)); -+ else -+ disable_irq(gpio_to_irq(gpio_dev->gpio_nr)); -+ -+ return 0; -+} -+ -+static int gpio_ir_recv_resume(struct device *dev) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); -+ -+ if (device_may_wakeup(dev)) -+ disable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr)); -+ else -+ enable_irq(gpio_to_irq(gpio_dev->gpio_nr)); -+ -+ return 0; -+} -+ -+static const struct dev_pm_ops gpio_ir_recv_pm_ops = { -+ .suspend = gpio_ir_recv_suspend, -+ .resume = gpio_ir_recv_resume, -+}; -+#endif -+ -+static struct platform_driver gpio_ir_recv_driver = { -+ .probe = gpio_ir_recv_probe, -+ .remove = __devexit_p(gpio_ir_recv_remove), -+ .driver = { -+ .name = GPIO_IR_DRIVER_NAME, -+ .owner = THIS_MODULE, -+#ifdef CONFIG_PM -+ .pm = &gpio_ir_recv_pm_ops, -+#endif -+ }, -+}; -+ -+static int __init gpio_ir_recv_init(void) -+{ -+ return platform_driver_register(&gpio_ir_recv_driver); -+} -+module_init(gpio_ir_recv_init); -+ -+static void __exit gpio_ir_recv_exit(void) -+{ -+ platform_driver_unregister(&gpio_ir_recv_driver); -+} -+module_exit(gpio_ir_recv_exit); -+ -+MODULE_DESCRIPTION("GPIO IR Receiver driver"); -+MODULE_LICENSE("GPL v2"); -Index: linux-3.3.x86_64/include/media/gpio-ir-recv.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/include/media/gpio-ir-recv.h -@@ -0,0 +1,22 @@ -+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#ifndef __GPIO_IR_RECV_H__ -+#define __GPIO_IR_RECV_H__ -+ -+struct gpio_ir_recv_platform_data { -+ int gpio_nr; -+ bool active_low; -+}; -+ -+#endif /* __GPIO_IR_RECV_H__ */ -+ -Index: linux-3.3.x86_64/drivers/media/rc/ir-sony-decoder.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/rc/ir-sony-decoder.c -+++ linux-3.3.x86_64/drivers/media/rc/ir-sony-decoder.c -@@ -130,7 +130,7 @@ static int ir_sony_decode(struct rc_dev - case 15: - device = bitrev8((data->bits >> 0) & 0xFF); - subdevice = 0; -- function = bitrev8((data->bits >> 7) & 0xFD); -+ function = bitrev8((data->bits >> 7) & 0xFE); - break; - case 20: - device = bitrev8((data->bits >> 5) & 0xF8); -Index: linux-3.3.x86_64/drivers/media/video/cx25821/cx25821-core.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/cx25821/cx25821-core.c -+++ linux-3.3.x86_64/drivers/media/video/cx25821/cx25821-core.c -@@ -1474,8 +1474,13 @@ static DEFINE_PCI_DEVICE_TABLE(cx25821_p - .device = 0x8210, - .subvendor = 0x14f1, - .subdevice = 0x0920, -- }, -- { -+ }, { -+ /* CX25821 No Brand */ -+ .vendor = 0x14f1, -+ .device = 0x8210, -+ .subvendor = 0x0000, -+ .subdevice = 0x0000, -+ }, { - /* --- end of list --- */ - } - }; -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/dib0090.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/dib0090.c -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/dib0090.c -@@ -519,7 +519,7 @@ static int dib0090_fw_identify(struct dv - return 0; - - identification_error: -- return -EIO;; -+ return -EIO; - } - - static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg) -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/stb0899_drv.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/stb0899_drv.c -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/stb0899_drv.c -@@ -67,7 +67,7 @@ static const struct stb0899_tab stb0899_ - * Crude linear extrapolation below -84.8dBm and above -8.0dBm. - */ - static const struct stb0899_tab stb0899_dvbsrf_tab[] = { -- { -950, -128 }, -+ { -750, -128 }, - { -748, -94 }, - { -745, -92 }, - { -735, -90 }, -@@ -131,7 +131,7 @@ static const struct stb0899_tab stb0899_ - { -730, 13645 }, - { -750, 13909 }, - { -766, 14153 }, -- { -999, 16383 } -+ { -950, 16383 } - }; - - /* DVB-S2 Es/N0 quant in dB/100 vs read value * 100*/ -@@ -964,6 +964,7 @@ static int stb0899_read_signal_strength( - - int val; - u32 reg; -+ *strength = 0; - switch (state->delsys) { - case SYS_DVBS: - case SYS_DSS: -@@ -983,11 +984,11 @@ static int stb0899_read_signal_strength( - break; - case SYS_DVBS2: - if (internal->lock) { -- reg = STB0899_READ_S2REG(STB0899_DEMOD, IF_AGC_GAIN); -+ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_GAIN); - val = STB0899_GETFIELD(IF_AGC_GAIN, reg); - - *strength = stb0899_table_lookup(stb0899_dvbs2rf_tab, ARRAY_SIZE(stb0899_dvbs2rf_tab) - 1, val); -- *strength += 750; -+ *strength += 950; - dprintk(state->verbose, FE_DEBUG, 1, "IF_AGC_GAIN = 0x%04x, C = %d * 0.1 dBm", - val & 0x3fff, *strength); - } -@@ -1009,6 +1010,7 @@ static int stb0899_read_snr(struct dvb_f - u8 buf[2]; - u32 reg; - -+ *snr = 0; - reg = stb0899_read_reg(state, STB0899_VSTATUS); - switch (state->delsys) { - case SYS_DVBS: -@@ -1071,7 +1073,7 @@ static int stb0899_read_status(struct dv - reg = stb0899_read_reg(state, STB0899_VSTATUS); - if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) { - dprintk(state->verbose, FE_DEBUG, 1, "--------> FE_HAS_CARRIER | FE_HAS_LOCK"); -- *status |= FE_HAS_CARRIER | FE_HAS_LOCK; -+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK; - - reg = stb0899_read_reg(state, STB0899_PLPARM); - if (STB0899_GETFIELD(VITCURPUN, reg)) { -Index: linux-3.3.x86_64/include/sound/tea575x-tuner.h -=================================================================== ---- linux-3.3.x86_64.orig/include/sound/tea575x-tuner.h -+++ linux-3.3.x86_64/include/sound/tea575x-tuner.h -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - - #define TEA575X_FMIF 10700 - -@@ -42,13 +43,16 @@ struct snd_tea575x_ops { - }; - - struct snd_tea575x { -+ struct v4l2_device *v4l2_dev; - struct video_device vd; /* video device */ -+ int radio_nr; /* radio_nr */ - bool tea5759; /* 5759 chip is present */ -+ bool cannot_read_data; /* Device cannot read the data pin */ - bool mute; /* Device is muted? */ - bool stereo; /* receiving stereo */ - bool tuned; /* tuned to a station */ - unsigned int val; /* hw value */ -- unsigned long freq; /* frequency */ -+ u32 freq; /* frequency */ - struct mutex mutex; - struct snd_tea575x_ops *ops; - void *private_data; -Index: linux-3.3.x86_64/sound/i2c/other/tea575x-tuner.c -=================================================================== ---- linux-3.3.x86_64.orig/sound/i2c/other/tea575x-tuner.c -+++ linux-3.3.x86_64/sound/i2c/other/tea575x-tuner.c -@@ -25,21 +25,20 @@ - #include - #include - #include --#include -+#include -+#include - #include -+#include - #include -+#include - #include - - MODULE_AUTHOR("Jaroslav Kysela "); - MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); - MODULE_LICENSE("GPL"); - --static int radio_nr = -1; --module_param(radio_nr, int, 0); -- --#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) --#define FREQ_LO (50UL * 16000) --#define FREQ_HI (150UL * 16000) -+#define FREQ_LO (76U * 16000) -+#define FREQ_HI (108U * 16000) - - /* - * definitions -@@ -121,28 +120,10 @@ static unsigned int snd_tea575x_read(str - return data; - } - --static void snd_tea575x_get_freq(struct snd_tea575x *tea) --{ -- unsigned long freq; -- -- freq = snd_tea575x_read(tea) & TEA575X_BIT_FREQ_MASK; -- /* freq *= 12.5 */ -- freq *= 125; -- freq /= 10; -- /* crystal fixup */ -- if (tea->tea5759) -- freq += TEA575X_FMIF; -- else -- freq -= TEA575X_FMIF; -- -- tea->freq = freq * 16; /* from kHz */ --} -- - static void snd_tea575x_set_freq(struct snd_tea575x *tea) - { -- unsigned long freq; -+ u32 freq = tea->freq; - -- freq = clamp(tea->freq, FREQ_LO, FREQ_HI); - freq /= 16; /* to kHz */ - /* crystal fixup */ - if (tea->tea5759) -@@ -167,12 +148,14 @@ static int vidioc_querycap(struct file * - { - struct snd_tea575x *tea = video_drvdata(file); - -- strlcpy(v->driver, "tea575x-tuner", sizeof(v->driver)); -+ strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); - strlcpy(v->card, tea->card, sizeof(v->card)); - strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); - strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); -- v->version = RADIO_VERSION; -- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; -+ v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; -+ if (!tea->cannot_read_data) -+ v->device_caps |= V4L2_CAP_HW_FREQ_SEEK; -+ v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; - } - -@@ -191,18 +174,24 @@ static int vidioc_g_tuner(struct file *f - v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; - v->rangelow = FREQ_LO; - v->rangehigh = FREQ_HI; -- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; -- v->audmode = tea->stereo ? V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO; -+ v->rxsubchans = tea->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; -+ v->audmode = (tea->val & TEA575X_BIT_MONO) ? -+ V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO; - v->signal = tea->tuned ? 0xffff : 0; -- - return 0; - } - - static int vidioc_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *v) - { -- if (v->index > 0) -+ struct snd_tea575x *tea = video_drvdata(file); -+ -+ if (v->index) - return -EINVAL; -+ tea->val &= ~TEA575X_BIT_MONO; -+ if (v->audmode == V4L2_TUNER_MODE_MONO) -+ tea->val |= TEA575X_BIT_MONO; -+ snd_tea575x_write(tea, tea->val); - return 0; - } - -@@ -214,7 +203,6 @@ static int vidioc_g_frequency(struct fil - if (f->tuner != 0) - return -EINVAL; - f->type = V4L2_TUNER_RADIO; -- snd_tea575x_get_freq(tea); - f->frequency = tea->freq; - return 0; - } -@@ -227,32 +215,47 @@ static int vidioc_s_frequency(struct fil - if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) - return -EINVAL; - -- if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) -- return -EINVAL; -- -- tea->freq = f->frequency; -- -+ tea->val &= ~TEA575X_BIT_SEARCH; -+ tea->freq = clamp(f->frequency, FREQ_LO, FREQ_HI); - snd_tea575x_set_freq(tea); -- - return 0; - } - --static int vidioc_g_audio(struct file *file, void *priv, -- struct v4l2_audio *a) -+static int vidioc_s_hw_freq_seek(struct file *file, void *fh, -+ struct v4l2_hw_freq_seek *a) - { -- if (a->index > 1) -- return -EINVAL; -- -- strcpy(a->name, "Radio"); -- a->capability = V4L2_AUDCAP_STEREO; -- return 0; --} -+ struct snd_tea575x *tea = video_drvdata(file); - --static int vidioc_s_audio(struct file *file, void *priv, -- struct v4l2_audio *a) --{ -- if (a->index != 0) -+ if (tea->cannot_read_data) -+ return -ENOTTY; -+ if (a->tuner || a->wrap_around) - return -EINVAL; -+ tea->val |= TEA575X_BIT_SEARCH; -+ tea->val &= ~TEA575X_BIT_UPDOWN; -+ if (a->seek_upward) -+ tea->val |= TEA575X_BIT_UPDOWN; -+ snd_tea575x_write(tea, tea->val); -+ for (;;) { -+ unsigned val = snd_tea575x_read(tea); -+ -+ if (!(val & TEA575X_BIT_SEARCH)) { -+ /* Found a frequency */ -+ val &= TEA575X_BIT_FREQ_MASK; -+ val = (val * 10) / 125; -+ if (tea->tea5759) -+ val += TEA575X_FMIF; -+ else -+ val -= TEA575X_FMIF; -+ tea->freq = clamp(val * 16, FREQ_LO, FREQ_HI); -+ return 0; -+ } -+ if (schedule_timeout_interruptible(msecs_to_jiffies(10))) { -+ /* some signal arrived, stop search */ -+ tea->val &= ~TEA575X_BIT_SEARCH; -+ snd_tea575x_write(tea, tea->val); -+ return -ERESTARTSYS; -+ } -+ } - return 0; - } - -@@ -273,23 +276,27 @@ static int tea575x_s_ctrl(struct v4l2_ct - static const struct v4l2_file_operations tea575x_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = video_ioctl2, -+ .open = v4l2_fh_open, -+ .release = v4l2_fh_release, -+ .poll = v4l2_ctrl_poll, - }; - - static const struct v4l2_ioctl_ops tea575x_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, -- .vidioc_g_audio = vidioc_g_audio, -- .vidioc_s_audio = vidioc_s_audio, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, -+ .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek, -+ .vidioc_log_status = v4l2_ctrl_log_status, -+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, -+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - }; - --static struct video_device tea575x_radio = { -- .name = "tea575x-tuner", -+static const struct video_device tea575x_radio = { - .fops = &tea575x_fops, - .ioctl_ops = &tea575x_ioctl_ops, -- .release = video_device_release_empty, -+ .release = video_device_release_empty, - }; - - static const struct v4l2_ctrl_ops tea575x_ctrl_ops = { -@@ -303,11 +310,15 @@ int snd_tea575x_init(struct snd_tea575x - { - int retval; - -- tea->mute = 1; -+ tea->mute = true; - -- snd_tea575x_write(tea, 0x55AA); -- if (snd_tea575x_read(tea) != 0x55AA) -- return -ENODEV; -+ /* Not all devices can or know how to read the data back. -+ Such devices can set cannot_read_data to true. */ -+ if (!tea->cannot_read_data) { -+ snd_tea575x_write(tea, 0x55AA); -+ if (snd_tea575x_read(tea) != 0x55AA) -+ return -ENODEV; -+ } - - tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40; - tea->freq = 90500 * 16; /* 90.5Mhz default */ -@@ -316,14 +327,17 @@ int snd_tea575x_init(struct snd_tea575x - tea->vd = tea575x_radio; - video_set_drvdata(&tea->vd, tea); - mutex_init(&tea->mutex); -+ strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name)); - tea->vd.lock = &tea->mutex; -+ tea->vd.v4l2_dev = tea->v4l2_dev; -+ tea->vd.ctrl_handler = &tea->ctrl_handler; -+ set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags); - - v4l2_ctrl_handler_init(&tea->ctrl_handler, 1); -- tea->vd.ctrl_handler = &tea->ctrl_handler; - v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops, V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); - retval = tea->ctrl_handler.error; - if (retval) { -- printk(KERN_ERR "tea575x-tuner: can't initialize controls\n"); -+ v4l2_err(tea->v4l2_dev, "can't initialize controls\n"); - v4l2_ctrl_handler_free(&tea->ctrl_handler); - return retval; - } -@@ -338,9 +352,9 @@ int snd_tea575x_init(struct snd_tea575x - - v4l2_ctrl_handler_setup(&tea->ctrl_handler); - -- retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, radio_nr); -+ retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->radio_nr); - if (retval) { -- printk(KERN_ERR "tea575x-tuner: can't register video device!\n"); -+ v4l2_err(tea->v4l2_dev, "can't register video device!\n"); - v4l2_ctrl_handler_free(&tea->ctrl_handler); - return retval; - } -Index: linux-3.3.x86_64/sound/pci/es1968.c -=================================================================== ---- linux-3.3.x86_64.orig/sound/pci/es1968.c -+++ linux-3.3.x86_64/sound/pci/es1968.c -@@ -142,6 +142,7 @@ static int enable_mpu[SNDRV_CARDS] = {[0 - #ifdef SUPPORT_JOYSTICK - static bool joystick[SNDRV_CARDS]; - #endif -+static int radio_nr[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; - - module_param_array(index, int, NULL, 0444); - MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -@@ -165,6 +166,9 @@ MODULE_PARM_DESC(enable_mpu, "Enable MPU - module_param_array(joystick, bool, NULL, 0444); - MODULE_PARM_DESC(joystick, "Enable joystick."); - #endif -+module_param_array(radio_nr, int, NULL, 0444); -+MODULE_PARM_DESC(radio_nr, "Radio device numbers"); -+ - - - #define NR_APUS 64 -@@ -558,6 +562,7 @@ struct es1968 { - struct work_struct hwvol_work; - - #ifdef CONFIG_SND_ES1968_RADIO -+ struct v4l2_device v4l2_dev; - struct snd_tea575x tea; - #endif - }; -@@ -2613,6 +2618,7 @@ static int snd_es1968_free(struct es1968 - - #ifdef CONFIG_SND_ES1968_RADIO - snd_tea575x_exit(&chip->tea); -+ v4l2_device_unregister(&chip->v4l2_dev); - #endif - - if (chip->irq >= 0) -@@ -2655,6 +2661,7 @@ static int __devinit snd_es1968_create(s - int capt_streams, - int chip_type, - int do_pm, -+ int radio_nr, - struct es1968 **chip_ret) - { - static struct snd_device_ops ops = { -@@ -2751,7 +2758,14 @@ static int __devinit snd_es1968_create(s - snd_card_set_dev(card, &pci->dev); - - #ifdef CONFIG_SND_ES1968_RADIO -+ err = v4l2_device_register(&pci->dev, &chip->v4l2_dev); -+ if (err < 0) { -+ snd_es1968_free(chip); -+ return err; -+ } -+ chip->tea.v4l2_dev = &chip->v4l2_dev; - chip->tea.private_data = chip; -+ chip->tea.radio_nr = radio_nr; - chip->tea.ops = &snd_es1968_tea_ops; - strlcpy(chip->tea.card, "SF64-PCE2", sizeof(chip->tea.card)); - sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); -@@ -2797,6 +2811,7 @@ static int __devinit snd_es1968_probe(st - pcm_substreams_c[dev], - pci_id->driver_data, - use_pm[dev], -+ radio_nr[dev], - &chip)) < 0) { - snd_card_free(card); - return err; -Index: linux-3.3.x86_64/sound/pci/fm801.c -=================================================================== ---- linux-3.3.x86_64.orig/sound/pci/fm801.c -+++ linux-3.3.x86_64/sound/pci/fm801.c -@@ -58,6 +58,7 @@ static bool enable[SNDRV_CARDS] = SNDRV_ - * High 16-bits are video (radio) device number + 1 - */ - static int tea575x_tuner[SNDRV_CARDS]; -+static int radio_nr[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; - - module_param_array(index, int, NULL, 0444); - MODULE_PARM_DESC(index, "Index value for the FM801 soundcard."); -@@ -67,6 +68,9 @@ module_param_array(enable, bool, NULL, 0 - MODULE_PARM_DESC(enable, "Enable FM801 soundcard."); - module_param_array(tea575x_tuner, int, NULL, 0444); - MODULE_PARM_DESC(tea575x_tuner, "TEA575x tuner access method (0 = auto, 1 = SF256-PCS, 2=SF256-PCP, 3=SF64-PCR, 8=disable, +16=tuner-only)."); -+module_param_array(radio_nr, int, NULL, 0444); -+MODULE_PARM_DESC(radio_nr, "Radio device numbers"); -+ - - #define TUNER_DISABLED (1<<3) - #define TUNER_ONLY (1<<4) -@@ -197,6 +201,7 @@ struct fm801 { - struct snd_info_entry *proc_entry; - - #ifdef CONFIG_SND_FM801_TEA575X_BOOL -+ struct v4l2_device v4l2_dev; - struct snd_tea575x tea; - #endif - -@@ -1154,8 +1159,10 @@ static int snd_fm801_free(struct fm801 * - - __end_hw: - #ifdef CONFIG_SND_FM801_TEA575X_BOOL -- if (!(chip->tea575x_tuner & TUNER_DISABLED)) -+ if (!(chip->tea575x_tuner & TUNER_DISABLED)) { - snd_tea575x_exit(&chip->tea); -+ v4l2_device_unregister(&chip->v4l2_dev); -+ } - #endif - if (chip->irq >= 0) - free_irq(chip->irq, chip); -@@ -1175,6 +1182,7 @@ static int snd_fm801_dev_free(struct snd - static int __devinit snd_fm801_create(struct snd_card *card, - struct pci_dev * pci, - int tea575x_tuner, -+ int radio_nr, - struct fm801 ** rchip) - { - struct fm801 *chip; -@@ -1234,6 +1242,13 @@ static int __devinit snd_fm801_create(st - snd_card_set_dev(card, &pci->dev); - - #ifdef CONFIG_SND_FM801_TEA575X_BOOL -+ err = v4l2_device_register(&pci->dev, &chip->v4l2_dev); -+ if (err < 0) { -+ snd_fm801_free(chip); -+ return err; -+ } -+ chip->tea.v4l2_dev = &chip->v4l2_dev; -+ chip->tea.radio_nr = radio_nr; - chip->tea.private_data = chip; - chip->tea.ops = &snd_fm801_tea_ops; - sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); -@@ -1241,6 +1256,7 @@ static int __devinit snd_fm801_create(st - (tea575x_tuner & TUNER_TYPE_MASK) < 4) { - if (snd_tea575x_init(&chip->tea)) { - snd_printk(KERN_ERR "TEA575x radio not found\n"); -+ snd_fm801_free(chip); - return -ENODEV; - } - } else if ((tea575x_tuner & TUNER_TYPE_MASK) == 0) { -@@ -1287,7 +1303,7 @@ static int __devinit snd_card_fm801_prob - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; -- if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], &chip)) < 0) { -+ if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], radio_nr[dev], &chip)) < 0) { - snd_card_free(card); - return err; - } -Index: linux-3.3.x86_64/drivers/media/radio/radio-maxiradio.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/radio/radio-maxiradio.c -+++ linux-3.3.x86_64/drivers/media/radio/radio-maxiradio.c -@@ -42,67 +42,37 @@ - #include - #include - #include -+#include - #include - #include -- --#define DRIVER_VERSION "0.7.8" -- -+#include -+#include -+#include - - MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net"); --MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio."); -+MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000."); - MODULE_LICENSE("GPL"); --MODULE_VERSION(DRIVER_VERSION); -+MODULE_VERSION("1.0.0"); - - static int radio_nr = -1; --module_param(radio_nr, int, 0); -- --static int debug; -- --module_param(debug, int, 0644); --MODULE_PARM_DESC(debug, "activates debug info"); -- --#define dprintk(dev, num, fmt, arg...) \ -- v4l2_dbg(num, debug, &dev->v4l2_dev, fmt, ## arg) -- --#ifndef PCI_VENDOR_ID_GUILLEMOT --#define PCI_VENDOR_ID_GUILLEMOT 0x5046 --#endif -- --#ifndef PCI_DEVICE_ID_GUILLEMOT --#define PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO 0x1001 --#endif -- -+module_param(radio_nr, int, 0644); -+MODULE_PARM_DESC(radio_nr, "Radio device number"); - - /* TEA5757 pin mappings */ - static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16; - --#define FREQ_LO (87 * 16000) --#define FREQ_HI (108 * 16000) -- --#define FREQ_IF 171200 /* 10.7*16000 */ --#define FREQ_STEP 200 /* 12.5*16 */ -- --/* (x==fmhz*16*1000) -> bits */ --#define FREQ2BITS(x) \ -- ((((unsigned int)(x) + FREQ_IF + (FREQ_STEP << 1)) / (FREQ_STEP << 2)) << 2) -- --#define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF) -+static atomic_t maxiradio_instance = ATOMIC_INIT(0); - -+#define PCI_VENDOR_ID_GUILLEMOT 0x5046 -+#define PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO 0x1001 - - struct maxiradio - { -+ struct snd_tea575x tea; - struct v4l2_device v4l2_dev; -- struct video_device vdev; - struct pci_dev *pdev; - - u16 io; /* base of radio io */ -- u16 muted; /* VIDEO_AUDIO_MUTE */ -- u16 stereo; /* VIDEO_TUNER_STEREO_ON */ -- u16 tuned; /* signal strength (0 or 0xffff) */ -- -- unsigned long freq; -- -- struct mutex lock; - }; - - static inline struct maxiradio *to_maxiradio(struct v4l2_device *v4l2_dev) -@@ -110,259 +80,41 @@ static inline struct maxiradio *to_maxir - return container_of(v4l2_dev, struct maxiradio, v4l2_dev); - } - --static void outbit(unsigned long bit, u16 io) --{ -- int val = power | wren | (bit ? data : 0); -- -- outb(val, io); -- udelay(4); -- outb(val | clk, io); -- udelay(4); -- outb(val, io); -- udelay(4); --} -- --static void turn_power(struct maxiradio *dev, int p) --{ -- if (p != 0) { -- dprintk(dev, 1, "Radio powered on\n"); -- outb(power, dev->io); -- } else { -- dprintk(dev, 1, "Radio powered off\n"); -- outb(0, dev->io); -- } --} -- --static void set_freq(struct maxiradio *dev, u32 freq) --{ -- unsigned long int si; -- int bl; -- int io = dev->io; -- int val = FREQ2BITS(freq); -- -- /* TEA5757 shift register bits (see pdf) */ -- -- outbit(0, io); /* 24 search */ -- outbit(1, io); /* 23 search up/down */ -- -- outbit(0, io); /* 22 stereo/mono */ -- -- outbit(0, io); /* 21 band */ -- outbit(0, io); /* 20 band (only 00=FM works I think) */ -- -- outbit(0, io); /* 19 port ? */ -- outbit(0, io); /* 18 port ? */ -- -- outbit(0, io); /* 17 search level */ -- outbit(0, io); /* 16 search level */ -- -- si = 0x8000; -- for (bl = 1; bl <= 16; bl++) { -- outbit(val & si, io); -- si >>= 1; -- } -- -- dprintk(dev, 1, "Radio freq set to %d.%02d MHz\n", -- freq / 16000, -- freq % 16000 * 100 / 16000); -- -- turn_power(dev, 1); --} -- --static int get_stereo(u16 io) --{ -- outb(power,io); -- udelay(4); -- -- return !(inb(io) & mo_st); --} -- --static int get_tune(u16 io) --{ -- outb(power+clk,io); -- udelay(4); -- -- return !(inb(io) & mo_st); --} -- -- --static int vidioc_querycap(struct file *file, void *priv, -- struct v4l2_capability *v) --{ -- struct maxiradio *dev = video_drvdata(file); -- -- strlcpy(v->driver, "radio-maxiradio", sizeof(v->driver)); -- strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof(v->card)); -- snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(dev->pdev)); -- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; -- return 0; --} -- --static int vidioc_g_tuner(struct file *file, void *priv, -- struct v4l2_tuner *v) -+static void maxiradio_tea575x_set_pins(struct snd_tea575x *tea, u8 pins) - { -- struct maxiradio *dev = video_drvdata(file); -+ struct maxiradio *dev = tea->private_data; -+ u8 bits = 0; - -- if (v->index > 0) -- return -EINVAL; -+ bits |= (pins & TEA575X_DATA) ? data : 0; -+ bits |= (pins & TEA575X_CLK) ? clk : 0; -+ bits |= (pins & TEA575X_WREN) ? wren : 0; -+ bits |= power; - -- mutex_lock(&dev->lock); -- strlcpy(v->name, "FM", sizeof(v->name)); -- v->type = V4L2_TUNER_RADIO; -- v->rangelow = FREQ_LO; -- v->rangehigh = FREQ_HI; -- v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; -- v->capability = V4L2_TUNER_CAP_LOW; -- if (get_stereo(dev->io)) -- v->audmode = V4L2_TUNER_MODE_STEREO; -- else -- v->audmode = V4L2_TUNER_MODE_MONO; -- v->signal = 0xffff * get_tune(dev->io); -- mutex_unlock(&dev->lock); -- -- return 0; --} -- --static int vidioc_s_tuner(struct file *file, void *priv, -- struct v4l2_tuner *v) --{ -- return v->index ? -EINVAL : 0; --} -- --static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) --{ -- *i = 0; -- return 0; --} -- --static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) --{ -- return i ? -EINVAL : 0; --} -- --static int vidioc_g_audio(struct file *file, void *priv, -- struct v4l2_audio *a) --{ -- a->index = 0; -- strlcpy(a->name, "Radio", sizeof(a->name)); -- a->capability = V4L2_AUDCAP_STEREO; -- return 0; --} -- -- --static int vidioc_s_audio(struct file *file, void *priv, -- struct v4l2_audio *a) --{ -- return a->index ? -EINVAL : 0; --} -- --static int vidioc_s_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) --{ -- struct maxiradio *dev = video_drvdata(file); -- -- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) -- return -EINVAL; -- if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) { -- dprintk(dev, 1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n", -- f->frequency / 16000, -- f->frequency % 16000 * 100 / 16000, -- FREQ_LO / 16000, FREQ_HI / 16000); -- -- return -EINVAL; -- } -- -- mutex_lock(&dev->lock); -- dev->freq = f->frequency; -- set_freq(dev, dev->freq); -- msleep(125); -- mutex_unlock(&dev->lock); -- -- return 0; --} -- --static int vidioc_g_frequency(struct file *file, void *priv, -- struct v4l2_frequency *f) --{ -- struct maxiradio *dev = video_drvdata(file); -- -- if (f->tuner != 0) -- return -EINVAL; -- f->type = V4L2_TUNER_RADIO; -- f->frequency = dev->freq; -- -- dprintk(dev, 4, "radio freq is %d.%02d MHz", -- f->frequency / 16000, -- f->frequency % 16000 * 100 / 16000); -- -- return 0; --} -- --static int vidioc_queryctrl(struct file *file, void *priv, -- struct v4l2_queryctrl *qc) --{ -- switch (qc->id) { -- case V4L2_CID_AUDIO_MUTE: -- return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); -- } -- return -EINVAL; -+ outb(bits, dev->io); - } - --static int vidioc_g_ctrl(struct file *file, void *priv, -- struct v4l2_control *ctrl) -+/* Note: this card cannot read out the data of the shift registers, -+ only the mono/stereo pin works. */ -+static u8 maxiradio_tea575x_get_pins(struct snd_tea575x *tea) - { -- struct maxiradio *dev = video_drvdata(file); -+ struct maxiradio *dev = tea->private_data; -+ u8 bits = inb(dev->io); - -- switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- ctrl->value = dev->muted; -- return 0; -- } -- -- return -EINVAL; -+ return ((bits & data) ? TEA575X_DATA : 0) | -+ ((bits & mo_st) ? TEA575X_MOST : 0); - } - --static int vidioc_s_ctrl(struct file *file, void *priv, -- struct v4l2_control *ctrl) -+static void maxiradio_tea575x_set_direction(struct snd_tea575x *tea, bool output) - { -- struct maxiradio *dev = video_drvdata(file); -- -- switch (ctrl->id) { -- case V4L2_CID_AUDIO_MUTE: -- mutex_lock(&dev->lock); -- dev->muted = ctrl->value; -- if (dev->muted) -- turn_power(dev, 0); -- else -- set_freq(dev, dev->freq); -- mutex_unlock(&dev->lock); -- return 0; -- } -- -- return -EINVAL; - } - --static const struct v4l2_file_operations maxiradio_fops = { -- .owner = THIS_MODULE, -- .unlocked_ioctl = video_ioctl2, --}; -- --static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = { -- .vidioc_querycap = vidioc_querycap, -- .vidioc_g_tuner = vidioc_g_tuner, -- .vidioc_s_tuner = vidioc_s_tuner, -- .vidioc_g_audio = vidioc_g_audio, -- .vidioc_s_audio = vidioc_s_audio, -- .vidioc_g_input = vidioc_g_input, -- .vidioc_s_input = vidioc_s_input, -- .vidioc_g_frequency = vidioc_g_frequency, -- .vidioc_s_frequency = vidioc_s_frequency, -- .vidioc_queryctrl = vidioc_queryctrl, -- .vidioc_g_ctrl = vidioc_g_ctrl, -- .vidioc_s_ctrl = vidioc_s_ctrl, -+static struct snd_tea575x_ops maxiradio_tea_ops = { -+ .set_pins = maxiradio_tea575x_set_pins, -+ .get_pins = maxiradio_tea575x_get_pins, -+ .set_direction = maxiradio_tea575x_set_direction, - }; - --static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -+static int __devinit maxiradio_probe(struct pci_dev *pdev, const struct pci_device_id *ent) - { - struct maxiradio *dev; - struct v4l2_device *v4l2_dev; -@@ -375,63 +127,60 @@ static int __devinit maxiradio_init_one( - } - - v4l2_dev = &dev->v4l2_dev; -- mutex_init(&dev->lock); -- dev->pdev = pdev; -- dev->muted = 1; -- dev->freq = FREQ_LO; -- -- strlcpy(v4l2_dev->name, "maxiradio", sizeof(v4l2_dev->name)); -+ v4l2_device_set_name(v4l2_dev, "maxiradio", &maxiradio_instance); - - retval = v4l2_device_register(&pdev->dev, v4l2_dev); - if (retval < 0) { - v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); - goto errfr; - } -+ dev->tea.private_data = dev; -+ dev->tea.ops = &maxiradio_tea_ops; -+ /* The data pin cannot be read. This may be a hardware limitation, or -+ we just don't know how to read it. */ -+ dev->tea.cannot_read_data = true; -+ dev->tea.v4l2_dev = v4l2_dev; -+ dev->tea.radio_nr = radio_nr; -+ strlcpy(dev->tea.card, "Maxi Radio FM2000", sizeof(dev->tea.card)); -+ snprintf(dev->tea.bus_info, sizeof(dev->tea.bus_info), -+ "PCI:%s", pci_name(pdev)); -+ -+ retval = -ENODEV; - - if (!request_region(pci_resource_start(pdev, 0), -- pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) { -- v4l2_err(v4l2_dev, "can't reserve I/O ports\n"); -- goto err_out; -+ pci_resource_len(pdev, 0), v4l2_dev->name)) { -+ dev_err(&pdev->dev, "can't reserve I/O ports\n"); -+ goto err_hdl; - } - - if (pci_enable_device(pdev)) - goto err_out_free_region; - - dev->io = pci_resource_start(pdev, 0); -- strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); -- dev->vdev.v4l2_dev = v4l2_dev; -- dev->vdev.fops = &maxiradio_fops; -- dev->vdev.ioctl_ops = &maxiradio_ioctl_ops; -- dev->vdev.release = video_device_release_empty; -- video_set_drvdata(&dev->vdev, dev); -- -- if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -- v4l2_err(v4l2_dev, "can't register device!"); -+ if (snd_tea575x_init(&dev->tea)) { -+ printk(KERN_ERR "radio-maxiradio: Unable to detect TEA575x tuner\n"); - goto err_out_free_region; - } -- -- v4l2_info(v4l2_dev, "version " DRIVER_VERSION "\n"); -- -- v4l2_info(v4l2_dev, "found Guillemot MAXI Radio device (io = 0x%x)\n", -- dev->io); - return 0; - - err_out_free_region: - release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); --err_out: -+err_hdl: - v4l2_device_unregister(v4l2_dev); - errfr: - kfree(dev); -- return -ENODEV; -+ return retval; - } - --static void __devexit maxiradio_remove_one(struct pci_dev *pdev) -+static void __devexit maxiradio_remove(struct pci_dev *pdev) - { - struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); - struct maxiradio *dev = to_maxiradio(v4l2_dev); - -- video_unregister_device(&dev->vdev); -- v4l2_device_unregister(&dev->v4l2_dev); -+ snd_tea575x_exit(&dev->tea); -+ /* Turn off power */ -+ outb(0, dev->io); -+ v4l2_device_unregister(v4l2_dev); - release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); - } - -@@ -446,19 +195,19 @@ MODULE_DEVICE_TABLE(pci, maxiradio_pci_t - static struct pci_driver maxiradio_driver = { - .name = "radio-maxiradio", - .id_table = maxiradio_pci_tbl, -- .probe = maxiradio_init_one, -- .remove = __devexit_p(maxiradio_remove_one), -+ .probe = maxiradio_probe, -+ .remove = __devexit_p(maxiradio_remove), - }; - --static int __init maxiradio_radio_init(void) -+static int __init maxiradio_init(void) - { - return pci_register_driver(&maxiradio_driver); - } - --static void __exit maxiradio_radio_exit(void) -+static void __exit maxiradio_exit(void) - { - pci_unregister_driver(&maxiradio_driver); - } - --module_init(maxiradio_radio_init); --module_exit(maxiradio_radio_exit); -+module_init(maxiradio_init); -+module_exit(maxiradio_exit); -Index: linux-3.3.x86_64/include/media/v4l2-dev.h -=================================================================== ---- linux-3.3.x86_64.orig/include/media/v4l2-dev.h -+++ linux-3.3.x86_64/include/media/v4l2-dev.h -@@ -62,6 +62,9 @@ struct v4l2_file_operations { - unsigned int (*poll) (struct file *, struct poll_table_struct *); - long (*ioctl) (struct file *, unsigned int, unsigned long); - long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); -+#ifdef CONFIG_COMPAT -+ long (*compat_ioctl32) (struct file *, unsigned int, unsigned long); -+#endif - unsigned long (*get_unmapped_area) (struct file *, unsigned long, - unsigned long, unsigned long, unsigned long); - int (*mmap) (struct file *, struct vm_area_struct *); -Index: linux-3.3.x86_64/drivers/media/video/uvc/uvc_v4l2.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/uvc/uvc_v4l2.c -+++ linux-3.3.x86_64/drivers/media/video/uvc/uvc_v4l2.c -@@ -11,6 +11,7 @@ - * - */ - -+#include - #include - #include - #include -@@ -1012,7 +1013,7 @@ static long uvc_v4l2_do_ioctl(struct fil - - default: - uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd); -- return -EINVAL; -+ return -ENOTTY; - } - - return ret; -@@ -1030,6 +1031,207 @@ static long uvc_v4l2_ioctl(struct file * - return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl); - } - -+#ifdef CONFIG_COMPAT -+struct uvc_xu_control_mapping32 { -+ __u32 id; -+ __u8 name[32]; -+ __u8 entity[16]; -+ __u8 selector; -+ -+ __u8 size; -+ __u8 offset; -+ __u32 v4l2_type; -+ __u32 data_type; -+ -+ compat_caddr_t menu_info; -+ __u32 menu_count; -+ -+ __u32 reserved[4]; -+}; -+ -+static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp, -+ const struct uvc_xu_control_mapping32 __user *up) -+{ -+ struct uvc_menu_info __user *umenus; -+ struct uvc_menu_info __user *kmenus; -+ compat_caddr_t p; -+ -+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || -+ __copy_from_user(kp, up, offsetof(typeof(*up), menu_info)) || -+ __get_user(kp->menu_count, &up->menu_count)) -+ return -EFAULT; -+ -+ memset(kp->reserved, 0, sizeof(kp->reserved)); -+ -+ if (kp->menu_count == 0) { -+ kp->menu_info = NULL; -+ return 0; -+ } -+ -+ if (__get_user(p, &up->menu_info)) -+ return -EFAULT; -+ umenus = compat_ptr(p); -+ if (!access_ok(VERIFY_READ, umenus, kp->menu_count * sizeof(*umenus))) -+ return -EFAULT; -+ -+ kmenus = compat_alloc_user_space(kp->menu_count * sizeof(*kmenus)); -+ if (kmenus == NULL) -+ return -EFAULT; -+ kp->menu_info = kmenus; -+ -+ if (copy_in_user(kmenus, umenus, kp->menu_count * sizeof(*umenus))) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp, -+ struct uvc_xu_control_mapping32 __user *up) -+{ -+ struct uvc_menu_info __user *umenus; -+ struct uvc_menu_info __user *kmenus = kp->menu_info; -+ compat_caddr_t p; -+ -+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || -+ __copy_to_user(up, kp, offsetof(typeof(*up), menu_info)) || -+ __put_user(kp->menu_count, &up->menu_count)) -+ return -EFAULT; -+ -+ __clear_user(up->reserved, sizeof(up->reserved)); -+ -+ if (kp->menu_count == 0) -+ return 0; -+ -+ if (get_user(p, &up->menu_info)) -+ return -EFAULT; -+ umenus = compat_ptr(p); -+ if (!access_ok(VERIFY_WRITE, umenus, kp->menu_count * sizeof(*umenus))) -+ return -EFAULT; -+ -+ if (copy_in_user(umenus, kmenus, kp->menu_count * sizeof(*umenus))) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+struct uvc_xu_control_query32 { -+ __u8 unit; -+ __u8 selector; -+ __u8 query; -+ __u16 size; -+ compat_caddr_t data; -+}; -+ -+static int uvc_v4l2_get_xu_query(struct uvc_xu_control_query *kp, -+ const struct uvc_xu_control_query32 __user *up) -+{ -+ u8 __user *udata; -+ u8 __user *kdata; -+ compat_caddr_t p; -+ -+ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || -+ __copy_from_user(kp, up, offsetof(typeof(*up), data))) -+ return -EFAULT; -+ -+ if (kp->size == 0) { -+ kp->data = NULL; -+ return 0; -+ } -+ -+ if (__get_user(p, &up->data)) -+ return -EFAULT; -+ udata = compat_ptr(p); -+ if (!access_ok(VERIFY_READ, udata, kp->size)) -+ return -EFAULT; -+ -+ kdata = compat_alloc_user_space(kp->size); -+ if (kdata == NULL) -+ return -EFAULT; -+ kp->data = kdata; -+ -+ if (copy_in_user(kdata, udata, kp->size)) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+static int uvc_v4l2_put_xu_query(const struct uvc_xu_control_query *kp, -+ struct uvc_xu_control_query32 __user *up) -+{ -+ u8 __user *udata; -+ u8 __user *kdata = kp->data; -+ compat_caddr_t p; -+ -+ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || -+ __copy_to_user(up, kp, offsetof(typeof(*up), data))) -+ return -EFAULT; -+ -+ if (kp->size == 0) -+ return 0; -+ -+ if (get_user(p, &up->data)) -+ return -EFAULT; -+ udata = compat_ptr(p); -+ if (!access_ok(VERIFY_READ, udata, kp->size)) -+ return -EFAULT; -+ -+ if (copy_in_user(udata, kdata, kp->size)) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+#define UVCIOC_CTRL_MAP32 _IOWR('u', 0x20, struct uvc_xu_control_mapping32) -+#define UVCIOC_CTRL_QUERY32 _IOWR('u', 0x21, struct uvc_xu_control_query32) -+ -+static long uvc_v4l2_compat_ioctl32(struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ union { -+ struct uvc_xu_control_mapping xmap; -+ struct uvc_xu_control_query xqry; -+ } karg; -+ void __user *up = compat_ptr(arg); -+ mm_segment_t old_fs; -+ long ret; -+ -+ switch (cmd) { -+ case UVCIOC_CTRL_MAP32: -+ cmd = UVCIOC_CTRL_MAP; -+ ret = uvc_v4l2_get_xu_mapping(&karg.xmap, up); -+ break; -+ -+ case UVCIOC_CTRL_QUERY32: -+ cmd = UVCIOC_CTRL_QUERY; -+ ret = uvc_v4l2_get_xu_query(&karg.xqry, up); -+ break; -+ -+ default: -+ return -ENOIOCTLCMD; -+ } -+ -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ ret = uvc_v4l2_ioctl(file, cmd, (unsigned long)&karg); -+ set_fs(old_fs); -+ -+ if (ret < 0) -+ return ret; -+ -+ switch (cmd) { -+ case UVCIOC_CTRL_MAP: -+ ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up); -+ break; -+ -+ case UVCIOC_CTRL_QUERY: -+ ret = uvc_v4l2_put_xu_query(&karg.xqry, up); -+ break; -+ } -+ -+ return ret; -+} -+#endif -+ - static ssize_t uvc_v4l2_read(struct file *file, char __user *data, - size_t count, loff_t *ppos) - { -@@ -1076,6 +1278,9 @@ const struct v4l2_file_operations uvc_fo - .open = uvc_v4l2_open, - .release = uvc_v4l2_release, - .unlocked_ioctl = uvc_v4l2_ioctl, -+#ifdef CONFIG_COMPAT -+ .compat_ioctl32 = uvc_v4l2_compat_ioctl32, -+#endif - .read = uvc_v4l2_read, - .mmap = uvc_v4l2_mmap, - .poll = uvc_v4l2_poll, -Index: linux-3.3.x86_64/drivers/media/video/uvc/uvc_queue.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/uvc/uvc_queue.c -+++ linux-3.3.x86_64/drivers/media/video/uvc/uvc_queue.c -@@ -126,7 +126,7 @@ void uvc_queue_init(struct uvc_video_que - int drop_corrupted) - { - queue->queue.type = type; -- queue->queue.io_modes = VB2_MMAP; -+ queue->queue.io_modes = VB2_MMAP | VB2_USERPTR; - queue->queue.drv_priv = queue; - queue->queue.buf_struct_size = sizeof(struct uvc_buffer); - queue->queue.ops = &uvc_queue_qops; -Index: linux-3.3.x86_64/drivers/media/video/uvc/uvc_driver.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/uvc/uvc_driver.c -+++ linux-3.3.x86_64/drivers/media/video/uvc/uvc_driver.c -@@ -23,6 +23,7 @@ - * codec can't handle MJPEG data. - */ - -+#include - #include - #include - #include -@@ -32,7 +33,6 @@ - #include - #include - #include --#include - #include - - #include -@@ -2139,6 +2139,15 @@ static struct usb_device_id uvc_ids[] = - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_MINMAX }, -+ /* Dell XPS m1530 */ -+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE -+ | USB_DEVICE_ID_MATCH_INT_INFO, -+ .idVendor = 0x05a9, -+ .idProduct = 0x2640, -+ .bInterfaceClass = USB_CLASS_VIDEO, -+ .bInterfaceSubClass = 1, -+ .bInterfaceProtocol = 0, -+ .driver_info = UVC_QUIRK_PROBE_DEF }, - /* Apple Built-In iSight */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/stv0288.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/stv0288.c -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/stv0288.c -@@ -506,7 +506,7 @@ static int stv0288_set_frontend(struct d - tda[1] = (unsigned char)tm; - stv0288_writeregI(state, 0x2b, tda[1]); - stv0288_writeregI(state, 0x2c, tda[2]); -- udelay(30); -+ msleep(30); - } - state->tuner_frequency = c->frequency; - state->fec_inner = FEC_AUTO; -Index: linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-cards.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/cx231xx/cx231xx-cards.c -+++ linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-cards.c -@@ -861,7 +861,6 @@ void cx231xx_release_resources(struct cx - kfree(dev->sliced_cc_mode.alt_max_pkt_size); - kfree(dev->ts1_mode.alt_max_pkt_size); - kfree(dev); -- dev = NULL; - } - - /* -Index: linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-video.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/cx231xx/cx231xx-video.c -+++ linux-3.3.x86_64/drivers/media/video/cx231xx/cx231xx-video.c -@@ -2319,8 +2319,7 @@ static int cx231xx_v4l2_close(struct fil - if (dev->state & DEV_DISCONNECTED) { - if (atomic_read(&dev->devlist_count) > 0) { - cx231xx_release_resources(dev); -- kfree(dev); -- dev = NULL; -+ fh->dev = NULL; - return 0; - } - return 0; -@@ -2350,8 +2349,7 @@ static int cx231xx_v4l2_close(struct fil - free the remaining resources */ - if (dev->state & DEV_DISCONNECTED) { - cx231xx_release_resources(dev); -- kfree(dev); -- dev = NULL; -+ fh->dev = NULL; - return 0; - } - -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/dib9000.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/dib9000.c -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/dib9000.c -@@ -33,7 +33,7 @@ struct i2c_device { - - /* lock */ - #define DIB_LOCK struct mutex --#define DibAcquireLock(lock) do { if (mutex_lock_interruptible(lock) < 0) dprintk("could not get the lock"); } while (0) -+#define DibAcquireLock(lock) mutex_lock_interruptible(lock) - #define DibReleaseLock(lock) mutex_unlock(lock) - #define DibInitLock(lock) mutex_init(lock) - #define DibFreeLock(lock) -@@ -446,7 +446,10 @@ static int dib9000_risc_mem_read(struct - if (!state->platform.risc.fw_is_running) - return -EIO; - -- DibAcquireLock(&state->platform.risc.mem_lock); -+ if (DibAcquireLock(&state->platform.risc.mem_lock) < 0) { -+ dprintk("could not get the lock"); -+ return -EINTR; -+ } - dib9000_risc_mem_setup(state, cmd | 0x80); - dib9000_risc_mem_read_chunks(state, b, len); - DibReleaseLock(&state->platform.risc.mem_lock); -@@ -459,7 +462,10 @@ static int dib9000_risc_mem_write(struct - if (!state->platform.risc.fw_is_running) - return -EIO; - -- DibAcquireLock(&state->platform.risc.mem_lock); -+ if (DibAcquireLock(&state->platform.risc.mem_lock) < 0) { -+ dprintk("could not get the lock"); -+ return -EINTR; -+ } - dib9000_risc_mem_setup(state, cmd); - dib9000_risc_mem_write_chunks(state, b, m->size); - DibReleaseLock(&state->platform.risc.mem_lock); -@@ -531,7 +537,10 @@ static int dib9000_mbx_send_attr(struct - if (!state->platform.risc.fw_is_running) - return -EINVAL; - -- DibAcquireLock(&state->platform.risc.mbx_if_lock); -+ if (DibAcquireLock(&state->platform.risc.mbx_if_lock) < 0) { -+ dprintk("could not get the lock"); -+ return -EINTR; -+ } - tmp = MAX_MAILBOX_TRY; - do { - size = dib9000_read_word_attr(state, 1043, attr) & 0xff; -@@ -593,7 +602,10 @@ static u8 dib9000_mbx_read(struct dib900 - if (!state->platform.risc.fw_is_running) - return 0; - -- DibAcquireLock(&state->platform.risc.mbx_if_lock); -+ if (DibAcquireLock(&state->platform.risc.mbx_if_lock) < 0) { -+ dprintk("could not get the lock"); -+ return 0; -+ } - if (risc_id == 1) - mc_base = 16; - else -@@ -701,7 +713,10 @@ static int dib9000_mbx_process(struct di - if (!state->platform.risc.fw_is_running) - return -1; - -- DibAcquireLock(&state->platform.risc.mbx_lock); -+ if (DibAcquireLock(&state->platform.risc.mbx_lock) < 0) { -+ dprintk("could not get the lock"); -+ return -1; -+ } - - if (dib9000_mbx_count(state, 1, attr)) /* 1=RiscB */ - ret = dib9000_mbx_fetch_to_cache(state, attr); -@@ -1178,7 +1193,10 @@ static int dib9000_fw_get_channel(struct - struct dibDVBTChannel *ch; - int ret = 0; - -- DibAcquireLock(&state->platform.risc.mem_mbx_lock); -+ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { -+ dprintk("could not get the lock"); -+ return -EINTR; -+ } - if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { - ret = -EIO; - goto error; -@@ -1660,7 +1678,10 @@ static int dib9000_fw_component_bus_xfer - p[12] = 0; - } - -- DibAcquireLock(&state->platform.risc.mem_mbx_lock); -+ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { -+ dprintk("could not get the lock"); -+ return 0; -+ } - - dib9000_risc_mem_write(state, FE_MM_W_COMPONENT_ACCESS, p); - -@@ -1768,7 +1789,10 @@ int dib9000_fw_pid_filter_ctrl(struct dv - return 0; - } - -- DibAcquireLock(&state->demod_lock); -+ if (DibAcquireLock(&state->demod_lock) < 0) { -+ dprintk("could not get the lock"); -+ return -EINTR; -+ } - - val = dib9000_read_word(state, 294 + 1) & 0xffef; - val |= (onoff & 0x1) << 4; -@@ -1800,7 +1824,10 @@ int dib9000_fw_pid_filter(struct dvb_fro - return 0; - } - -- DibAcquireLock(&state->demod_lock); -+ if (DibAcquireLock(&state->demod_lock) < 0) { -+ dprintk("could not get the lock"); -+ return -EINTR; -+ } - dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff); - ret = dib9000_write_word(state, 300 + 1 + id, - onoff ? (1 << 13) | pid : 0); -@@ -1848,7 +1875,10 @@ static int dib9000_sleep(struct dvb_fron - u8 index_frontend; - int ret = 0; - -- DibAcquireLock(&state->demod_lock); -+ if (DibAcquireLock(&state->demod_lock) < 0) { -+ dprintk("could not get the lock"); -+ return -EINTR; -+ } - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]); - if (ret < 0) -@@ -1874,8 +1904,12 @@ static int dib9000_get_frontend(struct d - fe_status_t stat; - int ret = 0; - -- if (state->get_frontend_internal == 0) -- DibAcquireLock(&state->demod_lock); -+ if (state->get_frontend_internal == 0) { -+ if (DibAcquireLock(&state->demod_lock) < 0) { -+ dprintk("could not get the lock"); -+ return -EINTR; -+ } -+ } - - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat); -@@ -1978,7 +2012,10 @@ static int dib9000_set_frontend(struct d - } - - state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */ -- DibAcquireLock(&state->demod_lock); -+ if (DibAcquireLock(&state->demod_lock) < 0) { -+ dprintk("could not get the lock"); -+ return 0; -+ } - - fe->dtv_property_cache.delivery_system = SYS_DVBT; - -@@ -2138,7 +2175,10 @@ static int dib9000_read_status(struct dv - u8 index_frontend; - u16 lock = 0, lock_slave = 0; - -- DibAcquireLock(&state->demod_lock); -+ if (DibAcquireLock(&state->demod_lock) < 0) { -+ dprintk("could not get the lock"); -+ return -EINTR; -+ } - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) - lock_slave |= dib9000_read_lock(state->fe[index_frontend]); - -@@ -2168,8 +2208,15 @@ static int dib9000_read_ber(struct dvb_f - u16 *c; - int ret = 0; - -- DibAcquireLock(&state->demod_lock); -- DibAcquireLock(&state->platform.risc.mem_mbx_lock); -+ if (DibAcquireLock(&state->demod_lock) < 0) { -+ dprintk("could not get the lock"); -+ return -EINTR; -+ } -+ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { -+ dprintk("could not get the lock"); -+ ret = -EINTR; -+ goto error; -+ } - if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { - DibReleaseLock(&state->platform.risc.mem_mbx_lock); - ret = -EIO; -@@ -2196,7 +2243,10 @@ static int dib9000_read_signal_strength( - u16 val; - int ret = 0; - -- DibAcquireLock(&state->demod_lock); -+ if (DibAcquireLock(&state->demod_lock) < 0) { -+ dprintk("could not get the lock"); -+ return -EINTR; -+ } - *strength = 0; - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val); -@@ -2206,8 +2256,13 @@ static int dib9000_read_signal_strength( - *strength += val; - } - -- DibAcquireLock(&state->platform.risc.mem_mbx_lock); -+ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { -+ dprintk("could not get the lock"); -+ ret = -EINTR; -+ goto error; -+ } - if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { -+ DibReleaseLock(&state->platform.risc.mem_mbx_lock); - ret = -EIO; - goto error; - } -@@ -2232,9 +2287,14 @@ static u32 dib9000_get_snr(struct dvb_fr - u32 n, s, exp; - u16 val; - -- DibAcquireLock(&state->platform.risc.mem_mbx_lock); -- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) -- return -EIO; -+ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { -+ dprintk("could not get the lock"); -+ return 0; -+ } -+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { -+ DibReleaseLock(&state->platform.risc.mem_mbx_lock); -+ return 0; -+ } - dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); - DibReleaseLock(&state->platform.risc.mem_mbx_lock); - -@@ -2266,7 +2326,10 @@ static int dib9000_read_snr(struct dvb_f - u8 index_frontend; - u32 snr_master; - -- DibAcquireLock(&state->demod_lock); -+ if (DibAcquireLock(&state->demod_lock) < 0) { -+ dprintk("could not get the lock"); -+ return -EINTR; -+ } - snr_master = dib9000_get_snr(fe); - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) - snr_master += dib9000_get_snr(state->fe[index_frontend]); -@@ -2288,9 +2351,17 @@ static int dib9000_read_unc_blocks(struc - u16 *c = (u16 *)state->i2c_read_buffer; - int ret = 0; - -- DibAcquireLock(&state->demod_lock); -- DibAcquireLock(&state->platform.risc.mem_mbx_lock); -+ if (DibAcquireLock(&state->demod_lock) < 0) { -+ dprintk("could not get the lock"); -+ return -EINTR; -+ } -+ if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) { -+ dprintk("could not get the lock"); -+ ret = -EINTR; -+ goto error; -+ } - if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { -+ DibReleaseLock(&state->platform.risc.mem_mbx_lock); - ret = -EIO; - goto error; - } -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/drxd_hard.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/drxd_hard.c -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/drxd_hard.c -@@ -101,9 +101,9 @@ struct SCfgAgc { - - struct SNoiseCal { - int cpOpt; -- u16 cpNexpOfs; -- u16 tdCal2k; -- u16 tdCal8k; -+ short cpNexpOfs; -+ short tdCal2k; -+ short tdCal8k; - }; - - enum app_env { -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/m88rs2000.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/m88rs2000.c -@@ -0,0 +1,904 @@ -+/* -+ Driver for M88RS2000 demodulator and tuner -+ -+ Copyright (C) 2012 Malcolm Priestley (tvboxspy@gmail.com) -+ Beta Driver -+ -+ Include various calculation code from DS3000 driver. -+ Copyright (C) 2009 Konstantin Dimitrov. -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ -+*/ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+#include "dvb_frontend.h" -+#include "m88rs2000.h" -+ -+struct m88rs2000_state { -+ struct i2c_adapter *i2c; -+ const struct m88rs2000_config *config; -+ struct dvb_frontend frontend; -+ u8 no_lock_count; -+ u32 tuner_frequency; -+ u32 symbol_rate; -+ fe_code_rate_t fec_inner; -+ u8 tuner_level; -+ int errmode; -+}; -+ -+static int m88rs2000_debug; -+ -+module_param_named(debug, m88rs2000_debug, int, 0644); -+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); -+ -+#define dprintk(level, args...) do { \ -+ if (level & m88rs2000_debug) \ -+ printk(KERN_DEBUG "m88rs2000-fe: " args); \ -+} while (0) -+ -+#define deb_info(args...) dprintk(0x01, args) -+#define info(format, arg...) \ -+ printk(KERN_INFO "m88rs2000-fe: " format "\n" , ## arg) -+ -+static int m88rs2000_writereg(struct m88rs2000_state *state, u8 tuner, -+ u8 reg, u8 data) -+{ -+ int ret; -+ u8 addr = (tuner == 0) ? state->config->tuner_addr : -+ state->config->demod_addr; -+ u8 buf[] = { reg, data }; -+ struct i2c_msg msg = { -+ .addr = addr, -+ .flags = 0, -+ .buf = buf, -+ .len = 2 -+ }; -+ -+ ret = i2c_transfer(state->i2c, &msg, 1); -+ -+ if (ret != 1) -+ deb_info("%s: writereg error (reg == 0x%02x, val == 0x%02x, " -+ "ret == %i)\n", __func__, reg, data, ret); -+ -+ return (ret != 1) ? -EREMOTEIO : 0; -+} -+ -+static int m88rs2000_demod_write(struct m88rs2000_state *state, u8 reg, u8 data) -+{ -+ return m88rs2000_writereg(state, 1, reg, data); -+} -+ -+static int m88rs2000_tuner_write(struct m88rs2000_state *state, u8 reg, u8 data) -+{ -+ m88rs2000_demod_write(state, 0x81, 0x84); -+ udelay(10); -+ return m88rs2000_writereg(state, 0, reg, data); -+ -+} -+ -+static int m88rs2000_write(struct dvb_frontend *fe, const u8 buf[], int len) -+{ -+ struct m88rs2000_state *state = fe->demodulator_priv; -+ -+ if (len != 2) -+ return -EINVAL; -+ -+ return m88rs2000_writereg(state, 1, buf[0], buf[1]); -+} -+ -+static u8 m88rs2000_readreg(struct m88rs2000_state *state, u8 tuner, u8 reg) -+{ -+ int ret; -+ u8 b0[] = { reg }; -+ u8 b1[] = { 0 }; -+ u8 addr = (tuner == 0) ? state->config->tuner_addr : -+ state->config->demod_addr; -+ struct i2c_msg msg[] = { -+ { -+ .addr = addr, -+ .flags = 0, -+ .buf = b0, -+ .len = 1 -+ }, { -+ .addr = addr, -+ .flags = I2C_M_RD, -+ .buf = b1, -+ .len = 1 -+ } -+ }; -+ -+ ret = i2c_transfer(state->i2c, msg, 2); -+ -+ if (ret != 2) -+ deb_info("%s: readreg error (reg == 0x%02x, ret == %i)\n", -+ __func__, reg, ret); -+ -+ return b1[0]; -+} -+ -+static u8 m88rs2000_demod_read(struct m88rs2000_state *state, u8 reg) -+{ -+ return m88rs2000_readreg(state, 1, reg); -+} -+ -+static u8 m88rs2000_tuner_read(struct m88rs2000_state *state, u8 reg) -+{ -+ m88rs2000_demod_write(state, 0x81, 0x85); -+ udelay(10); -+ return m88rs2000_readreg(state, 0, reg); -+} -+ -+static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate) -+{ -+ struct m88rs2000_state *state = fe->demodulator_priv; -+ int ret; -+ u32 temp; -+ u8 b[3]; -+ -+ if ((srate < 1000000) || (srate > 45000000)) -+ return -EINVAL; -+ -+ temp = srate / 1000; -+ temp *= 11831; -+ temp /= 68; -+ temp -= 3; -+ -+ b[0] = (u8) (temp >> 16) & 0xff; -+ b[1] = (u8) (temp >> 8) & 0xff; -+ b[2] = (u8) temp & 0xff; -+ ret = m88rs2000_demod_write(state, 0x93, b[2]); -+ ret |= m88rs2000_demod_write(state, 0x94, b[1]); -+ ret |= m88rs2000_demod_write(state, 0x95, b[0]); -+ -+ deb_info("m88rs2000: m88rs2000_set_symbolrate\n"); -+ return ret; -+} -+ -+static int m88rs2000_send_diseqc_msg(struct dvb_frontend *fe, -+ struct dvb_diseqc_master_cmd *m) -+{ -+ struct m88rs2000_state *state = fe->demodulator_priv; -+ -+ int i; -+ u8 reg; -+ deb_info("%s\n", __func__); -+ m88rs2000_demod_write(state, 0x9a, 0x30); -+ reg = m88rs2000_demod_read(state, 0xb2); -+ reg &= 0x3f; -+ m88rs2000_demod_write(state, 0xb2, reg); -+ for (i = 0; i < m->msg_len; i++) -+ m88rs2000_demod_write(state, 0xb3 + i, m->msg[i]); -+ -+ reg = m88rs2000_demod_read(state, 0xb1); -+ reg &= 0x87; -+ reg |= ((m->msg_len - 1) << 3) | 0x07; -+ reg &= 0x7f; -+ m88rs2000_demod_write(state, 0xb1, reg); -+ -+ for (i = 0; i < 15; i++) { -+ if ((m88rs2000_demod_read(state, 0xb1) & 0x40) == 0x0) -+ break; -+ msleep(20); -+ } -+ -+ reg = m88rs2000_demod_read(state, 0xb1); -+ if ((reg & 0x40) > 0x0) { -+ reg &= 0x7f; -+ reg |= 0x40; -+ m88rs2000_demod_write(state, 0xb1, reg); -+ } -+ -+ reg = m88rs2000_demod_read(state, 0xb2); -+ reg &= 0x3f; -+ reg |= 0x80; -+ m88rs2000_demod_write(state, 0xb2, reg); -+ m88rs2000_demod_write(state, 0x9a, 0xb0); -+ -+ -+ return 0; -+} -+ -+static int m88rs2000_send_diseqc_burst(struct dvb_frontend *fe, -+ fe_sec_mini_cmd_t burst) -+{ -+ struct m88rs2000_state *state = fe->demodulator_priv; -+ u8 reg0, reg1; -+ deb_info("%s\n", __func__); -+ m88rs2000_demod_write(state, 0x9a, 0x30); -+ msleep(50); -+ reg0 = m88rs2000_demod_read(state, 0xb1); -+ reg1 = m88rs2000_demod_read(state, 0xb2); -+ /* TODO complete this section */ -+ m88rs2000_demod_write(state, 0xb2, reg1); -+ m88rs2000_demod_write(state, 0xb1, reg0); -+ m88rs2000_demod_write(state, 0x9a, 0xb0); -+ -+ return 0; -+} -+ -+static int m88rs2000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) -+{ -+ struct m88rs2000_state *state = fe->demodulator_priv; -+ u8 reg0, reg1; -+ m88rs2000_demod_write(state, 0x9a, 0x30); -+ reg0 = m88rs2000_demod_read(state, 0xb1); -+ reg1 = m88rs2000_demod_read(state, 0xb2); -+ -+ reg1 &= 0x3f; -+ -+ switch (tone) { -+ case SEC_TONE_ON: -+ reg0 |= 0x4; -+ reg0 &= 0xbc; -+ break; -+ case SEC_TONE_OFF: -+ reg1 |= 0x80; -+ break; -+ default: -+ break; -+ } -+ m88rs2000_demod_write(state, 0xb2, reg1); -+ m88rs2000_demod_write(state, 0xb1, reg0); -+ m88rs2000_demod_write(state, 0x9a, 0xb0); -+ return 0; -+} -+ -+struct inittab { -+ u8 cmd; -+ u8 reg; -+ u8 val; -+}; -+ -+struct inittab m88rs2000_setup[] = { -+ {DEMOD_WRITE, 0x9a, 0x30}, -+ {DEMOD_WRITE, 0x00, 0x01}, -+ {WRITE_DELAY, 0x19, 0x00}, -+ {DEMOD_WRITE, 0x00, 0x00}, -+ {DEMOD_WRITE, 0x9a, 0xb0}, -+ {DEMOD_WRITE, 0x81, 0xc1}, -+ {TUNER_WRITE, 0x42, 0x73}, -+ {TUNER_WRITE, 0x05, 0x07}, -+ {TUNER_WRITE, 0x20, 0x27}, -+ {TUNER_WRITE, 0x07, 0x02}, -+ {TUNER_WRITE, 0x11, 0xff}, -+ {TUNER_WRITE, 0x60, 0xf9}, -+ {TUNER_WRITE, 0x08, 0x01}, -+ {TUNER_WRITE, 0x00, 0x41}, -+ {DEMOD_WRITE, 0x81, 0x81}, -+ {DEMOD_WRITE, 0x86, 0xc6}, -+ {DEMOD_WRITE, 0x9a, 0x30}, -+ {DEMOD_WRITE, 0xf0, 0x22}, -+ {DEMOD_WRITE, 0xf1, 0xbf}, -+ {DEMOD_WRITE, 0xb0, 0x45}, -+ {DEMOD_WRITE, 0xb2, 0x01}, /* set voltage pin always set 1*/ -+ {DEMOD_WRITE, 0x9a, 0xb0}, -+ {0xff, 0xaa, 0xff} -+}; -+ -+struct inittab m88rs2000_shutdown[] = { -+ {DEMOD_WRITE, 0x9a, 0x30}, -+ {DEMOD_WRITE, 0xb0, 0x00}, -+ {DEMOD_WRITE, 0xf1, 0x89}, -+ {DEMOD_WRITE, 0x00, 0x01}, -+ {DEMOD_WRITE, 0x9a, 0xb0}, -+ {TUNER_WRITE, 0x00, 0x40}, -+ {DEMOD_WRITE, 0x81, 0x81}, -+ {0xff, 0xaa, 0xff} -+}; -+ -+struct inittab tuner_reset[] = { -+ {TUNER_WRITE, 0x42, 0x73}, -+ {TUNER_WRITE, 0x05, 0x07}, -+ {TUNER_WRITE, 0x20, 0x27}, -+ {TUNER_WRITE, 0x07, 0x02}, -+ {TUNER_WRITE, 0x11, 0xff}, -+ {TUNER_WRITE, 0x60, 0xf9}, -+ {TUNER_WRITE, 0x08, 0x01}, -+ {TUNER_WRITE, 0x00, 0x41}, -+ {0xff, 0xaa, 0xff} -+}; -+ -+struct inittab fe_reset[] = { -+ {DEMOD_WRITE, 0x00, 0x01}, -+ {DEMOD_WRITE, 0xf1, 0xbf}, -+ {DEMOD_WRITE, 0x00, 0x01}, -+ {DEMOD_WRITE, 0x20, 0x81}, -+ {DEMOD_WRITE, 0x21, 0x80}, -+ {DEMOD_WRITE, 0x10, 0x33}, -+ {DEMOD_WRITE, 0x11, 0x44}, -+ {DEMOD_WRITE, 0x12, 0x07}, -+ {DEMOD_WRITE, 0x18, 0x20}, -+ {DEMOD_WRITE, 0x28, 0x04}, -+ {DEMOD_WRITE, 0x29, 0x8e}, -+ {DEMOD_WRITE, 0x3b, 0xff}, -+ {DEMOD_WRITE, 0x32, 0x10}, -+ {DEMOD_WRITE, 0x33, 0x02}, -+ {DEMOD_WRITE, 0x34, 0x30}, -+ {DEMOD_WRITE, 0x35, 0xff}, -+ {DEMOD_WRITE, 0x38, 0x50}, -+ {DEMOD_WRITE, 0x39, 0x68}, -+ {DEMOD_WRITE, 0x3c, 0x7f}, -+ {DEMOD_WRITE, 0x3d, 0x0f}, -+ {DEMOD_WRITE, 0x45, 0x20}, -+ {DEMOD_WRITE, 0x46, 0x24}, -+ {DEMOD_WRITE, 0x47, 0x7c}, -+ {DEMOD_WRITE, 0x48, 0x16}, -+ {DEMOD_WRITE, 0x49, 0x04}, -+ {DEMOD_WRITE, 0x4a, 0x01}, -+ {DEMOD_WRITE, 0x4b, 0x78}, -+ {DEMOD_WRITE, 0X4d, 0xd2}, -+ {DEMOD_WRITE, 0x4e, 0x6d}, -+ {DEMOD_WRITE, 0x50, 0x30}, -+ {DEMOD_WRITE, 0x51, 0x30}, -+ {DEMOD_WRITE, 0x54, 0x7b}, -+ {DEMOD_WRITE, 0x56, 0x09}, -+ {DEMOD_WRITE, 0x58, 0x59}, -+ {DEMOD_WRITE, 0x59, 0x37}, -+ {DEMOD_WRITE, 0x63, 0xfa}, -+ {0xff, 0xaa, 0xff} -+}; -+ -+struct inittab fe_trigger[] = { -+ {DEMOD_WRITE, 0x97, 0x04}, -+ {DEMOD_WRITE, 0x99, 0x77}, -+ {DEMOD_WRITE, 0x9b, 0x64}, -+ {DEMOD_WRITE, 0x9e, 0x00}, -+ {DEMOD_WRITE, 0x9f, 0xf8}, -+ {DEMOD_WRITE, 0xa0, 0x20}, -+ {DEMOD_WRITE, 0xa1, 0xe0}, -+ {DEMOD_WRITE, 0xa3, 0x38}, -+ {DEMOD_WRITE, 0x98, 0xff}, -+ {DEMOD_WRITE, 0xc0, 0x0f}, -+ {DEMOD_WRITE, 0x89, 0x01}, -+ {DEMOD_WRITE, 0x00, 0x00}, -+ {WRITE_DELAY, 0x0a, 0x00}, -+ {DEMOD_WRITE, 0x00, 0x01}, -+ {DEMOD_WRITE, 0x00, 0x00}, -+ {DEMOD_WRITE, 0x9a, 0xb0}, -+ {0xff, 0xaa, 0xff} -+}; -+ -+static int m88rs2000_tab_set(struct m88rs2000_state *state, -+ struct inittab *tab) -+{ -+ int ret = 0; -+ u8 i; -+ if (tab == NULL) -+ return -EINVAL; -+ -+ for (i = 0; i < 255; i++) { -+ switch (tab[i].cmd) { -+ case 0x01: -+ ret = m88rs2000_demod_write(state, tab[i].reg, -+ tab[i].val); -+ break; -+ case 0x02: -+ ret = m88rs2000_tuner_write(state, tab[i].reg, -+ tab[i].val); -+ break; -+ case 0x10: -+ if (tab[i].reg > 0) -+ mdelay(tab[i].reg); -+ break; -+ case 0xff: -+ if (tab[i].reg == 0xaa && tab[i].val == 0xff) -+ return 0; -+ case 0x00: -+ break; -+ default: -+ return -EINVAL; -+ } -+ if (ret < 0) -+ return -ENODEV; -+ } -+ return 0; -+} -+ -+static int m88rs2000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt) -+{ -+ deb_info("%s: %s\n", __func__, -+ volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" : -+ volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??"); -+ -+ return 0; -+} -+ -+static int m88rs2000_startup(struct m88rs2000_state *state) -+{ -+ int ret = 0; -+ u8 reg; -+ -+ reg = m88rs2000_tuner_read(state, 0x00); -+ if ((reg & 0x40) == 0) -+ ret = -ENODEV; -+ -+ return ret; -+} -+ -+static int m88rs2000_init(struct dvb_frontend *fe) -+{ -+ struct m88rs2000_state *state = fe->demodulator_priv; -+ int ret; -+ -+ deb_info("m88rs2000: init chip\n"); -+ /* Setup frontend from shutdown/cold */ -+ ret = m88rs2000_tab_set(state, m88rs2000_setup); -+ -+ return ret; -+} -+ -+static int m88rs2000_sleep(struct dvb_frontend *fe) -+{ -+ struct m88rs2000_state *state = fe->demodulator_priv; -+ int ret; -+ /* Shutdown the frondend */ -+ ret = m88rs2000_tab_set(state, m88rs2000_shutdown); -+ return ret; -+} -+ -+static int m88rs2000_read_status(struct dvb_frontend *fe, fe_status_t *status) -+{ -+ struct m88rs2000_state *state = fe->demodulator_priv; -+ u8 reg = m88rs2000_demod_read(state, 0x8c); -+ -+ *status = 0; -+ -+ if ((reg & 0x7) == 0x7) { -+ *status = FE_HAS_CARRIER | FE_HAS_SIGNAL | FE_HAS_VITERBI -+ | FE_HAS_LOCK; -+ if (state->config->set_ts_params) -+ state->config->set_ts_params(fe, CALL_IS_READ); -+ } -+ return 0; -+} -+ -+/* Extact code for these unknown but lmedm04 driver uses interupt callbacks */ -+ -+static int m88rs2000_read_ber(struct dvb_frontend *fe, u32 *ber) -+{ -+ deb_info("m88rs2000_read_ber %d\n", *ber); -+ *ber = 0; -+ return 0; -+} -+ -+static int m88rs2000_read_signal_strength(struct dvb_frontend *fe, -+ u16 *strength) -+{ -+ *strength = 0; -+ return 0; -+} -+ -+static int m88rs2000_read_snr(struct dvb_frontend *fe, u16 *snr) -+{ -+ deb_info("m88rs2000_read_snr %d\n", *snr); -+ *snr = 0; -+ return 0; -+} -+ -+static int m88rs2000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -+{ -+ deb_info("m88rs2000_read_ber %d\n", *ucblocks); -+ *ucblocks = 0; -+ return 0; -+} -+ -+static int m88rs2000_tuner_gate_ctrl(struct m88rs2000_state *state, u8 offset) -+{ -+ int ret; -+ ret = m88rs2000_tuner_write(state, 0x51, 0x1f - offset); -+ ret |= m88rs2000_tuner_write(state, 0x51, 0x1f); -+ ret |= m88rs2000_tuner_write(state, 0x50, offset); -+ ret |= m88rs2000_tuner_write(state, 0x50, 0x00); -+ msleep(20); -+ return ret; -+} -+ -+static int m88rs2000_set_tuner_rf(struct dvb_frontend *fe) -+{ -+ struct m88rs2000_state *state = fe->demodulator_priv; -+ int reg; -+ reg = m88rs2000_tuner_read(state, 0x3d); -+ reg &= 0x7f; -+ if (reg < 0x16) -+ reg = 0xa1; -+ else if (reg == 0x16) -+ reg = 0x99; -+ else -+ reg = 0xf9; -+ -+ m88rs2000_tuner_write(state, 0x60, reg); -+ reg = m88rs2000_tuner_gate_ctrl(state, 0x08); -+ -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); -+ return reg; -+} -+ -+static int m88rs2000_set_tuner(struct dvb_frontend *fe, u16 *offset) -+{ -+ struct dtv_frontend_properties *c = &fe->dtv_property_cache; -+ struct m88rs2000_state *state = fe->demodulator_priv; -+ int ret; -+ u32 frequency = c->frequency; -+ s32 offset_khz; -+ s32 tmp; -+ u32 symbol_rate = (c->symbol_rate / 1000); -+ u32 f3db, gdiv28; -+ u16 value, ndiv, lpf_coeff; -+ u8 lpf_mxdiv, mlpf_max, mlpf_min, nlpf; -+ u8 lo = 0x01, div4 = 0x0; -+ -+ /* Reset Tuner */ -+ ret = m88rs2000_tab_set(state, tuner_reset); -+ -+ /* Calculate frequency divider */ -+ if (frequency < 1060000) { -+ lo |= 0x10; -+ div4 = 0x1; -+ ndiv = (frequency * 14 * 4) / FE_CRYSTAL_KHZ; -+ } else -+ ndiv = (frequency * 14 * 2) / FE_CRYSTAL_KHZ; -+ ndiv = ndiv + ndiv % 2; -+ ndiv = ndiv - 1024; -+ -+ ret = m88rs2000_tuner_write(state, 0x10, 0x80 | lo); -+ -+ /* Set frequency divider */ -+ ret |= m88rs2000_tuner_write(state, 0x01, (ndiv >> 8) & 0xf); -+ ret |= m88rs2000_tuner_write(state, 0x02, ndiv & 0xff); -+ -+ ret |= m88rs2000_tuner_write(state, 0x03, 0x06); -+ ret |= m88rs2000_tuner_gate_ctrl(state, 0x10); -+ if (ret < 0) -+ return -ENODEV; -+ -+ /* Tuner Frequency Range */ -+ ret = m88rs2000_tuner_write(state, 0x10, lo); -+ -+ ret |= m88rs2000_tuner_gate_ctrl(state, 0x08); -+ -+ /* Tuner RF */ -+ ret |= m88rs2000_set_tuner_rf(fe); -+ -+ gdiv28 = (FE_CRYSTAL_KHZ / 1000 * 1694 + 500) / 1000; -+ ret |= m88rs2000_tuner_write(state, 0x04, gdiv28 & 0xff); -+ ret |= m88rs2000_tuner_gate_ctrl(state, 0x04); -+ if (ret < 0) -+ return -ENODEV; -+ -+ value = m88rs2000_tuner_read(state, 0x26); -+ -+ f3db = (symbol_rate * 135) / 200 + 2000; -+ f3db += FREQ_OFFSET_LOW_SYM_RATE; -+ if (f3db < 7000) -+ f3db = 7000; -+ if (f3db > 40000) -+ f3db = 40000; -+ -+ gdiv28 = gdiv28 * 207 / (value * 2 + 151); -+ mlpf_max = gdiv28 * 135 / 100; -+ mlpf_min = gdiv28 * 78 / 100; -+ if (mlpf_max > 63) -+ mlpf_max = 63; -+ -+ lpf_coeff = 2766; -+ -+ nlpf = (f3db * gdiv28 * 2 / lpf_coeff / -+ (FE_CRYSTAL_KHZ / 1000) + 1) / 2; -+ if (nlpf > 23) -+ nlpf = 23; -+ if (nlpf < 1) -+ nlpf = 1; -+ -+ lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000) -+ * lpf_coeff * 2 / f3db + 1) / 2; -+ -+ if (lpf_mxdiv < mlpf_min) { -+ nlpf++; -+ lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000) -+ * lpf_coeff * 2 / f3db + 1) / 2; -+ } -+ -+ if (lpf_mxdiv > mlpf_max) -+ lpf_mxdiv = mlpf_max; -+ -+ ret = m88rs2000_tuner_write(state, 0x04, lpf_mxdiv); -+ ret |= m88rs2000_tuner_write(state, 0x06, nlpf); -+ -+ ret |= m88rs2000_tuner_gate_ctrl(state, 0x04); -+ -+ ret |= m88rs2000_tuner_gate_ctrl(state, 0x01); -+ -+ msleep(80); -+ /* calculate offset assuming 96000kHz*/ -+ offset_khz = (ndiv - ndiv % 2 + 1024) * FE_CRYSTAL_KHZ -+ / 14 / (div4 + 1) / 2; -+ -+ offset_khz -= frequency; -+ -+ tmp = offset_khz; -+ tmp *= 65536; -+ -+ tmp = (2 * tmp + 96000) / (2 * 96000); -+ if (tmp < 0) -+ tmp += 65536; -+ -+ *offset = tmp & 0xffff; -+ -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); -+ -+ return (ret < 0) ? -EINVAL : 0; -+} -+ -+static int m88rs2000_set_fec(struct m88rs2000_state *state, -+ fe_code_rate_t fec) -+{ -+ int ret; -+ u16 fec_set; -+ switch (fec) { -+ /* This is not confirmed kept for reference */ -+/* case FEC_1_2: -+ fec_set = 0x88; -+ break; -+ case FEC_2_3: -+ fec_set = 0x68; -+ break; -+ case FEC_3_4: -+ fec_set = 0x48; -+ break; -+ case FEC_5_6: -+ fec_set = 0x28; -+ break; -+ case FEC_7_8: -+ fec_set = 0x18; -+ break; */ -+ case FEC_AUTO: -+ default: -+ fec_set = 0x08; -+ } -+ ret = m88rs2000_demod_write(state, 0x76, fec_set); -+ -+ return 0; -+} -+ -+ -+static fe_code_rate_t m88rs2000_get_fec(struct m88rs2000_state *state) -+{ -+ u8 reg; -+ m88rs2000_demod_write(state, 0x9a, 0x30); -+ reg = m88rs2000_demod_read(state, 0x76); -+ m88rs2000_demod_write(state, 0x9a, 0xb0); -+ -+ switch (reg) { -+ case 0x88: -+ return FEC_1_2; -+ case 0x68: -+ return FEC_2_3; -+ case 0x48: -+ return FEC_3_4; -+ case 0x28: -+ return FEC_5_6; -+ case 0x18: -+ return FEC_7_8; -+ case 0x08: -+ default: -+ break; -+ } -+ -+ return FEC_AUTO; -+} -+ -+static int m88rs2000_set_frontend(struct dvb_frontend *fe) -+{ -+ struct m88rs2000_state *state = fe->demodulator_priv; -+ struct dtv_frontend_properties *c = &fe->dtv_property_cache; -+ fe_status_t status; -+ int i, ret; -+ u16 offset = 0; -+ u8 reg; -+ -+ state->no_lock_count = 0; -+ -+ if (c->delivery_system != SYS_DVBS) { -+ deb_info("%s: unsupported delivery " -+ "system selected (%d)\n", -+ __func__, c->delivery_system); -+ return -EOPNOTSUPP; -+ } -+ -+ /* Set Tuner */ -+ ret = m88rs2000_set_tuner(fe, &offset); -+ if (ret < 0) -+ return -ENODEV; -+ -+ ret = m88rs2000_demod_write(state, 0x9a, 0x30); -+ /* Unknown usually 0xc6 sometimes 0xc1 */ -+ reg = m88rs2000_demod_read(state, 0x86); -+ ret |= m88rs2000_demod_write(state, 0x86, reg); -+ /* Offset lower nibble always 0 */ -+ ret |= m88rs2000_demod_write(state, 0x9c, (offset >> 8)); -+ ret |= m88rs2000_demod_write(state, 0x9d, offset & 0xf0); -+ -+ -+ /* Reset Demod */ -+ ret = m88rs2000_tab_set(state, fe_reset); -+ if (ret < 0) -+ return -ENODEV; -+ -+ /* Unknown */ -+ reg = m88rs2000_demod_read(state, 0x70); -+ ret = m88rs2000_demod_write(state, 0x70, reg); -+ -+ /* Set FEC */ -+ ret |= m88rs2000_set_fec(state, c->fec_inner); -+ ret |= m88rs2000_demod_write(state, 0x85, 0x1); -+ ret |= m88rs2000_demod_write(state, 0x8a, 0xbf); -+ ret |= m88rs2000_demod_write(state, 0x8d, 0x1e); -+ ret |= m88rs2000_demod_write(state, 0x90, 0xf1); -+ ret |= m88rs2000_demod_write(state, 0x91, 0x08); -+ -+ if (ret < 0) -+ return -ENODEV; -+ -+ /* Set Symbol Rate */ -+ ret = m88rs2000_set_symbolrate(fe, c->symbol_rate); -+ if (ret < 0) -+ return -ENODEV; -+ -+ /* Set up Demod */ -+ ret = m88rs2000_tab_set(state, fe_trigger); -+ if (ret < 0) -+ return -ENODEV; -+ -+ for (i = 0; i < 25; i++) { -+ u8 reg = m88rs2000_demod_read(state, 0x8c); -+ if ((reg & 0x7) == 0x7) { -+ status = FE_HAS_LOCK; -+ break; -+ } -+ state->no_lock_count++; -+ if (state->no_lock_count > 15) { -+ reg = m88rs2000_demod_read(state, 0x70); -+ reg ^= 0x4; -+ m88rs2000_demod_write(state, 0x70, reg); -+ state->no_lock_count = 0; -+ } -+ if (state->no_lock_count == 20) -+ m88rs2000_set_tuner_rf(fe); -+ msleep(20); -+ } -+ -+ if (status & FE_HAS_LOCK) { -+ state->fec_inner = m88rs2000_get_fec(state); -+ /* Uknown suspect SNR level */ -+ reg = m88rs2000_demod_read(state, 0x65); -+ } -+ -+ state->tuner_frequency = c->frequency; -+ state->symbol_rate = c->symbol_rate; -+ return 0; -+} -+ -+static int m88rs2000_get_frontend(struct dvb_frontend *fe) -+{ -+ struct dtv_frontend_properties *c = &fe->dtv_property_cache; -+ struct m88rs2000_state *state = fe->demodulator_priv; -+ c->fec_inner = state->fec_inner; -+ c->frequency = state->tuner_frequency; -+ c->symbol_rate = state->symbol_rate; -+ return 0; -+} -+ -+static int m88rs2000_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) -+{ -+ struct m88rs2000_state *state = fe->demodulator_priv; -+ -+ if (enable) -+ m88rs2000_demod_write(state, 0x81, 0x84); -+ else -+ m88rs2000_demod_write(state, 0x81, 0x81); -+ udelay(10); -+ return 0; -+} -+ -+static void m88rs2000_release(struct dvb_frontend *fe) -+{ -+ struct m88rs2000_state *state = fe->demodulator_priv; -+ kfree(state); -+} -+ -+static struct dvb_frontend_ops m88rs2000_ops = { -+ .delsys = { SYS_DVBS }, -+ .info = { -+ .name = "M88RS2000 DVB-S", -+ .frequency_min = 950000, -+ .frequency_max = 2150000, -+ .frequency_stepsize = 1000, /* kHz for QPSK frontends */ -+ .frequency_tolerance = 5000, -+ .symbol_rate_min = 1000000, -+ .symbol_rate_max = 45000000, -+ .symbol_rate_tolerance = 500, /* ppm */ -+ .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | -+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | -+ FE_CAN_QPSK | -+ FE_CAN_FEC_AUTO -+ }, -+ -+ .release = m88rs2000_release, -+ .init = m88rs2000_init, -+ .sleep = m88rs2000_sleep, -+ .write = m88rs2000_write, -+ .i2c_gate_ctrl = m88rs2000_i2c_gate_ctrl, -+ .read_status = m88rs2000_read_status, -+ .read_ber = m88rs2000_read_ber, -+ .read_signal_strength = m88rs2000_read_signal_strength, -+ .read_snr = m88rs2000_read_snr, -+ .read_ucblocks = m88rs2000_read_ucblocks, -+ .diseqc_send_master_cmd = m88rs2000_send_diseqc_msg, -+ .diseqc_send_burst = m88rs2000_send_diseqc_burst, -+ .set_tone = m88rs2000_set_tone, -+ .set_voltage = m88rs2000_set_voltage, -+ -+ .set_frontend = m88rs2000_set_frontend, -+ .get_frontend = m88rs2000_get_frontend, -+}; -+ -+struct dvb_frontend *m88rs2000_attach(const struct m88rs2000_config *config, -+ struct i2c_adapter *i2c) -+{ -+ struct m88rs2000_state *state = NULL; -+ -+ /* allocate memory for the internal state */ -+ state = kzalloc(sizeof(struct m88rs2000_state), GFP_KERNEL); -+ if (state == NULL) -+ goto error; -+ -+ /* setup the state */ -+ state->config = config; -+ state->i2c = i2c; -+ state->tuner_frequency = 0; -+ state->symbol_rate = 0; -+ state->fec_inner = 0; -+ -+ if (m88rs2000_startup(state) < 0) -+ goto error; -+ -+ /* create dvb_frontend */ -+ memcpy(&state->frontend.ops, &m88rs2000_ops, -+ sizeof(struct dvb_frontend_ops)); -+ state->frontend.demodulator_priv = state; -+ return &state->frontend; -+ -+error: -+ kfree(state); -+ -+ return NULL; -+} -+EXPORT_SYMBOL(m88rs2000_attach); -+ -+MODULE_DESCRIPTION("M88RS2000 DVB-S Demodulator driver"); -+MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION("1.13"); -+ -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/m88rs2000.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/m88rs2000.h -@@ -0,0 +1,66 @@ -+/* -+ Driver for M88RS2000 demodulator -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ -+*/ -+ -+#ifndef M88RS2000_H -+#define M88RS2000_H -+ -+#include -+#include "dvb_frontend.h" -+ -+struct m88rs2000_config { -+ /* Demodulator i2c address */ -+ u8 demod_addr; -+ /* Tuner address */ -+ u8 tuner_addr; -+ -+ u8 *inittab; -+ -+ /* minimum delay before retuning */ -+ int min_delay_ms; -+ -+ int (*set_ts_params)(struct dvb_frontend *, int); -+}; -+ -+enum { -+ CALL_IS_SET_FRONTEND = 0x0, -+ CALL_IS_READ, -+}; -+ -+#if defined(CONFIG_DVB_M88RS2000) || (defined(CONFIG_DVB_M88RS2000_MODULE) && \ -+ defined(MODULE)) -+extern struct dvb_frontend *m88rs2000_attach( -+ const struct m88rs2000_config *config, struct i2c_adapter *i2c); -+#else -+static inline struct dvb_frontend *m88rs2000_attach( -+ const struct m88rs2000_config *config, struct i2c_adapter *i2c) -+{ -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+#endif /* CONFIG_DVB_M88RS2000 */ -+ -+#define FE_CRYSTAL_KHZ 27000 -+#define FREQ_OFFSET_LOW_SYM_RATE 3000 -+ -+enum { -+ DEMOD_WRITE = 0x1, -+ TUNER_WRITE, -+ WRITE_DELAY = 0x10, -+}; -+#endif /* M88RS2000_H */ -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/lmedm04.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/lmedm04.h -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/lmedm04.h -@@ -41,6 +41,7 @@ - #define LME_ST_ON_W {0x06, 0x00} - #define LME_CLEAR_PID {0x03, 0x02, 0x20, 0xa0} - #define LME_ZERO_PID {0x03, 0x06, 0x00, 0x00, 0x01, 0x00, 0x20, 0x9c} -+#define LME_ALL_PIDS {0x03, 0x06, 0x00, 0xff, 0x01, 0x1f, 0x20, 0x81} - - /* LNB Voltage - * 07 XX XX -Index: linux-3.3.x86_64/drivers/media/video/adv7183.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/video/adv7183.c -@@ -0,0 +1,699 @@ -+/* -+ * adv7183.c Analog Devices ADV7183 video decoder driver -+ * -+ * Copyright (c) 2011 Analog Devices Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "adv7183_regs.h" -+ -+struct adv7183 { -+ struct v4l2_subdev sd; -+ struct v4l2_ctrl_handler hdl; -+ -+ v4l2_std_id std; /* Current set standard */ -+ u32 input; -+ u32 output; -+ unsigned reset_pin; -+ unsigned oe_pin; -+ struct v4l2_mbus_framefmt fmt; -+}; -+ -+/* EXAMPLES USING 27 MHz CLOCK -+ * Mode 1 CVBS Input (Composite Video on AIN5) -+ * All standards are supported through autodetect, 8-bit, 4:2:2, ITU-R BT.656 output on P15 to P8. -+ */ -+static const unsigned char adv7183_init_regs[] = { -+ ADV7183_IN_CTRL, 0x04, /* CVBS input on AIN5 */ -+ ADV7183_DIGI_CLAMP_CTRL_1, 0x00, /* Slow down digital clamps */ -+ ADV7183_SHAP_FILT_CTRL, 0x41, /* Set CSFM to SH1 */ -+ ADV7183_ADC_CTRL, 0x16, /* Power down ADC 1 and ADC 2 */ -+ ADV7183_CTI_DNR_CTRL_4, 0x04, /* Set DNR threshold to 4 for flat response */ -+ /* ADI recommended programming sequence */ -+ ADV7183_ADI_CTRL, 0x80, -+ ADV7183_CTI_DNR_CTRL_4, 0x20, -+ 0x52, 0x18, -+ 0x58, 0xED, -+ 0x77, 0xC5, -+ 0x7C, 0x93, -+ 0x7D, 0x00, -+ 0xD0, 0x48, -+ 0xD5, 0xA0, -+ 0xD7, 0xEA, -+ ADV7183_SD_SATURATION_CR, 0x3E, -+ ADV7183_PAL_V_END, 0x3E, -+ ADV7183_PAL_F_TOGGLE, 0x0F, -+ ADV7183_ADI_CTRL, 0x00, -+}; -+ -+static inline struct adv7183 *to_adv7183(struct v4l2_subdev *sd) -+{ -+ return container_of(sd, struct adv7183, sd); -+} -+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) -+{ -+ return &container_of(ctrl->handler, struct adv7183, hdl)->sd; -+} -+ -+static inline int adv7183_read(struct v4l2_subdev *sd, unsigned char reg) -+{ -+ struct i2c_client *client = v4l2_get_subdevdata(sd); -+ -+ return i2c_smbus_read_byte_data(client, reg); -+} -+ -+static inline int adv7183_write(struct v4l2_subdev *sd, unsigned char reg, -+ unsigned char value) -+{ -+ struct i2c_client *client = v4l2_get_subdevdata(sd); -+ -+ return i2c_smbus_write_byte_data(client, reg, value); -+} -+ -+static int adv7183_writeregs(struct v4l2_subdev *sd, -+ const unsigned char *regs, unsigned int num) -+{ -+ unsigned char reg, data; -+ unsigned int cnt = 0; -+ -+ if (num & 0x1) { -+ v4l2_err(sd, "invalid regs array\n"); -+ return -1; -+ } -+ -+ while (cnt < num) { -+ reg = *regs++; -+ data = *regs++; -+ cnt += 2; -+ -+ adv7183_write(sd, reg, data); -+ } -+ return 0; -+} -+ -+static int adv7183_log_status(struct v4l2_subdev *sd) -+{ -+ struct adv7183 *decoder = to_adv7183(sd); -+ -+ v4l2_info(sd, "adv7183: Input control = 0x%02x\n", -+ adv7183_read(sd, ADV7183_IN_CTRL)); -+ v4l2_info(sd, "adv7183: Video selection = 0x%02x\n", -+ adv7183_read(sd, ADV7183_VD_SEL)); -+ v4l2_info(sd, "adv7183: Output control = 0x%02x\n", -+ adv7183_read(sd, ADV7183_OUT_CTRL)); -+ v4l2_info(sd, "adv7183: Extended output control = 0x%02x\n", -+ adv7183_read(sd, ADV7183_EXT_OUT_CTRL)); -+ v4l2_info(sd, "adv7183: Autodetect enable = 0x%02x\n", -+ adv7183_read(sd, ADV7183_AUTO_DET_EN)); -+ v4l2_info(sd, "adv7183: Contrast = 0x%02x\n", -+ adv7183_read(sd, ADV7183_CONTRAST)); -+ v4l2_info(sd, "adv7183: Brightness = 0x%02x\n", -+ adv7183_read(sd, ADV7183_BRIGHTNESS)); -+ v4l2_info(sd, "adv7183: Hue = 0x%02x\n", -+ adv7183_read(sd, ADV7183_HUE)); -+ v4l2_info(sd, "adv7183: Default value Y = 0x%02x\n", -+ adv7183_read(sd, ADV7183_DEF_Y)); -+ v4l2_info(sd, "adv7183: Default value C = 0x%02x\n", -+ adv7183_read(sd, ADV7183_DEF_C)); -+ v4l2_info(sd, "adv7183: ADI control = 0x%02x\n", -+ adv7183_read(sd, ADV7183_ADI_CTRL)); -+ v4l2_info(sd, "adv7183: Power Management = 0x%02x\n", -+ adv7183_read(sd, ADV7183_POW_MANAGE)); -+ v4l2_info(sd, "adv7183: Status 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n", -+ adv7183_read(sd, ADV7183_STATUS_1), -+ adv7183_read(sd, ADV7183_STATUS_2), -+ adv7183_read(sd, ADV7183_STATUS_3)); -+ v4l2_info(sd, "adv7183: Ident = 0x%02x\n", -+ adv7183_read(sd, ADV7183_IDENT)); -+ v4l2_info(sd, "adv7183: Analog clamp control = 0x%02x\n", -+ adv7183_read(sd, ADV7183_ANAL_CLAMP_CTRL)); -+ v4l2_info(sd, "adv7183: Digital clamp control 1 = 0x%02x\n", -+ adv7183_read(sd, ADV7183_DIGI_CLAMP_CTRL_1)); -+ v4l2_info(sd, "adv7183: Shaping filter control 1 and 2 = 0x%02x 0x%02x\n", -+ adv7183_read(sd, ADV7183_SHAP_FILT_CTRL), -+ adv7183_read(sd, ADV7183_SHAP_FILT_CTRL_2)); -+ v4l2_info(sd, "adv7183: Comb filter control = 0x%02x\n", -+ adv7183_read(sd, ADV7183_COMB_FILT_CTRL)); -+ v4l2_info(sd, "adv7183: ADI control 2 = 0x%02x\n", -+ adv7183_read(sd, ADV7183_ADI_CTRL_2)); -+ v4l2_info(sd, "adv7183: Pixel delay control = 0x%02x\n", -+ adv7183_read(sd, ADV7183_PIX_DELAY_CTRL)); -+ v4l2_info(sd, "adv7183: Misc gain control = 0x%02x\n", -+ adv7183_read(sd, ADV7183_MISC_GAIN_CTRL)); -+ v4l2_info(sd, "adv7183: AGC mode control = 0x%02x\n", -+ adv7183_read(sd, ADV7183_AGC_MODE_CTRL)); -+ v4l2_info(sd, "adv7183: Chroma gain control 1 and 2 = 0x%02x 0x%02x\n", -+ adv7183_read(sd, ADV7183_CHRO_GAIN_CTRL_1), -+ adv7183_read(sd, ADV7183_CHRO_GAIN_CTRL_2)); -+ v4l2_info(sd, "adv7183: Luma gain control 1 and 2 = 0x%02x 0x%02x\n", -+ adv7183_read(sd, ADV7183_LUMA_GAIN_CTRL_1), -+ adv7183_read(sd, ADV7183_LUMA_GAIN_CTRL_2)); -+ v4l2_info(sd, "adv7183: Vsync field control 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n", -+ adv7183_read(sd, ADV7183_VS_FIELD_CTRL_1), -+ adv7183_read(sd, ADV7183_VS_FIELD_CTRL_2), -+ adv7183_read(sd, ADV7183_VS_FIELD_CTRL_3)); -+ v4l2_info(sd, "adv7183: Hsync positon control 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n", -+ adv7183_read(sd, ADV7183_HS_POS_CTRL_1), -+ adv7183_read(sd, ADV7183_HS_POS_CTRL_2), -+ adv7183_read(sd, ADV7183_HS_POS_CTRL_3)); -+ v4l2_info(sd, "adv7183: Polarity = 0x%02x\n", -+ adv7183_read(sd, ADV7183_POLARITY)); -+ v4l2_info(sd, "adv7183: ADC control = 0x%02x\n", -+ adv7183_read(sd, ADV7183_ADC_CTRL)); -+ v4l2_info(sd, "adv7183: SD offset Cb and Cr = 0x%02x 0x%02x\n", -+ adv7183_read(sd, ADV7183_SD_OFFSET_CB), -+ adv7183_read(sd, ADV7183_SD_OFFSET_CR)); -+ v4l2_info(sd, "adv7183: SD saturation Cb and Cr = 0x%02x 0x%02x\n", -+ adv7183_read(sd, ADV7183_SD_SATURATION_CB), -+ adv7183_read(sd, ADV7183_SD_SATURATION_CR)); -+ v4l2_info(sd, "adv7183: Drive strength = 0x%02x\n", -+ adv7183_read(sd, ADV7183_DRIVE_STR)); -+ v4l2_ctrl_handler_log_status(&decoder->hdl, sd->name); -+ return 0; -+} -+ -+static int adv7183_g_std(struct v4l2_subdev *sd, v4l2_std_id *std) -+{ -+ struct adv7183 *decoder = to_adv7183(sd); -+ -+ *std = decoder->std; -+ return 0; -+} -+ -+static int adv7183_s_std(struct v4l2_subdev *sd, v4l2_std_id std) -+{ -+ struct adv7183 *decoder = to_adv7183(sd); -+ int reg; -+ -+ reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF; -+ if (std == V4L2_STD_PAL_60) -+ reg |= 0x60; -+ else if (std == V4L2_STD_NTSC_443) -+ reg |= 0x70; -+ else if (std == V4L2_STD_PAL_N) -+ reg |= 0x90; -+ else if (std == V4L2_STD_PAL_M) -+ reg |= 0xA0; -+ else if (std == V4L2_STD_PAL_Nc) -+ reg |= 0xC0; -+ else if (std & V4L2_STD_PAL) -+ reg |= 0x80; -+ else if (std & V4L2_STD_NTSC) -+ reg |= 0x50; -+ else if (std & V4L2_STD_SECAM) -+ reg |= 0xE0; -+ else -+ return -EINVAL; -+ adv7183_write(sd, ADV7183_IN_CTRL, reg); -+ -+ decoder->std = std; -+ -+ return 0; -+} -+ -+static int adv7183_reset(struct v4l2_subdev *sd, u32 val) -+{ -+ int reg; -+ -+ reg = adv7183_read(sd, ADV7183_POW_MANAGE) | 0x80; -+ adv7183_write(sd, ADV7183_POW_MANAGE, reg); -+ /* wait 5ms before any further i2c writes are performed */ -+ usleep_range(5000, 10000); -+ return 0; -+} -+ -+static int adv7183_s_routing(struct v4l2_subdev *sd, -+ u32 input, u32 output, u32 config) -+{ -+ struct adv7183 *decoder = to_adv7183(sd); -+ int reg; -+ -+ if ((input > ADV7183_COMPONENT1) || (output > ADV7183_16BIT_OUT)) -+ return -EINVAL; -+ -+ if (input != decoder->input) { -+ decoder->input = input; -+ reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF0; -+ switch (input) { -+ case ADV7183_COMPOSITE1: -+ reg |= 0x1; -+ break; -+ case ADV7183_COMPOSITE2: -+ reg |= 0x2; -+ break; -+ case ADV7183_COMPOSITE3: -+ reg |= 0x3; -+ break; -+ case ADV7183_COMPOSITE4: -+ reg |= 0x4; -+ break; -+ case ADV7183_COMPOSITE5: -+ reg |= 0x5; -+ break; -+ case ADV7183_COMPOSITE6: -+ reg |= 0xB; -+ break; -+ case ADV7183_COMPOSITE7: -+ reg |= 0xC; -+ break; -+ case ADV7183_COMPOSITE8: -+ reg |= 0xD; -+ break; -+ case ADV7183_COMPOSITE9: -+ reg |= 0xE; -+ break; -+ case ADV7183_COMPOSITE10: -+ reg |= 0xF; -+ break; -+ case ADV7183_SVIDEO0: -+ reg |= 0x6; -+ break; -+ case ADV7183_SVIDEO1: -+ reg |= 0x7; -+ break; -+ case ADV7183_SVIDEO2: -+ reg |= 0x8; -+ break; -+ case ADV7183_COMPONENT0: -+ reg |= 0x9; -+ break; -+ case ADV7183_COMPONENT1: -+ reg |= 0xA; -+ break; -+ default: -+ break; -+ } -+ adv7183_write(sd, ADV7183_IN_CTRL, reg); -+ } -+ -+ if (output != decoder->output) { -+ decoder->output = output; -+ reg = adv7183_read(sd, ADV7183_OUT_CTRL) & 0xC0; -+ switch (output) { -+ case ADV7183_16BIT_OUT: -+ reg |= 0x9; -+ break; -+ default: -+ reg |= 0xC; -+ break; -+ } -+ adv7183_write(sd, ADV7183_OUT_CTRL, reg); -+ } -+ -+ return 0; -+} -+ -+static int adv7183_s_ctrl(struct v4l2_ctrl *ctrl) -+{ -+ struct v4l2_subdev *sd = to_sd(ctrl); -+ int val = ctrl->val; -+ -+ switch (ctrl->id) { -+ case V4L2_CID_BRIGHTNESS: -+ if (val < 0) -+ val = 127 - val; -+ adv7183_write(sd, ADV7183_BRIGHTNESS, val); -+ break; -+ case V4L2_CID_CONTRAST: -+ adv7183_write(sd, ADV7183_CONTRAST, val); -+ break; -+ case V4L2_CID_SATURATION: -+ adv7183_write(sd, ADV7183_SD_SATURATION_CB, val >> 8); -+ adv7183_write(sd, ADV7183_SD_SATURATION_CR, (val & 0xFF)); -+ break; -+ case V4L2_CID_HUE: -+ adv7183_write(sd, ADV7183_SD_OFFSET_CB, val >> 8); -+ adv7183_write(sd, ADV7183_SD_OFFSET_CR, (val & 0xFF)); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int adv7183_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) -+{ -+ struct adv7183 *decoder = to_adv7183(sd); -+ int reg; -+ -+ /* enable autodetection block */ -+ reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF; -+ adv7183_write(sd, ADV7183_IN_CTRL, reg); -+ -+ /* wait autodetection switch */ -+ mdelay(10); -+ -+ /* get autodetection result */ -+ reg = adv7183_read(sd, ADV7183_STATUS_1); -+ switch ((reg >> 0x4) & 0x7) { -+ case 0: -+ *std = V4L2_STD_NTSC; -+ break; -+ case 1: -+ *std = V4L2_STD_NTSC_443; -+ break; -+ case 2: -+ *std = V4L2_STD_PAL_M; -+ break; -+ case 3: -+ *std = V4L2_STD_PAL_60; -+ break; -+ case 4: -+ *std = V4L2_STD_PAL; -+ break; -+ case 5: -+ *std = V4L2_STD_SECAM; -+ break; -+ case 6: -+ *std = V4L2_STD_PAL_Nc; -+ break; -+ case 7: -+ *std = V4L2_STD_SECAM; -+ break; -+ default: -+ *std = V4L2_STD_UNKNOWN; -+ break; -+ } -+ -+ /* after std detection, write back user set std */ -+ adv7183_s_std(sd, decoder->std); -+ return 0; -+} -+ -+static int adv7183_g_input_status(struct v4l2_subdev *sd, u32 *status) -+{ -+ int reg; -+ -+ *status = V4L2_IN_ST_NO_SIGNAL; -+ reg = adv7183_read(sd, ADV7183_STATUS_1); -+ if (reg < 0) -+ return reg; -+ if (reg & 0x1) -+ *status = 0; -+ return 0; -+} -+ -+static int adv7183_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, -+ enum v4l2_mbus_pixelcode *code) -+{ -+ if (index > 0) -+ return -EINVAL; -+ -+ *code = V4L2_MBUS_FMT_UYVY8_2X8; -+ return 0; -+} -+ -+static int adv7183_try_mbus_fmt(struct v4l2_subdev *sd, -+ struct v4l2_mbus_framefmt *fmt) -+{ -+ struct adv7183 *decoder = to_adv7183(sd); -+ -+ fmt->code = V4L2_MBUS_FMT_UYVY8_2X8; -+ fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; -+ if (decoder->std & V4L2_STD_525_60) { -+ fmt->field = V4L2_FIELD_SEQ_TB; -+ fmt->width = 720; -+ fmt->height = 480; -+ } else { -+ fmt->field = V4L2_FIELD_SEQ_BT; -+ fmt->width = 720; -+ fmt->height = 576; -+ } -+ return 0; -+} -+ -+static int adv7183_s_mbus_fmt(struct v4l2_subdev *sd, -+ struct v4l2_mbus_framefmt *fmt) -+{ -+ struct adv7183 *decoder = to_adv7183(sd); -+ -+ adv7183_try_mbus_fmt(sd, fmt); -+ decoder->fmt = *fmt; -+ return 0; -+} -+ -+static int adv7183_g_mbus_fmt(struct v4l2_subdev *sd, -+ struct v4l2_mbus_framefmt *fmt) -+{ -+ struct adv7183 *decoder = to_adv7183(sd); -+ -+ *fmt = decoder->fmt; -+ return 0; -+} -+ -+static int adv7183_s_stream(struct v4l2_subdev *sd, int enable) -+{ -+ struct adv7183 *decoder = to_adv7183(sd); -+ -+ if (enable) -+ gpio_direction_output(decoder->oe_pin, 0); -+ else -+ gpio_direction_output(decoder->oe_pin, 1); -+ udelay(1); -+ return 0; -+} -+ -+static int adv7183_g_chip_ident(struct v4l2_subdev *sd, -+ struct v4l2_dbg_chip_ident *chip) -+{ -+ int rev; -+ struct i2c_client *client = v4l2_get_subdevdata(sd); -+ -+ /* 0x11 for adv7183, 0x13 for adv7183b */ -+ rev = adv7183_read(sd, ADV7183_IDENT); -+ -+ return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7183, rev); -+} -+ -+#ifdef CONFIG_VIDEO_ADV_DEBUG -+static int adv7183_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) -+{ -+ struct i2c_client *client = v4l2_get_subdevdata(sd); -+ -+ if (!v4l2_chip_match_i2c_client(client, ®->match)) -+ return -EINVAL; -+ if (!capable(CAP_SYS_ADMIN)) -+ return -EPERM; -+ reg->val = adv7183_read(sd, reg->reg & 0xff); -+ reg->size = 1; -+ return 0; -+} -+ -+static int adv7183_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) -+{ -+ struct i2c_client *client = v4l2_get_subdevdata(sd); -+ -+ if (!v4l2_chip_match_i2c_client(client, ®->match)) -+ return -EINVAL; -+ if (!capable(CAP_SYS_ADMIN)) -+ return -EPERM; -+ adv7183_write(sd, reg->reg & 0xff, reg->val & 0xff); -+ return 0; -+} -+#endif -+ -+static const struct v4l2_ctrl_ops adv7183_ctrl_ops = { -+ .s_ctrl = adv7183_s_ctrl, -+}; -+ -+static const struct v4l2_subdev_core_ops adv7183_core_ops = { -+ .log_status = adv7183_log_status, -+ .g_std = adv7183_g_std, -+ .s_std = adv7183_s_std, -+ .reset = adv7183_reset, -+ .g_chip_ident = adv7183_g_chip_ident, -+#ifdef CONFIG_VIDEO_ADV_DEBUG -+ .g_register = adv7183_g_register, -+ .s_register = adv7183_s_register, -+#endif -+}; -+ -+static const struct v4l2_subdev_video_ops adv7183_video_ops = { -+ .s_routing = adv7183_s_routing, -+ .querystd = adv7183_querystd, -+ .g_input_status = adv7183_g_input_status, -+ .enum_mbus_fmt = adv7183_enum_mbus_fmt, -+ .try_mbus_fmt = adv7183_try_mbus_fmt, -+ .s_mbus_fmt = adv7183_s_mbus_fmt, -+ .g_mbus_fmt = adv7183_g_mbus_fmt, -+ .s_stream = adv7183_s_stream, -+}; -+ -+static const struct v4l2_subdev_ops adv7183_ops = { -+ .core = &adv7183_core_ops, -+ .video = &adv7183_video_ops, -+}; -+ -+static int adv7183_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+{ -+ struct adv7183 *decoder; -+ struct v4l2_subdev *sd; -+ struct v4l2_ctrl_handler *hdl; -+ int ret; -+ struct v4l2_mbus_framefmt fmt; -+ const unsigned *pin_array; -+ -+ /* Check if the adapter supports the needed features */ -+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) -+ return -EIO; -+ -+ v4l_info(client, "chip found @ 0x%02x (%s)\n", -+ client->addr << 1, client->adapter->name); -+ -+ pin_array = client->dev.platform_data; -+ if (pin_array == NULL) -+ return -EINVAL; -+ -+ decoder = kzalloc(sizeof(struct adv7183), GFP_KERNEL); -+ if (decoder == NULL) -+ return -ENOMEM; -+ -+ decoder->reset_pin = pin_array[0]; -+ decoder->oe_pin = pin_array[1]; -+ -+ if (gpio_request(decoder->reset_pin, "ADV7183 Reset")) { -+ v4l_err(client, "failed to request GPIO %d\n", decoder->reset_pin); -+ ret = -EBUSY; -+ goto err_free_decoder; -+ } -+ -+ if (gpio_request(decoder->oe_pin, "ADV7183 Output Enable")) { -+ v4l_err(client, "failed to request GPIO %d\n", decoder->oe_pin); -+ ret = -EBUSY; -+ goto err_free_reset; -+ } -+ -+ sd = &decoder->sd; -+ v4l2_i2c_subdev_init(sd, client, &adv7183_ops); -+ -+ hdl = &decoder->hdl; -+ v4l2_ctrl_handler_init(hdl, 4); -+ v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops, -+ V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); -+ v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops, -+ V4L2_CID_CONTRAST, 0, 0xFF, 1, 0x80); -+ v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops, -+ V4L2_CID_SATURATION, 0, 0xFFFF, 1, 0x8080); -+ v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops, -+ V4L2_CID_HUE, 0, 0xFFFF, 1, 0x8080); -+ /* hook the control handler into the driver */ -+ sd->ctrl_handler = hdl; -+ if (hdl->error) { -+ ret = hdl->error; -+ -+ v4l2_ctrl_handler_free(hdl); -+ goto err_free_oe; -+ } -+ -+ /* v4l2 doesn't support an autodetect standard, pick PAL as default */ -+ decoder->std = V4L2_STD_PAL; -+ decoder->input = ADV7183_COMPOSITE4; -+ decoder->output = ADV7183_8BIT_OUT; -+ -+ gpio_direction_output(decoder->oe_pin, 1); -+ /* reset chip */ -+ gpio_direction_output(decoder->reset_pin, 0); -+ /* reset pulse width at least 5ms */ -+ mdelay(10); -+ gpio_direction_output(decoder->reset_pin, 1); -+ /* wait 5ms before any further i2c writes are performed */ -+ mdelay(5); -+ -+ adv7183_writeregs(sd, adv7183_init_regs, ARRAY_SIZE(adv7183_init_regs)); -+ adv7183_s_std(sd, decoder->std); -+ fmt.width = 720; -+ fmt.height = 576; -+ adv7183_s_mbus_fmt(sd, &fmt); -+ -+ /* initialize the hardware to the default control values */ -+ ret = v4l2_ctrl_handler_setup(hdl); -+ if (ret) { -+ v4l2_ctrl_handler_free(hdl); -+ goto err_free_oe; -+ } -+ -+ return 0; -+err_free_oe: -+ gpio_free(decoder->oe_pin); -+err_free_reset: -+ gpio_free(decoder->reset_pin); -+err_free_decoder: -+ kfree(decoder); -+ return ret; -+} -+ -+static int adv7183_remove(struct i2c_client *client) -+{ -+ struct v4l2_subdev *sd = i2c_get_clientdata(client); -+ struct adv7183 *decoder = to_adv7183(sd); -+ -+ v4l2_device_unregister_subdev(sd); -+ v4l2_ctrl_handler_free(sd->ctrl_handler); -+ gpio_free(decoder->oe_pin); -+ gpio_free(decoder->reset_pin); -+ kfree(decoder); -+ return 0; -+} -+ -+static const struct i2c_device_id adv7183_id[] = { -+ {"adv7183", 0}, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(i2c, adv7183_id); -+ -+static struct i2c_driver adv7183_driver = { -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "adv7183", -+ }, -+ .probe = adv7183_probe, -+ .remove = __devexit_p(adv7183_remove), -+ .id_table = adv7183_id, -+}; -+ -+static __init int adv7183_init(void) -+{ -+ return i2c_add_driver(&adv7183_driver); -+} -+ -+static __exit void adv7183_exit(void) -+{ -+ i2c_del_driver(&adv7183_driver); -+} -+ -+module_init(adv7183_init); -+module_exit(adv7183_exit); -+ -+MODULE_DESCRIPTION("Analog Devices ADV7183 video decoder driver"); -+MODULE_AUTHOR("Scott Jiang "); -+MODULE_LICENSE("GPL v2"); -Index: linux-3.3.x86_64/drivers/media/video/adv7183_regs.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/video/adv7183_regs.h -@@ -0,0 +1,107 @@ -+/* -+ * adv7183 - Analog Devices ADV7183 video decoder registers -+ * -+ * Copyright (c) 2011 Analog Devices Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#ifndef _ADV7183_REGS_H_ -+#define _ADV7183_REGS_H_ -+ -+#define ADV7183_IN_CTRL 0x00 /* Input control */ -+#define ADV7183_VD_SEL 0x01 /* Video selection */ -+#define ADV7183_OUT_CTRL 0x03 /* Output control */ -+#define ADV7183_EXT_OUT_CTRL 0x04 /* Extended output control */ -+#define ADV7183_AUTO_DET_EN 0x07 /* Autodetect enable */ -+#define ADV7183_CONTRAST 0x08 /* Contrast */ -+#define ADV7183_BRIGHTNESS 0x0A /* Brightness */ -+#define ADV7183_HUE 0x0B /* Hue */ -+#define ADV7183_DEF_Y 0x0C /* Default value Y */ -+#define ADV7183_DEF_C 0x0D /* Default value C */ -+#define ADV7183_ADI_CTRL 0x0E /* ADI control */ -+#define ADV7183_POW_MANAGE 0x0F /* Power Management */ -+#define ADV7183_STATUS_1 0x10 /* Status 1 */ -+#define ADV7183_IDENT 0x11 /* Ident */ -+#define ADV7183_STATUS_2 0x12 /* Status 2 */ -+#define ADV7183_STATUS_3 0x13 /* Status 3 */ -+#define ADV7183_ANAL_CLAMP_CTRL 0x14 /* Analog clamp control */ -+#define ADV7183_DIGI_CLAMP_CTRL_1 0x15 /* Digital clamp control 1 */ -+#define ADV7183_SHAP_FILT_CTRL 0x17 /* Shaping filter control */ -+#define ADV7183_SHAP_FILT_CTRL_2 0x18 /* Shaping filter control 2 */ -+#define ADV7183_COMB_FILT_CTRL 0x19 /* Comb filter control */ -+#define ADV7183_ADI_CTRL_2 0x1D /* ADI control 2 */ -+#define ADV7183_PIX_DELAY_CTRL 0x27 /* Pixel delay control */ -+#define ADV7183_MISC_GAIN_CTRL 0x2B /* Misc gain control */ -+#define ADV7183_AGC_MODE_CTRL 0x2C /* AGC mode control */ -+#define ADV7183_CHRO_GAIN_CTRL_1 0x2D /* Chroma gain control 1 */ -+#define ADV7183_CHRO_GAIN_CTRL_2 0x2E /* Chroma gain control 2 */ -+#define ADV7183_LUMA_GAIN_CTRL_1 0x2F /* Luma gain control 1 */ -+#define ADV7183_LUMA_GAIN_CTRL_2 0x30 /* Luma gain control 2 */ -+#define ADV7183_VS_FIELD_CTRL_1 0x31 /* Vsync field control 1 */ -+#define ADV7183_VS_FIELD_CTRL_2 0x32 /* Vsync field control 2 */ -+#define ADV7183_VS_FIELD_CTRL_3 0x33 /* Vsync field control 3 */ -+#define ADV7183_HS_POS_CTRL_1 0x34 /* Hsync positon control 1 */ -+#define ADV7183_HS_POS_CTRL_2 0x35 /* Hsync positon control 2 */ -+#define ADV7183_HS_POS_CTRL_3 0x36 /* Hsync positon control 3 */ -+#define ADV7183_POLARITY 0x37 /* Polarity */ -+#define ADV7183_NTSC_COMB_CTRL 0x38 /* NTSC comb control */ -+#define ADV7183_PAL_COMB_CTRL 0x39 /* PAL comb control */ -+#define ADV7183_ADC_CTRL 0x3A /* ADC control */ -+#define ADV7183_MAN_WIN_CTRL 0x3D /* Manual window control */ -+#define ADV7183_RESAMPLE_CTRL 0x41 /* Resample control */ -+#define ADV7183_GEMSTAR_CTRL_1 0x48 /* Gemstar ctrl 1 */ -+#define ADV7183_GEMSTAR_CTRL_2 0x49 /* Gemstar ctrl 2 */ -+#define ADV7183_GEMSTAR_CTRL_3 0x4A /* Gemstar ctrl 3 */ -+#define ADV7183_GEMSTAR_CTRL_4 0x4B /* Gemstar ctrl 4 */ -+#define ADV7183_GEMSTAR_CTRL_5 0x4C /* Gemstar ctrl 5 */ -+#define ADV7183_CTI_DNR_CTRL_1 0x4D /* CTI DNR ctrl 1 */ -+#define ADV7183_CTI_DNR_CTRL_2 0x4E /* CTI DNR ctrl 2 */ -+#define ADV7183_CTI_DNR_CTRL_4 0x50 /* CTI DNR ctrl 4 */ -+#define ADV7183_LOCK_CNT 0x51 /* Lock count */ -+#define ADV7183_FREE_LINE_LEN 0x8F /* Free-Run line length 1 */ -+#define ADV7183_VBI_INFO 0x90 /* VBI info */ -+#define ADV7183_WSS_1 0x91 /* WSS 1 */ -+#define ADV7183_WSS_2 0x92 /* WSS 2 */ -+#define ADV7183_EDTV_1 0x93 /* EDTV 1 */ -+#define ADV7183_EDTV_2 0x94 /* EDTV 2 */ -+#define ADV7183_EDTV_3 0x95 /* EDTV 3 */ -+#define ADV7183_CGMS_1 0x96 /* CGMS 1 */ -+#define ADV7183_CGMS_2 0x97 /* CGMS 2 */ -+#define ADV7183_CGMS_3 0x98 /* CGMS 3 */ -+#define ADV7183_CCAP_1 0x99 /* CCAP 1 */ -+#define ADV7183_CCAP_2 0x9A /* CCAP 2 */ -+#define ADV7183_LETTERBOX_1 0x9B /* Letterbox 1 */ -+#define ADV7183_LETTERBOX_2 0x9C /* Letterbox 2 */ -+#define ADV7183_LETTERBOX_3 0x9D /* Letterbox 3 */ -+#define ADV7183_CRC_EN 0xB2 /* CRC enable */ -+#define ADV7183_ADC_SWITCH_1 0xC3 /* ADC switch 1 */ -+#define ADV7183_ADC_SWITCH_2 0xC4 /* ADC swithc 2 */ -+#define ADV7183_LETTERBOX_CTRL_1 0xDC /* Letterbox control 1 */ -+#define ADV7183_LETTERBOX_CTRL_2 0xDD /* Letterbox control 2 */ -+#define ADV7183_SD_OFFSET_CB 0xE1 /* SD offset Cb */ -+#define ADV7183_SD_OFFSET_CR 0xE2 /* SD offset Cr */ -+#define ADV7183_SD_SATURATION_CB 0xE3 /* SD saturation Cb */ -+#define ADV7183_SD_SATURATION_CR 0xE4 /* SD saturation Cr */ -+#define ADV7183_NTSC_V_BEGIN 0xE5 /* NTSC V bit begin */ -+#define ADV7183_NTSC_V_END 0xE6 /* NTSC V bit end */ -+#define ADV7183_NTSC_F_TOGGLE 0xE7 /* NTSC F bit toggle */ -+#define ADV7183_PAL_V_BEGIN 0xE8 /* PAL V bit begin */ -+#define ADV7183_PAL_V_END 0xE9 /* PAL V bit end */ -+#define ADV7183_PAL_F_TOGGLE 0xEA /* PAL F bit toggle */ -+#define ADV7183_DRIVE_STR 0xF4 /* Drive strength */ -+#define ADV7183_IF_COMP_CTRL 0xF8 /* IF comp control */ -+#define ADV7183_VS_MODE_CTRL 0xF9 /* VS mode control */ -+ -+#endif -Index: linux-3.3.x86_64/include/media/adv7183.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/include/media/adv7183.h -@@ -0,0 +1,47 @@ -+/* -+ * adv7183.h - definition for adv7183 inputs and outputs -+ * -+ * Copyright (c) 2011 Analog Devices Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#ifndef _ADV7183_H_ -+#define _ADV7183_H_ -+ -+/* ADV7183 HW inputs */ -+#define ADV7183_COMPOSITE0 0 /* CVBS in on AIN1 */ -+#define ADV7183_COMPOSITE1 1 /* CVBS in on AIN2 */ -+#define ADV7183_COMPOSITE2 2 /* CVBS in on AIN3 */ -+#define ADV7183_COMPOSITE3 3 /* CVBS in on AIN4 */ -+#define ADV7183_COMPOSITE4 4 /* CVBS in on AIN5 */ -+#define ADV7183_COMPOSITE5 5 /* CVBS in on AIN6 */ -+#define ADV7183_COMPOSITE6 6 /* CVBS in on AIN7 */ -+#define ADV7183_COMPOSITE7 7 /* CVBS in on AIN8 */ -+#define ADV7183_COMPOSITE8 8 /* CVBS in on AIN9 */ -+#define ADV7183_COMPOSITE9 9 /* CVBS in on AIN10 */ -+#define ADV7183_COMPOSITE10 10 /* CVBS in on AIN11 */ -+ -+#define ADV7183_SVIDEO0 11 /* Y on AIN1, C on AIN4 */ -+#define ADV7183_SVIDEO1 12 /* Y on AIN2, C on AIN5 */ -+#define ADV7183_SVIDEO2 13 /* Y on AIN3, C on AIN6 */ -+ -+#define ADV7183_COMPONENT0 14 /* Y on AIN1, Pr on AIN4, Pb on AIN5 */ -+#define ADV7183_COMPONENT1 15 /* Y on AIN2, Pr on AIN3, Pb on AIN6 */ -+ -+/* ADV7183 HW outputs */ -+#define ADV7183_8BIT_OUT 0 -+#define ADV7183_16BIT_OUT 1 -+ -+#endif -Index: linux-3.3.x86_64/include/media/v4l2-chip-ident.h -=================================================================== ---- linux-3.3.x86_64.orig/include/media/v4l2-chip-ident.h -+++ linux-3.3.x86_64/include/media/v4l2-chip-ident.h -@@ -143,6 +143,9 @@ enum { - /* module saa6588: just ident 6588 */ - V4L2_IDENT_SAA6588 = 6588, - -+ /* module vs6624: just ident 6624 */ -+ V4L2_IDENT_VS6624 = 6624, -+ - /* module saa6752hs: reserved range 6750-6759 */ - V4L2_IDENT_SAA6752HS = 6752, - V4L2_IDENT_SAA6752HS_AC3 = 6753, -@@ -162,6 +165,9 @@ enum { - /* module adv7180: just ident 7180 */ - V4L2_IDENT_ADV7180 = 7180, - -+ /* module adv7183: just ident 7183 */ -+ V4L2_IDENT_ADV7183 = 7183, -+ - /* module saa7185: just ident 7185 */ - V4L2_IDENT_SAA7185 = 7185, - -Index: linux-3.3.x86_64/drivers/media/video/vs6624.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/video/vs6624.c -@@ -0,0 +1,928 @@ -+/* -+ * vs6624.c ST VS6624 CMOS image sensor driver -+ * -+ * Copyright (c) 2011 Analog Devices Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "vs6624_regs.h" -+ -+#define VGA_WIDTH 640 -+#define VGA_HEIGHT 480 -+#define QVGA_WIDTH 320 -+#define QVGA_HEIGHT 240 -+#define QQVGA_WIDTH 160 -+#define QQVGA_HEIGHT 120 -+#define CIF_WIDTH 352 -+#define CIF_HEIGHT 288 -+#define QCIF_WIDTH 176 -+#define QCIF_HEIGHT 144 -+#define QQCIF_WIDTH 88 -+#define QQCIF_HEIGHT 72 -+ -+#define MAX_FRAME_RATE 30 -+ -+struct vs6624 { -+ struct v4l2_subdev sd; -+ struct v4l2_ctrl_handler hdl; -+ struct v4l2_fract frame_rate; -+ struct v4l2_mbus_framefmt fmt; -+ unsigned ce_pin; -+}; -+ -+static const struct vs6624_format { -+ enum v4l2_mbus_pixelcode mbus_code; -+ enum v4l2_colorspace colorspace; -+} vs6624_formats[] = { -+ { -+ .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, -+ .colorspace = V4L2_COLORSPACE_JPEG, -+ }, -+ { -+ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, -+ .colorspace = V4L2_COLORSPACE_JPEG, -+ }, -+ { -+ .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, -+ .colorspace = V4L2_COLORSPACE_SRGB, -+ }, -+}; -+ -+static struct v4l2_mbus_framefmt vs6624_default_fmt = { -+ .width = VGA_WIDTH, -+ .height = VGA_HEIGHT, -+ .code = V4L2_MBUS_FMT_UYVY8_2X8, -+ .field = V4L2_FIELD_NONE, -+ .colorspace = V4L2_COLORSPACE_JPEG, -+}; -+ -+static const u16 vs6624_p1[] = { -+ 0x8104, 0x03, -+ 0x8105, 0x01, -+ 0xc900, 0x03, -+ 0xc904, 0x47, -+ 0xc905, 0x10, -+ 0xc906, 0x80, -+ 0xc907, 0x3a, -+ 0x903a, 0x02, -+ 0x903b, 0x47, -+ 0x903c, 0x15, -+ 0xc908, 0x31, -+ 0xc909, 0xdc, -+ 0xc90a, 0x80, -+ 0xc90b, 0x44, -+ 0x9044, 0x02, -+ 0x9045, 0x31, -+ 0x9046, 0xe2, -+ 0xc90c, 0x07, -+ 0xc90d, 0xe0, -+ 0xc90e, 0x80, -+ 0xc90f, 0x47, -+ 0x9047, 0x90, -+ 0x9048, 0x83, -+ 0x9049, 0x81, -+ 0x904a, 0xe0, -+ 0x904b, 0x60, -+ 0x904c, 0x08, -+ 0x904d, 0x90, -+ 0x904e, 0xc0, -+ 0x904f, 0x43, -+ 0x9050, 0x74, -+ 0x9051, 0x01, -+ 0x9052, 0xf0, -+ 0x9053, 0x80, -+ 0x9054, 0x05, -+ 0x9055, 0xE4, -+ 0x9056, 0x90, -+ 0x9057, 0xc0, -+ 0x9058, 0x43, -+ 0x9059, 0xf0, -+ 0x905a, 0x02, -+ 0x905b, 0x07, -+ 0x905c, 0xec, -+ 0xc910, 0x5d, -+ 0xc911, 0xca, -+ 0xc912, 0x80, -+ 0xc913, 0x5d, -+ 0x905d, 0xa3, -+ 0x905e, 0x04, -+ 0x905f, 0xf0, -+ 0x9060, 0xa3, -+ 0x9061, 0x04, -+ 0x9062, 0xf0, -+ 0x9063, 0x22, -+ 0xc914, 0x72, -+ 0xc915, 0x92, -+ 0xc916, 0x80, -+ 0xc917, 0x64, -+ 0x9064, 0x74, -+ 0x9065, 0x01, -+ 0x9066, 0x02, -+ 0x9067, 0x72, -+ 0x9068, 0x95, -+ 0xc918, 0x47, -+ 0xc919, 0xf2, -+ 0xc91a, 0x81, -+ 0xc91b, 0x69, -+ 0x9169, 0x74, -+ 0x916a, 0x02, -+ 0x916b, 0xf0, -+ 0x916c, 0xec, -+ 0x916d, 0xb4, -+ 0x916e, 0x10, -+ 0x916f, 0x0a, -+ 0x9170, 0x90, -+ 0x9171, 0x80, -+ 0x9172, 0x16, -+ 0x9173, 0xe0, -+ 0x9174, 0x70, -+ 0x9175, 0x04, -+ 0x9176, 0x90, -+ 0x9177, 0xd3, -+ 0x9178, 0xc4, -+ 0x9179, 0xf0, -+ 0x917a, 0x22, -+ 0xc91c, 0x0a, -+ 0xc91d, 0xbe, -+ 0xc91e, 0x80, -+ 0xc91f, 0x73, -+ 0x9073, 0xfc, -+ 0x9074, 0xa3, -+ 0x9075, 0xe0, -+ 0x9076, 0xf5, -+ 0x9077, 0x82, -+ 0x9078, 0x8c, -+ 0x9079, 0x83, -+ 0x907a, 0xa3, -+ 0x907b, 0xa3, -+ 0x907c, 0xe0, -+ 0x907d, 0xfc, -+ 0x907e, 0xa3, -+ 0x907f, 0xe0, -+ 0x9080, 0xc3, -+ 0x9081, 0x9f, -+ 0x9082, 0xff, -+ 0x9083, 0xec, -+ 0x9084, 0x9e, -+ 0x9085, 0xfe, -+ 0x9086, 0x02, -+ 0x9087, 0x0a, -+ 0x9088, 0xea, -+ 0xc920, 0x47, -+ 0xc921, 0x38, -+ 0xc922, 0x80, -+ 0xc923, 0x89, -+ 0x9089, 0xec, -+ 0x908a, 0xd3, -+ 0x908b, 0x94, -+ 0x908c, 0x20, -+ 0x908d, 0x40, -+ 0x908e, 0x01, -+ 0x908f, 0x1c, -+ 0x9090, 0x90, -+ 0x9091, 0xd3, -+ 0x9092, 0xd4, -+ 0x9093, 0xec, -+ 0x9094, 0xf0, -+ 0x9095, 0x02, -+ 0x9096, 0x47, -+ 0x9097, 0x3d, -+ 0xc924, 0x45, -+ 0xc925, 0xca, -+ 0xc926, 0x80, -+ 0xc927, 0x98, -+ 0x9098, 0x12, -+ 0x9099, 0x77, -+ 0x909a, 0xd6, -+ 0x909b, 0x02, -+ 0x909c, 0x45, -+ 0x909d, 0xcd, -+ 0xc928, 0x20, -+ 0xc929, 0xd5, -+ 0xc92a, 0x80, -+ 0xc92b, 0x9e, -+ 0x909e, 0x90, -+ 0x909f, 0x82, -+ 0x90a0, 0x18, -+ 0x90a1, 0xe0, -+ 0x90a2, 0xb4, -+ 0x90a3, 0x03, -+ 0x90a4, 0x0e, -+ 0x90a5, 0x90, -+ 0x90a6, 0x83, -+ 0x90a7, 0xbf, -+ 0x90a8, 0xe0, -+ 0x90a9, 0x60, -+ 0x90aa, 0x08, -+ 0x90ab, 0x90, -+ 0x90ac, 0x81, -+ 0x90ad, 0xfc, -+ 0x90ae, 0xe0, -+ 0x90af, 0xff, -+ 0x90b0, 0xc3, -+ 0x90b1, 0x13, -+ 0x90b2, 0xf0, -+ 0x90b3, 0x90, -+ 0x90b4, 0x81, -+ 0x90b5, 0xfc, -+ 0x90b6, 0xe0, -+ 0x90b7, 0xff, -+ 0x90b8, 0x02, -+ 0x90b9, 0x20, -+ 0x90ba, 0xda, -+ 0xc92c, 0x70, -+ 0xc92d, 0xbc, -+ 0xc92e, 0x80, -+ 0xc92f, 0xbb, -+ 0x90bb, 0x90, -+ 0x90bc, 0x82, -+ 0x90bd, 0x18, -+ 0x90be, 0xe0, -+ 0x90bf, 0xb4, -+ 0x90c0, 0x03, -+ 0x90c1, 0x06, -+ 0x90c2, 0x90, -+ 0x90c3, 0xc1, -+ 0x90c4, 0x06, -+ 0x90c5, 0x74, -+ 0x90c6, 0x05, -+ 0x90c7, 0xf0, -+ 0x90c8, 0x90, -+ 0x90c9, 0xd3, -+ 0x90ca, 0xa0, -+ 0x90cb, 0x02, -+ 0x90cc, 0x70, -+ 0x90cd, 0xbf, -+ 0xc930, 0x72, -+ 0xc931, 0x21, -+ 0xc932, 0x81, -+ 0xc933, 0x3b, -+ 0x913b, 0x7d, -+ 0x913c, 0x02, -+ 0x913d, 0x7f, -+ 0x913e, 0x7b, -+ 0x913f, 0x02, -+ 0x9140, 0x72, -+ 0x9141, 0x25, -+ 0xc934, 0x28, -+ 0xc935, 0xae, -+ 0xc936, 0x80, -+ 0xc937, 0xd2, -+ 0x90d2, 0xf0, -+ 0x90d3, 0x90, -+ 0x90d4, 0xd2, -+ 0x90d5, 0x0a, -+ 0x90d6, 0x02, -+ 0x90d7, 0x28, -+ 0x90d8, 0xb4, -+ 0xc938, 0x28, -+ 0xc939, 0xb1, -+ 0xc93a, 0x80, -+ 0xc93b, 0xd9, -+ 0x90d9, 0x90, -+ 0x90da, 0x83, -+ 0x90db, 0xba, -+ 0x90dc, 0xe0, -+ 0x90dd, 0xff, -+ 0x90de, 0x90, -+ 0x90df, 0xd2, -+ 0x90e0, 0x08, -+ 0x90e1, 0xe0, -+ 0x90e2, 0xe4, -+ 0x90e3, 0xef, -+ 0x90e4, 0xf0, -+ 0x90e5, 0xa3, -+ 0x90e6, 0xe0, -+ 0x90e7, 0x74, -+ 0x90e8, 0xff, -+ 0x90e9, 0xf0, -+ 0x90ea, 0x90, -+ 0x90eb, 0xd2, -+ 0x90ec, 0x0a, -+ 0x90ed, 0x02, -+ 0x90ee, 0x28, -+ 0x90ef, 0xb4, -+ 0xc93c, 0x29, -+ 0xc93d, 0x79, -+ 0xc93e, 0x80, -+ 0xc93f, 0xf0, -+ 0x90f0, 0xf0, -+ 0x90f1, 0x90, -+ 0x90f2, 0xd2, -+ 0x90f3, 0x0e, -+ 0x90f4, 0x02, -+ 0x90f5, 0x29, -+ 0x90f6, 0x7f, -+ 0xc940, 0x29, -+ 0xc941, 0x7c, -+ 0xc942, 0x80, -+ 0xc943, 0xf7, -+ 0x90f7, 0x90, -+ 0x90f8, 0x83, -+ 0x90f9, 0xba, -+ 0x90fa, 0xe0, -+ 0x90fb, 0xff, -+ 0x90fc, 0x90, -+ 0x90fd, 0xd2, -+ 0x90fe, 0x0c, -+ 0x90ff, 0xe0, -+ 0x9100, 0xe4, -+ 0x9101, 0xef, -+ 0x9102, 0xf0, -+ 0x9103, 0xa3, -+ 0x9104, 0xe0, -+ 0x9105, 0x74, -+ 0x9106, 0xff, -+ 0x9107, 0xf0, -+ 0x9108, 0x90, -+ 0x9109, 0xd2, -+ 0x910a, 0x0e, -+ 0x910b, 0x02, -+ 0x910c, 0x29, -+ 0x910d, 0x7f, -+ 0xc944, 0x2a, -+ 0xc945, 0x42, -+ 0xc946, 0x81, -+ 0xc947, 0x0e, -+ 0x910e, 0xf0, -+ 0x910f, 0x90, -+ 0x9110, 0xd2, -+ 0x9111, 0x12, -+ 0x9112, 0x02, -+ 0x9113, 0x2a, -+ 0x9114, 0x48, -+ 0xc948, 0x2a, -+ 0xc949, 0x45, -+ 0xc94a, 0x81, -+ 0xc94b, 0x15, -+ 0x9115, 0x90, -+ 0x9116, 0x83, -+ 0x9117, 0xba, -+ 0x9118, 0xe0, -+ 0x9119, 0xff, -+ 0x911a, 0x90, -+ 0x911b, 0xd2, -+ 0x911c, 0x10, -+ 0x911d, 0xe0, -+ 0x911e, 0xe4, -+ 0x911f, 0xef, -+ 0x9120, 0xf0, -+ 0x9121, 0xa3, -+ 0x9122, 0xe0, -+ 0x9123, 0x74, -+ 0x9124, 0xff, -+ 0x9125, 0xf0, -+ 0x9126, 0x90, -+ 0x9127, 0xd2, -+ 0x9128, 0x12, -+ 0x9129, 0x02, -+ 0x912a, 0x2a, -+ 0x912b, 0x48, -+ 0xc900, 0x01, -+ 0x0000, 0x00, -+}; -+ -+static const u16 vs6624_p2[] = { -+ 0x806f, 0x01, -+ 0x058c, 0x01, -+ 0x0000, 0x00, -+}; -+ -+static const u16 vs6624_run_setup[] = { -+ 0x1d18, 0x00, /* Enableconstrainedwhitebalance */ -+ VS6624_PEAK_MIN_OUT_G_MSB, 0x3c, /* Damper PeakGain Output MSB */ -+ VS6624_PEAK_MIN_OUT_G_LSB, 0x66, /* Damper PeakGain Output LSB */ -+ VS6624_CM_LOW_THR_MSB, 0x65, /* Damper Low MSB */ -+ VS6624_CM_LOW_THR_LSB, 0xd1, /* Damper Low LSB */ -+ VS6624_CM_HIGH_THR_MSB, 0x66, /* Damper High MSB */ -+ VS6624_CM_HIGH_THR_LSB, 0x62, /* Damper High LSB */ -+ VS6624_CM_MIN_OUT_MSB, 0x00, /* Damper Min output MSB */ -+ VS6624_CM_MIN_OUT_LSB, 0x00, /* Damper Min output LSB */ -+ VS6624_NORA_DISABLE, 0x00, /* Nora fDisable */ -+ VS6624_NORA_USAGE, 0x04, /* Nora usage */ -+ VS6624_NORA_LOW_THR_MSB, 0x63, /* Damper Low MSB Changed 0x63 to 0x65 */ -+ VS6624_NORA_LOW_THR_LSB, 0xd1, /* Damper Low LSB */ -+ VS6624_NORA_HIGH_THR_MSB, 0x68, /* Damper High MSB */ -+ VS6624_NORA_HIGH_THR_LSB, 0xdd, /* Damper High LSB */ -+ VS6624_NORA_MIN_OUT_MSB, 0x3a, /* Damper Min output MSB */ -+ VS6624_NORA_MIN_OUT_LSB, 0x00, /* Damper Min output LSB */ -+ VS6624_F2B_DISABLE, 0x00, /* Disable */ -+ 0x1d8a, 0x30, /* MAXWeightHigh */ -+ 0x1d91, 0x62, /* fpDamperLowThresholdHigh MSB */ -+ 0x1d92, 0x4a, /* fpDamperLowThresholdHigh LSB */ -+ 0x1d95, 0x65, /* fpDamperHighThresholdHigh MSB */ -+ 0x1d96, 0x0e, /* fpDamperHighThresholdHigh LSB */ -+ 0x1da1, 0x3a, /* fpMinimumDamperOutputLow MSB */ -+ 0x1da2, 0xb8, /* fpMinimumDamperOutputLow LSB */ -+ 0x1e08, 0x06, /* MAXWeightLow */ -+ 0x1e0a, 0x0a, /* MAXWeightHigh */ -+ 0x1601, 0x3a, /* Red A MSB */ -+ 0x1602, 0x14, /* Red A LSB */ -+ 0x1605, 0x3b, /* Blue A MSB */ -+ 0x1606, 0x85, /* BLue A LSB */ -+ 0x1609, 0x3b, /* RED B MSB */ -+ 0x160a, 0x85, /* RED B LSB */ -+ 0x160d, 0x3a, /* Blue B MSB */ -+ 0x160e, 0x14, /* Blue B LSB */ -+ 0x1611, 0x30, /* Max Distance from Locus MSB */ -+ 0x1612, 0x8f, /* Max Distance from Locus MSB */ -+ 0x1614, 0x01, /* Enable constrainer */ -+ 0x0000, 0x00, -+}; -+ -+static const u16 vs6624_default[] = { -+ VS6624_CONTRAST0, 0x84, -+ VS6624_SATURATION0, 0x75, -+ VS6624_GAMMA0, 0x11, -+ VS6624_CONTRAST1, 0x84, -+ VS6624_SATURATION1, 0x75, -+ VS6624_GAMMA1, 0x11, -+ VS6624_MAN_RG, 0x80, -+ VS6624_MAN_GG, 0x80, -+ VS6624_MAN_BG, 0x80, -+ VS6624_WB_MODE, 0x1, -+ VS6624_EXPO_COMPENSATION, 0xfe, -+ VS6624_EXPO_METER, 0x0, -+ VS6624_LIGHT_FREQ, 0x64, -+ VS6624_PEAK_GAIN, 0xe, -+ VS6624_PEAK_LOW_THR, 0x28, -+ VS6624_HMIRROR0, 0x0, -+ VS6624_VFLIP0, 0x0, -+ VS6624_ZOOM_HSTEP0_MSB, 0x0, -+ VS6624_ZOOM_HSTEP0_LSB, 0x1, -+ VS6624_ZOOM_VSTEP0_MSB, 0x0, -+ VS6624_ZOOM_VSTEP0_LSB, 0x1, -+ VS6624_PAN_HSTEP0_MSB, 0x0, -+ VS6624_PAN_HSTEP0_LSB, 0xf, -+ VS6624_PAN_VSTEP0_MSB, 0x0, -+ VS6624_PAN_VSTEP0_LSB, 0xf, -+ VS6624_SENSOR_MODE, 0x1, -+ VS6624_SYNC_CODE_SETUP, 0x21, -+ VS6624_DISABLE_FR_DAMPER, 0x0, -+ VS6624_FR_DEN, 0x1, -+ VS6624_FR_NUM_LSB, 0xf, -+ VS6624_INIT_PIPE_SETUP, 0x0, -+ VS6624_IMG_FMT0, 0x0, -+ VS6624_YUV_SETUP, 0x1, -+ VS6624_IMAGE_SIZE0, 0x2, -+ 0x0000, 0x00, -+}; -+ -+static inline struct vs6624 *to_vs6624(struct v4l2_subdev *sd) -+{ -+ return container_of(sd, struct vs6624, sd); -+} -+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) -+{ -+ return &container_of(ctrl->handler, struct vs6624, hdl)->sd; -+} -+ -+static int vs6624_read(struct v4l2_subdev *sd, u16 index) -+{ -+ struct i2c_client *client = v4l2_get_subdevdata(sd); -+ u8 buf[2]; -+ -+ buf[0] = index >> 8; -+ buf[1] = index; -+ i2c_master_send(client, buf, 2); -+ i2c_master_recv(client, buf, 1); -+ -+ return buf[0]; -+} -+ -+static int vs6624_write(struct v4l2_subdev *sd, u16 index, -+ u8 value) -+{ -+ struct i2c_client *client = v4l2_get_subdevdata(sd); -+ u8 buf[3]; -+ -+ buf[0] = index >> 8; -+ buf[1] = index; -+ buf[2] = value; -+ -+ return i2c_master_send(client, buf, 3); -+} -+ -+static int vs6624_writeregs(struct v4l2_subdev *sd, const u16 *regs) -+{ -+ u16 reg; -+ u8 data; -+ -+ while (*regs != 0x00) { -+ reg = *regs++; -+ data = *regs++; -+ -+ vs6624_write(sd, reg, data); -+ } -+ return 0; -+} -+ -+static int vs6624_s_ctrl(struct v4l2_ctrl *ctrl) -+{ -+ struct v4l2_subdev *sd = to_sd(ctrl); -+ -+ switch (ctrl->id) { -+ case V4L2_CID_CONTRAST: -+ vs6624_write(sd, VS6624_CONTRAST0, ctrl->val); -+ break; -+ case V4L2_CID_SATURATION: -+ vs6624_write(sd, VS6624_SATURATION0, ctrl->val); -+ break; -+ case V4L2_CID_HFLIP: -+ vs6624_write(sd, VS6624_HMIRROR0, ctrl->val); -+ break; -+ case V4L2_CID_VFLIP: -+ vs6624_write(sd, VS6624_VFLIP0, ctrl->val); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int vs6624_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, -+ enum v4l2_mbus_pixelcode *code) -+{ -+ if (index >= ARRAY_SIZE(vs6624_formats)) -+ return -EINVAL; -+ -+ *code = vs6624_formats[index].mbus_code; -+ return 0; -+} -+ -+static int vs6624_try_mbus_fmt(struct v4l2_subdev *sd, -+ struct v4l2_mbus_framefmt *fmt) -+{ -+ int index; -+ -+ for (index = 0; index < ARRAY_SIZE(vs6624_formats); index++) -+ if (vs6624_formats[index].mbus_code == fmt->code) -+ break; -+ if (index >= ARRAY_SIZE(vs6624_formats)) { -+ /* default to first format */ -+ index = 0; -+ fmt->code = vs6624_formats[0].mbus_code; -+ } -+ -+ /* sensor mode is VGA */ -+ if (fmt->width > VGA_WIDTH) -+ fmt->width = VGA_WIDTH; -+ if (fmt->height > VGA_HEIGHT) -+ fmt->height = VGA_HEIGHT; -+ fmt->width = fmt->width & (~3); -+ fmt->height = fmt->height & (~3); -+ fmt->field = V4L2_FIELD_NONE; -+ fmt->colorspace = vs6624_formats[index].colorspace; -+ return 0; -+} -+ -+static int vs6624_s_mbus_fmt(struct v4l2_subdev *sd, -+ struct v4l2_mbus_framefmt *fmt) -+{ -+ struct vs6624 *sensor = to_vs6624(sd); -+ int ret; -+ -+ ret = vs6624_try_mbus_fmt(sd, fmt); -+ if (ret) -+ return ret; -+ -+ /* set image format */ -+ switch (fmt->code) { -+ case V4L2_MBUS_FMT_UYVY8_2X8: -+ vs6624_write(sd, VS6624_IMG_FMT0, 0x0); -+ vs6624_write(sd, VS6624_YUV_SETUP, 0x1); -+ break; -+ case V4L2_MBUS_FMT_YUYV8_2X8: -+ vs6624_write(sd, VS6624_IMG_FMT0, 0x0); -+ vs6624_write(sd, VS6624_YUV_SETUP, 0x3); -+ break; -+ case V4L2_MBUS_FMT_RGB565_2X8_LE: -+ vs6624_write(sd, VS6624_IMG_FMT0, 0x4); -+ vs6624_write(sd, VS6624_RGB_SETUP, 0x0); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* set image size */ -+ if ((fmt->width == VGA_WIDTH) && (fmt->height == VGA_HEIGHT)) -+ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x2); -+ else if ((fmt->width == QVGA_WIDTH) && (fmt->height == QVGA_HEIGHT)) -+ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x4); -+ else if ((fmt->width == QQVGA_WIDTH) && (fmt->height == QQVGA_HEIGHT)) -+ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x6); -+ else if ((fmt->width == CIF_WIDTH) && (fmt->height == CIF_HEIGHT)) -+ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x3); -+ else if ((fmt->width == QCIF_WIDTH) && (fmt->height == QCIF_HEIGHT)) -+ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x5); -+ else if ((fmt->width == QQCIF_WIDTH) && (fmt->height == QQCIF_HEIGHT)) -+ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x7); -+ else { -+ vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x8); -+ vs6624_write(sd, VS6624_MAN_HSIZE0_MSB, fmt->width >> 8); -+ vs6624_write(sd, VS6624_MAN_HSIZE0_LSB, fmt->width & 0xFF); -+ vs6624_write(sd, VS6624_MAN_VSIZE0_MSB, fmt->height >> 8); -+ vs6624_write(sd, VS6624_MAN_VSIZE0_LSB, fmt->height & 0xFF); -+ vs6624_write(sd, VS6624_CROP_CTRL0, 0x1); -+ } -+ -+ sensor->fmt = *fmt; -+ -+ return 0; -+} -+ -+static int vs6624_g_mbus_fmt(struct v4l2_subdev *sd, -+ struct v4l2_mbus_framefmt *fmt) -+{ -+ struct vs6624 *sensor = to_vs6624(sd); -+ -+ *fmt = sensor->fmt; -+ return 0; -+} -+ -+static int vs6624_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) -+{ -+ struct vs6624 *sensor = to_vs6624(sd); -+ struct v4l2_captureparm *cp = &parms->parm.capture; -+ -+ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ -+ memset(cp, 0, sizeof(*cp)); -+ cp->capability = V4L2_CAP_TIMEPERFRAME; -+ cp->timeperframe.numerator = sensor->frame_rate.denominator; -+ cp->timeperframe.denominator = sensor->frame_rate.numerator; -+ return 0; -+} -+ -+static int vs6624_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) -+{ -+ struct vs6624 *sensor = to_vs6624(sd); -+ struct v4l2_captureparm *cp = &parms->parm.capture; -+ struct v4l2_fract *tpf = &cp->timeperframe; -+ -+ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ if (cp->extendedmode != 0) -+ return -EINVAL; -+ -+ if (tpf->numerator == 0 || tpf->denominator == 0 -+ || (tpf->denominator > tpf->numerator * MAX_FRAME_RATE)) { -+ /* reset to max frame rate */ -+ tpf->numerator = 1; -+ tpf->denominator = MAX_FRAME_RATE; -+ } -+ sensor->frame_rate.numerator = tpf->denominator; -+ sensor->frame_rate.denominator = tpf->numerator; -+ vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0); -+ vs6624_write(sd, VS6624_FR_NUM_MSB, -+ sensor->frame_rate.numerator >> 8); -+ vs6624_write(sd, VS6624_FR_NUM_LSB, -+ sensor->frame_rate.numerator & 0xFF); -+ vs6624_write(sd, VS6624_FR_DEN, -+ sensor->frame_rate.denominator & 0xFF); -+ return 0; -+} -+ -+static int vs6624_s_stream(struct v4l2_subdev *sd, int enable) -+{ -+ if (enable) -+ vs6624_write(sd, VS6624_USER_CMD, 0x2); -+ else -+ vs6624_write(sd, VS6624_USER_CMD, 0x4); -+ udelay(100); -+ return 0; -+} -+ -+static int vs6624_g_chip_ident(struct v4l2_subdev *sd, -+ struct v4l2_dbg_chip_ident *chip) -+{ -+ int rev; -+ struct i2c_client *client = v4l2_get_subdevdata(sd); -+ -+ rev = (vs6624_read(sd, VS6624_FW_VSN_MAJOR) << 8) -+ | vs6624_read(sd, VS6624_FW_VSN_MINOR); -+ -+ return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_VS6624, rev); -+} -+ -+#ifdef CONFIG_VIDEO_ADV_DEBUG -+static int vs6624_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) -+{ -+ struct i2c_client *client = v4l2_get_subdevdata(sd); -+ -+ if (!v4l2_chip_match_i2c_client(client, ®->match)) -+ return -EINVAL; -+ if (!capable(CAP_SYS_ADMIN)) -+ return -EPERM; -+ reg->val = vs6624_read(sd, reg->reg & 0xffff); -+ reg->size = 1; -+ return 0; -+} -+ -+static int vs6624_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) -+{ -+ struct i2c_client *client = v4l2_get_subdevdata(sd); -+ -+ if (!v4l2_chip_match_i2c_client(client, ®->match)) -+ return -EINVAL; -+ if (!capable(CAP_SYS_ADMIN)) -+ return -EPERM; -+ vs6624_write(sd, reg->reg & 0xffff, reg->val & 0xff); -+ return 0; -+} -+#endif -+ -+static const struct v4l2_ctrl_ops vs6624_ctrl_ops = { -+ .s_ctrl = vs6624_s_ctrl, -+}; -+ -+static const struct v4l2_subdev_core_ops vs6624_core_ops = { -+ .g_chip_ident = vs6624_g_chip_ident, -+#ifdef CONFIG_VIDEO_ADV_DEBUG -+ .g_register = vs6624_g_register, -+ .s_register = vs6624_s_register, -+#endif -+}; -+ -+static const struct v4l2_subdev_video_ops vs6624_video_ops = { -+ .enum_mbus_fmt = vs6624_enum_mbus_fmt, -+ .try_mbus_fmt = vs6624_try_mbus_fmt, -+ .s_mbus_fmt = vs6624_s_mbus_fmt, -+ .g_mbus_fmt = vs6624_g_mbus_fmt, -+ .s_parm = vs6624_s_parm, -+ .g_parm = vs6624_g_parm, -+ .s_stream = vs6624_s_stream, -+}; -+ -+static const struct v4l2_subdev_ops vs6624_ops = { -+ .core = &vs6624_core_ops, -+ .video = &vs6624_video_ops, -+}; -+ -+static int __devinit vs6624_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+{ -+ struct vs6624 *sensor; -+ struct v4l2_subdev *sd; -+ struct v4l2_ctrl_handler *hdl; -+ const unsigned *ce; -+ int ret; -+ -+ /* Check if the adapter supports the needed features */ -+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) -+ return -EIO; -+ -+ ce = client->dev.platform_data; -+ if (ce == NULL) -+ return -EINVAL; -+ -+ ret = gpio_request(*ce, "VS6624 Chip Enable"); -+ if (ret) { -+ v4l_err(client, "failed to request GPIO %d\n", *ce); -+ return ret; -+ } -+ gpio_direction_output(*ce, 1); -+ /* wait 100ms before any further i2c writes are performed */ -+ mdelay(100); -+ -+ sensor = kzalloc(sizeof(*sensor), GFP_KERNEL); -+ if (sensor == NULL) { -+ gpio_free(*ce); -+ return -ENOMEM; -+ } -+ -+ sd = &sensor->sd; -+ v4l2_i2c_subdev_init(sd, client, &vs6624_ops); -+ -+ vs6624_writeregs(sd, vs6624_p1); -+ vs6624_write(sd, VS6624_MICRO_EN, 0x2); -+ vs6624_write(sd, VS6624_DIO_EN, 0x1); -+ mdelay(10); -+ vs6624_writeregs(sd, vs6624_p2); -+ -+ vs6624_writeregs(sd, vs6624_default); -+ vs6624_write(sd, VS6624_HSYNC_SETUP, 0xF); -+ vs6624_writeregs(sd, vs6624_run_setup); -+ -+ /* set frame rate */ -+ sensor->frame_rate.numerator = MAX_FRAME_RATE; -+ sensor->frame_rate.denominator = 1; -+ vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0); -+ vs6624_write(sd, VS6624_FR_NUM_MSB, -+ sensor->frame_rate.numerator >> 8); -+ vs6624_write(sd, VS6624_FR_NUM_LSB, -+ sensor->frame_rate.numerator & 0xFF); -+ vs6624_write(sd, VS6624_FR_DEN, -+ sensor->frame_rate.denominator & 0xFF); -+ -+ sensor->fmt = vs6624_default_fmt; -+ sensor->ce_pin = *ce; -+ -+ v4l_info(client, "chip found @ 0x%02x (%s)\n", -+ client->addr << 1, client->adapter->name); -+ -+ hdl = &sensor->hdl; -+ v4l2_ctrl_handler_init(hdl, 4); -+ v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, -+ V4L2_CID_CONTRAST, 0, 0xFF, 1, 0x87); -+ v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, -+ V4L2_CID_SATURATION, 0, 0xFF, 1, 0x78); -+ v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, -+ V4L2_CID_HFLIP, 0, 1, 1, 0); -+ v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, -+ V4L2_CID_VFLIP, 0, 1, 1, 0); -+ /* hook the control handler into the driver */ -+ sd->ctrl_handler = hdl; -+ if (hdl->error) { -+ int err = hdl->error; -+ -+ v4l2_ctrl_handler_free(hdl); -+ kfree(sensor); -+ gpio_free(*ce); -+ return err; -+ } -+ -+ /* initialize the hardware to the default control values */ -+ ret = v4l2_ctrl_handler_setup(hdl); -+ if (ret) { -+ v4l2_ctrl_handler_free(hdl); -+ kfree(sensor); -+ gpio_free(*ce); -+ } -+ return ret; -+} -+ -+static int __devexit vs6624_remove(struct i2c_client *client) -+{ -+ struct v4l2_subdev *sd = i2c_get_clientdata(client); -+ struct vs6624 *sensor = to_vs6624(sd); -+ -+ v4l2_device_unregister_subdev(sd); -+ v4l2_ctrl_handler_free(sd->ctrl_handler); -+ gpio_free(sensor->ce_pin); -+ kfree(sensor); -+ return 0; -+} -+ -+static const struct i2c_device_id vs6624_id[] = { -+ {"vs6624", 0}, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(i2c, vs6624_id); -+ -+static struct i2c_driver vs6624_driver = { -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "vs6624", -+ }, -+ .probe = vs6624_probe, -+ .remove = __devexit_p(vs6624_remove), -+ .id_table = vs6624_id, -+}; -+ -+static __init int vs6624_init(void) -+{ -+ return i2c_add_driver(&vs6624_driver); -+} -+ -+static __exit void vs6624_exit(void) -+{ -+ i2c_del_driver(&vs6624_driver); -+} -+ -+module_init(vs6624_init); -+module_exit(vs6624_exit); -+ -+MODULE_DESCRIPTION("VS6624 sensor driver"); -+MODULE_AUTHOR("Scott Jiang "); -+MODULE_LICENSE("GPL v2"); -Index: linux-3.3.x86_64/drivers/media/video/vs6624_regs.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/video/vs6624_regs.h -@@ -0,0 +1,337 @@ -+/* -+ * vs6624 - ST VS6624 CMOS image sensor registers -+ * -+ * Copyright (c) 2011 Analog Devices Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#ifndef _VS6624_REGS_H_ -+#define _VS6624_REGS_H_ -+ -+/* low level control registers */ -+#define VS6624_MICRO_EN 0xC003 /* power enable for all MCU clock */ -+#define VS6624_DIO_EN 0xC044 /* enable digital I/O */ -+/* device parameters */ -+#define VS6624_DEV_ID_MSB 0x0001 /* device id MSB */ -+#define VS6624_DEV_ID_LSB 0x0002 /* device id LSB */ -+#define VS6624_FW_VSN_MAJOR 0x0004 /* firmware version major */ -+#define VS6624_FW_VSN_MINOR 0x0006 /* firmware version minor */ -+#define VS6624_PATCH_VSN_MAJOR 0x0008 /* patch version major */ -+#define VS6624_PATCH_VSN_MINOR 0x000A /* patch version minor */ -+/* host interface manager control */ -+#define VS6624_USER_CMD 0x0180 /* user level control of operating states */ -+/* host interface manager status */ -+#define VS6624_STATE 0x0202 /* current state of the mode manager */ -+/* run mode control */ -+#define VS6624_METER_ON 0x0280 /* if false AE and AWB are disabled */ -+/* mode setup */ -+#define VS6624_ACTIVE_PIPE_SETUP 0x0302 /* select the active bank for non view live mode */ -+#define VS6624_SENSOR_MODE 0x0308 /* select the different sensor mode */ -+/* pipe setup bank0 */ -+#define VS6624_IMAGE_SIZE0 0x0380 /* required output dimension */ -+#define VS6624_MAN_HSIZE0_MSB 0x0383 /* input required manual H size MSB */ -+#define VS6624_MAN_HSIZE0_LSB 0x0384 /* input required manual H size LSB */ -+#define VS6624_MAN_VSIZE0_MSB 0x0387 /* input required manual V size MSB */ -+#define VS6624_MAN_VSIZE0_LSB 0x0388 /* input required manual V size LSB */ -+#define VS6624_ZOOM_HSTEP0_MSB 0x038B /* set the zoom H step MSB */ -+#define VS6624_ZOOM_HSTEP0_LSB 0x038C /* set the zoom H step LSB */ -+#define VS6624_ZOOM_VSTEP0_MSB 0x038F /* set the zoom V step MSB */ -+#define VS6624_ZOOM_VSTEP0_LSB 0x0390 /* set the zoom V step LSB */ -+#define VS6624_ZOOM_CTRL0 0x0392 /* control zoon in, out and stop */ -+#define VS6624_PAN_HSTEP0_MSB 0x0395 /* set the pan H step MSB */ -+#define VS6624_PAN_HSTEP0_LSB 0x0396 /* set the pan H step LSB */ -+#define VS6624_PAN_VSTEP0_MSB 0x0399 /* set the pan V step MSB */ -+#define VS6624_PAN_VSTEP0_LSB 0x039A /* set the pan V step LSB */ -+#define VS6624_PAN_CTRL0 0x039C /* control pan operation */ -+#define VS6624_CROP_CTRL0 0x039E /* select cropping mode */ -+#define VS6624_CROP_HSTART0_MSB 0x03A1 /* set the cropping H start address MSB */ -+#define VS6624_CROP_HSTART0_LSB 0x03A2 /* set the cropping H start address LSB */ -+#define VS6624_CROP_HSIZE0_MSB 0x03A5 /* set the cropping H size MSB */ -+#define VS6624_CROP_HSIZE0_LSB 0x03A6 /* set the cropping H size LSB */ -+#define VS6624_CROP_VSTART0_MSB 0x03A9 /* set the cropping V start address MSB */ -+#define VS6624_CROP_VSTART0_LSB 0x03AA /* set the cropping V start address LSB */ -+#define VS6624_CROP_VSIZE0_MSB 0x03AD /* set the cropping V size MSB */ -+#define VS6624_CROP_VSIZE0_LSB 0x03AE /* set the cropping V size LSB */ -+#define VS6624_IMG_FMT0 0x03B0 /* select required output image format */ -+#define VS6624_BAYER_OUT_ALIGN0 0x03B2 /* set bayer output alignment */ -+#define VS6624_CONTRAST0 0x03B4 /* contrast control for output */ -+#define VS6624_SATURATION0 0x03B6 /* saturation control for output */ -+#define VS6624_GAMMA0 0x03B8 /* gamma settings */ -+#define VS6624_HMIRROR0 0x03BA /* horizontal image orientation flip */ -+#define VS6624_VFLIP0 0x03BC /* vertical image orientation flip */ -+#define VS6624_CHANNEL_ID0 0x03BE /* logical DMA channel number */ -+/* pipe setup bank1 */ -+#define VS6624_IMAGE_SIZE1 0x0400 /* required output dimension */ -+#define VS6624_MAN_HSIZE1_MSB 0x0403 /* input required manual H size MSB */ -+#define VS6624_MAN_HSIZE1_LSB 0x0404 /* input required manual H size LSB */ -+#define VS6624_MAN_VSIZE1_MSB 0x0407 /* input required manual V size MSB */ -+#define VS6624_MAN_VSIZE1_LSB 0x0408 /* input required manual V size LSB */ -+#define VS6624_ZOOM_HSTEP1_MSB 0x040B /* set the zoom H step MSB */ -+#define VS6624_ZOOM_HSTEP1_LSB 0x040C /* set the zoom H step LSB */ -+#define VS6624_ZOOM_VSTEP1_MSB 0x040F /* set the zoom V step MSB */ -+#define VS6624_ZOOM_VSTEP1_LSB 0x0410 /* set the zoom V step LSB */ -+#define VS6624_ZOOM_CTRL1 0x0412 /* control zoon in, out and stop */ -+#define VS6624_PAN_HSTEP1_MSB 0x0415 /* set the pan H step MSB */ -+#define VS6624_PAN_HSTEP1_LSB 0x0416 /* set the pan H step LSB */ -+#define VS6624_PAN_VSTEP1_MSB 0x0419 /* set the pan V step MSB */ -+#define VS6624_PAN_VSTEP1_LSB 0x041A /* set the pan V step LSB */ -+#define VS6624_PAN_CTRL1 0x041C /* control pan operation */ -+#define VS6624_CROP_CTRL1 0x041E /* select cropping mode */ -+#define VS6624_CROP_HSTART1_MSB 0x0421 /* set the cropping H start address MSB */ -+#define VS6624_CROP_HSTART1_LSB 0x0422 /* set the cropping H start address LSB */ -+#define VS6624_CROP_HSIZE1_MSB 0x0425 /* set the cropping H size MSB */ -+#define VS6624_CROP_HSIZE1_LSB 0x0426 /* set the cropping H size LSB */ -+#define VS6624_CROP_VSTART1_MSB 0x0429 /* set the cropping V start address MSB */ -+#define VS6624_CROP_VSTART1_LSB 0x042A /* set the cropping V start address LSB */ -+#define VS6624_CROP_VSIZE1_MSB 0x042D /* set the cropping V size MSB */ -+#define VS6624_CROP_VSIZE1_LSB 0x042E /* set the cropping V size LSB */ -+#define VS6624_IMG_FMT1 0x0430 /* select required output image format */ -+#define VS6624_BAYER_OUT_ALIGN1 0x0432 /* set bayer output alignment */ -+#define VS6624_CONTRAST1 0x0434 /* contrast control for output */ -+#define VS6624_SATURATION1 0x0436 /* saturation control for output */ -+#define VS6624_GAMMA1 0x0438 /* gamma settings */ -+#define VS6624_HMIRROR1 0x043A /* horizontal image orientation flip */ -+#define VS6624_VFLIP1 0x043C /* vertical image orientation flip */ -+#define VS6624_CHANNEL_ID1 0x043E /* logical DMA channel number */ -+/* view live control */ -+#define VS6624_VIEW_LIVE_EN 0x0480 /* enable view live mode */ -+#define VS6624_INIT_PIPE_SETUP 0x0482 /* select initial pipe setup bank */ -+/* view live status */ -+#define VS6624_CUR_PIPE_SETUP 0x0500 /* indicates most recently applied setup bank */ -+/* power management */ -+#define VS6624_TIME_TO_POWER_DOWN 0x0580 /* automatically transition time to stop mode */ -+/* video timing parameter host inputs */ -+#define VS6624_EXT_CLK_FREQ_NUM_MSB 0x0605 /* external clock frequency numerator MSB */ -+#define VS6624_EXT_CLK_FREQ_NUM_LSB 0x0606 /* external clock frequency numerator LSB */ -+#define VS6624_EXT_CLK_FREQ_DEN 0x0608 /* external clock frequency denominator */ -+/* video timing control */ -+#define VS6624_SYS_CLK_MODE 0x0880 /* decides system clock frequency */ -+/* frame dimension parameter host inputs */ -+#define VS6624_LIGHT_FREQ 0x0C80 /* AC frequency used for flicker free time */ -+#define VS6624_FLICKER_COMPAT 0x0C82 /* flicker compatible frame length */ -+/* static frame rate control */ -+#define VS6624_FR_NUM_MSB 0x0D81 /* desired frame rate numerator MSB */ -+#define VS6624_FR_NUM_LSB 0x0D82 /* desired frame rate numerator LSB */ -+#define VS6624_FR_DEN 0x0D84 /* desired frame rate denominator */ -+/* automatic frame rate control */ -+#define VS6624_DISABLE_FR_DAMPER 0x0E80 /* defines frame rate mode */ -+#define VS6624_MIN_DAMPER_OUT_MSB 0x0E8C /* minimum frame rate MSB */ -+#define VS6624_MIN_DAMPER_OUT_LSB 0x0E8A /* minimum frame rate LSB */ -+/* exposure controls */ -+#define VS6624_EXPO_MODE 0x1180 /* exposure mode */ -+#define VS6624_EXPO_METER 0x1182 /* weights to be associated with the zones */ -+#define VS6624_EXPO_TIME_NUM 0x1184 /* exposure time numerator */ -+#define VS6624_EXPO_TIME_DEN 0x1186 /* exposure time denominator */ -+#define VS6624_EXPO_TIME_MSB 0x1189 /* exposure time for the Manual Mode MSB */ -+#define VS6624_EXPO_TIME_LSB 0x118A /* exposure time for the Manual Mode LSB */ -+#define VS6624_EXPO_COMPENSATION 0x1190 /* exposure compensation */ -+#define VS6624_DIRECT_COARSE_MSB 0x1195 /* coarse integration lines for Direct Mode MSB */ -+#define VS6624_DIRECT_COARSE_LSB 0x1196 /* coarse integration lines for Direct Mode LSB */ -+#define VS6624_DIRECT_FINE_MSB 0x1199 /* fine integration pixels for Direct Mode MSB */ -+#define VS6624_DIRECT_FINE_LSB 0x119A /* fine integration pixels for Direct Mode LSB */ -+#define VS6624_DIRECT_ANAL_GAIN_MSB 0x119D /* analog gain for Direct Mode MSB */ -+#define VS6624_DIRECT_ANAL_GAIN_LSB 0x119E /* analog gain for Direct Mode LSB */ -+#define VS6624_DIRECT_DIGI_GAIN_MSB 0x11A1 /* digital gain for Direct Mode MSB */ -+#define VS6624_DIRECT_DIGI_GAIN_LSB 0x11A2 /* digital gain for Direct Mode LSB */ -+#define VS6624_FLASH_COARSE_MSB 0x11A5 /* coarse integration lines for Flash Gun Mode MSB */ -+#define VS6624_FLASH_COARSE_LSB 0x11A6 /* coarse integration lines for Flash Gun Mode LSB */ -+#define VS6624_FLASH_FINE_MSB 0x11A9 /* fine integration pixels for Flash Gun Mode MSB */ -+#define VS6624_FLASH_FINE_LSB 0x11AA /* fine integration pixels for Flash Gun Mode LSB */ -+#define VS6624_FLASH_ANAL_GAIN_MSB 0x11AD /* analog gain for Flash Gun Mode MSB */ -+#define VS6624_FLASH_ANAL_GAIN_LSB 0x11AE /* analog gain for Flash Gun Mode LSB */ -+#define VS6624_FLASH_DIGI_GAIN_MSB 0x11B1 /* digital gain for Flash Gun Mode MSB */ -+#define VS6624_FLASH_DIGI_GAIN_LSB 0x11B2 /* digital gain for Flash Gun Mode LSB */ -+#define VS6624_FREEZE_AE 0x11B4 /* freeze auto exposure */ -+#define VS6624_MAX_INT_TIME_MSB 0x11B7 /* user maximum integration time MSB */ -+#define VS6624_MAX_INT_TIME_LSB 0x11B8 /* user maximum integration time LSB */ -+#define VS6624_FLASH_AG_THR_MSB 0x11BB /* recommend flash gun analog gain threshold MSB */ -+#define VS6624_FLASH_AG_THR_LSB 0x11BC /* recommend flash gun analog gain threshold LSB */ -+#define VS6624_ANTI_FLICKER_MODE 0x11C0 /* anti flicker mode */ -+/* white balance control */ -+#define VS6624_WB_MODE 0x1480 /* set white balance mode */ -+#define VS6624_MAN_RG 0x1482 /* user setting for red channel gain */ -+#define VS6624_MAN_GG 0x1484 /* user setting for green channel gain */ -+#define VS6624_MAN_BG 0x1486 /* user setting for blue channel gain */ -+#define VS6624_FLASH_RG_MSB 0x148B /* red gain for Flash Gun MSB */ -+#define VS6624_FLASH_RG_LSB 0x148C /* red gain for Flash Gun LSB */ -+#define VS6624_FLASH_GG_MSB 0x148F /* green gain for Flash Gun MSB */ -+#define VS6624_FLASH_GG_LSB 0x1490 /* green gain for Flash Gun LSB */ -+#define VS6624_FLASH_BG_MSB 0x1493 /* blue gain for Flash Gun MSB */ -+#define VS6624_FLASH_BG_LSB 0x1494 /* blue gain for Flash Gun LSB */ -+/* sensor setup */ -+#define VS6624_BC_OFFSET 0x1990 /* Black Correction Offset */ -+/* image stability */ -+#define VS6624_STABLE_WB 0x1900 /* white balance stable */ -+#define VS6624_STABLE_EXPO 0x1902 /* exposure stable */ -+#define VS6624_STABLE 0x1906 /* system stable */ -+/* flash control */ -+#define VS6624_FLASH_MODE 0x1A80 /* flash mode */ -+#define VS6624_FLASH_OFF_LINE_MSB 0x1A83 /* off line at flash pulse mode MSB */ -+#define VS6624_FLASH_OFF_LINE_LSB 0x1A84 /* off line at flash pulse mode LSB */ -+/* flash status */ -+#define VS6624_FLASH_RECOM 0x1B00 /* flash gun is recommended */ -+#define VS6624_FLASH_GRAB_COMPLETE 0x1B02 /* flash gun image has been grabbed */ -+/* scythe filter controls */ -+#define VS6624_SCYTHE_FILTER 0x1D80 /* disable scythe defect correction */ -+/* jack filter controls */ -+#define VS6624_JACK_FILTER 0x1E00 /* disable jack defect correction */ -+/* demosaic control */ -+#define VS6624_ANTI_ALIAS_FILTER 0x1E80 /* anti alias filter suppress */ -+/* color matrix dampers */ -+#define VS6624_CM_DISABLE 0x1F00 /* disable color matrix damper */ -+#define VS6624_CM_LOW_THR_MSB 0x1F03 /* low threshold for exposure MSB */ -+#define VS6624_CM_LOW_THR_LSB 0x1F04 /* low threshold for exposure LSB */ -+#define VS6624_CM_HIGH_THR_MSB 0x1F07 /* high threshold for exposure MSB */ -+#define VS6624_CM_HIGH_THR_LSB 0x1F08 /* high threshold for exposure LSB */ -+#define VS6624_CM_MIN_OUT_MSB 0x1F0B /* minimum possible damper output MSB */ -+#define VS6624_CM_MIN_OUT_LSB 0x1F0C /* minimum possible damper output LSB */ -+/* peaking control */ -+#define VS6624_PEAK_GAIN 0x2000 /* controls peaking gain */ -+#define VS6624_PEAK_G_DISABLE 0x2002 /* disable peak gain damping */ -+#define VS6624_PEAK_LOW_THR_G_MSB 0x2005 /* low threshold for exposure for gain MSB */ -+#define VS6624_PEAK_LOW_THR_G_LSB 0x2006 /* low threshold for exposure for gain LSB */ -+#define VS6624_PEAK_HIGH_THR_G_MSB 0x2009 /* high threshold for exposure for gain MSB */ -+#define VS6624_PEAK_HIGH_THR_G_LSB 0x200A /* high threshold for exposure for gain LSB */ -+#define VS6624_PEAK_MIN_OUT_G_MSB 0x200D /* minimum damper output for gain MSB */ -+#define VS6624_PEAK_MIN_OUT_G_LSB 0x200E /* minimum damper output for gain LSB */ -+#define VS6624_PEAK_LOW_THR 0x2010 /* adjust degree of coring */ -+#define VS6624_PEAK_C_DISABLE 0x2012 /* disable coring damping */ -+#define VS6624_PEAK_HIGH_THR 0x2014 /* adjust maximum gain */ -+#define VS6624_PEAK_LOW_THR_C_MSB 0x2017 /* low threshold for exposure for coring MSB */ -+#define VS6624_PEAK_LOW_THR_C_LSB 0x2018 /* low threshold for exposure for coring LSB */ -+#define VS6624_PEAK_HIGH_THR_C_MSB 0x201B /* high threshold for exposure for coring MSB */ -+#define VS6624_PEAK_HIGH_THR_C_LSB 0x201C /* high threshold for exposure for coring LSB */ -+#define VS6624_PEAK_MIN_OUT_C_MSB 0x201F /* minimum damper output for coring MSB */ -+#define VS6624_PEAK_MIN_OUT_C_LSB 0x2020 /* minimum damper output for coring LSB */ -+/* pipe 0 RGB to YUV matrix manual control */ -+#define VS6624_RYM0_MAN_CTRL 0x2180 /* enable manual RGB to YUV matrix */ -+#define VS6624_RYM0_W00_MSB 0x2183 /* row 0 column 0 of YUV matrix MSB */ -+#define VS6624_RYM0_W00_LSB 0x2184 /* row 0 column 0 of YUV matrix LSB */ -+#define VS6624_RYM0_W01_MSB 0x2187 /* row 0 column 1 of YUV matrix MSB */ -+#define VS6624_RYM0_W01_LSB 0x2188 /* row 0 column 1 of YUV matrix LSB */ -+#define VS6624_RYM0_W02_MSB 0x218C /* row 0 column 2 of YUV matrix MSB */ -+#define VS6624_RYM0_W02_LSB 0x218D /* row 0 column 2 of YUV matrix LSB */ -+#define VS6624_RYM0_W10_MSB 0x2190 /* row 1 column 0 of YUV matrix MSB */ -+#define VS6624_RYM0_W10_LSB 0x218F /* row 1 column 0 of YUV matrix LSB */ -+#define VS6624_RYM0_W11_MSB 0x2193 /* row 1 column 1 of YUV matrix MSB */ -+#define VS6624_RYM0_W11_LSB 0x2194 /* row 1 column 1 of YUV matrix LSB */ -+#define VS6624_RYM0_W12_MSB 0x2197 /* row 1 column 2 of YUV matrix MSB */ -+#define VS6624_RYM0_W12_LSB 0x2198 /* row 1 column 2 of YUV matrix LSB */ -+#define VS6624_RYM0_W20_MSB 0x219B /* row 2 column 0 of YUV matrix MSB */ -+#define VS6624_RYM0_W20_LSB 0x219C /* row 2 column 0 of YUV matrix LSB */ -+#define VS6624_RYM0_W21_MSB 0x21A0 /* row 2 column 1 of YUV matrix MSB */ -+#define VS6624_RYM0_W21_LSB 0x219F /* row 2 column 1 of YUV matrix LSB */ -+#define VS6624_RYM0_W22_MSB 0x21A3 /* row 2 column 2 of YUV matrix MSB */ -+#define VS6624_RYM0_W22_LSB 0x21A4 /* row 2 column 2 of YUV matrix LSB */ -+#define VS6624_RYM0_YINY_MSB 0x21A7 /* Y in Y MSB */ -+#define VS6624_RYM0_YINY_LSB 0x21A8 /* Y in Y LSB */ -+#define VS6624_RYM0_YINCB_MSB 0x21AB /* Y in Cb MSB */ -+#define VS6624_RYM0_YINCB_LSB 0x21AC /* Y in Cb LSB */ -+#define VS6624_RYM0_YINCR_MSB 0x21B0 /* Y in Cr MSB */ -+#define VS6624_RYM0_YINCR_LSB 0x21AF /* Y in Cr LSB */ -+/* pipe 1 RGB to YUV matrix manual control */ -+#define VS6624_RYM1_MAN_CTRL 0x2200 /* enable manual RGB to YUV matrix */ -+#define VS6624_RYM1_W00_MSB 0x2203 /* row 0 column 0 of YUV matrix MSB */ -+#define VS6624_RYM1_W00_LSB 0x2204 /* row 0 column 0 of YUV matrix LSB */ -+#define VS6624_RYM1_W01_MSB 0x2207 /* row 0 column 1 of YUV matrix MSB */ -+#define VS6624_RYM1_W01_LSB 0x2208 /* row 0 column 1 of YUV matrix LSB */ -+#define VS6624_RYM1_W02_MSB 0x220C /* row 0 column 2 of YUV matrix MSB */ -+#define VS6624_RYM1_W02_LSB 0x220D /* row 0 column 2 of YUV matrix LSB */ -+#define VS6624_RYM1_W10_MSB 0x2210 /* row 1 column 0 of YUV matrix MSB */ -+#define VS6624_RYM1_W10_LSB 0x220F /* row 1 column 0 of YUV matrix LSB */ -+#define VS6624_RYM1_W11_MSB 0x2213 /* row 1 column 1 of YUV matrix MSB */ -+#define VS6624_RYM1_W11_LSB 0x2214 /* row 1 column 1 of YUV matrix LSB */ -+#define VS6624_RYM1_W12_MSB 0x2217 /* row 1 column 2 of YUV matrix MSB */ -+#define VS6624_RYM1_W12_LSB 0x2218 /* row 1 column 2 of YUV matrix LSB */ -+#define VS6624_RYM1_W20_MSB 0x221B /* row 2 column 0 of YUV matrix MSB */ -+#define VS6624_RYM1_W20_LSB 0x221C /* row 2 column 0 of YUV matrix LSB */ -+#define VS6624_RYM1_W21_MSB 0x2220 /* row 2 column 1 of YUV matrix MSB */ -+#define VS6624_RYM1_W21_LSB 0x221F /* row 2 column 1 of YUV matrix LSB */ -+#define VS6624_RYM1_W22_MSB 0x2223 /* row 2 column 2 of YUV matrix MSB */ -+#define VS6624_RYM1_W22_LSB 0x2224 /* row 2 column 2 of YUV matrix LSB */ -+#define VS6624_RYM1_YINY_MSB 0x2227 /* Y in Y MSB */ -+#define VS6624_RYM1_YINY_LSB 0x2228 /* Y in Y LSB */ -+#define VS6624_RYM1_YINCB_MSB 0x222B /* Y in Cb MSB */ -+#define VS6624_RYM1_YINCB_LSB 0x222C /* Y in Cb LSB */ -+#define VS6624_RYM1_YINCR_MSB 0x2220 /* Y in Cr MSB */ -+#define VS6624_RYM1_YINCR_LSB 0x222F /* Y in Cr LSB */ -+/* pipe 0 gamma manual control */ -+#define VS6624_GAMMA_MAN_CTRL0 0x2280 /* enable manual gamma setup */ -+#define VS6624_GAMMA_PEAK_R0 0x2282 /* peaked red channel gamma value */ -+#define VS6624_GAMMA_PEAK_G0 0x2284 /* peaked green channel gamma value */ -+#define VS6624_GAMMA_PEAK_B0 0x2286 /* peaked blue channel gamma value */ -+#define VS6624_GAMMA_UNPEAK_R0 0x2288 /* unpeaked red channel gamma value */ -+#define VS6624_GAMMA_UNPEAK_G0 0x228A /* unpeaked green channel gamma value */ -+#define VS6624_GAMMA_UNPEAK_B0 0x228C /* unpeaked blue channel gamma value */ -+/* pipe 1 gamma manual control */ -+#define VS6624_GAMMA_MAN_CTRL1 0x2300 /* enable manual gamma setup */ -+#define VS6624_GAMMA_PEAK_R1 0x2302 /* peaked red channel gamma value */ -+#define VS6624_GAMMA_PEAK_G1 0x2304 /* peaked green channel gamma value */ -+#define VS6624_GAMMA_PEAK_B1 0x2306 /* peaked blue channel gamma value */ -+#define VS6624_GAMMA_UNPEAK_R1 0x2308 /* unpeaked red channel gamma value */ -+#define VS6624_GAMMA_UNPEAK_G1 0x230A /* unpeaked green channel gamma value */ -+#define VS6624_GAMMA_UNPEAK_B1 0x230C /* unpeaked blue channel gamma value */ -+/* fade to black */ -+#define VS6624_F2B_DISABLE 0x2480 /* disable fade to black */ -+#define VS6624_F2B_BLACK_VAL_MSB 0x2483 /* black value MSB */ -+#define VS6624_F2B_BLACK_VAL_LSB 0x2484 /* black value LSB */ -+#define VS6624_F2B_LOW_THR_MSB 0x2487 /* low threshold for exposure MSB */ -+#define VS6624_F2B_LOW_THR_LSB 0x2488 /* low threshold for exposure LSB */ -+#define VS6624_F2B_HIGH_THR_MSB 0x248B /* high threshold for exposure MSB */ -+#define VS6624_F2B_HIGH_THR_LSB 0x248C /* high threshold for exposure LSB */ -+#define VS6624_F2B_MIN_OUT_MSB 0x248F /* minimum damper output MSB */ -+#define VS6624_F2B_MIN_OUT_LSB 0x2490 /* minimum damper output LSB */ -+/* output formatter control */ -+#define VS6624_CODE_CK_EN 0x2580 /* code check enable */ -+#define VS6624_BLANK_FMT 0x2582 /* blank format */ -+#define VS6624_SYNC_CODE_SETUP 0x2584 /* sync code setup */ -+#define VS6624_HSYNC_SETUP 0x2586 /* H sync setup */ -+#define VS6624_VSYNC_SETUP 0x2588 /* V sync setup */ -+#define VS6624_PCLK_SETUP 0x258A /* PCLK setup */ -+#define VS6624_PCLK_EN 0x258C /* PCLK enable */ -+#define VS6624_OPF_SP_SETUP 0x258E /* output formatter sp setup */ -+#define VS6624_BLANK_DATA_MSB 0x2590 /* blank data MSB */ -+#define VS6624_BLANK_DATA_LSB 0x2592 /* blank data LSB */ -+#define VS6624_RGB_SETUP 0x2594 /* RGB setup */ -+#define VS6624_YUV_SETUP 0x2596 /* YUV setup */ -+#define VS6624_VSYNC_RIS_COARSE_H 0x2598 /* V sync rising coarse high */ -+#define VS6624_VSYNC_RIS_COARSE_L 0x259A /* V sync rising coarse low */ -+#define VS6624_VSYNC_RIS_FINE_H 0x259C /* V sync rising fine high */ -+#define VS6624_VSYNC_RIS_FINE_L 0x259E /* V sync rising fine low */ -+#define VS6624_VSYNC_FALL_COARSE_H 0x25A0 /* V sync falling coarse high */ -+#define VS6624_VSYNC_FALL_COARSE_L 0x25A2 /* V sync falling coarse low */ -+#define VS6624_VSYNC_FALL_FINE_H 0x25A4 /* V sync falling fine high */ -+#define VS6624_VSYNC_FALL_FINE_L 0x25A6 /* V sync falling fine low */ -+#define VS6624_HSYNC_RIS_H 0x25A8 /* H sync rising high */ -+#define VS6624_HSYNC_RIS_L 0x25AA /* H sync rising low */ -+#define VS6624_HSYNC_FALL_H 0x25AC /* H sync falling high */ -+#define VS6624_HSYNC_FALL_L 0x25AE /* H sync falling low */ -+#define VS6624_OUT_IF 0x25B0 /* output interface */ -+#define VS6624_CCP_EXT_DATA 0x25B2 /* CCP extra data */ -+/* NoRA controls */ -+#define VS6624_NORA_DISABLE 0x2600 /* NoRA control mode */ -+#define VS6624_NORA_USAGE 0x2602 /* usage */ -+#define VS6624_NORA_SPLIT_KN 0x2604 /* split kn */ -+#define VS6624_NORA_SPLIT_NI 0x2606 /* split ni */ -+#define VS6624_NORA_TIGHT_G 0x2608 /* tight green */ -+#define VS6624_NORA_DISABLE_NP 0x260A /* disable noro promoting */ -+#define VS6624_NORA_LOW_THR_MSB 0x260D /* low threshold for exposure MSB */ -+#define VS6624_NORA_LOW_THR_LSB 0x260E /* low threshold for exposure LSB */ -+#define VS6624_NORA_HIGH_THR_MSB 0x2611 /* high threshold for exposure MSB */ -+#define VS6624_NORA_HIGH_THR_LSB 0x2612 /* high threshold for exposure LSB */ -+#define VS6624_NORA_MIN_OUT_MSB 0x2615 /* minimum damper output MSB */ -+#define VS6624_NORA_MIN_OUT_LSB 0x2616 /* minimum damper output LSB */ -+ -+#endif -Index: linux-3.3.x86_64/drivers/media/video/blackfin/Kconfig -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/video/blackfin/Kconfig -@@ -0,0 +1,10 @@ -+config VIDEO_BLACKFIN_CAPTURE -+ tristate "Blackfin Video Capture Driver" -+ depends on VIDEO_V4L2 && BLACKFIN && I2C -+ select VIDEOBUF2_DMA_CONTIG -+ help -+ V4L2 bridge driver for Blackfin video capture device. -+ Choose PPI or EPPI as its interface. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called bfin_video_capture. -Index: linux-3.3.x86_64/drivers/media/video/blackfin/Makefile -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/video/blackfin/Makefile -@@ -0,0 +1,2 @@ -+bfin_video_capture-objs := bfin_capture.o ppi.o -+obj-$(CONFIG_VIDEO_BLACKFIN_CAPTURE) += bfin_video_capture.o -Index: linux-3.3.x86_64/drivers/media/video/blackfin/bfin_capture.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/video/blackfin/bfin_capture.c -@@ -0,0 +1,1059 @@ -+/* -+ * Analog Devices video capture driver -+ * -+ * Copyright (c) 2011 Analog Devices Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+#define CAPTURE_DRV_NAME "bfin_capture" -+#define BCAP_MIN_NUM_BUF 2 -+ -+struct bcap_format { -+ char *desc; -+ u32 pixelformat; -+ enum v4l2_mbus_pixelcode mbus_code; -+ int bpp; /* bits per pixel */ -+}; -+ -+struct bcap_buffer { -+ struct vb2_buffer vb; -+ struct list_head list; -+}; -+ -+struct bcap_device { -+ /* capture device instance */ -+ struct v4l2_device v4l2_dev; -+ /* v4l2 control handler */ -+ struct v4l2_ctrl_handler ctrl_handler; -+ /* device node data */ -+ struct video_device *video_dev; -+ /* sub device instance */ -+ struct v4l2_subdev *sd; -+ /* capture config */ -+ struct bfin_capture_config *cfg; -+ /* ppi interface */ -+ struct ppi_if *ppi; -+ /* current input */ -+ unsigned int cur_input; -+ /* current selected standard */ -+ v4l2_std_id std; -+ /* used to store pixel format */ -+ struct v4l2_pix_format fmt; -+ /* bits per pixel*/ -+ int bpp; -+ /* used to store sensor supported format */ -+ struct bcap_format *sensor_formats; -+ /* number of sensor formats array */ -+ int num_sensor_formats; -+ /* pointing to current video buffer */ -+ struct bcap_buffer *cur_frm; -+ /* pointing to next video buffer */ -+ struct bcap_buffer *next_frm; -+ /* buffer queue used in videobuf2 */ -+ struct vb2_queue buffer_queue; -+ /* allocator-specific contexts for each plane */ -+ struct vb2_alloc_ctx *alloc_ctx; -+ /* queue of filled frames */ -+ struct list_head dma_queue; -+ /* used in videobuf2 callback */ -+ spinlock_t lock; -+ /* used to access capture device */ -+ struct mutex mutex; -+ /* used to wait ppi to complete one transfer */ -+ struct completion comp; -+ /* prepare to stop */ -+ bool stop; -+}; -+ -+struct bcap_fh { -+ struct v4l2_fh fh; -+ /* indicates whether this file handle is doing IO */ -+ bool io_allowed; -+}; -+ -+static const struct bcap_format bcap_formats[] = { -+ { -+ .desc = "YCbCr 4:2:2 Interleaved UYVY", -+ .pixelformat = V4L2_PIX_FMT_UYVY, -+ .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, -+ .bpp = 16, -+ }, -+ { -+ .desc = "YCbCr 4:2:2 Interleaved YUYV", -+ .pixelformat = V4L2_PIX_FMT_YUYV, -+ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, -+ .bpp = 16, -+ }, -+ { -+ .desc = "RGB 565", -+ .pixelformat = V4L2_PIX_FMT_RGB565, -+ .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, -+ .bpp = 16, -+ }, -+ { -+ .desc = "RGB 444", -+ .pixelformat = V4L2_PIX_FMT_RGB444, -+ .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, -+ .bpp = 16, -+ }, -+ -+}; -+#define BCAP_MAX_FMTS ARRAY_SIZE(bcap_formats) -+ -+static irqreturn_t bcap_isr(int irq, void *dev_id); -+ -+static struct bcap_buffer *to_bcap_vb(struct vb2_buffer *vb) -+{ -+ return container_of(vb, struct bcap_buffer, vb); -+} -+ -+static int bcap_init_sensor_formats(struct bcap_device *bcap_dev) -+{ -+ enum v4l2_mbus_pixelcode code; -+ struct bcap_format *sf; -+ unsigned int num_formats = 0; -+ int i, j; -+ -+ while (!v4l2_subdev_call(bcap_dev->sd, video, -+ enum_mbus_fmt, num_formats, &code)) -+ num_formats++; -+ if (!num_formats) -+ return -ENXIO; -+ -+ sf = kzalloc(num_formats * sizeof(*sf), GFP_KERNEL); -+ if (!sf) -+ return -ENOMEM; -+ -+ for (i = 0; i < num_formats; i++) { -+ v4l2_subdev_call(bcap_dev->sd, video, -+ enum_mbus_fmt, i, &code); -+ for (j = 0; j < BCAP_MAX_FMTS; j++) -+ if (code == bcap_formats[j].mbus_code) -+ break; -+ if (j == BCAP_MAX_FMTS) { -+ /* we don't allow this sensor working with our bridge */ -+ kfree(sf); -+ return -EINVAL; -+ } -+ sf[i] = bcap_formats[j]; -+ } -+ bcap_dev->sensor_formats = sf; -+ bcap_dev->num_sensor_formats = num_formats; -+ return 0; -+} -+ -+static void bcap_free_sensor_formats(struct bcap_device *bcap_dev) -+{ -+ bcap_dev->num_sensor_formats = 0; -+ kfree(bcap_dev->sensor_formats); -+ bcap_dev->sensor_formats = NULL; -+} -+ -+static int bcap_open(struct file *file) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ struct video_device *vfd = bcap_dev->video_dev; -+ struct bcap_fh *bcap_fh; -+ -+ if (!bcap_dev->sd) { -+ v4l2_err(&bcap_dev->v4l2_dev, "No sub device registered\n"); -+ return -ENODEV; -+ } -+ -+ bcap_fh = kzalloc(sizeof(*bcap_fh), GFP_KERNEL); -+ if (!bcap_fh) { -+ v4l2_err(&bcap_dev->v4l2_dev, -+ "unable to allocate memory for file handle object\n"); -+ return -ENOMEM; -+ } -+ -+ v4l2_fh_init(&bcap_fh->fh, vfd); -+ -+ /* store pointer to v4l2_fh in private_data member of file */ -+ file->private_data = &bcap_fh->fh; -+ v4l2_fh_add(&bcap_fh->fh); -+ bcap_fh->io_allowed = false; -+ return 0; -+} -+ -+static int bcap_release(struct file *file) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ struct v4l2_fh *fh = file->private_data; -+ struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); -+ -+ /* if this instance is doing IO */ -+ if (bcap_fh->io_allowed) -+ vb2_queue_release(&bcap_dev->buffer_queue); -+ -+ file->private_data = NULL; -+ v4l2_fh_del(&bcap_fh->fh); -+ v4l2_fh_exit(&bcap_fh->fh); -+ kfree(bcap_fh); -+ return 0; -+} -+ -+static int bcap_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ -+ return vb2_mmap(&bcap_dev->buffer_queue, vma); -+} -+ -+#ifndef CONFIG_MMU -+static unsigned long bcap_get_unmapped_area(struct file *file, -+ unsigned long addr, -+ unsigned long len, -+ unsigned long pgoff, -+ unsigned long flags) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ -+ return vb2_get_unmapped_area(&bcap_dev->buffer_queue, -+ addr, -+ len, -+ pgoff, -+ flags); -+} -+#endif -+ -+static unsigned int bcap_poll(struct file *file, poll_table *wait) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ -+ return vb2_poll(&bcap_dev->buffer_queue, file, wait); -+} -+ -+static int bcap_queue_setup(struct vb2_queue *vq, -+ const struct v4l2_format *fmt, -+ unsigned int *nbuffers, unsigned int *nplanes, -+ unsigned int sizes[], void *alloc_ctxs[]) -+{ -+ struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); -+ -+ if (*nbuffers < BCAP_MIN_NUM_BUF) -+ *nbuffers = BCAP_MIN_NUM_BUF; -+ -+ *nplanes = 1; -+ sizes[0] = bcap_dev->fmt.sizeimage; -+ alloc_ctxs[0] = bcap_dev->alloc_ctx; -+ -+ return 0; -+} -+ -+static int bcap_buffer_init(struct vb2_buffer *vb) -+{ -+ struct bcap_buffer *buf = to_bcap_vb(vb); -+ -+ INIT_LIST_HEAD(&buf->list); -+ return 0; -+} -+ -+static int bcap_buffer_prepare(struct vb2_buffer *vb) -+{ -+ struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); -+ struct bcap_buffer *buf = to_bcap_vb(vb); -+ unsigned long size; -+ -+ size = bcap_dev->fmt.sizeimage; -+ if (vb2_plane_size(vb, 0) < size) { -+ v4l2_err(&bcap_dev->v4l2_dev, "buffer too small (%lu < %lu)\n", -+ vb2_plane_size(vb, 0), size); -+ return -EINVAL; -+ } -+ vb2_set_plane_payload(&buf->vb, 0, size); -+ -+ return 0; -+} -+ -+static void bcap_buffer_queue(struct vb2_buffer *vb) -+{ -+ struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); -+ struct bcap_buffer *buf = to_bcap_vb(vb); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&bcap_dev->lock, flags); -+ list_add_tail(&buf->list, &bcap_dev->dma_queue); -+ spin_unlock_irqrestore(&bcap_dev->lock, flags); -+} -+ -+static void bcap_buffer_cleanup(struct vb2_buffer *vb) -+{ -+ struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); -+ struct bcap_buffer *buf = to_bcap_vb(vb); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&bcap_dev->lock, flags); -+ list_del_init(&buf->list); -+ spin_unlock_irqrestore(&bcap_dev->lock, flags); -+} -+ -+static void bcap_lock(struct vb2_queue *vq) -+{ -+ struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); -+ mutex_lock(&bcap_dev->mutex); -+} -+ -+static void bcap_unlock(struct vb2_queue *vq) -+{ -+ struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); -+ mutex_unlock(&bcap_dev->mutex); -+} -+ -+static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count) -+{ -+ struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); -+ struct ppi_if *ppi = bcap_dev->ppi; -+ struct ppi_params params; -+ int ret; -+ -+ /* enable streamon on the sub device */ -+ ret = v4l2_subdev_call(bcap_dev->sd, video, s_stream, 1); -+ if (ret && (ret != -ENOIOCTLCMD)) { -+ v4l2_err(&bcap_dev->v4l2_dev, "stream on failed in subdev\n"); -+ return ret; -+ } -+ -+ /* set ppi params */ -+ params.width = bcap_dev->fmt.width; -+ params.height = bcap_dev->fmt.height; -+ params.bpp = bcap_dev->bpp; -+ params.ppi_control = bcap_dev->cfg->ppi_control; -+ params.int_mask = bcap_dev->cfg->int_mask; -+ params.blank_clocks = bcap_dev->cfg->blank_clocks; -+ ret = ppi->ops->set_params(ppi, ¶ms); -+ if (ret < 0) { -+ v4l2_err(&bcap_dev->v4l2_dev, -+ "Error in setting ppi params\n"); -+ return ret; -+ } -+ -+ /* attach ppi DMA irq handler */ -+ ret = ppi->ops->attach_irq(ppi, bcap_isr); -+ if (ret < 0) { -+ v4l2_err(&bcap_dev->v4l2_dev, -+ "Error in attaching interrupt handler\n"); -+ return ret; -+ } -+ -+ INIT_COMPLETION(bcap_dev->comp); -+ bcap_dev->stop = false; -+ return 0; -+} -+ -+static int bcap_stop_streaming(struct vb2_queue *vq) -+{ -+ struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); -+ struct ppi_if *ppi = bcap_dev->ppi; -+ int ret; -+ -+ if (!vb2_is_streaming(vq)) -+ return 0; -+ -+ bcap_dev->stop = true; -+ wait_for_completion(&bcap_dev->comp); -+ ppi->ops->stop(ppi); -+ ppi->ops->detach_irq(ppi); -+ ret = v4l2_subdev_call(bcap_dev->sd, video, s_stream, 0); -+ if (ret && (ret != -ENOIOCTLCMD)) -+ v4l2_err(&bcap_dev->v4l2_dev, -+ "stream off failed in subdev\n"); -+ -+ /* release all active buffers */ -+ while (!list_empty(&bcap_dev->dma_queue)) { -+ bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, -+ struct bcap_buffer, list); -+ list_del(&bcap_dev->next_frm->list); -+ vb2_buffer_done(&bcap_dev->next_frm->vb, VB2_BUF_STATE_ERROR); -+ } -+ return 0; -+} -+ -+static struct vb2_ops bcap_video_qops = { -+ .queue_setup = bcap_queue_setup, -+ .buf_init = bcap_buffer_init, -+ .buf_prepare = bcap_buffer_prepare, -+ .buf_cleanup = bcap_buffer_cleanup, -+ .buf_queue = bcap_buffer_queue, -+ .wait_prepare = bcap_unlock, -+ .wait_finish = bcap_lock, -+ .start_streaming = bcap_start_streaming, -+ .stop_streaming = bcap_stop_streaming, -+}; -+ -+static int bcap_reqbufs(struct file *file, void *priv, -+ struct v4l2_requestbuffers *req_buf) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ struct vb2_queue *vq = &bcap_dev->buffer_queue; -+ struct v4l2_fh *fh = file->private_data; -+ struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); -+ -+ if (vb2_is_busy(vq)) -+ return -EBUSY; -+ -+ bcap_fh->io_allowed = true; -+ -+ return vb2_reqbufs(vq, req_buf); -+} -+ -+static int bcap_querybuf(struct file *file, void *priv, -+ struct v4l2_buffer *buf) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ -+ return vb2_querybuf(&bcap_dev->buffer_queue, buf); -+} -+ -+static int bcap_qbuf(struct file *file, void *priv, -+ struct v4l2_buffer *buf) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ struct v4l2_fh *fh = file->private_data; -+ struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); -+ -+ if (!bcap_fh->io_allowed) -+ return -EBUSY; -+ -+ return vb2_qbuf(&bcap_dev->buffer_queue, buf); -+} -+ -+static int bcap_dqbuf(struct file *file, void *priv, -+ struct v4l2_buffer *buf) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ struct v4l2_fh *fh = file->private_data; -+ struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); -+ -+ if (!bcap_fh->io_allowed) -+ return -EBUSY; -+ -+ return vb2_dqbuf(&bcap_dev->buffer_queue, -+ buf, file->f_flags & O_NONBLOCK); -+} -+ -+static irqreturn_t bcap_isr(int irq, void *dev_id) -+{ -+ struct ppi_if *ppi = dev_id; -+ struct bcap_device *bcap_dev = ppi->priv; -+ struct timeval timevalue; -+ struct vb2_buffer *vb = &bcap_dev->cur_frm->vb; -+ dma_addr_t addr; -+ -+ spin_lock(&bcap_dev->lock); -+ -+ if (bcap_dev->cur_frm != bcap_dev->next_frm) { -+ do_gettimeofday(&timevalue); -+ vb->v4l2_buf.timestamp = timevalue; -+ vb2_buffer_done(vb, VB2_BUF_STATE_DONE); -+ bcap_dev->cur_frm = bcap_dev->next_frm; -+ } -+ -+ ppi->ops->stop(ppi); -+ -+ if (bcap_dev->stop) { -+ complete(&bcap_dev->comp); -+ } else { -+ if (!list_empty(&bcap_dev->dma_queue)) { -+ bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, -+ struct bcap_buffer, list); -+ list_del(&bcap_dev->next_frm->list); -+ addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->next_frm->vb, 0); -+ ppi->ops->update_addr(ppi, (unsigned long)addr); -+ } -+ ppi->ops->start(ppi); -+ } -+ -+ spin_unlock(&bcap_dev->lock); -+ -+ return IRQ_HANDLED; -+} -+ -+static int bcap_streamon(struct file *file, void *priv, -+ enum v4l2_buf_type buf_type) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ struct bcap_fh *fh = file->private_data; -+ struct ppi_if *ppi = bcap_dev->ppi; -+ dma_addr_t addr; -+ int ret; -+ -+ if (!fh->io_allowed) -+ return -EBUSY; -+ -+ /* call streamon to start streaming in videobuf */ -+ ret = vb2_streamon(&bcap_dev->buffer_queue, buf_type); -+ if (ret) -+ return ret; -+ -+ /* if dma queue is empty, return error */ -+ if (list_empty(&bcap_dev->dma_queue)) { -+ v4l2_err(&bcap_dev->v4l2_dev, "dma queue is empty\n"); -+ ret = -EINVAL; -+ goto err; -+ } -+ -+ /* get the next frame from the dma queue */ -+ bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, -+ struct bcap_buffer, list); -+ bcap_dev->cur_frm = bcap_dev->next_frm; -+ /* remove buffer from the dma queue */ -+ list_del(&bcap_dev->cur_frm->list); -+ addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0); -+ /* update DMA address */ -+ ppi->ops->update_addr(ppi, (unsigned long)addr); -+ /* enable ppi */ -+ ppi->ops->start(ppi); -+ -+ return 0; -+err: -+ vb2_streamoff(&bcap_dev->buffer_queue, buf_type); -+ return ret; -+} -+ -+static int bcap_streamoff(struct file *file, void *priv, -+ enum v4l2_buf_type buf_type) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ struct bcap_fh *fh = file->private_data; -+ -+ if (!fh->io_allowed) -+ return -EBUSY; -+ -+ return vb2_streamoff(&bcap_dev->buffer_queue, buf_type); -+} -+ -+static int bcap_querystd(struct file *file, void *priv, v4l2_std_id *std) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ -+ return v4l2_subdev_call(bcap_dev->sd, video, querystd, std); -+} -+ -+static int bcap_g_std(struct file *file, void *priv, v4l2_std_id *std) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ -+ *std = bcap_dev->std; -+ return 0; -+} -+ -+static int bcap_s_std(struct file *file, void *priv, v4l2_std_id *std) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ int ret; -+ -+ if (vb2_is_busy(&bcap_dev->buffer_queue)) -+ return -EBUSY; -+ -+ ret = v4l2_subdev_call(bcap_dev->sd, core, s_std, *std); -+ if (ret < 0) -+ return ret; -+ -+ bcap_dev->std = *std; -+ return 0; -+} -+ -+static int bcap_enum_input(struct file *file, void *priv, -+ struct v4l2_input *input) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ struct bfin_capture_config *config = bcap_dev->cfg; -+ int ret; -+ u32 status; -+ -+ if (input->index >= config->num_inputs) -+ return -EINVAL; -+ -+ *input = config->inputs[input->index]; -+ /* get input status */ -+ ret = v4l2_subdev_call(bcap_dev->sd, video, g_input_status, &status); -+ if (!ret) -+ input->status = status; -+ return 0; -+} -+ -+static int bcap_g_input(struct file *file, void *priv, unsigned int *index) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ -+ *index = bcap_dev->cur_input; -+ return 0; -+} -+ -+static int bcap_s_input(struct file *file, void *priv, unsigned int index) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ struct bfin_capture_config *config = bcap_dev->cfg; -+ struct bcap_route *route; -+ int ret; -+ -+ if (vb2_is_busy(&bcap_dev->buffer_queue)) -+ return -EBUSY; -+ -+ if (index >= config->num_inputs) -+ return -EINVAL; -+ -+ route = &config->routes[index]; -+ ret = v4l2_subdev_call(bcap_dev->sd, video, s_routing, -+ route->input, route->output, 0); -+ if ((ret < 0) && (ret != -ENOIOCTLCMD)) { -+ v4l2_err(&bcap_dev->v4l2_dev, "Failed to set input\n"); -+ return ret; -+ } -+ bcap_dev->cur_input = index; -+ return 0; -+} -+ -+static int bcap_try_format(struct bcap_device *bcap, -+ struct v4l2_pix_format *pixfmt, -+ enum v4l2_mbus_pixelcode *mbus_code, -+ int *bpp) -+{ -+ struct bcap_format *sf = bcap->sensor_formats; -+ struct bcap_format *fmt = NULL; -+ struct v4l2_mbus_framefmt mbus_fmt; -+ int ret, i; -+ -+ for (i = 0; i < bcap->num_sensor_formats; i++) { -+ fmt = &sf[i]; -+ if (pixfmt->pixelformat == fmt->pixelformat) -+ break; -+ } -+ if (i == bcap->num_sensor_formats) -+ fmt = &sf[0]; -+ -+ if (mbus_code) -+ *mbus_code = fmt->mbus_code; -+ if (bpp) -+ *bpp = fmt->bpp; -+ v4l2_fill_mbus_format(&mbus_fmt, pixfmt, fmt->mbus_code); -+ ret = v4l2_subdev_call(bcap->sd, video, -+ try_mbus_fmt, &mbus_fmt); -+ if (ret < 0) -+ return ret; -+ v4l2_fill_pix_format(pixfmt, &mbus_fmt); -+ pixfmt->bytesperline = pixfmt->width * fmt->bpp / 8; -+ pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; -+ return 0; -+} -+ -+static int bcap_enum_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_fmtdesc *fmt) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ struct bcap_format *sf = bcap_dev->sensor_formats; -+ -+ if (fmt->index >= bcap_dev->num_sensor_formats) -+ return -EINVAL; -+ -+ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ strlcpy(fmt->description, -+ sf[fmt->index].desc, -+ sizeof(fmt->description)); -+ fmt->pixelformat = sf[fmt->index].pixelformat; -+ return 0; -+} -+ -+static int bcap_try_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_format *fmt) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; -+ -+ return bcap_try_format(bcap_dev, pixfmt, NULL, NULL); -+} -+ -+static int bcap_g_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_format *fmt) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ -+ fmt->fmt.pix = bcap_dev->fmt; -+ return 0; -+} -+ -+static int bcap_s_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_format *fmt) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ struct v4l2_mbus_framefmt mbus_fmt; -+ enum v4l2_mbus_pixelcode mbus_code; -+ struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; -+ int ret, bpp; -+ -+ if (vb2_is_busy(&bcap_dev->buffer_queue)) -+ return -EBUSY; -+ -+ /* see if format works */ -+ ret = bcap_try_format(bcap_dev, pixfmt, &mbus_code, &bpp); -+ if (ret < 0) -+ return ret; -+ -+ v4l2_fill_mbus_format(&mbus_fmt, pixfmt, mbus_code); -+ ret = v4l2_subdev_call(bcap_dev->sd, video, s_mbus_fmt, &mbus_fmt); -+ if (ret < 0) -+ return ret; -+ bcap_dev->fmt = *pixfmt; -+ bcap_dev->bpp = bpp; -+ return 0; -+} -+ -+static int bcap_querycap(struct file *file, void *priv, -+ struct v4l2_capability *cap) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ -+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; -+ strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver)); -+ strlcpy(cap->bus_info, "Blackfin Platform", sizeof(cap->bus_info)); -+ strlcpy(cap->card, bcap_dev->cfg->card_name, sizeof(cap->card)); -+ return 0; -+} -+ -+static int bcap_g_parm(struct file *file, void *fh, -+ struct v4l2_streamparm *a) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ -+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ return v4l2_subdev_call(bcap_dev->sd, video, g_parm, a); -+} -+ -+static int bcap_s_parm(struct file *file, void *fh, -+ struct v4l2_streamparm *a) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ -+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ return v4l2_subdev_call(bcap_dev->sd, video, s_parm, a); -+} -+ -+static int bcap_g_chip_ident(struct file *file, void *priv, -+ struct v4l2_dbg_chip_ident *chip) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ -+ chip->ident = V4L2_IDENT_NONE; -+ chip->revision = 0; -+ if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && -+ chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) -+ return -EINVAL; -+ -+ return v4l2_subdev_call(bcap_dev->sd, core, -+ g_chip_ident, chip); -+} -+ -+#ifdef CONFIG_VIDEO_ADV_DEBUG -+static int bcap_dbg_g_register(struct file *file, void *priv, -+ struct v4l2_dbg_register *reg) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ -+ return v4l2_subdev_call(bcap_dev->sd, core, -+ g_register, reg); -+} -+ -+static int bcap_dbg_s_register(struct file *file, void *priv, -+ struct v4l2_dbg_register *reg) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ -+ return v4l2_subdev_call(bcap_dev->sd, core, -+ s_register, reg); -+} -+#endif -+ -+static int bcap_log_status(struct file *file, void *priv) -+{ -+ struct bcap_device *bcap_dev = video_drvdata(file); -+ /* status for sub devices */ -+ v4l2_device_call_all(&bcap_dev->v4l2_dev, 0, core, log_status); -+ return 0; -+} -+ -+static const struct v4l2_ioctl_ops bcap_ioctl_ops = { -+ .vidioc_querycap = bcap_querycap, -+ .vidioc_g_fmt_vid_cap = bcap_g_fmt_vid_cap, -+ .vidioc_enum_fmt_vid_cap = bcap_enum_fmt_vid_cap, -+ .vidioc_s_fmt_vid_cap = bcap_s_fmt_vid_cap, -+ .vidioc_try_fmt_vid_cap = bcap_try_fmt_vid_cap, -+ .vidioc_enum_input = bcap_enum_input, -+ .vidioc_g_input = bcap_g_input, -+ .vidioc_s_input = bcap_s_input, -+ .vidioc_querystd = bcap_querystd, -+ .vidioc_s_std = bcap_s_std, -+ .vidioc_g_std = bcap_g_std, -+ .vidioc_reqbufs = bcap_reqbufs, -+ .vidioc_querybuf = bcap_querybuf, -+ .vidioc_qbuf = bcap_qbuf, -+ .vidioc_dqbuf = bcap_dqbuf, -+ .vidioc_streamon = bcap_streamon, -+ .vidioc_streamoff = bcap_streamoff, -+ .vidioc_g_parm = bcap_g_parm, -+ .vidioc_s_parm = bcap_s_parm, -+ .vidioc_g_chip_ident = bcap_g_chip_ident, -+#ifdef CONFIG_VIDEO_ADV_DEBUG -+ .vidioc_g_register = bcap_dbg_g_register, -+ .vidioc_s_register = bcap_dbg_s_register, -+#endif -+ .vidioc_log_status = bcap_log_status, -+}; -+ -+static struct v4l2_file_operations bcap_fops = { -+ .owner = THIS_MODULE, -+ .open = bcap_open, -+ .release = bcap_release, -+ .unlocked_ioctl = video_ioctl2, -+ .mmap = bcap_mmap, -+#ifndef CONFIG_MMU -+ .get_unmapped_area = bcap_get_unmapped_area, -+#endif -+ .poll = bcap_poll -+}; -+ -+static int __devinit bcap_probe(struct platform_device *pdev) -+{ -+ struct bcap_device *bcap_dev; -+ struct video_device *vfd; -+ struct i2c_adapter *i2c_adap; -+ struct bfin_capture_config *config; -+ struct vb2_queue *q; -+ int ret; -+ -+ config = pdev->dev.platform_data; -+ if (!config) { -+ v4l2_err(pdev->dev.driver, "Unable to get board config\n"); -+ return -ENODEV; -+ } -+ -+ bcap_dev = kzalloc(sizeof(*bcap_dev), GFP_KERNEL); -+ if (!bcap_dev) { -+ v4l2_err(pdev->dev.driver, "Unable to alloc bcap_dev\n"); -+ return -ENOMEM; -+ } -+ -+ bcap_dev->cfg = config; -+ -+ bcap_dev->ppi = ppi_create_instance(config->ppi_info); -+ if (!bcap_dev->ppi) { -+ v4l2_err(pdev->dev.driver, "Unable to create ppi\n"); -+ ret = -ENODEV; -+ goto err_free_dev; -+ } -+ bcap_dev->ppi->priv = bcap_dev; -+ -+ bcap_dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); -+ if (IS_ERR(bcap_dev->alloc_ctx)) { -+ ret = PTR_ERR(bcap_dev->alloc_ctx); -+ goto err_free_ppi; -+ } -+ -+ vfd = video_device_alloc(); -+ if (!vfd) { -+ ret = -ENOMEM; -+ v4l2_err(pdev->dev.driver, "Unable to alloc video device\n"); -+ goto err_cleanup_ctx; -+ } -+ -+ /* initialize field of video device */ -+ vfd->release = video_device_release; -+ vfd->fops = &bcap_fops; -+ vfd->ioctl_ops = &bcap_ioctl_ops; -+ vfd->tvnorms = 0; -+ vfd->v4l2_dev = &bcap_dev->v4l2_dev; -+ set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); -+ strncpy(vfd->name, CAPTURE_DRV_NAME, sizeof(vfd->name)); -+ bcap_dev->video_dev = vfd; -+ -+ ret = v4l2_device_register(&pdev->dev, &bcap_dev->v4l2_dev); -+ if (ret) { -+ v4l2_err(pdev->dev.driver, -+ "Unable to register v4l2 device\n"); -+ goto err_release_vdev; -+ } -+ v4l2_info(&bcap_dev->v4l2_dev, "v4l2 device registered\n"); -+ -+ bcap_dev->v4l2_dev.ctrl_handler = &bcap_dev->ctrl_handler; -+ ret = v4l2_ctrl_handler_init(&bcap_dev->ctrl_handler, 0); -+ if (ret) { -+ v4l2_err(&bcap_dev->v4l2_dev, -+ "Unable to init control handler\n"); -+ goto err_unreg_v4l2; -+ } -+ -+ spin_lock_init(&bcap_dev->lock); -+ /* initialize queue */ -+ q = &bcap_dev->buffer_queue; -+ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ q->io_modes = VB2_MMAP; -+ q->drv_priv = bcap_dev; -+ q->buf_struct_size = sizeof(struct bcap_buffer); -+ q->ops = &bcap_video_qops; -+ q->mem_ops = &vb2_dma_contig_memops; -+ -+ vb2_queue_init(q); -+ -+ mutex_init(&bcap_dev->mutex); -+ init_completion(&bcap_dev->comp); -+ -+ /* init video dma queues */ -+ INIT_LIST_HEAD(&bcap_dev->dma_queue); -+ -+ vfd->lock = &bcap_dev->mutex; -+ -+ /* register video device */ -+ ret = video_register_device(bcap_dev->video_dev, VFL_TYPE_GRABBER, -1); -+ if (ret) { -+ v4l2_err(&bcap_dev->v4l2_dev, -+ "Unable to register video device\n"); -+ goto err_free_handler; -+ } -+ video_set_drvdata(bcap_dev->video_dev, bcap_dev); -+ v4l2_info(&bcap_dev->v4l2_dev, "video device registered as: %s\n", -+ video_device_node_name(vfd)); -+ -+ /* load up the subdevice */ -+ i2c_adap = i2c_get_adapter(config->i2c_adapter_id); -+ if (!i2c_adap) { -+ v4l2_err(&bcap_dev->v4l2_dev, -+ "Unable to find i2c adapter\n"); -+ goto err_unreg_vdev; -+ -+ } -+ bcap_dev->sd = v4l2_i2c_new_subdev_board(&bcap_dev->v4l2_dev, -+ i2c_adap, -+ &config->board_info, -+ NULL); -+ if (bcap_dev->sd) { -+ int i; -+ /* update tvnorms from the sub devices */ -+ for (i = 0; i < config->num_inputs; i++) -+ vfd->tvnorms |= config->inputs[i].std; -+ } else { -+ v4l2_err(&bcap_dev->v4l2_dev, -+ "Unable to register sub device\n"); -+ goto err_unreg_vdev; -+ } -+ -+ v4l2_info(&bcap_dev->v4l2_dev, "v4l2 sub device registered\n"); -+ -+ /* now we can probe the default state */ -+ if (vfd->tvnorms) { -+ v4l2_std_id std; -+ ret = v4l2_subdev_call(bcap_dev->sd, core, g_std, &std); -+ if (ret) { -+ v4l2_err(&bcap_dev->v4l2_dev, -+ "Unable to get std\n"); -+ goto err_unreg_vdev; -+ } -+ bcap_dev->std = std; -+ } -+ ret = bcap_init_sensor_formats(bcap_dev); -+ if (ret) { -+ v4l2_err(&bcap_dev->v4l2_dev, -+ "Unable to create sensor formats table\n"); -+ goto err_unreg_vdev; -+ } -+ return 0; -+err_unreg_vdev: -+ video_unregister_device(bcap_dev->video_dev); -+ bcap_dev->video_dev = NULL; -+err_free_handler: -+ v4l2_ctrl_handler_free(&bcap_dev->ctrl_handler); -+err_unreg_v4l2: -+ v4l2_device_unregister(&bcap_dev->v4l2_dev); -+err_release_vdev: -+ if (bcap_dev->video_dev) -+ video_device_release(bcap_dev->video_dev); -+err_cleanup_ctx: -+ vb2_dma_contig_cleanup_ctx(bcap_dev->alloc_ctx); -+err_free_ppi: -+ ppi_delete_instance(bcap_dev->ppi); -+err_free_dev: -+ kfree(bcap_dev); -+ return ret; -+} -+ -+static int __devexit bcap_remove(struct platform_device *pdev) -+{ -+ struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); -+ struct bcap_device *bcap_dev = container_of(v4l2_dev, -+ struct bcap_device, v4l2_dev); -+ -+ bcap_free_sensor_formats(bcap_dev); -+ video_unregister_device(bcap_dev->video_dev); -+ v4l2_ctrl_handler_free(&bcap_dev->ctrl_handler); -+ v4l2_device_unregister(v4l2_dev); -+ vb2_dma_contig_cleanup_ctx(bcap_dev->alloc_ctx); -+ ppi_delete_instance(bcap_dev->ppi); -+ kfree(bcap_dev); -+ return 0; -+} -+ -+static struct platform_driver bcap_driver = { -+ .driver = { -+ .name = CAPTURE_DRV_NAME, -+ .owner = THIS_MODULE, -+ }, -+ .probe = bcap_probe, -+ .remove = __devexit_p(bcap_remove), -+}; -+ -+static __init int bcap_init(void) -+{ -+ return platform_driver_register(&bcap_driver); -+} -+ -+static __exit void bcap_exit(void) -+{ -+ platform_driver_unregister(&bcap_driver); -+} -+ -+module_init(bcap_init); -+module_exit(bcap_exit); -+ -+MODULE_DESCRIPTION("Analog Devices blackfin video capture driver"); -+MODULE_AUTHOR("Scott Jiang "); -+MODULE_LICENSE("GPL v2"); -Index: linux-3.3.x86_64/drivers/media/video/blackfin/ppi.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/video/blackfin/ppi.c -@@ -0,0 +1,271 @@ -+/* -+ * ppi.c Analog Devices Parallel Peripheral Interface driver -+ * -+ * Copyright (c) 2011 Analog Devices Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+static int ppi_attach_irq(struct ppi_if *ppi, irq_handler_t handler); -+static void ppi_detach_irq(struct ppi_if *ppi); -+static int ppi_start(struct ppi_if *ppi); -+static int ppi_stop(struct ppi_if *ppi); -+static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params); -+static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr); -+ -+static const struct ppi_ops ppi_ops = { -+ .attach_irq = ppi_attach_irq, -+ .detach_irq = ppi_detach_irq, -+ .start = ppi_start, -+ .stop = ppi_stop, -+ .set_params = ppi_set_params, -+ .update_addr = ppi_update_addr, -+}; -+ -+static irqreturn_t ppi_irq_err(int irq, void *dev_id) -+{ -+ struct ppi_if *ppi = dev_id; -+ const struct ppi_info *info = ppi->info; -+ -+ switch (info->type) { -+ case PPI_TYPE_PPI: -+ { -+ struct bfin_ppi_regs *reg = info->base; -+ unsigned short status; -+ -+ /* register on bf561 is cleared when read -+ * others are W1C -+ */ -+ status = bfin_read16(®->status); -+ bfin_write16(®->status, 0xff00); -+ break; -+ } -+ case PPI_TYPE_EPPI: -+ { -+ struct bfin_eppi_regs *reg = info->base; -+ bfin_write16(®->status, 0xffff); -+ break; -+ } -+ default: -+ break; -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static int ppi_attach_irq(struct ppi_if *ppi, irq_handler_t handler) -+{ -+ const struct ppi_info *info = ppi->info; -+ int ret; -+ -+ ret = request_dma(info->dma_ch, "PPI_DMA"); -+ -+ if (ret) { -+ pr_err("Unable to allocate DMA channel for PPI\n"); -+ return ret; -+ } -+ set_dma_callback(info->dma_ch, handler, ppi); -+ -+ if (ppi->err_int) { -+ ret = request_irq(info->irq_err, ppi_irq_err, 0, "PPI ERROR", ppi); -+ if (ret) { -+ pr_err("Unable to allocate IRQ for PPI\n"); -+ free_dma(info->dma_ch); -+ } -+ } -+ return ret; -+} -+ -+static void ppi_detach_irq(struct ppi_if *ppi) -+{ -+ const struct ppi_info *info = ppi->info; -+ -+ if (ppi->err_int) -+ free_irq(info->irq_err, ppi); -+ free_dma(info->dma_ch); -+} -+ -+static int ppi_start(struct ppi_if *ppi) -+{ -+ const struct ppi_info *info = ppi->info; -+ -+ /* enable DMA */ -+ enable_dma(info->dma_ch); -+ -+ /* enable PPI */ -+ ppi->ppi_control |= PORT_EN; -+ switch (info->type) { -+ case PPI_TYPE_PPI: -+ { -+ struct bfin_ppi_regs *reg = info->base; -+ bfin_write16(®->control, ppi->ppi_control); -+ break; -+ } -+ case PPI_TYPE_EPPI: -+ { -+ struct bfin_eppi_regs *reg = info->base; -+ bfin_write32(®->control, ppi->ppi_control); -+ break; -+ } -+ default: -+ return -EINVAL; -+ } -+ -+ SSYNC(); -+ return 0; -+} -+ -+static int ppi_stop(struct ppi_if *ppi) -+{ -+ const struct ppi_info *info = ppi->info; -+ -+ /* disable PPI */ -+ ppi->ppi_control &= ~PORT_EN; -+ switch (info->type) { -+ case PPI_TYPE_PPI: -+ { -+ struct bfin_ppi_regs *reg = info->base; -+ bfin_write16(®->control, ppi->ppi_control); -+ break; -+ } -+ case PPI_TYPE_EPPI: -+ { -+ struct bfin_eppi_regs *reg = info->base; -+ bfin_write32(®->control, ppi->ppi_control); -+ break; -+ } -+ default: -+ return -EINVAL; -+ } -+ -+ /* disable DMA */ -+ clear_dma_irqstat(info->dma_ch); -+ disable_dma(info->dma_ch); -+ -+ SSYNC(); -+ return 0; -+} -+ -+static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) -+{ -+ const struct ppi_info *info = ppi->info; -+ int dma32 = 0; -+ int dma_config, bytes_per_line, lines_per_frame; -+ -+ bytes_per_line = params->width * params->bpp / 8; -+ lines_per_frame = params->height; -+ if (params->int_mask == 0xFFFFFFFF) -+ ppi->err_int = false; -+ else -+ ppi->err_int = true; -+ -+ dma_config = (DMA_FLOW_STOP | WNR | RESTART | DMA2D | DI_EN); -+ ppi->ppi_control = params->ppi_control & ~PORT_EN; -+ switch (info->type) { -+ case PPI_TYPE_PPI: -+ { -+ struct bfin_ppi_regs *reg = info->base; -+ -+ if (params->ppi_control & DMA32) -+ dma32 = 1; -+ -+ bfin_write16(®->control, ppi->ppi_control); -+ bfin_write16(®->count, bytes_per_line - 1); -+ bfin_write16(®->frame, lines_per_frame); -+ break; -+ } -+ case PPI_TYPE_EPPI: -+ { -+ struct bfin_eppi_regs *reg = info->base; -+ -+ if ((params->ppi_control & PACK_EN) -+ || (params->ppi_control & 0x38000) > DLEN_16) -+ dma32 = 1; -+ -+ bfin_write32(®->control, ppi->ppi_control); -+ bfin_write16(®->line, bytes_per_line + params->blank_clocks); -+ bfin_write16(®->frame, lines_per_frame); -+ bfin_write16(®->hdelay, 0); -+ bfin_write16(®->vdelay, 0); -+ bfin_write16(®->hcount, bytes_per_line); -+ bfin_write16(®->vcount, lines_per_frame); -+ break; -+ } -+ default: -+ return -EINVAL; -+ } -+ -+ if (dma32) { -+ dma_config |= WDSIZE_32; -+ set_dma_x_count(info->dma_ch, bytes_per_line >> 2); -+ set_dma_x_modify(info->dma_ch, 4); -+ set_dma_y_modify(info->dma_ch, 4); -+ } else { -+ dma_config |= WDSIZE_16; -+ set_dma_x_count(info->dma_ch, bytes_per_line >> 1); -+ set_dma_x_modify(info->dma_ch, 2); -+ set_dma_y_modify(info->dma_ch, 2); -+ } -+ set_dma_y_count(info->dma_ch, lines_per_frame); -+ set_dma_config(info->dma_ch, dma_config); -+ -+ SSYNC(); -+ return 0; -+} -+ -+static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr) -+{ -+ set_dma_start_addr(ppi->info->dma_ch, addr); -+} -+ -+struct ppi_if *ppi_create_instance(const struct ppi_info *info) -+{ -+ struct ppi_if *ppi; -+ -+ if (!info || !info->pin_req) -+ return NULL; -+ -+ if (peripheral_request_list(info->pin_req, KBUILD_MODNAME)) { -+ pr_err("request peripheral failed\n"); -+ return NULL; -+ } -+ -+ ppi = kzalloc(sizeof(*ppi), GFP_KERNEL); -+ if (!ppi) { -+ peripheral_free_list(info->pin_req); -+ pr_err("unable to allocate memory for ppi handle\n"); -+ return NULL; -+ } -+ ppi->ops = &ppi_ops; -+ ppi->info = info; -+ -+ pr_info("ppi probe success\n"); -+ return ppi; -+} -+ -+void ppi_delete_instance(struct ppi_if *ppi) -+{ -+ peripheral_free_list(ppi->info->pin_req); -+ kfree(ppi); -+} -Index: linux-3.3.x86_64/include/media/blackfin/bfin_capture.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/include/media/blackfin/bfin_capture.h -@@ -0,0 +1,37 @@ -+#ifndef _BFIN_CAPTURE_H_ -+#define _BFIN_CAPTURE_H_ -+ -+#include -+ -+struct v4l2_input; -+struct ppi_info; -+ -+struct bcap_route { -+ u32 input; -+ u32 output; -+}; -+ -+struct bfin_capture_config { -+ /* card name */ -+ char *card_name; -+ /* inputs available at the sub device */ -+ struct v4l2_input *inputs; -+ /* number of inputs supported */ -+ int num_inputs; -+ /* routing information for each input */ -+ struct bcap_route *routes; -+ /* i2c bus adapter no */ -+ int i2c_adapter_id; -+ /* i2c subdevice board info */ -+ struct i2c_board_info board_info; -+ /* ppi board info */ -+ const struct ppi_info *ppi_info; -+ /* ppi control */ -+ unsigned long ppi_control; -+ /* ppi interrupt mask */ -+ u32 int_mask; -+ /* horizontal blanking clocks */ -+ int blank_clocks; -+}; -+ -+#endif -Index: linux-3.3.x86_64/include/media/blackfin/ppi.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/include/media/blackfin/ppi.h -@@ -0,0 +1,74 @@ -+/* -+ * Analog Devices PPI header file -+ * -+ * Copyright (c) 2011 Analog Devices Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#ifndef _PPI_H_ -+#define _PPI_H_ -+ -+#include -+ -+#ifdef EPPI_EN -+#define PORT_EN EPPI_EN -+#define DMA32 0 -+#define PACK_EN PACKEN -+#endif -+ -+struct ppi_if; -+ -+struct ppi_params { -+ int width; -+ int height; -+ int bpp; -+ unsigned long ppi_control; -+ u32 int_mask; -+ int blank_clocks; -+}; -+ -+struct ppi_ops { -+ int (*attach_irq)(struct ppi_if *ppi, irq_handler_t handler); -+ void (*detach_irq)(struct ppi_if *ppi); -+ int (*start)(struct ppi_if *ppi); -+ int (*stop)(struct ppi_if *ppi); -+ int (*set_params)(struct ppi_if *ppi, struct ppi_params *params); -+ void (*update_addr)(struct ppi_if *ppi, unsigned long addr); -+}; -+ -+enum ppi_type { -+ PPI_TYPE_PPI, -+ PPI_TYPE_EPPI, -+}; -+ -+struct ppi_info { -+ enum ppi_type type; -+ int dma_ch; -+ int irq_err; -+ void __iomem *base; -+ const unsigned short *pin_req; -+}; -+ -+struct ppi_if { -+ unsigned long ppi_control; -+ const struct ppi_ops *ops; -+ const struct ppi_info *info; -+ bool err_int; -+ void *priv; -+}; -+ -+struct ppi_if *ppi_create_instance(const struct ppi_info *info); -+void ppi_delete_instance(struct ppi_if *ppi); -+#endif -Index: linux-3.3.x86_64/Documentation/DocBook/media/v4l/selection-api.xml -=================================================================== ---- linux-3.3.x86_64.orig/Documentation/DocBook/media/v4l/selection-api.xml -+++ linux-3.3.x86_64/Documentation/DocBook/media/v4l/selection-api.xml -@@ -52,6 +52,10 @@ cropping and composing rectangles have t - - - -+ -+For complete list of the available selection targets see table -+ -
- -
-@@ -186,7 +190,7 @@ V4L2_SEL_TGT_COMPOSE_ACTIVE - -
- -- Scaling control. -+ Scaling control - - An application can detect if scaling is performed by comparing the width - and the height of rectangles obtained using V4L2_SEL_TGT_CROP_ACTIVE -@@ -200,7 +204,7 @@ the scaling ratios using these values. - -- Comparison with old cropping API. -+ Comparison with old cropping API - - The selection API was introduced to cope with deficiencies of previous - API , that was designed to control simple capture -Index: linux-3.3.x86_64/Documentation/DocBook/media/v4l/vidioc-g-selection.xml -=================================================================== ---- linux-3.3.x86_64.orig/Documentation/DocBook/media/v4l/vidioc-g-selection.xml -+++ linux-3.3.x86_64/Documentation/DocBook/media/v4l/vidioc-g-selection.xml -@@ -58,43 +58,43 @@ - - The ioctls are used to query and configure selection rectangles. - -- To query the cropping (composing) rectangle set --&v4l2-selection;::type to the respective buffer type. Do not --use multiplanar buffers. Use V4L2_BUF_TYPE_VIDEO_CAPTURE -+ To query the cropping (composing) rectangle set &v4l2-selection; -+ type field to the respective buffer type. -+Do not use multiplanar buffers. Use V4L2_BUF_TYPE_VIDEO_CAPTURE - instead of V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE - . Use V4L2_BUF_TYPE_VIDEO_OUTPUT instead of - V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE . The next step is --setting &v4l2-selection;::target to value -- V4L2_SEL_TGT_CROP_ACTIVE ( -+setting the value of &v4l2-selection; target field -+to V4L2_SEL_TGT_CROP_ACTIVE ( - V4L2_SEL_TGT_COMPOSE_ACTIVE ). Please refer to table or for additional --targets. Fields &v4l2-selection;::flags and -- &v4l2-selection;::reserved are ignored and they --must be filled with zeros. The driver fills the rest of the structure or -+targets. The flags and reserved -+ fields of &v4l2-selection; are ignored and they must be filled -+with zeros. The driver fills the rest of the structure or - returns &EINVAL; if incorrect buffer type or target was used. If cropping - (composing) is not supported then the active rectangle is not mutable and it is --always equal to the bounds rectangle. Finally, structure --&v4l2-selection;::r is filled with the current cropping -+always equal to the bounds rectangle. Finally, the &v4l2-rect; -+r rectangle is filled with the current cropping - (composing) coordinates. The coordinates are expressed in driver-dependent - units. The only exception are rectangles for images in raw formats, whose - coordinates are always expressed in pixels. - -- To change the cropping (composing) rectangle set --&v4l2-selection;::type to the respective buffer type. Do not -+ To change the cropping (composing) rectangle set the &v4l2-selection; -+type field to the respective buffer type. Do not - use multiplanar buffers. Use V4L2_BUF_TYPE_VIDEO_CAPTURE - instead of V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE - . Use V4L2_BUF_TYPE_VIDEO_OUTPUT instead of - V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE . The next step is --setting &v4l2-selection;::target to value -- V4L2_SEL_TGT_CROP_ACTIVE ( -+setting the value of &v4l2-selection; target to -+V4L2_SEL_TGT_CROP_ACTIVE ( - V4L2_SEL_TGT_COMPOSE_ACTIVE ). Please refer to table or for additional --targets. Set desired active area into the field --&v4l2-selection;::r . Field --&v4l2-selection;::reserved is ignored and must be filled with --zeros. The driver may adjust the rectangle coordinates. An application may --introduce constraints to control rounding behaviour. Set the field -- &v4l2-selection;::flags to one of values: -+targets. The &v4l2-rect; r rectangle need to be -+set to the desired active area. Field &v4l2-selection; reserved -+ is ignored and must be filled with zeros. The driver may adjust -+coordinates of the requested rectangle. An application may -+introduce constraints to control rounding behaviour. The &v4l2-selection; -+flags field must be set to one of the following: - - - -@@ -129,7 +129,7 @@ and vertical offset and sizes are chosen - - - -- Satisfy constraints from &v4l2-selection;::flags. -+ Satisfy constraints from &v4l2-selection; flags. - - - Adjust width, height, left, and top to hardware limits and alignments. -@@ -145,7 +145,7 @@ and vertical offset and sizes are chosen - - - --On success the field &v4l2-selection;::r contains -+On success the &v4l2-rect; r field contains - the adjusted rectangle. When the parameters are unsuitable the application may - modify the cropping (composing) or image parameters and repeat the cycle until - satisfactory parameters have been negotiated. If constraints flags have to be -@@ -162,38 +162,38 @@ exist no rectangle that sati - - - V4L2_SEL_TGT_CROP_ACTIVE -- 0 -- area that is currently cropped by hardware -+ 0x0000 -+ The area that is currently cropped by hardware. - - - V4L2_SEL_TGT_CROP_DEFAULT -- 1 -- suggested cropping rectangle that covers the "whole picture" -+ 0x0001 -+ Suggested cropping rectangle that covers the "whole picture". - - - V4L2_SEL_TGT_CROP_BOUNDS -- 2 -- limits for the cropping rectangle -+ 0x0002 -+ Limits for the cropping rectangle. - - - V4L2_SEL_TGT_COMPOSE_ACTIVE -- 256 -- area to which data are composed by hardware -+ 0x0100 -+ The area to which data is composed by hardware. - - - V4L2_SEL_TGT_COMPOSE_DEFAULT -- 257 -- suggested composing rectangle that covers the "whole picture" -+ 0x0101 -+ Suggested composing rectangle that covers the "whole picture". - - - V4L2_SEL_TGT_COMPOSE_BOUNDS -- 258 -- limits for the composing rectangle -+ 0x0102 -+ Limits for the composing rectangle. - - - V4L2_SEL_TGT_COMPOSE_PADDED -- 259 -- the active area and all padding pixels that are inserted or modified by the hardware -+ 0x0103 -+ The active area and all padding pixels that are inserted or modified by hardware. - - - -@@ -209,12 +209,14 @@ exist no rectangle that sati - - V4L2_SEL_FLAG_GE - 0x00000001 -- indicate that adjusted rectangle must contain a rectangle from &v4l2-selection;::r -+ Indicates that the adjusted rectangle must contain the original -+ &v4l2-selection; r rectangle. - - - V4L2_SEL_FLAG_LE - 0x00000002 -- indicate that adjusted rectangle must be inside a rectangle from &v4l2-selection;::r -+ Indicates that the adjusted rectangle must be inside the original -+ &v4l2-rect; r rectangle. - - - -@@ -245,27 +247,29 @@ exist no rectangle that sati - - __u32 - type -- Type of the buffer (from &v4l2-buf-type;) -+ Type of the buffer (from &v4l2-buf-type;). - - - __u32 - target -- used to select between cropping and composing rectangles -+ Used to select between cropping -+ and composing rectangles. - - - __u32 - flags -- control over coordinates adjustments, refer to selection flags -+ Flags controlling the selection rectangle adjustments, refer to -+ selection flags. - - - &v4l2-rect; - r -- selection rectangle -+ The selection rectangle. - - - __u32 - reserved[9] -- Reserved fields for future use -+ Reserved fields for future use. - - - -@@ -278,24 +282,24 @@ exist no rectangle that sati - - EINVAL - -- The buffer &v4l2-selection;::type --or &v4l2-selection;::target is not supported, or --the &v4l2-selection;::flags are invalid. -+ Given buffer type type or -+the selection target target is not supported, -+or the flags argument is not valid. - - - - ERANGE - -- it is not possible to adjust a rectangle --&v4l2-selection;::r that satisfies all contraints from -- &v4l2-selection;::flags . -+ It is not possible to adjust &v4l2-rect; -+r rectangle to satisfy all contraints given in the -+flags argument. - - - - EBUSY - -- it is not possible to apply change of selection rectangle at the moment. --Usually because streaming is in progress. -+ It is not possible to apply change of the selection rectangle -+at the moment. Usually because streaming is in progress. - - - -Index: linux-3.3.x86_64/drivers/media/video/w9966.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/w9966.c -+++ linux-3.3.x86_64/drivers/media/video/w9966.c -@@ -129,9 +129,9 @@ MODULE_LICENSE("GPL"); - MODULE_VERSION("0.33.1"); - - #ifdef MODULE --static const char *pardev[] = {[0 ... W9966_MAXCAMS] = ""}; -+static char *pardev[] = {[0 ... W9966_MAXCAMS] = ""}; - #else --static const char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"}; -+static char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"}; - #endif - module_param_array(pardev, charp, NULL, 0); - MODULE_PARM_DESC(pardev, "pardev: where to search for\n" -Index: linux-3.3.x86_64/drivers/media/dvb/pt1/pt1.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/pt1/pt1.c -+++ linux-3.3.x86_64/drivers/media/dvb/pt1/pt1.c -@@ -28,6 +28,7 @@ - #include - #include - #include -+#include - - #include "dvbdev.h" - #include "dvb_demux.h" -@@ -77,6 +78,8 @@ struct pt1 { - struct pt1_adapter *adaps[PT1_NR_ADAPS]; - struct pt1_table *tables; - struct task_struct *kthread; -+ int table_index; -+ int buf_index; - - struct mutex lock; - int power; -@@ -90,12 +93,12 @@ struct pt1_adapter { - u8 *buf; - int upacket_count; - int packet_count; -+ int st_count; - - struct dvb_adapter adap; - struct dvb_demux demux; - int users; - struct dmxdev dmxdev; -- struct dvb_net net; - struct dvb_frontend *fe; - int (*orig_set_voltage)(struct dvb_frontend *fe, - fe_sec_voltage_t voltage); -@@ -119,7 +122,7 @@ static u32 pt1_read_reg(struct pt1 *pt1, - return readl(pt1->regs + reg * 4); - } - --static int pt1_nr_tables = 64; -+static int pt1_nr_tables = 8; - module_param_named(nr_tables, pt1_nr_tables, int, 0); - - static void pt1_increment_table_count(struct pt1 *pt1) -@@ -264,6 +267,7 @@ static int pt1_filter(struct pt1 *pt1, s - struct pt1_adapter *adap; - int offset; - u8 *buf; -+ int sc; - - if (!page->upackets[PT1_NR_UPACKETS - 1]) - return 0; -@@ -280,6 +284,16 @@ static int pt1_filter(struct pt1 *pt1, s - else if (!adap->upacket_count) - continue; - -+ if (upacket >> 24 & 1) -+ printk_ratelimited(KERN_INFO "earth-pt1: device " -+ "buffer overflowing. table[%d] buf[%d]\n", -+ pt1->table_index, pt1->buf_index); -+ sc = upacket >> 26 & 0x7; -+ if (adap->st_count != -1 && sc != ((adap->st_count + 1) & 0x7)) -+ printk_ratelimited(KERN_INFO "earth-pt1: data loss" -+ " in streamID(adapter)[%d]\n", index); -+ adap->st_count = sc; -+ - buf = adap->buf; - offset = adap->packet_count * 188 + adap->upacket_count * 3; - buf[offset] = upacket >> 16; -@@ -303,30 +317,25 @@ static int pt1_filter(struct pt1 *pt1, s - static int pt1_thread(void *data) - { - struct pt1 *pt1; -- int table_index; -- int buf_index; - struct pt1_buffer_page *page; - - pt1 = data; - set_freezable(); - -- table_index = 0; -- buf_index = 0; -- - while (!kthread_should_stop()) { - try_to_freeze(); - -- page = pt1->tables[table_index].bufs[buf_index].page; -+ page = pt1->tables[pt1->table_index].bufs[pt1->buf_index].page; - if (!pt1_filter(pt1, page)) { - schedule_timeout_interruptible((HZ + 999) / 1000); - continue; - } - -- if (++buf_index >= PT1_NR_BUFS) { -+ if (++pt1->buf_index >= PT1_NR_BUFS) { - pt1_increment_table_count(pt1); -- buf_index = 0; -- if (++table_index >= pt1_nr_tables) -- table_index = 0; -+ pt1->buf_index = 0; -+ if (++pt1->table_index >= pt1_nr_tables) -+ pt1->table_index = 0; - } - } - -@@ -477,21 +486,60 @@ err: - return ret; - } - -+static int pt1_start_polling(struct pt1 *pt1) -+{ -+ int ret = 0; -+ -+ mutex_lock(&pt1->lock); -+ if (!pt1->kthread) { -+ pt1->kthread = kthread_run(pt1_thread, pt1, "earth-pt1"); -+ if (IS_ERR(pt1->kthread)) { -+ ret = PTR_ERR(pt1->kthread); -+ pt1->kthread = NULL; -+ } -+ } -+ mutex_unlock(&pt1->lock); -+ return ret; -+} -+ - static int pt1_start_feed(struct dvb_demux_feed *feed) - { - struct pt1_adapter *adap; - adap = container_of(feed->demux, struct pt1_adapter, demux); -- if (!adap->users++) -+ if (!adap->users++) { -+ int ret; -+ -+ ret = pt1_start_polling(adap->pt1); -+ if (ret) -+ return ret; - pt1_set_stream(adap->pt1, adap->index, 1); -+ } - return 0; - } - -+static void pt1_stop_polling(struct pt1 *pt1) -+{ -+ int i, count; -+ -+ mutex_lock(&pt1->lock); -+ for (i = 0, count = 0; i < PT1_NR_ADAPS; i++) -+ count += pt1->adaps[i]->users; -+ -+ if (count == 0 && pt1->kthread) { -+ kthread_stop(pt1->kthread); -+ pt1->kthread = NULL; -+ } -+ mutex_unlock(&pt1->lock); -+} -+ - static int pt1_stop_feed(struct dvb_demux_feed *feed) - { - struct pt1_adapter *adap; - adap = container_of(feed->demux, struct pt1_adapter, demux); -- if (!--adap->users) -+ if (!--adap->users) { - pt1_set_stream(adap->pt1, adap->index, 0); -+ pt1_stop_polling(adap->pt1); -+ } - return 0; - } - -@@ -575,7 +623,6 @@ static int pt1_wakeup(struct dvb_fronten - - static void pt1_free_adapter(struct pt1_adapter *adap) - { -- dvb_net_release(&adap->net); - adap->demux.dmx.close(&adap->demux.dmx); - dvb_dmxdev_release(&adap->dmxdev); - dvb_dmx_release(&adap->demux); -@@ -616,6 +663,7 @@ pt1_alloc_adapter(struct pt1 *pt1) - adap->buf = buf; - adap->upacket_count = 0; - adap->packet_count = 0; -+ adap->st_count = -1; - - dvb_adap = &adap->adap; - dvb_adap->priv = adap; -@@ -644,8 +692,6 @@ pt1_alloc_adapter(struct pt1 *pt1) - if (ret < 0) - goto err_dmx_release; - -- dvb_net_init(dvb_adap, &adap->net, &demux->dmx); -- - return adap; - - err_dmx_release: -@@ -1020,7 +1066,8 @@ static void __devexit pt1_remove(struct - pt1 = pci_get_drvdata(pdev); - regs = pt1->regs; - -- kthread_stop(pt1->kthread); -+ if (pt1->kthread) -+ kthread_stop(pt1->kthread); - pt1_cleanup_tables(pt1); - pt1_cleanup_frontends(pt1); - pt1_disable_ram(pt1); -@@ -1043,7 +1090,6 @@ pt1_probe(struct pci_dev *pdev, const st - void __iomem *regs; - struct pt1 *pt1; - struct i2c_adapter *i2c_adap; -- struct task_struct *kthread; - - ret = pci_enable_device(pdev); - if (ret < 0) -@@ -1139,17 +1185,8 @@ pt1_probe(struct pci_dev *pdev, const st - if (ret < 0) - goto err_pt1_cleanup_frontends; - -- kthread = kthread_run(pt1_thread, pt1, "pt1"); -- if (IS_ERR(kthread)) { -- ret = PTR_ERR(kthread); -- goto err_pt1_cleanup_tables; -- } -- -- pt1->kthread = kthread; - return 0; - --err_pt1_cleanup_tables: -- pt1_cleanup_tables(pt1); - err_pt1_cleanup_frontends: - pt1_cleanup_frontends(pt1); - err_pt1_disable_ram: -Index: linux-3.3.x86_64/drivers/media/video/aptina-pll.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/video/aptina-pll.c -@@ -0,0 +1,174 @@ -+/* -+ * Aptina Sensor PLL Configuration -+ * -+ * Copyright (C) 2012 Laurent Pinchart -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -+ * 02110-1301 USA -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "aptina-pll.h" -+ -+int aptina_pll_calculate(struct device *dev, -+ const struct aptina_pll_limits *limits, -+ struct aptina_pll *pll) -+{ -+ unsigned int mf_min; -+ unsigned int mf_max; -+ unsigned int p1_min; -+ unsigned int p1_max; -+ unsigned int p1; -+ unsigned int div; -+ -+ dev_dbg(dev, "PLL: ext clock %u pix clock %u\n", -+ pll->ext_clock, pll->pix_clock); -+ -+ if (pll->ext_clock < limits->ext_clock_min || -+ pll->ext_clock > limits->ext_clock_max) { -+ dev_err(dev, "pll: invalid external clock frequency.\n"); -+ return -EINVAL; -+ } -+ -+ if (pll->pix_clock == 0 || pll->pix_clock > limits->pix_clock_max) { -+ dev_err(dev, "pll: invalid pixel clock frequency.\n"); -+ return -EINVAL; -+ } -+ -+ /* Compute the multiplier M and combined N*P1 divisor. */ -+ div = gcd(pll->pix_clock, pll->ext_clock); -+ pll->m = pll->pix_clock / div; -+ div = pll->ext_clock / div; -+ -+ /* We now have the smallest M and N*P1 values that will result in the -+ * desired pixel clock frequency, but they might be out of the valid -+ * range. Compute the factor by which we should multiply them given the -+ * following constraints: -+ * -+ * - minimum/maximum multiplier -+ * - minimum/maximum multiplier output clock frequency assuming the -+ * minimum/maximum N value -+ * - minimum/maximum combined N*P1 divisor -+ */ -+ mf_min = DIV_ROUND_UP(limits->m_min, pll->m); -+ mf_min = max(mf_min, limits->out_clock_min / -+ (pll->ext_clock / limits->n_min * pll->m)); -+ mf_min = max(mf_min, limits->n_min * limits->p1_min / div); -+ mf_max = limits->m_max / pll->m; -+ mf_max = min(mf_max, limits->out_clock_max / -+ (pll->ext_clock / limits->n_max * pll->m)); -+ mf_max = min(mf_max, DIV_ROUND_UP(limits->n_max * limits->p1_max, div)); -+ -+ dev_dbg(dev, "pll: mf min %u max %u\n", mf_min, mf_max); -+ if (mf_min > mf_max) { -+ dev_err(dev, "pll: no valid combined N*P1 divisor.\n"); -+ return -EINVAL; -+ } -+ -+ /* -+ * We're looking for the highest acceptable P1 value for which a -+ * multiplier factor MF exists that fulfills the following conditions: -+ * -+ * 1. p1 is in the [p1_min, p1_max] range given by the limits and is -+ * even -+ * 2. mf is in the [mf_min, mf_max] range computed above -+ * 3. div * mf is a multiple of p1, in order to compute -+ * n = div * mf / p1 -+ * m = pll->m * mf -+ * 4. the internal clock frequency, given by ext_clock / n, is in the -+ * [int_clock_min, int_clock_max] range given by the limits -+ * 5. the output clock frequency, given by ext_clock / n * m, is in the -+ * [out_clock_min, out_clock_max] range given by the limits -+ * -+ * The first naive approach is to iterate over all p1 values acceptable -+ * according to (1) and all mf values acceptable according to (2), and -+ * stop at the first combination that fulfills (3), (4) and (5). This -+ * has a O(n^2) complexity. -+ * -+ * Instead of iterating over all mf values in the [mf_min, mf_max] range -+ * we can compute the mf increment between two acceptable values -+ * according to (3) with -+ * -+ * mf_inc = p1 / gcd(div, p1) (6) -+ * -+ * and round the minimum up to the nearest multiple of mf_inc. This will -+ * restrict the number of mf values to be checked. -+ * -+ * Furthermore, conditions (4) and (5) only restrict the range of -+ * acceptable p1 and mf values by modifying the minimum and maximum -+ * limits. (5) can be expressed as -+ * -+ * ext_clock / (div * mf / p1) * m * mf >= out_clock_min -+ * ext_clock / (div * mf / p1) * m * mf <= out_clock_max -+ * -+ * or -+ * -+ * p1 >= out_clock_min * div / (ext_clock * m) (7) -+ * p1 <= out_clock_max * div / (ext_clock * m) -+ * -+ * Similarly, (4) can be expressed as -+ * -+ * mf >= ext_clock * p1 / (int_clock_max * div) (8) -+ * mf <= ext_clock * p1 / (int_clock_min * div) -+ * -+ * We can thus iterate over the restricted p1 range defined by the -+ * combination of (1) and (7), and then compute the restricted mf range -+ * defined by the combination of (2), (6) and (8). If the resulting mf -+ * range is not empty, any value in the mf range is acceptable. We thus -+ * select the mf lwoer bound and the corresponding p1 value. -+ */ -+ if (limits->p1_min == 0) { -+ dev_err(dev, "pll: P1 minimum value must be >0.\n"); -+ return -EINVAL; -+ } -+ -+ p1_min = max(limits->p1_min, DIV_ROUND_UP(limits->out_clock_min * div, -+ pll->ext_clock * pll->m)); -+ p1_max = min(limits->p1_max, limits->out_clock_max * div / -+ (pll->ext_clock * pll->m)); -+ -+ for (p1 = p1_max & ~1; p1 >= p1_min; p1 -= 2) { -+ unsigned int mf_inc = p1 / gcd(div, p1); -+ unsigned int mf_high; -+ unsigned int mf_low; -+ -+ mf_low = max(roundup(mf_min, mf_inc), -+ DIV_ROUND_UP(pll->ext_clock * p1, -+ limits->int_clock_max * div)); -+ mf_high = min(mf_max, pll->ext_clock * p1 / -+ (limits->int_clock_min * div)); -+ -+ if (mf_low > mf_high) -+ continue; -+ -+ pll->n = div * mf_low / p1; -+ pll->m *= mf_low; -+ pll->p1 = p1; -+ dev_dbg(dev, "PLL: N %u M %u P1 %u\n", pll->n, pll->m, pll->p1); -+ return 0; -+ } -+ -+ dev_err(dev, "pll: no valid N and P1 divisors found.\n"); -+ return -EINVAL; -+} -+EXPORT_SYMBOL_GPL(aptina_pll_calculate); -+ -+MODULE_DESCRIPTION("Aptina PLL Helpers"); -+MODULE_AUTHOR("Laurent Pinchart "); -+MODULE_LICENSE("GPL v2"); -Index: linux-3.3.x86_64/drivers/media/video/aptina-pll.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/video/aptina-pll.h -@@ -0,0 +1,56 @@ -+/* -+ * Aptina Sensor PLL Configuration -+ * -+ * Copyright (C) 2012 Laurent Pinchart -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -+ * 02110-1301 USA -+ */ -+ -+#ifndef __APTINA_PLL_H -+#define __APTINA_PLL_H -+ -+struct aptina_pll { -+ unsigned int ext_clock; -+ unsigned int pix_clock; -+ -+ unsigned int n; -+ unsigned int m; -+ unsigned int p1; -+}; -+ -+struct aptina_pll_limits { -+ unsigned int ext_clock_min; -+ unsigned int ext_clock_max; -+ unsigned int int_clock_min; -+ unsigned int int_clock_max; -+ unsigned int out_clock_min; -+ unsigned int out_clock_max; -+ unsigned int pix_clock_max; -+ -+ unsigned int n_min; -+ unsigned int n_max; -+ unsigned int m_min; -+ unsigned int m_max; -+ unsigned int p1_min; -+ unsigned int p1_max; -+}; -+ -+struct device; -+ -+int aptina_pll_calculate(struct device *dev, -+ const struct aptina_pll_limits *limits, -+ struct aptina_pll *pll); -+ -+#endif /* __APTINA_PLL_H */ -Index: linux-3.3.x86_64/drivers/media/video/mt9m032.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/video/mt9m032.c -@@ -0,0 +1,868 @@ -+/* -+ * Driver for MT9M032 CMOS Image Sensor from Micron -+ * -+ * Copyright (C) 2010-2011 Lund Engineering -+ * Contact: Gil Lund -+ * Author: Martin Hostettler -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -+ * 02110-1301 USA -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "aptina-pll.h" -+ -+/* -+ * width and height include active boundary and black parts -+ * -+ * column 0- 15 active boundary -+ * column 16-1455 image -+ * column 1456-1471 active boundary -+ * column 1472-1599 black -+ * -+ * row 0- 51 black -+ * row 53- 59 active boundary -+ * row 60-1139 image -+ * row 1140-1147 active boundary -+ * row 1148-1151 black -+ */ -+ -+#define MT9M032_PIXEL_ARRAY_WIDTH 1600 -+#define MT9M032_PIXEL_ARRAY_HEIGHT 1152 -+ -+#define MT9M032_CHIP_VERSION 0x00 -+#define MT9M032_CHIP_VERSION_VALUE 0x1402 -+#define MT9M032_ROW_START 0x01 -+#define MT9M032_ROW_START_MIN 0 -+#define MT9M032_ROW_START_MAX 1152 -+#define MT9M032_ROW_START_DEF 60 -+#define MT9M032_COLUMN_START 0x02 -+#define MT9M032_COLUMN_START_MIN 0 -+#define MT9M032_COLUMN_START_MAX 1600 -+#define MT9M032_COLUMN_START_DEF 16 -+#define MT9M032_ROW_SIZE 0x03 -+#define MT9M032_ROW_SIZE_MIN 32 -+#define MT9M032_ROW_SIZE_MAX 1152 -+#define MT9M032_ROW_SIZE_DEF 1080 -+#define MT9M032_COLUMN_SIZE 0x04 -+#define MT9M032_COLUMN_SIZE_MIN 32 -+#define MT9M032_COLUMN_SIZE_MAX 1600 -+#define MT9M032_COLUMN_SIZE_DEF 1440 -+#define MT9M032_HBLANK 0x05 -+#define MT9M032_VBLANK 0x06 -+#define MT9M032_VBLANK_MAX 0x7ff -+#define MT9M032_SHUTTER_WIDTH_HIGH 0x08 -+#define MT9M032_SHUTTER_WIDTH_LOW 0x09 -+#define MT9M032_SHUTTER_WIDTH_MIN 1 -+#define MT9M032_SHUTTER_WIDTH_MAX 1048575 -+#define MT9M032_SHUTTER_WIDTH_DEF 1943 -+#define MT9M032_PIX_CLK_CTRL 0x0a -+#define MT9M032_PIX_CLK_CTRL_INV_PIXCLK 0x8000 -+#define MT9M032_RESTART 0x0b -+#define MT9M032_RESET 0x0d -+#define MT9M032_PLL_CONFIG1 0x11 -+#define MT9M032_PLL_CONFIG1_OUTDIV_MASK 0x3f -+#define MT9M032_PLL_CONFIG1_MUL_SHIFT 8 -+#define MT9M032_READ_MODE1 0x1e -+#define MT9M032_READ_MODE2 0x20 -+#define MT9M032_READ_MODE2_VFLIP_SHIFT 15 -+#define MT9M032_READ_MODE2_HFLIP_SHIFT 14 -+#define MT9M032_READ_MODE2_ROW_BLC 0x40 -+#define MT9M032_GAIN_GREEN1 0x2b -+#define MT9M032_GAIN_BLUE 0x2c -+#define MT9M032_GAIN_RED 0x2d -+#define MT9M032_GAIN_GREEN2 0x2e -+ -+/* write only */ -+#define MT9M032_GAIN_ALL 0x35 -+#define MT9M032_GAIN_DIGITAL_MASK 0x7f -+#define MT9M032_GAIN_DIGITAL_SHIFT 8 -+#define MT9M032_GAIN_AMUL_SHIFT 6 -+#define MT9M032_GAIN_ANALOG_MASK 0x3f -+#define MT9M032_FORMATTER1 0x9e -+#define MT9M032_FORMATTER2 0x9f -+#define MT9M032_FORMATTER2_DOUT_EN 0x1000 -+#define MT9M032_FORMATTER2_PIXCLK_EN 0x2000 -+ -+/* -+ * The available MT9M032 datasheet is missing documentation for register 0x10 -+ * MT9P031 seems to be close enough, so use constants from that datasheet for -+ * now. -+ * But keep the name MT9P031 to remind us, that this isn't really confirmed -+ * for this sensor. -+ */ -+#define MT9P031_PLL_CONTROL 0x10 -+#define MT9P031_PLL_CONTROL_PWROFF 0x0050 -+#define MT9P031_PLL_CONTROL_PWRON 0x0051 -+#define MT9P031_PLL_CONTROL_USEPLL 0x0052 -+#define MT9P031_PLL_CONFIG2 0x11 -+#define MT9P031_PLL_CONFIG2_P1_DIV_MASK 0x1f -+ -+struct mt9m032 { -+ struct v4l2_subdev subdev; -+ struct media_pad pad; -+ struct mt9m032_platform_data *pdata; -+ -+ unsigned int pix_clock; -+ -+ struct v4l2_ctrl_handler ctrls; -+ struct { -+ struct v4l2_ctrl *hflip; -+ struct v4l2_ctrl *vflip; -+ }; -+ -+ struct mutex lock; /* Protects streaming, format, interval and crop */ -+ -+ bool streaming; -+ -+ struct v4l2_mbus_framefmt format; -+ struct v4l2_rect crop; -+ struct v4l2_fract frame_interval; -+}; -+ -+#define to_mt9m032(sd) container_of(sd, struct mt9m032, subdev) -+#define to_dev(sensor) \ -+ (&((struct i2c_client *)v4l2_get_subdevdata(&(sensor)->subdev))->dev) -+ -+static int mt9m032_read(struct i2c_client *client, u8 reg) -+{ -+ return i2c_smbus_read_word_swapped(client, reg); -+} -+ -+static int mt9m032_write(struct i2c_client *client, u8 reg, const u16 data) -+{ -+ return i2c_smbus_write_word_swapped(client, reg, data); -+} -+ -+static u32 mt9m032_row_time(struct mt9m032 *sensor, unsigned int width) -+{ -+ unsigned int effective_width; -+ u32 ns; -+ -+ effective_width = width + 716; /* empirical value */ -+ ns = div_u64(1000000000ULL * effective_width, sensor->pix_clock); -+ dev_dbg(to_dev(sensor), "MT9M032 line time: %u ns\n", ns); -+ return ns; -+} -+ -+static int mt9m032_update_timing(struct mt9m032 *sensor, -+ struct v4l2_fract *interval) -+{ -+ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); -+ struct v4l2_rect *crop = &sensor->crop; -+ unsigned int min_vblank; -+ unsigned int vblank; -+ u32 row_time; -+ -+ if (!interval) -+ interval = &sensor->frame_interval; -+ -+ row_time = mt9m032_row_time(sensor, crop->width); -+ -+ vblank = div_u64(1000000000ULL * interval->numerator, -+ (u64)row_time * interval->denominator) -+ - crop->height; -+ -+ if (vblank > MT9M032_VBLANK_MAX) { -+ /* hardware limits to 11 bit values */ -+ interval->denominator = 1000; -+ interval->numerator = -+ div_u64((crop->height + MT9M032_VBLANK_MAX) * -+ (u64)row_time * interval->denominator, -+ 1000000000ULL); -+ vblank = div_u64(1000000000ULL * interval->numerator, -+ (u64)row_time * interval->denominator) -+ - crop->height; -+ } -+ /* enforce minimal 1.6ms blanking time. */ -+ min_vblank = 1600000 / row_time; -+ vblank = clamp_t(unsigned int, vblank, min_vblank, MT9M032_VBLANK_MAX); -+ -+ return mt9m032_write(client, MT9M032_VBLANK, vblank); -+} -+ -+static int mt9m032_update_geom_timing(struct mt9m032 *sensor) -+{ -+ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); -+ int ret; -+ -+ ret = mt9m032_write(client, MT9M032_COLUMN_SIZE, -+ sensor->crop.width - 1); -+ if (!ret) -+ ret = mt9m032_write(client, MT9M032_ROW_SIZE, -+ sensor->crop.height - 1); -+ if (!ret) -+ ret = mt9m032_write(client, MT9M032_COLUMN_START, -+ sensor->crop.left); -+ if (!ret) -+ ret = mt9m032_write(client, MT9M032_ROW_START, -+ sensor->crop.top); -+ if (!ret) -+ ret = mt9m032_update_timing(sensor, NULL); -+ return ret; -+} -+ -+static int update_formatter2(struct mt9m032 *sensor, bool streaming) -+{ -+ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); -+ u16 reg_val = MT9M032_FORMATTER2_DOUT_EN -+ | 0x0070; /* parts reserved! */ -+ /* possibly for changing to 14-bit mode */ -+ -+ if (streaming) -+ reg_val |= MT9M032_FORMATTER2_PIXCLK_EN; /* pixclock enable */ -+ -+ return mt9m032_write(client, MT9M032_FORMATTER2, reg_val); -+} -+ -+static int mt9m032_setup_pll(struct mt9m032 *sensor) -+{ -+ static const struct aptina_pll_limits limits = { -+ .ext_clock_min = 8000000, -+ .ext_clock_max = 16500000, -+ .int_clock_min = 2000000, -+ .int_clock_max = 24000000, -+ .out_clock_min = 322000000, -+ .out_clock_max = 693000000, -+ .pix_clock_max = 99000000, -+ .n_min = 1, -+ .n_max = 64, -+ .m_min = 16, -+ .m_max = 255, -+ .p1_min = 1, -+ .p1_max = 128, -+ }; -+ -+ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); -+ struct mt9m032_platform_data *pdata = sensor->pdata; -+ struct aptina_pll pll; -+ int ret; -+ -+ pll.ext_clock = pdata->ext_clock; -+ pll.pix_clock = pdata->pix_clock; -+ -+ ret = aptina_pll_calculate(&client->dev, &limits, &pll); -+ if (ret < 0) -+ return ret; -+ -+ sensor->pix_clock = pdata->pix_clock; -+ -+ ret = mt9m032_write(client, MT9M032_PLL_CONFIG1, -+ (pll.m << MT9M032_PLL_CONFIG1_MUL_SHIFT) -+ | (pll.p1 - 1)); -+ if (!ret) -+ ret = mt9m032_write(client, MT9P031_PLL_CONFIG2, pll.n - 1); -+ if (!ret) -+ ret = mt9m032_write(client, MT9P031_PLL_CONTROL, -+ MT9P031_PLL_CONTROL_PWRON | -+ MT9P031_PLL_CONTROL_USEPLL); -+ if (!ret) /* more reserved, Continuous, Master Mode */ -+ ret = mt9m032_write(client, MT9M032_READ_MODE1, 0x8006); -+ if (!ret) /* Set 14-bit mode, select 7 divider */ -+ ret = mt9m032_write(client, MT9M032_FORMATTER1, 0x111e); -+ -+ return ret; -+} -+ -+/* ----------------------------------------------------------------------------- -+ * Subdev pad operations -+ */ -+ -+static int mt9m032_enum_mbus_code(struct v4l2_subdev *subdev, -+ struct v4l2_subdev_fh *fh, -+ struct v4l2_subdev_mbus_code_enum *code) -+{ -+ if (code->index != 0) -+ return -EINVAL; -+ -+ code->code = V4L2_MBUS_FMT_Y8_1X8; -+ return 0; -+} -+ -+static int mt9m032_enum_frame_size(struct v4l2_subdev *subdev, -+ struct v4l2_subdev_fh *fh, -+ struct v4l2_subdev_frame_size_enum *fse) -+{ -+ if (fse->index != 0 || fse->code != V4L2_MBUS_FMT_Y8_1X8) -+ return -EINVAL; -+ -+ fse->min_width = MT9M032_COLUMN_SIZE_DEF; -+ fse->max_width = MT9M032_COLUMN_SIZE_DEF; -+ fse->min_height = MT9M032_ROW_SIZE_DEF; -+ fse->max_height = MT9M032_ROW_SIZE_DEF; -+ -+ return 0; -+} -+ -+/** -+ * __mt9m032_get_pad_crop() - get crop rect -+ * @sensor: pointer to the sensor struct -+ * @fh: file handle for getting the try crop rect from -+ * @which: select try or active crop rect -+ * -+ * Returns a pointer the current active or fh relative try crop rect -+ */ -+static struct v4l2_rect * -+__mt9m032_get_pad_crop(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh, -+ enum v4l2_subdev_format_whence which) -+{ -+ switch (which) { -+ case V4L2_SUBDEV_FORMAT_TRY: -+ return v4l2_subdev_get_try_crop(fh, 0); -+ case V4L2_SUBDEV_FORMAT_ACTIVE: -+ return &sensor->crop; -+ default: -+ return NULL; -+ } -+} -+ -+/** -+ * __mt9m032_get_pad_format() - get format -+ * @sensor: pointer to the sensor struct -+ * @fh: file handle for getting the try format from -+ * @which: select try or active format -+ * -+ * Returns a pointer the current active or fh relative try format -+ */ -+static struct v4l2_mbus_framefmt * -+__mt9m032_get_pad_format(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh, -+ enum v4l2_subdev_format_whence which) -+{ -+ switch (which) { -+ case V4L2_SUBDEV_FORMAT_TRY: -+ return v4l2_subdev_get_try_format(fh, 0); -+ case V4L2_SUBDEV_FORMAT_ACTIVE: -+ return &sensor->format; -+ default: -+ return NULL; -+ } -+} -+ -+static int mt9m032_get_pad_format(struct v4l2_subdev *subdev, -+ struct v4l2_subdev_fh *fh, -+ struct v4l2_subdev_format *fmt) -+{ -+ struct mt9m032 *sensor = to_mt9m032(subdev); -+ -+ mutex_lock(&sensor->lock); -+ fmt->format = *__mt9m032_get_pad_format(sensor, fh, fmt->which); -+ mutex_unlock(&sensor->lock); -+ -+ return 0; -+} -+ -+static int mt9m032_set_pad_format(struct v4l2_subdev *subdev, -+ struct v4l2_subdev_fh *fh, -+ struct v4l2_subdev_format *fmt) -+{ -+ struct mt9m032 *sensor = to_mt9m032(subdev); -+ int ret; -+ -+ mutex_lock(&sensor->lock); -+ -+ if (sensor->streaming && fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { -+ ret = -EBUSY; -+ goto done; -+ } -+ -+ /* Scaling is not supported, the format is thus fixed. */ -+ ret = mt9m032_get_pad_format(subdev, fh, fmt); -+ -+done: -+ mutex_lock(&sensor->lock); -+ return ret; -+} -+ -+static int mt9m032_get_pad_crop(struct v4l2_subdev *subdev, -+ struct v4l2_subdev_fh *fh, -+ struct v4l2_subdev_crop *crop) -+{ -+ struct mt9m032 *sensor = to_mt9m032(subdev); -+ -+ mutex_lock(&sensor->lock); -+ crop->rect = *__mt9m032_get_pad_crop(sensor, fh, crop->which); -+ mutex_unlock(&sensor->lock); -+ -+ return 0; -+} -+ -+static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev, -+ struct v4l2_subdev_fh *fh, -+ struct v4l2_subdev_crop *crop) -+{ -+ struct mt9m032 *sensor = to_mt9m032(subdev); -+ struct v4l2_mbus_framefmt *format; -+ struct v4l2_rect *__crop; -+ struct v4l2_rect rect; -+ int ret = 0; -+ -+ mutex_lock(&sensor->lock); -+ -+ if (sensor->streaming && crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) { -+ ret = -EBUSY; -+ goto done; -+ } -+ -+ /* Clamp the crop rectangle boundaries and align them to a multiple of 2 -+ * pixels to ensure a GRBG Bayer pattern. -+ */ -+ rect.left = clamp(ALIGN(crop->rect.left, 2), MT9M032_COLUMN_START_MIN, -+ MT9M032_COLUMN_START_MAX); -+ rect.top = clamp(ALIGN(crop->rect.top, 2), MT9M032_ROW_START_MIN, -+ MT9M032_ROW_START_MAX); -+ rect.width = clamp(ALIGN(crop->rect.width, 2), MT9M032_COLUMN_SIZE_MIN, -+ MT9M032_COLUMN_SIZE_MAX); -+ rect.height = clamp(ALIGN(crop->rect.height, 2), MT9M032_ROW_SIZE_MIN, -+ MT9M032_ROW_SIZE_MAX); -+ -+ rect.width = min(rect.width, MT9M032_PIXEL_ARRAY_WIDTH - rect.left); -+ rect.height = min(rect.height, MT9M032_PIXEL_ARRAY_HEIGHT - rect.top); -+ -+ __crop = __mt9m032_get_pad_crop(sensor, fh, crop->which); -+ -+ if (rect.width != __crop->width || rect.height != __crop->height) { -+ /* Reset the output image size if the crop rectangle size has -+ * been modified. -+ */ -+ format = __mt9m032_get_pad_format(sensor, fh, crop->which); -+ format->width = rect.width; -+ format->height = rect.height; -+ } -+ -+ *__crop = rect; -+ crop->rect = rect; -+ -+ if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) -+ ret = mt9m032_update_geom_timing(sensor); -+ -+done: -+ mutex_unlock(&sensor->lock); -+ return ret; -+} -+ -+static int mt9m032_get_frame_interval(struct v4l2_subdev *subdev, -+ struct v4l2_subdev_frame_interval *fi) -+{ -+ struct mt9m032 *sensor = to_mt9m032(subdev); -+ -+ mutex_lock(&sensor->lock); -+ memset(fi, 0, sizeof(*fi)); -+ fi->interval = sensor->frame_interval; -+ mutex_unlock(&sensor->lock); -+ -+ return 0; -+} -+ -+static int mt9m032_set_frame_interval(struct v4l2_subdev *subdev, -+ struct v4l2_subdev_frame_interval *fi) -+{ -+ struct mt9m032 *sensor = to_mt9m032(subdev); -+ int ret; -+ -+ mutex_lock(&sensor->lock); -+ -+ if (sensor->streaming) { -+ ret = -EBUSY; -+ goto done; -+ } -+ -+ /* Avoid divisions by 0. */ -+ if (fi->interval.denominator == 0) -+ fi->interval.denominator = 1; -+ -+ ret = mt9m032_update_timing(sensor, &fi->interval); -+ if (!ret) -+ sensor->frame_interval = fi->interval; -+ -+done: -+ mutex_unlock(&sensor->lock); -+ return ret; -+} -+ -+static int mt9m032_s_stream(struct v4l2_subdev *subdev, int streaming) -+{ -+ struct mt9m032 *sensor = to_mt9m032(subdev); -+ int ret; -+ -+ mutex_lock(&sensor->lock); -+ ret = update_formatter2(sensor, streaming); -+ if (!ret) -+ sensor->streaming = streaming; -+ mutex_unlock(&sensor->lock); -+ -+ return ret; -+} -+ -+/* ----------------------------------------------------------------------------- -+ * V4L2 subdev core operations -+ */ -+ -+#ifdef CONFIG_VIDEO_ADV_DEBUG -+static int mt9m032_g_register(struct v4l2_subdev *sd, -+ struct v4l2_dbg_register *reg) -+{ -+ struct mt9m032 *sensor = to_mt9m032(sd); -+ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); -+ int val; -+ -+ if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) -+ return -EINVAL; -+ if (reg->match.addr != client->addr) -+ return -ENODEV; -+ -+ val = mt9m032_read(client, reg->reg); -+ if (val < 0) -+ return -EIO; -+ -+ reg->size = 2; -+ reg->val = val; -+ -+ return 0; -+} -+ -+static int mt9m032_s_register(struct v4l2_subdev *sd, -+ struct v4l2_dbg_register *reg) -+{ -+ struct mt9m032 *sensor = to_mt9m032(sd); -+ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); -+ -+ if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) -+ return -EINVAL; -+ -+ if (reg->match.addr != client->addr) -+ return -ENODEV; -+ -+ return mt9m032_write(client, reg->reg, reg->val); -+} -+#endif -+ -+/* ----------------------------------------------------------------------------- -+ * V4L2 subdev control operations -+ */ -+ -+static int update_read_mode2(struct mt9m032 *sensor, bool vflip, bool hflip) -+{ -+ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); -+ int reg_val = (vflip << MT9M032_READ_MODE2_VFLIP_SHIFT) -+ | (hflip << MT9M032_READ_MODE2_HFLIP_SHIFT) -+ | MT9M032_READ_MODE2_ROW_BLC -+ | 0x0007; -+ -+ return mt9m032_write(client, MT9M032_READ_MODE2, reg_val); -+} -+ -+static int mt9m032_set_gain(struct mt9m032 *sensor, s32 val) -+{ -+ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); -+ int digital_gain_val; /* in 1/8th (0..127) */ -+ int analog_mul; /* 0 or 1 */ -+ int analog_gain_val; /* in 1/16th. (0..63) */ -+ u16 reg_val; -+ -+ digital_gain_val = 51; /* from setup example */ -+ -+ if (val < 63) { -+ analog_mul = 0; -+ analog_gain_val = val; -+ } else { -+ analog_mul = 1; -+ analog_gain_val = val / 2; -+ } -+ -+ /* a_gain = (1 + analog_mul) + (analog_gain_val + 1) / 16 */ -+ /* overall_gain = a_gain * (1 + digital_gain_val / 8) */ -+ -+ reg_val = ((digital_gain_val & MT9M032_GAIN_DIGITAL_MASK) -+ << MT9M032_GAIN_DIGITAL_SHIFT) -+ | ((analog_mul & 1) << MT9M032_GAIN_AMUL_SHIFT) -+ | (analog_gain_val & MT9M032_GAIN_ANALOG_MASK); -+ -+ return mt9m032_write(client, MT9M032_GAIN_ALL, reg_val); -+} -+ -+static int mt9m032_try_ctrl(struct v4l2_ctrl *ctrl) -+{ -+ if (ctrl->id == V4L2_CID_GAIN && ctrl->val >= 63) { -+ /* round because of multiplier used for values >= 63 */ -+ ctrl->val &= ~1; -+ } -+ -+ return 0; -+} -+ -+static int mt9m032_set_ctrl(struct v4l2_ctrl *ctrl) -+{ -+ struct mt9m032 *sensor = -+ container_of(ctrl->handler, struct mt9m032, ctrls); -+ struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); -+ int ret; -+ -+ switch (ctrl->id) { -+ case V4L2_CID_GAIN: -+ return mt9m032_set_gain(sensor, ctrl->val); -+ -+ case V4L2_CID_HFLIP: -+ /* case V4L2_CID_VFLIP: -- In the same cluster */ -+ return update_read_mode2(sensor, sensor->vflip->val, -+ sensor->hflip->val); -+ -+ case V4L2_CID_EXPOSURE: -+ ret = mt9m032_write(client, MT9M032_SHUTTER_WIDTH_HIGH, -+ (ctrl->val >> 16) & 0xffff); -+ if (ret < 0) -+ return ret; -+ -+ return mt9m032_write(client, MT9M032_SHUTTER_WIDTH_LOW, -+ ctrl->val & 0xffff); -+ } -+ -+ return 0; -+} -+ -+static struct v4l2_ctrl_ops mt9m032_ctrl_ops = { -+ .s_ctrl = mt9m032_set_ctrl, -+ .try_ctrl = mt9m032_try_ctrl, -+}; -+ -+/* -------------------------------------------------------------------------- */ -+ -+static const struct v4l2_subdev_core_ops mt9m032_core_ops = { -+#ifdef CONFIG_VIDEO_ADV_DEBUG -+ .g_register = mt9m032_g_register, -+ .s_register = mt9m032_s_register, -+#endif -+}; -+ -+static const struct v4l2_subdev_video_ops mt9m032_video_ops = { -+ .s_stream = mt9m032_s_stream, -+ .g_frame_interval = mt9m032_get_frame_interval, -+ .s_frame_interval = mt9m032_set_frame_interval, -+}; -+ -+static const struct v4l2_subdev_pad_ops mt9m032_pad_ops = { -+ .enum_mbus_code = mt9m032_enum_mbus_code, -+ .enum_frame_size = mt9m032_enum_frame_size, -+ .get_fmt = mt9m032_get_pad_format, -+ .set_fmt = mt9m032_set_pad_format, -+ .set_crop = mt9m032_set_pad_crop, -+ .get_crop = mt9m032_get_pad_crop, -+}; -+ -+static const struct v4l2_subdev_ops mt9m032_ops = { -+ .core = &mt9m032_core_ops, -+ .video = &mt9m032_video_ops, -+ .pad = &mt9m032_pad_ops, -+}; -+ -+/* ----------------------------------------------------------------------------- -+ * Driver initialization and probing -+ */ -+ -+static int mt9m032_probe(struct i2c_client *client, -+ const struct i2c_device_id *devid) -+{ -+ struct i2c_adapter *adapter = client->adapter; -+ struct mt9m032 *sensor; -+ int chip_version; -+ int ret; -+ -+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { -+ dev_warn(&client->dev, -+ "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); -+ return -EIO; -+ } -+ -+ if (!client->dev.platform_data) -+ return -ENODEV; -+ -+ sensor = kzalloc(sizeof(*sensor), GFP_KERNEL); -+ if (sensor == NULL) -+ return -ENOMEM; -+ -+ mutex_init(&sensor->lock); -+ -+ sensor->pdata = client->dev.platform_data; -+ -+ v4l2_i2c_subdev_init(&sensor->subdev, client, &mt9m032_ops); -+ sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; -+ -+ chip_version = mt9m032_read(client, MT9M032_CHIP_VERSION); -+ if (chip_version != MT9M032_CHIP_VERSION_VALUE) { -+ dev_err(&client->dev, "MT9M032 not detected, wrong version " -+ "0x%04x\n", chip_version); -+ ret = -ENODEV; -+ goto error_sensor; -+ } -+ -+ dev_info(&client->dev, "MT9M032 detected at address 0x%02x\n", -+ client->addr); -+ -+ sensor->frame_interval.numerator = 1; -+ sensor->frame_interval.denominator = 30; -+ -+ sensor->crop.left = MT9M032_COLUMN_START_DEF; -+ sensor->crop.top = MT9M032_ROW_START_DEF; -+ sensor->crop.width = MT9M032_COLUMN_SIZE_DEF; -+ sensor->crop.height = MT9M032_ROW_SIZE_DEF; -+ -+ sensor->format.width = sensor->crop.width; -+ sensor->format.height = sensor->crop.height; -+ sensor->format.code = V4L2_MBUS_FMT_Y8_1X8; -+ sensor->format.field = V4L2_FIELD_NONE; -+ sensor->format.colorspace = V4L2_COLORSPACE_SRGB; -+ -+ v4l2_ctrl_handler_init(&sensor->ctrls, 4); -+ -+ v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops, -+ V4L2_CID_GAIN, 0, 127, 1, 64); -+ -+ sensor->hflip = v4l2_ctrl_new_std(&sensor->ctrls, -+ &mt9m032_ctrl_ops, -+ V4L2_CID_HFLIP, 0, 1, 1, 0); -+ sensor->vflip = v4l2_ctrl_new_std(&sensor->ctrls, -+ &mt9m032_ctrl_ops, -+ V4L2_CID_VFLIP, 0, 1, 1, 0); -+ -+ v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops, -+ V4L2_CID_EXPOSURE, MT9M032_SHUTTER_WIDTH_MIN, -+ MT9M032_SHUTTER_WIDTH_MAX, 1, -+ MT9M032_SHUTTER_WIDTH_DEF); -+ -+ if (sensor->ctrls.error) { -+ ret = sensor->ctrls.error; -+ dev_err(&client->dev, "control initialization error %d\n", ret); -+ goto error_ctrl; -+ } -+ -+ v4l2_ctrl_cluster(2, &sensor->hflip); -+ -+ sensor->subdev.ctrl_handler = &sensor->ctrls; -+ sensor->pad.flags = MEDIA_PAD_FL_SOURCE; -+ ret = media_entity_init(&sensor->subdev.entity, 1, &sensor->pad, 0); -+ if (ret < 0) -+ goto error_ctrl; -+ -+ ret = mt9m032_write(client, MT9M032_RESET, 1); /* reset on */ -+ if (ret < 0) -+ goto error_entity; -+ mt9m032_write(client, MT9M032_RESET, 0); /* reset off */ -+ if (ret < 0) -+ goto error_entity; -+ -+ ret = mt9m032_setup_pll(sensor); -+ if (ret < 0) -+ goto error_entity; -+ usleep_range(10000, 11000); -+ -+ ret = v4l2_ctrl_handler_setup(&sensor->ctrls); -+ if (ret < 0) -+ goto error_entity; -+ -+ /* SIZE */ -+ ret = mt9m032_update_geom_timing(sensor); -+ if (ret < 0) -+ goto error_entity; -+ -+ ret = mt9m032_write(client, 0x41, 0x0000); /* reserved !!! */ -+ if (ret < 0) -+ goto error_entity; -+ ret = mt9m032_write(client, 0x42, 0x0003); /* reserved !!! */ -+ if (ret < 0) -+ goto error_entity; -+ ret = mt9m032_write(client, 0x43, 0x0003); /* reserved !!! */ -+ if (ret < 0) -+ goto error_entity; -+ ret = mt9m032_write(client, 0x7f, 0x0000); /* reserved !!! */ -+ if (ret < 0) -+ goto error_entity; -+ if (sensor->pdata->invert_pixclock) { -+ ret = mt9m032_write(client, MT9M032_PIX_CLK_CTRL, -+ MT9M032_PIX_CLK_CTRL_INV_PIXCLK); -+ if (ret < 0) -+ goto error_entity; -+ } -+ -+ ret = mt9m032_write(client, MT9M032_RESTART, 1); /* Restart on */ -+ if (ret < 0) -+ goto error_entity; -+ msleep(100); -+ ret = mt9m032_write(client, MT9M032_RESTART, 0); /* Restart off */ -+ if (ret < 0) -+ goto error_entity; -+ msleep(100); -+ ret = update_formatter2(sensor, false); -+ if (ret < 0) -+ goto error_entity; -+ -+ return ret; -+ -+error_entity: -+ media_entity_cleanup(&sensor->subdev.entity); -+error_ctrl: -+ v4l2_ctrl_handler_free(&sensor->ctrls); -+error_sensor: -+ mutex_destroy(&sensor->lock); -+ kfree(sensor); -+ return ret; -+} -+ -+static int mt9m032_remove(struct i2c_client *client) -+{ -+ struct v4l2_subdev *subdev = i2c_get_clientdata(client); -+ struct mt9m032 *sensor = to_mt9m032(subdev); -+ -+ v4l2_device_unregister_subdev(&sensor->subdev); -+ v4l2_ctrl_handler_free(&sensor->ctrls); -+ media_entity_cleanup(&sensor->subdev.entity); -+ mutex_destroy(&sensor->lock); -+ kfree(sensor); -+ return 0; -+} -+ -+static const struct i2c_device_id mt9m032_id_table[] = { -+ { MT9M032_NAME, 0 }, -+ { } -+}; -+ -+MODULE_DEVICE_TABLE(i2c, mt9m032_id_table); -+ -+static struct i2c_driver mt9m032_i2c_driver = { -+ .driver = { -+ .name = MT9M032_NAME, -+ }, -+ .probe = mt9m032_probe, -+ .remove = mt9m032_remove, -+ .id_table = mt9m032_id_table, -+}; -+ -+module_i2c_driver(mt9m032_i2c_driver); -+ -+MODULE_AUTHOR("Martin Hostettler "); -+MODULE_DESCRIPTION("MT9M032 camera sensor driver"); -+MODULE_LICENSE("GPL v2"); -Index: linux-3.3.x86_64/include/media/mt9m032.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/include/media/mt9m032.h -@@ -0,0 +1,36 @@ -+/* -+ * Driver for MT9M032 CMOS Image Sensor from Micron -+ * -+ * Copyright (C) 2010-2011 Lund Engineering -+ * Contact: Gil Lund -+ * Author: Martin Hostettler -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -+ * 02110-1301 USA -+ * -+ */ -+ -+#ifndef MT9M032_H -+#define MT9M032_H -+ -+#define MT9M032_NAME "mt9m032" -+#define MT9M032_I2C_ADDR (0xb8 >> 1) -+ -+struct mt9m032_platform_data { -+ u32 ext_clock; -+ u32 pix_clock; -+ bool invert_pixclock; -+ -+}; -+#endif /* MT9M032_H */ -Index: linux-3.3.x86_64/drivers/media/video/v4l2-dev.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/v4l2-dev.c -+++ linux-3.3.x86_64/drivers/media/video/v4l2-dev.c -@@ -788,7 +788,7 @@ static void __exit videodev_exit(void) - unregister_chrdev_region(dev, VIDEO_NUM_DEVICES); - } - --module_init(videodev_init) -+subsys_initcall(videodev_init); - module_exit(videodev_exit) - - MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab "); -Index: linux-3.3.x86_64/drivers/media/media-devnode.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/media-devnode.c -+++ linux-3.3.x86_64/drivers/media/media-devnode.c -@@ -312,7 +312,7 @@ static void __exit media_devnode_exit(vo - unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES); - } - --module_init(media_devnode_init) -+subsys_initcall(media_devnode_init); - module_exit(media_devnode_exit) - - MODULE_AUTHOR("Laurent Pinchart "); -Index: linux-3.3.x86_64/drivers/media/rc/mceusb.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/rc/mceusb.c -+++ linux-3.3.x86_64/drivers/media/rc/mceusb.c -@@ -361,6 +361,8 @@ static struct usb_device_id mceusb_dev_t - { USB_DEVICE(VENDOR_FORMOSA, 0xe03c) }, - /* Formosa Industrial Computing */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe03e) }, -+ /* Formosa Industrial Computing */ -+ { USB_DEVICE(VENDOR_FORMOSA, 0xe042) }, - /* Fintek eHome Infrared Transceiver (HP branded) */ - { USB_DEVICE(VENDOR_FINTEK, 0x5168) }, - /* Fintek eHome Infrared Transceiver */ -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/au8522_dig.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/frontends/au8522_dig.c -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/au8522_dig.c -@@ -604,6 +604,11 @@ static int au8522_set_frontend(struct dv - - au8522_enable_modulation(fe, c->modulation); - -+ /* Allow the tuner to settle */ -+ msleep(100); -+ -+ au8522_enable_modulation(fe, c->modulation); -+ - state->current_frequency = c->frequency; - - return 0; -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/dib0700_core.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/dib0700_core.c -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/dib0700_core.c -@@ -677,11 +677,9 @@ static void dib0700_rc_urb_completion(st - u8 toggle; - - deb_info("%s()\n", __func__); -- if (d == NULL) -- return; -- - if (d->rc_dev == NULL) { - /* This will occur if disable_rc_polling=1 */ -+ kfree(purb->transfer_buffer); - usb_free_urb(purb); - return; - } -@@ -690,6 +688,7 @@ static void dib0700_rc_urb_completion(st - - if (purb->status < 0) { - deb_info("discontinuing polling\n"); -+ kfree(purb->transfer_buffer); - usb_free_urb(purb); - return; - } -@@ -784,8 +783,11 @@ int dib0700_rc_setup(struct dvb_usb_devi - dib0700_rc_urb_completion, d); - - ret = usb_submit_urb(purb, GFP_ATOMIC); -- if (ret) -+ if (ret) { - err("rc submit urb failed\n"); -+ kfree(purb->transfer_buffer); -+ usb_free_urb(purb); -+ } - - return ret; - } -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9015.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/af9015.c -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9015.c -@@ -1164,6 +1164,41 @@ static int af9015_af9013_sleep(struct dv - return ret; - } - -+/* override tuner callbacks for resource locking */ -+static int af9015_tuner_init(struct dvb_frontend *fe) -+{ -+ int ret; -+ struct dvb_usb_adapter *adap = fe->dvb->priv; -+ struct af9015_state *priv = adap->dev->priv; -+ -+ if (mutex_lock_interruptible(&adap->dev->usb_mutex)) -+ return -EAGAIN; -+ -+ ret = priv->tuner_init[adap->id](fe); -+ -+ mutex_unlock(&adap->dev->usb_mutex); -+ -+ return ret; -+} -+ -+/* override tuner callbacks for resource locking */ -+static int af9015_tuner_sleep(struct dvb_frontend *fe) -+{ -+ int ret; -+ struct dvb_usb_adapter *adap = fe->dvb->priv; -+ struct af9015_state *priv = adap->dev->priv; -+ -+ if (mutex_lock_interruptible(&adap->dev->usb_mutex)) -+ return -EAGAIN; -+ -+ ret = priv->tuner_sleep[adap->id](fe); -+ -+ mutex_unlock(&adap->dev->usb_mutex); -+ -+ return ret; -+} -+ -+ - static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) - { - int ret; -@@ -1283,6 +1318,7 @@ static struct mxl5007t_config af9015_mxl - static int af9015_tuner_attach(struct dvb_usb_adapter *adap) - { - int ret; -+ struct af9015_state *state = adap->dev->priv; - deb_info("%s:\n", __func__); - - switch (af9015_af9013_config[adap->id].tuner) { -@@ -1340,6 +1376,19 @@ static int af9015_tuner_attach(struct dv - err("Unknown tuner id:%d", - af9015_af9013_config[adap->id].tuner); - } -+ -+ if (adap->fe_adap[0].fe->ops.tuner_ops.init) { -+ state->tuner_init[adap->id] = -+ adap->fe_adap[0].fe->ops.tuner_ops.init; -+ adap->fe_adap[0].fe->ops.tuner_ops.init = af9015_tuner_init; -+ } -+ -+ if (adap->fe_adap[0].fe->ops.tuner_ops.sleep) { -+ state->tuner_sleep[adap->id] = -+ adap->fe_adap[0].fe->ops.tuner_ops.sleep; -+ adap->fe_adap[0].fe->ops.tuner_ops.sleep = af9015_tuner_sleep; -+ } -+ - return ret; - } - -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9015.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/af9015.h -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9015.h -@@ -108,6 +108,8 @@ struct af9015_state { - int (*read_status[2]) (struct dvb_frontend *fe, fe_status_t *status); - int (*init[2]) (struct dvb_frontend *fe); - int (*sleep[2]) (struct dvb_frontend *fe); -+ int (*tuner_init[2]) (struct dvb_frontend *fe); -+ int (*tuner_sleep[2]) (struct dvb_frontend *fe); - }; - - struct af9015_config { -Index: linux-3.3.x86_64/drivers/media/rc/rc-main.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/rc/rc-main.c -+++ linux-3.3.x86_64/drivers/media/rc/rc-main.c -@@ -1029,6 +1029,7 @@ EXPORT_SYMBOL_GPL(rc_free_device); - - int rc_register_device(struct rc_dev *dev) - { -+ static bool raw_init = false; /* raw decoders loaded? */ - static atomic_t devno = ATOMIC_INIT(0); - struct rc_map *rc_map; - const char *path; -@@ -1103,6 +1104,12 @@ int rc_register_device(struct rc_dev *de - kfree(path); - - if (dev->driver_type == RC_DRIVER_IR_RAW) { -+ /* Load raw decoders, if they aren't already */ -+ if (!raw_init) { -+ IR_dprintk(1, "Loading raw decoders\n"); -+ ir_raw_init(); -+ raw_init = true; -+ } - rc = ir_raw_event_register(dev); - if (rc < 0) - goto out_input; -@@ -1176,8 +1183,6 @@ static int __init rc_core_init(void) - return rc; - } - -- /* Initialize/load the decoders/keymap code that will be used */ -- ir_raw_init(); - rc_map_register(&empty_map); - - return 0; -Index: linux-3.3.x86_64/drivers/media/video/soc_camera.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/soc_camera.c -+++ linux-3.3.x86_64/drivers/media/video/soc_camera.c -@@ -526,10 +526,6 @@ static int soc_camera_open(struct file * - }, - }; - -- ret = soc_camera_power_on(icd, icl); -- if (ret < 0) -- goto epower; -- - /* The camera could have been already on, try to reset */ - if (icl->reset) - icl->reset(icd->pdev); -@@ -540,6 +536,10 @@ static int soc_camera_open(struct file * - goto eiciadd; - } - -+ ret = soc_camera_power_on(icd, icl); -+ if (ret < 0) -+ goto epower; -+ - pm_runtime_enable(&icd->vdev->dev); - ret = pm_runtime_resume(&icd->vdev->dev); - if (ret < 0 && ret != -ENOSYS) -@@ -578,10 +578,10 @@ einitvb: - esfmt: - pm_runtime_disable(&icd->vdev->dev); - eresume: -- ici->ops->remove(icd); --eiciadd: - soc_camera_power_off(icd, icl); - epower: -+ ici->ops->remove(icd); -+eiciadd: - icd->use_count--; - module_put(ici->ops->owner); - -@@ -1050,6 +1050,14 @@ static int soc_camera_probe(struct soc_c - if (ret < 0) - goto ereg; - -+ /* The camera could have been already on, try to reset */ -+ if (icl->reset) -+ icl->reset(icd->pdev); -+ -+ ret = ici->ops->add(icd); -+ if (ret < 0) -+ goto eadd; -+ - /* - * This will not yet call v4l2_subdev_core_ops::s_power(1), because the - * subdevice has not been initialised yet. We'll have to call it once -@@ -1060,14 +1068,6 @@ static int soc_camera_probe(struct soc_c - if (ret < 0) - goto epower; - -- /* The camera could have been already on, try to reset */ -- if (icl->reset) -- icl->reset(icd->pdev); -- -- ret = ici->ops->add(icd); -- if (ret < 0) -- goto eadd; -- - /* Must have icd->vdev before registering the device */ - ret = video_dev_create(icd); - if (ret < 0) -@@ -1165,10 +1165,10 @@ eadddev: - video_device_release(icd->vdev); - icd->vdev = NULL; - evdc: -- ici->ops->remove(icd); --eadd: - soc_camera_power_off(icd, icl); - epower: -+ ici->ops->remove(icd); -+eadd: - regulator_bulk_free(icl->num_regulators, icl->regulators); - ereg: - v4l2_ctrl_handler_free(&icd->ctrl_handler); -Index: linux-3.3.x86_64/drivers/media/video/sh_mobile_ceu_camera.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/sh_mobile_ceu_camera.c -+++ linux-3.3.x86_64/drivers/media/video/sh_mobile_ceu_camera.c -@@ -112,6 +112,10 @@ struct sh_mobile_ceu_dev { - - u32 cflcr; - -+ /* static max sizes either from platform data or default */ -+ int max_width; -+ int max_height; -+ - enum v4l2_field field; - int sequence; - -@@ -1081,7 +1085,15 @@ static int sh_mobile_ceu_get_formats(str - if (ret < 0) - return ret; - -- while ((mf.width > 2560 || mf.height > 1920) && shift < 4) { -+ /* -+ * All currently existing CEU implementations support 2560x1920 -+ * or larger frames. If the sensor is proposing too big a frame, -+ * don't bother with possibly supportred by the CEU larger -+ * sizes, just try VGA multiples. If needed, this can be -+ * adjusted in the future. -+ */ -+ while ((mf.width > pcdev->max_width || -+ mf.height > pcdev->max_height) && shift < 4) { - /* Try 2560x1920, 1280x960, 640x480, 320x240 */ - mf.width = 2560 >> shift; - mf.height = 1920 >> shift; -@@ -1377,6 +1389,8 @@ static int client_s_crop(struct soc_came - static int client_s_fmt(struct soc_camera_device *icd, - struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) - { -+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); -+ struct sh_mobile_ceu_dev *pcdev = ici->priv; - struct sh_mobile_ceu_cam *cam = icd->host_priv; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - struct device *dev = icd->parent; -@@ -1410,8 +1424,8 @@ static int client_s_fmt(struct soc_camer - if (ret < 0) - return ret; - -- max_width = min(cap.bounds.width, 2560); -- max_height = min(cap.bounds.height, 1920); -+ max_width = min(cap.bounds.width, pcdev->max_width); -+ max_height = min(cap.bounds.height, pcdev->max_height); - - /* Camera set a format, but geometry is not precise, try to improve */ - tmp_w = mf->width; -@@ -1551,7 +1565,7 @@ static int sh_mobile_ceu_set_crop(struct - if (ret < 0) - return ret; - -- if (mf.width > 2560 || mf.height > 1920) -+ if (mf.width > pcdev->max_width || mf.height > pcdev->max_height) - return -EINVAL; - - /* 4. Calculate camera scales */ -@@ -1834,6 +1848,8 @@ static int sh_mobile_ceu_set_fmt(struct - static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) - { -+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); -+ struct sh_mobile_ceu_dev *pcdev = ici->priv; - const struct soc_camera_format_xlate *xlate; - struct v4l2_pix_format *pix = &f->fmt.pix; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); -@@ -1854,8 +1870,8 @@ static int sh_mobile_ceu_try_fmt(struct - /* FIXME: calculate using depth and bus width */ - - /* CFSZR requires height and width to be 4-pixel aligned */ -- v4l_bound_align_image(&pix->width, 2, 2560, 2, -- &pix->height, 4, 1920, 2, 0); -+ v4l_bound_align_image(&pix->width, 2, pcdev->max_width, 2, -+ &pix->height, 4, pcdev->max_height, 2, 0); - - width = pix->width; - height = pix->height; -@@ -1890,8 +1906,8 @@ static int sh_mobile_ceu_try_fmt(struct - * requested a bigger rectangle, it will not return a - * smaller one. - */ -- mf.width = 2560; -- mf.height = 1920; -+ mf.width = pcdev->max_width; -+ mf.height = pcdev->max_height; - ret = v4l2_device_call_until_err(sd->v4l2_dev, - soc_camera_grp_id(icd), video, - try_mbus_fmt, &mf); -@@ -2082,6 +2098,9 @@ static int __devinit sh_mobile_ceu_probe - goto exit_kfree; - } - -+ pcdev->max_width = pcdev->pdata->max_width ? : 2560; -+ pcdev->max_height = pcdev->pdata->max_height ? : 1920; -+ - base = ioremap_nocache(res->start, resource_size(res)); - if (!base) { - err = -ENXIO; -Index: linux-3.3.x86_64/include/media/sh_mobile_ceu.h -=================================================================== ---- linux-3.3.x86_64.orig/include/media/sh_mobile_ceu.h -+++ linux-3.3.x86_64/include/media/sh_mobile_ceu.h -@@ -18,6 +18,8 @@ struct sh_mobile_ceu_companion { - - struct sh_mobile_ceu_info { - unsigned long flags; -+ int max_width; -+ int max_height; - struct sh_mobile_ceu_companion *csi2; - }; - -Index: linux-3.3.x86_64/drivers/media/video/pxa_camera.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/pxa_camera.c -+++ linux-3.3.x86_64/drivers/media/video/pxa_camera.c -@@ -921,12 +921,12 @@ static void pxa_camera_activate(struct p - /* "Safe default" - 13MHz */ - recalculate_fifo_timeout(pcdev, 13000000); - -- clk_enable(pcdev->clk); -+ clk_prepare_enable(pcdev->clk); - } - - static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) - { -- clk_disable(pcdev->clk); -+ clk_disable_unprepare(pcdev->clk); - } - - static irqreturn_t pxa_camera_irq(int irq, void *data) -Index: linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-i2c.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/em28xx/em28xx-i2c.c -+++ linux-3.3.x86_64/drivers/media/video/em28xx/em28xx-i2c.c -@@ -41,14 +41,6 @@ static unsigned int i2c_debug; - module_param(i2c_debug, int, 0644); - MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); - -- --#define dprintk1(lvl, fmt, args...) \ --do { \ -- if (i2c_debug >= lvl) { \ -- printk(fmt, ##args); \ -- } \ --} while (0) -- - #define dprintk2(lvl, fmt, args...) \ - do { \ - if (i2c_debug >= lvl) { \ -Index: linux-3.3.x86_64/drivers/media/video/marvell-ccic/mcam-core.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/marvell-ccic/mcam-core.c -+++ linux-3.3.x86_64/drivers/media/video/marvell-ccic/mcam-core.c -@@ -509,11 +509,17 @@ static void mcam_sg_next_buffer(struct m - - buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue); - list_del_init(&buf->queue); -+ /* -+ * Very Bad Not Good Things happen if you don't clear -+ * C1_DESC_ENA before making any descriptor changes. -+ */ -+ mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_ENA); - mcam_reg_write(cam, REG_DMA_DESC_Y, buf->dma_desc_pa); - mcam_reg_write(cam, REG_DESC_LEN_Y, - buf->dma_desc_nent*sizeof(struct mcam_dma_desc)); - mcam_reg_write(cam, REG_DESC_LEN_U, 0); - mcam_reg_write(cam, REG_DESC_LEN_V, 0); -+ mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA); - cam->vb_bufs[0] = buf; - } - -@@ -533,7 +539,6 @@ static void mcam_ctlr_dma_sg(struct mcam - - mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_3WORD); - mcam_sg_next_buffer(cam); -- mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA); - cam->nbufs = 3; - } - -@@ -556,17 +561,16 @@ static void mcam_dma_sg_done(struct mcam - struct mcam_vb_buffer *buf = cam->vb_bufs[0]; - - /* -- * Very Bad Not Good Things happen if you don't clear -- * C1_DESC_ENA before making any descriptor changes. -+ * If we're no longer supposed to be streaming, don't do anything. - */ -- mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_ENA); -+ if (cam->state != S_STREAMING) -+ return; - /* - * If we have another buffer available, put it in and - * restart the engine. - */ - if (!list_empty(&cam->buffers)) { - mcam_sg_next_buffer(cam); -- mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA); - mcam_ctlr_start(cam); - /* - * Otherwise set CF_SG_RESTART and the controller will -@@ -737,7 +741,14 @@ static void mcam_ctlr_stop_dma(struct mc - mcam_ctlr_stop(cam); - cam->state = S_IDLE; - spin_unlock_irqrestore(&cam->dev_lock, flags); -- msleep(40); -+ /* -+ * This is a brutally long sleep, but experience shows that -+ * it can take the controller a while to get the message that -+ * it needs to stop grabbing frames. In particular, we can -+ * sometimes (on mmp) get a frame at the end WITHOUT the -+ * start-of-frame indication. -+ */ -+ msleep(150); - if (test_bit(CF_DMA_ACTIVE, &cam->flags)) - cam_err(cam, "Timeout waiting for DMA to end\n"); - /* This would be bad news - what now? */ -@@ -880,6 +891,7 @@ static int mcam_read_setup(struct mcam_c - * Turn it loose. - */ - spin_lock_irqsave(&cam->dev_lock, flags); -+ clear_bit(CF_DMA_ACTIVE, &cam->flags); - mcam_reset_buffers(cam); - mcam_ctlr_irq_enable(cam); - cam->state = S_STREAMING; -@@ -922,7 +934,7 @@ static void mcam_vb_buf_queue(struct vb2 - spin_lock_irqsave(&cam->dev_lock, flags); - start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers); - list_add(&mvb->queue, &cam->buffers); -- if (test_bit(CF_SG_RESTART, &cam->flags)) -+ if (cam->state == S_STREAMING && test_bit(CF_SG_RESTART, &cam->flags)) - mcam_sg_restart(cam); - spin_unlock_irqrestore(&cam->dev_lock, flags); - if (start) -@@ -1555,15 +1567,12 @@ static int mcam_v4l_release(struct file - { - struct mcam_camera *cam = filp->private_data; - -- cam_err(cam, "Release, %d frames, %d singles, %d delivered\n", frames, -+ cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n", frames, - singles, delivered); - mutex_lock(&cam->s_mutex); - (cam->users)--; -- if (filp == cam->owner) { -- mcam_ctlr_stop_dma(cam); -- cam->owner = NULL; -- } - if (cam->users == 0) { -+ mcam_ctlr_stop_dma(cam); - mcam_cleanup_vb2(cam); - mcam_ctlr_power_down(cam); - if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read) -@@ -1688,6 +1697,8 @@ int mccic_irq(struct mcam_camera *cam, u - if (irqs & (IRQ_EOF0 << frame)) { - mcam_frame_complete(cam, frame); - handled = 1; -+ if (cam->buffer_mode == B_DMA_sg) -+ break; - } - /* - * If a frame starts, note that we have DMA active. This -Index: linux-3.3.x86_64/drivers/media/video/marvell-ccic/mcam-core.h -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/marvell-ccic/mcam-core.h -+++ linux-3.3.x86_64/drivers/media/video/marvell-ccic/mcam-core.h -@@ -107,7 +107,6 @@ struct mcam_camera { - enum mcam_state state; - unsigned long flags; /* Buffer status, mainly (dev_lock) */ - int users; /* How many open FDs */ -- struct file *owner; /* Who has data access (v4l2) */ - - /* - * Subsystem structures. -Index: linux-3.3.x86_64/drivers/media/video/marvell-ccic/mmp-driver.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/marvell-ccic/mmp-driver.c -+++ linux-3.3.x86_64/drivers/media/video/marvell-ccic/mmp-driver.c -@@ -106,6 +106,13 @@ static struct mmp_camera *mmpcam_find_de - /* - * Power control. - */ -+static void mmpcam_power_up_ctlr(struct mmp_camera *cam) -+{ -+ iowrite32(0x3f, cam->power_regs + REG_CCIC_DCGCR); -+ iowrite32(0x3805b, cam->power_regs + REG_CCIC_CRCR); -+ mdelay(1); -+} -+ - static void mmpcam_power_up(struct mcam_camera *mcam) - { - struct mmp_camera *cam = mcam_to_cam(mcam); -@@ -113,9 +120,7 @@ static void mmpcam_power_up(struct mcam_ - /* - * Turn on power and clocks to the controller. - */ -- iowrite32(0x3f, cam->power_regs + REG_CCIC_DCGCR); -- iowrite32(0x3805b, cam->power_regs + REG_CCIC_CRCR); -- mdelay(1); -+ mmpcam_power_up_ctlr(cam); - /* - * Provide power to the sensor. - */ -@@ -335,7 +340,7 @@ static int mmpcam_resume(struct platform - * touch a register even if nothing was active before; trust - * me, it's better this way. - */ -- mmpcam_power_up(&cam->mcam); -+ mmpcam_power_up_ctlr(cam); - return mccic_resume(&cam->mcam); - } - -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/mxl111sf.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/dvb/dvb-usb/mxl111sf.c -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/mxl111sf.c -@@ -340,7 +340,6 @@ static int mxl111sf_ep6_streaming_ctrl(s - struct mxl111sf_state *state = d->priv; - struct mxl111sf_adap_state *adap_state = adap->fe_adap[adap->active_fe].priv; - int ret = 0; -- u8 tmp; - - deb_info("%s(%d)\n", __func__, onoff); - -Index: linux-3.3.x86_64/drivers/media/video/gspca/ov534_9.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/gspca/ov534_9.c -+++ linux-3.3.x86_64/drivers/media/video/gspca/ov534_9.c -@@ -1107,16 +1107,34 @@ static void setbrightness(struct gspca_d - { - struct sd *sd = (struct sd *) gspca_dev; - u8 val; -+ s8 sval; - - if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS)) - return; -- val = sd->ctrls[BRIGHTNESS].val; -- if (val < 8) -- val = 15 - val; /* f .. 8 */ -- else -- val = val - 8; /* 0 .. 7 */ -- sccb_write(gspca_dev, 0x55, /* brtn - brightness adjustment */ -- 0x0f | (val << 4)); -+ if (sd->sensor == SENSOR_OV562x) { -+ sval = sd->ctrls[BRIGHTNESS].val; -+ val = 0x76; -+ val += sval; -+ sccb_write(gspca_dev, 0x24, val); -+ val = 0x6a; -+ val += sval; -+ sccb_write(gspca_dev, 0x25, val); -+ if (sval < -40) -+ val = 0x71; -+ else if (sval < 20) -+ val = 0x94; -+ else -+ val = 0xe6; -+ sccb_write(gspca_dev, 0x26, val); -+ } else { -+ val = sd->ctrls[BRIGHTNESS].val; -+ if (val < 8) -+ val = 15 - val; /* f .. 8 */ -+ else -+ val = val - 8; /* 0 .. 7 */ -+ sccb_write(gspca_dev, 0x55, /* brtn - brightness adjustment */ -+ 0x0f | (val << 4)); -+ } - } - - static void setcontrast(struct gspca_dev *gspca_dev) -@@ -1339,7 +1357,16 @@ static int sd_init(struct gspca_dev *gsp - reg_w(gspca_dev, 0x56, 0x17); - } else if ((sensor_id & 0xfff0) == 0x5620) { - sd->sensor = SENSOR_OV562x; -- -+ gspca_dev->ctrl_dis = (1 << CONTRAST) | -+ (1 << AUTOGAIN) | -+ (1 << EXPOSURE) | -+ (1 << SHARPNESS) | -+ (1 << SATUR) | -+ (1 << LIGHTFREQ); -+ -+ sd->ctrls[BRIGHTNESS].min = -90; -+ sd->ctrls[BRIGHTNESS].max = 90; -+ sd->ctrls[BRIGHTNESS].def = 0; - gspca_dev->cam.cam_mode = ov562x_mode; - gspca_dev->cam.nmodes = ARRAY_SIZE(ov562x_mode); - -@@ -1360,8 +1387,12 @@ static int sd_start(struct gspca_dev *gs - { - struct sd *sd = (struct sd *) gspca_dev; - -- if (sd->sensor == SENSOR_OV971x || sd->sensor == SENSOR_OV562x) -+ if (sd->sensor == SENSOR_OV971x) - return gspca_dev->usb_err; -+ else if (sd->sensor == SENSOR_OV562x) { -+ setbrightness(gspca_dev); -+ return gspca_dev->usb_err; -+ } - switch (gspca_dev->curr_mode) { - case QVGA_MODE: /* 320x240 */ - sccb_w_array(gspca_dev, ov965x_start_1_vga, -Index: linux-3.3.x86_64/drivers/media/video/gspca/sn9c20x.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/gspca/sn9c20x.c -+++ linux-3.3.x86_64/drivers/media/video/gspca/sn9c20x.c -@@ -1,5 +1,7 @@ - /* - * Sonix sn9c201 sn9c202 library -+ * -+ * Copyright (C) 2012 Jean-Francois Moine - * Copyright (C) 2008-2009 microdia project - * Copyright (C) 2009 Brian Johnson - * -@@ -33,8 +35,6 @@ MODULE_AUTHOR("Brian Johnson dev; - int result; -+ -+ if (gspca_dev->usb_err < 0) -+ return; - result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - 0x00, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, -@@ -1125,17 +1103,19 @@ static int reg_r(struct gspca_dev *gspca - length, - 500); - if (unlikely(result < 0 || result != length)) { -- pr_err("Read register failed 0x%02X\n", reg); -- return -EIO; -+ pr_err("Read register %02x failed %d\n", reg, result); -+ gspca_dev->usb_err = result; - } -- return 0; - } - --static int reg_w(struct gspca_dev *gspca_dev, u16 reg, -+static void reg_w(struct gspca_dev *gspca_dev, u16 reg, - const u8 *buffer, int length) - { - struct usb_device *dev = gspca_dev->dev; - int result; -+ -+ if (gspca_dev->usb_err < 0) -+ return; - memcpy(gspca_dev->usb_buf, buffer, length); - result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0x08, -@@ -1146,38 +1126,41 @@ static int reg_w(struct gspca_dev *gspca - length, - 500); - if (unlikely(result < 0 || result != length)) { -- pr_err("Write register failed index 0x%02X\n", reg); -- return -EIO; -+ pr_err("Write register %02x failed %d\n", reg, result); -+ gspca_dev->usb_err = result; - } -- return 0; - } - --static int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value) -+static void reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value) - { -- u8 data[1] = {value}; -- return reg_w(gspca_dev, reg, data, 1); -+ reg_w(gspca_dev, reg, &value, 1); - } - --static int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer) -+static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer) - { - int i; -+ - reg_w(gspca_dev, 0x10c0, buffer, 8); - for (i = 0; i < 5; i++) { - reg_r(gspca_dev, 0x10c0, 1); -+ if (gspca_dev->usb_err < 0) -+ return; - if (gspca_dev->usb_buf[0] & 0x04) { -- if (gspca_dev->usb_buf[0] & 0x08) -- return -EIO; -- return 0; -+ if (gspca_dev->usb_buf[0] & 0x08) { -+ pr_err("i2c_w error\n"); -+ gspca_dev->usb_err = -EIO; -+ } -+ return; - } -- msleep(1); -+ msleep(10); - } -- return -EIO; -+ pr_err("i2c_w reg %02x no response\n", buffer[2]); -+/* gspca_dev->usb_err = -EIO; fixme: may occur */ - } - --static int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) -+static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) - { - struct sd *sd = (struct sd *) gspca_dev; -- - u8 row[8]; - - /* -@@ -1193,10 +1176,19 @@ static int i2c_w1(struct gspca_dev *gspc - row[6] = 0x00; - row[7] = 0x10; - -- return i2c_w(gspca_dev, row); -+ i2c_w(gspca_dev, row); -+} -+ -+static void i2c_w1_buf(struct gspca_dev *gspca_dev, -+ struct i2c_reg_u8 *buf, int sz) -+{ -+ while (--sz >= 0) { -+ i2c_w1(gspca_dev, buf->reg, buf->val); -+ buf++; -+ } - } - --static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val) -+static void i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val) - { - struct sd *sd = (struct sd *) gspca_dev; - u8 row[8]; -@@ -1208,16 +1200,25 @@ static int i2c_w2(struct gspca_dev *gspc - row[0] = 0x81 | (3 << 4); - row[1] = sd->i2c_addr; - row[2] = reg; -- row[3] = (val >> 8) & 0xff; -- row[4] = val & 0xff; -+ row[3] = val >> 8; -+ row[4] = val; - row[5] = 0x00; - row[6] = 0x00; - row[7] = 0x10; - -- return i2c_w(gspca_dev, row); -+ i2c_w(gspca_dev, row); - } - --static int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) -+static void i2c_w2_buf(struct gspca_dev *gspca_dev, -+ struct i2c_reg_u16 *buf, int sz) -+{ -+ while (--sz >= 0) { -+ i2c_w2(gspca_dev, buf->reg, buf->val); -+ buf++; -+ } -+} -+ -+static void i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) - { - struct sd *sd = (struct sd *) gspca_dev; - u8 row[8]; -@@ -1230,19 +1231,15 @@ static int i2c_r1(struct gspca_dev *gspc - row[5] = 0; - row[6] = 0; - row[7] = 0x10; -- if (i2c_w(gspca_dev, row) < 0) -- return -EIO; -+ i2c_w(gspca_dev, row); - row[0] = 0x81 | (1 << 4) | 0x02; - row[2] = 0; -- if (i2c_w(gspca_dev, row) < 0) -- return -EIO; -- if (reg_r(gspca_dev, 0x10c2, 5) < 0) -- return -EIO; -+ i2c_w(gspca_dev, row); -+ reg_r(gspca_dev, 0x10c2, 5); - *val = gspca_dev->usb_buf[4]; -- return 0; - } - --static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) -+static void i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) - { - struct sd *sd = (struct sd *) gspca_dev; - u8 row[8]; -@@ -1255,233 +1252,204 @@ static int i2c_r2(struct gspca_dev *gspc - row[5] = 0; - row[6] = 0; - row[7] = 0x10; -- if (i2c_w(gspca_dev, row) < 0) -- return -EIO; -+ i2c_w(gspca_dev, row); - row[0] = 0x81 | (2 << 4) | 0x02; - row[2] = 0; -- if (i2c_w(gspca_dev, row) < 0) -- return -EIO; -- if (reg_r(gspca_dev, 0x10c2, 5) < 0) -- return -EIO; -+ i2c_w(gspca_dev, row); -+ reg_r(gspca_dev, 0x10c2, 5); - *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; -- return 0; - } - --static int ov9650_init_sensor(struct gspca_dev *gspca_dev) -+static void ov9650_init_sensor(struct gspca_dev *gspca_dev) - { -- int i; - u16 id; - struct sd *sd = (struct sd *) gspca_dev; - -- if (i2c_r2(gspca_dev, 0x1c, &id) < 0) -- return -EINVAL; -+ i2c_r2(gspca_dev, 0x1c, &id); -+ if (gspca_dev->usb_err < 0) -+ return; - - if (id != 0x7fa2) { - pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id); -- return -ENODEV; -+ gspca_dev->usb_err = -ENODEV; -+ return; - } - -- for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) { -- if (i2c_w1(gspca_dev, ov9650_init[i].reg, -- ov9650_init[i].val) < 0) { -- pr_err("OV9650 sensor initialization failed\n"); -- return -ENODEV; -- } -- } -+ i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ -+ msleep(200); -+ i2c_w1_buf(gspca_dev, ov9650_init, ARRAY_SIZE(ov9650_init)); -+ if (gspca_dev->usb_err < 0) -+ pr_err("OV9650 sensor initialization failed\n"); - sd->hstart = 1; - sd->vstart = 7; -- return 0; - } - --static int ov9655_init_sensor(struct gspca_dev *gspca_dev) -+static void ov9655_init_sensor(struct gspca_dev *gspca_dev) - { -- int i; - struct sd *sd = (struct sd *) gspca_dev; - -- for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) { -- if (i2c_w1(gspca_dev, ov9655_init[i].reg, -- ov9655_init[i].val) < 0) { -- pr_err("OV9655 sensor initialization failed\n"); -- return -ENODEV; -- } -- } -+ i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ -+ msleep(200); -+ i2c_w1_buf(gspca_dev, ov9655_init, ARRAY_SIZE(ov9655_init)); -+ if (gspca_dev->usb_err < 0) -+ pr_err("OV9655 sensor initialization failed\n"); -+ - /* disable hflip and vflip */ -- gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); -+ gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP); - sd->hstart = 1; - sd->vstart = 2; -- return 0; - } - --static int soi968_init_sensor(struct gspca_dev *gspca_dev) -+static void soi968_init_sensor(struct gspca_dev *gspca_dev) - { -- int i; - struct sd *sd = (struct sd *) gspca_dev; - -- for (i = 0; i < ARRAY_SIZE(soi968_init); i++) { -- if (i2c_w1(gspca_dev, soi968_init[i].reg, -- soi968_init[i].val) < 0) { -- pr_err("SOI968 sensor initialization failed\n"); -- return -ENODEV; -- } -- } -+ i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ -+ msleep(200); -+ i2c_w1_buf(gspca_dev, soi968_init, ARRAY_SIZE(soi968_init)); -+ if (gspca_dev->usb_err < 0) -+ pr_err("SOI968 sensor initialization failed\n"); -+ - /* disable hflip and vflip */ -- gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) -- | (1 << EXPOSURE_IDX); -+ gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP) -+ | (1 << EXPOSURE); - sd->hstart = 60; - sd->vstart = 11; -- return 0; - } - --static int ov7660_init_sensor(struct gspca_dev *gspca_dev) -+static void ov7660_init_sensor(struct gspca_dev *gspca_dev) - { -- int i; - struct sd *sd = (struct sd *) gspca_dev; - -- for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) { -- if (i2c_w1(gspca_dev, ov7660_init[i].reg, -- ov7660_init[i].val) < 0) { -- pr_err("OV7660 sensor initialization failed\n"); -- return -ENODEV; -- } -- } -+ i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ -+ msleep(200); -+ i2c_w1_buf(gspca_dev, ov7660_init, ARRAY_SIZE(ov7660_init)); -+ if (gspca_dev->usb_err < 0) -+ pr_err("OV7660 sensor initialization failed\n"); - sd->hstart = 3; - sd->vstart = 3; -- return 0; - } - --static int ov7670_init_sensor(struct gspca_dev *gspca_dev) -+static void ov7670_init_sensor(struct gspca_dev *gspca_dev) - { -- int i; - struct sd *sd = (struct sd *) gspca_dev; - -- for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) { -- if (i2c_w1(gspca_dev, ov7670_init[i].reg, -- ov7670_init[i].val) < 0) { -- pr_err("OV7670 sensor initialization failed\n"); -- return -ENODEV; -- } -- } -+ i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ -+ msleep(200); -+ i2c_w1_buf(gspca_dev, ov7670_init, ARRAY_SIZE(ov7670_init)); -+ if (gspca_dev->usb_err < 0) -+ pr_err("OV7670 sensor initialization failed\n"); -+ - /* disable hflip and vflip */ -- gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); -+ gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP); - sd->hstart = 0; - sd->vstart = 1; -- return 0; - } - --static int mt9v_init_sensor(struct gspca_dev *gspca_dev) -+static void mt9v_init_sensor(struct gspca_dev *gspca_dev) - { - struct sd *sd = (struct sd *) gspca_dev; -- int i; - u16 value; -- int ret; - - sd->i2c_addr = 0x5d; -- ret = i2c_r2(gspca_dev, 0xff, &value); -- if ((ret == 0) && (value == 0x8243)) { -- for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) { -- if (i2c_w2(gspca_dev, mt9v011_init[i].reg, -- mt9v011_init[i].val) < 0) { -- pr_err("MT9V011 sensor initialization failed\n"); -- return -ENODEV; -- } -+ i2c_r2(gspca_dev, 0xff, &value); -+ if (gspca_dev->usb_err >= 0 -+ && value == 0x8243) { -+ i2c_w2_buf(gspca_dev, mt9v011_init, ARRAY_SIZE(mt9v011_init)); -+ if (gspca_dev->usb_err < 0) { -+ pr_err("MT9V011 sensor initialization failed\n"); -+ return; - } - sd->hstart = 2; - sd->vstart = 2; - sd->sensor = SENSOR_MT9V011; - pr_info("MT9V011 sensor detected\n"); -- return 0; -+ return; - } - -+ gspca_dev->usb_err = 0; - sd->i2c_addr = 0x5c; - i2c_w2(gspca_dev, 0x01, 0x0004); -- ret = i2c_r2(gspca_dev, 0xff, &value); -- if ((ret == 0) && (value == 0x823a)) { -- for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) { -- if (i2c_w2(gspca_dev, mt9v111_init[i].reg, -- mt9v111_init[i].val) < 0) { -- pr_err("MT9V111 sensor initialization failed\n"); -- return -ENODEV; -- } -+ i2c_r2(gspca_dev, 0xff, &value); -+ if (gspca_dev->usb_err >= 0 -+ && value == 0x823a) { -+ i2c_w2_buf(gspca_dev, mt9v111_init, ARRAY_SIZE(mt9v111_init)); -+ if (gspca_dev->usb_err < 0) { -+ pr_err("MT9V111 sensor initialization failed\n"); -+ return; - } -- gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) -- | (1 << AUTOGAIN_IDX) -- | (1 << GAIN_IDX); -+ gspca_dev->ctrl_dis = (1 << EXPOSURE) -+ | (1 << AUTOGAIN) -+ | (1 << GAIN); - sd->hstart = 2; - sd->vstart = 2; - sd->sensor = SENSOR_MT9V111; - pr_info("MT9V111 sensor detected\n"); -- return 0; -+ return; - } - -+ gspca_dev->usb_err = 0; - sd->i2c_addr = 0x5d; -- ret = i2c_w2(gspca_dev, 0xf0, 0x0000); -- if (ret < 0) { -+ i2c_w2(gspca_dev, 0xf0, 0x0000); -+ if (gspca_dev->usb_err < 0) { -+ gspca_dev->usb_err = 0; - sd->i2c_addr = 0x48; - i2c_w2(gspca_dev, 0xf0, 0x0000); - } -- ret = i2c_r2(gspca_dev, 0x00, &value); -- if ((ret == 0) && (value == 0x1229)) { -- for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) { -- if (i2c_w2(gspca_dev, mt9v112_init[i].reg, -- mt9v112_init[i].val) < 0) { -- pr_err("MT9V112 sensor initialization failed\n"); -- return -ENODEV; -- } -+ i2c_r2(gspca_dev, 0x00, &value); -+ if (gspca_dev->usb_err >= 0 -+ && value == 0x1229) { -+ i2c_w2_buf(gspca_dev, mt9v112_init, ARRAY_SIZE(mt9v112_init)); -+ if (gspca_dev->usb_err < 0) { -+ pr_err("MT9V112 sensor initialization failed\n"); -+ return; - } - sd->hstart = 6; - sd->vstart = 2; - sd->sensor = SENSOR_MT9V112; - pr_info("MT9V112 sensor detected\n"); -- return 0; -+ return; - } - -- return -ENODEV; -+ gspca_dev->usb_err = -ENODEV; - } - --static int mt9m112_init_sensor(struct gspca_dev *gspca_dev) -+static void mt9m112_init_sensor(struct gspca_dev *gspca_dev) - { - struct sd *sd = (struct sd *) gspca_dev; -- int i; -- for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) { -- if (i2c_w2(gspca_dev, mt9m112_init[i].reg, -- mt9m112_init[i].val) < 0) { -- pr_err("MT9M112 sensor initialization failed\n"); -- return -ENODEV; -- } -- } -- gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) -- | (1 << GAIN_IDX); -+ -+ i2c_w2_buf(gspca_dev, mt9m112_init, ARRAY_SIZE(mt9m112_init)); -+ if (gspca_dev->usb_err < 0) -+ pr_err("MT9M112 sensor initialization failed\n"); -+ -+ gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN) -+ | (1 << GAIN); - sd->hstart = 0; - sd->vstart = 2; -- return 0; - } - --static int mt9m111_init_sensor(struct gspca_dev *gspca_dev) -+static void mt9m111_init_sensor(struct gspca_dev *gspca_dev) - { - struct sd *sd = (struct sd *) gspca_dev; -- int i; -- for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) { -- if (i2c_w2(gspca_dev, mt9m111_init[i].reg, -- mt9m111_init[i].val) < 0) { -- pr_err("MT9M111 sensor initialization failed\n"); -- return -ENODEV; -- } -- } -- gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) -- | (1 << GAIN_IDX); -+ -+ i2c_w2_buf(gspca_dev, mt9m111_init, ARRAY_SIZE(mt9m111_init)); -+ if (gspca_dev->usb_err < 0) -+ pr_err("MT9M111 sensor initialization failed\n"); -+ -+ gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN) -+ | (1 << GAIN); - sd->hstart = 0; - sd->vstart = 2; -- return 0; - } - --static int mt9m001_init_sensor(struct gspca_dev *gspca_dev) -+static void mt9m001_init_sensor(struct gspca_dev *gspca_dev) - { - struct sd *sd = (struct sd *) gspca_dev; -- int i; - u16 id; - -- if (i2c_r2(gspca_dev, 0x00, &id) < 0) -- return -EINVAL; -+ i2c_r2(gspca_dev, 0x00, &id); -+ if (gspca_dev->usb_err < 0) -+ return; - - /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ - switch (id) { -@@ -1494,85 +1462,78 @@ static int mt9m001_init_sensor(struct gs - break; - default: - pr_err("No MT9M001 chip detected, ID = %x\n\n", id); -- return -ENODEV; -+ gspca_dev->usb_err = -ENODEV; -+ return; - } - -- for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) { -- if (i2c_w2(gspca_dev, mt9m001_init[i].reg, -- mt9m001_init[i].val) < 0) { -- pr_err("MT9M001 sensor initialization failed\n"); -- return -ENODEV; -- } -- } -+ i2c_w2_buf(gspca_dev, mt9m001_init, ARRAY_SIZE(mt9m001_init)); -+ if (gspca_dev->usb_err < 0) -+ pr_err("MT9M001 sensor initialization failed\n"); -+ - /* disable hflip and vflip */ -- gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); -+ gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP); - sd->hstart = 1; - sd->vstart = 1; -- return 0; - } - --static int hv7131r_init_sensor(struct gspca_dev *gspca_dev) -+static void hv7131r_init_sensor(struct gspca_dev *gspca_dev) - { -- int i; - struct sd *sd = (struct sd *) gspca_dev; - -- for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) { -- if (i2c_w1(gspca_dev, hv7131r_init[i].reg, -- hv7131r_init[i].val) < 0) { -- pr_err("HV7131R Sensor initialization failed\n"); -- return -ENODEV; -- } -- } -+ i2c_w1_buf(gspca_dev, hv7131r_init, ARRAY_SIZE(hv7131r_init)); -+ if (gspca_dev->usb_err < 0) -+ pr_err("HV7131R Sensor initialization failed\n"); -+ - sd->hstart = 0; - sd->vstart = 1; -- return 0; - } - --static int set_cmatrix(struct gspca_dev *gspca_dev) -+static void set_cmatrix(struct gspca_dev *gspca_dev) - { - struct sd *sd = (struct sd *) gspca_dev; -- s32 hue_coord, hue_index = 180 + sd->hue; -+ int satur; -+ s32 hue_coord, hue_index = 180 + sd->ctrls[HUE].val; - u8 cmatrix[21]; - - memset(cmatrix, 0, sizeof cmatrix); -- cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26; -+ cmatrix[2] = (sd->ctrls[CONTRAST].val * 0x25 / 0x100) + 0x26; - cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25; - cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25; -- cmatrix[18] = sd->brightness - 0x80; -+ cmatrix[18] = sd->ctrls[BRIGHTNESS].val - 0x80; - -- hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8; -+ satur = sd->ctrls[SATURATION].val; -+ hue_coord = (hsv_red_x[hue_index] * satur) >> 8; - cmatrix[6] = hue_coord; - cmatrix[7] = (hue_coord >> 8) & 0x0f; - -- hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8; -+ hue_coord = (hsv_red_y[hue_index] * satur) >> 8; - cmatrix[8] = hue_coord; - cmatrix[9] = (hue_coord >> 8) & 0x0f; - -- hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8; -+ hue_coord = (hsv_green_x[hue_index] * satur) >> 8; - cmatrix[10] = hue_coord; - cmatrix[11] = (hue_coord >> 8) & 0x0f; - -- hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8; -+ hue_coord = (hsv_green_y[hue_index] * satur) >> 8; - cmatrix[12] = hue_coord; - cmatrix[13] = (hue_coord >> 8) & 0x0f; - -- hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8; -+ hue_coord = (hsv_blue_x[hue_index] * satur) >> 8; - cmatrix[14] = hue_coord; - cmatrix[15] = (hue_coord >> 8) & 0x0f; - -- hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8; -+ hue_coord = (hsv_blue_y[hue_index] * satur) >> 8; - cmatrix[16] = hue_coord; - cmatrix[17] = (hue_coord >> 8) & 0x0f; - -- return reg_w(gspca_dev, 0x10e1, cmatrix, 21); -+ reg_w(gspca_dev, 0x10e1, cmatrix, 21); - } - --static int set_gamma(struct gspca_dev *gspca_dev) -+static void set_gamma(struct gspca_dev *gspca_dev) - { - struct sd *sd = (struct sd *) gspca_dev; - u8 gamma[17]; -- u8 gval = sd->gamma * 0xb8 / 0x100; -- -+ u8 gval = sd->ctrls[GAMMA].val * 0xb8 / 0x100; - - gamma[0] = 0x0a; - gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8); -@@ -1592,29 +1553,29 @@ static int set_gamma(struct gspca_dev *g - gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8); - gamma[16] = 0xf5; - -- return reg_w(gspca_dev, 0x1190, gamma, 17); -+ reg_w(gspca_dev, 0x1190, gamma, 17); - } - --static int set_redblue(struct gspca_dev *gspca_dev) -+static void set_redblue(struct gspca_dev *gspca_dev) - { - struct sd *sd = (struct sd *) gspca_dev; -- reg_w1(gspca_dev, 0x118c, sd->red); -- reg_w1(gspca_dev, 0x118f, sd->blue); -- return 0; -+ -+ reg_w1(gspca_dev, 0x118c, sd->ctrls[RED].val); -+ reg_w1(gspca_dev, 0x118f, sd->ctrls[BLUE].val); - } - --static int set_hvflip(struct gspca_dev *gspca_dev) -+static void set_hvflip(struct gspca_dev *gspca_dev) - { - u8 value, tslb, hflip, vflip; - u16 value2; - struct sd *sd = (struct sd *) gspca_dev; - - if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) { -- hflip = !sd->hflip; -- vflip = !sd->vflip; -+ hflip = !sd->ctrls[HFLIP].val; -+ vflip = !sd->ctrls[VFLIP].val; - } else { -- hflip = sd->hflip; -- vflip = sd->vflip; -+ hflip = sd->ctrls[HFLIP].val; -+ vflip = sd->ctrls[VFLIP].val; - } - - switch (sd->sensor) { -@@ -1625,8 +1586,9 @@ static int set_hvflip(struct gspca_dev * - if (vflip) { - value |= 0x10; - sd->vstart = 2; -- } else -+ } else { - sd->vstart = 3; -+ } - reg_w1(gspca_dev, 0x1182, sd->vstart); - i2c_w1(gspca_dev, 0x1e, value); - break; -@@ -1674,13 +1636,15 @@ static int set_hvflip(struct gspca_dev * - i2c_w1(gspca_dev, 0x01, value); - break; - } -- return 0; - } - --static int set_exposure(struct gspca_dev *gspca_dev) -+static void set_exposure(struct gspca_dev *gspca_dev) - { - struct sd *sd = (struct sd *) gspca_dev; - u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e}; -+ int expo; -+ -+ expo = sd->ctrls[EXPOSURE].val; - switch (sd->sensor) { - case SENSOR_OV7660: - case SENSOR_OV7670: -@@ -1688,35 +1652,37 @@ static int set_exposure(struct gspca_dev - case SENSOR_OV9650: - exp[0] |= (3 << 4); - exp[2] = 0x2d; -- exp[3] = sd->exposure & 0xff; -- exp[4] = sd->exposure >> 8; -+ exp[3] = expo; -+ exp[4] = expo >> 8; - break; - case SENSOR_MT9M001: - case SENSOR_MT9V112: - case SENSOR_MT9V011: - exp[0] |= (3 << 4); - exp[2] = 0x09; -- exp[3] = sd->exposure >> 8; -- exp[4] = sd->exposure & 0xff; -+ exp[3] = expo >> 8; -+ exp[4] = expo; - break; - case SENSOR_HV7131R: - exp[0] |= (4 << 4); - exp[2] = 0x25; -- exp[3] = (sd->exposure >> 5) & 0xff; -- exp[4] = (sd->exposure << 3) & 0xff; -+ exp[3] = expo >> 5; -+ exp[4] = expo << 3; - exp[5] = 0; - break; - default: -- return 0; -+ return; - } - i2c_w(gspca_dev, exp); -- return 0; - } - --static int set_gain(struct gspca_dev *gspca_dev) -+static void set_gain(struct gspca_dev *gspca_dev) - { - struct sd *sd = (struct sd *) gspca_dev; - u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d}; -+ int g; -+ -+ g = sd->ctrls[GAIN].val; - switch (sd->sensor) { - case SENSOR_OV7660: - case SENSOR_OV7670: -@@ -1724,238 +1690,50 @@ static int set_gain(struct gspca_dev *gs - case SENSOR_OV9655: - case SENSOR_OV9650: - gain[0] |= (2 << 4); -- gain[3] = ov_gain[sd->gain]; -+ gain[3] = ov_gain[g]; - break; - case SENSOR_MT9V011: - gain[0] |= (3 << 4); - gain[2] = 0x35; -- gain[3] = micron1_gain[sd->gain] >> 8; -- gain[4] = micron1_gain[sd->gain] & 0xff; -+ gain[3] = micron1_gain[g] >> 8; -+ gain[4] = micron1_gain[g]; - break; - case SENSOR_MT9V112: - gain[0] |= (3 << 4); - gain[2] = 0x2f; -- gain[3] = micron1_gain[sd->gain] >> 8; -- gain[4] = micron1_gain[sd->gain] & 0xff; -+ gain[3] = micron1_gain[g] >> 8; -+ gain[4] = micron1_gain[g]; - break; - case SENSOR_MT9M001: - gain[0] |= (3 << 4); - gain[2] = 0x2f; -- gain[3] = micron2_gain[sd->gain] >> 8; -- gain[4] = micron2_gain[sd->gain] & 0xff; -+ gain[3] = micron2_gain[g] >> 8; -+ gain[4] = micron2_gain[g]; - break; - case SENSOR_HV7131R: - gain[0] |= (2 << 4); - gain[2] = 0x30; -- gain[3] = hv7131r_gain[sd->gain]; -+ gain[3] = hv7131r_gain[g]; - break; - default: -- return 0; -+ return; - } - i2c_w(gspca_dev, gain); -- return 0; --} -- --static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->brightness = val; -- if (gspca_dev->streaming) -- return set_cmatrix(gspca_dev); -- return 0; --} -- --static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- *val = sd->brightness; -- return 0; --} -- -- --static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->contrast = val; -- if (gspca_dev->streaming) -- return set_cmatrix(gspca_dev); -- return 0; --} -- --static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- *val = sd->contrast; -- return 0; --} -- --static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->saturation = val; -- if (gspca_dev->streaming) -- return set_cmatrix(gspca_dev); -- return 0; --} -- --static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- *val = sd->saturation; -- return 0; --} -- --static int sd_sethue(struct gspca_dev *gspca_dev, s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->hue = val; -- if (gspca_dev->streaming) -- return set_cmatrix(gspca_dev); -- return 0; --} -- --static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- *val = sd->hue; -- return 0; --} -- --static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->gamma = val; -- if (gspca_dev->streaming) -- return set_gamma(gspca_dev); -- return 0; --} -- --static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- *val = sd->gamma; -- return 0; --} -- --static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->red = val; -- if (gspca_dev->streaming) -- return set_redblue(gspca_dev); -- return 0; --} -- --static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- *val = sd->red; -- return 0; --} -- --static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->blue = val; -- if (gspca_dev->streaming) -- return set_redblue(gspca_dev); -- return 0; --} -- --static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- *val = sd->blue; -- return 0; --} -- --static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->hflip = val; -- if (gspca_dev->streaming) -- return set_hvflip(gspca_dev); -- return 0; --} -- --static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- *val = sd->hflip; -- return 0; --} -- --static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->vflip = val; -- if (gspca_dev->streaming) -- return set_hvflip(gspca_dev); -- return 0; --} -- --static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- *val = sd->vflip; -- return 0; --} -- --static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->exposure = val; -- if (gspca_dev->streaming) -- return set_exposure(gspca_dev); -- return 0; --} -- --static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- *val = sd->exposure; -- return 0; --} -- --static int sd_setgain(struct gspca_dev *gspca_dev, s32 val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- -- sd->gain = val; -- if (gspca_dev->streaming) -- return set_gain(gspca_dev); -- return 0; --} -- --static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- *val = sd->gain; -- return 0; - } - --static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val) -+static void set_quality(struct gspca_dev *gspca_dev) - { - struct sd *sd = (struct sd *) gspca_dev; -- sd->auto_exposure = val; -- return 0; --} - --static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val) --{ -- struct sd *sd = (struct sd *) gspca_dev; -- *val = sd->auto_exposure; -- return 0; -+ jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); -+ reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */ -+ reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */ -+ reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64); -+ reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64); -+ reg_w1(gspca_dev, 0x1061, 0x03); /* restart transfer */ -+ reg_w1(gspca_dev, 0x10e0, sd->fmt); -+ sd->fmt ^= 0x0c; /* invert QTAB use + write */ -+ reg_w1(gspca_dev, 0x10e0, sd->fmt); - } - - #ifdef CONFIG_VIDEO_ADV_DEBUG -@@ -1963,28 +1741,26 @@ static int sd_dbg_g_register(struct gspc - struct v4l2_dbg_register *reg) - { - struct sd *sd = (struct sd *) gspca_dev; -+ - switch (reg->match.type) { - case V4L2_CHIP_MATCH_HOST: - if (reg->match.addr != 0) - return -EINVAL; - if (reg->reg < 0x1000 || reg->reg > 0x11ff) - return -EINVAL; -- if (reg_r(gspca_dev, reg->reg, 1) < 0) -- return -EINVAL; -+ reg_r(gspca_dev, reg->reg, 1); - reg->val = gspca_dev->usb_buf[0]; -- return 0; -+ return gspca_dev->usb_err; - case V4L2_CHIP_MATCH_I2C_ADDR: - if (reg->match.addr != sd->i2c_addr) - return -EINVAL; - if (sd->sensor >= SENSOR_MT9V011 && - sd->sensor <= SENSOR_MT9M112) { -- if (i2c_r2(gspca_dev, reg->reg, (u16 *)®->val) < 0) -- return -EINVAL; -+ i2c_r2(gspca_dev, reg->reg, (u16 *) ®->val); - } else { -- if (i2c_r1(gspca_dev, reg->reg, (u8 *)®->val) < 0) -- return -EINVAL; -+ i2c_r1(gspca_dev, reg->reg, (u8 *) ®->val); - } -- return 0; -+ return gspca_dev->usb_err; - } - return -EINVAL; - } -@@ -1993,27 +1769,25 @@ static int sd_dbg_s_register(struct gspc - struct v4l2_dbg_register *reg) - { - struct sd *sd = (struct sd *) gspca_dev; -+ - switch (reg->match.type) { - case V4L2_CHIP_MATCH_HOST: - if (reg->match.addr != 0) - return -EINVAL; - if (reg->reg < 0x1000 || reg->reg > 0x11ff) - return -EINVAL; -- if (reg_w1(gspca_dev, reg->reg, reg->val) < 0) -- return -EINVAL; -- return 0; -+ reg_w1(gspca_dev, reg->reg, reg->val); -+ return gspca_dev->usb_err; - case V4L2_CHIP_MATCH_I2C_ADDR: - if (reg->match.addr != sd->i2c_addr) - return -EINVAL; - if (sd->sensor >= SENSOR_MT9V011 && - sd->sensor <= SENSOR_MT9M112) { -- if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0) -- return -EINVAL; -+ i2c_w2(gspca_dev, reg->reg, reg->val); - } else { -- if (i2c_w1(gspca_dev, reg->reg, reg->val) < 0) -- return -EINVAL; -+ i2c_w1(gspca_dev, reg->reg, reg->val); - } -- return 0; -+ return gspca_dev->usb_err; - } - return -EINVAL; - } -@@ -2050,9 +1824,9 @@ static int sd_config(struct gspca_dev *g - cam = &gspca_dev->cam; - cam->needs_full_bandwidth = 1; - -- sd->sensor = (id->driver_info >> 8) & 0xff; -- sd->i2c_addr = id->driver_info & 0xff; -- sd->flags = (id->driver_info >> 16) & 0xff; -+ sd->sensor = id->driver_info >> 8; -+ sd->i2c_addr = id->driver_info; -+ sd->flags = id->driver_info >> 16; - - switch (sd->sensor) { - case SENSOR_MT9M112: -@@ -2076,21 +1850,9 @@ static int sd_config(struct gspca_dev *g - sd->older_step = 0; - sd->exposure_step = 16; - -- sd->brightness = BRIGHTNESS_DEFAULT; -- sd->contrast = CONTRAST_DEFAULT; -- sd->saturation = SATURATION_DEFAULT; -- sd->hue = HUE_DEFAULT; -- sd->gamma = GAMMA_DEFAULT; -- sd->red = RED_DEFAULT; -- sd->blue = BLUE_DEFAULT; -- -- sd->hflip = HFLIP_DEFAULT; -- sd->vflip = VFLIP_DEFAULT; -- sd->exposure = EXPOSURE_DEFAULT; -- sd->gain = GAIN_DEFAULT; -- sd->auto_exposure = AUTO_EXPOSURE_DEFAULT; -+ gspca_dev->cam.ctrls = sd->ctrls; - -- sd->quality = 95; -+ INIT_WORK(&sd->work, qual_upd); - - return 0; - } -@@ -2105,9 +1867,10 @@ static int sd_init(struct gspca_dev *gsp - - for (i = 0; i < ARRAY_SIZE(bridge_init); i++) { - value = bridge_init[i][1]; -- if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) { -+ reg_w(gspca_dev, bridge_init[i][0], &value, 1); -+ if (gspca_dev->usb_err < 0) { - pr_err("Device initialization failed\n"); -- return -ENODEV; -+ return gspca_dev->usb_err; - } - } - -@@ -2116,72 +1879,85 @@ static int sd_init(struct gspca_dev *gsp - else - reg_w1(gspca_dev, 0x1006, 0x20); - -- if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) { -+ reg_w(gspca_dev, 0x10c0, i2c_init, 9); -+ if (gspca_dev->usb_err < 0) { - pr_err("Device initialization failed\n"); -- return -ENODEV; -+ return gspca_dev->usb_err; - } - - switch (sd->sensor) { - case SENSOR_OV9650: -- if (ov9650_init_sensor(gspca_dev) < 0) -- return -ENODEV; -+ ov9650_init_sensor(gspca_dev); -+ if (gspca_dev->usb_err < 0) -+ break; - pr_info("OV9650 sensor detected\n"); - break; - case SENSOR_OV9655: -- if (ov9655_init_sensor(gspca_dev) < 0) -- return -ENODEV; -+ ov9655_init_sensor(gspca_dev); -+ if (gspca_dev->usb_err < 0) -+ break; - pr_info("OV9655 sensor detected\n"); - break; - case SENSOR_SOI968: -- if (soi968_init_sensor(gspca_dev) < 0) -- return -ENODEV; -+ soi968_init_sensor(gspca_dev); -+ if (gspca_dev->usb_err < 0) -+ break; - pr_info("SOI968 sensor detected\n"); - break; - case SENSOR_OV7660: -- if (ov7660_init_sensor(gspca_dev) < 0) -- return -ENODEV; -+ ov7660_init_sensor(gspca_dev); -+ if (gspca_dev->usb_err < 0) -+ break; - pr_info("OV7660 sensor detected\n"); - break; - case SENSOR_OV7670: -- if (ov7670_init_sensor(gspca_dev) < 0) -- return -ENODEV; -+ ov7670_init_sensor(gspca_dev); -+ if (gspca_dev->usb_err < 0) -+ break; - pr_info("OV7670 sensor detected\n"); - break; - case SENSOR_MT9VPRB: -- if (mt9v_init_sensor(gspca_dev) < 0) -- return -ENODEV; -+ mt9v_init_sensor(gspca_dev); -+ if (gspca_dev->usb_err < 0) -+ break; -+ pr_info("MT9VPRB sensor detected\n"); - break; - case SENSOR_MT9M111: -- if (mt9m111_init_sensor(gspca_dev) < 0) -- return -ENODEV; -+ mt9m111_init_sensor(gspca_dev); -+ if (gspca_dev->usb_err < 0) -+ break; - pr_info("MT9M111 sensor detected\n"); - break; - case SENSOR_MT9M112: -- if (mt9m112_init_sensor(gspca_dev) < 0) -- return -ENODEV; -+ mt9m112_init_sensor(gspca_dev); -+ if (gspca_dev->usb_err < 0) -+ break; - pr_info("MT9M112 sensor detected\n"); - break; - case SENSOR_MT9M001: -- if (mt9m001_init_sensor(gspca_dev) < 0) -- return -ENODEV; -+ mt9m001_init_sensor(gspca_dev); -+ if (gspca_dev->usb_err < 0) -+ break; - break; - case SENSOR_HV7131R: -- if (hv7131r_init_sensor(gspca_dev) < 0) -- return -ENODEV; -+ hv7131r_init_sensor(gspca_dev); -+ if (gspca_dev->usb_err < 0) -+ break; - pr_info("HV7131R sensor detected\n"); - break; - default: -- pr_info("Unsupported Sensor\n"); -- return -ENODEV; -+ pr_err("Unsupported sensor\n"); -+ gspca_dev->usb_err = -ENODEV; - } - -- return 0; -+ return gspca_dev->usb_err; - } - - static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode) - { - struct sd *sd = (struct sd *) gspca_dev; - u8 value; -+ - switch (sd->sensor) { - case SENSOR_SOI968: - if (mode & MODE_SXGA) { -@@ -2264,6 +2040,7 @@ static int sd_isoc_init(struct gspca_dev - break; - default: /* >= 640x480 */ - gspca_dev->alt = 9; -+ break; - } - } - -@@ -2290,14 +2067,15 @@ static int sd_start(struct gspca_dev *gs - - jpeg_define(sd->jpeg_hdr, height, width, - 0x21); -- jpeg_set_qual(sd->jpeg_hdr, sd->quality); -+ jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); - - if (mode & MODE_RAW) - fmt = 0x2d; - else if (mode & MODE_JPEG) -- fmt = 0x2c; -+ fmt = 0x24; - else - fmt = 0x2f; /* YUV 420 */ -+ sd->fmt = fmt; - - switch (mode & SCALE_MASK) { - case SCALE_1280x1024: -@@ -2334,18 +2112,37 @@ static int sd_start(struct gspca_dev *gs - set_hvflip(gspca_dev); - - reg_w1(gspca_dev, 0x1007, 0x20); -+ reg_w1(gspca_dev, 0x1061, 0x03); - -- reg_r(gspca_dev, 0x1061, 1); -- reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02); -- return 0; -+ /* if JPEG, prepare the compression quality update */ -+ if (mode & MODE_JPEG) { -+ sd->pktsz = sd->npkt = 0; -+ sd->nchg = 0; -+ sd->work_thread = -+ create_singlethread_workqueue(KBUILD_MODNAME); -+ } -+ -+ return gspca_dev->usb_err; - } - - static void sd_stopN(struct gspca_dev *gspca_dev) - { - reg_w1(gspca_dev, 0x1007, 0x00); -+ reg_w1(gspca_dev, 0x1061, 0x01); -+} - -- reg_r(gspca_dev, 0x1061, 1); -- reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02); -+/* called on streamoff with alt==0 and on disconnect */ -+/* the usb_lock is held at entry - restore on exit */ -+static void sd_stop0(struct gspca_dev *gspca_dev) -+{ -+ struct sd *sd = (struct sd *) gspca_dev; -+ -+ if (sd->work_thread != NULL) { -+ mutex_unlock(&gspca_dev->usb_lock); -+ destroy_workqueue(sd->work_thread); -+ mutex_lock(&gspca_dev->usb_lock); -+ sd->work_thread = NULL; -+ } - } - - static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum) -@@ -2359,15 +2156,15 @@ static void do_autoexposure(struct gspca - * and exposure steps - */ - if (avg_lum < MIN_AVG_LUM) { -- if (sd->exposure > 0x1770) -+ if (sd->ctrls[EXPOSURE].val > 0x1770) - return; - -- new_exp = sd->exposure + sd->exposure_step; -+ new_exp = sd->ctrls[EXPOSURE].val + sd->exposure_step; - if (new_exp > 0x1770) - new_exp = 0x1770; - if (new_exp < 0x10) - new_exp = 0x10; -- sd->exposure = new_exp; -+ sd->ctrls[EXPOSURE].val = new_exp; - set_exposure(gspca_dev); - - sd->older_step = sd->old_step; -@@ -2379,14 +2176,14 @@ static void do_autoexposure(struct gspca - sd->exposure_step += 2; - } - if (avg_lum > MAX_AVG_LUM) { -- if (sd->exposure < 0x10) -+ if (sd->ctrls[EXPOSURE].val < 0x10) - return; -- new_exp = sd->exposure - sd->exposure_step; -+ new_exp = sd->ctrls[EXPOSURE].val - sd->exposure_step; - if (new_exp > 0x1700) - new_exp = 0x1770; - if (new_exp < 0x10) - new_exp = 0x10; -- sd->exposure = new_exp; -+ sd->ctrls[EXPOSURE].val = new_exp; - set_exposure(gspca_dev); - sd->older_step = sd->old_step; - sd->old_step = 0; -@@ -2403,14 +2200,14 @@ static void do_autogain(struct gspca_dev - struct sd *sd = (struct sd *) gspca_dev; - - if (avg_lum < MIN_AVG_LUM) { -- if (sd->gain + 1 <= 28) { -- sd->gain++; -+ if (sd->ctrls[GAIN].val + 1 <= 28) { -+ sd->ctrls[GAIN].val++; - set_gain(gspca_dev); - } - } - if (avg_lum > MAX_AVG_LUM) { -- if (sd->gain > 0) { -- sd->gain--; -+ if (sd->ctrls[GAIN].val > 0) { -+ sd->ctrls[GAIN].val--; - set_gain(gspca_dev); - } - } -@@ -2421,7 +2218,7 @@ static void sd_dqcallback(struct gspca_d - struct sd *sd = (struct sd *) gspca_dev; - int avg_lum; - -- if (!sd->auto_exposure) -+ if (!sd->ctrls[AUTOGAIN].val) - return; - - avg_lum = atomic_read(&sd->avg_lum); -@@ -2431,33 +2228,92 @@ static void sd_dqcallback(struct gspca_d - do_autoexposure(gspca_dev, avg_lum); - } - -+/* JPEG quality update */ -+/* This function is executed from a work queue. */ -+static void qual_upd(struct work_struct *work) -+{ -+ struct sd *sd = container_of(work, struct sd, work); -+ struct gspca_dev *gspca_dev = &sd->gspca_dev; -+ -+ mutex_lock(&gspca_dev->usb_lock); -+ PDEBUG(D_STREAM, "qual_upd %d%%", sd->ctrls[QUALITY].val); -+ set_quality(gspca_dev); -+ mutex_unlock(&gspca_dev->usb_lock); -+} -+ - #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* interrupt packet */ - int len) /* interrupt packet length */ - { - struct sd *sd = (struct sd *) gspca_dev; -- int ret = -EINVAL; -+ - if (!(sd->flags & HAS_NO_BUTTON) && len == 1) { -- input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); -- input_sync(gspca_dev->input_dev); -- input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); -- input_sync(gspca_dev->input_dev); -- ret = 0; -+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); -+ input_sync(gspca_dev->input_dev); -+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); -+ input_sync(gspca_dev->input_dev); -+ return 0; - } -- return ret; -+ return -EINVAL; - } - #endif - -+/* check the JPEG compression */ -+static void transfer_check(struct gspca_dev *gspca_dev, -+ u8 *data) -+{ -+ struct sd *sd = (struct sd *) gspca_dev; -+ int new_qual, r; -+ -+ new_qual = 0; -+ -+ /* if USB error, discard the frame and decrease the quality */ -+ if (data[6] & 0x08) { /* USB FIFO full */ -+ gspca_dev->last_packet_type = DISCARD_PACKET; -+ new_qual = -5; -+ } else { -+ -+ /* else, compute the filling rate and a new JPEG quality */ -+ r = (sd->pktsz * 100) / -+ (sd->npkt * -+ gspca_dev->urb[0]->iso_frame_desc[0].length); -+ if (r >= 85) -+ new_qual = -3; -+ else if (r < 75) -+ new_qual = 2; -+ } -+ if (new_qual != 0) { -+ sd->nchg += new_qual; -+ if (sd->nchg < -6 || sd->nchg >= 12) { -+ sd->nchg = 0; -+ new_qual += sd->ctrls[QUALITY].val; -+ if (new_qual < QUALITY_MIN) -+ new_qual = QUALITY_MIN; -+ else if (new_qual > QUALITY_MAX) -+ new_qual = QUALITY_MAX; -+ if (new_qual != sd->ctrls[QUALITY].val) { -+ sd->ctrls[QUALITY].val = new_qual; -+ queue_work(sd->work_thread, &sd->work); -+ } -+ } -+ } else { -+ sd->nchg = 0; -+ } -+ sd->pktsz = sd->npkt = 0; -+} -+ - static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ - { - struct sd *sd = (struct sd *) gspca_dev; -- int avg_lum; -+ int avg_lum, is_jpeg; - static u8 frame_header[] = - {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; -- if (len == 64 && memcmp(data, frame_header, 6) == 0) { -+ -+ is_jpeg = (sd->fmt & 0x03) == 0; -+ if (len >= 64 && memcmp(data, frame_header, 6) == 0) { - avg_lum = ((data[35] >> 2) & 3) | - (data[20] << 2) | - (data[19] << 10); -@@ -2484,12 +2340,18 @@ static void sd_pkt_scan(struct gspca_dev - (data[33] << 10); - avg_lum >>= 9; - atomic_set(&sd->avg_lum, avg_lum); -+ -+ if (is_jpeg) -+ transfer_check(gspca_dev, data); -+ - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); -- return; -+ len -= 64; -+ if (len == 0) -+ return; -+ data += 64; - } - if (gspca_dev->last_packet_type == LAST_PACKET) { -- if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv -- & MODE_JPEG) { -+ if (is_jpeg) { - gspca_frame_add(gspca_dev, FIRST_PACKET, - sd->jpeg_hdr, JPEG_HDR_SZ); - gspca_frame_add(gspca_dev, INTER_PACKET, -@@ -2499,13 +2361,18 @@ static void sd_pkt_scan(struct gspca_dev - data, len); - } - } else { -+ /* if JPEG, count the packets and their size */ -+ if (is_jpeg) { -+ sd->npkt++; -+ sd->pktsz += len; -+ } - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); - } - } - - /* sub-driver description */ - static const struct sd_desc sd_desc = { -- .name = MODULE_NAME, -+ .name = KBUILD_MODNAME, - .ctrls = sd_ctrls, - .nctrls = ARRAY_SIZE(sd_ctrls), - .config = sd_config, -@@ -2513,6 +2380,7 @@ static const struct sd_desc sd_desc = { - .isoc_init = sd_isoc_init, - .start = sd_start, - .stopN = sd_stopN, -+ .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, - #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .int_pkt_scan = sd_int_pkt_scan, -@@ -2581,7 +2449,7 @@ static int sd_probe(struct usb_interface - } - - static struct usb_driver sd_driver = { -- .name = MODULE_NAME, -+ .name = KBUILD_MODNAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -Index: linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-udma.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/ivtv/ivtv-udma.c -+++ linux-3.3.x86_64/drivers/media/video/ivtv/ivtv-udma.c -@@ -57,9 +57,9 @@ int ivtv_udma_fill_sg_list (struct ivtv_ - if (dma->bouncemap[map_offset] == NULL) - return -1; - local_irq_save(flags); -- src = kmap_atomic(dma->map[map_offset], KM_BOUNCE_READ) + offset; -+ src = kmap_atomic(dma->map[map_offset]) + offset; - memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len); -- kunmap_atomic(src, KM_BOUNCE_READ); -+ kunmap_atomic(src); - local_irq_restore(flags); - sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset], len, offset); - } -Index: linux-3.3.x86_64/drivers/media/video/videobuf2-core.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/videobuf2-core.c -+++ linux-3.3.x86_64/drivers/media/video/videobuf2-core.c -@@ -19,6 +19,9 @@ - #include - #include - -+#include -+#include -+#include - #include - - static int debug; -@@ -1642,32 +1645,46 @@ static int __vb2_cleanup_fileio(struct v - * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor - * will be reported as available for writing. - * -+ * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any -+ * pending events. -+ * - * The return values from this function are intended to be directly returned - * from poll handler in driver. - */ - unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) - { -- unsigned long flags; -- unsigned int ret; -+ struct video_device *vfd = video_devdata(file); -+ unsigned long req_events = poll_requested_events(wait); - struct vb2_buffer *vb = NULL; -+ unsigned int res = 0; -+ unsigned long flags; -+ -+ if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { -+ struct v4l2_fh *fh = file->private_data; -+ -+ if (v4l2_event_pending(fh)) -+ res = POLLPRI; -+ else if (req_events & POLLPRI) -+ poll_wait(file, &fh->wait, wait); -+ } - - /* - * Start file I/O emulator only if streaming API has not been used yet. - */ - if (q->num_buffers == 0 && q->fileio == NULL) { -- if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ)) { -- ret = __vb2_init_fileio(q, 1); -- if (ret) -- return POLLERR; -+ if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) && -+ (req_events & (POLLIN | POLLRDNORM))) { -+ if (__vb2_init_fileio(q, 1)) -+ return res | POLLERR; - } -- if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE)) { -- ret = __vb2_init_fileio(q, 0); -- if (ret) -- return POLLERR; -+ if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE) && -+ (req_events & (POLLOUT | POLLWRNORM))) { -+ if (__vb2_init_fileio(q, 0)) -+ return res | POLLERR; - /* - * Write to OUTPUT queue can be done immediately. - */ -- return POLLOUT | POLLWRNORM; -+ return res | POLLOUT | POLLWRNORM; - } - } - -@@ -1675,7 +1692,7 @@ unsigned int vb2_poll(struct vb2_queue * - * There is nothing to wait for if no buffers have already been queued. - */ - if (list_empty(&q->queued_list)) -- return POLLERR; -+ return res | POLLERR; - - poll_wait(file, &q->done_wq, wait); - -@@ -1690,10 +1707,11 @@ unsigned int vb2_poll(struct vb2_queue * - - if (vb && (vb->state == VB2_BUF_STATE_DONE - || vb->state == VB2_BUF_STATE_ERROR)) { -- return (V4L2_TYPE_IS_OUTPUT(q->type)) ? POLLOUT | POLLWRNORM : -- POLLIN | POLLRDNORM; -+ return (V4L2_TYPE_IS_OUTPUT(q->type)) ? -+ res | POLLOUT | POLLWRNORM : -+ res | POLLIN | POLLRDNORM; - } -- return 0; -+ return res; - } - EXPORT_SYMBOL_GPL(vb2_poll); - -Index: linux-3.3.x86_64/drivers/media/video/videobuf-core.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/videobuf-core.c -+++ linux-3.3.x86_64/drivers/media/video/videobuf-core.c -@@ -1129,6 +1129,7 @@ unsigned int videobuf_poll_stream(struct - struct videobuf_queue *q, - poll_table *wait) - { -+ unsigned long req_events = poll_requested_events(wait); - struct videobuf_buffer *buf = NULL; - unsigned int rc = 0; - -@@ -1137,7 +1138,7 @@ unsigned int videobuf_poll_stream(struct - if (!list_empty(&q->stream)) - buf = list_entry(q->stream.next, - struct videobuf_buffer, stream); -- } else { -+ } else if (req_events & (POLLIN | POLLRDNORM)) { - if (!q->reading) - __videobuf_read_start(q); - if (!q->reading) { -Index: linux-3.3.x86_64/drivers/media/video/pwc/pwc-if.c -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/video/pwc/pwc-if.c -+++ linux-3.3.x86_64/drivers/media/video/pwc/pwc-if.c -@@ -625,10 +625,19 @@ static ssize_t pwc_video_read(struct fil - static unsigned int pwc_video_poll(struct file *file, poll_table *wait) - { - struct pwc_device *pdev = video_drvdata(file); -+ unsigned long req_events = poll_requested_events(wait); - - if (!pdev->udev) - return POLL_ERR; - -+ if ((req_events & (POLLIN | POLLRDNORM)) && -+ pdev->vb_queue.num_buffers == 0 && -+ !pdev->iso_init) { -+ /* This poll will start a read stream, check capt_file */ -+ if (pwc_test_n_set_capt_file(pdev, file)) -+ return POLL_ERR; -+ } -+ - return vb2_poll(&pdev->vb_queue, file, wait); - } - -Index: linux-3.3.x86_64/drivers/media/common/tuners/Kconfig -=================================================================== ---- linux-3.3.x86_64.orig/drivers/media/common/tuners/Kconfig -+++ linux-3.3.x86_64/drivers/media/common/tuners/Kconfig -@@ -204,6 +204,13 @@ config MEDIA_TUNER_TDA18218 - help - NXP TDA18218 silicon tuner driver. - -+config MEDIA_TUNER_FC0011 -+ tristate "Fitipower FC0011 silicon tuner" -+ depends on VIDEO_MEDIA && I2C -+ default m if MEDIA_TUNER_CUSTOMISE -+ help -+ Fitipower FC0011 silicon tuner driver. -+ - config MEDIA_TUNER_TDA18212 - tristate "NXP TDA18212 silicon tuner" - depends on VIDEO_MEDIA && I2C -@@ -211,4 +218,10 @@ config MEDIA_TUNER_TDA18212 - help - NXP TDA18212 silicon tuner driver. - -+config MEDIA_TUNER_TUA9001 -+ tristate "Infineon TUA 9001 silicon tuner" -+ depends on VIDEO_MEDIA && I2C -+ default m if MEDIA_TUNER_CUSTOMISE -+ help -+ Infineon TUA 9001 silicon tuner driver. - endmenu -Index: linux-3.3.x86_64/drivers/media/common/tuners/tua9001.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/common/tuners/tua9001.c -@@ -0,0 +1,215 @@ -+/* -+ * Infineon TUA 9001 silicon tuner driver -+ * -+ * Copyright (C) 2009 Antti Palosaari -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#include "tua9001.h" -+#include "tua9001_priv.h" -+ -+/* write register */ -+static int tua9001_wr_reg(struct tua9001_priv *priv, u8 reg, u16 val) -+{ -+ int ret; -+ u8 buf[3] = { reg, (val >> 8) & 0xff, (val >> 0) & 0xff }; -+ struct i2c_msg msg[1] = { -+ { -+ .addr = priv->cfg->i2c_addr, -+ .flags = 0, -+ .len = sizeof(buf), -+ .buf = buf, -+ } -+ }; -+ -+ ret = i2c_transfer(priv->i2c, msg, 1); -+ if (ret == 1) { -+ ret = 0; -+ } else { -+ printk(KERN_WARNING "%s: I2C wr failed=%d reg=%02x\n", -+ __func__, ret, reg); -+ ret = -EREMOTEIO; -+ } -+ -+ return ret; -+} -+ -+static int tua9001_release(struct dvb_frontend *fe) -+{ -+ kfree(fe->tuner_priv); -+ fe->tuner_priv = NULL; -+ -+ return 0; -+} -+ -+static int tua9001_init(struct dvb_frontend *fe) -+{ -+ struct tua9001_priv *priv = fe->tuner_priv; -+ int ret = 0; -+ u8 i; -+ struct reg_val data[] = { -+ { 0x1e, 0x6512 }, -+ { 0x25, 0xb888 }, -+ { 0x39, 0x5460 }, -+ { 0x3b, 0x00c0 }, -+ { 0x3a, 0xf000 }, -+ { 0x08, 0x0000 }, -+ { 0x32, 0x0030 }, -+ { 0x41, 0x703a }, -+ { 0x40, 0x1c78 }, -+ { 0x2c, 0x1c00 }, -+ { 0x36, 0xc013 }, -+ { 0x37, 0x6f18 }, -+ { 0x27, 0x0008 }, -+ { 0x2a, 0x0001 }, -+ { 0x34, 0x0a40 }, -+ }; -+ -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */ -+ -+ for (i = 0; i < ARRAY_SIZE(data); i++) { -+ ret = tua9001_wr_reg(priv, data[i].reg, data[i].val); -+ if (ret) -+ break; -+ } -+ -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */ -+ -+ if (ret < 0) -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+static int tua9001_set_params(struct dvb_frontend *fe) -+{ -+ struct tua9001_priv *priv = fe->tuner_priv; -+ struct dtv_frontend_properties *c = &fe->dtv_property_cache; -+ int ret, i; -+ u16 val; -+ u32 frequency; -+ struct reg_val data[2]; -+ -+ pr_debug("%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n", -+ __func__, c->delivery_system, c->frequency, -+ c->bandwidth_hz); -+ -+ switch (c->delivery_system) { -+ case SYS_DVBT: -+ switch (c->bandwidth_hz) { -+ case 8000000: -+ val = 0x0000; -+ break; -+ case 7000000: -+ val = 0x1000; -+ break; -+ case 6000000: -+ val = 0x2000; -+ break; -+ case 5000000: -+ val = 0x3000; -+ break; -+ default: -+ ret = -EINVAL; -+ goto err; -+ } -+ break; -+ default: -+ ret = -EINVAL; -+ goto err; -+ } -+ -+ data[0].reg = 0x04; -+ data[0].val = val; -+ -+ frequency = (c->frequency - 150000000); -+ frequency /= 100; -+ frequency *= 48; -+ frequency /= 10000; -+ -+ data[1].reg = 0x1f; -+ data[1].val = frequency; -+ -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */ -+ -+ for (i = 0; i < ARRAY_SIZE(data); i++) { -+ ret = tua9001_wr_reg(priv, data[i].reg, data[i].val); -+ if (ret < 0) -+ break; -+ } -+ -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */ -+ -+err: -+ if (ret < 0) -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+static int tua9001_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) -+{ -+ *frequency = 0; /* Zero-IF */ -+ -+ return 0; -+} -+ -+static const struct dvb_tuner_ops tua9001_tuner_ops = { -+ .info = { -+ .name = "Infineon TUA 9001", -+ -+ .frequency_min = 170000000, -+ .frequency_max = 862000000, -+ .frequency_step = 0, -+ }, -+ -+ .release = tua9001_release, -+ -+ .init = tua9001_init, -+ .set_params = tua9001_set_params, -+ -+ .get_if_frequency = tua9001_get_if_frequency, -+}; -+ -+struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, struct tua9001_config *cfg) -+{ -+ struct tua9001_priv *priv = NULL; -+ -+ priv = kzalloc(sizeof(struct tua9001_priv), GFP_KERNEL); -+ if (priv == NULL) -+ return NULL; -+ -+ priv->cfg = cfg; -+ priv->i2c = i2c; -+ -+ printk(KERN_INFO "Infineon TUA 9001 successfully attached."); -+ -+ memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops, -+ sizeof(struct dvb_tuner_ops)); -+ -+ fe->tuner_priv = priv; -+ return fe; -+} -+EXPORT_SYMBOL(tua9001_attach); -+ -+MODULE_DESCRIPTION("Infineon TUA 9001 silicon tuner driver"); -+MODULE_AUTHOR("Antti Palosaari "); -+MODULE_LICENSE("GPL"); -Index: linux-3.3.x86_64/drivers/media/common/tuners/tua9001.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/common/tuners/tua9001.h -@@ -0,0 +1,46 @@ -+/* -+ * Infineon TUA 9001 silicon tuner driver -+ * -+ * Copyright (C) 2009 Antti Palosaari -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#ifndef TUA9001_H -+#define TUA9001_H -+ -+#include "dvb_frontend.h" -+ -+struct tua9001_config { -+ /* -+ * I2C address -+ */ -+ u8 i2c_addr; -+}; -+ -+#if defined(CONFIG_MEDIA_TUNER_TUA9001) || \ -+ (defined(CONFIG_MEDIA_TUNER_TUA9001_MODULE) && defined(MODULE)) -+extern struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, struct tua9001_config *cfg); -+#else -+static inline struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, struct tua9001_config *cfg) -+{ -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+#endif -+ -+#endif -Index: linux-3.3.x86_64/drivers/media/common/tuners/tua9001_priv.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/common/tuners/tua9001_priv.h -@@ -0,0 +1,34 @@ -+/* -+ * Infineon TUA 9001 silicon tuner driver -+ * -+ * Copyright (C) 2009 Antti Palosaari -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#ifndef TUA9001_PRIV_H -+#define TUA9001_PRIV_H -+ -+struct reg_val { -+ u8 reg; -+ u16 val; -+}; -+ -+struct tua9001_priv { -+ struct tua9001_config *cfg; -+ struct i2c_adapter *i2c; -+}; -+ -+#endif -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/af9033.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/af9033.c -@@ -0,0 +1,919 @@ -+/* -+ * Afatech AF9033 demodulator driver -+ * -+ * Copyright (C) 2009 Antti Palosaari -+ * Copyright (C) 2012 Antti Palosaari -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#include "af9033_priv.h" -+ -+struct af9033_state { -+ struct i2c_adapter *i2c; -+ struct dvb_frontend fe; -+ struct af9033_config cfg; -+ -+ u32 bandwidth_hz; -+ bool ts_mode_parallel; -+ bool ts_mode_serial; -+}; -+ -+/* write multiple registers */ -+static int af9033_wr_regs(struct af9033_state *state, u32 reg, const u8 *val, -+ int len) -+{ -+ int ret; -+ u8 buf[3 + len]; -+ struct i2c_msg msg[1] = { -+ { -+ .addr = state->cfg.i2c_addr, -+ .flags = 0, -+ .len = sizeof(buf), -+ .buf = buf, -+ } -+ }; -+ -+ buf[0] = (reg >> 16) & 0xff; -+ buf[1] = (reg >> 8) & 0xff; -+ buf[2] = (reg >> 0) & 0xff; -+ memcpy(&buf[3], val, len); -+ -+ ret = i2c_transfer(state->i2c, msg, 1); -+ if (ret == 1) { -+ ret = 0; -+ } else { -+ printk(KERN_WARNING "%s: i2c wr failed=%d reg=%06x len=%d\n", -+ __func__, ret, reg, len); -+ ret = -EREMOTEIO; -+ } -+ -+ return ret; -+} -+ -+/* read multiple registers */ -+static int af9033_rd_regs(struct af9033_state *state, u32 reg, u8 *val, int len) -+{ -+ int ret; -+ u8 buf[3] = { (reg >> 16) & 0xff, (reg >> 8) & 0xff, -+ (reg >> 0) & 0xff }; -+ struct i2c_msg msg[2] = { -+ { -+ .addr = state->cfg.i2c_addr, -+ .flags = 0, -+ .len = sizeof(buf), -+ .buf = buf -+ }, { -+ .addr = state->cfg.i2c_addr, -+ .flags = I2C_M_RD, -+ .len = len, -+ .buf = val -+ } -+ }; -+ -+ ret = i2c_transfer(state->i2c, msg, 2); -+ if (ret == 2) { -+ ret = 0; -+ } else { -+ printk(KERN_WARNING "%s: i2c rd failed=%d reg=%06x len=%d\n", -+ __func__, ret, reg, len); -+ ret = -EREMOTEIO; -+ } -+ -+ return ret; -+} -+ -+ -+/* write single register */ -+static int af9033_wr_reg(struct af9033_state *state, u32 reg, u8 val) -+{ -+ return af9033_wr_regs(state, reg, &val, 1); -+} -+ -+/* read single register */ -+static int af9033_rd_reg(struct af9033_state *state, u32 reg, u8 *val) -+{ -+ return af9033_rd_regs(state, reg, val, 1); -+} -+ -+/* write single register with mask */ -+static int af9033_wr_reg_mask(struct af9033_state *state, u32 reg, u8 val, -+ u8 mask) -+{ -+ int ret; -+ u8 tmp; -+ -+ /* no need for read if whole reg is written */ -+ if (mask != 0xff) { -+ ret = af9033_rd_regs(state, reg, &tmp, 1); -+ if (ret) -+ return ret; -+ -+ val &= mask; -+ tmp &= ~mask; -+ val |= tmp; -+ } -+ -+ return af9033_wr_regs(state, reg, &val, 1); -+} -+ -+/* read single register with mask */ -+static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val, -+ u8 mask) -+{ -+ int ret, i; -+ u8 tmp; -+ -+ ret = af9033_rd_regs(state, reg, &tmp, 1); -+ if (ret) -+ return ret; -+ -+ tmp &= mask; -+ -+ /* find position of the first bit */ -+ for (i = 0; i < 8; i++) { -+ if ((mask >> i) & 0x01) -+ break; -+ } -+ *val = tmp >> i; -+ -+ return 0; -+} -+ -+static u32 af9033_div(u32 a, u32 b, u32 x) -+{ -+ u32 r = 0, c = 0, i; -+ -+ pr_debug("%s: a=%d b=%d x=%d\n", __func__, a, b, x); -+ -+ if (a > b) { -+ c = a / b; -+ a = a - c * b; -+ } -+ -+ for (i = 0; i < x; i++) { -+ if (a >= b) { -+ r += 1; -+ a -= b; -+ } -+ a <<= 1; -+ r <<= 1; -+ } -+ r = (c << (u32)x) + r; -+ -+ pr_debug("%s: a=%d b=%d x=%d r=%d r=%x\n", __func__, a, b, x, r, r); -+ -+ return r; -+} -+ -+static void af9033_release(struct dvb_frontend *fe) -+{ -+ struct af9033_state *state = fe->demodulator_priv; -+ -+ kfree(state); -+} -+ -+static int af9033_init(struct dvb_frontend *fe) -+{ -+ struct af9033_state *state = fe->demodulator_priv; -+ int ret, i, len; -+ const struct reg_val *init; -+ u8 buf[4]; -+ u32 adc_cw, clock_cw; -+ struct reg_val_mask tab[] = { -+ { 0x80fb24, 0x00, 0x08 }, -+ { 0x80004c, 0x00, 0xff }, -+ { 0x00f641, state->cfg.tuner, 0xff }, -+ { 0x80f5ca, 0x01, 0x01 }, -+ { 0x80f715, 0x01, 0x01 }, -+ { 0x00f41f, 0x04, 0x04 }, -+ { 0x00f41a, 0x01, 0x01 }, -+ { 0x80f731, 0x00, 0x01 }, -+ { 0x00d91e, 0x00, 0x01 }, -+ { 0x00d919, 0x00, 0x01 }, -+ { 0x80f732, 0x00, 0x01 }, -+ { 0x00d91f, 0x00, 0x01 }, -+ { 0x00d91a, 0x00, 0x01 }, -+ { 0x80f730, 0x00, 0x01 }, -+ { 0x80f778, 0x00, 0xff }, -+ { 0x80f73c, 0x01, 0x01 }, -+ { 0x80f776, 0x00, 0x01 }, -+ { 0x00d8fd, 0x01, 0xff }, -+ { 0x00d830, 0x01, 0xff }, -+ { 0x00d831, 0x00, 0xff }, -+ { 0x00d832, 0x00, 0xff }, -+ { 0x80f985, state->ts_mode_serial, 0x01 }, -+ { 0x80f986, state->ts_mode_parallel, 0x01 }, -+ { 0x00d827, 0x00, 0xff }, -+ { 0x00d829, 0x00, 0xff }, -+ }; -+ -+ /* program clock control */ -+ clock_cw = af9033_div(state->cfg.clock, 1000000ul, 19ul); -+ buf[0] = (clock_cw >> 0) & 0xff; -+ buf[1] = (clock_cw >> 8) & 0xff; -+ buf[2] = (clock_cw >> 16) & 0xff; -+ buf[3] = (clock_cw >> 24) & 0xff; -+ -+ pr_debug("%s: clock=%d clock_cw=%08x\n", __func__, state->cfg.clock, -+ clock_cw); -+ -+ ret = af9033_wr_regs(state, 0x800025, buf, 4); -+ if (ret < 0) -+ goto err; -+ -+ /* program ADC control */ -+ for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { -+ if (clock_adc_lut[i].clock == state->cfg.clock) -+ break; -+ } -+ -+ adc_cw = af9033_div(clock_adc_lut[i].adc, 1000000ul, 19ul); -+ buf[0] = (adc_cw >> 0) & 0xff; -+ buf[1] = (adc_cw >> 8) & 0xff; -+ buf[2] = (adc_cw >> 16) & 0xff; -+ -+ pr_debug("%s: adc=%d adc_cw=%06x\n", __func__, clock_adc_lut[i].adc, -+ adc_cw); -+ -+ ret = af9033_wr_regs(state, 0x80f1cd, buf, 3); -+ if (ret < 0) -+ goto err; -+ -+ /* program register table */ -+ for (i = 0; i < ARRAY_SIZE(tab); i++) { -+ ret = af9033_wr_reg_mask(state, tab[i].reg, tab[i].val, -+ tab[i].mask); -+ if (ret < 0) -+ goto err; -+ } -+ -+ /* settings for TS interface */ -+ if (state->cfg.ts_mode == AF9033_TS_MODE_USB) { -+ ret = af9033_wr_reg_mask(state, 0x80f9a5, 0x00, 0x01); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x01, 0x01); -+ if (ret < 0) -+ goto err; -+ } else { -+ ret = af9033_wr_reg_mask(state, 0x80f990, 0x00, 0x01); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x00, 0x01); -+ if (ret < 0) -+ goto err; -+ } -+ -+ /* load OFSM settings */ -+ pr_debug("%s: load ofsm settings\n", __func__); -+ len = ARRAY_SIZE(ofsm_init); -+ init = ofsm_init; -+ for (i = 0; i < len; i++) { -+ ret = af9033_wr_reg(state, init[i].reg, init[i].val); -+ if (ret < 0) -+ goto err; -+ } -+ -+ /* load tuner specific settings */ -+ pr_debug("%s: load tuner specific settings\n", -+ __func__); -+ switch (state->cfg.tuner) { -+ case AF9033_TUNER_TUA9001: -+ len = ARRAY_SIZE(tuner_init_tua9001); -+ init = tuner_init_tua9001; -+ break; -+ case AF9033_TUNER_FC0011: -+ len = ARRAY_SIZE(tuner_init_fc0011); -+ init = tuner_init_fc0011; -+ break; -+ case AF9033_TUNER_MXL5007T: -+ len = ARRAY_SIZE(tuner_init_mxl5007t); -+ init = tuner_init_mxl5007t; -+ break; -+ case AF9033_TUNER_TDA18218: -+ len = ARRAY_SIZE(tuner_init_tda18218); -+ init = tuner_init_tda18218; -+ break; -+ default: -+ pr_debug("%s: unsupported tuner ID=%d\n", __func__, -+ state->cfg.tuner); -+ ret = -ENODEV; -+ goto err; -+ } -+ -+ for (i = 0; i < len; i++) { -+ ret = af9033_wr_reg(state, init[i].reg, init[i].val); -+ if (ret < 0) -+ goto err; -+ } -+ -+ state->bandwidth_hz = 0; /* force to program all parameters */ -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+static int af9033_sleep(struct dvb_frontend *fe) -+{ -+ struct af9033_state *state = fe->demodulator_priv; -+ int ret, i; -+ u8 tmp; -+ -+ ret = af9033_wr_reg(state, 0x80004c, 1); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9033_wr_reg(state, 0x800000, 0); -+ if (ret < 0) -+ goto err; -+ -+ for (i = 100, tmp = 1; i && tmp; i--) { -+ ret = af9033_rd_reg(state, 0x80004c, &tmp); -+ if (ret < 0) -+ goto err; -+ -+ usleep_range(200, 10000); -+ } -+ -+ pr_debug("%s: loop=%d\n", __func__, i); -+ -+ if (i == 0) { -+ ret = -ETIMEDOUT; -+ goto err; -+ } -+ -+ ret = af9033_wr_reg_mask(state, 0x80fb24, 0x08, 0x08); -+ if (ret < 0) -+ goto err; -+ -+ /* prevent current leak (?) */ -+ if (state->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { -+ /* enable parallel TS */ -+ ret = af9033_wr_reg_mask(state, 0x00d917, 0x00, 0x01); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9033_wr_reg_mask(state, 0x00d916, 0x01, 0x01); -+ if (ret < 0) -+ goto err; -+ } -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+static int af9033_get_tune_settings(struct dvb_frontend *fe, -+ struct dvb_frontend_tune_settings *fesettings) -+{ -+ fesettings->min_delay_ms = 800; -+ fesettings->step_size = 0; -+ fesettings->max_drift = 0; -+ -+ return 0; -+} -+ -+static int af9033_set_frontend(struct dvb_frontend *fe) -+{ -+ struct af9033_state *state = fe->demodulator_priv; -+ struct dtv_frontend_properties *c = &fe->dtv_property_cache; -+ int ret, i, spec_inv; -+ u8 tmp, buf[3], bandwidth_reg_val; -+ u32 if_frequency, freq_cw, adc_freq; -+ -+ pr_debug("%s: frequency=%d bandwidth_hz=%d\n", __func__, c->frequency, -+ c->bandwidth_hz); -+ -+ /* check bandwidth */ -+ switch (c->bandwidth_hz) { -+ case 6000000: -+ bandwidth_reg_val = 0x00; -+ break; -+ case 7000000: -+ bandwidth_reg_val = 0x01; -+ break; -+ case 8000000: -+ bandwidth_reg_val = 0x02; -+ break; -+ default: -+ pr_debug("%s: invalid bandwidth_hz\n", __func__); -+ ret = -EINVAL; -+ goto err; -+ } -+ -+ /* program tuner */ -+ if (fe->ops.tuner_ops.set_params) -+ fe->ops.tuner_ops.set_params(fe); -+ -+ /* program CFOE coefficients */ -+ if (c->bandwidth_hz != state->bandwidth_hz) { -+ for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) { -+ if (coeff_lut[i].clock == state->cfg.clock && -+ coeff_lut[i].bandwidth_hz == c->bandwidth_hz) { -+ break; -+ } -+ } -+ ret = af9033_wr_regs(state, 0x800001, -+ coeff_lut[i].val, sizeof(coeff_lut[i].val)); -+ } -+ -+ /* program frequency control */ -+ if (c->bandwidth_hz != state->bandwidth_hz) { -+ spec_inv = state->cfg.spec_inv ? -1 : 1; -+ -+ for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { -+ if (clock_adc_lut[i].clock == state->cfg.clock) -+ break; -+ } -+ adc_freq = clock_adc_lut[i].adc; -+ -+ /* get used IF frequency */ -+ if (fe->ops.tuner_ops.get_if_frequency) -+ fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency); -+ else -+ if_frequency = 0; -+ -+ while (if_frequency > (adc_freq / 2)) -+ if_frequency -= adc_freq; -+ -+ if (if_frequency >= 0) -+ spec_inv *= -1; -+ else -+ if_frequency *= -1; -+ -+ freq_cw = af9033_div(if_frequency, adc_freq, 23ul); -+ -+ if (spec_inv == -1) -+ freq_cw *= -1; -+ -+ /* get adc multiplies */ -+ ret = af9033_rd_reg(state, 0x800045, &tmp); -+ if (ret < 0) -+ goto err; -+ -+ if (tmp == 1) -+ freq_cw /= 2; -+ -+ buf[0] = (freq_cw >> 0) & 0xff; -+ buf[1] = (freq_cw >> 8) & 0xff; -+ buf[2] = (freq_cw >> 16) & 0x7f; -+ ret = af9033_wr_regs(state, 0x800029, buf, 3); -+ if (ret < 0) -+ goto err; -+ -+ state->bandwidth_hz = c->bandwidth_hz; -+ } -+ -+ ret = af9033_wr_reg_mask(state, 0x80f904, bandwidth_reg_val, 0x03); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9033_wr_reg(state, 0x800040, 0x00); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9033_wr_reg(state, 0x800047, 0x00); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9033_wr_reg_mask(state, 0x80f999, 0x00, 0x01); -+ if (ret < 0) -+ goto err; -+ -+ if (c->frequency <= 230000000) -+ tmp = 0x00; /* VHF */ -+ else -+ tmp = 0x01; /* UHF */ -+ -+ ret = af9033_wr_reg(state, 0x80004b, tmp); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9033_wr_reg(state, 0x800000, 0x00); -+ if (ret < 0) -+ goto err; -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+static int af9033_get_frontend(struct dvb_frontend *fe) -+{ -+ struct af9033_state *state = fe->demodulator_priv; -+ struct dtv_frontend_properties *c = &fe->dtv_property_cache; -+ int ret; -+ u8 buf[8]; -+ -+ pr_debug("%s\n", __func__); -+ -+ /* read all needed registers */ -+ ret = af9033_rd_regs(state, 0x80f900, buf, sizeof(buf)); -+ if (ret < 0) -+ goto err; -+ -+ switch ((buf[0] >> 0) & 3) { -+ case 0: -+ c->transmission_mode = TRANSMISSION_MODE_2K; -+ break; -+ case 1: -+ c->transmission_mode = TRANSMISSION_MODE_8K; -+ break; -+ } -+ -+ switch ((buf[1] >> 0) & 3) { -+ case 0: -+ c->guard_interval = GUARD_INTERVAL_1_32; -+ break; -+ case 1: -+ c->guard_interval = GUARD_INTERVAL_1_16; -+ break; -+ case 2: -+ c->guard_interval = GUARD_INTERVAL_1_8; -+ break; -+ case 3: -+ c->guard_interval = GUARD_INTERVAL_1_4; -+ break; -+ } -+ -+ switch ((buf[2] >> 0) & 7) { -+ case 0: -+ c->hierarchy = HIERARCHY_NONE; -+ break; -+ case 1: -+ c->hierarchy = HIERARCHY_1; -+ break; -+ case 2: -+ c->hierarchy = HIERARCHY_2; -+ break; -+ case 3: -+ c->hierarchy = HIERARCHY_4; -+ break; -+ } -+ -+ switch ((buf[3] >> 0) & 3) { -+ case 0: -+ c->modulation = QPSK; -+ break; -+ case 1: -+ c->modulation = QAM_16; -+ break; -+ case 2: -+ c->modulation = QAM_64; -+ break; -+ } -+ -+ switch ((buf[4] >> 0) & 3) { -+ case 0: -+ c->bandwidth_hz = 6000000; -+ break; -+ case 1: -+ c->bandwidth_hz = 7000000; -+ break; -+ case 2: -+ c->bandwidth_hz = 8000000; -+ break; -+ } -+ -+ switch ((buf[6] >> 0) & 7) { -+ case 0: -+ c->code_rate_HP = FEC_1_2; -+ break; -+ case 1: -+ c->code_rate_HP = FEC_2_3; -+ break; -+ case 2: -+ c->code_rate_HP = FEC_3_4; -+ break; -+ case 3: -+ c->code_rate_HP = FEC_5_6; -+ break; -+ case 4: -+ c->code_rate_HP = FEC_7_8; -+ break; -+ case 5: -+ c->code_rate_HP = FEC_NONE; -+ break; -+ } -+ -+ switch ((buf[7] >> 0) & 7) { -+ case 0: -+ c->code_rate_LP = FEC_1_2; -+ break; -+ case 1: -+ c->code_rate_LP = FEC_2_3; -+ break; -+ case 2: -+ c->code_rate_LP = FEC_3_4; -+ break; -+ case 3: -+ c->code_rate_LP = FEC_5_6; -+ break; -+ case 4: -+ c->code_rate_LP = FEC_7_8; -+ break; -+ case 5: -+ c->code_rate_LP = FEC_NONE; -+ break; -+ } -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+static int af9033_read_status(struct dvb_frontend *fe, fe_status_t *status) -+{ -+ struct af9033_state *state = fe->demodulator_priv; -+ int ret; -+ u8 tmp; -+ -+ *status = 0; -+ -+ /* radio channel status, 0=no result, 1=has signal, 2=no signal */ -+ ret = af9033_rd_reg(state, 0x800047, &tmp); -+ if (ret < 0) -+ goto err; -+ -+ /* has signal */ -+ if (tmp == 0x01) -+ *status |= FE_HAS_SIGNAL; -+ -+ if (tmp != 0x02) { -+ /* TPS lock */ -+ ret = af9033_rd_reg_mask(state, 0x80f5a9, &tmp, 0x01); -+ if (ret < 0) -+ goto err; -+ -+ if (tmp) -+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | -+ FE_HAS_VITERBI; -+ -+ /* full lock */ -+ ret = af9033_rd_reg_mask(state, 0x80f999, &tmp, 0x01); -+ if (ret < 0) -+ goto err; -+ -+ if (tmp) -+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | -+ FE_HAS_VITERBI | FE_HAS_SYNC | -+ FE_HAS_LOCK; -+ } -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+static int af9033_read_snr(struct dvb_frontend *fe, u16 *snr) -+{ -+ struct af9033_state *state = fe->demodulator_priv; -+ int ret, i, len; -+ u8 buf[3], tmp; -+ u32 snr_val; -+ const struct val_snr *uninitialized_var(snr_lut); -+ -+ /* read value */ -+ ret = af9033_rd_regs(state, 0x80002c, buf, 3); -+ if (ret < 0) -+ goto err; -+ -+ snr_val = (buf[2] << 16) | (buf[1] << 8) | buf[0]; -+ -+ /* read current modulation */ -+ ret = af9033_rd_reg(state, 0x80f903, &tmp); -+ if (ret < 0) -+ goto err; -+ -+ switch ((tmp >> 0) & 3) { -+ case 0: -+ len = ARRAY_SIZE(qpsk_snr_lut); -+ snr_lut = qpsk_snr_lut; -+ break; -+ case 1: -+ len = ARRAY_SIZE(qam16_snr_lut); -+ snr_lut = qam16_snr_lut; -+ break; -+ case 2: -+ len = ARRAY_SIZE(qam64_snr_lut); -+ snr_lut = qam64_snr_lut; -+ break; -+ default: -+ goto err; -+ } -+ -+ for (i = 0; i < len; i++) { -+ tmp = snr_lut[i].snr; -+ -+ if (snr_val < snr_lut[i].val) -+ break; -+ } -+ -+ *snr = tmp * 10; /* dB/10 */ -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+static int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength) -+{ -+ struct af9033_state *state = fe->demodulator_priv; -+ int ret; -+ u8 strength2; -+ -+ /* read signal strength of 0-100 scale */ -+ ret = af9033_rd_reg(state, 0x800048, &strength2); -+ if (ret < 0) -+ goto err; -+ -+ /* scale value to 0x0000-0xffff */ -+ *strength = strength2 * 0xffff / 100; -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+static int af9033_read_ber(struct dvb_frontend *fe, u32 *ber) -+{ -+ *ber = 0; -+ -+ return 0; -+} -+ -+static int af9033_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -+{ -+ *ucblocks = 0; -+ -+ return 0; -+} -+ -+static int af9033_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) -+{ -+ struct af9033_state *state = fe->demodulator_priv; -+ int ret; -+ -+ pr_debug("%s: enable=%d\n", __func__, enable); -+ -+ ret = af9033_wr_reg_mask(state, 0x00fa04, enable, 0x01); -+ if (ret < 0) -+ goto err; -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+static struct dvb_frontend_ops af9033_ops; -+ -+struct dvb_frontend *af9033_attach(const struct af9033_config *config, -+ struct i2c_adapter *i2c) -+{ -+ int ret; -+ struct af9033_state *state; -+ u8 buf[8]; -+ -+ pr_debug("%s:\n", __func__); -+ -+ /* allocate memory for the internal state */ -+ state = kzalloc(sizeof(struct af9033_state), GFP_KERNEL); -+ if (state == NULL) -+ goto err; -+ -+ /* setup the state */ -+ state->i2c = i2c; -+ memcpy(&state->cfg, config, sizeof(struct af9033_config)); -+ -+ if (state->cfg.clock != 12000000) { -+ printk(KERN_INFO "af9033: unsupported clock=%d, only " \ -+ "12000000 Hz is supported currently\n", -+ state->cfg.clock); -+ goto err; -+ } -+ -+ /* firmware version */ -+ ret = af9033_rd_regs(state, 0x0083e9, &buf[0], 4); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9033_rd_regs(state, 0x804191, &buf[4], 4); -+ if (ret < 0) -+ goto err; -+ -+ printk(KERN_INFO "af9033: firmware version: LINK=%d.%d.%d.%d " \ -+ "OFDM=%d.%d.%d.%d\n", buf[0], buf[1], buf[2], buf[3], -+ buf[4], buf[5], buf[6], buf[7]); -+ -+ /* configure internal TS mode */ -+ switch (state->cfg.ts_mode) { -+ case AF9033_TS_MODE_PARALLEL: -+ state->ts_mode_parallel = true; -+ break; -+ case AF9033_TS_MODE_SERIAL: -+ state->ts_mode_serial = true; -+ break; -+ case AF9033_TS_MODE_USB: -+ /* usb mode for AF9035 */ -+ default: -+ break; -+ } -+ -+ /* create dvb_frontend */ -+ memcpy(&state->fe.ops, &af9033_ops, sizeof(struct dvb_frontend_ops)); -+ state->fe.demodulator_priv = state; -+ -+ return &state->fe; -+ -+err: -+ kfree(state); -+ return NULL; -+} -+EXPORT_SYMBOL(af9033_attach); -+ -+static struct dvb_frontend_ops af9033_ops = { -+ .delsys = { SYS_DVBT }, -+ .info = { -+ .name = "Afatech AF9033 (DVB-T)", -+ .frequency_min = 174000000, -+ .frequency_max = 862000000, -+ .frequency_stepsize = 250000, -+ .frequency_tolerance = 0, -+ .caps = FE_CAN_FEC_1_2 | -+ FE_CAN_FEC_2_3 | -+ FE_CAN_FEC_3_4 | -+ FE_CAN_FEC_5_6 | -+ FE_CAN_FEC_7_8 | -+ FE_CAN_FEC_AUTO | -+ FE_CAN_QPSK | -+ FE_CAN_QAM_16 | -+ FE_CAN_QAM_64 | -+ FE_CAN_QAM_AUTO | -+ FE_CAN_TRANSMISSION_MODE_AUTO | -+ FE_CAN_GUARD_INTERVAL_AUTO | -+ FE_CAN_HIERARCHY_AUTO | -+ FE_CAN_RECOVER | -+ FE_CAN_MUTE_TS -+ }, -+ -+ .release = af9033_release, -+ -+ .init = af9033_init, -+ .sleep = af9033_sleep, -+ -+ .get_tune_settings = af9033_get_tune_settings, -+ .set_frontend = af9033_set_frontend, -+ .get_frontend = af9033_get_frontend, -+ -+ .read_status = af9033_read_status, -+ .read_snr = af9033_read_snr, -+ .read_signal_strength = af9033_read_signal_strength, -+ .read_ber = af9033_read_ber, -+ .read_ucblocks = af9033_read_ucblocks, -+ -+ .i2c_gate_ctrl = af9033_i2c_gate_ctrl, -+}; -+ -+MODULE_AUTHOR("Antti Palosaari "); -+MODULE_DESCRIPTION("Afatech AF9033 DVB-T demodulator driver"); -+MODULE_LICENSE("GPL"); -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/af9033.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/af9033.h -@@ -0,0 +1,75 @@ -+/* -+ * Afatech AF9033 demodulator driver -+ * -+ * Copyright (C) 2009 Antti Palosaari -+ * Copyright (C) 2012 Antti Palosaari -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#ifndef AF9033_H -+#define AF9033_H -+ -+struct af9033_config { -+ /* -+ * I2C address -+ */ -+ u8 i2c_addr; -+ -+ /* -+ * clock Hz -+ * 12000000, 22000000, 24000000, 34000000, 32000000, 28000000, 26000000, -+ * 30000000, 36000000, 20480000, 16384000 -+ */ -+ u32 clock; -+ -+ /* -+ * tuner -+ */ -+#define AF9033_TUNER_TUA9001 0x27 /* Infineon TUA 9001 */ -+#define AF9033_TUNER_FC0011 0x28 /* Fitipower FC0011 */ -+#define AF9033_TUNER_MXL5007T 0xa0 /* MaxLinear MxL5007T */ -+#define AF9033_TUNER_TDA18218 0xa1 /* NXP TDA 18218HN */ -+ u8 tuner; -+ -+ /* -+ * TS settings -+ */ -+#define AF9033_TS_MODE_USB 0 -+#define AF9033_TS_MODE_PARALLEL 1 -+#define AF9033_TS_MODE_SERIAL 2 -+ u8 ts_mode:2; -+ -+ /* -+ * input spectrum inversion -+ */ -+ bool spec_inv; -+}; -+ -+ -+#if defined(CONFIG_DVB_AF9033) || \ -+ (defined(CONFIG_DVB_AF9033_MODULE) && defined(MODULE)) -+extern struct dvb_frontend *af9033_attach(const struct af9033_config *config, -+ struct i2c_adapter *i2c); -+#else -+static inline struct dvb_frontend *af9033_attach( -+ const struct af9033_config *config, struct i2c_adapter *i2c) -+{ -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+#endif -+ -+#endif /* AF9033_H */ -Index: linux-3.3.x86_64/drivers/media/dvb/frontends/af9033_priv.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/dvb/frontends/af9033_priv.h -@@ -0,0 +1,470 @@ -+/* -+ * Afatech AF9033 demodulator driver -+ * -+ * Copyright (C) 2009 Antti Palosaari -+ * Copyright (C) 2012 Antti Palosaari -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#ifndef AF9033_PRIV_H -+#define AF9033_PRIV_H -+ -+#include "dvb_frontend.h" -+#include "af9033.h" -+ -+struct reg_val { -+ u32 reg; -+ u8 val; -+}; -+ -+struct reg_val_mask { -+ u32 reg; -+ u8 val; -+ u8 mask; -+}; -+ -+struct coeff { -+ u32 clock; -+ u32 bandwidth_hz; -+ u8 val[36]; -+}; -+ -+struct clock_adc { -+ u32 clock; -+ u32 adc; -+}; -+ -+struct val_snr { -+ u32 val; -+ u8 snr; -+}; -+ -+/* Xtal clock vs. ADC clock lookup table */ -+static const struct clock_adc clock_adc_lut[] = { -+ { 16384000, 20480000 }, -+ { 20480000, 20480000 }, -+ { 36000000, 20250000 }, -+ { 30000000, 20156250 }, -+ { 26000000, 20583333 }, -+ { 28000000, 20416667 }, -+ { 32000000, 20500000 }, -+ { 34000000, 20187500 }, -+ { 24000000, 20500000 }, -+ { 22000000, 20625000 }, -+ { 12000000, 20250000 }, -+}; -+ -+/* pre-calculated coeff lookup table */ -+static const struct coeff coeff_lut[] = { -+ /* 12.000 MHz */ -+ { 12000000, 8000000, { -+ 0x01, 0xce, 0x55, 0xc9, 0x00, 0xe7, 0x2a, 0xe4, 0x00, 0x73, -+ 0x99, 0x0f, 0x00, 0x73, 0x95, 0x72, 0x00, 0x73, 0x91, 0xd5, -+ 0x00, 0x39, 0xca, 0xb9, 0x00, 0xe7, 0x2a, 0xe4, 0x00, 0x73, -+ 0x95, 0x72, 0x37, 0x02, 0xce, 0x01 } -+ }, -+ { 12000000, 7000000, { -+ 0x01, 0x94, 0x8b, 0x10, 0x00, 0xca, 0x45, 0x88, 0x00, 0x65, -+ 0x25, 0xed, 0x00, 0x65, 0x22, 0xc4, 0x00, 0x65, 0x1f, 0x9b, -+ 0x00, 0x32, 0x91, 0x62, 0x00, 0xca, 0x45, 0x88, 0x00, 0x65, -+ 0x22, 0xc4, 0x88, 0x02, 0x95, 0x01 } -+ }, -+ { 12000000, 6000000, { -+ 0x01, 0x5a, 0xc0, 0x56, 0x00, 0xad, 0x60, 0x2b, 0x00, 0x56, -+ 0xb2, 0xcb, 0x00, 0x56, 0xb0, 0x15, 0x00, 0x56, 0xad, 0x60, -+ 0x00, 0x2b, 0x58, 0x0b, 0x00, 0xad, 0x60, 0x2b, 0x00, 0x56, -+ 0xb0, 0x15, 0xf4, 0x02, 0x5b, 0x01 } -+ }, -+}; -+ -+/* QPSK SNR lookup table */ -+static const struct val_snr qpsk_snr_lut[] = { -+ { 0x0b4771, 0 }, -+ { 0x0c1aed, 1 }, -+ { 0x0d0d27, 2 }, -+ { 0x0e4d19, 3 }, -+ { 0x0e5da8, 4 }, -+ { 0x107097, 5 }, -+ { 0x116975, 6 }, -+ { 0x1252d9, 7 }, -+ { 0x131fa4, 8 }, -+ { 0x13d5e1, 9 }, -+ { 0x148e53, 10 }, -+ { 0x15358b, 11 }, -+ { 0x15dd29, 12 }, -+ { 0x168112, 13 }, -+ { 0x170b61, 14 }, -+ { 0x17a532, 15 }, -+ { 0x180f94, 16 }, -+ { 0x186ed2, 17 }, -+ { 0x18b271, 18 }, -+ { 0x18e118, 19 }, -+ { 0x18ff4b, 20 }, -+ { 0x190af1, 21 }, -+ { 0x191451, 22 }, -+ { 0xffffff, 23 }, -+}; -+ -+/* QAM16 SNR lookup table */ -+static const struct val_snr qam16_snr_lut[] = { -+ { 0x04f0d5, 0 }, -+ { 0x05387a, 1 }, -+ { 0x0573a4, 2 }, -+ { 0x05a99e, 3 }, -+ { 0x05cc80, 4 }, -+ { 0x05eb62, 5 }, -+ { 0x05fecf, 6 }, -+ { 0x060b80, 7 }, -+ { 0x062501, 8 }, -+ { 0x064865, 9 }, -+ { 0x069604, 10 }, -+ { 0x06f356, 11 }, -+ { 0x07706a, 12 }, -+ { 0x0804d3, 13 }, -+ { 0x089d1a, 14 }, -+ { 0x093e3d, 15 }, -+ { 0x09e35d, 16 }, -+ { 0x0a7c3c, 17 }, -+ { 0x0afaf8, 18 }, -+ { 0x0b719d, 19 }, -+ { 0x0bda6a, 20 }, -+ { 0x0c0c75, 21 }, -+ { 0x0c3f7d, 22 }, -+ { 0x0c5e62, 23 }, -+ { 0x0c6c31, 24 }, -+ { 0x0c7925, 25 }, -+ { 0xffffff, 26 }, -+}; -+ -+/* QAM64 SNR lookup table */ -+static const struct val_snr qam64_snr_lut[] = { -+ { 0x0256d0, 0 }, -+ { 0x027a65, 1 }, -+ { 0x029873, 2 }, -+ { 0x02b7fe, 3 }, -+ { 0x02cf1e, 4 }, -+ { 0x02e234, 5 }, -+ { 0x02f409, 6 }, -+ { 0x030046, 7 }, -+ { 0x030844, 8 }, -+ { 0x030a02, 9 }, -+ { 0x030cde, 10 }, -+ { 0x031031, 11 }, -+ { 0x03144c, 12 }, -+ { 0x0315dd, 13 }, -+ { 0x031920, 14 }, -+ { 0x0322d0, 15 }, -+ { 0x0339fc, 16 }, -+ { 0x0364a1, 17 }, -+ { 0x038bcc, 18 }, -+ { 0x03c7d3, 19 }, -+ { 0x0408cc, 20 }, -+ { 0x043bed, 21 }, -+ { 0x048061, 22 }, -+ { 0x04be95, 23 }, -+ { 0x04fa7d, 24 }, -+ { 0x052405, 25 }, -+ { 0x05570d, 26 }, -+ { 0x059feb, 27 }, -+ { 0x05bf38, 28 }, -+ { 0xffffff, 29 }, -+}; -+ -+static const struct reg_val ofsm_init[] = { -+ { 0x800051, 0x01 }, -+ { 0x800070, 0x0a }, -+ { 0x80007e, 0x04 }, -+ { 0x800081, 0x0a }, -+ { 0x80008a, 0x01 }, -+ { 0x80008e, 0x01 }, -+ { 0x800092, 0x06 }, -+ { 0x800099, 0x01 }, -+ { 0x80009f, 0xe1 }, -+ { 0x8000a0, 0xcf }, -+ { 0x8000a3, 0x01 }, -+ { 0x8000a5, 0x01 }, -+ { 0x8000a6, 0x01 }, -+ { 0x8000a9, 0x00 }, -+ { 0x8000aa, 0x01 }, -+ { 0x8000ab, 0x01 }, -+ { 0x8000b0, 0x01 }, -+ { 0x8000c0, 0x05 }, -+ { 0x8000c4, 0x19 }, -+ { 0x80f000, 0x0f }, -+ { 0x80f016, 0x10 }, -+ { 0x80f017, 0x04 }, -+ { 0x80f018, 0x05 }, -+ { 0x80f019, 0x04 }, -+ { 0x80f01a, 0x05 }, -+ { 0x80f021, 0x03 }, -+ { 0x80f022, 0x0a }, -+ { 0x80f023, 0x0a }, -+ { 0x80f02b, 0x00 }, -+ { 0x80f02c, 0x01 }, -+ { 0x80f064, 0x03 }, -+ { 0x80f065, 0xf9 }, -+ { 0x80f066, 0x03 }, -+ { 0x80f067, 0x01 }, -+ { 0x80f06f, 0xe0 }, -+ { 0x80f070, 0x03 }, -+ { 0x80f072, 0x0f }, -+ { 0x80f073, 0x03 }, -+ { 0x80f078, 0x00 }, -+ { 0x80f087, 0x00 }, -+ { 0x80f09b, 0x3f }, -+ { 0x80f09c, 0x00 }, -+ { 0x80f09d, 0x20 }, -+ { 0x80f09e, 0x00 }, -+ { 0x80f09f, 0x0c }, -+ { 0x80f0a0, 0x00 }, -+ { 0x80f130, 0x04 }, -+ { 0x80f132, 0x04 }, -+ { 0x80f144, 0x1a }, -+ { 0x80f146, 0x00 }, -+ { 0x80f14a, 0x01 }, -+ { 0x80f14c, 0x00 }, -+ { 0x80f14d, 0x00 }, -+ { 0x80f14f, 0x04 }, -+ { 0x80f158, 0x7f }, -+ { 0x80f15a, 0x00 }, -+ { 0x80f15b, 0x08 }, -+ { 0x80f15d, 0x03 }, -+ { 0x80f15e, 0x05 }, -+ { 0x80f163, 0x05 }, -+ { 0x80f166, 0x01 }, -+ { 0x80f167, 0x40 }, -+ { 0x80f168, 0x0f }, -+ { 0x80f17a, 0x00 }, -+ { 0x80f17b, 0x00 }, -+ { 0x80f183, 0x01 }, -+ { 0x80f19d, 0x40 }, -+ { 0x80f1bc, 0x36 }, -+ { 0x80f1bd, 0x00 }, -+ { 0x80f1cb, 0xa0 }, -+ { 0x80f1cc, 0x01 }, -+ { 0x80f204, 0x10 }, -+ { 0x80f214, 0x00 }, -+ { 0x80f40e, 0x0a }, -+ { 0x80f40f, 0x40 }, -+ { 0x80f410, 0x08 }, -+ { 0x80f55f, 0x0a }, -+ { 0x80f561, 0x15 }, -+ { 0x80f562, 0x20 }, -+ { 0x80f5df, 0xfb }, -+ { 0x80f5e0, 0x00 }, -+ { 0x80f5e3, 0x09 }, -+ { 0x80f5e4, 0x01 }, -+ { 0x80f5e5, 0x01 }, -+ { 0x80f5f8, 0x01 }, -+ { 0x80f5fd, 0x01 }, -+ { 0x80f600, 0x05 }, -+ { 0x80f601, 0x08 }, -+ { 0x80f602, 0x0b }, -+ { 0x80f603, 0x0e }, -+ { 0x80f604, 0x11 }, -+ { 0x80f605, 0x14 }, -+ { 0x80f606, 0x17 }, -+ { 0x80f607, 0x1f }, -+ { 0x80f60e, 0x00 }, -+ { 0x80f60f, 0x04 }, -+ { 0x80f610, 0x32 }, -+ { 0x80f611, 0x10 }, -+ { 0x80f707, 0xfc }, -+ { 0x80f708, 0x00 }, -+ { 0x80f709, 0x37 }, -+ { 0x80f70a, 0x00 }, -+ { 0x80f78b, 0x01 }, -+ { 0x80f80f, 0x40 }, -+ { 0x80f810, 0x54 }, -+ { 0x80f811, 0x5a }, -+ { 0x80f905, 0x01 }, -+ { 0x80fb06, 0x03 }, -+ { 0x80fd8b, 0x00 }, -+}; -+ -+/* Infineon TUA 9001 tuner init -+ AF9033_TUNER_TUA9001 = 0x27 */ -+static const struct reg_val tuner_init_tua9001[] = { -+ { 0x800046, 0x27 }, -+ { 0x800057, 0x00 }, -+ { 0x800058, 0x01 }, -+ { 0x80005f, 0x00 }, -+ { 0x800060, 0x00 }, -+ { 0x80006d, 0x00 }, -+ { 0x800071, 0x05 }, -+ { 0x800072, 0x02 }, -+ { 0x800074, 0x01 }, -+ { 0x800075, 0x03 }, -+ { 0x800076, 0x02 }, -+ { 0x800077, 0x00 }, -+ { 0x800078, 0x01 }, -+ { 0x800079, 0x00 }, -+ { 0x80007a, 0x7e }, -+ { 0x80007b, 0x3e }, -+ { 0x800093, 0x00 }, -+ { 0x800094, 0x01 }, -+ { 0x800095, 0x02 }, -+ { 0x800096, 0x01 }, -+ { 0x800098, 0x0a }, -+ { 0x80009b, 0x05 }, -+ { 0x80009c, 0x80 }, -+ { 0x8000b3, 0x00 }, -+ { 0x8000c1, 0x01 }, -+ { 0x8000c2, 0x00 }, -+ { 0x80f007, 0x00 }, -+ { 0x80f01f, 0x82 }, -+ { 0x80f020, 0x00 }, -+ { 0x80f029, 0x82 }, -+ { 0x80f02a, 0x00 }, -+ { 0x80f047, 0x00 }, -+ { 0x80f054, 0x00 }, -+ { 0x80f055, 0x00 }, -+ { 0x80f077, 0x01 }, -+ { 0x80f1e6, 0x00 }, -+}; -+ -+/* Fitipower fc0011 tuner init -+ AF9033_TUNER_FC0011 = 0x28 */ -+static const struct reg_val tuner_init_fc0011[] = { -+ { 0x800046, AF9033_TUNER_FC0011 }, -+ { 0x800057, 0x00 }, -+ { 0x800058, 0x01 }, -+ { 0x80005f, 0x00 }, -+ { 0x800060, 0x00 }, -+ { 0x800068, 0xa5 }, -+ { 0x80006e, 0x01 }, -+ { 0x800071, 0x0A }, -+ { 0x800072, 0x02 }, -+ { 0x800074, 0x01 }, -+ { 0x800079, 0x01 }, -+ { 0x800093, 0x00 }, -+ { 0x800094, 0x00 }, -+ { 0x800095, 0x00 }, -+ { 0x800096, 0x00 }, -+ { 0x80009b, 0x2D }, -+ { 0x80009c, 0x60 }, -+ { 0x80009d, 0x23 }, -+ { 0x8000a4, 0x50 }, -+ { 0x8000ad, 0x50 }, -+ { 0x8000b3, 0x01 }, -+ { 0x8000b7, 0x88 }, -+ { 0x8000b8, 0xa6 }, -+ { 0x8000c3, 0x01 }, -+ { 0x8000c4, 0x01 }, -+ { 0x8000c7, 0x69 }, -+ { 0x80F007, 0x00 }, -+ { 0x80F00A, 0x1B }, -+ { 0x80F00B, 0x1B }, -+ { 0x80F00C, 0x1B }, -+ { 0x80F00D, 0x1B }, -+ { 0x80F00E, 0xFF }, -+ { 0x80F00F, 0x01 }, -+ { 0x80F010, 0x00 }, -+ { 0x80F011, 0x02 }, -+ { 0x80F012, 0xFF }, -+ { 0x80F013, 0x01 }, -+ { 0x80F014, 0x00 }, -+ { 0x80F015, 0x02 }, -+ { 0x80F01B, 0xEF }, -+ { 0x80F01C, 0x01 }, -+ { 0x80F01D, 0x0f }, -+ { 0x80F01E, 0x02 }, -+ { 0x80F01F, 0x6E }, -+ { 0x80F020, 0x00 }, -+ { 0x80F025, 0xDE }, -+ { 0x80F026, 0x00 }, -+ { 0x80F027, 0x0A }, -+ { 0x80F028, 0x03 }, -+ { 0x80F029, 0x6E }, -+ { 0x80F02A, 0x00 }, -+ { 0x80F047, 0x00 }, -+ { 0x80F054, 0x00 }, -+ { 0x80F055, 0x00 }, -+ { 0x80F077, 0x01 }, -+ { 0x80F1E6, 0x00 }, -+}; -+ -+/* MaxLinear MxL5007T tuner init -+ AF9033_TUNER_MXL5007T = 0xa0 */ -+static const struct reg_val tuner_init_mxl5007t[] = { -+ { 0x800046, 0x1b }, -+ { 0x800057, 0x01 }, -+ { 0x800058, 0x01 }, -+ { 0x80005f, 0x00 }, -+ { 0x800060, 0x00 }, -+ { 0x800068, 0x96 }, -+ { 0x800071, 0x05 }, -+ { 0x800072, 0x02 }, -+ { 0x800074, 0x01 }, -+ { 0x800079, 0x01 }, -+ { 0x800093, 0x00 }, -+ { 0x800094, 0x00 }, -+ { 0x800095, 0x00 }, -+ { 0x800096, 0x00 }, -+ { 0x8000b3, 0x01 }, -+ { 0x8000c1, 0x01 }, -+ { 0x8000c2, 0x00 }, -+ { 0x80f007, 0x00 }, -+ { 0x80f00c, 0x19 }, -+ { 0x80f00d, 0x1a }, -+ { 0x80f012, 0xda }, -+ { 0x80f013, 0x00 }, -+ { 0x80f014, 0x00 }, -+ { 0x80f015, 0x02 }, -+ { 0x80f01f, 0x82 }, -+ { 0x80f020, 0x00 }, -+ { 0x80f029, 0x82 }, -+ { 0x80f02a, 0x00 }, -+ { 0x80f077, 0x02 }, -+ { 0x80f1e6, 0x00 }, -+}; -+ -+/* NXP TDA 18218HN tuner init -+ AF9033_TUNER_TDA18218 = 0xa1 */ -+static const struct reg_val tuner_init_tda18218[] = { -+ {0x800046, 0xa1}, -+ {0x800057, 0x01}, -+ {0x800058, 0x01}, -+ {0x80005f, 0x00}, -+ {0x800060, 0x00}, -+ {0x800071, 0x05}, -+ {0x800072, 0x02}, -+ {0x800074, 0x01}, -+ {0x800079, 0x01}, -+ {0x800093, 0x00}, -+ {0x800094, 0x00}, -+ {0x800095, 0x00}, -+ {0x800096, 0x00}, -+ {0x8000b3, 0x01}, -+ {0x8000c3, 0x01}, -+ {0x8000c4, 0x00}, -+ {0x80f007, 0x00}, -+ {0x80f00c, 0x19}, -+ {0x80f00d, 0x1a}, -+ {0x80f012, 0xda}, -+ {0x80f013, 0x00}, -+ {0x80f014, 0x00}, -+ {0x80f015, 0x02}, -+ {0x80f01f, 0x82}, -+ {0x80f020, 0x00}, -+ {0x80f029, 0x82}, -+ {0x80f02a, 0x00}, -+ {0x80f077, 0x02}, -+ {0x80f1e6, 0x00}, -+}; -+ -+#endif /* AF9033_PRIV_H */ -+ -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9035.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9035.c -@@ -0,0 +1,1164 @@ -+/* -+ * Afatech AF9035 DVB USB driver -+ * -+ * Copyright (C) 2009 Antti Palosaari -+ * Copyright (C) 2012 Antti Palosaari -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#include "af9035.h" -+#include "af9033.h" -+#include "tua9001.h" -+#include "fc0011.h" -+#include "mxl5007t.h" -+#include "tda18218.h" -+ -+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -+static DEFINE_MUTEX(af9035_usb_mutex); -+static struct config af9035_config; -+static struct dvb_usb_device_properties af9035_properties[2]; -+static int af9035_properties_count = ARRAY_SIZE(af9035_properties); -+static struct af9033_config af9035_af9033_config[] = { -+ { -+ .ts_mode = AF9033_TS_MODE_USB, -+ }, { -+ .ts_mode = AF9033_TS_MODE_SERIAL, -+ } -+}; -+ -+static u16 af9035_checksum(const u8 *buf, size_t len) -+{ -+ size_t i; -+ u16 checksum = 0; -+ -+ for (i = 1; i < len; i++) { -+ if (i % 2) -+ checksum += buf[i] << 8; -+ else -+ checksum += buf[i]; -+ } -+ checksum = ~checksum; -+ -+ return checksum; -+} -+ -+static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req) -+{ -+#define BUF_LEN 63 -+#define REQ_HDR_LEN 4 /* send header size */ -+#define ACK_HDR_LEN 3 /* rece header size */ -+#define CHECKSUM_LEN 2 -+#define USB_TIMEOUT 2000 -+ -+ int ret, act_len; -+ u8 buf[BUF_LEN]; -+ u32 msg_len; -+ static u8 seq; /* packet sequence number */ -+ u16 checksum, tmpsum; -+ -+ /* buffer overflow check */ -+ if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) || -+ req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) { -+ pr_debug("%s: too much data wlen=%d rlen=%d\n", __func__, -+ req->wlen, req->rlen); -+ return -EINVAL; -+ } -+ -+ if (mutex_lock_interruptible(&af9035_usb_mutex) < 0) -+ return -EAGAIN; -+ -+ buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1; -+ buf[1] = req->mbox; -+ buf[2] = req->cmd; -+ buf[3] = seq++; -+ if (req->wlen) -+ memcpy(&buf[4], req->wbuf, req->wlen); -+ -+ /* calc and add checksum */ -+ checksum = af9035_checksum(buf, buf[0] - 1); -+ buf[buf[0]-1] = (checksum >> 8); -+ buf[buf[0]-0] = (checksum & 0xff); -+ -+ msg_len = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN ; -+ -+ /* send req */ -+ ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len, -+ &act_len, USB_TIMEOUT); -+ if (ret < 0) -+ err("bulk message failed=%d (%d/%d)", ret, msg_len, act_len); -+ else -+ if (act_len != msg_len) -+ ret = -EIO; /* all data is not send */ -+ if (ret < 0) -+ goto err_mutex_unlock; -+ -+ /* no ack for those packets */ -+ if (req->cmd == CMD_FW_DL) -+ goto exit_mutex_unlock; -+ -+ /* receive ack and data if read req */ -+ msg_len = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN; -+ ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len, -+ &act_len, USB_TIMEOUT); -+ if (ret < 0) { -+ err("recv bulk message failed=%d", ret); -+ ret = -EIO; -+ goto err_mutex_unlock; -+ } -+ if (act_len != msg_len) { -+ err("recv bulk message truncated (%d != %u)\n", -+ act_len, (unsigned int)msg_len); -+ ret = -EIO; -+ goto err_mutex_unlock; -+ } -+ -+ /* verify checksum */ -+ checksum = af9035_checksum(buf, act_len - 2); -+ tmpsum = (buf[act_len - 2] << 8) | buf[act_len - 1]; -+ if (tmpsum != checksum) { -+ err("%s: command=%02X checksum mismatch (%04X != %04X)\n", -+ __func__, req->cmd, -+ (unsigned int)tmpsum, (unsigned int)checksum); -+ ret = -EIO; -+ goto err_mutex_unlock; -+ } -+ /* check status */ -+ if (buf[2]) { -+ pr_debug("%s: command=%02x failed fw error=%d\n", __func__, -+ req->cmd, buf[2]); -+ ret = -EIO; -+ goto err_mutex_unlock; -+ } -+ -+ /* read request, copy returned data to return buf */ -+ if (req->rlen) -+ memcpy(req->rbuf, &buf[ACK_HDR_LEN], req->rlen); -+ -+err_mutex_unlock: -+exit_mutex_unlock: -+ mutex_unlock(&af9035_usb_mutex); -+ -+ return ret; -+} -+ -+/* write multiple registers */ -+static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) -+{ -+ u8 wbuf[6 + len]; -+ u8 mbox = (reg >> 16) & 0xff; -+ struct usb_req req = { CMD_MEM_WR, mbox, sizeof(wbuf), wbuf, 0, NULL }; -+ -+ wbuf[0] = len; -+ wbuf[1] = 2; -+ wbuf[2] = 0; -+ wbuf[3] = 0; -+ wbuf[4] = (reg >> 8) & 0xff; -+ wbuf[5] = (reg >> 0) & 0xff; -+ memcpy(&wbuf[6], val, len); -+ -+ return af9035_ctrl_msg(d->udev, &req); -+} -+ -+/* read multiple registers */ -+static int af9035_rd_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) -+{ -+ u8 wbuf[] = { len, 2, 0, 0, (reg >> 8) & 0xff, reg & 0xff }; -+ u8 mbox = (reg >> 16) & 0xff; -+ struct usb_req req = { CMD_MEM_RD, mbox, sizeof(wbuf), wbuf, len, val }; -+ -+ return af9035_ctrl_msg(d->udev, &req); -+} -+ -+/* write single register */ -+static int af9035_wr_reg(struct dvb_usb_device *d, u32 reg, u8 val) -+{ -+ return af9035_wr_regs(d, reg, &val, 1); -+} -+ -+/* read single register */ -+static int af9035_rd_reg(struct dvb_usb_device *d, u32 reg, u8 *val) -+{ -+ return af9035_rd_regs(d, reg, val, 1); -+} -+ -+/* write single register with mask */ -+static int af9035_wr_reg_mask(struct dvb_usb_device *d, u32 reg, u8 val, -+ u8 mask) -+{ -+ int ret; -+ u8 tmp; -+ -+ /* no need for read if whole reg is written */ -+ if (mask != 0xff) { -+ ret = af9035_rd_regs(d, reg, &tmp, 1); -+ if (ret) -+ return ret; -+ -+ val &= mask; -+ tmp &= ~mask; -+ val |= tmp; -+ } -+ -+ return af9035_wr_regs(d, reg, &val, 1); -+} -+ -+static int af9035_i2c_master_xfer(struct i2c_adapter *adap, -+ struct i2c_msg msg[], int num) -+{ -+ struct dvb_usb_device *d = i2c_get_adapdata(adap); -+ int ret; -+ -+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) -+ return -EAGAIN; -+ -+ /* -+ * I2C sub header is 5 bytes long. Meaning of those bytes are: -+ * 0: data len -+ * 1: I2C addr << 1 -+ * 2: reg addr len -+ * byte 3 and 4 can be used as reg addr -+ * 3: reg addr MSB -+ * used when reg addr len is set to 2 -+ * 4: reg addr LSB -+ * used when reg addr len is set to 1 or 2 -+ * -+ * For the simplify we do not use register addr at all. -+ * NOTE: As a firmware knows tuner type there is very small possibility -+ * there could be some tuner I2C hacks done by firmware and this may -+ * lead problems if firmware expects those bytes are used. -+ */ -+ if (num == 2 && !(msg[0].flags & I2C_M_RD) && -+ (msg[1].flags & I2C_M_RD)) { -+ if (msg[0].len > 40 || msg[1].len > 40) { -+ /* TODO: correct limits > 40 */ -+ ret = -EOPNOTSUPP; -+ } else if (msg[0].addr == af9035_af9033_config[0].i2c_addr) { -+ /* integrated demod */ -+ u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | -+ msg[0].buf[2]; -+ ret = af9035_rd_regs(d, reg, &msg[1].buf[0], -+ msg[1].len); -+ } else { -+ /* I2C */ -+ u8 buf[5 + msg[0].len]; -+ struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf), -+ buf, msg[1].len, msg[1].buf }; -+ buf[0] = msg[1].len; -+ buf[1] = msg[0].addr << 1; -+ buf[2] = 0x00; /* reg addr len */ -+ buf[3] = 0x00; /* reg addr MSB */ -+ buf[4] = 0x00; /* reg addr LSB */ -+ memcpy(&buf[5], msg[0].buf, msg[0].len); -+ ret = af9035_ctrl_msg(d->udev, &req); -+ } -+ } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { -+ if (msg[0].len > 40) { -+ /* TODO: correct limits > 40 */ -+ ret = -EOPNOTSUPP; -+ } else if (msg[0].addr == af9035_af9033_config[0].i2c_addr) { -+ /* integrated demod */ -+ u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | -+ msg[0].buf[2]; -+ ret = af9035_wr_regs(d, reg, &msg[0].buf[3], -+ msg[0].len - 3); -+ } else { -+ /* I2C */ -+ u8 buf[5 + msg[0].len]; -+ struct usb_req req = { CMD_I2C_WR, 0, sizeof(buf), buf, -+ 0, NULL }; -+ buf[0] = msg[0].len; -+ buf[1] = msg[0].addr << 1; -+ buf[2] = 0x00; /* reg addr len */ -+ buf[3] = 0x00; /* reg addr MSB */ -+ buf[4] = 0x00; /* reg addr LSB */ -+ memcpy(&buf[5], msg[0].buf, msg[0].len); -+ ret = af9035_ctrl_msg(d->udev, &req); -+ } -+ } else { -+ /* -+ * We support only two kind of I2C transactions: -+ * 1) 1 x read + 1 x write -+ * 2) 1 x write -+ */ -+ ret = -EOPNOTSUPP; -+ } -+ -+ mutex_unlock(&d->i2c_mutex); -+ -+ if (ret < 0) -+ return ret; -+ else -+ return num; -+} -+ -+static u32 af9035_i2c_functionality(struct i2c_adapter *adapter) -+{ -+ return I2C_FUNC_I2C; -+} -+ -+static struct i2c_algorithm af9035_i2c_algo = { -+ .master_xfer = af9035_i2c_master_xfer, -+ .functionality = af9035_i2c_functionality, -+}; -+ -+static int af9035_init(struct dvb_usb_device *d) -+{ -+ int ret, i; -+ u16 frame_size = 87 * 188 / 4; -+ u8 packet_size = 512 / 4; -+ struct reg_val_mask tab[] = { -+ { 0x80f99d, 0x01, 0x01 }, -+ { 0x80f9a4, 0x01, 0x01 }, -+ { 0x00dd11, 0x00, 0x20 }, -+ { 0x00dd11, 0x00, 0x40 }, -+ { 0x00dd13, 0x00, 0x20 }, -+ { 0x00dd13, 0x00, 0x40 }, -+ { 0x00dd11, 0x20, 0x20 }, -+ { 0x00dd88, (frame_size >> 0) & 0xff, 0xff}, -+ { 0x00dd89, (frame_size >> 8) & 0xff, 0xff}, -+ { 0x00dd0c, packet_size, 0xff}, -+ { 0x00dd11, af9035_config.dual_mode << 6, 0x40 }, -+ { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff}, -+ { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff}, -+ { 0x00dd0d, packet_size, 0xff }, -+ { 0x80f9a3, 0x00, 0x01 }, -+ { 0x80f9cd, 0x00, 0x01 }, -+ { 0x80f99d, 0x00, 0x01 }, -+ { 0x80f9a4, 0x00, 0x01 }, -+ }; -+ -+ pr_debug("%s: USB speed=%d frame_size=%04x packet_size=%02x\n", -+ __func__, d->udev->speed, frame_size, packet_size); -+ -+ /* init endpoints */ -+ for (i = 0; i < ARRAY_SIZE(tab); i++) { -+ ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val, -+ tab[i].mask); -+ if (ret < 0) -+ goto err; -+ } -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+static int af9035_identify_state(struct usb_device *udev, -+ struct dvb_usb_device_properties *props, -+ struct dvb_usb_device_description **desc, -+ int *cold) -+{ -+ int ret; -+ u8 wbuf[1] = { 1 }; -+ u8 rbuf[4]; -+ struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf, -+ sizeof(rbuf), rbuf }; -+ -+ ret = af9035_ctrl_msg(udev, &req); -+ if (ret < 0) -+ goto err; -+ -+ pr_debug("%s: reply=%02x %02x %02x %02x\n", __func__, -+ rbuf[0], rbuf[1], rbuf[2], rbuf[3]); -+ if (rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3]) -+ *cold = 0; -+ else -+ *cold = 1; -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+static int af9035_download_firmware(struct usb_device *udev, -+ const struct firmware *fw) -+{ -+ int ret, i, j, len; -+ u8 wbuf[1]; -+ u8 rbuf[4]; -+ struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; -+ struct usb_req req_fw_dl = { CMD_FW_DL, 0, 0, wbuf, 0, NULL }; -+ struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; -+ u8 hdr_core; -+ u16 hdr_addr, hdr_data_len, hdr_checksum; -+ #define MAX_DATA 57 -+ #define HDR_SIZE 7 -+ -+ /* -+ * Thanks to Daniel Glöckner about that info! -+ * -+ * byte 0: MCS 51 core -+ * There are two inside the AF9035 (1=Link and 2=OFDM) with separate -+ * address spaces -+ * byte 1-2: Big endian destination address -+ * byte 3-4: Big endian number of data bytes following the header -+ * byte 5-6: Big endian header checksum, apparently ignored by the chip -+ * Calculated as ~(h[0]*256+h[1]+h[2]*256+h[3]+h[4]*256) -+ */ -+ -+ for (i = fw->size; i > HDR_SIZE;) { -+ hdr_core = fw->data[fw->size - i + 0]; -+ hdr_addr = fw->data[fw->size - i + 1] << 8; -+ hdr_addr |= fw->data[fw->size - i + 2] << 0; -+ hdr_data_len = fw->data[fw->size - i + 3] << 8; -+ hdr_data_len |= fw->data[fw->size - i + 4] << 0; -+ hdr_checksum = fw->data[fw->size - i + 5] << 8; -+ hdr_checksum |= fw->data[fw->size - i + 6] << 0; -+ -+ pr_debug("%s: core=%d addr=%04x data_len=%d checksum=%04x\n", -+ __func__, hdr_core, hdr_addr, hdr_data_len, -+ hdr_checksum); -+ -+ if (((hdr_core != 1) && (hdr_core != 2)) || -+ (hdr_data_len > i)) { -+ pr_debug("%s: bad firmware\n", __func__); -+ break; -+ } -+ -+ /* download begin packet */ -+ req.cmd = CMD_FW_DL_BEGIN; -+ ret = af9035_ctrl_msg(udev, &req); -+ if (ret < 0) -+ goto err; -+ -+ /* download firmware packet(s) */ -+ for (j = HDR_SIZE + hdr_data_len; j > 0; j -= MAX_DATA) { -+ len = j; -+ if (len > MAX_DATA) -+ len = MAX_DATA; -+ req_fw_dl.wlen = len; -+ req_fw_dl.wbuf = (u8 *) &fw->data[fw->size - i + -+ HDR_SIZE + hdr_data_len - j]; -+ ret = af9035_ctrl_msg(udev, &req_fw_dl); -+ if (ret < 0) -+ goto err; -+ } -+ -+ /* download end packet */ -+ req.cmd = CMD_FW_DL_END; -+ ret = af9035_ctrl_msg(udev, &req); -+ if (ret < 0) -+ goto err; -+ -+ i -= hdr_data_len + HDR_SIZE; -+ -+ pr_debug("%s: data uploaded=%zu\n", __func__, fw->size - i); -+ } -+ -+ /* firmware loaded, request boot */ -+ req.cmd = CMD_FW_BOOT; -+ ret = af9035_ctrl_msg(udev, &req); -+ if (ret < 0) -+ goto err; -+ -+ /* ensure firmware starts */ -+ wbuf[0] = 1; -+ ret = af9035_ctrl_msg(udev, &req_fw_ver); -+ if (ret < 0) -+ goto err; -+ -+ if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { -+ info("firmware did not run"); -+ ret = -ENODEV; -+ goto err; -+ } -+ -+ info("firmware version=%d.%d.%d.%d", rbuf[0], rbuf[1], rbuf[2], -+ rbuf[3]); -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+static int af9035_download_firmware_it9135(struct usb_device *udev, -+ const struct firmware *fw) -+{ -+ int ret, i, i_prev; -+ u8 wbuf[1]; -+ u8 rbuf[4]; -+ struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; -+ struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR, 0, 0, NULL, 0, NULL }; -+ struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; -+ #define HDR_SIZE 7 -+ -+ /* -+ * There seems to be following firmware header. Meaning of bytes 0-3 -+ * is unknown. -+ * -+ * 0: 3 -+ * 1: 0, 1 -+ * 2: 0 -+ * 3: 1, 2, 3 -+ * 4: addr MSB -+ * 5: addr LSB -+ * 6: count of data bytes ? -+ */ -+ -+ for (i = HDR_SIZE, i_prev = 0; i <= fw->size; i++) { -+ if (i == fw->size || -+ (fw->data[i + 0] == 0x03 && -+ (fw->data[i + 1] == 0x00 || -+ fw->data[i + 1] == 0x01) && -+ fw->data[i + 2] == 0x00)) { -+ req_fw_dl.wlen = i - i_prev; -+ req_fw_dl.wbuf = (u8 *) &fw->data[i_prev]; -+ i_prev = i; -+ ret = af9035_ctrl_msg(udev, &req_fw_dl); -+ if (ret < 0) -+ goto err; -+ -+ pr_debug("%s: data uploaded=%d\n", __func__, i); -+ } -+ } -+ -+ /* firmware loaded, request boot */ -+ req.cmd = CMD_FW_BOOT; -+ ret = af9035_ctrl_msg(udev, &req); -+ if (ret < 0) -+ goto err; -+ -+ /* ensure firmware starts */ -+ wbuf[0] = 1; -+ ret = af9035_ctrl_msg(udev, &req_fw_ver); -+ if (ret < 0) -+ goto err; -+ -+ if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { -+ info("firmware did not run"); -+ ret = -ENODEV; -+ goto err; -+ } -+ -+ info("firmware version=%d.%d.%d.%d", rbuf[0], rbuf[1], rbuf[2], -+ rbuf[3]); -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+/* abuse that callback as there is no better one for reading eeprom */ -+static int af9035_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) -+{ -+ int ret, i, eeprom_shift = 0; -+ u8 tmp; -+ u16 tmp16; -+ -+ /* check if there is dual tuners */ -+ ret = af9035_rd_reg(d, EEPROM_DUAL_MODE, &tmp); -+ if (ret < 0) -+ goto err; -+ -+ af9035_config.dual_mode = tmp; -+ pr_debug("%s: dual mode=%d\n", __func__, af9035_config.dual_mode); -+ -+ for (i = 0; i < af9035_properties[0].num_adapters; i++) { -+ /* tuner */ -+ ret = af9035_rd_reg(d, EEPROM_1_TUNER_ID + eeprom_shift, &tmp); -+ if (ret < 0) -+ goto err; -+ -+ af9035_af9033_config[i].tuner = tmp; -+ pr_debug("%s: [%d]tuner=%02x\n", __func__, i, tmp); -+ -+ switch (tmp) { -+ case AF9033_TUNER_TUA9001: -+ case AF9033_TUNER_FC0011: -+ case AF9033_TUNER_MXL5007T: -+ case AF9033_TUNER_TDA18218: -+ af9035_af9033_config[i].spec_inv = 1; -+ break; -+ default: -+ af9035_config.hw_not_supported = true; -+ warn("tuner ID=%02x not supported, please report!", -+ tmp); -+ }; -+ -+ /* tuner IF frequency */ -+ ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_L + eeprom_shift, &tmp); -+ if (ret < 0) -+ goto err; -+ -+ tmp16 = tmp; -+ -+ ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_H + eeprom_shift, &tmp); -+ if (ret < 0) -+ goto err; -+ -+ tmp16 |= tmp << 8; -+ -+ pr_debug("%s: [%d]IF=%d\n", __func__, i, tmp16); -+ -+ eeprom_shift = 0x10; /* shift for the 2nd tuner params */ -+ } -+ -+ /* get demod clock */ -+ ret = af9035_rd_reg(d, 0x00d800, &tmp); -+ if (ret < 0) -+ goto err; -+ -+ tmp = (tmp >> 0) & 0x0f; -+ -+ for (i = 0; i < af9035_properties[0].num_adapters; i++) -+ af9035_af9033_config[i].clock = clock_lut[tmp]; -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+/* abuse that callback as there is no better one for reading eeprom */ -+static int af9035_read_mac_address_it9135(struct dvb_usb_device *d, u8 mac[6]) -+{ -+ int ret, i; -+ u8 tmp; -+ -+ af9035_config.dual_mode = 0; -+ -+ /* get demod clock */ -+ ret = af9035_rd_reg(d, 0x00d800, &tmp); -+ if (ret < 0) -+ goto err; -+ -+ tmp = (tmp >> 0) & 0x0f; -+ -+ for (i = 0; i < af9035_properties[0].num_adapters; i++) -+ af9035_af9033_config[i].clock = clock_lut_it9135[tmp]; -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d, -+ int cmd, int arg) -+{ -+ int ret; -+ -+ switch (cmd) { -+ case FC0011_FE_CALLBACK_POWER: -+ /* Tuner enable */ -+ ret = af9035_wr_reg_mask(d, 0xd8eb, 1, 1); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9035_wr_reg_mask(d, 0xd8ec, 1, 1); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9035_wr_reg_mask(d, 0xd8ed, 1, 1); -+ if (ret < 0) -+ goto err; -+ -+ /* LED */ -+ ret = af9035_wr_reg_mask(d, 0xd8d0, 1, 1); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9035_wr_reg_mask(d, 0xd8d1, 1, 1); -+ if (ret < 0) -+ goto err; -+ -+ usleep_range(10000, 50000); -+ break; -+ case FC0011_FE_CALLBACK_RESET: -+ ret = af9035_wr_reg(d, 0xd8e9, 1); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9035_wr_reg(d, 0xd8e8, 1); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9035_wr_reg(d, 0xd8e7, 1); -+ if (ret < 0) -+ goto err; -+ -+ usleep_range(10000, 20000); -+ -+ ret = af9035_wr_reg(d, 0xd8e7, 0); -+ if (ret < 0) -+ goto err; -+ -+ usleep_range(10000, 20000); -+ break; -+ default: -+ ret = -EINVAL; -+ goto err; -+ } -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+static int af9035_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) -+{ -+ switch (af9035_af9033_config[0].tuner) { -+ case AF9033_TUNER_FC0011: -+ return af9035_fc0011_tuner_callback(d, cmd, arg); -+ default: -+ break; -+ } -+ -+ return -ENODEV; -+} -+ -+static int af9035_frontend_callback(void *adapter_priv, int component, -+ int cmd, int arg) -+{ -+ struct i2c_adapter *adap = adapter_priv; -+ struct dvb_usb_device *d = i2c_get_adapdata(adap); -+ -+ switch (component) { -+ case DVB_FRONTEND_COMPONENT_TUNER: -+ return af9035_tuner_callback(d, cmd, arg); -+ default: -+ break; -+ } -+ -+ return -EINVAL; -+} -+ -+static int af9035_frontend_attach(struct dvb_usb_adapter *adap) -+{ -+ int ret; -+ -+ if (af9035_config.hw_not_supported) { -+ ret = -ENODEV; -+ goto err; -+ } -+ -+ if (adap->id == 0) { -+ ret = af9035_wr_reg(adap->dev, 0x00417f, -+ af9035_af9033_config[1].i2c_addr); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9035_wr_reg(adap->dev, 0x00d81a, -+ af9035_config.dual_mode); -+ if (ret < 0) -+ goto err; -+ } -+ -+ /* attach demodulator */ -+ adap->fe_adap[0].fe = dvb_attach(af9033_attach, -+ &af9035_af9033_config[adap->id], &adap->dev->i2c_adap); -+ if (adap->fe_adap[0].fe == NULL) { -+ ret = -ENODEV; -+ goto err; -+ } -+ -+ /* disable I2C-gate */ -+ adap->fe_adap[0].fe->ops.i2c_gate_ctrl = NULL; -+ adap->fe_adap[0].fe->callback = af9035_frontend_callback; -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+static struct tua9001_config af9035_tua9001_config = { -+ .i2c_addr = 0x60, -+}; -+ -+static const struct fc0011_config af9035_fc0011_config = { -+ .i2c_address = 0x60, -+}; -+ -+static struct mxl5007t_config af9035_mxl5007t_config = { -+ .xtal_freq_hz = MxL_XTAL_24_MHZ, -+ .if_freq_hz = MxL_IF_4_57_MHZ, -+ .invert_if = 0, -+ .loop_thru_enable = 0, -+ .clk_out_enable = 0, -+ .clk_out_amp = MxL_CLKOUT_AMP_0_94V, -+}; -+ -+static struct tda18218_config af9035_tda18218_config = { -+ .i2c_address = 0x60, -+ .i2c_wr_max = 21, -+}; -+ -+static int af9035_tuner_attach(struct dvb_usb_adapter *adap) -+{ -+ int ret; -+ struct dvb_frontend *fe; -+ -+ switch (af9035_af9033_config[adap->id].tuner) { -+ case AF9033_TUNER_TUA9001: -+ /* AF9035 gpiot3 = TUA9001 RESETN -+ AF9035 gpiot2 = TUA9001 RXEN */ -+ -+ /* configure gpiot2 and gpiot2 as output */ -+ ret = af9035_wr_reg_mask(adap->dev, 0x00d8ec, 0x01, 0x01); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9035_wr_reg_mask(adap->dev, 0x00d8ed, 0x01, 0x01); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9035_wr_reg_mask(adap->dev, 0x00d8e8, 0x01, 0x01); -+ if (ret < 0) -+ goto err; -+ -+ ret = af9035_wr_reg_mask(adap->dev, 0x00d8e9, 0x01, 0x01); -+ if (ret < 0) -+ goto err; -+ -+ /* reset tuner */ -+ ret = af9035_wr_reg_mask(adap->dev, 0x00d8e7, 0x00, 0x01); -+ if (ret < 0) -+ goto err; -+ -+ usleep_range(2000, 20000); -+ -+ ret = af9035_wr_reg_mask(adap->dev, 0x00d8e7, 0x01, 0x01); -+ if (ret < 0) -+ goto err; -+ -+ /* activate tuner RX */ -+ /* TODO: use callback for TUA9001 RXEN */ -+ ret = af9035_wr_reg_mask(adap->dev, 0x00d8eb, 0x01, 0x01); -+ if (ret < 0) -+ goto err; -+ -+ /* attach tuner */ -+ fe = dvb_attach(tua9001_attach, adap->fe_adap[0].fe, -+ &adap->dev->i2c_adap, &af9035_tua9001_config); -+ break; -+ case AF9033_TUNER_FC0011: -+ fe = dvb_attach(fc0011_attach, adap->fe_adap[0].fe, -+ &adap->dev->i2c_adap, &af9035_fc0011_config); -+ break; -+ case AF9033_TUNER_MXL5007T: -+ ret = af9035_wr_reg(adap->dev, 0x00d8e0, 1); -+ if (ret < 0) -+ goto err; -+ ret = af9035_wr_reg(adap->dev, 0x00d8e1, 1); -+ if (ret < 0) -+ goto err; -+ ret = af9035_wr_reg(adap->dev, 0x00d8df, 0); -+ if (ret < 0) -+ goto err; -+ -+ msleep(30); -+ -+ ret = af9035_wr_reg(adap->dev, 0x00d8df, 1); -+ if (ret < 0) -+ goto err; -+ -+ msleep(300); -+ -+ ret = af9035_wr_reg(adap->dev, 0x00d8c0, 1); -+ if (ret < 0) -+ goto err; -+ ret = af9035_wr_reg(adap->dev, 0x00d8c1, 1); -+ if (ret < 0) -+ goto err; -+ ret = af9035_wr_reg(adap->dev, 0x00d8bf, 0); -+ if (ret < 0) -+ goto err; -+ ret = af9035_wr_reg(adap->dev, 0x00d8b4, 1); -+ if (ret < 0) -+ goto err; -+ ret = af9035_wr_reg(adap->dev, 0x00d8b5, 1); -+ if (ret < 0) -+ goto err; -+ ret = af9035_wr_reg(adap->dev, 0x00d8b3, 1); -+ if (ret < 0) -+ goto err; -+ -+ /* attach tuner */ -+ fe = dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe, -+ &adap->dev->i2c_adap, 0x60, &af9035_mxl5007t_config); -+ break; -+ case AF9033_TUNER_TDA18218: -+ /* attach tuner */ -+ fe = dvb_attach(tda18218_attach, adap->fe_adap[0].fe, -+ &adap->dev->i2c_adap, &af9035_tda18218_config); -+ break; -+ default: -+ fe = NULL; -+ } -+ -+ if (fe == NULL) { -+ ret = -ENODEV; -+ goto err; -+ } -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+enum af9035_id_entry { -+ AF9035_15A4_9035, -+ AF9035_15A4_1001, -+ AF9035_0CCD_0093, -+ AF9035_07CA_A835, -+ AF9035_07CA_B835, -+ AF9035_07CA_1867, -+ AF9035_07CA_A867, -+ AF9035_07CA_0825, -+}; -+ -+static struct usb_device_id af9035_id[] = { -+ [AF9035_15A4_9035] = { -+ USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035)}, -+ [AF9035_15A4_1001] = { -+ USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_2)}, -+ [AF9035_0CCD_0093] = { -+ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK)}, -+ [AF9035_07CA_A835] = { -+ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835)}, -+ [AF9035_07CA_B835] = { -+ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835)}, -+ [AF9035_07CA_1867] = { -+ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867)}, -+ [AF9035_07CA_A867] = { -+ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867)}, -+ [AF9035_07CA_0825] = { -+ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR)}, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(usb, af9035_id); -+ -+static struct dvb_usb_device_properties af9035_properties[] = { -+ { -+ .caps = DVB_USB_IS_AN_I2C_ADAPTER, -+ -+ .usb_ctrl = DEVICE_SPECIFIC, -+ .download_firmware = af9035_download_firmware, -+ .firmware = "dvb-usb-af9035-02.fw", -+ .no_reconnect = 1, -+ -+ .num_adapters = 1, -+ .adapter = { -+ { -+ .num_frontends = 1, -+ .fe = { -+ { -+ .frontend_attach = af9035_frontend_attach, -+ .tuner_attach = af9035_tuner_attach, -+ .stream = { -+ .type = USB_BULK, -+ .count = 6, -+ .endpoint = 0x84, -+ .u = { -+ .bulk = { -+ .buffersize = (87 * 188), -+ } -+ } -+ } -+ } -+ } -+ } -+ }, -+ -+ .identify_state = af9035_identify_state, -+ .read_mac_address = af9035_read_mac_address, -+ -+ .i2c_algo = &af9035_i2c_algo, -+ -+ .num_device_descs = 5, -+ .devices = { -+ { -+ .name = "Afatech AF9035 reference design", -+ .cold_ids = { -+ &af9035_id[AF9035_15A4_9035], -+ &af9035_id[AF9035_15A4_1001], -+ }, -+ }, { -+ .name = "TerraTec Cinergy T Stick", -+ .cold_ids = { -+ &af9035_id[AF9035_0CCD_0093], -+ }, -+ }, { -+ .name = "AVerMedia AVerTV Volar HD/PRO (A835)", -+ .cold_ids = { -+ &af9035_id[AF9035_07CA_A835], -+ &af9035_id[AF9035_07CA_B835], -+ }, -+ }, { -+ .name = "AVerMedia HD Volar (A867)", -+ .cold_ids = { -+ &af9035_id[AF9035_07CA_1867], -+ &af9035_id[AF9035_07CA_A867], -+ }, -+ }, { -+ .name = "AVerMedia Twinstar (A825)", -+ .cold_ids = { -+ &af9035_id[AF9035_07CA_0825], -+ }, -+ }, -+ } -+ }, -+ { -+ .caps = DVB_USB_IS_AN_I2C_ADAPTER, -+ -+ .usb_ctrl = DEVICE_SPECIFIC, -+ .download_firmware = af9035_download_firmware_it9135, -+ .firmware = "dvb-usb-it9135-01.fw", -+ .no_reconnect = 1, -+ -+ .num_adapters = 1, -+ .adapter = { -+ { -+ .num_frontends = 1, -+ .fe = { -+ { -+ .frontend_attach = af9035_frontend_attach, -+ .tuner_attach = af9035_tuner_attach, -+ .stream = { -+ .type = USB_BULK, -+ .count = 6, -+ .endpoint = 0x84, -+ .u = { -+ .bulk = { -+ .buffersize = (87 * 188), -+ } -+ } -+ } -+ } -+ } -+ } -+ }, -+ -+ .identify_state = af9035_identify_state, -+ .read_mac_address = af9035_read_mac_address_it9135, -+ -+ .i2c_algo = &af9035_i2c_algo, -+ -+ .num_device_descs = 0, /* disabled as no support for IT9135 */ -+ .devices = { -+ { -+ .name = "ITE Tech. IT9135 reference design", -+ }, -+ } -+ }, -+}; -+ -+static int af9035_usb_probe(struct usb_interface *intf, -+ const struct usb_device_id *id) -+{ -+ int ret, i; -+ struct dvb_usb_device *d = NULL; -+ struct usb_device *udev; -+ bool found; -+ -+ pr_debug("%s: interface=%d\n", __func__, -+ intf->cur_altsetting->desc.bInterfaceNumber); -+ -+ /* interface 0 is used by DVB-T receiver and -+ interface 1 is for remote controller (HID) */ -+ if (intf->cur_altsetting->desc.bInterfaceNumber != 0) -+ return 0; -+ -+ /* Dynamic USB ID support. Replaces first device ID with current one. */ -+ udev = interface_to_usbdev(intf); -+ -+ for (i = 0, found = false; i < ARRAY_SIZE(af9035_id) - 1; i++) { -+ if (af9035_id[i].idVendor == -+ le16_to_cpu(udev->descriptor.idVendor) && -+ af9035_id[i].idProduct == -+ le16_to_cpu(udev->descriptor.idProduct)) { -+ found = true; -+ break; -+ } -+ } -+ -+ if (!found) { -+ pr_debug("%s: using dynamic ID %04x:%04x\n", __func__, -+ le16_to_cpu(udev->descriptor.idVendor), -+ le16_to_cpu(udev->descriptor.idProduct)); -+ af9035_properties[0].devices[0].cold_ids[0]->idVendor = -+ le16_to_cpu(udev->descriptor.idVendor); -+ af9035_properties[0].devices[0].cold_ids[0]->idProduct = -+ le16_to_cpu(udev->descriptor.idProduct); -+ } -+ -+ -+ for (i = 0; i < af9035_properties_count; i++) { -+ ret = dvb_usb_device_init(intf, &af9035_properties[i], -+ THIS_MODULE, &d, adapter_nr); -+ -+ if (ret == -ENODEV) -+ continue; -+ else -+ break; -+ } -+ -+ if (ret < 0) -+ goto err; -+ -+ if (d) { -+ ret = af9035_init(d); -+ if (ret < 0) -+ goto err; -+ } -+ -+ return 0; -+ -+err: -+ pr_debug("%s: failed=%d\n", __func__, ret); -+ -+ return ret; -+} -+ -+/* usb specific object needed to register this driver with the usb subsystem */ -+static struct usb_driver af9035_usb_driver = { -+ .name = "dvb_usb_af9035", -+ .probe = af9035_usb_probe, -+ .disconnect = dvb_usb_device_exit, -+ .id_table = af9035_id, -+}; -+ -+module_usb_driver(af9035_usb_driver); -+ -+MODULE_AUTHOR("Antti Palosaari "); -+MODULE_DESCRIPTION("Afatech AF9035 driver"); -+MODULE_LICENSE("GPL"); -Index: linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9035.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/dvb/dvb-usb/af9035.h -@@ -0,0 +1,120 @@ -+/* -+ * Afatech AF9035 DVB USB driver -+ * -+ * Copyright (C) 2009 Antti Palosaari -+ * Copyright (C) 2012 Antti Palosaari -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#ifndef AF9035_H -+#define AF9035_H -+ -+/* prefix for dvb-usb log writings */ -+#define DVB_USB_LOG_PREFIX "af9035" -+ -+#include "dvb-usb.h" -+ -+struct reg_val { -+ u32 reg; -+ u8 val; -+}; -+ -+struct reg_val_mask { -+ u32 reg; -+ u8 val; -+ u8 mask; -+}; -+ -+struct usb_req { -+ u8 cmd; -+ u8 mbox; -+ u8 wlen; -+ u8 *wbuf; -+ u8 rlen; -+ u8 *rbuf; -+}; -+ -+struct config { -+ bool dual_mode; -+ bool hw_not_supported; -+}; -+ -+struct fw_segment { -+#define SEGMENT_FW_DL 0 -+#define SEGMENT_ROM_COPY 1 -+#define SEGMENT_DIRECT_CMD 2 -+ u8 type; -+ u32 len; -+}; -+ -+struct fw_header { -+#define SEGMENT_MAX_COUNT 6 -+ u8 segment_count; -+ struct fw_segment segment[SEGMENT_MAX_COUNT]; -+}; -+ -+u32 clock_lut[] = { -+ 20480000, /* FPGA */ -+ 16384000, /* 16.38 MHz */ -+ 20480000, /* 20.48 MHz */ -+ 36000000, /* 36.00 MHz */ -+ 30000000, /* 30.00 MHz */ -+ 26000000, /* 26.00 MHz */ -+ 28000000, /* 28.00 MHz */ -+ 32000000, /* 32.00 MHz */ -+ 34000000, /* 34.00 MHz */ -+ 24000000, /* 24.00 MHz */ -+ 22000000, /* 22.00 MHz */ -+ 12000000, /* 12.00 MHz */ -+}; -+ -+u32 clock_lut_it9135[] = { -+ 12000000, /* 12.00 MHz */ -+ 20480000, /* 20.48 MHz */ -+ 36000000, /* 36.00 MHz */ -+ 30000000, /* 30.00 MHz */ -+ 26000000, /* 26.00 MHz */ -+ 28000000, /* 28.00 MHz */ -+ 32000000, /* 32.00 MHz */ -+ 34000000, /* 34.00 MHz */ -+ 24000000, /* 24.00 MHz */ -+ 22000000, /* 22.00 MHz */ -+}; -+ -+/* EEPROM locations */ -+#define EEPROM_IR_MODE 0x430d -+#define EEPROM_DUAL_MODE 0x4326 -+#define EEPROM_IR_TYPE 0x4329 -+#define EEPROM_1_IFFREQ_L 0x432d -+#define EEPROM_1_IFFREQ_H 0x432e -+#define EEPROM_1_TUNER_ID 0x4331 -+#define EEPROM_2_IFFREQ_L 0x433d -+#define EEPROM_2_IFFREQ_H 0x433e -+#define EEPROM_2_TUNER_ID 0x4341 -+ -+/* USB commands */ -+#define CMD_MEM_RD 0x00 -+#define CMD_MEM_WR 0x01 -+#define CMD_I2C_RD 0x02 -+#define CMD_I2C_WR 0x03 -+#define CMD_FW_DL 0x21 -+#define CMD_FW_QUERYINFO 0x22 -+#define CMD_FW_BOOT 0x23 -+#define CMD_FW_DL_BEGIN 0x24 -+#define CMD_FW_DL_END 0x25 -+#define CMD_FW_SCATTER_WR 0x29 -+ -+#endif -Index: linux-3.3.x86_64/MAINTAINERS -=================================================================== ---- linux-3.3.x86_64.orig/MAINTAINERS -+++ linux-3.3.x86_64/MAINTAINERS -@@ -2659,6 +2659,13 @@ S: Maintained - F: Documentation/hwmon/f71805f - F: drivers/hwmon/f71805f.c - -+FC0011 TUNER DRIVER -+M: Michael Buesch -+L: linux-media@vger.kernel.org -+S: Maintained -+F: drivers/media/common/tuners/fc0011.h -+F: drivers/media/common/tuners/fc0011.c -+ - FANOTIFY - M: Eric Paris - S: Maintained -Index: linux-3.3.x86_64/drivers/media/common/tuners/fc0011.c -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/common/tuners/fc0011.c -@@ -0,0 +1,524 @@ -+/* -+ * Fitipower FC0011 tuner driver -+ * -+ * Copyright (C) 2012 Michael Buesch -+ * -+ * Derived from FC0012 tuner driver: -+ * Copyright (C) 2012 Hans-Frieder Vogt -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include "fc0011.h" -+ -+ -+/* Tuner registers */ -+enum { -+ FC11_REG_0, -+ FC11_REG_FA, /* FA */ -+ FC11_REG_FP, /* FP */ -+ FC11_REG_XINHI, /* XIN high 8 bit */ -+ FC11_REG_XINLO, /* XIN low 8 bit */ -+ FC11_REG_VCO, /* VCO */ -+ FC11_REG_VCOSEL, /* VCO select */ -+ FC11_REG_7, /* Unknown tuner reg 7 */ -+ FC11_REG_8, /* Unknown tuner reg 8 */ -+ FC11_REG_9, -+ FC11_REG_10, /* Unknown tuner reg 10 */ -+ FC11_REG_11, /* Unknown tuner reg 11 */ -+ FC11_REG_12, -+ FC11_REG_RCCAL, /* RC calibrate */ -+ FC11_REG_VCOCAL, /* VCO calibrate */ -+ FC11_REG_15, -+ FC11_REG_16, /* Unknown tuner reg 16 */ -+ FC11_REG_17, -+ -+ FC11_NR_REGS, /* Number of registers */ -+}; -+ -+enum FC11_REG_VCOSEL_bits { -+ FC11_VCOSEL_2 = 0x08, /* VCO select 2 */ -+ FC11_VCOSEL_1 = 0x10, /* VCO select 1 */ -+ FC11_VCOSEL_CLKOUT = 0x20, /* Fix clock out */ -+ FC11_VCOSEL_BW7M = 0x40, /* 7MHz bw */ -+ FC11_VCOSEL_BW6M = 0x80, /* 6MHz bw */ -+}; -+ -+enum FC11_REG_RCCAL_bits { -+ FC11_RCCAL_FORCE = 0x10, /* force */ -+}; -+ -+enum FC11_REG_VCOCAL_bits { -+ FC11_VCOCAL_RUN = 0, /* VCO calibration run */ -+ FC11_VCOCAL_VALUEMASK = 0x3F, /* VCO calibration value mask */ -+ FC11_VCOCAL_OK = 0x40, /* VCO calibration Ok */ -+ FC11_VCOCAL_RESET = 0x80, /* VCO calibration reset */ -+}; -+ -+ -+struct fc0011_priv { -+ struct i2c_adapter *i2c; -+ u8 addr; -+ -+ u32 frequency; -+ u32 bandwidth; -+}; -+ -+ -+static int fc0011_writereg(struct fc0011_priv *priv, u8 reg, u8 val) -+{ -+ u8 buf[2] = { reg, val }; -+ struct i2c_msg msg = { .addr = priv->addr, -+ .flags = 0, .buf = buf, .len = 2 }; -+ -+ if (i2c_transfer(priv->i2c, &msg, 1) != 1) { -+ dev_err(&priv->i2c->dev, -+ "I2C write reg failed, reg: %02x, val: %02x\n", -+ reg, val); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+static int fc0011_readreg(struct fc0011_priv *priv, u8 reg, u8 *val) -+{ -+ u8 dummy; -+ struct i2c_msg msg[2] = { -+ { .addr = priv->addr, -+ .flags = 0, .buf = ®, .len = 1 }, -+ { .addr = priv->addr, -+ .flags = I2C_M_RD, .buf = val ? : &dummy, .len = 1 }, -+ }; -+ -+ if (i2c_transfer(priv->i2c, msg, 2) != 2) { -+ dev_err(&priv->i2c->dev, -+ "I2C read failed, reg: %02x\n", reg); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+static int fc0011_release(struct dvb_frontend *fe) -+{ -+ kfree(fe->tuner_priv); -+ fe->tuner_priv = NULL; -+ -+ return 0; -+} -+ -+static int fc0011_init(struct dvb_frontend *fe) -+{ -+ struct fc0011_priv *priv = fe->tuner_priv; -+ int err; -+ -+ if (WARN_ON(!fe->callback)) -+ return -EINVAL; -+ -+ err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, -+ FC0011_FE_CALLBACK_POWER, priv->addr); -+ if (err) { -+ dev_err(&priv->i2c->dev, "Power-on callback failed\n"); -+ return err; -+ } -+ err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, -+ FC0011_FE_CALLBACK_RESET, priv->addr); -+ if (err) { -+ dev_err(&priv->i2c->dev, "Reset callback failed\n"); -+ return err; -+ } -+ -+ return 0; -+} -+ -+/* Initiate VCO calibration */ -+static int fc0011_vcocal_trigger(struct fc0011_priv *priv) -+{ -+ int err; -+ -+ err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RESET); -+ if (err) -+ return err; -+ err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN); -+ if (err) -+ return err; -+ -+ return 0; -+} -+ -+/* Read VCO calibration value */ -+static int fc0011_vcocal_read(struct fc0011_priv *priv, u8 *value) -+{ -+ int err; -+ -+ err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN); -+ if (err) -+ return err; -+ usleep_range(10000, 20000); -+ err = fc0011_readreg(priv, FC11_REG_VCOCAL, value); -+ if (err) -+ return err; -+ -+ return 0; -+} -+ -+static int fc0011_set_params(struct dvb_frontend *fe) -+{ -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ struct fc0011_priv *priv = fe->tuner_priv; -+ int err; -+ unsigned int i, vco_retries; -+ u32 freq = p->frequency / 1000; -+ u32 bandwidth = p->bandwidth_hz / 1000; -+ u32 fvco, xin, xdiv, xdivr; -+ u16 frac; -+ u8 fa, fp, vco_sel, vco_cal; -+ u8 regs[FC11_NR_REGS] = { }; -+ -+ regs[FC11_REG_7] = 0x0F; -+ regs[FC11_REG_8] = 0x3E; -+ regs[FC11_REG_10] = 0xB8; -+ regs[FC11_REG_11] = 0x80; -+ regs[FC11_REG_RCCAL] = 0x04; -+ err = fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]); -+ err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]); -+ err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]); -+ err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]); -+ err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]); -+ if (err) -+ return -EIO; -+ -+ /* Set VCO freq and VCO div */ -+ if (freq < 54000) { -+ fvco = freq * 64; -+ regs[FC11_REG_VCO] = 0x82; -+ } else if (freq < 108000) { -+ fvco = freq * 32; -+ regs[FC11_REG_VCO] = 0x42; -+ } else if (freq < 216000) { -+ fvco = freq * 16; -+ regs[FC11_REG_VCO] = 0x22; -+ } else if (freq < 432000) { -+ fvco = freq * 8; -+ regs[FC11_REG_VCO] = 0x12; -+ } else { -+ fvco = freq * 4; -+ regs[FC11_REG_VCO] = 0x0A; -+ } -+ -+ /* Calc XIN. The PLL reference frequency is 18 MHz. */ -+ xdiv = fvco / 18000; -+ frac = fvco - xdiv * 18000; -+ frac = (frac << 15) / 18000; -+ if (frac >= 16384) -+ frac += 32786; -+ if (!frac) -+ xin = 0; -+ else if (frac < 511) -+ xin = 512; -+ else if (frac < 65026) -+ xin = frac; -+ else -+ xin = 65024; -+ regs[FC11_REG_XINHI] = xin >> 8; -+ regs[FC11_REG_XINLO] = xin; -+ -+ /* Calc FP and FA */ -+ xdivr = xdiv; -+ if (fvco - xdiv * 18000 >= 9000) -+ xdivr += 1; /* round */ -+ fp = xdivr / 8; -+ fa = xdivr - fp * 8; -+ if (fa < 2) { -+ fp -= 1; -+ fa += 8; -+ } -+ if (fp > 0x1F) { -+ fp &= 0x1F; -+ fa &= 0xF; -+ } -+ if (fa >= fp) { -+ dev_warn(&priv->i2c->dev, -+ "fa %02X >= fp %02X, but trying to continue\n", -+ (unsigned int)(u8)fa, (unsigned int)(u8)fp); -+ } -+ regs[FC11_REG_FA] = fa; -+ regs[FC11_REG_FP] = fp; -+ -+ /* Select bandwidth */ -+ switch (bandwidth) { -+ case 8000: -+ break; -+ case 7000: -+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW7M; -+ break; -+ default: -+ dev_warn(&priv->i2c->dev, "Unsupported bandwidth %u kHz. " -+ "Using 6000 kHz.\n", -+ bandwidth); -+ bandwidth = 6000; -+ /* fallthrough */ -+ case 6000: -+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW6M; -+ break; -+ } -+ -+ /* Pre VCO select */ -+ if (fvco < 2320000) { -+ vco_sel = 0; -+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); -+ } else if (fvco < 3080000) { -+ vco_sel = 1; -+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); -+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1; -+ } else { -+ vco_sel = 2; -+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); -+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2; -+ } -+ -+ /* Fix for low freqs */ -+ if (freq < 45000) { -+ regs[FC11_REG_FA] = 0x6; -+ regs[FC11_REG_FP] = 0x11; -+ } -+ -+ /* Clock out fix */ -+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_CLKOUT; -+ -+ /* Write the cached registers */ -+ for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++) { -+ err = fc0011_writereg(priv, i, regs[i]); -+ if (err) -+ return err; -+ } -+ -+ /* VCO calibration */ -+ err = fc0011_vcocal_trigger(priv); -+ if (err) -+ return err; -+ err = fc0011_vcocal_read(priv, &vco_cal); -+ if (err) -+ return err; -+ vco_retries = 0; -+ while (!(vco_cal & FC11_VCOCAL_OK) && vco_retries < 3) { -+ /* Reset the tuner and try again */ -+ err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, -+ FC0011_FE_CALLBACK_RESET, priv->addr); -+ if (err) { -+ dev_err(&priv->i2c->dev, "Failed to reset tuner\n"); -+ return err; -+ } -+ /* Reinit tuner config */ -+ err = 0; -+ for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++) -+ err |= fc0011_writereg(priv, i, regs[i]); -+ err |= fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]); -+ err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]); -+ err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]); -+ err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]); -+ err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]); -+ if (err) -+ return -EIO; -+ /* VCO calibration */ -+ err = fc0011_vcocal_trigger(priv); -+ if (err) -+ return err; -+ err = fc0011_vcocal_read(priv, &vco_cal); -+ if (err) -+ return err; -+ vco_retries++; -+ } -+ if (!(vco_cal & FC11_VCOCAL_OK)) { -+ dev_err(&priv->i2c->dev, -+ "Failed to read VCO calibration value (got %02X)\n", -+ (unsigned int)vco_cal); -+ return -EIO; -+ } -+ vco_cal &= FC11_VCOCAL_VALUEMASK; -+ -+ switch (vco_sel) { -+ case 0: -+ if (vco_cal < 8) { -+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); -+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1; -+ err = fc0011_writereg(priv, FC11_REG_VCOSEL, -+ regs[FC11_REG_VCOSEL]); -+ if (err) -+ return err; -+ err = fc0011_vcocal_trigger(priv); -+ if (err) -+ return err; -+ } else { -+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); -+ err = fc0011_writereg(priv, FC11_REG_VCOSEL, -+ regs[FC11_REG_VCOSEL]); -+ if (err) -+ return err; -+ } -+ break; -+ case 1: -+ if (vco_cal < 5) { -+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); -+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2; -+ err = fc0011_writereg(priv, FC11_REG_VCOSEL, -+ regs[FC11_REG_VCOSEL]); -+ if (err) -+ return err; -+ err = fc0011_vcocal_trigger(priv); -+ if (err) -+ return err; -+ } else if (vco_cal <= 48) { -+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); -+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1; -+ err = fc0011_writereg(priv, FC11_REG_VCOSEL, -+ regs[FC11_REG_VCOSEL]); -+ if (err) -+ return err; -+ } else { -+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); -+ err = fc0011_writereg(priv, FC11_REG_VCOSEL, -+ regs[FC11_REG_VCOSEL]); -+ if (err) -+ return err; -+ err = fc0011_vcocal_trigger(priv); -+ if (err) -+ return err; -+ } -+ break; -+ case 2: -+ if (vco_cal > 53) { -+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); -+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1; -+ err = fc0011_writereg(priv, FC11_REG_VCOSEL, -+ regs[FC11_REG_VCOSEL]); -+ if (err) -+ return err; -+ err = fc0011_vcocal_trigger(priv); -+ if (err) -+ return err; -+ } else { -+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); -+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2; -+ err = fc0011_writereg(priv, FC11_REG_VCOSEL, -+ regs[FC11_REG_VCOSEL]); -+ if (err) -+ return err; -+ } -+ break; -+ } -+ err = fc0011_vcocal_read(priv, NULL); -+ if (err) -+ return err; -+ usleep_range(10000, 50000); -+ -+ err = fc0011_readreg(priv, FC11_REG_RCCAL, ®s[FC11_REG_RCCAL]); -+ if (err) -+ return err; -+ regs[FC11_REG_RCCAL] |= FC11_RCCAL_FORCE; -+ err = fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]); -+ if (err) -+ return err; -+ err = fc0011_writereg(priv, FC11_REG_16, 0xB); -+ if (err) -+ return err; -+ -+ dev_dbg(&priv->i2c->dev, "Tuned to " -+ "fa=%02X fp=%02X xin=%02X%02X vco=%02X vcosel=%02X " -+ "vcocal=%02X(%u) bw=%u\n", -+ (unsigned int)regs[FC11_REG_FA], -+ (unsigned int)regs[FC11_REG_FP], -+ (unsigned int)regs[FC11_REG_XINHI], -+ (unsigned int)regs[FC11_REG_XINLO], -+ (unsigned int)regs[FC11_REG_VCO], -+ (unsigned int)regs[FC11_REG_VCOSEL], -+ (unsigned int)vco_cal, vco_retries, -+ (unsigned int)bandwidth); -+ -+ priv->frequency = p->frequency; -+ priv->bandwidth = p->bandwidth_hz; -+ -+ return 0; -+} -+ -+static int fc0011_get_frequency(struct dvb_frontend *fe, u32 *frequency) -+{ -+ struct fc0011_priv *priv = fe->tuner_priv; -+ -+ *frequency = priv->frequency; -+ -+ return 0; -+} -+ -+static int fc0011_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) -+{ -+ *frequency = 0; -+ -+ return 0; -+} -+ -+static int fc0011_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) -+{ -+ struct fc0011_priv *priv = fe->tuner_priv; -+ -+ *bandwidth = priv->bandwidth; -+ -+ return 0; -+} -+ -+static const struct dvb_tuner_ops fc0011_tuner_ops = { -+ .info = { -+ .name = "Fitipower FC0011", -+ -+ .frequency_min = 45000000, -+ .frequency_max = 1000000000, -+ }, -+ -+ .release = fc0011_release, -+ .init = fc0011_init, -+ -+ .set_params = fc0011_set_params, -+ -+ .get_frequency = fc0011_get_frequency, -+ .get_if_frequency = fc0011_get_if_frequency, -+ .get_bandwidth = fc0011_get_bandwidth, -+}; -+ -+struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, -+ const struct fc0011_config *config) -+{ -+ struct fc0011_priv *priv; -+ -+ priv = kzalloc(sizeof(struct fc0011_priv), GFP_KERNEL); -+ if (!priv) -+ return NULL; -+ -+ priv->i2c = i2c; -+ priv->addr = config->i2c_address; -+ -+ fe->tuner_priv = priv; -+ fe->ops.tuner_ops = fc0011_tuner_ops; -+ -+ dev_info(&priv->i2c->dev, "Fitipower FC0011 tuner attached\n"); -+ -+ return fe; -+} -+EXPORT_SYMBOL(fc0011_attach); -+ -+MODULE_DESCRIPTION("Fitipower FC0011 silicon tuner driver"); -+MODULE_AUTHOR("Michael Buesch "); -+MODULE_LICENSE("GPL"); -Index: linux-3.3.x86_64/drivers/media/common/tuners/fc0011.h -=================================================================== ---- /dev/null -+++ linux-3.3.x86_64/drivers/media/common/tuners/fc0011.h -@@ -0,0 +1,41 @@ -+#ifndef LINUX_FC0011_H_ -+#define LINUX_FC0011_H_ -+ -+#include "dvb_frontend.h" -+ -+ -+/** struct fc0011_config - fc0011 hardware config -+ * -+ * @i2c_address: I2C bus address. -+ */ -+struct fc0011_config { -+ u8 i2c_address; -+}; -+ -+/** enum fc0011_fe_callback_commands - Frontend callbacks -+ * -+ * @FC0011_FE_CALLBACK_POWER: Power on tuner hardware. -+ * @FC0011_FE_CALLBACK_RESET: Request a tuner reset. -+ */ -+enum fc0011_fe_callback_commands { -+ FC0011_FE_CALLBACK_POWER, -+ FC0011_FE_CALLBACK_RESET, -+}; -+ -+#if defined(CONFIG_MEDIA_TUNER_FC0011) ||\ -+ defined(CONFIG_MEDIA_TUNER_FC0011_MODULE) -+struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, -+ const struct fc0011_config *config); -+#else -+static inline -+struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, -+ const struct fc0011_config *config) -+{ -+ dev_err(&i2c->dev, "fc0011 driver disabled in Kconfig\n"); -+ return NULL; -+} -+#endif -+ -+#endif /* LINUX_FC0011_H_ */ diff --git a/drm-i915-dp-stfu.patch b/drm-i915-dp-stfu.patch index 8948229dc..c005a06ba 100644 --- a/drm-i915-dp-stfu.patch +++ b/drm-i915-dp-stfu.patch @@ -1,21 +1,8 @@ -From 04a43e2598db35b3d0ec25925bb8475b5c0a3809 Mon Sep 17 00:00:00 2001 -From: Adam Jackson -Date: Fri, 16 Mar 2012 16:39:11 -0400 -Subject: [PATCH] drm/i915/dp: Use DRM_ERROR not WARN for sanity checks - -These are noisy as shit and creating a ton of abrt reports. I don't -need more, thanks. Proper fix upstream eventually. - -Signed-off-by: Adam Jackson ---- - drivers/gpu/drm/i915/intel_dp.c | 14 ++++++++------ - 1 files changed, 8 insertions(+), 6 deletions(-) - diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c -index 94f860c..6bf27c9 100644 +index 296cfc2..516e1e2 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c -@@ -331,7 +331,7 @@ intel_dp_check_edp(struct intel_dp *intel_dp) +@@ -350,7 +350,7 @@ intel_dp_check_edp(struct intel_dp *intel_dp) if (!is_edp(intel_dp)) return; if (!ironlake_edp_have_panel_power(intel_dp) && !ironlake_edp_have_panel_vdd(intel_dp)) { @@ -24,7 +11,7 @@ index 94f860c..6bf27c9 100644 DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n", I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL)); -@@ -386,7 +386,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, +@@ -400,7 +400,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, } if (try == 3) { @@ -33,7 +20,7 @@ index 94f860c..6bf27c9 100644 I915_READ(ch_ctl)); return -EBUSY; } -@@ -992,8 +992,8 @@ static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) +@@ -1024,8 +1024,8 @@ static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) return; DRM_DEBUG_KMS("Turn eDP VDD on\n"); @@ -44,7 +31,7 @@ index 94f860c..6bf27c9 100644 intel_dp->want_panel_vdd = true; -@@ -1058,7 +1058,8 @@ static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) +@@ -1090,7 +1090,8 @@ static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) return; DRM_DEBUG_KMS("Turn eDP VDD off %d\n", intel_dp->want_panel_vdd); @@ -54,16 +41,13 @@ index 94f860c..6bf27c9 100644 intel_dp->want_panel_vdd = false; -@@ -1128,7 +1129,8 @@ static void ironlake_edp_panel_off(struct intel_dp *intel_dp) +@@ -1160,7 +1161,8 @@ static void ironlake_edp_panel_off(struct intel_dp *intel_dp) DRM_DEBUG_KMS("Turn eDP power off\n"); -- WARN(intel_dp->want_panel_vdd, "Cannot turn power off while VDD is on\n"); -+ if (intel_dp->want_panel_vdd) -+ DRM_ERROR("Cannot turn power off while VDD is on\n"); +- WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n"); ++ if (!intel_dp->want_panel_vdd) ++ DRM_ERROR("Need VDD to turn off panel\n"); pp = ironlake_get_pp_control(dev_priv); - pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE); --- -1.7.7.6 - + pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE); diff --git a/ext4-Support-check-none-nocheck-mount-options.patch b/ext4-Support-check-none-nocheck-mount-options.patch deleted file mode 100644 index 281e4237a..000000000 --- a/ext4-Support-check-none-nocheck-mount-options.patch +++ /dev/null @@ -1,51 +0,0 @@ -From ea75f7357e3a881bd1bd0db5e483fc6a8681567b Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Tue, 10 Jan 2012 09:39:02 -0500 -Subject: [PATCH] ext4: Support "check=none" "nocheck" mount options - -The ext2/ext3 filesystems supported "check=none" and "nocheck" as mount options -even though that was already the default behavior and it essentially did -nothing. When using ext4 to mount ext2/ext3 filesystems, that mount option -causes the mount to fail. That isn't as backward compatible as it could be, -so add support to ext4 to accept the option. - -Signed-off-by: Josh Boyer ---- - fs/ext4/super.c | 7 ++++++- - 1 files changed, 6 insertions(+), 1 deletions(-) - -diff --git a/fs/ext4/super.c b/fs/ext4/super.c -index 3e1329e..5ff09e7 100644 ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -1333,7 +1333,7 @@ enum { - Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, - Opt_inode_readahead_blks, Opt_journal_ioprio, - Opt_dioread_nolock, Opt_dioread_lock, -- Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable, -+ Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable, Opt_nocheck, - }; - - static const match_table_t tokens = { -@@ -1409,6 +1409,8 @@ static const match_table_t tokens = { - {Opt_init_itable, "init_itable=%u"}, - {Opt_init_itable, "init_itable"}, - {Opt_noinit_itable, "noinit_itable"}, -+ {Opt_nocheck, "check=none"}, -+ {Opt_nocheck, "nocheck"}, - {Opt_err, NULL}, - }; - -@@ -1905,6 +1907,9 @@ set_qf_format: - case Opt_noinit_itable: - clear_opt(sb, INIT_INODE_TABLE); - break; -+ case Opt_nocheck: -+ /* ext2/ext3 used to "support" this option. Silently eat it */ -+ break; - default: - ext4_msg(sb, KERN_ERR, - "Unrecognized mount option \"%s\" " --- -1.7.7.5 - diff --git a/floppy-drop-disable_hlt-warning.patch b/floppy-drop-disable_hlt-warning.patch deleted file mode 100644 index 8f0849e1e..000000000 --- a/floppy-drop-disable_hlt-warning.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c -index 9955a53..aef66d1 100644 ---- a/drivers/block/floppy.c -+++ b/drivers/block/floppy.c -@@ -1038,7 +1038,7 @@ static void floppy_disable_hlt(void) - { - unsigned long flags; - -- WARN_ONCE(1, "floppy_disable_hlt() scheduled for removal in 2012"); -+ printk(KERN_INFO "floppy_disable_hlt() scheduled for removal in 2012"); - spin_lock_irqsave(&floppy_hlt_lock, flags); - if (!hlt_disabled) { - hlt_disabled = 1; diff --git a/hugetlb-fix-resv_map-leak-in-error-path.patch b/hugetlb-fix-resv_map-leak-in-error-path.patch deleted file mode 100644 index 888d5ce70..000000000 --- a/hugetlb-fix-resv_map-leak-in-error-path.patch +++ /dev/null @@ -1,176 +0,0 @@ -From c50ac050811d6485616a193eb0f37bfbd191cc89 Mon Sep 17 00:00:00 2001 -From: Dave Hansen -Date: Tue, 29 May 2012 15:06:46 -0700 -Subject: [PATCH] hugetlb: fix resv_map leak in error path - -When called for anonymous (non-shared) mappings, hugetlb_reserve_pages() -does a resv_map_alloc(). It depends on code in hugetlbfs's -vm_ops->close() to release that allocation. - -However, in the mmap() failure path, we do a plain unmap_region() without -the remove_vma() which actually calls vm_ops->close(). - -This is a decent fix. This leak could get reintroduced if new code (say, -after hugetlb_reserve_pages() in hugetlbfs_file_mmap()) decides to return -an error. But, I think it would have to unroll the reservation anyway. - -Christoph's test case: - - http://marc.info/?l=linux-mm&m=133728900729735 - -This patch applies to 3.4 and later. A version for earlier kernels is at -https://lkml.org/lkml/2012/5/22/418. - -Signed-off-by: Dave Hansen -Acked-by: Mel Gorman -Acked-by: KOSAKI Motohiro -Reported-by: Christoph Lameter -Tested-by: Christoph Lameter -Cc: Andrea Arcangeli -Cc: [2.6.32+] -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds ---- - mm/hugetlb.c | 28 ++++++++++++++++++++++------ - 1 files changed, 22 insertions(+), 6 deletions(-) - -diff --git a/mm/hugetlb.c b/mm/hugetlb.c -index 41a647d..285a81e 100644 ---- a/mm/hugetlb.c -+++ b/mm/hugetlb.c -@@ -2157,6 +2157,15 @@ static void hugetlb_vm_op_open(struct vm_area_struct *vma) - kref_get(&reservations->refs); - } - -+static void resv_map_put(struct vm_area_struct *vma) -+{ -+ struct resv_map *reservations = vma_resv_map(vma); -+ -+ if (!reservations) -+ return; -+ kref_put(&reservations->refs, resv_map_release); -+} -+ - static void hugetlb_vm_op_close(struct vm_area_struct *vma) - { - struct hstate *h = hstate_vma(vma); -@@ -2173,7 +2182,7 @@ static void hugetlb_vm_op_close(struct vm_area_struct *vma) - reserve = (end - start) - - region_count(&reservations->regions, start, end); - -- kref_put(&reservations->refs, resv_map_release); -+ resv_map_put(vma); - - if (reserve) { - hugetlb_acct_memory(h, -reserve); -@@ -2991,12 +3000,16 @@ int hugetlb_reserve_pages(struct inode *inode, - set_vma_resv_flags(vma, HPAGE_RESV_OWNER); - } - -- if (chg < 0) -- return chg; -+ if (chg < 0) { -+ ret = chg; -+ goto out_err; -+ } - - /* There must be enough pages in the subpool for the mapping */ -- if (hugepage_subpool_get_pages(spool, chg)) -- return -ENOSPC; -+ if (hugepage_subpool_get_pages(spool, chg)) { -+ ret = -ENOSPC; -+ goto out_err; -+ } - - /* - * Check enough hugepages are available for the reservation. -@@ -3005,7 +3018,7 @@ int hugetlb_reserve_pages(struct inode *inode, - ret = hugetlb_acct_memory(h, chg); - if (ret < 0) { - hugepage_subpool_put_pages(spool, chg); -- return ret; -+ goto out_err; - } - - /* -@@ -3022,6 +3035,9 @@ int hugetlb_reserve_pages(struct inode *inode, - if (!vma || vma->vm_flags & VM_MAYSHARE) - region_add(&inode->i_mapping->private_list, from, to); - return 0; -+out_err: -+ resv_map_put(vma); -+ return ret; - } - - void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed) --- -1.7.7.6 - -From 4523e1458566a0e8ecfaff90f380dd23acc44d27 Mon Sep 17 00:00:00 2001 -From: Dave Hansen -Date: Wed, 30 May 2012 07:51:07 -0700 -Subject: [PATCH] mm: fix vma_resv_map() NULL pointer - -hugetlb_reserve_pages() can be used for either normal file-backed -hugetlbfs mappings, or MAP_HUGETLB. In the MAP_HUGETLB, semi-anonymous -mode, there is not a VMA around. The new call to resv_map_put() assumed -that there was, and resulted in a NULL pointer dereference: - - BUG: unable to handle kernel NULL pointer dereference at 0000000000000030 - IP: vma_resv_map+0x9/0x30 - PGD 141453067 PUD 1421e1067 PMD 0 - Oops: 0000 [#1] PREEMPT SMP - ... - Pid: 14006, comm: trinity-child6 Not tainted 3.4.0+ #36 - RIP: vma_resv_map+0x9/0x30 - ... - Process trinity-child6 (pid: 14006, threadinfo ffff8801414e0000, task ffff8801414f26b0) - Call Trace: - resv_map_put+0xe/0x40 - hugetlb_reserve_pages+0xa6/0x1d0 - hugetlb_file_setup+0x102/0x2c0 - newseg+0x115/0x360 - ipcget+0x1ce/0x310 - sys_shmget+0x5a/0x60 - system_call_fastpath+0x16/0x1b - -This was reported by Dave Jones, but was reproducible with the -libhugetlbfs test cases, so shame on me for not running them in the -first place. - -With this, the oops is gone, and the output of libhugetlbfs's -run_tests.py is identical to plain 3.4 again. - -[ Marked for stable, since this was introduced by commit c50ac050811d - ("hugetlb: fix resv_map leak in error path") which was also marked for - stable ] - -Reported-by: Dave Jones -Cc: Mel Gorman -Cc: KOSAKI Motohiro -Cc: Christoph Lameter -Cc: Andrea Arcangeli -Cc: Andrew Morton -Cc: [2.6.32+] -Signed-off-by: Linus Torvalds ---- - mm/hugetlb.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/mm/hugetlb.c b/mm/hugetlb.c -index 285a81e..e198831 100644 ---- a/mm/hugetlb.c -+++ b/mm/hugetlb.c -@@ -3036,7 +3036,8 @@ int hugetlb_reserve_pages(struct inode *inode, - region_add(&inode->i_mapping->private_list, from, to); - return 0; - out_err: -- resv_map_put(vma); -+ if (vma) -+ resv_map_put(vma); - return ret; - } - --- -1.7.7.6 - diff --git a/iwlwifi-disable-the-buggy-chain-extension-feature-in-HW.patch b/iwlwifi-disable-the-buggy-chain-extension-feature-in-HW.patch new file mode 100644 index 000000000..c4f2ed3a1 --- /dev/null +++ b/iwlwifi-disable-the-buggy-chain-extension-feature-in-HW.patch @@ -0,0 +1,48 @@ +From d012d04e4d6312ea157b6cf19e9689af934f5aa7 Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Wed, 6 Jun 2012 13:55:02 +0200 +Subject: [PATCH] iwlwifi: disable the buggy chain extension feature in HW + +This feature has been reported to be buggy and enabled by +default. We therefore need to disable it manually. + +Cc: stable@vger.kernel.org +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +Signed-off-by: John W. Linville +--- + drivers/net/wireless/iwlwifi/iwl-prph.h | 1 + + drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 5 +++++ + 2 files changed, 6 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h +index 3b10692..dfd5466 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-prph.h ++++ b/drivers/net/wireless/iwlwifi/iwl-prph.h +@@ -224,6 +224,7 @@ + #define SCD_TXFACT (SCD_BASE + 0x10) + #define SCD_ACTIVE (SCD_BASE + 0x14) + #define SCD_QUEUECHAIN_SEL (SCD_BASE + 0xe8) ++#define SCD_CHAINEXT_EN (SCD_BASE + 0x244) + #define SCD_AGGR_SEL (SCD_BASE + 0x248) + #define SCD_INTERRUPT_MASK (SCD_BASE + 0x108) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +index ec6fb39..79c6b91 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c ++++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +@@ -1058,6 +1058,11 @@ static void iwl_tx_start(struct iwl_trans *trans) + iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, + trans_pcie->scd_bc_tbls.dma >> 10); + ++ /* The chain extension of the SCD doesn't work well. This feature is ++ * enabled by default by the HW, so we need to disable it manually. ++ */ ++ iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); ++ + /* Enable DMA channel */ + for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) + iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), +-- +1.7.7.6 + diff --git a/iwlwifi-dont-mess-up-the-SCD-when-removing-a-key.patch b/iwlwifi-dont-mess-up-the-SCD-when-removing-a-key.patch new file mode 100644 index 000000000..f7c3c7181 --- /dev/null +++ b/iwlwifi-dont-mess-up-the-SCD-when-removing-a-key.patch @@ -0,0 +1,45 @@ +From d6ee27eb13beab94056e0de52d81220058ca2297 Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Wed, 6 Jun 2012 09:13:36 +0200 +Subject: [PATCH] iwlwifi: don't mess up the SCD when removing a key + +When we remove a key, we put a key index which was supposed +to tell the fw that we are actually removing the key. But +instead the fw took that index as a valid index and messed +up the SRAM of the device. + +This memory corruption on the device mangled the data of +the SCD. The impact on the user is that SCD queue 2 got +stuck after having removed keys. +The message is the log that was printed is: + +Queue 2 stuck for 10000ms + +This doesn't seem to fix the higher queues that get stuck +from time to time. + +Cc: stable@vger.kernel.org [2.6.27+] +Reviewed-by: Meenakshi Venkataraman +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +Signed-off-by: John W. Linville +--- + drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +index aea07aa..eb6a8ea 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +@@ -1267,7 +1267,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, + key_flags |= STA_KEY_MULTICAST_MSK; + + sta_cmd.key.key_flags = key_flags; +- sta_cmd.key.key_offset = WEP_INVALID_OFFSET; ++ sta_cmd.key.key_offset = keyconf->hw_key_idx; + sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK; + sta_cmd.mode = STA_CONTROL_MODIFY_MSK; + +-- +1.7.6.5 + diff --git a/kernel.spec b/kernel.spec index 7a442ed55..068ded8b9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -60,13 +60,13 @@ Summary: The Linux kernel # base_sublevel is the kernel version we're starting with and patching # on top of -- for example, 2.6.22-rc7-git1 starts with a 2.6.21 base, # which yields a base_sublevel of 21. -%define base_sublevel 3 +%define base_sublevel 4 ## If this is a released kernel ## %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 8 +%define stable_update 2 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -409,12 +409,13 @@ Summary: The Linux kernel # we build a up kernel on armv5tel. its used for qemu. %ifnarch armv5tel %define with_up 0 -%define with_perf 0 %endif # we only build headers on the base arm arches # just like we used to only build them on i386 for x86 %ifnarch armv5tel armv7hl %define with_headers 0 +%define with_perf 0 +%define with_tools 0 %endif %endif @@ -661,8 +662,6 @@ Patch160: linux-2.6-32bit-mmap-exec-randomization.patch Patch161: linux-2.6-i386-nx-emulation.patch Patch162: nx-emu-remove-cpuinitdata-for-disable_nx-on-x86_32.patch -Patch383: linux-2.6-defaults-aspm.patch - Patch390: linux-2.6-defaults-acpi-video.patch Patch391: linux-2.6-acpi-video-dos.patch Patch394: linux-2.6-acpi-debug-infinite-loop.patch @@ -674,10 +673,8 @@ Patch452: linux-2.6.30-no-pcspkr-modalias.patch Patch460: linux-2.6-serial-460800.patch Patch470: die-floppy-die.patch -Patch471: floppy-drop-disable_hlt-warning.patch Patch510: linux-2.6-silence-noise.patch -Patch511: silence-timekeeping-spew.patch Patch520: quite-apm.patch Patch530: linux-2.6-silence-fbcon-logo.patch @@ -707,8 +704,6 @@ Patch1900: linux-2.6-intel-iommu-igfx.patch Patch2802: linux-2.6-silence-acpi-blacklist.patch # media patches -# add-poll-requested-events.patch was added for 3.4 -Patch2900: add-poll-requested-events.patch Patch2901: drivers-media-update.patch # fs fixes @@ -717,14 +712,6 @@ Patch2901: drivers-media-update.patch Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # NFSv4 -Patch4000: NFSv4-Reduce-the-footprint-of-the-idmapper.patch -Patch4001: NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch -Patch4107: NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch - -# NFS Client Patch set from Upstream -Patch4113: NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch -Patch4114: NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch -Patch4115: NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch # patches headed upstream @@ -736,48 +723,25 @@ Patch13003: efi-dont-map-boot-services-on-32bit.patch Patch14010: lis3-improve-handling-of-null-rate.patch -Patch15000: bluetooth-use-after-free.patch - Patch19000: ips-noirq.patch -Patch20000: utrace.patch - # Flattened devicetree support Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch -Patch21070: ext4-Support-check-none-nocheck-mount-options.patch - #rhbz 769766 Patch21072: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch Patch21226: pci-crs-blacklist.patch -#rhbz 772772 -Patch21232: rt2x00_fix_MCU_request_failures.patch - #rhbz 754518 #Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch -#rhbz 789644 -Patch21237: mcelog-rcu-splat.patch - Patch21300: unhandled-irqs-switch-to-polling.patch #rhbz 804957 CVE-2012-1568 Patch21306: shlib_base_randomize.patch -#rhbz 804347 -Patch21351: x86-add-io_apic_ops-to-allow-interception.patch -Patch21352: x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch -Patch21353: xen-x86-Implement-x86_apic_ops.patch - -#rhbz 808559 -Patch21530: ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch - -#rhbz 806295 -Patch21710: disable-hid-battery.patch - # Debug patches Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch @@ -789,7 +753,7 @@ Patch22007: macvtap-zerocopy-validate-vector-length.patch Patch22013: ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch #rhbz 749276 -Patch22018: atl1c_net_next_update-3.3.patch +Patch22018: atl1c_net_next_update-3.4.patch #rhbz 795176 Patch22019: rtl818x-fix-sleeping-function-called-from-invalid-context.patch @@ -797,8 +761,16 @@ Patch22019: rtl818x-fix-sleeping-function-called-from-invalid-context.patch #rhbz 822825 822821 CVE-2012-2372 Patch22021: mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch -#rhbz 824352 824345 CVE-2012-2390 -Patch22022: hugetlb-fix-resv_map-leak-in-error-path.patch +#rhbz 829016 +Patch22022: thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch + +#rhbz 825491 +Patch22023: iwlwifi-disable-the-buggy-chain-extension-feature-in-HW.patch +Patch22024: iwlwifi-dont-mess-up-the-SCD-when-removing-a-key.patch + +#rhbz 830862 +Patch22030: SUNRPC-new-svc_bind-routine-introduced.patch +Patch22031: SUNRPC-move-per-net-operations-from-svc_destroy.patch # END OF PATCH DEFINITIONS @@ -1304,7 +1276,7 @@ ApplyOptionalPatch linux-2.6-upstream-reverts.patch -R # ARM # # ApplyPatch arm-omap-dt-compat.patch -ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch +# ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch ApplyPatch taint-vbox.patch # @@ -1333,14 +1305,6 @@ ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # eCryptfs # NFSv4 -ApplyPatch NFSv4-Reduce-the-footprint-of-the-idmapper.patch -ApplyPatch NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch -ApplyPatch NFSv4-Minor-cleanups-for-nfs4_handle_exception-and-n.patch - -# NFS Client Patch set from Upstream -ApplyPatch NFS-optimise-away-unnecessary-setattrs-for-open-O_TRUNC.patch -ApplyPatch NFSv4-fix-open-O_TRUNC-and-ftruncate-error-handling.patch -ApplyPatch NFSv4-Rate-limit-the-state-manager-for-lock-reclaim-.patch # USB @@ -1355,8 +1319,6 @@ ApplyPatch acpi-sony-nonvs-blacklist.patch # # PCI # -# enable ASPM by default on hardware we expect to work -ApplyPatch linux-2.6-defaults-aspm.patch # # SCSI Bits. @@ -1366,9 +1328,6 @@ ApplyPatch linux-2.6-defaults-aspm.patch # ALSA -#rhbz 808559 -ApplyPatch ALSA-hda-realtek-Add-quirk-for-Mac-Pro-5-1-machines.patch - # Networking @@ -1378,7 +1337,6 @@ ApplyPatch linux-2.6-input-kill-stupid-messages.patch # stop floppy.ko from autoloading during udev... ApplyPatch die-floppy-die.patch -ApplyPatch floppy-drop-disable_hlt-warning.patch ApplyPatch linux-2.6.30-no-pcspkr-modalias.patch @@ -1388,8 +1346,6 @@ ApplyPatch linux-2.6-serial-460800.patch # Silence some useless messages that still get printed with 'quiet' ApplyPatch linux-2.6-silence-noise.patch -ApplyPatch silence-timekeeping-spew.patch - # Make fbcon not show the penguins with 'quiet' ApplyPatch linux-2.6-silence-fbcon-logo.patch @@ -1423,7 +1379,6 @@ ApplyPatch quite-apm.patch # Media (V4L/DVB/IR) updates/fixes/experimental drivers # apply if non-empty -ApplyPatch add-poll-requested-events.patch ApplyOptionalPatch drivers-media-update.patch # Patches headed upstream @@ -1437,40 +1392,19 @@ ApplyPatch efi-dont-map-boot-services-on-32bit.patch ApplyPatch lis3-improve-handling-of-null-rate.patch -ApplyPatch bluetooth-use-after-free.patch - ApplyPatch ips-noirq.patch -# utrace. -ApplyPatch utrace.patch - #ApplyPatch pci-crs-blacklist.patch -ApplyPatch ext4-Support-check-none-nocheck-mount-options.patch - -#rhbz 772772 -ApplyPatch rt2x00_fix_MCU_request_failures.patch - #rhbz 754518 #ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch -#rhbz 789644 -ApplyPatch mcelog-rcu-splat.patch - ApplyPatch unhandled-irqs-switch-to-polling.patch # debug patches ApplyPatch weird-root-dentry-name-debug.patch ApplyPatch debug-808990.patch -#rhbz 804347 -ApplyPatch x86-add-io_apic_ops-to-allow-interception.patch -ApplyPatch x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch -ApplyPatch xen-x86-Implement-x86_apic_ops.patch - -#rhbz 806295 -ApplyPatch disable-hid-battery.patch - #rhbz 814278 814289 CVE-2012-2119 ApplyPatch macvtap-zerocopy-validate-vector-length.patch @@ -1478,7 +1412,7 @@ ApplyPatch macvtap-zerocopy-validate-vector-length.patch ApplyPatch ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch #rhbz 749276 -ApplyPatch atl1c_net_next_update-3.3.patch +ApplyPatch atl1c_net_next_update-3.4.patch #rhbz 795176 ApplyPatch rtl818x-fix-sleeping-function-called-from-invalid-context.patch @@ -1486,8 +1420,15 @@ ApplyPatch rtl818x-fix-sleeping-function-called-from-invalid-context.patch #rhbz 822825 822821 CVE-2012-2372 ApplyPatch mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch -#rhbz 824352 824345 CVE-2012-2390 -ApplyPatch hugetlb-fix-resv_map-leak-in-error-path.patch +ApplyPatch thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch + +#rhbz 825491 +ApplyPatch iwlwifi-disable-the-buggy-chain-extension-feature-in-HW.patch +ApplyPatch iwlwifi-dont-mess-up-the-SCD-when-removing-a-key.patch + +#rhbz 830862 +ApplyPatch SUNRPC-new-svc_bind-routine-introduced.patch +ApplyPatch SUNRPC-move-per-net-operations-from-svc_destroy.patch # END OF PATCH APPLICATIONS @@ -2227,6 +2168,9 @@ fi # and build. %changelog +* Thu Jun 14 2012 Justin M. Forbes 3.4.2-1 +- Linux 3.4.2 + * Mon Jun 04 2012 Josh Boyer 3.3.8-1 - Linux v3.3.8 diff --git a/linux-2.6-acpi-debug-infinite-loop.patch b/linux-2.6-acpi-debug-infinite-loop.patch index d20025224..f2cc1a55e 100644 --- a/linux-2.6-acpi-debug-infinite-loop.patch +++ b/linux-2.6-acpi-debug-infinite-loop.patch @@ -1,5 +1,5 @@ ---- linux-2.6.34.noarch/drivers/acpi/acpica/acconfig.h~ 2010-07-01 14:49:03.000000000 -0400 -+++ linux-2.6.34.noarch/drivers/acpi/acpica/acconfig.h 2010-07-01 14:49:17.000000000 -0400 +--- linux-2.6.34.noarch/include/acpi/acconfig.h~ 2010-07-01 14:49:03.000000000 -0400 ++++ linux-2.6.34.noarch/include/acpi/acconfig.h 2010-07-01 14:49:17.000000000 -0400 @@ -117,7 +117,7 @@ /* Maximum number of While() loop iterations before forced abort */ diff --git a/linux-2.6-defaults-aspm.patch b/linux-2.6-defaults-aspm.patch deleted file mode 100644 index 49b832d2c..000000000 --- a/linux-2.6-defaults-aspm.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up linux-2.6.30.noarch/drivers/pci/pcie/aspm.c.mjg linux-2.6.30.noarch/drivers/pci/pcie/aspm.c ---- linux-2.6.30.noarch/drivers/pci/pcie/aspm.c.mjg 2009-07-16 22:01:11.000000000 +0100 -+++ linux-2.6.30.noarch/drivers/pci/pcie/aspm.c 2009-07-16 22:01:30.000000000 +0100 -@@ -65,7 +65,7 @@ static LIST_HEAD(link_list); - #define POLICY_DEFAULT 0 /* BIOS default setting */ - #define POLICY_PERFORMANCE 1 /* high performance */ - #define POLICY_POWERSAVE 2 /* high power saving */ --static int aspm_policy; -+static int aspm_policy = POLICY_POWERSAVE; - static const char *policy_str[] = { - [POLICY_DEFAULT] = "default", - [POLICY_PERFORMANCE] = "performance", diff --git a/mcelog-rcu-splat.patch b/mcelog-rcu-splat.patch deleted file mode 100644 index 12c1fe3ea..000000000 --- a/mcelog-rcu-splat.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c -index f22a9f7..f525f99 100644 ---- a/arch/x86/kernel/cpu/mcheck/mce.c -+++ b/arch/x86/kernel/cpu/mcheck/mce.c -@@ -191,7 +191,7 @@ static void drain_mcelog_buffer(void) - { - unsigned int next, i, prev = 0; - -- next = rcu_dereference_check_mce(mcelog.next); -+ next = ACCESS_ONCE(mcelog.next); - - do { - struct mce *m; - - \ No newline at end of file diff --git a/rt2x00_fix_MCU_request_failures.patch b/rt2x00_fix_MCU_request_failures.patch deleted file mode 100644 index f7b8a6a4c..000000000 --- a/rt2x00_fix_MCU_request_failures.patch +++ /dev/null @@ -1,136 +0,0 @@ -diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h -index 2571a2f..822f9e5 100644 ---- a/drivers/net/wireless/rt2x00/rt2800.h -+++ b/drivers/net/wireless/rt2x00/rt2800.h -@@ -1627,6 +1627,7 @@ struct mac_iveiv_entry { - - /* - * H2M_MAILBOX_CSR: Host-to-MCU Mailbox. -+ * CMD_TOKEN: Command id, 0xff disable status reporting - */ - #define H2M_MAILBOX_CSR 0x7010 - #define H2M_MAILBOX_CSR_ARG0 FIELD32(0x000000ff) -@@ -1636,6 +1637,8 @@ struct mac_iveiv_entry { - - /* - * H2M_MAILBOX_CID: -+ * Free slots contain 0xff. MCU will store command's token to lowest free slot. -+ * If all slots are occupied status will be dropped. - */ - #define H2M_MAILBOX_CID 0x7014 - #define H2M_MAILBOX_CID_CMD0 FIELD32(0x000000ff) -@@ -1645,6 +1648,7 @@ struct mac_iveiv_entry { - - /* - * H2M_MAILBOX_STATUS: -+ * Command status will be saved to same slot as command id. - */ - #define H2M_MAILBOX_STATUS 0x701c - -@@ -2259,6 +2263,12 @@ struct mac_iveiv_entry { - - /* - * MCU mailbox commands. -+ * MCU_SLEEP - go to power-save mode. -+ * arg1: 1: save as much power as possible, 0: save less power -+ * status: 1: success, 2: already asleep, -+ * 3: maybe MAC is busy so can't finish this task -+ * MCU_RADIO_OFF -+ * arg0: 0: do power-saving, NOT turn off radio - */ - #define MCU_SLEEP 0x30 - #define MCU_WAKEUP 0x31 -@@ -2279,7 +2289,9 @@ struct mac_iveiv_entry { - /* - * MCU mailbox tokens - */ --#define TOKEN_WAKUP 3 -+#define TOKEN_SLEEP 1 -+#define TOKEN_RADIO_OFF 2 -+#define TOKEN_WAKEUP 3 - - /* - * DMA descriptor defines. -diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c -index dc88bae..9ac3017 100644 ---- a/drivers/net/wireless/rt2x00/rt2800pci.c -+++ b/drivers/net/wireless/rt2x00/rt2800pci.c -@@ -517,23 +517,6 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) - } - } - --static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, -- enum dev_state state) --{ -- if (state == STATE_AWAKE) { -- rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0x02); -- rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP); -- } else if (state == STATE_SLEEP) { -- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, -- 0xffffffff); -- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, -- 0xffffffff); -- rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0x01, 0xff, 0x01); -- } -- -- return 0; --} -- - static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) - { -@@ -541,14 +524,20 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, - - switch (state) { - case STATE_RADIO_ON: -- /* -- * Before the radio can be enabled, the device first has -- * to be woken up. After that it needs a bit of time -- * to be fully awake and then the radio can be enabled. -- */ -- rt2800pci_set_state(rt2x00dev, STATE_AWAKE); -- msleep(1); -+ /* Initialise all registers and send MCU_BOOT_SIGNAL. */ - retval = rt2800pci_enable_radio(rt2x00dev); -+ -+ /* After resume MCU_BOOT_SIGNAL will trash those. */ -+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); -+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); -+ -+ /* Finish initialization procedure. */ -+ rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, -+ 0xff, 0x02); -+ rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF); -+ -+ rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKEUP, 0, 0); -+ rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP); - break; - case STATE_RADIO_OFF: - /* -@@ -556,7 +545,7 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, - * be put to sleep for powersaving. - */ - rt2800pci_disable_radio(rt2x00dev); -- rt2800pci_set_state(rt2x00dev, STATE_SLEEP); -+ rt2800pci_set_device_state(rt2x00dev, STATE_SLEEP); - break; - case STATE_RADIO_IRQ_ON: - case STATE_RADIO_IRQ_OFF: -@@ -565,8 +554,16 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, - case STATE_DEEP_SLEEP: - case STATE_SLEEP: - case STATE_STANDBY: -+ /* PCIe devices won't report status after SLEEP request. */ -+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); -+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); -+ rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP, -+ 0xff, 0x01); -+ break; - case STATE_AWAKE: -- retval = rt2800pci_set_state(rt2x00dev, state); -+ rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKEUP, -+ 0, 0x02); -+ rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP); - break; - default: - retval = -ENOTSUPP; diff --git a/silence-timekeeping-spew.patch b/silence-timekeeping-spew.patch deleted file mode 100644 index 19416d433..000000000 --- a/silence-timekeeping-spew.patch +++ /dev/null @@ -1,16 +0,0 @@ ---- linux-3.3.0-4.fc17.noarch/kernel/time/timekeeping.c~ 2012-03-30 14:18:15.591162207 -0400 -+++ linux-3.3.0-4.fc17.noarch/kernel/time/timekeeping.c 2012-03-30 14:18:38.959121171 -0400 -@@ -854,13 +854,6 @@ static void timekeeping_adjust(s64 offse - } else /* No adjustment needed */ - return; - -- WARN_ONCE(timekeeper.clock->maxadj && -- (timekeeper.mult + adj > timekeeper.clock->mult + -- timekeeper.clock->maxadj), -- "Adjusting %s more then 11%% (%ld vs %ld)\n", -- timekeeper.clock->name, (long)timekeeper.mult + adj, -- (long)timekeeper.clock->mult + -- timekeeper.clock->maxadj); - /* - * So the following can be confusing. - * diff --git a/sources b/sources index 033ae54df..cd364717e 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -7133f5a2086a7d7ef97abac610c094f5 linux-3.3.tar.xz -e1714b5136a7f4dab1b5d2d7f98e2891 patch-3.3.8.xz +967f72983655e2479f951195953e8480 linux-3.4.tar.xz +ac52d3d82c20c7e80740fc5fb00b6ed4 patch-3.4.2.xz diff --git a/thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch b/thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch new file mode 100644 index 000000000..a91e9bbe4 --- /dev/null +++ b/thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch @@ -0,0 +1,228 @@ + +Delivered-To: jwboyer@gmail.com +Received: by 10.229.175.203 with SMTP id bb11csp66243qcb; + Fri, 8 Jun 2012 15:08:27 -0700 (PDT) +Received: by 10.68.222.133 with SMTP id qm5mr23412736pbc.113.1339193307132; + Fri, 08 Jun 2012 15:08:27 -0700 (PDT) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id ku9si12482578pbc.355.2012.06.08.15.08.24; + Fri, 08 Jun 2012 15:08:25 -0700 (PDT) +Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S964992Ab2FHWIW (ORCPT + 21 others); + Fri, 8 Jun 2012 18:08:22 -0400 +Received: from mail-bk0-f74.google.com ([209.85.214.74]:41783 "EHLO + mail-bk0-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S964922Ab2FHWIV (ORCPT + ); Fri, 8 Jun 2012 18:08:21 -0400 +Received: by bkty5 with SMTP id y5so128736bkt.1 + for ; Fri, 08 Jun 2012 15:08:20 -0700 (PDT) +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=google.com; s=20120113; + h=subject:to:cc:from:date:message-id:x-gm-message-state; + bh=RSdNZSZcXg/enKaYIM+JR4+Bd890ieO+blY9bsk9giI=; + b=NwTZEmRSdqDAiTV/EW91GXpM/yrRd7CNzfPif0JcF0iFgxGAo4lB7W1I05vmrnPcCQ + Va+P6xXLWle2rAVQLsPooKdtb3u2wnNRDEGvBPZl2alje+qzhKGlQcVgnI5+KCM6GaS+ + YWoE+2gv5UFmF6JlelThyecGTyZ0D93K5aVYewSxg0H7KZ6BgvMnB/qJKFdScatv1uDH + g39MFwJzmD+DmNMn149jeUWYOLLTeMZJkymtJCLgxS8eJzQxXA0nes2Wz/pXCBdxXF2z + mft6LyzKtoEUDeTtalgm9zxkT4XJ+6bsAMEXBFgkcyNq0Ic8P79AP0ynlET2L/Ql3ARP + C5Sg== +Received: by 10.14.101.2 with SMTP id a2mr2823176eeg.6.1339193299969; + Fri, 08 Jun 2012 15:08:19 -0700 (PDT) +Received: from hpza10.eem.corp.google.com ([74.125.121.33]) + by gmr-mx.google.com with ESMTPS id d52si7345113eei.1.2012.06.08.15.08.19 + (version=TLSv1/SSLv3 cipher=AES128-SHA); + Fri, 08 Jun 2012 15:08:19 -0700 (PDT) +Received: from akpm.mtv.corp.google.com (akpm.mtv.corp.google.com [172.18.96.75]) + by hpza10.eem.corp.google.com (Postfix) with ESMTP id 9D09620004E; + Fri, 8 Jun 2012 15:08:19 -0700 (PDT) +Received: from localhost.localdomain (localhost [127.0.0.1]) + by akpm.mtv.corp.google.com (Postfix) with ESMTP id D5FACA0329; + Fri, 8 Jun 2012 15:08:18 -0700 (PDT) +Subject: + thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae.patch added to -mm tree +To: mm-commits@vger.kernel.org +Cc: aarcange@redhat.com, hughd@google.com, jbeulich@suse.com, + jrnieder@gmail.com, kosaki.motohiro@gmail.com, lwoodman@redhat.com, + mgorman@suse.de, pmatouse@redhat.com, riel@redhat.com, + stable@vger.kernel.org, uobergfe@redhat.com +From: akpm@linux-foundation.org +Date: Fri, 08 Jun 2012 15:08:18 -0700 +Message-Id: <20120608220818.D5FACA0329@akpm.mtv.corp.google.com> +X-Gm-Message-State: ALoCoQnqC0C+2OVVfC5Yi43jUu5vH03b/RBncPoI4SpE4HFSgaRrM+gM2J8rR6MMoba3nM/OmDAU +Sender: stable-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: stable@vger.kernel.org + + +The patch titled + Subject: thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE +has been added to the -mm tree. Its filename is + thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae.patch + +Before you just go and hit "reply", please: + a) Consider who else should be cc'ed + b) Prefer to cc a suitable mailing list as well + c) Ideally: find the original patch on the mailing list and do a + reply-to-all to that, adding suitable additional cc's + +*** Remember to use Documentation/SubmitChecklist when testing your code *** + +The -mm tree is included into linux-next and is updated +there every 3-4 working days + +------------------------------------------------------ +From: Andrea Arcangeli +Subject: thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE + +In the x86 32bit PAE CONFIG_TRANSPARENT_HUGEPAGE=y case while holding the +mmap_sem for reading, cmpxchg8b cannot be used to read pmd contents under +Xen. + +So instead of dealing only with "consistent" pmdvals in +pmd_none_or_trans_huge_or_clear_bad() (which would be conceptually +simpler) we let pmd_none_or_trans_huge_or_clear_bad() deal with pmdvals +where the low 32bit and high 32bit could be inconsistent (to avoid having +to use cmpxchg8b). + +The only guarantee we get from pmd_read_atomic is that if the low part of +the pmd was found null, the high part will be null too (so the pmd will be +considered unstable). And if the low part of the pmd is found "stable" +later, then it means the whole pmd was read atomically (because after a +pmd is stable, neither MADV_DONTNEED nor page faults can alter it anymore, +and we read the high part after the low part). + +In the 32bit PAE x86 case, it is enough to read the low part of the pmdval +atomically to declare the pmd as "stable" and that's true for THP and no +THP, furthermore in the THP case we also have a barrier() that will +prevent any inconsistent pmdvals to be cached by a later re-read of the +*pmd. + +Signed-off-by: Andrea Arcangeli +Cc: Jonathan Nieder +Cc: Ulrich Obergfell +Cc: Mel Gorman +Cc: Hugh Dickins +Cc: Larry Woodman +Cc: Petr Matousek +Cc: Rik van Riel +Cc: Jan Beulich +Cc: KOSAKI Motohiro +Cc: +Signed-off-by: Andrew Morton +--- + + arch/x86/include/asm/pgtable-3level.h | 30 +++++++++++++----------- + include/asm-generic/pgtable.h | 10 ++++++++ + 2 files changed, 27 insertions(+), 13 deletions(-) + +diff -puN arch/x86/include/asm/pgtable-3level.h~thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae arch/x86/include/asm/pgtable-3level.h +--- a/arch/x86/include/asm/pgtable-3level.h~thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae ++++ a/arch/x86/include/asm/pgtable-3level.h +@@ -47,16 +47,26 @@ static inline void native_set_pte(pte_t + * they can run pmd_offset_map_lock or pmd_trans_huge or other pmd + * operations. + * +- * Without THP if the mmap_sem is hold for reading, the +- * pmd can only transition from null to not null while pmd_read_atomic runs. +- * So there's no need of literally reading it atomically. ++ * Without THP if the mmap_sem is hold for reading, the pmd can only ++ * transition from null to not null while pmd_read_atomic runs. So ++ * we can always return atomic pmd values with this function. + * + * With THP if the mmap_sem is hold for reading, the pmd can become +- * THP or null or point to a pte (and in turn become "stable") at any +- * time under pmd_read_atomic, so it's mandatory to read it atomically +- * with cmpxchg8b. ++ * trans_huge or none or point to a pte (and in turn become "stable") ++ * at any time under pmd_read_atomic. We could read it really ++ * atomically here with a atomic64_read for the THP enabled case (and ++ * it would be a whole lot simpler), but to avoid using cmpxchg8b we ++ * only return an atomic pmdval if the low part of the pmdval is later ++ * found stable (i.e. pointing to a pte). And we're returning a none ++ * pmdval if the low part of the pmd is none. In some cases the high ++ * and low part of the pmdval returned may not be consistent if THP is ++ * enabled (the low part may point to previously mapped hugepage, ++ * while the high part may point to a more recently mapped hugepage), ++ * but pmd_none_or_trans_huge_or_clear_bad() only needs the low part ++ * of the pmd to be read atomically to decide if the pmd is unstable ++ * or not, with the only exception of when the low part of the pmd is ++ * zero in which case we return a none pmd. + */ +-#ifndef CONFIG_TRANSPARENT_HUGEPAGE + static inline pmd_t pmd_read_atomic(pmd_t *pmdp) + { + pmdval_t ret; +@@ -74,12 +84,6 @@ static inline pmd_t pmd_read_atomic(pmd_ + + return (pmd_t) { ret }; + } +-#else /* CONFIG_TRANSPARENT_HUGEPAGE */ +-static inline pmd_t pmd_read_atomic(pmd_t *pmdp) +-{ +- return (pmd_t) { atomic64_read((atomic64_t *)pmdp) }; +-} +-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ + + static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) + { +diff -puN include/asm-generic/pgtable.h~thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae include/asm-generic/pgtable.h +--- a/include/asm-generic/pgtable.h~thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae ++++ a/include/asm-generic/pgtable.h +@@ -484,6 +484,16 @@ static inline int pmd_none_or_trans_huge + /* + * The barrier will stabilize the pmdval in a register or on + * the stack so that it will stop changing under the code. ++ * ++ * When CONFIG_TRANSPARENT_HUGEPAGE=y on x86 32bit PAE, ++ * pmd_read_atomic is allowed to return a not atomic pmdval ++ * (for example pointing to an hugepage that has never been ++ * mapped in the pmd). The below checks will only care about ++ * the low part of the pmd with 32bit PAE x86 anyway, with the ++ * exception of pmd_none(). So the important thing is that if ++ * the low part of the pmd is found null, the high part will ++ * be also null or the pmd_none() check below would be ++ * confused. + */ + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + barrier(); +_ +Subject: Subject: thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE + +Patches currently in -mm which might be from aarcange@redhat.com are + +origin.patch +linux-next.patch +mm-fix-slab-page-_count-corruption-when-using-slub.patch +thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae.patch +hugetlb-rename-max_hstate-to-hugetlb_max_hstate.patch +hugetlbfs-dont-use-err_ptr-with-vm_fault-values.patch +hugetlbfs-add-an-inline-helper-for-finding-hstate-index.patch +hugetlbfs-add-an-inline-helper-for-finding-hstate-index-fix.patch +hugetlb-use-mmu_gather-instead-of-a-temporary-linked-list-for-accumulating-pages.patch +hugetlb-use-mmu_gather-instead-of-a-temporary-linked-list-for-accumulating-pages-fix.patch +hugetlb-use-mmu_gather-instead-of-a-temporary-linked-list-for-accumulating-pages-fix-fix.patch +hugetlb-avoid-taking-i_mmap_mutex-in-unmap_single_vma-for-hugetlb.patch +hugetlb-simplify-migrate_huge_page.patch +hugetlb-simplify-migrate_huge_page-fix.patch +memcg-add-hugetlb-extension.patch +memcg-add-hugetlb-extension-fix.patch +memcg-add-hugetlb-extension-fix-fix.patch +hugetlb-add-charge-uncharge-calls-for-hugetlb-alloc-free.patch +memcg-track-resource-index-in-cftype-private.patch +hugetlbfs-add-memcg-control-files-for-hugetlbfs.patch +hugetlbfs-add-memcg-control-files-for-hugetlbfs-use-scnprintf-instead-of-sprintf.patch +hugetlbfs-add-memcg-control-files-for-hugetlbfs-use-scnprintf-instead-of-sprintf-fix.patch +hugetlbfs-add-a-list-for-tracking-in-use-hugetlb-pages.patch +memcg-move-hugetlb-resource-count-to-parent-cgroup-on-memcg-removal.patch +memcg-move-hugetlb-resource-count-to-parent-cgroup-on-memcg-removal-fix.patch +memcg-move-hugetlb-resource-count-to-parent-cgroup-on-memcg-removal-fix-fix.patch +hugetlb-migrate-memcg-info-from-oldpage-to-new-page-during-migration.patch +memcg-add-memory-controller-documentation-for-hugetlb-management.patch + +-- +To unsubscribe from this list: send the line "unsubscribe stable" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/utrace.patch b/utrace.patch deleted file mode 100644 index fdf24a472..000000000 --- a/utrace.patch +++ /dev/null @@ -1,4696 +0,0 @@ -From d007ce2c3f1f67624fde5e6b7ccc00566b7df9c3 Mon Sep 17 00:00:00 2001 -From: Oleg Nesterov -Date: Sat, 25 Feb 2012 07:29:40 -0500 -Subject: [PATCH] utrace for 3.3-rc4 kernel, on top of - b52b80023f262ce8a0ffdcb490acb23e8678377a. - -The split-out series is available in the git repository at: - - git@github.com:utrace/linux.git utrace-3.3 - -Oleg Nesterov (31): - utrace: add utrace_init_task/utrace_free_task calls - tracehooks: add utrace hooks - tracehooks: reintroduce tracehook_consider_fatal_signal() - add utrace hooks into sig_ignored() and recalc_sigpending() - restore the EXEC/EXIT/CLONE utrace hooks - utrace: utrace_report_death() can use task_utrace_struct() - restore the DEATH/REAP utrace hooks - utrace: remove jobctl bits - ptrace: take ->siglock around s/TRACED/RUNNING/ - introduce wake_up_quiescent() - introduce ptrace_signal_wake_up() - wait_task_inactive: treat task->state and match_state as bitmasks - introduce TASK_UTRACED state - utrace: use TASK_UTRACED instead of TASK_TRACED - reintroduce tracehook_finish_jctl() as utrace_end_stop() - teach wake_up_quiescent() to do "selective" wake_up - ptrace_stop: do not assume the task is running after wake_up_quiescent() - get_signal_to_deliver: restore/restructure utrace/ptrace signal reporting - utrace_get_signal: s/JOBCTL_STOP_PENDING/JOBCTL_PENDING_MASK/ - introduce ptrace_set_syscall_trace() - introduce PT_SYSCALL_TRACE flag - utrace: don't clear TIF_SYSCALL_TRACE if it is needed by ptrace - introduce task_utrace_lock/task_utrace_unlock - teach ptrace_set_syscall_trace() to play well with utrace - introduce PT_SINGLE_STEP and PT_SINGLE_BLOCK - utrace: finish_resume_report: don't do user_xxx_step() if ptrace_wants_step() - ptrace: shift user_*_step() from ptrace_resume() to ptrace_stop() - ptrace_disable: no need to disable stepping - ptrace_report_syscall: check TIF_SYSCALL_EMU - utrace_resume: check irqs_disabled() to shut up lockdep - utrace: s390: fix the compile problem with traps.c - -Roland McGrath (1): - utrace core - -Tony Breeds (1): - ptrace_report_syscall: check if TIF_SYSCALL_EMU is defined - -Signed-off-by: Oleg Nesterov ---- - Documentation/DocBook/Makefile | 2 +- - Documentation/DocBook/utrace.tmpl | 589 +++++++++ - arch/s390/kernel/traps.c | 6 +- - arch/x86/kernel/ptrace.c | 1 - - fs/exec.c | 5 +- - fs/proc/array.c | 14 +- - include/linux/ptrace.h | 7 + - include/linux/sched.h | 25 +- - include/linux/signal.h | 2 + - include/linux/tracehook.h | 59 +- - include/linux/utrace.h | 774 ++++++++++++ - init/Kconfig | 9 + - kernel/Makefile | 1 + - kernel/exit.c | 5 + - kernel/fork.c | 9 + - kernel/ptrace.c | 57 +- - kernel/sched/core.c | 2 +- - kernel/signal.c | 97 ++- - kernel/utrace.c | 2466 +++++++++++++++++++++++++++++++++++++ - 19 files changed, 4074 insertions(+), 56 deletions(-) - create mode 100644 Documentation/DocBook/utrace.tmpl - create mode 100644 include/linux/utrace.h - create mode 100644 kernel/utrace.c - -diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile -index 66725a3..08ed954 100644 ---- a/Documentation/DocBook/Makefile -+++ b/Documentation/DocBook/Makefile -@@ -14,7 +14,7 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ - genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ - 80211.xml debugobjects.xml sh.xml regulator.xml \ - alsa-driver-api.xml writing-an-alsa-driver.xml \ -- tracepoint.xml drm.xml media_api.xml -+ tracepoint.xml utrace.xml drm.xml media_api.xml - - include $(srctree)/Documentation/DocBook/media/Makefile - -diff --git a/Documentation/DocBook/utrace.tmpl b/Documentation/DocBook/utrace.tmpl -new file mode 100644 -index 0000000..0c40add ---- /dev/null -+++ b/Documentation/DocBook/utrace.tmpl -@@ -0,0 +1,589 @@ -+ -+ -+ -+ -+ -+ The utrace User Debugging Infrastructure -+ -+ -+ -+ -+ utrace concepts -+ -+ Introduction -+ -+ -+ utrace is infrastructure code for tracing -+ and controlling user threads. This is the foundation for writing -+ tracing engines, which can be loadable kernel modules. -+ -+ -+ -+ The basic actors in utrace are the thread -+ and the tracing engine. A tracing engine is some body of code that -+ calls into the <linux/utrace.h> -+ interfaces, represented by a struct -+ utrace_engine_ops. (Usually it's a kernel module, -+ though the legacy ptrace support is a tracing -+ engine that is not in a kernel module.) The interface operates on -+ individual threads (struct task_struct). -+ If an engine wants to treat several threads as a group, that is up -+ to its higher-level code. -+ -+ -+ -+ Tracing begins by attaching an engine to a thread, using -+ utrace_attach_task or -+ utrace_attach_pid. If successful, it returns a -+ pointer that is the handle used in all other calls. -+ -+ -+ -+ -+ Events and Callbacks -+ -+ -+ An attached engine does nothing by default. An engine makes something -+ happen by requesting callbacks via utrace_set_events -+ and poking the thread with utrace_control. -+ The synchronization issues related to these two calls -+ are discussed further below in . -+ -+ -+ -+ Events are specified using the macro -+ UTRACE_EVENT(type). -+ Each event type is associated with a callback in struct -+ utrace_engine_ops. A tracing engine can leave unused -+ callbacks NULL. The only callbacks required -+ are those used by the event flags it sets. -+ -+ -+ -+ Many engines can be attached to each thread. When a thread has an -+ event, each engine gets a callback if it has set the event flag for -+ that event type. For most events, engines are called in the order they -+ attached. Engines that attach after the event has occurred do not get -+ callbacks for that event. This includes any new engines just attached -+ by an existing engine's callback function. Once the sequence of -+ callbacks for that one event has completed, such new engines are then -+ eligible in the next sequence that starts when there is another event. -+ -+ -+ -+ Event reporting callbacks have details particular to the event type, -+ but are all called in similar environments and have the same -+ constraints. Callbacks are made from safe points, where no locks -+ are held, no special resources are pinned (usually), and the -+ user-mode state of the thread is accessible. So, callback code has -+ a pretty free hand. But to be a good citizen, callback code should -+ never block for long periods. It is fine to block in -+ kmalloc and the like, but never wait for i/o or -+ for user mode to do something. If you need the thread to wait, use -+ UTRACE_STOP and return from the callback -+ quickly. When your i/o finishes or whatever, you can use -+ utrace_control to resume the thread. -+ -+ -+ -+ The UTRACE_EVENT(SYSCALL_ENTRY) event is a special -+ case. While other events happen in the kernel when it will return to -+ user mode soon, this event happens when entering the kernel before it -+ will proceed with the work requested from user mode. Because of this -+ difference, the report_syscall_entry callback is -+ special in two ways. For this event, engines are called in reverse of -+ the normal order (this includes the report_quiesce -+ call that precedes a report_syscall_entry call). -+ This preserves the semantics that the last engine to attach is called -+ "closest to user mode"--the engine that is first to see a thread's user -+ state when it enters the kernel is also the last to see that state when -+ the thread returns to user mode. For the same reason, if these -+ callbacks use UTRACE_STOP (see the next section), -+ the thread stops immediately after callbacks rather than only when it's -+ ready to return to user mode; when allowed to resume, it will actually -+ attempt the system call indicated by the register values at that time. -+ -+ -+ -+ -+ Stopping Safely -+ -+ Writing well-behaved callbacks -+ -+ -+ Well-behaved callbacks are important to maintain two essential -+ properties of the interface. The first of these is that unrelated -+ tracing engines should not interfere with each other. If your engine's -+ event callback does not return quickly, then another engine won't get -+ the event notification in a timely manner. The second important -+ property is that tracing should be as noninvasive as possible to the -+ normal operation of the system overall and of the traced thread in -+ particular. That is, attached tracing engines should not perturb a -+ thread's behavior, except to the extent that changing its user-visible -+ state is explicitly what you want to do. (Obviously some perturbation -+ is unavoidable, primarily timing changes, ranging from small delays due -+ to the overhead of tracing, to arbitrary pauses in user code execution -+ when a user stops a thread with a debugger for examination.) Even when -+ you explicitly want the perturbation of making the traced thread block, -+ just blocking directly in your callback has more unwanted effects. For -+ example, the CLONE event callbacks are called when -+ the new child thread has been created but not yet started running; the -+ child can never be scheduled until the CLONE -+ tracing callbacks return. (This allows engines tracing the parent to -+ attach to the child.) If a CLONE event callback -+ blocks the parent thread, it also prevents the child thread from -+ running (even to process a SIGKILL). If what you -+ want is to make both the parent and child block, then use -+ utrace_attach_task on the child and then use -+ UTRACE_STOP on both threads. A more crucial -+ problem with blocking in callbacks is that it can prevent -+ SIGKILL from working. A thread that is blocking -+ due to UTRACE_STOP will still wake up and die -+ immediately when sent a SIGKILL, as all threads -+ should. Relying on the utrace -+ infrastructure rather than on private synchronization calls in event -+ callbacks is an important way to help keep tracing robustly -+ noninvasive. -+ -+ -+ -+ -+ Using <constant>UTRACE_STOP</constant> -+ -+ -+ To control another thread and access its state, it must be stopped -+ with UTRACE_STOP. This means that it is -+ stopped and won't start running again while we access it. When a -+ thread is not already stopped, utrace_control -+ returns -EINPROGRESS and an engine must wait -+ for an event callback when the thread is ready to stop. The thread -+ may be running on another CPU or may be blocked. When it is ready -+ to be examined, it will make callbacks to engines that set the -+ UTRACE_EVENT(QUIESCE) event bit. To wake up an -+ interruptible wait, use UTRACE_INTERRUPT. -+ -+ -+ -+ As long as some engine has used UTRACE_STOP and -+ not called utrace_control to resume the thread, -+ then the thread will remain stopped. SIGKILL -+ will wake it up, but it will not run user code. When the stop is -+ cleared with utrace_control or a callback -+ return value, the thread starts running again. -+ (See also .) -+ -+ -+ -+ -+ -+ -+ Tear-down Races -+ -+ Primacy of <constant>SIGKILL</constant> -+ -+ Ordinarily synchronization issues for tracing engines are kept fairly -+ straightforward by using UTRACE_STOP. You ask a -+ thread to stop, and then once it makes the -+ report_quiesce callback it cannot do anything else -+ that would result in another callback, until you let it with a -+ utrace_control call. This simple arrangement -+ avoids complex and error-prone code in each one of a tracing engine's -+ event callbacks to keep them serialized with the engine's other -+ operations done on that thread from another thread of control. -+ However, giving tracing engines complete power to keep a traced thread -+ stuck in place runs afoul of a more important kind of simplicity that -+ the kernel overall guarantees: nothing can prevent or delay -+ SIGKILL from making a thread die and release its -+ resources. To preserve this important property of -+ SIGKILL, it as a special case can break -+ UTRACE_STOP like nothing else normally can. This -+ includes both explicit SIGKILL signals and the -+ implicit SIGKILL sent to each other thread in the -+ same thread group by a thread doing an exec, or processing a fatal -+ signal, or making an exit_group system call. A -+ tracing engine can prevent a thread from beginning the exit or exec or -+ dying by signal (other than SIGKILL) if it is -+ attached to that thread, but once the operation begins, no tracing -+ engine can prevent or delay all other threads in the same thread group -+ dying. -+ -+ -+ -+ Final callbacks -+ -+ The report_reap callback is always the final event -+ in the life cycle of a traced thread. Tracing engines can use this as -+ the trigger to clean up their own data structures. The -+ report_death callback is always the penultimate -+ event a tracing engine might see; it's seen unless the thread was -+ already in the midst of dying when the engine attached. Many tracing -+ engines will have no interest in when a parent reaps a dead process, -+ and nothing they want to do with a zombie thread once it dies; for -+ them, the report_death callback is the natural -+ place to clean up data structures and detach. To facilitate writing -+ such engines robustly, given the asynchrony of -+ SIGKILL, and without error-prone manual -+ implementation of synchronization schemes, the -+ utrace infrastructure provides some special -+ guarantees about the report_death and -+ report_reap callbacks. It still takes some care -+ to be sure your tracing engine is robust to tear-down races, but these -+ rules make it reasonably straightforward and concise to handle a lot of -+ corner cases correctly. -+ -+ -+ -+ Engine and task pointers -+ -+ The first sort of guarantee concerns the core data structures -+ themselves. struct utrace_engine is -+ a reference-counted data structure. While you hold a reference, an -+ engine pointer will always stay valid so that you can safely pass it to -+ any utrace call. Each call to -+ utrace_attach_task or -+ utrace_attach_pid returns an engine pointer with a -+ reference belonging to the caller. You own that reference until you -+ drop it using utrace_engine_put. There is an -+ implicit reference on the engine while it is attached. So if you drop -+ your only reference, and then use -+ utrace_attach_task without -+ UTRACE_ATTACH_CREATE to look up that same engine, -+ you will get the same pointer with a new reference to replace the one -+ you dropped, just like calling utrace_engine_get. -+ When an engine has been detached, either explicitly with -+ UTRACE_DETACH or implicitly after -+ report_reap, then any references you hold are all -+ that keep the old engine pointer alive. -+ -+ -+ -+ There is nothing a kernel module can do to keep a struct -+ task_struct alive outside of -+ rcu_read_lock. When the task dies and is reaped -+ by its parent (or itself), that structure can be freed so that any -+ dangling pointers you have stored become invalid. -+ utrace will not prevent this, but it can -+ help you detect it safely. By definition, a task that has been reaped -+ has had all its engines detached. All -+ utrace calls can be safely called on a -+ detached engine if the caller holds a reference on that engine pointer, -+ even if the task pointer passed in the call is invalid. All calls -+ return -ESRCH for a detached engine, which tells -+ you that the task pointer you passed could be invalid now. Since -+ utrace_control and -+ utrace_set_events do not block, you can call those -+ inside a rcu_read_lock section and be sure after -+ they don't return -ESRCH that the task pointer is -+ still valid until rcu_read_unlock. The -+ infrastructure never holds task references of its own. Though neither -+ rcu_read_lock nor any other lock is held while -+ making a callback, it's always guaranteed that the struct -+ task_struct and the struct -+ utrace_engine passed as arguments remain valid -+ until the callback function returns. -+ -+ -+ -+ The common means for safely holding task pointers that is available to -+ kernel modules is to use struct pid, which -+ permits put_pid from kernel modules. When using -+ that, the calls utrace_attach_pid, -+ utrace_control_pid, -+ utrace_set_events_pid, and -+ utrace_barrier_pid are available. -+ -+ -+ -+ -+ -+ Serialization of <constant>DEATH</constant> and <constant>REAP</constant> -+ -+ -+ The second guarantee is the serialization of -+ DEATH and REAP event -+ callbacks for a given thread. The actual reaping by the parent -+ (release_task call) can occur simultaneously -+ while the thread is still doing the final steps of dying, including -+ the report_death callback. If a tracing engine -+ has requested both DEATH and -+ REAP event reports, it's guaranteed that the -+ report_reap callback will not be made until -+ after the report_death callback has returned. -+ If the report_death callback itself detaches -+ from the thread, then the report_reap callback -+ will never be made. Thus it is safe for a -+ report_death callback to clean up data -+ structures and detach. -+ -+ -+ -+ Interlock with final callbacks -+ -+ The final sort of guarantee is that a tracing engine will know for sure -+ whether or not the report_death and/or -+ report_reap callbacks will be made for a certain -+ thread. These tear-down races are disambiguated by the error return -+ values of utrace_set_events and -+ utrace_control. Normally -+ utrace_control called with -+ UTRACE_DETACH returns zero, and this means that no -+ more callbacks will be made. If the thread is in the midst of dying, -+ it returns -EALREADY to indicate that the -+ report_death callback may already be in progress; -+ when you get this error, you know that any cleanup your -+ report_death callback does is about to happen or -+ has just happened--note that if the report_death -+ callback does not detach, the engine remains attached until the thread -+ gets reaped. If the thread is in the midst of being reaped, -+ utrace_control returns -ESRCH -+ to indicate that the report_reap callback may -+ already be in progress; this means the engine is implicitly detached -+ when the callback completes. This makes it possible for a tracing -+ engine that has decided asynchronously to detach from a thread to -+ safely clean up its data structures, knowing that no -+ report_death or report_reap -+ callback will try to do the same. utrace_detach -+ returns -ESRCH when the struct -+ utrace_engine has already been detached, but is -+ still a valid pointer because of its reference count. A tracing engine -+ can use this to safely synchronize its own independent multiple threads -+ of control with each other and with its event callbacks that detach. -+ -+ -+ -+ In the same vein, utrace_set_events normally -+ returns zero; if the target thread was stopped before the call, then -+ after a successful call, no event callbacks not requested in the new -+ flags will be made. It fails with -EALREADY if -+ you try to clear UTRACE_EVENT(DEATH) when the -+ report_death callback may already have begun, or if -+ you try to newly set UTRACE_EVENT(DEATH) or -+ UTRACE_EVENT(QUIESCE) when the target is already -+ dead or dying. Like utrace_control, it returns -+ -ESRCH when the report_reap -+ callback may already have begun, or the thread has already been detached -+ (including forcible detach on reaping). This lets the tracing engine -+ know for sure which event callbacks it will or won't see after -+ utrace_set_events has returned. By checking for -+ errors, it can know whether to clean up its data structures immediately -+ or to let its callbacks do the work. -+ -+ -+ -+ Using <function>utrace_barrier</function> -+ -+ When a thread is safely stopped, calling -+ utrace_control with UTRACE_DETACH -+ or calling utrace_set_events to disable some events -+ ensures synchronously that your engine won't get any more of the callbacks -+ that have been disabled (none at all when detaching). But these can also -+ be used while the thread is not stopped, when it might be simultaneously -+ making a callback to your engine. For this situation, these calls return -+ -EINPROGRESS when it's possible a callback is in -+ progress. If you are not prepared to have your old callbacks still run, -+ then you can synchronize to be sure all the old callbacks are finished, -+ using utrace_barrier. This is necessary if the -+ kernel module containing your callback code is going to be unloaded. -+ -+ -+ After using UTRACE_DETACH once, further calls to -+ utrace_control with the same engine pointer will -+ return -ESRCH. In contrast, after getting -+ -EINPROGRESS from -+ utrace_set_events, you can call -+ utrace_set_events again later and if it returns zero -+ then know the old callbacks have finished. -+ -+ -+ Unlike all other calls, utrace_barrier (and -+ utrace_barrier_pid) will accept any engine pointer you -+ hold a reference on, even if UTRACE_DETACH has already -+ been used. After any utrace_control or -+ utrace_set_events call (these do not block), you can -+ call utrace_barrier to block until callbacks have -+ finished. This returns -ESRCH only if the engine is -+ completely detached (finished all callbacks). Otherwise it waits -+ until the thread is definitely not in the midst of a callback to this -+ engine and then returns zero, but can return -+ -ERESTARTSYS if its wait is interrupted. -+ -+ -+ -+ -+ -+ -+ -+utrace core API -+ -+ -+ The utrace API is declared in <linux/utrace.h>. -+ -+ -+!Iinclude/linux/utrace.h -+!Ekernel/utrace.c -+ -+ -+ -+Machine State -+ -+ -+ The task_current_syscall function can be used on any -+ valid struct task_struct at any time, and does -+ not even require that utrace_attach_task was used at all. -+ -+ -+ -+ The other ways to access the registers and other machine-dependent state of -+ a task can only be used on a task that is at a known safe point. The safe -+ points are all the places where utrace_set_events can -+ request callbacks (except for the DEATH and -+ REAP events). So at any event callback, it is safe to -+ examine current. -+ -+ -+ -+ One task can examine another only after a callback in the target task that -+ returns UTRACE_STOP so that task will not return to user -+ mode after the safe point. This guarantees that the task will not resume -+ until the same engine uses utrace_control, unless the -+ task dies suddenly. To examine safely, one must use a pair of calls to -+ utrace_prepare_examine and -+ utrace_finish_examine surrounding the calls to -+ struct user_regset functions or direct examination -+ of task data structures. utrace_prepare_examine returns -+ an error if the task is not properly stopped, or is dead. After a -+ successful examination, the paired utrace_finish_examine -+ call returns an error if the task ever woke up during the examination. If -+ so, any data gathered may be scrambled and should be discarded. This means -+ there was a spurious wake-up (which should not happen), or a sudden death. -+ -+ -+<structname>struct user_regset</structname> -+ -+ -+ The struct user_regset API -+ is declared in <linux/regset.h>. -+ -+ -+!Finclude/linux/regset.h -+ -+ -+ -+ -+ <filename>System Call Information</filename> -+ -+ -+ This function is declared in <linux/ptrace.h>. -+ -+ -+!Elib/syscall.c -+ -+ -+ -+<filename>System Call Tracing</filename> -+ -+ -+ The arch API for system call information is declared in -+ <asm/syscall.h>. -+ Each of these calls can be used only at system call entry tracing, -+ or can be used only at system call exit and the subsequent safe points -+ before returning to user mode. -+ At system call entry tracing means either during a -+ report_syscall_entry callback, -+ or any time after that callback has returned UTRACE_STOP. -+ -+ -+!Finclude/asm-generic/syscall.h -+ -+ -+ -+ -+ -+Kernel Internals -+ -+ -+ This chapter covers the interface to the tracing infrastructure -+ from the core of the kernel and the architecture-specific code. -+ This is for maintainers of the kernel and arch code, and not relevant -+ to using the tracing facilities described in preceding chapters. -+ -+ -+Core Calls In -+ -+ -+ These calls are declared in <linux/tracehook.h>. -+ The core kernel calls these functions at various important places. -+ -+ -+!Finclude/linux/tracehook.h -+ -+ -+ -+Architecture Calls Out -+ -+ -+ An arch that has done all these things sets -+ CONFIG_HAVE_ARCH_TRACEHOOK. -+ This is required to enable the utrace code. -+ -+ -+<filename><asm/ptrace.h></filename> -+ -+ -+ An arch defines these in <asm/ptrace.h> -+ if it supports hardware single-step or block-step features. -+ -+ -+!Finclude/linux/ptrace.h arch_has_single_step arch_has_block_step -+!Finclude/linux/ptrace.h user_enable_single_step user_enable_block_step -+!Finclude/linux/ptrace.h user_disable_single_step -+ -+ -+ -+ -+ <filename><asm/syscall.h></filename> -+ -+ -+ An arch provides <asm/syscall.h> that -+ defines these as inlines, or declares them as exported functions. -+ These interfaces are described in . -+ -+ -+ -+ -+ -+ <filename><linux/tracehook.h></filename> -+ -+ -+ An arch must define TIF_NOTIFY_RESUME -+ and TIF_SYSCALL_TRACE -+ in its <asm/thread_info.h>. -+ The arch code must call the following functions, all declared -+ in <linux/tracehook.h> and -+ described in : -+ -+ -+ -+ tracehook_notify_resume -+ -+ -+ tracehook_report_syscall_entry -+ -+ -+ tracehook_report_syscall_exit -+ -+ -+ tracehook_signal_handler -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c -index 5ce3750..4f0b32f 100644 ---- a/arch/s390/kernel/traps.c -+++ b/arch/s390/kernel/traps.c -@@ -18,7 +18,7 @@ - #include - #include - #include --#include -+#include - #include - #include - #include -@@ -330,7 +330,7 @@ void __kprobes do_per_trap(struct pt_regs *regs) - - if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP) - return; -- if (!current->ptrace) -+ if (!tracehook_consider_fatal_signal(current, SIGTRAP)) - return; - info.si_signo = SIGTRAP; - info.si_errno = 0; -@@ -415,7 +415,7 @@ static void __kprobes illegal_op(struct pt_regs *regs) - if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) - return; - if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) { -- if (current->ptrace) { -+ if (tracehook_consider_fatal_signal(current, SIGTRAP)) { - info.si_signo = SIGTRAP; - info.si_errno = 0; - info.si_code = TRAP_BRKPT; -diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c -index 5026738..97687f3 100644 ---- a/arch/x86/kernel/ptrace.c -+++ b/arch/x86/kernel/ptrace.c -@@ -809,7 +809,6 @@ static int ioperm_get(struct task_struct *target, - */ - void ptrace_disable(struct task_struct *child) - { -- user_disable_single_step(child); - #ifdef TIF_SYSCALL_EMU - clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); - #endif -diff --git a/fs/exec.c b/fs/exec.c -index 92ce83a..87ff31f 100644 ---- a/fs/exec.c -+++ b/fs/exec.c -@@ -1402,9 +1402,12 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) - */ - bprm->recursion_depth = depth; - if (retval >= 0) { -- if (depth == 0) -+ if (depth == 0) { -+ UTRACE_HOOK(current, EXEC, -+ report_exec(fmt, bprm, regs)); - ptrace_event(PTRACE_EVENT_EXEC, - old_pid); -+ } - put_binfmt(fmt); - allow_write_access(bprm->file); - if (bprm->file) -diff --git a/fs/proc/array.c b/fs/proc/array.c -index c602b8d..a700b78 100644 ---- a/fs/proc/array.c -+++ b/fs/proc/array.c -@@ -81,6 +81,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -137,11 +138,12 @@ static const char * const task_state_array[] = { - "D (disk sleep)", /* 2 */ - "T (stopped)", /* 4 */ - "t (tracing stop)", /* 8 */ -- "Z (zombie)", /* 16 */ -- "X (dead)", /* 32 */ -- "x (dead)", /* 64 */ -- "K (wakekill)", /* 128 */ -- "W (waking)", /* 256 */ -+ "t (tracing stop)", /* 16 (stopped by utrace) */ -+ "Z (zombie)", /* 32 */ -+ "X (dead)", /* 64 */ -+ "x (dead)", /* 128 */ -+ "K (wakekill)", /* 256 */ -+ "W (waking)", /* 512 */ - }; - - static inline const char *get_task_state(struct task_struct *tsk) -@@ -192,6 +194,8 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, - cred->uid, cred->euid, cred->suid, cred->fsuid, - cred->gid, cred->egid, cred->sgid, cred->fsgid); - -+ task_utrace_proc_status(m, p); -+ - task_lock(p); - if (p->files) - fdt = files_fdtable(p->files); -diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h -index c2f1f6a..236b920 100644 ---- a/include/linux/ptrace.h -+++ b/include/linux/ptrace.h -@@ -104,6 +104,10 @@ - - #define PT_TRACE_MASK 0x000003f4 - -+#define PT_SYSCALL_TRACE 0x00020000 -+#define PT_SINGLE_STEP 0x00040000 -+#define PT_SINGLE_BLOCK 0x00080000 -+ - /* single stepping state bits (used on ARM and PA-RISC) */ - #define PT_SINGLESTEP_BIT 31 - #define PT_SINGLESTEP (1< /* For struct task_struct. */ - #include /* for IS_ERR_VALUE */ - -+extern void ptrace_signal_wake_up(struct task_struct *p, int quiescent); - - extern long arch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data); -@@ -228,6 +233,8 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) - - if (unlikely(ptrace) && current->ptrace) { - child->ptrace = current->ptrace; -+ child->ptrace &= -+ ~(PT_SYSCALL_TRACE | PT_SINGLE_STEP | PT_SINGLE_BLOCK); - __ptrace_link(child, current->parent); - - if (child->ptrace & PT_SEIZED) -diff --git a/include/linux/sched.h b/include/linux/sched.h -index 7d379a6..a3c4599 100644 ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -185,16 +185,17 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) - #define TASK_UNINTERRUPTIBLE 2 - #define __TASK_STOPPED 4 - #define __TASK_TRACED 8 -+#define __TASK_UTRACED 16 - /* in tsk->exit_state */ --#define EXIT_ZOMBIE 16 --#define EXIT_DEAD 32 -+#define EXIT_ZOMBIE 32 -+#define EXIT_DEAD 64 - /* in tsk->state again */ --#define TASK_DEAD 64 --#define TASK_WAKEKILL 128 --#define TASK_WAKING 256 --#define TASK_STATE_MAX 512 -+#define TASK_DEAD 128 -+#define TASK_WAKEKILL 256 -+#define TASK_WAKING 512 -+#define TASK_STATE_MAX 1024 - --#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKW" -+#define TASK_STATE_TO_CHAR_STR "RSDTtUZXxKW" - - extern char ___assert_task_state[1 - 2*!!( - sizeof(TASK_STATE_TO_CHAR_STR)-1 != ilog2(TASK_STATE_MAX)+1)]; -@@ -203,15 +204,16 @@ extern char ___assert_task_state[1 - 2*!!( - #define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE) - #define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED) - #define TASK_TRACED (TASK_WAKEKILL | __TASK_TRACED) -+#define TASK_UTRACED (TASK_WAKEKILL | __TASK_UTRACED) - - /* Convenience macros for the sake of wake_up */ - #define TASK_NORMAL (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE) --#define TASK_ALL (TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED) -+#define TASK_ALL (TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED | __TASK_UTRACED) - - /* get_task_state() */ - #define TASK_REPORT (TASK_RUNNING | TASK_INTERRUPTIBLE | \ - TASK_UNINTERRUPTIBLE | __TASK_STOPPED | \ -- __TASK_TRACED) -+ __TASK_TRACED | __TASK_UTRACED) - - #define task_is_traced(task) ((task->state & __TASK_TRACED) != 0) - #define task_is_stopped(task) ((task->state & __TASK_STOPPED) != 0) -@@ -1420,6 +1422,11 @@ struct task_struct { - #endif - seccomp_t seccomp; - -+#ifdef CONFIG_UTRACE -+ struct utrace *utrace; -+ unsigned long utrace_flags; -+#endif -+ - /* Thread group tracking */ - u32 parent_exec_id; - u32 self_exec_id; -diff --git a/include/linux/signal.h b/include/linux/signal.h -index 7987ce74..c320549 100644 ---- a/include/linux/signal.h -+++ b/include/linux/signal.h -@@ -239,6 +239,8 @@ static inline int valid_signal(unsigned long sig) - struct timespec; - struct pt_regs; - -+extern int wake_up_quiescent(struct task_struct *p, unsigned int state); -+ - extern int next_signal(struct sigpending *pending, sigset_t *mask); - extern int do_send_sig_info(int sig, struct siginfo *info, - struct task_struct *p, bool group); -diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h -index a71a292..a1bac95 100644 ---- a/include/linux/tracehook.h -+++ b/include/linux/tracehook.h -@@ -49,6 +49,7 @@ - #include - #include - #include -+#include - struct linux_binprm; - - /* -@@ -58,8 +59,12 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) - { - int ptrace = current->ptrace; - -- if (!(ptrace & PT_PTRACED)) -- return; -+ if (!(ptrace & PT_SYSCALL_TRACE)) { -+#ifdef TIF_SYSCALL_EMU -+ if (!test_thread_flag(TIF_SYSCALL_EMU)) -+#endif -+ return; -+ } - - ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); - -@@ -96,10 +101,16 @@ static inline void ptrace_report_syscall(struct pt_regs *regs) - static inline __must_check int tracehook_report_syscall_entry( - struct pt_regs *regs) - { -+ if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && -+ utrace_report_syscall_entry(regs)) -+ return 1; - ptrace_report_syscall(regs); - return 0; - } - -+#define ptrace_wants_step(task) \ -+ ((task)->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK)) -+ - /** - * tracehook_report_syscall_exit - task has just finished a system call - * @regs: user register state of current task -@@ -119,7 +130,10 @@ static inline __must_check int tracehook_report_syscall_entry( - */ - static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) - { -- if (step) { -+ if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) -+ utrace_report_syscall_exit(regs); -+ -+ if (step && ptrace_wants_step(current)) { - siginfo_t info; - user_single_step_siginfo(current, regs, &info); - force_sig_info(SIGTRAP, &info, current); -@@ -148,10 +162,34 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, - const struct k_sigaction *ka, - struct pt_regs *regs, int stepping) - { -- if (stepping) -+ if (task_utrace_flags(current)) -+ utrace_signal_handler(current, stepping); -+ if (stepping && ptrace_wants_step(current)) - ptrace_notify(SIGTRAP); - } - -+/** -+ * tracehook_consider_fatal_signal - suppress special handling of fatal signal -+ * @task: task receiving the signal -+ * @sig: signal number being sent -+ * -+ * Return nonzero to prevent special handling of this termination signal. -+ * Normally handler for signal is %SIG_DFL. It can be %SIG_IGN if @sig is -+ * ignored, in which case force_sig() is about to reset it to %SIG_DFL. -+ * When this returns zero, this signal might cause a quick termination -+ * that does not give the debugger a chance to intercept the signal. -+ * -+ * Called with or without @task->sighand->siglock held. -+ */ -+static inline int tracehook_consider_fatal_signal(struct task_struct *task, -+ int sig) -+{ -+ if (unlikely(task_utrace_flags(task) & (UTRACE_EVENT(SIGNAL_TERM) | -+ UTRACE_EVENT(SIGNAL_CORE)))) -+ return 1; -+ return task->ptrace != 0; -+} -+ - #ifdef TIF_NOTIFY_RESUME - /** - * set_notify_resume - cause tracehook_notify_resume() to be called -@@ -179,10 +217,21 @@ static inline void set_notify_resume(struct task_struct *task) - * asynchronously, this will be called again before we return to - * user mode. - * -- * Called without locks. -+ * Called without locks. However, on some machines this may be -+ * called with interrupts disabled. - */ - static inline void tracehook_notify_resume(struct pt_regs *regs) - { -+ struct task_struct *task = current; -+ /* -+ * Prevent the following store/load from getting ahead of the -+ * caller which clears TIF_NOTIFY_RESUME. This pairs with the -+ * implicit mb() before setting TIF_NOTIFY_RESUME in -+ * set_notify_resume(). -+ */ -+ smp_mb(); -+ if (task_utrace_flags(task)) -+ utrace_resume(task, regs); - } - #endif /* TIF_NOTIFY_RESUME */ - -diff --git a/include/linux/utrace.h b/include/linux/utrace.h -new file mode 100644 -index 0000000..46959af ---- /dev/null -+++ b/include/linux/utrace.h -@@ -0,0 +1,774 @@ -+/* -+ * utrace infrastructure interface for debugging user processes -+ * -+ * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved. -+ * -+ * This copyrighted material is made available to anyone wishing to use, -+ * modify, copy, or redistribute it subject to the terms and conditions -+ * of the GNU General Public License v.2. -+ * -+ * Red Hat Author: Roland McGrath. -+ * -+ * This interface allows for notification of interesting events in a -+ * thread. It also mediates access to thread state such as registers. -+ * Multiple unrelated users can be associated with a single thread. -+ * We call each of these a tracing engine. -+ * -+ * A tracing engine starts by calling utrace_attach_task() or -+ * utrace_attach_pid() on the chosen thread, passing in a set of hooks -+ * (&struct utrace_engine_ops), and some associated data. This produces a -+ * &struct utrace_engine, which is the handle used for all other -+ * operations. An attached engine has its ops vector, its data, and an -+ * event mask controlled by utrace_set_events(). -+ * -+ * For each event bit that is set, that engine will get the -+ * appropriate ops->report_*() callback when the event occurs. The -+ * &struct utrace_engine_ops need not provide callbacks for an event -+ * unless the engine sets one of the associated event bits. -+ */ -+ -+#ifndef _LINUX_UTRACE_H -+#define _LINUX_UTRACE_H 1 -+ -+#include -+#include -+#include -+#include -+ -+struct linux_binprm; -+struct pt_regs; -+struct utrace; -+struct user_regset; -+struct user_regset_view; -+ -+/* -+ * Event bits passed to utrace_set_events(). -+ * These appear in &struct task_struct.@utrace_flags -+ * and &struct utrace_engine.@flags. -+ */ -+enum utrace_events { -+ _UTRACE_EVENT_QUIESCE, /* Thread is available for examination. */ -+ _UTRACE_EVENT_REAP, /* Zombie reaped, no more tracing possible. */ -+ _UTRACE_EVENT_CLONE, /* Successful clone/fork/vfork just done. */ -+ _UTRACE_EVENT_EXEC, /* Successful execve just completed. */ -+ _UTRACE_EVENT_EXIT, /* Thread exit in progress. */ -+ _UTRACE_EVENT_DEATH, /* Thread has died. */ -+ _UTRACE_EVENT_SYSCALL_ENTRY, /* User entered kernel for system call. */ -+ _UTRACE_EVENT_SYSCALL_EXIT, /* Returning to user after system call. */ -+ _UTRACE_EVENT_SIGNAL, /* Signal delivery will run a user handler. */ -+ _UTRACE_EVENT_SIGNAL_IGN, /* No-op signal to be delivered. */ -+ _UTRACE_EVENT_SIGNAL_STOP, /* Signal delivery will suspend. */ -+ _UTRACE_EVENT_SIGNAL_TERM, /* Signal delivery will terminate. */ -+ _UTRACE_EVENT_SIGNAL_CORE, /* Signal delivery will dump core. */ -+ _UTRACE_EVENT_JCTL, /* Job control stop or continue completed. */ -+ _UTRACE_NEVENTS -+}; -+#define UTRACE_EVENT(type) (1UL << _UTRACE_EVENT_##type) -+ -+/* -+ * All the kinds of signal events. -+ * These all use the @report_signal() callback. -+ */ -+#define UTRACE_EVENT_SIGNAL_ALL (UTRACE_EVENT(SIGNAL) \ -+ | UTRACE_EVENT(SIGNAL_IGN) \ -+ | UTRACE_EVENT(SIGNAL_STOP) \ -+ | UTRACE_EVENT(SIGNAL_TERM) \ -+ | UTRACE_EVENT(SIGNAL_CORE)) -+/* -+ * Both kinds of syscall events; these call the @report_syscall_entry() -+ * and @report_syscall_exit() callbacks, respectively. -+ */ -+#define UTRACE_EVENT_SYSCALL \ -+ (UTRACE_EVENT(SYSCALL_ENTRY) | UTRACE_EVENT(SYSCALL_EXIT)) -+ -+/* -+ * The event reports triggered synchronously by task death. -+ */ -+#define _UTRACE_DEATH_EVENTS (UTRACE_EVENT(DEATH) | UTRACE_EVENT(QUIESCE)) -+ -+/* -+ * Hooks in call these entry points to the utrace dispatch. -+ */ -+void utrace_free_task(struct task_struct *); -+bool utrace_interrupt_pending(void); -+void utrace_resume(struct task_struct *, struct pt_regs *); -+void utrace_finish_stop(void); -+void utrace_maybe_reap(struct task_struct *, struct utrace *, bool); -+int utrace_get_signal(struct task_struct *, struct pt_regs *, -+ siginfo_t *, struct k_sigaction *); -+void utrace_report_clone(unsigned long, struct task_struct *); -+void utrace_finish_vfork(struct task_struct *); -+void utrace_report_exit(long *exit_code); -+void utrace_report_death(struct task_struct *, bool, int); -+void utrace_report_jctl(int notify, int type); -+void utrace_report_exec(struct linux_binfmt *, struct linux_binprm *, -+ struct pt_regs *regs); -+bool utrace_report_syscall_entry(struct pt_regs *); -+void utrace_report_syscall_exit(struct pt_regs *); -+void utrace_signal_handler(struct task_struct *, int); -+ -+#define UTRACE_FLAG(task, ev) (task_utrace_flags(task) & UTRACE_EVENT(ev)) -+ -+#define UTRACE_HOOK(task, ev, callback) \ -+ do { \ -+ if (UTRACE_FLAG(task, ev)) \ -+ utrace_ ## callback; \ -+ } while (0) -+ -+#ifndef CONFIG_UTRACE -+ -+static inline void task_utrace_lock(struct task_struct *task) -+{ -+} -+static inline void task_utrace_unlock(struct task_struct *task) -+{ -+} -+/* -+ * uses these accessors to avoid #ifdef CONFIG_UTRACE. -+ */ -+static inline unsigned long task_utrace_flags(struct task_struct *task) -+{ -+ return 0; -+} -+static inline struct utrace *task_utrace_struct(struct task_struct *task) -+{ -+ return NULL; -+} -+static inline void utrace_init_task(struct task_struct *child) -+{ -+} -+ -+static inline void task_utrace_proc_status(struct seq_file *m, -+ struct task_struct *p) -+{ -+} -+ -+#else /* CONFIG_UTRACE */ -+ -+extern void task_utrace_lock(struct task_struct *task); -+extern void task_utrace_unlock(struct task_struct *task); -+ -+static inline unsigned long task_utrace_flags(struct task_struct *task) -+{ -+ return task->utrace_flags; -+} -+ -+static inline struct utrace *task_utrace_struct(struct task_struct *task) -+{ -+ struct utrace *utrace; -+ -+ /* -+ * This barrier ensures that any prior load of task->utrace_flags -+ * is ordered before this load of task->utrace. We use those -+ * utrace_flags checks in the hot path to decide to call into -+ * the utrace code. The first attach installs task->utrace before -+ * setting task->utrace_flags nonzero with implicit barrier in -+ * between, see utrace_add_engine(). -+ */ -+ smp_rmb(); -+ utrace = task->utrace; -+ -+ smp_read_barrier_depends(); /* See utrace_task_alloc(). */ -+ return utrace; -+} -+ -+static inline void utrace_init_task(struct task_struct *task) -+{ -+ task->utrace_flags = 0; -+ task->utrace = NULL; -+} -+ -+void task_utrace_proc_status(struct seq_file *m, struct task_struct *p); -+ -+ -+/* -+ * Version number of the API defined in this file. This will change -+ * whenever a tracing engine's code would need some updates to keep -+ * working. We maintain this here for the benefit of tracing engine code -+ * that is developed concurrently with utrace API improvements before they -+ * are merged into the kernel, making LINUX_VERSION_CODE checks unwieldy. -+ */ -+#define UTRACE_API_VERSION 20091216 -+ -+/** -+ * enum utrace_resume_action - engine's choice of action for a traced task -+ * @UTRACE_STOP: Stay quiescent after callbacks. -+ * @UTRACE_INTERRUPT: Make @report_signal() callback soon. -+ * @UTRACE_REPORT: Make some callback soon. -+ * @UTRACE_SINGLESTEP: Resume in user mode for one instruction. -+ * @UTRACE_BLOCKSTEP: Resume in user mode until next branch. -+ * @UTRACE_RESUME: Resume normally in user mode. -+ * @UTRACE_DETACH: Detach my engine (implies %UTRACE_RESUME). -+ * -+ * See utrace_control() for detailed descriptions of each action. This is -+ * encoded in the @action argument and the return value for every callback -+ * with a &u32 return value. -+ * -+ * The order of these is important. When there is more than one engine, -+ * each supplies its choice and the smallest value prevails. -+ */ -+enum utrace_resume_action { -+ UTRACE_STOP, -+ UTRACE_INTERRUPT, -+ UTRACE_REPORT, -+ UTRACE_SINGLESTEP, -+ UTRACE_BLOCKSTEP, -+ UTRACE_RESUME, -+ UTRACE_DETACH, -+ UTRACE_RESUME_MAX -+}; -+#define UTRACE_RESUME_BITS (ilog2(UTRACE_RESUME_MAX) + 1) -+#define UTRACE_RESUME_MASK ((1 << UTRACE_RESUME_BITS) - 1) -+ -+/** -+ * utrace_resume_action - &enum utrace_resume_action from callback action -+ * @action: &u32 callback @action argument or return value -+ * -+ * This extracts the &enum utrace_resume_action from @action, -+ * which is the @action argument to a &struct utrace_engine_ops -+ * callback or the return value from one. -+ */ -+static inline enum utrace_resume_action utrace_resume_action(u32 action) -+{ -+ return action & UTRACE_RESUME_MASK; -+} -+ -+/** -+ * enum utrace_signal_action - disposition of signal -+ * @UTRACE_SIGNAL_DELIVER: Deliver according to sigaction. -+ * @UTRACE_SIGNAL_IGN: Ignore the signal. -+ * @UTRACE_SIGNAL_TERM: Terminate the process. -+ * @UTRACE_SIGNAL_CORE: Terminate with core dump. -+ * @UTRACE_SIGNAL_STOP: Deliver as absolute stop. -+ * @UTRACE_SIGNAL_TSTP: Deliver as job control stop. -+ * @UTRACE_SIGNAL_REPORT: Reporting before pending signals. -+ * @UTRACE_SIGNAL_HANDLER: Reporting after signal handler setup. -+ * -+ * This is encoded in the @action argument and the return value for -+ * a @report_signal() callback. It says what will happen to the -+ * signal described by the &siginfo_t parameter to the callback. -+ * -+ * The %UTRACE_SIGNAL_REPORT value is used in an @action argument when -+ * a tracing report is being made before dequeuing any pending signal. -+ * If this is immediately after a signal handler has been set up, then -+ * %UTRACE_SIGNAL_HANDLER is used instead. A @report_signal callback -+ * that uses %UTRACE_SIGNAL_DELIVER|%UTRACE_SINGLESTEP will ensure -+ * it sees a %UTRACE_SIGNAL_HANDLER report. -+ */ -+enum utrace_signal_action { -+ UTRACE_SIGNAL_DELIVER = 0x00, -+ UTRACE_SIGNAL_IGN = 0x10, -+ UTRACE_SIGNAL_TERM = 0x20, -+ UTRACE_SIGNAL_CORE = 0x30, -+ UTRACE_SIGNAL_STOP = 0x40, -+ UTRACE_SIGNAL_TSTP = 0x50, -+ UTRACE_SIGNAL_REPORT = 0x60, -+ UTRACE_SIGNAL_HANDLER = 0x70 -+}; -+#define UTRACE_SIGNAL_MASK 0xf0 -+#define UTRACE_SIGNAL_HOLD 0x100 /* Flag, push signal back on queue. */ -+ -+/** -+ * utrace_signal_action - &enum utrace_signal_action from callback action -+ * @action: @report_signal callback @action argument or return value -+ * -+ * This extracts the &enum utrace_signal_action from @action, which -+ * is the @action argument to a @report_signal callback or the -+ * return value from one. -+ */ -+static inline enum utrace_signal_action utrace_signal_action(u32 action) -+{ -+ return action & UTRACE_SIGNAL_MASK; -+} -+ -+/** -+ * enum utrace_syscall_action - disposition of system call attempt -+ * @UTRACE_SYSCALL_RUN: Run the system call. -+ * @UTRACE_SYSCALL_ABORT: Don't run the system call. -+ * -+ * This is encoded in the @action argument and the return value for -+ * a @report_syscall_entry callback. -+ */ -+enum utrace_syscall_action { -+ UTRACE_SYSCALL_RUN = 0x00, -+ UTRACE_SYSCALL_ABORT = 0x10 -+}; -+#define UTRACE_SYSCALL_MASK 0xf0 -+#define UTRACE_SYSCALL_RESUMED 0x100 /* Flag, report_syscall_entry() repeats */ -+ -+/** -+ * utrace_syscall_action - &enum utrace_syscall_action from callback action -+ * @action: @report_syscall_entry callback @action or return value -+ * -+ * This extracts the &enum utrace_syscall_action from @action, which -+ * is the @action argument to a @report_syscall_entry callback or the -+ * return value from one. -+ */ -+static inline enum utrace_syscall_action utrace_syscall_action(u32 action) -+{ -+ return action & UTRACE_SYSCALL_MASK; -+} -+ -+/* -+ * Flags for utrace_attach_task() and utrace_attach_pid(). -+ */ -+#define UTRACE_ATTACH_MATCH_OPS 0x0001 /* Match engines on ops. */ -+#define UTRACE_ATTACH_MATCH_DATA 0x0002 /* Match engines on data. */ -+#define UTRACE_ATTACH_MATCH_MASK 0x000f -+#define UTRACE_ATTACH_CREATE 0x0010 /* Attach a new engine. */ -+#define UTRACE_ATTACH_EXCLUSIVE 0x0020 /* Refuse if existing match. */ -+#define UTRACE_ATTACH_ATOMIC 0x0040 /* For _CREATE, don't sleep */ -+ -+/** -+ * struct utrace_engine - per-engine structure -+ * @ops: &struct utrace_engine_ops pointer passed to utrace_attach_task() -+ * @data: engine-private &void * passed to utrace_attach_task() -+ * @flags: event mask set by utrace_set_events() plus internal flag bits -+ * -+ * The task itself never has to worry about engines detaching while -+ * it's doing event callbacks. These structures are removed from the -+ * task's active list only when it's stopped, or by the task itself. -+ * -+ * utrace_engine_get() and utrace_engine_put() maintain a reference count. -+ * When it drops to zero, the structure is freed. One reference is held -+ * implicitly while the engine is attached to its task. -+ */ -+struct utrace_engine { -+/* private: */ -+ struct kref kref; -+ void (*release)(void *); -+ struct list_head entry; -+ -+/* public: */ -+ const struct utrace_engine_ops *ops; -+ void *data; -+ -+ unsigned long flags; -+}; -+ -+/** -+ * utrace_engine_get - acquire a reference on a &struct utrace_engine -+ * @engine: &struct utrace_engine pointer -+ * -+ * You must hold a reference on @engine, and you get another. -+ */ -+static inline void utrace_engine_get(struct utrace_engine *engine) -+{ -+ kref_get(&engine->kref); -+} -+ -+void __utrace_engine_release(struct kref *); -+ -+/** -+ * utrace_engine_put - release a reference on a &struct utrace_engine -+ * @engine: &struct utrace_engine pointer -+ * -+ * You must hold a reference on @engine, and you lose that reference. -+ * If it was the last one, @engine becomes an invalid pointer. -+ */ -+static inline void utrace_engine_put(struct utrace_engine *engine) -+{ -+ kref_put(&engine->kref, __utrace_engine_release); -+} -+ -+/** -+ * struct utrace_engine_ops - tracing engine callbacks -+ * -+ * Each @report_*() callback corresponds to an %UTRACE_EVENT(*) bit. -+ * utrace_set_events() calls on @engine choose which callbacks will -+ * be made to @engine from @task. -+ * -+ * Most callbacks take an @action argument, giving the resume action -+ * chosen by other tracing engines. All callbacks take an @engine -+ * argument. The @report_reap callback takes a @task argument that -+ * might or might not be @current. All other @report_* callbacks -+ * report an event in the @current task. -+ * -+ * For some calls, @action also includes bits specific to that event -+ * and utrace_resume_action() is used to extract the resume action. -+ * This shows what would happen if @engine wasn't there, or will if -+ * the callback's return value uses %UTRACE_RESUME. This always -+ * starts as %UTRACE_RESUME when no other tracing is being done on -+ * this task. -+ * -+ * All return values contain &enum utrace_resume_action bits. For -+ * some calls, other bits specific to that kind of event are added to -+ * the resume action bits with OR. These are the same bits used in -+ * the @action argument. The resume action returned by a callback -+ * does not override previous engines' choices, it only says what -+ * @engine wants done. What @current actually does is the action that's -+ * most constrained among the choices made by all attached engines. -+ * See utrace_control() for more information on the actions. -+ * -+ * When %UTRACE_STOP is used in @report_syscall_entry, then @current -+ * stops before attempting the system call. In this case, another -+ * @report_syscall_entry callback will follow after @current resumes if -+ * %UTRACE_REPORT or %UTRACE_INTERRUPT was returned by some callback -+ * or passed to utrace_control(). In a second or later callback, -+ * %UTRACE_SYSCALL_RESUMED is set in the @action argument to indicate -+ * a repeat callback still waiting to attempt the same system call -+ * invocation. This repeat callback gives each engine an opportunity -+ * to reexamine registers another engine might have changed while -+ * @current was held in %UTRACE_STOP. -+ * -+ * In other cases, the resume action does not take effect until @current -+ * is ready to check for signals and return to user mode. If there -+ * are more callbacks to be made, the last round of calls determines -+ * the final action. A @report_quiesce callback with @event zero, or -+ * a @report_signal callback, will always be the last one made before -+ * @current resumes. Only %UTRACE_STOP is "sticky"--if @engine returned -+ * %UTRACE_STOP then @current stays stopped unless @engine returns -+ * different from a following callback. -+ * -+ * The report_death() and report_reap() callbacks do not take @action -+ * arguments, and only %UTRACE_DETACH is meaningful in the return value -+ * from a report_death() callback. None of the resume actions applies -+ * to a dead thread. -+ * -+ * All @report_*() hooks are called with no locks held, in a generally -+ * safe environment when we will be returning to user mode soon (or just -+ * entered the kernel). It is fine to block for memory allocation and -+ * the like, but all hooks are asynchronous and must not block on -+ * external events! If you want the thread to block, use %UTRACE_STOP -+ * in your hook's return value; then later wake it up with utrace_control(). -+ * -+ * @report_quiesce: -+ * Requested by %UTRACE_EVENT(%QUIESCE). -+ * This does not indicate any event, but just that @current is in a -+ * safe place for examination. This call is made before each specific -+ * event callback, except for @report_reap. The @event argument gives -+ * the %UTRACE_EVENT(@which) value for the event occurring. This -+ * callback might be made for events @engine has not requested, if -+ * some other engine is tracing the event; calling utrace_set_events() -+ * call here can request the immediate callback for this occurrence of -+ * @event. @event is zero when there is no other event, @current is -+ * now ready to check for signals and return to user mode, and some -+ * engine has used %UTRACE_REPORT or %UTRACE_INTERRUPT to request this -+ * callback. For this case, if @report_signal is not %NULL, the -+ * @report_quiesce callback may be replaced with a @report_signal -+ * callback passing %UTRACE_SIGNAL_REPORT in its @action argument, -+ * whenever @current is entering the signal-check path anyway. -+ * -+ * @report_signal: -+ * Requested by %UTRACE_EVENT(%SIGNAL_*) or %UTRACE_EVENT(%QUIESCE). -+ * Use utrace_signal_action() and utrace_resume_action() on @action. -+ * The signal action is %UTRACE_SIGNAL_REPORT when some engine has -+ * used %UTRACE_REPORT or %UTRACE_INTERRUPT; the callback can choose -+ * to stop or to deliver an artificial signal, before pending signals. -+ * It's %UTRACE_SIGNAL_HANDLER instead when signal handler setup just -+ * finished (after a previous %UTRACE_SIGNAL_DELIVER return); this -+ * serves in lieu of any %UTRACE_SIGNAL_REPORT callback requested by -+ * %UTRACE_REPORT or %UTRACE_INTERRUPT, and is also implicitly -+ * requested by %UTRACE_SINGLESTEP or %UTRACE_BLOCKSTEP into the -+ * signal delivery. The other signal actions indicate a signal about -+ * to be delivered; the previous engine's return value sets the signal -+ * action seen by the the following engine's callback. The @info data -+ * can be changed at will, including @info->si_signo. The settings in -+ * @return_ka determines what %UTRACE_SIGNAL_DELIVER does. @orig_ka -+ * is what was in force before other tracing engines intervened, and -+ * it's %NULL when this report began as %UTRACE_SIGNAL_REPORT or -+ * %UTRACE_SIGNAL_HANDLER. For a report without a new signal, @info -+ * is left uninitialized and must be set completely by an engine that -+ * chooses to deliver a signal; if there was a previous @report_signal -+ * callback ending in %UTRACE_STOP and it was just resumed using -+ * %UTRACE_REPORT or %UTRACE_INTERRUPT, then @info is left unchanged -+ * from the previous callback. In this way, the original signal can -+ * be left in @info while returning %UTRACE_STOP|%UTRACE_SIGNAL_IGN -+ * and then found again when resuming with %UTRACE_INTERRUPT. -+ * The %UTRACE_SIGNAL_HOLD flag bit can be OR'd into the return value, -+ * and might be in @action if the previous engine returned it. This -+ * flag asks that the signal in @info be pushed back on @current's queue -+ * so that it will be seen again after whatever action is taken now. -+ * -+ * @report_clone: -+ * Requested by %UTRACE_EVENT(%CLONE). -+ * Event reported for parent, before the new task @child might run. -+ * @clone_flags gives the flags used in the clone system call, or -+ * equivalent flags for a fork() or vfork() system call. This -+ * function can use utrace_attach_task() on @child. Then passing -+ * %UTRACE_STOP to utrace_control() on @child here keeps the child -+ * stopped before it ever runs in user mode, %UTRACE_REPORT or -+ * %UTRACE_INTERRUPT ensures a callback from @child before it -+ * starts in user mode. -+ * -+ * @report_jctl: -+ * Requested by %UTRACE_EVENT(%JCTL). -+ * Job control event; @type is %CLD_STOPPED or %CLD_CONTINUED, -+ * indicating whether we are stopping or resuming now. If @notify -+ * is nonzero, @current is the last thread to stop and so will send -+ * %SIGCHLD to its parent after this callback; @notify reflects -+ * what the parent's %SIGCHLD has in @si_code, which can sometimes -+ * be %CLD_STOPPED even when @type is %CLD_CONTINUED. -+ * -+ * @report_exec: -+ * Requested by %UTRACE_EVENT(%EXEC). -+ * An execve system call has succeeded and the new program is about to -+ * start running. The initial user register state is handy to be tweaked -+ * directly in @regs. @fmt and @bprm gives the details of this exec. -+ * -+ * @report_syscall_entry: -+ * Requested by %UTRACE_EVENT(%SYSCALL_ENTRY). -+ * Thread has entered the kernel to request a system call. -+ * The user register state is handy to be tweaked directly in @regs. -+ * The @action argument contains an &enum utrace_syscall_action, -+ * use utrace_syscall_action() to extract it. The return value -+ * overrides the last engine's action for the system call. -+ * If the final action is %UTRACE_SYSCALL_ABORT, no system call -+ * is made. The details of the system call being attempted can -+ * be fetched here with syscall_get_nr() and syscall_get_arguments(). -+ * The parameter registers can be changed with syscall_set_arguments(). -+ * See above about the %UTRACE_SYSCALL_RESUMED flag in @action. -+ * Use %UTRACE_REPORT in the return value to guarantee you get -+ * another callback (with %UTRACE_SYSCALL_RESUMED flag) in case -+ * @current stops with %UTRACE_STOP before attempting the system call. -+ * -+ * @report_syscall_exit: -+ * Requested by %UTRACE_EVENT(%SYSCALL_EXIT). -+ * Thread is about to leave the kernel after a system call request. -+ * The user register state is handy to be tweaked directly in @regs. -+ * The results of the system call attempt can be examined here using -+ * syscall_get_error() and syscall_get_return_value(). It is safe -+ * here to call syscall_set_return_value() or syscall_rollback(). -+ * -+ * @report_exit: -+ * Requested by %UTRACE_EVENT(%EXIT). -+ * Thread is exiting and cannot be prevented from doing so, -+ * but all its state is still live. The @code value will be -+ * the wait result seen by the parent, and can be changed by -+ * this engine or others. The @orig_code value is the real -+ * status, not changed by any tracing engine. Returning %UTRACE_STOP -+ * here keeps @current stopped before it cleans up its state and dies, -+ * so it can be examined by other processes. When @current is allowed -+ * to run, it will die and get to the @report_death callback. -+ * -+ * @report_death: -+ * Requested by %UTRACE_EVENT(%DEATH). -+ * Thread is really dead now. It might be reaped by its parent at -+ * any time, or self-reap immediately. Though the actual reaping -+ * may happen in parallel, a report_reap() callback will always be -+ * ordered after a report_death() callback. -+ * -+ * @report_reap: -+ * Requested by %UTRACE_EVENT(%REAP). -+ * Called when someone reaps the dead task (parent, init, or self). -+ * This means the parent called wait, or else this was a detached -+ * thread or a process whose parent ignores SIGCHLD. -+ * No more callbacks are made after this one. -+ * The engine is always detached. -+ * There is nothing more a tracing engine can do about this thread. -+ * After this callback, the @engine pointer will become invalid. -+ * The @task pointer may become invalid if get_task_struct() hasn't -+ * been used to keep it alive. -+ * An engine should always request this callback if it stores the -+ * @engine pointer or stores any pointer in @engine->data, so it -+ * can clean up its data structures. -+ * Unlike other callbacks, this can be called from the parent's context -+ * rather than from the traced thread itself--it must not delay the -+ * parent by blocking. -+ * -+ * @release: -+ * If not %NULL, this is called after the last utrace_engine_put() -+ * call for a &struct utrace_engine, which could be implicit after -+ * a %UTRACE_DETACH return from another callback. Its argument is -+ * the engine's @data member. -+ */ -+struct utrace_engine_ops { -+ u32 (*report_quiesce)(u32 action, struct utrace_engine *engine, -+ unsigned long event); -+ u32 (*report_signal)(u32 action, struct utrace_engine *engine, -+ struct pt_regs *regs, -+ siginfo_t *info, -+ const struct k_sigaction *orig_ka, -+ struct k_sigaction *return_ka); -+ u32 (*report_clone)(u32 action, struct utrace_engine *engine, -+ unsigned long clone_flags, -+ struct task_struct *child); -+ u32 (*report_jctl)(u32 action, struct utrace_engine *engine, -+ int type, int notify); -+ u32 (*report_exec)(u32 action, struct utrace_engine *engine, -+ const struct linux_binfmt *fmt, -+ const struct linux_binprm *bprm, -+ struct pt_regs *regs); -+ u32 (*report_syscall_entry)(u32 action, struct utrace_engine *engine, -+ struct pt_regs *regs); -+ u32 (*report_syscall_exit)(u32 action, struct utrace_engine *engine, -+ struct pt_regs *regs); -+ u32 (*report_exit)(u32 action, struct utrace_engine *engine, -+ long orig_code, long *code); -+ u32 (*report_death)(struct utrace_engine *engine, -+ bool group_dead, int signal); -+ void (*report_reap)(struct utrace_engine *engine, -+ struct task_struct *task); -+ void (*release)(void *data); -+}; -+ -+/** -+ * struct utrace_examiner - private state for using utrace_prepare_examine() -+ * -+ * The members of &struct utrace_examiner are private to the implementation. -+ * This data type holds the state from a call to utrace_prepare_examine() -+ * to be used by a call to utrace_finish_examine(). -+ */ -+struct utrace_examiner { -+/* private: */ -+ long state; -+ unsigned long ncsw; -+}; -+ -+/* -+ * These are the exported entry points for tracing engines to use. -+ * See kernel/utrace.c for their kerneldoc comments with interface details. -+ */ -+struct utrace_engine *utrace_attach_task(struct task_struct *, int, -+ const struct utrace_engine_ops *, -+ void *); -+struct utrace_engine *utrace_attach_pid(struct pid *, int, -+ const struct utrace_engine_ops *, -+ void *); -+int __must_check utrace_control(struct task_struct *, -+ struct utrace_engine *, -+ enum utrace_resume_action); -+int __must_check utrace_set_events(struct task_struct *, -+ struct utrace_engine *, -+ unsigned long eventmask); -+int __must_check utrace_barrier(struct task_struct *, -+ struct utrace_engine *); -+int __must_check utrace_prepare_examine(struct task_struct *, -+ struct utrace_engine *, -+ struct utrace_examiner *); -+int __must_check utrace_finish_examine(struct task_struct *, -+ struct utrace_engine *, -+ struct utrace_examiner *); -+ -+/** -+ * utrace_control_pid - control a thread being traced by a tracing engine -+ * @pid: thread to affect -+ * @engine: attached engine to affect -+ * @action: &enum utrace_resume_action for thread to do -+ * -+ * This is the same as utrace_control(), but takes a &struct pid -+ * pointer rather than a &struct task_struct pointer. The caller must -+ * hold a ref on @pid, but does not need to worry about the task -+ * staying valid. If it's been reaped so that @pid points nowhere, -+ * then this call returns -%ESRCH. -+ */ -+static inline __must_check int utrace_control_pid( -+ struct pid *pid, struct utrace_engine *engine, -+ enum utrace_resume_action action) -+{ -+ /* -+ * We don't bother with rcu_read_lock() here to protect the -+ * task_struct pointer, because utrace_control will return -+ * -ESRCH without looking at that pointer if the engine is -+ * already detached. A task_struct pointer can't die before -+ * all the engines are detached in release_task() first. -+ */ -+ struct task_struct *task = pid_task(pid, PIDTYPE_PID); -+ return unlikely(!task) ? -ESRCH : utrace_control(task, engine, action); -+} -+ -+/** -+ * utrace_set_events_pid - choose which event reports a tracing engine gets -+ * @pid: thread to affect -+ * @engine: attached engine to affect -+ * @eventmask: new event mask -+ * -+ * This is the same as utrace_set_events(), but takes a &struct pid -+ * pointer rather than a &struct task_struct pointer. The caller must -+ * hold a ref on @pid, but does not need to worry about the task -+ * staying valid. If it's been reaped so that @pid points nowhere, -+ * then this call returns -%ESRCH. -+ */ -+static inline __must_check int utrace_set_events_pid( -+ struct pid *pid, struct utrace_engine *engine, unsigned long eventmask) -+{ -+ struct task_struct *task = pid_task(pid, PIDTYPE_PID); -+ return unlikely(!task) ? -ESRCH : -+ utrace_set_events(task, engine, eventmask); -+} -+ -+/** -+ * utrace_barrier_pid - synchronize with simultaneous tracing callbacks -+ * @pid: thread to affect -+ * @engine: engine to affect (can be detached) -+ * -+ * This is the same as utrace_barrier(), but takes a &struct pid -+ * pointer rather than a &struct task_struct pointer. The caller must -+ * hold a ref on @pid, but does not need to worry about the task -+ * staying valid. If it's been reaped so that @pid points nowhere, -+ * then this call returns -%ESRCH. -+ */ -+static inline __must_check int utrace_barrier_pid(struct pid *pid, -+ struct utrace_engine *engine) -+{ -+ struct task_struct *task = pid_task(pid, PIDTYPE_PID); -+ return unlikely(!task) ? -ESRCH : utrace_barrier(task, engine); -+} -+ -+#endif /* CONFIG_UTRACE */ -+ -+static inline void utrace_release_task(struct task_struct *task) -+{ -+ /* see utrace_add_engine() about this barrier */ -+ smp_mb(); -+ if (task_utrace_flags(task)) -+ utrace_maybe_reap(task, task_utrace_struct(task), true); -+} -+ -+static inline void utrace_exit_notify(struct task_struct *task, -+ int signal, int group_dead) -+{ -+ /* -+ * If utrace_set_events() was just called to enable -+ * UTRACE_EVENT(DEATH), then we are obliged to call -+ * utrace_report_death() and not miss it. utrace_set_events() -+ * checks @task->exit_state under tasklist_lock to synchronize -+ * with exit_notify(), the caller. -+ */ -+ if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) -+ utrace_report_death(task, group_dead, signal); -+} -+ -+/** -+ * utrace_end_stop - report about return from STOPPED/TRACED -+ * -+ * This is called by do_signal_stop() and ptrace_stop after wakeup. -+ */ -+static inline void utrace_end_stop(void) -+{ -+ if (task_utrace_flags(current)) -+ utrace_finish_stop(); -+} -+ -+/** -+ * utrace_hook_signal - deliver synthetic signal to traced task -+ * @task: @current -+ * @regs: task_pt_regs(@current) -+ * @info: details of synthetic signal -+ * @return_ka: sigaction for synthetic signal -+ * -+ * Return zero to check for a real pending signal normally. -+ * Return -1 after releasing the siglock to repeat the check. -+ * Return a signal number to induce an artificial signal delivery, -+ * setting *@info and *@return_ka to specify its details and behavior. -+ * -+ * The @return_ka->sa_handler value controls the disposition of the -+ * signal, no matter the signal number. For %SIG_DFL, the return value -+ * is a representative signal to indicate the behavior (e.g. %SIGTERM -+ * for death, %SIGQUIT for core dump, %SIGSTOP for job control stop, -+ * %SIGTSTP for stop unless in an orphaned pgrp), but the signal number -+ * reported will be @info->si_signo instead. -+ * -+ * Called with @task->sighand->siglock held, before dequeuing pending signals. -+ */ -+static inline int utrace_hook_signal(struct task_struct *task, -+ struct pt_regs *regs, -+ siginfo_t *info, -+ struct k_sigaction *return_ka) -+{ -+ if (unlikely(task_utrace_flags(task))) -+ return utrace_get_signal(task, regs, info, return_ka); -+ return 0; -+} -+ -+#endif /* linux/utrace.h */ -diff --git a/init/Kconfig b/init/Kconfig -index 3f42cd6..5f4f92e 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -386,6 +386,15 @@ config AUDIT_LOGINUID_IMMUTABLE - one to drop potentially dangerous capabilites from the login tasks, - but may not be backwards compatible with older init systems. - -+config UTRACE -+ bool "Infrastructure for tracing and debugging user processes" -+ depends on EXPERIMENTAL -+ depends on HAVE_ARCH_TRACEHOOK -+ help -+ Enable the utrace process tracing interface. This is an internal -+ kernel interface exported to kernel modules, to track events in -+ user threads, extract and change user thread state. -+ - source "kernel/irq/Kconfig" - - menu "RCU Subsystem" -diff --git a/kernel/Makefile b/kernel/Makefile -index 2d9de86..6c6749d 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -67,6 +67,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o - obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o - obj-$(CONFIG_SMP) += stop_machine.o - obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o -+obj-$(CONFIG_UTRACE) += utrace.o - obj-$(CONFIG_AUDIT) += audit.o auditfilter.o - obj-$(CONFIG_AUDITSYSCALL) += auditsc.o - obj-$(CONFIG_AUDIT_WATCH) += audit_watch.o -diff --git a/kernel/exit.c b/kernel/exit.c -index 4b4042f..b1e0518 100644 ---- a/kernel/exit.c -+++ b/kernel/exit.c -@@ -169,6 +169,8 @@ void release_task(struct task_struct * p) - struct task_struct *leader; - int zap_leader; - repeat: -+ utrace_release_task(p); -+ - /* don't need to get the RCU readlock here - the process is dead and - * can't be modifying its own credentials. But shut RCU-lockdep up */ - rcu_read_lock(); -@@ -857,6 +859,8 @@ static void exit_notify(struct task_struct *tsk, int group_dead) - wake_up_process(tsk->signal->group_exit_task); - write_unlock_irq(&tasklist_lock); - -+ utrace_exit_notify(tsk, autoreap ? -1 : SIGCHLD, group_dead); -+ - /* If the process is dead, release it - nobody will wait for it */ - if (autoreap) - release_task(tsk); -@@ -910,6 +914,7 @@ void do_exit(long code) - */ - set_fs(USER_DS); - -+ UTRACE_HOOK(current, EXIT, report_exit(&code)); - ptrace_event(PTRACE_EVENT_EXIT, code); - - validate_creds_for_do_exit(tsk); -diff --git a/kernel/fork.c b/kernel/fork.c -index e2cd3e2..fa40928 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -67,6 +67,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -170,6 +171,8 @@ void free_task(struct task_struct *tsk) - free_thread_info(tsk->stack); - rt_mutex_debug_task_free(tsk); - ftrace_graph_exit_task(tsk); -+ if (task_utrace_struct(tsk)) -+ utrace_free_task(tsk); - free_task_struct(tsk); - } - EXPORT_SYMBOL(free_task); -@@ -1115,6 +1118,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, - if (!p) - goto fork_out; - -+ utrace_init_task(p); -+ - ftrace_graph_init_task(p); - - rt_mutex_init_task(p); -@@ -1583,6 +1583,8 @@ long do_fork(unsigned long clone_flags, - get_task_struct(p); - } - -+ UTRACE_HOOK(current, CLONE, report_clone(clone_flags, p)); -+ - wake_up_new_task(p); - - /* forking complete and child started to run, tell ptracer */ -@@ -1561,6 +1568,8 @@ long do_fork(unsigned long clone_flags, - wake_up_new_task(p); - - /* forking complete and child started to run, tell ptracer */ -+ if (clone_flags & CLONE_VFORK) -+ UTRACE_HOOK(current, CLONE, finish_vfork(current)); - if (unlikely(trace)) - ptrace_event(trace, nr); - -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index 00ab2ca..a7024b8 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -24,7 +24,34 @@ - #include - #include - #include -+#include - -+void ptrace_signal_wake_up(struct task_struct *p, int quiescent) -+{ -+ unsigned int state; -+ -+ set_tsk_thread_flag(p, TIF_SIGPENDING); -+ -+ state = TASK_INTERRUPTIBLE; -+ if (quiescent) -+ state |= (__TASK_STOPPED | __TASK_TRACED); -+ if (!wake_up_quiescent(p, state)) -+ kick_process(p); -+} -+ -+static void ptrace_set_syscall_trace(struct task_struct *p, bool on) -+{ -+ task_utrace_lock(p); -+ if (on) { -+ p->ptrace |= PT_SYSCALL_TRACE; -+ set_tsk_thread_flag(p, TIF_SYSCALL_TRACE); -+ } else { -+ p->ptrace &= ~PT_SYSCALL_TRACE; -+ if (!(task_utrace_flags(p) & UTRACE_EVENT_SYSCALL)) -+ clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); -+ } -+ task_utrace_unlock(p); -+} - - static int ptrace_trapping_sleep_fn(void *flags) - { -@@ -117,7 +144,7 @@ void __ptrace_unlink(struct task_struct *child) - * TASK_KILLABLE sleeps. - */ - if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child)) -- signal_wake_up(child, task_is_traced(child)); -+ ptrace_signal_wake_up(child, task_is_traced(child)); - - spin_unlock(&child->sighand->siglock); - } -@@ -315,7 +342,7 @@ static int ptrace_attach(struct task_struct *task, long request, - */ - if (task_is_stopped(task) && - task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING)) -- signal_wake_up(task, 1); -+ ptrace_signal_wake_up(task, 1); - - spin_unlock(&task->sighand->siglock); - -@@ -425,7 +452,7 @@ static int ptrace_detach(struct task_struct *child, unsigned int data) - - /* Architecture-specific hardware disable .. */ - ptrace_disable(child); -- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); -+ ptrace_set_syscall_trace(child, false); - - write_lock_irq(&tasklist_lock); - /* -@@ -608,13 +635,12 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info) - static int ptrace_resume(struct task_struct *child, long request, - unsigned long data) - { -+ unsigned long flags; -+ - if (!valid_signal(data)) - return -EIO; - -- if (request == PTRACE_SYSCALL) -- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); -- else -- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); -+ ptrace_set_syscall_trace(child, request == PTRACE_SYSCALL); - - #ifdef TIF_SYSCALL_EMU - if (request == PTRACE_SYSEMU || request == PTRACE_SYSEMU_SINGLESTEP) -@@ -623,20 +649,23 @@ static int ptrace_resume(struct task_struct *child, long request, - clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); - #endif - -+ child->ptrace &= ~(PT_SINGLE_STEP | PT_SINGLE_BLOCK); - if (is_singleblock(request)) { - if (unlikely(!arch_has_block_step())) - return -EIO; -- user_enable_block_step(child); -+ child->ptrace |= PT_SINGLE_BLOCK; - } else if (is_singlestep(request) || is_sysemu_singlestep(request)) { - if (unlikely(!arch_has_single_step())) - return -EIO; -- user_enable_single_step(child); -- } else { -- user_disable_single_step(child); -+ child->ptrace |= PT_SINGLE_STEP; - } - - child->exit_code = data; -- wake_up_state(child, __TASK_TRACED); -+ -+ if (lock_task_sighand(child, &flags)) { -+ wake_up_quiescent(child, __TASK_TRACED); -+ unlock_task_sighand(child, &flags); -+ } - - return 0; - } -@@ -744,7 +773,7 @@ int ptrace_request(struct task_struct *child, long request, - * tracee into STOP. - */ - if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP))) -- signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); -+ ptrace_signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); - - unlock_task_sighand(child, &flags); - ret = 0; -@@ -770,7 +799,7 @@ int ptrace_request(struct task_struct *child, long request, - * start of this trap and now. Trigger re-trap. - */ - if (child->jobctl & JOBCTL_TRAP_NOTIFY) -- signal_wake_up(child, true); -+ ptrace_signal_wake_up(child, true); - ret = 0; - } - unlock_task_sighand(child, &flags); -diff --git a/kernel/sched/core.c b/kernel/sched/core.c -index 5255c9d..f1719b8 100644 ---- a/kernel/sched/core.c -+++ b/kernel/sched/core.c -@@ -1167,7 +1167,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) - * is actually now running somewhere else! - */ - while (task_running(rq, p)) { -- if (match_state && unlikely(p->state != match_state)) -+ if (match_state && !likely(p->state & match_state)) - return 0; - cpu_relax(); - } -diff --git a/kernel/signal.c b/kernel/signal.c -index c73c428..0508d93 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -88,7 +88,7 @@ static int sig_ignored(struct task_struct *t, int sig, int from_ancestor_ns) - /* - * Tracers may want to know about even ignored signals. - */ -- return !t->ptrace; -+ return !t->ptrace && !UTRACE_FLAG(t, SIGNAL_IGN); - } - - /* -@@ -151,6 +151,11 @@ void recalc_sigpending_and_wake(struct task_struct *t) - - void recalc_sigpending(void) - { -+ if (task_utrace_flags(current) && utrace_interrupt_pending()) { -+ set_thread_flag(TIF_SIGPENDING); -+ return; -+ } -+ - if (!recalc_sigpending_tsk(current) && !freezing(current)) - clear_thread_flag(TIF_SIGPENDING); - -@@ -495,7 +500,7 @@ int unhandled_signal(struct task_struct *tsk, int sig) - if (handler != SIG_IGN && handler != SIG_DFL) - return 0; - /* if ptraced, let the tracer determine */ -- return !tsk->ptrace; -+ return !tracehook_consider_fatal_signal(tsk, sig); - } - - /* -@@ -697,6 +702,29 @@ void signal_wake_up(struct task_struct *t, int resume) - kick_process(t); - } - -+#define STATE_QUIESCENT (__TASK_STOPPED | __TASK_TRACED | __TASK_UTRACED) -+/* -+ * wakes up the STOPPED/TRACED task, must be called with ->siglock held. -+ */ -+int wake_up_quiescent(struct task_struct *p, unsigned int state) -+{ -+ unsigned int quiescent = (p->state & STATE_QUIESCENT); -+ -+ WARN_ON(state & ~(STATE_QUIESCENT | TASK_INTERRUPTIBLE)); -+ -+ if (quiescent) { -+ state &= ~TASK_INTERRUPTIBLE; -+ if ((quiescent & ~state) != 0) { -+ p->state &= ~state; -+ WARN_ON(!(p->state & STATE_QUIESCENT)); -+ WARN_ON(!(p->state & TASK_WAKEKILL)); -+ return 0; -+ } -+ } -+ -+ return wake_up_state(p, state); -+} -+ - /* - * Remove signals in mask from the pending set and queue. - * Returns 1 if any signals were found. -@@ -842,7 +870,7 @@ static void ptrace_trap_notify(struct task_struct *t) - assert_spin_locked(&t->sighand->siglock); - - task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY); -- signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); -+ ptrace_signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); - } - - /* -@@ -884,7 +912,7 @@ static int prepare_signal(int sig, struct task_struct *p, int from_ancestor_ns) - task_clear_jobctl_pending(t, JOBCTL_STOP_PENDING); - rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending); - if (likely(!(t->ptrace & PT_SEIZED))) -- wake_up_state(t, __TASK_STOPPED); -+ wake_up_quiescent(t, __TASK_STOPPED); - else - ptrace_trap_notify(t); - } while_each_thread(p, t); -@@ -983,7 +1011,7 @@ static void complete_signal(int sig, struct task_struct *p, int group) - if (sig_fatal(p, sig) && - !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) && - !sigismember(&t->real_blocked, sig) && -- (sig == SIGKILL || !t->ptrace)) { -+ (sig == SIGKILL || !tracehook_consider_fatal_signal(t, sig))) { - /* - * This signal will be fatal to the whole group. - */ -@@ -1913,10 +1941,34 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) - if (gstop_done) - do_notify_parent_cldstop(current, false, why); - -- __set_current_state(TASK_RUNNING); -+ spin_lock_irq(¤t->sighand->siglock); -+ wake_up_quiescent(current, __TASK_TRACED); -+ spin_unlock_irq(¤t->sighand->siglock); -+ - if (clear_code) - current->exit_code = 0; - read_unlock(&tasklist_lock); -+ -+ /* -+ * It is possible that __TASK_UTRACED was added by utrace -+ * while we were __TASK_TRACED and before we take ->siglock -+ * for wake_up_quiescent(), we need to block in this case. -+ * Otherwise this is unnecessary but absolutely harmless. -+ */ -+ schedule(); -+ } -+ -+ utrace_end_stop(); -+ -+ if (current->ptrace & PT_SINGLE_BLOCK) -+ user_enable_block_step(current); -+ else if (current->ptrace & PT_SINGLE_STEP) -+ user_enable_single_step(current); -+ else { -+ user_disable_single_step(current); -+ /* if utrace needs the stepping it should reassert */ -+ if (task_utrace_flags(current)) -+ set_thread_flag(TIF_NOTIFY_RESUME); - } - - /* -@@ -2081,6 +2133,9 @@ static bool do_signal_stop(int signr) - - /* Now we don't run again until woken by SIGCONT or SIGKILL */ - schedule(); -+ -+ utrace_end_stop(); -+ - return true; - } else { - /* -@@ -2231,17 +2286,27 @@ relock: - for (;;) { - struct k_sigaction *ka; - -- if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) && -- do_signal_stop(0)) -+ signr = utrace_hook_signal(current, regs, info, return_ka); -+ if (unlikely(signr < 0)) - goto relock; - -- if (unlikely(current->jobctl & JOBCTL_TRAP_MASK)) { -- do_jobctl_trap(); -- spin_unlock_irq(&sighand->siglock); -- goto relock; -- } -+ if (unlikely(signr != 0)) -+ ka = return_ka; -+ else { -+ if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) && -+ do_signal_stop(0)) -+ goto relock; -+ -+ if (unlikely(current->jobctl & JOBCTL_TRAP_MASK)) { -+ do_jobctl_trap(); -+ spin_unlock_irq(&sighand->siglock); -+ goto relock; -+ } - -- signr = dequeue_signal(current, ¤t->blocked, info); -+ signr = dequeue_signal(current, ¤t->blocked, info); -+ -+ ka = &sighand->action[signr-1]; -+ } - - if (!signr) - break; /* will return 0 */ -@@ -2251,9 +2316,9 @@ relock: - regs, cookie); - if (!signr) - continue; -- } - -- ka = &sighand->action[signr-1]; -+ ka = &sighand->action[signr-1]; -+ } - - /* Trace actually delivered signals. */ - trace_signal_deliver(signr, info, ka); -diff --git a/kernel/utrace.c b/kernel/utrace.c -new file mode 100644 -index 0000000..a169e1b ---- /dev/null -+++ b/kernel/utrace.c -@@ -0,0 +1,2466 @@ -+/* -+ * utrace infrastructure interface for debugging user processes -+ * -+ * Copyright (C) 2006-2010 Red Hat, Inc. All rights reserved. -+ * -+ * This copyrighted material is made available to anyone wishing to use, -+ * modify, copy, or redistribute it subject to the terms and conditions -+ * of the GNU General Public License v.2. -+ * -+ * Red Hat Author: Roland McGrath. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+/* -+ * Per-thread structure private to utrace implementation. -+ * If task_struct.utrace_flags is nonzero, task_struct.utrace -+ * has always been allocated first. Once allocated, it is -+ * never freed until free_task(). -+ * -+ * The common event reporting loops are done by the task making the -+ * report without ever taking any locks. To facilitate this, the two -+ * lists @attached and @attaching work together for smooth asynchronous -+ * attaching with low overhead. Modifying either list requires @lock. -+ * The @attaching list can be modified any time while holding @lock. -+ * New engines being attached always go on this list. -+ * -+ * The @attached list is what the task itself uses for its reporting -+ * loops. When the task itself is not quiescent, it can use the -+ * @attached list without taking any lock. Nobody may modify the list -+ * when the task is not quiescent. When it is quiescent, that means -+ * that it won't run again without taking @lock itself before using -+ * the list. -+ * -+ * At each place where we know the task is quiescent (or it's current), -+ * while holding @lock, we call splice_attaching(), below. This moves -+ * the @attaching list members on to the end of the @attached list. -+ * Since this happens at the start of any reporting pass, any new -+ * engines attached asynchronously go on the stable @attached list -+ * in time to have their callbacks seen. -+ */ -+struct utrace { -+ spinlock_t lock; -+ struct list_head attached, attaching; -+ -+ struct task_struct *cloning; -+ -+ struct utrace_engine *reporting; -+ -+ enum utrace_resume_action resume:UTRACE_RESUME_BITS; -+ unsigned int signal_handler:1; -+ unsigned int vfork_stop:1; /* need utrace_stop() before vfork wait */ -+ unsigned int death:1; /* in utrace_report_death() now */ -+ unsigned int reap:1; /* release_task() has run */ -+ unsigned int pending_attach:1; /* need splice_attaching() */ -+}; -+ -+static struct kmem_cache *utrace_cachep; -+static struct kmem_cache *utrace_engine_cachep; -+static const struct utrace_engine_ops utrace_detached_ops; /* forward decl */ -+ -+static int __init utrace_init(void) -+{ -+ utrace_cachep = KMEM_CACHE(utrace, SLAB_PANIC); -+ utrace_engine_cachep = KMEM_CACHE(utrace_engine, SLAB_PANIC); -+ return 0; -+} -+module_init(utrace_init); -+ -+void task_utrace_lock(struct task_struct *task) -+{ -+ struct utrace *utrace = task_utrace_struct(task); -+ -+ if (!utrace) { -+ task_lock(task); -+ utrace = task_utrace_struct(task); -+ if (!utrace) -+ return; -+ -+ task_unlock(task); -+ } -+ -+ spin_lock(&utrace->lock); -+} -+ -+void task_utrace_unlock(struct task_struct *task) -+{ -+ struct utrace *utrace = task_utrace_struct(task); -+ -+ if (utrace) -+ spin_unlock(&utrace->lock); -+ else -+ task_unlock(task); -+} -+ -+/* -+ * Set up @task.utrace for the first time. We can have races -+ * between two utrace_attach_task() calls here. The task_lock() -+ * governs installing the new pointer. If another one got in first, -+ * we just punt the new one we allocated. -+ * -+ * This returns false only in case of a memory allocation failure. -+ */ -+static bool utrace_task_alloc(struct task_struct *task, gfp_t gfp_flags) -+{ -+ struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, gfp_flags); -+ if (unlikely(!utrace)) -+ return false; -+ spin_lock_init(&utrace->lock); -+ INIT_LIST_HEAD(&utrace->attached); -+ INIT_LIST_HEAD(&utrace->attaching); -+ utrace->resume = UTRACE_RESUME; -+ task_lock(task); -+ if (likely(!task->utrace)) { -+ /* -+ * This barrier makes sure the initialization of the struct -+ * precedes the installation of the pointer. This pairs -+ * with smp_read_barrier_depends() in task_utrace_struct(). -+ */ -+ smp_wmb(); -+ task->utrace = utrace; -+ } -+ task_unlock(task); -+ -+ if (unlikely(task->utrace != utrace)) -+ kmem_cache_free(utrace_cachep, utrace); -+ return true; -+} -+ -+/* -+ * This is called via tracehook_free_task() from free_task() -+ * when @task is being deallocated. -+ */ -+void utrace_free_task(struct task_struct *task) -+{ -+ kmem_cache_free(utrace_cachep, task->utrace); -+} -+ -+/* -+ * This is calledwhen the task is safely quiescent, i.e. it won't consult -+ * utrace->attached without the lock. Move any engines attached -+ * asynchronously from @utrace->attaching onto the @utrace->attached list. -+ */ -+static void splice_attaching(struct utrace *utrace) -+{ -+ lockdep_assert_held(&utrace->lock); -+ list_splice_tail_init(&utrace->attaching, &utrace->attached); -+ utrace->pending_attach = 0; -+} -+ -+/* -+ * This is the exported function used by the utrace_engine_put() inline. -+ */ -+void __utrace_engine_release(struct kref *kref) -+{ -+ struct utrace_engine *engine = container_of(kref, struct utrace_engine, -+ kref); -+ BUG_ON(!list_empty(&engine->entry)); -+ if (engine->release) -+ (*engine->release)(engine->data); -+ kmem_cache_free(utrace_engine_cachep, engine); -+} -+EXPORT_SYMBOL_GPL(__utrace_engine_release); -+ -+static bool engine_matches(struct utrace_engine *engine, int flags, -+ const struct utrace_engine_ops *ops, void *data) -+{ -+ if ((flags & UTRACE_ATTACH_MATCH_OPS) && engine->ops != ops) -+ return false; -+ if ((flags & UTRACE_ATTACH_MATCH_DATA) && engine->data != data) -+ return false; -+ return engine->ops && engine->ops != &utrace_detached_ops; -+} -+ -+static struct utrace_engine *find_matching_engine( -+ struct utrace *utrace, int flags, -+ const struct utrace_engine_ops *ops, void *data) -+{ -+ struct utrace_engine *engine; -+ list_for_each_entry(engine, &utrace->attached, entry) -+ if (engine_matches(engine, flags, ops, data)) -+ return engine; -+ list_for_each_entry(engine, &utrace->attaching, entry) -+ if (engine_matches(engine, flags, ops, data)) -+ return engine; -+ return NULL; -+} -+ -+/* -+ * Enqueue @engine, or maybe don't if UTRACE_ATTACH_EXCLUSIVE. -+ */ -+static int utrace_add_engine(struct task_struct *target, -+ struct utrace *utrace, -+ struct utrace_engine *engine, -+ int flags, -+ const struct utrace_engine_ops *ops, -+ void *data) -+{ -+ int ret; -+ -+ spin_lock(&utrace->lock); -+ -+ ret = -EEXIST; -+ if ((flags & UTRACE_ATTACH_EXCLUSIVE) && -+ unlikely(find_matching_engine(utrace, flags, ops, data))) -+ goto unlock; -+ -+ /* -+ * In case we had no engines before, make sure that -+ * utrace_flags is not zero. Since we did unlock+lock -+ * at least once after utrace_task_alloc() installed -+ * ->utrace, we have the necessary barrier which pairs -+ * with rmb() in task_utrace_struct(). -+ */ -+ ret = -ESRCH; -+ if (!target->utrace_flags) { -+ target->utrace_flags = UTRACE_EVENT(REAP); -+ /* -+ * If we race with tracehook_prepare_release_task() -+ * make sure that either it sees utrace_flags != 0 -+ * or we see exit_state == EXIT_DEAD. -+ */ -+ smp_mb(); -+ if (unlikely(target->exit_state == EXIT_DEAD)) { -+ target->utrace_flags = 0; -+ goto unlock; -+ } -+ } -+ -+ /* -+ * Put the new engine on the pending ->attaching list. -+ * Make sure it gets onto the ->attached list by the next -+ * time it's examined. Setting ->pending_attach ensures -+ * that start_report() takes the lock and splices the lists -+ * before the next new reporting pass. -+ * -+ * When target == current, it would be safe just to call -+ * splice_attaching() right here. But if we're inside a -+ * callback, that would mean the new engine also gets -+ * notified about the event that precipitated its own -+ * creation. This is not what the user wants. -+ */ -+ list_add_tail(&engine->entry, &utrace->attaching); -+ utrace->pending_attach = 1; -+ utrace_engine_get(engine); -+ ret = 0; -+unlock: -+ spin_unlock(&utrace->lock); -+ -+ return ret; -+} -+ -+/** -+ * utrace_attach_task - attach new engine, or look up an attached engine -+ * @target: thread to attach to -+ * @flags: flag bits combined with OR, see below -+ * @ops: callback table for new engine -+ * @data: engine private data pointer -+ * -+ * The caller must ensure that the @target thread does not get freed, -+ * i.e. hold a ref or be its parent. It is always safe to call this -+ * on @current, or on the @child pointer in a @report_clone callback. -+ * For most other cases, it's easier to use utrace_attach_pid() instead. -+ * -+ * UTRACE_ATTACH_CREATE: -+ * Create a new engine. If %UTRACE_ATTACH_CREATE is not specified, you -+ * only look up an existing engine already attached to the thread. -+ * -+ * UTRACE_ATTACH_EXCLUSIVE: -+ * Attempting to attach a second (matching) engine fails with -%EEXIST. -+ * -+ * UTRACE_ATTACH_MATCH_OPS: Only consider engines matching @ops. -+ * UTRACE_ATTACH_MATCH_DATA: Only consider engines matching @data. -+ * -+ * Calls with neither %UTRACE_ATTACH_MATCH_OPS nor %UTRACE_ATTACH_MATCH_DATA -+ * match the first among any engines attached to @target. That means that -+ * %UTRACE_ATTACH_EXCLUSIVE in such a call fails with -%EEXIST if there -+ * are any engines on @target at all. -+ */ -+struct utrace_engine *utrace_attach_task( -+ struct task_struct *target, int flags, -+ const struct utrace_engine_ops *ops, void *data) -+{ -+ struct utrace *utrace = task_utrace_struct(target); -+ struct utrace_engine *engine; -+ gfp_t gfp_flags; -+ int ret; -+ -+ if (!(flags & UTRACE_ATTACH_CREATE)) { -+ if (unlikely(!utrace)) -+ return ERR_PTR(-ENOENT); -+ spin_lock(&utrace->lock); -+ engine = find_matching_engine(utrace, flags, ops, data); -+ if (engine) -+ utrace_engine_get(engine); -+ spin_unlock(&utrace->lock); -+ return engine ?: ERR_PTR(-ENOENT); -+ } -+ -+ if (unlikely(!ops) || unlikely(ops == &utrace_detached_ops)) -+ return ERR_PTR(-EINVAL); -+ -+ if (unlikely(target->flags & PF_KTHREAD)) -+ /* -+ * Silly kernel, utrace is for users! -+ */ -+ return ERR_PTR(-EPERM); -+ -+ gfp_flags = (flags & UTRACE_ATTACH_ATOMIC) -+ ? GFP_ATOMIC : GFP_KERNEL; -+ -+ if (!utrace) { -+ if (unlikely(!utrace_task_alloc(target, gfp_flags))) -+ return ERR_PTR(-ENOMEM); -+ utrace = task_utrace_struct(target); -+ } -+ -+ engine = kmem_cache_alloc(utrace_engine_cachep, gfp_flags); -+ if (unlikely(!engine)) -+ return ERR_PTR(-ENOMEM); -+ -+ /* -+ * Initialize the new engine structure. It starts out with one ref -+ * to return. utrace_add_engine() adds another for being attached. -+ */ -+ kref_init(&engine->kref); -+ engine->flags = 0; -+ engine->ops = ops; -+ engine->data = data; -+ engine->release = ops->release; -+ -+ ret = utrace_add_engine(target, utrace, engine, flags, ops, data); -+ -+ if (unlikely(ret)) { -+ kmem_cache_free(utrace_engine_cachep, engine); -+ engine = ERR_PTR(ret); -+ } -+ -+ -+ return engine; -+} -+EXPORT_SYMBOL_GPL(utrace_attach_task); -+ -+/** -+ * utrace_attach_pid - attach new engine, or look up an attached engine -+ * @pid: &struct pid pointer representing thread to attach to -+ * @flags: flag bits combined with OR, see utrace_attach_task() -+ * @ops: callback table for new engine -+ * @data: engine private data pointer -+ * -+ * This is the same as utrace_attach_task(), but takes a &struct pid -+ * pointer rather than a &struct task_struct pointer. The caller must -+ * hold a ref on @pid, but does not need to worry about the task -+ * staying valid. If it's been reaped so that @pid points nowhere, -+ * then this call returns -%ESRCH. -+ */ -+struct utrace_engine *utrace_attach_pid( -+ struct pid *pid, int flags, -+ const struct utrace_engine_ops *ops, void *data) -+{ -+ struct utrace_engine *engine = ERR_PTR(-ESRCH); -+ struct task_struct *task = get_pid_task(pid, PIDTYPE_PID); -+ if (task) { -+ engine = utrace_attach_task(task, flags, ops, data); -+ put_task_struct(task); -+ } -+ return engine; -+} -+EXPORT_SYMBOL_GPL(utrace_attach_pid); -+ -+/* -+ * When an engine is detached, the target thread may still see it and -+ * make callbacks until it quiesces. We install a special ops vector -+ * with these two callbacks. When the target thread quiesces, it can -+ * safely free the engine itself. For any event we will always get -+ * the report_quiesce() callback first, so we only need this one -+ * pointer to be set. The only exception is report_reap(), so we -+ * supply that callback too. -+ */ -+static u32 utrace_detached_quiesce(u32 action, struct utrace_engine *engine, -+ unsigned long event) -+{ -+ return UTRACE_DETACH; -+} -+ -+static void utrace_detached_reap(struct utrace_engine *engine, -+ struct task_struct *task) -+{ -+} -+ -+static const struct utrace_engine_ops utrace_detached_ops = { -+ .report_quiesce = &utrace_detached_quiesce, -+ .report_reap = &utrace_detached_reap -+}; -+ -+/* -+ * The caller has to hold a ref on the engine. If the attached flag is -+ * true (all but utrace_barrier() calls), the engine is supposed to be -+ * attached. If the attached flag is false (utrace_barrier() only), -+ * then return -ERESTARTSYS for an engine marked for detach but not yet -+ * fully detached. The task pointer can be invalid if the engine is -+ * detached. -+ * -+ * Get the utrace lock for the target task. -+ * Returns the struct if locked, or ERR_PTR(-errno). -+ * -+ * This has to be robust against races with: -+ * utrace_control(target, UTRACE_DETACH) calls -+ * UTRACE_DETACH after reports -+ * utrace_report_death -+ * utrace_release_task -+ */ -+static struct utrace *get_utrace_lock(struct task_struct *target, -+ struct utrace_engine *engine, -+ bool attached) -+ __acquires(utrace->lock) -+{ -+ struct utrace *utrace; -+ -+ rcu_read_lock(); -+ -+ /* -+ * If this engine was already detached, bail out before we look at -+ * the task_struct pointer at all. If it's detached after this -+ * check, then RCU is still keeping this task_struct pointer valid. -+ * -+ * The ops pointer is NULL when the engine is fully detached. -+ * It's &utrace_detached_ops when it's marked detached but still -+ * on the list. In the latter case, utrace_barrier() still works, -+ * since the target might be in the middle of an old callback. -+ */ -+ if (unlikely(!engine->ops)) { -+ rcu_read_unlock(); -+ return ERR_PTR(-ESRCH); -+ } -+ -+ if (unlikely(engine->ops == &utrace_detached_ops)) { -+ rcu_read_unlock(); -+ return attached ? ERR_PTR(-ESRCH) : ERR_PTR(-ERESTARTSYS); -+ } -+ -+ utrace = task_utrace_struct(target); -+ spin_lock(&utrace->lock); -+ if (unlikely(utrace->reap) || unlikely(!engine->ops) || -+ unlikely(engine->ops == &utrace_detached_ops)) { -+ /* -+ * By the time we got the utrace lock, -+ * it had been reaped or detached already. -+ */ -+ spin_unlock(&utrace->lock); -+ utrace = ERR_PTR(-ESRCH); -+ if (!attached && engine->ops == &utrace_detached_ops) -+ utrace = ERR_PTR(-ERESTARTSYS); -+ } -+ rcu_read_unlock(); -+ -+ return utrace; -+} -+ -+/* -+ * Now that we don't hold any locks, run through any -+ * detached engines and free their references. Each -+ * engine had one implicit ref while it was attached. -+ */ -+static void put_detached_list(struct list_head *list) -+{ -+ struct utrace_engine *engine, *next; -+ list_for_each_entry_safe(engine, next, list, entry) { -+ list_del_init(&engine->entry); -+ utrace_engine_put(engine); -+ } -+} -+ -+/* -+ * We use an extra bit in utrace_engine.flags past the event bits, -+ * to record whether the engine is keeping the target thread stopped. -+ * -+ * This bit is set in task_struct.utrace_flags whenever it is set in any -+ * engine's flags. Only utrace_reset() resets it in utrace_flags. -+ */ -+#define ENGINE_STOP (1UL << _UTRACE_NEVENTS) -+ -+#define task_is_utraced(task) ((task->state & __TASK_UTRACED) != 0) -+ -+static void mark_engine_wants_stop(struct task_struct *task, -+ struct utrace_engine *engine) -+{ -+ engine->flags |= ENGINE_STOP; -+ task->utrace_flags |= ENGINE_STOP; -+} -+ -+static void clear_engine_wants_stop(struct utrace_engine *engine) -+{ -+ engine->flags &= ~ENGINE_STOP; -+} -+ -+static bool engine_wants_stop(struct utrace_engine *engine) -+{ -+ return (engine->flags & ENGINE_STOP) != 0; -+} -+ -+/** -+ * utrace_set_events - choose which event reports a tracing engine gets -+ * @target: thread to affect -+ * @engine: attached engine to affect -+ * @events: new event mask -+ * -+ * This changes the set of events for which @engine wants callbacks made. -+ * -+ * This fails with -%EALREADY and does nothing if you try to clear -+ * %UTRACE_EVENT(%DEATH) when the @report_death callback may already have -+ * begun, or if you try to newly set %UTRACE_EVENT(%DEATH) or -+ * %UTRACE_EVENT(%QUIESCE) when @target is already dead or dying. -+ * -+ * This fails with -%ESRCH if you try to clear %UTRACE_EVENT(%REAP) when -+ * the @report_reap callback may already have begun, or when @target has -+ * already been detached, including forcible detach on reaping. -+ * -+ * If @target was stopped before the call, then after a successful call, -+ * no event callbacks not requested in @events will be made; if -+ * %UTRACE_EVENT(%QUIESCE) is included in @events, then a -+ * @report_quiesce callback will be made when @target resumes. -+ * -+ * If @target was not stopped and @events excludes some bits that were -+ * set before, this can return -%EINPROGRESS to indicate that @target -+ * may have been making some callback to @engine. When this returns -+ * zero, you can be sure that no event callbacks you've disabled in -+ * @events can be made. If @events only sets new bits that were not set -+ * before on @engine, then -%EINPROGRESS will never be returned. -+ * -+ * To synchronize after an -%EINPROGRESS return, see utrace_barrier(). -+ * -+ * When @target is @current, -%EINPROGRESS is not returned. But note -+ * that a newly-created engine will not receive any callbacks related to -+ * an event notification already in progress. This call enables @events -+ * callbacks to be made as soon as @engine becomes eligible for any -+ * callbacks, see utrace_attach_task(). -+ * -+ * These rules provide for coherent synchronization based on %UTRACE_STOP, -+ * even when %SIGKILL is breaking its normal simple rules. -+ */ -+int utrace_set_events(struct task_struct *target, -+ struct utrace_engine *engine, -+ unsigned long events) -+{ -+ struct utrace *utrace; -+ unsigned long old_flags, old_utrace_flags; -+ int ret = -EALREADY; -+ -+ /* -+ * We just ignore the internal bit, so callers can use -+ * engine->flags to seed bitwise ops for our argument. -+ */ -+ events &= ~ENGINE_STOP; -+ -+ utrace = get_utrace_lock(target, engine, true); -+ if (unlikely(IS_ERR(utrace))) -+ return PTR_ERR(utrace); -+ -+ old_utrace_flags = target->utrace_flags; -+ old_flags = engine->flags & ~ENGINE_STOP; -+ -+ /* -+ * If utrace_report_death() is already progress now, -+ * it's too late to clear the death event bits. -+ */ -+ if (((old_flags & ~events) & _UTRACE_DEATH_EVENTS) && utrace->death) -+ goto unlock; -+ -+ /* -+ * When setting these flags, it's essential that we really -+ * synchronize with exit_notify(). They cannot be set after -+ * exit_notify() takes the tasklist_lock. By holding the read -+ * lock here while setting the flags, we ensure that the calls -+ * to tracehook_notify_death() and tracehook_report_death() will -+ * see the new flags. This ensures that utrace_release_task() -+ * knows positively that utrace_report_death() will be called or -+ * that it won't. -+ */ -+ if ((events & ~old_flags) & _UTRACE_DEATH_EVENTS) { -+ read_lock(&tasklist_lock); -+ if (unlikely(target->exit_state)) { -+ read_unlock(&tasklist_lock); -+ goto unlock; -+ } -+ target->utrace_flags |= events; -+ read_unlock(&tasklist_lock); -+ } -+ -+ engine->flags = events | (engine->flags & ENGINE_STOP); -+ target->utrace_flags |= events; -+ -+ if ((events & UTRACE_EVENT_SYSCALL) && -+ !(old_utrace_flags & UTRACE_EVENT_SYSCALL)) -+ set_tsk_thread_flag(target, TIF_SYSCALL_TRACE); -+ -+ ret = 0; -+ if ((old_flags & ~events) && target != current && -+ !task_is_utraced(target) && !target->exit_state) { -+ /* -+ * This barrier ensures that our engine->flags changes -+ * have hit before we examine utrace->reporting, -+ * pairing with the barrier in start_callback(). If -+ * @target has not yet hit finish_callback() to clear -+ * utrace->reporting, we might be in the middle of a -+ * callback to @engine. -+ */ -+ smp_mb(); -+ if (utrace->reporting == engine) -+ ret = -EINPROGRESS; -+ } -+unlock: -+ spin_unlock(&utrace->lock); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(utrace_set_events); -+ -+/* -+ * Asynchronously mark an engine as being detached. -+ * -+ * This must work while the target thread races with us doing -+ * start_callback(), defined below. It uses smp_rmb() between checking -+ * @engine->flags and using @engine->ops. Here we change @engine->ops -+ * first, then use smp_wmb() before changing @engine->flags. This ensures -+ * it can check the old flags before using the old ops, or check the old -+ * flags before using the new ops, or check the new flags before using the -+ * new ops, but can never check the new flags before using the old ops. -+ * Hence, utrace_detached_ops might be used with any old flags in place. -+ * It has report_quiesce() and report_reap() callbacks to handle all cases. -+ */ -+static void mark_engine_detached(struct utrace_engine *engine) -+{ -+ engine->ops = &utrace_detached_ops; -+ smp_wmb(); -+ engine->flags = UTRACE_EVENT(QUIESCE); -+} -+ -+/* -+ * Get @target to stop and return true if it is already stopped now. -+ * If we return false, it will make some event callback soonish. -+ * Called with @utrace locked. -+ */ -+static bool utrace_do_stop(struct task_struct *target, struct utrace *utrace) -+{ -+ if (task_is_stopped_or_traced(target)) { -+ /* -+ * Stopped is considered quiescent; when it wakes up, it will -+ * go through utrace_finish_stop() before doing anything else. -+ */ -+ spin_lock_irq(&target->sighand->siglock); -+ if (likely(task_is_stopped_or_traced(target))) -+ target->state |= TASK_UTRACED; -+ spin_unlock_irq(&target->sighand->siglock); -+ } else if (utrace->resume > UTRACE_REPORT) { -+ utrace->resume = UTRACE_REPORT; -+ set_notify_resume(target); -+ } -+ -+ return task_is_utraced(target); -+} -+ -+/* -+ * If the target is not dead it should not be in tracing -+ * stop any more. Wake it unless it's in job control stop. -+ */ -+static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) -+{ -+ lockdep_assert_held(&utrace->lock); -+ spin_lock_irq(&target->sighand->siglock); -+ wake_up_quiescent(target, __TASK_UTRACED); -+ spin_unlock_irq(&target->sighand->siglock); -+} -+ -+/* -+ * This is called when there might be some detached engines on the list or -+ * some stale bits in @task->utrace_flags. Clean them up and recompute the -+ * flags. Returns true if we're now fully detached. -+ * -+ * Called with @utrace->lock held, returns with it released. -+ * After this returns, @utrace might be freed if everything detached. -+ */ -+static bool utrace_reset(struct task_struct *task, struct utrace *utrace) -+ __releases(utrace->lock) -+{ -+ struct utrace_engine *engine, *next; -+ unsigned long flags = 0; -+ LIST_HEAD(detached); -+ -+ splice_attaching(utrace); -+ -+ /* -+ * Update the set of events of interest from the union -+ * of the interests of the remaining tracing engines. -+ * For any engine marked detached, remove it from the list. -+ * We'll collect them on the detached list. -+ */ -+ list_for_each_entry_safe(engine, next, &utrace->attached, entry) { -+ if (engine->ops == &utrace_detached_ops) { -+ engine->ops = NULL; -+ list_move(&engine->entry, &detached); -+ } else { -+ flags |= engine->flags | UTRACE_EVENT(REAP); -+ } -+ } -+ -+ if (task->exit_state) { -+ /* -+ * Once it's already dead, we never install any flags -+ * except REAP. When ->exit_state is set and events -+ * like DEATH are not set, then they never can be set. -+ * This ensures that utrace_release_task() knows -+ * positively that utrace_report_death() can never run. -+ */ -+ BUG_ON(utrace->death); -+ flags &= UTRACE_EVENT(REAP); -+ } else if (!(flags & UTRACE_EVENT_SYSCALL) && -+ !(task->ptrace & PT_SYSCALL_TRACE) && -+ test_tsk_thread_flag(task, TIF_SYSCALL_TRACE)) { -+ clear_tsk_thread_flag(task, TIF_SYSCALL_TRACE); -+ } -+ -+ if (!flags) { -+ /* -+ * No more engines, cleared out the utrace. -+ */ -+ utrace->resume = UTRACE_RESUME; -+ utrace->signal_handler = 0; -+ } -+ -+ /* -+ * If no more engines want it stopped, wake it up. -+ */ -+ if (task_is_utraced(task) && !(flags & ENGINE_STOP)) { -+ /* -+ * It just resumes, so make sure single-step -+ * is not left set. -+ */ -+ if (utrace->resume == UTRACE_RESUME) -+ user_disable_single_step(task); -+ utrace_wakeup(task, utrace); -+ } -+ -+ /* -+ * In theory spin_lock() doesn't imply rcu_read_lock(). -+ * Once we clear ->utrace_flags this task_struct can go away -+ * because tracehook_prepare_release_task() path does not take -+ * utrace->lock when ->utrace_flags == 0. -+ */ -+ rcu_read_lock(); -+ task->utrace_flags = flags; -+ spin_unlock(&utrace->lock); -+ rcu_read_unlock(); -+ -+ put_detached_list(&detached); -+ -+ return !flags; -+} -+ -+void utrace_finish_stop(void) -+{ -+ /* -+ * If we were task_is_utraced() and then SIGKILL'ed, make -+ * sure we do nothing until the tracer drops utrace->lock. -+ */ -+ if (unlikely(__fatal_signal_pending(current))) { -+ struct utrace *utrace = task_utrace_struct(current); -+ spin_unlock_wait(&utrace->lock); -+ } -+} -+ -+/* -+ * Perform %UTRACE_STOP, i.e. block in TASK_UTRACED until woken up. -+ * @task == current, @utrace == current->utrace, which is not locked. -+ * Return true if we were woken up by SIGKILL even though some utrace -+ * engine may still want us to stay stopped. -+ */ -+static void utrace_stop(struct task_struct *task, struct utrace *utrace, -+ enum utrace_resume_action action) -+{ -+relock: -+ spin_lock(&utrace->lock); -+ -+ if (action < utrace->resume) { -+ /* -+ * Ensure a reporting pass when we're resumed. -+ */ -+ utrace->resume = action; -+ if (action == UTRACE_INTERRUPT) -+ set_thread_flag(TIF_SIGPENDING); -+ else -+ set_thread_flag(TIF_NOTIFY_RESUME); -+ } -+ -+ /* -+ * If the ENGINE_STOP bit is clear in utrace_flags, that means -+ * utrace_reset() ran after we processed some UTRACE_STOP return -+ * values from callbacks to get here. If all engines have detached -+ * or resumed us, we don't stop. This check doesn't require -+ * siglock, but it should follow the interrupt/report bookkeeping -+ * steps (this can matter for UTRACE_RESUME but not UTRACE_DETACH). -+ */ -+ if (unlikely(!(task->utrace_flags & ENGINE_STOP))) { -+ utrace_reset(task, utrace); -+ if (task->utrace_flags & ENGINE_STOP) -+ goto relock; -+ return; -+ } -+ -+ /* -+ * The siglock protects us against signals. As well as SIGKILL -+ * waking us up, we must synchronize with the signal bookkeeping -+ * for stop signals and SIGCONT. -+ */ -+ spin_lock_irq(&task->sighand->siglock); -+ -+ if (unlikely(__fatal_signal_pending(task))) { -+ spin_unlock_irq(&task->sighand->siglock); -+ spin_unlock(&utrace->lock); -+ return; -+ } -+ -+ __set_current_state(TASK_UTRACED); -+ -+ spin_unlock_irq(&task->sighand->siglock); -+ spin_unlock(&utrace->lock); -+ -+ schedule(); -+ -+ utrace_finish_stop(); -+ -+ /* -+ * While in TASK_UTRACED, we were considered "frozen enough". -+ * Now that we woke up, it's crucial if we're supposed to be -+ * frozen that we freeze now before running anything substantial. -+ */ -+ try_to_freeze(); -+ -+ /* -+ * While we were in TASK_UTRACED, complete_signal() considered -+ * us "uninterested" in signal wakeups. Now make sure our -+ * TIF_SIGPENDING state is correct for normal running. -+ */ -+ spin_lock_irq(&task->sighand->siglock); -+ recalc_sigpending(); -+ spin_unlock_irq(&task->sighand->siglock); -+} -+ -+/* -+ * Called by release_task() with @reap set to true. -+ * Called by utrace_report_death() with @reap set to false. -+ * On reap, make report_reap callbacks and clean out @utrace -+ * unless still making callbacks. On death, update bookkeeping -+ * and handle the reap work if release_task() came in first. -+ */ -+void utrace_maybe_reap(struct task_struct *target, struct utrace *utrace, -+ bool reap) -+{ -+ struct utrace_engine *engine, *next; -+ struct list_head attached; -+ -+ spin_lock(&utrace->lock); -+ -+ if (reap) { -+ /* -+ * If the target will do some final callbacks but hasn't -+ * finished them yet, we know because it clears these event -+ * bits after it's done. Instead of cleaning up here and -+ * requiring utrace_report_death() to cope with it, we -+ * delay the REAP report and the teardown until after the -+ * target finishes its death reports. -+ */ -+ utrace->reap = 1; -+ -+ if (target->utrace_flags & _UTRACE_DEATH_EVENTS) { -+ spin_unlock(&utrace->lock); -+ return; -+ } -+ } else { -+ /* -+ * After we unlock with this flag clear, any competing -+ * utrace_control/utrace_set_events calls know that we've -+ * finished our callbacks and any detach bookkeeping. -+ */ -+ utrace->death = 0; -+ -+ if (!utrace->reap) { -+ /* -+ * We're just dead, not reaped yet. This will -+ * reset @target->utrace_flags so the later call -+ * with @reap set won't hit the check above. -+ */ -+ utrace_reset(target, utrace); -+ return; -+ } -+ } -+ -+ /* -+ * utrace_add_engine() checks ->utrace_flags != 0. Since -+ * @utrace->reap is set, nobody can set or clear UTRACE_EVENT(REAP) -+ * in @engine->flags or change @engine->ops and nobody can change -+ * @utrace->attached after we drop the lock. -+ */ -+ target->utrace_flags = 0; -+ -+ /* -+ * We clear out @utrace->attached before we drop the lock so -+ * that find_matching_engine() can't come across any old engine -+ * while we are busy tearing it down. -+ */ -+ list_replace_init(&utrace->attached, &attached); -+ list_splice_tail_init(&utrace->attaching, &attached); -+ -+ spin_unlock(&utrace->lock); -+ -+ list_for_each_entry_safe(engine, next, &attached, entry) { -+ if (engine->flags & UTRACE_EVENT(REAP)) -+ engine->ops->report_reap(engine, target); -+ -+ engine->ops = NULL; -+ engine->flags = 0; -+ list_del_init(&engine->entry); -+ -+ utrace_engine_put(engine); -+ } -+} -+ -+/* -+ * You can't do anything to a dead task but detach it. -+ * If release_task() has been called, you can't do that. -+ * -+ * On the exit path, DEATH and QUIESCE event bits are set only -+ * before utrace_report_death() has taken the lock. At that point, -+ * the death report will come soon, so disallow detach until it's -+ * done. This prevents us from racing with it detaching itself. -+ * -+ * Called only when @target->exit_state is nonzero. -+ */ -+static inline int utrace_control_dead(struct task_struct *target, -+ struct utrace *utrace, -+ enum utrace_resume_action action) -+{ -+ lockdep_assert_held(&utrace->lock); -+ -+ if (action != UTRACE_DETACH || unlikely(utrace->reap)) -+ return -ESRCH; -+ -+ if (unlikely(utrace->death)) -+ /* -+ * We have already started the death report. We can't -+ * prevent the report_death and report_reap callbacks, -+ * so tell the caller they will happen. -+ */ -+ return -EALREADY; -+ -+ return 0; -+} -+ -+/** -+ * utrace_control - control a thread being traced by a tracing engine -+ * @target: thread to affect -+ * @engine: attached engine to affect -+ * @action: &enum utrace_resume_action for thread to do -+ * -+ * This is how a tracing engine asks a traced thread to do something. -+ * This call is controlled by the @action argument, which has the -+ * same meaning as the &enum utrace_resume_action value returned by -+ * event reporting callbacks. -+ * -+ * If @target is already dead (@target->exit_state nonzero), -+ * all actions except %UTRACE_DETACH fail with -%ESRCH. -+ * -+ * The following sections describe each option for the @action argument. -+ * -+ * UTRACE_DETACH: -+ * -+ * After this, the @engine data structure is no longer accessible, -+ * and the thread might be reaped. The thread will start running -+ * again if it was stopped and no longer has any attached engines -+ * that want it stopped. -+ * -+ * If the @report_reap callback may already have begun, this fails -+ * with -%ESRCH. If the @report_death callback may already have -+ * begun, this fails with -%EALREADY. -+ * -+ * If @target is not already stopped, then a callback to this engine -+ * might be in progress or about to start on another CPU. If so, -+ * then this returns -%EINPROGRESS; the detach happens as soon as -+ * the pending callback is finished. To synchronize after an -+ * -%EINPROGRESS return, see utrace_barrier(). -+ * -+ * If @target is properly stopped before utrace_control() is called, -+ * then after successful return it's guaranteed that no more callbacks -+ * to the @engine->ops vector will be made. -+ * -+ * The only exception is %SIGKILL (and exec or group-exit by another -+ * thread in the group), which can cause asynchronous @report_death -+ * and/or @report_reap callbacks even when %UTRACE_STOP was used. -+ * (In that event, this fails with -%ESRCH or -%EALREADY, see above.) -+ * -+ * UTRACE_STOP: -+ * -+ * This asks that @target stop running. This returns 0 only if -+ * @target is already stopped, either for tracing or for job -+ * control. Then @target will remain stopped until another -+ * utrace_control() call is made on @engine; @target can be woken -+ * only by %SIGKILL (or equivalent, such as exec or termination by -+ * another thread in the same thread group). -+ * -+ * This returns -%EINPROGRESS if @target is not already stopped. -+ * Then the effect is like %UTRACE_REPORT. A @report_quiesce or -+ * @report_signal callback will be made soon. Your callback can -+ * then return %UTRACE_STOP to keep @target stopped. -+ * -+ * This does not interrupt system calls in progress, including ones -+ * that sleep for a long time. For that, use %UTRACE_INTERRUPT. -+ * To interrupt system calls and then keep @target stopped, your -+ * @report_signal callback can return %UTRACE_STOP. -+ * -+ * UTRACE_RESUME: -+ * -+ * Just let @target continue running normally, reversing the effect -+ * of a previous %UTRACE_STOP. If another engine is keeping @target -+ * stopped, then it remains stopped until all engines let it resume. -+ * If @target was not stopped, this has no effect. -+ * -+ * UTRACE_REPORT: -+ * -+ * This is like %UTRACE_RESUME, but also ensures that there will be -+ * a @report_quiesce or @report_signal callback made soon. If -+ * @target had been stopped, then there will be a callback before it -+ * resumes running normally. If another engine is keeping @target -+ * stopped, then there might be no callbacks until all engines let -+ * it resume. -+ * -+ * Since this is meaningless unless @report_quiesce callbacks will -+ * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). -+ * -+ * UTRACE_INTERRUPT: -+ * -+ * This is like %UTRACE_REPORT, but ensures that @target will make a -+ * @report_signal callback before it resumes or delivers signals. -+ * If @target was in a system call or about to enter one, work in -+ * progress will be interrupted as if by %SIGSTOP. If another -+ * engine is keeping @target stopped, then there might be no -+ * callbacks until all engines let it resume. -+ * -+ * This gives @engine an opportunity to introduce a forced signal -+ * disposition via its @report_signal callback. -+ * -+ * UTRACE_SINGLESTEP: -+ * -+ * It's invalid to use this unless arch_has_single_step() returned true. -+ * This is like %UTRACE_RESUME, but resumes for one user instruction only. -+ * -+ * Note that passing %UTRACE_SINGLESTEP or %UTRACE_BLOCKSTEP to -+ * utrace_control() or returning it from an event callback alone does -+ * not necessarily ensure that stepping will be enabled. If there are -+ * more callbacks made to any engine before returning to user mode, -+ * then the resume action is chosen only by the last set of callbacks. -+ * To be sure, enable %UTRACE_EVENT(%QUIESCE) and look for the -+ * @report_quiesce callback with a zero event mask, or the -+ * @report_signal callback with %UTRACE_SIGNAL_REPORT. -+ * -+ * Since this is not robust unless @report_quiesce callbacks will -+ * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). -+ * -+ * UTRACE_BLOCKSTEP: -+ * -+ * It's invalid to use this unless arch_has_block_step() returned true. -+ * This is like %UTRACE_SINGLESTEP, but resumes for one whole basic -+ * block of user instructions. -+ * -+ * Since this is not robust unless @report_quiesce callbacks will -+ * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). -+ * -+ * %UTRACE_BLOCKSTEP devolves to %UTRACE_SINGLESTEP when another -+ * tracing engine is using %UTRACE_SINGLESTEP at the same time. -+ */ -+int utrace_control(struct task_struct *target, -+ struct utrace_engine *engine, -+ enum utrace_resume_action action) -+{ -+ struct utrace *utrace; -+ bool reset; -+ int ret; -+ -+ if (unlikely(action >= UTRACE_RESUME_MAX)) { -+ WARN(1, "invalid action argument to utrace_control()!"); -+ return -EINVAL; -+ } -+ -+ /* -+ * This is a sanity check for a programming error in the caller. -+ * Their request can only work properly in all cases by relying on -+ * a follow-up callback, but they didn't set one up! This check -+ * doesn't do locking, but it shouldn't matter. The caller has to -+ * be synchronously sure the callback is set up to be operating the -+ * interface properly. -+ */ -+ if (action >= UTRACE_REPORT && action < UTRACE_RESUME && -+ unlikely(!(engine->flags & UTRACE_EVENT(QUIESCE)))) { -+ WARN(1, "utrace_control() with no QUIESCE callback in place!"); -+ return -EINVAL; -+ } -+ -+ utrace = get_utrace_lock(target, engine, true); -+ if (unlikely(IS_ERR(utrace))) -+ return PTR_ERR(utrace); -+ -+ reset = task_is_utraced(target); -+ ret = 0; -+ -+ /* -+ * ->exit_state can change under us, this doesn't matter. -+ * We do not care about ->exit_state in fact, but we do -+ * care about ->reap and ->death. If either flag is set, -+ * we must also see ->exit_state != 0. -+ */ -+ if (unlikely(target->exit_state)) { -+ ret = utrace_control_dead(target, utrace, action); -+ if (ret) { -+ spin_unlock(&utrace->lock); -+ return ret; -+ } -+ reset = true; -+ } -+ -+ switch (action) { -+ case UTRACE_STOP: -+ mark_engine_wants_stop(target, engine); -+ if (!reset && !utrace_do_stop(target, utrace)) -+ ret = -EINPROGRESS; -+ reset = false; -+ break; -+ -+ case UTRACE_DETACH: -+ if (engine_wants_stop(engine)) -+ target->utrace_flags &= ~ENGINE_STOP; -+ mark_engine_detached(engine); -+ reset = reset || utrace_do_stop(target, utrace); -+ if (!reset) { -+ /* -+ * As in utrace_set_events(), this barrier ensures -+ * that our engine->flags changes have hit before we -+ * examine utrace->reporting, pairing with the barrier -+ * in start_callback(). If @target has not yet hit -+ * finish_callback() to clear utrace->reporting, we -+ * might be in the middle of a callback to @engine. -+ */ -+ smp_mb(); -+ if (utrace->reporting == engine) -+ ret = -EINPROGRESS; -+ } -+ break; -+ -+ case UTRACE_RESUME: -+ clear_engine_wants_stop(engine); -+ break; -+ -+ case UTRACE_BLOCKSTEP: -+ /* -+ * Resume from stopped, step one block. -+ * We fall through to treat it like UTRACE_SINGLESTEP. -+ */ -+ if (unlikely(!arch_has_block_step())) { -+ WARN(1, "UTRACE_BLOCKSTEP when !arch_has_block_step()"); -+ action = UTRACE_SINGLESTEP; -+ } -+ -+ case UTRACE_SINGLESTEP: -+ /* -+ * Resume from stopped, step one instruction. -+ * We fall through to the UTRACE_REPORT case. -+ */ -+ if (unlikely(!arch_has_single_step())) { -+ WARN(1, -+ "UTRACE_SINGLESTEP when !arch_has_single_step()"); -+ reset = false; -+ ret = -EOPNOTSUPP; -+ break; -+ } -+ -+ case UTRACE_REPORT: -+ /* -+ * Make the thread call tracehook_notify_resume() soon. -+ * But don't bother if it's already been interrupted. -+ * In that case, utrace_get_signal() will be reporting soon. -+ */ -+ clear_engine_wants_stop(engine); -+ if (action < utrace->resume) { -+ utrace->resume = action; -+ set_notify_resume(target); -+ } -+ break; -+ -+ case UTRACE_INTERRUPT: -+ /* -+ * Make the thread call tracehook_get_signal() soon. -+ */ -+ clear_engine_wants_stop(engine); -+ if (utrace->resume == UTRACE_INTERRUPT) -+ break; -+ utrace->resume = UTRACE_INTERRUPT; -+ -+ /* -+ * If it's not already stopped, interrupt it now. We need -+ * the siglock here in case it calls recalc_sigpending() -+ * and clears its own TIF_SIGPENDING. By taking the lock, -+ * we've serialized any later recalc_sigpending() after our -+ * setting of utrace->resume to force it on. -+ */ -+ if (reset) { -+ /* -+ * This is really just to keep the invariant that -+ * TIF_SIGPENDING is set with UTRACE_INTERRUPT. -+ * When it's stopped, we know it's always going -+ * through utrace_get_signal() and will recalculate. -+ */ -+ set_tsk_thread_flag(target, TIF_SIGPENDING); -+ } else { -+ struct sighand_struct *sighand; -+ unsigned long irqflags; -+ sighand = lock_task_sighand(target, &irqflags); -+ if (likely(sighand)) { -+ signal_wake_up(target, 0); -+ unlock_task_sighand(target, &irqflags); -+ } -+ } -+ break; -+ -+ default: -+ BUG(); /* We checked it on entry. */ -+ } -+ -+ /* -+ * Let the thread resume running. If it's not stopped now, -+ * there is nothing more we need to do. -+ */ -+ if (reset) -+ utrace_reset(target, utrace); -+ else -+ spin_unlock(&utrace->lock); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(utrace_control); -+ -+/** -+ * utrace_barrier - synchronize with simultaneous tracing callbacks -+ * @target: thread to affect -+ * @engine: engine to affect (can be detached) -+ * -+ * This blocks while @target might be in the midst of making a callback to -+ * @engine. It can be interrupted by signals and will return -%ERESTARTSYS. -+ * A return value of zero means no callback from @target to @engine was -+ * in progress. Any effect of its return value (such as %UTRACE_STOP) has -+ * already been applied to @engine. -+ * -+ * It's not necessary to keep the @target pointer alive for this call. -+ * It's only necessary to hold a ref on @engine. This will return -+ * safely even if @target has been reaped and has no task refs. -+ * -+ * A successful return from utrace_barrier() guarantees its ordering -+ * with respect to utrace_set_events() and utrace_control() calls. If -+ * @target was not properly stopped, event callbacks just disabled might -+ * still be in progress; utrace_barrier() waits until there is no chance -+ * an unwanted callback can be in progress. -+ */ -+int utrace_barrier(struct task_struct *target, struct utrace_engine *engine) -+{ -+ struct utrace *utrace; -+ int ret = -ERESTARTSYS; -+ -+ if (unlikely(target == current)) -+ return 0; -+ -+ do { -+ utrace = get_utrace_lock(target, engine, false); -+ if (unlikely(IS_ERR(utrace))) { -+ ret = PTR_ERR(utrace); -+ if (ret != -ERESTARTSYS) -+ break; -+ } else { -+ /* -+ * All engine state changes are done while -+ * holding the lock, i.e. before we get here. -+ * Since we have the lock, we only need to -+ * worry about @target making a callback. -+ * When it has entered start_callback() but -+ * not yet gotten to finish_callback(), we -+ * will see utrace->reporting == @engine. -+ * When @target doesn't take the lock, it uses -+ * barriers to order setting utrace->reporting -+ * before it examines the engine state. -+ */ -+ if (utrace->reporting != engine) -+ ret = 0; -+ spin_unlock(&utrace->lock); -+ if (!ret) -+ break; -+ } -+ schedule_timeout_interruptible(1); -+ } while (!signal_pending(current)); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(utrace_barrier); -+ -+/* -+ * This is local state used for reporting loops, perhaps optimized away. -+ */ -+struct utrace_report { -+ u32 result; -+ enum utrace_resume_action action; -+ enum utrace_resume_action resume_action; -+ bool detaches; -+ bool spurious; -+}; -+ -+#define INIT_REPORT(var) \ -+ struct utrace_report var = { \ -+ .action = UTRACE_RESUME, \ -+ .resume_action = UTRACE_RESUME, \ -+ .spurious = true \ -+ } -+ -+/* -+ * We are now making the report, so clear the flag saying we need one. -+ * When there is a new attach, ->pending_attach is set just so we will -+ * know to do splice_attaching() here before the callback loop. -+ */ -+static enum utrace_resume_action start_report(struct utrace *utrace) -+{ -+ enum utrace_resume_action resume = utrace->resume; -+ if (utrace->pending_attach || -+ (resume > UTRACE_INTERRUPT && resume < UTRACE_RESUME)) { -+ spin_lock(&utrace->lock); -+ splice_attaching(utrace); -+ resume = utrace->resume; -+ if (resume > UTRACE_INTERRUPT) -+ utrace->resume = UTRACE_RESUME; -+ spin_unlock(&utrace->lock); -+ } -+ return resume; -+} -+ -+static inline void finish_report_reset(struct task_struct *task, -+ struct utrace *utrace, -+ struct utrace_report *report) -+{ -+ if (unlikely(report->spurious || report->detaches)) { -+ spin_lock(&utrace->lock); -+ if (utrace_reset(task, utrace)) -+ report->action = UTRACE_RESUME; -+ } -+} -+ -+/* -+ * Complete a normal reporting pass, pairing with a start_report() call. -+ * This handles any UTRACE_DETACH or UTRACE_REPORT or UTRACE_INTERRUPT -+ * returns from engine callbacks. If @will_not_stop is true and any -+ * engine's last callback used UTRACE_STOP, we do UTRACE_REPORT here to -+ * ensure we stop before user mode. If there were no callbacks made, it -+ * will recompute @task->utrace_flags to avoid another false-positive. -+ */ -+static void finish_report(struct task_struct *task, struct utrace *utrace, -+ struct utrace_report *report, bool will_not_stop) -+{ -+ enum utrace_resume_action resume = report->action; -+ -+ if (resume == UTRACE_STOP) -+ resume = will_not_stop ? UTRACE_REPORT : UTRACE_RESUME; -+ -+ if (resume < utrace->resume) { -+ spin_lock(&utrace->lock); -+ utrace->resume = resume; -+ if (resume == UTRACE_INTERRUPT) -+ set_tsk_thread_flag(task, TIF_SIGPENDING); -+ else -+ set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); -+ spin_unlock(&utrace->lock); -+ } -+ -+ finish_report_reset(task, utrace, report); -+} -+ -+static void finish_callback_report(struct task_struct *task, -+ struct utrace *utrace, -+ struct utrace_report *report, -+ struct utrace_engine *engine, -+ enum utrace_resume_action action) -+{ -+ if (action == UTRACE_DETACH) { -+ /* -+ * By holding the lock here, we make sure that -+ * utrace_barrier() (really get_utrace_lock()) sees the -+ * effect of this detach. Otherwise utrace_barrier() could -+ * return 0 after this callback had returned UTRACE_DETACH. -+ * This way, a 0 return is an unambiguous indicator that any -+ * callback returning UTRACE_DETACH has indeed caused detach. -+ */ -+ spin_lock(&utrace->lock); -+ engine->ops = &utrace_detached_ops; -+ spin_unlock(&utrace->lock); -+ } -+ -+ /* -+ * If utrace_control() was used, treat that like UTRACE_DETACH here. -+ */ -+ if (engine->ops == &utrace_detached_ops) { -+ report->detaches = true; -+ return; -+ } -+ -+ if (action < report->action) -+ report->action = action; -+ -+ if (action != UTRACE_STOP) { -+ if (action < report->resume_action) -+ report->resume_action = action; -+ -+ if (engine_wants_stop(engine)) { -+ spin_lock(&utrace->lock); -+ clear_engine_wants_stop(engine); -+ spin_unlock(&utrace->lock); -+ } -+ -+ return; -+ } -+ -+ if (!engine_wants_stop(engine)) { -+ spin_lock(&utrace->lock); -+ /* -+ * If utrace_control() came in and detached us -+ * before we got the lock, we must not stop now. -+ */ -+ if (unlikely(engine->ops == &utrace_detached_ops)) -+ report->detaches = true; -+ else -+ mark_engine_wants_stop(task, engine); -+ spin_unlock(&utrace->lock); -+ } -+} -+ -+/* -+ * Apply the return value of one engine callback to @report. -+ * Returns true if @engine detached and should not get any more callbacks. -+ */ -+static bool finish_callback(struct task_struct *task, struct utrace *utrace, -+ struct utrace_report *report, -+ struct utrace_engine *engine, -+ u32 ret) -+{ -+ report->result = ret & ~UTRACE_RESUME_MASK; -+ finish_callback_report(task, utrace, report, engine, -+ utrace_resume_action(ret)); -+ -+ /* -+ * Now that we have applied the effect of the return value, -+ * clear this so that utrace_barrier() can stop waiting. -+ * A subsequent utrace_control() can stop or resume @engine -+ * and know this was ordered after its callback's action. -+ * -+ * We don't need any barriers here because utrace_barrier() -+ * takes utrace->lock. If we touched engine->flags above, -+ * the lock guaranteed this change was before utrace_barrier() -+ * examined utrace->reporting. -+ */ -+ utrace->reporting = NULL; -+ -+ /* -+ * We've just done an engine callback. These are allowed to sleep, -+ * though all well-behaved ones restrict that to blocking kalloc() -+ * or quickly-acquired mutex_lock() and the like. This is a good -+ * place to make sure tracing engines don't introduce too much -+ * latency under voluntary preemption. -+ */ -+ might_sleep(); -+ -+ return engine->ops == &utrace_detached_ops; -+} -+ -+/* -+ * Start the callbacks for @engine to consider @event (a bit mask). -+ * This makes the report_quiesce() callback first. If @engine wants -+ * a specific callback for @event, we return the ops vector to use. -+ * If not, we return NULL. The return value from the ops->callback -+ * function called should be passed to finish_callback(). -+ */ -+static const struct utrace_engine_ops *start_callback( -+ struct utrace *utrace, struct utrace_report *report, -+ struct utrace_engine *engine, struct task_struct *task, -+ unsigned long event) -+{ -+ const struct utrace_engine_ops *ops; -+ unsigned long want; -+ -+ /* -+ * This barrier ensures that we've set utrace->reporting before -+ * we examine engine->flags or engine->ops. utrace_barrier() -+ * relies on this ordering to indicate that the effect of any -+ * utrace_control() and utrace_set_events() calls is in place -+ * by the time utrace->reporting can be seen to be NULL. -+ */ -+ utrace->reporting = engine; -+ smp_mb(); -+ -+ /* -+ * This pairs with the barrier in mark_engine_detached(). -+ * It makes sure that we never see the old ops vector with -+ * the new flags, in case the original vector had no report_quiesce. -+ */ -+ want = engine->flags; -+ smp_rmb(); -+ ops = engine->ops; -+ -+ if ((want & UTRACE_EVENT(QUIESCE)) || ops == &utrace_detached_ops) { -+ if (finish_callback(task, utrace, report, engine, -+ (*ops->report_quiesce)(report->action, -+ engine, event))) -+ return NULL; -+ -+ if (!event) { -+ /* We only got here to report QUIESCE */ -+ report->spurious = false; -+ return NULL; -+ } -+ -+ /* -+ * finish_callback() reset utrace->reporting after the -+ * quiesce callback. Now we set it again (as above) -+ * before re-examining engine->flags, which could have -+ * been changed synchronously by ->report_quiesce or -+ * asynchronously by utrace_control() or utrace_set_events(). -+ */ -+ utrace->reporting = engine; -+ smp_mb(); -+ want = engine->flags; -+ } -+ -+ if (want & ENGINE_STOP) -+ report->action = UTRACE_STOP; -+ -+ if (want & event) { -+ report->spurious = false; -+ return ops; -+ } -+ -+ utrace->reporting = NULL; -+ return NULL; -+} -+ -+/* -+ * Do a normal reporting pass for engines interested in @event. -+ * @callback is the name of the member in the ops vector, and remaining -+ * args are the extras it takes after the standard three args. -+ */ -+#define REPORT_CALLBACKS(rev, task, utrace, report, event, callback, ...) \ -+ do { \ -+ struct utrace_engine *engine; \ -+ const struct utrace_engine_ops *ops; \ -+ list_for_each_entry##rev(engine, &utrace->attached, entry) { \ -+ ops = start_callback(utrace, report, engine, task, \ -+ event); \ -+ if (!ops) \ -+ continue; \ -+ finish_callback(task, utrace, report, engine, \ -+ (*ops->callback)(__VA_ARGS__)); \ -+ } \ -+ } while (0) -+#define REPORT(task, utrace, report, event, callback, ...) \ -+ do { \ -+ start_report(utrace); \ -+ REPORT_CALLBACKS(, task, utrace, report, event, callback, \ -+ (report)->action, engine, ## __VA_ARGS__); \ -+ finish_report(task, utrace, report, true); \ -+ } while (0) -+ -+/* -+ * Called iff UTRACE_EVENT(EXEC) flag is set. -+ */ -+void utrace_report_exec(struct linux_binfmt *fmt, struct linux_binprm *bprm, -+ struct pt_regs *regs) -+{ -+ struct task_struct *task = current; -+ struct utrace *utrace = task_utrace_struct(task); -+ INIT_REPORT(report); -+ -+ REPORT(task, utrace, &report, UTRACE_EVENT(EXEC), -+ report_exec, fmt, bprm, regs); -+} -+ -+static u32 do_report_syscall_entry(struct pt_regs *regs, -+ struct task_struct *task, -+ struct utrace *utrace, -+ struct utrace_report *report, -+ u32 resume_report) -+{ -+ start_report(utrace); -+ REPORT_CALLBACKS(_reverse, task, utrace, report, -+ UTRACE_EVENT(SYSCALL_ENTRY), report_syscall_entry, -+ resume_report | report->result | report->action, -+ engine, regs); -+ finish_report(task, utrace, report, false); -+ -+ if (report->action != UTRACE_STOP) -+ return 0; -+ -+ utrace_stop(task, utrace, report->resume_action); -+ -+ if (fatal_signal_pending(task)) { -+ /* -+ * We are continuing despite UTRACE_STOP because of a -+ * SIGKILL. Don't let the system call actually proceed. -+ */ -+ report->result = UTRACE_SYSCALL_ABORT; -+ } else if (utrace->resume <= UTRACE_REPORT) { -+ /* -+ * If we've been asked for another report after our stop, -+ * go back to report (and maybe stop) again before we run -+ * the system call. The second (and later) reports are -+ * marked with the UTRACE_SYSCALL_RESUMED flag so that -+ * engines know this is a second report at the same -+ * entry. This gives them the chance to examine the -+ * registers anew after they might have been changed -+ * while we were stopped. -+ */ -+ report->detaches = false; -+ report->spurious = true; -+ report->action = report->resume_action = UTRACE_RESUME; -+ return UTRACE_SYSCALL_RESUMED; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Called iff UTRACE_EVENT(SYSCALL_ENTRY) flag is set. -+ * Return true to prevent the system call. -+ */ -+bool utrace_report_syscall_entry(struct pt_regs *regs) -+{ -+ struct task_struct *task = current; -+ struct utrace *utrace = task_utrace_struct(task); -+ INIT_REPORT(report); -+ u32 resume_report = 0; -+ -+ do { -+ resume_report = do_report_syscall_entry(regs, task, utrace, -+ &report, resume_report); -+ } while (resume_report); -+ -+ return utrace_syscall_action(report.result) == UTRACE_SYSCALL_ABORT; -+} -+ -+/* -+ * Called iff UTRACE_EVENT(SYSCALL_EXIT) flag is set. -+ */ -+void utrace_report_syscall_exit(struct pt_regs *regs) -+{ -+ struct task_struct *task = current; -+ struct utrace *utrace = task_utrace_struct(task); -+ INIT_REPORT(report); -+ -+ REPORT(task, utrace, &report, UTRACE_EVENT(SYSCALL_EXIT), -+ report_syscall_exit, regs); -+} -+ -+/* -+ * Called iff UTRACE_EVENT(CLONE) flag is set. -+ * This notification call blocks the wake_up_new_task call on the child. -+ * So we must not quiesce here. tracehook_report_clone_complete will do -+ * a quiescence check momentarily. -+ */ -+void utrace_report_clone(unsigned long clone_flags, struct task_struct *child) -+{ -+ struct task_struct *task = current; -+ struct utrace *utrace = task_utrace_struct(task); -+ INIT_REPORT(report); -+ -+ /* -+ * We don't use the REPORT() macro here, because we need -+ * to clear utrace->cloning before finish_report(). -+ * After finish_report(), utrace can be a stale pointer -+ * in cases when report.action is still UTRACE_RESUME. -+ */ -+ start_report(utrace); -+ utrace->cloning = child; -+ -+ REPORT_CALLBACKS(, task, utrace, &report, -+ UTRACE_EVENT(CLONE), report_clone, -+ report.action, engine, clone_flags, child); -+ -+ utrace->cloning = NULL; -+ finish_report(task, utrace, &report, !(clone_flags & CLONE_VFORK)); -+ -+ /* -+ * For a vfork, we will go into an uninterruptible block waiting -+ * for the child. We need UTRACE_STOP to happen before this, not -+ * after. For CLONE_VFORK, utrace_finish_vfork() will be called. -+ */ -+ if (report.action == UTRACE_STOP && (clone_flags & CLONE_VFORK)) { -+ spin_lock(&utrace->lock); -+ utrace->vfork_stop = 1; -+ spin_unlock(&utrace->lock); -+ } -+} -+ -+/* -+ * We're called after utrace_report_clone() for a CLONE_VFORK. -+ * If UTRACE_STOP was left from the clone report, we stop here. -+ * After this, we'll enter the uninterruptible wait_for_completion() -+ * waiting for the child. -+ */ -+void utrace_finish_vfork(struct task_struct *task) -+{ -+ struct utrace *utrace = task_utrace_struct(task); -+ -+ if (utrace->vfork_stop) { -+ spin_lock(&utrace->lock); -+ utrace->vfork_stop = 0; -+ spin_unlock(&utrace->lock); -+ utrace_stop(task, utrace, UTRACE_RESUME); /* XXX */ -+ } -+} -+ -+/* -+ * Called iff UTRACE_EVENT(JCTL) flag is set. -+ * -+ * Called with siglock held. -+ */ -+void utrace_report_jctl(int notify, int what) -+{ -+ struct task_struct *task = current; -+ struct utrace *utrace = task_utrace_struct(task); -+ INIT_REPORT(report); -+ -+ spin_unlock_irq(&task->sighand->siglock); -+ -+ REPORT(task, utrace, &report, UTRACE_EVENT(JCTL), -+ report_jctl, what, notify); -+ -+ spin_lock_irq(&task->sighand->siglock); -+} -+ -+/* -+ * Called iff UTRACE_EVENT(EXIT) flag is set. -+ */ -+void utrace_report_exit(long *exit_code) -+{ -+ struct task_struct *task = current; -+ struct utrace *utrace = task_utrace_struct(task); -+ INIT_REPORT(report); -+ long orig_code = *exit_code; -+ -+ REPORT(task, utrace, &report, UTRACE_EVENT(EXIT), -+ report_exit, orig_code, exit_code); -+ -+ if (report.action == UTRACE_STOP) -+ utrace_stop(task, utrace, report.resume_action); -+} -+ -+/* -+ * Called iff UTRACE_EVENT(DEATH) or UTRACE_EVENT(QUIESCE) flag is set. -+ * -+ * It is always possible that we are racing with utrace_release_task here. -+ * For this reason, utrace_release_task checks for the event bits that get -+ * us here, and delays its cleanup for us to do. -+ */ -+void utrace_report_death(struct task_struct *task, bool group_dead, int signal) -+{ -+ struct utrace *utrace = task_utrace_struct(task); -+ -+ INIT_REPORT(report); -+ -+ BUG_ON(!task->exit_state); -+ -+ /* -+ * We are presently considered "quiescent"--which is accurate -+ * inasmuch as we won't run any more user instructions ever again. -+ * But for utrace_control and utrace_set_events to be robust, they -+ * must be sure whether or not we will run any more callbacks. If -+ * a call comes in before we do, taking the lock here synchronizes -+ * us so we don't run any callbacks just disabled. Calls that come -+ * in while we're running the callbacks will see the exit.death -+ * flag and know that we are not yet fully quiescent for purposes -+ * of detach bookkeeping. -+ */ -+ spin_lock(&utrace->lock); -+ BUG_ON(utrace->death); -+ utrace->death = 1; -+ utrace->resume = UTRACE_RESUME; -+ splice_attaching(utrace); -+ spin_unlock(&utrace->lock); -+ -+ REPORT_CALLBACKS(, task, utrace, &report, UTRACE_EVENT(DEATH), -+ report_death, engine, group_dead, signal); -+ -+ utrace_maybe_reap(task, utrace, false); -+} -+ -+/* -+ * Finish the last reporting pass before returning to user mode. -+ */ -+static void finish_resume_report(struct task_struct *task, -+ struct utrace *utrace, -+ struct utrace_report *report) -+{ -+ finish_report_reset(task, utrace, report); -+ -+ switch (report->action) { -+ case UTRACE_STOP: -+ utrace_stop(task, utrace, report->resume_action); -+ break; -+ -+ case UTRACE_INTERRUPT: -+ if (!signal_pending(task)) -+ set_tsk_thread_flag(task, TIF_SIGPENDING); -+ break; -+ -+ case UTRACE_BLOCKSTEP: -+ if (likely(arch_has_block_step())) { -+ if (!ptrace_wants_step(task)) -+ user_enable_block_step(task); -+ break; -+ } -+ -+ /* -+ * This means some callback is to blame for failing -+ * to check arch_has_block_step() itself. Warn and -+ * then fall through to treat it as SINGLESTEP. -+ */ -+ WARN(1, "UTRACE_BLOCKSTEP when !arch_has_block_step()"); -+ -+ case UTRACE_SINGLESTEP: -+ if (likely(arch_has_single_step())) { -+ if (!ptrace_wants_step(task)) -+ user_enable_single_step(task); -+ } else { -+ /* -+ * This means some callback is to blame for failing -+ * to check arch_has_single_step() itself. Spew -+ * about it so the loser will fix his module. -+ */ -+ WARN(1, -+ "UTRACE_SINGLESTEP when !arch_has_single_step()"); -+ } -+ break; -+ -+ case UTRACE_REPORT: -+ case UTRACE_RESUME: -+ default: -+ if (!ptrace_wants_step(task)) -+ user_disable_single_step(task); -+ break; -+ } -+} -+ -+/* -+ * This is called when TIF_NOTIFY_RESUME had been set (and is now clear). -+ * We are close to user mode, and this is the place to report or stop. -+ * When we return, we're going to user mode or into the signals code. -+ */ -+void utrace_resume(struct task_struct *task, struct pt_regs *regs) -+{ -+ struct utrace *utrace = task_utrace_struct(task); -+ INIT_REPORT(report); -+ struct utrace_engine *engine; -+ -+ /* -+ * Some machines get here with interrupts disabled. The same arch -+ * code path leads to calling into get_signal_to_deliver(), which -+ * implicitly reenables them by virtue of spin_unlock_irq. -+ */ -+ if (irqs_disabled()) /* make trace_hardirqs_on() happy */ -+ local_irq_enable(); -+ -+ /* -+ * If this flag is still set it's because there was a signal -+ * handler setup done but no report_signal following it. Clear -+ * the flag before we get to user so it doesn't confuse us later. -+ */ -+ if (unlikely(utrace->signal_handler)) { -+ spin_lock(&utrace->lock); -+ utrace->signal_handler = 0; -+ spin_unlock(&utrace->lock); -+ } -+ -+ /* -+ * Update our bookkeeping even if there are no callbacks made here. -+ */ -+ report.action = start_report(utrace); -+ -+ switch (report.action) { -+ case UTRACE_RESUME: -+ /* -+ * Anything we might have done was already handled by -+ * utrace_get_signal(), or this is an entirely spurious -+ * call. (The arch might use TIF_NOTIFY_RESUME for other -+ * purposes as well as calling us.) -+ */ -+ return; -+ case UTRACE_REPORT: -+ if (unlikely(!(task->utrace_flags & UTRACE_EVENT(QUIESCE)))) -+ break; -+ /* -+ * Do a simple reporting pass, with no specific -+ * callback after report_quiesce. -+ */ -+ report.action = UTRACE_RESUME; -+ list_for_each_entry(engine, &utrace->attached, entry) -+ start_callback(utrace, &report, engine, task, 0); -+ break; -+ default: -+ /* -+ * Even if this report was truly spurious, there is no need -+ * for utrace_reset() now. TIF_NOTIFY_RESUME was already -+ * cleared--it doesn't stay spuriously set. -+ */ -+ report.spurious = false; -+ break; -+ } -+ -+ /* -+ * Finish the report and either stop or get ready to resume. -+ * If utrace->resume was not UTRACE_REPORT, this applies its -+ * effect now (i.e. step or interrupt). -+ */ -+ finish_resume_report(task, utrace, &report); -+} -+ -+/* -+ * Return true if current has forced signal_pending(). -+ * -+ * This is called only when current->utrace_flags is nonzero, so we know -+ * that current->utrace must be set. It's not inlined in tracehook.h -+ * just so that struct utrace can stay opaque outside this file. -+ */ -+bool utrace_interrupt_pending(void) -+{ -+ return task_utrace_struct(current)->resume == UTRACE_INTERRUPT; -+} -+ -+/* -+ * Take the siglock and push @info back on our queue. -+ * Returns with @task->sighand->siglock held. -+ */ -+static void push_back_signal(struct task_struct *task, siginfo_t *info) -+ __acquires(task->sighand->siglock) -+{ -+ struct sigqueue *q; -+ -+ if (unlikely(!info->si_signo)) { /* Oh, a wise guy! */ -+ spin_lock_irq(&task->sighand->siglock); -+ return; -+ } -+ -+ q = sigqueue_alloc(); -+ if (likely(q)) { -+ q->flags = 0; -+ copy_siginfo(&q->info, info); -+ } -+ -+ spin_lock_irq(&task->sighand->siglock); -+ -+ sigaddset(&task->pending.signal, info->si_signo); -+ if (likely(q)) -+ list_add(&q->list, &task->pending.list); -+ -+ set_tsk_thread_flag(task, TIF_SIGPENDING); -+} -+ -+/* -+ * This is the hook from the signals code, called with the siglock held. -+ * Here is the ideal place to stop. We also dequeue and intercept signals. -+ */ -+int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, -+ siginfo_t *info, struct k_sigaction *return_ka) -+ __releases(task->sighand->siglock) -+ __acquires(task->sighand->siglock) -+{ -+ struct utrace *utrace; -+ struct k_sigaction *ka; -+ INIT_REPORT(report); -+ struct utrace_engine *engine; -+ const struct utrace_engine_ops *ops; -+ unsigned long event, want; -+ u32 ret; -+ int signr; -+ -+ utrace = task_utrace_struct(task); -+ if (utrace->resume < UTRACE_RESUME || -+ utrace->pending_attach || utrace->signal_handler) { -+ enum utrace_resume_action resume; -+ -+ /* -+ * We've been asked for an explicit report before we -+ * even check for pending signals. -+ */ -+ -+ spin_unlock_irq(&task->sighand->siglock); -+ -+ spin_lock(&utrace->lock); -+ -+ splice_attaching(utrace); -+ -+ report.result = utrace->signal_handler ? -+ UTRACE_SIGNAL_HANDLER : UTRACE_SIGNAL_REPORT; -+ utrace->signal_handler = 0; -+ -+ resume = utrace->resume; -+ utrace->resume = UTRACE_RESUME; -+ -+ spin_unlock(&utrace->lock); -+ -+ /* -+ * Make sure signal_pending() only returns true -+ * if there are real signals pending. -+ */ -+ if (signal_pending(task)) { -+ spin_lock_irq(&task->sighand->siglock); -+ recalc_sigpending(); -+ spin_unlock_irq(&task->sighand->siglock); -+ } -+ -+ if (resume > UTRACE_REPORT) { -+ /* -+ * We only got here to process utrace->resume. -+ * Despite no callbacks, this report is not spurious. -+ */ -+ report.action = resume; -+ report.spurious = false; -+ finish_resume_report(task, utrace, &report); -+ return -1; -+ } else if (!(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { -+ /* -+ * We only got here to clear utrace->signal_handler. -+ */ -+ return -1; -+ } -+ -+ /* -+ * Do a reporting pass for no signal, just for EVENT(QUIESCE). -+ * The engine callbacks can fill in *info and *return_ka. -+ * We'll pass NULL for the @orig_ka argument to indicate -+ * that there was no original signal. -+ */ -+ event = 0; -+ ka = NULL; -+ memset(return_ka, 0, sizeof *return_ka); -+ } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || -+ unlikely(task->jobctl & JOBCTL_PENDING_MASK)) { -+ /* -+ * If no engine is interested in intercepting signals or -+ * we must stop, let the caller just dequeue them normally -+ * or participate in group-stop. -+ */ -+ return 0; -+ } else { -+ /* -+ * Steal the next signal so we can let tracing engines -+ * examine it. From the signal number and sigaction, -+ * determine what normal delivery would do. If no -+ * engine perturbs it, we'll do that by returning the -+ * signal number after setting *return_ka. -+ */ -+ signr = dequeue_signal(task, &task->blocked, info); -+ if (signr == 0) -+ return signr; -+ BUG_ON(signr != info->si_signo); -+ -+ ka = &task->sighand->action[signr - 1]; -+ *return_ka = *ka; -+ -+ /* -+ * We are never allowed to interfere with SIGKILL. -+ * Just punt after filling in *return_ka for our caller. -+ */ -+ if (signr == SIGKILL) -+ return signr; -+ -+ if (ka->sa.sa_handler == SIG_IGN) { -+ event = UTRACE_EVENT(SIGNAL_IGN); -+ report.result = UTRACE_SIGNAL_IGN; -+ } else if (ka->sa.sa_handler != SIG_DFL) { -+ event = UTRACE_EVENT(SIGNAL); -+ report.result = UTRACE_SIGNAL_DELIVER; -+ } else if (sig_kernel_coredump(signr)) { -+ event = UTRACE_EVENT(SIGNAL_CORE); -+ report.result = UTRACE_SIGNAL_CORE; -+ } else if (sig_kernel_ignore(signr)) { -+ event = UTRACE_EVENT(SIGNAL_IGN); -+ report.result = UTRACE_SIGNAL_IGN; -+ } else if (signr == SIGSTOP) { -+ event = UTRACE_EVENT(SIGNAL_STOP); -+ report.result = UTRACE_SIGNAL_STOP; -+ } else if (sig_kernel_stop(signr)) { -+ event = UTRACE_EVENT(SIGNAL_STOP); -+ report.result = UTRACE_SIGNAL_TSTP; -+ } else { -+ event = UTRACE_EVENT(SIGNAL_TERM); -+ report.result = UTRACE_SIGNAL_TERM; -+ } -+ -+ /* -+ * Now that we know what event type this signal is, we -+ * can short-circuit if no engines care about those. -+ */ -+ if ((task->utrace_flags & (event | UTRACE_EVENT(QUIESCE))) == 0) -+ return signr; -+ -+ /* -+ * We have some interested engines, so tell them about -+ * the signal and let them change its disposition. -+ */ -+ spin_unlock_irq(&task->sighand->siglock); -+ } -+ -+ /* -+ * This reporting pass chooses what signal disposition we'll act on. -+ */ -+ list_for_each_entry(engine, &utrace->attached, entry) { -+ /* -+ * See start_callback() comment about this barrier. -+ */ -+ utrace->reporting = engine; -+ smp_mb(); -+ -+ /* -+ * This pairs with the barrier in mark_engine_detached(), -+ * see start_callback() comments. -+ */ -+ want = engine->flags; -+ smp_rmb(); -+ ops = engine->ops; -+ -+ if ((want & (event | UTRACE_EVENT(QUIESCE))) == 0) { -+ utrace->reporting = NULL; -+ continue; -+ } -+ -+ if (ops->report_signal) -+ ret = (*ops->report_signal)( -+ report.result | report.action, engine, -+ regs, info, ka, return_ka); -+ else -+ ret = (report.result | (*ops->report_quiesce)( -+ report.action, engine, event)); -+ -+ /* -+ * Avoid a tight loop reporting again and again if some -+ * engine is too stupid. -+ */ -+ switch (utrace_resume_action(ret)) { -+ default: -+ break; -+ case UTRACE_INTERRUPT: -+ case UTRACE_REPORT: -+ ret = (ret & ~UTRACE_RESUME_MASK) | UTRACE_RESUME; -+ break; -+ } -+ -+ finish_callback(task, utrace, &report, engine, ret); -+ } -+ -+ /* -+ * We express the chosen action to the signals code in terms -+ * of a representative signal whose default action does it. -+ * Our caller uses our return value (signr) to decide what to -+ * do, but uses info->si_signo as the signal number to report. -+ */ -+ switch (utrace_signal_action(report.result)) { -+ case UTRACE_SIGNAL_TERM: -+ signr = SIGTERM; -+ break; -+ -+ case UTRACE_SIGNAL_CORE: -+ signr = SIGQUIT; -+ break; -+ -+ case UTRACE_SIGNAL_STOP: -+ signr = SIGSTOP; -+ break; -+ -+ case UTRACE_SIGNAL_TSTP: -+ signr = SIGTSTP; -+ break; -+ -+ case UTRACE_SIGNAL_DELIVER: -+ signr = info->si_signo; -+ -+ if (return_ka->sa.sa_handler == SIG_DFL) { -+ /* -+ * We'll do signr's normal default action. -+ * For ignore, we'll fall through below. -+ * For stop/death, break locks and returns it. -+ */ -+ if (likely(signr) && !sig_kernel_ignore(signr)) -+ break; -+ } else if (return_ka->sa.sa_handler != SIG_IGN && -+ likely(signr)) { -+ /* -+ * Complete the bookkeeping after the report. -+ * The handler will run. If an engine wanted to -+ * stop or step, then make sure we do another -+ * report after signal handler setup. -+ */ -+ if (report.action != UTRACE_RESUME) -+ report.action = UTRACE_INTERRUPT; -+ finish_report(task, utrace, &report, true); -+ -+ if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) -+ push_back_signal(task, info); -+ else -+ spin_lock_irq(&task->sighand->siglock); -+ -+ /* -+ * We do the SA_ONESHOT work here since the -+ * normal path will only touch *return_ka now. -+ */ -+ if (unlikely(return_ka->sa.sa_flags & SA_ONESHOT)) { -+ return_ka->sa.sa_flags &= ~SA_ONESHOT; -+ if (likely(valid_signal(signr))) { -+ ka = &task->sighand->action[signr - 1]; -+ ka->sa.sa_handler = SIG_DFL; -+ } -+ } -+ -+ return signr; -+ } -+ -+ /* Fall through for an ignored signal. */ -+ -+ case UTRACE_SIGNAL_IGN: -+ case UTRACE_SIGNAL_REPORT: -+ default: -+ /* -+ * If the signal is being ignored, then we are on the way -+ * directly back to user mode. We can stop here, or step, -+ * as in utrace_resume(), above. After we've dealt with that, -+ * our caller will relock and come back through here. -+ */ -+ finish_resume_report(task, utrace, &report); -+ -+ if (unlikely(fatal_signal_pending(task))) { -+ /* -+ * The only reason we woke up now was because of a -+ * SIGKILL. Don't do normal dequeuing in case it -+ * might get a signal other than SIGKILL. That would -+ * perturb the death state so it might differ from -+ * what the debugger would have allowed to happen. -+ * Instead, pluck out just the SIGKILL to be sure -+ * we'll die immediately with nothing else different -+ * from the quiescent state the debugger wanted us in. -+ */ -+ sigset_t sigkill_only; -+ siginitsetinv(&sigkill_only, sigmask(SIGKILL)); -+ spin_lock_irq(&task->sighand->siglock); -+ signr = dequeue_signal(task, &sigkill_only, info); -+ BUG_ON(signr != SIGKILL); -+ *return_ka = task->sighand->action[SIGKILL - 1]; -+ return signr; -+ } -+ -+ if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) { -+ push_back_signal(task, info); -+ spin_unlock_irq(&task->sighand->siglock); -+ } -+ -+ return -1; -+ } -+ -+ /* -+ * Complete the bookkeeping after the report. -+ * This sets utrace->resume if UTRACE_STOP was used. -+ */ -+ finish_report(task, utrace, &report, true); -+ -+ return_ka->sa.sa_handler = SIG_DFL; -+ -+ /* -+ * If this signal is fatal, si_signo gets through as exit_code. -+ * We can't allow a completely bogus value there or else core -+ * kernel code can freak out. (If an engine wants to control -+ * the exit_code value exactly, it can do so in report_exit.) -+ * We'll produce a big complaint in dmesg, but won't crash. -+ * That's nicer for debugging your utrace engine. -+ */ -+ if (unlikely(info->si_signo & 0x80)) { -+ WARN(1, "utrace engine left bogus si_signo value!"); -+ info->si_signo = SIGTRAP; -+ } -+ -+ if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) -+ push_back_signal(task, info); -+ else -+ spin_lock_irq(&task->sighand->siglock); -+ -+ if (sig_kernel_stop(signr)) -+ task->jobctl |= JOBCTL_STOP_DEQUEUED; -+ -+ return signr; -+} -+ -+/* -+ * This gets called after a signal handler has been set up. -+ * We set a flag so the next report knows it happened. -+ * If we're already stepping, make sure we do a report_signal. -+ * If not, make sure we get into utrace_resume() where we can -+ * clear the signal_handler flag before resuming. -+ */ -+void utrace_signal_handler(struct task_struct *task, int stepping) -+{ -+ struct utrace *utrace = task_utrace_struct(task); -+ -+ spin_lock(&utrace->lock); -+ -+ utrace->signal_handler = 1; -+ if (utrace->resume > UTRACE_INTERRUPT) { -+ if (stepping) { -+ utrace->resume = UTRACE_INTERRUPT; -+ set_tsk_thread_flag(task, TIF_SIGPENDING); -+ } else if (utrace->resume == UTRACE_RESUME) { -+ set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); -+ } -+ } -+ -+ spin_unlock(&utrace->lock); -+} -+ -+/** -+ * utrace_prepare_examine - prepare to examine thread state -+ * @target: thread of interest, a &struct task_struct pointer -+ * @engine: engine pointer returned by utrace_attach_task() -+ * @exam: temporary state, a &struct utrace_examiner pointer -+ * -+ * This call prepares to safely examine the thread @target using -+ * &struct user_regset calls, or direct access to thread-synchronous fields. -+ * -+ * When @target is current, this call is superfluous. When @target is -+ * another thread, it must be held stopped via %UTRACE_STOP by @engine. -+ * -+ * This call may block the caller until @target stays stopped, so it must -+ * be called only after the caller is sure @target is about to unschedule. -+ * This means a zero return from a utrace_control() call on @engine giving -+ * %UTRACE_STOP, or a report_quiesce() or report_signal() callback to -+ * @engine that used %UTRACE_STOP in its return value. -+ * -+ * Returns -%ESRCH if @target is dead or -%EINVAL if %UTRACE_STOP was -+ * not used. If @target has started running again despite %UTRACE_STOP -+ * (for %SIGKILL or a spurious wakeup), this call returns -%EAGAIN. -+ * -+ * When this call returns zero, it's safe to use &struct user_regset -+ * calls and task_user_regset_view() on @target and to examine some of -+ * its fields directly. When the examination is complete, a -+ * utrace_finish_examine() call must follow to check whether it was -+ * completed safely. -+ */ -+int utrace_prepare_examine(struct task_struct *target, -+ struct utrace_engine *engine, -+ struct utrace_examiner *exam) -+{ -+ int ret = 0; -+ -+ if (unlikely(target == current)) -+ return 0; -+ -+ rcu_read_lock(); -+ if (unlikely(!engine_wants_stop(engine))) -+ ret = -EINVAL; -+ else if (unlikely(target->exit_state)) -+ ret = -ESRCH; -+ else { -+ exam->state = target->state; -+ if (unlikely(exam->state == TASK_RUNNING)) -+ ret = -EAGAIN; -+ else -+ get_task_struct(target); -+ } -+ rcu_read_unlock(); -+ -+ if (likely(!ret)) { -+ exam->ncsw = wait_task_inactive(target, exam->state); -+ put_task_struct(target); -+ if (unlikely(!exam->ncsw)) -+ ret = -EAGAIN; -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(utrace_prepare_examine); -+ -+/** -+ * utrace_finish_examine - complete an examination of thread state -+ * @target: thread of interest, a &struct task_struct pointer -+ * @engine: engine pointer returned by utrace_attach_task() -+ * @exam: pointer passed to utrace_prepare_examine() call -+ * -+ * This call completes an examination on the thread @target begun by a -+ * paired utrace_prepare_examine() call with the same arguments that -+ * returned success (zero). -+ * -+ * When @target is current, this call is superfluous. When @target is -+ * another thread, this returns zero if @target has remained unscheduled -+ * since the paired utrace_prepare_examine() call returned zero. -+ * -+ * When this returns an error, any examination done since the paired -+ * utrace_prepare_examine() call is unreliable and the data extracted -+ * should be discarded. The error is -%EINVAL if @engine is not -+ * keeping @target stopped, or -%EAGAIN if @target woke up unexpectedly. -+ */ -+int utrace_finish_examine(struct task_struct *target, -+ struct utrace_engine *engine, -+ struct utrace_examiner *exam) -+{ -+ int ret = 0; -+ -+ if (unlikely(target == current)) -+ return 0; -+ -+ rcu_read_lock(); -+ if (unlikely(!engine_wants_stop(engine))) -+ ret = -EINVAL; -+ else if (unlikely(target->state != exam->state)) -+ ret = -EAGAIN; -+ else -+ get_task_struct(target); -+ rcu_read_unlock(); -+ -+ if (likely(!ret)) { -+ unsigned long ncsw = wait_task_inactive(target, exam->state); -+ if (unlikely(ncsw != exam->ncsw)) -+ ret = -EAGAIN; -+ put_task_struct(target); -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(utrace_finish_examine); -+ -+/* -+ * This is declared in linux/regset.h and defined in machine-dependent -+ * code. We put the export here to ensure no machine forgets it. -+ */ -+EXPORT_SYMBOL_GPL(task_user_regset_view); -+ -+/* -+ * Called with rcu_read_lock() held. -+ */ -+void task_utrace_proc_status(struct seq_file *m, struct task_struct *p) -+{ -+ seq_printf(m, "Utrace:\t%lx\n", p->utrace_flags); -+} --- -1.7.9.1 - diff --git a/x86-add-io_apic_ops-to-allow-interception.patch b/x86-add-io_apic_ops-to-allow-interception.patch deleted file mode 100644 index c82d21fff..000000000 --- a/x86-add-io_apic_ops-to-allow-interception.patch +++ /dev/null @@ -1,135 +0,0 @@ -From: Jeremy Fitzhardinge - -Xen dom0 needs to paravirtualize IO operations to the IO APIC, so add -a io_apic_ops for it to intercept. Do this as ops structure because -there's at least some chance that another paravirtualized environment -may want to intercept these. - -[ Impact: indirect IO APIC access via io_apic_ops ] - -Signed-off-by: Jeremy Fitzhardinge -Signed-off-by: Konrad Rzeszutek Wilk -Acked-by: Suresh Siddha ---- - arch/x86/include/asm/io_apic.h | 9 +++++++ - arch/x86/kernel/apic/io_apic.c | 50 +++++++++++++++++++++++++++++++++++++-- - 2 files changed, 56 insertions(+), 3 deletions(-) - -diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h -index 690d1cc..190d8c2 100644 ---- a/arch/x86/include/asm/io_apic.h -+++ b/arch/x86/include/asm/io_apic.h -@@ -21,6 +21,15 @@ - #define IO_APIC_REDIR_LEVEL_TRIGGER (1 << 15) - #define IO_APIC_REDIR_MASKED (1 << 16) - -+struct io_apic_ops { -+ void (*init)(void); -+ unsigned int (*read)(unsigned int apic, unsigned int reg); -+ void (*write)(unsigned int apic, unsigned int reg, unsigned int value); -+ void (*modify)(unsigned int apic, unsigned int reg, unsigned int value); -+}; -+ -+void __init set_io_apic_ops(const struct io_apic_ops *); -+ - /* - * The structure of the IO-APIC: - */ -diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c -index fb07275..bf120234 100644 ---- a/arch/x86/kernel/apic/io_apic.c -+++ b/arch/x86/kernel/apic/io_apic.c -@@ -67,6 +67,25 @@ - #define for_each_irq_pin(entry, head) \ - for (entry = head; entry; entry = entry->next) - -+static void __init __ioapic_init_mappings(void); -+static unsigned int __io_apic_read(unsigned int apic, unsigned int reg); -+static void __io_apic_write(unsigned int apic, unsigned int reg, -+ unsigned int val); -+static void __io_apic_modify(unsigned int apic, unsigned int reg, -+ unsigned int val); -+ -+static struct io_apic_ops io_apic_ops = { -+ .init = __ioapic_init_mappings, -+ .read = __io_apic_read, -+ .write = __io_apic_write, -+ .modify = __io_apic_modify, -+}; -+ -+void __init set_io_apic_ops(const struct io_apic_ops *ops) -+{ -+ io_apic_ops = *ops; -+} -+ - /* - * Is the SiS APIC rmw bug present ? - * -1 = don't know, 0 = no, 1 = yes -@@ -294,6 +313,24 @@ static void free_irq_at(unsigned int at, struct irq_cfg *cfg) - irq_free_desc(at); - } - -+static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) -+{ -+ return io_apic_ops.read(apic, reg); -+} -+ -+static inline void io_apic_write(unsigned int apic, unsigned int reg, -+ unsigned int value) -+{ -+ io_apic_ops.write(apic, reg, value); -+} -+ -+static inline void io_apic_modify(unsigned int apic, unsigned int reg, -+ unsigned int value) -+{ -+ io_apic_ops.modify(apic, reg, value); -+} -+ -+ - struct io_apic { - unsigned int index; - unsigned int unused[3]; -@@ -314,14 +351,15 @@ static inline void io_apic_eoi(unsigned int apic, unsigned int vector) - writel(vector, &io_apic->eoi); - } - --static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) -+static unsigned int __io_apic_read(unsigned int apic, unsigned int reg) - { - struct io_apic __iomem *io_apic = io_apic_base(apic); - writel(reg, &io_apic->index); - return readl(&io_apic->data); - } - --static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) -+static void __io_apic_write(unsigned int apic, unsigned int reg, -+ unsigned int value) - { - struct io_apic __iomem *io_apic = io_apic_base(apic); - writel(reg, &io_apic->index); -@@ -334,7 +372,8 @@ static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned i - * - * Older SiS APIC requires we rewrite the index register - */ --static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) -+static void __io_apic_modify(unsigned int apic, unsigned int reg, -+ unsigned int value) - { - struct io_apic __iomem *io_apic = io_apic_base(apic); - -@@ -3873,6 +3912,11 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics) - - void __init ioapic_and_gsi_init(void) - { -+ io_apic_ops.init(); -+} -+ -+static void __init __ioapic_init_mappings(void) -+{ - unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; - struct resource *ioapic_res; - int i; --- -1.7.7.5 - diff --git a/x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch b/x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch deleted file mode 100644 index ddbb92412..000000000 --- a/x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch +++ /dev/null @@ -1,258 +0,0 @@ -. which makes the code fit within the rest of the x86_ops functions. - -Signed-off-by: Konrad Rzeszutek Wilk -[v1: Changed x86_apic -> x86_ioapic per Yinghai Lu suggestion] -Acked-by: Suresh Siddha ---- - arch/x86/include/asm/io_apic.h | 40 +++++++++++++++++++++-------- - arch/x86/include/asm/x86_init.h | 8 ++++++ - arch/x86/kernel/apic/io_apic.c | 54 ++++---------------------------------- - arch/x86/kernel/setup.c | 2 +- - arch/x86/kernel/x86_init.c | 8 ++++++ - 5 files changed, 52 insertions(+), 60 deletions(-) - -diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h -index 190d8c2..ba1b11a 100644 ---- a/arch/x86/include/asm/io_apic.h -+++ b/arch/x86/include/asm/io_apic.h -@@ -5,6 +5,7 @@ - #include - #include - #include -+#include - - /* - * Intel IO-APIC support for SMP and UP systems. -@@ -21,15 +22,6 @@ - #define IO_APIC_REDIR_LEVEL_TRIGGER (1 << 15) - #define IO_APIC_REDIR_MASKED (1 << 16) - --struct io_apic_ops { -- void (*init)(void); -- unsigned int (*read)(unsigned int apic, unsigned int reg); -- void (*write)(unsigned int apic, unsigned int reg, unsigned int value); -- void (*modify)(unsigned int apic, unsigned int reg, unsigned int value); --}; -- --void __init set_io_apic_ops(const struct io_apic_ops *); -- - /* - * The structure of the IO-APIC: - */ -@@ -156,7 +148,6 @@ struct io_apic_irq_attr; - extern int io_apic_set_pci_routing(struct device *dev, int irq, - struct io_apic_irq_attr *irq_attr); - void setup_IO_APIC_irq_extra(u32 gsi); --extern void ioapic_and_gsi_init(void); - extern void ioapic_insert_resources(void); - - int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr); -@@ -185,12 +176,35 @@ extern void mp_save_irq(struct mpc_intsrc *m); - - extern void disable_ioapic_support(void); - -+ -+void __init native_ioapic_init_mappings(void); -+unsigned int native_ioapic_read(unsigned int apic, unsigned int reg); -+void native_ioapic_write(unsigned int apic, unsigned int reg, -+ unsigned int val); -+void native_ioapic_modify(unsigned int apic, unsigned int reg, -+ unsigned int val); -+ -+static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) -+{ -+ return x86_ioapic.read(apic, reg); -+} -+ -+static inline void io_apic_write(unsigned int apic, unsigned int reg, -+ unsigned int value) -+{ -+ x86_ioapic.write(apic, reg, value); -+} -+ -+static inline void io_apic_modify(unsigned int apic, unsigned int reg, -+ unsigned int value) -+{ -+ x86_ioapic.modify(apic, reg, value); -+} - #else /* !CONFIG_X86_IO_APIC */ - - #define io_apic_assign_pci_irqs 0 - #define setup_ioapic_ids_from_mpc x86_init_noop - static const int timer_through_8259 = 0; --static inline void ioapic_and_gsi_init(void) { } - static inline void ioapic_insert_resources(void) { } - #define gsi_top (NR_IRQS_LEGACY) - static inline int mp_find_ioapic(u32 gsi) { return 0; } -@@ -212,6 +226,10 @@ static inline int restore_ioapic_entries(void) - - static inline void mp_save_irq(struct mpc_intsrc *m) { }; - static inline void disable_ioapic_support(void) { } -+#define native_ioapic_init_mappings NULL -+#define native_ioapic_read NULL -+#define native_ioapic_write NULL -+#define native_ioapic_modify NULL - #endif - - #endif /* _ASM_X86_IO_APIC_H */ -diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h -index 517d476..a3730cc 100644 ---- a/arch/x86/include/asm/x86_init.h -+++ b/arch/x86/include/asm/x86_init.h -@@ -182,10 +182,18 @@ struct x86_msi_ops { - void (*restore_msi_irqs)(struct pci_dev *dev, int irq); - }; - -+struct x86_ioapic_ops { -+ void (*init)(void); -+ unsigned int (*read)(unsigned int apic, unsigned int reg); -+ void (*write)(unsigned int apic, unsigned int reg, unsigned int value); -+ void (*modify)(unsigned int apic, unsigned int reg, unsigned int value); -+}; -+ - extern struct x86_init_ops x86_init; - extern struct x86_cpuinit_ops x86_cpuinit; - extern struct x86_platform_ops x86_platform; - extern struct x86_msi_ops x86_msi; -+extern struct x86_ioapic_ops x86_ioapic; - - extern void x86_init_noop(void); - extern void x86_init_uint_noop(unsigned int unused); -diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c -index bf120234..9a15d4b 100644 ---- a/arch/x86/kernel/apic/io_apic.c -+++ b/arch/x86/kernel/apic/io_apic.c -@@ -67,25 +67,6 @@ - #define for_each_irq_pin(entry, head) \ - for (entry = head; entry; entry = entry->next) - --static void __init __ioapic_init_mappings(void); --static unsigned int __io_apic_read(unsigned int apic, unsigned int reg); --static void __io_apic_write(unsigned int apic, unsigned int reg, -- unsigned int val); --static void __io_apic_modify(unsigned int apic, unsigned int reg, -- unsigned int val); -- --static struct io_apic_ops io_apic_ops = { -- .init = __ioapic_init_mappings, -- .read = __io_apic_read, -- .write = __io_apic_write, -- .modify = __io_apic_modify, --}; -- --void __init set_io_apic_ops(const struct io_apic_ops *ops) --{ -- io_apic_ops = *ops; --} -- - /* - * Is the SiS APIC rmw bug present ? - * -1 = don't know, 0 = no, 1 = yes -@@ -313,24 +294,6 @@ static void free_irq_at(unsigned int at, struct irq_cfg *cfg) - irq_free_desc(at); - } - --static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) --{ -- return io_apic_ops.read(apic, reg); --} -- --static inline void io_apic_write(unsigned int apic, unsigned int reg, -- unsigned int value) --{ -- io_apic_ops.write(apic, reg, value); --} -- --static inline void io_apic_modify(unsigned int apic, unsigned int reg, -- unsigned int value) --{ -- io_apic_ops.modify(apic, reg, value); --} -- -- - struct io_apic { - unsigned int index; - unsigned int unused[3]; -@@ -351,15 +314,15 @@ static inline void io_apic_eoi(unsigned int apic, unsigned int vector) - writel(vector, &io_apic->eoi); - } - --static unsigned int __io_apic_read(unsigned int apic, unsigned int reg) -+unsigned int native_ioapic_read(unsigned int apic, unsigned int reg) - { - struct io_apic __iomem *io_apic = io_apic_base(apic); - writel(reg, &io_apic->index); - return readl(&io_apic->data); - } - --static void __io_apic_write(unsigned int apic, unsigned int reg, -- unsigned int value) -+void native_ioapic_write(unsigned int apic, unsigned int reg, -+ unsigned int value) - { - struct io_apic __iomem *io_apic = io_apic_base(apic); - writel(reg, &io_apic->index); -@@ -372,8 +335,8 @@ static void __io_apic_write(unsigned int apic, unsigned int reg, - * - * Older SiS APIC requires we rewrite the index register - */ --static void __io_apic_modify(unsigned int apic, unsigned int reg, -- unsigned int value) -+void native_ioapic_modify(unsigned int apic, unsigned int reg, -+ unsigned int value) - { - struct io_apic __iomem *io_apic = io_apic_base(apic); - -@@ -3910,12 +3873,7 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics) - return res; - } - --void __init ioapic_and_gsi_init(void) --{ -- io_apic_ops.init(); --} -- --static void __init __ioapic_init_mappings(void) -+void __init native_ioapic_init_mappings(void) - { - unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; - struct resource *ioapic_res; -diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index d7d5099..7eaef1a 100644 ---- a/arch/x86/kernel/setup.c -+++ b/arch/x86/kernel/setup.c -@@ -1016,7 +1016,7 @@ void __init setup_arch(char **cmdline_p) - init_cpu_to_node(); - - init_apic_mappings(); -- ioapic_and_gsi_init(); -+ x86_ioapic.init(); - - kvm_guest_init(); - -diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c -index 947a06c..df870d3 100644 ---- a/arch/x86/kernel/x86_init.c -+++ b/arch/x86/kernel/x86_init.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -117,3 +118,10 @@ struct x86_msi_ops x86_msi = { - .teardown_msi_irqs = default_teardown_msi_irqs, - .restore_msi_irqs = default_restore_msi_irqs, - }; -+ -+struct x86_ioapic_ops x86_ioapic = { -+ .init = native_ioapic_init_mappings, -+ .read = native_ioapic_read, -+ .write = native_ioapic_write, -+ .modify = native_ioapic_modify, -+}; --- -1.7.7.5 - diff --git a/xen-x86-Implement-x86_apic_ops.patch b/xen-x86-Implement-x86_apic_ops.patch deleted file mode 100644 index 0963ecb25..000000000 --- a/xen-x86-Implement-x86_apic_ops.patch +++ /dev/null @@ -1,85 +0,0 @@ -Or rather just implement one different function as opposed -to the native one : the read function. - -We synthesize the values. - -Acked-by: Suresh Siddha -Signed-off-by: Konrad Rzeszutek Wilk ---- - arch/x86/xen/Makefile | 2 +- - arch/x86/xen/apic.c | 17 +++++++++++++++++ - arch/x86/xen/enlighten.c | 2 ++ - arch/x86/xen/xen-ops.h | 4 ++++ - 4 files changed, 24 insertions(+), 1 deletions(-) - create mode 100644 arch/x86/xen/apic.c - -diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile -index add2c2d..96ab2c0 100644 ---- a/arch/x86/xen/Makefile -+++ b/arch/x86/xen/Makefile -@@ -20,5 +20,5 @@ obj-$(CONFIG_EVENT_TRACING) += trace.o - obj-$(CONFIG_SMP) += smp.o - obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o - obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o --obj-$(CONFIG_XEN_DOM0) += vga.o -+obj-$(CONFIG_XEN_DOM0) += apic.o vga.o - obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o -diff --git a/arch/x86/xen/apic.c b/arch/x86/xen/apic.c -new file mode 100644 -index 0000000..71ed91c ---- /dev/null -+++ b/arch/x86/xen/apic.c -@@ -0,0 +1,17 @@ -+#include -+#include -+ -+unsigned int xen_io_apic_read(unsigned apic, unsigned reg) -+{ -+ if (reg == 0x1) -+ return 0x00170020; -+ else if (reg == 0x0) -+ return apic << 24; -+ -+ return 0xff; -+} -+ -+void __init xen_init_apic(void) -+{ -+ x86_ioapic.read = xen_io_apic_read; -+} -diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c -index 0732326..93a03195 100644 ---- a/arch/x86/xen/enlighten.c -+++ b/arch/x86/xen/enlighten.c -@@ -1377,6 +1377,8 @@ asmlinkage void __init xen_start_kernel(void) - xen_start_info->console.domU.mfn = 0; - xen_start_info->console.domU.evtchn = 0; - -+ xen_init_apic(); -+ - /* Make sure ACS will be enabled */ - pci_request_acs(); - -diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h -index b095739..45c0c06 100644 ---- a/arch/x86/xen/xen-ops.h -+++ b/arch/x86/xen/xen-ops.h -@@ -92,11 +92,15 @@ struct dom0_vga_console_info; - - #ifdef CONFIG_XEN_DOM0 - void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size); -+void __init xen_init_apic(void); - #else - static inline void __init xen_init_vga(const struct dom0_vga_console_info *info, - size_t size) - { - } -+static inline void __init xen_init_apic(void) -+{ -+} - #endif - - /* Declare an asm function, along with symbols needed to make it --- -1.7.7.5 - From 8b4ddbe29f94e6e859b280aa39e9f81972403b88 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 14 Jun 2012 15:02:27 -0500 Subject: [PATCH 390/487] Add bison to buildrequires, learn from my mistakes --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 068ded8b9..7d6a79c19 100644 --- a/kernel.spec +++ b/kernel.spec @@ -547,7 +547,7 @@ BuildRequires: xmlto, asciidoc BuildRequires: sparse >= 0.4.1 %endif %if %{with_tools} -BuildRequires: elfutils-devel zlib-devel binutils-devel newt-devel python-devel perl(ExtUtils::Embed) pciutils-devel gettext +BuildRequires: elfutils-devel zlib-devel binutils-devel newt-devel python-devel perl(ExtUtils::Embed) pciutils-devel gettext bison %endif BuildConflicts: rhbuildsys(DiskFree) < 500Mb From fd269b5b6a111a5a77ffe1141f01eeeda25da54e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 18 Jun 2012 08:36:01 -0400 Subject: [PATCH 391/487] Add patch to fix CIFS password mount option parsing (rhbz 832741) - Add patch to fix udl device binding (rhbz 832188) --- ...fix-parsing-of-password-mount-option.patch | 86 +++++++++++++++++++ kernel.spec | 18 +++- udl-bind-fix.patch | 28 ++++++ 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 cifs-fix-parsing-of-password-mount-option.patch create mode 100644 udl-bind-fix.patch diff --git a/cifs-fix-parsing-of-password-mount-option.patch b/cifs-fix-parsing-of-password-mount-option.patch new file mode 100644 index 000000000..9805c6bf9 --- /dev/null +++ b/cifs-fix-parsing-of-password-mount-option.patch @@ -0,0 +1,86 @@ +From e73f843a3235a19de38359c91586e9eadef12238 Mon Sep 17 00:00:00 2001 +From: Suresh Jayaraman +Date: Tue, 12 Jun 2012 07:15:50 +0530 +Subject: [PATCH] cifs: fix parsing of password mount option + +The double delimiter check that allows a comma in the password parsing code is +unconditional. We set "tmp_end" to the end of the string and we continue to +check for double delimiter. In the case where the password doesn't contain a +comma we end up setting tmp_end to NULL and eventually setting "options" to +"end". This results in the premature termination of the options string and hence +the values of UNCip and UNC are being set to NULL. This results in mount failure +with "Connecting to DFS root not implemented yet" error. + +This error is usually not noticable as we have password as the last option in +the superblock mountdata. But when we call expand_dfs_referral() from +cifs_mount() and try to compose mount options for the submount, the resulting +mountdata will be of the form + + ",ver=1,user=foo,pass=bar,ip=x.x.x.x,unc=\\server\share" + +and hence results in the above error. This bug has been seen with older NAS +servers running Samba 3.0.24. + +Fix this by moving the double delimiter check inside the conditional loop. + +Changes since -v1 + + - removed the wrong strlen() micro optimization. + +Signed-off-by: Suresh Jayaraman +Acked-by: Sachin Prabhu +Cc: stable@vger.kernel.org [3.1+] +Signed-off-by: Steve French +--- + fs/cifs/connect.c | 32 +++++++++++++++++--------------- + 1 files changed, 17 insertions(+), 15 deletions(-) + +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index 78db68a..5b38407 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -1653,24 +1653,26 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, + * If yes, we have encountered a double deliminator + * reset the NULL character to the deliminator + */ +- if (tmp_end < end && tmp_end[1] == delim) ++ if (tmp_end < end && tmp_end[1] == delim) { + tmp_end[0] = delim; + +- /* Keep iterating until we get to a single deliminator +- * OR the end +- */ +- while ((tmp_end = strchr(tmp_end, delim)) != NULL && +- (tmp_end[1] == delim)) { +- tmp_end = (char *) &tmp_end[2]; +- } ++ /* Keep iterating until we get to a single ++ * deliminator OR the end ++ */ ++ while ((tmp_end = strchr(tmp_end, delim)) ++ != NULL && (tmp_end[1] == delim)) { ++ tmp_end = (char *) &tmp_end[2]; ++ } + +- /* Reset var options to point to next element */ +- if (tmp_end) { +- tmp_end[0] = '\0'; +- options = (char *) &tmp_end[1]; +- } else +- /* Reached the end of the mount option string */ +- options = end; ++ /* Reset var options to point to next element */ ++ if (tmp_end) { ++ tmp_end[0] = '\0'; ++ options = (char *) &tmp_end[1]; ++ } else ++ /* Reached the end of the mount option ++ * string */ ++ options = end; ++ } + + /* Now build new password string */ + temp_len = strlen(value); +-- +1.7.0.4 + diff --git a/kernel.spec b/kernel.spec index 7d6a79c19..8f67ad4b6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -772,6 +772,12 @@ Patch22024: iwlwifi-dont-mess-up-the-SCD-when-removing-a-key.patch Patch22030: SUNRPC-new-svc_bind-routine-introduced.patch Patch22031: SUNRPC-move-per-net-operations-from-svc_destroy.patch +#rhbz 832741 +Patch22032: cifs-fix-parsing-of-password-mount-option.patch + +#rhbz 832188 +Patch22033: udl-bind-fix.patch + # END OF PATCH DEFINITIONS %endif @@ -1430,6 +1436,12 @@ ApplyPatch iwlwifi-dont-mess-up-the-SCD-when-removing-a-key.patch ApplyPatch SUNRPC-new-svc_bind-routine-introduced.patch ApplyPatch SUNRPC-move-per-net-operations-from-svc_destroy.patch +#rhbz 832741 +ApplyPatch cifs-fix-parsing-of-password-mount-option.patch + +#rhbz 832188 +ApplyPatch udl-bind-fix.patch + # END OF PATCH APPLICATIONS %endif @@ -2168,6 +2180,10 @@ fi # and build. %changelog +* Mon Jun 18 2012 Josh Boyer +- Add patch to fix CIFS password mount option parsing (rhbz 832741) +- Add patch to fix udl device binding (rhbz 832188) + * Thu Jun 14 2012 Justin M. Forbes 3.4.2-1 - Linux 3.4.2 diff --git a/udl-bind-fix.patch b/udl-bind-fix.patch new file mode 100644 index 000000000..45b4563c1 --- /dev/null +++ b/udl-bind-fix.patch @@ -0,0 +1,28 @@ +@@ -, +, @@ + drivers/gpu/drm/udl/udl_drv.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) +--- a/drivers/gpu/drm/udl/udl_drv.c ++++ a/drivers/gpu/drm/udl/udl_drv.c +@@ -13,8 +13,21 @@ + + static struct drm_driver driver; + ++/* ++ * There are many DisplayLink-based graphics products, all with unique PIDs. ++ * So we match on DisplayLink's VID + Vendor-Defined Interface Class (0xff) ++ * We also require a match on SubClass (0x00) and Protocol (0x00), ++ * which is compatible with all known USB 2.0 era graphics chips and firmware, ++ * but allows DisplayLink to increment those for any future incompatible chips ++ */ + static struct usb_device_id id_table[] = { +- {.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,}, ++ {.idVendor = 0x17e9, .bInterfaceClass = 0xff, ++ .bInterfaceSubClass = 0x00, ++ .bInterfaceProtocol = 0x00, ++ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | ++ USB_DEVICE_ID_MATCH_INT_CLASS | ++ USB_DEVICE_ID_MATCH_INT_SUBCLASS | ++ USB_DEVICE_ID_MATCH_INT_PROTOCOL,}, + {}, + }; + MODULE_DEVICE_TABLE(usb, id_table); From 06bcea703a3887e772a52df51843ce827568b93c Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 18 Jun 2012 10:50:32 -0500 Subject: [PATCH 392/487] Linux 3.4.3 --- ...-buggy-chain-extension-feature-in-HW.patch | 48 ------------------- ...-mess-up-the-SCD-when-removing-a-key.patch | 45 ----------------- kernel.spec | 15 ++---- sources | 2 +- 4 files changed, 6 insertions(+), 104 deletions(-) delete mode 100644 iwlwifi-disable-the-buggy-chain-extension-feature-in-HW.patch delete mode 100644 iwlwifi-dont-mess-up-the-SCD-when-removing-a-key.patch diff --git a/iwlwifi-disable-the-buggy-chain-extension-feature-in-HW.patch b/iwlwifi-disable-the-buggy-chain-extension-feature-in-HW.patch deleted file mode 100644 index c4f2ed3a1..000000000 --- a/iwlwifi-disable-the-buggy-chain-extension-feature-in-HW.patch +++ /dev/null @@ -1,48 +0,0 @@ -From d012d04e4d6312ea157b6cf19e9689af934f5aa7 Mon Sep 17 00:00:00 2001 -From: Emmanuel Grumbach -Date: Wed, 6 Jun 2012 13:55:02 +0200 -Subject: [PATCH] iwlwifi: disable the buggy chain extension feature in HW - -This feature has been reported to be buggy and enabled by -default. We therefore need to disable it manually. - -Cc: stable@vger.kernel.org -Signed-off-by: Emmanuel Grumbach -Signed-off-by: Johannes Berg -Signed-off-by: John W. Linville ---- - drivers/net/wireless/iwlwifi/iwl-prph.h | 1 + - drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 5 +++++ - 2 files changed, 6 insertions(+), 0 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h -index 3b10692..dfd5466 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-prph.h -+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h -@@ -224,6 +224,7 @@ - #define SCD_TXFACT (SCD_BASE + 0x10) - #define SCD_ACTIVE (SCD_BASE + 0x14) - #define SCD_QUEUECHAIN_SEL (SCD_BASE + 0xe8) -+#define SCD_CHAINEXT_EN (SCD_BASE + 0x244) - #define SCD_AGGR_SEL (SCD_BASE + 0x248) - #define SCD_INTERRUPT_MASK (SCD_BASE + 0x108) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c -index ec6fb39..79c6b91 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c -+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c -@@ -1058,6 +1058,11 @@ static void iwl_tx_start(struct iwl_trans *trans) - iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, - trans_pcie->scd_bc_tbls.dma >> 10); - -+ /* The chain extension of the SCD doesn't work well. This feature is -+ * enabled by default by the HW, so we need to disable it manually. -+ */ -+ iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); -+ - /* Enable DMA channel */ - for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) - iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), --- -1.7.7.6 - diff --git a/iwlwifi-dont-mess-up-the-SCD-when-removing-a-key.patch b/iwlwifi-dont-mess-up-the-SCD-when-removing-a-key.patch deleted file mode 100644 index f7c3c7181..000000000 --- a/iwlwifi-dont-mess-up-the-SCD-when-removing-a-key.patch +++ /dev/null @@ -1,45 +0,0 @@ -From d6ee27eb13beab94056e0de52d81220058ca2297 Mon Sep 17 00:00:00 2001 -From: Emmanuel Grumbach -Date: Wed, 6 Jun 2012 09:13:36 +0200 -Subject: [PATCH] iwlwifi: don't mess up the SCD when removing a key - -When we remove a key, we put a key index which was supposed -to tell the fw that we are actually removing the key. But -instead the fw took that index as a valid index and messed -up the SRAM of the device. - -This memory corruption on the device mangled the data of -the SCD. The impact on the user is that SCD queue 2 got -stuck after having removed keys. -The message is the log that was printed is: - -Queue 2 stuck for 10000ms - -This doesn't seem to fix the higher queues that get stuck -from time to time. - -Cc: stable@vger.kernel.org [2.6.27+] -Reviewed-by: Meenakshi Venkataraman -Signed-off-by: Emmanuel Grumbach -Signed-off-by: Johannes Berg -Signed-off-by: John W. Linville ---- - drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c -index aea07aa..eb6a8ea 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c -@@ -1267,7 +1267,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, - key_flags |= STA_KEY_MULTICAST_MSK; - - sta_cmd.key.key_flags = key_flags; -- sta_cmd.key.key_offset = WEP_INVALID_OFFSET; -+ sta_cmd.key.key_offset = keyconf->hw_key_idx; - sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK; - sta_cmd.mode = STA_CONTROL_MODIFY_MSK; - --- -1.7.6.5 - diff --git a/kernel.spec b/kernel.spec index 8f67ad4b6..229986787 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 2 +%define stable_update 3 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -764,10 +764,6 @@ Patch22021: mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-c #rhbz 829016 Patch22022: thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch -#rhbz 825491 -Patch22023: iwlwifi-disable-the-buggy-chain-extension-feature-in-HW.patch -Patch22024: iwlwifi-dont-mess-up-the-SCD-when-removing-a-key.patch - #rhbz 830862 Patch22030: SUNRPC-new-svc_bind-routine-introduced.patch Patch22031: SUNRPC-move-per-net-operations-from-svc_destroy.patch @@ -1428,10 +1424,6 @@ ApplyPatch mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-co ApplyPatch thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch -#rhbz 825491 -ApplyPatch iwlwifi-disable-the-buggy-chain-extension-feature-in-HW.patch -ApplyPatch iwlwifi-dont-mess-up-the-SCD-when-removing-a-key.patch - #rhbz 830862 ApplyPatch SUNRPC-new-svc_bind-routine-introduced.patch ApplyPatch SUNRPC-move-per-net-operations-from-svc_destroy.patch @@ -2180,6 +2172,9 @@ fi # and build. %changelog +* Mon Jun 18 2012 Justin M. Forbes 3.4.3-1 +- Linux 3.4.3 + * Mon Jun 18 2012 Josh Boyer - Add patch to fix CIFS password mount option parsing (rhbz 832741) - Add patch to fix udl device binding (rhbz 832188) diff --git a/sources b/sources index cd364717e..341fd2705 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 967f72983655e2479f951195953e8480 linux-3.4.tar.xz -ac52d3d82c20c7e80740fc5fb00b6ed4 patch-3.4.2.xz +3b6cf4f6337346ee78904eb70e2d4e08 patch-3.4.3.xz From 783e7aa493f2f7da3aaeb8b348417b1f7a6d2b27 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 20 Jun 2012 08:35:14 -0400 Subject: [PATCH 393/487] Add proposed patch to fix READ_CAPACITY command on usb keys (rhbz 831807) --- kernel.spec | 11 +- usb-storage-try-read_capacity-10-first.patch | 130 +++++++++++++++++++ 2 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 usb-storage-try-read_capacity-10-first.patch diff --git a/kernel.spec b/kernel.spec index 229986787..60a78ad59 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -774,6 +774,9 @@ Patch22032: cifs-fix-parsing-of-password-mount-option.patch #rhbz 832188 Patch22033: udl-bind-fix.patch +#rhbz 831807 +Patch22034: usb-storage-try-read_capacity-10-first.patch + # END OF PATCH DEFINITIONS %endif @@ -1434,6 +1437,9 @@ ApplyPatch cifs-fix-parsing-of-password-mount-option.patch #rhbz 832188 ApplyPatch udl-bind-fix.patch +#rhbz 831807 +ApplyPatch usb-storage-try-read_capacity-10-first.patch + # END OF PATCH APPLICATIONS %endif @@ -2172,6 +2178,9 @@ fi # and build. %changelog +* Tue Jun 19 2012 Josh Boyer +- Add proposed patch to fix READ_CAPACITY command on usb keys (rhbz 831807) + * Mon Jun 18 2012 Justin M. Forbes 3.4.3-1 - Linux 3.4.3 diff --git a/usb-storage-try-read_capacity-10-first.patch b/usb-storage-try-read_capacity-10-first.patch new file mode 100644 index 000000000..c9791cdc1 --- /dev/null +++ b/usb-storage-try-read_capacity-10-first.patch @@ -0,0 +1,130 @@ +Path: news.gmane.org!not-for-mail +From: Alan Stern +Newsgroups: gmane.linux.usb.general +Subject: Re: USB mass-storage devices and READ CAPACITY(16) +Date: Sun, 17 Jun 2012 11:26:31 -0400 (EDT) +Lines: 81 +Approved: news@gmane.org +Message-ID: +References: +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +X-Trace: dough.gmane.org 1339946799 1694 80.91.229.3 (17 Jun 2012 15:26:39 GMT) +X-Complaints-To: usenet@dough.gmane.org +NNTP-Posting-Date: Sun, 17 Jun 2012 15:26:39 +0000 (UTC) +Cc: Torsten Wohlfarth , + Sturm Flut , + Sergey , + Philippe Valembois - Phil + , + USB list +To: Hans de Goede +Original-X-From: linux-usb-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Sun Jun 17 17:26:37 2012 +Return-path: +Envelope-to: glug-linux-usb-wOFGN7rlS/M9smdsby/KFg@public.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1SgHN3-0002d5-Pq + for glug-linux-usb-wOFGN7rlS/M9smdsby/KFg@public.gmane.org; Sun, 17 Jun 2012 17:26:34 +0200 +Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand + id S1757469Ab2FQP0d (ORCPT ); + Sun, 17 Jun 2012 11:26:33 -0400 +Original-Received: from netrider.rowland.org ([192.131.102.5]:55086 "HELO + netrider.rowland.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with SMTP id S1757447Ab2FQP0c (ORCPT + ); Sun, 17 Jun 2012 11:26:32 -0400 +Original-Received: (qmail 16789 invoked by uid 500); 17 Jun 2012 11:26:31 -0400 +Original-Received: from localhost (sendmail-bs-savSHZN5Fh8qMp+WYRx65w@public.gmane.org) + by localhost with SMTP; 17 Jun 2012 11:26:31 -0400 +X-X-Sender: stern-pYrvlCTfrz9XsRXLowluHWD2FQJk+8+b@public.gmane.org +In-Reply-To: +Original-Sender: linux-usb-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +Xref: news.gmane.org gmane.linux.usb.general:65976 +Archived-At: + +On Fri, 15 Jun 2012, Alan Stern wrote: + +> On Fri, 15 Jun 2012, Hans de Goede wrote: +> +> > Hi, +> > +> > On 06/15/2012 08:20 PM, Alan Stern wrote: +> > > As we can see from recent bug reports, a lot of USB mass-storage +> > > devices cannot handle READ CAPACITY(16) commands properly. They send +> > > back garbage and are unusable as a result. +> > > +> > > Should we go ahead and set a flag on all these devices, telling the sd +> > > driver to try READ CAPACITY(10) first? That's a lot easier than adding +> > > more and more entries to unusual_devs.h. +> > +> > That certainly sound reasonable to me. Note that the 071b:3203 really +> > needs the US_FL_NO_READ_CAPACITY_16 flag though, as it wrongly reports +> > a capacity of -1 when there is no sd card in its slot, and in response +> > to that the kernel tries READ CAPACITY(16) and things go downhill +> > from there... +> +> Yes, we need to be able to have both flags set for the same device. +> For that card reader they would mean try READ CAPACITY(10) first, and +> if it fails, don't try READ CAPACITY(16). + +In other words, I'm suggesting we adopt this patch and get rid Hans's +new unusual_devs entry. + +Alan Stern + + + + +Index: usb-3.4/include/scsi/scsi_device.h +=================================================================== +--- usb-3.4.orig/include/scsi/scsi_device.h ++++ usb-3.4/include/scsi/scsi_device.h +@@ -151,6 +151,7 @@ struct scsi_device { + SD_LAST_BUGGY_SECTORS */ + unsigned no_read_disc_info:1; /* Avoid READ_DISC_INFO cmds */ + unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */ ++ unsigned try_rc_10_first:1; /* Try READ_CAPACACITY_10 first */ + unsigned is_visible:1; /* is the device visible in sysfs */ + + DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */ +Index: usb-3.4/drivers/scsi/sd.c +=================================================================== +--- usb-3.4.orig/drivers/scsi/sd.c ++++ usb-3.4/drivers/scsi/sd.c +@@ -1899,6 +1899,8 @@ static int sd_try_rc16_first(struct scsi + { + if (sdp->host->max_cmd_len < 16) + return 0; ++ if (sdp->try_rc_10_first) ++ return 0; + if (sdp->scsi_level > SCSI_SPC_2) + return 1; + if (scsi_device_protection(sdp)) +Index: usb-3.4/drivers/usb/storage/scsiglue.c +=================================================================== +--- usb-3.4.orig/drivers/usb/storage/scsiglue.c ++++ usb-3.4/drivers/usb/storage/scsiglue.c +@@ -202,6 +202,12 @@ static int slave_configure(struct scsi_d + if (us->fflags & US_FL_NO_READ_CAPACITY_16) + sdev->no_read_capacity_16 = 1; + ++ /* ++ * Many devices do not respond properly to READ_CAPACITY_16. ++ * Tell the SCSI layer to try READ_CAPACITY_10 first. ++ */ ++ sdev->try_rc_10_first = 1; ++ + /* assume SPC3 or latter devices support sense size > 18 */ + if (sdev->scsi_level > SCSI_SPC_2) + us->fflags |= US_FL_SANE_SENSE; + +-- +To unsubscribe from this list: send the line "unsubscribe linux-usb" in +the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + From d82b14bfca97d271839f68e219fd2c38cc45436b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 20 Jun 2012 15:06:01 -0400 Subject: [PATCH 394/487] Fix incorrect logic in irqpoll patch --- kernel.spec | 5 +- unhandled-irqs-switch-to-polling.patch | 101 ++++++++++++------------- 2 files changed, 53 insertions(+), 53 deletions(-) diff --git a/kernel.spec b/kernel.spec index 60a78ad59..526e58450 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2178,6 +2178,9 @@ fi # and build. %changelog +* Wed Jun 20 2012 Josh Boyer +- Fix incorrect logic in irqpoll patch + * Tue Jun 19 2012 Josh Boyer - Add proposed patch to fix READ_CAPACITY command on usb keys (rhbz 831807) diff --git a/unhandled-irqs-switch-to-polling.patch b/unhandled-irqs-switch-to-polling.patch index 2f25cda6f..0fc4d080e 100644 --- a/unhandled-irqs-switch-to-polling.patch +++ b/unhandled-irqs-switch-to-polling.patch @@ -1,23 +1,8 @@ -Date: Mon, 30 Jan 2012 22:37:28 +0100 -Message-ID: +From f9b32cd97783f2be14386f1347439e86109050b9 Mon Sep 17 00:00:00 2001 +From: Jeroen Van den Keybus +Date: Mon, 30 Jan 2012 22:37:28 +0100 Subject: [PATCH] Unhandled IRQs on AMD E-450: temporarily switch to low-performance polling IRQ mode -From: Jeroen Van den Keybus -To: linux-kernel@vger.kernel.org -Cc: Clemens Ladisch , "Huang, Shane" , - Borislav Petkov , "Nguyen, Dong" , - jesse.brandeburg@gmail.com -Content-Type: text/plain; charset=ISO-8859-1 -Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org -X-RedHat-Spam-Score: -4.898 (DKIM_ADSP_CUSTOM_MED,DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_HI,T_DKIM_INVALID,T_RP_MATCHES_RCVD) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -X-Scanned-By: MIMEDefang 2.68 on 10.5.110.19 -Status: RO -Content-Length: 7029 -Lines: 189 It seems that some motherboard designs using the ASM1083 PCI/PCIe bridge (PCI device ID 1b21:1080, Rev. 01) suffer from stuck IRQ lines @@ -79,16 +64,49 @@ I would like to thank Clemens Ladisch for his invaluable help in finding a solution (and providing a patch to avoid my SATA going down every time during debugging). - Signed-off-by: Jeroen Van den Keybus Make it less chatty. Only kick it in if we detect an ASM1083 PCI bridge. +Fix logic error due to lack of braces Josh Boyer ====== +--- + drivers/pci/quirks.c | 16 +++++++++++ + kernel/irq/spurious.c | 73 +++++++++++++++++++++++++++++++++++++++--------- + 2 files changed, 75 insertions(+), 14 deletions(-) ---- linux-2.6.orig/kernel/irq/spurious.c -+++ linux-2.6/kernel/irq/spurious.c +diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c +index 78fda9c..6ba5dbf 100644 +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -1677,6 +1677,22 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2609, quirk_intel_pcie_pm); + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm); + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm); + ++/* ASM108x transparent PCI bridges apparently have broken IRQ deassert ++ * handling. This causes interrupts to get "stuck" and eventually disabled. ++ * However, the interrupts are often shared and disabling them is fairly bad. ++ * It's been somewhat successful to switch to polling mode and retry after ++ * a bit, so let's do that. ++ */ ++extern int irq_poll_and_retry; ++static void quirk_asm108x_poll_interrupts(struct pci_dev *dev) ++{ ++ dev_info(&dev->dev, "Buggy bridge found [%04x:%04x]\n", ++ dev->vendor, dev->device); ++ dev_info(&dev->dev, "Stuck interrupts will be polled and retried\n"); ++ irq_poll_and_retry = 1; ++} ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_asm108x_poll_interrupts); ++ + #ifdef CONFIG_X86_IO_APIC + /* + * Boot interrupts on some chipsets cannot be turned off. For these chipsets, +diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c +index 611cd60..f722eb6 100644 +--- a/kernel/irq/spurious.c ++++ b/kernel/irq/spurious.c @@ -18,6 +18,8 @@ static int irqfixup __read_mostly; @@ -113,7 +131,7 @@ Josh Boyer for_each_irq_desc(i, desc) { unsigned int state; -@@ -159,14 +162,33 @@ static void poll_spurious_irqs(unsigned +@@ -159,14 +162,33 @@ static void poll_spurious_irqs(unsigned long dummy) if (!(state & IRQS_SPURIOUS_DISABLED)) continue; @@ -152,7 +170,7 @@ Josh Boyer } static inline int bad_action_ret(irqreturn_t action_ret) -@@ -177,11 +199,19 @@ static inline int bad_action_ret(irqretu +@@ -177,11 +199,19 @@ static inline int bad_action_ret(irqreturn_t action_ret) } /* @@ -174,7 +192,7 @@ Josh Boyer * functioning device sharing an IRQ with the failing one) */ static void -@@ -269,6 +299,8 @@ try_misrouted_irq(unsigned int irq, stru +@@ -269,6 +299,8 @@ try_misrouted_irq(unsigned int irq, struct irq_desc *desc, void note_interrupt(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret) { @@ -183,18 +201,19 @@ Josh Boyer if (desc->istate & IRQS_POLL_INPROGRESS) return; -@@ -302,19 +334,31 @@ void note_interrupt(unsigned int irq, st +@@ -302,19 +334,32 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, } desc->irq_count++; - if (likely(desc->irq_count < 100000)) - return; -+ if (!irq_poll_and_retry) ++ if (!irq_poll_and_retry) { + if (likely(desc->irq_count < 100000)) + return; -+ else ++ } else { + if (likely(desc->irq_count < 10)) + return; ++ } desc->irq_count = 0; - if (unlikely(desc->irqs_unhandled > 99900)) { @@ -221,28 +240,6 @@ Josh Boyer desc->istate |= IRQS_SPURIOUS_DISABLED; desc->depth++; irq_disable(desc); ---- linux-2.6.orig/drivers/pci/quirks.c -+++ linux-2.6/drivers/pci/quirks.c -@@ -1677,6 +1677,22 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN - DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm); - DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm); - -+/* ASM108x transparent PCI bridges apparently have broken IRQ deassert -+ * handling. This causes interrupts to get "stuck" and eventually disabled. -+ * However, the interrupts are often shared and disabling them is fairly bad. -+ * It's been somewhat successful to switch to polling mode and retry after -+ * a bit, so let's do that. -+ */ -+extern int irq_poll_and_retry; -+static void quirk_asm108x_poll_interrupts(struct pci_dev *dev) -+{ -+ dev_info(&dev->dev, "Buggy bridge found [%04x:%04x]\n", -+ dev->vendor, dev->device); -+ dev_info(&dev->dev, "Stuck interrupts will be polled and retried\n"); -+ irq_poll_and_retry = 1; -+} -+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_asm108x_poll_interrupts); -+ - #ifdef CONFIG_X86_IO_APIC - /* - * Boot interrupts on some chipsets cannot be turned off. For these chipsets, +-- +1.7.7.6 + From 8a1178d1844b8f40957eb456d370fbd99ca1f886 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 22 Jun 2012 07:47:04 -0400 Subject: [PATCH 395/487] Disable UDL DRM driver per Dave Airlie --- config-generic | 2 +- kernel.spec | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/config-generic b/config-generic index a6508a90c..95a3a3d72 100644 --- a/config-generic +++ b/config-generic @@ -2597,7 +2597,7 @@ CONFIG_DRM_NOUVEAU_BACKLIGHT=y CONFIG_DRM_NOUVEAU_DEBUG=y CONFIG_DRM_I2C_CH7006=m CONFIG_DRM_I2C_SIL164=m -CONFIG_DRM_UDL=m +# CONFIG_DRM_UDL is not set CONFIG_DRM_VMWGFX=m # diff --git a/kernel.spec b/kernel.spec index 526e58450..35452f70d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2178,6 +2178,9 @@ fi # and build. %changelog +* Fri Jun 22 2012 Josh Boyer +- Disable UDL DRM driver per Dave Airlie + * Wed Jun 20 2012 Josh Boyer - Fix incorrect logic in irqpoll patch From 2da3bb764c4545e562ff197215c29bea51dcde57 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 22 Jun 2012 10:18:04 -0400 Subject: [PATCH 396/487] Add uprobe backports from Anton Arapov (rhbz 832083) --- config-generic | 1 + kernel.spec | 9 + uprobes-3.4-backport.patch | 6983 ++++++++++++++++++++++++++++++++++++ uprobes-3.4-tip.patch | 915 +++++ 4 files changed, 7908 insertions(+) create mode 100644 uprobes-3.4-backport.patch create mode 100644 uprobes-3.4-tip.patch diff --git a/config-generic b/config-generic index 95a3a3d72..7427c2d8d 100644 --- a/config-generic +++ b/config-generic @@ -4291,6 +4291,7 @@ CONFIG_STACK_TRACER=y CONFIG_KPROBES=y CONFIG_KPROBE_EVENT=y +CONFIG_UPROBE_EVENT=y # CONFIG_KPROBES_SANITY_TEST is not set CONFIG_JUMP_LABEL=y CONFIG_OPTPROBES=y diff --git a/kernel.spec b/kernel.spec index 35452f70d..d09caff97 100644 --- a/kernel.spec +++ b/kernel.spec @@ -725,6 +725,10 @@ Patch14010: lis3-improve-handling-of-null-rate.patch Patch19000: ips-noirq.patch +# Uprobes (rhbz 832083) +Patch20000: uprobes-3.4-backport.patch +Patch20001: uprobes-3.4-tip.patch + # Flattened devicetree support Patch21000: arm-omap-dt-compat.patch Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch @@ -1401,6 +1405,10 @@ ApplyPatch ips-noirq.patch #ApplyPatch pci-crs-blacklist.patch +# Uprobes (rhbz 832083) +ApplyPatch uprobes-3.4-backport.patch +ApplyPatch uprobes-3.4-tip.patch + #rhbz 754518 #ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -2179,6 +2187,7 @@ fi %changelog * Fri Jun 22 2012 Josh Boyer +- Add uprobe backports from Anton Arapov (rhbz 832083) - Disable UDL DRM driver per Dave Airlie * Wed Jun 20 2012 Josh Boyer diff --git a/uprobes-3.4-backport.patch b/uprobes-3.4-backport.patch new file mode 100644 index 000000000..4a5bfe60b --- /dev/null +++ b/uprobes-3.4-backport.patch @@ -0,0 +1,6983 @@ +Modification of the kernel config is needed: + +CONFIG_ARCH_SUPPORTS_UPROBES=y + +CONFIG_UPROBES=y + +CONFIG_UPROBE_EVENT=y + +CONFIG_PROBE_EVENTS=y + +The split-out series is available in the git repository at: + + git://fedorapeople.org/home/fedora/aarapov/public_git/kernel-uprobes.git f17_uprobes_upstream + +Ingo Molnar (3): + uprobes/core: Clean up, refactor and improve the code + uprobes: Move to kernel/events/ + uprobes: Update copyright notices + +Srikar Dronamraju (20): + uprobes, mm, x86: Add the ability to install and remove uprobes breakpoints + uprobes/core: Make instruction tables volatile + uprobes/core: Remove uprobe_opcode_sz + uprobes/core: Move insn to arch specific structure + uprobes/core: Make macro names consistent + uprobes/core: Make order of function parameters consistent across functions + uprobes/core: Rename bkpt to swbp + uprobes/core: Handle breakpoint and singlestep exceptions + uprobes/core: Allocate XOL slots for uprobes use + uprobes/core: Optimize probe hits with the help of a counter + uprobes/core: Make background page replacement logic account for rss_stat counters + uprobes/core: Decrement uprobe count before the pages are unmapped + tracing: Modify is_delete, is_return from int to bool + tracing: Extract out common code for kprobes/uprobes trace events + tracing: Provide trace events interface for uprobes + tracing: Fix kconfig warning due to a typo + perf probe: Provide perf interface for uprobes + perf probe: Detect probe target when m/x options are absent + perf symbols: Check for valid dso before creating map + perf uprobes: Remove unnecessary check before strlist__delete + +Signed-off-by: Anton Arapov +--- + Documentation/trace/uprobetracer.txt | 113 +++ + arch/Kconfig | 17 + + arch/x86/Kconfig | 5 +- + arch/x86/include/asm/thread_info.h | 2 + + arch/x86/include/asm/uprobes.h | 57 ++ + arch/x86/kernel/Makefile | 1 + + arch/x86/kernel/signal.c | 6 + + arch/x86/kernel/uprobes.c | 674 +++++++++++++ + include/linux/mm_types.h | 2 + + include/linux/sched.h | 4 + + include/linux/uprobes.h | 165 +++ + kernel/events/Makefile | 3 + + kernel/events/uprobes.c | 1667 +++++++++++++++++++++++++++++++ + kernel/fork.c | 9 + + kernel/signal.c | 4 + + kernel/trace/Kconfig | 20 + + kernel/trace/Makefile | 2 + + kernel/trace/trace.h | 5 + + kernel/trace/trace_kprobe.c | 899 +---------------- + kernel/trace/trace_probe.c | 839 ++++++++++++++++ + kernel/trace/trace_probe.h | 161 +++ + kernel/trace/trace_uprobe.c | 788 +++++++++++++++ + mm/memory.c | 3 + + mm/mmap.c | 33 +- + tools/perf/Documentation/perf-probe.txt | 19 +- + tools/perf/builtin-probe.c | 86 +- + tools/perf/util/probe-event.c | 418 ++++++-- + tools/perf/util/probe-event.h | 12 +- + tools/perf/util/symbol.c | 11 + + tools/perf/util/symbol.h | 1 + + 30 files changed, 5047 insertions(+), 979 deletions(-) + create mode 100644 Documentation/trace/uprobetracer.txt + create mode 100644 arch/x86/include/asm/uprobes.h + create mode 100644 arch/x86/kernel/uprobes.c + create mode 100644 include/linux/uprobes.h + create mode 100644 kernel/events/uprobes.c + create mode 100644 kernel/trace/trace_probe.c + create mode 100644 kernel/trace/trace_probe.h + create mode 100644 kernel/trace/trace_uprobe.c + +diff --git a/Documentation/trace/uprobetracer.txt b/Documentation/trace/uprobetracer.txt +new file mode 100644 +index 0000000..24ce682 +--- /dev/null ++++ b/Documentation/trace/uprobetracer.txt +@@ -0,0 +1,113 @@ ++ Uprobe-tracer: Uprobe-based Event Tracing ++ ========================================= ++ Documentation written by Srikar Dronamraju ++ ++Overview ++-------- ++Uprobe based trace events are similar to kprobe based trace events. ++To enable this feature, build your kernel with CONFIG_UPROBE_EVENT=y. ++ ++Similar to the kprobe-event tracer, this doesn't need to be activated via ++current_tracer. Instead of that, add probe points via ++/sys/kernel/debug/tracing/uprobe_events, and enable it via ++/sys/kernel/debug/tracing/events/uprobes//enabled. ++ ++However unlike kprobe-event tracer, the uprobe event interface expects the ++user to calculate the offset of the probepoint in the object ++ ++Synopsis of uprobe_tracer ++------------------------- ++ p[:[GRP/]EVENT] PATH:SYMBOL[+offs] [FETCHARGS] : Set a probe ++ ++ GRP : Group name. If omitted, use "uprobes" for it. ++ EVENT : Event name. If omitted, the event name is generated ++ based on SYMBOL+offs. ++ PATH : path to an executable or a library. ++ SYMBOL[+offs] : Symbol+offset where the probe is inserted. ++ ++ FETCHARGS : Arguments. Each probe can have up to 128 args. ++ %REG : Fetch register REG ++ ++Event Profiling ++--------------- ++ You can check the total number of probe hits and probe miss-hits via ++/sys/kernel/debug/tracing/uprobe_profile. ++ The first column is event name, the second is the number of probe hits, ++the third is the number of probe miss-hits. ++ ++Usage examples ++-------------- ++To add a probe as a new event, write a new definition to uprobe_events ++as below. ++ ++ echo 'p: /bin/bash:0x4245c0' > /sys/kernel/debug/tracing/uprobe_events ++ ++ This sets a uprobe at an offset of 0x4245c0 in the executable /bin/bash ++ ++ echo > /sys/kernel/debug/tracing/uprobe_events ++ ++ This clears all probe points. ++ ++The following example shows how to dump the instruction pointer and %ax ++a register at the probed text address. Here we are trying to probe ++function zfree in /bin/zsh ++ ++ # cd /sys/kernel/debug/tracing/ ++ # cat /proc/`pgrep zsh`/maps | grep /bin/zsh | grep r-xp ++ 00400000-0048a000 r-xp 00000000 08:03 130904 /bin/zsh ++ # objdump -T /bin/zsh | grep -w zfree ++ 0000000000446420 g DF .text 0000000000000012 Base zfree ++ ++0x46420 is the offset of zfree in object /bin/zsh that is loaded at ++0x00400000. Hence the command to probe would be : ++ ++ # echo 'p /bin/zsh:0x46420 %ip %ax' > uprobe_events ++ ++Please note: User has to explicitly calculate the offset of the probepoint ++in the object. We can see the events that are registered by looking at the ++uprobe_events file. ++ ++ # cat uprobe_events ++ p:uprobes/p_zsh_0x46420 /bin/zsh:0x00046420 arg1=%ip arg2=%ax ++ ++The format of events can be seen by viewing the file events/uprobes/p_zsh_0x46420/format ++ ++ # cat events/uprobes/p_zsh_0x46420/format ++ name: p_zsh_0x46420 ++ ID: 922 ++ format: ++ field:unsigned short common_type; offset:0; size:2; signed:0; ++ field:unsigned char common_flags; offset:2; size:1; signed:0; ++ field:unsigned char common_preempt_count; offset:3; size:1; signed:0; ++ field:int common_pid; offset:4; size:4; signed:1; ++ field:int common_padding; offset:8; size:4; signed:1; ++ ++ field:unsigned long __probe_ip; offset:12; size:4; signed:0; ++ field:u32 arg1; offset:16; size:4; signed:0; ++ field:u32 arg2; offset:20; size:4; signed:0; ++ ++ print fmt: "(%lx) arg1=%lx arg2=%lx", REC->__probe_ip, REC->arg1, REC->arg2 ++ ++Right after definition, each event is disabled by default. For tracing these ++events, you need to enable it by: ++ ++ # echo 1 > events/uprobes/enable ++ ++Lets disable the event after sleeping for some time. ++ # sleep 20 ++ # echo 0 > events/uprobes/enable ++ ++And you can see the traced information via /sys/kernel/debug/tracing/trace. ++ ++ # cat trace ++ # tracer: nop ++ # ++ # TASK-PID CPU# TIMESTAMP FUNCTION ++ # | | | | | ++ zsh-24842 [006] 258544.995456: p_zsh_0x46420: (0x446420) arg1=446421 arg2=79 ++ zsh-24842 [007] 258545.000270: p_zsh_0x46420: (0x446420) arg1=446421 arg2=79 ++ zsh-24842 [002] 258545.043929: p_zsh_0x46420: (0x446420) arg1=446421 arg2=79 ++ zsh-24842 [004] 258547.046129: p_zsh_0x46420: (0x446420) arg1=446421 arg2=79 ++ ++Each line shows us probes were triggered for a pid 24842 with ip being ++0x446421 and contents of ax register being 79. +diff --git a/arch/Kconfig b/arch/Kconfig +index 684eb5a..2880abf 100644 +--- a/arch/Kconfig ++++ b/arch/Kconfig +@@ -76,6 +76,23 @@ config OPTPROBES + depends on KPROBES && HAVE_OPTPROBES + depends on !PREEMPT + ++config UPROBES ++ bool "Transparent user-space probes (EXPERIMENTAL)" ++ depends on UPROBE_EVENT && PERF_EVENTS ++ default n ++ help ++ Uprobes is the user-space counterpart to kprobes: they ++ enable instrumentation applications (such as 'perf probe') ++ to establish unintrusive probes in user-space binaries and ++ libraries, by executing handler functions when the probes ++ are hit by user-space applications. ++ ++ ( These probes come in the form of single-byte breakpoints, ++ managed by the kernel and kept transparent to the probed ++ application. ) ++ ++ If in doubt, say "N". ++ + config HAVE_EFFICIENT_UNALIGNED_ACCESS + bool + help +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index c9866b0..1f5c307 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -84,7 +84,7 @@ config X86 + select DCACHE_WORD_ACCESS + + config INSTRUCTION_DECODER +- def_bool (KPROBES || PERF_EVENTS) ++ def_bool (KPROBES || PERF_EVENTS || UPROBES) + + config OUTPUT_FORMAT + string +@@ -243,6 +243,9 @@ config ARCH_CPU_PROBE_RELEASE + def_bool y + depends on HOTPLUG_CPU + ++config ARCH_SUPPORTS_UPROBES ++ def_bool y ++ + source "init/Kconfig" + source "kernel/Kconfig.freezer" + +diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h +index ad6df8c..0710c11 100644 +--- a/arch/x86/include/asm/thread_info.h ++++ b/arch/x86/include/asm/thread_info.h +@@ -85,6 +85,7 @@ struct thread_info { + #define TIF_SECCOMP 8 /* secure computing */ + #define TIF_MCE_NOTIFY 10 /* notify userspace of an MCE */ + #define TIF_USER_RETURN_NOTIFY 11 /* notify kernel of userspace return */ ++#define TIF_UPROBE 12 /* breakpointed or singlestepping */ + #define TIF_NOTSC 16 /* TSC is not accessible in userland */ + #define TIF_IA32 17 /* IA32 compatibility process */ + #define TIF_FORK 18 /* ret_from_fork */ +@@ -109,6 +110,7 @@ struct thread_info { + #define _TIF_SECCOMP (1 << TIF_SECCOMP) + #define _TIF_MCE_NOTIFY (1 << TIF_MCE_NOTIFY) + #define _TIF_USER_RETURN_NOTIFY (1 << TIF_USER_RETURN_NOTIFY) ++#define _TIF_UPROBE (1 << TIF_UPROBE) + #define _TIF_NOTSC (1 << TIF_NOTSC) + #define _TIF_IA32 (1 << TIF_IA32) + #define _TIF_FORK (1 << TIF_FORK) +diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h +new file mode 100644 +index 0000000..1e9bed1 +--- /dev/null ++++ b/arch/x86/include/asm/uprobes.h +@@ -0,0 +1,57 @@ ++#ifndef _ASM_UPROBES_H ++#define _ASM_UPROBES_H ++/* ++ * User-space Probes (UProbes) for x86 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) IBM Corporation, 2008-2011 ++ * Authors: ++ * Srikar Dronamraju ++ * Jim Keniston ++ */ ++ ++#include ++ ++typedef u8 uprobe_opcode_t; ++ ++#define MAX_UINSN_BYTES 16 ++#define UPROBE_XOL_SLOT_BYTES 128 /* to keep it cache aligned */ ++ ++#define UPROBE_SWBP_INSN 0xcc ++#define UPROBE_SWBP_INSN_SIZE 1 ++ ++struct arch_uprobe { ++ u16 fixups; ++ u8 insn[MAX_UINSN_BYTES]; ++#ifdef CONFIG_X86_64 ++ unsigned long rip_rela_target_address; ++#endif ++}; ++ ++struct arch_uprobe_task { ++ unsigned long saved_trap_nr; ++#ifdef CONFIG_X86_64 ++ unsigned long saved_scratch_register; ++#endif ++}; ++ ++extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm); ++extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs); ++extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs); ++extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk); ++extern int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data); ++extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs); ++#endif /* _ASM_UPROBES_H */ +diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile +index 532d2e0..d23d835 100644 +--- a/arch/x86/kernel/Makefile ++++ b/arch/x86/kernel/Makefile +@@ -101,6 +101,7 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o + + obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o + obj-$(CONFIG_OF) += devicetree.o ++obj-$(CONFIG_UPROBES) += uprobes.o + + ### + # 64 bit specific files +diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c +index 115eac4..041af2f 100644 +--- a/arch/x86/kernel/signal.c ++++ b/arch/x86/kernel/signal.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -824,6 +825,11 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) + mce_notify_process(); + #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */ + ++ if (thread_info_flags & _TIF_UPROBE) { ++ clear_thread_flag(TIF_UPROBE); ++ uprobe_notify_resume(regs); ++ } ++ + /* deal with pending signal delivery */ + if (thread_info_flags & _TIF_SIGPENDING) + do_signal(regs); +diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c +new file mode 100644 +index 0000000..dc4e910 +--- /dev/null ++++ b/arch/x86/kernel/uprobes.c +@@ -0,0 +1,674 @@ ++/* ++ * User-space Probes (UProbes) for x86 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) IBM Corporation, 2008-2011 ++ * Authors: ++ * Srikar Dronamraju ++ * Jim Keniston ++ */ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* Post-execution fixups. */ ++ ++/* No fixup needed */ ++#define UPROBE_FIX_NONE 0x0 ++ ++/* Adjust IP back to vicinity of actual insn */ ++#define UPROBE_FIX_IP 0x1 ++ ++/* Adjust the return address of a call insn */ ++#define UPROBE_FIX_CALL 0x2 ++ ++#define UPROBE_FIX_RIP_AX 0x8000 ++#define UPROBE_FIX_RIP_CX 0x4000 ++ ++#define UPROBE_TRAP_NR UINT_MAX ++ ++/* Adaptations for mhiramat x86 decoder v14. */ ++#define OPCODE1(insn) ((insn)->opcode.bytes[0]) ++#define OPCODE2(insn) ((insn)->opcode.bytes[1]) ++#define OPCODE3(insn) ((insn)->opcode.bytes[2]) ++#define MODRM_REG(insn) X86_MODRM_REG(insn->modrm.value) ++ ++#define W(row, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf)\ ++ (((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) | \ ++ (b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) | \ ++ (b8##UL << 0x8)|(b9##UL << 0x9)|(ba##UL << 0xa)|(bb##UL << 0xb) | \ ++ (bc##UL << 0xc)|(bd##UL << 0xd)|(be##UL << 0xe)|(bf##UL << 0xf)) \ ++ << (row % 32)) ++ ++/* ++ * Good-instruction tables for 32-bit apps. This is non-const and volatile ++ * to keep gcc from statically optimizing it out, as variable_test_bit makes ++ * some versions of gcc to think only *(unsigned long*) is used. ++ */ ++static volatile u32 good_insns_32[256 / 32] = { ++ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ ++ /* ---------------------------------------------- */ ++ W(0x00, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) | /* 00 */ ++ W(0x10, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) , /* 10 */ ++ W(0x20, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1) | /* 20 */ ++ W(0x30, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1) , /* 30 */ ++ W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 40 */ ++ W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 50 */ ++ W(0x60, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* 60 */ ++ W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 70 */ ++ W(0x80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 80 */ ++ W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 90 */ ++ W(0xa0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* a0 */ ++ W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* b0 */ ++ W(0xc0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0) | /* c0 */ ++ W(0xd0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */ ++ W(0xe0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* e0 */ ++ W(0xf0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1) /* f0 */ ++ /* ---------------------------------------------- */ ++ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ ++}; ++ ++/* Using this for both 64-bit and 32-bit apps */ ++static volatile u32 good_2byte_insns[256 / 32] = { ++ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ ++ /* ---------------------------------------------- */ ++ W(0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1) | /* 00 */ ++ W(0x10, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1) , /* 10 */ ++ W(0x20, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1) | /* 20 */ ++ W(0x30, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 30 */ ++ W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 40 */ ++ W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 50 */ ++ W(0x60, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 60 */ ++ W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1) , /* 70 */ ++ W(0x80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 80 */ ++ W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 90 */ ++ W(0xa0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1) | /* a0 */ ++ W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1) , /* b0 */ ++ W(0xc0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* c0 */ ++ W(0xd0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */ ++ W(0xe0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* e0 */ ++ W(0xf0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0) /* f0 */ ++ /* ---------------------------------------------- */ ++ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ ++}; ++ ++#ifdef CONFIG_X86_64 ++/* Good-instruction tables for 64-bit apps */ ++static volatile u32 good_insns_64[256 / 32] = { ++ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ ++ /* ---------------------------------------------- */ ++ W(0x00, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) | /* 00 */ ++ W(0x10, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) , /* 10 */ ++ W(0x20, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) | /* 20 */ ++ W(0x30, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) , /* 30 */ ++ W(0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* 40 */ ++ W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 50 */ ++ W(0x60, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* 60 */ ++ W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 70 */ ++ W(0x80, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 80 */ ++ W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 90 */ ++ W(0xa0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* a0 */ ++ W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* b0 */ ++ W(0xc0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0) | /* c0 */ ++ W(0xd0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */ ++ W(0xe0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* e0 */ ++ W(0xf0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1) /* f0 */ ++ /* ---------------------------------------------- */ ++ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ ++}; ++#endif ++#undef W ++ ++/* ++ * opcodes we'll probably never support: ++ * ++ * 6c-6d, e4-e5, ec-ed - in ++ * 6e-6f, e6-e7, ee-ef - out ++ * cc, cd - int3, int ++ * cf - iret ++ * d6 - illegal instruction ++ * f1 - int1/icebp ++ * f4 - hlt ++ * fa, fb - cli, sti ++ * 0f - lar, lsl, syscall, clts, sysret, sysenter, sysexit, invd, wbinvd, ud2 ++ * ++ * invalid opcodes in 64-bit mode: ++ * ++ * 06, 0e, 16, 1e, 27, 2f, 37, 3f, 60-62, 82, c4-c5, d4-d5 ++ * 63 - we support this opcode in x86_64 but not in i386. ++ * ++ * opcodes we may need to refine support for: ++ * ++ * 0f - 2-byte instructions: For many of these instructions, the validity ++ * depends on the prefix and/or the reg field. On such instructions, we ++ * just consider the opcode combination valid if it corresponds to any ++ * valid instruction. ++ * ++ * 8f - Group 1 - only reg = 0 is OK ++ * c6-c7 - Group 11 - only reg = 0 is OK ++ * d9-df - fpu insns with some illegal encodings ++ * f2, f3 - repnz, repz prefixes. These are also the first byte for ++ * certain floating-point instructions, such as addsd. ++ * ++ * fe - Group 4 - only reg = 0 or 1 is OK ++ * ff - Group 5 - only reg = 0-6 is OK ++ * ++ * others -- Do we need to support these? ++ * ++ * 0f - (floating-point?) prefetch instructions ++ * 07, 17, 1f - pop es, pop ss, pop ds ++ * 26, 2e, 36, 3e - es:, cs:, ss:, ds: segment prefixes -- ++ * but 64 and 65 (fs: and gs:) seem to be used, so we support them ++ * 67 - addr16 prefix ++ * ce - into ++ * f0 - lock prefix ++ */ ++ ++/* ++ * TODO: ++ * - Where necessary, examine the modrm byte and allow only valid instructions ++ * in the different Groups and fpu instructions. ++ */ ++ ++static bool is_prefix_bad(struct insn *insn) ++{ ++ int i; ++ ++ for (i = 0; i < insn->prefixes.nbytes; i++) { ++ switch (insn->prefixes.bytes[i]) { ++ case 0x26: /* INAT_PFX_ES */ ++ case 0x2E: /* INAT_PFX_CS */ ++ case 0x36: /* INAT_PFX_DS */ ++ case 0x3E: /* INAT_PFX_SS */ ++ case 0xF0: /* INAT_PFX_LOCK */ ++ return true; ++ } ++ } ++ return false; ++} ++ ++static int validate_insn_32bits(struct arch_uprobe *auprobe, struct insn *insn) ++{ ++ insn_init(insn, auprobe->insn, false); ++ ++ /* Skip good instruction prefixes; reject "bad" ones. */ ++ insn_get_opcode(insn); ++ if (is_prefix_bad(insn)) ++ return -ENOTSUPP; ++ ++ if (test_bit(OPCODE1(insn), (unsigned long *)good_insns_32)) ++ return 0; ++ ++ if (insn->opcode.nbytes == 2) { ++ if (test_bit(OPCODE2(insn), (unsigned long *)good_2byte_insns)) ++ return 0; ++ } ++ ++ return -ENOTSUPP; ++} ++ ++/* ++ * Figure out which fixups arch_uprobe_post_xol() will need to perform, and ++ * annotate arch_uprobe->fixups accordingly. To start with, ++ * arch_uprobe->fixups is either zero or it reflects rip-related fixups. ++ */ ++static void prepare_fixups(struct arch_uprobe *auprobe, struct insn *insn) ++{ ++ bool fix_ip = true, fix_call = false; /* defaults */ ++ int reg; ++ ++ insn_get_opcode(insn); /* should be a nop */ ++ ++ switch (OPCODE1(insn)) { ++ case 0xc3: /* ret/lret */ ++ case 0xcb: ++ case 0xc2: ++ case 0xca: ++ /* ip is correct */ ++ fix_ip = false; ++ break; ++ case 0xe8: /* call relative - Fix return addr */ ++ fix_call = true; ++ break; ++ case 0x9a: /* call absolute - Fix return addr, not ip */ ++ fix_call = true; ++ fix_ip = false; ++ break; ++ case 0xff: ++ insn_get_modrm(insn); ++ reg = MODRM_REG(insn); ++ if (reg == 2 || reg == 3) { ++ /* call or lcall, indirect */ ++ /* Fix return addr; ip is correct. */ ++ fix_call = true; ++ fix_ip = false; ++ } else if (reg == 4 || reg == 5) { ++ /* jmp or ljmp, indirect */ ++ /* ip is correct. */ ++ fix_ip = false; ++ } ++ break; ++ case 0xea: /* jmp absolute -- ip is correct */ ++ fix_ip = false; ++ break; ++ default: ++ break; ++ } ++ if (fix_ip) ++ auprobe->fixups |= UPROBE_FIX_IP; ++ if (fix_call) ++ auprobe->fixups |= UPROBE_FIX_CALL; ++} ++ ++#ifdef CONFIG_X86_64 ++/* ++ * If arch_uprobe->insn doesn't use rip-relative addressing, return ++ * immediately. Otherwise, rewrite the instruction so that it accesses ++ * its memory operand indirectly through a scratch register. Set ++ * arch_uprobe->fixups and arch_uprobe->rip_rela_target_address ++ * accordingly. (The contents of the scratch register will be saved ++ * before we single-step the modified instruction, and restored ++ * afterward.) ++ * ++ * We do this because a rip-relative instruction can access only a ++ * relatively small area (+/- 2 GB from the instruction), and the XOL ++ * area typically lies beyond that area. At least for instructions ++ * that store to memory, we can't execute the original instruction ++ * and "fix things up" later, because the misdirected store could be ++ * disastrous. ++ * ++ * Some useful facts about rip-relative instructions: ++ * ++ * - There's always a modrm byte. ++ * - There's never a SIB byte. ++ * - The displacement is always 4 bytes. ++ */ ++static void ++handle_riprel_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, struct insn *insn) ++{ ++ u8 *cursor; ++ u8 reg; ++ ++ if (mm->context.ia32_compat) ++ return; ++ ++ auprobe->rip_rela_target_address = 0x0; ++ if (!insn_rip_relative(insn)) ++ return; ++ ++ /* ++ * insn_rip_relative() would have decoded rex_prefix, modrm. ++ * Clear REX.b bit (extension of MODRM.rm field): ++ * we want to encode rax/rcx, not r8/r9. ++ */ ++ if (insn->rex_prefix.nbytes) { ++ cursor = auprobe->insn + insn_offset_rex_prefix(insn); ++ *cursor &= 0xfe; /* Clearing REX.B bit */ ++ } ++ ++ /* ++ * Point cursor at the modrm byte. The next 4 bytes are the ++ * displacement. Beyond the displacement, for some instructions, ++ * is the immediate operand. ++ */ ++ cursor = auprobe->insn + insn_offset_modrm(insn); ++ insn_get_length(insn); ++ ++ /* ++ * Convert from rip-relative addressing to indirect addressing ++ * via a scratch register. Change the r/m field from 0x5 (%rip) ++ * to 0x0 (%rax) or 0x1 (%rcx), and squeeze out the offset field. ++ */ ++ reg = MODRM_REG(insn); ++ if (reg == 0) { ++ /* ++ * The register operand (if any) is either the A register ++ * (%rax, %eax, etc.) or (if the 0x4 bit is set in the ++ * REX prefix) %r8. In any case, we know the C register ++ * is NOT the register operand, so we use %rcx (register ++ * #1) for the scratch register. ++ */ ++ auprobe->fixups = UPROBE_FIX_RIP_CX; ++ /* Change modrm from 00 000 101 to 00 000 001. */ ++ *cursor = 0x1; ++ } else { ++ /* Use %rax (register #0) for the scratch register. */ ++ auprobe->fixups = UPROBE_FIX_RIP_AX; ++ /* Change modrm from 00 xxx 101 to 00 xxx 000 */ ++ *cursor = (reg << 3); ++ } ++ ++ /* Target address = address of next instruction + (signed) offset */ ++ auprobe->rip_rela_target_address = (long)insn->length + insn->displacement.value; ++ ++ /* Displacement field is gone; slide immediate field (if any) over. */ ++ if (insn->immediate.nbytes) { ++ cursor++; ++ memmove(cursor, cursor + insn->displacement.nbytes, insn->immediate.nbytes); ++ } ++ return; ++} ++ ++static int validate_insn_64bits(struct arch_uprobe *auprobe, struct insn *insn) ++{ ++ insn_init(insn, auprobe->insn, true); ++ ++ /* Skip good instruction prefixes; reject "bad" ones. */ ++ insn_get_opcode(insn); ++ if (is_prefix_bad(insn)) ++ return -ENOTSUPP; ++ ++ if (test_bit(OPCODE1(insn), (unsigned long *)good_insns_64)) ++ return 0; ++ ++ if (insn->opcode.nbytes == 2) { ++ if (test_bit(OPCODE2(insn), (unsigned long *)good_2byte_insns)) ++ return 0; ++ } ++ return -ENOTSUPP; ++} ++ ++static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm, struct insn *insn) ++{ ++ if (mm->context.ia32_compat) ++ return validate_insn_32bits(auprobe, insn); ++ return validate_insn_64bits(auprobe, insn); ++} ++#else /* 32-bit: */ ++static void handle_riprel_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, struct insn *insn) ++{ ++ /* No RIP-relative addressing on 32-bit */ ++} ++ ++static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm, struct insn *insn) ++{ ++ return validate_insn_32bits(auprobe, insn); ++} ++#endif /* CONFIG_X86_64 */ ++ ++/** ++ * arch_uprobe_analyze_insn - instruction analysis including validity and fixups. ++ * @mm: the probed address space. ++ * @arch_uprobe: the probepoint information. ++ * Return 0 on success or a -ve number on error. ++ */ ++int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm) ++{ ++ int ret; ++ struct insn insn; ++ ++ auprobe->fixups = 0; ++ ret = validate_insn_bits(auprobe, mm, &insn); ++ if (ret != 0) ++ return ret; ++ ++ handle_riprel_insn(auprobe, mm, &insn); ++ prepare_fixups(auprobe, &insn); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_X86_64 ++/* ++ * If we're emulating a rip-relative instruction, save the contents ++ * of the scratch register and store the target address in that register. ++ */ ++static void ++pre_xol_rip_insn(struct arch_uprobe *auprobe, struct pt_regs *regs, ++ struct arch_uprobe_task *autask) ++{ ++ if (auprobe->fixups & UPROBE_FIX_RIP_AX) { ++ autask->saved_scratch_register = regs->ax; ++ regs->ax = current->utask->vaddr; ++ regs->ax += auprobe->rip_rela_target_address; ++ } else if (auprobe->fixups & UPROBE_FIX_RIP_CX) { ++ autask->saved_scratch_register = regs->cx; ++ regs->cx = current->utask->vaddr; ++ regs->cx += auprobe->rip_rela_target_address; ++ } ++} ++#else ++static void ++pre_xol_rip_insn(struct arch_uprobe *auprobe, struct pt_regs *regs, ++ struct arch_uprobe_task *autask) ++{ ++ /* No RIP-relative addressing on 32-bit */ ++} ++#endif ++ ++/* ++ * arch_uprobe_pre_xol - prepare to execute out of line. ++ * @auprobe: the probepoint information. ++ * @regs: reflects the saved user state of current task. ++ */ ++int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) ++{ ++ struct arch_uprobe_task *autask; ++ ++ autask = ¤t->utask->autask; ++ autask->saved_trap_nr = current->thread.trap_nr; ++ current->thread.trap_nr = UPROBE_TRAP_NR; ++ regs->ip = current->utask->xol_vaddr; ++ pre_xol_rip_insn(auprobe, regs, autask); ++ ++ return 0; ++} ++ ++/* ++ * This function is called by arch_uprobe_post_xol() to adjust the return ++ * address pushed by a call instruction executed out of line. ++ */ ++static int adjust_ret_addr(unsigned long sp, long correction) ++{ ++ int rasize, ncopied; ++ long ra = 0; ++ ++ if (is_ia32_task()) ++ rasize = 4; ++ else ++ rasize = 8; ++ ++ ncopied = copy_from_user(&ra, (void __user *)sp, rasize); ++ if (unlikely(ncopied)) ++ return -EFAULT; ++ ++ ra += correction; ++ ncopied = copy_to_user((void __user *)sp, &ra, rasize); ++ if (unlikely(ncopied)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_X86_64 ++static bool is_riprel_insn(struct arch_uprobe *auprobe) ++{ ++ return ((auprobe->fixups & (UPROBE_FIX_RIP_AX | UPROBE_FIX_RIP_CX)) != 0); ++} ++ ++static void ++handle_riprel_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs, long *correction) ++{ ++ if (is_riprel_insn(auprobe)) { ++ struct arch_uprobe_task *autask; ++ ++ autask = ¤t->utask->autask; ++ if (auprobe->fixups & UPROBE_FIX_RIP_AX) ++ regs->ax = autask->saved_scratch_register; ++ else ++ regs->cx = autask->saved_scratch_register; ++ ++ /* ++ * The original instruction includes a displacement, and so ++ * is 4 bytes longer than what we've just single-stepped. ++ * Fall through to handle stuff like "jmpq *...(%rip)" and ++ * "callq *...(%rip)". ++ */ ++ if (correction) ++ *correction += 4; ++ } ++} ++#else ++static void ++handle_riprel_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs, long *correction) ++{ ++ /* No RIP-relative addressing on 32-bit */ ++} ++#endif ++ ++/* ++ * If xol insn itself traps and generates a signal(Say, ++ * SIGILL/SIGSEGV/etc), then detect the case where a singlestepped ++ * instruction jumps back to its own address. It is assumed that anything ++ * like do_page_fault/do_trap/etc sets thread.trap_nr != -1. ++ * ++ * arch_uprobe_pre_xol/arch_uprobe_post_xol save/restore thread.trap_nr, ++ * arch_uprobe_xol_was_trapped() simply checks that ->trap_nr is not equal to ++ * UPROBE_TRAP_NR == -1 set by arch_uprobe_pre_xol(). ++ */ ++bool arch_uprobe_xol_was_trapped(struct task_struct *t) ++{ ++ if (t->thread.trap_nr != UPROBE_TRAP_NR) ++ return true; ++ ++ return false; ++} ++ ++/* ++ * Called after single-stepping. To avoid the SMP problems that can ++ * occur when we temporarily put back the original opcode to ++ * single-step, we single-stepped a copy of the instruction. ++ * ++ * This function prepares to resume execution after the single-step. ++ * We have to fix things up as follows: ++ * ++ * Typically, the new ip is relative to the copied instruction. We need ++ * to make it relative to the original instruction (FIX_IP). Exceptions ++ * are return instructions and absolute or indirect jump or call instructions. ++ * ++ * If the single-stepped instruction was a call, the return address that ++ * is atop the stack is the address following the copied instruction. We ++ * need to make it the address following the original instruction (FIX_CALL). ++ * ++ * If the original instruction was a rip-relative instruction such as ++ * "movl %edx,0xnnnn(%rip)", we have instead executed an equivalent ++ * instruction using a scratch register -- e.g., "movl %edx,(%rax)". ++ * We need to restore the contents of the scratch register and adjust ++ * the ip, keeping in mind that the instruction we executed is 4 bytes ++ * shorter than the original instruction (since we squeezed out the offset ++ * field). (FIX_RIP_AX or FIX_RIP_CX) ++ */ ++int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) ++{ ++ struct uprobe_task *utask; ++ long correction; ++ int result = 0; ++ ++ WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR); ++ ++ utask = current->utask; ++ current->thread.trap_nr = utask->autask.saved_trap_nr; ++ correction = (long)(utask->vaddr - utask->xol_vaddr); ++ handle_riprel_post_xol(auprobe, regs, &correction); ++ if (auprobe->fixups & UPROBE_FIX_IP) ++ regs->ip += correction; ++ ++ if (auprobe->fixups & UPROBE_FIX_CALL) ++ result = adjust_ret_addr(regs->sp, correction); ++ ++ return result; ++} ++ ++/* callback routine for handling exceptions. */ ++int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data) ++{ ++ struct die_args *args = data; ++ struct pt_regs *regs = args->regs; ++ int ret = NOTIFY_DONE; ++ ++ /* We are only interested in userspace traps */ ++ if (regs && !user_mode_vm(regs)) ++ return NOTIFY_DONE; ++ ++ switch (val) { ++ case DIE_INT3: ++ if (uprobe_pre_sstep_notifier(regs)) ++ ret = NOTIFY_STOP; ++ ++ break; ++ ++ case DIE_DEBUG: ++ if (uprobe_post_sstep_notifier(regs)) ++ ret = NOTIFY_STOP; ++ ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ ++/* ++ * This function gets called when XOL instruction either gets trapped or ++ * the thread has a fatal signal, so reset the instruction pointer to its ++ * probed address. ++ */ ++void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) ++{ ++ struct uprobe_task *utask = current->utask; ++ ++ current->thread.trap_nr = utask->autask.saved_trap_nr; ++ handle_riprel_post_xol(auprobe, regs, NULL); ++ instruction_pointer_set(regs, utask->vaddr); ++} ++ ++/* ++ * Skip these instructions as per the currently known x86 ISA. ++ * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 } ++ */ ++bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) ++{ ++ int i; ++ ++ for (i = 0; i < MAX_UINSN_BYTES; i++) { ++ if ((auprobe->insn[i] == 0x66)) ++ continue; ++ ++ if (auprobe->insn[i] == 0x90) ++ return true; ++ ++ if (i == (MAX_UINSN_BYTES - 1)) ++ break; ++ ++ if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x1f)) ++ return true; ++ ++ if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x19)) ++ return true; ++ ++ if ((auprobe->insn[i] == 0x87) && (auprobe->insn[i+1] == 0xc0)) ++ return true; ++ ++ break; ++ } ++ return false; ++} +diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h +index 3cc3062..26574c7 100644 +--- a/include/linux/mm_types.h ++++ b/include/linux/mm_types.h +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -388,6 +389,7 @@ struct mm_struct { + #ifdef CONFIG_CPUMASK_OFFSTACK + struct cpumask cpumask_allocation; + #endif ++ struct uprobes_state uprobes_state; + }; + + static inline void mm_init_cpumask(struct mm_struct *mm) +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 81a173c..cff94cd 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -1617,6 +1617,10 @@ struct task_struct { + #ifdef CONFIG_HAVE_HW_BREAKPOINT + atomic_t ptrace_bp_refcnt; + #endif ++#ifdef CONFIG_UPROBES ++ struct uprobe_task *utask; ++ int uprobe_srcu_id; ++#endif + }; + + /* Future-safe accessor for struct task_struct's cpus_allowed. */ +diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h +new file mode 100644 +index 0000000..efe4b33 +--- /dev/null ++++ b/include/linux/uprobes.h +@@ -0,0 +1,165 @@ ++#ifndef _LINUX_UPROBES_H ++#define _LINUX_UPROBES_H ++/* ++ * User-space Probes (UProbes) ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) IBM Corporation, 2008-2012 ++ * Authors: ++ * Srikar Dronamraju ++ * Jim Keniston ++ * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra ++ */ ++ ++#include ++#include ++ ++struct vm_area_struct; ++struct mm_struct; ++struct inode; ++ ++#ifdef CONFIG_ARCH_SUPPORTS_UPROBES ++# include ++#endif ++ ++/* flags that denote/change uprobes behaviour */ ++ ++/* Have a copy of original instruction */ ++#define UPROBE_COPY_INSN 0x1 ++ ++/* Dont run handlers when first register/ last unregister in progress*/ ++#define UPROBE_RUN_HANDLER 0x2 ++/* Can skip singlestep */ ++#define UPROBE_SKIP_SSTEP 0x4 ++ ++struct uprobe_consumer { ++ int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs); ++ /* ++ * filter is optional; If a filter exists, handler is run ++ * if and only if filter returns true. ++ */ ++ bool (*filter)(struct uprobe_consumer *self, struct task_struct *task); ++ ++ struct uprobe_consumer *next; ++}; ++ ++#ifdef CONFIG_UPROBES ++enum uprobe_task_state { ++ UTASK_RUNNING, ++ UTASK_BP_HIT, ++ UTASK_SSTEP, ++ UTASK_SSTEP_ACK, ++ UTASK_SSTEP_TRAPPED, ++}; ++ ++/* ++ * uprobe_task: Metadata of a task while it singlesteps. ++ */ ++struct uprobe_task { ++ enum uprobe_task_state state; ++ struct arch_uprobe_task autask; ++ ++ struct uprobe *active_uprobe; ++ ++ unsigned long xol_vaddr; ++ unsigned long vaddr; ++}; ++ ++/* ++ * On a breakpoint hit, thread contests for a slot. It frees the ++ * slot after singlestep. Currently a fixed number of slots are ++ * allocated. ++ */ ++struct xol_area { ++ wait_queue_head_t wq; /* if all slots are busy */ ++ atomic_t slot_count; /* number of in-use slots */ ++ unsigned long *bitmap; /* 0 = free slot */ ++ struct page *page; ++ ++ /* ++ * We keep the vma's vm_start rather than a pointer to the vma ++ * itself. The probed process or a naughty kernel module could make ++ * the vma go away, and we must handle that reasonably gracefully. ++ */ ++ unsigned long vaddr; /* Page(s) of instruction slots */ ++}; ++ ++struct uprobes_state { ++ struct xol_area *xol_area; ++ atomic_t count; ++}; ++extern int __weak set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); ++extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr, bool verify); ++extern bool __weak is_swbp_insn(uprobe_opcode_t *insn); ++extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); ++extern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); ++extern int uprobe_mmap(struct vm_area_struct *vma); ++extern void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end); ++extern void uprobe_free_utask(struct task_struct *t); ++extern void uprobe_copy_process(struct task_struct *t); ++extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs); ++extern int uprobe_post_sstep_notifier(struct pt_regs *regs); ++extern int uprobe_pre_sstep_notifier(struct pt_regs *regs); ++extern void uprobe_notify_resume(struct pt_regs *regs); ++extern bool uprobe_deny_signal(void); ++extern bool __weak arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs); ++extern void uprobe_clear_state(struct mm_struct *mm); ++extern void uprobe_reset_state(struct mm_struct *mm); ++#else /* !CONFIG_UPROBES */ ++struct uprobes_state { ++}; ++static inline int ++uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc) ++{ ++ return -ENOSYS; ++} ++static inline void ++uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc) ++{ ++} ++static inline int uprobe_mmap(struct vm_area_struct *vma) ++{ ++ return 0; ++} ++static inline void ++uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) ++{ ++} ++static inline void uprobe_notify_resume(struct pt_regs *regs) ++{ ++} ++static inline bool uprobe_deny_signal(void) ++{ ++ return false; ++} ++static inline unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) ++{ ++ return 0; ++} ++static inline void uprobe_free_utask(struct task_struct *t) ++{ ++} ++static inline void uprobe_copy_process(struct task_struct *t) ++{ ++} ++static inline void uprobe_clear_state(struct mm_struct *mm) ++{ ++} ++static inline void uprobe_reset_state(struct mm_struct *mm) ++{ ++} ++#endif /* !CONFIG_UPROBES */ ++#endif /* _LINUX_UPROBES_H */ +diff --git a/kernel/events/Makefile b/kernel/events/Makefile +index 22d901f..103f5d1 100644 +--- a/kernel/events/Makefile ++++ b/kernel/events/Makefile +@@ -3,4 +3,7 @@ CFLAGS_REMOVE_core.o = -pg + endif + + obj-y := core.o ring_buffer.o callchain.o ++ + obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o ++obj-$(CONFIG_UPROBES) += uprobes.o ++ +diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c +new file mode 100644 +index 0000000..985be4d +--- /dev/null ++++ b/kernel/events/uprobes.c +@@ -0,0 +1,1667 @@ ++/* ++ * User-space Probes (UProbes) ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) IBM Corporation, 2008-2012 ++ * Authors: ++ * Srikar Dronamraju ++ * Jim Keniston ++ * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra ++ */ ++ ++#include ++#include ++#include /* read_mapping_page */ ++#include ++#include ++#include /* anon_vma_prepare */ ++#include /* set_pte_at_notify */ ++#include /* try_to_free_swap */ ++#include /* user_enable_single_step */ ++#include /* notifier mechanism */ ++ ++#include ++ ++#define UINSNS_PER_PAGE (PAGE_SIZE/UPROBE_XOL_SLOT_BYTES) ++#define MAX_UPROBE_XOL_SLOTS UINSNS_PER_PAGE ++ ++static struct srcu_struct uprobes_srcu; ++static struct rb_root uprobes_tree = RB_ROOT; ++ ++static DEFINE_SPINLOCK(uprobes_treelock); /* serialize rbtree access */ ++ ++#define UPROBES_HASH_SZ 13 ++ ++/* serialize (un)register */ ++static struct mutex uprobes_mutex[UPROBES_HASH_SZ]; ++ ++#define uprobes_hash(v) (&uprobes_mutex[((unsigned long)(v)) % UPROBES_HASH_SZ]) ++ ++/* serialize uprobe->pending_list */ ++static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ]; ++#define uprobes_mmap_hash(v) (&uprobes_mmap_mutex[((unsigned long)(v)) % UPROBES_HASH_SZ]) ++ ++/* ++ * uprobe_events allows us to skip the uprobe_mmap if there are no uprobe ++ * events active at this time. Probably a fine grained per inode count is ++ * better? ++ */ ++static atomic_t uprobe_events = ATOMIC_INIT(0); ++ ++/* ++ * Maintain a temporary per vma info that can be used to search if a vma ++ * has already been handled. This structure is introduced since extending ++ * vm_area_struct wasnt recommended. ++ */ ++struct vma_info { ++ struct list_head probe_list; ++ struct mm_struct *mm; ++ loff_t vaddr; ++}; ++ ++struct uprobe { ++ struct rb_node rb_node; /* node in the rb tree */ ++ atomic_t ref; ++ struct rw_semaphore consumer_rwsem; ++ struct list_head pending_list; ++ struct uprobe_consumer *consumers; ++ struct inode *inode; /* Also hold a ref to inode */ ++ loff_t offset; ++ int flags; ++ struct arch_uprobe arch; ++}; ++ ++/* ++ * valid_vma: Verify if the specified vma is an executable vma ++ * Relax restrictions while unregistering: vm_flags might have ++ * changed after breakpoint was inserted. ++ * - is_register: indicates if we are in register context. ++ * - Return 1 if the specified virtual address is in an ++ * executable vma. ++ */ ++static bool valid_vma(struct vm_area_struct *vma, bool is_register) ++{ ++ if (!vma->vm_file) ++ return false; ++ ++ if (!is_register) ++ return true; ++ ++ if ((vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) == (VM_READ|VM_EXEC)) ++ return true; ++ ++ return false; ++} ++ ++static loff_t vma_address(struct vm_area_struct *vma, loff_t offset) ++{ ++ loff_t vaddr; ++ ++ vaddr = vma->vm_start + offset; ++ vaddr -= vma->vm_pgoff << PAGE_SHIFT; ++ ++ return vaddr; ++} ++ ++/** ++ * __replace_page - replace page in vma by new page. ++ * based on replace_page in mm/ksm.c ++ * ++ * @vma: vma that holds the pte pointing to page ++ * @page: the cowed page we are replacing by kpage ++ * @kpage: the modified page we replace page by ++ * ++ * Returns 0 on success, -EFAULT on failure. ++ */ ++static int __replace_page(struct vm_area_struct *vma, struct page *page, struct page *kpage) ++{ ++ struct mm_struct *mm = vma->vm_mm; ++ pgd_t *pgd; ++ pud_t *pud; ++ pmd_t *pmd; ++ pte_t *ptep; ++ spinlock_t *ptl; ++ unsigned long addr; ++ int err = -EFAULT; ++ ++ addr = page_address_in_vma(page, vma); ++ if (addr == -EFAULT) ++ goto out; ++ ++ pgd = pgd_offset(mm, addr); ++ if (!pgd_present(*pgd)) ++ goto out; ++ ++ pud = pud_offset(pgd, addr); ++ if (!pud_present(*pud)) ++ goto out; ++ ++ pmd = pmd_offset(pud, addr); ++ if (!pmd_present(*pmd)) ++ goto out; ++ ++ ptep = pte_offset_map_lock(mm, pmd, addr, &ptl); ++ if (!ptep) ++ goto out; ++ ++ get_page(kpage); ++ page_add_new_anon_rmap(kpage, vma, addr); ++ ++ if (!PageAnon(page)) { ++ dec_mm_counter(mm, MM_FILEPAGES); ++ inc_mm_counter(mm, MM_ANONPAGES); ++ } ++ ++ flush_cache_page(vma, addr, pte_pfn(*ptep)); ++ ptep_clear_flush(vma, addr, ptep); ++ set_pte_at_notify(mm, addr, ptep, mk_pte(kpage, vma->vm_page_prot)); ++ ++ page_remove_rmap(page); ++ if (!page_mapped(page)) ++ try_to_free_swap(page); ++ put_page(page); ++ pte_unmap_unlock(ptep, ptl); ++ err = 0; ++ ++out: ++ return err; ++} ++ ++/** ++ * is_swbp_insn - check if instruction is breakpoint instruction. ++ * @insn: instruction to be checked. ++ * Default implementation of is_swbp_insn ++ * Returns true if @insn is a breakpoint instruction. ++ */ ++bool __weak is_swbp_insn(uprobe_opcode_t *insn) ++{ ++ return *insn == UPROBE_SWBP_INSN; ++} ++ ++/* ++ * NOTE: ++ * Expect the breakpoint instruction to be the smallest size instruction for ++ * the architecture. If an arch has variable length instruction and the ++ * breakpoint instruction is not of the smallest length instruction ++ * supported by that architecture then we need to modify read_opcode / ++ * write_opcode accordingly. This would never be a problem for archs that ++ * have fixed length instructions. ++ */ ++ ++/* ++ * write_opcode - write the opcode at a given virtual address. ++ * @auprobe: arch breakpointing information. ++ * @mm: the probed process address space. ++ * @vaddr: the virtual address to store the opcode. ++ * @opcode: opcode to be written at @vaddr. ++ * ++ * Called with mm->mmap_sem held (for read and with a reference to ++ * mm). ++ * ++ * For mm @mm, write the opcode at @vaddr. ++ * Return 0 (success) or a negative errno. ++ */ ++static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, ++ unsigned long vaddr, uprobe_opcode_t opcode) ++{ ++ struct page *old_page, *new_page; ++ struct address_space *mapping; ++ void *vaddr_old, *vaddr_new; ++ struct vm_area_struct *vma; ++ struct uprobe *uprobe; ++ loff_t addr; ++ int ret; ++ ++ /* Read the page with vaddr into memory */ ++ ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma); ++ if (ret <= 0) ++ return ret; ++ ++ ret = -EINVAL; ++ ++ /* ++ * We are interested in text pages only. Our pages of interest ++ * should be mapped for read and execute only. We desist from ++ * adding probes in write mapped pages since the breakpoints ++ * might end up in the file copy. ++ */ ++ if (!valid_vma(vma, is_swbp_insn(&opcode))) ++ goto put_out; ++ ++ uprobe = container_of(auprobe, struct uprobe, arch); ++ mapping = uprobe->inode->i_mapping; ++ if (mapping != vma->vm_file->f_mapping) ++ goto put_out; ++ ++ addr = vma_address(vma, uprobe->offset); ++ if (vaddr != (unsigned long)addr) ++ goto put_out; ++ ++ ret = -ENOMEM; ++ new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr); ++ if (!new_page) ++ goto put_out; ++ ++ __SetPageUptodate(new_page); ++ ++ /* ++ * lock page will serialize against do_wp_page()'s ++ * PageAnon() handling ++ */ ++ lock_page(old_page); ++ /* copy the page now that we've got it stable */ ++ vaddr_old = kmap_atomic(old_page); ++ vaddr_new = kmap_atomic(new_page); ++ ++ memcpy(vaddr_new, vaddr_old, PAGE_SIZE); ++ ++ /* poke the new insn in, ASSUMES we don't cross page boundary */ ++ vaddr &= ~PAGE_MASK; ++ BUG_ON(vaddr + UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); ++ memcpy(vaddr_new + vaddr, &opcode, UPROBE_SWBP_INSN_SIZE); ++ ++ kunmap_atomic(vaddr_new); ++ kunmap_atomic(vaddr_old); ++ ++ ret = anon_vma_prepare(vma); ++ if (ret) ++ goto unlock_out; ++ ++ lock_page(new_page); ++ ret = __replace_page(vma, old_page, new_page); ++ unlock_page(new_page); ++ ++unlock_out: ++ unlock_page(old_page); ++ page_cache_release(new_page); ++ ++put_out: ++ put_page(old_page); ++ ++ return ret; ++} ++ ++/** ++ * read_opcode - read the opcode at a given virtual address. ++ * @mm: the probed process address space. ++ * @vaddr: the virtual address to read the opcode. ++ * @opcode: location to store the read opcode. ++ * ++ * Called with mm->mmap_sem held (for read and with a reference to ++ * mm. ++ * ++ * For mm @mm, read the opcode at @vaddr and store it in @opcode. ++ * Return 0 (success) or a negative errno. ++ */ ++static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t *opcode) ++{ ++ struct page *page; ++ void *vaddr_new; ++ int ret; ++ ++ ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &page, NULL); ++ if (ret <= 0) ++ return ret; ++ ++ lock_page(page); ++ vaddr_new = kmap_atomic(page); ++ vaddr &= ~PAGE_MASK; ++ memcpy(opcode, vaddr_new + vaddr, UPROBE_SWBP_INSN_SIZE); ++ kunmap_atomic(vaddr_new); ++ unlock_page(page); ++ ++ put_page(page); ++ ++ return 0; ++} ++ ++static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) ++{ ++ uprobe_opcode_t opcode; ++ int result; ++ ++ result = read_opcode(mm, vaddr, &opcode); ++ if (result) ++ return result; ++ ++ if (is_swbp_insn(&opcode)) ++ return 1; ++ ++ return 0; ++} ++ ++/** ++ * set_swbp - store breakpoint at a given address. ++ * @auprobe: arch specific probepoint information. ++ * @mm: the probed process address space. ++ * @vaddr: the virtual address to insert the opcode. ++ * ++ * For mm @mm, store the breakpoint instruction at @vaddr. ++ * Return 0 (success) or a negative errno. ++ */ ++int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) ++{ ++ int result; ++ ++ result = is_swbp_at_addr(mm, vaddr); ++ if (result == 1) ++ return -EEXIST; ++ ++ if (result) ++ return result; ++ ++ return write_opcode(auprobe, mm, vaddr, UPROBE_SWBP_INSN); ++} ++ ++/** ++ * set_orig_insn - Restore the original instruction. ++ * @mm: the probed process address space. ++ * @auprobe: arch specific probepoint information. ++ * @vaddr: the virtual address to insert the opcode. ++ * @verify: if true, verify existance of breakpoint instruction. ++ * ++ * For mm @mm, restore the original opcode (opcode) at @vaddr. ++ * Return 0 (success) or a negative errno. ++ */ ++int __weak ++set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr, bool verify) ++{ ++ if (verify) { ++ int result; ++ ++ result = is_swbp_at_addr(mm, vaddr); ++ if (!result) ++ return -EINVAL; ++ ++ if (result != 1) ++ return result; ++ } ++ return write_opcode(auprobe, mm, vaddr, *(uprobe_opcode_t *)auprobe->insn); ++} ++ ++static int match_uprobe(struct uprobe *l, struct uprobe *r) ++{ ++ if (l->inode < r->inode) ++ return -1; ++ ++ if (l->inode > r->inode) ++ return 1; ++ ++ if (l->offset < r->offset) ++ return -1; ++ ++ if (l->offset > r->offset) ++ return 1; ++ ++ return 0; ++} ++ ++static struct uprobe *__find_uprobe(struct inode *inode, loff_t offset) ++{ ++ struct uprobe u = { .inode = inode, .offset = offset }; ++ struct rb_node *n = uprobes_tree.rb_node; ++ struct uprobe *uprobe; ++ int match; ++ ++ while (n) { ++ uprobe = rb_entry(n, struct uprobe, rb_node); ++ match = match_uprobe(&u, uprobe); ++ if (!match) { ++ atomic_inc(&uprobe->ref); ++ return uprobe; ++ } ++ ++ if (match < 0) ++ n = n->rb_left; ++ else ++ n = n->rb_right; ++ } ++ return NULL; ++} ++ ++/* ++ * Find a uprobe corresponding to a given inode:offset ++ * Acquires uprobes_treelock ++ */ ++static struct uprobe *find_uprobe(struct inode *inode, loff_t offset) ++{ ++ struct uprobe *uprobe; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&uprobes_treelock, flags); ++ uprobe = __find_uprobe(inode, offset); ++ spin_unlock_irqrestore(&uprobes_treelock, flags); ++ ++ return uprobe; ++} ++ ++static struct uprobe *__insert_uprobe(struct uprobe *uprobe) ++{ ++ struct rb_node **p = &uprobes_tree.rb_node; ++ struct rb_node *parent = NULL; ++ struct uprobe *u; ++ int match; ++ ++ while (*p) { ++ parent = *p; ++ u = rb_entry(parent, struct uprobe, rb_node); ++ match = match_uprobe(uprobe, u); ++ if (!match) { ++ atomic_inc(&u->ref); ++ return u; ++ } ++ ++ if (match < 0) ++ p = &parent->rb_left; ++ else ++ p = &parent->rb_right; ++ ++ } ++ ++ u = NULL; ++ rb_link_node(&uprobe->rb_node, parent, p); ++ rb_insert_color(&uprobe->rb_node, &uprobes_tree); ++ /* get access + creation ref */ ++ atomic_set(&uprobe->ref, 2); ++ ++ return u; ++} ++ ++/* ++ * Acquire uprobes_treelock. ++ * Matching uprobe already exists in rbtree; ++ * increment (access refcount) and return the matching uprobe. ++ * ++ * No matching uprobe; insert the uprobe in rb_tree; ++ * get a double refcount (access + creation) and return NULL. ++ */ ++static struct uprobe *insert_uprobe(struct uprobe *uprobe) ++{ ++ unsigned long flags; ++ struct uprobe *u; ++ ++ spin_lock_irqsave(&uprobes_treelock, flags); ++ u = __insert_uprobe(uprobe); ++ spin_unlock_irqrestore(&uprobes_treelock, flags); ++ ++ /* For now assume that the instruction need not be single-stepped */ ++ uprobe->flags |= UPROBE_SKIP_SSTEP; ++ ++ return u; ++} ++ ++static void put_uprobe(struct uprobe *uprobe) ++{ ++ if (atomic_dec_and_test(&uprobe->ref)) ++ kfree(uprobe); ++} ++ ++static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset) ++{ ++ struct uprobe *uprobe, *cur_uprobe; ++ ++ uprobe = kzalloc(sizeof(struct uprobe), GFP_KERNEL); ++ if (!uprobe) ++ return NULL; ++ ++ uprobe->inode = igrab(inode); ++ uprobe->offset = offset; ++ init_rwsem(&uprobe->consumer_rwsem); ++ INIT_LIST_HEAD(&uprobe->pending_list); ++ ++ /* add to uprobes_tree, sorted on inode:offset */ ++ cur_uprobe = insert_uprobe(uprobe); ++ ++ /* a uprobe exists for this inode:offset combination */ ++ if (cur_uprobe) { ++ kfree(uprobe); ++ uprobe = cur_uprobe; ++ iput(inode); ++ } else { ++ atomic_inc(&uprobe_events); ++ } ++ ++ return uprobe; ++} ++ ++static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs) ++{ ++ struct uprobe_consumer *uc; ++ ++ if (!(uprobe->flags & UPROBE_RUN_HANDLER)) ++ return; ++ ++ down_read(&uprobe->consumer_rwsem); ++ for (uc = uprobe->consumers; uc; uc = uc->next) { ++ if (!uc->filter || uc->filter(uc, current)) ++ uc->handler(uc, regs); ++ } ++ up_read(&uprobe->consumer_rwsem); ++} ++ ++/* Returns the previous consumer */ ++static struct uprobe_consumer * ++consumer_add(struct uprobe *uprobe, struct uprobe_consumer *uc) ++{ ++ down_write(&uprobe->consumer_rwsem); ++ uc->next = uprobe->consumers; ++ uprobe->consumers = uc; ++ up_write(&uprobe->consumer_rwsem); ++ ++ return uc->next; ++} ++ ++/* ++ * For uprobe @uprobe, delete the consumer @uc. ++ * Return true if the @uc is deleted successfully ++ * or return false. ++ */ ++static bool consumer_del(struct uprobe *uprobe, struct uprobe_consumer *uc) ++{ ++ struct uprobe_consumer **con; ++ bool ret = false; ++ ++ down_write(&uprobe->consumer_rwsem); ++ for (con = &uprobe->consumers; *con; con = &(*con)->next) { ++ if (*con == uc) { ++ *con = uc->next; ++ ret = true; ++ break; ++ } ++ } ++ up_write(&uprobe->consumer_rwsem); ++ ++ return ret; ++} ++ ++static int ++__copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *insn, ++ unsigned long nbytes, unsigned long offset) ++{ ++ struct file *filp = vma->vm_file; ++ struct page *page; ++ void *vaddr; ++ unsigned long off1; ++ unsigned long idx; ++ ++ if (!filp) ++ return -EINVAL; ++ ++ idx = (unsigned long)(offset >> PAGE_CACHE_SHIFT); ++ off1 = offset &= ~PAGE_MASK; ++ ++ /* ++ * Ensure that the page that has the original instruction is ++ * populated and in page-cache. ++ */ ++ page = read_mapping_page(mapping, idx, filp); ++ if (IS_ERR(page)) ++ return PTR_ERR(page); ++ ++ vaddr = kmap_atomic(page); ++ memcpy(insn, vaddr + off1, nbytes); ++ kunmap_atomic(vaddr); ++ page_cache_release(page); ++ ++ return 0; ++} ++ ++static int ++copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr) ++{ ++ struct address_space *mapping; ++ unsigned long nbytes; ++ int bytes; ++ ++ addr &= ~PAGE_MASK; ++ nbytes = PAGE_SIZE - addr; ++ mapping = uprobe->inode->i_mapping; ++ ++ /* Instruction at end of binary; copy only available bytes */ ++ if (uprobe->offset + MAX_UINSN_BYTES > uprobe->inode->i_size) ++ bytes = uprobe->inode->i_size - uprobe->offset; ++ else ++ bytes = MAX_UINSN_BYTES; ++ ++ /* Instruction at the page-boundary; copy bytes in second page */ ++ if (nbytes < bytes) { ++ if (__copy_insn(mapping, vma, uprobe->arch.insn + nbytes, ++ bytes - nbytes, uprobe->offset + nbytes)) ++ return -ENOMEM; ++ ++ bytes = nbytes; ++ } ++ return __copy_insn(mapping, vma, uprobe->arch.insn, bytes, uprobe->offset); ++} ++ ++/* ++ * How mm->uprobes_state.count gets updated ++ * uprobe_mmap() increments the count if ++ * - it successfully adds a breakpoint. ++ * - it cannot add a breakpoint, but sees that there is a underlying ++ * breakpoint (via a is_swbp_at_addr()). ++ * ++ * uprobe_munmap() decrements the count if ++ * - it sees a underlying breakpoint, (via is_swbp_at_addr) ++ * (Subsequent uprobe_unregister wouldnt find the breakpoint ++ * unless a uprobe_mmap kicks in, since the old vma would be ++ * dropped just after uprobe_munmap.) ++ * ++ * uprobe_register increments the count if: ++ * - it successfully adds a breakpoint. ++ * ++ * uprobe_unregister decrements the count if: ++ * - it sees a underlying breakpoint and removes successfully. ++ * (via is_swbp_at_addr) ++ * (Subsequent uprobe_munmap wouldnt find the breakpoint ++ * since there is no underlying breakpoint after the ++ * breakpoint removal.) ++ */ ++static int ++install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, ++ struct vm_area_struct *vma, loff_t vaddr) ++{ ++ unsigned long addr; ++ int ret; ++ ++ /* ++ * If probe is being deleted, unregister thread could be done with ++ * the vma-rmap-walk through. Adding a probe now can be fatal since ++ * nobody will be able to cleanup. Also we could be from fork or ++ * mremap path, where the probe might have already been inserted. ++ * Hence behave as if probe already existed. ++ */ ++ if (!uprobe->consumers) ++ return -EEXIST; ++ ++ addr = (unsigned long)vaddr; ++ ++ if (!(uprobe->flags & UPROBE_COPY_INSN)) { ++ ret = copy_insn(uprobe, vma, addr); ++ if (ret) ++ return ret; ++ ++ if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) ++ return -EEXIST; ++ ++ ret = arch_uprobe_analyze_insn(&uprobe->arch, mm); ++ if (ret) ++ return ret; ++ ++ uprobe->flags |= UPROBE_COPY_INSN; ++ } ++ ++ /* ++ * Ideally, should be updating the probe count after the breakpoint ++ * has been successfully inserted. However a thread could hit the ++ * breakpoint we just inserted even before the probe count is ++ * incremented. If this is the first breakpoint placed, breakpoint ++ * notifier might ignore uprobes and pass the trap to the thread. ++ * Hence increment before and decrement on failure. ++ */ ++ atomic_inc(&mm->uprobes_state.count); ++ ret = set_swbp(&uprobe->arch, mm, addr); ++ if (ret) ++ atomic_dec(&mm->uprobes_state.count); ++ ++ return ret; ++} ++ ++static void ++remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, loff_t vaddr) ++{ ++ if (!set_orig_insn(&uprobe->arch, mm, (unsigned long)vaddr, true)) ++ atomic_dec(&mm->uprobes_state.count); ++} ++ ++/* ++ * There could be threads that have hit the breakpoint and are entering the ++ * notifier code and trying to acquire the uprobes_treelock. The thread ++ * calling delete_uprobe() that is removing the uprobe from the rb_tree can ++ * race with these threads and might acquire the uprobes_treelock compared ++ * to some of the breakpoint hit threads. In such a case, the breakpoint ++ * hit threads will not find the uprobe. The current unregistering thread ++ * waits till all other threads have hit a breakpoint, to acquire the ++ * uprobes_treelock before the uprobe is removed from the rbtree. ++ */ ++static void delete_uprobe(struct uprobe *uprobe) ++{ ++ unsigned long flags; ++ ++ synchronize_srcu(&uprobes_srcu); ++ spin_lock_irqsave(&uprobes_treelock, flags); ++ rb_erase(&uprobe->rb_node, &uprobes_tree); ++ spin_unlock_irqrestore(&uprobes_treelock, flags); ++ iput(uprobe->inode); ++ put_uprobe(uprobe); ++ atomic_dec(&uprobe_events); ++} ++ ++static struct vma_info * ++__find_next_vma_info(struct address_space *mapping, struct list_head *head, ++ struct vma_info *vi, loff_t offset, bool is_register) ++{ ++ struct prio_tree_iter iter; ++ struct vm_area_struct *vma; ++ struct vma_info *tmpvi; ++ unsigned long pgoff; ++ int existing_vma; ++ loff_t vaddr; ++ ++ pgoff = offset >> PAGE_SHIFT; ++ ++ vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { ++ if (!valid_vma(vma, is_register)) ++ continue; ++ ++ existing_vma = 0; ++ vaddr = vma_address(vma, offset); ++ ++ list_for_each_entry(tmpvi, head, probe_list) { ++ if (tmpvi->mm == vma->vm_mm && tmpvi->vaddr == vaddr) { ++ existing_vma = 1; ++ break; ++ } ++ } ++ ++ /* ++ * Another vma needs a probe to be installed. However skip ++ * installing the probe if the vma is about to be unlinked. ++ */ ++ if (!existing_vma && atomic_inc_not_zero(&vma->vm_mm->mm_users)) { ++ vi->mm = vma->vm_mm; ++ vi->vaddr = vaddr; ++ list_add(&vi->probe_list, head); ++ ++ return vi; ++ } ++ } ++ ++ return NULL; ++} ++ ++/* ++ * Iterate in the rmap prio tree and find a vma where a probe has not ++ * yet been inserted. ++ */ ++static struct vma_info * ++find_next_vma_info(struct address_space *mapping, struct list_head *head, ++ loff_t offset, bool is_register) ++{ ++ struct vma_info *vi, *retvi; ++ ++ vi = kzalloc(sizeof(struct vma_info), GFP_KERNEL); ++ if (!vi) ++ return ERR_PTR(-ENOMEM); ++ ++ mutex_lock(&mapping->i_mmap_mutex); ++ retvi = __find_next_vma_info(mapping, head, vi, offset, is_register); ++ mutex_unlock(&mapping->i_mmap_mutex); ++ ++ if (!retvi) ++ kfree(vi); ++ ++ return retvi; ++} ++ ++static int register_for_each_vma(struct uprobe *uprobe, bool is_register) ++{ ++ struct list_head try_list; ++ struct vm_area_struct *vma; ++ struct address_space *mapping; ++ struct vma_info *vi, *tmpvi; ++ struct mm_struct *mm; ++ loff_t vaddr; ++ int ret; ++ ++ mapping = uprobe->inode->i_mapping; ++ INIT_LIST_HEAD(&try_list); ++ ++ ret = 0; ++ ++ for (;;) { ++ vi = find_next_vma_info(mapping, &try_list, uprobe->offset, is_register); ++ if (!vi) ++ break; ++ ++ if (IS_ERR(vi)) { ++ ret = PTR_ERR(vi); ++ break; ++ } ++ ++ mm = vi->mm; ++ down_read(&mm->mmap_sem); ++ vma = find_vma(mm, (unsigned long)vi->vaddr); ++ if (!vma || !valid_vma(vma, is_register)) { ++ list_del(&vi->probe_list); ++ kfree(vi); ++ up_read(&mm->mmap_sem); ++ mmput(mm); ++ continue; ++ } ++ vaddr = vma_address(vma, uprobe->offset); ++ if (vma->vm_file->f_mapping->host != uprobe->inode || ++ vaddr != vi->vaddr) { ++ list_del(&vi->probe_list); ++ kfree(vi); ++ up_read(&mm->mmap_sem); ++ mmput(mm); ++ continue; ++ } ++ ++ if (is_register) ++ ret = install_breakpoint(uprobe, mm, vma, vi->vaddr); ++ else ++ remove_breakpoint(uprobe, mm, vi->vaddr); ++ ++ up_read(&mm->mmap_sem); ++ mmput(mm); ++ if (is_register) { ++ if (ret && ret == -EEXIST) ++ ret = 0; ++ if (ret) ++ break; ++ } ++ } ++ ++ list_for_each_entry_safe(vi, tmpvi, &try_list, probe_list) { ++ list_del(&vi->probe_list); ++ kfree(vi); ++ } ++ ++ return ret; ++} ++ ++static int __uprobe_register(struct uprobe *uprobe) ++{ ++ return register_for_each_vma(uprobe, true); ++} ++ ++static void __uprobe_unregister(struct uprobe *uprobe) ++{ ++ if (!register_for_each_vma(uprobe, false)) ++ delete_uprobe(uprobe); ++ ++ /* TODO : cant unregister? schedule a worker thread */ ++} ++ ++/* ++ * uprobe_register - register a probe ++ * @inode: the file in which the probe has to be placed. ++ * @offset: offset from the start of the file. ++ * @uc: information on howto handle the probe.. ++ * ++ * Apart from the access refcount, uprobe_register() takes a creation ++ * refcount (thro alloc_uprobe) if and only if this @uprobe is getting ++ * inserted into the rbtree (i.e first consumer for a @inode:@offset ++ * tuple). Creation refcount stops uprobe_unregister from freeing the ++ * @uprobe even before the register operation is complete. Creation ++ * refcount is released when the last @uc for the @uprobe ++ * unregisters. ++ * ++ * Return errno if it cannot successully install probes ++ * else return 0 (success) ++ */ ++int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc) ++{ ++ struct uprobe *uprobe; ++ int ret; ++ ++ if (!inode || !uc || uc->next) ++ return -EINVAL; ++ ++ if (offset > i_size_read(inode)) ++ return -EINVAL; ++ ++ ret = 0; ++ mutex_lock(uprobes_hash(inode)); ++ uprobe = alloc_uprobe(inode, offset); ++ ++ if (uprobe && !consumer_add(uprobe, uc)) { ++ ret = __uprobe_register(uprobe); ++ if (ret) { ++ uprobe->consumers = NULL; ++ __uprobe_unregister(uprobe); ++ } else { ++ uprobe->flags |= UPROBE_RUN_HANDLER; ++ } ++ } ++ ++ mutex_unlock(uprobes_hash(inode)); ++ put_uprobe(uprobe); ++ ++ return ret; ++} ++ ++/* ++ * uprobe_unregister - unregister a already registered probe. ++ * @inode: the file in which the probe has to be removed. ++ * @offset: offset from the start of the file. ++ * @uc: identify which probe if multiple probes are colocated. ++ */ ++void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc) ++{ ++ struct uprobe *uprobe; ++ ++ if (!inode || !uc) ++ return; ++ ++ uprobe = find_uprobe(inode, offset); ++ if (!uprobe) ++ return; ++ ++ mutex_lock(uprobes_hash(inode)); ++ ++ if (consumer_del(uprobe, uc)) { ++ if (!uprobe->consumers) { ++ __uprobe_unregister(uprobe); ++ uprobe->flags &= ~UPROBE_RUN_HANDLER; ++ } ++ } ++ ++ mutex_unlock(uprobes_hash(inode)); ++ if (uprobe) ++ put_uprobe(uprobe); ++} ++ ++/* ++ * Of all the nodes that correspond to the given inode, return the node ++ * with the least offset. ++ */ ++static struct rb_node *find_least_offset_node(struct inode *inode) ++{ ++ struct uprobe u = { .inode = inode, .offset = 0}; ++ struct rb_node *n = uprobes_tree.rb_node; ++ struct rb_node *close_node = NULL; ++ struct uprobe *uprobe; ++ int match; ++ ++ while (n) { ++ uprobe = rb_entry(n, struct uprobe, rb_node); ++ match = match_uprobe(&u, uprobe); ++ ++ if (uprobe->inode == inode) ++ close_node = n; ++ ++ if (!match) ++ return close_node; ++ ++ if (match < 0) ++ n = n->rb_left; ++ else ++ n = n->rb_right; ++ } ++ ++ return close_node; ++} ++ ++/* ++ * For a given inode, build a list of probes that need to be inserted. ++ */ ++static void build_probe_list(struct inode *inode, struct list_head *head) ++{ ++ struct uprobe *uprobe; ++ unsigned long flags; ++ struct rb_node *n; ++ ++ spin_lock_irqsave(&uprobes_treelock, flags); ++ ++ n = find_least_offset_node(inode); ++ ++ for (; n; n = rb_next(n)) { ++ uprobe = rb_entry(n, struct uprobe, rb_node); ++ if (uprobe->inode != inode) ++ break; ++ ++ list_add(&uprobe->pending_list, head); ++ atomic_inc(&uprobe->ref); ++ } ++ ++ spin_unlock_irqrestore(&uprobes_treelock, flags); ++} ++ ++/* ++ * Called from mmap_region. ++ * called with mm->mmap_sem acquired. ++ * ++ * Return -ve no if we fail to insert probes and we cannot ++ * bail-out. ++ * Return 0 otherwise. i.e: ++ * ++ * - successful insertion of probes ++ * - (or) no possible probes to be inserted. ++ * - (or) insertion of probes failed but we can bail-out. ++ */ ++int uprobe_mmap(struct vm_area_struct *vma) ++{ ++ struct list_head tmp_list; ++ struct uprobe *uprobe, *u; ++ struct inode *inode; ++ int ret, count; ++ ++ if (!atomic_read(&uprobe_events) || !valid_vma(vma, true)) ++ return 0; ++ ++ inode = vma->vm_file->f_mapping->host; ++ if (!inode) ++ return 0; ++ ++ INIT_LIST_HEAD(&tmp_list); ++ mutex_lock(uprobes_mmap_hash(inode)); ++ build_probe_list(inode, &tmp_list); ++ ++ ret = 0; ++ count = 0; ++ ++ list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { ++ loff_t vaddr; ++ ++ list_del(&uprobe->pending_list); ++ if (!ret) { ++ vaddr = vma_address(vma, uprobe->offset); ++ ++ if (vaddr < vma->vm_start || vaddr >= vma->vm_end) { ++ put_uprobe(uprobe); ++ continue; ++ } ++ ++ ret = install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); ++ ++ /* Ignore double add: */ ++ if (ret == -EEXIST) { ++ ret = 0; ++ ++ if (!is_swbp_at_addr(vma->vm_mm, vaddr)) ++ continue; ++ ++ /* ++ * Unable to insert a breakpoint, but ++ * breakpoint lies underneath. Increment the ++ * probe count. ++ */ ++ atomic_inc(&vma->vm_mm->uprobes_state.count); ++ } ++ ++ if (!ret) ++ count++; ++ } ++ put_uprobe(uprobe); ++ } ++ ++ mutex_unlock(uprobes_mmap_hash(inode)); ++ ++ if (ret) ++ atomic_sub(count, &vma->vm_mm->uprobes_state.count); ++ ++ return ret; ++} ++ ++/* ++ * Called in context of a munmap of a vma. ++ */ ++void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) ++{ ++ struct list_head tmp_list; ++ struct uprobe *uprobe, *u; ++ struct inode *inode; ++ ++ if (!atomic_read(&uprobe_events) || !valid_vma(vma, false)) ++ return; ++ ++ if (!atomic_read(&vma->vm_mm->uprobes_state.count)) ++ return; ++ ++ inode = vma->vm_file->f_mapping->host; ++ if (!inode) ++ return; ++ ++ INIT_LIST_HEAD(&tmp_list); ++ mutex_lock(uprobes_mmap_hash(inode)); ++ build_probe_list(inode, &tmp_list); ++ ++ list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { ++ loff_t vaddr; ++ ++ list_del(&uprobe->pending_list); ++ vaddr = vma_address(vma, uprobe->offset); ++ ++ if (vaddr >= start && vaddr < end) { ++ /* ++ * An unregister could have removed the probe before ++ * unmap. So check before we decrement the count. ++ */ ++ if (is_swbp_at_addr(vma->vm_mm, vaddr) == 1) ++ atomic_dec(&vma->vm_mm->uprobes_state.count); ++ } ++ put_uprobe(uprobe); ++ } ++ mutex_unlock(uprobes_mmap_hash(inode)); ++} ++ ++/* Slot allocation for XOL */ ++static int xol_add_vma(struct xol_area *area) ++{ ++ struct mm_struct *mm; ++ int ret; ++ ++ area->page = alloc_page(GFP_HIGHUSER); ++ if (!area->page) ++ return -ENOMEM; ++ ++ ret = -EALREADY; ++ mm = current->mm; ++ ++ down_write(&mm->mmap_sem); ++ if (mm->uprobes_state.xol_area) ++ goto fail; ++ ++ ret = -ENOMEM; ++ ++ /* Try to map as high as possible, this is only a hint. */ ++ area->vaddr = get_unmapped_area(NULL, TASK_SIZE - PAGE_SIZE, PAGE_SIZE, 0, 0); ++ if (area->vaddr & ~PAGE_MASK) { ++ ret = area->vaddr; ++ goto fail; ++ } ++ ++ ret = install_special_mapping(mm, area->vaddr, PAGE_SIZE, ++ VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|VM_IO, &area->page); ++ if (ret) ++ goto fail; ++ ++ smp_wmb(); /* pairs with get_xol_area() */ ++ mm->uprobes_state.xol_area = area; ++ ret = 0; ++ ++fail: ++ up_write(&mm->mmap_sem); ++ if (ret) ++ __free_page(area->page); ++ ++ return ret; ++} ++ ++static struct xol_area *get_xol_area(struct mm_struct *mm) ++{ ++ struct xol_area *area; ++ ++ area = mm->uprobes_state.xol_area; ++ smp_read_barrier_depends(); /* pairs with wmb in xol_add_vma() */ ++ ++ return area; ++} ++ ++/* ++ * xol_alloc_area - Allocate process's xol_area. ++ * This area will be used for storing instructions for execution out of ++ * line. ++ * ++ * Returns the allocated area or NULL. ++ */ ++static struct xol_area *xol_alloc_area(void) ++{ ++ struct xol_area *area; ++ ++ area = kzalloc(sizeof(*area), GFP_KERNEL); ++ if (unlikely(!area)) ++ return NULL; ++ ++ area->bitmap = kzalloc(BITS_TO_LONGS(UINSNS_PER_PAGE) * sizeof(long), GFP_KERNEL); ++ ++ if (!area->bitmap) ++ goto fail; ++ ++ init_waitqueue_head(&area->wq); ++ if (!xol_add_vma(area)) ++ return area; ++ ++fail: ++ kfree(area->bitmap); ++ kfree(area); ++ ++ return get_xol_area(current->mm); ++} ++ ++/* ++ * uprobe_clear_state - Free the area allocated for slots. ++ */ ++void uprobe_clear_state(struct mm_struct *mm) ++{ ++ struct xol_area *area = mm->uprobes_state.xol_area; ++ ++ if (!area) ++ return; ++ ++ put_page(area->page); ++ kfree(area->bitmap); ++ kfree(area); ++} ++ ++/* ++ * uprobe_reset_state - Free the area allocated for slots. ++ */ ++void uprobe_reset_state(struct mm_struct *mm) ++{ ++ mm->uprobes_state.xol_area = NULL; ++ atomic_set(&mm->uprobes_state.count, 0); ++} ++ ++/* ++ * - search for a free slot. ++ */ ++static unsigned long xol_take_insn_slot(struct xol_area *area) ++{ ++ unsigned long slot_addr; ++ int slot_nr; ++ ++ do { ++ slot_nr = find_first_zero_bit(area->bitmap, UINSNS_PER_PAGE); ++ if (slot_nr < UINSNS_PER_PAGE) { ++ if (!test_and_set_bit(slot_nr, area->bitmap)) ++ break; ++ ++ slot_nr = UINSNS_PER_PAGE; ++ continue; ++ } ++ wait_event(area->wq, (atomic_read(&area->slot_count) < UINSNS_PER_PAGE)); ++ } while (slot_nr >= UINSNS_PER_PAGE); ++ ++ slot_addr = area->vaddr + (slot_nr * UPROBE_XOL_SLOT_BYTES); ++ atomic_inc(&area->slot_count); ++ ++ return slot_addr; ++} ++ ++/* ++ * xol_get_insn_slot - If was not allocated a slot, then ++ * allocate a slot. ++ * Returns the allocated slot address or 0. ++ */ ++static unsigned long xol_get_insn_slot(struct uprobe *uprobe, unsigned long slot_addr) ++{ ++ struct xol_area *area; ++ unsigned long offset; ++ void *vaddr; ++ ++ area = get_xol_area(current->mm); ++ if (!area) { ++ area = xol_alloc_area(); ++ if (!area) ++ return 0; ++ } ++ current->utask->xol_vaddr = xol_take_insn_slot(area); ++ ++ /* ++ * Initialize the slot if xol_vaddr points to valid ++ * instruction slot. ++ */ ++ if (unlikely(!current->utask->xol_vaddr)) ++ return 0; ++ ++ current->utask->vaddr = slot_addr; ++ offset = current->utask->xol_vaddr & ~PAGE_MASK; ++ vaddr = kmap_atomic(area->page); ++ memcpy(vaddr + offset, uprobe->arch.insn, MAX_UINSN_BYTES); ++ kunmap_atomic(vaddr); ++ ++ return current->utask->xol_vaddr; ++} ++ ++/* ++ * xol_free_insn_slot - If slot was earlier allocated by ++ * @xol_get_insn_slot(), make the slot available for ++ * subsequent requests. ++ */ ++static void xol_free_insn_slot(struct task_struct *tsk) ++{ ++ struct xol_area *area; ++ unsigned long vma_end; ++ unsigned long slot_addr; ++ ++ if (!tsk->mm || !tsk->mm->uprobes_state.xol_area || !tsk->utask) ++ return; ++ ++ slot_addr = tsk->utask->xol_vaddr; ++ ++ if (unlikely(!slot_addr || IS_ERR_VALUE(slot_addr))) ++ return; ++ ++ area = tsk->mm->uprobes_state.xol_area; ++ vma_end = area->vaddr + PAGE_SIZE; ++ if (area->vaddr <= slot_addr && slot_addr < vma_end) { ++ unsigned long offset; ++ int slot_nr; ++ ++ offset = slot_addr - area->vaddr; ++ slot_nr = offset / UPROBE_XOL_SLOT_BYTES; ++ if (slot_nr >= UINSNS_PER_PAGE) ++ return; ++ ++ clear_bit(slot_nr, area->bitmap); ++ atomic_dec(&area->slot_count); ++ if (waitqueue_active(&area->wq)) ++ wake_up(&area->wq); ++ ++ tsk->utask->xol_vaddr = 0; ++ } ++} ++ ++/** ++ * uprobe_get_swbp_addr - compute address of swbp given post-swbp regs ++ * @regs: Reflects the saved state of the task after it has hit a breakpoint ++ * instruction. ++ * Return the address of the breakpoint instruction. ++ */ ++unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs) ++{ ++ return instruction_pointer(regs) - UPROBE_SWBP_INSN_SIZE; ++} ++ ++/* ++ * Called with no locks held. ++ * Called in context of a exiting or a exec-ing thread. ++ */ ++void uprobe_free_utask(struct task_struct *t) ++{ ++ struct uprobe_task *utask = t->utask; ++ ++ if (t->uprobe_srcu_id != -1) ++ srcu_read_unlock_raw(&uprobes_srcu, t->uprobe_srcu_id); ++ ++ if (!utask) ++ return; ++ ++ if (utask->active_uprobe) ++ put_uprobe(utask->active_uprobe); ++ ++ xol_free_insn_slot(t); ++ kfree(utask); ++ t->utask = NULL; ++} ++ ++/* ++ * Called in context of a new clone/fork from copy_process. ++ */ ++void uprobe_copy_process(struct task_struct *t) ++{ ++ t->utask = NULL; ++ t->uprobe_srcu_id = -1; ++} ++ ++/* ++ * Allocate a uprobe_task object for the task. ++ * Called when the thread hits a breakpoint for the first time. ++ * ++ * Returns: ++ * - pointer to new uprobe_task on success ++ * - NULL otherwise ++ */ ++static struct uprobe_task *add_utask(void) ++{ ++ struct uprobe_task *utask; ++ ++ utask = kzalloc(sizeof *utask, GFP_KERNEL); ++ if (unlikely(!utask)) ++ return NULL; ++ ++ utask->active_uprobe = NULL; ++ current->utask = utask; ++ return utask; ++} ++ ++/* Prepare to single-step probed instruction out of line. */ ++static int ++pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long vaddr) ++{ ++ if (xol_get_insn_slot(uprobe, vaddr) && !arch_uprobe_pre_xol(&uprobe->arch, regs)) ++ return 0; ++ ++ return -EFAULT; ++} ++ ++/* ++ * If we are singlestepping, then ensure this thread is not connected to ++ * non-fatal signals until completion of singlestep. When xol insn itself ++ * triggers the signal, restart the original insn even if the task is ++ * already SIGKILL'ed (since coredump should report the correct ip). This ++ * is even more important if the task has a handler for SIGSEGV/etc, The ++ * _same_ instruction should be repeated again after return from the signal ++ * handler, and SSTEP can never finish in this case. ++ */ ++bool uprobe_deny_signal(void) ++{ ++ struct task_struct *t = current; ++ struct uprobe_task *utask = t->utask; ++ ++ if (likely(!utask || !utask->active_uprobe)) ++ return false; ++ ++ WARN_ON_ONCE(utask->state != UTASK_SSTEP); ++ ++ if (signal_pending(t)) { ++ spin_lock_irq(&t->sighand->siglock); ++ clear_tsk_thread_flag(t, TIF_SIGPENDING); ++ spin_unlock_irq(&t->sighand->siglock); ++ ++ if (__fatal_signal_pending(t) || arch_uprobe_xol_was_trapped(t)) { ++ utask->state = UTASK_SSTEP_TRAPPED; ++ set_tsk_thread_flag(t, TIF_UPROBE); ++ set_tsk_thread_flag(t, TIF_NOTIFY_RESUME); ++ } ++ } ++ ++ return true; ++} ++ ++/* ++ * Avoid singlestepping the original instruction if the original instruction ++ * is a NOP or can be emulated. ++ */ ++static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs) ++{ ++ if (arch_uprobe_skip_sstep(&uprobe->arch, regs)) ++ return true; ++ ++ uprobe->flags &= ~UPROBE_SKIP_SSTEP; ++ return false; ++} ++ ++/* ++ * Run handler and ask thread to singlestep. ++ * Ensure all non-fatal signals cannot interrupt thread while it singlesteps. ++ */ ++static void handle_swbp(struct pt_regs *regs) ++{ ++ struct vm_area_struct *vma; ++ struct uprobe_task *utask; ++ struct uprobe *uprobe; ++ struct mm_struct *mm; ++ unsigned long bp_vaddr; ++ ++ uprobe = NULL; ++ bp_vaddr = uprobe_get_swbp_addr(regs); ++ mm = current->mm; ++ down_read(&mm->mmap_sem); ++ vma = find_vma(mm, bp_vaddr); ++ ++ if (vma && vma->vm_start <= bp_vaddr && valid_vma(vma, false)) { ++ struct inode *inode; ++ loff_t offset; ++ ++ inode = vma->vm_file->f_mapping->host; ++ offset = bp_vaddr - vma->vm_start; ++ offset += (vma->vm_pgoff << PAGE_SHIFT); ++ uprobe = find_uprobe(inode, offset); ++ } ++ ++ srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id); ++ current->uprobe_srcu_id = -1; ++ up_read(&mm->mmap_sem); ++ ++ if (!uprobe) { ++ /* No matching uprobe; signal SIGTRAP. */ ++ send_sig(SIGTRAP, current, 0); ++ return; ++ } ++ ++ utask = current->utask; ++ if (!utask) { ++ utask = add_utask(); ++ /* Cannot allocate; re-execute the instruction. */ ++ if (!utask) ++ goto cleanup_ret; ++ } ++ utask->active_uprobe = uprobe; ++ handler_chain(uprobe, regs); ++ if (uprobe->flags & UPROBE_SKIP_SSTEP && can_skip_sstep(uprobe, regs)) ++ goto cleanup_ret; ++ ++ utask->state = UTASK_SSTEP; ++ if (!pre_ssout(uprobe, regs, bp_vaddr)) { ++ user_enable_single_step(current); ++ return; ++ } ++ ++cleanup_ret: ++ if (utask) { ++ utask->active_uprobe = NULL; ++ utask->state = UTASK_RUNNING; ++ } ++ if (uprobe) { ++ if (!(uprobe->flags & UPROBE_SKIP_SSTEP)) ++ ++ /* ++ * cannot singlestep; cannot skip instruction; ++ * re-execute the instruction. ++ */ ++ instruction_pointer_set(regs, bp_vaddr); ++ ++ put_uprobe(uprobe); ++ } ++} ++ ++/* ++ * Perform required fix-ups and disable singlestep. ++ * Allow pending signals to take effect. ++ */ ++static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs) ++{ ++ struct uprobe *uprobe; ++ ++ uprobe = utask->active_uprobe; ++ if (utask->state == UTASK_SSTEP_ACK) ++ arch_uprobe_post_xol(&uprobe->arch, regs); ++ else if (utask->state == UTASK_SSTEP_TRAPPED) ++ arch_uprobe_abort_xol(&uprobe->arch, regs); ++ else ++ WARN_ON_ONCE(1); ++ ++ put_uprobe(uprobe); ++ utask->active_uprobe = NULL; ++ utask->state = UTASK_RUNNING; ++ user_disable_single_step(current); ++ xol_free_insn_slot(current); ++ ++ spin_lock_irq(¤t->sighand->siglock); ++ recalc_sigpending(); /* see uprobe_deny_signal() */ ++ spin_unlock_irq(¤t->sighand->siglock); ++} ++ ++/* ++ * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag. (and on ++ * subsequent probe hits on the thread sets the state to UTASK_BP_HIT) and ++ * allows the thread to return from interrupt. ++ * ++ * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag and ++ * also sets the state to UTASK_SSTEP_ACK and allows the thread to return from ++ * interrupt. ++ * ++ * While returning to userspace, thread notices the TIF_UPROBE flag and calls ++ * uprobe_notify_resume(). ++ */ ++void uprobe_notify_resume(struct pt_regs *regs) ++{ ++ struct uprobe_task *utask; ++ ++ utask = current->utask; ++ if (!utask || utask->state == UTASK_BP_HIT) ++ handle_swbp(regs); ++ else ++ handle_singlestep(utask, regs); ++} ++ ++/* ++ * uprobe_pre_sstep_notifier gets called from interrupt context as part of ++ * notifier mechanism. Set TIF_UPROBE flag and indicate breakpoint hit. ++ */ ++int uprobe_pre_sstep_notifier(struct pt_regs *regs) ++{ ++ struct uprobe_task *utask; ++ ++ if (!current->mm || !atomic_read(¤t->mm->uprobes_state.count)) ++ /* task is currently not uprobed */ ++ return 0; ++ ++ utask = current->utask; ++ if (utask) ++ utask->state = UTASK_BP_HIT; ++ ++ set_thread_flag(TIF_UPROBE); ++ current->uprobe_srcu_id = srcu_read_lock_raw(&uprobes_srcu); ++ ++ return 1; ++} ++ ++/* ++ * uprobe_post_sstep_notifier gets called in interrupt context as part of notifier ++ * mechanism. Set TIF_UPROBE flag and indicate completion of singlestep. ++ */ ++int uprobe_post_sstep_notifier(struct pt_regs *regs) ++{ ++ struct uprobe_task *utask = current->utask; ++ ++ if (!current->mm || !utask || !utask->active_uprobe) ++ /* task is currently not uprobed */ ++ return 0; ++ ++ utask->state = UTASK_SSTEP_ACK; ++ set_thread_flag(TIF_UPROBE); ++ return 1; ++} ++ ++static struct notifier_block uprobe_exception_nb = { ++ .notifier_call = arch_uprobe_exception_notify, ++ .priority = INT_MAX-1, /* notified after kprobes, kgdb */ ++}; ++ ++static int __init init_uprobes(void) ++{ ++ int i; ++ ++ for (i = 0; i < UPROBES_HASH_SZ; i++) { ++ mutex_init(&uprobes_mutex[i]); ++ mutex_init(&uprobes_mmap_mutex[i]); ++ } ++ init_srcu_struct(&uprobes_srcu); ++ ++ return register_die_notifier(&uprobe_exception_nb); ++} ++module_init(init_uprobes); ++ ++static void __exit exit_uprobes(void) ++{ ++} ++module_exit(exit_uprobes); +diff --git a/kernel/fork.c b/kernel/fork.c +index c3eafd8..5b87e9f 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -68,6 +68,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -423,6 +424,9 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) + + if (retval) + goto out; ++ ++ if (file && uprobe_mmap(tmp)) ++ goto out; + } + /* a new mm has just been created */ + arch_dup_mmap(oldmm, mm); +@@ -571,6 +575,7 @@ void mmput(struct mm_struct *mm) + might_sleep(); + + if (atomic_dec_and_test(&mm->mm_users)) { ++ uprobe_clear_state(mm); + exit_aio(mm); + ksm_exit(mm); + khugepaged_exit(mm); /* must run before exit_mmap */ +@@ -749,6 +754,8 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm) + exit_pi_state_list(tsk); + #endif + ++ uprobe_free_utask(tsk); ++ + /* Get rid of any cached register state */ + deactivate_mm(tsk, mm); + +@@ -803,6 +810,7 @@ struct mm_struct *dup_mm(struct task_struct *tsk) + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + mm->pmd_huge_pte = NULL; + #endif ++ uprobe_reset_state(mm); + + if (!mm_init(mm, tsk)) + goto fail_nomem; +@@ -1344,6 +1352,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, + INIT_LIST_HEAD(&p->pi_state_list); + p->pi_state_cache = NULL; + #endif ++ uprobe_copy_process(p); + /* + * sigaltstack should be cleared when sharing the same VM + */ +diff --git a/kernel/signal.c b/kernel/signal.c +index 17afcaf..60d80ab 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #define CREATE_TRACE_POINTS + #include + +@@ -2202,6 +2203,9 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, + struct signal_struct *signal = current->signal; + int signr; + ++ if (unlikely(uprobe_deny_signal())) ++ return 0; ++ + relock: + /* + * We'll jump back here after any time we were stopped in TASK_STOPPED. +diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig +index a1d2849..ea4bff6 100644 +--- a/kernel/trace/Kconfig ++++ b/kernel/trace/Kconfig +@@ -373,6 +373,7 @@ config KPROBE_EVENT + depends on HAVE_REGS_AND_STACK_ACCESS_API + bool "Enable kprobes-based dynamic events" + select TRACING ++ select PROBE_EVENTS + default y + help + This allows the user to add tracing events (similar to tracepoints) +@@ -385,6 +386,25 @@ config KPROBE_EVENT + This option is also required by perf-probe subcommand of perf tools. + If you want to use perf tools, this option is strongly recommended. + ++config UPROBE_EVENT ++ bool "Enable uprobes-based dynamic events" ++ depends on ARCH_SUPPORTS_UPROBES ++ depends on MMU ++ select UPROBES ++ select PROBE_EVENTS ++ select TRACING ++ default n ++ help ++ This allows the user to add tracing events on top of userspace ++ dynamic events (similar to tracepoints) on the fly via the trace ++ events interface. Those events can be inserted wherever uprobes ++ can probe, and record various registers. ++ This option is required if you plan to use perf-probe subcommand ++ of perf tools on user space applications. ++ ++config PROBE_EVENTS ++ def_bool n ++ + config DYNAMIC_FTRACE + bool "enable/disable ftrace tracepoints dynamically" + depends on FUNCTION_TRACER +diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile +index 5f39a07..1734c03 100644 +--- a/kernel/trace/Makefile ++++ b/kernel/trace/Makefile +@@ -61,5 +61,7 @@ endif + ifeq ($(CONFIG_TRACING),y) + obj-$(CONFIG_KGDB_KDB) += trace_kdb.o + endif ++obj-$(CONFIG_PROBE_EVENTS) += trace_probe.o ++obj-$(CONFIG_UPROBE_EVENT) += trace_uprobe.o + + libftrace-y := ftrace.o +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index f95d65d..a6bf705 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -103,6 +103,11 @@ struct kretprobe_trace_entry_head { + unsigned long ret_ip; + }; + ++struct uprobe_trace_entry_head { ++ struct trace_entry ent; ++ unsigned long ip; ++}; ++ + /* + * trace_flag_type is an enumeration that holds different + * states when a trace occurs. These are: +diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c +index 580a05e..b31d3d5 100644 +--- a/kernel/trace/trace_kprobe.c ++++ b/kernel/trace/trace_kprobe.c +@@ -19,547 +19,15 @@ + + #include + #include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "trace.h" +-#include "trace_output.h" +- +-#define MAX_TRACE_ARGS 128 +-#define MAX_ARGSTR_LEN 63 +-#define MAX_EVENT_NAME_LEN 64 +-#define MAX_STRING_SIZE PATH_MAX +-#define KPROBE_EVENT_SYSTEM "kprobes" +- +-/* Reserved field names */ +-#define FIELD_STRING_IP "__probe_ip" +-#define FIELD_STRING_RETIP "__probe_ret_ip" +-#define FIELD_STRING_FUNC "__probe_func" +- +-const char *reserved_field_names[] = { +- "common_type", +- "common_flags", +- "common_preempt_count", +- "common_pid", +- "common_tgid", +- FIELD_STRING_IP, +- FIELD_STRING_RETIP, +- FIELD_STRING_FUNC, +-}; +- +-/* Printing function type */ +-typedef int (*print_type_func_t)(struct trace_seq *, const char *, void *, +- void *); +-#define PRINT_TYPE_FUNC_NAME(type) print_type_##type +-#define PRINT_TYPE_FMT_NAME(type) print_type_format_##type +- +-/* Printing in basic type function template */ +-#define DEFINE_BASIC_PRINT_TYPE_FUNC(type, fmt, cast) \ +-static __kprobes int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s, \ +- const char *name, \ +- void *data, void *ent)\ +-{ \ +- return trace_seq_printf(s, " %s=" fmt, name, (cast)*(type *)data);\ +-} \ +-static const char PRINT_TYPE_FMT_NAME(type)[] = fmt; +- +-DEFINE_BASIC_PRINT_TYPE_FUNC(u8, "%x", unsigned int) +-DEFINE_BASIC_PRINT_TYPE_FUNC(u16, "%x", unsigned int) +-DEFINE_BASIC_PRINT_TYPE_FUNC(u32, "%lx", unsigned long) +-DEFINE_BASIC_PRINT_TYPE_FUNC(u64, "%llx", unsigned long long) +-DEFINE_BASIC_PRINT_TYPE_FUNC(s8, "%d", int) +-DEFINE_BASIC_PRINT_TYPE_FUNC(s16, "%d", int) +-DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%ld", long) +-DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%lld", long long) +- +-/* data_rloc: data relative location, compatible with u32 */ +-#define make_data_rloc(len, roffs) \ +- (((u32)(len) << 16) | ((u32)(roffs) & 0xffff)) +-#define get_rloc_len(dl) ((u32)(dl) >> 16) +-#define get_rloc_offs(dl) ((u32)(dl) & 0xffff) +- +-static inline void *get_rloc_data(u32 *dl) +-{ +- return (u8 *)dl + get_rloc_offs(*dl); +-} +- +-/* For data_loc conversion */ +-static inline void *get_loc_data(u32 *dl, void *ent) +-{ +- return (u8 *)ent + get_rloc_offs(*dl); +-} +- +-/* +- * Convert data_rloc to data_loc: +- * data_rloc stores the offset from data_rloc itself, but data_loc +- * stores the offset from event entry. +- */ +-#define convert_rloc_to_loc(dl, offs) ((u32)(dl) + (offs)) +- +-/* For defining macros, define string/string_size types */ +-typedef u32 string; +-typedef u32 string_size; +- +-/* Print type function for string type */ +-static __kprobes int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, +- const char *name, +- void *data, void *ent) +-{ +- int len = *(u32 *)data >> 16; +- +- if (!len) +- return trace_seq_printf(s, " %s=(fault)", name); +- else +- return trace_seq_printf(s, " %s=\"%s\"", name, +- (const char *)get_loc_data(data, ent)); +-} +-static const char PRINT_TYPE_FMT_NAME(string)[] = "\\\"%s\\\""; +- +-/* Data fetch function type */ +-typedef void (*fetch_func_t)(struct pt_regs *, void *, void *); +- +-struct fetch_param { +- fetch_func_t fn; +- void *data; +-}; +- +-static __kprobes void call_fetch(struct fetch_param *fprm, +- struct pt_regs *regs, void *dest) +-{ +- return fprm->fn(regs, fprm->data, dest); +-} +- +-#define FETCH_FUNC_NAME(method, type) fetch_##method##_##type +-/* +- * Define macro for basic types - we don't need to define s* types, because +- * we have to care only about bitwidth at recording time. +- */ +-#define DEFINE_BASIC_FETCH_FUNCS(method) \ +-DEFINE_FETCH_##method(u8) \ +-DEFINE_FETCH_##method(u16) \ +-DEFINE_FETCH_##method(u32) \ +-DEFINE_FETCH_##method(u64) +- +-#define CHECK_FETCH_FUNCS(method, fn) \ +- (((FETCH_FUNC_NAME(method, u8) == fn) || \ +- (FETCH_FUNC_NAME(method, u16) == fn) || \ +- (FETCH_FUNC_NAME(method, u32) == fn) || \ +- (FETCH_FUNC_NAME(method, u64) == fn) || \ +- (FETCH_FUNC_NAME(method, string) == fn) || \ +- (FETCH_FUNC_NAME(method, string_size) == fn)) \ +- && (fn != NULL)) +- +-/* Data fetch function templates */ +-#define DEFINE_FETCH_reg(type) \ +-static __kprobes void FETCH_FUNC_NAME(reg, type)(struct pt_regs *regs, \ +- void *offset, void *dest) \ +-{ \ +- *(type *)dest = (type)regs_get_register(regs, \ +- (unsigned int)((unsigned long)offset)); \ +-} +-DEFINE_BASIC_FETCH_FUNCS(reg) +-/* No string on the register */ +-#define fetch_reg_string NULL +-#define fetch_reg_string_size NULL +- +-#define DEFINE_FETCH_stack(type) \ +-static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\ +- void *offset, void *dest) \ +-{ \ +- *(type *)dest = (type)regs_get_kernel_stack_nth(regs, \ +- (unsigned int)((unsigned long)offset)); \ +-} +-DEFINE_BASIC_FETCH_FUNCS(stack) +-/* No string on the stack entry */ +-#define fetch_stack_string NULL +-#define fetch_stack_string_size NULL +- +-#define DEFINE_FETCH_retval(type) \ +-static __kprobes void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,\ +- void *dummy, void *dest) \ +-{ \ +- *(type *)dest = (type)regs_return_value(regs); \ +-} +-DEFINE_BASIC_FETCH_FUNCS(retval) +-/* No string on the retval */ +-#define fetch_retval_string NULL +-#define fetch_retval_string_size NULL +- +-#define DEFINE_FETCH_memory(type) \ +-static __kprobes void FETCH_FUNC_NAME(memory, type)(struct pt_regs *regs,\ +- void *addr, void *dest) \ +-{ \ +- type retval; \ +- if (probe_kernel_address(addr, retval)) \ +- *(type *)dest = 0; \ +- else \ +- *(type *)dest = retval; \ +-} +-DEFINE_BASIC_FETCH_FUNCS(memory) +-/* +- * Fetch a null-terminated string. Caller MUST set *(u32 *)dest with max +- * length and relative data location. +- */ +-static __kprobes void FETCH_FUNC_NAME(memory, string)(struct pt_regs *regs, +- void *addr, void *dest) +-{ +- long ret; +- int maxlen = get_rloc_len(*(u32 *)dest); +- u8 *dst = get_rloc_data(dest); +- u8 *src = addr; +- mm_segment_t old_fs = get_fs(); +- if (!maxlen) +- return; +- /* +- * Try to get string again, since the string can be changed while +- * probing. +- */ +- set_fs(KERNEL_DS); +- pagefault_disable(); +- do +- ret = __copy_from_user_inatomic(dst++, src++, 1); +- while (dst[-1] && ret == 0 && src - (u8 *)addr < maxlen); +- dst[-1] = '\0'; +- pagefault_enable(); +- set_fs(old_fs); +- +- if (ret < 0) { /* Failed to fetch string */ +- ((u8 *)get_rloc_data(dest))[0] = '\0'; +- *(u32 *)dest = make_data_rloc(0, get_rloc_offs(*(u32 *)dest)); +- } else +- *(u32 *)dest = make_data_rloc(src - (u8 *)addr, +- get_rloc_offs(*(u32 *)dest)); +-} +-/* Return the length of string -- including null terminal byte */ +-static __kprobes void FETCH_FUNC_NAME(memory, string_size)(struct pt_regs *regs, +- void *addr, void *dest) +-{ +- int ret, len = 0; +- u8 c; +- mm_segment_t old_fs = get_fs(); +- +- set_fs(KERNEL_DS); +- pagefault_disable(); +- do { +- ret = __copy_from_user_inatomic(&c, (u8 *)addr + len, 1); +- len++; +- } while (c && ret == 0 && len < MAX_STRING_SIZE); +- pagefault_enable(); +- set_fs(old_fs); +- +- if (ret < 0) /* Failed to check the length */ +- *(u32 *)dest = 0; +- else +- *(u32 *)dest = len; +-} +- +-/* Memory fetching by symbol */ +-struct symbol_cache { +- char *symbol; +- long offset; +- unsigned long addr; +-}; +- +-static unsigned long update_symbol_cache(struct symbol_cache *sc) +-{ +- sc->addr = (unsigned long)kallsyms_lookup_name(sc->symbol); +- if (sc->addr) +- sc->addr += sc->offset; +- return sc->addr; +-} +- +-static void free_symbol_cache(struct symbol_cache *sc) +-{ +- kfree(sc->symbol); +- kfree(sc); +-} +- +-static struct symbol_cache *alloc_symbol_cache(const char *sym, long offset) +-{ +- struct symbol_cache *sc; +- +- if (!sym || strlen(sym) == 0) +- return NULL; +- sc = kzalloc(sizeof(struct symbol_cache), GFP_KERNEL); +- if (!sc) +- return NULL; +- +- sc->symbol = kstrdup(sym, GFP_KERNEL); +- if (!sc->symbol) { +- kfree(sc); +- return NULL; +- } +- sc->offset = offset; + +- update_symbol_cache(sc); +- return sc; +-} +- +-#define DEFINE_FETCH_symbol(type) \ +-static __kprobes void FETCH_FUNC_NAME(symbol, type)(struct pt_regs *regs,\ +- void *data, void *dest) \ +-{ \ +- struct symbol_cache *sc = data; \ +- if (sc->addr) \ +- fetch_memory_##type(regs, (void *)sc->addr, dest); \ +- else \ +- *(type *)dest = 0; \ +-} +-DEFINE_BASIC_FETCH_FUNCS(symbol) +-DEFINE_FETCH_symbol(string) +-DEFINE_FETCH_symbol(string_size) +- +-/* Dereference memory access function */ +-struct deref_fetch_param { +- struct fetch_param orig; +- long offset; +-}; +- +-#define DEFINE_FETCH_deref(type) \ +-static __kprobes void FETCH_FUNC_NAME(deref, type)(struct pt_regs *regs,\ +- void *data, void *dest) \ +-{ \ +- struct deref_fetch_param *dprm = data; \ +- unsigned long addr; \ +- call_fetch(&dprm->orig, regs, &addr); \ +- if (addr) { \ +- addr += dprm->offset; \ +- fetch_memory_##type(regs, (void *)addr, dest); \ +- } else \ +- *(type *)dest = 0; \ +-} +-DEFINE_BASIC_FETCH_FUNCS(deref) +-DEFINE_FETCH_deref(string) +-DEFINE_FETCH_deref(string_size) +- +-static __kprobes void update_deref_fetch_param(struct deref_fetch_param *data) +-{ +- if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) +- update_deref_fetch_param(data->orig.data); +- else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) +- update_symbol_cache(data->orig.data); +-} +- +-static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data) +-{ +- if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) +- free_deref_fetch_param(data->orig.data); +- else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) +- free_symbol_cache(data->orig.data); +- kfree(data); +-} +- +-/* Bitfield fetch function */ +-struct bitfield_fetch_param { +- struct fetch_param orig; +- unsigned char hi_shift; +- unsigned char low_shift; +-}; ++#include "trace_probe.h" + +-#define DEFINE_FETCH_bitfield(type) \ +-static __kprobes void FETCH_FUNC_NAME(bitfield, type)(struct pt_regs *regs,\ +- void *data, void *dest) \ +-{ \ +- struct bitfield_fetch_param *bprm = data; \ +- type buf = 0; \ +- call_fetch(&bprm->orig, regs, &buf); \ +- if (buf) { \ +- buf <<= bprm->hi_shift; \ +- buf >>= bprm->low_shift; \ +- } \ +- *(type *)dest = buf; \ +-} +-DEFINE_BASIC_FETCH_FUNCS(bitfield) +-#define fetch_bitfield_string NULL +-#define fetch_bitfield_string_size NULL +- +-static __kprobes void +-update_bitfield_fetch_param(struct bitfield_fetch_param *data) +-{ +- /* +- * Don't check the bitfield itself, because this must be the +- * last fetch function. +- */ +- if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) +- update_deref_fetch_param(data->orig.data); +- else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) +- update_symbol_cache(data->orig.data); +-} +- +-static __kprobes void +-free_bitfield_fetch_param(struct bitfield_fetch_param *data) +-{ +- /* +- * Don't check the bitfield itself, because this must be the +- * last fetch function. +- */ +- if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) +- free_deref_fetch_param(data->orig.data); +- else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) +- free_symbol_cache(data->orig.data); +- kfree(data); +-} +- +-/* Default (unsigned long) fetch type */ +-#define __DEFAULT_FETCH_TYPE(t) u##t +-#define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t) +-#define DEFAULT_FETCH_TYPE _DEFAULT_FETCH_TYPE(BITS_PER_LONG) +-#define DEFAULT_FETCH_TYPE_STR __stringify(DEFAULT_FETCH_TYPE) +- +-/* Fetch types */ +-enum { +- FETCH_MTD_reg = 0, +- FETCH_MTD_stack, +- FETCH_MTD_retval, +- FETCH_MTD_memory, +- FETCH_MTD_symbol, +- FETCH_MTD_deref, +- FETCH_MTD_bitfield, +- FETCH_MTD_END, +-}; +- +-#define ASSIGN_FETCH_FUNC(method, type) \ +- [FETCH_MTD_##method] = FETCH_FUNC_NAME(method, type) +- +-#define __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, _fmttype) \ +- {.name = _name, \ +- .size = _size, \ +- .is_signed = sign, \ +- .print = PRINT_TYPE_FUNC_NAME(ptype), \ +- .fmt = PRINT_TYPE_FMT_NAME(ptype), \ +- .fmttype = _fmttype, \ +- .fetch = { \ +-ASSIGN_FETCH_FUNC(reg, ftype), \ +-ASSIGN_FETCH_FUNC(stack, ftype), \ +-ASSIGN_FETCH_FUNC(retval, ftype), \ +-ASSIGN_FETCH_FUNC(memory, ftype), \ +-ASSIGN_FETCH_FUNC(symbol, ftype), \ +-ASSIGN_FETCH_FUNC(deref, ftype), \ +-ASSIGN_FETCH_FUNC(bitfield, ftype), \ +- } \ +- } +- +-#define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \ +- __ASSIGN_FETCH_TYPE(#ptype, ptype, ftype, sizeof(ftype), sign, #ptype) +- +-#define FETCH_TYPE_STRING 0 +-#define FETCH_TYPE_STRSIZE 1 +- +-/* Fetch type information table */ +-static const struct fetch_type { +- const char *name; /* Name of type */ +- size_t size; /* Byte size of type */ +- int is_signed; /* Signed flag */ +- print_type_func_t print; /* Print functions */ +- const char *fmt; /* Fromat string */ +- const char *fmttype; /* Name in format file */ +- /* Fetch functions */ +- fetch_func_t fetch[FETCH_MTD_END]; +-} fetch_type_table[] = { +- /* Special types */ +- [FETCH_TYPE_STRING] = __ASSIGN_FETCH_TYPE("string", string, string, +- sizeof(u32), 1, "__data_loc char[]"), +- [FETCH_TYPE_STRSIZE] = __ASSIGN_FETCH_TYPE("string_size", u32, +- string_size, sizeof(u32), 0, "u32"), +- /* Basic types */ +- ASSIGN_FETCH_TYPE(u8, u8, 0), +- ASSIGN_FETCH_TYPE(u16, u16, 0), +- ASSIGN_FETCH_TYPE(u32, u32, 0), +- ASSIGN_FETCH_TYPE(u64, u64, 0), +- ASSIGN_FETCH_TYPE(s8, u8, 1), +- ASSIGN_FETCH_TYPE(s16, u16, 1), +- ASSIGN_FETCH_TYPE(s32, u32, 1), +- ASSIGN_FETCH_TYPE(s64, u64, 1), +-}; +- +-static const struct fetch_type *find_fetch_type(const char *type) +-{ +- int i; +- +- if (!type) +- type = DEFAULT_FETCH_TYPE_STR; +- +- /* Special case: bitfield */ +- if (*type == 'b') { +- unsigned long bs; +- type = strchr(type, '/'); +- if (!type) +- goto fail; +- type++; +- if (strict_strtoul(type, 0, &bs)) +- goto fail; +- switch (bs) { +- case 8: +- return find_fetch_type("u8"); +- case 16: +- return find_fetch_type("u16"); +- case 32: +- return find_fetch_type("u32"); +- case 64: +- return find_fetch_type("u64"); +- default: +- goto fail; +- } +- } +- +- for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++) +- if (strcmp(type, fetch_type_table[i].name) == 0) +- return &fetch_type_table[i]; +-fail: +- return NULL; +-} +- +-/* Special function : only accept unsigned long */ +-static __kprobes void fetch_stack_address(struct pt_regs *regs, +- void *dummy, void *dest) +-{ +- *(unsigned long *)dest = kernel_stack_pointer(regs); +-} +- +-static fetch_func_t get_fetch_size_function(const struct fetch_type *type, +- fetch_func_t orig_fn) +-{ +- int i; +- +- if (type != &fetch_type_table[FETCH_TYPE_STRING]) +- return NULL; /* Only string type needs size function */ +- for (i = 0; i < FETCH_MTD_END; i++) +- if (type->fetch[i] == orig_fn) +- return fetch_type_table[FETCH_TYPE_STRSIZE].fetch[i]; +- +- WARN_ON(1); /* This should not happen */ +- return NULL; +-} ++#define KPROBE_EVENT_SYSTEM "kprobes" + + /** + * Kprobe event core functions + */ + +-struct probe_arg { +- struct fetch_param fetch; +- struct fetch_param fetch_size; +- unsigned int offset; /* Offset from argument entry */ +- const char *name; /* Name of this argument */ +- const char *comm; /* Command of this argument */ +- const struct fetch_type *type; /* Type of this argument */ +-}; +- +-/* Flags for trace_probe */ +-#define TP_FLAG_TRACE 1 +-#define TP_FLAG_PROFILE 2 +-#define TP_FLAG_REGISTERED 4 +- + struct trace_probe { + struct list_head list; + struct kretprobe rp; /* Use rp.kp for kprobe use */ +@@ -631,18 +99,6 @@ static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs); + static int kretprobe_dispatcher(struct kretprobe_instance *ri, + struct pt_regs *regs); + +-/* Check the name is good for event/group/fields */ +-static int is_good_name(const char *name) +-{ +- if (!isalpha(*name) && *name != '_') +- return 0; +- while (*++name != '\0') { +- if (!isalpha(*name) && !isdigit(*name) && *name != '_') +- return 0; +- } +- return 1; +-} +- + /* + * Allocate new trace_probe and initialize it (including kprobes). + */ +@@ -651,7 +107,7 @@ static struct trace_probe *alloc_trace_probe(const char *group, + void *addr, + const char *symbol, + unsigned long offs, +- int nargs, int is_return) ++ int nargs, bool is_return) + { + struct trace_probe *tp; + int ret = -ENOMEM; +@@ -702,34 +158,12 @@ error: + return ERR_PTR(ret); + } + +-static void update_probe_arg(struct probe_arg *arg) +-{ +- if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn)) +- update_bitfield_fetch_param(arg->fetch.data); +- else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn)) +- update_deref_fetch_param(arg->fetch.data); +- else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn)) +- update_symbol_cache(arg->fetch.data); +-} +- +-static void free_probe_arg(struct probe_arg *arg) +-{ +- if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn)) +- free_bitfield_fetch_param(arg->fetch.data); +- else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn)) +- free_deref_fetch_param(arg->fetch.data); +- else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn)) +- free_symbol_cache(arg->fetch.data); +- kfree(arg->name); +- kfree(arg->comm); +-} +- + static void free_trace_probe(struct trace_probe *tp) + { + int i; + + for (i = 0; i < tp->nr_args; i++) +- free_probe_arg(&tp->args[i]); ++ traceprobe_free_probe_arg(&tp->args[i]); + + kfree(tp->call.class->system); + kfree(tp->call.name); +@@ -787,7 +221,7 @@ static int __register_trace_probe(struct trace_probe *tp) + return -EINVAL; + + for (i = 0; i < tp->nr_args; i++) +- update_probe_arg(&tp->args[i]); ++ traceprobe_update_arg(&tp->args[i]); + + /* Set/clear disabled flag according to tp->flag */ + if (trace_probe_is_enabled(tp)) +@@ -919,227 +353,6 @@ static struct notifier_block trace_probe_module_nb = { + .priority = 1 /* Invoked after kprobe module callback */ + }; + +-/* Split symbol and offset. */ +-static int split_symbol_offset(char *symbol, unsigned long *offset) +-{ +- char *tmp; +- int ret; +- +- if (!offset) +- return -EINVAL; +- +- tmp = strchr(symbol, '+'); +- if (tmp) { +- /* skip sign because strict_strtol doesn't accept '+' */ +- ret = strict_strtoul(tmp + 1, 0, offset); +- if (ret) +- return ret; +- *tmp = '\0'; +- } else +- *offset = 0; +- return 0; +-} +- +-#define PARAM_MAX_ARGS 16 +-#define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) +- +-static int parse_probe_vars(char *arg, const struct fetch_type *t, +- struct fetch_param *f, int is_return) +-{ +- int ret = 0; +- unsigned long param; +- +- if (strcmp(arg, "retval") == 0) { +- if (is_return) +- f->fn = t->fetch[FETCH_MTD_retval]; +- else +- ret = -EINVAL; +- } else if (strncmp(arg, "stack", 5) == 0) { +- if (arg[5] == '\0') { +- if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR) == 0) +- f->fn = fetch_stack_address; +- else +- ret = -EINVAL; +- } else if (isdigit(arg[5])) { +- ret = strict_strtoul(arg + 5, 10, ¶m); +- if (ret || param > PARAM_MAX_STACK) +- ret = -EINVAL; +- else { +- f->fn = t->fetch[FETCH_MTD_stack]; +- f->data = (void *)param; +- } +- } else +- ret = -EINVAL; +- } else +- ret = -EINVAL; +- return ret; +-} +- +-/* Recursive argument parser */ +-static int __parse_probe_arg(char *arg, const struct fetch_type *t, +- struct fetch_param *f, int is_return) +-{ +- int ret = 0; +- unsigned long param; +- long offset; +- char *tmp; +- +- switch (arg[0]) { +- case '$': +- ret = parse_probe_vars(arg + 1, t, f, is_return); +- break; +- case '%': /* named register */ +- ret = regs_query_register_offset(arg + 1); +- if (ret >= 0) { +- f->fn = t->fetch[FETCH_MTD_reg]; +- f->data = (void *)(unsigned long)ret; +- ret = 0; +- } +- break; +- case '@': /* memory or symbol */ +- if (isdigit(arg[1])) { +- ret = strict_strtoul(arg + 1, 0, ¶m); +- if (ret) +- break; +- f->fn = t->fetch[FETCH_MTD_memory]; +- f->data = (void *)param; +- } else { +- ret = split_symbol_offset(arg + 1, &offset); +- if (ret) +- break; +- f->data = alloc_symbol_cache(arg + 1, offset); +- if (f->data) +- f->fn = t->fetch[FETCH_MTD_symbol]; +- } +- break; +- case '+': /* deref memory */ +- arg++; /* Skip '+', because strict_strtol() rejects it. */ +- case '-': +- tmp = strchr(arg, '('); +- if (!tmp) +- break; +- *tmp = '\0'; +- ret = strict_strtol(arg, 0, &offset); +- if (ret) +- break; +- arg = tmp + 1; +- tmp = strrchr(arg, ')'); +- if (tmp) { +- struct deref_fetch_param *dprm; +- const struct fetch_type *t2 = find_fetch_type(NULL); +- *tmp = '\0'; +- dprm = kzalloc(sizeof(struct deref_fetch_param), +- GFP_KERNEL); +- if (!dprm) +- return -ENOMEM; +- dprm->offset = offset; +- ret = __parse_probe_arg(arg, t2, &dprm->orig, +- is_return); +- if (ret) +- kfree(dprm); +- else { +- f->fn = t->fetch[FETCH_MTD_deref]; +- f->data = (void *)dprm; +- } +- } +- break; +- } +- if (!ret && !f->fn) { /* Parsed, but do not find fetch method */ +- pr_info("%s type has no corresponding fetch method.\n", +- t->name); +- ret = -EINVAL; +- } +- return ret; +-} +- +-#define BYTES_TO_BITS(nb) ((BITS_PER_LONG * (nb)) / sizeof(long)) +- +-/* Bitfield type needs to be parsed into a fetch function */ +-static int __parse_bitfield_probe_arg(const char *bf, +- const struct fetch_type *t, +- struct fetch_param *f) +-{ +- struct bitfield_fetch_param *bprm; +- unsigned long bw, bo; +- char *tail; +- +- if (*bf != 'b') +- return 0; +- +- bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); +- if (!bprm) +- return -ENOMEM; +- bprm->orig = *f; +- f->fn = t->fetch[FETCH_MTD_bitfield]; +- f->data = (void *)bprm; +- +- bw = simple_strtoul(bf + 1, &tail, 0); /* Use simple one */ +- if (bw == 0 || *tail != '@') +- return -EINVAL; +- +- bf = tail + 1; +- bo = simple_strtoul(bf, &tail, 0); +- if (tail == bf || *tail != '/') +- return -EINVAL; +- +- bprm->hi_shift = BYTES_TO_BITS(t->size) - (bw + bo); +- bprm->low_shift = bprm->hi_shift + bo; +- return (BYTES_TO_BITS(t->size) < (bw + bo)) ? -EINVAL : 0; +-} +- +-/* String length checking wrapper */ +-static int parse_probe_arg(char *arg, struct trace_probe *tp, +- struct probe_arg *parg, int is_return) +-{ +- const char *t; +- int ret; +- +- if (strlen(arg) > MAX_ARGSTR_LEN) { +- pr_info("Argument is too long.: %s\n", arg); +- return -ENOSPC; +- } +- parg->comm = kstrdup(arg, GFP_KERNEL); +- if (!parg->comm) { +- pr_info("Failed to allocate memory for command '%s'.\n", arg); +- return -ENOMEM; +- } +- t = strchr(parg->comm, ':'); +- if (t) { +- arg[t - parg->comm] = '\0'; +- t++; +- } +- parg->type = find_fetch_type(t); +- if (!parg->type) { +- pr_info("Unsupported type: %s\n", t); +- return -EINVAL; +- } +- parg->offset = tp->size; +- tp->size += parg->type->size; +- ret = __parse_probe_arg(arg, parg->type, &parg->fetch, is_return); +- if (ret >= 0 && t != NULL) +- ret = __parse_bitfield_probe_arg(t, parg->type, &parg->fetch); +- if (ret >= 0) { +- parg->fetch_size.fn = get_fetch_size_function(parg->type, +- parg->fetch.fn); +- parg->fetch_size.data = parg->fetch.data; +- } +- return ret; +-} +- +-/* Return 1 if name is reserved or already used by another argument */ +-static int conflict_field_name(const char *name, +- struct probe_arg *args, int narg) +-{ +- int i; +- for (i = 0; i < ARRAY_SIZE(reserved_field_names); i++) +- if (strcmp(reserved_field_names[i], name) == 0) +- return 1; +- for (i = 0; i < narg; i++) +- if (strcmp(args[i].name, name) == 0) +- return 1; +- return 0; +-} +- + static int create_trace_probe(int argc, char **argv) + { + /* +@@ -1162,7 +375,7 @@ static int create_trace_probe(int argc, char **argv) + */ + struct trace_probe *tp; + int i, ret = 0; +- int is_return = 0, is_delete = 0; ++ bool is_return = false, is_delete = false; + char *symbol = NULL, *event = NULL, *group = NULL; + char *arg; + unsigned long offset = 0; +@@ -1171,11 +384,11 @@ static int create_trace_probe(int argc, char **argv) + + /* argc must be >= 1 */ + if (argv[0][0] == 'p') +- is_return = 0; ++ is_return = false; + else if (argv[0][0] == 'r') +- is_return = 1; ++ is_return = true; + else if (argv[0][0] == '-') +- is_delete = 1; ++ is_delete = true; + else { + pr_info("Probe definition must be started with 'p', 'r' or" + " '-'.\n"); +@@ -1240,7 +453,7 @@ static int create_trace_probe(int argc, char **argv) + /* a symbol specified */ + symbol = argv[1]; + /* TODO: support .init module functions */ +- ret = split_symbol_offset(symbol, &offset); ++ ret = traceprobe_split_symbol_offset(symbol, &offset); + if (ret) { + pr_info("Failed to parse symbol.\n"); + return ret; +@@ -1302,7 +515,8 @@ static int create_trace_probe(int argc, char **argv) + goto error; + } + +- if (conflict_field_name(tp->args[i].name, tp->args, i)) { ++ if (traceprobe_conflict_field_name(tp->args[i].name, ++ tp->args, i)) { + pr_info("Argument[%d] name '%s' conflicts with " + "another field.\n", i, argv[i]); + ret = -EINVAL; +@@ -1310,7 +524,8 @@ static int create_trace_probe(int argc, char **argv) + } + + /* Parse fetch argument */ +- ret = parse_probe_arg(arg, tp, &tp->args[i], is_return); ++ ret = traceprobe_parse_probe_arg(arg, &tp->size, &tp->args[i], ++ is_return, true); + if (ret) { + pr_info("Parse error at argument[%d]. (%d)\n", i, ret); + goto error; +@@ -1412,70 +627,11 @@ static int probes_open(struct inode *inode, struct file *file) + return seq_open(file, &probes_seq_op); + } + +-static int command_trace_probe(const char *buf) +-{ +- char **argv; +- int argc = 0, ret = 0; +- +- argv = argv_split(GFP_KERNEL, buf, &argc); +- if (!argv) +- return -ENOMEM; +- +- if (argc) +- ret = create_trace_probe(argc, argv); +- +- argv_free(argv); +- return ret; +-} +- +-#define WRITE_BUFSIZE 4096 +- + static ssize_t probes_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) + { +- char *kbuf, *tmp; +- int ret; +- size_t done; +- size_t size; +- +- kbuf = kmalloc(WRITE_BUFSIZE, GFP_KERNEL); +- if (!kbuf) +- return -ENOMEM; +- +- ret = done = 0; +- while (done < count) { +- size = count - done; +- if (size >= WRITE_BUFSIZE) +- size = WRITE_BUFSIZE - 1; +- if (copy_from_user(kbuf, buffer + done, size)) { +- ret = -EFAULT; +- goto out; +- } +- kbuf[size] = '\0'; +- tmp = strchr(kbuf, '\n'); +- if (tmp) { +- *tmp = '\0'; +- size = tmp - kbuf + 1; +- } else if (done + size < count) { +- pr_warning("Line length is too long: " +- "Should be less than %d.", WRITE_BUFSIZE); +- ret = -EINVAL; +- goto out; +- } +- done += size; +- /* Remove comments */ +- tmp = strchr(kbuf, '#'); +- if (tmp) +- *tmp = '\0'; +- +- ret = command_trace_probe(kbuf); +- if (ret) +- goto out; +- } +- ret = done; +-out: +- kfree(kbuf); +- return ret; ++ return traceprobe_probes_write(file, buffer, count, ppos, ++ create_trace_probe); + } + + static const struct file_operations kprobe_events_ops = { +@@ -1711,16 +867,6 @@ partial: + return TRACE_TYPE_PARTIAL_LINE; + } + +-#undef DEFINE_FIELD +-#define DEFINE_FIELD(type, item, name, is_signed) \ +- do { \ +- ret = trace_define_field(event_call, #type, name, \ +- offsetof(typeof(field), item), \ +- sizeof(field.item), is_signed, \ +- FILTER_OTHER); \ +- if (ret) \ +- return ret; \ +- } while (0) + + static int kprobe_event_define_fields(struct ftrace_event_call *event_call) + { +@@ -2051,8 +1197,9 @@ static __init int kprobe_trace_self_tests_init(void) + + pr_info("Testing kprobe tracing: "); + +- ret = command_trace_probe("p:testprobe kprobe_trace_selftest_target " +- "$stack $stack0 +0($stack)"); ++ ret = traceprobe_command("p:testprobe kprobe_trace_selftest_target " ++ "$stack $stack0 +0($stack)", ++ create_trace_probe); + if (WARN_ON_ONCE(ret)) { + pr_warning("error on probing function entry.\n"); + warn++; +@@ -2066,8 +1213,8 @@ static __init int kprobe_trace_self_tests_init(void) + enable_trace_probe(tp, TP_FLAG_TRACE); + } + +- ret = command_trace_probe("r:testprobe2 kprobe_trace_selftest_target " +- "$retval"); ++ ret = traceprobe_command("r:testprobe2 kprobe_trace_selftest_target " ++ "$retval", create_trace_probe); + if (WARN_ON_ONCE(ret)) { + pr_warning("error on probing function return.\n"); + warn++; +@@ -2101,13 +1248,13 @@ static __init int kprobe_trace_self_tests_init(void) + } else + disable_trace_probe(tp, TP_FLAG_TRACE); + +- ret = command_trace_probe("-:testprobe"); ++ ret = traceprobe_command("-:testprobe", create_trace_probe); + if (WARN_ON_ONCE(ret)) { + pr_warning("error on deleting a probe.\n"); + warn++; + } + +- ret = command_trace_probe("-:testprobe2"); ++ ret = traceprobe_command("-:testprobe2", create_trace_probe); + if (WARN_ON_ONCE(ret)) { + pr_warning("error on deleting a probe.\n"); + warn++; +diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c +new file mode 100644 +index 0000000..daa9980 +--- /dev/null ++++ b/kernel/trace/trace_probe.c +@@ -0,0 +1,839 @@ ++/* ++ * Common code for probe-based Dynamic events. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * This code was copied from kernel/trace/trace_kprobe.c written by ++ * Masami Hiramatsu ++ * ++ * Updates to make this generic: ++ * Copyright (C) IBM Corporation, 2010-2011 ++ * Author: Srikar Dronamraju ++ */ ++ ++#include "trace_probe.h" ++ ++const char *reserved_field_names[] = { ++ "common_type", ++ "common_flags", ++ "common_preempt_count", ++ "common_pid", ++ "common_tgid", ++ FIELD_STRING_IP, ++ FIELD_STRING_RETIP, ++ FIELD_STRING_FUNC, ++}; ++ ++/* Printing function type */ ++#define PRINT_TYPE_FUNC_NAME(type) print_type_##type ++#define PRINT_TYPE_FMT_NAME(type) print_type_format_##type ++ ++/* Printing in basic type function template */ ++#define DEFINE_BASIC_PRINT_TYPE_FUNC(type, fmt, cast) \ ++static __kprobes int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s, \ ++ const char *name, \ ++ void *data, void *ent)\ ++{ \ ++ return trace_seq_printf(s, " %s=" fmt, name, (cast)*(type *)data);\ ++} \ ++static const char PRINT_TYPE_FMT_NAME(type)[] = fmt; ++ ++DEFINE_BASIC_PRINT_TYPE_FUNC(u8, "%x", unsigned int) ++DEFINE_BASIC_PRINT_TYPE_FUNC(u16, "%x", unsigned int) ++DEFINE_BASIC_PRINT_TYPE_FUNC(u32, "%lx", unsigned long) ++DEFINE_BASIC_PRINT_TYPE_FUNC(u64, "%llx", unsigned long long) ++DEFINE_BASIC_PRINT_TYPE_FUNC(s8, "%d", int) ++DEFINE_BASIC_PRINT_TYPE_FUNC(s16, "%d", int) ++DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%ld", long) ++DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%lld", long long) ++ ++static inline void *get_rloc_data(u32 *dl) ++{ ++ return (u8 *)dl + get_rloc_offs(*dl); ++} ++ ++/* For data_loc conversion */ ++static inline void *get_loc_data(u32 *dl, void *ent) ++{ ++ return (u8 *)ent + get_rloc_offs(*dl); ++} ++ ++/* For defining macros, define string/string_size types */ ++typedef u32 string; ++typedef u32 string_size; ++ ++/* Print type function for string type */ ++static __kprobes int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, ++ const char *name, ++ void *data, void *ent) ++{ ++ int len = *(u32 *)data >> 16; ++ ++ if (!len) ++ return trace_seq_printf(s, " %s=(fault)", name); ++ else ++ return trace_seq_printf(s, " %s=\"%s\"", name, ++ (const char *)get_loc_data(data, ent)); ++} ++ ++static const char PRINT_TYPE_FMT_NAME(string)[] = "\\\"%s\\\""; ++ ++#define FETCH_FUNC_NAME(method, type) fetch_##method##_##type ++/* ++ * Define macro for basic types - we don't need to define s* types, because ++ * we have to care only about bitwidth at recording time. ++ */ ++#define DEFINE_BASIC_FETCH_FUNCS(method) \ ++DEFINE_FETCH_##method(u8) \ ++DEFINE_FETCH_##method(u16) \ ++DEFINE_FETCH_##method(u32) \ ++DEFINE_FETCH_##method(u64) ++ ++#define CHECK_FETCH_FUNCS(method, fn) \ ++ (((FETCH_FUNC_NAME(method, u8) == fn) || \ ++ (FETCH_FUNC_NAME(method, u16) == fn) || \ ++ (FETCH_FUNC_NAME(method, u32) == fn) || \ ++ (FETCH_FUNC_NAME(method, u64) == fn) || \ ++ (FETCH_FUNC_NAME(method, string) == fn) || \ ++ (FETCH_FUNC_NAME(method, string_size) == fn)) \ ++ && (fn != NULL)) ++ ++/* Data fetch function templates */ ++#define DEFINE_FETCH_reg(type) \ ++static __kprobes void FETCH_FUNC_NAME(reg, type)(struct pt_regs *regs, \ ++ void *offset, void *dest) \ ++{ \ ++ *(type *)dest = (type)regs_get_register(regs, \ ++ (unsigned int)((unsigned long)offset)); \ ++} ++DEFINE_BASIC_FETCH_FUNCS(reg) ++/* No string on the register */ ++#define fetch_reg_string NULL ++#define fetch_reg_string_size NULL ++ ++#define DEFINE_FETCH_stack(type) \ ++static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\ ++ void *offset, void *dest) \ ++{ \ ++ *(type *)dest = (type)regs_get_kernel_stack_nth(regs, \ ++ (unsigned int)((unsigned long)offset)); \ ++} ++DEFINE_BASIC_FETCH_FUNCS(stack) ++/* No string on the stack entry */ ++#define fetch_stack_string NULL ++#define fetch_stack_string_size NULL ++ ++#define DEFINE_FETCH_retval(type) \ ++static __kprobes void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,\ ++ void *dummy, void *dest) \ ++{ \ ++ *(type *)dest = (type)regs_return_value(regs); \ ++} ++DEFINE_BASIC_FETCH_FUNCS(retval) ++/* No string on the retval */ ++#define fetch_retval_string NULL ++#define fetch_retval_string_size NULL ++ ++#define DEFINE_FETCH_memory(type) \ ++static __kprobes void FETCH_FUNC_NAME(memory, type)(struct pt_regs *regs,\ ++ void *addr, void *dest) \ ++{ \ ++ type retval; \ ++ if (probe_kernel_address(addr, retval)) \ ++ *(type *)dest = 0; \ ++ else \ ++ *(type *)dest = retval; \ ++} ++DEFINE_BASIC_FETCH_FUNCS(memory) ++/* ++ * Fetch a null-terminated string. Caller MUST set *(u32 *)dest with max ++ * length and relative data location. ++ */ ++static __kprobes void FETCH_FUNC_NAME(memory, string)(struct pt_regs *regs, ++ void *addr, void *dest) ++{ ++ long ret; ++ int maxlen = get_rloc_len(*(u32 *)dest); ++ u8 *dst = get_rloc_data(dest); ++ u8 *src = addr; ++ mm_segment_t old_fs = get_fs(); ++ ++ if (!maxlen) ++ return; ++ ++ /* ++ * Try to get string again, since the string can be changed while ++ * probing. ++ */ ++ set_fs(KERNEL_DS); ++ pagefault_disable(); ++ ++ do ++ ret = __copy_from_user_inatomic(dst++, src++, 1); ++ while (dst[-1] && ret == 0 && src - (u8 *)addr < maxlen); ++ ++ dst[-1] = '\0'; ++ pagefault_enable(); ++ set_fs(old_fs); ++ ++ if (ret < 0) { /* Failed to fetch string */ ++ ((u8 *)get_rloc_data(dest))[0] = '\0'; ++ *(u32 *)dest = make_data_rloc(0, get_rloc_offs(*(u32 *)dest)); ++ } else { ++ *(u32 *)dest = make_data_rloc(src - (u8 *)addr, ++ get_rloc_offs(*(u32 *)dest)); ++ } ++} ++ ++/* Return the length of string -- including null terminal byte */ ++static __kprobes void FETCH_FUNC_NAME(memory, string_size)(struct pt_regs *regs, ++ void *addr, void *dest) ++{ ++ mm_segment_t old_fs; ++ int ret, len = 0; ++ u8 c; ++ ++ old_fs = get_fs(); ++ set_fs(KERNEL_DS); ++ pagefault_disable(); ++ ++ do { ++ ret = __copy_from_user_inatomic(&c, (u8 *)addr + len, 1); ++ len++; ++ } while (c && ret == 0 && len < MAX_STRING_SIZE); ++ ++ pagefault_enable(); ++ set_fs(old_fs); ++ ++ if (ret < 0) /* Failed to check the length */ ++ *(u32 *)dest = 0; ++ else ++ *(u32 *)dest = len; ++} ++ ++/* Memory fetching by symbol */ ++struct symbol_cache { ++ char *symbol; ++ long offset; ++ unsigned long addr; ++}; ++ ++static unsigned long update_symbol_cache(struct symbol_cache *sc) ++{ ++ sc->addr = (unsigned long)kallsyms_lookup_name(sc->symbol); ++ ++ if (sc->addr) ++ sc->addr += sc->offset; ++ ++ return sc->addr; ++} ++ ++static void free_symbol_cache(struct symbol_cache *sc) ++{ ++ kfree(sc->symbol); ++ kfree(sc); ++} ++ ++static struct symbol_cache *alloc_symbol_cache(const char *sym, long offset) ++{ ++ struct symbol_cache *sc; ++ ++ if (!sym || strlen(sym) == 0) ++ return NULL; ++ ++ sc = kzalloc(sizeof(struct symbol_cache), GFP_KERNEL); ++ if (!sc) ++ return NULL; ++ ++ sc->symbol = kstrdup(sym, GFP_KERNEL); ++ if (!sc->symbol) { ++ kfree(sc); ++ return NULL; ++ } ++ sc->offset = offset; ++ update_symbol_cache(sc); ++ ++ return sc; ++} ++ ++#define DEFINE_FETCH_symbol(type) \ ++static __kprobes void FETCH_FUNC_NAME(symbol, type)(struct pt_regs *regs,\ ++ void *data, void *dest) \ ++{ \ ++ struct symbol_cache *sc = data; \ ++ if (sc->addr) \ ++ fetch_memory_##type(regs, (void *)sc->addr, dest); \ ++ else \ ++ *(type *)dest = 0; \ ++} ++DEFINE_BASIC_FETCH_FUNCS(symbol) ++DEFINE_FETCH_symbol(string) ++DEFINE_FETCH_symbol(string_size) ++ ++/* Dereference memory access function */ ++struct deref_fetch_param { ++ struct fetch_param orig; ++ long offset; ++}; ++ ++#define DEFINE_FETCH_deref(type) \ ++static __kprobes void FETCH_FUNC_NAME(deref, type)(struct pt_regs *regs,\ ++ void *data, void *dest) \ ++{ \ ++ struct deref_fetch_param *dprm = data; \ ++ unsigned long addr; \ ++ call_fetch(&dprm->orig, regs, &addr); \ ++ if (addr) { \ ++ addr += dprm->offset; \ ++ fetch_memory_##type(regs, (void *)addr, dest); \ ++ } else \ ++ *(type *)dest = 0; \ ++} ++DEFINE_BASIC_FETCH_FUNCS(deref) ++DEFINE_FETCH_deref(string) ++DEFINE_FETCH_deref(string_size) ++ ++static __kprobes void update_deref_fetch_param(struct deref_fetch_param *data) ++{ ++ if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) ++ update_deref_fetch_param(data->orig.data); ++ else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) ++ update_symbol_cache(data->orig.data); ++} ++ ++static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data) ++{ ++ if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) ++ free_deref_fetch_param(data->orig.data); ++ else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) ++ free_symbol_cache(data->orig.data); ++ kfree(data); ++} ++ ++/* Bitfield fetch function */ ++struct bitfield_fetch_param { ++ struct fetch_param orig; ++ unsigned char hi_shift; ++ unsigned char low_shift; ++}; ++ ++#define DEFINE_FETCH_bitfield(type) \ ++static __kprobes void FETCH_FUNC_NAME(bitfield, type)(struct pt_regs *regs,\ ++ void *data, void *dest) \ ++{ \ ++ struct bitfield_fetch_param *bprm = data; \ ++ type buf = 0; \ ++ call_fetch(&bprm->orig, regs, &buf); \ ++ if (buf) { \ ++ buf <<= bprm->hi_shift; \ ++ buf >>= bprm->low_shift; \ ++ } \ ++ *(type *)dest = buf; \ ++} ++ ++DEFINE_BASIC_FETCH_FUNCS(bitfield) ++#define fetch_bitfield_string NULL ++#define fetch_bitfield_string_size NULL ++ ++static __kprobes void ++update_bitfield_fetch_param(struct bitfield_fetch_param *data) ++{ ++ /* ++ * Don't check the bitfield itself, because this must be the ++ * last fetch function. ++ */ ++ if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) ++ update_deref_fetch_param(data->orig.data); ++ else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) ++ update_symbol_cache(data->orig.data); ++} ++ ++static __kprobes void ++free_bitfield_fetch_param(struct bitfield_fetch_param *data) ++{ ++ /* ++ * Don't check the bitfield itself, because this must be the ++ * last fetch function. ++ */ ++ if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) ++ free_deref_fetch_param(data->orig.data); ++ else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) ++ free_symbol_cache(data->orig.data); ++ ++ kfree(data); ++} ++ ++/* Default (unsigned long) fetch type */ ++#define __DEFAULT_FETCH_TYPE(t) u##t ++#define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t) ++#define DEFAULT_FETCH_TYPE _DEFAULT_FETCH_TYPE(BITS_PER_LONG) ++#define DEFAULT_FETCH_TYPE_STR __stringify(DEFAULT_FETCH_TYPE) ++ ++#define ASSIGN_FETCH_FUNC(method, type) \ ++ [FETCH_MTD_##method] = FETCH_FUNC_NAME(method, type) ++ ++#define __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, _fmttype) \ ++ {.name = _name, \ ++ .size = _size, \ ++ .is_signed = sign, \ ++ .print = PRINT_TYPE_FUNC_NAME(ptype), \ ++ .fmt = PRINT_TYPE_FMT_NAME(ptype), \ ++ .fmttype = _fmttype, \ ++ .fetch = { \ ++ASSIGN_FETCH_FUNC(reg, ftype), \ ++ASSIGN_FETCH_FUNC(stack, ftype), \ ++ASSIGN_FETCH_FUNC(retval, ftype), \ ++ASSIGN_FETCH_FUNC(memory, ftype), \ ++ASSIGN_FETCH_FUNC(symbol, ftype), \ ++ASSIGN_FETCH_FUNC(deref, ftype), \ ++ASSIGN_FETCH_FUNC(bitfield, ftype), \ ++ } \ ++ } ++ ++#define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \ ++ __ASSIGN_FETCH_TYPE(#ptype, ptype, ftype, sizeof(ftype), sign, #ptype) ++ ++#define FETCH_TYPE_STRING 0 ++#define FETCH_TYPE_STRSIZE 1 ++ ++/* Fetch type information table */ ++static const struct fetch_type fetch_type_table[] = { ++ /* Special types */ ++ [FETCH_TYPE_STRING] = __ASSIGN_FETCH_TYPE("string", string, string, ++ sizeof(u32), 1, "__data_loc char[]"), ++ [FETCH_TYPE_STRSIZE] = __ASSIGN_FETCH_TYPE("string_size", u32, ++ string_size, sizeof(u32), 0, "u32"), ++ /* Basic types */ ++ ASSIGN_FETCH_TYPE(u8, u8, 0), ++ ASSIGN_FETCH_TYPE(u16, u16, 0), ++ ASSIGN_FETCH_TYPE(u32, u32, 0), ++ ASSIGN_FETCH_TYPE(u64, u64, 0), ++ ASSIGN_FETCH_TYPE(s8, u8, 1), ++ ASSIGN_FETCH_TYPE(s16, u16, 1), ++ ASSIGN_FETCH_TYPE(s32, u32, 1), ++ ASSIGN_FETCH_TYPE(s64, u64, 1), ++}; ++ ++static const struct fetch_type *find_fetch_type(const char *type) ++{ ++ int i; ++ ++ if (!type) ++ type = DEFAULT_FETCH_TYPE_STR; ++ ++ /* Special case: bitfield */ ++ if (*type == 'b') { ++ unsigned long bs; ++ ++ type = strchr(type, '/'); ++ if (!type) ++ goto fail; ++ ++ type++; ++ if (strict_strtoul(type, 0, &bs)) ++ goto fail; ++ ++ switch (bs) { ++ case 8: ++ return find_fetch_type("u8"); ++ case 16: ++ return find_fetch_type("u16"); ++ case 32: ++ return find_fetch_type("u32"); ++ case 64: ++ return find_fetch_type("u64"); ++ default: ++ goto fail; ++ } ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++) ++ if (strcmp(type, fetch_type_table[i].name) == 0) ++ return &fetch_type_table[i]; ++ ++fail: ++ return NULL; ++} ++ ++/* Special function : only accept unsigned long */ ++static __kprobes void fetch_stack_address(struct pt_regs *regs, ++ void *dummy, void *dest) ++{ ++ *(unsigned long *)dest = kernel_stack_pointer(regs); ++} ++ ++static fetch_func_t get_fetch_size_function(const struct fetch_type *type, ++ fetch_func_t orig_fn) ++{ ++ int i; ++ ++ if (type != &fetch_type_table[FETCH_TYPE_STRING]) ++ return NULL; /* Only string type needs size function */ ++ ++ for (i = 0; i < FETCH_MTD_END; i++) ++ if (type->fetch[i] == orig_fn) ++ return fetch_type_table[FETCH_TYPE_STRSIZE].fetch[i]; ++ ++ WARN_ON(1); /* This should not happen */ ++ ++ return NULL; ++} ++ ++/* Split symbol and offset. */ ++int traceprobe_split_symbol_offset(char *symbol, unsigned long *offset) ++{ ++ char *tmp; ++ int ret; ++ ++ if (!offset) ++ return -EINVAL; ++ ++ tmp = strchr(symbol, '+'); ++ if (tmp) { ++ /* skip sign because strict_strtol doesn't accept '+' */ ++ ret = strict_strtoul(tmp + 1, 0, offset); ++ if (ret) ++ return ret; ++ ++ *tmp = '\0'; ++ } else ++ *offset = 0; ++ ++ return 0; ++} ++ ++#define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) ++ ++static int parse_probe_vars(char *arg, const struct fetch_type *t, ++ struct fetch_param *f, bool is_return) ++{ ++ int ret = 0; ++ unsigned long param; ++ ++ if (strcmp(arg, "retval") == 0) { ++ if (is_return) ++ f->fn = t->fetch[FETCH_MTD_retval]; ++ else ++ ret = -EINVAL; ++ } else if (strncmp(arg, "stack", 5) == 0) { ++ if (arg[5] == '\0') { ++ if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR) == 0) ++ f->fn = fetch_stack_address; ++ else ++ ret = -EINVAL; ++ } else if (isdigit(arg[5])) { ++ ret = strict_strtoul(arg + 5, 10, ¶m); ++ if (ret || param > PARAM_MAX_STACK) ++ ret = -EINVAL; ++ else { ++ f->fn = t->fetch[FETCH_MTD_stack]; ++ f->data = (void *)param; ++ } ++ } else ++ ret = -EINVAL; ++ } else ++ ret = -EINVAL; ++ ++ return ret; ++} ++ ++/* Recursive argument parser */ ++static int parse_probe_arg(char *arg, const struct fetch_type *t, ++ struct fetch_param *f, bool is_return, bool is_kprobe) ++{ ++ unsigned long param; ++ long offset; ++ char *tmp; ++ int ret; ++ ++ ret = 0; ++ ++ /* Until uprobe_events supports only reg arguments */ ++ if (!is_kprobe && arg[0] != '%') ++ return -EINVAL; ++ ++ switch (arg[0]) { ++ case '$': ++ ret = parse_probe_vars(arg + 1, t, f, is_return); ++ break; ++ ++ case '%': /* named register */ ++ ret = regs_query_register_offset(arg + 1); ++ if (ret >= 0) { ++ f->fn = t->fetch[FETCH_MTD_reg]; ++ f->data = (void *)(unsigned long)ret; ++ ret = 0; ++ } ++ break; ++ ++ case '@': /* memory or symbol */ ++ if (isdigit(arg[1])) { ++ ret = strict_strtoul(arg + 1, 0, ¶m); ++ if (ret) ++ break; ++ ++ f->fn = t->fetch[FETCH_MTD_memory]; ++ f->data = (void *)param; ++ } else { ++ ret = traceprobe_split_symbol_offset(arg + 1, &offset); ++ if (ret) ++ break; ++ ++ f->data = alloc_symbol_cache(arg + 1, offset); ++ if (f->data) ++ f->fn = t->fetch[FETCH_MTD_symbol]; ++ } ++ break; ++ ++ case '+': /* deref memory */ ++ arg++; /* Skip '+', because strict_strtol() rejects it. */ ++ case '-': ++ tmp = strchr(arg, '('); ++ if (!tmp) ++ break; ++ ++ *tmp = '\0'; ++ ret = strict_strtol(arg, 0, &offset); ++ ++ if (ret) ++ break; ++ ++ arg = tmp + 1; ++ tmp = strrchr(arg, ')'); ++ ++ if (tmp) { ++ struct deref_fetch_param *dprm; ++ const struct fetch_type *t2; ++ ++ t2 = find_fetch_type(NULL); ++ *tmp = '\0'; ++ dprm = kzalloc(sizeof(struct deref_fetch_param), GFP_KERNEL); ++ ++ if (!dprm) ++ return -ENOMEM; ++ ++ dprm->offset = offset; ++ ret = parse_probe_arg(arg, t2, &dprm->orig, is_return, ++ is_kprobe); ++ if (ret) ++ kfree(dprm); ++ else { ++ f->fn = t->fetch[FETCH_MTD_deref]; ++ f->data = (void *)dprm; ++ } ++ } ++ break; ++ } ++ if (!ret && !f->fn) { /* Parsed, but do not find fetch method */ ++ pr_info("%s type has no corresponding fetch method.\n", t->name); ++ ret = -EINVAL; ++ } ++ ++ return ret; ++} ++ ++#define BYTES_TO_BITS(nb) ((BITS_PER_LONG * (nb)) / sizeof(long)) ++ ++/* Bitfield type needs to be parsed into a fetch function */ ++static int __parse_bitfield_probe_arg(const char *bf, ++ const struct fetch_type *t, ++ struct fetch_param *f) ++{ ++ struct bitfield_fetch_param *bprm; ++ unsigned long bw, bo; ++ char *tail; ++ ++ if (*bf != 'b') ++ return 0; ++ ++ bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); ++ if (!bprm) ++ return -ENOMEM; ++ ++ bprm->orig = *f; ++ f->fn = t->fetch[FETCH_MTD_bitfield]; ++ f->data = (void *)bprm; ++ bw = simple_strtoul(bf + 1, &tail, 0); /* Use simple one */ ++ ++ if (bw == 0 || *tail != '@') ++ return -EINVAL; ++ ++ bf = tail + 1; ++ bo = simple_strtoul(bf, &tail, 0); ++ ++ if (tail == bf || *tail != '/') ++ return -EINVAL; ++ ++ bprm->hi_shift = BYTES_TO_BITS(t->size) - (bw + bo); ++ bprm->low_shift = bprm->hi_shift + bo; ++ ++ return (BYTES_TO_BITS(t->size) < (bw + bo)) ? -EINVAL : 0; ++} ++ ++/* String length checking wrapper */ ++int traceprobe_parse_probe_arg(char *arg, ssize_t *size, ++ struct probe_arg *parg, bool is_return, bool is_kprobe) ++{ ++ const char *t; ++ int ret; ++ ++ if (strlen(arg) > MAX_ARGSTR_LEN) { ++ pr_info("Argument is too long.: %s\n", arg); ++ return -ENOSPC; ++ } ++ parg->comm = kstrdup(arg, GFP_KERNEL); ++ if (!parg->comm) { ++ pr_info("Failed to allocate memory for command '%s'.\n", arg); ++ return -ENOMEM; ++ } ++ t = strchr(parg->comm, ':'); ++ if (t) { ++ arg[t - parg->comm] = '\0'; ++ t++; ++ } ++ parg->type = find_fetch_type(t); ++ if (!parg->type) { ++ pr_info("Unsupported type: %s\n", t); ++ return -EINVAL; ++ } ++ parg->offset = *size; ++ *size += parg->type->size; ++ ret = parse_probe_arg(arg, parg->type, &parg->fetch, is_return, is_kprobe); ++ ++ if (ret >= 0 && t != NULL) ++ ret = __parse_bitfield_probe_arg(t, parg->type, &parg->fetch); ++ ++ if (ret >= 0) { ++ parg->fetch_size.fn = get_fetch_size_function(parg->type, ++ parg->fetch.fn); ++ parg->fetch_size.data = parg->fetch.data; ++ } ++ ++ return ret; ++} ++ ++/* Return 1 if name is reserved or already used by another argument */ ++int traceprobe_conflict_field_name(const char *name, ++ struct probe_arg *args, int narg) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(reserved_field_names); i++) ++ if (strcmp(reserved_field_names[i], name) == 0) ++ return 1; ++ ++ for (i = 0; i < narg; i++) ++ if (strcmp(args[i].name, name) == 0) ++ return 1; ++ ++ return 0; ++} ++ ++void traceprobe_update_arg(struct probe_arg *arg) ++{ ++ if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn)) ++ update_bitfield_fetch_param(arg->fetch.data); ++ else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn)) ++ update_deref_fetch_param(arg->fetch.data); ++ else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn)) ++ update_symbol_cache(arg->fetch.data); ++} ++ ++void traceprobe_free_probe_arg(struct probe_arg *arg) ++{ ++ if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn)) ++ free_bitfield_fetch_param(arg->fetch.data); ++ else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn)) ++ free_deref_fetch_param(arg->fetch.data); ++ else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn)) ++ free_symbol_cache(arg->fetch.data); ++ ++ kfree(arg->name); ++ kfree(arg->comm); ++} ++ ++int traceprobe_command(const char *buf, int (*createfn)(int, char **)) ++{ ++ char **argv; ++ int argc, ret; ++ ++ argc = 0; ++ ret = 0; ++ argv = argv_split(GFP_KERNEL, buf, &argc); ++ if (!argv) ++ return -ENOMEM; ++ ++ if (argc) ++ ret = createfn(argc, argv); ++ ++ argv_free(argv); ++ ++ return ret; ++} ++ ++#define WRITE_BUFSIZE 4096 ++ ++ssize_t traceprobe_probes_write(struct file *file, const char __user *buffer, ++ size_t count, loff_t *ppos, ++ int (*createfn)(int, char **)) ++{ ++ char *kbuf, *tmp; ++ int ret = 0; ++ size_t done = 0; ++ size_t size; ++ ++ kbuf = kmalloc(WRITE_BUFSIZE, GFP_KERNEL); ++ if (!kbuf) ++ return -ENOMEM; ++ ++ while (done < count) { ++ size = count - done; ++ ++ if (size >= WRITE_BUFSIZE) ++ size = WRITE_BUFSIZE - 1; ++ ++ if (copy_from_user(kbuf, buffer + done, size)) { ++ ret = -EFAULT; ++ goto out; ++ } ++ kbuf[size] = '\0'; ++ tmp = strchr(kbuf, '\n'); ++ ++ if (tmp) { ++ *tmp = '\0'; ++ size = tmp - kbuf + 1; ++ } else if (done + size < count) { ++ pr_warning("Line length is too long: " ++ "Should be less than %d.", WRITE_BUFSIZE); ++ ret = -EINVAL; ++ goto out; ++ } ++ done += size; ++ /* Remove comments */ ++ tmp = strchr(kbuf, '#'); ++ ++ if (tmp) ++ *tmp = '\0'; ++ ++ ret = traceprobe_command(kbuf, createfn); ++ if (ret) ++ goto out; ++ } ++ ret = done; ++ ++out: ++ kfree(kbuf); ++ ++ return ret; ++} +diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h +new file mode 100644 +index 0000000..9337086 +--- /dev/null ++++ b/kernel/trace/trace_probe.h +@@ -0,0 +1,161 @@ ++/* ++ * Common header file for probe-based Dynamic events. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * This code was copied from kernel/trace/trace_kprobe.h written by ++ * Masami Hiramatsu ++ * ++ * Updates to make this generic: ++ * Copyright (C) IBM Corporation, 2010-2011 ++ * Author: Srikar Dronamraju ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "trace.h" ++#include "trace_output.h" ++ ++#define MAX_TRACE_ARGS 128 ++#define MAX_ARGSTR_LEN 63 ++#define MAX_EVENT_NAME_LEN 64 ++#define MAX_STRING_SIZE PATH_MAX ++ ++/* Reserved field names */ ++#define FIELD_STRING_IP "__probe_ip" ++#define FIELD_STRING_RETIP "__probe_ret_ip" ++#define FIELD_STRING_FUNC "__probe_func" ++ ++#undef DEFINE_FIELD ++#define DEFINE_FIELD(type, item, name, is_signed) \ ++ do { \ ++ ret = trace_define_field(event_call, #type, name, \ ++ offsetof(typeof(field), item), \ ++ sizeof(field.item), is_signed, \ ++ FILTER_OTHER); \ ++ if (ret) \ ++ return ret; \ ++ } while (0) ++ ++ ++/* Flags for trace_probe */ ++#define TP_FLAG_TRACE 1 ++#define TP_FLAG_PROFILE 2 ++#define TP_FLAG_REGISTERED 4 ++#define TP_FLAG_UPROBE 8 ++ ++ ++/* data_rloc: data relative location, compatible with u32 */ ++#define make_data_rloc(len, roffs) \ ++ (((u32)(len) << 16) | ((u32)(roffs) & 0xffff)) ++#define get_rloc_len(dl) ((u32)(dl) >> 16) ++#define get_rloc_offs(dl) ((u32)(dl) & 0xffff) ++ ++/* ++ * Convert data_rloc to data_loc: ++ * data_rloc stores the offset from data_rloc itself, but data_loc ++ * stores the offset from event entry. ++ */ ++#define convert_rloc_to_loc(dl, offs) ((u32)(dl) + (offs)) ++ ++/* Data fetch function type */ ++typedef void (*fetch_func_t)(struct pt_regs *, void *, void *); ++/* Printing function type */ ++typedef int (*print_type_func_t)(struct trace_seq *, const char *, void *, void *); ++ ++/* Fetch types */ ++enum { ++ FETCH_MTD_reg = 0, ++ FETCH_MTD_stack, ++ FETCH_MTD_retval, ++ FETCH_MTD_memory, ++ FETCH_MTD_symbol, ++ FETCH_MTD_deref, ++ FETCH_MTD_bitfield, ++ FETCH_MTD_END, ++}; ++ ++/* Fetch type information table */ ++struct fetch_type { ++ const char *name; /* Name of type */ ++ size_t size; /* Byte size of type */ ++ int is_signed; /* Signed flag */ ++ print_type_func_t print; /* Print functions */ ++ const char *fmt; /* Fromat string */ ++ const char *fmttype; /* Name in format file */ ++ /* Fetch functions */ ++ fetch_func_t fetch[FETCH_MTD_END]; ++}; ++ ++struct fetch_param { ++ fetch_func_t fn; ++ void *data; ++}; ++ ++struct probe_arg { ++ struct fetch_param fetch; ++ struct fetch_param fetch_size; ++ unsigned int offset; /* Offset from argument entry */ ++ const char *name; /* Name of this argument */ ++ const char *comm; /* Command of this argument */ ++ const struct fetch_type *type; /* Type of this argument */ ++}; ++ ++static inline __kprobes void call_fetch(struct fetch_param *fprm, ++ struct pt_regs *regs, void *dest) ++{ ++ return fprm->fn(regs, fprm->data, dest); ++} ++ ++/* Check the name is good for event/group/fields */ ++static inline int is_good_name(const char *name) ++{ ++ if (!isalpha(*name) && *name != '_') ++ return 0; ++ while (*++name != '\0') { ++ if (!isalpha(*name) && !isdigit(*name) && *name != '_') ++ return 0; ++ } ++ return 1; ++} ++ ++extern int traceprobe_parse_probe_arg(char *arg, ssize_t *size, ++ struct probe_arg *parg, bool is_return, bool is_kprobe); ++ ++extern int traceprobe_conflict_field_name(const char *name, ++ struct probe_arg *args, int narg); ++ ++extern void traceprobe_update_arg(struct probe_arg *arg); ++extern void traceprobe_free_probe_arg(struct probe_arg *arg); ++ ++extern int traceprobe_split_symbol_offset(char *symbol, unsigned long *offset); ++ ++extern ssize_t traceprobe_probes_write(struct file *file, ++ const char __user *buffer, size_t count, loff_t *ppos, ++ int (*createfn)(int, char**)); ++ ++extern int traceprobe_command(const char *buf, int (*createfn)(int, char**)); +diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c +new file mode 100644 +index 0000000..2b36ac6 +--- /dev/null ++++ b/kernel/trace/trace_uprobe.c +@@ -0,0 +1,788 @@ ++/* ++ * uprobes-based tracing events ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Copyright (C) IBM Corporation, 2010-2012 ++ * Author: Srikar Dronamraju ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "trace_probe.h" ++ ++#define UPROBE_EVENT_SYSTEM "uprobes" ++ ++/* ++ * uprobe event core functions ++ */ ++struct trace_uprobe; ++struct uprobe_trace_consumer { ++ struct uprobe_consumer cons; ++ struct trace_uprobe *tu; ++}; ++ ++struct trace_uprobe { ++ struct list_head list; ++ struct ftrace_event_class class; ++ struct ftrace_event_call call; ++ struct uprobe_trace_consumer *consumer; ++ struct inode *inode; ++ char *filename; ++ unsigned long offset; ++ unsigned long nhit; ++ unsigned int flags; /* For TP_FLAG_* */ ++ ssize_t size; /* trace entry size */ ++ unsigned int nr_args; ++ struct probe_arg args[]; ++}; ++ ++#define SIZEOF_TRACE_UPROBE(n) \ ++ (offsetof(struct trace_uprobe, args) + \ ++ (sizeof(struct probe_arg) * (n))) ++ ++static int register_uprobe_event(struct trace_uprobe *tu); ++static void unregister_uprobe_event(struct trace_uprobe *tu); ++ ++static DEFINE_MUTEX(uprobe_lock); ++static LIST_HEAD(uprobe_list); ++ ++static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs); ++ ++/* ++ * Allocate new trace_uprobe and initialize it (including uprobes). ++ */ ++static struct trace_uprobe * ++alloc_trace_uprobe(const char *group, const char *event, int nargs) ++{ ++ struct trace_uprobe *tu; ++ ++ if (!event || !is_good_name(event)) ++ return ERR_PTR(-EINVAL); ++ ++ if (!group || !is_good_name(group)) ++ return ERR_PTR(-EINVAL); ++ ++ tu = kzalloc(SIZEOF_TRACE_UPROBE(nargs), GFP_KERNEL); ++ if (!tu) ++ return ERR_PTR(-ENOMEM); ++ ++ tu->call.class = &tu->class; ++ tu->call.name = kstrdup(event, GFP_KERNEL); ++ if (!tu->call.name) ++ goto error; ++ ++ tu->class.system = kstrdup(group, GFP_KERNEL); ++ if (!tu->class.system) ++ goto error; ++ ++ INIT_LIST_HEAD(&tu->list); ++ return tu; ++ ++error: ++ kfree(tu->call.name); ++ kfree(tu); ++ ++ return ERR_PTR(-ENOMEM); ++} ++ ++static void free_trace_uprobe(struct trace_uprobe *tu) ++{ ++ int i; ++ ++ for (i = 0; i < tu->nr_args; i++) ++ traceprobe_free_probe_arg(&tu->args[i]); ++ ++ iput(tu->inode); ++ kfree(tu->call.class->system); ++ kfree(tu->call.name); ++ kfree(tu->filename); ++ kfree(tu); ++} ++ ++static struct trace_uprobe *find_probe_event(const char *event, const char *group) ++{ ++ struct trace_uprobe *tu; ++ ++ list_for_each_entry(tu, &uprobe_list, list) ++ if (strcmp(tu->call.name, event) == 0 && ++ strcmp(tu->call.class->system, group) == 0) ++ return tu; ++ ++ return NULL; ++} ++ ++/* Unregister a trace_uprobe and probe_event: call with locking uprobe_lock */ ++static void unregister_trace_uprobe(struct trace_uprobe *tu) ++{ ++ list_del(&tu->list); ++ unregister_uprobe_event(tu); ++ free_trace_uprobe(tu); ++} ++ ++/* Register a trace_uprobe and probe_event */ ++static int register_trace_uprobe(struct trace_uprobe *tu) ++{ ++ struct trace_uprobe *old_tp; ++ int ret; ++ ++ mutex_lock(&uprobe_lock); ++ ++ /* register as an event */ ++ old_tp = find_probe_event(tu->call.name, tu->call.class->system); ++ if (old_tp) ++ /* delete old event */ ++ unregister_trace_uprobe(old_tp); ++ ++ ret = register_uprobe_event(tu); ++ if (ret) { ++ pr_warning("Failed to register probe event(%d)\n", ret); ++ goto end; ++ } ++ ++ list_add_tail(&tu->list, &uprobe_list); ++ ++end: ++ mutex_unlock(&uprobe_lock); ++ ++ return ret; ++} ++ ++/* ++ * Argument syntax: ++ * - Add uprobe: p[:[GRP/]EVENT] PATH:SYMBOL[+offs] [FETCHARGS] ++ * ++ * - Remove uprobe: -:[GRP/]EVENT ++ */ ++static int create_trace_uprobe(int argc, char **argv) ++{ ++ struct trace_uprobe *tu; ++ struct inode *inode; ++ char *arg, *event, *group, *filename; ++ char buf[MAX_EVENT_NAME_LEN]; ++ struct path path; ++ unsigned long offset; ++ bool is_delete; ++ int i, ret; ++ ++ inode = NULL; ++ ret = 0; ++ is_delete = false; ++ event = NULL; ++ group = NULL; ++ ++ /* argc must be >= 1 */ ++ if (argv[0][0] == '-') ++ is_delete = true; ++ else if (argv[0][0] != 'p') { ++ pr_info("Probe definition must be started with 'p', 'r' or" " '-'.\n"); ++ return -EINVAL; ++ } ++ ++ if (argv[0][1] == ':') { ++ event = &argv[0][2]; ++ arg = strchr(event, '/'); ++ ++ if (arg) { ++ group = event; ++ event = arg + 1; ++ event[-1] = '\0'; ++ ++ if (strlen(group) == 0) { ++ pr_info("Group name is not specified\n"); ++ return -EINVAL; ++ } ++ } ++ if (strlen(event) == 0) { ++ pr_info("Event name is not specified\n"); ++ return -EINVAL; ++ } ++ } ++ if (!group) ++ group = UPROBE_EVENT_SYSTEM; ++ ++ if (is_delete) { ++ if (!event) { ++ pr_info("Delete command needs an event name.\n"); ++ return -EINVAL; ++ } ++ mutex_lock(&uprobe_lock); ++ tu = find_probe_event(event, group); ++ ++ if (!tu) { ++ mutex_unlock(&uprobe_lock); ++ pr_info("Event %s/%s doesn't exist.\n", group, event); ++ return -ENOENT; ++ } ++ /* delete an event */ ++ unregister_trace_uprobe(tu); ++ mutex_unlock(&uprobe_lock); ++ return 0; ++ } ++ ++ if (argc < 2) { ++ pr_info("Probe point is not specified.\n"); ++ return -EINVAL; ++ } ++ if (isdigit(argv[1][0])) { ++ pr_info("probe point must be have a filename.\n"); ++ return -EINVAL; ++ } ++ arg = strchr(argv[1], ':'); ++ if (!arg) ++ goto fail_address_parse; ++ ++ *arg++ = '\0'; ++ filename = argv[1]; ++ ret = kern_path(filename, LOOKUP_FOLLOW, &path); ++ if (ret) ++ goto fail_address_parse; ++ ++ ret = strict_strtoul(arg, 0, &offset); ++ if (ret) ++ goto fail_address_parse; ++ ++ inode = igrab(path.dentry->d_inode); ++ ++ argc -= 2; ++ argv += 2; ++ ++ /* setup a probe */ ++ if (!event) { ++ char *tail = strrchr(filename, '/'); ++ char *ptr; ++ ++ ptr = kstrdup((tail ? tail + 1 : filename), GFP_KERNEL); ++ if (!ptr) { ++ ret = -ENOMEM; ++ goto fail_address_parse; ++ } ++ ++ tail = ptr; ++ ptr = strpbrk(tail, ".-_"); ++ if (ptr) ++ *ptr = '\0'; ++ ++ snprintf(buf, MAX_EVENT_NAME_LEN, "%c_%s_0x%lx", 'p', tail, offset); ++ event = buf; ++ kfree(tail); ++ } ++ ++ tu = alloc_trace_uprobe(group, event, argc); ++ if (IS_ERR(tu)) { ++ pr_info("Failed to allocate trace_uprobe.(%d)\n", (int)PTR_ERR(tu)); ++ ret = PTR_ERR(tu); ++ goto fail_address_parse; ++ } ++ tu->offset = offset; ++ tu->inode = inode; ++ tu->filename = kstrdup(filename, GFP_KERNEL); ++ ++ if (!tu->filename) { ++ pr_info("Failed to allocate filename.\n"); ++ ret = -ENOMEM; ++ goto error; ++ } ++ ++ /* parse arguments */ ++ ret = 0; ++ for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { ++ /* Increment count for freeing args in error case */ ++ tu->nr_args++; ++ ++ /* Parse argument name */ ++ arg = strchr(argv[i], '='); ++ if (arg) { ++ *arg++ = '\0'; ++ tu->args[i].name = kstrdup(argv[i], GFP_KERNEL); ++ } else { ++ arg = argv[i]; ++ /* If argument name is omitted, set "argN" */ ++ snprintf(buf, MAX_EVENT_NAME_LEN, "arg%d", i + 1); ++ tu->args[i].name = kstrdup(buf, GFP_KERNEL); ++ } ++ ++ if (!tu->args[i].name) { ++ pr_info("Failed to allocate argument[%d] name.\n", i); ++ ret = -ENOMEM; ++ goto error; ++ } ++ ++ if (!is_good_name(tu->args[i].name)) { ++ pr_info("Invalid argument[%d] name: %s\n", i, tu->args[i].name); ++ ret = -EINVAL; ++ goto error; ++ } ++ ++ if (traceprobe_conflict_field_name(tu->args[i].name, tu->args, i)) { ++ pr_info("Argument[%d] name '%s' conflicts with " ++ "another field.\n", i, argv[i]); ++ ret = -EINVAL; ++ goto error; ++ } ++ ++ /* Parse fetch argument */ ++ ret = traceprobe_parse_probe_arg(arg, &tu->size, &tu->args[i], false, false); ++ if (ret) { ++ pr_info("Parse error at argument[%d]. (%d)\n", i, ret); ++ goto error; ++ } ++ } ++ ++ ret = register_trace_uprobe(tu); ++ if (ret) ++ goto error; ++ return 0; ++ ++error: ++ free_trace_uprobe(tu); ++ return ret; ++ ++fail_address_parse: ++ if (inode) ++ iput(inode); ++ ++ pr_info("Failed to parse address.\n"); ++ ++ return ret; ++} ++ ++static void cleanup_all_probes(void) ++{ ++ struct trace_uprobe *tu; ++ ++ mutex_lock(&uprobe_lock); ++ while (!list_empty(&uprobe_list)) { ++ tu = list_entry(uprobe_list.next, struct trace_uprobe, list); ++ unregister_trace_uprobe(tu); ++ } ++ mutex_unlock(&uprobe_lock); ++} ++ ++/* Probes listing interfaces */ ++static void *probes_seq_start(struct seq_file *m, loff_t *pos) ++{ ++ mutex_lock(&uprobe_lock); ++ return seq_list_start(&uprobe_list, *pos); ++} ++ ++static void *probes_seq_next(struct seq_file *m, void *v, loff_t *pos) ++{ ++ return seq_list_next(v, &uprobe_list, pos); ++} ++ ++static void probes_seq_stop(struct seq_file *m, void *v) ++{ ++ mutex_unlock(&uprobe_lock); ++} ++ ++static int probes_seq_show(struct seq_file *m, void *v) ++{ ++ struct trace_uprobe *tu = v; ++ int i; ++ ++ seq_printf(m, "p:%s/%s", tu->call.class->system, tu->call.name); ++ seq_printf(m, " %s:0x%p", tu->filename, (void *)tu->offset); ++ ++ for (i = 0; i < tu->nr_args; i++) ++ seq_printf(m, " %s=%s", tu->args[i].name, tu->args[i].comm); ++ ++ seq_printf(m, "\n"); ++ return 0; ++} ++ ++static const struct seq_operations probes_seq_op = { ++ .start = probes_seq_start, ++ .next = probes_seq_next, ++ .stop = probes_seq_stop, ++ .show = probes_seq_show ++}; ++ ++static int probes_open(struct inode *inode, struct file *file) ++{ ++ if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) ++ cleanup_all_probes(); ++ ++ return seq_open(file, &probes_seq_op); ++} ++ ++static ssize_t probes_write(struct file *file, const char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ return traceprobe_probes_write(file, buffer, count, ppos, create_trace_uprobe); ++} ++ ++static const struct file_operations uprobe_events_ops = { ++ .owner = THIS_MODULE, ++ .open = probes_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = seq_release, ++ .write = probes_write, ++}; ++ ++/* Probes profiling interfaces */ ++static int probes_profile_seq_show(struct seq_file *m, void *v) ++{ ++ struct trace_uprobe *tu = v; ++ ++ seq_printf(m, " %s %-44s %15lu\n", tu->filename, tu->call.name, tu->nhit); ++ return 0; ++} ++ ++static const struct seq_operations profile_seq_op = { ++ .start = probes_seq_start, ++ .next = probes_seq_next, ++ .stop = probes_seq_stop, ++ .show = probes_profile_seq_show ++}; ++ ++static int profile_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &profile_seq_op); ++} ++ ++static const struct file_operations uprobe_profile_ops = { ++ .owner = THIS_MODULE, ++ .open = profile_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = seq_release, ++}; ++ ++/* uprobe handler */ ++static void uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs) ++{ ++ struct uprobe_trace_entry_head *entry; ++ struct ring_buffer_event *event; ++ struct ring_buffer *buffer; ++ u8 *data; ++ int size, i, pc; ++ unsigned long irq_flags; ++ struct ftrace_event_call *call = &tu->call; ++ ++ tu->nhit++; ++ ++ local_save_flags(irq_flags); ++ pc = preempt_count(); ++ ++ size = sizeof(*entry) + tu->size; ++ ++ event = trace_current_buffer_lock_reserve(&buffer, call->event.type, ++ size, irq_flags, pc); ++ if (!event) ++ return; ++ ++ entry = ring_buffer_event_data(event); ++ entry->ip = uprobe_get_swbp_addr(task_pt_regs(current)); ++ data = (u8 *)&entry[1]; ++ for (i = 0; i < tu->nr_args; i++) ++ call_fetch(&tu->args[i].fetch, regs, data + tu->args[i].offset); ++ ++ if (!filter_current_check_discard(buffer, call, entry, event)) ++ trace_buffer_unlock_commit(buffer, event, irq_flags, pc); ++} ++ ++/* Event entry printers */ ++static enum print_line_t ++print_uprobe_event(struct trace_iterator *iter, int flags, struct trace_event *event) ++{ ++ struct uprobe_trace_entry_head *field; ++ struct trace_seq *s = &iter->seq; ++ struct trace_uprobe *tu; ++ u8 *data; ++ int i; ++ ++ field = (struct uprobe_trace_entry_head *)iter->ent; ++ tu = container_of(event, struct trace_uprobe, call.event); ++ ++ if (!trace_seq_printf(s, "%s: (", tu->call.name)) ++ goto partial; ++ ++ if (!seq_print_ip_sym(s, field->ip, flags | TRACE_ITER_SYM_OFFSET)) ++ goto partial; ++ ++ if (!trace_seq_puts(s, ")")) ++ goto partial; ++ ++ data = (u8 *)&field[1]; ++ for (i = 0; i < tu->nr_args; i++) { ++ if (!tu->args[i].type->print(s, tu->args[i].name, ++ data + tu->args[i].offset, field)) ++ goto partial; ++ } ++ ++ if (trace_seq_puts(s, "\n")) ++ return TRACE_TYPE_HANDLED; ++ ++partial: ++ return TRACE_TYPE_PARTIAL_LINE; ++} ++ ++static int probe_event_enable(struct trace_uprobe *tu, int flag) ++{ ++ struct uprobe_trace_consumer *utc; ++ int ret = 0; ++ ++ if (!tu->inode || tu->consumer) ++ return -EINTR; ++ ++ utc = kzalloc(sizeof(struct uprobe_trace_consumer), GFP_KERNEL); ++ if (!utc) ++ return -EINTR; ++ ++ utc->cons.handler = uprobe_dispatcher; ++ utc->cons.filter = NULL; ++ ret = uprobe_register(tu->inode, tu->offset, &utc->cons); ++ if (ret) { ++ kfree(utc); ++ return ret; ++ } ++ ++ tu->flags |= flag; ++ utc->tu = tu; ++ tu->consumer = utc; ++ ++ return 0; ++} ++ ++static void probe_event_disable(struct trace_uprobe *tu, int flag) ++{ ++ if (!tu->inode || !tu->consumer) ++ return; ++ ++ uprobe_unregister(tu->inode, tu->offset, &tu->consumer->cons); ++ tu->flags &= ~flag; ++ kfree(tu->consumer); ++ tu->consumer = NULL; ++} ++ ++static int uprobe_event_define_fields(struct ftrace_event_call *event_call) ++{ ++ int ret, i; ++ struct uprobe_trace_entry_head field; ++ struct trace_uprobe *tu = (struct trace_uprobe *)event_call->data; ++ ++ DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); ++ /* Set argument names as fields */ ++ for (i = 0; i < tu->nr_args; i++) { ++ ret = trace_define_field(event_call, tu->args[i].type->fmttype, ++ tu->args[i].name, ++ sizeof(field) + tu->args[i].offset, ++ tu->args[i].type->size, ++ tu->args[i].type->is_signed, ++ FILTER_OTHER); ++ ++ if (ret) ++ return ret; ++ } ++ return 0; ++} ++ ++#define LEN_OR_ZERO (len ? len - pos : 0) ++static int __set_print_fmt(struct trace_uprobe *tu, char *buf, int len) ++{ ++ const char *fmt, *arg; ++ int i; ++ int pos = 0; ++ ++ fmt = "(%lx)"; ++ arg = "REC->" FIELD_STRING_IP; ++ ++ /* When len=0, we just calculate the needed length */ ++ ++ pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt); ++ ++ for (i = 0; i < tu->nr_args; i++) { ++ pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%s", ++ tu->args[i].name, tu->args[i].type->fmt); ++ } ++ ++ pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg); ++ ++ for (i = 0; i < tu->nr_args; i++) { ++ pos += snprintf(buf + pos, LEN_OR_ZERO, ", REC->%s", ++ tu->args[i].name); ++ } ++ ++ return pos; /* return the length of print_fmt */ ++} ++#undef LEN_OR_ZERO ++ ++static int set_print_fmt(struct trace_uprobe *tu) ++{ ++ char *print_fmt; ++ int len; ++ ++ /* First: called with 0 length to calculate the needed length */ ++ len = __set_print_fmt(tu, NULL, 0); ++ print_fmt = kmalloc(len + 1, GFP_KERNEL); ++ if (!print_fmt) ++ return -ENOMEM; ++ ++ /* Second: actually write the @print_fmt */ ++ __set_print_fmt(tu, print_fmt, len + 1); ++ tu->call.print_fmt = print_fmt; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PERF_EVENTS ++/* uprobe profile handler */ ++static void uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs) ++{ ++ struct ftrace_event_call *call = &tu->call; ++ struct uprobe_trace_entry_head *entry; ++ struct hlist_head *head; ++ u8 *data; ++ int size, __size, i; ++ int rctx; ++ ++ __size = sizeof(*entry) + tu->size; ++ size = ALIGN(__size + sizeof(u32), sizeof(u64)); ++ size -= sizeof(u32); ++ if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, "profile buffer not large enough")) ++ return; ++ ++ preempt_disable(); ++ ++ entry = perf_trace_buf_prepare(size, call->event.type, regs, &rctx); ++ if (!entry) ++ goto out; ++ ++ entry->ip = uprobe_get_swbp_addr(task_pt_regs(current)); ++ data = (u8 *)&entry[1]; ++ for (i = 0; i < tu->nr_args; i++) ++ call_fetch(&tu->args[i].fetch, regs, data + tu->args[i].offset); ++ ++ head = this_cpu_ptr(call->perf_events); ++ perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head); ++ ++ out: ++ preempt_enable(); ++} ++#endif /* CONFIG_PERF_EVENTS */ ++ ++static ++int trace_uprobe_register(struct ftrace_event_call *event, enum trace_reg type, void *data) ++{ ++ struct trace_uprobe *tu = (struct trace_uprobe *)event->data; ++ ++ switch (type) { ++ case TRACE_REG_REGISTER: ++ return probe_event_enable(tu, TP_FLAG_TRACE); ++ ++ case TRACE_REG_UNREGISTER: ++ probe_event_disable(tu, TP_FLAG_TRACE); ++ return 0; ++ ++#ifdef CONFIG_PERF_EVENTS ++ case TRACE_REG_PERF_REGISTER: ++ return probe_event_enable(tu, TP_FLAG_PROFILE); ++ ++ case TRACE_REG_PERF_UNREGISTER: ++ probe_event_disable(tu, TP_FLAG_PROFILE); ++ return 0; ++#endif ++ default: ++ return 0; ++ } ++ return 0; ++} ++ ++static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs) ++{ ++ struct uprobe_trace_consumer *utc; ++ struct trace_uprobe *tu; ++ ++ utc = container_of(con, struct uprobe_trace_consumer, cons); ++ tu = utc->tu; ++ if (!tu || tu->consumer != utc) ++ return 0; ++ ++ if (tu->flags & TP_FLAG_TRACE) ++ uprobe_trace_func(tu, regs); ++ ++#ifdef CONFIG_PERF_EVENTS ++ if (tu->flags & TP_FLAG_PROFILE) ++ uprobe_perf_func(tu, regs); ++#endif ++ return 0; ++} ++ ++static struct trace_event_functions uprobe_funcs = { ++ .trace = print_uprobe_event ++}; ++ ++static int register_uprobe_event(struct trace_uprobe *tu) ++{ ++ struct ftrace_event_call *call = &tu->call; ++ int ret; ++ ++ /* Initialize ftrace_event_call */ ++ INIT_LIST_HEAD(&call->class->fields); ++ call->event.funcs = &uprobe_funcs; ++ call->class->define_fields = uprobe_event_define_fields; ++ ++ if (set_print_fmt(tu) < 0) ++ return -ENOMEM; ++ ++ ret = register_ftrace_event(&call->event); ++ if (!ret) { ++ kfree(call->print_fmt); ++ return -ENODEV; ++ } ++ call->flags = 0; ++ call->class->reg = trace_uprobe_register; ++ call->data = tu; ++ ret = trace_add_event_call(call); ++ ++ if (ret) { ++ pr_info("Failed to register uprobe event: %s\n", call->name); ++ kfree(call->print_fmt); ++ unregister_ftrace_event(&call->event); ++ } ++ ++ return ret; ++} ++ ++static void unregister_uprobe_event(struct trace_uprobe *tu) ++{ ++ /* tu->event is unregistered in trace_remove_event_call() */ ++ trace_remove_event_call(&tu->call); ++ kfree(tu->call.print_fmt); ++ tu->call.print_fmt = NULL; ++} ++ ++/* Make a trace interface for controling probe points */ ++static __init int init_uprobe_trace(void) ++{ ++ struct dentry *d_tracer; ++ ++ d_tracer = tracing_init_dentry(); ++ if (!d_tracer) ++ return 0; ++ ++ trace_create_file("uprobe_events", 0644, d_tracer, ++ NULL, &uprobe_events_ops); ++ /* Profile interface */ ++ trace_create_file("uprobe_profile", 0444, d_tracer, ++ NULL, &uprobe_profile_ops); ++ return 0; ++} ++ ++fs_initcall(init_uprobe_trace); +diff --git a/mm/memory.c b/mm/memory.c +index 6105f47..bf8b403 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -1307,6 +1307,9 @@ static void unmap_single_vma(struct mmu_gather *tlb, + if (end <= vma->vm_start) + return; + ++ if (vma->vm_file) ++ uprobe_munmap(vma, start, end); ++ + if (vma->vm_flags & VM_ACCOUNT) + *nr_accounted += (end - start) >> PAGE_SHIFT; + +diff --git a/mm/mmap.c b/mm/mmap.c +index 848ef52..b8c4072 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -546,8 +547,15 @@ again: remove_next = 1 + (end > next->vm_end); + + if (file) { + mapping = file->f_mapping; +- if (!(vma->vm_flags & VM_NONLINEAR)) ++ if (!(vma->vm_flags & VM_NONLINEAR)) { + root = &mapping->i_mmap; ++ uprobe_munmap(vma, vma->vm_start, vma->vm_end); ++ ++ if (adjust_next) ++ uprobe_munmap(next, next->vm_start, ++ next->vm_end); ++ } ++ + mutex_lock(&mapping->i_mmap_mutex); + if (insert) { + /* +@@ -617,8 +625,16 @@ again: remove_next = 1 + (end > next->vm_end); + if (mapping) + mutex_unlock(&mapping->i_mmap_mutex); + ++ if (root) { ++ uprobe_mmap(vma); ++ ++ if (adjust_next) ++ uprobe_mmap(next); ++ } ++ + if (remove_next) { + if (file) { ++ uprobe_munmap(next, next->vm_start, next->vm_end); + fput(file); + if (next->vm_flags & VM_EXECUTABLE) + removed_exe_file_vma(mm); +@@ -638,6 +654,8 @@ again: remove_next = 1 + (end > next->vm_end); + goto again; + } + } ++ if (insert && file) ++ uprobe_mmap(insert); + + validate_mm(mm); + +@@ -1371,6 +1389,11 @@ out: + mm->locked_vm += (len >> PAGE_SHIFT); + } else if ((flags & MAP_POPULATE) && !(flags & MAP_NONBLOCK)) + make_pages_present(addr, addr + len); ++ ++ if (file && uprobe_mmap(vma)) ++ /* matching probes but cannot insert */ ++ goto unmap_and_free_vma; ++ + return addr; + + unmap_and_free_vma: +@@ -2352,6 +2375,10 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) + if ((vma->vm_flags & VM_ACCOUNT) && + security_vm_enough_memory_mm(mm, vma_pages(vma))) + return -ENOMEM; ++ ++ if (vma->vm_file && uprobe_mmap(vma)) ++ return -EINVAL; ++ + vma_link(mm, vma, prev, rb_link, rb_parent); + return 0; + } +@@ -2421,6 +2448,10 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, + new_vma->vm_pgoff = pgoff; + if (new_vma->vm_file) { + get_file(new_vma->vm_file); ++ ++ if (uprobe_mmap(new_vma)) ++ goto out_free_mempol; ++ + if (vma->vm_flags & VM_EXECUTABLE) + added_exe_file_vma(mm); + } +diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt +index 2780d9c..b715cb7 100644 +--- a/tools/perf/Documentation/perf-probe.txt ++++ b/tools/perf/Documentation/perf-probe.txt +@@ -77,7 +77,8 @@ OPTIONS + + -F:: + --funcs:: +- Show available functions in given module or kernel. ++ Show available functions in given module or kernel. With -x/--exec, ++ can also list functions in a user space executable / shared library. + + --filter=FILTER:: + (Only for --vars and --funcs) Set filter. FILTER is a combination of glob +@@ -98,6 +99,15 @@ OPTIONS + --max-probes:: + Set the maximum number of probe points for an event. Default is 128. + ++-x:: ++--exec=PATH:: ++ Specify path to the executable or shared library file for user ++ space tracing. Can also be used with --funcs option. ++ ++In absence of -m/-x options, perf probe checks if the first argument after ++the options is an absolute path name. If its an absolute path, perf probe ++uses it as a target module/target user space binary to probe. ++ + PROBE SYNTAX + ------------ + Probe points are defined by following syntax. +@@ -182,6 +192,13 @@ Delete all probes on schedule(). + + ./perf probe --del='schedule*' + ++Add probes at zfree() function on /bin/zsh ++ ++ ./perf probe -x /bin/zsh zfree or ./perf probe /bin/zsh zfree ++ ++Add probes at malloc() function on libc ++ ++ ./perf probe -x /lib/libc.so.6 malloc or ./perf probe /lib/libc.so.6 malloc + + SEE ALSO + -------- +diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c +index 4935c09..e215ae6 100644 +--- a/tools/perf/builtin-probe.c ++++ b/tools/perf/builtin-probe.c +@@ -54,6 +54,7 @@ static struct { + bool show_ext_vars; + bool show_funcs; + bool mod_events; ++ bool uprobes; + int nevents; + struct perf_probe_event events[MAX_PROBES]; + struct strlist *dellist; +@@ -75,6 +76,8 @@ static int parse_probe_event(const char *str) + return -1; + } + ++ pev->uprobes = params.uprobes; ++ + /* Parse a perf-probe command into event */ + ret = parse_perf_probe_command(str, pev); + pr_debug("%d arguments\n", pev->nargs); +@@ -82,21 +85,58 @@ static int parse_probe_event(const char *str) + return ret; + } + ++static int set_target(const char *ptr) ++{ ++ int found = 0; ++ const char *buf; ++ ++ /* ++ * The first argument after options can be an absolute path ++ * to an executable / library or kernel module. ++ * ++ * TODO: Support relative path, and $PATH, $LD_LIBRARY_PATH, ++ * short module name. ++ */ ++ if (!params.target && ptr && *ptr == '/') { ++ params.target = ptr; ++ found = 1; ++ buf = ptr + (strlen(ptr) - 3); ++ ++ if (strcmp(buf, ".ko")) ++ params.uprobes = true; ++ ++ } ++ ++ return found; ++} ++ + static int parse_probe_event_argv(int argc, const char **argv) + { +- int i, len, ret; ++ int i, len, ret, found_target; + char *buf; + ++ found_target = set_target(argv[0]); ++ if (found_target && argc == 1) ++ return 0; ++ + /* Bind up rest arguments */ + len = 0; +- for (i = 0; i < argc; i++) ++ for (i = 0; i < argc; i++) { ++ if (i == 0 && found_target) ++ continue; ++ + len += strlen(argv[i]) + 1; ++ } + buf = zalloc(len + 1); + if (buf == NULL) + return -ENOMEM; + len = 0; +- for (i = 0; i < argc; i++) ++ for (i = 0; i < argc; i++) { ++ if (i == 0 && found_target) ++ continue; ++ + len += sprintf(&buf[len], "%s ", argv[i]); ++ } + params.mod_events = true; + ret = parse_probe_event(buf); + free(buf); +@@ -125,6 +165,28 @@ static int opt_del_probe_event(const struct option *opt __used, + return 0; + } + ++static int opt_set_target(const struct option *opt, const char *str, ++ int unset __used) ++{ ++ int ret = -ENOENT; ++ ++ if (str && !params.target) { ++ if (!strcmp(opt->long_name, "exec")) ++ params.uprobes = true; ++#ifdef DWARF_SUPPORT ++ else if (!strcmp(opt->long_name, "module")) ++ params.uprobes = false; ++#endif ++ else ++ return ret; ++ ++ params.target = str; ++ ret = 0; ++ } ++ ++ return ret; ++} ++ + #ifdef DWARF_SUPPORT + static int opt_show_lines(const struct option *opt __used, + const char *str, int unset __used) +@@ -246,9 +308,9 @@ static const struct option options[] = { + "file", "vmlinux pathname"), + OPT_STRING('s', "source", &symbol_conf.source_prefix, + "directory", "path to kernel source"), +- OPT_STRING('m', "module", ¶ms.target, +- "modname|path", +- "target module name (for online) or path (for offline)"), ++ OPT_CALLBACK('m', "module", NULL, "modname|path", ++ "target module name (for online) or path (for offline)", ++ opt_set_target), + #endif + OPT__DRY_RUN(&probe_event_dry_run), + OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, +@@ -260,6 +322,8 @@ static const struct option options[] = { + "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n" + "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)", + opt_set_filter), ++ OPT_CALLBACK('x', "exec", NULL, "executable|path", ++ "target executable name or path", opt_set_target), + OPT_END() + }; + +@@ -310,6 +374,10 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) + pr_err(" Error: Don't use --list with --funcs.\n"); + usage_with_options(probe_usage, options); + } ++ if (params.uprobes) { ++ pr_warning(" Error: Don't use --list with --exec.\n"); ++ usage_with_options(probe_usage, options); ++ } + ret = show_perf_probe_events(); + if (ret < 0) + pr_err(" Error: Failed to show event list. (%d)\n", +@@ -333,8 +401,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) + if (!params.filter) + params.filter = strfilter__new(DEFAULT_FUNC_FILTER, + NULL); +- ret = show_available_funcs(params.target, +- params.filter); ++ ret = show_available_funcs(params.target, params.filter, ++ params.uprobes); + strfilter__delete(params.filter); + if (ret < 0) + pr_err(" Error: Failed to show functions." +@@ -343,7 +411,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) + } + + #ifdef DWARF_SUPPORT +- if (params.show_lines) { ++ if (params.show_lines && !params.uprobes) { + if (params.mod_events) { + pr_err(" Error: Don't use --line with" + " --add/--del.\n"); +diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c +index 8a8ee64..0dda25d 100644 +--- a/tools/perf/util/probe-event.c ++++ b/tools/perf/util/probe-event.c +@@ -44,6 +44,7 @@ + #include "trace-event.h" /* For __unused */ + #include "probe-event.h" + #include "probe-finder.h" ++#include "session.h" + + #define MAX_CMDLEN 256 + #define MAX_PROBE_ARGS 128 +@@ -70,6 +71,8 @@ static int e_snprintf(char *str, size_t size, const char *format, ...) + } + + static char *synthesize_perf_probe_point(struct perf_probe_point *pp); ++static int convert_name_to_addr(struct perf_probe_event *pev, ++ const char *exec); + static struct machine machine; + + /* Initialize symbol maps and path of vmlinux/modules */ +@@ -170,6 +173,34 @@ const char *kernel_get_module_path(const char *module) + return (dso) ? dso->long_name : NULL; + } + ++static int init_user_exec(void) ++{ ++ int ret = 0; ++ ++ symbol_conf.try_vmlinux_path = false; ++ symbol_conf.sort_by_name = true; ++ ret = symbol__init(); ++ ++ if (ret < 0) ++ pr_debug("Failed to init symbol map.\n"); ++ ++ return ret; ++} ++ ++static int convert_to_perf_probe_point(struct probe_trace_point *tp, ++ struct perf_probe_point *pp) ++{ ++ pp->function = strdup(tp->symbol); ++ ++ if (pp->function == NULL) ++ return -ENOMEM; ++ ++ pp->offset = tp->offset; ++ pp->retprobe = tp->retprobe; ++ ++ return 0; ++} ++ + #ifdef DWARF_SUPPORT + /* Open new debuginfo of given module */ + static struct debuginfo *open_debuginfo(const char *module) +@@ -224,10 +255,7 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, + if (ret <= 0) { + pr_debug("Failed to find corresponding probes from " + "debuginfo. Use kprobe event information.\n"); +- pp->function = strdup(tp->symbol); +- if (pp->function == NULL) +- return -ENOMEM; +- pp->offset = tp->offset; ++ return convert_to_perf_probe_point(tp, pp); + } + pp->retprobe = tp->retprobe; + +@@ -275,9 +303,20 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, + int max_tevs, const char *target) + { + bool need_dwarf = perf_probe_event_need_dwarf(pev); +- struct debuginfo *dinfo = open_debuginfo(target); ++ struct debuginfo *dinfo; + int ntevs, ret = 0; + ++ if (pev->uprobes) { ++ if (need_dwarf) { ++ pr_warning("Debuginfo-analysis is not yet supported" ++ " with -x/--exec option.\n"); ++ return -ENOSYS; ++ } ++ return convert_name_to_addr(pev, target); ++ } ++ ++ dinfo = open_debuginfo(target); ++ + if (!dinfo) { + if (need_dwarf) { + pr_warning("Failed to open debuginfo file.\n"); +@@ -603,23 +642,22 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, + pr_err("Failed to find symbol %s in kernel.\n", tp->symbol); + return -ENOENT; + } +- pp->function = strdup(tp->symbol); +- if (pp->function == NULL) +- return -ENOMEM; +- pp->offset = tp->offset; +- pp->retprobe = tp->retprobe; + +- return 0; ++ return convert_to_perf_probe_point(tp, pp); + } + + static int try_to_find_probe_trace_events(struct perf_probe_event *pev, + struct probe_trace_event **tevs __unused, +- int max_tevs __unused, const char *mod __unused) ++ int max_tevs __unused, const char *target) + { + if (perf_probe_event_need_dwarf(pev)) { + pr_warning("Debuginfo-analysis is not supported.\n"); + return -ENOSYS; + } ++ ++ if (pev->uprobes) ++ return convert_name_to_addr(pev, target); ++ + return 0; + } + +@@ -1341,11 +1379,18 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev) + if (buf == NULL) + return NULL; + +- len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu", +- tp->retprobe ? 'r' : 'p', +- tev->group, tev->event, +- tp->module ?: "", tp->module ? ":" : "", +- tp->symbol, tp->offset); ++ if (tev->uprobes) ++ len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s:%s", ++ tp->retprobe ? 'r' : 'p', ++ tev->group, tev->event, ++ tp->module, tp->symbol); ++ else ++ len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu", ++ tp->retprobe ? 'r' : 'p', ++ tev->group, tev->event, ++ tp->module ?: "", tp->module ? ":" : "", ++ tp->symbol, tp->offset); ++ + if (len <= 0) + goto error; + +@@ -1364,7 +1409,7 @@ error: + } + + static int convert_to_perf_probe_event(struct probe_trace_event *tev, +- struct perf_probe_event *pev) ++ struct perf_probe_event *pev, bool is_kprobe) + { + char buf[64] = ""; + int i, ret; +@@ -1376,7 +1421,11 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev, + return -ENOMEM; + + /* Convert trace_point to probe_point */ +- ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point); ++ if (is_kprobe) ++ ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point); ++ else ++ ret = convert_to_perf_probe_point(&tev->point, &pev->point); ++ + if (ret < 0) + return ret; + +@@ -1472,7 +1521,26 @@ static void clear_probe_trace_event(struct probe_trace_event *tev) + memset(tev, 0, sizeof(*tev)); + } + +-static int open_kprobe_events(bool readwrite) ++static void print_warn_msg(const char *file, bool is_kprobe) ++{ ++ ++ if (errno == ENOENT) { ++ const char *config; ++ ++ if (!is_kprobe) ++ config = "CONFIG_UPROBE_EVENTS"; ++ else ++ config = "CONFIG_KPROBE_EVENTS"; ++ ++ pr_warning("%s file does not exist - please rebuild kernel" ++ " with %s.\n", file, config); ++ } else ++ pr_warning("Failed to open %s file: %s\n", file, ++ strerror(errno)); ++} ++ ++static int open_probe_events(const char *trace_file, bool readwrite, ++ bool is_kprobe) + { + char buf[PATH_MAX]; + const char *__debugfs; +@@ -1484,27 +1552,31 @@ static int open_kprobe_events(bool readwrite) + return -ENOENT; + } + +- ret = e_snprintf(buf, PATH_MAX, "%stracing/kprobe_events", __debugfs); ++ ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file); + if (ret >= 0) { + pr_debug("Opening %s write=%d\n", buf, readwrite); + if (readwrite && !probe_event_dry_run) + ret = open(buf, O_RDWR, O_APPEND); + else + ret = open(buf, O_RDONLY, 0); +- } + +- if (ret < 0) { +- if (errno == ENOENT) +- pr_warning("kprobe_events file does not exist - please" +- " rebuild kernel with CONFIG_KPROBE_EVENT.\n"); +- else +- pr_warning("Failed to open kprobe_events file: %s\n", +- strerror(errno)); ++ if (ret < 0) ++ print_warn_msg(buf, is_kprobe); + } + return ret; + } + +-/* Get raw string list of current kprobe_events */ ++static int open_kprobe_events(bool readwrite) ++{ ++ return open_probe_events("tracing/kprobe_events", readwrite, true); ++} ++ ++static int open_uprobe_events(bool readwrite) ++{ ++ return open_probe_events("tracing/uprobe_events", readwrite, false); ++} ++ ++/* Get raw string list of current kprobe_events or uprobe_events */ + static struct strlist *get_probe_trace_command_rawlist(int fd) + { + int ret, idx; +@@ -1569,36 +1641,26 @@ static int show_perf_probe_event(struct perf_probe_event *pev) + return ret; + } + +-/* List up current perf-probe events */ +-int show_perf_probe_events(void) ++static int __show_perf_probe_events(int fd, bool is_kprobe) + { +- int fd, ret; ++ int ret = 0; + struct probe_trace_event tev; + struct perf_probe_event pev; + struct strlist *rawlist; + struct str_node *ent; + +- setup_pager(); +- ret = init_vmlinux(); +- if (ret < 0) +- return ret; +- + memset(&tev, 0, sizeof(tev)); + memset(&pev, 0, sizeof(pev)); + +- fd = open_kprobe_events(false); +- if (fd < 0) +- return fd; +- + rawlist = get_probe_trace_command_rawlist(fd); +- close(fd); + if (!rawlist) + return -ENOENT; + + strlist__for_each(ent, rawlist) { + ret = parse_probe_trace_command(ent->s, &tev); + if (ret >= 0) { +- ret = convert_to_perf_probe_event(&tev, &pev); ++ ret = convert_to_perf_probe_event(&tev, &pev, ++ is_kprobe); + if (ret >= 0) + ret = show_perf_probe_event(&pev); + } +@@ -1612,6 +1674,33 @@ int show_perf_probe_events(void) + return ret; + } + ++/* List up current perf-probe events */ ++int show_perf_probe_events(void) ++{ ++ int fd, ret; ++ ++ setup_pager(); ++ fd = open_kprobe_events(false); ++ ++ if (fd < 0) ++ return fd; ++ ++ ret = init_vmlinux(); ++ if (ret < 0) ++ return ret; ++ ++ ret = __show_perf_probe_events(fd, true); ++ close(fd); ++ ++ fd = open_uprobe_events(false); ++ if (fd >= 0) { ++ ret = __show_perf_probe_events(fd, false); ++ close(fd); ++ } ++ ++ return ret; ++} ++ + /* Get current perf-probe event names */ + static struct strlist *get_probe_trace_event_names(int fd, bool include_group) + { +@@ -1717,7 +1806,11 @@ static int __add_probe_trace_events(struct perf_probe_event *pev, + const char *event, *group; + struct strlist *namelist; + +- fd = open_kprobe_events(true); ++ if (pev->uprobes) ++ fd = open_uprobe_events(true); ++ else ++ fd = open_kprobe_events(true); ++ + if (fd < 0) + return fd; + /* Get current event names */ +@@ -1829,6 +1922,8 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, + tev->point.offset = pev->point.offset; + tev->point.retprobe = pev->point.retprobe; + tev->nargs = pev->nargs; ++ tev->uprobes = pev->uprobes; ++ + if (tev->nargs) { + tev->args = zalloc(sizeof(struct probe_trace_arg) + * tev->nargs); +@@ -1859,6 +1954,9 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, + } + } + ++ if (pev->uprobes) ++ return 1; ++ + /* Currently just checking function name from symbol map */ + sym = __find_kernel_function_by_name(tev->point.symbol, NULL); + if (!sym) { +@@ -1894,12 +1992,18 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, + int i, j, ret; + struct __event_package *pkgs; + ++ ret = 0; + pkgs = zalloc(sizeof(struct __event_package) * npevs); ++ + if (pkgs == NULL) + return -ENOMEM; + +- /* Init vmlinux path */ +- ret = init_vmlinux(); ++ if (!pevs->uprobes) ++ /* Init vmlinux path */ ++ ret = init_vmlinux(); ++ else ++ ret = init_user_exec(); ++ + if (ret < 0) { + free(pkgs); + return ret; +@@ -1971,23 +2075,15 @@ error: + return ret; + } + +-static int del_trace_probe_event(int fd, const char *group, +- const char *event, struct strlist *namelist) ++static int del_trace_probe_event(int fd, const char *buf, ++ struct strlist *namelist) + { +- char buf[128]; + struct str_node *ent, *n; +- int found = 0, ret = 0; +- +- ret = e_snprintf(buf, 128, "%s:%s", group, event); +- if (ret < 0) { +- pr_err("Failed to copy event.\n"); +- return ret; +- } ++ int ret = -1; + + if (strpbrk(buf, "*?")) { /* Glob-exp */ + strlist__for_each_safe(ent, n, namelist) + if (strglobmatch(ent->s, buf)) { +- found++; + ret = __del_trace_probe_event(fd, ent); + if (ret < 0) + break; +@@ -1996,40 +2092,43 @@ static int del_trace_probe_event(int fd, const char *group, + } else { + ent = strlist__find(namelist, buf); + if (ent) { +- found++; + ret = __del_trace_probe_event(fd, ent); + if (ret >= 0) + strlist__remove(namelist, ent); + } + } +- if (found == 0 && ret >= 0) +- pr_info("Info: Event \"%s\" does not exist.\n", buf); + + return ret; + } + + int del_perf_probe_events(struct strlist *dellist) + { +- int fd, ret = 0; ++ int ret = -1, ufd = -1, kfd = -1; ++ char buf[128]; + const char *group, *event; + char *p, *str; + struct str_node *ent; +- struct strlist *namelist; +- +- fd = open_kprobe_events(true); +- if (fd < 0) +- return fd; ++ struct strlist *namelist = NULL, *unamelist = NULL; + + /* Get current event names */ +- namelist = get_probe_trace_event_names(fd, true); +- if (namelist == NULL) +- return -EINVAL; ++ kfd = open_kprobe_events(true); ++ if (kfd < 0) ++ return kfd; ++ ++ namelist = get_probe_trace_event_names(kfd, true); ++ ufd = open_uprobe_events(true); ++ ++ if (ufd >= 0) ++ unamelist = get_probe_trace_event_names(ufd, true); ++ ++ if (namelist == NULL && unamelist == NULL) ++ goto error; + + strlist__for_each(ent, dellist) { + str = strdup(ent->s); + if (str == NULL) { + ret = -ENOMEM; +- break; ++ goto error; + } + pr_debug("Parsing: %s\n", str); + p = strchr(str, ':'); +@@ -2041,17 +2140,42 @@ int del_perf_probe_events(struct strlist *dellist) + group = "*"; + event = str; + } ++ ++ ret = e_snprintf(buf, 128, "%s:%s", group, event); ++ if (ret < 0) { ++ pr_err("Failed to copy event."); ++ free(str); ++ goto error; ++ } ++ + pr_debug("Group: %s, Event: %s\n", group, event); +- ret = del_trace_probe_event(fd, group, event, namelist); ++ ++ if (namelist) ++ ret = del_trace_probe_event(kfd, buf, namelist); ++ ++ if (unamelist && ret != 0) ++ ret = del_trace_probe_event(ufd, buf, unamelist); ++ ++ if (ret != 0) ++ pr_info("Info: Event \"%s\" does not exist.\n", buf); ++ + free(str); +- if (ret < 0) +- break; + } +- strlist__delete(namelist); +- close(fd); ++ ++error: ++ if (kfd >= 0) { ++ strlist__delete(namelist); ++ close(kfd); ++ } ++ ++ if (ufd >= 0) { ++ strlist__delete(unamelist); ++ close(ufd); ++ } + + return ret; + } ++ + /* TODO: don't use a global variable for filter ... */ + static struct strfilter *available_func_filter; + +@@ -2068,30 +2192,152 @@ static int filter_available_functions(struct map *map __unused, + return 1; + } + +-int show_available_funcs(const char *target, struct strfilter *_filter) ++static int __show_available_funcs(struct map *map) ++{ ++ if (map__load(map, filter_available_functions)) { ++ pr_err("Failed to load map.\n"); ++ return -EINVAL; ++ } ++ if (!dso__sorted_by_name(map->dso, map->type)) ++ dso__sort_by_name(map->dso, map->type); ++ ++ dso__fprintf_symbols_by_name(map->dso, map->type, stdout); ++ return 0; ++} ++ ++static int available_kernel_funcs(const char *module) + { + struct map *map; + int ret; + +- setup_pager(); +- + ret = init_vmlinux(); + if (ret < 0) + return ret; + +- map = kernel_get_module_map(target); ++ map = kernel_get_module_map(module); + if (!map) { +- pr_err("Failed to find %s map.\n", (target) ? : "kernel"); ++ pr_err("Failed to find %s map.\n", (module) ? : "kernel"); + return -EINVAL; + } ++ return __show_available_funcs(map); ++} ++ ++static int available_user_funcs(const char *target) ++{ ++ struct map *map; ++ int ret; ++ ++ ret = init_user_exec(); ++ if (ret < 0) ++ return ret; ++ ++ map = dso__new_map(target); ++ ret = __show_available_funcs(map); ++ dso__delete(map->dso); ++ map__delete(map); ++ return ret; ++} ++ ++int show_available_funcs(const char *target, struct strfilter *_filter, ++ bool user) ++{ ++ setup_pager(); + available_func_filter = _filter; ++ ++ if (!user) ++ return available_kernel_funcs(target); ++ ++ return available_user_funcs(target); ++} ++ ++/* ++ * uprobe_events only accepts address: ++ * Convert function and any offset to address ++ */ ++static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec) ++{ ++ struct perf_probe_point *pp = &pev->point; ++ struct symbol *sym; ++ struct map *map = NULL; ++ char *function = NULL, *name = NULL; ++ int ret = -EINVAL; ++ unsigned long long vaddr = 0; ++ ++ if (!pp->function) { ++ pr_warning("No function specified for uprobes"); ++ goto out; ++ } ++ ++ function = strdup(pp->function); ++ if (!function) { ++ pr_warning("Failed to allocate memory by strdup.\n"); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ name = realpath(exec, NULL); ++ if (!name) { ++ pr_warning("Cannot find realpath for %s.\n", exec); ++ goto out; ++ } ++ map = dso__new_map(name); ++ if (!map) { ++ pr_warning("Cannot find appropriate DSO for %s.\n", exec); ++ goto out; ++ } ++ available_func_filter = strfilter__new(function, NULL); + if (map__load(map, filter_available_functions)) { + pr_err("Failed to load map.\n"); +- return -EINVAL; ++ goto out; + } +- if (!dso__sorted_by_name(map->dso, map->type)) +- dso__sort_by_name(map->dso, map->type); + +- dso__fprintf_symbols_by_name(map->dso, map->type, stdout); +- return 0; ++ sym = map__find_symbol_by_name(map, function, NULL); ++ if (!sym) { ++ pr_warning("Cannot find %s in DSO %s\n", function, exec); ++ goto out; ++ } ++ ++ if (map->start > sym->start) ++ vaddr = map->start; ++ vaddr += sym->start + pp->offset + map->pgoff; ++ pp->offset = 0; ++ ++ if (!pev->event) { ++ pev->event = function; ++ function = NULL; ++ } ++ if (!pev->group) { ++ char *ptr1, *ptr2; ++ ++ pev->group = zalloc(sizeof(char *) * 64); ++ ptr1 = strdup(basename(exec)); ++ if (ptr1) { ++ ptr2 = strpbrk(ptr1, "-._"); ++ if (ptr2) ++ *ptr2 = '\0'; ++ e_snprintf(pev->group, 64, "%s_%s", PERFPROBE_GROUP, ++ ptr1); ++ free(ptr1); ++ } ++ } ++ free(pp->function); ++ pp->function = zalloc(sizeof(char *) * MAX_PROBE_ARGS); ++ if (!pp->function) { ++ ret = -ENOMEM; ++ pr_warning("Failed to allocate memory by zalloc.\n"); ++ goto out; ++ } ++ e_snprintf(pp->function, MAX_PROBE_ARGS, "0x%llx", vaddr); ++ ret = 0; ++ ++out: ++ if (map) { ++ dso__delete(map->dso); ++ map__delete(map); ++ } ++ if (function) ++ free(function); ++ if (name) ++ free(name); ++ return ret; + } +diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h +index a7dee83..f9f3de8 100644 +--- a/tools/perf/util/probe-event.h ++++ b/tools/perf/util/probe-event.h +@@ -7,7 +7,7 @@ + + extern bool probe_event_dry_run; + +-/* kprobe-tracer tracing point */ ++/* kprobe-tracer and uprobe-tracer tracing point */ + struct probe_trace_point { + char *symbol; /* Base symbol */ + char *module; /* Module name */ +@@ -21,7 +21,7 @@ struct probe_trace_arg_ref { + long offset; /* Offset value */ + }; + +-/* kprobe-tracer tracing argument */ ++/* kprobe-tracer and uprobe-tracer tracing argument */ + struct probe_trace_arg { + char *name; /* Argument name */ + char *value; /* Base value */ +@@ -29,12 +29,13 @@ struct probe_trace_arg { + struct probe_trace_arg_ref *ref; /* Referencing offset */ + }; + +-/* kprobe-tracer tracing event (point + arg) */ ++/* kprobe-tracer and uprobe-tracer tracing event (point + arg) */ + struct probe_trace_event { + char *event; /* Event name */ + char *group; /* Group name */ + struct probe_trace_point point; /* Trace point */ + int nargs; /* Number of args */ ++ bool uprobes; /* uprobes only */ + struct probe_trace_arg *args; /* Arguments */ + }; + +@@ -70,6 +71,7 @@ struct perf_probe_event { + char *group; /* Group name */ + struct perf_probe_point point; /* Probe point */ + int nargs; /* Number of arguments */ ++ bool uprobes; + struct perf_probe_arg *args; /* Arguments */ + }; + +@@ -129,8 +131,8 @@ extern int show_line_range(struct line_range *lr, const char *module); + extern int show_available_vars(struct perf_probe_event *pevs, int npevs, + int max_probe_points, const char *module, + struct strfilter *filter, bool externs); +-extern int show_available_funcs(const char *module, struct strfilter *filter); +- ++extern int show_available_funcs(const char *module, struct strfilter *filter, ++ bool user); + + /* Maximum index number of event-name postfix */ + #define MAX_EVENT_INDEX 1024 +diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c +index ab9867b..0ef529e 100644 +--- a/tools/perf/util/symbol.c ++++ b/tools/perf/util/symbol.c +@@ -2783,3 +2783,14 @@ int machine__load_vmlinux_path(struct machine *machine, enum map_type type, + + return ret; + } ++ ++struct map *dso__new_map(const char *name) ++{ ++ struct map *map = NULL; ++ struct dso *dso = dso__new(name); ++ ++ if (dso) ++ map = map__new2(0, dso, MAP__FUNCTION); ++ ++ return map; ++} +diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h +index ac49ef2..9e7742c 100644 +--- a/tools/perf/util/symbol.h ++++ b/tools/perf/util/symbol.h +@@ -237,6 +237,7 @@ void dso__set_long_name(struct dso *dso, char *name); + void dso__set_build_id(struct dso *dso, void *build_id); + void dso__read_running_kernel_build_id(struct dso *dso, + struct machine *machine); ++struct map *dso__new_map(const char *name); + struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, + u64 addr); + struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, diff --git a/uprobes-3.4-tip.patch b/uprobes-3.4-tip.patch new file mode 100644 index 000000000..190b03544 --- /dev/null +++ b/uprobes-3.4-tip.patch @@ -0,0 +1,915 @@ +The split-out series is available in the git repository at: + + git://fedorapeople.org/home/fedora/aarapov/public_git/kernel-uprobes.git tags/f17_exported + +Ananth N Mavinakayanahalli (1): + uprobes: Pass probed vaddr to arch_uprobe_analyze_insn() + +Josh Stone (1): + uprobes: add exports necessary for uprobes use by modules + +Oleg Nesterov (21): + uprobes: Optimize is_swbp_at_addr() for current->mm + uprobes: Change read_opcode() to use FOLL_FORCE + uprobes: Introduce find_active_uprobe() helper + uprobes: Teach find_active_uprobe() to provide the "is_swbp" info + uprobes: Change register_for_each_vma() to take mm->mmap_sem for writing + uprobes: Teach handle_swbp() to rely on "is_swbp" rather than uprobes_srcu + uprobes: Kill uprobes_srcu/uprobe_srcu_id + uprobes: Valid_vma() should reject VM_HUGETLB + uprobes: __copy_insn() should ensure a_ops->readpage != NULL + uprobes: Write_opcode()->__replace_page() can race with try_to_unmap() + uprobes: Install_breakpoint() should fail if is_swbp_insn() == T + uprobes: Rework register_for_each_vma() to make it O(n) + uprobes: Change build_map_info() to try kmalloc(GFP_NOWAIT) first + uprobes: Copy_insn() shouldn't depend on mm/vma/vaddr + uprobes: Copy_insn() should not return -ENOMEM if __copy_insn() fails + uprobes: No need to re-check vma_address() in write_opcode() + uprobes: Simplify the usage of uprobe->pending_list + uprobes: Don't use loff_t for the valid virtual address + uprobes: __copy_insn() needs "loff_t offset" + uprobes: Remove the unnecessary initialization in add_utask() + uprobes: Move BUG_ON(UPROBE_SWBP_INSN_SIZE) from write_opcode() to install_breakpoint() + +Peter Zijlstra (1): + uprobes: Document uprobe_register() vs uprobe_mmap() race + +Signed-off-by: Anton Arapov +--- + arch/x86/include/asm/uprobes.h | 2 +- + arch/x86/kernel/ptrace.c | 6 + + arch/x86/kernel/uprobes.c | 3 +- + include/linux/sched.h | 1 - + kernel/events/uprobes.c | 464 ++++++++++++++++++++-------------------- + 5 files changed, 240 insertions(+), 236 deletions(-) + +diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h +index 1e9bed1..f3971bb 100644 +--- a/arch/x86/include/asm/uprobes.h ++++ b/arch/x86/include/asm/uprobes.h +@@ -48,7 +48,7 @@ struct arch_uprobe_task { + #endif + }; + +-extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm); ++extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr); + extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs); + extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs); + extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk); +diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c +index cf11783..4609190 100644 +--- a/arch/x86/kernel/ptrace.c ++++ b/arch/x86/kernel/ptrace.c +@@ -1415,6 +1415,12 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) + #endif + } + ++/* ++ * This is declared in linux/regset.h and defined in machine-dependent ++ * code. We put the export here to ensure no machine forgets it. ++ */ ++EXPORT_SYMBOL_GPL(task_user_regset_view); ++ + static void fill_sigtrap_info(struct task_struct *tsk, + struct pt_regs *regs, + int error_code, int si_code, +diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c +index dc4e910..36fd420 100644 +--- a/arch/x86/kernel/uprobes.c ++++ b/arch/x86/kernel/uprobes.c +@@ -409,9 +409,10 @@ static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm, + * arch_uprobe_analyze_insn - instruction analysis including validity and fixups. + * @mm: the probed address space. + * @arch_uprobe: the probepoint information. ++ * @addr: virtual address at which to install the probepoint + * Return 0 on success or a -ve number on error. + */ +-int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm) ++int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr) + { + int ret; + struct insn insn; +diff --git a/include/linux/sched.h b/include/linux/sched.h +index cff94cd..6869c60 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -1619,7 +1619,6 @@ struct task_struct { + #endif + #ifdef CONFIG_UPROBES + struct uprobe_task *utask; +- int uprobe_srcu_id; + #endif + }; + +diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c +index 985be4d..d9e5ba5 100644 +--- a/kernel/events/uprobes.c ++++ b/kernel/events/uprobes.c +@@ -34,17 +34,34 @@ + #include /* notifier mechanism */ + + #include ++#include + + #define UINSNS_PER_PAGE (PAGE_SIZE/UPROBE_XOL_SLOT_BYTES) + #define MAX_UPROBE_XOL_SLOTS UINSNS_PER_PAGE + +-static struct srcu_struct uprobes_srcu; + static struct rb_root uprobes_tree = RB_ROOT; + + static DEFINE_SPINLOCK(uprobes_treelock); /* serialize rbtree access */ + + #define UPROBES_HASH_SZ 13 + ++/* ++ * We need separate register/unregister and mmap/munmap lock hashes because ++ * of mmap_sem nesting. ++ * ++ * uprobe_register() needs to install probes on (potentially) all processes ++ * and thus needs to acquire multiple mmap_sems (consequtively, not ++ * concurrently), whereas uprobe_mmap() is called while holding mmap_sem ++ * for the particular process doing the mmap. ++ * ++ * uprobe_register()->register_for_each_vma() needs to drop/acquire mmap_sem ++ * because of lock order against i_mmap_mutex. This means there's a hole in ++ * the register vma iteration where a mmap() can happen. ++ * ++ * Thus uprobe_register() can race with uprobe_mmap() and we can try and ++ * install a probe where one is already installed. ++ */ ++ + /* serialize (un)register */ + static struct mutex uprobes_mutex[UPROBES_HASH_SZ]; + +@@ -61,17 +78,6 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ]; + */ + static atomic_t uprobe_events = ATOMIC_INIT(0); + +-/* +- * Maintain a temporary per vma info that can be used to search if a vma +- * has already been handled. This structure is introduced since extending +- * vm_area_struct wasnt recommended. +- */ +-struct vma_info { +- struct list_head probe_list; +- struct mm_struct *mm; +- loff_t vaddr; +-}; +- + struct uprobe { + struct rb_node rb_node; /* node in the rb tree */ + atomic_t ref; +@@ -100,7 +106,8 @@ static bool valid_vma(struct vm_area_struct *vma, bool is_register) + if (!is_register) + return true; + +- if ((vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) == (VM_READ|VM_EXEC)) ++ if ((vma->vm_flags & (VM_HUGETLB|VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) ++ == (VM_READ|VM_EXEC)) + return true; + + return false; +@@ -129,33 +136,17 @@ static loff_t vma_address(struct vm_area_struct *vma, loff_t offset) + static int __replace_page(struct vm_area_struct *vma, struct page *page, struct page *kpage) + { + struct mm_struct *mm = vma->vm_mm; +- pgd_t *pgd; +- pud_t *pud; +- pmd_t *pmd; +- pte_t *ptep; +- spinlock_t *ptl; + unsigned long addr; +- int err = -EFAULT; ++ spinlock_t *ptl; ++ pte_t *ptep; + + addr = page_address_in_vma(page, vma); + if (addr == -EFAULT) +- goto out; +- +- pgd = pgd_offset(mm, addr); +- if (!pgd_present(*pgd)) +- goto out; +- +- pud = pud_offset(pgd, addr); +- if (!pud_present(*pud)) +- goto out; +- +- pmd = pmd_offset(pud, addr); +- if (!pmd_present(*pmd)) +- goto out; ++ return -EFAULT; + +- ptep = pte_offset_map_lock(mm, pmd, addr, &ptl); ++ ptep = page_check_address(page, mm, addr, &ptl, 0); + if (!ptep) +- goto out; ++ return -EAGAIN; + + get_page(kpage); + page_add_new_anon_rmap(kpage, vma, addr); +@@ -174,10 +165,8 @@ static int __replace_page(struct vm_area_struct *vma, struct page *page, struct + try_to_free_swap(page); + put_page(page); + pte_unmap_unlock(ptep, ptl); +- err = 0; + +-out: +- return err; ++ return 0; + } + + /** +@@ -222,9 +211,8 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, + void *vaddr_old, *vaddr_new; + struct vm_area_struct *vma; + struct uprobe *uprobe; +- loff_t addr; + int ret; +- ++retry: + /* Read the page with vaddr into memory */ + ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma); + if (ret <= 0) +@@ -246,10 +234,6 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, + if (mapping != vma->vm_file->f_mapping) + goto put_out; + +- addr = vma_address(vma, uprobe->offset); +- if (vaddr != (unsigned long)addr) +- goto put_out; +- + ret = -ENOMEM; + new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr); + if (!new_page) +@@ -267,11 +251,7 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, + vaddr_new = kmap_atomic(new_page); + + memcpy(vaddr_new, vaddr_old, PAGE_SIZE); +- +- /* poke the new insn in, ASSUMES we don't cross page boundary */ +- vaddr &= ~PAGE_MASK; +- BUG_ON(vaddr + UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); +- memcpy(vaddr_new + vaddr, &opcode, UPROBE_SWBP_INSN_SIZE); ++ memcpy(vaddr_new + (vaddr & ~PAGE_MASK), &opcode, UPROBE_SWBP_INSN_SIZE); + + kunmap_atomic(vaddr_new); + kunmap_atomic(vaddr_old); +@@ -291,6 +271,8 @@ unlock_out: + put_out: + put_page(old_page); + ++ if (unlikely(ret == -EAGAIN)) ++ goto retry; + return ret; + } + +@@ -312,7 +294,7 @@ static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_ + void *vaddr_new; + int ret; + +- ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &page, NULL); ++ ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL); + if (ret <= 0) + return ret; + +@@ -333,10 +315,20 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) + uprobe_opcode_t opcode; + int result; + ++ if (current->mm == mm) { ++ pagefault_disable(); ++ result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr, ++ sizeof(opcode)); ++ pagefault_enable(); ++ ++ if (likely(result == 0)) ++ goto out; ++ } ++ + result = read_opcode(mm, vaddr, &opcode); + if (result) + return result; +- ++out: + if (is_swbp_insn(&opcode)) + return 1; + +@@ -355,7 +347,9 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) + int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) + { + int result; +- ++ /* ++ * See the comment near uprobes_hash(). ++ */ + result = is_swbp_at_addr(mm, vaddr); + if (result == 1) + return -EEXIST; +@@ -520,7 +514,6 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset) + uprobe->inode = igrab(inode); + uprobe->offset = offset; + init_rwsem(&uprobe->consumer_rwsem); +- INIT_LIST_HEAD(&uprobe->pending_list); + + /* add to uprobes_tree, sorted on inode:offset */ + cur_uprobe = insert_uprobe(uprobe); +@@ -588,20 +581,22 @@ static bool consumer_del(struct uprobe *uprobe, struct uprobe_consumer *uc) + } + + static int +-__copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *insn, +- unsigned long nbytes, unsigned long offset) ++__copy_insn(struct address_space *mapping, struct file *filp, char *insn, ++ unsigned long nbytes, loff_t offset) + { +- struct file *filp = vma->vm_file; + struct page *page; + void *vaddr; +- unsigned long off1; +- unsigned long idx; ++ unsigned long off; ++ pgoff_t idx; + + if (!filp) + return -EINVAL; + +- idx = (unsigned long)(offset >> PAGE_CACHE_SHIFT); +- off1 = offset &= ~PAGE_MASK; ++ if (!mapping->a_ops->readpage) ++ return -EIO; ++ ++ idx = offset >> PAGE_CACHE_SHIFT; ++ off = offset & ~PAGE_MASK; + + /* + * Ensure that the page that has the original instruction is +@@ -612,22 +607,20 @@ __copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *ins + return PTR_ERR(page); + + vaddr = kmap_atomic(page); +- memcpy(insn, vaddr + off1, nbytes); ++ memcpy(insn, vaddr + off, nbytes); + kunmap_atomic(vaddr); + page_cache_release(page); + + return 0; + } + +-static int +-copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr) ++static int copy_insn(struct uprobe *uprobe, struct file *filp) + { + struct address_space *mapping; + unsigned long nbytes; + int bytes; + +- addr &= ~PAGE_MASK; +- nbytes = PAGE_SIZE - addr; ++ nbytes = PAGE_SIZE - (uprobe->offset & ~PAGE_MASK); + mapping = uprobe->inode->i_mapping; + + /* Instruction at end of binary; copy only available bytes */ +@@ -638,13 +631,13 @@ copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr) + + /* Instruction at the page-boundary; copy bytes in second page */ + if (nbytes < bytes) { +- if (__copy_insn(mapping, vma, uprobe->arch.insn + nbytes, +- bytes - nbytes, uprobe->offset + nbytes)) +- return -ENOMEM; +- ++ int err = __copy_insn(mapping, filp, uprobe->arch.insn + nbytes, ++ bytes - nbytes, uprobe->offset + nbytes); ++ if (err) ++ return err; + bytes = nbytes; + } +- return __copy_insn(mapping, vma, uprobe->arch.insn, bytes, uprobe->offset); ++ return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset); + } + + /* +@@ -672,9 +665,8 @@ copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr) + */ + static int + install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, +- struct vm_area_struct *vma, loff_t vaddr) ++ struct vm_area_struct *vma, unsigned long vaddr) + { +- unsigned long addr; + int ret; + + /* +@@ -687,20 +679,22 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, + if (!uprobe->consumers) + return -EEXIST; + +- addr = (unsigned long)vaddr; +- + if (!(uprobe->flags & UPROBE_COPY_INSN)) { +- ret = copy_insn(uprobe, vma, addr); ++ ret = copy_insn(uprobe, vma->vm_file); + if (ret) + return ret; + + if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) +- return -EEXIST; ++ return -ENOTSUPP; + +- ret = arch_uprobe_analyze_insn(&uprobe->arch, mm); ++ ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr); + if (ret) + return ret; + ++ /* write_opcode() assumes we don't cross page boundary */ ++ BUG_ON((uprobe->offset & ~PAGE_MASK) + ++ UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); ++ + uprobe->flags |= UPROBE_COPY_INSN; + } + +@@ -713,7 +707,7 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, + * Hence increment before and decrement on failure. + */ + atomic_inc(&mm->uprobes_state.count); +- ret = set_swbp(&uprobe->arch, mm, addr); ++ ret = set_swbp(&uprobe->arch, mm, vaddr); + if (ret) + atomic_dec(&mm->uprobes_state.count); + +@@ -721,27 +715,21 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, + } + + static void +-remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, loff_t vaddr) ++remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr) + { +- if (!set_orig_insn(&uprobe->arch, mm, (unsigned long)vaddr, true)) ++ if (!set_orig_insn(&uprobe->arch, mm, vaddr, true)) + atomic_dec(&mm->uprobes_state.count); + } + + /* +- * There could be threads that have hit the breakpoint and are entering the +- * notifier code and trying to acquire the uprobes_treelock. The thread +- * calling delete_uprobe() that is removing the uprobe from the rb_tree can +- * race with these threads and might acquire the uprobes_treelock compared +- * to some of the breakpoint hit threads. In such a case, the breakpoint +- * hit threads will not find the uprobe. The current unregistering thread +- * waits till all other threads have hit a breakpoint, to acquire the +- * uprobes_treelock before the uprobe is removed from the rbtree. ++ * There could be threads that have already hit the breakpoint. They ++ * will recheck the current insn and restart if find_uprobe() fails. ++ * See find_active_uprobe(). + */ + static void delete_uprobe(struct uprobe *uprobe) + { + unsigned long flags; + +- synchronize_srcu(&uprobes_srcu); + spin_lock_irqsave(&uprobes_treelock, flags); + rb_erase(&uprobe->rb_node, &uprobes_tree); + spin_unlock_irqrestore(&uprobes_treelock, flags); +@@ -750,139 +738,135 @@ static void delete_uprobe(struct uprobe *uprobe) + atomic_dec(&uprobe_events); + } + +-static struct vma_info * +-__find_next_vma_info(struct address_space *mapping, struct list_head *head, +- struct vma_info *vi, loff_t offset, bool is_register) ++struct map_info { ++ struct map_info *next; ++ struct mm_struct *mm; ++ unsigned long vaddr; ++}; ++ ++static inline struct map_info *free_map_info(struct map_info *info) ++{ ++ struct map_info *next = info->next; ++ kfree(info); ++ return next; ++} ++ ++static struct map_info * ++build_map_info(struct address_space *mapping, loff_t offset, bool is_register) + { ++ unsigned long pgoff = offset >> PAGE_SHIFT; + struct prio_tree_iter iter; + struct vm_area_struct *vma; +- struct vma_info *tmpvi; +- unsigned long pgoff; +- int existing_vma; +- loff_t vaddr; +- +- pgoff = offset >> PAGE_SHIFT; ++ struct map_info *curr = NULL; ++ struct map_info *prev = NULL; ++ struct map_info *info; ++ int more = 0; + ++ again: ++ mutex_lock(&mapping->i_mmap_mutex); + vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { + if (!valid_vma(vma, is_register)) + continue; + +- existing_vma = 0; +- vaddr = vma_address(vma, offset); +- +- list_for_each_entry(tmpvi, head, probe_list) { +- if (tmpvi->mm == vma->vm_mm && tmpvi->vaddr == vaddr) { +- existing_vma = 1; +- break; +- } ++ if (!prev && !more) { ++ /* ++ * Needs GFP_NOWAIT to avoid i_mmap_mutex recursion through ++ * reclaim. This is optimistic, no harm done if it fails. ++ */ ++ prev = kmalloc(sizeof(struct map_info), ++ GFP_NOWAIT | __GFP_NOMEMALLOC | __GFP_NOWARN); ++ if (prev) ++ prev->next = NULL; + } +- +- /* +- * Another vma needs a probe to be installed. However skip +- * installing the probe if the vma is about to be unlinked. +- */ +- if (!existing_vma && atomic_inc_not_zero(&vma->vm_mm->mm_users)) { +- vi->mm = vma->vm_mm; +- vi->vaddr = vaddr; +- list_add(&vi->probe_list, head); +- +- return vi; ++ if (!prev) { ++ more++; ++ continue; + } +- } + +- return NULL; +-} +- +-/* +- * Iterate in the rmap prio tree and find a vma where a probe has not +- * yet been inserted. +- */ +-static struct vma_info * +-find_next_vma_info(struct address_space *mapping, struct list_head *head, +- loff_t offset, bool is_register) +-{ +- struct vma_info *vi, *retvi; ++ if (!atomic_inc_not_zero(&vma->vm_mm->mm_users)) ++ continue; + +- vi = kzalloc(sizeof(struct vma_info), GFP_KERNEL); +- if (!vi) +- return ERR_PTR(-ENOMEM); ++ info = prev; ++ prev = prev->next; ++ info->next = curr; ++ curr = info; + +- mutex_lock(&mapping->i_mmap_mutex); +- retvi = __find_next_vma_info(mapping, head, vi, offset, is_register); ++ info->mm = vma->vm_mm; ++ info->vaddr = vma_address(vma, offset); ++ } + mutex_unlock(&mapping->i_mmap_mutex); + +- if (!retvi) +- kfree(vi); ++ if (!more) ++ goto out; ++ ++ prev = curr; ++ while (curr) { ++ mmput(curr->mm); ++ curr = curr->next; ++ } + +- return retvi; ++ do { ++ info = kmalloc(sizeof(struct map_info), GFP_KERNEL); ++ if (!info) { ++ curr = ERR_PTR(-ENOMEM); ++ goto out; ++ } ++ info->next = prev; ++ prev = info; ++ } while (--more); ++ ++ goto again; ++ out: ++ while (prev) ++ prev = free_map_info(prev); ++ return curr; + } + + static int register_for_each_vma(struct uprobe *uprobe, bool is_register) + { +- struct list_head try_list; +- struct vm_area_struct *vma; +- struct address_space *mapping; +- struct vma_info *vi, *tmpvi; +- struct mm_struct *mm; +- loff_t vaddr; +- int ret; ++ struct map_info *info; ++ int err = 0; + +- mapping = uprobe->inode->i_mapping; +- INIT_LIST_HEAD(&try_list); ++ info = build_map_info(uprobe->inode->i_mapping, ++ uprobe->offset, is_register); ++ if (IS_ERR(info)) ++ return PTR_ERR(info); + +- ret = 0; ++ while (info) { ++ struct mm_struct *mm = info->mm; ++ struct vm_area_struct *vma; + +- for (;;) { +- vi = find_next_vma_info(mapping, &try_list, uprobe->offset, is_register); +- if (!vi) +- break; ++ if (err) ++ goto free; + +- if (IS_ERR(vi)) { +- ret = PTR_ERR(vi); +- break; +- } ++ down_write(&mm->mmap_sem); ++ vma = find_vma(mm, (unsigned long)info->vaddr); ++ if (!vma || !valid_vma(vma, is_register)) ++ goto unlock; + +- mm = vi->mm; +- down_read(&mm->mmap_sem); +- vma = find_vma(mm, (unsigned long)vi->vaddr); +- if (!vma || !valid_vma(vma, is_register)) { +- list_del(&vi->probe_list); +- kfree(vi); +- up_read(&mm->mmap_sem); +- mmput(mm); +- continue; +- } +- vaddr = vma_address(vma, uprobe->offset); + if (vma->vm_file->f_mapping->host != uprobe->inode || +- vaddr != vi->vaddr) { +- list_del(&vi->probe_list); +- kfree(vi); +- up_read(&mm->mmap_sem); +- mmput(mm); +- continue; +- } +- +- if (is_register) +- ret = install_breakpoint(uprobe, mm, vma, vi->vaddr); +- else +- remove_breakpoint(uprobe, mm, vi->vaddr); ++ vma_address(vma, uprobe->offset) != info->vaddr) ++ goto unlock; + +- up_read(&mm->mmap_sem); +- mmput(mm); + if (is_register) { +- if (ret && ret == -EEXIST) +- ret = 0; +- if (ret) +- break; ++ err = install_breakpoint(uprobe, mm, vma, info->vaddr); ++ /* ++ * We can race against uprobe_mmap(), see the ++ * comment near uprobe_hash(). ++ */ ++ if (err == -EEXIST) ++ err = 0; ++ } else { ++ remove_breakpoint(uprobe, mm, info->vaddr); + } ++ unlock: ++ up_write(&mm->mmap_sem); ++ free: ++ mmput(mm); ++ info = free_map_info(info); + } + +- list_for_each_entry_safe(vi, tmpvi, &try_list, probe_list) { +- list_del(&vi->probe_list); +- kfree(vi); +- } +- +- return ret; ++ return err; + } + + static int __uprobe_register(struct uprobe *uprobe) +@@ -945,6 +929,7 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer * + + return ret; + } ++EXPORT_SYMBOL_GPL(uprobe_register); + + /* + * uprobe_unregister - unregister a already registered probe. +@@ -976,6 +961,7 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume + if (uprobe) + put_uprobe(uprobe); + } ++EXPORT_SYMBOL_GPL(uprobe_unregister); + + /* + * Of all the nodes that correspond to the given inode, return the node +@@ -1048,7 +1034,7 @@ static void build_probe_list(struct inode *inode, struct list_head *head) + int uprobe_mmap(struct vm_area_struct *vma) + { + struct list_head tmp_list; +- struct uprobe *uprobe, *u; ++ struct uprobe *uprobe; + struct inode *inode; + int ret, count; + +@@ -1066,12 +1052,9 @@ int uprobe_mmap(struct vm_area_struct *vma) + ret = 0; + count = 0; + +- list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { +- loff_t vaddr; +- +- list_del(&uprobe->pending_list); ++ list_for_each_entry(uprobe, &tmp_list, pending_list) { + if (!ret) { +- vaddr = vma_address(vma, uprobe->offset); ++ loff_t vaddr = vma_address(vma, uprobe->offset); + + if (vaddr < vma->vm_start || vaddr >= vma->vm_end) { + put_uprobe(uprobe); +@@ -1079,8 +1062,10 @@ int uprobe_mmap(struct vm_area_struct *vma) + } + + ret = install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); +- +- /* Ignore double add: */ ++ /* ++ * We can race against uprobe_register(), see the ++ * comment near uprobe_hash(). ++ */ + if (ret == -EEXIST) { + ret = 0; + +@@ -1115,7 +1100,7 @@ int uprobe_mmap(struct vm_area_struct *vma) + void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) + { + struct list_head tmp_list; +- struct uprobe *uprobe, *u; ++ struct uprobe *uprobe; + struct inode *inode; + + if (!atomic_read(&uprobe_events) || !valid_vma(vma, false)) +@@ -1132,11 +1117,8 @@ void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned lon + mutex_lock(uprobes_mmap_hash(inode)); + build_probe_list(inode, &tmp_list); + +- list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { +- loff_t vaddr; +- +- list_del(&uprobe->pending_list); +- vaddr = vma_address(vma, uprobe->offset); ++ list_for_each_entry(uprobe, &tmp_list, pending_list) { ++ loff_t vaddr = vma_address(vma, uprobe->offset); + + if (vaddr >= start && vaddr < end) { + /* +@@ -1378,9 +1360,6 @@ void uprobe_free_utask(struct task_struct *t) + { + struct uprobe_task *utask = t->utask; + +- if (t->uprobe_srcu_id != -1) +- srcu_read_unlock_raw(&uprobes_srcu, t->uprobe_srcu_id); +- + if (!utask) + return; + +@@ -1398,7 +1377,6 @@ void uprobe_free_utask(struct task_struct *t) + void uprobe_copy_process(struct task_struct *t) + { + t->utask = NULL; +- t->uprobe_srcu_id = -1; + } + + /* +@@ -1417,7 +1395,6 @@ static struct uprobe_task *add_utask(void) + if (unlikely(!utask)) + return NULL; + +- utask->active_uprobe = NULL; + current->utask = utask; + return utask; + } +@@ -1479,41 +1456,64 @@ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs) + return false; + } + ++static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) ++{ ++ struct mm_struct *mm = current->mm; ++ struct uprobe *uprobe = NULL; ++ struct vm_area_struct *vma; ++ ++ down_read(&mm->mmap_sem); ++ vma = find_vma(mm, bp_vaddr); ++ if (vma && vma->vm_start <= bp_vaddr) { ++ if (valid_vma(vma, false)) { ++ struct inode *inode; ++ loff_t offset; ++ ++ inode = vma->vm_file->f_mapping->host; ++ offset = bp_vaddr - vma->vm_start; ++ offset += (vma->vm_pgoff << PAGE_SHIFT); ++ uprobe = find_uprobe(inode, offset); ++ } ++ ++ if (!uprobe) ++ *is_swbp = is_swbp_at_addr(mm, bp_vaddr); ++ } else { ++ *is_swbp = -EFAULT; ++ } ++ up_read(&mm->mmap_sem); ++ ++ return uprobe; ++} ++ + /* + * Run handler and ask thread to singlestep. + * Ensure all non-fatal signals cannot interrupt thread while it singlesteps. + */ + static void handle_swbp(struct pt_regs *regs) + { +- struct vm_area_struct *vma; + struct uprobe_task *utask; + struct uprobe *uprobe; +- struct mm_struct *mm; + unsigned long bp_vaddr; ++ int uninitialized_var(is_swbp); + +- uprobe = NULL; + bp_vaddr = uprobe_get_swbp_addr(regs); +- mm = current->mm; +- down_read(&mm->mmap_sem); +- vma = find_vma(mm, bp_vaddr); +- +- if (vma && vma->vm_start <= bp_vaddr && valid_vma(vma, false)) { +- struct inode *inode; +- loff_t offset; +- +- inode = vma->vm_file->f_mapping->host; +- offset = bp_vaddr - vma->vm_start; +- offset += (vma->vm_pgoff << PAGE_SHIFT); +- uprobe = find_uprobe(inode, offset); +- } +- +- srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id); +- current->uprobe_srcu_id = -1; +- up_read(&mm->mmap_sem); ++ uprobe = find_active_uprobe(bp_vaddr, &is_swbp); + + if (!uprobe) { +- /* No matching uprobe; signal SIGTRAP. */ +- send_sig(SIGTRAP, current, 0); ++ if (is_swbp > 0) { ++ /* No matching uprobe; signal SIGTRAP. */ ++ send_sig(SIGTRAP, current, 0); ++ } else { ++ /* ++ * Either we raced with uprobe_unregister() or we can't ++ * access this memory. The latter is only possible if ++ * another thread plays with our ->mm. In both cases ++ * we can simply restart. If this vma was unmapped we ++ * can pretend this insn was not executed yet and get ++ * the (correct) SIGSEGV after restart. ++ */ ++ instruction_pointer_set(regs, bp_vaddr); ++ } + return; + } + +@@ -1620,7 +1620,6 @@ int uprobe_pre_sstep_notifier(struct pt_regs *regs) + utask->state = UTASK_BP_HIT; + + set_thread_flag(TIF_UPROBE); +- current->uprobe_srcu_id = srcu_read_lock_raw(&uprobes_srcu); + + return 1; + } +@@ -1655,7 +1654,6 @@ static int __init init_uprobes(void) + mutex_init(&uprobes_mutex[i]); + mutex_init(&uprobes_mmap_mutex[i]); + } +- init_srcu_struct(&uprobes_srcu); + + return register_die_notifier(&uprobe_exception_nb); + } From 1b3fae83d0e49f9ceaa99060290c7669cc0c766f Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 22 Jun 2012 16:53:07 -0500 Subject: [PATCH 397/487] Linux 3.4.4 --- kernel.spec | 13 +++++-------- sources | 2 +- udl-bind-fix.patch | 28 ---------------------------- 3 files changed, 6 insertions(+), 37 deletions(-) delete mode 100644 udl-bind-fix.patch diff --git a/kernel.spec b/kernel.spec index d09caff97..b19b88755 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 3 +%define stable_update 4 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -775,9 +775,6 @@ Patch22031: SUNRPC-move-per-net-operations-from-svc_destroy.patch #rhbz 832741 Patch22032: cifs-fix-parsing-of-password-mount-option.patch -#rhbz 832188 -Patch22033: udl-bind-fix.patch - #rhbz 831807 Patch22034: usb-storage-try-read_capacity-10-first.patch @@ -1442,9 +1439,6 @@ ApplyPatch SUNRPC-move-per-net-operations-from-svc_destroy.patch #rhbz 832741 ApplyPatch cifs-fix-parsing-of-password-mount-option.patch -#rhbz 832188 -ApplyPatch udl-bind-fix.patch - #rhbz 831807 ApplyPatch usb-storage-try-read_capacity-10-first.patch @@ -2186,6 +2180,9 @@ fi # and build. %changelog +* Fri Jun 22 2012 Justin M. Forbes 3.4.4-1 +- Linux 3.4.4 + * Fri Jun 22 2012 Josh Boyer - Add uprobe backports from Anton Arapov (rhbz 832083) - Disable UDL DRM driver per Dave Airlie diff --git a/sources b/sources index 341fd2705..274b06a6c 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 967f72983655e2479f951195953e8480 linux-3.4.tar.xz -3b6cf4f6337346ee78904eb70e2d4e08 patch-3.4.3.xz +58e6672d932d74d5e2b6811b9d37d67c patch-3.4.4.xz diff --git a/udl-bind-fix.patch b/udl-bind-fix.patch deleted file mode 100644 index 45b4563c1..000000000 --- a/udl-bind-fix.patch +++ /dev/null @@ -1,28 +0,0 @@ -@@ -, +, @@ - drivers/gpu/drm/udl/udl_drv.c | 15 ++++++++++++++- - 1 file changed, 14 insertions(+), 1 deletion(-) ---- a/drivers/gpu/drm/udl/udl_drv.c -+++ a/drivers/gpu/drm/udl/udl_drv.c -@@ -13,8 +13,21 @@ - - static struct drm_driver driver; - -+/* -+ * There are many DisplayLink-based graphics products, all with unique PIDs. -+ * So we match on DisplayLink's VID + Vendor-Defined Interface Class (0xff) -+ * We also require a match on SubClass (0x00) and Protocol (0x00), -+ * which is compatible with all known USB 2.0 era graphics chips and firmware, -+ * but allows DisplayLink to increment those for any future incompatible chips -+ */ - static struct usb_device_id id_table[] = { -- {.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,}, -+ {.idVendor = 0x17e9, .bInterfaceClass = 0xff, -+ .bInterfaceSubClass = 0x00, -+ .bInterfaceProtocol = 0x00, -+ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | -+ USB_DEVICE_ID_MATCH_INT_CLASS | -+ USB_DEVICE_ID_MATCH_INT_SUBCLASS | -+ USB_DEVICE_ID_MATCH_INT_PROTOCOL,}, - {}, - }; - MODULE_DEVICE_TABLE(usb, id_table); From def7f17730695ac4b19deb43436f477d14f67af3 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 26 Jun 2012 11:10:47 -0400 Subject: [PATCH 398/487] ath9k_htc: configure bssid on ASSOC/IBSS change (rhbz 828731) --- ...configure-bssid-on-ASSOC-IBSS-change.patch | 44 +++++++++++++++++++ kernel.spec | 9 ++++ 2 files changed, 53 insertions(+) create mode 100644 ath9k_htc-configure-bssid-on-ASSOC-IBSS-change.patch diff --git a/ath9k_htc-configure-bssid-on-ASSOC-IBSS-change.patch b/ath9k_htc-configure-bssid-on-ASSOC-IBSS-change.patch new file mode 100644 index 000000000..51dc6e211 --- /dev/null +++ b/ath9k_htc-configure-bssid-on-ASSOC-IBSS-change.patch @@ -0,0 +1,44 @@ +commit 931cb03afed7b541392295f3afc4638da32f08a0 +Author: Rajkumar Manoharan +Date: Wed Jun 20 16:29:20 2012 +0530 + + ath9k_htc: configure bssid on ASSOC/IBSS change + + After the change "mac80211: remove spurious BSSID change flag", + BSS_CHANGED_BSSID will not be passed on association or IBSS + status changes. So it could be better to program bssid on ASSOC + or IBSS change notification. Not doing so, is affecting the + packet transmission. + + Cc: stable@vger.kernel.org [3.4+] + Reported-by: Michael Leun + Signed-off-by: Rajkumar Manoharan + Signed-off-by: John W. Linville + +diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c +index 2b8f61c..abbd6ef 100644 +--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c ++++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c +@@ -1496,6 +1496,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, + priv->num_sta_assoc_vif++ : priv->num_sta_assoc_vif--; + + if (priv->ah->opmode == NL80211_IFTYPE_STATION) { ++ ath9k_htc_choose_set_bssid(priv); + if (bss_conf->assoc && (priv->num_sta_assoc_vif == 1)) + ath9k_htc_start_ani(priv); + else if (priv->num_sta_assoc_vif == 0) +@@ -1503,13 +1504,11 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, + } + } + +- if (changed & BSS_CHANGED_BSSID) { ++ if (changed & BSS_CHANGED_IBSS) { + if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) { + common->curaid = bss_conf->aid; + memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); + ath9k_htc_set_bssid(priv); +- } else if (priv->ah->opmode == NL80211_IFTYPE_STATION) { +- ath9k_htc_choose_set_bssid(priv); + } + } + diff --git a/kernel.spec b/kernel.spec index b19b88755..407c296ff 100644 --- a/kernel.spec +++ b/kernel.spec @@ -778,6 +778,9 @@ Patch22032: cifs-fix-parsing-of-password-mount-option.patch #rhbz 831807 Patch22034: usb-storage-try-read_capacity-10-first.patch +#rhbz 828731 +Patch22035: ath9k_htc-configure-bssid-on-ASSOC-IBSS-change.patch + # END OF PATCH DEFINITIONS %endif @@ -1442,6 +1445,9 @@ ApplyPatch cifs-fix-parsing-of-password-mount-option.patch #rhbz 831807 ApplyPatch usb-storage-try-read_capacity-10-first.patch +#rhbz 828731 +ApplyPatch ath9k_htc-configure-bssid-on-ASSOC-IBSS-change.patch + # END OF PATCH APPLICATIONS %endif @@ -2180,6 +2186,9 @@ fi # and build. %changelog +* Tue Jun 26 2012 John W. Linville +- ath9k_htc: configure bssid on ASSOC/IBSS change (rhbz 828731) + * Fri Jun 22 2012 Justin M. Forbes 3.4.4-1 - Linux 3.4.4 From cec1aca5a9bde5d687050ba67efc0fc60bddad24 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 26 Jun 2012 11:38:02 -0400 Subject: [PATCH 399/487] Add patch to fix mount hangs (rhbz 835019) --- ...k-fix-infinite-loop-in-__getblk_slow.patch | 153 ++++++++++++++++++ kernel.spec | 11 +- 2 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 block-fix-infinite-loop-in-__getblk_slow.patch diff --git a/block-fix-infinite-loop-in-__getblk_slow.patch b/block-fix-infinite-loop-in-__getblk_slow.patch new file mode 100644 index 000000000..f075a7133 --- /dev/null +++ b/block-fix-infinite-loop-in-__getblk_slow.patch @@ -0,0 +1,153 @@ + +Delivered-To: jwboyer@gmail.com +Received: by 10.229.191.66 with SMTP id dl2csp36421qcb; + Tue, 26 Jun 2012 07:55:48 -0700 (PDT) +Received: by 10.68.228.136 with SMTP id si8mr53042278pbc.159.1340722548310; + Tue, 26 Jun 2012 07:55:48 -0700 (PDT) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id qg1si15735731pbc.300.2012.06.26.07.55.47; + Tue, 26 Jun 2012 07:55:48 -0700 (PDT) +Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1757370Ab2FZOzp (ORCPT + + 23 others); Tue, 26 Jun 2012 10:55:45 -0400 +Received: from mx1.redhat.com ([209.132.183.28]:64097 "EHLO mx1.redhat.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1757325Ab2FZOzo (ORCPT ); + Tue, 26 Jun 2012 10:55:44 -0400 +Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q5QEtbK2017450 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Tue, 26 Jun 2012 10:55:38 -0400 +Received: from segfault.boston.devel.redhat.com (segfault.boston.devel.redhat.com [10.16.60.26]) + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q5QEtZV9023431; + Tue, 26 Jun 2012 10:55:35 -0400 +From: Jeff Moyer +To: Jens Axboe , Nick Piggin +Cc: LKML List , + torsten.hilbrich@secunet.com, Richard Jones , + stable@vger.kernel.org, Marcos Mello +Subject: [patch] block: fix infinite loop in __getblk_slow +X-PGP-KeyID: 1F78E1B4 +X-PGP-CertKey: F6FE 280D 8293 F72C 65FD 5A58 1FF8 A7CA 1F78 E1B4 +X-PCLoadLetter: What the f**k does that mean? +Date: Tue, 26 Jun 2012 10:55:34 -0400 +Message-ID: +User-Agent: Gnus/5.110011 (No Gnus v0.11) Emacs/23.1 (gnu/linux) +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +Sender: stable-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: stable@vger.kernel.org + +Hi, + +This commit: + +commit 080399aaaf3531f5b8761ec0ac30ff98891e8686 +Author: Jeff Moyer +Date: Fri May 11 16:34:10 2012 +0200 + + block: don't mark buffers beyond end of disk as mapped + +exposed a bug in __getblk_slow that causes mount to hang as it loops +infinitely waiting for a buffer that lies beyond the end of the disk to +become uptodate. The problem was initially reported by Torsten Hilbrich +here: https://lkml.org/lkml/2012/6/18/54, and also reported +independently here: +http://www.sysresccd.org/forums/viewtopic.php?f=13&t=4511, and then +Richard W.M. Jones and Marcos Mello noted a few separate bugzillas also +associated with the same issue. + +The main problem is here, in __getblk_slow: + + for (;;) { + struct buffer_head * bh; + int ret; + + bh = __find_get_block(bdev, block, size); + if (bh) + return bh; + + ret = grow_buffers(bdev, block, size); + if (ret < 0) + return NULL; + if (ret == 0) + free_more_memory(); + } + +__find_get_block does not find the block, since it will not be marked as +mapped, and so grow_buffers is called to fill in the buffers for the +associated page. I believe the for (;;) loop is there primarily to +retry in the case of memory pressure keeping grow_buffers from +succeeding. However, we also continue to loop for other cases, like the +block lying beond the end of the disk. So, the fix I came up with is to +only loop when grow_buffers fails due to memory allocation issues +(return value of 0). + +The attached patch was tested by myself, Torsten, and Rich, and was +found to resolve the problem in call cases. + +Comments, as always, are appreciated. + +Signed-off-by: Jeff Moyer +Reported-and-Tested-by: Torsten Hilbrich +Tested-by: Richard W.M. Jones +Cc: Stable + +-- +Stable Notes: this patch requires backport to 3.0, 3.2 and 3.3. + +diff --git a/fs/buffer.c b/fs/buffer.c +index 838a9cf..c7062c8 100644 +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -1036,6 +1036,9 @@ grow_buffers(struct block_device *bdev, sector_t block, int size) + static struct buffer_head * + __getblk_slow(struct block_device *bdev, sector_t block, int size) + { ++ int ret; ++ struct buffer_head *bh; ++ + /* Size must be multiple of hard sectorsize */ + if (unlikely(size & (bdev_logical_block_size(bdev)-1) || + (size < 512 || size > PAGE_SIZE))) { +@@ -1048,20 +1051,21 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size) + return NULL; + } + +- for (;;) { +- struct buffer_head * bh; +- int ret; ++retry: ++ bh = __find_get_block(bdev, block, size); ++ if (bh) ++ return bh; + ++ ret = grow_buffers(bdev, block, size); ++ if (ret == 0) { ++ free_more_memory(); ++ goto retry; ++ } else if (ret > 0) { + bh = __find_get_block(bdev, block, size); + if (bh) + return bh; +- +- ret = grow_buffers(bdev, block, size); +- if (ret < 0) +- return NULL; +- if (ret == 0) +- free_more_memory(); + } ++ return NULL; + } + + /* +-- +To unsubscribe from this list: send the line "unsubscribe stable" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/kernel.spec b/kernel.spec index 407c296ff..30f299c7b 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -781,6 +781,9 @@ Patch22034: usb-storage-try-read_capacity-10-first.patch #rhbz 828731 Patch22035: ath9k_htc-configure-bssid-on-ASSOC-IBSS-change.patch +#rhbz 835019 +Patch22036: block-fix-infinite-loop-in-__getblk_slow.patch + # END OF PATCH DEFINITIONS %endif @@ -1448,6 +1451,9 @@ ApplyPatch usb-storage-try-read_capacity-10-first.patch #rhbz 828731 ApplyPatch ath9k_htc-configure-bssid-on-ASSOC-IBSS-change.patch +#rhbz 835019 +ApplyPatch block-fix-infinite-loop-in-__getblk_slow.patch + # END OF PATCH APPLICATIONS %endif @@ -2186,6 +2192,9 @@ fi # and build. %changelog +* Tue Jun 26 2012 Josh Boyer +- Add patch to fix mount hangs (rhbz 835019) + * Tue Jun 26 2012 John W. Linville - ath9k_htc: configure bssid on ASSOC/IBSS change (rhbz 828731) From 7d971d55eb081e180a33844a9e74c25a54f46cac Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 26 Jun 2012 15:40:00 -0400 Subject: [PATCH 400/487] Add task_work_add backport from Anton Arapov --- kernel.spec | 5 +- ...dd-generic-process-context-callbacks.patch | 249 ++++++++++++++++++ 2 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 uprobes-task_work_add-generic-process-context-callbacks.patch diff --git a/kernel.spec b/kernel.spec index 30f299c7b..992728c71 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -728,6 +728,7 @@ Patch19000: ips-noirq.patch # Uprobes (rhbz 832083) Patch20000: uprobes-3.4-backport.patch Patch20001: uprobes-3.4-tip.patch +Patch20002: uprobes-task_work_add-generic-process-context-callbacks.patch # Flattened devicetree support Patch21000: arm-omap-dt-compat.patch @@ -1411,6 +1412,7 @@ ApplyPatch ips-noirq.patch # Uprobes (rhbz 832083) ApplyPatch uprobes-3.4-backport.patch ApplyPatch uprobes-3.4-tip.patch +ApplyPatch uprobes-task_work_add-generic-process-context-callbacks.patch #rhbz 754518 #ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -2193,6 +2195,7 @@ fi %changelog * Tue Jun 26 2012 Josh Boyer +- Add task_work_add backport from Anton Arapov - Add patch to fix mount hangs (rhbz 835019) * Tue Jun 26 2012 John W. Linville diff --git a/uprobes-task_work_add-generic-process-context-callbacks.patch b/uprobes-task_work_add-generic-process-context-callbacks.patch new file mode 100644 index 000000000..6f56b4261 --- /dev/null +++ b/uprobes-task_work_add-generic-process-context-callbacks.patch @@ -0,0 +1,249 @@ +FYI. This patch is upstream since linux-3.5. Backported in order to +bring SystemTap functionality back after the switch to linux-3.4 that +doesn't have utrace. :) + +The split-out series is available in the git repository at: + + git://fedorapeople.org/home/fedora/aarapov/public_git/kernel-uprobes.git + +Oleg Nesterov (1): + task_work_add: generic process-context callbacks + +Signed-off-by: Anton Arapov +--- + include/linux/sched.h | 2 ++ + include/linux/task_work.h | 33 ++++++++++++++++++ + include/linux/tracehook.h | 11 ++++++ + kernel/Makefile | 2 +- + kernel/exit.c | 5 ++- + kernel/fork.c | 1 + + kernel/task_work.c | 84 +++++++++++++++++++++++++++++++++++++++++++++ + 7 files changed, 136 insertions(+), 2 deletions(-) + create mode 100644 include/linux/task_work.h + create mode 100644 kernel/task_work.c + +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 6869c60..e011a11 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -1445,6 +1445,8 @@ struct task_struct { + int (*notifier)(void *priv); + void *notifier_data; + sigset_t *notifier_mask; ++ struct hlist_head task_works; ++ + struct audit_context *audit_context; + #ifdef CONFIG_AUDITSYSCALL + uid_t loginuid; +diff --git a/include/linux/task_work.h b/include/linux/task_work.h +new file mode 100644 +index 0000000..294d5d5 +--- /dev/null ++++ b/include/linux/task_work.h +@@ -0,0 +1,33 @@ ++#ifndef _LINUX_TASK_WORK_H ++#define _LINUX_TASK_WORK_H ++ ++#include ++#include ++ ++struct task_work; ++typedef void (*task_work_func_t)(struct task_work *); ++ ++struct task_work { ++ struct hlist_node hlist; ++ task_work_func_t func; ++ void *data; ++}; ++ ++static inline void ++init_task_work(struct task_work *twork, task_work_func_t func, void *data) ++{ ++ twork->func = func; ++ twork->data = data; ++} ++ ++int task_work_add(struct task_struct *task, struct task_work *twork, bool); ++struct task_work *task_work_cancel(struct task_struct *, task_work_func_t); ++void task_work_run(void); ++ ++static inline void exit_task_work(struct task_struct *task) ++{ ++ if (unlikely(!hlist_empty(&task->task_works))) ++ task_work_run(); ++} ++ ++#endif /* _LINUX_TASK_WORK_H */ +diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h +index 51bd91d..48c597d 100644 +--- a/include/linux/tracehook.h ++++ b/include/linux/tracehook.h +@@ -49,6 +49,7 @@ + #include + #include + #include ++#include + struct linux_binprm; + + /* +@@ -165,8 +166,10 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, + */ + static inline void set_notify_resume(struct task_struct *task) + { ++#ifdef TIF_NOTIFY_RESUME + if (!test_and_set_tsk_thread_flag(task, TIF_NOTIFY_RESUME)) + kick_process(task); ++#endif + } + + /** +@@ -184,6 +187,14 @@ static inline void set_notify_resume(struct task_struct *task) + */ + static inline void tracehook_notify_resume(struct pt_regs *regs) + { ++ /* ++ * The caller just cleared TIF_NOTIFY_RESUME. This barrier ++ * pairs with task_work_add()->set_notify_resume() after ++ * hlist_add_head(task->task_works); ++ */ ++ smp_mb__after_clear_bit(); ++ if (unlikely(!hlist_empty(¤t->task_works))) ++ task_work_run(); + } + #endif /* TIF_NOTIFY_RESUME */ + +diff --git a/kernel/Makefile b/kernel/Makefile +index cb41b95..2479528 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -5,7 +5,7 @@ + obj-y = fork.o exec_domain.o panic.o printk.o \ + cpu.o exit.o itimer.o time.o softirq.o resource.o \ + sysctl.o sysctl_binary.o capability.o ptrace.o timer.o user.o \ +- signal.o sys.o kmod.o workqueue.o pid.o \ ++ signal.o sys.o kmod.o workqueue.o pid.o task_work.o \ + rcupdate.o extable.o params.o posix-timers.o \ + kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ + hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ +diff --git a/kernel/exit.c b/kernel/exit.c +index d8bd3b42..b82c38e 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -946,11 +946,14 @@ void do_exit(long code) + exit_signals(tsk); /* sets PF_EXITING */ + /* + * tsk->flags are checked in the futex code to protect against +- * an exiting task cleaning up the robust pi futexes. ++ * an exiting task cleaning up the robust pi futexes, and in ++ * task_work_add() to avoid the race with exit_task_work(). + */ + smp_mb(); + raw_spin_unlock_wait(&tsk->pi_lock); + ++ exit_task_work(tsk); ++ + exit_irq_thread(); + + if (unlikely(in_atomic())) +diff --git a/kernel/fork.c b/kernel/fork.c +index 5b87e9f..76a961d 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -1391,6 +1391,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, + */ + p->group_leader = p; + INIT_LIST_HEAD(&p->thread_group); ++ INIT_HLIST_HEAD(&p->task_works); + + /* Now that the task is set up, run cgroup callbacks if + * necessary. We need to run them before the task is visible +diff --git a/kernel/task_work.c b/kernel/task_work.c +new file mode 100644 +index 0000000..82d1c79 +--- /dev/null ++++ b/kernel/task_work.c +@@ -0,0 +1,84 @@ ++#include ++#include ++#include ++ ++int ++task_work_add(struct task_struct *task, struct task_work *twork, bool notify) ++{ ++ unsigned long flags; ++ int err = -ESRCH; ++ ++#ifndef TIF_NOTIFY_RESUME ++ if (notify) ++ return -ENOTSUPP; ++#endif ++ /* ++ * We must not insert the new work if the task has already passed ++ * exit_task_work(). We rely on do_exit()->raw_spin_unlock_wait() ++ * and check PF_EXITING under pi_lock. ++ */ ++ raw_spin_lock_irqsave(&task->pi_lock, flags); ++ if (likely(!(task->flags & PF_EXITING))) { ++ hlist_add_head(&twork->hlist, &task->task_works); ++ err = 0; ++ } ++ raw_spin_unlock_irqrestore(&task->pi_lock, flags); ++ ++ /* test_and_set_bit() implies mb(), see tracehook_notify_resume(). */ ++ if (likely(!err) && notify) ++ set_notify_resume(task); ++ return err; ++} ++ ++struct task_work * ++task_work_cancel(struct task_struct *task, task_work_func_t func) ++{ ++ unsigned long flags; ++ struct task_work *twork; ++ struct hlist_node *pos; ++ ++ raw_spin_lock_irqsave(&task->pi_lock, flags); ++ hlist_for_each_entry(twork, pos, &task->task_works, hlist) { ++ if (twork->func == func) { ++ hlist_del(&twork->hlist); ++ goto found; ++ } ++ } ++ twork = NULL; ++ found: ++ raw_spin_unlock_irqrestore(&task->pi_lock, flags); ++ ++ return twork; ++} ++ ++void task_work_run(void) ++{ ++ struct task_struct *task = current; ++ struct hlist_head task_works; ++ struct hlist_node *pos; ++ ++ raw_spin_lock_irq(&task->pi_lock); ++ hlist_move_list(&task->task_works, &task_works); ++ raw_spin_unlock_irq(&task->pi_lock); ++ ++ if (unlikely(hlist_empty(&task_works))) ++ return; ++ /* ++ * We use hlist to save the space in task_struct, but we want fifo. ++ * Find the last entry, the list should be short, then process them ++ * in reverse order. ++ */ ++ for (pos = task_works.first; pos->next; pos = pos->next) ++ ; ++ ++ for (;;) { ++ struct hlist_node **pprev = pos->pprev; ++ struct task_work *twork = container_of(pos, struct task_work, ++ hlist); ++ twork->func(twork); ++ ++ if (pprev == &task_works.first) ++ break; ++ pos = container_of(pprev, struct hlist_node, next); ++ } ++} From 079eb63f0111d726eca78117fa92a2e4facbcbf6 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 26 Jun 2012 15:56:16 -0400 Subject: [PATCH 401/487] Add mm-correctly-synchronize-rss-counters-at-exit-exec.patch (rhbz 832867) --- kernel.spec | 9 ++ ...ynchronize-rss-counters-at-exit-exec.patch | 125 ++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 mm-correctly-synchronize-rss-counters-at-exit-exec.patch diff --git a/kernel.spec b/kernel.spec index 992728c71..b9f6d9b4a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -785,6 +785,9 @@ Patch22035: ath9k_htc-configure-bssid-on-ASSOC-IBSS-change.patch #rhbz 835019 Patch22036: block-fix-infinite-loop-in-__getblk_slow.patch +#rhbz 832867 +Patch22040: mm-correctly-synchronize-rss-counters-at-exit-exec.patch + # END OF PATCH DEFINITIONS %endif @@ -1456,6 +1459,9 @@ ApplyPatch ath9k_htc-configure-bssid-on-ASSOC-IBSS-change.patch #rhbz 835019 ApplyPatch block-fix-infinite-loop-in-__getblk_slow.patch +#rhbz 832867 +ApplyPatch mm-correctly-synchronize-rss-counters-at-exit-exec.patch + # END OF PATCH APPLICATIONS %endif @@ -2194,6 +2200,9 @@ fi # and build. %changelog +* Tue Jun 26 2012 Dave Jones +- Add mm-correctly-synchronize-rss-counters-at-exit-exec.patch (rhbz 832867) + * Tue Jun 26 2012 Josh Boyer - Add task_work_add backport from Anton Arapov - Add patch to fix mount hangs (rhbz 835019) diff --git a/mm-correctly-synchronize-rss-counters-at-exit-exec.patch b/mm-correctly-synchronize-rss-counters-at-exit-exec.patch new file mode 100644 index 000000000..0ef36b311 --- /dev/null +++ b/mm-correctly-synchronize-rss-counters-at-exit-exec.patch @@ -0,0 +1,125 @@ +From davej Wed Jun 20 11:37:32 2012 +Return-Path: oleg@redhat.com +X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on + gelk.kernelslacker.org +X-Spam-Level: +X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, + UNPARSEABLE_RELAY autolearn=ham version=3.3.2 +Received: from mail.corp.redhat.com [10.4.128.1] + by gelk.kernelslacker.org with IMAP (fetchmail-6.3.21) + for (single-drop); Wed, 20 Jun 2012 11:37:32 -0400 (EDT) +Received: from zmta05.collab.prod.int.phx2.redhat.com (LHLO + zmta05.collab.prod.int.phx2.redhat.com) (10.5.81.12) by + zmail11.collab.prod.int.phx2.redhat.com with LMTP; Wed, 20 Jun 2012 + 11:37:18 -0400 (EDT) +Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) + by zmta05.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 539B1F2080 + for ; Wed, 20 Jun 2012 11:37:18 -0400 (EDT) +Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) + by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id q5KFbGde008148; + Wed, 20 Jun 2012 11:37:17 -0400 +Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 + oleg@redhat.com; Wed, 20 Jun 2012 17:35:20 +0200 (CEST) +Date: Wed, 20 Jun 2012 17:35:19 +0200 +From: Oleg Nesterov +To: Dave Jones +Cc: Fedora Kernel Team +Subject: Re: [Bug 832867] BUG: Bad rss-counter state mm:xxxxxxxx idx:1 + val:-2 output in console +Message-ID: <20120620153519.GA17642@redhat.com> +References: <20120619172633.GG26103@redhat.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <20120619172633.GG26103@redhat.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +Status: RO +Content-Length: 2687 +Lines: 84 + +Hi Dave, + +sorry for delay + +On 06/19, Dave Jones wrote: +> +> > https://bugzilla.redhat.com/show_bug.cgi?id=832867 +> > +> > --- Comment #11 from Bojan Smojver --- +> > Patches for this: +> > +> > http://comments.gmane.org/gmane.linux.kernel/1306252 +> +> Oleg, +> +> are these patches final ? Are they headed for stable ? + +No. And 1/2 was wrong actually, see +http://marc.info/?l=linux-kernel&m=133911852215275 + +Konstantin sent the minimal fix, +mm-correctly-synchronize-rss-counters-at-exit-exec.patch in -mm tree, +attached below. + +Oleg. + +------------------------------------------------------ +From: Konstantin Khlebnikov +Subject: mm: correctly synchronize rss-counters at exit/exec + +do_exit() and exec_mmap() call sync_mm_rss() before mm_release() does +put_user(clear_child_tid) which can update task->rss_stat and thus make +mm->rss_stat inconsistent. This triggers the "BUG:" printk in check_mm(). + +Let's fix this bug in the safest way, and optimize/cleanup this later. + +Reported-by: Markus Trippelsdorf +Signed-off-by: Konstantin Khlebnikov +Cc: Oleg Nesterov +Cc: KAMEZAWA Hiroyuki +Cc: Hugh Dickins +Cc: +Signed-off-by: Andrew Morton +--- + + fs/exec.c | 2 +- + kernel/exit.c | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff -puN fs/exec.c~mm-correctly-synchronize-rss-counters-at-exit-exec fs/exec.c +--- a/fs/exec.c~mm-correctly-synchronize-rss-counters-at-exit-exec ++++ a/fs/exec.c +@@ -819,10 +819,10 @@ static int exec_mmap(struct mm_struct *m + /* Notify parent that we're no longer interested in the old VM */ + tsk = current; + old_mm = current->mm; +- sync_mm_rss(old_mm); + mm_release(tsk, old_mm); + + if (old_mm) { ++ sync_mm_rss(old_mm); + /* + * Make sure that if there is a core dump in progress + * for the old mm, we get out and die instead of going +diff -puN kernel/exit.c~mm-correctly-synchronize-rss-counters-at-exit-exec kernel/exit.c +--- a/kernel/exit.c~mm-correctly-synchronize-rss-counters-at-exit-exec ++++ a/kernel/exit.c +@@ -643,6 +643,7 @@ static void exit_mm(struct task_struct * + mm_release(tsk, mm); + if (!mm) + return; ++ sync_mm_rss(mm); + /* + * Serialize with any possible pending coredump. + * We must hold mmap_sem around checking core_state +_ +Subject: From: Konstantin Khlebnikov + +Patches currently in -mm which might be from khlebnikov@openvz.org are + +linux-next.patch +memcg-fix-use_hierarchy-css_is_ancestor-oops-regression.patch +mm-correctly-synchronize-rss-counters-at-exit-exec.patch + + From 2f6d12ef4aaac4cc71052d9416e382fd8aa98264 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 26 Jun 2012 16:15:10 -0400 Subject: [PATCH 402/487] Add version to changelog for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index b9f6d9b4a..b05887eb7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2200,7 +2200,7 @@ fi # and build. %changelog -* Tue Jun 26 2012 Dave Jones +* Tue Jun 26 2012 Dave Jones 3.4.4-3 - Add mm-correctly-synchronize-rss-counters-at-exit-exec.patch (rhbz 832867) * Tue Jun 26 2012 Josh Boyer From 727632ebef5a5a95455988ef98ae5a73bce64cbc Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 29 Jun 2012 10:26:56 -0400 Subject: [PATCH 403/487] ath9k: fix panic caused by returning a descriptor we have... (rhbz 832927) --- ...caused-by-returning-a-descriptor-we-.patch | 66 +++++++++++++++++++ kernel.spec | 9 +++ 2 files changed, 75 insertions(+) create mode 100644 ath9k-fix-panic-caused-by-returning-a-descriptor-we-.patch diff --git a/ath9k-fix-panic-caused-by-returning-a-descriptor-we-.patch b/ath9k-fix-panic-caused-by-returning-a-descriptor-we-.patch new file mode 100644 index 000000000..aec1f4245 --- /dev/null +++ b/ath9k-fix-panic-caused-by-returning-a-descriptor-we-.patch @@ -0,0 +1,66 @@ +From 6bb51c70cabaadddc54a6454844eceba91a56083 Mon Sep 17 00:00:00 2001 +From: Tom Hughes +Date: Wed, 27 Jun 2012 18:21:15 +0100 +Subject: [PATCH] ath9k: fix panic caused by returning a descriptor we have + queued for reuse + +Commit 3a2923e83c introduced a bug when a corrupt descriptor +is encountered - although the following descriptor is discarded +and returned to the queue for reuse the associated frame is +also returned for processing. This leads to a panic: + +BUG: unable to handle kernel NULL pointer dereference at 000000000000003a +IP: [] ath_rx_tasklet+0x165/0x1b00 [ath9k] +Call Trace: + +[] ? map_single+0x60/0x60 +[] ? ath9k_ioread32+0x34/0x90 [ath9k] +[] athk9k_tasklet+0xdc/0x160 [ath9k] +[] tasklet_action+0x63/0xd0 +[] __do_softirq+0xc0/0x1e0 +[] ? native_sched_clock+0x13/0x80 +[] call_softirq+0x1c/0x30 +[] do_softirq+0x75/0xb0 +[] irq_exit+0xb5/0xc0 +[] do_IRQ+0x63/0xe0 +[] common_interrupt+0x6a/0x6a + +[] ? intel_idle+0xea/0x150 +[] ? intel_idle+0xcb/0x150 +[] cpuidle_enter+0x19/0x20 +[] cpuidle_idle_call+0xa9/0x240 +[] cpu_idle+0xaf/0x120 +[] rest_init+0x72/0x74 +[] start_kernel+0x3b7/0x3c4 +[] ? repair_env_string+0x5e/0x5e +[] x86_64_start_reservations+0x131/0x135 +[] x86_64_start_kernel+0x100/0x10f + +Making sure bf is cleared to NULL in this case restores the +old behaviour. + +Signed-off-by: Tom Hughes +Signed-off-by: John W. Linville +--- + drivers/net/wireless/ath/ath9k/recv.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c +index 599667a..0735aeb 100644 +--- a/drivers/net/wireless/ath/ath9k/recv.c ++++ b/drivers/net/wireless/ath/ath9k/recv.c +@@ -695,9 +695,9 @@ static bool ath_edma_get_buffers(struct ath_softc *sc, + __skb_unlink(skb, &rx_edma->rx_fifo); + list_add_tail(&bf->list, &sc->rx.rxbuf); + ath_rx_edma_buf_link(sc, qtype); +- } else { +- bf = NULL; + } ++ ++ bf = NULL; + } + + *dest = bf; +-- +1.7.10.2 + diff --git a/kernel.spec b/kernel.spec index b05887eb7..c1ffb6f9a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -788,6 +788,9 @@ Patch22036: block-fix-infinite-loop-in-__getblk_slow.patch #rhbz 832867 Patch22040: mm-correctly-synchronize-rss-counters-at-exit-exec.patch +#rhbz 832927 +Patch22041: ath9k-fix-panic-caused-by-returning-a-descriptor-we-.patch + # END OF PATCH DEFINITIONS %endif @@ -1462,6 +1465,9 @@ ApplyPatch block-fix-infinite-loop-in-__getblk_slow.patch #rhbz 832867 ApplyPatch mm-correctly-synchronize-rss-counters-at-exit-exec.patch +#rhbz 832927 +ApplyPatch ath9k-fix-panic-caused-by-returning-a-descriptor-we-.patch + # END OF PATCH APPLICATIONS %endif @@ -2200,6 +2206,9 @@ fi # and build. %changelog +* Fri Jun 29 2012 John W. Linville +- ath9k: fix panic caused by returning a descriptor we have... (rhbz 832927) + * Tue Jun 26 2012 Dave Jones 3.4.4-3 - Add mm-correctly-synchronize-rss-counters-at-exit-exec.patch (rhbz 832867) From 523e29cf0b869ec8248eace6b8a38152696c618e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 3 Jul 2012 10:23:03 -0400 Subject: [PATCH 404/487] Allow ACPI backlight to still work if _DOS isn't present (rhbz 834910) --- ...cklight-control-if-_DOS-doesnt-exist.patch | 34 +++++++++++++++++++ kernel.spec | 11 +++++- 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 ACPI-video-Still-use-ACPI-backlight-control-if-_DOS-doesnt-exist.patch diff --git a/ACPI-video-Still-use-ACPI-backlight-control-if-_DOS-doesnt-exist.patch b/ACPI-video-Still-use-ACPI-backlight-control-if-_DOS-doesnt-exist.patch new file mode 100644 index 000000000..a89711132 --- /dev/null +++ b/ACPI-video-Still-use-ACPI-backlight-control-if-_DOS-doesnt-exist.patch @@ -0,0 +1,34 @@ + +This is a regression introduced by commit +ea9f8856bd6d4ed45885b06a338f7362cd6c60e5 +https://bugzilla.kernel.org/show_bug.cgi?id=43168 + +Some platforms don't have _DOS control method, but the ACPI +backlight still works. +We should not invoke _DOS for these platforms. + +CC : Igor Murzov +Signed-off-by: Zhang Rui +--- + drivers/acpi/video.c | 2 ++ + 1 file changed, 2 insertions(+) + +Index: rtd3/drivers/acpi/video.c +=================================================================== +--- rtd3.orig/drivers/acpi/video.c ++++ rtd3/drivers/acpi/video.c +@@ -558,6 +558,8 @@ acpi_video_bus_DOS(struct acpi_video_bus + union acpi_object arg0 = { ACPI_TYPE_INTEGER }; + struct acpi_object_list args = { 1, &arg0 }; + ++ if (!video->cap._DOS) ++ return 0; + + if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1) + return -EINVAL; + + +-- +To unsubscribe from this list: send the line "unsubscribe linux-acpi" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index c1ffb6f9a..8c03778be 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -791,6 +791,9 @@ Patch22040: mm-correctly-synchronize-rss-counters-at-exit-exec.patch #rhbz 832927 Patch22041: ath9k-fix-panic-caused-by-returning-a-descriptor-we-.patch +#rhbz 834910 +Patch22042: ACPI-video-Still-use-ACPI-backlight-control-if-_DOS-doesnt-exist.patch + # END OF PATCH DEFINITIONS %endif @@ -1468,6 +1471,9 @@ ApplyPatch mm-correctly-synchronize-rss-counters-at-exit-exec.patch #rhbz 832927 ApplyPatch ath9k-fix-panic-caused-by-returning-a-descriptor-we-.patch +#rhbz 834910 +ApplyPatch ACPI-video-Still-use-ACPI-backlight-control-if-_DOS-doesnt-exist.patch + # END OF PATCH APPLICATIONS %endif @@ -2206,6 +2212,9 @@ fi # and build. %changelog +* Tue Jul 3 2012 Josh Boyer +- Allow ACPI backlight to still work if _DOS isn't present (rhbz 834910) + * Fri Jun 29 2012 John W. Linville - ath9k: fix panic caused by returning a descriptor we have... (rhbz 832927) From 4ce79607e9945595a161dcb0444b5b287f01365b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 4 Jul 2012 11:30:05 -0400 Subject: [PATCH 405/487] Patch from Stanislaw Gruszka to fix rt2x00 USB access point (rhbz 828824) --- kernel.spec | 9 ++++ ...ix-indexes-ordering-on-RX-queue-kick.patch | 43 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch diff --git a/kernel.spec b/kernel.spec index 8c03778be..924e80752 100644 --- a/kernel.spec +++ b/kernel.spec @@ -794,6 +794,9 @@ Patch22041: ath9k-fix-panic-caused-by-returning-a-descriptor-we-.patch #rhbz 834910 Patch22042: ACPI-video-Still-use-ACPI-backlight-control-if-_DOS-doesnt-exist.patch +#rhbz 828824 +Patch22043: rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch + # END OF PATCH DEFINITIONS %endif @@ -1474,6 +1477,9 @@ ApplyPatch ath9k-fix-panic-caused-by-returning-a-descriptor-we-.patch #rhbz 834910 ApplyPatch ACPI-video-Still-use-ACPI-backlight-control-if-_DOS-doesnt-exist.patch +#rhbz 828824 +ApplyPatch rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch + # END OF PATCH APPLICATIONS %endif @@ -2212,6 +2218,9 @@ fi # and build. %changelog +* Wed Jul 4 2012 Josh Boyer +- Patch from Stanislaw Gruszka to fix rt2x00 USB access point (rhbz 828824) + * Tue Jul 3 2012 Josh Boyer - Allow ACPI backlight to still work if _DOS isn't present (rhbz 834910) diff --git a/rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch b/rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch new file mode 100644 index 000000000..76b83cca4 --- /dev/null +++ b/rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch @@ -0,0 +1,43 @@ +From e899a84a6e9bec0ce653713a48ca121cd754430c Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Mon, 2 Jul 2012 09:42:14 +0200 +Subject: [PATCH] rt2x00usb: fix indexes ordering on RX queue kick + +On rt2x00_dmastart() we increase index specified by Q_INDEX and on +rt2x00_dmadone() we increase index specified by Q_INDEX_DONE. So entries +between Q_INDEX_DONE and Q_INDEX are those we currently process in the +hardware. Entries between Q_INDEX and Q_INDEX_DONE are those we can +submit to the hardware. + +According to that fix rt2x00usb_kick_queue(), as we need to submit rx +entries that are not processed by the hardware. It worked before only +for empty queue, otherwise was broken. + +Note that for TX queues indexes ordering are ok. We need to kick entries +that have filled skb, but was not submitted to the hardware, i.e. +strted from Q_INDEX_DONE and have ENTRY_DATA_PENDING bit set. + +From practical standpoint this patch fixes AP mode connection hangs. + +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/rt2x00/rt2x00usb.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c +index d357d1e..74ecc33 100644 +--- a/drivers/net/wireless/rt2x00/rt2x00usb.c ++++ b/drivers/net/wireless/rt2x00/rt2x00usb.c +@@ -436,8 +436,8 @@ void rt2x00usb_kick_queue(struct data_queue *queue) + case QID_RX: + if (!rt2x00queue_full(queue)) + rt2x00queue_for_each_entry(queue, +- Q_INDEX_DONE, + Q_INDEX, ++ Q_INDEX_DONE, + NULL, + rt2x00usb_kick_rx_entry); + break; +-- +1.7.1 + From 84bcf579de5c7e36ecc24268bf138872a2e2d76e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 5 Jul 2012 13:44:39 -0400 Subject: [PATCH 406/487] Apply patch to fix tg3 watchdog hangs on BCM5906 devices (rhbz 825123) --- kernel.spec | 9 ++++++ ...ly-short-DMA-frag-workaround-to-5906.patch | 32 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tg3-Apply-short-DMA-frag-workaround-to-5906.patch diff --git a/kernel.spec b/kernel.spec index 924e80752..b4512e5ff 100644 --- a/kernel.spec +++ b/kernel.spec @@ -797,6 +797,9 @@ Patch22042: ACPI-video-Still-use-ACPI-backlight-control-if-_DOS-doesnt-exist.pat #rhbz 828824 Patch22043: rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch +#rhbz 825123 +Patch22044: tg3-Apply-short-DMA-frag-workaround-to-5906.patch + # END OF PATCH DEFINITIONS %endif @@ -1480,6 +1483,9 @@ ApplyPatch ACPI-video-Still-use-ACPI-backlight-control-if-_DOS-doesnt-exist.patc #rhbz 828824 ApplyPatch rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch +#rhbz 825123 +ApplyPatch tg3-Apply-short-DMA-frag-workaround-to-5906.patch + # END OF PATCH APPLICATIONS %endif @@ -2218,6 +2224,9 @@ fi # and build. %changelog +* Thu Jul 05 2012 Josh Boyer +- Apply patch to fix tg3 watchdog hangs on BCM5906 devices (rhbz 825123) + * Wed Jul 4 2012 Josh Boyer - Patch from Stanislaw Gruszka to fix rt2x00 USB access point (rhbz 828824) diff --git a/tg3-Apply-short-DMA-frag-workaround-to-5906.patch b/tg3-Apply-short-DMA-frag-workaround-to-5906.patch new file mode 100644 index 000000000..5cb78c7ca --- /dev/null +++ b/tg3-Apply-short-DMA-frag-workaround-to-5906.patch @@ -0,0 +1,32 @@ +From b7abee6ef888117f92db370620ebf116a38e3f4d Mon Sep 17 00:00:00 2001 +From: Matt Carlson +Date: Thu, 7 Jun 2012 12:56:54 +0000 +Subject: [PATCH] tg3: Apply short DMA frag workaround to 5906 + +5906 devices also need the short DMA fragment workaround. This patch +makes the necessary change. + +Signed-off-by: Matt Carlson +Tested-by: Christian Kujau +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/broadcom/tg3.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c +index edeeb51..e47ff8b 100644 +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -14275,7 +14275,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) + } + } + +- if (tg3_flag(tp, 5755_PLUS)) ++ if (tg3_flag(tp, 5755_PLUS) || ++ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + tg3_flag_set(tp, SHORT_DMA_BUG); + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) +-- +1.7.10.2 + From 5dd559875a1f6ca8472c275a9a6a11b45d0b09b2 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 5 Jul 2012 13:50:37 -0400 Subject: [PATCH 407/487] Fix breakage in nouveau with nv_two_heads (rhbz 830359) --- ...n-using-nv_two_heads-is-not-a-good-i.patch | 40 +++++++++++++++++++ kernel.spec | 7 ++++ 2 files changed, 47 insertions(+) create mode 100644 drm-nouveau-fbcon-using-nv_two_heads-is-not-a-good-i.patch diff --git a/drm-nouveau-fbcon-using-nv_two_heads-is-not-a-good-i.patch b/drm-nouveau-fbcon-using-nv_two_heads-is-not-a-good-i.patch new file mode 100644 index 000000000..2b164755d --- /dev/null +++ b/drm-nouveau-fbcon-using-nv_two_heads-is-not-a-good-i.patch @@ -0,0 +1,40 @@ +From 9bd0c15fcfb42f6245447c53347d65ad9e72080b Mon Sep 17 00:00:00 2001 +From: Ben Skeggs +Date: Tue, 26 Jun 2012 12:12:30 +1000 +Subject: [PATCH] drm/nouveau/fbcon: using nv_two_heads is not a good idea + +nv_two_heads() was never meant to be used outside of pre-nv50 code. The +code checks for >= NV_10 for 2 CRTCs, then downgrades a few specific +chipsets to 1 CRTC based on (pci_device & 0x0ff0). + +The breakage example seen is on GTX 560Ti, with a pciid of 0x1200, which +gets detected as an NV20 (0x020x) with 1 CRTC by nv_two_heads(), causing +memory corruption because there's actually 2 CRTCs.. + +This switches fbcon to use the CRTC count directly from the mode_config +structure, which will also fix the same issue on Kepler boards which have +4 CRTCs. + +Signed-off-by: Ben Skeggs +Cc: stable@vger.kernel.org +Signed-off-by: Dave Airlie +--- + drivers/gpu/drm/nouveau/nouveau_fbcon.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c +index 153b9a1..1074bc5 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c ++++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c +@@ -467,7 +467,7 @@ int nouveau_fbcon_init(struct drm_device *dev) + nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs; + + ret = drm_fb_helper_init(dev, &nfbdev->helper, +- nv_two_heads(dev) ? 2 : 1, 4); ++ dev->mode_config.num_crtc, 4); + if (ret) { + kfree(nfbdev); + return ret; +-- +1.7.10.2 + diff --git a/kernel.spec b/kernel.spec index b4512e5ff..2cf32eeaf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -800,6 +800,9 @@ Patch22043: rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch #rhbz 825123 Patch22044: tg3-Apply-short-DMA-frag-workaround-to-5906.patch +#rhbz 830359 +Patch22045: drm-nouveau-fbcon-using-nv_two_heads-is-not-a-good-i.patch + # END OF PATCH DEFINITIONS %endif @@ -1486,6 +1489,9 @@ ApplyPatch rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch #rhbz 825123 ApplyPatch tg3-Apply-short-DMA-frag-workaround-to-5906.patch +#rhbz 830359 +ApplyPatch drm-nouveau-fbcon-using-nv_two_heads-is-not-a-good-i.patch + # END OF PATCH APPLICATIONS %endif @@ -2225,6 +2231,7 @@ fi %changelog * Thu Jul 05 2012 Josh Boyer +- Fix breakage in nouveau with nv_two_heads (rhbz 830359) - Apply patch to fix tg3 watchdog hangs on BCM5906 devices (rhbz 825123) * Wed Jul 4 2012 Josh Boyer From e8239bd251fa6655da9858841796e1094228977a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 5 Jul 2012 13:58:22 -0400 Subject: [PATCH 408/487] Fix device misprobe for Gobi devices (rhbz 829880) --- USB-qmi_wwan-Add-ZTE-Vodafone-K3520-Z.patch | 54 +++++ ...-Make-forced-int-4-whitelist-generic.patch | 47 +++++ kernel.spec | 11 + net-qmi_wwan-fix-Gobi-device-probing.patch | 194 ++++++++++++++++++ 4 files changed, 306 insertions(+) create mode 100644 USB-qmi_wwan-Add-ZTE-Vodafone-K3520-Z.patch create mode 100644 USB-qmi_wwan-Make-forced-int-4-whitelist-generic.patch create mode 100644 net-qmi_wwan-fix-Gobi-device-probing.patch diff --git a/USB-qmi_wwan-Add-ZTE-Vodafone-K3520-Z.patch b/USB-qmi_wwan-Add-ZTE-Vodafone-K3520-Z.patch new file mode 100644 index 000000000..9ce05cc72 --- /dev/null +++ b/USB-qmi_wwan-Add-ZTE-Vodafone-K3520-Z.patch @@ -0,0 +1,54 @@ +From f7142e6c226076fd40c2ebaad9fb0c9a631b790e Mon Sep 17 00:00:00 2001 +From: "Andrew Bird (Sphere Systems)" +Date: Sat, 19 May 2012 22:28:38 +0000 +Subject: [PATCH] USB: qmi_wwan: Add ZTE (Vodafone) K3520-Z +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Andrew Bird +Acked-by: Bjørn Mork +Signed-off-by: David S. Miller +--- + drivers/net/usb/qmi_wwan.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c +index b381368..63cfd0b 100644 +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -356,6 +356,15 @@ static const struct driver_info qmi_wwan_gobi = { + }; + + /* ZTE suck at making USB descriptors */ ++static const struct driver_info qmi_wwan_force_int1 = { ++ .description = "Qualcomm WWAN/QMI device", ++ .flags = FLAG_WWAN, ++ .bind = qmi_wwan_bind_shared, ++ .unbind = qmi_wwan_unbind_shared, ++ .manage_power = qmi_wwan_manage_power, ++ .data = BIT(1), /* interface whitelist bitmap */ ++}; ++ + static const struct driver_info qmi_wwan_force_int4 = { + .description = "Qualcomm WWAN/QMI device", + .flags = FLAG_WWAN, +@@ -438,6 +447,15 @@ static const struct usb_device_id products[] = { + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int4, + }, ++ { /* ZTE (Vodafone) K3520-Z */ ++ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x19d2, ++ .idProduct = 0x0055, ++ .bInterfaceClass = 0xff, ++ .bInterfaceSubClass = 0xff, ++ .bInterfaceProtocol = 0xff, ++ .driver_info = (unsigned long)&qmi_wwan_force_int1, ++ }, + { /* ZTE (Vodafone) K3565-Z */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, +-- +1.7.10.2 + diff --git a/USB-qmi_wwan-Make-forced-int-4-whitelist-generic.patch b/USB-qmi_wwan-Make-forced-int-4-whitelist-generic.patch new file mode 100644 index 000000000..87e84a0bd --- /dev/null +++ b/USB-qmi_wwan-Make-forced-int-4-whitelist-generic.patch @@ -0,0 +1,47 @@ +From 00001880cd8faaa349fe2ebb158f7e0cd8026048 Mon Sep 17 00:00:00 2001 +From: "Andrew Bird (Sphere Systems)" +Date: Sat, 19 May 2012 22:28:36 +0000 +Subject: [PATCH] USB: qmi_wwan: Make forced int 4 whitelist generic +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Change the forced interface 4 whitelist to use the generic shared +binder instead of the Gobi specific one. Certain ZTE devices +(K3520-Z & K3765-Z) don't work with the Gobi version, but function +quite happily with the generic. This has been tested with the following +devices: +K3520-Z +K3565-Z +K3765-Z +K4505-Z +It hasn't been tested with the ZTE MF820D, which is the only other +device that uses this whitelist at present. Although Bjorn doesn't +expect any problems, any testing with that device would be appreciated. + +Signed-off-by: Andrew Bird +Acked-by: Bjørn Mork +Signed-off-by: David S. Miller +--- + drivers/net/usb/qmi_wwan.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c +index fc1ebef..a0fee0d 100644 +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -357,9 +357,9 @@ static const struct driver_info qmi_wwan_gobi = { + + /* ZTE suck at making USB descriptors */ + static const struct driver_info qmi_wwan_force_int4 = { +- .description = "Qualcomm Gobi wwan/QMI device", ++ .description = "Qualcomm WWAN/QMI device", + .flags = FLAG_WWAN, +- .bind = qmi_wwan_bind_gobi, ++ .bind = qmi_wwan_bind_shared, + .unbind = qmi_wwan_unbind_shared, + .manage_power = qmi_wwan_manage_power, + .data = BIT(4), /* interface whitelist bitmap */ +-- +1.7.10.2 + diff --git a/kernel.spec b/kernel.spec index 2cf32eeaf..d205d4219 100644 --- a/kernel.spec +++ b/kernel.spec @@ -803,6 +803,11 @@ Patch22044: tg3-Apply-short-DMA-frag-workaround-to-5906.patch #rhbz 830359 Patch22045: drm-nouveau-fbcon-using-nv_two_heads-is-not-a-good-i.patch +#rhbz 829880 +Patch22046: USB-qmi_wwan-Make-forced-int-4-whitelist-generic.patch +Patch22047: USB-qmi_wwan-Add-ZTE-Vodafone-K3520-Z.patch +Patch22048: net-qmi_wwan-fix-Gobi-device-probing.patch + # END OF PATCH DEFINITIONS %endif @@ -1492,6 +1497,11 @@ ApplyPatch tg3-Apply-short-DMA-frag-workaround-to-5906.patch #rhbz 830359 ApplyPatch drm-nouveau-fbcon-using-nv_two_heads-is-not-a-good-i.patch +#rhbz 829880 +ApplyPatch USB-qmi_wwan-Make-forced-int-4-whitelist-generic.patch +ApplyPatch USB-qmi_wwan-Add-ZTE-Vodafone-K3520-Z.patch +ApplyPatch net-qmi_wwan-fix-Gobi-device-probing.patch + # END OF PATCH APPLICATIONS %endif @@ -2231,6 +2241,7 @@ fi %changelog * Thu Jul 05 2012 Josh Boyer +- Fix device misprobe for Gobi devices (rhbz 829880) - Fix breakage in nouveau with nv_two_heads (rhbz 830359) - Apply patch to fix tg3 watchdog hangs on BCM5906 devices (rhbz 825123) diff --git a/net-qmi_wwan-fix-Gobi-device-probing.patch b/net-qmi_wwan-fix-Gobi-device-probing.patch new file mode 100644 index 000000000..9dce14f4a --- /dev/null +++ b/net-qmi_wwan-fix-Gobi-device-probing.patch @@ -0,0 +1,194 @@ +From b9f90eb2740203ff2592efe640409ad48335d1c2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= +Date: Thu, 21 Jun 2012 02:45:58 +0000 +Subject: [PATCH] net: qmi_wwan: fix Gobi device probing +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Ignoring interfaces with additional descriptors is not a reliable +method for locating the correct interface on Gobi devices. There +is at least one device where this method fails: +https://bbs.archlinux.org/viewtopic.php?id=143506 + +The result is that the AT command port (interface #2) is hidden +from qcserial, preventing traditional serial modem usage: + +[ 15.562552] qmi_wwan 4-1.6:1.0: cdc-wdm0: USB WDM device +[ 15.562691] qmi_wwan 4-1.6:1.0: wwan0: register 'qmi_wwan' at usb-0000:00:1d.0-1.6, Qualcomm Gobi wwan/QMI device, 1e:df:3c:3a:4e:3b +[ 15.563383] qmi_wwan: probe of 4-1.6:1.1 failed with error -22 +[ 15.564189] qmi_wwan 4-1.6:1.2: cdc-wdm1: USB WDM device +[ 15.564302] qmi_wwan 4-1.6:1.2: wwan1: register 'qmi_wwan' at usb-0000:00:1d.0-1.6, Qualcomm Gobi wwan/QMI device, 1e:df:3c:3a:4e:3b +[ 15.564328] qmi_wwan: probe of 4-1.6:1.3 failed with error -22 +[ 15.569376] qcserial 4-1.6:1.1: Qualcomm USB modem converter detected +[ 15.569440] usb 4-1.6: Qualcomm USB modem converter now attached to ttyUSB0 +[ 15.570372] qcserial 4-1.6:1.3: Qualcomm USB modem converter detected +[ 15.570430] usb 4-1.6: Qualcomm USB modem converter now attached to ttyUSB1 + +Use static interface numbers taken from the interface map in +qcserial for all Gobi devices instead: + + Gobi 1K USB layout: + 0: serial port (doesn't respond) + 1: serial port (doesn't respond) + 2: AT-capable modem port + 3: QMI/net + + Gobi 2K+ USB layout: + 0: QMI/net + 1: DM/DIAG (use libqcdm from ModemManager for communication) + 2: AT-capable modem port + 3: NMEA + +This should be more reliable over all, and will also prevent the +noisy "probe failed" messages. The whitelisting logic is expected +to be replaced by direct interface number matching in 3.6. + +Reported-by: Heinrich Siebmanns (Harvey) +Cc: # v3.4: 0000188 USB: qmi_wwan: Make forced int 4 whitelist generic +Cc: # v3.4: f7142e6 USB: qmi_wwan: Add ZTE (Vodafone) K3520-Z +Cc: # v3.4 +Signed-off-by: Bjørn Mork +Signed-off-by: David S. Miller +--- + drivers/net/usb/qmi_wwan.c | 83 +++++++++++++++++++++----------------------- + 1 file changed, 40 insertions(+), 43 deletions(-) + +diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c +index 3b20678..3767a12 100644 +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -257,29 +257,6 @@ err: + return rv; + } + +-/* Gobi devices uses identical class/protocol codes for all interfaces regardless +- * of function. Some of these are CDC ACM like and have the exact same endpoints +- * we are looking for. This leaves two possible strategies for identifying the +- * correct interface: +- * a) hardcoding interface number, or +- * b) use the fact that the wwan interface is the only one lacking additional +- * (CDC functional) descriptors +- * +- * Let's see if we can get away with the generic b) solution. +- */ +-static int qmi_wwan_bind_gobi(struct usbnet *dev, struct usb_interface *intf) +-{ +- int rv = -EINVAL; +- +- /* ignore any interface with additional descriptors */ +- if (intf->cur_altsetting->extralen) +- goto err; +- +- rv = qmi_wwan_bind_shared(dev, intf); +-err: +- return rv; +-} +- + static void qmi_wwan_unbind_shared(struct usbnet *dev, struct usb_interface *intf) + { + struct usb_driver *subdriver = (void *)dev->data[0]; +@@ -347,15 +324,15 @@ static const struct driver_info qmi_wwan_shared = { + .manage_power = qmi_wwan_manage_power, + }; + +-static const struct driver_info qmi_wwan_gobi = { +- .description = "Qualcomm Gobi wwan/QMI device", ++static const struct driver_info qmi_wwan_force_int0 = { ++ .description = "Qualcomm WWAN/QMI device", + .flags = FLAG_WWAN, +- .bind = qmi_wwan_bind_gobi, ++ .bind = qmi_wwan_bind_shared, + .unbind = qmi_wwan_unbind_shared, + .manage_power = qmi_wwan_manage_power, ++ .data = BIT(0), /* interface whitelist bitmap */ + }; + +-/* ZTE suck at making USB descriptors */ + static const struct driver_info qmi_wwan_force_int1 = { + .description = "Qualcomm WWAN/QMI device", + .flags = FLAG_WWAN, +@@ -365,6 +342,15 @@ static const struct driver_info qmi_wwan_force_int1 = { + .data = BIT(1), /* interface whitelist bitmap */ + }; + ++static const struct driver_info qmi_wwan_force_int3 = { ++ .description = "Qualcomm WWAN/QMI device", ++ .flags = FLAG_WWAN, ++ .bind = qmi_wwan_bind_shared, ++ .unbind = qmi_wwan_unbind_shared, ++ .manage_power = qmi_wwan_manage_power, ++ .data = BIT(3), /* interface whitelist bitmap */ ++}; ++ + static const struct driver_info qmi_wwan_force_int4 = { + .description = "Qualcomm WWAN/QMI device", + .flags = FLAG_WWAN, +@@ -390,16 +376,23 @@ static const struct driver_info qmi_wwan_force_int4 = { + static const struct driver_info qmi_wwan_sierra = { + .description = "Sierra Wireless wwan/QMI device", + .flags = FLAG_WWAN, +- .bind = qmi_wwan_bind_gobi, ++ .bind = qmi_wwan_bind_shared, + .unbind = qmi_wwan_unbind_shared, + .manage_power = qmi_wwan_manage_power, + .data = BIT(8) | BIT(19), /* interface whitelist bitmap */ + }; + + #define HUAWEI_VENDOR_ID 0x12D1 ++ ++/* Gobi 1000 QMI/wwan interface number is 3 according to qcserial */ ++#define QMI_GOBI1K_DEVICE(vend, prod) \ ++ USB_DEVICE(vend, prod), \ ++ .driver_info = (unsigned long)&qmi_wwan_force_int3 ++ ++/* Gobi 2000 and Gobi 3000 QMI/wwan interface number is 0 according to qcserial */ + #define QMI_GOBI_DEVICE(vend, prod) \ + USB_DEVICE(vend, prod), \ +- .driver_info = (unsigned long)&qmi_wwan_gobi ++ .driver_info = (unsigned long)&qmi_wwan_force_int0 + + static const struct usb_device_id products[] = { + { /* Huawei E392, E398 and possibly others sharing both device id and more... */ +@@ -510,20 +503,24 @@ static const struct usb_device_id products[] = { + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_sierra, + }, +- {QMI_GOBI_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ +- {QMI_GOBI_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ +- {QMI_GOBI_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ +- {QMI_GOBI_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ +- {QMI_GOBI_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */ +- {QMI_GOBI_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ +- {QMI_GOBI_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ +- {QMI_GOBI_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */ +- {QMI_GOBI_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */ +- {QMI_GOBI_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */ +- {QMI_GOBI_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */ +- {QMI_GOBI_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */ +- {QMI_GOBI_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ +- {QMI_GOBI_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ ++ ++ /* Gobi 1000 devices */ ++ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ ++ {QMI_GOBI1K_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ ++ {QMI_GOBI1K_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ ++ {QMI_GOBI1K_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ ++ {QMI_GOBI1K_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */ ++ {QMI_GOBI1K_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ ++ {QMI_GOBI1K_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ ++ {QMI_GOBI1K_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */ ++ {QMI_GOBI1K_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */ ++ {QMI_GOBI1K_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */ ++ {QMI_GOBI1K_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */ ++ {QMI_GOBI1K_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */ ++ {QMI_GOBI1K_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ ++ {QMI_GOBI1K_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ ++ ++ /* Gobi 2000 and 3000 devices */ + {QMI_GOBI_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */ + {QMI_GOBI_DEVICE(0x05c6, 0x920b)}, /* Generic Gobi 2000 Modem device */ + {QMI_GOBI_DEVICE(0x05c6, 0x9225)}, /* Sony Gobi 2000 Modem device (N0279, VU730) */ +-- +1.7.10.2 + From 6cc1c4a89f28eaa40ad4b6f270a4507163a44e46 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 6 Jul 2012 16:29:41 -0500 Subject: [PATCH 409/487] ACPI, APEI, Avoid too much error reporting in runtime --- ...-APEI-Avoid-too-much-error-reporting.patch | 121 ++++++++++++++++++ kernel.spec | 7 + 2 files changed, 128 insertions(+) create mode 100644 ACPI-APEI-Avoid-too-much-error-reporting.patch diff --git a/ACPI-APEI-Avoid-too-much-error-reporting.patch b/ACPI-APEI-Avoid-too-much-error-reporting.patch new file mode 100644 index 000000000..fe6e697b4 --- /dev/null +++ b/ACPI-APEI-Avoid-too-much-error-reporting.patch @@ -0,0 +1,121 @@ +commit 34ddeb035d704eafdcdb3cbc781894300136c3c4 +Author: Huang Ying +Date: Tue Jun 12 11:20:19 2012 +0800 + + ACPI, APEI, Avoid too much error reporting in runtime + + This patch fixed the following bug. + + https://bugzilla.kernel.org/show_bug.cgi?id=43282 + + This is caused by a firmware bug checking (checking generic address + register provided by firmware) in runtime. The checking should be + done in address mapping time instead of runtime to avoid too much + error reporting in runtime. + + Reported-by: Pawel Sikora + Signed-off-by: Huang Ying + Tested-by: Jean Delvare + Cc: stable@vger.kernel.org + Signed-off-by: Len Brown + +diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c +index 5577762..6686b1e 100644 +--- a/drivers/acpi/apei/apei-base.c ++++ b/drivers/acpi/apei/apei-base.c +@@ -243,7 +243,7 @@ static int pre_map_gar_callback(struct apei_exec_context *ctx, + u8 ins = entry->instruction; + + if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER) +- return acpi_os_map_generic_address(&entry->register_region); ++ return apei_map_generic_address(&entry->register_region); + + return 0; + } +@@ -276,7 +276,7 @@ static int post_unmap_gar_callback(struct apei_exec_context *ctx, + u8 ins = entry->instruction; + + if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER) +- acpi_os_unmap_generic_address(&entry->register_region); ++ apei_unmap_generic_address(&entry->register_region); + + return 0; + } +@@ -606,6 +606,19 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr, + return 0; + } + ++int apei_map_generic_address(struct acpi_generic_address *reg) ++{ ++ int rc; ++ u32 access_bit_width; ++ u64 address; ++ ++ rc = apei_check_gar(reg, &address, &access_bit_width); ++ if (rc) ++ return rc; ++ return acpi_os_map_generic_address(reg); ++} ++EXPORT_SYMBOL_GPL(apei_map_generic_address); ++ + /* read GAR in interrupt (including NMI) or process context */ + int apei_read(u64 *val, struct acpi_generic_address *reg) + { +diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h +index cca240a..f220d64 100644 +--- a/drivers/acpi/apei/apei-internal.h ++++ b/drivers/acpi/apei/apei-internal.h +@@ -7,6 +7,8 @@ + #define APEI_INTERNAL_H + + #include ++#include ++#include + + struct apei_exec_context; + +@@ -68,6 +70,13 @@ static inline int apei_exec_run_optional(struct apei_exec_context *ctx, u8 actio + /* IP has been set in instruction function */ + #define APEI_EXEC_SET_IP 1 + ++int apei_map_generic_address(struct acpi_generic_address *reg); ++ ++static inline void apei_unmap_generic_address(struct acpi_generic_address *reg) ++{ ++ acpi_os_unmap_generic_address(reg); ++} ++ + int apei_read(u64 *val, struct acpi_generic_address *reg); + int apei_write(u64 val, struct acpi_generic_address *reg); + +diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c +index 9b3cac0..1599566 100644 +--- a/drivers/acpi/apei/ghes.c ++++ b/drivers/acpi/apei/ghes.c +@@ -301,7 +301,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic) + if (!ghes) + return ERR_PTR(-ENOMEM); + ghes->generic = generic; +- rc = acpi_os_map_generic_address(&generic->error_status_address); ++ rc = apei_map_generic_address(&generic->error_status_address); + if (rc) + goto err_free; + error_block_length = generic->error_block_length; +@@ -321,7 +321,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic) + return ghes; + + err_unmap: +- acpi_os_unmap_generic_address(&generic->error_status_address); ++ apei_unmap_generic_address(&generic->error_status_address); + err_free: + kfree(ghes); + return ERR_PTR(rc); +@@ -330,7 +330,7 @@ err_free: + static void ghes_fini(struct ghes *ghes) + { + kfree(ghes->estatus); +- acpi_os_unmap_generic_address(&ghes->generic->error_status_address); ++ apei_unmap_generic_address(&ghes->generic->error_status_address); + } + + enum { diff --git a/kernel.spec b/kernel.spec index d205d4219..bde26bf45 100644 --- a/kernel.spec +++ b/kernel.spec @@ -808,6 +808,8 @@ Patch22046: USB-qmi_wwan-Make-forced-int-4-whitelist-generic.patch Patch22047: USB-qmi_wwan-Add-ZTE-Vodafone-K3520-Z.patch Patch22048: net-qmi_wwan-fix-Gobi-device-probing.patch +Patch22050: ACPI-APEI-Avoid-too-much-error-reporting.patch + # END OF PATCH DEFINITIONS %endif @@ -1502,6 +1504,8 @@ ApplyPatch USB-qmi_wwan-Make-forced-int-4-whitelist-generic.patch ApplyPatch USB-qmi_wwan-Add-ZTE-Vodafone-K3520-Z.patch ApplyPatch net-qmi_wwan-fix-Gobi-device-probing.patch +ApplyPatch ACPI-APEI-Avoid-too-much-error-reporting.patch + # END OF PATCH APPLICATIONS %endif @@ -2240,6 +2244,9 @@ fi # and build. %changelog +* Fri Jul 06 2012 Justin M. Forbes +- ACPI, APEI, Avoid too much error reporting in runtime + * Thu Jul 05 2012 Josh Boyer - Fix device misprobe for Gobi devices (rhbz 829880) - Fix breakage in nouveau with nv_two_heads (rhbz 830359) From 3c82288578a839833c02e6d5fc9efde16afda79a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 10 Jul 2012 13:26:24 -0400 Subject: [PATCH 410/487] Add patch to fix xen dom0 crash when using BLKDISCARD (rhbz 824641) --- kernel.spec | 11 +++- ...py-id-field-when-doing-BLKIF_DISCARD.patch | 54 +++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 xen-blkback-Copy-id-field-when-doing-BLKIF_DISCARD.patch diff --git a/kernel.spec b/kernel.spec index bde26bf45..bb8e2f6e5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -810,6 +810,9 @@ Patch22048: net-qmi_wwan-fix-Gobi-device-probing.patch Patch22050: ACPI-APEI-Avoid-too-much-error-reporting.patch +#rhbz 824641 +Patch22051: xen-blkback-Copy-id-field-when-doing-BLKIF_DISCARD.patch + # END OF PATCH DEFINITIONS %endif @@ -1506,6 +1509,9 @@ ApplyPatch net-qmi_wwan-fix-Gobi-device-probing.patch ApplyPatch ACPI-APEI-Avoid-too-much-error-reporting.patch +#rhbz 824641 +ApplyPatch xen-blkback-Copy-id-field-when-doing-BLKIF_DISCARD.patch + # END OF PATCH APPLICATIONS %endif @@ -2244,6 +2250,9 @@ fi # and build. %changelog +* Tue Jul 10 2012 Josh Boyer +- Add patch to fix xen dom0 crash when using BLKDISCARD (rhbz 824641) + * Fri Jul 06 2012 Justin M. Forbes - ACPI, APEI, Avoid too much error reporting in runtime diff --git a/xen-blkback-Copy-id-field-when-doing-BLKIF_DISCARD.patch b/xen-blkback-Copy-id-field-when-doing-BLKIF_DISCARD.patch new file mode 100644 index 000000000..056d79b15 --- /dev/null +++ b/xen-blkback-Copy-id-field-when-doing-BLKIF_DISCARD.patch @@ -0,0 +1,54 @@ +From 8c9ce606a60e4a0cb447bdc082ce383b96b227b4 Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Fri, 25 May 2012 16:11:09 -0400 +Subject: [PATCH] xen/blkback: Copy id field when doing BLKIF_DISCARD. + +We weren't copying the id field so when we sent the response +back to the frontend (especially with a 64-bit host and 32-bit +guest), we ended up using a random value. This lead to the +frontend crashing as it would try to pass to __blk_end_request_all +a NULL 'struct request' (b/c it would use the 'id' to find the +proper 'struct request' in its shadow array) and end up crashing: + +BUG: unable to handle kernel NULL pointer dereference at 000000e4 +IP: [] __blk_end_request_all+0xc/0x40 +.. snip.. +EIP is at __blk_end_request_all+0xc/0x40 +.. snip.. + [] blkif_interrupt+0x172/0x330 [xen_blkfront] + +This fixes the bug by passing in the proper id for the response. + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=824641 + +CC: stable@kernel.org +Tested-by: William Dauchy +Acked-by: Stefano Stabellini +Signed-off-by: Konrad Rzeszutek Wilk +--- + drivers/block/xen-blkback/common.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h +index 773cf27..9ad3b5e 100644 +--- a/drivers/block/xen-blkback/common.h ++++ b/drivers/block/xen-blkback/common.h +@@ -257,6 +257,7 @@ static inline void blkif_get_x86_32_req(struct blkif_request *dst, + break; + case BLKIF_OP_DISCARD: + dst->u.discard.flag = src->u.discard.flag; ++ dst->u.discard.id = src->u.discard.id; + dst->u.discard.sector_number = src->u.discard.sector_number; + dst->u.discard.nr_sectors = src->u.discard.nr_sectors; + break; +@@ -287,6 +288,7 @@ static inline void blkif_get_x86_64_req(struct blkif_request *dst, + break; + case BLKIF_OP_DISCARD: + dst->u.discard.flag = src->u.discard.flag; ++ dst->u.discard.id = src->u.discard.id; + dst->u.discard.sector_number = src->u.discard.sector_number; + dst->u.discard.nr_sectors = src->u.discard.nr_sectors; + break; +-- +1.7.10.4 + From a9a4422683b53fbaf2e13499be57ebfa2649e8e9 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 11 Jul 2012 10:47:41 -0500 Subject: [PATCH 411/487] Fix FIPS for aesni hardware (rhbz 839239) --- ...-aesni-intel-fix-wrong-kfree-pointer.patch | 45 +++++++ ...-aesni-intel-and-ghash_clmulni-intel.patch | 122 ++++++++++++++++++ kernel.spec | 11 ++ 3 files changed, 178 insertions(+) create mode 100644 crypto-aesni-intel-fix-wrong-kfree-pointer.patch create mode 100644 crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch diff --git a/crypto-aesni-intel-fix-wrong-kfree-pointer.patch b/crypto-aesni-intel-fix-wrong-kfree-pointer.patch new file mode 100644 index 000000000..e9942c06f --- /dev/null +++ b/crypto-aesni-intel-fix-wrong-kfree-pointer.patch @@ -0,0 +1,45 @@ +From bf084d8f6eb4ded3f90a6ab79bb682db00ebfbd4 Mon Sep 17 00:00:00 2001 +From: Milan Broz +Date: Thu, 28 Jun 2012 17:26:02 +0200 +Subject: [PATCH] crypto: aesni-intel - fix wrong kfree pointer + +kfree(new_key_mem) in rfc4106_set_key() should be called on malloced pointer, +not on aligned one, otherwise it can cause invalid pointer on free. + +(Seen at least once when running tcrypt tests with debug kernel.) + +Signed-off-by: Milan Broz +Signed-off-by: Herbert Xu +--- + arch/x86/crypto/aesni-intel_glue.c | 8 ++++---- + 1 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c +index d662615..34fdcff 100644 +--- a/arch/x86/crypto/aesni-intel_glue.c ++++ b/arch/x86/crypto/aesni-intel_glue.c +@@ -529,7 +529,7 @@ static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key, + struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm); + struct aesni_rfc4106_gcm_ctx *child_ctx = + aesni_rfc4106_gcm_ctx_get(cryptd_child); +- u8 *new_key_mem = NULL; ++ u8 *new_key_align, *new_key_mem = NULL; + + if (key_len < 4) { + crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); +@@ -553,9 +553,9 @@ static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key, + if (!new_key_mem) + return -ENOMEM; + +- new_key_mem = PTR_ALIGN(new_key_mem, AESNI_ALIGN); +- memcpy(new_key_mem, key, key_len); +- key = new_key_mem; ++ new_key_align = PTR_ALIGN(new_key_mem, AESNI_ALIGN); ++ memcpy(new_key_align, key, key_len); ++ key = new_key_align; + } + + if (!irq_fpu_usable()) +-- +1.7.6.5 + diff --git a/crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch b/crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch new file mode 100644 index 000000000..9aef14c52 --- /dev/null +++ b/crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch @@ -0,0 +1,122 @@ +From 6c79294f44fd7d1122cbaabff3b9815b074c0dd0 Mon Sep 17 00:00:00 2001 +From: Milan Broz +Date: Fri, 29 Jun 2012 22:08:09 +0200 +Subject: [PATCH] crypto: testmgr - allow aesni-intel and ghash_clmulni-intel + in fips mode + +Patch 863b557a88f8c033f7419fabafef4712a5055f85 added NULL entries +for intel accelerated drivers but did not marked these fips allowed. +This cause panic if running tests with fips=1. + +For ghash, fips_allowed flag was added in patch +18c0ebd2d8194cce4b3f67e2903fa01bea892cbc. + +Without patch, "modprobe tcrypt" fails with + alg: skcipher: Failed to load transform for cbc-aes-aesni: -2 + cbc-aes-aesni: cbc(aes) alg self test failed in fips mode! + (panic) + +Also add missing cryptd(__driver-cbc-aes-aesni) and +cryptd(__driver-gcm-aes-aesni) test to complement +null tests above, otherwise system complains with + alg: No test for __cbc-aes-aesni (cryptd(__driver-cbc-aes-aesni)) + alg: No test for __gcm-aes-aesni (cryptd(__driver-gcm-aes-aesni)) + +Signed-off-by: Milan Broz +Signed-off-by: Paul Wouters +Signed-off-by: Herbert Xu +--- + crypto/testmgr.c | 38 ++++++++++++++++++++++++++++++++++++++ + 1 files changed, 38 insertions(+), 0 deletions(-) + +diff --git a/crypto/testmgr.c b/crypto/testmgr.c +index 36748a5..4308a11 100644 +--- a/crypto/testmgr.c ++++ b/crypto/testmgr.c +@@ -1581,6 +1581,7 @@ static const struct alg_test_desc alg_test_descs[] = { + }, { + .alg = "__driver-cbc-aes-aesni", + .test = alg_test_null, ++ .fips_allowed = 1, + .suite = { + .cipher = { + .enc = { +@@ -1641,6 +1642,7 @@ static const struct alg_test_desc alg_test_descs[] = { + }, { + .alg = "__driver-ecb-aes-aesni", + .test = alg_test_null, ++ .fips_allowed = 1, + .suite = { + .cipher = { + .enc = { +@@ -1701,6 +1703,7 @@ static const struct alg_test_desc alg_test_descs[] = { + }, { + .alg = "__ghash-pclmulqdqni", + .test = alg_test_null, ++ .fips_allowed = 1, + .suite = { + .hash = { + .vecs = NULL, +@@ -1866,8 +1869,25 @@ static const struct alg_test_desc alg_test_descs[] = { + } + } + }, { ++ .alg = "cryptd(__driver-cbc-aes-aesni)", ++ .test = alg_test_null, ++ .fips_allowed = 1, ++ .suite = { ++ .cipher = { ++ .enc = { ++ .vecs = NULL, ++ .count = 0 ++ }, ++ .dec = { ++ .vecs = NULL, ++ .count = 0 ++ } ++ } ++ } ++ }, { + .alg = "cryptd(__driver-ecb-aes-aesni)", + .test = alg_test_null, ++ .fips_allowed = 1, + .suite = { + .cipher = { + .enc = { +@@ -1926,8 +1946,25 @@ static const struct alg_test_desc alg_test_descs[] = { + } + } + }, { ++ .alg = "cryptd(__driver-gcm-aes-aesni)", ++ .test = alg_test_null, ++ .fips_allowed = 1, ++ .suite = { ++ .cipher = { ++ .enc = { ++ .vecs = NULL, ++ .count = 0 ++ }, ++ .dec = { ++ .vecs = NULL, ++ .count = 0 ++ } ++ } ++ } ++ }, { + .alg = "cryptd(__ghash-pclmulqdqni)", + .test = alg_test_null, ++ .fips_allowed = 1, + .suite = { + .hash = { + .vecs = NULL, +@@ -2043,6 +2080,7 @@ static const struct alg_test_desc alg_test_descs[] = { + }, { + .alg = "ecb(__aes-aesni)", + .test = alg_test_null, ++ .fips_allowed = 1, + .suite = { + .cipher = { + .enc = { +-- +1.7.6.5 + diff --git a/kernel.spec b/kernel.spec index bb8e2f6e5..e9b58e363 100644 --- a/kernel.spec +++ b/kernel.spec @@ -813,6 +813,10 @@ Patch22050: ACPI-APEI-Avoid-too-much-error-reporting.patch #rhbz 824641 Patch22051: xen-blkback-Copy-id-field-when-doing-BLKIF_DISCARD.patch +#Fix FIPS for aesni hardare +Patch22055: crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch +Patch22056: crypto-aesni-intel-fix-wrong-kfree-pointer.patch + # END OF PATCH DEFINITIONS %endif @@ -1512,6 +1516,10 @@ ApplyPatch ACPI-APEI-Avoid-too-much-error-reporting.patch #rhbz 824641 ApplyPatch xen-blkback-Copy-id-field-when-doing-BLKIF_DISCARD.patch +#Fix FIPS for aesni hardare +ApplyPatch crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch +ApplyPatch crypto-aesni-intel-fix-wrong-kfree-pointer.patch + # END OF PATCH APPLICATIONS %endif @@ -2250,6 +2258,9 @@ fi # and build. %changelog +* Wed Jul 11 2012 Justin M. Forbes +- Fix FIPS for aesni hardware (rhbz 839239) + * Tue Jul 10 2012 Josh Boyer - Add patch to fix xen dom0 crash when using BLKDISCARD (rhbz 824641) From b24ad922a559331a5c4e3f39d5e578edbb3a9e40 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 12 Jul 2012 16:49:16 -0400 Subject: [PATCH 412/487] Add patch to fix ACPICA null pointer exception regression (rhbz 834318) --- ...in-return-package-object-repair-code.patch | 44 +++++++++++++++++++ kernel.spec | 11 ++++- 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 ACPICA-Fix-possible-fault-in-return-package-object-repair-code.patch diff --git a/ACPICA-Fix-possible-fault-in-return-package-object-repair-code.patch b/ACPICA-Fix-possible-fault-in-return-package-object-repair-code.patch new file mode 100644 index 000000000..c8956b810 --- /dev/null +++ b/ACPICA-Fix-possible-fault-in-return-package-object-repair-code.patch @@ -0,0 +1,44 @@ +From: Bob Moore + +Fixes a problem that can occur when a lone package object is +wrapped with an outer package object in order to conform to +the ACPI specification. Can affect these predefined names: +_ALR,_MLS,_PSS,_TRT,_TSS,_PRT,_HPX,_DLM,_CSD,_PSD,_TSD + +https://bugzilla.kernel.org/show_bug.cgi?id=44171 + +Reported-by: Vlastimil Babka +Signed-off-by: Bob Moore +Signed-off-by: Lin Ming +--- + +Len, + +This is an important bug fix. +Could you merge it? + + drivers/acpi/acpica/nspredef.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c +index 23ce096..fe66260 100644 +--- a/drivers/acpi/acpica/nspredef.c ++++ b/drivers/acpi/acpica/nspredef.c +@@ -638,7 +638,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data, + /* Create the new outer package and populate it */ + + status = +- acpi_ns_wrap_with_package(data, *elements, ++ acpi_ns_wrap_with_package(data, return_object, + return_object_ptr); + if (ACPI_FAILURE(status)) { + return (status); +-- +1.7.2.5 + + + +-- +To unsubscribe from this list: send the line "unsubscribe linux-acpi" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index e9b58e363..70988bb30 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 5 +%global baserelease 6 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -817,6 +817,9 @@ Patch22051: xen-blkback-Copy-id-field-when-doing-BLKIF_DISCARD.patch Patch22055: crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch Patch22056: crypto-aesni-intel-fix-wrong-kfree-pointer.patch +#rhbz 834318 +Patch22057: ACPICA-Fix-possible-fault-in-return-package-object-repair-code.patch + # END OF PATCH DEFINITIONS %endif @@ -1520,6 +1523,9 @@ ApplyPatch xen-blkback-Copy-id-field-when-doing-BLKIF_DISCARD.patch ApplyPatch crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch ApplyPatch crypto-aesni-intel-fix-wrong-kfree-pointer.patch +#rhbz 834318 +ApplyPatch ACPICA-Fix-possible-fault-in-return-package-object-repair-code.patch + # END OF PATCH APPLICATIONS %endif @@ -2258,6 +2264,9 @@ fi # and build. %changelog +* Thu Jul 12 2012 Josh Boyer +- Add patch to fix ACPICA null pointer exception regression (rhbz 834318) + * Wed Jul 11 2012 Justin M. Forbes - Fix FIPS for aesni hardware (rhbz 839239) From 28a83dc6984518fbcae5b9f4190e9dc30bad88e7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 16 Jul 2012 14:50:33 -0400 Subject: [PATCH 413/487] Linux v3.4.5 --- ...-APEI-Avoid-too-much-error-reporting.patch | 121 ------- ...cklight-control-if-_DOS-doesnt-exist.patch | 34 -- ...-per-net-operations-from-svc_destroy.patch | 327 ------------------ SUNRPC-new-svc_bind-routine-introduced.patch | 249 ------------- USB-qmi_wwan-Add-ZTE-Vodafone-K3520-Z.patch | 54 --- ...-Make-forced-int-4-whitelist-generic.patch | 47 --- ...caused-by-returning-a-descriptor-we-.patch | 66 ---- ...configure-bssid-on-ASSOC-IBSS-change.patch | 44 --- ...fix-parsing-of-password-mount-option.patch | 86 ----- ...n-using-nv_two_heads-is-not-a-good-i.patch | 40 --- ...ipher-suites-to-wiphy-initialization.patch | 155 --------- kernel.spec | 112 +----- macvtap-zerocopy-validate-vector-length.patch | 25 -- ...ynchronize-rss-counters-at-exit-exec.patch | 125 ------- ...k-vs-pmd_populate-SMP-race-condition.patch | 272 --------------- net-qmi_wwan-fix-Gobi-device-probing.patch | 194 ----------- ...function-called-from-invalid-context.patch | 49 --- sources | 2 +- ...ly-short-DMA-frag-workaround-to-5906.patch | 32 -- ...ead-in-pmd_read_atomic-for-32bit-PAE.patch | 228 ------------ usb-storage-try-read_capacity-10-first.patch | 130 ------- ...py-id-field-when-doing-BLKIF_DISCARD.patch | 54 --- 22 files changed, 6 insertions(+), 2440 deletions(-) delete mode 100644 ACPI-APEI-Avoid-too-much-error-reporting.patch delete mode 100644 ACPI-video-Still-use-ACPI-backlight-control-if-_DOS-doesnt-exist.patch delete mode 100644 SUNRPC-move-per-net-operations-from-svc_destroy.patch delete mode 100644 SUNRPC-new-svc_bind-routine-introduced.patch delete mode 100644 USB-qmi_wwan-Add-ZTE-Vodafone-K3520-Z.patch delete mode 100644 USB-qmi_wwan-Make-forced-int-4-whitelist-generic.patch delete mode 100644 ath9k-fix-panic-caused-by-returning-a-descriptor-we-.patch delete mode 100644 ath9k_htc-configure-bssid-on-ASSOC-IBSS-change.patch delete mode 100644 cifs-fix-parsing-of-password-mount-option.patch delete mode 100644 drm-nouveau-fbcon-using-nv_two_heads-is-not-a-good-i.patch delete mode 100644 ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch delete mode 100644 macvtap-zerocopy-validate-vector-length.patch delete mode 100644 mm-correctly-synchronize-rss-counters-at-exit-exec.patch delete mode 100644 mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch delete mode 100644 net-qmi_wwan-fix-Gobi-device-probing.patch delete mode 100644 rtl818x-fix-sleeping-function-called-from-invalid-context.patch delete mode 100644 tg3-Apply-short-DMA-frag-workaround-to-5906.patch delete mode 100644 thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch delete mode 100644 usb-storage-try-read_capacity-10-first.patch delete mode 100644 xen-blkback-Copy-id-field-when-doing-BLKIF_DISCARD.patch diff --git a/ACPI-APEI-Avoid-too-much-error-reporting.patch b/ACPI-APEI-Avoid-too-much-error-reporting.patch deleted file mode 100644 index fe6e697b4..000000000 --- a/ACPI-APEI-Avoid-too-much-error-reporting.patch +++ /dev/null @@ -1,121 +0,0 @@ -commit 34ddeb035d704eafdcdb3cbc781894300136c3c4 -Author: Huang Ying -Date: Tue Jun 12 11:20:19 2012 +0800 - - ACPI, APEI, Avoid too much error reporting in runtime - - This patch fixed the following bug. - - https://bugzilla.kernel.org/show_bug.cgi?id=43282 - - This is caused by a firmware bug checking (checking generic address - register provided by firmware) in runtime. The checking should be - done in address mapping time instead of runtime to avoid too much - error reporting in runtime. - - Reported-by: Pawel Sikora - Signed-off-by: Huang Ying - Tested-by: Jean Delvare - Cc: stable@vger.kernel.org - Signed-off-by: Len Brown - -diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c -index 5577762..6686b1e 100644 ---- a/drivers/acpi/apei/apei-base.c -+++ b/drivers/acpi/apei/apei-base.c -@@ -243,7 +243,7 @@ static int pre_map_gar_callback(struct apei_exec_context *ctx, - u8 ins = entry->instruction; - - if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER) -- return acpi_os_map_generic_address(&entry->register_region); -+ return apei_map_generic_address(&entry->register_region); - - return 0; - } -@@ -276,7 +276,7 @@ static int post_unmap_gar_callback(struct apei_exec_context *ctx, - u8 ins = entry->instruction; - - if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER) -- acpi_os_unmap_generic_address(&entry->register_region); -+ apei_unmap_generic_address(&entry->register_region); - - return 0; - } -@@ -606,6 +606,19 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr, - return 0; - } - -+int apei_map_generic_address(struct acpi_generic_address *reg) -+{ -+ int rc; -+ u32 access_bit_width; -+ u64 address; -+ -+ rc = apei_check_gar(reg, &address, &access_bit_width); -+ if (rc) -+ return rc; -+ return acpi_os_map_generic_address(reg); -+} -+EXPORT_SYMBOL_GPL(apei_map_generic_address); -+ - /* read GAR in interrupt (including NMI) or process context */ - int apei_read(u64 *val, struct acpi_generic_address *reg) - { -diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h -index cca240a..f220d64 100644 ---- a/drivers/acpi/apei/apei-internal.h -+++ b/drivers/acpi/apei/apei-internal.h -@@ -7,6 +7,8 @@ - #define APEI_INTERNAL_H - - #include -+#include -+#include - - struct apei_exec_context; - -@@ -68,6 +70,13 @@ static inline int apei_exec_run_optional(struct apei_exec_context *ctx, u8 actio - /* IP has been set in instruction function */ - #define APEI_EXEC_SET_IP 1 - -+int apei_map_generic_address(struct acpi_generic_address *reg); -+ -+static inline void apei_unmap_generic_address(struct acpi_generic_address *reg) -+{ -+ acpi_os_unmap_generic_address(reg); -+} -+ - int apei_read(u64 *val, struct acpi_generic_address *reg); - int apei_write(u64 val, struct acpi_generic_address *reg); - -diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c -index 9b3cac0..1599566 100644 ---- a/drivers/acpi/apei/ghes.c -+++ b/drivers/acpi/apei/ghes.c -@@ -301,7 +301,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic) - if (!ghes) - return ERR_PTR(-ENOMEM); - ghes->generic = generic; -- rc = acpi_os_map_generic_address(&generic->error_status_address); -+ rc = apei_map_generic_address(&generic->error_status_address); - if (rc) - goto err_free; - error_block_length = generic->error_block_length; -@@ -321,7 +321,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic) - return ghes; - - err_unmap: -- acpi_os_unmap_generic_address(&generic->error_status_address); -+ apei_unmap_generic_address(&generic->error_status_address); - err_free: - kfree(ghes); - return ERR_PTR(rc); -@@ -330,7 +330,7 @@ err_free: - static void ghes_fini(struct ghes *ghes) - { - kfree(ghes->estatus); -- acpi_os_unmap_generic_address(&ghes->generic->error_status_address); -+ apei_unmap_generic_address(&ghes->generic->error_status_address); - } - - enum { diff --git a/ACPI-video-Still-use-ACPI-backlight-control-if-_DOS-doesnt-exist.patch b/ACPI-video-Still-use-ACPI-backlight-control-if-_DOS-doesnt-exist.patch deleted file mode 100644 index a89711132..000000000 --- a/ACPI-video-Still-use-ACPI-backlight-control-if-_DOS-doesnt-exist.patch +++ /dev/null @@ -1,34 +0,0 @@ - -This is a regression introduced by commit -ea9f8856bd6d4ed45885b06a338f7362cd6c60e5 -https://bugzilla.kernel.org/show_bug.cgi?id=43168 - -Some platforms don't have _DOS control method, but the ACPI -backlight still works. -We should not invoke _DOS for these platforms. - -CC : Igor Murzov -Signed-off-by: Zhang Rui ---- - drivers/acpi/video.c | 2 ++ - 1 file changed, 2 insertions(+) - -Index: rtd3/drivers/acpi/video.c -=================================================================== ---- rtd3.orig/drivers/acpi/video.c -+++ rtd3/drivers/acpi/video.c -@@ -558,6 +558,8 @@ acpi_video_bus_DOS(struct acpi_video_bus - union acpi_object arg0 = { ACPI_TYPE_INTEGER }; - struct acpi_object_list args = { 1, &arg0 }; - -+ if (!video->cap._DOS) -+ return 0; - - if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1) - return -EINVAL; - - --- -To unsubscribe from this list: send the line "unsubscribe linux-acpi" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/SUNRPC-move-per-net-operations-from-svc_destroy.patch b/SUNRPC-move-per-net-operations-from-svc_destroy.patch deleted file mode 100644 index 1895b5bca..000000000 --- a/SUNRPC-move-per-net-operations-from-svc_destroy.patch +++ /dev/null @@ -1,327 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Stanislav Kinsbursky -Newsgroups: gmane.linux.kernel,gmane.linux.nfs,gmane.linux.openvz.devel -Subject: [PATCH 2/2] SUNRPC: move per-net operations from svc_destroy() -Date: Fri, 01 Jun 2012 15:17:50 +0400 -Lines: 281 -Approved: news@gmane.org -Message-ID: <20120601111750.7846.23782.stgit@localhost.localdomain> -References: <20120601111619.7846.95457.stgit@localhost.localdomain> -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset="utf-8" -Content-Transfer-Encoding: 7bit -X-Trace: dough.gmane.org 1338549639 9108 80.91.229.3 (1 Jun 2012 11:20:39 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Fri, 1 Jun 2012 11:20:39 +0000 (UTC) -Cc: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, - devel@openvz.org -To: bfields@fieldses.org, Trond.Myklebust@netapp.com -Original-X-From: linux-kernel-owner@vger.kernel.org Fri Jun 01 13:20:37 2012 -Return-path: -Envelope-to: glk-linux-kernel-3@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1SaPuE-0002JL-ED - for glk-linux-kernel-3@plane.gmane.org; Fri, 01 Jun 2012 13:20:34 +0200 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1759489Ab2FALUJ (ORCPT ); - Fri, 1 Jun 2012 07:20:09 -0400 -Original-Received: from mailhub.sw.ru ([195.214.232.25]:7947 "EHLO relay.sw.ru" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1759474Ab2FALUE (ORCPT ); - Fri, 1 Jun 2012 07:20:04 -0400 -Original-Received: from localhost.localdomain ([10.30.21.131]) - by relay.sw.ru (8.13.4/8.13.4) with ESMTP id q51BJrkd020556; - Fri, 1 Jun 2012 15:19:54 +0400 (MSK) -In-Reply-To: <20120601111619.7846.95457.stgit@localhost.localdomain> -User-Agent: StGit/0.16 -Original-Sender: linux-kernel-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-kernel@vger.kernel.org -Xref: news.gmane.org gmane.linux.kernel:1306567 gmane.linux.nfs:50236 gmane.linux.openvz.devel:1597 -Archived-At: - -This patch was back-ported from 3.5 kernel. - -The idea is to separate service destruction and per-net operations, because -these are two different things and it's mix looks ugly. - -Notes: -1) For NFS server this patch looks ugly (sorry for that). But these place will -be -rewritten soon during NFSd containerization. -2) LockD per-net counter increase int lockd_up() was moved prior to -make_socks() to make lockd_down_net() call safe in case of error. - -Signed-off-by: Stanislav Kinsbursky ---- - fs/lockd/svc.c | 27 +++++++++++++++------------ - fs/nfs/callback.c | 3 +++ - fs/nfsd/nfsctl.c | 12 +++++++++--- - fs/nfsd/nfssvc.c | 14 ++++++++++++++ - net/sunrpc/svc.c | 4 ---- - 5 files changed, 41 insertions(+), 19 deletions(-) - -diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c -index b1d0708..f1b3cce 100644 ---- a/fs/lockd/svc.c -+++ b/fs/lockd/svc.c -@@ -257,7 +257,7 @@ static int lockd_up_net(struct net *net) - struct svc_serv *serv = nlmsvc_rqst->rq_server; - int error; - -- if (ln->nlmsvc_users) -+ if (ln->nlmsvc_users++) - return 0; - - error = svc_rpcb_setup(serv, net); -@@ -272,6 +272,7 @@ static int lockd_up_net(struct net *net) - err_socks: - svc_rpcb_cleanup(serv, net); - err_rpcb: -+ ln->nlmsvc_users--; - return error; - } - -@@ -300,6 +301,7 @@ int lockd_up(void) - struct svc_serv *serv; - int error = 0; - struct net *net = current->nsproxy->net_ns; -+ struct lockd_net *ln = net_generic(net, lockd_net_id); - - mutex_lock(&nlmsvc_mutex); - /* -@@ -331,9 +333,11 @@ int lockd_up(void) - goto destroy_and_out; - } - -+ ln->nlmsvc_users++; -+ - error = make_socks(serv, net); - if (error < 0) -- goto destroy_and_out; -+ goto err_start; - - /* - * Create the kernel thread and wait for it to start. -@@ -345,7 +349,7 @@ int lockd_up(void) - printk(KERN_WARNING - "lockd_up: svc_rqst allocation failed, error=%d\n", - error); -- goto destroy_and_out; -+ goto err_start; - } - - svc_sock_update_bufs(serv); -@@ -359,7 +363,7 @@ int lockd_up(void) - nlmsvc_rqst = NULL; - printk(KERN_WARNING - "lockd_up: kthread_run failed, error=%d\n", error); -- goto destroy_and_out; -+ goto err_start; - } - - /* -@@ -369,14 +373,14 @@ int lockd_up(void) - destroy_and_out: - svc_destroy(serv); - out: -- if (!error) { -- struct lockd_net *ln = net_generic(net, lockd_net_id); -- -- ln->nlmsvc_users++; -+ if (!error) - nlmsvc_users++; -- } - mutex_unlock(&nlmsvc_mutex); - return error; -+ -+err_start: -+ lockd_down_net(net); -+ goto destroy_and_out; - } - EXPORT_SYMBOL_GPL(lockd_up); - -@@ -387,11 +391,10 @@ void - lockd_down(void) - { - mutex_lock(&nlmsvc_mutex); -+ lockd_down_net(current->nsproxy->net_ns); - if (nlmsvc_users) { -- if (--nlmsvc_users) { -- lockd_down_net(current->nsproxy->net_ns); -+ if (--nlmsvc_users) - goto out; -- } - } else { - printk(KERN_ERR "lockd_down: no users! task=%p\n", - nlmsvc_task); -diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c -index 0563237..38a44c6 100644 ---- a/fs/nfs/callback.c -+++ b/fs/nfs/callback.c -@@ -313,6 +313,8 @@ out_err: - dprintk("NFS: Couldn't create callback socket or server thread; " - "err = %d\n", ret); - cb_info->users--; -+ if (serv) -+ svc_shutdown_net(serv, net); - goto out; - } - -@@ -327,6 +329,7 @@ void nfs_callback_down(int minorversion) - cb_info->users--; - if (cb_info->users == 0 && cb_info->task != NULL) { - kthread_stop(cb_info->task); -+ svc_shutdown_net(cb_info->serv, &init_net); - svc_exit_thread(cb_info->rqst); - cb_info->serv = NULL; - cb_info->rqst = NULL; -diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c -index 2c53be6..3ab12eb 100644 ---- a/fs/nfsd/nfsctl.c -+++ b/fs/nfsd/nfsctl.c -@@ -651,6 +651,7 @@ static ssize_t __write_ports_addfd(char *buf) - { - char *mesg = buf; - int fd, err; -+ struct net *net = &init_net; - - err = get_int(&mesg, &fd); - if (err != 0 || fd < 0) -@@ -662,6 +663,8 @@ static ssize_t __write_ports_addfd(char *buf) - - err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); - if (err < 0) { -+ if (nfsd_serv->sv_nrthreads == 1) -+ svc_shutdown_net(nfsd_serv, net); - svc_destroy(nfsd_serv); - return err; - } -@@ -699,6 +702,7 @@ static ssize_t __write_ports_addxprt(char *buf) - char transport[16]; - struct svc_xprt *xprt; - int port, err; -+ struct net *net = &init_net; - - if (sscanf(buf, "%15s %4u", transport, &port) != 2) - return -EINVAL; -@@ -710,12 +714,12 @@ static ssize_t __write_ports_addxprt(char *buf) - if (err != 0) - return err; - -- err = svc_create_xprt(nfsd_serv, transport, &init_net, -+ err = svc_create_xprt(nfsd_serv, transport, net, - PF_INET, port, SVC_SOCK_ANONYMOUS); - if (err < 0) - goto out_err; - -- err = svc_create_xprt(nfsd_serv, transport, &init_net, -+ err = svc_create_xprt(nfsd_serv, transport, net, - PF_INET6, port, SVC_SOCK_ANONYMOUS); - if (err < 0 && err != -EAFNOSUPPORT) - goto out_close; -@@ -724,12 +728,14 @@ static ssize_t __write_ports_addxprt(char *buf) - nfsd_serv->sv_nrthreads--; - return 0; - out_close: -- xprt = svc_find_xprt(nfsd_serv, transport, &init_net, PF_INET, port); -+ xprt = svc_find_xprt(nfsd_serv, transport, net, PF_INET, port); - if (xprt != NULL) { - svc_close_xprt(xprt); - svc_xprt_put(xprt); - } - out_err: -+ if (nfsd_serv->sv_nrthreads == 1) -+ svc_shutdown_net(nfsd_serv, net); - svc_destroy(nfsd_serv); - return err; - } -diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c -index a6461f3..da50e1c 100644 ---- a/fs/nfsd/nfssvc.c -+++ b/fs/nfsd/nfssvc.c -@@ -382,6 +382,7 @@ int nfsd_set_nrthreads(int n, int *nthreads) - int i = 0; - int tot = 0; - int err = 0; -+ struct net *net = &init_net; - - WARN_ON(!mutex_is_locked(&nfsd_mutex)); - -@@ -426,6 +427,9 @@ int nfsd_set_nrthreads(int n, int *nthreads) - if (err) - break; - } -+ -+ if (nfsd_serv->sv_nrthreads == 1) -+ svc_shutdown_net(nfsd_serv, net); - svc_destroy(nfsd_serv); - - return err; -@@ -441,6 +445,7 @@ nfsd_svc(unsigned short port, int nrservs) - { - int error; - bool nfsd_up_before; -+ struct net *net = &init_net; - - mutex_lock(&nfsd_mutex); - dprintk("nfsd: creating service\n"); -@@ -473,6 +478,8 @@ out_shutdown: - if (error < 0 && !nfsd_up_before) - nfsd_shutdown(); - out_destroy: -+ if (nfsd_serv->sv_nrthreads == 1) -+ svc_shutdown_net(nfsd_serv, net); - svc_destroy(nfsd_serv); /* Release server */ - out: - mutex_unlock(&nfsd_mutex); -@@ -556,6 +563,9 @@ nfsd(void *vrqstp) - nfsdstats.th_cnt --; - - out: -+ if (rqstp->rq_server->sv_nrthreads == 1) -+ svc_shutdown_net(rqstp->rq_server, &init_net); -+ - /* Release the thread */ - svc_exit_thread(rqstp); - -@@ -668,8 +678,12 @@ int nfsd_pool_stats_open(struct inode *inode, struct file *file) - int nfsd_pool_stats_release(struct inode *inode, struct file *file) - { - int ret = seq_release(inode, file); -+ struct net *net = &init_net; -+ - mutex_lock(&nfsd_mutex); - /* this function really, really should have been called svc_put() */ -+ if (nfsd_serv->sv_nrthreads == 1) -+ svc_shutdown_net(nfsd_serv, net); - svc_destroy(nfsd_serv); - mutex_unlock(&nfsd_mutex); - return ret; -diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c -index e6d542c..b7210f5 100644 ---- a/net/sunrpc/svc.c -+++ b/net/sunrpc/svc.c -@@ -537,8 +537,6 @@ EXPORT_SYMBOL_GPL(svc_shutdown_net); - void - svc_destroy(struct svc_serv *serv) - { -- struct net *net = current->nsproxy->net_ns; -- - dprintk("svc: svc_destroy(%s, %d)\n", - serv->sv_program->pg_name, - serv->sv_nrthreads); -@@ -553,8 +551,6 @@ svc_destroy(struct svc_serv *serv) - - del_timer_sync(&serv->sv_temptimer); - -- svc_shutdown_net(serv, net); -- - /* - * The last user is gone and thus all sockets have to be destroyed to - * the point. Check this. - diff --git a/SUNRPC-new-svc_bind-routine-introduced.patch b/SUNRPC-new-svc_bind-routine-introduced.patch deleted file mode 100644 index 58127cca0..000000000 --- a/SUNRPC-new-svc_bind-routine-introduced.patch +++ /dev/null @@ -1,249 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Stanislav Kinsbursky -Newsgroups: gmane.linux.nfs,gmane.linux.kernel,gmane.linux.openvz.devel -Subject: [PATCH 1/2] SUNRPC: new svc_bind() routine introduced -Date: Fri, 01 Jun 2012 15:17:42 +0400 -Lines: 203 -Approved: news@gmane.org -Message-ID: <20120601111742.7846.99872.stgit@localhost.localdomain> -References: <20120601111619.7846.95457.stgit@localhost.localdomain> -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset="utf-8" -Content-Transfer-Encoding: 7bit -X-Trace: dough.gmane.org 1338549604 8815 80.91.229.3 (1 Jun 2012 11:20:04 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Fri, 1 Jun 2012 11:20:04 +0000 (UTC) -Cc: linux-nfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, - devel-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org -To: bfields-uC3wQj2KruNg9hUCZPvPmw@public.gmane.org, Trond.Myklebust-HgOvQuBEEgTQT0dZR+AlfA@public.gmane.org -Original-X-From: linux-nfs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Fri Jun 01 13:20:02 2012 -Return-path: -Envelope-to: glN-linux-nfs-wOFGN7rlS/M9smdsby/KFg@public.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1SaPtg-0001Xs-F8 - for glN-linux-nfs-wOFGN7rlS/M9smdsby/KFg@public.gmane.org; Fri, 01 Jun 2012 13:20:00 +0200 -Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand - id S1759450Ab2FALT7 (ORCPT ); - Fri, 1 Jun 2012 07:19:59 -0400 -Original-Received: from mailhub.sw.ru ([195.214.232.25]:20534 "EHLO relay.sw.ru" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1759448Ab2FALT6 (ORCPT ); - Fri, 1 Jun 2012 07:19:58 -0400 -Original-Received: from localhost.localdomain ([10.30.21.131]) - by relay.sw.ru (8.13.4/8.13.4) with ESMTP id q51BJjDD010948; - Fri, 1 Jun 2012 15:19:46 +0400 (MSK) -In-Reply-To: <20120601111619.7846.95457.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org> -User-Agent: StGit/0.16 -Original-Sender: linux-nfs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-nfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Xref: news.gmane.org gmane.linux.nfs:50234 gmane.linux.kernel:1306565 gmane.linux.openvz.devel:1595 -Archived-At: - -This patch was back-ported from 3.5 kernel. - -New routine is responsible for service registration in specified network -context. -The idea is to separate service creation from per-net operations. -Since registering service with svc_bind() can fail, then service will be -destroyed and during destruction it will try to unregister itself from -rpcbind. In this case unregister have to be skipped. - -Signed-off-by: Stanislav Kinsbursky ---- - fs/lockd/svc.c | 6 ++++++ - fs/nfs/callback.c | 13 ++++++++++--- - fs/nfsd/nfssvc.c | 9 +++++++++ - include/linux/sunrpc/svc.h | 1 + - net/sunrpc/rpcb_clnt.c | 12 +++++++----- - net/sunrpc/svc.c | 19 ++++++++++--------- - 6 files changed, 43 insertions(+), 17 deletions(-) - -diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c -index f49b9af..b1d0708 100644 ---- a/fs/lockd/svc.c -+++ b/fs/lockd/svc.c -@@ -325,6 +325,12 @@ int lockd_up(void) - goto out; - } - -+ error = svc_bind(serv, net); -+ if (error < 0) { -+ printk(KERN_WARNING "lockd_up: bind service failed\n"); -+ goto destroy_and_out; -+ } -+ - error = make_socks(serv, net); - if (error < 0) - goto destroy_and_out; -diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c -index eb95f50..0563237 100644 ---- a/fs/nfs/callback.c -+++ b/fs/nfs/callback.c -@@ -106,7 +106,7 @@ nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) - { - int ret; - -- ret = svc_create_xprt(serv, "tcp", xprt->xprt_net, PF_INET, -+ ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET, - nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); - if (ret <= 0) - goto out_err; -@@ -114,7 +114,7 @@ nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) - dprintk("NFS: Callback listener port = %u (af %u)\n", - nfs_callback_tcpport, PF_INET); - -- ret = svc_create_xprt(serv, "tcp", xprt->xprt_net, PF_INET6, -+ ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET6, - nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); - if (ret > 0) { - nfs_callback_tcpport6 = ret; -@@ -183,7 +183,7 @@ nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) - * fore channel connection. - * Returns the input port (0) and sets the svc_serv bc_xprt on success - */ -- ret = svc_create_xprt(serv, "tcp-bc", xprt->xprt_net, PF_INET, 0, -+ ret = svc_create_xprt(serv, "tcp-bc", &init_net, PF_INET, 0, - SVC_SOCK_ANONYMOUS); - if (ret < 0) { - rqstp = ERR_PTR(ret); -@@ -253,6 +253,7 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) - char svc_name[12]; - int ret = 0; - int minorversion_setup; -+ struct net *net = &init_net; - - mutex_lock(&nfs_callback_mutex); - if (cb_info->users++ || cb_info->task != NULL) { -@@ -265,6 +266,12 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) - goto out_err; - } - -+ ret = svc_bind(serv, net); -+ if (ret < 0) { -+ printk(KERN_WARNING "NFS: bind callback service failed\n"); -+ goto out_err; -+ } -+ - minorversion_setup = nfs_minorversion_callback_svc_setup(minorversion, - serv, xprt, &rqstp, &callback_svc); - if (!minorversion_setup) { -diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c -index 28dfad3..a6461f3 100644 ---- a/fs/nfsd/nfssvc.c -+++ b/fs/nfsd/nfssvc.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -330,6 +331,8 @@ static int nfsd_get_default_max_blksize(void) - - int nfsd_create_serv(void) - { -+ int error; -+ - WARN_ON(!mutex_is_locked(&nfsd_mutex)); - if (nfsd_serv) { - svc_get(nfsd_serv); -@@ -343,6 +346,12 @@ int nfsd_create_serv(void) - if (nfsd_serv == NULL) - return -ENOMEM; - -+ error = svc_bind(nfsd_serv, current->nsproxy->net_ns); -+ if (error < 0) { -+ svc_destroy(nfsd_serv); -+ return error; -+ } -+ - set_max_drc(); - do_gettimeofday(&nfssvc_boot); /* record boot time */ - return 0; -diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h -index 51b29ac..2b43e02 100644 ---- a/include/linux/sunrpc/svc.h -+++ b/include/linux/sunrpc/svc.h -@@ -416,6 +416,7 @@ struct svc_procedure { - */ - int svc_rpcb_setup(struct svc_serv *serv, struct net *net); - void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net); -+int svc_bind(struct svc_serv *serv, struct net *net); - struct svc_serv *svc_create(struct svc_program *, unsigned int, - void (*shutdown)(struct svc_serv *, struct net *net)); - struct svc_rqst *svc_prepare_thread(struct svc_serv *serv, -diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c -index 78ac39f..4c38b33 100644 ---- a/net/sunrpc/rpcb_clnt.c -+++ b/net/sunrpc/rpcb_clnt.c -@@ -180,14 +180,16 @@ void rpcb_put_local(struct net *net) - struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); - struct rpc_clnt *clnt = sn->rpcb_local_clnt; - struct rpc_clnt *clnt4 = sn->rpcb_local_clnt4; -- int shutdown; -+ int shutdown = 0; - - spin_lock(&sn->rpcb_clnt_lock); -- if (--sn->rpcb_users == 0) { -- sn->rpcb_local_clnt = NULL; -- sn->rpcb_local_clnt4 = NULL; -+ if (sn->rpcb_users) { -+ if (--sn->rpcb_users == 0) { -+ sn->rpcb_local_clnt = NULL; -+ sn->rpcb_local_clnt4 = NULL; -+ } -+ shutdown = !sn->rpcb_users; - } -- shutdown = !sn->rpcb_users; - spin_unlock(&sn->rpcb_clnt_lock); - - if (shutdown) { -diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c -index 4153846..e6d542c 100644 ---- a/net/sunrpc/svc.c -+++ b/net/sunrpc/svc.c -@@ -407,6 +407,14 @@ static int svc_uses_rpcbind(struct svc_serv *serv) - return 0; - } - -+int svc_bind(struct svc_serv *serv, struct net *net) -+{ -+ if (!svc_uses_rpcbind(serv)) -+ return 0; -+ return svc_rpcb_setup(serv, net); -+} -+EXPORT_SYMBOL_GPL(svc_bind); -+ - /* - * Create an RPC service - */ -@@ -471,15 +479,8 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, - spin_lock_init(&pool->sp_lock); - } - -- if (svc_uses_rpcbind(serv)) { -- if (svc_rpcb_setup(serv, current->nsproxy->net_ns) < 0) { -- kfree(serv->sv_pools); -- kfree(serv); -- return NULL; -- } -- if (!serv->sv_shutdown) -- serv->sv_shutdown = svc_rpcb_cleanup; -- } -+ if (svc_uses_rpcbind(serv) && (!serv->sv_shutdown)) -+ serv->sv_shutdown = svc_rpcb_cleanup; - - return serv; - } - --- -To unsubscribe from this list: send the line "unsubscribe linux-nfs" in -the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - diff --git a/USB-qmi_wwan-Add-ZTE-Vodafone-K3520-Z.patch b/USB-qmi_wwan-Add-ZTE-Vodafone-K3520-Z.patch deleted file mode 100644 index 9ce05cc72..000000000 --- a/USB-qmi_wwan-Add-ZTE-Vodafone-K3520-Z.patch +++ /dev/null @@ -1,54 +0,0 @@ -From f7142e6c226076fd40c2ebaad9fb0c9a631b790e Mon Sep 17 00:00:00 2001 -From: "Andrew Bird (Sphere Systems)" -Date: Sat, 19 May 2012 22:28:38 +0000 -Subject: [PATCH] USB: qmi_wwan: Add ZTE (Vodafone) K3520-Z -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Andrew Bird -Acked-by: Bjørn Mork -Signed-off-by: David S. Miller ---- - drivers/net/usb/qmi_wwan.c | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - -diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c -index b381368..63cfd0b 100644 ---- a/drivers/net/usb/qmi_wwan.c -+++ b/drivers/net/usb/qmi_wwan.c -@@ -356,6 +356,15 @@ static const struct driver_info qmi_wwan_gobi = { - }; - - /* ZTE suck at making USB descriptors */ -+static const struct driver_info qmi_wwan_force_int1 = { -+ .description = "Qualcomm WWAN/QMI device", -+ .flags = FLAG_WWAN, -+ .bind = qmi_wwan_bind_shared, -+ .unbind = qmi_wwan_unbind_shared, -+ .manage_power = qmi_wwan_manage_power, -+ .data = BIT(1), /* interface whitelist bitmap */ -+}; -+ - static const struct driver_info qmi_wwan_force_int4 = { - .description = "Qualcomm WWAN/QMI device", - .flags = FLAG_WWAN, -@@ -438,6 +447,15 @@ static const struct usb_device_id products[] = { - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_force_int4, - }, -+ { /* ZTE (Vodafone) K3520-Z */ -+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -+ .idVendor = 0x19d2, -+ .idProduct = 0x0055, -+ .bInterfaceClass = 0xff, -+ .bInterfaceSubClass = 0xff, -+ .bInterfaceProtocol = 0xff, -+ .driver_info = (unsigned long)&qmi_wwan_force_int1, -+ }, - { /* ZTE (Vodafone) K3565-Z */ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19d2, --- -1.7.10.2 - diff --git a/USB-qmi_wwan-Make-forced-int-4-whitelist-generic.patch b/USB-qmi_wwan-Make-forced-int-4-whitelist-generic.patch deleted file mode 100644 index 87e84a0bd..000000000 --- a/USB-qmi_wwan-Make-forced-int-4-whitelist-generic.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 00001880cd8faaa349fe2ebb158f7e0cd8026048 Mon Sep 17 00:00:00 2001 -From: "Andrew Bird (Sphere Systems)" -Date: Sat, 19 May 2012 22:28:36 +0000 -Subject: [PATCH] USB: qmi_wwan: Make forced int 4 whitelist generic -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Change the forced interface 4 whitelist to use the generic shared -binder instead of the Gobi specific one. Certain ZTE devices -(K3520-Z & K3765-Z) don't work with the Gobi version, but function -quite happily with the generic. This has been tested with the following -devices: -K3520-Z -K3565-Z -K3765-Z -K4505-Z -It hasn't been tested with the ZTE MF820D, which is the only other -device that uses this whitelist at present. Although Bjorn doesn't -expect any problems, any testing with that device would be appreciated. - -Signed-off-by: Andrew Bird -Acked-by: Bjørn Mork -Signed-off-by: David S. Miller ---- - drivers/net/usb/qmi_wwan.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c -index fc1ebef..a0fee0d 100644 ---- a/drivers/net/usb/qmi_wwan.c -+++ b/drivers/net/usb/qmi_wwan.c -@@ -357,9 +357,9 @@ static const struct driver_info qmi_wwan_gobi = { - - /* ZTE suck at making USB descriptors */ - static const struct driver_info qmi_wwan_force_int4 = { -- .description = "Qualcomm Gobi wwan/QMI device", -+ .description = "Qualcomm WWAN/QMI device", - .flags = FLAG_WWAN, -- .bind = qmi_wwan_bind_gobi, -+ .bind = qmi_wwan_bind_shared, - .unbind = qmi_wwan_unbind_shared, - .manage_power = qmi_wwan_manage_power, - .data = BIT(4), /* interface whitelist bitmap */ --- -1.7.10.2 - diff --git a/ath9k-fix-panic-caused-by-returning-a-descriptor-we-.patch b/ath9k-fix-panic-caused-by-returning-a-descriptor-we-.patch deleted file mode 100644 index aec1f4245..000000000 --- a/ath9k-fix-panic-caused-by-returning-a-descriptor-we-.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 6bb51c70cabaadddc54a6454844eceba91a56083 Mon Sep 17 00:00:00 2001 -From: Tom Hughes -Date: Wed, 27 Jun 2012 18:21:15 +0100 -Subject: [PATCH] ath9k: fix panic caused by returning a descriptor we have - queued for reuse - -Commit 3a2923e83c introduced a bug when a corrupt descriptor -is encountered - although the following descriptor is discarded -and returned to the queue for reuse the associated frame is -also returned for processing. This leads to a panic: - -BUG: unable to handle kernel NULL pointer dereference at 000000000000003a -IP: [] ath_rx_tasklet+0x165/0x1b00 [ath9k] -Call Trace: - -[] ? map_single+0x60/0x60 -[] ? ath9k_ioread32+0x34/0x90 [ath9k] -[] athk9k_tasklet+0xdc/0x160 [ath9k] -[] tasklet_action+0x63/0xd0 -[] __do_softirq+0xc0/0x1e0 -[] ? native_sched_clock+0x13/0x80 -[] call_softirq+0x1c/0x30 -[] do_softirq+0x75/0xb0 -[] irq_exit+0xb5/0xc0 -[] do_IRQ+0x63/0xe0 -[] common_interrupt+0x6a/0x6a - -[] ? intel_idle+0xea/0x150 -[] ? intel_idle+0xcb/0x150 -[] cpuidle_enter+0x19/0x20 -[] cpuidle_idle_call+0xa9/0x240 -[] cpu_idle+0xaf/0x120 -[] rest_init+0x72/0x74 -[] start_kernel+0x3b7/0x3c4 -[] ? repair_env_string+0x5e/0x5e -[] x86_64_start_reservations+0x131/0x135 -[] x86_64_start_kernel+0x100/0x10f - -Making sure bf is cleared to NULL in this case restores the -old behaviour. - -Signed-off-by: Tom Hughes -Signed-off-by: John W. Linville ---- - drivers/net/wireless/ath/ath9k/recv.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c -index 599667a..0735aeb 100644 ---- a/drivers/net/wireless/ath/ath9k/recv.c -+++ b/drivers/net/wireless/ath/ath9k/recv.c -@@ -695,9 +695,9 @@ static bool ath_edma_get_buffers(struct ath_softc *sc, - __skb_unlink(skb, &rx_edma->rx_fifo); - list_add_tail(&bf->list, &sc->rx.rxbuf); - ath_rx_edma_buf_link(sc, qtype); -- } else { -- bf = NULL; - } -+ -+ bf = NULL; - } - - *dest = bf; --- -1.7.10.2 - diff --git a/ath9k_htc-configure-bssid-on-ASSOC-IBSS-change.patch b/ath9k_htc-configure-bssid-on-ASSOC-IBSS-change.patch deleted file mode 100644 index 51dc6e211..000000000 --- a/ath9k_htc-configure-bssid-on-ASSOC-IBSS-change.patch +++ /dev/null @@ -1,44 +0,0 @@ -commit 931cb03afed7b541392295f3afc4638da32f08a0 -Author: Rajkumar Manoharan -Date: Wed Jun 20 16:29:20 2012 +0530 - - ath9k_htc: configure bssid on ASSOC/IBSS change - - After the change "mac80211: remove spurious BSSID change flag", - BSS_CHANGED_BSSID will not be passed on association or IBSS - status changes. So it could be better to program bssid on ASSOC - or IBSS change notification. Not doing so, is affecting the - packet transmission. - - Cc: stable@vger.kernel.org [3.4+] - Reported-by: Michael Leun - Signed-off-by: Rajkumar Manoharan - Signed-off-by: John W. Linville - -diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c -index 2b8f61c..abbd6ef 100644 ---- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c -+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c -@@ -1496,6 +1496,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, - priv->num_sta_assoc_vif++ : priv->num_sta_assoc_vif--; - - if (priv->ah->opmode == NL80211_IFTYPE_STATION) { -+ ath9k_htc_choose_set_bssid(priv); - if (bss_conf->assoc && (priv->num_sta_assoc_vif == 1)) - ath9k_htc_start_ani(priv); - else if (priv->num_sta_assoc_vif == 0) -@@ -1503,13 +1504,11 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, - } - } - -- if (changed & BSS_CHANGED_BSSID) { -+ if (changed & BSS_CHANGED_IBSS) { - if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) { - common->curaid = bss_conf->aid; - memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); - ath9k_htc_set_bssid(priv); -- } else if (priv->ah->opmode == NL80211_IFTYPE_STATION) { -- ath9k_htc_choose_set_bssid(priv); - } - } - diff --git a/cifs-fix-parsing-of-password-mount-option.patch b/cifs-fix-parsing-of-password-mount-option.patch deleted file mode 100644 index 9805c6bf9..000000000 --- a/cifs-fix-parsing-of-password-mount-option.patch +++ /dev/null @@ -1,86 +0,0 @@ -From e73f843a3235a19de38359c91586e9eadef12238 Mon Sep 17 00:00:00 2001 -From: Suresh Jayaraman -Date: Tue, 12 Jun 2012 07:15:50 +0530 -Subject: [PATCH] cifs: fix parsing of password mount option - -The double delimiter check that allows a comma in the password parsing code is -unconditional. We set "tmp_end" to the end of the string and we continue to -check for double delimiter. In the case where the password doesn't contain a -comma we end up setting tmp_end to NULL and eventually setting "options" to -"end". This results in the premature termination of the options string and hence -the values of UNCip and UNC are being set to NULL. This results in mount failure -with "Connecting to DFS root not implemented yet" error. - -This error is usually not noticable as we have password as the last option in -the superblock mountdata. But when we call expand_dfs_referral() from -cifs_mount() and try to compose mount options for the submount, the resulting -mountdata will be of the form - - ",ver=1,user=foo,pass=bar,ip=x.x.x.x,unc=\\server\share" - -and hence results in the above error. This bug has been seen with older NAS -servers running Samba 3.0.24. - -Fix this by moving the double delimiter check inside the conditional loop. - -Changes since -v1 - - - removed the wrong strlen() micro optimization. - -Signed-off-by: Suresh Jayaraman -Acked-by: Sachin Prabhu -Cc: stable@vger.kernel.org [3.1+] -Signed-off-by: Steve French ---- - fs/cifs/connect.c | 32 +++++++++++++++++--------------- - 1 files changed, 17 insertions(+), 15 deletions(-) - -diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c -index 78db68a..5b38407 100644 ---- a/fs/cifs/connect.c -+++ b/fs/cifs/connect.c -@@ -1653,24 +1653,26 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, - * If yes, we have encountered a double deliminator - * reset the NULL character to the deliminator - */ -- if (tmp_end < end && tmp_end[1] == delim) -+ if (tmp_end < end && tmp_end[1] == delim) { - tmp_end[0] = delim; - -- /* Keep iterating until we get to a single deliminator -- * OR the end -- */ -- while ((tmp_end = strchr(tmp_end, delim)) != NULL && -- (tmp_end[1] == delim)) { -- tmp_end = (char *) &tmp_end[2]; -- } -+ /* Keep iterating until we get to a single -+ * deliminator OR the end -+ */ -+ while ((tmp_end = strchr(tmp_end, delim)) -+ != NULL && (tmp_end[1] == delim)) { -+ tmp_end = (char *) &tmp_end[2]; -+ } - -- /* Reset var options to point to next element */ -- if (tmp_end) { -- tmp_end[0] = '\0'; -- options = (char *) &tmp_end[1]; -- } else -- /* Reached the end of the mount option string */ -- options = end; -+ /* Reset var options to point to next element */ -+ if (tmp_end) { -+ tmp_end[0] = '\0'; -+ options = (char *) &tmp_end[1]; -+ } else -+ /* Reached the end of the mount option -+ * string */ -+ options = end; -+ } - - /* Now build new password string */ - temp_len = strlen(value); --- -1.7.0.4 - diff --git a/drm-nouveau-fbcon-using-nv_two_heads-is-not-a-good-i.patch b/drm-nouveau-fbcon-using-nv_two_heads-is-not-a-good-i.patch deleted file mode 100644 index 2b164755d..000000000 --- a/drm-nouveau-fbcon-using-nv_two_heads-is-not-a-good-i.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 9bd0c15fcfb42f6245447c53347d65ad9e72080b Mon Sep 17 00:00:00 2001 -From: Ben Skeggs -Date: Tue, 26 Jun 2012 12:12:30 +1000 -Subject: [PATCH] drm/nouveau/fbcon: using nv_two_heads is not a good idea - -nv_two_heads() was never meant to be used outside of pre-nv50 code. The -code checks for >= NV_10 for 2 CRTCs, then downgrades a few specific -chipsets to 1 CRTC based on (pci_device & 0x0ff0). - -The breakage example seen is on GTX 560Ti, with a pciid of 0x1200, which -gets detected as an NV20 (0x020x) with 1 CRTC by nv_two_heads(), causing -memory corruption because there's actually 2 CRTCs.. - -This switches fbcon to use the CRTC count directly from the mode_config -structure, which will also fix the same issue on Kepler boards which have -4 CRTCs. - -Signed-off-by: Ben Skeggs -Cc: stable@vger.kernel.org -Signed-off-by: Dave Airlie ---- - drivers/gpu/drm/nouveau/nouveau_fbcon.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c -index 153b9a1..1074bc5 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c -+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c -@@ -467,7 +467,7 @@ int nouveau_fbcon_init(struct drm_device *dev) - nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs; - - ret = drm_fb_helper_init(dev, &nfbdev->helper, -- nv_two_heads(dev) ? 2 : 1, 4); -+ dev->mode_config.num_crtc, 4); - if (ret) { - kfree(nfbdev); - return ret; --- -1.7.10.2 - diff --git a/ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch b/ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch deleted file mode 100644 index 705c5eff0..000000000 --- a/ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch +++ /dev/null @@ -1,155 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Stanislav Yakovlev -Newsgroups: gmane.linux.kernel.wireless.general -Subject: [PATCH] net/wireless: ipw2x00: add supported cipher suites to wiphy initialization -Date: Tue, 10 Apr 2012 21:44:47 -0400 -Lines: 97 -Approved: news@gmane.org -Message-ID: <1334108687-12954-1-git-send-email-stas.yakovlev@gmail.com> -NNTP-Posting-Host: plane.gmane.org -X-Trace: dough.gmane.org 1334108469 22291 80.91.229.3 (11 Apr 2012 01:41:09 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Wed, 11 Apr 2012 01:41:09 +0000 (UTC) -Cc: simar-hi6Y0CQ0nG0@public.gmane.org, linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, - Stanislav Yakovlev -To: linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org -Original-X-From: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Wed Apr 11 03:41:07 2012 -Return-path: -Envelope-to: glkwg-linux-wireless-wOFGN7rlS/M9smdsby/KFg@public.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1SHmYV-0004IK-CT - for glkwg-linux-wireless-wOFGN7rlS/M9smdsby/KFg@public.gmane.org; Wed, 11 Apr 2012 03:41:07 +0200 -Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand - id S1759898Ab2DKBlF (ORCPT - ); - Tue, 10 Apr 2012 21:41:05 -0400 -Original-Received: from mail-ob0-f174.google.com ([209.85.214.174]:60108 "EHLO - mail-ob0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S1753779Ab2DKBlE (ORCPT - ); - Tue, 10 Apr 2012 21:41:04 -0400 -Original-Received: by obbtb18 with SMTP id tb18so567970obb.19 - for ; Tue, 10 Apr 2012 18:41:02 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=20120113; - h=from:to:cc:subject:date:message-id:x-mailer; - bh=8+D+Uuo0bIOG6rz8vxd6TGAxmrbuAw2bjWhd058IjOQ=; - b=beOgy1Y9ZAV1Xw5XqsnPDJ1Oc0qOpOo+gCWlwmWbLdVHxUVG+ZVuRW9eCRQkh+5bZm - 5Ic+xOISztYUJp144Fr4flnbGPRKKp7jP8qQ/HvCOo34J6MCgBlnuWNYKbn4/NUvOYAh - SeHpk2D8yOHbiWAMV+JGTqGG+/N4jVvRL147Yg1IfNDAJd8Ahbl0wARLOVg8WGGTSPvn - MU3HNbmKFFBDhnukYr4keCnjixuDkqPYGMYuDrsmKdiAFHBRDI6qudnvaqi8F8gbtaWg - dfssdTbmNYM/R/PJenInoy7IbRps2iW9ZX+zFzydZWp2EyJ4EZkKrYKmnezQgNJzRVex - KHfg== -Original-Received: by 10.60.24.9 with SMTP id q9mr19071024oef.4.1334108462648; - Tue, 10 Apr 2012 18:41:02 -0700 (PDT) -Original-Received: from localhost.localdomain (50-0-191-227.dsl.static.sonic.net. [50.0.191.227]) - by mx.google.com with ESMTPS id tx2sm1309336obb.8.2012.04.10.18.40.54 - (version=TLSv1/SSLv3 cipher=OTHER); - Tue, 10 Apr 2012 18:41:01 -0700 (PDT) -X-Mailer: git-send-email 1.7.2.5 -Original-Sender: linux-wireless-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Xref: news.gmane.org gmane.linux.kernel.wireless.general:88613 -Archived-At: - -Driver doesn't report its supported cipher suites through cfg80211 -interface. It still uses wext interface and probably will not work -through nl80211, but will at least correctly advertise supported -features. - -Bug was reported by Omar Siam. -https://bugzilla.kernel.org/show_bug.cgi?id=43049 - -Signed-off-by: Stanislav Yakovlev ---- - drivers/net/wireless/ipw2x00/ipw.h | 23 +++++++++++++++++++++++ - drivers/net/wireless/ipw2x00/ipw2100.c | 4 ++++ - drivers/net/wireless/ipw2x00/ipw2200.c | 4 ++++ - 3 files changed, 31 insertions(+), 0 deletions(-) - create mode 100644 drivers/net/wireless/ipw2x00/ipw.h - -diff --git a/drivers/net/wireless/ipw2x00/ipw.h b/drivers/net/wireless/ipw2x00/ipw.h -new file mode 100644 -index 0000000..4007bf5 ---- /dev/null -+++ b/drivers/net/wireless/ipw2x00/ipw.h -@@ -0,0 +1,23 @@ -+/* -+ * Intel Pro/Wireless 2100, 2200BG, 2915ABG network connection driver -+ * -+ * Copyright 2012 Stanislav Yakovlev -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __IPW_H__ -+#define __IPW_H__ -+ -+#include -+ -+static const u32 ipw_cipher_suites[] = { -+ WLAN_CIPHER_SUITE_WEP40, -+ WLAN_CIPHER_SUITE_WEP104, -+ WLAN_CIPHER_SUITE_TKIP, -+ WLAN_CIPHER_SUITE_CCMP, -+}; -+ -+#endif -diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c -index f0551f8..7c8e8b1 100644 ---- a/drivers/net/wireless/ipw2x00/ipw2100.c -+++ b/drivers/net/wireless/ipw2x00/ipw2100.c -@@ -166,6 +166,7 @@ that only one external action is invoked at a time. - #include - - #include "ipw2100.h" -+#include "ipw.h" - - #define IPW2100_VERSION "git-1.2.2" - -@@ -1946,6 +1947,9 @@ static int ipw2100_wdev_init(struct net_device *dev) - wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band; - } - -+ wdev->wiphy->cipher_suites = ipw_cipher_suites; -+ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites); -+ - set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); - if (wiphy_register(wdev->wiphy)) { - ipw2100_down(priv); -diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c -index 2b02257..bb4f42a 100644 ---- a/drivers/net/wireless/ipw2x00/ipw2200.c -+++ b/drivers/net/wireless/ipw2x00/ipw2200.c -@@ -34,6 +34,7 @@ - #include - #include - #include "ipw2200.h" -+#include "ipw.h" - - - #ifndef KBUILD_EXTMOD -@@ -11533,6 +11534,9 @@ static int ipw_wdev_init(struct net_device *dev) - wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = a_band; - } - -+ wdev->wiphy->cipher_suites = ipw_cipher_suites; -+ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites); -+ - set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); - - /* With that information in place, we can now register the wiphy... */ --- -1.7.2.5 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - diff --git a/kernel.spec b/kernel.spec index 70988bb30..78789c710 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 6 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 4 +%define stable_update 5 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -751,68 +751,15 @@ Patch21306: shlib_base_randomize.patch Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch -#rhbz 814278 814289 CVE-2012-2119 -Patch22007: macvtap-zerocopy-validate-vector-length.patch - -#rhbz 817298 -Patch22013: ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch - #rhbz 749276 Patch22018: atl1c_net_next_update-3.4.patch -#rhbz 795176 -Patch22019: rtl818x-fix-sleeping-function-called-from-invalid-context.patch - -#rhbz 822825 822821 CVE-2012-2372 -Patch22021: mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch - -#rhbz 829016 -Patch22022: thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch - -#rhbz 830862 -Patch22030: SUNRPC-new-svc_bind-routine-introduced.patch -Patch22031: SUNRPC-move-per-net-operations-from-svc_destroy.patch - -#rhbz 832741 -Patch22032: cifs-fix-parsing-of-password-mount-option.patch - -#rhbz 831807 -Patch22034: usb-storage-try-read_capacity-10-first.patch - -#rhbz 828731 -Patch22035: ath9k_htc-configure-bssid-on-ASSOC-IBSS-change.patch - #rhbz 835019 Patch22036: block-fix-infinite-loop-in-__getblk_slow.patch -#rhbz 832867 -Patch22040: mm-correctly-synchronize-rss-counters-at-exit-exec.patch - -#rhbz 832927 -Patch22041: ath9k-fix-panic-caused-by-returning-a-descriptor-we-.patch - -#rhbz 834910 -Patch22042: ACPI-video-Still-use-ACPI-backlight-control-if-_DOS-doesnt-exist.patch - #rhbz 828824 Patch22043: rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch -#rhbz 825123 -Patch22044: tg3-Apply-short-DMA-frag-workaround-to-5906.patch - -#rhbz 830359 -Patch22045: drm-nouveau-fbcon-using-nv_two_heads-is-not-a-good-i.patch - -#rhbz 829880 -Patch22046: USB-qmi_wwan-Make-forced-int-4-whitelist-generic.patch -Patch22047: USB-qmi_wwan-Add-ZTE-Vodafone-K3520-Z.patch -Patch22048: net-qmi_wwan-fix-Gobi-device-probing.patch - -Patch22050: ACPI-APEI-Avoid-too-much-error-reporting.patch - -#rhbz 824641 -Patch22051: xen-blkback-Copy-id-field-when-doing-BLKIF_DISCARD.patch - #Fix FIPS for aesni hardare Patch22055: crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch Patch22056: crypto-aesni-intel-fix-wrong-kfree-pointer.patch @@ -1458,67 +1405,15 @@ ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch ApplyPatch debug-808990.patch -#rhbz 814278 814289 CVE-2012-2119 -ApplyPatch macvtap-zerocopy-validate-vector-length.patch - -#rhbz 817298 -ApplyPatch ipw2x00-add-supported-cipher-suites-to-wiphy-initialization.patch - #rhbz 749276 ApplyPatch atl1c_net_next_update-3.4.patch -#rhbz 795176 -ApplyPatch rtl818x-fix-sleeping-function-called-from-invalid-context.patch - -#rhbz 822825 822821 CVE-2012-2372 -ApplyPatch mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch - -ApplyPatch thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch - -#rhbz 830862 -ApplyPatch SUNRPC-new-svc_bind-routine-introduced.patch -ApplyPatch SUNRPC-move-per-net-operations-from-svc_destroy.patch - -#rhbz 832741 -ApplyPatch cifs-fix-parsing-of-password-mount-option.patch - -#rhbz 831807 -ApplyPatch usb-storage-try-read_capacity-10-first.patch - -#rhbz 828731 -ApplyPatch ath9k_htc-configure-bssid-on-ASSOC-IBSS-change.patch - #rhbz 835019 ApplyPatch block-fix-infinite-loop-in-__getblk_slow.patch -#rhbz 832867 -ApplyPatch mm-correctly-synchronize-rss-counters-at-exit-exec.patch - -#rhbz 832927 -ApplyPatch ath9k-fix-panic-caused-by-returning-a-descriptor-we-.patch - -#rhbz 834910 -ApplyPatch ACPI-video-Still-use-ACPI-backlight-control-if-_DOS-doesnt-exist.patch - #rhbz 828824 ApplyPatch rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch -#rhbz 825123 -ApplyPatch tg3-Apply-short-DMA-frag-workaround-to-5906.patch - -#rhbz 830359 -ApplyPatch drm-nouveau-fbcon-using-nv_two_heads-is-not-a-good-i.patch - -#rhbz 829880 -ApplyPatch USB-qmi_wwan-Make-forced-int-4-whitelist-generic.patch -ApplyPatch USB-qmi_wwan-Add-ZTE-Vodafone-K3520-Z.patch -ApplyPatch net-qmi_wwan-fix-Gobi-device-probing.patch - -ApplyPatch ACPI-APEI-Avoid-too-much-error-reporting.patch - -#rhbz 824641 -ApplyPatch xen-blkback-Copy-id-field-when-doing-BLKIF_DISCARD.patch - #Fix FIPS for aesni hardare ApplyPatch crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch ApplyPatch crypto-aesni-intel-fix-wrong-kfree-pointer.patch @@ -2264,6 +2159,9 @@ fi # and build. %changelog +* Mon Jul 16 2012 Josh Boyer - 3.4.5-1 +- Linux v3.4.5 + * Thu Jul 12 2012 Josh Boyer - Add patch to fix ACPICA null pointer exception regression (rhbz 834318) diff --git a/macvtap-zerocopy-validate-vector-length.patch b/macvtap-zerocopy-validate-vector-length.patch deleted file mode 100644 index 3ac31e4b6..000000000 --- a/macvtap-zerocopy-validate-vector-length.patch +++ /dev/null @@ -1,25 +0,0 @@ -Currently we do not validate the vector length before calling -get_user_pages_fast(), host stack would be easily overflowed by -malicious guest driver who give us a descriptor with length greater -than MAX_SKB_FRAGS. Solve this problem by checking the free entries -before trying to pin user pages. - -Signed-off-by: Jason Wang ---- - drivers/net/macvtap.c | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) - -diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c -index 7cb2684..d197a78 100644 ---- a/drivers/net/macvtap.c -+++ b/drivers/net/macvtap.c -@@ -527,6 +527,8 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, - } - base = (unsigned long)from->iov_base + offset1; - size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT; -+ if (i + size >= MAX_SKB_FRAGS) -+ return -EFAULT; - num_pages = get_user_pages_fast(base, size, 0, &page[i]); - if ((num_pages != size) || - (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags)) - diff --git a/mm-correctly-synchronize-rss-counters-at-exit-exec.patch b/mm-correctly-synchronize-rss-counters-at-exit-exec.patch deleted file mode 100644 index 0ef36b311..000000000 --- a/mm-correctly-synchronize-rss-counters-at-exit-exec.patch +++ /dev/null @@ -1,125 +0,0 @@ -From davej Wed Jun 20 11:37:32 2012 -Return-Path: oleg@redhat.com -X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on - gelk.kernelslacker.org -X-Spam-Level: -X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD, - UNPARSEABLE_RELAY autolearn=ham version=3.3.2 -Received: from mail.corp.redhat.com [10.4.128.1] - by gelk.kernelslacker.org with IMAP (fetchmail-6.3.21) - for (single-drop); Wed, 20 Jun 2012 11:37:32 -0400 (EDT) -Received: from zmta05.collab.prod.int.phx2.redhat.com (LHLO - zmta05.collab.prod.int.phx2.redhat.com) (10.5.81.12) by - zmail11.collab.prod.int.phx2.redhat.com with LMTP; Wed, 20 Jun 2012 - 11:37:18 -0400 (EDT) -Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) - by zmta05.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 539B1F2080 - for ; Wed, 20 Jun 2012 11:37:18 -0400 (EDT) -Received: from tranklukator.englab.brq.redhat.com (dhcp-1-232.brq.redhat.com [10.34.1.232]) - by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id q5KFbGde008148; - Wed, 20 Jun 2012 11:37:17 -0400 -Received: by tranklukator.englab.brq.redhat.com (nbSMTP-1.00) for uid 500 - oleg@redhat.com; Wed, 20 Jun 2012 17:35:20 +0200 (CEST) -Date: Wed, 20 Jun 2012 17:35:19 +0200 -From: Oleg Nesterov -To: Dave Jones -Cc: Fedora Kernel Team -Subject: Re: [Bug 832867] BUG: Bad rss-counter state mm:xxxxxxxx idx:1 - val:-2 output in console -Message-ID: <20120620153519.GA17642@redhat.com> -References: <20120619172633.GG26103@redhat.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -In-Reply-To: <20120619172633.GG26103@redhat.com> -User-Agent: Mutt/1.5.18 (2008-05-17) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -Status: RO -Content-Length: 2687 -Lines: 84 - -Hi Dave, - -sorry for delay - -On 06/19, Dave Jones wrote: -> -> > https://bugzilla.redhat.com/show_bug.cgi?id=832867 -> > -> > --- Comment #11 from Bojan Smojver --- -> > Patches for this: -> > -> > http://comments.gmane.org/gmane.linux.kernel/1306252 -> -> Oleg, -> -> are these patches final ? Are they headed for stable ? - -No. And 1/2 was wrong actually, see -http://marc.info/?l=linux-kernel&m=133911852215275 - -Konstantin sent the minimal fix, -mm-correctly-synchronize-rss-counters-at-exit-exec.patch in -mm tree, -attached below. - -Oleg. - ------------------------------------------------------- -From: Konstantin Khlebnikov -Subject: mm: correctly synchronize rss-counters at exit/exec - -do_exit() and exec_mmap() call sync_mm_rss() before mm_release() does -put_user(clear_child_tid) which can update task->rss_stat and thus make -mm->rss_stat inconsistent. This triggers the "BUG:" printk in check_mm(). - -Let's fix this bug in the safest way, and optimize/cleanup this later. - -Reported-by: Markus Trippelsdorf -Signed-off-by: Konstantin Khlebnikov -Cc: Oleg Nesterov -Cc: KAMEZAWA Hiroyuki -Cc: Hugh Dickins -Cc: -Signed-off-by: Andrew Morton ---- - - fs/exec.c | 2 +- - kernel/exit.c | 1 + - 2 files changed, 2 insertions(+), 1 deletion(-) - -diff -puN fs/exec.c~mm-correctly-synchronize-rss-counters-at-exit-exec fs/exec.c ---- a/fs/exec.c~mm-correctly-synchronize-rss-counters-at-exit-exec -+++ a/fs/exec.c -@@ -819,10 +819,10 @@ static int exec_mmap(struct mm_struct *m - /* Notify parent that we're no longer interested in the old VM */ - tsk = current; - old_mm = current->mm; -- sync_mm_rss(old_mm); - mm_release(tsk, old_mm); - - if (old_mm) { -+ sync_mm_rss(old_mm); - /* - * Make sure that if there is a core dump in progress - * for the old mm, we get out and die instead of going -diff -puN kernel/exit.c~mm-correctly-synchronize-rss-counters-at-exit-exec kernel/exit.c ---- a/kernel/exit.c~mm-correctly-synchronize-rss-counters-at-exit-exec -+++ a/kernel/exit.c -@@ -643,6 +643,7 @@ static void exit_mm(struct task_struct * - mm_release(tsk, mm); - if (!mm) - return; -+ sync_mm_rss(mm); - /* - * Serialize with any possible pending coredump. - * We must hold mmap_sem around checking core_state -_ -Subject: From: Konstantin Khlebnikov - -Patches currently in -mm which might be from khlebnikov@openvz.org are - -linux-next.patch -memcg-fix-use_hierarchy-css_is_ancestor-oops-regression.patch -mm-correctly-synchronize-rss-counters-at-exit-exec.patch - - diff --git a/mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch b/mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch deleted file mode 100644 index 49ff98a62..000000000 --- a/mm-pmd_read_atomic-fix-32bit-PAE-pmd-walk-vs-pmd_populate-SMP-race-condition.patch +++ /dev/null @@ -1,272 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Andrea Arcangeli -Newsgroups: gmane.linux.kernel.mm -Subject: [PATCH] mm: pmd_read_atomic: fix 32bit PAE pmd walk vs pmd_populate SMP race condition -Date: Thu, 24 May 2012 01:39:01 +0200 -Lines: 208 -Approved: news@gmane.org -Message-ID: <1337816341-30743-1-git-send-email-aarcange@redhat.com> -References: <20120518230028.GF32479@redhat.com> -NNTP-Posting-Host: plane.gmane.org -X-Trace: dough.gmane.org 1337816354 18906 80.91.229.3 (23 May 2012 23:39:14 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Wed, 23 May 2012 23:39:14 +0000 (UTC) -Cc: Andrew Morton , Mel Gorman , - Hugh Dickins , Larry Woodman , - Petr Matousek , - Ulrich Obergfell , Rik van Riel -To: linux-mm@kvack.org -Original-X-From: owner-linux-mm@kvack.org Thu May 24 01:39:12 2012 -Return-path: -Envelope-to: glkm-linux-mm-2@m.gmane.org -Original-Received: from kanga.kvack.org ([205.233.56.17]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1SXL94-0002ub-3P - for glkm-linux-mm-2@m.gmane.org; Thu, 24 May 2012 01:39:10 +0200 -Original-Received: by kanga.kvack.org (Postfix) - id 1684A6B0083; Wed, 23 May 2012 19:39:09 -0400 (EDT) -Delivered-To: linux-mm-outgoing@kvack.org -Original-Received: by kanga.kvack.org (Postfix, from userid 40) - id 080DD6B0092; Wed, 23 May 2012 19:39:08 -0400 (EDT) -X-Original-To: int-list-linux-mm@kvack.org -Delivered-To: int-list-linux-mm@kvack.org -Original-Received: by kanga.kvack.org (Postfix, from userid 63042) - id C84046B00E7; Wed, 23 May 2012 19:39:08 -0400 (EDT) -X-Original-To: linux-mm@kvack.org -Delivered-To: linux-mm@kvack.org -Original-Received: from psmtp.com (na3sys010amx119.postini.com [74.125.245.119]) - by kanga.kvack.org (Postfix) with SMTP id 0B2DC6B0083 - for ; Wed, 23 May 2012 19:39:07 -0400 (EDT) -Original-Received: from mx1.redhat.com ([209.132.183.28]) (using TLSv1) by na3sys010amx119.postini.com ([74.125.244.10]) with SMTP; - Wed, 23 May 2012 18:39:08 CDT -Original-Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q4NNd3dP002492 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); - Wed, 23 May 2012 19:39:03 -0400 -Original-Received: from random.random (ovpn-113-72.phx2.redhat.com [10.3.113.72]) - by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q4NNd1P7012233; - Wed, 23 May 2012 19:39:02 -0400 -In-Reply-To: <20120518230028.GF32479@redhat.com> -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 -X-pstn-neptune: 0/0/0.00/0 -X-pstn-levels: (S:99.90000/99.90000 CV:99.9000 FC:95.5390 LC:95.5390 R:95.9108 P:95.9108 M:97.0282 C:98.6951 ) -X-pstn-dkim: 0 skipped:not-enabled -X-pstn-settings: 3 (1.0000:1.0000) s cv gt3 gt2 gt1 r p m c -X-pstn-addresses: from [db-null] -X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.2 -Original-Sender: owner-linux-mm@kvack.org -Precedence: bulk -X-Loop: owner-majordomo@kvack.org -List-ID: -Xref: news.gmane.org gmane.linux.kernel.mm:78936 -Archived-At: - -When holding the mmap_sem for reading, pmd_offset_map_lock should only -run on a pmd_t that has been read atomically from the pmdp -pointer, otherwise we may read only half of it leading to this crash. - -PID: 11679 TASK: f06e8000 CPU: 3 COMMAND: "do_race_2_panic" - #0 [f06a9dd8] crash_kexec at c049b5ec - #1 [f06a9e2c] oops_end at c083d1c2 - #2 [f06a9e40] no_context at c0433ded - #3 [f06a9e64] bad_area_nosemaphore at c043401a - #4 [f06a9e6c] __do_page_fault at c0434493 - #5 [f06a9eec] do_page_fault at c083eb45 - #6 [f06a9f04] error_code (via page_fault) at c083c5d5 - EAX: 01fb470c EBX: fff35000 ECX: 00000003 EDX: 00000100 EBP: - 00000000 - DS: 007b ESI: 9e201000 ES: 007b EDI: 01fb4700 GS: 00e0 - CS: 0060 EIP: c083bc14 ERR: ffffffff EFLAGS: 00010246 - #7 [f06a9f38] _spin_lock at c083bc14 - #8 [f06a9f44] sys_mincore at c0507b7d - #9 [f06a9fb0] system_call at c083becd - start len - EAX: ffffffda EBX: 9e200000 ECX: 00001000 EDX: 6228537f - DS: 007b ESI: 00000000 ES: 007b EDI: 003d0f00 - SS: 007b ESP: 62285354 EBP: 62285388 GS: 0033 - CS: 0073 EIP: 00291416 ERR: 000000da EFLAGS: 00000286 - -This should be a longstanding bug affecting x86 32bit PAE without -THP. Only archs with 64bit large pmd_t and 32bit unsigned long should -be affected. - -With THP enabled the barrier() in -pmd_none_or_trans_huge_or_clear_bad() would partly hide the bug when -the pmd transition from none to stable, by forcing a re-read of the -*pmd in pmd_offset_map_lock, but when THP is enabled a new set of -problem arises by the fact could then transition freely in any of the -none, pmd_trans_huge or pmd_trans_stable states. So making the barrier -in pmd_none_or_trans_huge_or_clear_bad() unconditional isn't good idea -and it would be a flakey solution. - -This should be fully fixed by introducing a pmd_read_atomic that reads -the pmd in order with THP disabled, or by reading the pmd atomically -with cmpxchg8b with THP enabled. - -Luckily this new race condition only triggers in the places that must -already be covered by pmd_none_or_trans_huge_or_clear_bad() so the fix -is localized there but this bug is not related to THP. - -NOTE: this can trigger on x86 32bit systems with PAE enabled with more -than 4G of ram, otherwise the high part of the pmd will never risk to -be truncated because it would be zero at all times, in turn so hiding -the SMP race. - -This bug was discovered and fully debugged by Ulrich, quote: - ----- -[..] -pmd_none_or_trans_huge_or_clear_bad() loads the content of edx and -eax. - - 496 static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t - *pmd) - 497 { - 498 /* depend on compiler for an atomic pmd read */ - 499 pmd_t pmdval = *pmd; - - // edi = pmd pointer -0xc0507a74 : mov 0x8(%esp),%edi -... - // edx = PTE page table high address -0xc0507a84 : mov 0x4(%edi),%edx -... - // eax = PTE page table low address -0xc0507a8e : mov (%edi),%eax - -[..] - -Please note that the PMD is not read atomically. These are two "mov" -instructions where the high order bits of the PMD entry are fetched -first. Hence, the above machine code is prone to the following race. - -- The PMD entry {high|low} is 0x0000000000000000. - The "mov" at 0xc0507a84 loads 0x00000000 into edx. - -- A page fault (on another CPU) sneaks in between the two "mov" - instructions and instantiates the PMD. - -- The PMD entry {high|low} is now 0x00000003fda38067. - The "mov" at 0xc0507a8e loads 0xfda38067 into eax. ----- - -Reported-by: Ulrich Obergfell -Signed-off-by: Andrea Arcangeli ---- - arch/x86/include/asm/pgtable-3level.h | 50 +++++++++++++++++++++++++++++++++ - include/asm-generic/pgtable.h | 22 +++++++++++++- - 2 files changed, 70 insertions(+), 2 deletions(-) - -diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h -index effff47..43876f1 100644 ---- a/arch/x86/include/asm/pgtable-3level.h -+++ b/arch/x86/include/asm/pgtable-3level.h -@@ -31,6 +31,56 @@ static inline void native_set_pte(pte_t *ptep, pte_t pte) - ptep->pte_low = pte.pte_low; - } - -+#define pmd_read_atomic pmd_read_atomic -+/* -+ * pte_offset_map_lock on 32bit PAE kernels was reading the pmd_t with -+ * a "*pmdp" dereference done by gcc. Problem is, in certain places -+ * where pte_offset_map_lock is called, concurrent page faults are -+ * allowed, if the mmap_sem is hold for reading. An example is mincore -+ * vs page faults vs MADV_DONTNEED. On the page fault side -+ * pmd_populate rightfully does a set_64bit, but if we're reading the -+ * pmd_t with a "*pmdp" on the mincore side, a SMP race can happen -+ * because gcc will not read the 64bit of the pmd atomically. To fix -+ * this all places running pmd_offset_map_lock() while holding the -+ * mmap_sem in read mode, shall read the pmdp pointer using this -+ * function to know if the pmd is null nor not, and in turn to know if -+ * they can run pmd_offset_map_lock or pmd_trans_huge or other pmd -+ * operations. -+ * -+ * Without THP if the mmap_sem is hold for reading, the -+ * pmd can only transition from null to not null while pmd_read_atomic runs. -+ * So there's no need of literally reading it atomically. -+ * -+ * With THP if the mmap_sem is hold for reading, the pmd can become -+ * THP or null or point to a pte (and in turn become "stable") at any -+ * time under pmd_read_atomic, so it's mandatory to read it atomically -+ * with cmpxchg8b. -+ */ -+#ifndef CONFIG_TRANSPARENT_HUGEPAGE -+static inline pmd_t pmd_read_atomic(pmd_t *pmdp) -+{ -+ pmdval_t ret; -+ u32 *tmp = (u32 *)pmdp; -+ -+ ret = (pmdval_t) (*tmp); -+ if (ret) { -+ /* -+ * If the low part is null, we must not read the high part -+ * or we can end up with a partial pmd. -+ */ -+ smp_rmb(); -+ ret |= ((pmdval_t)*(tmp + 1)) << 32; -+ } -+ -+ return (pmd_t) { ret }; -+} -+#else /* CONFIG_TRANSPARENT_HUGEPAGE */ -+static inline pmd_t pmd_read_atomic(pmd_t *pmdp) -+{ -+ return (pmd_t) { atomic64_read((atomic64_t *)pmdp) }; -+} -+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ -+ - static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) - { - set_64bit((unsigned long long *)(ptep), native_pte_val(pte)); -diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h -index 125c54e..fa596d9 100644 ---- a/include/asm-generic/pgtable.h -+++ b/include/asm-generic/pgtable.h -@@ -446,6 +446,18 @@ static inline int pmd_write(pmd_t pmd) - #endif /* __HAVE_ARCH_PMD_WRITE */ - #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ - -+#ifndef pmd_read_atomic -+static inline pmd_t pmd_read_atomic(pmd_t *pmdp) -+{ -+ /* -+ * Depend on compiler for an atomic pmd read. NOTE: this is -+ * only going to work, if the pmdval_t isn't larger than -+ * an unsigned long. -+ */ -+ return *pmdp; -+} -+#endif -+ - /* - * This function is meant to be used by sites walking pagetables with - * the mmap_sem hold in read mode to protect against MADV_DONTNEED and -@@ -459,11 +471,17 @@ static inline int pmd_write(pmd_t pmd) - * undefined so behaving like if the pmd was none is safe (because it - * can return none anyway). The compiler level barrier() is critically - * important to compute the two checks atomically on the same pmdval. -+ * -+ * For 32bit kernels with a 64bit large pmd_t this automatically takes -+ * care of reading the pmd atomically to avoid SMP race conditions -+ * against pmd_populate() when the mmap_sem is hold for reading by the -+ * caller (a special atomic read not done by "gcc" as in the generic -+ * version above, is also needed when THP is disabled because the page -+ * fault can populate the pmd from under us). - */ - static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd) - { -- /* depend on compiler for an atomic pmd read */ -- pmd_t pmdval = *pmd; -+ pmd_t pmdval = pmd_read_atomic(pmd); - /* - * The barrier will stabilize the pmdval in a register or on - * the stack so that it will stop changing under the code. - --- -To unsubscribe, send a message with 'unsubscribe linux-mm' in -the body to majordomo@kvack.org. For more info on Linux MM, -see: http://www.linux-mm.org/ . -Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ -Don't email: email@kvack.org - diff --git a/net-qmi_wwan-fix-Gobi-device-probing.patch b/net-qmi_wwan-fix-Gobi-device-probing.patch deleted file mode 100644 index 9dce14f4a..000000000 --- a/net-qmi_wwan-fix-Gobi-device-probing.patch +++ /dev/null @@ -1,194 +0,0 @@ -From b9f90eb2740203ff2592efe640409ad48335d1c2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= -Date: Thu, 21 Jun 2012 02:45:58 +0000 -Subject: [PATCH] net: qmi_wwan: fix Gobi device probing -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Ignoring interfaces with additional descriptors is not a reliable -method for locating the correct interface on Gobi devices. There -is at least one device where this method fails: -https://bbs.archlinux.org/viewtopic.php?id=143506 - -The result is that the AT command port (interface #2) is hidden -from qcserial, preventing traditional serial modem usage: - -[ 15.562552] qmi_wwan 4-1.6:1.0: cdc-wdm0: USB WDM device -[ 15.562691] qmi_wwan 4-1.6:1.0: wwan0: register 'qmi_wwan' at usb-0000:00:1d.0-1.6, Qualcomm Gobi wwan/QMI device, 1e:df:3c:3a:4e:3b -[ 15.563383] qmi_wwan: probe of 4-1.6:1.1 failed with error -22 -[ 15.564189] qmi_wwan 4-1.6:1.2: cdc-wdm1: USB WDM device -[ 15.564302] qmi_wwan 4-1.6:1.2: wwan1: register 'qmi_wwan' at usb-0000:00:1d.0-1.6, Qualcomm Gobi wwan/QMI device, 1e:df:3c:3a:4e:3b -[ 15.564328] qmi_wwan: probe of 4-1.6:1.3 failed with error -22 -[ 15.569376] qcserial 4-1.6:1.1: Qualcomm USB modem converter detected -[ 15.569440] usb 4-1.6: Qualcomm USB modem converter now attached to ttyUSB0 -[ 15.570372] qcserial 4-1.6:1.3: Qualcomm USB modem converter detected -[ 15.570430] usb 4-1.6: Qualcomm USB modem converter now attached to ttyUSB1 - -Use static interface numbers taken from the interface map in -qcserial for all Gobi devices instead: - - Gobi 1K USB layout: - 0: serial port (doesn't respond) - 1: serial port (doesn't respond) - 2: AT-capable modem port - 3: QMI/net - - Gobi 2K+ USB layout: - 0: QMI/net - 1: DM/DIAG (use libqcdm from ModemManager for communication) - 2: AT-capable modem port - 3: NMEA - -This should be more reliable over all, and will also prevent the -noisy "probe failed" messages. The whitelisting logic is expected -to be replaced by direct interface number matching in 3.6. - -Reported-by: Heinrich Siebmanns (Harvey) -Cc: # v3.4: 0000188 USB: qmi_wwan: Make forced int 4 whitelist generic -Cc: # v3.4: f7142e6 USB: qmi_wwan: Add ZTE (Vodafone) K3520-Z -Cc: # v3.4 -Signed-off-by: Bjørn Mork -Signed-off-by: David S. Miller ---- - drivers/net/usb/qmi_wwan.c | 83 +++++++++++++++++++++----------------------- - 1 file changed, 40 insertions(+), 43 deletions(-) - -diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c -index 3b20678..3767a12 100644 ---- a/drivers/net/usb/qmi_wwan.c -+++ b/drivers/net/usb/qmi_wwan.c -@@ -257,29 +257,6 @@ err: - return rv; - } - --/* Gobi devices uses identical class/protocol codes for all interfaces regardless -- * of function. Some of these are CDC ACM like and have the exact same endpoints -- * we are looking for. This leaves two possible strategies for identifying the -- * correct interface: -- * a) hardcoding interface number, or -- * b) use the fact that the wwan interface is the only one lacking additional -- * (CDC functional) descriptors -- * -- * Let's see if we can get away with the generic b) solution. -- */ --static int qmi_wwan_bind_gobi(struct usbnet *dev, struct usb_interface *intf) --{ -- int rv = -EINVAL; -- -- /* ignore any interface with additional descriptors */ -- if (intf->cur_altsetting->extralen) -- goto err; -- -- rv = qmi_wwan_bind_shared(dev, intf); --err: -- return rv; --} -- - static void qmi_wwan_unbind_shared(struct usbnet *dev, struct usb_interface *intf) - { - struct usb_driver *subdriver = (void *)dev->data[0]; -@@ -347,15 +324,15 @@ static const struct driver_info qmi_wwan_shared = { - .manage_power = qmi_wwan_manage_power, - }; - --static const struct driver_info qmi_wwan_gobi = { -- .description = "Qualcomm Gobi wwan/QMI device", -+static const struct driver_info qmi_wwan_force_int0 = { -+ .description = "Qualcomm WWAN/QMI device", - .flags = FLAG_WWAN, -- .bind = qmi_wwan_bind_gobi, -+ .bind = qmi_wwan_bind_shared, - .unbind = qmi_wwan_unbind_shared, - .manage_power = qmi_wwan_manage_power, -+ .data = BIT(0), /* interface whitelist bitmap */ - }; - --/* ZTE suck at making USB descriptors */ - static const struct driver_info qmi_wwan_force_int1 = { - .description = "Qualcomm WWAN/QMI device", - .flags = FLAG_WWAN, -@@ -365,6 +342,15 @@ static const struct driver_info qmi_wwan_force_int1 = { - .data = BIT(1), /* interface whitelist bitmap */ - }; - -+static const struct driver_info qmi_wwan_force_int3 = { -+ .description = "Qualcomm WWAN/QMI device", -+ .flags = FLAG_WWAN, -+ .bind = qmi_wwan_bind_shared, -+ .unbind = qmi_wwan_unbind_shared, -+ .manage_power = qmi_wwan_manage_power, -+ .data = BIT(3), /* interface whitelist bitmap */ -+}; -+ - static const struct driver_info qmi_wwan_force_int4 = { - .description = "Qualcomm WWAN/QMI device", - .flags = FLAG_WWAN, -@@ -390,16 +376,23 @@ static const struct driver_info qmi_wwan_force_int4 = { - static const struct driver_info qmi_wwan_sierra = { - .description = "Sierra Wireless wwan/QMI device", - .flags = FLAG_WWAN, -- .bind = qmi_wwan_bind_gobi, -+ .bind = qmi_wwan_bind_shared, - .unbind = qmi_wwan_unbind_shared, - .manage_power = qmi_wwan_manage_power, - .data = BIT(8) | BIT(19), /* interface whitelist bitmap */ - }; - - #define HUAWEI_VENDOR_ID 0x12D1 -+ -+/* Gobi 1000 QMI/wwan interface number is 3 according to qcserial */ -+#define QMI_GOBI1K_DEVICE(vend, prod) \ -+ USB_DEVICE(vend, prod), \ -+ .driver_info = (unsigned long)&qmi_wwan_force_int3 -+ -+/* Gobi 2000 and Gobi 3000 QMI/wwan interface number is 0 according to qcserial */ - #define QMI_GOBI_DEVICE(vend, prod) \ - USB_DEVICE(vend, prod), \ -- .driver_info = (unsigned long)&qmi_wwan_gobi -+ .driver_info = (unsigned long)&qmi_wwan_force_int0 - - static const struct usb_device_id products[] = { - { /* Huawei E392, E398 and possibly others sharing both device id and more... */ -@@ -510,20 +503,24 @@ static const struct usb_device_id products[] = { - .bInterfaceProtocol = 0xff, - .driver_info = (unsigned long)&qmi_wwan_sierra, - }, -- {QMI_GOBI_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ -- {QMI_GOBI_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ -- {QMI_GOBI_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ -- {QMI_GOBI_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ -- {QMI_GOBI_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */ -- {QMI_GOBI_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ -- {QMI_GOBI_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ -- {QMI_GOBI_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */ -- {QMI_GOBI_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */ -- {QMI_GOBI_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */ -- {QMI_GOBI_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */ -- {QMI_GOBI_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */ -- {QMI_GOBI_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ -- {QMI_GOBI_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ -+ -+ /* Gobi 1000 devices */ -+ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ -+ {QMI_GOBI1K_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ -+ {QMI_GOBI1K_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ -+ {QMI_GOBI1K_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ -+ {QMI_GOBI1K_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */ -+ {QMI_GOBI1K_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ -+ {QMI_GOBI1K_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ -+ {QMI_GOBI1K_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */ -+ {QMI_GOBI1K_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */ -+ {QMI_GOBI1K_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */ -+ {QMI_GOBI1K_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */ -+ {QMI_GOBI1K_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */ -+ {QMI_GOBI1K_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ -+ {QMI_GOBI1K_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ -+ -+ /* Gobi 2000 and 3000 devices */ - {QMI_GOBI_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */ - {QMI_GOBI_DEVICE(0x05c6, 0x920b)}, /* Generic Gobi 2000 Modem device */ - {QMI_GOBI_DEVICE(0x05c6, 0x9225)}, /* Sony Gobi 2000 Modem device (N0279, VU730) */ --- -1.7.10.2 - diff --git a/rtl818x-fix-sleeping-function-called-from-invalid-context.patch b/rtl818x-fix-sleeping-function-called-from-invalid-context.patch deleted file mode 100644 index 141fcd201..000000000 --- a/rtl818x-fix-sleeping-function-called-from-invalid-context.patch +++ /dev/null @@ -1,49 +0,0 @@ -Fix: - -BUG: sleeping function called from invalid context at kernel/workqueue.c:2547 -in_atomic(): 1, irqs_disabled(): 0, pid: 629, name: wpa_supplicant -2 locks held by wpa_supplicant/629: - #0: (rtnl_mutex){+.+.+.}, at: [] rtnl_lock+0x14/0x20 - #1: (&trigger->leddev_list_lock){.+.?..}, at: [] led_trigger_event+0x21/0x80 -Pid: 629, comm: wpa_supplicant Not tainted 3.3.0-0.rc3.git5.1.fc17.i686 -Call Trace: - [] __might_sleep+0x126/0x1d0 - [] wait_on_work+0x2c/0x1d0 - [] __cancel_work_timer+0x6a/0x120 - [] cancel_delayed_work_sync+0x10/0x20 - [] rtl8187_led_brightness_set+0x82/0xf0 [rtl8187] - [] led_trigger_event+0x5c/0x80 - [] ieee80211_led_radio+0x1d/0x40 [mac80211] - [] ieee80211_stop_device+0x13/0x230 [mac80211] - -Removing _sync is ok, because if led_on work is currently running -it will be finished before led_off work start to perform, since -they are always queued on the same mac80211 local->workqueue. - -Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=795176 - -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/rtl818x/rtl8187/leds.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wireless/rtl818x/rtl8187/leds.c b/drivers/net/wireless/rtl818x/rtl8187/leds.c -index 2e0de2f..c2d5b49 100644 ---- a/drivers/net/wireless/rtl818x/rtl8187/leds.c -+++ b/drivers/net/wireless/rtl818x/rtl8187/leds.c -@@ -117,7 +117,7 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev, - radio_on = true; - } else if (radio_on) { - radio_on = false; -- cancel_delayed_work_sync(&priv->led_on); -+ cancel_delayed_work(&priv->led_on); - ieee80211_queue_delayed_work(hw, &priv->led_off, 0); - } - } else if (radio_on) { --- -1.7.1 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/sources b/sources index 274b06a6c..a65a00325 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 967f72983655e2479f951195953e8480 linux-3.4.tar.xz -58e6672d932d74d5e2b6811b9d37d67c patch-3.4.4.xz +e60f1d8032069d091f3692c1d7a89b8b patch-3.4.5.xz diff --git a/tg3-Apply-short-DMA-frag-workaround-to-5906.patch b/tg3-Apply-short-DMA-frag-workaround-to-5906.patch deleted file mode 100644 index 5cb78c7ca..000000000 --- a/tg3-Apply-short-DMA-frag-workaround-to-5906.patch +++ /dev/null @@ -1,32 +0,0 @@ -From b7abee6ef888117f92db370620ebf116a38e3f4d Mon Sep 17 00:00:00 2001 -From: Matt Carlson -Date: Thu, 7 Jun 2012 12:56:54 +0000 -Subject: [PATCH] tg3: Apply short DMA frag workaround to 5906 - -5906 devices also need the short DMA fragment workaround. This patch -makes the necessary change. - -Signed-off-by: Matt Carlson -Tested-by: Christian Kujau -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/broadcom/tg3.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c -index edeeb51..e47ff8b 100644 ---- a/drivers/net/ethernet/broadcom/tg3.c -+++ b/drivers/net/ethernet/broadcom/tg3.c -@@ -14275,7 +14275,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) - } - } - -- if (tg3_flag(tp, 5755_PLUS)) -+ if (tg3_flag(tp, 5755_PLUS) || -+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) - tg3_flag_set(tp, SHORT_DMA_BUG); - - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) --- -1.7.10.2 - diff --git a/thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch b/thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch deleted file mode 100644 index a91e9bbe4..000000000 --- a/thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-PAE.patch +++ /dev/null @@ -1,228 +0,0 @@ - -Delivered-To: jwboyer@gmail.com -Received: by 10.229.175.203 with SMTP id bb11csp66243qcb; - Fri, 8 Jun 2012 15:08:27 -0700 (PDT) -Received: by 10.68.222.133 with SMTP id qm5mr23412736pbc.113.1339193307132; - Fri, 08 Jun 2012 15:08:27 -0700 (PDT) -Return-Path: -Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) - by mx.google.com with ESMTP id ku9si12482578pbc.355.2012.06.08.15.08.24; - Fri, 08 Jun 2012 15:08:25 -0700 (PDT) -Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; -Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S964992Ab2FHWIW (ORCPT + 21 others); - Fri, 8 Jun 2012 18:08:22 -0400 -Received: from mail-bk0-f74.google.com ([209.85.214.74]:41783 "EHLO - mail-bk0-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with ESMTP id S964922Ab2FHWIV (ORCPT - ); Fri, 8 Jun 2012 18:08:21 -0400 -Received: by bkty5 with SMTP id y5so128736bkt.1 - for ; Fri, 08 Jun 2012 15:08:20 -0700 (PDT) -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=google.com; s=20120113; - h=subject:to:cc:from:date:message-id:x-gm-message-state; - bh=RSdNZSZcXg/enKaYIM+JR4+Bd890ieO+blY9bsk9giI=; - b=NwTZEmRSdqDAiTV/EW91GXpM/yrRd7CNzfPif0JcF0iFgxGAo4lB7W1I05vmrnPcCQ - Va+P6xXLWle2rAVQLsPooKdtb3u2wnNRDEGvBPZl2alje+qzhKGlQcVgnI5+KCM6GaS+ - YWoE+2gv5UFmF6JlelThyecGTyZ0D93K5aVYewSxg0H7KZ6BgvMnB/qJKFdScatv1uDH - g39MFwJzmD+DmNMn149jeUWYOLLTeMZJkymtJCLgxS8eJzQxXA0nes2Wz/pXCBdxXF2z - mft6LyzKtoEUDeTtalgm9zxkT4XJ+6bsAMEXBFgkcyNq0Ic8P79AP0ynlET2L/Ql3ARP - C5Sg== -Received: by 10.14.101.2 with SMTP id a2mr2823176eeg.6.1339193299969; - Fri, 08 Jun 2012 15:08:19 -0700 (PDT) -Received: from hpza10.eem.corp.google.com ([74.125.121.33]) - by gmr-mx.google.com with ESMTPS id d52si7345113eei.1.2012.06.08.15.08.19 - (version=TLSv1/SSLv3 cipher=AES128-SHA); - Fri, 08 Jun 2012 15:08:19 -0700 (PDT) -Received: from akpm.mtv.corp.google.com (akpm.mtv.corp.google.com [172.18.96.75]) - by hpza10.eem.corp.google.com (Postfix) with ESMTP id 9D09620004E; - Fri, 8 Jun 2012 15:08:19 -0700 (PDT) -Received: from localhost.localdomain (localhost [127.0.0.1]) - by akpm.mtv.corp.google.com (Postfix) with ESMTP id D5FACA0329; - Fri, 8 Jun 2012 15:08:18 -0700 (PDT) -Subject: + thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae.patch added to -mm tree -To: mm-commits@vger.kernel.org -Cc: aarcange@redhat.com, hughd@google.com, jbeulich@suse.com, - jrnieder@gmail.com, kosaki.motohiro@gmail.com, lwoodman@redhat.com, - mgorman@suse.de, pmatouse@redhat.com, riel@redhat.com, - stable@vger.kernel.org, uobergfe@redhat.com -From: akpm@linux-foundation.org -Date: Fri, 08 Jun 2012 15:08:18 -0700 -Message-Id: <20120608220818.D5FACA0329@akpm.mtv.corp.google.com> -X-Gm-Message-State: ALoCoQnqC0C+2OVVfC5Yi43jUu5vH03b/RBncPoI4SpE4HFSgaRrM+gM2J8rR6MMoba3nM/OmDAU -Sender: stable-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: stable@vger.kernel.org - - -The patch titled - Subject: thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE -has been added to the -mm tree. Its filename is - thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae.patch - -Before you just go and hit "reply", please: - a) Consider who else should be cc'ed - b) Prefer to cc a suitable mailing list as well - c) Ideally: find the original patch on the mailing list and do a - reply-to-all to that, adding suitable additional cc's - -*** Remember to use Documentation/SubmitChecklist when testing your code *** - -The -mm tree is included into linux-next and is updated -there every 3-4 working days - ------------------------------------------------------- -From: Andrea Arcangeli -Subject: thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE - -In the x86 32bit PAE CONFIG_TRANSPARENT_HUGEPAGE=y case while holding the -mmap_sem for reading, cmpxchg8b cannot be used to read pmd contents under -Xen. - -So instead of dealing only with "consistent" pmdvals in -pmd_none_or_trans_huge_or_clear_bad() (which would be conceptually -simpler) we let pmd_none_or_trans_huge_or_clear_bad() deal with pmdvals -where the low 32bit and high 32bit could be inconsistent (to avoid having -to use cmpxchg8b). - -The only guarantee we get from pmd_read_atomic is that if the low part of -the pmd was found null, the high part will be null too (so the pmd will be -considered unstable). And if the low part of the pmd is found "stable" -later, then it means the whole pmd was read atomically (because after a -pmd is stable, neither MADV_DONTNEED nor page faults can alter it anymore, -and we read the high part after the low part). - -In the 32bit PAE x86 case, it is enough to read the low part of the pmdval -atomically to declare the pmd as "stable" and that's true for THP and no -THP, furthermore in the THP case we also have a barrier() that will -prevent any inconsistent pmdvals to be cached by a later re-read of the -*pmd. - -Signed-off-by: Andrea Arcangeli -Cc: Jonathan Nieder -Cc: Ulrich Obergfell -Cc: Mel Gorman -Cc: Hugh Dickins -Cc: Larry Woodman -Cc: Petr Matousek -Cc: Rik van Riel -Cc: Jan Beulich -Cc: KOSAKI Motohiro -Cc: -Signed-off-by: Andrew Morton ---- - - arch/x86/include/asm/pgtable-3level.h | 30 +++++++++++++----------- - include/asm-generic/pgtable.h | 10 ++++++++ - 2 files changed, 27 insertions(+), 13 deletions(-) - -diff -puN arch/x86/include/asm/pgtable-3level.h~thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae arch/x86/include/asm/pgtable-3level.h ---- a/arch/x86/include/asm/pgtable-3level.h~thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae -+++ a/arch/x86/include/asm/pgtable-3level.h -@@ -47,16 +47,26 @@ static inline void native_set_pte(pte_t - * they can run pmd_offset_map_lock or pmd_trans_huge or other pmd - * operations. - * -- * Without THP if the mmap_sem is hold for reading, the -- * pmd can only transition from null to not null while pmd_read_atomic runs. -- * So there's no need of literally reading it atomically. -+ * Without THP if the mmap_sem is hold for reading, the pmd can only -+ * transition from null to not null while pmd_read_atomic runs. So -+ * we can always return atomic pmd values with this function. - * - * With THP if the mmap_sem is hold for reading, the pmd can become -- * THP or null or point to a pte (and in turn become "stable") at any -- * time under pmd_read_atomic, so it's mandatory to read it atomically -- * with cmpxchg8b. -+ * trans_huge or none or point to a pte (and in turn become "stable") -+ * at any time under pmd_read_atomic. We could read it really -+ * atomically here with a atomic64_read for the THP enabled case (and -+ * it would be a whole lot simpler), but to avoid using cmpxchg8b we -+ * only return an atomic pmdval if the low part of the pmdval is later -+ * found stable (i.e. pointing to a pte). And we're returning a none -+ * pmdval if the low part of the pmd is none. In some cases the high -+ * and low part of the pmdval returned may not be consistent if THP is -+ * enabled (the low part may point to previously mapped hugepage, -+ * while the high part may point to a more recently mapped hugepage), -+ * but pmd_none_or_trans_huge_or_clear_bad() only needs the low part -+ * of the pmd to be read atomically to decide if the pmd is unstable -+ * or not, with the only exception of when the low part of the pmd is -+ * zero in which case we return a none pmd. - */ --#ifndef CONFIG_TRANSPARENT_HUGEPAGE - static inline pmd_t pmd_read_atomic(pmd_t *pmdp) - { - pmdval_t ret; -@@ -74,12 +84,6 @@ static inline pmd_t pmd_read_atomic(pmd_ - - return (pmd_t) { ret }; - } --#else /* CONFIG_TRANSPARENT_HUGEPAGE */ --static inline pmd_t pmd_read_atomic(pmd_t *pmdp) --{ -- return (pmd_t) { atomic64_read((atomic64_t *)pmdp) }; --} --#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ - - static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) - { -diff -puN include/asm-generic/pgtable.h~thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae include/asm-generic/pgtable.h ---- a/include/asm-generic/pgtable.h~thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae -+++ a/include/asm-generic/pgtable.h -@@ -484,6 +484,16 @@ static inline int pmd_none_or_trans_huge - /* - * The barrier will stabilize the pmdval in a register or on - * the stack so that it will stop changing under the code. -+ * -+ * When CONFIG_TRANSPARENT_HUGEPAGE=y on x86 32bit PAE, -+ * pmd_read_atomic is allowed to return a not atomic pmdval -+ * (for example pointing to an hugepage that has never been -+ * mapped in the pmd). The below checks will only care about -+ * the low part of the pmd with 32bit PAE x86 anyway, with the -+ * exception of pmd_none(). So the important thing is that if -+ * the low part of the pmd is found null, the high part will -+ * be also null or the pmd_none() check below would be -+ * confused. - */ - #ifdef CONFIG_TRANSPARENT_HUGEPAGE - barrier(); -_ -Subject: Subject: thp: avoid atomic64_read in pmd_read_atomic for 32bit PAE - -Patches currently in -mm which might be from aarcange@redhat.com are - -origin.patch -linux-next.patch -mm-fix-slab-page-_count-corruption-when-using-slub.patch -thp-avoid-atomic64_read-in-pmd_read_atomic-for-32bit-pae.patch -hugetlb-rename-max_hstate-to-hugetlb_max_hstate.patch -hugetlbfs-dont-use-err_ptr-with-vm_fault-values.patch -hugetlbfs-add-an-inline-helper-for-finding-hstate-index.patch -hugetlbfs-add-an-inline-helper-for-finding-hstate-index-fix.patch -hugetlb-use-mmu_gather-instead-of-a-temporary-linked-list-for-accumulating-pages.patch -hugetlb-use-mmu_gather-instead-of-a-temporary-linked-list-for-accumulating-pages-fix.patch -hugetlb-use-mmu_gather-instead-of-a-temporary-linked-list-for-accumulating-pages-fix-fix.patch -hugetlb-avoid-taking-i_mmap_mutex-in-unmap_single_vma-for-hugetlb.patch -hugetlb-simplify-migrate_huge_page.patch -hugetlb-simplify-migrate_huge_page-fix.patch -memcg-add-hugetlb-extension.patch -memcg-add-hugetlb-extension-fix.patch -memcg-add-hugetlb-extension-fix-fix.patch -hugetlb-add-charge-uncharge-calls-for-hugetlb-alloc-free.patch -memcg-track-resource-index-in-cftype-private.patch -hugetlbfs-add-memcg-control-files-for-hugetlbfs.patch -hugetlbfs-add-memcg-control-files-for-hugetlbfs-use-scnprintf-instead-of-sprintf.patch -hugetlbfs-add-memcg-control-files-for-hugetlbfs-use-scnprintf-instead-of-sprintf-fix.patch -hugetlbfs-add-a-list-for-tracking-in-use-hugetlb-pages.patch -memcg-move-hugetlb-resource-count-to-parent-cgroup-on-memcg-removal.patch -memcg-move-hugetlb-resource-count-to-parent-cgroup-on-memcg-removal-fix.patch -memcg-move-hugetlb-resource-count-to-parent-cgroup-on-memcg-removal-fix-fix.patch -hugetlb-migrate-memcg-info-from-oldpage-to-new-page-during-migration.patch -memcg-add-memory-controller-documentation-for-hugetlb-management.patch - --- -To unsubscribe from this list: send the line "unsubscribe stable" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/usb-storage-try-read_capacity-10-first.patch b/usb-storage-try-read_capacity-10-first.patch deleted file mode 100644 index c9791cdc1..000000000 --- a/usb-storage-try-read_capacity-10-first.patch +++ /dev/null @@ -1,130 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Alan Stern -Newsgroups: gmane.linux.usb.general -Subject: Re: USB mass-storage devices and READ CAPACITY(16) -Date: Sun, 17 Jun 2012 11:26:31 -0400 (EDT) -Lines: 81 -Approved: news@gmane.org -Message-ID: -References: -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=US-ASCII -X-Trace: dough.gmane.org 1339946799 1694 80.91.229.3 (17 Jun 2012 15:26:39 GMT) -X-Complaints-To: usenet@dough.gmane.org -NNTP-Posting-Date: Sun, 17 Jun 2012 15:26:39 +0000 (UTC) -Cc: Torsten Wohlfarth , - Sturm Flut , - Sergey , - Philippe Valembois - Phil - , - USB list -To: Hans de Goede -Original-X-From: linux-usb-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Sun Jun 17 17:26:37 2012 -Return-path: -Envelope-to: glug-linux-usb-wOFGN7rlS/M9smdsby/KFg@public.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1SgHN3-0002d5-Pq - for glug-linux-usb-wOFGN7rlS/M9smdsby/KFg@public.gmane.org; Sun, 17 Jun 2012 17:26:34 +0200 -Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand - id S1757469Ab2FQP0d (ORCPT ); - Sun, 17 Jun 2012 11:26:33 -0400 -Original-Received: from netrider.rowland.org ([192.131.102.5]:55086 "HELO - netrider.rowland.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org - with SMTP id S1757447Ab2FQP0c (ORCPT - ); Sun, 17 Jun 2012 11:26:32 -0400 -Original-Received: (qmail 16789 invoked by uid 500); 17 Jun 2012 11:26:31 -0400 -Original-Received: from localhost (sendmail-bs-savSHZN5Fh8qMp+WYRx65w@public.gmane.org) - by localhost with SMTP; 17 Jun 2012 11:26:31 -0400 -X-X-Sender: stern-pYrvlCTfrz9XsRXLowluHWD2FQJk+8+b@public.gmane.org -In-Reply-To: -Original-Sender: linux-usb-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Precedence: bulk -List-ID: -X-Mailing-List: linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -Xref: news.gmane.org gmane.linux.usb.general:65976 -Archived-At: - -On Fri, 15 Jun 2012, Alan Stern wrote: - -> On Fri, 15 Jun 2012, Hans de Goede wrote: -> -> > Hi, -> > -> > On 06/15/2012 08:20 PM, Alan Stern wrote: -> > > As we can see from recent bug reports, a lot of USB mass-storage -> > > devices cannot handle READ CAPACITY(16) commands properly. They send -> > > back garbage and are unusable as a result. -> > > -> > > Should we go ahead and set a flag on all these devices, telling the sd -> > > driver to try READ CAPACITY(10) first? That's a lot easier than adding -> > > more and more entries to unusual_devs.h. -> > -> > That certainly sound reasonable to me. Note that the 071b:3203 really -> > needs the US_FL_NO_READ_CAPACITY_16 flag though, as it wrongly reports -> > a capacity of -1 when there is no sd card in its slot, and in response -> > to that the kernel tries READ CAPACITY(16) and things go downhill -> > from there... -> -> Yes, we need to be able to have both flags set for the same device. -> For that card reader they would mean try READ CAPACITY(10) first, and -> if it fails, don't try READ CAPACITY(16). - -In other words, I'm suggesting we adopt this patch and get rid Hans's -new unusual_devs entry. - -Alan Stern - - - - -Index: usb-3.4/include/scsi/scsi_device.h -=================================================================== ---- usb-3.4.orig/include/scsi/scsi_device.h -+++ usb-3.4/include/scsi/scsi_device.h -@@ -151,6 +151,7 @@ struct scsi_device { - SD_LAST_BUGGY_SECTORS */ - unsigned no_read_disc_info:1; /* Avoid READ_DISC_INFO cmds */ - unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */ -+ unsigned try_rc_10_first:1; /* Try READ_CAPACACITY_10 first */ - unsigned is_visible:1; /* is the device visible in sysfs */ - - DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */ -Index: usb-3.4/drivers/scsi/sd.c -=================================================================== ---- usb-3.4.orig/drivers/scsi/sd.c -+++ usb-3.4/drivers/scsi/sd.c -@@ -1899,6 +1899,8 @@ static int sd_try_rc16_first(struct scsi - { - if (sdp->host->max_cmd_len < 16) - return 0; -+ if (sdp->try_rc_10_first) -+ return 0; - if (sdp->scsi_level > SCSI_SPC_2) - return 1; - if (scsi_device_protection(sdp)) -Index: usb-3.4/drivers/usb/storage/scsiglue.c -=================================================================== ---- usb-3.4.orig/drivers/usb/storage/scsiglue.c -+++ usb-3.4/drivers/usb/storage/scsiglue.c -@@ -202,6 +202,12 @@ static int slave_configure(struct scsi_d - if (us->fflags & US_FL_NO_READ_CAPACITY_16) - sdev->no_read_capacity_16 = 1; - -+ /* -+ * Many devices do not respond properly to READ_CAPACITY_16. -+ * Tell the SCSI layer to try READ_CAPACITY_10 first. -+ */ -+ sdev->try_rc_10_first = 1; -+ - /* assume SPC3 or latter devices support sense size > 18 */ - if (sdev->scsi_level > SCSI_SPC_2) - us->fflags |= US_FL_SANE_SENSE; - --- -To unsubscribe from this list: send the line "unsubscribe linux-usb" in -the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - diff --git a/xen-blkback-Copy-id-field-when-doing-BLKIF_DISCARD.patch b/xen-blkback-Copy-id-field-when-doing-BLKIF_DISCARD.patch deleted file mode 100644 index 056d79b15..000000000 --- a/xen-blkback-Copy-id-field-when-doing-BLKIF_DISCARD.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 8c9ce606a60e4a0cb447bdc082ce383b96b227b4 Mon Sep 17 00:00:00 2001 -From: Konrad Rzeszutek Wilk -Date: Fri, 25 May 2012 16:11:09 -0400 -Subject: [PATCH] xen/blkback: Copy id field when doing BLKIF_DISCARD. - -We weren't copying the id field so when we sent the response -back to the frontend (especially with a 64-bit host and 32-bit -guest), we ended up using a random value. This lead to the -frontend crashing as it would try to pass to __blk_end_request_all -a NULL 'struct request' (b/c it would use the 'id' to find the -proper 'struct request' in its shadow array) and end up crashing: - -BUG: unable to handle kernel NULL pointer dereference at 000000e4 -IP: [] __blk_end_request_all+0xc/0x40 -.. snip.. -EIP is at __blk_end_request_all+0xc/0x40 -.. snip.. - [] blkif_interrupt+0x172/0x330 [xen_blkfront] - -This fixes the bug by passing in the proper id for the response. - -Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=824641 - -CC: stable@kernel.org -Tested-by: William Dauchy -Acked-by: Stefano Stabellini -Signed-off-by: Konrad Rzeszutek Wilk ---- - drivers/block/xen-blkback/common.h | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h -index 773cf27..9ad3b5e 100644 ---- a/drivers/block/xen-blkback/common.h -+++ b/drivers/block/xen-blkback/common.h -@@ -257,6 +257,7 @@ static inline void blkif_get_x86_32_req(struct blkif_request *dst, - break; - case BLKIF_OP_DISCARD: - dst->u.discard.flag = src->u.discard.flag; -+ dst->u.discard.id = src->u.discard.id; - dst->u.discard.sector_number = src->u.discard.sector_number; - dst->u.discard.nr_sectors = src->u.discard.nr_sectors; - break; -@@ -287,6 +288,7 @@ static inline void blkif_get_x86_64_req(struct blkif_request *dst, - break; - case BLKIF_OP_DISCARD: - dst->u.discard.flag = src->u.discard.flag; -+ dst->u.discard.id = src->u.discard.id; - dst->u.discard.sector_number = src->u.discard.sector_number; - dst->u.discard.nr_sectors = src->u.discard.nr_sectors; - break; --- -1.7.10.4 - From 9358096eaf687c7feafc0dc7b9e693392d7630cf Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 18 Jul 2012 09:12:02 -0400 Subject: [PATCH 414/487] check return value of power_supply_register from Lan Tianyu (rhbz 772730) --- ...eturn-value-of-power_supply_register.patch | 37 +++++++++++++++++++ kernel.spec | 11 +++++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 ACPI-AC-check-the-return-value-of-power_supply_register.patch diff --git a/ACPI-AC-check-the-return-value-of-power_supply_register.patch b/ACPI-AC-check-the-return-value-of-power_supply_register.patch new file mode 100644 index 000000000..c9eb1a17d --- /dev/null +++ b/ACPI-AC-check-the-return-value-of-power_supply_register.patch @@ -0,0 +1,37 @@ +In the ac.c, lack check return value of power_supply_register(). +This may casue that acpi driver's add() ops was called successful +while the device may be failed to be initalized. For example, some +ugly bios may describe two ACADs in the same dsdt. They use the same +name which will cause the second ACAD device can no be registered. +And then power_supply_register() failed. But acpi driver's add() ops +is called sucessfully. The acpi device also will receive acpi notification +and cause oops. + https://bugzilla.redhat.com/show_bug.cgi?id=772730 + +Signed-off-by: Lan Tianyu +--- + drivers/acpi/ac.c | 4 +++- + 1 files changed, 3 insertions(+), 1 deletions(-) + +diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c +index 6512b20..d1fcbc0 100644 +--- a/drivers/acpi/ac.c ++++ b/drivers/acpi/ac.c +@@ -292,7 +292,9 @@ static int acpi_ac_add(struct acpi_device *device) + ac->charger.properties = ac_props; + ac->charger.num_properties = ARRAY_SIZE(ac_props); + ac->charger.get_property = get_ac_property; +- power_supply_register(&ac->device->dev, &ac->charger); ++ result = power_supply_register(&ac->device->dev, &ac->charger); ++ if (result) ++ goto end; + + printk(KERN_INFO PREFIX "%s [%s] (%s)\n", + acpi_device_name(device), acpi_device_bid(device), +-- +1.7.6.rc2.8.g28eb + +-- +To unsubscribe from this list: send the line "unsubscribe linux-acpi" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index 78789c710..52569d1cf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -767,6 +767,9 @@ Patch22056: crypto-aesni-intel-fix-wrong-kfree-pointer.patch #rhbz 834318 Patch22057: ACPICA-Fix-possible-fault-in-return-package-object-repair-code.patch +#rhbz 772730 +Patch22058: ACPI-AC-check-the-return-value-of-power_supply_register.patch + # END OF PATCH DEFINITIONS %endif @@ -1421,6 +1424,9 @@ ApplyPatch crypto-aesni-intel-fix-wrong-kfree-pointer.patch #rhbz 834318 ApplyPatch ACPICA-Fix-possible-fault-in-return-package-object-repair-code.patch +#rhbz 772730 +ApplyPatch ACPI-AC-check-the-return-value-of-power_supply_register.patch + # END OF PATCH APPLICATIONS %endif @@ -2159,6 +2165,9 @@ fi # and build. %changelog +* Wed Jul 18 2012 Josh Boyer +- check return value of power_supply_register from Lan Tianyu (rhbz 772730) + * Mon Jul 16 2012 Josh Boyer - 3.4.5-1 - Linux v3.4.5 From 83ce91e6c28de64a299ea4a0bbf2e7c6ebd06b13 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 19 Jul 2012 16:27:37 -0400 Subject: [PATCH 415/487] Linux v3.4.6 --- ...in-return-package-object-repair-code.patch | 44 ----- ...k-fix-infinite-loop-in-__getblk_slow.patch | 153 ------------------ kernel.spec | 25 +-- ...ix-indexes-ordering-on-RX-queue-kick.patch | 43 ----- sources | 2 +- 5 files changed, 6 insertions(+), 261 deletions(-) delete mode 100644 ACPICA-Fix-possible-fault-in-return-package-object-repair-code.patch delete mode 100644 block-fix-infinite-loop-in-__getblk_slow.patch delete mode 100644 rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch diff --git a/ACPICA-Fix-possible-fault-in-return-package-object-repair-code.patch b/ACPICA-Fix-possible-fault-in-return-package-object-repair-code.patch deleted file mode 100644 index c8956b810..000000000 --- a/ACPICA-Fix-possible-fault-in-return-package-object-repair-code.patch +++ /dev/null @@ -1,44 +0,0 @@ -From: Bob Moore - -Fixes a problem that can occur when a lone package object is -wrapped with an outer package object in order to conform to -the ACPI specification. Can affect these predefined names: -_ALR,_MLS,_PSS,_TRT,_TSS,_PRT,_HPX,_DLM,_CSD,_PSD,_TSD - -https://bugzilla.kernel.org/show_bug.cgi?id=44171 - -Reported-by: Vlastimil Babka -Signed-off-by: Bob Moore -Signed-off-by: Lin Ming ---- - -Len, - -This is an important bug fix. -Could you merge it? - - drivers/acpi/acpica/nspredef.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c -index 23ce096..fe66260 100644 ---- a/drivers/acpi/acpica/nspredef.c -+++ b/drivers/acpi/acpica/nspredef.c -@@ -638,7 +638,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data, - /* Create the new outer package and populate it */ - - status = -- acpi_ns_wrap_with_package(data, *elements, -+ acpi_ns_wrap_with_package(data, return_object, - return_object_ptr); - if (ACPI_FAILURE(status)) { - return (status); --- -1.7.2.5 - - - --- -To unsubscribe from this list: send the line "unsubscribe linux-acpi" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/block-fix-infinite-loop-in-__getblk_slow.patch b/block-fix-infinite-loop-in-__getblk_slow.patch deleted file mode 100644 index f075a7133..000000000 --- a/block-fix-infinite-loop-in-__getblk_slow.patch +++ /dev/null @@ -1,153 +0,0 @@ - -Delivered-To: jwboyer@gmail.com -Received: by 10.229.191.66 with SMTP id dl2csp36421qcb; - Tue, 26 Jun 2012 07:55:48 -0700 (PDT) -Received: by 10.68.228.136 with SMTP id si8mr53042278pbc.159.1340722548310; - Tue, 26 Jun 2012 07:55:48 -0700 (PDT) -Return-Path: -Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) - by mx.google.com with ESMTP id qg1si15735731pbc.300.2012.06.26.07.55.47; - Tue, 26 Jun 2012 07:55:48 -0700 (PDT) -Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; -Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1757370Ab2FZOzp (ORCPT - + 23 others); Tue, 26 Jun 2012 10:55:45 -0400 -Received: from mx1.redhat.com ([209.132.183.28]:64097 "EHLO mx1.redhat.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1757325Ab2FZOzo (ORCPT ); - Tue, 26 Jun 2012 10:55:44 -0400 -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q5QEtbK2017450 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); - Tue, 26 Jun 2012 10:55:38 -0400 -Received: from segfault.boston.devel.redhat.com (segfault.boston.devel.redhat.com [10.16.60.26]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q5QEtZV9023431; - Tue, 26 Jun 2012 10:55:35 -0400 -From: Jeff Moyer -To: Jens Axboe , Nick Piggin -Cc: LKML List , - torsten.hilbrich@secunet.com, Richard Jones , - stable@vger.kernel.org, Marcos Mello -Subject: [patch] block: fix infinite loop in __getblk_slow -X-PGP-KeyID: 1F78E1B4 -X-PGP-CertKey: F6FE 280D 8293 F72C 65FD 5A58 1FF8 A7CA 1F78 E1B4 -X-PCLoadLetter: What the f**k does that mean? -Date: Tue, 26 Jun 2012 10:55:34 -0400 -Message-ID: -User-Agent: Gnus/5.110011 (No Gnus v0.11) Emacs/23.1 (gnu/linux) -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 -Sender: stable-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: stable@vger.kernel.org - -Hi, - -This commit: - -commit 080399aaaf3531f5b8761ec0ac30ff98891e8686 -Author: Jeff Moyer -Date: Fri May 11 16:34:10 2012 +0200 - - block: don't mark buffers beyond end of disk as mapped - -exposed a bug in __getblk_slow that causes mount to hang as it loops -infinitely waiting for a buffer that lies beyond the end of the disk to -become uptodate. The problem was initially reported by Torsten Hilbrich -here: https://lkml.org/lkml/2012/6/18/54, and also reported -independently here: -http://www.sysresccd.org/forums/viewtopic.php?f=13&t=4511, and then -Richard W.M. Jones and Marcos Mello noted a few separate bugzillas also -associated with the same issue. - -The main problem is here, in __getblk_slow: - - for (;;) { - struct buffer_head * bh; - int ret; - - bh = __find_get_block(bdev, block, size); - if (bh) - return bh; - - ret = grow_buffers(bdev, block, size); - if (ret < 0) - return NULL; - if (ret == 0) - free_more_memory(); - } - -__find_get_block does not find the block, since it will not be marked as -mapped, and so grow_buffers is called to fill in the buffers for the -associated page. I believe the for (;;) loop is there primarily to -retry in the case of memory pressure keeping grow_buffers from -succeeding. However, we also continue to loop for other cases, like the -block lying beond the end of the disk. So, the fix I came up with is to -only loop when grow_buffers fails due to memory allocation issues -(return value of 0). - -The attached patch was tested by myself, Torsten, and Rich, and was -found to resolve the problem in call cases. - -Comments, as always, are appreciated. - -Signed-off-by: Jeff Moyer -Reported-and-Tested-by: Torsten Hilbrich -Tested-by: Richard W.M. Jones -Cc: Stable - --- -Stable Notes: this patch requires backport to 3.0, 3.2 and 3.3. - -diff --git a/fs/buffer.c b/fs/buffer.c -index 838a9cf..c7062c8 100644 ---- a/fs/buffer.c -+++ b/fs/buffer.c -@@ -1036,6 +1036,9 @@ grow_buffers(struct block_device *bdev, sector_t block, int size) - static struct buffer_head * - __getblk_slow(struct block_device *bdev, sector_t block, int size) - { -+ int ret; -+ struct buffer_head *bh; -+ - /* Size must be multiple of hard sectorsize */ - if (unlikely(size & (bdev_logical_block_size(bdev)-1) || - (size < 512 || size > PAGE_SIZE))) { -@@ -1048,20 +1051,21 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size) - return NULL; - } - -- for (;;) { -- struct buffer_head * bh; -- int ret; -+retry: -+ bh = __find_get_block(bdev, block, size); -+ if (bh) -+ return bh; - -+ ret = grow_buffers(bdev, block, size); -+ if (ret == 0) { -+ free_more_memory(); -+ goto retry; -+ } else if (ret > 0) { - bh = __find_get_block(bdev, block, size); - if (bh) - return bh; -- -- ret = grow_buffers(bdev, block, size); -- if (ret < 0) -- return NULL; -- if (ret == 0) -- free_more_memory(); - } -+ return NULL; - } - - /* --- -To unsubscribe from this list: send the line "unsubscribe stable" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/kernel.spec b/kernel.spec index 52569d1cf..420764e09 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 5 +%define stable_update 6 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -754,19 +754,10 @@ Patch30010: debug-808990.patch #rhbz 749276 Patch22018: atl1c_net_next_update-3.4.patch -#rhbz 835019 -Patch22036: block-fix-infinite-loop-in-__getblk_slow.patch - -#rhbz 828824 -Patch22043: rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch - #Fix FIPS for aesni hardare Patch22055: crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch Patch22056: crypto-aesni-intel-fix-wrong-kfree-pointer.patch -#rhbz 834318 -Patch22057: ACPICA-Fix-possible-fault-in-return-package-object-repair-code.patch - #rhbz 772730 Patch22058: ACPI-AC-check-the-return-value-of-power_supply_register.patch @@ -1411,19 +1402,10 @@ ApplyPatch debug-808990.patch #rhbz 749276 ApplyPatch atl1c_net_next_update-3.4.patch -#rhbz 835019 -ApplyPatch block-fix-infinite-loop-in-__getblk_slow.patch - -#rhbz 828824 -ApplyPatch rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch - #Fix FIPS for aesni hardare ApplyPatch crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch ApplyPatch crypto-aesni-intel-fix-wrong-kfree-pointer.patch -#rhbz 834318 -ApplyPatch ACPICA-Fix-possible-fault-in-return-package-object-repair-code.patch - #rhbz 772730 ApplyPatch ACPI-AC-check-the-return-value-of-power_supply_register.patch @@ -2165,6 +2147,9 @@ fi # and build. %changelog +* Thu Jul 19 2012 Josh Boyer - 3.4.6-1 +- Linux v3.4.6 + * Wed Jul 18 2012 Josh Boyer - check return value of power_supply_register from Lan Tianyu (rhbz 772730) diff --git a/rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch b/rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch deleted file mode 100644 index 76b83cca4..000000000 --- a/rt2x00usb-fix-indexes-ordering-on-RX-queue-kick.patch +++ /dev/null @@ -1,43 +0,0 @@ -From e899a84a6e9bec0ce653713a48ca121cd754430c Mon Sep 17 00:00:00 2001 -From: Stanislaw Gruszka -Date: Mon, 2 Jul 2012 09:42:14 +0200 -Subject: [PATCH] rt2x00usb: fix indexes ordering on RX queue kick - -On rt2x00_dmastart() we increase index specified by Q_INDEX and on -rt2x00_dmadone() we increase index specified by Q_INDEX_DONE. So entries -between Q_INDEX_DONE and Q_INDEX are those we currently process in the -hardware. Entries between Q_INDEX and Q_INDEX_DONE are those we can -submit to the hardware. - -According to that fix rt2x00usb_kick_queue(), as we need to submit rx -entries that are not processed by the hardware. It worked before only -for empty queue, otherwise was broken. - -Note that for TX queues indexes ordering are ok. We need to kick entries -that have filled skb, but was not submitted to the hardware, i.e. -strted from Q_INDEX_DONE and have ENTRY_DATA_PENDING bit set. - -From practical standpoint this patch fixes AP mode connection hangs. - -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/rt2x00/rt2x00usb.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c -index d357d1e..74ecc33 100644 ---- a/drivers/net/wireless/rt2x00/rt2x00usb.c -+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c -@@ -436,8 +436,8 @@ void rt2x00usb_kick_queue(struct data_queue *queue) - case QID_RX: - if (!rt2x00queue_full(queue)) - rt2x00queue_for_each_entry(queue, -- Q_INDEX_DONE, - Q_INDEX, -+ Q_INDEX_DONE, - NULL, - rt2x00usb_kick_rx_entry); - break; --- -1.7.1 - diff --git a/sources b/sources index a65a00325..6f10d0c05 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 967f72983655e2479f951195953e8480 linux-3.4.tar.xz -e60f1d8032069d091f3692c1d7a89b8b patch-3.4.5.xz +14443e53d3ab88e6eac45d954d891e00 patch-3.4.6.xz From 0e04e7c4764f828f62c0b6d61f1b0cb7e862e0a7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 24 Jul 2012 12:59:03 -0400 Subject: [PATCH 416/487] Add patch to fix cpu pinning after suspend/resume (rhbz 714271) --- ...s-suspend-Dont-modify-cpusets-during.patch | 139 ++++++++++++++++++ kernel.spec | 11 +- 2 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch diff --git a/CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch b/CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch new file mode 100644 index 000000000..f57eceed9 --- /dev/null +++ b/CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch @@ -0,0 +1,139 @@ +From 0c1508129adc051fabaf8debefea79baa2f1a81b Mon Sep 17 00:00:00 2001 +From: "Srivatsa S. Bhat" +Date: Thu, 24 May 2012 19:46:26 +0530 +Subject: [PATCH] CPU hotplug, cpusets, suspend: Don't modify cpusets during + suspend/resume + +In the event of CPU hotplug, the kernel modifies the cpusets' cpus_allowed +masks as and when necessary to ensure that the tasks belonging to the cpusets +have some place (online CPUs) to run on. And regular CPU hotplug is +destructive in the sense that the kernel doesn't remember the original cpuset +configurations set by the user, across hotplug operations. + +However, suspend/resume (which uses CPU hotplug) is a special case in which +the kernel has the responsibility to restore the system (during resume), to +exactly the same state it was in before suspend. + +In order to achieve that, do the following: + +1. Don't modify cpusets during suspend/resume. At all. + In particular, don't move the tasks from one cpuset to another, and + don't modify any cpuset's cpus_allowed mask. So, simply ignore cpusets + during the CPU hotplug operations that are carried out in the + suspend/resume path. + +2. However, cpusets and sched domains are related. We just want to avoid + altering cpusets alone. So, to keep the sched domains updated, build + a single sched domain (containing all active cpus) during each of the + CPU hotplug operations carried out in s/r path, effectively ignoring + the cpusets' cpus_allowed masks. + + (Since userspace is frozen while doing all this, it will go unnoticed.) + +3. During the last CPU online operation during resume, build the sched + domains by looking up the (unaltered) cpusets' cpus_allowed masks. + That will bring back the system to the same original state as it was in + before suspend. + +Ultimately, this will not only solve the cpuset problem related to suspend +resume (ie., restores the cpusets to exactly what it was before suspend, by +not touching it at all) but also speeds up suspend/resume because we avoid +running cpuset update code for every CPU being offlined/onlined. + +Signed-off-by: Srivatsa S. Bhat +Signed-off-by: Peter Zijlstra +Cc: Linus Torvalds +Cc: Andrew Morton +Cc: Thomas Gleixner +Link: http://lkml.kernel.org/r/20120524141611.3692.20155.stgit@srivatsabhat.in.ibm.com +Signed-off-by: Ingo Molnar +--- + kernel/cpuset.c | 3 +++ + kernel/sched/core.c | 40 ++++++++++++++++++++++++++++++++++++---- + 2 files changed, 39 insertions(+), 4 deletions(-) + +--- linux-3.4.6-3.1.fc17.noarch.orig/kernel/cpuset.c ++++ linux-3.4.6-3.1.fc17.noarch/kernel/cpuset.c +@@ -2065,6 +2065,9 @@ static void scan_for_empty_cpusets(struc + * (of no affect) on systems that are actively using CPU hotplug + * but making no active use of cpusets. + * ++ * The only exception to this is suspend/resume, where we don't ++ * modify cpusets at all. ++ * + * This routine ensures that top_cpuset.cpus_allowed tracks + * cpu_active_mask on each CPU hotplug (cpuhp) event. + * +--- linux-3.4.6-3.1.fc17.noarch.orig/kernel/sched/core.c ++++ linux-3.4.6-3.1.fc17.noarch/kernel/sched/core.c +@@ -6931,34 +6931,66 @@ int __init sched_create_sysfs_power_savi + } + #endif /* CONFIG_SCHED_MC || CONFIG_SCHED_SMT */ + ++static int num_cpus_frozen; /* used to mark begin/end of suspend/resume */ ++ + /* + * Update cpusets according to cpu_active mask. If cpusets are + * disabled, cpuset_update_active_cpus() becomes a simple wrapper + * around partition_sched_domains(). ++ * ++ * If we come here as part of a suspend/resume, don't touch cpusets because we ++ * want to restore it back to its original state upon resume anyway. + */ + static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action, + void *hcpu) + { +- switch (action & ~CPU_TASKS_FROZEN) { ++ switch (action) { ++ case CPU_ONLINE_FROZEN: ++ case CPU_DOWN_FAILED_FROZEN: ++ ++ /* ++ * num_cpus_frozen tracks how many CPUs are involved in suspend ++ * resume sequence. As long as this is not the last online ++ * operation in the resume sequence, just build a single sched ++ * domain, ignoring cpusets. ++ */ ++ num_cpus_frozen--; ++ if (likely(num_cpus_frozen)) { ++ partition_sched_domains(1, NULL, NULL); ++ break; ++ } ++ ++ /* ++ * This is the last CPU online operation. So fall through and ++ * restore the original sched domains by considering the ++ * cpuset configurations. ++ */ ++ + case CPU_ONLINE: + case CPU_DOWN_FAILED: + cpuset_update_active_cpus(); +- return NOTIFY_OK; ++ break; + default: + return NOTIFY_DONE; + } ++ return NOTIFY_OK; + } + + static int cpuset_cpu_inactive(struct notifier_block *nfb, unsigned long action, + void *hcpu) + { +- switch (action & ~CPU_TASKS_FROZEN) { ++ switch (action) { + case CPU_DOWN_PREPARE: + cpuset_update_active_cpus(); +- return NOTIFY_OK; ++ break; ++ case CPU_DOWN_PREPARE_FROZEN: ++ num_cpus_frozen++; ++ partition_sched_domains(1, NULL, NULL); ++ break; + default: + return NOTIFY_DONE; + } ++ return NOTIFY_OK; + } + + void __init sched_init_smp(void) diff --git a/kernel.spec b/kernel.spec index 420764e09..2069a06c8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -761,6 +761,9 @@ Patch22056: crypto-aesni-intel-fix-wrong-kfree-pointer.patch #rhbz 772730 Patch22058: ACPI-AC-check-the-return-value-of-power_supply_register.patch +#rhbz 714271 +Patch22060: CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch + # END OF PATCH DEFINITIONS %endif @@ -1409,6 +1412,9 @@ ApplyPatch crypto-aesni-intel-fix-wrong-kfree-pointer.patch #rhbz 772730 ApplyPatch ACPI-AC-check-the-return-value-of-power_supply_register.patch +#rhbz 714271 +ApplyPatch CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch + # END OF PATCH APPLICATIONS %endif @@ -2147,6 +2153,9 @@ fi # and build. %changelog +* Wed Jul 25 2012 Josh Boyer +- Add patch to fix cpu pinning after suspend/resume (rhbz 714271) + * Thu Jul 19 2012 Josh Boyer - 3.4.6-1 - Linux v3.4.6 From 4277cc49acc8f5dded21d504a00aa614d3874e4f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 25 Jul 2012 16:33:25 -0400 Subject: [PATCH 417/487] Drop ARM support. It isn't built in F16. --- Makefile.config | 56 - arm-omap-dt-compat.patch | 42 - ...reading-mac-address-from-device-tree.patch | 92 -- config-arm-generic | 365 ------ config-arm-highbank | 31 - config-arm-imx | 89 -- config-arm-kirkwood | 54 - config-arm-omap-generic | 1086 ----------------- config-arm-tegra | 99 -- kernel.spec | 135 +- 10 files changed, 3 insertions(+), 2046 deletions(-) delete mode 100644 arm-omap-dt-compat.patch delete mode 100644 arm-smsc-support-reading-mac-address-from-device-tree.patch delete mode 100644 config-arm-generic delete mode 100644 config-arm-highbank delete mode 100644 config-arm-imx delete mode 100644 config-arm-kirkwood delete mode 100644 config-arm-omap-generic delete mode 100644 config-arm-tegra diff --git a/Makefile.config b/Makefile.config index 331aa46b9..0e6587f56 100644 --- a/Makefile.config +++ b/Makefile.config @@ -9,11 +9,6 @@ CONFIGFILES = \ $(CFG)-i686-PAE.config $(CFG)-i686-PAEdebug.config \ $(CFG)-x86_64.config $(CFG)-x86_64-debug.config \ $(CFG)-s390x.config \ - $(CFG)-arm.config $(CFG)-armv5tel.config \ - $(CFG)-armv5tel-kirkwood.config $(CFG)-armv7l-imx.config \ - $(CFG)-armv7l-omap.config $(CFG)-armv7l-tegra.config \ - $(CFG)-armv7hl-imx.config $(CFG)-armv7hl-highbank.config \ - $(CFG)-armv7hl-omap.config $(CFG)-armv7hl-tegra.config \ $(CFG)-ppc.config $(CFG)-ppc-smp.config \ $(CFG)-sparc64.config \ $(CFG)-ppc64.config $(CFG)-ppc64-debug.config @@ -36,24 +31,6 @@ temp-generic: config-generic temp-debug-generic: config-generic cat config-generic config-debug > temp-debug-generic -temp-arm-generic: config-arm-generic temp-generic - perl merge.pl $^ > $@ - -temp-armv7l-omap-generic: config-arm-omap-generic temp-arm-generic - perl merge.pl $^ > $@ - -temp-armv7l-tegra: config-arm-tegra temp-arm-generic - perl merge.pl $^ > $@ - -temp-armv5tel-kirkwood: config-arm-kirkwood temp-arm-generic - perl merge.pl $^ > $@ - -temp-armv7l-imx: config-arm-imx temp-arm-generic - perl merge.pl $^ > $@ - -temp-armv7l-highbank: config-arm-highbank temp-arm-generic - perl merge.pl $^ > $@ - temp-x86-32: config-x86-32-generic config-x86-generic perl merge.pl $^ > $@ @@ -117,39 +94,6 @@ kernel-$(VERSION)-ppc64-debug.config: config-powerpc64 temp-powerpc-debug-generi kernel-$(VERSION)-s390x.config: config-s390x temp-s390-generic perl merge.pl $^ s390 > $@ -kernel-$(VERSION)-arm.config: /dev/null temp-arm-generic - perl merge.pl $^ arm > $@ - -kernel-$(VERSION)-armv5tel.config: /dev/null temp-arm-generic - perl merge.pl $^ arm > $@ - -kernel-$(VERSION)-armv5tel-kirkwood.config: /dev/null temp-armv5tel-kirkwood - perl merge.pl $^ arm > $@ - -kernel-$(VERSION)-armv7l-imx.config: /dev/null temp-armv7l-imx - perl merge.pl $^ arm > $@ - -kernel-$(VERSION)-armv7l-highbank.config: /dev/null temp-armv7l-highbank - perl merge.pl $^ arm > $@ - -kernel-$(VERSION)-armv7l-omap.config: /dev/null temp-armv7l-omap-generic - perl merge.pl $^ arm > $@ - -kernel-$(VERSION)-armv7l-tegra.config: /dev/null temp-armv7l-tegra - perl merge.pl $^ arm > $@ - -kernel-$(VERSION)-armv7hl-imx.config: /dev/null temp-armv7l-imx - perl merge.pl $^ arm > $@ - -kernel-$(VERSION)-armv7hl-highbank.config: /dev/null temp-armv7l-highbank - perl merge.pl $^ arm > $@ - -kernel-$(VERSION)-armv7hl-omap.config: /dev/null temp-armv7l-omap-generic - perl merge.pl $^ arm > $@ - -kernel-$(VERSION)-armv7hl-tegra.config: /dev/null temp-armv7l-tegra - perl merge.pl $^ arm > $@ - kernel-$(VERSION)-ppc.config: /dev/null temp-powerpc32-generic perl merge.pl $^ powerpc > $@ diff --git a/arm-omap-dt-compat.patch b/arm-omap-dt-compat.patch deleted file mode 100644 index 4046e938f..000000000 --- a/arm-omap-dt-compat.patch +++ /dev/null @@ -1,42 +0,0 @@ -diff -up linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap3beagle.c.fdt linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap3beagle.c ---- linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap3beagle.c.fdt 2011-08-04 16:51:12.034188064 -0500 -+++ linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap3beagle.c 2011-08-04 22:13:52.801156923 -0500 -@@ -591,6 +591,11 @@ static void __init omap3_beagle_init(voi - beagle_opp_init(); - } - -+static const char *omap3_beagle_dt_match[] __initdata = { -+ "ti,omap3-beagle", -+ NULL -+}; -+ - MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board") - /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */ - .boot_params = 0x80000100, -@@ -600,4 +605,5 @@ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagl - .init_irq = omap3_beagle_init_irq, - .init_machine = omap3_beagle_init, - .timer = &omap3_secure_timer, -+ .dt_compat = omap3_beagle_dt_match, - MACHINE_END -diff -up linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c.fdt linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c ---- linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c.fdt 2011-08-04 16:51:12.092169023 -0500 -+++ linux-2.6.39.armv7l/arch/arm/mach-omap2/board-omap4panda.c 2011-08-04 22:15:29.200157437 -0500 -@@ -708,6 +708,11 @@ static void __init omap4_panda_map_io(vo - omap44xx_map_common_io(); - } - -+static const char *omap4_panda_match[] __initdata = { -+ "ti,omap4-panda", -+ NULL, -+}; -+ - MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board") - /* Maintainer: David Anders - Texas Instruments Inc */ - .boot_params = 0x80000100, -@@ -717,4 +722,5 @@ MACHINE_START(OMAP4_PANDA, "OMAP4 Panda - .init_irq = gic_init_irq, - .init_machine = omap4_panda_init, - .timer = &omap4_timer, -+ .dt_compat = omap4_panda_match, - MACHINE_END diff --git a/arm-smsc-support-reading-mac-address-from-device-tree.patch b/arm-smsc-support-reading-mac-address-from-device-tree.patch deleted file mode 100644 index a36c68369..000000000 --- a/arm-smsc-support-reading-mac-address-from-device-tree.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0b608345e114681f66ca0a3cf9d9434728da62ce Mon Sep 17 00:00:00 2001 -From: Ken Cox -Date: Thu, 23 Jun 2011 10:36:43 -0500 -Subject: [PATCH] Support reading mac address from device tree. - -If CONFIG_OF is enabled, we will try to read the mac address from the device tree. This enables us the ability to have a "static" mac address on arm boards such as the pandaboard and beagleboard which generate random mac addresses. ---- - drivers/net/usb/smsc75xx.c | 17 +++++++++++++++++ - drivers/net/usb/smsc95xx.c | 18 +++++++++++++++++- - 2 files changed, 34 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c -index 753ee6e..ac0a200 100644 ---- a/drivers/net/usb/smsc75xx.c -+++ b/drivers/net/usb/smsc75xx.c -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include "smsc75xx.h" - - #define SMSC_CHIPNAME "smsc75xx" -@@ -658,6 +659,22 @@ static int smsc75xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) - - static void smsc75xx_init_mac_address(struct usbnet *dev) - { -+ void *address; -+#ifdef CONFIG_OF -+ struct device_node *np; -+ -+ /* try the device tree */ -+ np = of_find_node_by_name(NULL, "smsc75xx"); -+ if (np) { -+ address = of_get_property(np, "local-mac-address", NULL); -+ if (address) { -+ memcpy(dev->net->dev_addr, address, ETH_ALEN); -+ netif_dbg(dev, ifup, dev->net, "MAC address read from device tree\n"); -+ return; -+ } -+ } -+#endif -+ - /* try reading mac address from EEPROM */ - if (smsc75xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, - dev->net->dev_addr) == 0) { -diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index bc86f4b..c83942d 100644 ---- a/drivers/net/usb/smsc95xx.c -+++ b/drivers/net/usb/smsc95xx.c -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include "smsc95xx.h" - - #define SMSC_CHIPNAME "smsc95xx" -@@ -639,6 +640,22 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) - - static void smsc95xx_init_mac_address(struct usbnet *dev) - { -+ void *address; -+#ifdef CONFIG_OF -+ struct device_node *np; -+ -+ /* try the device tree */ -+ np = of_find_node_by_name(NULL, "smsc95xx"); -+ if (np) { -+ address = of_get_property(np, "local-mac-address", NULL); -+ if (address) { -+ memcpy(dev->net->dev_addr, address, ETH_ALEN); -+ netif_dbg(dev, ifup, dev->net, "MAC address read from device tree\n"); -+ return; -+ } -+ } -+#endif -+ - /* try reading mac address from EEPROM */ - if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, - dev->net->dev_addr) == 0) { -@@ -648,7 +665,6 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) - return; - } - } -- - /* no eeprom, or eeprom values are invalid. generate random MAC */ - random_ether_addr(dev->net->dev_addr); - netif_dbg(dev, ifup, dev->net, "MAC address set to random_ether_addr\n"); --- -1.7.2.3 - diff --git a/config-arm-generic b/config-arm-generic deleted file mode 100644 index 80a7f2b87..000000000 --- a/config-arm-generic +++ /dev/null @@ -1,365 +0,0 @@ -CONFIG_ARM=y -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_SMP=y -CONFIG_SMP_ON_UP=y -CONFIG_ARM_CPU_TOPOLOGY=y -CONFIG_NR_CPUS=4 -CONFIG_HOTPLUG_CPU=y - -# CONFIG_CMDLINE_FORCE is not set - -CONFIG_CC_OPTIMIZE_FOR_SIZE=y - -CONFIG_ARCH_VEXPRESS=y -CONFIG_ARCH_VEXPRESS_CA9X4=y -CONFIG_ARCH_VEXPRESS_DT=y -CONFIG_PLAT_VERSATILE_CLCD=y -CONFIG_PLAT_VERSATILE_SCHED_CLOCK=y -CONFIG_PLAT_VERSATILE=y -CONFIG_ARM_TIMER_SP804=y - -CONFIG_CPU_V7=y -CONFIG_CPU_32v6K=y -CONFIG_CPU_32v7=y -CONFIG_CPU_ABRT_EV7=y -CONFIG_CPU_PABRT_V7=y -CONFIG_CPU_CACHE_V7=y -CONFIG_CPU_CACHE_VIPT=y -CONFIG_CPU_COPY_V6=y -CONFIG_CPU_TLB_V7=y -CONFIG_CPU_HAS_ASID=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y - -CONFIG_HIGHMEM=y -# CONFIG_HIGHPTE is not set - -# CONFIG_CPU_ICACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_WRITETHROUGH is not set -# CONFIG_CPU_CACHE_ROUND_ROBIN is not set - -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZBOOT_ROM_BSS=0 - -# CONFIG_XIP_KERNEL is not set - -CONFIG_ATAGS_PROC=y - -CONFIG_CPU_IDLE=y -# CONFIG_CPU_IDLE_GOV_LADDER is not set -ONFIG_CPU_IDLE_GOV_MENU=y - -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y - -# CONFIG_FPE_NWFPE is not set -CONFIG_FPE_FASTFPE=y -CONFIG_VFP=y -CONFIG_VFPv3=y -CONFIG_NEON=y - -CONFIG_PM=y -# CONFIG_PM_DEBUG is not set -# CONFIG_PM_TRACE is not set -CONFIG_SUSPEND=y -# CONFIG_PM_TEST_SUSPEND is not set -CONFIG_APM_EMULATION=y - -CONFIG_ARM_THUMB=y - -CONFIG_AEABI=y -CONFIG_OABI_COMPAT=y - -CONFIG_HW_PERF_EVENTS=y - -# CONFIG_UACCESS_WITH_MEMCPY is not set - -CONFIG_CMDLINE="console=ttyAM0,115200 root=/dev/sda1 rootdelay=20" - -CONFIG_LEDS=y -CONFIG_LEDS_CPU=y - -CONFIG_MTD_AFS_PARTS=y -CONFIG_MTD_ARM_INTEGRATOR=y -CONFIG_MTD_IMPA7=y - -CONFIG_AX88796=m -CONFIG_AX88796_93CX6=y -CONFIG_SMC91X=m -CONFIG_DM9000=m -CONFIG_DM9000_DEBUGLEVEL=4 -# CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL is not set -CONFIG_SMC911X=m -CONFIG_SMSC911X=m - -CONFIG_SERIO_AMBAKMI=m - -CONFIG_SERIAL_AMBA_PL011=y -CONFIG_SERIAL_AMBA_PL011_CONSOLE=y - -CONFIG_I2C_VERSATILE=y - -CONFIG_THERMAL=y - -# CONFIG_MFD_T7L66XB is not set -# CONFIG_MFD_TC6387XB is not set - -CONFIG_FB_ARMCLCD=m - -CONFIG_SND_ARM=y -CONFIG_SND_ARMAACI=m -CONFIG_SND_SOC=m -# CONFIG_SND_SOC_CACHE_LZO is not set -# CONFIG_SND_SOC_ALL_CODECS is not set - -CONFIG_USB_MUSB_HDRC=y -CONFIG_MUSB_PIO_ONLY=y -CONFIG_USB_TUSB6010=y -# CONFIG_USB_MUSB_DEBUG is not set - -CONFIG_MMC_ARMMMCI=m -CONFIG_MMC_DW=m -CONFIG_MMC_DW_PLTFM=y -# CONFIG_MMC_DW_PCI is not set -# CONFIG_MMC_DW_IDMAC is not set - -CONFIG_RTC_DRV_PL030=y -CONFIG_RTC_DRV_PL031=y - -# CONFIG_SGI_IOC4 is not set - -# CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_ERRORS is not set -# CONFIG_DEBUG_LL is not set -# CONFIG_DEBUG_PER_CPU_MAPS is not set -# CONFIG_IRQ_DOMAIN_DEBUG is not set - -CONFIG_ARM_UNWIND=y - -CONFIG_RCU_FANOUT=32 - -# CONFIG_USB_ULPI is not set -# CONFIG_OC_ETM is not set - -# CONFIG_MTD_PISMO is not set - -CONFIG_PERF_EVENTS=y -CONFIG_PERF_COUNTERS=y - -# CONFIG_MG_DISK is not set -# CONFIG_GPIO_PL061 is not set - -CONFIG_CC_STACKPROTECTOR=y - -CONFIG_AUTO_ZRELADDR=y - -# CONFIG_ARM_CHARLCD is not set -# CONFIG_DEPRECATED_PARAM_STRUCT is not set - -# CONFIG_ARM_SP805_WATCHDOG is not set - -CONFIG_PM_OPP=y - -CONFIG_SECCOMP=y -CONFIG_STRICT_DEVMEM=y - -# CONFIG_AMBA_PL08X is not set - -# CONFIG_HVC_DCC is not set - -CONFIG_SPARSE_IRQ=y - -# CONFIG_ARM_PATCH_PHYS_VIRT is not set - -CONFIG_HWSPINLOCK_OMAP=m - -CONFIG_USE_OF=y -CONFIG_PROC_DEVICETREE=y -CONFIG_MTD_PHYSMAP_OF=m -CONFIG_SERIAL_OF_PLATFORM=m -CONFIG_MMC_SDHCI_OF=m -CONFIG_MMC_SDHCI_PXAV3=m -CONFIG_MMC_SDHCI_PXAV2=m - -CONFIG_ARM_APPENDED_DTB=y -CONFIG_MTD_OF_PARTS=y -CONFIG_PL330_DMA=y -# CONFIG_ARM_KPROBES_TEST is not set -# CONFIG_ARM_ATAG_DTB_COMPAT is not set - -# CONFIG_FTGMAC100 is not set -# CONFIG_FTMAC100 is not set -# -CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 -CONFIG_LSM_MMAP_MIN_ADDR=32768 - -# CONFIG_ARM_LPAE is not set -# CONFIG_ARM_THUMBEE is not set -CONFIG_SWP_EMULATE=y -# CONFIG_CPU_BPREDICT_DISABLE is not set -CONFIG_CACHE_L2X0=y -# CONFIG_ARM_ERRATA_430973 is not set -# CONFIG_ARM_ERRATA_458693 is not set -# CONFIG_ARM_ERRATA_460075 is not set -# CONFIG_ARM_ERRATA_742230 is not set -# CONFIG_ARM_ERRATA_742231 is not set -# CONFIG_PL310_ERRATA_588369 is not set -# CONFIG_PL310_ERRATA_727915 is not set -# CONFIG_ARM_ERRATA_743622 is not set -# CONFIG_ARM_ERRATA_754322 is not set -# CONFIG_ARM_ERRATA_754327 is not set -# CONFIG_ARM_ERRATA_764369 is not set -# CONFIG_PL310_ERRATA_769419 is not set -CONFIG_SCHED_MC=y -# CONFIG_SCHED_SMT is not set -CONFIG_LOCAL_TIMERS=y -# CONFIG_THUMB2_KERNEL is not set -# CONFIG_PATA_PLATFORM is not set -CONFIG_ETHERNET=y -CONFIG_NET_VENDOR_BROADCOM=y -# CONFIG_SERIAL_AMBA_PL010 is not set -# CONFIG_MPCORE_WATCHDOG is not set - -CONFIG_DVB_PLL=m -CONFIG_DVB_TDA1004X=m - -# disable TPM on arm at least on the trimslices it causes havoc -# CONFIG_TCG_TPM is not set -# CONFIG_IMA is not set - -# ERROR: "__bswapsi2" [drivers/staging/crystalhd/crystalhd.ko] undefined! -# CONFIG_CRYSTALHD is not set - -# these modules all fail with missing __bad_udelay -# http://www.spinics.net/lists/arm/msg15615.html provides some background -# CONFIG_SUNGEM is not set -# CONFIG_FB_SAVAGE is not set -# CONFIG_FB_RADEON is not set -# CONFIG_DRM_RADEON is not set -# CONFIG_ATM_HE is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SFC is not set - -# these all currently fail due to missing symbols __bad_udelay or -# error: implicit declaration of function ‘iowrite32be’ -# CONFIG_SND_ALI5451 is not set -# CONFIG_DRM_NOUVEAU is not set -# CONFIG_MLX4_EN is not set - -# drivers/input/touchscreen/eeti_ts.c:65:2: error: implicit declaration of function 'irq_to_gpio' [-Werror=implicit-function-declaration] -# CONFIG_TOUCHSCREEN_EETI is not set -# CONFIG_TOUCHSCREEN_EGALAX is not set -# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set -# -# FIXME: Guesses, need checking -# CONFIG_MACH_EUKREA_CPUIMX35SD is not set -CONFIG_ARM_ERRATA_720789=y -CONFIG_ARM_ERRATA_751472=y -CONFIG_ARM_ERRATA_326103=y -# CONFIG_OMAP4_ERRATA_I688 is not set -# CONFIG_FB_MX3 is not set -# CONFIG_MX3_IPU is not set -# CONFIG_MX3_IPU_IRQS is not set - -# CONFIG_NET_VENDOR_CIRRUS is not set -# CONFIG_CS89x0 is not set - -# CONFIG_OF_SELFTEST is not set -# CONFIG_MACH_IMX51_DT is not set -# CONFIG_MACH_IMX53_DT is not set -# CONFIG_MACH_MX53_EVK is not set -# CONFIG_MACH_MX53_SMD is not set -# CONFIG_MACH_MX53_LOCO is not set -# CONFIG_MACH_MX53_ARD is not set -# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set - -CONFIG_OF_GPIO=y -CONFIG_INPUT_GP2A=m -CONFIG_INPUT_GPIO_TILT_POLLED=m - -CONFIG_BPF_JIT=y - -CONFIG_MTD=m -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_AFS_PARTS=y -CONFIG_MTD_CHAR=m -CONFIG_MTD_BLKDEVS=m -CONFIG_MTD_BLOCK=m -# CONFIG_MTD_TESTS is not set -# CONFIG_MTD_BLOCK_RO is not set -# CONFIG_MTD_AR7_PARTS is not set -CONFIG_MTD_CFI=m -CONFIG_MTD_CFI_AMDSTD=m -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_NOSWAP=y -CONFIG_MTD_CFI_GEOMETRY=y -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -CONFIG_MTD_CFI_INTELEXT=y -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_CFI_UTIL=y -CONFIG_MTD_DOC2000=m -CONFIG_MTD_DOC2001=m -CONFIG_MTD_DOC2001PLUS=m -# CONFIG_MTD_DOCPROBE_ADVANCED is not set -CONFIG_MTD_ALAUDA=m -# CONFIG_MTD_ONENAND is not set -CONFIG_MTD_JEDECPROBE=m -CONFIG_MTD_GEN_PROBE=y -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_PHYSMAP=m -# CONFIG_MTD_PHYSMAP_COMPAT is not set -CONFIG_MTD_M25P80=m -CONFIG_M25PXX_USE_FAST_READ=y -CONFIG_MTD_NAND=m -CONFIG_MTD_NAND_ECC=m -CONFIG_MTD_NAND_IDS=m -# CONFIG_MTD_NAND_CAFE is not set -# CONFIG_MTD_NAND_ECC_SMC is not set -# CONFIG_MTD_NAND_DENALI is not set -# CONFIG_MTD_NAND_DOCG4 is not set -CONFIG_MTD_NAND_GPIO=m -# CONFIG_MTD_INTEL_VR_NOR is not set -# CONFIG_MTD_NAND_NANDSIM is not set -CONFIG_MTD_NAND_ORION=m -# CONFIG_MTD_NAND_RICOH is not set -# CONFIG_MTD_NAND_PLATFORM is not set -# CONFIG_MTD_OTP is not set -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_PLATRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_SLRAM is not set -CONFIG_MTD_UBI=m -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_MTD_UBI_BEB_RESERVE=1 -# CONFIG_MTD_UBI_GLUEBI is not set -# CONFIG_MTD_UBI_DEBUG is not set - -# CONFIG_SM_FTL is not set - -CONFIG_JFFS2_FS=m -CONFIG_JFFS2_FS_DEBUG=0 -CONFIG_JFFS2_FS_WRITEBUFFER=y -# CONFIG_JFFS2_FS_WBUF_VERIFY is not set -# CONFIG_JFFS2_SUMMARY is not set -# CONFIG_JFFS2_FS_XATTR is not set -# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set -CONFIG_JFFS2_ZLIB=y -# CONFIG_JFFS2_LZO is not set -CONFIG_JFFS2_RTIME=y -# CONFIG_JFFS2_RUBIN is not set - -CONFIG_UBIFS_FS=m -CONFIG_UBIFS_FS_XATTR=y -CONFIG_UBIFS_FS_ADVANCED_COMPR=y -CONFIG_UBIFS_FS_LZO=y -CONFIG_UBIFS_FS_ZLIB=y -# CONFIG_UBIFS_FS_DEBUG is not set diff --git a/config-arm-highbank b/config-arm-highbank deleted file mode 100644 index 60178dd1f..000000000 --- a/config-arm-highbank +++ /dev/null @@ -1,31 +0,0 @@ -CONFIG_ARCH_HIGHBANK=y -# CONFIG_ARM_LPAE is not set -# CONFIG_ARM_THUMBEE is not set -CONFIG_SWP_EMULATE=y -# CONFIG_CPU_BPREDICT_DISABLE is not set -# CONFIG_ARM_ERRATA_430973 is not set -# CONFIG_ARM_ERRATA_458693 is not set -# CONFIG_ARM_ERRATA_460075 is not set -# CONFIG_PL310_ERRATA_588369 is not set -# CONFIG_PL310_ERRATA_727915 is not set -# CONFIG_ARM_ERRATA_743622 is not set -# CONFIG_PL310_ERRATA_753970 is not set -# CONFIG_ARM_ERRATA_754322 is not set -# CONFIG_PL310_ERRATA_769419 is not set - -# CONFIG_THUMB2_KERNEL is not set - -CONFIG_ARM_TIMER_SP804=y - -CONFIG_SATA_AHCI_PLATFORM=y -CONFIG_ATA_SFF=y - -CONFIG_ETHERNET=y -CONFIG_NET_VENDOR_BROADCOM=y -CONFIG_NET_CALXEDA_XGMAC=y - -CONFIG_GPIO_PL061=y - -CONFIG_SERIAL_AMBA_PL010=y -CONFIG_SERIAL_AMBA_PL010_CONSOLE=y - diff --git a/config-arm-imx b/config-arm-imx deleted file mode 100644 index 493769814..000000000 --- a/config-arm-imx +++ /dev/null @@ -1,89 +0,0 @@ -CONFIG_ARCH_MXC=y -CONFIG_ARCH_MX51=y -CONFIG_MACH_MX51_BABBAGE=y -CONFIG_MACH_MX51_3DS=y -CONFIG_MACH_EUKREA_CPUIMX51=y - -CONFIG_MACH_EUKREA_CPUIMX51SD=y -CONFIG_MACH_MX51_EFIKAMX=y -CONFIG_MACH_MX51_EFIKASB=y -# CONFIG_SWP_EMULATE is not set -# CONFIG_THUMB2_KERNEL is not set -CONFIG_CPU_FREQ_IMX=y -CONFIG_W1_MASTER_MXC=m -CONFIG_IMX_DMA=m -CONFIG_IMX_SDMA=y -CONFIG_MACH_MX31ADS=y -CONFIG_MACH_MX31LILLY=y -CONFIG_MACH_MX31LITE=y -CONFIG_MACH_PCM037=y -CONFIG_MACH_MX31_3DS=y -CONFIG_MACH_MX31MOBOARD=y -CONFIG_MACH_QONG=y -CONFIG_MACH_ARMADILLO5X0=y -CONFIG_MACH_KZM_ARM11_01=y -CONFIG_MACH_BUG=y -CONFIG_MACH_PCM043=y -CONFIG_MACH_MX35_3DS=y -CONFIG_MACH_EUKREA_CPUIMX35=y -CONFIG_MACH_VPR200=y -CONFIG_SOC_IMX6Q=y -CONFIG_MXC_IRQ_PRIOR=y -CONFIG_MXC_PWM=m -CONFIG_MXC_DEBUG_BOARD=y -# CONFIG_CPU_BPREDICT_DISABLE is not set -CONFIG_CACHE_L2X0=y -CONFIG_ARM_DMA_MEM_BUFFERABLE=y -CONFIG_ARM_ERRATA_411920=y -CONFIG_PL310_ERRATA_588369=y -CONFIG_PL310_ERRATA_727915=y -CONFIG_ARM_ERRATA_364296=y -CONFIG_RFKILL_GPIO=m -CONFIG_PATA_IMX=m -CONFIG_ETHERNET=y -CONFIG_NET_VENDOR_BROADCOM=y -CONFIG_NET_VENDOR_FREESCALE=y -CONFIG_FEC=y -CONFIG_KEYBOARD_IMX=m -CONFIG_SERIAL_IMX=y -CONFIG_HW_RANDOM_MXC_RNGA=m -CONFIG_I2C_IMX=m -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_MCP23S08=m -# CONFIG_GPIO_MC9S08DZ60 is not set -CONFIG_SND_IMX_SOC=m -CONFIG_USB_EHCI_MXC=y -# CONFIG_USB_IMX21_HCD is not set -CONFIG_MMC_SDHCI_ESDHC_IMX=m -CONFIG_MMC_MXC=m -CONFIG_RTC_MXC=y - -CONFIG_BACKLIGHT_PWM=m -CONFIG_LEDS_PWM=m - -CONFIG_MACH_PCM037_EET=y -# CONFIG_MACH_MX31_3DS_MXC_NAND_USE_BBT is not set -CONFIG_MXC_USE_EPIT=y -CONFIG_ARM_THUMBEE=y -CONFIG_ARM_ERRATA_430973=y -CONFIG_ARM_ERRATA_458693=y -CONFIG_ARM_ERRATA_460075=y -CONFIG_ARM_ERRATA_743622=y -CONFIG_ARM_ERRATA_754322=y -CONFIG_CAN_FLEXCAN=m -CONFIG_MTD_NAND_MXC=m -CONFIG_INPUT_PWM_BEEPER=m -CONFIG_SERIAL_IMX_CONSOLE=y -CONFIG_IMX2_WDT=m -CONFIG_SND_SOC_PHYCORE_AC97=m -CONFIG_SND_SOC_EUKREA_TLV320=m - -CONFIG_PL310_ERRATA_769419=y -CONFIG_LEDS_RENESAS_TPU=y - -# CONFIG_ARM_LPAE is not set -# CONFIG_INPUT_GP2A is not set -# CONFIG_INPUT_GPIO_TILT_POLLED is not set - -CONFIG_MFD_ANATOP=y - diff --git a/config-arm-kirkwood b/config-arm-kirkwood deleted file mode 100644 index 3d3466bc4..000000000 --- a/config-arm-kirkwood +++ /dev/null @@ -1,54 +0,0 @@ -CONFIG_ARCH_KIRKWOOD=y -CONFIG_ARCH_KIRKWOOD_DT=y -# CONFIG_SMP is not set -# CONFIG_VFP is not set -CONFIG_MACH_DB88F6281_BP=y -CONFIG_MACH_RD88F6192_NAS=y -CONFIG_MACH_RD88F6281=y -CONFIG_MACH_MV88F6281GTW_GE=y -CONFIG_MACH_SHEEVAPLUG=y -CONFIG_MACH_ESATA_SHEEVAPLUG=y -CONFIG_MACH_GURUPLUG=y -CONFIG_MACH_DREAMPLUG_DT=y -CONFIG_MACH_DOCKSTAR=y -CONFIG_MACH_TS219=y -CONFIG_MACH_TS41X=y -CONFIG_MACH_OPENRD_BASE=y -CONFIG_MACH_OPENRD_CLIENT=y -CONFIG_MACH_OPENRD_ULTIMATE=y -CONFIG_MACH_NETSPACE_V2=y -CONFIG_MACH_INETSPACE_V2=y -CONFIG_MACH_NETSPACE_MAX_V2=y -CONFIG_MACH_D2NET_V2=y -CONFIG_MACH_NET2BIG_V2=y -CONFIG_MACH_NET5BIG_V2=y -CONFIG_MACH_T5325=y -# CONFIG_CPU_FEROCEON_OLD_ID is not set - - -CONFIG_CACHE_FEROCEON_L2=y -CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH=y -CONFIG_MTD_NAND_ORION=m -CONFIG_MV643XX_ETH=m -CONFIG_I2C_MV64XXX=m -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_MCP23S08=m -CONFIG_ORION_WATCHDOG=m -CONFIG_SND_KIRKWOOD_SOC=m -CONFIG_SND_KIRKWOOD_SOC_OPENRD=m -CONFIG_SND_KIRKWOOD_SOC_T5325=m -CONFIG_MMC_MVSDIO=m -CONFIG_LEDS_NS2=m -CONFIG_LEDS_NETXBIG=m -CONFIG_RTC_DRV_MV=y -CONFIG_MV_XOR=y -CONFIG_CRYPTO_DEV_MV_CESA=m - -# CONFIG_INPUT_GP2A is not set -# CONFIG_INPUT_GPIO_TILT_POLLED is not set - - -# CONFIG_VFP is not set -# CONFIG_VFPv3 is not set -# CONFIG_NEON is not set -# CONFIG_SMP is not set diff --git a/config-arm-omap-generic b/config-arm-omap-generic deleted file mode 100644 index c4f22dc3d..000000000 --- a/config-arm-omap-generic +++ /dev/null @@ -1,1086 +0,0 @@ -# CONFIG_OMAP4_ERRATA_I688 is not set - -CONFIG_GENERIC_GPIO=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_LOCKBREAK=y -CONFIG_ARCH_HAS_CPUFREQ=y -# CONFIG_SPARSE_IRQ is not set -CONFIG_TREE_PREEMPT_RCU=y -CONFIG_PREEMPT_RCU=y -CONFIG_RCU_FANOUT=32 -# CONFIG_RCU_FANOUT_EXACT is not set -# CONFIG_RCU_BOOST is not set -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -# CONFIG_SCHED_AUTOGROUP is not set -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_USE_GENERIC_SMP_HELPERS=y -CONFIG_HAVE_HW_BREAKPOINT=y -CONFIG_STOP_MACHINE=y -# CONFIG_INLINE_SPIN_UNLOCK is not set -# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set -# CONFIG_INLINE_READ_UNLOCK is not set -# CONFIG_INLINE_READ_UNLOCK_IRQ is not set -# CONFIG_INLINE_WRITE_UNLOCK is not set -# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set -CONFIG_MUTEX_SPIN_ON_OWNER=y -# CONFIG_ARCH_VERSATILE is not set -CONFIG_ARCH_OMAP=y -# CONFIG_GPIO_PCA953X is not set -# CONFIG_KEYBOARD_GPIO_POLLED is not set -# TI OMAP Common Features -CONFIG_ARCH_OMAP_OTG=y -# CONFIG_ARCH_OMAP1 is not set -CONFIG_ARCH_OMAP2PLUS=y - -# -# OMAP Feature Selections -# -CONFIG_OMAP_SMARTREFLEX=y -CONFIG_OMAP_SMARTREFLEX_CLASS3=y -CONFIG_OMAP_RESET_CLOCKS=y -CONFIG_OMAP_MUX=y -# CONFIG_OMAP_MUX_DEBUG is not set -CONFIG_OMAP_MUX_WARNINGS=y -CONFIG_OMAP_MCBSP=y -CONFIG_OMAP_MBOX_FWK=m -CONFIG_OMAP_MBOX_KFIFO_SIZE=256 -CONFIG_OMAP_32K_TIMER=y -# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set -CONFIG_OMAP_32K_TIMER_HZ=128 -CONFIG_OMAP_DM_TIMER=y -# CONFIG_OMAP_PM_NONE is not set -CONFIG_OMAP_PM_NOOP=y - -# -# TI OMAP2/3/4 Specific Features -# -CONFIG_ARCH_OMAP2PLUS_TYPICAL=y -# CONFIG_ARCH_OMAP2 is not set -CONFIG_ARCH_OMAP3=y -CONFIG_ARCH_OMAP4=y -CONFIG_SOC_OMAP3430=y -# CONFIG_SOC_OMAPTI816X is not set -CONFIG_OMAP_PACKAGE_CBB=y -CONFIG_OMAP_PACKAGE_CBL=y -CONFIG_OMAP_PACKAGE_CBS=y - -# -# OMAP Board Type -# -CONFIG_MACH_OMAP3_BEAGLE=y -CONFIG_MACH_DEVKIT8000=y -CONFIG_MACH_OMAP_LDP=y -CONFIG_MACH_OMAP3530_LV_SOM=y -CONFIG_MACH_OMAP3_TORPEDO=y -CONFIG_MACH_OVERO=y -CONFIG_MACH_OMAP3EVM=y -CONFIG_MACH_OMAP3517EVM=y -CONFIG_MACH_CRANEBOARD=y -CONFIG_MACH_OMAP3_PANDORA=y -CONFIG_MACH_OMAP3_TOUCHBOOK=y -CONFIG_MACH_OMAP_3430SDP=y -CONFIG_MACH_NOKIA_RM680=y -CONFIG_MACH_NOKIA_RX51=y -CONFIG_MACH_OMAP_ZOOM2=y -CONFIG_MACH_OMAP_ZOOM3=y -CONFIG_MACH_CM_T35=y -CONFIG_MACH_CM_T3517=y -CONFIG_MACH_IGEP0020=y -CONFIG_MACH_IGEP0030=y -CONFIG_MACH_SBC3530=y -CONFIG_MACH_OMAP_3630SDP=y -CONFIG_MACH_OMAP_4430SDP=y -CONFIG_MACH_OMAP4_PANDA=y -CONFIG_MACH_TI8168EVM=y -CONFIG_OMAP3_EMU=y -# CONFIG_OMAP3_SDRC_AC_TIMING is not set -# System MMU -CONFIG_CPU_32v6K=y -CONFIG_CPU_V7=y -CONFIG_CPU_32v7=y -CONFIG_CPU_ABRT_EV7=y -CONFIG_CPU_PABRT_V7=y -CONFIG_CPU_CACHE_V7=y -CONFIG_CPU_CACHE_VIPT=y -CONFIG_CPU_COPY_V6=y -CONFIG_CPU_TLB_V7=y -CONFIG_CPU_HAS_ASID=y -CONFIG_ARM_THUMBEE=y -CONFIG_SWP_EMULATE=y -# CONFIG_CPU_BPREDICT_DISABLE is not set -CONFIG_OUTER_CACHE=y -CONFIG_OUTER_CACHE_SYNC=y -CONFIG_CACHE_L2X0=y -CONFIG_CACHE_PL310=y -CONFIG_ARM_DMA_MEM_BUFFERABLE=y -CONFIG_CPU_HAS_PMU=y -CONFIG_ARM_ERRATA_430973=y -# CONFIG_ARM_ERRATA_458693 is not set -# CONFIG_ARM_ERRATA_460075 is not set -# CONFIG_ARM_ERRATA_742230 is not set -# CONFIG_ARM_ERRATA_742231 is not set -CONFIG_PL310_ERRATA_588369=y -CONFIG_PL310_ERRATA_769419=y -CONFIG_ARM_ERRATA_720789=y -# CONFIG_ARM_ERRATA_743622 is not set -# CONFIG_ARM_ERRATA_751472 is not set -# CONFIG_ARM_ERRATA_753970 is not set -# CONFIG_ARM_ERRATA_754322 is not set -# CONFIG_ARM_ERRATA_754327 is not set -# CONFIG_ARM_ERRATA_764369 is not set -CONFIG_ARM_GIC=y -# CONFIG_PCI_SYSCALL is not set -# CONFIG_PCCARD is not set -CONFIG_SMP=y -CONFIG_SMP_ON_UP=y -CONFIG_HAVE_ARM_SCU=y -CONFIG_HAVE_ARM_TWD=y -CONFIG_NR_CPUS=2 -CONFIG_HOTPLUG_CPU=y -CONFIG_LOCAL_TIMERS=y -# CONFIG_PREEMPT_VOLUNTARY is not set -CONFIG_PREEMPT=y -CONFIG_HZ=128 -# CONFIG_THUMB2_KERNEL is not set -CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y -CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_KSM is not set -# CONFIG_CC_STACKPROTECTOR is not set -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="" -# CONFIG_AUTO_ZRELADDR is not set -CONFIG_VFPv3=y -CONFIG_NEON=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_BINFMT_MISC=m -CONFIG_PM_DEBUG=y -# CONFIG_PM_ADVANCED_DEBUG is not set -# CONFIG_PM_VERBOSE is not set -CONFIG_CAN_PM_TRACE=y -CONFIG_PM_SLEEP_SMP=y -# CONFIG_APM_EMULATION is not set -CONFIG_ARCH_HAS_OPP=y -CONFIG_PM_OPP=y -# CONFIG_NET_IPGRE_DEMUX is not set -# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set -# CONFIG_ARPD is not set -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -CONFIG_IPV6=y -# CONFIG_IPV6_ROUTER_PREF is not set -# CONFIG_IPV6_OPTIMISTIC_DAD is not set -# CONFIG_IPV6_MIP6 is not set -# CONFIG_IPV6_SUBTREES is not set -# CONFIG_IPV6_MROUTE is not set -CONFIG_NF_DEFRAG_IPV4=m -# CONFIG_NET_DCCPPROBE is not set -# CONFIG_L2TP_V3 is not set -# CONFIG_DECNET_ROUTER is not set -# CONFIG_NET_SCH_INGRESS is not set -# CONFIG_NET_CLS_U32 is not set -# CONFIG_NET_CLS_FLOW is not set -# CONFIG_NET_ACT_CSUM is not set -# CONFIG_NET_CLS_IND is not set -CONFIG_RPS=y -CONFIG_XPS=y -# CONFIG_CAN_SLCAN is not set -# CONFIG_CAN_DEV is not set -CONFIG_RXKAD=m -CONFIG_FIRMWARE_IN_KERNEL=y -# CONFIG_DEBUG_DEVRES is not set -CONFIG_MTD=y -CONFIG_MTD_TESTS=m -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set -# CONFIG_MTD_AR7_PARTS is not set -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLKDEVS=y -CONFIG_MTD_BLOCK=y -CONFIG_SM_FTL=m -CONFIG_MTD_PHYSMAP=m -# CONFIG_MTD_PHYSMAP_COMPAT is not set -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_IMPA7 is not set -# CONFIG_MTD_GPIO_ADDR is not set -CONFIG_MTD_PLATRAM=m -# CONFIG_MTD_DATAFLASH is not set -CONFIG_MTD_M25P80=m -CONFIG_M25PXX_USE_FAST_READ=y -# CONFIG_MTD_SST25L is not set -CONFIG_MTD_SLRAM=m -CONFIG_MTD_PHRAM=m -CONFIG_MTD_DOC2000=m -CONFIG_MTD_DOC2001=m -CONFIG_MTD_DOC2001PLUS=m -CONFIG_MTD_DOCPROBE=m -CONFIG_MTD_DOCECC=m -# CONFIG_MTD_DOCPROBE_ADVANCED is not set -CONFIG_MTD_DOCPROBE_ADDRESS=0 -CONFIG_MTD_NAND_ECC=y -# CONFIG_MTD_NAND_ECC_SMC is not set -CONFIG_MTD_NAND=y -# CONFIG_MTD_SM_COMMON is not set -# CONFIG_MTD_NAND_GPIO is not set -# CONFIG_MTD_NAND_DOCG4 is not set -CONFIG_MTD_NAND_OMAP2=y -CONFIG_MTD_NAND_OMAP_PREFETCH=y -CONFIG_MTD_NAND_OMAP_PREFETCH_DMA=y -CONFIG_MTD_NAND_IDS=y -# CONFIG_MTD_NAND_NANDSIM is not set -CONFIG_MTD_NAND_PLATFORM=y -# CONFIG_MTD_ALAUDA is not set -CONFIG_MTD_ONENAND=y -# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set -# CONFIG_MTD_ONENAND_GENERIC is not set -CONFIG_MTD_ONENAND_OMAP2=y -# CONFIG_MTD_ONENAND_OTP is not set -CONFIG_MTD_ONENAND_2X_PROGRAM=y -CONFIG_MTD_ONENAND_SIM=m -CONFIG_MTD_UBI_GLUEBI=m -# CONFIG_PARPORT is not set -CONFIG_BLK_DEV_RAM_SIZE=65536 -CONFIG_MG_DISK=m -CONFIG_MG_DISK_RES=0 -# CONFIG_BLK_DEV_RBD is not set -# CONFIG_APDS9802ALS is not set -# CONFIG_ISL29020 is not set -# CONFIG_SENSORS_BH1770 is not set -# CONFIG_SENSORS_APDS990X is not set -CONFIG_HMC6352=m -CONFIG_DS1682=m -CONFIG_TI_DAC7512=m -CONFIG_BMP085=m -CONFIG_C2PORT=m -CONFIG_EEPROM_AT25=m -CONFIG_EEPROM_93XX46=m -# CONFIG_IWMC3200TOP_DEBUGFS is not set -# CONFIG_SCSI_PROC_FS is not set -# CONFIG_BLK_DEV_SR_VENDOR is not set -# CONFIG_SCSI_SPI_ATTRS is not set -# CONFIG_ISCSI_BOOT_SYSFS is not set -# CONFIG_SCSI_OSD_INITIATOR is not set -# CONFIG_SATA_AHCI_PLATFORM is not set -# CONFIG_DM_DEBUG is not set -# CONFIG_DM_RAID is not set -# CONFIG_DM_LOG_USERSPACE is not set -CONFIG_DM_MULTIPATH=y -# CONFIG_TARGET_CORE is not set -# CONFIG_MACVTAP is not set -CONFIG_MII=y -# CONFIG_MARVELL_PHY is not set -# CONFIG_DAVICOM_PHY is not set -# CONFIG_QSEMI_PHY is not set -# CONFIG_LXT_PHY is not set -# CONFIG_CICADA_PHY is not set -# CONFIG_VITESSE_PHY is not set -# CONFIG_SMSC_PHY is not set -# CONFIG_BROADCOM_PHY is not set -# CONFIG_BCM63XX_PHY is not set -# CONFIG_ICPLUS_PHY is not set -# CONFIG_REALTEK_PHY is not set -# CONFIG_NATIONAL_PHY is not set -# CONFIG_STE10XP is not set -# CONFIG_LSI_ET1011C_PHY is not set -# CONFIG_MICREL_PHY is not set -# CONFIG_FIXED_PHY is not set -# CONFIG_MDIO_BITBANG is not set -# CONFIG_AX88796 is not set -# CONFIG_SMC91X is not set -# CONFIG_TI_DAVINCI_EMAC is not set -# CONFIG_TI_DAVINCI_MDIO is not set -# CONFIG_TI_DAVINCI_CPDMA is not set -CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y -CONFIG_ENC28J60=m -# CONFIG_ENC28J60_WRITEVERIFY is not set -# CONFIG_ETHOC is not set -CONFIG_SMC911X=y -CONFIG_SMSC911X=y -# CONFIG_DNET is not set -# CONFIG_B44 is not set -CONFIG_KS8851=m -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set -# CONFIG_ATH9K_HTC is not set -# CONFIG_AR9170_USB is not set -# CONFIG_B43_SDIO is not set -# CONFIG_B43_PHY_N is not set -# CONFIG_HOSTAP is not set -# CONFIG_IWM is not set -CONFIG_LIBERTAS_SPI=m -# CONFIG_LIBERTAS_MESH is not set -CONFIG_P54_SPI=m -# CONFIG_P54_SPI_DEFAULT_EEPROM is not set -# CONFIG_RT2800USB_RT33XX is not set -# CONFIG_RTL8192CE is not set -CONFIG_WL1251_SPI=m -CONFIG_WL12XX_SPI=m -CONFIG_WL12XX_SDIO_TEST=m -# CONFIG_WIMAX_IWMC3200_SDIO is not set -CONFIG_USB_USBNET=y -CONFIG_USB_NET_CDCETHER=y -CONFIG_USB_NET_CDC_NCM=y -CONFIG_USB_NET_RNDIS_HOST=y -# CONFIG_ATM_TCP is not set -# CONFIG_IEEE802154_FAKEHARD is not set -# CONFIG_CAIF_TTY is not set -# CONFIG_CAIF_SPI_SLAVE is not set -CONFIG_PPP_BSDCOMP=m -# CONFIG_PPPOL2TP is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_ISDN is not set -CONFIG_INPUT_POLLDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_EVBUG=m -# CONFIG_KEYBOARD_QT2160 is not set -CONFIG_KEYBOARD_LKKBD=m -CONFIG_KEYBOARD_GPIO=m -CONFIG_KEYBOARD_TCA6416=m -CONFIG_KEYBOARD_MATRIX=m -CONFIG_KEYBOARD_LM8323=m -CONFIG_KEYBOARD_MCS=m -CONFIG_KEYBOARD_NEWTON=m -CONFIG_KEYBOARD_STOWAWAY=m -CONFIG_KEYBOARD_SUNKBD=m -# CONFIG_KEYBOARD_OMAP4 is not set -CONFIG_KEYBOARD_TWL4030=m -CONFIG_KEYBOARD_XTKBD=m -CONFIG_MOUSE_PS2=m -CONFIG_MOUSE_GPIO=m -CONFIG_JOYSTICK_AS5011=m -# CONFIG_TABLET_USB_HANWANG is not set -CONFIG_TOUCHSCREEN_ADS7846=m -CONFIG_TOUCHSCREEN_AD7877=m -CONFIG_TOUCHSCREEN_AD7879=m -CONFIG_TOUCHSCREEN_AD7879_I2C=m -# CONFIG_TOUCHSCREEN_AD7879_SPI is not set -CONFIG_TOUCHSCREEN_CY8CTMG110=m -CONFIG_TOUCHSCREEN_HAMPSHIRE=m -CONFIG_TOUCHSCREEN_QT602240=m -CONFIG_TOUCHSCREEN_TI_TSCADC=m -CONFIG_TOUCHSCREEN_TPS6507X=m -# CONFIG_TOUCHSCREEN_TSC2005 is not set -CONFIG_INPUT_AD714X=m -CONFIG_INPUT_AD714X_I2C=m -CONFIG_INPUT_AD714X_SPI=m -# CONFIG_INPUT_APPLEIR is not set -CONFIG_INPUT_TWL4030_PWRBUTTON=y -CONFIG_INPUT_TWL4030_VIBRA=y -CONFIG_INPUT_TWL6040_VIBRA=y -CONFIG_KEYBOARD_OMAP4=m -CONFIG_INPUT_UINPUT=y -# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set -CONFIG_INPUT_ADXL34X=m -CONFIG_INPUT_ADXL34X_I2C=m -CONFIG_INPUT_ADXL34X_SPI=m -# CONFIG_INPUT_CMA3000_I2C is not set -# CONFIG_SERIO_AMBAKMI is not set -# CONFIG_SERIO_RAW is not set -# CONFIG_SERIO_ALTERA_PS2 is not set -# CONFIG_GAMEPORT_NS558 is not set -# CONFIG_GAMEPORT_L4 is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_N_GSM is not set -CONFIG_SERIAL_8250_DETECT_IRQ=y -# CONFIG_SERIAL_AMBA_PL010 is not set -# CONFIG_SERIAL_AMBA_PL011 is not set -# CONFIG_SERIAL_MAX3100 is not set -# CONFIG_SERIAL_MAX3107 is not set -CONFIG_SERIAL_OMAP=y -CONFIG_SERIAL_OMAP_CONSOLE=y -# CONFIG_SERIAL_IFX6X60 is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_HW_RANDOM_TIMERIOMEM is not set -# CONFIG_R3964 is not set -# CONFIG_RAW_DRIVER is not set -CONFIG_I2C=y -CONFIG_I2C_CHARDEV=y -# CONFIG_I2C_GPIO is not set -CONFIG_I2C_OMAP=y -# CONFIG_I2C_SIMTEC is not set -CONFIG_I2C_TAOS_EVM=m -CONFIG_SPI=y -# CONFIG_SPI_DEBUG is not set -CONFIG_SPI_MASTER=y -# SPI Master Controller Drivers -# CONFIG_SPI_ALTERA is not set -# CONFIG_SPI_BITBANG is not set -# CONFIG_SPI_GPIO is not set -# CONFIG_SPI_OC_TINY is not set -CONFIG_SPI_OMAP24XX=y -# CONFIG_SPI_PL022 is not set -# CONFIG_SPI_PXA2XX_PCI is not set -# CONFIG_SPI_XILINX is not set -# CONFIG_SPI_DESIGNWARE is not set -# SPI Protocol Masters -CONFIG_SPI_SPIDEV=y -# CONFIG_SPI_TLE62X0 is not set - -# -# PPS support -# -# CONFIG_PPS is not set -CONFIG_ARCH_REQUIRE_GPIOLIB=y -CONFIG_GPIOLIB=y -# CONFIG_DEBUG_GPIO is not set -CONFIG_GPIO_SYSFS=y - -# -# Memory mapped GPIO expanders: -# -# CONFIG_GPIO_BASIC_MMIO is not set -# CONFIG_GPIO_IT8761E is not set -# CONFIG_GPIO_PL061 is not set - -# -# I2C GPIO expanders: -# -# CONFIG_GPIO_MAX7300 is not set -# CONFIG_GPIO_MAX732X is not set -# CONFIG_GPIO_PCF857X is not set -# CONFIG_GPIO_SX150X is not set -CONFIG_GPIO_TWL4030=y -# CONFIG_GPIO_ADP5588 is not set - -# -# PCI GPIO expanders: -# - -# -# SPI GPIO expanders: -# -# CONFIG_GPIO_MAX7301 is not set -# CONFIG_GPIO_MCP23S08 is not set -# CONFIG_GPIO_MC33880 is not set -# CONFIG_GPIO_74X164 is not set - -# -# AC97 GPIO expanders: -# - -# -# MODULbus GPIO expanders: -# -# CONFIG_W1 is not set -# CONFIG_CHARGER_TWL4030 is not set -# CONFIG_CHARGER_GPIO is not set -# CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_AD7414 is not set -# CONFIG_SENSORS_AD7418 is not set -# CONFIG_SENSORS_ADCXX is not set -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1026 is not set -# CONFIG_SENSORS_ADM1029 is not set -# CONFIG_SENSORS_ADM1031 is not set -# CONFIG_SENSORS_ADM9240 is not set -# CONFIG_SENSORS_ADT7411 is not set -# CONFIG_SENSORS_ADT7462 is not set -# CONFIG_SENSORS_ADT7470 is not set -# CONFIG_SENSORS_ADT7475 is not set -# CONFIG_SENSORS_ASC7621 is not set -# CONFIG_SENSORS_ATXP1 is not set -# CONFIG_SENSORS_DS620 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_F71805F is not set -# CONFIG_SENSORS_F71882FG is not set -# CONFIG_SENSORS_F75375S is not set -# CONFIG_SENSORS_G760A is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_GL520SM is not set -# CONFIG_SENSORS_GPIO_FAN is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM63 is not set -# CONFIG_SENSORS_LM70 is not set -# CONFIG_SENSORS_LM73 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM87 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_LM92 is not set -# CONFIG_SENSORS_LM93 is not set -# CONFIG_SENSORS_LTC4215 is not set -# CONFIG_SENSORS_LTC4245 is not set -# CONFIG_SENSORS_LTC4261 is not set -# CONFIG_SENSORS_LM95241 is not set -# CONFIG_SENSORS_MAX1111 is not set -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_MAX6650 is not set -# CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_PC87427 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_SHT15 is not set -# CONFIG_SENSORS_SHT21 is not set -# CONFIG_SENSORS_DME1737 is not set -# CONFIG_SENSORS_EMC1403 is not set -# CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_SMSC47M192 is not set -# CONFIG_SENSORS_SMSC47B397 is not set -# CONFIG_SENSORS_ADS7828 is not set -# CONFIG_SENSORS_ADS7871 is not set -# CONFIG_SENSORS_AMC6821 is not set -# CONFIG_SENSORS_THMC50 is not set -# CONFIG_SENSORS_TMP102 is not set -# CONFIG_SENSORS_TMP401 is not set -# CONFIG_SENSORS_TMP421 is not set -# CONFIG_SENSORS_VT1211 is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83791D is not set -# CONFIG_SENSORS_W83792D is not set -# CONFIG_SENSORS_W83793 is not set -# CONFIG_SENSORS_W83795 is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83L786NG is not set -# CONFIG_SENSORS_W83627HF is not set -# CONFIG_SENSORS_W83627EHF is not set -# CONFIG_SENSORS_LIS3_SPI is not set -# CONFIG_SENSORS_LIS3_I2C is not set -CONFIG_WATCHDOG_NOWAYOUT=y -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_MPCORE_WATCHDOG is not set -CONFIG_OMAP_WATCHDOG=y -# CONFIG_TWL4030_WATCHDOG is not set -CONFIG_SSB=y -# CONFIG_SSB_SDIOHOST is not set -CONFIG_MFD_CORE=y -# CONFIG_MFD_AAT2870_CORE is not set -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_MFD_ASIC3 is not set -# CONFIG_HTC_EGPIO is not set -# CONFIG_HTC_I2CPLD is not set -# CONFIG_TPS65010 is not set -CONFIG_TWL4030_CORE=y -# CONFIG_TWL4030_MADC is not set -CONFIG_TWL4030_POWER=y -CONFIG_TWL4030_CODEC=y -# CONFIG_TWL6030_PWM is not set -# CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TC6393XB is not set -# CONFIG_MFD_TPS65090 is not set/ -# CONFIG_PMIC_DA903X is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_MAX8925 is not set -# CONFIG_MFD_MAX8997 is not set -# CONFIG_MFD_MAX8998 is not set -# CONFIG_MFD_RC5T583 is not set -# CONFIG_MFD_WM8400 is not set -# CONFIG_MFD_WM831X_I2C is not set -# CONFIG_MFD_WM831X_SPI is not set -# CONFIG_MFD_WM8350_I2C is not set -# CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_MC13XXX is not set -# CONFIG_EZX_PCAP is not set -CONFIG_MFD_OMAP_USB_HOST=y -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS65910 is not set -# CONFIG_MFD_TPS65912_I2C is not set -# CONFIG_MFD_TPS65912_SPI is not set -# CONFIG_MFD_WL1273_CORE is not set -CONFIG_REGULATOR=y -# CONFIG_REGULATOR_DEBUG is not set -# CONFIG_REGULATOR_DUMMY is not set -CONFIG_REGULATOR_FIXED_VOLTAGE=y -# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set -# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set -# CONFIG_REGULATOR_BQ24022 is not set -# CONFIG_REGULATOR_MAX1586 is not set -# CONFIG_REGULATOR_MAX8649 is not set -# CONFIG_REGULATOR_MAX8660 is not set -# CONFIG_REGULATOR_MAX8952 is not set -CONFIG_REGULATOR_TWL4030=y -# CONFIG_REGULATOR_LP3971 is not set -# CONFIG_REGULATOR_LP3972 is not set -# CONFIG_REGULATOR_TPS62360 is not set -# CONFIG_REGULATOR_TPS65023 is not set -# CONFIG_REGULATOR_TPS6507X is not set -# CONFIG_REGULATOR_ISL6271A is not set -# CONFIG_REGULATOR_AD5398 is not set -# CONFIG_REGULATOR_TPS6524X is not set -CONFIG_VIDEOBUF_DMA_CONTIG=m -CONFIG_V4L2_MEM2MEM_DEV=m -# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set -# Encoders/decoders and other helper chips -# - -# -CONFIG_VIDEO_IR_I2C=m -CONFIG_VIDEO_CS5345=m -CONFIG_VIDEO_M52790=m -CONFIG_VIDEO_WM8739=m -CONFIG_VIDEO_VP27SMPX=m -CONFIG_VIDEO_OV7670=m -CONFIG_VIDEO_SAA717X=m -CONFIG_VIDEO_SAA7127=m -CONFIG_VIDEO_UPD64031A=m -CONFIG_VIDEO_UPD64083=m -CONFIG_VIDEO_ADP1653=m -# -# CONFIG_VIDEO_TVAUDIO is not set -# CONFIG_VIDEO_TDA7432 is not set -# CONFIG_VIDEO_TDA9840 is not set -# CONFIG_VIDEO_TEA6415C is not set -# CONFIG_VIDEO_TEA6420 is not set -# CONFIG_VIDEO_TLV320AIC23B is not set -# CONFIG_VIDEO_SAA6588 is not set -# CONFIG_VIDEO_ADV7180 is not set -# CONFIG_VIDEO_BT819 is not set -# CONFIG_VIDEO_BT856 is not set -# CONFIG_VIDEO_BT866 is not set -# CONFIG_VIDEO_KS0127 is not set -# CONFIG_VIDEO_MT9V011 is not set -# CONFIG_VIDEO_MT9V032 is not set -# CONFIG_VIDEO_TCM825X is not set -# CONFIG_VIDEO_SAA7110 is not set -# CONFIG_VIDEO_SAA7191 is not set -# CONFIG_VIDEO_TVP514X is not set -# CONFIG_VIDEO_TVP5150 is not set -CONFIG_VIDEO_TVP7002=m -# CONFIG_VIDEO_VPX3220 is not set -# CONFIG_VIDEO_SAA7185 is not set -# CONFIG_VIDEO_ADV7170 is not set -# CONFIG_VIDEO_ADV7175 is not set -# CONFIG_VIDEO_THS7303 is not set -# CONFIG_VIDEO_ADV7343 is not set -CONFIG_VIDEO_AK881X=m -# CONFIG_VIDEO_VPFE_CAPTURE is not set -CONFIG_VIDEO_OMAP2_VOUT=m -# CONFIG_VIDEO_CPIA2 is not set -# CONFIG_VIDEO_AU0828 is not set -# CONFIG_VIDEO_SR030PC30 is not set -# CONFIG_VIDEO_OMAP3 is not set -# CONFIG_SOC_CAMERA is not set -CONFIG_USB_ET61X251=m -CONFIG_USB_SN9C102=m -CONFIG_VIDEO_MEM2MEM_TESTDEV=m -CONFIG_RADIO_TEA5764=m -CONFIG_RADIO_SAA7706H=m -CONFIG_RADIO_TEF6862=m -# CONFIG_TTPCI_EEPROM is not set -# CONFIG_SMS_SDIO_DRV is not set -# CONFIG_DVB_DUMMY_FE is not set -CONFIG_DRM=m -CONFIG_DRM_OMAP=m -CONFIG_DRM_OMAP_NUM_CRTCS=2 -# CONFIG_VGASTATE is not set -# CONFIG_VIDEO_OUTPUT_CONTROL is not set -# CONFIG_FB_DDC is not set -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_IMAGEBLIT=y -# CONFIG_FB_SVGALIB is not set -# CONFIG_FB_BACKLIGHT is not set -# CONFIG_FB_TILEBLITTING is not set -# CONFIG_FB_ARMCLCD is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FB_METRONOME is not set -# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set -# CONFIG_FB_OMAP_LCD_VGA is not set -CONFIG_OMAP2_VRAM=y -CONFIG_OMAP2_VRFB=y -CONFIG_OMAP2_DSS=y -CONFIG_OMAP2_VRAM_SIZE=12 -CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y -# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set -CONFIG_OMAP2_DSS_DPI=y -# CONFIG_OMAP2_DSS_RFBI is not set -CONFIG_OMAP2_DSS_VENC=y -CONFIG_OMAP4_DSS_HDMI=y -# CONFIG_OMAP2_DSS_SDI is not set -# CONFIG_OMAP2_DSS_DSI is not set -# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set -CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1 -CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET=y -CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y -# CONFIG_FB_OMAP2 is not set - -# -# OMAP2/3 Display Device Drivers -# -CONFIG_PANEL_GENERIC_DPI=y -CONFIG_PANEL_SHARP_LS037V7DW01=y -CONFIG_PANEL_NEC_NL8048HL11_01B=y -CONFIG_PANEL_TPO_TD043MTEA1=y -# CONFIG_LCD_L4F00242T03 is not set -# CONFIG_LCD_LMS283GF05 is not set -# CONFIG_LCD_LTV350QV is not set -# CONFIG_LCD_TDO24M is not set -# CONFIG_LCD_VGG2432A4 is not set -# CONFIG_LCD_PLATFORM is not set -# CONFIG_LCD_S6E63M0 is not set -# CONFIG_LCD_AMS369FG06 is not set -CONFIG_BACKLIGHT_GENERIC=m -# CONFIG_BACKLIGHT_PANDORA is not set -CONFIG_DISPLAY_SUPPORT=y -# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -CONFIG_LOGO_LINUX_MONO=y -CONFIG_LOGO_LINUX_VGA16=y -CONFIG_SOUND=y -CONFIG_SND=y -CONFIG_SND_TIMER=y -CONFIG_SND_PCM=y -CONFIG_SND_HWDEP=m -CONFIG_SND_RAWMIDI=m -CONFIG_SND_JACK=y -CONFIG_SND_SEQUENCER=m -CONFIG_SND_SEQ_DUMMY=m -CONFIG_SND_OSSEMUL=y -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m -CONFIG_SND_PCM_OSS_PLUGINS=y -CONFIG_SND_SEQUENCER_OSS=y -CONFIG_SND_HRTIMER=m -CONFIG_SND_SEQ_HRTIMER_DEFAULT=y -CONFIG_SND_DYNAMIC_MINORS=y -CONFIG_SND_SUPPORT_OLD_API=y -CONFIG_SND_VERBOSE_PROCFS=y -# CONFIG_SND_VERBOSE_PRINTK is not set -# CONFIG_SND_DEBUG is not set -CONFIG_SND_RAWMIDI_SEQ=m -# CONFIG_SND_OPL3_LIB_SEQ is not set -# CONFIG_SND_OPL4_LIB_SEQ is not set -# CONFIG_SND_SBAWE_SEQ is not set -# CONFIG_SND_EMU10K1_SEQ is not set -# CONFIG_SND_DRIVERS is not set -# CONFIG_SND_ARM is not set -# CONFIG_SND_SPI is not set -CONFIG_SND_USB=y -CONFIG_SND_USB_AUDIO=m -CONFIG_SND_USB_UA101=m -CONFIG_SND_USB_CAIAQ=m -CONFIG_SND_USB_CAIAQ_INPUT=y -CONFIG_SND_SOC=y -# CONFIG_SND_SOC_CACHE_LZO is not set -CONFIG_SND_OMAP_SOC=y -CONFIG_SND_OMAP_SOC_MCBSP=y -CONFIG_SND_OMAP_SOC_MCPDM=y -CONFIG_SND_OMAP_SOC_RX51=y -CONFIG_SND_OMAP_SOC_OVERO=y -CONFIG_SND_OMAP_SOC_OMAP3EVM=y -CONFIG_SND_OMAP_SOC_AM3517EVM=y -CONFIG_SND_OMAP_SOC_SDP3430=y -CONFIG_SND_OMAP_SOC_SDP4430=y -CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=y -CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y -CONFIG_SND_OMAP_SOC_ZOOM2=y -CONFIG_SND_OMAP_SOC_IGEP0020=y -CONFIG_SND_OMAP_SOC_OMAP4_HDMI=y -CONFIG_SND_SOC_I2C_AND_SPI=y -# CONFIG_SND_SOC_ALL_CODECS is not set -CONFIG_SND_SOC_TLV320AIC23=y -CONFIG_SND_SOC_TLV320AIC3X=y -CONFIG_SND_SOC_TWL4030=y -CONFIG_SND_SOC_TWL6040=y -# CONFIG_SOUND_PRIME is not set -# CONFIG_HID_TIVO_SLIDE is not set -# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set -# CONFIG_USB_DEVICEFS is not set -CONFIG_USB_OTG=y -# CONFIG_USB_OTG_WHITELIST is not set -# CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_WUSB is not set -# CONFIG_USB_WUSB_CBAF is not set -# CONFIG_USB_EHCI_ROOT_HUB_TT is not set -CONFIG_USB_EHCI_HCD_OMAP=y -# CONFIG_USB_ISP1362_HCD is not set -# CONFIG_USB_OHCI_HCD is not set -# CONFIG_USB_U132_HCD is not set -# CONFIG_USB_SL811_HCD is not set -# CONFIG_USB_HWA_HCD is not set -# CONFIG_USB_MUSB_TUSB6010 is not set -CONFIG_USB_MUSB_OMAP2PLUS=y -# CONFIG_USB_MUSB_AM35X is not set -# CONFIG_USB_MUSB_HOST is not set -# CONFIG_USB_MUSB_PERIPHERAL is not set -CONFIG_USB_MUSB_OTG=y -CONFIG_USB_GADGET_MUSB_HDRC=y -CONFIG_USB_INVENTRA_DMA=y -CONFIG_USB_STORAGE=y -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_DATAFAB=m -CONFIG_USB_STORAGE_FREECOM=m -CONFIG_USB_STORAGE_ISD200=m -CONFIG_USB_STORAGE_USBAT=m -CONFIG_USB_STORAGE_SDDR09=m -CONFIG_USB_STORAGE_SDDR55=m -CONFIG_USB_STORAGE_JUMPSHOT=m -CONFIG_USB_STORAGE_ALAUDA=m -CONFIG_USB_STORAGE_ONETOUCH=m -CONFIG_USB_STORAGE_KARMA=m -CONFIG_USB_STORAGE_CYPRESS_ATACB=m -# CONFIG_USB_UAS is not set -# CONFIG_USB_LIBUSUAL is not set -CONFIG_USB_SERIAL_KEYSPAN_MPR=y -CONFIG_USB_SERIAL_KEYSPAN_USA28=y -CONFIG_USB_SERIAL_KEYSPAN_USA28X=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y -CONFIG_USB_SERIAL_KEYSPAN_USA19=y -CONFIG_USB_SERIAL_KEYSPAN_USA18X=y -CONFIG_USB_SERIAL_KEYSPAN_USA19W=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y -CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y -# CONFIG_USB_SERIAL_SAFE_PADDED is not set -# CONFIG_USB_SERIAL_SAMBA is not set -CONFIG_USB_SERIAL_ZIO=m -CONFIG_USB_RIO500=m -CONFIG_USB_CYPRESS_CY7C63=m -CONFIG_USB_CYTHERM=m -CONFIG_USB_TEST=m -CONFIG_USB_GADGET=y -# CONFIG_USB_GADGET_DEBUG is not set -# CONFIG_USB_GADGET_DEBUG_FILES is not set -CONFIG_USB_GADGET_DEBUG_FS=y -CONFIG_USB_GADGET_VBUS_DRAW=2 -CONFIG_USB_GADGET_SELECTED=y -# CONFIG_USB_GADGET_OMAP is not set -# CONFIG_USB_GADGET_R8A66597 is not set -# CONFIG_USB_GADGET_PXA_U2O is not set -# CONFIG_USB_GADGET_M66592 is not set -# CONFIG_USB_GADGET_DUMMY_HCD is not set -CONFIG_USB_GADGET_DUALSPEED=y -# CONFIG_USB_ZERO is not set -# CONFIG_USB_AUDIO is not set -CONFIG_USB_ETH=y -CONFIG_USB_ETH_RNDIS=y -CONFIG_USB_ETH_EEM=y -# CONFIG_USB_G_NCM is not set -# CONFIG_USB_GADGETFS is not set -# CONFIG_USB_FUNCTIONFS is not set -# CONFIG_USB_FILE_STORAGE is not set -# CONFIG_USB_MASS_STORAGE is not set -# CONFIG_USB_G_SERIAL is not set -# CONFIG_USB_MIDI_GADGET is not set -# CONFIG_USB_G_PRINTER is not set -# CONFIG_USB_CDC_COMPOSITE is not set -# CONFIG_USB_G_NOKIA is not set -# CONFIG_USB_G_MULTI is not set -# CONFIG_USB_G_HID is not set -# CONFIG_USB_G_DBGP is not set -# CONFIG_USB_G_WEBCAM is not set -CONFIG_USB_GPIO_VBUS=y -# CONFIG_ISP1301_OMAP is not set -CONFIG_TWL4030_USB=y -CONFIG_TWL6030_USB=y -CONFIG_NOP_USB_XCEIV=y -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_OMAP=m -CONFIG_MMC_OMAP_HS=y -CONFIG_MMC_SPI=m -# CONFIG_MMC_DW is not set -# CONFIG_MMC_USHC is not set -# CONFIG_MEMSTICK is not set -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_GPIO_PLATFORM=y -CONFIG_LEDS_GPIO_OF=y -# CONFIG_LEDS_LP3944 is not set -# CONFIG_LEDS_LP5521 is not set -# CONFIG_LEDS_LP5523 is not set -# CONFIG_LEDS_DAC124S085 is not set -# CONFIG_LEDS_REGULATOR is not set -# CONFIG_LEDS_LT3593 is not set -CONFIG_LEDS_TRIGGER_HEARTBEAT=y -# CONFIG_LEDS_TRIGGER_GPIO is not set -# CONFIG_NFC_DEVICES is not set -# CONFIG_ACCESSIBILITY is not set -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_TWL4030=m -CONFIG_RTC_DRV_S35390A=m -CONFIG_RTC_DRV_M41T94=m -CONFIG_RTC_DRV_DS1305=m -CONFIG_RTC_DRV_DS1390=m -CONFIG_RTC_DRV_MAX6902=m -CONFIG_RTC_DRV_R9701=m -CONFIG_RTC_DRV_RS5C348=m -CONFIG_RTC_DRV_DS3234=m -CONFIG_RTC_DRV_PCF2123=m -CONFIG_RTC_DRV_CMOS=m -CONFIG_RTC_DRV_M48T86=m -# CONFIG_RTC_DRV_PL030 is not set -# CONFIG_RTC_DRV_PL031 is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_VICAM is not set -CONFIG_PRISM2_USB=m -CONFIG_BRCM80211=y -CONFIG_BRCMFMAC=y -CONFIG_RT2870=m -CONFIG_R8712U=m -CONFIG_R8712_AP=y -CONFIG_ZRAM=m -# CONFIG_ZRAM_DEBUG is not set -# CONFIG_LIRC_STAGING is not set -CONFIG_TIDSPBRIDGE=m -CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE=0x600000 -# CONFIG_TIDSPBRIDGE_DEBUG is not set -CONFIG_TIDSPBRIDGE_RECOVERY=y -# CONFIG_TIDSPBRIDGE_CACHE_LINE_CHECK is not set -CONFIG_TIDSPBRIDGE_WDT3=y -CONFIG_TIDSPBRIDGE_WDT_TIMEOUT=5 -# CONFIG_TIDSPBRIDGE_NTFY_PWRERR is not set -# CONFIG_TIDSPBRIDGE_BACKTRACE is not set -# CONFIG_WESTBRIDGE is not set -CONFIG_WESTBRIDGE_HAL_SELECTED=y -CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL=y -# CONFIG_MACH_NO_WESTBRIDGE is not set -# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set -# CONFIG_REISERFS_PROC_INFO is not set -CONFIG_JFS_STATISTICS=y -CONFIG_XFS_RT=y -CONFIG_OCFS2_FS_STATS=y -CONFIG_OCFS2_DEBUG_MASKLOG=y -# CONFIG_BTRFS_FS is not set -CONFIG_PRINT_QUOTA_WARNING=y -CONFIG_QUOTA_TREE=m -CONFIG_QFMT_V1=m -CONFIG_QFMT_V2=m -CONFIG_AUTOFS4_FS=m -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set -# CONFIG_JFFS2_SUMMARY is not set -# CONFIG_JFFS2_FS_XATTR is not set -CONFIG_JFFS2_COMPRESSION_OPTIONS=y -CONFIG_JFFS2_LZO=y -CONFIG_JFFS2_ZLIB=y -CONFIG_JFFS2_RTIME=y -# CONFIG_JFFS2_RUBIN is not set -# CONFIG_JFFS2_CMODE_NONE is not set -# CONFIG_JFFS2_CMODE_PRIORITY is not set -# CONFIG_JFFS2_CMODE_SIZE is not set -CONFIG_JFFS2_CMODE_FAVOURLZO=y -# CONFIG_LOGFS is not set -CONFIG_NFS_FS=m -# CONFIG_NFS_V4_1 is not set -CONFIG_ROOT_NFS=y -CONFIG_NFSD_DEPRECATED=y -CONFIG_LOCKD=y -CONFIG_NFS_ACL_SUPPORT=y -# CONFIG_CIFS_STATS is not set -# CONFIG_CIFS_FSCACHE is not set -# CONFIG_CIFS_ACL is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_9P_FSCACHE is not set -# CONFIG_9P_FS_POSIX_ACL is not set -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_ASCII=m -CONFIG_NLS_ISO8859_1=y -# CONFIG_DLM_DEBUG is not set -CONFIG_ENABLE_WARN_DEPRECATED=y -# CONFIG_STRIP_ASM_SYMS is not set -# CONFIG_HEADERS_CHECK is not set -# CONFIG_DEBUG_SHIRQ is not set -# CONFIG_LOCKUP_DETECTOR is not set -CONFIG_DETECT_HUNG_TASK=y -CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 -# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 -CONFIG_DEBUG_PREEMPT=y -# CONFIG_BKL is not set -# CONFIG_SPARSE_RCU_POINTER is not set -# CONFIG_DEBUG_HIGHMEM is not set -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_LIST is not set -# CONFIG_BOOT_PRINTK_DELAY is not set -# CONFIG_RCU_CPU_STALL_DETECTOR is not set -CONFIG_RCU_CPU_STALL_TIMEOUT=60 -CONFIG_RCU_CPU_STALL_VERBOSE=y -# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y -# CONFIG_FUNCTION_TRACER is not set -# CONFIG_PREEMPT_TRACER is not set -# CONFIG_STACK_TRACER is not set -# CONFIG_RING_BUFFER_BENCHMARK is not set -# CONFIG_DYNAMIC_DEBUG is not set -# CONFIG_ATOMIC64_SELFTEST is not set -# CONFIG_KGDB_TESTS is not set -# CONFIG_TEST_KSTRTOX is not set -# CONFIG_STRICT_DEVMEM is not set -CONFIG_DEBUG_USER=y -CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_LL=y -CONFIG_EARLY_PRINTK=y -# CONFIG_DEBUG_ICEDCC is not set -CONFIG_OC_ETM=y -# CONFIG_KEYS_DEBUG_PROC_KEYS is not set -# CONFIG_IMA is not set -CONFIG_CRYPTO_AEAD=m -CONFIG_CRYPTO_RNG=m -# CONFIG_CRYPTO_PCRYPT is not set -CONFIG_CRYPTO_CRYPTD=m -CONFIG_CRYPTO_SEQIV=m -CONFIG_CRYPTO_CTR=m -# CONFIG_CRYPTO_VMAC is not set -CONFIG_CRYPTO_SHA1=m -CONFIG_CRYPTO_AES=m -# CONFIG_CRYPTO_CAST6 is not set -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_USER_API=m -CONFIG_CRYPTO_USER_API_HASH=m -CONFIG_CRYPTO_USER_API_SKCIPHER=m -CONFIG_CRYPTO_DEV_OMAP_SHAM=m -CONFIG_CRYPTO_DEV_OMAP_AES=m -CONFIG_LIBCRC32C=y -# CONFIG_RFKILL_REGULATOR is not set -# CONFIG_RFKILL_GPIO is not set -# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set -# CONFIG_LCD_LD9040 is not set -# CONFIG_RTC_DRV_M41T93 is not set -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_OPROFILE is not set -# CONFIG_OPROFILE is not set -# CONFIG_PATA_ARASAN_CF is not set -# CONFIG_BT_ATH3K is not set -# CONFIG_BT_WILINK is not set -# CONFIG_USB_HSO is not set - -CONFIG_GPIO_GENERIC_PLATFORM=y - -CONFIG_MACH_OMAP_GENERIC=y -CONFIG_PL310_ERRATA_753970=y -CONFIG_ARM_CPU_TOPOLOGY=y -CONFIG_SCHED_MC=y -CONFIG_SCHED_SMT=y -CONFIG_ETHERNET=y -CONFIG_NET_VENDOR_BROADCOM=y -CONFIG_NET_VENDOR_MICROCHIP=y -CONFIG_SENSORS_AD7314=m -CONFIG_REGULATOR_GPIO=y -CONFIG_VIDEO_MT9P031=m -CONFIG_VIDEO_MT9T001=m -CONFIG_VIDEO_S5K6AA=m -CONFIG_PANEL_DVI=m -CONFIG_PANEL_PICODLP=m -CONFIG_USB_RENESAS_USBHS=m -CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 -CONFIG_LEDS_RENESAS_TPU=y -# CONFIG_OMAP_IOMMU is not set -CONFIG_USB_RENESAS_USBHS_HCD=m - -# CONFIG_ARM_LPAE is not set -# CONFIG_INPUT_GP2A is not set -# CONFIG_INPUT_GPIO_TILT_POLLED is not set -# CONFIG_SOC_OMAPTI81XX is not set -# CONFIG_SOC_OMAPAM33XX is not set -# CONFIG_MACH_TI8148EVM is not set -# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set -# CONFIG_MICREL_KS8995MA is not set -# CONFIG_CHARGER_MANAGER is not set -# CONFIG_MFD_DA9052_SPI is not set -# CONFIG_MFD_DA9052_I2C is not set -# CONFIG_MFD_S5M_CORE is not set -# CONFIG_VIDEO_AS3645A is not set -# CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set -# - diff --git a/config-arm-tegra b/config-arm-tegra deleted file mode 100644 index ef4f53599..000000000 --- a/config-arm-tegra +++ /dev/null @@ -1,99 +0,0 @@ -CONFIG_ARCH_TEGRA=y - -CONFIG_ARCH_TEGRA_2x_SOC=y -# CONFIG_ARCH_TEGRA_3x_SOC is not set -# CONFIG_ARM_LPAE is not set -CONFIG_TEGRA_PCI=y - -CONFIG_MACH_HARMONY=y -CONFIG_MACH_KAEN=y -CONFIG_MACH_PAZ00=y -CONFIG_MACH_SEABOARD=y -CONFIG_MACH_TEGRA_DT=y -CONFIG_MACH_TRIMSLICE=y -CONFIG_MACH_WARIO=y -CONFIG_MACH_TEGRA_DT=y -CONFIG_MACH_VENTANA=y - -CONFIG_TEGRA_DEBUG_UARTD=y -CONFIG_NO_HZ=y -CONFIG_PREEMPT=y -CONFIG_AEABI=y - -CONFIG_I2C_TEGRA=y - -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMC_SDHCI_TEGRA=y - -# CONFIG_RCU_BOOST is not set -CONFIG_TEGRA_SYSTEM_DMA=y -CONFIG_TEGRA_EMC_SCALING_ENABLE=y -CONFIG_ARM_THUMBEE=y -CONFIG_SWP_EMULATE=y -# CONFIG_CPU_BPREDICT_DISABLE is not set -CONFIG_CACHE_L2X0=y -CONFIG_ARM_ERRATA_430973=y -# CONFIG_ARM_ERRATA_458693 is not set -# CONFIG_ARM_ERRATA_460075 is not set -CONFIG_ARM_ERRATA_742230=y -# CONFIG_ARM_ERRATA_742231 is not set -CONFIG_PL310_ERRATA_588369=y -CONFIG_PL310_ERRATA_769419=y -CONFIG_ARM_ERRATA_720789=y -# CONFIG_PL310_ERRATA_727915 is not set -# CONFIG_ARM_ERRATA_743622 is not set -# CONFIG_ARM_ERRATA_751472 is not set -# CONFIG_ARM_ERRATA_753970 is not set -# CONFIG_ARM_ERRATA_754322 is not set -# CONFIG_ARM_ERRATA_754327 is not set -# CONFIG_ARM_ERRATA_764369 is not set -CONFIG_SMP_ON_UP=y -CONFIG_LOCAL_TIMERS=y -# CONFIG_THUMB2_KERNEL is not set -# CONFIG_NEON is not set -# CONFIG_RFKILL_GPIO is not set -CONFIG_GPIO_GENERIC_PLATFORM=y -# CONFIG_GPIO_MCP23S08 is not set -# CONFIG_KEYBOARD_TEGRA is not set -# CONFIG_MPCORE_WATCHDOG is not set -CONFIG_USB_EHCI_TEGRA=y -CONFIG_RTC_DRV_TEGRA=y - -CONFIG_SND_SOC_TEGRA=m -CONFIG_SND_SOC_TEGRA_ALC5632=m -CONFIG_SND_SOC_TEGRA_WM8903=m -CONFIG_SND_SOC_TEGRA_TRIMSLICE=m - -CONFIG_MFD_NVEC=y -# CONFIG_DEBUG_PREEMPT is not set -# CONFIG_RCU_CPU_STALL_VERBOSE is not set -# CONFIG_PREEMPT_TRACER is not set -# CONFIG_DEBUG_PINCTRL is not set -CONFIG_KEYBOARD_NVEC=y -CONFIG_SERIO_NVEC_PS2=y -CONFIG_NVEC_POWER=y -CONFIG_POWER_SUPPLY=y -CONFIG_NVEC_LEDS=y - -CONFIG_CPU_PM=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARM_CPU_SUSPEND=y - -CONFIG_CRYPTO_DEV_TEGRA_AES=m - -CONFIG_PL310_ERRATA_753970=y -CONFIG_SCHED_MC=y -CONFIG_SCHED_SMT=y -CONFIG_LEDS_RENESAS_TPU=y - -CONFIG_OF_GPIO=y -CONFIG_OF_PCI=y -CONFIG_OF_PCI_IRQ=y -CONFIG_OF=y -CONFIG_SERIAL_OF_PLATFORM=y - -CONFIG_TEGRA_IOMMU_GART=y -CONFIG_TEGRA_IOMMU_SMMU=y diff --git a/kernel.spec b/kernel.spec index 2069a06c8..1286e8f29 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -124,16 +124,6 @@ Summary: The Linux kernel %define with_bootwrapper %{?_without_bootwrapper: 0} %{?!_without_bootwrapper: 1} # Want to build a the vsdo directories installed %define with_vdso_install %{?_without_vdso_install: 0} %{?!_without_vdso_install: 1} -# ARM OMAP (Beagle/Panda Board) -%define with_omap %{?_without_omap: 0} %{?!_without_omap: 1} -# kernel-tegra (only valid for arm) -%define with_tegra %{?_without_tegra: 0} %{?!_without_tegra: 1} -# kernel-kirkwood (only valid for arm) -%define with_kirkwood %{?_without_kirkwood: 0} %{?!_without_kirkwood: 1} -# kernel-imx (only valid for arm) -%define with_imx %{?_without_imx: 0} %{?!_without_imx: 1} -# kernel-highbank (only valid for arm) -%define with_highbank %{?_without_highbank: 0} %{?!_without_highbank: 1} # Build the kernel-doc package, but don't fail the build if it botches. # Here "true" means "continue" and "false" means "fail the build". @@ -244,19 +234,6 @@ Summary: The Linux kernel %define with_pae 0 %endif -# kernel-tegra, omap, imx and highbank are only built on armv7 hard and softfp -%ifnarch armv7hl armv7l -%define with_tegra 0 -%define with_omap 0 -%define with_imx 0 -%define with_highbank 0 -%endif - -# kernel-kirkwood is only built for armv5 -%ifnarch armv5tel -%define with_kirkwood 0 -%endif - # if requested, only build base kernel %if %{with_baseonly} %define with_smp 0 @@ -399,26 +376,6 @@ Summary: The Linux kernel %define kernel_image vmlinux %endif -%ifarch %{arm} -%define all_arch_configs kernel-%{version}-arm*.config -%define image_install_path boot -%define asmarch arm -%define hdrarch arm -%define make_target bzImage -%define kernel_image arch/arm/boot/zImage -# we build a up kernel on armv5tel. its used for qemu. -%ifnarch armv5tel -%define with_up 0 -%endif -# we only build headers on the base arm arches -# just like we used to only build them on i386 for x86 -%ifnarch armv5tel armv7hl -%define with_headers 0 -%define with_perf 0 -%define with_tools 0 -%endif -%endif - %if %{nopatches} # XXX temporary until last vdso patches are upstream %define vdso_arches ppc ppc64 @@ -530,7 +487,7 @@ Version: %{rpmversion} Release: %{pkg_release} # DO NOT CHANGE THE 'ExclusiveArch' LINE TO TEMPORARILY EXCLUDE AN ARCHITECTURE BUILD. # SET %%nobuildarches (ABOVE) INSTEAD -ExclusiveArch: noarch %{all_x86} x86_64 ppc ppc64 %{sparc} s390 s390x alpha alphaev56 %{arm} +ExclusiveArch: noarch %{all_x86} x86_64 ppc ppc64 %{sparc} s390 s390x alpha alphaev56 ExclusiveOS: Linux %kernel_reqprovconf @@ -591,13 +548,6 @@ Source70: config-s390x Source90: config-sparc64-generic -Source100: config-arm-generic -Source110: config-arm-omap-generic -Source111: config-arm-tegra -Source112: config-arm-kirkwood -Source113: config-arm-imx -Source114: config-arm-highbank - # This file is intentionally left empty in the stock kernel. Its a nicety # added for those wanting to do custom rebuilds with altered config opts. Source1000: config-local @@ -730,10 +680,6 @@ Patch20000: uprobes-3.4-backport.patch Patch20001: uprobes-3.4-tip.patch Patch20002: uprobes-task_work_add-generic-process-context-callbacks.patch -# Flattened devicetree support -Patch21000: arm-omap-dt-compat.patch -Patch21001: arm-smsc-support-reading-mac-address-from-device-tree.patch - #rhbz 769766 Patch21072: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch @@ -978,36 +924,6 @@ This variant of the kernel has numerous debugging options enabled. It should only be installed when trying to gather additional information on kernel bugs, as some of these options impact performance noticably. -%define variant_summary The Linux kernel compiled for marvell kirkwood boards -%kernel_variant_package kirkwood -%description kirkwood -This package includes a version of the Linux kernel with support for -marvell kirkwood based systems, i.e., guruplug, sheevaplug - -%define variant_summary The Linux kernel compiled for freescale boards -%kernel_variant_package imx -%description imx -This package includes a version of the Linux kernel with support for -freescale based systems, i.e., efika smartbook. - -%define variant_summary The Linux kernel compiled for Calxeda boards -%kernel_variant_package highbank -%description highbank -This package includes a version of the Linux kernel with support for -Calxeda based systems, i.e., HP arm servers. - -%define variant_summary The Linux kernel compiled for TI-OMAP boards -%kernel_variant_package omap -%description omap -This package includes a version of the Linux kernel with support for -TI-OMAP based systems, i.e., BeagleBoard-xM. - -%define variant_summary The Linux kernel compiled for tegra boards -%kernel_variant_package tegra -%description tegra -This package includes a version of the Linux kernel with support for -nvidia tegra based systems, i.e., trimslice, ac-100. - %prep # do a few sanity-checks for --with *only builds @@ -1264,12 +1180,6 @@ ApplyOptionalPatch linux-2.6-upstream-reverts.patch -R # Architecture patches # x86(-64) -# -# ARM -# -# ApplyPatch arm-omap-dt-compat.patch -# ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch - ApplyPatch taint-vbox.patch # # NX Emulation @@ -1734,26 +1644,6 @@ BuildKernel %make_target %kernel_image PAEdebug BuildKernel %make_target %kernel_image PAE %endif -%if %{with_kirkwood} -BuildKernel %make_target %kernel_image kirkwood -%endif - -%if %{with_imx} -BuildKernel %make_target %kernel_image imx -%endif - -%if %{with_highbank} -BuildKernel %make_target %kernel_image highbank -%endif - -%if %{with_omap} -BuildKernel %make_target %kernel_image omap -%endif - -%if %{with_tegra} -BuildKernel %make_target %kernel_image tegra -%endif - %if %{with_up} BuildKernel %make_target %kernel_image %endif @@ -1999,21 +1889,6 @@ fi}\ %kernel_variant_post -v PAEdebug -r (kernel|kernel-smp) %kernel_variant_preun PAEdebug -%kernel_variant_preun kirkwood -%kernel_variant_post -v kirkwood - -%kernel_variant_preun imx -%kernel_variant_post -v imx - -%kernel_variant_preun highbank -%kernel_variant_post -v highbank - -%kernel_variant_preun omap -%kernel_variant_post -v omap - -%kernel_variant_preun tegra -%kernel_variant_post -v tegra - if [ -x /sbin/ldconfig ] then /sbin/ldconfig -X || exit $? @@ -2143,17 +2018,13 @@ fi %kernel_variant_files %{with_debug} debug %kernel_variant_files %{with_pae} PAE %kernel_variant_files %{with_pae_debug} PAEdebug -%kernel_variant_files %{with_kirkwood} kirkwood -%kernel_variant_files %{with_imx} imx -%kernel_variant_files %{with_highbank} highbank -%kernel_variant_files %{with_omap} omap -%kernel_variant_files %{with_tegra} tegra # plz don't put in a version string unless you're going to tag # and build. %changelog * Wed Jul 25 2012 Josh Boyer +- Drop ARM support. It isn't built in F16. - Add patch to fix cpu pinning after suspend/resume (rhbz 714271) * Thu Jul 19 2012 Josh Boyer - 3.4.6-1 From 9f67b6884b26743cc80c72485cf05306eec45096 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 26 Jul 2012 10:17:19 -0400 Subject: [PATCH 418/487] Apply patch to fix uvcvideo crash (rhbz 836742) --- kernel.spec | 9 +++++ ...ield-when-recycling-erroneous-buffer.patch | 36 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch diff --git a/kernel.spec b/kernel.spec index 1286e8f29..d9816f479 100644 --- a/kernel.spec +++ b/kernel.spec @@ -707,6 +707,9 @@ Patch22056: crypto-aesni-intel-fix-wrong-kfree-pointer.patch #rhbz 772730 Patch22058: ACPI-AC-check-the-return-value-of-power_supply_register.patch +#rhbz 836742 +Patch22059: uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch + #rhbz 714271 Patch22060: CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch @@ -1322,6 +1325,9 @@ ApplyPatch crypto-aesni-intel-fix-wrong-kfree-pointer.patch #rhbz 772730 ApplyPatch ACPI-AC-check-the-return-value-of-power_supply_register.patch +#rhbz 836742 +ApplyPatch uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch + #rhbz 714271 ApplyPatch CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch @@ -2023,6 +2029,9 @@ fi # and build. %changelog +* Thu Jul 26 2012 Josh Boyer +- Apply patch to fix uvcvideo crash (rhbz 836742) + * Wed Jul 25 2012 Josh Boyer - Drop ARM support. It isn't built in F16. - Add patch to fix cpu pinning after suspend/resume (rhbz 714271) diff --git a/uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch b/uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch new file mode 100644 index 000000000..6606b7d3d --- /dev/null +++ b/uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch @@ -0,0 +1,36 @@ +From 3771973542a4807b251352253ed22c50e688e573 Mon Sep 17 00:00:00 2001 +From: Jayakrishnan Memana +Date: Sun, 15 Jul 2012 15:54:03 +0200 +Subject: [PATCH] uvcvideo: Reset the bytesused field when recycling an erroneous buffer + +Buffers marked as erroneous are recycled immediately by the driver if +the nodrop module parameter isn't set. The buffer payload size is reset +to 0, but the buffer bytesused field isn't. This results in the buffer +being immediately considered as complete, leading to an infinite loop in +interrupt context. + +Fix the problem by resetting the bytesused field when recycling the +buffer. + +Cc: +Signed-off-by: Jayakrishnan Memana +Signed-off-by: Laurent Pinchart +--- + drivers/media/video/uvc/uvc_queue.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c +index 9288fbd..5577381 100644 +--- a/drivers/media/video/uvc/uvc_queue.c ++++ b/drivers/media/video/uvc/uvc_queue.c +@@ -338,6 +338,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, + if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) { + buf->error = 0; + buf->state = UVC_BUF_STATE_QUEUED; ++ buf->bytesused = 0; + vb2_set_plane_payload(&buf->buf, 0, 0); + return buf; + } +-- +1.7.2.5 + From 4750a280ed43448d9459065a9c237eaa64c5e580 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 26 Jul 2012 13:40:12 -0400 Subject: [PATCH 419/487] kernel: recv{from,msg}() on an rds socket can leak kernel memory (rhbz 820039 843554) - Apply patch to fix uvcvideo crash (rhbz 836742) --- kernel.spec | 8 ++ rds-set-correct-msg_namelen.patch | 219 ++++++++++++++++++++++++++++++ 2 files changed, 227 insertions(+) create mode 100644 rds-set-correct-msg_namelen.patch diff --git a/kernel.spec b/kernel.spec index d9816f479..7e3b1d3dc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -713,6 +713,9 @@ Patch22059: uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch #rhbz 714271 Patch22060: CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch +#rhbz 820039 843554 +Patch22061: rds-set-correct-msg_namelen.patch + # END OF PATCH DEFINITIONS %endif @@ -1331,6 +1334,9 @@ ApplyPatch uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch #rhbz 714271 ApplyPatch CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch +#rhbz 820039 843554 +ApplyPatch rds-set-correct-msg_namelen.patch + # END OF PATCH APPLICATIONS %endif @@ -2030,6 +2036,8 @@ fi %changelog * Thu Jul 26 2012 Josh Boyer +- kernel: recv{from,msg}() on an rds socket can leak kernel + memory (rhbz 820039 843554) - Apply patch to fix uvcvideo crash (rhbz 836742) * Wed Jul 25 2012 Josh Boyer diff --git a/rds-set-correct-msg_namelen.patch b/rds-set-correct-msg_namelen.patch new file mode 100644 index 000000000..340d0cd68 --- /dev/null +++ b/rds-set-correct-msg_namelen.patch @@ -0,0 +1,219 @@ +From 06b6a1cf6e776426766298d055bb3991957d90a7 Mon Sep 17 00:00:00 2001 +From: Weiping Pan +Date: Mon, 23 Jul 2012 10:37:48 +0800 +Subject: [PATCH] rds: set correct msg_namelen + +Jay Fenlason (fenlason@redhat.com) found a bug, +that recvfrom() on an RDS socket can return the contents of random kernel +memory to userspace if it was called with a address length larger than +sizeof(struct sockaddr_in). +rds_recvmsg() also fails to set the addr_len paramater properly before +returning, but that's just a bug. +There are also a number of cases wher recvfrom() can return an entirely bogus +address. Anything in rds_recvmsg() that returns a non-negative value but does +not go through the "sin = (struct sockaddr_in *)msg->msg_name;" code path +at the end of the while(1) loop will return up to 128 bytes of kernel memory +to userspace. + +And I write two test programs to reproduce this bug, you will see that in +rds_server, fromAddr will be overwritten and the following sock_fd will be +destroyed. +Yes, it is the programmer's fault to set msg_namelen incorrectly, but it is +better to make the kernel copy the real length of address to user space in +such case. + +How to run the test programs ? +I test them on 32bit x86 system, 3.5.0-rc7. + +1 compile +gcc -o rds_client rds_client.c +gcc -o rds_server rds_server.c + +2 run ./rds_server on one console + +3 run ./rds_client on another console + +4 you will see something like: +server is waiting to receive data... +old socket fd=3 +server received data from client:data from client +msg.msg_namelen=32 +new socket fd=-1067277685 +sendmsg() +: Bad file descriptor + +/***************** rds_client.c ********************/ + +int main(void) +{ + int sock_fd; + struct sockaddr_in serverAddr; + struct sockaddr_in toAddr; + char recvBuffer[128] = "data from client"; + struct msghdr msg; + struct iovec iov; + + sock_fd = socket(AF_RDS, SOCK_SEQPACKET, 0); + if (sock_fd < 0) { + perror("create socket error\n"); + exit(1); + } + + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); + serverAddr.sin_port = htons(4001); + + if (bind(sock_fd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { + perror("bind() error\n"); + close(sock_fd); + exit(1); + } + + memset(&toAddr, 0, sizeof(toAddr)); + toAddr.sin_family = AF_INET; + toAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); + toAddr.sin_port = htons(4000); + msg.msg_name = &toAddr; + msg.msg_namelen = sizeof(toAddr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_iov->iov_base = recvBuffer; + msg.msg_iov->iov_len = strlen(recvBuffer) + 1; + msg.msg_control = 0; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + if (sendmsg(sock_fd, &msg, 0) == -1) { + perror("sendto() error\n"); + close(sock_fd); + exit(1); + } + + printf("client send data:%s\n", recvBuffer); + + memset(recvBuffer, '\0', 128); + + msg.msg_name = &toAddr; + msg.msg_namelen = sizeof(toAddr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_iov->iov_base = recvBuffer; + msg.msg_iov->iov_len = 128; + msg.msg_control = 0; + msg.msg_controllen = 0; + msg.msg_flags = 0; + if (recvmsg(sock_fd, &msg, 0) == -1) { + perror("recvmsg() error\n"); + close(sock_fd); + exit(1); + } + + printf("receive data from server:%s\n", recvBuffer); + + close(sock_fd); + + return 0; +} + +/***************** rds_server.c ********************/ + +int main(void) +{ + struct sockaddr_in fromAddr; + int sock_fd; + struct sockaddr_in serverAddr; + unsigned int addrLen; + char recvBuffer[128]; + struct msghdr msg; + struct iovec iov; + + sock_fd = socket(AF_RDS, SOCK_SEQPACKET, 0); + if(sock_fd < 0) { + perror("create socket error\n"); + exit(0); + } + + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); + serverAddr.sin_port = htons(4000); + if (bind(sock_fd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { + perror("bind error\n"); + close(sock_fd); + exit(1); + } + + printf("server is waiting to receive data...\n"); + msg.msg_name = &fromAddr; + + /* + * I add 16 to sizeof(fromAddr), ie 32, + * and pay attention to the definition of fromAddr, + * recvmsg() will overwrite sock_fd, + * since kernel will copy 32 bytes to userspace. + * + * If you just use sizeof(fromAddr), it works fine. + * */ + msg.msg_namelen = sizeof(fromAddr) + 16; + /* msg.msg_namelen = sizeof(fromAddr); */ + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_iov->iov_base = recvBuffer; + msg.msg_iov->iov_len = 128; + msg.msg_control = 0; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + while (1) { + printf("old socket fd=%d\n", sock_fd); + if (recvmsg(sock_fd, &msg, 0) == -1) { + perror("recvmsg() error\n"); + close(sock_fd); + exit(1); + } + printf("server received data from client:%s\n", recvBuffer); + printf("msg.msg_namelen=%d\n", msg.msg_namelen); + printf("new socket fd=%d\n", sock_fd); + strcat(recvBuffer, "--data from server"); + if (sendmsg(sock_fd, &msg, 0) == -1) { + perror("sendmsg()\n"); + close(sock_fd); + exit(1); + } + } + + close(sock_fd); + return 0; +} + +Signed-off-by: Weiping Pan +Signed-off-by: David S. Miller +--- + net/rds/recv.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/rds/recv.c b/net/rds/recv.c +index 5c6e9f1..9f0f17c 100644 +--- a/net/rds/recv.c ++++ b/net/rds/recv.c +@@ -410,6 +410,8 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, + + rdsdebug("size %zu flags 0x%x timeo %ld\n", size, msg_flags, timeo); + ++ msg->msg_namelen = 0; ++ + if (msg_flags & MSG_OOB) + goto out; + +@@ -485,6 +487,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, + sin->sin_port = inc->i_hdr.h_sport; + sin->sin_addr.s_addr = inc->i_saddr; + memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); ++ msg->msg_namelen = sizeof(*sin); + } + break; + } +-- +1.7.11.2 + From 5613df668e2de9433369f6c79cdb62d621c1e7d2 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 30 Jul 2012 11:46:40 -0400 Subject: [PATCH 420/487] Linux 3.4.7 --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 7e3b1d3dc..da5f214a5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 6 +%define stable_update 7 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2035,6 +2035,9 @@ fi # and build. %changelog +* Mon Jul 30 2012 Dave Jones 3.4.7-1 +- Linux 3.4.7 + * Thu Jul 26 2012 Josh Boyer - kernel: recv{from,msg}() on an rds socket can leak kernel memory (rhbz 820039 843554) diff --git a/sources b/sources index 6f10d0c05..d9defce07 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 967f72983655e2479f951195953e8480 linux-3.4.tar.xz -14443e53d3ab88e6eac45d954d891e00 patch-3.4.6.xz +5258bea05aa6d0a52fcaea28b1b74c29 patch-3.4.7.xz From d1e55656898e3a21bde3e8980fe6fefe7f2b589f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 3 Aug 2012 09:30:37 -0400 Subject: [PATCH 421/487] CVE-2012-3412 sfc: potential rDOS through TCP MSS option (rhbz 844714 845558) --- kernel.spec | 15 +- ...limit-number-of-GSO-segments-per-skb.patch | 70 ++++++++ ...O-segments-and-minimum-TX-queue-size.patch | 156 ++++++++++++++++++ ...ply-device-TSO-segment-limit-earlier.patch | 124 ++++++++++++++ 4 files changed, 364 insertions(+), 1 deletion(-) create mode 100644 net-Allow-driver-to-limit-number-of-GSO-segments-per-skb.patch create mode 100644 sfc-Fix-maximum-number-of-TSO-segments-and-minimum-TX-queue-size.patch create mode 100644 tcp-Apply-device-TSO-segment-limit-earlier.patch diff --git a/kernel.spec b/kernel.spec index da5f214a5..b00245231 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -716,6 +716,11 @@ Patch22060: CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch #rhbz 820039 843554 Patch22061: rds-set-correct-msg_namelen.patch +#rhbz 845558 844714 +Patch22070: net-Allow-driver-to-limit-number-of-GSO-segments-per-skb.patch +Patch22071: sfc-Fix-maximum-number-of-TSO-segments-and-minimum-TX-queue-size.patch +Patch22072: tcp-Apply-device-TSO-segment-limit-earlier.patch + # END OF PATCH DEFINITIONS %endif @@ -1337,6 +1342,11 @@ ApplyPatch CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch #rhbz 820039 843554 ApplyPatch rds-set-correct-msg_namelen.patch +#rhbz 845558 844714 +ApplyPatch net-Allow-driver-to-limit-number-of-GSO-segments-per-skb.patch +ApplyPatch sfc-Fix-maximum-number-of-TSO-segments-and-minimum-TX-queue-size.patch +ApplyPatch tcp-Apply-device-TSO-segment-limit-earlier.patch + # END OF PATCH APPLICATIONS %endif @@ -2035,6 +2045,9 @@ fi # and build. %changelog +* Fri Aug 03 2012 Josh Boyer +- CVE-2012-3412 sfc: potential rDOS through TCP MSS option (rhbz 844714 845558) + * Mon Jul 30 2012 Dave Jones 3.4.7-1 - Linux 3.4.7 diff --git a/net-Allow-driver-to-limit-number-of-GSO-segments-per-skb.patch b/net-Allow-driver-to-limit-number-of-GSO-segments-per-skb.patch new file mode 100644 index 000000000..bebccf3d0 --- /dev/null +++ b/net-Allow-driver-to-limit-number-of-GSO-segments-per-skb.patch @@ -0,0 +1,70 @@ +From 30b678d844af3305cda5953467005cebb5d7b687 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Mon, 30 Jul 2012 15:57:00 +0000 +Subject: [PATCH] net: Allow driver to limit number of GSO segments per skb + +A peer (or local user) may cause TCP to use a nominal MSS of as little +as 88 (actual MSS of 76 with timestamps). Given that we have a +sufficiently prodigious local sender and the peer ACKs quickly enough, +it is nevertheless possible to grow the window for such a connection +to the point that we will try to send just under 64K at once. This +results in a single skb that expands to 861 segments. + +In some drivers with TSO support, such an skb will require hundreds of +DMA descriptors; a substantial fraction of a TX ring or even more than +a full ring. The TX queue selected for the skb may stall and trigger +the TX watchdog repeatedly (since the problem skb will be retried +after the TX reset). This particularly affects sfc, for which the +issue is designated as CVE-2012-3412. + +Therefore: +1. Add the field net_device::gso_max_segs holding the device-specific + limit. +2. In netif_skb_features(), if the number of segments is too high then + mask out GSO features to force fall back to software GSO. + +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +--- + include/linux/netdevice.h | 2 ++ + net/core/dev.c | 4 ++++ + 2 files changed, 6 insertions(+), 0 deletions(-) + +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index eb06e58..a9db4f3 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -1300,6 +1300,8 @@ struct net_device { + /* for setting kernel sock attribute on TCP connection setup */ + #define GSO_MAX_SIZE 65536 + unsigned int gso_max_size; ++#define GSO_MAX_SEGS 65535 ++ u16 gso_max_segs; + + #ifdef CONFIG_DCB + /* Data Center Bridging netlink ops */ +diff --git a/net/core/dev.c b/net/core/dev.c +index 0cb3fe8..f91abf8 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -2134,6 +2134,9 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) + __be16 protocol = skb->protocol; + netdev_features_t features = skb->dev->features; + ++ if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs) ++ features &= ~NETIF_F_GSO_MASK; ++ + if (protocol == htons(ETH_P_8021Q)) { + struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; + protocol = veh->h_vlan_encapsulated_proto; +@@ -5986,6 +5989,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, + dev_net_set(dev, &init_net); + + dev->gso_max_size = GSO_MAX_SIZE; ++ dev->gso_max_segs = GSO_MAX_SEGS; + + INIT_LIST_HEAD(&dev->napi_list); + INIT_LIST_HEAD(&dev->unreg_list); +-- +1.7.7.6 + diff --git a/sfc-Fix-maximum-number-of-TSO-segments-and-minimum-TX-queue-size.patch b/sfc-Fix-maximum-number-of-TSO-segments-and-minimum-TX-queue-size.patch new file mode 100644 index 000000000..07ec616e0 --- /dev/null +++ b/sfc-Fix-maximum-number-of-TSO-segments-and-minimum-TX-queue-size.patch @@ -0,0 +1,156 @@ +From 7e6d06f0de3f74ca929441add094518ae332257c Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Mon, 30 Jul 2012 15:57:44 +0000 +Subject: [PATCH] sfc: Fix maximum number of TSO segments and minimum TX queue + size + +Currently an skb requiring TSO may not fit within a minimum-size TX +queue. The TX queue selected for the skb may stall and trigger the TX +watchdog repeatedly (since the problem skb will be retried after the +TX reset). This issue is designated as CVE-2012-3412. + +Set the maximum number of TSO segments for our devices to 100. This +should make no difference to behaviour unless the actual MSS is less +than about 700. Increase the minimum TX queue size accordingly to +allow for 2 worst-case skbs, so that there will definitely be space +to add an skb after we wake a queue. + +To avoid invalidating existing configurations, change +efx_ethtool_set_ringparam() to fix up values that are too small rather +than returning -EINVAL. + +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/sfc/efx.c | 6 ++++++ + drivers/net/ethernet/sfc/efx.h | 14 ++++++++++---- + drivers/net/ethernet/sfc/ethtool.c | 16 +++++++++++----- + drivers/net/ethernet/sfc/tx.c | 19 +++++++++++++++++++ + 4 files changed, 46 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c +index 70554a1..65a8d49 100644 +--- a/drivers/net/ethernet/sfc/efx.c ++++ b/drivers/net/ethernet/sfc/efx.c +@@ -1503,6 +1503,11 @@ static int efx_probe_all(struct efx_nic *efx) + goto fail2; + } + ++ BUILD_BUG_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_RXQ_MIN_ENT); ++ if (WARN_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_TXQ_MIN_ENT(efx))) { ++ rc = -EINVAL; ++ goto fail3; ++ } + efx->rxq_entries = efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE; + + rc = efx_probe_filters(efx); +@@ -2070,6 +2075,7 @@ static int efx_register_netdev(struct efx_nic *efx) + net_dev->irq = efx->pci_dev->irq; + net_dev->netdev_ops = &efx_netdev_ops; + SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops); ++ net_dev->gso_max_segs = EFX_TSO_MAX_SEGS; + + rtnl_lock(); + +diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h +index be8f915..70755c9 100644 +--- a/drivers/net/ethernet/sfc/efx.h ++++ b/drivers/net/ethernet/sfc/efx.h +@@ -30,6 +30,7 @@ extern netdev_tx_t + efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb); + extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index); + extern int efx_setup_tc(struct net_device *net_dev, u8 num_tc); ++extern unsigned int efx_tx_max_skb_descs(struct efx_nic *efx); + + /* RX */ + extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue); +@@ -52,10 +53,15 @@ extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue); + #define EFX_MAX_EVQ_SIZE 16384UL + #define EFX_MIN_EVQ_SIZE 512UL + +-/* The smallest [rt]xq_entries that the driver supports. Callers of +- * efx_wake_queue() assume that they can subsequently send at least one +- * skb. Falcon/A1 may require up to three descriptors per skb_frag. */ +-#define EFX_MIN_RING_SIZE (roundup_pow_of_two(2 * 3 * MAX_SKB_FRAGS)) ++/* Maximum number of TCP segments we support for soft-TSO */ ++#define EFX_TSO_MAX_SEGS 100 ++ ++/* The smallest [rt]xq_entries that the driver supports. RX minimum ++ * is a bit arbitrary. For TX, we must have space for at least 2 ++ * TSO skbs. ++ */ ++#define EFX_RXQ_MIN_ENT 128U ++#define EFX_TXQ_MIN_ENT(efx) (2 * efx_tx_max_skb_descs(efx)) + + /* Filters */ + extern int efx_probe_filters(struct efx_nic *efx); +diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c +index 10536f9..8cba2df 100644 +--- a/drivers/net/ethernet/sfc/ethtool.c ++++ b/drivers/net/ethernet/sfc/ethtool.c +@@ -680,21 +680,27 @@ static int efx_ethtool_set_ringparam(struct net_device *net_dev, + struct ethtool_ringparam *ring) + { + struct efx_nic *efx = netdev_priv(net_dev); ++ u32 txq_entries; + + if (ring->rx_mini_pending || ring->rx_jumbo_pending || + ring->rx_pending > EFX_MAX_DMAQ_SIZE || + ring->tx_pending > EFX_MAX_DMAQ_SIZE) + return -EINVAL; + +- if (ring->rx_pending < EFX_MIN_RING_SIZE || +- ring->tx_pending < EFX_MIN_RING_SIZE) { ++ if (ring->rx_pending < EFX_RXQ_MIN_ENT) { + netif_err(efx, drv, efx->net_dev, +- "TX and RX queues cannot be smaller than %ld\n", +- EFX_MIN_RING_SIZE); ++ "RX queues cannot be smaller than %u\n", ++ EFX_RXQ_MIN_ENT); + return -EINVAL; + } + +- return efx_realloc_channels(efx, ring->rx_pending, ring->tx_pending); ++ txq_entries = max(ring->tx_pending, EFX_TXQ_MIN_ENT(efx)); ++ if (txq_entries != ring->tx_pending) ++ netif_warn(efx, drv, efx->net_dev, ++ "increasing TX queue size to minimum of %u\n", ++ txq_entries); ++ ++ return efx_realloc_channels(efx, ring->rx_pending, txq_entries); + } + + static int efx_ethtool_set_pauseparam(struct net_device *net_dev, +diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c +index 9b225a7..1871343 100644 +--- a/drivers/net/ethernet/sfc/tx.c ++++ b/drivers/net/ethernet/sfc/tx.c +@@ -119,6 +119,25 @@ efx_max_tx_len(struct efx_nic *efx, dma_addr_t dma_addr) + return len; + } + ++unsigned int efx_tx_max_skb_descs(struct efx_nic *efx) ++{ ++ /* Header and payload descriptor for each output segment, plus ++ * one for every input fragment boundary within a segment ++ */ ++ unsigned int max_descs = EFX_TSO_MAX_SEGS * 2 + MAX_SKB_FRAGS; ++ ++ /* Possibly one more per segment for the alignment workaround */ ++ if (EFX_WORKAROUND_5391(efx)) ++ max_descs += EFX_TSO_MAX_SEGS; ++ ++ /* Possibly more for PCIe page boundaries within input fragments */ ++ if (PAGE_SIZE > EFX_PAGE_SIZE) ++ max_descs += max_t(unsigned int, MAX_SKB_FRAGS, ++ DIV_ROUND_UP(GSO_MAX_SIZE, EFX_PAGE_SIZE)); ++ ++ return max_descs; ++} ++ + /* + * Add a socket buffer to a TX queue + * +-- +1.7.7.6 + diff --git a/tcp-Apply-device-TSO-segment-limit-earlier.patch b/tcp-Apply-device-TSO-segment-limit-earlier.patch new file mode 100644 index 000000000..d6fa7f49e --- /dev/null +++ b/tcp-Apply-device-TSO-segment-limit-earlier.patch @@ -0,0 +1,124 @@ +From 1485348d2424e1131ea42efc033cbd9366462b01 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Mon, 30 Jul 2012 16:11:42 +0000 +Subject: [PATCH] tcp: Apply device TSO segment limit earlier + +Cache the device gso_max_segs in sock::sk_gso_max_segs and use it to +limit the size of TSO skbs. This avoids the need to fall back to +software GSO for local TCP senders. + +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +--- + include/net/sock.h | 2 ++ + net/core/sock.c | 1 + + net/ipv4/tcp.c | 4 +++- + net/ipv4/tcp_cong.c | 3 ++- + net/ipv4/tcp_output.c | 21 ++++++++++++--------- + 5 files changed, 20 insertions(+), 11 deletions(-) + +--- linux-3.4.noarch.orig/include/net/sock.h ++++ linux-3.4.noarch/include/net/sock.h +@@ -216,6 +216,7 @@ struct cg_proto; + * @sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK) + * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4) + * @sk_gso_max_size: Maximum GSO segment size to build ++ * @sk_gso_max_segs: Maximum number of GSO segments + * @sk_lingertime: %SO_LINGER l_linger setting + * @sk_backlog: always used with the per-socket spinlock held + * @sk_callback_lock: used with the callbacks in the end of this struct +@@ -335,6 +336,7 @@ struct sock { + netdev_features_t sk_route_nocaps; + int sk_gso_type; + unsigned int sk_gso_max_size; ++ u16 sk_gso_max_segs; + int sk_rcvlowat; + unsigned long sk_lingertime; + struct sk_buff_head sk_error_queue; +--- linux-3.4.noarch.orig/net/core/sock.c ++++ linux-3.4.noarch/net/core/sock.c +@@ -1411,6 +1411,7 @@ void sk_setup_caps(struct sock *sk, stru + } else { + sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; + sk->sk_gso_max_size = dst->dev->gso_max_size; ++ sk->sk_gso_max_segs = dst->dev->gso_max_segs; + } + } + } +--- linux-3.4.noarch.orig/net/ipv4/tcp.c ++++ linux-3.4.noarch/net/ipv4/tcp.c +@@ -740,7 +740,9 @@ static unsigned int tcp_xmit_size_goal(s + old_size_goal + mss_now > xmit_size_goal)) { + xmit_size_goal = old_size_goal; + } else { +- tp->xmit_size_goal_segs = xmit_size_goal / mss_now; ++ tp->xmit_size_goal_segs = ++ min_t(u16, xmit_size_goal / mss_now, ++ sk->sk_gso_max_segs); + xmit_size_goal = tp->xmit_size_goal_segs * mss_now; + } + } +--- linux-3.4.noarch.orig/net/ipv4/tcp_cong.c ++++ linux-3.4.noarch/net/ipv4/tcp_cong.c +@@ -291,7 +291,8 @@ int tcp_is_cwnd_limited(const struct soc + left = tp->snd_cwnd - in_flight; + if (sk_can_gso(sk) && + left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd && +- left * tp->mss_cache < sk->sk_gso_max_size) ++ left * tp->mss_cache < sk->sk_gso_max_size && ++ left < sk->sk_gso_max_segs) + return 1; + return left <= tcp_max_tso_deferred_mss(tp); + } +--- linux-3.4.noarch.orig/net/ipv4/tcp_output.c ++++ linux-3.4.noarch/net/ipv4/tcp_output.c +@@ -1318,21 +1318,21 @@ static void tcp_cwnd_validate(struct soc + * when we would be allowed to send the split-due-to-Nagle skb fully. + */ + static unsigned int tcp_mss_split_point(const struct sock *sk, const struct sk_buff *skb, +- unsigned int mss_now, unsigned int cwnd) ++ unsigned int mss_now, unsigned int max_segs) + { + const struct tcp_sock *tp = tcp_sk(sk); +- u32 needed, window, cwnd_len; ++ u32 needed, window, max_len; + + window = tcp_wnd_end(tp) - TCP_SKB_CB(skb)->seq; +- cwnd_len = mss_now * cwnd; ++ max_len = mss_now * max_segs; + +- if (likely(cwnd_len <= window && skb != tcp_write_queue_tail(sk))) +- return cwnd_len; ++ if (likely(max_len <= window && skb != tcp_write_queue_tail(sk))) ++ return max_len; + + needed = min(skb->len, window); + +- if (cwnd_len <= needed) +- return cwnd_len; ++ if (max_len <= needed) ++ return max_len; + + return needed - needed % mss_now; + } +@@ -1560,7 +1560,8 @@ static int tcp_tso_should_defer(struct s + limit = min(send_win, cong_win); + + /* If a full-sized TSO skb can be sent, do it. */ +- if (limit >= sk->sk_gso_max_size) ++ if (limit >= min_t(unsigned int, sk->sk_gso_max_size, ++ sk->sk_gso_max_segs * tp->mss_cache)) + goto send_now; + + /* Middle in queue won't get any more data, full sendable already? */ +@@ -1786,7 +1787,9 @@ static int tcp_write_xmit(struct sock *s + limit = mss_now; + if (tso_segs > 1 && !tcp_urg_mode(tp)) + limit = tcp_mss_split_point(sk, skb, mss_now, +- cwnd_quota); ++ min_t(unsigned int, ++ cwnd_quota, ++ sk->sk_gso_max_segs)); + + if (skb->len > limit && + unlikely(tso_fragment(sk, skb, limit, mss_now, gfp))) From cc9d306d065a1ff90b37a398353dcc012f76b66c Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 14 Aug 2012 16:22:51 -0500 Subject: [PATCH 422/487] Linux 3.4.8 --- ...eturn-value-of-power_supply_register.patch | 37 ------------------- atl1c_net_next_update-3.4.patch | 3 +- kernel.spec | 13 +++---- sources | 2 +- 4 files changed, 7 insertions(+), 48 deletions(-) delete mode 100644 ACPI-AC-check-the-return-value-of-power_supply_register.patch diff --git a/ACPI-AC-check-the-return-value-of-power_supply_register.patch b/ACPI-AC-check-the-return-value-of-power_supply_register.patch deleted file mode 100644 index c9eb1a17d..000000000 --- a/ACPI-AC-check-the-return-value-of-power_supply_register.patch +++ /dev/null @@ -1,37 +0,0 @@ -In the ac.c, lack check return value of power_supply_register(). -This may casue that acpi driver's add() ops was called successful -while the device may be failed to be initalized. For example, some -ugly bios may describe two ACADs in the same dsdt. They use the same -name which will cause the second ACAD device can no be registered. -And then power_supply_register() failed. But acpi driver's add() ops -is called sucessfully. The acpi device also will receive acpi notification -and cause oops. - https://bugzilla.redhat.com/show_bug.cgi?id=772730 - -Signed-off-by: Lan Tianyu ---- - drivers/acpi/ac.c | 4 +++- - 1 files changed, 3 insertions(+), 1 deletions(-) - -diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c -index 6512b20..d1fcbc0 100644 ---- a/drivers/acpi/ac.c -+++ b/drivers/acpi/ac.c -@@ -292,7 +292,9 @@ static int acpi_ac_add(struct acpi_device *device) - ac->charger.properties = ac_props; - ac->charger.num_properties = ARRAY_SIZE(ac_props); - ac->charger.get_property = get_ac_property; -- power_supply_register(&ac->device->dev, &ac->charger); -+ result = power_supply_register(&ac->device->dev, &ac->charger); -+ if (result) -+ goto end; - - printk(KERN_INFO PREFIX "%s [%s] (%s)\n", - acpi_device_name(device), acpi_device_bid(device), --- -1.7.6.rc2.8.g28eb - --- -To unsubscribe from this list: send the line "unsubscribe linux-acpi" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/atl1c_net_next_update-3.4.patch b/atl1c_net_next_update-3.4.patch index 1ec9771bc..94422b124 100644 --- a/atl1c_net_next_update-3.4.patch +++ b/atl1c_net_next_update-3.4.patch @@ -2221,7 +2221,7 @@ index 1ef0c92..9cc1570 100644 return 0; msleep(1); } -@@ -261,15 +260,16 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) +@@ -261,14 +260,15 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) if ((phy_data & BMSR_LSTATUS) == 0) { /* link down */ @@ -2231,7 +2231,6 @@ index 1ef0c92..9cc1570 100644 - dev_warn(&pdev->dev, "stop mac failed\n"); - atl1c_set_aspm(hw, false); netif_carrier_off(netdev); - netif_stop_queue(netdev); - atl1c_phy_reset(hw); - atl1c_phy_init(&adapter->hw); + hw->hibernate = true; diff --git a/kernel.spec b/kernel.spec index b00245231..e6abd051f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 7 +%define stable_update 8 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -704,9 +704,6 @@ Patch22018: atl1c_net_next_update-3.4.patch Patch22055: crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch Patch22056: crypto-aesni-intel-fix-wrong-kfree-pointer.patch -#rhbz 772730 -Patch22058: ACPI-AC-check-the-return-value-of-power_supply_register.patch - #rhbz 836742 Patch22059: uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch @@ -1330,9 +1327,6 @@ ApplyPatch atl1c_net_next_update-3.4.patch ApplyPatch crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch ApplyPatch crypto-aesni-intel-fix-wrong-kfree-pointer.patch -#rhbz 772730 -ApplyPatch ACPI-AC-check-the-return-value-of-power_supply_register.patch - #rhbz 836742 ApplyPatch uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch @@ -2045,6 +2039,9 @@ fi # and build. %changelog +* Tue Aug 14 2012 Justin M. Forbes 3.4.8-1 +- Linux 3.4.8 + * Fri Aug 03 2012 Josh Boyer - CVE-2012-3412 sfc: potential rDOS through TCP MSS option (rhbz 844714 845558) diff --git a/sources b/sources index d9defce07..d8fa226e0 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 967f72983655e2479f951195953e8480 linux-3.4.tar.xz -5258bea05aa6d0a52fcaea28b1b74c29 patch-3.4.7.xz +ac5a5a5d6679b1aca8780f4e539f0228 patch-3.4.8.xz From 66065a295f021cde230c856a3a69885dbba5f8c1 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 15 Aug 2012 15:05:38 -0500 Subject: [PATCH 423/487] Linux 3.4.9 --- sources | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources b/sources index d8fa226e0..1e2b5e42d 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 967f72983655e2479f951195953e8480 linux-3.4.tar.xz -ac5a5a5d6679b1aca8780f4e539f0228 patch-3.4.8.xz +ffd1d2010b97fe45a62c9ce856ca224f patch-3.4.9.xz From ecc0fbceb4738208e03710f0c830f34e9aeaecfa Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 15 Aug 2012 15:06:21 -0500 Subject: [PATCH 424/487] Linux 3.4.9 --- kernel.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index e6abd051f..d891486f7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 8 +%define stable_update 9 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2039,6 +2039,9 @@ fi # and build. %changelog +* Wed Aug 15 2012 Justin M. Forbes 3.4.9-1 +- Linux 3.4.9 + * Tue Aug 14 2012 Justin M. Forbes 3.4.8-1 - Linux 3.4.8 From e0bf103272d5ce120abb56f97a237c11a1412547 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 23 Aug 2012 12:15:02 -0500 Subject: [PATCH 425/487] af_netlink: force credentials passing [CVE-2012-3520] --- af_netlink-credentials-cve-2012-3520.patch | 114 + kernel.spec | 16 +- linux-3.4.10-queue.patch | 2464 ++++++++++++++++++++ 3 files changed, 2593 insertions(+), 1 deletion(-) create mode 100644 af_netlink-credentials-cve-2012-3520.patch create mode 100644 linux-3.4.10-queue.patch diff --git a/af_netlink-credentials-cve-2012-3520.patch b/af_netlink-credentials-cve-2012-3520.patch new file mode 100644 index 000000000..c324a4a90 --- /dev/null +++ b/af_netlink-credentials-cve-2012-3520.patch @@ -0,0 +1,114 @@ +Subject: [PATCH] af_netlink: force credentials passing [CVE-2012-3520] +From: Eric Dumazet +To: David Miller +Cc: netdev , Petr Matousek , + Florian Weimer , + Pablo Neira Ayuso +Content-Type: text/plain; charset="UTF-8" +Date: Tue, 21 Aug 2012 18:21:17 +0200 +Message-ID: <1345566077.5158.530.camel@edumazet-glaptop> +Mime-Version: 1.0 +Content-Transfer-Encoding: 7bit +Sender: netdev-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org +X-RedHat-Spam-Score: -6.999 (BAYES_00,DKIM_ADSP_CUSTOM_MED,DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID) +X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 +X-Scanned-By: MIMEDefang 2.68 on 10.5.110.16 +Status: RO +Content-Length: 3042 +Lines: 91 + +From: Eric Dumazet + +Pablo Neira Ayuso discovered that avahi and +potentially NetworkManager accept spoofed Netlink messages because of a +kernel bug. The kernel passes all-zero SCM_CREDENTIALS ancillary data +to the receiver if the sender did not provide such data, instead of not +including any such data at all or including the correct data from the +peer (as it is the case with AF_UNIX). + +This bug was introduced in commit 16e572626961 +(af_unix: dont send SCM_CREDENTIALS by default) + +This patch forces passing credentials for netlink, as +before the regression. + +Another fix would be to not add SCM_CREDENTIALS in +netlink messages if not provided by the sender, but it +might break some programs. + +With help from Florian Weimer & Petr Matousek + +This issue is designated as CVE-2012-3520 + +Signed-off-by: Eric Dumazet +Cc: Petr Matousek +Cc: Florian Weimer +Cc: Pablo Neira Ayuso +--- + include/net/scm.h | 4 +++- + net/netlink/af_netlink.c | 2 +- + net/unix/af_unix.c | 4 ++-- + 3 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/include/net/scm.h b/include/net/scm.h +index 079d788..7dc0854 100644 +--- a/include/net/scm.h ++++ b/include/net/scm.h +@@ -70,9 +70,11 @@ static __inline__ void scm_destroy(struct scm_cookie *scm) + } + + static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, +- struct scm_cookie *scm) ++ struct scm_cookie *scm, bool forcecreds) + { + memset(scm, 0, sizeof(*scm)); ++ if (forcecreds) ++ scm_set_cred(scm, task_tgid(current), current_cred()); + unix_get_peersec_dgram(sock, scm); + if (msg->msg_controllen <= 0) + return 0; +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index 5463969..1445d73 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -1362,7 +1362,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, + if (NULL == siocb->scm) + siocb->scm = &scm; + +- err = scm_send(sock, msg, siocb->scm); ++ err = scm_send(sock, msg, siocb->scm, true); + if (err < 0) + return err; + +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index e4768c1..c5ee4ff 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1450,7 +1450,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, + if (NULL == siocb->scm) + siocb->scm = &tmp_scm; + wait_for_unix_gc(); +- err = scm_send(sock, msg, siocb->scm); ++ err = scm_send(sock, msg, siocb->scm, false); + if (err < 0) + return err; + +@@ -1619,7 +1619,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, + if (NULL == siocb->scm) + siocb->scm = &tmp_scm; + wait_for_unix_gc(); +- err = scm_send(sock, msg, siocb->scm); ++ err = scm_send(sock, msg, siocb->scm, false); + if (err < 0) + return err; + + + +-- +To unsubscribe from this list: send the line "unsubscribe netdev" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + diff --git a/kernel.spec b/kernel.spec index d891486f7..f84d837fe 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -718,6 +718,11 @@ Patch22070: net-Allow-driver-to-limit-number-of-GSO-segments-per-skb.patch Patch22071: sfc-Fix-maximum-number-of-TSO-segments-and-minimum-TX-queue-size.patch Patch22072: tcp-Apply-device-TSO-segment-limit-earlier.patch +Patch22075: af_netlink-credentials-cve-2012-3520.patch + +#Patches from the 3.4.10 stable queue +Patch22100: linux-3.4.10-queue.patch + # END OF PATCH DEFINITIONS %endif @@ -1341,6 +1346,11 @@ ApplyPatch net-Allow-driver-to-limit-number-of-GSO-segments-per-skb.patch ApplyPatch sfc-Fix-maximum-number-of-TSO-segments-and-minimum-TX-queue-size.patch ApplyPatch tcp-Apply-device-TSO-segment-limit-earlier.patch +ApplyPatch af_netlink-credentials-cve-2012-3520.patch + +#Patches from the 3.4.10 stable queue +ApplyPatch linux-3.4.10-queue.patch + # END OF PATCH APPLICATIONS %endif @@ -2039,6 +2049,10 @@ fi # and build. %changelog +* Thu Aug 23 2012 Justin M. Forbes 3.4.9-2 +- af_netlink: force credentials passing [CVE-2012-3520] +- Add patches from 3.4.10 queue + * Wed Aug 15 2012 Justin M. Forbes 3.4.9-1 - Linux 3.4.9 diff --git a/linux-3.4.10-queue.patch b/linux-3.4.10-queue.patch new file mode 100644 index 000000000..72cfb19f5 --- /dev/null +++ b/linux-3.4.10-queue.patch @@ -0,0 +1,2464 @@ +From a2367db2ec5e7fc6fe93e221e0fcdee81b053daf Mon Sep 17 00:00:00 2001 +From: Fabio Estevam +Date: Tue, 3 Jul 2012 15:33:29 -0300 +Subject: dma: imx-dma: Fix kernel crash due to missing clock conversion + +From: Fabio Estevam + +commit a2367db2ec5e7fc6fe93e221e0fcdee81b053daf upstream. + +With the new i.MX clock infrastructure we need to request the dma clocks +seperately: ahb and ipg clocks. + +This fixes the following kernel crash and make audio to be functional again: + +root@freescale /home$ aplay audio48k16S.wav +Playing WAVE 'audio48k16S.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo +Unable to handle kernel NULL pointer dereference at virtual address 00000000 +pgd = c7b74000 +[00000000] *pgd=a7bb5831, *pte=00000000, *ppte=00000000 +Internal error: Oops: 17 [#1] PREEMPT ARM +Modules linked in: +CPU: 0 Not tainted (3.5.0-rc5-next-20120702-00007-g3028b64 #1128) +PC is at snd_dmaengine_pcm_get_chan+0x8/0x10 +LR is at snd_imx_pcm_hw_params+0x18/0xdc +pc : [] lr : [] psr: a0000013 +sp : c7b45e30 ip : ffffffff fp : c7ae58e0 +r10: 00000000 r9 : c7ae981c r8 : c7b88800 +r7 : c7ae5a60 r6 : c7ae5b20 r5 : c7ae9810 r4 : c7afa060 +r3 : 00000000 r2 : 00000001 r1 : c7b88800 r0 : c7afa060 +Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user +Control: 0005317f Table: a7b74000 DAC: 00000015 +Process aplay (pid: 701, stack limit = 0xc7b44270) +Stack: (0xc7b45e30 to 0xc7b46000) +5e20: 00100000 00000029 c7b88800 c02db870 +5e40: c7ae5a60 c02d4594 00000010 01ae5a60 c7ae5a60 c7ae9810 c7ae9810 c7afa060 +5e60: c7ae5b20 c7ae5a60 c7b88800 c02e3ef0 c02e3e08 c7b1e400 c7afa060 c7b88800 +5e80: 00000000 c0014da8 c7b44000 00000000 bec566ac c02cd400 c7afa060 c7afa060 +5ea0: bec56800 c7b88800 c0014da8 c02cdd7c c04ee710 c04ee7b8 00000003 c005fc74 +5ec0: 00000000 7fffffff c7b45f00 c7afa060 c7b67420 c7ba3070 00000004 c0014da8 +5ee0: c7b44000 00000000 bec566ac c02ced88 c04e95f8 b6f5ab04 c7b45fb0 0145a468 +5f00: 0145a600 bec566bc bec56800 c7b67420 c7ba3070 c00d499c c7b45f18 c7b45f18 +5f20: 0000001a 00000004 00000001 c7b44000 c0527f40 00000009 00000008 00000000 +5f40: c7b44000 c002c9ec 00000001 c04f0ab0 c04ebec0 00000101 00000000 0000000a +5f60: 60000093 c7b67420 bec56800 c25c4111 00000004 c0014da8 c7b44000 00000000 +5f80: bec566ac c00d4f38 b6ffb658 00000000 c0522d80 0145a468 b6fd5000 0145a418 +5fa0: 00000036 c0014c00 0145a468 b6fd5000 00000004 c25c4111 bec56800 00020001 +5fc0: 0145a468 b6fd5000 0145a418 00000036 0145a468 0145a600 bec566bc bec566ac +5fe0: 0145a468 bec56388 b6f65ce4 b6dcebec 20000010 00000004 00000000 00000000 +[] (snd_dmaengine_pcm_get_chan+0x8/0x10) from [] (snd_imx_pcm_hw_params+0x18/0xdc) +[] (snd_imx_pcm_hw_params+0x18/0xdc) from [] (soc_pcm_hw_params+0xe8/0x1f0) +[] (soc_pcm_hw_params+0xe8/0x1f0) from [] (snd_pcm_hw_params+0x124/0x474) +[] (snd_pcm_hw_params+0x124/0x474) from [] (snd_pcm_common_ioctl1+0x4b4/0xf74) +[] (snd_pcm_common_ioctl1+0x4b4/0xf74) from [] (snd_pcm_playback_ioctl1+0x30/0x510) +[] (snd_pcm_playback_ioctl1+0x30/0x510) from [] (do_vfs_ioctl+0x80/0x5e4) +[] (do_vfs_ioctl+0x80/0x5e4) from [] (sys_ioctl+0x38/0x60) +[] (sys_ioctl+0x38/0x60) from [] (ret_fast_syscall+0x0/0x2c) +Code: e593000c e12fff1e e59030a0 e59330bc (e5930000) +---[ end trace fa518c8ba3a74e97 ]-- + +Reported-by: Javier Martin +Signed-off-by: Fabio Estevam +Acked-by: Sascha Hauer +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/dma/imx-dma.c | 36 +++++++++++++++++++++++++----------- + 1 file changed, 25 insertions(+), 11 deletions(-) + +--- a/drivers/dma/imx-dma.c ++++ b/drivers/dma/imx-dma.c +@@ -172,7 +172,8 @@ struct imxdma_engine { + struct device_dma_parameters dma_parms; + struct dma_device dma_device; + void __iomem *base; +- struct clk *dma_clk; ++ struct clk *dma_ahb; ++ struct clk *dma_ipg; + spinlock_t lock; + struct imx_dma_2d_config slots_2d[IMX_DMA_2D_SLOTS]; + struct imxdma_channel channel[IMX_DMA_CHANNELS]; +@@ -976,10 +977,20 @@ static int __init imxdma_probe(struct pl + return 0; + } + +- imxdma->dma_clk = clk_get(NULL, "dma"); +- if (IS_ERR(imxdma->dma_clk)) +- return PTR_ERR(imxdma->dma_clk); +- clk_enable(imxdma->dma_clk); ++ imxdma->dma_ipg = devm_clk_get(&pdev->dev, "ipg"); ++ if (IS_ERR(imxdma->dma_ipg)) { ++ ret = PTR_ERR(imxdma->dma_ipg); ++ goto err_clk; ++ } ++ ++ imxdma->dma_ahb = devm_clk_get(&pdev->dev, "ahb"); ++ if (IS_ERR(imxdma->dma_ahb)) { ++ ret = PTR_ERR(imxdma->dma_ahb); ++ goto err_clk; ++ } ++ ++ clk_prepare_enable(imxdma->dma_ipg); ++ clk_prepare_enable(imxdma->dma_ahb); + + /* reset DMA module */ + imx_dmav1_writel(imxdma, DCR_DRST, DMA_DCR); +@@ -988,16 +999,14 @@ static int __init imxdma_probe(struct pl + ret = request_irq(MX1_DMA_INT, dma_irq_handler, 0, "DMA", imxdma); + if (ret) { + dev_warn(imxdma->dev, "Can't register IRQ for DMA\n"); +- kfree(imxdma); +- return ret; ++ goto err_enable; + } + + ret = request_irq(MX1_DMA_ERR, imxdma_err_handler, 0, "DMA", imxdma); + if (ret) { + dev_warn(imxdma->dev, "Can't register ERRIRQ for DMA\n"); + free_irq(MX1_DMA_INT, NULL); +- kfree(imxdma); +- return ret; ++ goto err_enable; + } + } + +@@ -1094,7 +1103,10 @@ err_init: + free_irq(MX1_DMA_INT, NULL); + free_irq(MX1_DMA_ERR, NULL); + } +- ++err_enable: ++ clk_disable_unprepare(imxdma->dma_ipg); ++ clk_disable_unprepare(imxdma->dma_ahb); ++err_clk: + kfree(imxdma); + return ret; + } +@@ -1114,7 +1126,9 @@ static int __exit imxdma_remove(struct p + free_irq(MX1_DMA_ERR, NULL); + } + +- kfree(imxdma); ++ clk_disable_unprepare(imxdma->dma_ipg); ++ clk_disable_unprepare(imxdma->dma_ahb); ++ kfree(imxdma); + + return 0; + } +From 0d8957c8a90bbb5d34fab9a304459448a5131e06 Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Tue, 7 Aug 2012 09:54:14 +0200 +Subject: drm/i915: correctly order the ring init sequence + +From: Daniel Vetter + +commit 0d8957c8a90bbb5d34fab9a304459448a5131e06 upstream. + +We may only start to set up the new register values after having +confirmed that the ring is truely off. Otherwise the hw might lose the +newly written register values. This is caught later on in the init +sequence, when we check whether the register writes have stuck. + +Reviewed-by: Jani Nikula +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=50522 +Tested-by: Yang Guang +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_ringbuffer.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_ringbuffer.c ++++ b/drivers/gpu/drm/i915/intel_ringbuffer.c +@@ -258,8 +258,6 @@ static int init_ring_common(struct intel + I915_WRITE_HEAD(ring, 0); + ring->write_tail(ring, 0); + +- /* Initialize the ring. */ +- I915_WRITE_START(ring, obj->gtt_offset); + head = I915_READ_HEAD(ring) & HEAD_ADDR; + + /* G45 ring initialization fails to reset head to zero */ +@@ -285,6 +283,11 @@ static int init_ring_common(struct intel + } + } + ++ /* Initialize the ring. This must happen _after_ we've cleared the ring ++ * registers with the above sequence (the readback of the HEAD registers ++ * also enforces ordering), otherwise the hw might lose the new ring ++ * register values. */ ++ I915_WRITE_START(ring, obj->gtt_offset); + I915_WRITE_CTL(ring, + ((ring->size - PAGE_SIZE) & RING_NR_PAGES) + | RING_VALID); +From 4344b813f105a19f793f1fd93ad775b784648b95 Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Fri, 10 Aug 2012 11:10:20 +0200 +Subject: drm/i915: ignore eDP bpc settings from vbt + +From: Daniel Vetter + +commit 4344b813f105a19f793f1fd93ad775b784648b95 upstream. + +This has originally been introduced to not oversubscribe the dp links +in + +commit 885a5fb5b120a5c7e0b3baad7b0feb5a89f76c18 +Author: Zhenyu Wang +Date: Tue Jan 12 05:38:31 2010 +0800 + + drm/i915: fix pixel color depth setting on eDP + +Since then we've fixed up the dp link bandwidth calculation code and +should now automatically fall back to 6bpc dithering. So this is +unnecessary. + +Furthermore it seems to break the new MacbookPro with retina display, +hence let's just rip this out. + +Reported-by: Benoit Gschwind +Cc: Benoit Gschwind +Cc: Francois Rigaut +Tested-by: Benoit Gschwind +Tested-by: Bernhard Froemel +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +-- + +Testing feedback highgly welcome, and thanks for Benoit for finding +out that the bpc computations are busted. +-Daniel + +--- + drivers/gpu/drm/i915/intel_display.c | 11 ----------- + 1 file changed, 11 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -4982,17 +4982,6 @@ static bool intel_choose_pipe_bpp_dither + continue; + } + +- if (intel_encoder->type == INTEL_OUTPUT_EDP) { +- /* Use VBT settings if we have an eDP panel */ +- unsigned int edp_bpc = dev_priv->edp.bpp / 3; +- +- if (edp_bpc < display_bpc) { +- DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); +- display_bpc = edp_bpc; +- } +- continue; +- } +- + /* Not one of the known troublemakers, check the EDID */ + list_for_each_entry(connector, &dev->mode_config.connector_list, + head) { +From 2514bc510d0c3aadcc5204056bb440fa36845147 Mon Sep 17 00:00:00 2001 +From: Jesse Barnes +Date: Thu, 21 Jun 2012 15:13:50 -0700 +Subject: drm/i915: prefer wide & slow to fast & narrow in DP configs + +From: Jesse Barnes + +commit 2514bc510d0c3aadcc5204056bb440fa36845147 upstream. + +High frequency link configurations have the potential to cause trouble +with long and/or cheap cables, so prefer slow and wide configurations +instead. This patch has the potential to cause trouble for eDP +configurations that lie about available lanes, so if we run into that we +can make it conditional on eDP. + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=45801 +Tested-by: peter@colberg.org +Signed-off-by: Jesse Barnes +Signed-off-by: Daniel Vetter +Cc: Jonathan Nieder +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_dp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_dp.c ++++ b/drivers/gpu/drm/i915/intel_dp.c +@@ -712,8 +712,8 @@ intel_dp_mode_fixup(struct drm_encoder * + + bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24; + +- for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { +- for (clock = 0; clock <= max_clock; clock++) { ++ for (clock = 0; clock <= max_clock; clock++) { ++ for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { + int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); + + if (intel_dp_link_required(mode->clock, bpp) +From 35a38556d900b9cb5dfa2529c93944b847f8a8a4 Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Sun, 12 Aug 2012 22:17:14 +0200 +Subject: drm/i915: reorder edp disabling to fix ivb MacBook Air + +From: Daniel Vetter + +commit 35a38556d900b9cb5dfa2529c93944b847f8a8a4 upstream. + +eDP is tons of fun. It turns out that at least the new MacBook Air 5,1 +model absolutely doesn't like the new force vdd dance we've introduced +in + +commit 6cb49835da0426f69a2931bc2a0a8156344b0e41 +Author: Daniel Vetter +Date: Sun May 20 17:14:50 2012 +0200 + + drm/i915: enable vdd when switching off the eDP panel + +But that patch also tried to fix some neat edp sequence issue with the +force_vdd timings. Closer inspection reveals that we've raised +force_vdd only to do the aux channel communication dp_sink_dpms. If we +move the edp_panel_off below that, we don't need any force_vdd for the +disable sequence, which makes the Air happy. + +Unfortunately the reporter of the original bug that the above commit +fixed is travelling, so we can't test whether this regresses things. +But my theory is that since we don't check for any power-off -> +force_vdd-on delays in edp_panel_vdd_on, this was the actual +root-cause of this failure. With that force_vdd dance completely +eliminated, I'm hopeful the original bug stays fixed, too. + +For reference the old bug, which hopefully doesn't get broken by this: + +https://bugzilla.kernel.org/show_bug.cgi?id=43163 + +In any case, regression fixers win over plain bugfixes, so this needs +to go in asap. + +v2: The crucial pieces seems to be to clear the force_vdd flag +uncoditionally, too, in edp_panel_off. Looks like this is left behind +by the firmware somehow. + +v3: The Apple firmware seems to switch off the panel on it's own, hence +we still need to keep force_vdd on, but properly clear it when switching +the panel off. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45671 +Tested-by: Roberto Romer +Tested-by: Daniel Wagner +Tested-by: Keith Packard +Cc: Keith Packard +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_dp.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_dp.c ++++ b/drivers/gpu/drm/i915/intel_dp.c +@@ -1156,10 +1156,14 @@ static void ironlake_edp_panel_off(struc + WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n"); + + pp = ironlake_get_pp_control(dev_priv); +- pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE); ++ /* We need to switch off panel power _and_ force vdd, for otherwise some ++ * panels get very unhappy and cease to work. */ ++ pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE); + I915_WRITE(PCH_PP_CONTROL, pp); + POSTING_READ(PCH_PP_CONTROL); + ++ intel_dp->want_panel_vdd = false; ++ + ironlake_wait_panel_off(intel_dp); + } + +@@ -1269,11 +1273,9 @@ static void intel_dp_prepare(struct drm_ + * ensure that we have vdd while we switch off the panel. */ + ironlake_edp_panel_vdd_on(intel_dp); + ironlake_edp_backlight_off(intel_dp); +- ironlake_edp_panel_off(intel_dp); +- + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); ++ ironlake_edp_panel_off(intel_dp); + intel_dp_link_down(intel_dp); +- ironlake_edp_panel_vdd_off(intel_dp, false); + } + + static void intel_dp_commit(struct drm_encoder *encoder) +@@ -1308,11 +1310,9 @@ intel_dp_dpms(struct drm_encoder *encode + /* Switching the panel off requires vdd. */ + ironlake_edp_panel_vdd_on(intel_dp); + ironlake_edp_backlight_off(intel_dp); +- ironlake_edp_panel_off(intel_dp); +- + intel_dp_sink_dpms(intel_dp, mode); ++ ironlake_edp_panel_off(intel_dp); + intel_dp_link_down(intel_dp); +- ironlake_edp_panel_vdd_off(intel_dp, false); + + if (is_cpu_edp(intel_dp)) + ironlake_edp_pll_off(encoder); +From af5e7d84b0ec45b2b614b0d6e3657cbdceaa21f9 Mon Sep 17 00:00:00 2001 +From: Christoph Bumiller +Date: Thu, 26 Jul 2012 20:53:19 +0200 +Subject: drm/nvd0/disp: mask off high 16 bit of negative cursor x-coordinate + +From: Christoph Bumiller + +commit af5e7d84b0ec45b2b614b0d6e3657cbdceaa21f9 upstream. + +Signed-off-by: Christoph Bumiller +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nvd0_display.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/nouveau/nvd0_display.c ++++ b/drivers/gpu/drm/nouveau/nvd0_display.c +@@ -790,7 +790,7 @@ nvd0_crtc_cursor_move(struct drm_crtc *c + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + int ch = EVO_CURS(nv_crtc->index); + +- evo_piow(crtc->dev, ch, 0x0084, (y << 16) | x); ++ evo_piow(crtc->dev, ch, 0x0084, (y << 16) | (x & 0xffff)); + evo_piow(crtc->dev, ch, 0x0080, 0x00000000); + return 0; + } +From 2f292004dd1fb005788dc0a9cdd5559812ed866e Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Mon, 6 Aug 2012 10:03:59 -0400 +Subject: drm/radeon: add some new SI pci ids + +From: Alex Deucher + +commit 2f292004dd1fb005788dc0a9cdd5559812ed866e upstream. + +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + include/drm/drm_pciids.h | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/include/drm/drm_pciids.h ++++ b/include/drm/drm_pciids.h +@@ -217,9 +217,12 @@ + {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6802, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6806, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6819, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ +From 81ee8fb6b52ec69eeed37fe7943446af1dccecc5 Mon Sep 17 00:00:00 2001 +From: Jerome Glisse +Date: Fri, 27 Jul 2012 16:32:24 -0400 +Subject: drm/radeon: do not reenable crtc after moving vram start address + +From: Jerome Glisse + +commit 81ee8fb6b52ec69eeed37fe7943446af1dccecc5 upstream. + +It seems we can not update the crtc scanout address. After disabling +crtc, update to base address do not take effect after crtc being +reenable leading to at least frame being scanout from the old crtc +base address. Disabling crtc display request lead to same behavior. + +So after changing the vram address if we don't keep crtc disabled +we will have the GPU trying to read some random system memory address +with some iommu this will broke the crtc engine and will lead to +broken display and iommu error message. + +So to avoid this, disable crtc. For flicker less boot we will need +to avoid moving the vram start address. + +This patch should also fix : + +https://bugs.freedesktop.org/show_bug.cgi?id=42373 + +Signed-off-by: Jerome Glisse +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/evergreen.c | 57 ----------------------------------- + drivers/gpu/drm/radeon/radeon_asic.h | 8 +--- + drivers/gpu/drm/radeon/rv515.c | 13 ------- + 3 files changed, 2 insertions(+), 76 deletions(-) + +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -1117,24 +1117,8 @@ void evergreen_agp_enable(struct radeon_ + + void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) + { +- save->vga_control[0] = RREG32(D1VGA_CONTROL); +- save->vga_control[1] = RREG32(D2VGA_CONTROL); + save->vga_render_control = RREG32(VGA_RENDER_CONTROL); + save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); +- save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET); +- save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); +- if (rdev->num_crtc >= 4) { +- save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); +- save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL); +- save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); +- save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); +- } +- if (rdev->num_crtc >= 6) { +- save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); +- save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL); +- save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); +- save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); +- } + + /* Stop all video */ + WREG32(VGA_RENDER_CONTROL, 0); +@@ -1245,47 +1229,6 @@ void evergreen_mc_resume(struct radeon_d + /* Unlock host access */ + WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); + mdelay(1); +- /* Restore video state */ +- WREG32(D1VGA_CONTROL, save->vga_control[0]); +- WREG32(D2VGA_CONTROL, save->vga_control[1]); +- if (rdev->num_crtc >= 4) { +- WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]); +- WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]); +- } +- if (rdev->num_crtc >= 6) { +- WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]); +- WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]); +- } +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); +- if (rdev->num_crtc >= 4) { +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); +- } +- if (rdev->num_crtc >= 6) { +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); +- } +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]); +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]); +- if (rdev->num_crtc >= 4) { +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]); +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]); +- } +- if (rdev->num_crtc >= 6) { +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]); +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]); +- } +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); +- if (rdev->num_crtc >= 4) { +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); +- } +- if (rdev->num_crtc >= 6) { +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); +- } + WREG32(VGA_RENDER_CONTROL, save->vga_render_control); + } + +--- a/drivers/gpu/drm/radeon/radeon_asic.h ++++ b/drivers/gpu/drm/radeon/radeon_asic.h +@@ -262,13 +262,10 @@ extern int rs690_mc_wait_for_idle(struct + * rv515 + */ + struct rv515_mc_save { +- u32 d1vga_control; +- u32 d2vga_control; + u32 vga_render_control; + u32 vga_hdp_control; +- u32 d1crtc_control; +- u32 d2crtc_control; + }; ++ + int rv515_init(struct radeon_device *rdev); + void rv515_fini(struct radeon_device *rdev); + uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg); +@@ -401,11 +398,10 @@ void r700_cp_fini(struct radeon_device * + * evergreen + */ + struct evergreen_mc_save { +- u32 vga_control[6]; + u32 vga_render_control; + u32 vga_hdp_control; +- u32 crtc_control[6]; + }; ++ + void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev); + int evergreen_init(struct radeon_device *rdev); + void evergreen_fini(struct radeon_device *rdev); +--- a/drivers/gpu/drm/radeon/rv515.c ++++ b/drivers/gpu/drm/radeon/rv515.c +@@ -281,12 +281,8 @@ int rv515_debugfs_ga_info_init(struct ra + + void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save) + { +- save->d1vga_control = RREG32(R_000330_D1VGA_CONTROL); +- save->d2vga_control = RREG32(R_000338_D2VGA_CONTROL); + save->vga_render_control = RREG32(R_000300_VGA_RENDER_CONTROL); + save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL); +- save->d1crtc_control = RREG32(R_006080_D1CRTC_CONTROL); +- save->d2crtc_control = RREG32(R_006880_D2CRTC_CONTROL); + + /* Stop all video */ + WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); +@@ -311,15 +307,6 @@ void rv515_mc_resume(struct radeon_devic + /* Unlock host access */ + WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control); + mdelay(1); +- /* Restore video state */ +- WREG32(R_000330_D1VGA_CONTROL, save->d1vga_control); +- WREG32(R_000338_D2VGA_CONTROL, save->d2vga_control); +- WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1); +- WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1); +- WREG32(R_006080_D1CRTC_CONTROL, save->d1crtc_control); +- WREG32(R_006880_D2CRTC_CONTROL, save->d2crtc_control); +- WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0); +- WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); + WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control); + } + +From 5b23c9045a8b61352986270b2d109edf5085e113 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Tue, 31 Jul 2012 11:05:11 -0400 +Subject: drm/radeon: fix bank tiling parameters on cayman + +From: Alex Deucher + +commit 5b23c9045a8b61352986270b2d109edf5085e113 upstream. + +Handle the 16 bank case. + +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/ni.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/radeon/ni.c ++++ b/drivers/gpu/drm/radeon/ni.c +@@ -880,10 +880,18 @@ static void cayman_gpu_init(struct radeo + if (rdev->flags & RADEON_IS_IGP) + rdev->config.cayman.tile_config |= 1 << 4; + else { +- if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) +- rdev->config.cayman.tile_config |= 1 << 4; +- else ++ switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { ++ case 0: /* four banks */ + rdev->config.cayman.tile_config |= 0 << 4; ++ break; ++ case 1: /* eight banks */ ++ rdev->config.cayman.tile_config |= 1 << 4; ++ break; ++ case 2: /* sixteen banks */ ++ default: ++ rdev->config.cayman.tile_config |= 2 << 4; ++ break; ++ } + } + rdev->config.cayman.tile_config |= + ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; +From c8d15edc17d836686d1f071e564800e1a2724fa6 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Tue, 31 Jul 2012 11:01:10 -0400 +Subject: drm/radeon: fix bank tiling parameters on evergreen + +From: Alex Deucher + +commit c8d15edc17d836686d1f071e564800e1a2724fa6 upstream. + +Handle the 16 bank case. + +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/evergreen.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -2085,10 +2085,18 @@ static void evergreen_gpu_init(struct ra + if (rdev->flags & RADEON_IS_IGP) + rdev->config.evergreen.tile_config |= 1 << 4; + else { +- if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) +- rdev->config.evergreen.tile_config |= 1 << 4; +- else ++ switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { ++ case 0: /* four banks */ + rdev->config.evergreen.tile_config |= 0 << 4; ++ break; ++ case 1: /* eight banks */ ++ rdev->config.evergreen.tile_config |= 1 << 4; ++ break; ++ case 2: /* sixteen banks */ ++ default: ++ rdev->config.evergreen.tile_config |= 2 << 4; ++ break; ++ } + } + rdev->config.evergreen.tile_config |= + ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) << 8; +From 6c0ae2ab85fc4a95cae82047a7db1f688a7737ab Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Thu, 26 Jul 2012 13:38:52 -0400 +Subject: drm/radeon: properly handle crtc powergating + +From: Alex Deucher + +commit 6c0ae2ab85fc4a95cae82047a7db1f688a7737ab upstream. + +Need to make sure the crtc is gated on before modesetting. +Explicitly gate the crtc on in prepare() and set a flag +so that the dpms functions don't gate it off during +mode set. + +Noticed by sylware on IRC. + +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/atombios_crtc.c | 14 ++++++++++++-- + drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 4 ++++ + drivers/gpu/drm/radeon/radeon_mode.h | 1 + + 3 files changed, 17 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/radeon/atombios_crtc.c ++++ b/drivers/gpu/drm/radeon/atombios_crtc.c +@@ -259,7 +259,7 @@ void atombios_crtc_dpms(struct drm_crtc + /* adjust pm to dpms changes BEFORE enabling crtcs */ + radeon_pm_compute_clocks(rdev); + /* disable crtc pair power gating before programming */ +- if (ASIC_IS_DCE6(rdev)) ++ if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) + atombios_powergate_crtc(crtc, ATOM_DISABLE); + atombios_enable_crtc(crtc, ATOM_ENABLE); + if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) +@@ -279,7 +279,7 @@ void atombios_crtc_dpms(struct drm_crtc + atombios_enable_crtc(crtc, ATOM_DISABLE); + radeon_crtc->enabled = false; + /* power gating is per-pair */ +- if (ASIC_IS_DCE6(rdev)) { ++ if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) { + struct drm_crtc *other_crtc; + struct radeon_crtc *other_radeon_crtc; + list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) { +@@ -1634,18 +1634,28 @@ static bool atombios_crtc_mode_fixup(str + static void atombios_crtc_prepare(struct drm_crtc *crtc) + { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); ++ struct drm_device *dev = crtc->dev; ++ struct radeon_device *rdev = dev->dev_private; + ++ radeon_crtc->in_mode_set = true; + /* pick pll */ + radeon_crtc->pll_id = radeon_atom_pick_pll(crtc); + ++ /* disable crtc pair power gating before programming */ ++ if (ASIC_IS_DCE6(rdev)) ++ atombios_powergate_crtc(crtc, ATOM_DISABLE); ++ + atombios_lock_crtc(crtc, ATOM_ENABLE); + atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + } + + static void atombios_crtc_commit(struct drm_crtc *crtc) + { ++ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); ++ + atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON); + atombios_lock_crtc(crtc, ATOM_DISABLE); ++ radeon_crtc->in_mode_set = false; + } + + static void atombios_crtc_disable(struct drm_crtc *crtc) +--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c ++++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +@@ -1025,9 +1025,11 @@ static int radeon_crtc_mode_set(struct d + + static void radeon_crtc_prepare(struct drm_crtc *crtc) + { ++ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_crtc *crtci; + ++ radeon_crtc->in_mode_set = true; + /* + * The hardware wedges sometimes if you reconfigure one CRTC + * whilst another is running (see fdo bug #24611). +@@ -1038,6 +1040,7 @@ static void radeon_crtc_prepare(struct d + + static void radeon_crtc_commit(struct drm_crtc *crtc) + { ++ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_crtc *crtci; + +@@ -1048,6 +1051,7 @@ static void radeon_crtc_commit(struct dr + if (crtci->enabled) + radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON); + } ++ radeon_crtc->in_mode_set = false; + } + + static const struct drm_crtc_helper_funcs legacy_helper_funcs = { +--- a/drivers/gpu/drm/radeon/radeon_mode.h ++++ b/drivers/gpu/drm/radeon/radeon_mode.h +@@ -266,6 +266,7 @@ struct radeon_crtc { + u16 lut_r[256], lut_g[256], lut_b[256]; + bool enabled; + bool can_tile; ++ bool in_mode_set; + uint32_t crtc_offset; + struct drm_gem_object *cursor_bo; + uint64_t cursor_addr; +From 7e731bc9a12339f344cddf82166b82633d99dd86 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sun, 5 Aug 2012 23:28:16 -0400 +Subject: ext4: avoid kmemcheck complaint from reading uninitialized memory + +From: Theodore Ts'o + +commit 7e731bc9a12339f344cddf82166b82633d99dd86 upstream. + +Commit 03179fe923 introduced a kmemcheck complaint in +ext4_da_get_block_prep() because we save and restore +ei->i_da_metadata_calc_last_lblock even though it is left +uninitialized in the case where i_da_metadata_calc_len is zero. + +This doesn't hurt anything, but silencing the kmemcheck complaint +makes it easier for people to find real bugs. + +Addresses https://bugzilla.kernel.org/show_bug.cgi?id=45631 +(which is marked as a regression). + +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -932,6 +932,7 @@ static struct inode *ext4_alloc_inode(st + ei->i_reserved_meta_blocks = 0; + ei->i_allocated_meta_blocks = 0; + ei->i_da_metadata_calc_len = 0; ++ ei->i_da_metadata_calc_last_lblock = 0; + spin_lock_init(&(ei->i_block_reservation_lock)); + #ifdef CONFIG_QUOTA + ei->i_reserved_quota = 0; +From 89a4e48f8479f8145eca9698f39fe188c982212f Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Fri, 17 Aug 2012 08:54:52 -0400 +Subject: ext4: fix kernel BUG on large-scale rm -rf commands +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Theodore Ts'o + +commit 89a4e48f8479f8145eca9698f39fe188c982212f upstream. + +Commit 968dee7722: "ext4: fix hole punch failure when depth is greater +than 0" introduced a regression in v3.5.1/v3.6-rc1 which caused kernel +crashes when users ran run "rm -rf" on large directory hierarchy on +ext4 filesystems on RAID devices: + + BUG: unable to handle kernel NULL pointer dereference at 0000000000000028 + + Process rm (pid: 18229, threadinfo ffff8801276bc000, task ffff880123631710) + Call Trace: + [] ? __ext4_handle_dirty_metadata+0x83/0x110 + [] ext4_ext_truncate+0x193/0x1d0 + [] ? ext4_mark_inode_dirty+0x7f/0x1f0 + [] ext4_truncate+0xf5/0x100 + [] ext4_evict_inode+0x461/0x490 + [] evict+0xa2/0x1a0 + [] iput+0x103/0x1f0 + [] do_unlinkat+0x154/0x1c0 + [] ? sys_newfstatat+0x2a/0x40 + [] sys_unlinkat+0x1b/0x50 + [] system_call_fastpath+0x16/0x1b + Code: 8b 4d 20 0f b7 41 02 48 8d 04 40 48 8d 04 81 49 89 45 18 0f b7 49 02 48 83 c1 01 49 89 4d 00 e9 ae f8 ff ff 0f 1f 00 49 8b 45 28 <48> 8b 40 28 49 89 45 20 e9 85 f8 ff ff 0f 1f 80 00 00 00 + + RIP [] ext4_ext_remove_space+0xa34/0xdf0 + +This could be reproduced as follows: + +The problem in commit 968dee7722 was that caused the variable 'i' to +be left uninitialized if the truncate required more space than was +available in the journal. This resulted in the function +ext4_ext_truncate_extend_restart() returning -EAGAIN, which caused +ext4_ext_remove_space() to restart the truncate operation after +starting a new jbd2 handle. + +Reported-by: Maciej Żenczykowski +Reported-by: Marti Raudsepp +Tested-by: Fengguang Wu +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/extents.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -2596,6 +2596,7 @@ cont: + } + path[0].p_depth = depth; + path[0].p_hdr = ext_inode_hdr(inode); ++ i = 0; + + if (ext4_ext_check(inode, path[0].p_hdr, depth)) { + err = -EIO; +From 0548bbb85337e532ca2ed697c3e9b227ff2ed4b4 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Thu, 16 Aug 2012 11:59:04 -0400 +Subject: ext4: fix long mount times on very big file systems + +From: Theodore Ts'o + +commit 0548bbb85337e532ca2ed697c3e9b227ff2ed4b4 upstream. + +Commit 8aeb00ff85a: "ext4: fix overhead calculation used by +ext4_statfs()" introduced a O(n**2) calculation which makes very large +file systems take forever to mount. Fix this with an optimization for +non-bigalloc file systems. (For bigalloc file systems the overhead +needs to be set in the the superblock.) + +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -2969,6 +2969,10 @@ static int count_overhead(struct super_b + ext4_group_t i, ngroups = ext4_get_groups_count(sb); + int s, j, count = 0; + ++ if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC)) ++ return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) + ++ sbi->s_itb_per_group + 2); ++ + first_block = le32_to_cpu(sbi->s_es->s_first_data_block) + + (grp * EXT4_BLOCKS_PER_GROUP(sb)); + last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1; +From d796c52ef0b71a988364f6109aeb63d79c5b116b Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sun, 5 Aug 2012 19:04:57 -0400 +Subject: ext4: make sure the journal sb is written in ext4_clear_journal_err() + +From: Theodore Ts'o + +commit d796c52ef0b71a988364f6109aeb63d79c5b116b upstream. + +After we transfer set the EXT4_ERROR_FS bit in the file system +superblock, it's not enough to call jbd2_journal_clear_err() to clear +the error indication from journal superblock --- we need to call +jbd2_journal_update_sb_errno() as well. Otherwise, when the root file +system is mounted read-only, the journal is replayed, and the error +indicator is transferred to the superblock --- but the s_errno field +in the jbd2 superblock is left set (since although we cleared it in +memory, we never flushed it out to disk). + +This can end up confusing e2fsck. We should make e2fsck more robust +in this case, but the kernel shouldn't be leaving things in this +confused state, either. + +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 1 + + fs/jbd2/journal.c | 3 ++- + include/linux/jbd2.h | 1 + + 3 files changed, 4 insertions(+), 1 deletion(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -4227,6 +4227,7 @@ static void ext4_clear_journal_err(struc + ext4_commit_super(sb, 1); + + jbd2_journal_clear_err(journal); ++ jbd2_journal_update_sb_errno(journal); + } + } + +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -1340,7 +1340,7 @@ static void jbd2_mark_journal_empty(jour + * Update a journal's errno. Write updated superblock to disk waiting for IO + * to complete. + */ +-static void jbd2_journal_update_sb_errno(journal_t *journal) ++void jbd2_journal_update_sb_errno(journal_t *journal) + { + journal_superblock_t *sb = journal->j_superblock; + +@@ -1352,6 +1352,7 @@ static void jbd2_journal_update_sb_errno + + jbd2_write_superblock(journal, WRITE_SYNC); + } ++EXPORT_SYMBOL(jbd2_journal_update_sb_errno); + + /* + * Read the superblock for a given journal, performing initial +--- a/include/linux/jbd2.h ++++ b/include/linux/jbd2.h +@@ -1091,6 +1091,7 @@ extern int jbd2_journal_destroy (j + extern int jbd2_journal_recover (journal_t *journal); + extern int jbd2_journal_wipe (journal_t *, int); + extern int jbd2_journal_skip_recovery (journal_t *); ++extern void jbd2_journal_update_sb_errno(journal_t *); + extern void jbd2_journal_update_sb_log_tail (journal_t *, tid_t, + unsigned long, int); + extern void __jbd2_journal_abort_hard (journal_t *); +From fb6ccff667712c46b4501b920ea73a326e49626a Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Tue, 24 Jul 2012 12:10:11 -0700 +Subject: fuse: verify all ioctl retry iov elements + +From: Zach Brown + +commit fb6ccff667712c46b4501b920ea73a326e49626a upstream. + +Commit 7572777eef78ebdee1ecb7c258c0ef94d35bad16 attempted to verify that +the total iovec from the client doesn't overflow iov_length() but it +only checked the first element. The iovec could still overflow by +starting with a small element. The obvious fix is to check all the +elements. + +The overflow case doesn't look dangerous to the kernel as the copy is +limited by the length after the overflow. This fix restores the +intention of returning an error instead of successfully copying less +than the iovec represented. + +I found this by code inspection. I built it but don't have a test case. +I'm cc:ing stable because the initial commit did as well. + +Signed-off-by: Zach Brown +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman + +--- + fs/fuse/file.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -1698,7 +1698,7 @@ static int fuse_verify_ioctl_iov(struct + size_t n; + u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT; + +- for (n = 0; n < count; n++) { ++ for (n = 0; n < count; n++, iov++) { + if (iov->iov_len > (size_t) max) + return -ENOMEM; + max -= iov->iov_len; +From 220329916c72ee3d54ae7262b215a050f04a18fc Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Tue, 14 Aug 2012 13:18:53 +0000 +Subject: IB/srp: Fix a race condition + +From: Bart Van Assche + +commit 220329916c72ee3d54ae7262b215a050f04a18fc upstream. + +Avoid a crash caused by the scmnd->scsi_done(scmnd) call in +srp_process_rsp() being invoked with scsi_done == NULL. This can +happen if a reply is received during or after a command abort. + +Reported-by: Joseph Glanville +Reference: http://marc.info/?l=linux-rdma&m=134314367801595 +Acked-by: David Dillow +Signed-off-by: Bart Van Assche +Signed-off-by: Roland Dreier +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/ulp/srp/ib_srp.c | 87 ++++++++++++++++++++++++++---------- + 1 file changed, 63 insertions(+), 24 deletions(-) + +--- a/drivers/infiniband/ulp/srp/ib_srp.c ++++ b/drivers/infiniband/ulp/srp/ib_srp.c +@@ -586,24 +586,62 @@ static void srp_unmap_data(struct scsi_c + scmnd->sc_data_direction); + } + +-static void srp_remove_req(struct srp_target_port *target, +- struct srp_request *req, s32 req_lim_delta) ++/** ++ * srp_claim_req - Take ownership of the scmnd associated with a request. ++ * @target: SRP target port. ++ * @req: SRP request. ++ * @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take ++ * ownership of @req->scmnd if it equals @scmnd. ++ * ++ * Return value: ++ * Either NULL or a pointer to the SCSI command the caller became owner of. ++ */ ++static struct scsi_cmnd *srp_claim_req(struct srp_target_port *target, ++ struct srp_request *req, ++ struct scsi_cmnd *scmnd) + { + unsigned long flags; + +- srp_unmap_data(req->scmnd, target, req); ++ spin_lock_irqsave(&target->lock, flags); ++ if (!scmnd) { ++ scmnd = req->scmnd; ++ req->scmnd = NULL; ++ } else if (req->scmnd == scmnd) { ++ req->scmnd = NULL; ++ } else { ++ scmnd = NULL; ++ } ++ spin_unlock_irqrestore(&target->lock, flags); ++ ++ return scmnd; ++} ++ ++/** ++ * srp_free_req() - Unmap data and add request to the free request list. ++ */ ++static void srp_free_req(struct srp_target_port *target, ++ struct srp_request *req, struct scsi_cmnd *scmnd, ++ s32 req_lim_delta) ++{ ++ unsigned long flags; ++ ++ srp_unmap_data(scmnd, target, req); ++ + spin_lock_irqsave(&target->lock, flags); + target->req_lim += req_lim_delta; +- req->scmnd = NULL; + list_add_tail(&req->list, &target->free_reqs); + spin_unlock_irqrestore(&target->lock, flags); + } + + static void srp_reset_req(struct srp_target_port *target, struct srp_request *req) + { +- req->scmnd->result = DID_RESET << 16; +- req->scmnd->scsi_done(req->scmnd); +- srp_remove_req(target, req, 0); ++ struct scsi_cmnd *scmnd = srp_claim_req(target, req, NULL); ++ ++ if (scmnd) { ++ scmnd->result = DID_RESET << 16; ++ scmnd->scsi_done(scmnd); ++ srp_free_req(target, req, scmnd, 0); ++ } + } + + static int srp_reconnect_target(struct srp_target_port *target) +@@ -1073,11 +1111,18 @@ static void srp_process_rsp(struct srp_t + complete(&target->tsk_mgmt_done); + } else { + req = &target->req_ring[rsp->tag]; +- scmnd = req->scmnd; +- if (!scmnd) ++ scmnd = srp_claim_req(target, req, NULL); ++ if (!scmnd) { + shost_printk(KERN_ERR, target->scsi_host, + "Null scmnd for RSP w/tag %016llx\n", + (unsigned long long) rsp->tag); ++ ++ spin_lock_irqsave(&target->lock, flags); ++ target->req_lim += be32_to_cpu(rsp->req_lim_delta); ++ spin_unlock_irqrestore(&target->lock, flags); ++ ++ return; ++ } + scmnd->result = rsp->status; + + if (rsp->flags & SRP_RSP_FLAG_SNSVALID) { +@@ -1092,7 +1137,9 @@ static void srp_process_rsp(struct srp_t + else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER)) + scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt)); + +- srp_remove_req(target, req, be32_to_cpu(rsp->req_lim_delta)); ++ srp_free_req(target, req, scmnd, ++ be32_to_cpu(rsp->req_lim_delta)); ++ + scmnd->host_scribble = NULL; + scmnd->scsi_done(scmnd); + } +@@ -1631,25 +1678,17 @@ static int srp_abort(struct scsi_cmnd *s + { + struct srp_target_port *target = host_to_target(scmnd->device->host); + struct srp_request *req = (struct srp_request *) scmnd->host_scribble; +- int ret = SUCCESS; + + shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n"); + +- if (!req || target->qp_in_error) +- return FAILED; +- if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, +- SRP_TSK_ABORT_TASK)) ++ if (!req || target->qp_in_error || !srp_claim_req(target, req, scmnd)) + return FAILED; ++ srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, ++ SRP_TSK_ABORT_TASK); ++ srp_free_req(target, req, scmnd, 0); ++ scmnd->result = DID_ABORT << 16; + +- if (req->scmnd) { +- if (!target->tsk_mgmt_status) { +- srp_remove_req(target, req, 0); +- scmnd->result = DID_ABORT << 16; +- } else +- ret = FAILED; +- } +- +- return ret; ++ return SUCCESS; + } + + static int srp_reset_device(struct scsi_cmnd *scmnd) +From 38f8eefccf3a23c4058a570fa2938a4f553cf8e0 Mon Sep 17 00:00:00 2001 +From: Jason Wessel +Date: Sun, 12 Aug 2012 07:16:43 -0500 +Subject: pmac_zilog,kdb: Fix console poll hook to return instead of loop + +From: Jason Wessel + +commit 38f8eefccf3a23c4058a570fa2938a4f553cf8e0 upstream. + +kdb <-> kgdb transitioning does not work properly with this UART +driver because the get character routine loops indefinitely as opposed +to returning NO_POLL_CHAR per the expectation of the KDB I/O driver +API. + +The symptom is a kernel hang when trying to switch debug modes. + +Signed-off-by: Jason Wessel +Cc: Alan Cox +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/pmac_zilog.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +--- a/drivers/tty/serial/pmac_zilog.c ++++ b/drivers/tty/serial/pmac_zilog.c +@@ -1348,10 +1348,16 @@ static int pmz_verify_port(struct uart_p + static int pmz_poll_get_char(struct uart_port *port) + { + struct uart_pmac_port *uap = (struct uart_pmac_port *)port; ++ int tries = 2; + +- while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) +- udelay(5); +- return read_zsdata(uap); ++ while (tries) { ++ if ((read_zsreg(uap, R0) & Rx_CH_AV) != 0) ++ return read_zsdata(uap); ++ if (tries--) ++ udelay(5); ++ } ++ ++ return NO_POLL_CHAR; + } + + static void pmz_poll_put_char(struct uart_port *port, unsigned char c) +From a769f9577232afe2c754606a83aad85127e7052a Mon Sep 17 00:00:00 2001 +From: Jeongdo Son +Date: Fri, 15 Jun 2012 02:28:01 +0900 +Subject: rt2x00: Add support for BUFFALO WLI-UC-GNM2 to rt2800usb. + +From: Jeongdo Son + +commit a769f9577232afe2c754606a83aad85127e7052a upstream. + +This is a RT3070 based device. + +Signed-off-by: Jeongdo Son +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/rt2x00/rt2800usb.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/rt2x00/rt2800usb.c +@@ -971,6 +971,7 @@ static struct usb_device_id rt2800usb_de + { USB_DEVICE(0x0411, 0x015d) }, + { USB_DEVICE(0x0411, 0x016f) }, + { USB_DEVICE(0x0411, 0x01a2) }, ++ { USB_DEVICE(0x0411, 0x01ee) }, + /* Corega */ + { USB_DEVICE(0x07aa, 0x002f) }, + { USB_DEVICE(0x07aa, 0x003c) }, +From 82aabdb6f1eb61e0034ec23901480f5dd23db7c4 Mon Sep 17 00:00:00 2001 +From: Heiko Carstens +Date: Tue, 7 Aug 2012 09:48:13 +0200 +Subject: s390/compat: fix compat wrappers for process_vm system calls + +From: Heiko Carstens + +commit 82aabdb6f1eb61e0034ec23901480f5dd23db7c4 upstream. + +The compat wrappers incorrectly called the non compat versions of +the system process_vm system calls. + +Signed-off-by: Heiko Carstens +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/kernel/compat_wrapper.S | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/s390/kernel/compat_wrapper.S ++++ b/arch/s390/kernel/compat_wrapper.S +@@ -1636,7 +1636,7 @@ ENTRY(compat_sys_process_vm_readv_wrappe + llgfr %r6,%r6 # unsigned long + llgf %r0,164(%r15) # unsigned long + stg %r0,160(%r15) +- jg sys_process_vm_readv ++ jg compat_sys_process_vm_readv + + ENTRY(compat_sys_process_vm_writev_wrapper) + lgfr %r2,%r2 # compat_pid_t +@@ -1646,4 +1646,4 @@ ENTRY(compat_sys_process_vm_writev_wrapp + llgfr %r6,%r6 # unsigned long + llgf %r0,164(%r15) # unsigned long + stg %r0,160(%r15) +- jg sys_process_vm_writev ++ jg compat_sys_process_vm_writev +From e85871218513c54f7dfdb6009043cb638f2fecbe Mon Sep 17 00:00:00 2001 +From: Heiko Carstens +Date: Wed, 8 Aug 2012 09:32:20 +0200 +Subject: s390/compat: fix mmap compat system calls + +From: Heiko Carstens + +commit e85871218513c54f7dfdb6009043cb638f2fecbe upstream. + +The native 31 bit and the compat behaviour for the mmap system calls differ: + +In native 31 bit mode the passed in address for the mmap system call will be +unmodified passed to sys_mmap_pgoff(). +In compat mode however the passed in address will be modified with +compat_ptr() which masks out the most significant bit. + +The result is that in native 31 bit mode each mmap request (with MAP_FIXED) +will fail where the most significat bit is set, while in compat mode it +may succeed. + +This odd behaviour was introduced with d3815898 "[S390] mmap: add missing +compat_ptr conversion to both mmap compat syscalls". + +To restore a consistent behaviour accross native and compat mode this +patch functionally reverts the above mentioned commit. + +Signed-off-by: Heiko Carstens +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/kernel/compat_linux.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/arch/s390/kernel/compat_linux.c ++++ b/arch/s390/kernel/compat_linux.c +@@ -612,7 +612,6 @@ asmlinkage unsigned long old32_mmap(stru + return -EFAULT; + if (a.offset & ~PAGE_MASK) + return -EINVAL; +- a.addr = (unsigned long) compat_ptr(a.addr); + return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, + a.offset >> PAGE_SHIFT); + } +@@ -623,7 +622,6 @@ asmlinkage long sys32_mmap2(struct mmap_ + + if (copy_from_user(&a, arg, sizeof(a))) + return -EFAULT; +- a.addr = (unsigned long) compat_ptr(a.addr); + return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); + } + +From d81a5d1956731c453b85c141458d4ff5d6cc5366 Mon Sep 17 00:00:00 2001 +From: Gustavo Padovan +Date: Tue, 10 Jul 2012 19:10:06 -0300 +Subject: USB: add USB_VENDOR_AND_INTERFACE_INFO() macro + +From: Gustavo Padovan + +commit d81a5d1956731c453b85c141458d4ff5d6cc5366 upstream. + +A lot of Broadcom Bluetooth devices provides vendor specific interface +class and we are getting flooded by patches adding new device support. +This change will help us enable support for any other Broadcom with vendor +specific device that arrives in the future. + +Only the product id changes for those devices, so this macro would be +perfect for us: + +{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) } + +Signed-off-by: Marcel Holtmann +Signed-off-by: Gustavo Padovan +Acked-by: Henrik Rydberg +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/usb.h | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +--- a/include/linux/usb.h ++++ b/include/linux/usb.h +@@ -783,6 +783,27 @@ static inline int usb_make_path(struct u + .bInterfaceSubClass = (sc), \ + .bInterfaceProtocol = (pr) + ++/** ++ * USB_VENDOR_AND_INTERFACE_INFO - describe a specific usb vendor with a class of usb interfaces ++ * @vend: the 16 bit USB Vendor ID ++ * @cl: bInterfaceClass value ++ * @sc: bInterfaceSubClass value ++ * @pr: bInterfaceProtocol value ++ * ++ * This macro is used to create a struct usb_device_id that matches a ++ * specific vendor with a specific class of interfaces. ++ * ++ * This is especially useful when explicitly matching devices that have ++ * vendor specific bDeviceClass values, but standards-compliant interfaces. ++ */ ++#define USB_VENDOR_AND_INTERFACE_INFO(vend, cl, sc, pr) \ ++ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \ ++ | USB_DEVICE_ID_MATCH_VENDOR, \ ++ .idVendor = (vend), \ ++ .bInterfaceClass = (cl), \ ++ .bInterfaceSubClass = (sc), \ ++ .bInterfaceProtocol = (pr) ++ + /* ----------------------------------------------------------------------- */ + + /* Stuff for dynamic usb ids */ +From 7724a1edbe463b06d4e7831a41149ba095b16c53 Mon Sep 17 00:00:00 2001 +From: Ozan Çağlayan +Date: Fri, 10 Aug 2012 17:25:10 +0300 +Subject: USB: ftdi_sio: Add VID/PID for Kondo Serial USB + +From: Ozan Çağlayan + +commit 7724a1edbe463b06d4e7831a41149ba095b16c53 upstream. + +This adds VID/PID for Kondo Kagaku Co. Ltd. Serial USB Adapter +interface: +http://www.kondo-robot.com/EN/wp/?cat=28 + +Tested by controlling an RCB3 board using libRCB3. + +Signed-off-by: Ozan Çağlayan +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/ftdi_sio.c | 1 + + drivers/usb/serial/ftdi_sio_ids.h | 7 +++++++ + 2 files changed, 8 insertions(+) + +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -811,6 +811,7 @@ static struct usb_device_id id_table_com + { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) }, + { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) }, + { USB_DEVICE(PI_VID, PI_E861_PID) }, ++ { USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) }, + { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, + { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -795,6 +795,13 @@ + #define PI_E861_PID 0x1008 /* E-861 piezo controller USB connection */ + + /* ++ * Kondo Kagaku Co.Ltd. ++ * http://www.kondo-robot.com/EN ++ */ ++#define KONDO_VID 0x165c ++#define KONDO_USB_SERIAL_PID 0x0002 ++ ++/* + * Bayer Ascensia Contour blood glucose meter USB-converter cable. + * http://winglucofacts.com/cables/ + */ +From b1b552a69b8805e7e338074a9e8b670b4a795218 Mon Sep 17 00:00:00 2001 +From: Michael Grzeschik +Date: Wed, 8 Aug 2012 11:48:10 +0200 +Subject: usb: gadget: u_ether: fix kworker 100% CPU issue with still used interfaces in eth_stop + +From: Michael Grzeschik + +commit b1b552a69b8805e7e338074a9e8b670b4a795218 upstream. + +This patch fixes an issue introduced by patch: + + 72c973d usb: gadget: add usb_endpoint_descriptor to struct usb_ep + +Without this patch we see a kworker taking 100% CPU, after this sequence: + +- Connect gadget to a windows host +- load g_ether +- ifconfig up ; ifconfig down; ifconfig up +- ping + +The "ifconfig down" results in calling eth_stop(), which will call +usb_ep_disable() and, if the carrier is still ok, usb_ep_enable(): + + usb_ep_disable(link->in_ep); + usb_ep_disable(link->out_ep); + if (netif_carrier_ok(net)) { + usb_ep_enable(link->in_ep); + usb_ep_enable(link->out_ep); + } + +The ep should stay enabled, but will not, as ep_disable set the desc +pointer to NULL, therefore the subsequent ep_enable will fail. This leads +to permanent rescheduling of the eth_work() worker as usb_ep_queue() +(called by the worker) will fail due to the unconfigured endpoint. + +We fix this issue by saving the ep descriptors and re-assign them before +usb_ep_enable(). + +Cc: Tatyana Brokhman +Signed-off-by: Michael Grzeschik +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/u_ether.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/usb/gadget/u_ether.c ++++ b/drivers/usb/gadget/u_ether.c +@@ -669,6 +669,8 @@ static int eth_stop(struct net_device *n + spin_lock_irqsave(&dev->lock, flags); + if (dev->port_usb) { + struct gether *link = dev->port_usb; ++ const struct usb_endpoint_descriptor *in; ++ const struct usb_endpoint_descriptor *out; + + if (link->close) + link->close(link); +@@ -682,10 +684,14 @@ static int eth_stop(struct net_device *n + * their own pace; the network stack can handle old packets. + * For the moment we leave this here, since it works. + */ ++ in = link->in_ep->desc; ++ out = link->out_ep->desc; + usb_ep_disable(link->in_ep); + usb_ep_disable(link->out_ep); + if (netif_carrier_ok(net)) { + DBG(dev, "host still using in/out endpoints\n"); ++ link->in_ep->desc = in; ++ link->out_ep->desc = out; + usb_ep_enable(link->in_ep); + usb_ep_enable(link->out_ep); + } +From f1b5c997e68533df1f96dcd3068a231bca495603 Mon Sep 17 00:00:00 2001 +From: Bjørn Mork +Date: Wed, 15 Aug 2012 15:43:33 +0200 +Subject: USB: option: add ZTE K5006-Z + +From: Bjørn Mork + +commit f1b5c997e68533df1f96dcd3068a231bca495603 upstream. + +The ZTE (Vodafone) K5006-Z use the following +interface layout: + +00 DIAG +01 secondary +02 modem +03 networkcard +04 storage + +Ignoring interface #3 which is handled by the qmi_wwan +driver. + +Signed-off-by: Bjørn Mork +Cc: Thomas Schäfer +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/option.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -886,6 +886,8 @@ static const struct usb_device_id option + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) }, +From 5c263b92f828af6a8cf54041db45ceae5af8f2ab Mon Sep 17 00:00:00 2001 +From: Mark Ferrell +Date: Tue, 24 Jul 2012 14:15:13 -0500 +Subject: usb: serial: mos7840: Fixup mos7840_chars_in_buffer() + +From: Mark Ferrell + +commit 5c263b92f828af6a8cf54041db45ceae5af8f2ab upstream. + + * Use the buffer content length as opposed to the total buffer size. This can + be a real problem when using the mos7840 as a usb serial-console as all + kernel output is truncated during boot. + +Signed-off-by: Mark Ferrell +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/mos7840.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/usb/serial/mos7840.c ++++ b/drivers/usb/serial/mos7840.c +@@ -1189,9 +1189,12 @@ static int mos7840_chars_in_buffer(struc + } + + spin_lock_irqsave(&mos7840_port->pool_lock, flags); +- for (i = 0; i < NUM_URBS; ++i) +- if (mos7840_port->busy[i]) +- chars += URB_TRANSFER_BUFFER_SIZE; ++ for (i = 0; i < NUM_URBS; ++i) { ++ if (mos7840_port->busy[i]) { ++ struct urb *urb = mos7840_port->write_urb_pool[i]; ++ chars += urb->transfer_buffer_length; ++ } ++ } + spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); + dbg("%s - returns %d", __func__, chars); + return chars; +From ee6f827df9107139e8960326e49e1376352ced4d Mon Sep 17 00:00:00 2001 +From: fangxiaozhi +Date: Wed, 8 Aug 2012 09:24:45 +0000 +Subject: USB: support the new interfaces of Huawei Data Card devices in option driver + +From: fangxiaozhi + +commit ee6f827df9107139e8960326e49e1376352ced4d upstream. + +In this patch, we add new declarations into option.c to support the new +interfaces of Huawei Data Card devices. And at the same time, remove the +redundant declarations from option.c. + +Signed-off-by: fangxiaozhi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/option.c | 279 +++++++++++++++++--------------------------- + 1 file changed, 111 insertions(+), 168 deletions(-) + +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -80,85 +80,9 @@ static void option_instat_callback(struc + #define OPTION_PRODUCT_GTM380_MODEM 0x7201 + + #define HUAWEI_VENDOR_ID 0x12D1 +-#define HUAWEI_PRODUCT_E600 0x1001 +-#define HUAWEI_PRODUCT_E220 0x1003 +-#define HUAWEI_PRODUCT_E220BIS 0x1004 +-#define HUAWEI_PRODUCT_E1401 0x1401 +-#define HUAWEI_PRODUCT_E1402 0x1402 +-#define HUAWEI_PRODUCT_E1403 0x1403 +-#define HUAWEI_PRODUCT_E1404 0x1404 +-#define HUAWEI_PRODUCT_E1405 0x1405 +-#define HUAWEI_PRODUCT_E1406 0x1406 +-#define HUAWEI_PRODUCT_E1407 0x1407 +-#define HUAWEI_PRODUCT_E1408 0x1408 +-#define HUAWEI_PRODUCT_E1409 0x1409 +-#define HUAWEI_PRODUCT_E140A 0x140A +-#define HUAWEI_PRODUCT_E140B 0x140B +-#define HUAWEI_PRODUCT_E140C 0x140C +-#define HUAWEI_PRODUCT_E140D 0x140D +-#define HUAWEI_PRODUCT_E140E 0x140E +-#define HUAWEI_PRODUCT_E140F 0x140F +-#define HUAWEI_PRODUCT_E1410 0x1410 +-#define HUAWEI_PRODUCT_E1411 0x1411 +-#define HUAWEI_PRODUCT_E1412 0x1412 +-#define HUAWEI_PRODUCT_E1413 0x1413 +-#define HUAWEI_PRODUCT_E1414 0x1414 +-#define HUAWEI_PRODUCT_E1415 0x1415 +-#define HUAWEI_PRODUCT_E1416 0x1416 +-#define HUAWEI_PRODUCT_E1417 0x1417 +-#define HUAWEI_PRODUCT_E1418 0x1418 +-#define HUAWEI_PRODUCT_E1419 0x1419 +-#define HUAWEI_PRODUCT_E141A 0x141A +-#define HUAWEI_PRODUCT_E141B 0x141B +-#define HUAWEI_PRODUCT_E141C 0x141C +-#define HUAWEI_PRODUCT_E141D 0x141D +-#define HUAWEI_PRODUCT_E141E 0x141E +-#define HUAWEI_PRODUCT_E141F 0x141F +-#define HUAWEI_PRODUCT_E1420 0x1420 +-#define HUAWEI_PRODUCT_E1421 0x1421 +-#define HUAWEI_PRODUCT_E1422 0x1422 +-#define HUAWEI_PRODUCT_E1423 0x1423 +-#define HUAWEI_PRODUCT_E1424 0x1424 +-#define HUAWEI_PRODUCT_E1425 0x1425 +-#define HUAWEI_PRODUCT_E1426 0x1426 +-#define HUAWEI_PRODUCT_E1427 0x1427 +-#define HUAWEI_PRODUCT_E1428 0x1428 +-#define HUAWEI_PRODUCT_E1429 0x1429 +-#define HUAWEI_PRODUCT_E142A 0x142A +-#define HUAWEI_PRODUCT_E142B 0x142B +-#define HUAWEI_PRODUCT_E142C 0x142C +-#define HUAWEI_PRODUCT_E142D 0x142D +-#define HUAWEI_PRODUCT_E142E 0x142E +-#define HUAWEI_PRODUCT_E142F 0x142F +-#define HUAWEI_PRODUCT_E1430 0x1430 +-#define HUAWEI_PRODUCT_E1431 0x1431 +-#define HUAWEI_PRODUCT_E1432 0x1432 +-#define HUAWEI_PRODUCT_E1433 0x1433 +-#define HUAWEI_PRODUCT_E1434 0x1434 +-#define HUAWEI_PRODUCT_E1435 0x1435 +-#define HUAWEI_PRODUCT_E1436 0x1436 +-#define HUAWEI_PRODUCT_E1437 0x1437 +-#define HUAWEI_PRODUCT_E1438 0x1438 +-#define HUAWEI_PRODUCT_E1439 0x1439 +-#define HUAWEI_PRODUCT_E143A 0x143A +-#define HUAWEI_PRODUCT_E143B 0x143B +-#define HUAWEI_PRODUCT_E143C 0x143C +-#define HUAWEI_PRODUCT_E143D 0x143D +-#define HUAWEI_PRODUCT_E143E 0x143E +-#define HUAWEI_PRODUCT_E143F 0x143F + #define HUAWEI_PRODUCT_K4505 0x1464 + #define HUAWEI_PRODUCT_K3765 0x1465 +-#define HUAWEI_PRODUCT_E14AC 0x14AC +-#define HUAWEI_PRODUCT_K3806 0x14AE + #define HUAWEI_PRODUCT_K4605 0x14C6 +-#define HUAWEI_PRODUCT_K5005 0x14C8 +-#define HUAWEI_PRODUCT_K3770 0x14C9 +-#define HUAWEI_PRODUCT_K3771 0x14CA +-#define HUAWEI_PRODUCT_K4510 0x14CB +-#define HUAWEI_PRODUCT_K4511 0x14CC +-#define HUAWEI_PRODUCT_ETS1220 0x1803 +-#define HUAWEI_PRODUCT_E353 0x1506 +-#define HUAWEI_PRODUCT_E173S 0x1C05 + + #define QUANTA_VENDOR_ID 0x0408 + #define QUANTA_PRODUCT_Q101 0xEA02 +@@ -615,104 +539,123 @@ static const struct usb_device_id option + { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) }, + { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) }, + { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1402, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1404, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1407, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140A, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140B, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140C, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140D, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140E, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140F, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141A, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141B, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141C, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141D, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141E, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141F, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1420, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1421, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1422, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1423, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1424, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1425, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1426, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1427, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1428, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1429, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142A, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142B, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142C, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142D, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142E, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142F, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1430, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1431, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1432, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1433, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1434, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1435, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1436, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1437, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1438, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1439, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143A, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143B, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143C, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x31) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x32) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x31) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x32) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x33) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x32) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x31) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x32) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x31) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x32) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x02) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x03) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x10) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x12) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x13) }, +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x01) }, /* E398 3G Modem */ +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x02) }, /* E398 3G PC UI Interface */ +- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x03) }, /* E398 3G Application Interface */ ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0xff, 0xff) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x01) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x02) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x03) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x04) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x05) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x06) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0A) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0B) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0D) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0E) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0F) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x10) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x12) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x13) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x14) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x15) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x17) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x18) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x19) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1A) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1B) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1C) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x31) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x32) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x33) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x34) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x35) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x36) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3A) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3B) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3D) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3E) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3F) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x48) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x49) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4A) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4B) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4C) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x61) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x62) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x63) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x64) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x65) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x66) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6A) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6B) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6D) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6E) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6F) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x78) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x79) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7A) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7B) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7C) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x01) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x02) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x03) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x04) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x05) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x06) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0A) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0B) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0D) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0E) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0F) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x10) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x12) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x13) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x14) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x15) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x17) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x18) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x19) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1A) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1B) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1C) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x31) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x32) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x33) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x34) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x35) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x36) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3A) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3B) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3D) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3E) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3F) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x48) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x49) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4A) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4B) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4C) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x61) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x62) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x63) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x64) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x65) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x66) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6A) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6B) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6D) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6E) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6F) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x78) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x79) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7B) }, ++ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7C) }, ++ ++ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, +From b9e0d95c041ca2d7ad297ee37c2e9cfab67a188f Mon Sep 17 00:00:00 2001 +From: Stefano Stabellini +Date: Wed, 23 May 2012 18:57:20 +0100 +Subject: xen: mark local pages as FOREIGN in the m2p_override + +From: Stefano Stabellini + +commit b9e0d95c041ca2d7ad297ee37c2e9cfab67a188f upstream. + +When the frontend and the backend reside on the same domain, even if we +add pages to the m2p_override, these pages will never be returned by +mfn_to_pfn because the check "get_phys_to_machine(pfn) != mfn" will +always fail, so the pfn of the frontend will be returned instead +(resulting in a deadlock because the frontend pages are already locked). + +INFO: task qemu-system-i38:1085 blocked for more than 120 seconds. +"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +qemu-system-i38 D ffff8800cfc137c0 0 1085 1 0x00000000 + ffff8800c47ed898 0000000000000282 ffff8800be4596b0 00000000000137c0 + ffff8800c47edfd8 ffff8800c47ec010 00000000000137c0 00000000000137c0 + ffff8800c47edfd8 00000000000137c0 ffffffff82213020 ffff8800be4596b0 +Call Trace: + [] ? __lock_page+0x70/0x70 + [] schedule+0x29/0x70 + [] io_schedule+0x60/0x80 + [] sleep_on_page+0xe/0x20 + [] __wait_on_bit_lock+0x5a/0xc0 + [] __lock_page+0x67/0x70 + [] ? autoremove_wake_function+0x40/0x40 + [] ? bio_add_page+0x36/0x40 + [] set_page_dirty_lock+0x52/0x60 + [] bio_set_pages_dirty+0x51/0x70 + [] do_blockdev_direct_IO+0xb24/0xeb0 + [] ? ext3_get_blocks_handle+0xe00/0xe00 + [] __blockdev_direct_IO+0x55/0x60 + [] ? ext3_get_blocks_handle+0xe00/0xe00 + [] ext3_direct_IO+0xf8/0x390 + [] ? ext3_get_blocks_handle+0xe00/0xe00 + [] ? xen_mc_flush+0xb0/0x1b0 + [] generic_file_aio_read+0x737/0x780 + [] ? gnttab_map_refs+0x15b/0x1e0 + [] ? find_get_pages+0x150/0x150 + [] aio_rw_vect_retry+0x7c/0x1d0 + [] ? lookup_ioctx+0x90/0x90 + [] aio_run_iocb+0x66/0x1a0 + [] do_io_submit+0x708/0xb90 + [] sys_io_submit+0x10/0x20 + [] system_call_fastpath+0x16/0x1b + +The explanation is in the comment within the code: + +We need to do this because the pages shared by the frontend +(xen-blkfront) can be already locked (lock_page, called by +do_read_cache_page); when the userspace backend tries to use them +with direct_IO, mfn_to_pfn returns the pfn of the frontend, so +do_blockdev_direct_IO is going to try to lock the same pages +again resulting in a deadlock. + +A simplified call graph looks like this: + +pygrub QEMU +----------------------------------------------- +do_read_cache_page io_submit + | | +lock_page ext3_direct_IO + | + bio_add_page + | + lock_page + +Internally the xen-blkback uses m2p_add_override to swizzle (temporarily) +a 'struct page' to have a different MFN (so that it can point to another +guest). It also can easily find out whether another pfn corresponding +to the mfn exists in the m2p, and can set the FOREIGN bit +in the p2m, making sure that mfn_to_pfn returns the pfn of the backend. + +This allows the backend to perform direct_IO on these pages, but as a +side effect prevents the frontend from using get_user_pages_fast on +them while they are being shared with the backend. + +Signed-off-by: Stefano Stabellini +Signed-off-by: Konrad Rzeszutek Wilk +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/xen/p2m.c | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +--- a/arch/x86/xen/p2m.c ++++ b/arch/x86/xen/p2m.c +@@ -686,6 +686,7 @@ int m2p_add_override(unsigned long mfn, + unsigned long uninitialized_var(address); + unsigned level; + pte_t *ptep = NULL; ++ int ret = 0; + + pfn = page_to_pfn(page); + if (!PageHighMem(page)) { +@@ -721,6 +722,24 @@ int m2p_add_override(unsigned long mfn, + list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); + spin_unlock_irqrestore(&m2p_override_lock, flags); + ++ /* p2m(m2p(mfn)) == mfn: the mfn is already present somewhere in ++ * this domain. Set the FOREIGN_FRAME_BIT in the p2m for the other ++ * pfn so that the following mfn_to_pfn(mfn) calls will return the ++ * pfn from the m2p_override (the backend pfn) instead. ++ * We need to do this because the pages shared by the frontend ++ * (xen-blkfront) can be already locked (lock_page, called by ++ * do_read_cache_page); when the userspace backend tries to use them ++ * with direct_IO, mfn_to_pfn returns the pfn of the frontend, so ++ * do_blockdev_direct_IO is going to try to lock the same pages ++ * again resulting in a deadlock. ++ * As a side effect get_user_pages_fast might not be safe on the ++ * frontend pages while they are being shared with the backend, ++ * because mfn_to_pfn (that ends up being called by GUPF) will ++ * return the backend pfn rather than the frontend pfn. */ ++ ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); ++ if (ret == 0 && get_phys_to_machine(pfn) == mfn) ++ set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)); ++ + return 0; + } + EXPORT_SYMBOL_GPL(m2p_add_override); +@@ -732,6 +751,7 @@ int m2p_remove_override(struct page *pag + unsigned long uninitialized_var(address); + unsigned level; + pte_t *ptep = NULL; ++ int ret = 0; + + pfn = page_to_pfn(page); + mfn = get_phys_to_machine(pfn); +@@ -801,6 +821,22 @@ int m2p_remove_override(struct page *pag + } else + set_phys_to_machine(pfn, page->index); + ++ /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present ++ * somewhere in this domain, even before being added to the ++ * m2p_override (see comment above in m2p_add_override). ++ * If there are no other entries in the m2p_override corresponding ++ * to this mfn, then remove the FOREIGN_FRAME_BIT from the p2m for ++ * the original pfn (the one shared by the frontend): the backend ++ * cannot do any IO on this page anymore because it has been ++ * unshared. Removing the FOREIGN_FRAME_BIT from the p2m entry of ++ * the original pfn causes mfn_to_pfn(mfn) to return the frontend ++ * pfn again. */ ++ mfn &= ~FOREIGN_FRAME_BIT; ++ ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); ++ if (ret == 0 && get_phys_to_machine(pfn) == FOREIGN_FRAME(mfn) && ++ m2p_find_override(mfn) == NULL) ++ set_phys_to_machine(pfn, mfn); ++ + return 0; + } + EXPORT_SYMBOL_GPL(m2p_remove_override); +From 5cb7df2b2d3afee7638b3ef23a5bcb89c6f07bd9 Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Mon, 2 Jul 2012 13:36:23 -0700 +Subject: xhci: Add Etron XHCI_TRUST_TX_LENGTH quirk. + +From: Sarah Sharp + +commit 5cb7df2b2d3afee7638b3ef23a5bcb89c6f07bd9 upstream. + +Gary reports that with recent kernels, he notices more xHCI driver +warnings: + +xhci_hcd 0000:03:00.0: WARN Successful completion on short TX: needs XHCI_TRUST_TX_LENGTH quirk? + +We think his Etron xHCI host controller may have the same buggy behavior +as the Fresco Logic xHCI host. When a short transfer is received, the +host will mark the transfer as successfully completed when it should be +marking it with a short completion. + +Fix this by turning on the XHCI_TRUST_TX_LENGTH quirk when the Etron +host is discovered. Note that Gary has revision 1, but if Etron fixes +this bug in future revisions, the quirk will have no effect. + +This patch should be backported to kernels as old as 2.6.36, that +contain a backported version of commit +1530bbc6272d9da1e39ef8e06190d42c13a02733 "xhci: Add new short TX quirk +for Fresco Logic host." + +Signed-off-by: Sarah Sharp +Reported-by: Gary E. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-pci.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -95,6 +95,7 @@ static void xhci_pci_quirks(struct devic + pdev->device == PCI_DEVICE_ID_ASROCK_P67) { + xhci->quirks |= XHCI_RESET_ON_RESUME; + xhci_dbg(xhci, "QUIRK: Resetting on resume\n"); ++ xhci->quirks |= XHCI_TRUST_TX_LENGTH; + } + if (pdev->vendor == PCI_VENDOR_ID_VIA) + xhci->quirks |= XHCI_RESET_ON_RESUME; +From 50d0206fcaea3e736f912fd5b00ec6233fb4ce44 Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Thu, 26 Jul 2012 12:03:59 -0700 +Subject: xhci: Fix bug after deq ptr set to link TRB. + +From: Sarah Sharp + +commit 50d0206fcaea3e736f912fd5b00ec6233fb4ce44 upstream. + +This patch fixes a particularly nasty bug that was revealed by the ring +expansion patches. The bug has been present since the very beginning of +the xHCI driver history, and could have caused general protection faults +from bad memory accesses. + +The first thing to note is that a Set TR Dequeue Pointer command can +move the dequeue pointer to a link TRB, if the canceled or stalled +transfer TD ended just before a link TRB. The function to increment the +dequeue pointer, inc_deq, was written before cancellation and stall +support was added. It assumed that the dequeue pointer could never +point to a link TRB. It would unconditionally increment the dequeue +pointer at the start of the function, check if the pointer was now on a +link TRB, and move it to the top of the next segment if so. + +This means that if a Set TR Dequeue Point command moved the dequeue +pointer to a link TRB, a subsequent call to inc_deq() would move the +pointer off the segment and into la-la-land. It would then read from +that memory to determine if it was a link TRB. Other functions would +often call inc_deq() until the dequeue pointer matched some other +pointer, which means this function would quite happily read all of +system memory before wrapping around to the right pointer value. + +Often, there would be another endpoint segment from a different ring +allocated from the same DMA pool, which would be contiguous to the +segment inc_deq just stepped off of. inc_deq would eventually find the +link TRB in that segment, and blindly move the dequeue pointer back to +the top of the correct ring segment. + +The only reason the original code worked at all is because there was +only one ring segment. With the ring expansion patches, the dequeue +pointer would eventually wrap into place, but the dequeue segment would +be out-of-sync. On the second TD after the dequeue pointer was moved to +a link TRB, trb_in_td() would fail (because the dequeue pointer and +dequeue segment were out-of-sync), and this message would appear: + +ERROR Transfer event TRB DMA ptr not part of current TD + +This fixes bugzilla entry 4333 (option-based modem unhappy on USB 3.0 +port: "Transfer event TRB DMA ptr not part of current TD", "rejecting +I/O to offline device"), + + https://bugzilla.kernel.org/show_bug.cgi?id=43333 + +and possibly other general protection fault bugs as well. + +This patch should be backported to kernels as old as 2.6.31. A separate +patch will be created for kernels older than 3.4, since inc_deq was +modified in 3.4 and this patch will not apply. + +Signed-off-by: Sarah Sharp +Tested-by: James Ettle +Tested-by: Matthew Hall +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-ring.c | 36 ++++++++++++++++++++++-------------- + 1 file changed, 22 insertions(+), 14 deletions(-) + +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -145,29 +145,37 @@ static void next_trb(struct xhci_hcd *xh + */ + static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring) + { +- union xhci_trb *next; + unsigned long long addr; + + ring->deq_updates++; + +- /* If this is not event ring, there is one more usable TRB */ ++ /* ++ * If this is not event ring, and the dequeue pointer ++ * is not on a link TRB, there is one more usable TRB ++ */ + if (ring->type != TYPE_EVENT && + !last_trb(xhci, ring, ring->deq_seg, ring->dequeue)) + ring->num_trbs_free++; +- next = ++(ring->dequeue); + +- /* Update the dequeue pointer further if that was a link TRB or we're at +- * the end of an event ring segment (which doesn't have link TRBS) +- */ +- while (last_trb(xhci, ring, ring->deq_seg, next)) { +- if (ring->type == TYPE_EVENT && last_trb_on_last_seg(xhci, +- ring, ring->deq_seg, next)) { +- ring->cycle_state = (ring->cycle_state ? 0 : 1); ++ do { ++ /* ++ * Update the dequeue pointer further if that was a link TRB or ++ * we're at the end of an event ring segment (which doesn't have ++ * link TRBS) ++ */ ++ if (last_trb(xhci, ring, ring->deq_seg, ring->dequeue)) { ++ if (ring->type == TYPE_EVENT && ++ last_trb_on_last_seg(xhci, ring, ++ ring->deq_seg, ring->dequeue)) { ++ ring->cycle_state = (ring->cycle_state ? 0 : 1); ++ } ++ ring->deq_seg = ring->deq_seg->next; ++ ring->dequeue = ring->deq_seg->trbs; ++ } else { ++ ring->dequeue++; + } +- ring->deq_seg = ring->deq_seg->next; +- ring->dequeue = ring->deq_seg->trbs; +- next = ring->dequeue; +- } ++ } while (last_trb(xhci, ring, ring->deq_seg, ring->dequeue)); ++ + addr = (unsigned long long) xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue); + } + +From 22ceac191211cf6688b1bf6ecd93c8b6bf80ed9b Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Mon, 23 Jul 2012 16:06:08 -0700 +Subject: xhci: Increase reset timeout for Renesas 720201 host. + +From: Sarah Sharp + +commit 22ceac191211cf6688b1bf6ecd93c8b6bf80ed9b upstream. + +The NEC/Renesas 720201 xHCI host controller does not complete its reset +within 250 milliseconds. In fact, it takes about 9 seconds to reset the +host controller, and 1 second for the host to be ready for doorbell +rings. Extend the reset and CNR polling timeout to 10 seconds each. + +This patch should be backported to kernels as old as 2.6.31, that +contain the commit 66d4eadd8d067269ea8fead1a50fe87c2979a80d "USB: xhci: +BIOS handoff and HW initialization." + +Signed-off-by: Sarah Sharp +Reported-by: Edwin Klein Mentink +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -166,7 +166,7 @@ int xhci_reset(struct xhci_hcd *xhci) + xhci_writel(xhci, command, &xhci->op_regs->command); + + ret = handshake(xhci, &xhci->op_regs->command, +- CMD_RESET, 0, 250 * 1000); ++ CMD_RESET, 0, 10 * 1000 * 1000); + if (ret) + return ret; + +@@ -175,7 +175,8 @@ int xhci_reset(struct xhci_hcd *xhci) + * xHCI cannot write to any doorbells or operational registers other + * than status until the "Controller Not Ready" flag is cleared. + */ +- ret = handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); ++ ret = handshake(xhci, &xhci->op_regs->status, ++ STS_CNR, 0, 10 * 1000 * 1000); + + for (i = 0; i < 2; ++i) { + xhci->bus_state[i].port_c_suspend = 0; +From e95829f474f0db3a4d940cae1423783edd966027 Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Mon, 23 Jul 2012 18:59:30 +0300 +Subject: xhci: Switch PPT ports to EHCI on shutdown. + +From: Sarah Sharp + +commit e95829f474f0db3a4d940cae1423783edd966027 upstream. + +The Intel desktop boards DH77EB and DH77DF have a hardware issue that +can be worked around by BIOS. If the USB ports are switched to xHCI on +shutdown, the xHCI host will send a spurious interrupt, which will wake +the system. Some BIOS will work around this, but not all. + +The bug can be avoided if the USB ports are switched back to EHCI on +shutdown. The Intel Windows driver switches the ports back to EHCI, so +change the Linux xHCI driver to do the same. + +Unfortunately, we can't tell the two effected boards apart from other +working motherboards, because the vendors will change the DMI strings +for the DH77EB and DH77DF boards to their own custom names. One example +is Compulab's mini-desktop, the Intense-PC. Instead, key off the +Panther Point xHCI host PCI vendor and device ID, and switch the ports +over for all PPT xHCI hosts. + +The only impact this will have on non-effected boards is to add a couple +hundred milliseconds delay on boot when the BIOS has to switch the ports +over from EHCI to xHCI. + +This patch should be backported to kernels as old as 3.0, that contain +the commit 69e848c2090aebba5698a1620604c7dccb448684 "Intel xhci: Support +EHCI/xHCI port switching." + +Signed-off-by: Sarah Sharp +Reported-by: Denis Turischev +Tested-by: Denis Turischev +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/pci-quirks.c | 7 +++++++ + drivers/usb/host/pci-quirks.h | 1 + + drivers/usb/host/xhci-pci.c | 9 +++++++++ + drivers/usb/host/xhci.c | 3 +++ + drivers/usb/host/xhci.h | 1 + + 5 files changed, 21 insertions(+) + +--- a/drivers/usb/host/pci-quirks.c ++++ b/drivers/usb/host/pci-quirks.c +@@ -800,6 +800,13 @@ void usb_enable_xhci_ports(struct pci_de + } + EXPORT_SYMBOL_GPL(usb_enable_xhci_ports); + ++void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) ++{ ++ pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, 0x0); ++ pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, 0x0); ++} ++EXPORT_SYMBOL_GPL(usb_disable_xhci_ports); ++ + /** + * PCI Quirks for xHCI. + * +--- a/drivers/usb/host/pci-quirks.h ++++ b/drivers/usb/host/pci-quirks.h +@@ -10,6 +10,7 @@ void usb_amd_quirk_pll_disable(void); + void usb_amd_quirk_pll_enable(void); + bool usb_is_intel_switchable_xhci(struct pci_dev *pdev); + void usb_enable_xhci_ports(struct pci_dev *xhci_pdev); ++void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); + #else + static inline void usb_amd_quirk_pll_disable(void) {} + static inline void usb_amd_quirk_pll_enable(void) {} +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -90,6 +90,15 @@ static void xhci_pci_quirks(struct devic + xhci->quirks |= XHCI_EP_LIMIT_QUIRK; + xhci->limit_active_eps = 64; + xhci->quirks |= XHCI_SW_BW_CHECKING; ++ /* ++ * PPT desktop boards DH77EB and DH77DF will power back on after ++ * a few seconds of being shutdown. The fix for this is to ++ * switch the ports from xHCI to EHCI on shutdown. We can't use ++ * DMI information to find those particular boards (since each ++ * vendor will change the board name), so we have to key off all ++ * PPT chipsets. ++ */ ++ xhci->quirks |= XHCI_SPURIOUS_REBOOT; + } + if (pdev->vendor == PCI_VENDOR_ID_ETRON && + pdev->device == PCI_DEVICE_ID_ASROCK_P67) { +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -659,6 +659,9 @@ void xhci_shutdown(struct usb_hcd *hcd) + { + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + ++ if (xhci->quirks && XHCI_SPURIOUS_REBOOT) ++ usb_disable_xhci_ports(to_pci_dev(hcd->self.controller)); ++ + spin_lock_irq(&xhci->lock); + xhci_halt(xhci); + spin_unlock_irq(&xhci->lock); +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1486,6 +1486,7 @@ struct xhci_hcd { + #define XHCI_SW_BW_CHECKING (1 << 8) + #define XHCI_AMD_0x96_HOST (1 << 9) + #define XHCI_TRUST_TX_LENGTH (1 << 10) ++#define XHCI_SPURIOUS_REBOOT (1 << 13) + unsigned int num_active_eps; + unsigned int limit_active_eps; + /* There are two roothubs to keep track of bus suspend info for */ From b750218819e18c8f6c5d21fd057f01a67f11218a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 5 Sep 2012 08:51:35 -0400 Subject: [PATCH 426/487] Linux v3.4.10 --- kernel.spec | 13 +- linux-3.4.10-queue.patch | 2464 -------------------------------------- sources | 2 +- 3 files changed, 6 insertions(+), 2473 deletions(-) delete mode 100644 linux-3.4.10-queue.patch diff --git a/kernel.spec b/kernel.spec index f84d837fe..a46db9d10 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 9 +%define stable_update 10 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -720,9 +720,6 @@ Patch22072: tcp-Apply-device-TSO-segment-limit-earlier.patch Patch22075: af_netlink-credentials-cve-2012-3520.patch -#Patches from the 3.4.10 stable queue -Patch22100: linux-3.4.10-queue.patch - # END OF PATCH DEFINITIONS %endif @@ -1348,9 +1345,6 @@ ApplyPatch tcp-Apply-device-TSO-segment-limit-earlier.patch ApplyPatch af_netlink-credentials-cve-2012-3520.patch -#Patches from the 3.4.10 stable queue -ApplyPatch linux-3.4.10-queue.patch - # END OF PATCH APPLICATIONS %endif @@ -2049,6 +2043,9 @@ fi # and build. %changelog +* Wed Sep 05 2012 Josh Boyer 3.4.10-1 +- Linux v3.4.10 + * Thu Aug 23 2012 Justin M. Forbes 3.4.9-2 - af_netlink: force credentials passing [CVE-2012-3520] - Add patches from 3.4.10 queue diff --git a/linux-3.4.10-queue.patch b/linux-3.4.10-queue.patch deleted file mode 100644 index 72cfb19f5..000000000 --- a/linux-3.4.10-queue.patch +++ /dev/null @@ -1,2464 +0,0 @@ -From a2367db2ec5e7fc6fe93e221e0fcdee81b053daf Mon Sep 17 00:00:00 2001 -From: Fabio Estevam -Date: Tue, 3 Jul 2012 15:33:29 -0300 -Subject: dma: imx-dma: Fix kernel crash due to missing clock conversion - -From: Fabio Estevam - -commit a2367db2ec5e7fc6fe93e221e0fcdee81b053daf upstream. - -With the new i.MX clock infrastructure we need to request the dma clocks -seperately: ahb and ipg clocks. - -This fixes the following kernel crash and make audio to be functional again: - -root@freescale /home$ aplay audio48k16S.wav -Playing WAVE 'audio48k16S.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo -Unable to handle kernel NULL pointer dereference at virtual address 00000000 -pgd = c7b74000 -[00000000] *pgd=a7bb5831, *pte=00000000, *ppte=00000000 -Internal error: Oops: 17 [#1] PREEMPT ARM -Modules linked in: -CPU: 0 Not tainted (3.5.0-rc5-next-20120702-00007-g3028b64 #1128) -PC is at snd_dmaengine_pcm_get_chan+0x8/0x10 -LR is at snd_imx_pcm_hw_params+0x18/0xdc -pc : [] lr : [] psr: a0000013 -sp : c7b45e30 ip : ffffffff fp : c7ae58e0 -r10: 00000000 r9 : c7ae981c r8 : c7b88800 -r7 : c7ae5a60 r6 : c7ae5b20 r5 : c7ae9810 r4 : c7afa060 -r3 : 00000000 r2 : 00000001 r1 : c7b88800 r0 : c7afa060 -Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user -Control: 0005317f Table: a7b74000 DAC: 00000015 -Process aplay (pid: 701, stack limit = 0xc7b44270) -Stack: (0xc7b45e30 to 0xc7b46000) -5e20: 00100000 00000029 c7b88800 c02db870 -5e40: c7ae5a60 c02d4594 00000010 01ae5a60 c7ae5a60 c7ae9810 c7ae9810 c7afa060 -5e60: c7ae5b20 c7ae5a60 c7b88800 c02e3ef0 c02e3e08 c7b1e400 c7afa060 c7b88800 -5e80: 00000000 c0014da8 c7b44000 00000000 bec566ac c02cd400 c7afa060 c7afa060 -5ea0: bec56800 c7b88800 c0014da8 c02cdd7c c04ee710 c04ee7b8 00000003 c005fc74 -5ec0: 00000000 7fffffff c7b45f00 c7afa060 c7b67420 c7ba3070 00000004 c0014da8 -5ee0: c7b44000 00000000 bec566ac c02ced88 c04e95f8 b6f5ab04 c7b45fb0 0145a468 -5f00: 0145a600 bec566bc bec56800 c7b67420 c7ba3070 c00d499c c7b45f18 c7b45f18 -5f20: 0000001a 00000004 00000001 c7b44000 c0527f40 00000009 00000008 00000000 -5f40: c7b44000 c002c9ec 00000001 c04f0ab0 c04ebec0 00000101 00000000 0000000a -5f60: 60000093 c7b67420 bec56800 c25c4111 00000004 c0014da8 c7b44000 00000000 -5f80: bec566ac c00d4f38 b6ffb658 00000000 c0522d80 0145a468 b6fd5000 0145a418 -5fa0: 00000036 c0014c00 0145a468 b6fd5000 00000004 c25c4111 bec56800 00020001 -5fc0: 0145a468 b6fd5000 0145a418 00000036 0145a468 0145a600 bec566bc bec566ac -5fe0: 0145a468 bec56388 b6f65ce4 b6dcebec 20000010 00000004 00000000 00000000 -[] (snd_dmaengine_pcm_get_chan+0x8/0x10) from [] (snd_imx_pcm_hw_params+0x18/0xdc) -[] (snd_imx_pcm_hw_params+0x18/0xdc) from [] (soc_pcm_hw_params+0xe8/0x1f0) -[] (soc_pcm_hw_params+0xe8/0x1f0) from [] (snd_pcm_hw_params+0x124/0x474) -[] (snd_pcm_hw_params+0x124/0x474) from [] (snd_pcm_common_ioctl1+0x4b4/0xf74) -[] (snd_pcm_common_ioctl1+0x4b4/0xf74) from [] (snd_pcm_playback_ioctl1+0x30/0x510) -[] (snd_pcm_playback_ioctl1+0x30/0x510) from [] (do_vfs_ioctl+0x80/0x5e4) -[] (do_vfs_ioctl+0x80/0x5e4) from [] (sys_ioctl+0x38/0x60) -[] (sys_ioctl+0x38/0x60) from [] (ret_fast_syscall+0x0/0x2c) -Code: e593000c e12fff1e e59030a0 e59330bc (e5930000) ----[ end trace fa518c8ba3a74e97 ]-- - -Reported-by: Javier Martin -Signed-off-by: Fabio Estevam -Acked-by: Sascha Hauer -Signed-off-by: Vinod Koul -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/dma/imx-dma.c | 36 +++++++++++++++++++++++++----------- - 1 file changed, 25 insertions(+), 11 deletions(-) - ---- a/drivers/dma/imx-dma.c -+++ b/drivers/dma/imx-dma.c -@@ -172,7 +172,8 @@ struct imxdma_engine { - struct device_dma_parameters dma_parms; - struct dma_device dma_device; - void __iomem *base; -- struct clk *dma_clk; -+ struct clk *dma_ahb; -+ struct clk *dma_ipg; - spinlock_t lock; - struct imx_dma_2d_config slots_2d[IMX_DMA_2D_SLOTS]; - struct imxdma_channel channel[IMX_DMA_CHANNELS]; -@@ -976,10 +977,20 @@ static int __init imxdma_probe(struct pl - return 0; - } - -- imxdma->dma_clk = clk_get(NULL, "dma"); -- if (IS_ERR(imxdma->dma_clk)) -- return PTR_ERR(imxdma->dma_clk); -- clk_enable(imxdma->dma_clk); -+ imxdma->dma_ipg = devm_clk_get(&pdev->dev, "ipg"); -+ if (IS_ERR(imxdma->dma_ipg)) { -+ ret = PTR_ERR(imxdma->dma_ipg); -+ goto err_clk; -+ } -+ -+ imxdma->dma_ahb = devm_clk_get(&pdev->dev, "ahb"); -+ if (IS_ERR(imxdma->dma_ahb)) { -+ ret = PTR_ERR(imxdma->dma_ahb); -+ goto err_clk; -+ } -+ -+ clk_prepare_enable(imxdma->dma_ipg); -+ clk_prepare_enable(imxdma->dma_ahb); - - /* reset DMA module */ - imx_dmav1_writel(imxdma, DCR_DRST, DMA_DCR); -@@ -988,16 +999,14 @@ static int __init imxdma_probe(struct pl - ret = request_irq(MX1_DMA_INT, dma_irq_handler, 0, "DMA", imxdma); - if (ret) { - dev_warn(imxdma->dev, "Can't register IRQ for DMA\n"); -- kfree(imxdma); -- return ret; -+ goto err_enable; - } - - ret = request_irq(MX1_DMA_ERR, imxdma_err_handler, 0, "DMA", imxdma); - if (ret) { - dev_warn(imxdma->dev, "Can't register ERRIRQ for DMA\n"); - free_irq(MX1_DMA_INT, NULL); -- kfree(imxdma); -- return ret; -+ goto err_enable; - } - } - -@@ -1094,7 +1103,10 @@ err_init: - free_irq(MX1_DMA_INT, NULL); - free_irq(MX1_DMA_ERR, NULL); - } -- -+err_enable: -+ clk_disable_unprepare(imxdma->dma_ipg); -+ clk_disable_unprepare(imxdma->dma_ahb); -+err_clk: - kfree(imxdma); - return ret; - } -@@ -1114,7 +1126,9 @@ static int __exit imxdma_remove(struct p - free_irq(MX1_DMA_ERR, NULL); - } - -- kfree(imxdma); -+ clk_disable_unprepare(imxdma->dma_ipg); -+ clk_disable_unprepare(imxdma->dma_ahb); -+ kfree(imxdma); - - return 0; - } -From 0d8957c8a90bbb5d34fab9a304459448a5131e06 Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Tue, 7 Aug 2012 09:54:14 +0200 -Subject: drm/i915: correctly order the ring init sequence - -From: Daniel Vetter - -commit 0d8957c8a90bbb5d34fab9a304459448a5131e06 upstream. - -We may only start to set up the new register values after having -confirmed that the ring is truely off. Otherwise the hw might lose the -newly written register values. This is caught later on in the init -sequence, when we check whether the register writes have stuck. - -Reviewed-by: Jani Nikula -Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=50522 -Tested-by: Yang Guang -Signed-off-by: Daniel Vetter -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/intel_ringbuffer.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - ---- a/drivers/gpu/drm/i915/intel_ringbuffer.c -+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c -@@ -258,8 +258,6 @@ static int init_ring_common(struct intel - I915_WRITE_HEAD(ring, 0); - ring->write_tail(ring, 0); - -- /* Initialize the ring. */ -- I915_WRITE_START(ring, obj->gtt_offset); - head = I915_READ_HEAD(ring) & HEAD_ADDR; - - /* G45 ring initialization fails to reset head to zero */ -@@ -285,6 +283,11 @@ static int init_ring_common(struct intel - } - } - -+ /* Initialize the ring. This must happen _after_ we've cleared the ring -+ * registers with the above sequence (the readback of the HEAD registers -+ * also enforces ordering), otherwise the hw might lose the new ring -+ * register values. */ -+ I915_WRITE_START(ring, obj->gtt_offset); - I915_WRITE_CTL(ring, - ((ring->size - PAGE_SIZE) & RING_NR_PAGES) - | RING_VALID); -From 4344b813f105a19f793f1fd93ad775b784648b95 Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Fri, 10 Aug 2012 11:10:20 +0200 -Subject: drm/i915: ignore eDP bpc settings from vbt - -From: Daniel Vetter - -commit 4344b813f105a19f793f1fd93ad775b784648b95 upstream. - -This has originally been introduced to not oversubscribe the dp links -in - -commit 885a5fb5b120a5c7e0b3baad7b0feb5a89f76c18 -Author: Zhenyu Wang -Date: Tue Jan 12 05:38:31 2010 +0800 - - drm/i915: fix pixel color depth setting on eDP - -Since then we've fixed up the dp link bandwidth calculation code and -should now automatically fall back to 6bpc dithering. So this is -unnecessary. - -Furthermore it seems to break the new MacbookPro with retina display, -hence let's just rip this out. - -Reported-by: Benoit Gschwind -Cc: Benoit Gschwind -Cc: Francois Rigaut -Tested-by: Benoit Gschwind -Tested-by: Bernhard Froemel -Signed-off-by: Daniel Vetter -Signed-off-by: Greg Kroah-Hartman - --- - -Testing feedback highgly welcome, and thanks for Benoit for finding -out that the bpc computations are busted. --Daniel - ---- - drivers/gpu/drm/i915/intel_display.c | 11 ----------- - 1 file changed, 11 deletions(-) - ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -4982,17 +4982,6 @@ static bool intel_choose_pipe_bpp_dither - continue; - } - -- if (intel_encoder->type == INTEL_OUTPUT_EDP) { -- /* Use VBT settings if we have an eDP panel */ -- unsigned int edp_bpc = dev_priv->edp.bpp / 3; -- -- if (edp_bpc < display_bpc) { -- DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); -- display_bpc = edp_bpc; -- } -- continue; -- } -- - /* Not one of the known troublemakers, check the EDID */ - list_for_each_entry(connector, &dev->mode_config.connector_list, - head) { -From 2514bc510d0c3aadcc5204056bb440fa36845147 Mon Sep 17 00:00:00 2001 -From: Jesse Barnes -Date: Thu, 21 Jun 2012 15:13:50 -0700 -Subject: drm/i915: prefer wide & slow to fast & narrow in DP configs - -From: Jesse Barnes - -commit 2514bc510d0c3aadcc5204056bb440fa36845147 upstream. - -High frequency link configurations have the potential to cause trouble -with long and/or cheap cables, so prefer slow and wide configurations -instead. This patch has the potential to cause trouble for eDP -configurations that lie about available lanes, so if we run into that we -can make it conditional on eDP. - -Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=45801 -Tested-by: peter@colberg.org -Signed-off-by: Jesse Barnes -Signed-off-by: Daniel Vetter -Cc: Jonathan Nieder -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/intel_dp.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/gpu/drm/i915/intel_dp.c -+++ b/drivers/gpu/drm/i915/intel_dp.c -@@ -712,8 +712,8 @@ intel_dp_mode_fixup(struct drm_encoder * - - bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24; - -- for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { -- for (clock = 0; clock <= max_clock; clock++) { -+ for (clock = 0; clock <= max_clock; clock++) { -+ for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { - int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); - - if (intel_dp_link_required(mode->clock, bpp) -From 35a38556d900b9cb5dfa2529c93944b847f8a8a4 Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Sun, 12 Aug 2012 22:17:14 +0200 -Subject: drm/i915: reorder edp disabling to fix ivb MacBook Air - -From: Daniel Vetter - -commit 35a38556d900b9cb5dfa2529c93944b847f8a8a4 upstream. - -eDP is tons of fun. It turns out that at least the new MacBook Air 5,1 -model absolutely doesn't like the new force vdd dance we've introduced -in - -commit 6cb49835da0426f69a2931bc2a0a8156344b0e41 -Author: Daniel Vetter -Date: Sun May 20 17:14:50 2012 +0200 - - drm/i915: enable vdd when switching off the eDP panel - -But that patch also tried to fix some neat edp sequence issue with the -force_vdd timings. Closer inspection reveals that we've raised -force_vdd only to do the aux channel communication dp_sink_dpms. If we -move the edp_panel_off below that, we don't need any force_vdd for the -disable sequence, which makes the Air happy. - -Unfortunately the reporter of the original bug that the above commit -fixed is travelling, so we can't test whether this regresses things. -But my theory is that since we don't check for any power-off -> -force_vdd-on delays in edp_panel_vdd_on, this was the actual -root-cause of this failure. With that force_vdd dance completely -eliminated, I'm hopeful the original bug stays fixed, too. - -For reference the old bug, which hopefully doesn't get broken by this: - -https://bugzilla.kernel.org/show_bug.cgi?id=43163 - -In any case, regression fixers win over plain bugfixes, so this needs -to go in asap. - -v2: The crucial pieces seems to be to clear the force_vdd flag -uncoditionally, too, in edp_panel_off. Looks like this is left behind -by the firmware somehow. - -v3: The Apple firmware seems to switch off the panel on it's own, hence -we still need to keep force_vdd on, but properly clear it when switching -the panel off. - -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45671 -Tested-by: Roberto Romer -Tested-by: Daniel Wagner -Tested-by: Keith Packard -Cc: Keith Packard -Signed-off-by: Daniel Vetter -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/i915/intel_dp.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - ---- a/drivers/gpu/drm/i915/intel_dp.c -+++ b/drivers/gpu/drm/i915/intel_dp.c -@@ -1156,10 +1156,14 @@ static void ironlake_edp_panel_off(struc - WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n"); - - pp = ironlake_get_pp_control(dev_priv); -- pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE); -+ /* We need to switch off panel power _and_ force vdd, for otherwise some -+ * panels get very unhappy and cease to work. */ -+ pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE); - I915_WRITE(PCH_PP_CONTROL, pp); - POSTING_READ(PCH_PP_CONTROL); - -+ intel_dp->want_panel_vdd = false; -+ - ironlake_wait_panel_off(intel_dp); - } - -@@ -1269,11 +1273,9 @@ static void intel_dp_prepare(struct drm_ - * ensure that we have vdd while we switch off the panel. */ - ironlake_edp_panel_vdd_on(intel_dp); - ironlake_edp_backlight_off(intel_dp); -- ironlake_edp_panel_off(intel_dp); -- - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); -+ ironlake_edp_panel_off(intel_dp); - intel_dp_link_down(intel_dp); -- ironlake_edp_panel_vdd_off(intel_dp, false); - } - - static void intel_dp_commit(struct drm_encoder *encoder) -@@ -1308,11 +1310,9 @@ intel_dp_dpms(struct drm_encoder *encode - /* Switching the panel off requires vdd. */ - ironlake_edp_panel_vdd_on(intel_dp); - ironlake_edp_backlight_off(intel_dp); -- ironlake_edp_panel_off(intel_dp); -- - intel_dp_sink_dpms(intel_dp, mode); -+ ironlake_edp_panel_off(intel_dp); - intel_dp_link_down(intel_dp); -- ironlake_edp_panel_vdd_off(intel_dp, false); - - if (is_cpu_edp(intel_dp)) - ironlake_edp_pll_off(encoder); -From af5e7d84b0ec45b2b614b0d6e3657cbdceaa21f9 Mon Sep 17 00:00:00 2001 -From: Christoph Bumiller -Date: Thu, 26 Jul 2012 20:53:19 +0200 -Subject: drm/nvd0/disp: mask off high 16 bit of negative cursor x-coordinate - -From: Christoph Bumiller - -commit af5e7d84b0ec45b2b614b0d6e3657cbdceaa21f9 upstream. - -Signed-off-by: Christoph Bumiller -Signed-off-by: Ben Skeggs -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/nouveau/nvd0_display.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/gpu/drm/nouveau/nvd0_display.c -+++ b/drivers/gpu/drm/nouveau/nvd0_display.c -@@ -790,7 +790,7 @@ nvd0_crtc_cursor_move(struct drm_crtc *c - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - int ch = EVO_CURS(nv_crtc->index); - -- evo_piow(crtc->dev, ch, 0x0084, (y << 16) | x); -+ evo_piow(crtc->dev, ch, 0x0084, (y << 16) | (x & 0xffff)); - evo_piow(crtc->dev, ch, 0x0080, 0x00000000); - return 0; - } -From 2f292004dd1fb005788dc0a9cdd5559812ed866e Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Mon, 6 Aug 2012 10:03:59 -0400 -Subject: drm/radeon: add some new SI pci ids - -From: Alex Deucher - -commit 2f292004dd1fb005788dc0a9cdd5559812ed866e upstream. - -Signed-off-by: Alex Deucher -Signed-off-by: Greg Kroah-Hartman - ---- - include/drm/drm_pciids.h | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/include/drm/drm_pciids.h -+++ b/include/drm/drm_pciids.h -@@ -217,9 +217,12 @@ - {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6802, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ -+ {0x1002, 0x6806, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ -+ {0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ -+ {0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6819, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ -From 81ee8fb6b52ec69eeed37fe7943446af1dccecc5 Mon Sep 17 00:00:00 2001 -From: Jerome Glisse -Date: Fri, 27 Jul 2012 16:32:24 -0400 -Subject: drm/radeon: do not reenable crtc after moving vram start address - -From: Jerome Glisse - -commit 81ee8fb6b52ec69eeed37fe7943446af1dccecc5 upstream. - -It seems we can not update the crtc scanout address. After disabling -crtc, update to base address do not take effect after crtc being -reenable leading to at least frame being scanout from the old crtc -base address. Disabling crtc display request lead to same behavior. - -So after changing the vram address if we don't keep crtc disabled -we will have the GPU trying to read some random system memory address -with some iommu this will broke the crtc engine and will lead to -broken display and iommu error message. - -So to avoid this, disable crtc. For flicker less boot we will need -to avoid moving the vram start address. - -This patch should also fix : - -https://bugs.freedesktop.org/show_bug.cgi?id=42373 - -Signed-off-by: Jerome Glisse -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/evergreen.c | 57 ----------------------------------- - drivers/gpu/drm/radeon/radeon_asic.h | 8 +--- - drivers/gpu/drm/radeon/rv515.c | 13 ------- - 3 files changed, 2 insertions(+), 76 deletions(-) - ---- a/drivers/gpu/drm/radeon/evergreen.c -+++ b/drivers/gpu/drm/radeon/evergreen.c -@@ -1117,24 +1117,8 @@ void evergreen_agp_enable(struct radeon_ - - void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) - { -- save->vga_control[0] = RREG32(D1VGA_CONTROL); -- save->vga_control[1] = RREG32(D2VGA_CONTROL); - save->vga_render_control = RREG32(VGA_RENDER_CONTROL); - save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); -- save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET); -- save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); -- if (rdev->num_crtc >= 4) { -- save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); -- save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL); -- save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); -- save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); -- } -- if (rdev->num_crtc >= 6) { -- save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); -- save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL); -- save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); -- save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); -- } - - /* Stop all video */ - WREG32(VGA_RENDER_CONTROL, 0); -@@ -1245,47 +1229,6 @@ void evergreen_mc_resume(struct radeon_d - /* Unlock host access */ - WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); - mdelay(1); -- /* Restore video state */ -- WREG32(D1VGA_CONTROL, save->vga_control[0]); -- WREG32(D2VGA_CONTROL, save->vga_control[1]); -- if (rdev->num_crtc >= 4) { -- WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]); -- WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]); -- } -- if (rdev->num_crtc >= 6) { -- WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]); -- WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]); -- } -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); -- if (rdev->num_crtc >= 4) { -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); -- } -- if (rdev->num_crtc >= 6) { -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); -- } -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]); -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]); -- if (rdev->num_crtc >= 4) { -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]); -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]); -- } -- if (rdev->num_crtc >= 6) { -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]); -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]); -- } -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); -- if (rdev->num_crtc >= 4) { -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); -- } -- if (rdev->num_crtc >= 6) { -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); -- } - WREG32(VGA_RENDER_CONTROL, save->vga_render_control); - } - ---- a/drivers/gpu/drm/radeon/radeon_asic.h -+++ b/drivers/gpu/drm/radeon/radeon_asic.h -@@ -262,13 +262,10 @@ extern int rs690_mc_wait_for_idle(struct - * rv515 - */ - struct rv515_mc_save { -- u32 d1vga_control; -- u32 d2vga_control; - u32 vga_render_control; - u32 vga_hdp_control; -- u32 d1crtc_control; -- u32 d2crtc_control; - }; -+ - int rv515_init(struct radeon_device *rdev); - void rv515_fini(struct radeon_device *rdev); - uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg); -@@ -401,11 +398,10 @@ void r700_cp_fini(struct radeon_device * - * evergreen - */ - struct evergreen_mc_save { -- u32 vga_control[6]; - u32 vga_render_control; - u32 vga_hdp_control; -- u32 crtc_control[6]; - }; -+ - void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev); - int evergreen_init(struct radeon_device *rdev); - void evergreen_fini(struct radeon_device *rdev); ---- a/drivers/gpu/drm/radeon/rv515.c -+++ b/drivers/gpu/drm/radeon/rv515.c -@@ -281,12 +281,8 @@ int rv515_debugfs_ga_info_init(struct ra - - void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save) - { -- save->d1vga_control = RREG32(R_000330_D1VGA_CONTROL); -- save->d2vga_control = RREG32(R_000338_D2VGA_CONTROL); - save->vga_render_control = RREG32(R_000300_VGA_RENDER_CONTROL); - save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL); -- save->d1crtc_control = RREG32(R_006080_D1CRTC_CONTROL); -- save->d2crtc_control = RREG32(R_006880_D2CRTC_CONTROL); - - /* Stop all video */ - WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); -@@ -311,15 +307,6 @@ void rv515_mc_resume(struct radeon_devic - /* Unlock host access */ - WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control); - mdelay(1); -- /* Restore video state */ -- WREG32(R_000330_D1VGA_CONTROL, save->d1vga_control); -- WREG32(R_000338_D2VGA_CONTROL, save->d2vga_control); -- WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1); -- WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1); -- WREG32(R_006080_D1CRTC_CONTROL, save->d1crtc_control); -- WREG32(R_006880_D2CRTC_CONTROL, save->d2crtc_control); -- WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0); -- WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); - WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control); - } - -From 5b23c9045a8b61352986270b2d109edf5085e113 Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Tue, 31 Jul 2012 11:05:11 -0400 -Subject: drm/radeon: fix bank tiling parameters on cayman - -From: Alex Deucher - -commit 5b23c9045a8b61352986270b2d109edf5085e113 upstream. - -Handle the 16 bank case. - -Signed-off-by: Alex Deucher -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/ni.c | 14 +++++++++++--- - 1 file changed, 11 insertions(+), 3 deletions(-) - ---- a/drivers/gpu/drm/radeon/ni.c -+++ b/drivers/gpu/drm/radeon/ni.c -@@ -880,10 +880,18 @@ static void cayman_gpu_init(struct radeo - if (rdev->flags & RADEON_IS_IGP) - rdev->config.cayman.tile_config |= 1 << 4; - else { -- if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) -- rdev->config.cayman.tile_config |= 1 << 4; -- else -+ switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { -+ case 0: /* four banks */ - rdev->config.cayman.tile_config |= 0 << 4; -+ break; -+ case 1: /* eight banks */ -+ rdev->config.cayman.tile_config |= 1 << 4; -+ break; -+ case 2: /* sixteen banks */ -+ default: -+ rdev->config.cayman.tile_config |= 2 << 4; -+ break; -+ } - } - rdev->config.cayman.tile_config |= - ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; -From c8d15edc17d836686d1f071e564800e1a2724fa6 Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Tue, 31 Jul 2012 11:01:10 -0400 -Subject: drm/radeon: fix bank tiling parameters on evergreen - -From: Alex Deucher - -commit c8d15edc17d836686d1f071e564800e1a2724fa6 upstream. - -Handle the 16 bank case. - -Signed-off-by: Alex Deucher -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/evergreen.c | 14 +++++++++++--- - 1 file changed, 11 insertions(+), 3 deletions(-) - ---- a/drivers/gpu/drm/radeon/evergreen.c -+++ b/drivers/gpu/drm/radeon/evergreen.c -@@ -2085,10 +2085,18 @@ static void evergreen_gpu_init(struct ra - if (rdev->flags & RADEON_IS_IGP) - rdev->config.evergreen.tile_config |= 1 << 4; - else { -- if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) -- rdev->config.evergreen.tile_config |= 1 << 4; -- else -+ switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { -+ case 0: /* four banks */ - rdev->config.evergreen.tile_config |= 0 << 4; -+ break; -+ case 1: /* eight banks */ -+ rdev->config.evergreen.tile_config |= 1 << 4; -+ break; -+ case 2: /* sixteen banks */ -+ default: -+ rdev->config.evergreen.tile_config |= 2 << 4; -+ break; -+ } - } - rdev->config.evergreen.tile_config |= - ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) << 8; -From 6c0ae2ab85fc4a95cae82047a7db1f688a7737ab Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Thu, 26 Jul 2012 13:38:52 -0400 -Subject: drm/radeon: properly handle crtc powergating - -From: Alex Deucher - -commit 6c0ae2ab85fc4a95cae82047a7db1f688a7737ab upstream. - -Need to make sure the crtc is gated on before modesetting. -Explicitly gate the crtc on in prepare() and set a flag -so that the dpms functions don't gate it off during -mode set. - -Noticed by sylware on IRC. - -Signed-off-by: Alex Deucher -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/atombios_crtc.c | 14 ++++++++++++-- - drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 4 ++++ - drivers/gpu/drm/radeon/radeon_mode.h | 1 + - 3 files changed, 17 insertions(+), 2 deletions(-) - ---- a/drivers/gpu/drm/radeon/atombios_crtc.c -+++ b/drivers/gpu/drm/radeon/atombios_crtc.c -@@ -259,7 +259,7 @@ void atombios_crtc_dpms(struct drm_crtc - /* adjust pm to dpms changes BEFORE enabling crtcs */ - radeon_pm_compute_clocks(rdev); - /* disable crtc pair power gating before programming */ -- if (ASIC_IS_DCE6(rdev)) -+ if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) - atombios_powergate_crtc(crtc, ATOM_DISABLE); - atombios_enable_crtc(crtc, ATOM_ENABLE); - if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) -@@ -279,7 +279,7 @@ void atombios_crtc_dpms(struct drm_crtc - atombios_enable_crtc(crtc, ATOM_DISABLE); - radeon_crtc->enabled = false; - /* power gating is per-pair */ -- if (ASIC_IS_DCE6(rdev)) { -+ if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) { - struct drm_crtc *other_crtc; - struct radeon_crtc *other_radeon_crtc; - list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) { -@@ -1634,18 +1634,28 @@ static bool atombios_crtc_mode_fixup(str - static void atombios_crtc_prepare(struct drm_crtc *crtc) - { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); -+ struct drm_device *dev = crtc->dev; -+ struct radeon_device *rdev = dev->dev_private; - -+ radeon_crtc->in_mode_set = true; - /* pick pll */ - radeon_crtc->pll_id = radeon_atom_pick_pll(crtc); - -+ /* disable crtc pair power gating before programming */ -+ if (ASIC_IS_DCE6(rdev)) -+ atombios_powergate_crtc(crtc, ATOM_DISABLE); -+ - atombios_lock_crtc(crtc, ATOM_ENABLE); - atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); - } - - static void atombios_crtc_commit(struct drm_crtc *crtc) - { -+ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); -+ - atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON); - atombios_lock_crtc(crtc, ATOM_DISABLE); -+ radeon_crtc->in_mode_set = false; - } - - static void atombios_crtc_disable(struct drm_crtc *crtc) ---- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c -+++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c -@@ -1025,9 +1025,11 @@ static int radeon_crtc_mode_set(struct d - - static void radeon_crtc_prepare(struct drm_crtc *crtc) - { -+ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - struct drm_device *dev = crtc->dev; - struct drm_crtc *crtci; - -+ radeon_crtc->in_mode_set = true; - /* - * The hardware wedges sometimes if you reconfigure one CRTC - * whilst another is running (see fdo bug #24611). -@@ -1038,6 +1040,7 @@ static void radeon_crtc_prepare(struct d - - static void radeon_crtc_commit(struct drm_crtc *crtc) - { -+ struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - struct drm_device *dev = crtc->dev; - struct drm_crtc *crtci; - -@@ -1048,6 +1051,7 @@ static void radeon_crtc_commit(struct dr - if (crtci->enabled) - radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON); - } -+ radeon_crtc->in_mode_set = false; - } - - static const struct drm_crtc_helper_funcs legacy_helper_funcs = { ---- a/drivers/gpu/drm/radeon/radeon_mode.h -+++ b/drivers/gpu/drm/radeon/radeon_mode.h -@@ -266,6 +266,7 @@ struct radeon_crtc { - u16 lut_r[256], lut_g[256], lut_b[256]; - bool enabled; - bool can_tile; -+ bool in_mode_set; - uint32_t crtc_offset; - struct drm_gem_object *cursor_bo; - uint64_t cursor_addr; -From 7e731bc9a12339f344cddf82166b82633d99dd86 Mon Sep 17 00:00:00 2001 -From: Theodore Ts'o -Date: Sun, 5 Aug 2012 23:28:16 -0400 -Subject: ext4: avoid kmemcheck complaint from reading uninitialized memory - -From: Theodore Ts'o - -commit 7e731bc9a12339f344cddf82166b82633d99dd86 upstream. - -Commit 03179fe923 introduced a kmemcheck complaint in -ext4_da_get_block_prep() because we save and restore -ei->i_da_metadata_calc_last_lblock even though it is left -uninitialized in the case where i_da_metadata_calc_len is zero. - -This doesn't hurt anything, but silencing the kmemcheck complaint -makes it easier for people to find real bugs. - -Addresses https://bugzilla.kernel.org/show_bug.cgi?id=45631 -(which is marked as a regression). - -Signed-off-by: "Theodore Ts'o" -Signed-off-by: Greg Kroah-Hartman - ---- - fs/ext4/super.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -932,6 +932,7 @@ static struct inode *ext4_alloc_inode(st - ei->i_reserved_meta_blocks = 0; - ei->i_allocated_meta_blocks = 0; - ei->i_da_metadata_calc_len = 0; -+ ei->i_da_metadata_calc_last_lblock = 0; - spin_lock_init(&(ei->i_block_reservation_lock)); - #ifdef CONFIG_QUOTA - ei->i_reserved_quota = 0; -From 89a4e48f8479f8145eca9698f39fe188c982212f Mon Sep 17 00:00:00 2001 -From: Theodore Ts'o -Date: Fri, 17 Aug 2012 08:54:52 -0400 -Subject: ext4: fix kernel BUG on large-scale rm -rf commands -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -From: Theodore Ts'o - -commit 89a4e48f8479f8145eca9698f39fe188c982212f upstream. - -Commit 968dee7722: "ext4: fix hole punch failure when depth is greater -than 0" introduced a regression in v3.5.1/v3.6-rc1 which caused kernel -crashes when users ran run "rm -rf" on large directory hierarchy on -ext4 filesystems on RAID devices: - - BUG: unable to handle kernel NULL pointer dereference at 0000000000000028 - - Process rm (pid: 18229, threadinfo ffff8801276bc000, task ffff880123631710) - Call Trace: - [] ? __ext4_handle_dirty_metadata+0x83/0x110 - [] ext4_ext_truncate+0x193/0x1d0 - [] ? ext4_mark_inode_dirty+0x7f/0x1f0 - [] ext4_truncate+0xf5/0x100 - [] ext4_evict_inode+0x461/0x490 - [] evict+0xa2/0x1a0 - [] iput+0x103/0x1f0 - [] do_unlinkat+0x154/0x1c0 - [] ? sys_newfstatat+0x2a/0x40 - [] sys_unlinkat+0x1b/0x50 - [] system_call_fastpath+0x16/0x1b - Code: 8b 4d 20 0f b7 41 02 48 8d 04 40 48 8d 04 81 49 89 45 18 0f b7 49 02 48 83 c1 01 49 89 4d 00 e9 ae f8 ff ff 0f 1f 00 49 8b 45 28 <48> 8b 40 28 49 89 45 20 e9 85 f8 ff ff 0f 1f 80 00 00 00 - - RIP [] ext4_ext_remove_space+0xa34/0xdf0 - -This could be reproduced as follows: - -The problem in commit 968dee7722 was that caused the variable 'i' to -be left uninitialized if the truncate required more space than was -available in the journal. This resulted in the function -ext4_ext_truncate_extend_restart() returning -EAGAIN, which caused -ext4_ext_remove_space() to restart the truncate operation after -starting a new jbd2 handle. - -Reported-by: Maciej Żenczykowski -Reported-by: Marti Raudsepp -Tested-by: Fengguang Wu -Signed-off-by: "Theodore Ts'o" -Signed-off-by: Greg Kroah-Hartman - ---- - fs/ext4/extents.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -2596,6 +2596,7 @@ cont: - } - path[0].p_depth = depth; - path[0].p_hdr = ext_inode_hdr(inode); -+ i = 0; - - if (ext4_ext_check(inode, path[0].p_hdr, depth)) { - err = -EIO; -From 0548bbb85337e532ca2ed697c3e9b227ff2ed4b4 Mon Sep 17 00:00:00 2001 -From: Theodore Ts'o -Date: Thu, 16 Aug 2012 11:59:04 -0400 -Subject: ext4: fix long mount times on very big file systems - -From: Theodore Ts'o - -commit 0548bbb85337e532ca2ed697c3e9b227ff2ed4b4 upstream. - -Commit 8aeb00ff85a: "ext4: fix overhead calculation used by -ext4_statfs()" introduced a O(n**2) calculation which makes very large -file systems take forever to mount. Fix this with an optimization for -non-bigalloc file systems. (For bigalloc file systems the overhead -needs to be set in the the superblock.) - -Signed-off-by: "Theodore Ts'o" -Signed-off-by: Greg Kroah-Hartman - ---- - fs/ext4/super.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -2969,6 +2969,10 @@ static int count_overhead(struct super_b - ext4_group_t i, ngroups = ext4_get_groups_count(sb); - int s, j, count = 0; - -+ if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC)) -+ return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) + -+ sbi->s_itb_per_group + 2); -+ - first_block = le32_to_cpu(sbi->s_es->s_first_data_block) + - (grp * EXT4_BLOCKS_PER_GROUP(sb)); - last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1; -From d796c52ef0b71a988364f6109aeb63d79c5b116b Mon Sep 17 00:00:00 2001 -From: Theodore Ts'o -Date: Sun, 5 Aug 2012 19:04:57 -0400 -Subject: ext4: make sure the journal sb is written in ext4_clear_journal_err() - -From: Theodore Ts'o - -commit d796c52ef0b71a988364f6109aeb63d79c5b116b upstream. - -After we transfer set the EXT4_ERROR_FS bit in the file system -superblock, it's not enough to call jbd2_journal_clear_err() to clear -the error indication from journal superblock --- we need to call -jbd2_journal_update_sb_errno() as well. Otherwise, when the root file -system is mounted read-only, the journal is replayed, and the error -indicator is transferred to the superblock --- but the s_errno field -in the jbd2 superblock is left set (since although we cleared it in -memory, we never flushed it out to disk). - -This can end up confusing e2fsck. We should make e2fsck more robust -in this case, but the kernel shouldn't be leaving things in this -confused state, either. - -Signed-off-by: "Theodore Ts'o" -Signed-off-by: Greg Kroah-Hartman - ---- - fs/ext4/super.c | 1 + - fs/jbd2/journal.c | 3 ++- - include/linux/jbd2.h | 1 + - 3 files changed, 4 insertions(+), 1 deletion(-) - ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -4227,6 +4227,7 @@ static void ext4_clear_journal_err(struc - ext4_commit_super(sb, 1); - - jbd2_journal_clear_err(journal); -+ jbd2_journal_update_sb_errno(journal); - } - } - ---- a/fs/jbd2/journal.c -+++ b/fs/jbd2/journal.c -@@ -1340,7 +1340,7 @@ static void jbd2_mark_journal_empty(jour - * Update a journal's errno. Write updated superblock to disk waiting for IO - * to complete. - */ --static void jbd2_journal_update_sb_errno(journal_t *journal) -+void jbd2_journal_update_sb_errno(journal_t *journal) - { - journal_superblock_t *sb = journal->j_superblock; - -@@ -1352,6 +1352,7 @@ static void jbd2_journal_update_sb_errno - - jbd2_write_superblock(journal, WRITE_SYNC); - } -+EXPORT_SYMBOL(jbd2_journal_update_sb_errno); - - /* - * Read the superblock for a given journal, performing initial ---- a/include/linux/jbd2.h -+++ b/include/linux/jbd2.h -@@ -1091,6 +1091,7 @@ extern int jbd2_journal_destroy (j - extern int jbd2_journal_recover (journal_t *journal); - extern int jbd2_journal_wipe (journal_t *, int); - extern int jbd2_journal_skip_recovery (journal_t *); -+extern void jbd2_journal_update_sb_errno(journal_t *); - extern void jbd2_journal_update_sb_log_tail (journal_t *, tid_t, - unsigned long, int); - extern void __jbd2_journal_abort_hard (journal_t *); -From fb6ccff667712c46b4501b920ea73a326e49626a Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Tue, 24 Jul 2012 12:10:11 -0700 -Subject: fuse: verify all ioctl retry iov elements - -From: Zach Brown - -commit fb6ccff667712c46b4501b920ea73a326e49626a upstream. - -Commit 7572777eef78ebdee1ecb7c258c0ef94d35bad16 attempted to verify that -the total iovec from the client doesn't overflow iov_length() but it -only checked the first element. The iovec could still overflow by -starting with a small element. The obvious fix is to check all the -elements. - -The overflow case doesn't look dangerous to the kernel as the copy is -limited by the length after the overflow. This fix restores the -intention of returning an error instead of successfully copying less -than the iovec represented. - -I found this by code inspection. I built it but don't have a test case. -I'm cc:ing stable because the initial commit did as well. - -Signed-off-by: Zach Brown -Signed-off-by: Miklos Szeredi -Signed-off-by: Greg Kroah-Hartman - ---- - fs/fuse/file.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/fs/fuse/file.c -+++ b/fs/fuse/file.c -@@ -1698,7 +1698,7 @@ static int fuse_verify_ioctl_iov(struct - size_t n; - u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT; - -- for (n = 0; n < count; n++) { -+ for (n = 0; n < count; n++, iov++) { - if (iov->iov_len > (size_t) max) - return -ENOMEM; - max -= iov->iov_len; -From 220329916c72ee3d54ae7262b215a050f04a18fc Mon Sep 17 00:00:00 2001 -From: Bart Van Assche -Date: Tue, 14 Aug 2012 13:18:53 +0000 -Subject: IB/srp: Fix a race condition - -From: Bart Van Assche - -commit 220329916c72ee3d54ae7262b215a050f04a18fc upstream. - -Avoid a crash caused by the scmnd->scsi_done(scmnd) call in -srp_process_rsp() being invoked with scsi_done == NULL. This can -happen if a reply is received during or after a command abort. - -Reported-by: Joseph Glanville -Reference: http://marc.info/?l=linux-rdma&m=134314367801595 -Acked-by: David Dillow -Signed-off-by: Bart Van Assche -Signed-off-by: Roland Dreier -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/infiniband/ulp/srp/ib_srp.c | 87 ++++++++++++++++++++++++++---------- - 1 file changed, 63 insertions(+), 24 deletions(-) - ---- a/drivers/infiniband/ulp/srp/ib_srp.c -+++ b/drivers/infiniband/ulp/srp/ib_srp.c -@@ -586,24 +586,62 @@ static void srp_unmap_data(struct scsi_c - scmnd->sc_data_direction); - } - --static void srp_remove_req(struct srp_target_port *target, -- struct srp_request *req, s32 req_lim_delta) -+/** -+ * srp_claim_req - Take ownership of the scmnd associated with a request. -+ * @target: SRP target port. -+ * @req: SRP request. -+ * @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take -+ * ownership of @req->scmnd if it equals @scmnd. -+ * -+ * Return value: -+ * Either NULL or a pointer to the SCSI command the caller became owner of. -+ */ -+static struct scsi_cmnd *srp_claim_req(struct srp_target_port *target, -+ struct srp_request *req, -+ struct scsi_cmnd *scmnd) - { - unsigned long flags; - -- srp_unmap_data(req->scmnd, target, req); -+ spin_lock_irqsave(&target->lock, flags); -+ if (!scmnd) { -+ scmnd = req->scmnd; -+ req->scmnd = NULL; -+ } else if (req->scmnd == scmnd) { -+ req->scmnd = NULL; -+ } else { -+ scmnd = NULL; -+ } -+ spin_unlock_irqrestore(&target->lock, flags); -+ -+ return scmnd; -+} -+ -+/** -+ * srp_free_req() - Unmap data and add request to the free request list. -+ */ -+static void srp_free_req(struct srp_target_port *target, -+ struct srp_request *req, struct scsi_cmnd *scmnd, -+ s32 req_lim_delta) -+{ -+ unsigned long flags; -+ -+ srp_unmap_data(scmnd, target, req); -+ - spin_lock_irqsave(&target->lock, flags); - target->req_lim += req_lim_delta; -- req->scmnd = NULL; - list_add_tail(&req->list, &target->free_reqs); - spin_unlock_irqrestore(&target->lock, flags); - } - - static void srp_reset_req(struct srp_target_port *target, struct srp_request *req) - { -- req->scmnd->result = DID_RESET << 16; -- req->scmnd->scsi_done(req->scmnd); -- srp_remove_req(target, req, 0); -+ struct scsi_cmnd *scmnd = srp_claim_req(target, req, NULL); -+ -+ if (scmnd) { -+ scmnd->result = DID_RESET << 16; -+ scmnd->scsi_done(scmnd); -+ srp_free_req(target, req, scmnd, 0); -+ } - } - - static int srp_reconnect_target(struct srp_target_port *target) -@@ -1073,11 +1111,18 @@ static void srp_process_rsp(struct srp_t - complete(&target->tsk_mgmt_done); - } else { - req = &target->req_ring[rsp->tag]; -- scmnd = req->scmnd; -- if (!scmnd) -+ scmnd = srp_claim_req(target, req, NULL); -+ if (!scmnd) { - shost_printk(KERN_ERR, target->scsi_host, - "Null scmnd for RSP w/tag %016llx\n", - (unsigned long long) rsp->tag); -+ -+ spin_lock_irqsave(&target->lock, flags); -+ target->req_lim += be32_to_cpu(rsp->req_lim_delta); -+ spin_unlock_irqrestore(&target->lock, flags); -+ -+ return; -+ } - scmnd->result = rsp->status; - - if (rsp->flags & SRP_RSP_FLAG_SNSVALID) { -@@ -1092,7 +1137,9 @@ static void srp_process_rsp(struct srp_t - else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER)) - scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt)); - -- srp_remove_req(target, req, be32_to_cpu(rsp->req_lim_delta)); -+ srp_free_req(target, req, scmnd, -+ be32_to_cpu(rsp->req_lim_delta)); -+ - scmnd->host_scribble = NULL; - scmnd->scsi_done(scmnd); - } -@@ -1631,25 +1678,17 @@ static int srp_abort(struct scsi_cmnd *s - { - struct srp_target_port *target = host_to_target(scmnd->device->host); - struct srp_request *req = (struct srp_request *) scmnd->host_scribble; -- int ret = SUCCESS; - - shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n"); - -- if (!req || target->qp_in_error) -- return FAILED; -- if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, -- SRP_TSK_ABORT_TASK)) -+ if (!req || target->qp_in_error || !srp_claim_req(target, req, scmnd)) - return FAILED; -+ srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, -+ SRP_TSK_ABORT_TASK); -+ srp_free_req(target, req, scmnd, 0); -+ scmnd->result = DID_ABORT << 16; - -- if (req->scmnd) { -- if (!target->tsk_mgmt_status) { -- srp_remove_req(target, req, 0); -- scmnd->result = DID_ABORT << 16; -- } else -- ret = FAILED; -- } -- -- return ret; -+ return SUCCESS; - } - - static int srp_reset_device(struct scsi_cmnd *scmnd) -From 38f8eefccf3a23c4058a570fa2938a4f553cf8e0 Mon Sep 17 00:00:00 2001 -From: Jason Wessel -Date: Sun, 12 Aug 2012 07:16:43 -0500 -Subject: pmac_zilog,kdb: Fix console poll hook to return instead of loop - -From: Jason Wessel - -commit 38f8eefccf3a23c4058a570fa2938a4f553cf8e0 upstream. - -kdb <-> kgdb transitioning does not work properly with this UART -driver because the get character routine loops indefinitely as opposed -to returning NO_POLL_CHAR per the expectation of the KDB I/O driver -API. - -The symptom is a kernel hang when trying to switch debug modes. - -Signed-off-by: Jason Wessel -Cc: Alan Cox -Signed-off-by: Greg Kroah-Hartman -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/tty/serial/pmac_zilog.c | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - ---- a/drivers/tty/serial/pmac_zilog.c -+++ b/drivers/tty/serial/pmac_zilog.c -@@ -1348,10 +1348,16 @@ static int pmz_verify_port(struct uart_p - static int pmz_poll_get_char(struct uart_port *port) - { - struct uart_pmac_port *uap = (struct uart_pmac_port *)port; -+ int tries = 2; - -- while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) -- udelay(5); -- return read_zsdata(uap); -+ while (tries) { -+ if ((read_zsreg(uap, R0) & Rx_CH_AV) != 0) -+ return read_zsdata(uap); -+ if (tries--) -+ udelay(5); -+ } -+ -+ return NO_POLL_CHAR; - } - - static void pmz_poll_put_char(struct uart_port *port, unsigned char c) -From a769f9577232afe2c754606a83aad85127e7052a Mon Sep 17 00:00:00 2001 -From: Jeongdo Son -Date: Fri, 15 Jun 2012 02:28:01 +0900 -Subject: rt2x00: Add support for BUFFALO WLI-UC-GNM2 to rt2800usb. - -From: Jeongdo Son - -commit a769f9577232afe2c754606a83aad85127e7052a upstream. - -This is a RT3070 based device. - -Signed-off-by: Jeongdo Son -Signed-off-by: John W. Linville -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/net/wireless/rt2x00/rt2800usb.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/net/wireless/rt2x00/rt2800usb.c -+++ b/drivers/net/wireless/rt2x00/rt2800usb.c -@@ -971,6 +971,7 @@ static struct usb_device_id rt2800usb_de - { USB_DEVICE(0x0411, 0x015d) }, - { USB_DEVICE(0x0411, 0x016f) }, - { USB_DEVICE(0x0411, 0x01a2) }, -+ { USB_DEVICE(0x0411, 0x01ee) }, - /* Corega */ - { USB_DEVICE(0x07aa, 0x002f) }, - { USB_DEVICE(0x07aa, 0x003c) }, -From 82aabdb6f1eb61e0034ec23901480f5dd23db7c4 Mon Sep 17 00:00:00 2001 -From: Heiko Carstens -Date: Tue, 7 Aug 2012 09:48:13 +0200 -Subject: s390/compat: fix compat wrappers for process_vm system calls - -From: Heiko Carstens - -commit 82aabdb6f1eb61e0034ec23901480f5dd23db7c4 upstream. - -The compat wrappers incorrectly called the non compat versions of -the system process_vm system calls. - -Signed-off-by: Heiko Carstens -Signed-off-by: Martin Schwidefsky -Signed-off-by: Greg Kroah-Hartman - ---- - arch/s390/kernel/compat_wrapper.S | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/s390/kernel/compat_wrapper.S -+++ b/arch/s390/kernel/compat_wrapper.S -@@ -1636,7 +1636,7 @@ ENTRY(compat_sys_process_vm_readv_wrappe - llgfr %r6,%r6 # unsigned long - llgf %r0,164(%r15) # unsigned long - stg %r0,160(%r15) -- jg sys_process_vm_readv -+ jg compat_sys_process_vm_readv - - ENTRY(compat_sys_process_vm_writev_wrapper) - lgfr %r2,%r2 # compat_pid_t -@@ -1646,4 +1646,4 @@ ENTRY(compat_sys_process_vm_writev_wrapp - llgfr %r6,%r6 # unsigned long - llgf %r0,164(%r15) # unsigned long - stg %r0,160(%r15) -- jg sys_process_vm_writev -+ jg compat_sys_process_vm_writev -From e85871218513c54f7dfdb6009043cb638f2fecbe Mon Sep 17 00:00:00 2001 -From: Heiko Carstens -Date: Wed, 8 Aug 2012 09:32:20 +0200 -Subject: s390/compat: fix mmap compat system calls - -From: Heiko Carstens - -commit e85871218513c54f7dfdb6009043cb638f2fecbe upstream. - -The native 31 bit and the compat behaviour for the mmap system calls differ: - -In native 31 bit mode the passed in address for the mmap system call will be -unmodified passed to sys_mmap_pgoff(). -In compat mode however the passed in address will be modified with -compat_ptr() which masks out the most significant bit. - -The result is that in native 31 bit mode each mmap request (with MAP_FIXED) -will fail where the most significat bit is set, while in compat mode it -may succeed. - -This odd behaviour was introduced with d3815898 "[S390] mmap: add missing -compat_ptr conversion to both mmap compat syscalls". - -To restore a consistent behaviour accross native and compat mode this -patch functionally reverts the above mentioned commit. - -Signed-off-by: Heiko Carstens -Signed-off-by: Martin Schwidefsky -Signed-off-by: Greg Kroah-Hartman - ---- - arch/s390/kernel/compat_linux.c | 2 -- - 1 file changed, 2 deletions(-) - ---- a/arch/s390/kernel/compat_linux.c -+++ b/arch/s390/kernel/compat_linux.c -@@ -612,7 +612,6 @@ asmlinkage unsigned long old32_mmap(stru - return -EFAULT; - if (a.offset & ~PAGE_MASK) - return -EINVAL; -- a.addr = (unsigned long) compat_ptr(a.addr); - return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, - a.offset >> PAGE_SHIFT); - } -@@ -623,7 +622,6 @@ asmlinkage long sys32_mmap2(struct mmap_ - - if (copy_from_user(&a, arg, sizeof(a))) - return -EFAULT; -- a.addr = (unsigned long) compat_ptr(a.addr); - return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); - } - -From d81a5d1956731c453b85c141458d4ff5d6cc5366 Mon Sep 17 00:00:00 2001 -From: Gustavo Padovan -Date: Tue, 10 Jul 2012 19:10:06 -0300 -Subject: USB: add USB_VENDOR_AND_INTERFACE_INFO() macro - -From: Gustavo Padovan - -commit d81a5d1956731c453b85c141458d4ff5d6cc5366 upstream. - -A lot of Broadcom Bluetooth devices provides vendor specific interface -class and we are getting flooded by patches adding new device support. -This change will help us enable support for any other Broadcom with vendor -specific device that arrives in the future. - -Only the product id changes for those devices, so this macro would be -perfect for us: - -{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) } - -Signed-off-by: Marcel Holtmann -Signed-off-by: Gustavo Padovan -Acked-by: Henrik Rydberg -Signed-off-by: Greg Kroah-Hartman - ---- - include/linux/usb.h | 21 +++++++++++++++++++++ - 1 file changed, 21 insertions(+) - ---- a/include/linux/usb.h -+++ b/include/linux/usb.h -@@ -783,6 +783,27 @@ static inline int usb_make_path(struct u - .bInterfaceSubClass = (sc), \ - .bInterfaceProtocol = (pr) - -+/** -+ * USB_VENDOR_AND_INTERFACE_INFO - describe a specific usb vendor with a class of usb interfaces -+ * @vend: the 16 bit USB Vendor ID -+ * @cl: bInterfaceClass value -+ * @sc: bInterfaceSubClass value -+ * @pr: bInterfaceProtocol value -+ * -+ * This macro is used to create a struct usb_device_id that matches a -+ * specific vendor with a specific class of interfaces. -+ * -+ * This is especially useful when explicitly matching devices that have -+ * vendor specific bDeviceClass values, but standards-compliant interfaces. -+ */ -+#define USB_VENDOR_AND_INTERFACE_INFO(vend, cl, sc, pr) \ -+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \ -+ | USB_DEVICE_ID_MATCH_VENDOR, \ -+ .idVendor = (vend), \ -+ .bInterfaceClass = (cl), \ -+ .bInterfaceSubClass = (sc), \ -+ .bInterfaceProtocol = (pr) -+ - /* ----------------------------------------------------------------------- */ - - /* Stuff for dynamic usb ids */ -From 7724a1edbe463b06d4e7831a41149ba095b16c53 Mon Sep 17 00:00:00 2001 -From: Ozan Çağlayan -Date: Fri, 10 Aug 2012 17:25:10 +0300 -Subject: USB: ftdi_sio: Add VID/PID for Kondo Serial USB - -From: Ozan Çağlayan - -commit 7724a1edbe463b06d4e7831a41149ba095b16c53 upstream. - -This adds VID/PID for Kondo Kagaku Co. Ltd. Serial USB Adapter -interface: -http://www.kondo-robot.com/EN/wp/?cat=28 - -Tested by controlling an RCB3 board using libRCB3. - -Signed-off-by: Ozan Çağlayan -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/serial/ftdi_sio.c | 1 + - drivers/usb/serial/ftdi_sio_ids.h | 7 +++++++ - 2 files changed, 8 insertions(+) - ---- a/drivers/usb/serial/ftdi_sio.c -+++ b/drivers/usb/serial/ftdi_sio.c -@@ -811,6 +811,7 @@ static struct usb_device_id id_table_com - { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) }, - { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) }, - { USB_DEVICE(PI_VID, PI_E861_PID) }, -+ { USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) }, - { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, - { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), - .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, ---- a/drivers/usb/serial/ftdi_sio_ids.h -+++ b/drivers/usb/serial/ftdi_sio_ids.h -@@ -795,6 +795,13 @@ - #define PI_E861_PID 0x1008 /* E-861 piezo controller USB connection */ - - /* -+ * Kondo Kagaku Co.Ltd. -+ * http://www.kondo-robot.com/EN -+ */ -+#define KONDO_VID 0x165c -+#define KONDO_USB_SERIAL_PID 0x0002 -+ -+/* - * Bayer Ascensia Contour blood glucose meter USB-converter cable. - * http://winglucofacts.com/cables/ - */ -From b1b552a69b8805e7e338074a9e8b670b4a795218 Mon Sep 17 00:00:00 2001 -From: Michael Grzeschik -Date: Wed, 8 Aug 2012 11:48:10 +0200 -Subject: usb: gadget: u_ether: fix kworker 100% CPU issue with still used interfaces in eth_stop - -From: Michael Grzeschik - -commit b1b552a69b8805e7e338074a9e8b670b4a795218 upstream. - -This patch fixes an issue introduced by patch: - - 72c973d usb: gadget: add usb_endpoint_descriptor to struct usb_ep - -Without this patch we see a kworker taking 100% CPU, after this sequence: - -- Connect gadget to a windows host -- load g_ether -- ifconfig up ; ifconfig down; ifconfig up -- ping - -The "ifconfig down" results in calling eth_stop(), which will call -usb_ep_disable() and, if the carrier is still ok, usb_ep_enable(): - - usb_ep_disable(link->in_ep); - usb_ep_disable(link->out_ep); - if (netif_carrier_ok(net)) { - usb_ep_enable(link->in_ep); - usb_ep_enable(link->out_ep); - } - -The ep should stay enabled, but will not, as ep_disable set the desc -pointer to NULL, therefore the subsequent ep_enable will fail. This leads -to permanent rescheduling of the eth_work() worker as usb_ep_queue() -(called by the worker) will fail due to the unconfigured endpoint. - -We fix this issue by saving the ep descriptors and re-assign them before -usb_ep_enable(). - -Cc: Tatyana Brokhman -Signed-off-by: Michael Grzeschik -Signed-off-by: Marc Kleine-Budde -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/gadget/u_ether.c | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/drivers/usb/gadget/u_ether.c -+++ b/drivers/usb/gadget/u_ether.c -@@ -669,6 +669,8 @@ static int eth_stop(struct net_device *n - spin_lock_irqsave(&dev->lock, flags); - if (dev->port_usb) { - struct gether *link = dev->port_usb; -+ const struct usb_endpoint_descriptor *in; -+ const struct usb_endpoint_descriptor *out; - - if (link->close) - link->close(link); -@@ -682,10 +684,14 @@ static int eth_stop(struct net_device *n - * their own pace; the network stack can handle old packets. - * For the moment we leave this here, since it works. - */ -+ in = link->in_ep->desc; -+ out = link->out_ep->desc; - usb_ep_disable(link->in_ep); - usb_ep_disable(link->out_ep); - if (netif_carrier_ok(net)) { - DBG(dev, "host still using in/out endpoints\n"); -+ link->in_ep->desc = in; -+ link->out_ep->desc = out; - usb_ep_enable(link->in_ep); - usb_ep_enable(link->out_ep); - } -From f1b5c997e68533df1f96dcd3068a231bca495603 Mon Sep 17 00:00:00 2001 -From: Bjørn Mork -Date: Wed, 15 Aug 2012 15:43:33 +0200 -Subject: USB: option: add ZTE K5006-Z - -From: Bjørn Mork - -commit f1b5c997e68533df1f96dcd3068a231bca495603 upstream. - -The ZTE (Vodafone) K5006-Z use the following -interface layout: - -00 DIAG -01 secondary -02 modem -03 networkcard -04 storage - -Ignoring interface #3 which is handled by the qmi_wwan -driver. - -Signed-off-by: Bjørn Mork -Cc: Thomas Schäfer -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/serial/option.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/usb/serial/option.c -+++ b/drivers/usb/serial/option.c -@@ -886,6 +886,8 @@ static const struct usb_device_id option - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff), -+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) }, -From 5c263b92f828af6a8cf54041db45ceae5af8f2ab Mon Sep 17 00:00:00 2001 -From: Mark Ferrell -Date: Tue, 24 Jul 2012 14:15:13 -0500 -Subject: usb: serial: mos7840: Fixup mos7840_chars_in_buffer() - -From: Mark Ferrell - -commit 5c263b92f828af6a8cf54041db45ceae5af8f2ab upstream. - - * Use the buffer content length as opposed to the total buffer size. This can - be a real problem when using the mos7840 as a usb serial-console as all - kernel output is truncated during boot. - -Signed-off-by: Mark Ferrell -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/serial/mos7840.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - ---- a/drivers/usb/serial/mos7840.c -+++ b/drivers/usb/serial/mos7840.c -@@ -1189,9 +1189,12 @@ static int mos7840_chars_in_buffer(struc - } - - spin_lock_irqsave(&mos7840_port->pool_lock, flags); -- for (i = 0; i < NUM_URBS; ++i) -- if (mos7840_port->busy[i]) -- chars += URB_TRANSFER_BUFFER_SIZE; -+ for (i = 0; i < NUM_URBS; ++i) { -+ if (mos7840_port->busy[i]) { -+ struct urb *urb = mos7840_port->write_urb_pool[i]; -+ chars += urb->transfer_buffer_length; -+ } -+ } - spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); - dbg("%s - returns %d", __func__, chars); - return chars; -From ee6f827df9107139e8960326e49e1376352ced4d Mon Sep 17 00:00:00 2001 -From: fangxiaozhi -Date: Wed, 8 Aug 2012 09:24:45 +0000 -Subject: USB: support the new interfaces of Huawei Data Card devices in option driver - -From: fangxiaozhi - -commit ee6f827df9107139e8960326e49e1376352ced4d upstream. - -In this patch, we add new declarations into option.c to support the new -interfaces of Huawei Data Card devices. And at the same time, remove the -redundant declarations from option.c. - -Signed-off-by: fangxiaozhi -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/serial/option.c | 279 +++++++++++++++++--------------------------- - 1 file changed, 111 insertions(+), 168 deletions(-) - ---- a/drivers/usb/serial/option.c -+++ b/drivers/usb/serial/option.c -@@ -80,85 +80,9 @@ static void option_instat_callback(struc - #define OPTION_PRODUCT_GTM380_MODEM 0x7201 - - #define HUAWEI_VENDOR_ID 0x12D1 --#define HUAWEI_PRODUCT_E600 0x1001 --#define HUAWEI_PRODUCT_E220 0x1003 --#define HUAWEI_PRODUCT_E220BIS 0x1004 --#define HUAWEI_PRODUCT_E1401 0x1401 --#define HUAWEI_PRODUCT_E1402 0x1402 --#define HUAWEI_PRODUCT_E1403 0x1403 --#define HUAWEI_PRODUCT_E1404 0x1404 --#define HUAWEI_PRODUCT_E1405 0x1405 --#define HUAWEI_PRODUCT_E1406 0x1406 --#define HUAWEI_PRODUCT_E1407 0x1407 --#define HUAWEI_PRODUCT_E1408 0x1408 --#define HUAWEI_PRODUCT_E1409 0x1409 --#define HUAWEI_PRODUCT_E140A 0x140A --#define HUAWEI_PRODUCT_E140B 0x140B --#define HUAWEI_PRODUCT_E140C 0x140C --#define HUAWEI_PRODUCT_E140D 0x140D --#define HUAWEI_PRODUCT_E140E 0x140E --#define HUAWEI_PRODUCT_E140F 0x140F --#define HUAWEI_PRODUCT_E1410 0x1410 --#define HUAWEI_PRODUCT_E1411 0x1411 --#define HUAWEI_PRODUCT_E1412 0x1412 --#define HUAWEI_PRODUCT_E1413 0x1413 --#define HUAWEI_PRODUCT_E1414 0x1414 --#define HUAWEI_PRODUCT_E1415 0x1415 --#define HUAWEI_PRODUCT_E1416 0x1416 --#define HUAWEI_PRODUCT_E1417 0x1417 --#define HUAWEI_PRODUCT_E1418 0x1418 --#define HUAWEI_PRODUCT_E1419 0x1419 --#define HUAWEI_PRODUCT_E141A 0x141A --#define HUAWEI_PRODUCT_E141B 0x141B --#define HUAWEI_PRODUCT_E141C 0x141C --#define HUAWEI_PRODUCT_E141D 0x141D --#define HUAWEI_PRODUCT_E141E 0x141E --#define HUAWEI_PRODUCT_E141F 0x141F --#define HUAWEI_PRODUCT_E1420 0x1420 --#define HUAWEI_PRODUCT_E1421 0x1421 --#define HUAWEI_PRODUCT_E1422 0x1422 --#define HUAWEI_PRODUCT_E1423 0x1423 --#define HUAWEI_PRODUCT_E1424 0x1424 --#define HUAWEI_PRODUCT_E1425 0x1425 --#define HUAWEI_PRODUCT_E1426 0x1426 --#define HUAWEI_PRODUCT_E1427 0x1427 --#define HUAWEI_PRODUCT_E1428 0x1428 --#define HUAWEI_PRODUCT_E1429 0x1429 --#define HUAWEI_PRODUCT_E142A 0x142A --#define HUAWEI_PRODUCT_E142B 0x142B --#define HUAWEI_PRODUCT_E142C 0x142C --#define HUAWEI_PRODUCT_E142D 0x142D --#define HUAWEI_PRODUCT_E142E 0x142E --#define HUAWEI_PRODUCT_E142F 0x142F --#define HUAWEI_PRODUCT_E1430 0x1430 --#define HUAWEI_PRODUCT_E1431 0x1431 --#define HUAWEI_PRODUCT_E1432 0x1432 --#define HUAWEI_PRODUCT_E1433 0x1433 --#define HUAWEI_PRODUCT_E1434 0x1434 --#define HUAWEI_PRODUCT_E1435 0x1435 --#define HUAWEI_PRODUCT_E1436 0x1436 --#define HUAWEI_PRODUCT_E1437 0x1437 --#define HUAWEI_PRODUCT_E1438 0x1438 --#define HUAWEI_PRODUCT_E1439 0x1439 --#define HUAWEI_PRODUCT_E143A 0x143A --#define HUAWEI_PRODUCT_E143B 0x143B --#define HUAWEI_PRODUCT_E143C 0x143C --#define HUAWEI_PRODUCT_E143D 0x143D --#define HUAWEI_PRODUCT_E143E 0x143E --#define HUAWEI_PRODUCT_E143F 0x143F - #define HUAWEI_PRODUCT_K4505 0x1464 - #define HUAWEI_PRODUCT_K3765 0x1465 --#define HUAWEI_PRODUCT_E14AC 0x14AC --#define HUAWEI_PRODUCT_K3806 0x14AE - #define HUAWEI_PRODUCT_K4605 0x14C6 --#define HUAWEI_PRODUCT_K5005 0x14C8 --#define HUAWEI_PRODUCT_K3770 0x14C9 --#define HUAWEI_PRODUCT_K3771 0x14CA --#define HUAWEI_PRODUCT_K4510 0x14CB --#define HUAWEI_PRODUCT_K4511 0x14CC --#define HUAWEI_PRODUCT_ETS1220 0x1803 --#define HUAWEI_PRODUCT_E353 0x1506 --#define HUAWEI_PRODUCT_E173S 0x1C05 - - #define QUANTA_VENDOR_ID 0x0408 - #define QUANTA_PRODUCT_Q101 0xEA02 -@@ -615,104 +539,123 @@ static const struct usb_device_id option - { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) }, - { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) }, - { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1402, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1404, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1407, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140A, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140B, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140C, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140D, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140E, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140F, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141A, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141B, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141C, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141D, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141E, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141F, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1420, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1421, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1422, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1423, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1424, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1425, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1426, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1427, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1428, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1429, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142A, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142B, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142C, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142D, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142E, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142F, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1430, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1431, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1432, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1433, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1434, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1435, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1436, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1437, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1438, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1439, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143A, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143B, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143C, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x31) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x32) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x31) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x32) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x33) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x32) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x31) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x32) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x31) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x32) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x02) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x03) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x10) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x12) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x13) }, -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x01) }, /* E398 3G Modem */ -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x02) }, /* E398 3G PC UI Interface */ -- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x03) }, /* E398 3G Application Interface */ -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0xff, 0xff) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x01) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x02) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x03) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x04) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x05) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x06) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0A) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0B) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0D) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0E) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0F) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x10) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x12) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x13) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x14) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x15) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x17) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x18) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x19) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1A) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1B) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1C) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x31) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x32) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x33) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x34) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x35) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x36) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3A) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3B) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3D) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3E) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3F) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x48) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x49) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4A) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4B) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4C) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x61) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x62) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x63) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x64) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x65) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x66) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6A) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6B) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6D) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6E) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6F) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x78) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x79) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7A) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7B) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7C) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x01) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x02) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x03) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x04) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x05) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x06) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0A) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0B) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0D) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0E) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0F) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x10) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x12) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x13) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x14) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x15) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x17) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x18) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x19) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1A) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1B) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1C) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x31) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x32) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x33) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x34) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x35) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x36) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3A) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3B) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3D) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3E) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3F) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x48) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x49) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4A) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4B) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4C) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x61) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x62) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x63) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x64) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x65) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x66) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6A) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6B) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6D) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6E) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6F) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x78) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x79) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7B) }, -+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7C) }, -+ -+ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, -From b9e0d95c041ca2d7ad297ee37c2e9cfab67a188f Mon Sep 17 00:00:00 2001 -From: Stefano Stabellini -Date: Wed, 23 May 2012 18:57:20 +0100 -Subject: xen: mark local pages as FOREIGN in the m2p_override - -From: Stefano Stabellini - -commit b9e0d95c041ca2d7ad297ee37c2e9cfab67a188f upstream. - -When the frontend and the backend reside on the same domain, even if we -add pages to the m2p_override, these pages will never be returned by -mfn_to_pfn because the check "get_phys_to_machine(pfn) != mfn" will -always fail, so the pfn of the frontend will be returned instead -(resulting in a deadlock because the frontend pages are already locked). - -INFO: task qemu-system-i38:1085 blocked for more than 120 seconds. -"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. -qemu-system-i38 D ffff8800cfc137c0 0 1085 1 0x00000000 - ffff8800c47ed898 0000000000000282 ffff8800be4596b0 00000000000137c0 - ffff8800c47edfd8 ffff8800c47ec010 00000000000137c0 00000000000137c0 - ffff8800c47edfd8 00000000000137c0 ffffffff82213020 ffff8800be4596b0 -Call Trace: - [] ? __lock_page+0x70/0x70 - [] schedule+0x29/0x70 - [] io_schedule+0x60/0x80 - [] sleep_on_page+0xe/0x20 - [] __wait_on_bit_lock+0x5a/0xc0 - [] __lock_page+0x67/0x70 - [] ? autoremove_wake_function+0x40/0x40 - [] ? bio_add_page+0x36/0x40 - [] set_page_dirty_lock+0x52/0x60 - [] bio_set_pages_dirty+0x51/0x70 - [] do_blockdev_direct_IO+0xb24/0xeb0 - [] ? ext3_get_blocks_handle+0xe00/0xe00 - [] __blockdev_direct_IO+0x55/0x60 - [] ? ext3_get_blocks_handle+0xe00/0xe00 - [] ext3_direct_IO+0xf8/0x390 - [] ? ext3_get_blocks_handle+0xe00/0xe00 - [] ? xen_mc_flush+0xb0/0x1b0 - [] generic_file_aio_read+0x737/0x780 - [] ? gnttab_map_refs+0x15b/0x1e0 - [] ? find_get_pages+0x150/0x150 - [] aio_rw_vect_retry+0x7c/0x1d0 - [] ? lookup_ioctx+0x90/0x90 - [] aio_run_iocb+0x66/0x1a0 - [] do_io_submit+0x708/0xb90 - [] sys_io_submit+0x10/0x20 - [] system_call_fastpath+0x16/0x1b - -The explanation is in the comment within the code: - -We need to do this because the pages shared by the frontend -(xen-blkfront) can be already locked (lock_page, called by -do_read_cache_page); when the userspace backend tries to use them -with direct_IO, mfn_to_pfn returns the pfn of the frontend, so -do_blockdev_direct_IO is going to try to lock the same pages -again resulting in a deadlock. - -A simplified call graph looks like this: - -pygrub QEMU ------------------------------------------------ -do_read_cache_page io_submit - | | -lock_page ext3_direct_IO - | - bio_add_page - | - lock_page - -Internally the xen-blkback uses m2p_add_override to swizzle (temporarily) -a 'struct page' to have a different MFN (so that it can point to another -guest). It also can easily find out whether another pfn corresponding -to the mfn exists in the m2p, and can set the FOREIGN bit -in the p2m, making sure that mfn_to_pfn returns the pfn of the backend. - -This allows the backend to perform direct_IO on these pages, but as a -side effect prevents the frontend from using get_user_pages_fast on -them while they are being shared with the backend. - -Signed-off-by: Stefano Stabellini -Signed-off-by: Konrad Rzeszutek Wilk -Signed-off-by: Greg Kroah-Hartman - ---- - arch/x86/xen/p2m.c | 36 ++++++++++++++++++++++++++++++++++++ - 1 file changed, 36 insertions(+) - ---- a/arch/x86/xen/p2m.c -+++ b/arch/x86/xen/p2m.c -@@ -686,6 +686,7 @@ int m2p_add_override(unsigned long mfn, - unsigned long uninitialized_var(address); - unsigned level; - pte_t *ptep = NULL; -+ int ret = 0; - - pfn = page_to_pfn(page); - if (!PageHighMem(page)) { -@@ -721,6 +722,24 @@ int m2p_add_override(unsigned long mfn, - list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); - spin_unlock_irqrestore(&m2p_override_lock, flags); - -+ /* p2m(m2p(mfn)) == mfn: the mfn is already present somewhere in -+ * this domain. Set the FOREIGN_FRAME_BIT in the p2m for the other -+ * pfn so that the following mfn_to_pfn(mfn) calls will return the -+ * pfn from the m2p_override (the backend pfn) instead. -+ * We need to do this because the pages shared by the frontend -+ * (xen-blkfront) can be already locked (lock_page, called by -+ * do_read_cache_page); when the userspace backend tries to use them -+ * with direct_IO, mfn_to_pfn returns the pfn of the frontend, so -+ * do_blockdev_direct_IO is going to try to lock the same pages -+ * again resulting in a deadlock. -+ * As a side effect get_user_pages_fast might not be safe on the -+ * frontend pages while they are being shared with the backend, -+ * because mfn_to_pfn (that ends up being called by GUPF) will -+ * return the backend pfn rather than the frontend pfn. */ -+ ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); -+ if (ret == 0 && get_phys_to_machine(pfn) == mfn) -+ set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)); -+ - return 0; - } - EXPORT_SYMBOL_GPL(m2p_add_override); -@@ -732,6 +751,7 @@ int m2p_remove_override(struct page *pag - unsigned long uninitialized_var(address); - unsigned level; - pte_t *ptep = NULL; -+ int ret = 0; - - pfn = page_to_pfn(page); - mfn = get_phys_to_machine(pfn); -@@ -801,6 +821,22 @@ int m2p_remove_override(struct page *pag - } else - set_phys_to_machine(pfn, page->index); - -+ /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present -+ * somewhere in this domain, even before being added to the -+ * m2p_override (see comment above in m2p_add_override). -+ * If there are no other entries in the m2p_override corresponding -+ * to this mfn, then remove the FOREIGN_FRAME_BIT from the p2m for -+ * the original pfn (the one shared by the frontend): the backend -+ * cannot do any IO on this page anymore because it has been -+ * unshared. Removing the FOREIGN_FRAME_BIT from the p2m entry of -+ * the original pfn causes mfn_to_pfn(mfn) to return the frontend -+ * pfn again. */ -+ mfn &= ~FOREIGN_FRAME_BIT; -+ ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); -+ if (ret == 0 && get_phys_to_machine(pfn) == FOREIGN_FRAME(mfn) && -+ m2p_find_override(mfn) == NULL) -+ set_phys_to_machine(pfn, mfn); -+ - return 0; - } - EXPORT_SYMBOL_GPL(m2p_remove_override); -From 5cb7df2b2d3afee7638b3ef23a5bcb89c6f07bd9 Mon Sep 17 00:00:00 2001 -From: Sarah Sharp -Date: Mon, 2 Jul 2012 13:36:23 -0700 -Subject: xhci: Add Etron XHCI_TRUST_TX_LENGTH quirk. - -From: Sarah Sharp - -commit 5cb7df2b2d3afee7638b3ef23a5bcb89c6f07bd9 upstream. - -Gary reports that with recent kernels, he notices more xHCI driver -warnings: - -xhci_hcd 0000:03:00.0: WARN Successful completion on short TX: needs XHCI_TRUST_TX_LENGTH quirk? - -We think his Etron xHCI host controller may have the same buggy behavior -as the Fresco Logic xHCI host. When a short transfer is received, the -host will mark the transfer as successfully completed when it should be -marking it with a short completion. - -Fix this by turning on the XHCI_TRUST_TX_LENGTH quirk when the Etron -host is discovered. Note that Gary has revision 1, but if Etron fixes -this bug in future revisions, the quirk will have no effect. - -This patch should be backported to kernels as old as 2.6.36, that -contain a backported version of commit -1530bbc6272d9da1e39ef8e06190d42c13a02733 "xhci: Add new short TX quirk -for Fresco Logic host." - -Signed-off-by: Sarah Sharp -Reported-by: Gary E. Miller -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/host/xhci-pci.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/usb/host/xhci-pci.c -+++ b/drivers/usb/host/xhci-pci.c -@@ -95,6 +95,7 @@ static void xhci_pci_quirks(struct devic - pdev->device == PCI_DEVICE_ID_ASROCK_P67) { - xhci->quirks |= XHCI_RESET_ON_RESUME; - xhci_dbg(xhci, "QUIRK: Resetting on resume\n"); -+ xhci->quirks |= XHCI_TRUST_TX_LENGTH; - } - if (pdev->vendor == PCI_VENDOR_ID_VIA) - xhci->quirks |= XHCI_RESET_ON_RESUME; -From 50d0206fcaea3e736f912fd5b00ec6233fb4ce44 Mon Sep 17 00:00:00 2001 -From: Sarah Sharp -Date: Thu, 26 Jul 2012 12:03:59 -0700 -Subject: xhci: Fix bug after deq ptr set to link TRB. - -From: Sarah Sharp - -commit 50d0206fcaea3e736f912fd5b00ec6233fb4ce44 upstream. - -This patch fixes a particularly nasty bug that was revealed by the ring -expansion patches. The bug has been present since the very beginning of -the xHCI driver history, and could have caused general protection faults -from bad memory accesses. - -The first thing to note is that a Set TR Dequeue Pointer command can -move the dequeue pointer to a link TRB, if the canceled or stalled -transfer TD ended just before a link TRB. The function to increment the -dequeue pointer, inc_deq, was written before cancellation and stall -support was added. It assumed that the dequeue pointer could never -point to a link TRB. It would unconditionally increment the dequeue -pointer at the start of the function, check if the pointer was now on a -link TRB, and move it to the top of the next segment if so. - -This means that if a Set TR Dequeue Point command moved the dequeue -pointer to a link TRB, a subsequent call to inc_deq() would move the -pointer off the segment and into la-la-land. It would then read from -that memory to determine if it was a link TRB. Other functions would -often call inc_deq() until the dequeue pointer matched some other -pointer, which means this function would quite happily read all of -system memory before wrapping around to the right pointer value. - -Often, there would be another endpoint segment from a different ring -allocated from the same DMA pool, which would be contiguous to the -segment inc_deq just stepped off of. inc_deq would eventually find the -link TRB in that segment, and blindly move the dequeue pointer back to -the top of the correct ring segment. - -The only reason the original code worked at all is because there was -only one ring segment. With the ring expansion patches, the dequeue -pointer would eventually wrap into place, but the dequeue segment would -be out-of-sync. On the second TD after the dequeue pointer was moved to -a link TRB, trb_in_td() would fail (because the dequeue pointer and -dequeue segment were out-of-sync), and this message would appear: - -ERROR Transfer event TRB DMA ptr not part of current TD - -This fixes bugzilla entry 4333 (option-based modem unhappy on USB 3.0 -port: "Transfer event TRB DMA ptr not part of current TD", "rejecting -I/O to offline device"), - - https://bugzilla.kernel.org/show_bug.cgi?id=43333 - -and possibly other general protection fault bugs as well. - -This patch should be backported to kernels as old as 2.6.31. A separate -patch will be created for kernels older than 3.4, since inc_deq was -modified in 3.4 and this patch will not apply. - -Signed-off-by: Sarah Sharp -Tested-by: James Ettle -Tested-by: Matthew Hall -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/host/xhci-ring.c | 36 ++++++++++++++++++++++-------------- - 1 file changed, 22 insertions(+), 14 deletions(-) - ---- a/drivers/usb/host/xhci-ring.c -+++ b/drivers/usb/host/xhci-ring.c -@@ -145,29 +145,37 @@ static void next_trb(struct xhci_hcd *xh - */ - static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring) - { -- union xhci_trb *next; - unsigned long long addr; - - ring->deq_updates++; - -- /* If this is not event ring, there is one more usable TRB */ -+ /* -+ * If this is not event ring, and the dequeue pointer -+ * is not on a link TRB, there is one more usable TRB -+ */ - if (ring->type != TYPE_EVENT && - !last_trb(xhci, ring, ring->deq_seg, ring->dequeue)) - ring->num_trbs_free++; -- next = ++(ring->dequeue); - -- /* Update the dequeue pointer further if that was a link TRB or we're at -- * the end of an event ring segment (which doesn't have link TRBS) -- */ -- while (last_trb(xhci, ring, ring->deq_seg, next)) { -- if (ring->type == TYPE_EVENT && last_trb_on_last_seg(xhci, -- ring, ring->deq_seg, next)) { -- ring->cycle_state = (ring->cycle_state ? 0 : 1); -+ do { -+ /* -+ * Update the dequeue pointer further if that was a link TRB or -+ * we're at the end of an event ring segment (which doesn't have -+ * link TRBS) -+ */ -+ if (last_trb(xhci, ring, ring->deq_seg, ring->dequeue)) { -+ if (ring->type == TYPE_EVENT && -+ last_trb_on_last_seg(xhci, ring, -+ ring->deq_seg, ring->dequeue)) { -+ ring->cycle_state = (ring->cycle_state ? 0 : 1); -+ } -+ ring->deq_seg = ring->deq_seg->next; -+ ring->dequeue = ring->deq_seg->trbs; -+ } else { -+ ring->dequeue++; - } -- ring->deq_seg = ring->deq_seg->next; -- ring->dequeue = ring->deq_seg->trbs; -- next = ring->dequeue; -- } -+ } while (last_trb(xhci, ring, ring->deq_seg, ring->dequeue)); -+ - addr = (unsigned long long) xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue); - } - -From 22ceac191211cf6688b1bf6ecd93c8b6bf80ed9b Mon Sep 17 00:00:00 2001 -From: Sarah Sharp -Date: Mon, 23 Jul 2012 16:06:08 -0700 -Subject: xhci: Increase reset timeout for Renesas 720201 host. - -From: Sarah Sharp - -commit 22ceac191211cf6688b1bf6ecd93c8b6bf80ed9b upstream. - -The NEC/Renesas 720201 xHCI host controller does not complete its reset -within 250 milliseconds. In fact, it takes about 9 seconds to reset the -host controller, and 1 second for the host to be ready for doorbell -rings. Extend the reset and CNR polling timeout to 10 seconds each. - -This patch should be backported to kernels as old as 2.6.31, that -contain the commit 66d4eadd8d067269ea8fead1a50fe87c2979a80d "USB: xhci: -BIOS handoff and HW initialization." - -Signed-off-by: Sarah Sharp -Reported-by: Edwin Klein Mentink -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/host/xhci.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - ---- a/drivers/usb/host/xhci.c -+++ b/drivers/usb/host/xhci.c -@@ -166,7 +166,7 @@ int xhci_reset(struct xhci_hcd *xhci) - xhci_writel(xhci, command, &xhci->op_regs->command); - - ret = handshake(xhci, &xhci->op_regs->command, -- CMD_RESET, 0, 250 * 1000); -+ CMD_RESET, 0, 10 * 1000 * 1000); - if (ret) - return ret; - -@@ -175,7 +175,8 @@ int xhci_reset(struct xhci_hcd *xhci) - * xHCI cannot write to any doorbells or operational registers other - * than status until the "Controller Not Ready" flag is cleared. - */ -- ret = handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); -+ ret = handshake(xhci, &xhci->op_regs->status, -+ STS_CNR, 0, 10 * 1000 * 1000); - - for (i = 0; i < 2; ++i) { - xhci->bus_state[i].port_c_suspend = 0; -From e95829f474f0db3a4d940cae1423783edd966027 Mon Sep 17 00:00:00 2001 -From: Sarah Sharp -Date: Mon, 23 Jul 2012 18:59:30 +0300 -Subject: xhci: Switch PPT ports to EHCI on shutdown. - -From: Sarah Sharp - -commit e95829f474f0db3a4d940cae1423783edd966027 upstream. - -The Intel desktop boards DH77EB and DH77DF have a hardware issue that -can be worked around by BIOS. If the USB ports are switched to xHCI on -shutdown, the xHCI host will send a spurious interrupt, which will wake -the system. Some BIOS will work around this, but not all. - -The bug can be avoided if the USB ports are switched back to EHCI on -shutdown. The Intel Windows driver switches the ports back to EHCI, so -change the Linux xHCI driver to do the same. - -Unfortunately, we can't tell the two effected boards apart from other -working motherboards, because the vendors will change the DMI strings -for the DH77EB and DH77DF boards to their own custom names. One example -is Compulab's mini-desktop, the Intense-PC. Instead, key off the -Panther Point xHCI host PCI vendor and device ID, and switch the ports -over for all PPT xHCI hosts. - -The only impact this will have on non-effected boards is to add a couple -hundred milliseconds delay on boot when the BIOS has to switch the ports -over from EHCI to xHCI. - -This patch should be backported to kernels as old as 3.0, that contain -the commit 69e848c2090aebba5698a1620604c7dccb448684 "Intel xhci: Support -EHCI/xHCI port switching." - -Signed-off-by: Sarah Sharp -Reported-by: Denis Turischev -Tested-by: Denis Turischev -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/usb/host/pci-quirks.c | 7 +++++++ - drivers/usb/host/pci-quirks.h | 1 + - drivers/usb/host/xhci-pci.c | 9 +++++++++ - drivers/usb/host/xhci.c | 3 +++ - drivers/usb/host/xhci.h | 1 + - 5 files changed, 21 insertions(+) - ---- a/drivers/usb/host/pci-quirks.c -+++ b/drivers/usb/host/pci-quirks.c -@@ -800,6 +800,13 @@ void usb_enable_xhci_ports(struct pci_de - } - EXPORT_SYMBOL_GPL(usb_enable_xhci_ports); - -+void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) -+{ -+ pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, 0x0); -+ pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, 0x0); -+} -+EXPORT_SYMBOL_GPL(usb_disable_xhci_ports); -+ - /** - * PCI Quirks for xHCI. - * ---- a/drivers/usb/host/pci-quirks.h -+++ b/drivers/usb/host/pci-quirks.h -@@ -10,6 +10,7 @@ void usb_amd_quirk_pll_disable(void); - void usb_amd_quirk_pll_enable(void); - bool usb_is_intel_switchable_xhci(struct pci_dev *pdev); - void usb_enable_xhci_ports(struct pci_dev *xhci_pdev); -+void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); - #else - static inline void usb_amd_quirk_pll_disable(void) {} - static inline void usb_amd_quirk_pll_enable(void) {} ---- a/drivers/usb/host/xhci-pci.c -+++ b/drivers/usb/host/xhci-pci.c -@@ -90,6 +90,15 @@ static void xhci_pci_quirks(struct devic - xhci->quirks |= XHCI_EP_LIMIT_QUIRK; - xhci->limit_active_eps = 64; - xhci->quirks |= XHCI_SW_BW_CHECKING; -+ /* -+ * PPT desktop boards DH77EB and DH77DF will power back on after -+ * a few seconds of being shutdown. The fix for this is to -+ * switch the ports from xHCI to EHCI on shutdown. We can't use -+ * DMI information to find those particular boards (since each -+ * vendor will change the board name), so we have to key off all -+ * PPT chipsets. -+ */ -+ xhci->quirks |= XHCI_SPURIOUS_REBOOT; - } - if (pdev->vendor == PCI_VENDOR_ID_ETRON && - pdev->device == PCI_DEVICE_ID_ASROCK_P67) { ---- a/drivers/usb/host/xhci.c -+++ b/drivers/usb/host/xhci.c -@@ -659,6 +659,9 @@ void xhci_shutdown(struct usb_hcd *hcd) - { - struct xhci_hcd *xhci = hcd_to_xhci(hcd); - -+ if (xhci->quirks && XHCI_SPURIOUS_REBOOT) -+ usb_disable_xhci_ports(to_pci_dev(hcd->self.controller)); -+ - spin_lock_irq(&xhci->lock); - xhci_halt(xhci); - spin_unlock_irq(&xhci->lock); ---- a/drivers/usb/host/xhci.h -+++ b/drivers/usb/host/xhci.h -@@ -1486,6 +1486,7 @@ struct xhci_hcd { - #define XHCI_SW_BW_CHECKING (1 << 8) - #define XHCI_AMD_0x96_HOST (1 << 9) - #define XHCI_TRUST_TX_LENGTH (1 << 10) -+#define XHCI_SPURIOUS_REBOOT (1 << 13) - unsigned int num_active_eps; - unsigned int limit_active_eps; - /* There are two roothubs to keep track of bus suspend info for */ diff --git a/sources b/sources index 1e2b5e42d..b08ce31e1 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 967f72983655e2479f951195953e8480 linux-3.4.tar.xz -ffd1d2010b97fe45a62c9ce856ca224f patch-3.4.9.xz +5ac016a4a5b47179a0aee0dbadbb2254 patch-3.4.10.xz From 751c8f124b5e9f729659b9964d4d09f49abefe52 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 11 Sep 2012 09:02:30 -0400 Subject: [PATCH 427/487] Drop old Xen EC2 patch. It is no longer needed per Matt Wilson --- fix_xen_guest_on_old_EC2.patch | 34 ---------------------------------- kernel.spec | 7 ++++--- 2 files changed, 4 insertions(+), 37 deletions(-) delete mode 100644 fix_xen_guest_on_old_EC2.patch diff --git a/fix_xen_guest_on_old_EC2.patch b/fix_xen_guest_on_old_EC2.patch deleted file mode 100644 index e86200295..000000000 --- a/fix_xen_guest_on_old_EC2.patch +++ /dev/null @@ -1,34 +0,0 @@ - -Legacy hypervisors (RHEL 5.0 and RHEL 5.1) do not handle guest writes to -cr4 gracefully. If a guest attempts to write a bit of cr4 that is -unsupported, then the HV is so offended it crashes the domain. While -later guest kernels (such as RHEL6) don't assume the HV supports all -features, they do expect nicer responses. That assumption introduced -code that probes whether or not xsave is supported early in the boot. So -now when attempting to boot a RHEL6 guest on RHEL5.0 or RHEL5.1 an early -crash will occur. - -This patch is quite obviously an undesirable hack. The real fix for this -problem should be in the HV, and is, in later HVs. However, to support -running on old HVs, RHEL6 can take this small change. No impact will -occur for running on any RHEL HV (not even RHEL 5.5 supports xsave). -There is only potential for guest performance loss on upstream Xen. - ---- - arch/x86/xen/enlighten.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c -index 52f8e19..6db3d67 100644 ---- a/arch/x86/xen/enlighten.c -+++ b/arch/x86/xen/enlighten.c -@@ -802,6 +802,7 @@ static void xen_write_cr4(unsigned long cr4) - { - cr4 &= ~X86_CR4_PGE; - cr4 &= ~X86_CR4_PSE; -+ cr4 &= ~X86_CR4_OSXSAVE; - - native_write_cr4(cr4); - } --- -1.6.6.1 diff --git a/kernel.spec b/kernel.spec index a46db9d10..9796ca3ff 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -635,7 +635,6 @@ Patch800: linux-2.6-crash-driver.patch # crypto/ # virt + ksm patches -Patch1500: fix_xen_guest_on_old_EC2.patch # DRM #atch1700: drm-edid-try-harder-to-fix-up-broken-headers.patch @@ -1273,7 +1272,6 @@ ApplyPatch linux-2.6-e1000-ich9-montevina.patch # crypto/ # Assorted Virt Fixes -ApplyPatch fix_xen_guest_on_old_EC2.patch # DRM core #ApplyPatch drm-edid-try-harder-to-fix-up-broken-headers.patch @@ -2043,6 +2041,9 @@ fi # and build. %changelog +* Tue Sep 11 2012 Josh Boyer 3.4.10-2 +- Drop old Xen EC2 patch. It is no longer needed per Matt Wilson + * Wed Sep 05 2012 Josh Boyer 3.4.10-1 - Linux v3.4.10 From d456ca0684a1cee3074cbec5f982edd2e26fc279 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Sun, 16 Sep 2012 09:00:19 -0400 Subject: [PATCH 428/487] Linux v3.4.11 --- kernel.spec | 13 +++---- sources | 2 +- ...ield-when-recycling-erroneous-buffer.patch | 36 ------------------- 3 files changed, 6 insertions(+), 45 deletions(-) delete mode 100644 uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch diff --git a/kernel.spec b/kernel.spec index 9796ca3ff..4c482ab63 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 10 +%define stable_update 11 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -703,9 +703,6 @@ Patch22018: atl1c_net_next_update-3.4.patch Patch22055: crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch Patch22056: crypto-aesni-intel-fix-wrong-kfree-pointer.patch -#rhbz 836742 -Patch22059: uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch - #rhbz 714271 Patch22060: CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch @@ -1327,9 +1324,6 @@ ApplyPatch atl1c_net_next_update-3.4.patch ApplyPatch crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch ApplyPatch crypto-aesni-intel-fix-wrong-kfree-pointer.patch -#rhbz 836742 -ApplyPatch uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch - #rhbz 714271 ApplyPatch CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch @@ -2041,6 +2035,9 @@ fi # and build. %changelog +* Sun Sep 16 2012 Josh Boyer 3.4.11-1 +- Linux v3.4.11 + * Tue Sep 11 2012 Josh Boyer 3.4.10-2 - Drop old Xen EC2 patch. It is no longer needed per Matt Wilson diff --git a/sources b/sources index b08ce31e1..a4d0de728 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 967f72983655e2479f951195953e8480 linux-3.4.tar.xz -5ac016a4a5b47179a0aee0dbadbb2254 patch-3.4.10.xz +2149df47fc96fec05787bf0197fb7b16 patch-3.4.11.xz diff --git a/uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch b/uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch deleted file mode 100644 index 6606b7d3d..000000000 --- a/uvcvideo-Reset-bytesused-field-when-recycling-erroneous-buffer.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 3771973542a4807b251352253ed22c50e688e573 Mon Sep 17 00:00:00 2001 -From: Jayakrishnan Memana -Date: Sun, 15 Jul 2012 15:54:03 +0200 -Subject: [PATCH] uvcvideo: Reset the bytesused field when recycling an erroneous buffer - -Buffers marked as erroneous are recycled immediately by the driver if -the nodrop module parameter isn't set. The buffer payload size is reset -to 0, but the buffer bytesused field isn't. This results in the buffer -being immediately considered as complete, leading to an infinite loop in -interrupt context. - -Fix the problem by resetting the bytesused field when recycling the -buffer. - -Cc: -Signed-off-by: Jayakrishnan Memana -Signed-off-by: Laurent Pinchart ---- - drivers/media/video/uvc/uvc_queue.c | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c -index 9288fbd..5577381 100644 ---- a/drivers/media/video/uvc/uvc_queue.c -+++ b/drivers/media/video/uvc/uvc_queue.c -@@ -338,6 +338,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, - if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) { - buf->error = 0; - buf->state = UVC_BUF_STATE_QUEUED; -+ buf->bytesused = 0; - vb2_set_plane_payload(&buf->buf, 0, 0); - return buf; - } --- -1.7.2.5 - From 197b7297271cf42d50e14f76b83403d90d60c0b8 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 21 Sep 2012 09:06:24 -0400 Subject: [PATCH 429/487] Add patch to fix radeon regression from Jerome Glisse (rhbz 785375) --- ...-dma32-to-fix-regression-rs4xx-rs6xx.patch | 35 +++++++++++++++++++ kernel.spec | 7 +++- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 drm-radeon-force-dma32-to-fix-regression-rs4xx-rs6xx.patch diff --git a/drm-radeon-force-dma32-to-fix-regression-rs4xx-rs6xx.patch b/drm-radeon-force-dma32-to-fix-regression-rs4xx-rs6xx.patch new file mode 100644 index 000000000..43a5eb6f7 --- /dev/null +++ b/drm-radeon-force-dma32-to-fix-regression-rs4xx-rs6xx.patch @@ -0,0 +1,35 @@ +From 4a2b6662c3632176b4fdf012243dd3751367bf1f Mon Sep 17 00:00:00 2001 +From: Jerome Glisse +Date: Tue, 28 Aug 2012 16:50:22 -0400 +Subject: [PATCH] drm/radeon: force dma32 to fix regression rs4xx,rs6xx,rs740 + +It seems some of those IGP dislike non dma32 page despite what +documentation says. Fix regression since we allowed non dma32 +pages. It seems it only affect some revision of those IGP chips +as we don't know which one just force dma32 for all of them. + +https://bugzilla.redhat.com/show_bug.cgi?id=785375 + +Signed-off-by: Jerome Glisse +Cc: +Signed-off-by: Alex Deucher +--- + drivers/gpu/drm/radeon/radeon_device.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c +index d2e2438..33da8bf 100644 +--- a/drivers/gpu/drm/radeon/radeon_device.c ++++ b/drivers/gpu/drm/radeon/radeon_device.c +@@ -1051,7 +1051,7 @@ int radeon_device_init(struct radeon_device *rdev, + if (rdev->flags & RADEON_IS_AGP) + rdev->need_dma32 = true; + if ((rdev->flags & RADEON_IS_PCI) && +- (rdev->family < CHIP_RS400)) ++ (rdev->family <= CHIP_RS740)) + rdev->need_dma32 = true; + + dma_bits = rdev->need_dma32 ? 32 : 40; +-- +1.7.11.4 + diff --git a/kernel.spec b/kernel.spec index 4c482ab63..56600ced3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -638,6 +638,7 @@ Patch800: linux-2.6-crash-driver.patch # DRM #atch1700: drm-edid-try-harder-to-fix-up-broken-headers.patch +Patch1701: drm-radeon-force-dma32-to-fix-regression-rs4xx-rs6xx.patch # intel drm is all merged upstream Patch1824: drm-intel-next.patch @@ -1272,6 +1273,7 @@ ApplyPatch linux-2.6-e1000-ich9-montevina.patch # DRM core #ApplyPatch drm-edid-try-harder-to-fix-up-broken-headers.patch +ApplyPatch drm-radeon-force-dma32-to-fix-regression-rs4xx-rs6xx.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch @@ -2035,6 +2037,9 @@ fi # and build. %changelog +* Fri Sep 21 2012 Josh Boyer 3.4.11-2 +- Add patch to fix radeon regression from Jerome Glisse (rhbz 785375) + * Sun Sep 16 2012 Josh Boyer 3.4.11-1 - Linux v3.4.11 From 5b27c793de2ac1993a1565b8a9738e84aea9879c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 28 Sep 2012 08:31:01 -0400 Subject: [PATCH 430/487] Split out kernel-tools-libs (rhbz 859943) --- kernel.spec | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/kernel.spec b/kernel.spec index 56600ced3..df30f13ab 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -796,18 +796,28 @@ Provides: cpufrequtils = 1:009-0.6.p1 Obsoletes: cpufreq-utils < 1:009-0.6.p1 Obsoletes: cpufrequtils < 1:009-0.6.p1 Obsoletes: cpuspeed < 1:1.5-16 +Requires: kernel-tools-libs = %{version}-%{release} %description -n kernel-tools This package contains the tools/ directory from the kernel source - the perf tool and the supporting documentation. -%package -n kernel-tools-devel +%package -n kernel-tools-libs +Summary: Libraries for the kernels-tools +Group: Development/System +License: GPLv2 +%description -n kernel-tools-libs +This package contains the libraries built from the tools/ directory +from the kernel source. + +%package -n kernel-tools-libs-devel Summary: Assortment of tools for the Linux kernel Group: Development/System License: GPLv2 Requires: kernel-tools = %{version}-%{release} Provides: cpupowerutils-devel = 1:009-0.6.p1 Obsoletes: cpupowerutils-devel < 1:009-0.6.p1 -%description -n kernel-tools-devel +Requires: kernel-tools-libs = %{version}-%{release} +%description -n kernel-tools-libs-devel This package contains the development files for the tools/ directory from the kernel source. @@ -1956,8 +1966,6 @@ fi %{_bindir}/centrino-decode %{_bindir}/powernow-k8-decode %endif -%{_libdir}/libcpupower.so.0 -%{_libdir}/libcpupower.so.0.0.0 %{_unitdir}/cpupower.service %config(noreplace) %{_sysconfdir}/sysconfig/cpupower %endif @@ -1968,7 +1976,11 @@ fi %endif %ifarch %{cpupowerarchs} -%files -n kernel-tools-devel +%files -n kernel-tools-libs +%{_libdir}/libcpupower.so.0 +%{_libdir}/libcpupower.so.0.0.0 + +%files -n kernel-tools-libs-devel %{_libdir}/libcpupower.so %{_includedir}/cpufreq.h %endif @@ -2037,6 +2049,9 @@ fi # and build. %changelog +* Fri Sep 28 2012 Josh Boyer - 3.4.11-3 +- Split out kernel-tools-libs (rhbz 859943) + * Fri Sep 21 2012 Josh Boyer 3.4.11-2 - Add patch to fix radeon regression from Jerome Glisse (rhbz 785375) From 9e634cfc4b0955cad06bce56671bd827918368d4 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 2 Oct 2012 15:47:25 -0400 Subject: [PATCH 431/487] 3.4.12 --- af_netlink-credentials-cve-2012-3520.patch | 114 --------- ...-dma32-to-fix-regression-rs4xx-rs6xx.patch | 35 --- kernel.spec | 35 +-- ...limit-number-of-GSO-segments-per-skb.patch | 70 ------ rds-set-correct-msg_namelen.patch | 219 ------------------ ...O-segments-and-minimum-TX-queue-size.patch | 156 ------------- sources | 2 +- ...ply-device-TSO-segment-limit-earlier.patch | 124 ---------- 8 files changed, 12 insertions(+), 743 deletions(-) delete mode 100644 af_netlink-credentials-cve-2012-3520.patch delete mode 100644 drm-radeon-force-dma32-to-fix-regression-rs4xx-rs6xx.patch delete mode 100644 net-Allow-driver-to-limit-number-of-GSO-segments-per-skb.patch delete mode 100644 rds-set-correct-msg_namelen.patch delete mode 100644 sfc-Fix-maximum-number-of-TSO-segments-and-minimum-TX-queue-size.patch delete mode 100644 tcp-Apply-device-TSO-segment-limit-earlier.patch diff --git a/af_netlink-credentials-cve-2012-3520.patch b/af_netlink-credentials-cve-2012-3520.patch deleted file mode 100644 index c324a4a90..000000000 --- a/af_netlink-credentials-cve-2012-3520.patch +++ /dev/null @@ -1,114 +0,0 @@ -Subject: [PATCH] af_netlink: force credentials passing [CVE-2012-3520] -From: Eric Dumazet -To: David Miller -Cc: netdev , Petr Matousek , - Florian Weimer , - Pablo Neira Ayuso -Content-Type: text/plain; charset="UTF-8" -Date: Tue, 21 Aug 2012 18:21:17 +0200 -Message-ID: <1345566077.5158.530.camel@edumazet-glaptop> -Mime-Version: 1.0 -Content-Transfer-Encoding: 7bit -Sender: netdev-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org -X-RedHat-Spam-Score: -6.999 (BAYES_00,DKIM_ADSP_CUSTOM_MED,DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID) -X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 -X-Scanned-By: MIMEDefang 2.68 on 10.5.110.16 -Status: RO -Content-Length: 3042 -Lines: 91 - -From: Eric Dumazet - -Pablo Neira Ayuso discovered that avahi and -potentially NetworkManager accept spoofed Netlink messages because of a -kernel bug. The kernel passes all-zero SCM_CREDENTIALS ancillary data -to the receiver if the sender did not provide such data, instead of not -including any such data at all or including the correct data from the -peer (as it is the case with AF_UNIX). - -This bug was introduced in commit 16e572626961 -(af_unix: dont send SCM_CREDENTIALS by default) - -This patch forces passing credentials for netlink, as -before the regression. - -Another fix would be to not add SCM_CREDENTIALS in -netlink messages if not provided by the sender, but it -might break some programs. - -With help from Florian Weimer & Petr Matousek - -This issue is designated as CVE-2012-3520 - -Signed-off-by: Eric Dumazet -Cc: Petr Matousek -Cc: Florian Weimer -Cc: Pablo Neira Ayuso ---- - include/net/scm.h | 4 +++- - net/netlink/af_netlink.c | 2 +- - net/unix/af_unix.c | 4 ++-- - 3 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/include/net/scm.h b/include/net/scm.h -index 079d788..7dc0854 100644 ---- a/include/net/scm.h -+++ b/include/net/scm.h -@@ -70,9 +70,11 @@ static __inline__ void scm_destroy(struct scm_cookie *scm) - } - - static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, -- struct scm_cookie *scm) -+ struct scm_cookie *scm, bool forcecreds) - { - memset(scm, 0, sizeof(*scm)); -+ if (forcecreds) -+ scm_set_cred(scm, task_tgid(current), current_cred()); - unix_get_peersec_dgram(sock, scm); - if (msg->msg_controllen <= 0) - return 0; -diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c -index 5463969..1445d73 100644 ---- a/net/netlink/af_netlink.c -+++ b/net/netlink/af_netlink.c -@@ -1362,7 +1362,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, - if (NULL == siocb->scm) - siocb->scm = &scm; - -- err = scm_send(sock, msg, siocb->scm); -+ err = scm_send(sock, msg, siocb->scm, true); - if (err < 0) - return err; - -diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c -index e4768c1..c5ee4ff 100644 ---- a/net/unix/af_unix.c -+++ b/net/unix/af_unix.c -@@ -1450,7 +1450,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, - if (NULL == siocb->scm) - siocb->scm = &tmp_scm; - wait_for_unix_gc(); -- err = scm_send(sock, msg, siocb->scm); -+ err = scm_send(sock, msg, siocb->scm, false); - if (err < 0) - return err; - -@@ -1619,7 +1619,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, - if (NULL == siocb->scm) - siocb->scm = &tmp_scm; - wait_for_unix_gc(); -- err = scm_send(sock, msg, siocb->scm); -+ err = scm_send(sock, msg, siocb->scm, false); - if (err < 0) - return err; - - - --- -To unsubscribe from this list: send the line "unsubscribe netdev" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - diff --git a/drm-radeon-force-dma32-to-fix-regression-rs4xx-rs6xx.patch b/drm-radeon-force-dma32-to-fix-regression-rs4xx-rs6xx.patch deleted file mode 100644 index 43a5eb6f7..000000000 --- a/drm-radeon-force-dma32-to-fix-regression-rs4xx-rs6xx.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 4a2b6662c3632176b4fdf012243dd3751367bf1f Mon Sep 17 00:00:00 2001 -From: Jerome Glisse -Date: Tue, 28 Aug 2012 16:50:22 -0400 -Subject: [PATCH] drm/radeon: force dma32 to fix regression rs4xx,rs6xx,rs740 - -It seems some of those IGP dislike non dma32 page despite what -documentation says. Fix regression since we allowed non dma32 -pages. It seems it only affect some revision of those IGP chips -as we don't know which one just force dma32 for all of them. - -https://bugzilla.redhat.com/show_bug.cgi?id=785375 - -Signed-off-by: Jerome Glisse -Cc: -Signed-off-by: Alex Deucher ---- - drivers/gpu/drm/radeon/radeon_device.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c -index d2e2438..33da8bf 100644 ---- a/drivers/gpu/drm/radeon/radeon_device.c -+++ b/drivers/gpu/drm/radeon/radeon_device.c -@@ -1051,7 +1051,7 @@ int radeon_device_init(struct radeon_device *rdev, - if (rdev->flags & RADEON_IS_AGP) - rdev->need_dma32 = true; - if ((rdev->flags & RADEON_IS_PCI) && -- (rdev->family < CHIP_RS400)) -+ (rdev->family <= CHIP_RS740)) - rdev->need_dma32 = true; - - dma_bits = rdev->need_dma32 ? 32 : 40; --- -1.7.11.4 - diff --git a/kernel.spec b/kernel.spec index df30f13ab..097920ba4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 11 +%define stable_update 12 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -638,7 +638,6 @@ Patch800: linux-2.6-crash-driver.patch # DRM #atch1700: drm-edid-try-harder-to-fix-up-broken-headers.patch -Patch1701: drm-radeon-force-dma32-to-fix-regression-rs4xx-rs6xx.patch # intel drm is all merged upstream Patch1824: drm-intel-next.patch @@ -707,16 +706,6 @@ Patch22056: crypto-aesni-intel-fix-wrong-kfree-pointer.patch #rhbz 714271 Patch22060: CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch -#rhbz 820039 843554 -Patch22061: rds-set-correct-msg_namelen.patch - -#rhbz 845558 844714 -Patch22070: net-Allow-driver-to-limit-number-of-GSO-segments-per-skb.patch -Patch22071: sfc-Fix-maximum-number-of-TSO-segments-and-minimum-TX-queue-size.patch -Patch22072: tcp-Apply-device-TSO-segment-limit-earlier.patch - -Patch22075: af_netlink-credentials-cve-2012-3520.patch - # END OF PATCH DEFINITIONS %endif @@ -1283,7 +1272,6 @@ ApplyPatch linux-2.6-e1000-ich9-montevina.patch # DRM core #ApplyPatch drm-edid-try-harder-to-fix-up-broken-headers.patch -ApplyPatch drm-radeon-force-dma32-to-fix-regression-rs4xx-rs6xx.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch @@ -1339,16 +1327,6 @@ ApplyPatch crypto-aesni-intel-fix-wrong-kfree-pointer.patch #rhbz 714271 ApplyPatch CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch -#rhbz 820039 843554 -ApplyPatch rds-set-correct-msg_namelen.patch - -#rhbz 845558 844714 -ApplyPatch net-Allow-driver-to-limit-number-of-GSO-segments-per-skb.patch -ApplyPatch sfc-Fix-maximum-number-of-TSO-segments-and-minimum-TX-queue-size.patch -ApplyPatch tcp-Apply-device-TSO-segment-limit-earlier.patch - -ApplyPatch af_netlink-credentials-cve-2012-3520.patch - # END OF PATCH APPLICATIONS %endif @@ -2049,6 +2027,15 @@ fi # and build. %changelog +* Tue Oct 02 2012 Dave Jones 3.4.12-1 +- Linux v3.4.12 + merged: drm-radeon-force-dma32-to-fix-regression-rs4xx-rs6xx.patch + merged: rds-set-correct-msg_namelen.patch + merged: net-Allow-driver-to-limit-number-of-GSO-segments-per-skb.patch + merged: sfc-Fix-maximum-number-of-TSO-segments-and-minimum-TX-queue-size.patch + merged: tcp-Apply-device-TSO-segment-limit-earlier.patch + merged: af_netlink-credentials-cve-2012-3520.patch + * Fri Sep 28 2012 Josh Boyer - 3.4.11-3 - Split out kernel-tools-libs (rhbz 859943) diff --git a/net-Allow-driver-to-limit-number-of-GSO-segments-per-skb.patch b/net-Allow-driver-to-limit-number-of-GSO-segments-per-skb.patch deleted file mode 100644 index bebccf3d0..000000000 --- a/net-Allow-driver-to-limit-number-of-GSO-segments-per-skb.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 30b678d844af3305cda5953467005cebb5d7b687 Mon Sep 17 00:00:00 2001 -From: Ben Hutchings -Date: Mon, 30 Jul 2012 15:57:00 +0000 -Subject: [PATCH] net: Allow driver to limit number of GSO segments per skb - -A peer (or local user) may cause TCP to use a nominal MSS of as little -as 88 (actual MSS of 76 with timestamps). Given that we have a -sufficiently prodigious local sender and the peer ACKs quickly enough, -it is nevertheless possible to grow the window for such a connection -to the point that we will try to send just under 64K at once. This -results in a single skb that expands to 861 segments. - -In some drivers with TSO support, such an skb will require hundreds of -DMA descriptors; a substantial fraction of a TX ring or even more than -a full ring. The TX queue selected for the skb may stall and trigger -the TX watchdog repeatedly (since the problem skb will be retried -after the TX reset). This particularly affects sfc, for which the -issue is designated as CVE-2012-3412. - -Therefore: -1. Add the field net_device::gso_max_segs holding the device-specific - limit. -2. In netif_skb_features(), if the number of segments is too high then - mask out GSO features to force fall back to software GSO. - -Signed-off-by: Ben Hutchings -Signed-off-by: David S. Miller ---- - include/linux/netdevice.h | 2 ++ - net/core/dev.c | 4 ++++ - 2 files changed, 6 insertions(+), 0 deletions(-) - -diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h -index eb06e58..a9db4f3 100644 ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -1300,6 +1300,8 @@ struct net_device { - /* for setting kernel sock attribute on TCP connection setup */ - #define GSO_MAX_SIZE 65536 - unsigned int gso_max_size; -+#define GSO_MAX_SEGS 65535 -+ u16 gso_max_segs; - - #ifdef CONFIG_DCB - /* Data Center Bridging netlink ops */ -diff --git a/net/core/dev.c b/net/core/dev.c -index 0cb3fe8..f91abf8 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -2134,6 +2134,9 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) - __be16 protocol = skb->protocol; - netdev_features_t features = skb->dev->features; - -+ if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs) -+ features &= ~NETIF_F_GSO_MASK; -+ - if (protocol == htons(ETH_P_8021Q)) { - struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; - protocol = veh->h_vlan_encapsulated_proto; -@@ -5986,6 +5989,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, - dev_net_set(dev, &init_net); - - dev->gso_max_size = GSO_MAX_SIZE; -+ dev->gso_max_segs = GSO_MAX_SEGS; - - INIT_LIST_HEAD(&dev->napi_list); - INIT_LIST_HEAD(&dev->unreg_list); --- -1.7.7.6 - diff --git a/rds-set-correct-msg_namelen.patch b/rds-set-correct-msg_namelen.patch deleted file mode 100644 index 340d0cd68..000000000 --- a/rds-set-correct-msg_namelen.patch +++ /dev/null @@ -1,219 +0,0 @@ -From 06b6a1cf6e776426766298d055bb3991957d90a7 Mon Sep 17 00:00:00 2001 -From: Weiping Pan -Date: Mon, 23 Jul 2012 10:37:48 +0800 -Subject: [PATCH] rds: set correct msg_namelen - -Jay Fenlason (fenlason@redhat.com) found a bug, -that recvfrom() on an RDS socket can return the contents of random kernel -memory to userspace if it was called with a address length larger than -sizeof(struct sockaddr_in). -rds_recvmsg() also fails to set the addr_len paramater properly before -returning, but that's just a bug. -There are also a number of cases wher recvfrom() can return an entirely bogus -address. Anything in rds_recvmsg() that returns a non-negative value but does -not go through the "sin = (struct sockaddr_in *)msg->msg_name;" code path -at the end of the while(1) loop will return up to 128 bytes of kernel memory -to userspace. - -And I write two test programs to reproduce this bug, you will see that in -rds_server, fromAddr will be overwritten and the following sock_fd will be -destroyed. -Yes, it is the programmer's fault to set msg_namelen incorrectly, but it is -better to make the kernel copy the real length of address to user space in -such case. - -How to run the test programs ? -I test them on 32bit x86 system, 3.5.0-rc7. - -1 compile -gcc -o rds_client rds_client.c -gcc -o rds_server rds_server.c - -2 run ./rds_server on one console - -3 run ./rds_client on another console - -4 you will see something like: -server is waiting to receive data... -old socket fd=3 -server received data from client:data from client -msg.msg_namelen=32 -new socket fd=-1067277685 -sendmsg() -: Bad file descriptor - -/***************** rds_client.c ********************/ - -int main(void) -{ - int sock_fd; - struct sockaddr_in serverAddr; - struct sockaddr_in toAddr; - char recvBuffer[128] = "data from client"; - struct msghdr msg; - struct iovec iov; - - sock_fd = socket(AF_RDS, SOCK_SEQPACKET, 0); - if (sock_fd < 0) { - perror("create socket error\n"); - exit(1); - } - - memset(&serverAddr, 0, sizeof(serverAddr)); - serverAddr.sin_family = AF_INET; - serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); - serverAddr.sin_port = htons(4001); - - if (bind(sock_fd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { - perror("bind() error\n"); - close(sock_fd); - exit(1); - } - - memset(&toAddr, 0, sizeof(toAddr)); - toAddr.sin_family = AF_INET; - toAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); - toAddr.sin_port = htons(4000); - msg.msg_name = &toAddr; - msg.msg_namelen = sizeof(toAddr); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_iov->iov_base = recvBuffer; - msg.msg_iov->iov_len = strlen(recvBuffer) + 1; - msg.msg_control = 0; - msg.msg_controllen = 0; - msg.msg_flags = 0; - - if (sendmsg(sock_fd, &msg, 0) == -1) { - perror("sendto() error\n"); - close(sock_fd); - exit(1); - } - - printf("client send data:%s\n", recvBuffer); - - memset(recvBuffer, '\0', 128); - - msg.msg_name = &toAddr; - msg.msg_namelen = sizeof(toAddr); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_iov->iov_base = recvBuffer; - msg.msg_iov->iov_len = 128; - msg.msg_control = 0; - msg.msg_controllen = 0; - msg.msg_flags = 0; - if (recvmsg(sock_fd, &msg, 0) == -1) { - perror("recvmsg() error\n"); - close(sock_fd); - exit(1); - } - - printf("receive data from server:%s\n", recvBuffer); - - close(sock_fd); - - return 0; -} - -/***************** rds_server.c ********************/ - -int main(void) -{ - struct sockaddr_in fromAddr; - int sock_fd; - struct sockaddr_in serverAddr; - unsigned int addrLen; - char recvBuffer[128]; - struct msghdr msg; - struct iovec iov; - - sock_fd = socket(AF_RDS, SOCK_SEQPACKET, 0); - if(sock_fd < 0) { - perror("create socket error\n"); - exit(0); - } - - memset(&serverAddr, 0, sizeof(serverAddr)); - serverAddr.sin_family = AF_INET; - serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); - serverAddr.sin_port = htons(4000); - if (bind(sock_fd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { - perror("bind error\n"); - close(sock_fd); - exit(1); - } - - printf("server is waiting to receive data...\n"); - msg.msg_name = &fromAddr; - - /* - * I add 16 to sizeof(fromAddr), ie 32, - * and pay attention to the definition of fromAddr, - * recvmsg() will overwrite sock_fd, - * since kernel will copy 32 bytes to userspace. - * - * If you just use sizeof(fromAddr), it works fine. - * */ - msg.msg_namelen = sizeof(fromAddr) + 16; - /* msg.msg_namelen = sizeof(fromAddr); */ - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_iov->iov_base = recvBuffer; - msg.msg_iov->iov_len = 128; - msg.msg_control = 0; - msg.msg_controllen = 0; - msg.msg_flags = 0; - - while (1) { - printf("old socket fd=%d\n", sock_fd); - if (recvmsg(sock_fd, &msg, 0) == -1) { - perror("recvmsg() error\n"); - close(sock_fd); - exit(1); - } - printf("server received data from client:%s\n", recvBuffer); - printf("msg.msg_namelen=%d\n", msg.msg_namelen); - printf("new socket fd=%d\n", sock_fd); - strcat(recvBuffer, "--data from server"); - if (sendmsg(sock_fd, &msg, 0) == -1) { - perror("sendmsg()\n"); - close(sock_fd); - exit(1); - } - } - - close(sock_fd); - return 0; -} - -Signed-off-by: Weiping Pan -Signed-off-by: David S. Miller ---- - net/rds/recv.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/net/rds/recv.c b/net/rds/recv.c -index 5c6e9f1..9f0f17c 100644 ---- a/net/rds/recv.c -+++ b/net/rds/recv.c -@@ -410,6 +410,8 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, - - rdsdebug("size %zu flags 0x%x timeo %ld\n", size, msg_flags, timeo); - -+ msg->msg_namelen = 0; -+ - if (msg_flags & MSG_OOB) - goto out; - -@@ -485,6 +487,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, - sin->sin_port = inc->i_hdr.h_sport; - sin->sin_addr.s_addr = inc->i_saddr; - memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); -+ msg->msg_namelen = sizeof(*sin); - } - break; - } --- -1.7.11.2 - diff --git a/sfc-Fix-maximum-number-of-TSO-segments-and-minimum-TX-queue-size.patch b/sfc-Fix-maximum-number-of-TSO-segments-and-minimum-TX-queue-size.patch deleted file mode 100644 index 07ec616e0..000000000 --- a/sfc-Fix-maximum-number-of-TSO-segments-and-minimum-TX-queue-size.patch +++ /dev/null @@ -1,156 +0,0 @@ -From 7e6d06f0de3f74ca929441add094518ae332257c Mon Sep 17 00:00:00 2001 -From: Ben Hutchings -Date: Mon, 30 Jul 2012 15:57:44 +0000 -Subject: [PATCH] sfc: Fix maximum number of TSO segments and minimum TX queue - size - -Currently an skb requiring TSO may not fit within a minimum-size TX -queue. The TX queue selected for the skb may stall and trigger the TX -watchdog repeatedly (since the problem skb will be retried after the -TX reset). This issue is designated as CVE-2012-3412. - -Set the maximum number of TSO segments for our devices to 100. This -should make no difference to behaviour unless the actual MSS is less -than about 700. Increase the minimum TX queue size accordingly to -allow for 2 worst-case skbs, so that there will definitely be space -to add an skb after we wake a queue. - -To avoid invalidating existing configurations, change -efx_ethtool_set_ringparam() to fix up values that are too small rather -than returning -EINVAL. - -Signed-off-by: Ben Hutchings -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/sfc/efx.c | 6 ++++++ - drivers/net/ethernet/sfc/efx.h | 14 ++++++++++---- - drivers/net/ethernet/sfc/ethtool.c | 16 +++++++++++----- - drivers/net/ethernet/sfc/tx.c | 19 +++++++++++++++++++ - 4 files changed, 46 insertions(+), 9 deletions(-) - -diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c -index 70554a1..65a8d49 100644 ---- a/drivers/net/ethernet/sfc/efx.c -+++ b/drivers/net/ethernet/sfc/efx.c -@@ -1503,6 +1503,11 @@ static int efx_probe_all(struct efx_nic *efx) - goto fail2; - } - -+ BUILD_BUG_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_RXQ_MIN_ENT); -+ if (WARN_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_TXQ_MIN_ENT(efx))) { -+ rc = -EINVAL; -+ goto fail3; -+ } - efx->rxq_entries = efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE; - - rc = efx_probe_filters(efx); -@@ -2070,6 +2075,7 @@ static int efx_register_netdev(struct efx_nic *efx) - net_dev->irq = efx->pci_dev->irq; - net_dev->netdev_ops = &efx_netdev_ops; - SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops); -+ net_dev->gso_max_segs = EFX_TSO_MAX_SEGS; - - rtnl_lock(); - -diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h -index be8f915..70755c9 100644 ---- a/drivers/net/ethernet/sfc/efx.h -+++ b/drivers/net/ethernet/sfc/efx.h -@@ -30,6 +30,7 @@ extern netdev_tx_t - efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb); - extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index); - extern int efx_setup_tc(struct net_device *net_dev, u8 num_tc); -+extern unsigned int efx_tx_max_skb_descs(struct efx_nic *efx); - - /* RX */ - extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue); -@@ -52,10 +53,15 @@ extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue); - #define EFX_MAX_EVQ_SIZE 16384UL - #define EFX_MIN_EVQ_SIZE 512UL - --/* The smallest [rt]xq_entries that the driver supports. Callers of -- * efx_wake_queue() assume that they can subsequently send at least one -- * skb. Falcon/A1 may require up to three descriptors per skb_frag. */ --#define EFX_MIN_RING_SIZE (roundup_pow_of_two(2 * 3 * MAX_SKB_FRAGS)) -+/* Maximum number of TCP segments we support for soft-TSO */ -+#define EFX_TSO_MAX_SEGS 100 -+ -+/* The smallest [rt]xq_entries that the driver supports. RX minimum -+ * is a bit arbitrary. For TX, we must have space for at least 2 -+ * TSO skbs. -+ */ -+#define EFX_RXQ_MIN_ENT 128U -+#define EFX_TXQ_MIN_ENT(efx) (2 * efx_tx_max_skb_descs(efx)) - - /* Filters */ - extern int efx_probe_filters(struct efx_nic *efx); -diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c -index 10536f9..8cba2df 100644 ---- a/drivers/net/ethernet/sfc/ethtool.c -+++ b/drivers/net/ethernet/sfc/ethtool.c -@@ -680,21 +680,27 @@ static int efx_ethtool_set_ringparam(struct net_device *net_dev, - struct ethtool_ringparam *ring) - { - struct efx_nic *efx = netdev_priv(net_dev); -+ u32 txq_entries; - - if (ring->rx_mini_pending || ring->rx_jumbo_pending || - ring->rx_pending > EFX_MAX_DMAQ_SIZE || - ring->tx_pending > EFX_MAX_DMAQ_SIZE) - return -EINVAL; - -- if (ring->rx_pending < EFX_MIN_RING_SIZE || -- ring->tx_pending < EFX_MIN_RING_SIZE) { -+ if (ring->rx_pending < EFX_RXQ_MIN_ENT) { - netif_err(efx, drv, efx->net_dev, -- "TX and RX queues cannot be smaller than %ld\n", -- EFX_MIN_RING_SIZE); -+ "RX queues cannot be smaller than %u\n", -+ EFX_RXQ_MIN_ENT); - return -EINVAL; - } - -- return efx_realloc_channels(efx, ring->rx_pending, ring->tx_pending); -+ txq_entries = max(ring->tx_pending, EFX_TXQ_MIN_ENT(efx)); -+ if (txq_entries != ring->tx_pending) -+ netif_warn(efx, drv, efx->net_dev, -+ "increasing TX queue size to minimum of %u\n", -+ txq_entries); -+ -+ return efx_realloc_channels(efx, ring->rx_pending, txq_entries); - } - - static int efx_ethtool_set_pauseparam(struct net_device *net_dev, -diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c -index 9b225a7..1871343 100644 ---- a/drivers/net/ethernet/sfc/tx.c -+++ b/drivers/net/ethernet/sfc/tx.c -@@ -119,6 +119,25 @@ efx_max_tx_len(struct efx_nic *efx, dma_addr_t dma_addr) - return len; - } - -+unsigned int efx_tx_max_skb_descs(struct efx_nic *efx) -+{ -+ /* Header and payload descriptor for each output segment, plus -+ * one for every input fragment boundary within a segment -+ */ -+ unsigned int max_descs = EFX_TSO_MAX_SEGS * 2 + MAX_SKB_FRAGS; -+ -+ /* Possibly one more per segment for the alignment workaround */ -+ if (EFX_WORKAROUND_5391(efx)) -+ max_descs += EFX_TSO_MAX_SEGS; -+ -+ /* Possibly more for PCIe page boundaries within input fragments */ -+ if (PAGE_SIZE > EFX_PAGE_SIZE) -+ max_descs += max_t(unsigned int, MAX_SKB_FRAGS, -+ DIV_ROUND_UP(GSO_MAX_SIZE, EFX_PAGE_SIZE)); -+ -+ return max_descs; -+} -+ - /* - * Add a socket buffer to a TX queue - * --- -1.7.7.6 - diff --git a/sources b/sources index a4d0de728..b45a416d5 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 967f72983655e2479f951195953e8480 linux-3.4.tar.xz -2149df47fc96fec05787bf0197fb7b16 patch-3.4.11.xz +4b80842c0edc3d7f37185716160687d0 patch-3.4.12.xz diff --git a/tcp-Apply-device-TSO-segment-limit-earlier.patch b/tcp-Apply-device-TSO-segment-limit-earlier.patch deleted file mode 100644 index d6fa7f49e..000000000 --- a/tcp-Apply-device-TSO-segment-limit-earlier.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 1485348d2424e1131ea42efc033cbd9366462b01 Mon Sep 17 00:00:00 2001 -From: Ben Hutchings -Date: Mon, 30 Jul 2012 16:11:42 +0000 -Subject: [PATCH] tcp: Apply device TSO segment limit earlier - -Cache the device gso_max_segs in sock::sk_gso_max_segs and use it to -limit the size of TSO skbs. This avoids the need to fall back to -software GSO for local TCP senders. - -Signed-off-by: Ben Hutchings -Signed-off-by: David S. Miller ---- - include/net/sock.h | 2 ++ - net/core/sock.c | 1 + - net/ipv4/tcp.c | 4 +++- - net/ipv4/tcp_cong.c | 3 ++- - net/ipv4/tcp_output.c | 21 ++++++++++++--------- - 5 files changed, 20 insertions(+), 11 deletions(-) - ---- linux-3.4.noarch.orig/include/net/sock.h -+++ linux-3.4.noarch/include/net/sock.h -@@ -216,6 +216,7 @@ struct cg_proto; - * @sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK) - * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4) - * @sk_gso_max_size: Maximum GSO segment size to build -+ * @sk_gso_max_segs: Maximum number of GSO segments - * @sk_lingertime: %SO_LINGER l_linger setting - * @sk_backlog: always used with the per-socket spinlock held - * @sk_callback_lock: used with the callbacks in the end of this struct -@@ -335,6 +336,7 @@ struct sock { - netdev_features_t sk_route_nocaps; - int sk_gso_type; - unsigned int sk_gso_max_size; -+ u16 sk_gso_max_segs; - int sk_rcvlowat; - unsigned long sk_lingertime; - struct sk_buff_head sk_error_queue; ---- linux-3.4.noarch.orig/net/core/sock.c -+++ linux-3.4.noarch/net/core/sock.c -@@ -1411,6 +1411,7 @@ void sk_setup_caps(struct sock *sk, stru - } else { - sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; - sk->sk_gso_max_size = dst->dev->gso_max_size; -+ sk->sk_gso_max_segs = dst->dev->gso_max_segs; - } - } - } ---- linux-3.4.noarch.orig/net/ipv4/tcp.c -+++ linux-3.4.noarch/net/ipv4/tcp.c -@@ -740,7 +740,9 @@ static unsigned int tcp_xmit_size_goal(s - old_size_goal + mss_now > xmit_size_goal)) { - xmit_size_goal = old_size_goal; - } else { -- tp->xmit_size_goal_segs = xmit_size_goal / mss_now; -+ tp->xmit_size_goal_segs = -+ min_t(u16, xmit_size_goal / mss_now, -+ sk->sk_gso_max_segs); - xmit_size_goal = tp->xmit_size_goal_segs * mss_now; - } - } ---- linux-3.4.noarch.orig/net/ipv4/tcp_cong.c -+++ linux-3.4.noarch/net/ipv4/tcp_cong.c -@@ -291,7 +291,8 @@ int tcp_is_cwnd_limited(const struct soc - left = tp->snd_cwnd - in_flight; - if (sk_can_gso(sk) && - left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd && -- left * tp->mss_cache < sk->sk_gso_max_size) -+ left * tp->mss_cache < sk->sk_gso_max_size && -+ left < sk->sk_gso_max_segs) - return 1; - return left <= tcp_max_tso_deferred_mss(tp); - } ---- linux-3.4.noarch.orig/net/ipv4/tcp_output.c -+++ linux-3.4.noarch/net/ipv4/tcp_output.c -@@ -1318,21 +1318,21 @@ static void tcp_cwnd_validate(struct soc - * when we would be allowed to send the split-due-to-Nagle skb fully. - */ - static unsigned int tcp_mss_split_point(const struct sock *sk, const struct sk_buff *skb, -- unsigned int mss_now, unsigned int cwnd) -+ unsigned int mss_now, unsigned int max_segs) - { - const struct tcp_sock *tp = tcp_sk(sk); -- u32 needed, window, cwnd_len; -+ u32 needed, window, max_len; - - window = tcp_wnd_end(tp) - TCP_SKB_CB(skb)->seq; -- cwnd_len = mss_now * cwnd; -+ max_len = mss_now * max_segs; - -- if (likely(cwnd_len <= window && skb != tcp_write_queue_tail(sk))) -- return cwnd_len; -+ if (likely(max_len <= window && skb != tcp_write_queue_tail(sk))) -+ return max_len; - - needed = min(skb->len, window); - -- if (cwnd_len <= needed) -- return cwnd_len; -+ if (max_len <= needed) -+ return max_len; - - return needed - needed % mss_now; - } -@@ -1560,7 +1560,8 @@ static int tcp_tso_should_defer(struct s - limit = min(send_win, cong_win); - - /* If a full-sized TSO skb can be sent, do it. */ -- if (limit >= sk->sk_gso_max_size) -+ if (limit >= min_t(unsigned int, sk->sk_gso_max_size, -+ sk->sk_gso_max_segs * tp->mss_cache)) - goto send_now; - - /* Middle in queue won't get any more data, full sendable already? */ -@@ -1786,7 +1787,9 @@ static int tcp_write_xmit(struct sock *s - limit = mss_now; - if (tso_segs > 1 && !tcp_urg_mode(tp)) - limit = tcp_mss_split_point(sk, skb, mss_now, -- cwnd_quota); -+ min_t(unsigned int, -+ cwnd_quota, -+ sk->sk_gso_max_segs)); - - if (skb->len > limit && - unlikely(tso_fragment(sk, skb, limit, mss_now, gfp))) From 10aac2362f49cc369898039ba8a5c22f192202d2 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 3 Oct 2012 08:23:43 -0400 Subject: [PATCH 432/487] Make sure kernel-tools-libs-devel provides kernel-tools-devel --- kernel.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 097920ba4..bb643c20c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -806,6 +806,7 @@ Requires: kernel-tools = %{version}-%{release} Provides: cpupowerutils-devel = 1:009-0.6.p1 Obsoletes: cpupowerutils-devel < 1:009-0.6.p1 Requires: kernel-tools-libs = %{version}-%{release} +Provides: kernel-tools-devel %description -n kernel-tools-libs-devel This package contains the development files for the tools/ directory from the kernel source. @@ -2027,6 +2028,9 @@ fi # and build. %changelog +* Wed Oct 03 2012 Josh Boyer +- Make sure kernel-tools-libs-devel provides kernel-tools-devel + * Tue Oct 02 2012 Dave Jones 3.4.12-1 - Linux v3.4.12 merged: drm-radeon-force-dma32-to-fix-regression-rs4xx-rs6xx.patch From e23703485a6401d79e3ad23876ec3f055d9959af Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 11 Oct 2012 11:30:02 -0400 Subject: [PATCH 433/487] Linux 3.4.13 --- kernel.spec | 5 ++++- sources | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index bb643c20c..8c527e389 100644 --- a/kernel.spec +++ b/kernel.spec @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 12 +%define stable_update 13 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2028,6 +2028,9 @@ fi # and build. %changelog +* Thu Oct 11 2012 Dave Jones +- Linux 3.4.13 + * Wed Oct 03 2012 Josh Boyer - Make sure kernel-tools-libs-devel provides kernel-tools-devel diff --git a/sources b/sources index b45a416d5..72b028409 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 967f72983655e2479f951195953e8480 linux-3.4.tar.xz -4b80842c0edc3d7f37185716160687d0 patch-3.4.12.xz +65c1d3da2074c552e0a405a1c2f44310 patch-3.4.13.xz From 985716fccdbcaa2746f9823c3d8b2cf6be726b01 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 11 Oct 2012 11:30:31 -0400 Subject: [PATCH 434/487] fix version --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 8c527e389..a58953866 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2028,7 +2028,7 @@ fi # and build. %changelog -* Thu Oct 11 2012 Dave Jones +* Thu Oct 11 2012 Dave Jones 3.4.13-1 - Linux 3.4.13 * Wed Oct 03 2012 Josh Boyer From 6bedaf46ce47918d618084d780a7a9647032efe3 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 16 Oct 2012 09:48:40 -0400 Subject: [PATCH 435/487] Linux 3.4.14 --- ...s-suspend-Dont-modify-cpusets-during.patch | 139 ------------------ kernel.spec | 11 +- sources | 2 +- 3 files changed, 5 insertions(+), 147 deletions(-) delete mode 100644 CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch diff --git a/CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch b/CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch deleted file mode 100644 index f57eceed9..000000000 --- a/CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 0c1508129adc051fabaf8debefea79baa2f1a81b Mon Sep 17 00:00:00 2001 -From: "Srivatsa S. Bhat" -Date: Thu, 24 May 2012 19:46:26 +0530 -Subject: [PATCH] CPU hotplug, cpusets, suspend: Don't modify cpusets during - suspend/resume - -In the event of CPU hotplug, the kernel modifies the cpusets' cpus_allowed -masks as and when necessary to ensure that the tasks belonging to the cpusets -have some place (online CPUs) to run on. And regular CPU hotplug is -destructive in the sense that the kernel doesn't remember the original cpuset -configurations set by the user, across hotplug operations. - -However, suspend/resume (which uses CPU hotplug) is a special case in which -the kernel has the responsibility to restore the system (during resume), to -exactly the same state it was in before suspend. - -In order to achieve that, do the following: - -1. Don't modify cpusets during suspend/resume. At all. - In particular, don't move the tasks from one cpuset to another, and - don't modify any cpuset's cpus_allowed mask. So, simply ignore cpusets - during the CPU hotplug operations that are carried out in the - suspend/resume path. - -2. However, cpusets and sched domains are related. We just want to avoid - altering cpusets alone. So, to keep the sched domains updated, build - a single sched domain (containing all active cpus) during each of the - CPU hotplug operations carried out in s/r path, effectively ignoring - the cpusets' cpus_allowed masks. - - (Since userspace is frozen while doing all this, it will go unnoticed.) - -3. During the last CPU online operation during resume, build the sched - domains by looking up the (unaltered) cpusets' cpus_allowed masks. - That will bring back the system to the same original state as it was in - before suspend. - -Ultimately, this will not only solve the cpuset problem related to suspend -resume (ie., restores the cpusets to exactly what it was before suspend, by -not touching it at all) but also speeds up suspend/resume because we avoid -running cpuset update code for every CPU being offlined/onlined. - -Signed-off-by: Srivatsa S. Bhat -Signed-off-by: Peter Zijlstra -Cc: Linus Torvalds -Cc: Andrew Morton -Cc: Thomas Gleixner -Link: http://lkml.kernel.org/r/20120524141611.3692.20155.stgit@srivatsabhat.in.ibm.com -Signed-off-by: Ingo Molnar ---- - kernel/cpuset.c | 3 +++ - kernel/sched/core.c | 40 ++++++++++++++++++++++++++++++++++++---- - 2 files changed, 39 insertions(+), 4 deletions(-) - ---- linux-3.4.6-3.1.fc17.noarch.orig/kernel/cpuset.c -+++ linux-3.4.6-3.1.fc17.noarch/kernel/cpuset.c -@@ -2065,6 +2065,9 @@ static void scan_for_empty_cpusets(struc - * (of no affect) on systems that are actively using CPU hotplug - * but making no active use of cpusets. - * -+ * The only exception to this is suspend/resume, where we don't -+ * modify cpusets at all. -+ * - * This routine ensures that top_cpuset.cpus_allowed tracks - * cpu_active_mask on each CPU hotplug (cpuhp) event. - * ---- linux-3.4.6-3.1.fc17.noarch.orig/kernel/sched/core.c -+++ linux-3.4.6-3.1.fc17.noarch/kernel/sched/core.c -@@ -6931,34 +6931,66 @@ int __init sched_create_sysfs_power_savi - } - #endif /* CONFIG_SCHED_MC || CONFIG_SCHED_SMT */ - -+static int num_cpus_frozen; /* used to mark begin/end of suspend/resume */ -+ - /* - * Update cpusets according to cpu_active mask. If cpusets are - * disabled, cpuset_update_active_cpus() becomes a simple wrapper - * around partition_sched_domains(). -+ * -+ * If we come here as part of a suspend/resume, don't touch cpusets because we -+ * want to restore it back to its original state upon resume anyway. - */ - static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action, - void *hcpu) - { -- switch (action & ~CPU_TASKS_FROZEN) { -+ switch (action) { -+ case CPU_ONLINE_FROZEN: -+ case CPU_DOWN_FAILED_FROZEN: -+ -+ /* -+ * num_cpus_frozen tracks how many CPUs are involved in suspend -+ * resume sequence. As long as this is not the last online -+ * operation in the resume sequence, just build a single sched -+ * domain, ignoring cpusets. -+ */ -+ num_cpus_frozen--; -+ if (likely(num_cpus_frozen)) { -+ partition_sched_domains(1, NULL, NULL); -+ break; -+ } -+ -+ /* -+ * This is the last CPU online operation. So fall through and -+ * restore the original sched domains by considering the -+ * cpuset configurations. -+ */ -+ - case CPU_ONLINE: - case CPU_DOWN_FAILED: - cpuset_update_active_cpus(); -- return NOTIFY_OK; -+ break; - default: - return NOTIFY_DONE; - } -+ return NOTIFY_OK; - } - - static int cpuset_cpu_inactive(struct notifier_block *nfb, unsigned long action, - void *hcpu) - { -- switch (action & ~CPU_TASKS_FROZEN) { -+ switch (action) { - case CPU_DOWN_PREPARE: - cpuset_update_active_cpus(); -- return NOTIFY_OK; -+ break; -+ case CPU_DOWN_PREPARE_FROZEN: -+ num_cpus_frozen++; -+ partition_sched_domains(1, NULL, NULL); -+ break; - default: - return NOTIFY_DONE; - } -+ return NOTIFY_OK; - } - - void __init sched_init_smp(void) diff --git a/kernel.spec b/kernel.spec index a58953866..d37818baa 100644 --- a/kernel.spec +++ b/kernel.spec @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 13 +%define stable_update 14 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -703,9 +703,6 @@ Patch22018: atl1c_net_next_update-3.4.patch Patch22055: crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch Patch22056: crypto-aesni-intel-fix-wrong-kfree-pointer.patch -#rhbz 714271 -Patch22060: CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch - # END OF PATCH DEFINITIONS %endif @@ -1325,9 +1322,6 @@ ApplyPatch atl1c_net_next_update-3.4.patch ApplyPatch crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch ApplyPatch crypto-aesni-intel-fix-wrong-kfree-pointer.patch -#rhbz 714271 -ApplyPatch CPU-hotplug-cpusets-suspend-Dont-modify-cpusets-during.patch - # END OF PATCH APPLICATIONS %endif @@ -2028,6 +2022,9 @@ fi # and build. %changelog +* Tue Oct 16 2012 Dave Jones 3.4.14-1 +- Linux 3.4.14 + * Thu Oct 11 2012 Dave Jones 3.4.13-1 - Linux 3.4.13 diff --git a/sources b/sources index 72b028409..40daba29f 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 967f72983655e2479f951195953e8480 linux-3.4.tar.xz -65c1d3da2074c552e0a405a1c2f44310 patch-3.4.13.xz +c3225a0538db8486d991c1af70f5f0a4 patch-3.4.14.xz From f692e37cf5b02cc4341a78f65f49589747bae80a Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 16 Oct 2012 14:00:18 -0400 Subject: [PATCH 436/487] Linux 3.5 --- atl1c_net_next_update-3.4.patch | 3657 --------- config-generic | 87 +- config-powerpc-generic | 4 + config-powerpc64 | 5 + config-s390x | 1 + config-sparc64-generic | 3 + config-x86-32-generic | 4 + config-x86-generic | 5 + drm-i915-fbc-stfu.patch | 102 - ...e-sb-s_first-in-journal_get_superblo.patch | 95 - kernel.spec | 32 +- linux-2.6-input-kill-stupid-messages.patch | 20 +- linux-2.6-makefile-after_link.patch | 100 +- ...validate_disk-prevent-NULL-ptr-deref.patch | 2 +- sources | 3 +- uprobes-3.4-backport.patch | 6983 ----------------- uprobes-3.4-tip.patch | 915 --- uprobes-backport.patch | 1742 ++++ 18 files changed, 1908 insertions(+), 11852 deletions(-) delete mode 100644 atl1c_net_next_update-3.4.patch delete mode 100644 drm-i915-fbc-stfu.patch delete mode 100644 jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch delete mode 100644 uprobes-3.4-backport.patch delete mode 100644 uprobes-3.4-tip.patch create mode 100644 uprobes-backport.patch diff --git a/atl1c_net_next_update-3.4.patch b/atl1c_net_next_update-3.4.patch deleted file mode 100644 index 94422b124..000000000 --- a/atl1c_net_next_update-3.4.patch +++ /dev/null @@ -1,3657 +0,0 @@ -diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c.h b/drivers/net/ethernet/atheros/atl1c/atl1c.h -index ca70e16..b2bf324 100644 ---- a/drivers/net/ethernet/atheros/atl1c/atl1c.h -+++ b/drivers/net/ethernet/atheros/atl1c/atl1c.h -@@ -74,8 +74,6 @@ - - #define AT_RX_BUF_SIZE (ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN) - #define MAX_JUMBO_FRAME_SIZE (6*1024) --#define MAX_TSO_FRAME_SIZE (7*1024) --#define MAX_TX_OFFLOAD_THRESH (9*1024) - - #define AT_MAX_RECEIVE_QUEUE 4 - #define AT_DEF_RECEIVE_QUEUE 1 -@@ -100,7 +98,7 @@ - #define ATL1C_ASPM_L0s_ENABLE 0x0001 - #define ATL1C_ASPM_L1_ENABLE 0x0002 - --#define AT_REGS_LEN (75 * sizeof(u32)) -+#define AT_REGS_LEN (74 * sizeof(u32)) - #define AT_EEPROM_LEN 512 - - #define ATL1C_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i])) -@@ -297,20 +295,6 @@ enum atl1c_dma_req_block { - atl1c_dma_req_4096 = 5 - }; - --enum atl1c_rss_mode { -- atl1c_rss_mode_disable = 0, -- atl1c_rss_sig_que = 1, -- atl1c_rss_mul_que_sig_int = 2, -- atl1c_rss_mul_que_mul_int = 4, --}; -- --enum atl1c_rss_type { -- atl1c_rss_disable = 0, -- atl1c_rss_ipv4 = 1, -- atl1c_rss_ipv4_tcp = 2, -- atl1c_rss_ipv6 = 4, -- atl1c_rss_ipv6_tcp = 8 --}; - - enum atl1c_nic_type { - athr_l1c = 0, -@@ -388,7 +372,6 @@ struct atl1c_hw { - enum atl1c_dma_order dma_order; - enum atl1c_dma_rcb rcb_value; - enum atl1c_dma_req_block dmar_block; -- enum atl1c_dma_req_block dmaw_block; - - u16 device_id; - u16 vendor_id; -@@ -399,8 +382,6 @@ struct atl1c_hw { - u16 phy_id2; - - u32 intr_mask; -- u8 dmaw_dly_cnt; -- u8 dmar_dly_cnt; - - u8 preamble_len; - u16 max_frame_size; -@@ -440,10 +421,6 @@ struct atl1c_hw { - #define ATL1C_FPGA_VERSION 0x8000 - u16 link_cap_flags; - #define ATL1C_LINK_CAP_1000M 0x0001 -- u16 cmb_tpd; -- u16 cmb_rrd; -- u16 cmb_rx_timer; /* 2us resolution */ -- u16 cmb_tx_timer; - u32 smb_timer; - - u16 rrd_thresh; /* Threshold of number of RRD produced to trigger -@@ -451,9 +428,6 @@ struct atl1c_hw { - u16 tpd_thresh; - u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. */ - u8 rfd_burst; -- enum atl1c_rss_type rss_type; -- enum atl1c_rss_mode rss_mode; -- u8 rss_hash_bits; - u32 base_cpu; - u32 indirect_tab; - u8 mac_addr[ETH_ALEN]; -@@ -462,12 +436,12 @@ struct atl1c_hw { - bool phy_configured; - bool re_autoneg; - bool emi_ca; -+ bool msi_lnkpatch; /* link patch for specific platforms */ - }; - - /* - * atl1c_ring_header represents a single, contiguous block of DMA space -- * mapped for the three descriptor rings (tpd, rfd, rrd) and the two -- * message blocks (cmb, smb) described below -+ * mapped for the three descriptor rings (tpd, rfd, rrd) described below - */ - struct atl1c_ring_header { - void *desc; /* virtual address */ -@@ -541,16 +515,6 @@ struct atl1c_rrd_ring { - u16 next_to_clean; - }; - --struct atl1c_cmb { -- void *cmb; -- dma_addr_t dma; --}; -- --struct atl1c_smb { -- void *smb; -- dma_addr_t dma; --}; -- - /* board specific private data structure */ - struct atl1c_adapter { - struct net_device *netdev; -@@ -586,11 +550,8 @@ struct atl1c_adapter { - /* All Descriptor memory */ - struct atl1c_ring_header ring_header; - struct atl1c_tpd_ring tpd_ring[AT_MAX_TRANSMIT_QUEUE]; -- struct atl1c_rfd_ring rfd_ring[AT_MAX_RECEIVE_QUEUE]; -- struct atl1c_rrd_ring rrd_ring[AT_MAX_RECEIVE_QUEUE]; -- struct atl1c_cmb cmb; -- struct atl1c_smb smb; -- int num_rx_queues; -+ struct atl1c_rfd_ring rfd_ring; -+ struct atl1c_rrd_ring rrd_ring; - u32 bd_number; /* board number;*/ - }; - -@@ -618,8 +579,14 @@ struct atl1c_adapter { - #define AT_WRITE_REGW(a, reg, value) (\ - writew((value), ((a)->hw_addr + reg))) - --#define AT_READ_REGW(a, reg) (\ -- readw((a)->hw_addr + reg)) -+#define AT_READ_REGW(a, reg, pdata) do { \ -+ if (unlikely((a)->hibernate)) { \ -+ readw((a)->hw_addr + reg); \ -+ *(u16 *)pdata = readw((a)->hw_addr + reg); \ -+ } else { \ -+ *(u16 *)pdata = readw((a)->hw_addr + reg); \ -+ } \ -+ } while (0) - - #define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \ - writel((value), (((a)->hw_addr + reg) + ((offset) << 2)))) -diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c -index 0a9326a..859ea84 100644 ---- a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c -+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c -@@ -141,8 +141,7 @@ static void atl1c_get_regs(struct net_device *netdev, - - memset(p, 0, AT_REGS_LEN); - -- regs->version = 0; -- AT_READ_REG(hw, REG_VPD_CAP, p++); -+ regs->version = 1; - AT_READ_REG(hw, REG_PM_CTRL, p++); - AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL, p++); - AT_READ_REG(hw, REG_TWSI_CTRL, p++); -@@ -154,7 +153,7 @@ static void atl1c_get_regs(struct net_device *netdev, - AT_READ_REG(hw, REG_LINK_CTRL, p++); - AT_READ_REG(hw, REG_IDLE_STATUS, p++); - AT_READ_REG(hw, REG_MDIO_CTRL, p++); -- AT_READ_REG(hw, REG_SERDES_LOCK, p++); -+ AT_READ_REG(hw, REG_SERDES, p++); - AT_READ_REG(hw, REG_MAC_CTRL, p++); - AT_READ_REG(hw, REG_MAC_IPG_IFG, p++); - AT_READ_REG(hw, REG_MAC_STA_ADDR, p++); -@@ -167,9 +166,9 @@ static void atl1c_get_regs(struct net_device *netdev, - AT_READ_REG(hw, REG_WOL_CTRL, p++); - - atl1c_read_phy_reg(hw, MII_BMCR, &phy_data); -- regs_buff[73] = (u32) phy_data; -+ regs_buff[AT_REGS_LEN/sizeof(u32) - 2] = (u32) phy_data; - atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); -- regs_buff[74] = (u32) phy_data; -+ regs_buff[AT_REGS_LEN/sizeof(u32) - 1] = (u32) phy_data; - } - - static int atl1c_get_eeprom_len(struct net_device *netdev) -diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c -index bd1667c..ff9c738 100644 ---- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c -+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c -@@ -43,7 +43,7 @@ int atl1c_check_eeprom_exist(struct atl1c_hw *hw) - return 0; - } - --void atl1c_hw_set_mac_addr(struct atl1c_hw *hw) -+void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr) - { - u32 value; - /* -@@ -51,35 +51,48 @@ void atl1c_hw_set_mac_addr(struct atl1c_hw *hw) - * 0: 6AF600DC 1: 000B - * low dword - */ -- value = (((u32)hw->mac_addr[2]) << 24) | -- (((u32)hw->mac_addr[3]) << 16) | -- (((u32)hw->mac_addr[4]) << 8) | -- (((u32)hw->mac_addr[5])) ; -+ value = mac_addr[2] << 24 | -+ mac_addr[3] << 16 | -+ mac_addr[4] << 8 | -+ mac_addr[5]; - AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value); - /* hight dword */ -- value = (((u32)hw->mac_addr[0]) << 8) | -- (((u32)hw->mac_addr[1])) ; -+ value = mac_addr[0] << 8 | -+ mac_addr[1]; - AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value); - } - -+/* read mac address from hardware register */ -+static bool atl1c_read_current_addr(struct atl1c_hw *hw, u8 *eth_addr) -+{ -+ u32 addr[2]; -+ -+ AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]); -+ AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]); -+ -+ *(u32 *) ð_addr[2] = htonl(addr[0]); -+ *(u16 *) ð_addr[0] = htons((u16)addr[1]); -+ -+ return is_valid_ether_addr(eth_addr); -+} -+ - /* - * atl1c_get_permanent_address - * return 0 if get valid mac address, - */ - static int atl1c_get_permanent_address(struct atl1c_hw *hw) - { -- u32 addr[2]; - u32 i; - u32 otp_ctrl_data; - u32 twsi_ctrl_data; -- u32 ltssm_ctrl_data; -- u32 wol_data; -- u8 eth_addr[ETH_ALEN]; - u16 phy_data; - bool raise_vol = false; - -+ /* MAC-address from BIOS is the 1st priority */ -+ if (atl1c_read_current_addr(hw, hw->perm_mac_addr)) -+ return 0; -+ - /* init */ -- addr[0] = addr[1] = 0; - AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data); - if (atl1c_check_eeprom_exist(hw)) { - if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) { -@@ -91,33 +104,17 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw) - msleep(1); - } - } -- -- if (hw->nic_type == athr_l2c_b || -- hw->nic_type == athr_l2c_b2 || -- hw->nic_type == athr_l1d) { -- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00); -- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) -- goto out; -- phy_data &= 0xFF7F; -- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); -- -- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B); -- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) -- goto out; -- phy_data |= 0x8; -- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); -+ /* raise voltage temporally for l2cb */ -+ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { -+ atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data); -+ phy_data &= ~ANACTRL_HB_EN; -+ atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data); -+ atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); -+ phy_data |= VOLT_CTRL_SWLOWEST; -+ atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); - udelay(20); - raise_vol = true; - } -- /* close open bit of ReadOnly*/ -- AT_READ_REG(hw, REG_LTSSM_ID_CTRL, <ssm_ctrl_data); -- ltssm_ctrl_data &= ~LTSSM_ID_EN_WRO; -- AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, ltssm_ctrl_data); -- -- /* clear any WOL settings */ -- AT_WRITE_REG(hw, REG_WOL_CTRL, 0); -- AT_READ_REG(hw, REG_WOL_CTRL, &wol_data); -- - - AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data); - twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART; -@@ -138,37 +135,18 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw) - msleep(1); - } - if (raise_vol) { -- if (hw->nic_type == athr_l2c_b || -- hw->nic_type == athr_l2c_b2 || -- hw->nic_type == athr_l1d || -- hw->nic_type == athr_l1d_2) { -- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00); -- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) -- goto out; -- phy_data |= 0x80; -- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); -- -- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B); -- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) -- goto out; -- phy_data &= 0xFFF7; -- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); -- udelay(20); -- } -+ atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data); -+ phy_data |= ANACTRL_HB_EN; -+ atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data); -+ atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); -+ phy_data &= ~VOLT_CTRL_SWLOWEST; -+ atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); -+ udelay(20); - } - -- /* maybe MAC-address is from BIOS */ -- AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]); -- AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]); -- *(u32 *) ð_addr[2] = swab32(addr[0]); -- *(u16 *) ð_addr[0] = swab16(*(u16 *)&addr[1]); -- -- if (is_valid_ether_addr(eth_addr)) { -- memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN); -+ if (atl1c_read_current_addr(hw, hw->perm_mac_addr)) - return 0; -- } - --out: - return -1; - } - -@@ -278,33 +256,158 @@ void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value) - } - - /* -- * Reads the value from a PHY register -- * hw - Struct containing variables accessed by shared code -- * reg_addr - address of the PHY register to read -+ * wait mdio module be idle -+ * return true: idle -+ * false: still busy - */ --int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) -+bool atl1c_wait_mdio_idle(struct atl1c_hw *hw) - { - u32 val; - int i; - -- val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT | -- MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | -- MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; -+ for (i = 0; i < MDIO_MAX_AC_TO; i++) { -+ AT_READ_REG(hw, REG_MDIO_CTRL, &val); -+ if (!(val & (MDIO_CTRL_BUSY | MDIO_CTRL_START))) -+ break; -+ udelay(10); -+ } -+ -+ return i != MDIO_MAX_AC_TO; -+} -+ -+void atl1c_stop_phy_polling(struct atl1c_hw *hw) -+{ -+ if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION)) -+ return; -+ -+ AT_WRITE_REG(hw, REG_MDIO_CTRL, 0); -+ atl1c_wait_mdio_idle(hw); -+} -+ -+void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel) -+{ -+ u32 val; -+ -+ if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION)) -+ return; - -+ val = MDIO_CTRL_SPRES_PRMBL | -+ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | -+ FIELDX(MDIO_CTRL_REG, 1) | -+ MDIO_CTRL_START | -+ MDIO_CTRL_OP_READ; -+ AT_WRITE_REG(hw, REG_MDIO_CTRL, val); -+ atl1c_wait_mdio_idle(hw); -+ val |= MDIO_CTRL_AP_EN; -+ val &= ~MDIO_CTRL_START; - AT_WRITE_REG(hw, REG_MDIO_CTRL, val); -+ udelay(30); -+} - -- for (i = 0; i < MDIO_WAIT_TIMES; i++) { -- udelay(2); -- AT_READ_REG(hw, REG_MDIO_CTRL, &val); -- if (!(val & (MDIO_START | MDIO_BUSY))) -- break; -+ -+/* -+ * atl1c_read_phy_core -+ * core funtion to read register in PHY via MDIO control regsiter. -+ * ext: extension register (see IEEE 802.3) -+ * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0) -+ * reg: reg to read -+ */ -+int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, -+ u16 reg, u16 *phy_data) -+{ -+ u32 val; -+ u16 clk_sel = MDIO_CTRL_CLK_25_4; -+ -+ atl1c_stop_phy_polling(hw); -+ -+ *phy_data = 0; -+ -+ /* only l2c_b2 & l1d_2 could use slow clock */ -+ if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) && -+ hw->hibernate) -+ clk_sel = MDIO_CTRL_CLK_25_128; -+ if (ext) { -+ val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg); -+ AT_WRITE_REG(hw, REG_MDIO_EXTN, val); -+ val = MDIO_CTRL_SPRES_PRMBL | -+ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | -+ MDIO_CTRL_START | -+ MDIO_CTRL_MODE_EXT | -+ MDIO_CTRL_OP_READ; -+ } else { -+ val = MDIO_CTRL_SPRES_PRMBL | -+ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | -+ FIELDX(MDIO_CTRL_REG, reg) | -+ MDIO_CTRL_START | -+ MDIO_CTRL_OP_READ; - } -- if (!(val & (MDIO_START | MDIO_BUSY))) { -- *phy_data = (u16)val; -- return 0; -+ AT_WRITE_REG(hw, REG_MDIO_CTRL, val); -+ -+ if (!atl1c_wait_mdio_idle(hw)) -+ return -1; -+ -+ AT_READ_REG(hw, REG_MDIO_CTRL, &val); -+ *phy_data = (u16)FIELD_GETX(val, MDIO_CTRL_DATA); -+ -+ atl1c_start_phy_polling(hw, clk_sel); -+ -+ return 0; -+} -+ -+/* -+ * atl1c_write_phy_core -+ * core funtion to write to register in PHY via MDIO control regsiter. -+ * ext: extension register (see IEEE 802.3) -+ * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0) -+ * reg: reg to write -+ */ -+int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, -+ u16 reg, u16 phy_data) -+{ -+ u32 val; -+ u16 clk_sel = MDIO_CTRL_CLK_25_4; -+ -+ atl1c_stop_phy_polling(hw); -+ -+ -+ /* only l2c_b2 & l1d_2 could use slow clock */ -+ if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) && -+ hw->hibernate) -+ clk_sel = MDIO_CTRL_CLK_25_128; -+ -+ if (ext) { -+ val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg); -+ AT_WRITE_REG(hw, REG_MDIO_EXTN, val); -+ val = MDIO_CTRL_SPRES_PRMBL | -+ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | -+ FIELDX(MDIO_CTRL_DATA, phy_data) | -+ MDIO_CTRL_START | -+ MDIO_CTRL_MODE_EXT; -+ } else { -+ val = MDIO_CTRL_SPRES_PRMBL | -+ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | -+ FIELDX(MDIO_CTRL_DATA, phy_data) | -+ FIELDX(MDIO_CTRL_REG, reg) | -+ MDIO_CTRL_START; - } -+ AT_WRITE_REG(hw, REG_MDIO_CTRL, val); - -- return -1; -+ if (!atl1c_wait_mdio_idle(hw)) -+ return -1; -+ -+ atl1c_start_phy_polling(hw, clk_sel); -+ -+ return 0; -+} -+ -+/* -+ * Reads the value from a PHY register -+ * hw - Struct containing variables accessed by shared code -+ * reg_addr - address of the PHY register to read -+ */ -+int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) -+{ -+ return atl1c_read_phy_core(hw, false, 0, reg_addr, phy_data); - } - - /* -@@ -315,27 +418,47 @@ int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) - */ - int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data) - { -- int i; -- u32 val; -+ return atl1c_write_phy_core(hw, false, 0, reg_addr, phy_data); -+} - -- val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT | -- (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT | -- MDIO_SUP_PREAMBLE | MDIO_START | -- MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; -+/* read from PHY extension register */ -+int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr, -+ u16 reg_addr, u16 *phy_data) -+{ -+ return atl1c_read_phy_core(hw, true, dev_addr, reg_addr, phy_data); -+} - -- AT_WRITE_REG(hw, REG_MDIO_CTRL, val); -+/* write to PHY extension register */ -+int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr, -+ u16 reg_addr, u16 phy_data) -+{ -+ return atl1c_write_phy_core(hw, true, dev_addr, reg_addr, phy_data); -+} - -- for (i = 0; i < MDIO_WAIT_TIMES; i++) { -- udelay(2); -- AT_READ_REG(hw, REG_MDIO_CTRL, &val); -- if (!(val & (MDIO_START | MDIO_BUSY))) -- break; -- } -+int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) -+{ -+ int err; - -- if (!(val & (MDIO_START | MDIO_BUSY))) -- return 0; -+ err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr); -+ if (unlikely(err)) -+ return err; -+ else -+ err = atl1c_read_phy_reg(hw, MII_DBG_DATA, phy_data); - -- return -1; -+ return err; -+} -+ -+int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data) -+{ -+ int err; -+ -+ err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr); -+ if (unlikely(err)) -+ return err; -+ else -+ err = atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); -+ -+ return err; - } - - /* -@@ -380,119 +503,100 @@ static int atl1c_phy_setup_adv(struct atl1c_hw *hw) - - void atl1c_phy_disable(struct atl1c_hw *hw) - { -- AT_WRITE_REGW(hw, REG_GPHY_CTRL, -- GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET); -+ atl1c_power_saving(hw, 0); - } - --static void atl1c_phy_magic_data(struct atl1c_hw *hw) --{ -- u16 data; -- -- data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE | -- ((1 & ANA_INTERVAL_SEL_TIMER_MASK) << -- ANA_INTERVAL_SEL_TIMER_SHIFT); -- -- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_18); -- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); -- -- data = (2 & ANA_SERDES_CDR_BW_MASK) | ANA_MS_PAD_DBG | -- ANA_SERDES_EN_DEEM | ANA_SERDES_SEL_HSP | ANA_SERDES_EN_PLL | -- ANA_SERDES_EN_LCKDT; -- -- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_5); -- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); -- -- data = (44 & ANA_LONG_CABLE_TH_100_MASK) | -- ((33 & ANA_SHORT_CABLE_TH_100_MASK) << -- ANA_SHORT_CABLE_TH_100_SHIFT) | ANA_BP_BAD_LINK_ACCUM | -- ANA_BP_SMALL_BW; -- -- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_54); -- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); -- -- data = (11 & ANA_IECHO_ADJ_MASK) | ((11 & ANA_IECHO_ADJ_MASK) << -- ANA_IECHO_ADJ_2_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) << -- ANA_IECHO_ADJ_1_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) << -- ANA_IECHO_ADJ_0_SHIFT); -- -- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_4); -- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); -- -- data = ANA_RESTART_CAL | ((7 & ANA_MANUL_SWICH_ON_MASK) << -- ANA_MANUL_SWICH_ON_SHIFT) | ANA_MAN_ENABLE | -- ANA_SEL_HSP | ANA_EN_HB | ANA_OEN_125M; -- -- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_0); -- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); -- -- if (hw->ctrl_flags & ATL1C_HIB_DISABLE) { -- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_41); -- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0) -- return; -- data &= ~ANA_TOP_PS_EN; -- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); -- -- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_11); -- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0) -- return; -- data &= ~ANA_PS_HIB_EN; -- atl1c_write_phy_reg(hw, MII_DBG_DATA, data); -- } --} - - int atl1c_phy_reset(struct atl1c_hw *hw) - { - struct atl1c_adapter *adapter = hw->adapter; - struct pci_dev *pdev = adapter->pdev; - u16 phy_data; -- u32 phy_ctrl_data = GPHY_CTRL_DEFAULT; -- u32 mii_ier_data = IER_LINK_UP | IER_LINK_DOWN; -+ u32 phy_ctrl_data, lpi_ctrl; - int err; - -- if (hw->ctrl_flags & ATL1C_HIB_DISABLE) -- phy_ctrl_data &= ~GPHY_CTRL_HIB_EN; -- -+ /* reset PHY core */ -+ AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl_data); -+ phy_ctrl_data &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_PHY_IDDQ | -+ GPHY_CTRL_GATE_25M_EN | GPHY_CTRL_PWDOWN_HW | GPHY_CTRL_CLS); -+ phy_ctrl_data |= GPHY_CTRL_SEL_ANA_RST; -+ if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE)) -+ phy_ctrl_data |= (GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE); -+ else -+ phy_ctrl_data &= ~(GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE); - AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data); - AT_WRITE_FLUSH(hw); -- msleep(40); -- phy_ctrl_data |= GPHY_CTRL_EXT_RESET; -- AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data); -+ udelay(10); -+ AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data | GPHY_CTRL_EXT_RESET); - AT_WRITE_FLUSH(hw); -- msleep(10); -+ udelay(10 * GPHY_CTRL_EXT_RST_TO); /* delay 800us */ - -+ /* switch clock */ - if (hw->nic_type == athr_l2c_b) { -- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x0A); -- atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data); -- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xDFFF); -+ atl1c_read_phy_dbg(hw, MIIDBG_CFGLPSPD, &phy_data); -+ atl1c_write_phy_dbg(hw, MIIDBG_CFGLPSPD, -+ phy_data & ~CFGLPSPD_RSTCNT_CLK125SW); - } - -- if (hw->nic_type == athr_l2c_b || -- hw->nic_type == athr_l2c_b2 || -- hw->nic_type == athr_l1d || -- hw->nic_type == athr_l1d_2) { -- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B); -- atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data); -- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xFFF7); -- msleep(20); -+ /* tx-half amplitude issue fix */ -+ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { -+ atl1c_read_phy_dbg(hw, MIIDBG_CABLE1TH_DET, &phy_data); -+ phy_data |= CABLE1TH_DET_EN; -+ atl1c_write_phy_dbg(hw, MIIDBG_CABLE1TH_DET, phy_data); - } -- if (hw->nic_type == athr_l1d) { -- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29); -- atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x929D); -+ -+ /* clear bit3 of dbgport 3B to lower voltage */ -+ if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE)) { -+ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { -+ atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); -+ phy_data &= ~VOLT_CTRL_SWLOWEST; -+ atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); -+ } -+ /* power saving config */ -+ phy_data = -+ hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 ? -+ L1D_LEGCYPS_DEF : L1C_LEGCYPS_DEF; -+ atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS, phy_data); -+ /* hib */ -+ atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, -+ SYSMODCTRL_IECHOADJ_DEF); -+ } else { -+ /* disable pws */ -+ atl1c_read_phy_dbg(hw, MIIDBG_LEGCYPS, &phy_data); -+ atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS, -+ phy_data & ~LEGCYPS_EN); -+ /* disable hibernate */ -+ atl1c_read_phy_dbg(hw, MIIDBG_HIBNEG, &phy_data); -+ atl1c_write_phy_dbg(hw, MIIDBG_HIBNEG, -+ phy_data & HIBNEG_PSHIB_EN); - } -- if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c_b2 -- || hw->nic_type == athr_l2c) { -- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29); -- atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD); -+ /* disable AZ(EEE) by default */ -+ if (hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 || -+ hw->nic_type == athr_l2c_b2) { -+ AT_READ_REG(hw, REG_LPI_CTRL, &lpi_ctrl); -+ AT_WRITE_REG(hw, REG_LPI_CTRL, lpi_ctrl & ~LPI_CTRL_EN); -+ atl1c_write_phy_ext(hw, MIIEXT_ANEG, MIIEXT_LOCAL_EEEADV, 0); -+ atl1c_write_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL3, -+ L2CB_CLDCTRL3); - } -- err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data); -+ -+ /* other debug port to set */ -+ atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, ANACTRL_DEF); -+ atl1c_write_phy_dbg(hw, MIIDBG_SRDSYSMOD, SRDSYSMOD_DEF); -+ atl1c_write_phy_dbg(hw, MIIDBG_TST10BTCFG, TST10BTCFG_DEF); -+ /* UNH-IOL test issue, set bit7 */ -+ atl1c_write_phy_dbg(hw, MIIDBG_TST100BTCFG, -+ TST100BTCFG_DEF | TST100BTCFG_LITCH_EN); -+ -+ /* set phy interrupt mask */ -+ phy_data = IER_LINK_UP | IER_LINK_DOWN; -+ err = atl1c_write_phy_reg(hw, MII_IER, phy_data); - if (err) { - if (netif_msg_hw(adapter)) - dev_err(&pdev->dev, - "Error enable PHY linkChange Interrupt\n"); - return err; - } -- if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION)) -- atl1c_phy_magic_data(hw); - return 0; - } - -@@ -589,7 +693,8 @@ int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex) - return 0; - } - --int atl1c_phy_power_saving(struct atl1c_hw *hw) -+/* select one link mode to get lower power consumption */ -+int atl1c_phy_to_ps_link(struct atl1c_hw *hw) - { - struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter; - struct pci_dev *pdev = adapter->pdev; -@@ -660,3 +765,101 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw) - - return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data); - } -+ -+int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc) -+{ -+ struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter; -+ struct pci_dev *pdev = adapter->pdev; -+ u32 master_ctrl, mac_ctrl, phy_ctrl; -+ u32 wol_ctrl, speed; -+ u16 phy_data; -+ -+ wol_ctrl = 0; -+ speed = adapter->link_speed == SPEED_1000 ? -+ MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100; -+ -+ AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl); -+ AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl); -+ AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl); -+ -+ master_ctrl &= ~MASTER_CTRL_CLK_SEL_DIS; -+ mac_ctrl = FIELD_SETX(mac_ctrl, MAC_CTRL_SPEED, speed); -+ mac_ctrl &= ~(MAC_CTRL_DUPLX | MAC_CTRL_RX_EN | MAC_CTRL_TX_EN); -+ if (adapter->link_duplex == FULL_DUPLEX) -+ mac_ctrl |= MAC_CTRL_DUPLX; -+ phy_ctrl &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_CLS); -+ phy_ctrl |= GPHY_CTRL_SEL_ANA_RST | GPHY_CTRL_HIB_PULSE | -+ GPHY_CTRL_HIB_EN; -+ if (!wufc) { /* without WoL */ -+ master_ctrl |= MASTER_CTRL_CLK_SEL_DIS; -+ phy_ctrl |= GPHY_CTRL_PHY_IDDQ | GPHY_CTRL_PWDOWN_HW; -+ AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl); -+ AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl); -+ AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl); -+ AT_WRITE_REG(hw, REG_WOL_CTRL, 0); -+ hw->phy_configured = false; /* re-init PHY when resume */ -+ return 0; -+ } -+ phy_ctrl |= GPHY_CTRL_EXT_RESET; -+ if (wufc & AT_WUFC_MAG) { -+ mac_ctrl |= MAC_CTRL_RX_EN | MAC_CTRL_BC_EN; -+ wol_ctrl |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN; -+ if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V11) -+ wol_ctrl |= WOL_PATTERN_EN | WOL_PATTERN_PME_EN; -+ } -+ if (wufc & AT_WUFC_LNKC) { -+ wol_ctrl |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN; -+ if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) { -+ dev_dbg(&pdev->dev, "%s: write phy MII_IER faild.\n", -+ atl1c_driver_name); -+ } -+ } -+ /* clear PHY interrupt */ -+ atl1c_read_phy_reg(hw, MII_ISR, &phy_data); -+ -+ dev_dbg(&pdev->dev, "%s: suspend MAC=%x,MASTER=%x,PHY=0x%x,WOL=%x\n", -+ atl1c_driver_name, mac_ctrl, master_ctrl, phy_ctrl, wol_ctrl); -+ AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl); -+ AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl); -+ AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl); -+ AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl); -+ -+ return 0; -+} -+ -+ -+/* configure phy after Link change Event */ -+void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed) -+{ -+ u16 phy_val; -+ bool adj_thresh = false; -+ -+ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 || -+ hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2) -+ adj_thresh = true; -+ -+ if (link_speed != SPEED_0) { /* link up */ -+ /* az with brcm, half-amp */ -+ if (hw->nic_type == athr_l1d_2) { -+ atl1c_read_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL6, -+ &phy_val); -+ phy_val = FIELD_GETX(phy_val, CLDCTRL6_CAB_LEN); -+ phy_val = phy_val > CLDCTRL6_CAB_LEN_SHORT ? -+ AZ_ANADECT_LONG : AZ_ANADECT_DEF; -+ atl1c_write_phy_dbg(hw, MIIDBG_AZ_ANADECT, phy_val); -+ } -+ /* threshold adjust */ -+ if (adj_thresh && link_speed == SPEED_100 && hw->msi_lnkpatch) { -+ atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, L1D_MSE16DB_UP); -+ atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, -+ L1D_SYSMODCTRL_IECHOADJ_DEF); -+ } -+ } else { /* link down */ -+ if (adj_thresh && hw->msi_lnkpatch) { -+ atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, -+ SYSMODCTRL_IECHOADJ_DEF); -+ atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, -+ L1D_MSE16DB_DOWN); -+ } -+ } -+} -diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h -index 655fc6c..17d935b 100644 ---- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h -+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h -@@ -25,12 +25,18 @@ - #include - #include - -+#define FIELD_GETX(_x, _name) ((_x) >> (_name##_SHIFT) & (_name##_MASK)) -+#define FIELD_SETX(_x, _name, _v) \ -+(((_x) & ~((_name##_MASK) << (_name##_SHIFT))) |\ -+(((_v) & (_name##_MASK)) << (_name##_SHIFT))) -+#define FIELDX(_name, _v) (((_v) & (_name##_MASK)) << (_name##_SHIFT)) -+ - struct atl1c_adapter; - struct atl1c_hw; - - /* function prototype */ - void atl1c_phy_disable(struct atl1c_hw *hw); --void atl1c_hw_set_mac_addr(struct atl1c_hw *hw); -+void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr); - int atl1c_phy_reset(struct atl1c_hw *hw); - int atl1c_read_mac_addr(struct atl1c_hw *hw); - int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex); -@@ -42,47 +48,45 @@ bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value); - int atl1c_phy_init(struct atl1c_hw *hw); - int atl1c_check_eeprom_exist(struct atl1c_hw *hw); - int atl1c_restart_autoneg(struct atl1c_hw *hw); --int atl1c_phy_power_saving(struct atl1c_hw *hw); -+int atl1c_phy_to_ps_link(struct atl1c_hw *hw); -+int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc); -+bool atl1c_wait_mdio_idle(struct atl1c_hw *hw); -+void atl1c_stop_phy_polling(struct atl1c_hw *hw); -+void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel); -+int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, -+ u16 reg, u16 *phy_data); -+int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, -+ u16 reg, u16 phy_data); -+int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr, -+ u16 reg_addr, u16 *phy_data); -+int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr, -+ u16 reg_addr, u16 phy_data); -+int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data); -+int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data); -+void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed); -+ -+/* hw-ids */ -+#define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062 -+#define PCI_DEVICE_ID_ATTANSIC_L1C 0x1063 -+#define PCI_DEVICE_ID_ATHEROS_L2C_B 0x2060 /* AR8152 v1.1 Fast 10/100 */ -+#define PCI_DEVICE_ID_ATHEROS_L2C_B2 0x2062 /* AR8152 v2.0 Fast 10/100 */ -+#define PCI_DEVICE_ID_ATHEROS_L1D 0x1073 /* AR8151 v1.0 Gigabit 1000 */ -+#define PCI_DEVICE_ID_ATHEROS_L1D_2_0 0x1083 /* AR8151 v2.0 Gigabit 1000 */ -+#define L2CB_V10 0xc0 -+#define L2CB_V11 0xc1 -+ - /* register definition */ - #define REG_DEVICE_CAP 0x5C - #define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7 - #define DEVICE_CAP_MAX_PAYLOAD_SHIFT 0 - --#define REG_DEVICE_CTRL 0x60 --#define DEVICE_CTRL_MAX_PAYLOAD_MASK 0x7 --#define DEVICE_CTRL_MAX_PAYLOAD_SHIFT 5 --#define DEVICE_CTRL_MAX_RREQ_SZ_MASK 0x7 --#define DEVICE_CTRL_MAX_RREQ_SZ_SHIFT 12 -+#define DEVICE_CTRL_MAXRRS_MIN 2 - - #define REG_LINK_CTRL 0x68 - #define LINK_CTRL_L0S_EN 0x01 - #define LINK_CTRL_L1_EN 0x02 - #define LINK_CTRL_EXT_SYNC 0x80 - --#define REG_VPD_CAP 0x6C --#define VPD_CAP_ID_MASK 0xff --#define VPD_CAP_ID_SHIFT 0 --#define VPD_CAP_NEXT_PTR_MASK 0xFF --#define VPD_CAP_NEXT_PTR_SHIFT 8 --#define VPD_CAP_VPD_ADDR_MASK 0x7FFF --#define VPD_CAP_VPD_ADDR_SHIFT 16 --#define VPD_CAP_VPD_FLAG 0x80000000 -- --#define REG_VPD_DATA 0x70 -- --#define REG_PCIE_UC_SEVERITY 0x10C --#define PCIE_UC_SERVRITY_TRN 0x00000001 --#define PCIE_UC_SERVRITY_DLP 0x00000010 --#define PCIE_UC_SERVRITY_PSN_TLP 0x00001000 --#define PCIE_UC_SERVRITY_FCP 0x00002000 --#define PCIE_UC_SERVRITY_CPL_TO 0x00004000 --#define PCIE_UC_SERVRITY_CA 0x00008000 --#define PCIE_UC_SERVRITY_UC 0x00010000 --#define PCIE_UC_SERVRITY_ROV 0x00020000 --#define PCIE_UC_SERVRITY_MLFP 0x00040000 --#define PCIE_UC_SERVRITY_ECRC 0x00080000 --#define PCIE_UC_SERVRITY_UR 0x00100000 -- - #define REG_DEV_SERIALNUM_CTRL 0x200 - #define REG_DEV_MAC_SEL_MASK 0x0 /* 0:EUI; 1:MAC */ - #define REG_DEV_MAC_SEL_SHIFT 0 -@@ -90,25 +94,17 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); - #define REG_DEV_SERIAL_NUM_EN_SHIFT 1 - - #define REG_TWSI_CTRL 0x218 -+#define TWSI_CTLR_FREQ_MASK 0x3UL -+#define TWSI_CTRL_FREQ_SHIFT 24 -+#define TWSI_CTRL_FREQ_100K 0 -+#define TWSI_CTRL_FREQ_200K 1 -+#define TWSI_CTRL_FREQ_300K 2 -+#define TWSI_CTRL_FREQ_400K 3 -+#define TWSI_CTRL_LD_EXIST BIT(23) -+#define TWSI_CTRL_HW_LDSTAT BIT(12) /* 0:finish,1:in progress */ -+#define TWSI_CTRL_SW_LDSTART BIT(11) - #define TWSI_CTRL_LD_OFFSET_MASK 0xFF - #define TWSI_CTRL_LD_OFFSET_SHIFT 0 --#define TWSI_CTRL_LD_SLV_ADDR_MASK 0x7 --#define TWSI_CTRL_LD_SLV_ADDR_SHIFT 8 --#define TWSI_CTRL_SW_LDSTART 0x800 --#define TWSI_CTRL_HW_LDSTART 0x1000 --#define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x7F --#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT 15 --#define TWSI_CTRL_LD_EXIST 0x400000 --#define TWSI_CTRL_READ_FREQ_SEL_MASK 0x3 --#define TWSI_CTRL_READ_FREQ_SEL_SHIFT 23 --#define TWSI_CTRL_FREQ_SEL_100K 0 --#define TWSI_CTRL_FREQ_SEL_200K 1 --#define TWSI_CTRL_FREQ_SEL_300K 2 --#define TWSI_CTRL_FREQ_SEL_400K 3 --#define TWSI_CTRL_SMB_SLV_ADDR --#define TWSI_CTRL_WRITE_FREQ_SEL_MASK 0x3 --#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT 24 -- - - #define REG_PCIE_DEV_MISC_CTRL 0x21C - #define PCIE_DEV_MISC_EXT_PIPE 0x2 -@@ -118,16 +114,23 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); - #define PCIE_DEV_MISC_SERDES_SEL_DIN 0x10 - - #define REG_PCIE_PHYMISC 0x1000 --#define PCIE_PHYMISC_FORCE_RCV_DET 0x4 -+#define PCIE_PHYMISC_FORCE_RCV_DET BIT(2) -+#define PCIE_PHYMISC_NFTS_MASK 0xFFUL -+#define PCIE_PHYMISC_NFTS_SHIFT 16 - - #define REG_PCIE_PHYMISC2 0x1004 --#define PCIE_PHYMISC2_SERDES_CDR_MASK 0x3 --#define PCIE_PHYMISC2_SERDES_CDR_SHIFT 16 --#define PCIE_PHYMISC2_SERDES_TH_MASK 0x3 --#define PCIE_PHYMISC2_SERDES_TH_SHIFT 18 -+#define PCIE_PHYMISC2_L0S_TH_MASK 0x3UL -+#define PCIE_PHYMISC2_L0S_TH_SHIFT 18 -+#define L2CB1_PCIE_PHYMISC2_L0S_TH 3 -+#define PCIE_PHYMISC2_CDR_BW_MASK 0x3UL -+#define PCIE_PHYMISC2_CDR_BW_SHIFT 16 -+#define L2CB1_PCIE_PHYMISC2_CDR_BW 3 - - #define REG_TWSI_DEBUG 0x1108 --#define TWSI_DEBUG_DEV_EXIST 0x20000000 -+#define TWSI_DEBUG_DEV_EXIST BIT(29) -+ -+#define REG_DMA_DBG 0x1114 -+#define DMA_DBG_VENDOR_MSG BIT(0) - - #define REG_EEPROM_CTRL 0x12C0 - #define EEPROM_CTRL_DATA_HI_MASK 0xFFFF -@@ -140,56 +143,81 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); - #define REG_EEPROM_DATA_LO 0x12C4 - - #define REG_OTP_CTRL 0x12F0 --#define OTP_CTRL_CLK_EN 0x0002 -+#define OTP_CTRL_CLK_EN BIT(1) - - #define REG_PM_CTRL 0x12F8 --#define PM_CTRL_SDES_EN 0x00000001 --#define PM_CTRL_RBER_EN 0x00000002 --#define PM_CTRL_CLK_REQ_EN 0x00000004 --#define PM_CTRL_ASPM_L1_EN 0x00000008 --#define PM_CTRL_SERDES_L1_EN 0x00000010 --#define PM_CTRL_SERDES_PLL_L1_EN 0x00000020 --#define PM_CTRL_SERDES_PD_EX_L1 0x00000040 --#define PM_CTRL_SERDES_BUDS_RX_L1_EN 0x00000080 --#define PM_CTRL_L0S_ENTRY_TIMER_MASK 0xF --#define PM_CTRL_L0S_ENTRY_TIMER_SHIFT 8 --#define PM_CTRL_ASPM_L0S_EN 0x00001000 --#define PM_CTRL_CLK_SWH_L1 0x00002000 --#define PM_CTRL_CLK_PWM_VER1_1 0x00004000 --#define PM_CTRL_RCVR_WT_TIMER 0x00008000 --#define PM_CTRL_L1_ENTRY_TIMER_MASK 0xF --#define PM_CTRL_L1_ENTRY_TIMER_SHIFT 16 --#define PM_CTRL_PM_REQ_TIMER_MASK 0xF --#define PM_CTRL_PM_REQ_TIMER_SHIFT 20 --#define PM_CTRL_LCKDET_TIMER_MASK 0xF -+#define PM_CTRL_HOTRST BIT(31) -+#define PM_CTRL_MAC_ASPM_CHK BIT(30) /* L0s/L1 dis by MAC based on -+ * thrghput(setting in 15A0) */ -+#define PM_CTRL_SA_DLY_EN BIT(29) -+#define PM_CTRL_L0S_BUFSRX_EN BIT(28) -+#define PM_CTRL_LCKDET_TIMER_MASK 0xFUL - #define PM_CTRL_LCKDET_TIMER_SHIFT 24 --#define PM_CTRL_EN_BUFS_RX_L0S 0x10000000 --#define PM_CTRL_SA_DLY_EN 0x20000000 --#define PM_CTRL_MAC_ASPM_CHK 0x40000000 --#define PM_CTRL_HOTRST 0x80000000 -+#define PM_CTRL_LCKDET_TIMER_DEF 0xC -+#define PM_CTRL_PM_REQ_TIMER_MASK 0xFUL -+#define PM_CTRL_PM_REQ_TIMER_SHIFT 20 /* pm_request_l1 time > @ -+ * ->L0s not L1 */ -+#define PM_CTRL_PM_REQ_TO_DEF 0xF -+#define PMCTRL_TXL1_AFTER_L0S BIT(19) /* l1dv2.0+ */ -+#define L1D_PMCTRL_L1_ENTRY_TM_MASK 7UL /* l1dv2.0+, 3bits */ -+#define L1D_PMCTRL_L1_ENTRY_TM_SHIFT 16 -+#define L1D_PMCTRL_L1_ENTRY_TM_DIS 0 -+#define L1D_PMCTRL_L1_ENTRY_TM_2US 1 -+#define L1D_PMCTRL_L1_ENTRY_TM_4US 2 -+#define L1D_PMCTRL_L1_ENTRY_TM_8US 3 -+#define L1D_PMCTRL_L1_ENTRY_TM_16US 4 -+#define L1D_PMCTRL_L1_ENTRY_TM_24US 5 -+#define L1D_PMCTRL_L1_ENTRY_TM_32US 6 -+#define L1D_PMCTRL_L1_ENTRY_TM_63US 7 -+#define PM_CTRL_L1_ENTRY_TIMER_MASK 0xFUL /* l1C 4bits */ -+#define PM_CTRL_L1_ENTRY_TIMER_SHIFT 16 -+#define L2CB1_PM_CTRL_L1_ENTRY_TM 7 -+#define L1C_PM_CTRL_L1_ENTRY_TM 0xF -+#define PM_CTRL_RCVR_WT_TIMER BIT(15) /* 1:1us, 0:2ms */ -+#define PM_CTRL_CLK_PWM_VER1_1 BIT(14) /* 0:1.0a,1:1.1 */ -+#define PM_CTRL_CLK_SWH_L1 BIT(13) /* en pcie clk sw in L1 */ -+#define PM_CTRL_ASPM_L0S_EN BIT(12) -+#define PM_CTRL_RXL1_AFTER_L0S BIT(11) /* l1dv2.0+ */ -+#define L1D_PMCTRL_L0S_TIMER_MASK 7UL /* l1d2.0+, 3bits*/ -+#define L1D_PMCTRL_L0S_TIMER_SHIFT 8 -+#define PM_CTRL_L0S_ENTRY_TIMER_MASK 0xFUL /* l1c, 4bits */ -+#define PM_CTRL_L0S_ENTRY_TIMER_SHIFT 8 -+#define PM_CTRL_SERDES_BUFS_RX_L1_EN BIT(7) -+#define PM_CTRL_SERDES_PD_EX_L1 BIT(6) /* power down serdes rx */ -+#define PM_CTRL_SERDES_PLL_L1_EN BIT(5) -+#define PM_CTRL_SERDES_L1_EN BIT(4) -+#define PM_CTRL_ASPM_L1_EN BIT(3) -+#define PM_CTRL_CLK_REQ_EN BIT(2) -+#define PM_CTRL_RBER_EN BIT(1) -+#define PM_CTRL_SPRSDWER_EN BIT(0) - - #define REG_LTSSM_ID_CTRL 0x12FC - #define LTSSM_ID_EN_WRO 0x1000 -+ -+ - /* Selene Master Control Register */ - #define REG_MASTER_CTRL 0x1400 --#define MASTER_CTRL_SOFT_RST 0x1 --#define MASTER_CTRL_TEST_MODE_MASK 0x3 --#define MASTER_CTRL_TEST_MODE_SHIFT 2 --#define MASTER_CTRL_BERT_START 0x10 --#define MASTER_CTRL_OOB_DIS_OFF 0x40 --#define MASTER_CTRL_SA_TIMER_EN 0x80 --#define MASTER_CTRL_MTIMER_EN 0x100 --#define MASTER_CTRL_MANUAL_INT 0x200 --#define MASTER_CTRL_TX_ITIMER_EN 0x400 --#define MASTER_CTRL_RX_ITIMER_EN 0x800 --#define MASTER_CTRL_CLK_SEL_DIS 0x1000 --#define MASTER_CTRL_CLK_SWH_MODE 0x2000 --#define MASTER_CTRL_INT_RDCLR 0x4000 --#define MASTER_CTRL_REV_NUM_SHIFT 16 --#define MASTER_CTRL_REV_NUM_MASK 0xff --#define MASTER_CTRL_DEV_ID_SHIFT 24 --#define MASTER_CTRL_DEV_ID_MASK 0x7f --#define MASTER_CTRL_OTP_SEL 0x80000000 -+#define MASTER_CTRL_OTP_SEL BIT(31) -+#define MASTER_DEV_NUM_MASK 0x7FUL -+#define MASTER_DEV_NUM_SHIFT 24 -+#define MASTER_REV_NUM_MASK 0xFFUL -+#define MASTER_REV_NUM_SHIFT 16 -+#define MASTER_CTRL_INT_RDCLR BIT(14) -+#define MASTER_CTRL_CLK_SEL_DIS BIT(12) /* 1:alwys sel pclk from -+ * serdes, not sw to 25M */ -+#define MASTER_CTRL_RX_ITIMER_EN BIT(11) /* IRQ MODURATION FOR RX */ -+#define MASTER_CTRL_TX_ITIMER_EN BIT(10) /* MODURATION FOR TX/RX */ -+#define MASTER_CTRL_MANU_INT BIT(9) /* SOFT MANUAL INT */ -+#define MASTER_CTRL_MANUTIMER_EN BIT(8) -+#define MASTER_CTRL_SA_TIMER_EN BIT(7) /* SYS ALIVE TIMER EN */ -+#define MASTER_CTRL_OOB_DIS BIT(6) /* OUT OF BOX DIS */ -+#define MASTER_CTRL_WAKEN_25M BIT(5) /* WAKE WO. PCIE CLK */ -+#define MASTER_CTRL_BERT_START BIT(4) -+#define MASTER_PCIE_TSTMOD_MASK 3UL -+#define MASTER_PCIE_TSTMOD_SHIFT 2 -+#define MASTER_PCIE_RST BIT(1) -+#define MASTER_CTRL_SOFT_RST BIT(0) /* RST MAC & DMA */ -+#define DMA_MAC_RST_TO 50 - - /* Timer Initial Value Register */ - #define REG_MANUAL_TIMER_INIT 0x1404 -@@ -201,87 +229,85 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); - #define IRQ_MODRT_RX_TIMER_SHIFT 16 - - #define REG_GPHY_CTRL 0x140C --#define GPHY_CTRL_EXT_RESET 0x1 --#define GPHY_CTRL_RTL_MODE 0x2 --#define GPHY_CTRL_LED_MODE 0x4 --#define GPHY_CTRL_ANEG_NOW 0x8 --#define GPHY_CTRL_REV_ANEG 0x10 --#define GPHY_CTRL_GATE_25M_EN 0x20 --#define GPHY_CTRL_LPW_EXIT 0x40 --#define GPHY_CTRL_PHY_IDDQ 0x80 --#define GPHY_CTRL_PHY_IDDQ_DIS 0x100 --#define GPHY_CTRL_GIGA_DIS 0x200 --#define GPHY_CTRL_HIB_EN 0x400 --#define GPHY_CTRL_HIB_PULSE 0x800 --#define GPHY_CTRL_SEL_ANA_RST 0x1000 --#define GPHY_CTRL_PHY_PLL_ON 0x2000 --#define GPHY_CTRL_PWDOWN_HW 0x4000 --#define GPHY_CTRL_PHY_PLL_BYPASS 0x8000 -- --#define GPHY_CTRL_DEFAULT ( \ -- GPHY_CTRL_SEL_ANA_RST |\ -- GPHY_CTRL_HIB_PULSE |\ -- GPHY_CTRL_HIB_EN) -- --#define GPHY_CTRL_PW_WOL_DIS ( \ -- GPHY_CTRL_SEL_ANA_RST |\ -- GPHY_CTRL_HIB_PULSE |\ -- GPHY_CTRL_HIB_EN |\ -- GPHY_CTRL_PWDOWN_HW |\ -- GPHY_CTRL_PHY_IDDQ) -- --#define GPHY_CTRL_POWER_SAVING ( \ -- GPHY_CTRL_SEL_ANA_RST |\ -- GPHY_CTRL_HIB_EN |\ -- GPHY_CTRL_HIB_PULSE |\ -- GPHY_CTRL_PWDOWN_HW |\ -- GPHY_CTRL_PHY_IDDQ) -+#define GPHY_CTRL_ADDR_MASK 0x1FUL -+#define GPHY_CTRL_ADDR_SHIFT 19 -+#define GPHY_CTRL_BP_VLTGSW BIT(18) -+#define GPHY_CTRL_100AB_EN BIT(17) -+#define GPHY_CTRL_10AB_EN BIT(16) -+#define GPHY_CTRL_PHY_PLL_BYPASS BIT(15) -+#define GPHY_CTRL_PWDOWN_HW BIT(14) /* affect MAC&PHY, to low pw */ -+#define GPHY_CTRL_PHY_PLL_ON BIT(13) /* 1:pll always on, 0:can sw */ -+#define GPHY_CTRL_SEL_ANA_RST BIT(12) -+#define GPHY_CTRL_HIB_PULSE BIT(11) -+#define GPHY_CTRL_HIB_EN BIT(10) -+#define GPHY_CTRL_GIGA_DIS BIT(9) -+#define GPHY_CTRL_PHY_IDDQ_DIS BIT(8) /* pw on RST */ -+#define GPHY_CTRL_PHY_IDDQ BIT(7) /* bit8 affect bit7 while rb */ -+#define GPHY_CTRL_LPW_EXIT BIT(6) -+#define GPHY_CTRL_GATE_25M_EN BIT(5) -+#define GPHY_CTRL_REV_ANEG BIT(4) -+#define GPHY_CTRL_ANEG_NOW BIT(3) -+#define GPHY_CTRL_LED_MODE BIT(2) -+#define GPHY_CTRL_RTL_MODE BIT(1) -+#define GPHY_CTRL_EXT_RESET BIT(0) /* 1:out of DSP RST status */ -+#define GPHY_CTRL_EXT_RST_TO 80 /* 800us atmost */ -+#define GPHY_CTRL_CLS (\ -+ GPHY_CTRL_LED_MODE |\ -+ GPHY_CTRL_100AB_EN |\ -+ GPHY_CTRL_PHY_PLL_ON) -+ - /* Block IDLE Status Register */ --#define REG_IDLE_STATUS 0x1410 --#define IDLE_STATUS_MASK 0x00FF --#define IDLE_STATUS_RXMAC_NO_IDLE 0x1 --#define IDLE_STATUS_TXMAC_NO_IDLE 0x2 --#define IDLE_STATUS_RXQ_NO_IDLE 0x4 --#define IDLE_STATUS_TXQ_NO_IDLE 0x8 --#define IDLE_STATUS_DMAR_NO_IDLE 0x10 --#define IDLE_STATUS_DMAW_NO_IDLE 0x20 --#define IDLE_STATUS_SMB_NO_IDLE 0x40 --#define IDLE_STATUS_CMB_NO_IDLE 0x80 -+#define REG_IDLE_STATUS 0x1410 -+#define IDLE_STATUS_SFORCE_MASK 0xFUL -+#define IDLE_STATUS_SFORCE_SHIFT 14 -+#define IDLE_STATUS_CALIB_DONE BIT(13) -+#define IDLE_STATUS_CALIB_RES_MASK 0x1FUL -+#define IDLE_STATUS_CALIB_RES_SHIFT 8 -+#define IDLE_STATUS_CALIBERR_MASK 0xFUL -+#define IDLE_STATUS_CALIBERR_SHIFT 4 -+#define IDLE_STATUS_TXQ_BUSY BIT(3) -+#define IDLE_STATUS_RXQ_BUSY BIT(2) -+#define IDLE_STATUS_TXMAC_BUSY BIT(1) -+#define IDLE_STATUS_RXMAC_BUSY BIT(0) -+#define IDLE_STATUS_MASK (\ -+ IDLE_STATUS_TXQ_BUSY |\ -+ IDLE_STATUS_RXQ_BUSY |\ -+ IDLE_STATUS_TXMAC_BUSY |\ -+ IDLE_STATUS_RXMAC_BUSY) - - /* MDIO Control Register */ - #define REG_MDIO_CTRL 0x1414 --#define MDIO_DATA_MASK 0xffff /* On MDIO write, the 16-bit -- * control data to write to PHY -- * MII management register */ --#define MDIO_DATA_SHIFT 0 /* On MDIO read, the 16-bit -- * status data that was read -- * from the PHY MII management register */ --#define MDIO_REG_ADDR_MASK 0x1f /* MDIO register address */ --#define MDIO_REG_ADDR_SHIFT 16 --#define MDIO_RW 0x200000 /* 1: read, 0: write */ --#define MDIO_SUP_PREAMBLE 0x400000 /* Suppress preamble */ --#define MDIO_START 0x800000 /* Write 1 to initiate the MDIO -- * master. And this bit is self -- * cleared after one cycle */ --#define MDIO_CLK_SEL_SHIFT 24 --#define MDIO_CLK_25_4 0 --#define MDIO_CLK_25_6 2 --#define MDIO_CLK_25_8 3 --#define MDIO_CLK_25_10 4 --#define MDIO_CLK_25_14 5 --#define MDIO_CLK_25_20 6 --#define MDIO_CLK_25_28 7 --#define MDIO_BUSY 0x8000000 --#define MDIO_AP_EN 0x10000000 --#define MDIO_WAIT_TIMES 10 -- --/* MII PHY Status Register */ --#define REG_PHY_STATUS 0x1418 --#define PHY_GENERAL_STATUS_MASK 0xFFFF --#define PHY_STATUS_RECV_ENABLE 0x0001 --#define PHY_OE_PWSP_STATUS_MASK 0x07FF --#define PHY_OE_PWSP_STATUS_SHIFT 16 --#define PHY_STATUS_LPW_STATE 0x80000000 -+#define MDIO_CTRL_MODE_EXT BIT(30) -+#define MDIO_CTRL_POST_READ BIT(29) -+#define MDIO_CTRL_AP_EN BIT(28) -+#define MDIO_CTRL_BUSY BIT(27) -+#define MDIO_CTRL_CLK_SEL_MASK 0x7UL -+#define MDIO_CTRL_CLK_SEL_SHIFT 24 -+#define MDIO_CTRL_CLK_25_4 0 /* 25MHz divide 4 */ -+#define MDIO_CTRL_CLK_25_6 2 -+#define MDIO_CTRL_CLK_25_8 3 -+#define MDIO_CTRL_CLK_25_10 4 -+#define MDIO_CTRL_CLK_25_32 5 -+#define MDIO_CTRL_CLK_25_64 6 -+#define MDIO_CTRL_CLK_25_128 7 -+#define MDIO_CTRL_START BIT(23) -+#define MDIO_CTRL_SPRES_PRMBL BIT(22) -+#define MDIO_CTRL_OP_READ BIT(21) /* 1:read, 0:write */ -+#define MDIO_CTRL_REG_MASK 0x1FUL -+#define MDIO_CTRL_REG_SHIFT 16 -+#define MDIO_CTRL_DATA_MASK 0xFFFFUL -+#define MDIO_CTRL_DATA_SHIFT 0 -+#define MDIO_MAX_AC_TO 120 /* 1.2ms timeout for slow clk */ -+ -+/* for extension reg access */ -+#define REG_MDIO_EXTN 0x1448 -+#define MDIO_EXTN_PORTAD_MASK 0x1FUL -+#define MDIO_EXTN_PORTAD_SHIFT 21 -+#define MDIO_EXTN_DEVAD_MASK 0x1FUL -+#define MDIO_EXTN_DEVAD_SHIFT 16 -+#define MDIO_EXTN_REG_MASK 0xFFFFUL -+#define MDIO_EXTN_REG_SHIFT 0 -+ - /* BIST Control and Status Register0 (for the Packet Memory) */ - #define REG_BIST0_CTRL 0x141c - #define BIST0_NOW 0x1 -@@ -299,50 +325,81 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); - #define BIST1_FUSE_FLAG 0x4 - - /* SerDes Lock Detect Control and Status Register */ --#define REG_SERDES_LOCK 0x1424 --#define SERDES_LOCK_DETECT 0x1 /* SerDes lock detected. This signal -- * comes from Analog SerDes */ --#define SERDES_LOCK_DETECT_EN 0x2 /* 1: Enable SerDes Lock detect function */ --#define SERDES_LOCK_STS_SELFB_PLL_SHIFT 0xE --#define SERDES_LOCK_STS_SELFB_PLL_MASK 0x3 --#define SERDES_OVCLK_18_25 0x0 --#define SERDES_OVCLK_12_18 0x1 --#define SERDES_OVCLK_0_4 0x2 --#define SERDES_OVCLK_4_12 0x3 --#define SERDES_MAC_CLK_SLOWDOWN 0x20000 --#define SERDES_PYH_CLK_SLOWDOWN 0x40000 -+#define REG_SERDES 0x1424 -+#define SERDES_PHY_CLK_SLOWDOWN BIT(18) -+#define SERDES_MAC_CLK_SLOWDOWN BIT(17) -+#define SERDES_SELFB_PLL_MASK 0x3UL -+#define SERDES_SELFB_PLL_SHIFT 14 -+#define SERDES_PHYCLK_SEL_GTX BIT(13) /* 1:gtx_clk, 0:25M */ -+#define SERDES_PCIECLK_SEL_SRDS BIT(12) /* 1:serdes,0:25M */ -+#define SERDES_BUFS_RX_EN BIT(11) -+#define SERDES_PD_RX BIT(10) -+#define SERDES_PLL_EN BIT(9) -+#define SERDES_EN BIT(8) -+#define SERDES_SELFB_PLL_SEL_CSR BIT(6) /* 0:state-machine,1:csr */ -+#define SERDES_SELFB_PLL_CSR_MASK 0x3UL -+#define SERDES_SELFB_PLL_CSR_SHIFT 4 -+#define SERDES_SELFB_PLL_CSR_4 3 /* 4-12% OV-CLK */ -+#define SERDES_SELFB_PLL_CSR_0 2 /* 0-4% OV-CLK */ -+#define SERDES_SELFB_PLL_CSR_12 1 /* 12-18% OV-CLK */ -+#define SERDES_SELFB_PLL_CSR_18 0 /* 18-25% OV-CLK */ -+#define SERDES_VCO_SLOW BIT(3) -+#define SERDES_VCO_FAST BIT(2) -+#define SERDES_LOCK_DETECT_EN BIT(1) -+#define SERDES_LOCK_DETECT BIT(0) -+ -+#define REG_LPI_DECISN_TIMER 0x143C -+#define L2CB_LPI_DESISN_TIMER 0x7D00 -+ -+#define REG_LPI_CTRL 0x1440 -+#define LPI_CTRL_CHK_DA BIT(31) -+#define LPI_CTRL_ENH_TO_MASK 0x1FFFUL -+#define LPI_CTRL_ENH_TO_SHIFT 12 -+#define LPI_CTRL_ENH_TH_MASK 0x1FUL -+#define LPI_CTRL_ENH_TH_SHIFT 6 -+#define LPI_CTRL_ENH_EN BIT(5) -+#define LPI_CTRL_CHK_RX BIT(4) -+#define LPI_CTRL_CHK_STATE BIT(3) -+#define LPI_CTRL_GMII BIT(2) -+#define LPI_CTRL_TO_PHY BIT(1) -+#define LPI_CTRL_EN BIT(0) -+ -+#define REG_LPI_WAIT 0x1444 -+#define LPI_WAIT_TIMER_MASK 0xFFFFUL -+#define LPI_WAIT_TIMER_SHIFT 0 - - /* MAC Control Register */ - #define REG_MAC_CTRL 0x1480 --#define MAC_CTRL_TX_EN 0x1 --#define MAC_CTRL_RX_EN 0x2 --#define MAC_CTRL_TX_FLOW 0x4 --#define MAC_CTRL_RX_FLOW 0x8 --#define MAC_CTRL_LOOPBACK 0x10 --#define MAC_CTRL_DUPLX 0x20 --#define MAC_CTRL_ADD_CRC 0x40 --#define MAC_CTRL_PAD 0x80 --#define MAC_CTRL_LENCHK 0x100 --#define MAC_CTRL_HUGE_EN 0x200 --#define MAC_CTRL_PRMLEN_SHIFT 10 --#define MAC_CTRL_PRMLEN_MASK 0xf --#define MAC_CTRL_RMV_VLAN 0x4000 --#define MAC_CTRL_PROMIS_EN 0x8000 --#define MAC_CTRL_TX_PAUSE 0x10000 --#define MAC_CTRL_SCNT 0x20000 --#define MAC_CTRL_SRST_TX 0x40000 --#define MAC_CTRL_TX_SIMURST 0x80000 --#define MAC_CTRL_SPEED_SHIFT 20 --#define MAC_CTRL_SPEED_MASK 0x3 --#define MAC_CTRL_DBG_TX_BKPRESURE 0x400000 --#define MAC_CTRL_TX_HUGE 0x800000 --#define MAC_CTRL_RX_CHKSUM_EN 0x1000000 --#define MAC_CTRL_MC_ALL_EN 0x2000000 --#define MAC_CTRL_BC_EN 0x4000000 --#define MAC_CTRL_DBG 0x8000000 --#define MAC_CTRL_SINGLE_PAUSE_EN 0x10000000 --#define MAC_CTRL_HASH_ALG_CRC32 0x20000000 --#define MAC_CTRL_SPEED_MODE_SW 0x40000000 -+#define MAC_CTRL_SPEED_MODE_SW BIT(30) /* 0:phy,1:sw */ -+#define MAC_CTRL_HASH_ALG_CRC32 BIT(29) /* 1:legacy,0:lw_5b */ -+#define MAC_CTRL_SINGLE_PAUSE_EN BIT(28) -+#define MAC_CTRL_DBG BIT(27) -+#define MAC_CTRL_BC_EN BIT(26) -+#define MAC_CTRL_MC_ALL_EN BIT(25) -+#define MAC_CTRL_RX_CHKSUM_EN BIT(24) -+#define MAC_CTRL_TX_HUGE BIT(23) -+#define MAC_CTRL_DBG_TX_BKPRESURE BIT(22) -+#define MAC_CTRL_SPEED_MASK 3UL -+#define MAC_CTRL_SPEED_SHIFT 20 -+#define MAC_CTRL_SPEED_10_100 1 -+#define MAC_CTRL_SPEED_1000 2 -+#define MAC_CTRL_TX_SIMURST BIT(19) -+#define MAC_CTRL_SCNT BIT(17) -+#define MAC_CTRL_TX_PAUSE BIT(16) -+#define MAC_CTRL_PROMIS_EN BIT(15) -+#define MAC_CTRL_RMV_VLAN BIT(14) -+#define MAC_CTRL_PRMLEN_MASK 0xFUL -+#define MAC_CTRL_PRMLEN_SHIFT 10 -+#define MAC_CTRL_HUGE_EN BIT(9) -+#define MAC_CTRL_LENCHK BIT(8) -+#define MAC_CTRL_PAD BIT(7) -+#define MAC_CTRL_ADD_CRC BIT(6) -+#define MAC_CTRL_DUPLX BIT(5) -+#define MAC_CTRL_LOOPBACK BIT(4) -+#define MAC_CTRL_RX_FLOW BIT(3) -+#define MAC_CTRL_TX_FLOW BIT(2) -+#define MAC_CTRL_RX_EN BIT(1) -+#define MAC_CTRL_TX_EN BIT(0) - - /* MAC IPG/IFG Control Register */ - #define REG_MAC_IPG_IFG 0x1484 -@@ -386,34 +443,53 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); - - /* Wake-On-Lan control register */ - #define REG_WOL_CTRL 0x14a0 --#define WOL_PATTERN_EN 0x00000001 --#define WOL_PATTERN_PME_EN 0x00000002 --#define WOL_MAGIC_EN 0x00000004 --#define WOL_MAGIC_PME_EN 0x00000008 --#define WOL_LINK_CHG_EN 0x00000010 --#define WOL_LINK_CHG_PME_EN 0x00000020 --#define WOL_PATTERN_ST 0x00000100 --#define WOL_MAGIC_ST 0x00000200 --#define WOL_LINKCHG_ST 0x00000400 --#define WOL_CLK_SWITCH_EN 0x00008000 --#define WOL_PT0_EN 0x00010000 --#define WOL_PT1_EN 0x00020000 --#define WOL_PT2_EN 0x00040000 --#define WOL_PT3_EN 0x00080000 --#define WOL_PT4_EN 0x00100000 --#define WOL_PT5_EN 0x00200000 --#define WOL_PT6_EN 0x00400000 -+#define WOL_PT7_MATCH BIT(31) -+#define WOL_PT6_MATCH BIT(30) -+#define WOL_PT5_MATCH BIT(29) -+#define WOL_PT4_MATCH BIT(28) -+#define WOL_PT3_MATCH BIT(27) -+#define WOL_PT2_MATCH BIT(26) -+#define WOL_PT1_MATCH BIT(25) -+#define WOL_PT0_MATCH BIT(24) -+#define WOL_PT7_EN BIT(23) -+#define WOL_PT6_EN BIT(22) -+#define WOL_PT5_EN BIT(21) -+#define WOL_PT4_EN BIT(20) -+#define WOL_PT3_EN BIT(19) -+#define WOL_PT2_EN BIT(18) -+#define WOL_PT1_EN BIT(17) -+#define WOL_PT0_EN BIT(16) -+#define WOL_LNKCHG_ST BIT(10) -+#define WOL_MAGIC_ST BIT(9) -+#define WOL_PATTERN_ST BIT(8) -+#define WOL_OOB_EN BIT(6) -+#define WOL_LINK_CHG_PME_EN BIT(5) -+#define WOL_LINK_CHG_EN BIT(4) -+#define WOL_MAGIC_PME_EN BIT(3) -+#define WOL_MAGIC_EN BIT(2) -+#define WOL_PATTERN_PME_EN BIT(1) -+#define WOL_PATTERN_EN BIT(0) - - /* WOL Length ( 2 DWORD ) */ --#define REG_WOL_PATTERN_LEN 0x14a4 --#define WOL_PT_LEN_MASK 0x7f --#define WOL_PT0_LEN_SHIFT 0 --#define WOL_PT1_LEN_SHIFT 8 --#define WOL_PT2_LEN_SHIFT 16 --#define WOL_PT3_LEN_SHIFT 24 --#define WOL_PT4_LEN_SHIFT 0 --#define WOL_PT5_LEN_SHIFT 8 --#define WOL_PT6_LEN_SHIFT 16 -+#define REG_WOL_PTLEN1 0x14A4 -+#define WOL_PTLEN1_3_MASK 0xFFUL -+#define WOL_PTLEN1_3_SHIFT 24 -+#define WOL_PTLEN1_2_MASK 0xFFUL -+#define WOL_PTLEN1_2_SHIFT 16 -+#define WOL_PTLEN1_1_MASK 0xFFUL -+#define WOL_PTLEN1_1_SHIFT 8 -+#define WOL_PTLEN1_0_MASK 0xFFUL -+#define WOL_PTLEN1_0_SHIFT 0 -+ -+#define REG_WOL_PTLEN2 0x14A8 -+#define WOL_PTLEN2_7_MASK 0xFFUL -+#define WOL_PTLEN2_7_SHIFT 24 -+#define WOL_PTLEN2_6_MASK 0xFFUL -+#define WOL_PTLEN2_6_SHIFT 16 -+#define WOL_PTLEN2_5_MASK 0xFFUL -+#define WOL_PTLEN2_5_SHIFT 8 -+#define WOL_PTLEN2_4_MASK 0xFFUL -+#define WOL_PTLEN2_4_SHIFT 0 - - /* Internal SRAM Partition Register */ - #define RFDX_HEAD_ADDR_MASK 0x03FF -@@ -458,66 +534,50 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); - */ - #define REG_RX_BASE_ADDR_HI 0x1540 - #define REG_TX_BASE_ADDR_HI 0x1544 --#define REG_SMB_BASE_ADDR_HI 0x1548 --#define REG_SMB_BASE_ADDR_LO 0x154C - #define REG_RFD0_HEAD_ADDR_LO 0x1550 --#define REG_RFD1_HEAD_ADDR_LO 0x1554 --#define REG_RFD2_HEAD_ADDR_LO 0x1558 --#define REG_RFD3_HEAD_ADDR_LO 0x155C - #define REG_RFD_RING_SIZE 0x1560 - #define RFD_RING_SIZE_MASK 0x0FFF - #define REG_RX_BUF_SIZE 0x1564 - #define RX_BUF_SIZE_MASK 0xFFFF - #define REG_RRD0_HEAD_ADDR_LO 0x1568 --#define REG_RRD1_HEAD_ADDR_LO 0x156C --#define REG_RRD2_HEAD_ADDR_LO 0x1570 --#define REG_RRD3_HEAD_ADDR_LO 0x1574 - #define REG_RRD_RING_SIZE 0x1578 - #define RRD_RING_SIZE_MASK 0x0FFF --#define REG_HTPD_HEAD_ADDR_LO 0x157C --#define REG_NTPD_HEAD_ADDR_LO 0x1580 -+#define REG_TPD_PRI1_ADDR_LO 0x157C -+#define REG_TPD_PRI0_ADDR_LO 0x1580 - #define REG_TPD_RING_SIZE 0x1584 - #define TPD_RING_SIZE_MASK 0xFFFF --#define REG_CMB_BASE_ADDR_LO 0x1588 -- --/* RSS about */ --#define REG_RSS_KEY0 0x14B0 --#define REG_RSS_KEY1 0x14B4 --#define REG_RSS_KEY2 0x14B8 --#define REG_RSS_KEY3 0x14BC --#define REG_RSS_KEY4 0x14C0 --#define REG_RSS_KEY5 0x14C4 --#define REG_RSS_KEY6 0x14C8 --#define REG_RSS_KEY7 0x14CC --#define REG_RSS_KEY8 0x14D0 --#define REG_RSS_KEY9 0x14D4 --#define REG_IDT_TABLE0 0x14E0 --#define REG_IDT_TABLE1 0x14E4 --#define REG_IDT_TABLE2 0x14E8 --#define REG_IDT_TABLE3 0x14EC --#define REG_IDT_TABLE4 0x14F0 --#define REG_IDT_TABLE5 0x14F4 --#define REG_IDT_TABLE6 0x14F8 --#define REG_IDT_TABLE7 0x14FC --#define REG_IDT_TABLE REG_IDT_TABLE0 --#define REG_RSS_HASH_VALUE 0x15B0 --#define REG_RSS_HASH_FLAG 0x15B4 --#define REG_BASE_CPU_NUMBER 0x15B8 - - /* TXQ Control Register */ --#define REG_TXQ_CTRL 0x1590 --#define TXQ_NUM_TPD_BURST_MASK 0xF --#define TXQ_NUM_TPD_BURST_SHIFT 0 --#define TXQ_CTRL_IP_OPTION_EN 0x10 --#define TXQ_CTRL_EN 0x20 --#define TXQ_CTRL_ENH_MODE 0x40 --#define TXQ_CTRL_LS_8023_EN 0x80 --#define TXQ_TXF_BURST_NUM_SHIFT 16 --#define TXQ_TXF_BURST_NUM_MASK 0xFFFF -+#define REG_TXQ_CTRL 0x1590 -+#define TXQ_TXF_BURST_NUM_MASK 0xFFFFUL -+#define TXQ_TXF_BURST_NUM_SHIFT 16 -+#define L1C_TXQ_TXF_BURST_PREF 0x200 -+#define L2CB_TXQ_TXF_BURST_PREF 0x40 -+#define TXQ_CTRL_PEDING_CLR BIT(8) -+#define TXQ_CTRL_LS_8023_EN BIT(7) -+#define TXQ_CTRL_ENH_MODE BIT(6) -+#define TXQ_CTRL_EN BIT(5) -+#define TXQ_CTRL_IP_OPTION_EN BIT(4) -+#define TXQ_NUM_TPD_BURST_MASK 0xFUL -+#define TXQ_NUM_TPD_BURST_SHIFT 0 -+#define TXQ_NUM_TPD_BURST_DEF 5 -+#define TXQ_CFGV (\ -+ FIELDX(TXQ_NUM_TPD_BURST, TXQ_NUM_TPD_BURST_DEF) |\ -+ TXQ_CTRL_ENH_MODE |\ -+ TXQ_CTRL_LS_8023_EN |\ -+ TXQ_CTRL_IP_OPTION_EN) -+#define L1C_TXQ_CFGV (\ -+ TXQ_CFGV |\ -+ FIELDX(TXQ_TXF_BURST_NUM, L1C_TXQ_TXF_BURST_PREF)) -+#define L2CB_TXQ_CFGV (\ -+ TXQ_CFGV |\ -+ FIELDX(TXQ_TXF_BURST_NUM, L2CB_TXQ_TXF_BURST_PREF)) -+ - - /* Jumbo packet Threshold for task offload */ - #define REG_TX_TSO_OFFLOAD_THRESH 0x1594 /* In 8-bytes */ - #define TX_TSO_OFFLOAD_THRESH_MASK 0x07FF -+#define MAX_TSO_FRAME_SIZE (7*1024) - - #define REG_TXF_WATER_MARK 0x1598 /* In 8-bytes */ - #define TXF_WATER_MARK_MASK 0x0FFF -@@ -537,26 +597,21 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); - #define ASPM_THRUPUT_LIMIT_NO 0x00 - #define ASPM_THRUPUT_LIMIT_1M 0x01 - #define ASPM_THRUPUT_LIMIT_10M 0x02 --#define ASPM_THRUPUT_LIMIT_100M 0x04 --#define RXQ1_CTRL_EN 0x10 --#define RXQ2_CTRL_EN 0x20 --#define RXQ3_CTRL_EN 0x40 --#define IPV6_CHKSUM_CTRL_EN 0x80 --#define RSS_HASH_BITS_MASK 0x00FF --#define RSS_HASH_BITS_SHIFT 8 --#define RSS_HASH_IPV4 0x10000 --#define RSS_HASH_IPV4_TCP 0x20000 --#define RSS_HASH_IPV6 0x40000 --#define RSS_HASH_IPV6_TCP 0x80000 -+#define ASPM_THRUPUT_LIMIT_100M 0x03 -+#define IPV6_CHKSUM_CTRL_EN BIT(7) - #define RXQ_RFD_BURST_NUM_MASK 0x003F - #define RXQ_RFD_BURST_NUM_SHIFT 20 --#define RSS_MODE_MASK 0x0003 -+#define RXQ_NUM_RFD_PREF_DEF 8 -+#define RSS_MODE_MASK 3UL - #define RSS_MODE_SHIFT 26 --#define RSS_NIP_QUEUE_SEL_MASK 0x1 --#define RSS_NIP_QUEUE_SEL_SHIFT 28 --#define RRS_HASH_CTRL_EN 0x20000000 --#define RX_CUT_THRU_EN 0x40000000 --#define RXQ_CTRL_EN 0x80000000 -+#define RSS_MODE_DIS 0 -+#define RSS_MODE_SQSI 1 -+#define RSS_MODE_MQSI 2 -+#define RSS_MODE_MQMI 3 -+#define RSS_NIP_QUEUE_SEL BIT(28) /* 0:q0, 1:table */ -+#define RRS_HASH_CTRL_EN BIT(29) -+#define RX_CUT_THRU_EN BIT(30) -+#define RXQ_CTRL_EN BIT(31) - - #define REG_RFD_FREE_THRESH 0x15A4 - #define RFD_FREE_THRESH_MASK 0x003F -@@ -577,57 +632,45 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); - #define RXD_DMA_DOWN_TIMER_SHIFT 16 - - /* DMA Engine Control Register */ --#define REG_DMA_CTRL 0x15C0 --#define DMA_CTRL_DMAR_IN_ORDER 0x1 --#define DMA_CTRL_DMAR_ENH_ORDER 0x2 --#define DMA_CTRL_DMAR_OUT_ORDER 0x4 --#define DMA_CTRL_RCB_VALUE 0x8 --#define DMA_CTRL_DMAR_BURST_LEN_MASK 0x0007 --#define DMA_CTRL_DMAR_BURST_LEN_SHIFT 4 --#define DMA_CTRL_DMAW_BURST_LEN_MASK 0x0007 --#define DMA_CTRL_DMAW_BURST_LEN_SHIFT 7 --#define DMA_CTRL_DMAR_REQ_PRI 0x400 --#define DMA_CTRL_DMAR_DLY_CNT_MASK 0x001F --#define DMA_CTRL_DMAR_DLY_CNT_SHIFT 11 --#define DMA_CTRL_DMAW_DLY_CNT_MASK 0x000F --#define DMA_CTRL_DMAW_DLY_CNT_SHIFT 16 --#define DMA_CTRL_CMB_EN 0x100000 --#define DMA_CTRL_SMB_EN 0x200000 --#define DMA_CTRL_CMB_NOW 0x400000 --#define MAC_CTRL_SMB_DIS 0x1000000 --#define DMA_CTRL_SMB_NOW 0x80000000 -- --/* CMB/SMB Control Register */ -+#define REG_DMA_CTRL 0x15C0 -+#define DMA_CTRL_SMB_NOW BIT(31) -+#define DMA_CTRL_WPEND_CLR BIT(30) -+#define DMA_CTRL_RPEND_CLR BIT(29) -+#define DMA_CTRL_WDLY_CNT_MASK 0xFUL -+#define DMA_CTRL_WDLY_CNT_SHIFT 16 -+#define DMA_CTRL_WDLY_CNT_DEF 4 -+#define DMA_CTRL_RDLY_CNT_MASK 0x1FUL -+#define DMA_CTRL_RDLY_CNT_SHIFT 11 -+#define DMA_CTRL_RDLY_CNT_DEF 15 -+#define DMA_CTRL_RREQ_PRI_DATA BIT(10) /* 0:tpd, 1:data */ -+#define DMA_CTRL_WREQ_BLEN_MASK 7UL -+#define DMA_CTRL_WREQ_BLEN_SHIFT 7 -+#define DMA_CTRL_RREQ_BLEN_MASK 7UL -+#define DMA_CTRL_RREQ_BLEN_SHIFT 4 -+#define L1C_CTRL_DMA_RCB_LEN128 BIT(3) /* 0:64bytes,1:128bytes */ -+#define DMA_CTRL_RORDER_MODE_MASK 7UL -+#define DMA_CTRL_RORDER_MODE_SHIFT 0 -+#define DMA_CTRL_RORDER_MODE_OUT 4 -+#define DMA_CTRL_RORDER_MODE_ENHANCE 2 -+#define DMA_CTRL_RORDER_MODE_IN 1 -+ -+/* INT-triggle/SMB Control Register */ - #define REG_SMB_STAT_TIMER 0x15C4 /* 2us resolution */ - #define SMB_STAT_TIMER_MASK 0xFFFFFF --#define REG_CMB_TPD_THRESH 0x15C8 --#define CMB_TPD_THRESH_MASK 0xFFFF --#define REG_CMB_TX_TIMER 0x15CC /* 2us resolution */ --#define CMB_TX_TIMER_MASK 0xFFFF -+#define REG_TINT_TPD_THRESH 0x15C8 /* tpd th to trig intrrupt */ - - /* Mail box */ - #define MB_RFDX_PROD_IDX_MASK 0xFFFF - #define REG_MB_RFD0_PROD_IDX 0x15E0 --#define REG_MB_RFD1_PROD_IDX 0x15E4 --#define REG_MB_RFD2_PROD_IDX 0x15E8 --#define REG_MB_RFD3_PROD_IDX 0x15EC - --#define MB_PRIO_PROD_IDX_MASK 0xFFFF --#define REG_MB_PRIO_PROD_IDX 0x15F0 --#define MB_HTPD_PROD_IDX_SHIFT 0 --#define MB_NTPD_PROD_IDX_SHIFT 16 -- --#define MB_PRIO_CONS_IDX_MASK 0xFFFF --#define REG_MB_PRIO_CONS_IDX 0x15F4 --#define MB_HTPD_CONS_IDX_SHIFT 0 --#define MB_NTPD_CONS_IDX_SHIFT 16 -+#define REG_TPD_PRI1_PIDX 0x15F0 /* 16bit,hi-tpd producer idx */ -+#define REG_TPD_PRI0_PIDX 0x15F2 /* 16bit,lo-tpd producer idx */ -+#define REG_TPD_PRI1_CIDX 0x15F4 /* 16bit,hi-tpd consumer idx */ -+#define REG_TPD_PRI0_CIDX 0x15F6 /* 16bit,lo-tpd consumer idx */ - - #define REG_MB_RFD01_CONS_IDX 0x15F8 - #define MB_RFD0_CONS_IDX_MASK 0x0000FFFF - #define MB_RFD1_CONS_IDX_MASK 0xFFFF0000 --#define REG_MB_RFD23_CONS_IDX 0x15FC --#define MB_RFD2_CONS_IDX_MASK 0x0000FFFF --#define MB_RFD3_CONS_IDX_MASK 0xFFFF0000 - - /* Interrupt Status Register */ - #define REG_ISR 0x1600 -@@ -705,13 +748,6 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); - #define REG_INT_RETRIG_TIMER 0x1608 - #define INT_RETRIG_TIMER_MASK 0xFFFF - --#define REG_HDS_CTRL 0x160C --#define HDS_CTRL_EN 0x0001 --#define HDS_CTRL_BACKFILLSIZE_SHIFT 8 --#define HDS_CTRL_BACKFILLSIZE_MASK 0x0FFF --#define HDS_CTRL_MAX_HDRSIZE_SHIFT 20 --#define HDS_CTRL_MAC_HDRSIZE_MASK 0x0FFF -- - #define REG_MAC_RX_STATUS_BIN 0x1700 - #define REG_MAC_RX_STATUS_END 0x175c - #define REG_MAC_TX_STATUS_BIN 0x1760 -@@ -796,73 +832,188 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); - #define MII_DBG_ADDR 0x1D - #define MII_DBG_DATA 0x1E - --#define MII_ANA_CTRL_0 0x0 --#define ANA_RESTART_CAL 0x0001 --#define ANA_MANUL_SWICH_ON_SHIFT 0x1 --#define ANA_MANUL_SWICH_ON_MASK 0xF --#define ANA_MAN_ENABLE 0x0020 --#define ANA_SEL_HSP 0x0040 --#define ANA_EN_HB 0x0080 --#define ANA_EN_HBIAS 0x0100 --#define ANA_OEN_125M 0x0200 --#define ANA_EN_LCKDT 0x0400 --#define ANA_LCKDT_PHY 0x0800 --#define ANA_AFE_MODE 0x1000 --#define ANA_VCO_SLOW 0x2000 --#define ANA_VCO_FAST 0x4000 --#define ANA_SEL_CLK125M_DSP 0x8000 -- --#define MII_ANA_CTRL_4 0x4 --#define ANA_IECHO_ADJ_MASK 0xF --#define ANA_IECHO_ADJ_3_SHIFT 0 --#define ANA_IECHO_ADJ_2_SHIFT 4 --#define ANA_IECHO_ADJ_1_SHIFT 8 --#define ANA_IECHO_ADJ_0_SHIFT 12 -- --#define MII_ANA_CTRL_5 0x5 --#define ANA_SERDES_CDR_BW_SHIFT 0 --#define ANA_SERDES_CDR_BW_MASK 0x3 --#define ANA_MS_PAD_DBG 0x0004 --#define ANA_SPEEDUP_DBG 0x0008 --#define ANA_SERDES_TH_LOS_SHIFT 4 --#define ANA_SERDES_TH_LOS_MASK 0x3 --#define ANA_SERDES_EN_DEEM 0x0040 --#define ANA_SERDES_TXELECIDLE 0x0080 --#define ANA_SERDES_BEACON 0x0100 --#define ANA_SERDES_HALFTXDR 0x0200 --#define ANA_SERDES_SEL_HSP 0x0400 --#define ANA_SERDES_EN_PLL 0x0800 --#define ANA_SERDES_EN 0x1000 --#define ANA_SERDES_EN_LCKDT 0x2000 -- --#define MII_ANA_CTRL_11 0xB --#define ANA_PS_HIB_EN 0x8000 -- --#define MII_ANA_CTRL_18 0x12 --#define ANA_TEST_MODE_10BT_01SHIFT 0 --#define ANA_TEST_MODE_10BT_01MASK 0x3 --#define ANA_LOOP_SEL_10BT 0x0004 --#define ANA_RGMII_MODE_SW 0x0008 --#define ANA_EN_LONGECABLE 0x0010 --#define ANA_TEST_MODE_10BT_2 0x0020 --#define ANA_EN_10BT_IDLE 0x0400 --#define ANA_EN_MASK_TB 0x0800 --#define ANA_TRIGGER_SEL_TIMER_SHIFT 12 --#define ANA_TRIGGER_SEL_TIMER_MASK 0x3 --#define ANA_INTERVAL_SEL_TIMER_SHIFT 14 --#define ANA_INTERVAL_SEL_TIMER_MASK 0x3 -- --#define MII_ANA_CTRL_41 0x29 --#define ANA_TOP_PS_EN 0x8000 -- --#define MII_ANA_CTRL_54 0x36 --#define ANA_LONG_CABLE_TH_100_SHIFT 0 --#define ANA_LONG_CABLE_TH_100_MASK 0x3F --#define ANA_DESERVED 0x0040 --#define ANA_EN_LIT_CH 0x0080 --#define ANA_SHORT_CABLE_TH_100_SHIFT 8 --#define ANA_SHORT_CABLE_TH_100_MASK 0x3F --#define ANA_BP_BAD_LINK_ACCUM 0x4000 --#define ANA_BP_SMALL_BW 0x8000 -+/***************************** debug port *************************************/ -+ -+#define MIIDBG_ANACTRL 0x00 -+#define ANACTRL_CLK125M_DELAY_EN 0x8000 -+#define ANACTRL_VCO_FAST 0x4000 -+#define ANACTRL_VCO_SLOW 0x2000 -+#define ANACTRL_AFE_MODE_EN 0x1000 -+#define ANACTRL_LCKDET_PHY 0x800 -+#define ANACTRL_LCKDET_EN 0x400 -+#define ANACTRL_OEN_125M 0x200 -+#define ANACTRL_HBIAS_EN 0x100 -+#define ANACTRL_HB_EN 0x80 -+#define ANACTRL_SEL_HSP 0x40 -+#define ANACTRL_CLASSA_EN 0x20 -+#define ANACTRL_MANUSWON_SWR_MASK 3U -+#define ANACTRL_MANUSWON_SWR_SHIFT 2 -+#define ANACTRL_MANUSWON_SWR_2V 0 -+#define ANACTRL_MANUSWON_SWR_1P9V 1 -+#define ANACTRL_MANUSWON_SWR_1P8V 2 -+#define ANACTRL_MANUSWON_SWR_1P7V 3 -+#define ANACTRL_MANUSWON_BW3_4M 0x2 -+#define ANACTRL_RESTART_CAL 0x1 -+#define ANACTRL_DEF 0x02EF -+ -+#define MIIDBG_SYSMODCTRL 0x04 -+#define SYSMODCTRL_IECHOADJ_PFMH_PHY 0x8000 -+#define SYSMODCTRL_IECHOADJ_BIASGEN 0x4000 -+#define SYSMODCTRL_IECHOADJ_PFML_PHY 0x2000 -+#define SYSMODCTRL_IECHOADJ_PS_MASK 3U -+#define SYSMODCTRL_IECHOADJ_PS_SHIFT 10 -+#define SYSMODCTRL_IECHOADJ_PS_40 3 -+#define SYSMODCTRL_IECHOADJ_PS_20 2 -+#define SYSMODCTRL_IECHOADJ_PS_0 1 -+#define SYSMODCTRL_IECHOADJ_10BT_100MV 0x40 /* 1:100mv, 0:200mv */ -+#define SYSMODCTRL_IECHOADJ_HLFAP_MASK 3U -+#define SYSMODCTRL_IECHOADJ_HLFAP_SHIFT 4 -+#define SYSMODCTRL_IECHOADJ_VDFULBW 0x8 -+#define SYSMODCTRL_IECHOADJ_VDBIASHLF 0x4 -+#define SYSMODCTRL_IECHOADJ_VDAMPHLF 0x2 -+#define SYSMODCTRL_IECHOADJ_VDLANSW 0x1 -+#define SYSMODCTRL_IECHOADJ_DEF 0x88BB /* ???? */ -+ -+/* for l1d & l2cb */ -+#define SYSMODCTRL_IECHOADJ_CUR_ADD 0x8000 -+#define SYSMODCTRL_IECHOADJ_CUR_MASK 7U -+#define SYSMODCTRL_IECHOADJ_CUR_SHIFT 12 -+#define SYSMODCTRL_IECHOADJ_VOL_MASK 0xFU -+#define SYSMODCTRL_IECHOADJ_VOL_SHIFT 8 -+#define SYSMODCTRL_IECHOADJ_VOL_17ALL 3 -+#define SYSMODCTRL_IECHOADJ_VOL_100M15 1 -+#define SYSMODCTRL_IECHOADJ_VOL_10M17 0 -+#define SYSMODCTRL_IECHOADJ_BIAS1_MASK 0xFU -+#define SYSMODCTRL_IECHOADJ_BIAS1_SHIFT 4 -+#define SYSMODCTRL_IECHOADJ_BIAS2_MASK 0xFU -+#define SYSMODCTRL_IECHOADJ_BIAS2_SHIFT 0 -+#define L1D_SYSMODCTRL_IECHOADJ_DEF 0x4FBB -+ -+#define MIIDBG_SRDSYSMOD 0x05 -+#define SRDSYSMOD_LCKDET_EN 0x2000 -+#define SRDSYSMOD_PLL_EN 0x800 -+#define SRDSYSMOD_SEL_HSP 0x400 -+#define SRDSYSMOD_HLFTXDR 0x200 -+#define SRDSYSMOD_TXCLK_DELAY_EN 0x100 -+#define SRDSYSMOD_TXELECIDLE 0x80 -+#define SRDSYSMOD_DEEMP_EN 0x40 -+#define SRDSYSMOD_MS_PAD 0x4 -+#define SRDSYSMOD_CDR_ADC_VLTG 0x2 -+#define SRDSYSMOD_CDR_DAC_1MA 0x1 -+#define SRDSYSMOD_DEF 0x2C46 -+ -+#define MIIDBG_CFGLPSPD 0x0A -+#define CFGLPSPD_RSTCNT_MASK 3U -+#define CFGLPSPD_RSTCNT_SHIFT 14 -+#define CFGLPSPD_RSTCNT_CLK125SW 0x2000 -+ -+#define MIIDBG_HIBNEG 0x0B -+#define HIBNEG_PSHIB_EN 0x8000 -+#define HIBNEG_WAKE_BOTH 0x4000 -+#define HIBNEG_ONOFF_ANACHG_SUDEN 0x2000 -+#define HIBNEG_HIB_PULSE 0x1000 -+#define HIBNEG_GATE_25M_EN 0x800 -+#define HIBNEG_RST_80U 0x400 -+#define HIBNEG_RST_TIMER_MASK 3U -+#define HIBNEG_RST_TIMER_SHIFT 8 -+#define HIBNEG_GTX_CLK_DELAY_MASK 3U -+#define HIBNEG_GTX_CLK_DELAY_SHIFT 5 -+#define HIBNEG_BYPSS_BRKTIMER 0x10 -+#define HIBNEG_DEF 0xBC40 -+ -+#define MIIDBG_TST10BTCFG 0x12 -+#define TST10BTCFG_INTV_TIMER_MASK 3U -+#define TST10BTCFG_INTV_TIMER_SHIFT 14 -+#define TST10BTCFG_TRIGER_TIMER_MASK 3U -+#define TST10BTCFG_TRIGER_TIMER_SHIFT 12 -+#define TST10BTCFG_DIV_MAN_MLT3_EN 0x800 -+#define TST10BTCFG_OFF_DAC_IDLE 0x400 -+#define TST10BTCFG_LPBK_DEEP 0x4 /* 1:deep,0:shallow */ -+#define TST10BTCFG_DEF 0x4C04 -+ -+#define MIIDBG_AZ_ANADECT 0x15 -+#define AZ_ANADECT_10BTRX_TH 0x8000 -+#define AZ_ANADECT_BOTH_01CHNL 0x4000 -+#define AZ_ANADECT_INTV_MASK 0x3FU -+#define AZ_ANADECT_INTV_SHIFT 8 -+#define AZ_ANADECT_THRESH_MASK 0xFU -+#define AZ_ANADECT_THRESH_SHIFT 4 -+#define AZ_ANADECT_CHNL_MASK 0xFU -+#define AZ_ANADECT_CHNL_SHIFT 0 -+#define AZ_ANADECT_DEF 0x3220 -+#define AZ_ANADECT_LONG 0xb210 -+ -+#define MIIDBG_MSE16DB 0x18 /* l1d */ -+#define L1D_MSE16DB_UP 0x05EA -+#define L1D_MSE16DB_DOWN 0x02EA -+ -+#define MIIDBG_LEGCYPS 0x29 -+#define LEGCYPS_EN 0x8000 -+#define LEGCYPS_DAC_AMP1000_MASK 7U -+#define LEGCYPS_DAC_AMP1000_SHIFT 12 -+#define LEGCYPS_DAC_AMP100_MASK 7U -+#define LEGCYPS_DAC_AMP100_SHIFT 9 -+#define LEGCYPS_DAC_AMP10_MASK 7U -+#define LEGCYPS_DAC_AMP10_SHIFT 6 -+#define LEGCYPS_UNPLUG_TIMER_MASK 7U -+#define LEGCYPS_UNPLUG_TIMER_SHIFT 3 -+#define LEGCYPS_UNPLUG_DECT_EN 0x4 -+#define LEGCYPS_ECNC_PS_EN 0x1 -+#define L1D_LEGCYPS_DEF 0x129D -+#define L1C_LEGCYPS_DEF 0x36DD -+ -+#define MIIDBG_TST100BTCFG 0x36 -+#define TST100BTCFG_NORMAL_BW_EN 0x8000 -+#define TST100BTCFG_BADLNK_BYPASS 0x4000 -+#define TST100BTCFG_SHORTCABL_TH_MASK 0x3FU -+#define TST100BTCFG_SHORTCABL_TH_SHIFT 8 -+#define TST100BTCFG_LITCH_EN 0x80 -+#define TST100BTCFG_VLT_SW 0x40 -+#define TST100BTCFG_LONGCABL_TH_MASK 0x3FU -+#define TST100BTCFG_LONGCABL_TH_SHIFT 0 -+#define TST100BTCFG_DEF 0xE12C -+ -+#define MIIDBG_VOLT_CTRL 0x3B /* only for l2cb 1 & 2 */ -+#define VOLT_CTRL_CABLE1TH_MASK 0x1FFU -+#define VOLT_CTRL_CABLE1TH_SHIFT 7 -+#define VOLT_CTRL_AMPCTRL_MASK 3U -+#define VOLT_CTRL_AMPCTRL_SHIFT 5 -+#define VOLT_CTRL_SW_BYPASS 0x10 -+#define VOLT_CTRL_SWLOWEST 0x8 -+#define VOLT_CTRL_DACAMP10_MASK 7U -+#define VOLT_CTRL_DACAMP10_SHIFT 0 -+ -+#define MIIDBG_CABLE1TH_DET 0x3E -+#define CABLE1TH_DET_EN 0x8000 -+ -+ -+/******* dev 3 *********/ -+#define MIIEXT_PCS 3 -+ -+#define MIIEXT_CLDCTRL3 0x8003 -+#define CLDCTRL3_BP_CABLE1TH_DET_GT 0x8000 -+#define CLDCTRL3_AZ_DISAMP 0x1000 -+#define L2CB_CLDCTRL3 0x4D19 -+#define L1D_CLDCTRL3 0xDD19 -+ -+#define MIIEXT_CLDCTRL6 0x8006 -+#define CLDCTRL6_CAB_LEN_MASK 0x1FFU -+#define CLDCTRL6_CAB_LEN_SHIFT 0 -+#define CLDCTRL6_CAB_LEN_SHORT 0x50 -+ -+/********* dev 7 **********/ -+#define MIIEXT_ANEG 7 -+ -+#define MIIEXT_LOCAL_EEEADV 0x3C -+#define LOCAL_EEEADV_1000BT 0x4 -+#define LOCAL_EEEADV_100BT 0x2 -+ -+#define MIIEXT_REMOTE_EEEADV 0x3D -+#define REMOTE_EEEADV_1000BT 0x4 -+#define REMOTE_EEEADV_100BT 0x2 -+ -+#define MIIEXT_EEE_ANEG 0x8000 -+#define EEE_ANEG_1000M 0x4 -+#define EEE_ANEG_100M 0x2 - - #endif /*_ATL1C_HW_H_*/ -diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c -index 1ef0c92..9cc1570 100644 ---- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c -+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c -@@ -24,14 +24,6 @@ - #define ATL1C_DRV_VERSION "1.0.1.0-NAPI" - char atl1c_driver_name[] = "atl1c"; - char atl1c_driver_version[] = ATL1C_DRV_VERSION; --#define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062 --#define PCI_DEVICE_ID_ATTANSIC_L1C 0x1063 --#define PCI_DEVICE_ID_ATHEROS_L2C_B 0x2060 /* AR8152 v1.1 Fast 10/100 */ --#define PCI_DEVICE_ID_ATHEROS_L2C_B2 0x2062 /* AR8152 v2.0 Fast 10/100 */ --#define PCI_DEVICE_ID_ATHEROS_L1D 0x1073 /* AR8151 v1.0 Gigabit 1000 */ --#define PCI_DEVICE_ID_ATHEROS_L1D_2_0 0x1083 /* AR8151 v2.0 Gigabit 1000 */ --#define L2CB_V10 0xc0 --#define L2CB_V11 0xc1 - - /* - * atl1c_pci_tbl - PCI Device ID Table -@@ -54,70 +46,72 @@ static DEFINE_PCI_DEVICE_TABLE(atl1c_pci_tbl) = { - }; - MODULE_DEVICE_TABLE(pci, atl1c_pci_tbl); - --MODULE_AUTHOR("Jie Yang "); --MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver"); -+MODULE_AUTHOR("Jie Yang"); -+MODULE_AUTHOR("Qualcomm Atheros Inc., "); -+MODULE_DESCRIPTION("Qualcom Atheros 100/1000M Ethernet Network Driver"); - MODULE_LICENSE("GPL"); - MODULE_VERSION(ATL1C_DRV_VERSION); - - static int atl1c_stop_mac(struct atl1c_hw *hw); --static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw); --static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw); - static void atl1c_disable_l0s_l1(struct atl1c_hw *hw); --static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup); --static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter); --static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que, -+static void atl1c_set_aspm(struct atl1c_hw *hw, u16 link_speed); -+static void atl1c_start_mac(struct atl1c_adapter *adapter); -+static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, - int *work_done, int work_to_do); - static int atl1c_up(struct atl1c_adapter *adapter); - static void atl1c_down(struct atl1c_adapter *adapter); -+static int atl1c_reset_mac(struct atl1c_hw *hw); -+static void atl1c_reset_dma_ring(struct atl1c_adapter *adapter); -+static int atl1c_configure(struct atl1c_adapter *adapter); -+static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter); - - static const u16 atl1c_pay_load_size[] = { - 128, 256, 512, 1024, 2048, 4096, - }; - --static const u16 atl1c_rfd_prod_idx_regs[AT_MAX_RECEIVE_QUEUE] = --{ -- REG_MB_RFD0_PROD_IDX, -- REG_MB_RFD1_PROD_IDX, -- REG_MB_RFD2_PROD_IDX, -- REG_MB_RFD3_PROD_IDX --}; -- --static const u16 atl1c_rfd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] = --{ -- REG_RFD0_HEAD_ADDR_LO, -- REG_RFD1_HEAD_ADDR_LO, -- REG_RFD2_HEAD_ADDR_LO, -- REG_RFD3_HEAD_ADDR_LO --}; -- --static const u16 atl1c_rrd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] = --{ -- REG_RRD0_HEAD_ADDR_LO, -- REG_RRD1_HEAD_ADDR_LO, -- REG_RRD2_HEAD_ADDR_LO, -- REG_RRD3_HEAD_ADDR_LO --}; - - static const u32 atl1c_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | - NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP; - static void atl1c_pcie_patch(struct atl1c_hw *hw) - { -- u32 data; -+ u32 mst_data, data; - -- AT_READ_REG(hw, REG_PCIE_PHYMISC, &data); -- data |= PCIE_PHYMISC_FORCE_RCV_DET; -- AT_WRITE_REG(hw, REG_PCIE_PHYMISC, data); -+ /* pclk sel could switch to 25M */ -+ AT_READ_REG(hw, REG_MASTER_CTRL, &mst_data); -+ mst_data &= ~MASTER_CTRL_CLK_SEL_DIS; -+ AT_WRITE_REG(hw, REG_MASTER_CTRL, mst_data); - -+ /* WoL/PCIE related settings */ -+ if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) { -+ AT_READ_REG(hw, REG_PCIE_PHYMISC, &data); -+ data |= PCIE_PHYMISC_FORCE_RCV_DET; -+ AT_WRITE_REG(hw, REG_PCIE_PHYMISC, data); -+ } else { /* new dev set bit5 of MASTER */ -+ if (!(mst_data & MASTER_CTRL_WAKEN_25M)) -+ AT_WRITE_REG(hw, REG_MASTER_CTRL, -+ mst_data | MASTER_CTRL_WAKEN_25M); -+ } -+ /* aspm/PCIE setting only for l2cb 1.0 */ - if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) { - AT_READ_REG(hw, REG_PCIE_PHYMISC2, &data); -- -- data &= ~(PCIE_PHYMISC2_SERDES_CDR_MASK << -- PCIE_PHYMISC2_SERDES_CDR_SHIFT); -- data |= 3 << PCIE_PHYMISC2_SERDES_CDR_SHIFT; -- data &= ~(PCIE_PHYMISC2_SERDES_TH_MASK << -- PCIE_PHYMISC2_SERDES_TH_SHIFT); -- data |= 3 << PCIE_PHYMISC2_SERDES_TH_SHIFT; -+ data = FIELD_SETX(data, PCIE_PHYMISC2_CDR_BW, -+ L2CB1_PCIE_PHYMISC2_CDR_BW); -+ data = FIELD_SETX(data, PCIE_PHYMISC2_L0S_TH, -+ L2CB1_PCIE_PHYMISC2_L0S_TH); - AT_WRITE_REG(hw, REG_PCIE_PHYMISC2, data); -+ /* extend L1 sync timer */ -+ AT_READ_REG(hw, REG_LINK_CTRL, &data); -+ data |= LINK_CTRL_EXT_SYNC; -+ AT_WRITE_REG(hw, REG_LINK_CTRL, data); -+ } -+ /* l2cb 1.x & l1d 1.x */ -+ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d) { -+ AT_READ_REG(hw, REG_PM_CTRL, &data); -+ data |= PM_CTRL_L0S_BUFSRX_EN; -+ AT_WRITE_REG(hw, REG_PM_CTRL, data); -+ /* clear vendor msg */ -+ AT_READ_REG(hw, REG_DMA_DBG, &data); -+ AT_WRITE_REG(hw, REG_DMA_DBG, data & ~DMA_DBG_VENDOR_MSG); - } - } - -@@ -130,6 +124,7 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag) - u32 data; - u32 pci_cmd; - struct pci_dev *pdev = hw->adapter->pdev; -+ int pos; - - AT_READ_REG(hw, PCI_COMMAND, &pci_cmd); - pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; -@@ -142,14 +137,23 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag) - */ - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); -+ /* wol sts read-clear */ -+ AT_READ_REG(hw, REG_WOL_CTRL, &data); -+ AT_WRITE_REG(hw, REG_WOL_CTRL, 0); - - /* - * Mask some pcie error bits - */ -- AT_READ_REG(hw, REG_PCIE_UC_SEVERITY, &data); -- data &= ~PCIE_UC_SERVRITY_DLP; -- data &= ~PCIE_UC_SERVRITY_FCP; -- AT_WRITE_REG(hw, REG_PCIE_UC_SEVERITY, data); -+ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); -+ pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data); -+ data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP); -+ pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data); -+ /* clear error status */ -+ pci_write_config_word(pdev, pci_pcie_cap(pdev) + PCI_EXP_DEVSTA, -+ PCI_EXP_DEVSTA_NFED | -+ PCI_EXP_DEVSTA_FED | -+ PCI_EXP_DEVSTA_CED | -+ PCI_EXP_DEVSTA_URD); - - AT_READ_REG(hw, REG_LTSSM_ID_CTRL, &data); - data &= ~LTSSM_ID_EN_WRO; -@@ -158,11 +162,6 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag) - atl1c_pcie_patch(hw); - if (flag & ATL1C_PCIE_L0S_L1_DISABLE) - atl1c_disable_l0s_l1(hw); -- if (flag & ATL1C_PCIE_PHY_RESET) -- AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT); -- else -- AT_WRITE_REG(hw, REG_GPHY_CTRL, -- GPHY_CTRL_DEFAULT | GPHY_CTRL_EXT_RESET); - - msleep(5); - } -@@ -207,14 +206,14 @@ static inline void atl1c_irq_reset(struct atl1c_adapter *adapter) - * atl1c_wait_until_idle - wait up to AT_HW_MAX_IDLE_DELAY reads - * of the idle status register until the device is actually idle - */ --static u32 atl1c_wait_until_idle(struct atl1c_hw *hw) -+static u32 atl1c_wait_until_idle(struct atl1c_hw *hw, u32 modu_ctrl) - { - int timeout; - u32 data; - - for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) { - AT_READ_REG(hw, REG_IDLE_STATUS, &data); -- if ((data & IDLE_STATUS_MASK) == 0) -+ if ((data & modu_ctrl) == 0) - return 0; - msleep(1); - } -@@ -261,14 +260,15 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) - - if ((phy_data & BMSR_LSTATUS) == 0) { - /* link down */ -- hw->hibernate = true; -- if (atl1c_stop_mac(hw) != 0) -- if (netif_msg_hw(adapter)) -- dev_warn(&pdev->dev, "stop mac failed\n"); -- atl1c_set_aspm(hw, false); - netif_carrier_off(netdev); -- atl1c_phy_reset(hw); -- atl1c_phy_init(&adapter->hw); -+ hw->hibernate = true; -+ if (atl1c_reset_mac(hw) != 0) -+ if (netif_msg_hw(adapter)) -+ dev_warn(&pdev->dev, "reset mac failed\n"); -+ atl1c_set_aspm(hw, SPEED_0); -+ atl1c_post_phy_linkchg(hw, SPEED_0); -+ atl1c_reset_dma_ring(adapter); -+ atl1c_configure(adapter); - } else { - /* Link Up */ - hw->hibernate = false; -@@ -283,10 +283,9 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) - adapter->link_duplex != duplex) { - adapter->link_speed = speed; - adapter->link_duplex = duplex; -- atl1c_set_aspm(hw, true); -- atl1c_enable_tx_ctrl(hw); -- atl1c_enable_rx_ctrl(hw); -- atl1c_setup_mac_ctrl(adapter); -+ atl1c_set_aspm(hw, speed); -+ atl1c_post_phy_linkchg(hw, speed); -+ atl1c_start_mac(adapter); - if (netif_msg_link(adapter)) - dev_info(&pdev->dev, - "%s: %s NIC Link is Up<%d Mbps %s>\n", -@@ -337,6 +336,9 @@ static void atl1c_common_task(struct work_struct *work) - adapter = container_of(work, struct atl1c_adapter, common_task); - netdev = adapter->netdev; - -+ if (test_bit(__AT_DOWN, &adapter->flags)) -+ return; -+ - if (test_and_clear_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event)) { - netif_device_detach(netdev); - atl1c_down(adapter); -@@ -345,8 +347,11 @@ static void atl1c_common_task(struct work_struct *work) - } - - if (test_and_clear_bit(ATL1C_WORK_EVENT_LINK_CHANGE, -- &adapter->work_event)) -+ &adapter->work_event)) { -+ atl1c_irq_disable(adapter); - atl1c_check_link_status(adapter); -+ atl1c_irq_enable(adapter); -+ } - } - - -@@ -470,7 +475,7 @@ static int atl1c_set_mac_addr(struct net_device *netdev, void *p) - memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); - netdev->addr_assign_type &= ~NET_ADDR_RANDOM; - -- atl1c_hw_set_mac_addr(&adapter->hw); -+ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr); - - return 0; - } -@@ -523,11 +528,16 @@ static int atl1c_set_features(struct net_device *netdev, - static int atl1c_change_mtu(struct net_device *netdev, int new_mtu) - { - struct atl1c_adapter *adapter = netdev_priv(netdev); -+ struct atl1c_hw *hw = &adapter->hw; - int old_mtu = netdev->mtu; - int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; - -- if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || -- (max_frame > MAX_JUMBO_FRAME_SIZE)) { -+ /* Fast Ethernet controller doesn't support jumbo packet */ -+ if (((hw->nic_type == athr_l2c || -+ hw->nic_type == athr_l2c_b || -+ hw->nic_type == athr_l2c_b2) && new_mtu > ETH_DATA_LEN) || -+ max_frame < ETH_ZLEN + ETH_FCS_LEN || -+ max_frame > MAX_JUMBO_FRAME_SIZE) { - if (netif_msg_link(adapter)) - dev_warn(&adapter->pdev->dev, "invalid MTU setting\n"); - return -EINVAL; -@@ -543,14 +553,6 @@ static int atl1c_change_mtu(struct net_device *netdev, int new_mtu) - netdev_update_features(netdev); - atl1c_up(adapter); - clear_bit(__AT_RESETTING, &adapter->flags); -- if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) { -- u32 phy_data; -- -- AT_READ_REG(&adapter->hw, 0x1414, &phy_data); -- phy_data |= 0x10000000; -- AT_WRITE_REG(&adapter->hw, 0x1414, phy_data); -- } -- - } - return 0; - } -@@ -563,7 +565,7 @@ static int atl1c_mdio_read(struct net_device *netdev, int phy_id, int reg_num) - struct atl1c_adapter *adapter = netdev_priv(netdev); - u16 result; - -- atl1c_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result); -+ atl1c_read_phy_reg(&adapter->hw, reg_num, &result); - return result; - } - -@@ -572,7 +574,7 @@ static void atl1c_mdio_write(struct net_device *netdev, int phy_id, - { - struct atl1c_adapter *adapter = netdev_priv(netdev); - -- atl1c_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val); -+ atl1c_write_phy_reg(&adapter->hw, reg_num, val); - } - - /* -@@ -687,21 +689,15 @@ static void atl1c_set_mac_type(struct atl1c_hw *hw) - - static int atl1c_setup_mac_funcs(struct atl1c_hw *hw) - { -- u32 phy_status_data; - u32 link_ctrl_data; - - atl1c_set_mac_type(hw); -- AT_READ_REG(hw, REG_PHY_STATUS, &phy_status_data); - AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data); - - hw->ctrl_flags = ATL1C_INTR_MODRT_ENABLE | - ATL1C_TXQ_MODE_ENHANCE; -- if (link_ctrl_data & LINK_CTRL_L0S_EN) -- hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT; -- if (link_ctrl_data & LINK_CTRL_L1_EN) -- hw->ctrl_flags |= ATL1C_ASPM_L1_SUPPORT; -- if (link_ctrl_data & LINK_CTRL_EXT_SYNC) -- hw->ctrl_flags |= ATL1C_LINK_EXT_SYNC; -+ hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT | -+ ATL1C_ASPM_L1_SUPPORT; - hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON; - - if (hw->nic_type == athr_l1c || -@@ -710,6 +706,55 @@ static int atl1c_setup_mac_funcs(struct atl1c_hw *hw) - hw->link_cap_flags |= ATL1C_LINK_CAP_1000M; - return 0; - } -+ -+struct atl1c_platform_patch { -+ u16 pci_did; -+ u8 pci_revid; -+ u16 subsystem_vid; -+ u16 subsystem_did; -+ u32 patch_flag; -+#define ATL1C_LINK_PATCH 0x1 -+}; -+static const struct atl1c_platform_patch plats[] __devinitdata = { -+{0x2060, 0xC1, 0x1019, 0x8152, 0x1}, -+{0x2060, 0xC1, 0x1019, 0x2060, 0x1}, -+{0x2060, 0xC1, 0x1019, 0xE000, 0x1}, -+{0x2062, 0xC0, 0x1019, 0x8152, 0x1}, -+{0x2062, 0xC0, 0x1019, 0x2062, 0x1}, -+{0x2062, 0xC0, 0x1458, 0xE000, 0x1}, -+{0x2062, 0xC1, 0x1019, 0x8152, 0x1}, -+{0x2062, 0xC1, 0x1019, 0x2062, 0x1}, -+{0x2062, 0xC1, 0x1458, 0xE000, 0x1}, -+{0x2062, 0xC1, 0x1565, 0x2802, 0x1}, -+{0x2062, 0xC1, 0x1565, 0x2801, 0x1}, -+{0x1073, 0xC0, 0x1019, 0x8151, 0x1}, -+{0x1073, 0xC0, 0x1019, 0x1073, 0x1}, -+{0x1073, 0xC0, 0x1458, 0xE000, 0x1}, -+{0x1083, 0xC0, 0x1458, 0xE000, 0x1}, -+{0x1083, 0xC0, 0x1019, 0x8151, 0x1}, -+{0x1083, 0xC0, 0x1019, 0x1083, 0x1}, -+{0x1083, 0xC0, 0x1462, 0x7680, 0x1}, -+{0x1083, 0xC0, 0x1565, 0x2803, 0x1}, -+{0}, -+}; -+ -+static void __devinit atl1c_patch_assign(struct atl1c_hw *hw) -+{ -+ int i = 0; -+ -+ hw->msi_lnkpatch = false; -+ -+ while (plats[i].pci_did != 0) { -+ if (plats[i].pci_did == hw->device_id && -+ plats[i].pci_revid == hw->revision_id && -+ plats[i].subsystem_vid == hw->subsystem_vendor_id && -+ plats[i].subsystem_did == hw->subsystem_id) { -+ if (plats[i].patch_flag & ATL1C_LINK_PATCH) -+ hw->msi_lnkpatch = true; -+ } -+ i++; -+ } -+} - /* - * atl1c_sw_init - Initialize general software structures (struct atl1c_adapter) - * @adapter: board private structure to initialize -@@ -729,9 +774,8 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) - device_set_wakeup_enable(&pdev->dev, false); - adapter->link_speed = SPEED_0; - adapter->link_duplex = FULL_DUPLEX; -- adapter->num_rx_queues = AT_DEF_RECEIVE_QUEUE; - adapter->tpd_ring[0].count = 1024; -- adapter->rfd_ring[0].count = 512; -+ adapter->rfd_ring.count = 512; - - hw->vendor_id = pdev->vendor; - hw->device_id = pdev->device; -@@ -746,26 +790,18 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) - dev_err(&pdev->dev, "set mac function pointers failed\n"); - return -1; - } -+ atl1c_patch_assign(hw); -+ - hw->intr_mask = IMR_NORMAL_MASK; - hw->phy_configured = false; - hw->preamble_len = 7; - hw->max_frame_size = adapter->netdev->mtu; -- if (adapter->num_rx_queues < 2) { -- hw->rss_type = atl1c_rss_disable; -- hw->rss_mode = atl1c_rss_mode_disable; -- } else { -- hw->rss_type = atl1c_rss_ipv4; -- hw->rss_mode = atl1c_rss_mul_que_mul_int; -- hw->rss_hash_bits = 16; -- } - hw->autoneg_advertised = ADVERTISED_Autoneg; - hw->indirect_tab = 0xE4E4E4E4; - hw->base_cpu = 0; - - hw->ict = 50000; /* 100ms */ - hw->smb_timer = 200000; /* 400ms */ -- hw->cmb_tpd = 4; -- hw->cmb_tx_timer = 1; /* 2 us */ - hw->rx_imt = 200; - hw->tx_imt = 1000; - -@@ -773,9 +809,6 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) - hw->rfd_burst = 8; - hw->dma_order = atl1c_dma_ord_out; - hw->dmar_block = atl1c_dma_req_1024; -- hw->dmaw_block = atl1c_dma_req_1024; -- hw->dmar_dly_cnt = 15; -- hw->dmaw_dly_cnt = 4; - - if (atl1c_alloc_queues(adapter)) { - dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); -@@ -851,24 +884,22 @@ static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter, - */ - static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter) - { -- struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring; -- struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring; -+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; -+ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct atl1c_buffer *buffer_info; - struct pci_dev *pdev = adapter->pdev; -- int i, j; -+ int j; - -- for (i = 0; i < adapter->num_rx_queues; i++) { -- for (j = 0; j < rfd_ring[i].count; j++) { -- buffer_info = &rfd_ring[i].buffer_info[j]; -- atl1c_clean_buffer(pdev, buffer_info, 0); -- } -- /* zero out the descriptor ring */ -- memset(rfd_ring[i].desc, 0, rfd_ring[i].size); -- rfd_ring[i].next_to_clean = 0; -- rfd_ring[i].next_to_use = 0; -- rrd_ring[i].next_to_use = 0; -- rrd_ring[i].next_to_clean = 0; -+ for (j = 0; j < rfd_ring->count; j++) { -+ buffer_info = &rfd_ring->buffer_info[j]; -+ atl1c_clean_buffer(pdev, buffer_info, 0); - } -+ /* zero out the descriptor ring */ -+ memset(rfd_ring->desc, 0, rfd_ring->size); -+ rfd_ring->next_to_clean = 0; -+ rfd_ring->next_to_use = 0; -+ rrd_ring->next_to_use = 0; -+ rrd_ring->next_to_clean = 0; - } - - /* -@@ -877,8 +908,8 @@ static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter) - static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter) - { - struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring; -- struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring; -- struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring; -+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; -+ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct atl1c_buffer *buffer_info; - int i, j; - -@@ -890,15 +921,13 @@ static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter) - ATL1C_SET_BUFFER_STATE(&buffer_info[i], - ATL1C_BUFFER_FREE); - } -- for (i = 0; i < adapter->num_rx_queues; i++) { -- rfd_ring[i].next_to_use = 0; -- rfd_ring[i].next_to_clean = 0; -- rrd_ring[i].next_to_use = 0; -- rrd_ring[i].next_to_clean = 0; -- for (j = 0; j < rfd_ring[i].count; j++) { -- buffer_info = &rfd_ring[i].buffer_info[j]; -- ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); -- } -+ rfd_ring->next_to_use = 0; -+ rfd_ring->next_to_clean = 0; -+ rrd_ring->next_to_use = 0; -+ rrd_ring->next_to_clean = 0; -+ for (j = 0; j < rfd_ring->count; j++) { -+ buffer_info = &rfd_ring->buffer_info[j]; -+ ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); - } - } - -@@ -935,27 +964,23 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) - { - struct pci_dev *pdev = adapter->pdev; - struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring; -- struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring; -- struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring; -+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; -+ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct atl1c_ring_header *ring_header = &adapter->ring_header; -- int num_rx_queues = adapter->num_rx_queues; - int size; - int i; - int count = 0; - int rx_desc_count = 0; - u32 offset = 0; - -- rrd_ring[0].count = rfd_ring[0].count; -+ rrd_ring->count = rfd_ring->count; - for (i = 1; i < AT_MAX_TRANSMIT_QUEUE; i++) - tpd_ring[i].count = tpd_ring[0].count; - -- for (i = 1; i < adapter->num_rx_queues; i++) -- rfd_ring[i].count = rrd_ring[i].count = rfd_ring[0].count; -- - /* 2 tpd queue, one high priority queue, - * another normal priority queue */ - size = sizeof(struct atl1c_buffer) * (tpd_ring->count * 2 + -- rfd_ring->count * num_rx_queues); -+ rfd_ring->count); - tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL); - if (unlikely(!tpd_ring->buffer_info)) { - dev_err(&pdev->dev, "kzalloc failed, size = %d\n", -@@ -968,12 +993,11 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) - count += tpd_ring[i].count; - } - -- for (i = 0; i < num_rx_queues; i++) { -- rfd_ring[i].buffer_info = -- (struct atl1c_buffer *) (tpd_ring->buffer_info + count); -- count += rfd_ring[i].count; -- rx_desc_count += rfd_ring[i].count; -- } -+ rfd_ring->buffer_info = -+ (struct atl1c_buffer *) (tpd_ring->buffer_info + count); -+ count += rfd_ring->count; -+ rx_desc_count += rfd_ring->count; -+ - /* - * real ring DMA buffer - * each ring/block may need up to 8 bytes for alignment, hence the -@@ -983,8 +1007,7 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) - sizeof(struct atl1c_tpd_desc) * tpd_ring->count * 2 + - sizeof(struct atl1c_rx_free_desc) * rx_desc_count + - sizeof(struct atl1c_recv_ret_status) * rx_desc_count + -- sizeof(struct atl1c_hw_stats) + -- 8 * 4 + 8 * 2 * num_rx_queues; -+ 8 * 4; - - ring_header->desc = pci_alloc_consistent(pdev, ring_header->size, - &ring_header->dma); -@@ -1005,25 +1028,18 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) - offset += roundup(tpd_ring[i].size, 8); - } - /* init RFD ring */ -- for (i = 0; i < num_rx_queues; i++) { -- rfd_ring[i].dma = ring_header->dma + offset; -- rfd_ring[i].desc = (u8 *) ring_header->desc + offset; -- rfd_ring[i].size = sizeof(struct atl1c_rx_free_desc) * -- rfd_ring[i].count; -- offset += roundup(rfd_ring[i].size, 8); -- } -+ rfd_ring->dma = ring_header->dma + offset; -+ rfd_ring->desc = (u8 *) ring_header->desc + offset; -+ rfd_ring->size = sizeof(struct atl1c_rx_free_desc) * rfd_ring->count; -+ offset += roundup(rfd_ring->size, 8); - - /* init RRD ring */ -- for (i = 0; i < num_rx_queues; i++) { -- rrd_ring[i].dma = ring_header->dma + offset; -- rrd_ring[i].desc = (u8 *) ring_header->desc + offset; -- rrd_ring[i].size = sizeof(struct atl1c_recv_ret_status) * -- rrd_ring[i].count; -- offset += roundup(rrd_ring[i].size, 8); -- } -+ rrd_ring->dma = ring_header->dma + offset; -+ rrd_ring->desc = (u8 *) ring_header->desc + offset; -+ rrd_ring->size = sizeof(struct atl1c_recv_ret_status) * -+ rrd_ring->count; -+ offset += roundup(rrd_ring->size, 8); - -- adapter->smb.dma = ring_header->dma + offset; -- adapter->smb.smb = (u8 *)ring_header->desc + offset; - return 0; - - err_nomem: -@@ -1034,26 +1050,20 @@ err_nomem: - static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) - { - struct atl1c_hw *hw = &adapter->hw; -- struct atl1c_rfd_ring *rfd_ring = (struct atl1c_rfd_ring *) -- adapter->rfd_ring; -- struct atl1c_rrd_ring *rrd_ring = (struct atl1c_rrd_ring *) -- adapter->rrd_ring; -+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; -+ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *) - adapter->tpd_ring; -- struct atl1c_cmb *cmb = (struct atl1c_cmb *) &adapter->cmb; -- struct atl1c_smb *smb = (struct atl1c_smb *) &adapter->smb; -- int i; -- u32 data; - - /* TPD */ - AT_WRITE_REG(hw, REG_TX_BASE_ADDR_HI, - (u32)((tpd_ring[atl1c_trans_normal].dma & - AT_DMA_HI_ADDR_MASK) >> 32)); - /* just enable normal priority TX queue */ -- AT_WRITE_REG(hw, REG_NTPD_HEAD_ADDR_LO, -+ AT_WRITE_REG(hw, REG_TPD_PRI0_ADDR_LO, - (u32)(tpd_ring[atl1c_trans_normal].dma & - AT_DMA_LO_ADDR_MASK)); -- AT_WRITE_REG(hw, REG_HTPD_HEAD_ADDR_LO, -+ AT_WRITE_REG(hw, REG_TPD_PRI1_ADDR_LO, - (u32)(tpd_ring[atl1c_trans_high].dma & - AT_DMA_LO_ADDR_MASK)); - AT_WRITE_REG(hw, REG_TPD_RING_SIZE, -@@ -1062,31 +1072,21 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) - - /* RFD */ - AT_WRITE_REG(hw, REG_RX_BASE_ADDR_HI, -- (u32)((rfd_ring[0].dma & AT_DMA_HI_ADDR_MASK) >> 32)); -- for (i = 0; i < adapter->num_rx_queues; i++) -- AT_WRITE_REG(hw, atl1c_rfd_addr_lo_regs[i], -- (u32)(rfd_ring[i].dma & AT_DMA_LO_ADDR_MASK)); -+ (u32)((rfd_ring->dma & AT_DMA_HI_ADDR_MASK) >> 32)); -+ AT_WRITE_REG(hw, REG_RFD0_HEAD_ADDR_LO, -+ (u32)(rfd_ring->dma & AT_DMA_LO_ADDR_MASK)); - - AT_WRITE_REG(hw, REG_RFD_RING_SIZE, -- rfd_ring[0].count & RFD_RING_SIZE_MASK); -+ rfd_ring->count & RFD_RING_SIZE_MASK); - AT_WRITE_REG(hw, REG_RX_BUF_SIZE, - adapter->rx_buffer_len & RX_BUF_SIZE_MASK); - - /* RRD */ -- for (i = 0; i < adapter->num_rx_queues; i++) -- AT_WRITE_REG(hw, atl1c_rrd_addr_lo_regs[i], -- (u32)(rrd_ring[i].dma & AT_DMA_LO_ADDR_MASK)); -+ AT_WRITE_REG(hw, REG_RRD0_HEAD_ADDR_LO, -+ (u32)(rrd_ring->dma & AT_DMA_LO_ADDR_MASK)); - AT_WRITE_REG(hw, REG_RRD_RING_SIZE, -- (rrd_ring[0].count & RRD_RING_SIZE_MASK)); -+ (rrd_ring->count & RRD_RING_SIZE_MASK)); - -- /* CMB */ -- AT_WRITE_REG(hw, REG_CMB_BASE_ADDR_LO, cmb->dma & AT_DMA_LO_ADDR_MASK); -- -- /* SMB */ -- AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_HI, -- (u32)((smb->dma & AT_DMA_HI_ADDR_MASK) >> 32)); -- AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_LO, -- (u32)(smb->dma & AT_DMA_LO_ADDR_MASK)); - if (hw->nic_type == athr_l2c_b) { - AT_WRITE_REG(hw, REG_SRAM_RXF_LEN, 0x02a0L); - AT_WRITE_REG(hw, REG_SRAM_TXF_LEN, 0x0100L); -@@ -1097,13 +1097,6 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) - AT_WRITE_REG(hw, REG_TXF_WATER_MARK, 0); /* TX watermark, to enter l1 state.*/ - AT_WRITE_REG(hw, REG_RXD_DMA_CTRL, 0); /* RXD threshold.*/ - } -- if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d_2) { -- /* Power Saving for L2c_B */ -- AT_READ_REG(hw, REG_SERDES_LOCK, &data); -- data |= SERDES_MAC_CLK_SLOWDOWN; -- data |= SERDES_PYH_CLK_SLOWDOWN; -- AT_WRITE_REG(hw, REG_SERDES_LOCK, data); -- } - /* Load all of base address above */ - AT_WRITE_REG(hw, REG_LOAD_PTR, 1); - } -@@ -1111,32 +1104,26 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) - static void atl1c_configure_tx(struct atl1c_adapter *adapter) - { - struct atl1c_hw *hw = &adapter->hw; -- u32 dev_ctrl_data; -- u32 max_pay_load; -+ int max_pay_load; - u16 tx_offload_thresh; - u32 txq_ctrl_data; -- u32 max_pay_load_data; - -- tx_offload_thresh = MAX_TX_OFFLOAD_THRESH; -+ tx_offload_thresh = MAX_TSO_FRAME_SIZE; - AT_WRITE_REG(hw, REG_TX_TSO_OFFLOAD_THRESH, - (tx_offload_thresh >> 3) & TX_TSO_OFFLOAD_THRESH_MASK); -- AT_READ_REG(hw, REG_DEVICE_CTRL, &dev_ctrl_data); -- max_pay_load = (dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT) & -- DEVICE_CTRL_MAX_PAYLOAD_MASK; -- hw->dmaw_block = min_t(u32, max_pay_load, hw->dmaw_block); -- max_pay_load = (dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT) & -- DEVICE_CTRL_MAX_RREQ_SZ_MASK; -+ max_pay_load = pcie_get_readrq(adapter->pdev) >> 8; - hw->dmar_block = min_t(u32, max_pay_load, hw->dmar_block); -- -- txq_ctrl_data = (hw->tpd_burst & TXQ_NUM_TPD_BURST_MASK) << -- TXQ_NUM_TPD_BURST_SHIFT; -- if (hw->ctrl_flags & ATL1C_TXQ_MODE_ENHANCE) -- txq_ctrl_data |= TXQ_CTRL_ENH_MODE; -- max_pay_load_data = (atl1c_pay_load_size[hw->dmar_block] & -- TXQ_TXF_BURST_NUM_MASK) << TXQ_TXF_BURST_NUM_SHIFT; -- if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) -- max_pay_load_data >>= 1; -- txq_ctrl_data |= max_pay_load_data; -+ /* -+ * if BIOS had changed the dam-read-max-length to an invalid value, -+ * restore it to default value -+ */ -+ if (hw->dmar_block < DEVICE_CTRL_MAXRRS_MIN) { -+ pcie_set_readrq(adapter->pdev, 128 << DEVICE_CTRL_MAXRRS_MIN); -+ hw->dmar_block = DEVICE_CTRL_MAXRRS_MIN; -+ } -+ txq_ctrl_data = -+ hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 ? -+ L2CB_TXQ_CFGV : L1C_TXQ_CFGV; - - AT_WRITE_REG(hw, REG_TXQ_CTRL, txq_ctrl_data); - } -@@ -1151,34 +1138,13 @@ static void atl1c_configure_rx(struct atl1c_adapter *adapter) - - if (hw->ctrl_flags & ATL1C_RX_IPV6_CHKSUM) - rxq_ctrl_data |= IPV6_CHKSUM_CTRL_EN; -- if (hw->rss_type == atl1c_rss_ipv4) -- rxq_ctrl_data |= RSS_HASH_IPV4; -- if (hw->rss_type == atl1c_rss_ipv4_tcp) -- rxq_ctrl_data |= RSS_HASH_IPV4_TCP; -- if (hw->rss_type == atl1c_rss_ipv6) -- rxq_ctrl_data |= RSS_HASH_IPV6; -- if (hw->rss_type == atl1c_rss_ipv6_tcp) -- rxq_ctrl_data |= RSS_HASH_IPV6_TCP; -- if (hw->rss_type != atl1c_rss_disable) -- rxq_ctrl_data |= RRS_HASH_CTRL_EN; -- -- rxq_ctrl_data |= (hw->rss_mode & RSS_MODE_MASK) << -- RSS_MODE_SHIFT; -- rxq_ctrl_data |= (hw->rss_hash_bits & RSS_HASH_BITS_MASK) << -- RSS_HASH_BITS_SHIFT; -- if (hw->ctrl_flags & ATL1C_ASPM_CTRL_MON) -- rxq_ctrl_data |= (ASPM_THRUPUT_LIMIT_1M & -- ASPM_THRUPUT_LIMIT_MASK) << ASPM_THRUPUT_LIMIT_SHIFT; - -- AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data); --} -- --static void atl1c_configure_rss(struct atl1c_adapter *adapter) --{ -- struct atl1c_hw *hw = &adapter->hw; -+ /* aspm for gigabit */ -+ if (hw->nic_type != athr_l1d_2 && (hw->device_id & 1) != 0) -+ rxq_ctrl_data = FIELD_SETX(rxq_ctrl_data, ASPM_THRUPUT_LIMIT, -+ ASPM_THRUPUT_LIMIT_100M); - -- AT_WRITE_REG(hw, REG_IDT_TABLE, hw->indirect_tab); -- AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, hw->base_cpu); -+ AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data); - } - - static void atl1c_configure_dma(struct atl1c_adapter *adapter) -@@ -1186,36 +1152,11 @@ static void atl1c_configure_dma(struct atl1c_adapter *adapter) - struct atl1c_hw *hw = &adapter->hw; - u32 dma_ctrl_data; - -- dma_ctrl_data = DMA_CTRL_DMAR_REQ_PRI; -- if (hw->ctrl_flags & ATL1C_CMB_ENABLE) -- dma_ctrl_data |= DMA_CTRL_CMB_EN; -- if (hw->ctrl_flags & ATL1C_SMB_ENABLE) -- dma_ctrl_data |= DMA_CTRL_SMB_EN; -- else -- dma_ctrl_data |= MAC_CTRL_SMB_DIS; -- -- switch (hw->dma_order) { -- case atl1c_dma_ord_in: -- dma_ctrl_data |= DMA_CTRL_DMAR_IN_ORDER; -- break; -- case atl1c_dma_ord_enh: -- dma_ctrl_data |= DMA_CTRL_DMAR_ENH_ORDER; -- break; -- case atl1c_dma_ord_out: -- dma_ctrl_data |= DMA_CTRL_DMAR_OUT_ORDER; -- break; -- default: -- break; -- } -- -- dma_ctrl_data |= (((u32)hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK) -- << DMA_CTRL_DMAR_BURST_LEN_SHIFT; -- dma_ctrl_data |= (((u32)hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK) -- << DMA_CTRL_DMAW_BURST_LEN_SHIFT; -- dma_ctrl_data |= (((u32)hw->dmar_dly_cnt) & DMA_CTRL_DMAR_DLY_CNT_MASK) -- << DMA_CTRL_DMAR_DLY_CNT_SHIFT; -- dma_ctrl_data |= (((u32)hw->dmaw_dly_cnt) & DMA_CTRL_DMAW_DLY_CNT_MASK) -- << DMA_CTRL_DMAW_DLY_CNT_SHIFT; -+ dma_ctrl_data = FIELDX(DMA_CTRL_RORDER_MODE, DMA_CTRL_RORDER_MODE_OUT) | -+ DMA_CTRL_RREQ_PRI_DATA | -+ FIELDX(DMA_CTRL_RREQ_BLEN, hw->dmar_block) | -+ FIELDX(DMA_CTRL_WDLY_CNT, DMA_CTRL_WDLY_CNT_DEF) | -+ FIELDX(DMA_CTRL_RDLY_CNT, DMA_CTRL_RDLY_CNT_DEF); - - AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data); - } -@@ -1230,52 +1171,53 @@ static int atl1c_stop_mac(struct atl1c_hw *hw) - u32 data; - - AT_READ_REG(hw, REG_RXQ_CTRL, &data); -- data &= ~(RXQ1_CTRL_EN | RXQ2_CTRL_EN | -- RXQ3_CTRL_EN | RXQ_CTRL_EN); -+ data &= ~RXQ_CTRL_EN; - AT_WRITE_REG(hw, REG_RXQ_CTRL, data); - - AT_READ_REG(hw, REG_TXQ_CTRL, &data); - data &= ~TXQ_CTRL_EN; -- AT_WRITE_REG(hw, REG_TWSI_CTRL, data); -+ AT_WRITE_REG(hw, REG_TXQ_CTRL, data); - -- atl1c_wait_until_idle(hw); -+ atl1c_wait_until_idle(hw, IDLE_STATUS_RXQ_BUSY | IDLE_STATUS_TXQ_BUSY); - - AT_READ_REG(hw, REG_MAC_CTRL, &data); - data &= ~(MAC_CTRL_TX_EN | MAC_CTRL_RX_EN); - AT_WRITE_REG(hw, REG_MAC_CTRL, data); - -- return (int)atl1c_wait_until_idle(hw); --} -- --static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw) --{ -- u32 data; -- -- AT_READ_REG(hw, REG_RXQ_CTRL, &data); -- switch (hw->adapter->num_rx_queues) { -- case 4: -- data |= (RXQ3_CTRL_EN | RXQ2_CTRL_EN | RXQ1_CTRL_EN); -- break; -- case 3: -- data |= (RXQ2_CTRL_EN | RXQ1_CTRL_EN); -- break; -- case 2: -- data |= RXQ1_CTRL_EN; -- break; -- default: -- break; -- } -- data |= RXQ_CTRL_EN; -- AT_WRITE_REG(hw, REG_RXQ_CTRL, data); -+ return (int)atl1c_wait_until_idle(hw, -+ IDLE_STATUS_TXMAC_BUSY | IDLE_STATUS_RXMAC_BUSY); - } - --static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw) -+static void atl1c_start_mac(struct atl1c_adapter *adapter) - { -- u32 data; -+ struct atl1c_hw *hw = &adapter->hw; -+ u32 mac, txq, rxq; -+ -+ hw->mac_duplex = adapter->link_duplex == FULL_DUPLEX ? true : false; -+ hw->mac_speed = adapter->link_speed == SPEED_1000 ? -+ atl1c_mac_speed_1000 : atl1c_mac_speed_10_100; -+ -+ AT_READ_REG(hw, REG_TXQ_CTRL, &txq); -+ AT_READ_REG(hw, REG_RXQ_CTRL, &rxq); -+ AT_READ_REG(hw, REG_MAC_CTRL, &mac); -+ -+ txq |= TXQ_CTRL_EN; -+ rxq |= RXQ_CTRL_EN; -+ mac |= MAC_CTRL_TX_EN | MAC_CTRL_TX_FLOW | -+ MAC_CTRL_RX_EN | MAC_CTRL_RX_FLOW | -+ MAC_CTRL_ADD_CRC | MAC_CTRL_PAD | -+ MAC_CTRL_BC_EN | MAC_CTRL_SINGLE_PAUSE_EN | -+ MAC_CTRL_HASH_ALG_CRC32; -+ if (hw->mac_duplex) -+ mac |= MAC_CTRL_DUPLX; -+ else -+ mac &= ~MAC_CTRL_DUPLX; -+ mac = FIELD_SETX(mac, MAC_CTRL_SPEED, hw->mac_speed); -+ mac = FIELD_SETX(mac, MAC_CTRL_PRMLEN, hw->preamble_len); - -- AT_READ_REG(hw, REG_TXQ_CTRL, &data); -- data |= TXQ_CTRL_EN; -- AT_WRITE_REG(hw, REG_TXQ_CTRL, data); -+ AT_WRITE_REG(hw, REG_TXQ_CTRL, txq); -+ AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq); -+ AT_WRITE_REG(hw, REG_MAC_CTRL, mac); - } - - /* -@@ -1287,10 +1229,7 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) - { - struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter; - struct pci_dev *pdev = adapter->pdev; -- u32 master_ctrl_data = 0; -- -- AT_WRITE_REG(hw, REG_IMR, 0); -- AT_WRITE_REG(hw, REG_ISR, ISR_DIS_INT); -+ u32 ctrl_data = 0; - - atl1c_stop_mac(hw); - /* -@@ -1299,194 +1238,148 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) - * the current PCI configuration. The global reset bit is self- - * clearing, and should clear within a microsecond. - */ -- AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); -- master_ctrl_data |= MASTER_CTRL_OOB_DIS_OFF; -- AT_WRITE_REGW(hw, REG_MASTER_CTRL, ((master_ctrl_data | MASTER_CTRL_SOFT_RST) -- & 0xFFFF)); -+ AT_READ_REG(hw, REG_MASTER_CTRL, &ctrl_data); -+ ctrl_data |= MASTER_CTRL_OOB_DIS; -+ AT_WRITE_REG(hw, REG_MASTER_CTRL, ctrl_data | MASTER_CTRL_SOFT_RST); - - AT_WRITE_FLUSH(hw); - msleep(10); - /* Wait at least 10ms for All module to be Idle */ - -- if (atl1c_wait_until_idle(hw)) { -+ if (atl1c_wait_until_idle(hw, IDLE_STATUS_MASK)) { - dev_err(&pdev->dev, - "MAC state machine can't be idle since" - " disabled for 10ms second\n"); - return -1; - } -+ AT_WRITE_REG(hw, REG_MASTER_CTRL, ctrl_data); -+ -+ /* driver control speed/duplex */ -+ AT_READ_REG(hw, REG_MAC_CTRL, &ctrl_data); -+ AT_WRITE_REG(hw, REG_MAC_CTRL, ctrl_data | MAC_CTRL_SPEED_MODE_SW); -+ -+ /* clk switch setting */ -+ AT_READ_REG(hw, REG_SERDES, &ctrl_data); -+ switch (hw->nic_type) { -+ case athr_l2c_b: -+ ctrl_data &= ~(SERDES_PHY_CLK_SLOWDOWN | -+ SERDES_MAC_CLK_SLOWDOWN); -+ AT_WRITE_REG(hw, REG_SERDES, ctrl_data); -+ break; -+ case athr_l2c_b2: -+ case athr_l1d_2: -+ ctrl_data |= SERDES_PHY_CLK_SLOWDOWN | SERDES_MAC_CLK_SLOWDOWN; -+ AT_WRITE_REG(hw, REG_SERDES, ctrl_data); -+ break; -+ default: -+ break; -+ } -+ - return 0; - } - - static void atl1c_disable_l0s_l1(struct atl1c_hw *hw) - { -- u32 pm_ctrl_data; -+ u16 ctrl_flags = hw->ctrl_flags; - -- AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data); -- pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << -- PM_CTRL_L1_ENTRY_TIMER_SHIFT); -- pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1; -- pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; -- pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; -- pm_ctrl_data &= ~PM_CTRL_MAC_ASPM_CHK; -- pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1; -- -- pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN; -- pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN; -- pm_ctrl_data |= PM_CTRL_SERDES_L1_EN; -- AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data); -+ hw->ctrl_flags &= ~(ATL1C_ASPM_L0S_SUPPORT | ATL1C_ASPM_L1_SUPPORT); -+ atl1c_set_aspm(hw, SPEED_0); -+ hw->ctrl_flags = ctrl_flags; - } - - /* - * Set ASPM state. - * Enable/disable L0s/L1 depend on link state. - */ --static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup) -+static void atl1c_set_aspm(struct atl1c_hw *hw, u16 link_speed) - { - u32 pm_ctrl_data; -- u32 link_ctrl_data; -- u32 link_l1_timer = 0xF; -+ u32 link_l1_timer; - - AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data); -- AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data); -+ pm_ctrl_data &= ~(PM_CTRL_ASPM_L1_EN | -+ PM_CTRL_ASPM_L0S_EN | -+ PM_CTRL_MAC_ASPM_CHK); -+ /* L1 timer */ -+ if (hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { -+ pm_ctrl_data &= ~PMCTRL_TXL1_AFTER_L0S; -+ link_l1_timer = -+ link_speed == SPEED_1000 || link_speed == SPEED_100 ? -+ L1D_PMCTRL_L1_ENTRY_TM_16US : 1; -+ pm_ctrl_data = FIELD_SETX(pm_ctrl_data, -+ L1D_PMCTRL_L1_ENTRY_TM, link_l1_timer); -+ } else { -+ link_l1_timer = hw->nic_type == athr_l2c_b ? -+ L2CB1_PM_CTRL_L1_ENTRY_TM : L1C_PM_CTRL_L1_ENTRY_TM; -+ if (link_speed != SPEED_1000 && link_speed != SPEED_100) -+ link_l1_timer = 1; -+ pm_ctrl_data = FIELD_SETX(pm_ctrl_data, -+ PM_CTRL_L1_ENTRY_TIMER, link_l1_timer); -+ } - -- pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1; -- pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << -- PM_CTRL_L1_ENTRY_TIMER_SHIFT); -- pm_ctrl_data &= ~(PM_CTRL_LCKDET_TIMER_MASK << -- PM_CTRL_LCKDET_TIMER_SHIFT); -- pm_ctrl_data |= AT_LCKDET_TIMER << PM_CTRL_LCKDET_TIMER_SHIFT; -+ /* L0S/L1 enable */ -+ if ((hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT) && link_speed != SPEED_0) -+ pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN | PM_CTRL_MAC_ASPM_CHK; -+ if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) -+ pm_ctrl_data |= PM_CTRL_ASPM_L1_EN | PM_CTRL_MAC_ASPM_CHK; - -+ /* l2cb & l1d & l2cb2 & l1d2 */ - if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d || -- hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { -- link_ctrl_data &= ~LINK_CTRL_EXT_SYNC; -- if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE)) { -- if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) -- link_ctrl_data |= LINK_CTRL_EXT_SYNC; -- } -- -- AT_WRITE_REG(hw, REG_LINK_CTRL, link_ctrl_data); -- -- pm_ctrl_data |= PM_CTRL_RCVR_WT_TIMER; -- pm_ctrl_data &= ~(PM_CTRL_PM_REQ_TIMER_MASK << -- PM_CTRL_PM_REQ_TIMER_SHIFT); -- pm_ctrl_data |= AT_ASPM_L1_TIMER << -- PM_CTRL_PM_REQ_TIMER_SHIFT; -- pm_ctrl_data &= ~PM_CTRL_SA_DLY_EN; -- pm_ctrl_data &= ~PM_CTRL_HOTRST; -- pm_ctrl_data |= 1 << PM_CTRL_L1_ENTRY_TIMER_SHIFT; -- pm_ctrl_data |= PM_CTRL_SERDES_PD_EX_L1; -- } -- pm_ctrl_data |= PM_CTRL_MAC_ASPM_CHK; -- if (linkup) { -- pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; -- pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; -- if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) -- pm_ctrl_data |= PM_CTRL_ASPM_L1_EN; -- if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT) -- pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN; -- -- if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d || -- hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { -- if (hw->nic_type == athr_l2c_b) -- if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE)) -- pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; -- pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN; -- pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN; -- pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN; -- pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; -- if (hw->adapter->link_speed == SPEED_100 || -- hw->adapter->link_speed == SPEED_1000) { -- pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << -- PM_CTRL_L1_ENTRY_TIMER_SHIFT); -- if (hw->nic_type == athr_l2c_b) -- link_l1_timer = 7; -- else if (hw->nic_type == athr_l2c_b2 || -- hw->nic_type == athr_l1d_2) -- link_l1_timer = 4; -- pm_ctrl_data |= link_l1_timer << -- PM_CTRL_L1_ENTRY_TIMER_SHIFT; -- } -- } else { -- pm_ctrl_data |= PM_CTRL_SERDES_L1_EN; -- pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN; -- pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN; -- pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1; -+ hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { -+ pm_ctrl_data = FIELD_SETX(pm_ctrl_data, -+ PM_CTRL_PM_REQ_TIMER, PM_CTRL_PM_REQ_TO_DEF); -+ pm_ctrl_data |= PM_CTRL_RCVR_WT_TIMER | -+ PM_CTRL_SERDES_PD_EX_L1 | -+ PM_CTRL_CLK_SWH_L1; -+ pm_ctrl_data &= ~(PM_CTRL_SERDES_L1_EN | -+ PM_CTRL_SERDES_PLL_L1_EN | -+ PM_CTRL_SERDES_BUFS_RX_L1_EN | -+ PM_CTRL_SA_DLY_EN | -+ PM_CTRL_HOTRST); -+ /* disable l0s if link down or l2cb */ -+ if (link_speed == SPEED_0 || hw->nic_type == athr_l2c_b) - pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; -- pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; -- -+ } else { /* l1c */ -+ pm_ctrl_data = -+ FIELD_SETX(pm_ctrl_data, PM_CTRL_L1_ENTRY_TIMER, 0); -+ if (link_speed != SPEED_0) { -+ pm_ctrl_data |= PM_CTRL_SERDES_L1_EN | -+ PM_CTRL_SERDES_PLL_L1_EN | -+ PM_CTRL_SERDES_BUFS_RX_L1_EN; -+ pm_ctrl_data &= ~(PM_CTRL_SERDES_PD_EX_L1 | -+ PM_CTRL_CLK_SWH_L1 | -+ PM_CTRL_ASPM_L0S_EN | -+ PM_CTRL_ASPM_L1_EN); -+ } else { /* link down */ -+ pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; -+ pm_ctrl_data &= ~(PM_CTRL_SERDES_L1_EN | -+ PM_CTRL_SERDES_PLL_L1_EN | -+ PM_CTRL_SERDES_BUFS_RX_L1_EN | -+ PM_CTRL_ASPM_L0S_EN); - } -- } else { -- pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN; -- pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; -- pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN; -- pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; -- -- if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) -- pm_ctrl_data |= PM_CTRL_ASPM_L1_EN; -- else -- pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; - } - AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data); - - return; - } - --static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter) --{ -- struct atl1c_hw *hw = &adapter->hw; -- struct net_device *netdev = adapter->netdev; -- u32 mac_ctrl_data; -- -- mac_ctrl_data = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN; -- mac_ctrl_data |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW); -- -- if (adapter->link_duplex == FULL_DUPLEX) { -- hw->mac_duplex = true; -- mac_ctrl_data |= MAC_CTRL_DUPLX; -- } -- -- if (adapter->link_speed == SPEED_1000) -- hw->mac_speed = atl1c_mac_speed_1000; -- else -- hw->mac_speed = atl1c_mac_speed_10_100; -- -- mac_ctrl_data |= (hw->mac_speed & MAC_CTRL_SPEED_MASK) << -- MAC_CTRL_SPEED_SHIFT; -- -- mac_ctrl_data |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD); -- mac_ctrl_data |= ((hw->preamble_len & MAC_CTRL_PRMLEN_MASK) << -- MAC_CTRL_PRMLEN_SHIFT); -- -- __atl1c_vlan_mode(netdev->features, &mac_ctrl_data); -- -- mac_ctrl_data |= MAC_CTRL_BC_EN; -- if (netdev->flags & IFF_PROMISC) -- mac_ctrl_data |= MAC_CTRL_PROMIS_EN; -- if (netdev->flags & IFF_ALLMULTI) -- mac_ctrl_data |= MAC_CTRL_MC_ALL_EN; -- -- mac_ctrl_data |= MAC_CTRL_SINGLE_PAUSE_EN; -- if (hw->nic_type == athr_l1d || hw->nic_type == athr_l2c_b2 || -- hw->nic_type == athr_l1d_2) { -- mac_ctrl_data |= MAC_CTRL_SPEED_MODE_SW; -- mac_ctrl_data |= MAC_CTRL_HASH_ALG_CRC32; -- } -- AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); --} -- - /* - * atl1c_configure - Configure Transmit&Receive Unit after Reset - * @adapter: board private structure - * - * Configure the Tx /Rx unit of the MAC after a reset. - */ --static int atl1c_configure(struct atl1c_adapter *adapter) -+static int atl1c_configure_mac(struct atl1c_adapter *adapter) - { - struct atl1c_hw *hw = &adapter->hw; - u32 master_ctrl_data = 0; - u32 intr_modrt_data; - u32 data; - -+ AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); -+ master_ctrl_data &= ~(MASTER_CTRL_TX_ITIMER_EN | -+ MASTER_CTRL_RX_ITIMER_EN | -+ MASTER_CTRL_INT_RDCLR); - /* clear interrupt status */ - AT_WRITE_REG(hw, REG_ISR, 0xFFFFFFFF); - /* Clear any WOL status */ -@@ -1525,30 +1418,39 @@ static int atl1c_configure(struct atl1c_adapter *adapter) - master_ctrl_data |= MASTER_CTRL_SA_TIMER_EN; - AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); - -- if (hw->ctrl_flags & ATL1C_CMB_ENABLE) { -- AT_WRITE_REG(hw, REG_CMB_TPD_THRESH, -- hw->cmb_tpd & CMB_TPD_THRESH_MASK); -- AT_WRITE_REG(hw, REG_CMB_TX_TIMER, -- hw->cmb_tx_timer & CMB_TX_TIMER_MASK); -- } -+ AT_WRITE_REG(hw, REG_SMB_STAT_TIMER, -+ hw->smb_timer & SMB_STAT_TIMER_MASK); - -- if (hw->ctrl_flags & ATL1C_SMB_ENABLE) -- AT_WRITE_REG(hw, REG_SMB_STAT_TIMER, -- hw->smb_timer & SMB_STAT_TIMER_MASK); - /* set MTU */ - AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN + - VLAN_HLEN + ETH_FCS_LEN); -- /* HDS, disable */ -- AT_WRITE_REG(hw, REG_HDS_CTRL, 0); - - atl1c_configure_tx(adapter); - atl1c_configure_rx(adapter); -- atl1c_configure_rss(adapter); - atl1c_configure_dma(adapter); - - return 0; - } - -+static int atl1c_configure(struct atl1c_adapter *adapter) -+{ -+ struct net_device *netdev = adapter->netdev; -+ int num; -+ -+ atl1c_init_ring_ptrs(adapter); -+ atl1c_set_multi(netdev); -+ atl1c_restore_vlan(adapter); -+ -+ num = atl1c_alloc_rx_buffer(adapter); -+ if (unlikely(num == 0)) -+ return -ENOMEM; -+ -+ if (atl1c_configure_mac(adapter)) -+ return -EIO; -+ -+ return 0; -+} -+ - static void atl1c_update_hw_stats(struct atl1c_adapter *adapter) - { - u16 hw_reg_addr = 0; -@@ -1635,16 +1537,11 @@ static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter, - struct pci_dev *pdev = adapter->pdev; - u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean); - u16 hw_next_to_clean; -- u16 shift; -- u32 data; -+ u16 reg; - -- if (type == atl1c_trans_high) -- shift = MB_HTPD_CONS_IDX_SHIFT; -- else -- shift = MB_NTPD_CONS_IDX_SHIFT; -+ reg = type == atl1c_trans_high ? REG_TPD_PRI1_CIDX : REG_TPD_PRI0_CIDX; - -- AT_READ_REG(&adapter->hw, REG_MB_PRIO_CONS_IDX, &data); -- hw_next_to_clean = (data >> shift) & MB_PRIO_PROD_IDX_MASK; -+ AT_READ_REGW(&adapter->hw, reg, &hw_next_to_clean); - - while (next_to_clean != hw_next_to_clean) { - buffer_info = &tpd_ring->buffer_info[next_to_clean]; -@@ -1746,9 +1643,9 @@ static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter, - skb_checksum_none_assert(skb); - } - --static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid) -+static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter) - { -- struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[ringid]; -+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct pci_dev *pdev = adapter->pdev; - struct atl1c_buffer *buffer_info, *next_info; - struct sk_buff *skb; -@@ -1800,7 +1697,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid - /* TODO: update mailbox here */ - wmb(); - rfd_ring->next_to_use = rfd_next_to_use; -- AT_WRITE_REG(&adapter->hw, atl1c_rfd_prod_idx_regs[ringid], -+ AT_WRITE_REG(&adapter->hw, REG_MB_RFD0_PROD_IDX, - rfd_ring->next_to_use & MB_RFDX_PROD_IDX_MASK); - } - -@@ -1839,7 +1736,7 @@ static void atl1c_clean_rfd(struct atl1c_rfd_ring *rfd_ring, - rfd_ring->next_to_clean = rfd_index; - } - --static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que, -+static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, - int *work_done, int work_to_do) - { - u16 rfd_num, rfd_index; -@@ -1847,8 +1744,8 @@ static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que, - u16 length; - struct pci_dev *pdev = adapter->pdev; - struct net_device *netdev = adapter->netdev; -- struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[que]; -- struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring[que]; -+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; -+ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct sk_buff *skb; - struct atl1c_recv_ret_status *rrs; - struct atl1c_buffer *buffer_info; -@@ -1914,7 +1811,7 @@ rrs_checked: - count++; - } - if (count) -- atl1c_alloc_rx_buffer(adapter, que); -+ atl1c_alloc_rx_buffer(adapter); - } - - /* -@@ -1931,7 +1828,7 @@ static int atl1c_clean(struct napi_struct *napi, int budget) - if (!netif_carrier_ok(adapter->netdev)) - goto quit_polling; - /* just enable one RXQ */ -- atl1c_clean_rx_irq(adapter, 0, &work_done, budget); -+ atl1c_clean_rx_irq(adapter, &work_done, budget); - - if (work_done < budget) { - quit_polling: -@@ -2206,23 +2103,10 @@ static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb, - struct atl1c_tpd_desc *tpd, enum atl1c_trans_queue type) - { - struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; -- u32 prod_data; -+ u16 reg; - -- AT_READ_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, &prod_data); -- switch (type) { -- case atl1c_trans_high: -- prod_data &= 0xFFFF0000; -- prod_data |= tpd_ring->next_to_use & 0xFFFF; -- break; -- case atl1c_trans_normal: -- prod_data &= 0x0000FFFF; -- prod_data |= (tpd_ring->next_to_use & 0xFFFF) << 16; -- break; -- default: -- break; -- } -- wmb(); -- AT_WRITE_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, prod_data); -+ reg = type == atl1c_trans_high ? REG_TPD_PRI1_PIDX : REG_TPD_PRI0_PIDX; -+ AT_WRITE_REGW(&adapter->hw, reg, tpd_ring->next_to_use); - } - - static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb, -@@ -2307,8 +2191,7 @@ static int atl1c_request_irq(struct atl1c_adapter *adapter) - "Unable to allocate MSI interrupt Error: %d\n", - err); - adapter->have_msi = false; -- } else -- netdev->irq = pdev->irq; -+ } - - if (!adapter->have_msi) - flags |= IRQF_SHARED; -@@ -2328,44 +2211,38 @@ static int atl1c_request_irq(struct atl1c_adapter *adapter) - return err; - } - -+ -+static void atl1c_reset_dma_ring(struct atl1c_adapter *adapter) -+{ -+ /* release tx-pending skbs and reset tx/rx ring index */ -+ atl1c_clean_tx_ring(adapter, atl1c_trans_normal); -+ atl1c_clean_tx_ring(adapter, atl1c_trans_high); -+ atl1c_clean_rx_ring(adapter); -+} -+ - static int atl1c_up(struct atl1c_adapter *adapter) - { - struct net_device *netdev = adapter->netdev; -- int num; - int err; -- int i; - - netif_carrier_off(netdev); -- atl1c_init_ring_ptrs(adapter); -- atl1c_set_multi(netdev); -- atl1c_restore_vlan(adapter); - -- for (i = 0; i < adapter->num_rx_queues; i++) { -- num = atl1c_alloc_rx_buffer(adapter, i); -- if (unlikely(num == 0)) { -- err = -ENOMEM; -- goto err_alloc_rx; -- } -- } -- -- if (atl1c_configure(adapter)) { -- err = -EIO; -+ err = atl1c_configure(adapter); -+ if (unlikely(err)) - goto err_up; -- } - - err = atl1c_request_irq(adapter); - if (unlikely(err)) - goto err_up; - -+ atl1c_check_link_status(adapter); - clear_bit(__AT_DOWN, &adapter->flags); - napi_enable(&adapter->napi); - atl1c_irq_enable(adapter); -- atl1c_check_link_status(adapter); - netif_start_queue(netdev); - return err; - - err_up: --err_alloc_rx: - atl1c_clean_rx_ring(adapter); - return err; - } -@@ -2383,15 +2260,15 @@ static void atl1c_down(struct atl1c_adapter *adapter) - napi_disable(&adapter->napi); - atl1c_irq_disable(adapter); - atl1c_free_irq(adapter); -+ /* disable ASPM if device inactive */ -+ atl1c_disable_l0s_l1(&adapter->hw); - /* reset MAC to disable all RX/TX */ - atl1c_reset_mac(&adapter->hw); - msleep(1); - - adapter->link_speed = SPEED_0; - adapter->link_duplex = -1; -- atl1c_clean_tx_ring(adapter, atl1c_trans_normal); -- atl1c_clean_tx_ring(adapter, atl1c_trans_high); -- atl1c_clean_rx_ring(adapter); -+ atl1c_reset_dma_ring(adapter); - } - - /* -@@ -2424,13 +2301,6 @@ static int atl1c_open(struct net_device *netdev) - if (unlikely(err)) - goto err_up; - -- if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) { -- u32 phy_data; -- -- AT_READ_REG(&adapter->hw, REG_MDIO_CTRL, &phy_data); -- phy_data |= MDIO_AP_EN; -- AT_WRITE_REG(&adapter->hw, REG_MDIO_CTRL, phy_data); -- } - return 0; - - err_up: -@@ -2456,6 +2326,8 @@ static int atl1c_close(struct net_device *netdev) - struct atl1c_adapter *adapter = netdev_priv(netdev); - - WARN_ON(test_bit(__AT_RESETTING, &adapter->flags)); -+ set_bit(__AT_DOWN, &adapter->flags); -+ cancel_work_sync(&adapter->common_task); - atl1c_down(adapter); - atl1c_free_ring_resources(adapter); - return 0; -@@ -2467,10 +2339,6 @@ static int atl1c_suspend(struct device *dev) - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw *hw = &adapter->hw; -- u32 mac_ctrl_data = 0; -- u32 master_ctrl_data = 0; -- u32 wol_ctrl_data = 0; -- u16 mii_intr_status_data = 0; - u32 wufc = adapter->wol; - - atl1c_disable_l0s_l1(hw); -@@ -2481,75 +2349,10 @@ static int atl1c_suspend(struct device *dev) - netif_device_detach(netdev); - - if (wufc) -- if (atl1c_phy_power_saving(hw) != 0) -+ if (atl1c_phy_to_ps_link(hw) != 0) - dev_dbg(&pdev->dev, "phy power saving failed"); - -- AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); -- AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data); -- -- master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS; -- mac_ctrl_data &= ~(MAC_CTRL_PRMLEN_MASK << MAC_CTRL_PRMLEN_SHIFT); -- mac_ctrl_data |= (((u32)adapter->hw.preamble_len & -- MAC_CTRL_PRMLEN_MASK) << -- MAC_CTRL_PRMLEN_SHIFT); -- mac_ctrl_data &= ~(MAC_CTRL_SPEED_MASK << MAC_CTRL_SPEED_SHIFT); -- mac_ctrl_data &= ~MAC_CTRL_DUPLX; -- -- if (wufc) { -- mac_ctrl_data |= MAC_CTRL_RX_EN; -- if (adapter->link_speed == SPEED_1000 || -- adapter->link_speed == SPEED_0) { -- mac_ctrl_data |= atl1c_mac_speed_1000 << -- MAC_CTRL_SPEED_SHIFT; -- mac_ctrl_data |= MAC_CTRL_DUPLX; -- } else -- mac_ctrl_data |= atl1c_mac_speed_10_100 << -- MAC_CTRL_SPEED_SHIFT; -- -- if (adapter->link_duplex == DUPLEX_FULL) -- mac_ctrl_data |= MAC_CTRL_DUPLX; -- -- /* turn on magic packet wol */ -- if (wufc & AT_WUFC_MAG) -- wol_ctrl_data |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN; -- -- if (wufc & AT_WUFC_LNKC) { -- wol_ctrl_data |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN; -- /* only link up can wake up */ -- if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) { -- dev_dbg(&pdev->dev, "%s: read write phy " -- "register failed.\n", -- atl1c_driver_name); -- } -- } -- /* clear phy interrupt */ -- atl1c_read_phy_reg(hw, MII_ISR, &mii_intr_status_data); -- /* Config MAC Ctrl register */ -- __atl1c_vlan_mode(netdev->features, &mac_ctrl_data); -- -- /* magic packet maybe Broadcast&multicast&Unicast frame */ -- if (wufc & AT_WUFC_MAG) -- mac_ctrl_data |= MAC_CTRL_BC_EN; -- -- dev_dbg(&pdev->dev, -- "%s: suspend MAC=0x%x\n", -- atl1c_driver_name, mac_ctrl_data); -- AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); -- AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data); -- AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); -- -- AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT | -- GPHY_CTRL_EXT_RESET); -- } else { -- AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_POWER_SAVING); -- master_ctrl_data |= MASTER_CTRL_CLK_SEL_DIS; -- mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT; -- mac_ctrl_data |= MAC_CTRL_DUPLX; -- AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); -- AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); -- AT_WRITE_REG(hw, REG_WOL_CTRL, 0); -- hw->phy_configured = false; /* re-init PHY when resume */ -- } -+ atl1c_power_saving(hw, wufc); - - return 0; - } -@@ -2562,8 +2365,7 @@ static int atl1c_resume(struct device *dev) - struct atl1c_adapter *adapter = netdev_priv(netdev); - - AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0); -- atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE | -- ATL1C_PCIE_PHY_RESET); -+ atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE); - - atl1c_phy_reset(&adapter->hw); - atl1c_reset_mac(&adapter->hw); -@@ -2616,7 +2418,6 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev) - SET_NETDEV_DEV(netdev, &pdev->dev); - pci_set_drvdata(pdev, netdev); - -- netdev->irq = pdev->irq; - netdev->netdev_ops = &atl1c_netdev_ops; - netdev->watchdog_timeo = AT_TX_WATCHDOG; - atl1c_set_ethtool_ops(netdev); -@@ -2706,14 +2507,13 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, - dev_err(&pdev->dev, "cannot map device registers\n"); - goto err_ioremap; - } -- netdev->base_addr = (unsigned long)adapter->hw.hw_addr; - - /* init mii data */ - adapter->mii.dev = netdev; - adapter->mii.mdio_read = atl1c_mdio_read; - adapter->mii.mdio_write = atl1c_mdio_write; - adapter->mii.phy_id_mask = 0x1f; -- adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK; -+ adapter->mii.reg_num_mask = MDIO_CTRL_REG_MASK; - netif_napi_add(netdev, &adapter->napi, atl1c_clean, 64); - setup_timer(&adapter->phy_config_timer, atl1c_phy_config, - (unsigned long)adapter); -@@ -2723,8 +2523,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, - dev_err(&pdev->dev, "net device private data init failed\n"); - goto err_sw_init; - } -- atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE | -- ATL1C_PCIE_PHY_RESET); -+ atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE); - - /* Init GPHY as early as possible due to power saving issue */ - atl1c_phy_reset(&adapter->hw); -@@ -2752,7 +2551,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, - dev_dbg(&pdev->dev, "mac address : %pM\n", - adapter->hw.mac_addr); - -- atl1c_hw_set_mac_addr(&adapter->hw); -+ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr); - INIT_WORK(&adapter->common_task, atl1c_common_task); - adapter->work_event = 0; - err = register_netdev(netdev); -@@ -2796,6 +2595,8 @@ static void __devexit atl1c_remove(struct pci_dev *pdev) - struct atl1c_adapter *adapter = netdev_priv(netdev); - - unregister_netdev(netdev); -+ /* restore permanent address */ -+ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.perm_mac_addr); - atl1c_phy_disable(&adapter->hw); - - iounmap(adapter->hw.hw_addr); diff --git a/config-generic b/config-generic index 7427c2d8d..dc9441e34 100644 --- a/config-generic +++ b/config-generic @@ -169,6 +169,7 @@ CONFIG_MLX4_INFINIBAND=m CONFIG_INFINIBAND_NES=m # CONFIG_INFINIBAND_NES_DEBUG is not set CONFIG_INFINIBAND_QIB=m +# CONFIG_INFINIBAND_OCRDMA is not set # # Executable file formats @@ -189,6 +190,8 @@ CONFIG_FW_LOADER=y # CONFIG_FIRMWARE_IN_KERNEL is not set CONFIG_EXTRA_FIRMWARE="" +# CONFIG_CMA is not set + # CONFIG_SPI is not set # @@ -446,6 +449,7 @@ CONFIG_VIRTIO_BLK=m CONFIG_VIRTIO_PCI=y CONFIG_VIRTIO_BALLOON=m CONFIG_VIRTIO_MMIO=m +# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set CONFIG_VIRTIO_NET=m CONFIG_VMXNET3=m CONFIG_HW_RANDOM_VIRTIO=m @@ -589,6 +593,7 @@ CONFIG_SCSI_DC395x=m CONFIG_SCSI_DEBUG=m CONFIG_SCSI_DC390T=m CONFIG_SCSI_QLA_FC=m +CONFIG_TCM_QLA2XXX=m CONFIG_SCSI_QLA_ISCSI=m # CONFIG_SCSI_IPR is not set # CONFIG_SCSI_DPT_I2O is not set @@ -914,6 +919,7 @@ CONFIG_NETFILTER_XT_TARGET_CONNMARK=m CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m CONFIG_NETFILTER_XT_TARGET_CT=m CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m CONFIG_NETFILTER_XT_TARGET_LED=m CONFIG_NETFILTER_XT_TARGET_LOG=m @@ -1168,6 +1174,8 @@ CONFIG_NET_SCH_MQPRIO=m CONFIG_NET_SCH_MULTIQ=m CONFIG_NET_SCH_CHOKE=m CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_CODEL=m +CONFIG_NET_SCH_FQ_CODEL=m CONFIG_NET_SCH_PLUG=m CONFIG_NET_CLS=y CONFIG_NET_CLS_ACT=y @@ -1225,6 +1233,7 @@ CONFIG_IFB=m CONFIG_NET_TEAM=m CONFIG_NET_TEAM_MODE_ROUNDROBIN=m CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m +CONFIG_NET_TEAM_MODE_LOADBALANCE=m CONFIG_DUMMY=m CONFIG_BONDING=m CONFIG_MACVLAN=m @@ -1371,12 +1380,15 @@ CONFIG_E1000=m CONFIG_E1000E=m CONFIG_IGB=m CONFIG_IGB_DCA=y +CONFIG_IGB_PTP=y CONFIG_IGBVF=m CONFIG_IXGB=m CONFIG_IXGBEVF=m CONFIG_IXGBE=m CONFIG_IXGBE_DCA=y CONFIG_IXGBE_DCB=y +CONFIG_IXGBE_HWMON=y +CONFIG_IXGBE_PTP=y # CONFIG_NET_VENDOR_I825XX is not set CONFIG_NET_VENDOR_MARVELL=y @@ -1477,6 +1489,10 @@ CONFIG_VIA_RHINE=m CONFIG_VIA_RHINE_MMIO=y CONFIG_VIA_VELOCITY=m +CONFIG_NET_VENDOR_WIZNET=y +CONFIG_WIZNET_W5100=m +CONFIG_WIZNET_W5300=m + CONFIG_NET_VENDOR_XIRCOM=y CONFIG_PCMCIA_XIRC2PS=m @@ -1529,6 +1545,7 @@ CONFIG_JME=m # CONFIG_IP1000=m CONFIG_MLX4_EN=m +CONFIG_MLX4_EN_DCB=y # CONFIG_MLX4_DEBUG is not set CONFIG_SFC=m CONFIG_SFC_MCDI_MON=y @@ -1645,6 +1662,7 @@ CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y CONFIG_BRCMSMAC=m CONFIG_BRCMFMAC=m CONFIG_BRCMFMAC_SDIO=y +CONFIG_BRCMFMAC_SDIO_OOB=y CONFIG_BRCMFMAC_USB=y # CONFIG_BRCMDBG is not set CONFIG_HERMES=m @@ -1727,6 +1745,7 @@ CONFIG_USB_NET_RNDIS_WLAN=m CONFIG_USB_NET_KALMIA=m CONFIG_USB_NET_QMI_WWAN=m CONFIG_USB_NET_SMSC75XX=m +# CONFIG_WL_TI is not set CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set @@ -1749,6 +1768,7 @@ CONFIG_RTL8192DE=m CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m CONFIG_MWIFIEX_PCIE=m +CONFIG_MWIFIEX_USB=m # # Token Ring devices @@ -2012,6 +2032,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 CONFIG_INPUT_JOYDEV=m CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT_MATRIXKMAP is not set CONFIG_INPUT_TABLET=y CONFIG_TABLET_USB_ACECAD=m @@ -2062,6 +2083,7 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_STOWAWAY is not set # CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set # CONFIG_KEYBOARD_ADP5588 is not set # CONFIG_KEYBOARD_MAX7359 is not set # CONFIG_KEYBOARD_ADP5589 is not set @@ -2145,6 +2167,7 @@ CONFIG_TOUCHSCREEN_TOUCHWIN=m CONFIG_TOUCHSCREEN_PIXCIR=m CONFIG_TOUCHSCREEN_UCB1400=m CONFIG_TOUCHSCREEN_WACOM_W8001=m +CONFIG_TOUCHSCREEN_WACOM_I2C=m CONFIG_TOUCHSCREEN_USB_E2I=y CONFIG_TOUCHSCREEN_USB_COMPOSITE=m # CONFIG_TOUCHSCREEN_WM97XX is not set @@ -2401,6 +2424,7 @@ CONFIG_SENSORS_WM8350=m CONFIG_SENSORS_WM831X=m CONFIG_SENSORS_LM73=m CONFIG_SENSORS_AMC6821=m +CONFIG_SENSORS_INA2XX=m CONFIG_SENSORS_ADT7411=m CONFIG_SENSORS_ASC7621=m CONFIG_SENSORS_EMC1403=m @@ -2440,6 +2464,7 @@ CONFIG_SENSORS_MAX1668=m # CONFIG_HMC6352 is not set # CONFIG_BMP085 is not set +# CONFIG_BMP085_I2C is not set # CONFIG_PCH_PHUB is not set # CONFIG_SERIAL_PCH_UART is not set # CONFIG_USB_SWITCH_FSA9480 is not set @@ -2583,10 +2608,13 @@ CONFIG_DRM=m # CONFIG_DRM_LOAD_EDID_FIRMWARE is not set CONFIG_DRM_TDFX=m CONFIG_DRM_R128=m +# CONFIG_DRM_AST is not set +# CONFIG_DRM_CIRRUS_QEMU is not set CONFIG_DRM_RADEON=m CONFIG_DRM_RADEON_KMS=y CONFIG_DRM_I810=m CONFIG_DRM_MGA=m +# CONFIG_DRM_MGAG200 is not set CONFIG_DRM_SIS=m CONFIG_DRM_SAVAGE=m CONFIG_DRM_I915=m @@ -2866,6 +2894,7 @@ CONFIG_FB=y # CONFIG_FB_ATY_CT is not set # CONFIG_FB_ATY_GX is not set # CONFIG_FB_ASILIANT is not set +# CONFIG_FB_AUO_K190X is not set # CONFIG_FB_CARMINE is not set # CONFIG_FB_CIRRUS is not set # CONFIG_FB_CYBER2000 is not set @@ -3192,7 +3221,8 @@ CONFIG_USB_HID=y CONFIG_HID_SUPPORT=y -CONFIG_HID=m +CONFIG_HID=ym +CONFIG_HID_BATTERY_STRENGTH=y # debugging default is y upstream now CONFIG_HIDRAW=y CONFIG_HID_PID=y @@ -3257,6 +3287,9 @@ CONFIG_HID_WIIMOTE_EXT=y CONFIG_HID_KYE=m CONFIG_HID_SAITEK=m CONFIG_HID_TIVO=m +CONFIG_HID_GENERIC=y +CONFIG_HID_AUREAL=m + # # USB Imaging devices @@ -3368,6 +3401,7 @@ CONFIG_USB_EPSON2888=y CONFIG_USB_KC2190=y # CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_CHIPIDEA is not set # # USB port drivers @@ -3444,6 +3478,7 @@ CONFIG_USB_SERIAL_QCAUX=m CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m CONFIG_USB_SERIAL_DEBUG=m CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_QT2=m CONFIG_USB_SERIAL_CONSOLE=y @@ -3505,6 +3540,8 @@ CONFIG_USB_ZERO=m CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +# CONFIG_USB_ISP1301 is not set + # CONFIG_USB_OTG is not set # @@ -3543,6 +3580,7 @@ CONFIG_MFD_WM8400=m # CONFIG_MFD_WM8994 is not set # CONFIG_MFD_88PM860X is not set # CONFIG_LPC_SCH is not set +# CONFIG_LPC_ICH is not set # CONFIG_HTC_I2CPLD is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_ASIC3 is not set @@ -3559,6 +3597,8 @@ CONFIG_MFD_WM8400=m # CONFIG_MFD_TC3589X is not set # CONFIG_MFD_WL1273_CORE is not set # CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_MC13XXX_I2C is not set # # File systems @@ -3695,6 +3735,7 @@ CONFIG_CUSE=m # CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=m +CONFIG_NFS_V2=y CONFIG_NFS_V3=y CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y @@ -3827,6 +3868,17 @@ CONFIG_NLS_ISO8859_14=m CONFIG_NLS_ISO8859_15=m CONFIG_NLS_KOI8_R=m CONFIG_NLS_KOI8_U=m +CONFIG_NLS_MAC_ROMAN=m +CONFIG_NLS_MAC_CELTIC=m +CONFIG_NLS_MAC_CENTEURO=m +CONFIG_NLS_MAC_CROATIAN=m +CONFIG_NLS_MAC_CYRILLIC=m +CONFIG_NLS_MAC_GAELIC=m +CONFIG_NLS_MAC_GREEK=m +CONFIG_NLS_MAC_ICELAND=m +CONFIG_NLS_MAC_INUIT=m +CONFIG_NLS_MAC_ROMANIAN=m +CONFIG_NLS_MAC_TURKISH=m CONFIG_NLS_UTF8=m CONFIG_NLS_ASCII=y @@ -3849,6 +3901,7 @@ CONFIG_FRAME_POINTER=y # CONFIG_DEBUG_DRIVER is not set CONFIG_HEADERS_CHECK=y # CONFIG_LKDTM is not set +# CONFIG_READABLE_ASM is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_LOCKDEP is not set @@ -3884,6 +3937,7 @@ CONFIG_LOCKUP_DETECTOR=y CONFIG_ATOMIC64_SELFTEST=y CONFIG_MEMORY_FAILURE=y CONFIG_HWPOISON_INJECT=m +CONFIG_CROSS_MEMORY_ATTACH=y # CONFIG_DEBUG_SECTION_MISMATCH is not set # CONFIG_BACKTRACE_SELF_TEST is not set CONFIG_LATENCYTOP=y @@ -4016,6 +4070,7 @@ CONFIG_CRC_T10DIF=m CONFIG_CRC8=m # CONFIG_CRC7 is not set CONFIG_CORDIC=m +# CONFIG_DDR is not set CONFIG_CRYPTO_ZLIB=m CONFIG_ZLIB_INFLATE=y @@ -4102,6 +4157,8 @@ CONFIG_PM_TRACE_RTC=y # CONFIG_PM_TEST_SUSPEND is not set CONFIG_PM_RUNTIME=y # CONFIG_PM_OPP is not set +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_GOV_PERFORMANCE=y @@ -4250,6 +4307,7 @@ CONFIG_LEDS_TRIGGER_IDE_DISK=y CONFIG_LEDS_TRIGGER_HEARTBEAT=m CONFIG_LEDS_TRIGGER_BACKLIGHT=m CONFIG_LEDS_TRIGGER_DEFAULT_ON=m +CONFIG_LEDS_TRIGGER_TRANSIENT=m CONFIG_LEDS_ALIX2=m CONFIG_LEDS_CLEVO_MAIL=m CONFIG_LEDS_INTEL_SS4200=m @@ -4310,7 +4368,7 @@ CONFIG_CFAG12864B_RATE=20 # CONFIG_PHANTOM is not set # CONFIG_INTEL_MID_PTI is not set -CONFIG_POWER_SUPPLY=m +CONFIG_POWER_SUPPLY=y # CONFIG_POWER_SUPPLY_DEBUG is not set # CONFIG_TEST_POWER is not set @@ -4401,10 +4459,10 @@ CONFIG_OPTIMIZE_INLINING=y # CONFIG_GPIOLIB is not set # CONFIG_PINCTRL is not set -CONFIG_NET_DSA=y -CONFIG_NET_DSA_MV88E6060=y -CONFIG_NET_DSA_MV88E6131=y -CONFIG_NET_DSA_MV88E6123_61_65=y +CONFIG_NET_DSA=m +CONFIG_NET_DSA_MV88E6060=m +CONFIG_NET_DSA_MV88E6131=m +CONFIG_NET_DSA_MV88E6123_61_65=m # Used by Maemo, we don't care. # CONFIG_PHONET is not set @@ -4425,6 +4483,8 @@ CONFIG_USB_WUSB_CBAF=m # CONFIG_USB_WUSB_CBAF_DEBUG is not set CONFIG_USB_WHCI_HCD=m CONFIG_USB_HWA_HCD=m +# CONFIG_USB_HCD_BCMA is not set +# CONFIG_USB_HCD_SSB is not set CONFIG_UWB=m CONFIG_UWB_HWA=m @@ -4473,7 +4533,8 @@ CONFIG_USB_ATMEL=m # CONFIG_EASYCAP is not set # CONFIG_SOLO6X10 is not set # CONFIG_ACPI_QUICKSTART is not set -# CONFIG_R8712U is not set +CONFIG_R8712U=m # Larry Finger maintains this (rhbz 699618) +# CONFIG_R8712_AP is not set # CONFIG_ATH6K_LEGACY is not set # CONFIG_USB_ENESTORAGE is not set # CONFIG_BCM_WIMAX is not set @@ -4494,6 +4555,8 @@ CONFIG_ALTERA_STAPL=m # CONFIG_ZSMALLOC is not set # CONFIG_RAMSTER is not set # CONFIG_USB_WPAN_HCD is not set +# CONFIG_WIMAX_GDM72XX is not set +# CONFIG_IPACK_BUS is not set # # END OF STAGING @@ -4534,6 +4597,12 @@ CONFIG_IEEE802154=m CONFIG_IEEE802154_6LOWPAN=m CONFIG_IEEE802154_DRIVERS=m CONFIG_IEEE802154_FAKEHARD=m +CONFIG_IEEE802154_FAKELB=m + +CONFIG_MAC802154=m + +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set CONFIG_PPS=m # CONFIG_PPS_CLIENT_KTIMER is not set @@ -4548,6 +4617,7 @@ CONFIG_PTP_1588_CLOCK=m CONFIG_PTP_1588_CLOCK_PCH=m CONFIG_CLEANCACHE=y +CONFIG_FRONTSWAP=y # CONFIG_MDIO_GPIO is not set # CONFIG_KEYBOARD_GPIO is not set @@ -4589,6 +4659,7 @@ CONFIG_TEST_KSTRTOX=y CONFIG_TARGET_CORE=m CONFIG_ISCSI_TARGET=m CONFIG_LOOPBACK_TARGET=m +CONFIG_SBP_TARGET=m CONFIG_TCM_IBLOCK=m CONFIG_TCM_FILEIO=m CONFIG_TCM_PSCSI=m @@ -4597,6 +4668,7 @@ CONFIG_TCM_FC=m CONFIG_HWSPINLOCK=m CONFIG_PSTORE=y +CONFIG_PSTORE_RAM=m # CONFIG_AVERAGE is not set @@ -4616,3 +4688,4 @@ CONFIG_IOMMU_SUPPORT=y # CONFIG_HSI is not set # CONFIG_PM_DEVFREQ is not set + diff --git a/config-powerpc-generic b/config-powerpc-generic index 59e7d5c9e..1b82cf499 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -359,7 +359,11 @@ CONFIG_RFKILL_GPIO=m # CONFIG_INPUT_GPIO_TILT_POLLED is not set # CONFIG_CPU_IDLE is not set CONFIG_STRICT_DEVMEM=y + +CONFIG_RCU_FANOUT_LEAF=16 + # CONFIG_V4L_RADIO_ISA_DRIVERS is not set # CONFIG_IRQ_DOMAIN_DEBUG is not set # CONFIG_MPIC_MSGR is not set # CONFIG_FA_DUMP is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set diff --git a/config-powerpc64 b/config-powerpc64 index 30571917d..708e3115b 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -1,6 +1,8 @@ +CONFIG_WINDFARM_PM72=y CONFIG_WINDFARM_PM81=y CONFIG_WINDFARM_PM91=y CONFIG_WINDFARM_PM121=y +CONFIG_WINDFARM_RM31=y CONFIG_PPC_PMAC64=y CONFIG_PPC_MAPLE=y # CONFIG_PPC_CELL is not set @@ -158,6 +160,9 @@ CONFIG_PPC_ICSWX=y CONFIG_IO_EVENT_IRQ=y CONFIG_HW_RANDOM_AMD=m +CONFIG_HW_RANDOM_PSERIES=m +CONFIG_CRYPTO_DEV_NX=m + CONFIG_BPF_JIT=y # CONFIG_PPC_ICSWX_PID is not set diff --git a/config-s390x b/config-s390x index 848709dfb..e68ad4750 100644 --- a/config-s390x +++ b/config-s390x @@ -211,6 +211,7 @@ CONFIG_CHSC_SCH=m CONFIG_HVC_IUCV=y CONFIG_RCU_FANOUT=64 +CONFIG_RCU_FANOUT_LEAF=8 CONFIG_SECCOMP=y diff --git a/config-sparc64-generic b/config-sparc64-generic index 2b29f9b7e..a2b72dfe6 100644 --- a/config-sparc64-generic +++ b/config-sparc64-generic @@ -173,6 +173,7 @@ CONFIG_LEDS_SUNFIRE=m CONFIG_TADPOLE_TS102_UCTRL=m CONFIG_RCU_FANOUT=64 +CONFIG_RCU_FANOUT_LEAF=16 CONFIG_LIRC_ENE0100=m # CONFIG_BATTERY_DS2782 is not set @@ -196,3 +197,5 @@ CONFIG_CRYPTO_DEV_NIAGARA2=y # CONFIG_MTD_PHYSMAP_OF is not set # CONFIG_MMC_SDHCI_OF is not set # CONFIG_OF_SELFTEST is not set + +CONFIG_BPF_JIT=y diff --git a/config-x86-32-generic b/config-x86-32-generic index b00834482..5b9805a97 100644 --- a/config-x86-32-generic +++ b/config-x86-32-generic @@ -211,5 +211,9 @@ CONFIG_I2O_BUS=m # CONFIG_INPUT_GPIO_TILT_POLLED is not set # CONFIG_GEOS is not set # CONFIG_NET5501 is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set # CONFIG_GPIO_SODAVILLE is not set # CONFIG_BACKLIGHT_OT200 is not set + +# CONFIG_STA2X11 is not set + diff --git a/config-x86-generic b/config-x86-generic index 181e3e92f..c5fb4d815 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -218,6 +218,7 @@ CONFIG_XO15_EBOOK=m # CONFIG_SMSC37B787_WDT is not set CONFIG_W83697HF_WDT=m CONFIG_VIA_WDT=m +CONFIG_IE6XX_WDT=m CONFIG_CRASH_DUMP=y CONFIG_PROC_VMCORE=y @@ -351,6 +352,8 @@ CONFIG_TOSHIBA_BT_RFKILL=m CONFIG_VGA_SWITCHEROO=y CONFIG_LPC_SCH=m +CONFIG_GPIO_ICH=m + CONFIG_PCI_CNB20LE_QUIRK=y CONFIG_ACPI_EC_DEBUGFS=m @@ -405,6 +408,8 @@ CONFIG_DRM_GMA500=m # CONFIG_DRM_GMA600 is not set # CONFIG_DRM_GMA3600 is not set +CONFIG_RCU_FANOUT_LEAF=16 + # Maybe enable in debug kernels? # CONFIG_DEBUG_NMI_SELFTEST is not set diff --git a/drm-i915-fbc-stfu.patch b/drm-i915-fbc-stfu.patch deleted file mode 100644 index 9240387ee..000000000 --- a/drm-i915-fbc-stfu.patch +++ /dev/null @@ -1,102 +0,0 @@ -From c5d1455d9340c63e5c5d987e2d816e77538caa90 Mon Sep 17 00:00:00 2001 -From: Adam Jackson -Date: Tue, 13 Sep 2011 12:07:37 -0400 -Subject: [PATCH] drm/i915: Shut the fbc messages up - -FB compression enable/disable fires on pretty much every pageflip now, -which is just uncredibly excessive. Hush that noise. - -Signed-off-by: Adam Jackson ---- - drivers/gpu/drm/i915/intel_display.c | 19 ------------------- - 1 files changed, 0 insertions(+), 19 deletions(-) - -diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c -index 56a8554..a6d14eb 100644 ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -1474,8 +1474,6 @@ static void i8xx_disable_fbc(struct drm_device *dev) - DRM_DEBUG_KMS("FBC idle timed out\n"); - return; - } -- -- DRM_DEBUG_KMS("disabled FBC\n"); - } - - static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) -@@ -1516,9 +1514,6 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) - fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT; - fbc_ctl |= obj->fence_reg; - I915_WRITE(FBC_CONTROL, fbc_ctl); -- -- DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %d, ", -- cfb_pitch, crtc->y, intel_crtc->plane); - } - - static bool i8xx_fbc_enabled(struct drm_device *dev) -@@ -1551,8 +1546,6 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) - - /* enable it... */ - I915_WRITE(DPFC_CONTROL, I915_READ(DPFC_CONTROL) | DPFC_CTL_EN); -- -- DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); - } - - static void g4x_disable_fbc(struct drm_device *dev) -@@ -1565,8 +1558,6 @@ static void g4x_disable_fbc(struct drm_device *dev) - if (dpfc_ctl & DPFC_CTL_EN) { - dpfc_ctl &= ~DPFC_CTL_EN; - I915_WRITE(DPFC_CONTROL, dpfc_ctl); -- -- DRM_DEBUG_KMS("disabled FBC\n"); - } - } - -@@ -1631,8 +1622,6 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) - I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y); - sandybridge_blit_fbc_update(dev); - } -- -- DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); - } - - static void ironlake_disable_fbc(struct drm_device *dev) -@@ -1645,8 +1634,6 @@ static void ironlake_disable_fbc(struct drm_device *dev) - if (dpfc_ctl & DPFC_CTL_EN) { - dpfc_ctl &= ~DPFC_CTL_EN; - I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); -- -- DRM_DEBUG_KMS("disabled FBC\n"); - } - } - -@@ -1701,8 +1688,6 @@ static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv) - if (dev_priv->fbc_work == NULL) - return; - -- DRM_DEBUG_KMS("cancelling pending FBC enable\n"); -- - /* Synchronisation is provided by struct_mutex and checking of - * dev_priv->fbc_work, so we can perform the cancellation - * entirely asynchronously. -@@ -1743,8 +1728,6 @@ static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval) - - dev_priv->fbc_work = work; - -- DRM_DEBUG_KMS("scheduling delayed FBC enable\n"); -- - /* Delay the actual enabling to let pageflipping cease and the - * display to settle before starting the compression. Note that - * this delay also serves a second purpose: it allows for a -@@ -1800,8 +1783,6 @@ static void intel_update_fbc(struct drm_device *dev) - struct drm_i915_gem_object *obj; - int enable_fbc; - -- DRM_DEBUG_KMS("\n"); -- - if (!i915_powersave) - return; - --- -1.7.6 - diff --git a/jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch b/jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch deleted file mode 100644 index f5d82914f..000000000 --- a/jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 8762202dd0d6e46854f786bdb6fb3780a1625efe Mon Sep 17 00:00:00 2001 -From: Eryu Guan -Date: Tue, 1 Nov 2011 19:04:59 -0400 -Subject: [PATCH] jbd/jbd2: validate sb->s_first in journal_get_superblock() - -I hit a J_ASSERT(blocknr != 0) failure in cleanup_journal_tail() when -mounting a fsfuzzed ext3 image. It turns out that the corrupted ext3 -image has s_first = 0 in journal superblock, and the 0 is passed to -journal->j_head in journal_reset(), then to blocknr in -cleanup_journal_tail(), in the end the J_ASSERT failed. - -So validate s_first after reading journal superblock from disk in -journal_get_superblock() to ensure s_first is valid. - -The following script could reproduce it: - -fstype=ext3 -blocksize=1024 -img=$fstype.img -offset=0 -found=0 -magic="c0 3b 39 98" - -dd if=/dev/zero of=$img bs=1M count=8 -mkfs -t $fstype -b $blocksize -F $img -filesize=`stat -c %s $img` -while [ $offset -lt $filesize ] -do - if od -j $offset -N 4 -t x1 $img | grep -i "$magic";then - echo "Found journal: $offset" - found=1 - break - fi - offset=`echo "$offset+$blocksize" | bc` -done - -if [ $found -ne 1 ];then - echo "Magic \"$magic\" not found" - exit 1 -fi - -dd if=/dev/zero of=$img seek=$(($offset+23)) conv=notrunc bs=1 count=1 - -mkdir -p ./mnt -mount -o loop $img ./mnt - -Cc: Jan Kara -Signed-off-by: Eryu Guan -Signed-off-by: "Theodore Ts'o" ---- - fs/jbd/journal.c | 8 ++++++++ - fs/jbd2/journal.c | 8 ++++++++ - 2 files changed, 16 insertions(+), 0 deletions(-) - -diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c -index 9fe061f..fea8dd6 100644 ---- a/fs/jbd/journal.c -+++ b/fs/jbd/journal.c -@@ -1135,6 +1135,14 @@ static int journal_get_superblock(journal_t *journal) - goto out; - } - -+ if (be32_to_cpu(sb->s_first) == 0 || -+ be32_to_cpu(sb->s_first) >= journal->j_maxlen) { -+ printk(KERN_WARNING -+ "JBD: Invalid start block of journal: %u\n", -+ be32_to_cpu(sb->s_first)); -+ goto out; -+ } -+ - return 0; - - out: -diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c -index f24df13..d6e93d0 100644 ---- a/fs/jbd2/journal.c -+++ b/fs/jbd2/journal.c -@@ -1251,6 +1251,14 @@ static int journal_get_superblock(journal_t *journal) - goto out; - } - -+ if (be32_to_cpu(sb->s_first) == 0 || -+ be32_to_cpu(sb->s_first) >= journal->j_maxlen) { -+ printk(KERN_WARNING -+ "JBD2: Invalid start block of journal: %u\n", -+ be32_to_cpu(sb->s_first)); -+ goto out; -+ } -+ - return 0; - - out: --- -1.7.7.1 - diff --git a/kernel.spec b/kernel.spec index d37818baa..31b1fc809 100644 --- a/kernel.spec +++ b/kernel.spec @@ -60,13 +60,13 @@ Summary: The Linux kernel # base_sublevel is the kernel version we're starting with and patching # on top of -- for example, 2.6.22-rc7-git1 starts with a 2.6.21 base, # which yields a base_sublevel of 21. -%define base_sublevel 4 +%define base_sublevel 5 ## If this is a released kernel ## %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 14 +%define stable_update 0 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -643,9 +643,6 @@ Patch800: linux-2.6-crash-driver.patch Patch1824: drm-intel-next.patch Patch1825: drm-i915-dp-stfu.patch -# hush the i915 fbc noise -Patch1826: drm-i915-fbc-stfu.patch - Patch1900: linux-2.6-intel-iommu-igfx.patch # Quiet boot fixes @@ -657,9 +654,6 @@ Patch2901: drivers-media-update.patch # fs fixes -#rhbz 753346 -Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch - # NFSv4 # patches headed upstream @@ -675,9 +669,7 @@ Patch14010: lis3-improve-handling-of-null-rate.patch Patch19000: ips-noirq.patch # Uprobes (rhbz 832083) -Patch20000: uprobes-3.4-backport.patch -Patch20001: uprobes-3.4-tip.patch -Patch20002: uprobes-task_work_add-generic-process-context-callbacks.patch +Patch20000: uprobes-backport.patch #rhbz 769766 Patch21072: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch @@ -696,9 +688,6 @@ Patch21306: shlib_base_randomize.patch Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch -#rhbz 749276 -Patch22018: atl1c_net_next_update-3.4.patch - #Fix FIPS for aesni hardare Patch22055: crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch Patch22056: crypto-aesni-intel-fix-wrong-kfree-pointer.patch @@ -1199,10 +1188,6 @@ ApplyPatch taint-vbox.patch # bugfixes to drivers and filesystems # -# ext4 -#rhbz 753346 -ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch - # xfs # btrfs @@ -1274,7 +1259,6 @@ ApplyPatch linux-2.6-e1000-ich9-montevina.patch # Intel DRM ApplyOptionalPatch drm-intel-next.patch ApplyPatch drm-i915-dp-stfu.patch -ApplyPatch drm-i915-fbc-stfu.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch @@ -1302,9 +1286,7 @@ ApplyPatch ips-noirq.patch #ApplyPatch pci-crs-blacklist.patch # Uprobes (rhbz 832083) -ApplyPatch uprobes-3.4-backport.patch -ApplyPatch uprobes-3.4-tip.patch -ApplyPatch uprobes-task_work_add-generic-process-context-callbacks.patch +ApplyPatch uprobes-backport.patch #rhbz 754518 #ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -1315,9 +1297,6 @@ ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch ApplyPatch debug-808990.patch -#rhbz 749276 -ApplyPatch atl1c_net_next_update-3.4.patch - #Fix FIPS for aesni hardare ApplyPatch crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch ApplyPatch crypto-aesni-intel-fix-wrong-kfree-pointer.patch @@ -2022,6 +2001,9 @@ fi # and build. %changelog +* Tue Oct 16 2012 Dave Jones 3.5.0-1 +- Linux 3.5 + * Tue Oct 16 2012 Dave Jones 3.4.14-1 - Linux 3.4.14 diff --git a/linux-2.6-input-kill-stupid-messages.patch b/linux-2.6-input-kill-stupid-messages.patch index cc1dd7470..ff7023f51 100644 --- a/linux-2.6-input-kill-stupid-messages.patch +++ b/linux-2.6-input-kill-stupid-messages.patch @@ -1,32 +1,20 @@ -From b2c6d55b2351152696aafb8c9bf3ec8968acf77c Mon Sep 17 00:00:00 2001 -From: Kyle McMartin -Date: Mon, 29 Mar 2010 23:59:58 -0400 -Subject: linux-2.6-input-kill-stupid-messages - ---- - drivers/input/keyboard/atkbd.c | 5 +++++ - 1 files changed, 5 insertions(+), 0 deletions(-) - diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c -index d358ef8..38db098 100644 +index add5ffd..5eb2f03 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c -@@ -425,11 +426,15 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, +@@ -430,11 +430,15 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, goto out; case ATKBD_RET_ACK: case ATKBD_RET_NAK: -+#if 0 ++# if 0 + /* Quite a few key switchers and other tools trigger this + * and it confuses people who can do nothing about it */ if (printk_ratelimit()) dev_warn(&serio->dev, "Spurious %s on %s. " - "Some program might be trying access hardware directly.\n", + "Some program might be trying to access hardware directly.\n", data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); +#endif goto out; case ATKBD_RET_ERR: atkbd->err_count++; --- -1.7.0.1 - diff --git a/linux-2.6-makefile-after_link.patch b/linux-2.6-makefile-after_link.patch index c2541b1d8..b520b1942 100644 --- a/linux-2.6-makefile-after_link.patch +++ b/linux-2.6-makefile-after_link.patch @@ -1,4 +1,4 @@ -From f072f7db2194c8255c003d985b61ad2f97ebbee0 Mon Sep 17 00:00:00 2001 +From b707aea6a4947c3806ced2c23e889943a0f36876 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Mon, 6 Oct 2008 23:03:03 -0700 Subject: [PATCH] kbuild: AFTER_LINK @@ -7,24 +7,9 @@ If the make variable AFTER_LINK is set, it is a command line to run after each final link. This includes vmlinux itself and vDSO images. Signed-off-by: Roland McGrath ---- -diff --git a/Makefile b/Makefile -index f908acc..960ff6f 100644 ---- a/Makefile -+++ b/Makefile -@@ -746,6 +746,10 @@ quiet_cmd_vmlinux__ ?= LD $@ - --start-group $(vmlinux-main) --end-group \ - $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o FORCE ,$^) - -+ifdef AFTER_LINK -+cmd_vmlinux__ += ; $(AFTER_LINK) -+endif -+ - # Generate new vmlinux version - quiet_cmd_vmlinux_version = GEN .version - cmd_vmlinux_version = set -e; \ + diff --git a/arch/powerpc/kernel/vdso32/Makefile b/arch/powerpc/kernel/vdso32/Makefile -index 51ead52..ad21273 100644 +index 9a7946c..28d6765 100644 --- a/arch/powerpc/kernel/vdso32/Makefile +++ b/arch/powerpc/kernel/vdso32/Makefile @@ -41,7 +41,8 @@ $(obj-vdso32): %.o: %.S @@ -38,7 +23,7 @@ index 51ead52..ad21273 100644 cmd_vdso32as = $(CROSS32CC) $(a_flags) -c -o $@ $< diff --git a/arch/powerpc/kernel/vdso64/Makefile b/arch/powerpc/kernel/vdso64/Makefile -index 79da65d..f11c21b 100644 +index 8c500d8..d27737b 100644 --- a/arch/powerpc/kernel/vdso64/Makefile +++ b/arch/powerpc/kernel/vdso64/Makefile @@ -36,7 +36,8 @@ $(obj-vdso64): %.o: %.S @@ -51,11 +36,39 @@ index 79da65d..f11c21b 100644 quiet_cmd_vdso64as = VDSO64A $@ cmd_vdso64as = $(CC) $(a_flags) -c -o $@ $< +diff --git a/arch/s390/kernel/vdso32/Makefile b/arch/s390/kernel/vdso32/Makefile +index 8ad2b34..e153572 100644 +--- a/arch/s390/kernel/vdso32/Makefile ++++ b/arch/s390/kernel/vdso32/Makefile +@@ -43,7 +43,8 @@ $(obj-vdso32): %.o: %.S + + # actual build commands + quiet_cmd_vdso32ld = VDSO32L $@ +- cmd_vdso32ld = $(CC) $(c_flags) -Wl,-T $^ -o $@ ++ cmd_vdso32ld = $(CC) $(c_flags) -Wl,-T $^ -o $@ \ ++ $(if $(AFTER_LINK),; $(AFTER_LINK)) + quiet_cmd_vdso32as = VDSO32A $@ + cmd_vdso32as = $(CC) $(a_flags) -c -o $@ $< + +diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile +index 2a8ddfd..452ca53 100644 +--- a/arch/s390/kernel/vdso64/Makefile ++++ b/arch/s390/kernel/vdso64/Makefile +@@ -43,7 +43,8 @@ $(obj-vdso64): %.o: %.S + + # actual build commands + quiet_cmd_vdso64ld = VDSO64L $@ +- cmd_vdso64ld = $(CC) $(c_flags) -Wl,-T $^ -o $@ ++ cmd_vdso64ld = $(CC) $(c_flags) -Wl,-T $^ -o $@ \ ++ $(if $(AFTER_LINK),; $(AFTER_LINK)) + quiet_cmd_vdso64as = VDSO64A $@ + cmd_vdso64as = $(CC) $(a_flags) -c -o $@ $< + diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile -index 4a2afa1..12ad9f7 100644 +index fd14be1..1f3eb19 100644 --- a/arch/x86/vdso/Makefile +++ b/arch/x86/vdso/Makefile -@@ -120,8 +120,9 @@ $(obj)/vdso32-syms.lds: $(vdso32.so-y:%=$(obj)/vdso32-%-syms.lds) FORCE +@@ -178,8 +178,9 @@ $(obj)/vdso32-syms.lds: $(vdso32.so-y:%=$(obj)/vdso32-%-syms.lds) FORCE quiet_cmd_vdso = VDSO $@ cmd_vdso = $(CC) -nostdlib -o $@ \ $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \ @@ -67,32 +80,21 @@ index 4a2afa1..12ad9f7 100644 VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) GCOV_PROFILE := n +diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh +index cd9c6c6..3edf048 100644 +--- a/scripts/link-vmlinux.sh ++++ b/scripts/link-vmlinux.sh +@@ -65,6 +65,10 @@ vmlinux_link() + -lutil ${1} + rm -f linux + fi ++ if [ -n "${AFTER_LINK}" ]; then ++ /usr/lib/rpm/debugedit -b ${RPM_BUILD_DIR} -d /usr/src/debug -i ${2} \ ++ > ${2}.id ++ fi + } + + +-- +1.7.7.6 -diff --git a/arch/s390/kernel/vdso32/Makefile b/arch/s390/kernel/vdso32/Makefile -index d13e875..28a3e1ad 100644 ---- a/arch/s390/kernel/vdso32/Makefile -+++ b/arch/s390/kernel/vdso32/Makefile -@@ -40,7 +40,8 @@ $(obj-vdso32): %.o: %.S - - # actual build commands - quiet_cmd_vdso32ld = VDSO32L $@ -- cmd_vdso32ld = $(CC) $(c_flags) -Wl,-T $^ -o $@ -+ cmd_vdso32ld = $(CC) $(c_flags) -Wl,-T $^ -o $@ \ -+ $(if $(AFTER_LINK),; $(AFTER_LINK)) - quiet_cmd_vdso32as = VDSO32A $@ - cmd_vdso32as = $(CC) $(a_flags) -c -o $@ $< - -diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile -index 449352d..e90e656 100644 ---- a/arch/s390/kernel/vdso64/Makefile -+++ b/arch/s390/kernel/vdso64/Makefile -@@ -40,7 +40,8 @@ $(obj-vdso64): %.o: %.S - - # actual build commands - quiet_cmd_vdso64ld = VDSO64L $@ -- cmd_vdso64ld = $(CC) $(c_flags) -Wl,-T $^ -o $@ -+ cmd_vdso64ld = $(CC) $(c_flags) -Wl,-T $^ -o $@ \ -+ $(if $(AFTER_LINK),; $(AFTER_LINK)) - quiet_cmd_vdso64as = VDSO64A $@ - cmd_vdso64as = $(CC) $(a_flags) -c -o $@ $< - diff --git a/scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch b/scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch index 492376d78..48db13328 100644 --- a/scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch +++ b/scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -12,7 +12,7 @@ SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_revalidate_disk\n")); -+ if (!sdkp) ++ if (WARN_ONCE((!sdkp), "Invalid scsi_disk from %p\n", disk)) + goto out; + + sdp = sdkp->device; diff --git a/sources b/sources index 40daba29f..d239339bc 100644 --- a/sources +++ b/sources @@ -1,2 +1 @@ -967f72983655e2479f951195953e8480 linux-3.4.tar.xz -c3225a0538db8486d991c1af70f5f0a4 patch-3.4.14.xz +24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz diff --git a/uprobes-3.4-backport.patch b/uprobes-3.4-backport.patch deleted file mode 100644 index 4a5bfe60b..000000000 --- a/uprobes-3.4-backport.patch +++ /dev/null @@ -1,6983 +0,0 @@ -Modification of the kernel config is needed: - +CONFIG_ARCH_SUPPORTS_UPROBES=y - +CONFIG_UPROBES=y - +CONFIG_UPROBE_EVENT=y - +CONFIG_PROBE_EVENTS=y - -The split-out series is available in the git repository at: - - git://fedorapeople.org/home/fedora/aarapov/public_git/kernel-uprobes.git f17_uprobes_upstream - -Ingo Molnar (3): - uprobes/core: Clean up, refactor and improve the code - uprobes: Move to kernel/events/ - uprobes: Update copyright notices - -Srikar Dronamraju (20): - uprobes, mm, x86: Add the ability to install and remove uprobes breakpoints - uprobes/core: Make instruction tables volatile - uprobes/core: Remove uprobe_opcode_sz - uprobes/core: Move insn to arch specific structure - uprobes/core: Make macro names consistent - uprobes/core: Make order of function parameters consistent across functions - uprobes/core: Rename bkpt to swbp - uprobes/core: Handle breakpoint and singlestep exceptions - uprobes/core: Allocate XOL slots for uprobes use - uprobes/core: Optimize probe hits with the help of a counter - uprobes/core: Make background page replacement logic account for rss_stat counters - uprobes/core: Decrement uprobe count before the pages are unmapped - tracing: Modify is_delete, is_return from int to bool - tracing: Extract out common code for kprobes/uprobes trace events - tracing: Provide trace events interface for uprobes - tracing: Fix kconfig warning due to a typo - perf probe: Provide perf interface for uprobes - perf probe: Detect probe target when m/x options are absent - perf symbols: Check for valid dso before creating map - perf uprobes: Remove unnecessary check before strlist__delete - -Signed-off-by: Anton Arapov ---- - Documentation/trace/uprobetracer.txt | 113 +++ - arch/Kconfig | 17 + - arch/x86/Kconfig | 5 +- - arch/x86/include/asm/thread_info.h | 2 + - arch/x86/include/asm/uprobes.h | 57 ++ - arch/x86/kernel/Makefile | 1 + - arch/x86/kernel/signal.c | 6 + - arch/x86/kernel/uprobes.c | 674 +++++++++++++ - include/linux/mm_types.h | 2 + - include/linux/sched.h | 4 + - include/linux/uprobes.h | 165 +++ - kernel/events/Makefile | 3 + - kernel/events/uprobes.c | 1667 +++++++++++++++++++++++++++++++ - kernel/fork.c | 9 + - kernel/signal.c | 4 + - kernel/trace/Kconfig | 20 + - kernel/trace/Makefile | 2 + - kernel/trace/trace.h | 5 + - kernel/trace/trace_kprobe.c | 899 +---------------- - kernel/trace/trace_probe.c | 839 ++++++++++++++++ - kernel/trace/trace_probe.h | 161 +++ - kernel/trace/trace_uprobe.c | 788 +++++++++++++++ - mm/memory.c | 3 + - mm/mmap.c | 33 +- - tools/perf/Documentation/perf-probe.txt | 19 +- - tools/perf/builtin-probe.c | 86 +- - tools/perf/util/probe-event.c | 418 ++++++-- - tools/perf/util/probe-event.h | 12 +- - tools/perf/util/symbol.c | 11 + - tools/perf/util/symbol.h | 1 + - 30 files changed, 5047 insertions(+), 979 deletions(-) - create mode 100644 Documentation/trace/uprobetracer.txt - create mode 100644 arch/x86/include/asm/uprobes.h - create mode 100644 arch/x86/kernel/uprobes.c - create mode 100644 include/linux/uprobes.h - create mode 100644 kernel/events/uprobes.c - create mode 100644 kernel/trace/trace_probe.c - create mode 100644 kernel/trace/trace_probe.h - create mode 100644 kernel/trace/trace_uprobe.c - -diff --git a/Documentation/trace/uprobetracer.txt b/Documentation/trace/uprobetracer.txt -new file mode 100644 -index 0000000..24ce682 ---- /dev/null -+++ b/Documentation/trace/uprobetracer.txt -@@ -0,0 +1,113 @@ -+ Uprobe-tracer: Uprobe-based Event Tracing -+ ========================================= -+ Documentation written by Srikar Dronamraju -+ -+Overview -+-------- -+Uprobe based trace events are similar to kprobe based trace events. -+To enable this feature, build your kernel with CONFIG_UPROBE_EVENT=y. -+ -+Similar to the kprobe-event tracer, this doesn't need to be activated via -+current_tracer. Instead of that, add probe points via -+/sys/kernel/debug/tracing/uprobe_events, and enable it via -+/sys/kernel/debug/tracing/events/uprobes//enabled. -+ -+However unlike kprobe-event tracer, the uprobe event interface expects the -+user to calculate the offset of the probepoint in the object -+ -+Synopsis of uprobe_tracer -+------------------------- -+ p[:[GRP/]EVENT] PATH:SYMBOL[+offs] [FETCHARGS] : Set a probe -+ -+ GRP : Group name. If omitted, use "uprobes" for it. -+ EVENT : Event name. If omitted, the event name is generated -+ based on SYMBOL+offs. -+ PATH : path to an executable or a library. -+ SYMBOL[+offs] : Symbol+offset where the probe is inserted. -+ -+ FETCHARGS : Arguments. Each probe can have up to 128 args. -+ %REG : Fetch register REG -+ -+Event Profiling -+--------------- -+ You can check the total number of probe hits and probe miss-hits via -+/sys/kernel/debug/tracing/uprobe_profile. -+ The first column is event name, the second is the number of probe hits, -+the third is the number of probe miss-hits. -+ -+Usage examples -+-------------- -+To add a probe as a new event, write a new definition to uprobe_events -+as below. -+ -+ echo 'p: /bin/bash:0x4245c0' > /sys/kernel/debug/tracing/uprobe_events -+ -+ This sets a uprobe at an offset of 0x4245c0 in the executable /bin/bash -+ -+ echo > /sys/kernel/debug/tracing/uprobe_events -+ -+ This clears all probe points. -+ -+The following example shows how to dump the instruction pointer and %ax -+a register at the probed text address. Here we are trying to probe -+function zfree in /bin/zsh -+ -+ # cd /sys/kernel/debug/tracing/ -+ # cat /proc/`pgrep zsh`/maps | grep /bin/zsh | grep r-xp -+ 00400000-0048a000 r-xp 00000000 08:03 130904 /bin/zsh -+ # objdump -T /bin/zsh | grep -w zfree -+ 0000000000446420 g DF .text 0000000000000012 Base zfree -+ -+0x46420 is the offset of zfree in object /bin/zsh that is loaded at -+0x00400000. Hence the command to probe would be : -+ -+ # echo 'p /bin/zsh:0x46420 %ip %ax' > uprobe_events -+ -+Please note: User has to explicitly calculate the offset of the probepoint -+in the object. We can see the events that are registered by looking at the -+uprobe_events file. -+ -+ # cat uprobe_events -+ p:uprobes/p_zsh_0x46420 /bin/zsh:0x00046420 arg1=%ip arg2=%ax -+ -+The format of events can be seen by viewing the file events/uprobes/p_zsh_0x46420/format -+ -+ # cat events/uprobes/p_zsh_0x46420/format -+ name: p_zsh_0x46420 -+ ID: 922 -+ format: -+ field:unsigned short common_type; offset:0; size:2; signed:0; -+ field:unsigned char common_flags; offset:2; size:1; signed:0; -+ field:unsigned char common_preempt_count; offset:3; size:1; signed:0; -+ field:int common_pid; offset:4; size:4; signed:1; -+ field:int common_padding; offset:8; size:4; signed:1; -+ -+ field:unsigned long __probe_ip; offset:12; size:4; signed:0; -+ field:u32 arg1; offset:16; size:4; signed:0; -+ field:u32 arg2; offset:20; size:4; signed:0; -+ -+ print fmt: "(%lx) arg1=%lx arg2=%lx", REC->__probe_ip, REC->arg1, REC->arg2 -+ -+Right after definition, each event is disabled by default. For tracing these -+events, you need to enable it by: -+ -+ # echo 1 > events/uprobes/enable -+ -+Lets disable the event after sleeping for some time. -+ # sleep 20 -+ # echo 0 > events/uprobes/enable -+ -+And you can see the traced information via /sys/kernel/debug/tracing/trace. -+ -+ # cat trace -+ # tracer: nop -+ # -+ # TASK-PID CPU# TIMESTAMP FUNCTION -+ # | | | | | -+ zsh-24842 [006] 258544.995456: p_zsh_0x46420: (0x446420) arg1=446421 arg2=79 -+ zsh-24842 [007] 258545.000270: p_zsh_0x46420: (0x446420) arg1=446421 arg2=79 -+ zsh-24842 [002] 258545.043929: p_zsh_0x46420: (0x446420) arg1=446421 arg2=79 -+ zsh-24842 [004] 258547.046129: p_zsh_0x46420: (0x446420) arg1=446421 arg2=79 -+ -+Each line shows us probes were triggered for a pid 24842 with ip being -+0x446421 and contents of ax register being 79. -diff --git a/arch/Kconfig b/arch/Kconfig -index 684eb5a..2880abf 100644 ---- a/arch/Kconfig -+++ b/arch/Kconfig -@@ -76,6 +76,23 @@ config OPTPROBES - depends on KPROBES && HAVE_OPTPROBES - depends on !PREEMPT - -+config UPROBES -+ bool "Transparent user-space probes (EXPERIMENTAL)" -+ depends on UPROBE_EVENT && PERF_EVENTS -+ default n -+ help -+ Uprobes is the user-space counterpart to kprobes: they -+ enable instrumentation applications (such as 'perf probe') -+ to establish unintrusive probes in user-space binaries and -+ libraries, by executing handler functions when the probes -+ are hit by user-space applications. -+ -+ ( These probes come in the form of single-byte breakpoints, -+ managed by the kernel and kept transparent to the probed -+ application. ) -+ -+ If in doubt, say "N". -+ - config HAVE_EFFICIENT_UNALIGNED_ACCESS - bool - help -diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig -index c9866b0..1f5c307 100644 ---- a/arch/x86/Kconfig -+++ b/arch/x86/Kconfig -@@ -84,7 +84,7 @@ config X86 - select DCACHE_WORD_ACCESS - - config INSTRUCTION_DECODER -- def_bool (KPROBES || PERF_EVENTS) -+ def_bool (KPROBES || PERF_EVENTS || UPROBES) - - config OUTPUT_FORMAT - string -@@ -243,6 +243,9 @@ config ARCH_CPU_PROBE_RELEASE - def_bool y - depends on HOTPLUG_CPU - -+config ARCH_SUPPORTS_UPROBES -+ def_bool y -+ - source "init/Kconfig" - source "kernel/Kconfig.freezer" - -diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h -index ad6df8c..0710c11 100644 ---- a/arch/x86/include/asm/thread_info.h -+++ b/arch/x86/include/asm/thread_info.h -@@ -85,6 +85,7 @@ struct thread_info { - #define TIF_SECCOMP 8 /* secure computing */ - #define TIF_MCE_NOTIFY 10 /* notify userspace of an MCE */ - #define TIF_USER_RETURN_NOTIFY 11 /* notify kernel of userspace return */ -+#define TIF_UPROBE 12 /* breakpointed or singlestepping */ - #define TIF_NOTSC 16 /* TSC is not accessible in userland */ - #define TIF_IA32 17 /* IA32 compatibility process */ - #define TIF_FORK 18 /* ret_from_fork */ -@@ -109,6 +110,7 @@ struct thread_info { - #define _TIF_SECCOMP (1 << TIF_SECCOMP) - #define _TIF_MCE_NOTIFY (1 << TIF_MCE_NOTIFY) - #define _TIF_USER_RETURN_NOTIFY (1 << TIF_USER_RETURN_NOTIFY) -+#define _TIF_UPROBE (1 << TIF_UPROBE) - #define _TIF_NOTSC (1 << TIF_NOTSC) - #define _TIF_IA32 (1 << TIF_IA32) - #define _TIF_FORK (1 << TIF_FORK) -diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h -new file mode 100644 -index 0000000..1e9bed1 ---- /dev/null -+++ b/arch/x86/include/asm/uprobes.h -@@ -0,0 +1,57 @@ -+#ifndef _ASM_UPROBES_H -+#define _ASM_UPROBES_H -+/* -+ * User-space Probes (UProbes) for x86 -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) IBM Corporation, 2008-2011 -+ * Authors: -+ * Srikar Dronamraju -+ * Jim Keniston -+ */ -+ -+#include -+ -+typedef u8 uprobe_opcode_t; -+ -+#define MAX_UINSN_BYTES 16 -+#define UPROBE_XOL_SLOT_BYTES 128 /* to keep it cache aligned */ -+ -+#define UPROBE_SWBP_INSN 0xcc -+#define UPROBE_SWBP_INSN_SIZE 1 -+ -+struct arch_uprobe { -+ u16 fixups; -+ u8 insn[MAX_UINSN_BYTES]; -+#ifdef CONFIG_X86_64 -+ unsigned long rip_rela_target_address; -+#endif -+}; -+ -+struct arch_uprobe_task { -+ unsigned long saved_trap_nr; -+#ifdef CONFIG_X86_64 -+ unsigned long saved_scratch_register; -+#endif -+}; -+ -+extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm); -+extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs); -+extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs); -+extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk); -+extern int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data); -+extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs); -+#endif /* _ASM_UPROBES_H */ -diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile -index 532d2e0..d23d835 100644 ---- a/arch/x86/kernel/Makefile -+++ b/arch/x86/kernel/Makefile -@@ -101,6 +101,7 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o - - obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o - obj-$(CONFIG_OF) += devicetree.o -+obj-$(CONFIG_UPROBES) += uprobes.o - - ### - # 64 bit specific files -diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c -index 115eac4..041af2f 100644 ---- a/arch/x86/kernel/signal.c -+++ b/arch/x86/kernel/signal.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -824,6 +825,11 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) - mce_notify_process(); - #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */ - -+ if (thread_info_flags & _TIF_UPROBE) { -+ clear_thread_flag(TIF_UPROBE); -+ uprobe_notify_resume(regs); -+ } -+ - /* deal with pending signal delivery */ - if (thread_info_flags & _TIF_SIGPENDING) - do_signal(regs); -diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c -new file mode 100644 -index 0000000..dc4e910 ---- /dev/null -+++ b/arch/x86/kernel/uprobes.c -@@ -0,0 +1,674 @@ -+/* -+ * User-space Probes (UProbes) for x86 -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) IBM Corporation, 2008-2011 -+ * Authors: -+ * Srikar Dronamraju -+ * Jim Keniston -+ */ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+/* Post-execution fixups. */ -+ -+/* No fixup needed */ -+#define UPROBE_FIX_NONE 0x0 -+ -+/* Adjust IP back to vicinity of actual insn */ -+#define UPROBE_FIX_IP 0x1 -+ -+/* Adjust the return address of a call insn */ -+#define UPROBE_FIX_CALL 0x2 -+ -+#define UPROBE_FIX_RIP_AX 0x8000 -+#define UPROBE_FIX_RIP_CX 0x4000 -+ -+#define UPROBE_TRAP_NR UINT_MAX -+ -+/* Adaptations for mhiramat x86 decoder v14. */ -+#define OPCODE1(insn) ((insn)->opcode.bytes[0]) -+#define OPCODE2(insn) ((insn)->opcode.bytes[1]) -+#define OPCODE3(insn) ((insn)->opcode.bytes[2]) -+#define MODRM_REG(insn) X86_MODRM_REG(insn->modrm.value) -+ -+#define W(row, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf)\ -+ (((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) | \ -+ (b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) | \ -+ (b8##UL << 0x8)|(b9##UL << 0x9)|(ba##UL << 0xa)|(bb##UL << 0xb) | \ -+ (bc##UL << 0xc)|(bd##UL << 0xd)|(be##UL << 0xe)|(bf##UL << 0xf)) \ -+ << (row % 32)) -+ -+/* -+ * Good-instruction tables for 32-bit apps. This is non-const and volatile -+ * to keep gcc from statically optimizing it out, as variable_test_bit makes -+ * some versions of gcc to think only *(unsigned long*) is used. -+ */ -+static volatile u32 good_insns_32[256 / 32] = { -+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -+ /* ---------------------------------------------- */ -+ W(0x00, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) | /* 00 */ -+ W(0x10, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) , /* 10 */ -+ W(0x20, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1) | /* 20 */ -+ W(0x30, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1) , /* 30 */ -+ W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 40 */ -+ W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 50 */ -+ W(0x60, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* 60 */ -+ W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 70 */ -+ W(0x80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 80 */ -+ W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 90 */ -+ W(0xa0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* a0 */ -+ W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* b0 */ -+ W(0xc0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0) | /* c0 */ -+ W(0xd0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */ -+ W(0xe0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* e0 */ -+ W(0xf0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1) /* f0 */ -+ /* ---------------------------------------------- */ -+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -+}; -+ -+/* Using this for both 64-bit and 32-bit apps */ -+static volatile u32 good_2byte_insns[256 / 32] = { -+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -+ /* ---------------------------------------------- */ -+ W(0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1) | /* 00 */ -+ W(0x10, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1) , /* 10 */ -+ W(0x20, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1) | /* 20 */ -+ W(0x30, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 30 */ -+ W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 40 */ -+ W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 50 */ -+ W(0x60, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 60 */ -+ W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1) , /* 70 */ -+ W(0x80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 80 */ -+ W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 90 */ -+ W(0xa0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1) | /* a0 */ -+ W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1) , /* b0 */ -+ W(0xc0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* c0 */ -+ W(0xd0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */ -+ W(0xe0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* e0 */ -+ W(0xf0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0) /* f0 */ -+ /* ---------------------------------------------- */ -+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -+}; -+ -+#ifdef CONFIG_X86_64 -+/* Good-instruction tables for 64-bit apps */ -+static volatile u32 good_insns_64[256 / 32] = { -+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -+ /* ---------------------------------------------- */ -+ W(0x00, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) | /* 00 */ -+ W(0x10, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) , /* 10 */ -+ W(0x20, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) | /* 20 */ -+ W(0x30, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) , /* 30 */ -+ W(0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* 40 */ -+ W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 50 */ -+ W(0x60, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* 60 */ -+ W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 70 */ -+ W(0x80, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 80 */ -+ W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 90 */ -+ W(0xa0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* a0 */ -+ W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* b0 */ -+ W(0xc0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0) | /* c0 */ -+ W(0xd0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */ -+ W(0xe0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* e0 */ -+ W(0xf0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1) /* f0 */ -+ /* ---------------------------------------------- */ -+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -+}; -+#endif -+#undef W -+ -+/* -+ * opcodes we'll probably never support: -+ * -+ * 6c-6d, e4-e5, ec-ed - in -+ * 6e-6f, e6-e7, ee-ef - out -+ * cc, cd - int3, int -+ * cf - iret -+ * d6 - illegal instruction -+ * f1 - int1/icebp -+ * f4 - hlt -+ * fa, fb - cli, sti -+ * 0f - lar, lsl, syscall, clts, sysret, sysenter, sysexit, invd, wbinvd, ud2 -+ * -+ * invalid opcodes in 64-bit mode: -+ * -+ * 06, 0e, 16, 1e, 27, 2f, 37, 3f, 60-62, 82, c4-c5, d4-d5 -+ * 63 - we support this opcode in x86_64 but not in i386. -+ * -+ * opcodes we may need to refine support for: -+ * -+ * 0f - 2-byte instructions: For many of these instructions, the validity -+ * depends on the prefix and/or the reg field. On such instructions, we -+ * just consider the opcode combination valid if it corresponds to any -+ * valid instruction. -+ * -+ * 8f - Group 1 - only reg = 0 is OK -+ * c6-c7 - Group 11 - only reg = 0 is OK -+ * d9-df - fpu insns with some illegal encodings -+ * f2, f3 - repnz, repz prefixes. These are also the first byte for -+ * certain floating-point instructions, such as addsd. -+ * -+ * fe - Group 4 - only reg = 0 or 1 is OK -+ * ff - Group 5 - only reg = 0-6 is OK -+ * -+ * others -- Do we need to support these? -+ * -+ * 0f - (floating-point?) prefetch instructions -+ * 07, 17, 1f - pop es, pop ss, pop ds -+ * 26, 2e, 36, 3e - es:, cs:, ss:, ds: segment prefixes -- -+ * but 64 and 65 (fs: and gs:) seem to be used, so we support them -+ * 67 - addr16 prefix -+ * ce - into -+ * f0 - lock prefix -+ */ -+ -+/* -+ * TODO: -+ * - Where necessary, examine the modrm byte and allow only valid instructions -+ * in the different Groups and fpu instructions. -+ */ -+ -+static bool is_prefix_bad(struct insn *insn) -+{ -+ int i; -+ -+ for (i = 0; i < insn->prefixes.nbytes; i++) { -+ switch (insn->prefixes.bytes[i]) { -+ case 0x26: /* INAT_PFX_ES */ -+ case 0x2E: /* INAT_PFX_CS */ -+ case 0x36: /* INAT_PFX_DS */ -+ case 0x3E: /* INAT_PFX_SS */ -+ case 0xF0: /* INAT_PFX_LOCK */ -+ return true; -+ } -+ } -+ return false; -+} -+ -+static int validate_insn_32bits(struct arch_uprobe *auprobe, struct insn *insn) -+{ -+ insn_init(insn, auprobe->insn, false); -+ -+ /* Skip good instruction prefixes; reject "bad" ones. */ -+ insn_get_opcode(insn); -+ if (is_prefix_bad(insn)) -+ return -ENOTSUPP; -+ -+ if (test_bit(OPCODE1(insn), (unsigned long *)good_insns_32)) -+ return 0; -+ -+ if (insn->opcode.nbytes == 2) { -+ if (test_bit(OPCODE2(insn), (unsigned long *)good_2byte_insns)) -+ return 0; -+ } -+ -+ return -ENOTSUPP; -+} -+ -+/* -+ * Figure out which fixups arch_uprobe_post_xol() will need to perform, and -+ * annotate arch_uprobe->fixups accordingly. To start with, -+ * arch_uprobe->fixups is either zero or it reflects rip-related fixups. -+ */ -+static void prepare_fixups(struct arch_uprobe *auprobe, struct insn *insn) -+{ -+ bool fix_ip = true, fix_call = false; /* defaults */ -+ int reg; -+ -+ insn_get_opcode(insn); /* should be a nop */ -+ -+ switch (OPCODE1(insn)) { -+ case 0xc3: /* ret/lret */ -+ case 0xcb: -+ case 0xc2: -+ case 0xca: -+ /* ip is correct */ -+ fix_ip = false; -+ break; -+ case 0xe8: /* call relative - Fix return addr */ -+ fix_call = true; -+ break; -+ case 0x9a: /* call absolute - Fix return addr, not ip */ -+ fix_call = true; -+ fix_ip = false; -+ break; -+ case 0xff: -+ insn_get_modrm(insn); -+ reg = MODRM_REG(insn); -+ if (reg == 2 || reg == 3) { -+ /* call or lcall, indirect */ -+ /* Fix return addr; ip is correct. */ -+ fix_call = true; -+ fix_ip = false; -+ } else if (reg == 4 || reg == 5) { -+ /* jmp or ljmp, indirect */ -+ /* ip is correct. */ -+ fix_ip = false; -+ } -+ break; -+ case 0xea: /* jmp absolute -- ip is correct */ -+ fix_ip = false; -+ break; -+ default: -+ break; -+ } -+ if (fix_ip) -+ auprobe->fixups |= UPROBE_FIX_IP; -+ if (fix_call) -+ auprobe->fixups |= UPROBE_FIX_CALL; -+} -+ -+#ifdef CONFIG_X86_64 -+/* -+ * If arch_uprobe->insn doesn't use rip-relative addressing, return -+ * immediately. Otherwise, rewrite the instruction so that it accesses -+ * its memory operand indirectly through a scratch register. Set -+ * arch_uprobe->fixups and arch_uprobe->rip_rela_target_address -+ * accordingly. (The contents of the scratch register will be saved -+ * before we single-step the modified instruction, and restored -+ * afterward.) -+ * -+ * We do this because a rip-relative instruction can access only a -+ * relatively small area (+/- 2 GB from the instruction), and the XOL -+ * area typically lies beyond that area. At least for instructions -+ * that store to memory, we can't execute the original instruction -+ * and "fix things up" later, because the misdirected store could be -+ * disastrous. -+ * -+ * Some useful facts about rip-relative instructions: -+ * -+ * - There's always a modrm byte. -+ * - There's never a SIB byte. -+ * - The displacement is always 4 bytes. -+ */ -+static void -+handle_riprel_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, struct insn *insn) -+{ -+ u8 *cursor; -+ u8 reg; -+ -+ if (mm->context.ia32_compat) -+ return; -+ -+ auprobe->rip_rela_target_address = 0x0; -+ if (!insn_rip_relative(insn)) -+ return; -+ -+ /* -+ * insn_rip_relative() would have decoded rex_prefix, modrm. -+ * Clear REX.b bit (extension of MODRM.rm field): -+ * we want to encode rax/rcx, not r8/r9. -+ */ -+ if (insn->rex_prefix.nbytes) { -+ cursor = auprobe->insn + insn_offset_rex_prefix(insn); -+ *cursor &= 0xfe; /* Clearing REX.B bit */ -+ } -+ -+ /* -+ * Point cursor at the modrm byte. The next 4 bytes are the -+ * displacement. Beyond the displacement, for some instructions, -+ * is the immediate operand. -+ */ -+ cursor = auprobe->insn + insn_offset_modrm(insn); -+ insn_get_length(insn); -+ -+ /* -+ * Convert from rip-relative addressing to indirect addressing -+ * via a scratch register. Change the r/m field from 0x5 (%rip) -+ * to 0x0 (%rax) or 0x1 (%rcx), and squeeze out the offset field. -+ */ -+ reg = MODRM_REG(insn); -+ if (reg == 0) { -+ /* -+ * The register operand (if any) is either the A register -+ * (%rax, %eax, etc.) or (if the 0x4 bit is set in the -+ * REX prefix) %r8. In any case, we know the C register -+ * is NOT the register operand, so we use %rcx (register -+ * #1) for the scratch register. -+ */ -+ auprobe->fixups = UPROBE_FIX_RIP_CX; -+ /* Change modrm from 00 000 101 to 00 000 001. */ -+ *cursor = 0x1; -+ } else { -+ /* Use %rax (register #0) for the scratch register. */ -+ auprobe->fixups = UPROBE_FIX_RIP_AX; -+ /* Change modrm from 00 xxx 101 to 00 xxx 000 */ -+ *cursor = (reg << 3); -+ } -+ -+ /* Target address = address of next instruction + (signed) offset */ -+ auprobe->rip_rela_target_address = (long)insn->length + insn->displacement.value; -+ -+ /* Displacement field is gone; slide immediate field (if any) over. */ -+ if (insn->immediate.nbytes) { -+ cursor++; -+ memmove(cursor, cursor + insn->displacement.nbytes, insn->immediate.nbytes); -+ } -+ return; -+} -+ -+static int validate_insn_64bits(struct arch_uprobe *auprobe, struct insn *insn) -+{ -+ insn_init(insn, auprobe->insn, true); -+ -+ /* Skip good instruction prefixes; reject "bad" ones. */ -+ insn_get_opcode(insn); -+ if (is_prefix_bad(insn)) -+ return -ENOTSUPP; -+ -+ if (test_bit(OPCODE1(insn), (unsigned long *)good_insns_64)) -+ return 0; -+ -+ if (insn->opcode.nbytes == 2) { -+ if (test_bit(OPCODE2(insn), (unsigned long *)good_2byte_insns)) -+ return 0; -+ } -+ return -ENOTSUPP; -+} -+ -+static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm, struct insn *insn) -+{ -+ if (mm->context.ia32_compat) -+ return validate_insn_32bits(auprobe, insn); -+ return validate_insn_64bits(auprobe, insn); -+} -+#else /* 32-bit: */ -+static void handle_riprel_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, struct insn *insn) -+{ -+ /* No RIP-relative addressing on 32-bit */ -+} -+ -+static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm, struct insn *insn) -+{ -+ return validate_insn_32bits(auprobe, insn); -+} -+#endif /* CONFIG_X86_64 */ -+ -+/** -+ * arch_uprobe_analyze_insn - instruction analysis including validity and fixups. -+ * @mm: the probed address space. -+ * @arch_uprobe: the probepoint information. -+ * Return 0 on success or a -ve number on error. -+ */ -+int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm) -+{ -+ int ret; -+ struct insn insn; -+ -+ auprobe->fixups = 0; -+ ret = validate_insn_bits(auprobe, mm, &insn); -+ if (ret != 0) -+ return ret; -+ -+ handle_riprel_insn(auprobe, mm, &insn); -+ prepare_fixups(auprobe, &insn); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_X86_64 -+/* -+ * If we're emulating a rip-relative instruction, save the contents -+ * of the scratch register and store the target address in that register. -+ */ -+static void -+pre_xol_rip_insn(struct arch_uprobe *auprobe, struct pt_regs *regs, -+ struct arch_uprobe_task *autask) -+{ -+ if (auprobe->fixups & UPROBE_FIX_RIP_AX) { -+ autask->saved_scratch_register = regs->ax; -+ regs->ax = current->utask->vaddr; -+ regs->ax += auprobe->rip_rela_target_address; -+ } else if (auprobe->fixups & UPROBE_FIX_RIP_CX) { -+ autask->saved_scratch_register = regs->cx; -+ regs->cx = current->utask->vaddr; -+ regs->cx += auprobe->rip_rela_target_address; -+ } -+} -+#else -+static void -+pre_xol_rip_insn(struct arch_uprobe *auprobe, struct pt_regs *regs, -+ struct arch_uprobe_task *autask) -+{ -+ /* No RIP-relative addressing on 32-bit */ -+} -+#endif -+ -+/* -+ * arch_uprobe_pre_xol - prepare to execute out of line. -+ * @auprobe: the probepoint information. -+ * @regs: reflects the saved user state of current task. -+ */ -+int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) -+{ -+ struct arch_uprobe_task *autask; -+ -+ autask = ¤t->utask->autask; -+ autask->saved_trap_nr = current->thread.trap_nr; -+ current->thread.trap_nr = UPROBE_TRAP_NR; -+ regs->ip = current->utask->xol_vaddr; -+ pre_xol_rip_insn(auprobe, regs, autask); -+ -+ return 0; -+} -+ -+/* -+ * This function is called by arch_uprobe_post_xol() to adjust the return -+ * address pushed by a call instruction executed out of line. -+ */ -+static int adjust_ret_addr(unsigned long sp, long correction) -+{ -+ int rasize, ncopied; -+ long ra = 0; -+ -+ if (is_ia32_task()) -+ rasize = 4; -+ else -+ rasize = 8; -+ -+ ncopied = copy_from_user(&ra, (void __user *)sp, rasize); -+ if (unlikely(ncopied)) -+ return -EFAULT; -+ -+ ra += correction; -+ ncopied = copy_to_user((void __user *)sp, &ra, rasize); -+ if (unlikely(ncopied)) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+#ifdef CONFIG_X86_64 -+static bool is_riprel_insn(struct arch_uprobe *auprobe) -+{ -+ return ((auprobe->fixups & (UPROBE_FIX_RIP_AX | UPROBE_FIX_RIP_CX)) != 0); -+} -+ -+static void -+handle_riprel_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs, long *correction) -+{ -+ if (is_riprel_insn(auprobe)) { -+ struct arch_uprobe_task *autask; -+ -+ autask = ¤t->utask->autask; -+ if (auprobe->fixups & UPROBE_FIX_RIP_AX) -+ regs->ax = autask->saved_scratch_register; -+ else -+ regs->cx = autask->saved_scratch_register; -+ -+ /* -+ * The original instruction includes a displacement, and so -+ * is 4 bytes longer than what we've just single-stepped. -+ * Fall through to handle stuff like "jmpq *...(%rip)" and -+ * "callq *...(%rip)". -+ */ -+ if (correction) -+ *correction += 4; -+ } -+} -+#else -+static void -+handle_riprel_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs, long *correction) -+{ -+ /* No RIP-relative addressing on 32-bit */ -+} -+#endif -+ -+/* -+ * If xol insn itself traps and generates a signal(Say, -+ * SIGILL/SIGSEGV/etc), then detect the case where a singlestepped -+ * instruction jumps back to its own address. It is assumed that anything -+ * like do_page_fault/do_trap/etc sets thread.trap_nr != -1. -+ * -+ * arch_uprobe_pre_xol/arch_uprobe_post_xol save/restore thread.trap_nr, -+ * arch_uprobe_xol_was_trapped() simply checks that ->trap_nr is not equal to -+ * UPROBE_TRAP_NR == -1 set by arch_uprobe_pre_xol(). -+ */ -+bool arch_uprobe_xol_was_trapped(struct task_struct *t) -+{ -+ if (t->thread.trap_nr != UPROBE_TRAP_NR) -+ return true; -+ -+ return false; -+} -+ -+/* -+ * Called after single-stepping. To avoid the SMP problems that can -+ * occur when we temporarily put back the original opcode to -+ * single-step, we single-stepped a copy of the instruction. -+ * -+ * This function prepares to resume execution after the single-step. -+ * We have to fix things up as follows: -+ * -+ * Typically, the new ip is relative to the copied instruction. We need -+ * to make it relative to the original instruction (FIX_IP). Exceptions -+ * are return instructions and absolute or indirect jump or call instructions. -+ * -+ * If the single-stepped instruction was a call, the return address that -+ * is atop the stack is the address following the copied instruction. We -+ * need to make it the address following the original instruction (FIX_CALL). -+ * -+ * If the original instruction was a rip-relative instruction such as -+ * "movl %edx,0xnnnn(%rip)", we have instead executed an equivalent -+ * instruction using a scratch register -- e.g., "movl %edx,(%rax)". -+ * We need to restore the contents of the scratch register and adjust -+ * the ip, keeping in mind that the instruction we executed is 4 bytes -+ * shorter than the original instruction (since we squeezed out the offset -+ * field). (FIX_RIP_AX or FIX_RIP_CX) -+ */ -+int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) -+{ -+ struct uprobe_task *utask; -+ long correction; -+ int result = 0; -+ -+ WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR); -+ -+ utask = current->utask; -+ current->thread.trap_nr = utask->autask.saved_trap_nr; -+ correction = (long)(utask->vaddr - utask->xol_vaddr); -+ handle_riprel_post_xol(auprobe, regs, &correction); -+ if (auprobe->fixups & UPROBE_FIX_IP) -+ regs->ip += correction; -+ -+ if (auprobe->fixups & UPROBE_FIX_CALL) -+ result = adjust_ret_addr(regs->sp, correction); -+ -+ return result; -+} -+ -+/* callback routine for handling exceptions. */ -+int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data) -+{ -+ struct die_args *args = data; -+ struct pt_regs *regs = args->regs; -+ int ret = NOTIFY_DONE; -+ -+ /* We are only interested in userspace traps */ -+ if (regs && !user_mode_vm(regs)) -+ return NOTIFY_DONE; -+ -+ switch (val) { -+ case DIE_INT3: -+ if (uprobe_pre_sstep_notifier(regs)) -+ ret = NOTIFY_STOP; -+ -+ break; -+ -+ case DIE_DEBUG: -+ if (uprobe_post_sstep_notifier(regs)) -+ ret = NOTIFY_STOP; -+ -+ default: -+ break; -+ } -+ -+ return ret; -+} -+ -+/* -+ * This function gets called when XOL instruction either gets trapped or -+ * the thread has a fatal signal, so reset the instruction pointer to its -+ * probed address. -+ */ -+void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) -+{ -+ struct uprobe_task *utask = current->utask; -+ -+ current->thread.trap_nr = utask->autask.saved_trap_nr; -+ handle_riprel_post_xol(auprobe, regs, NULL); -+ instruction_pointer_set(regs, utask->vaddr); -+} -+ -+/* -+ * Skip these instructions as per the currently known x86 ISA. -+ * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 } -+ */ -+bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) -+{ -+ int i; -+ -+ for (i = 0; i < MAX_UINSN_BYTES; i++) { -+ if ((auprobe->insn[i] == 0x66)) -+ continue; -+ -+ if (auprobe->insn[i] == 0x90) -+ return true; -+ -+ if (i == (MAX_UINSN_BYTES - 1)) -+ break; -+ -+ if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x1f)) -+ return true; -+ -+ if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x19)) -+ return true; -+ -+ if ((auprobe->insn[i] == 0x87) && (auprobe->insn[i+1] == 0xc0)) -+ return true; -+ -+ break; -+ } -+ return false; -+} -diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h -index 3cc3062..26574c7 100644 ---- a/include/linux/mm_types.h -+++ b/include/linux/mm_types.h -@@ -12,6 +12,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -388,6 +389,7 @@ struct mm_struct { - #ifdef CONFIG_CPUMASK_OFFSTACK - struct cpumask cpumask_allocation; - #endif -+ struct uprobes_state uprobes_state; - }; - - static inline void mm_init_cpumask(struct mm_struct *mm) -diff --git a/include/linux/sched.h b/include/linux/sched.h -index 81a173c..cff94cd 100644 ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -1617,6 +1617,10 @@ struct task_struct { - #ifdef CONFIG_HAVE_HW_BREAKPOINT - atomic_t ptrace_bp_refcnt; - #endif -+#ifdef CONFIG_UPROBES -+ struct uprobe_task *utask; -+ int uprobe_srcu_id; -+#endif - }; - - /* Future-safe accessor for struct task_struct's cpus_allowed. */ -diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h -new file mode 100644 -index 0000000..efe4b33 ---- /dev/null -+++ b/include/linux/uprobes.h -@@ -0,0 +1,165 @@ -+#ifndef _LINUX_UPROBES_H -+#define _LINUX_UPROBES_H -+/* -+ * User-space Probes (UProbes) -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) IBM Corporation, 2008-2012 -+ * Authors: -+ * Srikar Dronamraju -+ * Jim Keniston -+ * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra -+ */ -+ -+#include -+#include -+ -+struct vm_area_struct; -+struct mm_struct; -+struct inode; -+ -+#ifdef CONFIG_ARCH_SUPPORTS_UPROBES -+# include -+#endif -+ -+/* flags that denote/change uprobes behaviour */ -+ -+/* Have a copy of original instruction */ -+#define UPROBE_COPY_INSN 0x1 -+ -+/* Dont run handlers when first register/ last unregister in progress*/ -+#define UPROBE_RUN_HANDLER 0x2 -+/* Can skip singlestep */ -+#define UPROBE_SKIP_SSTEP 0x4 -+ -+struct uprobe_consumer { -+ int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs); -+ /* -+ * filter is optional; If a filter exists, handler is run -+ * if and only if filter returns true. -+ */ -+ bool (*filter)(struct uprobe_consumer *self, struct task_struct *task); -+ -+ struct uprobe_consumer *next; -+}; -+ -+#ifdef CONFIG_UPROBES -+enum uprobe_task_state { -+ UTASK_RUNNING, -+ UTASK_BP_HIT, -+ UTASK_SSTEP, -+ UTASK_SSTEP_ACK, -+ UTASK_SSTEP_TRAPPED, -+}; -+ -+/* -+ * uprobe_task: Metadata of a task while it singlesteps. -+ */ -+struct uprobe_task { -+ enum uprobe_task_state state; -+ struct arch_uprobe_task autask; -+ -+ struct uprobe *active_uprobe; -+ -+ unsigned long xol_vaddr; -+ unsigned long vaddr; -+}; -+ -+/* -+ * On a breakpoint hit, thread contests for a slot. It frees the -+ * slot after singlestep. Currently a fixed number of slots are -+ * allocated. -+ */ -+struct xol_area { -+ wait_queue_head_t wq; /* if all slots are busy */ -+ atomic_t slot_count; /* number of in-use slots */ -+ unsigned long *bitmap; /* 0 = free slot */ -+ struct page *page; -+ -+ /* -+ * We keep the vma's vm_start rather than a pointer to the vma -+ * itself. The probed process or a naughty kernel module could make -+ * the vma go away, and we must handle that reasonably gracefully. -+ */ -+ unsigned long vaddr; /* Page(s) of instruction slots */ -+}; -+ -+struct uprobes_state { -+ struct xol_area *xol_area; -+ atomic_t count; -+}; -+extern int __weak set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); -+extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr, bool verify); -+extern bool __weak is_swbp_insn(uprobe_opcode_t *insn); -+extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); -+extern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); -+extern int uprobe_mmap(struct vm_area_struct *vma); -+extern void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end); -+extern void uprobe_free_utask(struct task_struct *t); -+extern void uprobe_copy_process(struct task_struct *t); -+extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs); -+extern int uprobe_post_sstep_notifier(struct pt_regs *regs); -+extern int uprobe_pre_sstep_notifier(struct pt_regs *regs); -+extern void uprobe_notify_resume(struct pt_regs *regs); -+extern bool uprobe_deny_signal(void); -+extern bool __weak arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs); -+extern void uprobe_clear_state(struct mm_struct *mm); -+extern void uprobe_reset_state(struct mm_struct *mm); -+#else /* !CONFIG_UPROBES */ -+struct uprobes_state { -+}; -+static inline int -+uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc) -+{ -+ return -ENOSYS; -+} -+static inline void -+uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc) -+{ -+} -+static inline int uprobe_mmap(struct vm_area_struct *vma) -+{ -+ return 0; -+} -+static inline void -+uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) -+{ -+} -+static inline void uprobe_notify_resume(struct pt_regs *regs) -+{ -+} -+static inline bool uprobe_deny_signal(void) -+{ -+ return false; -+} -+static inline unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) -+{ -+ return 0; -+} -+static inline void uprobe_free_utask(struct task_struct *t) -+{ -+} -+static inline void uprobe_copy_process(struct task_struct *t) -+{ -+} -+static inline void uprobe_clear_state(struct mm_struct *mm) -+{ -+} -+static inline void uprobe_reset_state(struct mm_struct *mm) -+{ -+} -+#endif /* !CONFIG_UPROBES */ -+#endif /* _LINUX_UPROBES_H */ -diff --git a/kernel/events/Makefile b/kernel/events/Makefile -index 22d901f..103f5d1 100644 ---- a/kernel/events/Makefile -+++ b/kernel/events/Makefile -@@ -3,4 +3,7 @@ CFLAGS_REMOVE_core.o = -pg - endif - - obj-y := core.o ring_buffer.o callchain.o -+ - obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o -+obj-$(CONFIG_UPROBES) += uprobes.o -+ -diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c -new file mode 100644 -index 0000000..985be4d ---- /dev/null -+++ b/kernel/events/uprobes.c -@@ -0,0 +1,1667 @@ -+/* -+ * User-space Probes (UProbes) -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * Copyright (C) IBM Corporation, 2008-2012 -+ * Authors: -+ * Srikar Dronamraju -+ * Jim Keniston -+ * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra -+ */ -+ -+#include -+#include -+#include /* read_mapping_page */ -+#include -+#include -+#include /* anon_vma_prepare */ -+#include /* set_pte_at_notify */ -+#include /* try_to_free_swap */ -+#include /* user_enable_single_step */ -+#include /* notifier mechanism */ -+ -+#include -+ -+#define UINSNS_PER_PAGE (PAGE_SIZE/UPROBE_XOL_SLOT_BYTES) -+#define MAX_UPROBE_XOL_SLOTS UINSNS_PER_PAGE -+ -+static struct srcu_struct uprobes_srcu; -+static struct rb_root uprobes_tree = RB_ROOT; -+ -+static DEFINE_SPINLOCK(uprobes_treelock); /* serialize rbtree access */ -+ -+#define UPROBES_HASH_SZ 13 -+ -+/* serialize (un)register */ -+static struct mutex uprobes_mutex[UPROBES_HASH_SZ]; -+ -+#define uprobes_hash(v) (&uprobes_mutex[((unsigned long)(v)) % UPROBES_HASH_SZ]) -+ -+/* serialize uprobe->pending_list */ -+static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ]; -+#define uprobes_mmap_hash(v) (&uprobes_mmap_mutex[((unsigned long)(v)) % UPROBES_HASH_SZ]) -+ -+/* -+ * uprobe_events allows us to skip the uprobe_mmap if there are no uprobe -+ * events active at this time. Probably a fine grained per inode count is -+ * better? -+ */ -+static atomic_t uprobe_events = ATOMIC_INIT(0); -+ -+/* -+ * Maintain a temporary per vma info that can be used to search if a vma -+ * has already been handled. This structure is introduced since extending -+ * vm_area_struct wasnt recommended. -+ */ -+struct vma_info { -+ struct list_head probe_list; -+ struct mm_struct *mm; -+ loff_t vaddr; -+}; -+ -+struct uprobe { -+ struct rb_node rb_node; /* node in the rb tree */ -+ atomic_t ref; -+ struct rw_semaphore consumer_rwsem; -+ struct list_head pending_list; -+ struct uprobe_consumer *consumers; -+ struct inode *inode; /* Also hold a ref to inode */ -+ loff_t offset; -+ int flags; -+ struct arch_uprobe arch; -+}; -+ -+/* -+ * valid_vma: Verify if the specified vma is an executable vma -+ * Relax restrictions while unregistering: vm_flags might have -+ * changed after breakpoint was inserted. -+ * - is_register: indicates if we are in register context. -+ * - Return 1 if the specified virtual address is in an -+ * executable vma. -+ */ -+static bool valid_vma(struct vm_area_struct *vma, bool is_register) -+{ -+ if (!vma->vm_file) -+ return false; -+ -+ if (!is_register) -+ return true; -+ -+ if ((vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) == (VM_READ|VM_EXEC)) -+ return true; -+ -+ return false; -+} -+ -+static loff_t vma_address(struct vm_area_struct *vma, loff_t offset) -+{ -+ loff_t vaddr; -+ -+ vaddr = vma->vm_start + offset; -+ vaddr -= vma->vm_pgoff << PAGE_SHIFT; -+ -+ return vaddr; -+} -+ -+/** -+ * __replace_page - replace page in vma by new page. -+ * based on replace_page in mm/ksm.c -+ * -+ * @vma: vma that holds the pte pointing to page -+ * @page: the cowed page we are replacing by kpage -+ * @kpage: the modified page we replace page by -+ * -+ * Returns 0 on success, -EFAULT on failure. -+ */ -+static int __replace_page(struct vm_area_struct *vma, struct page *page, struct page *kpage) -+{ -+ struct mm_struct *mm = vma->vm_mm; -+ pgd_t *pgd; -+ pud_t *pud; -+ pmd_t *pmd; -+ pte_t *ptep; -+ spinlock_t *ptl; -+ unsigned long addr; -+ int err = -EFAULT; -+ -+ addr = page_address_in_vma(page, vma); -+ if (addr == -EFAULT) -+ goto out; -+ -+ pgd = pgd_offset(mm, addr); -+ if (!pgd_present(*pgd)) -+ goto out; -+ -+ pud = pud_offset(pgd, addr); -+ if (!pud_present(*pud)) -+ goto out; -+ -+ pmd = pmd_offset(pud, addr); -+ if (!pmd_present(*pmd)) -+ goto out; -+ -+ ptep = pte_offset_map_lock(mm, pmd, addr, &ptl); -+ if (!ptep) -+ goto out; -+ -+ get_page(kpage); -+ page_add_new_anon_rmap(kpage, vma, addr); -+ -+ if (!PageAnon(page)) { -+ dec_mm_counter(mm, MM_FILEPAGES); -+ inc_mm_counter(mm, MM_ANONPAGES); -+ } -+ -+ flush_cache_page(vma, addr, pte_pfn(*ptep)); -+ ptep_clear_flush(vma, addr, ptep); -+ set_pte_at_notify(mm, addr, ptep, mk_pte(kpage, vma->vm_page_prot)); -+ -+ page_remove_rmap(page); -+ if (!page_mapped(page)) -+ try_to_free_swap(page); -+ put_page(page); -+ pte_unmap_unlock(ptep, ptl); -+ err = 0; -+ -+out: -+ return err; -+} -+ -+/** -+ * is_swbp_insn - check if instruction is breakpoint instruction. -+ * @insn: instruction to be checked. -+ * Default implementation of is_swbp_insn -+ * Returns true if @insn is a breakpoint instruction. -+ */ -+bool __weak is_swbp_insn(uprobe_opcode_t *insn) -+{ -+ return *insn == UPROBE_SWBP_INSN; -+} -+ -+/* -+ * NOTE: -+ * Expect the breakpoint instruction to be the smallest size instruction for -+ * the architecture. If an arch has variable length instruction and the -+ * breakpoint instruction is not of the smallest length instruction -+ * supported by that architecture then we need to modify read_opcode / -+ * write_opcode accordingly. This would never be a problem for archs that -+ * have fixed length instructions. -+ */ -+ -+/* -+ * write_opcode - write the opcode at a given virtual address. -+ * @auprobe: arch breakpointing information. -+ * @mm: the probed process address space. -+ * @vaddr: the virtual address to store the opcode. -+ * @opcode: opcode to be written at @vaddr. -+ * -+ * Called with mm->mmap_sem held (for read and with a reference to -+ * mm). -+ * -+ * For mm @mm, write the opcode at @vaddr. -+ * Return 0 (success) or a negative errno. -+ */ -+static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, -+ unsigned long vaddr, uprobe_opcode_t opcode) -+{ -+ struct page *old_page, *new_page; -+ struct address_space *mapping; -+ void *vaddr_old, *vaddr_new; -+ struct vm_area_struct *vma; -+ struct uprobe *uprobe; -+ loff_t addr; -+ int ret; -+ -+ /* Read the page with vaddr into memory */ -+ ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma); -+ if (ret <= 0) -+ return ret; -+ -+ ret = -EINVAL; -+ -+ /* -+ * We are interested in text pages only. Our pages of interest -+ * should be mapped for read and execute only. We desist from -+ * adding probes in write mapped pages since the breakpoints -+ * might end up in the file copy. -+ */ -+ if (!valid_vma(vma, is_swbp_insn(&opcode))) -+ goto put_out; -+ -+ uprobe = container_of(auprobe, struct uprobe, arch); -+ mapping = uprobe->inode->i_mapping; -+ if (mapping != vma->vm_file->f_mapping) -+ goto put_out; -+ -+ addr = vma_address(vma, uprobe->offset); -+ if (vaddr != (unsigned long)addr) -+ goto put_out; -+ -+ ret = -ENOMEM; -+ new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr); -+ if (!new_page) -+ goto put_out; -+ -+ __SetPageUptodate(new_page); -+ -+ /* -+ * lock page will serialize against do_wp_page()'s -+ * PageAnon() handling -+ */ -+ lock_page(old_page); -+ /* copy the page now that we've got it stable */ -+ vaddr_old = kmap_atomic(old_page); -+ vaddr_new = kmap_atomic(new_page); -+ -+ memcpy(vaddr_new, vaddr_old, PAGE_SIZE); -+ -+ /* poke the new insn in, ASSUMES we don't cross page boundary */ -+ vaddr &= ~PAGE_MASK; -+ BUG_ON(vaddr + UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); -+ memcpy(vaddr_new + vaddr, &opcode, UPROBE_SWBP_INSN_SIZE); -+ -+ kunmap_atomic(vaddr_new); -+ kunmap_atomic(vaddr_old); -+ -+ ret = anon_vma_prepare(vma); -+ if (ret) -+ goto unlock_out; -+ -+ lock_page(new_page); -+ ret = __replace_page(vma, old_page, new_page); -+ unlock_page(new_page); -+ -+unlock_out: -+ unlock_page(old_page); -+ page_cache_release(new_page); -+ -+put_out: -+ put_page(old_page); -+ -+ return ret; -+} -+ -+/** -+ * read_opcode - read the opcode at a given virtual address. -+ * @mm: the probed process address space. -+ * @vaddr: the virtual address to read the opcode. -+ * @opcode: location to store the read opcode. -+ * -+ * Called with mm->mmap_sem held (for read and with a reference to -+ * mm. -+ * -+ * For mm @mm, read the opcode at @vaddr and store it in @opcode. -+ * Return 0 (success) or a negative errno. -+ */ -+static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t *opcode) -+{ -+ struct page *page; -+ void *vaddr_new; -+ int ret; -+ -+ ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &page, NULL); -+ if (ret <= 0) -+ return ret; -+ -+ lock_page(page); -+ vaddr_new = kmap_atomic(page); -+ vaddr &= ~PAGE_MASK; -+ memcpy(opcode, vaddr_new + vaddr, UPROBE_SWBP_INSN_SIZE); -+ kunmap_atomic(vaddr_new); -+ unlock_page(page); -+ -+ put_page(page); -+ -+ return 0; -+} -+ -+static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) -+{ -+ uprobe_opcode_t opcode; -+ int result; -+ -+ result = read_opcode(mm, vaddr, &opcode); -+ if (result) -+ return result; -+ -+ if (is_swbp_insn(&opcode)) -+ return 1; -+ -+ return 0; -+} -+ -+/** -+ * set_swbp - store breakpoint at a given address. -+ * @auprobe: arch specific probepoint information. -+ * @mm: the probed process address space. -+ * @vaddr: the virtual address to insert the opcode. -+ * -+ * For mm @mm, store the breakpoint instruction at @vaddr. -+ * Return 0 (success) or a negative errno. -+ */ -+int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) -+{ -+ int result; -+ -+ result = is_swbp_at_addr(mm, vaddr); -+ if (result == 1) -+ return -EEXIST; -+ -+ if (result) -+ return result; -+ -+ return write_opcode(auprobe, mm, vaddr, UPROBE_SWBP_INSN); -+} -+ -+/** -+ * set_orig_insn - Restore the original instruction. -+ * @mm: the probed process address space. -+ * @auprobe: arch specific probepoint information. -+ * @vaddr: the virtual address to insert the opcode. -+ * @verify: if true, verify existance of breakpoint instruction. -+ * -+ * For mm @mm, restore the original opcode (opcode) at @vaddr. -+ * Return 0 (success) or a negative errno. -+ */ -+int __weak -+set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr, bool verify) -+{ -+ if (verify) { -+ int result; -+ -+ result = is_swbp_at_addr(mm, vaddr); -+ if (!result) -+ return -EINVAL; -+ -+ if (result != 1) -+ return result; -+ } -+ return write_opcode(auprobe, mm, vaddr, *(uprobe_opcode_t *)auprobe->insn); -+} -+ -+static int match_uprobe(struct uprobe *l, struct uprobe *r) -+{ -+ if (l->inode < r->inode) -+ return -1; -+ -+ if (l->inode > r->inode) -+ return 1; -+ -+ if (l->offset < r->offset) -+ return -1; -+ -+ if (l->offset > r->offset) -+ return 1; -+ -+ return 0; -+} -+ -+static struct uprobe *__find_uprobe(struct inode *inode, loff_t offset) -+{ -+ struct uprobe u = { .inode = inode, .offset = offset }; -+ struct rb_node *n = uprobes_tree.rb_node; -+ struct uprobe *uprobe; -+ int match; -+ -+ while (n) { -+ uprobe = rb_entry(n, struct uprobe, rb_node); -+ match = match_uprobe(&u, uprobe); -+ if (!match) { -+ atomic_inc(&uprobe->ref); -+ return uprobe; -+ } -+ -+ if (match < 0) -+ n = n->rb_left; -+ else -+ n = n->rb_right; -+ } -+ return NULL; -+} -+ -+/* -+ * Find a uprobe corresponding to a given inode:offset -+ * Acquires uprobes_treelock -+ */ -+static struct uprobe *find_uprobe(struct inode *inode, loff_t offset) -+{ -+ struct uprobe *uprobe; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&uprobes_treelock, flags); -+ uprobe = __find_uprobe(inode, offset); -+ spin_unlock_irqrestore(&uprobes_treelock, flags); -+ -+ return uprobe; -+} -+ -+static struct uprobe *__insert_uprobe(struct uprobe *uprobe) -+{ -+ struct rb_node **p = &uprobes_tree.rb_node; -+ struct rb_node *parent = NULL; -+ struct uprobe *u; -+ int match; -+ -+ while (*p) { -+ parent = *p; -+ u = rb_entry(parent, struct uprobe, rb_node); -+ match = match_uprobe(uprobe, u); -+ if (!match) { -+ atomic_inc(&u->ref); -+ return u; -+ } -+ -+ if (match < 0) -+ p = &parent->rb_left; -+ else -+ p = &parent->rb_right; -+ -+ } -+ -+ u = NULL; -+ rb_link_node(&uprobe->rb_node, parent, p); -+ rb_insert_color(&uprobe->rb_node, &uprobes_tree); -+ /* get access + creation ref */ -+ atomic_set(&uprobe->ref, 2); -+ -+ return u; -+} -+ -+/* -+ * Acquire uprobes_treelock. -+ * Matching uprobe already exists in rbtree; -+ * increment (access refcount) and return the matching uprobe. -+ * -+ * No matching uprobe; insert the uprobe in rb_tree; -+ * get a double refcount (access + creation) and return NULL. -+ */ -+static struct uprobe *insert_uprobe(struct uprobe *uprobe) -+{ -+ unsigned long flags; -+ struct uprobe *u; -+ -+ spin_lock_irqsave(&uprobes_treelock, flags); -+ u = __insert_uprobe(uprobe); -+ spin_unlock_irqrestore(&uprobes_treelock, flags); -+ -+ /* For now assume that the instruction need not be single-stepped */ -+ uprobe->flags |= UPROBE_SKIP_SSTEP; -+ -+ return u; -+} -+ -+static void put_uprobe(struct uprobe *uprobe) -+{ -+ if (atomic_dec_and_test(&uprobe->ref)) -+ kfree(uprobe); -+} -+ -+static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset) -+{ -+ struct uprobe *uprobe, *cur_uprobe; -+ -+ uprobe = kzalloc(sizeof(struct uprobe), GFP_KERNEL); -+ if (!uprobe) -+ return NULL; -+ -+ uprobe->inode = igrab(inode); -+ uprobe->offset = offset; -+ init_rwsem(&uprobe->consumer_rwsem); -+ INIT_LIST_HEAD(&uprobe->pending_list); -+ -+ /* add to uprobes_tree, sorted on inode:offset */ -+ cur_uprobe = insert_uprobe(uprobe); -+ -+ /* a uprobe exists for this inode:offset combination */ -+ if (cur_uprobe) { -+ kfree(uprobe); -+ uprobe = cur_uprobe; -+ iput(inode); -+ } else { -+ atomic_inc(&uprobe_events); -+ } -+ -+ return uprobe; -+} -+ -+static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs) -+{ -+ struct uprobe_consumer *uc; -+ -+ if (!(uprobe->flags & UPROBE_RUN_HANDLER)) -+ return; -+ -+ down_read(&uprobe->consumer_rwsem); -+ for (uc = uprobe->consumers; uc; uc = uc->next) { -+ if (!uc->filter || uc->filter(uc, current)) -+ uc->handler(uc, regs); -+ } -+ up_read(&uprobe->consumer_rwsem); -+} -+ -+/* Returns the previous consumer */ -+static struct uprobe_consumer * -+consumer_add(struct uprobe *uprobe, struct uprobe_consumer *uc) -+{ -+ down_write(&uprobe->consumer_rwsem); -+ uc->next = uprobe->consumers; -+ uprobe->consumers = uc; -+ up_write(&uprobe->consumer_rwsem); -+ -+ return uc->next; -+} -+ -+/* -+ * For uprobe @uprobe, delete the consumer @uc. -+ * Return true if the @uc is deleted successfully -+ * or return false. -+ */ -+static bool consumer_del(struct uprobe *uprobe, struct uprobe_consumer *uc) -+{ -+ struct uprobe_consumer **con; -+ bool ret = false; -+ -+ down_write(&uprobe->consumer_rwsem); -+ for (con = &uprobe->consumers; *con; con = &(*con)->next) { -+ if (*con == uc) { -+ *con = uc->next; -+ ret = true; -+ break; -+ } -+ } -+ up_write(&uprobe->consumer_rwsem); -+ -+ return ret; -+} -+ -+static int -+__copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *insn, -+ unsigned long nbytes, unsigned long offset) -+{ -+ struct file *filp = vma->vm_file; -+ struct page *page; -+ void *vaddr; -+ unsigned long off1; -+ unsigned long idx; -+ -+ if (!filp) -+ return -EINVAL; -+ -+ idx = (unsigned long)(offset >> PAGE_CACHE_SHIFT); -+ off1 = offset &= ~PAGE_MASK; -+ -+ /* -+ * Ensure that the page that has the original instruction is -+ * populated and in page-cache. -+ */ -+ page = read_mapping_page(mapping, idx, filp); -+ if (IS_ERR(page)) -+ return PTR_ERR(page); -+ -+ vaddr = kmap_atomic(page); -+ memcpy(insn, vaddr + off1, nbytes); -+ kunmap_atomic(vaddr); -+ page_cache_release(page); -+ -+ return 0; -+} -+ -+static int -+copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr) -+{ -+ struct address_space *mapping; -+ unsigned long nbytes; -+ int bytes; -+ -+ addr &= ~PAGE_MASK; -+ nbytes = PAGE_SIZE - addr; -+ mapping = uprobe->inode->i_mapping; -+ -+ /* Instruction at end of binary; copy only available bytes */ -+ if (uprobe->offset + MAX_UINSN_BYTES > uprobe->inode->i_size) -+ bytes = uprobe->inode->i_size - uprobe->offset; -+ else -+ bytes = MAX_UINSN_BYTES; -+ -+ /* Instruction at the page-boundary; copy bytes in second page */ -+ if (nbytes < bytes) { -+ if (__copy_insn(mapping, vma, uprobe->arch.insn + nbytes, -+ bytes - nbytes, uprobe->offset + nbytes)) -+ return -ENOMEM; -+ -+ bytes = nbytes; -+ } -+ return __copy_insn(mapping, vma, uprobe->arch.insn, bytes, uprobe->offset); -+} -+ -+/* -+ * How mm->uprobes_state.count gets updated -+ * uprobe_mmap() increments the count if -+ * - it successfully adds a breakpoint. -+ * - it cannot add a breakpoint, but sees that there is a underlying -+ * breakpoint (via a is_swbp_at_addr()). -+ * -+ * uprobe_munmap() decrements the count if -+ * - it sees a underlying breakpoint, (via is_swbp_at_addr) -+ * (Subsequent uprobe_unregister wouldnt find the breakpoint -+ * unless a uprobe_mmap kicks in, since the old vma would be -+ * dropped just after uprobe_munmap.) -+ * -+ * uprobe_register increments the count if: -+ * - it successfully adds a breakpoint. -+ * -+ * uprobe_unregister decrements the count if: -+ * - it sees a underlying breakpoint and removes successfully. -+ * (via is_swbp_at_addr) -+ * (Subsequent uprobe_munmap wouldnt find the breakpoint -+ * since there is no underlying breakpoint after the -+ * breakpoint removal.) -+ */ -+static int -+install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, -+ struct vm_area_struct *vma, loff_t vaddr) -+{ -+ unsigned long addr; -+ int ret; -+ -+ /* -+ * If probe is being deleted, unregister thread could be done with -+ * the vma-rmap-walk through. Adding a probe now can be fatal since -+ * nobody will be able to cleanup. Also we could be from fork or -+ * mremap path, where the probe might have already been inserted. -+ * Hence behave as if probe already existed. -+ */ -+ if (!uprobe->consumers) -+ return -EEXIST; -+ -+ addr = (unsigned long)vaddr; -+ -+ if (!(uprobe->flags & UPROBE_COPY_INSN)) { -+ ret = copy_insn(uprobe, vma, addr); -+ if (ret) -+ return ret; -+ -+ if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) -+ return -EEXIST; -+ -+ ret = arch_uprobe_analyze_insn(&uprobe->arch, mm); -+ if (ret) -+ return ret; -+ -+ uprobe->flags |= UPROBE_COPY_INSN; -+ } -+ -+ /* -+ * Ideally, should be updating the probe count after the breakpoint -+ * has been successfully inserted. However a thread could hit the -+ * breakpoint we just inserted even before the probe count is -+ * incremented. If this is the first breakpoint placed, breakpoint -+ * notifier might ignore uprobes and pass the trap to the thread. -+ * Hence increment before and decrement on failure. -+ */ -+ atomic_inc(&mm->uprobes_state.count); -+ ret = set_swbp(&uprobe->arch, mm, addr); -+ if (ret) -+ atomic_dec(&mm->uprobes_state.count); -+ -+ return ret; -+} -+ -+static void -+remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, loff_t vaddr) -+{ -+ if (!set_orig_insn(&uprobe->arch, mm, (unsigned long)vaddr, true)) -+ atomic_dec(&mm->uprobes_state.count); -+} -+ -+/* -+ * There could be threads that have hit the breakpoint and are entering the -+ * notifier code and trying to acquire the uprobes_treelock. The thread -+ * calling delete_uprobe() that is removing the uprobe from the rb_tree can -+ * race with these threads and might acquire the uprobes_treelock compared -+ * to some of the breakpoint hit threads. In such a case, the breakpoint -+ * hit threads will not find the uprobe. The current unregistering thread -+ * waits till all other threads have hit a breakpoint, to acquire the -+ * uprobes_treelock before the uprobe is removed from the rbtree. -+ */ -+static void delete_uprobe(struct uprobe *uprobe) -+{ -+ unsigned long flags; -+ -+ synchronize_srcu(&uprobes_srcu); -+ spin_lock_irqsave(&uprobes_treelock, flags); -+ rb_erase(&uprobe->rb_node, &uprobes_tree); -+ spin_unlock_irqrestore(&uprobes_treelock, flags); -+ iput(uprobe->inode); -+ put_uprobe(uprobe); -+ atomic_dec(&uprobe_events); -+} -+ -+static struct vma_info * -+__find_next_vma_info(struct address_space *mapping, struct list_head *head, -+ struct vma_info *vi, loff_t offset, bool is_register) -+{ -+ struct prio_tree_iter iter; -+ struct vm_area_struct *vma; -+ struct vma_info *tmpvi; -+ unsigned long pgoff; -+ int existing_vma; -+ loff_t vaddr; -+ -+ pgoff = offset >> PAGE_SHIFT; -+ -+ vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { -+ if (!valid_vma(vma, is_register)) -+ continue; -+ -+ existing_vma = 0; -+ vaddr = vma_address(vma, offset); -+ -+ list_for_each_entry(tmpvi, head, probe_list) { -+ if (tmpvi->mm == vma->vm_mm && tmpvi->vaddr == vaddr) { -+ existing_vma = 1; -+ break; -+ } -+ } -+ -+ /* -+ * Another vma needs a probe to be installed. However skip -+ * installing the probe if the vma is about to be unlinked. -+ */ -+ if (!existing_vma && atomic_inc_not_zero(&vma->vm_mm->mm_users)) { -+ vi->mm = vma->vm_mm; -+ vi->vaddr = vaddr; -+ list_add(&vi->probe_list, head); -+ -+ return vi; -+ } -+ } -+ -+ return NULL; -+} -+ -+/* -+ * Iterate in the rmap prio tree and find a vma where a probe has not -+ * yet been inserted. -+ */ -+static struct vma_info * -+find_next_vma_info(struct address_space *mapping, struct list_head *head, -+ loff_t offset, bool is_register) -+{ -+ struct vma_info *vi, *retvi; -+ -+ vi = kzalloc(sizeof(struct vma_info), GFP_KERNEL); -+ if (!vi) -+ return ERR_PTR(-ENOMEM); -+ -+ mutex_lock(&mapping->i_mmap_mutex); -+ retvi = __find_next_vma_info(mapping, head, vi, offset, is_register); -+ mutex_unlock(&mapping->i_mmap_mutex); -+ -+ if (!retvi) -+ kfree(vi); -+ -+ return retvi; -+} -+ -+static int register_for_each_vma(struct uprobe *uprobe, bool is_register) -+{ -+ struct list_head try_list; -+ struct vm_area_struct *vma; -+ struct address_space *mapping; -+ struct vma_info *vi, *tmpvi; -+ struct mm_struct *mm; -+ loff_t vaddr; -+ int ret; -+ -+ mapping = uprobe->inode->i_mapping; -+ INIT_LIST_HEAD(&try_list); -+ -+ ret = 0; -+ -+ for (;;) { -+ vi = find_next_vma_info(mapping, &try_list, uprobe->offset, is_register); -+ if (!vi) -+ break; -+ -+ if (IS_ERR(vi)) { -+ ret = PTR_ERR(vi); -+ break; -+ } -+ -+ mm = vi->mm; -+ down_read(&mm->mmap_sem); -+ vma = find_vma(mm, (unsigned long)vi->vaddr); -+ if (!vma || !valid_vma(vma, is_register)) { -+ list_del(&vi->probe_list); -+ kfree(vi); -+ up_read(&mm->mmap_sem); -+ mmput(mm); -+ continue; -+ } -+ vaddr = vma_address(vma, uprobe->offset); -+ if (vma->vm_file->f_mapping->host != uprobe->inode || -+ vaddr != vi->vaddr) { -+ list_del(&vi->probe_list); -+ kfree(vi); -+ up_read(&mm->mmap_sem); -+ mmput(mm); -+ continue; -+ } -+ -+ if (is_register) -+ ret = install_breakpoint(uprobe, mm, vma, vi->vaddr); -+ else -+ remove_breakpoint(uprobe, mm, vi->vaddr); -+ -+ up_read(&mm->mmap_sem); -+ mmput(mm); -+ if (is_register) { -+ if (ret && ret == -EEXIST) -+ ret = 0; -+ if (ret) -+ break; -+ } -+ } -+ -+ list_for_each_entry_safe(vi, tmpvi, &try_list, probe_list) { -+ list_del(&vi->probe_list); -+ kfree(vi); -+ } -+ -+ return ret; -+} -+ -+static int __uprobe_register(struct uprobe *uprobe) -+{ -+ return register_for_each_vma(uprobe, true); -+} -+ -+static void __uprobe_unregister(struct uprobe *uprobe) -+{ -+ if (!register_for_each_vma(uprobe, false)) -+ delete_uprobe(uprobe); -+ -+ /* TODO : cant unregister? schedule a worker thread */ -+} -+ -+/* -+ * uprobe_register - register a probe -+ * @inode: the file in which the probe has to be placed. -+ * @offset: offset from the start of the file. -+ * @uc: information on howto handle the probe.. -+ * -+ * Apart from the access refcount, uprobe_register() takes a creation -+ * refcount (thro alloc_uprobe) if and only if this @uprobe is getting -+ * inserted into the rbtree (i.e first consumer for a @inode:@offset -+ * tuple). Creation refcount stops uprobe_unregister from freeing the -+ * @uprobe even before the register operation is complete. Creation -+ * refcount is released when the last @uc for the @uprobe -+ * unregisters. -+ * -+ * Return errno if it cannot successully install probes -+ * else return 0 (success) -+ */ -+int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc) -+{ -+ struct uprobe *uprobe; -+ int ret; -+ -+ if (!inode || !uc || uc->next) -+ return -EINVAL; -+ -+ if (offset > i_size_read(inode)) -+ return -EINVAL; -+ -+ ret = 0; -+ mutex_lock(uprobes_hash(inode)); -+ uprobe = alloc_uprobe(inode, offset); -+ -+ if (uprobe && !consumer_add(uprobe, uc)) { -+ ret = __uprobe_register(uprobe); -+ if (ret) { -+ uprobe->consumers = NULL; -+ __uprobe_unregister(uprobe); -+ } else { -+ uprobe->flags |= UPROBE_RUN_HANDLER; -+ } -+ } -+ -+ mutex_unlock(uprobes_hash(inode)); -+ put_uprobe(uprobe); -+ -+ return ret; -+} -+ -+/* -+ * uprobe_unregister - unregister a already registered probe. -+ * @inode: the file in which the probe has to be removed. -+ * @offset: offset from the start of the file. -+ * @uc: identify which probe if multiple probes are colocated. -+ */ -+void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc) -+{ -+ struct uprobe *uprobe; -+ -+ if (!inode || !uc) -+ return; -+ -+ uprobe = find_uprobe(inode, offset); -+ if (!uprobe) -+ return; -+ -+ mutex_lock(uprobes_hash(inode)); -+ -+ if (consumer_del(uprobe, uc)) { -+ if (!uprobe->consumers) { -+ __uprobe_unregister(uprobe); -+ uprobe->flags &= ~UPROBE_RUN_HANDLER; -+ } -+ } -+ -+ mutex_unlock(uprobes_hash(inode)); -+ if (uprobe) -+ put_uprobe(uprobe); -+} -+ -+/* -+ * Of all the nodes that correspond to the given inode, return the node -+ * with the least offset. -+ */ -+static struct rb_node *find_least_offset_node(struct inode *inode) -+{ -+ struct uprobe u = { .inode = inode, .offset = 0}; -+ struct rb_node *n = uprobes_tree.rb_node; -+ struct rb_node *close_node = NULL; -+ struct uprobe *uprobe; -+ int match; -+ -+ while (n) { -+ uprobe = rb_entry(n, struct uprobe, rb_node); -+ match = match_uprobe(&u, uprobe); -+ -+ if (uprobe->inode == inode) -+ close_node = n; -+ -+ if (!match) -+ return close_node; -+ -+ if (match < 0) -+ n = n->rb_left; -+ else -+ n = n->rb_right; -+ } -+ -+ return close_node; -+} -+ -+/* -+ * For a given inode, build a list of probes that need to be inserted. -+ */ -+static void build_probe_list(struct inode *inode, struct list_head *head) -+{ -+ struct uprobe *uprobe; -+ unsigned long flags; -+ struct rb_node *n; -+ -+ spin_lock_irqsave(&uprobes_treelock, flags); -+ -+ n = find_least_offset_node(inode); -+ -+ for (; n; n = rb_next(n)) { -+ uprobe = rb_entry(n, struct uprobe, rb_node); -+ if (uprobe->inode != inode) -+ break; -+ -+ list_add(&uprobe->pending_list, head); -+ atomic_inc(&uprobe->ref); -+ } -+ -+ spin_unlock_irqrestore(&uprobes_treelock, flags); -+} -+ -+/* -+ * Called from mmap_region. -+ * called with mm->mmap_sem acquired. -+ * -+ * Return -ve no if we fail to insert probes and we cannot -+ * bail-out. -+ * Return 0 otherwise. i.e: -+ * -+ * - successful insertion of probes -+ * - (or) no possible probes to be inserted. -+ * - (or) insertion of probes failed but we can bail-out. -+ */ -+int uprobe_mmap(struct vm_area_struct *vma) -+{ -+ struct list_head tmp_list; -+ struct uprobe *uprobe, *u; -+ struct inode *inode; -+ int ret, count; -+ -+ if (!atomic_read(&uprobe_events) || !valid_vma(vma, true)) -+ return 0; -+ -+ inode = vma->vm_file->f_mapping->host; -+ if (!inode) -+ return 0; -+ -+ INIT_LIST_HEAD(&tmp_list); -+ mutex_lock(uprobes_mmap_hash(inode)); -+ build_probe_list(inode, &tmp_list); -+ -+ ret = 0; -+ count = 0; -+ -+ list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { -+ loff_t vaddr; -+ -+ list_del(&uprobe->pending_list); -+ if (!ret) { -+ vaddr = vma_address(vma, uprobe->offset); -+ -+ if (vaddr < vma->vm_start || vaddr >= vma->vm_end) { -+ put_uprobe(uprobe); -+ continue; -+ } -+ -+ ret = install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); -+ -+ /* Ignore double add: */ -+ if (ret == -EEXIST) { -+ ret = 0; -+ -+ if (!is_swbp_at_addr(vma->vm_mm, vaddr)) -+ continue; -+ -+ /* -+ * Unable to insert a breakpoint, but -+ * breakpoint lies underneath. Increment the -+ * probe count. -+ */ -+ atomic_inc(&vma->vm_mm->uprobes_state.count); -+ } -+ -+ if (!ret) -+ count++; -+ } -+ put_uprobe(uprobe); -+ } -+ -+ mutex_unlock(uprobes_mmap_hash(inode)); -+ -+ if (ret) -+ atomic_sub(count, &vma->vm_mm->uprobes_state.count); -+ -+ return ret; -+} -+ -+/* -+ * Called in context of a munmap of a vma. -+ */ -+void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) -+{ -+ struct list_head tmp_list; -+ struct uprobe *uprobe, *u; -+ struct inode *inode; -+ -+ if (!atomic_read(&uprobe_events) || !valid_vma(vma, false)) -+ return; -+ -+ if (!atomic_read(&vma->vm_mm->uprobes_state.count)) -+ return; -+ -+ inode = vma->vm_file->f_mapping->host; -+ if (!inode) -+ return; -+ -+ INIT_LIST_HEAD(&tmp_list); -+ mutex_lock(uprobes_mmap_hash(inode)); -+ build_probe_list(inode, &tmp_list); -+ -+ list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { -+ loff_t vaddr; -+ -+ list_del(&uprobe->pending_list); -+ vaddr = vma_address(vma, uprobe->offset); -+ -+ if (vaddr >= start && vaddr < end) { -+ /* -+ * An unregister could have removed the probe before -+ * unmap. So check before we decrement the count. -+ */ -+ if (is_swbp_at_addr(vma->vm_mm, vaddr) == 1) -+ atomic_dec(&vma->vm_mm->uprobes_state.count); -+ } -+ put_uprobe(uprobe); -+ } -+ mutex_unlock(uprobes_mmap_hash(inode)); -+} -+ -+/* Slot allocation for XOL */ -+static int xol_add_vma(struct xol_area *area) -+{ -+ struct mm_struct *mm; -+ int ret; -+ -+ area->page = alloc_page(GFP_HIGHUSER); -+ if (!area->page) -+ return -ENOMEM; -+ -+ ret = -EALREADY; -+ mm = current->mm; -+ -+ down_write(&mm->mmap_sem); -+ if (mm->uprobes_state.xol_area) -+ goto fail; -+ -+ ret = -ENOMEM; -+ -+ /* Try to map as high as possible, this is only a hint. */ -+ area->vaddr = get_unmapped_area(NULL, TASK_SIZE - PAGE_SIZE, PAGE_SIZE, 0, 0); -+ if (area->vaddr & ~PAGE_MASK) { -+ ret = area->vaddr; -+ goto fail; -+ } -+ -+ ret = install_special_mapping(mm, area->vaddr, PAGE_SIZE, -+ VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|VM_IO, &area->page); -+ if (ret) -+ goto fail; -+ -+ smp_wmb(); /* pairs with get_xol_area() */ -+ mm->uprobes_state.xol_area = area; -+ ret = 0; -+ -+fail: -+ up_write(&mm->mmap_sem); -+ if (ret) -+ __free_page(area->page); -+ -+ return ret; -+} -+ -+static struct xol_area *get_xol_area(struct mm_struct *mm) -+{ -+ struct xol_area *area; -+ -+ area = mm->uprobes_state.xol_area; -+ smp_read_barrier_depends(); /* pairs with wmb in xol_add_vma() */ -+ -+ return area; -+} -+ -+/* -+ * xol_alloc_area - Allocate process's xol_area. -+ * This area will be used for storing instructions for execution out of -+ * line. -+ * -+ * Returns the allocated area or NULL. -+ */ -+static struct xol_area *xol_alloc_area(void) -+{ -+ struct xol_area *area; -+ -+ area = kzalloc(sizeof(*area), GFP_KERNEL); -+ if (unlikely(!area)) -+ return NULL; -+ -+ area->bitmap = kzalloc(BITS_TO_LONGS(UINSNS_PER_PAGE) * sizeof(long), GFP_KERNEL); -+ -+ if (!area->bitmap) -+ goto fail; -+ -+ init_waitqueue_head(&area->wq); -+ if (!xol_add_vma(area)) -+ return area; -+ -+fail: -+ kfree(area->bitmap); -+ kfree(area); -+ -+ return get_xol_area(current->mm); -+} -+ -+/* -+ * uprobe_clear_state - Free the area allocated for slots. -+ */ -+void uprobe_clear_state(struct mm_struct *mm) -+{ -+ struct xol_area *area = mm->uprobes_state.xol_area; -+ -+ if (!area) -+ return; -+ -+ put_page(area->page); -+ kfree(area->bitmap); -+ kfree(area); -+} -+ -+/* -+ * uprobe_reset_state - Free the area allocated for slots. -+ */ -+void uprobe_reset_state(struct mm_struct *mm) -+{ -+ mm->uprobes_state.xol_area = NULL; -+ atomic_set(&mm->uprobes_state.count, 0); -+} -+ -+/* -+ * - search for a free slot. -+ */ -+static unsigned long xol_take_insn_slot(struct xol_area *area) -+{ -+ unsigned long slot_addr; -+ int slot_nr; -+ -+ do { -+ slot_nr = find_first_zero_bit(area->bitmap, UINSNS_PER_PAGE); -+ if (slot_nr < UINSNS_PER_PAGE) { -+ if (!test_and_set_bit(slot_nr, area->bitmap)) -+ break; -+ -+ slot_nr = UINSNS_PER_PAGE; -+ continue; -+ } -+ wait_event(area->wq, (atomic_read(&area->slot_count) < UINSNS_PER_PAGE)); -+ } while (slot_nr >= UINSNS_PER_PAGE); -+ -+ slot_addr = area->vaddr + (slot_nr * UPROBE_XOL_SLOT_BYTES); -+ atomic_inc(&area->slot_count); -+ -+ return slot_addr; -+} -+ -+/* -+ * xol_get_insn_slot - If was not allocated a slot, then -+ * allocate a slot. -+ * Returns the allocated slot address or 0. -+ */ -+static unsigned long xol_get_insn_slot(struct uprobe *uprobe, unsigned long slot_addr) -+{ -+ struct xol_area *area; -+ unsigned long offset; -+ void *vaddr; -+ -+ area = get_xol_area(current->mm); -+ if (!area) { -+ area = xol_alloc_area(); -+ if (!area) -+ return 0; -+ } -+ current->utask->xol_vaddr = xol_take_insn_slot(area); -+ -+ /* -+ * Initialize the slot if xol_vaddr points to valid -+ * instruction slot. -+ */ -+ if (unlikely(!current->utask->xol_vaddr)) -+ return 0; -+ -+ current->utask->vaddr = slot_addr; -+ offset = current->utask->xol_vaddr & ~PAGE_MASK; -+ vaddr = kmap_atomic(area->page); -+ memcpy(vaddr + offset, uprobe->arch.insn, MAX_UINSN_BYTES); -+ kunmap_atomic(vaddr); -+ -+ return current->utask->xol_vaddr; -+} -+ -+/* -+ * xol_free_insn_slot - If slot was earlier allocated by -+ * @xol_get_insn_slot(), make the slot available for -+ * subsequent requests. -+ */ -+static void xol_free_insn_slot(struct task_struct *tsk) -+{ -+ struct xol_area *area; -+ unsigned long vma_end; -+ unsigned long slot_addr; -+ -+ if (!tsk->mm || !tsk->mm->uprobes_state.xol_area || !tsk->utask) -+ return; -+ -+ slot_addr = tsk->utask->xol_vaddr; -+ -+ if (unlikely(!slot_addr || IS_ERR_VALUE(slot_addr))) -+ return; -+ -+ area = tsk->mm->uprobes_state.xol_area; -+ vma_end = area->vaddr + PAGE_SIZE; -+ if (area->vaddr <= slot_addr && slot_addr < vma_end) { -+ unsigned long offset; -+ int slot_nr; -+ -+ offset = slot_addr - area->vaddr; -+ slot_nr = offset / UPROBE_XOL_SLOT_BYTES; -+ if (slot_nr >= UINSNS_PER_PAGE) -+ return; -+ -+ clear_bit(slot_nr, area->bitmap); -+ atomic_dec(&area->slot_count); -+ if (waitqueue_active(&area->wq)) -+ wake_up(&area->wq); -+ -+ tsk->utask->xol_vaddr = 0; -+ } -+} -+ -+/** -+ * uprobe_get_swbp_addr - compute address of swbp given post-swbp regs -+ * @regs: Reflects the saved state of the task after it has hit a breakpoint -+ * instruction. -+ * Return the address of the breakpoint instruction. -+ */ -+unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs) -+{ -+ return instruction_pointer(regs) - UPROBE_SWBP_INSN_SIZE; -+} -+ -+/* -+ * Called with no locks held. -+ * Called in context of a exiting or a exec-ing thread. -+ */ -+void uprobe_free_utask(struct task_struct *t) -+{ -+ struct uprobe_task *utask = t->utask; -+ -+ if (t->uprobe_srcu_id != -1) -+ srcu_read_unlock_raw(&uprobes_srcu, t->uprobe_srcu_id); -+ -+ if (!utask) -+ return; -+ -+ if (utask->active_uprobe) -+ put_uprobe(utask->active_uprobe); -+ -+ xol_free_insn_slot(t); -+ kfree(utask); -+ t->utask = NULL; -+} -+ -+/* -+ * Called in context of a new clone/fork from copy_process. -+ */ -+void uprobe_copy_process(struct task_struct *t) -+{ -+ t->utask = NULL; -+ t->uprobe_srcu_id = -1; -+} -+ -+/* -+ * Allocate a uprobe_task object for the task. -+ * Called when the thread hits a breakpoint for the first time. -+ * -+ * Returns: -+ * - pointer to new uprobe_task on success -+ * - NULL otherwise -+ */ -+static struct uprobe_task *add_utask(void) -+{ -+ struct uprobe_task *utask; -+ -+ utask = kzalloc(sizeof *utask, GFP_KERNEL); -+ if (unlikely(!utask)) -+ return NULL; -+ -+ utask->active_uprobe = NULL; -+ current->utask = utask; -+ return utask; -+} -+ -+/* Prepare to single-step probed instruction out of line. */ -+static int -+pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long vaddr) -+{ -+ if (xol_get_insn_slot(uprobe, vaddr) && !arch_uprobe_pre_xol(&uprobe->arch, regs)) -+ return 0; -+ -+ return -EFAULT; -+} -+ -+/* -+ * If we are singlestepping, then ensure this thread is not connected to -+ * non-fatal signals until completion of singlestep. When xol insn itself -+ * triggers the signal, restart the original insn even if the task is -+ * already SIGKILL'ed (since coredump should report the correct ip). This -+ * is even more important if the task has a handler for SIGSEGV/etc, The -+ * _same_ instruction should be repeated again after return from the signal -+ * handler, and SSTEP can never finish in this case. -+ */ -+bool uprobe_deny_signal(void) -+{ -+ struct task_struct *t = current; -+ struct uprobe_task *utask = t->utask; -+ -+ if (likely(!utask || !utask->active_uprobe)) -+ return false; -+ -+ WARN_ON_ONCE(utask->state != UTASK_SSTEP); -+ -+ if (signal_pending(t)) { -+ spin_lock_irq(&t->sighand->siglock); -+ clear_tsk_thread_flag(t, TIF_SIGPENDING); -+ spin_unlock_irq(&t->sighand->siglock); -+ -+ if (__fatal_signal_pending(t) || arch_uprobe_xol_was_trapped(t)) { -+ utask->state = UTASK_SSTEP_TRAPPED; -+ set_tsk_thread_flag(t, TIF_UPROBE); -+ set_tsk_thread_flag(t, TIF_NOTIFY_RESUME); -+ } -+ } -+ -+ return true; -+} -+ -+/* -+ * Avoid singlestepping the original instruction if the original instruction -+ * is a NOP or can be emulated. -+ */ -+static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs) -+{ -+ if (arch_uprobe_skip_sstep(&uprobe->arch, regs)) -+ return true; -+ -+ uprobe->flags &= ~UPROBE_SKIP_SSTEP; -+ return false; -+} -+ -+/* -+ * Run handler and ask thread to singlestep. -+ * Ensure all non-fatal signals cannot interrupt thread while it singlesteps. -+ */ -+static void handle_swbp(struct pt_regs *regs) -+{ -+ struct vm_area_struct *vma; -+ struct uprobe_task *utask; -+ struct uprobe *uprobe; -+ struct mm_struct *mm; -+ unsigned long bp_vaddr; -+ -+ uprobe = NULL; -+ bp_vaddr = uprobe_get_swbp_addr(regs); -+ mm = current->mm; -+ down_read(&mm->mmap_sem); -+ vma = find_vma(mm, bp_vaddr); -+ -+ if (vma && vma->vm_start <= bp_vaddr && valid_vma(vma, false)) { -+ struct inode *inode; -+ loff_t offset; -+ -+ inode = vma->vm_file->f_mapping->host; -+ offset = bp_vaddr - vma->vm_start; -+ offset += (vma->vm_pgoff << PAGE_SHIFT); -+ uprobe = find_uprobe(inode, offset); -+ } -+ -+ srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id); -+ current->uprobe_srcu_id = -1; -+ up_read(&mm->mmap_sem); -+ -+ if (!uprobe) { -+ /* No matching uprobe; signal SIGTRAP. */ -+ send_sig(SIGTRAP, current, 0); -+ return; -+ } -+ -+ utask = current->utask; -+ if (!utask) { -+ utask = add_utask(); -+ /* Cannot allocate; re-execute the instruction. */ -+ if (!utask) -+ goto cleanup_ret; -+ } -+ utask->active_uprobe = uprobe; -+ handler_chain(uprobe, regs); -+ if (uprobe->flags & UPROBE_SKIP_SSTEP && can_skip_sstep(uprobe, regs)) -+ goto cleanup_ret; -+ -+ utask->state = UTASK_SSTEP; -+ if (!pre_ssout(uprobe, regs, bp_vaddr)) { -+ user_enable_single_step(current); -+ return; -+ } -+ -+cleanup_ret: -+ if (utask) { -+ utask->active_uprobe = NULL; -+ utask->state = UTASK_RUNNING; -+ } -+ if (uprobe) { -+ if (!(uprobe->flags & UPROBE_SKIP_SSTEP)) -+ -+ /* -+ * cannot singlestep; cannot skip instruction; -+ * re-execute the instruction. -+ */ -+ instruction_pointer_set(regs, bp_vaddr); -+ -+ put_uprobe(uprobe); -+ } -+} -+ -+/* -+ * Perform required fix-ups and disable singlestep. -+ * Allow pending signals to take effect. -+ */ -+static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs) -+{ -+ struct uprobe *uprobe; -+ -+ uprobe = utask->active_uprobe; -+ if (utask->state == UTASK_SSTEP_ACK) -+ arch_uprobe_post_xol(&uprobe->arch, regs); -+ else if (utask->state == UTASK_SSTEP_TRAPPED) -+ arch_uprobe_abort_xol(&uprobe->arch, regs); -+ else -+ WARN_ON_ONCE(1); -+ -+ put_uprobe(uprobe); -+ utask->active_uprobe = NULL; -+ utask->state = UTASK_RUNNING; -+ user_disable_single_step(current); -+ xol_free_insn_slot(current); -+ -+ spin_lock_irq(¤t->sighand->siglock); -+ recalc_sigpending(); /* see uprobe_deny_signal() */ -+ spin_unlock_irq(¤t->sighand->siglock); -+} -+ -+/* -+ * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag. (and on -+ * subsequent probe hits on the thread sets the state to UTASK_BP_HIT) and -+ * allows the thread to return from interrupt. -+ * -+ * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag and -+ * also sets the state to UTASK_SSTEP_ACK and allows the thread to return from -+ * interrupt. -+ * -+ * While returning to userspace, thread notices the TIF_UPROBE flag and calls -+ * uprobe_notify_resume(). -+ */ -+void uprobe_notify_resume(struct pt_regs *regs) -+{ -+ struct uprobe_task *utask; -+ -+ utask = current->utask; -+ if (!utask || utask->state == UTASK_BP_HIT) -+ handle_swbp(regs); -+ else -+ handle_singlestep(utask, regs); -+} -+ -+/* -+ * uprobe_pre_sstep_notifier gets called from interrupt context as part of -+ * notifier mechanism. Set TIF_UPROBE flag and indicate breakpoint hit. -+ */ -+int uprobe_pre_sstep_notifier(struct pt_regs *regs) -+{ -+ struct uprobe_task *utask; -+ -+ if (!current->mm || !atomic_read(¤t->mm->uprobes_state.count)) -+ /* task is currently not uprobed */ -+ return 0; -+ -+ utask = current->utask; -+ if (utask) -+ utask->state = UTASK_BP_HIT; -+ -+ set_thread_flag(TIF_UPROBE); -+ current->uprobe_srcu_id = srcu_read_lock_raw(&uprobes_srcu); -+ -+ return 1; -+} -+ -+/* -+ * uprobe_post_sstep_notifier gets called in interrupt context as part of notifier -+ * mechanism. Set TIF_UPROBE flag and indicate completion of singlestep. -+ */ -+int uprobe_post_sstep_notifier(struct pt_regs *regs) -+{ -+ struct uprobe_task *utask = current->utask; -+ -+ if (!current->mm || !utask || !utask->active_uprobe) -+ /* task is currently not uprobed */ -+ return 0; -+ -+ utask->state = UTASK_SSTEP_ACK; -+ set_thread_flag(TIF_UPROBE); -+ return 1; -+} -+ -+static struct notifier_block uprobe_exception_nb = { -+ .notifier_call = arch_uprobe_exception_notify, -+ .priority = INT_MAX-1, /* notified after kprobes, kgdb */ -+}; -+ -+static int __init init_uprobes(void) -+{ -+ int i; -+ -+ for (i = 0; i < UPROBES_HASH_SZ; i++) { -+ mutex_init(&uprobes_mutex[i]); -+ mutex_init(&uprobes_mmap_mutex[i]); -+ } -+ init_srcu_struct(&uprobes_srcu); -+ -+ return register_die_notifier(&uprobe_exception_nb); -+} -+module_init(init_uprobes); -+ -+static void __exit exit_uprobes(void) -+{ -+} -+module_exit(exit_uprobes); -diff --git a/kernel/fork.c b/kernel/fork.c -index c3eafd8..5b87e9f 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -68,6 +68,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -423,6 +424,9 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) - - if (retval) - goto out; -+ -+ if (file && uprobe_mmap(tmp)) -+ goto out; - } - /* a new mm has just been created */ - arch_dup_mmap(oldmm, mm); -@@ -571,6 +575,7 @@ void mmput(struct mm_struct *mm) - might_sleep(); - - if (atomic_dec_and_test(&mm->mm_users)) { -+ uprobe_clear_state(mm); - exit_aio(mm); - ksm_exit(mm); - khugepaged_exit(mm); /* must run before exit_mmap */ -@@ -749,6 +754,8 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm) - exit_pi_state_list(tsk); - #endif - -+ uprobe_free_utask(tsk); -+ - /* Get rid of any cached register state */ - deactivate_mm(tsk, mm); - -@@ -803,6 +810,7 @@ struct mm_struct *dup_mm(struct task_struct *tsk) - #ifdef CONFIG_TRANSPARENT_HUGEPAGE - mm->pmd_huge_pte = NULL; - #endif -+ uprobe_reset_state(mm); - - if (!mm_init(mm, tsk)) - goto fail_nomem; -@@ -1344,6 +1352,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, - INIT_LIST_HEAD(&p->pi_state_list); - p->pi_state_cache = NULL; - #endif -+ uprobe_copy_process(p); - /* - * sigaltstack should be cleared when sharing the same VM - */ -diff --git a/kernel/signal.c b/kernel/signal.c -index 17afcaf..60d80ab 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #define CREATE_TRACE_POINTS - #include - -@@ -2202,6 +2203,9 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, - struct signal_struct *signal = current->signal; - int signr; - -+ if (unlikely(uprobe_deny_signal())) -+ return 0; -+ - relock: - /* - * We'll jump back here after any time we were stopped in TASK_STOPPED. -diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig -index a1d2849..ea4bff6 100644 ---- a/kernel/trace/Kconfig -+++ b/kernel/trace/Kconfig -@@ -373,6 +373,7 @@ config KPROBE_EVENT - depends on HAVE_REGS_AND_STACK_ACCESS_API - bool "Enable kprobes-based dynamic events" - select TRACING -+ select PROBE_EVENTS - default y - help - This allows the user to add tracing events (similar to tracepoints) -@@ -385,6 +386,25 @@ config KPROBE_EVENT - This option is also required by perf-probe subcommand of perf tools. - If you want to use perf tools, this option is strongly recommended. - -+config UPROBE_EVENT -+ bool "Enable uprobes-based dynamic events" -+ depends on ARCH_SUPPORTS_UPROBES -+ depends on MMU -+ select UPROBES -+ select PROBE_EVENTS -+ select TRACING -+ default n -+ help -+ This allows the user to add tracing events on top of userspace -+ dynamic events (similar to tracepoints) on the fly via the trace -+ events interface. Those events can be inserted wherever uprobes -+ can probe, and record various registers. -+ This option is required if you plan to use perf-probe subcommand -+ of perf tools on user space applications. -+ -+config PROBE_EVENTS -+ def_bool n -+ - config DYNAMIC_FTRACE - bool "enable/disable ftrace tracepoints dynamically" - depends on FUNCTION_TRACER -diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile -index 5f39a07..1734c03 100644 ---- a/kernel/trace/Makefile -+++ b/kernel/trace/Makefile -@@ -61,5 +61,7 @@ endif - ifeq ($(CONFIG_TRACING),y) - obj-$(CONFIG_KGDB_KDB) += trace_kdb.o - endif -+obj-$(CONFIG_PROBE_EVENTS) += trace_probe.o -+obj-$(CONFIG_UPROBE_EVENT) += trace_uprobe.o - - libftrace-y := ftrace.o -diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h -index f95d65d..a6bf705 100644 ---- a/kernel/trace/trace.h -+++ b/kernel/trace/trace.h -@@ -103,6 +103,11 @@ struct kretprobe_trace_entry_head { - unsigned long ret_ip; - }; - -+struct uprobe_trace_entry_head { -+ struct trace_entry ent; -+ unsigned long ip; -+}; -+ - /* - * trace_flag_type is an enumeration that holds different - * states when a trace occurs. These are: -diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c -index 580a05e..b31d3d5 100644 ---- a/kernel/trace/trace_kprobe.c -+++ b/kernel/trace/trace_kprobe.c -@@ -19,547 +19,15 @@ - - #include - #include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include "trace.h" --#include "trace_output.h" -- --#define MAX_TRACE_ARGS 128 --#define MAX_ARGSTR_LEN 63 --#define MAX_EVENT_NAME_LEN 64 --#define MAX_STRING_SIZE PATH_MAX --#define KPROBE_EVENT_SYSTEM "kprobes" -- --/* Reserved field names */ --#define FIELD_STRING_IP "__probe_ip" --#define FIELD_STRING_RETIP "__probe_ret_ip" --#define FIELD_STRING_FUNC "__probe_func" -- --const char *reserved_field_names[] = { -- "common_type", -- "common_flags", -- "common_preempt_count", -- "common_pid", -- "common_tgid", -- FIELD_STRING_IP, -- FIELD_STRING_RETIP, -- FIELD_STRING_FUNC, --}; -- --/* Printing function type */ --typedef int (*print_type_func_t)(struct trace_seq *, const char *, void *, -- void *); --#define PRINT_TYPE_FUNC_NAME(type) print_type_##type --#define PRINT_TYPE_FMT_NAME(type) print_type_format_##type -- --/* Printing in basic type function template */ --#define DEFINE_BASIC_PRINT_TYPE_FUNC(type, fmt, cast) \ --static __kprobes int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s, \ -- const char *name, \ -- void *data, void *ent)\ --{ \ -- return trace_seq_printf(s, " %s=" fmt, name, (cast)*(type *)data);\ --} \ --static const char PRINT_TYPE_FMT_NAME(type)[] = fmt; -- --DEFINE_BASIC_PRINT_TYPE_FUNC(u8, "%x", unsigned int) --DEFINE_BASIC_PRINT_TYPE_FUNC(u16, "%x", unsigned int) --DEFINE_BASIC_PRINT_TYPE_FUNC(u32, "%lx", unsigned long) --DEFINE_BASIC_PRINT_TYPE_FUNC(u64, "%llx", unsigned long long) --DEFINE_BASIC_PRINT_TYPE_FUNC(s8, "%d", int) --DEFINE_BASIC_PRINT_TYPE_FUNC(s16, "%d", int) --DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%ld", long) --DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%lld", long long) -- --/* data_rloc: data relative location, compatible with u32 */ --#define make_data_rloc(len, roffs) \ -- (((u32)(len) << 16) | ((u32)(roffs) & 0xffff)) --#define get_rloc_len(dl) ((u32)(dl) >> 16) --#define get_rloc_offs(dl) ((u32)(dl) & 0xffff) -- --static inline void *get_rloc_data(u32 *dl) --{ -- return (u8 *)dl + get_rloc_offs(*dl); --} -- --/* For data_loc conversion */ --static inline void *get_loc_data(u32 *dl, void *ent) --{ -- return (u8 *)ent + get_rloc_offs(*dl); --} -- --/* -- * Convert data_rloc to data_loc: -- * data_rloc stores the offset from data_rloc itself, but data_loc -- * stores the offset from event entry. -- */ --#define convert_rloc_to_loc(dl, offs) ((u32)(dl) + (offs)) -- --/* For defining macros, define string/string_size types */ --typedef u32 string; --typedef u32 string_size; -- --/* Print type function for string type */ --static __kprobes int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, -- const char *name, -- void *data, void *ent) --{ -- int len = *(u32 *)data >> 16; -- -- if (!len) -- return trace_seq_printf(s, " %s=(fault)", name); -- else -- return trace_seq_printf(s, " %s=\"%s\"", name, -- (const char *)get_loc_data(data, ent)); --} --static const char PRINT_TYPE_FMT_NAME(string)[] = "\\\"%s\\\""; -- --/* Data fetch function type */ --typedef void (*fetch_func_t)(struct pt_regs *, void *, void *); -- --struct fetch_param { -- fetch_func_t fn; -- void *data; --}; -- --static __kprobes void call_fetch(struct fetch_param *fprm, -- struct pt_regs *regs, void *dest) --{ -- return fprm->fn(regs, fprm->data, dest); --} -- --#define FETCH_FUNC_NAME(method, type) fetch_##method##_##type --/* -- * Define macro for basic types - we don't need to define s* types, because -- * we have to care only about bitwidth at recording time. -- */ --#define DEFINE_BASIC_FETCH_FUNCS(method) \ --DEFINE_FETCH_##method(u8) \ --DEFINE_FETCH_##method(u16) \ --DEFINE_FETCH_##method(u32) \ --DEFINE_FETCH_##method(u64) -- --#define CHECK_FETCH_FUNCS(method, fn) \ -- (((FETCH_FUNC_NAME(method, u8) == fn) || \ -- (FETCH_FUNC_NAME(method, u16) == fn) || \ -- (FETCH_FUNC_NAME(method, u32) == fn) || \ -- (FETCH_FUNC_NAME(method, u64) == fn) || \ -- (FETCH_FUNC_NAME(method, string) == fn) || \ -- (FETCH_FUNC_NAME(method, string_size) == fn)) \ -- && (fn != NULL)) -- --/* Data fetch function templates */ --#define DEFINE_FETCH_reg(type) \ --static __kprobes void FETCH_FUNC_NAME(reg, type)(struct pt_regs *regs, \ -- void *offset, void *dest) \ --{ \ -- *(type *)dest = (type)regs_get_register(regs, \ -- (unsigned int)((unsigned long)offset)); \ --} --DEFINE_BASIC_FETCH_FUNCS(reg) --/* No string on the register */ --#define fetch_reg_string NULL --#define fetch_reg_string_size NULL -- --#define DEFINE_FETCH_stack(type) \ --static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\ -- void *offset, void *dest) \ --{ \ -- *(type *)dest = (type)regs_get_kernel_stack_nth(regs, \ -- (unsigned int)((unsigned long)offset)); \ --} --DEFINE_BASIC_FETCH_FUNCS(stack) --/* No string on the stack entry */ --#define fetch_stack_string NULL --#define fetch_stack_string_size NULL -- --#define DEFINE_FETCH_retval(type) \ --static __kprobes void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,\ -- void *dummy, void *dest) \ --{ \ -- *(type *)dest = (type)regs_return_value(regs); \ --} --DEFINE_BASIC_FETCH_FUNCS(retval) --/* No string on the retval */ --#define fetch_retval_string NULL --#define fetch_retval_string_size NULL -- --#define DEFINE_FETCH_memory(type) \ --static __kprobes void FETCH_FUNC_NAME(memory, type)(struct pt_regs *regs,\ -- void *addr, void *dest) \ --{ \ -- type retval; \ -- if (probe_kernel_address(addr, retval)) \ -- *(type *)dest = 0; \ -- else \ -- *(type *)dest = retval; \ --} --DEFINE_BASIC_FETCH_FUNCS(memory) --/* -- * Fetch a null-terminated string. Caller MUST set *(u32 *)dest with max -- * length and relative data location. -- */ --static __kprobes void FETCH_FUNC_NAME(memory, string)(struct pt_regs *regs, -- void *addr, void *dest) --{ -- long ret; -- int maxlen = get_rloc_len(*(u32 *)dest); -- u8 *dst = get_rloc_data(dest); -- u8 *src = addr; -- mm_segment_t old_fs = get_fs(); -- if (!maxlen) -- return; -- /* -- * Try to get string again, since the string can be changed while -- * probing. -- */ -- set_fs(KERNEL_DS); -- pagefault_disable(); -- do -- ret = __copy_from_user_inatomic(dst++, src++, 1); -- while (dst[-1] && ret == 0 && src - (u8 *)addr < maxlen); -- dst[-1] = '\0'; -- pagefault_enable(); -- set_fs(old_fs); -- -- if (ret < 0) { /* Failed to fetch string */ -- ((u8 *)get_rloc_data(dest))[0] = '\0'; -- *(u32 *)dest = make_data_rloc(0, get_rloc_offs(*(u32 *)dest)); -- } else -- *(u32 *)dest = make_data_rloc(src - (u8 *)addr, -- get_rloc_offs(*(u32 *)dest)); --} --/* Return the length of string -- including null terminal byte */ --static __kprobes void FETCH_FUNC_NAME(memory, string_size)(struct pt_regs *regs, -- void *addr, void *dest) --{ -- int ret, len = 0; -- u8 c; -- mm_segment_t old_fs = get_fs(); -- -- set_fs(KERNEL_DS); -- pagefault_disable(); -- do { -- ret = __copy_from_user_inatomic(&c, (u8 *)addr + len, 1); -- len++; -- } while (c && ret == 0 && len < MAX_STRING_SIZE); -- pagefault_enable(); -- set_fs(old_fs); -- -- if (ret < 0) /* Failed to check the length */ -- *(u32 *)dest = 0; -- else -- *(u32 *)dest = len; --} -- --/* Memory fetching by symbol */ --struct symbol_cache { -- char *symbol; -- long offset; -- unsigned long addr; --}; -- --static unsigned long update_symbol_cache(struct symbol_cache *sc) --{ -- sc->addr = (unsigned long)kallsyms_lookup_name(sc->symbol); -- if (sc->addr) -- sc->addr += sc->offset; -- return sc->addr; --} -- --static void free_symbol_cache(struct symbol_cache *sc) --{ -- kfree(sc->symbol); -- kfree(sc); --} -- --static struct symbol_cache *alloc_symbol_cache(const char *sym, long offset) --{ -- struct symbol_cache *sc; -- -- if (!sym || strlen(sym) == 0) -- return NULL; -- sc = kzalloc(sizeof(struct symbol_cache), GFP_KERNEL); -- if (!sc) -- return NULL; -- -- sc->symbol = kstrdup(sym, GFP_KERNEL); -- if (!sc->symbol) { -- kfree(sc); -- return NULL; -- } -- sc->offset = offset; - -- update_symbol_cache(sc); -- return sc; --} -- --#define DEFINE_FETCH_symbol(type) \ --static __kprobes void FETCH_FUNC_NAME(symbol, type)(struct pt_regs *regs,\ -- void *data, void *dest) \ --{ \ -- struct symbol_cache *sc = data; \ -- if (sc->addr) \ -- fetch_memory_##type(regs, (void *)sc->addr, dest); \ -- else \ -- *(type *)dest = 0; \ --} --DEFINE_BASIC_FETCH_FUNCS(symbol) --DEFINE_FETCH_symbol(string) --DEFINE_FETCH_symbol(string_size) -- --/* Dereference memory access function */ --struct deref_fetch_param { -- struct fetch_param orig; -- long offset; --}; -- --#define DEFINE_FETCH_deref(type) \ --static __kprobes void FETCH_FUNC_NAME(deref, type)(struct pt_regs *regs,\ -- void *data, void *dest) \ --{ \ -- struct deref_fetch_param *dprm = data; \ -- unsigned long addr; \ -- call_fetch(&dprm->orig, regs, &addr); \ -- if (addr) { \ -- addr += dprm->offset; \ -- fetch_memory_##type(regs, (void *)addr, dest); \ -- } else \ -- *(type *)dest = 0; \ --} --DEFINE_BASIC_FETCH_FUNCS(deref) --DEFINE_FETCH_deref(string) --DEFINE_FETCH_deref(string_size) -- --static __kprobes void update_deref_fetch_param(struct deref_fetch_param *data) --{ -- if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) -- update_deref_fetch_param(data->orig.data); -- else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) -- update_symbol_cache(data->orig.data); --} -- --static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data) --{ -- if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) -- free_deref_fetch_param(data->orig.data); -- else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) -- free_symbol_cache(data->orig.data); -- kfree(data); --} -- --/* Bitfield fetch function */ --struct bitfield_fetch_param { -- struct fetch_param orig; -- unsigned char hi_shift; -- unsigned char low_shift; --}; -+#include "trace_probe.h" - --#define DEFINE_FETCH_bitfield(type) \ --static __kprobes void FETCH_FUNC_NAME(bitfield, type)(struct pt_regs *regs,\ -- void *data, void *dest) \ --{ \ -- struct bitfield_fetch_param *bprm = data; \ -- type buf = 0; \ -- call_fetch(&bprm->orig, regs, &buf); \ -- if (buf) { \ -- buf <<= bprm->hi_shift; \ -- buf >>= bprm->low_shift; \ -- } \ -- *(type *)dest = buf; \ --} --DEFINE_BASIC_FETCH_FUNCS(bitfield) --#define fetch_bitfield_string NULL --#define fetch_bitfield_string_size NULL -- --static __kprobes void --update_bitfield_fetch_param(struct bitfield_fetch_param *data) --{ -- /* -- * Don't check the bitfield itself, because this must be the -- * last fetch function. -- */ -- if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) -- update_deref_fetch_param(data->orig.data); -- else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) -- update_symbol_cache(data->orig.data); --} -- --static __kprobes void --free_bitfield_fetch_param(struct bitfield_fetch_param *data) --{ -- /* -- * Don't check the bitfield itself, because this must be the -- * last fetch function. -- */ -- if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) -- free_deref_fetch_param(data->orig.data); -- else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) -- free_symbol_cache(data->orig.data); -- kfree(data); --} -- --/* Default (unsigned long) fetch type */ --#define __DEFAULT_FETCH_TYPE(t) u##t --#define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t) --#define DEFAULT_FETCH_TYPE _DEFAULT_FETCH_TYPE(BITS_PER_LONG) --#define DEFAULT_FETCH_TYPE_STR __stringify(DEFAULT_FETCH_TYPE) -- --/* Fetch types */ --enum { -- FETCH_MTD_reg = 0, -- FETCH_MTD_stack, -- FETCH_MTD_retval, -- FETCH_MTD_memory, -- FETCH_MTD_symbol, -- FETCH_MTD_deref, -- FETCH_MTD_bitfield, -- FETCH_MTD_END, --}; -- --#define ASSIGN_FETCH_FUNC(method, type) \ -- [FETCH_MTD_##method] = FETCH_FUNC_NAME(method, type) -- --#define __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, _fmttype) \ -- {.name = _name, \ -- .size = _size, \ -- .is_signed = sign, \ -- .print = PRINT_TYPE_FUNC_NAME(ptype), \ -- .fmt = PRINT_TYPE_FMT_NAME(ptype), \ -- .fmttype = _fmttype, \ -- .fetch = { \ --ASSIGN_FETCH_FUNC(reg, ftype), \ --ASSIGN_FETCH_FUNC(stack, ftype), \ --ASSIGN_FETCH_FUNC(retval, ftype), \ --ASSIGN_FETCH_FUNC(memory, ftype), \ --ASSIGN_FETCH_FUNC(symbol, ftype), \ --ASSIGN_FETCH_FUNC(deref, ftype), \ --ASSIGN_FETCH_FUNC(bitfield, ftype), \ -- } \ -- } -- --#define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \ -- __ASSIGN_FETCH_TYPE(#ptype, ptype, ftype, sizeof(ftype), sign, #ptype) -- --#define FETCH_TYPE_STRING 0 --#define FETCH_TYPE_STRSIZE 1 -- --/* Fetch type information table */ --static const struct fetch_type { -- const char *name; /* Name of type */ -- size_t size; /* Byte size of type */ -- int is_signed; /* Signed flag */ -- print_type_func_t print; /* Print functions */ -- const char *fmt; /* Fromat string */ -- const char *fmttype; /* Name in format file */ -- /* Fetch functions */ -- fetch_func_t fetch[FETCH_MTD_END]; --} fetch_type_table[] = { -- /* Special types */ -- [FETCH_TYPE_STRING] = __ASSIGN_FETCH_TYPE("string", string, string, -- sizeof(u32), 1, "__data_loc char[]"), -- [FETCH_TYPE_STRSIZE] = __ASSIGN_FETCH_TYPE("string_size", u32, -- string_size, sizeof(u32), 0, "u32"), -- /* Basic types */ -- ASSIGN_FETCH_TYPE(u8, u8, 0), -- ASSIGN_FETCH_TYPE(u16, u16, 0), -- ASSIGN_FETCH_TYPE(u32, u32, 0), -- ASSIGN_FETCH_TYPE(u64, u64, 0), -- ASSIGN_FETCH_TYPE(s8, u8, 1), -- ASSIGN_FETCH_TYPE(s16, u16, 1), -- ASSIGN_FETCH_TYPE(s32, u32, 1), -- ASSIGN_FETCH_TYPE(s64, u64, 1), --}; -- --static const struct fetch_type *find_fetch_type(const char *type) --{ -- int i; -- -- if (!type) -- type = DEFAULT_FETCH_TYPE_STR; -- -- /* Special case: bitfield */ -- if (*type == 'b') { -- unsigned long bs; -- type = strchr(type, '/'); -- if (!type) -- goto fail; -- type++; -- if (strict_strtoul(type, 0, &bs)) -- goto fail; -- switch (bs) { -- case 8: -- return find_fetch_type("u8"); -- case 16: -- return find_fetch_type("u16"); -- case 32: -- return find_fetch_type("u32"); -- case 64: -- return find_fetch_type("u64"); -- default: -- goto fail; -- } -- } -- -- for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++) -- if (strcmp(type, fetch_type_table[i].name) == 0) -- return &fetch_type_table[i]; --fail: -- return NULL; --} -- --/* Special function : only accept unsigned long */ --static __kprobes void fetch_stack_address(struct pt_regs *regs, -- void *dummy, void *dest) --{ -- *(unsigned long *)dest = kernel_stack_pointer(regs); --} -- --static fetch_func_t get_fetch_size_function(const struct fetch_type *type, -- fetch_func_t orig_fn) --{ -- int i; -- -- if (type != &fetch_type_table[FETCH_TYPE_STRING]) -- return NULL; /* Only string type needs size function */ -- for (i = 0; i < FETCH_MTD_END; i++) -- if (type->fetch[i] == orig_fn) -- return fetch_type_table[FETCH_TYPE_STRSIZE].fetch[i]; -- -- WARN_ON(1); /* This should not happen */ -- return NULL; --} -+#define KPROBE_EVENT_SYSTEM "kprobes" - - /** - * Kprobe event core functions - */ - --struct probe_arg { -- struct fetch_param fetch; -- struct fetch_param fetch_size; -- unsigned int offset; /* Offset from argument entry */ -- const char *name; /* Name of this argument */ -- const char *comm; /* Command of this argument */ -- const struct fetch_type *type; /* Type of this argument */ --}; -- --/* Flags for trace_probe */ --#define TP_FLAG_TRACE 1 --#define TP_FLAG_PROFILE 2 --#define TP_FLAG_REGISTERED 4 -- - struct trace_probe { - struct list_head list; - struct kretprobe rp; /* Use rp.kp for kprobe use */ -@@ -631,18 +99,6 @@ static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs); - static int kretprobe_dispatcher(struct kretprobe_instance *ri, - struct pt_regs *regs); - --/* Check the name is good for event/group/fields */ --static int is_good_name(const char *name) --{ -- if (!isalpha(*name) && *name != '_') -- return 0; -- while (*++name != '\0') { -- if (!isalpha(*name) && !isdigit(*name) && *name != '_') -- return 0; -- } -- return 1; --} -- - /* - * Allocate new trace_probe and initialize it (including kprobes). - */ -@@ -651,7 +107,7 @@ static struct trace_probe *alloc_trace_probe(const char *group, - void *addr, - const char *symbol, - unsigned long offs, -- int nargs, int is_return) -+ int nargs, bool is_return) - { - struct trace_probe *tp; - int ret = -ENOMEM; -@@ -702,34 +158,12 @@ error: - return ERR_PTR(ret); - } - --static void update_probe_arg(struct probe_arg *arg) --{ -- if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn)) -- update_bitfield_fetch_param(arg->fetch.data); -- else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn)) -- update_deref_fetch_param(arg->fetch.data); -- else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn)) -- update_symbol_cache(arg->fetch.data); --} -- --static void free_probe_arg(struct probe_arg *arg) --{ -- if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn)) -- free_bitfield_fetch_param(arg->fetch.data); -- else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn)) -- free_deref_fetch_param(arg->fetch.data); -- else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn)) -- free_symbol_cache(arg->fetch.data); -- kfree(arg->name); -- kfree(arg->comm); --} -- - static void free_trace_probe(struct trace_probe *tp) - { - int i; - - for (i = 0; i < tp->nr_args; i++) -- free_probe_arg(&tp->args[i]); -+ traceprobe_free_probe_arg(&tp->args[i]); - - kfree(tp->call.class->system); - kfree(tp->call.name); -@@ -787,7 +221,7 @@ static int __register_trace_probe(struct trace_probe *tp) - return -EINVAL; - - for (i = 0; i < tp->nr_args; i++) -- update_probe_arg(&tp->args[i]); -+ traceprobe_update_arg(&tp->args[i]); - - /* Set/clear disabled flag according to tp->flag */ - if (trace_probe_is_enabled(tp)) -@@ -919,227 +353,6 @@ static struct notifier_block trace_probe_module_nb = { - .priority = 1 /* Invoked after kprobe module callback */ - }; - --/* Split symbol and offset. */ --static int split_symbol_offset(char *symbol, unsigned long *offset) --{ -- char *tmp; -- int ret; -- -- if (!offset) -- return -EINVAL; -- -- tmp = strchr(symbol, '+'); -- if (tmp) { -- /* skip sign because strict_strtol doesn't accept '+' */ -- ret = strict_strtoul(tmp + 1, 0, offset); -- if (ret) -- return ret; -- *tmp = '\0'; -- } else -- *offset = 0; -- return 0; --} -- --#define PARAM_MAX_ARGS 16 --#define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) -- --static int parse_probe_vars(char *arg, const struct fetch_type *t, -- struct fetch_param *f, int is_return) --{ -- int ret = 0; -- unsigned long param; -- -- if (strcmp(arg, "retval") == 0) { -- if (is_return) -- f->fn = t->fetch[FETCH_MTD_retval]; -- else -- ret = -EINVAL; -- } else if (strncmp(arg, "stack", 5) == 0) { -- if (arg[5] == '\0') { -- if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR) == 0) -- f->fn = fetch_stack_address; -- else -- ret = -EINVAL; -- } else if (isdigit(arg[5])) { -- ret = strict_strtoul(arg + 5, 10, ¶m); -- if (ret || param > PARAM_MAX_STACK) -- ret = -EINVAL; -- else { -- f->fn = t->fetch[FETCH_MTD_stack]; -- f->data = (void *)param; -- } -- } else -- ret = -EINVAL; -- } else -- ret = -EINVAL; -- return ret; --} -- --/* Recursive argument parser */ --static int __parse_probe_arg(char *arg, const struct fetch_type *t, -- struct fetch_param *f, int is_return) --{ -- int ret = 0; -- unsigned long param; -- long offset; -- char *tmp; -- -- switch (arg[0]) { -- case '$': -- ret = parse_probe_vars(arg + 1, t, f, is_return); -- break; -- case '%': /* named register */ -- ret = regs_query_register_offset(arg + 1); -- if (ret >= 0) { -- f->fn = t->fetch[FETCH_MTD_reg]; -- f->data = (void *)(unsigned long)ret; -- ret = 0; -- } -- break; -- case '@': /* memory or symbol */ -- if (isdigit(arg[1])) { -- ret = strict_strtoul(arg + 1, 0, ¶m); -- if (ret) -- break; -- f->fn = t->fetch[FETCH_MTD_memory]; -- f->data = (void *)param; -- } else { -- ret = split_symbol_offset(arg + 1, &offset); -- if (ret) -- break; -- f->data = alloc_symbol_cache(arg + 1, offset); -- if (f->data) -- f->fn = t->fetch[FETCH_MTD_symbol]; -- } -- break; -- case '+': /* deref memory */ -- arg++; /* Skip '+', because strict_strtol() rejects it. */ -- case '-': -- tmp = strchr(arg, '('); -- if (!tmp) -- break; -- *tmp = '\0'; -- ret = strict_strtol(arg, 0, &offset); -- if (ret) -- break; -- arg = tmp + 1; -- tmp = strrchr(arg, ')'); -- if (tmp) { -- struct deref_fetch_param *dprm; -- const struct fetch_type *t2 = find_fetch_type(NULL); -- *tmp = '\0'; -- dprm = kzalloc(sizeof(struct deref_fetch_param), -- GFP_KERNEL); -- if (!dprm) -- return -ENOMEM; -- dprm->offset = offset; -- ret = __parse_probe_arg(arg, t2, &dprm->orig, -- is_return); -- if (ret) -- kfree(dprm); -- else { -- f->fn = t->fetch[FETCH_MTD_deref]; -- f->data = (void *)dprm; -- } -- } -- break; -- } -- if (!ret && !f->fn) { /* Parsed, but do not find fetch method */ -- pr_info("%s type has no corresponding fetch method.\n", -- t->name); -- ret = -EINVAL; -- } -- return ret; --} -- --#define BYTES_TO_BITS(nb) ((BITS_PER_LONG * (nb)) / sizeof(long)) -- --/* Bitfield type needs to be parsed into a fetch function */ --static int __parse_bitfield_probe_arg(const char *bf, -- const struct fetch_type *t, -- struct fetch_param *f) --{ -- struct bitfield_fetch_param *bprm; -- unsigned long bw, bo; -- char *tail; -- -- if (*bf != 'b') -- return 0; -- -- bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); -- if (!bprm) -- return -ENOMEM; -- bprm->orig = *f; -- f->fn = t->fetch[FETCH_MTD_bitfield]; -- f->data = (void *)bprm; -- -- bw = simple_strtoul(bf + 1, &tail, 0); /* Use simple one */ -- if (bw == 0 || *tail != '@') -- return -EINVAL; -- -- bf = tail + 1; -- bo = simple_strtoul(bf, &tail, 0); -- if (tail == bf || *tail != '/') -- return -EINVAL; -- -- bprm->hi_shift = BYTES_TO_BITS(t->size) - (bw + bo); -- bprm->low_shift = bprm->hi_shift + bo; -- return (BYTES_TO_BITS(t->size) < (bw + bo)) ? -EINVAL : 0; --} -- --/* String length checking wrapper */ --static int parse_probe_arg(char *arg, struct trace_probe *tp, -- struct probe_arg *parg, int is_return) --{ -- const char *t; -- int ret; -- -- if (strlen(arg) > MAX_ARGSTR_LEN) { -- pr_info("Argument is too long.: %s\n", arg); -- return -ENOSPC; -- } -- parg->comm = kstrdup(arg, GFP_KERNEL); -- if (!parg->comm) { -- pr_info("Failed to allocate memory for command '%s'.\n", arg); -- return -ENOMEM; -- } -- t = strchr(parg->comm, ':'); -- if (t) { -- arg[t - parg->comm] = '\0'; -- t++; -- } -- parg->type = find_fetch_type(t); -- if (!parg->type) { -- pr_info("Unsupported type: %s\n", t); -- return -EINVAL; -- } -- parg->offset = tp->size; -- tp->size += parg->type->size; -- ret = __parse_probe_arg(arg, parg->type, &parg->fetch, is_return); -- if (ret >= 0 && t != NULL) -- ret = __parse_bitfield_probe_arg(t, parg->type, &parg->fetch); -- if (ret >= 0) { -- parg->fetch_size.fn = get_fetch_size_function(parg->type, -- parg->fetch.fn); -- parg->fetch_size.data = parg->fetch.data; -- } -- return ret; --} -- --/* Return 1 if name is reserved or already used by another argument */ --static int conflict_field_name(const char *name, -- struct probe_arg *args, int narg) --{ -- int i; -- for (i = 0; i < ARRAY_SIZE(reserved_field_names); i++) -- if (strcmp(reserved_field_names[i], name) == 0) -- return 1; -- for (i = 0; i < narg; i++) -- if (strcmp(args[i].name, name) == 0) -- return 1; -- return 0; --} -- - static int create_trace_probe(int argc, char **argv) - { - /* -@@ -1162,7 +375,7 @@ static int create_trace_probe(int argc, char **argv) - */ - struct trace_probe *tp; - int i, ret = 0; -- int is_return = 0, is_delete = 0; -+ bool is_return = false, is_delete = false; - char *symbol = NULL, *event = NULL, *group = NULL; - char *arg; - unsigned long offset = 0; -@@ -1171,11 +384,11 @@ static int create_trace_probe(int argc, char **argv) - - /* argc must be >= 1 */ - if (argv[0][0] == 'p') -- is_return = 0; -+ is_return = false; - else if (argv[0][0] == 'r') -- is_return = 1; -+ is_return = true; - else if (argv[0][0] == '-') -- is_delete = 1; -+ is_delete = true; - else { - pr_info("Probe definition must be started with 'p', 'r' or" - " '-'.\n"); -@@ -1240,7 +453,7 @@ static int create_trace_probe(int argc, char **argv) - /* a symbol specified */ - symbol = argv[1]; - /* TODO: support .init module functions */ -- ret = split_symbol_offset(symbol, &offset); -+ ret = traceprobe_split_symbol_offset(symbol, &offset); - if (ret) { - pr_info("Failed to parse symbol.\n"); - return ret; -@@ -1302,7 +515,8 @@ static int create_trace_probe(int argc, char **argv) - goto error; - } - -- if (conflict_field_name(tp->args[i].name, tp->args, i)) { -+ if (traceprobe_conflict_field_name(tp->args[i].name, -+ tp->args, i)) { - pr_info("Argument[%d] name '%s' conflicts with " - "another field.\n", i, argv[i]); - ret = -EINVAL; -@@ -1310,7 +524,8 @@ static int create_trace_probe(int argc, char **argv) - } - - /* Parse fetch argument */ -- ret = parse_probe_arg(arg, tp, &tp->args[i], is_return); -+ ret = traceprobe_parse_probe_arg(arg, &tp->size, &tp->args[i], -+ is_return, true); - if (ret) { - pr_info("Parse error at argument[%d]. (%d)\n", i, ret); - goto error; -@@ -1412,70 +627,11 @@ static int probes_open(struct inode *inode, struct file *file) - return seq_open(file, &probes_seq_op); - } - --static int command_trace_probe(const char *buf) --{ -- char **argv; -- int argc = 0, ret = 0; -- -- argv = argv_split(GFP_KERNEL, buf, &argc); -- if (!argv) -- return -ENOMEM; -- -- if (argc) -- ret = create_trace_probe(argc, argv); -- -- argv_free(argv); -- return ret; --} -- --#define WRITE_BUFSIZE 4096 -- - static ssize_t probes_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) - { -- char *kbuf, *tmp; -- int ret; -- size_t done; -- size_t size; -- -- kbuf = kmalloc(WRITE_BUFSIZE, GFP_KERNEL); -- if (!kbuf) -- return -ENOMEM; -- -- ret = done = 0; -- while (done < count) { -- size = count - done; -- if (size >= WRITE_BUFSIZE) -- size = WRITE_BUFSIZE - 1; -- if (copy_from_user(kbuf, buffer + done, size)) { -- ret = -EFAULT; -- goto out; -- } -- kbuf[size] = '\0'; -- tmp = strchr(kbuf, '\n'); -- if (tmp) { -- *tmp = '\0'; -- size = tmp - kbuf + 1; -- } else if (done + size < count) { -- pr_warning("Line length is too long: " -- "Should be less than %d.", WRITE_BUFSIZE); -- ret = -EINVAL; -- goto out; -- } -- done += size; -- /* Remove comments */ -- tmp = strchr(kbuf, '#'); -- if (tmp) -- *tmp = '\0'; -- -- ret = command_trace_probe(kbuf); -- if (ret) -- goto out; -- } -- ret = done; --out: -- kfree(kbuf); -- return ret; -+ return traceprobe_probes_write(file, buffer, count, ppos, -+ create_trace_probe); - } - - static const struct file_operations kprobe_events_ops = { -@@ -1711,16 +867,6 @@ partial: - return TRACE_TYPE_PARTIAL_LINE; - } - --#undef DEFINE_FIELD --#define DEFINE_FIELD(type, item, name, is_signed) \ -- do { \ -- ret = trace_define_field(event_call, #type, name, \ -- offsetof(typeof(field), item), \ -- sizeof(field.item), is_signed, \ -- FILTER_OTHER); \ -- if (ret) \ -- return ret; \ -- } while (0) - - static int kprobe_event_define_fields(struct ftrace_event_call *event_call) - { -@@ -2051,8 +1197,9 @@ static __init int kprobe_trace_self_tests_init(void) - - pr_info("Testing kprobe tracing: "); - -- ret = command_trace_probe("p:testprobe kprobe_trace_selftest_target " -- "$stack $stack0 +0($stack)"); -+ ret = traceprobe_command("p:testprobe kprobe_trace_selftest_target " -+ "$stack $stack0 +0($stack)", -+ create_trace_probe); - if (WARN_ON_ONCE(ret)) { - pr_warning("error on probing function entry.\n"); - warn++; -@@ -2066,8 +1213,8 @@ static __init int kprobe_trace_self_tests_init(void) - enable_trace_probe(tp, TP_FLAG_TRACE); - } - -- ret = command_trace_probe("r:testprobe2 kprobe_trace_selftest_target " -- "$retval"); -+ ret = traceprobe_command("r:testprobe2 kprobe_trace_selftest_target " -+ "$retval", create_trace_probe); - if (WARN_ON_ONCE(ret)) { - pr_warning("error on probing function return.\n"); - warn++; -@@ -2101,13 +1248,13 @@ static __init int kprobe_trace_self_tests_init(void) - } else - disable_trace_probe(tp, TP_FLAG_TRACE); - -- ret = command_trace_probe("-:testprobe"); -+ ret = traceprobe_command("-:testprobe", create_trace_probe); - if (WARN_ON_ONCE(ret)) { - pr_warning("error on deleting a probe.\n"); - warn++; - } - -- ret = command_trace_probe("-:testprobe2"); -+ ret = traceprobe_command("-:testprobe2", create_trace_probe); - if (WARN_ON_ONCE(ret)) { - pr_warning("error on deleting a probe.\n"); - warn++; -diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c -new file mode 100644 -index 0000000..daa9980 ---- /dev/null -+++ b/kernel/trace/trace_probe.c -@@ -0,0 +1,839 @@ -+/* -+ * Common code for probe-based Dynamic events. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * This code was copied from kernel/trace/trace_kprobe.c written by -+ * Masami Hiramatsu -+ * -+ * Updates to make this generic: -+ * Copyright (C) IBM Corporation, 2010-2011 -+ * Author: Srikar Dronamraju -+ */ -+ -+#include "trace_probe.h" -+ -+const char *reserved_field_names[] = { -+ "common_type", -+ "common_flags", -+ "common_preempt_count", -+ "common_pid", -+ "common_tgid", -+ FIELD_STRING_IP, -+ FIELD_STRING_RETIP, -+ FIELD_STRING_FUNC, -+}; -+ -+/* Printing function type */ -+#define PRINT_TYPE_FUNC_NAME(type) print_type_##type -+#define PRINT_TYPE_FMT_NAME(type) print_type_format_##type -+ -+/* Printing in basic type function template */ -+#define DEFINE_BASIC_PRINT_TYPE_FUNC(type, fmt, cast) \ -+static __kprobes int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s, \ -+ const char *name, \ -+ void *data, void *ent)\ -+{ \ -+ return trace_seq_printf(s, " %s=" fmt, name, (cast)*(type *)data);\ -+} \ -+static const char PRINT_TYPE_FMT_NAME(type)[] = fmt; -+ -+DEFINE_BASIC_PRINT_TYPE_FUNC(u8, "%x", unsigned int) -+DEFINE_BASIC_PRINT_TYPE_FUNC(u16, "%x", unsigned int) -+DEFINE_BASIC_PRINT_TYPE_FUNC(u32, "%lx", unsigned long) -+DEFINE_BASIC_PRINT_TYPE_FUNC(u64, "%llx", unsigned long long) -+DEFINE_BASIC_PRINT_TYPE_FUNC(s8, "%d", int) -+DEFINE_BASIC_PRINT_TYPE_FUNC(s16, "%d", int) -+DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%ld", long) -+DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%lld", long long) -+ -+static inline void *get_rloc_data(u32 *dl) -+{ -+ return (u8 *)dl + get_rloc_offs(*dl); -+} -+ -+/* For data_loc conversion */ -+static inline void *get_loc_data(u32 *dl, void *ent) -+{ -+ return (u8 *)ent + get_rloc_offs(*dl); -+} -+ -+/* For defining macros, define string/string_size types */ -+typedef u32 string; -+typedef u32 string_size; -+ -+/* Print type function for string type */ -+static __kprobes int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, -+ const char *name, -+ void *data, void *ent) -+{ -+ int len = *(u32 *)data >> 16; -+ -+ if (!len) -+ return trace_seq_printf(s, " %s=(fault)", name); -+ else -+ return trace_seq_printf(s, " %s=\"%s\"", name, -+ (const char *)get_loc_data(data, ent)); -+} -+ -+static const char PRINT_TYPE_FMT_NAME(string)[] = "\\\"%s\\\""; -+ -+#define FETCH_FUNC_NAME(method, type) fetch_##method##_##type -+/* -+ * Define macro for basic types - we don't need to define s* types, because -+ * we have to care only about bitwidth at recording time. -+ */ -+#define DEFINE_BASIC_FETCH_FUNCS(method) \ -+DEFINE_FETCH_##method(u8) \ -+DEFINE_FETCH_##method(u16) \ -+DEFINE_FETCH_##method(u32) \ -+DEFINE_FETCH_##method(u64) -+ -+#define CHECK_FETCH_FUNCS(method, fn) \ -+ (((FETCH_FUNC_NAME(method, u8) == fn) || \ -+ (FETCH_FUNC_NAME(method, u16) == fn) || \ -+ (FETCH_FUNC_NAME(method, u32) == fn) || \ -+ (FETCH_FUNC_NAME(method, u64) == fn) || \ -+ (FETCH_FUNC_NAME(method, string) == fn) || \ -+ (FETCH_FUNC_NAME(method, string_size) == fn)) \ -+ && (fn != NULL)) -+ -+/* Data fetch function templates */ -+#define DEFINE_FETCH_reg(type) \ -+static __kprobes void FETCH_FUNC_NAME(reg, type)(struct pt_regs *regs, \ -+ void *offset, void *dest) \ -+{ \ -+ *(type *)dest = (type)regs_get_register(regs, \ -+ (unsigned int)((unsigned long)offset)); \ -+} -+DEFINE_BASIC_FETCH_FUNCS(reg) -+/* No string on the register */ -+#define fetch_reg_string NULL -+#define fetch_reg_string_size NULL -+ -+#define DEFINE_FETCH_stack(type) \ -+static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\ -+ void *offset, void *dest) \ -+{ \ -+ *(type *)dest = (type)regs_get_kernel_stack_nth(regs, \ -+ (unsigned int)((unsigned long)offset)); \ -+} -+DEFINE_BASIC_FETCH_FUNCS(stack) -+/* No string on the stack entry */ -+#define fetch_stack_string NULL -+#define fetch_stack_string_size NULL -+ -+#define DEFINE_FETCH_retval(type) \ -+static __kprobes void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,\ -+ void *dummy, void *dest) \ -+{ \ -+ *(type *)dest = (type)regs_return_value(regs); \ -+} -+DEFINE_BASIC_FETCH_FUNCS(retval) -+/* No string on the retval */ -+#define fetch_retval_string NULL -+#define fetch_retval_string_size NULL -+ -+#define DEFINE_FETCH_memory(type) \ -+static __kprobes void FETCH_FUNC_NAME(memory, type)(struct pt_regs *regs,\ -+ void *addr, void *dest) \ -+{ \ -+ type retval; \ -+ if (probe_kernel_address(addr, retval)) \ -+ *(type *)dest = 0; \ -+ else \ -+ *(type *)dest = retval; \ -+} -+DEFINE_BASIC_FETCH_FUNCS(memory) -+/* -+ * Fetch a null-terminated string. Caller MUST set *(u32 *)dest with max -+ * length and relative data location. -+ */ -+static __kprobes void FETCH_FUNC_NAME(memory, string)(struct pt_regs *regs, -+ void *addr, void *dest) -+{ -+ long ret; -+ int maxlen = get_rloc_len(*(u32 *)dest); -+ u8 *dst = get_rloc_data(dest); -+ u8 *src = addr; -+ mm_segment_t old_fs = get_fs(); -+ -+ if (!maxlen) -+ return; -+ -+ /* -+ * Try to get string again, since the string can be changed while -+ * probing. -+ */ -+ set_fs(KERNEL_DS); -+ pagefault_disable(); -+ -+ do -+ ret = __copy_from_user_inatomic(dst++, src++, 1); -+ while (dst[-1] && ret == 0 && src - (u8 *)addr < maxlen); -+ -+ dst[-1] = '\0'; -+ pagefault_enable(); -+ set_fs(old_fs); -+ -+ if (ret < 0) { /* Failed to fetch string */ -+ ((u8 *)get_rloc_data(dest))[0] = '\0'; -+ *(u32 *)dest = make_data_rloc(0, get_rloc_offs(*(u32 *)dest)); -+ } else { -+ *(u32 *)dest = make_data_rloc(src - (u8 *)addr, -+ get_rloc_offs(*(u32 *)dest)); -+ } -+} -+ -+/* Return the length of string -- including null terminal byte */ -+static __kprobes void FETCH_FUNC_NAME(memory, string_size)(struct pt_regs *regs, -+ void *addr, void *dest) -+{ -+ mm_segment_t old_fs; -+ int ret, len = 0; -+ u8 c; -+ -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ pagefault_disable(); -+ -+ do { -+ ret = __copy_from_user_inatomic(&c, (u8 *)addr + len, 1); -+ len++; -+ } while (c && ret == 0 && len < MAX_STRING_SIZE); -+ -+ pagefault_enable(); -+ set_fs(old_fs); -+ -+ if (ret < 0) /* Failed to check the length */ -+ *(u32 *)dest = 0; -+ else -+ *(u32 *)dest = len; -+} -+ -+/* Memory fetching by symbol */ -+struct symbol_cache { -+ char *symbol; -+ long offset; -+ unsigned long addr; -+}; -+ -+static unsigned long update_symbol_cache(struct symbol_cache *sc) -+{ -+ sc->addr = (unsigned long)kallsyms_lookup_name(sc->symbol); -+ -+ if (sc->addr) -+ sc->addr += sc->offset; -+ -+ return sc->addr; -+} -+ -+static void free_symbol_cache(struct symbol_cache *sc) -+{ -+ kfree(sc->symbol); -+ kfree(sc); -+} -+ -+static struct symbol_cache *alloc_symbol_cache(const char *sym, long offset) -+{ -+ struct symbol_cache *sc; -+ -+ if (!sym || strlen(sym) == 0) -+ return NULL; -+ -+ sc = kzalloc(sizeof(struct symbol_cache), GFP_KERNEL); -+ if (!sc) -+ return NULL; -+ -+ sc->symbol = kstrdup(sym, GFP_KERNEL); -+ if (!sc->symbol) { -+ kfree(sc); -+ return NULL; -+ } -+ sc->offset = offset; -+ update_symbol_cache(sc); -+ -+ return sc; -+} -+ -+#define DEFINE_FETCH_symbol(type) \ -+static __kprobes void FETCH_FUNC_NAME(symbol, type)(struct pt_regs *regs,\ -+ void *data, void *dest) \ -+{ \ -+ struct symbol_cache *sc = data; \ -+ if (sc->addr) \ -+ fetch_memory_##type(regs, (void *)sc->addr, dest); \ -+ else \ -+ *(type *)dest = 0; \ -+} -+DEFINE_BASIC_FETCH_FUNCS(symbol) -+DEFINE_FETCH_symbol(string) -+DEFINE_FETCH_symbol(string_size) -+ -+/* Dereference memory access function */ -+struct deref_fetch_param { -+ struct fetch_param orig; -+ long offset; -+}; -+ -+#define DEFINE_FETCH_deref(type) \ -+static __kprobes void FETCH_FUNC_NAME(deref, type)(struct pt_regs *regs,\ -+ void *data, void *dest) \ -+{ \ -+ struct deref_fetch_param *dprm = data; \ -+ unsigned long addr; \ -+ call_fetch(&dprm->orig, regs, &addr); \ -+ if (addr) { \ -+ addr += dprm->offset; \ -+ fetch_memory_##type(regs, (void *)addr, dest); \ -+ } else \ -+ *(type *)dest = 0; \ -+} -+DEFINE_BASIC_FETCH_FUNCS(deref) -+DEFINE_FETCH_deref(string) -+DEFINE_FETCH_deref(string_size) -+ -+static __kprobes void update_deref_fetch_param(struct deref_fetch_param *data) -+{ -+ if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) -+ update_deref_fetch_param(data->orig.data); -+ else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) -+ update_symbol_cache(data->orig.data); -+} -+ -+static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data) -+{ -+ if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) -+ free_deref_fetch_param(data->orig.data); -+ else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) -+ free_symbol_cache(data->orig.data); -+ kfree(data); -+} -+ -+/* Bitfield fetch function */ -+struct bitfield_fetch_param { -+ struct fetch_param orig; -+ unsigned char hi_shift; -+ unsigned char low_shift; -+}; -+ -+#define DEFINE_FETCH_bitfield(type) \ -+static __kprobes void FETCH_FUNC_NAME(bitfield, type)(struct pt_regs *regs,\ -+ void *data, void *dest) \ -+{ \ -+ struct bitfield_fetch_param *bprm = data; \ -+ type buf = 0; \ -+ call_fetch(&bprm->orig, regs, &buf); \ -+ if (buf) { \ -+ buf <<= bprm->hi_shift; \ -+ buf >>= bprm->low_shift; \ -+ } \ -+ *(type *)dest = buf; \ -+} -+ -+DEFINE_BASIC_FETCH_FUNCS(bitfield) -+#define fetch_bitfield_string NULL -+#define fetch_bitfield_string_size NULL -+ -+static __kprobes void -+update_bitfield_fetch_param(struct bitfield_fetch_param *data) -+{ -+ /* -+ * Don't check the bitfield itself, because this must be the -+ * last fetch function. -+ */ -+ if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) -+ update_deref_fetch_param(data->orig.data); -+ else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) -+ update_symbol_cache(data->orig.data); -+} -+ -+static __kprobes void -+free_bitfield_fetch_param(struct bitfield_fetch_param *data) -+{ -+ /* -+ * Don't check the bitfield itself, because this must be the -+ * last fetch function. -+ */ -+ if (CHECK_FETCH_FUNCS(deref, data->orig.fn)) -+ free_deref_fetch_param(data->orig.data); -+ else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn)) -+ free_symbol_cache(data->orig.data); -+ -+ kfree(data); -+} -+ -+/* Default (unsigned long) fetch type */ -+#define __DEFAULT_FETCH_TYPE(t) u##t -+#define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t) -+#define DEFAULT_FETCH_TYPE _DEFAULT_FETCH_TYPE(BITS_PER_LONG) -+#define DEFAULT_FETCH_TYPE_STR __stringify(DEFAULT_FETCH_TYPE) -+ -+#define ASSIGN_FETCH_FUNC(method, type) \ -+ [FETCH_MTD_##method] = FETCH_FUNC_NAME(method, type) -+ -+#define __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, _fmttype) \ -+ {.name = _name, \ -+ .size = _size, \ -+ .is_signed = sign, \ -+ .print = PRINT_TYPE_FUNC_NAME(ptype), \ -+ .fmt = PRINT_TYPE_FMT_NAME(ptype), \ -+ .fmttype = _fmttype, \ -+ .fetch = { \ -+ASSIGN_FETCH_FUNC(reg, ftype), \ -+ASSIGN_FETCH_FUNC(stack, ftype), \ -+ASSIGN_FETCH_FUNC(retval, ftype), \ -+ASSIGN_FETCH_FUNC(memory, ftype), \ -+ASSIGN_FETCH_FUNC(symbol, ftype), \ -+ASSIGN_FETCH_FUNC(deref, ftype), \ -+ASSIGN_FETCH_FUNC(bitfield, ftype), \ -+ } \ -+ } -+ -+#define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \ -+ __ASSIGN_FETCH_TYPE(#ptype, ptype, ftype, sizeof(ftype), sign, #ptype) -+ -+#define FETCH_TYPE_STRING 0 -+#define FETCH_TYPE_STRSIZE 1 -+ -+/* Fetch type information table */ -+static const struct fetch_type fetch_type_table[] = { -+ /* Special types */ -+ [FETCH_TYPE_STRING] = __ASSIGN_FETCH_TYPE("string", string, string, -+ sizeof(u32), 1, "__data_loc char[]"), -+ [FETCH_TYPE_STRSIZE] = __ASSIGN_FETCH_TYPE("string_size", u32, -+ string_size, sizeof(u32), 0, "u32"), -+ /* Basic types */ -+ ASSIGN_FETCH_TYPE(u8, u8, 0), -+ ASSIGN_FETCH_TYPE(u16, u16, 0), -+ ASSIGN_FETCH_TYPE(u32, u32, 0), -+ ASSIGN_FETCH_TYPE(u64, u64, 0), -+ ASSIGN_FETCH_TYPE(s8, u8, 1), -+ ASSIGN_FETCH_TYPE(s16, u16, 1), -+ ASSIGN_FETCH_TYPE(s32, u32, 1), -+ ASSIGN_FETCH_TYPE(s64, u64, 1), -+}; -+ -+static const struct fetch_type *find_fetch_type(const char *type) -+{ -+ int i; -+ -+ if (!type) -+ type = DEFAULT_FETCH_TYPE_STR; -+ -+ /* Special case: bitfield */ -+ if (*type == 'b') { -+ unsigned long bs; -+ -+ type = strchr(type, '/'); -+ if (!type) -+ goto fail; -+ -+ type++; -+ if (strict_strtoul(type, 0, &bs)) -+ goto fail; -+ -+ switch (bs) { -+ case 8: -+ return find_fetch_type("u8"); -+ case 16: -+ return find_fetch_type("u16"); -+ case 32: -+ return find_fetch_type("u32"); -+ case 64: -+ return find_fetch_type("u64"); -+ default: -+ goto fail; -+ } -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++) -+ if (strcmp(type, fetch_type_table[i].name) == 0) -+ return &fetch_type_table[i]; -+ -+fail: -+ return NULL; -+} -+ -+/* Special function : only accept unsigned long */ -+static __kprobes void fetch_stack_address(struct pt_regs *regs, -+ void *dummy, void *dest) -+{ -+ *(unsigned long *)dest = kernel_stack_pointer(regs); -+} -+ -+static fetch_func_t get_fetch_size_function(const struct fetch_type *type, -+ fetch_func_t orig_fn) -+{ -+ int i; -+ -+ if (type != &fetch_type_table[FETCH_TYPE_STRING]) -+ return NULL; /* Only string type needs size function */ -+ -+ for (i = 0; i < FETCH_MTD_END; i++) -+ if (type->fetch[i] == orig_fn) -+ return fetch_type_table[FETCH_TYPE_STRSIZE].fetch[i]; -+ -+ WARN_ON(1); /* This should not happen */ -+ -+ return NULL; -+} -+ -+/* Split symbol and offset. */ -+int traceprobe_split_symbol_offset(char *symbol, unsigned long *offset) -+{ -+ char *tmp; -+ int ret; -+ -+ if (!offset) -+ return -EINVAL; -+ -+ tmp = strchr(symbol, '+'); -+ if (tmp) { -+ /* skip sign because strict_strtol doesn't accept '+' */ -+ ret = strict_strtoul(tmp + 1, 0, offset); -+ if (ret) -+ return ret; -+ -+ *tmp = '\0'; -+ } else -+ *offset = 0; -+ -+ return 0; -+} -+ -+#define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) -+ -+static int parse_probe_vars(char *arg, const struct fetch_type *t, -+ struct fetch_param *f, bool is_return) -+{ -+ int ret = 0; -+ unsigned long param; -+ -+ if (strcmp(arg, "retval") == 0) { -+ if (is_return) -+ f->fn = t->fetch[FETCH_MTD_retval]; -+ else -+ ret = -EINVAL; -+ } else if (strncmp(arg, "stack", 5) == 0) { -+ if (arg[5] == '\0') { -+ if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR) == 0) -+ f->fn = fetch_stack_address; -+ else -+ ret = -EINVAL; -+ } else if (isdigit(arg[5])) { -+ ret = strict_strtoul(arg + 5, 10, ¶m); -+ if (ret || param > PARAM_MAX_STACK) -+ ret = -EINVAL; -+ else { -+ f->fn = t->fetch[FETCH_MTD_stack]; -+ f->data = (void *)param; -+ } -+ } else -+ ret = -EINVAL; -+ } else -+ ret = -EINVAL; -+ -+ return ret; -+} -+ -+/* Recursive argument parser */ -+static int parse_probe_arg(char *arg, const struct fetch_type *t, -+ struct fetch_param *f, bool is_return, bool is_kprobe) -+{ -+ unsigned long param; -+ long offset; -+ char *tmp; -+ int ret; -+ -+ ret = 0; -+ -+ /* Until uprobe_events supports only reg arguments */ -+ if (!is_kprobe && arg[0] != '%') -+ return -EINVAL; -+ -+ switch (arg[0]) { -+ case '$': -+ ret = parse_probe_vars(arg + 1, t, f, is_return); -+ break; -+ -+ case '%': /* named register */ -+ ret = regs_query_register_offset(arg + 1); -+ if (ret >= 0) { -+ f->fn = t->fetch[FETCH_MTD_reg]; -+ f->data = (void *)(unsigned long)ret; -+ ret = 0; -+ } -+ break; -+ -+ case '@': /* memory or symbol */ -+ if (isdigit(arg[1])) { -+ ret = strict_strtoul(arg + 1, 0, ¶m); -+ if (ret) -+ break; -+ -+ f->fn = t->fetch[FETCH_MTD_memory]; -+ f->data = (void *)param; -+ } else { -+ ret = traceprobe_split_symbol_offset(arg + 1, &offset); -+ if (ret) -+ break; -+ -+ f->data = alloc_symbol_cache(arg + 1, offset); -+ if (f->data) -+ f->fn = t->fetch[FETCH_MTD_symbol]; -+ } -+ break; -+ -+ case '+': /* deref memory */ -+ arg++; /* Skip '+', because strict_strtol() rejects it. */ -+ case '-': -+ tmp = strchr(arg, '('); -+ if (!tmp) -+ break; -+ -+ *tmp = '\0'; -+ ret = strict_strtol(arg, 0, &offset); -+ -+ if (ret) -+ break; -+ -+ arg = tmp + 1; -+ tmp = strrchr(arg, ')'); -+ -+ if (tmp) { -+ struct deref_fetch_param *dprm; -+ const struct fetch_type *t2; -+ -+ t2 = find_fetch_type(NULL); -+ *tmp = '\0'; -+ dprm = kzalloc(sizeof(struct deref_fetch_param), GFP_KERNEL); -+ -+ if (!dprm) -+ return -ENOMEM; -+ -+ dprm->offset = offset; -+ ret = parse_probe_arg(arg, t2, &dprm->orig, is_return, -+ is_kprobe); -+ if (ret) -+ kfree(dprm); -+ else { -+ f->fn = t->fetch[FETCH_MTD_deref]; -+ f->data = (void *)dprm; -+ } -+ } -+ break; -+ } -+ if (!ret && !f->fn) { /* Parsed, but do not find fetch method */ -+ pr_info("%s type has no corresponding fetch method.\n", t->name); -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+#define BYTES_TO_BITS(nb) ((BITS_PER_LONG * (nb)) / sizeof(long)) -+ -+/* Bitfield type needs to be parsed into a fetch function */ -+static int __parse_bitfield_probe_arg(const char *bf, -+ const struct fetch_type *t, -+ struct fetch_param *f) -+{ -+ struct bitfield_fetch_param *bprm; -+ unsigned long bw, bo; -+ char *tail; -+ -+ if (*bf != 'b') -+ return 0; -+ -+ bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); -+ if (!bprm) -+ return -ENOMEM; -+ -+ bprm->orig = *f; -+ f->fn = t->fetch[FETCH_MTD_bitfield]; -+ f->data = (void *)bprm; -+ bw = simple_strtoul(bf + 1, &tail, 0); /* Use simple one */ -+ -+ if (bw == 0 || *tail != '@') -+ return -EINVAL; -+ -+ bf = tail + 1; -+ bo = simple_strtoul(bf, &tail, 0); -+ -+ if (tail == bf || *tail != '/') -+ return -EINVAL; -+ -+ bprm->hi_shift = BYTES_TO_BITS(t->size) - (bw + bo); -+ bprm->low_shift = bprm->hi_shift + bo; -+ -+ return (BYTES_TO_BITS(t->size) < (bw + bo)) ? -EINVAL : 0; -+} -+ -+/* String length checking wrapper */ -+int traceprobe_parse_probe_arg(char *arg, ssize_t *size, -+ struct probe_arg *parg, bool is_return, bool is_kprobe) -+{ -+ const char *t; -+ int ret; -+ -+ if (strlen(arg) > MAX_ARGSTR_LEN) { -+ pr_info("Argument is too long.: %s\n", arg); -+ return -ENOSPC; -+ } -+ parg->comm = kstrdup(arg, GFP_KERNEL); -+ if (!parg->comm) { -+ pr_info("Failed to allocate memory for command '%s'.\n", arg); -+ return -ENOMEM; -+ } -+ t = strchr(parg->comm, ':'); -+ if (t) { -+ arg[t - parg->comm] = '\0'; -+ t++; -+ } -+ parg->type = find_fetch_type(t); -+ if (!parg->type) { -+ pr_info("Unsupported type: %s\n", t); -+ return -EINVAL; -+ } -+ parg->offset = *size; -+ *size += parg->type->size; -+ ret = parse_probe_arg(arg, parg->type, &parg->fetch, is_return, is_kprobe); -+ -+ if (ret >= 0 && t != NULL) -+ ret = __parse_bitfield_probe_arg(t, parg->type, &parg->fetch); -+ -+ if (ret >= 0) { -+ parg->fetch_size.fn = get_fetch_size_function(parg->type, -+ parg->fetch.fn); -+ parg->fetch_size.data = parg->fetch.data; -+ } -+ -+ return ret; -+} -+ -+/* Return 1 if name is reserved or already used by another argument */ -+int traceprobe_conflict_field_name(const char *name, -+ struct probe_arg *args, int narg) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(reserved_field_names); i++) -+ if (strcmp(reserved_field_names[i], name) == 0) -+ return 1; -+ -+ for (i = 0; i < narg; i++) -+ if (strcmp(args[i].name, name) == 0) -+ return 1; -+ -+ return 0; -+} -+ -+void traceprobe_update_arg(struct probe_arg *arg) -+{ -+ if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn)) -+ update_bitfield_fetch_param(arg->fetch.data); -+ else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn)) -+ update_deref_fetch_param(arg->fetch.data); -+ else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn)) -+ update_symbol_cache(arg->fetch.data); -+} -+ -+void traceprobe_free_probe_arg(struct probe_arg *arg) -+{ -+ if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn)) -+ free_bitfield_fetch_param(arg->fetch.data); -+ else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn)) -+ free_deref_fetch_param(arg->fetch.data); -+ else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn)) -+ free_symbol_cache(arg->fetch.data); -+ -+ kfree(arg->name); -+ kfree(arg->comm); -+} -+ -+int traceprobe_command(const char *buf, int (*createfn)(int, char **)) -+{ -+ char **argv; -+ int argc, ret; -+ -+ argc = 0; -+ ret = 0; -+ argv = argv_split(GFP_KERNEL, buf, &argc); -+ if (!argv) -+ return -ENOMEM; -+ -+ if (argc) -+ ret = createfn(argc, argv); -+ -+ argv_free(argv); -+ -+ return ret; -+} -+ -+#define WRITE_BUFSIZE 4096 -+ -+ssize_t traceprobe_probes_write(struct file *file, const char __user *buffer, -+ size_t count, loff_t *ppos, -+ int (*createfn)(int, char **)) -+{ -+ char *kbuf, *tmp; -+ int ret = 0; -+ size_t done = 0; -+ size_t size; -+ -+ kbuf = kmalloc(WRITE_BUFSIZE, GFP_KERNEL); -+ if (!kbuf) -+ return -ENOMEM; -+ -+ while (done < count) { -+ size = count - done; -+ -+ if (size >= WRITE_BUFSIZE) -+ size = WRITE_BUFSIZE - 1; -+ -+ if (copy_from_user(kbuf, buffer + done, size)) { -+ ret = -EFAULT; -+ goto out; -+ } -+ kbuf[size] = '\0'; -+ tmp = strchr(kbuf, '\n'); -+ -+ if (tmp) { -+ *tmp = '\0'; -+ size = tmp - kbuf + 1; -+ } else if (done + size < count) { -+ pr_warning("Line length is too long: " -+ "Should be less than %d.", WRITE_BUFSIZE); -+ ret = -EINVAL; -+ goto out; -+ } -+ done += size; -+ /* Remove comments */ -+ tmp = strchr(kbuf, '#'); -+ -+ if (tmp) -+ *tmp = '\0'; -+ -+ ret = traceprobe_command(kbuf, createfn); -+ if (ret) -+ goto out; -+ } -+ ret = done; -+ -+out: -+ kfree(kbuf); -+ -+ return ret; -+} -diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h -new file mode 100644 -index 0000000..9337086 ---- /dev/null -+++ b/kernel/trace/trace_probe.h -@@ -0,0 +1,161 @@ -+/* -+ * Common header file for probe-based Dynamic events. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * This code was copied from kernel/trace/trace_kprobe.h written by -+ * Masami Hiramatsu -+ * -+ * Updates to make this generic: -+ * Copyright (C) IBM Corporation, 2010-2011 -+ * Author: Srikar Dronamraju -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "trace.h" -+#include "trace_output.h" -+ -+#define MAX_TRACE_ARGS 128 -+#define MAX_ARGSTR_LEN 63 -+#define MAX_EVENT_NAME_LEN 64 -+#define MAX_STRING_SIZE PATH_MAX -+ -+/* Reserved field names */ -+#define FIELD_STRING_IP "__probe_ip" -+#define FIELD_STRING_RETIP "__probe_ret_ip" -+#define FIELD_STRING_FUNC "__probe_func" -+ -+#undef DEFINE_FIELD -+#define DEFINE_FIELD(type, item, name, is_signed) \ -+ do { \ -+ ret = trace_define_field(event_call, #type, name, \ -+ offsetof(typeof(field), item), \ -+ sizeof(field.item), is_signed, \ -+ FILTER_OTHER); \ -+ if (ret) \ -+ return ret; \ -+ } while (0) -+ -+ -+/* Flags for trace_probe */ -+#define TP_FLAG_TRACE 1 -+#define TP_FLAG_PROFILE 2 -+#define TP_FLAG_REGISTERED 4 -+#define TP_FLAG_UPROBE 8 -+ -+ -+/* data_rloc: data relative location, compatible with u32 */ -+#define make_data_rloc(len, roffs) \ -+ (((u32)(len) << 16) | ((u32)(roffs) & 0xffff)) -+#define get_rloc_len(dl) ((u32)(dl) >> 16) -+#define get_rloc_offs(dl) ((u32)(dl) & 0xffff) -+ -+/* -+ * Convert data_rloc to data_loc: -+ * data_rloc stores the offset from data_rloc itself, but data_loc -+ * stores the offset from event entry. -+ */ -+#define convert_rloc_to_loc(dl, offs) ((u32)(dl) + (offs)) -+ -+/* Data fetch function type */ -+typedef void (*fetch_func_t)(struct pt_regs *, void *, void *); -+/* Printing function type */ -+typedef int (*print_type_func_t)(struct trace_seq *, const char *, void *, void *); -+ -+/* Fetch types */ -+enum { -+ FETCH_MTD_reg = 0, -+ FETCH_MTD_stack, -+ FETCH_MTD_retval, -+ FETCH_MTD_memory, -+ FETCH_MTD_symbol, -+ FETCH_MTD_deref, -+ FETCH_MTD_bitfield, -+ FETCH_MTD_END, -+}; -+ -+/* Fetch type information table */ -+struct fetch_type { -+ const char *name; /* Name of type */ -+ size_t size; /* Byte size of type */ -+ int is_signed; /* Signed flag */ -+ print_type_func_t print; /* Print functions */ -+ const char *fmt; /* Fromat string */ -+ const char *fmttype; /* Name in format file */ -+ /* Fetch functions */ -+ fetch_func_t fetch[FETCH_MTD_END]; -+}; -+ -+struct fetch_param { -+ fetch_func_t fn; -+ void *data; -+}; -+ -+struct probe_arg { -+ struct fetch_param fetch; -+ struct fetch_param fetch_size; -+ unsigned int offset; /* Offset from argument entry */ -+ const char *name; /* Name of this argument */ -+ const char *comm; /* Command of this argument */ -+ const struct fetch_type *type; /* Type of this argument */ -+}; -+ -+static inline __kprobes void call_fetch(struct fetch_param *fprm, -+ struct pt_regs *regs, void *dest) -+{ -+ return fprm->fn(regs, fprm->data, dest); -+} -+ -+/* Check the name is good for event/group/fields */ -+static inline int is_good_name(const char *name) -+{ -+ if (!isalpha(*name) && *name != '_') -+ return 0; -+ while (*++name != '\0') { -+ if (!isalpha(*name) && !isdigit(*name) && *name != '_') -+ return 0; -+ } -+ return 1; -+} -+ -+extern int traceprobe_parse_probe_arg(char *arg, ssize_t *size, -+ struct probe_arg *parg, bool is_return, bool is_kprobe); -+ -+extern int traceprobe_conflict_field_name(const char *name, -+ struct probe_arg *args, int narg); -+ -+extern void traceprobe_update_arg(struct probe_arg *arg); -+extern void traceprobe_free_probe_arg(struct probe_arg *arg); -+ -+extern int traceprobe_split_symbol_offset(char *symbol, unsigned long *offset); -+ -+extern ssize_t traceprobe_probes_write(struct file *file, -+ const char __user *buffer, size_t count, loff_t *ppos, -+ int (*createfn)(int, char**)); -+ -+extern int traceprobe_command(const char *buf, int (*createfn)(int, char**)); -diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c -new file mode 100644 -index 0000000..2b36ac6 ---- /dev/null -+++ b/kernel/trace/trace_uprobe.c -@@ -0,0 +1,788 @@ -+/* -+ * uprobes-based tracing events -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Copyright (C) IBM Corporation, 2010-2012 -+ * Author: Srikar Dronamraju -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include "trace_probe.h" -+ -+#define UPROBE_EVENT_SYSTEM "uprobes" -+ -+/* -+ * uprobe event core functions -+ */ -+struct trace_uprobe; -+struct uprobe_trace_consumer { -+ struct uprobe_consumer cons; -+ struct trace_uprobe *tu; -+}; -+ -+struct trace_uprobe { -+ struct list_head list; -+ struct ftrace_event_class class; -+ struct ftrace_event_call call; -+ struct uprobe_trace_consumer *consumer; -+ struct inode *inode; -+ char *filename; -+ unsigned long offset; -+ unsigned long nhit; -+ unsigned int flags; /* For TP_FLAG_* */ -+ ssize_t size; /* trace entry size */ -+ unsigned int nr_args; -+ struct probe_arg args[]; -+}; -+ -+#define SIZEOF_TRACE_UPROBE(n) \ -+ (offsetof(struct trace_uprobe, args) + \ -+ (sizeof(struct probe_arg) * (n))) -+ -+static int register_uprobe_event(struct trace_uprobe *tu); -+static void unregister_uprobe_event(struct trace_uprobe *tu); -+ -+static DEFINE_MUTEX(uprobe_lock); -+static LIST_HEAD(uprobe_list); -+ -+static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs); -+ -+/* -+ * Allocate new trace_uprobe and initialize it (including uprobes). -+ */ -+static struct trace_uprobe * -+alloc_trace_uprobe(const char *group, const char *event, int nargs) -+{ -+ struct trace_uprobe *tu; -+ -+ if (!event || !is_good_name(event)) -+ return ERR_PTR(-EINVAL); -+ -+ if (!group || !is_good_name(group)) -+ return ERR_PTR(-EINVAL); -+ -+ tu = kzalloc(SIZEOF_TRACE_UPROBE(nargs), GFP_KERNEL); -+ if (!tu) -+ return ERR_PTR(-ENOMEM); -+ -+ tu->call.class = &tu->class; -+ tu->call.name = kstrdup(event, GFP_KERNEL); -+ if (!tu->call.name) -+ goto error; -+ -+ tu->class.system = kstrdup(group, GFP_KERNEL); -+ if (!tu->class.system) -+ goto error; -+ -+ INIT_LIST_HEAD(&tu->list); -+ return tu; -+ -+error: -+ kfree(tu->call.name); -+ kfree(tu); -+ -+ return ERR_PTR(-ENOMEM); -+} -+ -+static void free_trace_uprobe(struct trace_uprobe *tu) -+{ -+ int i; -+ -+ for (i = 0; i < tu->nr_args; i++) -+ traceprobe_free_probe_arg(&tu->args[i]); -+ -+ iput(tu->inode); -+ kfree(tu->call.class->system); -+ kfree(tu->call.name); -+ kfree(tu->filename); -+ kfree(tu); -+} -+ -+static struct trace_uprobe *find_probe_event(const char *event, const char *group) -+{ -+ struct trace_uprobe *tu; -+ -+ list_for_each_entry(tu, &uprobe_list, list) -+ if (strcmp(tu->call.name, event) == 0 && -+ strcmp(tu->call.class->system, group) == 0) -+ return tu; -+ -+ return NULL; -+} -+ -+/* Unregister a trace_uprobe and probe_event: call with locking uprobe_lock */ -+static void unregister_trace_uprobe(struct trace_uprobe *tu) -+{ -+ list_del(&tu->list); -+ unregister_uprobe_event(tu); -+ free_trace_uprobe(tu); -+} -+ -+/* Register a trace_uprobe and probe_event */ -+static int register_trace_uprobe(struct trace_uprobe *tu) -+{ -+ struct trace_uprobe *old_tp; -+ int ret; -+ -+ mutex_lock(&uprobe_lock); -+ -+ /* register as an event */ -+ old_tp = find_probe_event(tu->call.name, tu->call.class->system); -+ if (old_tp) -+ /* delete old event */ -+ unregister_trace_uprobe(old_tp); -+ -+ ret = register_uprobe_event(tu); -+ if (ret) { -+ pr_warning("Failed to register probe event(%d)\n", ret); -+ goto end; -+ } -+ -+ list_add_tail(&tu->list, &uprobe_list); -+ -+end: -+ mutex_unlock(&uprobe_lock); -+ -+ return ret; -+} -+ -+/* -+ * Argument syntax: -+ * - Add uprobe: p[:[GRP/]EVENT] PATH:SYMBOL[+offs] [FETCHARGS] -+ * -+ * - Remove uprobe: -:[GRP/]EVENT -+ */ -+static int create_trace_uprobe(int argc, char **argv) -+{ -+ struct trace_uprobe *tu; -+ struct inode *inode; -+ char *arg, *event, *group, *filename; -+ char buf[MAX_EVENT_NAME_LEN]; -+ struct path path; -+ unsigned long offset; -+ bool is_delete; -+ int i, ret; -+ -+ inode = NULL; -+ ret = 0; -+ is_delete = false; -+ event = NULL; -+ group = NULL; -+ -+ /* argc must be >= 1 */ -+ if (argv[0][0] == '-') -+ is_delete = true; -+ else if (argv[0][0] != 'p') { -+ pr_info("Probe definition must be started with 'p', 'r' or" " '-'.\n"); -+ return -EINVAL; -+ } -+ -+ if (argv[0][1] == ':') { -+ event = &argv[0][2]; -+ arg = strchr(event, '/'); -+ -+ if (arg) { -+ group = event; -+ event = arg + 1; -+ event[-1] = '\0'; -+ -+ if (strlen(group) == 0) { -+ pr_info("Group name is not specified\n"); -+ return -EINVAL; -+ } -+ } -+ if (strlen(event) == 0) { -+ pr_info("Event name is not specified\n"); -+ return -EINVAL; -+ } -+ } -+ if (!group) -+ group = UPROBE_EVENT_SYSTEM; -+ -+ if (is_delete) { -+ if (!event) { -+ pr_info("Delete command needs an event name.\n"); -+ return -EINVAL; -+ } -+ mutex_lock(&uprobe_lock); -+ tu = find_probe_event(event, group); -+ -+ if (!tu) { -+ mutex_unlock(&uprobe_lock); -+ pr_info("Event %s/%s doesn't exist.\n", group, event); -+ return -ENOENT; -+ } -+ /* delete an event */ -+ unregister_trace_uprobe(tu); -+ mutex_unlock(&uprobe_lock); -+ return 0; -+ } -+ -+ if (argc < 2) { -+ pr_info("Probe point is not specified.\n"); -+ return -EINVAL; -+ } -+ if (isdigit(argv[1][0])) { -+ pr_info("probe point must be have a filename.\n"); -+ return -EINVAL; -+ } -+ arg = strchr(argv[1], ':'); -+ if (!arg) -+ goto fail_address_parse; -+ -+ *arg++ = '\0'; -+ filename = argv[1]; -+ ret = kern_path(filename, LOOKUP_FOLLOW, &path); -+ if (ret) -+ goto fail_address_parse; -+ -+ ret = strict_strtoul(arg, 0, &offset); -+ if (ret) -+ goto fail_address_parse; -+ -+ inode = igrab(path.dentry->d_inode); -+ -+ argc -= 2; -+ argv += 2; -+ -+ /* setup a probe */ -+ if (!event) { -+ char *tail = strrchr(filename, '/'); -+ char *ptr; -+ -+ ptr = kstrdup((tail ? tail + 1 : filename), GFP_KERNEL); -+ if (!ptr) { -+ ret = -ENOMEM; -+ goto fail_address_parse; -+ } -+ -+ tail = ptr; -+ ptr = strpbrk(tail, ".-_"); -+ if (ptr) -+ *ptr = '\0'; -+ -+ snprintf(buf, MAX_EVENT_NAME_LEN, "%c_%s_0x%lx", 'p', tail, offset); -+ event = buf; -+ kfree(tail); -+ } -+ -+ tu = alloc_trace_uprobe(group, event, argc); -+ if (IS_ERR(tu)) { -+ pr_info("Failed to allocate trace_uprobe.(%d)\n", (int)PTR_ERR(tu)); -+ ret = PTR_ERR(tu); -+ goto fail_address_parse; -+ } -+ tu->offset = offset; -+ tu->inode = inode; -+ tu->filename = kstrdup(filename, GFP_KERNEL); -+ -+ if (!tu->filename) { -+ pr_info("Failed to allocate filename.\n"); -+ ret = -ENOMEM; -+ goto error; -+ } -+ -+ /* parse arguments */ -+ ret = 0; -+ for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { -+ /* Increment count for freeing args in error case */ -+ tu->nr_args++; -+ -+ /* Parse argument name */ -+ arg = strchr(argv[i], '='); -+ if (arg) { -+ *arg++ = '\0'; -+ tu->args[i].name = kstrdup(argv[i], GFP_KERNEL); -+ } else { -+ arg = argv[i]; -+ /* If argument name is omitted, set "argN" */ -+ snprintf(buf, MAX_EVENT_NAME_LEN, "arg%d", i + 1); -+ tu->args[i].name = kstrdup(buf, GFP_KERNEL); -+ } -+ -+ if (!tu->args[i].name) { -+ pr_info("Failed to allocate argument[%d] name.\n", i); -+ ret = -ENOMEM; -+ goto error; -+ } -+ -+ if (!is_good_name(tu->args[i].name)) { -+ pr_info("Invalid argument[%d] name: %s\n", i, tu->args[i].name); -+ ret = -EINVAL; -+ goto error; -+ } -+ -+ if (traceprobe_conflict_field_name(tu->args[i].name, tu->args, i)) { -+ pr_info("Argument[%d] name '%s' conflicts with " -+ "another field.\n", i, argv[i]); -+ ret = -EINVAL; -+ goto error; -+ } -+ -+ /* Parse fetch argument */ -+ ret = traceprobe_parse_probe_arg(arg, &tu->size, &tu->args[i], false, false); -+ if (ret) { -+ pr_info("Parse error at argument[%d]. (%d)\n", i, ret); -+ goto error; -+ } -+ } -+ -+ ret = register_trace_uprobe(tu); -+ if (ret) -+ goto error; -+ return 0; -+ -+error: -+ free_trace_uprobe(tu); -+ return ret; -+ -+fail_address_parse: -+ if (inode) -+ iput(inode); -+ -+ pr_info("Failed to parse address.\n"); -+ -+ return ret; -+} -+ -+static void cleanup_all_probes(void) -+{ -+ struct trace_uprobe *tu; -+ -+ mutex_lock(&uprobe_lock); -+ while (!list_empty(&uprobe_list)) { -+ tu = list_entry(uprobe_list.next, struct trace_uprobe, list); -+ unregister_trace_uprobe(tu); -+ } -+ mutex_unlock(&uprobe_lock); -+} -+ -+/* Probes listing interfaces */ -+static void *probes_seq_start(struct seq_file *m, loff_t *pos) -+{ -+ mutex_lock(&uprobe_lock); -+ return seq_list_start(&uprobe_list, *pos); -+} -+ -+static void *probes_seq_next(struct seq_file *m, void *v, loff_t *pos) -+{ -+ return seq_list_next(v, &uprobe_list, pos); -+} -+ -+static void probes_seq_stop(struct seq_file *m, void *v) -+{ -+ mutex_unlock(&uprobe_lock); -+} -+ -+static int probes_seq_show(struct seq_file *m, void *v) -+{ -+ struct trace_uprobe *tu = v; -+ int i; -+ -+ seq_printf(m, "p:%s/%s", tu->call.class->system, tu->call.name); -+ seq_printf(m, " %s:0x%p", tu->filename, (void *)tu->offset); -+ -+ for (i = 0; i < tu->nr_args; i++) -+ seq_printf(m, " %s=%s", tu->args[i].name, tu->args[i].comm); -+ -+ seq_printf(m, "\n"); -+ return 0; -+} -+ -+static const struct seq_operations probes_seq_op = { -+ .start = probes_seq_start, -+ .next = probes_seq_next, -+ .stop = probes_seq_stop, -+ .show = probes_seq_show -+}; -+ -+static int probes_open(struct inode *inode, struct file *file) -+{ -+ if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) -+ cleanup_all_probes(); -+ -+ return seq_open(file, &probes_seq_op); -+} -+ -+static ssize_t probes_write(struct file *file, const char __user *buffer, -+ size_t count, loff_t *ppos) -+{ -+ return traceprobe_probes_write(file, buffer, count, ppos, create_trace_uprobe); -+} -+ -+static const struct file_operations uprobe_events_ops = { -+ .owner = THIS_MODULE, -+ .open = probes_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = seq_release, -+ .write = probes_write, -+}; -+ -+/* Probes profiling interfaces */ -+static int probes_profile_seq_show(struct seq_file *m, void *v) -+{ -+ struct trace_uprobe *tu = v; -+ -+ seq_printf(m, " %s %-44s %15lu\n", tu->filename, tu->call.name, tu->nhit); -+ return 0; -+} -+ -+static const struct seq_operations profile_seq_op = { -+ .start = probes_seq_start, -+ .next = probes_seq_next, -+ .stop = probes_seq_stop, -+ .show = probes_profile_seq_show -+}; -+ -+static int profile_open(struct inode *inode, struct file *file) -+{ -+ return seq_open(file, &profile_seq_op); -+} -+ -+static const struct file_operations uprobe_profile_ops = { -+ .owner = THIS_MODULE, -+ .open = profile_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = seq_release, -+}; -+ -+/* uprobe handler */ -+static void uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs) -+{ -+ struct uprobe_trace_entry_head *entry; -+ struct ring_buffer_event *event; -+ struct ring_buffer *buffer; -+ u8 *data; -+ int size, i, pc; -+ unsigned long irq_flags; -+ struct ftrace_event_call *call = &tu->call; -+ -+ tu->nhit++; -+ -+ local_save_flags(irq_flags); -+ pc = preempt_count(); -+ -+ size = sizeof(*entry) + tu->size; -+ -+ event = trace_current_buffer_lock_reserve(&buffer, call->event.type, -+ size, irq_flags, pc); -+ if (!event) -+ return; -+ -+ entry = ring_buffer_event_data(event); -+ entry->ip = uprobe_get_swbp_addr(task_pt_regs(current)); -+ data = (u8 *)&entry[1]; -+ for (i = 0; i < tu->nr_args; i++) -+ call_fetch(&tu->args[i].fetch, regs, data + tu->args[i].offset); -+ -+ if (!filter_current_check_discard(buffer, call, entry, event)) -+ trace_buffer_unlock_commit(buffer, event, irq_flags, pc); -+} -+ -+/* Event entry printers */ -+static enum print_line_t -+print_uprobe_event(struct trace_iterator *iter, int flags, struct trace_event *event) -+{ -+ struct uprobe_trace_entry_head *field; -+ struct trace_seq *s = &iter->seq; -+ struct trace_uprobe *tu; -+ u8 *data; -+ int i; -+ -+ field = (struct uprobe_trace_entry_head *)iter->ent; -+ tu = container_of(event, struct trace_uprobe, call.event); -+ -+ if (!trace_seq_printf(s, "%s: (", tu->call.name)) -+ goto partial; -+ -+ if (!seq_print_ip_sym(s, field->ip, flags | TRACE_ITER_SYM_OFFSET)) -+ goto partial; -+ -+ if (!trace_seq_puts(s, ")")) -+ goto partial; -+ -+ data = (u8 *)&field[1]; -+ for (i = 0; i < tu->nr_args; i++) { -+ if (!tu->args[i].type->print(s, tu->args[i].name, -+ data + tu->args[i].offset, field)) -+ goto partial; -+ } -+ -+ if (trace_seq_puts(s, "\n")) -+ return TRACE_TYPE_HANDLED; -+ -+partial: -+ return TRACE_TYPE_PARTIAL_LINE; -+} -+ -+static int probe_event_enable(struct trace_uprobe *tu, int flag) -+{ -+ struct uprobe_trace_consumer *utc; -+ int ret = 0; -+ -+ if (!tu->inode || tu->consumer) -+ return -EINTR; -+ -+ utc = kzalloc(sizeof(struct uprobe_trace_consumer), GFP_KERNEL); -+ if (!utc) -+ return -EINTR; -+ -+ utc->cons.handler = uprobe_dispatcher; -+ utc->cons.filter = NULL; -+ ret = uprobe_register(tu->inode, tu->offset, &utc->cons); -+ if (ret) { -+ kfree(utc); -+ return ret; -+ } -+ -+ tu->flags |= flag; -+ utc->tu = tu; -+ tu->consumer = utc; -+ -+ return 0; -+} -+ -+static void probe_event_disable(struct trace_uprobe *tu, int flag) -+{ -+ if (!tu->inode || !tu->consumer) -+ return; -+ -+ uprobe_unregister(tu->inode, tu->offset, &tu->consumer->cons); -+ tu->flags &= ~flag; -+ kfree(tu->consumer); -+ tu->consumer = NULL; -+} -+ -+static int uprobe_event_define_fields(struct ftrace_event_call *event_call) -+{ -+ int ret, i; -+ struct uprobe_trace_entry_head field; -+ struct trace_uprobe *tu = (struct trace_uprobe *)event_call->data; -+ -+ DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); -+ /* Set argument names as fields */ -+ for (i = 0; i < tu->nr_args; i++) { -+ ret = trace_define_field(event_call, tu->args[i].type->fmttype, -+ tu->args[i].name, -+ sizeof(field) + tu->args[i].offset, -+ tu->args[i].type->size, -+ tu->args[i].type->is_signed, -+ FILTER_OTHER); -+ -+ if (ret) -+ return ret; -+ } -+ return 0; -+} -+ -+#define LEN_OR_ZERO (len ? len - pos : 0) -+static int __set_print_fmt(struct trace_uprobe *tu, char *buf, int len) -+{ -+ const char *fmt, *arg; -+ int i; -+ int pos = 0; -+ -+ fmt = "(%lx)"; -+ arg = "REC->" FIELD_STRING_IP; -+ -+ /* When len=0, we just calculate the needed length */ -+ -+ pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt); -+ -+ for (i = 0; i < tu->nr_args; i++) { -+ pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%s", -+ tu->args[i].name, tu->args[i].type->fmt); -+ } -+ -+ pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg); -+ -+ for (i = 0; i < tu->nr_args; i++) { -+ pos += snprintf(buf + pos, LEN_OR_ZERO, ", REC->%s", -+ tu->args[i].name); -+ } -+ -+ return pos; /* return the length of print_fmt */ -+} -+#undef LEN_OR_ZERO -+ -+static int set_print_fmt(struct trace_uprobe *tu) -+{ -+ char *print_fmt; -+ int len; -+ -+ /* First: called with 0 length to calculate the needed length */ -+ len = __set_print_fmt(tu, NULL, 0); -+ print_fmt = kmalloc(len + 1, GFP_KERNEL); -+ if (!print_fmt) -+ return -ENOMEM; -+ -+ /* Second: actually write the @print_fmt */ -+ __set_print_fmt(tu, print_fmt, len + 1); -+ tu->call.print_fmt = print_fmt; -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PERF_EVENTS -+/* uprobe profile handler */ -+static void uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs) -+{ -+ struct ftrace_event_call *call = &tu->call; -+ struct uprobe_trace_entry_head *entry; -+ struct hlist_head *head; -+ u8 *data; -+ int size, __size, i; -+ int rctx; -+ -+ __size = sizeof(*entry) + tu->size; -+ size = ALIGN(__size + sizeof(u32), sizeof(u64)); -+ size -= sizeof(u32); -+ if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, "profile buffer not large enough")) -+ return; -+ -+ preempt_disable(); -+ -+ entry = perf_trace_buf_prepare(size, call->event.type, regs, &rctx); -+ if (!entry) -+ goto out; -+ -+ entry->ip = uprobe_get_swbp_addr(task_pt_regs(current)); -+ data = (u8 *)&entry[1]; -+ for (i = 0; i < tu->nr_args; i++) -+ call_fetch(&tu->args[i].fetch, regs, data + tu->args[i].offset); -+ -+ head = this_cpu_ptr(call->perf_events); -+ perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head); -+ -+ out: -+ preempt_enable(); -+} -+#endif /* CONFIG_PERF_EVENTS */ -+ -+static -+int trace_uprobe_register(struct ftrace_event_call *event, enum trace_reg type, void *data) -+{ -+ struct trace_uprobe *tu = (struct trace_uprobe *)event->data; -+ -+ switch (type) { -+ case TRACE_REG_REGISTER: -+ return probe_event_enable(tu, TP_FLAG_TRACE); -+ -+ case TRACE_REG_UNREGISTER: -+ probe_event_disable(tu, TP_FLAG_TRACE); -+ return 0; -+ -+#ifdef CONFIG_PERF_EVENTS -+ case TRACE_REG_PERF_REGISTER: -+ return probe_event_enable(tu, TP_FLAG_PROFILE); -+ -+ case TRACE_REG_PERF_UNREGISTER: -+ probe_event_disable(tu, TP_FLAG_PROFILE); -+ return 0; -+#endif -+ default: -+ return 0; -+ } -+ return 0; -+} -+ -+static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs) -+{ -+ struct uprobe_trace_consumer *utc; -+ struct trace_uprobe *tu; -+ -+ utc = container_of(con, struct uprobe_trace_consumer, cons); -+ tu = utc->tu; -+ if (!tu || tu->consumer != utc) -+ return 0; -+ -+ if (tu->flags & TP_FLAG_TRACE) -+ uprobe_trace_func(tu, regs); -+ -+#ifdef CONFIG_PERF_EVENTS -+ if (tu->flags & TP_FLAG_PROFILE) -+ uprobe_perf_func(tu, regs); -+#endif -+ return 0; -+} -+ -+static struct trace_event_functions uprobe_funcs = { -+ .trace = print_uprobe_event -+}; -+ -+static int register_uprobe_event(struct trace_uprobe *tu) -+{ -+ struct ftrace_event_call *call = &tu->call; -+ int ret; -+ -+ /* Initialize ftrace_event_call */ -+ INIT_LIST_HEAD(&call->class->fields); -+ call->event.funcs = &uprobe_funcs; -+ call->class->define_fields = uprobe_event_define_fields; -+ -+ if (set_print_fmt(tu) < 0) -+ return -ENOMEM; -+ -+ ret = register_ftrace_event(&call->event); -+ if (!ret) { -+ kfree(call->print_fmt); -+ return -ENODEV; -+ } -+ call->flags = 0; -+ call->class->reg = trace_uprobe_register; -+ call->data = tu; -+ ret = trace_add_event_call(call); -+ -+ if (ret) { -+ pr_info("Failed to register uprobe event: %s\n", call->name); -+ kfree(call->print_fmt); -+ unregister_ftrace_event(&call->event); -+ } -+ -+ return ret; -+} -+ -+static void unregister_uprobe_event(struct trace_uprobe *tu) -+{ -+ /* tu->event is unregistered in trace_remove_event_call() */ -+ trace_remove_event_call(&tu->call); -+ kfree(tu->call.print_fmt); -+ tu->call.print_fmt = NULL; -+} -+ -+/* Make a trace interface for controling probe points */ -+static __init int init_uprobe_trace(void) -+{ -+ struct dentry *d_tracer; -+ -+ d_tracer = tracing_init_dentry(); -+ if (!d_tracer) -+ return 0; -+ -+ trace_create_file("uprobe_events", 0644, d_tracer, -+ NULL, &uprobe_events_ops); -+ /* Profile interface */ -+ trace_create_file("uprobe_profile", 0444, d_tracer, -+ NULL, &uprobe_profile_ops); -+ return 0; -+} -+ -+fs_initcall(init_uprobe_trace); -diff --git a/mm/memory.c b/mm/memory.c -index 6105f47..bf8b403 100644 ---- a/mm/memory.c -+++ b/mm/memory.c -@@ -1307,6 +1307,9 @@ static void unmap_single_vma(struct mmu_gather *tlb, - if (end <= vma->vm_start) - return; - -+ if (vma->vm_file) -+ uprobe_munmap(vma, start, end); -+ - if (vma->vm_flags & VM_ACCOUNT) - *nr_accounted += (end - start) >> PAGE_SHIFT; - -diff --git a/mm/mmap.c b/mm/mmap.c -index 848ef52..b8c4072 100644 ---- a/mm/mmap.c -+++ b/mm/mmap.c -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -546,8 +547,15 @@ again: remove_next = 1 + (end > next->vm_end); - - if (file) { - mapping = file->f_mapping; -- if (!(vma->vm_flags & VM_NONLINEAR)) -+ if (!(vma->vm_flags & VM_NONLINEAR)) { - root = &mapping->i_mmap; -+ uprobe_munmap(vma, vma->vm_start, vma->vm_end); -+ -+ if (adjust_next) -+ uprobe_munmap(next, next->vm_start, -+ next->vm_end); -+ } -+ - mutex_lock(&mapping->i_mmap_mutex); - if (insert) { - /* -@@ -617,8 +625,16 @@ again: remove_next = 1 + (end > next->vm_end); - if (mapping) - mutex_unlock(&mapping->i_mmap_mutex); - -+ if (root) { -+ uprobe_mmap(vma); -+ -+ if (adjust_next) -+ uprobe_mmap(next); -+ } -+ - if (remove_next) { - if (file) { -+ uprobe_munmap(next, next->vm_start, next->vm_end); - fput(file); - if (next->vm_flags & VM_EXECUTABLE) - removed_exe_file_vma(mm); -@@ -638,6 +654,8 @@ again: remove_next = 1 + (end > next->vm_end); - goto again; - } - } -+ if (insert && file) -+ uprobe_mmap(insert); - - validate_mm(mm); - -@@ -1371,6 +1389,11 @@ out: - mm->locked_vm += (len >> PAGE_SHIFT); - } else if ((flags & MAP_POPULATE) && !(flags & MAP_NONBLOCK)) - make_pages_present(addr, addr + len); -+ -+ if (file && uprobe_mmap(vma)) -+ /* matching probes but cannot insert */ -+ goto unmap_and_free_vma; -+ - return addr; - - unmap_and_free_vma: -@@ -2352,6 +2375,10 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) - if ((vma->vm_flags & VM_ACCOUNT) && - security_vm_enough_memory_mm(mm, vma_pages(vma))) - return -ENOMEM; -+ -+ if (vma->vm_file && uprobe_mmap(vma)) -+ return -EINVAL; -+ - vma_link(mm, vma, prev, rb_link, rb_parent); - return 0; - } -@@ -2421,6 +2448,10 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, - new_vma->vm_pgoff = pgoff; - if (new_vma->vm_file) { - get_file(new_vma->vm_file); -+ -+ if (uprobe_mmap(new_vma)) -+ goto out_free_mempol; -+ - if (vma->vm_flags & VM_EXECUTABLE) - added_exe_file_vma(mm); - } -diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt -index 2780d9c..b715cb7 100644 ---- a/tools/perf/Documentation/perf-probe.txt -+++ b/tools/perf/Documentation/perf-probe.txt -@@ -77,7 +77,8 @@ OPTIONS - - -F:: - --funcs:: -- Show available functions in given module or kernel. -+ Show available functions in given module or kernel. With -x/--exec, -+ can also list functions in a user space executable / shared library. - - --filter=FILTER:: - (Only for --vars and --funcs) Set filter. FILTER is a combination of glob -@@ -98,6 +99,15 @@ OPTIONS - --max-probes:: - Set the maximum number of probe points for an event. Default is 128. - -+-x:: -+--exec=PATH:: -+ Specify path to the executable or shared library file for user -+ space tracing. Can also be used with --funcs option. -+ -+In absence of -m/-x options, perf probe checks if the first argument after -+the options is an absolute path name. If its an absolute path, perf probe -+uses it as a target module/target user space binary to probe. -+ - PROBE SYNTAX - ------------ - Probe points are defined by following syntax. -@@ -182,6 +192,13 @@ Delete all probes on schedule(). - - ./perf probe --del='schedule*' - -+Add probes at zfree() function on /bin/zsh -+ -+ ./perf probe -x /bin/zsh zfree or ./perf probe /bin/zsh zfree -+ -+Add probes at malloc() function on libc -+ -+ ./perf probe -x /lib/libc.so.6 malloc or ./perf probe /lib/libc.so.6 malloc - - SEE ALSO - -------- -diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c -index 4935c09..e215ae6 100644 ---- a/tools/perf/builtin-probe.c -+++ b/tools/perf/builtin-probe.c -@@ -54,6 +54,7 @@ static struct { - bool show_ext_vars; - bool show_funcs; - bool mod_events; -+ bool uprobes; - int nevents; - struct perf_probe_event events[MAX_PROBES]; - struct strlist *dellist; -@@ -75,6 +76,8 @@ static int parse_probe_event(const char *str) - return -1; - } - -+ pev->uprobes = params.uprobes; -+ - /* Parse a perf-probe command into event */ - ret = parse_perf_probe_command(str, pev); - pr_debug("%d arguments\n", pev->nargs); -@@ -82,21 +85,58 @@ static int parse_probe_event(const char *str) - return ret; - } - -+static int set_target(const char *ptr) -+{ -+ int found = 0; -+ const char *buf; -+ -+ /* -+ * The first argument after options can be an absolute path -+ * to an executable / library or kernel module. -+ * -+ * TODO: Support relative path, and $PATH, $LD_LIBRARY_PATH, -+ * short module name. -+ */ -+ if (!params.target && ptr && *ptr == '/') { -+ params.target = ptr; -+ found = 1; -+ buf = ptr + (strlen(ptr) - 3); -+ -+ if (strcmp(buf, ".ko")) -+ params.uprobes = true; -+ -+ } -+ -+ return found; -+} -+ - static int parse_probe_event_argv(int argc, const char **argv) - { -- int i, len, ret; -+ int i, len, ret, found_target; - char *buf; - -+ found_target = set_target(argv[0]); -+ if (found_target && argc == 1) -+ return 0; -+ - /* Bind up rest arguments */ - len = 0; -- for (i = 0; i < argc; i++) -+ for (i = 0; i < argc; i++) { -+ if (i == 0 && found_target) -+ continue; -+ - len += strlen(argv[i]) + 1; -+ } - buf = zalloc(len + 1); - if (buf == NULL) - return -ENOMEM; - len = 0; -- for (i = 0; i < argc; i++) -+ for (i = 0; i < argc; i++) { -+ if (i == 0 && found_target) -+ continue; -+ - len += sprintf(&buf[len], "%s ", argv[i]); -+ } - params.mod_events = true; - ret = parse_probe_event(buf); - free(buf); -@@ -125,6 +165,28 @@ static int opt_del_probe_event(const struct option *opt __used, - return 0; - } - -+static int opt_set_target(const struct option *opt, const char *str, -+ int unset __used) -+{ -+ int ret = -ENOENT; -+ -+ if (str && !params.target) { -+ if (!strcmp(opt->long_name, "exec")) -+ params.uprobes = true; -+#ifdef DWARF_SUPPORT -+ else if (!strcmp(opt->long_name, "module")) -+ params.uprobes = false; -+#endif -+ else -+ return ret; -+ -+ params.target = str; -+ ret = 0; -+ } -+ -+ return ret; -+} -+ - #ifdef DWARF_SUPPORT - static int opt_show_lines(const struct option *opt __used, - const char *str, int unset __used) -@@ -246,9 +308,9 @@ static const struct option options[] = { - "file", "vmlinux pathname"), - OPT_STRING('s', "source", &symbol_conf.source_prefix, - "directory", "path to kernel source"), -- OPT_STRING('m', "module", ¶ms.target, -- "modname|path", -- "target module name (for online) or path (for offline)"), -+ OPT_CALLBACK('m', "module", NULL, "modname|path", -+ "target module name (for online) or path (for offline)", -+ opt_set_target), - #endif - OPT__DRY_RUN(&probe_event_dry_run), - OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, -@@ -260,6 +322,8 @@ static const struct option options[] = { - "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n" - "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)", - opt_set_filter), -+ OPT_CALLBACK('x', "exec", NULL, "executable|path", -+ "target executable name or path", opt_set_target), - OPT_END() - }; - -@@ -310,6 +374,10 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) - pr_err(" Error: Don't use --list with --funcs.\n"); - usage_with_options(probe_usage, options); - } -+ if (params.uprobes) { -+ pr_warning(" Error: Don't use --list with --exec.\n"); -+ usage_with_options(probe_usage, options); -+ } - ret = show_perf_probe_events(); - if (ret < 0) - pr_err(" Error: Failed to show event list. (%d)\n", -@@ -333,8 +401,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) - if (!params.filter) - params.filter = strfilter__new(DEFAULT_FUNC_FILTER, - NULL); -- ret = show_available_funcs(params.target, -- params.filter); -+ ret = show_available_funcs(params.target, params.filter, -+ params.uprobes); - strfilter__delete(params.filter); - if (ret < 0) - pr_err(" Error: Failed to show functions." -@@ -343,7 +411,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) - } - - #ifdef DWARF_SUPPORT -- if (params.show_lines) { -+ if (params.show_lines && !params.uprobes) { - if (params.mod_events) { - pr_err(" Error: Don't use --line with" - " --add/--del.\n"); -diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c -index 8a8ee64..0dda25d 100644 ---- a/tools/perf/util/probe-event.c -+++ b/tools/perf/util/probe-event.c -@@ -44,6 +44,7 @@ - #include "trace-event.h" /* For __unused */ - #include "probe-event.h" - #include "probe-finder.h" -+#include "session.h" - - #define MAX_CMDLEN 256 - #define MAX_PROBE_ARGS 128 -@@ -70,6 +71,8 @@ static int e_snprintf(char *str, size_t size, const char *format, ...) - } - - static char *synthesize_perf_probe_point(struct perf_probe_point *pp); -+static int convert_name_to_addr(struct perf_probe_event *pev, -+ const char *exec); - static struct machine machine; - - /* Initialize symbol maps and path of vmlinux/modules */ -@@ -170,6 +173,34 @@ const char *kernel_get_module_path(const char *module) - return (dso) ? dso->long_name : NULL; - } - -+static int init_user_exec(void) -+{ -+ int ret = 0; -+ -+ symbol_conf.try_vmlinux_path = false; -+ symbol_conf.sort_by_name = true; -+ ret = symbol__init(); -+ -+ if (ret < 0) -+ pr_debug("Failed to init symbol map.\n"); -+ -+ return ret; -+} -+ -+static int convert_to_perf_probe_point(struct probe_trace_point *tp, -+ struct perf_probe_point *pp) -+{ -+ pp->function = strdup(tp->symbol); -+ -+ if (pp->function == NULL) -+ return -ENOMEM; -+ -+ pp->offset = tp->offset; -+ pp->retprobe = tp->retprobe; -+ -+ return 0; -+} -+ - #ifdef DWARF_SUPPORT - /* Open new debuginfo of given module */ - static struct debuginfo *open_debuginfo(const char *module) -@@ -224,10 +255,7 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, - if (ret <= 0) { - pr_debug("Failed to find corresponding probes from " - "debuginfo. Use kprobe event information.\n"); -- pp->function = strdup(tp->symbol); -- if (pp->function == NULL) -- return -ENOMEM; -- pp->offset = tp->offset; -+ return convert_to_perf_probe_point(tp, pp); - } - pp->retprobe = tp->retprobe; - -@@ -275,9 +303,20 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, - int max_tevs, const char *target) - { - bool need_dwarf = perf_probe_event_need_dwarf(pev); -- struct debuginfo *dinfo = open_debuginfo(target); -+ struct debuginfo *dinfo; - int ntevs, ret = 0; - -+ if (pev->uprobes) { -+ if (need_dwarf) { -+ pr_warning("Debuginfo-analysis is not yet supported" -+ " with -x/--exec option.\n"); -+ return -ENOSYS; -+ } -+ return convert_name_to_addr(pev, target); -+ } -+ -+ dinfo = open_debuginfo(target); -+ - if (!dinfo) { - if (need_dwarf) { - pr_warning("Failed to open debuginfo file.\n"); -@@ -603,23 +642,22 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, - pr_err("Failed to find symbol %s in kernel.\n", tp->symbol); - return -ENOENT; - } -- pp->function = strdup(tp->symbol); -- if (pp->function == NULL) -- return -ENOMEM; -- pp->offset = tp->offset; -- pp->retprobe = tp->retprobe; - -- return 0; -+ return convert_to_perf_probe_point(tp, pp); - } - - static int try_to_find_probe_trace_events(struct perf_probe_event *pev, - struct probe_trace_event **tevs __unused, -- int max_tevs __unused, const char *mod __unused) -+ int max_tevs __unused, const char *target) - { - if (perf_probe_event_need_dwarf(pev)) { - pr_warning("Debuginfo-analysis is not supported.\n"); - return -ENOSYS; - } -+ -+ if (pev->uprobes) -+ return convert_name_to_addr(pev, target); -+ - return 0; - } - -@@ -1341,11 +1379,18 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev) - if (buf == NULL) - return NULL; - -- len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu", -- tp->retprobe ? 'r' : 'p', -- tev->group, tev->event, -- tp->module ?: "", tp->module ? ":" : "", -- tp->symbol, tp->offset); -+ if (tev->uprobes) -+ len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s:%s", -+ tp->retprobe ? 'r' : 'p', -+ tev->group, tev->event, -+ tp->module, tp->symbol); -+ else -+ len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu", -+ tp->retprobe ? 'r' : 'p', -+ tev->group, tev->event, -+ tp->module ?: "", tp->module ? ":" : "", -+ tp->symbol, tp->offset); -+ - if (len <= 0) - goto error; - -@@ -1364,7 +1409,7 @@ error: - } - - static int convert_to_perf_probe_event(struct probe_trace_event *tev, -- struct perf_probe_event *pev) -+ struct perf_probe_event *pev, bool is_kprobe) - { - char buf[64] = ""; - int i, ret; -@@ -1376,7 +1421,11 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev, - return -ENOMEM; - - /* Convert trace_point to probe_point */ -- ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point); -+ if (is_kprobe) -+ ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point); -+ else -+ ret = convert_to_perf_probe_point(&tev->point, &pev->point); -+ - if (ret < 0) - return ret; - -@@ -1472,7 +1521,26 @@ static void clear_probe_trace_event(struct probe_trace_event *tev) - memset(tev, 0, sizeof(*tev)); - } - --static int open_kprobe_events(bool readwrite) -+static void print_warn_msg(const char *file, bool is_kprobe) -+{ -+ -+ if (errno == ENOENT) { -+ const char *config; -+ -+ if (!is_kprobe) -+ config = "CONFIG_UPROBE_EVENTS"; -+ else -+ config = "CONFIG_KPROBE_EVENTS"; -+ -+ pr_warning("%s file does not exist - please rebuild kernel" -+ " with %s.\n", file, config); -+ } else -+ pr_warning("Failed to open %s file: %s\n", file, -+ strerror(errno)); -+} -+ -+static int open_probe_events(const char *trace_file, bool readwrite, -+ bool is_kprobe) - { - char buf[PATH_MAX]; - const char *__debugfs; -@@ -1484,27 +1552,31 @@ static int open_kprobe_events(bool readwrite) - return -ENOENT; - } - -- ret = e_snprintf(buf, PATH_MAX, "%stracing/kprobe_events", __debugfs); -+ ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file); - if (ret >= 0) { - pr_debug("Opening %s write=%d\n", buf, readwrite); - if (readwrite && !probe_event_dry_run) - ret = open(buf, O_RDWR, O_APPEND); - else - ret = open(buf, O_RDONLY, 0); -- } - -- if (ret < 0) { -- if (errno == ENOENT) -- pr_warning("kprobe_events file does not exist - please" -- " rebuild kernel with CONFIG_KPROBE_EVENT.\n"); -- else -- pr_warning("Failed to open kprobe_events file: %s\n", -- strerror(errno)); -+ if (ret < 0) -+ print_warn_msg(buf, is_kprobe); - } - return ret; - } - --/* Get raw string list of current kprobe_events */ -+static int open_kprobe_events(bool readwrite) -+{ -+ return open_probe_events("tracing/kprobe_events", readwrite, true); -+} -+ -+static int open_uprobe_events(bool readwrite) -+{ -+ return open_probe_events("tracing/uprobe_events", readwrite, false); -+} -+ -+/* Get raw string list of current kprobe_events or uprobe_events */ - static struct strlist *get_probe_trace_command_rawlist(int fd) - { - int ret, idx; -@@ -1569,36 +1641,26 @@ static int show_perf_probe_event(struct perf_probe_event *pev) - return ret; - } - --/* List up current perf-probe events */ --int show_perf_probe_events(void) -+static int __show_perf_probe_events(int fd, bool is_kprobe) - { -- int fd, ret; -+ int ret = 0; - struct probe_trace_event tev; - struct perf_probe_event pev; - struct strlist *rawlist; - struct str_node *ent; - -- setup_pager(); -- ret = init_vmlinux(); -- if (ret < 0) -- return ret; -- - memset(&tev, 0, sizeof(tev)); - memset(&pev, 0, sizeof(pev)); - -- fd = open_kprobe_events(false); -- if (fd < 0) -- return fd; -- - rawlist = get_probe_trace_command_rawlist(fd); -- close(fd); - if (!rawlist) - return -ENOENT; - - strlist__for_each(ent, rawlist) { - ret = parse_probe_trace_command(ent->s, &tev); - if (ret >= 0) { -- ret = convert_to_perf_probe_event(&tev, &pev); -+ ret = convert_to_perf_probe_event(&tev, &pev, -+ is_kprobe); - if (ret >= 0) - ret = show_perf_probe_event(&pev); - } -@@ -1612,6 +1674,33 @@ int show_perf_probe_events(void) - return ret; - } - -+/* List up current perf-probe events */ -+int show_perf_probe_events(void) -+{ -+ int fd, ret; -+ -+ setup_pager(); -+ fd = open_kprobe_events(false); -+ -+ if (fd < 0) -+ return fd; -+ -+ ret = init_vmlinux(); -+ if (ret < 0) -+ return ret; -+ -+ ret = __show_perf_probe_events(fd, true); -+ close(fd); -+ -+ fd = open_uprobe_events(false); -+ if (fd >= 0) { -+ ret = __show_perf_probe_events(fd, false); -+ close(fd); -+ } -+ -+ return ret; -+} -+ - /* Get current perf-probe event names */ - static struct strlist *get_probe_trace_event_names(int fd, bool include_group) - { -@@ -1717,7 +1806,11 @@ static int __add_probe_trace_events(struct perf_probe_event *pev, - const char *event, *group; - struct strlist *namelist; - -- fd = open_kprobe_events(true); -+ if (pev->uprobes) -+ fd = open_uprobe_events(true); -+ else -+ fd = open_kprobe_events(true); -+ - if (fd < 0) - return fd; - /* Get current event names */ -@@ -1829,6 +1922,8 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, - tev->point.offset = pev->point.offset; - tev->point.retprobe = pev->point.retprobe; - tev->nargs = pev->nargs; -+ tev->uprobes = pev->uprobes; -+ - if (tev->nargs) { - tev->args = zalloc(sizeof(struct probe_trace_arg) - * tev->nargs); -@@ -1859,6 +1954,9 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, - } - } - -+ if (pev->uprobes) -+ return 1; -+ - /* Currently just checking function name from symbol map */ - sym = __find_kernel_function_by_name(tev->point.symbol, NULL); - if (!sym) { -@@ -1894,12 +1992,18 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, - int i, j, ret; - struct __event_package *pkgs; - -+ ret = 0; - pkgs = zalloc(sizeof(struct __event_package) * npevs); -+ - if (pkgs == NULL) - return -ENOMEM; - -- /* Init vmlinux path */ -- ret = init_vmlinux(); -+ if (!pevs->uprobes) -+ /* Init vmlinux path */ -+ ret = init_vmlinux(); -+ else -+ ret = init_user_exec(); -+ - if (ret < 0) { - free(pkgs); - return ret; -@@ -1971,23 +2075,15 @@ error: - return ret; - } - --static int del_trace_probe_event(int fd, const char *group, -- const char *event, struct strlist *namelist) -+static int del_trace_probe_event(int fd, const char *buf, -+ struct strlist *namelist) - { -- char buf[128]; - struct str_node *ent, *n; -- int found = 0, ret = 0; -- -- ret = e_snprintf(buf, 128, "%s:%s", group, event); -- if (ret < 0) { -- pr_err("Failed to copy event.\n"); -- return ret; -- } -+ int ret = -1; - - if (strpbrk(buf, "*?")) { /* Glob-exp */ - strlist__for_each_safe(ent, n, namelist) - if (strglobmatch(ent->s, buf)) { -- found++; - ret = __del_trace_probe_event(fd, ent); - if (ret < 0) - break; -@@ -1996,40 +2092,43 @@ static int del_trace_probe_event(int fd, const char *group, - } else { - ent = strlist__find(namelist, buf); - if (ent) { -- found++; - ret = __del_trace_probe_event(fd, ent); - if (ret >= 0) - strlist__remove(namelist, ent); - } - } -- if (found == 0 && ret >= 0) -- pr_info("Info: Event \"%s\" does not exist.\n", buf); - - return ret; - } - - int del_perf_probe_events(struct strlist *dellist) - { -- int fd, ret = 0; -+ int ret = -1, ufd = -1, kfd = -1; -+ char buf[128]; - const char *group, *event; - char *p, *str; - struct str_node *ent; -- struct strlist *namelist; -- -- fd = open_kprobe_events(true); -- if (fd < 0) -- return fd; -+ struct strlist *namelist = NULL, *unamelist = NULL; - - /* Get current event names */ -- namelist = get_probe_trace_event_names(fd, true); -- if (namelist == NULL) -- return -EINVAL; -+ kfd = open_kprobe_events(true); -+ if (kfd < 0) -+ return kfd; -+ -+ namelist = get_probe_trace_event_names(kfd, true); -+ ufd = open_uprobe_events(true); -+ -+ if (ufd >= 0) -+ unamelist = get_probe_trace_event_names(ufd, true); -+ -+ if (namelist == NULL && unamelist == NULL) -+ goto error; - - strlist__for_each(ent, dellist) { - str = strdup(ent->s); - if (str == NULL) { - ret = -ENOMEM; -- break; -+ goto error; - } - pr_debug("Parsing: %s\n", str); - p = strchr(str, ':'); -@@ -2041,17 +2140,42 @@ int del_perf_probe_events(struct strlist *dellist) - group = "*"; - event = str; - } -+ -+ ret = e_snprintf(buf, 128, "%s:%s", group, event); -+ if (ret < 0) { -+ pr_err("Failed to copy event."); -+ free(str); -+ goto error; -+ } -+ - pr_debug("Group: %s, Event: %s\n", group, event); -- ret = del_trace_probe_event(fd, group, event, namelist); -+ -+ if (namelist) -+ ret = del_trace_probe_event(kfd, buf, namelist); -+ -+ if (unamelist && ret != 0) -+ ret = del_trace_probe_event(ufd, buf, unamelist); -+ -+ if (ret != 0) -+ pr_info("Info: Event \"%s\" does not exist.\n", buf); -+ - free(str); -- if (ret < 0) -- break; - } -- strlist__delete(namelist); -- close(fd); -+ -+error: -+ if (kfd >= 0) { -+ strlist__delete(namelist); -+ close(kfd); -+ } -+ -+ if (ufd >= 0) { -+ strlist__delete(unamelist); -+ close(ufd); -+ } - - return ret; - } -+ - /* TODO: don't use a global variable for filter ... */ - static struct strfilter *available_func_filter; - -@@ -2068,30 +2192,152 @@ static int filter_available_functions(struct map *map __unused, - return 1; - } - --int show_available_funcs(const char *target, struct strfilter *_filter) -+static int __show_available_funcs(struct map *map) -+{ -+ if (map__load(map, filter_available_functions)) { -+ pr_err("Failed to load map.\n"); -+ return -EINVAL; -+ } -+ if (!dso__sorted_by_name(map->dso, map->type)) -+ dso__sort_by_name(map->dso, map->type); -+ -+ dso__fprintf_symbols_by_name(map->dso, map->type, stdout); -+ return 0; -+} -+ -+static int available_kernel_funcs(const char *module) - { - struct map *map; - int ret; - -- setup_pager(); -- - ret = init_vmlinux(); - if (ret < 0) - return ret; - -- map = kernel_get_module_map(target); -+ map = kernel_get_module_map(module); - if (!map) { -- pr_err("Failed to find %s map.\n", (target) ? : "kernel"); -+ pr_err("Failed to find %s map.\n", (module) ? : "kernel"); - return -EINVAL; - } -+ return __show_available_funcs(map); -+} -+ -+static int available_user_funcs(const char *target) -+{ -+ struct map *map; -+ int ret; -+ -+ ret = init_user_exec(); -+ if (ret < 0) -+ return ret; -+ -+ map = dso__new_map(target); -+ ret = __show_available_funcs(map); -+ dso__delete(map->dso); -+ map__delete(map); -+ return ret; -+} -+ -+int show_available_funcs(const char *target, struct strfilter *_filter, -+ bool user) -+{ -+ setup_pager(); - available_func_filter = _filter; -+ -+ if (!user) -+ return available_kernel_funcs(target); -+ -+ return available_user_funcs(target); -+} -+ -+/* -+ * uprobe_events only accepts address: -+ * Convert function and any offset to address -+ */ -+static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec) -+{ -+ struct perf_probe_point *pp = &pev->point; -+ struct symbol *sym; -+ struct map *map = NULL; -+ char *function = NULL, *name = NULL; -+ int ret = -EINVAL; -+ unsigned long long vaddr = 0; -+ -+ if (!pp->function) { -+ pr_warning("No function specified for uprobes"); -+ goto out; -+ } -+ -+ function = strdup(pp->function); -+ if (!function) { -+ pr_warning("Failed to allocate memory by strdup.\n"); -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ name = realpath(exec, NULL); -+ if (!name) { -+ pr_warning("Cannot find realpath for %s.\n", exec); -+ goto out; -+ } -+ map = dso__new_map(name); -+ if (!map) { -+ pr_warning("Cannot find appropriate DSO for %s.\n", exec); -+ goto out; -+ } -+ available_func_filter = strfilter__new(function, NULL); - if (map__load(map, filter_available_functions)) { - pr_err("Failed to load map.\n"); -- return -EINVAL; -+ goto out; - } -- if (!dso__sorted_by_name(map->dso, map->type)) -- dso__sort_by_name(map->dso, map->type); - -- dso__fprintf_symbols_by_name(map->dso, map->type, stdout); -- return 0; -+ sym = map__find_symbol_by_name(map, function, NULL); -+ if (!sym) { -+ pr_warning("Cannot find %s in DSO %s\n", function, exec); -+ goto out; -+ } -+ -+ if (map->start > sym->start) -+ vaddr = map->start; -+ vaddr += sym->start + pp->offset + map->pgoff; -+ pp->offset = 0; -+ -+ if (!pev->event) { -+ pev->event = function; -+ function = NULL; -+ } -+ if (!pev->group) { -+ char *ptr1, *ptr2; -+ -+ pev->group = zalloc(sizeof(char *) * 64); -+ ptr1 = strdup(basename(exec)); -+ if (ptr1) { -+ ptr2 = strpbrk(ptr1, "-._"); -+ if (ptr2) -+ *ptr2 = '\0'; -+ e_snprintf(pev->group, 64, "%s_%s", PERFPROBE_GROUP, -+ ptr1); -+ free(ptr1); -+ } -+ } -+ free(pp->function); -+ pp->function = zalloc(sizeof(char *) * MAX_PROBE_ARGS); -+ if (!pp->function) { -+ ret = -ENOMEM; -+ pr_warning("Failed to allocate memory by zalloc.\n"); -+ goto out; -+ } -+ e_snprintf(pp->function, MAX_PROBE_ARGS, "0x%llx", vaddr); -+ ret = 0; -+ -+out: -+ if (map) { -+ dso__delete(map->dso); -+ map__delete(map); -+ } -+ if (function) -+ free(function); -+ if (name) -+ free(name); -+ return ret; - } -diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h -index a7dee83..f9f3de8 100644 ---- a/tools/perf/util/probe-event.h -+++ b/tools/perf/util/probe-event.h -@@ -7,7 +7,7 @@ - - extern bool probe_event_dry_run; - --/* kprobe-tracer tracing point */ -+/* kprobe-tracer and uprobe-tracer tracing point */ - struct probe_trace_point { - char *symbol; /* Base symbol */ - char *module; /* Module name */ -@@ -21,7 +21,7 @@ struct probe_trace_arg_ref { - long offset; /* Offset value */ - }; - --/* kprobe-tracer tracing argument */ -+/* kprobe-tracer and uprobe-tracer tracing argument */ - struct probe_trace_arg { - char *name; /* Argument name */ - char *value; /* Base value */ -@@ -29,12 +29,13 @@ struct probe_trace_arg { - struct probe_trace_arg_ref *ref; /* Referencing offset */ - }; - --/* kprobe-tracer tracing event (point + arg) */ -+/* kprobe-tracer and uprobe-tracer tracing event (point + arg) */ - struct probe_trace_event { - char *event; /* Event name */ - char *group; /* Group name */ - struct probe_trace_point point; /* Trace point */ - int nargs; /* Number of args */ -+ bool uprobes; /* uprobes only */ - struct probe_trace_arg *args; /* Arguments */ - }; - -@@ -70,6 +71,7 @@ struct perf_probe_event { - char *group; /* Group name */ - struct perf_probe_point point; /* Probe point */ - int nargs; /* Number of arguments */ -+ bool uprobes; - struct perf_probe_arg *args; /* Arguments */ - }; - -@@ -129,8 +131,8 @@ extern int show_line_range(struct line_range *lr, const char *module); - extern int show_available_vars(struct perf_probe_event *pevs, int npevs, - int max_probe_points, const char *module, - struct strfilter *filter, bool externs); --extern int show_available_funcs(const char *module, struct strfilter *filter); -- -+extern int show_available_funcs(const char *module, struct strfilter *filter, -+ bool user); - - /* Maximum index number of event-name postfix */ - #define MAX_EVENT_INDEX 1024 -diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c -index ab9867b..0ef529e 100644 ---- a/tools/perf/util/symbol.c -+++ b/tools/perf/util/symbol.c -@@ -2783,3 +2783,14 @@ int machine__load_vmlinux_path(struct machine *machine, enum map_type type, - - return ret; - } -+ -+struct map *dso__new_map(const char *name) -+{ -+ struct map *map = NULL; -+ struct dso *dso = dso__new(name); -+ -+ if (dso) -+ map = map__new2(0, dso, MAP__FUNCTION); -+ -+ return map; -+} -diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h -index ac49ef2..9e7742c 100644 ---- a/tools/perf/util/symbol.h -+++ b/tools/perf/util/symbol.h -@@ -237,6 +237,7 @@ void dso__set_long_name(struct dso *dso, char *name); - void dso__set_build_id(struct dso *dso, void *build_id); - void dso__read_running_kernel_build_id(struct dso *dso, - struct machine *machine); -+struct map *dso__new_map(const char *name); - struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, - u64 addr); - struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, diff --git a/uprobes-3.4-tip.patch b/uprobes-3.4-tip.patch deleted file mode 100644 index 190b03544..000000000 --- a/uprobes-3.4-tip.patch +++ /dev/null @@ -1,915 +0,0 @@ -The split-out series is available in the git repository at: - - git://fedorapeople.org/home/fedora/aarapov/public_git/kernel-uprobes.git tags/f17_exported - -Ananth N Mavinakayanahalli (1): - uprobes: Pass probed vaddr to arch_uprobe_analyze_insn() - -Josh Stone (1): - uprobes: add exports necessary for uprobes use by modules - -Oleg Nesterov (21): - uprobes: Optimize is_swbp_at_addr() for current->mm - uprobes: Change read_opcode() to use FOLL_FORCE - uprobes: Introduce find_active_uprobe() helper - uprobes: Teach find_active_uprobe() to provide the "is_swbp" info - uprobes: Change register_for_each_vma() to take mm->mmap_sem for writing - uprobes: Teach handle_swbp() to rely on "is_swbp" rather than uprobes_srcu - uprobes: Kill uprobes_srcu/uprobe_srcu_id - uprobes: Valid_vma() should reject VM_HUGETLB - uprobes: __copy_insn() should ensure a_ops->readpage != NULL - uprobes: Write_opcode()->__replace_page() can race with try_to_unmap() - uprobes: Install_breakpoint() should fail if is_swbp_insn() == T - uprobes: Rework register_for_each_vma() to make it O(n) - uprobes: Change build_map_info() to try kmalloc(GFP_NOWAIT) first - uprobes: Copy_insn() shouldn't depend on mm/vma/vaddr - uprobes: Copy_insn() should not return -ENOMEM if __copy_insn() fails - uprobes: No need to re-check vma_address() in write_opcode() - uprobes: Simplify the usage of uprobe->pending_list - uprobes: Don't use loff_t for the valid virtual address - uprobes: __copy_insn() needs "loff_t offset" - uprobes: Remove the unnecessary initialization in add_utask() - uprobes: Move BUG_ON(UPROBE_SWBP_INSN_SIZE) from write_opcode() to install_breakpoint() - -Peter Zijlstra (1): - uprobes: Document uprobe_register() vs uprobe_mmap() race - -Signed-off-by: Anton Arapov ---- - arch/x86/include/asm/uprobes.h | 2 +- - arch/x86/kernel/ptrace.c | 6 + - arch/x86/kernel/uprobes.c | 3 +- - include/linux/sched.h | 1 - - kernel/events/uprobes.c | 464 ++++++++++++++++++++-------------------- - 5 files changed, 240 insertions(+), 236 deletions(-) - -diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h -index 1e9bed1..f3971bb 100644 ---- a/arch/x86/include/asm/uprobes.h -+++ b/arch/x86/include/asm/uprobes.h -@@ -48,7 +48,7 @@ struct arch_uprobe_task { - #endif - }; - --extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm); -+extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr); - extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs); - extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs); - extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk); -diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c -index cf11783..4609190 100644 ---- a/arch/x86/kernel/ptrace.c -+++ b/arch/x86/kernel/ptrace.c -@@ -1415,6 +1415,12 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) - #endif - } - -+/* -+ * This is declared in linux/regset.h and defined in machine-dependent -+ * code. We put the export here to ensure no machine forgets it. -+ */ -+EXPORT_SYMBOL_GPL(task_user_regset_view); -+ - static void fill_sigtrap_info(struct task_struct *tsk, - struct pt_regs *regs, - int error_code, int si_code, -diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c -index dc4e910..36fd420 100644 ---- a/arch/x86/kernel/uprobes.c -+++ b/arch/x86/kernel/uprobes.c -@@ -409,9 +409,10 @@ static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm, - * arch_uprobe_analyze_insn - instruction analysis including validity and fixups. - * @mm: the probed address space. - * @arch_uprobe: the probepoint information. -+ * @addr: virtual address at which to install the probepoint - * Return 0 on success or a -ve number on error. - */ --int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm) -+int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr) - { - int ret; - struct insn insn; -diff --git a/include/linux/sched.h b/include/linux/sched.h -index cff94cd..6869c60 100644 ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -1619,7 +1619,6 @@ struct task_struct { - #endif - #ifdef CONFIG_UPROBES - struct uprobe_task *utask; -- int uprobe_srcu_id; - #endif - }; - -diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c -index 985be4d..d9e5ba5 100644 ---- a/kernel/events/uprobes.c -+++ b/kernel/events/uprobes.c -@@ -34,17 +34,34 @@ - #include /* notifier mechanism */ - - #include -+#include - - #define UINSNS_PER_PAGE (PAGE_SIZE/UPROBE_XOL_SLOT_BYTES) - #define MAX_UPROBE_XOL_SLOTS UINSNS_PER_PAGE - --static struct srcu_struct uprobes_srcu; - static struct rb_root uprobes_tree = RB_ROOT; - - static DEFINE_SPINLOCK(uprobes_treelock); /* serialize rbtree access */ - - #define UPROBES_HASH_SZ 13 - -+/* -+ * We need separate register/unregister and mmap/munmap lock hashes because -+ * of mmap_sem nesting. -+ * -+ * uprobe_register() needs to install probes on (potentially) all processes -+ * and thus needs to acquire multiple mmap_sems (consequtively, not -+ * concurrently), whereas uprobe_mmap() is called while holding mmap_sem -+ * for the particular process doing the mmap. -+ * -+ * uprobe_register()->register_for_each_vma() needs to drop/acquire mmap_sem -+ * because of lock order against i_mmap_mutex. This means there's a hole in -+ * the register vma iteration where a mmap() can happen. -+ * -+ * Thus uprobe_register() can race with uprobe_mmap() and we can try and -+ * install a probe where one is already installed. -+ */ -+ - /* serialize (un)register */ - static struct mutex uprobes_mutex[UPROBES_HASH_SZ]; - -@@ -61,17 +78,6 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ]; - */ - static atomic_t uprobe_events = ATOMIC_INIT(0); - --/* -- * Maintain a temporary per vma info that can be used to search if a vma -- * has already been handled. This structure is introduced since extending -- * vm_area_struct wasnt recommended. -- */ --struct vma_info { -- struct list_head probe_list; -- struct mm_struct *mm; -- loff_t vaddr; --}; -- - struct uprobe { - struct rb_node rb_node; /* node in the rb tree */ - atomic_t ref; -@@ -100,7 +106,8 @@ static bool valid_vma(struct vm_area_struct *vma, bool is_register) - if (!is_register) - return true; - -- if ((vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) == (VM_READ|VM_EXEC)) -+ if ((vma->vm_flags & (VM_HUGETLB|VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) -+ == (VM_READ|VM_EXEC)) - return true; - - return false; -@@ -129,33 +136,17 @@ static loff_t vma_address(struct vm_area_struct *vma, loff_t offset) - static int __replace_page(struct vm_area_struct *vma, struct page *page, struct page *kpage) - { - struct mm_struct *mm = vma->vm_mm; -- pgd_t *pgd; -- pud_t *pud; -- pmd_t *pmd; -- pte_t *ptep; -- spinlock_t *ptl; - unsigned long addr; -- int err = -EFAULT; -+ spinlock_t *ptl; -+ pte_t *ptep; - - addr = page_address_in_vma(page, vma); - if (addr == -EFAULT) -- goto out; -- -- pgd = pgd_offset(mm, addr); -- if (!pgd_present(*pgd)) -- goto out; -- -- pud = pud_offset(pgd, addr); -- if (!pud_present(*pud)) -- goto out; -- -- pmd = pmd_offset(pud, addr); -- if (!pmd_present(*pmd)) -- goto out; -+ return -EFAULT; - -- ptep = pte_offset_map_lock(mm, pmd, addr, &ptl); -+ ptep = page_check_address(page, mm, addr, &ptl, 0); - if (!ptep) -- goto out; -+ return -EAGAIN; - - get_page(kpage); - page_add_new_anon_rmap(kpage, vma, addr); -@@ -174,10 +165,8 @@ static int __replace_page(struct vm_area_struct *vma, struct page *page, struct - try_to_free_swap(page); - put_page(page); - pte_unmap_unlock(ptep, ptl); -- err = 0; - --out: -- return err; -+ return 0; - } - - /** -@@ -222,9 +211,8 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, - void *vaddr_old, *vaddr_new; - struct vm_area_struct *vma; - struct uprobe *uprobe; -- loff_t addr; - int ret; -- -+retry: - /* Read the page with vaddr into memory */ - ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma); - if (ret <= 0) -@@ -246,10 +234,6 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, - if (mapping != vma->vm_file->f_mapping) - goto put_out; - -- addr = vma_address(vma, uprobe->offset); -- if (vaddr != (unsigned long)addr) -- goto put_out; -- - ret = -ENOMEM; - new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr); - if (!new_page) -@@ -267,11 +251,7 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, - vaddr_new = kmap_atomic(new_page); - - memcpy(vaddr_new, vaddr_old, PAGE_SIZE); -- -- /* poke the new insn in, ASSUMES we don't cross page boundary */ -- vaddr &= ~PAGE_MASK; -- BUG_ON(vaddr + UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); -- memcpy(vaddr_new + vaddr, &opcode, UPROBE_SWBP_INSN_SIZE); -+ memcpy(vaddr_new + (vaddr & ~PAGE_MASK), &opcode, UPROBE_SWBP_INSN_SIZE); - - kunmap_atomic(vaddr_new); - kunmap_atomic(vaddr_old); -@@ -291,6 +271,8 @@ unlock_out: - put_out: - put_page(old_page); - -+ if (unlikely(ret == -EAGAIN)) -+ goto retry; - return ret; - } - -@@ -312,7 +294,7 @@ static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_ - void *vaddr_new; - int ret; - -- ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &page, NULL); -+ ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL); - if (ret <= 0) - return ret; - -@@ -333,10 +315,20 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) - uprobe_opcode_t opcode; - int result; - -+ if (current->mm == mm) { -+ pagefault_disable(); -+ result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr, -+ sizeof(opcode)); -+ pagefault_enable(); -+ -+ if (likely(result == 0)) -+ goto out; -+ } -+ - result = read_opcode(mm, vaddr, &opcode); - if (result) - return result; -- -+out: - if (is_swbp_insn(&opcode)) - return 1; - -@@ -355,7 +347,9 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) - int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) - { - int result; -- -+ /* -+ * See the comment near uprobes_hash(). -+ */ - result = is_swbp_at_addr(mm, vaddr); - if (result == 1) - return -EEXIST; -@@ -520,7 +514,6 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset) - uprobe->inode = igrab(inode); - uprobe->offset = offset; - init_rwsem(&uprobe->consumer_rwsem); -- INIT_LIST_HEAD(&uprobe->pending_list); - - /* add to uprobes_tree, sorted on inode:offset */ - cur_uprobe = insert_uprobe(uprobe); -@@ -588,20 +581,22 @@ static bool consumer_del(struct uprobe *uprobe, struct uprobe_consumer *uc) - } - - static int --__copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *insn, -- unsigned long nbytes, unsigned long offset) -+__copy_insn(struct address_space *mapping, struct file *filp, char *insn, -+ unsigned long nbytes, loff_t offset) - { -- struct file *filp = vma->vm_file; - struct page *page; - void *vaddr; -- unsigned long off1; -- unsigned long idx; -+ unsigned long off; -+ pgoff_t idx; - - if (!filp) - return -EINVAL; - -- idx = (unsigned long)(offset >> PAGE_CACHE_SHIFT); -- off1 = offset &= ~PAGE_MASK; -+ if (!mapping->a_ops->readpage) -+ return -EIO; -+ -+ idx = offset >> PAGE_CACHE_SHIFT; -+ off = offset & ~PAGE_MASK; - - /* - * Ensure that the page that has the original instruction is -@@ -612,22 +607,20 @@ __copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *ins - return PTR_ERR(page); - - vaddr = kmap_atomic(page); -- memcpy(insn, vaddr + off1, nbytes); -+ memcpy(insn, vaddr + off, nbytes); - kunmap_atomic(vaddr); - page_cache_release(page); - - return 0; - } - --static int --copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr) -+static int copy_insn(struct uprobe *uprobe, struct file *filp) - { - struct address_space *mapping; - unsigned long nbytes; - int bytes; - -- addr &= ~PAGE_MASK; -- nbytes = PAGE_SIZE - addr; -+ nbytes = PAGE_SIZE - (uprobe->offset & ~PAGE_MASK); - mapping = uprobe->inode->i_mapping; - - /* Instruction at end of binary; copy only available bytes */ -@@ -638,13 +631,13 @@ copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr) - - /* Instruction at the page-boundary; copy bytes in second page */ - if (nbytes < bytes) { -- if (__copy_insn(mapping, vma, uprobe->arch.insn + nbytes, -- bytes - nbytes, uprobe->offset + nbytes)) -- return -ENOMEM; -- -+ int err = __copy_insn(mapping, filp, uprobe->arch.insn + nbytes, -+ bytes - nbytes, uprobe->offset + nbytes); -+ if (err) -+ return err; - bytes = nbytes; - } -- return __copy_insn(mapping, vma, uprobe->arch.insn, bytes, uprobe->offset); -+ return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset); - } - - /* -@@ -672,9 +665,8 @@ copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr) - */ - static int - install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, -- struct vm_area_struct *vma, loff_t vaddr) -+ struct vm_area_struct *vma, unsigned long vaddr) - { -- unsigned long addr; - int ret; - - /* -@@ -687,20 +679,22 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, - if (!uprobe->consumers) - return -EEXIST; - -- addr = (unsigned long)vaddr; -- - if (!(uprobe->flags & UPROBE_COPY_INSN)) { -- ret = copy_insn(uprobe, vma, addr); -+ ret = copy_insn(uprobe, vma->vm_file); - if (ret) - return ret; - - if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) -- return -EEXIST; -+ return -ENOTSUPP; - -- ret = arch_uprobe_analyze_insn(&uprobe->arch, mm); -+ ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr); - if (ret) - return ret; - -+ /* write_opcode() assumes we don't cross page boundary */ -+ BUG_ON((uprobe->offset & ~PAGE_MASK) + -+ UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); -+ - uprobe->flags |= UPROBE_COPY_INSN; - } - -@@ -713,7 +707,7 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, - * Hence increment before and decrement on failure. - */ - atomic_inc(&mm->uprobes_state.count); -- ret = set_swbp(&uprobe->arch, mm, addr); -+ ret = set_swbp(&uprobe->arch, mm, vaddr); - if (ret) - atomic_dec(&mm->uprobes_state.count); - -@@ -721,27 +715,21 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, - } - - static void --remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, loff_t vaddr) -+remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr) - { -- if (!set_orig_insn(&uprobe->arch, mm, (unsigned long)vaddr, true)) -+ if (!set_orig_insn(&uprobe->arch, mm, vaddr, true)) - atomic_dec(&mm->uprobes_state.count); - } - - /* -- * There could be threads that have hit the breakpoint and are entering the -- * notifier code and trying to acquire the uprobes_treelock. The thread -- * calling delete_uprobe() that is removing the uprobe from the rb_tree can -- * race with these threads and might acquire the uprobes_treelock compared -- * to some of the breakpoint hit threads. In such a case, the breakpoint -- * hit threads will not find the uprobe. The current unregistering thread -- * waits till all other threads have hit a breakpoint, to acquire the -- * uprobes_treelock before the uprobe is removed from the rbtree. -+ * There could be threads that have already hit the breakpoint. They -+ * will recheck the current insn and restart if find_uprobe() fails. -+ * See find_active_uprobe(). - */ - static void delete_uprobe(struct uprobe *uprobe) - { - unsigned long flags; - -- synchronize_srcu(&uprobes_srcu); - spin_lock_irqsave(&uprobes_treelock, flags); - rb_erase(&uprobe->rb_node, &uprobes_tree); - spin_unlock_irqrestore(&uprobes_treelock, flags); -@@ -750,139 +738,135 @@ static void delete_uprobe(struct uprobe *uprobe) - atomic_dec(&uprobe_events); - } - --static struct vma_info * --__find_next_vma_info(struct address_space *mapping, struct list_head *head, -- struct vma_info *vi, loff_t offset, bool is_register) -+struct map_info { -+ struct map_info *next; -+ struct mm_struct *mm; -+ unsigned long vaddr; -+}; -+ -+static inline struct map_info *free_map_info(struct map_info *info) -+{ -+ struct map_info *next = info->next; -+ kfree(info); -+ return next; -+} -+ -+static struct map_info * -+build_map_info(struct address_space *mapping, loff_t offset, bool is_register) - { -+ unsigned long pgoff = offset >> PAGE_SHIFT; - struct prio_tree_iter iter; - struct vm_area_struct *vma; -- struct vma_info *tmpvi; -- unsigned long pgoff; -- int existing_vma; -- loff_t vaddr; -- -- pgoff = offset >> PAGE_SHIFT; -+ struct map_info *curr = NULL; -+ struct map_info *prev = NULL; -+ struct map_info *info; -+ int more = 0; - -+ again: -+ mutex_lock(&mapping->i_mmap_mutex); - vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { - if (!valid_vma(vma, is_register)) - continue; - -- existing_vma = 0; -- vaddr = vma_address(vma, offset); -- -- list_for_each_entry(tmpvi, head, probe_list) { -- if (tmpvi->mm == vma->vm_mm && tmpvi->vaddr == vaddr) { -- existing_vma = 1; -- break; -- } -+ if (!prev && !more) { -+ /* -+ * Needs GFP_NOWAIT to avoid i_mmap_mutex recursion through -+ * reclaim. This is optimistic, no harm done if it fails. -+ */ -+ prev = kmalloc(sizeof(struct map_info), -+ GFP_NOWAIT | __GFP_NOMEMALLOC | __GFP_NOWARN); -+ if (prev) -+ prev->next = NULL; - } -- -- /* -- * Another vma needs a probe to be installed. However skip -- * installing the probe if the vma is about to be unlinked. -- */ -- if (!existing_vma && atomic_inc_not_zero(&vma->vm_mm->mm_users)) { -- vi->mm = vma->vm_mm; -- vi->vaddr = vaddr; -- list_add(&vi->probe_list, head); -- -- return vi; -+ if (!prev) { -+ more++; -+ continue; - } -- } - -- return NULL; --} -- --/* -- * Iterate in the rmap prio tree and find a vma where a probe has not -- * yet been inserted. -- */ --static struct vma_info * --find_next_vma_info(struct address_space *mapping, struct list_head *head, -- loff_t offset, bool is_register) --{ -- struct vma_info *vi, *retvi; -+ if (!atomic_inc_not_zero(&vma->vm_mm->mm_users)) -+ continue; - -- vi = kzalloc(sizeof(struct vma_info), GFP_KERNEL); -- if (!vi) -- return ERR_PTR(-ENOMEM); -+ info = prev; -+ prev = prev->next; -+ info->next = curr; -+ curr = info; - -- mutex_lock(&mapping->i_mmap_mutex); -- retvi = __find_next_vma_info(mapping, head, vi, offset, is_register); -+ info->mm = vma->vm_mm; -+ info->vaddr = vma_address(vma, offset); -+ } - mutex_unlock(&mapping->i_mmap_mutex); - -- if (!retvi) -- kfree(vi); -+ if (!more) -+ goto out; -+ -+ prev = curr; -+ while (curr) { -+ mmput(curr->mm); -+ curr = curr->next; -+ } - -- return retvi; -+ do { -+ info = kmalloc(sizeof(struct map_info), GFP_KERNEL); -+ if (!info) { -+ curr = ERR_PTR(-ENOMEM); -+ goto out; -+ } -+ info->next = prev; -+ prev = info; -+ } while (--more); -+ -+ goto again; -+ out: -+ while (prev) -+ prev = free_map_info(prev); -+ return curr; - } - - static int register_for_each_vma(struct uprobe *uprobe, bool is_register) - { -- struct list_head try_list; -- struct vm_area_struct *vma; -- struct address_space *mapping; -- struct vma_info *vi, *tmpvi; -- struct mm_struct *mm; -- loff_t vaddr; -- int ret; -+ struct map_info *info; -+ int err = 0; - -- mapping = uprobe->inode->i_mapping; -- INIT_LIST_HEAD(&try_list); -+ info = build_map_info(uprobe->inode->i_mapping, -+ uprobe->offset, is_register); -+ if (IS_ERR(info)) -+ return PTR_ERR(info); - -- ret = 0; -+ while (info) { -+ struct mm_struct *mm = info->mm; -+ struct vm_area_struct *vma; - -- for (;;) { -- vi = find_next_vma_info(mapping, &try_list, uprobe->offset, is_register); -- if (!vi) -- break; -+ if (err) -+ goto free; - -- if (IS_ERR(vi)) { -- ret = PTR_ERR(vi); -- break; -- } -+ down_write(&mm->mmap_sem); -+ vma = find_vma(mm, (unsigned long)info->vaddr); -+ if (!vma || !valid_vma(vma, is_register)) -+ goto unlock; - -- mm = vi->mm; -- down_read(&mm->mmap_sem); -- vma = find_vma(mm, (unsigned long)vi->vaddr); -- if (!vma || !valid_vma(vma, is_register)) { -- list_del(&vi->probe_list); -- kfree(vi); -- up_read(&mm->mmap_sem); -- mmput(mm); -- continue; -- } -- vaddr = vma_address(vma, uprobe->offset); - if (vma->vm_file->f_mapping->host != uprobe->inode || -- vaddr != vi->vaddr) { -- list_del(&vi->probe_list); -- kfree(vi); -- up_read(&mm->mmap_sem); -- mmput(mm); -- continue; -- } -- -- if (is_register) -- ret = install_breakpoint(uprobe, mm, vma, vi->vaddr); -- else -- remove_breakpoint(uprobe, mm, vi->vaddr); -+ vma_address(vma, uprobe->offset) != info->vaddr) -+ goto unlock; - -- up_read(&mm->mmap_sem); -- mmput(mm); - if (is_register) { -- if (ret && ret == -EEXIST) -- ret = 0; -- if (ret) -- break; -+ err = install_breakpoint(uprobe, mm, vma, info->vaddr); -+ /* -+ * We can race against uprobe_mmap(), see the -+ * comment near uprobe_hash(). -+ */ -+ if (err == -EEXIST) -+ err = 0; -+ } else { -+ remove_breakpoint(uprobe, mm, info->vaddr); - } -+ unlock: -+ up_write(&mm->mmap_sem); -+ free: -+ mmput(mm); -+ info = free_map_info(info); - } - -- list_for_each_entry_safe(vi, tmpvi, &try_list, probe_list) { -- list_del(&vi->probe_list); -- kfree(vi); -- } -- -- return ret; -+ return err; - } - - static int __uprobe_register(struct uprobe *uprobe) -@@ -945,6 +929,7 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer * - - return ret; - } -+EXPORT_SYMBOL_GPL(uprobe_register); - - /* - * uprobe_unregister - unregister a already registered probe. -@@ -976,6 +961,7 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume - if (uprobe) - put_uprobe(uprobe); - } -+EXPORT_SYMBOL_GPL(uprobe_unregister); - - /* - * Of all the nodes that correspond to the given inode, return the node -@@ -1048,7 +1034,7 @@ static void build_probe_list(struct inode *inode, struct list_head *head) - int uprobe_mmap(struct vm_area_struct *vma) - { - struct list_head tmp_list; -- struct uprobe *uprobe, *u; -+ struct uprobe *uprobe; - struct inode *inode; - int ret, count; - -@@ -1066,12 +1052,9 @@ int uprobe_mmap(struct vm_area_struct *vma) - ret = 0; - count = 0; - -- list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { -- loff_t vaddr; -- -- list_del(&uprobe->pending_list); -+ list_for_each_entry(uprobe, &tmp_list, pending_list) { - if (!ret) { -- vaddr = vma_address(vma, uprobe->offset); -+ loff_t vaddr = vma_address(vma, uprobe->offset); - - if (vaddr < vma->vm_start || vaddr >= vma->vm_end) { - put_uprobe(uprobe); -@@ -1079,8 +1062,10 @@ int uprobe_mmap(struct vm_area_struct *vma) - } - - ret = install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); -- -- /* Ignore double add: */ -+ /* -+ * We can race against uprobe_register(), see the -+ * comment near uprobe_hash(). -+ */ - if (ret == -EEXIST) { - ret = 0; - -@@ -1115,7 +1100,7 @@ int uprobe_mmap(struct vm_area_struct *vma) - void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) - { - struct list_head tmp_list; -- struct uprobe *uprobe, *u; -+ struct uprobe *uprobe; - struct inode *inode; - - if (!atomic_read(&uprobe_events) || !valid_vma(vma, false)) -@@ -1132,11 +1117,8 @@ void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned lon - mutex_lock(uprobes_mmap_hash(inode)); - build_probe_list(inode, &tmp_list); - -- list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { -- loff_t vaddr; -- -- list_del(&uprobe->pending_list); -- vaddr = vma_address(vma, uprobe->offset); -+ list_for_each_entry(uprobe, &tmp_list, pending_list) { -+ loff_t vaddr = vma_address(vma, uprobe->offset); - - if (vaddr >= start && vaddr < end) { - /* -@@ -1378,9 +1360,6 @@ void uprobe_free_utask(struct task_struct *t) - { - struct uprobe_task *utask = t->utask; - -- if (t->uprobe_srcu_id != -1) -- srcu_read_unlock_raw(&uprobes_srcu, t->uprobe_srcu_id); -- - if (!utask) - return; - -@@ -1398,7 +1377,6 @@ void uprobe_free_utask(struct task_struct *t) - void uprobe_copy_process(struct task_struct *t) - { - t->utask = NULL; -- t->uprobe_srcu_id = -1; - } - - /* -@@ -1417,7 +1395,6 @@ static struct uprobe_task *add_utask(void) - if (unlikely(!utask)) - return NULL; - -- utask->active_uprobe = NULL; - current->utask = utask; - return utask; - } -@@ -1479,41 +1456,64 @@ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs) - return false; - } - -+static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) -+{ -+ struct mm_struct *mm = current->mm; -+ struct uprobe *uprobe = NULL; -+ struct vm_area_struct *vma; -+ -+ down_read(&mm->mmap_sem); -+ vma = find_vma(mm, bp_vaddr); -+ if (vma && vma->vm_start <= bp_vaddr) { -+ if (valid_vma(vma, false)) { -+ struct inode *inode; -+ loff_t offset; -+ -+ inode = vma->vm_file->f_mapping->host; -+ offset = bp_vaddr - vma->vm_start; -+ offset += (vma->vm_pgoff << PAGE_SHIFT); -+ uprobe = find_uprobe(inode, offset); -+ } -+ -+ if (!uprobe) -+ *is_swbp = is_swbp_at_addr(mm, bp_vaddr); -+ } else { -+ *is_swbp = -EFAULT; -+ } -+ up_read(&mm->mmap_sem); -+ -+ return uprobe; -+} -+ - /* - * Run handler and ask thread to singlestep. - * Ensure all non-fatal signals cannot interrupt thread while it singlesteps. - */ - static void handle_swbp(struct pt_regs *regs) - { -- struct vm_area_struct *vma; - struct uprobe_task *utask; - struct uprobe *uprobe; -- struct mm_struct *mm; - unsigned long bp_vaddr; -+ int uninitialized_var(is_swbp); - -- uprobe = NULL; - bp_vaddr = uprobe_get_swbp_addr(regs); -- mm = current->mm; -- down_read(&mm->mmap_sem); -- vma = find_vma(mm, bp_vaddr); -- -- if (vma && vma->vm_start <= bp_vaddr && valid_vma(vma, false)) { -- struct inode *inode; -- loff_t offset; -- -- inode = vma->vm_file->f_mapping->host; -- offset = bp_vaddr - vma->vm_start; -- offset += (vma->vm_pgoff << PAGE_SHIFT); -- uprobe = find_uprobe(inode, offset); -- } -- -- srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id); -- current->uprobe_srcu_id = -1; -- up_read(&mm->mmap_sem); -+ uprobe = find_active_uprobe(bp_vaddr, &is_swbp); - - if (!uprobe) { -- /* No matching uprobe; signal SIGTRAP. */ -- send_sig(SIGTRAP, current, 0); -+ if (is_swbp > 0) { -+ /* No matching uprobe; signal SIGTRAP. */ -+ send_sig(SIGTRAP, current, 0); -+ } else { -+ /* -+ * Either we raced with uprobe_unregister() or we can't -+ * access this memory. The latter is only possible if -+ * another thread plays with our ->mm. In both cases -+ * we can simply restart. If this vma was unmapped we -+ * can pretend this insn was not executed yet and get -+ * the (correct) SIGSEGV after restart. -+ */ -+ instruction_pointer_set(regs, bp_vaddr); -+ } - return; - } - -@@ -1620,7 +1620,6 @@ int uprobe_pre_sstep_notifier(struct pt_regs *regs) - utask->state = UTASK_BP_HIT; - - set_thread_flag(TIF_UPROBE); -- current->uprobe_srcu_id = srcu_read_lock_raw(&uprobes_srcu); - - return 1; - } -@@ -1655,7 +1654,6 @@ static int __init init_uprobes(void) - mutex_init(&uprobes_mutex[i]); - mutex_init(&uprobes_mmap_mutex[i]); - } -- init_srcu_struct(&uprobes_srcu); - - return register_die_notifier(&uprobe_exception_nb); - } diff --git a/uprobes-backport.patch b/uprobes-backport.patch new file mode 100644 index 000000000..5f2bacfc0 --- /dev/null +++ b/uprobes-backport.patch @@ -0,0 +1,1742 @@ +Hello, + +Test build: http://koji.fedoraproject.org/koji/taskinfo?taskID=4490824 +This also fixes: https://bugzilla.redhat.com/show_bug.cgi?id=849364 + +The split-out series is available in the git repository at: + http://fedorapeople.org/cgit/aarapov/public_git/kernel-uprobes.git/log/?h=f17_uprobes_out + (Just @jistone's patch is not upstream that exports functions.) + +Ananth N Mavinakayanahalli (1): + uprobes: Pass probed vaddr to arch_uprobe_analyze_insn() + +Josh Stone (1): + uprobes: add exports necessary for uprobes use by modules + +Oleg Nesterov (52): + uprobes: Optimize is_swbp_at_addr() for current->mm + uprobes: Change read_opcode() to use FOLL_FORCE + uprobes: Introduce find_active_uprobe() helper + uprobes: Teach find_active_uprobe() to provide the "is_swbp" info + uprobes: Change register_for_each_vma() to take mm->mmap_sem for writing + uprobes: Teach handle_swbp() to rely on "is_swbp" rather than uprobes_srcu + uprobes: Kill uprobes_srcu/uprobe_srcu_id + uprobes: Valid_vma() should reject VM_HUGETLB + uprobes: __copy_insn() should ensure a_ops->readpage != NULL + uprobes: Write_opcode()->__replace_page() can race with try_to_unmap() + uprobes: Install_breakpoint() should fail if is_swbp_insn() == T + uprobes: Rework register_for_each_vma() to make it O(n) + uprobes: Change build_map_info() to try kmalloc(GFP_NOWAIT) first + uprobes: Copy_insn() shouldn't depend on mm/vma/vaddr + uprobes: Copy_insn() should not return -ENOMEM if __copy_insn() fails + uprobes: No need to re-check vma_address() in write_opcode() + uprobes: Move BUG_ON(UPROBE_SWBP_INSN_SIZE) from write_opcode() to install_breakpoint() + uprobes: Simplify the usage of uprobe->pending_list + uprobes: Don't use loff_t for the valid virtual address + uprobes: __copy_insn() needs "loff_t offset" + uprobes: Remove the unnecessary initialization in add_utask() + uprobes: Don't recheck vma/f_mapping in write_opcode() + uprobes: __replace_page() should not use page_address_in_vma() + uprobes: Kill write_opcode()->lock_page(new_page) + uprobes: Clean up and document write_opcode()->lock_page(old_page) + uprobes: Uprobe_mmap/munmap needs list_for_each_entry_safe() + uprobes: Suppress uprobe_munmap() from mmput() + uprobes: Fix overflow in vma_address()/find_active_uprobe() + uprobes: Remove copy_vma()->uprobe_mmap() + uprobes: Remove insert_vm_struct()->uprobe_mmap() + uprobes: Teach build_probe_list() to consider the range + uprobes: Introduce vaddr_to_offset(vma, vaddr) + uprobes: Fix register_for_each_vma()->vma_address() check + uprobes: Rename vma_address() and make it return "unsigned long" + uprobes: __replace_page() needs munlock_vma_page() + uprobes: Fix mmap_region()'s mm->mm_rb corruption if uprobe_mmap() fails + uprobes: Kill uprobes_state->count + uprobes: Kill dup_mmap()->uprobe_mmap(), simplify uprobe_mmap/munmap + uprobes: Change uprobe_mmap() to ignore the errors but check fatal_signal_pending() + uprobes: Do not use -EEXIST in install_breakpoint() paths + uprobes: Introduce MMF_HAS_UPROBES + uprobes: Fold uprobe_reset_state() into uprobe_dup_mmap() + uprobes: Remove "verify" argument from set_orig_insn() + uprobes: uprobes_treelock should not disable irqs + uprobes: Introduce MMF_RECALC_UPROBES + uprobes: Teach find_active_uprobe() to clear MMF_HAS_UPROBES + ptrace/x86: Introduce set_task_blockstep() helper + ptrace/x86: Partly fix set_task_blockstep()->update_debugctlmsr() logic + uprobes/x86: Do not (ab)use TIF_SINGLESTEP/user_*_single_step() for single-stepping + uprobes/x86: Xol should send SIGTRAP if X86_EFLAGS_TF was set + uprobes/x86: Fix arch_uprobe_disable_step() && UTASK_SSTEP_TRAPPED interaction + uprobes: Make arch_uprobe_task->saved_trap_nr "unsigned int" + +Peter Zijlstra (1): + uprobes: Document uprobe_register() vs uprobe_mmap() race + +Sebastian Andrzej Siewior (4): + uprobes: Remove check for uprobe variable in handle_swbp() + uprobes: Don't put NULL pointer in uprobe_register() + uprobes: Introduce arch_uprobe_enable/disable_step() + uprobes/x86: Implement x86 specific arch_uprobe_*_step + +Srikar Dronamraju (1): + uprobes: Remove redundant lock_page/unlock_page + +Signed-off-by: Anton Arapov +--- + arch/x86/include/asm/processor.h | 2 + + arch/x86/include/asm/uprobes.h | 5 +- + arch/x86/kernel/step.c | 53 ++- + arch/x86/kernel/uprobes.c | 55 ++- + include/linux/sched.h | 4 +- + include/linux/uprobes.h | 15 +- + kernel/events/uprobes.c | 819 +++++++++++++++++++-------------------- + kernel/fork.c | 6 +- + kernel/ptrace.c | 6 + + mm/mmap.c | 11 +- + 10 files changed, 505 insertions(+), 471 deletions(-) + +diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h +index 39bc577..2f9f8ca 100644 +--- a/arch/x86/include/asm/processor.h ++++ b/arch/x86/include/asm/processor.h +@@ -746,6 +746,8 @@ static inline void update_debugctlmsr(unsigned long debugctlmsr) + wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr); + } + ++extern void set_task_blockstep(struct task_struct *task, bool on); ++ + /* + * from system description table in BIOS. Mostly for MCA use, but + * others may find it useful: +diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h +index 1e9bed1..8ff8be7 100644 +--- a/arch/x86/include/asm/uprobes.h ++++ b/arch/x86/include/asm/uprobes.h +@@ -42,13 +42,14 @@ struct arch_uprobe { + }; + + struct arch_uprobe_task { +- unsigned long saved_trap_nr; + #ifdef CONFIG_X86_64 + unsigned long saved_scratch_register; + #endif ++ unsigned int saved_trap_nr; ++ unsigned int saved_tf; + }; + +-extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm); ++extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr); + extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs); + extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs); + extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk); +diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c +index c346d11..cd3b243 100644 +--- a/arch/x86/kernel/step.c ++++ b/arch/x86/kernel/step.c +@@ -157,6 +157,33 @@ static int enable_single_step(struct task_struct *child) + return 1; + } + ++void set_task_blockstep(struct task_struct *task, bool on) ++{ ++ unsigned long debugctl; ++ ++ /* ++ * Ensure irq/preemption can't change debugctl in between. ++ * Note also that both TIF_BLOCKSTEP and debugctl should ++ * be changed atomically wrt preemption. ++ * FIXME: this means that set/clear TIF_BLOCKSTEP is simply ++ * wrong if task != current, SIGKILL can wakeup the stopped ++ * tracee and set/clear can play with the running task, this ++ * can confuse the next __switch_to_xtra(). ++ */ ++ local_irq_disable(); ++ debugctl = get_debugctlmsr(); ++ if (on) { ++ debugctl |= DEBUGCTLMSR_BTF; ++ set_tsk_thread_flag(task, TIF_BLOCKSTEP); ++ } else { ++ debugctl &= ~DEBUGCTLMSR_BTF; ++ clear_tsk_thread_flag(task, TIF_BLOCKSTEP); ++ } ++ if (task == current) ++ update_debugctlmsr(debugctl); ++ local_irq_enable(); ++} ++ + /* + * Enable single or block step. + */ +@@ -169,19 +196,10 @@ static void enable_step(struct task_struct *child, bool block) + * So no one should try to use debugger block stepping in a program + * that uses user-mode single stepping itself. + */ +- if (enable_single_step(child) && block) { +- unsigned long debugctl = get_debugctlmsr(); +- +- debugctl |= DEBUGCTLMSR_BTF; +- update_debugctlmsr(debugctl); +- set_tsk_thread_flag(child, TIF_BLOCKSTEP); +- } else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { +- unsigned long debugctl = get_debugctlmsr(); +- +- debugctl &= ~DEBUGCTLMSR_BTF; +- update_debugctlmsr(debugctl); +- clear_tsk_thread_flag(child, TIF_BLOCKSTEP); +- } ++ if (enable_single_step(child) && block) ++ set_task_blockstep(child, true); ++ else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) ++ set_task_blockstep(child, false); + } + + void user_enable_single_step(struct task_struct *child) +@@ -199,13 +217,8 @@ void user_disable_single_step(struct task_struct *child) + /* + * Make sure block stepping (BTF) is disabled. + */ +- if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { +- unsigned long debugctl = get_debugctlmsr(); +- +- debugctl &= ~DEBUGCTLMSR_BTF; +- update_debugctlmsr(debugctl); +- clear_tsk_thread_flag(child, TIF_BLOCKSTEP); +- } ++ if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) ++ set_task_blockstep(child, false); + + /* Always clear TIF_SINGLESTEP... */ + clear_tsk_thread_flag(child, TIF_SINGLESTEP); +diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c +index dc4e910..9538f00 100644 +--- a/arch/x86/kernel/uprobes.c ++++ b/arch/x86/kernel/uprobes.c +@@ -41,6 +41,9 @@ + /* Adjust the return address of a call insn */ + #define UPROBE_FIX_CALL 0x2 + ++/* Instruction will modify TF, don't change it */ ++#define UPROBE_FIX_SETF 0x4 ++ + #define UPROBE_FIX_RIP_AX 0x8000 + #define UPROBE_FIX_RIP_CX 0x4000 + +@@ -239,6 +242,10 @@ static void prepare_fixups(struct arch_uprobe *auprobe, struct insn *insn) + insn_get_opcode(insn); /* should be a nop */ + + switch (OPCODE1(insn)) { ++ case 0x9d: ++ /* popf */ ++ auprobe->fixups |= UPROBE_FIX_SETF; ++ break; + case 0xc3: /* ret/lret */ + case 0xcb: + case 0xc2: +@@ -409,9 +416,10 @@ static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm, + * arch_uprobe_analyze_insn - instruction analysis including validity and fixups. + * @mm: the probed address space. + * @arch_uprobe: the probepoint information. ++ * @addr: virtual address at which to install the probepoint + * Return 0 on success or a -ve number on error. + */ +-int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm) ++int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr) + { + int ret; + struct insn insn; +@@ -645,7 +653,7 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) + * Skip these instructions as per the currently known x86 ISA. + * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 } + */ +-bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) ++static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) + { + int i; + +@@ -672,3 +680,46 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) + } + return false; + } ++ ++bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) ++{ ++ bool ret = __skip_sstep(auprobe, regs); ++ if (ret && (regs->flags & X86_EFLAGS_TF)) ++ send_sig(SIGTRAP, current, 0); ++ return ret; ++} ++ ++void arch_uprobe_enable_step(struct arch_uprobe *auprobe) ++{ ++ struct task_struct *task = current; ++ struct arch_uprobe_task *autask = &task->utask->autask; ++ struct pt_regs *regs = task_pt_regs(task); ++ ++ autask->saved_tf = !!(regs->flags & X86_EFLAGS_TF); ++ ++ regs->flags |= X86_EFLAGS_TF; ++ if (test_tsk_thread_flag(task, TIF_BLOCKSTEP)) ++ set_task_blockstep(task, false); ++} ++ ++void arch_uprobe_disable_step(struct arch_uprobe *auprobe) ++{ ++ struct task_struct *task = current; ++ struct arch_uprobe_task *autask = &task->utask->autask; ++ bool trapped = (task->utask->state == UTASK_SSTEP_TRAPPED); ++ struct pt_regs *regs = task_pt_regs(task); ++ /* ++ * The state of TIF_BLOCKSTEP was not saved so we can get an extra ++ * SIGTRAP if we do not clear TF. We need to examine the opcode to ++ * make it right. ++ */ ++ if (unlikely(trapped)) { ++ if (!autask->saved_tf) ++ regs->flags &= ~X86_EFLAGS_TF; ++ } else { ++ if (autask->saved_tf) ++ send_sig(SIGTRAP, task, 0); ++ else if (!(auprobe->fixups & UPROBE_FIX_SETF)) ++ regs->flags &= ~X86_EFLAGS_TF; ++ } ++} +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 4a1f493..864054f 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -441,6 +441,9 @@ extern int get_dumpable(struct mm_struct *mm); + #define MMF_VM_HUGEPAGE 17 /* set when VM_HUGEPAGE is set on vma */ + #define MMF_EXE_FILE_CHANGED 18 /* see prctl_set_mm_exe_file() */ + ++#define MMF_HAS_UPROBES 19 /* has uprobes */ ++#define MMF_RECALC_UPROBES 20 /* MMF_HAS_UPROBES can be wrong */ ++ + #define MMF_INIT_MASK (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK) + + struct sighand_struct { +@@ -1581,7 +1584,6 @@ struct task_struct { + #endif + #ifdef CONFIG_UPROBES + struct uprobe_task *utask; +- int uprobe_srcu_id; + #endif + }; + +diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h +index efe4b33..e6f0331 100644 +--- a/include/linux/uprobes.h ++++ b/include/linux/uprobes.h +@@ -99,25 +99,27 @@ struct xol_area { + + struct uprobes_state { + struct xol_area *xol_area; +- atomic_t count; + }; ++ + extern int __weak set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); +-extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr, bool verify); ++extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); + extern bool __weak is_swbp_insn(uprobe_opcode_t *insn); + extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); + extern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); + extern int uprobe_mmap(struct vm_area_struct *vma); + extern void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end); ++extern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm); + extern void uprobe_free_utask(struct task_struct *t); + extern void uprobe_copy_process(struct task_struct *t); + extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs); ++extern void __weak arch_uprobe_enable_step(struct arch_uprobe *arch); ++extern void __weak arch_uprobe_disable_step(struct arch_uprobe *arch); + extern int uprobe_post_sstep_notifier(struct pt_regs *regs); + extern int uprobe_pre_sstep_notifier(struct pt_regs *regs); + extern void uprobe_notify_resume(struct pt_regs *regs); + extern bool uprobe_deny_signal(void); + extern bool __weak arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs); + extern void uprobe_clear_state(struct mm_struct *mm); +-extern void uprobe_reset_state(struct mm_struct *mm); + #else /* !CONFIG_UPROBES */ + struct uprobes_state { + }; +@@ -138,6 +140,10 @@ static inline void + uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) + { + } ++static inline void ++uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm) ++{ ++} + static inline void uprobe_notify_resume(struct pt_regs *regs) + { + } +@@ -158,8 +164,5 @@ static inline void uprobe_copy_process(struct task_struct *t) + static inline void uprobe_clear_state(struct mm_struct *mm) + { + } +-static inline void uprobe_reset_state(struct mm_struct *mm) +-{ +-} + #endif /* !CONFIG_UPROBES */ + #endif /* _LINUX_UPROBES_H */ +diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c +index 985be4d..f8a97e7 100644 +--- a/kernel/events/uprobes.c ++++ b/kernel/events/uprobes.c +@@ -27,24 +27,42 @@ + #include /* read_mapping_page */ + #include + #include ++#include + #include /* anon_vma_prepare */ + #include /* set_pte_at_notify */ + #include /* try_to_free_swap */ + #include /* user_enable_single_step */ + #include /* notifier mechanism */ ++#include "../../mm/internal.h" /* munlock_vma_page */ + + #include + + #define UINSNS_PER_PAGE (PAGE_SIZE/UPROBE_XOL_SLOT_BYTES) + #define MAX_UPROBE_XOL_SLOTS UINSNS_PER_PAGE + +-static struct srcu_struct uprobes_srcu; + static struct rb_root uprobes_tree = RB_ROOT; + + static DEFINE_SPINLOCK(uprobes_treelock); /* serialize rbtree access */ + + #define UPROBES_HASH_SZ 13 + ++/* ++ * We need separate register/unregister and mmap/munmap lock hashes because ++ * of mmap_sem nesting. ++ * ++ * uprobe_register() needs to install probes on (potentially) all processes ++ * and thus needs to acquire multiple mmap_sems (consequtively, not ++ * concurrently), whereas uprobe_mmap() is called while holding mmap_sem ++ * for the particular process doing the mmap. ++ * ++ * uprobe_register()->register_for_each_vma() needs to drop/acquire mmap_sem ++ * because of lock order against i_mmap_mutex. This means there's a hole in ++ * the register vma iteration where a mmap() can happen. ++ * ++ * Thus uprobe_register() can race with uprobe_mmap() and we can try and ++ * install a probe where one is already installed. ++ */ ++ + /* serialize (un)register */ + static struct mutex uprobes_mutex[UPROBES_HASH_SZ]; + +@@ -61,17 +79,6 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ]; + */ + static atomic_t uprobe_events = ATOMIC_INIT(0); + +-/* +- * Maintain a temporary per vma info that can be used to search if a vma +- * has already been handled. This structure is introduced since extending +- * vm_area_struct wasnt recommended. +- */ +-struct vma_info { +- struct list_head probe_list; +- struct mm_struct *mm; +- loff_t vaddr; +-}; +- + struct uprobe { + struct rb_node rb_node; /* node in the rb tree */ + atomic_t ref; +@@ -100,20 +107,21 @@ static bool valid_vma(struct vm_area_struct *vma, bool is_register) + if (!is_register) + return true; + +- if ((vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) == (VM_READ|VM_EXEC)) ++ if ((vma->vm_flags & (VM_HUGETLB|VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) ++ == (VM_READ|VM_EXEC)) + return true; + + return false; + } + +-static loff_t vma_address(struct vm_area_struct *vma, loff_t offset) ++static unsigned long offset_to_vaddr(struct vm_area_struct *vma, loff_t offset) + { +- loff_t vaddr; +- +- vaddr = vma->vm_start + offset; +- vaddr -= vma->vm_pgoff << PAGE_SHIFT; ++ return vma->vm_start + offset - ((loff_t)vma->vm_pgoff << PAGE_SHIFT); ++} + +- return vaddr; ++static loff_t vaddr_to_offset(struct vm_area_struct *vma, unsigned long vaddr) ++{ ++ return ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (vaddr - vma->vm_start); + } + + /** +@@ -121,41 +129,27 @@ static loff_t vma_address(struct vm_area_struct *vma, loff_t offset) + * based on replace_page in mm/ksm.c + * + * @vma: vma that holds the pte pointing to page ++ * @addr: address the old @page is mapped at + * @page: the cowed page we are replacing by kpage + * @kpage: the modified page we replace page by + * + * Returns 0 on success, -EFAULT on failure. + */ +-static int __replace_page(struct vm_area_struct *vma, struct page *page, struct page *kpage) ++static int __replace_page(struct vm_area_struct *vma, unsigned long addr, ++ struct page *page, struct page *kpage) + { + struct mm_struct *mm = vma->vm_mm; +- pgd_t *pgd; +- pud_t *pud; +- pmd_t *pmd; +- pte_t *ptep; + spinlock_t *ptl; +- unsigned long addr; +- int err = -EFAULT; +- +- addr = page_address_in_vma(page, vma); +- if (addr == -EFAULT) +- goto out; +- +- pgd = pgd_offset(mm, addr); +- if (!pgd_present(*pgd)) +- goto out; +- +- pud = pud_offset(pgd, addr); +- if (!pud_present(*pud)) +- goto out; ++ pte_t *ptep; ++ int err; + +- pmd = pmd_offset(pud, addr); +- if (!pmd_present(*pmd)) +- goto out; ++ /* For try_to_free_swap() and munlock_vma_page() below */ ++ lock_page(page); + +- ptep = pte_offset_map_lock(mm, pmd, addr, &ptl); ++ err = -EAGAIN; ++ ptep = page_check_address(page, mm, addr, &ptl, 0); + if (!ptep) +- goto out; ++ goto unlock; + + get_page(kpage); + page_add_new_anon_rmap(kpage, vma, addr); +@@ -172,11 +166,15 @@ static int __replace_page(struct vm_area_struct *vma, struct page *page, struct + page_remove_rmap(page); + if (!page_mapped(page)) + try_to_free_swap(page); +- put_page(page); + pte_unmap_unlock(ptep, ptl); +- err = 0; + +-out: ++ if (vma->vm_flags & VM_LOCKED) ++ munlock_vma_page(page); ++ put_page(page); ++ ++ err = 0; ++ unlock: ++ unlock_page(page); + return err; + } + +@@ -218,79 +216,46 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, + unsigned long vaddr, uprobe_opcode_t opcode) + { + struct page *old_page, *new_page; +- struct address_space *mapping; + void *vaddr_old, *vaddr_new; + struct vm_area_struct *vma; +- struct uprobe *uprobe; +- loff_t addr; + int ret; + ++retry: + /* Read the page with vaddr into memory */ + ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma); + if (ret <= 0) + return ret; + +- ret = -EINVAL; +- +- /* +- * We are interested in text pages only. Our pages of interest +- * should be mapped for read and execute only. We desist from +- * adding probes in write mapped pages since the breakpoints +- * might end up in the file copy. +- */ +- if (!valid_vma(vma, is_swbp_insn(&opcode))) +- goto put_out; +- +- uprobe = container_of(auprobe, struct uprobe, arch); +- mapping = uprobe->inode->i_mapping; +- if (mapping != vma->vm_file->f_mapping) +- goto put_out; +- +- addr = vma_address(vma, uprobe->offset); +- if (vaddr != (unsigned long)addr) +- goto put_out; +- + ret = -ENOMEM; + new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr); + if (!new_page) +- goto put_out; ++ goto put_old; + + __SetPageUptodate(new_page); + +- /* +- * lock page will serialize against do_wp_page()'s +- * PageAnon() handling +- */ +- lock_page(old_page); + /* copy the page now that we've got it stable */ + vaddr_old = kmap_atomic(old_page); + vaddr_new = kmap_atomic(new_page); + + memcpy(vaddr_new, vaddr_old, PAGE_SIZE); +- +- /* poke the new insn in, ASSUMES we don't cross page boundary */ +- vaddr &= ~PAGE_MASK; +- BUG_ON(vaddr + UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); +- memcpy(vaddr_new + vaddr, &opcode, UPROBE_SWBP_INSN_SIZE); ++ memcpy(vaddr_new + (vaddr & ~PAGE_MASK), &opcode, UPROBE_SWBP_INSN_SIZE); + + kunmap_atomic(vaddr_new); + kunmap_atomic(vaddr_old); + + ret = anon_vma_prepare(vma); + if (ret) +- goto unlock_out; ++ goto put_new; + +- lock_page(new_page); +- ret = __replace_page(vma, old_page, new_page); +- unlock_page(new_page); ++ ret = __replace_page(vma, vaddr, old_page, new_page); + +-unlock_out: +- unlock_page(old_page); ++put_new: + page_cache_release(new_page); +- +-put_out: ++put_old: + put_page(old_page); + ++ if (unlikely(ret == -EAGAIN)) ++ goto retry; + return ret; + } + +@@ -312,16 +277,14 @@ static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_ + void *vaddr_new; + int ret; + +- ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &page, NULL); ++ ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL); + if (ret <= 0) + return ret; + +- lock_page(page); + vaddr_new = kmap_atomic(page); + vaddr &= ~PAGE_MASK; + memcpy(opcode, vaddr_new + vaddr, UPROBE_SWBP_INSN_SIZE); + kunmap_atomic(vaddr_new); +- unlock_page(page); + + put_page(page); + +@@ -333,10 +296,20 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) + uprobe_opcode_t opcode; + int result; + ++ if (current->mm == mm) { ++ pagefault_disable(); ++ result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr, ++ sizeof(opcode)); ++ pagefault_enable(); ++ ++ if (likely(result == 0)) ++ goto out; ++ } ++ + result = read_opcode(mm, vaddr, &opcode); + if (result) + return result; +- ++out: + if (is_swbp_insn(&opcode)) + return 1; + +@@ -355,10 +328,12 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) + int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) + { + int result; +- ++ /* ++ * See the comment near uprobes_hash(). ++ */ + result = is_swbp_at_addr(mm, vaddr); + if (result == 1) +- return -EEXIST; ++ return 0; + + if (result) + return result; +@@ -371,24 +346,22 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned + * @mm: the probed process address space. + * @auprobe: arch specific probepoint information. + * @vaddr: the virtual address to insert the opcode. +- * @verify: if true, verify existance of breakpoint instruction. + * + * For mm @mm, restore the original opcode (opcode) at @vaddr. + * Return 0 (success) or a negative errno. + */ + int __weak +-set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr, bool verify) ++set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) + { +- if (verify) { +- int result; ++ int result; + +- result = is_swbp_at_addr(mm, vaddr); +- if (!result) +- return -EINVAL; ++ result = is_swbp_at_addr(mm, vaddr); ++ if (!result) ++ return -EINVAL; ++ ++ if (result != 1) ++ return result; + +- if (result != 1) +- return result; +- } + return write_opcode(auprobe, mm, vaddr, *(uprobe_opcode_t *)auprobe->insn); + } + +@@ -439,11 +412,10 @@ static struct uprobe *__find_uprobe(struct inode *inode, loff_t offset) + static struct uprobe *find_uprobe(struct inode *inode, loff_t offset) + { + struct uprobe *uprobe; +- unsigned long flags; + +- spin_lock_irqsave(&uprobes_treelock, flags); ++ spin_lock(&uprobes_treelock); + uprobe = __find_uprobe(inode, offset); +- spin_unlock_irqrestore(&uprobes_treelock, flags); ++ spin_unlock(&uprobes_treelock); + + return uprobe; + } +@@ -490,12 +462,11 @@ static struct uprobe *__insert_uprobe(struct uprobe *uprobe) + */ + static struct uprobe *insert_uprobe(struct uprobe *uprobe) + { +- unsigned long flags; + struct uprobe *u; + +- spin_lock_irqsave(&uprobes_treelock, flags); ++ spin_lock(&uprobes_treelock); + u = __insert_uprobe(uprobe); +- spin_unlock_irqrestore(&uprobes_treelock, flags); ++ spin_unlock(&uprobes_treelock); + + /* For now assume that the instruction need not be single-stepped */ + uprobe->flags |= UPROBE_SKIP_SSTEP; +@@ -520,7 +491,6 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset) + uprobe->inode = igrab(inode); + uprobe->offset = offset; + init_rwsem(&uprobe->consumer_rwsem); +- INIT_LIST_HEAD(&uprobe->pending_list); + + /* add to uprobes_tree, sorted on inode:offset */ + cur_uprobe = insert_uprobe(uprobe); +@@ -588,20 +558,22 @@ static bool consumer_del(struct uprobe *uprobe, struct uprobe_consumer *uc) + } + + static int +-__copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *insn, +- unsigned long nbytes, unsigned long offset) ++__copy_insn(struct address_space *mapping, struct file *filp, char *insn, ++ unsigned long nbytes, loff_t offset) + { +- struct file *filp = vma->vm_file; + struct page *page; + void *vaddr; +- unsigned long off1; +- unsigned long idx; ++ unsigned long off; ++ pgoff_t idx; + + if (!filp) + return -EINVAL; + +- idx = (unsigned long)(offset >> PAGE_CACHE_SHIFT); +- off1 = offset &= ~PAGE_MASK; ++ if (!mapping->a_ops->readpage) ++ return -EIO; ++ ++ idx = offset >> PAGE_CACHE_SHIFT; ++ off = offset & ~PAGE_MASK; + + /* + * Ensure that the page that has the original instruction is +@@ -612,22 +584,20 @@ __copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *ins + return PTR_ERR(page); + + vaddr = kmap_atomic(page); +- memcpy(insn, vaddr + off1, nbytes); ++ memcpy(insn, vaddr + off, nbytes); + kunmap_atomic(vaddr); + page_cache_release(page); + + return 0; + } + +-static int +-copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr) ++static int copy_insn(struct uprobe *uprobe, struct file *filp) + { + struct address_space *mapping; + unsigned long nbytes; + int bytes; + +- addr &= ~PAGE_MASK; +- nbytes = PAGE_SIZE - addr; ++ nbytes = PAGE_SIZE - (uprobe->offset & ~PAGE_MASK); + mapping = uprobe->inode->i_mapping; + + /* Instruction at end of binary; copy only available bytes */ +@@ -638,13 +608,13 @@ copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr) + + /* Instruction at the page-boundary; copy bytes in second page */ + if (nbytes < bytes) { +- if (__copy_insn(mapping, vma, uprobe->arch.insn + nbytes, +- bytes - nbytes, uprobe->offset + nbytes)) +- return -ENOMEM; +- ++ int err = __copy_insn(mapping, filp, uprobe->arch.insn + nbytes, ++ bytes - nbytes, uprobe->offset + nbytes); ++ if (err) ++ return err; + bytes = nbytes; + } +- return __copy_insn(mapping, vma, uprobe->arch.insn, bytes, uprobe->offset); ++ return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset); + } + + /* +@@ -672,9 +642,9 @@ copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr) + */ + static int + install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, +- struct vm_area_struct *vma, loff_t vaddr) ++ struct vm_area_struct *vma, unsigned long vaddr) + { +- unsigned long addr; ++ bool first_uprobe; + int ret; + + /* +@@ -685,204 +655,194 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, + * Hence behave as if probe already existed. + */ + if (!uprobe->consumers) +- return -EEXIST; +- +- addr = (unsigned long)vaddr; ++ return 0; + + if (!(uprobe->flags & UPROBE_COPY_INSN)) { +- ret = copy_insn(uprobe, vma, addr); ++ ret = copy_insn(uprobe, vma->vm_file); + if (ret) + return ret; + + if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) +- return -EEXIST; ++ return -ENOTSUPP; + +- ret = arch_uprobe_analyze_insn(&uprobe->arch, mm); ++ ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr); + if (ret) + return ret; + ++ /* write_opcode() assumes we don't cross page boundary */ ++ BUG_ON((uprobe->offset & ~PAGE_MASK) + ++ UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); ++ + uprobe->flags |= UPROBE_COPY_INSN; + } + + /* +- * Ideally, should be updating the probe count after the breakpoint +- * has been successfully inserted. However a thread could hit the +- * breakpoint we just inserted even before the probe count is +- * incremented. If this is the first breakpoint placed, breakpoint +- * notifier might ignore uprobes and pass the trap to the thread. +- * Hence increment before and decrement on failure. ++ * set MMF_HAS_UPROBES in advance for uprobe_pre_sstep_notifier(), ++ * the task can hit this breakpoint right after __replace_page(). + */ +- atomic_inc(&mm->uprobes_state.count); +- ret = set_swbp(&uprobe->arch, mm, addr); +- if (ret) +- atomic_dec(&mm->uprobes_state.count); ++ first_uprobe = !test_bit(MMF_HAS_UPROBES, &mm->flags); ++ if (first_uprobe) ++ set_bit(MMF_HAS_UPROBES, &mm->flags); ++ ++ ret = set_swbp(&uprobe->arch, mm, vaddr); ++ if (!ret) ++ clear_bit(MMF_RECALC_UPROBES, &mm->flags); ++ else if (first_uprobe) ++ clear_bit(MMF_HAS_UPROBES, &mm->flags); + + return ret; + } + + static void +-remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, loff_t vaddr) ++remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr) + { +- if (!set_orig_insn(&uprobe->arch, mm, (unsigned long)vaddr, true)) +- atomic_dec(&mm->uprobes_state.count); ++ /* can happen if uprobe_register() fails */ ++ if (!test_bit(MMF_HAS_UPROBES, &mm->flags)) ++ return; ++ ++ set_bit(MMF_RECALC_UPROBES, &mm->flags); ++ set_orig_insn(&uprobe->arch, mm, vaddr); + } + + /* +- * There could be threads that have hit the breakpoint and are entering the +- * notifier code and trying to acquire the uprobes_treelock. The thread +- * calling delete_uprobe() that is removing the uprobe from the rb_tree can +- * race with these threads and might acquire the uprobes_treelock compared +- * to some of the breakpoint hit threads. In such a case, the breakpoint +- * hit threads will not find the uprobe. The current unregistering thread +- * waits till all other threads have hit a breakpoint, to acquire the +- * uprobes_treelock before the uprobe is removed from the rbtree. ++ * There could be threads that have already hit the breakpoint. They ++ * will recheck the current insn and restart if find_uprobe() fails. ++ * See find_active_uprobe(). + */ + static void delete_uprobe(struct uprobe *uprobe) + { +- unsigned long flags; +- +- synchronize_srcu(&uprobes_srcu); +- spin_lock_irqsave(&uprobes_treelock, flags); ++ spin_lock(&uprobes_treelock); + rb_erase(&uprobe->rb_node, &uprobes_tree); +- spin_unlock_irqrestore(&uprobes_treelock, flags); ++ spin_unlock(&uprobes_treelock); + iput(uprobe->inode); + put_uprobe(uprobe); + atomic_dec(&uprobe_events); + } + +-static struct vma_info * +-__find_next_vma_info(struct address_space *mapping, struct list_head *head, +- struct vma_info *vi, loff_t offset, bool is_register) ++struct map_info { ++ struct map_info *next; ++ struct mm_struct *mm; ++ unsigned long vaddr; ++}; ++ ++static inline struct map_info *free_map_info(struct map_info *info) ++{ ++ struct map_info *next = info->next; ++ kfree(info); ++ return next; ++} ++ ++static struct map_info * ++build_map_info(struct address_space *mapping, loff_t offset, bool is_register) + { ++ unsigned long pgoff = offset >> PAGE_SHIFT; + struct prio_tree_iter iter; + struct vm_area_struct *vma; +- struct vma_info *tmpvi; +- unsigned long pgoff; +- int existing_vma; +- loff_t vaddr; +- +- pgoff = offset >> PAGE_SHIFT; ++ struct map_info *curr = NULL; ++ struct map_info *prev = NULL; ++ struct map_info *info; ++ int more = 0; + ++ again: ++ mutex_lock(&mapping->i_mmap_mutex); + vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { + if (!valid_vma(vma, is_register)) + continue; + +- existing_vma = 0; +- vaddr = vma_address(vma, offset); +- +- list_for_each_entry(tmpvi, head, probe_list) { +- if (tmpvi->mm == vma->vm_mm && tmpvi->vaddr == vaddr) { +- existing_vma = 1; +- break; +- } ++ if (!prev && !more) { ++ /* ++ * Needs GFP_NOWAIT to avoid i_mmap_mutex recursion through ++ * reclaim. This is optimistic, no harm done if it fails. ++ */ ++ prev = kmalloc(sizeof(struct map_info), ++ GFP_NOWAIT | __GFP_NOMEMALLOC | __GFP_NOWARN); ++ if (prev) ++ prev->next = NULL; + } +- +- /* +- * Another vma needs a probe to be installed. However skip +- * installing the probe if the vma is about to be unlinked. +- */ +- if (!existing_vma && atomic_inc_not_zero(&vma->vm_mm->mm_users)) { +- vi->mm = vma->vm_mm; +- vi->vaddr = vaddr; +- list_add(&vi->probe_list, head); +- +- return vi; ++ if (!prev) { ++ more++; ++ continue; + } +- } +- +- return NULL; +-} + +-/* +- * Iterate in the rmap prio tree and find a vma where a probe has not +- * yet been inserted. +- */ +-static struct vma_info * +-find_next_vma_info(struct address_space *mapping, struct list_head *head, +- loff_t offset, bool is_register) +-{ +- struct vma_info *vi, *retvi; ++ if (!atomic_inc_not_zero(&vma->vm_mm->mm_users)) ++ continue; + +- vi = kzalloc(sizeof(struct vma_info), GFP_KERNEL); +- if (!vi) +- return ERR_PTR(-ENOMEM); ++ info = prev; ++ prev = prev->next; ++ info->next = curr; ++ curr = info; + +- mutex_lock(&mapping->i_mmap_mutex); +- retvi = __find_next_vma_info(mapping, head, vi, offset, is_register); ++ info->mm = vma->vm_mm; ++ info->vaddr = offset_to_vaddr(vma, offset); ++ } + mutex_unlock(&mapping->i_mmap_mutex); + +- if (!retvi) +- kfree(vi); ++ if (!more) ++ goto out; ++ ++ prev = curr; ++ while (curr) { ++ mmput(curr->mm); ++ curr = curr->next; ++ } + +- return retvi; ++ do { ++ info = kmalloc(sizeof(struct map_info), GFP_KERNEL); ++ if (!info) { ++ curr = ERR_PTR(-ENOMEM); ++ goto out; ++ } ++ info->next = prev; ++ prev = info; ++ } while (--more); ++ ++ goto again; ++ out: ++ while (prev) ++ prev = free_map_info(prev); ++ return curr; + } + + static int register_for_each_vma(struct uprobe *uprobe, bool is_register) + { +- struct list_head try_list; +- struct vm_area_struct *vma; +- struct address_space *mapping; +- struct vma_info *vi, *tmpvi; +- struct mm_struct *mm; +- loff_t vaddr; +- int ret; ++ struct map_info *info; ++ int err = 0; + +- mapping = uprobe->inode->i_mapping; +- INIT_LIST_HEAD(&try_list); ++ info = build_map_info(uprobe->inode->i_mapping, ++ uprobe->offset, is_register); ++ if (IS_ERR(info)) ++ return PTR_ERR(info); + +- ret = 0; ++ while (info) { ++ struct mm_struct *mm = info->mm; ++ struct vm_area_struct *vma; + +- for (;;) { +- vi = find_next_vma_info(mapping, &try_list, uprobe->offset, is_register); +- if (!vi) +- break; ++ if (err) ++ goto free; + +- if (IS_ERR(vi)) { +- ret = PTR_ERR(vi); +- break; +- } ++ down_write(&mm->mmap_sem); ++ vma = find_vma(mm, info->vaddr); ++ if (!vma || !valid_vma(vma, is_register) || ++ vma->vm_file->f_mapping->host != uprobe->inode) ++ goto unlock; + +- mm = vi->mm; +- down_read(&mm->mmap_sem); +- vma = find_vma(mm, (unsigned long)vi->vaddr); +- if (!vma || !valid_vma(vma, is_register)) { +- list_del(&vi->probe_list); +- kfree(vi); +- up_read(&mm->mmap_sem); +- mmput(mm); +- continue; +- } +- vaddr = vma_address(vma, uprobe->offset); +- if (vma->vm_file->f_mapping->host != uprobe->inode || +- vaddr != vi->vaddr) { +- list_del(&vi->probe_list); +- kfree(vi); +- up_read(&mm->mmap_sem); +- mmput(mm); +- continue; +- } ++ if (vma->vm_start > info->vaddr || ++ vaddr_to_offset(vma, info->vaddr) != uprobe->offset) ++ goto unlock; + + if (is_register) +- ret = install_breakpoint(uprobe, mm, vma, vi->vaddr); ++ err = install_breakpoint(uprobe, mm, vma, info->vaddr); + else +- remove_breakpoint(uprobe, mm, vi->vaddr); ++ remove_breakpoint(uprobe, mm, info->vaddr); + +- up_read(&mm->mmap_sem); ++ unlock: ++ up_write(&mm->mmap_sem); ++ free: + mmput(mm); +- if (is_register) { +- if (ret && ret == -EEXIST) +- ret = 0; +- if (ret) +- break; +- } +- } +- +- list_for_each_entry_safe(vi, tmpvi, &try_list, probe_list) { +- list_del(&vi->probe_list); +- kfree(vi); ++ info = free_map_info(info); + } + +- return ret; ++ return err; + } + + static int __uprobe_register(struct uprobe *uprobe) +@@ -941,10 +901,12 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer * + } + + mutex_unlock(uprobes_hash(inode)); +- put_uprobe(uprobe); ++ if (uprobe) ++ put_uprobe(uprobe); + + return ret; + } ++EXPORT_SYMBOL_GPL(uprobe_register); + + /* + * uprobe_unregister - unregister a already registered probe. +@@ -976,81 +938,81 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume + if (uprobe) + put_uprobe(uprobe); + } ++EXPORT_SYMBOL_GPL(uprobe_unregister); + +-/* +- * Of all the nodes that correspond to the given inode, return the node +- * with the least offset. +- */ +-static struct rb_node *find_least_offset_node(struct inode *inode) ++static struct rb_node * ++find_node_in_range(struct inode *inode, loff_t min, loff_t max) + { +- struct uprobe u = { .inode = inode, .offset = 0}; + struct rb_node *n = uprobes_tree.rb_node; +- struct rb_node *close_node = NULL; +- struct uprobe *uprobe; +- int match; + + while (n) { +- uprobe = rb_entry(n, struct uprobe, rb_node); +- match = match_uprobe(&u, uprobe); +- +- if (uprobe->inode == inode) +- close_node = n; +- +- if (!match) +- return close_node; ++ struct uprobe *u = rb_entry(n, struct uprobe, rb_node); + +- if (match < 0) ++ if (inode < u->inode) { + n = n->rb_left; +- else ++ } else if (inode > u->inode) { + n = n->rb_right; ++ } else { ++ if (max < u->offset) ++ n = n->rb_left; ++ else if (min > u->offset) ++ n = n->rb_right; ++ else ++ break; ++ } + } + +- return close_node; ++ return n; + } + + /* +- * For a given inode, build a list of probes that need to be inserted. ++ * For a given range in vma, build a list of probes that need to be inserted. + */ +-static void build_probe_list(struct inode *inode, struct list_head *head) ++static void build_probe_list(struct inode *inode, ++ struct vm_area_struct *vma, ++ unsigned long start, unsigned long end, ++ struct list_head *head) + { +- struct uprobe *uprobe; +- unsigned long flags; +- struct rb_node *n; +- +- spin_lock_irqsave(&uprobes_treelock, flags); +- +- n = find_least_offset_node(inode); ++ loff_t min, max; ++ struct rb_node *n, *t; ++ struct uprobe *u; + +- for (; n; n = rb_next(n)) { +- uprobe = rb_entry(n, struct uprobe, rb_node); +- if (uprobe->inode != inode) +- break; ++ INIT_LIST_HEAD(head); ++ min = vaddr_to_offset(vma, start); ++ max = min + (end - start) - 1; + +- list_add(&uprobe->pending_list, head); +- atomic_inc(&uprobe->ref); ++ spin_lock(&uprobes_treelock); ++ n = find_node_in_range(inode, min, max); ++ if (n) { ++ for (t = n; t; t = rb_prev(t)) { ++ u = rb_entry(t, struct uprobe, rb_node); ++ if (u->inode != inode || u->offset < min) ++ break; ++ list_add(&u->pending_list, head); ++ atomic_inc(&u->ref); ++ } ++ for (t = n; (t = rb_next(t)); ) { ++ u = rb_entry(t, struct uprobe, rb_node); ++ if (u->inode != inode || u->offset > max) ++ break; ++ list_add(&u->pending_list, head); ++ atomic_inc(&u->ref); ++ } + } +- +- spin_unlock_irqrestore(&uprobes_treelock, flags); ++ spin_unlock(&uprobes_treelock); + } + + /* +- * Called from mmap_region. +- * called with mm->mmap_sem acquired. +- * +- * Return -ve no if we fail to insert probes and we cannot +- * bail-out. +- * Return 0 otherwise. i.e: ++ * Called from mmap_region/vma_adjust with mm->mmap_sem acquired. + * +- * - successful insertion of probes +- * - (or) no possible probes to be inserted. +- * - (or) insertion of probes failed but we can bail-out. ++ * Currently we ignore all errors and always return 0, the callers ++ * can't handle the failure anyway. + */ + int uprobe_mmap(struct vm_area_struct *vma) + { + struct list_head tmp_list; + struct uprobe *uprobe, *u; + struct inode *inode; +- int ret, count; + + if (!atomic_read(&uprobe_events) || !valid_vma(vma, true)) + return 0; +@@ -1059,54 +1021,38 @@ int uprobe_mmap(struct vm_area_struct *vma) + if (!inode) + return 0; + +- INIT_LIST_HEAD(&tmp_list); + mutex_lock(uprobes_mmap_hash(inode)); +- build_probe_list(inode, &tmp_list); +- +- ret = 0; +- count = 0; ++ build_probe_list(inode, vma, vma->vm_start, vma->vm_end, &tmp_list); + + list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { +- loff_t vaddr; +- +- list_del(&uprobe->pending_list); +- if (!ret) { +- vaddr = vma_address(vma, uprobe->offset); +- +- if (vaddr < vma->vm_start || vaddr >= vma->vm_end) { +- put_uprobe(uprobe); +- continue; +- } +- +- ret = install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); +- +- /* Ignore double add: */ +- if (ret == -EEXIST) { +- ret = 0; +- +- if (!is_swbp_at_addr(vma->vm_mm, vaddr)) +- continue; +- +- /* +- * Unable to insert a breakpoint, but +- * breakpoint lies underneath. Increment the +- * probe count. +- */ +- atomic_inc(&vma->vm_mm->uprobes_state.count); +- } +- +- if (!ret) +- count++; ++ if (!fatal_signal_pending(current)) { ++ unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset); ++ install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); + } + put_uprobe(uprobe); + } +- + mutex_unlock(uprobes_mmap_hash(inode)); + +- if (ret) +- atomic_sub(count, &vma->vm_mm->uprobes_state.count); ++ return 0; ++} + +- return ret; ++static bool ++vma_has_uprobes(struct vm_area_struct *vma, unsigned long start, unsigned long end) ++{ ++ loff_t min, max; ++ struct inode *inode; ++ struct rb_node *n; ++ ++ inode = vma->vm_file->f_mapping->host; ++ ++ min = vaddr_to_offset(vma, start); ++ max = min + (end - start) - 1; ++ ++ spin_lock(&uprobes_treelock); ++ n = find_node_in_range(inode, min, max); ++ spin_unlock(&uprobes_treelock); ++ ++ return !!n; + } + + /* +@@ -1114,41 +1060,18 @@ int uprobe_mmap(struct vm_area_struct *vma) + */ + void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) + { +- struct list_head tmp_list; +- struct uprobe *uprobe, *u; +- struct inode *inode; +- + if (!atomic_read(&uprobe_events) || !valid_vma(vma, false)) + return; + +- if (!atomic_read(&vma->vm_mm->uprobes_state.count)) ++ if (!atomic_read(&vma->vm_mm->mm_users)) /* called by mmput() ? */ + return; + +- inode = vma->vm_file->f_mapping->host; +- if (!inode) ++ if (!test_bit(MMF_HAS_UPROBES, &vma->vm_mm->flags) || ++ test_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags)) + return; + +- INIT_LIST_HEAD(&tmp_list); +- mutex_lock(uprobes_mmap_hash(inode)); +- build_probe_list(inode, &tmp_list); +- +- list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { +- loff_t vaddr; +- +- list_del(&uprobe->pending_list); +- vaddr = vma_address(vma, uprobe->offset); +- +- if (vaddr >= start && vaddr < end) { +- /* +- * An unregister could have removed the probe before +- * unmap. So check before we decrement the count. +- */ +- if (is_swbp_at_addr(vma->vm_mm, vaddr) == 1) +- atomic_dec(&vma->vm_mm->uprobes_state.count); +- } +- put_uprobe(uprobe); +- } +- mutex_unlock(uprobes_mmap_hash(inode)); ++ if (vma_has_uprobes(vma, start, end)) ++ set_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags); + } + + /* Slot allocation for XOL */ +@@ -1250,13 +1173,15 @@ void uprobe_clear_state(struct mm_struct *mm) + kfree(area); + } + +-/* +- * uprobe_reset_state - Free the area allocated for slots. +- */ +-void uprobe_reset_state(struct mm_struct *mm) ++void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm) + { +- mm->uprobes_state.xol_area = NULL; +- atomic_set(&mm->uprobes_state.count, 0); ++ newmm->uprobes_state.xol_area = NULL; ++ ++ if (test_bit(MMF_HAS_UPROBES, &oldmm->flags)) { ++ set_bit(MMF_HAS_UPROBES, &newmm->flags); ++ /* unconditionally, dup_mmap() skips VM_DONTCOPY vmas */ ++ set_bit(MMF_RECALC_UPROBES, &newmm->flags); ++ } + } + + /* +@@ -1378,9 +1303,6 @@ void uprobe_free_utask(struct task_struct *t) + { + struct uprobe_task *utask = t->utask; + +- if (t->uprobe_srcu_id != -1) +- srcu_read_unlock_raw(&uprobes_srcu, t->uprobe_srcu_id); +- + if (!utask) + return; + +@@ -1398,7 +1320,6 @@ void uprobe_free_utask(struct task_struct *t) + void uprobe_copy_process(struct task_struct *t) + { + t->utask = NULL; +- t->uprobe_srcu_id = -1; + } + + /* +@@ -1417,7 +1338,6 @@ static struct uprobe_task *add_utask(void) + if (unlikely(!utask)) + return NULL; + +- utask->active_uprobe = NULL; + current->utask = utask; + return utask; + } +@@ -1479,41 +1399,93 @@ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs) + return false; + } + ++static void mmf_recalc_uprobes(struct mm_struct *mm) ++{ ++ struct vm_area_struct *vma; ++ ++ for (vma = mm->mmap; vma; vma = vma->vm_next) { ++ if (!valid_vma(vma, false)) ++ continue; ++ /* ++ * This is not strictly accurate, we can race with ++ * uprobe_unregister() and see the already removed ++ * uprobe if delete_uprobe() was not yet called. ++ */ ++ if (vma_has_uprobes(vma, vma->vm_start, vma->vm_end)) ++ return; ++ } ++ ++ clear_bit(MMF_HAS_UPROBES, &mm->flags); ++} ++ ++static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) ++{ ++ struct mm_struct *mm = current->mm; ++ struct uprobe *uprobe = NULL; ++ struct vm_area_struct *vma; ++ ++ down_read(&mm->mmap_sem); ++ vma = find_vma(mm, bp_vaddr); ++ if (vma && vma->vm_start <= bp_vaddr) { ++ if (valid_vma(vma, false)) { ++ struct inode *inode = vma->vm_file->f_mapping->host; ++ loff_t offset = vaddr_to_offset(vma, bp_vaddr); ++ ++ uprobe = find_uprobe(inode, offset); ++ } ++ ++ if (!uprobe) ++ *is_swbp = is_swbp_at_addr(mm, bp_vaddr); ++ } else { ++ *is_swbp = -EFAULT; ++ } ++ ++ if (!uprobe && test_and_clear_bit(MMF_RECALC_UPROBES, &mm->flags)) ++ mmf_recalc_uprobes(mm); ++ up_read(&mm->mmap_sem); ++ ++ return uprobe; ++} ++ ++void __weak arch_uprobe_enable_step(struct arch_uprobe *arch) ++{ ++ user_enable_single_step(current); ++} ++ ++void __weak arch_uprobe_disable_step(struct arch_uprobe *arch) ++{ ++ user_disable_single_step(current); ++} ++ + /* + * Run handler and ask thread to singlestep. + * Ensure all non-fatal signals cannot interrupt thread while it singlesteps. + */ + static void handle_swbp(struct pt_regs *regs) + { +- struct vm_area_struct *vma; + struct uprobe_task *utask; + struct uprobe *uprobe; +- struct mm_struct *mm; + unsigned long bp_vaddr; ++ int uninitialized_var(is_swbp); + +- uprobe = NULL; + bp_vaddr = uprobe_get_swbp_addr(regs); +- mm = current->mm; +- down_read(&mm->mmap_sem); +- vma = find_vma(mm, bp_vaddr); +- +- if (vma && vma->vm_start <= bp_vaddr && valid_vma(vma, false)) { +- struct inode *inode; +- loff_t offset; +- +- inode = vma->vm_file->f_mapping->host; +- offset = bp_vaddr - vma->vm_start; +- offset += (vma->vm_pgoff << PAGE_SHIFT); +- uprobe = find_uprobe(inode, offset); +- } +- +- srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id); +- current->uprobe_srcu_id = -1; +- up_read(&mm->mmap_sem); ++ uprobe = find_active_uprobe(bp_vaddr, &is_swbp); + + if (!uprobe) { +- /* No matching uprobe; signal SIGTRAP. */ +- send_sig(SIGTRAP, current, 0); ++ if (is_swbp > 0) { ++ /* No matching uprobe; signal SIGTRAP. */ ++ send_sig(SIGTRAP, current, 0); ++ } else { ++ /* ++ * Either we raced with uprobe_unregister() or we can't ++ * access this memory. The latter is only possible if ++ * another thread plays with our ->mm. In both cases ++ * we can simply restart. If this vma was unmapped we ++ * can pretend this insn was not executed yet and get ++ * the (correct) SIGSEGV after restart. ++ */ ++ instruction_pointer_set(regs, bp_vaddr); ++ } + return; + } + +@@ -1531,7 +1503,7 @@ static void handle_swbp(struct pt_regs *regs) + + utask->state = UTASK_SSTEP; + if (!pre_ssout(uprobe, regs, bp_vaddr)) { +- user_enable_single_step(current); ++ arch_uprobe_enable_step(&uprobe->arch); + return; + } + +@@ -1540,17 +1512,15 @@ cleanup_ret: + utask->active_uprobe = NULL; + utask->state = UTASK_RUNNING; + } +- if (uprobe) { +- if (!(uprobe->flags & UPROBE_SKIP_SSTEP)) ++ if (!(uprobe->flags & UPROBE_SKIP_SSTEP)) + +- /* +- * cannot singlestep; cannot skip instruction; +- * re-execute the instruction. +- */ +- instruction_pointer_set(regs, bp_vaddr); ++ /* ++ * cannot singlestep; cannot skip instruction; ++ * re-execute the instruction. ++ */ ++ instruction_pointer_set(regs, bp_vaddr); + +- put_uprobe(uprobe); +- } ++ put_uprobe(uprobe); + } + + /* +@@ -1569,10 +1539,10 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs) + else + WARN_ON_ONCE(1); + ++ arch_uprobe_disable_step(&uprobe->arch); + put_uprobe(uprobe); + utask->active_uprobe = NULL; + utask->state = UTASK_RUNNING; +- user_disable_single_step(current); + xol_free_insn_slot(current); + + spin_lock_irq(¤t->sighand->siglock); +@@ -1611,8 +1581,7 @@ int uprobe_pre_sstep_notifier(struct pt_regs *regs) + { + struct uprobe_task *utask; + +- if (!current->mm || !atomic_read(¤t->mm->uprobes_state.count)) +- /* task is currently not uprobed */ ++ if (!current->mm || !test_bit(MMF_HAS_UPROBES, ¤t->mm->flags)) + return 0; + + utask = current->utask; +@@ -1620,7 +1589,6 @@ int uprobe_pre_sstep_notifier(struct pt_regs *regs) + utask->state = UTASK_BP_HIT; + + set_thread_flag(TIF_UPROBE); +- current->uprobe_srcu_id = srcu_read_lock_raw(&uprobes_srcu); + + return 1; + } +@@ -1655,7 +1623,6 @@ static int __init init_uprobes(void) + mutex_init(&uprobes_mutex[i]); + mutex_init(&uprobes_mmap_mutex[i]); + } +- init_srcu_struct(&uprobes_srcu); + + return register_die_notifier(&uprobe_exception_nb); + } +diff --git a/kernel/fork.c b/kernel/fork.c +index 7a1d634..5d0137c 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -355,6 +355,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) + + down_write(&oldmm->mmap_sem); + flush_cache_dup_mm(oldmm); ++ uprobe_dup_mmap(oldmm, mm); + /* + * Not linked in yet - no deadlock potential: + */ +@@ -843,8 +841,6 @@ struct mm_struct *dup_mm(struct task_struct *tsk) + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + mm->pmd_huge_pte = NULL; + #endif +- uprobe_reset_state(mm); +- + if (!mm_init(mm, tsk)) + goto fail_nomem; + +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index a232bb5..764fcd1 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -33,6 +33,12 @@ static int ptrace_trapping_sleep_fn(void *flags) + } + + /* ++ * This is declared in linux/regset.h and defined in machine-dependent ++ * code. We put the export here to ensure no machine forgets it. ++ */ ++EXPORT_SYMBOL_GPL(task_user_regset_view); ++ ++/* + * ptrace a task: make the debugger its new parent and + * move it to the ptrace list. + * +diff --git a/mm/mmap.c b/mm/mmap.c +index 3edfcdf..f25fd3f 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -2345,9 +2344,6 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) + security_vm_enough_memory_mm(mm, vma_pages(vma))) + return -ENOMEM; + +- if (vma->vm_file && uprobe_mmap(vma)) +- return -EINVAL; +- + vma_link(mm, vma, prev, rb_link, rb_parent); + return 0; + } +@@ -2418,9 +2414,6 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, + if (new_vma->vm_file) { + get_file(new_vma->vm_file); + +- if (uprobe_mmap(new_vma)) +- goto out_free_mempol; +- + if (vma->vm_flags & VM_EXECUTABLE) + added_exe_file_vma(mm); + } +_______________________________________________ +kernel mailing list +kernel@lists.fedoraproject.org +https://admin.fedoraproject.org/mailman/listinfo/kernel From 51afabf34619ad72d0606ddeacba2a236eb7a2f5 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 16 Oct 2012 18:00:00 -0400 Subject: [PATCH 437/487] Linux 3.5.7 --- kernel.spec | 5 ++++- sources | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 31b1fc809..b588c141a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 0 +%define stable_update 7 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2001,6 +2001,9 @@ fi # and build. %changelog +* Tue Oct 16 2012 Dave Jones 3.5.7-1 +- Linux 3.5.7 + * Tue Oct 16 2012 Dave Jones 3.5.0-1 - Linux 3.5 diff --git a/sources b/sources index d239339bc..c3b8082d9 100644 --- a/sources +++ b/sources @@ -1 +1,2 @@ 24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz +42f3977dbc0a7b8c978bc4ae9bca56ad patch-3.5.7.xz From 9a52f7de034b136732c7eca2d7ed7ca98b1ae625 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 16 Oct 2012 21:20:32 -0400 Subject: [PATCH 438/487] Linux 3.6 --- config-debug | 3 + config-generic | 54 +- config-nodebug | 4 + config-powerpc-generic | 3 + config-sparc64-generic | 1 + config-x86-generic | 4 + config-x86_64-generic | 3 + ...-aesni-intel-fix-wrong-kfree-pointer.patch | 45 - ...-aesni-intel-and-ghash_clmulni-intel.patch | 122 -- kernel.spec | 21 +- uprobes-backport.patch | 1742 ----------------- 11 files changed, 72 insertions(+), 1930 deletions(-) delete mode 100644 crypto-aesni-intel-fix-wrong-kfree-pointer.patch delete mode 100644 crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch delete mode 100644 uprobes-backport.patch diff --git a/config-debug b/config-debug index ca1ba2b59..15a9aade2 100644 --- a/config-debug +++ b/config-debug @@ -110,3 +110,6 @@ CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 # CONFIG_DEBUG_KMEMLEAK_TEST is not set CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y +CONFIG_MAC80211_MESSAGE_TRACING=y + +CONFIG_EDAC_DEBUG=y diff --git a/config-generic b/config-generic index dc9441e34..afb70799b 100644 --- a/config-generic +++ b/config-generic @@ -455,6 +455,8 @@ CONFIG_VMXNET3=m CONFIG_HW_RANDOM_VIRTIO=m CONFIG_VIRTIO_CONSOLE=y CONFIG_VHOST_NET=m +# CONFIG_TCM_VHOST is not set + # # SCSI device support @@ -824,6 +826,7 @@ CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y CONFIG_ARPD=y CONFIG_SYN_COOKIES=y +CONFIG_NET_IPVTI=m CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_IPCOMP=m @@ -905,6 +908,7 @@ CONFIG_NF_CONNTRACK=m CONFIG_NETFILTER_NETLINK=m CONFIG_NETFILTER_NETLINK_ACCT=m CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_QUEUE_CT=y CONFIG_NETFILTER_NETLINK_LOG=m CONFIG_NETFILTER_TPROXY=m CONFIG_NETFILTER_XTABLES=y @@ -1010,6 +1014,7 @@ CONFIG_NF_CT_PROTO_DCCP=m CONFIG_NF_CT_PROTO_SCTP=m CONFIG_NF_CT_NETLINK=m # CONFIG_NF_CT_NETLINK_TIMEOUT is not set +CONFIG_NF_CT_NETLINK_HELPER=m CONFIG_NF_CT_PROTO_UDPLITE=m CONFIG_IP_NF_MATCH_AH=m @@ -1198,6 +1203,7 @@ CONFIG_NET_EMATCH_META=m CONFIG_NET_EMATCH_NBYTE=m CONFIG_NET_EMATCH_STACK=32 CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_EMATCH_IPSET=m CONFIG_NET_EMATCH_U32=m CONFIG_NET_ACT_CSUM=m @@ -1212,6 +1218,7 @@ CONFIG_NET_ACT_SIMP=m CONFIG_NET_ACT_SKBEDIT=m CONFIG_DCB=y +CONFIG_DNS_RESOLVER=m CONFIG_OPENVSWITCH=m CONFIG_NETPRIO_CGROUP=m @@ -1234,6 +1241,7 @@ CONFIG_NET_TEAM=m CONFIG_NET_TEAM_MODE_ROUNDROBIN=m CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m CONFIG_NET_TEAM_MODE_LOADBALANCE=m +CONFIG_NET_TEAM_MODE_BROADCAST=m CONFIG_DUMMY=m CONFIG_BONDING=m CONFIG_MACVLAN=m @@ -1499,6 +1507,7 @@ CONFIG_PCMCIA_XIRC2PS=m CONFIG_PHYLIB=y CONFIG_AMD_PHY=m CONFIG_BROADCOM_PHY=m +CONFIG_BCM87XX_PHY=m CONFIG_CICADA_PHY=m CONFIG_DAVICOM_PHY=m CONFIG_FIXED_PHY=y @@ -1727,6 +1736,7 @@ CONFIG_RT2500PCI=m CONFIG_RT61PCI=m CONFIG_RT2500USB=m CONFIG_RT2800USB=m +CONFIG_RT2800PCI_RT3290=y CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y CONFIG_RT2800USB_RT53XX=y @@ -1878,6 +1888,7 @@ CONFIG_BT_HCIUART=m CONFIG_BT_HCIUART_H4=y CONFIG_BT_HCIUART_BCSP=y CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIUART_3WIRE=y CONFIG_BT_HCIDTL1=m CONFIG_BT_HCIBT3C=m CONFIG_BT_HCIBLUECARD=m @@ -2145,6 +2156,7 @@ CONFIG_TOUCHSCREEN_AD7879_I2C=m # CONFIG_TOUCHSCREEN_CY8CTMG110 is not set # CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set CONFIG_TOUCHSCREEN_DYNAPRO=m +CONFIG_TOUCHSCREEN_EDT_FT5X06=m CONFIG_TOUCHSCREEN_EETI=m CONFIG_TOUCHSCREEN_EGALAX=m CONFIG_TOUCHSCREEN_ELO=m @@ -2154,6 +2166,7 @@ CONFIG_TOUCHSCREEN_GUNZE=m CONFIG_TOUCHSCREEN_HTCPEN=m CONFIG_TOUCHSCREEN_INEXIO=m CONFIG_TOUCHSCREEN_ILI210X=m +CONFIG_TOUCHSCREEN_MMS114=m CONFIG_TOUCHSCREEN_MTOUCH=m CONFIG_TOUCHSCREEN_MCS5000=m CONFIG_TOUCHSCREEN_MK712=m @@ -2362,6 +2375,7 @@ CONFIG_SENSORS_G760A=m CONFIG_SENSORS_GL518SM=m CONFIG_SENSORS_GL520SM=m CONFIG_SENSORS_HDAPS=m +# CONFIG_SENSORS_HIH6130 is not set # CONFIG_SENSORS_I5K_AMB is not set # FIXME: IBMAEM x86 only? CONFIG_SENSORS_IBMAEM=m @@ -2627,6 +2641,7 @@ CONFIG_DRM_I2C_CH7006=m CONFIG_DRM_I2C_SIL164=m # CONFIG_DRM_UDL is not set CONFIG_DRM_VMWGFX=m +# CONFIG_DRM_VMWGFX_FBCON is not set # # PCMCIA character devices @@ -2645,6 +2660,11 @@ CONFIG_HANGCHECK_TIMER=m # Multimedia devices # CONFIG_MEDIA_SUPPORT=m +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_ANALOG_TV_SUPPORT=y +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_RC_SUPPORT=y CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_DEV=m # CONFIG_VIDEO_ADV_DEBUG is not set @@ -2741,6 +2761,8 @@ CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y # Radio Adapters # CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_SHARK=m +CONFIG_RADIO_SHARK2=m CONFIG_RADIO_WL1273=m CONFIG_RADIO_WL128X=m @@ -2847,8 +2869,11 @@ CONFIG_VIDEO_PVRUSB2_SYSFS=y # CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set CONFIG_RC_CORE=m +CONFIG_RC_DECODERS=y +CONFIG_LIRC=m CONFIG_RC_LOOPBACK=m CONFIG_RC_MAP=m +CONFIG_RC_DEVICES=y CONFIG_RC_ATI_REMOTE=m CONFIG_IR_NEC_DECODER=m CONFIG_IR_RC5_DECODER=m @@ -2868,6 +2893,7 @@ CONFIG_IR_REDRAT3=m CONFIG_IR_ENE=m CONFIG_IR_STREAMZAP=m CONFIG_IR_WINBOND_CIR=m +CONFIG_IR_IGUANA=m CONFIG_V4L_MEM2MEM_DRIVERS=y # CONFIG_VIDEO_MEM2MEM_TESTDEV is not set @@ -3225,6 +3251,7 @@ CONFIG_HID=ym CONFIG_HID_BATTERY_STRENGTH=y # debugging default is y upstream now CONFIG_HIDRAW=y +CONFIG_UHID=m CONFIG_HID_PID=y CONFIG_LOGITECH_FF=y CONFIG_HID_LOGITECH_DJ=m @@ -3277,6 +3304,7 @@ CONFIG_HID_ACRUX=m CONFIG_HID_ACRUX_FF=y CONFIG_HID_KEYTOUCH=m CONFIG_HID_LCPOWER=m +CONFIG_HID_LENOVO_TPKBD=m CONFIG_HID_ROCCAT_ARVO=m CONFIG_HID_ROCCAT_KOVAPLUS=m CONFIG_HID_HOLTEK=m @@ -3599,6 +3627,8 @@ CONFIG_MFD_WM8400=m # CONFIG_MFD_TPS65217 is not set # CONFIG_MFD_LM3533 is not set # CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_ARIZONA is not set +# CONFIG_MFD_ARIZONA_I2C is not set # # File systems @@ -3741,6 +3771,7 @@ CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y CONFIG_NFS_V4_1=y CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org" +# CONFIG_NFS_SWAP is not set CONFIG_NFSD=m CONFIG_NFSD_V3=y CONFIG_NFSD_V3_ACL=y @@ -3901,6 +3932,7 @@ CONFIG_FRAME_POINTER=y # CONFIG_DEBUG_DRIVER is not set CONFIG_HEADERS_CHECK=y # CONFIG_LKDTM is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_READABLE_ASM is not set # CONFIG_RT_MUTEX_TESTER is not set @@ -4121,10 +4153,11 @@ CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_SCHED=y -CONFIG_CGROUP_MEM_RES_CTLR=y -CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y # XXX disabled by default, pass 'swapaccount' -# CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED is not set -CONFIG_CGROUP_MEM_RES_CTLR_KMEM=y +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y # XXX disabled by default, pass 'swapaccount' +# CONFIG_MEMCG_SWAP_ENABLED is not set +CONFIG_MEMCG_KMEM=y +# CONFIG_CGROUP_HUGETLB is not set CONFIG_CGROUP_PERF=y CONFIG_BLK_CGROUP=y @@ -4303,6 +4336,7 @@ CONFIG_LEDS_DELL_NETBOOKS=m # CONFIG_LEDS_OT200 is not set CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_ONESHOT=m CONFIG_LEDS_TRIGGER_IDE_DISK=y CONFIG_LEDS_TRIGGER_HEARTBEAT=m CONFIG_LEDS_TRIGGER_BACKLIGHT=m @@ -4312,6 +4346,8 @@ CONFIG_LEDS_ALIX2=m CONFIG_LEDS_CLEVO_MAIL=m CONFIG_LEDS_INTEL_SS4200=m CONFIG_LEDS_LM3530=m +CONFIG_LEDS_LM3556=m +CONFIG_LEDS_BLINKM=m CONFIG_LEDS_LP3944=m CONFIG_LEDS_LP5521=m CONFIG_LEDS_LP5523=m @@ -4404,7 +4440,7 @@ CONFIG_UIO_SERCOS3=m CONFIG_UIO_PCI_GENERIC=m # CONFIG_UIO_NETX is not set - +# CONFIG_VFIO is not set # LIRC CONFIG_LIRC_STAGING=y @@ -4557,6 +4593,7 @@ CONFIG_ALTERA_STAPL=m # CONFIG_USB_WPAN_HCD is not set # CONFIG_WIMAX_GDM72XX is not set # CONFIG_IPACK_BUS is not set +# CONFIG_CSR_WIFI is not set # # END OF STAGING @@ -4573,6 +4610,7 @@ CONFIG_IMA_AUDIT=y CONFIG_IMA_LSM_RULES=y # CONFIG_EVM is not set +# CONFIG_PWM is not set CONFIG_LSM_MMAP_MIN_ADDR=65536 @@ -4647,6 +4685,7 @@ CONFIG_GPIO_SYSFS=y # CONFIG_GPIO_VX855 is not set # CONFIG_GPIO_PCH is not set # CONFIG_GPIO_ML_IOH is not set +# CONFIG_GPIO_AMD8111 is not set # CONFIG_GPIO_SX150X is not set @@ -4656,6 +4695,8 @@ CONFIG_EVENT_POWER_TRACING_DEPRECATED=y CONFIG_TEST_KSTRTOX=y # CONFIG_XZ_DEC_TEST is not set +# CONFIG_POWER_AVS is not set + CONFIG_TARGET_CORE=m CONFIG_ISCSI_TARGET=m CONFIG_LOOPBACK_TARGET=m @@ -4669,6 +4710,8 @@ CONFIG_HWSPINLOCK=m CONFIG_PSTORE=y CONFIG_PSTORE_RAM=m +# CONFIG_PSTORE_CONSOLE is not set +# CONFIG_PSTORE_FTRACE is not set # CONFIG_AVERAGE is not set @@ -4680,6 +4723,7 @@ CONFIG_BCMA=m CONFIG_BCMA_BLOCKIO=y CONFIG_BCMA_HOST_PCI_POSSIBLE=y CONFIG_BCMA_HOST_PCI=y +CONFIG_BCMA_DRIVER_GMAC_CMN=y # CONFIG_BCMA_DEBUG is not set # CONFIG_GOOGLE_FIRMWARE is not set diff --git a/config-nodebug b/config-nodebug index 43b70d774..516a45e4a 100644 --- a/config-nodebug +++ b/config-nodebug @@ -104,3 +104,7 @@ CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set # CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set + +# CONFIG_MAC80211_MESSAGE_TRACING is not set + +# CONFIG_EDAC_DEBUG is not set diff --git a/config-powerpc-generic b/config-powerpc-generic index 1b82cf499..90120de7c 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -181,6 +181,7 @@ CONFIG_EDAC_MM_EDAC=m CONFIG_EDAC_PASEMI=m CONFIG_EDAC_AMD8131=m CONFIG_EDAC_AMD8111=m +CONFIG_EDAC_LEGACY_SYSFS=y # CONFIG_AXON_RAM is not set # CONFIG_OPROFILE_CELL is not set @@ -367,3 +368,5 @@ CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_MPIC_MSGR is not set # CONFIG_FA_DUMP is not set # CONFIG_MDIO_BUS_MUX_GPIO is not set + +# CONFIG_FAIL_IOMMU is not set diff --git a/config-sparc64-generic b/config-sparc64-generic index a2b72dfe6..a27e0b44b 100644 --- a/config-sparc64-generic +++ b/config-sparc64-generic @@ -199,3 +199,4 @@ CONFIG_CRYPTO_DEV_NIAGARA2=y # CONFIG_OF_SELFTEST is not set CONFIG_BPF_JIT=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set diff --git a/config-x86-generic b/config-x86-generic index c5fb4d815..de4fbd5cf 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -167,6 +167,7 @@ CONFIG_EDAC_R82600=m CONFIG_EDAC_X38=m CONFIG_EDAC_MCE_INJ=m CONFIG_EDAC_DECODE_MCE=m +CONFIG_EDAC_LEGACY_SYSFS=y CONFIG_SCHED_MC=y @@ -312,6 +313,7 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_NO_BOOTMEM is not set # CONFIG_MEMTEST is not set +# CONFIG_DEBUG_TLBFLUSH is not set # CONFIG_MAXSMP is not set @@ -376,6 +378,8 @@ CONFIG_VIDEO_VIA_CAMERA=m CONFIG_IRQ_TIME_ACCOUNTING=y CONFIG_X86_RESERVE_LOW=64 +# CONFIG_IRQ_DOMAIN_DEBUG is not set + CONFIG_PCH_GBE=m CONFIG_PCH_PHUB=m diff --git a/config-x86_64-generic b/config-x86_64-generic index 0b01f9f44..8d300df57 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -52,6 +52,8 @@ CONFIG_CRYPTO_SHA1_SSSE3=m CONFIG_CRYPTO_BLOWFISH_X86_64=m CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=m CONFIG_CRYPTO_CAMELLIA_X86_64=m +CONFIG_CRYPTO_SERPENT_AVX_X86_64=m +CONFIG_CRYPTO_TWOFISH_AVX_X86_64=m # CONFIG_I2C_ALI1535 is not set # CONFIG_I2C_ALI1563 is not set @@ -92,6 +94,7 @@ CONFIG_XEN_MAX_DOMAIN_MEMORY=128 # CONFIG_XEN_BALLOON_MEMORY_HOTPLUG is not set CONFIG_XEN_DEV_EVTCHN=m CONFIG_XEN_SYS_HYPERVISOR=y +# CONFIG_XEN_MCE_LOG is not set CONFIG_PROVIDE_OHCI1394_DMA_INIT=y diff --git a/crypto-aesni-intel-fix-wrong-kfree-pointer.patch b/crypto-aesni-intel-fix-wrong-kfree-pointer.patch deleted file mode 100644 index e9942c06f..000000000 --- a/crypto-aesni-intel-fix-wrong-kfree-pointer.patch +++ /dev/null @@ -1,45 +0,0 @@ -From bf084d8f6eb4ded3f90a6ab79bb682db00ebfbd4 Mon Sep 17 00:00:00 2001 -From: Milan Broz -Date: Thu, 28 Jun 2012 17:26:02 +0200 -Subject: [PATCH] crypto: aesni-intel - fix wrong kfree pointer - -kfree(new_key_mem) in rfc4106_set_key() should be called on malloced pointer, -not on aligned one, otherwise it can cause invalid pointer on free. - -(Seen at least once when running tcrypt tests with debug kernel.) - -Signed-off-by: Milan Broz -Signed-off-by: Herbert Xu ---- - arch/x86/crypto/aesni-intel_glue.c | 8 ++++---- - 1 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c -index d662615..34fdcff 100644 ---- a/arch/x86/crypto/aesni-intel_glue.c -+++ b/arch/x86/crypto/aesni-intel_glue.c -@@ -529,7 +529,7 @@ static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key, - struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm); - struct aesni_rfc4106_gcm_ctx *child_ctx = - aesni_rfc4106_gcm_ctx_get(cryptd_child); -- u8 *new_key_mem = NULL; -+ u8 *new_key_align, *new_key_mem = NULL; - - if (key_len < 4) { - crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); -@@ -553,9 +553,9 @@ static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key, - if (!new_key_mem) - return -ENOMEM; - -- new_key_mem = PTR_ALIGN(new_key_mem, AESNI_ALIGN); -- memcpy(new_key_mem, key, key_len); -- key = new_key_mem; -+ new_key_align = PTR_ALIGN(new_key_mem, AESNI_ALIGN); -+ memcpy(new_key_align, key, key_len); -+ key = new_key_align; - } - - if (!irq_fpu_usable()) --- -1.7.6.5 - diff --git a/crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch b/crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch deleted file mode 100644 index 9aef14c52..000000000 --- a/crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 6c79294f44fd7d1122cbaabff3b9815b074c0dd0 Mon Sep 17 00:00:00 2001 -From: Milan Broz -Date: Fri, 29 Jun 2012 22:08:09 +0200 -Subject: [PATCH] crypto: testmgr - allow aesni-intel and ghash_clmulni-intel - in fips mode - -Patch 863b557a88f8c033f7419fabafef4712a5055f85 added NULL entries -for intel accelerated drivers but did not marked these fips allowed. -This cause panic if running tests with fips=1. - -For ghash, fips_allowed flag was added in patch -18c0ebd2d8194cce4b3f67e2903fa01bea892cbc. - -Without patch, "modprobe tcrypt" fails with - alg: skcipher: Failed to load transform for cbc-aes-aesni: -2 - cbc-aes-aesni: cbc(aes) alg self test failed in fips mode! - (panic) - -Also add missing cryptd(__driver-cbc-aes-aesni) and -cryptd(__driver-gcm-aes-aesni) test to complement -null tests above, otherwise system complains with - alg: No test for __cbc-aes-aesni (cryptd(__driver-cbc-aes-aesni)) - alg: No test for __gcm-aes-aesni (cryptd(__driver-gcm-aes-aesni)) - -Signed-off-by: Milan Broz -Signed-off-by: Paul Wouters -Signed-off-by: Herbert Xu ---- - crypto/testmgr.c | 38 ++++++++++++++++++++++++++++++++++++++ - 1 files changed, 38 insertions(+), 0 deletions(-) - -diff --git a/crypto/testmgr.c b/crypto/testmgr.c -index 36748a5..4308a11 100644 ---- a/crypto/testmgr.c -+++ b/crypto/testmgr.c -@@ -1581,6 +1581,7 @@ static const struct alg_test_desc alg_test_descs[] = { - }, { - .alg = "__driver-cbc-aes-aesni", - .test = alg_test_null, -+ .fips_allowed = 1, - .suite = { - .cipher = { - .enc = { -@@ -1641,6 +1642,7 @@ static const struct alg_test_desc alg_test_descs[] = { - }, { - .alg = "__driver-ecb-aes-aesni", - .test = alg_test_null, -+ .fips_allowed = 1, - .suite = { - .cipher = { - .enc = { -@@ -1701,6 +1703,7 @@ static const struct alg_test_desc alg_test_descs[] = { - }, { - .alg = "__ghash-pclmulqdqni", - .test = alg_test_null, -+ .fips_allowed = 1, - .suite = { - .hash = { - .vecs = NULL, -@@ -1866,8 +1869,25 @@ static const struct alg_test_desc alg_test_descs[] = { - } - } - }, { -+ .alg = "cryptd(__driver-cbc-aes-aesni)", -+ .test = alg_test_null, -+ .fips_allowed = 1, -+ .suite = { -+ .cipher = { -+ .enc = { -+ .vecs = NULL, -+ .count = 0 -+ }, -+ .dec = { -+ .vecs = NULL, -+ .count = 0 -+ } -+ } -+ } -+ }, { - .alg = "cryptd(__driver-ecb-aes-aesni)", - .test = alg_test_null, -+ .fips_allowed = 1, - .suite = { - .cipher = { - .enc = { -@@ -1926,8 +1946,25 @@ static const struct alg_test_desc alg_test_descs[] = { - } - } - }, { -+ .alg = "cryptd(__driver-gcm-aes-aesni)", -+ .test = alg_test_null, -+ .fips_allowed = 1, -+ .suite = { -+ .cipher = { -+ .enc = { -+ .vecs = NULL, -+ .count = 0 -+ }, -+ .dec = { -+ .vecs = NULL, -+ .count = 0 -+ } -+ } -+ } -+ }, { - .alg = "cryptd(__ghash-pclmulqdqni)", - .test = alg_test_null, -+ .fips_allowed = 1, - .suite = { - .hash = { - .vecs = NULL, -@@ -2043,6 +2080,7 @@ static const struct alg_test_desc alg_test_descs[] = { - }, { - .alg = "ecb(__aes-aesni)", - .test = alg_test_null, -+ .fips_allowed = 1, - .suite = { - .cipher = { - .enc = { --- -1.7.6.5 - diff --git a/kernel.spec b/kernel.spec index b588c141a..1124dbddf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -60,13 +60,13 @@ Summary: The Linux kernel # base_sublevel is the kernel version we're starting with and patching # on top of -- for example, 2.6.22-rc7-git1 starts with a 2.6.21 base, # which yields a base_sublevel of 21. -%define base_sublevel 5 +%define base_sublevel 6 ## If this is a released kernel ## %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 7 +%define stable_update 0 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -668,9 +668,6 @@ Patch14010: lis3-improve-handling-of-null-rate.patch Patch19000: ips-noirq.patch -# Uprobes (rhbz 832083) -Patch20000: uprobes-backport.patch - #rhbz 769766 Patch21072: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch @@ -688,10 +685,6 @@ Patch21306: shlib_base_randomize.patch Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch -#Fix FIPS for aesni hardare -Patch22055: crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch -Patch22056: crypto-aesni-intel-fix-wrong-kfree-pointer.patch - # END OF PATCH DEFINITIONS %endif @@ -1285,9 +1278,6 @@ ApplyPatch ips-noirq.patch #ApplyPatch pci-crs-blacklist.patch -# Uprobes (rhbz 832083) -ApplyPatch uprobes-backport.patch - #rhbz 754518 #ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -1297,10 +1287,6 @@ ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch ApplyPatch debug-808990.patch -#Fix FIPS for aesni hardare -ApplyPatch crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch -ApplyPatch crypto-aesni-intel-fix-wrong-kfree-pointer.patch - # END OF PATCH APPLICATIONS %endif @@ -2001,6 +1987,9 @@ fi # and build. %changelog +* Tue Oct 16 2012 Dave Jones +- Linux 3.6 + * Tue Oct 16 2012 Dave Jones 3.5.7-1 - Linux 3.5.7 diff --git a/uprobes-backport.patch b/uprobes-backport.patch deleted file mode 100644 index 5f2bacfc0..000000000 --- a/uprobes-backport.patch +++ /dev/null @@ -1,1742 +0,0 @@ -Hello, - -Test build: http://koji.fedoraproject.org/koji/taskinfo?taskID=4490824 -This also fixes: https://bugzilla.redhat.com/show_bug.cgi?id=849364 - -The split-out series is available in the git repository at: - http://fedorapeople.org/cgit/aarapov/public_git/kernel-uprobes.git/log/?h=f17_uprobes_out - (Just @jistone's patch is not upstream that exports functions.) - -Ananth N Mavinakayanahalli (1): - uprobes: Pass probed vaddr to arch_uprobe_analyze_insn() - -Josh Stone (1): - uprobes: add exports necessary for uprobes use by modules - -Oleg Nesterov (52): - uprobes: Optimize is_swbp_at_addr() for current->mm - uprobes: Change read_opcode() to use FOLL_FORCE - uprobes: Introduce find_active_uprobe() helper - uprobes: Teach find_active_uprobe() to provide the "is_swbp" info - uprobes: Change register_for_each_vma() to take mm->mmap_sem for writing - uprobes: Teach handle_swbp() to rely on "is_swbp" rather than uprobes_srcu - uprobes: Kill uprobes_srcu/uprobe_srcu_id - uprobes: Valid_vma() should reject VM_HUGETLB - uprobes: __copy_insn() should ensure a_ops->readpage != NULL - uprobes: Write_opcode()->__replace_page() can race with try_to_unmap() - uprobes: Install_breakpoint() should fail if is_swbp_insn() == T - uprobes: Rework register_for_each_vma() to make it O(n) - uprobes: Change build_map_info() to try kmalloc(GFP_NOWAIT) first - uprobes: Copy_insn() shouldn't depend on mm/vma/vaddr - uprobes: Copy_insn() should not return -ENOMEM if __copy_insn() fails - uprobes: No need to re-check vma_address() in write_opcode() - uprobes: Move BUG_ON(UPROBE_SWBP_INSN_SIZE) from write_opcode() to install_breakpoint() - uprobes: Simplify the usage of uprobe->pending_list - uprobes: Don't use loff_t for the valid virtual address - uprobes: __copy_insn() needs "loff_t offset" - uprobes: Remove the unnecessary initialization in add_utask() - uprobes: Don't recheck vma/f_mapping in write_opcode() - uprobes: __replace_page() should not use page_address_in_vma() - uprobes: Kill write_opcode()->lock_page(new_page) - uprobes: Clean up and document write_opcode()->lock_page(old_page) - uprobes: Uprobe_mmap/munmap needs list_for_each_entry_safe() - uprobes: Suppress uprobe_munmap() from mmput() - uprobes: Fix overflow in vma_address()/find_active_uprobe() - uprobes: Remove copy_vma()->uprobe_mmap() - uprobes: Remove insert_vm_struct()->uprobe_mmap() - uprobes: Teach build_probe_list() to consider the range - uprobes: Introduce vaddr_to_offset(vma, vaddr) - uprobes: Fix register_for_each_vma()->vma_address() check - uprobes: Rename vma_address() and make it return "unsigned long" - uprobes: __replace_page() needs munlock_vma_page() - uprobes: Fix mmap_region()'s mm->mm_rb corruption if uprobe_mmap() fails - uprobes: Kill uprobes_state->count - uprobes: Kill dup_mmap()->uprobe_mmap(), simplify uprobe_mmap/munmap - uprobes: Change uprobe_mmap() to ignore the errors but check fatal_signal_pending() - uprobes: Do not use -EEXIST in install_breakpoint() paths - uprobes: Introduce MMF_HAS_UPROBES - uprobes: Fold uprobe_reset_state() into uprobe_dup_mmap() - uprobes: Remove "verify" argument from set_orig_insn() - uprobes: uprobes_treelock should not disable irqs - uprobes: Introduce MMF_RECALC_UPROBES - uprobes: Teach find_active_uprobe() to clear MMF_HAS_UPROBES - ptrace/x86: Introduce set_task_blockstep() helper - ptrace/x86: Partly fix set_task_blockstep()->update_debugctlmsr() logic - uprobes/x86: Do not (ab)use TIF_SINGLESTEP/user_*_single_step() for single-stepping - uprobes/x86: Xol should send SIGTRAP if X86_EFLAGS_TF was set - uprobes/x86: Fix arch_uprobe_disable_step() && UTASK_SSTEP_TRAPPED interaction - uprobes: Make arch_uprobe_task->saved_trap_nr "unsigned int" - -Peter Zijlstra (1): - uprobes: Document uprobe_register() vs uprobe_mmap() race - -Sebastian Andrzej Siewior (4): - uprobes: Remove check for uprobe variable in handle_swbp() - uprobes: Don't put NULL pointer in uprobe_register() - uprobes: Introduce arch_uprobe_enable/disable_step() - uprobes/x86: Implement x86 specific arch_uprobe_*_step - -Srikar Dronamraju (1): - uprobes: Remove redundant lock_page/unlock_page - -Signed-off-by: Anton Arapov ---- - arch/x86/include/asm/processor.h | 2 + - arch/x86/include/asm/uprobes.h | 5 +- - arch/x86/kernel/step.c | 53 ++- - arch/x86/kernel/uprobes.c | 55 ++- - include/linux/sched.h | 4 +- - include/linux/uprobes.h | 15 +- - kernel/events/uprobes.c | 819 +++++++++++++++++++-------------------- - kernel/fork.c | 6 +- - kernel/ptrace.c | 6 + - mm/mmap.c | 11 +- - 10 files changed, 505 insertions(+), 471 deletions(-) - -diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h -index 39bc577..2f9f8ca 100644 ---- a/arch/x86/include/asm/processor.h -+++ b/arch/x86/include/asm/processor.h -@@ -746,6 +746,8 @@ static inline void update_debugctlmsr(unsigned long debugctlmsr) - wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr); - } - -+extern void set_task_blockstep(struct task_struct *task, bool on); -+ - /* - * from system description table in BIOS. Mostly for MCA use, but - * others may find it useful: -diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h -index 1e9bed1..8ff8be7 100644 ---- a/arch/x86/include/asm/uprobes.h -+++ b/arch/x86/include/asm/uprobes.h -@@ -42,13 +42,14 @@ struct arch_uprobe { - }; - - struct arch_uprobe_task { -- unsigned long saved_trap_nr; - #ifdef CONFIG_X86_64 - unsigned long saved_scratch_register; - #endif -+ unsigned int saved_trap_nr; -+ unsigned int saved_tf; - }; - --extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm); -+extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr); - extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs); - extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs); - extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk); -diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c -index c346d11..cd3b243 100644 ---- a/arch/x86/kernel/step.c -+++ b/arch/x86/kernel/step.c -@@ -157,6 +157,33 @@ static int enable_single_step(struct task_struct *child) - return 1; - } - -+void set_task_blockstep(struct task_struct *task, bool on) -+{ -+ unsigned long debugctl; -+ -+ /* -+ * Ensure irq/preemption can't change debugctl in between. -+ * Note also that both TIF_BLOCKSTEP and debugctl should -+ * be changed atomically wrt preemption. -+ * FIXME: this means that set/clear TIF_BLOCKSTEP is simply -+ * wrong if task != current, SIGKILL can wakeup the stopped -+ * tracee and set/clear can play with the running task, this -+ * can confuse the next __switch_to_xtra(). -+ */ -+ local_irq_disable(); -+ debugctl = get_debugctlmsr(); -+ if (on) { -+ debugctl |= DEBUGCTLMSR_BTF; -+ set_tsk_thread_flag(task, TIF_BLOCKSTEP); -+ } else { -+ debugctl &= ~DEBUGCTLMSR_BTF; -+ clear_tsk_thread_flag(task, TIF_BLOCKSTEP); -+ } -+ if (task == current) -+ update_debugctlmsr(debugctl); -+ local_irq_enable(); -+} -+ - /* - * Enable single or block step. - */ -@@ -169,19 +196,10 @@ static void enable_step(struct task_struct *child, bool block) - * So no one should try to use debugger block stepping in a program - * that uses user-mode single stepping itself. - */ -- if (enable_single_step(child) && block) { -- unsigned long debugctl = get_debugctlmsr(); -- -- debugctl |= DEBUGCTLMSR_BTF; -- update_debugctlmsr(debugctl); -- set_tsk_thread_flag(child, TIF_BLOCKSTEP); -- } else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { -- unsigned long debugctl = get_debugctlmsr(); -- -- debugctl &= ~DEBUGCTLMSR_BTF; -- update_debugctlmsr(debugctl); -- clear_tsk_thread_flag(child, TIF_BLOCKSTEP); -- } -+ if (enable_single_step(child) && block) -+ set_task_blockstep(child, true); -+ else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) -+ set_task_blockstep(child, false); - } - - void user_enable_single_step(struct task_struct *child) -@@ -199,13 +217,8 @@ void user_disable_single_step(struct task_struct *child) - /* - * Make sure block stepping (BTF) is disabled. - */ -- if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { -- unsigned long debugctl = get_debugctlmsr(); -- -- debugctl &= ~DEBUGCTLMSR_BTF; -- update_debugctlmsr(debugctl); -- clear_tsk_thread_flag(child, TIF_BLOCKSTEP); -- } -+ if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) -+ set_task_blockstep(child, false); - - /* Always clear TIF_SINGLESTEP... */ - clear_tsk_thread_flag(child, TIF_SINGLESTEP); -diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c -index dc4e910..9538f00 100644 ---- a/arch/x86/kernel/uprobes.c -+++ b/arch/x86/kernel/uprobes.c -@@ -41,6 +41,9 @@ - /* Adjust the return address of a call insn */ - #define UPROBE_FIX_CALL 0x2 - -+/* Instruction will modify TF, don't change it */ -+#define UPROBE_FIX_SETF 0x4 -+ - #define UPROBE_FIX_RIP_AX 0x8000 - #define UPROBE_FIX_RIP_CX 0x4000 - -@@ -239,6 +242,10 @@ static void prepare_fixups(struct arch_uprobe *auprobe, struct insn *insn) - insn_get_opcode(insn); /* should be a nop */ - - switch (OPCODE1(insn)) { -+ case 0x9d: -+ /* popf */ -+ auprobe->fixups |= UPROBE_FIX_SETF; -+ break; - case 0xc3: /* ret/lret */ - case 0xcb: - case 0xc2: -@@ -409,9 +416,10 @@ static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm, - * arch_uprobe_analyze_insn - instruction analysis including validity and fixups. - * @mm: the probed address space. - * @arch_uprobe: the probepoint information. -+ * @addr: virtual address at which to install the probepoint - * Return 0 on success or a -ve number on error. - */ --int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm) -+int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr) - { - int ret; - struct insn insn; -@@ -645,7 +653,7 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) - * Skip these instructions as per the currently known x86 ISA. - * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 } - */ --bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) -+static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) - { - int i; - -@@ -672,3 +680,46 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) - } - return false; - } -+ -+bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) -+{ -+ bool ret = __skip_sstep(auprobe, regs); -+ if (ret && (regs->flags & X86_EFLAGS_TF)) -+ send_sig(SIGTRAP, current, 0); -+ return ret; -+} -+ -+void arch_uprobe_enable_step(struct arch_uprobe *auprobe) -+{ -+ struct task_struct *task = current; -+ struct arch_uprobe_task *autask = &task->utask->autask; -+ struct pt_regs *regs = task_pt_regs(task); -+ -+ autask->saved_tf = !!(regs->flags & X86_EFLAGS_TF); -+ -+ regs->flags |= X86_EFLAGS_TF; -+ if (test_tsk_thread_flag(task, TIF_BLOCKSTEP)) -+ set_task_blockstep(task, false); -+} -+ -+void arch_uprobe_disable_step(struct arch_uprobe *auprobe) -+{ -+ struct task_struct *task = current; -+ struct arch_uprobe_task *autask = &task->utask->autask; -+ bool trapped = (task->utask->state == UTASK_SSTEP_TRAPPED); -+ struct pt_regs *regs = task_pt_regs(task); -+ /* -+ * The state of TIF_BLOCKSTEP was not saved so we can get an extra -+ * SIGTRAP if we do not clear TF. We need to examine the opcode to -+ * make it right. -+ */ -+ if (unlikely(trapped)) { -+ if (!autask->saved_tf) -+ regs->flags &= ~X86_EFLAGS_TF; -+ } else { -+ if (autask->saved_tf) -+ send_sig(SIGTRAP, task, 0); -+ else if (!(auprobe->fixups & UPROBE_FIX_SETF)) -+ regs->flags &= ~X86_EFLAGS_TF; -+ } -+} -diff --git a/include/linux/sched.h b/include/linux/sched.h -index 4a1f493..864054f 100644 ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -441,6 +441,9 @@ extern int get_dumpable(struct mm_struct *mm); - #define MMF_VM_HUGEPAGE 17 /* set when VM_HUGEPAGE is set on vma */ - #define MMF_EXE_FILE_CHANGED 18 /* see prctl_set_mm_exe_file() */ - -+#define MMF_HAS_UPROBES 19 /* has uprobes */ -+#define MMF_RECALC_UPROBES 20 /* MMF_HAS_UPROBES can be wrong */ -+ - #define MMF_INIT_MASK (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK) - - struct sighand_struct { -@@ -1581,7 +1584,6 @@ struct task_struct { - #endif - #ifdef CONFIG_UPROBES - struct uprobe_task *utask; -- int uprobe_srcu_id; - #endif - }; - -diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h -index efe4b33..e6f0331 100644 ---- a/include/linux/uprobes.h -+++ b/include/linux/uprobes.h -@@ -99,25 +99,27 @@ struct xol_area { - - struct uprobes_state { - struct xol_area *xol_area; -- atomic_t count; - }; -+ - extern int __weak set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); --extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr, bool verify); -+extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); - extern bool __weak is_swbp_insn(uprobe_opcode_t *insn); - extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); - extern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); - extern int uprobe_mmap(struct vm_area_struct *vma); - extern void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end); -+extern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm); - extern void uprobe_free_utask(struct task_struct *t); - extern void uprobe_copy_process(struct task_struct *t); - extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs); -+extern void __weak arch_uprobe_enable_step(struct arch_uprobe *arch); -+extern void __weak arch_uprobe_disable_step(struct arch_uprobe *arch); - extern int uprobe_post_sstep_notifier(struct pt_regs *regs); - extern int uprobe_pre_sstep_notifier(struct pt_regs *regs); - extern void uprobe_notify_resume(struct pt_regs *regs); - extern bool uprobe_deny_signal(void); - extern bool __weak arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs); - extern void uprobe_clear_state(struct mm_struct *mm); --extern void uprobe_reset_state(struct mm_struct *mm); - #else /* !CONFIG_UPROBES */ - struct uprobes_state { - }; -@@ -138,6 +140,10 @@ static inline void - uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) - { - } -+static inline void -+uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm) -+{ -+} - static inline void uprobe_notify_resume(struct pt_regs *regs) - { - } -@@ -158,8 +164,5 @@ static inline void uprobe_copy_process(struct task_struct *t) - static inline void uprobe_clear_state(struct mm_struct *mm) - { - } --static inline void uprobe_reset_state(struct mm_struct *mm) --{ --} - #endif /* !CONFIG_UPROBES */ - #endif /* _LINUX_UPROBES_H */ -diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c -index 985be4d..f8a97e7 100644 ---- a/kernel/events/uprobes.c -+++ b/kernel/events/uprobes.c -@@ -27,24 +27,42 @@ - #include /* read_mapping_page */ - #include - #include -+#include - #include /* anon_vma_prepare */ - #include /* set_pte_at_notify */ - #include /* try_to_free_swap */ - #include /* user_enable_single_step */ - #include /* notifier mechanism */ -+#include "../../mm/internal.h" /* munlock_vma_page */ - - #include - - #define UINSNS_PER_PAGE (PAGE_SIZE/UPROBE_XOL_SLOT_BYTES) - #define MAX_UPROBE_XOL_SLOTS UINSNS_PER_PAGE - --static struct srcu_struct uprobes_srcu; - static struct rb_root uprobes_tree = RB_ROOT; - - static DEFINE_SPINLOCK(uprobes_treelock); /* serialize rbtree access */ - - #define UPROBES_HASH_SZ 13 - -+/* -+ * We need separate register/unregister and mmap/munmap lock hashes because -+ * of mmap_sem nesting. -+ * -+ * uprobe_register() needs to install probes on (potentially) all processes -+ * and thus needs to acquire multiple mmap_sems (consequtively, not -+ * concurrently), whereas uprobe_mmap() is called while holding mmap_sem -+ * for the particular process doing the mmap. -+ * -+ * uprobe_register()->register_for_each_vma() needs to drop/acquire mmap_sem -+ * because of lock order against i_mmap_mutex. This means there's a hole in -+ * the register vma iteration where a mmap() can happen. -+ * -+ * Thus uprobe_register() can race with uprobe_mmap() and we can try and -+ * install a probe where one is already installed. -+ */ -+ - /* serialize (un)register */ - static struct mutex uprobes_mutex[UPROBES_HASH_SZ]; - -@@ -61,17 +79,6 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ]; - */ - static atomic_t uprobe_events = ATOMIC_INIT(0); - --/* -- * Maintain a temporary per vma info that can be used to search if a vma -- * has already been handled. This structure is introduced since extending -- * vm_area_struct wasnt recommended. -- */ --struct vma_info { -- struct list_head probe_list; -- struct mm_struct *mm; -- loff_t vaddr; --}; -- - struct uprobe { - struct rb_node rb_node; /* node in the rb tree */ - atomic_t ref; -@@ -100,20 +107,21 @@ static bool valid_vma(struct vm_area_struct *vma, bool is_register) - if (!is_register) - return true; - -- if ((vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) == (VM_READ|VM_EXEC)) -+ if ((vma->vm_flags & (VM_HUGETLB|VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) -+ == (VM_READ|VM_EXEC)) - return true; - - return false; - } - --static loff_t vma_address(struct vm_area_struct *vma, loff_t offset) -+static unsigned long offset_to_vaddr(struct vm_area_struct *vma, loff_t offset) - { -- loff_t vaddr; -- -- vaddr = vma->vm_start + offset; -- vaddr -= vma->vm_pgoff << PAGE_SHIFT; -+ return vma->vm_start + offset - ((loff_t)vma->vm_pgoff << PAGE_SHIFT); -+} - -- return vaddr; -+static loff_t vaddr_to_offset(struct vm_area_struct *vma, unsigned long vaddr) -+{ -+ return ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (vaddr - vma->vm_start); - } - - /** -@@ -121,41 +129,27 @@ static loff_t vma_address(struct vm_area_struct *vma, loff_t offset) - * based on replace_page in mm/ksm.c - * - * @vma: vma that holds the pte pointing to page -+ * @addr: address the old @page is mapped at - * @page: the cowed page we are replacing by kpage - * @kpage: the modified page we replace page by - * - * Returns 0 on success, -EFAULT on failure. - */ --static int __replace_page(struct vm_area_struct *vma, struct page *page, struct page *kpage) -+static int __replace_page(struct vm_area_struct *vma, unsigned long addr, -+ struct page *page, struct page *kpage) - { - struct mm_struct *mm = vma->vm_mm; -- pgd_t *pgd; -- pud_t *pud; -- pmd_t *pmd; -- pte_t *ptep; - spinlock_t *ptl; -- unsigned long addr; -- int err = -EFAULT; -- -- addr = page_address_in_vma(page, vma); -- if (addr == -EFAULT) -- goto out; -- -- pgd = pgd_offset(mm, addr); -- if (!pgd_present(*pgd)) -- goto out; -- -- pud = pud_offset(pgd, addr); -- if (!pud_present(*pud)) -- goto out; -+ pte_t *ptep; -+ int err; - -- pmd = pmd_offset(pud, addr); -- if (!pmd_present(*pmd)) -- goto out; -+ /* For try_to_free_swap() and munlock_vma_page() below */ -+ lock_page(page); - -- ptep = pte_offset_map_lock(mm, pmd, addr, &ptl); -+ err = -EAGAIN; -+ ptep = page_check_address(page, mm, addr, &ptl, 0); - if (!ptep) -- goto out; -+ goto unlock; - - get_page(kpage); - page_add_new_anon_rmap(kpage, vma, addr); -@@ -172,11 +166,15 @@ static int __replace_page(struct vm_area_struct *vma, struct page *page, struct - page_remove_rmap(page); - if (!page_mapped(page)) - try_to_free_swap(page); -- put_page(page); - pte_unmap_unlock(ptep, ptl); -- err = 0; - --out: -+ if (vma->vm_flags & VM_LOCKED) -+ munlock_vma_page(page); -+ put_page(page); -+ -+ err = 0; -+ unlock: -+ unlock_page(page); - return err; - } - -@@ -218,79 +216,46 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, - unsigned long vaddr, uprobe_opcode_t opcode) - { - struct page *old_page, *new_page; -- struct address_space *mapping; - void *vaddr_old, *vaddr_new; - struct vm_area_struct *vma; -- struct uprobe *uprobe; -- loff_t addr; - int ret; - -+retry: - /* Read the page with vaddr into memory */ - ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma); - if (ret <= 0) - return ret; - -- ret = -EINVAL; -- -- /* -- * We are interested in text pages only. Our pages of interest -- * should be mapped for read and execute only. We desist from -- * adding probes in write mapped pages since the breakpoints -- * might end up in the file copy. -- */ -- if (!valid_vma(vma, is_swbp_insn(&opcode))) -- goto put_out; -- -- uprobe = container_of(auprobe, struct uprobe, arch); -- mapping = uprobe->inode->i_mapping; -- if (mapping != vma->vm_file->f_mapping) -- goto put_out; -- -- addr = vma_address(vma, uprobe->offset); -- if (vaddr != (unsigned long)addr) -- goto put_out; -- - ret = -ENOMEM; - new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr); - if (!new_page) -- goto put_out; -+ goto put_old; - - __SetPageUptodate(new_page); - -- /* -- * lock page will serialize against do_wp_page()'s -- * PageAnon() handling -- */ -- lock_page(old_page); - /* copy the page now that we've got it stable */ - vaddr_old = kmap_atomic(old_page); - vaddr_new = kmap_atomic(new_page); - - memcpy(vaddr_new, vaddr_old, PAGE_SIZE); -- -- /* poke the new insn in, ASSUMES we don't cross page boundary */ -- vaddr &= ~PAGE_MASK; -- BUG_ON(vaddr + UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); -- memcpy(vaddr_new + vaddr, &opcode, UPROBE_SWBP_INSN_SIZE); -+ memcpy(vaddr_new + (vaddr & ~PAGE_MASK), &opcode, UPROBE_SWBP_INSN_SIZE); - - kunmap_atomic(vaddr_new); - kunmap_atomic(vaddr_old); - - ret = anon_vma_prepare(vma); - if (ret) -- goto unlock_out; -+ goto put_new; - -- lock_page(new_page); -- ret = __replace_page(vma, old_page, new_page); -- unlock_page(new_page); -+ ret = __replace_page(vma, vaddr, old_page, new_page); - --unlock_out: -- unlock_page(old_page); -+put_new: - page_cache_release(new_page); -- --put_out: -+put_old: - put_page(old_page); - -+ if (unlikely(ret == -EAGAIN)) -+ goto retry; - return ret; - } - -@@ -312,16 +277,14 @@ static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_ - void *vaddr_new; - int ret; - -- ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &page, NULL); -+ ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL); - if (ret <= 0) - return ret; - -- lock_page(page); - vaddr_new = kmap_atomic(page); - vaddr &= ~PAGE_MASK; - memcpy(opcode, vaddr_new + vaddr, UPROBE_SWBP_INSN_SIZE); - kunmap_atomic(vaddr_new); -- unlock_page(page); - - put_page(page); - -@@ -333,10 +296,20 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) - uprobe_opcode_t opcode; - int result; - -+ if (current->mm == mm) { -+ pagefault_disable(); -+ result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr, -+ sizeof(opcode)); -+ pagefault_enable(); -+ -+ if (likely(result == 0)) -+ goto out; -+ } -+ - result = read_opcode(mm, vaddr, &opcode); - if (result) - return result; -- -+out: - if (is_swbp_insn(&opcode)) - return 1; - -@@ -355,10 +328,12 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) - int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) - { - int result; -- -+ /* -+ * See the comment near uprobes_hash(). -+ */ - result = is_swbp_at_addr(mm, vaddr); - if (result == 1) -- return -EEXIST; -+ return 0; - - if (result) - return result; -@@ -371,24 +346,22 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned - * @mm: the probed process address space. - * @auprobe: arch specific probepoint information. - * @vaddr: the virtual address to insert the opcode. -- * @verify: if true, verify existance of breakpoint instruction. - * - * For mm @mm, restore the original opcode (opcode) at @vaddr. - * Return 0 (success) or a negative errno. - */ - int __weak --set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr, bool verify) -+set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) - { -- if (verify) { -- int result; -+ int result; - -- result = is_swbp_at_addr(mm, vaddr); -- if (!result) -- return -EINVAL; -+ result = is_swbp_at_addr(mm, vaddr); -+ if (!result) -+ return -EINVAL; -+ -+ if (result != 1) -+ return result; - -- if (result != 1) -- return result; -- } - return write_opcode(auprobe, mm, vaddr, *(uprobe_opcode_t *)auprobe->insn); - } - -@@ -439,11 +412,10 @@ static struct uprobe *__find_uprobe(struct inode *inode, loff_t offset) - static struct uprobe *find_uprobe(struct inode *inode, loff_t offset) - { - struct uprobe *uprobe; -- unsigned long flags; - -- spin_lock_irqsave(&uprobes_treelock, flags); -+ spin_lock(&uprobes_treelock); - uprobe = __find_uprobe(inode, offset); -- spin_unlock_irqrestore(&uprobes_treelock, flags); -+ spin_unlock(&uprobes_treelock); - - return uprobe; - } -@@ -490,12 +462,11 @@ static struct uprobe *__insert_uprobe(struct uprobe *uprobe) - */ - static struct uprobe *insert_uprobe(struct uprobe *uprobe) - { -- unsigned long flags; - struct uprobe *u; - -- spin_lock_irqsave(&uprobes_treelock, flags); -+ spin_lock(&uprobes_treelock); - u = __insert_uprobe(uprobe); -- spin_unlock_irqrestore(&uprobes_treelock, flags); -+ spin_unlock(&uprobes_treelock); - - /* For now assume that the instruction need not be single-stepped */ - uprobe->flags |= UPROBE_SKIP_SSTEP; -@@ -520,7 +491,6 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset) - uprobe->inode = igrab(inode); - uprobe->offset = offset; - init_rwsem(&uprobe->consumer_rwsem); -- INIT_LIST_HEAD(&uprobe->pending_list); - - /* add to uprobes_tree, sorted on inode:offset */ - cur_uprobe = insert_uprobe(uprobe); -@@ -588,20 +558,22 @@ static bool consumer_del(struct uprobe *uprobe, struct uprobe_consumer *uc) - } - - static int --__copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *insn, -- unsigned long nbytes, unsigned long offset) -+__copy_insn(struct address_space *mapping, struct file *filp, char *insn, -+ unsigned long nbytes, loff_t offset) - { -- struct file *filp = vma->vm_file; - struct page *page; - void *vaddr; -- unsigned long off1; -- unsigned long idx; -+ unsigned long off; -+ pgoff_t idx; - - if (!filp) - return -EINVAL; - -- idx = (unsigned long)(offset >> PAGE_CACHE_SHIFT); -- off1 = offset &= ~PAGE_MASK; -+ if (!mapping->a_ops->readpage) -+ return -EIO; -+ -+ idx = offset >> PAGE_CACHE_SHIFT; -+ off = offset & ~PAGE_MASK; - - /* - * Ensure that the page that has the original instruction is -@@ -612,22 +584,20 @@ __copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *ins - return PTR_ERR(page); - - vaddr = kmap_atomic(page); -- memcpy(insn, vaddr + off1, nbytes); -+ memcpy(insn, vaddr + off, nbytes); - kunmap_atomic(vaddr); - page_cache_release(page); - - return 0; - } - --static int --copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr) -+static int copy_insn(struct uprobe *uprobe, struct file *filp) - { - struct address_space *mapping; - unsigned long nbytes; - int bytes; - -- addr &= ~PAGE_MASK; -- nbytes = PAGE_SIZE - addr; -+ nbytes = PAGE_SIZE - (uprobe->offset & ~PAGE_MASK); - mapping = uprobe->inode->i_mapping; - - /* Instruction at end of binary; copy only available bytes */ -@@ -638,13 +608,13 @@ copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr) - - /* Instruction at the page-boundary; copy bytes in second page */ - if (nbytes < bytes) { -- if (__copy_insn(mapping, vma, uprobe->arch.insn + nbytes, -- bytes - nbytes, uprobe->offset + nbytes)) -- return -ENOMEM; -- -+ int err = __copy_insn(mapping, filp, uprobe->arch.insn + nbytes, -+ bytes - nbytes, uprobe->offset + nbytes); -+ if (err) -+ return err; - bytes = nbytes; - } -- return __copy_insn(mapping, vma, uprobe->arch.insn, bytes, uprobe->offset); -+ return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset); - } - - /* -@@ -672,9 +642,9 @@ copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr) - */ - static int - install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, -- struct vm_area_struct *vma, loff_t vaddr) -+ struct vm_area_struct *vma, unsigned long vaddr) - { -- unsigned long addr; -+ bool first_uprobe; - int ret; - - /* -@@ -685,204 +655,194 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, - * Hence behave as if probe already existed. - */ - if (!uprobe->consumers) -- return -EEXIST; -- -- addr = (unsigned long)vaddr; -+ return 0; - - if (!(uprobe->flags & UPROBE_COPY_INSN)) { -- ret = copy_insn(uprobe, vma, addr); -+ ret = copy_insn(uprobe, vma->vm_file); - if (ret) - return ret; - - if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) -- return -EEXIST; -+ return -ENOTSUPP; - -- ret = arch_uprobe_analyze_insn(&uprobe->arch, mm); -+ ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr); - if (ret) - return ret; - -+ /* write_opcode() assumes we don't cross page boundary */ -+ BUG_ON((uprobe->offset & ~PAGE_MASK) + -+ UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); -+ - uprobe->flags |= UPROBE_COPY_INSN; - } - - /* -- * Ideally, should be updating the probe count after the breakpoint -- * has been successfully inserted. However a thread could hit the -- * breakpoint we just inserted even before the probe count is -- * incremented. If this is the first breakpoint placed, breakpoint -- * notifier might ignore uprobes and pass the trap to the thread. -- * Hence increment before and decrement on failure. -+ * set MMF_HAS_UPROBES in advance for uprobe_pre_sstep_notifier(), -+ * the task can hit this breakpoint right after __replace_page(). - */ -- atomic_inc(&mm->uprobes_state.count); -- ret = set_swbp(&uprobe->arch, mm, addr); -- if (ret) -- atomic_dec(&mm->uprobes_state.count); -+ first_uprobe = !test_bit(MMF_HAS_UPROBES, &mm->flags); -+ if (first_uprobe) -+ set_bit(MMF_HAS_UPROBES, &mm->flags); -+ -+ ret = set_swbp(&uprobe->arch, mm, vaddr); -+ if (!ret) -+ clear_bit(MMF_RECALC_UPROBES, &mm->flags); -+ else if (first_uprobe) -+ clear_bit(MMF_HAS_UPROBES, &mm->flags); - - return ret; - } - - static void --remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, loff_t vaddr) -+remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr) - { -- if (!set_orig_insn(&uprobe->arch, mm, (unsigned long)vaddr, true)) -- atomic_dec(&mm->uprobes_state.count); -+ /* can happen if uprobe_register() fails */ -+ if (!test_bit(MMF_HAS_UPROBES, &mm->flags)) -+ return; -+ -+ set_bit(MMF_RECALC_UPROBES, &mm->flags); -+ set_orig_insn(&uprobe->arch, mm, vaddr); - } - - /* -- * There could be threads that have hit the breakpoint and are entering the -- * notifier code and trying to acquire the uprobes_treelock. The thread -- * calling delete_uprobe() that is removing the uprobe from the rb_tree can -- * race with these threads and might acquire the uprobes_treelock compared -- * to some of the breakpoint hit threads. In such a case, the breakpoint -- * hit threads will not find the uprobe. The current unregistering thread -- * waits till all other threads have hit a breakpoint, to acquire the -- * uprobes_treelock before the uprobe is removed from the rbtree. -+ * There could be threads that have already hit the breakpoint. They -+ * will recheck the current insn and restart if find_uprobe() fails. -+ * See find_active_uprobe(). - */ - static void delete_uprobe(struct uprobe *uprobe) - { -- unsigned long flags; -- -- synchronize_srcu(&uprobes_srcu); -- spin_lock_irqsave(&uprobes_treelock, flags); -+ spin_lock(&uprobes_treelock); - rb_erase(&uprobe->rb_node, &uprobes_tree); -- spin_unlock_irqrestore(&uprobes_treelock, flags); -+ spin_unlock(&uprobes_treelock); - iput(uprobe->inode); - put_uprobe(uprobe); - atomic_dec(&uprobe_events); - } - --static struct vma_info * --__find_next_vma_info(struct address_space *mapping, struct list_head *head, -- struct vma_info *vi, loff_t offset, bool is_register) -+struct map_info { -+ struct map_info *next; -+ struct mm_struct *mm; -+ unsigned long vaddr; -+}; -+ -+static inline struct map_info *free_map_info(struct map_info *info) -+{ -+ struct map_info *next = info->next; -+ kfree(info); -+ return next; -+} -+ -+static struct map_info * -+build_map_info(struct address_space *mapping, loff_t offset, bool is_register) - { -+ unsigned long pgoff = offset >> PAGE_SHIFT; - struct prio_tree_iter iter; - struct vm_area_struct *vma; -- struct vma_info *tmpvi; -- unsigned long pgoff; -- int existing_vma; -- loff_t vaddr; -- -- pgoff = offset >> PAGE_SHIFT; -+ struct map_info *curr = NULL; -+ struct map_info *prev = NULL; -+ struct map_info *info; -+ int more = 0; - -+ again: -+ mutex_lock(&mapping->i_mmap_mutex); - vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { - if (!valid_vma(vma, is_register)) - continue; - -- existing_vma = 0; -- vaddr = vma_address(vma, offset); -- -- list_for_each_entry(tmpvi, head, probe_list) { -- if (tmpvi->mm == vma->vm_mm && tmpvi->vaddr == vaddr) { -- existing_vma = 1; -- break; -- } -+ if (!prev && !more) { -+ /* -+ * Needs GFP_NOWAIT to avoid i_mmap_mutex recursion through -+ * reclaim. This is optimistic, no harm done if it fails. -+ */ -+ prev = kmalloc(sizeof(struct map_info), -+ GFP_NOWAIT | __GFP_NOMEMALLOC | __GFP_NOWARN); -+ if (prev) -+ prev->next = NULL; - } -- -- /* -- * Another vma needs a probe to be installed. However skip -- * installing the probe if the vma is about to be unlinked. -- */ -- if (!existing_vma && atomic_inc_not_zero(&vma->vm_mm->mm_users)) { -- vi->mm = vma->vm_mm; -- vi->vaddr = vaddr; -- list_add(&vi->probe_list, head); -- -- return vi; -+ if (!prev) { -+ more++; -+ continue; - } -- } -- -- return NULL; --} - --/* -- * Iterate in the rmap prio tree and find a vma where a probe has not -- * yet been inserted. -- */ --static struct vma_info * --find_next_vma_info(struct address_space *mapping, struct list_head *head, -- loff_t offset, bool is_register) --{ -- struct vma_info *vi, *retvi; -+ if (!atomic_inc_not_zero(&vma->vm_mm->mm_users)) -+ continue; - -- vi = kzalloc(sizeof(struct vma_info), GFP_KERNEL); -- if (!vi) -- return ERR_PTR(-ENOMEM); -+ info = prev; -+ prev = prev->next; -+ info->next = curr; -+ curr = info; - -- mutex_lock(&mapping->i_mmap_mutex); -- retvi = __find_next_vma_info(mapping, head, vi, offset, is_register); -+ info->mm = vma->vm_mm; -+ info->vaddr = offset_to_vaddr(vma, offset); -+ } - mutex_unlock(&mapping->i_mmap_mutex); - -- if (!retvi) -- kfree(vi); -+ if (!more) -+ goto out; -+ -+ prev = curr; -+ while (curr) { -+ mmput(curr->mm); -+ curr = curr->next; -+ } - -- return retvi; -+ do { -+ info = kmalloc(sizeof(struct map_info), GFP_KERNEL); -+ if (!info) { -+ curr = ERR_PTR(-ENOMEM); -+ goto out; -+ } -+ info->next = prev; -+ prev = info; -+ } while (--more); -+ -+ goto again; -+ out: -+ while (prev) -+ prev = free_map_info(prev); -+ return curr; - } - - static int register_for_each_vma(struct uprobe *uprobe, bool is_register) - { -- struct list_head try_list; -- struct vm_area_struct *vma; -- struct address_space *mapping; -- struct vma_info *vi, *tmpvi; -- struct mm_struct *mm; -- loff_t vaddr; -- int ret; -+ struct map_info *info; -+ int err = 0; - -- mapping = uprobe->inode->i_mapping; -- INIT_LIST_HEAD(&try_list); -+ info = build_map_info(uprobe->inode->i_mapping, -+ uprobe->offset, is_register); -+ if (IS_ERR(info)) -+ return PTR_ERR(info); - -- ret = 0; -+ while (info) { -+ struct mm_struct *mm = info->mm; -+ struct vm_area_struct *vma; - -- for (;;) { -- vi = find_next_vma_info(mapping, &try_list, uprobe->offset, is_register); -- if (!vi) -- break; -+ if (err) -+ goto free; - -- if (IS_ERR(vi)) { -- ret = PTR_ERR(vi); -- break; -- } -+ down_write(&mm->mmap_sem); -+ vma = find_vma(mm, info->vaddr); -+ if (!vma || !valid_vma(vma, is_register) || -+ vma->vm_file->f_mapping->host != uprobe->inode) -+ goto unlock; - -- mm = vi->mm; -- down_read(&mm->mmap_sem); -- vma = find_vma(mm, (unsigned long)vi->vaddr); -- if (!vma || !valid_vma(vma, is_register)) { -- list_del(&vi->probe_list); -- kfree(vi); -- up_read(&mm->mmap_sem); -- mmput(mm); -- continue; -- } -- vaddr = vma_address(vma, uprobe->offset); -- if (vma->vm_file->f_mapping->host != uprobe->inode || -- vaddr != vi->vaddr) { -- list_del(&vi->probe_list); -- kfree(vi); -- up_read(&mm->mmap_sem); -- mmput(mm); -- continue; -- } -+ if (vma->vm_start > info->vaddr || -+ vaddr_to_offset(vma, info->vaddr) != uprobe->offset) -+ goto unlock; - - if (is_register) -- ret = install_breakpoint(uprobe, mm, vma, vi->vaddr); -+ err = install_breakpoint(uprobe, mm, vma, info->vaddr); - else -- remove_breakpoint(uprobe, mm, vi->vaddr); -+ remove_breakpoint(uprobe, mm, info->vaddr); - -- up_read(&mm->mmap_sem); -+ unlock: -+ up_write(&mm->mmap_sem); -+ free: - mmput(mm); -- if (is_register) { -- if (ret && ret == -EEXIST) -- ret = 0; -- if (ret) -- break; -- } -- } -- -- list_for_each_entry_safe(vi, tmpvi, &try_list, probe_list) { -- list_del(&vi->probe_list); -- kfree(vi); -+ info = free_map_info(info); - } - -- return ret; -+ return err; - } - - static int __uprobe_register(struct uprobe *uprobe) -@@ -941,10 +901,12 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer * - } - - mutex_unlock(uprobes_hash(inode)); -- put_uprobe(uprobe); -+ if (uprobe) -+ put_uprobe(uprobe); - - return ret; - } -+EXPORT_SYMBOL_GPL(uprobe_register); - - /* - * uprobe_unregister - unregister a already registered probe. -@@ -976,81 +938,81 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume - if (uprobe) - put_uprobe(uprobe); - } -+EXPORT_SYMBOL_GPL(uprobe_unregister); - --/* -- * Of all the nodes that correspond to the given inode, return the node -- * with the least offset. -- */ --static struct rb_node *find_least_offset_node(struct inode *inode) -+static struct rb_node * -+find_node_in_range(struct inode *inode, loff_t min, loff_t max) - { -- struct uprobe u = { .inode = inode, .offset = 0}; - struct rb_node *n = uprobes_tree.rb_node; -- struct rb_node *close_node = NULL; -- struct uprobe *uprobe; -- int match; - - while (n) { -- uprobe = rb_entry(n, struct uprobe, rb_node); -- match = match_uprobe(&u, uprobe); -- -- if (uprobe->inode == inode) -- close_node = n; -- -- if (!match) -- return close_node; -+ struct uprobe *u = rb_entry(n, struct uprobe, rb_node); - -- if (match < 0) -+ if (inode < u->inode) { - n = n->rb_left; -- else -+ } else if (inode > u->inode) { - n = n->rb_right; -+ } else { -+ if (max < u->offset) -+ n = n->rb_left; -+ else if (min > u->offset) -+ n = n->rb_right; -+ else -+ break; -+ } - } - -- return close_node; -+ return n; - } - - /* -- * For a given inode, build a list of probes that need to be inserted. -+ * For a given range in vma, build a list of probes that need to be inserted. - */ --static void build_probe_list(struct inode *inode, struct list_head *head) -+static void build_probe_list(struct inode *inode, -+ struct vm_area_struct *vma, -+ unsigned long start, unsigned long end, -+ struct list_head *head) - { -- struct uprobe *uprobe; -- unsigned long flags; -- struct rb_node *n; -- -- spin_lock_irqsave(&uprobes_treelock, flags); -- -- n = find_least_offset_node(inode); -+ loff_t min, max; -+ struct rb_node *n, *t; -+ struct uprobe *u; - -- for (; n; n = rb_next(n)) { -- uprobe = rb_entry(n, struct uprobe, rb_node); -- if (uprobe->inode != inode) -- break; -+ INIT_LIST_HEAD(head); -+ min = vaddr_to_offset(vma, start); -+ max = min + (end - start) - 1; - -- list_add(&uprobe->pending_list, head); -- atomic_inc(&uprobe->ref); -+ spin_lock(&uprobes_treelock); -+ n = find_node_in_range(inode, min, max); -+ if (n) { -+ for (t = n; t; t = rb_prev(t)) { -+ u = rb_entry(t, struct uprobe, rb_node); -+ if (u->inode != inode || u->offset < min) -+ break; -+ list_add(&u->pending_list, head); -+ atomic_inc(&u->ref); -+ } -+ for (t = n; (t = rb_next(t)); ) { -+ u = rb_entry(t, struct uprobe, rb_node); -+ if (u->inode != inode || u->offset > max) -+ break; -+ list_add(&u->pending_list, head); -+ atomic_inc(&u->ref); -+ } - } -- -- spin_unlock_irqrestore(&uprobes_treelock, flags); -+ spin_unlock(&uprobes_treelock); - } - - /* -- * Called from mmap_region. -- * called with mm->mmap_sem acquired. -- * -- * Return -ve no if we fail to insert probes and we cannot -- * bail-out. -- * Return 0 otherwise. i.e: -+ * Called from mmap_region/vma_adjust with mm->mmap_sem acquired. - * -- * - successful insertion of probes -- * - (or) no possible probes to be inserted. -- * - (or) insertion of probes failed but we can bail-out. -+ * Currently we ignore all errors and always return 0, the callers -+ * can't handle the failure anyway. - */ - int uprobe_mmap(struct vm_area_struct *vma) - { - struct list_head tmp_list; - struct uprobe *uprobe, *u; - struct inode *inode; -- int ret, count; - - if (!atomic_read(&uprobe_events) || !valid_vma(vma, true)) - return 0; -@@ -1059,54 +1021,38 @@ int uprobe_mmap(struct vm_area_struct *vma) - if (!inode) - return 0; - -- INIT_LIST_HEAD(&tmp_list); - mutex_lock(uprobes_mmap_hash(inode)); -- build_probe_list(inode, &tmp_list); -- -- ret = 0; -- count = 0; -+ build_probe_list(inode, vma, vma->vm_start, vma->vm_end, &tmp_list); - - list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { -- loff_t vaddr; -- -- list_del(&uprobe->pending_list); -- if (!ret) { -- vaddr = vma_address(vma, uprobe->offset); -- -- if (vaddr < vma->vm_start || vaddr >= vma->vm_end) { -- put_uprobe(uprobe); -- continue; -- } -- -- ret = install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); -- -- /* Ignore double add: */ -- if (ret == -EEXIST) { -- ret = 0; -- -- if (!is_swbp_at_addr(vma->vm_mm, vaddr)) -- continue; -- -- /* -- * Unable to insert a breakpoint, but -- * breakpoint lies underneath. Increment the -- * probe count. -- */ -- atomic_inc(&vma->vm_mm->uprobes_state.count); -- } -- -- if (!ret) -- count++; -+ if (!fatal_signal_pending(current)) { -+ unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset); -+ install_breakpoint(uprobe, vma->vm_mm, vma, vaddr); - } - put_uprobe(uprobe); - } -- - mutex_unlock(uprobes_mmap_hash(inode)); - -- if (ret) -- atomic_sub(count, &vma->vm_mm->uprobes_state.count); -+ return 0; -+} - -- return ret; -+static bool -+vma_has_uprobes(struct vm_area_struct *vma, unsigned long start, unsigned long end) -+{ -+ loff_t min, max; -+ struct inode *inode; -+ struct rb_node *n; -+ -+ inode = vma->vm_file->f_mapping->host; -+ -+ min = vaddr_to_offset(vma, start); -+ max = min + (end - start) - 1; -+ -+ spin_lock(&uprobes_treelock); -+ n = find_node_in_range(inode, min, max); -+ spin_unlock(&uprobes_treelock); -+ -+ return !!n; - } - - /* -@@ -1114,41 +1060,18 @@ int uprobe_mmap(struct vm_area_struct *vma) - */ - void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) - { -- struct list_head tmp_list; -- struct uprobe *uprobe, *u; -- struct inode *inode; -- - if (!atomic_read(&uprobe_events) || !valid_vma(vma, false)) - return; - -- if (!atomic_read(&vma->vm_mm->uprobes_state.count)) -+ if (!atomic_read(&vma->vm_mm->mm_users)) /* called by mmput() ? */ - return; - -- inode = vma->vm_file->f_mapping->host; -- if (!inode) -+ if (!test_bit(MMF_HAS_UPROBES, &vma->vm_mm->flags) || -+ test_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags)) - return; - -- INIT_LIST_HEAD(&tmp_list); -- mutex_lock(uprobes_mmap_hash(inode)); -- build_probe_list(inode, &tmp_list); -- -- list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) { -- loff_t vaddr; -- -- list_del(&uprobe->pending_list); -- vaddr = vma_address(vma, uprobe->offset); -- -- if (vaddr >= start && vaddr < end) { -- /* -- * An unregister could have removed the probe before -- * unmap. So check before we decrement the count. -- */ -- if (is_swbp_at_addr(vma->vm_mm, vaddr) == 1) -- atomic_dec(&vma->vm_mm->uprobes_state.count); -- } -- put_uprobe(uprobe); -- } -- mutex_unlock(uprobes_mmap_hash(inode)); -+ if (vma_has_uprobes(vma, start, end)) -+ set_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags); - } - - /* Slot allocation for XOL */ -@@ -1250,13 +1173,15 @@ void uprobe_clear_state(struct mm_struct *mm) - kfree(area); - } - --/* -- * uprobe_reset_state - Free the area allocated for slots. -- */ --void uprobe_reset_state(struct mm_struct *mm) -+void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm) - { -- mm->uprobes_state.xol_area = NULL; -- atomic_set(&mm->uprobes_state.count, 0); -+ newmm->uprobes_state.xol_area = NULL; -+ -+ if (test_bit(MMF_HAS_UPROBES, &oldmm->flags)) { -+ set_bit(MMF_HAS_UPROBES, &newmm->flags); -+ /* unconditionally, dup_mmap() skips VM_DONTCOPY vmas */ -+ set_bit(MMF_RECALC_UPROBES, &newmm->flags); -+ } - } - - /* -@@ -1378,9 +1303,6 @@ void uprobe_free_utask(struct task_struct *t) - { - struct uprobe_task *utask = t->utask; - -- if (t->uprobe_srcu_id != -1) -- srcu_read_unlock_raw(&uprobes_srcu, t->uprobe_srcu_id); -- - if (!utask) - return; - -@@ -1398,7 +1320,6 @@ void uprobe_free_utask(struct task_struct *t) - void uprobe_copy_process(struct task_struct *t) - { - t->utask = NULL; -- t->uprobe_srcu_id = -1; - } - - /* -@@ -1417,7 +1338,6 @@ static struct uprobe_task *add_utask(void) - if (unlikely(!utask)) - return NULL; - -- utask->active_uprobe = NULL; - current->utask = utask; - return utask; - } -@@ -1479,41 +1399,93 @@ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs) - return false; - } - -+static void mmf_recalc_uprobes(struct mm_struct *mm) -+{ -+ struct vm_area_struct *vma; -+ -+ for (vma = mm->mmap; vma; vma = vma->vm_next) { -+ if (!valid_vma(vma, false)) -+ continue; -+ /* -+ * This is not strictly accurate, we can race with -+ * uprobe_unregister() and see the already removed -+ * uprobe if delete_uprobe() was not yet called. -+ */ -+ if (vma_has_uprobes(vma, vma->vm_start, vma->vm_end)) -+ return; -+ } -+ -+ clear_bit(MMF_HAS_UPROBES, &mm->flags); -+} -+ -+static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) -+{ -+ struct mm_struct *mm = current->mm; -+ struct uprobe *uprobe = NULL; -+ struct vm_area_struct *vma; -+ -+ down_read(&mm->mmap_sem); -+ vma = find_vma(mm, bp_vaddr); -+ if (vma && vma->vm_start <= bp_vaddr) { -+ if (valid_vma(vma, false)) { -+ struct inode *inode = vma->vm_file->f_mapping->host; -+ loff_t offset = vaddr_to_offset(vma, bp_vaddr); -+ -+ uprobe = find_uprobe(inode, offset); -+ } -+ -+ if (!uprobe) -+ *is_swbp = is_swbp_at_addr(mm, bp_vaddr); -+ } else { -+ *is_swbp = -EFAULT; -+ } -+ -+ if (!uprobe && test_and_clear_bit(MMF_RECALC_UPROBES, &mm->flags)) -+ mmf_recalc_uprobes(mm); -+ up_read(&mm->mmap_sem); -+ -+ return uprobe; -+} -+ -+void __weak arch_uprobe_enable_step(struct arch_uprobe *arch) -+{ -+ user_enable_single_step(current); -+} -+ -+void __weak arch_uprobe_disable_step(struct arch_uprobe *arch) -+{ -+ user_disable_single_step(current); -+} -+ - /* - * Run handler and ask thread to singlestep. - * Ensure all non-fatal signals cannot interrupt thread while it singlesteps. - */ - static void handle_swbp(struct pt_regs *regs) - { -- struct vm_area_struct *vma; - struct uprobe_task *utask; - struct uprobe *uprobe; -- struct mm_struct *mm; - unsigned long bp_vaddr; -+ int uninitialized_var(is_swbp); - -- uprobe = NULL; - bp_vaddr = uprobe_get_swbp_addr(regs); -- mm = current->mm; -- down_read(&mm->mmap_sem); -- vma = find_vma(mm, bp_vaddr); -- -- if (vma && vma->vm_start <= bp_vaddr && valid_vma(vma, false)) { -- struct inode *inode; -- loff_t offset; -- -- inode = vma->vm_file->f_mapping->host; -- offset = bp_vaddr - vma->vm_start; -- offset += (vma->vm_pgoff << PAGE_SHIFT); -- uprobe = find_uprobe(inode, offset); -- } -- -- srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id); -- current->uprobe_srcu_id = -1; -- up_read(&mm->mmap_sem); -+ uprobe = find_active_uprobe(bp_vaddr, &is_swbp); - - if (!uprobe) { -- /* No matching uprobe; signal SIGTRAP. */ -- send_sig(SIGTRAP, current, 0); -+ if (is_swbp > 0) { -+ /* No matching uprobe; signal SIGTRAP. */ -+ send_sig(SIGTRAP, current, 0); -+ } else { -+ /* -+ * Either we raced with uprobe_unregister() or we can't -+ * access this memory. The latter is only possible if -+ * another thread plays with our ->mm. In both cases -+ * we can simply restart. If this vma was unmapped we -+ * can pretend this insn was not executed yet and get -+ * the (correct) SIGSEGV after restart. -+ */ -+ instruction_pointer_set(regs, bp_vaddr); -+ } - return; - } - -@@ -1531,7 +1503,7 @@ static void handle_swbp(struct pt_regs *regs) - - utask->state = UTASK_SSTEP; - if (!pre_ssout(uprobe, regs, bp_vaddr)) { -- user_enable_single_step(current); -+ arch_uprobe_enable_step(&uprobe->arch); - return; - } - -@@ -1540,17 +1512,15 @@ cleanup_ret: - utask->active_uprobe = NULL; - utask->state = UTASK_RUNNING; - } -- if (uprobe) { -- if (!(uprobe->flags & UPROBE_SKIP_SSTEP)) -+ if (!(uprobe->flags & UPROBE_SKIP_SSTEP)) - -- /* -- * cannot singlestep; cannot skip instruction; -- * re-execute the instruction. -- */ -- instruction_pointer_set(regs, bp_vaddr); -+ /* -+ * cannot singlestep; cannot skip instruction; -+ * re-execute the instruction. -+ */ -+ instruction_pointer_set(regs, bp_vaddr); - -- put_uprobe(uprobe); -- } -+ put_uprobe(uprobe); - } - - /* -@@ -1569,10 +1539,10 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs) - else - WARN_ON_ONCE(1); - -+ arch_uprobe_disable_step(&uprobe->arch); - put_uprobe(uprobe); - utask->active_uprobe = NULL; - utask->state = UTASK_RUNNING; -- user_disable_single_step(current); - xol_free_insn_slot(current); - - spin_lock_irq(¤t->sighand->siglock); -@@ -1611,8 +1581,7 @@ int uprobe_pre_sstep_notifier(struct pt_regs *regs) - { - struct uprobe_task *utask; - -- if (!current->mm || !atomic_read(¤t->mm->uprobes_state.count)) -- /* task is currently not uprobed */ -+ if (!current->mm || !test_bit(MMF_HAS_UPROBES, ¤t->mm->flags)) - return 0; - - utask = current->utask; -@@ -1620,7 +1589,6 @@ int uprobe_pre_sstep_notifier(struct pt_regs *regs) - utask->state = UTASK_BP_HIT; - - set_thread_flag(TIF_UPROBE); -- current->uprobe_srcu_id = srcu_read_lock_raw(&uprobes_srcu); - - return 1; - } -@@ -1655,7 +1623,6 @@ static int __init init_uprobes(void) - mutex_init(&uprobes_mutex[i]); - mutex_init(&uprobes_mmap_mutex[i]); - } -- init_srcu_struct(&uprobes_srcu); - - return register_die_notifier(&uprobe_exception_nb); - } -diff --git a/kernel/fork.c b/kernel/fork.c -index 7a1d634..5d0137c 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -355,6 +355,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) - - down_write(&oldmm->mmap_sem); - flush_cache_dup_mm(oldmm); -+ uprobe_dup_mmap(oldmm, mm); - /* - * Not linked in yet - no deadlock potential: - */ -@@ -843,8 +841,6 @@ struct mm_struct *dup_mm(struct task_struct *tsk) - #ifdef CONFIG_TRANSPARENT_HUGEPAGE - mm->pmd_huge_pte = NULL; - #endif -- uprobe_reset_state(mm); -- - if (!mm_init(mm, tsk)) - goto fail_nomem; - -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index a232bb5..764fcd1 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -33,6 +33,12 @@ static int ptrace_trapping_sleep_fn(void *flags) - } - - /* -+ * This is declared in linux/regset.h and defined in machine-dependent -+ * code. We put the export here to ensure no machine forgets it. -+ */ -+EXPORT_SYMBOL_GPL(task_user_regset_view); -+ -+/* - * ptrace a task: make the debugger its new parent and - * move it to the ptrace list. - * -diff --git a/mm/mmap.c b/mm/mmap.c -index 3edfcdf..f25fd3f 100644 ---- a/mm/mmap.c -+++ b/mm/mmap.c -@@ -2345,9 +2344,6 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) - security_vm_enough_memory_mm(mm, vma_pages(vma))) - return -ENOMEM; - -- if (vma->vm_file && uprobe_mmap(vma)) -- return -EINVAL; -- - vma_link(mm, vma, prev, rb_link, rb_parent); - return 0; - } -@@ -2418,9 +2414,6 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, - if (new_vma->vm_file) { - get_file(new_vma->vm_file); - -- if (uprobe_mmap(new_vma)) -- goto out_free_mempol; -- - if (vma->vm_flags & VM_EXECUTABLE) - added_exe_file_vma(mm); - } -_______________________________________________ -kernel mailing list -kernel@lists.fedoraproject.org -https://admin.fedoraproject.org/mailman/listinfo/kernel From 2620ccc11db27ac3d15169be22172fba723fa158 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 16 Oct 2012 21:31:56 -0400 Subject: [PATCH 439/487] upload --- sources | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sources b/sources index c3b8082d9..8ca40febd 100644 --- a/sources +++ b/sources @@ -1,2 +1 @@ -24153eaaa81dedc9481ada8cd9c3b83d linux-3.5.tar.xz -42f3977dbc0a7b8c978bc4ae9bca56ad patch-3.5.7.xz +1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz From d7f29cc8092d37ec600f55c2f4a05f8271cbc015 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 17 Oct 2012 00:54:20 -0400 Subject: [PATCH 440/487] Linux 3.6.2 --- kernel.spec | 7 +++++-- sources | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 1124dbddf..7755974d1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 0 +%define stable_update 2 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -1987,7 +1987,10 @@ fi # and build. %changelog -* Tue Oct 16 2012 Dave Jones +* Tue Oct 16 2012 Dave Jones 3.6.2-1 +- Linux 3.6.2 + +* Tue Oct 16 2012 Dave Jones 3.6.0-1 - Linux 3.6 * Tue Oct 16 2012 Dave Jones 3.5.7-1 diff --git a/sources b/sources index 8ca40febd..47fce40c3 100644 --- a/sources +++ b/sources @@ -1 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz +ad1020c82a71ee1ef2416a0d12e724df patch-3.6.2.xz From dec491e2b4d135c6aeb25535ef7afab3a285f6a9 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 18 Oct 2012 08:26:39 -0400 Subject: [PATCH 441/487] Apply patch to fix iwlwifi crash (rhbz 770484) --- iwlwifi-fix-6000-ch-switch.patch | 94 ++++++++++++++++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 iwlwifi-fix-6000-ch-switch.patch diff --git a/iwlwifi-fix-6000-ch-switch.patch b/iwlwifi-fix-6000-ch-switch.patch new file mode 100644 index 000000000..0fbca2354 --- /dev/null +++ b/iwlwifi-fix-6000-ch-switch.patch @@ -0,0 +1,94 @@ +commit a7d3a5d97acd4b8db17e1d5c3014357c9b2040f9 +Author: Johannes Berg +Date: Tue Sep 25 16:40:12 2012 +0200 + + iwlwifi: fix 6000 series channel switch command + + The channel switch command for 6000 series devices + is larger than the maximum inline command size of + 320 bytes. The command is therefore refused with a + warning. Fix this by allocating the command and + using the NOCOPY mechanism. + + Cc: stable@kernel.org + Signed-off-by: Johannes Berg + +diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c +index 349c205..da58620 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/devices.c ++++ b/drivers/net/wireless/iwlwifi/dvm/devices.c +@@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, + * See iwlagn_mac_channel_switch. + */ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; +- struct iwl6000_channel_switch_cmd cmd; ++ struct iwl6000_channel_switch_cmd *cmd; + u32 switch_time_in_usec, ucode_switch_time; + u16 ch; + u32 tsf_low; +@@ -527,18 +527,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, + struct ieee80211_vif *vif = ctx->vif; + struct iwl_host_cmd hcmd = { + .id = REPLY_CHANNEL_SWITCH, +- .len = { sizeof(cmd), }, ++ .len = { sizeof(*cmd), }, + .flags = CMD_SYNC, +- .data = { &cmd, }, ++ .dataflags[0] = IWL_HCMD_DFL_NOCOPY, + }; ++ int err; + +- cmd.band = priv->band == IEEE80211_BAND_2GHZ; ++ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); ++ if (!cmd) ++ return -ENOMEM; ++ ++ hcmd.data[0] = cmd; ++ ++ cmd->band = priv->band == IEEE80211_BAND_2GHZ; + ch = ch_switch->channel->hw_value; + IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", + ctx->active.channel, ch); +- cmd.channel = cpu_to_le16(ch); +- cmd.rxon_flags = ctx->staging.flags; +- cmd.rxon_filter_flags = ctx->staging.filter_flags; ++ cmd->channel = cpu_to_le16(ch); ++ cmd->rxon_flags = ctx->staging.flags; ++ cmd->rxon_filter_flags = ctx->staging.filter_flags; + switch_count = ch_switch->count; + tsf_low = ch_switch->timestamp & 0x0ffffffff; + /* +@@ -554,23 +561,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, + switch_count = 0; + } + if (switch_count <= 1) +- cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); ++ cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time); + else { + switch_time_in_usec = + vif->bss_conf.beacon_int * switch_count * TIME_UNIT; + ucode_switch_time = iwl_usecs_to_beacons(priv, + switch_time_in_usec, + beacon_interval); +- cmd.switch_time = iwl_add_beacon_time(priv, +- priv->ucode_beacon_time, +- ucode_switch_time, +- beacon_interval); ++ cmd->switch_time = iwl_add_beacon_time(priv, ++ priv->ucode_beacon_time, ++ ucode_switch_time, ++ beacon_interval); + } + IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", +- cmd.switch_time); +- cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; ++ cmd->switch_time); ++ cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; + +- return iwl_dvm_send_cmd(priv, &hcmd); ++ err = iwl_dvm_send_cmd(priv, &hcmd); ++ kfree(cmd); ++ return err; + } + + struct iwl_lib_ops iwl6000_lib = { diff --git a/kernel.spec b/kernel.spec index 7755974d1..2fbb11c53 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -681,6 +681,9 @@ Patch21300: unhandled-irqs-switch-to-polling.patch #rhbz 804957 CVE-2012-1568 Patch21306: shlib_base_randomize.patch +#rhbz 770484 +Patch22071: iwlwifi-fix-6000-ch-switch.patch + # Debug patches Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch @@ -1287,6 +1290,9 @@ ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch ApplyPatch debug-808990.patch +#rhbz 770484 +ApplyPatch iwlwifi-fix-6000-ch-switch.patch + # END OF PATCH APPLICATIONS %endif @@ -1987,6 +1993,9 @@ fi # and build. %changelog +* Thu Oct 18 2012 Josh Boyer +- Apply patch to fix iwlwifi crash (rhbz 770484) + * Tue Oct 16 2012 Dave Jones 3.6.2-1 - Linux 3.6.2 From bdfb624a6708f75332cfc1fdb39fd0bfd4019f25 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 18 Oct 2012 08:33:53 -0400 Subject: [PATCH 442/487] Apply patch from Stanislaw Gruszka to fix mac80211 issue (rhbz 862168) --- kernel.spec | 7 ++++ mac80211_local_deauth_v3.6.patch | 66 ++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 mac80211_local_deauth_v3.6.patch diff --git a/kernel.spec b/kernel.spec index 2fbb11c53..0cdb400f2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -684,6 +684,9 @@ Patch21306: shlib_base_randomize.patch #rhbz 770484 Patch22071: iwlwifi-fix-6000-ch-switch.patch +#rhbz 862168 +Patch22073: mac80211_local_deauth_v3.6.patch + # Debug patches Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch @@ -1293,6 +1296,9 @@ ApplyPatch debug-808990.patch #rhbz 770484 ApplyPatch iwlwifi-fix-6000-ch-switch.patch +#rhbz 862168 +ApplyPatch mac80211_local_deauth_v3.6.patch + # END OF PATCH APPLICATIONS %endif @@ -1994,6 +2000,7 @@ fi %changelog * Thu Oct 18 2012 Josh Boyer +- Apply patch from Stanislaw Gruszka to fix mac80211 issue (rhbz 862168) - Apply patch to fix iwlwifi crash (rhbz 770484) * Tue Oct 16 2012 Dave Jones 3.6.2-1 diff --git a/mac80211_local_deauth_v3.6.patch b/mac80211_local_deauth_v3.6.patch new file mode 100644 index 000000000..3b634860f --- /dev/null +++ b/mac80211_local_deauth_v3.6.patch @@ -0,0 +1,66 @@ +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 3d254e1..f10553c 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -1217,6 +1217,7 @@ struct cfg80211_deauth_request { + const u8 *ie; + size_t ie_len; + u16 reason_code; ++ bool local_state_change; + }; + + /** +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index f76b833..08343c2 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -3457,6 +3457,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, + { + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + u8 frame_buf[DEAUTH_DISASSOC_LEN]; ++ bool tx = !req->local_state_change; + + mutex_lock(&ifmgd->mtx); + +@@ -3473,12 +3474,11 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, + if (ifmgd->associated && + ether_addr_equal(ifmgd->associated->bssid, req->bssid)) + ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, +- req->reason_code, true, frame_buf); ++ req->reason_code, tx, frame_buf); + else + ieee80211_send_deauth_disassoc(sdata, req->bssid, + IEEE80211_STYPE_DEAUTH, +- req->reason_code, true, +- frame_buf); ++ req->reason_code, tx, frame_buf); + mutex_unlock(&ifmgd->mtx); + + __cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); +diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c +index 1cdb1d5..0877efb 100644 +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -457,21 +457,11 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, + .reason_code = reason, + .ie = ie, + .ie_len = ie_len, ++ .local_state_change = local_state_change, + }; + + ASSERT_WDEV_LOCK(wdev); + +- if (local_state_change) { +- if (wdev->current_bss && +- ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { +- cfg80211_unhold_bss(wdev->current_bss); +- cfg80211_put_bss(&wdev->current_bss->pub); +- wdev->current_bss = NULL; +- } +- +- return 0; +- } +- + return rdev->ops->deauth(&rdev->wiphy, dev, &req); + } + From de79bf517f44e0d9a7c8dbdcaf1ff959da37d981 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 18 Oct 2012 08:52:16 -0400 Subject: [PATCH 443/487] Patch to have mac80211 connect with HT20 if HT40 is not allowed (rhbz 866013) --- kernel.spec | 7 ++ ...t-with-HT20-if-HT40-is-not-permitted.patch | 75 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch diff --git a/kernel.spec b/kernel.spec index 0cdb400f2..d43409ed8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -687,6 +687,9 @@ Patch22071: iwlwifi-fix-6000-ch-switch.patch #rhbz 862168 Patch22073: mac80211_local_deauth_v3.6.patch +#rhbz 866013 +Patch22074: mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch + # Debug patches Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch @@ -1299,6 +1302,9 @@ ApplyPatch iwlwifi-fix-6000-ch-switch.patch #rhbz 862168 ApplyPatch mac80211_local_deauth_v3.6.patch +#rhbz 866013 +ApplyPatch mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch + # END OF PATCH APPLICATIONS %endif @@ -2000,6 +2006,7 @@ fi %changelog * Thu Oct 18 2012 Josh Boyer +- Patch to have mac80211 connect with HT20 if HT40 is not allowed (rhbz 866013) - Apply patch from Stanislaw Gruszka to fix mac80211 issue (rhbz 862168) - Apply patch to fix iwlwifi crash (rhbz 770484) diff --git a/mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch b/mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch new file mode 100644 index 000000000..8c46db671 --- /dev/null +++ b/mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch @@ -0,0 +1,75 @@ +From 3a40414f826a8f1096d9b94c4a53ef91b25ba28d Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Mon, 1 Oct 2012 15:52:00 +0200 +Subject: [PATCH] mac80211: connect with HT20 if HT40 is not permitted + +Some changes to fix issues with HT40 APs in Korea +and follow-up changes to allow using HT40 even if +the local regulatory database disallows it caused +issues with iwlwifi (and could cause issues with +other devices); iwlwifi firmware would assert if +you tried to connect to an AP that has an invalid +configuration (e.g. using HT40- on channel 140.) + +Fix this, while avoiding the "Korean AP" issue by +disabling HT40 and advertising HT20 to the AP +when connecting. + +Cc: stable@vger.kernel.org [3.6] +Reported-by: Florian Reitmeir +Tested-by: Florian Reitmeir +Signed-off-by: Johannes Berg +--- + net/mac80211/mlme.c | 30 ++++++++++++++++++++---------- + 1 files changed, 20 insertions(+), 10 deletions(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index e510a33..1b7eed2 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -3099,22 +3099,32 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, + ht_cfreq, ht_oper->primary_chan, + cbss->channel->band); + ht_oper = NULL; ++ } else { ++ channel_type = NL80211_CHAN_HT20; + } + } + +- if (ht_oper) { +- channel_type = NL80211_CHAN_HT20; ++ if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { ++ /* ++ * cfg80211 already verified that the channel itself can ++ * be used, but it didn't check that we can do the right ++ * HT type, so do that here as well. If HT40 isn't allowed ++ * on this channel, disable 40 MHz operation. ++ */ + +- if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { +- switch (ht_oper->ht_param & +- IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { +- case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: ++ switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { ++ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: ++ if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS) ++ ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; ++ else + channel_type = NL80211_CHAN_HT40PLUS; +- break; +- case IEEE80211_HT_PARAM_CHA_SEC_BELOW: ++ break; ++ case IEEE80211_HT_PARAM_CHA_SEC_BELOW: ++ if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS) ++ ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; ++ else + channel_type = NL80211_CHAN_HT40MINUS; +- break; +- } ++ break; + } + } + +-- +1.7.6.5 + From 74226869f06ce5605d94234eda5429cba97d54bc Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 22 Oct 2012 08:32:00 -0400 Subject: [PATCH 444/487] Fix rt2x00 usb reset resume (rhbz 856863) --- kernel.spec | 9 ++++ rt2x00-usb-fix-reset-resume.patch | 70 +++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 rt2x00-usb-fix-reset-resume.patch diff --git a/kernel.spec b/kernel.spec index d43409ed8..a29163113 100644 --- a/kernel.spec +++ b/kernel.spec @@ -690,6 +690,9 @@ Patch22073: mac80211_local_deauth_v3.6.patch #rhbz 866013 Patch22074: mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch +#rhbz 856863 +Patch22075: rt2x00-usb-fix-reset-resume.patch + # Debug patches Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch @@ -1305,6 +1308,9 @@ ApplyPatch mac80211_local_deauth_v3.6.patch #rhbz 866013 ApplyPatch mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch +#rhbz 856863 +ApplyPatch rt2x00-usb-fix-reset-resume.patch + # END OF PATCH APPLICATIONS %endif @@ -2005,6 +2011,9 @@ fi # and build. %changelog +* Mon Oct 22 2012 Josh Boyer +- Fix rt2x00 usb reset resume (rhbz 856863) + * Thu Oct 18 2012 Josh Boyer - Patch to have mac80211 connect with HT20 if HT40 is not allowed (rhbz 866013) - Apply patch from Stanislaw Gruszka to fix mac80211 issue (rhbz 862168) diff --git a/rt2x00-usb-fix-reset-resume.patch b/rt2x00-usb-fix-reset-resume.patch new file mode 100644 index 000000000..07d2b4c0e --- /dev/null +++ b/rt2x00-usb-fix-reset-resume.patch @@ -0,0 +1,70 @@ +Patch fixes warnings like below happened on resume: + +WARNING: at net/mac80211/driver-ops.h:12 check_sdata_in_driver+0x32/0x34() + +Problem is that in __ieee80211_susped() we remove sdata (i.e wlan0 +interface) and then during resume we call usb_unbind_interface() -> +ieee80211_unregister_hw() with sdata removed. + +Patch fixes problem by adding .reset_resume calback, hence we do not +unbind usb device on resume. This callback can be the same as normal +.resume callback, sice we do all needed initalization during interface +start, which is performed on resume [ ieee80211_resume() -> +ieee80211_reconfig() -> rt2x00mac_start() -> rt2x00lib_start ]. + +Resolves: +https://bugzilla.kernel.org/show_bug.cgi?id=48041 + +Reported-by: David Herrmann +Reported-and-tested-by: Stephen Boyd +Cc: stable@vger.kernel.org +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/rt2x00/rt2500usb.c | 1 + + drivers/net/wireless/rt2x00/rt2800usb.c | 1 + + drivers/net/wireless/rt2x00/rt73usb.c | 1 + + 3 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c +index a12e84f..6b2e1e4 100644 +--- a/drivers/net/wireless/rt2x00/rt2500usb.c ++++ b/drivers/net/wireless/rt2x00/rt2500usb.c +@@ -1988,6 +1988,7 @@ static struct usb_driver rt2500usb_driver = { + .disconnect = rt2x00usb_disconnect, + .suspend = rt2x00usb_suspend, + .resume = rt2x00usb_resume, ++ .reset_resume = rt2x00usb_resume, + .disable_hub_initiated_lpm = 1, + }; + +diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c +index c9e9370..3b8fb5a 100644 +--- a/drivers/net/wireless/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/rt2x00/rt2800usb.c +@@ -1282,6 +1282,7 @@ static struct usb_driver rt2800usb_driver = { + .disconnect = rt2x00usb_disconnect, + .suspend = rt2x00usb_suspend, + .resume = rt2x00usb_resume, ++ .reset_resume = rt2x00usb_resume, + .disable_hub_initiated_lpm = 1, + }; + +diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c +index e5eb43b..24eec66 100644 +--- a/drivers/net/wireless/rt2x00/rt73usb.c ++++ b/drivers/net/wireless/rt2x00/rt73usb.c +@@ -2535,6 +2535,7 @@ static struct usb_driver rt73usb_driver = { + .disconnect = rt2x00usb_disconnect, + .suspend = rt2x00usb_suspend, + .resume = rt2x00usb_resume, ++ .reset_resume = rt2x00usb_resume, + .disable_hub_initiated_lpm = 1, + }; + +-- +1.7.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file From 70df2cf6485ae8fe5d88f865274316ec189ad4b4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 22 Oct 2012 09:47:05 -0400 Subject: [PATCH 445/487] CVE-2012-0957: uts: stack memory leak in UNAME26 (rhbz 862877 864824) --- ...tack-memory-content-leak-via-UNAME26.patch | 98 +++++++++++++++++++ kernel.spec | 7 ++ 2 files changed, 105 insertions(+) create mode 100644 fix-stack-memory-content-leak-via-UNAME26.patch diff --git a/fix-stack-memory-content-leak-via-UNAME26.patch b/fix-stack-memory-content-leak-via-UNAME26.patch new file mode 100644 index 000000000..5121ca06b --- /dev/null +++ b/fix-stack-memory-content-leak-via-UNAME26.patch @@ -0,0 +1,98 @@ +From 2702b1526c7278c4d65d78de209a465d4de2885e Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Fri, 19 Oct 2012 13:56:51 -0700 +Subject: [PATCH 1/2] kernel/sys.c: fix stack memory content leak via UNAME26 + +Calling uname() with the UNAME26 personality set allows a leak of kernel +stack contents. This fixes it by defensively calculating the length of +copy_to_user() call, making the len argument unsigned, and initializing +the stack buffer to zero (now technically unneeded, but hey, overkill). + +CVE-2012-0957 + +Reported-by: PaX Team +Signed-off-by: Kees Cook +Cc: Andi Kleen +Cc: PaX Team +Cc: Brad Spengler +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + kernel/sys.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/kernel/sys.c b/kernel/sys.c +index c5cb5b9..01865c6 100644 +--- a/kernel/sys.c ++++ b/kernel/sys.c +@@ -1265,15 +1265,16 @@ DECLARE_RWSEM(uts_sem); + * Work around broken programs that cannot handle "Linux 3.0". + * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40 + */ +-static int override_release(char __user *release, int len) ++static int override_release(char __user *release, size_t len) + { + int ret = 0; +- char buf[65]; + + if (current->personality & UNAME26) { +- char *rest = UTS_RELEASE; ++ const char *rest = UTS_RELEASE; ++ char buf[65] = { 0 }; + int ndots = 0; + unsigned v; ++ size_t copy; + + while (*rest) { + if (*rest == '.' && ++ndots >= 3) +@@ -1283,8 +1284,9 @@ static int override_release(char __user *release, int len) + rest++; + } + v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40; +- snprintf(buf, len, "2.6.%u%s", v, rest); +- ret = copy_to_user(release, buf, len); ++ copy = min(sizeof(buf), max_t(size_t, 1, len)); ++ copy = scnprintf(buf, copy, "2.6.%u%s", v, rest); ++ ret = copy_to_user(release, buf, copy + 1); + } + return ret; + } +-- +1.7.12.1 + + +From 31fd84b95eb211d5db460a1dda85e004800a7b52 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Fri, 19 Oct 2012 18:45:53 -0700 +Subject: [PATCH 2/2] use clamp_t in UNAME26 fix + +The min/max call needed to have explicit types on some architectures +(e.g. mn10300). Use clamp_t instead to avoid the warning: + + kernel/sys.c: In function 'override_release': + kernel/sys.c:1287:10: warning: comparison of distinct pointer types lacks a cast [enabled by default] + +Reported-by: Fengguang Wu +Signed-off-by: Kees Cook +Signed-off-by: Linus Torvalds +--- + kernel/sys.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/sys.c b/kernel/sys.c +index 01865c6..e6e0ece 100644 +--- a/kernel/sys.c ++++ b/kernel/sys.c +@@ -1284,7 +1284,7 @@ static int override_release(char __user *release, size_t len) + rest++; + } + v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40; +- copy = min(sizeof(buf), max_t(size_t, 1, len)); ++ copy = clamp_t(size_t, len, 1, sizeof(buf)); + copy = scnprintf(buf, copy, "2.6.%u%s", v, rest); + ret = copy_to_user(release, buf, copy + 1); + } +-- +1.7.12.1 + diff --git a/kernel.spec b/kernel.spec index a29163113..86b0bde0f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -693,6 +693,9 @@ Patch22074: mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch #rhbz 856863 Patch22075: rt2x00-usb-fix-reset-resume.patch +#rhbz 862877 864824 CVE-2012-0957 +Patch22076: fix-stack-memory-content-leak-via-UNAME26.patch + # Debug patches Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch @@ -1311,6 +1314,9 @@ ApplyPatch mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch #rhbz 856863 ApplyPatch rt2x00-usb-fix-reset-resume.patch +#rhbz 862877 864824 CVE-2012-0957 +ApplyPatch fix-stack-memory-content-leak-via-UNAME26.patch + # END OF PATCH APPLICATIONS %endif @@ -2012,6 +2018,7 @@ fi %changelog * Mon Oct 22 2012 Josh Boyer +- CVE-2012-0957: uts: stack memory leak in UNAME26 (rhbz 862877 864824) - Fix rt2x00 usb reset resume (rhbz 856863) * Thu Oct 18 2012 Josh Boyer From d080f2b085215aca19ca72367d89bfd4effd0eca Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 22 Oct 2012 15:46:47 -0400 Subject: [PATCH 446/487] Add patch to fix CIFS oops from Jeff Layton (rhbz 867344) --- ...ifs_lookup-on-hashed-negative-dentry.patch | 21 +++++++++++++++++++ kernel.spec | 7 +++++++ 2 files changed, 28 insertions(+) create mode 100644 dont-call-cifs_lookup-on-hashed-negative-dentry.patch diff --git a/dont-call-cifs_lookup-on-hashed-negative-dentry.patch b/dont-call-cifs_lookup-on-hashed-negative-dentry.patch new file mode 100644 index 000000000..88b35e2f8 --- /dev/null +++ b/dont-call-cifs_lookup-on-hashed-negative-dentry.patch @@ -0,0 +1,21 @@ +@@ -, +, @@ + negative dentry + BUG_ON(!d_unhashed(entry)); + fs/cifs/dir.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) +--- a/fs/cifs/dir.c ++++ a/fs/cifs/dir.c +@@ -398,7 +398,12 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, + * in network traffic in the other paths. + */ + if (!(oflags & O_CREAT)) { +- struct dentry *res = cifs_lookup(inode, direntry, 0); ++ struct dentry *res; ++ ++ if (!direntry->d_inode) ++ return -ENOENT; ++ ++ res = cifs_lookup(inode, direntry, 0); + if (IS_ERR(res)) + return PTR_ERR(res); + diff --git a/kernel.spec b/kernel.spec index 86b0bde0f..6c25a4721 100644 --- a/kernel.spec +++ b/kernel.spec @@ -696,6 +696,9 @@ Patch22075: rt2x00-usb-fix-reset-resume.patch #rhbz 862877 864824 CVE-2012-0957 Patch22076: fix-stack-memory-content-leak-via-UNAME26.patch +#rhbz 867344 +Patch22077: dont-call-cifs_lookup-on-hashed-negative-dentry.patch + # Debug patches Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch @@ -1317,6 +1320,9 @@ ApplyPatch rt2x00-usb-fix-reset-resume.patch #rhbz 862877 864824 CVE-2012-0957 ApplyPatch fix-stack-memory-content-leak-via-UNAME26.patch +#rhbz 867344 +ApplyPatch dont-call-cifs_lookup-on-hashed-negative-dentry.patch + # END OF PATCH APPLICATIONS %endif @@ -2018,6 +2024,7 @@ fi %changelog * Mon Oct 22 2012 Josh Boyer +- Add patch to fix CIFS oops from Jeff Layton (rhbz 867344) - CVE-2012-0957: uts: stack memory leak in UNAME26 (rhbz 862877 864824) - Fix rt2x00 usb reset resume (rhbz 856863) From bf00e6862766bf0ff0d1acbe9231d088e0256654 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 24 Oct 2012 08:23:01 -0400 Subject: [PATCH 447/487] Add patch to fix corrupted text with i915 (rhbz 852210) --- ...-relocations-if-the-object-is-in-the.patch | 33 +++++++++++++++++++ kernel.spec | 9 +++++ 2 files changed, 42 insertions(+) create mode 100644 drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch diff --git a/drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch b/drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch new file mode 100644 index 000000000..0e282bf04 --- /dev/null +++ b/drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch @@ -0,0 +1,33 @@ +From 504c7267a1e84b157cbd7e9c1b805e1bc0c2c846 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Thu, 23 Aug 2012 13:12:52 +0100 +Subject: [PATCH] drm/i915: Use cpu relocations if the object is in the GTT + but not mappable + +This prevents the case of unbinding the object in order to process the +relocations through the GTT and then rebinding it only to then proceed +to use cpu relocations as the object is now in the CPU write domain. By +choosing to use cpu relocations up front, we can therefore avoid the +rebind penalty. + +Signed-off-by: Chris Wilson +Signed-off-by: Daniel Vetter +--- + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +index f7346d8..dc87563 100644 +--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c ++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +@@ -95,6 +95,7 @@ eb_destroy(struct eb_objects *eb) + static inline int use_cpu_reloc(struct drm_i915_gem_object *obj) + { + return (obj->base.write_domain == I915_GEM_DOMAIN_CPU || ++ !obj->map_and_fenceable || + obj->cache_level != I915_CACHE_NONE); + } + +-- +1.7.12.1 + diff --git a/kernel.spec b/kernel.spec index 6c25a4721..51f7da64f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -699,6 +699,9 @@ Patch22076: fix-stack-memory-content-leak-via-UNAME26.patch #rhbz 867344 Patch22077: dont-call-cifs_lookup-on-hashed-negative-dentry.patch +#rhbz 852210 +Patch22078: drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch + # Debug patches Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch @@ -1323,6 +1326,9 @@ ApplyPatch fix-stack-memory-content-leak-via-UNAME26.patch #rhbz 867344 ApplyPatch dont-call-cifs_lookup-on-hashed-negative-dentry.patch +#rhbz 852210 +ApplyPatch drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch + # END OF PATCH APPLICATIONS %endif @@ -2023,6 +2029,9 @@ fi # and build. %changelog +* Wed Oct 24 2012 Josh Boyer +- Add patch to fix corrupted text with i915 (rhbz 852210) + * Mon Oct 22 2012 Josh Boyer - Add patch to fix CIFS oops from Jeff Layton (rhbz 867344) - CVE-2012-0957: uts: stack memory leak in UNAME26 (rhbz 862877 864824) From fe92d94d16bdceb929a001394b6355f571385a78 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 24 Oct 2012 14:41:23 -0400 Subject: [PATCH 448/487] Remove patch added for rhbz 856863 --- kernel.spec | 7 +--- rt2x00-usb-fix-reset-resume.patch | 70 ------------------------------- 2 files changed, 1 insertion(+), 76 deletions(-) delete mode 100644 rt2x00-usb-fix-reset-resume.patch diff --git a/kernel.spec b/kernel.spec index 51f7da64f..15f5b3d91 100644 --- a/kernel.spec +++ b/kernel.spec @@ -690,9 +690,6 @@ Patch22073: mac80211_local_deauth_v3.6.patch #rhbz 866013 Patch22074: mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch -#rhbz 856863 -Patch22075: rt2x00-usb-fix-reset-resume.patch - #rhbz 862877 864824 CVE-2012-0957 Patch22076: fix-stack-memory-content-leak-via-UNAME26.patch @@ -1317,9 +1314,6 @@ ApplyPatch mac80211_local_deauth_v3.6.patch #rhbz 866013 ApplyPatch mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch -#rhbz 856863 -ApplyPatch rt2x00-usb-fix-reset-resume.patch - #rhbz 862877 864824 CVE-2012-0957 ApplyPatch fix-stack-memory-content-leak-via-UNAME26.patch @@ -2030,6 +2024,7 @@ fi %changelog * Wed Oct 24 2012 Josh Boyer +- Remove patch added for rhbz 856863 - Add patch to fix corrupted text with i915 (rhbz 852210) * Mon Oct 22 2012 Josh Boyer diff --git a/rt2x00-usb-fix-reset-resume.patch b/rt2x00-usb-fix-reset-resume.patch deleted file mode 100644 index 07d2b4c0e..000000000 --- a/rt2x00-usb-fix-reset-resume.patch +++ /dev/null @@ -1,70 +0,0 @@ -Patch fixes warnings like below happened on resume: - -WARNING: at net/mac80211/driver-ops.h:12 check_sdata_in_driver+0x32/0x34() - -Problem is that in __ieee80211_susped() we remove sdata (i.e wlan0 -interface) and then during resume we call usb_unbind_interface() -> -ieee80211_unregister_hw() with sdata removed. - -Patch fixes problem by adding .reset_resume calback, hence we do not -unbind usb device on resume. This callback can be the same as normal -.resume callback, sice we do all needed initalization during interface -start, which is performed on resume [ ieee80211_resume() -> -ieee80211_reconfig() -> rt2x00mac_start() -> rt2x00lib_start ]. - -Resolves: -https://bugzilla.kernel.org/show_bug.cgi?id=48041 - -Reported-by: David Herrmann -Reported-and-tested-by: Stephen Boyd -Cc: stable@vger.kernel.org -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/rt2x00/rt2500usb.c | 1 + - drivers/net/wireless/rt2x00/rt2800usb.c | 1 + - drivers/net/wireless/rt2x00/rt73usb.c | 1 + - 3 files changed, 3 insertions(+), 0 deletions(-) - -diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c -index a12e84f..6b2e1e4 100644 ---- a/drivers/net/wireless/rt2x00/rt2500usb.c -+++ b/drivers/net/wireless/rt2x00/rt2500usb.c -@@ -1988,6 +1988,7 @@ static struct usb_driver rt2500usb_driver = { - .disconnect = rt2x00usb_disconnect, - .suspend = rt2x00usb_suspend, - .resume = rt2x00usb_resume, -+ .reset_resume = rt2x00usb_resume, - .disable_hub_initiated_lpm = 1, - }; - -diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c -index c9e9370..3b8fb5a 100644 ---- a/drivers/net/wireless/rt2x00/rt2800usb.c -+++ b/drivers/net/wireless/rt2x00/rt2800usb.c -@@ -1282,6 +1282,7 @@ static struct usb_driver rt2800usb_driver = { - .disconnect = rt2x00usb_disconnect, - .suspend = rt2x00usb_suspend, - .resume = rt2x00usb_resume, -+ .reset_resume = rt2x00usb_resume, - .disable_hub_initiated_lpm = 1, - }; - -diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c -index e5eb43b..24eec66 100644 ---- a/drivers/net/wireless/rt2x00/rt73usb.c -+++ b/drivers/net/wireless/rt2x00/rt73usb.c -@@ -2535,6 +2535,7 @@ static struct usb_driver rt73usb_driver = { - .disconnect = rt2x00usb_disconnect, - .suspend = rt2x00usb_suspend, - .resume = rt2x00usb_resume, -+ .reset_resume = rt2x00usb_resume, - .disable_hub_initiated_lpm = 1, - }; - --- -1.7.1 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file From 029dfd43520f3d0e0e39dd07fc3fa2364ea01243 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 25 Oct 2012 13:14:53 -0500 Subject: [PATCH 449/487] CVE-2012-4508: ext4: AIO vs fallocate stale data exposure (rhbz 869904 869909) --- 0001-ext4-ext4_inode_info-diet.patch | 121 ++++ ...io_unwritten-a-more-appropriate-name.patch | 97 ++++ 0003-ext4-fix-unwritten-counter-leakage.patch | 112 ++++ 0004-ext4-completed_io-locking-cleanup.patch | 520 ++++++++++++++++++ ...io-nonlocked-reads-with-defrag-worke.patch | 144 +++++ ...ize-unlocked-dio-reads-with-truncate.patch | 65 +++ ...runcate-due-to-nonlocked-dio-readers.patch | 41 ++ ...-truncate-with-owerwrite-DIO-workers.patch | 61 ++ ...nch_hole-should-wait-for-DIO-writers.patch | 125 +++++ ...ext_remove_space-for-punch_hole-case.patch | 60 ++ ...t4_flush_completed_IO-wait-semantics.patch | 176 ++++++ ...allocate-with-ext4_convert_unwritten.patch | 46 ++ ...ion-protection-for-ext4_convert_unwr.patch | 153 ++++++ kernel.spec | 33 ++ 14 files changed, 1754 insertions(+) create mode 100644 0001-ext4-ext4_inode_info-diet.patch create mode 100644 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch create mode 100644 0003-ext4-fix-unwritten-counter-leakage.patch create mode 100644 0004-ext4-completed_io-locking-cleanup.patch create mode 100644 0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch create mode 100644 0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch create mode 100644 0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch create mode 100644 0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch create mode 100644 0009-ext4-punch_hole-should-wait-for-DIO-writers.patch create mode 100644 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch create mode 100644 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch create mode 100644 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch create mode 100644 0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch diff --git a/0001-ext4-ext4_inode_info-diet.patch b/0001-ext4-ext4_inode_info-diet.patch new file mode 100644 index 000000000..c7858ecc6 --- /dev/null +++ b/0001-ext4-ext4_inode_info-diet.patch @@ -0,0 +1,121 @@ +From 50b61634cf8d09f9ef334919b859735d381cbe39 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Fri, 28 Sep 2012 23:21:09 -0400 +Subject: [PATCH 01/13] ext4: ext4_inode_info diet + +Generic inode has unused i_private pointer which may be used as cur_aio_dio +storage. + +TODO: If cur_aio_dio will be passed as an argument to get_block_t this allow + to have concurent AIO_DIO requests. + +Reviewed-by: Zheng Liu +Reviewed-by: Jan Kara +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit f45ee3a1ea438af96e4fd2c0b16d195e67ef235f) +--- + fs/ext4/ext4.h | 12 ++++++++++-- + fs/ext4/extents.c | 4 ++-- + fs/ext4/inode.c | 6 +++--- + fs/ext4/super.c | 1 - + 4 files changed, 15 insertions(+), 8 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index c3411d4..80afc8f 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -912,8 +912,6 @@ struct ext4_inode_info { + struct list_head i_completed_io_list; + spinlock_t i_completed_io_lock; + atomic_t i_ioend_count; /* Number of outstanding io_end structs */ +- /* current io_end structure for async DIO write*/ +- ext4_io_end_t *cur_aio_dio; + atomic_t i_aiodio_unwritten; /* Nr. of inflight conversions pending */ + + spinlock_t i_block_reservation_lock; +@@ -1332,6 +1330,16 @@ static inline void ext4_set_io_unwritten_flag(struct inode *inode, + } + } + ++static inline ext4_io_end_t *ext4_inode_aio(struct inode *inode) ++{ ++ return inode->i_private; ++} ++ ++static inline void ext4_inode_aio_set(struct inode *inode, ext4_io_end_t *io) ++{ ++ inode->i_private = io; ++} ++ + /* + * Inode dynamic state flags + */ +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index aabbb3f..51fbef1 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -3600,7 +3600,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, + { + int ret = 0; + int err = 0; +- ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio; ++ ext4_io_end_t *io = ext4_inode_aio(inode); + + ext_debug("ext4_ext_handle_uninitialized_extents: inode %lu, logical " + "block %llu, max_blocks %u, flags %x, allocated %u\n", +@@ -3858,7 +3858,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, + unsigned int allocated = 0, offset = 0; + unsigned int allocated_clusters = 0; + struct ext4_allocation_request ar; +- ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio; ++ ext4_io_end_t *io = ext4_inode_aio(inode); + ext4_lblk_t cluster_offset; + + ext_debug("blocks %u/%u requested for inode %lu\n", +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index dff171c..acadd2b 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3054,7 +3054,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, + * hook to the iocb. + */ + iocb->private = NULL; +- EXT4_I(inode)->cur_aio_dio = NULL; ++ ext4_inode_aio_set(inode, NULL); + if (!is_sync_kiocb(iocb)) { + ext4_io_end_t *io_end = + ext4_init_io_end(inode, GFP_NOFS); +@@ -3071,7 +3071,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, + * is a unwritten extents needs to be converted + * when IO is completed. + */ +- EXT4_I(inode)->cur_aio_dio = iocb->private; ++ ext4_inode_aio_set(inode, io_end); + } + + if (overwrite) +@@ -3091,7 +3091,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, + NULL, + DIO_LOCKING); + if (iocb->private) +- EXT4_I(inode)->cur_aio_dio = NULL; ++ ext4_inode_aio_set(inode, NULL); + /* + * The io_end structure takes a reference to the inode, + * that structure needs to be destroyed and the +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index c6e0cb3..270e58f 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -956,7 +956,6 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) + ei->jinode = NULL; + INIT_LIST_HEAD(&ei->i_completed_io_list); + spin_lock_init(&ei->i_completed_io_lock); +- ei->cur_aio_dio = NULL; + ei->i_sync_tid = 0; + ei->i_datasync_tid = 0; + atomic_set(&ei->i_ioend_count, 0); +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch b/0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch new file mode 100644 index 000000000..cfd13f386 --- /dev/null +++ b/0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch @@ -0,0 +1,97 @@ +From 027d1aa67e32c2c80851105c6d962f3db46eb476 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Fri, 28 Sep 2012 23:24:52 -0400 +Subject: [PATCH 02/13] ext4: give i_aiodio_unwritten a more appropriate name + +AIO/DIO prefix is wrong because it account unwritten extents which +also may be scheduled from buffered write endio + +Reviewed-by: Jan Kara +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit e27f41e1b789e60e7d8cc9c81fd93ca49ef31f13) +--- + fs/ext4/ext4.h | 4 ++-- + fs/ext4/file.c | 6 +++--- + fs/ext4/page-io.c | 2 +- + fs/ext4/super.c | 2 +- + 4 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 80afc8f..28dfd9b 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -912,7 +912,7 @@ struct ext4_inode_info { + struct list_head i_completed_io_list; + spinlock_t i_completed_io_lock; + atomic_t i_ioend_count; /* Number of outstanding io_end structs */ +- atomic_t i_aiodio_unwritten; /* Nr. of inflight conversions pending */ ++ atomic_t i_unwritten; /* Nr. of inflight conversions pending */ + + spinlock_t i_block_reservation_lock; + +@@ -1326,7 +1326,7 @@ static inline void ext4_set_io_unwritten_flag(struct inode *inode, + { + if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { + io_end->flag |= EXT4_IO_END_UNWRITTEN; +- atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten); ++ atomic_inc(&EXT4_I(inode)->i_unwritten); + } + } + +diff --git a/fs/ext4/file.c b/fs/ext4/file.c +index 3b0e3bd..39335bd 100644 +--- a/fs/ext4/file.c ++++ b/fs/ext4/file.c +@@ -55,11 +55,11 @@ static int ext4_release_file(struct inode *inode, struct file *filp) + return 0; + } + +-static void ext4_aiodio_wait(struct inode *inode) ++static void ext4_unwritten_wait(struct inode *inode) + { + wait_queue_head_t *wq = ext4_ioend_wq(inode); + +- wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_aiodio_unwritten) == 0)); ++ wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_unwritten) == 0)); + } + + /* +@@ -116,7 +116,7 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov, + "performance will be poor.", + inode->i_ino, current->comm); + mutex_lock(ext4_aio_mutex(inode)); +- ext4_aiodio_wait(inode); ++ ext4_unwritten_wait(inode); + } + + BUG_ON(iocb->ki_pos != pos); +diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c +index dcdeef1..de77e31 100644 +--- a/fs/ext4/page-io.c ++++ b/fs/ext4/page-io.c +@@ -113,7 +113,7 @@ int ext4_end_io_nolock(ext4_io_end_t *io) + if (io->flag & EXT4_IO_END_DIRECT) + inode_dio_done(inode); + /* Wake up anyone waiting on unwritten extent conversion */ +- if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten)) ++ if (atomic_dec_and_test(&EXT4_I(inode)->i_unwritten)) + wake_up_all(ext4_ioend_wq(io->inode)); + return ret; + } +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 270e58f..1b6b425 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -959,7 +959,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) + ei->i_sync_tid = 0; + ei->i_datasync_tid = 0; + atomic_set(&ei->i_ioend_count, 0); +- atomic_set(&ei->i_aiodio_unwritten, 0); ++ atomic_set(&ei->i_unwritten, 0); + + return &ei->vfs_inode; + } +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0003-ext4-fix-unwritten-counter-leakage.patch b/0003-ext4-fix-unwritten-counter-leakage.patch new file mode 100644 index 000000000..2f1d0d813 --- /dev/null +++ b/0003-ext4-fix-unwritten-counter-leakage.patch @@ -0,0 +1,112 @@ +From 6a0e905bb7320571ed5fdd2d5efa3d642630b4f7 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Fri, 28 Sep 2012 23:36:25 -0400 +Subject: [PATCH 03/13] ext4: fix unwritten counter leakage + +ext4_set_io_unwritten_flag() will increment i_unwritten counter, so +once we mark end_io with EXT4_END_IO_UNWRITTEN we have to revert it back +on error path. + + - add missed error checks to prevent counter leakage + - ext4_end_io_nolock() will clear EXT4_END_IO_UNWRITTEN flag to signal + that conversion finished. + - add BUG_ON to ext4_free_end_io() to prevent similar leakage in future. + +Visible effect of this bug is that unaligned aio_stress may deadlock + +Reviewed-by: Jan Kara +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 82e54229118785badffb4ef5ba4803df25fe007f) +--- + fs/ext4/extents.c | 21 ++++++++++++++------- + fs/ext4/page-io.c | 6 +++++- + 2 files changed, 19 insertions(+), 8 deletions(-) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 51fbef1..e04eb4f 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -3615,6 +3615,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, + if ((flags & EXT4_GET_BLOCKS_PRE_IO)) { + ret = ext4_split_unwritten_extents(handle, inode, map, + path, flags); ++ if (ret <= 0) ++ goto out; + /* + * Flag the inode(non aio case) or end_io struct (aio case) + * that this IO needs to conversion to written when IO is +@@ -3860,6 +3862,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, + struct ext4_allocation_request ar; + ext4_io_end_t *io = ext4_inode_aio(inode); + ext4_lblk_t cluster_offset; ++ int set_unwritten = 0; + + ext_debug("blocks %u/%u requested for inode %lu\n", + map->m_lblk, map->m_len, inode->i_ino); +@@ -4082,13 +4085,8 @@ got_allocated_blocks: + * For non asycn direct IO case, flag the inode state + * that we need to perform conversion when IO is done. + */ +- if ((flags & EXT4_GET_BLOCKS_PRE_IO)) { +- if (io) +- ext4_set_io_unwritten_flag(inode, io); +- else +- ext4_set_inode_state(inode, +- EXT4_STATE_DIO_UNWRITTEN); +- } ++ if ((flags & EXT4_GET_BLOCKS_PRE_IO)) ++ set_unwritten = 1; + if (ext4_should_dioread_nolock(inode)) + map->m_flags |= EXT4_MAP_UNINIT; + } +@@ -4100,6 +4098,15 @@ got_allocated_blocks: + if (!err) + err = ext4_ext_insert_extent(handle, inode, path, + &newex, flags); ++ ++ if (!err && set_unwritten) { ++ if (io) ++ ext4_set_io_unwritten_flag(inode, io); ++ else ++ ext4_set_inode_state(inode, ++ EXT4_STATE_DIO_UNWRITTEN); ++ } ++ + if (err && free_on_err) { + int fb_flags = flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE ? + EXT4_FREE_BLOCKS_NO_QUOT_UPDATE : 0; +diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c +index de77e31..9970022 100644 +--- a/fs/ext4/page-io.c ++++ b/fs/ext4/page-io.c +@@ -71,6 +71,8 @@ void ext4_free_io_end(ext4_io_end_t *io) + int i; + + BUG_ON(!io); ++ BUG_ON(io->flag & EXT4_IO_END_UNWRITTEN); ++ + if (io->page) + put_page(io->page); + for (i = 0; i < io->num_io_pages; i++) +@@ -94,6 +96,8 @@ int ext4_end_io_nolock(ext4_io_end_t *io) + ssize_t size = io->size; + int ret = 0; + ++ BUG_ON(!(io->flag & EXT4_IO_END_UNWRITTEN)); ++ + ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p," + "list->prev 0x%p\n", + io, inode->i_ino, io->list.next, io->list.prev); +@@ -106,7 +110,7 @@ int ext4_end_io_nolock(ext4_io_end_t *io) + "(inode %lu, offset %llu, size %zd, error %d)", + inode->i_ino, offset, size, ret); + } +- ++ io->flag &= ~EXT4_IO_END_UNWRITTEN; + if (io->iocb) + aio_complete(io->iocb, io->result, 0); + +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0004-ext4-completed_io-locking-cleanup.patch b/0004-ext4-completed_io-locking-cleanup.patch new file mode 100644 index 000000000..a358a7952 --- /dev/null +++ b/0004-ext4-completed_io-locking-cleanup.patch @@ -0,0 +1,520 @@ +From e23394806df0768ed2dac87484590d2f3a730d55 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Sat, 29 Sep 2012 00:14:55 -0400 +Subject: [PATCH 04/13] ext4: completed_io locking cleanup + +Current unwritten extent conversion state-machine is very fuzzy. +- For unknown reason it performs conversion under i_mutex. What for? + My diagnosis: + We already protect extent tree with i_data_sem, truncate and punch_hole + should wait for DIO, so the only data we have to protect is end_io->flags + modification, but only flush_completed_IO and end_io_work modified this + flags and we can serialize them via i_completed_io_lock. + + Currently all these games with mutex_trylock result in the following deadlock + truncate: kworker: + ext4_setattr ext4_end_io_work + mutex_lock(i_mutex) + inode_dio_wait(inode) ->BLOCK + DEADLOCK<- mutex_trylock() + inode_dio_done() + #TEST_CASE1_BEGIN + MNT=/mnt_scrach + unlink $MNT/file + fallocate -l $((1024*1024*1024)) $MNT/file + aio-stress -I 100000 -O -s 100m -n -t 1 -c 10 -o 2 -o 3 $MNT/file + sleep 2 + truncate -s 0 $MNT/file + #TEST_CASE1_END + +Or use 286's xfstests https://github.com/dmonakhov/xfstests/blob/devel/286 + +This patch makes state machine simple and clean: + +(1) xxx_end_io schedule final extent conversion simply by calling + ext4_add_complete_io(), which append it to ei->i_completed_io_list + NOTE1: because of (2A) work should be queued only if + ->i_completed_io_list was empty, otherwise the work is scheduled already. + +(2) ext4_flush_completed_IO is responsible for handling all pending + end_io from ei->i_completed_io_list + Flushing sequence consists of following stages: + A) LOCKED: Atomically drain completed_io_list to local_list + B) Perform extents conversion + C) LOCKED: move converted io's to to_free list for final deletion + This logic depends on context which we was called from. + D) Final end_io context destruction + NOTE1: i_mutex is no longer required because end_io->flags modification + is protected by ei->ext4_complete_io_lock + +Full list of changes: +- Move all completion end_io related routines to page-io.c in order to improve + logic locality +- Move open coded logic from various xx_end_xx routines to ext4_add_complete_io() +- remove EXT4_IO_END_FSYNC +- Improve SMP scalability by removing useless i_mutex which does not + protect io->flags anymore. +- Reduce lock contention on i_completed_io_lock by optimizing list walk. +- Rename ext4_end_io_nolock to end4_end_io and make it static +- Check flush completion status to ext4_ext_punch_hole(). Because it is + not good idea to punch blocks from corrupted inode. + +Changes since V3 (in request to Jan's comments): + Fall back to active flush_completed_IO() approach in order to prevent + performance issues with nolocked DIO reads. +Changes since V2: + Fix use-after-free caused by race truncate vs end_io_work + +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 28a535f9a0df060569dcc786e5bc2e1de43d7dc7) +--- + fs/ext4/ext4.h | 3 +- + fs/ext4/extents.c | 4 +- + fs/ext4/fsync.c | 81 ------------------------- + fs/ext4/indirect.c | 6 +- + fs/ext4/inode.c | 25 +------- + fs/ext4/page-io.c | 171 +++++++++++++++++++++++++++++++++++------------------ + 6 files changed, 121 insertions(+), 169 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 28dfd9b..7687d15 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -186,7 +186,6 @@ struct mpage_da_data { + #define EXT4_IO_END_ERROR 0x0002 + #define EXT4_IO_END_QUEUED 0x0004 + #define EXT4_IO_END_DIRECT 0x0008 +-#define EXT4_IO_END_IN_FSYNC 0x0010 + + struct ext4_io_page { + struct page *p_page; +@@ -2408,11 +2407,11 @@ extern int ext4_move_extents(struct file *o_filp, struct file *d_filp, + + /* page-io.c */ + extern int __init ext4_init_pageio(void); ++extern void ext4_add_complete_io(ext4_io_end_t *io_end); + extern void ext4_exit_pageio(void); + extern void ext4_ioend_wait(struct inode *); + extern void ext4_free_io_end(ext4_io_end_t *io); + extern ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags); +-extern int ext4_end_io_nolock(ext4_io_end_t *io); + extern void ext4_io_submit(struct ext4_io_submit *io); + extern int ext4_bio_write_page(struct ext4_io_submit *io, + struct page *page, +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index e04eb4f..1fbf2ff 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4815,7 +4815,9 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) + } + + /* finish any pending end_io work */ +- ext4_flush_completed_IO(inode); ++ err = ext4_flush_completed_IO(inode); ++ if (err) ++ return err; + + credits = ext4_writepage_trans_blocks(inode); + handle = ext4_journal_start(inode, credits); +diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c +index 2a1dcea..520b058 100644 +--- a/fs/ext4/fsync.c ++++ b/fs/ext4/fsync.c +@@ -34,87 +34,6 @@ + + #include + +-static void dump_completed_IO(struct inode * inode) +-{ +-#ifdef EXT4FS_DEBUG +- struct list_head *cur, *before, *after; +- ext4_io_end_t *io, *io0, *io1; +- unsigned long flags; +- +- if (list_empty(&EXT4_I(inode)->i_completed_io_list)){ +- ext4_debug("inode %lu completed_io list is empty\n", inode->i_ino); +- return; +- } +- +- ext4_debug("Dump inode %lu completed_io list \n", inode->i_ino); +- spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); +- list_for_each_entry(io, &EXT4_I(inode)->i_completed_io_list, list){ +- cur = &io->list; +- before = cur->prev; +- io0 = container_of(before, ext4_io_end_t, list); +- after = cur->next; +- io1 = container_of(after, ext4_io_end_t, list); +- +- ext4_debug("io 0x%p from inode %lu,prev 0x%p,next 0x%p\n", +- io, inode->i_ino, io0, io1); +- } +- spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags); +-#endif +-} +- +-/* +- * This function is called from ext4_sync_file(). +- * +- * When IO is completed, the work to convert unwritten extents to +- * written is queued on workqueue but may not get immediately +- * scheduled. When fsync is called, we need to ensure the +- * conversion is complete before fsync returns. +- * The inode keeps track of a list of pending/completed IO that +- * might needs to do the conversion. This function walks through +- * the list and convert the related unwritten extents for completed IO +- * to written. +- * The function return the number of pending IOs on success. +- */ +-int ext4_flush_completed_IO(struct inode *inode) +-{ +- ext4_io_end_t *io; +- struct ext4_inode_info *ei = EXT4_I(inode); +- unsigned long flags; +- int ret = 0; +- int ret2 = 0; +- +- dump_completed_IO(inode); +- spin_lock_irqsave(&ei->i_completed_io_lock, flags); +- while (!list_empty(&ei->i_completed_io_list)){ +- io = list_entry(ei->i_completed_io_list.next, +- ext4_io_end_t, list); +- list_del_init(&io->list); +- io->flag |= EXT4_IO_END_IN_FSYNC; +- /* +- * Calling ext4_end_io_nolock() to convert completed +- * IO to written. +- * +- * When ext4_sync_file() is called, run_queue() may already +- * about to flush the work corresponding to this io structure. +- * It will be upset if it founds the io structure related +- * to the work-to-be schedule is freed. +- * +- * Thus we need to keep the io structure still valid here after +- * conversion finished. The io structure has a flag to +- * avoid double converting from both fsync and background work +- * queue work. +- */ +- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); +- ret = ext4_end_io_nolock(io); +- if (ret < 0) +- ret2 = ret; +- spin_lock_irqsave(&ei->i_completed_io_lock, flags); +- io->flag &= ~EXT4_IO_END_IN_FSYNC; +- } +- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); +- return (ret2 < 0) ? ret2 : 0; +-} +- + /* + * If we're not journaling and this is a just-created file, we have to + * sync our parent directory (if it was freshly created) since +diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c +index 830e1b2..61f13e5 100644 +--- a/fs/ext4/indirect.c ++++ b/fs/ext4/indirect.c +@@ -807,11 +807,9 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, + + retry: + if (rw == READ && ext4_should_dioread_nolock(inode)) { +- if (unlikely(!list_empty(&ei->i_completed_io_list))) { +- mutex_lock(&inode->i_mutex); ++ if (unlikely(!list_empty(&ei->i_completed_io_list))) + ext4_flush_completed_IO(inode); +- mutex_unlock(&inode->i_mutex); +- } ++ + ret = __blockdev_direct_IO(rw, iocb, inode, + inode->i_sb->s_bdev, iov, + offset, nr_segs, +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index acadd2b..dd3fd23 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -2879,9 +2879,6 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, + { + struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; + ext4_io_end_t *io_end = iocb->private; +- struct workqueue_struct *wq; +- unsigned long flags; +- struct ext4_inode_info *ei; + + /* if not async direct IO or dio with 0 bytes write, just return */ + if (!io_end || !size) +@@ -2910,24 +2907,14 @@ out: + io_end->iocb = iocb; + io_end->result = ret; + } +- wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq; +- +- /* Add the io_end to per-inode completed aio dio list*/ +- ei = EXT4_I(io_end->inode); +- spin_lock_irqsave(&ei->i_completed_io_lock, flags); +- list_add_tail(&io_end->list, &ei->i_completed_io_list); +- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); + +- /* queue the work to convert unwritten extents to written */ +- queue_work(wq, &io_end->work); ++ ext4_add_complete_io(io_end); + } + + static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate) + { + ext4_io_end_t *io_end = bh->b_private; +- struct workqueue_struct *wq; + struct inode *inode; +- unsigned long flags; + + if (!test_clear_buffer_uninit(bh) || !io_end) + goto out; +@@ -2946,15 +2933,7 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate) + */ + inode = io_end->inode; + ext4_set_io_unwritten_flag(inode, io_end); +- +- /* Add the io_end to per-inode completed io list*/ +- spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); +- list_add_tail(&io_end->list, &EXT4_I(inode)->i_completed_io_list); +- spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags); +- +- wq = EXT4_SB(inode->i_sb)->dio_unwritten_wq; +- /* queue the work to convert unwritten extents to written */ +- queue_work(wq, &io_end->work); ++ ext4_add_complete_io(io_end); + out: + bh->b_private = NULL; + bh->b_end_io = NULL; +diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c +index 9970022..5b24c40 100644 +--- a/fs/ext4/page-io.c ++++ b/fs/ext4/page-io.c +@@ -71,6 +71,7 @@ void ext4_free_io_end(ext4_io_end_t *io) + int i; + + BUG_ON(!io); ++ BUG_ON(!list_empty(&io->list)); + BUG_ON(io->flag & EXT4_IO_END_UNWRITTEN); + + if (io->page) +@@ -83,21 +84,14 @@ void ext4_free_io_end(ext4_io_end_t *io) + kmem_cache_free(io_end_cachep, io); + } + +-/* +- * check a range of space and convert unwritten extents to written. +- * +- * Called with inode->i_mutex; we depend on this when we manipulate +- * io->flag, since we could otherwise race with ext4_flush_completed_IO() +- */ +-int ext4_end_io_nolock(ext4_io_end_t *io) ++/* check a range of space and convert unwritten extents to written. */ ++static int ext4_end_io(ext4_io_end_t *io) + { + struct inode *inode = io->inode; + loff_t offset = io->offset; + ssize_t size = io->size; + int ret = 0; + +- BUG_ON(!(io->flag & EXT4_IO_END_UNWRITTEN)); +- + ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p," + "list->prev 0x%p\n", + io, inode->i_ino, io->list.next, io->list.prev); +@@ -110,7 +104,6 @@ int ext4_end_io_nolock(ext4_io_end_t *io) + "(inode %lu, offset %llu, size %zd, error %d)", + inode->i_ino, offset, size, ret); + } +- io->flag &= ~EXT4_IO_END_UNWRITTEN; + if (io->iocb) + aio_complete(io->iocb, io->result, 0); + +@@ -122,51 +115,122 @@ int ext4_end_io_nolock(ext4_io_end_t *io) + return ret; + } + +-/* +- * work on completed aio dio IO, to convert unwritten extents to extents +- */ +-static void ext4_end_io_work(struct work_struct *work) ++static void dump_completed_IO(struct inode *inode) ++{ ++#ifdef EXT4FS_DEBUG ++ struct list_head *cur, *before, *after; ++ ext4_io_end_t *io, *io0, *io1; ++ unsigned long flags; ++ ++ if (list_empty(&EXT4_I(inode)->i_completed_io_list)) { ++ ext4_debug("inode %lu completed_io list is empty\n", ++ inode->i_ino); ++ return; ++ } ++ ++ ext4_debug("Dump inode %lu completed_io list\n", inode->i_ino); ++ list_for_each_entry(io, &EXT4_I(inode)->i_completed_io_list, list) { ++ cur = &io->list; ++ before = cur->prev; ++ io0 = container_of(before, ext4_io_end_t, list); ++ after = cur->next; ++ io1 = container_of(after, ext4_io_end_t, list); ++ ++ ext4_debug("io 0x%p from inode %lu,prev 0x%p,next 0x%p\n", ++ io, inode->i_ino, io0, io1); ++ } ++#endif ++} ++ ++/* Add the io_end to per-inode completed end_io list. */ ++void ext4_add_complete_io(ext4_io_end_t *io_end) + { +- ext4_io_end_t *io = container_of(work, ext4_io_end_t, work); +- struct inode *inode = io->inode; +- struct ext4_inode_info *ei = EXT4_I(inode); +- unsigned long flags; ++ struct ext4_inode_info *ei = EXT4_I(io_end->inode); ++ struct workqueue_struct *wq; ++ unsigned long flags; ++ ++ BUG_ON(!(io_end->flag & EXT4_IO_END_UNWRITTEN)); ++ wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq; + + spin_lock_irqsave(&ei->i_completed_io_lock, flags); +- if (io->flag & EXT4_IO_END_IN_FSYNC) +- goto requeue; +- if (list_empty(&io->list)) { +- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); +- goto free; ++ if (list_empty(&ei->i_completed_io_list)) { ++ io_end->flag |= EXT4_IO_END_QUEUED; ++ queue_work(wq, &io_end->work); + } ++ list_add_tail(&io_end->list, &ei->i_completed_io_list); ++ spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); ++} + +- if (!mutex_trylock(&inode->i_mutex)) { +- bool was_queued; +-requeue: +- was_queued = !!(io->flag & EXT4_IO_END_QUEUED); +- io->flag |= EXT4_IO_END_QUEUED; +- spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); +- /* +- * Requeue the work instead of waiting so that the work +- * items queued after this can be processed. +- */ +- queue_work(EXT4_SB(inode->i_sb)->dio_unwritten_wq, &io->work); +- /* +- * To prevent the ext4-dio-unwritten thread from keeping +- * requeueing end_io requests and occupying cpu for too long, +- * yield the cpu if it sees an end_io request that has already +- * been requeued. +- */ +- if (was_queued) +- yield(); +- return; ++static int ext4_do_flush_completed_IO(struct inode *inode, ++ ext4_io_end_t *work_io) ++{ ++ ext4_io_end_t *io; ++ struct list_head unwritten, complete, to_free; ++ unsigned long flags; ++ struct ext4_inode_info *ei = EXT4_I(inode); ++ int err, ret = 0; ++ ++ INIT_LIST_HEAD(&complete); ++ INIT_LIST_HEAD(&to_free); ++ ++ spin_lock_irqsave(&ei->i_completed_io_lock, flags); ++ dump_completed_IO(inode); ++ list_replace_init(&ei->i_completed_io_list, &unwritten); ++ spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); ++ ++ while (!list_empty(&unwritten)) { ++ io = list_entry(unwritten.next, ext4_io_end_t, list); ++ BUG_ON(!(io->flag & EXT4_IO_END_UNWRITTEN)); ++ list_del_init(&io->list); ++ ++ err = ext4_end_io(io); ++ if (unlikely(!ret && err)) ++ ret = err; ++ ++ list_add_tail(&io->list, &complete); ++ } ++ /* It is important to update all flags for all end_io in one shot w/o ++ * dropping the lock.*/ ++ spin_lock_irqsave(&ei->i_completed_io_lock, flags); ++ while (!list_empty(&complete)) { ++ io = list_entry(complete.next, ext4_io_end_t, list); ++ io->flag &= ~EXT4_IO_END_UNWRITTEN; ++ /* end_io context can not be destroyed now because it still ++ * used by queued worker. Worker thread will destroy it later */ ++ if (io->flag & EXT4_IO_END_QUEUED) ++ list_del_init(&io->list); ++ else ++ list_move(&io->list, &to_free); ++ } ++ /* If we are called from worker context, it is time to clear queued ++ * flag, and destroy it's end_io if it was converted already */ ++ if (work_io) { ++ work_io->flag &= ~EXT4_IO_END_QUEUED; ++ if (!(work_io->flag & EXT4_IO_END_UNWRITTEN)) ++ list_add_tail(&work_io->list, &to_free); + } +- list_del_init(&io->list); + spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); +- (void) ext4_end_io_nolock(io); +- mutex_unlock(&inode->i_mutex); +-free: +- ext4_free_io_end(io); ++ ++ while (!list_empty(&to_free)) { ++ io = list_entry(to_free.next, ext4_io_end_t, list); ++ list_del_init(&io->list); ++ ext4_free_io_end(io); ++ } ++ return ret; ++} ++ ++/* ++ * work on completed aio dio IO, to convert unwritten extents to extents ++ */ ++static void ext4_end_io_work(struct work_struct *work) ++{ ++ ext4_io_end_t *io = container_of(work, ext4_io_end_t, work); ++ ext4_do_flush_completed_IO(io->inode, io); ++} ++ ++int ext4_flush_completed_IO(struct inode *inode) ++{ ++ return ext4_do_flush_completed_IO(inode, NULL); + } + + ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags) +@@ -199,9 +263,7 @@ static void buffer_io_error(struct buffer_head *bh) + static void ext4_end_bio(struct bio *bio, int error) + { + ext4_io_end_t *io_end = bio->bi_private; +- struct workqueue_struct *wq; + struct inode *inode; +- unsigned long flags; + int i; + sector_t bi_sector = bio->bi_sector; + +@@ -259,14 +321,7 @@ static void ext4_end_bio(struct bio *bio, int error) + return; + } + +- /* Add the io_end to per-inode completed io list*/ +- spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); +- list_add_tail(&io_end->list, &EXT4_I(inode)->i_completed_io_list); +- spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags); +- +- wq = EXT4_SB(inode->i_sb)->dio_unwritten_wq; +- /* queue the work to convert unwritten extents to written */ +- queue_work(wq, &io_end->work); ++ ext4_add_complete_io(io_end); + } + + void ext4_io_submit(struct ext4_io_submit *io) +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch b/0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch new file mode 100644 index 000000000..cf53b8dab --- /dev/null +++ b/0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch @@ -0,0 +1,144 @@ +From 994f567b2e99c82913a279ff438269c771b68a4b Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Sat, 29 Sep 2012 00:41:21 -0400 +Subject: [PATCH 05/13] ext4: serialize dio nonlocked reads with defrag + workers + +Inode's block defrag and ext4_change_inode_journal_flag() may +affect nonlocked DIO reads result, so proper synchronization +required. + +- Add missed inode_dio_wait() calls where appropriate +- Check inode state under extra i_dio_count reference. + +Reviewed-by: Jan Kara +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 17335dcc471199717839b2fa3492ca36f70f1168) + +Conflicts: + fs/ext4/move_extent.c +--- + fs/ext4/ext4.h | 17 +++++++++++++++++ + fs/ext4/indirect.c | 14 ++++++++++++++ + fs/ext4/inode.c | 5 +++++ + fs/ext4/move_extent.c | 8 ++++++++ + 4 files changed, 44 insertions(+) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 7687d15..3e740e9 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1352,6 +1352,8 @@ enum { + EXT4_STATE_DIO_UNWRITTEN, /* need convert on dio done*/ + EXT4_STATE_NEWENTRY, /* File just added to dir */ + EXT4_STATE_DELALLOC_RESERVED, /* blks already reserved for delalloc */ ++ EXT4_STATE_DIOREAD_LOCK, /* Disable support for dio read ++ nolocking */ + }; + + #define EXT4_INODE_BIT_FNS(name, field, offset) \ +@@ -2459,6 +2461,21 @@ static inline void set_bitmap_uptodate(struct buffer_head *bh) + set_bit(BH_BITMAP_UPTODATE, &(bh)->b_state); + } + ++/* ++ * Disable DIO read nolock optimization, so new dioreaders will be forced ++ * to grab i_mutex ++ */ ++static inline void ext4_inode_block_unlocked_dio(struct inode *inode) ++{ ++ ext4_set_inode_state(inode, EXT4_STATE_DIOREAD_LOCK); ++ smp_mb(); ++} ++static inline void ext4_inode_resume_unlocked_dio(struct inode *inode) ++{ ++ smp_mb(); ++ ext4_clear_inode_state(inode, EXT4_STATE_DIOREAD_LOCK); ++} ++ + #define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1) + + /* For ioend & aio unwritten conversion wait queues */ +diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c +index 61f13e5..8d849da 100644 +--- a/fs/ext4/indirect.c ++++ b/fs/ext4/indirect.c +@@ -810,11 +810,25 @@ retry: + if (unlikely(!list_empty(&ei->i_completed_io_list))) + ext4_flush_completed_IO(inode); + ++ /* ++ * Nolock dioread optimization may be dynamically disabled ++ * via ext4_inode_block_unlocked_dio(). Check inode's state ++ * while holding extra i_dio_count ref. ++ */ ++ atomic_inc(&inode->i_dio_count); ++ smp_mb(); ++ if (unlikely(ext4_test_inode_state(inode, ++ EXT4_STATE_DIOREAD_LOCK))) { ++ inode_dio_done(inode); ++ goto locked; ++ } + ret = __blockdev_direct_IO(rw, iocb, inode, + inode->i_sb->s_bdev, iov, + offset, nr_segs, + ext4_get_block, NULL, NULL, 0); ++ inode_dio_done(inode); + } else { ++locked: + ret = blockdev_direct_IO(rw, iocb, inode, iov, + offset, nr_segs, ext4_get_block); + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index dd3fd23..2bd7526 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4706,6 +4706,10 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) + return err; + } + ++ /* Wait for all existing dio workers */ ++ ext4_inode_block_unlocked_dio(inode); ++ inode_dio_wait(inode); ++ + jbd2_journal_lock_updates(journal); + + /* +@@ -4725,6 +4729,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) + ext4_set_aops(inode); + + jbd2_journal_unlock_updates(journal); ++ ext4_inode_resume_unlocked_dio(inode); + + /* Finally we can mark the inode as dirty. */ + +diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c +index c5826c6..fd1e32e 100644 +--- a/fs/ext4/move_extent.c ++++ b/fs/ext4/move_extent.c +@@ -1214,6 +1214,12 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, + /* Protect orig and donor inodes against a truncate */ + mext_inode_double_lock(orig_inode, donor_inode); + ++ /* Wait for all existing dio workers */ ++ ext4_inode_block_unlocked_dio(orig_inode); ++ ext4_inode_block_unlocked_dio(donor_inode); ++ inode_dio_wait(orig_inode); ++ inode_dio_wait(donor_inode); ++ + /* Protect extent tree against block allocations via delalloc */ + double_down_write_data_sem(orig_inode, donor_inode); + /* Check the filesystem environment whether move_extent can be done */ +@@ -1413,6 +1419,8 @@ out: + kfree(holecheck_path); + } + double_up_write_data_sem(orig_inode, donor_inode); ++ ext4_inode_resume_unlocked_dio(orig_inode); ++ ext4_inode_resume_unlocked_dio(donor_inode); + mext_inode_double_unlock(orig_inode, donor_inode); + + return ret; +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch b/0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch new file mode 100644 index 000000000..bddcc6024 --- /dev/null +++ b/0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch @@ -0,0 +1,65 @@ +From 4c4679fc02744ec3955e88faf5e8b6844fa8cbd3 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Sat, 29 Sep 2012 00:55:23 -0400 +Subject: [PATCH 06/13] ext4: serialize unlocked dio reads with truncate + +Current serialization will works only for DIO which holds +i_mutex, but nonlocked DIO following race is possible: + +dio_nolock_read_task truncate_task + ->ext4_setattr() + ->inode_dio_wait() +->ext4_ext_direct_IO + ->ext4_ind_direct_IO + ->__blockdev_direct_IO + ->ext4_get_block + ->truncate_setsize() + ->ext4_truncate() + #alloc truncated blocks + #to other inode + ->submit_io() + #INFORMATION LEAK + +In order to serialize with unlocked DIO reads we have to +rearrange wait sequence +1) update i_size first +2) if i_size about to be reduced wait for outstanding DIO requests +3) and only after that truncate inode blocks + +Reviewed-by: Jan Kara +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 1c9114f9c0f10f58dd7e568a7152025af47b27e5) +--- + fs/ext4/inode.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 2bd7526..b84322d 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4277,7 +4277,6 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) + } + + if (attr->ia_valid & ATTR_SIZE) { +- inode_dio_wait(inode); + + if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); +@@ -4326,8 +4325,12 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) + } + + if (attr->ia_valid & ATTR_SIZE) { +- if (attr->ia_size != i_size_read(inode)) ++ if (attr->ia_size != i_size_read(inode)) { + truncate_setsize(inode, attr->ia_size); ++ /* Inode size will be reduced, wait for dio in flight */ ++ if (orphan) ++ inode_dio_wait(inode); ++ } + ext4_truncate(inode); + } + +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch b/0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch new file mode 100644 index 000000000..768215f48 --- /dev/null +++ b/0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch @@ -0,0 +1,41 @@ +From ab7b8a329e12369d58e5fa59ba2e2c90370f12ef Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Sat, 29 Sep 2012 00:56:15 -0400 +Subject: [PATCH 07/13] ext4: endless truncate due to nonlocked dio readers + +If we have enough aggressive DIO readers, truncate and other dio +waiters will wait forever inside inode_dio_wait(). It is reasonable +to disable nonlock DIO read optimization during truncate. + +Reviewed-by: Jan Kara +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 1b65007e9870e0021397b548e8cd6bbc584f9152) +--- + fs/ext4/inode.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index b84322d..3b03dd6 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4327,9 +4327,14 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) + if (attr->ia_valid & ATTR_SIZE) { + if (attr->ia_size != i_size_read(inode)) { + truncate_setsize(inode, attr->ia_size); +- /* Inode size will be reduced, wait for dio in flight */ +- if (orphan) ++ /* Inode size will be reduced, wait for dio in flight. ++ * Temporarily disable dioread_nolock to prevent ++ * livelock. */ ++ if (orphan) { ++ ext4_inode_block_unlocked_dio(inode); + inode_dio_wait(inode); ++ ext4_inode_resume_unlocked_dio(inode); ++ } + } + ext4_truncate(inode); + } +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch b/0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch new file mode 100644 index 000000000..c7733ed74 --- /dev/null +++ b/0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch @@ -0,0 +1,61 @@ +From 69e4026a2d104ffcf1b935bc889f8abcbfbb29ec Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Sat, 29 Sep 2012 00:58:26 -0400 +Subject: [PATCH 08/13] ext4: serialize truncate with owerwrite DIO workers + +Jan Kara have spotted interesting issue: +There are potential data corruption issue with direct IO overwrites +racing with truncate: + Like: + dio write truncate_task + ->ext4_ext_direct_IO + ->overwrite == 1 + ->down_read(&EXT4_I(inode)->i_data_sem); + ->mutex_unlock(&inode->i_mutex); + ->ext4_setattr() + ->inode_dio_wait() + ->truncate_setsize() + ->ext4_truncate() + ->down_write(&EXT4_I(inode)->i_data_sem); + ->__blockdev_direct_IO + ->ext4_get_block + ->submit_io() + ->up_read(&EXT4_I(inode)->i_data_sem); + # truncate data blocks, allocate them to + # other inode - bad stuff happens because + # dio is still in flight. + +In order to serialize with truncate dio worker should grab extra i_dio_count +reference before drop i_mutex. + +Reviewed-by: Jan Kara +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 1f555cfa29e8f787d675e8390f88ce517a37271a) +--- + fs/ext4/inode.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 3b03dd6..484a327 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3008,6 +3008,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, + overwrite = *((int *)iocb->private); + + if (overwrite) { ++ atomic_inc(&inode->i_dio_count); + down_read(&EXT4_I(inode)->i_data_sem); + mutex_unlock(&inode->i_mutex); + } +@@ -3105,6 +3106,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, + retake_lock: + /* take i_mutex locking again if we do a ovewrite dio */ + if (overwrite) { ++ inode_dio_done(inode); + up_read(&EXT4_I(inode)->i_data_sem); + mutex_lock(&inode->i_mutex); + } +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0009-ext4-punch_hole-should-wait-for-DIO-writers.patch b/0009-ext4-punch_hole-should-wait-for-DIO-writers.patch new file mode 100644 index 000000000..4d7636668 --- /dev/null +++ b/0009-ext4-punch_hole-should-wait-for-DIO-writers.patch @@ -0,0 +1,125 @@ +From 71a6398a4b59ddcf920dfb68872b5a771c606e3a Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Sun, 30 Sep 2012 23:03:42 -0400 +Subject: [PATCH 09/13] ext4: punch_hole should wait for DIO writers + +punch_hole is the place where we have to wait for all existing writers +(writeback, aio, dio), but currently we simply flush pended end_io request +which is not sufficient. Other issue is that punch_hole performed w/o i_mutex +held which obviously result in dangerous data corruption due to +write-after-free. + +This patch performs following changes: +- Guard punch_hole with i_mutex +- Recheck inode flags under i_mutex +- Block all new dio readers in order to prevent information leak caused by + read-after-free pattern. +- punch_hole now wait for all writers in flight + NOTE: XXX write-after-free race is still possible because new dirty pages + may appear due to mmap(), and currently there is no easy way to stop + writeback while punch_hole is in progress. + +[ Fixed error return from ext4_ext_punch_hole() to make sure that we + release i_mutex before returning EPERM or ETXTBUSY -- Ted ] + +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 02d262dffcf4c74e5c4612ee736bdb94f18ed5b9) +--- + fs/ext4/extents.c | 53 ++++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 36 insertions(+), 17 deletions(-) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 1fbf2ff..202eb4d 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4776,9 +4776,32 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) + loff_t first_page_offset, last_page_offset; + int credits, err = 0; + ++ /* ++ * Write out all dirty pages to avoid race conditions ++ * Then release them. ++ */ ++ if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { ++ err = filemap_write_and_wait_range(mapping, ++ offset, offset + length - 1); ++ ++ if (err) ++ return err; ++ } ++ ++ mutex_lock(&inode->i_mutex); ++ /* It's not possible punch hole on append only file */ ++ if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) { ++ err = -EPERM; ++ goto out_mutex; ++ } ++ if (IS_SWAPFILE(inode)) { ++ err = -ETXTBSY; ++ goto out_mutex; ++ } ++ + /* No need to punch hole beyond i_size */ + if (offset >= inode->i_size) +- return 0; ++ goto out_mutex; + + /* + * If the hole extends beyond i_size, set the hole +@@ -4796,33 +4819,25 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) + first_page_offset = first_page << PAGE_CACHE_SHIFT; + last_page_offset = last_page << PAGE_CACHE_SHIFT; + +- /* +- * Write out all dirty pages to avoid race conditions +- * Then release them. +- */ +- if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { +- err = filemap_write_and_wait_range(mapping, +- offset, offset + length - 1); +- +- if (err) +- return err; +- } +- + /* Now release the pages */ + if (last_page_offset > first_page_offset) { + truncate_pagecache_range(inode, first_page_offset, + last_page_offset - 1); + } + +- /* finish any pending end_io work */ ++ /* Wait all existing dio workers, newcomers will block on i_mutex */ ++ ext4_inode_block_unlocked_dio(inode); ++ inode_dio_wait(inode); + err = ext4_flush_completed_IO(inode); + if (err) +- return err; ++ goto out_dio; + + credits = ext4_writepage_trans_blocks(inode); + handle = ext4_journal_start(inode, credits); +- if (IS_ERR(handle)) +- return PTR_ERR(handle); ++ if (IS_ERR(handle)) { ++ err = PTR_ERR(handle); ++ goto out_dio; ++ } + + err = ext4_orphan_add(handle, inode); + if (err) +@@ -4916,6 +4931,10 @@ out: + inode->i_mtime = inode->i_ctime = ext4_current_time(inode); + ext4_mark_inode_dirty(handle, inode); + ext4_journal_stop(handle); ++out_dio: ++ ext4_inode_resume_unlocked_dio(inode); ++out_mutex: ++ mutex_unlock(&inode->i_mutex); + return err; + } + int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch b/0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch new file mode 100644 index 000000000..d161bb765 --- /dev/null +++ b/0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch @@ -0,0 +1,60 @@ +From 66d08dd92b82dabfd64853aa4edde1547fdf9ef7 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Sun, 30 Sep 2012 23:03:50 -0400 +Subject: [PATCH 10/13] ext4: fix ext_remove_space for punch_hole case + +Inode is allowed to have empty leaf only if it this is blockless inode. + +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 6f2080e64487b9963f9c6ff8a252e1abce98f2d4) +--- + fs/ext4/extents.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 202eb4d..b1c92c0 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -2572,7 +2572,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, + struct ext4_ext_path *path = NULL; + ext4_fsblk_t partial_cluster = 0; + handle_t *handle; +- int i = 0, err; ++ int i = 0, err = 0; + + ext_debug("truncate since %u to %u\n", start, end); + +@@ -2604,12 +2604,16 @@ again: + return PTR_ERR(path); + } + depth = ext_depth(inode); ++ /* Leaf not may not exist only if inode has no blocks at all */ + ex = path[depth].p_ext; + if (!ex) { +- ext4_ext_drop_refs(path); +- kfree(path); +- path = NULL; +- goto cont; ++ if (depth) { ++ EXT4_ERROR_INODE(inode, ++ "path[%d].p_hdr == NULL", ++ depth); ++ err = -EIO; ++ } ++ goto out; + } + + ee_block = le32_to_cpu(ex->ee_block); +@@ -2641,8 +2645,6 @@ again: + goto out; + } + } +-cont: +- + /* + * We start scanning from right side, freeing all the blocks + * after i_size and walking into the tree depth-wise. +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch b/0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch new file mode 100644 index 000000000..517b20129 --- /dev/null +++ b/0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch @@ -0,0 +1,176 @@ +From ca6d3910cbf8854f3f3b9846391f669733899101 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Fri, 5 Oct 2012 11:31:55 -0400 +Subject: [PATCH 11/13] ext4: fix ext4_flush_completed_IO wait semantics + +BUG #1) All places where we call ext4_flush_completed_IO are broken + because buffered io and DIO/AIO goes through three stages + 1) submitted io, + 2) completed io (in i_completed_io_list) conversion pended + 3) finished io (conversion done) + And by calling ext4_flush_completed_IO we will flush only + requests which were in (2) stage, which is wrong because: + 1) punch_hole and truncate _must_ wait for all outstanding unwritten io + regardless to it's state. + 2) fsync and nolock_dio_read should also wait because there is + a time window between end_page_writeback() and ext4_add_complete_io() + As result integrity fsync is broken in case of buffered write + to fallocated region: + fsync blkdev_completion + ->filemap_write_and_wait_range + ->ext4_end_bio + ->end_page_writeback + <-- filemap_write_and_wait_range return + ->ext4_flush_completed_IO + sees empty i_completed_io_list but pended + conversion still exist + ->ext4_add_complete_io + +BUG #2) Race window becomes wider due to the 'ext4: completed_io +locking cleanup V4' patch series + +This patch make following changes: +1) ext4_flush_completed_io() now first try to flush completed io and when + wait for any outstanding unwritten io via ext4_unwritten_wait() +2) Rename function to more appropriate name. +3) Assert that all callers of ext4_flush_unwritten_io should hold i_mutex to + prevent endless wait + +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Jan Kara +(cherry picked from commit c278531d39f3158bfee93dc67da0b77e09776de2) +--- + fs/ext4/ext4.h | 3 ++- + fs/ext4/extents.c | 6 +++--- + fs/ext4/file.c | 2 +- + fs/ext4/fsync.c | 2 +- + fs/ext4/indirect.c | 8 +++++--- + fs/ext4/page-io.c | 11 +++++++---- + 6 files changed, 19 insertions(+), 13 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 3e740e9..7f13292 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1941,7 +1941,7 @@ extern void ext4_htree_free_dir_info(struct dir_private_info *p); + + /* fsync.c */ + extern int ext4_sync_file(struct file *, loff_t, loff_t, int); +-extern int ext4_flush_completed_IO(struct inode *); ++extern int ext4_flush_unwritten_io(struct inode *); + + /* hash.c */ + extern int ext4fs_dirhash(const char *name, int len, struct +@@ -2361,6 +2361,7 @@ extern const struct file_operations ext4_dir_operations; + extern const struct inode_operations ext4_file_inode_operations; + extern const struct file_operations ext4_file_operations; + extern loff_t ext4_llseek(struct file *file, loff_t offset, int origin); ++extern void ext4_unwritten_wait(struct inode *inode); + + /* namei.c */ + extern const struct inode_operations ext4_dir_inode_operations; +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index b1c92c0..37f46eb 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4250,7 +4250,7 @@ void ext4_ext_truncate(struct inode *inode) + * finish any pending end_io work so we won't run the risk of + * converting any truncated blocks to initialized later + */ +- ext4_flush_completed_IO(inode); ++ ext4_flush_unwritten_io(inode); + + /* + * probably first extent we're gonna free will be last in block +@@ -4829,10 +4829,10 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) + + /* Wait all existing dio workers, newcomers will block on i_mutex */ + ext4_inode_block_unlocked_dio(inode); +- inode_dio_wait(inode); +- err = ext4_flush_completed_IO(inode); ++ err = ext4_flush_unwritten_io(inode); + if (err) + goto out_dio; ++ inode_dio_wait(inode); + + credits = ext4_writepage_trans_blocks(inode); + handle = ext4_journal_start(inode, credits); +diff --git a/fs/ext4/file.c b/fs/ext4/file.c +index 39335bd..ca6f07a 100644 +--- a/fs/ext4/file.c ++++ b/fs/ext4/file.c +@@ -55,7 +55,7 @@ static int ext4_release_file(struct inode *inode, struct file *filp) + return 0; + } + +-static void ext4_unwritten_wait(struct inode *inode) ++void ext4_unwritten_wait(struct inode *inode) + { + wait_queue_head_t *wq = ext4_ioend_wq(inode); + +diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c +index 520b058..76051c6 100644 +--- a/fs/ext4/fsync.c ++++ b/fs/ext4/fsync.c +@@ -138,7 +138,7 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + if (inode->i_sb->s_flags & MS_RDONLY) + goto out; + +- ret = ext4_flush_completed_IO(inode); ++ ret = ext4_flush_unwritten_io(inode); + if (ret < 0) + goto out; + +diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c +index 8d849da..792e388 100644 +--- a/fs/ext4/indirect.c ++++ b/fs/ext4/indirect.c +@@ -807,9 +807,11 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, + + retry: + if (rw == READ && ext4_should_dioread_nolock(inode)) { +- if (unlikely(!list_empty(&ei->i_completed_io_list))) +- ext4_flush_completed_IO(inode); +- ++ if (unlikely(atomic_read(&EXT4_I(inode)->i_unwritten))) { ++ mutex_lock(&inode->i_mutex); ++ ext4_flush_unwritten_io(inode); ++ mutex_unlock(&inode->i_mutex); ++ } + /* + * Nolock dioread optimization may be dynamically disabled + * via ext4_inode_block_unlocked_dio(). Check inode's state +diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c +index 5b24c40..68e896e 100644 +--- a/fs/ext4/page-io.c ++++ b/fs/ext4/page-io.c +@@ -189,8 +189,6 @@ static int ext4_do_flush_completed_IO(struct inode *inode, + + list_add_tail(&io->list, &complete); + } +- /* It is important to update all flags for all end_io in one shot w/o +- * dropping the lock.*/ + spin_lock_irqsave(&ei->i_completed_io_lock, flags); + while (!list_empty(&complete)) { + io = list_entry(complete.next, ext4_io_end_t, list); +@@ -228,9 +226,14 @@ static void ext4_end_io_work(struct work_struct *work) + ext4_do_flush_completed_IO(io->inode, io); + } + +-int ext4_flush_completed_IO(struct inode *inode) ++int ext4_flush_unwritten_io(struct inode *inode) + { +- return ext4_do_flush_completed_IO(inode, NULL); ++ int ret; ++ WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex) && ++ !(inode->i_state & I_FREEING)); ++ ret = ext4_do_flush_completed_IO(inode, NULL); ++ ext4_unwritten_wait(inode); ++ return ret; + } + + ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags) +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch b/0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch new file mode 100644 index 000000000..3fcaef1f2 --- /dev/null +++ b/0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch @@ -0,0 +1,46 @@ +From 9f00d109efeaf4d12d56c8e46cd13af80e344f97 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Fri, 5 Oct 2012 11:32:02 -0400 +Subject: [PATCH 12/13] ext4: serialize fallocate with + ext4_convert_unwritten_extents + +Fallocate should wait for pended ext4_convert_unwritten_extents() +otherwise following race may happen: + +ftruncate( ,12288); +fallocate( ,0, 4096) +io_sibmit( ,0, 4096); /* Write to fallocated area, split extent if needed */ +fallocate( ,0, 8192); /* Grow extent and broke assumption about extent */ + +Later kwork completion will do: + ->ext4_convert_unwritten_extents (0, 4096) + ->ext4_map_blocks(handle, inode, &map, EXT4_GET_BLOCKS_IO_CONVERT_EXT); + ->ext4_ext_map_blocks() /* Will find new extent: ex = [0,2] !!!!!! */ + ->ext4_ext_handle_uninitialized_extents() + ->ext4_convert_unwritten_extents_endio() + /* convert [0,2] extent to initialized, but only[0,1] was written */ + +Signed-off-by: Dmitry Monakhov +Signed-off-by: "Theodore Ts'o" +(cherry picked from commit 60d4616f3dc63371b3dc367e5e88fd4b4f037f65) +--- + fs/ext4/extents.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 37f46eb..ea2db86 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4410,6 +4410,9 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) + */ + if (len <= EXT_UNINIT_MAX_LEN << blkbits) + flags |= EXT4_GET_BLOCKS_NO_NORMALIZE; ++ ++ /* Prevent race condition between unwritten */ ++ ext4_flush_unwritten_io(inode); + retry: + while (ret >= 0 && ret < max_blocks) { + map.m_lblk = map.m_lblk + ret; +-- +1.7.12.rc0.22.gcdd159b + diff --git a/0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch b/0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch new file mode 100644 index 000000000..ffd7975c6 --- /dev/null +++ b/0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch @@ -0,0 +1,153 @@ +From 5ff6b4cc64765e10df509a60e902561efdeb58d5 Mon Sep 17 00:00:00 2001 +From: Dmitry Monakhov +Date: Fri, 5 Oct 2012 11:32:04 -0400 +Subject: [PATCH 13/13] ext4: race-condition protection for + ext4_convert_unwritten_extents_endio + +We assumed that at the time we call ext4_convert_unwritten_extents_endio() +extent in question is fully inside [map.m_lblk, map->m_len] because +it was already split during submission. But this may not be true due to +a race between writeback vs fallocate. + +If extent in question is larger than requested we will split it again. +Special precautions should being done if zeroout required because +[map.m_lblk, map->m_len] already contains valid data. + +Signed-off-by: Dmitry Monakhov +(cherry picked from commit 0d4b4ff5282d07a4f83b87b3117cd898b0a3f673) +--- + fs/ext4/extents.c | 57 ++++++++++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 46 insertions(+), 11 deletions(-) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index ea2db86..ee0d61c 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -52,6 +52,9 @@ + #define EXT4_EXT_MARK_UNINIT1 0x2 /* mark first half uninitialized */ + #define EXT4_EXT_MARK_UNINIT2 0x4 /* mark second half uninitialized */ + ++#define EXT4_EXT_DATA_VALID1 0x8 /* first half contains valid data */ ++#define EXT4_EXT_DATA_VALID2 0x10 /* second half contains valid data */ ++ + static __le32 ext4_extent_block_csum(struct inode *inode, + struct ext4_extent_header *eh) + { +@@ -2897,6 +2900,9 @@ static int ext4_split_extent_at(handle_t *handle, + unsigned int ee_len, depth; + int err = 0; + ++ BUG_ON((split_flag & (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)) == ++ (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)); ++ + ext_debug("ext4_split_extents_at: inode %lu, logical" + "block %llu\n", inode->i_ino, (unsigned long long)split); + +@@ -2955,7 +2961,14 @@ static int ext4_split_extent_at(handle_t *handle, + + err = ext4_ext_insert_extent(handle, inode, path, &newex, flags); + if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) { +- err = ext4_ext_zeroout(inode, &orig_ex); ++ if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) { ++ if (split_flag & EXT4_EXT_DATA_VALID1) ++ err = ext4_ext_zeroout(inode, ex2); ++ else ++ err = ext4_ext_zeroout(inode, ex); ++ } else ++ err = ext4_ext_zeroout(inode, &orig_ex); ++ + if (err) + goto fix_extent_len; + /* update the extent length and mark as initialized */ +@@ -3008,12 +3021,13 @@ static int ext4_split_extent(handle_t *handle, + uninitialized = ext4_ext_is_uninitialized(ex); + + if (map->m_lblk + map->m_len < ee_block + ee_len) { +- split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? +- EXT4_EXT_MAY_ZEROOUT : 0; ++ split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT; + flags1 = flags | EXT4_GET_BLOCKS_PRE_IO; + if (uninitialized) + split_flag1 |= EXT4_EXT_MARK_UNINIT1 | + EXT4_EXT_MARK_UNINIT2; ++ if (split_flag & EXT4_EXT_DATA_VALID2) ++ split_flag1 |= EXT4_EXT_DATA_VALID1; + err = ext4_split_extent_at(handle, inode, path, + map->m_lblk + map->m_len, split_flag1, flags1); + if (err) +@@ -3026,8 +3040,8 @@ static int ext4_split_extent(handle_t *handle, + return PTR_ERR(path); + + if (map->m_lblk >= ee_block) { +- split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? +- EXT4_EXT_MAY_ZEROOUT : 0; ++ split_flag1 = split_flag & (EXT4_EXT_MAY_ZEROOUT | ++ EXT4_EXT_DATA_VALID2); + if (uninitialized) + split_flag1 |= EXT4_EXT_MARK_UNINIT1; + if (split_flag & EXT4_EXT_MARK_UNINIT2) +@@ -3305,26 +3319,47 @@ static int ext4_split_unwritten_extents(handle_t *handle, + + split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0; + split_flag |= EXT4_EXT_MARK_UNINIT2; +- ++ if (flags & EXT4_GET_BLOCKS_CONVERT) ++ split_flag |= EXT4_EXT_DATA_VALID2; + flags |= EXT4_GET_BLOCKS_PRE_IO; + return ext4_split_extent(handle, inode, path, map, split_flag, flags); + } + + static int ext4_convert_unwritten_extents_endio(handle_t *handle, +- struct inode *inode, +- struct ext4_ext_path *path) ++ struct inode *inode, ++ struct ext4_map_blocks *map, ++ struct ext4_ext_path *path) + { + struct ext4_extent *ex; ++ ext4_lblk_t ee_block; ++ unsigned int ee_len; + int depth; + int err = 0; + + depth = ext_depth(inode); + ex = path[depth].p_ext; ++ ee_block = le32_to_cpu(ex->ee_block); ++ ee_len = ext4_ext_get_actual_len(ex); + + ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical" + "block %llu, max_blocks %u\n", inode->i_ino, +- (unsigned long long)le32_to_cpu(ex->ee_block), +- ext4_ext_get_actual_len(ex)); ++ (unsigned long long)ee_block, ee_len); ++ ++ /* If extent is larger than requested then split is required */ ++ if (ee_block != map->m_lblk || ee_len > map->m_len) { ++ err = ext4_split_unwritten_extents(handle, inode, map, path, ++ EXT4_GET_BLOCKS_CONVERT); ++ if (err < 0) ++ goto out; ++ ext4_ext_drop_refs(path); ++ path = ext4_ext_find_extent(inode, map->m_lblk, path); ++ if (IS_ERR(path)) { ++ err = PTR_ERR(path); ++ goto out; ++ } ++ depth = ext_depth(inode); ++ ex = path[depth].p_ext; ++ } + + err = ext4_ext_get_access(handle, inode, path + depth); + if (err) +@@ -3634,7 +3669,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, + } + /* IO end_io complete, convert the filled extent to written */ + if ((flags & EXT4_GET_BLOCKS_CONVERT)) { +- ret = ext4_convert_unwritten_extents_endio(handle, inode, ++ ret = ext4_convert_unwritten_extents_endio(handle, inode, map, + path); + if (ret >= 0) { + ext4_update_inode_fsync_trans(handle, inode, 1); +-- +1.7.12.rc0.22.gcdd159b + diff --git a/kernel.spec b/kernel.spec index 15f5b3d91..8c77bb312 100644 --- a/kernel.spec +++ b/kernel.spec @@ -699,6 +699,21 @@ Patch22077: dont-call-cifs_lookup-on-hashed-negative-dentry.patch #rhbz 852210 Patch22078: drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch +#rhbz 869904 869909 CVE-2012-4508 +Patch22080: 0001-ext4-ext4_inode_info-diet.patch +Patch22081: 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch +Patch22082: 0003-ext4-fix-unwritten-counter-leakage.patch +Patch22083: 0004-ext4-completed_io-locking-cleanup.patch +Patch22084: 0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch +Patch22085: 0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch +Patch22086: 0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch +Patch22087: 0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch +Patch22088: 0009-ext4-punch_hole-should-wait-for-DIO-writers.patch +Patch22089: 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch +Patch22090: 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch +Patch22091: 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch +Patch22092: 0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch + # Debug patches Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch @@ -1323,6 +1338,21 @@ ApplyPatch dont-call-cifs_lookup-on-hashed-negative-dentry.patch #rhbz 852210 ApplyPatch drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch +#rhbz 869904 869909 CVE-2012-4508 +ApplyPatch 0001-ext4-ext4_inode_info-diet.patch +ApplyPatch 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch +ApplyPatch 0003-ext4-fix-unwritten-counter-leakage.patch +ApplyPatch 0004-ext4-completed_io-locking-cleanup.patch +ApplyPatch 0005-ext4-serialize-dio-nonlocked-reads-with-defrag-worke.patch +ApplyPatch 0006-ext4-serialize-unlocked-dio-reads-with-truncate.patch +ApplyPatch 0007-ext4-endless-truncate-due-to-nonlocked-dio-readers.patch +ApplyPatch 0008-ext4-serialize-truncate-with-owerwrite-DIO-workers.patch +ApplyPatch 0009-ext4-punch_hole-should-wait-for-DIO-writers.patch +ApplyPatch 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch +ApplyPatch 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch +ApplyPatch 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch +ApplyPatch 0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch + # END OF PATCH APPLICATIONS %endif @@ -2023,6 +2053,9 @@ fi # and build. %changelog +* Thu Oct 25 2012 Justin M. Forbes +- CVE-2012-4508: ext4: AIO vs fallocate stale data exposure (rhbz 869904 869909) + * Wed Oct 24 2012 Josh Boyer - Remove patch added for rhbz 856863 - Add patch to fix corrupted text with i915 (rhbz 852210) From 631b8185a4e15406aaa959b40272b0e205f21f99 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 29 Oct 2012 09:05:49 -0500 Subject: [PATCH 450/487] Linux 3.6.4 --- kernel.spec | 21 +++++---------------- sources | 2 +- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/kernel.spec b/kernel.spec index 8c77bb312..f4b5ce6a8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 2 +%define stable_update 4 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -690,15 +690,9 @@ Patch22073: mac80211_local_deauth_v3.6.patch #rhbz 866013 Patch22074: mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch -#rhbz 862877 864824 CVE-2012-0957 -Patch22076: fix-stack-memory-content-leak-via-UNAME26.patch - #rhbz 867344 Patch22077: dont-call-cifs_lookup-on-hashed-negative-dentry.patch -#rhbz 852210 -Patch22078: drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch - #rhbz 869904 869909 CVE-2012-4508 Patch22080: 0001-ext4-ext4_inode_info-diet.patch Patch22081: 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch @@ -712,7 +706,6 @@ Patch22088: 0009-ext4-punch_hole-should-wait-for-DIO-writers.patch Patch22089: 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch Patch22090: 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch Patch22091: 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch -Patch22092: 0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch # Debug patches Patch30000: weird-root-dentry-name-debug.patch @@ -1329,15 +1322,9 @@ ApplyPatch mac80211_local_deauth_v3.6.patch #rhbz 866013 ApplyPatch mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch -#rhbz 862877 864824 CVE-2012-0957 -ApplyPatch fix-stack-memory-content-leak-via-UNAME26.patch - #rhbz 867344 ApplyPatch dont-call-cifs_lookup-on-hashed-negative-dentry.patch -#rhbz 852210 -ApplyPatch drm-i915-Use-cpu-relocations-if-the-object-is-in-the.patch - #rhbz 869904 869909 CVE-2012-4508 ApplyPatch 0001-ext4-ext4_inode_info-diet.patch ApplyPatch 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch @@ -1351,7 +1338,6 @@ ApplyPatch 0009-ext4-punch_hole-should-wait-for-DIO-writers.patch ApplyPatch 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch ApplyPatch 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch ApplyPatch 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch -ApplyPatch 0013-ext4-race-condition-protection-for-ext4_convert_unwr.patch # END OF PATCH APPLICATIONS @@ -2053,6 +2039,9 @@ fi # and build. %changelog +* Mon Oct 29 2012 Justin M. Forbes 3.6.4-1 +- Linux 3.6.4 + * Thu Oct 25 2012 Justin M. Forbes - CVE-2012-4508: ext4: AIO vs fallocate stale data exposure (rhbz 869904 869909) diff --git a/sources b/sources index 47fce40c3..965397c16 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -ad1020c82a71ee1ef2416a0d12e724df patch-3.6.2.xz +d7efab4da2682c44662b684026b059f7 patch-3.6.4.xz From 3c9b3f75acb72d2af5c1472f86cd609a16a4b723 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 30 Oct 2012 13:06:45 -0400 Subject: [PATCH 451/487] Update patch for 867344 --- ...ifs_lookup-on-hashed-negative-dentry.patch | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/dont-call-cifs_lookup-on-hashed-negative-dentry.patch b/dont-call-cifs_lookup-on-hashed-negative-dentry.patch index 88b35e2f8..4e25f9d20 100644 --- a/dont-call-cifs_lookup-on-hashed-negative-dentry.patch +++ b/dont-call-cifs_lookup-on-hashed-negative-dentry.patch @@ -1,21 +1,19 @@ @@ -, +, @@ - negative dentry - BUG_ON(!d_unhashed(entry)); - fs/cifs/dir.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) + cifs_atomic_open + fs/cifs/dir.c | 6 ++++++ + 1 file changed, 6 insertions(+) --- a/fs/cifs/dir.c +++ a/fs/cifs/dir.c -@@ -398,7 +398,12 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, +@@ -398,6 +398,12 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, * in network traffic in the other paths. */ if (!(oflags & O_CREAT)) { -- struct dentry *res = cifs_lookup(inode, direntry, 0); -+ struct dentry *res; -+ -+ if (!direntry->d_inode) ++ /* Check for hashed negative dentry. We have already revalidated ++ * the dentry and it is fine. No need to perform another lookup. ++ */ ++ if (!d_unhashed(direntry)) + return -ENOENT; + -+ res = cifs_lookup(inode, direntry, 0); + struct dentry *res = cifs_lookup(inode, direntry, 0); if (IS_ERR(res)) return PTR_ERR(res); - From 81f7c502c415cf9c491b42f07bb8094ab6472244 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 31 Oct 2012 13:58:56 -0400 Subject: [PATCH 452/487] CVE-2012-4565 net: divide by zero in tcp algorithm illinois (rhbz 871848 871923) --- kernel.spec | 9 ++ ...de-by-zero-in-tcp-algorithm-illinois.patch | 117 ++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch diff --git a/kernel.spec b/kernel.spec index f4b5ce6a8..1055b514a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -707,6 +707,9 @@ Patch22089: 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch Patch22090: 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch Patch22091: 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch +#rhbz 871923 871848 CVE-2012-4565 +Patch22092: net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch + # Debug patches Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch @@ -1339,6 +1342,9 @@ ApplyPatch 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch ApplyPatch 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch ApplyPatch 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch +#rhbz 871923 871848 CVE-2012-4565 +ApplyPatch net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch + # END OF PATCH APPLICATIONS %endif @@ -2039,6 +2045,9 @@ fi # and build. %changelog +* Wed Oct 30 2012 Josh Boyer +- CVE-2012-4565 net: divide by zero in tcp algorithm illinois (rhbz 871848 871923) + * Mon Oct 29 2012 Justin M. Forbes 3.6.4-1 - Linux 3.6.4 diff --git a/net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch b/net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch new file mode 100644 index 000000000..109ee17b4 --- /dev/null +++ b/net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch @@ -0,0 +1,117 @@ +Path: news.gmane.org!not-for-mail +From: Jesper Dangaard Brouer +Newsgroups: gmane.linux.network +Subject: [net PATCH V2] net: fix divide by zero in tcp algorithm illinois +Date: Wed, 31 Oct 2012 13:45:32 +0100 +Lines: 63 +Approved: news@gmane.org +Message-ID: <20121031124318.30915.32293.stgit@dragon> +NNTP-Posting-Host: plane.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: 7bit +X-Trace: ger.gmane.org 1351687472 19921 80.91.229.3 (31 Oct 2012 12:44:32 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 31 Oct 2012 12:44:32 +0000 (UTC) +Cc: Jesper Dangaard Brouer , netdev@vger.kernel.org, + Petr Matousek , + Stephen Hemminger , + Eric Dumazet +To: "David S. Miller" +Original-X-From: netdev-owner@vger.kernel.org Wed Oct 31 13:44:40 2012 +Return-path: +Envelope-to: linux-netdev-2@plane.gmane.org +Original-Received: from vger.kernel.org ([209.132.180.67]) + by plane.gmane.org with esmtp (Exim 4.69) + (envelope-from ) + id 1TTXex-0002V3-Qk + for linux-netdev-2@plane.gmane.org; Wed, 31 Oct 2012 13:44:40 +0100 +Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S932565Ab2JaMo0 (ORCPT ); + Wed, 31 Oct 2012 08:44:26 -0400 +Original-Received: from mx1.redhat.com ([209.132.183.28]:57345 "EHLO mx1.redhat.com" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1751941Ab2JaMoZ (ORCPT ); + Wed, 31 Oct 2012 08:44:25 -0400 +Original-Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q9VCiOkC014655 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); + Wed, 31 Oct 2012 08:44:24 -0400 +Original-Received: from dragon.localdomain (ovpn-116-61.ams2.redhat.com [10.36.116.61]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q9VCiMuW008440; + Wed, 31 Oct 2012 08:44:23 -0400 +Original-Received: from [127.0.0.1] (localhost [IPv6:::1]) + by dragon.localdomain (Postfix) with ESMTP id 416D0E40666; + Wed, 31 Oct 2012 13:45:32 +0100 (CET) +User-Agent: StGIT/0.14.3 +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +Original-Sender: netdev-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: netdev@vger.kernel.org +Xref: news.gmane.org gmane.linux.network:247871 +Archived-At: + +Reading TCP stats when using TCP Illinois congestion control algorithm +can cause a divide by zero kernel oops. + +The division by zero occur in tcp_illinois_info() at: + do_div(t, ca->cnt_rtt); +where ca->cnt_rtt can become zero (when rtt_reset is called) + +Steps to Reproduce: + 1. Register tcp_illinois: + # sysctl -w net.ipv4.tcp_congestion_control=illinois + 2. Monitor internal TCP information via command "ss -i" + # watch -d ss -i + 3. Establish new TCP conn to machine + +Either it fails at the initial conn, or else it needs to wait +for a loss or a reset. + +This is only related to reading stats. The function avg_delay() also +performs the same divide, but is guarded with a (ca->cnt_rtt > 0) at its +calling point in update_params(). Thus, simply fix tcp_illinois_info(). + +Function tcp_illinois_info() / get_info() is called without +socket lock. Thus, eliminate any race condition on ca->cnt_rtt +by using a local stack variable. Simply reuse info.tcpv_rttcnt, +as its already set to ca->cnt_rtt. +Function avg_delay() is not affected by this race condition, as +its called with the socket lock. + +Cc: Petr Matousek +Signed-off-by: Jesper Dangaard Brouer + +--- +V2: + Address Eric Dumazets input: + - Save 2 bytes of stack, by using info.tcpv_rttcnt. + - Help compiler, and define "u64 t" inside if() lexical scope. + + + net/ipv4/tcp_illinois.c | 8 +++++--- + 1 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c +index 813b43a..834857f 100644 +--- a/net/ipv4/tcp_illinois.c ++++ b/net/ipv4/tcp_illinois.c +@@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext, + .tcpv_rttcnt = ca->cnt_rtt, + .tcpv_minrtt = ca->base_rtt, + }; +- u64 t = ca->sum_rtt; + +- do_div(t, ca->cnt_rtt); +- info.tcpv_rtt = t; ++ if (info.tcpv_rttcnt > 0) { ++ u64 t = ca->sum_rtt; + ++ do_div(t, info.tcpv_rttcnt); ++ info.tcpv_rtt = t; ++ } + nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info); + } + } + From 7557f2eb453cd04665cd4bca0d1c92f1860040a1 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 31 Oct 2012 14:24:18 -0500 Subject: [PATCH 453/487] Linux 3.6.5 --- iwlwifi-fix-6000-ch-switch.patch | 94 ------------------- kernel.spec | 23 +---- ...t-with-HT20-if-HT40-is-not-permitted.patch | 75 --------------- mac80211_local_deauth_v3.6.patch | 66 ------------- sources | 2 +- 5 files changed, 5 insertions(+), 255 deletions(-) delete mode 100644 iwlwifi-fix-6000-ch-switch.patch delete mode 100644 mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch delete mode 100644 mac80211_local_deauth_v3.6.patch diff --git a/iwlwifi-fix-6000-ch-switch.patch b/iwlwifi-fix-6000-ch-switch.patch deleted file mode 100644 index 0fbca2354..000000000 --- a/iwlwifi-fix-6000-ch-switch.patch +++ /dev/null @@ -1,94 +0,0 @@ -commit a7d3a5d97acd4b8db17e1d5c3014357c9b2040f9 -Author: Johannes Berg -Date: Tue Sep 25 16:40:12 2012 +0200 - - iwlwifi: fix 6000 series channel switch command - - The channel switch command for 6000 series devices - is larger than the maximum inline command size of - 320 bytes. The command is therefore refused with a - warning. Fix this by allocating the command and - using the NOCOPY mechanism. - - Cc: stable@kernel.org - Signed-off-by: Johannes Berg - -diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c -index 349c205..da58620 100644 ---- a/drivers/net/wireless/iwlwifi/dvm/devices.c -+++ b/drivers/net/wireless/iwlwifi/dvm/devices.c -@@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, - * See iwlagn_mac_channel_switch. - */ - struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; -- struct iwl6000_channel_switch_cmd cmd; -+ struct iwl6000_channel_switch_cmd *cmd; - u32 switch_time_in_usec, ucode_switch_time; - u16 ch; - u32 tsf_low; -@@ -527,18 +527,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, - struct ieee80211_vif *vif = ctx->vif; - struct iwl_host_cmd hcmd = { - .id = REPLY_CHANNEL_SWITCH, -- .len = { sizeof(cmd), }, -+ .len = { sizeof(*cmd), }, - .flags = CMD_SYNC, -- .data = { &cmd, }, -+ .dataflags[0] = IWL_HCMD_DFL_NOCOPY, - }; -+ int err; - -- cmd.band = priv->band == IEEE80211_BAND_2GHZ; -+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); -+ if (!cmd) -+ return -ENOMEM; -+ -+ hcmd.data[0] = cmd; -+ -+ cmd->band = priv->band == IEEE80211_BAND_2GHZ; - ch = ch_switch->channel->hw_value; - IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", - ctx->active.channel, ch); -- cmd.channel = cpu_to_le16(ch); -- cmd.rxon_flags = ctx->staging.flags; -- cmd.rxon_filter_flags = ctx->staging.filter_flags; -+ cmd->channel = cpu_to_le16(ch); -+ cmd->rxon_flags = ctx->staging.flags; -+ cmd->rxon_filter_flags = ctx->staging.filter_flags; - switch_count = ch_switch->count; - tsf_low = ch_switch->timestamp & 0x0ffffffff; - /* -@@ -554,23 +561,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, - switch_count = 0; - } - if (switch_count <= 1) -- cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); -+ cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time); - else { - switch_time_in_usec = - vif->bss_conf.beacon_int * switch_count * TIME_UNIT; - ucode_switch_time = iwl_usecs_to_beacons(priv, - switch_time_in_usec, - beacon_interval); -- cmd.switch_time = iwl_add_beacon_time(priv, -- priv->ucode_beacon_time, -- ucode_switch_time, -- beacon_interval); -+ cmd->switch_time = iwl_add_beacon_time(priv, -+ priv->ucode_beacon_time, -+ ucode_switch_time, -+ beacon_interval); - } - IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", -- cmd.switch_time); -- cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; -+ cmd->switch_time); -+ cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; - -- return iwl_dvm_send_cmd(priv, &hcmd); -+ err = iwl_dvm_send_cmd(priv, &hcmd); -+ kfree(cmd); -+ return err; - } - - struct iwl_lib_ops iwl6000_lib = { diff --git a/kernel.spec b/kernel.spec index 1055b514a..8cbcf4237 100644 --- a/kernel.spec +++ b/kernel.spec @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 4 +%define stable_update 5 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -681,15 +681,6 @@ Patch21300: unhandled-irqs-switch-to-polling.patch #rhbz 804957 CVE-2012-1568 Patch21306: shlib_base_randomize.patch -#rhbz 770484 -Patch22071: iwlwifi-fix-6000-ch-switch.patch - -#rhbz 862168 -Patch22073: mac80211_local_deauth_v3.6.patch - -#rhbz 866013 -Patch22074: mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch - #rhbz 867344 Patch22077: dont-call-cifs_lookup-on-hashed-negative-dentry.patch @@ -1316,15 +1307,6 @@ ApplyPatch unhandled-irqs-switch-to-polling.patch ApplyPatch weird-root-dentry-name-debug.patch ApplyPatch debug-808990.patch -#rhbz 770484 -ApplyPatch iwlwifi-fix-6000-ch-switch.patch - -#rhbz 862168 -ApplyPatch mac80211_local_deauth_v3.6.patch - -#rhbz 866013 -ApplyPatch mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch - #rhbz 867344 ApplyPatch dont-call-cifs_lookup-on-hashed-negative-dentry.patch @@ -2045,6 +2027,9 @@ fi # and build. %changelog +* Wed Oct 30 2012 Justin M. Forbes 3.6.5-1 +- Linux 3.6.5 + * Wed Oct 30 2012 Josh Boyer - CVE-2012-4565 net: divide by zero in tcp algorithm illinois (rhbz 871848 871923) diff --git a/mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch b/mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch deleted file mode 100644 index 8c46db671..000000000 --- a/mac80211-connect-with-HT20-if-HT40-is-not-permitted.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 3a40414f826a8f1096d9b94c4a53ef91b25ba28d Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Mon, 1 Oct 2012 15:52:00 +0200 -Subject: [PATCH] mac80211: connect with HT20 if HT40 is not permitted - -Some changes to fix issues with HT40 APs in Korea -and follow-up changes to allow using HT40 even if -the local regulatory database disallows it caused -issues with iwlwifi (and could cause issues with -other devices); iwlwifi firmware would assert if -you tried to connect to an AP that has an invalid -configuration (e.g. using HT40- on channel 140.) - -Fix this, while avoiding the "Korean AP" issue by -disabling HT40 and advertising HT20 to the AP -when connecting. - -Cc: stable@vger.kernel.org [3.6] -Reported-by: Florian Reitmeir -Tested-by: Florian Reitmeir -Signed-off-by: Johannes Berg ---- - net/mac80211/mlme.c | 30 ++++++++++++++++++++---------- - 1 files changed, 20 insertions(+), 10 deletions(-) - -diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index e510a33..1b7eed2 100644 ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -3099,22 +3099,32 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, - ht_cfreq, ht_oper->primary_chan, - cbss->channel->band); - ht_oper = NULL; -+ } else { -+ channel_type = NL80211_CHAN_HT20; - } - } - -- if (ht_oper) { -- channel_type = NL80211_CHAN_HT20; -+ if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { -+ /* -+ * cfg80211 already verified that the channel itself can -+ * be used, but it didn't check that we can do the right -+ * HT type, so do that here as well. If HT40 isn't allowed -+ * on this channel, disable 40 MHz operation. -+ */ - -- if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { -- switch (ht_oper->ht_param & -- IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { -- case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: -+ switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { -+ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: -+ if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS) -+ ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; -+ else - channel_type = NL80211_CHAN_HT40PLUS; -- break; -- case IEEE80211_HT_PARAM_CHA_SEC_BELOW: -+ break; -+ case IEEE80211_HT_PARAM_CHA_SEC_BELOW: -+ if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS) -+ ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; -+ else - channel_type = NL80211_CHAN_HT40MINUS; -- break; -- } -+ break; - } - } - --- -1.7.6.5 - diff --git a/mac80211_local_deauth_v3.6.patch b/mac80211_local_deauth_v3.6.patch deleted file mode 100644 index 3b634860f..000000000 --- a/mac80211_local_deauth_v3.6.patch +++ /dev/null @@ -1,66 +0,0 @@ -diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h -index 3d254e1..f10553c 100644 ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -1217,6 +1217,7 @@ struct cfg80211_deauth_request { - const u8 *ie; - size_t ie_len; - u16 reason_code; -+ bool local_state_change; - }; - - /** -diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index f76b833..08343c2 100644 ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -3457,6 +3457,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, - { - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - u8 frame_buf[DEAUTH_DISASSOC_LEN]; -+ bool tx = !req->local_state_change; - - mutex_lock(&ifmgd->mtx); - -@@ -3473,12 +3474,11 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, - if (ifmgd->associated && - ether_addr_equal(ifmgd->associated->bssid, req->bssid)) - ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, -- req->reason_code, true, frame_buf); -+ req->reason_code, tx, frame_buf); - else - ieee80211_send_deauth_disassoc(sdata, req->bssid, - IEEE80211_STYPE_DEAUTH, -- req->reason_code, true, -- frame_buf); -+ req->reason_code, tx, frame_buf); - mutex_unlock(&ifmgd->mtx); - - __cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); -diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c -index 1cdb1d5..0877efb 100644 ---- a/net/wireless/mlme.c -+++ b/net/wireless/mlme.c -@@ -457,21 +457,11 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, - .reason_code = reason, - .ie = ie, - .ie_len = ie_len, -+ .local_state_change = local_state_change, - }; - - ASSERT_WDEV_LOCK(wdev); - -- if (local_state_change) { -- if (wdev->current_bss && -- ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { -- cfg80211_unhold_bss(wdev->current_bss); -- cfg80211_put_bss(&wdev->current_bss->pub); -- wdev->current_bss = NULL; -- } -- -- return 0; -- } -- - return rdev->ops->deauth(&rdev->wiphy, dev, &req); - } - diff --git a/sources b/sources index 965397c16..3800ac99f 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -d7efab4da2682c44662b684026b059f7 patch-3.6.4.xz +6ad8ceebb9b5c1bf69a0c07ef7cc81f2 patch-3.6.5.xz From f1948ae3be76593ffe22c6b0181d544b1ab0a578 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 31 Oct 2012 22:36:04 -0500 Subject: [PATCH 454/487] Fix i82975x_edac OOPS (BZ#848149) --- config-powerpc-generic | 1 - config-x86-generic | 1 - i82975x-edac-fix.patch | 855 +++++++++++++++++++++++++++++++++++++++++ kernel.spec | 9 +- 4 files changed, 863 insertions(+), 3 deletions(-) create mode 100644 i82975x-edac-fix.patch diff --git a/config-powerpc-generic b/config-powerpc-generic index 90120de7c..063d8f764 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -176,7 +176,6 @@ CONFIG_PMAC_APM_EMU=m CONFIG_HW_RANDOM_PASEMI=m CONFIG_EDAC=y -# CONFIG_EDAC_DEBUG is not set CONFIG_EDAC_MM_EDAC=m CONFIG_EDAC_PASEMI=m CONFIG_EDAC_AMD8131=m diff --git a/config-x86-generic b/config-x86-generic index de4fbd5cf..77f95933a 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -146,7 +146,6 @@ CONFIG_DELL_RBU=m CONFIG_DCDBAS=m CONFIG_EDAC=y -# CONFIG_EDAC_DEBUG is not set CONFIG_EDAC_MM_EDAC=m CONFIG_EDAC_AMD76X=m CONFIG_EDAC_AMD8111=m diff --git a/i82975x-edac-fix.patch b/i82975x-edac-fix.patch new file mode 100644 index 000000000..f44ac7791 --- /dev/null +++ b/i82975x-edac-fix.patch @@ -0,0 +1,855 @@ +commit 9370a8d717720f6b17221490fea8d798396d9f2f +Author: Mauro Carvalho Chehab +Date: Mon Oct 15 21:49:35 2012 -0300 + + i82975x_edac: Use the edac standard debug macro + + Instead of declaring its own debug macro, that requires + to uncomment part of the code, use the edac standard macro + to add the debug code, and the edac debug level to print it, + just like any other EDAC driver. + + Signed-off-by: Mauro Carvalho Chehab + +diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c +index a980204..f998d2c 100644 +--- a/drivers/edac/i82975x_edac.c ++++ b/drivers/edac/i82975x_edac.c +@@ -435,11 +435,9 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, + } + } + +-/* #define i82975x_DEBUG_IOMEM */ +- +-#ifdef i82975x_DEBUG_IOMEM +-static void i82975x_print_dram_timings(void __iomem *mch_window) ++static void i82975x_print_dram_config(void __iomem *mch_window, u32 mchbar, u32 *drc) + { ++#ifdef CONFIG_EDAC_DEBUG + /* + * The register meanings are from Intel specs; + * (shows 13-5-5-5 for 800-DDR2) +@@ -448,26 +446,63 @@ static void i82975x_print_dram_timings(void __iomem *mch_window) + */ + static const int caslats[4] = { 5, 4, 3, 6 }; + u32 dtreg[2]; ++ u8 c0drb[4]; ++ u8 c1drb[4]; ++ ++ if (!edac_debug_level) ++ return; ++ ++ i82975x_printk(KERN_INFO, "MCHBAR real = %0x, remapped = %p\n", ++ mchbar, mch_window); ++ ++ c0drb[0] = readb(mch_window + I82975X_DRB_CH0R0); ++ c0drb[1] = readb(mch_window + I82975X_DRB_CH0R1); ++ c0drb[2] = readb(mch_window + I82975X_DRB_CH0R2); ++ c0drb[3] = readb(mch_window + I82975X_DRB_CH0R3); ++ c1drb[0] = readb(mch_window + I82975X_DRB_CH1R0); ++ c1drb[1] = readb(mch_window + I82975X_DRB_CH1R1); ++ c1drb[2] = readb(mch_window + I82975X_DRB_CH1R2); ++ c1drb[3] = readb(mch_window + I82975X_DRB_CH1R3); ++ i82975x_printk(KERN_INFO, "DRBCH0R0 = 0x%02x\n", c0drb[0]); ++ i82975x_printk(KERN_INFO, "DRBCH0R1 = 0x%02x\n", c0drb[1]); ++ i82975x_printk(KERN_INFO, "DRBCH0R2 = 0x%02x\n", c0drb[2]); ++ i82975x_printk(KERN_INFO, "DRBCH0R3 = 0x%02x\n", c0drb[3]); ++ i82975x_printk(KERN_INFO, "DRBCH1R0 = 0x%02x\n", c1drb[0]); ++ i82975x_printk(KERN_INFO, "DRBCH1R1 = 0x%02x\n", c1drb[1]); ++ i82975x_printk(KERN_INFO, "DRBCH1R2 = 0x%02x\n", c1drb[2]); ++ i82975x_printk(KERN_INFO, "DRBCH1R3 = 0x%02x\n", c1drb[3]); ++ ++ i82975x_printk(KERN_INFO, "DRC_CH0 = %0x, %s\n", drc[0], ++ ((drc[0] >> 21) & 3) == 1 ? ++ "ECC enabled" : "ECC disabled"); ++ i82975x_printk(KERN_INFO, "DRC_CH1 = %0x, %s\n", drc[1], ++ ((drc[1] >> 21) & 3) == 1 ? ++ "ECC enabled" : "ECC disabled"); ++ ++ i82975x_printk(KERN_INFO, "C0 BNKARC = %0x\n", ++ readw(mch_window + I82975X_C0BNKARC)); ++ i82975x_printk(KERN_INFO, "C1 BNKARC = %0x\n", ++ readw(mch_window + I82975X_C1BNKARC)); + + dtreg[0] = readl(mch_window + 0x114); + dtreg[1] = readl(mch_window + 0x194); +- i82975x_printk(KERN_INFO, "DRAM Timings : Ch0 Ch1\n" ++ i82975x_printk(KERN_INFO, ++ "DRAM Timings : Ch0 Ch1\n" + " RAS Active Min = %d %d\n" + " CAS latency = %d %d\n" + " RAS to CAS = %d %d\n" + " RAS precharge = %d %d\n", + (dtreg[0] >> 19 ) & 0x0f, +- (dtreg[1] >> 19) & 0x0f, ++ (dtreg[1] >> 19) & 0x0f, + caslats[(dtreg[0] >> 8) & 0x03], +- caslats[(dtreg[1] >> 8) & 0x03], ++ caslats[(dtreg[1] >> 8) & 0x03], + ((dtreg[0] >> 4) & 0x07) + 2, +- ((dtreg[1] >> 4) & 0x07) + 2, ++ ((dtreg[1] >> 4) & 0x07) + 2, + (dtreg[0] & 0x07) + 2, +- (dtreg[1] & 0x07) + 2 ++ (dtreg[1] & 0x07) + 2 + ); +- +-} + #endif ++} + + static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) + { +@@ -480,10 +515,6 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) + u32 drc[2]; + struct i82975x_error_info discard; + int chans; +-#ifdef i82975x_DEBUG_IOMEM +- u8 c0drb[4]; +- u8 c1drb[4]; +-#endif + + edac_dbg(0, "\n"); + +@@ -495,45 +526,11 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) + mchbar &= 0xffffc000; /* bits 31:14 used for 16K window */ + mch_window = ioremap_nocache(mchbar, 0x1000); + +-#ifdef i82975x_DEBUG_IOMEM +- i82975x_printk(KERN_INFO, "MCHBAR real = %0x, remapped = %p\n", +- mchbar, mch_window); +- +- c0drb[0] = readb(mch_window + I82975X_DRB_CH0R0); +- c0drb[1] = readb(mch_window + I82975X_DRB_CH0R1); +- c0drb[2] = readb(mch_window + I82975X_DRB_CH0R2); +- c0drb[3] = readb(mch_window + I82975X_DRB_CH0R3); +- c1drb[0] = readb(mch_window + I82975X_DRB_CH1R0); +- c1drb[1] = readb(mch_window + I82975X_DRB_CH1R1); +- c1drb[2] = readb(mch_window + I82975X_DRB_CH1R2); +- c1drb[3] = readb(mch_window + I82975X_DRB_CH1R3); +- i82975x_printk(KERN_INFO, "DRBCH0R0 = 0x%02x\n", c0drb[0]); +- i82975x_printk(KERN_INFO, "DRBCH0R1 = 0x%02x\n", c0drb[1]); +- i82975x_printk(KERN_INFO, "DRBCH0R2 = 0x%02x\n", c0drb[2]); +- i82975x_printk(KERN_INFO, "DRBCH0R3 = 0x%02x\n", c0drb[3]); +- i82975x_printk(KERN_INFO, "DRBCH1R0 = 0x%02x\n", c1drb[0]); +- i82975x_printk(KERN_INFO, "DRBCH1R1 = 0x%02x\n", c1drb[1]); +- i82975x_printk(KERN_INFO, "DRBCH1R2 = 0x%02x\n", c1drb[2]); +- i82975x_printk(KERN_INFO, "DRBCH1R3 = 0x%02x\n", c1drb[3]); +-#endif +- + drc[0] = readl(mch_window + I82975X_DRC_CH0M0); + drc[1] = readl(mch_window + I82975X_DRC_CH1M0); +-#ifdef i82975x_DEBUG_IOMEM +- i82975x_printk(KERN_INFO, "DRC_CH0 = %0x, %s\n", drc[0], +- ((drc[0] >> 21) & 3) == 1 ? +- "ECC enabled" : "ECC disabled"); +- i82975x_printk(KERN_INFO, "DRC_CH1 = %0x, %s\n", drc[1], +- ((drc[1] >> 21) & 3) == 1 ? +- "ECC enabled" : "ECC disabled"); + +- i82975x_printk(KERN_INFO, "C0 BNKARC = %0x\n", +- readw(mch_window + I82975X_C0BNKARC)); +- i82975x_printk(KERN_INFO, "C1 BNKARC = %0x\n", +- readw(mch_window + I82975X_C1BNKARC)); +- i82975x_print_dram_timings(mch_window); +- goto fail1; +-#endif ++ i82975x_print_dram_config(mch_window, mchbar, drc); ++ + if (!(((drc[0] >> 21) & 3) == 1 || ((drc[1] >> 21) & 3) == 1)) { + i82975x_printk(KERN_INFO, "ECC disabled on both channels.\n"); + goto fail1; + +commit 8992ed2f4295eab137e1713fa16be5546a759373 +Author: Mauro Carvalho Chehab +Date: Mon Oct 15 21:48:48 2012 -0300 + + i82975x_edac: Fix dimm label initialization + + The driver has only 4 hardcoded labels, but allows much more memory. + Fix it by removing the hardcoded logic, using snprintf() instead. + + [ 19.833972] general protection fault: 0000 [#1] SMP + [ 19.837733] Modules linked in: i82975x_edac(+) edac_core firewire_ohci firewire_core crc_itu_t nouveau mxm_wmi wmi video i2c_algo_bit drm_kms_helper ttm drm i2c_core + [ 19.837733] CPU 0 + [ 19.837733] Pid: 390, comm: udevd Not tainted 3.6.1-1.fc17.x86_64.debug #1 Dell Inc. Precision WorkStation 390 /0MY510 + [ 19.837733] RIP: 0010:[] [] strncpy+0x18/0x30 + [ 19.837733] RSP: 0018:ffff880078535b68 EFLAGS: 00010202 + [ 19.837733] RAX: ffff880069fa9708 RBX: ffff880078588000 RCX: ffff880069fa9708 + [ 19.837733] RDX: 000000000000001f RSI: 5f706f5f63616465 RDI: ffff880069fa9708 + [ 19.837733] RBP: ffff880078535b68 R08: ffff880069fa9727 R09: 000000000000fffe + [ 19.837733] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000003 + [ 19.837733] R13: 0000000000000000 R14: ffff880069fa9290 R15: ffff880079624a80 + [ 19.837733] FS: 00007f3de01ee840(0000) GS:ffff88007c400000(0000) knlGS:0000000000000000 + [ 19.837733] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + [ 19.837733] CR2: 00007f3de00b9000 CR3: 0000000078dbc000 CR4: 00000000000007f0 + [ 19.837733] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 + [ 19.837733] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 + [ 19.837733] Process udevd (pid: 390, threadinfo ffff880078534000, task ffff880079642450) + [ 19.837733] Stack: + [ 19.837733] ffff880078535c18 ffffffffa017c6b8 00040000816d627f ffff880079624a88 + [ 19.837733] ffffc90004cd6000 ffff880079624520 ffff88007ac21148 0000000000000000 + [ 19.837733] 0000000000000000 0004000000000000 feda000078535bc8 ffffffff810d696d + [ 19.837733] Call Trace: + [ 19.837733] [] i82975x_init_one+0x2e6/0x3e6 [i82975x_edac] + ... + + Fix bug reported at: + https://bugzilla.redhat.com/show_bug.cgi?id=848149 + And, very likely: + https://bbs.archlinux.org/viewtopic.php?id=148033 + https://bugzilla.kernel.org/show_bug.cgi?id=47171 + + Cc: Alan Cox + Signed-off-by: Mauro Carvalho Chehab + +diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c +index 069e26c..a980204 100644 +--- a/drivers/edac/i82975x_edac.c ++++ b/drivers/edac/i82975x_edac.c +@@ -370,10 +370,6 @@ static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank) + static void i82975x_init_csrows(struct mem_ctl_info *mci, + struct pci_dev *pdev, void __iomem *mch_window) + { +- static const char *labels[4] = { +- "DIMM A1", "DIMM A2", +- "DIMM B1", "DIMM B2" +- }; + struct csrow_info *csrow; + unsigned long last_cumul_size; + u8 value; +@@ -423,9 +419,10 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, + dimm = mci->csrows[index]->channels[chan]->dimm; + + dimm->nr_pages = nr_pages / csrow->nr_channels; +- strncpy(csrow->channels[chan]->dimm->label, +- labels[(index >> 1) + (chan * 2)], +- EDAC_MC_LABEL_LEN); ++ ++ snprintf(csrow->channels[chan]->dimm->label, EDAC_MC_LABEL_LEN, "DIMM %c%d", ++ (chan == 0) ? 'A' : 'B', ++ index); + dimm->grain = 1 << 7; /* 128Byte cache-line resolution */ + dimm->dtype = i82975x_dram_type(mch_window, index); + dimm->mtype = MEM_DDR2; /* I82975x supports only DDR2 */ +commit 6e7636c972951ba0c6c640758b1dcc7667cb2415 +Author: Mauro Carvalho Chehab +Date: Tue Oct 16 15:30:23 2012 -0300 + + i82975x_edac: rewrite the entire fill/report logic + + There are so many bugs at the fill/error report logic that + the code ended by being re-written. + + Issues solved: + + - DIMM labels were "randomly" filled: they won't + match the memory layout, due to a series of bugs on it; + + - The memory controller supports 3 different modes: + single, dual interleaved and dual async. The logic there were + written considering the dual interleaved one (yet, some + single mode support was there); + + - The boundary limit to decide on each channel the error happens, + at dual interleaved mode, is given by bit 6 of the error address, + and not bit 1. The practical effect is that Corrected errors + will have a 50% of chance of pointing to the right DIMM. Only + the DIMM pair logic were OK; + + - The asymetric mode weren't properly supported. The driver would + handle an asymetric mode as 'single mode', with doesn't actually + match it, creating some weird real/virtual DIMM mappings. + + - Some other random bugs got fixed. + + Tested on a Dell Precision N390, on dual interleaved mode. + + Signed-off-by: Mauro Carvalho Chehab + +diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c +index f998d2c..082e91e 100644 +--- a/drivers/edac/i82975x_edac.c ++++ b/drivers/edac/i82975x_edac.c +@@ -6,7 +6,17 @@ + * GNU General Public License. + * + * Written by Arvind R. +- * Copied from i82875p_edac.c source: ++ * Copied from i82875p_edac.c source, ++ * ++ * (c) 2012 Mauro Carvalho Chehab ++ * Driver re-written in order to fix lots of issues on it: ++ * - Fix Single Mode; ++ * - Add support for Asymetrical mode ++ * - Fix several issues with Interleaved mode ++ * - Fix memory label logic ++ * ++ * Intel datasheet: Intel(R) 975X Express Chipset Datasheet ++ * http://www.intel.com/assets/pdf/datasheet/310158.pdf + */ + + #include +@@ -29,8 +39,8 @@ + #define PCI_DEVICE_ID_INTEL_82975_0 0x277c + #endif /* PCI_DEVICE_ID_INTEL_82975_0 */ + +-#define I82975X_NR_DIMMS 8 +-#define I82975X_NR_CSROWS(nr_chans) (I82975X_NR_DIMMS / (nr_chans)) ++#define DIMMS_PER_CHANNEL 4 ++#define NUM_CHANNELS 2 + + /* Intel 82975X register addresses - device 0 function 0 - DRAM Controller */ + #define I82975X_EAP 0x58 /* Dram Error Address Pointer (32b) +@@ -112,7 +122,7 @@ NOTE: Only ONE of the three must be enabled + /* NOTE: Following addresses have to indexed using MCHBAR offset (44h, 32b) */ + /* Intel 82975x memory mapped register space */ + +-#define I82975X_DRB_SHIFT 25 /* fixed 32MiB grain */ ++#define I82975X_DRB_SHIFT 25 /* fixed 2^25 = 32 MiB grain */ + + #define I82975X_DRB 0x100 /* DRAM Row Boundary (8b x 8) + * +@@ -152,6 +162,10 @@ NOTE: Only ONE of the three must be enabled + #define I82975X_DRA_CH1R01 0x188 + #define I82975X_DRA_CH1R23 0x189 + ++/* Channels 0/1 DRAM Timing Register 1 */ ++#define I82975X_C0DRT1 0x114 ++#define I82975X_C1DRT1 0x194 ++ + + #define I82975X_BNKARC 0x10e /* Type of device in each rank - Bank Arch (16b) + * +@@ -206,8 +220,16 @@ enum i82975x_chips { + I82975X = 0, + }; + ++struct mem_range { ++ u32 start, end; ++}; ++ + struct i82975x_pvt { +- void __iomem *mch_window; ++ void __iomem *mch_window; ++ int num_channels; ++ bool is_symetric; ++ u8 drb[DIMMS_PER_CHANNEL][NUM_CHANNELS]; ++ struct mem_range page[DIMMS_PER_CHANNEL][NUM_CHANNELS]; + }; + + struct i82975x_dev_info { +@@ -278,8 +300,10 @@ static void i82975x_get_error_info(struct mem_ctl_info *mci, + static int i82975x_process_error_info(struct mem_ctl_info *mci, + struct i82975x_error_info *info, int handle_errors) + { +- int row, chan; +- unsigned long offst, page; ++ struct i82975x_pvt *pvt = mci->pvt_info; ++ struct mem_range *range; ++ unsigned int row, chan, grain; ++ unsigned long offst, page; + + if (!(info->errsts2 & 0x0003)) + return 0; +@@ -293,36 +317,70 @@ static int i82975x_process_error_info(struct mem_ctl_info *mci, + info->errsts = info->errsts2; + } + ++ /* Calculate page and offset of the error */ ++ + page = (unsigned long) info->eap; + page >>= 1; ++ + if (info->xeap & 1) + page |= 0x80000000; + page >>= (PAGE_SHIFT - 1); +- row = edac_mc_find_csrow_by_page(mci, page); +- +- if (row == -1) { +- i82975x_mc_printk(mci, KERN_ERR, "error processing EAP:\n" +- "\tXEAP=%u\n" +- "\t EAP=0x%08x\n" +- "\tPAGE=0x%08x\n", +- (info->xeap & 1) ? 1 : 0, info->eap, (unsigned int) page); +- return 0; ++ ++ if (pvt->is_symetric) ++ grain = 1 << 7; ++ else ++ grain = 1 << 6; ++ ++ offst = info->eap & ((1 << PAGE_SHIFT) - (1 << grain)); ++ ++ /* ++ * Search for the DIMM chip that match the error page. ++ * ++ * On Symmetric mode, this will always return channel = 0, as ++ * both channel A and B ranges are identical. ++ * A latter logic will determinte the channel on symetric mode ++ * ++ * On asymetric mode or single mode, there will be just one match, ++ * that will point to the csrow with the error. ++ */ ++ for (chan = 0; chan < pvt->num_channels; chan++) { ++ for (row = 0; row < DIMMS_PER_CHANNEL; row++) { ++ range = &pvt->page[row][chan]; ++ ++ if (page >= range->start && page <= range->end) ++ goto found; ++ } + } +- chan = (mci->csrows[row]->nr_channels == 1) ? 0 : info->eap & 1; +- offst = info->eap +- & ((1 << PAGE_SHIFT) - +- (1 << mci->csrows[row]->channels[chan]->dimm->grain)); ++ chan = -1; ++ row = -1; + +- if (info->errsts & 0x0002) ++found: ++ if (info->errsts & 0x0002) { ++ /* ++ * On uncorrected error, ECC doesn't allow do determine the ++ * channel where the error has occurred. ++ */ + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, + page, offst, 0, + row, -1, -1, + "i82975x UE", ""); +- else +- edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, +- page, offst, info->derrsyn, +- row, chan ? chan : 0, -1, +- "i82975x CE", ""); ++ return 1; ++ } ++ ++ if (pvt->is_symetric && row >= 0) { ++ /* ++ * On Symetric mode, the memory switch happens after each ++ * cache line (64 byte boundary). Channel 0 goes first. ++ */ ++ if (info->eap & (1 << 6)) ++ chan = 1; ++ else ++ chan = 0; ++ } ++ edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, ++ page, offst, info->derrsyn, ++ row, chan, -1, ++ "i82975x CE", ""); + + return 1; + } +@@ -331,111 +389,143 @@ static void i82975x_check(struct mem_ctl_info *mci) + { + struct i82975x_error_info info; + +- edac_dbg(1, "MC%d\n", mci->mc_idx); ++ edac_dbg(4, "MC%d\n", mci->mc_idx); + i82975x_get_error_info(mci, &info); + i82975x_process_error_info(mci, &info, 1); + } + +-/* Return 1 if dual channel mode is active. Else return 0. */ +-static int dual_channel_active(void __iomem *mch_window) ++/** ++ * detect_memory_style - Detect on what mode the memory controller is programmed ++ * ++ * @pvt: pointer to the private structure ++ * ++ * This function detects how many channels are in use, and if the memory ++ * controller is in symetric (interleaved) or asymetric mode. There's no ++ * need to distinguish between asymetric and single mode, as the routines ++ * that fill the csrows data and handle error are written in order to handle ++ * both at the same way. ++ */ ++static void detect_memory_style(struct i82975x_pvt *pvt) + { +- /* +- * We treat interleaved-symmetric configuration as dual-channel - EAP's +- * bit-0 giving the channel of the error location. +- * +- * All other configurations are treated as single channel - the EAP's +- * bit-0 will resolve ok in symmetric area of mixed +- * (symmetric/asymmetric) configurations +- */ +- u8 drb[4][2]; + int row; +- int dualch; ++ bool has_chan_a = false; ++ bool has_chan_b = false; ++ ++ pvt->is_symetric = true; ++ pvt->num_channels = 0; ++ ++ for (row = 0; row < DIMMS_PER_CHANNEL; row++) { ++ pvt->drb[row][0] = readb(pvt->mch_window + I82975X_DRB + row); ++ pvt->drb[row][1] = readb(pvt->mch_window + I82975X_DRB + row + 0x80); ++ ++ /* On symetric mode, both channels have the same boundaries */ ++ if (pvt->drb[row][0] != pvt->drb[row][1]) ++ pvt->is_symetric = false; + +- for (dualch = 1, row = 0; dualch && (row < 4); row++) { +- drb[row][0] = readb(mch_window + I82975X_DRB + row); +- drb[row][1] = readb(mch_window + I82975X_DRB + row + 0x80); +- dualch = dualch && (drb[row][0] == drb[row][1]); ++ if (pvt->drb[row][0]) ++ has_chan_a = true; ++ if (pvt->drb[row][1]) ++ has_chan_b = true; + } +- return dualch; +-} + +-static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank) +-{ +- /* +- * ECC is possible on i92975x ONLY with DEV_X8 +- */ +- return DEV_X8; ++ if (has_chan_a) ++ pvt->num_channels++; ++ ++ if (has_chan_b) ++ pvt->num_channels++; + } + + static void i82975x_init_csrows(struct mem_ctl_info *mci, +- struct pci_dev *pdev, void __iomem *mch_window) ++ struct i82975x_pvt *pvt, ++ struct pci_dev *pdev) + { +- struct csrow_info *csrow; +- unsigned long last_cumul_size; +- u8 value; +- u32 cumul_size, nr_pages; +- int index, chan; +- struct dimm_info *dimm; +- enum dev_type dtype; +- +- last_cumul_size = 0; ++ struct dimm_info *dimm; ++ struct mem_range *range; ++ u8 boundary; ++ u32 initial_page = 0, last_page; ++ int row, chan; + + /* +- * 82875 comment: +- * The dram row boundary (DRB) reg values are boundary address +- * for each DRAM row with a granularity of 32 or 64MB (single/dual +- * channel operation). DRB regs are cumulative; therefore DRB7 will +- * contain the total memory contained in all rows. +- * ++ * This chipset provides 3 address modes: ++ * Single channel - either Channel A or channel B is filled ++ * Dual channel, interleaved: Memory is organized in pairs, ++ * where channel A gets the lower address for each pair ++ * Dual channel, asymmetric: Channel A memory goes first. ++ * In order to cover all modes, we need to start describing ++ * memories considering the dual channel, asymmetric one. + */ + +- for (index = 0; index < mci->nr_csrows; index++) { +- csrow = mci->csrows[index]; +- +- value = readb(mch_window + I82975X_DRB + index + +- ((index >= 4) ? 0x80 : 0)); +- cumul_size = value; +- cumul_size <<= (I82975X_DRB_SHIFT - PAGE_SHIFT); +- /* +- * Adjust cumul_size w.r.t number of channels +- * +- */ +- if (csrow->nr_channels > 1) +- cumul_size <<= 1; +- edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size); +- +- nr_pages = cumul_size - last_cumul_size; +- if (!nr_pages) +- continue; +- ++ for (chan = 0; chan < pvt->num_channels; chan++) { + /* +- * Initialise dram labels +- * index values: +- * [0-7] for single-channel; i.e. csrow->nr_channels = 1 +- * [0-3] for dual-channel; i.e. csrow->nr_channels = 2 ++ * On symetric mode, both channels start from address 0 + */ +- dtype = i82975x_dram_type(mch_window, index); +- for (chan = 0; chan < csrow->nr_channels; chan++) { +- dimm = mci->csrows[index]->channels[chan]->dimm; +- +- dimm->nr_pages = nr_pages / csrow->nr_channels; +- +- snprintf(csrow->channels[chan]->dimm->label, EDAC_MC_LABEL_LEN, "DIMM %c%d", +- (chan == 0) ? 'A' : 'B', +- index); +- dimm->grain = 1 << 7; /* 128Byte cache-line resolution */ +- dimm->dtype = i82975x_dram_type(mch_window, index); ++ if (pvt->is_symetric) ++ initial_page = 0; ++ ++ for (row = 0; row < DIMMS_PER_CHANNEL; row++) { ++ boundary = pvt->drb[row][chan]; ++ dimm = mci->csrows[row]->channels[chan]->dimm; ++ ++ last_page = boundary << (I82975X_DRB_SHIFT - PAGE_SHIFT); ++ dimm->nr_pages = last_page - initial_page; ++ if (!dimm->nr_pages) ++ continue; ++ ++ range = &pvt->page[row][chan]; ++ range->start = initial_page; ++ range->end = range->start + dimm->nr_pages - 1; ++ ++ /* ++ * Grain is one cache-line: ++ * On dual symetric mode, it is 128 Bytes; ++ * On single mode or asymetric, it is 64 bytes. ++ */ ++ if (pvt->is_symetric) { ++ dimm->grain = 1 << 7; ++ ++ /* ++ * In dual interleaved mode, the addresses ++ * need to be multiplied by 2, as both ++ * channels are interlaced, and the boundary ++ * limit there actually match each DIMM size ++ */ ++ range->start <<= 1; ++ range->end <<= 1; ++ } else { ++ dimm->grain = 1 << 6; ++ } ++ ++ snprintf(dimm->label, ++ EDAC_MC_LABEL_LEN, "DIMM %c%d", ++ (chan == 0) ? 'A' : 'B', row); + dimm->mtype = MEM_DDR2; /* I82975x supports only DDR2 */ + dimm->edac_mode = EDAC_SECDED; /* only supported */ +- } + +- csrow->first_page = last_cumul_size; +- csrow->last_page = cumul_size - 1; +- last_cumul_size = cumul_size; ++ /* ++ * This chipset supports both x8 and x16 memories, ++ * but datasheet doesn't describe how to distinguish ++ * between them. ++ * ++ * Also, the "Rank" comment at initial_page 17 says that ++ * ECC is only available with x8 memories. As this ++ * driver doesn't even initialize without ECC, better ++ * to assume that everything is x8. This is not ++ * actually true, on a mixed ECC/non-ECC scenario. ++ */ ++ dimm->dtype = DEV_X8; ++ ++ edac_dbg(1, ++ "%s: from page 0x%08x to 0x%08x (size: 0x%08x pages)\n", ++ dimm->label, ++ range->start, range->end, ++ dimm->nr_pages); ++ initial_page = last_page; ++ } + } + } + +-static void i82975x_print_dram_config(void __iomem *mch_window, u32 mchbar, u32 *drc) ++static void i82975x_print_dram_config(struct i82975x_pvt *pvt, ++ u32 mchbar, u32 *drc) + { + #ifdef CONFIG_EDAC_DEBUG + /* +@@ -444,63 +534,57 @@ static void i82975x_print_dram_config(void __iomem *mch_window, u32 mchbar, u32 + * Asus P5W Bios reports 15-5-4-4 + * What's your religion? + */ +- static const int caslats[4] = { 5, 4, 3, 6 }; +- u32 dtreg[2]; +- u8 c0drb[4]; +- u8 c1drb[4]; ++ static const int caslats[4] = { 5, 4, 3, 6 }; ++ u32 dtreg[2]; ++ int row; + ++ /* Show memory config if debug level is 1 or upper */ + if (!edac_debug_level) + return; + + i82975x_printk(KERN_INFO, "MCHBAR real = %0x, remapped = %p\n", +- mchbar, mch_window); +- +- c0drb[0] = readb(mch_window + I82975X_DRB_CH0R0); +- c0drb[1] = readb(mch_window + I82975X_DRB_CH0R1); +- c0drb[2] = readb(mch_window + I82975X_DRB_CH0R2); +- c0drb[3] = readb(mch_window + I82975X_DRB_CH0R3); +- c1drb[0] = readb(mch_window + I82975X_DRB_CH1R0); +- c1drb[1] = readb(mch_window + I82975X_DRB_CH1R1); +- c1drb[2] = readb(mch_window + I82975X_DRB_CH1R2); +- c1drb[3] = readb(mch_window + I82975X_DRB_CH1R3); +- i82975x_printk(KERN_INFO, "DRBCH0R0 = 0x%02x\n", c0drb[0]); +- i82975x_printk(KERN_INFO, "DRBCH0R1 = 0x%02x\n", c0drb[1]); +- i82975x_printk(KERN_INFO, "DRBCH0R2 = 0x%02x\n", c0drb[2]); +- i82975x_printk(KERN_INFO, "DRBCH0R3 = 0x%02x\n", c0drb[3]); +- i82975x_printk(KERN_INFO, "DRBCH1R0 = 0x%02x\n", c1drb[0]); +- i82975x_printk(KERN_INFO, "DRBCH1R1 = 0x%02x\n", c1drb[1]); +- i82975x_printk(KERN_INFO, "DRBCH1R2 = 0x%02x\n", c1drb[2]); +- i82975x_printk(KERN_INFO, "DRBCH1R3 = 0x%02x\n", c1drb[3]); +- +- i82975x_printk(KERN_INFO, "DRC_CH0 = %0x, %s\n", drc[0], ++ mchbar, pvt->mch_window); ++ ++ for (row = 0; row < DIMMS_PER_CHANNEL; row++) { ++ if (row) ++ /* Only show if at least one bank is filled */ ++ if ((pvt->drb[row][0] == pvt->drb[row-1][0]) && ++ (pvt->drb[row][1] == pvt->drb[row-1][1])) ++ continue; ++ ++ i82975x_printk(KERN_INFO, ++ "DRAM%i Rank Boundary Address: Channel A: 0x%08x; Channel B: 0x%08x\n", ++ row, ++ pvt->drb[row][0], ++ pvt->drb[row][1]); ++ } ++ ++ i82975x_printk(KERN_INFO, "DRAM Controller mode Channel A: = 0x%08x (%s); Channel B: 0x%08x (%s)\n", ++ drc[0], + ((drc[0] >> 21) & 3) == 1 ? +- "ECC enabled" : "ECC disabled"); +- i82975x_printk(KERN_INFO, "DRC_CH1 = %0x, %s\n", drc[1], ++ "ECC enabled" : "ECC disabled", ++ drc[1], + ((drc[1] >> 21) & 3) == 1 ? + "ECC enabled" : "ECC disabled"); + +- i82975x_printk(KERN_INFO, "C0 BNKARC = %0x\n", +- readw(mch_window + I82975X_C0BNKARC)); +- i82975x_printk(KERN_INFO, "C1 BNKARC = %0x\n", +- readw(mch_window + I82975X_C1BNKARC)); +- +- dtreg[0] = readl(mch_window + 0x114); +- dtreg[1] = readl(mch_window + 0x194); +- i82975x_printk(KERN_INFO, +- "DRAM Timings : Ch0 Ch1\n" +- " RAS Active Min = %d %d\n" +- " CAS latency = %d %d\n" +- " RAS to CAS = %d %d\n" +- " RAS precharge = %d %d\n", +- (dtreg[0] >> 19 ) & 0x0f, +- (dtreg[1] >> 19) & 0x0f, +- caslats[(dtreg[0] >> 8) & 0x03], +- caslats[(dtreg[1] >> 8) & 0x03], +- ((dtreg[0] >> 4) & 0x07) + 2, +- ((dtreg[1] >> 4) & 0x07) + 2, ++ i82975x_printk(KERN_INFO, "Bank Architecture Channel A: 0x%08x, Channel B: 0x%08x\n", ++ readw(pvt->mch_window + I82975X_C0BNKARC), ++ readw(pvt->mch_window + I82975X_C1BNKARC)); ++ ++ dtreg[0] = readl(pvt->mch_window + I82975X_C0DRT1); ++ dtreg[1] = readl(pvt->mch_window + I82975X_C1DRT1); ++ i82975x_printk(KERN_INFO, "DRAM Timings : ChA ChB\n"); ++ i82975x_printk(KERN_INFO, " RAS Active Min = %2d %2d\n", ++ (dtreg[0] >> 19 ) & 0x0f,(dtreg[1] >> 19) & 0x0f); ++ i82975x_printk(KERN_INFO, " CAS latency = %2d %2d\n", ++ caslats[(dtreg[0] >> 8) & 0x03], ++ caslats[(dtreg[1] >> 8) & 0x03]); ++ i82975x_printk(KERN_INFO, " RAS to CAS = %2d %2d\n", ++ ((dtreg[0] >> 4) & 0x07) + 2, ++ ((dtreg[1] >> 4) & 0x07) + 2); ++ i82975x_printk(KERN_INFO, " RAS precharge = %2d %2d\n", + (dtreg[0] & 0x07) + 2, +- (dtreg[1] & 0x07) + 2 +- ); ++ (dtreg[1] & 0x07) + 2); + #endif + } + +@@ -509,12 +593,10 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) + int rc = -ENODEV; + struct mem_ctl_info *mci; + struct edac_mc_layer layers[2]; +- struct i82975x_pvt *pvt; +- void __iomem *mch_window; ++ struct i82975x_pvt tmp_pvt, *pvt; + u32 mchbar; + u32 drc[2]; + struct i82975x_error_info discard; +- int chans; + + edac_dbg(0, "\n"); + +@@ -524,26 +606,35 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) + goto fail0; + } + mchbar &= 0xffffc000; /* bits 31:14 used for 16K window */ +- mch_window = ioremap_nocache(mchbar, 0x1000); ++ tmp_pvt.mch_window = ioremap_nocache(mchbar, 0x1000); ++ if (!tmp_pvt.mch_window) { ++ i82975x_printk(KERN_ERR, "Couldn't map MCHBAR registers.\n"); ++ rc = -ENOMEM; ++ goto fail0; ++ } + +- drc[0] = readl(mch_window + I82975X_DRC_CH0M0); +- drc[1] = readl(mch_window + I82975X_DRC_CH1M0); ++ drc[0] = readl(tmp_pvt.mch_window + I82975X_DRC_CH0M0); ++ drc[1] = readl(tmp_pvt.mch_window + I82975X_DRC_CH1M0); ++ ++ detect_memory_style(&tmp_pvt); ++ if (!tmp_pvt.num_channels) { ++ edac_dbg(3, "No memories installed? This shouldn't be running!\n"); ++ goto fail0; ++ } + +- i82975x_print_dram_config(mch_window, mchbar, drc); ++ i82975x_print_dram_config(&tmp_pvt, mchbar, drc); + + if (!(((drc[0] >> 21) & 3) == 1 || ((drc[1] >> 21) & 3) == 1)) { + i82975x_printk(KERN_INFO, "ECC disabled on both channels.\n"); + goto fail1; + } + +- chans = dual_channel_active(mch_window) + 1; +- + /* assuming only one controller, index thus is 0 */ + layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; +- layers[0].size = I82975X_NR_DIMMS; ++ layers[0].size = DIMMS_PER_CHANNEL; + layers[0].is_virt_csrow = true; + layers[1].type = EDAC_MC_LAYER_CHANNEL; +- layers[1].size = I82975X_NR_CSROWS(chans); ++ layers[1].size = tmp_pvt.num_channels; + layers[1].is_virt_csrow = false; + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); + if (!mci) { +@@ -562,10 +653,12 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) + mci->dev_name = pci_name(pdev); + mci->edac_check = i82975x_check; + mci->ctl_page_to_phys = NULL; ++ + edac_dbg(3, "init pvt\n"); + pvt = (struct i82975x_pvt *) mci->pvt_info; +- pvt->mch_window = mch_window; +- i82975x_init_csrows(mci, pdev, mch_window); ++ *pvt = tmp_pvt; ++ ++ i82975x_init_csrows(mci, pvt, pdev); + mci->scrub_mode = SCRUB_HW_SRC; + i82975x_get_error_info(mci, &discard); /* clear counters */ + +@@ -583,7 +676,7 @@ fail2: + edac_mc_free(mci); + + fail1: +- iounmap(mch_window); ++ iounmap(tmp_pvt.mch_window); + fail0: + return rc; + } diff --git a/kernel.spec b/kernel.spec index 8cbcf4237..d710ef1de 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -668,6 +668,8 @@ Patch14010: lis3-improve-handling-of-null-rate.patch Patch19000: ips-noirq.patch +Patch19001: i82975x-edac-fix.patch + #rhbz 769766 Patch21072: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch @@ -1296,6 +1298,8 @@ ApplyPatch lis3-improve-handling-of-null-rate.patch ApplyPatch ips-noirq.patch +ApplyPatch i82975x-edac-fix.patch + #ApplyPatch pci-crs-blacklist.patch #rhbz 754518 @@ -2027,6 +2031,9 @@ fi # and build. %changelog +* Wed Oct 30 2012 Justin M. Forbes 3.6.5-2 +- Fix i82975x_edac OOPS (BZ#848149) + * Wed Oct 30 2012 Justin M. Forbes 3.6.5-1 - Linux 3.6.5 From 594eaa3550f3c2b88c32714476d9f8fd9584efaf Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 1 Nov 2012 14:34:11 -0500 Subject: [PATCH 455/487] Drop unhandled irq patch --- kernel.spec | 9 +- unhandled-irqs-switch-to-polling.patch | 245 ------------------------- 2 files changed, 4 insertions(+), 250 deletions(-) delete mode 100644 unhandled-irqs-switch-to-polling.patch diff --git a/kernel.spec b/kernel.spec index d710ef1de..9afbf8012 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -678,8 +678,6 @@ Patch21226: pci-crs-blacklist.patch #rhbz 754518 #Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch -Patch21300: unhandled-irqs-switch-to-polling.patch - #rhbz 804957 CVE-2012-1568 Patch21306: shlib_base_randomize.patch @@ -1305,8 +1303,6 @@ ApplyPatch i82975x-edac-fix.patch #rhbz 754518 #ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch -ApplyPatch unhandled-irqs-switch-to-polling.patch - # debug patches ApplyPatch weird-root-dentry-name-debug.patch ApplyPatch debug-808990.patch @@ -2031,6 +2027,9 @@ fi # and build. %changelog +* Thu Nov 01 2012 Justin M. Forbes 3.6.5-3 +- Drop unhandled irq patch. (rhbz 845211) + * Wed Oct 30 2012 Justin M. Forbes 3.6.5-2 - Fix i82975x_edac OOPS (BZ#848149) diff --git a/unhandled-irqs-switch-to-polling.patch b/unhandled-irqs-switch-to-polling.patch deleted file mode 100644 index 0fc4d080e..000000000 --- a/unhandled-irqs-switch-to-polling.patch +++ /dev/null @@ -1,245 +0,0 @@ -From f9b32cd97783f2be14386f1347439e86109050b9 Mon Sep 17 00:00:00 2001 -From: Jeroen Van den Keybus -Date: Mon, 30 Jan 2012 22:37:28 +0100 -Subject: [PATCH] Unhandled IRQs on AMD E-450: temporarily switch to - low-performance polling IRQ mode - -It seems that some motherboard designs using the ASM1083 PCI/PCIe -bridge (PCI device ID 1b21:1080, Rev. 01) suffer from stuck IRQ lines -on the PCI bus (causing the kernel to emit 'IRQxx: nobody cared' and -disable the IRQ). The following patch is an attempt to mitigate the -serious impact of permanently disabling an IRQ in that case and -actually make PCI devices better usable on this platform. - -It seems that the bridge fails to issue a IRQ deassertion message on -the PCIe bus, when the relevant driver causes the interrupting PCI -device to deassert its IRQ line. To solve this issue, it was tried to -re-issue an IRQ on a PCI device being able to do so (e1000 in this -case), but we suspect that the attempt to re-assert/deassert may have -occurred too soon after the initial IRQ for the ASM1083. Anyway, it -didn't work but if, after some delay, a new IRQ occurred, the related -IRQ deassertion message eventually did clear the IOAPIC IRQ. It would -be useful to re-enable the IRQ here. - -Therefore the patch below to poll_spurious_irqs() in spurious.c is -proposed, It does the following: - -1. lets the kernel decide that an IRQ is unhandled after only 10 -positives (instead of 100,000); -2. briefly (a few seconds or so, currently 1 s) switches to polling -IRQ at a higher rate than usual (100..1,000Hz instead of 10Hz, -currently 100Hz), but not too high to avoid excessive CPU load. Any -device drivers 'see' their interrupts handled with a higher latency -than usual, but they will still operate properly; -3. afterwards, simply reenable the IRQ. - -If proper operation of the PCIe legacy IRQ line emulation is restored -after 3, the system operates again at normal performance. If the IRQ -is still stuck after this procedure, the sequence repeats. - -If a genuinely stuck IRQ is used with this solution, the system would -simply sustain short bursts of 10 unhandled IRQs per second, and use -polling mode indefinitely at a moderate 100Hz rate. It seemed a good -alternative to the default irqpoll behaviour to me, which is why I -left it in poll_spurious_irqs() (instead of creating a new kernel -option). Additionally, if any device happens to share an IRQ with a -faulty one, that device is no longer banned forever. - -Debugging output is still present and may be removed. Bad IRQ -reporting is also commented out now. - -I have now tried it for about 2 months and I can conclude the following: - -1. The patch works and, judging from my Firewire card interrupt on -IRQ16, which repeats every 64 secs, I can confirm that the IRQ usually -gets reset when a new IRQ arrives (polling mode runs for 64 seconds -every time). -2. When testing a SiL-3114 SATA PCI card behind the ASM1083, I could -keep this running at fairly high speeds (50..70MB/s) for an hour or -so, but eventually the SiL driver crashed. In such conditions the PCI -system had to deal with a few hundred IRQs per second / polling mode -kicking in every 5..10 seconds). - -I would like to thank Clemens Ladisch for his invaluable help in -finding a solution (and providing a patch to avoid my SATA going down -every time during debugging). - -Signed-off-by: Jeroen Van den Keybus - -Make it less chatty. Only kick it in if we detect an ASM1083 PCI bridge. -Fix logic error due to lack of braces - -Josh Boyer -====== ---- - drivers/pci/quirks.c | 16 +++++++++++ - kernel/irq/spurious.c | 73 +++++++++++++++++++++++++++++++++++++++--------- - 2 files changed, 75 insertions(+), 14 deletions(-) - -diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c -index 78fda9c..6ba5dbf 100644 ---- a/drivers/pci/quirks.c -+++ b/drivers/pci/quirks.c -@@ -1677,6 +1677,22 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2609, quirk_intel_pcie_pm); - DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm); - DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm); - -+/* ASM108x transparent PCI bridges apparently have broken IRQ deassert -+ * handling. This causes interrupts to get "stuck" and eventually disabled. -+ * However, the interrupts are often shared and disabling them is fairly bad. -+ * It's been somewhat successful to switch to polling mode and retry after -+ * a bit, so let's do that. -+ */ -+extern int irq_poll_and_retry; -+static void quirk_asm108x_poll_interrupts(struct pci_dev *dev) -+{ -+ dev_info(&dev->dev, "Buggy bridge found [%04x:%04x]\n", -+ dev->vendor, dev->device); -+ dev_info(&dev->dev, "Stuck interrupts will be polled and retried\n"); -+ irq_poll_and_retry = 1; -+} -+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_asm108x_poll_interrupts); -+ - #ifdef CONFIG_X86_IO_APIC - /* - * Boot interrupts on some chipsets cannot be turned off. For these chipsets, -diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c -index 611cd60..f722eb6 100644 ---- a/kernel/irq/spurious.c -+++ b/kernel/irq/spurious.c -@@ -18,6 +18,8 @@ - - static int irqfixup __read_mostly; - -+int irq_poll_and_retry = 0; -+ - #define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10) - static void poll_spurious_irqs(unsigned long dummy); - static DEFINE_TIMER(poll_spurious_irq_timer, poll_spurious_irqs, 0, 0); -@@ -141,12 +143,13 @@ out: - static void poll_spurious_irqs(unsigned long dummy) - { - struct irq_desc *desc; -- int i; -+ int i, poll_again; - - if (atomic_inc_return(&irq_poll_active) != 1) - goto out; - irq_poll_cpu = smp_processor_id(); - -+ poll_again = 0; /* Will stay false as long as no polling candidate is found */ - for_each_irq_desc(i, desc) { - unsigned int state; - -@@ -159,14 +162,33 @@ static void poll_spurious_irqs(unsigned long dummy) - if (!(state & IRQS_SPURIOUS_DISABLED)) - continue; - -- local_irq_disable(); -- try_one_irq(i, desc, true); -- local_irq_enable(); -+ /* We end up here with a disabled spurious interrupt. -+ desc->irqs_unhandled now tracks the number of times -+ the interrupt has been polled */ -+ if (irq_poll_and_retry) { -+ if (desc->irqs_unhandled < 100) { /* 1 second delay with poll frequency 100 Hz */ -+ local_irq_disable(); -+ try_one_irq(i, desc, true); -+ local_irq_enable(); -+ desc->irqs_unhandled++; -+ poll_again = 1; -+ } else { -+ irq_enable(desc); /* Reenable the interrupt line */ -+ desc->depth--; -+ desc->istate &= (~IRQS_SPURIOUS_DISABLED); -+ desc->irqs_unhandled = 0; -+ } -+ } else { -+ local_irq_disable(); -+ try_one_irq(i, desc, true); -+ local_irq_enable(); -+ } - } -+ if (poll_again) -+ mod_timer(&poll_spurious_irq_timer, -+ jiffies + POLL_SPURIOUS_IRQ_INTERVAL); - out: - atomic_dec(&irq_poll_active); -- mod_timer(&poll_spurious_irq_timer, -- jiffies + POLL_SPURIOUS_IRQ_INTERVAL); - } - - static inline int bad_action_ret(irqreturn_t action_ret) -@@ -177,11 +199,19 @@ static inline int bad_action_ret(irqreturn_t action_ret) - } - - /* -- * If 99,900 of the previous 100,000 interrupts have not been handled -+ * If 9 of the previous 10 interrupts have not been handled - * then assume that the IRQ is stuck in some manner. Drop a diagnostic - * and try to turn the IRQ off. - * -- * (The other 100-of-100,000 interrupts may have been a correctly -+ * Although this may cause early deactivation of a sporadically -+ * malfunctioning IRQ line, the poll system will: -+ * a) Poll it for 100 cycles at a 100 Hz rate -+ * b) Reenable it afterwards -+ * -+ * In worst case, with current settings, this will cause short bursts -+ * of 10 interrupts every second. -+ * -+ * (The other single interrupt may have been a correctly - * functioning device sharing an IRQ with the failing one) - */ - static void -@@ -269,6 +299,8 @@ try_misrouted_irq(unsigned int irq, struct irq_desc *desc, - void note_interrupt(unsigned int irq, struct irq_desc *desc, - irqreturn_t action_ret) - { -+ int unhandled_thresh = 999000; -+ - if (desc->istate & IRQS_POLL_INPROGRESS) - return; - -@@ -302,19 +334,32 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, - } - - desc->irq_count++; -- if (likely(desc->irq_count < 100000)) -- return; -+ if (!irq_poll_and_retry) { -+ if (likely(desc->irq_count < 100000)) -+ return; -+ } else { -+ if (likely(desc->irq_count < 10)) -+ return; -+ } - - desc->irq_count = 0; -- if (unlikely(desc->irqs_unhandled > 99900)) { -+ if (irq_poll_and_retry) -+ unhandled_thresh = 9; -+ -+ if (unlikely(desc->irqs_unhandled >= unhandled_thresh)) { - /* -- * The interrupt is stuck -+ * The interrupt might be stuck - */ -- __report_bad_irq(irq, desc, action_ret); -+ if (!irq_poll_and_retry) { -+ __report_bad_irq(irq, desc, action_ret); -+ printk(KERN_EMERG "Disabling IRQ %d\n", irq); -+ } else { -+ printk(KERN_INFO "IRQ %d might be stuck. Polling\n", -+ irq); -+ } - /* - * Now kill the IRQ - */ -- printk(KERN_EMERG "Disabling IRQ #%d\n", irq); - desc->istate |= IRQS_SPURIOUS_DISABLED; - desc->depth++; - irq_disable(desc); --- -1.7.7.6 - From 123d75be63c61cde7b202482b8b1d20c64bcba9e Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 5 Nov 2012 10:39:30 -0600 Subject: [PATCH 456/487] Linux 3.6.6 --- kernel.spec | 7 +++++-- sources | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel.spec b/kernel.spec index 9afbf8012..34b56a711 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 5 +%define stable_update 6 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -2027,6 +2027,9 @@ fi # and build. %changelog +* Mon Nov 05 2012 Justin M. Forbes 3.6.6-1 +- Linux 3.6.6 + * Thu Nov 01 2012 Justin M. Forbes 3.6.5-3 - Drop unhandled irq patch. (rhbz 845211) diff --git a/sources b/sources index 3800ac99f..d3c14f4b8 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -6ad8ceebb9b5c1bf69a0c07ef7cc81f2 patch-3.6.5.xz +11d6d8749d4612a77f43f0531c0f2824 patch-3.6.6.xz From 02c38dbef5a274584620afc4c3b218a987a56c74 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Mon, 12 Nov 2012 12:23:45 -0600 Subject: [PATCH 457/487] fix list_del corruption warning on USB audio with twinkle (rhbz 871078) --- USB-EHCI-urb-hcpriv-should-not-be-NULL.patch | 72 ++++++++++ USB-report-submission-of-active-URBs.patch | 46 +++++++ kernel.spec | 15 ++- ...crash-at-re-preparing-the-PCM-stream.patch | 125 ++++++++++++++++++ 4 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 USB-EHCI-urb-hcpriv-should-not-be-NULL.patch create mode 100644 USB-report-submission-of-active-URBs.patch create mode 100644 usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch diff --git a/USB-EHCI-urb-hcpriv-should-not-be-NULL.patch b/USB-EHCI-urb-hcpriv-should-not-be-NULL.patch new file mode 100644 index 000000000..4b8e537c4 --- /dev/null +++ b/USB-EHCI-urb-hcpriv-should-not-be-NULL.patch @@ -0,0 +1,72 @@ +commit 2656a9abcf1ec8dd5fee6a75d6997a0f2fa0094e +Author: Alan Stern +Date: Thu Nov 8 10:17:01 2012 -0500 + + USB: EHCI: bugfix: urb->hcpriv should not be NULL + + This patch (as1632b) fixes a bug in ehci-hcd. The USB core uses + urb->hcpriv to determine whether or not an URB is active; host + controller drivers are supposed to set this pointer to a non-NULL + value when an URB is queued. However ehci-hcd sets it to NULL for + isochronous URBs, which defeats the check in usbcore. + + In itself this isn't a big deal. But people have recently found that + certain sequences of actions will cause the snd-usb-audio driver to + reuse URBs without waiting for them to complete. In the absence of + proper checking by usbcore, the URBs get added to their endpoint list + twice. This leads to list corruption and a system freeze. + + The patch makes ehci-hcd assign a meaningful value to urb->hcpriv for + isochronous URBs. Improving robustness always helps. + + Signed-off-by: Alan Stern + Reported-by: Artem S. Tashkinov + Reported-by: Christof Meerwald + CC: + Signed-off-by: Greg Kroah-Hartman + +diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c +index 4b66374..3d98902 100644 +--- a/drivers/usb/host/ehci-q.c ++++ b/drivers/usb/host/ehci-q.c +@@ -264,15 +264,9 @@ ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status) + __releases(ehci->lock) + __acquires(ehci->lock) + { +- if (likely (urb->hcpriv != NULL)) { +- struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; +- +- /* S-mask in a QH means it's an interrupt urb */ +- if ((qh->hw->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) { +- +- /* ... update hc-wide periodic stats (for usbfs) */ +- ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; +- } ++ if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { ++ /* ... update hc-wide periodic stats */ ++ ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; + } + + if (unlikely(urb->unlinked)) { +diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c +index 2e14714..69ebee7 100644 +--- a/drivers/usb/host/ehci-sched.c ++++ b/drivers/usb/host/ehci-sched.c +@@ -1630,7 +1630,7 @@ static void itd_link_urb( + + /* don't need that schedule data any more */ + iso_sched_free (stream, iso_sched); +- urb->hcpriv = NULL; ++ urb->hcpriv = stream; + + ++ehci->isoc_count; + enable_periodic(ehci); +@@ -2029,7 +2029,7 @@ static void sitd_link_urb( + + /* don't need that schedule data any more */ + iso_sched_free (stream, sched); +- urb->hcpriv = NULL; ++ urb->hcpriv = stream; + + ++ehci->isoc_count; + enable_periodic(ehci); diff --git a/USB-report-submission-of-active-URBs.patch b/USB-report-submission-of-active-URBs.patch new file mode 100644 index 000000000..4496c913a --- /dev/null +++ b/USB-report-submission-of-active-URBs.patch @@ -0,0 +1,46 @@ +commit 2f02bc8af3abb846823811af65ec6cc46a4d525d +Author: Alan Stern +Date: Wed Nov 7 16:35:00 2012 -0500 + + USB: report submission of active URBs + + This patch (as1633) changes slightly the way usbcore handled + submissions of URBs that are already active. It will now return + -EBUSY rather than -EINVAL, and it will call WARN_ONCE to draw + people's attention to the bug. + + Signed-off-by: Alan Stern + Signed-off-by: Greg Kroah-Hartman + +diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt +index 8d1e2a9..9c3eb84 100644 +--- a/Documentation/usb/error-codes.txt ++++ b/Documentation/usb/error-codes.txt +@@ -21,6 +21,8 @@ Non-USB-specific: + + USB-specific: + ++-EBUSY The URB is already active. ++ + -ENODEV specified USB-device or bus doesn't exist + + -ENOENT specified interface or endpoint does not exist or +diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c +index 3662287..e0d9d94 100644 +--- a/drivers/usb/core/urb.c ++++ b/drivers/usb/core/urb.c +@@ -321,8 +321,13 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) + struct usb_host_endpoint *ep; + int is_out; + +- if (!urb || urb->hcpriv || !urb->complete) ++ if (!urb || !urb->complete) + return -EINVAL; ++ if (urb->hcpriv) { ++ WARN_ONCE(1, "URB %p submitted while active\n", urb); ++ return -EBUSY; ++ } ++ + dev = urb->dev; + if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED)) + return -ENODEV; diff --git a/kernel.spec b/kernel.spec index 34b56a711..14b18864d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -705,6 +705,11 @@ Patch22092: net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch +#rhbz 871078 +Patch22110: usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch +Patch22111: USB-EHCI-urb-hcpriv-should-not-be-NULL.patch +Patch22112: USB-report-submission-of-active-URBs.patch + # END OF PATCH DEFINITIONS %endif @@ -1327,6 +1332,11 @@ ApplyPatch 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch #rhbz 871923 871848 CVE-2012-4565 ApplyPatch net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch +#rhbz 871078 +ApplyPatch usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch +ApplyPatch USB-EHCI-urb-hcpriv-should-not-be-NULL.patch +ApplyPatch USB-report-submission-of-active-URBs.patch + # END OF PATCH APPLICATIONS %endif @@ -2027,6 +2037,9 @@ fi # and build. %changelog +* Mon Nov 12 2012 Justin M. Forbes +- fix list_del corruption warning on USB audio with twinkle (rhbz 871078) + * Mon Nov 05 2012 Justin M. Forbes 3.6.6-1 - Linux 3.6.6 diff --git a/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch b/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch new file mode 100644 index 000000000..6d840ea2c --- /dev/null +++ b/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch @@ -0,0 +1,125 @@ +At Thu, 08 Nov 2012 08:31:35 +0100, +Daniel Mack wrote: +(snip) +> >> We can't simply stop both endpoints in the prepare callback. +> > +> > The new function doesn't stop the stream by itself but it just syncs +> > if the stream is being stopped beforehand. So, it's safe to call it +> > there. +> > +> > Maybe the name was confusing. It should have been like +> > snd_usb_endpoint_sync_pending_stop() or such. +> +> Ah, right. I was errornously looking closer to Alan's patch but then +> replied to yours. Alright then - thanks for explaining :) + +OK, thanks for checking. + +FWIW, below is the patch I applied now to for-linus branch. +Renamed the function, added the comment and put NULL check to the +function to simplify. + + +Takashi + +--- +From: Takashi Iwai +Subject: [PATCH] ALSA: usb-audio: Fix crash at re-preparing the PCM stream + +There are bug reports of a crash with USB-audio devices when PCM +prepare is performed immediately after the stream is stopped via +trigger callback. It turned out that the problem is that we don't +wait until all URBs are killed. + +This patch adds a new function to synchronize the pending stop +operation on an endpoint, and calls in the prepare callback for +avoiding the crash above. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=49181 + +Reported-and-tested-by: Artem S. Tashkinov +Cc: [v3.6] +Signed-off-by: Takashi Iwai +--- + sound/usb/endpoint.c | 13 +++++++++++++ + sound/usb/endpoint.h | 1 + + sound/usb/pcm.c | 3 +++ + 3 files changed, 17 insertions(+) + +diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c +index 7f78c6d..34de6f2 100644 +--- a/sound/usb/endpoint.c ++++ b/sound/usb/endpoint.c +@@ -35,6 +35,7 @@ + + #define EP_FLAG_ACTIVATED 0 + #define EP_FLAG_RUNNING 1 ++#define EP_FLAG_STOPPING 2 + + /* + * snd_usb_endpoint is a model that abstracts everything related to an +@@ -502,10 +503,20 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) + if (alive) + snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n", + alive, ep->ep_num); ++ clear_bit(EP_FLAG_STOPPING, &ep->flags); + + return 0; + } + ++/* sync the pending stop operation; ++ * this function itself doesn't trigger the stop operation ++ */ ++void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep) ++{ ++ if (ep && test_bit(EP_FLAG_STOPPING, &ep->flags)) ++ wait_clear_urbs(ep); ++} ++ + /* + * unlink active urbs. + */ +@@ -918,6 +929,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, + + if (wait) + wait_clear_urbs(ep); ++ else ++ set_bit(EP_FLAG_STOPPING, &ep->flags); + } + } + +diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h +index 6376ccf..3d4c970 100644 +--- a/sound/usb/endpoint.h ++++ b/sound/usb/endpoint.h +@@ -19,6 +19,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, + int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep); + void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, + int force, int can_sleep, int wait); ++void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep); + int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); + int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep); + void snd_usb_endpoint_free(struct list_head *head); +diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c +index 37428f7..5c12a3f 100644 +--- a/sound/usb/pcm.c ++++ b/sound/usb/pcm.c +@@ -552,6 +552,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) + if (snd_BUG_ON(!subs->data_endpoint)) + return -EIO; + ++ snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); ++ snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); ++ + /* some unit conversions in runtime */ + subs->data_endpoint->maxframesize = + bytes_to_frames(runtime, subs->data_endpoint->maxpacksize); +-- +1.8.0 + + +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ From 7a2a907f6df4ee3b09d2c4450fbd16b98e249d2f Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 15 Nov 2012 11:09:59 -0600 Subject: [PATCH 458/487] Fix panic in panic in smp_irq_move_cleanup_interrupt --- kernel.spec | 7 ++++ smp_irq_move_cleanup_interrupt.patch | 50 ++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 smp_irq_move_cleanup_interrupt.patch diff --git a/kernel.spec b/kernel.spec index 14b18864d..51dcfca76 100644 --- a/kernel.spec +++ b/kernel.spec @@ -710,6 +710,8 @@ Patch22110: usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch Patch22111: USB-EHCI-urb-hcpriv-should-not-be-NULL.patch Patch22112: USB-report-submission-of-active-URBs.patch +Patch22113: smp_irq_move_cleanup_interrupt.patch + # END OF PATCH DEFINITIONS %endif @@ -1337,6 +1339,8 @@ ApplyPatch usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch ApplyPatch USB-EHCI-urb-hcpriv-should-not-be-NULL.patch ApplyPatch USB-report-submission-of-active-URBs.patch +ApplyPatch smp_irq_move_cleanup_interrupt.patch + # END OF PATCH APPLICATIONS %endif @@ -2037,6 +2041,9 @@ fi # and build. %changelog +* Thu Nov 15 2012 Justin M. Forbes +- Fix panic in panic in smp_irq_move_cleanup_interrupt + * Mon Nov 12 2012 Justin M. Forbes - fix list_del corruption warning on USB audio with twinkle (rhbz 871078) diff --git a/smp_irq_move_cleanup_interrupt.patch b/smp_irq_move_cleanup_interrupt.patch new file mode 100644 index 000000000..c9b385a94 --- /dev/null +++ b/smp_irq_move_cleanup_interrupt.patch @@ -0,0 +1,50 @@ +commit 94777fc51b3ad85ff9f705ddf7cdd0eb3bbad5a6 +Author: Dimitri Sivanich +Date: Tue Oct 16 07:50:21 2012 -0500 + + x86/irq/ioapic: Check for valid irq_cfg pointer in smp_irq_move_cleanup_interrupt + + Posting this patch to fix an issue concerning sparse irq's that + I raised a while back. There was discussion about adding + refcounting to sparse irqs (to fix other potential race + conditions), but that does not appear to have been addressed + yet. This covers the only issue of this type that I've + encountered in this area. + + A NULL pointer dereference can occur in + smp_irq_move_cleanup_interrupt() if we haven't yet setup the + irq_cfg pointer in the irq_desc.irq_data.chip_data. + + In create_irq_nr() there is a window where we have set + vector_irq in __assign_irq_vector(), but not yet called + irq_set_chip_data() to set the irq_cfg pointer. + + Should an IRQ_MOVE_CLEANUP_VECTOR hit the cpu in question during + this time, smp_irq_move_cleanup_interrupt() will attempt to + process the aforementioned irq, but panic when accessing + irq_cfg. + + Only continue processing the irq if irq_cfg is non-NULL. + + Signed-off-by: Dimitri Sivanich + Cc: Suresh Siddha + Cc: Joerg Roedel + Cc: Yinghai Lu + Cc: Alexander Gordeev + Link: http://lkml.kernel.org/r/20121016125021.GA22935@sgi.com + Signed-off-by: Ingo Molnar + +diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c +index c265593..1817fa9 100644 +--- a/arch/x86/kernel/apic/io_apic.c ++++ b/arch/x86/kernel/apic/io_apic.c +@@ -2257,6 +2257,9 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void) + continue; + + cfg = irq_cfg(irq); ++ if (!cfg) ++ continue; ++ + raw_spin_lock(&desc->lock); + + /* From df9f4ec79ee96765f3d07d4d7233e5bde3aed71b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 16 Nov 2012 08:39:48 -0500 Subject: [PATCH 459/487] Don't WARN_ON empty queues in iwlwifi (rhbz 873001) --- iwlwifi-remove-queue-empty-warn-3.6.patch | 25 +++++++++++++++++++++++ kernel.spec | 15 ++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 iwlwifi-remove-queue-empty-warn-3.6.patch diff --git a/iwlwifi-remove-queue-empty-warn-3.6.patch b/iwlwifi-remove-queue-empty-warn-3.6.patch new file mode 100644 index 000000000..b8cf5a470 --- /dev/null +++ b/iwlwifi-remove-queue-empty-warn-3.6.patch @@ -0,0 +1,25 @@ +diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c +index 105e3af..79a4ddc 100644 +--- a/drivers/net/wireless/iwlwifi/pcie/tx.c ++++ b/drivers/net/wireless/iwlwifi/pcie/tx.c +@@ -480,20 +480,12 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, + void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) + { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); +- u16 rd_ptr, wr_ptr; +- int n_bd = trans_pcie->txq[txq_id].q.n_bd; + + if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) { + WARN_ONCE(1, "queue %d not used", txq_id); + return; + } + +- rd_ptr = iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & (n_bd - 1); +- wr_ptr = iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)); +- +- WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]", +- txq_id, rd_ptr, wr_ptr); +- + iwl_txq_set_inactive(trans, txq_id); + IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); + } diff --git a/kernel.spec b/kernel.spec index 51dcfca76..1cc8ebba0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -710,8 +710,12 @@ Patch22110: usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch Patch22111: USB-EHCI-urb-hcpriv-should-not-be-NULL.patch Patch22112: USB-report-submission-of-active-URBs.patch +#rhbz 869341 Patch22113: smp_irq_move_cleanup_interrupt.patch +#rhbz 873001 +Patch22114: iwlwifi-remove-queue-empty-warn-3.6.patch + # END OF PATCH DEFINITIONS %endif @@ -1339,8 +1343,12 @@ ApplyPatch usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch ApplyPatch USB-EHCI-urb-hcpriv-should-not-be-NULL.patch ApplyPatch USB-report-submission-of-active-URBs.patch +#rhbz 869341 ApplyPatch smp_irq_move_cleanup_interrupt.patch +#rhbz 873001 +ApplyPatch iwlwifi-remove-queue-empty-warn-3.6.patch + # END OF PATCH APPLICATIONS %endif @@ -2041,8 +2049,11 @@ fi # and build. %changelog +* Fri Nov 16 2012 Josh Boyer +- Don't WARN_ON empty queues in iwlwifi (rhbz 873001) + * Thu Nov 15 2012 Justin M. Forbes -- Fix panic in panic in smp_irq_move_cleanup_interrupt +- Fix panic in panic in smp_irq_move_cleanup_interrupt (rhbz 869341) * Mon Nov 12 2012 Justin M. Forbes - fix list_del corruption warning on USB audio with twinkle (rhbz 871078) From d94c6eb95a52c049b705651c3b33fd905db04cc0 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 16 Nov 2012 08:43:51 -0500 Subject: [PATCH 460/487] Fix oops causing typo in keyspan driver (rhbz 870562) --- kernel.spec | 7 ++++ keyspan.patch | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 keyspan.patch diff --git a/kernel.spec b/kernel.spec index 1cc8ebba0..9dab9fe32 100644 --- a/kernel.spec +++ b/kernel.spec @@ -716,6 +716,9 @@ Patch22113: smp_irq_move_cleanup_interrupt.patch #rhbz 873001 Patch22114: iwlwifi-remove-queue-empty-warn-3.6.patch +#rhbz 870562 +Patch22115: keyspan.patch + # END OF PATCH DEFINITIONS %endif @@ -1349,6 +1352,9 @@ ApplyPatch smp_irq_move_cleanup_interrupt.patch #rhbz 873001 ApplyPatch iwlwifi-remove-queue-empty-warn-3.6.patch +#rhbz 870562 +ApplyPatch keyspan.patch + # END OF PATCH APPLICATIONS %endif @@ -2050,6 +2056,7 @@ fi %changelog * Fri Nov 16 2012 Josh Boyer +- Fix oops causing typo in keyspan driver (rhbz 870562) - Don't WARN_ON empty queues in iwlwifi (rhbz 873001) * Thu Nov 15 2012 Justin M. Forbes diff --git a/keyspan.patch b/keyspan.patch new file mode 100644 index 000000000..43d116ea4 --- /dev/null +++ b/keyspan.patch @@ -0,0 +1,98 @@ + +Delivered-To: jwboyer@gmail.com +Received: by 10.58.186.240 with SMTP id fn16csp155256vec; + Sat, 10 Nov 2012 01:14:20 -0800 (PST) +Received: by 10.68.130.197 with SMTP id og5mr40733607pbb.138.1352538859530; + Sat, 10 Nov 2012 01:14:19 -0800 (PST) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id pj1si1353832pbc.115.2012.11.10.01.14.15; + Sat, 10 Nov 2012 01:14:19 -0800 (PST) +Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; +Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1750798Ab2KJJOO (ORCPT + 33 others); + Sat, 10 Nov 2012 04:14:14 -0500 +Received: from canardo.mork.no ([148.122.252.1]:37367 "EHLO canardo.mork.no" + rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP + id S1750699Ab2KJJOM (ORCPT ); + Sat, 10 Nov 2012 04:14:12 -0500 +Received: from nemi.mork.no (nemi.mork.no [IPv6:2001:4620:9:2:216:eaff:feb3:788]) + (authenticated bits=0) + by canardo.mork.no (8.14.3/8.14.3) with ESMTP id qAA9E1cX010750 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NOT); + Sat, 10 Nov 2012 10:14:02 +0100 +Received: from bjorn by nemi.mork.no with local (Exim 4.80) + (envelope-from ) + id 1TX78a-0007Li-AD; Sat, 10 Nov 2012 10:14:00 +0100 +From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= +To: Richard +Cc: Greg Kroah-Hartman , + linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, + =?UTF-8?q?Bj=C3=B8rn=20Mork?= , + , Johan Hovold +Subject: [PATCH usb-linus] USB: keyspan: fix typo causing GPF on open +Date: Sat, 10 Nov 2012 10:13:42 +0100 +Message-Id: <1352538822-28221-1-git-send-email-bjorn@mork.no> +X-Mailer: git-send-email 1.7.10.4 +In-Reply-To: <509D5BCD.3010901@pacbell.net> +References: <509D5BCD.3010901@pacbell.net> +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +X-Virus-Scanned: clamav-milter 0.97.6 at canardo +X-Virus-Status: Clean +Sender: stable-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: stable@vger.kernel.org + +Commit f79b2d0f (USB: keyspan: fix NULL-pointer dereferences and +memory leaks) had a small typo which made the driver use wrong +offsets when mapping serial port private data. This results in +in a GPF when the port is opened. + +Reported-by: Richard +Cc: +Cc: Johan Hovold +Signed-off-by: Bjørn Mork +--- +Hello Richard, + +I wonder if you are able to test and verify this? I do not guarantee +that there aren't other issues around, but this small typo looked like +an obvious killer... + +Bjørn + + drivers/usb/serial/keyspan.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c +index 7179b0c..cff8dd5 100644 +--- a/drivers/usb/serial/keyspan.c ++++ b/drivers/usb/serial/keyspan.c +@@ -2430,7 +2430,7 @@ static void keyspan_release(struct usb_serial *serial) + static int keyspan_port_probe(struct usb_serial_port *port) + { + struct usb_serial *serial = port->serial; +- struct keyspan_port_private *s_priv; ++ struct keyspan_serial_private *s_priv; + struct keyspan_port_private *p_priv; + const struct keyspan_device_details *d_details; + struct callbacks *cback; +@@ -2445,7 +2445,6 @@ static int keyspan_port_probe(struct usb_serial_port *port) + if (!p_priv) + return -ENOMEM; + +- s_priv = usb_get_serial_data(port->serial); + p_priv->device_details = d_details; + + /* Setup values for the various callback routines */ +-- +1.7.10.4 + +-- +To unsubscribe from this list: send the line "unsubscribe stable" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html From e7887c8a4851ff20480918f2ae43b99a2677fe52 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Sat, 17 Nov 2012 22:37:21 -0600 Subject: [PATCH 461/487] linux 3.6.7 --- kernel.spec | 13 +- ...de-by-zero-in-tcp-algorithm-illinois.patch | 117 ------------------ sources | 2 +- ...crash-at-re-preparing-the-PCM-stream.patch | 4 +- 4 files changed, 8 insertions(+), 128 deletions(-) delete mode 100644 net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch diff --git a/kernel.spec b/kernel.spec index 9dab9fe32..1eb0430f4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 6 +%define stable_update 7 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -698,9 +698,6 @@ Patch22089: 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch Patch22090: 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch Patch22091: 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch -#rhbz 871923 871848 CVE-2012-4565 -Patch22092: net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch - # Debug patches Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch @@ -1338,9 +1335,6 @@ ApplyPatch 0010-ext4-fix-ext_remove_space-for-punch_hole-case.patch ApplyPatch 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch ApplyPatch 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch -#rhbz 871923 871848 CVE-2012-4565 -ApplyPatch net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch - #rhbz 871078 ApplyPatch usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch ApplyPatch USB-EHCI-urb-hcpriv-should-not-be-NULL.patch @@ -2055,6 +2049,9 @@ fi # and build. %changelog +* Sat Nov 17 2012 Justin M. Forbes - 3.6.7-1 +- linux 3.6.7 + * Fri Nov 16 2012 Josh Boyer - Fix oops causing typo in keyspan driver (rhbz 870562) - Don't WARN_ON empty queues in iwlwifi (rhbz 873001) diff --git a/net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch b/net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch deleted file mode 100644 index 109ee17b4..000000000 --- a/net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch +++ /dev/null @@ -1,117 +0,0 @@ -Path: news.gmane.org!not-for-mail -From: Jesper Dangaard Brouer -Newsgroups: gmane.linux.network -Subject: [net PATCH V2] net: fix divide by zero in tcp algorithm illinois -Date: Wed, 31 Oct 2012 13:45:32 +0100 -Lines: 63 -Approved: news@gmane.org -Message-ID: <20121031124318.30915.32293.stgit@dragon> -NNTP-Posting-Host: plane.gmane.org -Mime-Version: 1.0 -Content-Type: text/plain; charset="utf-8" -Content-Transfer-Encoding: 7bit -X-Trace: ger.gmane.org 1351687472 19921 80.91.229.3 (31 Oct 2012 12:44:32 GMT) -X-Complaints-To: usenet@ger.gmane.org -NNTP-Posting-Date: Wed, 31 Oct 2012 12:44:32 +0000 (UTC) -Cc: Jesper Dangaard Brouer , netdev@vger.kernel.org, - Petr Matousek , - Stephen Hemminger , - Eric Dumazet -To: "David S. Miller" -Original-X-From: netdev-owner@vger.kernel.org Wed Oct 31 13:44:40 2012 -Return-path: -Envelope-to: linux-netdev-2@plane.gmane.org -Original-Received: from vger.kernel.org ([209.132.180.67]) - by plane.gmane.org with esmtp (Exim 4.69) - (envelope-from ) - id 1TTXex-0002V3-Qk - for linux-netdev-2@plane.gmane.org; Wed, 31 Oct 2012 13:44:40 +0100 -Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S932565Ab2JaMo0 (ORCPT ); - Wed, 31 Oct 2012 08:44:26 -0400 -Original-Received: from mx1.redhat.com ([209.132.183.28]:57345 "EHLO mx1.redhat.com" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1751941Ab2JaMoZ (ORCPT ); - Wed, 31 Oct 2012 08:44:25 -0400 -Original-Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q9VCiOkC014655 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); - Wed, 31 Oct 2012 08:44:24 -0400 -Original-Received: from dragon.localdomain (ovpn-116-61.ams2.redhat.com [10.36.116.61]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q9VCiMuW008440; - Wed, 31 Oct 2012 08:44:23 -0400 -Original-Received: from [127.0.0.1] (localhost [IPv6:::1]) - by dragon.localdomain (Postfix) with ESMTP id 416D0E40666; - Wed, 31 Oct 2012 13:45:32 +0100 (CET) -User-Agent: StGIT/0.14.3 -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -Original-Sender: netdev-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: netdev@vger.kernel.org -Xref: news.gmane.org gmane.linux.network:247871 -Archived-At: - -Reading TCP stats when using TCP Illinois congestion control algorithm -can cause a divide by zero kernel oops. - -The division by zero occur in tcp_illinois_info() at: - do_div(t, ca->cnt_rtt); -where ca->cnt_rtt can become zero (when rtt_reset is called) - -Steps to Reproduce: - 1. Register tcp_illinois: - # sysctl -w net.ipv4.tcp_congestion_control=illinois - 2. Monitor internal TCP information via command "ss -i" - # watch -d ss -i - 3. Establish new TCP conn to machine - -Either it fails at the initial conn, or else it needs to wait -for a loss or a reset. - -This is only related to reading stats. The function avg_delay() also -performs the same divide, but is guarded with a (ca->cnt_rtt > 0) at its -calling point in update_params(). Thus, simply fix tcp_illinois_info(). - -Function tcp_illinois_info() / get_info() is called without -socket lock. Thus, eliminate any race condition on ca->cnt_rtt -by using a local stack variable. Simply reuse info.tcpv_rttcnt, -as its already set to ca->cnt_rtt. -Function avg_delay() is not affected by this race condition, as -its called with the socket lock. - -Cc: Petr Matousek -Signed-off-by: Jesper Dangaard Brouer - ---- -V2: - Address Eric Dumazets input: - - Save 2 bytes of stack, by using info.tcpv_rttcnt. - - Help compiler, and define "u64 t" inside if() lexical scope. - - - net/ipv4/tcp_illinois.c | 8 +++++--- - 1 files changed, 5 insertions(+), 3 deletions(-) - -diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c -index 813b43a..834857f 100644 ---- a/net/ipv4/tcp_illinois.c -+++ b/net/ipv4/tcp_illinois.c -@@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext, - .tcpv_rttcnt = ca->cnt_rtt, - .tcpv_minrtt = ca->base_rtt, - }; -- u64 t = ca->sum_rtt; - -- do_div(t, ca->cnt_rtt); -- info.tcpv_rtt = t; -+ if (info.tcpv_rttcnt > 0) { -+ u64 t = ca->sum_rtt; - -+ do_div(t, info.tcpv_rttcnt); -+ info.tcpv_rtt = t; -+ } - nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info); - } - } - diff --git a/sources b/sources index d3c14f4b8..0d260fa79 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -11d6d8749d4612a77f43f0531c0f2824 patch-3.6.6.xz +134936c362d8812b5cafcf3c67afdce0 patch-3.6.7.xz diff --git a/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch b/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch index 6d840ea2c..9f3e6f993 100644 --- a/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch +++ b/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch @@ -105,8 +105,8 @@ index 37428f7..5c12a3f 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -552,6 +552,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) - if (snd_BUG_ON(!subs->data_endpoint)) - return -EIO; + goto unlock; + } + snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); + snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); From c9be30821bce10cc729a0367a577fe54405b2867 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 19 Nov 2012 11:04:45 -0500 Subject: [PATCH 462/487] Apply patches from Jeff Moyer to fix direct-io oops (rhbz 812129) --- block-fix-a-crash-when-block-device-is.patch | 214 +++++++++++++ ...-a-rw-semaphore-into-a-percpu-rw-sem.patch | 290 ++++++++++++++++++ ...lice_read-and-splice_write-functions.patch | 74 +++++ kernel.spec | 15 +- 4 files changed, 592 insertions(+), 1 deletion(-) create mode 100644 block-fix-a-crash-when-block-device-is.patch create mode 100644 blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch create mode 100644 fs-lock-splice_read-and-splice_write-functions.patch diff --git a/block-fix-a-crash-when-block-device-is.patch b/block-fix-a-crash-when-block-device-is.patch new file mode 100644 index 000000000..af992830e --- /dev/null +++ b/block-fix-a-crash-when-block-device-is.patch @@ -0,0 +1,214 @@ +Fix a crash when block device is read and block size is changed at the same time + +commit b87570f5d349661814b262dd5fc40787700f80d6 +Author: Mikulas Patocka +Date: Wed Sep 26 07:46:40 2012 +0200 + + Fix a crash when block device is read and block size is changed at the same time + + The kernel may crash when block size is changed and I/O is issued + simultaneously. + + Because some subsystems (udev or lvm) may read any block device anytime, + the bug actually puts any code that changes a block device size in + jeopardy. + + The crash can be reproduced if you place "msleep(1000)" to + blkdev_get_blocks just before "bh->b_size = max_blocks << + inode->i_blkbits;". + Then, run "dd if=/dev/ram0 of=/dev/null bs=4k count=1 iflag=direct" + While it is waiting in msleep, run "blockdev --setbsz 2048 /dev/ram0" + You get a BUG. + + The direct and non-direct I/O is written with the assumption that block + size does not change. It doesn't seem practical to fix these crashes + one-by-one there may be many crash possibilities when block size changes + at a certain place and it is impossible to find them all and verify the + code. + + This patch introduces a new rw-lock bd_block_size_semaphore. The lock is + taken for read during I/O. It is taken for write when changing block + size. Consequently, block size can't be changed while I/O is being + submitted. + + For asynchronous I/O, the patch only prevents block size change while + the I/O is being submitted. The block size can change when the I/O is in + progress or when the I/O is being finished. This is acceptable because + there are no accesses to block size when asynchronous I/O is being + finished. + + The patch prevents block size changing while the device is mapped with + mmap. + + Signed-off-by: Mikulas Patocka + Signed-off-by: Jens Axboe + +Index: linux-3.6.x86_64/drivers/char/raw.c +=================================================================== +--- linux-3.6.x86_64.orig/drivers/char/raw.c 2012-11-16 17:12:35.127010280 -0500 ++++ linux-3.6.x86_64/drivers/char/raw.c 2012-11-16 17:12:37.381002516 -0500 +@@ -285,7 +285,7 @@ + + static const struct file_operations raw_fops = { + .read = do_sync_read, +- .aio_read = generic_file_aio_read, ++ .aio_read = blkdev_aio_read, + .write = do_sync_write, + .aio_write = blkdev_aio_write, + .fsync = blkdev_fsync, +Index: linux-3.6.x86_64/fs/block_dev.c +=================================================================== +--- linux-3.6.x86_64.orig/fs/block_dev.c 2012-11-16 17:12:35.127010280 -0500 ++++ linux-3.6.x86_64/fs/block_dev.c 2012-11-16 17:12:37.381002516 -0500 +@@ -116,6 +116,8 @@ + + int set_blocksize(struct block_device *bdev, int size) + { ++ struct address_space *mapping; ++ + /* Size must be a power of two, and between 512 and PAGE_SIZE */ + if (size > PAGE_SIZE || size < 512 || !is_power_of_2(size)) + return -EINVAL; +@@ -124,6 +126,20 @@ + if (size < bdev_logical_block_size(bdev)) + return -EINVAL; + ++ /* Prevent starting I/O or mapping the device */ ++ down_write(&bdev->bd_block_size_semaphore); ++ ++ /* Check that the block device is not memory mapped */ ++ mapping = bdev->bd_inode->i_mapping; ++ mutex_lock(&mapping->i_mmap_mutex); ++ if (!prio_tree_empty(&mapping->i_mmap) || ++ !list_empty(&mapping->i_mmap_nonlinear)) { ++ mutex_unlock(&mapping->i_mmap_mutex); ++ up_write(&bdev->bd_block_size_semaphore); ++ return -EBUSY; ++ } ++ mutex_unlock(&mapping->i_mmap_mutex); ++ + /* Don't change the size if it is same as current */ + if (bdev->bd_block_size != size) { + sync_blockdev(bdev); +@@ -131,6 +147,9 @@ + bdev->bd_inode->i_blkbits = blksize_bits(size); + kill_bdev(bdev); + } ++ ++ up_write(&bdev->bd_block_size_semaphore); ++ + return 0; + } + +@@ -472,6 +491,7 @@ + inode_init_once(&ei->vfs_inode); + /* Initialize mutex for freeze. */ + mutex_init(&bdev->bd_fsfreeze_mutex); ++ init_rwsem(&bdev->bd_block_size_semaphore); + } + + static inline void __bd_forget(struct inode *inode) +@@ -1567,6 +1587,22 @@ + return blkdev_ioctl(bdev, mode, cmd, arg); + } + ++ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov, ++ unsigned long nr_segs, loff_t pos) ++{ ++ ssize_t ret; ++ struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); ++ ++ down_read(&bdev->bd_block_size_semaphore); ++ ++ ret = generic_file_aio_read(iocb, iov, nr_segs, pos); ++ ++ up_read(&bdev->bd_block_size_semaphore); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(blkdev_aio_read); ++ + /* + * Write data to the block device. Only intended for the block device itself + * and the raw driver which basically is a fake block device. +@@ -1578,12 +1614,16 @@ + unsigned long nr_segs, loff_t pos) + { + struct file *file = iocb->ki_filp; ++ struct block_device *bdev = I_BDEV(file->f_mapping->host); + struct blk_plug plug; + ssize_t ret; + + BUG_ON(iocb->ki_pos != pos); + + blk_start_plug(&plug); ++ ++ down_read(&bdev->bd_block_size_semaphore); ++ + ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); + if (ret > 0 || ret == -EIOCBQUEUED) { + ssize_t err; +@@ -1592,11 +1632,29 @@ + if (err < 0 && ret > 0) + ret = err; + } ++ ++ up_read(&bdev->bd_block_size_semaphore); ++ + blk_finish_plug(&plug); ++ + return ret; + } + EXPORT_SYMBOL_GPL(blkdev_aio_write); + ++int blkdev_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ int ret; ++ struct block_device *bdev = I_BDEV(file->f_mapping->host); ++ ++ down_read(&bdev->bd_block_size_semaphore); ++ ++ ret = generic_file_mmap(file, vma); ++ ++ up_read(&bdev->bd_block_size_semaphore); ++ ++ return ret; ++} ++ + /* + * Try to release a page associated with block device when the system + * is under memory pressure. +@@ -1627,9 +1685,9 @@ + .llseek = block_llseek, + .read = do_sync_read, + .write = do_sync_write, +- .aio_read = generic_file_aio_read, ++ .aio_read = blkdev_aio_read, + .aio_write = blkdev_aio_write, +- .mmap = generic_file_mmap, ++ .mmap = blkdev_mmap, + .fsync = blkdev_fsync, + .unlocked_ioctl = block_ioctl, + #ifdef CONFIG_COMPAT +Index: linux-3.6.x86_64/include/linux/fs.h +=================================================================== +--- linux-3.6.x86_64.orig/include/linux/fs.h 2012-11-16 17:12:35.127010280 -0500 ++++ linux-3.6.x86_64/include/linux/fs.h 2012-11-16 17:12:37.424002387 -0500 +@@ -724,6 +724,8 @@ + int bd_fsfreeze_count; + /* Mutex for freeze */ + struct mutex bd_fsfreeze_mutex; ++ /* A semaphore that prevents I/O while block size is being changed */ ++ struct rw_semaphore bd_block_size_semaphore; + }; + + /* +@@ -2564,6 +2566,8 @@ + unsigned long *nr_segs, size_t *count, int access_flags); + + /* fs/block_dev.c */ ++extern ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov, ++ unsigned long nr_segs, loff_t pos); + extern ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos); + extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end, diff --git a/blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch b/blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch new file mode 100644 index 000000000..82caa6b76 --- /dev/null +++ b/blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch @@ -0,0 +1,290 @@ +blockdev: turn a rw semaphore into a percpu rw semaphore + +commit 62ac665ff9fc07497ca524bd20d6a96893d11071 +Author: Mikulas Patocka +Date: Wed Sep 26 07:46:43 2012 +0200 + + blockdev: turn a rw semaphore into a percpu rw semaphore + + This avoids cache line bouncing when many processes lock the semaphore + for read. + + New percpu lock implementation + + The lock consists of an array of percpu unsigned integers, a boolean + variable and a mutex. + + When we take the lock for read, we enter rcu read section, check for a + "locked" variable. If it is false, we increase a percpu counter on the + current cpu and exit the rcu section. If "locked" is true, we exit the + rcu section, take the mutex and drop it (this waits until a writer + finished) and retry. + + Unlocking for read just decreases percpu variable. Note that we can + unlock on a difference cpu than where we locked, in this case the + counter underflows. The sum of all percpu counters represents the number + of processes that hold the lock for read. + + When we need to lock for write, we take the mutex, set "locked" variable + to true and synchronize rcu. Since RCU has been synchronized, no + processes can create new read locks. We wait until the sum of percpu + counters is zero - when it is, there are no readers in the critical + section. + + Signed-off-by: Mikulas Patocka + Signed-off-by: Jens Axboe + +Index: linux-3.6.x86_64/Documentation/percpu-rw-semaphore.txt +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-3.6.x86_64/Documentation/percpu-rw-semaphore.txt 2012-11-16 17:12:57.351936583 -0500 +@@ -0,0 +1,27 @@ ++Percpu rw semaphores ++-------------------- ++ ++Percpu rw semaphores is a new read-write semaphore design that is ++optimized for locking for reading. ++ ++The problem with traditional read-write semaphores is that when multiple ++cores take the lock for reading, the cache line containing the semaphore ++is bouncing between L1 caches of the cores, causing performance ++degradation. ++ ++Locking for reading it very fast, it uses RCU and it avoids any atomic ++instruction in the lock and unlock path. On the other hand, locking for ++writing is very expensive, it calls synchronize_rcu() that can take ++hundreds of microseconds. ++ ++The lock is declared with "struct percpu_rw_semaphore" type. ++The lock is initialized percpu_init_rwsem, it returns 0 on success and ++-ENOMEM on allocation failure. ++The lock must be freed with percpu_free_rwsem to avoid memory leak. ++ ++The lock is locked for read with percpu_down_read, percpu_up_read and ++for write with percpu_down_write, percpu_up_write. ++ ++The idea of using RCU for optimized rw-lock was introduced by ++Eric Dumazet . ++The code was written by Mikulas Patocka +Index: linux-3.6.x86_64/fs/block_dev.c +=================================================================== +--- linux-3.6.x86_64.orig/fs/block_dev.c 2012-11-16 17:12:37.381002516 -0500 ++++ linux-3.6.x86_64/fs/block_dev.c 2012-11-16 17:27:41.217005828 -0500 +@@ -127,7 +127,7 @@ + return -EINVAL; + + /* Prevent starting I/O or mapping the device */ +- down_write(&bdev->bd_block_size_semaphore); ++ percpu_down_write(&bdev->bd_block_size_semaphore); + + /* Check that the block device is not memory mapped */ + mapping = bdev->bd_inode->i_mapping; +@@ -135,7 +135,7 @@ + if (!prio_tree_empty(&mapping->i_mmap) || + !list_empty(&mapping->i_mmap_nonlinear)) { + mutex_unlock(&mapping->i_mmap_mutex); +- up_write(&bdev->bd_block_size_semaphore); ++ percpu_up_write(&bdev->bd_block_size_semaphore); + return -EBUSY; + } + mutex_unlock(&mapping->i_mmap_mutex); +@@ -148,7 +148,7 @@ + kill_bdev(bdev); + } + +- up_write(&bdev->bd_block_size_semaphore); ++ percpu_up_write(&bdev->bd_block_size_semaphore); + + return 0; + } +@@ -460,6 +460,12 @@ + struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, GFP_KERNEL); + if (!ei) + return NULL; ++ ++ if (unlikely(percpu_init_rwsem(&ei->bdev.bd_block_size_semaphore))) { ++ kmem_cache_free(bdev_cachep, ei); ++ return NULL; ++ } ++ + return &ei->vfs_inode; + } + +@@ -468,6 +474,8 @@ + struct inode *inode = container_of(head, struct inode, i_rcu); + struct bdev_inode *bdi = BDEV_I(inode); + ++ percpu_free_rwsem(&bdi->bdev.bd_block_size_semaphore); ++ + kmem_cache_free(bdev_cachep, bdi); + } + +@@ -491,7 +499,6 @@ + inode_init_once(&ei->vfs_inode); + /* Initialize mutex for freeze. */ + mutex_init(&bdev->bd_fsfreeze_mutex); +- init_rwsem(&bdev->bd_block_size_semaphore); + } + + static inline void __bd_forget(struct inode *inode) +@@ -1593,11 +1600,11 @@ + ssize_t ret; + struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); + +- down_read(&bdev->bd_block_size_semaphore); ++ percpu_down_read(&bdev->bd_block_size_semaphore); + + ret = generic_file_aio_read(iocb, iov, nr_segs, pos); + +- up_read(&bdev->bd_block_size_semaphore); ++ percpu_up_read(&bdev->bd_block_size_semaphore); + + return ret; + } +@@ -1622,7 +1629,7 @@ + + blk_start_plug(&plug); + +- down_read(&bdev->bd_block_size_semaphore); ++ percpu_down_read(&bdev->bd_block_size_semaphore); + + ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); + if (ret > 0 || ret == -EIOCBQUEUED) { +@@ -1633,7 +1640,7 @@ + ret = err; + } + +- up_read(&bdev->bd_block_size_semaphore); ++ percpu_up_read(&bdev->bd_block_size_semaphore); + + blk_finish_plug(&plug); + +@@ -1646,11 +1653,11 @@ + int ret; + struct block_device *bdev = I_BDEV(file->f_mapping->host); + +- down_read(&bdev->bd_block_size_semaphore); ++ percpu_down_read(&bdev->bd_block_size_semaphore); + + ret = generic_file_mmap(file, vma); + +- up_read(&bdev->bd_block_size_semaphore); ++ percpu_up_read(&bdev->bd_block_size_semaphore); + + return ret; + } +Index: linux-3.6.x86_64/include/linux/fs.h +=================================================================== +--- linux-3.6.x86_64.orig/include/linux/fs.h 2012-11-16 17:12:37.424002387 -0500 ++++ linux-3.6.x86_64/include/linux/fs.h 2012-11-16 17:28:12.578901349 -0500 +@@ -415,6 +415,7 @@ + #include + #include + #include ++#include + + #include + +@@ -725,7 +726,7 @@ + /* Mutex for freeze */ + struct mutex bd_fsfreeze_mutex; + /* A semaphore that prevents I/O while block size is being changed */ +- struct rw_semaphore bd_block_size_semaphore; ++ struct percpu_rw_semaphore bd_block_size_semaphore; + }; + + /* +Index: linux-3.6.x86_64/include/linux/percpu-rwsem.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-3.6.x86_64/include/linux/percpu-rwsem.h 2012-11-16 17:12:57.354936574 -0500 +@@ -0,0 +1,89 @@ ++#ifndef _LINUX_PERCPU_RWSEM_H ++#define _LINUX_PERCPU_RWSEM_H ++ ++#include ++#include ++#include ++#include ++ ++struct percpu_rw_semaphore { ++ unsigned __percpu *counters; ++ bool locked; ++ struct mutex mtx; ++}; ++ ++static inline void percpu_down_read(struct percpu_rw_semaphore *p) ++{ ++ rcu_read_lock(); ++ if (unlikely(p->locked)) { ++ rcu_read_unlock(); ++ mutex_lock(&p->mtx); ++ this_cpu_inc(*p->counters); ++ mutex_unlock(&p->mtx); ++ return; ++ } ++ this_cpu_inc(*p->counters); ++ rcu_read_unlock(); ++} ++ ++static inline void percpu_up_read(struct percpu_rw_semaphore *p) ++{ ++ /* ++ * On X86, write operation in this_cpu_dec serves as a memory unlock ++ * barrier (i.e. memory accesses may be moved before the write, but ++ * no memory accesses are moved past the write). ++ * On other architectures this may not be the case, so we need smp_mb() ++ * there. ++ */ ++#if defined(CONFIG_X86) && (!defined(CONFIG_X86_PPRO_FENCE) && !defined(CONFIG_X86_OOSTORE)) ++ barrier(); ++#else ++ smp_mb(); ++#endif ++ this_cpu_dec(*p->counters); ++} ++ ++static inline unsigned __percpu_count(unsigned __percpu *counters) ++{ ++ unsigned total = 0; ++ int cpu; ++ ++ for_each_possible_cpu(cpu) ++ total += ACCESS_ONCE(*per_cpu_ptr(counters, cpu)); ++ ++ return total; ++} ++ ++static inline void percpu_down_write(struct percpu_rw_semaphore *p) ++{ ++ mutex_lock(&p->mtx); ++ p->locked = true; ++ synchronize_rcu(); ++ while (__percpu_count(p->counters)) ++ msleep(1); ++ smp_rmb(); /* paired with smp_mb() in percpu_sem_up_read() */ ++} ++ ++static inline void percpu_up_write(struct percpu_rw_semaphore *p) ++{ ++ p->locked = false; ++ mutex_unlock(&p->mtx); ++} ++ ++static inline int percpu_init_rwsem(struct percpu_rw_semaphore *p) ++{ ++ p->counters = alloc_percpu(unsigned); ++ if (unlikely(!p->counters)) ++ return -ENOMEM; ++ p->locked = false; ++ mutex_init(&p->mtx); ++ return 0; ++} ++ ++static inline void percpu_free_rwsem(struct percpu_rw_semaphore *p) ++{ ++ free_percpu(p->counters); ++ p->counters = NULL; /* catch use after free bugs */ ++} ++ ++#endif diff --git a/fs-lock-splice_read-and-splice_write-functions.patch b/fs-lock-splice_read-and-splice_write-functions.patch new file mode 100644 index 000000000..938cbd9f5 --- /dev/null +++ b/fs-lock-splice_read-and-splice_write-functions.patch @@ -0,0 +1,74 @@ +Lock splice_read and splice_write functions + +commit 1a25b1c4ce189e3926f2981f3302352a930086db +Author: Mikulas Patocka +Date: Mon Oct 15 17:20:17 2012 -0400 + + Lock splice_read and splice_write functions + + Functions generic_file_splice_read and generic_file_splice_write access + the pagecache directly. For block devices these functions must be locked + so that block size is not changed while they are in progress. + + This patch is an additional fix for commit b87570f5d349 ("Fix a crash + when block device is read and block size is changed at the same time") + that locked aio_read, aio_write and mmap against block size change. + + Signed-off-by: Mikulas Patocka + Signed-off-by: Linus Torvalds + +Index: linux-3.6.x86_64/fs/block_dev.c +=================================================================== +--- linux-3.6.x86_64.orig/fs/block_dev.c 2012-11-16 17:12:57.352936580 -0500 ++++ linux-3.6.x86_64/fs/block_dev.c 2012-11-16 17:13:11.908887989 -0500 +@@ -1662,6 +1662,39 @@ + return ret; + } + ++static ssize_t blkdev_splice_read(struct file *file, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags) ++{ ++ ssize_t ret; ++ struct block_device *bdev = I_BDEV(file->f_mapping->host); ++ ++ percpu_down_read(&bdev->bd_block_size_semaphore); ++ ++ ret = generic_file_splice_read(file, ppos, pipe, len, flags); ++ ++ percpu_up_read(&bdev->bd_block_size_semaphore); ++ ++ return ret; ++} ++ ++static ssize_t blkdev_splice_write(struct pipe_inode_info *pipe, ++ struct file *file, loff_t *ppos, size_t len, ++ unsigned int flags) ++{ ++ ssize_t ret; ++ struct block_device *bdev = I_BDEV(file->f_mapping->host); ++ ++ percpu_down_read(&bdev->bd_block_size_semaphore); ++ ++ ret = generic_file_splice_write(pipe, file, ppos, len, flags); ++ ++ percpu_up_read(&bdev->bd_block_size_semaphore); ++ ++ return ret; ++} ++ ++ + /* + * Try to release a page associated with block device when the system + * is under memory pressure. +@@ -1700,8 +1733,8 @@ + #ifdef CONFIG_COMPAT + .compat_ioctl = compat_blkdev_ioctl, + #endif +- .splice_read = generic_file_splice_read, +- .splice_write = generic_file_splice_write, ++ .splice_read = blkdev_splice_read, ++ .splice_write = blkdev_splice_write, + }; + + int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg) diff --git a/kernel.spec b/kernel.spec index 1eb0430f4..068dbc8bc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -716,6 +716,11 @@ Patch22114: iwlwifi-remove-queue-empty-warn-3.6.patch #rhbz 870562 Patch22115: keyspan.patch +#rhbz 812129 +Patch22120: block-fix-a-crash-when-block-device-is.patch +Patch22121: blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch +Patch22122: fs-lock-splice_read-and-splice_write-functions.patch + # END OF PATCH DEFINITIONS %endif @@ -1349,6 +1354,11 @@ ApplyPatch iwlwifi-remove-queue-empty-warn-3.6.patch #rhbz 870562 ApplyPatch keyspan.patch +#rhbz 812129 +ApplyPatch block-fix-a-crash-when-block-device-is.patch +ApplyPatch blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch +ApplyPatch fs-lock-splice_read-and-splice_write-functions.patch + # END OF PATCH APPLICATIONS %endif @@ -2049,6 +2059,9 @@ fi # and build. %changelog +* Mon Nov 19 2012 Josh Boyer +- Apply patches from Jeff Moyer to fix direct-io oops (rhbz 812129) + * Sat Nov 17 2012 Justin M. Forbes - 3.6.7-1 - linux 3.6.7 From 31066dd569ea26d642fd726fcb18485ad9d1ac3b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 20 Nov 2012 07:51:30 -0500 Subject: [PATCH 463/487] Add support for BCM20702A0 (rhbz 874791) --- Bluetooth-Add-support-for-BCM20702A0.patch | 107 +++++++++++++++++++++ kernel.spec | 11 ++- 2 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 Bluetooth-Add-support-for-BCM20702A0.patch diff --git a/Bluetooth-Add-support-for-BCM20702A0.patch b/Bluetooth-Add-support-for-BCM20702A0.patch new file mode 100644 index 000000000..73f00fc43 --- /dev/null +++ b/Bluetooth-Add-support-for-BCM20702A0.patch @@ -0,0 +1,107 @@ +From 7f198e1cc6d4fda9c84c0da4fc3aafb441342f78 Mon Sep 17 00:00:00 2001 +From: Jaroslav Resler +Date: Tue, 11 Sep 2012 17:25:32 +0800 +Subject: [PATCH 1/2] Bluetooth: Add support for BCM20702A0 [04ca, 2003] + +Add another vendor specific ID for BCM20702A0. + +output of usb-devices: +T: Bus=01 Lev=02 Prnt=02 Port=03 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 +D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 +P: Vendor=04ca ProdID=2003 Rev= 1.12 +S: Manufacturer=Broadcom Corp +S: Product=BCM20702A0 +S: SerialNumber=446D57861623 +C:* #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr= 0mA +I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb +E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms +E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms +E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms +I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb +E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms +E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms +I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb +E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms +E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms +I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb +E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms +E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms +I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb +E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms +E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms +I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb +E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms +E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms +I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb +E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms +E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms +I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) +E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms +E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms +I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) + +Signed-off-by: Cho, Yu-Chen +Signed-off-by: Gustavo Padovan +--- + drivers/bluetooth/btusb.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 654e248..b167944 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -96,6 +96,7 @@ static struct usb_device_id btusb_table[] = { + { USB_DEVICE(0x0c10, 0x0000) }, + + /* Broadcom BCM20702A0 */ ++ { USB_DEVICE(0x04ca, 0x2003) }, + { USB_DEVICE(0x0489, 0xe042) }, + { USB_DEVICE(0x413c, 0x8197) }, + +-- +1.8.0 + + +From a5f86c3423428c8e28b6501d0e9c3929ca91f07d Mon Sep 17 00:00:00 2001 +From: Jeff Cook +Date: Fri, 9 Nov 2012 16:39:48 -0700 +Subject: [PATCH 2/2] Bluetooth: Add support for BCM20702A0 [0b05, 17b5] + +Vendor-specific ID for BCM20702A0. +Support for bluetooth over Asus Wi-Fi GO!, included with Asus P8Z77-V +Deluxe. + +T: Bus=07 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=12 MxCh= 0 +D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 +P: Vendor=0b05 ProdID=17b5 Rev=01.12 +S: Manufacturer=Broadcom Corp +S: Product=BCM20702A0 +S: SerialNumber=94DBC98AC113 +C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=0mA +I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) +I: If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) +I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) +I: If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) + +Cc: stable@vger.kernel.org +Signed-off-by: Jeff Cook +Signed-off-by: Gustavo Padovan +--- + drivers/bluetooth/btusb.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index b167944..6dc44ff 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -96,6 +96,7 @@ static struct usb_device_id btusb_table[] = { + { USB_DEVICE(0x0c10, 0x0000) }, + + /* Broadcom BCM20702A0 */ ++ { USB_DEVICE(0x0b05, 0x17b5) }, + { USB_DEVICE(0x04ca, 0x2003) }, + { USB_DEVICE(0x0489, 0xe042) }, + { USB_DEVICE(0x413c, 0x8197) }, +-- +1.8.0 + diff --git a/kernel.spec b/kernel.spec index 068dbc8bc..45b4c72cb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -721,6 +721,9 @@ Patch22120: block-fix-a-crash-when-block-device-is.patch Patch22121: blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch Patch22122: fs-lock-splice_read-and-splice_write-functions.patch +#rhbz 874791 +Patch22125: Bluetooth-Add-support-for-BCM20702A0.patch + # END OF PATCH DEFINITIONS %endif @@ -1359,6 +1362,9 @@ ApplyPatch block-fix-a-crash-when-block-device-is.patch ApplyPatch blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch ApplyPatch fs-lock-splice_read-and-splice_write-functions.patch +#rhbz 874791 +ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch + # END OF PATCH APPLICATIONS %endif @@ -2059,6 +2065,9 @@ fi # and build. %changelog +* Tue Nov 20 2012 Josh Boyer +- Add support for BCM20702A0 (rhbz 874791) + * Mon Nov 19 2012 Josh Boyer - Apply patches from Jeff Moyer to fix direct-io oops (rhbz 812129) From 0aacb42399ebb7a8fdac9f59428291cf64ed5856 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 20 Nov 2012 12:41:18 -0500 Subject: [PATCH 464/487] CVE-2012-4461: kvm: invalid opcode oops on SET_SREGS with OSXSAVE bit set (rhbz 878518 862900) --- ...opcode-oops-on-SET_SREGS-with-OSXSAV.patch | 83 +++++++++++++++++++ kernel.spec | 9 +- 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch diff --git a/KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch b/KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch new file mode 100644 index 000000000..890bf495e --- /dev/null +++ b/KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch @@ -0,0 +1,83 @@ +From 6d1068b3a98519247d8ba4ec85cd40ac136dbdf9 Mon Sep 17 00:00:00 2001 +From: Petr Matousek +Date: Tue, 6 Nov 2012 19:24:07 +0100 +Subject: [PATCH] KVM: x86: invalid opcode oops on SET_SREGS with OSXSAVE bit + set (CVE-2012-4461) + +On hosts without the XSAVE support unprivileged local user can trigger +oops similar to the one below by setting X86_CR4_OSXSAVE bit in guest +cr4 register using KVM_SET_SREGS ioctl and later issuing KVM_RUN +ioctl. + +invalid opcode: 0000 [#2] SMP +Modules linked in: tun ip6table_filter ip6_tables ebtable_nat ebtables +... +Pid: 24935, comm: zoog_kvm_monito Tainted: G D 3.2.0-3-686-pae +EIP: 0060:[] EFLAGS: 00210246 CPU: 0 +EIP is at kvm_arch_vcpu_ioctl_run+0x92a/0xd13 [kvm] +EAX: 00000001 EBX: 000f387e ECX: 00000000 EDX: 00000000 +ESI: 00000000 EDI: 00000000 EBP: ef5a0060 ESP: d7c63e70 + DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 +Process zoog_kvm_monito (pid: 24935, ti=d7c62000 task=ed84a0c0 +task.ti=d7c62000) +Stack: + 00000001 f70a1200 f8b940a9 ef5a0060 00000000 00200202 f8769009 00000000 + ef5a0060 000f387e eda5c020 8722f9c8 00015bae 00000000 ed84a0c0 ed84a0c0 + c12bf02d 0000ae80 ef7f8740 fffffffb f359b740 ef5a0060 f8b85dc1 0000ae80 +Call Trace: + [] ? kvm_arch_vcpu_ioctl_set_sregs+0x2fe/0x308 [kvm] +... + [] ? syscall_call+0x7/0xb +Code: 89 e8 e8 14 ee ff ff ba 00 00 04 00 89 e8 e8 98 48 ff ff 85 c0 74 +1e 83 7d 48 00 75 18 8b 85 08 07 00 00 31 c9 8b 95 0c 07 00 00 <0f> 01 +d1 c7 45 48 01 00 00 00 c7 45 1c 01 00 00 00 0f ae f0 89 +EIP: [] kvm_arch_vcpu_ioctl_run+0x92a/0xd13 [kvm] SS:ESP +0068:d7c63e70 + +QEMU first retrieves the supported features via KVM_GET_SUPPORTED_CPUID +and then sets them later. So guest's X86_FEATURE_XSAVE should be masked +out on hosts without X86_FEATURE_XSAVE, making kvm_set_cr4 with +X86_CR4_OSXSAVE fail. Userspaces that allow specifying guest cpuid with +X86_FEATURE_XSAVE even on hosts that do not support it, might be +susceptible to this attack from inside the guest as well. + +Allow setting X86_CR4_OSXSAVE bit only if host has XSAVE support. + +Signed-off-by: Petr Matousek +Signed-off-by: Marcelo Tosatti +--- + arch/x86/kvm/cpuid.h | 3 +++ + arch/x86/kvm/x86.c | 3 +++ + 2 files changed, 6 insertions(+) + +diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h +index a10e460..58fc514 100644 +--- a/arch/x86/kvm/cpuid.h ++++ b/arch/x86/kvm/cpuid.h +@@ -24,6 +24,9 @@ static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu) + { + struct kvm_cpuid_entry2 *best; + ++ if (!static_cpu_has(X86_FEATURE_XSAVE)) ++ return 0; ++ + best = kvm_find_cpuid_entry(vcpu, 1, 0); + return best && (best->ecx & bit(X86_FEATURE_XSAVE)); + } +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 224a7e7..4f76417 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -5781,6 +5781,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, + int pending_vec, max_bits, idx; + struct desc_ptr dt; + ++ if (!guest_cpuid_has_xsave(vcpu) && (sregs->cr4 & X86_CR4_OSXSAVE)) ++ return -EINVAL; ++ + dt.size = sregs->idt.limit; + dt.address = sregs->idt.base; + kvm_x86_ops->set_idt(vcpu, &dt); +-- +1.8.0 + diff --git a/kernel.spec b/kernel.spec index 45b4c72cb..4265c30b1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -724,6 +724,9 @@ Patch22122: fs-lock-splice_read-and-splice_write-functions.patch #rhbz 874791 Patch22125: Bluetooth-Add-support-for-BCM20702A0.patch +#rhbz CVE-2012-4461 862900 878518 +Patch21227: KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch + # END OF PATCH DEFINITIONS %endif @@ -1365,6 +1368,9 @@ ApplyPatch fs-lock-splice_read-and-splice_write-functions.patch #rhbz 874791 ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch +#rhbz CVE-2012-4461 862900 878518 +ApplyPatch KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch + # END OF PATCH APPLICATIONS %endif @@ -2066,6 +2072,7 @@ fi %changelog * Tue Nov 20 2012 Josh Boyer +- CVE-2012-4461: kvm: invalid opcode oops on SET_SREGS with OSXSAVE bit set (rhbz 878518 862900) - Add support for BCM20702A0 (rhbz 874791) * Mon Nov 19 2012 Josh Boyer From 27ddac64c7952a0dde94fbc47e5a3c4a57017f1c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 26 Nov 2012 09:03:26 -0500 Subject: [PATCH 465/487] CVE-2012-4530: stack disclosure binfmt_script load_script (rhbz 868285 880147) --- exec-do-not-leave-bprm-interp-on-stack.patch | 118 +++++++++++++++ exec-use-eloop-for-max-recursion-depth.patch | 144 +++++++++++++++++++ kernel.spec | 13 +- 3 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 exec-do-not-leave-bprm-interp-on-stack.patch create mode 100644 exec-use-eloop-for-max-recursion-depth.patch diff --git a/exec-do-not-leave-bprm-interp-on-stack.patch b/exec-do-not-leave-bprm-interp-on-stack.patch new file mode 100644 index 000000000..2a4b2dd28 --- /dev/null +++ b/exec-do-not-leave-bprm-interp-on-stack.patch @@ -0,0 +1,118 @@ +From 20ae2081584450e552735a3df968ce5b5946a607 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Mon, 26 Nov 2012 08:56:37 -0500 +Subject: [PATCH 1/2] exec: do not leave bprm->interp on stack + +If a series of scripts are executed, each triggering module loading via +unprintable bytes in the script header, kernel stack contents can leak +into the command line. + +Normally execution of binfmt_script and binfmt_misc happens recursively. +However, when modules are enabled, and unprintable bytes exist in the +bprm->buf, execution will restart after attempting to load matching binfmt +modules. Unfortunately, the logic in binfmt_script and binfmt_misc does +not expect to get restarted. They leave bprm->interp pointing to their +local stack. This means on restart bprm->interp is left pointing into +unused stack memory which can then be copied into the userspace argv +areas. + +After additional study, it seems that both recursion and restart remains +the desirable way to handle exec with scripts, misc, and modules. As +such, we need to protect the changes to interp. + +This changes the logic to require allocation for any changes to the +bprm->interp. To avoid adding a new kmalloc to every exec, the default +value is left as-is. Only when passing through binfmt_script or +binfmt_misc does an allocation take place. + +For a proof of concept, see DoTest.sh from: +http://www.halfdog.net/Security/2012/LinuxKernelBinfmtScriptStackDataDisclosure/ + +Signed-off-by: Kees Cook +Cc: halfdog +Cc: P J P +Cc: Alexander Viro +Cc: +Signed-off-by: Andrew Morton +--- + fs/binfmt_misc.c | 5 ++++- + fs/binfmt_script.c | 4 +++- + fs/exec.c | 15 +++++++++++++++ + include/linux/binfmts.h | 1 + + 4 files changed, 23 insertions(+), 2 deletions(-) + +diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c +index 790b3cd..772428d 100644 +--- a/fs/binfmt_misc.c ++++ b/fs/binfmt_misc.c +@@ -176,7 +176,10 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) + goto _error; + bprm->argc ++; + +- bprm->interp = iname; /* for binfmt_script */ ++ /* Update interp in case binfmt_script needs it. */ ++ retval = bprm_change_interp(iname, bprm); ++ if (retval < 0) ++ goto _error; + + interp_file = open_exec (iname); + retval = PTR_ERR (interp_file); +diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c +index d3b8c1f..df49d48 100644 +--- a/fs/binfmt_script.c ++++ b/fs/binfmt_script.c +@@ -82,7 +82,9 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs) + retval = copy_strings_kernel(1, &i_name, bprm); + if (retval) return retval; + bprm->argc++; +- bprm->interp = interp; ++ retval = bprm_change_interp(interp, bprm); ++ if (retval < 0) ++ return retval; + + /* + * OK, now restart the process with the interpreter's dentry. +diff --git a/fs/exec.c b/fs/exec.c +index fab2c6d..59896ae 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1202,9 +1202,24 @@ void free_bprm(struct linux_binprm *bprm) + mutex_unlock(¤t->signal->cred_guard_mutex); + abort_creds(bprm->cred); + } ++ /* If a binfmt changed the interp, free it. */ ++ if (bprm->interp != bprm->filename) ++ kfree(bprm->interp); + kfree(bprm); + } + ++int bprm_change_interp(char *interp, struct linux_binprm *bprm) ++{ ++ /* If a binfmt changed the interp, free it first. */ ++ if (bprm->interp != bprm->filename) ++ kfree(bprm->interp); ++ bprm->interp = kstrdup(interp, GFP_KERNEL); ++ if (!bprm->interp) ++ return -ENOMEM; ++ return 0; ++} ++EXPORT_SYMBOL(bprm_change_interp); ++ + /* + * install the new credentials for this executable + */ +diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h +index 366422b..eb53e15 100644 +--- a/include/linux/binfmts.h ++++ b/include/linux/binfmts.h +@@ -128,6 +128,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm, + unsigned long stack_top, + int executable_stack); + extern int bprm_mm_init(struct linux_binprm *bprm); ++extern int bprm_change_interp(char *interp, struct linux_binprm *bprm); + extern int copy_strings_kernel(int argc, const char *const *argv, + struct linux_binprm *bprm); + extern int prepare_bprm_creds(struct linux_binprm *bprm); +-- +1.8.0 + diff --git a/exec-use-eloop-for-max-recursion-depth.patch b/exec-use-eloop-for-max-recursion-depth.patch new file mode 100644 index 000000000..cbaff2f7a --- /dev/null +++ b/exec-use-eloop-for-max-recursion-depth.patch @@ -0,0 +1,144 @@ +From 4ae8186cd77835b45f1b35edb4ce70309287bfc3 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Mon, 26 Nov 2012 09:02:11 -0500 +Subject: [PATCH 2/2] exec: use -ELOOP for max recursion depth + +To avoid an explosion of request_module calls on a chain of abusive +scripts, fail maximum recursion with -ELOOP instead of -ENOEXEC. As soon +as maximum recursion depth is hit, the error will fail all the way back +up the chain, aborting immediately. + +This also has the side-effect of stopping the user's shell from attempting +to reexecute the top-level file as a shell script. As seen in the +dash source: + + if (cmd != path_bshell && errno == ENOEXEC) { + *argv-- = cmd; + *argv = cmd = path_bshell; + goto repeat; + } + +The above logic was designed for running scripts automatically that lacked +the "#!" header, not to re-try failed recursion. On a legitimate -ENOEXEC, +things continue to behave as the shell expects. + +Additionally, when tracking recursion, the binfmt handlers should not be +involved. The recursion being tracked is the depth of calls through +search_binary_handler(), so that function should be exclusively responsible +for tracking the depth. + +Signed-off-by: Kees Cook +Cc: halfdog +Cc: P J P +Cc: Alexander Viro +Signed-off-by: Andrew Morton +--- + fs/binfmt_em86.c | 1 - + fs/binfmt_misc.c | 6 ------ + fs/binfmt_script.c | 4 +--- + fs/exec.c | 10 +++++----- + include/linux/binfmts.h | 2 -- + 5 files changed, 6 insertions(+), 17 deletions(-) + +diff --git a/fs/binfmt_em86.c b/fs/binfmt_em86.c +index 2790c7e..575796a 100644 +--- a/fs/binfmt_em86.c ++++ b/fs/binfmt_em86.c +@@ -42,7 +42,6 @@ static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs) + return -ENOEXEC; + } + +- bprm->recursion_depth++; /* Well, the bang-shell is implicit... */ + allow_write_access(bprm->file); + fput(bprm->file); + bprm->file = NULL; +diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c +index 772428d..f0f1a06 100644 +--- a/fs/binfmt_misc.c ++++ b/fs/binfmt_misc.c +@@ -117,10 +117,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) + if (!enabled) + goto _ret; + +- retval = -ENOEXEC; +- if (bprm->recursion_depth > BINPRM_MAX_RECURSION) +- goto _ret; +- + /* to keep locking time low, we copy the interpreter string */ + read_lock(&entries_lock); + fmt = check_file(bprm); +@@ -200,8 +196,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) + if (retval < 0) + goto _error; + +- bprm->recursion_depth++; +- + retval = search_binary_handler (bprm, regs); + if (retval < 0) + goto _error; +diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c +index df49d48..8ae4be1 100644 +--- a/fs/binfmt_script.c ++++ b/fs/binfmt_script.c +@@ -22,15 +22,13 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs) + char interp[BINPRM_BUF_SIZE]; + int retval; + +- if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') || +- (bprm->recursion_depth > BINPRM_MAX_RECURSION)) ++ if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!')) + return -ENOEXEC; + /* + * This section does the #! interpretation. + * Sorta complicated, but hopefully it will work. -TYT + */ + +- bprm->recursion_depth++; + allow_write_access(bprm->file); + fput(bprm->file); + bprm->file = NULL; +diff --git a/fs/exec.c b/fs/exec.c +index 59896ae..541cc51 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1398,6 +1398,10 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) + struct linux_binfmt *fmt; + pid_t old_pid, old_vpid; + ++ /* This allows 4 levels of binfmt rewrites before failing hard. */ ++ if (depth > 5) ++ return -ELOOP; ++ + retval = security_bprm_check(bprm); + if (retval) + return retval; +@@ -1422,12 +1426,8 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) + if (!try_module_get(fmt->module)) + continue; + read_unlock(&binfmt_lock); ++ bprm->recursion_depth = depth + 1; + retval = fn(bprm, regs); +- /* +- * Restore the depth counter to its starting value +- * in this call, so we don't have to rely on every +- * load_binary function to restore it on return. +- */ + bprm->recursion_depth = depth; + if (retval >= 0) { + if (depth == 0) { +diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h +index eb53e15..5bab59b 100644 +--- a/include/linux/binfmts.h ++++ b/include/linux/binfmts.h +@@ -68,8 +68,6 @@ struct linux_binprm { + #define BINPRM_FLAGS_EXECFD_BIT 1 + #define BINPRM_FLAGS_EXECFD (1 << BINPRM_FLAGS_EXECFD_BIT) + +-#define BINPRM_MAX_RECURSION 4 +- + /* Function parameter for binfmt->coredump */ + struct coredump_params { + long signr; +-- +1.8.0 + diff --git a/kernel.spec b/kernel.spec index 4265c30b1..fdf9eb16e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -727,6 +727,10 @@ Patch22125: Bluetooth-Add-support-for-BCM20702A0.patch #rhbz CVE-2012-4461 862900 878518 Patch21227: KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch +#rhbz CVE-2012-4530 868285 880147 +Patch21228: exec-do-not-leave-bprm-interp-on-stack.patch +Patch21229: exec-use-eloop-for-max-recursion-depth.patch + # END OF PATCH DEFINITIONS %endif @@ -1371,6 +1375,10 @@ ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch #rhbz CVE-2012-4461 862900 878518 ApplyPatch KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch +#rhbz CVE-2012-4530 868285 880147 +ApplyPatch exec-do-not-leave-bprm-interp-on-stack.patch +ApplyPatch exec-use-eloop-for-max-recursion-depth.patch + # END OF PATCH APPLICATIONS %endif @@ -2071,6 +2079,9 @@ fi # and build. %changelog +* Mon Nov 26 2012 Josh Boyer +- CVE-2012-4530: stack disclosure binfmt_script load_script (rhbz 868285 880147) + * Tue Nov 20 2012 Josh Boyer - CVE-2012-4461: kvm: invalid opcode oops on SET_SREGS with OSXSAVE bit set (rhbz 878518 862900) - Add support for BCM20702A0 (rhbz 874791) From 7703a1b33fe7e2b0224009a1a266e121023304af Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 26 Nov 2012 13:42:22 -0500 Subject: [PATCH 466/487] Fix ata command timeout oops in mvsas (rhbz 869629) --- ...as-Fix-oops-when-ata-commond-timeout.patch | 102 ++++++++++++++++++ kernel.spec | 9 +- 2 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch diff --git a/SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch b/SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch new file mode 100644 index 000000000..0d83e8d03 --- /dev/null +++ b/SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch @@ -0,0 +1,102 @@ +From 95ab000388974d8ffef8257306b4be6e8778b768 Mon Sep 17 00:00:00 2001 +From: Jianpeng Ma +Date: Sat, 4 Aug 2012 10:34:14 +0800 +Subject: [PATCH] [SCSI] mvsas: Fix oops when ata commond timeout. + +Kernel message follows: + +[ 511.712011] sd 11:0:0:0: [sdf] command ffff8800a4e81400 timed out +[ 511.712022] sas: Enter sas_scsi_recover_host busy: 1 failed: 1 +[ 511.712024] sas: trying to find task 0xffff8800a4d24c80 +[ 511.712026] sas: sas_scsi_find_task: aborting task 0xffff8800a4d24c80 +[ 511.712029] drivers/scsi/mvsas/mv_sas.c 1631:mvs_abort_task() +mvi=ffff8800b5300000 task=ffff8800a4d24c80 slot=ffff8800b5325038 +slot_idx=x0 +[ 511.712035] BUG: unable to handle kernel NULL pointer dereference at +0000000000000058 +[ 511.712040] IP: [] _raw_spin_lock_irqsave+0xc/0x30 +[ 511.712047] PGD 0 +[ 511.712049] Oops: 0002 [#1] SMP +[ 511.712052] Modules linked in: mvsas libsas scsi_transport_sas +raid456 async_pq async_xor xor async_memcpy async_raid6_recov raid6_pq +async_tx [last unloaded: mvsas] +[ 511.712062] CPU 3 +[ 511.712066] Pid: 7322, comm: scsi_eh_11 Not tainted 3.5.0+ #106 To Be +Filled By O.E.M. To Be Filled By O.E.M./To be filled by O.E.M. +[ 511.712068] RIP: 0010:[] [] +_raw_spin_lock_irqsave+0xc/0x30 +[ 511.712073] RSP: 0018:ffff880098d3bcb0 EFLAGS: 00010086 +[ 511.712074] RAX: 0000000000000286 RBX: 0000000000000058 RCX: +00000000000000c3 +[ 511.712076] RDX: 0000000000000100 RSI: 0000000000000046 RDI: +0000000000000058 +[ 511.712078] RBP: ffff880098d3bcb0 R08: 000000000000000a R09: +0000000000000000 +[ 511.712080] R10: 00000000000004e8 R11: 00000000000004e7 R12: +ffff8800a4d24c80 +[ 511.712082] R13: 0000000000000050 R14: ffff8800b5325038 R15: +ffff8800a4eafe00 +[ 511.712084] FS: 0000000000000000(0000) GS:ffff8800bdb80000(0000) +knlGS:0000000000000000 +[ 511.712086] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b +[ 511.712088] CR2: 0000000000000058 CR3: 00000000a4ce6000 CR4: +00000000000407e0 +[ 511.712090] DR0: 0000000000000000 DR1: 0000000000000000 DR2: +0000000000000000 +[ 511.712091] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: +0000000000000400 +[ 511.712093] Process scsi_eh_11 (pid: 7322, threadinfo +ffff880098d3a000, task ffff8800a61dde40) +[ 511.712095] Stack: +[ 511.712096] ffff880098d3bce0 ffffffff81060683 ffff880000000000 +0000000000000000 +[ 511.712099] ffff8800a4d24c80 ffff8800b5300000 ffff880098d3bcf0 +ffffffffa0076a88 +[ 511.712102] ffff880098d3bd50 ffffffffa0079bb5 ffff880000000000 +ffff880000000018 +[ 511.712106] Call Trace: +[ 511.712110] [] complete+0x23/0x60 +[ 511.712115] [] mvs_tmf_timedout+0x18/0x20 [mvsas] +[ 511.712119] [] mvs_slot_complete+0x765/0x7d0 +[mvsas] +[ 511.712125] [] sas_scsi_recover_host+0x55d/0xdb0 +[libsas] +[ 511.712128] [] ? idle_balance+0xe0/0x130 +[ 511.712133] [] scsi_error_handler+0xcc/0x470 +[ 511.712136] [] ? __schedule+0x370/0x730 +[ 511.712139] [] ? __wake_up_common+0x58/0x90 +[ 511.712142] [] ? scsi_eh_get_sense+0x110/0x110 +[ 511.712146] [] kthread+0x8e/0xa0 +[ 511.712150] [] kernel_thread_helper+0x4/0x10 +[ 511.712153] [] ? flush_kthread_work+0x120/0x120 +[ 511.712156] [] ? gs_change+0xb/0xb +[ 511.712157] Code: 8a 00 01 00 00 89 d0 f0 66 0f b1 0f 66 39 d0 0f 94 +c0 0f b6 c0 5d c3 0f 1f 84 00 00 00 00 00 55 48 89 e5 9c 58 fa ba 00 01 +00 00 66 0f c1 17 0f b6 ce 38 d1 74 11 0f 1f 84 00 00 00 00 00 f3 +[ 511.712191] RIP [] _raw_spin_lock_irqsave+0xc/0x30 +[ 511.712194] RSP +[ 511.712196] CR2: 0000000000000058 +[ 511.712198] ---[ end trace a781c7b1e65db92c ]--- + +Signed-off-by: Jianpeng Ma +Signed-off-by: James Bottomley +--- + drivers/scsi/mvsas/mv_sas.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c +index 4539d59..a3776d6 100644 +--- a/drivers/scsi/mvsas/mv_sas.c ++++ b/drivers/scsi/mvsas/mv_sas.c +@@ -1629,7 +1629,7 @@ int mvs_abort_task(struct sas_task *task) + mv_dprintk("mvs_abort_task() mvi=%p task=%p " + "slot=%p slot_idx=x%x\n", + mvi, task, slot, slot_idx); +- mvs_tmf_timedout((unsigned long)task); ++ task->task_state_flags |= SAS_TASK_STATE_ABORTED; + mvs_slot_task_free(mvi, task, slot, slot_idx); + rc = TMF_RESP_FUNC_COMPLETE; + goto out; +-- +1.8.0 + diff --git a/kernel.spec b/kernel.spec index fdf9eb16e..7d9ddf958 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 5 +%global baserelease 6 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -731,6 +731,9 @@ Patch21227: KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch Patch21228: exec-do-not-leave-bprm-interp-on-stack.patch Patch21229: exec-use-eloop-for-max-recursion-depth.patch +#rhbz 869629 +Patch21230: SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch + # END OF PATCH DEFINITIONS %endif @@ -1379,6 +1382,9 @@ ApplyPatch KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch ApplyPatch exec-do-not-leave-bprm-interp-on-stack.patch ApplyPatch exec-use-eloop-for-max-recursion-depth.patch +#rhbz 869629 +ApplyPatch SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch + # END OF PATCH APPLICATIONS %endif @@ -2080,6 +2086,7 @@ fi %changelog * Mon Nov 26 2012 Josh Boyer +- Fix ata command timeout oops in mvsas (rhbz 869629) - CVE-2012-4530: stack disclosure binfmt_script load_script (rhbz 868285 880147) * Tue Nov 20 2012 Josh Boyer From 909219a1e99df4a9a7d471f16417f72407760e49 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 26 Nov 2012 14:15:41 -0500 Subject: [PATCH 467/487] Fix ACPI video after _DOD errors (rhbz 869383) --- ...-Ignore-errors-after-_DOD-evaluation.patch | 45 +++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 52 insertions(+) create mode 100644 ACPI-video-Ignore-errors-after-_DOD-evaluation.patch diff --git a/ACPI-video-Ignore-errors-after-_DOD-evaluation.patch b/ACPI-video-Ignore-errors-after-_DOD-evaluation.patch new file mode 100644 index 000000000..425acc7a0 --- /dev/null +++ b/ACPI-video-Ignore-errors-after-_DOD-evaluation.patch @@ -0,0 +1,45 @@ +From fba4e087361605d1eed63343bb08811f097c83ee Mon Sep 17 00:00:00 2001 +From: Igor Murzov +Date: Sat, 13 Oct 2012 04:41:25 +0400 +Subject: [PATCH] ACPI video: Ignore errors after _DOD evaluation. + +There are systems where video module known to work fine regardless +of broken _DOD and ignoring returned value here doesn't cause +any issues later. This should fix brightness controls on some laptops. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47861 + +Signed-off-by: Igor Murzov +Reviewed-by: Sergey V +Signed-off-by: Zhang Rui +--- + drivers/acpi/video.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c +index f94d4c8..0230cb6 100644 +--- a/drivers/acpi/video.c ++++ b/drivers/acpi/video.c +@@ -1345,12 +1345,15 @@ static int + acpi_video_bus_get_devices(struct acpi_video_bus *video, + struct acpi_device *device) + { +- int status; ++ int status = 0; + struct acpi_device *dev; + +- status = acpi_video_device_enumerate(video); +- if (status) +- return status; ++ /* ++ * There are systems where video module known to work fine regardless ++ * of broken _DOD and ignoring returned value here doesn't cause ++ * any issues later. ++ */ ++ acpi_video_device_enumerate(video); + + list_for_each_entry(dev, &device->children, node) { + +-- +1.8.0 + diff --git a/kernel.spec b/kernel.spec index 7d9ddf958..bc296e36e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -734,6 +734,9 @@ Patch21229: exec-use-eloop-for-max-recursion-depth.patch #rhbz 869629 Patch21230: SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch +#rhbz 869383 +Patch21231: ACPI-video-Ignore-errors-after-_DOD-evaluation.patch + # END OF PATCH DEFINITIONS %endif @@ -1385,6 +1388,9 @@ ApplyPatch exec-use-eloop-for-max-recursion-depth.patch #rhbz 869629 ApplyPatch SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch +#rhbz 869383 +ApplyPatch ACPI-video-Ignore-errors-after-_DOD-evaluation.patch + # END OF PATCH APPLICATIONS %endif @@ -2086,6 +2092,7 @@ fi %changelog * Mon Nov 26 2012 Josh Boyer +- Fix ACPI video after _DOD errors (rhbz 869383) - Fix ata command timeout oops in mvsas (rhbz 869629) - CVE-2012-4530: stack disclosure binfmt_script load_script (rhbz 868285 880147) From ca7a4a0081d95e2f65585d1d183c982f5a9736f5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 26 Nov 2012 14:48:18 -0500 Subject: [PATCH 468/487] Fix regression in 8139cp driver, debugged by William J. Eaton (rhbz 851278) --- ...t-ring-address-before-enabling-recei.patch | 62 +++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 69 insertions(+) create mode 100644 8139cp-revert-set-ring-address-before-enabling-recei.patch diff --git a/8139cp-revert-set-ring-address-before-enabling-recei.patch b/8139cp-revert-set-ring-address-before-enabling-recei.patch new file mode 100644 index 000000000..d9ca2f2a7 --- /dev/null +++ b/8139cp-revert-set-ring-address-before-enabling-recei.patch @@ -0,0 +1,62 @@ +From b26623dab7eeb1e9f5898c7a49458789dd492f20 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?fran=C3=A7ois=20romieu?= +Date: Wed, 21 Nov 2012 10:07:29 +0000 +Subject: [PATCH] 8139cp: revert "set ring address before enabling receiver" + +This patch reverts b01af4579ec41f48e9b9c774e70bd6474ad210db. + +The original patch was tested with emulated hardware. Real +hardware chokes. + +Fixes https://bugzilla.kernel.org/show_bug.cgi?id=47041 + +Signed-off-by: Francois Romieu +Acked-by: Jeff Garzik +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/realtek/8139cp.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c +index 1c81825..b01f83a 100644 +--- a/drivers/net/ethernet/realtek/8139cp.c ++++ b/drivers/net/ethernet/realtek/8139cp.c +@@ -979,17 +979,6 @@ static void cp_init_hw (struct cp_private *cp) + cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); + cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4))); + +- cpw32_f(HiTxRingAddr, 0); +- cpw32_f(HiTxRingAddr + 4, 0); +- +- ring_dma = cp->ring_dma; +- cpw32_f(RxRingAddr, ring_dma & 0xffffffff); +- cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); +- +- ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; +- cpw32_f(TxRingAddr, ring_dma & 0xffffffff); +- cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); +- + cp_start_hw(cp); + cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */ + +@@ -1003,6 +992,17 @@ static void cp_init_hw (struct cp_private *cp) + + cpw8(Config5, cpr8(Config5) & PMEStatus); + ++ cpw32_f(HiTxRingAddr, 0); ++ cpw32_f(HiTxRingAddr + 4, 0); ++ ++ ring_dma = cp->ring_dma; ++ cpw32_f(RxRingAddr, ring_dma & 0xffffffff); ++ cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); ++ ++ ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; ++ cpw32_f(TxRingAddr, ring_dma & 0xffffffff); ++ cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); ++ + cpw16(MultiIntr, 0); + + cpw8_f(Cfg9346, Cfg9346_Lock); +-- +1.8.0 + diff --git a/kernel.spec b/kernel.spec index bc296e36e..bc7d26999 100644 --- a/kernel.spec +++ b/kernel.spec @@ -737,6 +737,9 @@ Patch21230: SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch #rhbz 869383 Patch21231: ACPI-video-Ignore-errors-after-_DOD-evaluation.patch +#rhbz 851278 +Patch21232: 8139cp-revert-set-ring-address-before-enabling-recei.patch + # END OF PATCH DEFINITIONS %endif @@ -1391,6 +1394,9 @@ ApplyPatch SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch #rhbz 869383 ApplyPatch ACPI-video-Ignore-errors-after-_DOD-evaluation.patch +#rhbz 851278 +ApplyPatch 8139cp-revert-set-ring-address-before-enabling-recei.patch + # END OF PATCH APPLICATIONS %endif @@ -2092,6 +2098,7 @@ fi %changelog * Mon Nov 26 2012 Josh Boyer +- Fix regression in 8139cp driver, debugged by William J. Eaton (rhbz 851278) - Fix ACPI video after _DOD errors (rhbz 869383) - Fix ata command timeout oops in mvsas (rhbz 869629) - CVE-2012-4530: stack disclosure binfmt_script load_script (rhbz 868285 880147) From 68a134c10053e55e014fe4dfef498fde2ce70aaa Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 26 Nov 2012 15:15:00 -0500 Subject: [PATCH 469/487] Add verrel for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index bc7d26999..7f3eaa1e1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2097,7 +2097,7 @@ fi # and build. %changelog -* Mon Nov 26 2012 Josh Boyer +* Mon Nov 26 2012 Josh Boyer - 3.6.7-6 - Fix regression in 8139cp driver, debugged by William J. Eaton (rhbz 851278) - Fix ACPI video after _DOD errors (rhbz 869383) - Fix ata command timeout oops in mvsas (rhbz 869629) From 02636514798f2c8ce3d243d3165cca5728e06057 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 26 Nov 2012 15:37:25 -0500 Subject: [PATCH 470/487] Linux v3.6.8 --- ...-Ignore-errors-after-_DOD-evaluation.patch | 45 ------- ...ifs_lookup-on-hashed-negative-dentry.patch | 19 --- kernel.spec | 27 +--- keyspan.patch | 98 -------------- sources | 2 +- ...crash-at-re-preparing-the-PCM-stream.patch | 125 ------------------ 6 files changed, 6 insertions(+), 310 deletions(-) delete mode 100644 ACPI-video-Ignore-errors-after-_DOD-evaluation.patch delete mode 100644 dont-call-cifs_lookup-on-hashed-negative-dentry.patch delete mode 100644 keyspan.patch delete mode 100644 usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch diff --git a/ACPI-video-Ignore-errors-after-_DOD-evaluation.patch b/ACPI-video-Ignore-errors-after-_DOD-evaluation.patch deleted file mode 100644 index 425acc7a0..000000000 --- a/ACPI-video-Ignore-errors-after-_DOD-evaluation.patch +++ /dev/null @@ -1,45 +0,0 @@ -From fba4e087361605d1eed63343bb08811f097c83ee Mon Sep 17 00:00:00 2001 -From: Igor Murzov -Date: Sat, 13 Oct 2012 04:41:25 +0400 -Subject: [PATCH] ACPI video: Ignore errors after _DOD evaluation. - -There are systems where video module known to work fine regardless -of broken _DOD and ignoring returned value here doesn't cause -any issues later. This should fix brightness controls on some laptops. - -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47861 - -Signed-off-by: Igor Murzov -Reviewed-by: Sergey V -Signed-off-by: Zhang Rui ---- - drivers/acpi/video.c | 11 +++++++---- - 1 file changed, 7 insertions(+), 4 deletions(-) - -diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c -index f94d4c8..0230cb6 100644 ---- a/drivers/acpi/video.c -+++ b/drivers/acpi/video.c -@@ -1345,12 +1345,15 @@ static int - acpi_video_bus_get_devices(struct acpi_video_bus *video, - struct acpi_device *device) - { -- int status; -+ int status = 0; - struct acpi_device *dev; - -- status = acpi_video_device_enumerate(video); -- if (status) -- return status; -+ /* -+ * There are systems where video module known to work fine regardless -+ * of broken _DOD and ignoring returned value here doesn't cause -+ * any issues later. -+ */ -+ acpi_video_device_enumerate(video); - - list_for_each_entry(dev, &device->children, node) { - --- -1.8.0 - diff --git a/dont-call-cifs_lookup-on-hashed-negative-dentry.patch b/dont-call-cifs_lookup-on-hashed-negative-dentry.patch deleted file mode 100644 index 4e25f9d20..000000000 --- a/dont-call-cifs_lookup-on-hashed-negative-dentry.patch +++ /dev/null @@ -1,19 +0,0 @@ -@@ -, +, @@ - cifs_atomic_open - fs/cifs/dir.c | 6 ++++++ - 1 file changed, 6 insertions(+) ---- a/fs/cifs/dir.c -+++ a/fs/cifs/dir.c -@@ -398,6 +398,12 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, - * in network traffic in the other paths. - */ - if (!(oflags & O_CREAT)) { -+ /* Check for hashed negative dentry. We have already revalidated -+ * the dentry and it is fine. No need to perform another lookup. -+ */ -+ if (!d_unhashed(direntry)) -+ return -ENOENT; -+ - struct dentry *res = cifs_lookup(inode, direntry, 0); - if (IS_ERR(res)) - return PTR_ERR(res); diff --git a/kernel.spec b/kernel.spec index 7f3eaa1e1..cf500e39a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 6 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 7 +%define stable_update 8 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -681,9 +681,6 @@ Patch21226: pci-crs-blacklist.patch #rhbz 804957 CVE-2012-1568 Patch21306: shlib_base_randomize.patch -#rhbz 867344 -Patch22077: dont-call-cifs_lookup-on-hashed-negative-dentry.patch - #rhbz 869904 869909 CVE-2012-4508 Patch22080: 0001-ext4-ext4_inode_info-diet.patch Patch22081: 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch @@ -703,7 +700,6 @@ Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch #rhbz 871078 -Patch22110: usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch Patch22111: USB-EHCI-urb-hcpriv-should-not-be-NULL.patch Patch22112: USB-report-submission-of-active-URBs.patch @@ -713,9 +709,6 @@ Patch22113: smp_irq_move_cleanup_interrupt.patch #rhbz 873001 Patch22114: iwlwifi-remove-queue-empty-warn-3.6.patch -#rhbz 870562 -Patch22115: keyspan.patch - #rhbz 812129 Patch22120: block-fix-a-crash-when-block-device-is.patch Patch22121: blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch @@ -734,9 +727,6 @@ Patch21229: exec-use-eloop-for-max-recursion-depth.patch #rhbz 869629 Patch21230: SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch -#rhbz 869383 -Patch21231: ACPI-video-Ignore-errors-after-_DOD-evaluation.patch - #rhbz 851278 Patch21232: 8139cp-revert-set-ring-address-before-enabling-recei.patch @@ -1342,9 +1332,6 @@ ApplyPatch i82975x-edac-fix.patch ApplyPatch weird-root-dentry-name-debug.patch ApplyPatch debug-808990.patch -#rhbz 867344 -ApplyPatch dont-call-cifs_lookup-on-hashed-negative-dentry.patch - #rhbz 869904 869909 CVE-2012-4508 ApplyPatch 0001-ext4-ext4_inode_info-diet.patch ApplyPatch 0002-ext4-give-i_aiodio_unwritten-a-more-appropriate-name.patch @@ -1360,7 +1347,6 @@ ApplyPatch 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch ApplyPatch 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch #rhbz 871078 -ApplyPatch usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch ApplyPatch USB-EHCI-urb-hcpriv-should-not-be-NULL.patch ApplyPatch USB-report-submission-of-active-URBs.patch @@ -1370,9 +1356,6 @@ ApplyPatch smp_irq_move_cleanup_interrupt.patch #rhbz 873001 ApplyPatch iwlwifi-remove-queue-empty-warn-3.6.patch -#rhbz 870562 -ApplyPatch keyspan.patch - #rhbz 812129 ApplyPatch block-fix-a-crash-when-block-device-is.patch ApplyPatch blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch @@ -1391,9 +1374,6 @@ ApplyPatch exec-use-eloop-for-max-recursion-depth.patch #rhbz 869629 ApplyPatch SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch -#rhbz 869383 -ApplyPatch ACPI-video-Ignore-errors-after-_DOD-evaluation.patch - #rhbz 851278 ApplyPatch 8139cp-revert-set-ring-address-before-enabling-recei.patch @@ -2097,6 +2077,9 @@ fi # and build. %changelog +* Mon Nov 26 2012 Josh Boyer - 3.6.8-1 +- Linux v3.6.8 + * Mon Nov 26 2012 Josh Boyer - 3.6.7-6 - Fix regression in 8139cp driver, debugged by William J. Eaton (rhbz 851278) - Fix ACPI video after _DOD errors (rhbz 869383) diff --git a/keyspan.patch b/keyspan.patch deleted file mode 100644 index 43d116ea4..000000000 --- a/keyspan.patch +++ /dev/null @@ -1,98 +0,0 @@ - -Delivered-To: jwboyer@gmail.com -Received: by 10.58.186.240 with SMTP id fn16csp155256vec; - Sat, 10 Nov 2012 01:14:20 -0800 (PST) -Received: by 10.68.130.197 with SMTP id og5mr40733607pbb.138.1352538859530; - Sat, 10 Nov 2012 01:14:19 -0800 (PST) -Return-Path: -Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) - by mx.google.com with ESMTP id pj1si1353832pbc.115.2012.11.10.01.14.15; - Sat, 10 Nov 2012 01:14:19 -0800 (PST) -Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; -Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org -Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand - id S1750798Ab2KJJOO (ORCPT + 33 others); - Sat, 10 Nov 2012 04:14:14 -0500 -Received: from canardo.mork.no ([148.122.252.1]:37367 "EHLO canardo.mork.no" - rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP - id S1750699Ab2KJJOM (ORCPT ); - Sat, 10 Nov 2012 04:14:12 -0500 -Received: from nemi.mork.no (nemi.mork.no [IPv6:2001:4620:9:2:216:eaff:feb3:788]) - (authenticated bits=0) - by canardo.mork.no (8.14.3/8.14.3) with ESMTP id qAA9E1cX010750 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NOT); - Sat, 10 Nov 2012 10:14:02 +0100 -Received: from bjorn by nemi.mork.no with local (Exim 4.80) - (envelope-from ) - id 1TX78a-0007Li-AD; Sat, 10 Nov 2012 10:14:00 +0100 -From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= -To: Richard -Cc: Greg Kroah-Hartman , - linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, - =?UTF-8?q?Bj=C3=B8rn=20Mork?= , - , Johan Hovold -Subject: [PATCH usb-linus] USB: keyspan: fix typo causing GPF on open -Date: Sat, 10 Nov 2012 10:13:42 +0100 -Message-Id: <1352538822-28221-1-git-send-email-bjorn@mork.no> -X-Mailer: git-send-email 1.7.10.4 -In-Reply-To: <509D5BCD.3010901@pacbell.net> -References: <509D5BCD.3010901@pacbell.net> -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit -X-Virus-Scanned: clamav-milter 0.97.6 at canardo -X-Virus-Status: Clean -Sender: stable-owner@vger.kernel.org -Precedence: bulk -List-ID: -X-Mailing-List: stable@vger.kernel.org - -Commit f79b2d0f (USB: keyspan: fix NULL-pointer dereferences and -memory leaks) had a small typo which made the driver use wrong -offsets when mapping serial port private data. This results in -in a GPF when the port is opened. - -Reported-by: Richard -Cc: -Cc: Johan Hovold -Signed-off-by: Bjørn Mork ---- -Hello Richard, - -I wonder if you are able to test and verify this? I do not guarantee -that there aren't other issues around, but this small typo looked like -an obvious killer... - -Bjørn - - drivers/usb/serial/keyspan.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c -index 7179b0c..cff8dd5 100644 ---- a/drivers/usb/serial/keyspan.c -+++ b/drivers/usb/serial/keyspan.c -@@ -2430,7 +2430,7 @@ static void keyspan_release(struct usb_serial *serial) - static int keyspan_port_probe(struct usb_serial_port *port) - { - struct usb_serial *serial = port->serial; -- struct keyspan_port_private *s_priv; -+ struct keyspan_serial_private *s_priv; - struct keyspan_port_private *p_priv; - const struct keyspan_device_details *d_details; - struct callbacks *cback; -@@ -2445,7 +2445,6 @@ static int keyspan_port_probe(struct usb_serial_port *port) - if (!p_priv) - return -ENOMEM; - -- s_priv = usb_get_serial_data(port->serial); - p_priv->device_details = d_details; - - /* Setup values for the various callback routines */ --- -1.7.10.4 - --- -To unsubscribe from this list: send the line "unsubscribe stable" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/sources b/sources index 0d260fa79..891bb1e74 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -134936c362d8812b5cafcf3c67afdce0 patch-3.6.7.xz +f248294551c34753c5c019c8d513280c patch-3.6.8.xz diff --git a/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch b/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch deleted file mode 100644 index 9f3e6f993..000000000 --- a/usb-audio-fix-crash-at-re-preparing-the-PCM-stream.patch +++ /dev/null @@ -1,125 +0,0 @@ -At Thu, 08 Nov 2012 08:31:35 +0100, -Daniel Mack wrote: -(snip) -> >> We can't simply stop both endpoints in the prepare callback. -> > -> > The new function doesn't stop the stream by itself but it just syncs -> > if the stream is being stopped beforehand. So, it's safe to call it -> > there. -> > -> > Maybe the name was confusing. It should have been like -> > snd_usb_endpoint_sync_pending_stop() or such. -> -> Ah, right. I was errornously looking closer to Alan's patch but then -> replied to yours. Alright then - thanks for explaining :) - -OK, thanks for checking. - -FWIW, below is the patch I applied now to for-linus branch. -Renamed the function, added the comment and put NULL check to the -function to simplify. - - -Takashi - ---- -From: Takashi Iwai -Subject: [PATCH] ALSA: usb-audio: Fix crash at re-preparing the PCM stream - -There are bug reports of a crash with USB-audio devices when PCM -prepare is performed immediately after the stream is stopped via -trigger callback. It turned out that the problem is that we don't -wait until all URBs are killed. - -This patch adds a new function to synchronize the pending stop -operation on an endpoint, and calls in the prepare callback for -avoiding the crash above. - -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=49181 - -Reported-and-tested-by: Artem S. Tashkinov -Cc: [v3.6] -Signed-off-by: Takashi Iwai ---- - sound/usb/endpoint.c | 13 +++++++++++++ - sound/usb/endpoint.h | 1 + - sound/usb/pcm.c | 3 +++ - 3 files changed, 17 insertions(+) - -diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c -index 7f78c6d..34de6f2 100644 ---- a/sound/usb/endpoint.c -+++ b/sound/usb/endpoint.c -@@ -35,6 +35,7 @@ - - #define EP_FLAG_ACTIVATED 0 - #define EP_FLAG_RUNNING 1 -+#define EP_FLAG_STOPPING 2 - - /* - * snd_usb_endpoint is a model that abstracts everything related to an -@@ -502,10 +503,20 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) - if (alive) - snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n", - alive, ep->ep_num); -+ clear_bit(EP_FLAG_STOPPING, &ep->flags); - - return 0; - } - -+/* sync the pending stop operation; -+ * this function itself doesn't trigger the stop operation -+ */ -+void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep) -+{ -+ if (ep && test_bit(EP_FLAG_STOPPING, &ep->flags)) -+ wait_clear_urbs(ep); -+} -+ - /* - * unlink active urbs. - */ -@@ -918,6 +929,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, - - if (wait) - wait_clear_urbs(ep); -+ else -+ set_bit(EP_FLAG_STOPPING, &ep->flags); - } - } - -diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h -index 6376ccf..3d4c970 100644 ---- a/sound/usb/endpoint.h -+++ b/sound/usb/endpoint.h -@@ -19,6 +19,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, - int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep); - void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, - int force, int can_sleep, int wait); -+void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep); - int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); - int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep); - void snd_usb_endpoint_free(struct list_head *head); -diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c -index 37428f7..5c12a3f 100644 ---- a/sound/usb/pcm.c -+++ b/sound/usb/pcm.c -@@ -552,6 +552,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) - goto unlock; - } - -+ snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); -+ snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); -+ - /* some unit conversions in runtime */ - subs->data_endpoint->maxframesize = - bytes_to_frames(runtime, subs->data_endpoint->maxpacksize); --- -1.8.0 - - --- -To unsubscribe from this list: send the line "unsubscribe linux-kernel" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html -Please read the FAQ at http://www.tux.org/lkml/ From 826eb776109645585e420bc6044fe75e3d9f46e7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 27 Nov 2012 14:01:21 -0500 Subject: [PATCH 471/487] Update patches for 8139cp issues from David Woodhouse (rhbz 851278) --- ...e-enable-interrupts-after-tx-timeout.patch | 29 +++++ ...t-ring-address-before-enabling-recei.patch | 62 ----------- ...t-ring-address-after-enabling-C-mode.patch | 100 ++++++++++++++++++ kernel.spec | 11 +- 4 files changed, 137 insertions(+), 65 deletions(-) create mode 100644 8139cp-re-enable-interrupts-after-tx-timeout.patch delete mode 100644 8139cp-revert-set-ring-address-before-enabling-recei.patch create mode 100644 8139cp-set-ring-address-after-enabling-C-mode.patch diff --git a/8139cp-re-enable-interrupts-after-tx-timeout.patch b/8139cp-re-enable-interrupts-after-tx-timeout.patch new file mode 100644 index 000000000..c0196188e --- /dev/null +++ b/8139cp-re-enable-interrupts-after-tx-timeout.patch @@ -0,0 +1,29 @@ +From 01ffc0a7f1c1801a2354719dedbc32aff45b987d Mon Sep 17 00:00:00 2001 +From: David Woodhouse +Date: Sat, 24 Nov 2012 12:11:21 +0000 +Subject: [PATCH] 8139cp: re-enable interrupts after tx timeout + +Recovery doesn't work too well if we leave interrupts disabled... + +Signed-off-by: David Woodhouse +Acked-by: Francois Romieu +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/realtek/8139cp.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c +index 3de318d..6cb96b4 100644 +--- a/drivers/net/ethernet/realtek/8139cp.c ++++ b/drivers/net/ethernet/realtek/8139cp.c +@@ -1219,6 +1219,7 @@ static void cp_tx_timeout(struct net_device *dev) + cp_clean_rings(cp); + rc = cp_init_rings(cp); + cp_start_hw(cp); ++ cp_enable_irq(cp); + + netif_wake_queue(dev); + +-- +1.7.6.5 + diff --git a/8139cp-revert-set-ring-address-before-enabling-recei.patch b/8139cp-revert-set-ring-address-before-enabling-recei.patch deleted file mode 100644 index d9ca2f2a7..000000000 --- a/8139cp-revert-set-ring-address-before-enabling-recei.patch +++ /dev/null @@ -1,62 +0,0 @@ -From b26623dab7eeb1e9f5898c7a49458789dd492f20 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?fran=C3=A7ois=20romieu?= -Date: Wed, 21 Nov 2012 10:07:29 +0000 -Subject: [PATCH] 8139cp: revert "set ring address before enabling receiver" - -This patch reverts b01af4579ec41f48e9b9c774e70bd6474ad210db. - -The original patch was tested with emulated hardware. Real -hardware chokes. - -Fixes https://bugzilla.kernel.org/show_bug.cgi?id=47041 - -Signed-off-by: Francois Romieu -Acked-by: Jeff Garzik -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/realtek/8139cp.c | 22 +++++++++++----------- - 1 file changed, 11 insertions(+), 11 deletions(-) - -diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c -index 1c81825..b01f83a 100644 ---- a/drivers/net/ethernet/realtek/8139cp.c -+++ b/drivers/net/ethernet/realtek/8139cp.c -@@ -979,17 +979,6 @@ static void cp_init_hw (struct cp_private *cp) - cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); - cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4))); - -- cpw32_f(HiTxRingAddr, 0); -- cpw32_f(HiTxRingAddr + 4, 0); -- -- ring_dma = cp->ring_dma; -- cpw32_f(RxRingAddr, ring_dma & 0xffffffff); -- cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); -- -- ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; -- cpw32_f(TxRingAddr, ring_dma & 0xffffffff); -- cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); -- - cp_start_hw(cp); - cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */ - -@@ -1003,6 +992,17 @@ static void cp_init_hw (struct cp_private *cp) - - cpw8(Config5, cpr8(Config5) & PMEStatus); - -+ cpw32_f(HiTxRingAddr, 0); -+ cpw32_f(HiTxRingAddr + 4, 0); -+ -+ ring_dma = cp->ring_dma; -+ cpw32_f(RxRingAddr, ring_dma & 0xffffffff); -+ cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); -+ -+ ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; -+ cpw32_f(TxRingAddr, ring_dma & 0xffffffff); -+ cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); -+ - cpw16(MultiIntr, 0); - - cpw8_f(Cfg9346, Cfg9346_Lock); --- -1.8.0 - diff --git a/8139cp-set-ring-address-after-enabling-C-mode.patch b/8139cp-set-ring-address-after-enabling-C-mode.patch new file mode 100644 index 000000000..33bd340e9 --- /dev/null +++ b/8139cp-set-ring-address-after-enabling-C-mode.patch @@ -0,0 +1,100 @@ +From a9dbe40fc10cea2efe6e1ff9e03c62dd7579c5ba Mon Sep 17 00:00:00 2001 +From: David Woodhouse +Date: Wed, 21 Nov 2012 10:27:19 +0000 +Subject: [PATCH] 8139cp: set ring address after enabling C+ mode + +This fixes (for me) a regression introduced by commit b01af457 ("8139cp: +set ring address before enabling receiver"). That commit configured the +descriptor ring addresses earlier in the initialisation sequence, in +order to avoid the possibility of triggering stray DMA before the +correct address had been set up. + +Unfortunately, it seems that the hardware will scribble garbage into the +TxRingAddr registers when we enable "plus mode" Tx in the CpCmd +register. Observed on a Traverse Geos router board. + +To deal with this, while not reintroducing the problem which led to the +original commit, we augment cp_start_hw() to write to the CpCmd register +*first*, then set the descriptor ring addresses, and then finally to +enable Rx and Tx in the original 8139 Cmd register. The datasheet +actually indicates that we should enable Tx/Rx in the Cmd register +*before* configuring the descriptor addresses, but that would appear to +re-introduce the problem that the offending commit b01af457 was trying +to solve. And this variant appears to work fine on real hardware. + +Signed-off-by: David Woodhouse +Cc: stable@kernel.org [3.5+] +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/realtek/8139cp.c | 40 +++++++++++++++++++++++---------- + 1 files changed, 28 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c +index 1c81825..5166d94 100644 +--- a/drivers/net/ethernet/realtek/8139cp.c ++++ b/drivers/net/ethernet/realtek/8139cp.c +@@ -957,7 +957,35 @@ static void cp_reset_hw (struct cp_private *cp) + + static inline void cp_start_hw (struct cp_private *cp) + { ++ dma_addr_t ring_dma; ++ + cpw16(CpCmd, cp->cpcmd); ++ ++ /* ++ * These (at least TxRingAddr) need to be configured after the ++ * corresponding bits in CpCmd are enabled. Datasheet v1.6 §6.33 ++ * (C+ Command Register) recommends that these and more be configured ++ * *after* the [RT]xEnable bits in CpCmd are set. And on some hardware ++ * it's been observed that the TxRingAddr is actually reset to garbage ++ * when C+ mode Tx is enabled in CpCmd. ++ */ ++ cpw32_f(HiTxRingAddr, 0); ++ cpw32_f(HiTxRingAddr + 4, 0); ++ ++ ring_dma = cp->ring_dma; ++ cpw32_f(RxRingAddr, ring_dma & 0xffffffff); ++ cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); ++ ++ ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; ++ cpw32_f(TxRingAddr, ring_dma & 0xffffffff); ++ cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); ++ ++ /* ++ * Strictly speaking, the datasheet says this should be enabled ++ * *before* setting the descriptor addresses. But what, then, would ++ * prevent it from doing DMA to random unconfigured addresses? ++ * This variant appears to work fine. ++ */ + cpw8(Cmd, RxOn | TxOn); + } + +@@ -969,7 +997,6 @@ static void cp_enable_irq(struct cp_private *cp) + static void cp_init_hw (struct cp_private *cp) + { + struct net_device *dev = cp->dev; +- dma_addr_t ring_dma; + + cp_reset_hw(cp); + +@@ -979,17 +1006,6 @@ static void cp_init_hw (struct cp_private *cp) + cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); + cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4))); + +- cpw32_f(HiTxRingAddr, 0); +- cpw32_f(HiTxRingAddr + 4, 0); +- +- ring_dma = cp->ring_dma; +- cpw32_f(RxRingAddr, ring_dma & 0xffffffff); +- cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); +- +- ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; +- cpw32_f(TxRingAddr, ring_dma & 0xffffffff); +- cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); +- + cp_start_hw(cp); + cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */ + +-- +1.7.6.5 + diff --git a/kernel.spec b/kernel.spec index cf500e39a..1a6b1ea83 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -728,7 +728,8 @@ Patch21229: exec-use-eloop-for-max-recursion-depth.patch Patch21230: SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch #rhbz 851278 -Patch21232: 8139cp-revert-set-ring-address-before-enabling-recei.patch +Patch21232: 8139cp-set-ring-address-after-enabling-C-mode.patch +Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch # END OF PATCH DEFINITIONS @@ -1375,7 +1376,8 @@ ApplyPatch exec-use-eloop-for-max-recursion-depth.patch ApplyPatch SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch #rhbz 851278 -ApplyPatch 8139cp-revert-set-ring-address-before-enabling-recei.patch +ApplyPatch 8139cp-set-ring-address-after-enabling-C-mode.patch +ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch # END OF PATCH APPLICATIONS @@ -2077,6 +2079,9 @@ fi # and build. %changelog +* Tue Nov 27 2012 Josh Boyer +- Update patches for 8139cp issues from David Woodhouse (rhbz 851278) + * Mon Nov 26 2012 Josh Boyer - 3.6.8-1 - Linux v3.6.8 From 211b22ddafc20142047bbaf227cf68adbfc34821 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 27 Nov 2012 14:09:05 -0500 Subject: [PATCH 472/487] Add verrel for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 1a6b1ea83..523490267 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2079,7 +2079,7 @@ fi # and build. %changelog -* Tue Nov 27 2012 Josh Boyer +* Tue Nov 27 2012 Josh Boyer - 3.6.8-2 - Update patches for 8139cp issues from David Woodhouse (rhbz 851278) * Mon Nov 26 2012 Josh Boyer - 3.6.8-1 From 78f006e1f1fb728d87f0ac560838e016b1f59d58 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 3 Dec 2012 18:06:47 -0500 Subject: [PATCH 473/487] Linux v3.6.9 --- ...opcode-oops-on-SET_SREGS-with-OSXSAV.patch | 83 ------------------- iwlwifi-remove-queue-empty-warn-3.6.patch | 25 ------ kernel.spec | 19 ++--- sources | 2 +- 4 files changed, 6 insertions(+), 123 deletions(-) delete mode 100644 KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch delete mode 100644 iwlwifi-remove-queue-empty-warn-3.6.patch diff --git a/KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch b/KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch deleted file mode 100644 index 890bf495e..000000000 --- a/KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 6d1068b3a98519247d8ba4ec85cd40ac136dbdf9 Mon Sep 17 00:00:00 2001 -From: Petr Matousek -Date: Tue, 6 Nov 2012 19:24:07 +0100 -Subject: [PATCH] KVM: x86: invalid opcode oops on SET_SREGS with OSXSAVE bit - set (CVE-2012-4461) - -On hosts without the XSAVE support unprivileged local user can trigger -oops similar to the one below by setting X86_CR4_OSXSAVE bit in guest -cr4 register using KVM_SET_SREGS ioctl and later issuing KVM_RUN -ioctl. - -invalid opcode: 0000 [#2] SMP -Modules linked in: tun ip6table_filter ip6_tables ebtable_nat ebtables -... -Pid: 24935, comm: zoog_kvm_monito Tainted: G D 3.2.0-3-686-pae -EIP: 0060:[] EFLAGS: 00210246 CPU: 0 -EIP is at kvm_arch_vcpu_ioctl_run+0x92a/0xd13 [kvm] -EAX: 00000001 EBX: 000f387e ECX: 00000000 EDX: 00000000 -ESI: 00000000 EDI: 00000000 EBP: ef5a0060 ESP: d7c63e70 - DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 -Process zoog_kvm_monito (pid: 24935, ti=d7c62000 task=ed84a0c0 -task.ti=d7c62000) -Stack: - 00000001 f70a1200 f8b940a9 ef5a0060 00000000 00200202 f8769009 00000000 - ef5a0060 000f387e eda5c020 8722f9c8 00015bae 00000000 ed84a0c0 ed84a0c0 - c12bf02d 0000ae80 ef7f8740 fffffffb f359b740 ef5a0060 f8b85dc1 0000ae80 -Call Trace: - [] ? kvm_arch_vcpu_ioctl_set_sregs+0x2fe/0x308 [kvm] -... - [] ? syscall_call+0x7/0xb -Code: 89 e8 e8 14 ee ff ff ba 00 00 04 00 89 e8 e8 98 48 ff ff 85 c0 74 -1e 83 7d 48 00 75 18 8b 85 08 07 00 00 31 c9 8b 95 0c 07 00 00 <0f> 01 -d1 c7 45 48 01 00 00 00 c7 45 1c 01 00 00 00 0f ae f0 89 -EIP: [] kvm_arch_vcpu_ioctl_run+0x92a/0xd13 [kvm] SS:ESP -0068:d7c63e70 - -QEMU first retrieves the supported features via KVM_GET_SUPPORTED_CPUID -and then sets them later. So guest's X86_FEATURE_XSAVE should be masked -out on hosts without X86_FEATURE_XSAVE, making kvm_set_cr4 with -X86_CR4_OSXSAVE fail. Userspaces that allow specifying guest cpuid with -X86_FEATURE_XSAVE even on hosts that do not support it, might be -susceptible to this attack from inside the guest as well. - -Allow setting X86_CR4_OSXSAVE bit only if host has XSAVE support. - -Signed-off-by: Petr Matousek -Signed-off-by: Marcelo Tosatti ---- - arch/x86/kvm/cpuid.h | 3 +++ - arch/x86/kvm/x86.c | 3 +++ - 2 files changed, 6 insertions(+) - -diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h -index a10e460..58fc514 100644 ---- a/arch/x86/kvm/cpuid.h -+++ b/arch/x86/kvm/cpuid.h -@@ -24,6 +24,9 @@ static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu) - { - struct kvm_cpuid_entry2 *best; - -+ if (!static_cpu_has(X86_FEATURE_XSAVE)) -+ return 0; -+ - best = kvm_find_cpuid_entry(vcpu, 1, 0); - return best && (best->ecx & bit(X86_FEATURE_XSAVE)); - } -diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c -index 224a7e7..4f76417 100644 ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -5781,6 +5781,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, - int pending_vec, max_bits, idx; - struct desc_ptr dt; - -+ if (!guest_cpuid_has_xsave(vcpu) && (sregs->cr4 & X86_CR4_OSXSAVE)) -+ return -EINVAL; -+ - dt.size = sregs->idt.limit; - dt.address = sregs->idt.base; - kvm_x86_ops->set_idt(vcpu, &dt); --- -1.8.0 - diff --git a/iwlwifi-remove-queue-empty-warn-3.6.patch b/iwlwifi-remove-queue-empty-warn-3.6.patch deleted file mode 100644 index b8cf5a470..000000000 --- a/iwlwifi-remove-queue-empty-warn-3.6.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c -index 105e3af..79a4ddc 100644 ---- a/drivers/net/wireless/iwlwifi/pcie/tx.c -+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c -@@ -480,20 +480,12 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, - void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) - { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); -- u16 rd_ptr, wr_ptr; -- int n_bd = trans_pcie->txq[txq_id].q.n_bd; - - if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) { - WARN_ONCE(1, "queue %d not used", txq_id); - return; - } - -- rd_ptr = iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & (n_bd - 1); -- wr_ptr = iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)); -- -- WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]", -- txq_id, rd_ptr, wr_ptr); -- - iwl_txq_set_inactive(trans, txq_id); - IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); - } diff --git a/kernel.spec b/kernel.spec index 523490267..6c5332dda 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 8 +%define stable_update 9 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -706,9 +706,6 @@ Patch22112: USB-report-submission-of-active-URBs.patch #rhbz 869341 Patch22113: smp_irq_move_cleanup_interrupt.patch -#rhbz 873001 -Patch22114: iwlwifi-remove-queue-empty-warn-3.6.patch - #rhbz 812129 Patch22120: block-fix-a-crash-when-block-device-is.patch Patch22121: blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch @@ -717,9 +714,6 @@ Patch22122: fs-lock-splice_read-and-splice_write-functions.patch #rhbz 874791 Patch22125: Bluetooth-Add-support-for-BCM20702A0.patch -#rhbz CVE-2012-4461 862900 878518 -Patch21227: KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch - #rhbz CVE-2012-4530 868285 880147 Patch21228: exec-do-not-leave-bprm-interp-on-stack.patch Patch21229: exec-use-eloop-for-max-recursion-depth.patch @@ -1354,9 +1348,6 @@ ApplyPatch USB-report-submission-of-active-URBs.patch #rhbz 869341 ApplyPatch smp_irq_move_cleanup_interrupt.patch -#rhbz 873001 -ApplyPatch iwlwifi-remove-queue-empty-warn-3.6.patch - #rhbz 812129 ApplyPatch block-fix-a-crash-when-block-device-is.patch ApplyPatch blockdev-turn-a-rw-semaphore-into-a-percpu-rw-sem.patch @@ -1365,9 +1356,6 @@ ApplyPatch fs-lock-splice_read-and-splice_write-functions.patch #rhbz 874791 ApplyPatch Bluetooth-Add-support-for-BCM20702A0.patch -#rhbz CVE-2012-4461 862900 878518 -ApplyPatch KVM-x86-invalid-opcode-oops-on-SET_SREGS-with-OSXSAV.patch - #rhbz CVE-2012-4530 868285 880147 ApplyPatch exec-do-not-leave-bprm-interp-on-stack.patch ApplyPatch exec-use-eloop-for-max-recursion-depth.patch @@ -2079,6 +2067,9 @@ fi # and build. %changelog +* Mon Dec 03 2012 Josh Boyer - 3.6.9-1 +- Linux v3.6.9 + * Tue Nov 27 2012 Josh Boyer - 3.6.8-2 - Update patches for 8139cp issues from David Woodhouse (rhbz 851278) diff --git a/sources b/sources index 891bb1e74..7369b3635 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -f248294551c34753c5c019c8d513280c patch-3.6.8.xz +a7c656034599f90dcbc50895b69022aa patch-3.6.9.xz From 61d473f0987e800f650086c69f4adb231e39963c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 3 Dec 2012 18:20:15 -0500 Subject: [PATCH 474/487] Backport 3 upstream fixes to resolve radeon schedule IB errors (rhbz 855275) --- kernel.spec | 11 +- radeon-evergreen-3.6.9-fixes.mbox | 376 ++++++++++++++++++++++++++++++ 2 files changed, 386 insertions(+), 1 deletion(-) create mode 100644 radeon-evergreen-3.6.9-fixes.mbox diff --git a/kernel.spec b/kernel.spec index 6c5332dda..70ac47648 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -725,6 +725,9 @@ Patch21230: SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch Patch21232: 8139cp-set-ring-address-after-enabling-C-mode.patch Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch +#rhbz 855275 +Patch21235: radeon-evergreen-3.6.9-fixes.mbox + # END OF PATCH DEFINITIONS %endif @@ -1367,6 +1370,9 @@ ApplyPatch SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch ApplyPatch 8139cp-set-ring-address-after-enabling-C-mode.patch ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch +#rhbz 855275 +ApplyPatch radeon-evergreen-3.6.9-fixes.mbox + # END OF PATCH APPLICATIONS %endif @@ -2067,6 +2073,9 @@ fi # and build. %changelog +* Mon Dec 03 2012 Josh Boyer - 3.6.9-2 +- Backport 3 upstream fixes to resolve radeon schedule IB errors (rhbz 855275) + * Mon Dec 03 2012 Josh Boyer - 3.6.9-1 - Linux v3.6.9 diff --git a/radeon-evergreen-3.6.9-fixes.mbox b/radeon-evergreen-3.6.9-fixes.mbox new file mode 100644 index 000000000..96628fd2d --- /dev/null +++ b/radeon-evergreen-3.6.9-fixes.mbox @@ -0,0 +1,376 @@ +From 8e502f50fdade16ab4540159218be5d81b678d11 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Mon, 3 Dec 2012 18:12:05 -0500 +Subject: [PATCH 1/3] drm/radeon/dce4+: don't use radeon_crtc for vblank + callback + +Upstream commit 4a15903db02026728d0cf2755c6fabae16b8db6a + +This might be called before we've allocated the radeon_crtcs + +Signed-off-by: Alex Deucher +--- + drivers/gpu/drm/radeon/evergreen.c | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c +index e93b80a..0c79d9e 100644 +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -37,6 +37,16 @@ + #define EVERGREEN_PFP_UCODE_SIZE 1120 + #define EVERGREEN_PM4_UCODE_SIZE 1376 + ++static const u32 crtc_offsets[6] = ++{ ++ EVERGREEN_CRTC0_REGISTER_OFFSET, ++ EVERGREEN_CRTC1_REGISTER_OFFSET, ++ EVERGREEN_CRTC2_REGISTER_OFFSET, ++ EVERGREEN_CRTC3_REGISTER_OFFSET, ++ EVERGREEN_CRTC4_REGISTER_OFFSET, ++ EVERGREEN_CRTC5_REGISTER_OFFSET ++}; ++ + static void evergreen_gpu_init(struct radeon_device *rdev); + void evergreen_fini(struct radeon_device *rdev); + void evergreen_pcie_gen2_enable(struct radeon_device *rdev); +@@ -109,17 +119,19 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev) + */ + void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) + { +- struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; + int i; + +- if (RREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_MASTER_EN) { ++ if (crtc >= rdev->num_crtc) ++ return; ++ ++ if (RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_MASTER_EN) { + for (i = 0; i < rdev->usec_timeout; i++) { +- if (!(RREG32(EVERGREEN_CRTC_STATUS + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_V_BLANK)) ++ if (!(RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK)) + break; + udelay(1); + } + for (i = 0; i < rdev->usec_timeout; i++) { +- if (RREG32(EVERGREEN_CRTC_STATUS + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_V_BLANK) ++ if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK) + break; + udelay(1); + } +-- +1.8.0 + + +From 027eb4090e4261a9b9f5cce47493657d12f2caf3 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Mon, 3 Dec 2012 18:15:21 -0500 +Subject: [PATCH 2/3] drm/radeon: properly handle mc_stop/mc_resume on + evergreen+ (v2) + +Upstream commit 62444b7462a2b98bc78d68736c03a7c4e66ba7e2 + +- Stop the displays from accessing the FB +- Block CPU access +- Turn off MC client access + +This should fix issues some users have seen, especially +with UEFI, when changing the MC FB location that result +in hangs or display corruption. + +v2: fix crtc enabled check noticed by Luca Tettamanti + +Signed-off-by: Alex Deucher +--- + drivers/gpu/drm/radeon/evergreen.c | 169 +++++++++++++++------------------ + drivers/gpu/drm/radeon/evergreen_reg.h | 2 + + drivers/gpu/drm/radeon/evergreend.h | 7 ++ + drivers/gpu/drm/radeon/radeon_asic.h | 1 + + 4 files changed, 88 insertions(+), 91 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c +index 0c79d9e..10b34b8 100644 +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -1241,116 +1241,103 @@ void evergreen_agp_enable(struct radeon_device *rdev) + + void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) + { ++ u32 crtc_enabled, tmp, frame_count, blackout; ++ int i, j; ++ + save->vga_render_control = RREG32(VGA_RENDER_CONTROL); + save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); + +- /* Stop all video */ ++ /* disable VGA render */ + WREG32(VGA_RENDER_CONTROL, 0); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); +- if (rdev->num_crtc >= 4) { +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); +- } +- if (rdev->num_crtc >= 6) { +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); +- } +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); +- if (rdev->num_crtc >= 4) { +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); +- } +- if (rdev->num_crtc >= 6) { +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); +- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); +- } +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); +- if (rdev->num_crtc >= 4) { +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); +- } +- if (rdev->num_crtc >= 6) { +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); +- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); ++ /* blank the display controllers */ ++ for (i = 0; i < rdev->num_crtc; i++) { ++ crtc_enabled = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN; ++ if (crtc_enabled) { ++ save->crtc_enabled[i] = true; ++ if (ASIC_IS_DCE6(rdev)) { ++ tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); ++ if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { ++ radeon_wait_for_vblank(rdev, i); ++ tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; ++ WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); ++ } ++ } else { ++ tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); ++ if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { ++ radeon_wait_for_vblank(rdev, i); ++ tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; ++ WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); ++ } ++ } ++ /* wait for the next frame */ ++ frame_count = radeon_get_vblank_counter(rdev, i); ++ for (j = 0; j < rdev->usec_timeout; j++) { ++ if (radeon_get_vblank_counter(rdev, i) != frame_count) ++ break; ++ udelay(1); ++ } ++ } + } + +- WREG32(D1VGA_CONTROL, 0); +- WREG32(D2VGA_CONTROL, 0); +- if (rdev->num_crtc >= 4) { +- WREG32(EVERGREEN_D3VGA_CONTROL, 0); +- WREG32(EVERGREEN_D4VGA_CONTROL, 0); +- } +- if (rdev->num_crtc >= 6) { +- WREG32(EVERGREEN_D5VGA_CONTROL, 0); +- WREG32(EVERGREEN_D6VGA_CONTROL, 0); ++ radeon_mc_wait_for_idle(rdev); ++ ++ blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); ++ if ((blackout & BLACKOUT_MODE_MASK) != 1) { ++ /* Block CPU access */ ++ WREG32(BIF_FB_EN, 0); ++ /* blackout the MC */ ++ blackout &= ~BLACKOUT_MODE_MASK; ++ WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); + } + } + + void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) + { +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- +- if (rdev->num_crtc >= 4) { +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- } +- if (rdev->num_crtc >= 6) { +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, +- upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, +- (u32)rdev->mc.vram_start); ++ u32 tmp, frame_count; ++ int i, j; + +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, ++ /* update crtc base addresses */ ++ for (i = 0; i < rdev->num_crtc; i++) { ++ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], + upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, ++ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], + upper_32_bits(rdev->mc.vram_start)); +- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, ++ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], + (u32)rdev->mc.vram_start); +- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, ++ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i], + (u32)rdev->mc.vram_start); + } +- + WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); + WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); +- /* Unlock host access */ ++ ++ /* unblackout the MC */ ++ tmp = RREG32(MC_SHARED_BLACKOUT_CNTL); ++ tmp &= ~BLACKOUT_MODE_MASK; ++ WREG32(MC_SHARED_BLACKOUT_CNTL, tmp); ++ /* allow CPU access */ ++ WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); ++ ++ for (i = 0; i < rdev->num_crtc; i++) { ++ if (save->crtc_enabled) { ++ if (ASIC_IS_DCE6(rdev)) { ++ tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); ++ tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; ++ WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); ++ } else { ++ tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); ++ tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; ++ WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); ++ } ++ /* wait for the next frame */ ++ frame_count = radeon_get_vblank_counter(rdev, i); ++ for (j = 0; j < rdev->usec_timeout; j++) { ++ if (radeon_get_vblank_counter(rdev, i) != frame_count) ++ break; ++ udelay(1); ++ } ++ } ++ } ++ /* Unlock vga access */ + WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); + mdelay(1); + WREG32(VGA_RENDER_CONTROL, save->vga_render_control); +diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h +index 8beac10..034f4c2 100644 +--- a/drivers/gpu/drm/radeon/evergreen_reg.h ++++ b/drivers/gpu/drm/radeon/evergreen_reg.h +@@ -218,6 +218,8 @@ + #define EVERGREEN_CRTC_CONTROL 0x6e70 + # define EVERGREEN_CRTC_MASTER_EN (1 << 0) + # define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24) ++#define EVERGREEN_CRTC_BLANK_CONTROL 0x6e74 ++# define EVERGREEN_CRTC_BLANK_DATA_EN (1 << 8) + #define EVERGREEN_CRTC_STATUS 0x6e8c + # define EVERGREEN_CRTC_V_BLANK (1 << 0) + #define EVERGREEN_CRTC_STATUS_POSITION 0x6e90 +diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h +index 302af4f..2bc0f6a 100644 +--- a/drivers/gpu/drm/radeon/evergreend.h ++++ b/drivers/gpu/drm/radeon/evergreend.h +@@ -87,6 +87,10 @@ + + #define CONFIG_MEMSIZE 0x5428 + ++#define BIF_FB_EN 0x5490 ++#define FB_READ_EN (1 << 0) ++#define FB_WRITE_EN (1 << 1) ++ + #define CP_STRMOUT_CNTL 0x84FC + + #define CP_COHER_CNTL 0x85F0 +@@ -434,6 +438,9 @@ + #define NOOFCHAN_MASK 0x00003000 + #define MC_SHARED_CHREMAP 0x2008 + ++#define MC_SHARED_BLACKOUT_CNTL 0x20ac ++#define BLACKOUT_MODE_MASK 0x00000007 ++ + #define MC_ARB_RAMCFG 0x2760 + #define NOOFBANK_SHIFT 0 + #define NOOFBANK_MASK 0x00000003 +diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h +index 18c38d1..132429e 100644 +--- a/drivers/gpu/drm/radeon/radeon_asic.h ++++ b/drivers/gpu/drm/radeon/radeon_asic.h +@@ -389,6 +389,7 @@ void r700_cp_fini(struct radeon_device *rdev); + struct evergreen_mc_save { + u32 vga_render_control; + u32 vga_hdp_control; ++ bool crtc_enabled[RADEON_MAX_CRTCS]; + }; + + void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev); +-- +1.8.0 + + +From 5d46a79118cc6a8f5e30e39f19ad997bb2191b53 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Mon, 3 Dec 2012 18:15:55 -0500 +Subject: [PATCH 3/3] drm/radeon: properly track the crtc not_enabled case + evergreen_mc_stop() + +Upstream commit 804cc4a0ad3a896ca295f771a28c6eb36ced7903 + +The save struct is not initialized previously so explicitly +mark the crtcs as not used when they are not in use. + +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org +--- + drivers/gpu/drm/radeon/evergreen.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c +index 10b34b8..5528fea 100644 +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -1276,6 +1276,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav + break; + udelay(1); + } ++ } else { ++ save->crtc_enabled[i] = false; + } + } + +-- +1.8.0 + From 6ba6704e2fe7401290bf0c12ac9e4459e5ded1d2 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Tue, 11 Dec 2012 08:38:46 -0600 Subject: [PATCH 475/487] Linux 3.6.10 --- ...ing-address-before-enabling-receiver.patch | 64 +++ kernel.spec | 15 +- radeon-evergreen-3.6.9-fixes.mbox | 376 ------------------ sources | 2 +- 4 files changed, 72 insertions(+), 385 deletions(-) create mode 100644 8139cp-revert-set-ring-address-before-enabling-receiver.patch delete mode 100644 radeon-evergreen-3.6.9-fixes.mbox diff --git a/8139cp-revert-set-ring-address-before-enabling-receiver.patch b/8139cp-revert-set-ring-address-before-enabling-receiver.patch new file mode 100644 index 000000000..07ae2c28d --- /dev/null +++ b/8139cp-revert-set-ring-address-before-enabling-receiver.patch @@ -0,0 +1,64 @@ +From b26623dab7eeb1e9f5898c7a49458789dd492f20 Mon Sep 17 00:00:00 2001 +From: Francois Romieu +Date: Wed, 21 Nov 2012 10:07:29 +0000 +Subject: 8139cp: revert "set ring address before enabling receiver" + +From: Francois Romieu + +commit b26623dab7eeb1e9f5898c7a49458789dd492f20 upstream. + +This patch reverts b01af4579ec41f48e9b9c774e70bd6474ad210db. + +The original patch was tested with emulated hardware. Real +hardware chokes. + +Fixes https://bugzilla.kernel.org/show_bug.cgi?id=47041 + +Signed-off-by: Francois Romieu +Acked-by: Jeff Garzik +Signed-off-by: David S. Miller +Signed-off-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/realtek/8139cp.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/drivers/net/ethernet/realtek/8139cp.c ++++ b/drivers/net/ethernet/realtek/8139cp.c +@@ -979,17 +979,6 @@ static void cp_init_hw (struct cp_privat + cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); + cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4))); + +- cpw32_f(HiTxRingAddr, 0); +- cpw32_f(HiTxRingAddr + 4, 0); +- +- ring_dma = cp->ring_dma; +- cpw32_f(RxRingAddr, ring_dma & 0xffffffff); +- cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); +- +- ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; +- cpw32_f(TxRingAddr, ring_dma & 0xffffffff); +- cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); +- + cp_start_hw(cp); + cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */ + +@@ -1003,6 +992,17 @@ static void cp_init_hw (struct cp_privat + + cpw8(Config5, cpr8(Config5) & PMEStatus); + ++ cpw32_f(HiTxRingAddr, 0); ++ cpw32_f(HiTxRingAddr + 4, 0); ++ ++ ring_dma = cp->ring_dma; ++ cpw32_f(RxRingAddr, ring_dma & 0xffffffff); ++ cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); ++ ++ ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; ++ cpw32_f(TxRingAddr, ring_dma & 0xffffffff); ++ cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); ++ + cpw16(MultiIntr, 0); + + cpw8_f(Cfg9346, Cfg9346_Lock); diff --git a/kernel.spec b/kernel.spec index 70ac47648..37761f2ff 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 9 +%define stable_update 10 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -722,12 +722,10 @@ Patch21229: exec-use-eloop-for-max-recursion-depth.patch Patch21230: SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch #rhbz 851278 +Patch21231: 8139cp-revert-set-ring-address-before-enabling-receiver.patch Patch21232: 8139cp-set-ring-address-after-enabling-C-mode.patch Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch -#rhbz 855275 -Patch21235: radeon-evergreen-3.6.9-fixes.mbox - # END OF PATCH DEFINITIONS %endif @@ -1367,12 +1365,10 @@ ApplyPatch exec-use-eloop-for-max-recursion-depth.patch ApplyPatch SCSI-mvsas-Fix-oops-when-ata-commond-timeout.patch #rhbz 851278 +ApplyPatch 8139cp-revert-set-ring-address-before-enabling-receiver.patch -R ApplyPatch 8139cp-set-ring-address-after-enabling-C-mode.patch ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch -#rhbz 855275 -ApplyPatch radeon-evergreen-3.6.9-fixes.mbox - # END OF PATCH APPLICATIONS %endif @@ -2073,6 +2069,9 @@ fi # and build. %changelog +* Tue Dec 11 2012 Justin M. Forbes 3.6.10-1 +- Linux 3.6.10 + * Mon Dec 03 2012 Josh Boyer - 3.6.9-2 - Backport 3 upstream fixes to resolve radeon schedule IB errors (rhbz 855275) diff --git a/radeon-evergreen-3.6.9-fixes.mbox b/radeon-evergreen-3.6.9-fixes.mbox deleted file mode 100644 index 96628fd2d..000000000 --- a/radeon-evergreen-3.6.9-fixes.mbox +++ /dev/null @@ -1,376 +0,0 @@ -From 8e502f50fdade16ab4540159218be5d81b678d11 Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Mon, 3 Dec 2012 18:12:05 -0500 -Subject: [PATCH 1/3] drm/radeon/dce4+: don't use radeon_crtc for vblank - callback - -Upstream commit 4a15903db02026728d0cf2755c6fabae16b8db6a - -This might be called before we've allocated the radeon_crtcs - -Signed-off-by: Alex Deucher ---- - drivers/gpu/drm/radeon/evergreen.c | 20 ++++++++++++++++---- - 1 file changed, 16 insertions(+), 4 deletions(-) - -diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c -index e93b80a..0c79d9e 100644 ---- a/drivers/gpu/drm/radeon/evergreen.c -+++ b/drivers/gpu/drm/radeon/evergreen.c -@@ -37,6 +37,16 @@ - #define EVERGREEN_PFP_UCODE_SIZE 1120 - #define EVERGREEN_PM4_UCODE_SIZE 1376 - -+static const u32 crtc_offsets[6] = -+{ -+ EVERGREEN_CRTC0_REGISTER_OFFSET, -+ EVERGREEN_CRTC1_REGISTER_OFFSET, -+ EVERGREEN_CRTC2_REGISTER_OFFSET, -+ EVERGREEN_CRTC3_REGISTER_OFFSET, -+ EVERGREEN_CRTC4_REGISTER_OFFSET, -+ EVERGREEN_CRTC5_REGISTER_OFFSET -+}; -+ - static void evergreen_gpu_init(struct radeon_device *rdev); - void evergreen_fini(struct radeon_device *rdev); - void evergreen_pcie_gen2_enable(struct radeon_device *rdev); -@@ -109,17 +119,19 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev) - */ - void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) - { -- struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; - int i; - -- if (RREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_MASTER_EN) { -+ if (crtc >= rdev->num_crtc) -+ return; -+ -+ if (RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_MASTER_EN) { - for (i = 0; i < rdev->usec_timeout; i++) { -- if (!(RREG32(EVERGREEN_CRTC_STATUS + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_V_BLANK)) -+ if (!(RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK)) - break; - udelay(1); - } - for (i = 0; i < rdev->usec_timeout; i++) { -- if (RREG32(EVERGREEN_CRTC_STATUS + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_V_BLANK) -+ if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK) - break; - udelay(1); - } --- -1.8.0 - - -From 027eb4090e4261a9b9f5cce47493657d12f2caf3 Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Mon, 3 Dec 2012 18:15:21 -0500 -Subject: [PATCH 2/3] drm/radeon: properly handle mc_stop/mc_resume on - evergreen+ (v2) - -Upstream commit 62444b7462a2b98bc78d68736c03a7c4e66ba7e2 - -- Stop the displays from accessing the FB -- Block CPU access -- Turn off MC client access - -This should fix issues some users have seen, especially -with UEFI, when changing the MC FB location that result -in hangs or display corruption. - -v2: fix crtc enabled check noticed by Luca Tettamanti - -Signed-off-by: Alex Deucher ---- - drivers/gpu/drm/radeon/evergreen.c | 169 +++++++++++++++------------------ - drivers/gpu/drm/radeon/evergreen_reg.h | 2 + - drivers/gpu/drm/radeon/evergreend.h | 7 ++ - drivers/gpu/drm/radeon/radeon_asic.h | 1 + - 4 files changed, 88 insertions(+), 91 deletions(-) - -diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c -index 0c79d9e..10b34b8 100644 ---- a/drivers/gpu/drm/radeon/evergreen.c -+++ b/drivers/gpu/drm/radeon/evergreen.c -@@ -1241,116 +1241,103 @@ void evergreen_agp_enable(struct radeon_device *rdev) - - void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) - { -+ u32 crtc_enabled, tmp, frame_count, blackout; -+ int i, j; -+ - save->vga_render_control = RREG32(VGA_RENDER_CONTROL); - save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); - -- /* Stop all video */ -+ /* disable VGA render */ - WREG32(VGA_RENDER_CONTROL, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); -- if (rdev->num_crtc >= 4) { -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); -- } -- if (rdev->num_crtc >= 6) { -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); -- } -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); -- if (rdev->num_crtc >= 4) { -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); -- } -- if (rdev->num_crtc >= 6) { -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); -- } -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); -- if (rdev->num_crtc >= 4) { -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); -- } -- if (rdev->num_crtc >= 6) { -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); -- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); -+ /* blank the display controllers */ -+ for (i = 0; i < rdev->num_crtc; i++) { -+ crtc_enabled = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN; -+ if (crtc_enabled) { -+ save->crtc_enabled[i] = true; -+ if (ASIC_IS_DCE6(rdev)) { -+ tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); -+ if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { -+ radeon_wait_for_vblank(rdev, i); -+ tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; -+ WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); -+ } -+ } else { -+ tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); -+ if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { -+ radeon_wait_for_vblank(rdev, i); -+ tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; -+ WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); -+ } -+ } -+ /* wait for the next frame */ -+ frame_count = radeon_get_vblank_counter(rdev, i); -+ for (j = 0; j < rdev->usec_timeout; j++) { -+ if (radeon_get_vblank_counter(rdev, i) != frame_count) -+ break; -+ udelay(1); -+ } -+ } - } - -- WREG32(D1VGA_CONTROL, 0); -- WREG32(D2VGA_CONTROL, 0); -- if (rdev->num_crtc >= 4) { -- WREG32(EVERGREEN_D3VGA_CONTROL, 0); -- WREG32(EVERGREEN_D4VGA_CONTROL, 0); -- } -- if (rdev->num_crtc >= 6) { -- WREG32(EVERGREEN_D5VGA_CONTROL, 0); -- WREG32(EVERGREEN_D6VGA_CONTROL, 0); -+ radeon_mc_wait_for_idle(rdev); -+ -+ blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); -+ if ((blackout & BLACKOUT_MODE_MASK) != 1) { -+ /* Block CPU access */ -+ WREG32(BIF_FB_EN, 0); -+ /* blackout the MC */ -+ blackout &= ~BLACKOUT_MODE_MASK; -+ WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); - } - } - - void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) - { -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- -- if (rdev->num_crtc >= 4) { -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- } -- if (rdev->num_crtc >= 6) { -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, -- upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, -- (u32)rdev->mc.vram_start); -+ u32 tmp, frame_count; -+ int i, j; - -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, -+ /* update crtc base addresses */ -+ for (i = 0; i < rdev->num_crtc; i++) { -+ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], - upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, -+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], - upper_32_bits(rdev->mc.vram_start)); -- WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, -+ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], - (u32)rdev->mc.vram_start); -- WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, -+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i], - (u32)rdev->mc.vram_start); - } -- - WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); -- /* Unlock host access */ -+ -+ /* unblackout the MC */ -+ tmp = RREG32(MC_SHARED_BLACKOUT_CNTL); -+ tmp &= ~BLACKOUT_MODE_MASK; -+ WREG32(MC_SHARED_BLACKOUT_CNTL, tmp); -+ /* allow CPU access */ -+ WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); -+ -+ for (i = 0; i < rdev->num_crtc; i++) { -+ if (save->crtc_enabled) { -+ if (ASIC_IS_DCE6(rdev)) { -+ tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); -+ tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; -+ WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); -+ } else { -+ tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); -+ tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; -+ WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); -+ } -+ /* wait for the next frame */ -+ frame_count = radeon_get_vblank_counter(rdev, i); -+ for (j = 0; j < rdev->usec_timeout; j++) { -+ if (radeon_get_vblank_counter(rdev, i) != frame_count) -+ break; -+ udelay(1); -+ } -+ } -+ } -+ /* Unlock vga access */ - WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); - mdelay(1); - WREG32(VGA_RENDER_CONTROL, save->vga_render_control); -diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h -index 8beac10..034f4c2 100644 ---- a/drivers/gpu/drm/radeon/evergreen_reg.h -+++ b/drivers/gpu/drm/radeon/evergreen_reg.h -@@ -218,6 +218,8 @@ - #define EVERGREEN_CRTC_CONTROL 0x6e70 - # define EVERGREEN_CRTC_MASTER_EN (1 << 0) - # define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24) -+#define EVERGREEN_CRTC_BLANK_CONTROL 0x6e74 -+# define EVERGREEN_CRTC_BLANK_DATA_EN (1 << 8) - #define EVERGREEN_CRTC_STATUS 0x6e8c - # define EVERGREEN_CRTC_V_BLANK (1 << 0) - #define EVERGREEN_CRTC_STATUS_POSITION 0x6e90 -diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h -index 302af4f..2bc0f6a 100644 ---- a/drivers/gpu/drm/radeon/evergreend.h -+++ b/drivers/gpu/drm/radeon/evergreend.h -@@ -87,6 +87,10 @@ - - #define CONFIG_MEMSIZE 0x5428 - -+#define BIF_FB_EN 0x5490 -+#define FB_READ_EN (1 << 0) -+#define FB_WRITE_EN (1 << 1) -+ - #define CP_STRMOUT_CNTL 0x84FC - - #define CP_COHER_CNTL 0x85F0 -@@ -434,6 +438,9 @@ - #define NOOFCHAN_MASK 0x00003000 - #define MC_SHARED_CHREMAP 0x2008 - -+#define MC_SHARED_BLACKOUT_CNTL 0x20ac -+#define BLACKOUT_MODE_MASK 0x00000007 -+ - #define MC_ARB_RAMCFG 0x2760 - #define NOOFBANK_SHIFT 0 - #define NOOFBANK_MASK 0x00000003 -diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h -index 18c38d1..132429e 100644 ---- a/drivers/gpu/drm/radeon/radeon_asic.h -+++ b/drivers/gpu/drm/radeon/radeon_asic.h -@@ -389,6 +389,7 @@ void r700_cp_fini(struct radeon_device *rdev); - struct evergreen_mc_save { - u32 vga_render_control; - u32 vga_hdp_control; -+ bool crtc_enabled[RADEON_MAX_CRTCS]; - }; - - void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev); --- -1.8.0 - - -From 5d46a79118cc6a8f5e30e39f19ad997bb2191b53 Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Mon, 3 Dec 2012 18:15:55 -0500 -Subject: [PATCH 3/3] drm/radeon: properly track the crtc not_enabled case - evergreen_mc_stop() - -Upstream commit 804cc4a0ad3a896ca295f771a28c6eb36ced7903 - -The save struct is not initialized previously so explicitly -mark the crtcs as not used when they are not in use. - -Signed-off-by: Alex Deucher -Cc: stable@vger.kernel.org ---- - drivers/gpu/drm/radeon/evergreen.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c -index 10b34b8..5528fea 100644 ---- a/drivers/gpu/drm/radeon/evergreen.c -+++ b/drivers/gpu/drm/radeon/evergreen.c -@@ -1276,6 +1276,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav - break; - udelay(1); - } -+ } else { -+ save->crtc_enabled[i] = false; - } - } - --- -1.8.0 - diff --git a/sources b/sources index 7369b3635..eebf282fc 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -a7c656034599f90dcbc50895b69022aa patch-3.6.9.xz +406a52f90a2ddc78a3ecdf4fe46e7cf7 patch-3.6.10.xz From 551dcfff5066c9f79612505d5262d2641e07f280 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 11 Dec 2012 12:03:22 -0500 Subject: [PATCH 476/487] Fix IBSS scanning in mac80211 (rhbz 883414) --- kernel.spec | 12 ++- mac80211-fix-ibss-scanning.patch | 132 +++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 mac80211-fix-ibss-scanning.patch diff --git a/kernel.spec b/kernel.spec index 37761f2ff..31f33ce4c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -726,6 +726,9 @@ Patch21231: 8139cp-revert-set-ring-address-before-enabling-receiver.patch Patch21232: 8139cp-set-ring-address-after-enabling-C-mode.patch Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch +#rhbz 883414 +Patch21234: mac80211-fix-ibss-scanning.patch + # END OF PATCH DEFINITIONS %endif @@ -1369,6 +1372,10 @@ ApplyPatch 8139cp-revert-set-ring-address-before-enabling-receiver.patch -R ApplyPatch 8139cp-set-ring-address-after-enabling-C-mode.patch ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch +#rhbz 883414 +ApplyPatch mac80211-fix-ibss-scanning.patch + + # END OF PATCH APPLICATIONS %endif @@ -2069,6 +2076,9 @@ fi # and build. %changelog +* Tue Dec 11 2012 Josh Boyer +- Fix IBSS scanning in mac80211 (rhbz 883414) + * Tue Dec 11 2012 Justin M. Forbes 3.6.10-1 - Linux 3.6.10 diff --git a/mac80211-fix-ibss-scanning.patch b/mac80211-fix-ibss-scanning.patch new file mode 100644 index 000000000..c2bc698a0 --- /dev/null +++ b/mac80211-fix-ibss-scanning.patch @@ -0,0 +1,132 @@ +Do not scan on no-IBSS and disabled channels in IBSS mode. Doing this +can trigger Microcode errors on iwlwifi and iwlegacy drivers. + +Also rename ieee80211_request_internal_scan() function since it is only +used in IBSS mode and simplify calling it from ieee80211_sta_find_ibss(). + +This patch should address: +https://bugzilla.redhat.com/show_bug.cgi?id=883414 +https://bugzilla.kernel.org/show_bug.cgi?id=49411 + +Reported-by: Jesse Kahtava +Reported-by: Mikko Rapeli +Cc: stable@vger.kernel.org +Signed-off-by: Stanislaw Gruszka +--- + net/mac80211/ibss.c | 9 ++++----- + net/mac80211/ieee80211_i.h | 6 +++--- + net/mac80211/scan.c | 34 ++++++++++++++++++++++++---------- + 3 files changed, 31 insertions(+), 18 deletions(-) + +diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c +index c21e33d..d9df6b8 100644 +--- a/net/mac80211/ibss.c ++++ b/net/mac80211/ibss.c +@@ -678,8 +678,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) + sdata_info(sdata, + "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n"); + +- ieee80211_request_internal_scan(sdata, +- ifibss->ssid, ifibss->ssid_len, NULL); ++ ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, ++ NULL); + } + + static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) +@@ -777,9 +777,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) + IEEE80211_SCAN_INTERVAL)) { + sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); + +- ieee80211_request_internal_scan(sdata, +- ifibss->ssid, ifibss->ssid_len, +- ifibss->fixed_channel ? ifibss->channel : NULL); ++ ieee80211_request_ibss_scan(sdata, ifibss->ssid, ++ ifibss->ssid_len, chan); + } else { + int interval = IEEE80211_SCAN_INTERVAL; + +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 156e583..bc48d4d 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1247,9 +1247,9 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, + + /* scan/BSS handling */ + void ieee80211_scan_work(struct work_struct *work); +-int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, +- const u8 *ssid, u8 ssid_len, +- struct ieee80211_channel *chan); ++int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, ++ const u8 *ssid, u8 ssid_len, ++ struct ieee80211_channel *chan); + int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, + struct cfg80211_scan_request *req); + void ieee80211_scan_cancel(struct ieee80211_local *local); +diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c +index 43e60b5..fab706f 100644 +--- a/net/mac80211/scan.c ++++ b/net/mac80211/scan.c +@@ -819,9 +819,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, + return res; + } + +-int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, +- const u8 *ssid, u8 ssid_len, +- struct ieee80211_channel *chan) ++int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, ++ const u8 *ssid, u8 ssid_len, ++ struct ieee80211_channel *chan) + { + struct ieee80211_local *local = sdata->local; + int ret = -EBUSY; +@@ -835,22 +835,36 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, + + /* fill internal scan request */ + if (!chan) { +- int i, nchan = 0; ++ int i, max_n; ++ int n_ch = 0; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (!local->hw.wiphy->bands[band]) + continue; +- for (i = 0; +- i < local->hw.wiphy->bands[band]->n_channels; +- i++) { +- local->int_scan_req->channels[nchan] = ++ ++ max_n = local->hw.wiphy->bands[band]->n_channels; ++ for (i = 0; i < max_n; i++) { ++ struct ieee80211_channel *tmp_ch = + &local->hw.wiphy->bands[band]->channels[i]; +- nchan++; ++ ++ if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_DISABLED)) ++ continue; ++ ++ local->int_scan_req->channels[n_ch] = tmp_ch; ++ n_ch++; + } + } + +- local->int_scan_req->n_channels = nchan; ++ if (WARN_ON_ONCE(n_ch == 0)) ++ goto unlock; ++ ++ local->int_scan_req->n_channels = n_ch; + } else { ++ if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_DISABLED))) ++ goto unlock; ++ + local->int_scan_req->channels[0] = chan; + local->int_scan_req->n_channels = 1; + } +-- +1.7.1 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-wireless" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file From 87db8bc3ed43bf7c33303243573e8a804e2160d3 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 17 Dec 2012 09:04:27 -0500 Subject: [PATCH 477/487] Fix oops in sony-laptop setup (rhbz 873107) --- ...-do-proper-memcpy-for-ACPI_TYPE_INTE.patch | 50 +++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch diff --git a/0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch b/0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch new file mode 100644 index 000000000..857c73c51 --- /dev/null +++ b/0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch @@ -0,0 +1,50 @@ +From 690b1ad9d2032d6f2565d44f6564590d47835ae8 Mon Sep 17 00:00:00 2001 +From: Zhang Rui +Date: Thu, 29 Nov 2012 01:30:43 +0800 +Subject: [PATCH 1/2] ACPI sony-laptop: do proper memcpy for ACPI_TYPE_INTEGER + acpi_object + +the return value of __call_snc_method can either be +an ACPI_TYPE_BUFFER object or a ACPI_TYPE_INTEGER object. +do proper memcpy for ACPI_TYPE_INTEGER object. + +https://bugzilla.kernel.org/show_bug.cgi?id=50111 + +Signed-off-by: Zhang Rui +--- + drivers/platform/x86/sony-laptop.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c +index daaddec..92e0da2 100644 +--- a/drivers/platform/x86/sony-laptop.c ++++ b/drivers/platform/x86/sony-laptop.c +@@ -792,20 +792,19 @@ static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value, + if (!object) + return -EINVAL; + +- if (object->type == ACPI_TYPE_BUFFER) ++ if (object->type == ACPI_TYPE_BUFFER) { + len = MIN(buflen, object->buffer.length); +- +- else if (object->type == ACPI_TYPE_INTEGER) ++ memcpy(buffer, object->buffer.pointer, len); ++ } else if (object->type == ACPI_TYPE_INTEGER) { + len = MIN(buflen, sizeof(object->integer.value)); +- +- else { ++ memcpy(buffer, (void *)&object->integer.value, len); ++ } else { + pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", + ACPI_TYPE_BUFFER, object->type); + kfree(object); + return -EINVAL; + } + +- memcpy(buffer, object->buffer.pointer, len); + kfree(object); + return 0; + } +-- +1.7.9.5 + diff --git a/kernel.spec b/kernel.spec index 31f33ce4c..e2b45c236 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -729,6 +729,9 @@ Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch #rhbz 883414 Patch21234: mac80211-fix-ibss-scanning.patch +#rhbz 873107 +Patch21237: 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch + # END OF PATCH DEFINITIONS %endif @@ -1375,6 +1378,9 @@ ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch #rhbz 883414 ApplyPatch mac80211-fix-ibss-scanning.patch +#rhbz 873107 +ApplyPatch 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch + # END OF PATCH APPLICATIONS @@ -2076,6 +2082,9 @@ fi # and build. %changelog +* Mon Dec 17 2012 Josh Boyer +- Fix oops in sony-laptop setup (rhbz 873107) + * Tue Dec 11 2012 Josh Boyer - Fix IBSS scanning in mac80211 (rhbz 883414) From c51ab15fea321a90f30a588569e6e2cc3cc0ee5f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 17 Dec 2012 14:54:40 -0500 Subject: [PATCH 478/487] Linux v3.6.11 --- USB-EHCI-urb-hcpriv-should-not-be-NULL.patch | 72 -- i82975x-edac-fix.patch | 855 ------------------- kernel.spec | 11 +- sources | 2 +- 4 files changed, 4 insertions(+), 936 deletions(-) delete mode 100644 USB-EHCI-urb-hcpriv-should-not-be-NULL.patch delete mode 100644 i82975x-edac-fix.patch diff --git a/USB-EHCI-urb-hcpriv-should-not-be-NULL.patch b/USB-EHCI-urb-hcpriv-should-not-be-NULL.patch deleted file mode 100644 index 4b8e537c4..000000000 --- a/USB-EHCI-urb-hcpriv-should-not-be-NULL.patch +++ /dev/null @@ -1,72 +0,0 @@ -commit 2656a9abcf1ec8dd5fee6a75d6997a0f2fa0094e -Author: Alan Stern -Date: Thu Nov 8 10:17:01 2012 -0500 - - USB: EHCI: bugfix: urb->hcpriv should not be NULL - - This patch (as1632b) fixes a bug in ehci-hcd. The USB core uses - urb->hcpriv to determine whether or not an URB is active; host - controller drivers are supposed to set this pointer to a non-NULL - value when an URB is queued. However ehci-hcd sets it to NULL for - isochronous URBs, which defeats the check in usbcore. - - In itself this isn't a big deal. But people have recently found that - certain sequences of actions will cause the snd-usb-audio driver to - reuse URBs without waiting for them to complete. In the absence of - proper checking by usbcore, the URBs get added to their endpoint list - twice. This leads to list corruption and a system freeze. - - The patch makes ehci-hcd assign a meaningful value to urb->hcpriv for - isochronous URBs. Improving robustness always helps. - - Signed-off-by: Alan Stern - Reported-by: Artem S. Tashkinov - Reported-by: Christof Meerwald - CC: - Signed-off-by: Greg Kroah-Hartman - -diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c -index 4b66374..3d98902 100644 ---- a/drivers/usb/host/ehci-q.c -+++ b/drivers/usb/host/ehci-q.c -@@ -264,15 +264,9 @@ ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status) - __releases(ehci->lock) - __acquires(ehci->lock) - { -- if (likely (urb->hcpriv != NULL)) { -- struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; -- -- /* S-mask in a QH means it's an interrupt urb */ -- if ((qh->hw->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) { -- -- /* ... update hc-wide periodic stats (for usbfs) */ -- ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; -- } -+ if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { -+ /* ... update hc-wide periodic stats */ -+ ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; - } - - if (unlikely(urb->unlinked)) { -diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c -index 2e14714..69ebee7 100644 ---- a/drivers/usb/host/ehci-sched.c -+++ b/drivers/usb/host/ehci-sched.c -@@ -1630,7 +1630,7 @@ static void itd_link_urb( - - /* don't need that schedule data any more */ - iso_sched_free (stream, iso_sched); -- urb->hcpriv = NULL; -+ urb->hcpriv = stream; - - ++ehci->isoc_count; - enable_periodic(ehci); -@@ -2029,7 +2029,7 @@ static void sitd_link_urb( - - /* don't need that schedule data any more */ - iso_sched_free (stream, sched); -- urb->hcpriv = NULL; -+ urb->hcpriv = stream; - - ++ehci->isoc_count; - enable_periodic(ehci); diff --git a/i82975x-edac-fix.patch b/i82975x-edac-fix.patch deleted file mode 100644 index f44ac7791..000000000 --- a/i82975x-edac-fix.patch +++ /dev/null @@ -1,855 +0,0 @@ -commit 9370a8d717720f6b17221490fea8d798396d9f2f -Author: Mauro Carvalho Chehab -Date: Mon Oct 15 21:49:35 2012 -0300 - - i82975x_edac: Use the edac standard debug macro - - Instead of declaring its own debug macro, that requires - to uncomment part of the code, use the edac standard macro - to add the debug code, and the edac debug level to print it, - just like any other EDAC driver. - - Signed-off-by: Mauro Carvalho Chehab - -diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c -index a980204..f998d2c 100644 ---- a/drivers/edac/i82975x_edac.c -+++ b/drivers/edac/i82975x_edac.c -@@ -435,11 +435,9 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, - } - } - --/* #define i82975x_DEBUG_IOMEM */ -- --#ifdef i82975x_DEBUG_IOMEM --static void i82975x_print_dram_timings(void __iomem *mch_window) -+static void i82975x_print_dram_config(void __iomem *mch_window, u32 mchbar, u32 *drc) - { -+#ifdef CONFIG_EDAC_DEBUG - /* - * The register meanings are from Intel specs; - * (shows 13-5-5-5 for 800-DDR2) -@@ -448,26 +446,63 @@ static void i82975x_print_dram_timings(void __iomem *mch_window) - */ - static const int caslats[4] = { 5, 4, 3, 6 }; - u32 dtreg[2]; -+ u8 c0drb[4]; -+ u8 c1drb[4]; -+ -+ if (!edac_debug_level) -+ return; -+ -+ i82975x_printk(KERN_INFO, "MCHBAR real = %0x, remapped = %p\n", -+ mchbar, mch_window); -+ -+ c0drb[0] = readb(mch_window + I82975X_DRB_CH0R0); -+ c0drb[1] = readb(mch_window + I82975X_DRB_CH0R1); -+ c0drb[2] = readb(mch_window + I82975X_DRB_CH0R2); -+ c0drb[3] = readb(mch_window + I82975X_DRB_CH0R3); -+ c1drb[0] = readb(mch_window + I82975X_DRB_CH1R0); -+ c1drb[1] = readb(mch_window + I82975X_DRB_CH1R1); -+ c1drb[2] = readb(mch_window + I82975X_DRB_CH1R2); -+ c1drb[3] = readb(mch_window + I82975X_DRB_CH1R3); -+ i82975x_printk(KERN_INFO, "DRBCH0R0 = 0x%02x\n", c0drb[0]); -+ i82975x_printk(KERN_INFO, "DRBCH0R1 = 0x%02x\n", c0drb[1]); -+ i82975x_printk(KERN_INFO, "DRBCH0R2 = 0x%02x\n", c0drb[2]); -+ i82975x_printk(KERN_INFO, "DRBCH0R3 = 0x%02x\n", c0drb[3]); -+ i82975x_printk(KERN_INFO, "DRBCH1R0 = 0x%02x\n", c1drb[0]); -+ i82975x_printk(KERN_INFO, "DRBCH1R1 = 0x%02x\n", c1drb[1]); -+ i82975x_printk(KERN_INFO, "DRBCH1R2 = 0x%02x\n", c1drb[2]); -+ i82975x_printk(KERN_INFO, "DRBCH1R3 = 0x%02x\n", c1drb[3]); -+ -+ i82975x_printk(KERN_INFO, "DRC_CH0 = %0x, %s\n", drc[0], -+ ((drc[0] >> 21) & 3) == 1 ? -+ "ECC enabled" : "ECC disabled"); -+ i82975x_printk(KERN_INFO, "DRC_CH1 = %0x, %s\n", drc[1], -+ ((drc[1] >> 21) & 3) == 1 ? -+ "ECC enabled" : "ECC disabled"); -+ -+ i82975x_printk(KERN_INFO, "C0 BNKARC = %0x\n", -+ readw(mch_window + I82975X_C0BNKARC)); -+ i82975x_printk(KERN_INFO, "C1 BNKARC = %0x\n", -+ readw(mch_window + I82975X_C1BNKARC)); - - dtreg[0] = readl(mch_window + 0x114); - dtreg[1] = readl(mch_window + 0x194); -- i82975x_printk(KERN_INFO, "DRAM Timings : Ch0 Ch1\n" -+ i82975x_printk(KERN_INFO, -+ "DRAM Timings : Ch0 Ch1\n" - " RAS Active Min = %d %d\n" - " CAS latency = %d %d\n" - " RAS to CAS = %d %d\n" - " RAS precharge = %d %d\n", - (dtreg[0] >> 19 ) & 0x0f, -- (dtreg[1] >> 19) & 0x0f, -+ (dtreg[1] >> 19) & 0x0f, - caslats[(dtreg[0] >> 8) & 0x03], -- caslats[(dtreg[1] >> 8) & 0x03], -+ caslats[(dtreg[1] >> 8) & 0x03], - ((dtreg[0] >> 4) & 0x07) + 2, -- ((dtreg[1] >> 4) & 0x07) + 2, -+ ((dtreg[1] >> 4) & 0x07) + 2, - (dtreg[0] & 0x07) + 2, -- (dtreg[1] & 0x07) + 2 -+ (dtreg[1] & 0x07) + 2 - ); -- --} - #endif -+} - - static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) - { -@@ -480,10 +515,6 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) - u32 drc[2]; - struct i82975x_error_info discard; - int chans; --#ifdef i82975x_DEBUG_IOMEM -- u8 c0drb[4]; -- u8 c1drb[4]; --#endif - - edac_dbg(0, "\n"); - -@@ -495,45 +526,11 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) - mchbar &= 0xffffc000; /* bits 31:14 used for 16K window */ - mch_window = ioremap_nocache(mchbar, 0x1000); - --#ifdef i82975x_DEBUG_IOMEM -- i82975x_printk(KERN_INFO, "MCHBAR real = %0x, remapped = %p\n", -- mchbar, mch_window); -- -- c0drb[0] = readb(mch_window + I82975X_DRB_CH0R0); -- c0drb[1] = readb(mch_window + I82975X_DRB_CH0R1); -- c0drb[2] = readb(mch_window + I82975X_DRB_CH0R2); -- c0drb[3] = readb(mch_window + I82975X_DRB_CH0R3); -- c1drb[0] = readb(mch_window + I82975X_DRB_CH1R0); -- c1drb[1] = readb(mch_window + I82975X_DRB_CH1R1); -- c1drb[2] = readb(mch_window + I82975X_DRB_CH1R2); -- c1drb[3] = readb(mch_window + I82975X_DRB_CH1R3); -- i82975x_printk(KERN_INFO, "DRBCH0R0 = 0x%02x\n", c0drb[0]); -- i82975x_printk(KERN_INFO, "DRBCH0R1 = 0x%02x\n", c0drb[1]); -- i82975x_printk(KERN_INFO, "DRBCH0R2 = 0x%02x\n", c0drb[2]); -- i82975x_printk(KERN_INFO, "DRBCH0R3 = 0x%02x\n", c0drb[3]); -- i82975x_printk(KERN_INFO, "DRBCH1R0 = 0x%02x\n", c1drb[0]); -- i82975x_printk(KERN_INFO, "DRBCH1R1 = 0x%02x\n", c1drb[1]); -- i82975x_printk(KERN_INFO, "DRBCH1R2 = 0x%02x\n", c1drb[2]); -- i82975x_printk(KERN_INFO, "DRBCH1R3 = 0x%02x\n", c1drb[3]); --#endif -- - drc[0] = readl(mch_window + I82975X_DRC_CH0M0); - drc[1] = readl(mch_window + I82975X_DRC_CH1M0); --#ifdef i82975x_DEBUG_IOMEM -- i82975x_printk(KERN_INFO, "DRC_CH0 = %0x, %s\n", drc[0], -- ((drc[0] >> 21) & 3) == 1 ? -- "ECC enabled" : "ECC disabled"); -- i82975x_printk(KERN_INFO, "DRC_CH1 = %0x, %s\n", drc[1], -- ((drc[1] >> 21) & 3) == 1 ? -- "ECC enabled" : "ECC disabled"); - -- i82975x_printk(KERN_INFO, "C0 BNKARC = %0x\n", -- readw(mch_window + I82975X_C0BNKARC)); -- i82975x_printk(KERN_INFO, "C1 BNKARC = %0x\n", -- readw(mch_window + I82975X_C1BNKARC)); -- i82975x_print_dram_timings(mch_window); -- goto fail1; --#endif -+ i82975x_print_dram_config(mch_window, mchbar, drc); -+ - if (!(((drc[0] >> 21) & 3) == 1 || ((drc[1] >> 21) & 3) == 1)) { - i82975x_printk(KERN_INFO, "ECC disabled on both channels.\n"); - goto fail1; - -commit 8992ed2f4295eab137e1713fa16be5546a759373 -Author: Mauro Carvalho Chehab -Date: Mon Oct 15 21:48:48 2012 -0300 - - i82975x_edac: Fix dimm label initialization - - The driver has only 4 hardcoded labels, but allows much more memory. - Fix it by removing the hardcoded logic, using snprintf() instead. - - [ 19.833972] general protection fault: 0000 [#1] SMP - [ 19.837733] Modules linked in: i82975x_edac(+) edac_core firewire_ohci firewire_core crc_itu_t nouveau mxm_wmi wmi video i2c_algo_bit drm_kms_helper ttm drm i2c_core - [ 19.837733] CPU 0 - [ 19.837733] Pid: 390, comm: udevd Not tainted 3.6.1-1.fc17.x86_64.debug #1 Dell Inc. Precision WorkStation 390 /0MY510 - [ 19.837733] RIP: 0010:[] [] strncpy+0x18/0x30 - [ 19.837733] RSP: 0018:ffff880078535b68 EFLAGS: 00010202 - [ 19.837733] RAX: ffff880069fa9708 RBX: ffff880078588000 RCX: ffff880069fa9708 - [ 19.837733] RDX: 000000000000001f RSI: 5f706f5f63616465 RDI: ffff880069fa9708 - [ 19.837733] RBP: ffff880078535b68 R08: ffff880069fa9727 R09: 000000000000fffe - [ 19.837733] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000003 - [ 19.837733] R13: 0000000000000000 R14: ffff880069fa9290 R15: ffff880079624a80 - [ 19.837733] FS: 00007f3de01ee840(0000) GS:ffff88007c400000(0000) knlGS:0000000000000000 - [ 19.837733] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 - [ 19.837733] CR2: 00007f3de00b9000 CR3: 0000000078dbc000 CR4: 00000000000007f0 - [ 19.837733] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 - [ 19.837733] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 - [ 19.837733] Process udevd (pid: 390, threadinfo ffff880078534000, task ffff880079642450) - [ 19.837733] Stack: - [ 19.837733] ffff880078535c18 ffffffffa017c6b8 00040000816d627f ffff880079624a88 - [ 19.837733] ffffc90004cd6000 ffff880079624520 ffff88007ac21148 0000000000000000 - [ 19.837733] 0000000000000000 0004000000000000 feda000078535bc8 ffffffff810d696d - [ 19.837733] Call Trace: - [ 19.837733] [] i82975x_init_one+0x2e6/0x3e6 [i82975x_edac] - ... - - Fix bug reported at: - https://bugzilla.redhat.com/show_bug.cgi?id=848149 - And, very likely: - https://bbs.archlinux.org/viewtopic.php?id=148033 - https://bugzilla.kernel.org/show_bug.cgi?id=47171 - - Cc: Alan Cox - Signed-off-by: Mauro Carvalho Chehab - -diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c -index 069e26c..a980204 100644 ---- a/drivers/edac/i82975x_edac.c -+++ b/drivers/edac/i82975x_edac.c -@@ -370,10 +370,6 @@ static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank) - static void i82975x_init_csrows(struct mem_ctl_info *mci, - struct pci_dev *pdev, void __iomem *mch_window) - { -- static const char *labels[4] = { -- "DIMM A1", "DIMM A2", -- "DIMM B1", "DIMM B2" -- }; - struct csrow_info *csrow; - unsigned long last_cumul_size; - u8 value; -@@ -423,9 +419,10 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, - dimm = mci->csrows[index]->channels[chan]->dimm; - - dimm->nr_pages = nr_pages / csrow->nr_channels; -- strncpy(csrow->channels[chan]->dimm->label, -- labels[(index >> 1) + (chan * 2)], -- EDAC_MC_LABEL_LEN); -+ -+ snprintf(csrow->channels[chan]->dimm->label, EDAC_MC_LABEL_LEN, "DIMM %c%d", -+ (chan == 0) ? 'A' : 'B', -+ index); - dimm->grain = 1 << 7; /* 128Byte cache-line resolution */ - dimm->dtype = i82975x_dram_type(mch_window, index); - dimm->mtype = MEM_DDR2; /* I82975x supports only DDR2 */ -commit 6e7636c972951ba0c6c640758b1dcc7667cb2415 -Author: Mauro Carvalho Chehab -Date: Tue Oct 16 15:30:23 2012 -0300 - - i82975x_edac: rewrite the entire fill/report logic - - There are so many bugs at the fill/error report logic that - the code ended by being re-written. - - Issues solved: - - - DIMM labels were "randomly" filled: they won't - match the memory layout, due to a series of bugs on it; - - - The memory controller supports 3 different modes: - single, dual interleaved and dual async. The logic there were - written considering the dual interleaved one (yet, some - single mode support was there); - - - The boundary limit to decide on each channel the error happens, - at dual interleaved mode, is given by bit 6 of the error address, - and not bit 1. The practical effect is that Corrected errors - will have a 50% of chance of pointing to the right DIMM. Only - the DIMM pair logic were OK; - - - The asymetric mode weren't properly supported. The driver would - handle an asymetric mode as 'single mode', with doesn't actually - match it, creating some weird real/virtual DIMM mappings. - - - Some other random bugs got fixed. - - Tested on a Dell Precision N390, on dual interleaved mode. - - Signed-off-by: Mauro Carvalho Chehab - -diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c -index f998d2c..082e91e 100644 ---- a/drivers/edac/i82975x_edac.c -+++ b/drivers/edac/i82975x_edac.c -@@ -6,7 +6,17 @@ - * GNU General Public License. - * - * Written by Arvind R. -- * Copied from i82875p_edac.c source: -+ * Copied from i82875p_edac.c source, -+ * -+ * (c) 2012 Mauro Carvalho Chehab -+ * Driver re-written in order to fix lots of issues on it: -+ * - Fix Single Mode; -+ * - Add support for Asymetrical mode -+ * - Fix several issues with Interleaved mode -+ * - Fix memory label logic -+ * -+ * Intel datasheet: Intel(R) 975X Express Chipset Datasheet -+ * http://www.intel.com/assets/pdf/datasheet/310158.pdf - */ - - #include -@@ -29,8 +39,8 @@ - #define PCI_DEVICE_ID_INTEL_82975_0 0x277c - #endif /* PCI_DEVICE_ID_INTEL_82975_0 */ - --#define I82975X_NR_DIMMS 8 --#define I82975X_NR_CSROWS(nr_chans) (I82975X_NR_DIMMS / (nr_chans)) -+#define DIMMS_PER_CHANNEL 4 -+#define NUM_CHANNELS 2 - - /* Intel 82975X register addresses - device 0 function 0 - DRAM Controller */ - #define I82975X_EAP 0x58 /* Dram Error Address Pointer (32b) -@@ -112,7 +122,7 @@ NOTE: Only ONE of the three must be enabled - /* NOTE: Following addresses have to indexed using MCHBAR offset (44h, 32b) */ - /* Intel 82975x memory mapped register space */ - --#define I82975X_DRB_SHIFT 25 /* fixed 32MiB grain */ -+#define I82975X_DRB_SHIFT 25 /* fixed 2^25 = 32 MiB grain */ - - #define I82975X_DRB 0x100 /* DRAM Row Boundary (8b x 8) - * -@@ -152,6 +162,10 @@ NOTE: Only ONE of the three must be enabled - #define I82975X_DRA_CH1R01 0x188 - #define I82975X_DRA_CH1R23 0x189 - -+/* Channels 0/1 DRAM Timing Register 1 */ -+#define I82975X_C0DRT1 0x114 -+#define I82975X_C1DRT1 0x194 -+ - - #define I82975X_BNKARC 0x10e /* Type of device in each rank - Bank Arch (16b) - * -@@ -206,8 +220,16 @@ enum i82975x_chips { - I82975X = 0, - }; - -+struct mem_range { -+ u32 start, end; -+}; -+ - struct i82975x_pvt { -- void __iomem *mch_window; -+ void __iomem *mch_window; -+ int num_channels; -+ bool is_symetric; -+ u8 drb[DIMMS_PER_CHANNEL][NUM_CHANNELS]; -+ struct mem_range page[DIMMS_PER_CHANNEL][NUM_CHANNELS]; - }; - - struct i82975x_dev_info { -@@ -278,8 +300,10 @@ static void i82975x_get_error_info(struct mem_ctl_info *mci, - static int i82975x_process_error_info(struct mem_ctl_info *mci, - struct i82975x_error_info *info, int handle_errors) - { -- int row, chan; -- unsigned long offst, page; -+ struct i82975x_pvt *pvt = mci->pvt_info; -+ struct mem_range *range; -+ unsigned int row, chan, grain; -+ unsigned long offst, page; - - if (!(info->errsts2 & 0x0003)) - return 0; -@@ -293,36 +317,70 @@ static int i82975x_process_error_info(struct mem_ctl_info *mci, - info->errsts = info->errsts2; - } - -+ /* Calculate page and offset of the error */ -+ - page = (unsigned long) info->eap; - page >>= 1; -+ - if (info->xeap & 1) - page |= 0x80000000; - page >>= (PAGE_SHIFT - 1); -- row = edac_mc_find_csrow_by_page(mci, page); -- -- if (row == -1) { -- i82975x_mc_printk(mci, KERN_ERR, "error processing EAP:\n" -- "\tXEAP=%u\n" -- "\t EAP=0x%08x\n" -- "\tPAGE=0x%08x\n", -- (info->xeap & 1) ? 1 : 0, info->eap, (unsigned int) page); -- return 0; -+ -+ if (pvt->is_symetric) -+ grain = 1 << 7; -+ else -+ grain = 1 << 6; -+ -+ offst = info->eap & ((1 << PAGE_SHIFT) - (1 << grain)); -+ -+ /* -+ * Search for the DIMM chip that match the error page. -+ * -+ * On Symmetric mode, this will always return channel = 0, as -+ * both channel A and B ranges are identical. -+ * A latter logic will determinte the channel on symetric mode -+ * -+ * On asymetric mode or single mode, there will be just one match, -+ * that will point to the csrow with the error. -+ */ -+ for (chan = 0; chan < pvt->num_channels; chan++) { -+ for (row = 0; row < DIMMS_PER_CHANNEL; row++) { -+ range = &pvt->page[row][chan]; -+ -+ if (page >= range->start && page <= range->end) -+ goto found; -+ } - } -- chan = (mci->csrows[row]->nr_channels == 1) ? 0 : info->eap & 1; -- offst = info->eap -- & ((1 << PAGE_SHIFT) - -- (1 << mci->csrows[row]->channels[chan]->dimm->grain)); -+ chan = -1; -+ row = -1; - -- if (info->errsts & 0x0002) -+found: -+ if (info->errsts & 0x0002) { -+ /* -+ * On uncorrected error, ECC doesn't allow do determine the -+ * channel where the error has occurred. -+ */ - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, - page, offst, 0, - row, -1, -1, - "i82975x UE", ""); -- else -- edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, -- page, offst, info->derrsyn, -- row, chan ? chan : 0, -1, -- "i82975x CE", ""); -+ return 1; -+ } -+ -+ if (pvt->is_symetric && row >= 0) { -+ /* -+ * On Symetric mode, the memory switch happens after each -+ * cache line (64 byte boundary). Channel 0 goes first. -+ */ -+ if (info->eap & (1 << 6)) -+ chan = 1; -+ else -+ chan = 0; -+ } -+ edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, -+ page, offst, info->derrsyn, -+ row, chan, -1, -+ "i82975x CE", ""); - - return 1; - } -@@ -331,111 +389,143 @@ static void i82975x_check(struct mem_ctl_info *mci) - { - struct i82975x_error_info info; - -- edac_dbg(1, "MC%d\n", mci->mc_idx); -+ edac_dbg(4, "MC%d\n", mci->mc_idx); - i82975x_get_error_info(mci, &info); - i82975x_process_error_info(mci, &info, 1); - } - --/* Return 1 if dual channel mode is active. Else return 0. */ --static int dual_channel_active(void __iomem *mch_window) -+/** -+ * detect_memory_style - Detect on what mode the memory controller is programmed -+ * -+ * @pvt: pointer to the private structure -+ * -+ * This function detects how many channels are in use, and if the memory -+ * controller is in symetric (interleaved) or asymetric mode. There's no -+ * need to distinguish between asymetric and single mode, as the routines -+ * that fill the csrows data and handle error are written in order to handle -+ * both at the same way. -+ */ -+static void detect_memory_style(struct i82975x_pvt *pvt) - { -- /* -- * We treat interleaved-symmetric configuration as dual-channel - EAP's -- * bit-0 giving the channel of the error location. -- * -- * All other configurations are treated as single channel - the EAP's -- * bit-0 will resolve ok in symmetric area of mixed -- * (symmetric/asymmetric) configurations -- */ -- u8 drb[4][2]; - int row; -- int dualch; -+ bool has_chan_a = false; -+ bool has_chan_b = false; -+ -+ pvt->is_symetric = true; -+ pvt->num_channels = 0; -+ -+ for (row = 0; row < DIMMS_PER_CHANNEL; row++) { -+ pvt->drb[row][0] = readb(pvt->mch_window + I82975X_DRB + row); -+ pvt->drb[row][1] = readb(pvt->mch_window + I82975X_DRB + row + 0x80); -+ -+ /* On symetric mode, both channels have the same boundaries */ -+ if (pvt->drb[row][0] != pvt->drb[row][1]) -+ pvt->is_symetric = false; - -- for (dualch = 1, row = 0; dualch && (row < 4); row++) { -- drb[row][0] = readb(mch_window + I82975X_DRB + row); -- drb[row][1] = readb(mch_window + I82975X_DRB + row + 0x80); -- dualch = dualch && (drb[row][0] == drb[row][1]); -+ if (pvt->drb[row][0]) -+ has_chan_a = true; -+ if (pvt->drb[row][1]) -+ has_chan_b = true; - } -- return dualch; --} - --static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank) --{ -- /* -- * ECC is possible on i92975x ONLY with DEV_X8 -- */ -- return DEV_X8; -+ if (has_chan_a) -+ pvt->num_channels++; -+ -+ if (has_chan_b) -+ pvt->num_channels++; - } - - static void i82975x_init_csrows(struct mem_ctl_info *mci, -- struct pci_dev *pdev, void __iomem *mch_window) -+ struct i82975x_pvt *pvt, -+ struct pci_dev *pdev) - { -- struct csrow_info *csrow; -- unsigned long last_cumul_size; -- u8 value; -- u32 cumul_size, nr_pages; -- int index, chan; -- struct dimm_info *dimm; -- enum dev_type dtype; -- -- last_cumul_size = 0; -+ struct dimm_info *dimm; -+ struct mem_range *range; -+ u8 boundary; -+ u32 initial_page = 0, last_page; -+ int row, chan; - - /* -- * 82875 comment: -- * The dram row boundary (DRB) reg values are boundary address -- * for each DRAM row with a granularity of 32 or 64MB (single/dual -- * channel operation). DRB regs are cumulative; therefore DRB7 will -- * contain the total memory contained in all rows. -- * -+ * This chipset provides 3 address modes: -+ * Single channel - either Channel A or channel B is filled -+ * Dual channel, interleaved: Memory is organized in pairs, -+ * where channel A gets the lower address for each pair -+ * Dual channel, asymmetric: Channel A memory goes first. -+ * In order to cover all modes, we need to start describing -+ * memories considering the dual channel, asymmetric one. - */ - -- for (index = 0; index < mci->nr_csrows; index++) { -- csrow = mci->csrows[index]; -- -- value = readb(mch_window + I82975X_DRB + index + -- ((index >= 4) ? 0x80 : 0)); -- cumul_size = value; -- cumul_size <<= (I82975X_DRB_SHIFT - PAGE_SHIFT); -- /* -- * Adjust cumul_size w.r.t number of channels -- * -- */ -- if (csrow->nr_channels > 1) -- cumul_size <<= 1; -- edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size); -- -- nr_pages = cumul_size - last_cumul_size; -- if (!nr_pages) -- continue; -- -+ for (chan = 0; chan < pvt->num_channels; chan++) { - /* -- * Initialise dram labels -- * index values: -- * [0-7] for single-channel; i.e. csrow->nr_channels = 1 -- * [0-3] for dual-channel; i.e. csrow->nr_channels = 2 -+ * On symetric mode, both channels start from address 0 - */ -- dtype = i82975x_dram_type(mch_window, index); -- for (chan = 0; chan < csrow->nr_channels; chan++) { -- dimm = mci->csrows[index]->channels[chan]->dimm; -- -- dimm->nr_pages = nr_pages / csrow->nr_channels; -- -- snprintf(csrow->channels[chan]->dimm->label, EDAC_MC_LABEL_LEN, "DIMM %c%d", -- (chan == 0) ? 'A' : 'B', -- index); -- dimm->grain = 1 << 7; /* 128Byte cache-line resolution */ -- dimm->dtype = i82975x_dram_type(mch_window, index); -+ if (pvt->is_symetric) -+ initial_page = 0; -+ -+ for (row = 0; row < DIMMS_PER_CHANNEL; row++) { -+ boundary = pvt->drb[row][chan]; -+ dimm = mci->csrows[row]->channels[chan]->dimm; -+ -+ last_page = boundary << (I82975X_DRB_SHIFT - PAGE_SHIFT); -+ dimm->nr_pages = last_page - initial_page; -+ if (!dimm->nr_pages) -+ continue; -+ -+ range = &pvt->page[row][chan]; -+ range->start = initial_page; -+ range->end = range->start + dimm->nr_pages - 1; -+ -+ /* -+ * Grain is one cache-line: -+ * On dual symetric mode, it is 128 Bytes; -+ * On single mode or asymetric, it is 64 bytes. -+ */ -+ if (pvt->is_symetric) { -+ dimm->grain = 1 << 7; -+ -+ /* -+ * In dual interleaved mode, the addresses -+ * need to be multiplied by 2, as both -+ * channels are interlaced, and the boundary -+ * limit there actually match each DIMM size -+ */ -+ range->start <<= 1; -+ range->end <<= 1; -+ } else { -+ dimm->grain = 1 << 6; -+ } -+ -+ snprintf(dimm->label, -+ EDAC_MC_LABEL_LEN, "DIMM %c%d", -+ (chan == 0) ? 'A' : 'B', row); - dimm->mtype = MEM_DDR2; /* I82975x supports only DDR2 */ - dimm->edac_mode = EDAC_SECDED; /* only supported */ -- } - -- csrow->first_page = last_cumul_size; -- csrow->last_page = cumul_size - 1; -- last_cumul_size = cumul_size; -+ /* -+ * This chipset supports both x8 and x16 memories, -+ * but datasheet doesn't describe how to distinguish -+ * between them. -+ * -+ * Also, the "Rank" comment at initial_page 17 says that -+ * ECC is only available with x8 memories. As this -+ * driver doesn't even initialize without ECC, better -+ * to assume that everything is x8. This is not -+ * actually true, on a mixed ECC/non-ECC scenario. -+ */ -+ dimm->dtype = DEV_X8; -+ -+ edac_dbg(1, -+ "%s: from page 0x%08x to 0x%08x (size: 0x%08x pages)\n", -+ dimm->label, -+ range->start, range->end, -+ dimm->nr_pages); -+ initial_page = last_page; -+ } - } - } - --static void i82975x_print_dram_config(void __iomem *mch_window, u32 mchbar, u32 *drc) -+static void i82975x_print_dram_config(struct i82975x_pvt *pvt, -+ u32 mchbar, u32 *drc) - { - #ifdef CONFIG_EDAC_DEBUG - /* -@@ -444,63 +534,57 @@ static void i82975x_print_dram_config(void __iomem *mch_window, u32 mchbar, u32 - * Asus P5W Bios reports 15-5-4-4 - * What's your religion? - */ -- static const int caslats[4] = { 5, 4, 3, 6 }; -- u32 dtreg[2]; -- u8 c0drb[4]; -- u8 c1drb[4]; -+ static const int caslats[4] = { 5, 4, 3, 6 }; -+ u32 dtreg[2]; -+ int row; - -+ /* Show memory config if debug level is 1 or upper */ - if (!edac_debug_level) - return; - - i82975x_printk(KERN_INFO, "MCHBAR real = %0x, remapped = %p\n", -- mchbar, mch_window); -- -- c0drb[0] = readb(mch_window + I82975X_DRB_CH0R0); -- c0drb[1] = readb(mch_window + I82975X_DRB_CH0R1); -- c0drb[2] = readb(mch_window + I82975X_DRB_CH0R2); -- c0drb[3] = readb(mch_window + I82975X_DRB_CH0R3); -- c1drb[0] = readb(mch_window + I82975X_DRB_CH1R0); -- c1drb[1] = readb(mch_window + I82975X_DRB_CH1R1); -- c1drb[2] = readb(mch_window + I82975X_DRB_CH1R2); -- c1drb[3] = readb(mch_window + I82975X_DRB_CH1R3); -- i82975x_printk(KERN_INFO, "DRBCH0R0 = 0x%02x\n", c0drb[0]); -- i82975x_printk(KERN_INFO, "DRBCH0R1 = 0x%02x\n", c0drb[1]); -- i82975x_printk(KERN_INFO, "DRBCH0R2 = 0x%02x\n", c0drb[2]); -- i82975x_printk(KERN_INFO, "DRBCH0R3 = 0x%02x\n", c0drb[3]); -- i82975x_printk(KERN_INFO, "DRBCH1R0 = 0x%02x\n", c1drb[0]); -- i82975x_printk(KERN_INFO, "DRBCH1R1 = 0x%02x\n", c1drb[1]); -- i82975x_printk(KERN_INFO, "DRBCH1R2 = 0x%02x\n", c1drb[2]); -- i82975x_printk(KERN_INFO, "DRBCH1R3 = 0x%02x\n", c1drb[3]); -- -- i82975x_printk(KERN_INFO, "DRC_CH0 = %0x, %s\n", drc[0], -+ mchbar, pvt->mch_window); -+ -+ for (row = 0; row < DIMMS_PER_CHANNEL; row++) { -+ if (row) -+ /* Only show if at least one bank is filled */ -+ if ((pvt->drb[row][0] == pvt->drb[row-1][0]) && -+ (pvt->drb[row][1] == pvt->drb[row-1][1])) -+ continue; -+ -+ i82975x_printk(KERN_INFO, -+ "DRAM%i Rank Boundary Address: Channel A: 0x%08x; Channel B: 0x%08x\n", -+ row, -+ pvt->drb[row][0], -+ pvt->drb[row][1]); -+ } -+ -+ i82975x_printk(KERN_INFO, "DRAM Controller mode Channel A: = 0x%08x (%s); Channel B: 0x%08x (%s)\n", -+ drc[0], - ((drc[0] >> 21) & 3) == 1 ? -- "ECC enabled" : "ECC disabled"); -- i82975x_printk(KERN_INFO, "DRC_CH1 = %0x, %s\n", drc[1], -+ "ECC enabled" : "ECC disabled", -+ drc[1], - ((drc[1] >> 21) & 3) == 1 ? - "ECC enabled" : "ECC disabled"); - -- i82975x_printk(KERN_INFO, "C0 BNKARC = %0x\n", -- readw(mch_window + I82975X_C0BNKARC)); -- i82975x_printk(KERN_INFO, "C1 BNKARC = %0x\n", -- readw(mch_window + I82975X_C1BNKARC)); -- -- dtreg[0] = readl(mch_window + 0x114); -- dtreg[1] = readl(mch_window + 0x194); -- i82975x_printk(KERN_INFO, -- "DRAM Timings : Ch0 Ch1\n" -- " RAS Active Min = %d %d\n" -- " CAS latency = %d %d\n" -- " RAS to CAS = %d %d\n" -- " RAS precharge = %d %d\n", -- (dtreg[0] >> 19 ) & 0x0f, -- (dtreg[1] >> 19) & 0x0f, -- caslats[(dtreg[0] >> 8) & 0x03], -- caslats[(dtreg[1] >> 8) & 0x03], -- ((dtreg[0] >> 4) & 0x07) + 2, -- ((dtreg[1] >> 4) & 0x07) + 2, -+ i82975x_printk(KERN_INFO, "Bank Architecture Channel A: 0x%08x, Channel B: 0x%08x\n", -+ readw(pvt->mch_window + I82975X_C0BNKARC), -+ readw(pvt->mch_window + I82975X_C1BNKARC)); -+ -+ dtreg[0] = readl(pvt->mch_window + I82975X_C0DRT1); -+ dtreg[1] = readl(pvt->mch_window + I82975X_C1DRT1); -+ i82975x_printk(KERN_INFO, "DRAM Timings : ChA ChB\n"); -+ i82975x_printk(KERN_INFO, " RAS Active Min = %2d %2d\n", -+ (dtreg[0] >> 19 ) & 0x0f,(dtreg[1] >> 19) & 0x0f); -+ i82975x_printk(KERN_INFO, " CAS latency = %2d %2d\n", -+ caslats[(dtreg[0] >> 8) & 0x03], -+ caslats[(dtreg[1] >> 8) & 0x03]); -+ i82975x_printk(KERN_INFO, " RAS to CAS = %2d %2d\n", -+ ((dtreg[0] >> 4) & 0x07) + 2, -+ ((dtreg[1] >> 4) & 0x07) + 2); -+ i82975x_printk(KERN_INFO, " RAS precharge = %2d %2d\n", - (dtreg[0] & 0x07) + 2, -- (dtreg[1] & 0x07) + 2 -- ); -+ (dtreg[1] & 0x07) + 2); - #endif - } - -@@ -509,12 +593,10 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) - int rc = -ENODEV; - struct mem_ctl_info *mci; - struct edac_mc_layer layers[2]; -- struct i82975x_pvt *pvt; -- void __iomem *mch_window; -+ struct i82975x_pvt tmp_pvt, *pvt; - u32 mchbar; - u32 drc[2]; - struct i82975x_error_info discard; -- int chans; - - edac_dbg(0, "\n"); - -@@ -524,26 +606,35 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) - goto fail0; - } - mchbar &= 0xffffc000; /* bits 31:14 used for 16K window */ -- mch_window = ioremap_nocache(mchbar, 0x1000); -+ tmp_pvt.mch_window = ioremap_nocache(mchbar, 0x1000); -+ if (!tmp_pvt.mch_window) { -+ i82975x_printk(KERN_ERR, "Couldn't map MCHBAR registers.\n"); -+ rc = -ENOMEM; -+ goto fail0; -+ } - -- drc[0] = readl(mch_window + I82975X_DRC_CH0M0); -- drc[1] = readl(mch_window + I82975X_DRC_CH1M0); -+ drc[0] = readl(tmp_pvt.mch_window + I82975X_DRC_CH0M0); -+ drc[1] = readl(tmp_pvt.mch_window + I82975X_DRC_CH1M0); -+ -+ detect_memory_style(&tmp_pvt); -+ if (!tmp_pvt.num_channels) { -+ edac_dbg(3, "No memories installed? This shouldn't be running!\n"); -+ goto fail0; -+ } - -- i82975x_print_dram_config(mch_window, mchbar, drc); -+ i82975x_print_dram_config(&tmp_pvt, mchbar, drc); - - if (!(((drc[0] >> 21) & 3) == 1 || ((drc[1] >> 21) & 3) == 1)) { - i82975x_printk(KERN_INFO, "ECC disabled on both channels.\n"); - goto fail1; - } - -- chans = dual_channel_active(mch_window) + 1; -- - /* assuming only one controller, index thus is 0 */ - layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; -- layers[0].size = I82975X_NR_DIMMS; -+ layers[0].size = DIMMS_PER_CHANNEL; - layers[0].is_virt_csrow = true; - layers[1].type = EDAC_MC_LAYER_CHANNEL; -- layers[1].size = I82975X_NR_CSROWS(chans); -+ layers[1].size = tmp_pvt.num_channels; - layers[1].is_virt_csrow = false; - mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt)); - if (!mci) { -@@ -562,10 +653,12 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) - mci->dev_name = pci_name(pdev); - mci->edac_check = i82975x_check; - mci->ctl_page_to_phys = NULL; -+ - edac_dbg(3, "init pvt\n"); - pvt = (struct i82975x_pvt *) mci->pvt_info; -- pvt->mch_window = mch_window; -- i82975x_init_csrows(mci, pdev, mch_window); -+ *pvt = tmp_pvt; -+ -+ i82975x_init_csrows(mci, pvt, pdev); - mci->scrub_mode = SCRUB_HW_SRC; - i82975x_get_error_info(mci, &discard); /* clear counters */ - -@@ -583,7 +676,7 @@ fail2: - edac_mc_free(mci); - - fail1: -- iounmap(mch_window); -+ iounmap(tmp_pvt.mch_window); - fail0: - return rc; - } diff --git a/kernel.spec b/kernel.spec index e2b45c236..a881fc3fc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -66,7 +66,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 10 +%define stable_update 11 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -668,8 +668,6 @@ Patch14010: lis3-improve-handling-of-null-rate.patch Patch19000: ips-noirq.patch -Patch19001: i82975x-edac-fix.patch - #rhbz 769766 Patch21072: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch @@ -700,7 +698,6 @@ Patch30000: weird-root-dentry-name-debug.patch Patch30010: debug-808990.patch #rhbz 871078 -Patch22111: USB-EHCI-urb-hcpriv-should-not-be-NULL.patch Patch22112: USB-report-submission-of-active-URBs.patch #rhbz 869341 @@ -1323,8 +1320,6 @@ ApplyPatch lis3-improve-handling-of-null-rate.patch ApplyPatch ips-noirq.patch -ApplyPatch i82975x-edac-fix.patch - #ApplyPatch pci-crs-blacklist.patch #rhbz 754518 @@ -1349,7 +1344,6 @@ ApplyPatch 0011-ext4-fix-ext4_flush_completed_IO-wait-semantics.patch ApplyPatch 0012-ext4-serialize-fallocate-with-ext4_convert_unwritten.patch #rhbz 871078 -ApplyPatch USB-EHCI-urb-hcpriv-should-not-be-NULL.patch ApplyPatch USB-report-submission-of-active-URBs.patch #rhbz 869341 @@ -2083,6 +2077,7 @@ fi %changelog * Mon Dec 17 2012 Josh Boyer +- Linux v3.6.11 - Fix oops in sony-laptop setup (rhbz 873107) * Tue Dec 11 2012 Josh Boyer diff --git a/sources b/sources index eebf282fc..fdb1a3193 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 1a1760420eac802c541a20ab51a093d1 linux-3.6.tar.xz -406a52f90a2ddc78a3ecdf4fe46e7cf7 patch-3.6.10.xz +bd4bba74093405887d521309a74c19e9 patch-3.6.11.xz From cae88327ab98b18e7b2a5dd2f81c487cced3a444 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 17 Dec 2012 16:15:26 -0500 Subject: [PATCH 479/487] Add verrel for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index a881fc3fc..54d6222d7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2076,7 +2076,7 @@ fi # and build. %changelog -* Mon Dec 17 2012 Josh Boyer +* Mon Dec 17 2012 Josh Boyer - 3.6.11-1 - Linux v3.6.11 - Fix oops in sony-laptop setup (rhbz 873107) From d44d05a51b1f00db5747d8f4ebf22ca70a808e33 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 2 Jan 2013 10:30:41 -0500 Subject: [PATCH 480/487] Fix autofs issue in 3.6 (rhbz 874372) --- ...-do-blind-d_drop-in-nfs_prime_dcache.patch | 27 +++++++++++++++++++ kernel.spec | 11 +++++++- 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 don-t-do-blind-d_drop-in-nfs_prime_dcache.patch diff --git a/don-t-do-blind-d_drop-in-nfs_prime_dcache.patch b/don-t-do-blind-d_drop-in-nfs_prime_dcache.patch new file mode 100644 index 000000000..d4e837ab1 --- /dev/null +++ b/don-t-do-blind-d_drop-in-nfs_prime_dcache.patch @@ -0,0 +1,27 @@ +From 696199f8ccf7fc6d17ef89c296ad3b6c78c52d9c Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Thu, 29 Nov 2012 22:00:51 -0500 +Subject: [PATCH] don't do blind d_drop() in nfs_prime_dcache() + +Signed-off-by: Al Viro +--- + fs/nfs/dir.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c +index ce8cb92..99489cf 100644 +--- a/fs/nfs/dir.c ++++ b/fs/nfs/dir.c +@@ -450,7 +450,8 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) + nfs_refresh_inode(dentry->d_inode, entry->fattr); + goto out; + } else { +- d_drop(dentry); ++ if (d_invalidate(dentry) != 0) ++ goto out; + dput(dentry); + } + } +-- +1.8.0.1 + diff --git a/kernel.spec b/kernel.spec index 54d6222d7..f7ba3cdb8 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -729,6 +729,9 @@ Patch21234: mac80211-fix-ibss-scanning.patch #rhbz 873107 Patch21237: 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch +#rhbz 874372 +Patch21238: don-t-do-blind-d_drop-in-nfs_prime_dcache.patch + # END OF PATCH DEFINITIONS %endif @@ -1375,6 +1378,9 @@ ApplyPatch mac80211-fix-ibss-scanning.patch #rhbz 873107 ApplyPatch 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch +#rhbz 874372 +ApplyPatch don-t-do-blind-d_drop-in-nfs_prime_dcache.patch + # END OF PATCH APPLICATIONS @@ -2076,6 +2082,9 @@ fi # and build. %changelog +* Wed Jan 02 2013 Josh Boyer +- Fix autofs issue in 3.6 (rhbz 874372) + * Mon Dec 17 2012 Josh Boyer - 3.6.11-1 - Linux v3.6.11 - Fix oops in sony-laptop setup (rhbz 873107) From c4ae440dda62c4eb5826c81b0226938f184e93d5 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 4 Jan 2013 08:08:18 -0500 Subject: [PATCH 481/487] Fix oops on aoe module removal (rhbz 853064) --- aoe-remove-extra-bdi_init.patch | 78 +++++++++++++++++++++++++++++++++ kernel.spec | 11 ++++- 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 aoe-remove-extra-bdi_init.patch diff --git a/aoe-remove-extra-bdi_init.patch b/aoe-remove-extra-bdi_init.patch new file mode 100644 index 000000000..7275d5343 --- /dev/null +++ b/aoe-remove-extra-bdi_init.patch @@ -0,0 +1,78 @@ +Lines: 75 + +On Thu, Jan 03, 2013 at 12:15:35PM -0600, Ed Cashin wrote: +... +> >>>>> On Jan 3, 2013, at 8:25 AM, Josh Boyer wrote: +... +> >>>>>> [699170.611997] aoe: AoE v47 initialised. +... +> >>>>>> [699231.308319] WARNING: at lib/list_debug.c:62 __list_del_entry+0x82/0xd0() +> >>>>>> [699231.312031] Hardware name: S5000VSA +> >>>>>> [699231.315658] list_del corruption. next->prev should be ffff880009fa37e8, but was ffffffff81c79c00 +> >>>>>> [699231.319352] Modules linked in: aoe(-) ip6table_filter ip6_tables ebtable_nat ebtables lockd sunrpc bridge 8021q garp stp llc vfat fat binfmt_misc iTCO_wdt iTCO_vendor_support vhost_net lpc_ich radeon tun macvtap mfd_core serio_raw coretemp i2c_algo_bit ttm i5000_edac macvlan drm_kms_helper e1000e edac_core microcode i5k_amb shpchp i2c_i801 drm kvm_intel i2c_core kvm ioatdma dca raid1 +> >>>>>> [699231.336259] Pid: 8584, comm: modprobe Not tainted 3.6.11-1.fc17.x86_64 #1 +> >>>>>> [699231.340561] Call Trace: +> >>>>>> [699231.344865] [] warn_slowpath_common+0x7f/0xc0 +> >>>>>> [699231.349212] [] warn_slowpath_fmt+0x46/0x50 +> >>>>>> [699231.353595] [] __list_del_entry+0x82/0xd0 +> >>>>>> [699231.357954] [] list_del+0x11/0x40 +> >>>>>> [699231.362319] [] percpu_counter_destroy+0x28/0x50 +> >>>>>> [699231.366712] [] bdi_destroy+0x43/0x140 +> >>>>>> [699231.371127] [] blk_release_queue+0x8c/0xc0 +> >>>>>> [699231.375454] [] kobject_cleanup+0x82/0x1b0 +> >>>>>> [699231.379675] [] kobject_put+0x2b/0x60 +> >>>>>> [699231.383851] [] blk_put_queue+0x15/0x20 +> >>>>>> [699231.387899] [] blk_cleanup_queue+0xc9/0xe0 +> >>>>>> [699231.391794] [] aoedev_freedev+0x135/0x150 [aoe] +> >>>>>> [699231.395668] [] aoedev_exit+0x65/0x80 [aoe] +> >>>>>> [699231.399493] [] aoe_exit+0x2e/0x40 [aoe] +> >>>>>> [699231.403273] [] sys_delete_module+0x16e/0x2d0 +> >>>>>> [699231.407119] [] ? __schedule+0x3c6/0x7a0 +> >>>>>> [699231.411050] [] ? sys_write+0x4a/0x90 +> >>>>>> [699231.415033] [] system_call_fastpath+0x16/0x1b +> >>>>>> [699231.419117] ---[ end trace 9e1558af1964b569 ]--- +> >>>>>> [699231.423248] ------------[ cut here ]------------ + +The blk_alloc_queue has already done a bdi_init, so do not bdi_init again in +aoeblk_gdalloc. + +The patch below applies to v3.5.6, with its v47 aoe driver. On my system it +eliminates the list_del corruption messages. + +It updates VERSION for convenience during testing. + +diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h +index db195ab..2ccb9e2 100644 +--- a/drivers/block/aoe/aoe.h ++++ b/drivers/block/aoe/aoe.h +@@ -1,5 +1,5 @@ + /* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ +-#define VERSION "47" ++#define VERSION "47nobdi1" + #define AOE_MAJOR 152 + #define DEVICE_NAME "aoe" + +diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c +index 321de7b..7eca463 100644 +--- a/drivers/block/aoe/aoeblk.c ++++ b/drivers/block/aoe/aoeblk.c +@@ -276,8 +276,6 @@ aoeblk_gdalloc(void *vp) + goto err_mempool; + blk_queue_make_request(d->blkq, aoeblk_make_request); + d->blkq->backing_dev_info.name = "aoe"; +- if (bdi_init(&d->blkq->backing_dev_info)) +- goto err_blkq; + spin_lock_irqsave(&d->lock, flags); + gd->major = AOE_MAJOR; + gd->first_minor = d->sysminor * AOE_PARTITIONS; +@@ -298,9 +296,6 @@ aoeblk_gdalloc(void *vp) + aoedisk_add_sysfs(d); + return; + +-err_blkq: +- blk_cleanup_queue(d->blkq); +- d->blkq = NULL; + err_mempool: + mempool_destroy(d->bufpool); + err_disk: + diff --git a/kernel.spec b/kernel.spec index f7ba3cdb8..91cba201e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -732,6 +732,9 @@ Patch21237: 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch #rhbz 874372 Patch21238: don-t-do-blind-d_drop-in-nfs_prime_dcache.patch +#rhbz 853064 +Patch21239: aoe-remove-extra-bdi_init.patch + # END OF PATCH DEFINITIONS %endif @@ -1381,6 +1384,9 @@ ApplyPatch 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch #rhbz 874372 ApplyPatch don-t-do-blind-d_drop-in-nfs_prime_dcache.patch +#rhbz 853064 +ApplyPatch aoe-remove-extra-bdi_init.patch + # END OF PATCH APPLICATIONS @@ -2082,6 +2088,9 @@ fi # and build. %changelog +* Fri Jan 04 2013 Josh Boyer +- Fix oops on aoe module removal (rhbz 853064) + * Wed Jan 02 2013 Josh Boyer - Fix autofs issue in 3.6 (rhbz 874372) From c12415061c524cf2078d5060c6685bc9f50ae1c6 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 8 Jan 2013 08:28:32 -0500 Subject: [PATCH 482/487] Add patch to fix shutdown on some machines (rhbz 890547) --- ...e-Lid-and-Sleep-button-for-S5-wakeup.patch | 46 +++++++++++++++++++ kernel.spec | 11 ++++- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch diff --git a/ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch b/ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch new file mode 100644 index 000000000..f6e997c41 --- /dev/null +++ b/ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch @@ -0,0 +1,46 @@ +From b7e383046c2c7c13ad928cd7407eafff758ddd4b Mon Sep 17 00:00:00 2001 +From: Zhang Rui +Date: Tue, 4 Dec 2012 23:23:16 +0100 +Subject: [PATCH] ACPI : do not use Lid and Sleep button for S5 wakeup + +When system enters power off, the _PSW of Lid device is enabled. +But this may cause the system to reboot instead of power off. + +A proper way to fix this is to always disable lid wakeup capability for S5. + +References: https://bugzilla.kernel.org/show_bug.cgi?id=35262 +Signed-off-by: Zhang Rui +Signed-off-by: Rafael J. Wysocki +--- + drivers/acpi/scan.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c +index d0b38ab..bd523bf 100644 +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -917,8 +917,8 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, + static void acpi_bus_set_run_wake_flags(struct acpi_device *device) + { + struct acpi_device_id button_device_ids[] = { +- {"PNP0C0D", 0}, + {"PNP0C0C", 0}, ++ {"PNP0C0D", 0}, + {"PNP0C0E", 0}, + {"", 0}, + }; +@@ -930,6 +930,11 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) + /* Power button, Lid switch always enable wakeup */ + if (!acpi_match_device_ids(device, button_device_ids)) { + device->wakeup.flags.run_wake = 1; ++ if (!acpi_match_device_ids(device, &button_device_ids[1])) { ++ /* Do not use Lid/sleep button for S5 wakeup */ ++ if (device->wakeup.sleep_state == ACPI_STATE_S5) ++ device->wakeup.sleep_state = ACPI_STATE_S4; ++ } + device_set_wakeup_capable(&device->dev, true); + return; + } +-- +1.8.0.1 + diff --git a/kernel.spec b/kernel.spec index 91cba201e..372048e41 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -735,6 +735,9 @@ Patch21238: don-t-do-blind-d_drop-in-nfs_prime_dcache.patch #rhbz 853064 Patch21239: aoe-remove-extra-bdi_init.patch +#rhbz 890547 +Patch21240: ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch + # END OF PATCH DEFINITIONS %endif @@ -1387,6 +1390,9 @@ ApplyPatch don-t-do-blind-d_drop-in-nfs_prime_dcache.patch #rhbz 853064 ApplyPatch aoe-remove-extra-bdi_init.patch +#rhbz 890547 +ApplyPatch ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch + # END OF PATCH APPLICATIONS @@ -2088,6 +2094,9 @@ fi # and build. %changelog +* Tue Jan 08 2013 Josh Boyer +- Add patch to fix shutdown on some machines (rhbz 890547) + * Fri Jan 04 2013 Josh Boyer - Fix oops on aoe module removal (rhbz 853064) From 6195c49a1d3fcdf78a66b109367ad3ba1d429898 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 8 Jan 2013 15:40:38 -0500 Subject: [PATCH 483/487] Add verrel for build --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 372048e41..64a7b19b4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2094,7 +2094,7 @@ fi # and build. %changelog -* Tue Jan 08 2013 Josh Boyer +* Tue Jan 08 2013 Josh Boyer - 3.6.11-4 - Add patch to fix shutdown on some machines (rhbz 890547) * Fri Jan 04 2013 Josh Boyer From e158c0561c3f5337c4bf94c80985761921737f30 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 16 Jan 2013 08:31:28 -0500 Subject: [PATCH 484/487] Add patch from Stanislaw Gruszka to fix iwlegacy IBSS cleanup (rhbz 886946) --- iwlegacy-fix-IBSS-cleanup.patch | 104 ++++++++++++++++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 iwlegacy-fix-IBSS-cleanup.patch diff --git a/iwlegacy-fix-IBSS-cleanup.patch b/iwlegacy-fix-IBSS-cleanup.patch new file mode 100644 index 000000000..5533aed75 --- /dev/null +++ b/iwlegacy-fix-IBSS-cleanup.patch @@ -0,0 +1,104 @@ +From 658f1bd2dd632209df00ec66349e15941ffdd83b Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Wed, 16 Jan 2013 10:28:09 +0000 +Subject: [PATCH 3.8] iwlegacy: fix IBSS cleanup + +We do not correctly change interface type when switching from +IBSS mode to STA mode, that results in microcode errors. + +Resolves: +https://bugzilla.redhat.com/show_bug.cgi?id=886946 + +Reported-by: Jaroslav Skarvada +Cc: stable@vger.kernel.org +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/iwlegacy/common.c | 35 ++++++++++++++-------------------- + 1 file changed, 14 insertions(+), 21 deletions(-) + +diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c +index 7e16d10..90b8970 100644 +--- a/drivers/net/wireless/iwlegacy/common.c ++++ b/drivers/net/wireless/iwlegacy/common.c +@@ -3958,17 +3958,21 @@ il_connection_init_rx_config(struct il_priv *il) + + memset(&il->staging, 0, sizeof(il->staging)); + +- if (!il->vif) { ++ switch (il->iw_mode) { ++ case NL80211_IFTYPE_UNSPECIFIED: + il->staging.dev_type = RXON_DEV_TYPE_ESS; +- } else if (il->vif->type == NL80211_IFTYPE_STATION) { ++ break; ++ case NL80211_IFTYPE_STATION: + il->staging.dev_type = RXON_DEV_TYPE_ESS; + il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; +- } else if (il->vif->type == NL80211_IFTYPE_ADHOC) { ++ break; ++ case NL80211_IFTYPE_ADHOC: + il->staging.dev_type = RXON_DEV_TYPE_IBSS; + il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; + il->staging.filter_flags = + RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; +- } else { ++ break; ++ default: + IL_ERR("Unsupported interface type %d\n", il->vif->type); + return; + } +@@ -4550,8 +4554,7 @@ out: + EXPORT_SYMBOL(il_mac_add_interface); + + static void +-il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, +- bool mode_change) ++il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif) + { + lockdep_assert_held(&il->mutex); + +@@ -4560,9 +4563,7 @@ il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, + il_force_scan_end(il); + } + +- if (!mode_change) +- il_set_mode(il); +- ++ il_set_mode(il); + } + + void +@@ -4575,8 +4576,8 @@ il_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) + + WARN_ON(il->vif != vif); + il->vif = NULL; +- +- il_teardown_interface(il, vif, false); ++ il->iw_mode = NL80211_IFTYPE_UNSPECIFIED; ++ il_teardown_interface(il, vif); + memset(il->bssid, 0, ETH_ALEN); + + D_MAC80211("leave\n"); +@@ -4685,18 +4686,10 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + } + + /* success */ +- il_teardown_interface(il, vif, true); + vif->type = newtype; + vif->p2p = false; +- err = il_set_mode(il); +- WARN_ON(err); +- /* +- * We've switched internally, but submitting to the +- * device may have failed for some reason. Mask this +- * error, because otherwise mac80211 will not switch +- * (and set the interface type back) and we'll be +- * out of sync with it. +- */ ++ il->iw_mode = newtype; ++ il_teardown_interface(il, vif); + err = 0; + + out: +-- +1.8.0.2 + diff --git a/kernel.spec b/kernel.spec index 64a7b19b4..7a76430ad 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -738,6 +738,9 @@ Patch21239: aoe-remove-extra-bdi_init.patch #rhbz 890547 Patch21240: ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch +#rhbz 886946 +Patch21241: iwlegacy-fix-IBSS-cleanup.patch + # END OF PATCH DEFINITIONS %endif @@ -1393,6 +1396,9 @@ ApplyPatch aoe-remove-extra-bdi_init.patch #rhbz 890547 ApplyPatch ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch +#rhbz 886946 +ApplyPatch iwlegacy-fix-IBSS-cleanup.patch + # END OF PATCH APPLICATIONS @@ -2094,6 +2100,9 @@ fi # and build. %changelog +* Wed Jan 16 2013 Josh Boyer +- Add patch from Stanislaw Gruszka to fix iwlegacy IBSS cleanup (rhbz 886946) + * Tue Jan 08 2013 Josh Boyer - 3.6.11-4 - Add patch to fix shutdown on some machines (rhbz 890547) From 5325d16e0aafd28478e52d254ce310ef7bcf855d Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Wed, 16 Jan 2013 09:52:46 -0600 Subject: [PATCH 485/487] Fix for CVE-2013-0190 xen corruption with 32bit pvops (rhbz 896051 896038) --- ext4-set-bg_itable_unused-when-resizing.patch | 26 ++++++++ kernel.spec | 17 ++++- ...-corruption-in-xen_failsafe_callback.patch | 62 +++++++++++++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 ext4-set-bg_itable_unused-when-resizing.patch create mode 100644 xen-fix-stack-corruption-in-xen_failsafe_callback.patch diff --git a/ext4-set-bg_itable_unused-when-resizing.patch b/ext4-set-bg_itable_unused-when-resizing.patch new file mode 100644 index 000000000..bd7bc4424 --- /dev/null +++ b/ext4-set-bg_itable_unused-when-resizing.patch @@ -0,0 +1,26 @@ +commit 93f9052643409c13b3b5f76833865087351f55b8 +Author: Theodore Ts'o +Date: Wed Sep 12 14:32:42 2012 -0400 + + ext4: set bg_itable_unused when resizing + + Set bg_itable_unused for file systems that have uninit_bg enabled. + This will speed up the first e2fsck run after the file system is + resized. + + Signed-off-by: "Theodore Ts'o" + +diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c +index 7adc088..a5be589 100644 +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -1268,6 +1268,9 @@ static int ext4_setup_new_descs(handle_t *handle, struct super_block *sb, + ext4_free_group_clusters_set(sb, gdp, + EXT4_B2C(sbi, group_data->free_blocks_count)); + ext4_free_inodes_set(sb, gdp, EXT4_INODES_PER_GROUP(sb)); ++ if (ext4_has_group_desc_csum(sb)) ++ ext4_itable_unused_set(sb, gdp, ++ EXT4_INODES_PER_GROUP(sb)); + gdp->bg_flags = cpu_to_le16(*bg_flags); + ext4_group_desc_csum_set(sb, group, gdp); + diff --git a/kernel.spec b/kernel.spec index 7a76430ad..1e30ecffc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 5 +%global baserelease 6 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -741,6 +741,12 @@ Patch21240: ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch #rhbz 886946 Patch21241: iwlegacy-fix-IBSS-cleanup.patch +#rhbz 852833 +Patch21245: ext4-set-bg_itable_unused-when-resizing.patch + +#rhbz 896051 896038 CVE-2013-0190 +Patch21250: xen-fix-stack-corruption-in-xen_failsafe_callback.patch + # END OF PATCH DEFINITIONS %endif @@ -1399,6 +1405,11 @@ ApplyPatch ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch #rhbz 886946 ApplyPatch iwlegacy-fix-IBSS-cleanup.patch +#rhbz 852833 +ApplyPatch ext4-set-bg_itable_unused-when-resizing.patch + +#rhbz 896051 896038 CVE-2013-0190 +ApplyPatch xen-fix-stack-corruption-in-xen_failsafe_callback.patch # END OF PATCH APPLICATIONS @@ -2100,6 +2111,10 @@ fi # and build. %changelog +* Wed Jan 16 2013 Justin M. Forbes 3.6.11-6 +- Fix resize2fs issue with ext4 (rhbz 852833) +- Fix for CVE-2013-0190 xen corruption with 32bit pvops (rhbz 896051 896038) + * Wed Jan 16 2013 Josh Boyer - Add patch from Stanislaw Gruszka to fix iwlegacy IBSS cleanup (rhbz 886946) diff --git a/xen-fix-stack-corruption-in-xen_failsafe_callback.patch b/xen-fix-stack-corruption-in-xen_failsafe_callback.patch new file mode 100644 index 000000000..9d83ea0c9 --- /dev/null +++ b/xen-fix-stack-corruption-in-xen_failsafe_callback.patch @@ -0,0 +1,62 @@ +From 38174c8c07ad638cd18285ba402b59076849dc21 Mon Sep 17 00:00:00 2001 +From: Andrew Cooper +Date: Thu, 10 Jan 2013 17:16:30 +0000 +Subject: [PATCH] xen: Fix stack corruption in xen_failsafe_callback for 32bit PVOPS guests. + +There has been an error on the xen_failsafe_callback path for failed +iret, which causes the stack pointer to be wrong when entering the +iret_exc error path. This can result in the kernel crashing. + +In the classic kernel case, the relevant code looked a little like: + + popl %eax # Error code from hypervisor + jz 5f + addl $16,%esp + jmp iret_exc # Hypervisor said iret fault +5: addl $16,%esp + # Hypervisor said segment selector fault + +Here, there are two identical addls on either option of a branch which +appears to have been optimised by hoisting it above the jz, and +converting it to an lea, which leaves the flags register unaffected. + +In the PVOPS case, the code looks like: + + popl_cfi %eax # Error from the hypervisor + lea 16(%esp),%esp # Add $16 before choosing fault path + CFI_ADJUST_CFA_OFFSET -16 + jz 5f + addl $16,%esp # Incorrectly adjust %esp again + jmp iret_exc + +It is possible unprivileged userspace applications to cause this +behaviour, for example by loading an LDT code selector, then changing +the code selector to be not-present. At this point, there is a race +condition where it is possible for the hypervisor to return back to +userspace from an interrupt, fault on its own iret, and inject a +failsafe_callback into the kernel. + +This bug has been present since the introduction of Xen PVOPS support +in commit 5ead97c84 (xen: Core Xen implementation), in 2.6.23. + +Signed-off-by: Frediano Ziglio +Signed-off-by: Andrew Cooper +--- + arch/x86/kernel/entry_32.S | 1 - + 1 files changed, 0 insertions(+), 1 deletions(-) + +diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S +index ff84d54..6ed91d9 100644 +--- a/arch/x86/kernel/entry_32.S ++++ b/arch/x86/kernel/entry_32.S +@@ -1065,7 +1065,6 @@ ENTRY(xen_failsafe_callback) + lea 16(%esp),%esp + CFI_ADJUST_CFA_OFFSET -16 + jz 5f +- addl $16,%esp + jmp iret_exc + 5: pushl_cfi $-1 /* orig_ax = -1 => not a system call */ + SAVE_ALL +-- +1.7.2.5 + From a3dd486e63c9acb1b39b5af9f2a08171934d29d2 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 23 Jan 2013 10:50:51 -0500 Subject: [PATCH 486/487] Remove warning about empty IPI mask. --- kernel.spec | 7 +++++++ silence-empty-ipi-mask-warning.patch | 11 +++++++++++ 2 files changed, 18 insertions(+) create mode 100644 silence-empty-ipi-mask-warning.patch diff --git a/kernel.spec b/kernel.spec index 1e30ecffc..255596610 100644 --- a/kernel.spec +++ b/kernel.spec @@ -627,6 +627,7 @@ Patch470: die-floppy-die.patch Patch510: linux-2.6-silence-noise.patch Patch520: quite-apm.patch Patch530: linux-2.6-silence-fbcon-logo.patch +Patch540: silence-empty-ipi-mask-warning.patch Patch700: linux-2.6-e1000-ich9-montevina.patch @@ -1295,6 +1296,9 @@ ApplyPatch linux-2.6-silence-noise.patch # Make fbcon not show the penguins with 'quiet' ApplyPatch linux-2.6-silence-fbcon-logo.patch +# no-one cares about these warnings. +ApplyPatch silence-empty-ipi-mask-warning.patch + # Changes to upstream defaults. @@ -2111,6 +2115,9 @@ fi # and build. %changelog +* Wed Jan 23 2013 Dave Jones +- Remove warning about empty IPI mask. + * Wed Jan 16 2013 Justin M. Forbes 3.6.11-6 - Fix resize2fs issue with ext4 (rhbz 852833) - Fix for CVE-2013-0190 xen corruption with 32bit pvops (rhbz 896051 896038) diff --git a/silence-empty-ipi-mask-warning.patch b/silence-empty-ipi-mask-warning.patch new file mode 100644 index 000000000..65a637c06 --- /dev/null +++ b/silence-empty-ipi-mask-warning.patch @@ -0,0 +1,11 @@ +--- linux-3.6.noarch/arch/x86/kernel/apic/ipi.c~ 2013-01-23 10:48:14.716069615 -0500 ++++ linux-3.6.noarch/arch/x86/kernel/apic/ipi.c 2013-01-23 10:48:26.217046545 -0500 +@@ -106,7 +106,7 @@ void default_send_IPI_mask_logical(const + unsigned long mask = cpumask_bits(cpumask)[0]; + unsigned long flags; + +- if (WARN_ONCE(!mask, "empty IPI mask")) ++ if (!mask) + return; + + local_irq_save(flags); From e0b1d41f1c3cc49deb1d3873b581a2b8435d025b Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 7 Feb 2013 07:49:44 -0500 Subject: [PATCH 487/487] Fix local privilege escalation in MSR code (rhbz 908693 908706) --- kernel.spec | 11 +++++- x86-msr-Add-capabilities-check.patch | 54 ++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 x86-msr-Add-capabilities-check.patch diff --git a/kernel.spec b/kernel.spec index 255596610..fe5ef7877 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 6 +%global baserelease 7 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -748,6 +748,9 @@ Patch21245: ext4-set-bg_itable_unused-when-resizing.patch #rhbz 896051 896038 CVE-2013-0190 Patch21250: xen-fix-stack-corruption-in-xen_failsafe_callback.patch +#rhbz 908693 908706 +Patch21251: x86-msr-Add-capabilities-check.patch + # END OF PATCH DEFINITIONS %endif @@ -1415,6 +1418,9 @@ ApplyPatch ext4-set-bg_itable_unused-when-resizing.patch #rhbz 896051 896038 CVE-2013-0190 ApplyPatch xen-fix-stack-corruption-in-xen_failsafe_callback.patch +#rhbz 908693 908706 +ApplyPatch x86-msr-Add-capabilities-check.patch + # END OF PATCH APPLICATIONS %endif @@ -2115,6 +2121,9 @@ fi # and build. %changelog +* Thu Feb 07 2013 Josh Boyer +- Fix local privilege escalation in MSR code (rhbz 908693 908706) + * Wed Jan 23 2013 Dave Jones - Remove warning about empty IPI mask. diff --git a/x86-msr-Add-capabilities-check.patch b/x86-msr-Add-capabilities-check.patch new file mode 100644 index 000000000..a3dc0e532 --- /dev/null +++ b/x86-msr-Add-capabilities-check.patch @@ -0,0 +1,54 @@ +From b9f93c7550b62939f250fad55b111637b0f66bc8 Mon Sep 17 00:00:00 2001 +From: Alan Cox +Date: Thu, 15 Nov 2012 13:06:22 +0000 +Subject: [PATCH] x86/msr: Add capabilities check + +commit c903f0456bc69176912dee6dd25c6a66ee1aed00 upstream. + +At the moment the MSR driver only relies upon file system +checks. This means that anything as root with any capability set +can write to MSRs. Historically that wasn't very interesting but +on modern processors the MSRs are such that writing to them +provides several ways to execute arbitary code in kernel space. +Sample code and documentation on doing this is circulating and +MSR attacks are used on Windows 64bit rootkits already. + +In the Linux case you still need to be able to open the device +file so the impact is fairly limited and reduces the security of +some capability and security model based systems down towards +that of a generic "root owns the box" setup. + +Therefore they should require CAP_SYS_RAWIO to prevent an +elevation of capabilities. The impact of this is fairly minimal +on most setups because they don't have heavy use of +capabilities. Those using SELinux, SMACK or AppArmor rules might +want to consider if their rulesets on the MSR driver could be +tighter. + +Signed-off-by: Alan Cox +Cc: Linus Torvalds +Cc: Andrew Morton +Cc: Peter Zijlstra +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/msr.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c +index a7c5661..4929502 100644 +--- a/arch/x86/kernel/msr.c ++++ b/arch/x86/kernel/msr.c +@@ -174,6 +174,9 @@ static int msr_open(struct inode *inode, struct file *file) + unsigned int cpu; + struct cpuinfo_x86 *c; + ++ if (!capable(CAP_SYS_RAWIO)) ++ return -EPERM; ++ + cpu = iminor(file->f_path.dentry->d_inode); + if (cpu >= nr_cpu_ids || !cpu_online(cpu)) + return -ENXIO; /* No such CPU */ +-- +1.8.1 +